<?php

include_once __DIR__.'/../vendor/autoload.php';
function form_display($display)     //при выводе на экран
{
    if (is_array($display)) {
        foreach ($display as $k => $v) {
            $display[$k] = form_display($v);
        }
    } elseif (is_string($display)) {
        $display = htmlspecialchars($display, ENT_QUOTES, "utf-8", false);
    }
    return $display;
}

function form_input($input)     //при вводе данных (устарела еще в PHP 5.4; перестала работать в PHP 8; заменена на заглушку))
{
    return $input;
}

function form_sql($str, $link_identifier = 0)     //при занесении в базу
{
    global $sql_global_link, $sql_db_type;

    if ($link_identifier == 0) {
        $link_identifier = $sql_global_link;
    }

    if (is_array($str)) {
        foreach ($str as $k => $v) {
            $str[$k] = form_sql($v, $link_identifier) ;
        }
        return $str;
    } else {
        if ($sql_db_type == "mysql") {
            return mysqli_escape_string($link_identifier, $str);
        } elseif ($sql_db_type == "postgresql") {
            return pg_escape_string($link_identifier, $str);
        }
    }
}

function cb_keygen_s2k($hash, $password, $salt, $bytes)
{
    $algoCodes = [
        '0' =>	"crc32",
        '9' =>	"crc32b",
        '8' =>	"gost",
        '13' =>	"haval128,3",
        '12' =>	"haval160,3",
        '11' =>	"haval192,3",
        '10' =>	"haval224,3",
        '3' =>	"haval256,3",
        '16' =>	"md4",
        '1' =>	"md5",
        '5' =>	"ripemd160",
        '2' =>	"sha1",
        '17' =>	"sha256",
        '7' =>	"tiger192,3",
        '14' =>	"tiger128,3",
        '15' =>	"tiger160,3",
        MHASH_CRC32	=>	"crc32",
        MHASH_CRC32B	=>	"crc32b",
        MHASH_GOST	=>	"gost",
        MHASH_HAVAL128	=>	"haval128,3",
        MHASH_HAVAL160	=>	"haval160,3",
        MHASH_HAVAL192	=>	"haval192,3",
        MHASH_HAVAL224	=>	"haval224,3",
        MHASH_HAVAL256	=>	"haval256,3",
        MHASH_MD4	=>	"md4",
        MHASH_MD5	=>	"md5",
        MHASH_RIPEMD160	=>	"ripemd160",
        MHASH_SHA1	=>	"sha1",
        MHASH_SHA256	=>	"sha256",
        MHASH_TIGER	=>	"tiger192,3",
        MHASH_TIGER128	=>	"tiger128,3",
        MHASH_TIGER160	=>	"tiger160,3"
    ];


    $hash = $algoCodes[$hash];

    $result = false;

    if (extension_loaded('hash') === true)
    {
        foreach (range(0, ceil($bytes / strlen(hash($hash, null, true))) - 1) as $i)
        {
            $result .= hash($hash, str_repeat("\0", $i) . str_pad(substr($salt, 0, 8), 8, "\0", STR_PAD_RIGHT) . $password, true);
        }

        $result = substr($result, 0, intval($bytes));
    }

    return $result;
}

function form_sql_like($str) // вариант form_sql для операторов LIKE и NOT LIKE
{
    return form_sql(str_replace(array('\\', '%', '_'), array('\\\\', '\%', '\_'), $str));
}

function filter_sql($str) // Вырезаем кавычки
{
    $s = array("'", chr(0), '\\');
    $r = array("", "", "");
    return str_replace($s, $r, $str);
}

function form_local_number($eng_number, $decimals, $space_delimiter = "default")   //при выводе на экран
{
    return \CB\CornyFunc::form_local_number($eng_number, $decimals, $space_delimiter);
}

function form_eng_number($local_number)   //при занесении в базу
{
    return \CB\CornyFunc::form_eng_number($local_number);
}

function form_local_time($eng_time, $display_time = 0, $display_sec = 0)   //при выводе на экран
{
    return \CB\CornyFunc::form_local_time($eng_time, $display_time, $display_sec);
}

function form_eng_time($local_time, $display_time = 1)     //при занесении в базу
{
    global $lang;
    if ($local_time == "") {
        return "0000-00-00" . ($display_time ? (" 00:00:00") : "");
    }
    eval($lang['date_to_timestamp']);
    if (!$year) {
        $year = "0000";
    }
    if (!$month) {
        $month = "00";
    }
    if (!$day) {
        $day = "00";
    }
    if (!$hour) {
        $hour = "00";
    }
    if (!$min) {
        $min = "00";
    }
    if (!$sec) {
        $sec = "00";
    }
    if ("$year-$month-$day $hour:$min:$sec" != '0000-00-00 00:00:00') {
        $int_time = strtotime("$year-$month-$day $hour:$min:$sec");
        return date("Y-m-d" . ($display_time ? (" H:i:s") : ""), $int_time);
    } else {
        return false;
    }
}

function eval_php_condition($line, $evl)
{
    global $user, $config, $lang;

    //Проверяем корректный ли line, чтобы не было ошибок в ходе выполнения выражения
    if (!is_array($line) && (strpos($evl, '$line[') !== false)) {
        return false;
    }

    $shablons = array(
        "{current}",
        "{current_group}",
        "{empty_date}",
        "{current_date}",
        "{current_time}",
        "{cur.date}",
        "{cur.time}"
    );
    $replace = array(
        $user['id'],
        $user['group_id'],
        "0000-00-00 00:00:00",
        date("Y-m-d 00:00:00"),
        date("Y-m-d H:i:s"),
        date("Y-m-d 00:00:00"),
        date("Y-m-d H:i:s")
    );
    $evl = str_replace($shablons, $replace, $evl);

    $evl = 'return ' . $evl . ";";

    return eval($evl);
}

// тест, можно ли распечать шаблон
function test_allow_template_line($table, $line, $template_id, $default = -1)
{
    global $user, $array_form_template_read_acc;

    if (!is_array($line)) {
        $line = sql_select_array(DATA_TABLE . $table['id'], 'id=', $line);
    }

    if ($default == -1) {
        if (empty($array_form_template_read_acc)) {
            $array_form_template_read_acc = array();
            $result = sql_query("SELECT a.id, b.group_id, b.read_acc FROM " . FORMS_TABLE . " a, " . ACC_FORMS_TABLE . " b WHERE a.id=b.form_id");
            while ($form = sql_fetch_assoc($result)) {
                $array_form_template_read_acc[$form['id']][$form['group_id']] = $form['read_acc'];
            }
        }
        $default = $array_form_template_read_acc[$template_id][$user['group_id']];
    }

    $table_id = $table['id'];

    if ($table['rules']) {
        $can_do = -1;
        // Проверяем правила
        foreach ($table['rules'] as $one_rule) { // Перебираем правила, смотрим, есть ли доступ к полю
            foreach ($one_rule['rights'] as $one_right) {
                if (isset($one_right['template'])) {
                    if ($one_right['template'] == $template_id and isset($one_right['read_acc'])) { // Есть правило на собственно само действие
                        if (eval_php_condition($line, $one_rule['condition_php'])) {
                            $can_do = $one_right['read_acc'];
                            break;
                        }
                    }
                }
            }
        }
        if ($can_do == -1) {
            return $default;
        } else {
            return $can_do;
        }
    } else {
        return $default;
    }
}

function test_allow_template_table($table, $template_id, $default)
{
    if ($table['rules']) {
        $can_do = -1;
        // Проверяем правила
        foreach ($table['rules'] as $one_rule) { // Перебираем правила, смотрим, есть ли доступ к полю
            foreach ($one_rule['rights'] as $one_right) {
                if ($one_right['template'] == $template_id and isset($one_right['read_acc'])) { // Есть правило на собственно само действие
                    $can_do = $one_right['read_acc'];
                    break;
                }
            }
            if($can_do == 1) break;
        }
        if ($default == 0 && (!$can_do || $can_do == -1)) {
            return 0;
        } else {
            return 1;
        }
    } else {
        return $default;
    }
}

// тест, можно ли применять доп действие
function test_allow_button_line($table, $line, $button_id, $default)
{
    $table_id = $table['id'];
    if ($table['rules']) {
        $can_do = -1;
        // Проверяем правила
        foreach ($table['rules'] as $one_rule) { // Перебираем правила, смотрим, есть ли доступ к полю
            foreach ($one_rule['rights'] as $one_right) {
                if ($one_right['button'] == $button_id and isset($one_right['access'])) { // Есть правило на собственно само действие
                    if (eval_php_condition($line, $one_rule['condition_php'])) {
                        $can_do = $one_right['access'];
                        break;
                    }
                }
            }
        }
        if ($can_do == -1) {
            return $default;
        } else {
            return $can_do;
        }
    } else {
        return $default;
    }
}

function test_allow_button_table($table, $button_id, $default)
{
    $table_id = $table['id'];
    if ($table['rules']) {
        $can_do = -1;
        // Проверяем правила
        foreach ($table['rules'] as $one_rule) { // Перебираем правила, смотрим, есть ли доступ к полю
            foreach ($one_rule['rights'] as $one_right) {
                if ($one_right['button'] == $button_id and isset($one_right['access'])) { // Есть правило на собственно само действие
                    $can_do = $one_right['access'];
                    break;
                }
            }
        }
        if ($default == 0 && $can_do < 1) {
            return 0;
        } else {
            return 1;
        }
    } else {
        return $default;
    }
}

// тест, можно ли удалять/архивировать строку
function test_allow_right($table, $line, $type)
{
    $table_id = $table['id'];
    if ($table['rules']) {
        $can_do = -1;
        // Проверяем правила
        foreach ($table['rules'] as $one_rule) { // Перебираем правила, смотрим, есть ли доступ к полю
            foreach ($one_rule['rights'] as $one_right) {
                if ($one_right['table'] == $table_id and isset($one_right[$type . '_acc'])) { // Есть правило на собственно само действие
                    if (eval_php_condition($line, $one_rule['condition_php'])) {
                        $can_do = $one_right[$type . '_acc'];
                        break;
                    }
                }
            }
        }
        if (($can_do == -1 && !$table[$type]) || !$can_do) {
            return 0;
        }
    } elseif (!$table[$type]) {
        return 0;
    }
    if ($type) {
        return 1;
    }
}

// тест, можно ли читать в таблице данное поле
function test_allow_read($field, $line = array(), $type_out = "")
{
    global $user, $subtable_rights;
    if ($user['is_root']) {
        return 1;
    }
    // Преобразуем типы
    if ($type_out == "export") $type_out = "read";
    // Разрешенные режимы вывода
    $allowed_type_out = array(
        '' => '',
        'view' => 'view',
        'view_tb' => 'view_tb',
        'view_sub' => 'view_sub',
        'view_edit' => 'view_edit',
        'view_add' => 'view_add',
        'read' => 'read'
    );
    $type_out = $allowed_type_out[$type_out];
    $table_id = $field['table_id'];
    $table = get_table($table_id);

    $disallow_mask = array();
    if (isset($subtable_rights[$field['id']])) {
        return $subtable_rights[$field['id']] ? 1 : 0;
    }

    foreach ($table['rules_reverse'] as $one_rule) {
        if (!isset($one_rule['rights'][$field['id']])) {
            continue;
        }
        foreach ($one_rule['rights'][$field['id']] as $one_right) {
            if (
                $one_right['field'] == $field['id'] &&
                (
                    ($type_out && isset($one_right[$type_out])) ||
                    (!$type_out &&
                        (
                            isset($one_right['view']) ||
                            isset($one_right['view_tb']) ||
                            isset($one_right['read'])
                        )
                    )
                )
            ) {  // Есть правило на данное поле
                $one_rule['condition_php'] = htmlspecialchars_decode($one_rule['condition_php'], ENT_QUOTES); // исправление странного бага с экранированием
                if (eval_php_condition($line, $one_rule['condition_php'])) {  // Условие срабатывает, возвращаем права
                    if (!$type_out) { // Разрешение просмотра в строке / таблице
                        if ($one_right['view'] || $one_right['view_tb'] || $one_right['read']) {
                            return 1;
                        } elseif ($line) { // Необходимо чтобы все маски были запрещены
                            if ($disallow_mask['view'] && $disallow_mask['view_tb'] && $disallow_mask['read']) {
                                return 0;
                            } else {
                                if ($one_right['view']) {
                                    $disallow_mask['view'] = 1;
                                }
                                if ($one_right['view_tb']) {
                                    $disallow_mask['view_tb'] = 1;
                                }
                                if ($one_right['read']) {
                                    $disallow_mask['read'] = 1;
                                }
                            }
                        }

                    } else {
                        if (isset($one_right[$type_out])) {
                            if ($one_right[$type_out]) {
                                return 1;
                            } elseif ($line) {
                                return 0;
                            }
                        }
                    }
                }
            }
        }
    }
    // Правил на поле нет, срабатывает дефолт
    if (!$type_out) {

        //запиливаем штуку для проверки по полю связи, если в одной таблице стоит галочка на добавление записи
        // и в таблице на которую указывает поле связи есть экспорт, тогда разрешаем
        if ($field['view_add'] && $field['type_field'] == 5 && $field['s_table_id'] && $field['s_field_id']) {
            $table_id = $field['s_table_id'];
            $table = get_table($table_id);
            $new_fields = get_table_fields($table);
            $new_field = $new_fields[$field['s_field_id']];;
            foreach ($table['rules_reverse'] as $one_rule) {
                if (!isset($one_rule['rights'][$field['id']])) {
                    continue;
                }
                foreach ($one_rule['rights'][$field['id']] as $one_right) {
                    if ($one_right['field'] == $new_field['id'] && isset($one_right['read'])) {  // Есть правило на данное поле
                        if (eval_php_condition($line,
                            $one_rule['condition_php'])) {// Условие срабатывает, возвращаем права
                            return 1;
                        }
                    }
                }
            }
            //правила не нашли, смотри по дефолту
            if ($new_field['read']) {
                return 1;
            } else {
                return 0;
            }
        }

        if ($field['type_field'] == 7 || $field['type_field'] == 11 && ($field['view_add'])) {
            return 1;
        }

        if ($field['view'] || $field['view_tb'] || $field['read']) {
            return 1;
        } else {
            return 0;
        }
    } else {
        return $field[$type_out] ? 1 : 0;
    }
}

// Дополнить строку - данными из ссылок
function get_link_tables_line(&$line, $table, $ln_tables, $rc)
{
    $table_fields = $table['table_fields'];
    $link_tables = $ln_tables['sub_list'];

    if ($link_tables) {
        foreach ($link_tables as $link_field_id => $link_table_id) {  // перебираем используемые таблицы
            if (is_array($line[$table_fields[$link_field_id]['int_name']])) { // уже получено значение подмассива
                if ($ln_tables[$link_field_id]) {
                    // перебираем дальнейшие вкладки
                    $l_tbl = get_table($link_table_id);
                    $l_field = get_table_fields($l_tbl); // Заполняем link_tables
                    get_link_tables_line($line[$table_fields[$link_field_id]['int_name']], $l_tbl, $ln_tables[$link_field_id], $rc + 1);
                }
            } else { // получаем значение подмассива (для множественных разворачиваем пока только первое значение)
                $raw_value = $line[$table_fields[$link_field_id]['int_name']]; // сырое значение из БД
                if ($raw_value) {
                    $line[$table_fields[$link_field_id]['int_name']] = data_select_array($link_table_id, 'id = ', explode('-', trim($raw_value, '-'))[0]);
                    $line[$table_fields[$link_field_id]['int_name']]['raw'] = $raw_value;
                    if ($ln_tables[$link_field_id]) {
                        // перебираем дальнейшие вкладки
                        $l_tbl = get_table($link_table_id);
                        $l_field = get_table_fields($l_tbl); // Заполняем link_tables
                        get_link_tables_line($line[$table_fields[$link_field_id]['int_name']], $l_tbl, $ln_tables[$link_field_id], $rc + 1);
                    }
                } else {
                    $line[$table_fields[$link_field_id]['int_name']] = array();
                }
            }
        }
    }
}

// Формируем события на изменившиеся строки
function form_event_recurs($table, &$line, $tmp_old_line, $calc_id, & $start_calc, $is_new_line = 0)
{
    global $calc_fields_changes;
    $table_id = $table['id'];
    $table_fields = get_table_fields($table);
    $line_id = $tmp_old_line['id'];
    $event = array(
        'type' => 'calc',
        'table_id' => $table_id,
        'line_id' => $line_id,
        'changed' => array(),
        'calc_id' => $calc_id,
    );
    if ($is_new_line) $event['is_new_line'] = 1;
    foreach ($line as $k => $one_value) {
        $tmp_old_line[$k] = type_conversion($tmp_old_line[$k], $table_fields[$table['int_names'][$k]]['type_field'],
            $table_fields[$table['int_names'][$k]]['mult_value']);
        $one_value = type_conversion($one_value, $table_fields[$table['int_names'][$k]]['type_field'],
            $table_fields[$table['int_names'][$k]]['mult_value']);
        if ($tmp_old_line[$k] !== $one_value) {
            $field_id = $table["int_names"][$k];
            $t_field = $table_fields[$field_id];
            if (is_array($one_value) && $one_value['id']) // Доп защита по id от некоректных строк $line
            { // изменился подмассив, на каждую отдельную таблицу генерируется свое отдельное событие
                if ($tmp_old_line[$k]['raw'] != $one_value['raw']) { // Исходное значение поля ссылки
                    $one_value = $one_value['raw'];
                    data_update($table_id, array($k => $one_value), 'id=', $line_id);
                    // также фиксируем в истории изменений значений
                    $calc_fields_changes[$table_id][$field_id][$line_id] = $line;
                    $event["changed"][$field_id] = array(
                        "field_id" => $field_id,
                        "int_name" => $k,
                        "old" => $tmp_old_line[$k]['raw'],
                        "new" => $one_value
                    );
                } else { // Значения в подтаблице
                    $s_table = get_table($t_field['s_table_id']);
                    get_table_fields($s_table);
                    $s_line = $one_value;
                    $s_tmp_old_line = $tmp_old_line[$k];
                    $s_lines = explode('-', trim($s_tmp_old_line['raw'], '-'));
                    foreach ($s_lines as $s_line_id) {
                        if ($s_line['id'] == $s_tmp_old_line['id']) {
                            $s_line['id'] = $s_tmp_old_line['id'] = $s_line_id;
                        } else {
                            $s_tmp_old_line['id'] = $s_line_id;
                        }
                        form_event_recurs($s_table, $s_line, $s_tmp_old_line, $calc_id, $start_calc);
                    }
                }
            } else {
                if (is_array($tmp_old_line[$k]) && $tmp_old_line['id']) // Доп защита по id от некоректных строк $line
                {
                    if ($tmp_old_line[$k]['raw'] != $one_value) { // Исходное значение поля ссылки
                        data_update($table_id, [
                            $k => (
                                ($table_fields[$field_id]['mult_value'] == '1' && $table_fields[$field_id]['type_field'] == '5')
                                ?  (is_array($one_value) ? ('-'. implode('-', $one_value).'-') : $one_value)
                                : $one_value
                            )
                        ], 'id=', $line_id);
                        // также фиксируем в истории изменений значений
                        $calc_fields_changes[$table_id][$field_id][$line_id] = $line;
                        $event["changed"][$field_id] = array(
                            "field_id" => $field_id,
                            "int_name" => $k,
                            "old" => $tmp_old_line[$k]['raw'],
                            "new" => $one_value
                        );
                    }
                } else {
                    // изменилось значение - сохраняем его в базе
                    data_update($table_id, array($k => $one_value), 'id=', $line_id);
                    // также фиксируем в истории изменений значений
                    if ($k != 'r' and $k != 'u') {
                        $calc_fields_changes[$table_id][$field_id][$line_id] = $line;
                        $event["changed"][$field_id] = array(
                            "field_id" => $field_id,
                            "int_name" => $k,
                            "old" => $tmp_old_line[$k],
                            "new" => $one_value
                        );
                    }
                }
            }
        }
    }
    if ($event["changed"]) {
        // Поле изменилось, генерируем новое событие
        $start_calc[] = array('table' => $table, 'line' => $line, 'event' => $event);
    }
}

// Произвести вычисления над строкой в таблице
// Таблица в которой происходит вычисление
// Строка
// Само вычисление
// Событие которе вызвало вычисление
function calc_line($table, &$line, $calc, $event, $display_notification = 1)
{
    global $config, $user, $smarty, $lang, $ses_id, $button_id, $output, $event_cancel, $event_post_insert, $show_sql_request, $csrf, $calc_stack, $bm_errors, $qst;
    // Поля заголовка и описания
    $h1_name = $qst['h1_name'];
    $description = $qst['description'];

    $line_id = $line['id'];
    $calc['line_id'] = $line_id;
    // Проверка рекурсивного вызова
    if ($calc['recursion_disabled'] && $calc_stack) {
        foreach ($calc_stack AS $one_calc) {
            if ($calc['id'] == $one_calc['id'] && $one_calc['line_id'] == $line_id) {
                return;
            }
        }
    }
    // Проверяем фильтр если задан
    if ($calc['filter']) {
        if (!sql_num_rows(data_select_field($table['id'], 'id', 'id = ', $line['id'], ' AND (' . filter_tpl_replace($calc['filter']) . ')'))) {
            return;
        }
    }
    // Вычисления в поле
    $table_id = $table['id'];
    $table_fields = $table['table_fields'];
    // Запоминаем старые параметры строки
    $start_values = $line;
    get_link_tables_line($line, $table, $calc['link_fields'], 1);
    $tmp_old_line = $line;
    $ID = $line['id'];
    if ($qst['id']) {
        $qst_id = $qst['id'];
    } // для вычислений в формах
    $calculate = $calc['calculate'];
    if ($calc["old_format"]) {
        $calculate = str_replace("{ID}", $ID, $calculate);
    }
    $calc_errors = array();
    $calc['table_name'] = $table['name_table'];
    if (!is_array($calc_stack)) {
        $calc_stack = array();
    }
    array_push($calc_stack, $calc);

    $GLOBALS['cur_calc_id'] = $calc['id'];
    $calc_start = microtime(true);
    if (isset($config['api'])) {
        eval($calculate);
    } else {
        $bm_errors->start_calc();
        eval($calculate);
        $bm_errors->stop_calc();
    }
    $calc_end = microtime(true);
    unset($GLOBALS['cur_calc_id']);

    if ($config['log_calc_runtime']) {
        sql_insert(CALC_LOG_TABLE, ['calc_id' => $calc['id'], 'date' => date('Y-m-d H:i:s'), 'time' => $calc_end - $calc_start]);
    }

    // Нормализуем значения числовых полей в переменной $line, для более корректной работы с полем в других вычислениях
    foreach ($table_fields as $one_field) {
        if ($one_field['type_field'] == 1) {
            $line[$one_field['int_name']] = round((float)$line[$one_field['int_name']], $one_field['dec_dig']);
        }
    }

    // Сохраняем ошибки вычислений текущей строки в сессии
    if (!is_array($_SESSION[$ses_id]['calc_errors'][$line_id])) {
        $_SESSION[$ses_id]['calc_errors'][$line_id] = array();
    }
    foreach ($calc_errors as $one_error) {
        $_SESSION[$ses_id]['calc_errors'][$line_id][] = $one_error;
    }

    if (!$table['view_sql']) {
        // Сохраняем изменения в базе
        $start_calc = array();
        form_event_recurs($table, $line, $tmp_old_line, $calc['id'], $start_calc, ($event['is_new_line'] ?? 0));
        // Если необходимо генерируем новые события
        foreach ($start_calc as $one_calc) {
            if ($event['type'] == 'button' || $event['type'] == 'save' || $event['type'] == 'update') {
                tip_popup_event($one_calc['table'], $one_calc['line'], $one_calc['event'], $display_notification);
            } else {
                popup_event($one_calc['table'], $one_calc['line'], $one_calc['event'], $display_notification);
            }
        }
    }
    if (is_array($calc)) {
        array_pop($calc);
    }
}

// Вычисление переменной в шаблоне печати
function calc_form_var($calc)
{
    global $config, $user, $smarty, $lang, $ses_id, $csrf, $xls_ext;
    $line_id = $eval_line_id;
    try {
        return @eval($calc);
    } catch (Throwable $t) {
        return ;
    }
}

// Получить список необходимых вычислений, изходя из mysql запроса выбирающего вычисления
function get_calcs($sqlQuery, &$calcs)
{
    global $calc_cache_flag, $calcs_cache;
    if ($calc_cache_flag) {
        if (isset($calcs_cache[$sqlQuery])) { // Есть в кеше
            $calcs = array_merge($calcs, $calcs_cache[$sqlQuery]);
        } else {
            $calcs_add = array();
            $result = sql_query($sqlQuery);
            while ($cond_l = sql_fetch_assoc($result)) {
                if (!$calcs_add[$cond_l['id']]) { // если вычисление, не заполнено в массив, добавляем его.
                    $calc['id'] = $cond_l['id'];
                    $calc['table_id'] = $cond_l['table_id'];
                    $calc['name'] = $cond_l['name'];
                    $calc['calculate'] = $cond_l['calculate'];
                    $calc['old_format'] = $cond_l['old_format'];
                    $calc['link_fields'] = unserialize($cond_l['link_fields']);
                    $calc['recursion_disabled'] = $cond_l['recursion_disabled'];
                    $calc['filter'] = $cond_l['filter_id'] ? sql_fetch_row(sql_select_field(FILTERS_TABLE, 'value', 'id = ', $cond_l['filter_id'], ' AND table_id = ', $cond_l['table_id']))[0] : '';
                    $calcs_add[$calc['id']] = $calc;
                }
                $cond['type'] = $cond_l['cond_type'];
                $cond['param'] = $cond_l['cond_param'];
                $cond['param2'] = $cond_l['cond_param2'];
                $calcs_add[$cond_l['id']]['conditions'][] = $cond;
            }
            $calcs_cache[$sqlQuery] = $calcs_add;
            $calcs = array_merge($calcs, $calcs_add);
        }
    } else {
        $result = sql_query($sqlQuery);
        while ($cond_l = sql_fetch_assoc($result)) {
            if (!$calcs[$cond_l['id']]) { // если вычисление, не заполнено в массив, добавляем его.
                $calc['id'] = $cond_l['id'];
                $calc['table_id'] = $cond_l['table_id'];
                $calc['name'] = $cond_l['name'];
                $calc['calculate'] = $cond_l['calculate'];
                $calc['old_format'] = $cond_l['old_format'];
                $calc['link_fields'] = unserialize($cond_l['link_fields']);
                $calc['recursion_disabled'] = $cond_l['recursion_disabled'];
                $calc['filter'] = $cond_l['filter_id'] ? sql_fetch_row(sql_select_field(FILTERS_TABLE, 'value', 'id = ', $cond_l['filter_id'], ' AND table_id = ', $cond_l['table_id']))[0] : '';
                $calcs[$calc['id']] = $calc;
            }
            $cond['type'] = $cond_l['cond_type'];
            $cond['param'] = $cond_l['cond_param'];
            $cond['param2'] = $cond_l['cond_param2'];
            $calcs[$cond_l['id']]['conditions'][] = $cond;
        }
    }
}

// Функция
// Выполняет всплытие безтабличного сообщения
function popup_event_g($event)
{
    global $config, $user, $smarty, $lang, $ses_id, $csrf;
    $calcs = array();
    if ($event['type'] == 'login') {
        $sqlQuery = "SELECT a.type as cond_type, a.param as cond_param, a.param2 as cond_param2, b.* FROM " . CALC_COND_TABLE . " a, " . CALC_TABLE . " b WHERE a.type='" . EVT_USER_LOGIN . "' and a.calc_id=b.id and b.table_id='0' and b.disabled=0 ORDER BY num, id";
        get_calcs($sqlQuery, $calcs);
    }
    if ($event['type'] == 'user_change') {
        $sqlQuery = "SELECT a.type as cond_type, a.param as cond_param, a.param2 as cond_param2, b.* FROM " . CALC_COND_TABLE . " a, " . CALC_TABLE . " b WHERE a.type='" . EVT_USER_CHANGE . "' and a.calc_id=b.id and b.table_id='0' and b.disabled=0 ORDER BY num, id";
        get_calcs($sqlQuery, $calcs);
    }
    foreach ($calcs as $calc) {
        eval($calc['calculate']);
    }
}

// Выполняет всплытие табличного сообщения
function popup_event($table, & $line, $event, $display_notification = 1)
{
    global $calc_fields_changes, $event_recurs_level, $config, $lang, $user, $sync_exp_list, $sync_exp_fields, $sync_exp_rfields, $sync_exp_data, $sync_exp_rtables;
    $table_fields = get_table_fields($table); // В случае со старыми вычислениями, поля таблицы не загружены
    $table_id = $table['id'];
    $line_id = $line['id'] ?? $GLOBALS['line_id'] ?? -1;

    if ($event_recurs_level > 100) {
        generate_error("event_recurs_level > 100"); // Произошло зацикливание
        exit;
    }
    $event_recurs_level++;

    $calcs = array();

    if ($event['type'] == 'save' || $event['type2'] == 'save') { // Событие сохранение строки
        global $double_found;
        $sqlQuery = "SELECT a.type as cond_type, a.param as cond_param, a.param2 as cond_param2, b.* FROM " . CALC_COND_TABLE . " a, " . CALC_TABLE . " b WHERE a.type='" . EVT_LINE_SAVE . "' and a.calc_id=b.id and b.table_id='$table_id' and b.disabled=0 ORDER BY num, id";
        get_calcs($sqlQuery, $calcs);
        if ($display_notification == 1 && $event['line_id'] !== 'new') {
            if ($double_found) {
                display_notification($lang['No_save_notif'], 2);
            } else {
                if ($config['disable_full_edit'] && $_REQUEST['line'] == 'new') {
                    //
                } else {
                    display_notification($lang['Success_save_notif'], 1);
                }
            }
        }
        if (($event['is_new_line'] || $event['is_new_again']) && $config['event_on']['add_record']) { // событие добавления записи
            $name_record = get_name_record($table, $table_fields, $line);
            $subject = get_event_subject($event);
            $mess = $subject . $lang["new_line_added_p0"] . "<a href='view_line" . $config["vlm"] . ".php?table=$table_id&line=$line_id'>" . $name_record . "</a>" . $lang["new_line_added_p1"] . $table['display']['name_table'] . $lang["new_line_added_p2"];
            \CB\CornyService::insert_log_light("add_record", $mess, $table_id, $line_id);
        }
    }

    if ($event['type'] == 'restore' || $event['type2'] == 'restore') { // Событие восстановления строки
        $sqlQuery = "SELECT a.type as cond_type, a.param as cond_param, a.param2 as cond_param2, b.* FROM " . CALC_COND_TABLE . " a, " . CALC_TABLE . " b WHERE a.type='" . EVT_LINE_RESTORE . "' and a.calc_id=b.id and b.table_id='$table_id' and b.disabled=0 ORDER BY num, id";
        get_calcs($sqlQuery, $calcs);
        if ($display_notification == 1) {
            if ($event['archivation'] == 1) {
                display_notification($lang['Success_archive_notif'], 1);
            } else {
                display_notification($lang['Success_restore_notif'], 1);
            }
        }
    }

    if ($event['type'] == 'view' || $event['type2'] == 'view') { // Событие просмотр строки
        $sqlQuery = "SELECT a.type as cond_type, a.param as cond_param, a.param2 as cond_param2, b.* FROM " . CALC_COND_TABLE . " a, " . CALC_TABLE . " b WHERE a.type='" . EVT_FIELD_SHOW . "' and a.calc_id=b.id and b.table_id='$table_id' and b.disabled=0 ORDER BY num, id";
        get_calcs($sqlQuery, $calcs);
    }

    if ($event['type'] == 'delete' || $event['type2'] == 'delete') { // Событие удаление строки
        global $cancel_delete;
        $sqlQuery = "SELECT a.type as cond_type, a.param as cond_param, a.param2 as cond_param2, b.* FROM " . CALC_COND_TABLE . " a, " . CALC_TABLE . " b WHERE a.type='" . EVT_LINE_DROP . "' and a.calc_id=b.id and b.table_id='$table_id' and b.disabled=0 ORDER BY num, id";
        get_calcs($sqlQuery, $calcs);
        // логирование и display_notification перенесены вниз на после вызова вычисления, т.к. зависят от заполнения $cancel_delete
    }

    if ($event['type'] == 'import' || $event['type2'] == 'import') { // Событие импорт строки
        $sqlQuery = "SELECT a.type as cond_type, a.param as cond_param, a.param2 as cond_param2, b.* FROM " . CALC_COND_TABLE . " a, " . CALC_TABLE . " b WHERE a.type='" . EVT_TABLE_IMPORT . "' and a.calc_id=b.id and b.table_id='$table_id' and b.disabled=0 ORDER BY num, id";
        get_calcs($sqlQuery, $calcs);
        if ($config['event_on']['import'] && !$event['caller'] == '1C') {
            $name_record = get_name_record($table, $table_fields, $line);
            $subject = get_event_subject($event);
            $mess = $subject . $lang['import_p0'] . "<a href='view_line" . $config['vlm'] . ".php?table=$table_id&line=$line_id'>" . $name_record . "</a>" . $lang['import_p1'] . $table['name_table'] . $lang['import_p2'];
            \CB\CornyService::insert_log_light("import", $mess, $table_id, $line_id);
        }
    }

    if ($event['type'] == 'questionare' || $event['type2'] == 'questionare') { // Событие удаление строки
        $sqlQuery = "SELECT a.type as cond_type, a.param as cond_param, a.param2 as cond_param2, b.* FROM " . CALC_COND_TABLE . " a, " . CALC_TABLE . " b WHERE a.type='" . EVT_NEW_QST . "' and a.param='" . $event['param'] . "' and a.calc_id=b.id and b.table_id='$table_id' and b.disabled=0 LIMIT 1";
        get_calcs($sqlQuery, $calcs);
    }

    if ($event['changed']) { // Есть измененые поля, выполняем вычисления связанные с изменением полей
        $sync_first_array = array();
        foreach ($event['changed'] as $one_change) {
            $field_id = $one_change['field_id'];
            $type_field = $table['table_fields'][$field_id]['type_field'];
            $sqlQuery = "SELECT a.type as cond_type, a.param as cond_param, a.param2 as cond_param2, b.* FROM " . CALC_COND_TABLE . " a, " . CALC_TABLE . " b WHERE (a.param='$field_id' or a.param='-1') and a.type=3 and a.calc_id=b.id and b.table_id='$table_id' and b.disabled=0 ORDER BY num, id";
            get_calcs($sqlQuery, $calcs);
            if ($event["type"] == 'calc') {
                $event_type = "change_calc_field";
            } elseif ($user['is_cron']) {
                $event_type = "change_cron_field";
            } else {
                $event_type = "change_field";
            }

            if ($config['event_on'][$event_type] || $sync_exp_fields[$field_id]) {
                $t_field = $table['table_fields'][$one_change['field_id']];
                $t_line = $line;
                if ($t_field["crypt"]) {
                    $old_v = $new_v = "*****";
                } else {
                    $t_line[$t_field["int_name"]] = $one_change['old'];
                    $old_v = form_display_type($t_field, $t_line, 'text');
                    $t_line[$t_field["int_name"]] = $one_change['new'];
                    $new_v = form_display_type($t_field, $t_line, 'text');
                }
                if ($old_v == "0") {
                    $old_v = "";
                }
                if ($new_v == "0") {
                    $new_v = "";
                }
                if ($old_v != $new_v or $t_field["crypt"]) {
                    $old_v = htmlSubstrTrig($old_v, 100);
                    $new_v = htmlSubstrTrig($new_v, 100);
                    // Синхронизация
                    if ($sync_exp_fields[$field_id]) {
                        foreach ($sync_exp_fields[$field_id] as $sync_id => $sync_field_info) {
                            if ($sync_id == $event['sync_id']) { // Событие вызвано текущей синхронизацией, пропускаем
                                continue;
                            }
                            if ($line['s' . $sync_id] == '') { // Запись уже была добавлена, но не системно, пропускаем, т.к. добавление произойдёт в flush_sync()
                                continue;   // было закомментировано по заданию 78239 и раскомментировано назад по заданию 78819
                            }
                            if ($line['status'] == 3 OR $line['status'] == 4) { // Пропускаем строки со статусом 3 или 4
                                continue;
                            }
                            $sync_new_line = false;
                            // Определяем идентификатор выгружаемой строки
                            if ($sync_exp_list[$sync_id]['sync_mode'] AND $line['s' . $sync_id] != "S") {
                                $sync_line_id = $line['s' . $sync_id];
                            } elseif (!$sync_exp_list[$sync_id]['sync_mode'] AND $line['s' . $sync_id] != "S") {
                                $sync_line_id = $line_id;
                            } else {
                                $sync_line_id = "^" . $line_id;
                                $sync_new_line = true;
                            }

                            if ($type_field == 5) { // Поле связи
                                $link_field_data = data_select_array($t_field['s_table_id'], "id=", $one_change['new']);
                                if (!$link_field_data) {
                                    continue;
                                }

                                if ($sync_exp_list[$sync_id]['tables'][$t_field["s_table_id"]] OR $sync_exp_rtables[$t_field["s_table_id"]][$sync_id]) // Целевая таблица также синхронизируется
                                {
                                    if ($link_field_data["s" . $sync_id] == "S") { // Целевая строка не засинхронизирована
                                        $cache_res = sql_select_field(SYNC_CACHE_TABLE, "id", "sync_id=", $sync_id,
                                            " and field_id=", $t_field['s_field_id'], " and line_id=",
                                            $one_change['new']);
                                        if (!sql_fetch_assoc($cache_res)) // В кэше на выгрузку записи тоже нет, убираем S для того, чтобы строка добавилась в список для синхронизации
                                        {
                                            data_update($t_field['s_table_id'], array("s" . $sync_id => ""), "id=",
                                                $one_change['new']);
                                        }
                                        // Добавляем текущую строку в кэш для выгрузки
                                        sql_insert(SYNC_CACHE_TABLE, array(
                                            "sync_id" => $sync_id,
                                            "table_id" => $table_id,
                                            "field_id" => $field_id,
                                            "line_id" => $line_id,
                                            "value" => "^" . $one_change['new'],
                                            "upload_count" => 1,
                                            "last_upload" => date("Y-m-d H:i:s")
                                        ));
                                    } else // Целевая запись засинхронизирована, выгружаем поле связи
                                    {
                                        if ($sync_exp_list[$sync_id]['sync_mode']) // Активный режим
                                        {
                                            $link_export_data = $link_field_data["s" . $sync_id];
                                        } else // Пассивный режим
                                        {
                                            $link_export_data = $link_field_data["id"];
                                        }
                                        $sync_exp_data[$sync_field_info['sync_id']][$field_id][$sync_line_id] = $link_export_data;
                                        if ($sync_new_line) // Строка новая, добавляем в кэш
                                        {
                                            sql_insert(SYNC_CACHE_TABLE, array(
                                                "sync_id" => $sync_id,
                                                "table_id" => $table_id,
                                                "field_id" => $field_id,
                                                "line_id" => $line_id,
                                                "value" => $link_export_data,
                                                "upload_count" => 1,
                                                "last_upload" => date("Y-m-d H:i:s")
                                            ));
                                        }
                                    }
                                } else { // Целевое поле связи не синхронизируется, выгружаем текст
                                    $link_field_intname = form_int_name($t_field['s_field_id']);
                                    $sync_exp_data[$sync_field_info['sync_id']][$field_id][$sync_line_id] = $link_field_data[$link_field_intname];
                                    if ($sync_new_line) // Строка новая, добавляем в кэш
                                    {
                                        sql_insert(SYNC_CACHE_TABLE, array(
                                            "sync_id" => $sync_id,
                                            "table_id" => $table_id,
                                            "field_id" => $field_id,
                                            "line_id" => $line_id,
                                            "value" => $link_field_data[$link_field_intname],
                                            "upload_count" => 1,
                                            "last_upload" => date("Y-m-d H:i:s")
                                        ));
                                    }
                                }
                            } else { // Обычное поле, добавляем сразу
                                $sync_exp_data[$sync_field_info['sync_id']][$field_id][$sync_line_id] = $one_change['new'];
                                if ($sync_new_line) // Строка новая, добавляем в кэш
                                {
                                    sql_insert(SYNC_CACHE_TABLE, array(
                                        "sync_id" => $sync_id,
                                        "table_id" => $table_id,
                                        "field_id" => $field_id,
                                        "line_id" => $line_id,
                                        "value" => $one_change['new'],
                                        "upload_count" => 1,
                                        "last_upload" => date("Y-m-d H:i:s")
                                    ));
                                }
                            }
                            // Костыль для синхронизации по заданию 53185 так как данный аспект не продумали
                            if ($sync_new_line) {
                                $sync_first_array[$sync_id] = $sync_id;
                            }
                        }
                    }
                    // Логи
                    if ($config['event_on'][$event_type]) {
                        $subject = get_event_subject($event);
                        $name_record = get_name_record($table, $table_fields, $line);
                        if ($type_field == 6 || $type_field == 9) {
                            if ($event['is_new_line']) {
                                $files = array_filter(explode("\r\n", $new_v));
                                foreach ($files as $f_name) {
                                    $mess = $subject . $lang['add_file_p0'] . $t_field['name_field'] . $lang['add_file_p1'] . $table['name_table'] . $lang['add_file_p2'] . "<a href='view_line" . $config["vlm"] . ".php?table=$table_id&line=$line_id'>" . $name_record . "</a>" . $lang['add_file_p3'] . $f_name . $lang['add_file_p4'];
                                    \CB\CornyService::insert_log_light($event_type, $mess, $table_id, $line_id);
                                }
                            }
                        } else {
                            $mess = $subject . $lang['change_record_p0'] . $t_field['name_field'] . $lang['change_record_p1'] . $table['name_table'] . $lang['change_record_p2'] . " <a href='view_line" . $config["vlm"] . ".php?table=$table_id&line=$line_id'>" . $name_record . "</a> " . $lang['change_record_p3'] . strip_tags($old_v) . $lang['change_record_p4'] . strip_tags($new_v) . $lang['change_record_p5'];
                            \CB\CornyService::insert_log_light($event_type, $mess, $table_id, $line_id);
                        }
                        $test_read = test_allow_read($t_field, $line, 'view');
                        if (cb_isset($config, 'type_events_favorites', 'edit') && $test_read) {
                            $mess = $subject . $lang['change_record_p0'] . $t_field['name_field'] . $lang['change_record_p1'] . $table['name_table'] . $lang['change_record_p2'] . " <a href='view_line" . $config["vlm"] . ".php?table=$table_id&line=$line_id'>" . $name_record . "</a> " . $lang['change_record_p3'] . strip_tags($old_v) . $lang['change_record_p4'] . strip_tags($new_v) . $lang['change_record_p5'];
                            send_event_of_favorite_record($table_id, $line_id, $mess);
                        }
                    }
                }
            }

            // добавил для того чтобы на фронте получить обновленные данные
            $calc_fields_changes[$table_id][$field_id][$line_id] = $line;
        }
        if (count_cb($sync_first_array)) {
            foreach ($sync_first_array as $sync_id) {
                sync_first($sync_id, $table_id, $line_id);
            }
        }
    }

    $calc_start_flag = true;
    foreach ($calcs as $calc) {
        $calc_table = get_table($calc['table_id']);
        $calc_fields = get_table_fields($calc_table);
        foreach ($calc['conditions'] as $i => $one_condition) {
            //если вычисление при отображении поля, проверим отображение этого поля
            if ($one_condition['type'] == 2) {
                if (test_allow_read($calc_fields[$one_condition['param']], $line, 'view_tb')) {
                    $calc_start_flag = true;
                } else {
                    $calc_start_flag = false;
                }
            }
        }
        if ($calc_start_flag) {
            calc_line($table, $line, $calc, $event);
        } else {
            $calc_start_flag = true;
        }
    }
    $event_recurs_level--;

    if ($event['type'] == 'delete' || $event['type2'] == 'delete') { // удаление строки (перенос логирования и сообщений на после вызов вычисления)
        if (!$cancel_delete and $config['event_on']['delete_record']) {
            $name_record = get_name_record($table, $table_fields, $line);
            $subject = get_event_subject($event);
            $mess = $subject . $lang["delete_record_p0"] . " <a href='view_line" . $config["vlm"] . ".php?table=$table_id&line=$line_id'>" . $name_record . "</a> " . $lang["delete_record_p1"] . $table['name_table'] . $lang["delete_record_p2"];
            \CB\CornyService::insert_log_light("delete_record", $mess, $table_id, $line_id);
        }
        if ($config['type_events_favorites']['delete']) {
            $mess = $subject . $lang["delete_record_p0"] . " <a href='view_line" . $config["vlm"] . ".php?table=$table_id&line=$line_id'>" . $name_record . "</a> " . $lang["delete_record_p1"] . $table['name_table'] . $lang["delete_record_p2"];
            send_event_of_favorite_record($table_id, $line_id, $mess);
        }
        if ($display_notification == 1) {
            if ($cancel_delete) {
                display_notification($lang['No_delete_notif'], 2);
            } else {
                display_notification($lang['Success_delete_notif'], 1);
            }
        }
    }
}

function tip_popup_event($table, &$line, $event, $display_notification = 1, $call_from_update_value = 0)
{
    global $config;

    $line_id = $line['id'];
    popup_event($table, $line, $event, $display_notification);
    if (!$config['periodic_tips'] and $line_id > 0) {
        if($call_from_update_value == 0){
            form_tips_line($table, $line, $event); // запускаем напоминания по измененной строке
        }
        else {
            $field_int_name = '';
            foreach($event['changed'] as $id => $value){
                $field_int_name = $value['int_name'];
            }
            create_postponed_tip($table['id'], $line['id'], $field_int_name);
        }
    }
}

function create_postponed_tip($table_id, $line_id, $field_int_name)
{
    global $config;
    $result = sql_select($config['table_prefix'] . 'tips_postpone', "table_id='" . $table_id . "' AND line_id='" . $line_id . "' AND field_int_name='" . $field_int_name . "'");
    if(sql_num_rows($result) < 1){
        sql_insert($config["table_prefix"] . "tips_postpone", [
            "table_id" => $table_id,
            "line_id" => $line_id,
            "field_int_name" => $field_int_name,
        ]);
    }
}

function tips_after_update_value ($table_id, $line_id)
{
    $qesult = sql_query("SELECT tip.id AS tip_id, tip.cond_value AS tip_cond_value, tip.use_records AS tip_use_records, users.*
        FROM " . TIPS_TABLE . " AS tip, " . ACC_TIPS_TABLE . " AS acc_tip, " . USERS_TABLE . " AS users
        WHERE tip.disabled=0 AND tip.table_id=" . $table_id . " AND tip.id=acc_tip.tip_id AND tip.cond_value!='' AND acc_tip.group_id=users.group_id");
    while ($user = sql_fetch_assoc($qesult)) {
        $upd_arr = array();
        $upd_arr['u'] = 1;
        // также проверяем, активно ли условие, если нет - отмечаем это тоже
        $cond_value = filter_tpl_replace($user['tip_cond_value']);
        if ($cond_value) {
            $cond_value = "and ($cond_value)";
        }
        $table_sql = sql_query("SELECT id FROM " . DATA_TABLE . $table_id . " as a WHERE a.id = " . $line_id . " AND status IN (" . ($user['tip_use_records'] ?: '0') . ") $cond_value");
        if (!sql_num_rows($table_sql)) {
            $upd_arr['inactive'] = 1;
        }
        // сохраняем изменения
        $cond_tips_show_arhive_table = '';
        foreach ($upd_arr as $upd_arr_key => $upd_arr_value) {
            $cond_tips_show_arhive_table .= ' AND ' . $upd_arr_key . '!=' . $upd_arr_value;
        }
        $table_sql = sql_select_field(TIPS_SHOW_ARHIVE_TABLE, "id", "user_id=", $user["id"], " AND tip_id=", $user['tip_id'],
            " AND table_id=", $table_id, " AND line_id=", $line_id, " $cond_tips_show_arhive_table order by id desc limit 1");
        if (sql_num_rows($table_sql)) {
            sql_update(TIPS_SHOW_ARHIVE_TABLE, $upd_arr, "user_id=", $user["id"], " AND tip_id=",
                $user['tip_id'],
                " AND table_id=", $table_id, " AND line_id=", $line_id,
                " $cond_tips_show_arhive_table order by id desc limit 1");
        }
    }
}

/**
 * Сформировать значение ячейки для отображения в таблице
 *
 * @param [type] $field             описание поля
 * @param [type] $line              строка содержащая необходимое поле, является результатом выборки из таблицы
 * @param string $type_out          тип вывода
 * @param integer $recursive        служебное поле, указывать нет необходимости
 * @param boolean $for_subtable     данная функция вызвана для формирования значений в подтаблице?
 * @return mixed
 *
 * type_out
 *          view - просмотр записи
 *          text - текстовое значение
 *          view_sub - данные для подтаблицы
 *
 *          view_for_pdf - требуется расширенный уровень прав доступа "экспорт"(чтение) для шаблонов печати pdf,
 *                         после проверки права на чтение переназначаю на view, для получение правильной верстки.
 */
function form_display_type($field, &$line, $type_out = "view", $recursive = 0, $for_subtable = false)     //при выводе данных
{
    global $config, $user, $lang, $ses_id, $crypt_key, $crypt_value;

    if (is_array($type_out)) { /* для PDF шаблонов */
        // флаг для обработки прав доступа к полю для pdf
        $view_for_pdf = $type_out[0] == "view_for_pdf";
        // флаг для обработки переносов строк в pdf
        $part_form_template = in_array($type_out[2], ['head_form','body_form','foot_form']);
        // скидываю до первоначального флага при заходе в ф-цию
        $type_out = $type_out[1] ?? "view";
    }
    $type_out_for_test = $view_for_pdf ? "export" : $type_out;
    if (is_array($line) && $line['status'] == 3) {
        $type_out_for_test = 'view_add';
    }
    $test_read = test_allow_read($field, $line, $type_out_for_test);
    if (!$test_read) {
        return false;
    }

    $line_id = is_array($line) ? $line['id'] : $line;
    $value = is_array($line) ? $line[$field['int_name']] : $line;
    $table_id = $field['table_id'];
    if ($_COOKIE['is_mobile']) {
        $is_mobile = 1;
    }

    $type = $field['type_field'];
    $type_value = $field['type_value'];
    if ($type == 1 or $type == 10)  //тип поля число
    {
        // прибавляем нули слева, в случае необходимости ("минимальное число выводимых цифр")
        $dig_count = strlen(number_format((float)$value, $field['dec_dig'], '', ''));
        if ($dig_count < $field['min_dig']) {
            $value = str_repeat("9", $field['min_dig'] - $dig_count) . $value;
        } // вставляем временно 9 вместо 0, для успешного форматирования
        // форматируем число в локальном формате
        if ($type_out == "export") {
            $new_value = form_local_number($value, $field['dec_dig'], "");
        } // отключаем разделитель (разделитель - пустая строка) при экспорте
        else {
            $new_value = form_local_number($value, $field['dec_dig']);
        }
        // завершающая обработка
        for ($i = 0; $i < $field['min_dig'] - $dig_count; $i++) {
            if ($new_value[$i] == 9) {
                $new_value[$i] = 0;
            } else {
                $dig_count--;
            }
        } // заменяем 9 на 0
    } elseif ($type == 2 or $type == 12)  //тип поля дата
    {
        $new_value = form_local_time($value, $type_value);
    } elseif ($type == 3)   //тип поля текст
    {
        if ($field['crypt'] and isset($config['crypt_hash']) and $crypt_key and $config['crypt_type'] == "strong") {
            if ($_SESSION[$ses_id]['decrypt_lines'][$line_id]) {
                $value = text_decrypt($crypt_key, $value) ?: $value;
            } elseif ($line_id) {
                $value = "******";
                $crypt_value[$field['id']] = 1;
            }
        } elseif ($field['crypt'] and isset($config['crypt_hash']) and !$crypt_key) {
            $crypt_value[$field['id']] = 1;
        }

        if ($crypt_value[$field['id']] and $type_out == "view") {
            $new_value = $value . " <a href='' onclick='show_crypt_field(0); return false'>" . $lang['show'] . "</a>";
        } elseif ($field['hyperlink'] and ($type_out == "view" || $type_out == "view_tb")) {
            $sites = explode(', ', str_replace('; ', ', ', $value));
            $new_values = [];
            foreach ($sites as $one_site) {
                $new_values[] = form_hyperlink($one_site);
            }
            $new_value = implode(', ', $new_values);
        } elseif ($field['phone_type'] && $user['asterisk_login']) {
            global $ASTERISK_SETTINGS;
            $hide_phones_for_groups = explode(',', $ASTERISK_SETTINGS['hide_phones_for_groups']);
            $hide_phones_type = $ASTERISK_SETTINGS['hide_phones_type'];
            $hide_phones_count_chars = $ASTERISK_SETTINGS['hide_phones_count_chars'];
            $all_values = explode(",", $value);
            foreach ($all_values as &$one_value) {
                if (in_array($user['group_id'], $hide_phones_for_groups)) {
                    if ($hide_phones_type == -1) {
                        $one_value = "";
                    } elseif ($hide_phones_type == 0) {
                        $one_value = "******";
                    } elseif ($hide_phones_type == 1) {
                        $one_value = str_repeat("*", $hide_phones_count_chars) . substr($one_value, $hide_phones_count_chars);
                    } elseif ($hide_phones_type == 2) {
                        $one_value = substr($one_value, 0, -$hide_phones_count_chars) . str_repeat("*", $hide_phones_count_chars);
                    }
                }
            }
            $new_value = implode(" , ", $all_values);
        } else {
            if ((!$field['view_html']) && ($type_out != "text") && ($type_out != "export") && ($type_out != "tips")) {
                if ($type_out == "" || $type_out == "export_full") {
                    $new_value = $value;
                } else {
                    $new_value = \str_replace(["\r\n", "\n\r", "\n"], "<br>", form_display($value));
                }
            } else {
                $new_value = $value;
            }
        }
    } elseif ($type == 4)   //тип поля список
    {
        $new_values = [];
        $values = explode("\r\n", $value);
        foreach ($values as $value) {
            $new_values[] = $lang['conf'][$value] ?: $value;
        }
        $new_value = implode("\r\n", $new_values);
    } elseif ($type == 5)   //тип поля связь
    {
        if ($type_out != "search") {
            $table_id = $field['s_table_id'];
            $field_id = $field['s_field_id'];
            $show_field_name = $field['s_show_field_name'];
            $show_field_inline = $field['s_show_field_inline'];
            if ($type_out == "text") {
                $show_field_inline = false;
            } //Эмуляция поиска с выводом в одну строку

            $s_table_field = get_table($table_id);
            $display_fields = get_table_fields($s_table_field);
            $display_field = $display_fields[$field_id];

            if (is_array($value)) { // Значение уже заполнено, т.к. использовалось в вычислениях
                $link_line = $value;
                $value = $value['raw'];
            } elseif (!$value) {
                return '';
            }

            $mult_display_value = [];
            if ($field['mult_value'] && $value) {
                $values = array_unique(strpos('-', $value) === false ? explode('-', trim($value, '-')) : explode(',', trim($value)));
            } else {
                $values[] = $value;
            }

            foreach ($values as $value) {
                if (count($values) == 1 && $link_line) {
                    // уже есть массив значений из $line
                } else {
                    $link_line = data_select_array($table_id, 'id = ', $value);
                }
                if ($link_line) {
                    $current_value_id = (int)$value;

                    $old_disable = $field['disable_link'];
                    $display_value = $link_line[$s_table_field['int_names'][$field_id]];
                    if ($type_out == "view_tb") {
                        $type_out = "view";
                    }

                    if (($type_out == "" || $type_out == "view" || $type_out == "view_sub" || $type_out == "html") && $display_field['type_field'] == 9) {
                        $display_value = form_display_type($display_field, $link_line, "tips", 1);
                    } elseif ($type_out == "text" or $type_out == "export") {
                        $display_value = form_display_type($display_field, $link_line, "text", 1);
                    } else {
                        $display_value = form_display_type($display_field, $link_line, "", 1);
                    }
                    if ($display_value === false) {
                        $display_value = $lang['No_access'];
                    }
                    if ($type_out == 'view' || $type_out == 'view_sub' || $type_out == 'edit' || $type_out == 'text') {
                        $display_value = str_replace(["\r\n", "\r", "\n"], ' ', $display_value);
                    }

                    if ($type_out == 'view_sub' && $field['mult_value'] == 1) {
                        $mult_display_value[$current_value_id] = [
                            'id' => $current_value_id,
                            'text' => $display_value,
                            'additional_field' => []
                        ];
                    }

                    if (!in_array($type_out, ["html", "export", "export_full", "text", "edit", "tips", ""])) {
                        if ($field['mult_value']) {
                            $mult_display_value[$current_value_id] = [
                                'id' => $current_value_id,
                                'text' => $display_value,
                                'additional_field' => []
                            ];
                        } else {
                            $display_value = (($show_field_inline ? '<span>' : '') . $display_value . (!$show_field_inline ? '</span>' : ''));
                        }
                    }

                    if ((($type_out == 'edit' || $type_out == 'html' || $type_out == 'text' || $type_out == 'tips' || $recursive) && !$show_field_inline)
                        // если редактируем или выводим в шаблон/напоминания, то не вычисляем дополнительные поля, если они не в одну строку
                        || $type_out == 'export') { // а если экспортируем, то по умолчанию вывод доп.полей отключен вообще
                    } else {
                        $d_table = get_table($table_id);
                        $d_fields = get_table_fields($d_table);
                        foreach ($field['links_also_show'] as $key => $also_show) {
                            $d_field = $d_fields[$also_show];
                            if ($show_field_inline and $d_field['type_field'] == 9 and $type_out == "edit") {
                                continue;
                            }
                            if (/*$type_out == 'edit' || $type_out == 'tips' || $type_out == 'html' || */$type_out == 'text' || $type_out == 'export_full') {
                                $add_info .= $show_field_inline ? " " : "\n";
                            } elseif ($show_field_inline) {
                                $span = "<span class='show-field-slave__item--inline'>";
                            } else {
                                $span = "<span class='show-field-slave__item'>";
                            }
                            $count_name_field_str = 0;
                            if ($show_field_name) {
                                //если есть перевод на другой язык, нужно перевести
                                $cur_lang = $config['lang'];
                                $lang_file = $config['site_path'] . '/lang/' . $cur_lang . '_c.php';
                                if (file_exists($lang_file)) {
                                    $file = file($lang_file);
                                    for ($i = 3; $i < (count_cb($file) - 2); $i++) {
                                        $content[] = $file[$i];
                                    }

                                    foreach ($content as $one_str) {
                                        $pattern = "/'(.*)'.*'(.*)'/";
                                        preg_match_all($pattern, $one_str, $match);

                                        //если есть на что заменять, складываем в итоговый массив
                                        if ($match[2][0] && $match[2][0] != '') {
                                            $what_replace_arr[] = $match[1][0];
                                            $to_replace_arr[] = $match[2][0];
                                        }
                                    }
                                }
                                if ($what_replace_arr && $to_replace_arr) {
                                    $d_field["name_field"] = str_replace($what_replace_arr, $to_replace_arr, $d_field["name_field"]);
                                }
                                $space_before_name = $show_field_inline ? " " : "";
                                $count_name_field_str = $show_field_inline ? strlen($space_before_name . $d_field["name_field"] . ": ") : strlen($span . $space_before_name . $d_field["name_field"] . ": ");
                                $add_info .= (!$show_field_inline ? $span : '') . $space_before_name . $d_field["name_field"] . ": ";
                            }
                            $dsp_val = form_display_type($d_field, $link_line, '', 1);

                            if ($dsp_val === false) {
                                $dsp_val = '';
                            }
                            if (/*$type_out == 'edit' || $type_out == 'tips' || $type_out == 'html' || */$type_out == 'text' || $type_out == 'export_full') {
                                $add_info .= $dsp_val;
                            } elseif ($d_field['type_field'] == 9) {
                                $files = $dsp_val ? explode("\r\n", $dsp_val) : array();
                                foreach ($files as $i => $file) {
                                    $sizes = explode('x', $d_field['type_value']);
                                    if ($type_out == 'inline') {
                                        $fileLink = "<img src='cid:" . $d_field['id'] . "_" . $link_line['id'] . "_" . utf2eng($file) . "_ico'>";
                                    } else {
                                        $fileLink = (!file_exists($config["site_path"] . "/cache/" . $d_table['id'] . "_" . $d_field['id'] . "_" . $link_line['id'] . "_" . utf2eng($file) . ".png")) ? $file : "<img src='cache/" . $d_table['id'] . "_" . $d_field['id'] . "_" . $link_line['id'] . "_" . utf2eng($file) . ".png' width='" . $sizes[0] . "' height='" . $sizes[1] . "'>";
                                    }
                                    if ($key == 0 && $i == 0) {
                                        $add_info = substr($add_info, 0, $count_name_field_str * -1);
                                        $display_value = $fileLink . $display_value;
                                    } else {
                                        $add_info .= $span . $fileLink . '</span>';
                                    }
                                }

                                if(count_cb($files) == 0){
                                    $add_info = substr($add_info, 0, $count_name_field_str * -1);
                                }
                            } else {
                                $add_info .= $show_field_inline ? ' ' . $dsp_val : (!$show_field_name ? $span : '') . $dsp_val . ' </span>';
                            }

                            if (isset($mult_display_value, $mult_display_value[$current_value_id])) {
                                if ($show_field_name) {
                                    $mult_display_value[$current_value_id]['additional_field'][] = [
                                        'field_name' => $d_field["name_field"],
                                        'text' => $dsp_val,
                                    ];
                                } elseif (!empty($dsp_val)) {
                                    $mult_display_value[$current_value_id]['additional_field'][] = ['text' => $dsp_val];
                                }
                            }
                        }
                    }

                    if ( ($type_out == "view" || $type_out == "view_sub") and !$recursive and $s_table_field['view_lnk'] and !$field['disable_link']) {
                        global $base64_current_url, $back_url;
                        if ($value != 'array' and $value!= 'new' and $_REQUEST['get_subtable_data']) {
                            $base64_current_url = $back_url;
                        }
                        $input_hidden = "<input type='hidden' class='table-id' value='$table_id'>";
                        $new_value = $input_hidden . "<a class='autocomplete_val' autocomplete-val='" . $value . "' href='view_line" . $config['vlm'] . ".php?table=$table_id&line=$value&back_url=$base64_current_url'" . ($config['open_links_in_new_tab'] ? " target='_blank'" : "") . ">" . $display_value;
                        if ((!$show_field_inline) && ($add_info)) {
                            $sub_fields_style = 'sub-slave_fields';
                            if ($is_mobile) { // Для мобильной версии отображаем поля в столбец всегда
                                $sub_fields_style = 'm__sub-slave_fields';
                            }
                            $new_value = "<input type='hidden' class='table-id' value='$table_id'><div class='" . $sub_fields_style . "'><a class='autocomplete_val' autocomplete-val='" . $value . "' href='view_line" . $config['vlm'] . ".php?table=$table_id&line=$value&back_url=$base64_current_url'" . ($config['open_links_in_new_tab'] ? " target='_blank'" : "") . ">" . $display_value ." </a><span class='show_field_slave'>" . $add_info . "</span></div>";
                        } else {
                            if ($show_field_inline && $add_info) {
                                $new_value = $input_hidden . "<div class='sub-slave_fields inline'><a class='autocomplete_val' autocomplete-val='" . $value . "' href='view_line" . $config['vlm'] . ".php?table=$table_id&line=$value&back_url=$base64_current_url'" . ($config['open_links_in_new_tab'] ? " target='_blank'" : "") . ">" . $display_value . "</a>" . "<span class='show-field-slave__item--inline'>" . $add_info . "</span></span></div>";
                            } else {
                                $new_value .= $add_info . "</span></a>";
                            }
                        }
                    } elseif ( ($type_out == "view" || $type_out == "view_sub") and !$recursive and $s_table_field['view_lnk'] and $field['disable_link']) {
                        $autocomlete_val = "<span class='autocomplete_val' autocomplete-val='" . $value . "'>" . $display_value;
                        $ssstyle = ($display_field['type_field'] == 9) ? "style='width:auto;'" : "";
                        /*if ($show_field_inline) {
                            $new_value = $autocomlete_val;
                        } else {*/
                            $new_value = "<span class='sub-slave_fields' title='" . $field["help"] . "'>" . $autocomlete_val . ' ' . ($add_info ?
                                ($show_field_inline ?
                                    "<span class='show-field-slave__item--inline'>" . $add_info . $sub_slave_fields . "</span>" : "<span class='show-field-slave__item--inline'>" . $add_info . $sub_slave_fields . "</span>") : "") . "</span>";
                        //}
                        $new_value .= $show_field_inline ? "</span></span>" : "</span>";
                    } elseif ($for_subtable && !$old_disable) {
                        $new_value = "<a href='view_line" . $config['vlm'] . ".php?table=$table_id&line=$value&back_url=$base64_current_url'" . ($config['open_links_in_new_tab'] ? " target='_blank'" : "") . ">" . $display_value . "</a>";
                    } else {
                        $new_value = $display_value . ($add_info ? : '');
                    }
                }
                $new_values[] = $new_value;
            }

            if ($field['mult_value'] && !empty($mult_display_value)) {
                return $mult_display_value;
            } else {
                $new_value = implode($type_out == 'text' || $type_out == 'export' || $type_out == 'export_full' ? "\n" : ' <br>', $new_values);
            }
        } else {
            $new_value = $value;
        }
    } elseif ($type == 6)   //тип поля файл
    {
        if ($type_out == "view" || $type_out == "view_tb") {
            $files = $value ? array_filter(explode("\r\n", $value), 'strlen') : array();
            foreach ($files as $i => $file) {
                // Подготовка переменных
                $url_encode_f_name = urlencode($file);
                $disp_f_name = form_display($file);
                $fieldId = $field['id'];
                
                // Уникальный ID
                $unique_id = $fieldId . '_' . $line_id . '_' . $i;

                // Проверка на аудио
                $ext = strtolower(pathinfo(parse_url($file, PHP_URL_PATH) ?? $file, PATHINFO_EXTENSION));
                $isAudio = in_array($ext, ['mp3','wav','aac','m4a','mp4','ogg','oga','webm','flac'], true);

                // Ссылка
                $link_href = "open_file.php?table=" . $field['table_id'] . "&field=" . $fieldId . "&line=" . $line_id . "&file=" . $url_encode_f_name . ($field['show_file'] ? "&show=1" : "");
                $target_attr = ($field['show_file'] ? " target='_blanc'" : "");
                
                // Мобильный JS
                $mobile_js = ($is_mobile) ? " onclick=\"event.stopPropagation(); location.href='" . $link_href . "'; return false\"" : "";

                $rights = test_allow_write($field, $line, "view_edit");
                $can_edit = $field['fast_edit'];

                $cell_html = '';

                // --- HTML ЧАСТЬ ---
                // Используем глобальную переменную dont_open_view=1 в onmousedown
                $stop_attrs = "onmousedown='event.stopPropagation(); if(typeof dont_open_view!==\"undefined\") dont_open_view=1;' onclick='event.stopPropagation();'";

                // Обертка
                if ($can_edit || $isAudio) {
                    $cell_html .= "<span class='file-cell' id='audio_wrap_" . $unique_id . "' " . $stop_attrs . ">";
                }

                // Ссылка на файл
                $cell_html .= "<a class='file-cell__title' href='" . $link_href . "'" . $target_attr . $mobile_js . " " . $stop_attrs . ">" . $disp_f_name . "</a>";

                // Кнопки плеера
                if ($isAudio) {
                    if ($can_edit && $rights) {
                    $stop_mousedown = "onmousedown='event.stopPropagation(); if(typeof dont_open_view!==\"undefined\") dont_open_view=1;'";
                    $file_js = json_encode($file, JSON_UNESCAPED_UNICODE);

                    $cell_html .=
                        "<a id='deleteBtn_" . $unique_id . "' href='javascript:void(0)' " . $stop_mousedown . " " .
                        "onclick='event.stopPropagation(); if(typeof dont_open_view!==\"undefined\") dont_open_view=1; " .
                        "return deleteFile(\"src\",\"" . $fieldId . "\",\"" . $line_id . "\"," . $file_js . ", this);'>" .
                            "<span class='b_drop_hoverpopup_cross' style='cursor:pointer; margin-left:5px;'></span>" .
                        "</a>";
                }

                    $cell_html .= "<span id='playBtn_" . $unique_id . "' class='b_drop_hoverpopup_play' style='cursor:pointer; margin-left:5px;' " . $stop_attrs . "></span>";
                    $cell_html .= "<span id='pauseBtn_" . $unique_id . "' class='b_drop_hoverpopup_pause' style='cursor:pointer; margin-left:5px;' " . $stop_attrs . "></span>";
                }
                
                $stop_mousedown_only = "onmousedown='event.stopPropagation(); if(typeof dont_open_view!==\"undefined\") dont_open_view=1;'";
                // Кнопка удаления
                if (!$isAudio) {
                    if ($can_edit && $rights) {
                        $file_js = json_encode($file, JSON_UNESCAPED_UNICODE);
                        $cell_html .=
                            "<a class='file-cell__btn_delete' " . $stop_mousedown_only . " " .
                            "onclick='event.stopPropagation(); if(typeof dont_open_view!==\"undefined\") dont_open_view=1; " .
                            "return deleteFile(\"src\",\"" . $fieldId . "\",\"" . $line_id . "\"," . $file_js . ", this);'></a>";
                    }
                }

                if ($can_edit || $isAudio) {
                    $cell_html .= "</span>";
                }

                // --- JS ЧАСТЬ ---
                if ($isAudio) {
                    $cell_html .= "<script>";
                    $cell_html .= "(() => {";
                    
                    $cell_html .= "  const block = document.getElementById('audio_wrap_" . $unique_id . "');";
                    $cell_html .= "  if (!block) return;";
                    
                    $cell_html .= "  const playBtn = document.getElementById('playBtn_" . $unique_id . "');";
                    $cell_html .= "  const pauseBtn = document.getElementById('pauseBtn_" . $unique_id . "');";
                    $cell_html .= "  const link = block.querySelector('a.file-cell__title');";
                    
                    $cell_html .= "  if (!playBtn || !pauseBtn || !link) return;";

                    // Ищем или создаем аудио
                    $cell_html .= "  let audio = block.querySelector('audio');";
                    $cell_html .= "  if (!audio) {";
                    $cell_html .= "     audio = document.createElement('audio');";
                    $cell_html .= "     audio.preload = 'none';";
                    $cell_html .= "     block.appendChild(audio);";
                    $cell_html .= "  }";
                    $cell_html .= "  audio.src = link.href;";

                    // Функция полной блокировки всплытия 
                    $cell_html .= "  const stopAll = (e) => {";
                    $cell_html .= "     if(!e) return;";
                    $cell_html .= "     e.preventDefault();";
                    $cell_html .= "     e.stopPropagation();";
                    $cell_html .= "     if (e.stopImmediatePropagation) e.stopImmediatePropagation();";
                    $cell_html .= "     if (typeof dont_open_view !== 'undefined') dont_open_view = 1;";
                    $cell_html .= "  };";

                    // --- DELETE кнопка 
                    $cell_html .= "  const deleteBtn = document.getElementById('deleteBtn_" . $unique_id . "');";
                    $cell_html .= "  if (deleteBtn) {";
                    $cell_html .= "    deleteBtn.addEventListener('mousedown', (e) => { e.stopPropagation(); if(typeof dont_open_view!=='undefined') dont_open_view=1; });";

                    $cell_html .= "    const cleanupAndRemove = () => {";
                    $cell_html .= "      try {";
                    $cell_html .= "        const a = block.querySelector('audio');";
                    $cell_html .= "        if (a) {";
                    $cell_html .= "          a.pause();";
                    $cell_html .= "          a.removeAttribute('src');";
                    $cell_html .= "          a.load();";
                    $cell_html .= "          a.remove();";
                    $cell_html .= "        }";
                    $cell_html .= "      } catch (err) { console.warn('Audio cleanup error:', err); }";
                    $cell_html .= "      if (block && block.parentNode) block.parentNode.removeChild(block);";
                    $cell_html .= "    };";

                    $cell_html .= "    const obs = new MutationObserver(() => {";
                    $cell_html .= "      if (!document.body.contains(deleteBtn)) {";
                    $cell_html .= "        cleanupAndRemove();";
                    $cell_html .= "        obs.disconnect();";
                    $cell_html .= "      }";
                    $cell_html .= "    });";
                    $cell_html .= "    obs.observe(document.body, { childList: true, subtree: true });";
                    $cell_html .= "  }";

                    // Play
                    $cell_html .= "  playBtn.addEventListener('click', (e) => {";
                    $cell_html .= "     stopAll(e);";
                    $cell_html .= "     audio.play().catch(err => console.error('Play error:', err));";
                    $cell_html .= "     playBtn.classList.add('active');";
                    $cell_html .= "     pauseBtn.classList.remove('active');";
                    $cell_html .= "  });";
                    $cell_html .= "  playBtn.addEventListener('mousedown', stopAll);";

                    // Pause
                    $cell_html .= "  pauseBtn.addEventListener('click', (e) => {";
                    $cell_html .= "     stopAll(e);";
                    $cell_html .= "     audio.pause();";
                    $cell_html .= "     pauseBtn.classList.add('active');";
                    $cell_html .= "     playBtn.classList.remove('active');";
                    $cell_html .= "  });";
                    $cell_html .= "  pauseBtn.addEventListener('mousedown', stopAll);";

                    $cell_html .= "  audio.addEventListener('ended', () => {";
                    $cell_html .= "     playBtn.classList.remove('active');";
                    $cell_html .= "     pauseBtn.classList.remove('active');";
                    $cell_html .= "  });";

                    // Защита на контейнере
                    $cell_html .= "  block.addEventListener('click', (e) => e.stopPropagation());";
                    $cell_html .= "  block.addEventListener('mousedown', (e) => { e.stopPropagation(); if(typeof dont_open_view!=='undefined') dont_open_view=1; });";

                    $cell_html .= "})();";
                    $cell_html .= "</script>";
                }

                $files[$i] = $cell_html;
            }
            $new_value = implode("\r\n", $files);
        } else {
            $new_value = $value;
        }
    } elseif ($type == 7 or $type == 11)   //тип поля пользователь
    {
        $value = explode("-", trim($value, "-"));
        global $users_list_cache;
        if (!$users_list_cache) {
            $users_list_cache = array();
            $sqlQuery = "SELECT * FROM " . USERS_TABLE;
            $result = sql_query($sqlQuery);
            while ($row = sql_fetch_assoc($result)) {
                $users_list_cache[] = $row;
            }
        }
        $users = array();
        $temp_users = array();
        foreach ($users_list_cache as $one_user) {
            $temp_users[$one_user['id']] = form_display($one_user['fio']);
        }

        foreach ($value as $one_user) {
            if (isset($temp_users[$one_user])) {
                $users[] = $temp_users[$one_user];
            }
        }
        if (in_array("{current}", $value)) {
            $users[] = $user['fio'];
        }
        if (empty($users) and $field['int_name'] == 'user_id' and !$value[0]) {
            $users[] = $lang['System'];
        }
        if (count_cb($users)) {
            $new_value = implode("\r\n", $users);
        } elseif ($value[0] and ($type_out == "view" or $type_out == "view_tb")) {
            $new_value = "<span style='color:#afafaf'>" . $lang['deleted_u'] . "</span>";
        } elseif ($value[0]) {
            $new_value = $lang['deleted_u'];
        } else {
            $new_value = "";
        }
    } elseif ($type == 9)   //тип поля изображение
    {
        if (($type_out == "view" or $type_out == "view_edit" or $type_out == "view_tb" or $type_out == "html" or $type_out == "inline" or $type_out == "embed" or $type_out == "tips" or $type_out == "pdf") and $line_id != 'null') {
            $files = $value ? explode("\r\n", $value) : array();
            foreach ($files as $i => $file) {

                if (!trim($file)) {
                    unset($files[$i]);
                    continue;
                }
                $commonData = \CB\Core::get(\CB\Core::COMMON_DATA);
                $tableModels = $commonData->getTable($table_id);
                if (!$tableModels) {
                    continue;
                }
                if (!$line_id) {
                    continue;
                }
                $recordObject = $tableModels->getRecord($line_id);
                if (!$recordObject) {
                    continue;
                }
                $curFilesObject = $recordObject->get('f'.$field['id']);
                if (!$curFilesObject) {
                    continue;
                }
                if (!$curFilesObject->setPreview($file)) {
                    $files[$i] = $file . " (" . $lang['f_not_exits'] . ")"; // если изображение не существует то возвращаем надпись
                    continue;
                }

                if ($is_mobile) {
                    if ($type_out == "view" or $type_out == "view_tb") {
                        $files[$i] = "<a class=\"fancybox-item\" data-caption=\"" . urlencode($file) ."\" data-fancybox=\"gallery" . $line_id . "_" . $field['id'] . "\" href='open_file.php?field=" . $field['id'] . "&line=" . $line_id . "&file=" . urlencode($file) . "&show=1'><img src='cache/" . $field['table_id'] . "_" . $field['id'] . "_" . $line_id . "_" . utf2eng($file) . ".png'></a>";
                    }
                } else {
                    if ($type_out == "view" or $type_out == "view_tb" or $type_out == "view_edit") {
                        $rights = test_allow_write($field, $line,"view_edit");
                        if($field["fast_edit"] && $rights){
                            $img_source = $field['table_id'] . '_' . $field['id'] . '_' . $line_id . '_' . utf2eng($file) . '.png';
                            $field_id = $field['id'];

                            $files[$i] = "<span><a class=\"fancybox-item\" data-caption=\"" . urlencode($file) ."\" data-fancybox=\"gallery" . $line_id . "_" . $field['id'] . "\" href='open_file.php?field=" . $field['id'] . "&line=" . $line_id . "&file=" . urlencode($file) . "&show=1'><img src='cache/" . $field['table_id'] . "_" . $field['id'] . "_" . $line_id . "_" . utf2eng($file) . ".png' onmousedown='dont_open_view=1'></a><a class='delete_image_button_x' onClick='(function(el){deleteFile(`$img_source`, `$field_id`, `$line_id`, `$file`, el)})(this)' style='color:red;font-weight:bold;margin-left:10px;display:inline-block;width:30px;height:30px;font-size:15px;text-decoration:none' onmouseover='this.style.fontSize=\"19px\"' onmouseout='this.style.fontSize=\"15px\"'></a></span><br>";
                        } else {
                            $files[$i] = "<span style=\"\"><a class=\"fancybox-item\" data-caption=\"" . urlencode($file) ."\" data-fancybox=\"gallery" . $line_id . "_" . $field['id'] . "\" href='open_file.php?field=" . $field['id'] . "&line=" . $line_id . "&file=" . urlencode($file) . "&show=1'><img src='cache/" . $field['table_id'] . "_" . $field['id'] . "_" . $line_id . "_" . utf2eng($file) . ".png' onmousedown='dont_open_view=1'></a></span>";
                        }
                    }
                }
                if (is_object($recordObject)) {
                    if ($type_out == "tips" || $type_out == "html" || $type_out == "inline" || $type_out == "embed" || $type_out == "pdf") {
                        $files[$i] =  $curFilesObject->createHtmlVisImage($file, $type_out);
                    }
                }
            }
            $new_value = implode(" ", $files);
        } else {
            $new_value = $value;
        }
    } elseif ($type == 13)   //тип поля статус
    {
        if ($value == 0) {
            $new_value = $lang['active'];
        }
        if ($value == 1) {
            $new_value = $lang['archive'];
        }
        if ($value == 2) {
            $new_value = $lang['deleted'];
        }
    } elseif ($type == 14)   //тип поля группа
    {
        $value = explode("-", $value);
        global $groups_list_cache;
        if (!$groups_list_cache) {
            $groups_list_cache = array();
            $sqlQuery = "SELECT * FROM " . GROUPS_TABLE;
            $result = sql_query($sqlQuery);
            while ($row = sql_fetch_assoc($result)) {
                $groups_list_cache[] = $row;
            }
        }
        $groups = array();
        foreach ($groups_list_cache as $row) {
            if (in_array($row['id'], $value)) {
                $groups[] = $row['name'];
            }
        }
        if (in_array("{current_group}", $value)) {
            $groups[] = $group['name'];
        }
        if (count_cb($groups)) {
            $new_value = implode("\r\n", $groups);
        } elseif ($value[0] and ($type_out == "view" or $type_out == "view_tb")) {
            $new_value = "<span style='color:#afafaf'>" . $lang['deleted_g'] . "</span>";
        } elseif ($value[0]) {
            $new_value = $lang['deleted_g'];
        } else {
            $new_value = "";
        }
    } else {
        generate_error("Unknown field type ($type)");
    }

    if (($type_out == "view" or $type_out == "view_tb" or $type_out == "tips") && (!$field['view_html'])) {
        $new_value = str_replace("\n", "<br>", str_replace("\r", "", $new_value));
    }
    if ($type_out == "html" && !$field['view_html']) {
        if ($type == 4){
            $new_value = str_replace("\r\n", ($part_form_template ? "<br>" : ", "), $new_value);
        } else {
            $new_value = str_replace("\r\n", ($part_form_template ? "<br>" : "\n"), $new_value);
        }
    }
    if ($type_out == "export") {
        $new_value = str_replace("\r\n", "\n", $new_value);
    }
    return $new_value;
}

// Режим быстрого редактирования
// $one_field - поле по которому формируется быстрое значение
// $line - строка из б.д.
// $one_value - возвращаемый параметр
// $handler - префикс функции обработчика
// В случае невозможности установки быстрого значения, $one_value не меняется.
function form_fast_edit_value($one_field, $line, & $one_value, $part = "", $subtable_id = 0)
{
    global $tabindex_fast_edit, $lang, $config, $csrf, $user;
    if ($line["id"] == -1) {
        $line["id"] = "_undefined_line_id_";
    }
    $st_id = $one_field["table_id"];
    $sf_id = $one_field["id"];
    $sl_id = $line["id"];
    $sf_idp = $sf_id . "_";
    $field_help = $one_field["help"];
    if ($_COOKIE['is_mobile']) {
        $is_mobile = 1;
    }
    $sf_ids = "_" . $subtable_id;
    $tabindexp1_fast_edit = $tabindex_fast_edit;
    if ($part == "add_link_field") {
        $adds_class = "fast_edit_bordered "; // При добавлении в поле связи - неактивный бордюр виден всегда
        $adds_part = "\r\npart=$part";
    } else {
        $adds_class = "";
    } // Подтаблицы

    $one_field['allow_write'] = test_allow_write($one_field, $line); // Получение прав доступа (с учетом правил)

    if ($one_field["type_field"] == 2 || $one_field["type_field"] == 12) { // ------------- Дата и время ------------
        if ($line["id"] != "_undefined_line_id_") {
            $adds_class = "datepicker " . $adds_class;
        } else {
            $adds_class = "undefined_datepicker_class new_hidden_row" . $adds_class;
        }
        if ($one_field["type_value"]) {
            $input_lenght = 19;
            $adds_class .= ' datetimepicker fast_edit_datetime';
        } else {
            $input_lenght = 10;
        }
        if ($is_mobile) {
            $add_mobile = 'type=date';
        } else {
            $add_mobile = 'type=text';
        }
        $input_value = form_input_type($one_field, $line, $one_field['type_out']);
        if ($input_value !== false) {
            $input_value = $input_value["input"];
            $one_value["value"] = <<<EOD
<input id="fast_edit_span_$sf_idp$sl_id$sf_ids" $add_mobile $adds_part
SIZE=$input_lenght
MAXLENGTH=$input_lenght
class='fast_edit_span_$sf_idp$sl_id $adds_class fast_edit_datepicker not-init'
tabindex="$tabindex_fast_edit"
value='$input_value'
cur_value='$input_value'
field_id="$sf_id"
line_id="$sl_id"
subtable_id="$subtable_id"
onfocus="initMaskFromDateTimepicker();"
onchange="const tempValue = $('#fast_edit_span_$sf_idp$sl_id$sf_ids').val(); $('.fast_edit_span_$sf_idp$sl_id').val(tempValue);"
onkeypress="saveNewValueByEnterBtn(this, event);"
title="$field_help"
>
EOD;
        }
        $one_value["fast_edit_div"] = "<span class='datepicker_span'>";
        $one_value["fast_edit_div_close"] = "</span>";
    } elseif ($one_field["type_field"] == 1 || $one_field["type_field"] == 8 || $one_field["type_field"] == 10 || $one_field["type_field"] == 3) {
        // -------------- Обычный текст --------------
        if ($one_field['mult_value']) {
            $mult_value = 1;
        } else {
            $mult_value = 0;
        }

        //что бы корректно отображалось поле типа текст, многострочный, если оно 1 в подтаблице
        if (!$one_field['width'] && $one_field['type_field'] == 3 && $mult_value == 1) {
            $adds_style = "min-width:140px;border-radius:4px;";
        } else {
            if ($one_field['width']) {
                if ($one_field['prefix'] || $one_field['postfix']) {
                    if ($one_field['width'] - 100 > 50) {
                        $finalWidth = $one_field['width'] - 100;
                        $adds_style = "width:" . ($finalWidth > $config['table_other_max_width'] ? $config['table_other_max_width'] - 100 : $finalWidth) . "px;";
                    } else {
                        $totalWidth = $one_field['width'] - 15;
                        $adds_style = "width:" . ($totalWidth > $config['table_other_max_width'] ? $config['table_other_max_width'] - 15 : $totalWidth) . "px;";
                    }
                } else {
                    $totalWidthWithoutPp = $one_field['width'] - 15;
                    $adds_style = "width:" . ($totalWidthWithoutPp > $config['table_other_max_width'] ? $config['table_other_max_width'] - 15 : $totalWidthWithoutPp) . "px;";
                }
            }
        }

        $placeholder = ($one_field["type_field"] == 3) ? $one_field['placeholder'] : '';

        $cur_value = $one_value["value"];
        $one_value["fast_edit_div"] = <<<EOD
<span tabindex="$tabindex_fast_edit" onfocus="var t=this.nextSibling; t.contentEditable=true; t.focus();"></span><div $adds_part
id="fast_edit_span_$sf_idp$sl_id$sf_ids"
tabindex="$tabindexp1_fast_edit"
contentEditable=false
class="fast_edit_span_$sf_idp$sl_id $adds_class fast_edit_text not-init" $adds_style
field_id="$sf_id"
line_id="$sl_id"
cur_value="$cur_value"
mult_value="$mult_value"
subtable_id="$subtable_id"
>
EOD;
        $one_value["fast_edit_div_full_value"] = $one_value["fast_edit_div"];
        $one_value["fast_edit_div_close"] = "";
        $input_value = form_input_type($one_field, $line, $one_field['type_out']);
        if ($one_value["value"] === 0 || $one_value["value"] === '' || (!isset($one_value["value"]) && $part == "add_link_field")) {
            $one_value["value"] = $input_value['value'];
        }

        if ($part != "add_link_field") {
            if ($one_field["type_field"] != 3) {
                $align = "text-align:right;";
            }
            if ($one_field["type_field"] == 1) {
                $align_wrap = "white-space:nowrap;";
                $align = "text-align:right;";
            }
            if ($mult_value) {
                if (strpos($one_field['type_value'], '{view_html}') === false) {
                    $textarea_height = 'height:15px;';
                }
            }

            if($one_field['type_field'] == 3){
                $box = "box-sizing: border-box;";
            }
            else if($one_field['type_field'] == 1) {
                $box = "box-sizing: content-box;";
            }
            $bord = 'style="border:0px;padding-right:11px; outline:none;' . $box . $adds_style . $align . $textarea_height . '"';
            $one_value["fast_edit_div_close"] = "";
        }

        if ($mult_value) {
            if (strpos($one_field['type_value'], '{view_html}') !== false && $part != "add_link_field") {
                $text_html_field = str_replace(array('<p>', '</p>'), '', $one_value["value"]);
                $one_value["fast_edit_div"] = '<div class="fast_edit_span_' . $sf_idp . $sl_id . ' fast_edit_text html-editor-div not-init" id="edit_html_value_' . $sf_idp . $sl_id . $sf_ids . '" field_id="' . $sf_id . '" line_id="' . $sl_id . '" placeholder="' . $placeholder . '" onclick="get_edit_html_value(\'' . $sf_idp . $sl_id . $sf_ids . '\');">' . $text_html_field . '</div>';
            } else {
                if ($part == "add_link_field" && !$is_mobile) {
                    $bord = 'style="border: 1px dotted #a0a0a0;min-height:17px; outline:none; background: #fff;padding:0px;' . $adds_style . $align . '"';
                    $multi_text_class = "add_link_part__textarea-mult";
                }

                if ($one_field['view_edit'] == 1 || $one_field['view_add'] == 1 || $one_field['allow_write'] == 1) { // Если есть права на редактирование или отсутствуют на редактирование, но присутствуют на добавление
                    $one_value["fast_edit_div"] = '<textarea rows="1"' . $adds_part .
                                                  ' id="fast_edit_span_' . $sf_idp . $sl_id . $sf_ids .
                                                  '" field_id="' . $sf_id . '" line_id="' . $sl_id .
                                                  '" cur_value="' . $one_value["value"] .
                                                  '" mult_value="' . $mult_value .
                                                  '" placeholder="' . $placeholder .
                                                  '" subtable_id="' . $subtable_id .
                                                  '" ' . $bord . ' class="fast_edit_span_' . $sf_idp . $sl_id .
                                                  ' fast_edit_text not-init ' .$multi_text_class.
                                                  '" read_right="1" title="' . htmlspecialchars($field_help) . '">' . $one_value["value"] . '</textarea>';
                } else { // Если нет прав на редактирование
                    $one_value["fast_edit_div"] = '';
                    $one_value["def_value"] = $one_value["value"];
                    $one_value["fast_edit_div_close"] = '';
                }
            }
        } else {
            if (strpos($one_field['type_value'], '{hyperlink}') !== false && $part != "add_link_field") {
                if ($subtable_id <> 0) {
                    $sites = explode(', ', str_replace('; ', ', ', $one_value['value']));
                    $links = [];
                    foreach ($sites as $one_site) {
                        $links[] = form_hyperlink($one_site);
                    }
                    $one_value['value'] = implode(', ', $links);
                    $one_value["fast_edit_div"] = '<div class="fast_edit_span_' . $sf_idp . $sl_id . ' fast_edit_text not-init fast_edit_text--hyperlink" id="edit_hyper_value_' . $sf_idp . $sl_id . $sf_ids . '" field_id="' . $sf_id . '" line_id="' . $sl_id . '" placeholder="' . $placeholder . '" onclick="get_edit_hyper_value(\'' . $sf_idp . $sl_id . $sf_ids . '\');" style="' . $adds_style . '">' . $one_value['value'] . '</div>';
                } else {
                    if ($part != "add_link_field") {
                        $type_text = "type='text'";
                    }
                    $one_value["fast_edit_div"] = '<input ' . $type_text . ' ' . $adds_part . ' value="' . htmlspecialchars($one_value["value"]) . '" id="fast_edit_span_' . $sf_idp . $sl_id . $sf_ids . '" field_id="' . $sf_id . '" line_id="' . $sl_id . '" cur_value="' . htmlspecialchars($one_value["value"]) . '" mult_value="' . $mult_value . '" placeholder="' . $placeholder . '" subtable_id="' . $subtable_id . '" ' . $bord . ' class="fast_edit_span_' . $sf_idp . $sl_id . ' fast_edit_text not-init ' . $adds_class . '" title="' . $field_help . '"/>';
                }

            } elseif (strpos($one_field['type_value'], '{view_html}') !== false && $part != "add_link_field") {
                $one_value["fast_edit_div"] = '<div class="fast_edit_span_' . $sf_idp . $sl_id . ' fast_edit_text not-init" id="edit_html_input_value_' . $sf_idp . $sl_id . $sf_ids . '" field_id="' . $sf_id . '" line_id="' . $sl_id . '" cur_value="' . $one_value["value"] . '" placeholder="' . $placeholder . '" onclick="get_edit_html_input_value(\'' . $sf_idp . $sl_id . $sf_ids . '\');">' . $one_value["value"] . '</div>';
            }
            else {
                if ($part != "add_link_field") {
                    $type_text = "type='text'";
                }
                if ($one_field['view_edit'] == 1 || $one_field['view_add'] == 1 || $one_field['allow_write'] == 1) { // Если есть права на редактирование или отсутствуют на редактирование, но присутствуют на добавление
                    $one_value["fast_edit_div"] = '<input ' . $type_text . ' ' . $adds_part . '
                    value="' . $one_value["value"] . '" cur_value="' . $one_value["value"] . '"
                    id="fast_edit_span_' . $sf_idp . $sl_id . $sf_ids . '" field_id="' . $sf_id . '" line_id="' . $sl_id . '"
                    mult_value="' . $mult_value . '" placeholder="' . $placeholder . '" subtable_id="' . $subtable_id . '" ' . $bord . '
                    class="fast_edit_span_' . $sf_idp . $sl_id . ' fast_edit_text not-init ' . $adds_class . ' hidden-input"
                    style="box-sizing: content-box;" read_right="1" title="' . htmlspecialchars($field_help) . '"';
                    if (!$is_mobile) {
                        $one_value["fast_edit_div"] .= 'onkeypress="saveNewValueByEnterBtn(this, event);"/>';
                    } else {
                        $one_value["fast_edit_div"] .= '/>';
                    }
                } else { // Если нет прав на редактирование
                    $one_value["fast_edit_div"] = '';
                    $one_value["def_value"] = $one_value["value"];
                    $one_value["fast_edit_div_close"] = '';
                }
            }
        }

        $one_value["fast_edit_div_full_value"] = "";

        if ($part != "add_link_field") {
            $one_value["value"] = "";
        }
    }

    // --------------  Список и пользователь --------------
    if (in_array($one_field["type_field"], [4, 7, 13, 14])) {
        if ($one_field['width'] && $part != "add_link_field") {
            $adds_style = "\nstyle='width:" . $one_field['width'] . "px;'";
        }
        $one_field['form_fast_edit_flag'] = 1;
        $input_value = form_input_type($one_field, $line, $one_field['type_out']);
        if ($input_value !== false) {
            $mult_val_check_preview = $input_value["mult_val_check_preview"];
            $input_value = $input_value["input"];
            if (($one_field["mult_value"])) {  // множественное значение представляется как множество селектов
                if ($is_mobile) {
                    $one_value["fast_edit_div"] = $mult_val_check_preview . '
                        <input type="hidden" name="edit[new][' . str_replace("_","", $sf_idp) . ']" value="1">
                        <input type="hidden" id="value' . str_replace("_","", $sf_idp) . '" value="' . $line[$one_field["int_name"]] . '">
                        <div class="type_4_mult_val-row">
                            <input type="checkbox" id="view_all_' . $one_field["id"] . '"
                                    class="user-data__multi-checkbox type_4_mult_val--all"
                                    style="width:auto"
                                    onchange="type_4_mult_val_check_all(this);" value="">
                            <label for="view_all_' . $one_field["id"] . '"
                                    class="user-data__multi-label">' . $lang['All'] . '</label>
                        </div>
                        <div style="border-top: 1px solid gray;"></div>';
                } else {
                    $one_value["fast_edit_div"] = $mult_val_check_preview . '
                    <button type="button" class="user-data__close-edit-btn edit-mult-value-btn" id="close-edit-button' . $one_field["id"]. '" field_id="' . $one_field["id"]. '" style="display: none;" onclick="mult_value_preview(this);this.style.display=`none`;this.nextElementSibling.style.display=`block`;this.nextElementSibling.nextElementSibling.style.display=`none`;this.previousElementSibling.style.display=`block`;"></button>
                    <button class="user-data__edit-btn" id="edit-button' . $one_field["id"] . '" field_id="' . $one_field["id"]. '" type="button" onclick="this.style.display=`none`;this.nextElementSibling.style.display=`block`;this.previousElementSibling.previousElementSibling.style.display=`none`;this.previousElementSibling.style.display=`block`;"></button>
                    <div class="user-data__user-fields user-data__user-fields--view" id="edit-multi' . $one_field["id"] . '">
                        <input type="hidden" field_type="'.$one_field["type_field"].'" field_id="' . $sf_idp . '" line_id="' . $sl_id . '" class="type_4_mult" id="fast_edit_span_' . $sf_idp . $sl_id . $sf_ids . '" value="' . $line[$one_field["int_name"]] . '">
                        <div class="type_4_mult_val-row">
                            <input type="checkbox" id="view_all_' . $one_field["id"] . '"
                                    class="user-data__multi-checkbox type_4_mult_val--all"
                                    style="width:auto"
                                    onchange="type_4_mult_val_check_all(this);" value="">
                            <label for="view_all_' . $one_field["id"] . '"
                                    class="user-data__multi-label">' . $lang['All'] . '</label>
                        </div>
                        <div style="border-top: 1px solid gray;"></div>';
                }

                $one_value["fast_edit_div_full_value"] = "";
                $one_value["fast_edit_div_close"] = "";
                $one_value["value"] = "";
                $onload_script = "";
                if ($part == "add_link_field") {
                    $adds_class = "add_link_field nwidth ";
                } // Неизвестная ширина - объект при создании скрыт
                else {
                    $adds_class = "";
                }
                if ($line["id"] != "_undefined_line_id_") {
                    $adds_class .= "fast_edit_select";
                } else {
                    $adds_class .= "undefined_fast_edit_select";
                }
                foreach ($input_value['set'] as $pos => $one_set) {   // один селект
                    $one_value["value"] .= "<div>$one_set</div>";
                }
            } else { // Одинарный селект
                if ($part == "add_link_field") {
                    $adds_class = "add_link_field nwidth ";
                } // Неизвестная ширина - объект при создании скрыт
                else {
                    $adds_class = "";
                }
                if ($line["id"] != "_undefined_line_id_") {
                    $adds_class .= "fast_edit_select";
                } else {
                    $adds_class .= "undefined_fast_edit_select";
                }
                if ($is_mobile) {
                    $mobile_name = 'name="field[' . $one_field['id'] . ']"';
                } else {
                    $mobile_name = '';
                }
                $user_select = "";
                if ($one_field["type_field"] != 4) {
                    $user_select = "fast_edit_span--users";
                }
                $one_value["fast_edit_div"] = <<<EOD
<select id='fast_edit_span_$sf_idp$sl_id$sf_ids' $adds_part
$mobile_name
tabindex="$tabindex_fast_edit"
field_id="$sf_id"
line_id="$sl_id"
subtable_id="$subtable_id"
class="fast_edit_span_$sf_idp$sl_id $adds_class sub_fast_edit_select sub_fast_edit_select--select not-init $user_select" $adds_style title="$field_help"
>
EOD;
                $one_value["value"] = $input_value;
                $one_value["fast_edit_div_full_value"] = $one_value["fast_edit_div"];
                $one_value["fast_edit_div_close"] = "</select>";
            }
        }
    } elseif ($one_field["type_field"] == 5) { // Поле связь
        $ta = explode("|", $one_field["type_value"]);
        list ($lnk_table_id, $lnk_field_id, $lnk_filter_id, $lnk_show_field_name, $lnk_show_field_inline) = $ta;

        if ($part == "add_link_field") {
            $adds_class = "fast_edit_link not-init_input fast_edit_bordered fast_add_link_field";
        } else {
            $adds_class = "sub_edit_link_input";
        }
        // Смотрим на какое поле ссылается поле связь
        $ln_id = (is_array($line[$one_field["int_name"]]) && $line[$one_field["int_name"]]['raw']) ? $line[$one_field["int_name"]]['raw'] : $line[$one_field["int_name"]];
        $one_value["fast_edit_div"] = ""; // "<a href='view_line" . $config["vlm"] . ".php?table=" . $lnk_table_id . "&line=$ln_id' style='display: flex; align-items: center;' onclick='if (!event.ctrlKey) return false;' class='fast_edit_link not-init'>";
        $ex_style = "";
        $field_width = 280;
        if ($one_field["width"]) {
            $field_width = $one_field["width"];
            $ex_style = "style='width: " . $field_width . "px'";
        };
        if (is_array($line[$one_field["int_name"]])) {
            $f_value = $line[$one_field["int_name"]]['raw'];
        } else {
            $f_value = $line[$one_field["int_name"]];
        }
        $filter_field = "";
        if ($part == "add_link_field" && $lnk_filter_id) {
            $filter_field = "filter_field=\"" . str_replace("-", "", $lnk_filter_id) . "\" ";
        }
        if ($one_field["links_also_show"] && $one_field["s_show_field_inline"]) {
            $display_edit = form_display_type($one_field, $line, "view_tb");
            if (!is_array($display_edit)) {
                $display_edit = form_display(htmlspecialchars_decode(strip_tags($display_edit)));
            }
        } else {
            $display_edit = form_display(form_display_type($one_field, $line, "text"));
        }
        $disable_link = $one_field["disable_link"];
        $is_inline = explode("|", $one_field["type_value"])[4];
        $ac_link = "view_line" . $config["vlm"] . ".php?table=" . $lnk_table_id . "&line=" . $ln_id;
        $one_value["disable_link"] = $disable_link;
        $one_value["ac_link"] = $ac_link;
        $one_value["display"] = $display_edit;
        $one_value["value"] = <<<EOD
<select $adds_part
class="fast_edit_span_$sf_idp$sl_id $adds_class combobox combobox--hidden not-init"
tabindex="$tabindex_fast_edit"
type="text"
id="fast_edit_span_$sf_idp$sl_id$sf_ids"
ac_value="$display_edit"
ac_link_val="$f_value"
field_id="$sf_id"
line_id="$sl_id"
disable_link="$disable_link"
type_field="5"
subtable_id="$subtable_id"
inline="$is_inline"
link="$ac_link"
link_table="$lnk_table_id"
$filter_field
field_width="$field_width"
$ex_style
></select>
EOD;
        $one_value["fast_edit_div_full_value"] = $one_value["fast_edit_div"];
        $one_value["fast_edit_div_close"] = ""; // "</a>";
    } elseif ($one_field["type_field"] == 6) { // ФАЙЛ
        // поле не похожее на другие, обработка не вызывает form_input_type
        if ($one_field["width"]) {
            $field_width = $one_field["width"];
            $ex_style = "width: " . $field_width . "px;";
        }
        $one_value["fast_edit_div"] = <<<EOD
<div $adds_part
id='fast_edit_span_$sf_idp$sl_id$sf_ids'
class="fast_edit_span_$sf_idp$sl_id sub_fast_edit_file not-init"
style="min-width: 75px;word-wrap: break-word;$ex_style"
>
EOD;

        $value = $line["f" . $one_field['id']];
        $files = $value ? explode("\r\n", $value) : array();
        $files_count = count_cb($files);
        $requred = $one_field["main"];
        $one_value["value"] = "";
        $onload_script = "";
        if($one_field['max_size']>1000){ $one_field['max_size'] = round($one_field['max_size']/1024, 0) . " MB";}
        else{
            if($one_field['max_size']>0){
                $one_field['max_size'] = $one_field['max_size'] . " kB";
            }
            else{
                $one_field['max_size'] = "";
            }
        }
        if ($one_value['allow_write'] == 1) {
            foreach($files as $name){
                if (strstr($name, 'mp3') || strstr($name, 'wav')) {
                    $drop_hoverpopup = '
                    <span class="b_drop_hoverpopup" title="' . $lang['Delete'] . '"></span>
                    <span class="b_drop_hoverpopup" title="' . $lang['Delete'] . '"></span>
                    <span class="b_drop_hoverpopup" title="' . $lang['Delete'] . '"></span>
                    ';
                } else {
                    $drop_hoverpopup = '<span class="b_drop_hoverpopup" title="' . $lang['Delete'] . '">hi</span>';
                }
            }
        } else {
            $drop_hoverpopup = '';
        }


        $show_file = '';
        $target = '';
        if ($one_field['show_file'] == '1') {
            $show_file = '&show=1';
            $target = 'target="_blank"';
        }

        foreach ($files as $pos => $file) {
            $url_encode_f_name = urlencode($file);
            $disp_f_name = form_display($file);
            $ext = strtolower(pathinfo(parse_url($file, PHP_URL_PATH) ?? $file, PATHINFO_EXTENSION));
            $isAudio = in_array($ext, ['mp3','wav','aac','m4a','mp4','ogg','oga','webm','flac'], true);

            $wrapId = 'audio_wrap_' . $sf_id . '_' . $sl_id . '_' . $subtable_id . '_' . $pos;

            $drop_hoverpopup = '';
             if ($isAudio) {
                    $drop_hoverpopup = '
                        <span class="b_drop_hoverpopup_cross ancor" onclick="ondrop_file(event);" title="' . $lang['Delete'] . '" main_line></span>
                        <span class="b_drop_hoverpopup_play js-audio-play"></span>
                        <span class="b_drop_hoverpopup_pause js-audio-pause"></span>
                    ';
                } else {
                    $drop_hoverpopup = '<span class="b_drop_hoverpopup" title="' . $lang['Delete'] . '"></span>';
                }
            $one_value["value"] .= <<<EOD
<div id="$wrapId" class="whitespace_nowrap fast_edit_span_$sf_idp$sl_id$pos"><a $adds_part
href='open_file.php?field=$sf_id&line=$sl_id&file=$url_encode_f_name$show_file' $target
id='fast_edit_span_$sf_idp$sl_id$sf_ids$pos'
field_id="$sf_id"
line_id="$sl_id"
subtable_id="$subtable_id"
class="file_link"
title="$disp_f_name"
>$disp_f_name</a>$drop_hoverpopup</div>
<script>
(function(){
  const block = document.getElementById('$wrapId');
  if (!block) return;

  const playBtn  = block.querySelector('.js-audio-play');
  const pauseBtn = block.querySelector('.js-audio-pause');
  const link = block.querySelector('a.file_link');
  if (!playBtn || !pauseBtn || !link) return;

  let audio = block.querySelector('audio');
  if (!audio) {
    audio = document.createElement('audio');
    audio.preload = 'none';
    block.appendChild(audio);
  }
  audio.src = link.href;

  playBtn.addEventListener('click', () => {
    audio.play().catch(e => console.log('Play error:', e));
    playBtn.classList.add('active');
    pauseBtn.classList.remove('active');
  });

  pauseBtn.addEventListener('click', () => {
    audio.pause();
    pauseBtn.classList.add('active');
    playBtn.classList.remove('active');
  });

  audio.addEventListener('ended', () => {
    playBtn.classList.remove('active');
    pauseBtn.classList.remove('active');
  });
})();
</script>
EOD;
        }
        $one_value["fast_edit_div_full_value"] = $one_value["fast_edit_div"];
        $lng_s = $lang['file_wasnt_upload'];
        $lng_add = $lang['Add'];
        if ($one_value['allow_write']) {
            if ($part == "add_link_field") {
                $one_value["fast_edit_div_close"] = <<<EOD
</div>
<div class="sub_fast_edit_file_url add_file_url_$sf_idp$sl_id" id='add_file_url_$sf_idp$sl_id$sf_ids' style="position: relative;">
<div class="sub_fast_edit_file_form">
<div>
<input type=file name="lnk_add_file[]" size=1 $adds_part
onclick ='if (upload_in_progress) {alert("$lng_s");return false;}'
onchange='sub_add_file($sf_id,$sl_id,this);'
tabindex='$tabindex_fast_edit' multiple="multiple">
</div>
</div>
<div class="sub_fast_edit_file_form_text">
$lng_add
</div>
</div>
EOD;
            } else {
                $one_value["fast_edit_div_close"] = <<<EOD
</div>
</form>
<input type='hidden' id="sub_files_count_$sf_idp$sl_id" value="$files_count" required_field="$requred">
<div class="sub_fast_edit_file_url add_file_url_$sf_idp$sl_id$sf_ids" id='add_file_url_$sf_idp$sl_id$sf_ids' style="position: relative;">
<div class="sub_fast_edit_file_form">
<form
method=post
enctype="multipart/form-data"
action="update_value.php?field=$sf_id&line=$sl_id"
id='sbmt_file_$sf_idp$sl_id$sf_ids'
target='frame_upload'>
<input type=hidden name=csrf value='$csrf'><input type=hidden name=field value='$sf_id'><input type=hidden name=line value='$sl_id'>
<input type=hidden name=subtable_page value='' id='subtable_page$sf_idp$sl_id$sf_ids'>
<input type=hidden name=rel_field value='' id='rel_field$sf_idp$sl_id$sf_ids'>
<div class='sub_fast_edit_file_form2'>
<input type=file name="add_file[]" size=1 $adds_part
onclick ='if (upload_in_progress) {alert("$lng_s");return false;}'
onchange='sub_add_file($sf_id,$sl_id,this);'
tabindex='$tabindex_fast_edit' multiple="multiple">
</div>
</form>
</div>
<div class="sub_fast_edit_file_form_text">
$lng_add
<span class="sub_fast_edit_file_form_text_file_max_size">$one_field[max_size]</span>
</div>
</div>
<script>$onload_script</script>
<form autocomplete="off"></form>
EOD;
            }
        }
    } elseif ($one_field["type_field"] == 9) { // Изображение
        $one_value['fast_edit_div'] = "<div
            $adds_part
            id='fast_edit_span_{$sf_idp}{$sl_id}{$sf_ids}'
            class='fast_edit_span_{$sf_idp}{$sl_id} sub_fast_edit_file not-init'
            ". (
                $sl_id == '_undefined_line_id_' ? 'link-needs-to-be-updated="need"' : ''
            ) ."
        >";

        $value = $line["f" . $one_field['id']];
        $files = $value ? explode("\r\n", $value) : array();
        $files_count = count_cb($files);
        $requred = $one_field["main"];
        $one_value["value"] = "";
        $onload_script = "";

        if ($one_value['allow_write'] == 1) {
            $drop_hoverpopup = '<span class="b_drop_hoverpopup" title="' . $lang['Delete'] . '"></span>';
        } else {
            $drop_hoverpopup = '';
        }

        foreach ($files as $pos => $file) {
            if (!trim($file)) {
                    continue;
            }
            $url_encode_f_name = urlencode($file);
            $commonData = \CB\Core::get(\CB\Core::COMMON_DATA);
            $tableModels = $commonData->getTable($st_id);

            if (!$tableModels) {
                continue;
            }
            if (!$sl_id) {
                continue;
            }
            $recordObject = $tableModels->getRecord($sl_id);
            if (!$recordObject) {
                continue;
            }
            $curFilesObject = $recordObject->get('f'.$sf_id);
            if (!$curFilesObject) {
                continue;
            }
            $disp_f_name = form_display($file);
            $disp_img = form_display($file);
            if (!$curFilesObject->exists($file)) {
                $disp_img = $disp_f_name . " (" . $lang['f_not_exits'] . ")"; // если изображение не существует то возвращаем надпись
                continue;
            }
            $curFilesObject->setPreview($file);
            $utf2eng_f_name = utf2eng($file);
            $disp_img = "<img src='cache/" . $st_id . "_" . $sf_id . "_" . $sl_id . "_" . $utf2eng_f_name . ".png' class='sub_fast_edit_img'>";
            $space_delimiter = " ";
            // !!!!!!!!!!!!!!!!!!!!!!!!!!!! - Патч на ie, т.к. не воспринимает white-space:nowrap !!!!!!!!!!!!!!!!!!!!!!!!!!!!
            if (strpos($_SERVER["HTTP_USER_AGENT"], "MSIE 8.0")) {
                $space_delimiter = "<span class='white-small'>. .</span>";
            }

            $one_value["value"] .= <<<EOD
<span class='whitespace_nowrap fast_edit_span_$sf_idp$sl_id$pos not-init'><a $adds_part
href='open_file.php?field=$sf_id&line=$sl_id&file=$url_encode_f_name&show=1'
data-fancybox="gallery$sl_id"
id='fast_edit_span_$sf_idp$sl_id$sf_ids$pos'
field_id="$sf_id"
line_id="$sl_id"
subtable_id="$subtable_id"
title="$disp_f_name"
file_img=1
class="file_link"
>$disp_img</a>$drop_hoverpopup</span>$space_delimiter
EOD;
        }
        $one_value["fast_edit_div_full_value"] = $one_value["fast_edit_div"];
        $lng_s = $lang['file_wasnt_upload'];
        $lng_add = $lang['Add'];
        if($one_field['max_size']>1000){ $one_field['max_size'] = round($one_field['max_size']/1024, 0) . " MB";}
        else{
            if($one_field['max_size']>0){
                $one_field['max_size'] = $one_field['max_size'] . " kB";
            }
            else{
                $one_field['max_size'] = "";
            }
        }
        
            $one_value["fast_edit_div_close"] = <<<EOD
</div>
</form>
<input type='hidden' id="sub_files_count_$sf_idp$sl_id" value="$files_count" required_field="$requred">
<div class="sub_fast_edit_file_url add_file_url_$sf_idp$sl_id$sf_ids" id='add_file_url_$sf_idp$sl_id$sf_ids'>
<div class="sub_fast_edit_file_form">
<form
method=post
enctype="multipart/form-data"
action="update_value.php?field=$sf_id&line=$sl_id"
id='sbmt_file_$sf_idp$sl_id$sf_ids'
target='frame_upload'>
<div>
<input type=hidden name=csrf value='$csrf'><input type=hidden name=field value='$sf_id'><input type=hidden name=line value='$sl_id'>
<input type=hidden name=subtable_page value='' id='subtable_page$sf_idp$sl_id$sf_ids'>
<input type=hidden name=rel_field value='' id='rel_field$sf_idp$sl_id$sf_ids'>
<input type=file name="add_file[]" size=1 $adds_part
onclick ='if (upload_in_progress) {alert("$lng_s");return false;}'
onchange='sub_add_file($sf_id,$sl_id,this);'
file_img=1 accept='image/*'
tabindex='$tabindex_fast_edit' multiple="multiple">
</div>
</form>
</div>
<div class="sub_fast_edit_file_form_text">
$lng_add
<span class="sub_fast_edit_file_form_text_file_max_size">$one_field[max_size]</span>
</div>
</div>
<form autocomplete="off"></form>
EOD;
        }
    }


// тест на доступ к записи в строку
// возвращает 0 - если запись запрещена
// 1 - если разрешена
// 2 - если запись разешена, но текст не видно
function test_allow_write($field, $line, $type_out = '', $lnk_tbl = 0)
{
    global $user, $lang;
    if ($user['is_root']) {
        return 1;
    }

    // Тест можно ли запись читать
    $allow_read = test_allow_read($field, $line);

    // Разрешенные режимы вывода
    $allowed_type_out = array('view_edit' => 'view_edit', 'view_add' => 'view_add', 'write' => 'write');
    $type_out = $allowed_type_out[$type_out];

    $table_id = $field['table_id'];
    $table = get_table($table_id);

    $disallow_mask = array();
    foreach ($table['rules_reverse'] as $one_rule) {
        if (!isset($one_rule['rights'][$field['id']])) {
            continue;
        }
        foreach ($one_rule['rights'][$field['id']] as $one_right) {
            if ($one_right['field'] == $field['id'] && (
                    ($type_out && isset($one_right[$type_out])) ||
                    (!$type_out && (isset($one_right['view_edit']) || isset($one_right['view_add']) || isset($one_right['write'])))
                )) {  // Есть правило на данное поле
                if (eval_php_condition($line, $one_rule['condition_php'])) {  // Условие срабатывает, возвращаем права
                    if (!$type_out) { // Разрешение записи редактирования / добавления / импорта
                        if (($one_right['view_edit'] || $one_right['view_add'] || $one_right['write']) and !$lnk_tbl or ($lnk_tbl and $one_right['write'])) {
                            if (!$allow_read) {
                                return 2;
                            } else {
                                return 1;
                            }
                        } else { // Необходимо чтобы все маски были запрещены
                            if ($disallow_mask['view_edit'] && $disallow_mask['view_add'] && $disallow_mask['write']) {
                                return 0;
                            } else {
                                if ($one_right['view_edit']) {
                                    $disallow_mask['view_edit'] = 1;
                                }
                                if ($one_right['view_add']) {
                                    $disallow_mask['view_add'] = 1;
                                }
                                if ($one_right['write']) {
                                    $disallow_mask['write'] = 1;
                                }
                            }
                        }

                    } else {
                        if (isset($one_right[$type_out])) {
                            if ($one_right[$type_out]) {
                                if (!$allow_read) {
                                    return 2;
                                } else {
                                    return 1;
                                }
                            } else {
                                return 0;
                            }
                            return $one_right[$type_out] ? 1 : 0;
                        }
                    }
                }
                if (!$line['id']) {
                    if (!$type_out) {
                        if (($one_right['view_edit'] || $one_right['view_add'] || $one_right['write']) and !$lnk_tbl or ($lnk_tbl and $one_right['write'])) {
                            return 1;
                        }
                    }
                }
            }
        }
    }

    // Правил на поле нет, срабатывает дефолт
    if (!$type_out) {
        if (($field['view_edit'] || $field['view_add'] || $field['write']) and !$lnk_tbl or ($lnk_tbl and $field['write'])) {
            if (!$allow_read) {
                return 2;
            } else {
                return 1;
            }
        } else {
            return 0;
        }
    } else {
        if ($field[$type_out] && !$allow_read) {
            return 2;
        } // Запись разрешена, но запрещено чтение
        else {
            return $field[$type_out] ? 1 : 0;
        }
    }
}

// сформировать значение при редактировании
function form_input_type($field, $line, $type_out = 'view_edit')   //при вводе данных
{
    global $config, $user, $lang, $table, $ses_id, $crypt_key, $crypt_value;
    $line_id = $line['id'];
    $value = is_array($line) ? $line[$field['int_name']] : $line;

    if ($_COOKIE['is_mobile']) {
        $is_mobile = 1;
    }

    $type = $field['type_field'];
    $type_value = $field['type_value'];

    if ($type_out == 'view_edit') {
        if (!test_allow_read($field, $line)) {
            $value = $lang['No_access'];
        }
    } else {
        $test_write = test_allow_write($field, $line, $type_out);
        if ($test_write === 0 && $type_out !== 'subtable_user') {
            return false;
        } elseif ($test_write === 2) {
            $value = '';
        }
    }

    if ($type == 1 or $type == 10)  //тип поля число
    {
        if (($field['autonumber'] or $type == 10) and (($type_out === "view_add" and $table['auto_save'] != 1) or $type_out === "write")) {
            $value = "{" . $lang['autonumber'] . "}";
        } else {
            $value = form_local_number($value, $field['dec_dig']);
        }
        $new_value['input'] = $value;
        $new_value['value'] = $value;
    } elseif ($type == 2 or $type == 12)  //тип поля дата
    {
        $value = (substr($value, 0, 1) == "{") ? $value : form_local_time($value, $type_value, 0);

        if ($is_mobile) {
            if ($field['type_value']) {
                $value = str_replace(' ', 'T', form_eng_time($value));
            } else {
                $value = str_replace(' ', 'T', form_eng_time($value, 0));
            }
        }

        $new_value['input'] = $value;
        $new_value['value'] = $value;
    } elseif ($type == 3)   //тип поля текст
    {
        if ($field['crypt'] and isset($config['crypt_hash']) and $crypt_key and $config['crypt_type'] == "strong") {
            if ($_SESSION[$ses_id]['decrypt_lines'][$line_id]) {
                $value = text_decrypt($crypt_key, $value);
            } elseif ($line_id) {
                $value = "******";
                $crypt_value[$field['id']] = 1;
            }
        } elseif ($field['crypt'] and isset($config['crypt_hash']) and !$crypt_key) {
            $crypt_value[$field['id']] = 1;
        }
        $value = form_display($value);
        $new_value['input'] = $value;
        $new_value['value'] = $value;
    } elseif ($type == 4)   //тип поля список
    {
        $value = isset($value) ? explode("\n", $value) : array();
        foreach ($value as $i => $val){
            $val = str_replace("\r", "", $val);
            $value[$i] = $val;
        }
        if ($field['mult_value']) // мн.выбор
        {
            if ($field['form_fast_edit_flag']) {  // новый режим быстрого редактирования
                $value[] = '';
                $pos = 0;
                $new_value['input']['set'] = array();
                $set = "";
                foreach ($field['list_values'] as $list_value) {
                    $disabled = "";
                    if ((in_array($list_value, $value)) && ($list_value != $one_value)) { // Ограничиваем возможность выбора повторно, одних и тех же элементов
                        $disabled = "disabled";
                    }
                    $display_value = $lang['conf'][$list_value] ? $lang['conf'][$list_value] : $list_value;
                    if ($field['reduce'] and mb_strlen($display_value) > 35) {
                        $display_value = mb_substr($display_value, 0, 35) . "...";
                    }
                    $checked = (in_array($list_value, $value)) ? 'checked' : ' ';

                    if (!$is_mobile) {
                        $type_4_mult_val_span .= (
                            in_array($list_value, $value) ? '<div>'. form_display($display_value) .'</div>' : ''
                        );
                    }

                    if (!$is_mobile) {
                        $set .= '
                            <div class="type_4_mult_val"><input type="checkbox"
                                id="view_value' . $field['id']. '[' . form_display($display_value) . ']"
                                style="width:auto" value="'.form_display($display_value) . '" ' . $checked . ' onchange="save_type_4_mult_val(this)">
                            <label for="view_value' . $field['id']. '[' . form_display($display_value) . ']"
                                class="user-data__multi-label user-data__multi-label--data">'.form_display($display_value) . '</label></div>';
                    } else {
                        $set .= '
                            <div class="type_4_mult_val"><input type="checkbox"
                                id="view_value' . $field['id']. '[' . form_display($display_value) . ']"
                                name="value[new][' . $field['id']. '][]"
                                style="width:auto" value="'.form_display($display_value) . '" ' . $checked . ' >
                            <label for="view_value' . $field['id']. '[' . form_display($display_value) . ']"
                                class="user-data__multi-label user-data__multi-label--data">'.form_display($display_value) . '</label></div>';
                    }
                }

                if (!$is_mobile) {
                    $set .='</div>';
                    $mult_val_check_preview = (
                        '<div class="user-data__group-select-wrap" id="view-multi' . $field["id"] .
                        '" title="' . $field["help"] . '">'.$type_4_mult_val_span.'</div>'
                    );
                }

                $new_value['mult_val_check_preview'] = $mult_val_check_preview;
                $new_value['input']['set'][$pos] = $set;
                $pos++;
                $new_value['value'] = "";
            } else {  // старый режим галочками
                foreach ($field['list_values'] as $list_value) {
                    $display_value = $lang['conf'][$list_value] ? $lang['conf'][$list_value] : $list_value;
                    if ($field['reduce'] and mb_strlen($display_value) > 35) {
                        $display_value = mb_substr($display_value, 0, 35) . "...";
                    }
                    $one_value['list_value'] = $list_value;
                    if ($type_out == 'view_edit' || $test_write === 1) {
                        $one_value['checked'] = in_array($list_value, $value);
                    }
                    $one_value['display_value'] = $display_value;
                    $all_values[] = $one_value;
                }
                $new_value['input'] = $all_values;
                $new_value['value'] = count_cb(array_filter($value));
            };
        } else {
            $value = $value[0];

            $set = "<option value=''></option>";
            foreach ($field['list_values'] as $list_value) {
                $display_value = $lang['conf'][$list_value] ? $lang['conf'][$list_value] : $list_value;
                if (($field['reduce'] || $field['fast_edit']) and mb_strlen($display_value) > 35) {
                    $display_value = mb_substr($display_value, 0, 35) . "...";
                }
                $set .= "<option " . (($list_value == $value) ? "selected " : "")
                    . "value='" . form_display($list_value)
                    . "'>" . form_display($display_value)
                    . "</option>";
            }

            $new_value['input'] = $set;
            $new_value['value'] = $value;
        }
    } elseif ($type == 5)   //тип поля связь
    {
        $new_value['input'] = "";
        $new_value['value'] = $value;
    } elseif ($type == 6)   //тип поля файл
    {
        $files = $value ? explode("\r\n", $value) : array();
        foreach ($files as $i => $file) {
            if (!trim($file)) {
                unset($files[$i]);
                continue;
            }
            $one_file['name'] = form_display($file);
            $one_file['js'] = addslashes($file);
            $one_file['url'] = urlencode($file);
            $files[$i] = $one_file;
        }
        $new_value['input'] = $files;
        $new_value['value'] = $value;
    } elseif ($type == 7 or $type == 11)   //тип поля пользователь
    {
        $group_id = $field['groupe'];
        if (is_array($group_id)) {
            foreach ($group_id as $k => $v) {
                if (!$v) {
                    unset($group_id[$k]);
                }
                if ($v == '{current}' or $v == '{current_group}') {
                    $group_id[$k] = $user['group_id'];
                }
            }
        } else {
            $group_id = 0;
        }

        if (substr($value, -1) == "-") {
            $value = substr($value, 1, -1);
        }
        if ($field['mult_value']) // мн.выбор
        {
            $value = $value ? explode("-", $value) : array();
            foreach ($value as $k => $v) {
                if (!$v) {
                    unset($value[$k]);
                }
            }
            if ($field['form_fast_edit_flag']) {  // новый режим быстрого редактирования
                $value[] = '';
                $pos = 0;
                $new_value['input']['set'] = array();

                $type_value = array();
                $sqlQuery = "SELECT id, fio FROM " . USERS_TABLE . " WHERE arc=0" . ($group_id ? " AND group_id in (" . implode(", ",
                            $group_id) . ")" : "") . " ORDER BY fio";
                $result = sql_query($sqlQuery);
                while ($row = sql_fetch_assoc($result)) {
                    $type_value[$row['id']] = $row['fio'];
                }
                $set = "";
                foreach ($type_value as $id => $list_value) {
                    $disabled = "";
                    if ((in_array($id, $value)) && ($id != $one_value)) { // Ограничиваем возможность выбора повторно, одних и тех же элементов
                        $disabled = "disabled";
                    }
                    if ($field['reduce'] and mb_strlen($list_value) > 35) {
                        $display_value = mb_substr($list_value, 0, 35) . "...";
                    } else {
                        $display_value = $list_value;
                    }
                    $checked = (in_array($id, $value)) ? 'checked' : ' ';
                    if (!$is_mobile) {
                        $type_4_mult_val_span .= (
                            in_array($id, $value) ? '<div>'. $display_value .'</div>' : ''
                        );
                        $set .= '
                            <div class="type_4_mult_val"><input type="checkbox"
                                id="view_value' . $field['id']. '[' . $id . ']"
                                style="width:auto" value="'. $id . '" ' . $checked . ' onchange="save_type_4_mult_val(this)">
                            <label for="view_value' . $field['id']. '[' . $id . ']"
                                class="user-data__multi-label user-data__multi-label--data">'. $display_value . '</label></div>';
                    } else {
                        $set .= '
                            <div class="type_4_mult_val"><input type="checkbox"
                                id="view_value' . $field['id']. '[' . $id . ']"
                                name="value[new][' . $field['id']. '][]"
                                style="width:auto" value="'. $id . '" ' . $checked . '>
                            <label for="view_value' . $field['id']. '[' . $id . ']"
                                class="user-data__multi-label user-data__multi-label--data">'. $display_value . '</label></div>';
                    }
                }

                if (!$is_mobile) {
                    $set .='</div>';
                    $mult_val_check_preview = (
                        '<div class="user-data__group-select-wrap" id="view-multi' . $field["id"] .
                        '" title="' . $field["help"] . '">'.$type_4_mult_val_span.'</div>'
                    );
                }

                $new_value['mult_val_check_preview'] = $mult_val_check_preview;
                $new_value['input']['set'][$pos] = $set;
                $pos++;
                $new_value['value'] = "";
            } else {  // старый режим галочками
                if ($line_id and in_array("{current}", $value)) {
                    $value[array_search("{current}", $value)] = $user['id'];
                }
                if (!$line_id and $type_out !== "view_add") {
                    $one_value['list_value'] = "{current}";
                    $one_value['checked'] = in_array("{current}", $value);
                    $one_value['display_value'] = "{" . $lang['current'] . "}";
                    $all_values[] = $one_value;
                    if (in_array("{current}", $value)) {
                        $in_list = 1;
                    }

                    $one_value['list_value'] = "{random}";
                    $one_value['checked'] = in_array("{random}", $value);
                    $one_value['display_value'] = "{" . $lang['random'] . "}";
                    $all_values[] = $one_value;
                    if (in_array("{random}", $value)) {
                        $in_list = 1;
                    }

                    $one_value['list_value'] = "{inorder}";
                    $one_value['checked'] = in_array("{inorder}", $value);
                    $one_value['display_value'] = "{" . $lang['in_order'] . "}";
                    $all_values[] = $one_value;
                    if (in_array("{inorder}", $value)) {
                        $in_list = 1;
                    }
                }
                $result = sql_select_field(USERS_TABLE, "id, fio", "arc=0" . ($group_id ? " AND group_id in (" . implode(",", $group_id) . ")" : "") . " ORDER BY fio");
                while ($row = sql_fetch_assoc($result)) {
                    $one_value['list_value'] = $row['id'];
                    $one_value['checked'] = in_array($row['id'], $value);
                    $one_value['display_value'] = form_display($row['fio']);
                    $all_values[] = $one_value;
                    if (in_array($row['id'], $value)) {
                        $in_list = 1;
                    }
                }
                if ($value and !$in_list and trim(implode(",", $value)) != ''
                                         and trim(implode(",", $value)) != '{random}'
                                         and trim(implode(",", $value)) != '{inorder}'
                                         and trim(implode(",", $value)) != $lang['No_access']) {
                    $result = sql_select_field(USERS_TABLE, "id, fio", "arc=0 AND id in (" . implode(",", $value) . ") ORDER BY fio");
                    while ($row = sql_fetch_assoc($result)) {
                        $one_value['list_value'] = $row['id'];
                        $one_value['checked'] = in_array($row['id'], $value);
                        $one_value['display_value'] = form_display($row['fio']);
                        $all_values[] = $one_value;
                    }
                }
                $new_value['input'] = $all_values;
                $new_value['value'] = count_cb($value);
            }
        } else {
            if ($value < 0) {
                $value = -(int)$value;
            }
            $set = "<option value='0'>" . ($type == 11 ? $lang['System'] : '') . "</option>";
            $set .= "<option value='" . $lang['No_access'] . "' style='display:none'" .
                    (($value == $lang['No_access']) ? " selected" : "") . ">" . $lang['No_access'] . "</option>";
            if ($line_id and $value == "{current}") {
                $value = $user['id'];
            }
            if (!$line_id and $type_out !== "view_add" and !$config['is_mobile']) {
                $set .= "<option " . (($value == "{current}") ? "selected " : "") . "value='{current}'>{" . $lang['current'] . "}</option>
            <option " . (($value == "{random}") ? "selected " : "") . "value='{random}'>{" . $lang['random'] . "}</option>
            <option " . (($value == "{inorder}") ? "selected " : "") . "value='{inorder}'>{" . $lang['in_order'] . "}</option>";
            }
            $sqlQuery = "SELECT id, fio FROM " . USERS_TABLE . " WHERE arc=0" . ($group_id ? " AND group_id in (" . implode(", ",
                        $group_id) . ")" : "") . " ORDER BY fio";
            $result = sql_query($sqlQuery);
            while ($row = sql_fetch_assoc($result)) {
                $set .= "<option value='" . $row['id'] . "'" . (($row['id'] == $value) ? " selected" : "") . ">" . form_display($row['fio']) . "</option>";
                if ($row['id'] == $value) {
                    $in_list = 1;
                }
            }
            if ($line_id and $value and $value != $lang['No_access'] and !$in_list) {
                $sqlQuery = "SELECT fio FROM " . USERS_TABLE . " WHERE id='" . $value . "'";
                $result = sql_query($sqlQuery);
                if ($row = sql_fetch_assoc($result)) {
                    $set .= "<option value='" . $value . "' selected>" . form_display($row['fio']) . "</option>";
                } else {
                    $set .= "<option value='" . $value . "' selected style='color:#afafaf'>- " . $lang['deleted_u'] . " -</option>";
                }
            }
            $new_value['input'] = $set;
            $new_value['value'] = $value;
        }
    } elseif ($type == 9)   //тип поля изображение
    {
        $files = $value ? explode("\r\n", $value) : array();
        foreach ($files as $i => $file) {
            if (!trim($file)) {
                unset($files[$i]);
                continue;
            }
            $one_file['name'] = form_display($file);
            $one_file['js'] = addslashes($file);
            $one_file['url'] = urlencode($file);
            $one_file['file'] = utf2eng($file);
            $one_file['size'] = $type_value;
            $files[$i] = $one_file;
        }
        $new_value['input'] = $files;
        $new_value['value'] = $value;
    } elseif ($type == 13)   //тип поля статус
    {
        $set .= "<option " . (($value == 0) ? "selected " : "") . "value=0>" . $lang['active'] . "</option>";
        $set .= "<option " . (($value == 1) ? "selected " : "") . "value=1>" . $lang['archive'] . "</option>";
        $set .= "<option " . (($value == 2) ? "selected " : "") . "value=2>" . $lang['deleted'] . "</option>";
        $new_value['input'] = $set;
        $new_value['value'] = $value;
    } elseif ($type == 14)   //тип поля группа
    {
        // Права на изменение группы доступа для Субадминов
        $field_for_group = $table['user_table_fields']['group_id'];
        $field_for_user = $table['user_table_fields']['user_id'];
        if ($field_for_group && $config['master_sub_admin'] > 0 && $line['f' . $field_for_user] == $config['master_sub_admin']) {
            $sub_admin_groups = [];
            $query = sql_select(GROUPS_TABLE, "sub_admin=1");
            while ($row = sql_fetch_assoc($query)) {
                $sub_admin_groups[] = $row['id'];
            }
            $sub_admin_excep = " WHERE id IN (" . implode(", ", $sub_admin_groups) . ") ";
            $sub_admin_excep_and = " AND id IN (" . implode(", ", $sub_admin_groups) . ") ";
        } elseif ($field_for_group && $user['group_id'] != 1 && $user['sub_admin_rights']['access_subadmin'] == 1) {
            $sub_admin_excep = " WHERE id!=1 ";
            $sub_admin_excep_and = " AND id!=1 ";
        } elseif ($field_for_group && $user['group_id'] != 1) {
            $sub_admin_groups = [1];
            $query = sql_select(GROUPS_TABLE, "sub_admin=1");
            while ($row = sql_fetch_assoc($query)) {
                $sub_admin_groups[] = $row['id'];
                if ($value == $row['id']) {
                    $value = '0';
                }
            }
            $sub_admin_excep = " WHERE id NOT IN (" . implode(", ", $sub_admin_groups) . ") ";
            $sub_admin_excep_and = " AND id NOT IN (" . implode(", ", $sub_admin_groups) . ") ";
        } else {
            $sub_admin_excep = "";
            $sub_admin_excep_and = "";
        }

        global $all_modules;
        if ($config['clients_group_off'] || !$all_modules['client_group']) {
            $result = sql_select(USERS_TABLE, 'group_id = 777');
            $clients_group_off = sql_num_rows($result) ? 0 : 1;
        } else {
            $clients_group_off = 0;
        }
        if ($clients_group_off) {
            $sub_admin_excep = $sub_admin_excep ? $sub_admin_excep . ' AND id != 777 ' : ' WHERE id != 777 ';
            $sub_admin_excep_and = ' AND id != 777 ';
        }

        $value = trim($value, '-');

        $value = str_replace('--', '-', $value);
        while (strpos($value, '--') !== false) {
            $value = str_replace('--', '-', $value);
        }

        if ($field['mult_value']) // мн.выбор
        {
            $value = $value ? explode("-", $value) : array();

            if ($field['form_fast_edit_flag']) {  // новый режим быстрого редактирования
                $value[] = '';
                $pos = 0;
                $new_value['input']['set'] = array();

                $type_value = array();
                $sqlQuery = "SELECT id, name FROM " . GROUPS_TABLE . " " . $sub_admin_excep . " ORDER BY name";
                $result = sql_query($sqlQuery);
                while ($row = sql_fetch_assoc($result)) {
                    //костылек для обрезания нужных групп
                    if ($field['display_groups']) {
                        $need_value = explode(',', $field['display_groups']);
                        foreach ($need_value as $i => $v) {
                            if ($v == $row['id']) {
                                $type_value[$row['id']] = form_display($row['name']);
                            }
                        }
                    } else {
                        $type_value[$row['id']] = form_display($row['name']);
                    }
                }
                if (!$sub_admin_excep) {
                    $set = "";
                }
                foreach ($type_value as $id => $list_value) {
                    $disabled = "";
                    if ((in_array($id, $value)) && ($id != $one_value)) { // Ограничиваем возможность выбора повторно, одних и тех же элементов
                        $disabled = "disabled";
                    }
                    if ($field['reduce'] and mb_strlen($list_value) > 35) {
                        $display_value = mb_substr($list_value, 0, 35) . "...";
                    } else {
                        $display_value = $list_value;
                    }
                    $checked = (in_array($id, $value)) ? 'checked' : ' ';
                    if (!$is_mobile) {
                        $type_4_mult_val_span .= (
                            in_array($id, $value) ? '<div>'. $display_value .'</div>' : ''
                        );
                        $set .= '
                            <div class="type_4_mult_val"><input type="checkbox"
                                id="view_value' . $field['id']. '[' . $id . ']"
                                style="width:auto" value="'. $id . '" ' . $checked . ' onchange="save_type_4_mult_val(this)">
                            <label for="view_value' . $field['id']. '[' . $id . ']"
                                class="user-data__multi-label user-data__multi-label--data">'. $display_value . '</label></div>';
                    } else {
                        $set .= '
                            <div class="type_4_mult_val"><input type="checkbox"
                                id="view_value' . $field['id']. '[' . $id . ']"
                                name="value[new][' . $field['id']. '][]"
                                style="width:auto" value="'. $id . '" ' . $checked . '>
                            <label for="view_value' . $field['id']. '[' . $id . ']"
                                class="user-data__multi-label user-data__multi-label--data">'. $display_value . '</label></div>';
                    }
                }

                if (!$is_mobile) {
                    $set .='</div>';
                    $mult_val_check_preview = (
                        '<div class="user-data__group-select-wrap" id="view-multi' . $field["id"] .
                        '" title="' . $field["help"] . '">'.$type_4_mult_val_span.'</div>'
                    );
                }

                $new_value['mult_val_check_preview'] = $mult_val_check_preview;
                $new_value['input']['set'][$pos] = $set;
                $pos++;
                $new_value['value'] = "";
            } else {  // старый режим галочками
                if ($line_id and in_array("{current_group}", $value)) {
                    $value[array_search("{current_group}", $value)] = $user['group_id'];
                }
                if (!$line_id and $type_out !== "view_add") {
                    $one_value['list_value'] = "{current_group}";
                    $one_value['checked'] = in_array("{current_group}", $value);
                    $one_value['display_value'] = "{" . $lang['current_gr'] . "}";
                    $all_values[] = $one_value;
                    if (in_array("{current_group}", $value)) {
                        $in_list = 1;
                    }

                    $one_value['list_value'] = "{random}";
                    $one_value['checked'] = in_array("{random}", $value);
                    $one_value['display_value'] = "{" . $lang['random'] . "}";
                    $all_values[] = $one_value;
                    if (in_array("{random}", $value)) {
                        $in_list = 1;
                    }

                    $one_value['list_value'] = "{inorder}";
                    $one_value['checked'] = in_array("{inorder}", $value);
                    $one_value['display_value'] = "{" . $lang['in_order'] . "}";
                    $all_values[] = $one_value;
                    if (in_array("{inorder}", $value)) {
                        $in_list = 1;
                    }
                }
                $sqlQuery = "SELECT id, name FROM " . GROUPS_TABLE . ($field['display_groups'] ? (" WHERE id in (" . $field['display_groups'] . ")" . $sub_admin_excep_and) : $sub_admin_excep) . " ORDER BY name";
                $result = sql_query($sqlQuery);
                while ($row = sql_fetch_assoc($result)) {
                    $one_value['list_value'] = $row['id'];
                    $one_value['checked'] = in_array($row['id'], $value);
                    $one_value['display_value'] = form_display($row['name']);
                    $all_values[] = $one_value;
                    if (in_array($row['id'], $value)) {
                        $in_list = 1;
                    }
                }

                $temp_value = trim(implode(",", $value));
                if (
                    $value && !$in_list &&
                    !in_array($temp_value, ['', '{random}', '{inorder}', $lang['No_access']])
                ) {
                    $result = sql_query("
                        SELECT id, name
                        FROM " . GROUPS_TABLE . "
                        WHERE id in (" . implode(",", $value) . ") " . $sub_admin_excep_and . "
                        ORDER BY name
                    ");

                    while ($row = sql_fetch_assoc($result)) {
                        $one_value['list_value'] = $row['id'];
                        $one_value['checked'] = in_array($row['id'], $value);
                        $one_value['display_value'] = form_display($row['name']);
                        $all_values[] = $one_value;
                    }
                }

                $new_value['input'] = $all_values;
                $new_value['value'] = count_cb($value);
            }
        } else {
            if ($value < 0) {
                $value = - (int) $value;
            }
            $set = "<option value='0'></option>";
            $set .= "<option value='" . $lang['No_access'] . "' style='display:none'" .
                    (($value == $lang['No_access']) ? " selected" : "") . ">" . $lang['No_access'] . "</option>";
            if ($line_id and $value == "{current_group}") {
                $value = $user['group_id'];
            }
            if (!$line_id and $type_out !== "view_add") {
                $set .= "<option " . (($value == "{current_group}") ? "selected " : "") . "value='{current_group}'>{" . $lang['current_gr'] . "}</option>
            <option " . (($value == "{random}") ? "selected " : "") . "value='{random}'>{" . $lang['random'] . "}</option>
            <option " . (($value == "{inorder}") ? "selected " : "") . "value='{inorder}'>{" . $lang['in_order'] . "}</option>";
            }
            $sqlQuery = "SELECT id, name FROM " . GROUPS_TABLE . ($field['display_groups'] ? (" WHERE id in (" . $field['display_groups'] . ")" . $sub_admin_excep_and) : $sub_admin_excep) . " ORDER BY name";
            $result = sql_query($sqlQuery);
            while ($row = sql_fetch_assoc($result)) {
                $set .= "<option value='" . $row['id'] . "'" . (($row['id'] == $value) ? " selected" : "") . ">" . $row['name'] . "</option>";
                if ($row['id'] == $value) {
                    $in_list = 1;
                }
            }
            if ($line_id and $value and $value != $lang['No_access'] and !$in_list) {
                $sqlQuery = "SELECT name FROM " . GROUPS_TABLE . " WHERE id='" . $value . "'";
                $result = sql_query($sqlQuery);
                if ($row = sql_fetch_assoc($result)) {
                    $set .= "<option value='" . $value . "' selected>" . $row['name'] . "</option>";
                } else {
                    $set .= "<option value='" . $value . "' selected style='color:#afafaf'>- " . $lang['deleted_g'] . " -</option>";
                }
            }
            $new_value['input'] = $set;
            $new_value['value'] = $value;
        }
    } else {
        generate_error("Unknown field type ($type)");
    }
    return $new_value;
}

function form_sql_type($field, $value, $type_out = "", $term = "")     //при занесении в базу
{
    global $user, $lang;

    if ($_COOKIE['is_mobile']) {
        $is_mobile = 1;
    }

    $type = $field['type_field'];

    $value = default_tpl_replace($value);

    if ($type_out == "import") {
        $value = str_replace("\n", "\r\n", str_replace("\r\n", "\n", $value));
    }

    if ($type == 1 or $type == 10)  //тип поля число
    {
        if ($type_out == "search") {
            for ($i = 0; $i < strlen($value); $i++) {
                if (!(((ord($value[$i]) > 47) && (ord($value[$i]) < 58)) || ($value[$i] == ' ') || ($value[$i] == '.') || ($value[$i] == $lang["float_delimiter"]))) {
                    $not_is_number = 1;
                }
                if ($i == 0 && $value[$i] == '-') {
                    $not_is_number = 0;
                }
            }
        }
        if (!$not_is_number) {
            $new_value = form_eng_number($value);
        }
    } elseif ($type == 2 or $type == 12)  //тип поля дата
    {
        if (substr($value, 0, 1) == "{") {
            $new_value = $value;
        } else {
            if ($is_mobile && $type_out != 'search') {
                $new_value = str_replace('T', ' ', $value);
            } else {
                $new_value = form_eng_time($value);
            }
        }
    } elseif ($type == 3)   //тип поля текст
    {
        $new_value = trim($value);
    } elseif ($type == 4)   //тип поля список
    {
        if ($type_out == "search") {
            $value = mb_strtolower($value); // приводим искомое значение к нижнему регистру
            if (!$field['list_values']) {
                $field['list_values'] = explode("\r\n", $field['type_value']);
            }
            if (!$field['int_name']) {
                $field['int_name'] = form_int_name($field['id']);
            }
            $field['list_values'][] = ""; // добавляем пустой элемент
            $new_value = array();
            foreach ($field['list_values'] as $list_value) {
                if ($lang['conf'][$list_value] && ($term == " LIKE " or $term == " NOT LIKE ")) {
                    $f_value = mb_strtolower($lang['conf'][$list_value]);
                } else {
                    $f_value = mb_strtolower($list_value);
                }
                if ((($term == "=" or $term == "!=") and $f_value == $value) or (($term == " LIKE " or $term == " NOT LIKE ") and strpos($f_value, $value) !== false)) {
                    if (($term == " LIKE " or $term == " NOT LIKE ") and strpos($f_value, $value) !== false and $field['mult_value']) {
                        $new_value[] = $field['int_name'] . $term . "'%" . form_sql_like($list_value) . "%'";
                    } else {
                        $new_value[] = $field['int_name'] . $term . "'" . form_sql($list_value) . "'";
                    }
                }
                if (($term == " LIKE " or $term == " NOT LIKE ") and strpos($f_value, $value) !== false and $field['mult_value']) {
                    $new_value[] = $field['int_name'] . $term . "'" . form_sql_like($list_value) . "\\r\\n%'";
                    $new_value[] = $field['int_name'] . $term . "'%\\r\\n" . form_sql_like($list_value) . "'";
                    $new_value[] = $field['int_name'] . $term . "'%\\r\\n" . form_sql_like($list_value) . "\\r\\n%'";
                }
            }
            // Если не было явных совпадений и используется конструкция LIKE, то ищем прямо по тексту
            // Явные совпадения могут отсутвовать тк. например выбор удален из настроек
            if (!$new_value && ($term == " LIKE " or $term == " NOT LIKE ")) {
                $value = mb_substr($value, 0, 250); // Обрезаем если слишком длинное значение
                $new_value[] = $field['int_name'] . $term . "'%" . form_sql_like($value) . "%'";
            }
            if ($term == "=" or $term == " LIKE ") {
                $union = " or ";
            } else {
                $union = " and ";
            }
            if ($new_value) {
                $new_value = "(" . implode($union, $new_value) . ")";
            } else {
                $new_value = "'0'";
            }
        } else {
            if (is_array($value)) {
                $new_value = implode("\r\n", array_filter($value));
            } else {
                $new_value = $value;
            }
        }
    } elseif ($type == 5)   //тип поля связь
    {
        if ($type_out == "import") {
            $imp_values = explode("\n", $value);
            if (!$field['mult_value']) {
                $imp_values = [$imp_values[0]]; // если поле не множественное, берем только первое значение
            }
            $values = [];
            foreach ($imp_values as $value) {
                $value = trim($value);
                if ($field['s_show_field_inline']) { // если значение поля связи состоит из нескольких полей, поиск по sql условию невозможен, проходимся по всем записям
                    $result = data_select_field($field['s_table_id'], 'id', '1=1');
                    while ($row = sql_fetch_assoc($result)) {
                        $line = array($field['int_name'] => $row['id']);
                        $line_value = form_display_type($field, $line, "text");
                        $line_value_without_space = str_replace(' ', '', $line_value);
                        if ($line_value === $value || $line_value_without_space === $value) {
                            $values[] = $row['id'];
                            break;
                        }
                    }
                } else {
                    $result = data_select_field($field['s_table_id'], 'id', form_int_name($field['s_field_id']) . " = '", $value, "'");
                    if ($row = sql_fetch_assoc($result)) {
                        $values[] = $row['id'];
                    }
                }
            }
            if ($values) {
                $new_value = $field['mult_value'] ? '-' . implode('-', $values) . '-' : $values[0];
            } else {
                $new_value = $field['mult_value'] ? '' : 0;
            }
        } elseif ($type_out == "search") {
            $new_value = get_link_lines($field, $term, $value);
        } else {
            if ($field['mult_value'] == 1) {
                if (is_array($value)) {
                    $new_value = '-' . implode('-', $value) . '-';
                } elseif ((int)$value > 0) {
                    $new_value = "-{$value}-";
                } else {
                    $new_value = $value;
                }
            } else {
                $new_value = $value;
            }
        }
    } elseif ($type == 6)   //тип поля файл
    {
        $new_value = $value;
    } elseif ($type == 7 or $type == 11)   //тип поля пользователь
    {
        if ($type_out == "import") {
            $users = explode("\r\n", $value);
            foreach ($users as $i => $value) {
                $sqlQuery = "SELECT id FROM " . USERS_TABLE . " WHERE fio='" . form_sql($value) . "'";
                $result = sql_query($sqlQuery);
                if ($row = sql_fetch_assoc($result)) {
                    $users[$i] = $row['id'];
                } else {
                    unset($users[$i]);
                }
            }
            $new_value = implode("-", $users);
            if ($field['mult_value'] and count_cb($users)) {
                $new_value = "-" . $new_value . "-";
            }
        } elseif ($type_out != "search" and $field['mult_value'] and $value) {
            if (!is_array($value)) {
                $value = explode("\r\n", $value);
            }
            $new_value = "-" . (is_array($value) ? implode("-", $value) : $value) . "-";
        } else {
            $new_value = $value;
        }
    } elseif ($type == 9)   //тип поля изображение
    {
        $new_value = $value;
    } elseif ($type == 13)   //тип поля статус
    {
        if ($type_out == "import") {
            if ($value == $lang['active']) {
                $new_value = 0;
            }
            if ($value == $lang['archive']) {
                $new_value = 1;
            }
            if ($value == $lang['deleted']) {
                $new_value = 2;
            }
        } else {
            $new_value = $value;
        }
    } elseif ($type == 14)   //тип поля группа
    {
        if ($type_out == "import") {
            $groups = explode("\r\n", $value);
            foreach ($groups as $i => $value) {
                $sqlQuery = "SELECT id FROM " . GROUPS_TABLE . " WHERE name='" . form_sql($value) . "'";
                $result = sql_query($sqlQuery);
                if ($row = sql_fetch_assoc($result)) {
                    $groups[$i] = $row['id'];
                } else {
                    unset($groups[$i]);
                }
            }
            $new_value = implode("-", $groups);
            if ($field['mult_value'] and count_cb($groups)) {
                $new_value = "-" . $new_value . "-";
            }
        } elseif ($type_out != "search" and $field['mult_value'] and $value) {
            $new_value = "-" . (is_array($value) ? implode("-", $value) : $value) . "-";
        } else {
            $new_value = $value;
        }
    } else {
        generate_error("Unknown field type ($type)");
    }
    return $new_value;
}

function form_filter_type($field, $value, $type_out = "filter")     //при выборе значения фильтра
{
    global $lang, $user;

    $type = $field['type_field'];
    $type_value = $field['type_value'];

    if ($type_out == "fix_search") {
        $type_out = "search";
        $fix_search = 1;
    }

    if ($type == 2 or $type == 12)   //тип поля дата
    {
        if ($type_out == "filter") {
            $new_value = "<option value=\"0000-00-00 00:00:00\">{" . $lang['empty_date'] . "}</option>" .
                "<option value=\"curdate()\">{" . $lang['current_date'] . "}</option>" .
                "<option value=\"now()\">{" . $lang['current_time'] . "}</option>" .
                "<option value=\"week()\">{" . $lang['current_week'] . "}</option>" .
                "<option value=\"half_month()\">{" . $lang['current_half_month'] . "}</option>" .
                "<option value=\"month()\">{" . $lang['current_month'] . "}</option>" .
                "<option value=\"year()\">{" . $lang['current_year'] . "}</option>" .
                "<option value=\"fix_date\">{" . $lang['fix_date'] . "}</option>";
        } elseif ($type_out == "format") {
            $new_value = "<option value=\"0000-00-00 00:00:00\">{" . $lang['empty_date'] . "}</option>" .
                "<option value=\"date('Y-m-d')\">{" . $lang['current_date'] . "}</option>" .
                "<option value=\"date('Y-m-d H:i:s')\">{" . $lang['current_time'] . "}</option>" .
                "<option value=\"date('W')\">{" . $lang['current_week'] . "}</option>" .
                "<option value=\"date('W')\">{" . $lang['current_half_month'] . "}</option>" .
                "<option value=\"date('m')\">{" . $lang['current_month'] . "}</option>" .
                "<option value=\"date('Y')\">{" . $lang['current_year'] . "}</option>";
        } else {
            $new_value = form_display($value);
        }
    } elseif ($type == 4)   //тип поля список
    {
        $new_value = "<option value=''></option>";
        foreach ($field['list_values'] as $list_value) {
            if ($type_out == "search") {
                $display_value = $lang['conf'][$list_value] ? $lang['conf'][$list_value] : $list_value;
            } else {
                $display_value = $list_value;
            }
            if ($field['reduce'] and mb_strlen($display_value) > 35) {
                $display_value = mb_substr($display_value, 0, 35) . "...";
            }
            $new_value .= "<option " . (($list_value == $value) ? "selected " : "") . "value='" . form_display($list_value) . "'>" . form_display($display_value) . "</option>";
        }
    } elseif ($type == 7 or $type == 11)   //тип поля пользователь
    {
        $group_id = $field['groupe'];
        if (is_array($group_id)) {
            foreach ($group_id as $k => $v) {
                if (!$v) {
                    unset($group_id[$k]);
                }
                if ($v == '{current}' or $v == '{current_group}') {
                    $group_id[$k] = $user['group_id'];
                }
            }
        }

        if ($fix_search) {
            $new_value = "<option value=\"\"></option>";
        } else {
            $new_value = "<option value=\"\">" . ($type == 11 ? $lang['System'] : '') . "</option>";
        }
        if ($type_out == "format") {
            $new_value .= "<option value=\"\$user['fio']\">{" . $lang['current'] . "}</option>";
        } elseif ($type_out == "filter") {
            if ($field['mult_value']) {
                $cur_user = "-{current}-";
            } else {
                $cur_user = "{current}";
            }
            if ($field['id'] <> 999999999) {
                $new_value .= "<option value=\"" . $cur_user . "\">{" . $lang['current'] . "}</option>";
            }
        }
        $sqlQuery = "SELECT id, fio FROM " . USERS_TABLE . " WHERE arc=0" . (($type_out == "search") && ($group_id) ? " AND group_id in (" . implode(", ",
                    $group_id) . ")" : "") . " ORDER BY fio";
        $result = sql_query($sqlQuery);
        while ($row = sql_fetch_assoc($result)) {
            if ($type_out == "format") {
                $new_value .= "<option " . (($row['fio'] == $value) ? "selected " : "") . "value=\"" . $row['fio'] . "\">" . $row['fio'] . "</option>";
            } else {
                if ($field['mult_value']) {
                    $row['id'] = "-" . $row['id'] . "-";
                }
                $new_value .= "<option " . (($row['id'] == $value) ? "selected " : "") . "value=\"" . $row['id'] . "\">" . form_display($row['fio']) . "</option>";
            }
        }
    } elseif ($type == 13)   //тип поля статус
    {
        if ($type_out == "format") {
            $new_value .= "<option " . (($value == $lang['active']) ? "selected " : "") . "value='" . $lang['active'] . "'>" . $lang['active'] . "</option>";
            $new_value .= "<option " . (($value == $lang['archive']) ? "selected " : "") . "value='" . $lang['archive'] . "'>" . $lang['archive'] . "</option>";
            $new_value .= "<option " . (($value == $lang['deleted']) ? "selected " : "") . "value='" . $lang['deleted'] . "'>" . $lang['deleted'] . "</option>";
        } else {
            $new_value .= "<option " . (($value == 0) ? "selected " : "") . "value=0>" . $lang['active'] . "</option>";
            $new_value .= "<option " . (($value == 1) ? "selected " : "") . "value=1>" . $lang['archive'] . "</option>";
            $new_value .= "<option " . (($value == 2) ? "selected " : "") . "value=2>" . $lang['deleted'] . "</option>";
        }
    } elseif ($type == 14)   //тип поля группа
    {
        $new_value = "<option value=\"\"></option>";
        if (in_array($type_out, ["format", "filter"])) {
            if ($field['mult_value']) {
                $cur_group = "-{current_group}-";
            } else {
                $cur_group = "{current_group}";
            }
            if ($field['id'] <> 999999998) {
                $new_value .= "<option value=\"" . $cur_group . "\">{" . $lang['current_gr'] . "}</option>";
            }
        }

        $sqlQuery = "SELECT id, name FROM " . GROUPS_TABLE;
        if ($field['display_groups']) {
            $sqlQuery .= " WHERE id IN (" . form_sql($field['display_groups']) . ")";
        }
        $sqlQuery .= " ORDER BY name";
        $result = sql_query($sqlQuery);
        while ($row = sql_fetch_assoc($result)) {
            if ($type_out == "format") {
                $new_value .= "<option " . (($row['name'] == $value) ? "selected " : "") . "value=\"" . $row['id'] . "\">" . $row['name'] . "</option>";
            } else {
                if ($field['mult_value']) {
                    $row['id'] = "-" . $row['id'] . "-";
                }
                $new_value .= "<option " . (($row['id'] == $value) ? "selected " : "") . "value=\"" . $row['id'] . "\">" . $row['name'] . "</option>";
            }
        }
    } else   //остальные типы
    {
        $new_value = form_display($value);
    }
    return $new_value;
}

function type_array()
{
    global $lang;
    return array(
        "",
        $lang["digit"],
        $lang["date_time"],
        $lang["text"],
        $lang["list"],
        $lang["link"],
        $lang["file"],
        $lang["user"],
        $lang["number"],
        $lang["image"],
        $lang["digit"],
        $lang["user"],
        $lang["date_time"],
        $lang["list"],
        $lang["group"]
    );
}

function button_type_array()
{
    global $lang;
    return array("", $lang["in_current_window"], $lang["in_new_window"]);
}

function sql_type($type, $type_value, $mult_value, $size = 0)
{
    return \CB\CornyFunc::sql_type($type, $type_value, $mult_value, $size);
}

function form_select($type_names, $id_type)
{
    $types_count = count_cb($type_names);
    for ($i = 1; $i < $types_count; $i++) {
        $select .= "<option ";
        if ($i == $id_type) {
            $select .= "selected ";
        }
        $select .= "value='$i'>" . $type_names[$i] . "</option>";
    }
    return $select;
}

function form_num_select($all_fields, $field_num)
{
    global $lang;
    if (isset($_REQUEST['num'])) {
        $new_num = $_REQUEST['num'];
    } elseif (!isset($field_num)) {
        foreach ($all_fields as $one_field) {
            ;
        }
        $new_num = $one_field['num'] + 1;
    }
    if (isset($field_num)) {
        $select = "<option value=" . $field_num . ">" . $lang["no_change"] . "</option>";
    }
    $select .= "<option " . (($new_num == 1) ? "selected " : "") . "value=1>" . $lang["in_begin"] . "</option>";
    foreach ($all_fields as $one_field) {
        if (($one_field['num'] != $field_num) and ($one_field['num'] + 1 != $field_num)) {
            $select .= "<option ";
            if ($one_field['num'] + 1 == $new_num) {
                $select .= "selected ";
            }
            $select .= "value=" . ($one_field['num'] + 1) . ">" . $lang["after"] . " \"" . $one_field['name'] . "\"</option>";
        }
    }
    return $select;
}

function form_type_select($id_type, $hidden)
{
    $serv = array(10, 11, 12, 13);
    $type_names = type_array();
    $types_count = count_cb($type_names);
    for ($i = 1; $i < $types_count; $i++) {
        $option = '';
        if ($i == 8) {
            continue;
        } // Пропуск бывшего поля "Номер".
        if ((!in_array($i, $serv) and !$hidden) or (in_array($i, $serv) and $hidden)) {
            $option .= "<option ";
            if ($i == $id_type) {
                $option .= "selected ";
            }
            $option .= "value='$i'>" . $type_names[$i] . "</option>";
            if($i == 3) {
                $select = $option . $select;
            }
            else {
                $select .= $option;
            }
        }
    }
    return $select;
}

function form_fields_fgroups($table_id)
{
    $sqlQuery = "SELECT * FROM " . FIELDS_TABLE . " WHERE table_id=" . $table_id . " ORDER BY field_num";
    $result = sql_query($sqlQuery);
    while ($row = sql_fetch_array($result)) {
        $one_field['num'] = $row['field_num'];
        $one_field['name'] = $row['name_field'];
        $all_fields_fgroups[$one_field['num']] = $one_field;
    }
    $sqlQuery = "SELECT * FROM " . FIELD_GROUPS . " WHERE table_id=" . $table_id . " ORDER BY num";
    $result = sql_query($sqlQuery);
    while ($row = sql_fetch_array($result)) {
        $one_fgroup['num'] = $row['num'];
        $one_fgroup['name'] = $row['name'];
        $all_fields_fgroups[$one_fgroup['num']] = $one_fgroup;
    }
    ksort($all_fields_fgroups);
    return $all_fields_fgroups;
}

function form_field_num_select($all_fields_fgroups, $field_num)
{
    global $lang;
    if (isset($_REQUEST['field_num'])) {
        $new_num = $_REQUEST['field_num'];
    } elseif (!isset($field_num)) {
        foreach ($all_fields_fgroups as $one_elem) {
            ;
        }
        $new_num = $one_elem['num'] + 1;
    }

    if (isset($field_num)) {
        $select = "<option value=" . $field_num . ">" . $lang["no_change"] . "</option>";
    }
    $select .= "<option " . (($new_num == 1) ? "selected " : "") . "value=1>" . $lang["in_begin"] . "</option>";
    foreach ($all_fields_fgroups as $one_elem) {
        if (($one_elem['num'] != $field_num) and ($one_elem['num'] + 1 != $field_num)) {

            //обрехаем xss
            $one_elem['name'] = form_display($one_elem['name']);

            $select .= "<option ";
            if ($one_elem['num'] + 1 == $new_num) {
                $select .= "selected ";
            }
            $select .= "value=" . ($one_elem['num'] + 1) . ">" . $lang["after"] . " \"" . $one_elem['name'] . "\"</option>";
        }
    }
    return $select;
}

function form_field_id_select($table_fields, $field_id, $type_fields = "", $rel_fields_include = 0)
{
    $select = "<option value=0></option>";
    foreach ($table_fields as $one_field) {
        if (!$type_fields or ($one_field['type_field'] == $type_fields) or (('email' == $type_fields) && (($one_field['type_field'] == 3) || ($one_field['type_field'] == 7)))) {
            $select .= "<option ";
            if ($one_field['id'] == $field_id) {
                $select .= "selected ";
            }
            $select .= "value=" . $one_field['id'] . ">" . form_display($one_field['name_field']) . "</option>";
        }
        if ($rel_fields_include and $one_field['type_field'] == 5) {
            $rel_table = get_table($one_field['s_table_id']);
            $rel_table_fields = get_table_fields($rel_table);
            foreach ($rel_table_fields as $rel_field) {
                if (!$type_fields or ($rel_field['type_field'] == $type_fields) or (('email' == $type_fields) && (($rel_field['type_field'] == 3) || ($rel_field['type_field'] == 7)))) {
                    $select .= "<option ";
                    if ($one_field['id'] . "." . $rel_field['id'] === $field_id) {
                        $select .= "selected ";
                    }
                    $select .= "value=" . $one_field['id'] . "." . $rel_field['id'] . ">" . $one_field['name_field'] . "." . $rel_field['name_field'] . "</option>";
                }
            }
        }
    }
    return $select;
}

function form_type_table($link, $tableId = 0)
{
    $link = explode("|", $link);
    $all_tables = sql_type_table(0);
    foreach ($all_tables as $one_table) {
        if ($one_table['cat_id'] != $prev_cat) {
            if ($prev_cat) {
                $select .= "</optgroup>";
            }
            $sqlQuery = "SELECT * FROM " . CATS_TABLE . " WHERE id=" . $one_table['cat_id'];
            $result = sql_query($sqlQuery);
            $row = sql_fetch_assoc($result);
            $select .= "<optgroup label='" . form_display($row['name']) . "'>";
            $prev_cat = $one_table['cat_id'];
        }
        $select .= "<option ";
        if (!$tableId) {
            if ($one_table['id'] == $link[0]) {
                $select .= "selected ";
            }
        } else {
            if ($one_table['id'] == $tableId) {
                $select .= "selected ";
            }
        }
        $select .= "value='" . $one_table['id'] . "'>" . form_display($one_table['name_table']) . "</option>";
    }
    return $select;
}

function form_type_field($link, $exception = 0, $tableId = 0,$fieldId = 0)
{
    $link = explode("|", $link);
    if (!$fieldId && !$tableId) {
        $table = get_table($link[0]);
    } else {
        $table = get_table($tableId);
    }
    if (!$table) {
        return "";
    }
    $all_fields = get_table_fields($table);
    foreach ($all_fields as $one_field) {
        if ($one_field['id'] == $exception) {
            continue;
        }
        $select .= "<option ";
        if (!$fieldId && !$tableId) {
            if ($one_field['id'] == $link[1]) {
                $select .= "selected ";
            }
        } else {
            if ($one_field['id'] == $fieldId) {
                $select .= "selected ";
            }
        }
        $select .= "value='" . $one_field['id'] . "'>" . form_display($one_field['name_field']) . "</option>";
    }
    return $select;
}

function form_type_filter($link)
{
    global $lang;
    $select = "<option value='0'></option>";
    $link = explode("|", $link);
    $all_filters = sql_type_filter($link[0]);
    foreach ($all_filters as $one_filter) {
        $select .= "<option ";
        if ($one_filter['id'] == $link[2]) {
            $select .= "selected ";
        }
        $select .= "value='" . $one_filter['id'] . "'>" . $one_filter['name'] . "</option>";
    }
    return $select;
}

/** Получить внутреннее имя поля */
function form_int_name($field_id, $type_field = 0)
{
    return \CB\CornyService::getInnerFieldName($field_id, $type_field);
}

function sql_type_table($cat_id, $cache = 1)
{   global $lang;
    if ($cat_id) {
        $sqlQuery = "SELECT * FROM " . TABLES_TABLE . " WHERE cat_id=" . $cat_id . " ORDER BY table_num";
    } else {
        $sqlQuery = "SELECT * FROM " . CATS_TABLE . " a, " . TABLES_TABLE . " b WHERE a.id=b.cat_id and a.name!='' and a.name!='".$lang['Logs']."' ORDER BY a.num, b.table_num";
    }
    $result = sql_query($sqlQuery);
    while ($row = sql_fetch_assoc($result)) {
        $one_table = get_table($row['id'], $cache);
        $all_tables[] = $one_table;
    }
    if (!is_array($all_tables)) {
        $all_tables = array();
    }
    return $all_tables;
}

function sql_type_report($cat_id, $group_id = 0)
{
    if ($cat_id) {
        $sqlQuery = "SELECT * FROM " . REPORTS_TABLE . " WHERE cat_id=" . $cat_id . " ORDER BY num";
    } else {
        $sqlQuery = "SELECT * FROM " . CATS_TABLE . " a, " . REPORTS_TABLE . " b WHERE a.id=b.cat_id ORDER BY a.num, b.num";
    }
    $result = sql_query($sqlQuery);
    while ($row = sql_fetch_assoc($result)) {
        $one_report['id'] = $row['id'];
        $one_report['num'] = $row['num'];
        $one_report['name'] = form_display($row['name']);
        $one_report['code'] = form_display($row['code']);
        $one_report['form'] = form_display($row['form']);
        $one_report['help'] = form_display($row['help']);
        $sqlQuery = "SELECT * FROM " . ACC_REPORTS_TABLE . " WHERE group_id=" . $group_id . " AND report_id=" . $one_report['id'];
        $result2 = sql_query($sqlQuery);
        $row2 = sql_fetch_assoc($result2);
        $one_report['acc'] = $row2['access'];
        $all_reports[] = $one_report;
    }
    if (!is_array($all_reports)) {
        $all_reports = array();
    }
    return $all_reports;
}

function sql_type_button($table_id, $group_id = 0)
{
    global $config;
    if ($config['read_mode'] ?? 0) {
        return array();
    }
    $access_all_buttons = array();
    $result = sql_select_field(ACC_BUTTONS_TABLE, 'button_id, access', 'group_id = ', $group_id);
    while ($row = sql_fetch_assoc($result)) {
        $access_all_buttons[$row['button_id']] = $row['access'];
    }
    $calc_all_buttons = array();
    $result = sql_select(CALC_TABLE, 'table_id = ', $table_id, " AND name LIKE 'button %'");
    while ($row = sql_fetch_assoc($result)) {
        $calc_all_buttons[substr($row['name'], 7)] = $row;
    }
    $all_buttons = array();
    $result = sql_select(BUTTONS_TABLE, 'disabled = 0 AND table_id = ', $table_id, ' ORDER BY num');
    while ($row = sql_fetch_assoc($result)) {
        $one_button['id'] = $row['id'];
        $one_button['num'] = $row['num'];
        $one_button['name'] = form_display($row['name']);
        $one_button['help'] = form_display($row['help']);
        $one_button['type'] = form_display($row['type']);
        $one_button['width'] = form_display($row['width']);
        $one_button['height'] = form_display($row['height']);
        $one_button['javascript'] = $row['javascript'];
        $one_button['php_code'] = $calc_all_buttons[$one_button['id']]['calculate'];
        $one_button['construct'] = json_decode($calc_all_buttons[$one_button['id']]['construct_params'], 1);
        $one_button['scroll_bar'] = (int)$row['scroll_bar'];
        $one_button['color_mode'] = (int)$row['color_mode'];
        $one_button['color'] = form_display($row['color']);
        $one_button['text_color'] = form_display($row['text_color']);
        $one_button['acc'] = $access_all_buttons[$one_button['id']];
        $one_button['group_id'] = (int)$row['group_id'];
        $one_button['confirm_text'] = $row['confirm_text'];
        $all_buttons[] = $one_button;
    }
    if (!is_array($all_buttons)) {
        $all_buttons = array();
    }
    return $all_buttons;
}

function get_btns_groups($table_id, $table, $line, $group_id = 0)
{
    global $config;
    if ($config['read_mode'] ?? 0) {
        return array();
    }
    $all_buttons = array();
    $access_all_buttons = array();
    $result = sql_query("SELECT button_id, access FROM " . ACC_BUTTONS_TABLE . " WHERE group_id=" . $group_id);
    while ($row = sql_fetch_assoc($result)) {
        $access_all_buttons[$row['button_id']] = $row['access'];
    }
    $result = sql_query("SELECT * FROM " . BUTTONS_TABLE . ' AS t1 LEFT JOIN ' . BUTTON_COLORS . ' AS t2 ON t1.color = t2.color_name ' . ($table_id ? (" WHERE disabled=0 AND table_id=" . $table_id) : "") . " ORDER BY num");
    while ($row = sql_fetch_assoc($result)) {
        if (!test_allow_button_line($table, $line, $row['id'], $access_all_buttons[$row['id']])) {
            continue;
        }
        $one_button['id'] = $row['id'];
        $one_button['num'] = $row['num'];
        $one_button['name'] = form_display($row['name']);
        $one_button['help'] = form_display($row['help']);
        $one_button['type'] = form_display($row['type']);
        $one_button['width'] = form_display($row['width']);
        $one_button['height'] = form_display($row['height']);
        $one_button['javascript'] = $row['javascript'];
        $one_button['php_code'] = $row['php_code'];
        $one_button['scroll_bar'] = (int)$row["scroll_bar"];
        $one_button['color_mode'] = (int)$row["color_mode"];
        if ($row["color_mode"] == 0) {
            $one_button['color'] = form_display($row['background_color']);
            $one_button['text_color'] = form_display($row['word_color']);
        } else {
            $one_button['color'] = form_display($row['color']);
            $one_button['text_color'] = form_display($row['text_color']);
        }
        $one_button['acc'] = $access_all_buttons[$one_button['id']];
        $one_button['group_id'] = (int)$row["group_id"];
        $one_button['confirm_text'] = $row['confirm_text'];
        $one_button['table_id'] = $row['table_id'];
        $one_button['table'] = $table;
        $one_button['line'] = $line;
        $all_buttons[] = $one_button;
    }
    if (!is_array($all_buttons)) {
        $all_buttons = array();
    }

    //все группы доп.действий таблицы, кроме пустых
    $buttonGroupsQuery = sql_query("SELECT * FROM " . BUTTON_GROUPS . ' AS t1 LEFT JOIN ' . BUTTON_COLORS . ' AS t2 ON t1.color = t2.color_name ' . ($table_id ? (" WHERE disabled=0 AND table_id=" . $table_id) : "") . " ORDER BY num ASC");
    while ($buttonGroupsResult = sql_fetch_assoc($buttonGroupsQuery)) {
        if (array_search($buttonGroupsResult['id'], array_column($all_buttons, 'group_id', 'num'))) {
            $one_group['id'] = $buttonGroupsResult['id'];
            $one_group['num'] = $buttonGroupsResult['num'];
            $one_group['name'] = form_display($buttonGroupsResult['name']);
            $one_group['color_mode'] = (int)$buttonGroupsResult["color_mode"];
            if ($buttonGroupsResult["color_mode"] == 0) {
                $one_group['color'] = form_display($buttonGroupsResult['background_color']);
                $one_group['text_color'] = form_display($buttonGroupsResult['word_color']);
            } else {
                $one_group['color'] = form_display($buttonGroupsResult['color']);
                $one_group['text_color'] = form_display($buttonGroupsResult['text_color']);
            }
            $all_groups[] = $one_group;
        }
    }
    $resultArray = [0 => $all_buttons, 1 => $all_groups];
    return $resultArray;
}

function get_users_values($filter, bool $force = false) {
    global $users_values, $user;
    if (is_array($users_values) && count($users_values) && !$force) {
        ;
    }else{
        $users_values = array();
        $v_result = sql_select_field(USERS_TABLE, "id, fio as value_name, group_id", "arc=0");
        while ($v_row = sql_fetch_assoc($v_result)) {
            $users_values[$v_row['group_id']][$v_row['id']] = $v_row['value_name'];
        }
    }
    if(!empty($filter)){
        foreach ($filter as $id_group) {
            if($id_group == '{current}') {
                $id_group = $user['id'];
            }
            foreach ($users_values[$id_group] as $user_id => $one_user){
                $return_values[$user_id] = $one_user;
            }
        }
    } else {
        foreach ($users_values as $one_user){
            foreach($one_user as $id => $value){
                $return_values[$id] = $value;
            }
        }
    }
    return $return_values;
}

function get_groups_values($filter) {
    global $groups_values;
    if (!(is_array($groups_values) && count($groups_values))) {
        $groups_values = array();
        $v_result = sql_select_field(GROUPS_TABLE, "id, name as value_name", "hidden=0");
        while ($v_row = sql_fetch_assoc($v_result)) {
            $groups_values[$v_row['id']] = $v_row['value_name'];
        }
    }
    if(!empty($filter)) {
        $filter = explode(',', $filter);
        foreach($filter as $id_group) {
            $return_values[$id_group] = $groups_values[$id_group];
        }
    } else {
        $return_values = $groups_values;
    }
    return $return_values;
}

function get_table_fields_type($table_id, $type = null, $no_system = false, $no_type = null)
{
    if (!$table_id) {
        generate_error('Invalid table_id: ' . $table_id);
        exit;
    }
    $sql = '';
    if ($type !== null) {
        if (is_array($type)) {
            $sql .= ' AND type_field IN (' . implode(', ', $type) . ')';
        } else {
            $sql .= ' AND type_field = ' . (int)$type;
        }
    }

    if ($no_system === true) {
        $sql .= ' AND type_field NOT IN (10,11,12,13)';
    }
    if ($no_type !== null) {
        if (is_array($no_type)) {
            $sql .= ' AND type_field NOT IN (' . implode(', ', $no_type) . ')';
        } else {
            $sql .= ' AND type_field != ' . (int)$no_type;
        }
    }
    $table_fields = array();
    $result = sql_query('SELECT * FROM ' . FIELDS_TABLE . ' WHERE table_id = ' . $table_id . $sql . ' ORDER BY field_num');
    while ($row = sql_fetch_assoc($result)) {
        $one_field = array();
        $one_field['id'] = $row['id'];
        $one_field['name_field'] = $row['name_field'];
        $one_field['type_field'] = $row['type_field'];
        $one_field['type_value'] = $row['type_value'];
        $one_field['sub_type_field'] = $row['sub_type_field'];
        $one_field['int_name'] = form_int_name($one_field['id'], $one_field['type_field']);
        $one_field['mult_value'] = $row['mult_value'];
        if ($one_field['type_field'] == 4) {
            $field_values = explode("\r\n", $row['type_value']);
            foreach ($field_values as $one_value) {
                $one_field['field_values'][$one_value] = $one_value;
            }
        }
        if ($one_field['type_field'] == 7) {
            $result2 = sql_select_field(USERS_TABLE, "id, fio", "arc = 0");
            while ($row2 = sql_fetch_assoc($result2)) {
                $one_field['field_values'][$row2['id']] = $row2['fio'];
            }
        }
        $table_fields[$one_field['id']] = $one_field;
    }
    if (!count_cb($table_fields)) {
        return false;
    }
    return $table_fields;
}

function get_table_fields(& $table, $cache = 1)
{
    global $user, $tables_cache, $config, $lang; // для вычисления прав пользователя
    $table_id = (int)$table['id'];
    $group_id = $user['group_id'];
    if (!$table_id) {
        generate_error('Invalid table_id: ' . $table_id);
        exit;
    }
    // Если есть в кеше возвращаем его
    if (($tables_cache[$table_id]['table_fields']) && ($cache)) {
        $table['link_tables'] = $tables_cache[$table_id]["link_tables"];
        $table['table_fields'] = $tables_cache[$table_id]["table_fields"];
        $table['int_names'] = $tables_cache[$table_id]["int_names"];
        return $tables_cache[$table_id]['table_fields'];
    }

    // Выбираем доп поля информацинные
    $array_fields_links_show = array();
    $result = sql_query("SELECT show_field, field_id, is_ico_field FROM " . FIELDS_LINKS_SHOW_TABLE . " ORDER BY id");
    while ($row = sql_fetch_assoc($result)) {
        $array_fields_links_show[$row['field_id']][$row['is_ico_field']][] = $row['show_field'];
    }

    $type_names = type_array();
    $result = sql_query("SELECT * FROM " . FIELDS_TABLE . " WHERE table_id=" . $table_id . " ORDER BY field_num");
    $table_fields = array();
    $i = 0;
    $js_repl_arr_src = array("\r\n", '\\', "'", "</script>");
    $js_repl_arr_dst = array('\r\n', '\\\\', "\\'", "<\/script>");
    while ($row = sql_fetch_assoc($result)) {
        $one_field = array();
        $one_field['id'] = (int)$row['id'];
        $one_field['table_id'] = $row['table_id'];
        $one_field['field_num'] = $row['field_num'];
        $one_field['name_field'] = $row['name_field'];
        $one_field['type_field'] = $row['type_field'];
        // $one_field['sub_type_field'] = $row['sub_type_field'];   // who changed
        $one_field['type_name'] = $type_names[$row['type_field']];
        $one_field['type_value'] = $row['type_value'];
        $one_field['default_value'] = (string)$row['default_value'];
        $one_field['type_value_js'] = str_replace($js_repl_arr_src, $js_repl_arr_dst, $one_field['type_value']);
        $one_field['default_value_js'] = str_replace($js_repl_arr_src, $js_repl_arr_dst, $one_field['default_value']);
        $one_field['javascript'] = $row['javascript'];
        $one_field['help'] = $row['help'];
        $one_field['main'] = $row['main'];
        $one_field['uniq_field'] = $row['uniq_field'];
        $one_field['summa'] = $row['summa'];
        $one_field['average'] = $row['average'];
        $one_field['hidden'] = $row['hidden'];
        $one_field['width'] = $row['width'] ? ($row['width'] > $config['table_other_max_width'] ? $config['table_other_max_width'] : ($row['width'] < $config['table_other_min_width'] ? ($row['type_field'] == 1 || $row['type_field'] == 10 ? ($row['width'] < $config['table_number_min_width'] ? $config['table_number_min_width'] : $row['width']) : $config['table_other_min_width']) : $row['width'])) : $row['width'];
        $one_field['prefix'] = $row['prefix'];
        $one_field['postfix'] = $row['postfix'];
        $one_field['disable_link'] = $row['disable_link'];
        if ($table['group_field'] == $one_field['id']) {
            $one_field["group_field"] = 1;
        } else {
            $one_field["group_field"] = 0;
        }
        $one_field['mult_value'] = $row['mult_value'];
        $one_field['fast_edit'] = $row['fast_edit'];
        $one_field['pp'] = $i;
        $i++;
        $one_field['int_name'] = form_int_name($one_field['id']);
        $one_field['summa'] = 0;
        $one_field['average'] = 0;
        $one_field['fix_search_on'] = $row['fix_search_on'];
        $one_field['fix_search_mult'] = $row['fix_search_mult'];
        $one_field['no_outliers'] = $row['no_outliers'];
        $one_field['scw_set'] = $row['scw_set'] ? unserialize($row['scw_set']) : array();
        $one_field['owner_id'] = $row['owner_id'];
        $one_field['phone_type'] = $row['phone_type'];
        $one_field['placeholder'] = $row['placeholder'];
        $one_field['crypt'] = $row['crypt'];
        $one_field['reduce'] = $row['reduce'];
        if ($one_field['reduce'] == 0) {
            $one_field['full_value_table'] = 1;
        }
        $one_field['uniq_addit_fields'] = $row['uniq_addit_fields'] ? explode(',', $row['uniq_addit_fields']) : [];

        // Отображаемое имя поля
        $one_field['disp_name_field'] = form_display($lang['conf'][$one_field['name_field']] ?: $one_field['name_field']);
        if ($config['reduce_headers']) {
            $one_field['reduce_name_field'] = mb_substr($one_field['disp_name_field'], 0, $config['reduce_headers']);
        } else {
            $one_field['reduce_name_field'] = $one_field['disp_name_field'];
        }
        if ($one_field['reduce_name_field'] != $one_field['disp_name_field']) {
            $one_field['reduce_name_field'] .= "...";
        }

        // Заполняем свойства полей, зависящие от его типа
        if ($one_field['type_field'] == 1) { // Поле число
            if (strpos($one_field['type_value'], 'summa')) {
                $one_field['summa'] = 1;
            }
            if (strpos($one_field['type_value'], 'average')) {
                $one_field['average'] = 1;
            }
            if (strpos($one_field['type_value'], 'autonumber')) {
                $one_field['autonumber'] = 1;
            }
            $ta = explode("\r\n", $one_field['type_value']);
            $ta = explode("|", $ta[0]);
            $one_field['type_value'] = $ta[0]; // Приводим к старому виду - оставляем только формат числа
            $one_field['min_dig'] = $ta[1];
            $ta = explode('/', $one_field['type_value']);
            $one_field['all_dig'] = $ta[0];
            $one_field['dec_dig'] = $ta[1];
        }
        if ($one_field['type_field'] == 2 or $one_field['type_field'] == 12) {
            $one_field['display_time'] = $one_field["type_value"];
        }
        if ($one_field['type_field'] == 3) { // Поле текст
            if (strpos($one_field['type_value'], 'f_v_t')) {
                $one_field['full_value_table'] = 1;
            }
            if (strpos($one_field['type_value'], 'view_html')) {
                $one_field['view_html'] = 1;
            }
            if (strpos($one_field['type_value'], 'html_editor')) {
                $one_field['html_editor'] = 1;
            }
            if (strpos($one_field['type_value'], 'hyperlink')) {
                $one_field['hyperlink'] = 1;
            }
            if (strpos($one_field['type_value'], 'extra_large')) {
                $one_field['extra_large_size'] = 1;
            }
            if (strpos($one_field['type_value'], 'template')) {
                $tmp = explode('{template:', form_display($row['type_value']));
                $tmp = explode("}\r\n", $tmp[1]);
                $tmp[0] = str_replace('replacement of an opening brace', '{', $tmp[0]);
                $tmp[0] = str_replace('replacement of the closing brace', '}', $tmp[0]);
                $one_field['template'] = $tmp[0];

                $tmp = explode('{split_templ_mask:', form_display($row['type_value']));
                $tmp = explode("}\r\n", $tmp[1]);
                $one_field['split_templ_mask'] = $tmp[0];
                unset($tmp);
            }
        }
        if ($one_field['type_field'] == 4 or $one_field['type_field'] == 13) { // Поле список, либо статус
            $one_field['list_values'] = explode("\r\n", $one_field['type_value']);
        }
        if ($one_field['type_field'] == 5) {  // Если поле связь
            $ta = explode("|", $one_field['type_value']);
            list ($s_table_id, $s_field_id, $s_filter_id, $s_show_field_name, $s_show_field_inline) = $ta;
            $one_field["s_table_id"] = $s_table_id; // Таблица на которую указывает поле связи
            $one_field["s_field_id"] = $s_field_id; // Поле на которое указывает поле связи
            $one_field["s_filter_id"] = $s_filter_id; // Поле связи фильтруется с помощью фильтра или значения
            $one_field["s_show_field_name"] = $s_show_field_name;     // Флаг выводить имена информационных полей
            $one_field["s_show_field_inline"] = $s_show_field_inline; // Флаг выводить в одну строку, информационные поля
            $one_field["links_also_show"] = $array_fields_links_show[$one_field["id"]][0];
            $one_field["links_also_show_ico"] = $array_fields_links_show[$one_field["id"]][1];
        }
        if ($one_field['type_field'] == 6) {  // Если поле файл
            $ta = explode("|", $one_field['type_value']);
            list ($one_field['file_types'], $one_field['max_size'], $one_field['show_file']) = $ta;
            $file_types = $one_field['file_types'] ? explode(",", strtolower($one_field['file_types'])) : "";
            unset($one_field['file_types']);
            if ($file_types) {
                foreach ($file_types as $file_type) {
                    $one_field['file_types'][$file_type] = trim($file_type);
                }
            }

        }
        if ($one_field['type_field'] == 7 or $one_field['type_field'] == 11) { // Поле пользователь
            $one_field['groupe'] = $one_field['type_value'] ? explode("|", $one_field['type_value']) : array();
            $values = array();
            $one_field['s_list_values'] = array();
            $values = get_users_values($one_field['groupe']);
            $one_field['s_list_values'] = $values;
        }
        if ($one_field['type_field'] == 14) { // группа
            $ta = explode("|", $one_field['type_value']);
            $one_field['groupe'] = $ta[0];
            $one_field['use_rights'] = $ta[1];
            $one_field['display_groups'] = $ta[2];
            $values = array();
            $one_field['s_list_values'] = array();
            $values = get_groups_values($one_field['display_groups']);
            $one_field['s_list_values'] = $values;
        }
        if ($one_field['type_field'] == 9) {
            list (
                $one_field['img_size'],
                $one_field['max_size'],
                $one_field['orientation'],
                $one_field['maximum_size'],
                $one_field['max_height'],
                $one_field['max_width'],
                $one_field['not_crop_preview']
            ) = explode('|', $one_field['type_value']);
            list (
                $one_field['img_size_x'],
                $one_field['img_size_y']
            ) = explode('x', $one_field['img_size']);
            $one_field['file_types'] = array(
                'jpg' => 'jpg',
                'jpeg' => 'jpeg',
                'gif' => 'gif',
                'png' => 'png',
                'tiff' => 'tiff',
                'raw' => 'raw'
            );
            $gd_info = gd_info();
            if ($gd_info['WebP Support']) {
                $one_field['file_types']['webp'] = 'webp';
            }
            if ($gd_info['AVIF Support']) {
                $one_field['file_types']['avif'] = 'avif';
            }
            if ($gd_info['BMP Support']) {
                $one_field['file_types']['bmp'] = 'bmp';
            }
        }

        $table_fields[$one_field['id']] = $one_field;
    }

    // Выбираем доступ
    if ($table['access']) {
        $result2 = sql_select(ACC_FIELDS_TABLE, "group_id=", $user["group_id"], " and table_id=" . $table_id);
        while ($row2 = sql_fetch_assoc($result2)) {
            $field_id = $row2['field_id'];
            if (!$table_fields[$field_id]) {
                continue;
            } // Реально поля не существует
            $table_fields[$field_id]['view'] = $row2['view'] > 0;
            $table_fields[$field_id]['view_tb'] = $row2['view_tb'] > 0;
            $table_fields[$field_id]['view_sub'] = $row2['view_sub'] > 0;
            $table_fields[$field_id]['view_edit'] = $row2['view_edit'] > 0;
            $table_fields[$field_id]['view_add'] = $row2['view_add'] > 0;
            $table_fields[$field_id]['read'] = $row2['read_acc'] > 0;
            $table_fields[$field_id]['write'] = $row2['write_acc'] > 0;
        }
    }

    if (!is_array($table_fields)) {
        $table_fields = array();
    }

    // Заполнить информацию о связных таблицах
    $link_tables = array();
    foreach ($table_fields as $one_field) {
        if ($one_field['type_field'] == 5) { // Поле связи
            $link_tables[$one_field['id']] = $one_field['s_table_id'];
        }
    }

    // Заполнить связи между полями связи используемыми как фильтры
    foreach ($table_fields as $one_field) {
        $type_field = $one_field["type_field"];
        $type_value = $one_field["type_value"];
        if ($type_field == 5) {
            if ($one_field['s_filter_id'] < 0) // Фильтр является полем
            {
                $f_fld = -$one_field['s_filter_id'];
                $table_fields[$one_field["id"]]["parent_link_field"] = $f_fld; // Выставляем фильтруемому полю явное указание что оно фильтруется
                $table_fields[$f_fld]["child_link_field"] = $one_field["id"]; // Выставляем полю фильтратору, что оно фильтрует определенное поле

                $table_fields[$f_fld]["child_link_field_arr"][] = $one_field["id"]; //когда по 1 полю фильтруется несколько полей

                if ($table_fields[$f_fld]['s_table_id'] != $one_field['s_table_id']) {  // Фильтрация по коссвенной таблице, поле фильтратор находиться в другой таблице
                    $t_fld = $table_fields[$f_fld]['s_field_id']; // Поле на которое ссылается фильтрующее поле
                    // Выбираем id таблицы поля
                    $rlst = sql_select_field(FIELDS_TABLE, 'table_id', 'id=', $t_fld);
                    $t_tlb = sql_fetch_assoc($rlst);
                    $t_tlb = $t_tlb['table_id'];

                    // Ищем ссылку на данное поле среди полей таблицы $one_field['s_table_id']
                    $rlst = sql_query("SELECT id FROM " . FIELDS_TABLE . " WHERE table_id=" . $one_field['s_table_id'] . " and type_field=5 and type_value LIKE '$t_tlb|$t_fld|%'");
                    $filter_field = sql_fetch_assoc($rlst);
                    $table_fields[$one_field["id"]]["s_field_filter_id"] = $filter_field['id'];
                } else {  // Фильтрация по той же самой таблице
                    $l_table = get_table($one_field['s_table_id']); // Таблица на которое ссылается поле связь
                    $table_fields[$one_field["id"]]["s_field_filter_id"] = $l_table['first_link_field']; // Первое поле в таблице на которое ссылается поле связь
                }
            };
        }
    }
    // Заполнить информацию об обратной связи имени поля и его id
    $int_names_tables = array();
    foreach ($table_fields as $one_field) {
        $int_names_tables[$one_field["int_name"]] = $one_field['id'];
    }
    $table['int_names'] = $int_names_tables;
    $table['link_tables'] = $link_tables;
    $table['table_fields'] = $table_fields;
    if ($cache) // включен кеш
    {
        if (!$tables_cache[$table_id]) {
            $tables_cache[$table_id] = $table;
        } else {
            $tables_cache[$table_id]['table_fields'] = $table_fields;
            $tables_cache[$table_id]['link_tables'] = $link_tables;
            $tables_cache[$table_id]['int_names'] = $int_names_tables;
        }
        if (($config['xcache']) && (!$user["is_root"])) {
            xcache_set("table_info_" . $group_id . "_" . $table_id, $table, 360);
        }
    }
    return $table_fields;
}

function sql_type_filter($table_id, $group_id = 0)
{
    $sqlQuery = "SELECT * FROM " . FILTERS_TABLE . " WHERE table_id='$table_id' ORDER BY num";
    $result = sql_query($sqlQuery);
    while ($row = sql_fetch_assoc($result)) {
        $one_filter['id'] = $row['id'];
        $one_filter['table_id'] = $row['table_id'];
        $one_filter['name'] = form_display($row['name']);
        $one_filter['value'] = form_display($row['value']);

        $sqlQuery = "SELECT * FROM " . ACC_FILTERS_TABLE . " WHERE group_id=" . $group_id . " AND filter_id=" . $one_filter['id'];
        $result2 = sql_query($sqlQuery);
        $row2 = sql_fetch_assoc($result2);
        $one_filter['acc'] = $row2['access'];
        $one_filter['def'] = $row2['def_use'];
        $all_filters[] = $one_filter;
    }
    if (!is_array($all_filters)) {
        $all_filters = array();
    }
    return $all_filters;
}

// Тест, является ли поле связи Фильтром?
function test_field_is_filter($field_id)
{
    $sqlQuery = "SELECT id, type_value FROM " . FIELDS_TABLE . " WHERE type_value LIKE '%|-$field_id%' and type_field=5";
    $result = sql_query($sqlQuery);
    while ($row = sql_fetch_assoc($result)) { // доп проверка
        // -$field_id должно быть третьим параметром
        $ta = explode("|", $row["type_value"]);
        list ($t1, $t2, $filter_id, $t3, $t4) = $ta;
        if ($filter_id == "-$field_id") {
            return 1;
        };
    }
    return 0;
}

// Отсортировать поля, в необходимом порядке
function sort_by_field_num($a, $b)
{
    if ($a["field_num"] == $b["field_num"]) {
        return $a["id"] > $b["id"];
    }
    return $a["field_num"] > $b["field_num"];
}

// Функция суммы прописью
// number - число
// currency - имя валюты (по умолчанию - из текущего lang)
// cents - имя цента (по умолчанию - из текущего lang)
// caps - первая буква заглавная (по умолчанию - нет)
// female_cur - имя валюты женского рода (по умолчанию - нет)
// female_cents - имя цента женского рода (по умолчанию - нет)
function num2str($number, $currency = "", $cents = "", $caps = 0, $female_cur = 0, $female_cents = 0, $lang_name = "")
{
    global $config, $lang;

    if ($lang_name) {
        $cur_lang = $lang;
        include $config['site_path'] . "/lang/" . $lang_name . ".php";
    }

    if ($currency == "") {
        $namecur[1] = $lang['cur_1'];
        $namecur[2] = $lang['cur_2'];
        $namecur[3] = $lang['cur_3'];
        $female_cur = $lang['cur_f'];
    } elseif ($currency != "none") {
        $namecur[1] = $currency;
        $namecur[2] = $currency;
        $namecur[3] = $currency;
    }

    if ($cents == "") {
        $namecents[1] = $lang['cents_1'];
        $namecents[2] = $lang['cents_2'];
        $namecents[3] = $lang['cents_3'];
        $female_cents = $lang['cents_f'];
    } elseif ($cents != "none") {
        $namecents[1] = $cents;
        $namecents[2] = $cents;
        $namecents[3] = $cents;
    }

    $rub = abs((int)$number);
    if (strpos($number, ".")) {
        $kop = substr($number, strpos($number, ".") + 1);
        if (strlen($kop) == 1) {
            $kop .= "0";
        }
        $kop = (int)$kop;
    } else {
        $kop = 0;
    }

    if ($rub >= 1000000000) {
        $many = 0;
        semantic((int)($rub / 1000000000), $s1, $many, $lang['mrd_f']);
        $s .= $s1 . $lang['mrd_' . $many] . " ";
        $rub %= 1000000000;
        if ($rub == 0) {
            $s .= $namecur[3];
        }
    }

    if ($rub >= 1000000) {
        $many = 0;
        semantic((int)($rub / 1000000), $s1, $many, $lang['mil_f']);
        $s .= $s1 . $lang['mil_' . $many] . " ";
        $rub %= 1000000;
        if ($rub == 0) {
            $s .= $namecur[3];
        }
    }

    if ($rub >= 1000) {
        $many = 0;
        semantic((int)($rub / 1000), $s1, $many, $lang['tho_f']);
        $s .= $s1 . $lang['tho_' . $many] . " ";
        $rub %= 1000;
        if ($rub == 0) {
            $s .= $namecur[3];
        }
    }

    if ($rub != 0) {
        $many = 0;
        semantic($rub, $s1, $many, $female_cur);
        $s .= $s1 . $namecur[$many] . " ";
    } elseif (!$s) {
        $s .= $lang['zero'] . " " . $namecur[3];
    }

    $s = trim($s); // убрал лишний пробел
    if ($cents !== "none") {
        $many = 0;
        semantic($kop, $s1, $many, $female_cents);
        $s .= " " . sprintf("%02.0f ", $kop) . $namecents[$many];
    }

    $s = trim($s);
    if ($number < 0) {
        $s = $lang['minus'] . ' ' . $s;
    }
    if ($caps) {
        $s = mb_strtoupper(mb_substr($s, 0, 1)) . mb_substr($s, 1);
    }

    if ($lang_name) {
        $lang = $cur_lang;
    }

    return $s;
}

function semantic($i, &$words, &$fem, $f)
{
    global $lang;
    $words = "";
    $fl = 0;
    if ($i >= 100) {
        $jkl = (int)($i / 100);
        $words .= $lang['num_' . ($jkl * 100)] . " ";
        $i %= 100;
    }
    if ($i >= 20) {
        $jkl = (int)($i / 10);
        $words .= $lang['num_' . ($jkl * 10)] . " ";
        $i %= 10;
        $fl = 1;
    }
    switch ($i) {
        case 1:
            $fem = 1;
            break;
        case 2:
        case 3:
        case 4:
            $fem = 2;
            break;
        default:
            $fem = 3;
            break;
    }
    if ($i) {
        if ($i < 3 && $f == 1) {
            $words .= $lang['fem_num_' . $i] . " ";
        } else {
            $words .= $lang['num_' . $i] . " ";
        }
    }
}

function data2str($date, $date_format = "")
{
    global $lang;
    if (!$date_format) {
        $date_format = $lang['date_full_format'];
    }
    return str_replace(date("F", $date), $lang[date("F", $date)], date($date_format, $date));
}

function utf2eng($str, $replace_symbols = 1)
{
    $utf = ['а', 'б', 'в', 'г', 'д', 'е', 'ё', 'ж',  'з', 'и', 'й', 'к', 'л', 'м', 'н', 'о', 'п', 'р', 'с', 'т', 'у', 'ф', 'х', 'ц', 'ч',  'ш',  'щ',   'ъ', 'ь', 'ы', 'э', 'ю',  'я',  'А', 'Б', 'В', 'Г', 'Д', 'Е', 'Ё', 'Ж',  'З', 'И', 'Й', 'К', 'Л', 'М', 'Н', 'О', 'П', 'Р', 'С', 'Т', 'У', 'Ф', 'Х', 'Ц', 'Ч',  'Ш',  'Щ',   'Ь', 'Ъ', 'Ы', 'Э', 'Ю',  'Я' ];
    $eng = ['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'];
    $str = str_replace($utf, $eng, $str);
    if ($replace_symbols) {
        $sym = ['`', '~', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '-', '+', '=', '[', ']', '{', '}', ':', ';', '"', "'", '|', '\\', '/', '?', ',', '.', '<', '>', '№', ' '];
        $str = str_replace($sym, '_', $str);
        while (strpos($str, '__') !== false) {
            $str = str_replace('__', '_', $str);
        }
        $str = trim($str, '_');
    }
    return $str;
}

function eng2utf($str)
{
    $eng = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',  'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',  'Y', 'Z'];
    $utf = ['а', 'б', 'ц', 'д', 'е', 'ф', 'г', 'х', 'и', 'й', 'к', 'л', 'м', 'н', 'о', 'п', 'к', 'р', 'с', 'т', 'у', 'в', 'в', 'кс', 'й', 'з', 'А', 'Б', 'Ц', 'Д', 'Е', 'Ф', 'Г', 'Х', 'И', 'Й', 'К', 'Л', 'М', 'Н', 'О', 'П', 'К', 'Р', 'С', 'Т', 'У', 'В', 'В', 'Кс', 'Й', 'З'];
    $str = str_replace($eng, $utf, $str);
    return $str;
}

function run_query($sqlQuery)
{
    global $lang;
    $sqlQuery = back_apostrophe_replace($sqlQuery);
    $result = @sql_query($sqlQuery);
    if (!$result) {
        $err = debug_backtrace();
        $file = substr(str_replace("\\", "/", $err[0]['file']),
            strrpos(str_replace("\\", "/", $err[0]['file']), "/") + 1);
        $line = $err[0]['line'];
        die("<b class='error_convert'>" . $lang['error_convert'] . "</b><br><br><b>SQL</b>: " . $sqlQuery . "<br><b>Error</b>: " . sql_error() . "<br><b>File</b>: " . $file . ", str " . $line);
    }
    return $result;
}

/**
 * Отправка E-mail.
 * Функция добавляет письмо в очередь рассылки (см. send_all_mail) и возвращает uid письма в очереди.
 *
 * @param [type] $subject           тема письма
 * @param [type] $body              тело письма
 * @param [type] $to                кому
 * @param string $from              от кого, адрес
 * @param string $from_name         от кого, имя
 * @param string $reply_to          кому отвечать
 * @param string $content_type      тип контента
 * @param string $charset           кодировка
 * @param array $headers            массив заголовков письма
 * @param array $attach_files       массив прикрепленных файлов
 * @param integer $smtp_server_id   через какой smtp сервер проводить рассылку (по умолчанию - любой)
 * @param integer $thread_id        id потока писем (по умолчанию - системный), возвращается функцией create_mail_thread
 * @param integer $line_id          id записи таблицы
 * @param integer $user_id          пользователь
 * @param integer $unsubscribe      отписка
 * @return void
 */
function sendmail(
    $subject,
    $body,
    $to,
    $from = '',
    $from_name = '',
    $reply_to = '',
    $content_type = 'text/html',
    $charset = 'utf-8',
    $headers = array(),
    $attach_files = array(),
    $smtp_server_id = -1,
    $thread_id = 1,
    $line_id = 0,
    $user_id = 0,
    $unsubscribe = 0
) {
    $thread = sql_select_array(MAIL_THREADS, 'id = ', $thread_id);
    if (!$thread && $thread_id == 1) { // отсутствует системный поток, восстанавливаем
        sql_insert(MAIL_THREADS, ['id' => 1]);
    } elseif ($thread_id == 1 && $thread['name'] != '') { // у системного потока некорректное имя, исправляем
        sql_update(MAIL_THREADS, ['name' => ''], 'id = 1');
    } elseif (!$thread || $thread['deleted']) { // поток не существует или был удален, не добавляем письмо в очередь
        return false;
    }

    global $config, $user;

    $ins_mail['thread_id'] = $thread_id;
    $ins_mail['add_time'] = date('Y-m-d H:i:s');
    if (!$user_id) {
        $ins_mail['user_id'] = $user['id'];
    } else {
        $ins_mail['user_id'] = $user_id;
    }
    $ins_mail['line_id'] = $line_id;
    $ins_mail['subject'] = $subject;
    $ins_mail['body'] = $body;
    $ins_mail['from_mail'] = $from;
    $ins_mail['from_name'] = $from_name;
    $ins_mail['reply_to'] = $reply_to;
    $ins_mail['content_type'] = $content_type;
    $ins_mail['charset'] = $charset ?: "utf-8";
    $ins_mail['smtp_server_id'] = $smtp_server_id;
    $to_arr = explode(',', $to);
    if ($config['no_split_recipients'] && count_cb($to_arr) > 1) {
        $to_arr = [$to]; // одно письмо на нескольких получателей
        $unsubscribe = 0; // не поддерживается в этом режиме
    }
    foreach ($to_arr as $email) {
        if ($unsubscribe) { // прибавка к письму ссылки для отписки
            if (!sql_fetch_row(sql_select_field(UNSUBSCRIBE_TABLE, 'disabled', "email = '", filter_email($email), "'"))[0]) {
                if ($config['unsubscribe_url']) {
                    $unsubscribe_url = $config['unsubscribe_url'];
                } elseif ($config['type'] == 'LOCAL') {
                    $unsubscribe_url = 'https://saas.clientbase.ru';
                } else {
                    $unsubscribe_url = $config['site_url'];
                }
                $code = key_decrypt(file_get_contents($config['site_path'] . '/runtime/key.php'));
                $key_code = md5(substr($code, 16, 14));
                $l_salt = md5($key_code . $config['dbuser'] . $config['dbpass']);
                $l_hash = md5($l_salt . filter_email($email));
                $unsubscribe_url .= "/unsubscribe.php?email=" . filter_email($email) . "&hash=$l_hash&salt=$l_salt&lang=" . $config['lang'];
                if (strpos($body, '[[unsubscribe_url]]')) {
                    $ins_mail['body'] = str_replace('[[unsubscribe_url]]', $unsubscribe_url, $body);
                } else {
                    if ($content_type == 'text/plain') {
                        $unsub_text = "\n\n\n" . $lang['mail_unsubscribe_text'] . ": " . $unsubscribe_url;
                    }
                    if ($content_type == 'text/html') {
                        $unsub_text = "<div><a href='$unsubscribe_url'>" . \CB\Core::get(\CB\Core::COMMON_CONTEXT)->lang("mail_unsubscribe_text") . "</a></div>";
                    }
                    $ins_mail['body'] = $body . $unsub_text;
                }
                $headers['List-Unsubscribe'] = '<' . $unsubscribe_url . '>';
            }
        }
        $ins_mail['email'] = trim($email);
        $ins_mail['headers'] = serialize($headers);
        $mail_id = sql_insert(MAIL_QUEUE, $ins_mail);
        $uid = time() . $mail_id;
        sql_update(MAIL_QUEUE, array('uid' => $uid), 'id = ', $mail_id);
        foreach ($attach_files as $file) {
            while ($file['content']) {
                $ins_file['mail_id'] = $mail_id;
                $ins_file['name'] = $file['name'];
                $ins_file['type'] = $file['type'];
                $ins_file['disp'] = $file['disp'];
                $ins_file['cid'] = $file['cid'];
                $ins_file['content'] = substr($file['content'], 0, 500000);
                sql_insert(MAIL_FILES_TEMPORARY, $ins_file);
                $file['content'] = substr($file['content'], 500000);
            }
        }
    }
    sql_query('UPDATE ' . MAIL_THREADS . ' SET wait = wait + ' . count_cb($to_arr) . ' WHERE id = ' . $thread_id);

    return $uid;
}

/**
 * Отправка SMS.
 * Функция добавляет сообщение в очередь рассылки (см. send_all_sms) и возвращает uid сообщения в очереди
 *
 * @param [type] $text          текст сообщения
 * @param [type] $to            кому
 * @param string $from          от кого (подпись)
 * @param integer $smsc_id      через какой sms шлюз проводить рассылку (по умолчанию - текущий активный)
 * @param integer $thread_id    id потока смс (по умолчанию - системный), возвращается функцией create_sms_thread
 * @param integer $line_id      id записи таблицы
 * @param integer $user_id      пользователь
 * @return void
 */
function sendsms($text, $to, $from = '', $smsc_id = -1, $thread_id = 1, $line_id = 0, $user_id = 0)
{
    $thread = sql_select_array(SMS_THREADS, 'id = ', $thread_id);
    if (!$thread && $thread_id == 1) { // отсутствует системный поток, восстанавливаем
        sql_insert(SMS_THREADS, ['id' => 1]);
    } elseif (!$thread || $thread['deleted']) { // поток не существует или был удален, не добавляем сообщение в очередь
        return false;
    }

    global $user;

    $ins_mail['thread_id'] = $thread_id;
    $ins_mail['add_time'] = date('Y-m-d H:i:s');
    if (!$user_id) {
        $ins_mail['user_id'] = $user['id'];
    } else {
        $ins_mail['user_id'] = $user_id;
    }
    $ins_mail['line_id'] = $line_id;
    $ins_mail['text'] = $text;
    if (!$from) {
        $row = sql_select_array(SMS_SETTINGS, "name = 'signatures'");
        $signatures = explode("\n", $row['value']);
        $from = $signatures[0];
    }
    $ins_mail['sender'] = $from;
    $to_arr = explode(',', $to);
    foreach ($to_arr as $phone) {
        $ins_mail['phone'] = trim($phone);
        $sms_id = sql_insert(SMS_QUEUE, $ins_mail);
        $uid = time() . $sms_id;
        sql_update(SMS_QUEUE, array('uid' => $uid), 'id = ', $sms_id);
    }
    sql_query('UPDATE ' . SMS_THREADS . ' SET wait = wait + ' . count_cb($to_arr) . ' WHERE id = ' . $thread_id);

    return $uid;
}

/**
 * Отправка сообщений через мессенджер.
 * Функция добавляет сообщение в очередь рассылки (см. send_all_mess) и возвращает uid сообщения в очереди
 *
 * @param string $text          текст сообщения
 * @param string $phone         телефон
 * @param string $nickname      никнейм
 * @param string $channel       канал
 * @param integer $thread_id    id потока рассылки (по умолчанию - системный), возвращается функцией create_msg_thread
 * @param integer $line_id      id записи таблицы
 * @param integer $user_id      пользователь
 * @return void
 */
function sendmsg($text, $phone, $nickname, $channel, $thread_id = 1, $line_id = 0, $user_id = 0)
{
    $thread = sql_select_array(MSG_THREADS, 'id = ', $thread_id);
    if (!$thread && $thread_id == 1) { // отсутствует системный поток, восстанавливаем
        sql_insert(MSG_THREADS, ['id' => 1]);
    } elseif (!$thread || $thread['deleted']) { // поток не существует или был удален, не добавляем сообщение в очередь
        return false;
    }

    global $user;

    // Нормализуем телефон только если он не пустой (для MAX может быть только chatId)
    $phone = preg_replace('#\D#i', '', (string)$phone);
    if ($phone !== '') {
        if (strlen($phone) == 10) {
            $phone = '7' . $phone;
        }
        if ($phone[0] == '8') {
            $phone = '7' . substr($phone, 1);
        }
    }

    // Очищаем nickname (может содержать chatId для MAX)
    $nickname = trim((string)$nickname);

    $ins_mail['thread_id'] = $thread_id;
    $ins_mail['add_time'] = date('Y-m-d H:i:s');
    if (!$user_id) {
        $ins_mail['user_id'] = $user['id'];
    } else {
        $ins_mail['user_id'] = $user_id;
    }
    $ins_mail['line_id'] = $line_id;
    $ins_mail['phone'] = $phone;
    $ins_mail['nickname'] = $nickname;
    $ins_mail['text'] = $text;
    $ins_mail['channel'] = $channel;
    $mess_id = sql_insert(MSG_QUEUE, $ins_mail);
    $uid = time() . $mess_id;
    sql_update(MSG_QUEUE, array('uid' => $uid), 'id = ', $mess_id);
    sql_query('UPDATE ' . MSG_THREADS . ' SET wait = wait + 1 WHERE id = ' . $thread_id);

    return $uid;
}

/**
 * Создать цепочку писем. Возвращает id потока.
 */
function create_mail_thread($name, $form_id = 0, $scheduled_time = 0, $user_id = 0)
{
    global $user, $cur_time;
    $thread['add_time'] = $cur_time;
    if (!$user_id) {
        $thread['user_id'] = $user['id'];
    } else {
        $thread['user_id'] = $user_id;
    }
    $thread['form_id'] = $form_id;
    $thread['name'] = $name;
    $thread['scheduled_time'] = $scheduled_time;
    $thread_id = sql_insert(MAIL_THREADS, $thread);
    return $thread_id;
}

function create_sms_thread($name, $form_id = 0, $scheduled_time = 0, $user_id = 0)
{
    global $user;
    $thread['add_time'] = date("Y-m-d H:i:s");
    if (!$user_id) {
        $thread['user_id'] = $user['id'];
    } else {
        $thread['user_id'] = $user_id;
    }
    $thread['form_id'] = $form_id;
    $thread['name'] = $name;
    $thread['scheduled_time'] = $scheduled_time;
    $thread_id = sql_insert(SMS_THREADS, $thread);
    return $thread_id;
}

/**
 * Создание потока рассылки в очереди
 * Функция создает запись в таблице MSG_THREADS и возвращает id созданного потока
 *
 * @param string $name              название потока
 * @param integer $form_id          id шаблона мессенджера
 * @param string $scheduled_time    время отложенного старта
 * @param integer $user_id          пользователь
 * @return integer                  id потока
 */
function create_msg_thread($name, $form_id = 0, $scheduled_time = 0, $user_id = 0)
{
    global $user;
    $thread['add_time'] = date("Y-m-d H:i:s");
    if (!$user_id) {
        $thread['user_id'] = $user['id'];
    } else {
        $thread['user_id'] = $user_id;
    }
    $thread['form_id'] = $form_id;
    $thread['name'] = $name;
    $thread['scheduled_time'] = $scheduled_time;
    $thread_id = sql_insert(MSG_THREADS, $thread);
    return $thread_id;
}

function isWebP($imageData) {
    if (strlen($imageData) < 12) {
        return false;
    }
    $riff = substr($imageData, 0, 4);
    $webp = substr($imageData, 8, 4);
    if ($riff === 'RIFF' && $webp === 'WEBP') {
        return true;
    }
    return false;
}

function image_preview(
    $image,
    $w1,
    $h1,
    $w2,
    $h2,
    $file_name = "",
    $white_to_transparent = 0,
    $watermark = "",
    $wmc = ""
) {
    global $config;

    if (isWebP($image)) {
        $projectRoot = \CB\Tool\FileSystemFunctions::getSitePath();
        $tempDir = $projectRoot . '/temp';
        $tempFile = tempnam($tempDir, 'webp');
        file_put_contents($tempFile, $image);
        $image_src = imagecreatefromwebp($tempFile);
        unlink($tempFile);
    } else {
        @$image_src = imagecreatefromstring($image); // если невалидное изображение будет просто квадрат
    }
    if ($image_src === false) {
        return;
    }

    $w1 = imagesx($image_src);
    $h1 = imagesy($image_src); // получаем ширину и высоту исходного изображения

    if ($white_to_transparent) {
        imagesavealpha($image_src, true);
        imagealphablending($image_src, false);
        $white = imagecolorallocate($image_src, 255, 255, 255);
        $transparent = imagecolorallocatealpha($image_src, 0, 0, 0, 127);
        for ($x = 0; $x < $w1; $x++) {
            for ($y = 0; $y < $h1; $y++) {
                if (imagecolorat($image_src, $x, $y) == $white or
                    imagecolorat($image_src, $x, $y) == 15 or
                    imagecolorat($image_src, $x, $y) == 255
                ) {
                    imagesetpixel($image_src, $x, $y, $transparent);
                }
            }
        }
    }

    if (!$w2 and !$h2) {  // если не заданы оба размера, то выводим исходное изображение

        $image_out = $image_src;
        imagesavealpha($image_out, true);
        imagealphablending($image_out, false);

    } else {  // иначе меняем размер

        $x1 = 0;
        $y1 = 0;  // координаты левого верхнего угла исходного изображения по умолчанию

        if (!$h2 || !$w2) {  // если задан только один размер, то сохраняем пропорции
            $w2 = $w2 ? $w2 : $h2 / ($h1 / $w1);
            $h2 = $h2 ? $h2 : ($h1 / $w1) * $w2;

        } else {   // иначе обрезаем исходную картинку

            $p1 = $h1 ? ($w1 / $h1) : 1; //вычисляем отношение сторон исходной картинки, если h1=0(не изображение), то считаем что стороны равны (отношение=1),а warning в imagecopyresampled ниже будет подавлен.
            $p2 = $w2 / $h2;  // и требуемой картинки

            if ($p1 > $p2) {
                $w1_new = $w2 * $h1 / $h2; // вычисляем уменьшенную ширину исходной картинки
                $x1 = ($w1 - $w1_new) / 2;
                $w1 = $w1_new;
            } else {
                $h1_new = $w1 * $h2 / $w2; // вычисляем уменьшенную высоту исходной картинки
                $y1 = ($h1 - $h1_new) / 2;
                $h1 = $h1_new;
            }
        }

        $image_out = imagecreatetruecolor($w2, $h2);
        imagesavealpha($image_out, true);
        imagealphablending($image_out, false);
        @imagecopyresampled($image_out, $image_src, 0, 0, $x1, $y1, $w2, $h2, $w1, $h1);
    }

    if (file_exists($watermark)) {
        $image_wm = imagecreatefromstring(file_get_contents($watermark));
        list($w_wm, $h_wm) = getimagesize($watermark);
        if (!$w2) {
            $w_img = $w1;
        } else {
            $w_img = $w2;
        }
        if (!$h2) {
            $h_img = $h1;
        } else {
            $h_img = $h2;
        }
        if ($wmc == "lt") {
            $x_wm = 0;
            $y_wm = 0;
        } // расположение водяного знака - в левом верхнем углу
        elseif ($wmc == "rt") {
            $x_wm = $w_img - $w_wm;
            $y_wm = 0;
        } // расположение водяного знака - в правом верхнем углу
        elseif ($wmc == "lb") {
            $x_wm = 0;
            $y_wm = $h_img - $h_wm;
        } // расположение водяного знака - в левом нижнем углу
        elseif ($wmc == "rb") {
            $x_wm = $w_img - $w_wm;
            $y_wm = $h_img - $h_wm;
        } // расположение водяного знака - в правом нижнем углу
        else {
            $x_wm = ($w_img - $w_wm) / 2;
            $y_wm = ($h_img - $h_wm) / 2;
        } // расположение водяного знака - по центру
        imagealphablending($image_out, true);
        imagecopy($image_out, $image_wm, $x_wm, $y_wm, 0, 0, $w_wm, $h_wm);
    }

    if ($image_out) {
        if ($file_name) {
            imagepng($image_out, $config["site_path"] . "/cache/" . $file_name);
        } else {
            imagepng($image_out);
        }
    }
}

function image_resize(
    $image,
    $w_max,
    $h_max,
    $file_name = "",
    $white_to_transparent = 0
) {
    global $config;
    $image_src = imagecreatefromstring($image); // если невалидное изображение будет просто квадрат

    $w1 = imagesx($image_src);
    $h1 = imagesy($image_src); // получаем ширину и высоту исходного изображения

    if ($white_to_transparent) {
        imagesavealpha($image_src, true);
        imagealphablending($image_src, false);
        $white = imagecolorallocate($image_src, 255, 255, 255);
        $transparent = imagecolorallocatealpha($image_src, 0, 0, 0, 127);
        for ($x = 0; $x < $w1; $x++) {
            for ($y = 0; $y < $h1; $y++) {
                if (imagecolorat($image_src, $x, $y) == $white or
                    imagecolorat($image_src, $x, $y) == 15 or
                    imagecolorat($image_src, $x, $y) == 255
                ) {
                    imagesetpixel($image_src, $x, $y, $transparent);
                }
            }
        }
    }

    if (!$w_max) $w_max = $w1;
    if (!$h_max) $h_max = $h1;

    $w2 = $w1;
    $h2 = $h1;

    if ($w2 > $w_max)
    {
        $h2 = $h2/$w2 * $w_max;
        $w2 = $w_max;
    }
    if ($h2 > $h_max)
    {
        $w2 = $w2/$h2 * $h_max;
        $h2 = $h_max;
    }

    if ($w2==$w1 and $h2==$h1) {  // если размеры не изменились, то выводим исходное изображение

        $image_out = $image_src;
        imagesavealpha($image_out, true);
        imagealphablending($image_out, false);

    } else {  // иначе сжимаем

        $image_out = imagecreatetruecolor($w2, $h2);
        imagesavealpha($image_out, true);
        imagealphablending($image_out, false);
        @imagecopyresampled($image_out, $image_src, 0, 0, 0, 0, $w2, $h2, $w1, $h1);
    }

    if ($image_out) {
        if ($file_name) {
            imagepng($image_out, $config["site_path"] . "/cache/" . $file_name);
        } else {
            imagepng($image_out);
        }
    }
}

function str2rtf($str)
{
    $str = iconv("utf-8", "cp1251", $str);
    for ($i = 0; $i < strlen($str); $i++) {
        if (ord($str[$i]) > 126) {
            $str_rtf .= "\\'" . bin2hex($str[$i]);
        } else {
            $str_rtf .= $str[$i];
        }
    }
    return $str_rtf;
}

// Получить короткое имя браузера по AgentId
function get_browser_name($agent)
{
    // Chrome
    if (preg_match("/Chrome\/([0-9]*\.[0-9]*)/i", $agent, $found)) {
        $browser = "Chrome " . $found[1];
    } else // Opera (Disguised as MSIE)
    {
        if (preg_match("/Opera ([0-9]\.[0-9]{0,2})/i", $agent, $found) && strstr($agent, "MSIE")) {
            $browser = "Opera " . $found[1];
        } // Opera (Disguised as Netscape/Mozilla)
        else {
            if (preg_match("/Opera ([0-9]\.[0-9]{0,2})/i", $agent, $found) && strstr($agent, "Mozilla")) {
                $browser = "Opera " . $found[1];
            } // Opera (Itself)
            else {
                if (preg_match("/Opera\/([0-9]\.[0-9]{0,2})/i", $agent, $found)) {
                    $browser = "Opera " . $found[1];
                } // Netscape 6.x
                else {
                    if (preg_match("/Netscape[0-9]\/([0-9]{1,2}\.[0-9]{1,2})/i", $agent, $found)) {
                        $browser = "Netscape " . $found[1];
                    } // Netscape 7.x
                    else {
                        if (preg_match("/Netscape\/([0-9]{1,2}\.[0-9]{1,2})/i", $agent, $found)) {
                            $browser = "Netscape " . $found[1];
                        } // NetCaptor
                        else {
                            if (preg_match("/NetCaptor ([0-9]{1,2}\.[0-9]{1,2}\.[0-9]{1,2})/i", $agent, $found)) {
                                $browser = $found[0];
                            } // Crazy Browser
                            else {
                                if (preg_match("/Crazy Browser ([0-9]{1,2}\.[0-9]{1,2}\.[0-9]{1,2})/i", $agent,
                                    $found)) {
                                    $browser = $found[0];
                                } // MyIE2
                                else {
                                    if (preg_match("/MyIE2/i", $agent)) {
                                        $browser = "MyIE2";
                                    } // MSIE
                                    else {
                                        if (preg_match("/MSIE ([0-9]{1,2}\.[0-9]{1,2})/i", $agent, $found)) {
                                            $browser = $found[0];
                                        } // Konqueror
                                        else {
                                            if (preg_match("/Konqueror/i", $agent)) {
                                                $browser = "Konqueror";
                                            } // Galeon
                                            else {
                                                if (preg_match("/Galeon/i", $agent)) {
                                                    $browser = "Galeon";
                                                } // Phoenix
                                                else {
                                                    if (preg_match("/Phoenix\/([0-9]{1}\.[0-9]{1,2})/i", $agent,
                                                        $found)) {
                                                        $browser = "Phoenix " . $found[1];
                                                    } // Firebird
                                                    else {
                                                        if (preg_match("/Firebird\/([0-9]{1}\.[0-9]{1,2})/i", $agent,
                                                            $found)) {
                                                            $browser = "Firebird " . $found[1];
                                                        } // FireFox
                                                        else {
                                                            if (preg_match("/Firefox\/([0-9]{1}\.[0-9]{1,2})/i", $agent,
                                                                $found)) {
                                                                $browser = "Firefox " . $found[1];
                                                            } // Lynx
                                                            else {
                                                                if (preg_match("/Lynx/i", $agent, $found)) {
                                                                    $browser = "Lynx";
                                                                } // WebTV
                                                                else {
                                                                    if (preg_match("/WebTV/i", $agent, $found)) {
                                                                        $browser = "WebTV";
                                                                    } // Netscape 4.x
                                                                    else {
                                                                        if (preg_match("/Mozilla\/([0-9]{1}\.[0-9]{1,2}) \[en\]/i",
                                                                            $agent, $found)) {
                                                                            $browser = "Netscape " . $found[1];
                                                                        } // A different definition of Mozilla browsers
                                                                        else {
                                                                            if (preg_match("/Mozilla\/([0-9]{1,2}\.[0-9]{1,2})/i",
                                                                                $agent, $found)) {
                                                                                $browser = "Mozilla " . $found[1];
                                                                            } // Mozilla
                                                                            else {
                                                                                if (preg_match("/(^Mozilla)(.)*\;\srv:([0-9]\.[0-9])/i",
                                                                                    $agent, $found)) {
                                                                                    $browser = $found[1] . " " . $found[3];
                                                                                } // Other (Dont know what it is)
                                                                                else {
                                                                                    $browser = "Other";
                                                                                }
                                                                            }
                                                                        }
                                                                    }
                                                                }
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    return ($browser);
}

// Получить версию OS по AgentId
function get_os_name($agent)
{
    // Determine the platform they are on
    if (strstr($agent, "Win")) {
        $platform = "Windows";
        if (preg_match("/6\.1/i", $agent)) {
            $platform = "Windows7";
        } else {
            if (preg_match("/6\.0/i", $agent)) {
                $platform = "Windows Vista";
            } else {
                if (preg_match("/5\.1/i", $agent)) {
                    $platform = "Windows XP";
                } else {
                    if (preg_match("/5\.2/i", $agent)) {
                        $platform = "Windows 2003";
                    } else {
                        if (preg_match("/5\.0/i", $agent)) {
                            $platform = "Windows 2000";
                        } else {
                            if (preg_match("/NT/i", $agent)) {
                                $platform = "Windows NT";
                            } else {
                                if (preg_match("/ME/i", $agent)) {
                                    $platform = "Windows ME";
                                } else {
                                    if (preg_match("/Win 9x 4.90/i", $agent)) {
                                        $platform = "Windows ME";
                                    } else {
                                        if (preg_match("/Windows ME/i", $agent)) {
                                            $platform = "Windows ME";
                                        } else {
                                            if (preg_match("/Windows CE/i", $agent)) {
                                                $platform = "Windows CE";
                                            } else {
                                                if (preg_match("/98/i", $agent)) {
                                                    $platform = "Windows 98";
                                                } else {
                                                    if (preg_match("/95/i", $agent)) {
                                                        $platform = "Windows 95";
                                                    } else {
                                                        if (preg_match("/Win16/i", $agent)) {
                                                            $platform = "Windows 3.1";
                                                        } else {
                                                            if (preg_match("/Windows 3\.1/i", $agent)) {
                                                                $platform = "Windows 3.1";
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    } else {
        if (strstr($agent, "Mac")) {
            $platform = "Macintosh";
        } else {
            if (strstr($agent, "PPC")) {
                $platform = "Macintosh";
            } else {
                if (strstr($agent, "FreeBSD")) {
                    $platform = "FreeBSD";
                } else {
                    if (strstr($agent, "SunOS")) {
                        $platform = "SunOS";
                    } else {
                        if (strstr($agent, "IRIX")) {
                            $platform = "IRIX";
                        } else {
                            if (strstr($agent, "BeOS")) {
                                $platform = "BeOS";
                            } else {
                                if (strstr($agent, "OS/2")) {
                                    $platform = "OS/2";
                                } else {
                                    if (strstr($agent, "AIX")) {
                                        $platform = "AIX";
                                    } else {
                                        if (strstr($agent, "Linux")) {
                                            $platform = "Linux";
                                        } else {
                                            if (strstr($agent, "Unix")) {
                                                $platform = "Unix";
                                            } else {
                                                if (strstr($agent, "Amiga")) {
                                                    $platform = "Amiga";
                                                } else {
                                                    $platform = "Other";
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    return ($platform);
}

/**
 * Фильтр логина пользователя
 *
 * Ограничение по длине строки:
 * 1. доменное имя 255 в общем (https://ru.wikipedia.org/wiki/%D0%9F%D0%BE%D0%B4%D0%B4%D0%BE%D0%BC%D0%B5%D0%BD)
 * 2. в линукс системе 32 символа
 * 3. пользователь базы данных 32 символа, начиная с mysql 5.7 (до 5.7 было 16) (mariadb - 80)
 * 4. имя хоста базы данных - 60 символов
 */
function filter_login($login)
{ // В логине могут быть только маленкие латинские буквы и цифры, знак минус
    global $br;
    $login = strtolower($login);
    $login_len = strlen($login);
    if ($login_len > 26) {
        die($br . "Error: Too long filter login '" . htmlspecialchars(mb_substr($login, 0, 50)) . "'...");
    }
    for ($i = 0; $i < $login_len; $i++) {
        if (((ord($login[$i]) > 96) && (ord($login[$i]) < 123)) || ((ord($login[$i]) > 47) && (ord($login[$i]) < 58)) || ($login[$i] == '-')) {
            $new_login .= $login[$i];
        }
    }
    return $new_login;
}

// Фильтр имени файла
function filter_file_name($login)
{ // Запрещенные последовательности /\:*?"<>|
    global $br;
    $new_login = "";
    $login_len = strlen($login);
    if ($login_len > 300) {
        return ("");
    }
    $last_char = '-=/-/-/-';
    for ($i = 0; $i < $login_len; $i++) {
        if ((substr($login, $i, 1) == '/') || (substr($login, $i, 1) == '\\') || (substr($login, $i,
                    1) == '|') || (substr($login, $i, 1) == ':') || (substr($login, $i, 1) == '*') || (substr($login,
                    $i, 1) == '?') || (substr($login, $i, 1) == '"') || (substr($login, $i,
                    1) == '<') || (substr($login, $i, 1) == '>') || (substr($login, $i, 1) == '|')
        ) {
            continue;
        }
        if ((ord(substr($login, $i, 1)) == 0) && (ord($last_char) == 0)) {
            return $new_login;
        } // Конец строки
        if ((substr($login, $i, 1) == '\r') && ($last_char == '\n')) {
            return $new_login;
        } // Перевод строки
        $new_login .= substr($login, $i, 1);
        $last_char = substr($login, $i, 1);
    }
    return $new_login;
}

// Фильтр доменого имени
function filter_domain_name($login)
{ // Могут быть только маленкие латинские буквы и цифры, знак минус, знак точка
    global $br;
    $new_login = "";
    $login_len = strlen($login);
    if ($login_len > 60) {
        $login_len = 60;
    }
    for ($i = 0; $i < $login_len; $i++) {
        if (((ord($login[$i]) > 96) && (ord($login[$i]) < 123)) || ((ord($login[$i]) > 47) && (ord($login[$i]) < 58)) || ($login[$i] == '-') || ($login[$i] == '.')) {
            $new_login .= $login[$i];
        }
    }
    return $new_login;
}

// Фильтр ip
function filter_ip($login)
{
// Могут быть только цифры, знак точка
    global $br;
    $new_login = "";
    $login_len = strlen($login);
    if ($login_len > 15) {
        die($br . "Error: Too long filter ip '" . htmlspecialchars(mb_substr($login, 0, 50)) . "'...");
    }
    for ($i = 0; $i < $login_len; $i++) {
        if (((ord($login[$i]) > 47) && (ord($login[$i]) < 58)) || ($login[$i] == '.')) {
            $new_login .= $login[$i];
        }
    }
    return $new_login;
}

// Фильтр почты
function filter_email($login)
{ // Могут быть только маленкие латинские буквы и цифры, знак минус, знак точка, знак собачка, подчеркивание
    global $br;
    $login = strtolower($login);
    $new_login = "";
    $login_len = strlen($login);
    if ($login_len > 254) {
        $login_len = 254;
    }
    for ($i = 0; $i < $login_len; $i++) {
        if (((ord($login[$i]) > 96) && (ord($login[$i]) < 123)) || ((ord($login[$i]) > 47) && (ord($login[$i]) < 58)) || ($login[$i] == '_') || ($login[$i] == '-') || ($login[$i] == '.') || ($login[$i] == '@')) {
            $new_login .= $login[$i];
        }
    }
    return $new_login;
}

if (!function_exists('mb_ord')) { // < PHP 7.2

    function mb_ord($string)
    {
        @ $result = unpack('N', mb_convert_encoding($string, 'UCS-4BE', 'UTF-8'));

        if (is_array($result) === true) {
            return $result[1];
        }
        return ord($string);
    }

    function mb_chr($cp)
    {
        return mb_convert_encoding('&#' . $cp . ';', 'UTF-8', 'HTML-ENTITIES');
    }
}

// Фильтр ФИО
function filter_fio($login)
{ // Могут быть только русские, латинские буквы, пробелы, цифры
    global $br;
    $new_login = "";
    $login_len = mb_strlen($login);
    if ($login_len > 60) {
        die($br . "Error: Too long filter fio name '" . htmlspecialchars(mb_substr($login, 0, 60)) . "'...");
    }
    for ($i = 0; $i < $login_len; $i++) {
        $c = mb_substr($login, $i, 1);
        //echo "<br>'".$c."' ";
        $ord_c = mb_ord($c);
        //echo "'".$ord_c."' ";
        if ((($ord_c > 47) && ($ord_c < 58)) || (($ord_c > 64) && ($ord_c < 91)) || (($ord_c > 96) && ($ord_c < 123)) || ($ord_c == 32) ||
            (($ord_c >= 1040) && ($ord_c <= 1103))
        ) // русские буквы
        {
            //echo " '".$ord_c."' ";
            $new_login .= mb_chr($ord_c);
        }
    }
    return $new_login;
}

// Получить список ip адресов, на основе вывода ipconfig /all
function get_local_ips($out)
{
    global $config;
    $ips = array();
    $nets = array();
    foreach ($out as $str) {
        $str = strtoupper($str);
        if ($str[0] != " ") {
            $i++;
        }
        if (substr(trim($str), 0, 2) == "IP" and substr(trim($str), 0, 4) != "IPV6") {
            $nets[$i]['IP'] = trim(substr($str, strpos($str, ":") + 1,
                strpos($str, "(") ? (strpos($str, "(") - strpos($str, ":") - 1) : strlen($str)));
        }
        if (substr(trim($str), 0, 4) == "DHCP") {
            $nets[$i]['DHCP'] = trim(substr($str, strpos($str, ":") + 1));
        }
    }
    foreach ($nets as $net) {
        if (substr($net['IP'], 0, 3) == "10." or substr($net['IP'], 0, 8) == "192.168." or substr($net['IP'], 0,
                8) == "172."
        ) {
            $ips[] = $net['IP'];
        }
    }
    return $ips;
}

function rev_search($str, $find, $pos)
{
    $str = substr($str, 0, $pos);
    $rev_str = strrev($str);
    $rev_find = strrev($find);
    $str_len = strlen($str);
    $find_len = strlen($find);
    if ($str_len < 1) {
        return false;
    }
    if ($find_len < 1) {
        return false;
    }
    $f_pos = strpos($rev_str, $rev_find);
    if ($f_pos === false) {
        return false;
    }
//echo "<br>\nstrlen:'$str_len',fpos:'$f_pos',find_len'$find_len'";
    $ret_val = $str_len - $f_pos - $find_len;
    return $ret_val;
}

// сформировать гиперссылку на основе текста
function form_hyperlink($str, $short = 1)
{
    global $lang;
    $str = trim($str);
    $last_word = $str;

    if ($str == '') {
        return '';
    }

    /*$last_word_short=substr($str,0,30); //убираем убираем обрезку, чтобы работала настройка "не сокращать в таблице"
    if (strlen($last_word)>35)
    $last_word=$last_word_short."...";*/

    if (!$short) {
        $last_word = $str;
    } else {
        // Выделяем само имя сайта
        if ((strpos($str, "http:") === 0) || (strpos($str, "ftps:") === 0)) {
            $last_word = substr($str, 7, strlen($str));
            if ($last_word[strlen($last_word) - 1] == '/') {
                $last_word = substr($last_word, 0, -1);
            }
        }
        if (strpos($str, "https:") === 0) {
            $last_word = substr($str, 8, strlen($str));
            if ($last_word[strlen($last_word) - 1] == '/') {
                $last_word = substr($last_word, 0, -1);
            }
        }
        if (strpos($str, "ftp:") === 0) {
            $last_word = substr($str, 6, strlen($str));
            if ($last_word[strlen($last_word) - 1] == '/') {
                $last_word = substr($last_word, 0, -1);
            }
        }

        if ((strpos($str, "\\\\") === 0) || (strpos($str, "//") === 0)) { // Выделяем последнее слово для file
            $p1 = rev_search($str, "\\", strlen($str));
            $p2 = rev_search($str, "/", strlen($str));
            if ($p1 < $p2) {
                $p1 = $p2;
            }
            if ($p1) { // ссылка на файл
                $p1++;
                $last_word = substr($str, $p1, 255);
            }
        }
    }

    if ((!$last_word) && ($str)) {
        $last_word = $lang["Open"];
    }
    $str_url = $str;
    $str_url = str_replace(" ", "%20", $str_url);
    $str_url = str_replace('"', "%22", $str_url);
    $str_url = str_replace("'", "%27", $str_url);
    $str_url = str_replace("<", "%3C", $str_url);
    $str_url = str_replace(">", "%3E", $str_url);
    $str_text = htmlspecialchars(strip_tags($str));
    $last_word = htmlspecialchars(strip_tags($last_word));

    if ($_COOKIE['is_mobile']) {
        $is_mobile = 1;
    }

    if ((strpos($str, "http:") === 0) || (strpos($str, "https:") === 0) || (strpos($str, "ftp:") === 0) ||
        (strpos($str, "ftps:") === 0) || (strpos($str, "mailto:") === 0) || (strpos($str,
                "\\\\") === 0) || (strpos($str, "file:") === 0)
    ) {
        if ($is_mobile) {
            return "<a href=\"$str_url\" class=\"external\" target=\"_blank\">$last_word</a>";
        } else {
            return "<a href=\"$str_url\" target=\"_blank\">$last_word</a>";
        }
    }

    // Возможно файл
    if ((strpos($str, "\\\\") === 0) || (strpos($str, "//") === 0)) {
        if ($is_mobile) {
            return "<a href=\"$str_url\" class=\"external\" target=\"_blank\">$last_word</a>";
        } else {
            return "<a href=\"file://$str_url\" target=\"_blank\">$last_word</a>";
        }
    }

    // Возможно email
    if (strpos($str, "@")) {
        if ($is_mobile) {
            return "<a href=\"$str_url\" class=\"external\" target=\"_blank\">$last_word</a>";
        } else {
            return "<a href=\"mailto:$str_url\">$str_text</a>";
        }
    }

    // Возможно телефон
    if (preg_replace('#\D#i', '', $str) == preg_replace('#[ ()\-+]#i', '', $str)) {
        $str_url = preg_replace('#[ ()\-]#i', '', $str);
        if ($is_mobile) {
            return "<a href=\"$str_url\" class=\"external\" target=\"_blank\">$last_word</a>";
        } else {
            return "<a href=\"tel:$str_url\">$str_text</a>";
        }
    }

    if ($is_mobile) {
        return "<a href=\"$str_url\" class=\"external\" target=\"_blank\">$last_word</a>";
    } else {
        return "<a href=\"http://$str_url\" target=\"_blank\">$last_word</a>";
    }
}

function htmlSubstr($html, $length, $br = true)
{
    $out = '';
    $was_cut = 0;
    $single = array('img');
    $html = str_replace('<br>', '<br />', $html);
    $arr = preg_split('/(<.+?>|&#?\\w+;)/s', $html, -1, PREG_SPLIT_DELIM_CAPTURE);
    $tagStack = array();
    for ($i = 0, $l = 0; $i < count_cb($arr); $i++) {
        if ($i & 1) {
            if ($br && $arr[$i] == '<br />') {
                // если <br>, то обрезаем
                $out .= "...";
                $was_cut = 1;
                break;
            } elseif (substr($arr[$i], 0, 2) == '</') {
                array_pop($tagStack);
            } elseif ($arr[$i][0] == '&') {
                $l++;
            } elseif (substr($arr[$i], -2) != '/>') {
                array_push($tagStack, $arr[$i]);
            }
            $out .= $arr[$i];
        } else {
            if (($l += mb_strlen($arr[$i])) >= $length) {
                $out .= mb_substr($arr[$i], 0, $length - $l + mb_strlen($arr[$i]));
                $out .= "...";
                $was_cut = 1;
                break;
            } else {
                $out .= $arr[$i];
            }
        }
    }
    while (($tag = array_pop($tagStack)) !== null) {
        $out .= '</' . strtok(substr($tag, 1), " \t>") . '>';
    }
    if ($was_cut) {
        return $out;
    } else {
        return $html;
    }
}

function htmlSubstrTrig($html, $length, $br = true)
{
    $t1 = htmlSubstr($html, $length, $br);
    $t2 = htmlSubstr($html, $length + 5, $br);
    if (($t1 != $html) && ($t2 == $html)) {
        return $html;
    } else {
        return $t1;
    }
}

if (!function_exists('mb_ucfirst') && function_exists('mb_substr')) {
    function mb_ucfirst($string)
    {
        $string = mb_ereg_replace("^[\ ]+", "", $string);
        $string = mb_strtoupper(mb_substr($string, 0, 1, "UTF-8"), "UTF-8") . mb_substr($string, 1, mb_strlen($string),
                "UTF-8");
        return $string;
    }
}

function move_files($source, $destination)
{
    $dh = opendir($source);
    while ($filename = readdir($dh)) {
        if ($filename != "." and $filename != "..") {
            if (is_dir($source . "/" . $filename)) {
                if (!file_exists($destination . "/" . $filename)) {
                    if (!@rename($source . "/" . $filename, $destination . "/" . $filename)) {
                        return ($destination);
                    }
                } else {
                    $ret_val = move_files($source . "/" . $filename, $destination . "/" . $filename);
                    if ($ret_val) {
                        return $ret_val;
                    }
                }
            } else {
                if (file_exists($destination . "/" . $filename)) {
                    if (!@unlink($destination . "/" . $filename)) {
                        return ($destination . "/" . $filename);
                    }
                }
                if (!@rename($source . "/" . $filename, $destination . "/" . $filename)) {
                    return ($destination);
                }
            }
        }
    }
    closedir($dh);
    rmdir($source);
    return "";
}

// Обновляем версию базы данных, если она устарела
// Перенесено из common.php для увеличения производительности
function check_version_update($table_prefix = "")
{
    global $config, $lang, $sql_db_type, $sql_global_link;
    if ($sql_db_type == "postgresql") {
        $pg_db = 1;
    }
    $orig_config = $config;
    include $config['site_path'] . "/include/config.php";
    $orig_config['version'] = $config['version'];
    $config = $orig_config;
    // заменяем префикс
    $config['table_prefix'] = $table_prefix ? $table_prefix : $config['table_prefix'];
    // Старый механизм, обновления, на основе версии
    while (true) {
        $sqlQuery = "SELECT * FROM " . $config["table_prefix"] . "config";
        $result = sql_query($sqlQuery);
        $row = sql_fetch_assoc($result);
        $cur_version = $row['version'];
        if (!$cur_version) {
            $result = sql_query("SHOW COLUMNS FROM " . $config['table_prefix'] . "config LIKE 'key'");
            $old_field = sql_num_rows($result);
            if ($old_field and $pg_db) {
                $key_field = '"key"';
            } elseif ($old_field) {
                $key_field = "`key`";
            } else {
                $key_field = "name";
            }
            $sqlQuery = "SELECT * FROM " . $config["table_prefix"] . "config WHERE $key_field = 'version'";
            $result = sql_query($sqlQuery);
            $row = sql_fetch_assoc($result);
            $cur_version = $row['value'];
        }
        if (!$cur_version) {
            die("Invalid current version!");
        }
        if ($cur_version < $config['version']) {
            include "bd_update/$cur_version.php";
        } else {
            break;
        }
    }
    // Обновляем ревизии
    $need_update = array();
    $dir = $config["site_path"] . "/bd_update";
    if ($dh = opendir($dir)) {
        $array_update_log = array();
        $result = sql_query("SELECT revision FROM " . $config["table_prefix"] . "update_log");
        while ($row = sql_fetch_assoc($result)) {
            $array_update_log[$row['revision']] = true;
        }
        while (($file = readdir($dh)) !== false) {
            if (($file == "..") || ($file == ".")) {
                continue;
            }
            $p = strpos($file, "revision_");
            if ($p !== false) {
                $f_rev = (int)substr($file, strlen("revision_"), 1024);
                if ($f_rev == 0) {
                    die("Invalid bd_update file: " . $file);
                }
                // Проверяем, проводился ли данный update
                if (!$array_update_log) {
                    include $config["site_path"] . "/bd_update/revision_1.php";
                    run_query("INSERT INTO " . $config["table_prefix"] . "update_log (revision) VALUES ('1')");
                    $array_update_log[1] = true;
                } else {
                    if ($array_update_log[$f_rev]) { // UPDATE уже был произведен
                        continue;
                    } else {
                        $need_update[] = $f_rev;
                    }
                }
            }
        }
    }
    closedir($dh);
    sort($need_update); // cортируем update-ы в порядке возрастания
    $found_error = 0;
    foreach ($need_update as $one_rev) {
        try {
            include $config['site_path'] . '/bd_update/revision_' . $one_rev . '.php';
        } catch (Exception $e) {
            if (!$found_error) { // перед первой ошибкой очищаем файл
                file_put_contents($config['site_path'] . '/temp/db_update_errors.log', '');
            }
            $found_error = 1;
            file_put_contents($config['site_path'] . '/temp/db_update_errors.log', '<b>Revision:</b> ' . $one_rev . '. <b>Error:</b> ' . $e->getMessage() . "<br>\n", FILE_APPEND);
        }
        run_query("INSERT INTO " . $config["table_prefix"] . "update_log (revision) VALUES ('$one_rev')");
    }
    // возвращаем префикс
    $config['table_prefix'] = $orig_config['table_prefix'];
    if (isset($need_update) && count_cb($need_update)) {
        unlinkRecursive($config['site_path'] . '/cache', false, true);
        unlinkRecursive($config['site_path'] . '/templates_c', false, true);
    }
    return $found_error ? false : true;
}

// Формируем фильтр на основе прав доступа
function form_rights_filter($table, $user_id)
{
    echo "use depricated: form_rights_filter";
    return "";
}

function base64_url_encode($str)
{
    return strtr(base64_encode($str), array('+' => '-', '/' => '_'));
}

function base64_url_decode($str)
{
    return base64_decode(strtr($str, array('-' => '+', '_' => '/')));
}

// Обновить файл цветовой схемы
function update_cur_scheme()
{
    global $config, $smarty;

    // Составляем сайм файл схемы
    $sqlQuery = "SELECT * FROM " . $config['table_prefix'] . "schemes WHERE active=1";
    $result = sql_query($sqlQuery);
    $color_scheme = sql_fetch_assoc($result);
    $smarty->assign("add_button_color", $config['add_button_color']);
    $smarty->assign("color1", $color_scheme['color1']);
    $smarty->assign("color2", $color_scheme['color2']);
    $smarty->assign("color3", $color_scheme['color3']);
    $smarty->assign("color2rgb", hexToRgb($color_scheme['color2']));
    $smarty->assign("color3rgb", hexToRgb($color_scheme['color3']));
    $smarty->assign("color4", $color_scheme['color4']);
    $smarty->assign("color7", $color_scheme['color7']);
    $smarty->assign("gradient_stat", $color_scheme['gradient_stat']);
    $smarty->assign("size_opacity", $color_scheme['size_opacity']);
    $smarty->assign("bgImgSelect", $color_scheme['img_select']);
    $smarty->assign("secondBgImgSelect", $color_scheme['second_img_select']);
    $smarty->assign("tableBg", $color_scheme['table_bg']);
    $smarty->assign("radiusMenu", $color_scheme['radius_menu']);
    $smarty->assign("font_select", $color_scheme['font_select']);
    $smarty->assign("color_scheme", $color_scheme);
    $new_css = $smarty->fetch($config['site_path'] . '/templates/cur_scheme.tpl');
    $cur_css_name = $config['site_path'] . '/cache/cur_scheme_' . $config['css_id'] . '_' . $config['css_id_sheme'] . '.css';
    @$cur_css = file_get_contents($cur_css_name);
    if ($cur_css != $new_css) {
        // Удаляем текущий файл css
        @unlink($config['site_path'] . '/cache/cur_scheme_' . $config['css_id'] . '_' . $config['css_id_sheme'] . '.css');
        @unlink($config['site_path'] . '/cache/cur_scheme__1.css');

        // Увеличиваем номер последнего обновления
        $config['css_id_sheme']++;
        $sqlQuery = "UPDATE " . $config['table_prefix'] . "config SET value='" . $config['css_id_sheme'] . "' WHERE name='css_id_sheme'";
        $result = sql_query($sqlQuery);
        $smarty->assign('config', $config);

        // Пишем новый файл
        @$f = fopen($config['site_path'] . '/cache/cur_scheme_' . $config['css_id'] . '_' . $config['css_id_sheme'] . '.css',
            'w');
        if ($f) {#000000
            fwrite($f, $new_css);
            fclose($f);
        }
    }
}

/**
 * Получить данные о таблице, результат получение кешируется, формируются на основе текущего пользователя.
 *
 * @param [type] $table_id      идентификатор таблицы
 * @param integer $cache        данные кешируются
 * @return mixed
 */
function get_table($table_id, $cache = 1, $no_display_error = 0)
{
    global $tables_cache, $user, $config, $lang;
    $group_id = $user['group_id'];

    if ($cache && isset($tables_cache)) {
        // Локальный кеш
        if ($tables_cache[$table_id]) {
            return $tables_cache[$table_id];
        }
        // Проверяем кеш memcache
        if ($config['xcache']) {
            $table = xcache_get("table_info_" . $group_id . "_" . $table_id);
            if ($table) {
                $tables_cache[$table_id] = $table;
                return $table;
            }
        }
    }

    $table = sql_select_array(TABLES_TABLE, 'id = ', $table_id);
    if (!$table) {
        if ($no_display_error) {
            return false;
        } else {
            generate_error('Invalid table_id: ' . $table_id);
            exit;
        }
    }
    $table_id = $table['id'];
    $table['display']['name_table'] = form_display($lang['conf'][$table['name_table']] ?? $table['name_table']);
    $table['display']['full_name'] = form_display($lang['conf'][$table['full_name']] ?? $table['full_name']);
    $table['display']['add_text'] = form_display($lang['conf'][$table['add_text']] ?? $table['add_text']);
    $table['display']['edit_text'] = form_display($lang['conf'][$table['edit_text']] ?? $table['edit_text']);
    $table['display']['def_sort'] = form_display($lang['conf'][$table['def_sort']] ?? $table['def_sort']);
    $table['display']['help'] = form_display($lang['conf'][$table['help']] ?? $table['help']);

    $table['def_sort'] = $table['def_sort'] ? : '`id`';

    $table['user_table_fields'] = $table['user_table_link'] ? unserialize($table['user_table_link']) : array();
    $table['user_table_calcs'] = $table['user_table_fields']['calcs'];

    // если параметр для подтаблицы не задан, берем из основного.
    if (isset($table['slop']) && (int)$table['slop'] === 0) {
        $table['slop'] = $table['lop'];
    }

    $table['LOP'] = $table['lop']; // дублируем в другом регистре, для совместимости
    $table['SLOP'] = $table['slop'];

    // Права доступа
    $table['rule_filter'] = '';
    $table['rules'] = array();
    $cat_acc = sql_select_array(ACC_CATS_TABLE, 'cat_id=', $table['cat_id'], ' and group_id=', $group_id);
    if ($cat_acc['access']) { // Доступ на уровне категории разрешен
        $table_acc = sql_select_array(ACC_TABLES_TABLE, 'table_id=', $table_id, ' and group_id=', $group_id);
        if ($table_acc['acc']) {
            $table['access'] = $table_acc['acc'];
            $table['vis'] = $table_acc['vis_acc'];
            $table['add'] = $table_acc['add_acc'];
            $table['del'] = $table_acc['del_acc'];
            $table['arc'] = $table_acc['arc_acc'];
            $table['imp'] = $table_acc['imp_acc'];
            $table['exp'] = $table_acc['exp_acc'];
            $table['adf'] = $table_acc['adf_acc'];
            $table['bed'] = $table_acc['bed_acc'];
            $table['adf_print'] = $table_acc['adf_acc_print'];
            $table['adf_send'] = $table_acc['adf_acc_send'];
            $table['adf_sms'] = $table_acc['adf_acc_sms'];
            $table['adf_mess'] = $table_acc['adf_acc_mess'];
            $table['rule_filter'] = $table_acc['rule_filter'];
            $table['act_rec_acc'] = $table_acc['act_rec_acc'];
            $table['arc_rec_acc'] = $table_acc['arc_rec_acc'];
            $table['del_rec_acc'] = $table_acc['del_rec_acc'];

            // Выбираем правила доступа
            $result3 = sql_select(ACC_RULES_TABLE, 'table_id=', $table_id, ' AND (group_id=', $group_id, ' OR global=1) AND disabled = 0 ORDER BY num');
            while ($row = sql_fetch_assoc($result3)) {
                $rule['id'] = $row['id'];
                $rule['name'] = $row['name'];
                $rule['num'] = $row['num'];
                $rule['condition_php'] = $row['condition_php'];
                $rule['rights'] = unserialize($row['rights']);
                if (!is_array($rule['rights'])) {
                    $rule['rights'] = [];
                } else {
                    $rights = $rule['rights'];
                    $rule['rights'] = [];
                    $i = 0;
                    foreach ($rights as $right) {
                        if (!isset($right['field'])) {
                            $rule['rights'][--$i] = $right;
                            continue;
                        }
                        if (!isset($rule['rights'][$right['field']])) {
                            $rule['rights'][$right['field']] = [];
                        }
                        $rule['rights'][$right['field']][] = $right;
                    }
                }
                // Выбираем доступ к таблице по правилу
                $table['rules'][$rule['id']] = $rule;
            }
        }
    }
    //$table['rules_reverse'] = array_reverse($table['rules'], 1);
    $table['rules_reverse'] = &$table['rules'];

    if (!$table['access']) {
        $table['view_tb'] = 0;
        $table['view_sub'] = 0;
        $table['view'] = 0;
    } else {
        // Проверка, есть ли, доступ к полям из данной таблиц
        $sqlQuery = "SELECT max(view_tb) as max_view_tb, max(view_sub) as max_view_sub, max(view) as max_view FROM " . ACC_FIELDS_TABLE . " WHERE group_id='$group_id' AND table_id='$table_id' GROUP BY table_id";
        $result2 = sql_query($sqlQuery);
        if ($row2 = sql_fetch_assoc($result2)) {
            $table['view_tb'] = $row2['max_view_tb'];
            $table['view_sub'] = $row2['max_view_sub'];
            $table['view'] = $row2['max_view'];
        }
    }

    /** @var boolean Разрешен просмотр по полю связи */
    $table['view_lnk'] = sql_num_rows(
        sql_query(
            "SELECT (max(view)=1 OR max(view_tb)=1) AS view
            FROM " . ACC_FIELDS_TABLE . "
            WHERE group_id='$group_id' AND table_id='$table_id' AND (view_tb>0 OR view>0 OR read_acc>0)
            GROUP BY field_id"
        )
    ) > 0;

    // Добавляем учет правил
    if (is_array($table['rules'])) {
        $cnt_view_fields = 0;
        $cnt_view_tb_fields = 0;
        $cnt_view_sub_fields = 0;
        $cnt_view_lnk_fields = 0;
        foreach ($table['rules'] as $one_rule) {
            foreach ($one_rule['rights'] as $key => $one_right_group) {
                if ($key <= 0) {
                    continue;
                }
                foreach ($one_right_group as $one_right) {
                    if ($one_right['field'] and $one_right['view'] == 1) {
                        $cnt_view_fields++;
                    }
                    if ($one_right['field'] and $one_right['view_tb'] == 1) {
                        $cnt_view_tb_fields++;
                    }
                    if ($one_right['field'] and $one_right['view_sub'] == 1) {
                        $cnt_view_sub_fields++;
                    }
                    if ($one_right['field'] and ($one_right['view'] == 1 or $one_right['view_tb'] == 1)) {
                        $cnt_view_lnk_fields++;
                    }
                }
            }
        }
        if ($cnt_view_fields) {
            $table['view'] = 1;
        }
        if ($cnt_view_tb_fields) {
            $table['view_tb'] = 1;
        }
        if ($cnt_view_sub_fields) {
            $table['view_sub'] = 1;
        }
        if ($cnt_view_lnk_fields > 1) {
            $table['view_lnk'] = 1;
        }
    }

    // Получить id первого поля связи, т.к. оно используется - для связи с подтаблицами, а также используется как новый фильтр в полях связи
    $sqlQuery = "SELECT id FROM " . FIELDS_TABLE . " WHERE table_id=" . $table_id . " and type_field=5 ORDER BY field_num LIMIT 1";
    $result = sql_query($sqlQuery);
    if ($row = sql_fetch_assoc($result)) {
        $table['first_link_field'] = $row['id'];
    }

    if ($cache) {
        $tables_cache[$table_id] = $table;
        if (($config['xcache']) && (!$user["is_root"])) {
            xcache_set("table_info_" . $group_id . "_" . $table_id, $table, 360);
        }
    }
    return $table;
}

function form_link_fields($table, $calculate)
{
    $link_fields = array();
    $table_fields = $table['table_fields'];
    for ($p = 0; $p < strlen($calculate); $p++) {
        if (substr($calculate, $p, strlen('$line[')) == '$line[') { // есть переменная
            $s = $p + strlen('$line');
            $t = '';
            $l_f =& $link_fields;
            $t_table = $table;
            $t_fields = $table_fields;
            $f_a = array();
            $f_id = 0;
            for (; $s < strlen($calculate); $s++) {
                if (((ord($calculate[$s]) > 96) && (ord($calculate[$s]) < 123)) || ((ord($calculate[$s]) > 47) && (ord($calculate[$s]) < 58)) || ($calculate[$s] == '-') || ($calculate[$s] == '_')) {
                    // наименование переменной побуквенно
                    $t .= $calculate[$s];
                } elseif (($calculate[$s] == "'") || ($calculate[$s] == '"')) {

                } elseif ($calculate[$s] == '[') { // начало имени
                } elseif ($calculate[$s] == ']') { // Конец имени поля
                    $field_id = $t_table["int_names"][$t];
                    $field = $t_fields[$field_id];
                    $t = '';
                    if ($field['type_field'] == 5) { // Поле связь
                        $l_f["sub_list"][$field['id']] = $field['s_table_id'];
                        if (!$l_f[$field['id']]) {
                            $l_f[$field['id']] = array();
                        }
                        $l_f =& $l_f[$field['id']];
                        $t_table = get_table($field['s_table_id']);
                        $t_fields = get_table_fields($t_table);
                    }
                } else {
                    break;
                }
            }
            $p = $s;
        }
    }
    return $link_fields;
}

// Выполнитль sql запрос
function catch_bk_trace($text)
{
    global $sql_log_trace_text;
    $sql_log_trace_text = $text;
    return "";
}

// ------ Функции работы с файлами
if (!function_exists("get_file_hash"))  // Если пользователь переопределил своими значениями
{
// Получить хеш имя файла таблицы
    function get_file_hash($field_id, $line_id, $fname)
    {
        return md5($field_id . '_' . $line_id . '_' . $fname) . '_' . $field_id . '_' . $line_id . '_' . ord($fname[0]);
    }

// Получить полный путь к файлу таблицы
    function get_file_path($field_id, $line_id, $fname)
    {
        global $config;
        $h = get_file_hash($field_id, $line_id, $fname);
        return $config['site_path'] . '/files/' . substr($h, 0, 2) . '/' . substr($h, 2, 2) . '/' . $h;
    }

// Создать систему каталогов, если она необходимы, для заданного пути файла
    function create_data_file_dirs($field_id, $line_id, $fname)
    {
        global $config;
        $h = get_file_hash($field_id, $line_id, $fname);
        $d = $config['site_path'] . '/files/' . substr($h, 0, 2) . '/' . substr($h, 2, 2);
        if (!file_exists($d)) {
            $d1 = $config['site_path'] . '/files/' . substr($h, 0, 2);
            if (!file_exists($d1)) {
                mkdir($d1, 0777);
                // Если необходимы особые настройки прав сохраняем
                if ($config['chown']) {
                    chown($d1, $config['chown']);
                }
                if ($config['chgrp']) {
                    chgrp($d1, $config['chgrp']);
                }
            }
            mkdir($d, 0777);
            // Если необходимы особые настройки прав сохраняем
            if ($config['chown']) {
                chown($d, $config['chown']);
            }
            if ($config['chgrp']) {
                chgrp($d, $config['chgrp']);
            }
        }
    }

    /**
     * Сохранить файл, автоматически будут созданны необходимые каталоги, если они необходимы
     *
     * @param int $field_id     Идентификатор поля
     * @param int $line_id      Идентификатор записи
     * @param string $fname     Название файла
     * @param mixed $data       Контент/ресурс
     * @return void
     */
    function save_data_file($fieldId, $lineId, $fname, $content)
    {
        // Проверяем на валидность наименования файла и контента
        if(!$fname || !$content) {
            return;
        }
        // Получаем объект поля
        $fieldsRep = \CB\Data\Fields\FieldRepository::getInstance();
        $field = $fieldsRep->get($fieldId); // Находим поле по id поля. Чтобы получить id таблицы

        if (!$field) {
            return;
        }

        $tableId = $field->get('table_id'); // Получаем ID таблицы
        $commonData = \CB\Core::get(\CB\Core::COMMON_DATA); // Получаем объект работы с данными
        $tableModels = $commonData->getTable($tableId); // Получаем объект таблицы

        if (!$tableModels) {
            return;
        }

        if (!$lineId) {
            return;
        }

        $recordObject = $tableModels->getRecord($lineId); // Получаем объект записи

        if (!$recordObject) {
            return;
        }

        $curFilesObject = $recordObject->get('f' . $fieldId); // Получаем объект поля

        if (!$curFilesObject) {
            return;
        }

        $curFilesObject->add($fname, $content); // Сохраняем файл
    }

    /**
     * Удалить файл, автоматически будет удален каталог, если он окажется пуст
     *
     * @param int $field_id     Идентификатор поля
     * @param int $line_id      Идентификатор записи
     * @param string $fname     Название файла
     * @return void
     */
    function drop_data_file($fieldId, $lineId, $fname)
    {
        // Проверяем на валидность наименования файла
        if(!$fname) {
            return;
        }
        $fieldsRep = \CB\Data\Fields\FieldRepository::getInstance();
        $field = $fieldsRep->get($fieldId);

        if (!$field) {
            return;
        }

        $tableId = $field->get('table_id');
        $commonData = \CB\Core::get(\CB\Core::COMMON_DATA);
        $tableModels = $commonData->getTable($tableId);

        if (!$tableModels) {
            return;
        }

        $recordObject = $lineId
            ? $tableModels->getRecord($lineId)
            : $tableModels->getRecordFromArray(['f' . $fieldId => '']);

        if (!$recordObject) {
            return;
        }

        $curFilesObject = $recordObject->get('f' . $fieldId);

        if (!$curFilesObject) {
            return;
        }

        $curFilesObject->delete($fname);
    }

    function get_file_type($fname)
    {
        $ext_types = array(
            'jpeg' => 'image/jpeg',
            'jpg' => 'image/jpeg',
            'gif' => 'image/gif',
            'png' => 'image/png',
            'webp' => 'image/webp',
            'txt' => 'text/plain',
            'sql' => 'text/x-sql',
            'php' => 'application/x-httpd-php',
            'doc' => 'application/msword',
            'odt' => 'application/vnd.oasis.opendocument.text',
            'ods' => 'application/vnd.oasis.opendocument.spreadsheet',
            'odp' => 'application/vnd.oasis.opendocument.presentation',
            'odg' => 'application/vnd.oasis.opendocument.graphics',
            'odc' => 'application/vnd.oasis.opendocument.chart',
            'odf' => 'application/vnd.oasis.opendocument.formula',
            'odi' => 'application/vnd.oasis.opendocument.image',
            'odm' => 'application/vnd.oasis.opendocument.text-master',
            'odb' => 'application/vnd.oasis.opendocument.base',
            'ott' => 'application/vnd.oasis.opendocument.text-template',
            'ots' => 'application/vnd.oasis.opendocument.spreadsheet-template',
            'otp' => 'application/vnd.oasis.opendocument.presentation-template',
            'otg' => 'application/vnd.oasis.opendocument.graphics-template',
            'otc' => 'application/vnd.oasis.opendocument.chart-template',
            'otf' => 'application/vnd.oasis.opendocument.formula-template',
            'oti' => 'application/vnd.oasis.opendocument.image-template',
            'oth' => 'application/vnd.oasis.opendocument.text-web',
            'docm' => 'application/vnd.ms-word.document.macroEnabled.12',
            'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
            'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template',
            'potm' => 'application/vnd.ms-powerpoint.template.macroEnabled.12',
            'potx' => 'application/vnd.openxmlformats-officedocument.presentationml.template',
            'ppam' => 'application/vnd.ms-powerpoint.addin.macroEnabled.12',
            'ppsm' => 'application/vnd.ms-powerpoint.slideshow.macroEnabled.12',
            'ppsx' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow',
            'ppsx' => 'application/vnd.ms-powerpoint.presentation.macroEnabled.12',
            'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
            'xlam' => 'application/vnd.ms-excel.addin.macroEnabled.12',
            'xlsb' => 'application/vnd.ms-excel.sheet.binary.macroEnabled.12',
            'xlsm' => 'application/vnd.ms-excel.sheet.macroEnabled.12',
            'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
            'xltm' => 'application/vnd.ms-excel.template.macroEnabled.12',
            'xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template',
            'pdf' => 'application/pdf',
            'zip' => 'application/zip'
        );
        $ext_p = strrpos($fname, '.');
        if ($ext_p) {
            $ext = strtolower(substr($fname, $ext_p + 1));
            if ($ext_types[$ext]) {
                return $ext_types[$ext];
            }
        }
        return "";
    }

    /**
     * Удалить все файлы
     *
     * @return void
     */
    function drop_files()
    {
        global $config;
        $fdir = $config['site_path'] . "/files";
        $dirs1 = scandir($fdir);
        foreach ($dirs1 as $d1_short) {
            if ($d1_short[0] == '.') {
                continue;
            }
            $d1 = $fdir . "/" . $d1_short;
            if (!is_dir($d1)) {
                continue;
            }
            $dirs2 = scandir($d1);
            $dir2_count = count_cb($dirs2) - 2;
            foreach ($dirs2 as $d2_short) {
                if ($d2_short[0] == '.') {
                    continue;
                }
                $d2 = $d1 . "/" . $d2_short;
                $fnames = scandir($d2);
                $files_count = count_cb($fnames) - 2;
                foreach ($fnames as $fname_short) {
                    if ($fname_short[0] == '.') {
                        continue;
                    }
                    $fname = $d2 . "/" . $fname_short;
                    unlink($fname);
                    $files_count--;
                }
                if ($files_count == 0) { // Нет файлов в каталоге, удалем его
                    rmdir($d2);
                    $dir2_count--;
                }
            };
            if ($dir2_count == 0) // нет каталогов второго уровня, удаляем каталог первого уровня
            {
                rmdir($d1);
            }
        }
    }

    /**
     * Удалить все файлы по заданому полю
     *
     * @param int $field_id     Идентификатор поля
     * @return void
     */
    function drop_files_by_field($field_id)
    {
        global $config;
        $fdir = $config['site_path'] . "/files";
        $dirs1 = scandir($fdir);
        foreach ($dirs1 as $d1_short) {
            if ($d1_short[0] == '.') {
                continue;
            }
            $d1 = $fdir . "/" . $d1_short;
            if (!is_dir($d1)) {
                continue;
            }
            $dirs2 = scandir($d1);
            $dir2_count = count_cb($dirs2) - 2;
            foreach ($dirs2 as $d2_short) {
                if ($d2_short[0] == '.') {
                    continue;
                }
                $d2 = $d1 . "/" . $d2_short;
                $fnames = scandir($d2);
                $files_count = count_cb($fnames) - 2;
                foreach ($fnames as $fname_short) {
                    if ($fname_short[0] == '.') {
                        continue;
                    }
                    $efid = strpos($fname_short, '_', 33);
                    if (!$efid) {
                        continue;
                    } // неформат имени файла
                    $fname = $d2 . "/" . $fname_short;
                    $file_field_id = substr($fname_short, 33, $efid - 33);
                    if ($field_id == $file_field_id) {  // Поле совпало, удаляем файл
                        unlink($fname);
                        $files_count--;
                    }
                }
                if ($files_count == 0) { // Нет файлов в каталоге, удалем его
                    rmdir($d2);
                    $dir2_count--;
                }
            };
            if ($dir2_count == 0) // нет каталогов второго уровня, удаляем каталог первого уровня
            {
                rmdir($d1);
            }
        }
    }

// Удалить все файлы в строке
    function drop_files_by_line($table, $line)
    {
        $table_fields = get_table_fields($table);
        foreach ($table_fields as $one_field) {
            if ($one_field['type_field'] == 6 or $one_field['type_field'] == 9) {
                $fnames = explode("\r\n", $line[$one_field['int_name']]);
                foreach ($fnames as $fname) {
                    drop_data_file($one_field['id'], $line['id'], $fname);
                }
            }
        }
    }

// Удалить файл из базы, по пути на диске
    function drop_file_by_path($path)
    {
        global $config;
        @unlink($path);

        $last_slash = strrpos($path, '/');
        if (!$last_slash) {
            return;
        }
        $last_slash++;
        $fname_short = substr($path, $last_slash);
        $efid = strpos($fname_short, '_', 33);
        if (!$efid) {
            return;
        } // неформат имени файла
        $fname = $d2 . "/" . $fname_short;
        $file_field_id = (int)substr($fname_short, 33, $efid - 33);
        $efid++;
        $elid = strpos($fname_short, '_', $efid);
        $file_line_id = (int)substr($fname_short, $efid, $elid - $efid);
        $f_char = chr((int)substr($fname_short, $elid + 1));
        // Выбираем информацию по полю
        $sqlQuery = "SELECT * FROM " . FIELDS_TABLE . " WHERE id='" . $file_field_id . "' ORDER BY field_num";
        $result = sql_query($sqlQuery);
        $field_info = sql_fetch_assoc($result);
        $field_info['int_name'] = form_int_name($field_info['id']);
        if (!$field_info) {
            return;
        }
        $sqlQuery = "SELECT * FROM " . TABLES_TABLE . " WHERE id='" . $field_info['table_id'] . "'";
        $result = sql_query($sqlQuery);
        $table = sql_fetch_assoc($result);
        if (!$table) {
            return;
        }

        // Выбираем файлы в данной строке из базы
        $sqlQuery = "SELECT * FROM " . DATA_TABLE . $table['id'] . " WHERE id='$file_line_id'";
        $result2 = sql_query($sqlQuery);
        while ($line = sql_fetch_assoc($result2)) {
            $fnames = explode("\r\n", $line[$field_info['int_name']]);
            $new_fnames = array();
            $dont_exists = 0;
            foreach ($fnames as $fname) {
                if (!$fname) {
                    continue;
                }
                $f_path = get_file_path($field_info['id'], $line['id'], $fname);
                if (file_exists($f_path)) {
                    $new_fnames[] = $fname;
                } else {
                    $dont_exists = 1;
                }
            }
            if ($dont_exists) {
                $fnames_line = implode("\r\n", $new_fnames);
                $sqlQuery = "UPDATE " . DATA_TABLE . $table['id'] . " SET " . $field_info['int_name'] . "='" . form_sql($fnames_line) . "' WHERE id='$file_line_id'";
                sql_query($sqlQuery);
            };
        }
    }
}
// ====== Функции работы с файлами

// Удаление папки с файлами
function unlinkRecursive($dir, $deleteRootToo = false, $hidden_file = false)
{
    if (!$dh = @opendir($dir)) {
        return;
    }
    while (false !== ($obj = readdir($dh))) {
        if ($obj == '.' || $obj == '..') {
            continue;
        }

        if ($hidden_file && 0 === mb_strpos($obj, '.')) {
            continue;
        }

        if (!@unlink($dir . '/' . $obj)) {
            unlinkRecursive($dir . '/' . $obj, true);
        }
    }

    closedir($dh);

    if ($deleteRootToo) {
        @rmdir($dir);
    }
    return;
}

// Сформировать каталоги для распаковки zip архива
// Является обходом бага Zip PHP 5.3 при safe_mode
function create_zip_dirs($base_dir_path, $files)
{
    // Считаем что в каждой папке существуют файлы
    foreach ($files as $one_fname) {
        $one_fname = str_replace('\\', '/', $one_fname);
        if ($p = strrpos($one_fname, '/')) {
            $fname = substr($one_fname, 0, $p);
            @mkdir($base_dir_path . "/" . $fname, 0777, 1);
        }
    }
}

// Сформировать полный путь до файла из имени
function form_path($file_name)
{
    global $config;
    $file_name = str_replace('\\', '/', $file_name);
    if (($file_name[0] == '/') || ($file_name[1] == ':')) { // Абсолютный путь
        return $file_name;
    } else {
        return $config['site_path'] . "/" . $file_name;
    }
}

function term_array($type_field, $mult_value)
{
    global $lang;
    if ($type_field == 1 or $type_field == 8 or $type_field == 10) {
        $term_arr = array(
            '=' => $lang['='],
            '!=' => $lang['!='],
            '>' => $lang['>'],
            '<' => $lang['<'],
            '>=' => $lang['>='],
            '<=' => $lang['<=']
        );
    } elseif ($type_field == 2 or $type_field == 12) {
        $term_arr = array(
            '=' => $lang['='],
            '!=' => $lang['!='],
            '>' => $lang['>'],
            '<' => $lang['<'],
            '>=' => $lang['>='],
            '<=' => $lang['<='],
            'period' => $lang['period']
        );
    } elseif ($type_field == 3 or $type_field == 4 or $type_field == 5 or $type_field == 6 or ($type_field == 7 and $mult_value) or $type_field == 9 or $type_field == 11 or $type_field == 14 or !$type_field) {
        $term_arr = array(
            '=' => $lang['='],
            '!=' => $lang['!='],
            ' LIKE ' => $lang['LIKE'],
            ' NOT LIKE ' => $lang['NOT LIKE']
        );
    } elseif ($type_field == 7 and !$mult_value) {
        $term_arr = array('=' => $lang['='], '!=' => $lang['!=']);
    } else {
        $term_arr = array('' => '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;');
    }
    return $term_arr;
}

function get_name_record($table, $table_fields, $line)
{
    if ($table['edit_text']) {
        $name_record = $table['edit_text'];
        foreach ($table_fields as $one_field) {
            $name_record = str_replace("{" . $one_field['name_field'] . "}",
                strip_tags(form_display_type($one_field, $line, "text")), $name_record);
        }
        if ($name_record !== "") {
            return $name_record;
        }
    }
    return $line['id'];
}

function form_charset_select($charset)
{
    global $lang;
    $charsets = array(
        "" => array("utf-8" => "UTF-8"),
        "russian" => array("cp1251" => "Windows-1251", "cp866" => "CP-866", "koi8-r" => "KOI8-R"),
        "ukrainian" => array("koi8-u" => "KOI8-U")
    );
    $res = "<option value=''>" . $lang['auto'] . "</option>";
    foreach ($charsets as $g_name => $group) {
        $g_name = strtoupper($g_name[0]) . substr($g_name, 1);
        if ($g_name) {
            $res .= "<optgroup label='$g_name'>";
        }
        foreach ($group as $chrst => $descr) {
            $res .= "<option value='$chrst' ";
            if ($chrst == $charset) {
                $res .= "selected";
            }
            $res .= ">$descr</option>";
        }
        if ($g_name) {
            $res .= "</optgroup>";
        }
    }

    return $res;
}

function insert_tip($tip_id, $line, $user_id = -1)
{
    global $user;

    $site_url = $config['site_url'] ?? \CB\core()->SITE_URL;

    if ($user_id != -1) {
        $old_user = $user;
        $user = sql_select_array(USERS_TABLE, 'id=', $user_id);
        $tables_cache = array(); // Сбрасываем кеш таблиц, при переключении пользователя
    }

    $cur_date = date("Y-m-d H:i:s");
    $tip = sql_select_array(TIPS_TABLE, 'id=', $tip_id);
    if (!$tip) {
        return;
    }
    $table_id = $tip['table_id'];
    $table = get_table($table_id);
    $table_fields = get_table_fields($table);


    $shablons = array();
    $values = array();

    foreach ($table_fields as $one_field) {
        $shablons[] = "{" . $one_field['name_field'] . "}";
        $values[] = form_display_type($one_field, $line, "tips");
    }

    $email_subject = str_replace($shablons, $values, $tip['email_subject']);
    $message = str_replace($shablons, $values, $tip['message']);
    $one_tip = array();
    $one_tip['tip_id'] = $tip['id'];
    $one_tip['table_id'] = $tip['table_id'];
    $one_tip['line_id'] = $line['id'];
    $one_tip['bg_color'] = $tip['bg_color'];
    $one_tip['message'] = $message;

    $result = sql_select(TIPS_SHOW_TABLE, "tip_id=", $tip['id'], " and user_id=", $user['id'], " and table_id='",
        $table_id, "' and line_id=", $line['id']);
    $tip_show = sql_fetch_assoc($result);
    if ($tip_show) { // Уже отображается, лишь обновляем текст
        $sqlQuery = "UPDATE " . TIPS_SHOW_TABLE . " SET message='" . form_sql($message) . "', hidden='0', inactive='0' where id = '" . $tip_show['id'] . "'";
        sql_update(TIPS_SHOW_TABLE, array(
            'message' => $message,
            'hidden' => 0,
            'inactive' => 0
        ),
            'id = ', $tip_show['id']);
    } else {
        if ($tip["head_on"]) {
            $sqlQuery = "INSERT INTO " . TIPS_SHOW_TABLE . " (user_id, tip_id,table_id, line_id, bg_color, message, date) VALUES ('" . $user["id"] . "','" . $one_tip['tip_id'] . "', '" . $one_tip['table_id'] . "', '" . $one_tip['line_id'] . "', '" . $one_tip['bg_color'] . "', '" . form_sql($one_tip['message']) . "', '$cur_date')";
            sql_insert(TIPS_SHOW_TABLE, array(
                'user_id' => $user['id'],
                'tip_id' => $one_tip['tip_id'],
                'table_id' => $one_tip['table_id'],
                'line_id' => $one_tip['line_id'],
                'bg_color' => $one_tip['bg_color'],
                'message' => $one_tip['message'],
                'date' => $cur_date
            ));
        }
    }

    if ($tip["email_on"]) {
        if (!$tip["head_on"]) { // Если только отсылаем по email и не сохраняем в шапке, то сохраняем в архиве всеравно
            sql_insert(TIPS_SHOW_ARHIVE_TABLE, array(
                'user_id' => $user["id"],
                'tip_id' => $one_tip['tip_id'],
                'table_id' => $one_tip['table_id'],
                'line_id' => $one_tip['line_id'],
                'bg_color' => $one_tip['bg_color'],
                'message' => $one_tip['message'],
                'date' => $cur_date
            ));
        }
        // отсылать по email
        $logo = '<img src="' . $site_url . '/images/mail_logo.png">';
        $record_link = $site_url . "/view_line2.php?table=" . $tip['table_id'] . "&line=" . $line['id'];
        $mail_tmpl = sql_select_array(MAIL_TEMPLATES_TABLE, 'id=', $tip['email_template']);
        $mail_subj = $email_subject ? $email_subject : $mail_tmpl['subject'];
        $mail_body = str_replace(array('{logo}', '{fio}', '{tip_text}', '{record_link}'), array($logo, $user['fio'], $message, $record_link), $mail_tmpl['body']);
        sendmail($mail_subj, $mail_body, $user['e_mail'], $mail_tmpl['from_mail'], $mail_tmpl['sender'], '', 'text/html', (empty($mail_tmpl['charset']) ? 'utf-8' : $mail_tmpl['charset']), [], [], -1, 1, 0, 0, $mail_tmpl['unsubscribe']);
    }
    if ($tip["sms_on"]) {
        if (!$tip["head_on"]) { // Если только отсылаем по sms и не сохраняем в шапке, то сохраняем в архиве всеравно
            sql_insert(TIPS_SHOW_ARHIVE_TABLE, array(
                'user_id' => $user["id"],
                'tip_id' => $one_tip['tip_id'],
                'table_id' => $one_tip['table_id'],
                'line_id' => $one_tip['line_id'],
                'bg_color' => $one_tip['bg_color'],
                'message' => $one_tip['message'],
                'date' => $cur_date
            ));
        }
        // отсылать по sms
        sendsms($message, $user['phone'], $tip['sms_sender']);
    }
    if ($user_id != -1) {
        $user = $old_user;
        $tables_cache = array(); // Сбрасываем кеш таблиц, при переключении пользователя
    }
}

function generate_password($len_min = 7, $len_max = 10, $chars = 0)
{
    $i = 0;
    $ret_val = "";
    for ($i = 0; $i < $len_max; $i++) {
        if (($i >= $len_min) && (rand(0, 3) == 2)) {
            break;
        }
        if ($chars && (rand(0, 10) == 5)) {
            $ret_val .= chr(rand(97, 122));
        } else {
            if ($chars && (rand(0, 20) == 5)) {
                $r = rand(0, 5);
                if ($r == 0) {
                    $ret_val .= '*';
                }
                if ($r == 1) {
                    $ret_val .= '+';
                }
                if ($r == 2) {
                    $ret_val .= '-';
                }
                if ($r == 3) {
                    $ret_val .= '=';
                }
                if ($r == 4) {
                    $ret_val .= '#';
                }
                if ($r == 5) {
                    $ret_val .= '!';
                }
            } else {
                $r = rand(0, 1);
                if ($r) {
                    $ret_val .= chr(rand(65, 90));
                } else {
                    $ret_val .= chr(rand(97, 122));
                }
            }
        }
    }
    return $ret_val;
}

// Сохранить в файл все данные синхронизации
function flush_sync($manual_export = false)
{
    global $sync_exp_list, $sync_exp_data, $sync_exp_fields, $sync_exp_rfields, $sync_exp_rtables, $config, $tables_cache, $config, $lang;
    if (!$sync_exp_data) {
        $sync_exp_data = array();
    }
    if (!$sync_exp_list) {
        // Считываем настройки синхронизации, для экспорта
        $sync_exp_list = array();
        if ($manual_export) {
            $result = sql_select(SYNC_TABLE, "enabled=1 and id=", $manual_export);
        } else {
            $result = sql_select(SYNC_TABLE, "enabled=1");
        }

        while ($one_sync = sql_fetch_assoc($result)) {
            $one_sync['tables'] = array();
            $sync_exp_list[$one_sync['id']] = $one_sync;
        }
        $sync_exp_fields = array();
        $sqlQuery = "SELECT a.table_id, b.* FROM " . FIELDS_TABLE . " a, " . SYNC_FIELDS_TABLE . " b WHERE a.id=b.field_id and b.enabled='1'";
        $result2 = sql_query($sqlQuery);
        while ($one_field = sql_fetch_assoc($result2)) {
            if (!$sync_exp_list[$one_field['sync_id']]) {
                continue;
            }
            if ($one_field['direction'] == 0) {
                $sync_exp_rfields[$one_field['field_id']][$one_field['sync_id']] = 1;
                $sync_exp_rtables[$one_field['table_id']][$one_field['sync_id']] = 1;
            } else {
                $sync_exp_fields[$one_field['field_id']][$one_field['sync_id']] = array(
                    'sync_id' => $one_field['sync_id'],
                    'field_id' => $one_field['field_id'],
                    'c_field' => ($sync_exp_list[$one_field['sync_id']]['sync_mode'] == 0 ? $one_field['c_field'] : 0),
                    'filter_id' => $one_field['filter_id']
                );
                $sync_exp_list[$one_field['sync_id']]['fields'][$one_field['field_id']] = array(
                    'field_id' => $one_field['field_id'],
                    'table_id' => $one_field['table_id']
                );
                $sync_exp_list[$one_field['sync_id']]['tables'][$one_field['table_id']] = $one_field['table_id'];
            }
        }
    }

    // Поворачиваем sync_exp_data чтобы базой стала строка
    $sync_exp_data_lines = array();
    foreach ($sync_exp_data as $sync_id => $sync) {
        foreach ($sync as $field_id => $line) {
            foreach ($line as $line_id => $value) {
                $sync_exp_data_lines[$sync_id][$line_id][$field_id] = $value;
            }
        }
    }

    // Выбираем также строки которые были добавлены в базу, без использования кб.
    $all_table_fields = array();
    foreach ($sync_exp_list as $sync_id => $sync) {
        foreach ($sync['tables'] as $table_id => $table_info) {
            $table = get_table($table_id);
            $table_fields = get_table_fields($table);
            $all_table_fields += $table_fields;
            if (!$manual_export) {
                $result2 = data_select($table_id, "s$sync_id='' and status<3");
                while ($one_line = sql_fetch_assoc($result2)) {
                    $line_id = $one_line['id'];
                    $sync_line_id = "^" . $line_id;
                    // Cтавим отметку что строка была синхронизированна
                    data_update($table_id, array("s" . $sync_id => "S"), "id=", $line_id, " and s$sync_id=''");
                    if ($sync_exp_data_lines[$sync_id][$sync_line_id]) {
                        continue;
                    } // Строка уже добавлена в синхронизацию
                    foreach ($sync['fields'] as $field_id => $field_info) {
                        if (!$table_fields[$field_id]) {
                            continue;
                        }
                        $value = $one_line[$table_fields[$field_id]['int_name']];
                        if ($table_fields[$field_id]['type_field'] == 5 AND ($sync_exp_list[$sync_id]['tables'][$table_fields[$field_id]["s_table_id"]] OR $sync_exp_rtables[$table_fields[$field_id]["s_table_id"]][$sync_id]) AND $sync_exp_list[$sync_id]['sync_mode']) { // Поле связи
                            $link_field_data = data_select_array($table_fields[$field_id]['s_table_id'], "id=", $value);
                            if (!$link_field_data) {
                                continue;
                            }
                            if ($link_field_data["s" . $sync_id] == "S") { // Целевая строка не засинхронизирована
                                $cache_res = sql_select_field(SYNC_CACHE_TABLE, "id", "sync_id=", $sync_id,
                                    " and field_id=", $table_fields[$field_id]['s_field_id'], " and line_id=", $value);
                                if (!sql_fetch_assoc($cache_res)) // В кэше на выгрузку записи тоже нет, убираем S для того, чтобы строка добавилась в список для синхронизации
                                {
                                    data_update($table_fields[$field_id]['s_table_id'], array("s" . $sync_id => ""),
                                        "id=", $value);
                                }
                                // Добавляем текущую строку в кэш для выгрузки
                                sql_insert(SYNC_CACHE_TABLE, array(
                                    "sync_id" => $sync_id,
                                    "table_id" => $table_id,
                                    "field_id" => $field_id,
                                    "line_id" => $line_id,
                                    "value" => "^" . $value,
                                    "upload_count" => 1,
                                    "last_upload" => date("Y-m-d H:i:s")
                                ));
                            } else // Целевая запись засинхронизирована, выгружаем поле связи
                            {
                                $value = $link_field_data["s" . $sync_id];
                                $sync_exp_data[$sync_id][$field_id][$sync_line_id] = $value;
                                sql_insert(SYNC_CACHE_TABLE, array(
                                    "sync_id" => $sync_id,
                                    "table_id" => $table_id,
                                    "field_id" => $field_id,
                                    "line_id" => $line_id,
                                    "value" => $value,
                                    "upload_count" => 1,
                                    "last_upload" => date("Y-m-d H:i:s")
                                ));
                            }
                        } else {
                            $sync_exp_data[$sync_id][$field_id][$sync_line_id] = $value;
                            $sync_exp_data_lines[$sync_id][$sync_line_id][$field_id] = $value;
                            // Добавляем в кэш
                            sql_insert(SYNC_CACHE_TABLE, array(
                                "sync_id" => $sync_id,
                                "table_id" => $table_id,
                                "field_id" => $field_id,
                                "line_id" => $line_id,
                                "value" => $value,
                                "upload_count" => 1,
                                "last_upload" => date("Y-m-d H:i:s")
                            ));
                        }
                        // Если поле файл или изображение - необходимо засинхронизировать и файлы
                        if (($table_fields[$field_id]['type_field'] == 6 OR $table_fields[$field_id]['type_field'] == 9) AND $value != "") {
                            $files_list = explode("\r\n", $value);
                            foreach ($files_list AS $one_filename) {
                                sync_files_export($sync_id, $line_id, $field_id, $one_filename);
                            }
                        }
                    }
                }
            }
        }
    }
    if (!$sync_exp_data) {
        return false;
    }

    $array_c_field = array();
    foreach ($sync_exp_data as $sync_id => $sync) {
        foreach ($sync as $field_id => $line) {
            foreach ($line as $line_id => $value) {
                $field_type = $all_table_fields[$field_id]['type_field'];
                if (($field_type == 7 || $field_type == 11) && $sync_exp_list[$sync_id]['user_sync_mode']) {
                    if ($sync_exp_list[$sync_id]['user_sync_mode'] == 1) {
                        $user_field = 'login';
                    } elseif ($sync_exp_list[$sync_id]['user_sync_mode'] == 2) {
                        $user_field = 'fio';
                    }
                    $value = sql_fetch_row(sql_select_field(USERS_TABLE, $user_field, 'id = ', $value))[0];
                }
                $value = str_replace("\r\n", "\\" . chr(10) . "\\" . chr(13), $value);

                if ($sync_exp_list[$sync_id]['sync_mode'] OR $field_id == "ID" OR $field_id == "SYNC_COMMAND") {
                    $fld_id = $field_id;
                } else {
                    $fld_id = $sync_exp_fields[$field_id][$sync_id]['c_field'];
                }
                $array_c_field[$sync_id][$fld_id] = $field_id;
                $sync_out[$sync_id][$line_id][$fld_id] = $value;

                if (strpos($line_id, "^") === 0) // Строка новая, проверям наличие поля ID для синхронизации
                {
                    $f_table_id = $sync_exp_list[$sync_id]['fields'][$field_id]['table_id'];
                    if ($id_fields[$f_table_id]) {
                        $id_field = $id_fields[$f_table_id];
                    } else {
                        $result = sql_select_field(FIELDS_TABLE, "id", "table_id=", $f_table_id, " and type_field=10");
                        $row = sql_fetch_assoc($result);
                        $id_field = $row['id'];
                        $id_fields[$f_table_id] = $id_field;
                    }
                    if ($sync_exp_list[$sync_id]['fields'][$id_field] AND !$sync_exp_data[$sync_id][$id_field][$line_id]) {
                        $sync_exp_data[$sync_id][$id_field][$line_id] = substr($line_id, 1);
                        if ($sync_exp_list[$sync_id]['sync_mode'] OR $field_id == "ID" OR $field_id == "SYNC_COMMAND") {
                            $fld_id = $id_field;
                        } else {
                            $fld_id = $sync_exp_fields[$id_field][$sync_id]['c_field'];
                        }
                        $array_c_field[$sync_id][$fld_id] = $id_field;
                        $sync_out[$sync_id][$line_id][$fld_id] = substr($line_id, 1);;
                    }
                }
            }
        }
    }

    $filters_cache = array();
    $fields_cache = array();
    foreach ($sync_out AS $s_id => $s_lines) {
        $file_num = 1;
        $line_num = 1;

        foreach ($s_lines AS $s_line => $s_fields) {
            $was_checked = 0;
            foreach ($s_fields AS $s_field => $s_value) {
                $field_id = $array_c_field[$s_id][$s_field];
                if ($sync_exp_fields[$field_id][$s_id]['filter_id'] && $was_checked == 0) { // Экспорт по фильтру
                    $filter_id = $sync_exp_fields[$field_id][$s_id]['filter_id'];
                    if ($fields_cache[$field_id]) {
                        $table_id = $fields_cache[$field_id];
                    } else { // Проходимся по всему кешу таблиц и находим поле
                        $table_id = -1;
                        foreach ($tables_cache as $one_table) {
                            if ($one_table['table_fields'][$field_id]) {
                                $table_id = $one_table['id'];
                                break;
                            }
                        }
                        if (!$table_id) { // В кеше отсутвует, выбираем из базы
                            $result = sql_select(FIELDS_TABLE, "id=", $field_id);
                            $row = sql_fetch_assoc($result) or die("Sync invalid table id for field " . $field_id);
                            $table_id = $row['table_id'];
                        }
                        $fields_cache[$field_id] = $table_id;
                    }
                    if ($filters_cache[$filter_id]) {
                        $filter_cond = $filters_cache[$filter_id];
                    } else {
                        $result = sql_select(FILTERS_TABLE, "id=", $filter_id);
                        $row = sql_fetch_assoc($result);
                        $filter_cond = $row['value'];
                        $filters_cache[$filter_id] = $filter_cond;
                    }
                    if (!$filter_cond) {
                        $was_checked = 1;
                    } else {
                        $real_line_id = $s_line;
                        if ($real_line_id[0] == '^') {
                            $real_line_id = substr($real_line_id, 1);
                        }

                        if ($sync_exp_list[$s_id]['sync_mode']) // В случае активной синхронизации, если номер строки начинается на ^ то выдается локальный ID, если без шапки то выдается поле S
                        {
                            if ($s_line[0] != '^') {
                                $result = data_select_field($table_id, "count(*) as cnt", "s", $s_id, "='",
                                    $real_line_id, "' and ($filter_cond)");
                            } else {
                                $result = data_select_field($table_id, "count(*) as cnt", "id=", $real_line_id,
                                    " and ($filter_cond)");
                            }
                        } else // В случае пассивной синхронизации всегда передается id строки
                        {
                            $result = data_select_field($table_id, "count(*) as cnt", "id=", $real_line_id,
                                " and ($filter_cond)");
                        }


                        $row = sql_fetch_assoc($result);
                        if ($row['cnt'] < 1) { // Ошибка чтения строки по фильтру, пропускаем
                            break;
                        } else {
                            $was_checked = 1;
                        }
                    }
                }

                if (!$sync_exp_list[$s_id]['data'][$file_num]) {
                    $sync_exp_list[$s_id]['data'][$file_num] = array();
                }

                if (!in_array($s_field . ";" . $s_line . ";" . $s_value, $sync_exp_list[$s_id]['data'][$file_num])) {
                    if ($config['event_on']['sync']) {
                        \CB\CornyService::insert_log_light('sync',
                            $lang['User'] . ' "' . $lang['Sync'] . ' <a href="edit_sync.php?sync_id=' . $sync_id . '">' . form_display($sync_exp_list[$sync_id]['sync_name']) . '</a>" отправил значение поля "' . $table_fields[$s_field]['name_field'] . '" таблицы "' . $table['name_table'] . '" в строке ' . $s_line . ' - "' . $s_value . '"',
                            0, 0, $sync_id);
                    }
                    $sync_exp_list[$s_id]['data'][$file_num][] = $s_field . ";" . $s_line . ";" . $s_value;
                    $line_num += 1;
                }
            }
            if ($line_num > SYNC_STRINGS) {
                $file_num += 1;
                $line_num = 1;
            }
        }
    }

    $fnames = array();

    foreach ($sync_exp_list as $sync_id => $sync) {
        if (!$sync['data']) {
            continue;
        }

        if ($sync['sync_mode'] == 3 && !$config["modules"]['1csync']) {
            if ($sync['log_on']) {
                \CB\CornyService::insert_log_light("sync",
                    $lang['Sync'] . " <a href='edit_sync.php?sync_id=$sync_id'>" . form_display($sync['sync_name']) . "</a>: " . $lang['Sync_error'] . " 1C integration is not activated.",
                    0, 0, $sync_id);
            }
            continue;
        }

        $fcount = count_cb($sync['data']);

        foreach ($sync['data'] AS $sfile => $sync_part) {

            // rsort($sync_part); // костыль по заданию 78239, чтобы обновление записей шло поcле синхронизации ID (закомментировано по заданию 78819)

            $fname = (string)microtime(true);

            while (in_array($fname, $fnames)) {
                $fname = (string)microtime(true);
            }

            $fnames[] = $fname;

            while (strlen(substr($fname, strpos($fname, "."))) < 5) {
                $fname .= "0";
            }

            if (strpos($fname, ".") === false) {
                $fname .= ".0000";
            }

            if ($sync['sync_mode'] == 3) {
                $fname .= "82c1.log";
            } else {
                $fname .= ".log";
            }

            if ($sync['type_mode']) {
                $sync['upload_dir'] = "temp/sync_" . $sync_id . "/export";
            }

            if (!is_dir($sync['upload_dir'])) {
                $fl_error = 'Sync_no_upl_dir';
                if ($config['event_on']['sync']) {
                    \CB\CornyService::insert_log_light('sync',
                        $lang['Sync'] . " <a href='edit_sync.php?sync_id=$sync_id'>" . form_display($sync['sync_name']) . "</a>: " . $lang['Sync_error'] . " " . $lang['Sync_no_upl_dir'] . " <a href=\"edit_sync.php?sync_id=$sync_id\">" . $lang['Sync_set_check'] . "</a>",
                        0, 0, $sync_id);
                }
                continue;
            }
            if (($f = fopen($sync['upload_dir'] . "/" . $fname . ".tmp", "w")) == false) {
                $fl_error = 'invalid_write_rights';
                if ($config['event_on']['sync']) {
                    \CB\CornyService::insert_log_light('sync',
                        $lang['Sync'] . " <a href='edit_sync.php?sync_id=$sync_id'>" . form_display($sync['sync_name']) . "</a>: " . $lang['Sync_error'] . " " . $lang['no_write_to_folder'] . " " . $sync['upload_dir'],
                        0, 0, $sync_id);
                }
                continue;
            }
            fwrite($f, implode("\r\n", $sync_part) . "\r\n");
            fclose($f);
            rename($sync['upload_dir'] . "/" . $fname . ".tmp", $sync['upload_dir'] . "/" . $fname);
            chmod($sync['upload_dir'] . "/" . $fname, 0664);
        }
        $sync_exp_list[$sync_id]['data'] = array();
    }

    $sync_exp_data = array(); // Чистим данные

    if ($fl_error) {
        return $fl_error;
    } else {
        return false;
    }
}

// Вычисление в ограниченной области видимости
function in_eval($str)
{
    global $config, $user, $smarty, $lang, $ses_id, $button_id, $send_report, $csrf;
    return eval($str);
}

function mb_str_replace($needle, $replacement, $haystack)
{
    return implode($replacement, mb_split($needle, $haystack));
}

function html_form($str)
{
    $str = str_replace('<br>', "\n", $str);
    $str = str_replace('<BR>', "\n", $str);
    $str = str_replace('</div><div>', "\n", $str);
    $str = str_replace('</DIV><DIV>', "\n", $str);
    $str = str_replace('<div>', "\n", $str);
    $str = str_replace('<DIV>', "\n", $str);
    $str = str_replace('</div>', "", $str);
    $str = str_replace('</DIV>', "", $str);
    $str = str_replace('<span>', "", $str);
    $str = str_replace('</span>', "", $str);
    $str = str_replace('<SPAN>', "", $str);
    $str = str_replace('</SPAN>', "", $str);;
    $str = str_replace('&nbsp;', ' ', $str);
    $str = str_replace(' ', ' ', $str); // Заменяем тонкий пробел Chrome, на обычный
    $str = html_entity_decode($str, ENT_QUOTES, "UTF-8");
    $str = htmlspecialchars($str);
    $str = trim($str);
    return $str;
}

function get_link_lines($field, $term, $value)
{
    if ($term == " LIKE " or $term == " NOT LIKE ") {
        $f_term = " LIKE ";
        $f_value = "%" . form_sql_like($value) . "%";
    } else {
        $f_term = "=";
        $f_value = form_sql($value);
    }
    list ($s_table_id, $s_field_id) = explode("|", $field['type_value']);
    if ($s_field_id) {
        $s_field = sql_select_array(FIELDS_TABLE, "id = ", $s_field_id);
        if (!empty($s_field)) {
            if ($s_field['type_field'] == 7 or $s_field['type_field'] == 11) {
                $result = sql_select_field(USERS_TABLE, "id", "fio" . $f_term . "'" . $f_value . "'");
                while ($row = sql_fetch_assoc($result)) {
                    $f_users[] = $row['id'];
                }
                if ($value === "") { // если поиск по пустой строке, добавляем пустые поля (id=0)
                    $f_users[] = 0;
                }
                $f_users = $f_users ? implode(",", $f_users) : "";
                $filter = $f_users !== "" ? form_int_name($s_field_id) . " IN (" . $f_users . ")" : "";
            } elseif ($s_field['type_field'] == 14) {
                $result = sql_select_field(GROUPS_TABLE, "id", "name" . $f_term . "'" . $f_value . "'");
                while ($row = sql_fetch_assoc($result)) {
                    $f_groups[] = $row['id'];
                }
                if ($value === "") { // если поиск по пустой строке, добавляем пустые поля (id=0)
                    $f_groups[] = 0;
                }
                $f_groups = $f_groups ? implode(",", $f_groups) : "";
                $filter = $f_groups !== "" ? form_int_name($s_field_id) . " IN (" . $f_groups . ")" : "";
            } elseif ($s_field['type_field'] == 4) {
                $filter = form_sql_type($s_field, $value, "search", $f_term);
            } elseif ($s_field['type_field'] == 5) {
                $f_lines = get_link_lines($s_field, $term, $value);
                $f_lines = $f_lines ? implode(",", $f_lines) : "";
                $filter = $f_lines ? form_int_name($s_field_id) . " IN (" . $f_lines . ")" : "";
            } elseif ($s_field['type_field'] != 9 && $s_field['type_field'] != 13) {
                if ($s_field['type_field'] == 2 || $s_field['type_field'] == 12) {
                    if (form_local_time(form_eng_time($value)) != substr($value, 0, 10) && $f_term == " LIKE ") {
                        if ($value == preg_replace('/[^\d\-: ]/i', '', $value)) {
                            $s_value = $value;
                        } else {
                            $s_value = "";
                        }
                    } elseif ($f_term == " LIKE ") {
                        $s_value = substr(form_eng_time($value), 0, strlen($value));
                    } else {
                        $s_value = form_eng_time($value);
                    }
                } else {
                    $s_value = form_sql_type($s_field, $value, "search");
                }
                if ($f_term == " LIKE ") {
                    $sql_value = "%" . form_sql_like($s_value) . "%";
                } else {
                    $sql_value = form_sql($s_value);
                }
                $filter = ($s_value !== "" && $s_value !== null) || $value === "" ? form_int_name($s_field_id) . $f_term . "'" . $sql_value . "'" : "";
            }
        }
    }
    $f_lines = array();
    $result = data_select_field($s_table_id, "id", $filter ? $filter : "0");
    while ($row = sql_fetch_assoc($result)) {
        $f_lines[] = $row['id'];
    }
    if ($value === "") { // если поиск по пустому значению
         // добавляем пустые поля связи (id = 0)
        $f_lines[] = 0;
         // добавляем осиротевшие записи
        $field_int_name = form_int_name($field['id']);
        $result = sql_query("SELECT $field_int_name FROM " . DATA_TABLE . $field['table_id'] .
                            " WHERE $field_int_name NOT IN (SELECT id FROM " . DATA_TABLE . $s_table_id . ")");
        while ($row = sql_fetch_assoc($result)) {
            if (strpos($row[$field_int_name], '-') == false) { // если поле связи с множ.выбором
                $all_value = array_filter(explode('-', $row[$field_int_name]));
                $f_lines = array_merge($f_lines, $all_value);
            } else {
                $f_lines[] = $row[$field_int_name];
            }

            if (count_cb($f_lines) > 1000) break;
        }
    }
    return $f_lines;
}

// Получение динамически формируемых полей
function get_control($field, $line, $value)
{
    global $tabindex_fast_edit, $lang, $config;

    $field_id = $field['id'];
    $line_id = $line['id'];
    $f_table_id = $field['table_id'];
    $f_table = get_table($f_table_id);
    $f_table_fields = get_table_fields($f_table);
    $field = $f_table_fields[$field_id];

    if ($field["type_field"] == 1 OR $field["type_field"] == 8 OR $field["type_field"] == 10 OR $field["type_field"] == 3) // Текст или число
    {
        $one_field = $field;

        if ($f_table['subtable']) {
            $subtable_id = $f_table['subtable'];
        }

        $st_id = $one_field["table_id"];
        $sf_id = $one_field["id"];
        $sl_id = $line["id"];
        $sf_idp = $sf_id . "_";
        $sf_ids = "";
        if ($subtable_id) {
            $sf_ids = "_" . $subtable_id;
        }

        if ($one_field['width']) {
            $adds_style = "width:" . $one_field['width'] . "px;";
        }

        $new_scr = "";

        if ($one_field['mult_value']) {
            $mult_value = 1;
        } else {
            $mult_value = 0;
        }

        $cur_value = $one_value["value"];
        $one_value["fast_edit_div"] = <<<EOD
<span tabindex="$tabindex_fast_edit" onfocus="var t=this.nextSibling; t.contentEditable=true; t.focus();"></span><div $adds_part
id="fast_edit_span_$sf_idp$sl_id$sf_ids"
tabindex="$tabindexp1_fast_edit"
contentEditable=false
class="fast_edit_span_$sf_idp$sl_id $adds_class fast_edit_text not-init" $adds_style
field_id="$sf_id"
line_id="$sl_id"
cur_value="$cur_value"
mult_value="$mult_value"
subtable_id="$subtable_id"
>
EOD;
        $one_value["value"] = $value;
        $one_value["fast_edit_div_full_value"] = $one_value["fast_edit_div"];
        $one_value["fast_edit_div_close"] = "</div>";
        $input_value = form_input_type($one_field, $line, $one_field['type_out']);
        if ($one_value["value"] === 0 || $one_value["value"] === '' || (!isset($one_value["value"]) && $part == "add_link_field")) {
            $one_value["value"] = $input_value['value'];
        }

        if ($part != "add_link_field") {
            if ($one_field["type_field"] != 3) {
                $align = "text-align:right;";
            }
            if ($one_field["type_field"] == 1) {
                $align_wrap = "white-space:nowrap;";
            }
            if ($mult_value) {
                if (strpos($one_field['type_value'], '{view_html}') === false) {
                    $textarea_height = 'height:15px;';
                }
            }

            $bord = 'style="border:0; padding-right:10px; outline:none;' . $adds_style . $align . $textarea_height . '"';
            $one_value["fast_edit_div_close"] = "";
        }

        if ($mult_value) {
            if (strpos($one_field['type_value'], '{view_html}') !== false) {
                $one_value["fast_edit_div"] = '<div class="fast_edit_span_' . $sf_idp . $sl_id . ' fast_edit_text html-editor-div not-init" id="edit_html_value_' . $sf_idp . $sl_id . $sf_ids . '" field_id="' . $sf_id . '" line_id="' . $sl_id . '" onclick="get_edit_html_value(\'' . $sf_idp . $sl_id . $sf_ids . '\');">' . $one_value["value"] . '</div>';
            } else {
                if ($part == "add_link_field") {
                    $bord = 'style="border: 1px dotted #a0a0a0;min-height:17px; outline:none; background: #fff;padding:0px;' . $adds_style . $align . '"';
                }
                $one_value["fast_edit_div"] = '<textarea rows="1"' . $adds_part . ' id="fast_edit_span_' . $sf_idp . $sl_id . $sf_ids . '" field_id="' . $sf_id . '" line_id="' . $sl_id . '" cur_value="' . $one_value["value"] . '" mult_value="' . $mult_value . '" subtable_id="' . $subtable_id . '" ' . $bord . '>' . $one_value["value"] . '</textarea>';
            }
        } else {
            if (strpos($one_field['type_value'], '{hyperlink}') !== false) {
                $one_value["fast_edit_div"] = '<div class="fast_edit_span_' . $sf_idp . $sl_id . ' fast_edit_text not-init fast_edit_text--hyperlink" id="edit_hyper_value_' . $sf_idp . $sl_id . $sf_ids . '" field_id="' . $sf_id . '" line_id="' . $sl_id . '" onclick="get_edit_hyper_value(\'' . $sf_idp . $sl_id . $sf_ids . '\');">' . $one_value["value"] . '</div>';
            } elseif (strpos($one_field['type_value'], '{view_html}') !== false) {
                $one_value["fast_edit_div"] = '<div class="fast_edit_span_' . $sf_idp . $sl_id . ' fast_edit_text not-init" id="edit_html_input_value_' . $sf_idp . $sl_id . $sf_ids . '" field_id="' . $sf_id . '" line_id="' . $sl_id . '" cur_value="' . $one_value["value"] . '" onclick="get_edit_html_input_value(\'' . $sf_idp . $sl_id . $sf_ids . '\');">' . $one_value["value"] . '</div>';
            } elseif ($part != "add_link_field")//$one_field["type_field"]==3 &&
            {
                $one_value["fast_edit_div"] = '<div class="fast_edit_span_' . $sf_idp . $sl_id . ' fast_edit_text not-init" id="edit_non_html_input_value_' . $sf_idp . $sl_id . $sf_ids . '" field_id="' . $sf_id . '" line_id="' . $sl_id . '" field_type="' . $one_field["type_field"] . '" onclick="get_edit_non_html_input_value(\'' . $sf_idp . $sl_id . $sf_ids . '\');" style="' . $adds_style . $align_wrap . '">' . $one_value["value"] . '</div>';
            } else {
                if ($part != "add_link_field") {
                    $type_text = "type='text'";
                }
                $one_value["fast_edit_div"] = '<input ' . $type_text . ' ' . $adds_part . ' value="' . htmlspecialchars($one_value["value"]) . '" id="fast_edit_span_' . $sf_idp . $sl_id . $sf_ids . '" field_id="' . $sf_id . '" line_id="' . $sl_id . '" cur_value="' . $one_value["value"] . '" mult_value="' . $mult_value . '" subtable_id="' . $subtable_id . '" ' . $bord . ' class="fast_edit_span_' . $sf_idp . $sl_id . ' fast_edit_text not-init ' . $adds_class . '"/>';
            }
        }

        $one_value["fast_edit_div_full_value"] = "";

        if ($part != "add_link_field") {
            $one_value["value"] = "";
        }

        $control = $one_value["fast_edit_div"] . $one_value["fast_edit_div_close"] . $new_scr;
    } elseif ($field['type_field'] == 2 OR $field["type_field"] == 12) // тип поля дата
    {
        $value = form_local_time($value, $field['type_value'], 0);

        if (test_allow_read($field, $line, "read")) {
            if ($field["type_value"]) {
                $input_lenght = 19;
            } else {
                $input_lenght = 10;
            }

            $control = <<<EOD
<span class='datepicker_span'><input id="fast_edit_span_{$field_id}_{$line_id}" type=text
SIZE=10
MAXLENGTH=10
class='datepicker fast_edit_datepicker not-init'
tabindex="800"
value='{$value}'
field_id="{$field_id}"
line_id="{$line_id}"
></span>
EOD;
        } else {
            $control = $value;
        }
    } elseif ($field["type_field"] == 4 OR $field["type_field"] == 13 OR $one_field["type_field"] == 7 OR $one_field["type_field"] == 11 OR $one_field["type_field"] == 14) // списки, пользователи
    {
        $value = form_display($value);
        $field['form_fast_edit_flag'] = 1;
        $input_value = form_input_type($field, $line);

        if (test_allow_read($field, $line, "read")) {
            $input_value = $input_value["input"];

            if ($field['mult_value']) {
                $control = <<<EOD
<input type=hidden id='fast_edit_span_{$field_id}_{$line_id} fast_edit_span--multi' value='{$value}'>
EOD;

                foreach ($input_value['set'] as $pos => $one_set) {
                    if ($pos == (count_cb($input_value['set']) - 1)) {
                        $is_last = 1;
                    } else {
                        $is_last = 0;
                    }

                    $control .= <<<EOD
<select tabindex="800"
id='fast_edit_span_{$field_id}_{$line_id}_{$pos}'
multi_select_group="{$field_id}_{$line_id}"
field_id="{$field_id}"
line_id="{$line_id}"
pos="{$pos}"
is_last="{$is_last}"
class="fast_edit_select sub_fast_edit_select"
>
EOD;
                    $control .= $one_set;
                    $control .= <<<EOD
</select>
EOD;
                }
                $control .= <<<EOD
EOD;
            } else {
                $control = <<<EOD
<select id='fast_edit_span_{$field_id}_{$line_id}'
tabindex="800"
field_id="{$field_id}"
line_id="{$line_id}"
class="fast_edit_select sub_fast_edit_select"
>
EOD;

                $control .= $input_value;
                $control .= "</select>";
            }
        } else {
            $control = str_replace("\r\n", "<br />", $value);
        }
    } elseif ($field['type_field'] == 5) // тип поля связь
    {
        $value = form_display($value);

        if (test_allow_read($field, $line, "read")) {
            $f_info = explode("|", $field['type_value']);
            $s_table = $f_info[0];
            if ($field['width']) {
                $field_width = $field['width'];
            } else {
                $field_width = 300;
            }

            $field_real_width = $field_width - 20;

            $new_tab = $config['open_links_in_new_tab'] ? 'target="_blank"' : '';

            $control = <<<EOD
<a
href="view_line2.php?table={$s_table}&line=0"
onclick="if (!event.ctrlKey) return false;"
class="fast_edit_link"
style="white-space: nowrap"
{$new_tab}
><input
class="sub_edit_link_input ac_input autocomplete not-init"
tabindex="800"
type="text"
id="fast_edit_span_{$field_id}_{$line_id}"
value="{$value}"
field_id="{$field_id}"
line_id="{$line_id}"
f_value="0"
autocomplete="off"
size="0"
field_width="{$field_width}"
><span class></span></a>
EOD;
        } else {
            $control = $value;
        }
    } else // тип поля неопределен - просто выводим значение $value
    {
        $control = $value;
    }
    return $control;
}

function channel_insert_id($link_identifier = 0)
{
    global $config, $last_sql_request, $sql_global_link, $sql_db_type;
    if ($link_identifier == 0) {
        $link_identifier = $sql_global_link;
    }
    $insert_id = sql_insert_id($link_identifier);
    $insert_table = substr($last_sql_request, 12, strpos($last_sql_request, " ", 12) - 12);
    $insert_table = str_replace('`', '', form_sql($insert_table));
    $dev_channel = (int)$config['dev_channel'];
    if (substr($insert_id, -1) != $dev_channel) {
        $new_insert_id = substr($insert_id, 0, -1) . $dev_channel;
    } else {
        $new_insert_id = $insert_id;
    }
    if ($new_insert_id < $insert_id) {
        $new_insert_id += 10;
    }
    if ($new_insert_id != $insert_id) {
        $sqlQuery = "UPDATE $insert_table SET id=$new_insert_id WHERE id=$insert_id";
        sql_query($sqlQuery, $link_identifier);
    }
    return $new_insert_id;
}

// Формирует путь из локальной кодировки в utf8
function local_to_utf_path($path)
{
    $str = $path;
    global $lang;
    $t_path = strtolower($path);
    $t_path = str_replace('\\', '/', $t_path);
    if (substr($t_path, 1, 2) == ':/') {
        if (function_exists('iconv')) {
            $str = iconv($lang['charset'], "utf-8", $path);
        }
    }
    return $str;
}

// Функция проверки состояния дистрибутива, возвращает массив ошибок
// ["php_module"]["zip"]["description"] - список не установленных модулей или работающих не правильно, в описании текст ошибки
// ["php_module"]["zip"]["help_url"]
// ["crc_check"]["files"]["common.php"] - список файлов с поврежденной контрольной суммой
// ["crc_check"]["description"]
// ["crc_check"]["help_url"]
// ["critical"] - критические ошибки, например изменен файл common.php
// ["critical"]["0"]["description"]
// ["critical"]["0"]["help_url"]
// ["critical"]["1"]["description"]="Ivalid zend"
// ["critical"]["1"]["help_url"]=
// ["critical"]["2"]["description"]="Invalid notice type"
// ["check_access"]["temp"]["full_path"]
// ["check_access"]["temp"]["description"]
// ["check_access"]["temp"]["help_url"]
// ["check_access"]["config.php"]["full_path"]
// ["check_access"]["config.php"][...]
// ["check_sync"]["sync_name"]["description"]
// ["check_sync"]["sync_name"]["help_url"]
//
// Параметр check_type - для медленных проверок, либо проверок только определенных модулей
// может принимать занчения "fast" - только быстрые проверки, не требующие много времени
//                          "sync" - проверяем только синхронизацию
//                          "smtp" - настройки сервера рассылки - пробуем отправить тестовое письмо
//                          "all"  - проверяем все медленные проверки.
function check_distr($check_type = "fast")
{
    global $lang, $config;
    $checks = array();
    // Проверка контрольных сумм файлов
    $invalid_check_summ = array();
    if (!file_exists($config['site_path'] . "/include/checksum.php")) {
        $cr_err["description"] = $lang["no_checksum_file"];
        $cr_err["help_url"] = "https://clientbase.ru/help/for_admin_16/trebovaniya/#checksum";
        $checks["critical"][] = $cr_err;
    } else {
        include $config['site_path'] . "/include/checksum.php";
        $already_alarm = array();
        foreach ($files_check_summ as $f_name => $info) {
            $f_path = str_replace('\\', '/', $config['site_path']) . "/" . $f_name;
            if (!file_exists($f_path)) {
                // Возможно не существует корневая папка, разворачиваем
                while (strlen($f_path) > 1) {
                    $bk_slash = strrpos($f_path, '/');
                    if (!$bk_slash) {  // Нет больше папок, нельзя подняться выше
                        break;
                    }
                    $base_dir = substr($f_path, 0, $bk_slash);
                    if (!file_exists($base_dir)) { // Не существует корневой каталог
                        $f_path = $base_dir;
                    } else {
                        break;
                    }
                }
                if ($already_alarm[$f_path]) {
                    continue;
                }
                $already_alarm[$f_path] = 1;
                // Проверка на существование корня
                $cr_err["description"] = $lang["Not_exists"] . $f_path;
                $cr_err["help_url"] = "https://clientbase.ru/help/for_admin_16/trebovaniya/#checksum";
                $checks["critical"][] = $cr_err;
            } else {
                if ($check_type != "all") {  // Быстрая проверка на размер
                    $p1 = strpos($f_name, '/');
                    if ($p1 !== false) {
                        if (strpos($f_name, '/', $p1 + 1) !== false) {
                            continue;
                        }
                    } // Пропускаем проверку двойной вложенности
                    if (filesize($f_path) != $info['size']) {
                        $cr_err["description"] = $lang["checksum_error"] . $f_path;
                        $cr_err["help_url"] = "https://clientbase.ru/help/for_admin_16/trebovaniya/#checksum";
                        $checks["critical"][] = $cr_err;
                        $invalid_check_summ[$f_name] = 1;
                    }
                } else {  // Полная проверка md5
                    $f_data = file_get_contents($f_path);
                    if ($f_data === false) {
                        $cr_err["description"] = $lang["Not_exists"] . $f_path;
                        $cr_err["help_url"] = "https://clientbase.ru/help/for_admin_16/trebovaniya/#checksum";
                        $checks["critical"][] = $cr_err;
                    } else {
                        if ($info['md5'] != md5($f_data)) { // Ошибка контролькой суммы
                            $cr_err["description"] = $lang["checksum_error"] . $f_path;
                            $cr_err["help_url"] = "https://clientbase.ru/help/for_admin_16/trebovaniya/#checksum";
                            $checks["critical"][] = $cr_err;
                            $invalid_check_summ[$f_name] = 1;
                        }
                    }
                }
            }
        }
        unset($already_alarm);
    }
    //if ($config['type']=="SAAS") return ;

    //Проверяем в MySQL max_allowed_packet
    if ($config['installed']) {
        //@sql_query("set @@global.show_compatibility_56=ON");
        $sqlQuery = "SHOW VARIABLES LIKE 'max_allowed_packet'";
        $result = sql_query($sqlQuery);

        while ($max_allowed_packet = sql_fetch_array($result)) {
            if ((int)$max_allowed_packet['Value'] < 16777216) {
                $checks["mysql"]['max_allowed_packet']["description"] = $lang["small_max_allowed_packet"] . $max_allowed_packet['Value'];
                $checks["mysql"]['max_allowed_packet']["help_url"] = "https://clientbase.ru/help/for_admin_16/trebovaniya/#mysql_max_allowed_packet";
            }
        }
    }

    // Проверка существования модулей
    $loaded_modules = get_loaded_extensions();
    $l_m = array(); // Переворачиваем и приводим к нижнему регистру
    foreach ($loaded_modules as $one_module) {
        $l_m[strtolower($one_module)] = 1;
    }
    $loaded_modules = $l_m;
    // Разворачиваем массив, меняем местами ключи и значения
    $requare_modules = array('gd', 'mbstring', 'openssl', 'imap', 'iconv', 'zip');
    foreach ($requare_modules as $module) {
        if (!$loaded_modules[$module]) {
            $checks["php_module"][$module]["description"] = $lang['no_php_module'] . $module;
            $checks["php_module"][$module]["help_url"] = "https://clientbase.ru/help/for_admin_16/trebovaniya/#php_module_" . $module;

            // Марикируем критические модули
            if (($module == "gd") || ($module == "mbstring") || ($module == "zip") || ($module == "iconv")) {
                $checks["critical"][] = $checks["php_module"][$module];
            }
        }
    }

    if ($invalid_check_summ['test_zend.php']) {
        return $checks;
    }

    if ((!$config['type'] == 'SAAS') && ini_get('session.use_trans_sid')) {
        $checks["sec"]['trans_sid']['description'] = $lang['used_trans_sid'];
        $checks["sec"]['trans_sid']['help_url'] == "https://clientbase.ru/help/for_admin_16/trebovaniya/#trans_sid";
        $checks["critical"][] = $checks["sec"]['trans_sid'];
    }

    // Выполняем проверку соответствия дистрибутива версии php
    $rev_file_info = @file_get_contents('revision');
    if ($rev_file_info) {
        $lns = explode("\n", $rev_file_info);
        $coder_inf = explode(": ", $lns[2]);
        $config['coded_by'] = $coder = $coder_inf[1];
    }
    $p_v = explode('.', PHP_VERSION);
    $p_v = $p_v[0] . "." . $p_v[1];

    if ($coder == 'zended_52' and $p_v > '5.2') {
        $cr["description"] = $lang['invalid_coded_zend'] . "5.3 .";
        $cr["help_url"] = "https://clientbase.ru/help/for_admin_16/trebovaniya/#invalid_coded_zend";
        $checks["critical"][] = $cr;
    } else {
        if ($coder == 'zended_53' and $p_v < '5.3') {
            $cr["description"] = $lang['invalid_coded_zend'] . "5.2 .";
            $cr["help_url"] = "https://clientbase.ru/help/for_admin_16/trebovaniya/#invalid_coded_zend";
            $checks["critical"][] = $cr;
        } else {
            // Проверка zend (ioncube)
            // Тест выполнением файла test_zended.php
            // т.к. ряд хостингов падает при запуске зашифрованного файла, то перехватываем выброс
            global $zended_test;
            $zended_test = "";
            function terminated_invalid_zend($buffer)
            {
                global $zended_test, $lang, $config;
                if ($zended_test != "fine") { // Программа упала на этапе тестирования zend, выводим ошибку обычным текстом, с ссылкой на описание проблемы
                    $buffer = "";
                    $buffer .= $lang['no_zend_installed'] . ". ";
                    $buffer .= "<a href='https://clientbase.ru/help/for_admin_16/trebovaniya/#zend_module'>" . $lang['Details'] . "...</a>";
                }
                return $buffer;
            }

            ob_start("terminated_invalid_zend");
            include "test_zend.php";
            ob_end_clean();
            if ($zended_test != "fine") { // Ошибка не установлен кодировщик
                $fd = fopen("common.php", "r");
                $str1 = fgets($fd);
                $str2 = fgets($fd);
                fclose($fd);
                if ($str1 == "<?php @Zend;\n") {
                    $cr["description"] = $lang['no_zend_installed'];
                    $cr["help_url"] = "https://clientbase.ru/help/for_admin_16/trebovaniya/#zend_module";
                    $checks["critical"][] = $cr;
                    if (!$config["coded_by"]) {
                        $config["coded_by"] = "zended";
                    }
                } elseif (strpos($str2, "ionCube Loader")) {
                    $cr["description"] = $lang['no_ioncube_installed'];
                    $cr["help_url"] = "https://clientbase.ru/help/for_admin_16/trebovaniya/#ioncube_module";
                    $checks["critical"][] = $cr;
                    if (!$config["coded_by"]) {
                        $config["coded_by"] = "ioncube";
                    }
                } else {
                    $cr["description"] = $lang['invalid_coded'] . $module;
                    $cr["help_url"] = "https://clientbase.ru/help/for_admin_16/trebovaniya/#invalid_coded";
                    $checks["critical"][] = $cr;
                }
            }
        }
    }

    // Проверка на включенные notice
    ob_start();
    include "test_notice.php";
    $notice_res = ob_get_contents();
    ob_end_clean();
    if (strpos($notice_res, 'NoThisVarWasSet')) { // Включен вывод нотисов
        $cr["description"] = $lang['notice_not_disabled'];
        $cr["help_url"] = "https://clientbase.ru/help/for_admin_16/trebovaniya/#notice_enabled";
        $checks["critical"][] = $cr;
    }

    // Проверка на функцию fsockopen в список запрещенных, с включенным параметром остановки скрипта в случае срабатывания запрещенной функции
    function disabled_function_fscockopen()
    {
        global $lang;
        return $lang["disabled_function_fsockopen"];
    }

    ob_start('disabled_function_fscockopen');
    $f = fsockopen('127.0.0.1', 80, $errno, $errstr, 3);
    $str = ob_get_clean();
    if (strpos($str,
        'has been disabled for security reasons')) { // Установлен disable_functions, который не приводит к fatal_error
        $cr["description"] = $lang["disabled_function_fsockopen"];
        $cr["help_url"] = "https://clientbase.ru/help/for_admin_16/trebovaniya/#disabled_function_fsockopen";
        $checks["critical"][] = $cr;
    }

    // Проверка каталогов на доступ
    $requare_folders = array('cache', 'files', 'temp', 'templates_c', 'backup');
    foreach ($requare_folders as $one_folder) {
        $full_path = $config['site_path'] . "/" . $one_folder;
        if (($one_folder == 'backup') && ($config['backup_path'])) {
            foreach ($config["backup_path"] as $one_path) { // Берем первую строку
                if (!$one_path) {
                    $full_path = $one_path;
                    break;
                }
            }
        }
        if (!file_exists($config['site_path'] . "/" . $one_folder)) { // Данная папка вообще не существует
            $checks["check_access"][$one_folder]["full_path"] = $full_path;
            $checks["check_access"][$one_folder]["description"] = $lang["no_folder_exists"] . $full_path;
            $checks["check_access"][$one_folder]["help_url"] = "https://clientbase.ru/help/for_admin_16/trebovaniya/#check_access";
        } else { // Проверяем права записи в нее
            $f = @fopen($full_path . "/test_write.txt", "w");
            if (!$f) {
                $checks["check_access"][$one_folder]["full_path"] = $full_path;
                $checks["check_access"][$one_folder]["description"] = $lang["invalid_write_rights"] . $full_path;
                $checks["check_access"][$one_folder]["help_url"] = "https://clientbase.ru/help/for_admin_16/trebovaniya/#check_access";
            } else {
                $rand = rand(0, 999999);
                $err_rights = 0;
                if (!@fwrite($f, $rand)) {
                    $err_rights = 1;
                } else {
                    if (!fclose($f)) {
                        $err_rights = 1;
                    } else {
                        $txt = @file_get_contents($full_path . "/test_write.txt");
                        if ($txt != $rand) {
                            $err_rights = 1;
                        } else {
                            if (!unlink($full_path . "/test_write.txt")) {
                                $err_rights = 1;
                            }
                        }
                    }
                }
                if ($err_rights) {
                    $checks["check_access"][$one_folder]["full_path"] = $full_path;
                    $checks["check_access"][$one_folder]["description"] = $lang["invalid_write_rights"] . $full_path;
                    $checks["check_access"][$one_folder]["help_url"] = "https://clientbase.ru/help/for_admin_16/trebovaniya/#check_access";
                } else { // Если папка files то возможны доп проверки

                    if (($check_type == "all") && ($one_folder == "files")) { // Полная проверка, проверяем вложенные папки на доступ
                        $fdir = $config['site_path'] . "/files";
                        $dirs1 = scandir($fdir);
                        foreach ($dirs1 as $d1_short) {
                            if ($d1_short[0] == '.') {
                                continue;
                            }
                            $d1 = $fdir . "/" . $d1_short;
                            if (!is_dir($d1)) {
                                continue;
                            }
                            $f = @fopen($d1 . "/test_write.txt", "w");
                            if (!$f) {
                                $checks["check_access"][$one_folder]["full_path"] = $d1;
                                $checks["check_access"][$one_folder]["description"] = $lang["invalid_write_rights"] . $d1;
                                $checks["check_access"][$one_folder]["help_url"] = "https://clientbase.ru/help/for_admin_16/trebovaniya/#check_access";
                                break;
                            } else {
                                fclose($f);
                                @unlink($d1 . "/test_write.txt");
                                $dirs2 = scandir($d1);
                                $dir2_count = count_cb($dirs2) - 2;
                                foreach ($dirs2 as $d2_short) {
                                    if ($d2_short[0] == '.') {
                                        continue;
                                    }
                                    $d2 = $d1 . "/" . $d2_short;
                                    $f = @fopen($d2 . "/test_write.txt", "w");
                                    if (!$f) {
                                        $checks["check_access"][$one_folder]["full_path"] = $d2;
                                        $checks["check_access"][$one_folder]["description"] = $lang["invalid_write_rights"] . $d2;
                                        $checks["check_access"][$one_folder]["help_url"] = "https://clientbase.ru/help/for_admin_16/trebovaniya/#check_access";
                                        break;
                                    }
                                    @unlink($d2 . "/test_write.txt");
                                }
                                if ($checks["check_access"][$one_folder]) {
                                    break;
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    // Проверка на включенный basedir и его корректность
    if ($config['type'] == 'WEB') {
        $b_dir = @ini_get('open_basedir');
        if ($b_dir) {  // Установлен basedir, проверяем входят ли временные каталоги в список разрешенных
            // Раскладываем basedir в виде массива каталогов
            if (strpos($b_dir, ';')) { // Windows style
                $b_dirs = explode(";", $b_dir);
            } else {
                if (strpos($b_dir, ':') > 2) { // Linux style
                    $b_dirs = explode(":", $b_dir);
                } else {
                    $b_dirs = array($b_dir);
                }
            }
            $invalid_upload = 1;
            foreach ($b_dirs as $one_dir) {
                if (substr($one_dir, -1, 1) == '/') {
                    $one_dir = substr($one_dir, 0, -1);
                }
                $u_dir = @ini_get('upload_tmp_dir');
                if ($u_dir) {
                    if (substr($u_dir, 0, strlen($one_dir)) === $one_dir) {
                        $invalid_upload = 0;
                    }
                }
            }
            if ($invalid_upload) {
                $buffer = $lang['Ivalid_basedir'];
                $buffer .= " <a href='https://clientbase.ru/help/for_admin_16/trebovaniya/#basedir'>" . $lang['Details'] . "...</a>";
                die($buffer);
            }
        }
    }

    // Доп проверка на корректность работы zip модуля
    if (!$checks["php_module"]["zip"] && !$checks["check_access"]["temp"]) {  // Пробуем создать архив а затем распаковать его
        $tmp_zip_name = $config['site_path'] . "/temp/test_arhive.zip";
        $zip = new ZipArchive;
        if (!$zip) {
            $checks["php_module"]["zip"]["description"] = $lang["invalid_php_module"] . "Can`t create ZipArchive object";
            $checks["php_module"]["zip"]["help_url"] = "https://clientbase.ru/help/for_admin_16/trebovaniya/#php_module_zip";
        } else {
            if (@$zip->open($tmp_zip_name, ZipArchive::CREATE) !== true) {
                $checks["php_module"]["zip"]["description"] = $lang["invalid_php_module"] . "Can`t create zip file: ($tmp_zip_name)";
                $checks["php_module"]["zip"]["help_url"] = "https://clientbase.ru/help/for_admin_16/trebovaniya/#php_module_zip";
            } else {
                if (!@$zip->addFile($config['site_path'] . "/common.php", 'common.php')) {
                    $checks["php_module"]["zip"]["description"] = $lang["invalid_php_module"] . "Can`t add to zip file: ($tmp_zip_name)";
                    $checks["php_module"]["zip"]["help_url"] = "https://clientbase.ru/help/for_admin_16/trebovaniya/#php_module_zip";
                }
                $zip->close();
            }
            unset($zip);
            // Распаковка
            $zip = new ZipArchive;
            if (@$zip->open($tmp_zip_name) !== true) {
                $checks["php_module"]["zip"]["description"] = $lang["invalid_php_module"] . "Can`t open zip file: ($tmp_zip_name)";
                $checks["php_module"]["zip"]["help_url"] = "https://clientbase.ru/help/for_admin_16/trebovaniya/#php_module_zip";
            } else {
                // Список файлов в архиве
                if ((!method_exists($zip, 'addEmptyDir')) || (!($zip->getNameIndex(0)))) {
                    $checks["php_module"]["zip"]["description"] = $lang["invalid_php_module"] . "Zip addEmptyDir or getNameIndex don't work.";
                    $checks["php_module"]["zip"]["help_url"] = "https://clientbase.ru/help/for_admin_16/trebovaniya/#php_module_zip";
                } else // Распаковка
                {
                    if (!@$zip->extractTo($config["site_path"] . "/temp")) {
                        $checks["php_module"]["zip"]["description"] = $lang["invalid_php_module"] . "Can`t extract zip file ($tmp_zip_name)";
                        $checks["php_module"]["zip"]["help_url"] = "https://clientbase.ru/help/for_admin_16/trebovaniya/#php_module_zip";
                    }
                }
                $zip->close();
            };
            unset($zip);

            // Зачищаем файлы
            @unlink($config["site_path"] . "/temp/common.php");
            @unlink($tmp_zip_name);
        }
    };
    $short_open_tag = ini_get('short_open_tag');
    if ($short_open_tag == 'Off') { // Проверка включены ли короткие теги
        $cr["description"] = $lang['invalid_short_open_tag'];
        $cr["help_url"] = "https://clientbase.ru/help/for_admin_16/trebovaniya/#short_open_tag";
        $checks["critical"][] = $cr;
    };

    // Проверка коректности работы строковых функций
    if ((strlen("Счет MWE_самострой с регсбором.rtf") != 57) || (mb_strlen("Счет MWE_самострой с регсбором.rtf") != 34)) {
        $cr["description"] = $lang['invalid_str_func_php'];
        $cr["help_url"] = "https://clientbase.ru/help/for_admin_16/trebovaniya/#string_functions";
        $checks["critical"][] = $cr;
    }

    // Проверка синхронизаций
    if ($check_type == "all" OR $check_type == "sync") {
        $sqlQuery = "SELECT * FROM " . SYNC_TABLE . " WHERE enabled='1'";
        $result = sql_query($sqlQuery);

        while ($row = sql_fetch_assoc($result)) {
            $sync_long_desc = $lang['Sync'] . " <a href=\"edit_sync.php?sync_id=" . $row['id'] . "\">" . $row['sync_name'] . "</a>: ";

            if ($row['sync_mode'] == 3 AND !$config["modules"]["1csync"]) {
                $checks["check_sync"][$row["sync_name"]]["description"] = $sync_long_desc . $lang['1c_integration'] . " " . $lang['1c_not_aсtived'];
                $checks["check_sync"][$row["sync_name"]]["short_descr"] = $lang['1c_integration'] . " " . $lang['1c_not_aсtived'];
                $checks["check_sync"][$row["sync_name"]]["help_url"] = "https://clientbase.ru/help/for_admin_16/sync/";
                $checks["check_sync"][$row["sync_name"]]["sync_id"] = $row['id'];
                continue;
            }

            if ($row['type_mode'] == 1 || $row['type_mode'] == 2) // Проверка внутренних папок для удалённых режимов
            {
                $sync_dir = "temp/sync_" . $row['id'];

                $check_dirs = array(
                    $sync_dir,
                    $sync_dir . "/export",
                    $sync_dir . "/export/files",
                    $sync_dir . "/import",
                    $sync_dir . "/import/files"
                );

                $err_msg = "";
                $err_dirs = array();
                foreach ($check_dirs AS $one_dir) {
                    if (!is_dir($one_dir)) {
                        if (!@mkdir($one_dir)) {
                            $err_dirs[] = $one_dir;
                        }
                    }
                }

                if ($err_dirs) {
                    foreach ($err_dirs AS $one_err_dir) {
                        $err_msg .= $lang['Sync_files_dir'] . "&quot;" . $one_err_dir . "&quot;" . $lang['Dir_not_exists'] . $lang['No_create_dir'] . "<br />";
                    }

                    $checks["check_sync"][$row["sync_name"]]["description"] = $sync_long_desc . $err_msg;
                    $checks["check_sync"][$row["sync_name"]]["short_descr"] = $err_msg;
                    $checks["check_sync"][$row["sync_name"]]["help_url"] = "https://clientbase.ru/help/for_admin_16/sync/";
                    $checks["check_sync"][$row["sync_name"]]["sync_id"] = $row['id'];
                    continue;
                }
            }

            if ($row['type_mode'] == 1) // Режим FTP
            {
                $ta = explode(":", $row['server']);
                list($ftp_server, $ftp_port) = $ta;
                $ftp_login = $row['login'];
                $ftp_pass = $row['password'];

                if ($ftp_port == "") {
                    $ftp_port = 21;
                }

                if ($ftp_connect = @ftp_connect($ftp_server, $ftp_port)) {
                    if (@ftp_login($ftp_connect, $ftp_login, $ftp_pass)) {
                        ftp_pasv($ftp_connect, true);

                        if (!@ftp_chdir($ftp_connect, $row['download_dir'])) {
                            $checks["check_sync"][$row["sync_name"]]["description"] = $sync_long_desc . $lang['Sync_no_dnl_dir'];
                            $checks["check_sync"][$row["sync_name"]]["short_descr"] = $lang['Sync_no_dnl_dir'];
                            $checks["check_sync"][$row["sync_name"]]["help_url"] = "https://clientbase.ru/help/for_admin_16/sync/#ftp";
                            $checks["check_sync"][$row["sync_name"]]["sync_id"] = $row['id'];
                        }

                        if (@ftp_chdir($ftp_connect, $row['upload_dir'])) {
                            if (@ftp_mkdir($ftp_connect, "testsync")) {
                                @ftp_rmdir($ftp_connect, "testsync");
                            } else {
                                $checks["check_sync"][$row["sync_name"]]["description"] = $sync_long_desc . $lang['invalid_write_rights'] . $row['upload_dir'];
                                $checks["check_sync"][$row["sync_name"]]["short_descr"] = $lang['invalid_write_rights'] . $row['upload_dir'];
                                $checks["check_sync"][$row["sync_name"]]["help_url"] = "https://clientbase.ru/help/for_admin_16/sync/#ftp";
                                $checks["check_sync"][$row["sync_name"]]["sync_id"] = $row['id'];
                            }
                        } else {
                            $checks["check_sync"][$row["sync_name"]]["description"] = $sync_long_desc . $lang['Sync_no_upl_dir'];
                            $checks["check_sync"][$row["sync_name"]]["short_descr"] = $lang['Sync_no_upl_dir'];
                            $checks["check_sync"][$row["sync_name"]]["help_url"] = "https://clientbase.ru/help/for_admin_16/sync/#ftp";
                            $checks["check_sync"][$row["sync_name"]]["sync_id"] = $row['id'];
                        }
                    } else {
                        $checks["check_sync"][$row["sync_name"]]["description"] = $sync_long_desc . $lang['Ftp_login_error'];
                        $checks["check_sync"][$row["sync_name"]]["short_descr"] = $lang['Ftp_login_error'];
                        $checks["check_sync"][$row["sync_name"]]["help_url"] = "https://clientbase.ru/help/for_admin_16/sync/#ftp";
                        $checks["check_sync"][$row["sync_name"]]["sync_id"] = $row['id'];
                    }
                } else {
                    $checks["check_sync"][$row["sync_name"]]["description"] = $sync_long_desc . $lang['Ftp_connect_error'];
                    $checks["check_sync"][$row["sync_name"]]["short_descr"] = $lang['Ftp_connect_error'];
                    $checks["check_sync"][$row["sync_name"]]["help_url"] = "https://clientbase.ru/help/for_admin_16/sync/#ftp";
                    $checks["check_sync"][$row["sync_name"]]["sync_id"] = $row['id'];
                }
            } elseif ($row['type_mode'] == 2 AND $row['sync_mode']) // Режим HTTP
            {
                if (strpos($row['server'], "http://") === false AND strpos($row['server'], "https://") === false) {
                    $row['server'] = "http://" . $row['server'];
                }

                $snoopy = new Snoopy\Snoopy;
                $snoopy->proxy_host = $config["proxy_host"];
                $snoopy->proxy_port = $config["proxy_port"];
                $snoopy->proxy_user = $config["proxy_user"];
                $snoopy->proxy_pass = $config["proxy_pass"];

                $post_data['login'] = $row['login'];
                $post_data['password'] = $row['password'];
                $post_data['sync_id'] = $row['remote_sync'];

                if (@$snoopy->submit($row['server'] . "/sync.php", $post_data)) {
                    if ($snoopy->status == 200) {
                        $post_result = $snoopy->results;

                        if (strpos($post_result, "SYNC_COMMAND;SYNC_ERROR;INCORRECT_LOGIN") !== false) {
                            $checks["check_sync"][$row["sync_name"]]["description"] = $sync_long_desc . $lang['Http_login_error'];
                            $checks["check_sync"][$row["sync_name"]]["short_descr"] = $lang['Http_login_error'];
                            $checks["check_sync"][$row["sync_name"]]["help_url"] = "https://clientbase.ru/help/for_admin_16/sync/#http";
                            $checks["check_sync"][$row["sync_name"]]["sync_id"] = $row['id'];
                        }

                        if (strpos($post_result, "SYNC_COMMAND;SYNC_ERROR;SYNC_NOT_FOUND") !== false) {
                            $checks["check_sync"][$row["sync_name"]]["description"] = $sync_long_desc . $lang['Http_sync_not_found'];
                            $checks["check_sync"][$row["sync_name"]]["short_descr"] = $lang['Http_sync_not_found'];
                            $checks["check_sync"][$row["sync_name"]]["help_url"] = "https://clientbase.ru/help/for_admin_16/sync/#http";
                            $checks["check_sync"][$row["sync_name"]]["sync_id"] = $row['id'];
                        }
                    } else {
                        $checks["check_sync"][$row["sync_name"]]["description"] = $sync_long_desc . $lang['Http_server_error'];
                        $checks["check_sync"][$row["sync_name"]]["short_descr"] = $lang['Http_server_error'];
                        $checks["check_sync"][$row["sync_name"]]["help_url"] = "https://clientbase.ru/help/for_admin_16/sync/#http";
                        $checks["check_sync"][$row["sync_name"]]["sync_id"] = $row['id'];
                    }
                } else {
                    $checks["check_sync"][$row["sync_name"]]["description"] = $sync_long_desc . $lang['Http_connect_error'];
                    $checks["check_sync"][$row["sync_name"]]["short_descr"] = $lang['Http_connect_error'];
                    $checks["check_sync"][$row["sync_name"]]["help_url"] = "https://clientbase.ru/help/for_admin_16/sync/#http";
                    $checks["check_sync"][$row["sync_name"]]["sync_id"] = $row['id'];
                }
                unset($snoopy);
            } elseif ($row['type_mode'] == 0) // Local
            {
                if (!@is_dir($row['download_dir'])) {
                    $checks["check_sync"][$row["sync_name"]]["description"] = $sync_long_desc . $lang['Sync_no_dnl_dir'];
                    $checks["check_sync"][$row["sync_name"]]["short_descr"] = $lang['Sync_no_dnl_dir'];
                    $checks["check_sync"][$row["sync_name"]]["help_url"] = "https://clientbase.ru/help/for_admin_16/sync/";
                    $checks["check_sync"][$row["sync_name"]]["sync_id"] = $row['id'];
                }

                if (@is_dir($row['upload_dir'])) {
                    if ($ft = @fopen($row['upload_dir'] . "/testsync.tmp", "w")) {
                        @fclose($ft);
                        @unlink($upl_dir . "/testsync.tmp");
                    } else {
                        $checks["check_sync"][$row["sync_name"]]["description"] = $sync_long_desc . $lang['invalid_write_rights'] . $row['upload_dir'];
                        $checks["check_sync"][$row["sync_name"]]["short_descr"] = $lang['invalid_write_rights'] . $row['upload_dir'];
                        $checks["check_sync"][$row["sync_name"]]["help_url"] = "https://clientbase.ru/help/for_admin_16/sync/";
                        $checks["check_sync"][$row["sync_name"]]["sync_id"] = $row['id'];
                    }
                } else {
                    $checks["check_sync"][$row["sync_name"]]["description"] = $sync_long_desc . $lang['Sync_no_upl_dir'];
                    $checks["check_sync"][$row["sync_name"]]["short_descr"] = $lang['Sync_no_upl_dir'];
                    $checks["check_sync"][$row["sync_name"]]["help_url"] = "https://clientbase.ru/help/for_admin_16/sync/";
                    $checks["check_sync"][$row["sync_name"]]["sync_id"] = $row['id'];
                }
            }
        }
    }
    if ($config['invalid_cron']) {
        $checks["cron"]["setup"]["description"] = $lang['invalid_cron'];
        $checks["cron"]["setup"]["help_url"] = 'https://clientbase.ru/help/for_admin_16/cron/';
    }

    return $checks;
}

// Функция проверки состояния базы, возвращает 1 - если база исправна
// Также исравляет найденные ошибки, если включен параметр repair
function check_database($repair = 0)
{
    global $config, $lang;
    $checks = array();
    // Проверяем таблицы на предмет ошибок битой базы и выполняем repair
    $sqlQuery = "SHOW TABLES";
    $result = sql_query($sqlQuery);
    $i = 0;
    echo "<script>window.onload=function (){ document.getElementById('show_if_error').style.display='block'; }</script>\n";
    echo "<div id=show_if_error style='display:none'>\n";
    echo "If you see this text check database failed! Possible you have too little max_execution time or too slow database. <br>\n";
    @ob_flush();
    flush();
    $cur_time = time();
    if ($config['type'] != 'SAAS') {
        while ($table_raw = sql_fetch_array($result)) {
            $table_name = $table_raw[0];
            if (substr($table_name, 0, strlen($config["table_prefix"])) == $config["table_prefix"]) {
                echo (time() - $cur_time) . " sec. Check table: " . $was_check_tables . " - " . $table_name . "<br>\n";
                @ob_flush();
                flush();
                // Делаем REPAIR, если была ошибка пишем в отчет
                $sqlQuery = "select engine from information_schema.tables where table_name='$table_name'";
                $result2 = sql_query($sqlQuery);
                $table_engine = sql_fetch_array($result2);
                $table_engine = $table_engine[0];
                if ($table_engine == "MyISAM") { // Ремонтируем
                    $sqlQuery = "REPAIR TABLE $table_name";
                    $result2 = sql_query($sqlQuery);
                    while ($repair_res = sql_fetch_assoc($result2)) {
                        if ($repair_res["Msg_text"] != "OK") {
                            if (strtolower($repair_res["Msg_type"]) == "error") {
                                $cr_err["description"] = $lang["Table_repair_fail"] . ' "' . $table_name . '": ' . $repair_res["Msg_text"];
                                $cr_err["help_url"] = "https://clientbase.ru/help/for_admin_16/db_errors/";
                                $checks["db"]["repair$i"] = $cr_err;
                            } else {
                                $cr_err["description"] = $lang["Table_repair_res"] . ' "' . $table_name . '": ' . $repair_res["Msg_text"];
                                $cr_err["help_url"] = "https://clientbase.ru/help/for_admin_16/db_errors/";
                                $checks["db"]["repair$i"] = $cr_err;
                            }
                            $i++;
                        }
                    }
                    // Оптимизируем
                    sql_query("OPTIMIZE TABLE " . $table_name);
                }
            }
        }
    }

    // Проверяем наличие полей в data, описанных в fields
    $number_tables = array();
    $sqlQuery = "SELECT * FROM " . FIELDS_TABLE;
    $result = sql_query($sqlQuery);
    while ($field = sql_fetch_array($result)) {
        if ($field['type_field'] == 8) {
            $number_tables[$field['table_id']] = $field['table_id'];
            $numer_fields[$field['table_id']] = $field;
        }
        $was_check_tables++;
        echo (time() - $cur_time) . " sec. Check fields exists in table: " . $was_check_tables . " - " . DATA_TABLE . $field['table_id'] . "<br>\n";
        @ob_flush();
        flush();
        //Проверяем наличие таблицы
        $sqlCheckTable = "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = '".$config['dbname']."' AND table_name = '".DATA_TABLE.$field['table_id']."'"; 
        $resultCheckTable = sql_query($sqlCheckTable);
        $rowCheckTable = sql_fetch_array($resultCheckTable);
        if ($rowCheckTable[0] == 0) {
            continue;
        }
        
        $sqlQuery = "SHOW COLUMNS FROM " . DATA_TABLE . $field['table_id'] . " LIKE '" . form_int_name($field['id']) . "'";
        $result2 = sql_query($sqlQuery);
        if (!sql_num_rows($result2)) { // поле не найдено, восстанавливаем
            // Вычисляем sql-тип поля
            list($type_value) = explode("\r\n", $field['type_value']);
            $field_type = sql_type($field['type_field'], $type_value, $field['mult_value']);
            if ($field['type_field'] == 3) { // при очень большом количестве полей, заменяем на text
                $sqlQuery = "select count(*) as cnt from " . FIELDS_TABLE . " WHERE table_id='" . $field['table_id'] . "'";
                $result3 = sql_query($sqlQuery);
                $row = sql_fetch_array($result3);
                if ($row['cnt'] > 30) {
                    $field_type = sql_type($field['type_field'], 0, 1);
                }
            }
            // Вычисляем предыдущее поле
            $sqlQuery = "SELECT id FROM " . FIELDS_TABLE . " WHERE id<" . $field['id'] . " and table_id=" . $field['table_id'] . " ORDER BY id DESC LIMIT 1";
            $result3 = sql_query($sqlQuery);
            $row = sql_fetch_array($result3);
            $prev_field = form_int_name($row['id']);
            // Собственно добавление поля в data
            $sqlQuery = "ALTER TABLE " . DATA_TABLE . $field['table_id'] . " ADD f" . $field['id'] . " " . $field_type . " AFTER " . $prev_field;
            sql_query($sqlQuery);
            // Заполняем значения по умолчанию
            $default_value = "'" . $field['default_value'] . "'";
            if ($field['autonumber']) {
                $result = data_select_field($field['table_id'], "min(id) as first_id, max(id) as last_id");
                $row = sql_fetch_array($result);
                $first_id = $row['first_id'];
                $last_id = $row['last_id'];
                $default_value = "id + " . ($field['default_value'] - $first_id);
                $field['default_value'] = $last_id + $field['default_value'] - $first_id + 1;
                sql_update(FIELDS_TABLE, array('default_value' => $field['default_value']), 'id=', $field_id);
            }
            if ($field['default_value'] == "{current}") {
                $default_value = "user_id";
            }
            if ($field['default_value'] == "{cur.time}") {
                $default_value = "add_time";
            }
            if ($field['default_value'] == "{cur.date}") {
                $default_value = "date(add_time)";
            }
            if ($field['default_value'] == "{current_group}") {
                $default_value = "(SELECT group_id FROM " . USERS_TABLE . " b WHERE b.id=a.user_id)";
            }
            sql_query("UPDATE " . DATA_TABLE . $field['table_id'] . " a SET f" . $field['id'] . "=" . $default_value);
        }
    }

    // Проверяем таблицы на существование полей типа Номер, в больших таблицах
    $was_check_tables++;
    echo (time() - $cur_time) . " sec. Check for num fields.";
    @ob_flush();
    flush();
    if ($number_tables) {
        $number_tables_str = implode(',', $number_tables);
        $result = sql_select(TABLES_TABLE, "id in ($number_tables_str)");
        while ($table = sql_fetch_array($result)) {
            $result2 = sql_select_field($config['table_prefix'] . "data" . $table['id'], "count(*) as cnt", "1=1");
            $count = sql_fetch_array($result2);
            if ($count['cnt'] > 1500) { // При более 1500 записей, не рекомендуется использовать поле номер
                $table_name = form_display($table['name_table']);
                $err["description"] = $lang["use_number_field1"] . ' "<a href="edit_field.php?table=' . $table['id'] . '&field=' . $numer_fields[$table['id']]['id'] . '">' . form_display($numer_fields[$table['id']]['name_field']) . '</a>" ' . $lang["use_number_field2"] . ' "' . $table_name . '"';
                $err["help_url"] = "https://clientbase.ru/help/for_admin_16/Field_types/#big_tables_numer_field";
                $checks["db"]["number_fields" . $table['id']] = $err;
            }
        }
    }
    echo "Database check DONE.";
    echo "</div>\n";
    echo "<script>document.getElementById('show_if_error').outerHTML=''</script>\n";
    // Проверяем таблицы на совпадение правильной структуры
    // Правильная структура таблиц без данных описана в файле null_dump.zip
    // Проверка структыры таблиц с данными производиться на основе шаблона указанного прямо в коде
    return $checks;
}

// Функция построения графиков типа Bars, Pie, Line
// параметры:
// type_graph : Bars, Pie, Line1, LineDate
// div_id : id div тега, в котором будет размещен график
// title : текст, заголовок графика
// title_fontSize : число. Размер шрифта заголовка в pt, например 16
// title_fontFamily : текст. Название шрифта заголовка , например Arial
// x_label, y_label : текст. Надпись по соответствующей оси для Line1
// x_fontSize, y_fontSize : число. Размер шрифта подписи в pt, по соответствующей оси для Line1
// x_fontFamily, y_fontFamily : текст. Название шрифта подписи по соответствующей оси для Line1
// series_names : текст. Название серий данных
// min и max : текст или число. Для задания границ графика
// zoom : true/false
function draw_graph($data, $settings)
{
    $div_id = $settings['div_id'];
    $user_colors = $settings['user_colors'];
    $return_str = '';
    $title = '';
    if ($settings['title']) {
        $title = "title: {
        text:'" . $settings['title'] . "'";
        if ($settings['title_fontSize']) {
            $title .= ",\n        fontSize: '" . $settings['title_fontSize'] . "pt'";
        }
        if ($settings['title_fontFamily']) {
            $title .= ",\n        fontFamily: '" . $settings['title_fontFamily'] . "'";
        }
        $title .= "\n      },";
    }
    $rand_g = rand(0, 99999);
    $return_str .= "<script>
  function draw_graph$rand_g(){\n";
    $return_str .= "    $.jqplot.config.enablePlugins = true;\n";

    switch ($settings['type_graph']) {

        case 'Bars': // ----------------------------  Bars
            // ищем самую длинную серию данных
            $num_series = count_cb($data); // кол-во серий данных
            $max_len_ser = 0;
            for ($i = 0; $i < $num_series; $i++) {
                if (count_cb($data[$i]) > $max_len_ser) {
                    $max_len_ser = count_cb($data[$i]);
                    $num_max_ser = $i;
                }
            }
            // формируем метки
            $tiks = array();
            $tiks_str = "    var ticks = [";
            foreach ($data[$num_max_ser] as $t => $s) {
                $tiks[] = $t;
                $tiks_str .= "'" . $t . "', ";
            }
            $return_str .= substr($tiks_str, 0, -2) . "];\n";

            // Формируем серии с проверкой пропущенных значений
            $ticks_y_check = 1;
            $series_list = '';
            for ($i = 0; $i < $num_series; $i++) {
                $series_list .= 's' . ($i + 1) . ', ';
                $series = "";
                for ($j = 0; $j < $max_len_ser; $j++) {
                    //$element = each($data[$i]);
                    $element = current($data[$i]); next($data[$i]);
                    if ($element) {
                        if ($tiks[$j] == $element['key']) {
                            if ($element['value'] != 0.1) {
                                $ticks_y_check = 0;
                            }
                            $series .= $element['value'] . ', ';
                        } else {
                            $series .= '0, ';
                            prev($data[$i]);
                        }
                    } else {
                        $series .= '0, ';
                    }
                }
                $return_str .= "    var s" . ($i + 1) . " = [" . substr($series, 0, -2) . "];\n";
            }
            if ($ticks_y_check) {
                $ticks_y = "ticks: [0,1,2,3,4]";
            } else {
                $ticks_y = "";
            }
            $series_list = substr($series_list, 0, -2);
            // строим график
            $return_str .= "    plot_bars = $.jqplot('" . $div_id . "', [" . $series_list . "], {
      " . $title . "
      seriesDefaults: {
        shadow:false,
        renderer:$.jqplot.BarRenderer,
        pointLabels: { show: true }
      },
      grid:{
        shadow:false,
        borderWidth: 0,
        background: '#fff',
      },
      axesDefaults:{
        tickOptions:{
            showMark:false,
            fontSize:'12px',
            fontFamily:'Arial',
          },
      },
      axes: {
        xaxis: {
          renderer: $.jqplot.CategoryAxisRenderer,
          ticks: ticks,
        },
        yaxis: {
          showMark:false,
          tickOptions:{
            formatString: '%.0f',
          },
          $ticks_y
        }
      }
    });\n";

            break; // ---------------------------- end Bars

        case 'Pie': // ----------------------------  Pie
            echo "<style>.jqplot-data-label {color:white}</style>";

            $colors = array(
                "'#3366cc'",
                "'#dc3912'",
                "'#ff9900'",
                "'#109618'",
                "'#990099'",
                "'#4bb2c5'",
                "'#c5b47f'",
                "'#71c49b'",
                "'#579575'",
                "'#839557'",
                "'#958c12'",
                "'#953579'",
                "'#4b5de4'",
                "'#d8b83f'",
                "'#ff5800'",
                "'#0085cc'"
            );
            $colors = implode(",", $colors);

            $pie_sum = array_sum($data);
            foreach ($data as $k => $v) {
                if (round(100 * $v / $pie_sum) >= 1) {
                    if ($user_colors[$k]) {
                        $n_colors["$v"] = "'" . $user_colors[$k] . "'";
                    } else {
                        $n_colors["$v"] = "'#" . substr(md5($k), 0, 6) . "'";
                    }
                }
            }
            krsort($n_colors);
            if (count_cb($n_colors) > 0) {
                $push_colors = "'#" . substr(md5('Остальное'), 0, 6) . "'";
                $colors = implode(",", $n_colors);
            }
            arsort($data);

            $return_str .= "    if ($('#" . $div_id . "').height() < $('#" . $div_id . "').width() && $('#" . $div_id . "').height() > 0)
                          {
                              var h_rows = $('#" . $div_id . "').height()/18/2;
                          }
                          else
                          {
                              var h_rows = $('#" . $div_id . "').width()/19/3;
                          }
                          var g_padding = $('#" . $div_id . "').width()/5;
                          var b_padding = -50;
                          var r_padding = g_padding/2;
                          var l_padding = g_padding/2;
                          var t_padding = 20;
                      \n";

            $series = '';
            $common_percent = 0;
            $common_count = 0;
            $common_var = 0;
            foreach ($data as $t => $s) {
                $pie_percent = round(100 * $s / $pie_sum);
                if ($pie_percent < 1) {
                    $common_count++;
                    $common_percent += (100 * $s / $pie_sum);
                    $common_var += $s;
                } else {
                    $pie_labels[] = "'" . $t . " (" . $pie_percent . " %)'";
                    $series .= "['" . $t . " ($pie_percent %)', " . $s . "], ";
                }
            }
            if ($common_count > 0) {
                $push_labels = "'Остальное (" . round($common_percent) . " %)'";
                $push = "['Остальное (" . round($common_percent) . " %)', " . round($common_var) . "]";
            }

            $return_str .= "    var data = [" . substr($series, 0, -2) . "];\n";
            $return_str .= "    data.splice((Number(h_rows)-1));\n";
            $return_str .= "    data.push($push);\n";

            $return_str .= "    var pie_labels = [" . implode(",", $pie_labels) . "];\n";
            $return_str .= "    pie_labels.splice((Number(h_rows)-1));\n";
            $return_str .= "    pie_labels.push($push_labels);\n";

            $return_str .= "    var colors = [" . $colors . "];\n";
            $return_str .= "    colors.splice((Number(h_rows)-1));\n";
            $return_str .= "    colors.push($push_colors);\n";

            $return_str .= "    var plot_pie = jQuery.jqplot ('" . $div_id . "', [data], {
      " . $title . "
      grid: {
        shadow: false,
        borderWidth: 0,
        background: '#fff',
      },
      gridPadding: {left: l_padding, right: r_padding, bottom: b_padding, top: t_padding},
      seriesDefaults: {
        shadow:false,
        renderer: jQuery.jqplot.PieRenderer,
        rendererOptions: {
          showDataLabels: true,
          sliceMargin: 3,
          padding: 0,
        },
        seriesColors: colors
      },
      legend: {
        renderer: $.jqplot.EnhancedLegendRenderer,
        rendererOptions: {
          numberRows: h_rows,
          numberColumns: 1
        },
        show:true,
        location:'e',
        labels: pie_labels
      }
    });\n";

            break; // ---------------------------- end Pie

        case 'Line1': // ----------------------------  Line1
            // Формируем серии
            $num_series = count_cb($data); // кол-во серий данных
            $series_list = '';
            for ($i = 0; $i < $num_series; $i++) {
                $series_list .= 's' . ($i + 1) . ', ';
                $series = "";
                foreach ($data[$i] as $k => $v) {
                    $series .= "[" . $k . "," . $v . "], ";
                }
                $return_str .= "    var s" . ($i + 1) . " = [" . substr($series, 0, -2) . "];\n";
            }
            $series_list = substr($series_list, 0, -2);

            $return_str .= "    var plot_line = $.jqplot('" . $div_id . "', [" . $series_list . "], {
      " . $title . "
      legend: {show:true, location: 'se'},
      axes:{
        xaxis:{
          tickRenderer:$.jqplot.CanvasAxisTickRenderer,
          label:'" . $settings['x_label'] . "',
          labelOptions:{
            fontFamily:'" . $settings['x_fontFamily'] . "',
            fontSize: '" . $settings['x_fontSize'] . "pt'
          },
          labelRenderer: $.jqplot.CanvasAxisLabelRenderer
        },
        yaxis:{
          tickRenderer:$.jqplot.CanvasAxisTickRenderer,
          labelRenderer: $.jqplot.CanvasAxisLabelRenderer,
          labelOptions:{
            fontFamily:'" . $settings['y_fontFamily'] . "',
            fontSize: '" . $settings['y_fontSize'] . "pt'
          },
          label:'" . $settings['y_label'] . "'
        }
      }";
            if ($settings['zoom']) { // zoom
                $return_str .= ",
      cursor:{
        show: true,
        zoom: true
      }\n";
            }
            $return_str .= "    });\n";

            break; // ---------------------------- end Line1

        case 'LineDate': // ----------------------------  LineDate
            if (!isset($settings['markerOptions'])) {
                $settings['markerOptions'] = array();
            }
            if (!isset($settings['markerOptions']['shadow'])) {
                $settings['markerOptions']['shadow'] = 'false';
            }
            $markerOptionsLine = "";
            foreach ($settings['markerOptions'] as $k => $v) {
                $markerOptionsLine .= $k . ":" . $v . ",";
            }
            $markerOptionsLine = substr($markerOptionsLine, 0, -1);
            if (!isset($settings['pointLabels'])) {
                $settings['pointLabels'] = array();
            }
            if (!isset($settings['pointLabels']['show'])) {
                $settings['pointLabels']['show'] = 'false';
            }
            $pointLabelsLine = "";
            foreach ($settings['pointLabels'] as $k => $v) {
                $pointLabelsLine .= $k . ":" . $v . ",";
            }
            $pointLabelsLine = substr($pointLabelsLine, 0, -1);
            //Формирует отметки по y
            if (!isset($settings['correction_values_y'])) {
                $settings['correction_values_y'] = true;
            }
            if ($settings['correction_values_y']) {
                $settings['y_max'] = ceil($settings['y_max'] / pow(10,
                            (strlen(abs((int)$settings['y_max'])) - 1))) * pow(10,
                        (strlen(abs((int)$settings['y_max'])) - 1));
                $settings['y_min'] = floor($settings['y_min'] / pow(10,
                            (strlen(abs((int)$settings['y_min'])) - 1))) * pow(10,
                        (strlen(abs((int)$settings['y_min'])) - 1));
            }
            /* Закоментированнны по заданию № 49 703
            if ($settings['y_min'] < 0 && $settings['y_max'] > 0) {
                $ticks = array();
                $ymax = $settings['y_max'];
                $ymin = $settings['y_min'];

                $prep = $ymax / 3;
                $prepy = -$ymin / 3;
                if ($prep > $prepy) {
                    $ticks[0] = 0 - $prep;
                    if ($ticks[0] > $ymin) {
                        $ticks[0] = $ymin;
                        $prep = -$ymin;
                    }
                    $ticks[1] = 0;
                    $ticks[2] = 0 + $prep;
                    for ($i = 3; $ymax > $s; $i++) {
                        $ticks[$i] = $ticks[$i - 1] + $prep;
                        $s = $ticks[$i];
                    }
                } else {
                    $s = -1;
                    $prep = -$ymin / 3;
                    $ticks[0] = $ymin;

                    for ($i = 1; $s < 0; $i++) {
                        $ticks[$i] = $ticks[$i - 1] + $prep;
                        $s = $ticks[$i];
                    }
                    if (isset($ticks[$i + 1])) {
                        $ticks[$i + 1] = 0;
                    }

                    $ticks[$i + 2] = $ticks[$i + 1] + $prep;
                }
                $ticks = implode(',', $ticks);
            }
            */

            // Смещение
            /* Закоментированнны по заданию № 49 703
            if (!$prep) {
                $prep = $settings['y_max'] / 5 * 1;
            }
            if ($data[0]) {
                foreach ($data[0] as $k => $v) {
                    $data[0][$k] = $v + $prep * 0.04;
                }
            }
            if ($data[1]) {
                foreach ($data[1] as $k => $v) {
                    $data[1][$k] = $v + $prep * 0.01;
                }
            }
            if ($data[2]) {
                foreach ($data[2] as $k => $v) {
                    $data[2][$k] = $v + $prep * 0.07;
                }
            }
            if ($data[3]) {
                foreach ($data[3] as $k => $v) {
                    $data[3][$k] = $v + $prep * 0.1;
                }
            }
            if ($data[4]) {
                foreach ($data[4] as $k => $v) {
                    $data[4][$k] = $v - $prep * 0.2;
                }
            }
            */

            // Формируем серии
            $sotkl = array();
            $num_series = count_cb($data); // кол-во серий данных
            $series_list = '';
            $nullGraf = 0;
            $nullColor = "'#3366cc'";
            $nullLegend = '';
            for ($i = 0; $i < $num_series; $i++) {
                $series_list .= 's' . ($i + 1) . ', ';
                $series = "";
                foreach ($data[$i] as $k => $v) {
                    $series .= "['" . $k . "'," . $v . "], ";
                    $sotkl[$i][$k] = $v;
                    if ($v != 0) {
                        $nullGraf = 1;
                    }
                }
                $return_str .= "    var s" . ($i + 1) . " = [" . substr($series, 0, -2) . "];\n";
            }
            $series_list = substr($series_list, 0, -2);

            if (!$nullGraf) {
                $nullColor = "(('\v'=='v')?'white':'transparent')";
                $nullLegend = 'showLabels:false,showSwatches:false,';
            }
            $return_str .= "     var plot_line_date = $.jqplot('" . $div_id . "', [" . $series_list . "], {
      " . $title . "
      legend: {
        " . $nullLegend . "
        renderer: $.jqplot.EnhancedLegendRenderer,";
            if ($settings['series_names']) {
                $return_str .= "\n        labels: [ " . $settings['series_names'] . " ],";
            }
            $return_str .= "\n        show:true,
        location: 's',
        placement: 'outsideGrid',
        fontFamily:'Arial',
        fontSize:'20px',
        textColor:'#666',
        rendererOptions: {
          numberRows: 1,
          numberColumns: 10,
          seriesToggle: false,
          disableIEFading: true
        }
      },
      seriesDefaults: {
        shadow: false,
        shadowAngle: 0,
        shadowOffset:0,
        shadowDepth:0,
        shadowAlpha:0,
        lineWidth: 3.5,
        pointLabels: { $pointLabelsLine },
        markerOptions:{ $markerOptionsLine }";
            $return_str .= "},
      seriesColors: [" . $nullColor . ", '#dc3912', '#ff9900', '#109618', '#990099',
                      '#4bb2c5', '#c5b47f', '#EAA228', '#579575', '#839557', '#958c12',
                        '#953579', '#4b5de4', '#d8b83f', '#ff5800', '#0085cc'],
      grid: {
        shadow: false,
        backgroundColor: (('\\v'=='v')?'white':'transparent'),
        drawBorder:false
      },
      axes: {
        xaxis: {";
            if ($settings['x_max']) {
                $return_str .= "\n          max: '" . $settings['x_max'] . "',";
            }
            if ($settings['x_min']) {
                $return_str .= "\n          min: '" . $settings['x_min'] . "',";
            }
            if ($settings['view_time']) {
                $time_format = "<br />%H:%M";
            }
            if ($settings['view_sec']) {
                $sec_format = ":%S";
            }
            $return_str .= "\n          renderer: $.jqplot.DateAxisRenderer,
          tickOptions: {
            formatString: '%d.%m.%y" . $time_format . $sec_format . "',
            showMark:false,
            fontSize:'12px',
            fontFamily:'Arial'
          }";
            if ($settings['ticks_x']) {
                $return_str .= ",ticks:[" . $settings['ticks_x'] . "]";
            }
            if ($settings['ticks_x_interval']) {
                $return_str .= ",tickInterval:'" . $settings['ticks_x_interval'] . "'";
            }
            $return_str .= "},
        yaxis: {";
            if ($settings['y_max']) {
                $return_str .= "\n          max: " . $settings['y_max'] . ",";
            }
            if ($settings['y_min']) {
                $return_str .= "\n          min: " . $settings['y_min'];
            } else {
                $return_str .= "\n          min:0";
            }
            $return_str .= ",
            tickOptions:{
              formatString: '%.0f',
              fontSize:'12px',
              fontFamily:'Arial',
              showMark:false
            },
            tickRenderer: $.jqplot.CanvasAxisTickRenderer,
            labelRenderer: $.jqplot.CanvasAxisLabelRenderer,
            labelOptions:{
              formatString: '%.0f',
              fontSize:'12px',
              fontFamily:'Arial',
              showMark:false
        }}}";
            if ($settings['zoom']) { // zoom
                $return_str .= ",
      cursor:{
        show: true,
        zoom: true
      }\n";
            }
            $return_str .= "    });\n";

            break; // ---------------------------- end LineDate

    } // end switch

    $return_str .= "  }; setTimeout(draw_graph$rand_g, 1000);
</script>\n";
    return $return_str;
}

function json_encode_visual($php_arr)
{
    return json_encode($php_arr, PHP_VERSION_ID >= 50400 ? JSON_UNESCAPED_UNICODE + JSON_PRETTY_PRINT : 0);
}

function is_mobile($w = 0, $h = 0)
{
    global $config;
    $w = (int)$_COOKIE['screen_width'];
    $h = (int)$_COOKIE['screen_height'];

    $max_w = 641;
    $max_h = 481;
    $is_mob = false;

    if (($w && $h) && ($w <= $max_w or $h <= $max_h)) { // проверка по разрешению
        $is_mob = true;
    } else { // проверка по данным $_SERVER
        $regex_match = "/(nokia|iphone|android|motorola|^mot\-|softbank|foma|docomo|kddi|up\.browser|up\.link|"
            . "htc|dopod|blazer|netfront|helio|hosin|huawei|novarra|CoolPad|webos|techfaith|palmsource|"
            . "blackberry|alcatel|amoi|ktouch|nexian|samsung|^sam\-|s[cg]h|^lge|ericsson|philips|sagem|wellcom|bunjalloo|maui|"
            . "symbian|smartphone|mmp|midp|wap|phone|windows ce|iemobile|^spice|^bird|^zte\-|longcos|pantech|gionee|^sie\-|portalmmm|"
            . "jig\s browser|hiptop|^ucweb|^benq|haier|^lct|opera\s*mobi|opera\*mini|320x320|240x320|176x220"
            . ")/i";

        if (preg_match($regex_match, strtolower($_SERVER['HTTP_USER_AGENT']))) {
            $is_mob = true;
        } elseif ((strpos(strtolower($_SERVER['HTTP_ACCEPT']),
                    'application/vnd.wap.xhtml+xml') > 0) or ((isset($_SERVER['HTTP_X_WAP_PROFILE']) or isset($_SERVER['HTTP_PROFILE'])))
        ) {
            $is_mob = true;
        }

        $mobile_ua = strtolower(substr($_SERVER['HTTP_USER_AGENT'], 0, 4));
        $mobile_agents = array(
            'w3c ',
            'acs-',
            'alav',
            'alca',
            'amoi',
            'audi',
            'avan',
            'benq',
            'bird',
            'blac',
            'blaz',
            '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',
            'mits',
            'mmef',
            'mobi',
            'mot-',
            'moto',
            'mwbp',
            'nec-',
            'newt',
            'noki',
            'palm',
            'pana',
            'pant',
            'phil',
            'play',
            'port',
            'prox',
            'qwap',
            'sage',
            'sams',
            'sany',
            'sch-',
            'sec-',
            'send',
            'seri',
            'sgh-',
            'shar',
            'sie-',
            'siem',
            'smal',
            'smar',
            'sony',
            'sph-',
            'symb',
            't-mo',
            'teli',
            'tim-',
            'tosh',
            'tsm-',
            'upg1',
            'upsi',
            'vk-v',
            'voda',
            'wap-',
            'wapa',
            'wapi',
            'wapp',
            'wapr',
            'webc',
            'winw',
            'winw',
            'xda ',
            'xda-'
        );

        if (in_array($mobile_ua, $mobile_agents)) {
            $is_mob = true;
        }

        if (isset($_SERVER['ALL_HTTP']) && strpos(strtolower($_SERVER['ALL_HTTP']), 'OperaMini') > 0) {
            $is_mob = true;
        }

        if ($is_mob) {
            $w = $max_w - 1;
            $h = $max_h - 1;
        }
    }

    // устанавливаем соответствующие куки, если мобильная
    if ($is_mob) {
        setcookie('is_mobile', 1);
        $config['is_mobile'] = 1;
    } else {
        setcookie('is_mobile', 0);
        $config['is_mobile'] = 0;
    }
}

// Список полей для мастера вычислений
function get_scw_fields($base_field, $table_id, $table_fields, &$scw_fields = array(), $level = 1)
{
    foreach ($table_fields as $scw_field) {
        if ($scw_field['id'] != $base_field['id'] and ($scw_field['type_field'] == 5 or ($base_field['type_field'] == 1 and $scw_field['type_field'] == 1) or ($level > 1 and $scw_field['type_field'] == $base_field['type_field']))) {
            $scw_fields[$table_id][$scw_field['id']] = $scw_field;
            if ($scw_field['type_field'] == 5) {
                $rel_table = get_table($scw_field['s_table_id']);
                $rel_table_fields = get_table_fields($rel_table);
                $scw_fields[$table_id][$scw_field['id']]['s_name_table'] = $rel_table['name_table'];
                if (!$scw_fields[$scw_field['s_table_id']]) {
                    get_scw_fields($base_field, $scw_field['s_table_id'], $rel_table_fields, $scw_fields, $level + 1);
                    if (!$scw_fields[$scw_field['s_table_id']] and $scw_field['s_table_id'] != $base_field['s_table_id']) {
                        unset($scw_fields[$table_id][$scw_field['id']]);
                    }
                }
            }
        }
    }
    return $scw_fields;
}

// Прерывание работы скрипта с подключением шапки и подвала программы (свой аналог "die()" или "exit()");
// $die_text - текст сообщения
// $help_id  - идентификатор подсказки
// $cat - показывать ли категории при ошибке (нет по умолч)
//   0 - не показывать категории
//   1 - скрыть категории
//   2 - не показывать шапку вообще
function cb_die($die_text, $help_id = "", $cat = -1, $return_string = 0)
{
    global $user, $user_default_page, $cur_cat, $cur_table, $cur_report, $cur_calendar, $user_cats, $config, $lang, $script_name, $version, $res_error_die, $smarty;

    $is_mobile = (int)$_COOKIE['is_mobile'];

    if ($is_mobile) {
        if (!$res_error_die) {
            $res_error_die = $die_text;
        }
        $res_error_die = str_replace("<br><br><a href='javascript:history.go(-1)'>" . $lang['Return'] . "</a>",
            "<br><br><a href='#' onclick='mainView.goBack();return false;'>" . $lang['Return'] . "</a>",
            $res_error_die);
        //$res_error_die = str_replace("<br><br><a href='javascript:history.go(-1)'>".$lang['Return']."</a>",
        //                             "<br><br><a href='index.php' class='external'>Обновить</a>", $res_error_die);
        $smarty->assign("error", $res_error_die);
        smarty_display("cb_die");
        exit;
    }

    if ((isset($config['cb_die_show_cat'])) && ($cat == -1)) {
        $cat = $config['cb_die_show_cat'];
    } else {
        if ($cat == -1) {
            $cat = 0;
        }
    }

    if (($cat == 2) || ($script_name == 'cron.php')) // Вызов из крона, либо ajax
    {
        echo "\n $die_text";
        exit;
    }

    global $php_total_time, $sql_requests_count;
    include $config['site_path'] . "/templates/cb_die.tpl";
    if ($return_string !== 0) {
        return $res_error_die;
    } else {
        echo $res_error_die;
        include "index_bottom.php";
        exit;
    }
}

// Корректная альтернатива для basename() - выделение имени файла из пути
function alt_basename($path)
{
    $path = str_replace("\\", "/", $path);
    $file_name = mb_substr($path, mb_strrpos($path, "/") + 1);
    return $file_name;
}

// На основе массива условий, создать вычисление на php
// обрабатывающего данное условие, вычисление формируется по умочанию с переменной $line
function form_php_condition($cond_array, $cond_var = '$line')
{
    $php_condition = "";
    foreach ($cond_array as $one_cond) {
        $cond_link_id = " ";
        $one_cond['source_value'] = $one_cond['value'];

        if ($one_cond['field'] == 999999999) {
            $field_name = '$user[\'id\']';
        } elseif ($one_cond['field'] == 999999998) {
            $field_name = '$user[\'group_id\']';
        } else {
            $field_name = form_int_name($one_cond['field']);
        }
        if ($one_cond['term'] == '=') {
            $one_cond['term'] = '==';
        }

        if ($one_cond['oper'] && $one_cond['interval'] && $one_cond['period']) {
            $one_cond['oper'] = substr($one_cond['oper'], 0, 3);
            if (($one_cond['source_value'] === 'week()') || ($one_cond['source_value'] === 'half_month()') || ($one_cond['source_value'] === 'month()') || ($one_cond['source_value'] === 'year()')) {
                $cond_date = 'strtotime(\'' . $one_cond['oper'] . $one_cond['interval'] . $one_cond['period'] . '\', ';
            } else {
                $cond_date = ', strtotime(\'' . $one_cond['oper'] . $one_cond['interval'] . $one_cond['period'] . '\')';
            }
        } else {
            $cond_date = "";
        }

        if ($one_cond['open_bracket']) {
            $php_condition .= '(';
        }

        if ($one_cond['value'] === '{current}') {
            $one_cond['value'] = '$user[\'id\']';
        } elseif ($one_cond['value'] === '-{current}-') {
            $one_cond['value'] = '"-".$user[\'id\']."-"';
        } elseif ($one_cond['value'] === '{current_group}') {
            $one_cond['value'] = '$user[\'group_id\']';
        } elseif ($one_cond['value'] === 'fix_date') {
            $one_cond['value'] = "'" . $one_cond['date'] . "'";
        } elseif ($one_cond['value'] === 'now()') {
            $one_cond['value'] = 'date(\'Y-m-d H:i:s\'' . $cond_date . ')';
        } elseif ($one_cond['value'] === 'curdate()') {
            $one_cond['value'] = 'date(\'Y-m-d\'' . $cond_date . ')';
        } elseif ($one_cond['value'] === 'week()') {
            $begin = "strtotime('last Monday')";
            $end = "strtotime('Sunday')";
        } elseif ($one_cond['value'] === 'half_month()') {
            $begin = "strtotime('last Monday')";
            $end = "strtotime('Sunday')";
        } elseif ($one_cond['value'] === 'month()') {
            $begin = "strtotime('first day of this month')";
            $end = "strtotime('last day of this month')";
        } elseif ($one_cond['value'] === 'year()') {
            $begin = "strtotime('first day of January this year')";
            $end = "strtotime('last day of December this year')";
        } elseif (isset($one_cond['value_link'])) {
            if ($one_cond['value_link'] === '') {
                $one_cond['value_link'] = 0;
            }
        } else {
            $one_cond['value'] = "'" . $one_cond['value'] . "'";
        }

        if (isset($one_cond['value_link'])) {
            if (trim($one_cond['term']) == 'like') {
                $php_condition .= "((is_array(" . $cond_var . "['" . $field_name . "']) && strpos(" . $cond_var . "['" . $field_name . "']['raw'], '-" . $one_cond['value_link'] . "-')!==false) || " .
                    "(!is_array(" . $cond_var . "['" . $field_name . "']) && strpos(" . $cond_var . "['" . $field_name . "'], '-" . $one_cond['value_link'] . "-')!==false) || " .
                    "(is_array(" . $cond_var . "['" . $field_name . "']) && " . $cond_var . "['" . $field_name . "']['raw']==" . str_replace('-', '', $one_cond['value_link']) . ") || " .
                    "(!is_array(" . $cond_var . "['" . $field_name . "']) && " . $cond_var . "['" . $field_name . "']==" . str_replace('-', '', $one_cond['value_link']) . "))";
            } elseif ($one_cond['term'] == ' not like ') {
                $php_condition .= '(strpos(' . $cond_var . "['" . $field_name . "']['raw'], '-" . $one_cond['value_link'] . "-')===false || " .
                    $cond_var . "['" . $field_name . "']['raw']==" . str_replace('-', '', $one_cond['value_link']) . ')';
            } else {
                $php_condition .= "((is_array(" . $cond_var . "['" . $field_name . "']) && trim(" . $cond_var . "['" . $field_name . "']['raw'], '-')" . $one_cond['term'] . "'" . $one_cond['value_link'] . "') || " .
                    "(!is_array(" . $cond_var . "['" . $field_name . "']) && trim(" . $cond_var . "['" . $field_name . "'], '-')" . $one_cond['term'] . "'" . $one_cond['value_link'] . "'))";
            }
        } elseif (trim($one_cond['term']) == 'like') {
            if (preg_match("#^'-([^-]*?)-'$#", $one_cond['value'])) {
                $php_condition .= '(strpos(' . $cond_var . "['" . $field_name . "'], " . $one_cond['value'] . ')!==false || ' .
                    $cond_var . "['" . $field_name . "']==" . str_replace('-', '', $one_cond['value']) . ')';
            } else {
                $php_condition .= '(strpos(' . $cond_var . "['" . $field_name . "'], " . $one_cond['value'] . ')!==false)';
            }
        } elseif ($one_cond['term'] == ' not like ') {
            if (preg_match("#^'-([^-]*?)-'$#", $one_cond['value'])) {
                $php_condition .= '(strpos(' . $cond_var . "['" . $field_name . "'], " . $one_cond['value'] . ')===false || ' .
                    $cond_var . "['" . $field_name . "']==" . str_replace('-', '', $one_cond['value']) . ')';
            } else {
                $php_condition .= '(strpos(' . $cond_var . "['" . $field_name . "'], " . $one_cond['value'] . ')===false)';
            }
        } elseif (($one_cond['source_value'] === 'week()') || ($one_cond['source_value'] === 'half_month()') || ($one_cond['source_value'] === 'month()') || ($one_cond['source_value'] === 'year()')) {
            $begin = $cond_date ? $cond_date . $begin . ')' : $begin;
            $end = $cond_date ? $cond_date . $end . ')' : $end;
            if ($one_cond['term'] == "==") {
                $php_condition .= '(strtotime(' . $cond_var . "['" . $field_name . "'])" . '>=' . $begin . ' && strtotime(' . $cond_var . "['" . $field_name . "'])" . '<=' . $end . ')';
            } elseif ($one_cond['term'] == "!=") {
                $php_condition .= '(strtotime(' . $cond_var . "['" . $field_name . "'])" . '<=' . $begin . ' || strtotime(' . $cond_var . "['" . $field_name . "'])" . '>=' . $end . ')';
            } elseif ($one_cond['term'] == ">") {
                $php_condition .= '(strtotime(' . $cond_var . "['" . $field_name . "'])" . '>' . $end . ')';
            } elseif ($one_cond['term'] == "<") {
                $php_condition .= '(strtotime(' . $cond_var . "['" . $field_name . "'])" . '<' . $begin . ')';
            } elseif ($one_cond['term'] == ">=") {
                $php_condition .= '(strtotime(' . $cond_var . "['" . $field_name . "'])" . '>=' . $begin . ')';
            } elseif ($one_cond['term'] == "<=") {
                $php_condition .= '(strtotime(' . $cond_var . "['" . $field_name . "'])" . '<=' . $end . ')';
            }
        } elseif ($one_cond['source_value'] === 'now()') {
            $php_condition .= '(strtotime(' . $cond_var . "['" . $field_name . "'])" . $cond_link_id . $one_cond['term'] . ' strtotime(' . $one_cond['value'] . '))';
        } elseif ($one_cond['source_value'] === 'curdate()') {
            $php_condition .= '(strtotime(substr(' . $cond_var . "['" . $field_name . "'],0,10))" . $cond_link_id . $one_cond['term'] . ' strtotime(substr(' . $one_cond['value'] . ',0,10)))';
        } else {
            // Обычное условие
            if ($one_cond['field'] != 999999999 && $one_cond['field'] != 999999998) {
                $php_condition .= '(' . $cond_var . "['" . $field_name . "']" . $cond_link_id . $one_cond['term'] . $one_cond['value'] . ')';
            } else {
                $php_condition .= '(' . $field_name . $one_cond['term'] . $one_cond['value'] . ')';
            }
        }

        if ($one_cond['close_bracket']) {
            $php_condition .= ')';
        }

        $php_condition .= $one_cond['union'];
   }
    return $php_condition;
}

// На основе массива условий, создать фильтр на sql
// обрабатывающего данное условие, вычисление формируется по умочанию с переменной $line
function form_sql_condition($cond_array, $table_prefix = '')
{
    $sql_condition = '';
    foreach ($cond_array as $one_cond) {
        if ($one_cond['field'] == 999999999) {
            $field_name = "'{current}'";
        } elseif ($one_cond['field'] == 999999998) {
            $field_name = "'{current_group}'";
        } else {
            $field_name = form_int_name($one_cond['field']);
        }
        if ($one_cond['value'] == 'curdate()') {
            $field_name = 'left(' . $field_name . ', 10)';
        }
        if ($one_cond['term'] == ' like ' || $one_cond['term'] == ' not like ') {
            $one_cond['value'] = '%' . $one_cond['value'] . '%';
        }
        if ($one_cond['oper'] && $one_cond['interval'] && $one_cond['period']) {
            $cond_date = $one_cond['oper'] . $one_cond['interval'] . $one_cond['period'];
        } else {
            $cond_date = '';
        }
        if ($one_cond['value_link']) {
            $one_cond['value'] = "'" . $one_cond['value_link'] . "'";
        } elseif ($one_cond['value'] != 'now()' && $one_cond['value'] != 'curdate()') {
            $one_cond['value'] = "'" . $one_cond['value'] . "'";
        }
        $sql_condition .= $one_cond['open_bracket'] ? '((' : '(';
        $sql_condition .= $table_prefix ? $table_prefix . '.' : '';
        $sql_condition .= $field_name . $one_cond['term'] . $one_cond['value'] . $cond_date;
        $sql_condition .= $one_cond['close_bracket'] ? '))' : ')';
        $sql_condition .= $one_cond['union'];
    }
    return $sql_condition;
}


// Проверка полей перед удалением, используются ли они в отчётах/вычислениях/фильтрах по полю связи
// Возвращает сформированный массив из имён и ид вычислений, таблиц, доп. действий
// $del_table - если удаляется таблица, то проверять является ли поле фильтром не нужно
function check_field_actions($field_id, $del_table = 0)
{
    global $config;

    $field_id = (int)$field_id;
    $sel_limit = 20;
    if (!$field = sql_select_array(FIELDS_TABLE, "id=", $field_id)) {
        cb_die("Field not found");
    }
    if ($del_table) {
        $table_cond = " AND calc.table_id<>'{$field['table_id']}'";
    }
    $output['buttons'] = array();
    $output['calcs'] = array();
    $output['reports'] = array();
    $output['crons'] = array();
    $output['fields'] = array();
    $output['subtables'] = array();
    $output['addittables'] = array();
    $output['print_template'] = array();
    $output['calendars'] = array();
    $output['ext_files'] = array();

    // Проверка поля в вычислениях и доп. действиях
    $sqlQuery = "SELECT tables.name_table AS parent_name, calc.name AS calc_name, calc.table_id AS link_id, calc.id AS calc_id, calc.help AS calc_help
                FROM " . TABLES_TABLE . " AS tables, " . CALC_TABLE . " AS calc
                WHERE (
                      calc.calculate LIKE '%\\'f{$field_id}\\'%'
                      OR calc.calculate LIKE '%\"f{$field_id}\"%'
                      OR calc.calculate LIKE '%`f{$field_id}`%'
                      OR calc.calculate LIKE '%f{$field_id} %'
                      OR calc.calculate LIKE '%f{$field_id}*%'
                      OR calc.calculate LIKE '%f{$field_id}+%'
                      OR calc.calculate LIKE '%f{$field_id}-%'
                      OR calc.calculate LIKE '%f{$field_id}/%'
                      OR calc.calculate LIKE '%f{$field_id})%'
                      OR calc.calculate LIKE '%f{$field_id}=%'
                      OR calc.calculate LIKE '%f{$field_id}>%'
                      OR calc.calculate LIKE '%f{$field_id}<%'
                      OR calc.calculate LIKE '%f{$field_id}!%'
                      OR calc.calculate LIKE '%f{$field_id}^%'
                      OR calc.calculate LIKE '%set_filter({$field_id},%'
                      OR calc.calculate LIKE '%f{$field_id},%'
                  )
                  AND tables.id=calc.table_id{$table_cond}
                  AND calc.disabled='0'
                LIMIT {$sel_limit}";
    $result = sql_query($sqlQuery);
    while ($row = sql_fetch_assoc($result)) {
        $pre_data = array();
        $sel_limit -= 1;
        if (strpos($row['calc_name'], "Button") !== false) { // Вычисление является кнопкой доп. действия
            $button_id = str_replace("Button ", "", $row['calc_name']);
            $subresult = sql_select_field(BUTTONS_TABLE, 'name, help, disabled', 'id = ', $button_id);
            if ($subrow = sql_fetch_assoc($subresult)) {
                if ($subrow['disabled'] == 0) { // учитываем только включенные ДД
                    $pre_data['action_name'] = $subrow['name'];
                    $pre_data['action_id'] = $button_id;
                    $pre_data['table_name'] = $row['parent_name'];
                    $pre_data['help'] = $subrow['help'];
                    $output['buttons'][$row['link_id']][] = $pre_data;
                }
                continue;
            }
        }

        $pre_data['calc_name'] = $row['calc_name'];
        $pre_data['calc_id'] = $row['calc_id'];
        $pre_data['table_name'] = $row['parent_name'];
        $pre_data['help'] = $row['calc_help'];
        $output['calcs'][$row['link_id']][] = $pre_data;
    }

    if ($sel_limit > 0) { // Участие в отчётах
        $result = sql_query("
            SELECT cats.name AS cat_name, reports.name AS rep_name, cats.id AS cat_id, reports.id AS rep_id, reports.help AS rep_help, IF(code = 'yaml', 1, 0) as ko
            FROM " . CATS_TABLE . " AS cats, " . REPORTS_TABLE . " AS reports
            WHERE (
                reports.code LIKE '%\\'f{$field_id}\\'%'
                OR reports.code LIKE '%\"f{$field_id}\"%'
                OR reports.code LIKE '%`f{$field_id}`%'
                OR reports.code LIKE '%f{$field_id} %'
                OR reports.code LIKE '%f{$field_id}*%'
                OR reports.code LIKE '%f{$field_id}+%'
                OR reports.code LIKE '%f{$field_id}-%'
                OR reports.code LIKE '%f{$field_id}/%'
                OR reports.code LIKE '%f{$field_id})%'
                OR reports.code LIKE '%f{$field_id}=%'
                OR reports.code LIKE '%f{$field_id}>%'
                OR reports.code LIKE '%f{$field_id}<%'
                OR reports.code LIKE '%f{$field_id}!%'
                OR reports.code LIKE '%f{$field_id}^%'
                OR reports.code LIKE '%set_filter({$field_id},%'
                OR reports.code LIKE '%f{$field_id},%'
                OR reports.code LIKE '%yaml%' AND reports.form LIKE '%f{$field_id}%'
                OR reports.code LIKE '%yaml%' AND reports.form LIKE '%|f{$field_id}|%'
                OR reports.code LIKE '%yaml%' AND reports.form LIKE '%field|f{$field_id}%'
                OR reports.code LIKE '%yaml%' AND reports.form LIKE '%link|f{$field_id}%'
            )
            AND cats.id=reports.cat_id LIMIT $sel_limit"
        );
        while ($row = sql_fetch_assoc($result)) {
            $sel_limit -= 1;

            $output['reports'][$row['cat_id']][] = [
                'report_name' => $row['rep_name'],
                'report_id'   => $row['rep_id'],
                'cat_name'    => $row['cat_name'],
                'help'        => $row['rep_help'],
                'ko'          => $row['ko'],
            ];
        }
    }

    if ($sel_limit > 0) { // Участие в кроне
        $sqlQuery = "SELECT crons.description AS cron_name, crons.id AS cron_id, crons.help AS cron_help
                  FROM " . CRON_TABLE . " AS crons
                  WHERE (
                        crons.command LIKE '%\\'f{$field_id}\\'%'
                        OR crons.command LIKE '%\"f{$field_id}\"%'
                        OR crons.command LIKE '%`f{$field_id}`%'
                        OR crons.command LIKE '%f{$field_id} %'
                        OR crons.command LIKE '%f{$field_id}*%'
                        OR crons.command LIKE '%f{$field_id}+%'
                        OR crons.command LIKE '%f{$field_id}-%'
                        OR crons.command LIKE '%f{$field_id}/%'
                        OR crons.command LIKE '%f{$field_id})%'
                        OR crons.command LIKE '%f{$field_id}=%'
                        OR crons.command LIKE '%f{$field_id}>%'
                        OR crons.command LIKE '%f{$field_id}<%'
                        OR crons.command LIKE '%f{$field_id}!%'
                        OR crons.command LIKE '%f{$field_id}^%'
                        OR crons.command LIKE '%set_filter({$field_id},%'
                        OR crons.command LIKE '%f{$field_id},%'
                  )
                  AND crons.disabled='0'
                  LIMIT $sel_limit";
        $result = sql_query($sqlQuery);
        while ($row = sql_fetch_assoc($result)) {
            $pre_data = array();
            $sel_limit -= 1;
            $pre_data['cron_name'] = $row['cron_name'];
            $pre_data['cron_id'] = $row['cron_id'];
            $pre_data['help'] = $row['cron_help'];
            $output['crons'][] = $pre_data;
        }
    }

    if ($sel_limit > 0 AND !$del_table) { // Является ли фильтром по полю связи
        $result = sql_select_field(FIELDS_TABLE, "id, name_field", "table_id=", $field['table_id'],
            " and type_value LIKE '", "%|-" . $field_id . "|%", "' LIMIT $sel_limit");
        while ($row = sql_fetch_assoc($result)) {
            $sel_limit -= 1;
            $output['fields'][$row['id']] = $row['name_field'];
        }
    }

    if ($sel_limit > 0) { // Участие в подтаблицах
        $sqlQuery = "SELECT name_table, subs.name AS sub_name, tables.id AS table_id, subs.id AS sub_id
                  FROM " . TABLES_TABLE . " AS tables, " . SUBTABLES_TABLE . " AS subs
                  WHERE link_field_id=$field_id AND tables.id=subs.table_id LIMIT $sel_limit";
        $result = sql_query($sqlQuery);
        while ($row = sql_fetch_assoc($result)) {
            $pre_data = array();
            $sel_limit -= 1;
            $pre_data['sub_name'] = $row['sub_name'];
            $pre_data['sub_id'] = $row['sub_id'];
            $pre_data['table_name'] = $row['name_table'];
            $output['subtables'][$row['table_id']][] = $pre_data;
        }
    }

    if ($sel_limit > 0) { // Участие в доптаблицах
        $sqlQuery = "SELECT name_table, addits.name AS addit_name, tables.id AS table_id, addits.id AS addit_id
                  FROM " . TABLES_TABLE . " AS tables, " . ADDIT_TABLES_TABLE . " AS addits
                  WHERE link_field_id=$field_id AND tables.id=addits.table_id LIMIT $sel_limit";
        $result = sql_query($sqlQuery);
        while ($row = sql_fetch_assoc($result)) {
            $pre_data = array();
            $sel_limit -= 1;
            $pre_data['addit_name'] = $row['addit_name'];
            $pre_data['addit_id'] = $row['addit_id'];
            $pre_data['table_name'] = $row['name_table'];
            $output['addittables'][$row['table_id']][] = $pre_data;
        }
    }

    if ($sel_limit > 0) {
        //выбираем имена шаблонов которые используют текущее поле
        $sql = "SELECT name FROM " . FORMS_VARS_TABLE . " WHERE table_id=" . $field['table_id'] . " AND (eval LIKE '%[\\'f" . $field_id . "\\']%' OR eval LIKE '%[\"f" . $field_id . "\"]%')";
        $result = sql_query($sql);
        while ($row = sql_fetch_assoc($result)) {
            $pre_data = array();
            $sel_limit -= 1;
            $pre_data['print_template_name'] = $row['name'];
            $output['print_template'][$row['print_template_id']][] = $pre_data;
        }
    }

    if ($sel_limit > 0) { // Участие в календарях
        $result = sql_select(CALENDAR_EVENTS);
        while ($row = sql_fetch_assoc($result)) {
            if ($row['date_field'] != $field_id && $row['period_field'] != $field_id && !sql_select_array(CALENDAR_FIELDS,
                    "event_id=", $row['id'], " and field_id=", $field_id)
            ) {
                continue;
            }
            $calendar_data = sql_select_array(CALENDARS_TABLE, "id=", $row['calendar_id']);
            $output['calendars'][$row['calendar_id']][] = array(
                "calendar_name" => form_display($calendar_data['name']),
                "event_id" => $row['id'],
                "event_name" => form_display($row['name'])
            );
        }
    }

    if ($sel_limit > 0 && !$del_table) { // Участие в настроках фильтра
        $result = sql_select_field(FILTERS_TABLE, "id, name, def_sort", "def_sort LIKE '", "%" . form_int_name($field_id) . "%",
            "' or group_field=", $field_id);
        while ($row = sql_fetch_assoc($result)) {
            if (preg_match("/\b" . form_int_name($field_id) . "\b/", $row['def_sort'])) {
                $output['filters'][$row['id']] = form_display($row['name']);
            }
        }
    }

    if ($sel_limit > 0) { // Участие во внешних файлах
        $result = sql_select(EXT_FILES);
        while ($row = sql_fetch_assoc($result)) {
            $content = file_get_contents($config['site_path'] . '/' . $row['name']);
            if (preg_match("/\bf" . $field_id . "\b/", $content)) {
                $output['ext_files'][] = $row;
            }
        }
    }

    if ($output['buttons'] || $output['calcs'] || $output['reports'] || $output['crons'] || $output['fields'] || $output['filters'] ||
        $output['subtables'] || $output['addittables'] || $output['print_template'] || $output['calendars'] || $output['ext_files']) {
        return $output;
    } else {
        return false;
    }
}

// Установка прав доступа на элементы, с учетом вложенных подгрупп
function set_access($table, $set, $pid = 0, $gr_mass = [])
{
    global $user;
    $result = sql_select(GROUPS_TABLE, 'pid=', $pid);
    while ($row = sql_fetch_assoc($result)) {
        $group_id = $row['id'];
        if ($group_id == 1 ||
            $pid ||
            ($set['form_id'] && $user['group_id'] == $group_id) ||
            ($user['sub_admin'] > 0 && $group_id == $user['group_id'])
        ) {
            sql_insert($table, array_merge(array('group_id' => $group_id), $set));
            if ($table == ACC_FILTERS_TABLE &&
                sql_select_array($table . "_par", "group_id=", $group_id, " and table_id=", $set['table_id'])
            ) {
                sql_insert($table . "_par", array(
                    'group_id' => $group_id,
                    'table_id' => $set['table_id'],
                    'filter_id' => $set['filter_id'],
                    'access' => 0,
                    'def_use' => 1,
                ));
            }
            if ($table == ACC_REPORTS_TABLE) { // у отчетов дополнительно устанавливаем права по пользователям
                $result2 = sql_select_field(USERS_TABLE, 'id', "group_id=", $group_id);
                while ($row2 = sql_fetch_assoc($result2)) {
                    sql_insert(ACC_REPORTS_USERS_TABLE, array(
                        'report_id' => $set['report_id'],
                        'user_id' => $row2['id'],
                        'access' => 1,
                    ));
                }
            }
            set_access($table, $set, $group_id);
        }
    }
    if (!empty($gr_mass)) {
        foreach ($gr_mass as $g_id => $g_val) {
            if ($g_val == 1 && $g_id != 1) {
                sql_insert($table, array_merge(array('group_id' => $g_id), $set));
            }
        }
    }
}

// Набор вычислений для связи с пользователем
function get_user_link_calc($calc_type)
{
    $calc['import'] = <<<EOD
if (\$user['group_id']!=1)
{
  if (\$user['sub_admin']==1)
  {
    if (\$line['Группа доступа']==1)
    {
      if (\$table['user_table_fields']['group_id'])
      {
        data_update(\$event['table_id'], array("f".\$table['user_table_fields']['group_id']=>0), "id=".\$event['line_id']);
      }
    }
  }
}
EOD;

    $calc['del'] = <<<EOD
if (\$line[form_int_name(\$table['user_table_fields']['group_id'])] == 0) return;
\$login = \$line[form_int_name(\$table['user_table_fields']['login'])];
if (\$line['status']==2)
{ // delete record from trash -> delete user
  if (\$user['group_id']==1) sql_delete(USERS_TABLE, "login='",\$login,"' and id!=1 and id!='",intval(\$config['master_sub_admin']),"'");
  elseif (\$user['sub_admin_rights']['access_subadmin']==1) sql_delete(USERS_TABLE, "login='",\$login,"' and id!=1 and id!='",intval(\$config['master_sub_admin']),"' and id!='",\$user['id'],"'");
  else
  {
    \$query = sql_select(GROUPS_TABLE, "sub_admin=1");
    while (\$row = sql_fetch_assoc(\$query))
    {
      \$sub_admin_groups[] = \$row['id'];
      \$set=1;
    }
    if (\$set) sql_delete(USERS_TABLE, "login='",\$login,"' and id!=1 and id!='",intval(\$config['master_sub_admin']),"' and id!='",\$user['id'],"' and id NOT IN (".implode(", ", \$sub_admin_groups).")");
    else sql_delete(USERS_TABLE, "login='",\$login,"' and id!=1 and id!='",intval(\$config['master_sub_admin']),"' and id!='",\$user['id'],"'");
  }
}
else
{ // delete record to trash -> archive user
  if (\$user['group_id']==1) sql_update(USERS_TABLE, array('arc'=>1), "login='",\$login,"' and id!=1 and id!='",intval(\$config['master_sub_admin']),"'");
  elseif (\$user['sub_admin_rights']['access_subadmin']==1) sql_update(USERS_TABLE, array('arc'=>1), "login='",\$login,"' and id!=1 and id!='",intval(\$config['master_sub_admin']),"' and id!='",\$user['id'],"'");
  else
  {
    \$query = sql_select(GROUPS_TABLE, "sub_admin=1");
    while (\$row = sql_fetch_assoc(\$query))
    {
      \$sub_admin_groups[] = \$row['id'];
      \$set=1;
    }
    if (\$set) sql_update(USERS_TABLE, array('arc'=>1), "login='",\$login,"' and id!=1 and id!='",intval(\$config['master_sub_admin']),"' and id!='",\$user['id'],"' and id NOT IN (".implode(", ", \$sub_admin_groups).")");
    else sql_update(USERS_TABLE, array('arc'=>1), "login='",\$login,"' and id!=1 and id!='",intval(\$config['master_sub_admin']),"' and id!='",\$user['id'],"'");
  }
}
EOD;

    $calc['arc'] = <<<EOD
\$login = \$line[form_int_name(\$table['user_table_fields']['login'])];
if (\$line['status']==0 && \$event['type'] != 'delete')
{ // restore user
  if (\$user['group_id']==1) sql_update(USERS_TABLE, array('arc'=>0), "login='",\$login,"' and id!=1 and id!='",intval(\$config['master_sub_admin']),"'");
  elseif (\$user['sub_admin_rights']['access_subadmin']==1) sql_update(USERS_TABLE, array('arc'=>0), "login='",\$login,"' and id!=1 and id!='",intval(\$config['master_sub_admin']),"' and id!='",\$user['id'],"'");
  else
  {
    \$query = sql_select(GROUPS_TABLE, "sub_admin=1");
    while (\$row = sql_fetch_assoc(\$query))
    {
      \$sub_admin_groups[] = \$row['id'];
      \$set=1;
    }
    if (\$set) sql_update(USERS_TABLE, array('arc'=>0), "login='",\$login,"' and id!=1 and id!='",intval(\$config['master_sub_admin']),"' and id!='",\$user['id'],"' and id NOT IN (".implode(", ", \$sub_admin_groups).")");
    else sql_update(USERS_TABLE, array('arc'=>0), "login='",\$login,"' and id!=1 and id!='",intval(\$config['master_sub_admin']),"' and id!='",\$user['id'],"'");
  }
}
elseif (\$line['status']==1)
{ // archive user
  if (\$user['group_id']==1) sql_update(USERS_TABLE, array('arc'=>1), "login='",\$login,"' and id!=1 and id!='",intval(\$config['master_sub_admin']),"'");
  elseif (\$user['sub_admin_rights']['access_subadmin']==1) sql_update(USERS_TABLE, array('arc'=>1), "login='",\$login,"' and id!=1 and id!='",intval(\$config['master_sub_admin']),"' and id!='",\$user['id'],"'");
  else
  {
    \$query = sql_select(GROUPS_TABLE, "sub_admin=1");
    while (\$row = sql_fetch_assoc(\$query))
    {
      \$sub_admin_groups[] = \$row['id'];
      \$set=1;
    }
    if (\$set) sql_update(USERS_TABLE, array('arc'=>1), "login='",\$login,"' and id!=1 and id!='",intval(\$config['master_sub_admin']),"' and id!='",\$user['id'],"' and id NOT IN (".implode(", ", \$sub_admin_groups).")");
    else sql_update(USERS_TABLE, array('arc'=>1), "login='",\$login,"' and id!=1 and id!='",intval(\$config['master_sub_admin']),"' and id!='",\$user['id'],"'");
  }
}
EOD;

    $calc['add'] = <<<EOD
global \$double_cancel, \$archive, \$deleted;
if (!\$event_cancel and !\$double_cancel[\$ID] && !(\$event['line_id'] == 'new' && \$line['status'] == 3))
{ // if not was a cancel of adding from external form
  foreach (\$table['user_table_fields'] as \$ulf_name=>\$ulf_id) if (\$ulf_name!="invite" and \$ulf_name!="change_mail" and \$ulf_name!="calcs") \$ulf[\$ulf_name] = form_int_name(\$ulf_id);
  \$old_fname = \$event['changed'][\$table['user_table_fields']['fio']]['old'];
  \$old_login = \$event['changed'][\$table['user_table_fields']['login']]['old'];
  \$old_email = \$event['changed'][\$table['user_table_fields']['e_mail']]['old'];
  \$old_passw = \$event['changed'][\$table['user_table_fields']['password']]['old'];
  \$old_group = \$event['changed'][\$table['user_table_fields']['group_id']]['old'];
  \$old_user_id = \$event['changed'][\$table['user_table_fields']['user_id']]['old'];
  if (\$old_group === "0") \$old_login = "";
  if (\$old_login) \$login = \$old_login; else \$login = \$line[\$ulf['login']];
  \$fname_field = \$table_fields[\$table['user_table_fields']['fio']]['name_field'];
  \$login_field = \$table_fields[\$table['user_table_fields']['login']]['name_field'];
  \$email_field = \$table_fields[\$table['user_table_fields']['e_mail']]['name_field'];
  \$save_exit = 1;

  if(\$user['group_id']<> 1)
  {
    \$user_id_str = "f".\$table['user_table_fields']['user_id'];
    \$group_str = "f".\$table['user_table_fields']['group_id'];
    if(\$line[\$group_str] == 1)
    {
      foreach(\$event['changed'] as \$field_id=>\$change_data)
      {
        \$line[\$change_data['int_name']] = \$change_data['old'];
      }

      \$calc_errors[] = \$lang['no_change_admin_group_settings'];
      \$save_exit = 0;
    }

  if (\$old_group and \$old_group != \$line[\$ulf['group_id']])
    {

      if (\$old_group==1 || \$line[\$ulf['group_id']]==1)
        {
          \$calc_errors[] = \$lang['no_change_admin_group_settings'];
          \$line[\$ulf['group_id']] = \$old_group;
          \$save_exit = 0;
        }

      if(\$user['id'] == \$line[\$user_id_str])
        {
          \$calc_errors[]=\$lang['no_change_my_group_settings'];
          \$line[\$ulf['group_id']] = \$old_group;
          \$save_exit = 0;
        }
     }
   }
  /*
  if ((\$old_group==1 || \$line[\$ulf['group_id']]==1 || \$user['id']==\$line[\$ulf['user_id']] || \$user['id']==\$old_user_id || (\$user['group_id']==\$old_group && \$user['sub_admin_rights']['access_subadmin']!=1)) && \$user['group_id']!=1)
    {
      if (\$old_group==1 || \$line[\$ulf['group_id']]==1) \$calc_errors[] = \$lang['no_change_admin_group_settings'];
      elseif (\$user['group_id']!=\$old_group) \$calc_errors[] = \$lang['no_change_my_group_settings'];
      if (\$old_fname) \$line[\$ulf['fio']] = \$old_fname;
      if (\$old_login) \$line[\$ulf['login']] = \$old_login;
      if (\$old_email) \$line[\$ulf['e_mail']] = \$old_email;
      if (\$old_passw) \$line[\$ulf['password']] = \$old_passw;
      if (\$old_group) \$line[\$ulf['group_id']] = \$old_group;
      if (\$old_user_id) \$line[\$ulf['user_id']] = \$old_user_id;
      \$save_exit = 0;
    }
  */
  if (\$line[\$ulf['group_id']] && \$save_exit)
    { // group is not empty - check of user data
      if (!\$line[\$ulf['fio']])
        { // user name is empty
          if (\$old_fname)
            { // cancel changing
              \$calc_errors[] = \$lang['not_filed_field']." \"".\$fname_field."\". ".\$lang['return_previos_value'];
              \$line[\$ulf['fio']] = \$old_fname;
            }
            else
            { // clear group
              \$calc_errors[] = \$lang['not_filed_field']." \"".\$fname_field."\".";
              \$line[\$ulf['group_id']] = 0;
            }
        }
      if (!\$line[\$ulf['login']] and \$login_field!=\$fname_field)
        { // login is empty
          if (\$old_login)
            { // cancel changing
              \$calc_errors[] = \$lang['not_filed_field']." \"".\$login_field."\". ".\$lang['return_previos_value'];
              \$line[\$ulf['login']] = \$old_login;
            }
            else
            { // clear group
              \$calc_errors[] = \$lang['not_filed_field']." \"".\$login_field."\".";
              \$line[\$ulf['group_id']] = 0;
            }
        }
      if (!\$line[\$ulf['e_mail']] and \$email_field!=\$fname_field and \$email_field!=\$login_field)
        { // e-mail is empty
          if (\$old_email)
            { // cancel changing
              \$calc_errors[] = \$lang['not_filed_field']." \"".\$email_field."\". ".\$lang['return_previos_value'];
              \$line[\$ulf['e_mail']] = \$old_email;
            }
            else
            { // clear group
              \$calc_errors[] = \$lang['not_filed_field']." \"".\$email_field."\".";
              \$line[\$ulf['group_id']] = 0;
            }
        }
      \$data = data_select_array(\$table_id, \$ulf['login']."='",\$line[\$ulf['login']],"' and id!='",\$line['id'],"' and ".\$ulf['group_id']."!=''");
      if (\$data and \$line[\$ulf['login']])
        { // this login already have in another record
          if (\$old_login)
            { // cancel changing
              \$calc_errors[] = \$lang['Login']." \"".\$data[\$ulf['login']]."\" ".\$lang['in_use_another_user']." \"".\$data[\$ulf['fio']]."\". ".\$lang['return_previos_value'];
              \$line[\$ulf['login']] = \$old_login;
            }
            else
            { // clear group
              \$calc_errors[] = \$lang['Login']." \"".\$data[\$ulf['login']]."\" ".\$lang['in_use_another_user']." \"".\$data[\$ulf['fio']]."\".";
              \$line[\$ulf['group_id']] = 0;
            }
        }
      \$result = sql_select(USERS_TABLE, "arc=0 AND group_id!=777 AND login!='",\$login,"' AND login!='support_cb' ORDER BY id");
      if (sql_num_rows(\$result)>=\$config['max_users'] and \$line[\$ulf['group_id']]!="777")
        { // exceeded number of permitted users
          if (\$old_group)
            { // cancel changing
              \$calc_errors[] = \$lang['you_can_add_max']." ".\$config['max_users']." ".\$lang['m_users'].". ".\$lang['return_previos_value'];
              \$line[\$ulf['group_id']] = \$old_group;
            }
            else
            { // clear group
              \$calc_errors[] = \$lang['you_can_add_max']." ".\$config['max_users']." ".\$lang['m_users'].".";
              \$line[\$ulf['group_id']] = 0;
            }
        }
      if (!\$smarty->tpl_vars['full_version']->value)
        {
          \$result = sql_select(USERS_TABLE, "arc=0 AND group_id=777 AND login!='",\$login,"' ORDER BY id");
          if (sql_num_rows(\$result)>=3 and \$line[\$ulf['group_id']]=="777")
            { // exceeded number of permitted clients
              if (\$old_group)
                { // cancel changing
                  \$calc_errors[] = \$lang['you_can_add_max']." 3 ".\$lang['m_clients'].". ".\$lang['return_previos_value'];
                  \$line[\$ulf['group_id']] = \$old_group;
                }
                else
                { // clear group
                  \$calc_errors[] = \$lang['you_can_add_max']." 3 ".\$lang['m_clients'].".";
                  \$line[\$ulf['group_id']] = 0;
                }
            }
        }
      if (!\$line[\$ulf['group_id']]) \$calc_errors[] = \$lang['login_is_not_saved'];
    }
    if (\$line[\$ulf['group_id']] && \$save_exit)
    { // group is not empty and user data is corrected - add/update user
      \$line['f'.\$table['user_table_fields']['fio']] = str_replace(array('"',"'"),'', \$line['f'.\$table['user_table_fields']['fio']]);
      \$password = "";
      // looking for a user with this login
      \$result = sql_select(USERS_TABLE, "login='",\$login,"'");
      if (\$row = sql_fetch_assoc(\$result))
        { // user exists, update user data
          \$usr_id = \$row['id'];
          \$upd_data = array();
          foreach (\$ulf as \$ulf_name=>\$ulf_field) if (\$ulf_name!="user_id" and \$ulf_name!="password" and \$ulf_name!="avatar" and \$ulf_field) \$upd_data[\$ulf_name] = \$line[\$ulf_field];
          \$upd_data['fio'] = str_replace(array("\\r","\\n")," ",\$upd_data['fio']); // replace newline characters with a space
          \$upd_data['fio'] = str_replace(array("'",'"'),"",\$upd_data['fio']); // replace ' and " characters with a space
          if (!\$old_group and !\$archive and !\$deleted) \$upd_data['arc'] = 0; // if user has been inactive (empty group) - restore user
          if (\$usr_id==1 and \$upd_data['group_id']!=1)
            { // not change group of base admin
              \$calc_errors[] = \$lang['no_cnange_admin_group'];
              \$line[\$ulf['group_id']] = 1;
              \$upd_data['group_id'] = 1;
            }
          if (\$table['user_table_fields']['avatar']) {
            if (\$line[\$ulf['avatar']]) {
              \$upd_data['avatar'] = file_get_contents(get_file_path(\$table['user_table_fields']['avatar'], \$line['id'], \$line[\$ulf['avatar']]));
            } else {
              \$upd_data['avatar'] = '';
            }
            if (file_exists('cache/user' . \$usr_id . '.png')) {
              unlink('cache/user' . \$usr_id . '.png'); // удаляем старую превьюшку если была
            }
          }
          sql_update(USERS_TABLE, \$upd_data, "id=",\$usr_id);
          // send update info to user email
          if (\$table['user_table_fields']['change_mail'] and (isset(\$old_login) or isset(\$old_passw)))
            {
              if (\$mail_tmpl = sql_select_array(MAIL_TEMPLATES_TABLE, 'id=',\$table['user_table_fields']['change_mail']))
                {
                    \$smtp_server_id = -1;
                    if (\$mail_tmpl['from_mail']) {
                        \$result = sql_select(SMTP_TABLE, "active=1 and name='" . \$mail_tmpl['from_mail'] . "'");
                        if (\$smtp_server = sql_fetch_array(\$result)) {
                            \$smtp_server_id = \$smtp_server['id'];
                        }
                    }
                    \$logo = '<img src="' . \$config['site_url'] . '/images/mail_logo.png">';
                    \$shablons  = array('{logo}','{program}','{program_link}','{fio}','{login}','{password}');
                    \$values = array(\$logo, \$config['application'], \$config['site_url'], \$line[\$ulf['fio']], \$line[\$ulf['login']], \$ulf['password']?\$line[\$ulf['password']]:"не менялся");
                    \$mail_tmpl['body'] = str_replace(\$shablons, \$values, \$mail_tmpl['body']);
                    \$thread_id = create_mail_thread(\$mail_tmpl['subject']); // create separate thread
                    sendmail(\$mail_tmpl['subject'], \$mail_tmpl['body'], \$line[\$ulf['e_mail']], \$mail_tmpl['from_mail'], \$mail_tmpl['sender'], '',
                            'text/html', (\$mail_tmpl['charset'] ?: 'utf-8'), array(), array(), \$smtp_server_id, \$thread_id, 0, 0, \$mail_tmpl['unsubscribe']);
                    send_all_mail(\$thread_id); // send thread immediately
                }
            }
        }
        else
        { // user is not exists, add user data
          \$ins_data = array();
          foreach (\$ulf as \$ulf_name=>\$ulf_field) if (\$ulf_name!="user_id" and \$ulf_name!="password" and \$ulf_name!="avatar" and \$ulf_field) \$ins_data[\$ulf_name] = \$line[\$ulf_field];
          \$ins_data['fio'] = str_replace(array("\\r","\\n")," ",\$ins_data['fio']); // replace newline characters with a space
          \$ins_data['fio'] = str_replace(array("'",'"'),"",\$ins_data['fio']); // replace ' and " characters with a space
          \$ins_data['date_registr'] = date("Y-m-d");
          if (\$table['user_table_fields']['avatar']) {
            if (\$line[\$ulf['avatar']]) {
              \$ins_data['avatar'] = file_get_contents(get_file_path(\$table['user_table_fields']['avatar'], \$line['id'], \$line[\$ulf['avatar']]));
            }
          }
          \$usr_id = sql_insert(USERS_TABLE, \$ins_data);
          if (!\$ulf['password'])
            { // autogeneration password, if password field is not set
              \$password = generate_password(7, 10, 1);
            }
            else
            {
              \$password = \$line[\$ulf['password']];
            }
          // send invite to user email
          if (\$table['user_table_fields']['invite'])
            {
              if (\$mail_tmpl = sql_select_array(MAIL_TEMPLATES_TABLE, 'id=',\$table['user_table_fields']['invite']))
                {
                    \$smtp_server_id = -1;
                    if (\$mail_tmpl['from_mail']) {
                        \$result = sql_select(SMTP_TABLE, "active=1 and name='" . \$mail_tmpl['from_mail'] . "'");
                        if (\$smtp_server = sql_fetch_array(\$result)) {
                            \$smtp_server_id = \$smtp_server['id'];
                        }
                    }
                    \$logo = '<img src="' . \$config['site_url'] . '/images/mail_logo.png">';
                    \$shablons  = array('{logo}','{program}','{program_link}','{fio}','{login}','{password}');
                    \$values = array(\$logo, \$config['application'], \$config['site_url'], \$line[\$ulf['fio']], \$line[\$ulf['login']], \$password);
                    \$mail_tmpl['body'] = str_replace(\$shablons, \$values, \$mail_tmpl['body']);
                    \$thread_id = create_mail_thread(\$mail_tmpl['subject']); // create separate thread
                    sendmail(\$mail_tmpl['subject'], \$mail_tmpl['body'], \$line[\$ulf['e_mail']], \$mail_tmpl['from_mail'], \$mail_tmpl['sender'], '',
                            'text/html', (\$mail_tmpl['charset'] ?: 'utf-8'), array(), array(), \$smtp_server_id, \$thread_id, 0, 0, \$mail_tmpl['unsubscribe']);
                    send_all_mail(\$thread_id); // send thread immediately
                }
            }
          // add asterisk user
          if (\$config['modules']['asterisk'] and sql_select_array(GROUPS_TABLE, 'id=',\$ins_data['group_id'],' and auto_add_ip_user = 1'))
            {
              add_asterisk_user(\$usr_id);
            }
        }
      // update user link in this table
      \$line[\$ulf['user_id']] = \$usr_id;
      // update password in users table
      if (isset(\$old_passw) or \$password)
        {
          if (!\$password) \$password = \$line[\$ulf['password']];
          \$upd_data = array();
          if (\$config['password_hash_coder'] == "md5")
            {
              \$upd_data['password'] = md5(\$password);
              \$upd_data['crypt_mode'] = "md5";
            }
            else
            {
              if (!\$config['password_hash_coder']) \$crypt_type = MHASH_GOST;
              else \$crypt_type = \$config['password_hash_coder'];
              \$upd_data['password'] = base64_encode(cb_keygen_s2k(\$crypt_type, \$password, \$usr_id, 512));
              \$upd_data['crypt_mode'] = MHASH_GOST;
            }
          \$upd_data['user_hash'] = generate_password(32, 32, 1);
          sql_update(USERS_TABLE, \$upd_data, "id=",\$usr_id);
        }
        // set user access on reports
        if (\$line[\$ulf['group_id']] != \$old_group) {
            \$result = sql_select_field(REPORTS_TABLE, 'id');
            while (\$report_id = sql_fetch_row(\$result)[0]) {
                \$group_access = sql_fetch_row(sql_select_field(ACC_REPORTS_TABLE, 'access', 'report_id = ', \$report_id, ' AND group_id = ', \$line[\$ulf['group_id']]))[0];
                \$user_access = sql_fetch_row(sql_select_field(ACC_REPORTS_USERS_TABLE, 'access', 'report_id = ', \$report_id, ' AND user_id = ', \$usr_id))[0];
                if (\$group_access && !\$user_access) {
                    sql_insert(ACC_REPORTS_USERS_TABLE, ['report_id' => \$report_id, 'user_id' => \$usr_id, 'access' => 1]);
                } elseif (!\$group_access && \$user_access) {
                    sql_delete(ACC_REPORTS_USERS_TABLE, 'report_id = ', \$report_id, ' AND user_id = ', \$usr_id);
                }
            }
        }
      if (\$line[\$ulf['group_id']] == 1 && \$old_group != 1)
        {
           \$_SERVER['PHP_SELF'] = 'edit_user.php';
           \CB\Tool\Util::log_important_event('admin', 'У сотрудника ' . \$line[\$ulf['fio']] . ' установлена группа доступа Администратор');
        }
    }
    elseif (\$old_group && \$save_exit)
    { // group is removed, move user in archive (except base admin)
      sql_update(USERS_TABLE, array('arc'=>1), "login='",\$login,"' and id!=1");
    }
    if (!\$line[\$ulf['group_id']])
    { // group is empty - clear user link in this table
      \$line[\$ulf['user_id']] = 0;
    }
  // cancel of double calculate
  \$double_cancel[\$ID] = 1;
}
EOD;

    $calc['qst'] = <<<EOD
global \$qst, \$qst_id;

if (\$qst['lang']) {
    include "lang/".\$qst['lang'].".php";
}

if (\$table['user_table_fields'] && (((boolean)\$table['table_fields'][\$table['user_table_fields']['group_id']]['default_value']!=0) || \$qst['reg_group']))
{ // user registration
  foreach (\$table['user_table_fields'] as \$ulf_name=>\$ulf_id) if (\$ulf_name!="invite" and \$ulf_name!="change_mail" and \$ulf_name!="calcs") \$ulf[\$ulf_name] = form_int_name(\$ulf_id);
  \$fname_field = \$table_fields[\$table['user_table_fields']['fio']]['name_field'];
  \$login_field = \$table_fields[\$table['user_table_fields']['login']]['name_field'];
  \$email_field = \$table_fields[\$table['user_table_fields']['e_mail']]['name_field'];
  if(\$qst['allow_update'] != 1 OR empty(\$_REQUEST['hash'])) {
    if (!\$line[\$ulf['fio']])
      { // user name is empty
        // echo "<script>k_answer_hide_form\$qst_id=0; alert('".\$lang['not_filed_field']." \"".\$fname_field."\""."')</script>&nbsp;";
        \$_SESSION["k_qst_{\$qst_id}_answer"] = str_replace("'", "\'", json_encode(array('error'=>"<script>k_answer_hide_form\$qst_id=0; alert('".\$lang['not_filed_field']." \"".\$fname_field."\""."')</script>&nbsp;")));
        \$event_cancel = 1;
        return;
      }
    if (!\$line[\$ulf['login']] and \$login_field!=\$fname_field)
      { // login is empty
        // echo "<script>k_answer_hide_form\$qst_id=0; alert('".\$lang['not_filed_field']." \"".\$login_field."\""."')</script>&nbsp;";
        \$_SESSION["k_qst_{\$qst_id}_answer"] = str_replace("'", "\'", json_encode(array('error'=>"<script>k_answer_hide_form\$qst_id=0; alert('".\$lang['not_filed_field']." \"".\$login_field."\""."')</script>&nbsp;")));
        \$event_cancel = 1;
        return;
      }
    if (!\$line[\$ulf['e_mail']] and \$email_field!=\$fname_field and \$email_field!=\$login_field)
      { // e-mail is empty
        // echo "<script>k_answer_hide_form\$qst_id=0; alert('".\$lang['not_filed_field']." \"".\$email_field."\""."')</script>&nbsp;";
        \$_SESSION["k_qst_{\$qst_id}_answer"] = str_replace("'", "\'", json_encode(array('error'=>"<script>k_answer_hide_form\$qst_id=0; alert('".\$lang['not_filed_field']." \"".\$email_field."\""."')</script>&nbsp;")));
        \$event_cancel = 1;
        return;
      }
  }
  \$data = sql_select_array(USERS_TABLE, "login='",\$line[\$ulf['login']],"'");
  if (\$data and \$line[\$ulf['login']])
    { // this login already have in another record
      echo "<script>k_answer_hide_form\$qst_id=0; alert('".\$lang['Login']." \"".\$line[\$ulf['login']]."\" ".\$lang['already_used_another_user']."')</script>&nbsp;";
      \$_SESSION["k_qst_{\$qst_id}_answer"] = str_replace("'", "\'", json_encode(array('error'=>"<script>k_answer_hide_form\$qst_id=0; alert('".\$lang['Login']." \"".\$line[\$ulf['login']]."\" ".\$lang['already_used_another_user']."')</script>&nbsp;")));
      \$event_cancel = 1;
      return;
    }
  if (\$qst['reg_group']) \$line[\$ulf['group_id']] = \$qst['reg_group'];
  //echo str_replace("'", "\'", json_encode(array('done'=>"<script>k_answer_hide_form\$qst_id=1;</script>")));
}
EOD;

    return $calc[$calc_type];
}

//функция сравнения текста
//$text1,$text2 - текст или путь к файлу
//возвращает текстовое представление разности формата:
//[номер строки исходного файла]
//- что было (отсутствует если только добавление)
//+ что стало (отсутствует если только удаление)
function diff($text1, $text2)
{
    //БЛОК ОБРАБОТКИ ТЕКСТА ПЕРЕД СРАВНЕНИЕМ
    //проверяем на файл
    if (file_exists($text1)) {
        $text1 = file_get_contents($text1);
    }
    if (file_exists($text2)) {
        $text2 = file_get_contents($text2);
    }
    //формируем массив
    $regex = '/\r?\n/';
    $old = preg_split($regex, htmlspecialchars($text1));
    $new = preg_split($regex, htmlspecialchars($text2));
    //БЛОК ФУНКЦИИ СРАВНЕНИЯ
    function differ($old, $new)
    {
        $matrix = array();
        $maxlen = 0;
        foreach ($old as $oindex => $ovalue) {
            $nkeys = array_keys($new, $ovalue);
            foreach ($nkeys as $nindex) {
                $matrix[$oindex][$nindex] = isset($matrix[$oindex - 1][$nindex - 1]) ? $matrix[$oindex - 1][$nindex - 1] + 1 : 1;
                if ($matrix[$oindex][$nindex] > $maxlen) {
                    $maxlen = $matrix[$oindex][$nindex];
                    $omax = $oindex + 1 - $maxlen;
                    $nmax = $nindex + 1 - $maxlen;
                }
            }
        }
        if ($maxlen == 0) {
            return array(array('d' => $old, 'i' => $new));
        }
        return array_merge(
            differ(array_slice($old, 0, $omax), array_slice($new, 0, $nmax)),
            array_slice($new, $nmax, $maxlen),
            differ(array_slice($old, $omax + $maxlen), array_slice($new, $nmax + $maxlen))
        );
    }

    //БЛОК ФОРМИРОВАНИЯ ПРЕДСТАВЛЕНИЯ
    $result = differ($old, $new);
    $final_text = "";
    foreach ($result as $key => $value) {
        if (is_array($value) && (count_cb($value['d']) || count_cb($value['i']))) {
            $final_text .= ($key + 1) . "\n";
            if (count_cb($value['d'])) {
                foreach ($value['d'] as $v) {
                    $final_text .= "- " . $v . "\n";
                }
            }
            if (count_cb($value['i'])) {
                foreach ($value['i'] as $v) {
                    $final_text .= "+ " . $v . "\n";
                }
            }
            $final_text .= "";
        }
    }
    return $final_text;
}

function filter_compile_value($filter, $par_filter = array())
{
    if (!$par_filter) {
        $par_filter = sql_select_array(FILTERS_TABLE, "id=", $filter['pid']);
    }
    if (!$par_filter['value']) {
        $par_filter['value'] = "1=1";
    }
    $filter['value'] = str_replace("{parent}", "(" . $par_filter['value'] . ")", $filter['expert']);
    sql_update(FILTERS_TABLE, $filter, 'id=', $filter['id']);
    $result = sql_select(FILTERS_TABLE, "pid=", $filter['id']);
    while ($sub_filter = sql_fetch_assoc($result)) {
        filter_compile_value($sub_filter, $filter);
    }
}

// Функция выгрузки файлов в папку для синхронизации
function sync_files_export($sync_id, $line_id, $field_id, $f_name)
{
    global $config, $lang, $user, $sync_exp_list, $sync_exp_fields;
    if (!$sync_exp_list) { // Считываем настройки синхронизаций, если их нет
        $sync_exp_list = array();
        $result = sql_select(SYNC_TABLE, 'enabled=1');
        while ($one_sync = sql_fetch_assoc($result)) {
            $one_sync['tables'] = array();
            $sync_exp_list[$one_sync['id']] = $one_sync;
        }
        $sync_exp_fields = array();
        $sqlQuery = "SELECT a.table_id, b.* FROM " . FIELDS_TABLE . " a, " . SYNC_FIELDS_TABLE . " b WHERE a.id=b.field_id and b.enabled='1' and (b.direction=1 or b.direction=2)";
        $result2 = sql_query($sqlQuery);
        while ($one_field = sql_fetch_assoc($result2)) {
            $sync_exp_fields[$one_field['field_id']][$one_field['sync_id']] = array(
                'sync_id' => $one_field['sync_id'],
                'field_id' => $one_field['field_id'],
                'c_field' => ($sync_exp_list[$one_field['sync_id']]['sync_mode'] == 0 ? $one_field['c_field'] : 0),
                'filter_id' => $one_field['filter_id']
            );
            $sync_exp_list[$one_field['sync_id']]['fields'][$one_field['field_id']] = array(
                'field_id' => $one_field['field_id'],
                'table_id' => $one_field['table_id']
            );
            $sync_exp_list[$one_field['sync_id']]['tables'][$one_field['table_id']] = $one_field['table_id'];
        }
    }

    if ($sync_exp_list[$sync_id]['type_mode']) // Режимы удалённых синхронизаций, выгружаем в temp
    {
        $sync_exp_list[$sync_id]['upload_dir'] = "temp/sync_" . $sync_id . "/export";
    }

    if (!is_dir($sync_exp_list[$sync_id]['upload_dir'] . "/files")) { // В папке выгрузки отстутсвует папка files, пытаемся создать
        if (!@mkdir($sync_exp_list[$sync_id]['upload_dir'] . "/files")) { // Создание неуспешно
            \CB\CornyService::insert_log_light("sync",
                $lang['no_write_to_folder'] . " &quot;" . $sync_exp_list[$sync_id]['upload_dir'] . "&quot;");
            return;
        }
    }

    // Части имени файла
    if ($sync_exp_list[$sync_id]['sync_mode']) {
        $file_field = $field_id;
        $line_res = data_select_field($sync_exp_list[$sync_id]['fields'][$field_id]['table_id'], "s" . $sync_id, "id=",
            $line_id);
        if ($line_row = sql_fetch_assoc($line_res)) {
            $file_line = $line_row["s" . $sync_id];
        } else {
            return;
        }
        if ($file_line == "" OR $file_line == "S") {
            $file_line = "^" . $line_id;
        }
    } else {
        $file_field = $sync_exp_fields[$field_id][$sync_id]['c_field'];
        $file_line = $line_id;
    }

    if (!copy(get_file_path($field_id, $line_id, $f_name),
        $sync_exp_list[$sync_id]['upload_dir'] . "/files/" . $file_field . "_" . $file_line . "_" . encode_filename($f_name))
    ) {
        \CB\CornyService::insert_log_light("sync",
            $lang['no_write_to_folder'] . " &quot;" . $sync_exp_list[$sync_id]['upload_dir'] . "/files&quot;");
        return;
    }
}

function form_filters_list(&$all_filters, $pid = 0, $filter_id = 0)
{
    global $table_id;

    $filters = [];

    $result = sql_select(FILTERS_TABLE, 'table_id=', $table_id, ' and id!=', $filter_id,
        ' ORDER BY num');
    while ($one_filter = sql_fetch_assoc($result)) {
        $all_filters[$one_filter['id']] = $one_filter;

        $filters[$one_filter['id']] = [
            'name' => $one_filter['name'],
            'pid' => $one_filter['pid'],
        ];

        $is_parent_res = sql_select(FILTERS_TABLE, 'table_id=', $table_id, ' and pid=', $one_filter['id'], ' and id!=', $filter_id, ' ORDER BY num');
        $all_filters[$one_filter['id']]['is_parent'] = sql_num_rows($is_parent_res) ? 1 : 0;
    }

    $all_filters = get_filters($all_filters);

    foreach($all_filters as $key => $filter){
        $parent = '';
        $tab = $filter['pid'] == 0 ? '' : ' ∟ ';
        $pid = $filter['pid'];
        while((int)$pid > 0){
            $parent = $filters[$pid]['name'] . ' - ' . $parent;
            $pid = $filters[$pid]['pid'];
            $tab = str_repeat("&nbsp;", 3) . $tab;
        }
        $all_filters[$key]['tab'] = $tab;
        $all_filters[$key]['parent'] = $parent;
    }
}

function get_filters($all_filters, $pid = 0)
{
    $necessary_filters = [];

    foreach($all_filters as $key => $filter){
        if($filter['pid'] == $pid){
            $necessary_filters[$key] = $filter;
            $necessary_filters = array_merge($necessary_filters, get_filters($all_filters, $key));
        }
    }

    return $necessary_filters;
}

// Генерация кода анкеты
// Входящий параметр - массив, результат выборки из QST_TABLE
function generate_qst_code($qst) {
    if($qst['captcha'] != NULL) {
        $extensionManager = \CB\Core::get(\CB\Core::EXTENSION_MANAGER);
        if ($extensionManager->isActive("cbext.clientbase.".$qst['captcha'])) {
            $captcha = $extensionManager->getService('cbext.clientbase.'.$qst['captcha'], 'Main');
            $secret_key = $captcha->getClientKey();
        }
    }
    require_once __DIR__ .'/generate_qst_code.php';
    return $QST_HTML_CODE;
}

function keygen_s2k($hash, $password, $salt, $bytes)
{
    $result = false;
    if (extension_loaded('hash') === true) {
        $times = $bytes / ($block = strlen(hash($hash, null, true)));
        if ($bytes % $block != 0) {
            ++$times;
        }
        for ($i = 0; $i < $times; ++$i) {
            $result .= hash($hash, str_repeat("\0", $i) . $salt . $password, true);
        }
    }
    return $result;
}

function generate_qst_hash()
{
    global $config;
    if ($config['password_hash_coder'] == "md5") {
        return base64_encode(keygen_s2k('sha512', uniqid(), '4X1.eJ?i]j=c%glrHEf9yG@P', 128));
    } else {
        return base64_encode(cb_keygen_s2k(MHASH_GOST, uniqid(), '4X1.eJ?i]j=c%glrHEf9yG@P', 128));
    }
}

function encode_qst_hash($line_id, $qst_hash, $subtable_id = 0, $uniq_id = 0, $method = 'AES-128-CBC')
{
    global $config;
    $array_arg = array('lid' => $line_id, 'sid' => $subtable_id, 'uniq_qst' => $uniq_id);
    $serialize_arg = serialize($array_arg);
    $key = base64_decode($qst_hash);
    $iv_len = openssl_cipher_iv_length($method);
    $iv = substr($key, 0, $iv_len);
    return base64_url_encode(openssl_encrypt($serialize_arg, $method, $key, true, $iv));
}

function decode_qst_hash($data, $qst_hash, $method = 'AES-128-CBC')
{
    global $config;
    $key = base64_decode($qst_hash);
    $iv_len = openssl_cipher_iv_length($method);
    $iv = substr($key, 0, $iv_len);
    return openssl_decrypt(base64_url_decode($data), $method, $key, true, $iv);
}

if (!function_exists('hex2bin')) {
    function hex2bin($str)
    {
        for ($i = 0; $i < strlen($str); $i += 2) {
            $res .= chr(hexdec(substr($str, $i, 2)));
        }
        return $res;
    }
}

// Вывод сообщений через вычисления
// $text    - текст сообщения
// $status  - группировка сообщений по произвольному статусу
function calc_alerts($text, $status = "error")
{
    global $config, $lang, $smarty, $calc_error_order, $script_name, $line, $ses_id;
    if ($script_name == "update_value.php") { // В режиме быстрого редактирования группируем сообщения
        $calc_error_order[$status] = (int)$calc_error_order[$status] + 1;
        echo "\r\nmessage|$status|" . $calc_error_order[$status] . "|" . base64_encode($text) . "\r\n";
    } elseif (!$line['id'] && $script_name == 'calendar.php') {
        if (!is_array($_SESSION[$ses_id]['calc_errors']['_calendar_line_'])) {
            $_SESSION[$ses_id]['calc_errors']['_calendar_line_'] = [];
        }
        $_SESSION[$ses_id]['calc_errors']['_calendar_line_'][] = form_display($text);
    } else { // В режиме просмотра/редактирования записи (view_line2.php) выводим все сообщения без группировки
        if (!is_array($_SESSION[$ses_id]['calc_errors'][$line['id']])) {
            $_SESSION[$ses_id]['calc_errors'][$line['id']] = [];
        }
        $_SESSION[$ses_id]['calc_errors'][$line['id']][] = form_display($text);
    }
}

// Функция формирует безопасный bb-code
function form_bbcode_safe($text)
{
    global $config, $lang, $allow_bbcode_tags;
    $text = form_display($text);

    foreach ($allow_bbcode_tags AS $one_code => $param) {
        $search_results = array();
        // Замена непарных тегов (квадратные скобки в непарных тегах заменяются на html-последовательности)
        $text = preg_replace('/\[(' . $one_code . ')(.*)\](.*)\[\/(' . $one_code . ')\]/Usm',
            "{{{\$1\$2}}}\$3{{{/\$4}}}", $text);
        $text = preg_replace('/\[(\/?)(' . $one_code . ')\s*\]/Usm', "&#91;\$1\$2&#93;", $text);
        $text = preg_replace('/\{\{\{(' . $one_code . ')(.*)\}\}\}(.*)\{\{\{\/(' . $one_code . ')\}\}\}/Usm',
            "[\$1\$2]\$3[/\$4]", $text);

        if ($one_code == "noparse") { // Замена квадратных скобок на html-последовательности
            preg_match_all('/\[noparse\](.*)\[\/noparse\]/Usm', $text, $search_results, PREG_SET_ORDER);
            foreach ($search_results AS $one_result) {
                $text = str_replace($one_result[0],
                    str_replace(array("[noparse]", "[/noparse]", "[", "]"), array("", "", "&#91;", "&#93;"),
                        $one_result[1]), $text);
            }
        }

        if ($param) { // Проверка тегов с параметрами
            if ($one_code == "color" || $one_code == "size") { // Цвет и размер шрифта
                preg_match_all('/\[' . $one_code . '(.*)\](.*)\[\/' . $one_code . '\]/Usm', $text, $search_results,
                    PREG_SET_ORDER);
                foreach ($search_results AS $one_result) {
                    if (str_replace("=", "", $one_result[1]) == "") {
                        $text = str_replace($one_result[0],
                            "[" . $one_code . "=" . $param[$one_code]['default'] . "]" . $one_result[2] . "[/" . $one_code . "]",
                            $text);
                    } else {
                        $filter_param = trim(str_replace("=", "", $one_result[1]));
                        $filter_param = form_display($filter_param);
                        $filter_param = str_replace(array("[", "]"), array("&#91;", "&#93;"), $filter_param);
                        $filter_param = preg_replace('/expression[\s*]\((.*)\)/Usm', "\$1", $filter_param);
                        $text = str_replace($one_result[0],
                            "[" . $one_code . "=" . $filter_param . "]" . $one_result[2] . "[/" . $one_code . "]",
                            $text);
                    }
                }
            }
            if ($one_code == "email" || $one_code == "url" || $one_code == "img") { // Ссылки, изображения
                preg_match_all('/\[' . $one_code . '(.*)\](.*)\[\/' . $one_code . '\]/Usm', $text, $search_results,
                    PREG_SET_ORDER);
                foreach ($search_results AS $one_result) {
                    if (strpos($one_result[1], "=") === 0 && str_replace("=", "", $one_result[1]) == "") {
                        $url_param = $param[$one_code]['default'];
                    }
                    if (str_replace("=", "", $one_result[1]) == "") {
                        $url_param = $one_result[2];
                    } else {
                        $url_param = substr($one_result[1], 1);
                    }
                    $url_param = trim($url_param);
                    $url_param = form_display($url_param);
                    $url_param = str_replace(array("[", "]"), array("&#91;", "&#93;"), $url_param);
                    $url_param = preg_replace('/expression[\s*]\((.*)\)/Usm', "\$1", $url_param);

                    if (strpos(strtolower($url_param), "javascript:") === 0 || strrpos(strtolower($url_param),
                            ".js") == strlen($url_param) - 3 || strpos(strtolower($url_param), "data:") === 0
                    ) {
                        $text = str_replace($one_result[0], $one_result[2], $text);
                    } else {
                        $text = str_replace($one_result[0],
                            "[" . $one_code . "=" . $url_param . "]" . $one_result[2] . "[/" . $one_code . "]", $text);
                    }
                }
            }
            if ($one_code == "list") { // Списки
                preg_match_all('/\[list(.*)\](.*)\[\/list\]/Usm', $text, $search_results, PREG_SET_ORDER);
                foreach ($search_results AS $one_result) {
                    if (strpos($one_result[2], "[*]") === false) {
                        $one_result[2] = "[*]" . $one_result[2];
                    }
                    if (!in_array(str_replace("=", "", $one_result[1]), $param[$one_code]['values'])) {
                        $text = str_replace($one_result[0],
                            "[" . $one_code . "=" . $param[$one_code]['default'] . "]" . $one_result[2] . "[/" . $one_code . "]",
                            $text);
                    }
                }
            }
        }
    }

    return $text;
}

// Функция формирует html на основе bb-code
function form_bbcode_html($text)
{
    global $config, $lang, $allow_bbcode_tags;

    foreach ($allow_bbcode_tags AS $one_code => $param) {
        if ($one_code == "noparse") {
            continue;
        }
        $search_results = array();

        if ($param === false) {
            $regexp = '/\[(' . $one_code . ')\](.*)\[\/(' . $one_code . ')\]/Usm';
            if ($one_code == "strike" || $one_code == "s") {
                $text = preg_replace($regexp, "<span style='text-decoration: line-through'>\$2</span>", $text);
            } elseif ($one_code == "left" || $one_code == "right" || $one_code == "center") {
                $text = preg_replace($regexp, "<div style='text-align: " . $one_code . "'>\$2</div>", $text);
            } else {
                $text = preg_replace($regexp, "<\$1>\$2</\$3>", $text);
            }
        } else {
            if ($one_code == "color") {
                $text = preg_replace('/\[color=(.*)\](.*)\[\/color\]/Usm', "<span style='color: \$1'>\$2</span>",
                    $text);
            }
            if ($one_code == "size") {
                preg_match_all('/\[size=(.*)\](.*)\[\/size\]/Usm', $text, $search_results, PREG_SET_ORDER);
                foreach ($search_results AS $one_result) {
                    $fontsize = 13 + (int)$one_result[1];
                    $text = str_replace($one_result[0],
                        "<span style='font-size: " . $fontsize . "px'>" . $one_result[2] . "</span>", $text);
                }
            }
            if ($one_code == "url") {
                $text = preg_replace('/\[url=(.*)\](.*)\[\/url\]/Usm', "<a href=\"\$1\">\$2</a>", $text);
            }
            if ($one_code == "email") {
                $text = preg_replace('/\[email=(.*)\](.*)\[\/email\]/Usm', "<a href=\"mailto:\$1\">\$2</a>", $text);
            }
            if ($one_code == "img") {
                $text = preg_replace('/\[img=(.*)\](.*)\[\/img\]/Usm', "<img src=\"\$1\" />", $text);
            }
            if ($one_code == "list") {
                preg_match_all('/\[list=(.*)\](.*)\[\/list\]/Usm', $text, $search_results, PREG_SET_ORDER);
                foreach ($search_results AS $one_result) {
                    $list_option = "";
                    $list_content = array();
                    $list_items = "";
                    if ($one_result[1] == "*") {
                        $list_tag = "ul";
                    } else {
                        $list_tag = "ol";
                        $list_option = " type='" . $one_result[1] . "'";
                    }
                    $list_content = explode("[*]", $one_result[2]);
                    foreach ($list_content AS $c => $one_item) {
                        if (!$c) {
                            continue;
                        }
                        $list_items .= "<li>" . $one_item . "</li>";
                    }
                    $text = str_replace($one_result[0],
                        "<" . $list_tag . $list_option . ">" . $list_items . "</" . $list_tag . ">", $text);
                }
            }
        }
    }
    return $text;
}

// Функция генерирует безопасный bb-code и формирует html
function form_bbcode_display($text)
{
    return form_bbcode_html(form_bbcode_safe($text));
}

// Функция замены шаблонов в sql условиях (фильтры, напоминания, etc)
function filter_tpl_replace($sql, $calculate = '', $event = '', $user_data = '', $no_check_new_record = 0)
{
    global $user, $start_time;
    if($sql === 'NULL'){
        return true;
    }
    if (!$start_time) {
        $start_time = time();
    }
    if (!$user_data) {
        $user_data = $user;
    }

    // Рассчет времени для текущей половины месяца
    if  (date("d") < 16) {
        $begin_half_month = date("Y-m-01 00:00:00");
        $end_half_month = date("Y-m-15 23:59:59");
    } else {
        $begin_half_month = date("Y-m-16 00:00:00");
        $end_half_month = date("Y-m-d 23:59:59", strtotime('last day of this month', time()));
    }

    $shablons = array(
        "{current}",
        "{current_group}",
        "{current_user.fio}",
        "{current_user.email}",
        "{current_user.phone}",
        "{new_record}",
        "{empty_date}",
        "'{current_date}'",
        "'{current_time}'",
        "'{calculate}'",
        "'{begin_week}'",
        "'{end_week}'",
        "'{begin_half_month}'",
        "'{end_half_month}'",
        "'{begin_month}'",
        "'{end_month}'",
        "'{begin_year}'",
        "'{end_year}'"
    );
    $replace = array(
        $user_data['id'],
        $user_data['group_id'],
        $user_data['fio'],
        $user_data['e_mail'],
        $user_data['phone'],
        $no_check_new_record ? "1=1" : "(r<>0 and r<'$start_time')",
        "0000-00-00 00:00:00",
        "concat(current_date,' 00:00:00')",
        "now()",
        in_eval($calculate),
        "'" . date("Y-m-d 00:00:00", strtotime(date('o-\\WW-1'))) . "'",
        "'" . date("Y-m-d 23:59:59", strtotime(date('o-\\WW-7'))) . "'",
        "'" . date("Y-m-d 00:00:00", strtotime($begin_half_month)) . "'",
        "'" . date("Y-m-d 23:59:59", strtotime($end_half_month)) . "'",
        "'" . date('Y-m-d 00:00:00', strtotime('first day of this month')) . "'",
        "'" . date('Y-m-d 23:59:59', strtotime('last day of this month')) . "'",
        "'" . date('Y-m-d 00:00:00', strtotime('first day of January this year')) . "'",
        "'" . date('Y-m-d 23:59:59', strtotime('last day of December this year')) . "'"
    );
    if (strpos($sql, '{current_user.data')) {
        // связанные с пользователем таблицы
        $result = sql_select_field(TABLES_TABLE, 'id, user_table_link', "user_table_link != '' AND id != ", $table_id);
        while ($one_table = sql_fetch_assoc($result)) {
            $user_table_link = unserialize($one_table['user_table_link']);
            $line = data_select_array($one_table['id'], 'f' . $user_table_link['user_id'] . ' = ' . $user_data['id']);
            $result2 = sql_select_field(FIELDS_TABLE, 'id, type_field', 'table_id = ', $one_table['id']);
            while ($one_field = sql_fetch_assoc($result2)) {
                $one_field['int_name'] = $one_field['int_name'] ?: form_int_name($one_field['id'], $one_field['type_field']);
                $shablons[] = '{current_user.data' . $one_table['id'] . '.' . $one_field['int_name'] . '}';
                $replace[] = $line[$one_field['int_name']];
            }
        }
    }
    $sql = str_replace($shablons, $replace, $sql);
    $sql = str_replace("`", "", $sql);
    $sql = str_replace("DATA_TABLE", DATA_TABLE, $sql);

    if ($event and !$event['is_new_line']) {
        $shablons = array();
        foreach ($event['changed'] as $one_change) {
            $shablons[] = "{" . $one_change['int_name'] . "_changed}";
        }
        $sql = str_replace($shablons, "1", $sql);
    }

    global $sql_global_link, $sql_db_type;
    if ($link_identifier == 0) {
        $link_identifier = $sql_global_link;
    }
    if ($sql_db_type == "postgresql") {
        $sql = str_ireplace("`", "", $sql);
        $sql = str_ireplace("day(", "extract(day from ", $sql);
        $sql = str_ireplace("month(", "extract(month from ", $sql);
        $sql = str_ireplace("year(", "extract(year from ", $sql);
        $sql = str_ireplace("curdate()", "current_date", $sql);
        $sql = preg_replace("!left\((.*?),10\)!i", "cast($1 as date)", $sql);
        $sql = preg_replace("!interval (.*?) (.*?) !i", "interval '$1 $2' ", $sql);
    }

    return $sql;
}

// Функция замены шаблонов в умолчаниях полей
function default_tpl_replace($value, $field_id = 0, $mult = false)
{
    global $user;
    $rand_value = "";
    $inord_value = "";
    if ($value == "{random}") {
        $rand_value = field_random($field_id, $mult);
    }
    if($value == "{inorder}"){
        $inord_value = field_inorder($field_id, $mult);
    }
    $shablons = array("{current}", "{current_group}", "{cur.date}", "{cur.time}", "{random}", "{inorder}");
    $replace = array($user['id'], $user['group_id'], date("Y-m-d 00:00:00"), date("Y-m-d H:i:s"), $rand_value, $inord_value);
    $value = str_replace($shablons, $replace, $value);
    return $value;
}

// Функция замены обратного апострофа для PostgreSQL
function back_apostrophe_replace($str)
{
    global $sql_global_link, $sql_db_type;
    if ($sql_db_type == "postgresql") {
        for ($i = 0; $i < strlen($str); $i++) {
            if (!$infields and $str[$i] == "`") {
                $str[$i] = '"';
            } // замена ` на "
            if (!$infields and $str[$i] == "'") {
                $infields = 1;
                continue;
            }
            if ($infields and $str[$i] == "'") {
                $infields = 0;
                continue;
            }
        }
    }
    return $str;
}

// Вычисление страницы по умолчанию
function user_default_page($user_group)
{
    global $lang, $user, $script_name, $config;

    if ($config['is_mobile']) {
        if ($config['mobile_default_page_mode'] == 1) {
            $result = sql_select_field(USERS_TABLE, 'default_page', 'id=', $user['id']);
            if ($default_page = check_default_page($result)) {
                return $default_page;
            }
            $result = sql_select_field(GROUPS_TABLE, 'default_page', 'id=', $user['group_id']);
            if ($default_page = check_default_page($result)) {
                return $default_page;
            }
        }
        if ($config['mobile_default_page_mode'] == 2) {
            $default_page = explode('_', $config['mobile_default_page']);
            switch ($default_page[0]) {
                case 't':
                    return 'fields.php?table=' . $default_page[1];
                case 'r':
                    return 'report.php?id=' . $default_page[1];
                case 'c':
                    return 'calendar.php?id=' . $default_page[1];
            }
        }
        return 'm_menu.php';
    }

    //Проверяем наличие автозапускаемых бизнес-процессов
    if ($script_name == "login.php") { // только при входе
        if ($proc = sql_select_array(BIZPROC_TABLE, "autostart=1")) {
            $rights = explode(",", $proc['rights']);
            if (in_array($user['group_id'], $rights)) {
                sql_update(BIZPROC_TABLE, array('autostart' => 0), "id=", $proc['id']);
                if ($proc['bp_type'] == 0) {
                    $first_step = sql_select_array(BIZPROC_STEPS_TABLE, "proc_id=", $proc['id'], " and num=1");
                    return "fields.php?table=" . $first_step['table_id'] . "&bizproc=" . $proc['id'] . "&step=1";
                } else {
                    setcookie('bizproc_id', $proc['id']);
                }
            }
        }
    }

    //Проверяем определена ли страница по умолчанию для пользователя
    $result = sql_select_field(USERS_TABLE, 'default_page', 'id=', $user['id']);
    if ($user_default_page = check_default_page($result)) {
        return $user_default_page;
    }


    //Проверяем определена ли страница по умолчанию для группы
    $result = sql_select_field(GROUPS_TABLE, 'default_page', 'id=', $user['group_id']);
    if ($user_default_page = check_default_page($result)) {
        return $user_default_page;
    }

    $user_group = (int)$user_group;
    $cats = array();
    $sqlQuery = "SELECT tables.id, tables.table_num AS p_num, cats.num AS cat_num
               FROM " . CATS_TABLE . " AS cats, " . ACC_CATS_TABLE . " AS acc_cats, " . TABLES_TABLE . " AS tables, " . ACC_TABLES_TABLE . " AS acc_tables
               WHERE cats.id=acc_cats.cat_id AND acc_cats.access='1' AND acc_cats.group_id=$user_group
                     AND tables.cat_id=cats.id AND acc_tables.vis_acc=1 AND table_id=tables.id AND acc_tables.group_id=$user_group
               ORDER BY cat_num ASC, p_num ASC LIMIT 1";
    $result = sql_query($sqlQuery);
    if ($row = sql_fetch_assoc($result)) {
        $cats[$row['cat_num']][$row['p_num']] = array("type" => "table", "id" => $row['id']);
    }

    $sqlQuery = "SELECT reports.id, reports.num AS p_num, cats.num AS cat_num
               FROM " . CATS_TABLE . " AS cats, " . ACC_CATS_TABLE . " AS acc_cats, " . REPORTS_TABLE . " AS reports, " . ACC_REPORTS_TABLE . " AS acc_reports
               WHERE cats.id=acc_cats.cat_id AND acc_cats.access='1' AND acc_cats.group_id=$user_group
                     AND reports.cat_id=cats.id AND acc_reports.access=1 AND report_id=reports.id AND acc_reports.group_id=$user_group
               ORDER BY cat_num ASC, p_num ASC LIMIT 1";
    $result = sql_query($sqlQuery);
    if ($row = sql_fetch_assoc($result)) {
        $cats[$row['cat_num']][$row['p_num']] = array("type" => "report", "id" => $row['id']);
    }

    $sqlQuery = "SELECT calendars.id, calendars.num AS p_num, cats.num AS cat_num
               FROM " . CATS_TABLE . " AS cats, " . ACC_CATS_TABLE . " AS acc_cats, " . CALENDARS_TABLE . " AS calendars, " . ACC_CALENDARS_TABLE . " AS acc_calendars
               WHERE cats.id=acc_cats.cat_id AND acc_cats.access='1' AND acc_cats.group_id=$user_group
                     AND calendars.cat_id=cats.id AND acc_calendars.access=1 AND calendar_id=calendars.id AND acc_calendars.group_id=$user_group
               ORDER BY cat_num ASC, p_num ASC LIMIT 1";
    $result = sql_query($sqlQuery);
    if ($row = sql_fetch_assoc($result)) {
        $cats[$row['cat_num']][$row['p_num']] = array("type" => "calendar", "id" => $row['id']);
    }

    if ($cats) {
        ksort($cats);
        foreach ($cats AS $one_cat) {
            ksort($one_cat);
            foreach ($one_cat AS $one_part) {
                $default_page = $one_part;
                break;
            }
            break;
        }
        if ($default_page['type'] == "table") {
            $user_default_page = "fields.php?table=" . $default_page['id'];
        } else {
            $user_default_page = $default_page['type'] . ".php?id=" . $default_page['id'];
        }
    } else {
        if ($user['group_id'] == 1) {
            $user_default_page = "edit_cat.php";
        } else {
            $user_default_page = "fields.php";
        }
        // cb_die($lang['no_access_rigths']);
    }

    return $user_default_page;
}

function get_cats_pages($user_group_id = 0)
{
    if (!$user_group_id) {
        global $user;
        $user_group_id = $user['group_id'];
    }


    $dp_list = array();
    $data_c_acc = array();
    $data_t_acc = array();
    $data_r_acc = array();
    $data_cat_acc = array();
    $_cats = sql_select_field(CATS_TABLE, 'id, num, name', '1=', 1, ' ORDER BY num');
    $_tables = sql_select_field(TABLES_TABLE, 'id, cat_id, table_num, name_table', '1=', 1, ' ORDER BY 2, 3');
    $_reports = sql_select_field(REPORTS_TABLE, 'id, cat_id, num, name', '1=', 1, ' ORDER BY 2, 3');
    $_calendars = sql_select_field(CALENDARS_TABLE, 'id, cat_id, num, name', '1=', 1, ' ORDER BY 2, 3');
    $_tables_acc = sql_select_field(ACC_TABLES_TABLE, 'group_id, table_id, vis_acc', 'vis_acc=', 1, ' AND group_id=',
        $user_group_id);
    $_reports_acc = sql_select_field(ACC_REPORTS_TABLE, 'group_id, report_id, access', 'access=', 1, ' AND group_id=',
        $user_group_id);
    $_calendars_acc = sql_select_field(ACC_CALENDARS_TABLE, 'group_id, calendar_id, access', 'access=', 1,
        ' AND group_id=', $user_group_id);
    $_cats_acc = sql_select_field(ACC_CATS_TABLE, 'group_id, cat_id, access', 'access=', 1, ' AND group_id=',
        $user_group_id);


    while ($row_t_acc = sql_fetch_assoc($_tables_acc)) {
        array_push($data_t_acc, $row_t_acc['table_id']);
    }

    while ($row_r_acc = sql_fetch_assoc($_reports_acc)) {
        array_push($data_r_acc, $row_r_acc['report_id']);
    }

    while ($row_c_acc = sql_fetch_assoc($_calendars_acc)) {
        array_push($data_c_acc, $row_c_acc['calendar_id']);
    }

    while ($row_cat_acc = sql_fetch_assoc($_cats_acc)) {
        array_push($data_cat_acc, $row_cat_acc['cat_id']);
    }


    while ($row_t = sql_fetch_assoc($_tables)) {
        if (in_array($row_t['id'], $data_t_acc)) {
            $data_trc[$row_t['cat_id']][$row_t['table_num']] = array(
                'id' => 't_' . $row_t['id'],
                'name' => $row_t['name_table'],
                'type' => 't'
            );
        }
    }

    while ($row_r = sql_fetch_assoc($_reports)) {
        if (in_array($row_r['id'], $data_r_acc)) {
            $data_trc[$row_r['cat_id']][$row_r['num']] = array(
                'id' => 'r_' . $row_r['id'],
                'name' => $row_r['name'],
                'type' => 'r'
            );
        }
    }
    while ($row_c = sql_fetch_assoc($_calendars)) {
        if (in_array($row_c['id'], $data_c_acc)) {
            $data_trc[$row_c['cat_id']][$row_c['num']] = array(
                'id' => 'c_' . $row_c['id'],
                'name' => $row_c['name'],
                'type' => 'c'
            );
        }
    }

    while ($row = sql_fetch_assoc($_cats)) {
        if (in_array($row['id'], $data_cat_acc)) {
            $data_cat['name'] = $row['name'];
            if (is_array($data_trc[$row['id']])) {
                ksort($data_trc[$row['id']]);
            }
            $data_cat['contents'] = $data_trc[$row['id']];

            $dp_list[] = $data_cat;
        }
    }
    return $dp_list;
}

function check_default_page($result)
{
    if ($row = sql_fetch_assoc($result)) {
        $default_page = explode("_", $row['default_page']);
        if ($default_page[1]) {
            switch ($default_page[0]) {
                case 't':
                    $default_page[0] = 'table';
                    break;

                case 'r':
                    $default_page[0] = 'report';
                    break;

                case 'c':
                default:
                    $default_page[0] = 'calendar';
                    break;

            }
            if ($default_page[0] == "table") {
                $user_default_page = "fields.php?table=" . $default_page[1];
            } else {
                $user_default_page = $default_page[0] . ".php?id=" . $default_page[1];
            }

            return $user_default_page;
        }


    } else {
        return false;
    }
}

function file_size_formats($bytes)
{
    if ($bytes >= 1073741824) {
        $size = number_format($bytes / 1073741824, 2) . ' GB';
    } elseif ($bytes >= 1048576) {
        $size = number_format($bytes / 1048576, 2) . ' MB';
    } elseif ($bytes > 10) {
        $size = number_format($bytes / 1024, 2) . ' kB';
    } elseif ($bytes > 0) {
        $size = $bytes . ' B';
    } else {
        $size = '0 B';
    }
    return $size;
}

//костылим функцию getimagesizefromstring, которая появилась в php 5.4
function bm_getimagesizefromstring($param)
{
    $uniq_name = uniqid() . '.png';
    $temp_img = image_preview($param, 0, 0, 0, 0, $uniq_name);
    $size = getimagesize("cache/" . $uniq_name);
    if (file_exists("cache/temp.png")) {
        unlink("cache/" . $uniq_name);
    }
    return $size;
}

function display_notification($text, $type = 1, $where = 'all')
{
    global $ses_id, $lang, $user;
    if ($user['display_notification_on'] != 1) {
        return;
    }
    if ($type != 1 AND $type != 2 AND $type != 3) {
        return;
    }
    $display_notification_args_raw = array(
        'type' => $type,
        'text_raw' => $text,
        'where' => $where
    );
    $display_notification_args = array(
        'type' => $type,
        'text' => $text,
        'where' => $where
    );
    if (is_array($_SESSION[$ses_id]['display_notifications_raw'])) {
        $key = array_search($display_notification_args_raw, $_SESSION[$ses_id]['display_notifications_raw']);
    }
    if ($key !== false AND $key !== null AND (
            $display_notification_args_raw['text_raw'] == $lang['Success_save_notif'] OR
            $display_notification_args_raw['text_raw'] == $lang['Success_archive_notif'] OR
            $display_notification_args_raw['text_raw'] == $lang['Success_restore_notif'] OR
            $display_notification_args_raw['text_raw'] == $lang['Success_delete_notif']
        )
    ) {
//    $start = strpos($_SESSION[$ses_id]['display_notifications'][$key]['text'], '(');
//    $end = strpos($_SESSION[$ses_id]['display_notifications'][$key]['text'], ')');
//    $count = substr($_SESSION[$ses_id]['display_notifications'][$key]['text'], $start+1, $end - $start);
//    $count = intval($count)+1;
//    $display_notification_args['text'] = substr($_SESSION[$ses_id]['display_notifications'][$key]['text'], 0, $start+1).$count.substr($_SESSION[$ses_id]['display_notifications'][$key]['text'], $end);
        switch ($display_notification_args_raw['text_raw']) {
            case $lang['Success_save_notif']:
                $display_notification_args['text'] = $lang['Success_save_notifs'];
                break;
            case $lang['Success_archive_notif']:
                $display_notification_args['text'] = $lang['Success_archive_notifs'];
                break;
            case $lang['Success_restore_notif']:
                $display_notification_args['text'] = $lang['Success_restore_notifs'];
                break;
            case $lang['Success_delete_notif']:
                $display_notification_args['text'] = $lang['Success_delete_notifs'];
                break;
            default:
                break;
        }
        $_SESSION[$ses_id]['display_notifications'][$key] = $display_notification_args;
    } else {

        $_SESSION[$ses_id]['display_notifications_raw'][] = $display_notification_args_raw;
        $_SESSION[$ses_id]['display_notifications'][] = $display_notification_args;

        $use_arr = array();
        foreach ($_SESSION[$ses_id]['display_notifications'] as $index => $value) {
            if (!in_array($value['text'], $use_arr)) {
                $use_arr[] = $value['text'];
            } else {
                unset($_SESSION[$ses_id]['display_notifications'][$index]);
            }
        }

    }
}

function record_sublines_status_log($table_id, $link_field_id, $par_line)
{
    global $config, $lang, $user;

    $status = $par_line['status'];
    if ($status == 0) {
        $event_type = "restore_record";
    }
    if ($status == 1) {
        $event_type = "archive_record";
    }
    if ($status == 2) {
        $event_type = "delete_record";
    }

    if ($config['event_on'][$event_type]) {
        $table = get_table($table_id);
        $table_fields = get_table_fields($table);
        $result = data_select($table_id, "status=", $status, " and f", $link_field_id, "=", $par_line['id']);
        while ($line = sql_fetch_array($result)) {
            $line_id = $line['id'];
            $name_record = get_name_record($table, $table_fields, $line);
            if ($status == 0) {
                $mess = $lang['User'] . ' "' . form_display($user['fio']) . '" ' . $lang["restore_record_p0"] . "<a href='view_line2.php?table=$table_id&line=$line_id'>" . form_display($name_record) . "</a>" . $lang["restore_record_p1"] . $table['display']['name_table'] . $lang["restore_record_p2"];
            }
            if ($status == 1) {
                $mess = $lang['User'] . ' "' . form_display($user['fio']) . '" ' . $lang["archive_record_p0"] . "<a href='view_line2.php?table=$table_id&line=$line_id'>" . form_display($name_record) . "</a>" . $lang["archive_record_p1"] . $table['display']['name_table'] . $lang["archive_record_p2"];
            }
            if ($status == 2) {
                $mess = $lang['User'] . ' "' . form_display($user['fio']) . '" ' . $lang["delete_record_p0"] . "<a href='view_line" . $config["vlm"] . ".php?table=$table_id&line=$line_id'>" . $name_record . "</a>" . $lang["delete_record_p1"] . $table['name_table'] . $lang["delete_record_p2"];
            }
            \CB\CornyService::insert_log_light($event_type, $mess, $table_id, $line_id);
        }
    }
}

function form_subtables_join_query($filter_subtables, $table_id = 0)
{
    $sub_query = array();
    $filter_subtables = $filter_subtables ? unserialize($filter_subtables) : "";
    if (is_array($filter_subtables)) {
        foreach ($filter_subtables as $k => $v) {
            if ($table_id != 0 and $k != $table_id) {
                $sub_query['all_join'] .= " LEFT JOIN " . DATA_TABLE . $k . " as " . DATA_TABLE . $k . " on master.id = " . DATA_TABLE . $k . "." . $v['link_field'] . " ";
                foreach ($v['fields'] as $k1 => $v1) {
                    if ($v1 == 'id' OR $v1 == 'user_id' OR $v1 == 'add_time' OR $v1 == 'status') {
                        $sub_query['all_fields'] .= ',' . DATA_TABLE . $k . "." . $v1 . " as " . DATA_TABLE . $k . "_" . $v1;
                    }
                }
            }
        }

        $sub_query['group_rule'] = " GROUP BY master.id ";
    } else {
        $sub_query['all_join'] = '';
        $sub_query['all_fields'] = '';
        $sub_query['group_rule'] = "";

    }
    return $sub_query;
}

function close_bracket($str, $bracket_pos_start = -1)
{
    $p1 = $bracket_pos_start;
    $i = $p1;
    while ($i < strlen($str)) {
        if (substr($str, $i, 1) == '(') {
            $p1 = $i;
            break;
        }
        $i++;
    }
    if ($p1 == -1) {
        return false;
    }
    $p2 = -1;
    $count = 0;
    $i++;
    while ($i < strlen($str)) {
        if (substr($str, $i, 1) == '(') {
            $count++;
        } elseif (substr($str, $i, 1) == ')') {
            if ($count == 0) {
                $p2 = $i;
                break;
            } else {
                $count--;
            }
        }
        $i++;
    }
    if ($p2 == -1) {
        return false;
    }
    return $p2;
}

function subquery_to_left_join($str)
{
    $str = str_replace("\n", "", $str);
    $str = str_replace("curdate()", "current_date", $str);
    $str = str_replace("now()", "current_timestamp", $str);
    if (preg_match("/IN\s*\(SELECT\s+\w+\d+\s+FROM\s+".DATA_TABLE."/i", $str) && preg_match("/IN\s*\(SELECT id FROM\s+".DATA_TABLE."/i", $str) == false) {
        $from_pos = strpos($str, "FROM");
        $where_pos = strpos($str, "WHERE");
        $sql_arr[0] = substr($str, 0, $from_pos);
        $sql_arr[1] = substr($str, $from_pos, $where_pos - $from_pos);
        $sql_arr[2] = substr($str, $where_pos);

        $sql_arr[1] .= " as master ";
        $sql_arr[0] = preg_replace("/\s+\*/i", " master.*",$sql_arr[0], 1, $all_count);
        preg_match("/".DATA_TABLE."\d+/i", $sql_arr[1], $master_table);
        $pattern = "/IN\s+(\(SELECT\s+f\d+\s+FROM\s+".DATA_TABLE.".+)\)\s+/i";
        $master_pattern = array(
            "/([^_\.])(id)/i",
            "/([^\.])(user_id)/i",
            "/([^\.])(add_time)/i",
            "/([^\.])(status)/i",
        );
        $master_replace = array(
            "$1master.id",
            "$1master.user_id",
            "$1master.add_time",
            "$1master.status",
        );
        $sql_arr[0] = preg_replace($master_pattern, $master_replace, $sql_arr[0]);
        $subtables_joined = array();
        $subtables_fields = array();
        while (preg_match($pattern, $sql_arr[2], $matches, PREG_OFFSET_CAPTURE)) {
            $start_of_subquery = $matches['1']['1'];
            $end_of_subquery = close_bracket($sql_arr[2], $start_of_subquery);
            $start_str = substr($sql_arr[2], 0, $start_of_subquery);
            $end_str = substr($sql_arr[2], $end_of_subquery + 1);
            $subquery_str = substr($sql_arr[2], $start_of_subquery, $end_of_subquery - $start_of_subquery + 1);
            preg_match("/\(SELECT\s+(\w+\d+)\s+FROM\s+(".DATA_TABLE."\d+)\s+WHERE status=0 and (.*)\)$/i", $subquery_str, $submatches);
            $subquery_field = $submatches[1];
            $subquery_table = $submatches[2];
            $subquery_cond = $submatches[3];
            if (!isset($subtables_joined[$subquery_table])) {
                $subtables_joined[$subquery_table] = " LEFT JOIN " . $subquery_table . " as " . $subquery_table . " ON master.id=" . $subquery_table . "." . $subquery_field . " and " . $subquery_table . ".status=0 ";
            }
            $slave_replace = array(
                "$1" . $subquery_table . ".id",
                "$1" . $subquery_table . ".user_id",
                "$1" . $subquery_table . ".add_time",
                "$1" . $subquery_table . ".status",
            );
            $matches_sys = array();
            $matches_f = array();
            if ($master_table[0] == $subquery_table) {
                //Закомментировано, так как нельзя передавать в preg_match_all массив.
                //Раз нерабочий вариант всех устраивал, ок - просто комментирую (на всякий случай оставляю с примечанием)
                //preg_match_all($master_pattern, $subquery_cond, $matches_sys);
                $subquery_cond = preg_replace($master_pattern, $master_replace, $subquery_cond);
                preg_match_all("/([^a-zA-Z0-9]*?)(f\d+)/i", $subquery_cond, $matches_f);
                $subquery_cond = preg_replace("/([^a-zA-Z0-9]*?)(f\d+)/i", "$1" . $subquery_table . ".$2",
                    $subquery_cond);
            } else {
                //Закомментировано, так как нельзя передавать в preg_match_all массив.
                //Раз нерабочий вариант всех устраивал, ок - просто комментирую (на всякий случай оставляю с примечанием)
                //preg_match_all($master_pattern, $subquery_cond, $matches_sys);
                $subquery_cond = preg_replace($master_pattern, $slave_replace, $subquery_cond);
                preg_match_all("/([^a-zA-Z0-9]*?)(f\d+)/i", $subquery_cond, $matches_f);
                $subquery_cond = preg_replace("/([^a-zA-Z0-9]*?)(f\d+)/i", "$1" . $subquery_table . ".$2",
                    $subquery_cond);
            }
            foreach ($matches_sys[2] as $k => $v) {
                if (!isset($subtables_fields[$subquery_table . "." . $matches_sys[2][$k]])) {
                    $subtables_fields[$subquery_table . "." . $matches_sys[2][$k]] = $subquery_table . "." . $matches_f[2][$k];
                }
            }
            foreach ($matches_f[2] as $k => $v) {
                if (!isset($subtables_fields[$subquery_table . "." . $matches_f[2][$k]])) {
                    $subtables_fields[$subquery_table . "." . $matches_f[2][$k]] = $subquery_table . "." . $matches_f[2][$k];
                }
            }
            $start_str = preg_replace("/\s+id\s+IN/i", " (" . $subquery_cond . ")", $start_str);
            $sql_arr[2] = $start_str . $end_str;
        }
        $sql_arr[1] .= implode(" ", $subtables_joined);
        $sql_arr[2] = preg_replace($master_pattern, $master_replace, $sql_arr[2]);
        $sql_arr[2] = preg_replace("/([^\.\w])(f\d+)/i", "$1master.$2", $sql_arr[2]);
        $sql_arr[0] = preg_replace("/([^\.\w])(f\d+)/i", "$1master.$2", $sql_arr[0]);
        if (preg_match("/GROUP BY/", $sql_arr[2])) {
            $sql_arr[2] = preg_replace("/GROUP BY\s+/", " GROUP BY master.id,", $sql_arr[2]);
        } else {
            if (preg_match("/ORDER BY/i", $sql_arr[2])) {
                $sql_arr[2] = str_replace("ORDER BY", " GROUP BY master.id ORDER BY", $sql_arr[2]);
            } else {
                if (preg_match("/ LIMIT /i", $sql_arr[2])) {
                    $sql_arr[2] = str_replace(" LIMIT ", " GROUP BY master.id LIMIT ", $sql_arr[2]);
                } else {
                    $sql_arr[2] .= " GROUP BY master.id";
                }
            }
        }
        $replaced_sum = 0;
        if (preg_match_all("/sum\(master\.(f\d+)\) as ([\w\d]+)/i", $sql_arr[0], $sum_matches, PREG_SET_ORDER)) {
            $new_select_start = "SELECT ";
            foreach ($sum_matches as $one_key => $one_match) {

                $new_select_start .= "sum(temp_" . $one_match[2] . ") as " . $one_match[2] . " ,";
                $sql_arr[0] = preg_replace("/sum\((master\.f\d+)\) as ([^\s]+)/i", "$1 as temp_$2", $sql_arr[0]);
            }
            $new_select_start = substr($new_select_start, 0, -1);
            $new_select_start .= " FROM (";
            $replaced_sum = 1;
            $new_select_end = ") as master";
        }
        $str = implode(" ", $sql_arr);
        if (preg_match("/count\(/i", $sql_arr[0])) {
            $str = preg_replace("/\*/i", "master.*", $str, 1);
            $str = preg_replace("/count\(([\*\w\d_\.]+)\)\s+as\s+[\w\d_]+/i", "$1", $str);
            $str = exclude_dup_by_fields($str);
            $str = $sql_arr[0] . " FROM (" . $str . ") as master";
        } else {
            $str = exclude_dup_by_fields($str);
        }
        if ($replaced_sum == 1) {
            $str = $new_select_start . $str . $new_select_end;
        }
    } else {
        if (preg_match("/{{{{GROUPBY (\d+)}}}}/i", $str)) {
            if (preg_match("/count\(([\*\w\d_\.]+)\)\s+as\s+[\w\d_]+/i", $str, $count_matches)) {
                $str = preg_replace("/count\(([\*\w\d_\.]+)\)\s+as\s+[\w\d_]+/i", "$1", $str);
                $str = exclude_dup_by_fields($str);
                $str = "SELECT " . $count_matches[0] . " FROM (" . $str . ") as master";
            } elseif (preg_match_all("/sum\((f\d+)\) as ([\w\d]+)/i", $str, $sum_matches, PREG_SET_ORDER)) {
                $new_select_start = "SELECT ";
                foreach ($sum_matches as $one_key => $one_match) {
                    $new_select_start .= "sum(" . $one_match[1] . ") as " . $one_match[2] . " ,";
                }
                $str = preg_replace("/(sum\((f\d+)\) as ([^\s]+)\s*,?)+/i", " * ", $str);
                $str = exclude_dup_by_fields($str);
                $new_select_start = substr($new_select_start, 0, -1);
                $new_select_start .= " FROM (";
                $new_select_end = ") as master";
                $str = $new_select_start . $str . $new_select_end;
            } else {
                $str = exclude_dup_by_fields($str);
            }
        }
    }
//  $str = str_replace("`","",$str);
    $str = preg_replace("/`(master\.[\w\d_]+)`/i", "$1", $str);
    $str = preg_replace("/`(master_\d+\.[\w\d_]+)`/i", "$1", $str);
    $str = preg_replace("/`(" . DATA_TABLE . "\d+\.[\w\d_]+)`/i", "$1", $str);
    $str = preg_replace("/WHERE\s+\)/i", ")", $str);
    $str = str_replace(" and (1=1)", " ", $str);
    return $str;
}

function exclude_dup_by_fields($str)
{
    if (preg_match_all('/{{{{GROUPBY (\d+)}}}}/i', $str, $matches)) {
        $str = preg_replace('/{{{{GROUPBY \d+}}}}/i', '', $str);
        preg_match('/(ORDER BY.*)(LIMIT\s+(\d+))?.*$/', $str, $order_limit_fields);
        preg_match('/(ORDER BY.*?)(?=LIMIT|$)/i', $str, $order_by_match);
        $order_by = isset($order_by_match[1]) ? $order_by_match[1] : '';
        preg_match_all('/(\b\w+\b)/i', $order_limit_fields[1], $order_matches);
        $str = preg_replace('/(ORDER BY.*)(LIMIT\s+(\d+))?.*$/', '', $str);
        $fields = array_unique($matches[1]);
        $order_fields = array_unique($order_matches[1]);

        if (!preg_match('/.*SELECT.*?(count|sum|\*).*WHERE/i', $str)) {
            $tail = substr($str, 10000);   // отрезаем хвост если запрос слишком длинный
            $str = substr($str, 0, 10000); // иначе preg_replace вылетает и возвращает null
            foreach ($fields as $num => $one_field) {
                if (!preg_match('/.*SELECT.*?' . form_int_name($one_field) . '.*WHERE/', $str)) {
                    if (preg_match('/SELECT.*LEFT JOIN.*WHERE/', $str)) {
                        $master_add = 'master.';
                    } else {
                        $master_add = '';
                    }
                    $str = preg_replace('/(.*)SELECT(.*?)WHERE/i', '$1SELECT ' . $master_add . form_int_name($one_field) . ', $2WHERE', $str);
                }
            }
            foreach ($order_fields as $num => $one_field) {
                $one_field = strtolower($one_field);
                if (in_array($one_field, array('order', 'by', 'asc', 'desc'))) {
                    continue;
                }
                if ($one_field == 'limit') {
                    break;
                }
                if (!preg_match('/.*SELECT.*?' . $one_field . '.*WHERE/', $str)) {
                    if (preg_match('/SELECT.*LEFT JOIN.*WHERE/', $str)) {
                        $master_add = 'master.';
                    } else {
                        $master_add = '';
                    }
                    $str = preg_replace('/(.*)SELECT(.*?)WHERE/i', '$1SELECT ' . $master_add . $one_field . ', $2WHERE', $str);
                }
            }
            $str .= $tail; // возвращаем хвост на место
        }

        $str .= ' ' . $order_limit_fields[1] . ' ' . $order_limit_fields[2];
        foreach ($fields as $num => $one_field) {
            $fields[$num] = " master_$num." . form_int_name($one_field);
            $str = "SELECT master_$num.* FROM (" . $str . ") as master_$num GROUP BY " . $fields[$num];
            if($order_by) {
                $str .= " ". $order_by;
            }
        }
    }
    $str = preg_replace('/(and|or)\s+\(\)/i', '', $str);
    $str = preg_replace('/\s\(\)\s+(and|or)/i', '', $str);
    $str = preg_replace('/^\(\)\s+(and|or)/i', '', $str);
    return $str;
}

// Добавление таблиц из экспресс-конструктора
function apply_custom_conf($schema_json)
{
    global $config, $lang;

    $schema = json_decode($schema_json, true);

    // Добавляем категорию
    $row = sql_select_array(CATS_TABLE, "1=1 ORDER BY num DESC");
    $cat_id = sql_insert(CATS_TABLE, array('num'=>$row['num']+1,'name'=>'Мои таблицы'));
    sql_insert(ACC_CATS_TABLE, array('cat_id'=>$cat_id,'group_id'=>1,'access'=>1));


    foreach ($schema as $keyElement => $element) {

        // Смотрим, есть ли таблица с тем же именем в текущей конфе
        $row = sql_select_array(TABLES_TABLE, "name_table='". $element['name'] ."'");
        if ($row) {
            $element['name'] = $element['name']." 2";
        }
        // Добавляем таблицу
        $ins_table = array('cat_id'     => $cat_id,
                           'table_num'  => $keyElement + 1,
                           'name_table' => $element['name'],
                           'lop'        => 100);
        $table_id = sql_insert(TABLES_TABLE, $ins_table);

        // Создание служебных полей
        $ins_field = array('table_id'   => $table_id,
                           'field_num'  => 1,
                           'name_field' => 'ID',
                           'type_field' => 10,
                           'default_value' => '',
                           'main'       => 1,
                           'uniq_field' => 1);
        sql_insert(FIELDS_TABLE, $ins_field);
        $ins_field = array('table_id'   => $table_id,
                           'field_num'  => 2,
                           'name_field' => $lang['added_by'],
                           'type_field' => 11,
                           'type_value' => '0|0',
                           'default_value' => '{current}');
        sql_insert(FIELDS_TABLE, $ins_field);
        $ins_field = array('table_id'   => $table_id,
                           'field_num'  => 3,
                           'name_field' => $lang['addition_time'],
                           'type_field' => 12,
                           'type_value' => '1',
                           'default_value' => '{cur.time}');
        sql_insert(FIELDS_TABLE, $ins_field);
        $ins_field = array('table_id'   => $table_id,
                           'field_num'  => 4,
                           'name_field' => $lang['record_status'],
                           'type_field' => 13,
                           'default_value' => 0);
        sql_insert(FIELDS_TABLE, $ins_field);

        // Собственно создание таблицы (для данных)
        sql_query(\CB\CornyService::buildCreateTableSql(DATA_TABLE . $table_id));

        // Включаем права админу
        $table_acc = array(
            'table_id' => $table_id,
            'group_id' => 1,
            'acc'      => 1,
            'vis_acc'  => 1,
            'add_acc'  => 1,
            'del_acc'  => 1,
            'arc_acc'  => 1,
            'imp_acc'  => 1,
            'exp_acc'  => 1,
            'adf_acc'  => 1,
            'bed_acc'  => 1,
            'adf_acc_print' => 1,
            'adf_acc_send' => 1,
            'adf_acc_sms' => 1,
            'standart_template' => 1,
        );
        sql_insert(ACC_TABLES_TABLE, $table_acc);

        // Добавляем поля

        foreach ($element['fields'] as $k => $el) {

            switch ($el['type']) {
                case 1:
                    $ins_field = array('table_id'      => $table_id,
                                       'field_num'     => $k + 5,
                                       'name_field'    => $el['name'],
                                       'type_field'    => $el['type'],
                                       'type_value'    => '10/0|1',
                                       'default_value' => 0
                    );
                    break;
                case 2:
                    $ins_field = array('table_id'   => $table_id,
                                       'field_num'  => $k + 5,
                                       'name_field' => $el['name'],
                                       'type_field' => $el['type'],
                                       'type_value' => 0
                    );
                    break;
                case 3:
                    $ins_field = array('table_id'   => $table_id,
                                       'field_num'  => $k + 5,
                                       'name_field' => $el['name'],
                                       'type_field' => $el['type']
                    );
                    break;
                case 4:
                    $ins_field = array('table_id'   => $table_id,
                                       'field_num'  => $k + 5,
                                       'name_field' => $el['name'],
                                       'type_field' => $el['type'],
                                       'type_value' => $el['listrow']
                    );
                    break;
                case 5:
                    $ins_field = array('table_id'   => $table_id,
                                       'field_num'  => $k + 5,
                                       'name_field' => $el['name'],
                                       'type_field' => $el['type'],
                                       'type_value' => '0|0|0|0|0'
                    );
                    break;
                case 6:
                    $ins_field = array('table_id'   => $table_id,
                                       'field_num'  => $k + 5,
                                       'name_field' => $el['name'],
                                       'type_field' => $el['type'],
                                       'type_value' => '|0'
                    );
                    break;
                case 7:
                    $ins_field = array('table_id'      => $table_id,
                                       'field_num'     => $k + 5,
                                       'name_field'    => $el['name'],
                                       'type_field'    => $el['type'],
                                       'default_value' => 0
                    );
                    break;
                case 9:
                    $ins_field = array('table_id'   => $table_id,
                                       'field_num'  => $k + 5,
                                       'name_field' => $el['name'],
                                       'type_field' => $el['type'],
                                       'type_value' => '100x100|0'
                    );
                    break;
                case 14:
                    $ins_field = array('table_id'      => $table_id,
                                       'field_num'     => $k + 5,
                                       'name_field'    => $el['name'],
                                       'type_field'    => $el['type'],
                                       'type_value'    => '0|0|',
                                       'default_value' => 0
                    );
                    break;
            }
            $field_id = sql_insert(FIELDS_TABLE, $ins_field);


            // Собственно создание поля (для данных)
            sql_query("ALTER TABLE " . DATA_TABLE . $table_id . " ADD f" . $field_id . " VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT ''");

            // Включаем права админу
            $field_acc = array(
                'table_id'  => $table_id,
                'field_id'  => $field_id,
                'group_id'  => 1,
                'view_tb'   => 1,
                'view_add'  => 1,
                'view_edit' => 1,
                'view'      => 1,
                'read_acc'  => 1,
                'write_acc' => 1,
            );
            sql_insert(ACC_FIELDS_TABLE, $field_acc);
        }
        $schema[$keyElement] = $element;
    }

    // Перебираем массив снова, чтобы задать поля связи
    foreach ($schema as $keyElement => $element) {
        foreach ($element['fields'] as $k => $el) {
            if ($el['type'] == 5) {
                // id Таблицы и Поля с типом связь
                $idCurTable = sql_select_array(TABLES_TABLE, "name_table='".$element['name']."'");
                $idCurField = sql_select_array(FIELDS_TABLE, "name_field='".$el['name']."' and table_id=" . $idCurTable['id']);
                // id Таблицы и поля для связи
                $idJoinTable = sql_select_array(TABLES_TABLE, "name_table='".$schema[$el['joinrow']['idtable']]['name']."'");
                $idJoinFields = sql_select_array(FIELDS_TABLE, "name_field='".$schema[$el['joinrow']['idtable']]['fields'][$el['joinrow']['idfield']]['name']."' and table_id=".$idJoinTable['id']);

                $ins_field = array('type_value' => $idJoinTable['id'] . '|' . $idJoinFields['id'] . '|0|0|0');
                sql_update(FIELDS_TABLE, $ins_field, "id=".$idCurField['id']);
            }
        }
    }
}

// Обнуление конфигурации
function clear_configuration()
{
    global $config, $lang;

    sql_query("TRUNCATE TABLE ".ACC_ADDIT_TABLES_TABLE);
    sql_query("TRUNCATE TABLE ".ACC_BUTTONS_TABLE);
    sql_query("TRUNCATE TABLE ".ACC_CALENDARS_TABLE);
    sql_query("TRUNCATE TABLE ".ACC_RULES_TABLE);
    sql_query("TRUNCATE TABLE ".ACC_SUBTABLE_RULES_TABLE);
    sql_query("TRUNCATE TABLE ".ACC_FILTERS_TABLE);
    sql_query("TRUNCATE TABLE ".ACC_FORMS_TABLE);
    sql_query("TRUNCATE TABLE ".ACC_MESSAGES_TABLE);
    sql_query("TRUNCATE TABLE ".ACC_REPORTS_TABLE);
    sql_query("TRUNCATE TABLE ".ACC_REPORTS_USERS_TABLE);
    sql_query("TRUNCATE TABLE ".ACC_SUBTABLES_TABLE);
    sql_query("TRUNCATE TABLE ".ACC_TIPS_TABLE);
    sql_query("TRUNCATE TABLE ".ACC_ADDIT_TABLES_TABLE."_par");
    sql_query("TRUNCATE TABLE ".ACC_BUTTONS_TABLE."_par");
    sql_query("TRUNCATE TABLE ".ACC_CALENDARS_TABLE."_par");
    sql_query("TRUNCATE TABLE ".ACC_FILTERS_TABLE."_par");
    sql_query("TRUNCATE TABLE ".ACC_FORMS_TABLE."_par");
    sql_query("TRUNCATE TABLE ".ACC_REPORTS_TABLE."_par");
    sql_query("TRUNCATE TABLE ".ACC_SUBTABLES_TABLE."_par");
    sql_query("TRUNCATE TABLE ".ACC_TIPS_TABLE."_par");
    sql_query("TRUNCATE TABLE ".BIZPROC_TABLE);
    sql_query("TRUNCATE TABLE ".BIZPROC_STEPS_TABLE);
    sql_query("TRUNCATE TABLE ".BUTTONS_TABLE);
    sql_query("TRUNCATE TABLE ".BUTTONS_PARAMETERS_TABLE);
    sql_query("TRUNCATE TABLE ".CALC_TABLE);
    sql_query("TRUNCATE TABLE ".CALC_COND_TABLE);
    sql_query("TRUNCATE TABLE ".CALENDARS_TABLE);
    sql_query("TRUNCATE TABLE ".CALENDAR_EVENTS);
    sql_query("TRUNCATE TABLE ".CALENDAR_FIELDS);
    sql_query("TRUNCATE TABLE ".FIELD_GROUPS);
    sql_query("TRUNCATE TABLE ".FIELDS_LINKS_SHOW_TABLE);
    sql_query("TRUNCATE TABLE ".FILTERS_TABLE);
    sql_query("TRUNCATE TABLE ".FILTER_FIELDS_TABLE);
    sql_query("TRUNCATE TABLE ".FORMAT_TABLE);
    sql_query("TRUNCATE TABLE ".FORMS_TABLE);
    sql_query("TRUNCATE TABLE ".FORMS_VARS_TABLE);
    sql_query("TRUNCATE TABLE ".FREE_FORMS_TABLE);
    sql_query("TRUNCATE TABLE ".MAIL_FILES_LINKS_TABLE);
    sql_query("TRUNCATE TABLE ".MAIL_FILES_INFO_TABLE);
    sql_query("TRUNCATE TABLE ".MAIL_FILES_PART_TABLE);
    sql_query("TRUNCATE TABLE ".MESSAGES_TABLE);
    sql_query("TRUNCATE TABLE ".MESSAGES_SETTINGS_TABLE);
    sql_query("TRUNCATE TABLE ".CHATES_TABLE);
    sql_query("TRUNCATE TABLE ".QST_TABLE);
    sql_query("TRUNCATE TABLE ".QST_FIELDS_TABLE);
    sql_query("TRUNCATE TABLE ".QST_GROUPS_TABLE);
    sql_query("TRUNCATE TABLE ".QST_FILES_TABLE);
    sql_query("TRUNCATE TABLE ".QST_STAT_TABLE);
    sql_query("TRUNCATE TABLE ".QST_TAG_TABLE);
    sql_query("TRUNCATE TABLE ".REPORTS_TABLE);
    sql_query("TRUNCATE TABLE ".SUBTABLES_TABLE);
    sql_query("TRUNCATE TABLE ".ADDIT_TABLES_TABLE);
    sql_query("TRUNCATE TABLE ".TIPS_TABLE);
    sql_query("TRUNCATE TABLE ".INFORMERS_TABLE);
    sql_query("TRUNCATE TABLE ".LOGS_ACC_TABLE);
    sql_query("DELETE FROM ".CONFIG_TABLE." WHERE name = 'autoset_right_off'");
    sql_query("DELETE FROM ".CONFIG_TABLE." WHERE name = 'calendar_window'");
    sql_query("DELETE FROM ".CRON_TABLE." WHERE system = 0");

    $logs_mail = sql_select_array(LOGS_SUBTABLE_TABLE);
    if ($logs_mail || $config['fields_change_log']) {
        $change_log = json_decode($config['fields_change_log'], true);
        sql_query("DELETE FROM ".ACC_FIELDS_TABLE." WHERE table_id != '".$logs_mail['table_id']."' AND table_id != '".$change_log['table_id']."'");
        sql_query("DELETE FROM ".ACC_FIELDS_TABLE."_par WHERE table_id != '".$logs_mail['table_id']."' AND table_id != '".$change_log['table_id']."'");
        sql_query("DELETE FROM ".FIELDS_TABLE." WHERE (table_id != '".$logs_mail['table_id']."' AND table_id != '".$change_log['table_id']."') OR type_field = 5");
        sql_query("DELETE FROM ".ACC_TABLES_TABLE." WHERE table_id != '".$logs_mail['table_id']."' AND table_id != '".$change_log['table_id']."'");
        sql_query("DELETE FROM ".ACC_TABLES_TABLE."_par WHERE table_id != '".$logs_mail['table_id']."' AND table_id != '".$change_log['table_id']."'");
        sql_query("DELETE FROM ".TABLES_TABLE." WHERE id != '".$logs_mail['table_id']."' AND id != '".$change_log['table_id']."'");
        sql_query("DELETE FROM ".ACC_CATS_TABLE." WHERE cat_id != '".$logs_mail['cat_id']."'");
        sql_query("DELETE FROM ".ACC_CATS_TABLE."_par"." WHERE cat_id != '".$logs_mail['cat_id']."'");
        sql_query("DELETE FROM ".CATS_TABLE." WHERE id != '".$logs_mail['cat_id']."'");
    } else {
        sql_query("TRUNCATE TABLE ".ACC_FIELDS_TABLE);
        sql_query("TRUNCATE TABLE ".ACC_FIELDS_TABLE."_par");
        sql_query("TRUNCATE TABLE ".FIELDS_TABLE);
        sql_query("TRUNCATE TABLE ".ACC_TABLES_TABLE);
        sql_query("TRUNCATE TABLE ".ACC_TABLES_TABLE."_par");
        sql_query("TRUNCATE TABLE ".TABLES_TABLE);
        sql_query("TRUNCATE TABLE ".ACC_CATS_TABLE);
        sql_query("TRUNCATE TABLE ".ACC_CATS_TABLE."_par");
        sql_query("TRUNCATE TABLE ".CATS_TABLE);
    }

    // Оставляем системные вычисления
    sql_query("INSERT INTO ".CALC_TABLE." (name, calculate) VALUES ('".$lang['Calc_name_login']."','global \$user;\nif (\$event[''param'']==0) // Login\n   {\n   }\n   else\nif (\$event[''param'']==1) // Auto Login\n   {\n   }\n   else\nif (\$event[''param'']==2) // Logout\n   {\n   }')");
    $calc_id = sql_insert_id();
    sql_query("INSERT INTO ".CALC_COND_TABLE." (calc_id,type) VALUES ('$calc_id','".EVT_USER_LOGIN."')");
    sql_query("INSERT INTO ".CALC_TABLE." (name,calculate) VALUES ('".$lang['Calc_name_Change_User']."','\$user_id=\$event[''param''];\n\$change_act=\$event[''param2''];\nif (\$change_act==0) // Change\n   {\n   }\n   else\nif (\$change_act==1) // Addition\n   {\n   }\n   else\nif (\$change_act==2) // Removal\n   {\n   }\n   else\nif (\$change_act==3) // Archiving\n   {\n   }   \n   else\nif (\$change_act==4) // Restore\n   {\n   }')");
    $calc_id = sql_insert_id();
    sql_query("INSERT INTO ".CALC_COND_TABLE." (calc_id,type) VALUES ('$calc_id','".EVT_USER_CHANGE."')");

    // Удаляем таблицы с данными
    $result = sql_query("SHOW TABLES");
    while ($table = sql_fetch_array($result)) {
        if (substr($table[0],0,strlen(DATA_TABLE))==DATA_TABLE and $table[0]!=DATA_FILES_TABLE and $table[0]!=DATA_TABLE.$logs_mail['table_id'] and $table[0]!=DATA_TABLE.$change_log['table_id']) {
            sql_query("DROP TABLE ".$table[0]);
        }
    }
}

// Удаление таблицы со всеми элементами и данными
function delete_table($table_id, $include_files = 1)
{
    global $config;

    $table_fields = get_table_fields(get_table($table_id));
    foreach ($table_fields as $one_field) {
        $fields_array[] = $one_field['id'];
    }

    sql_delete(TABLES_TABLE, 'id=', $table_id);
    sql_delete(ACC_TABLES_TABLE, 'table_id=', $table_id);
    sql_delete(ACC_TABLES_TABLE . '_par', 'table_id=', $table_id);
    // удаление прав субадмина
    clear_subadmin_rights($table_id, 'table');
    // удаление полей
    sql_delete(FIELDS_TABLE, 'table_id=', $table_id);
    sql_delete(FIELD_GROUPS, 'table_id=', $table_id);
    sql_delete(ACC_FIELDS_TABLE, 'table_id=', $table_id);
    sql_delete(ACC_FIELDS_TABLE . '_par', 'table_id=', $table_id);
    // удаление полей фильтров
    $result = sql_select(FILTERS_TABLE, 'table_id=', $table_id);
    while ($filter = sql_fetch_assoc($result)) {
        sql_delete(FILTER_FIELDS_TABLE, 'filter_id=', $filter['id']);
    }
    // удаление фильтров
    sql_delete(FILTERS_TABLE, 'table_id=', $table_id);
    sql_delete(ACC_FILTERS_TABLE, 'table_id=', $table_id);
    sql_delete(ACC_FILTERS_TABLE . '_par', 'table_id=', $table_id);
    // удаление шаблонов
    sql_delete(FORMS_TABLE, 'table_id=', $table_id);
    sql_delete(FORMS_VARS_TABLE, 'table_id=', $table_id);
    sql_delete(ACC_FORMS_TABLE, 'table_id=', $table_id);
    sql_delete(ACC_FORMS_TABLE . '_par', 'table_id=', $table_id);
    sql_delete(LOGS_ACC_TABLE, 'table_id=', $table_id);
    // удаление напоминаний
    sql_delete(TIPS_TABLE, 'table_id=', $table_id);
    sql_delete(TIPS_SHOW_TABLE, 'table_id=', $table_id);
    sql_delete(TIPS_SHOW_ARHIVE_TABLE, 'table_id=', $table_id);
    sql_delete(ACC_TIPS_TABLE, 'table_id=', $table_id);
    sql_delete(ACC_TIPS_TABLE . '_par', 'table_id=', $table_id);
    // удаление форматирований
    sql_delete(FORMAT_TABLE, 'table_id=', $table_id);
    // удаление информеров
    sql_delete(INFORMERS_TABLE, 'table_id=', $table_id);
    // удаление шаблонов импорта
    sql_delete(IMPORT_TPL_TABLE, 'table_id=', $table_id);
    // удаление шаблонов экспорта
    sql_delete(EXPORT_TPL_TABLE, 'table_id=', $table_id);
    // удаление шаблонов поиска
    sql_delete(SEARCH_TEMPLATES_TABLE, 'table_id=', $table_id);
    // удаление связанных с шаблонами файлов
    $result_file_link = sql_select(MAIL_FILES_LINKS_TABLE, 'table_id=', $table_id);
    while ($row_file_link = sql_fetch_assoc($result_file_link)) {
        $links_file = sql_select(MAIL_FILES_LINKS_TABLE, 'file_id=', $row_file_link['file_id']);
        if (sql_num_rows($links_file) == 1) {
            sql_delete(MAIL_FILES_INFO_TABLE, 'id=', $row_file_link['file_id']);
            sql_delete(MAIL_FILES_PART_TABLE, 'file_id=', $row_file_link['file_id']);
        }
        sql_delete(MAIL_FILES_LINKS_TABLE, 'id=', $row_file_link['id']);
    }
    // удаление полей синхронизаций
    sql_delete(SYNC_FIELDS_TABLE, 'field_id in (', $fields_array, ')');
    // удаление доп.полей связи
    sql_delete(FIELDS_LINKS_SHOW_TABLE, 'field_id in (', $fields_array, ')');
    // удаление доп.полей быстрого добавления через поле связи
    sql_delete(LINK_FIELDS_FOR_ADDITION_TABLE, 'field_id in (', $fields_array, ')');
    // удаление вычислений
    $result = sql_select(CALC_TABLE, 'table_id=', $table_id);
    while ($calc = sql_fetch_assoc($result)) {
        sql_delete(CALC_TABLE, 'id=', $calc['id']);
        sql_delete(CALC_COND_TABLE, 'calc_id=', $calc['id']);
        sql_delete(CRON_TABLE, 'calc_id=', $calc['id']);
    }
    // удаление доп.действий
    $result = sql_select(BUTTONS_TABLE, 'table_id=', $table_id);
    while ($button = sql_fetch_assoc($result)) {
        sql_delete(BUTTONS_TABLE, 'id=', $button['id']);
        sql_delete(BUTTONS_PARAMETERS_TABLE, 'button_id=', $button['id']);
        sql_delete(ACC_BUTTONS_TABLE, 'button_id=', $button['id']);
        sql_delete(ACC_BUTTONS_TABLE . '_par', 'button_id=', $button['id']);
    }
    sql_delete(BUTTON_GROUPS, 'table_id=', $table_id);
    // удаление внешних форм (анкет)
    $result = sql_select(QST_TABLE, 'table_id=', $table_id);
    while ($qst = sql_fetch_assoc($result)) {
        sql_delete(QST_TABLE, 'id=', $qst['id']);
        sql_delete(QST_FIELDS_TABLE, 'qst_id=', $qst['id']);
        sql_delete(QST_GROUPS_TABLE, 'qst_id=', $qst['id']);
        sql_delete(QST_FILES_TABLE, 'qst_id=', $qst['id']);
        sql_delete(QST_STAT_TABLE, 'qst_id=', $qst['id']);
        sql_delete(QST_ANSWERS_TABLE, 'qst_id=', $qst['id']);
    }
    // удаление статуса легенды таблицы
    sql_delete(LEGEND_STATUS_TABLE, 'table_id=', $table_id);
    // удаление прав и правил на подтаблицы
    $result = sql_select(SUBTABLES_TABLE, 'table_id=', $table_id, ' or link_table_id=', $table_id);
    while ($subtable = sql_fetch_assoc($result)) {
        sql_delete(ACC_SUBTABLES_TABLE, 'subtable_id=', $subtable['id']);
        sql_delete(ACC_SUBTABLE_RULES_TABLE, 'subtable_id=', $subtable['id']);
    }
    // удаление подтаблиц
    sql_delete(SUBTABLES_TABLE, 'table_id=', $table_id, ' or link_table_id=', $table_id);
    // удаление прав на доптаблицы
    $result = sql_select(ADDIT_TABLES_TABLE, 'table_id=', $table_id, ' or link_table_id=', $table_id);
    while ($addittable = sql_fetch_assoc($result)) {
        sql_delete(ACC_ADDIT_TABLES_TABLE, 'addittable_id=', $addittable['id']);
    }
    // удаление доптаблиц
    sql_delete(ADDIT_TABLES_TABLE, 'table_id=', $table_id, ' or link_table_id=', $table_id);
    // удаление настроек доступа синхронизаций
    sql_delete(ACC_SYNC_TABLE, 'table_id=', $table_id);
    // удаление правил доступа
    sql_delete(ACC_RULES_TABLE, 'table_id=', $table_id);
    // удаление свободных шаблонов
    sql_delete(FREE_FORMS_TABLE, 'table_id=', $table_id);
    // удаление активностей
    sql_delete(ACTIVITY_REL_TABLE, 'table_id=', $table_id);
    sql_delete(ACTIVITY_BUTTONS_TABLE, 'table_id=', $table_id);
    // удаление информации по защите элементов таблицы
    sql_delete(PROTECT_TABLE, 'table_id=', $table_id);
    sql_delete(PROTECT_COMMENTS, 'table_id=', $table_id);
    // удаление собственно таблицы с данными
    sql_query('DROP TABLE ' . DATA_TABLE . $table_id);
    // удаляем таблицу с телефонами
    if (sql_table_exists($config['table_prefix'] . 'module_asterisk_phone_table' . $table_id)) {
        sql_query('DROP TABLE ' . $config['table_prefix'] . 'module_asterisk_phone_table' . $table_id);
    }
    if ($include_files) {
        // удаление связанных с таблицей файлов
        foreach ($table_fields as $one_field) {
            if ($one_field['type_field'] == 6 or $one_field['type_field'] == 9) {
                drop_files_by_field($one_field['id']);
            }
        }
        // удаление насовсем файлов из корзины
        sql_delete(DELETED_FILES, 'table_id=', $table_id);
        // очищаем кэш
        $dh = opendir($config['site_path'] . '/cache');
        while ($filename = readdir($dh)) {
            if (substr($filename, 0, strlen($table_id . '_')) == $table_id . '_') {
                @unlink($config['site_path'] . '/cache/' . $filename);
            }
        }
        closedir($dh);
    }
}

// Удаление поля со всеми элементами и данными
function delete_field($table_id, $field_id)
{
    global $config;

    // удаление информации о поле
    sql_delete(FIELDS_TABLE, 'id=', $field_id);
    // удаление прав пользователей на поле
    sql_delete(ACC_FIELDS_TABLE, 'field_id=', $field_id);
    // удаление наследуемых прав пользователей на поле
    sql_delete(ACC_FIELDS_TABLE . '_par', 'field_id=' . $field_id);
    // удаление из прав для подтаблиц
    sql_delete(ACC_SUBTABLE_RULES_TABLE, 'field_id=' . $field_id);
    // удаление поля из фильтров
    sql_delete(FILTER_FIELDS_TABLE, 'field_id=', $field_id);
    // удаление доп.полей связи
    sql_delete(FIELDS_LINKS_SHOW_TABLE, 'field_id=', $field_id);
    // удаление поля из других полей связи
    sql_delete(FIELDS_LINKS_SHOW_TABLE, 'show_field=', $field_id);
    //удаление списка полей, необходимых для заполнения при добавлении через зеленый плюс, привязанных к этому полю-связи
    sql_delete(LINK_FIELDS_FOR_ADDITION_TABLE, 'field_id=', $field_id);
    //удаление поля из других списков полей, необходимых для заполнения при добавлении через зеленый плюс, привязанных к другим полям связи
    sql_delete(LINK_FIELDS_FOR_ADDITION_TABLE, 'addition_field=', $field_id);
    // удаление из синхронизаций
    $result = sql_select_field(SYNC_FIELDS_TABLE, 'sync_id', 'field_id=', $field_id);
    while ($row = sql_fetch_array($result)) {
        $sync_id = $row['sync_id'];
        // проверяем наличие полей данной таблицы в синхронизации
        $sqlQuery = "SELECT COUNT(*) AS cnt
                      FROM " . SYNC_FIELDS_TABLE . " AS sync,
                      " . FIELDS_TABLE . " AS fields
                      WHERE sync.sync_id='$sync_id'
                      AND sync.field_id=fields.id
                      AND fields.table_id='$table_id'
                      AND fields.id<>'$field_id'";

        $subresult = sql_query($sqlQuery);
        $subrow = sql_fetch_array($subresult);

        $sqlQuery = "SHOW COLUMNS FROM " . DATA_TABLE . $table_id . " LIKE 's" . $sync_id . "'";
        $subresult = sql_query($sqlQuery);
        // Если полей таблицы в синхронизации не обнаружено и служебное поле присутсвует в таблице, модифицируем таблицу
        if (!$subrow['cnt'] AND sql_num_rows($subresult)) {
            $sqlQuery = "ALTER TABLE " . DATA_TABLE . $table_id . " DROP s" . $sync_id;
            sql_query($sqlQuery);
        }
    }
    sql_delete(SYNC_FIELDS_TABLE, 'field_id=', $field_id);
    update_run_flags('sync_fields');
    // удаление из условий вычислений
    sql_delete(CALC_COND_TABLE, '(type=2 or type=3) and param=', $field_id);
    // удаление информации по защите поля
    sql_delete(PROTECT_TABLE, "elem_type = 'field' AND elem_id = ", $field_id);
    sql_delete(PROTECT_COMMENTS, "elem_type = 'field' AND elem_id = ", $field_id);
    // удаление из правил
    $q = sql_select(ACC_RULES_TABLE, "rights LIKE '%", $field_id, "%'");
    while ($d = sql_fetch_assoc($q)) {
        $temp_r = unserialize($d['rights']);
        if (is_array($temp_r)) {
            foreach ($temp_r as $k => $v) {
                if ($v['field'] == $field_id) {
                    unset($temp_r[$k]);
                }
            }
        }
        $temp_r = serialize($temp_r);
        sql_update(ACC_RULES_TABLE, array('rights' => $temp_r), 'id=' . $d['id']);
    }
    // удаление файлов по умолчанию
    $field = sql_fetch_array(sql_select_field(FIELDS_TABLE, 'type_field, default_value', 'id=', $field_id));
    if (($field['type_field'] == 6 || $field['type_field'] == 9) && $field['default_value']) {
        $files = explode("\r\n", $field['default_value']);
        foreach ($files as $file_name) {
            drop_data_file($field_id, 0, $file_name);
        }
    }
    // удаление связанных файлов
    drop_files_by_field($field_id);
    // удаление насовсем файлов из корзины
    sql_delete(DELETED_FILES, 'field_id=', $field_id);
    // Очищаем кэш
    $dh = opendir($config['site_path'] . '/cache');
    while ($filename = readdir($dh)) {
        if (substr($filename, 0, strlen($table_id . '_' . $field_id . '_')) == $table_id . '_' . $field_id . '_') {
            @unlink($config['site_path'] . '/cache/' . $filename);
        }
    }
    // собственно удаление поля
    sql_query('ALTER TABLE ' . DATA_TABLE . $table_id . ' DROP f' . $field_id);
    // удаление поля из временной таблицы
    $search_table = sql_fetch_assoc(sql_query('SELECT TABLE_NAME FROM information_schema.tables WHERE TABLE_SCHEMA = "' . $config['dbname'] . '" AND TABLE_NAME = "' . DATA_TABLE . $table_id . '_today"'));
    if ($search_table) {
        sql_query('ALTER TABLE ' . DATA_TABLE . $table_id . '_today DROP f' . $field_id);
    }
    closedir($dh);
}

// Экспорт таблицы (структуры) со всеми элементами
function export_table($table_id, $exp_tables = array(), $with_integrations = false)
{
    global $config, $user;

    // экспорт таблицы
    $export_data['table'] = sql_select_array(TABLES_TABLE, "id=", $table_id);
    // экспорт прав доступа на таблицу
    $result = sql_select(ACC_TABLES_TABLE, "table_id=", $table_id);
    while ($row = sql_fetch_assoc($result)) {
        $export_data['acc_tables'][] = $row;
    }
    // экспорт полей
    $result = sql_select(FIELDS_TABLE, "table_id=", $table_id, " ORDER BY field_num");
    while ($row = sql_fetch_assoc($result)) {
        $export_data['fields'][] = $row;
        // экспорт прав доступа на поле
        $result2 = sql_select(ACC_FIELDS_TABLE, "field_id=", $row['id']);
        while ($row2 = sql_fetch_assoc($result2)) {
            $export_data['acc_fields'][] = $row2;
        }
        // экспорт доп.полей связи для просмотра
        $result2 = sql_select(FIELDS_LINKS_SHOW_TABLE, "field_id=", $row['id']);
        while ($row2 = sql_fetch_assoc($result2)) {
            $export_data['fields_links_show'][] = $row2;
        }
        // экспорт доп.полей связи для добавления
        $result2 = sql_select(LINK_FIELDS_FOR_ADDITION_TABLE, "field_id=", $row['id']);
        while ($row2 = sql_fetch_assoc($result2)) {
            $export_data['link_fields_for_addition'][] = $row2;
        }
    }
    // экспорт групп полей
    $result = sql_select(FIELD_GROUPS, "table_id=", $table_id);
    while ($row = sql_fetch_assoc($result)) {
        $export_data['fgroups'][] = $row;
    }
    // экспорт правил
    $result = sql_select(ACC_RULES_TABLE, "table_id=", $table_id, $group_id?(" and (group_id=".$group_id." or global=1)"):"");
    while ($row = sql_fetch_assoc($result)) {
        $export_data['acc_rules'][] = $row;
    }
    // экспорт групп доп. действий
    $result = sql_select(BUTTON_GROUPS, 'table_id=', $table_id);
    while ($row = sql_fetch_assoc($result)) {
        $export_data['bgroups'][] = $row;
    }
    // экспорт доп. действий
    $result = sql_select(BUTTONS_TABLE, "table_id=", $table_id);
    while ($row = sql_fetch_assoc($result)) {
        $export_data['buttons'][] = $row;
        // экспорт параметров доп. действий
        $result2 = sql_select(BUTTONS_PARAMETERS_TABLE, "button_id=", $row['id']);
        while ($row2 = sql_fetch_assoc($result2)) {
            $export_data['buttons_parameters'][] = $row2;
        }
        // экспорт прав доступа доп. действий
        $result2 = sql_select(ACC_BUTTONS_TABLE, "button_id=", $row['id']);
        while ($row2 = sql_fetch_assoc($result2)) {
            $export_data['acc_buttons'][] = $row2;
        }
    }
    // экспорт внешних форм
    $result = sql_select(QST_TABLE, "table_id=", $table_id);
    while ($row = sql_fetch_assoc($result)) {
        $export_data['questionare'][] = $row;
        // экспорт полей внешних форм
        $result2 = sql_select(QST_FIELDS_TABLE, "qst_id=", $row['id']);
        while ($row2 = sql_fetch_assoc($result2)) {
            $export_data['questionare_fields'][] = $row2;
        }
        // экспорт групп полей внешних форм
        $result2 = sql_select(QST_GROUPS_TABLE, "qst_id=", $row['id']);
        while ($row2 = sql_fetch_assoc($result2)) {
            $export_data['questionare_groups'][] = $row2;
        }
        // экспорт полей меток внешних форм
        $result2 = sql_select(QST_TAG_TABLE, "qst_id=", $row['id']);
        while ($row2 = sql_fetch_assoc($result2)) {
            $export_data['questionare_tag'][] = $row2;
        }
    }
    // экспорт вычислений
    $result = sql_select(CALC_TABLE, "table_id=", $table_id);
    while ($row = sql_fetch_assoc($result)) {
        $export_data['calc'][] = $row;
        // экспорт условий вычисления
        $result2 = sql_select(CALC_COND_TABLE, "calc_id=", $row['id']);
        while ($row2 = sql_fetch_assoc($result2)) {
            $export_data['calc_cond'][] = $row2;
        }
    }
    // экспорт фильтров
    $result = sql_select(FILTERS_TABLE, "table_id=", $table_id);
    while ($row = sql_fetch_assoc($result)) {
        $export_data['filters'][] = $row;
        // экспорт прав доступа на фильтр
        $result2 = sql_select(ACC_FILTERS_TABLE, "filter_id=", $row['id']);
        while ($row2 = sql_fetch_assoc($result2)) {
            $export_data['acc_filters'][] = $row2;
        }
        // экспорт полей фильтра
        $result2 = sql_select(FILTER_FIELDS_TABLE, "filter_id=", $row['id']);
        while ($row2 = sql_fetch_assoc($result2)) {
            $export_data['filter_fields'][] = $row2;
        }
    }
    // экспорт напоминаний
    $result = sql_select(TIPS_TABLE, "table_id=", $table_id);
    while ($row = sql_fetch_assoc($result)) {
        $export_data['tips'][] = $row;
        // экспорт прав доступа на напоминание
        $result2 = sql_select(ACC_TIPS_TABLE, "tip_id=", $row['id']);
        while ($row2 = sql_fetch_assoc($result2)) {
            $export_data['acc_tips'][] = $row2;
        }
    }
    // экспорт форматирований
    $result = sql_select(FORMAT_TABLE, "table_id=", $table_id);
    while ($row = sql_fetch_assoc($result)) {
        $export_data['format'][] = $row;
    }
    // экспорт информеров
    $result = sql_select(INFORMERS_TABLE, "table_id=", $table_id);
    while ($row = sql_fetch_assoc($result)) {
        $export_data['informers'][] = $row;
    }
    // экспорт шаблонов
    $result = sql_select(FORMS_TABLE, "table_id=", $table_id);
    while ($row = sql_fetch_assoc($result)) {
        if ($row['type_form'] > 2) {
            $row['body_form'] = base64_encode($row['body_form']);
        }
        $export_data['forms'][] = $row;
        // экспорт прав доступа на шаблон
        $result2 = sql_select(ACC_FORMS_TABLE, "form_id=", $row['id']);
        while ($row2 = sql_fetch_assoc($result2)) {
            $export_data['acc_forms'][] = $row2;
        }
    }
    // экспорт переменных шаблонов
    $result = sql_select(FORMS_VARS_TABLE, "table_id=", $table_id);
    while ($row = sql_fetch_assoc($result)) {
        $export_data['forms_vars'][] = $row;
    }
    // экспорт вложенных файлов для шаблонов рассылки
    $result = sql_select(MAIL_FILES_LINKS_TABLE, "table_id=", $table_id);
    while ($row = sql_fetch_assoc($result)) {
        $export_data['mail_files_links'][] = $row;
    }
    // экспорт подтаблиц
    $result = sql_select(SUBTABLES_TABLE, "table_id=", $table_id);
    while ($row = sql_fetch_assoc($result)) {
        if ($exp_tables[$row['link_table_id']]) {
            $export_data['subtables'][] = $row;
            // экспорт прав доступа на подтаблицу
            $result2 = sql_select(ACC_SUBTABLES_TABLE, "subtable_id=", $row['id']);
            while ($row2 = sql_fetch_assoc($result2)) {
                $export_data['acc_subtables'][] = $row2;
            }
            // экспорт правил доступа на подтаблицу
            $result2 = sql_select(ACC_SUBTABLE_RULES_TABLE, "subtable_id=", $row['id']);
            while ($row2 = sql_fetch_assoc($result2)) {
                $export_data['acc_subtable_rules'][] = $row2;
            }
        } elseif ($row['autostatus_calc_id']) {
            // подтаблица не экспортируется, убираем системные вычисления
            foreach ($export_data['calc'] as $k => $one_calc) {
                if ($one_calc['id'] == $row['autostatus_calc_id']) {
                    unset($export_data['calc'][$k]);
                }
            }
            foreach ($export_data['calc_cond'] as $k => $one_cond) {
                if ($one_cond['calc_id'] == $row['autostatus_calc_id']) {
                    unset($export_data['calc_cond'][$k]);
                }
            }
        }
    }
    // экспорт доптаблиц
    $result = sql_select(ADDIT_TABLES_TABLE, "table_id=", $table_id);
    while ($row = sql_fetch_assoc($result)) {
        if ($exp_tables[$row['link_table_id']]) {
            $export_data['addittables'][] = $row;
            // экспорт прав доступа на доптаблицу
            $result2 = sql_select(ACC_ADDIT_TABLES_TABLE, "addittable_id=", $row['id']);
            while ($row2 = sql_fetch_assoc($result2)) {
                $export_data['acc_addittables'][] = $row2;
            }
        }
    }
    // экспорт защиты
    if ($config['protect_of_elements'] && $user['id'] == 1) {
        $result = sql_select(PROTECT_TABLE, "elem_type = 'table' AND elem_id = ", $table_id);
        while ($row = sql_fetch_assoc($result)) {
            $export_data['protect'][] = $row;
        }
        $result = sql_select(PROTECT_COMMENTS, "elem_type = 'table' AND elem_id = ", $table_id);
        while ($row = sql_fetch_assoc($result)) {
            $export_data['protect_comments'][] = $row;
        }
    }
    // экспорт интеграций
    if ($with_integrations) {
        $export_data['integrations'] = CB\Assist\Integration\Service::getInstance()->exportIntegrations($table_id);
    }

    return $export_data;
}

// Импорт таблицы (структуры) со всеми элементами
function import_table($import_data, $new_groups = array(), $old_table_id = 0, $old_fields = array(), $old_max_id = array())
{
    global $config, $user;

    // импорт таблицы
    $table = $import_data['table'];
    $table_id = $table['id'];
    $table['id'] = "";
    $table['owner_id'] = $user['group_id'];
    $new_table_id = sql_insert(TABLES_TABLE, $table);
    if ($old_table_id) {
        sql_update(TABLES_TABLE, array('id' => $old_table_id), 'id = ', $new_table_id);
        $new_table_id = $old_table_id;
    } elseif ($new_table_id <= $old_max_id['table']) {
        sql_update(TABLES_TABLE, array('id' => $old_max_id['table'] + 10), 'id = ', $new_table_id);
        $new_table_id = $old_max_id['table'] + 10;
    }
    // импорт полей
    foreach ($import_data['fields'] as $row) {
        $field_id = $row['id'];
        $row['id'] = "";
        $row['table_id'] = $new_table_id;
        $row['owner_id'] = $user['group_id'];
        if ($row['type_field'] == 7) {
            $groups = [];
            $old_groups = explode('|', $row['type_value']);
            foreach ($old_groups as $old_group_id) {
                if ($new_groups[$old_group_id]) {
                    foreach ($new_groups[$old_group_id] as $new_group_id) {
                        $groups[] = $new_group_id;
                    }
                } else {
                    $groups[] = $old_group_id;
                }
            }
            $row['type_value'] = implode('|', $groups);
        }
        if ($row['type_field'] == 14) {
            $groups = [];
            $type_value = explode('|', $row['type_value']);
            $old_groups = explode(',', $type_value[2]);
            foreach ($old_groups as $old_group_id) {
                if ($new_groups[$old_group_id]) {
                    foreach ($new_groups[$old_group_id] as $new_group_id) {
                        $groups[] = $new_group_id;
                    }
                } else {
                    $groups[] = $old_group_id;
                }
            }
            $type_value[2] = implode(',', $groups);
            $row['type_value'] = implode('|', $type_value);
        }
        $new_field_id = sql_insert(FIELDS_TABLE, $row);
        $old_field_id = $old_fields[$field_id];
        if ($old_field_id) {
            sql_update(FIELDS_TABLE, array('id' => $old_field_id), 'id = ', $new_field_id);
            $new_field_id = $old_field_id;
        } elseif ($new_field_id <= $old_max_id['field']) {
            sql_update(FIELDS_TABLE, array('id' => $old_max_id['field'] + 10), 'id = ', $new_field_id);
            $new_field_id = $old_max_id['field'] + 10;
        }
        $new_fields[$field_id] = $new_field_id;
        $search_arr1[]  = "/\bf" . $field_id . "\b/";
        $search_arr2[]  = "/\b" . $field_id . "\b/";
        $search_arr3[]  = "/\bfield" . $field_id . "\b/";
        $search_arr4[]  = "/\bf" . $field_id . "_changed\b/";
        $replace_arr1[] = "f{#new#}" . $new_field_id; // {#new#} - костыль для предотвращения повторной замены
        $replace_arr2[] = "{#new#}s" . $new_field_id;
        $replace_arr3[] = "field{#new#}" . $new_field_id;
        $replace_arr4[] = "f{#new#}" . $new_field_id . "_changed";
    }
    // импорт прав доступа на таблицу
    foreach ($import_data['acc_tables'] as $row) {
        $row['id'] = "";
        $row['table_id'] = $new_table_id;
        $row['rule_filter'] = str_replace('{#new#}', '', preg_replace($search_arr1, $replace_arr1, $row['rule_filter']));
        $rel_groups = $new_groups[$row['group_id']] ? : ($new_groups ? array() : array($row['group_id']));
        foreach ($rel_groups as $new_group_id) {
            $row['group_id'] = $new_group_id;
            sql_insert(ACC_TABLES_TABLE, $row);
        }
    }
    // импорт прав доступа на поля
    foreach ($import_data['acc_fields'] as $row) {
        $row['id'] = "";
        $row['table_id'] = $new_table_id;
        $row['field_id'] = $new_fields[$row['field_id']];
        if (!isset($row['view_sub'])) {
            $row['view_sub'] = $row['view_tb'];
        }
        $rel_groups = $new_groups[$row['group_id']] ? : ($new_groups ? array() : array($row['group_id']));
        foreach ($rel_groups as $new_group_id) {
            $row['group_id'] = $new_group_id;
            sql_insert(ACC_FIELDS_TABLE, $row);
        }
    }
    // добавляем права субадмина, если импортирует субадмин
    if ($user['sub_admin'] == 1) {
        $row = sql_select_array(ACC_SUBADMIN_TABLE, "group_id=",$user['group_id']);
        $subadmin_acc = unserialize($row['acc']);
        $subadmin_acc['tables'][$new_table_id] = 2;
        $subadmin_acc = serialize($subadmin_acc);
        sql_update(ACC_SUBADMIN_TABLE, array('acc' => $subadmin_acc), "group_id=",$user['group_id']);
    }
    // импорт доп.полей связи для просмотра
    foreach ($import_data['fields_links_show'] as $row) {
        $row['id'] = "";
        $row['field_id'] = $new_fields[$row['field_id']];
        sql_insert(FIELDS_LINKS_SHOW_TABLE, $row);
    }
    // импорт доп.полей связи для добавления
    foreach ($import_data['link_fields_for_addition'] as $row) {
        $row['id'] = "";
        $row['field_id'] = $new_fields[$row['field_id']];
        sql_insert(LINK_FIELDS_FOR_ADDITION_TABLE, $row);
    }
    // импорт групп полей
    foreach ($import_data['fgroups'] as $row) {
        $fgroup_id = $row['id'];
        $row['id'] = "";
        $row['table_id'] = $new_table_id;
        $new_fgroup_id = sql_insert(FIELD_GROUPS, $row);
        $new_fgroups[$fgroup_id] = $new_fgroup_id;
    }
    // импорт групп доп. действий
    foreach ($import_data['bgroups'] as $row) {
        $bgroup_id = $row['id'];
        $row['id'] = '';
        $row['table_id'] = $new_table_id;
        $new_bgroup_id = sql_insert(BUTTON_GROUPS, $row);
        $new_bgroups[$bgroup_id] = $new_bgroup_id;
    }
    // импорт доп. действий
    foreach ($import_data['buttons'] as $row) {
        $button_id = $row['id'];
        $row['id'] = '';
        $row['table_id'] = $new_table_id;
        $row['group_id'] = $new_bgroups[$row['group_id']];
        $new_button_id = sql_insert(BUTTONS_TABLE, $row);
        $new_buttons[$button_id] = $new_button_id;
    }
    // импорт параметров доп. действий
    foreach ($import_data['buttons_parameters'] as $row) {
        $row['id'] = '';
        $row['button_id'] = $new_buttons[$row['button_id']];
        $params = json_decode($row['params'], 1);
        $params['field'] = $new_fields[$params['field']];
        if ($params['default_value']['is_field']) {
            $params['default_value']['value'] = (string)$new_fields[$params['default_value']['value']];
        }
        $row['params'] = json_encode_visual($params);
        sql_insert(BUTTONS_PARAMETERS_TABLE, $row);
    }
    // импорт прав доступа доп. действий
    foreach ($import_data['acc_buttons'] as $row) {
        $row['id'] = "";
        $row['button_id'] = $new_buttons[$row['button_id']];
        $rel_groups = $new_groups[$row['group_id']] ? : ($new_groups ? array() : array($row['group_id']));
        foreach ($rel_groups as $new_group_id) {
            $row['group_id'] = $new_group_id;
            sql_insert(ACC_BUTTONS_TABLE, $row);
        }
    }
    // импорт внешних форм
    foreach ($import_data['questionare'] as $row) {
        $qst_id = $row['id'];
        $row['id'] = "";
        $row['table_id'] = $new_table_id;
        $row['owner_id'] = $user['group_id'];
        $row['res_text'] = str_replace('{#new#}', '', preg_replace($search_arr3, $replace_arr3, $row['res_text']));
        $new_qst_id = sql_insert(QST_TABLE, $row);
        $new_qst[$qst_id] = $new_qst_id;
        $search_qst[]  = "_QstLink[" . $qst_id . "]";
        $replace_qst[] = "_QstLink{#new#}[" . $new_qst_id . "]";
    }
    // импорт полей внешних форм
    foreach ($import_data['questionare_fields'] as $row) {
        $row['qst_id'] = $new_qst[$row['qst_id']];
        $row['field_id'] = $new_fields[$row['field_id']];
        sql_insert(QST_FIELDS_TABLE, $row);
    }
    // импорт групп полей внешних форм
    foreach ($import_data['questionare_groups'] as $row) {
        $row['qst_id'] = $new_qst[$row['qst_id']];
        $row['group_id'] = $new_fgroups[$row['group_id']];
        sql_insert(QST_GROUPS_TABLE, $row);
    }
    // импорт полей меток внешних форм
    foreach ($import_data['questionare_tag'] as $row) {
        $row['id'] = "";
        $row['qst_id'] = $new_qst[$row['qst_id']];
        $row['utm_source'] = $new_fields[$row['utm_source']];
        $row['utm_medium'] = $new_fields[$row['utm_medium']];
        $row['utm_campaign'] = $new_fields[$row['utm_campaign']];
        $row['utm_content'] = $new_fields[$row['utm_content']];
        $row['utm_term'] = $new_fields[$row['utm_term']];
        sql_insert(QST_TAG_TABLE, $row);
    }
    // импорт вычислений
    foreach ($import_data['calc'] as $row) {
        $calc_id = $row['id'];
        $row['id'] = "";
        $row['table_id'] = $new_table_id;
        $new_calc_id = sql_insert(CALC_TABLE, $row);
        $new_calcs[$calc_id] = $new_calc_id;
    }
    // импорт условий вычислений
    foreach ($import_data['calc_cond'] as $row) {
        $row['calc_id'] = $new_calcs[$row['calc_id']];
        if ($row['type'] == 1 or $row['type'] == 4 or $row['type'] == 5)
            $row['param'] = $new_table_id;
        elseif ($row['type'] == 18) // внешние анкеты
            $row['param'] = $new_qst[$row['param']];
        elseif ($row['type'] == 24) // доп.действия
            $row['param'] = $new_buttons[$row['param']];
        elseif ($row['param'] > 0)
            $row['param'] = $new_fields[$row['param']];
        sql_insert(CALC_COND_TABLE, $row);
        if ($row['type'] == 18 or $row['type'] == 24)
            sql_update(CALC_TABLE, array('disabled' => '0'), "id=", $row['calc_id']);
        if ($row['type'] == 24)
            sql_update(CALC_TABLE, array('name' => 'Button ' . $row['param']), "id=", $row['calc_id']);
    }
    // импорт фильтров
    foreach ($import_data['filters'] as $row) {
        $filter_id = $row['id'];
        $row['id'] = "";
        $row['table_id'] = $new_table_id;
        $filters_pid[$filter_id] = $row['pid'];
        $row['def_sort'] = str_replace('{#new#}', '', preg_replace($search_arr1, $replace_arr1, $row['def_sort']));
        $row['group_field'] = $new_fields[$row['group_field']];
        $row['exclude_dup'] = $new_fields[$row['exclude_dup']];
        $row['owner_id'] = $user['group_id'];
        $new_filter_id = sql_insert(FILTERS_TABLE, $row);
        $new_filters[$filter_id] = $new_filter_id;
    }
    // обновление ссылок на родительские фильтры
    foreach ($new_filters as $old_filter_id => $new_filter_id) {
        if ($filters_pid[$old_filter_id]) {
            $new_pid = $new_filters[$filters_pid[$old_filter_id]];
            sql_update(FILTERS_TABLE, array('pid' => $new_pid), "id=", $new_filter_id);
        }
    }
    // импорт прав доступа на фильтры
    foreach ($import_data['acc_filters'] as $row) {
        $row['id'] = "";
        $row['table_id'] = $new_table_id;
        $row['filter_id'] = $new_filters[$row['filter_id']];
        $rel_groups = $new_groups[$row['group_id']] ? : ($new_groups ? array() : array($row['group_id']));
        foreach ($rel_groups as $new_group_id) {
            $row['group_id'] = $new_group_id;
            sql_insert(ACC_FILTERS_TABLE, $row);
        }
    }
    // импорт полей фильтров
    foreach ($import_data['filter_fields'] as $row) {
        $row['filter_id'] = $new_filters[$row['filter_id']];
        $row['field_id'] = $new_fields[$row['field_id']];
        sql_insert(FILTER_FIELDS_TABLE, $row);
    }
    // импорт напоминаний
    foreach ($import_data['tips'] as $row) {
        $tip_id = $row['id'];
        $row['id'] = "";
        $row['table_id'] = $new_table_id;
        $row['cond_value'] = str_replace('{#new#}', '', preg_replace($search_arr1, $replace_arr1, $row['cond_value']));
        $row['cond_value'] = str_replace('{#new#}', '', preg_replace($search_arr4, $replace_arr4, $row['cond_value']));
        $row['message'] = str_replace('{#new#}', '', preg_replace($search_arr1, $replace_arr1, $row['message']));
        $row['email_subject'] = str_replace('{#new#}', '', preg_replace($search_arr1, $replace_arr1, $row['email_subject']));
        $cond_set = unserialize($row['cond_set']);
        if (is_array($cond_set)) {
            foreach ($cond_set as $k => $cond) {
                if ($cond['field'] != -1) $cond_set[$k]['field'] = $new_fields[$cond['field']];
            }
            $row['cond_set'] = serialize($cond_set);
        }
        $row['owner_id'] = $user['group_id'];
        $new_tip_id = sql_insert(TIPS_TABLE, $row);
        $new_tips[$tip_id] = $new_tip_id;
    }
    // импорт прав доступа на напоминания
    foreach ($import_data['acc_tips'] as $row) {
        $row['id'] = "";
        $row['table_id'] = $new_table_id;
        $row['tip_id'] = $new_tips[$row['tip_id']];
        $rel_groups = $new_groups[$row['group_id']] ? : ($new_groups ? array() : array($row['group_id']));
        foreach ($rel_groups as $new_group_id) {
            $row['group_id'] = $new_group_id;
            sql_insert(ACC_TIPS_TABLE, $row);
        }
    }
    // импорт форматирований
    foreach ($import_data['format'] as $row) {
        $row['id'] = "";
        $row['table_id'] = $new_table_id;
        $row['cond_value'] = str_replace('{#new#}s', '', preg_replace($search_arr2, $replace_arr2, $row['cond_value']));
        $row['used_fields'] = str_replace('{#new#}s', '', preg_replace($search_arr2, $replace_arr2, $row['used_fields']));
        $cond_set = unserialize($row['cond_set']);
        if (is_array($cond_set)) {
            foreach ($cond_set as $k => $cond) {
                $cond_set[$k]['field'] = $new_fields[$cond['field']];
            }
            $row['cond_set'] = serialize($cond_set);
        }
        $row['target'] = $new_fields[$row['target']];
        $row['owner_id'] = $user['group_id'];
        sql_insert(FORMAT_TABLE, $row);
    }
    // импорт информеров
    foreach ($import_data['informers'] as $row) {
        $tip_id = $row['id'];
        $row['id'] = "";
        $row['table_id'] = $new_table_id;
        $row['cond_value'] = str_replace('{#new#}', '', preg_replace($search_arr1, $replace_arr1, $row['cond_value']));
        $row['cond_value'] = str_replace('{#new#}', '', preg_replace($search_arr4, $replace_arr4, $row['cond_value']));
        $row['text'] = str_replace('{#new#}', '', preg_replace($search_arr1, $replace_arr1, $row['text']));
        $cond_set = unserialize($row['cond_set']);
        if (is_array($cond_set)) {
            foreach ($cond_set as $k => $cond) {
                if ($cond['field'] != -1) $cond_set[$k]['field'] = $new_fields[$cond['field']];
            }
            $row['cond_set'] = serialize($cond_set);
        }
        $row['owner_id'] = $user['group_id'];
        sql_insert(INFORMERS_TABLE, $row);
    }
    // импорт шаблонов
    $parts = array("subj_mail", "head_form", "body_form", "foot_form", "doc_name");
    foreach ($import_data['forms'] as $row) {
        $form_id = $row['id'];
        $row['id'] = "";
        $row['table_id'] = $new_table_id;
        $row['log_mail'] = $new_fields[$row['log_mail']];
        $row['att_fields'] = str_replace('{#new#}s', '', preg_replace($search_arr2, $replace_arr2, $row['att_fields']));
        if ($row['type_form'] > 2) {
            $row['body_form'] = base64_decode($row['body_form']);
        } else {
            $row['body_form'] = str_replace('{#new#}', '', str_replace($search_qst, $replace_qst, $row['body_form']));
        }
        $row['cron_id'] = "0";
        $row['filter_id'] = "0";
        $row['owner_id'] = $user['group_id'];
        $new_form_id = sql_insert(FORMS_TABLE, $row);
        $new_forms[$form_id] = $new_form_id;
        $search_form_id[]  = "/\b" . $form_id . "\b/";
        $replace_form_id[] = "{#new#}s" . $new_form_id;
    }
    // обновление ссылок на вложенные шаблоны
    foreach ($import_data['forms'] as $row) {
        $att_forms = str_replace('{#new#}s', '', preg_replace($search_form_id, $replace_form_id, $row['att_forms']));
        sql_update(FORMS_TABLE, array("att_forms" => $att_forms), "id=", $new_forms[$row['form_id']]);
    }
    // импорт прав доступа на шаблоны
    foreach ($import_data['acc_forms'] as $row) {
        $row['id'] = "";
        $row['table_id'] = $new_table_id;
        $row['form_id'] = $new_forms[$row['form_id']];
        $rel_groups = $new_groups[$row['group_id']] ? : ($new_groups ? array() : array($row['group_id']));
        foreach ($rel_groups as $new_group_id) {
            $row['group_id'] = $new_group_id;
            sql_insert(ACC_FORMS_TABLE, $row);
        }
    }
    // импорт переменных шаблонов
    foreach ($import_data['forms_vars'] as $row) {
        $row['id'] = "";
        $row['table_id'] = $new_table_id;
        sql_insert(FORMS_VARS_TABLE, $row);
    }
    // импорт вложенных файлов для шаблонов рассылки
    foreach ($import_data['mail_files_links'] as $row) {
        $row['id'] = "";
        $row['table_id'] = $new_table_id;
        $row['form_id'] = $new_forms[$row['form_id']];
        sql_insert(MAIL_FILES_LINKS_TABLE, $row);
    }
    // импорт подтаблиц
    foreach ($import_data['subtables'] as $row) {
        $subtable_id = $row['id'];
        $row['id'] = "";
        $row['table_id'] = $new_table_id;
        $new_subtable_id = sql_insert(SUBTABLES_TABLE, $row);
        $new_subtables[$subtable_id] = $new_subtable_id;
    }
    // импорт прав доступа на подтаблицы
    foreach ($import_data['acc_subtables'] as $row) {
        $row['id'] = "";
        $row['table_id'] = $new_table_id;
        $row['subtable_id'] = $new_subtables[$row['subtable_id']];
        $rel_groups = $new_groups[$row['group_id']] ? : ($new_groups ? array() : array($row['group_id']));
        foreach ($rel_groups as $new_group_id) {
            $row['group_id'] = $new_group_id;
            sql_insert(ACC_SUBTABLES_TABLE, $row);
        }
    }
    // импорт правил доступа на подтаблицы
    foreach ($import_data['acc_subtable_rules'] as $row) {
        $row['id'] = "";
        $row['subtable_id'] = $new_subtables[$row['subtable_id']];
        $rel_groups = $new_groups[$row['group_id']] ? : ($new_groups ? array() : array($row['group_id']));
        foreach ($rel_groups as $new_group_id) {
            $row['group_id'] = $new_group_id;
            sql_insert(ACC_SUBTABLE_RULES_TABLE, $row);
        }
    }
    // импорт доптаблиц
    foreach ($import_data['adittables'] as $row) {
        $adittable_id = $row['id'];
        $row['id'] = "";
        $row['table_id'] = $new_table_id;
        $new_adittable_id = sql_insert(ADDIT_TABLES_TABLE, $row);
        $new_adittables[$adittable_id] = $new_adittable_id;
    }
    // импорт прав доступа на доптаблицы
    foreach ($import_data['acc_adittables'] as $row) {
        $row['id'] = "";
        $row['table_id'] = $new_table_id;
        $row['adittable_id'] = $new_adittables[$row['adittable_id']];
        $rel_groups = $new_groups[$row['group_id']] ? : ($new_groups ? array() : array($row['group_id']));
        foreach ($rel_groups as $new_group_id) {
            $row['group_id'] = $new_group_id;
            sql_insert(ACC_ADDIT_TABLES_TABLE, $row);
        }
    }
    // импорт правил
    foreach ($import_data['acc_rules'] as $row) {
        $row['id'] = "";
        $row['table_id'] = $new_table_id;
        $row['condition_php'] = str_replace('{#new#}', '', preg_replace($search_arr1, $replace_arr1, $row['condition_php']));
        $cond_set = unserialize($row['condition_set']);
        if (is_array($cond_set)) {
            foreach ($cond_set as $k => $cond) {
                $cond_set[$k]['field'] = $new_fields[$cond['field']];
            }
            $row['condition_set'] = serialize($cond_set);
        }
        $rights = unserialize($row['rights']);
        if (is_array($rights)) {
            foreach ($rights as $k => $one_right) {
                if ($one_right['table']) {
                    $rights[$k]['table'] = $new_table_id;
                }
                if ($one_right['field']) {
                    $rights[$k]['field'] = $new_fields[$one_right['field']];
                }
                if ($one_right['tip']) {
                    $rights[$k]['tip'] = $new_tips[$one_right['tip']];
                }
                if ($one_right['template']) {
                    $rights[$k]['template'] = $new_forms[$one_right['template']];
                }
                if ($one_right['button']) {
                    $rights[$k]['button'] = $new_buttons[$one_right['button']];
                }
            }
            $row['rights'] = serialize($rights);
        }
        if ($row['global'] == 1) {
            $row['group_id'] = 1;
            sql_insert(ACC_RULES_TABLE, $row);
        } else {
            $rel_groups = $new_groups[$row['group_id']] ? : ($new_groups ? array() : array($row['group_id']));
            foreach ($rel_groups as $new_group_id) {
                $row['group_id'] = $new_group_id;
                sql_insert(ACC_RULES_TABLE, $row);
            }
        }
    }
    // импорт защиты
    if ($config['protect_of_elements'] && $user['id'] == 1) {
        foreach ($import_data['protect'] as $row) {
            $row['table_id'] = $new_table_id;
            $row['elem_id'] = $new_table_id;
            sql_insert(PROTECT_TABLE, $row);
        }
        foreach ($import_data['protect_comments'] as $row) {
            $row['table_id'] = $new_table_id;
            $row['elem_id'] = $new_table_id;
            sql_insert(PROTECT_COMMENTS, $row);
        }
    }
    // импорт интеграций
    if ($import_data['integrations']) {
        // заменяем id элементов дополнения в интеграциях
        foreach ($import_data['integrations']['object_mappings'] as $k => $arr1) {
            $import_data['integrations']['object_mappings'][$k]['data']['internal_object_id'] = $new_table_id;
            foreach ($arr1['fields'] as $n => $arr2) {
                $field_arr = explode('.', $arr2['internal_field_id']);
                foreach ($field_arr as $i => $field_id) {
                    if ($new_fields[$field_id]) {
                        $field_arr[$i] = $new_fields[$field_id];
                    }
                }
                $import_data['integrations']['object_mappings'][$k]['fields'][$n]['internal_field_id'] = implode('.', $field_arr);
            }
            foreach ($arr1['data']['internal_connect_fields'] as $n => $field_id) {
                if ($new_fields[$field_id]) {
                    $import_data['integrations']['object_mappings'][$k]['data']['internal_connect_fields'][$n] = $new_fields[$field_id];
                }
            }
            foreach ($arr1['data']['internal_service_fields'] as $n => $field_id) {
                if ($new_fields[$field_id]) {
                    $import_data['integrations']['object_mappings'][$k]['data']['internal_service_fields'][$n] = $new_fields[$field_id];
                }
            }
        }
        foreach ($import_data['integrations']['connectors'] as $k => $arr1) {
            foreach ($arr1['fields'] as $n => $arr2) {
                $field_arr = explode('.', $arr2['internal_field_id']);
                foreach ($field_arr as $i => $field_id) {
                    if ($new_fields[$field_id]) {
                        $field_arr[$i] = $new_fields[$field_id];
                    }
                }
                $import_data['integrations']['connectors'][$k]['fields'][$n]['internal_field_id'] = implode('.', $field_arr);
                $import_data['integrations']['connectors'][$k]['fields'][$n]['internal_template'] = str_replace('{#new#}', '', preg_replace($search_arr1, $replace_arr1, $arr2['internal_template']));
            }
            $new_calc_id = (int)$new_calcs[$arr1['data']['calc_id']];
            $import_data['integrations']['connectors'][$k]['data']['calc_id'] = $new_calc_id;
            $integrations_calcs[$arr1['data']['id']] = $new_calc_id;
        }
        // импортируем интеграции
        $result = CB\Assist\Integration\Service::getInstance()->importIntegrations($import_data['integrations']);
        // заменяем id интеграций в вычислениях дополнения
        foreach ($integrations_calcs as $connector_id => $calc_id) {
            $calc = sql_fetch_assoc(sql_select_field(CALC_TABLE, 'calculate, construct_params', 'id = ', $calc_id));
            sql_update(CALC_TABLE, [
                'calculate' => str_replace(
                    '\\CB\\Assist\\Integration\\Service::getInstance()->run(' . $connector_id . ', $line);',
                    '\\CB\\Assist\\Integration\\Service::getInstance()->run(' . $result['connectors'][$connector_id] . ', $line);',
                    $calc['calculate']
                ),
                'construct_params' => str_replace(
                    ['{"integration_id":' . $connector_id . '}', '{"integration_id":"' . $connector_id . '"}'],
                    '{"integration_id":' . $result['connectors'][$connector_id] . '}',
                    $calc['construct_params']
                ),
            ], 'id = ', $calc_id);
        }
    }

    // обновление ссылок на поля и вычисления в таблице
    $user_table_fields = array();
    $table['user_table_fields'] = unserialize($table['user_table_link']);
    foreach ($table['user_table_fields'] as $ulf_name => $ulf_id) {
        if ($ulf_name == "calcs") {
            foreach ($table['user_table_fields']['calcs'] as $calc_type => $calc_id) {
                $user_table_fields['calcs'][$calc_type] = $new_calcs[$calc_id];
            }
        }
        elseif ($ulf_name != "invite" and $ulf_name != "change_mail")
            $user_table_fields[$ulf_name] = $new_fields[$ulf_id];
        else
            $user_table_fields[$ulf_name] = $ulf_id;
    }
    $table['def_sort'] = str_replace('{#new#}', '', preg_replace($search_arr1, $replace_arr1, $table['def_sort']));
    $new_data = array(
        "def_sort" => $table['def_sort'],
        "group_field" => $new_fields[$table['group_field']],
        "user_table_link" => $user_table_fields ? serialize($user_table_fields) : ""
    );
    sql_update(TABLES_TABLE, $new_data, "id=", $new_table_id);
    // обновление ссылок на поля в фильтрах полей связи
    $result = sql_select(FIELDS_TABLE, "table_id=", $new_table_id, " AND type_field=5 AND type_value LIKE '%|-%'");
    while ($row = sql_fetch_assoc($result)) {
        $row['type_value'] = str_replace('{#new#}s', '', preg_replace($search_arr2, $replace_arr2, $row['type_value']));
        sql_update(FIELDS_TABLE, array('type_value' => $row['type_value']), "id=", $row['id']);
    }
    // обновление ссылок на подтаблицы в фильтрах полей связи
    $result = sql_select(FIELDS_TABLE, "table_id=", $new_table_id, " AND type_field=5 AND type_value LIKE '%|0.%'");
    while ($row = sql_fetch_assoc($result)) {
        foreach ($new_subtables as $subtable_id => $new_subtable_id) {
			$row['type_value'] = str_replace('{#new#}', '', str_replace("|0.$subtable_id|", "|0.$new_subtable_id{#new#}|", $row['type_value']));
		}
        sql_update(FIELDS_TABLE, array('type_value' => $row['type_value']), "id=", $row['id']);
    }

    // создание собственно таблицы для данных
    foreach ($import_data['fields'] as $row) {
        // вычисляем sql-имя поля
        $field_name = "f" . $new_fields[$row['id']];
        if ($row['type_field'] == 10) $field_name = "id";
        if ($row['type_field'] == 11) $field_name = "user_id";
        if ($row['type_field'] == 12) $field_name = "add_time";
        if ($row['type_field'] == 13) $field_name = "status";
        // вычисляем sql-тип поля
        $ta = explode("\r\n", $row['type_value']);
        $ta = explode("|", $ta[0]);
        list($type_value) = $ta;
        $field_type = sql_type($row['type_field'], $type_value, $row['mult_value']);
        if ($row['type_field'] == 3 and sql_num_rows($result) > 30) $field_type = sql_type($row['type_field'], 0, 1);
        // создаем описание поля
        $fields[] = $field_name . " " . $field_type;
    }
    sql_query('CREATE TABLE ' . DATA_TABLE . $new_table_id . ' (' . implode(',', $fields) . ', r int(11) DEFAULT 0, u tinyint(1) DEFAULT 0, ' . ($new_qst ? "uniq_qst varchar(255) DEFAULT '', " : '') . 'PRIMARY KEY (id)) ENGINE=' . $config['db_engine'] . ' DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci');

    return [
        'new_table_id' => $new_table_id,
        'new_fields' => $new_fields,
        'new_filters' => $new_filters,
        'new_calcs' => $new_calcs,
        'new_forms' => $new_forms,
        'new_subtables' => $new_subtables,
        'new_buttons' => $new_buttons,
        'new_tips' => $new_tips,
    ];
}

// Конвертация вычислений при импорте конфигурации
function convert_import_calc(&$calc, $new_tables, $new_fields, $new_filters, $new_forms, $sel_links)
{
    convert_import_code($calc['calculate'], $new_tables, $new_fields, $new_filters, $new_forms);
    $link_fields = unserialize($calc['link_fields']);
    convert_import_links($link_fields, $new_tables, $new_fields, $sel_links);
    $calc['link_fields'] = serialize($link_fields);
    $params = json_decode($calc['construct_params'], 1);
    if ($params) {
        foreach ($params['params'] as &$one_param) {
            foreach ($one_param as &$sub_param) {
                if (is_array($sub_param) && $sub_param['table'] && $new_tables[$sub_param['table']]) {
                    $sub_param['table'] = $new_tables[$sub_param['table']];
                }
            }
            for ($i = 1; $i <= 2; $i++) {
                if ($one_param['table'.$i] && $new_tables[$one_param['table'.$i]]) {
                    $one_param['table'.$i] = $new_tables[$one_param['table'.$i]];
                }
                if (is_array($one_param['f'.$i])) {
                    $old_json = json_encode($one_param['f'.$i]);
                    foreach ($one_param['f'.$i] as &$sub_param) {
                        if ($new_fields[$sub_param]) {
                            $sub_param = $new_fields[$sub_param];
                        }
                    }
                    $new_json = json_encode($one_param['f'.$i]);
                    $calc['calculate'] = str_replace($old_json, $new_json, $calc['calculate']);
                }
            }
            if (is_array($one_param['correlation'])) {
                $one_param['correlation']['link_field_id'] = $new_fields[$one_param['correlation']['link_field_id']] ?: $one_param['correlation']['link_field_id'];
                $one_param['correlation']['save_field'] = $new_fields[$one_param['correlation']['save_field']] ?: $one_param['correlation']['save_field'];
                foreach ($one_param['correlation']['to_field'] as &$one_field) {
                    $one_field = $new_fields[$one_field] ?: $one_field;
                }
                foreach ($one_param['correlation']['cur_field'] as &$one_field) {
                    $one_field = $new_fields[$one_field] ?: $one_field;
                }
            }
            if ($one_param['filter'] && $new_filters[$one_param['filter']]) {
                $one_param['filter'] = $new_filters[$one_param['filter']];
            }
            if ($one_param['print_tpl'] && $new_forms[$one_param['print_tpl']]) {
                $one_param['print_tpl'] = $new_forms[$one_param['print_tpl']];
            }
            if ($one_param['send_tpl'] && $new_forms[$one_param['send_tpl']]) {
                $one_param['send_tpl'] = $new_forms[$one_param['send_tpl']];
            }
        }
        foreach ($params['cond_params'] as &$one_param) {
            if ($one_param['field'] != -1) {
                $one_param['field'] = $new_fields[$one_param['field']];
            }
        }
        $params = json_encode($params, JSON_FORCE_OBJECT | JSON_UNESCAPED_UNICODE);
        foreach ($new_fields as $old_field_id => $new_field_id) {
            $params = str_replace('"f' . $old_field_id . '"', '"f' . $new_field_id . 'o[{(#)}]"', $params);
        }
        $params = str_replace('o[{(#)}]', '', $params); // снимаем костыли
        $calc['construct_params'] = $params;
    }
}

// Конвертация кода при импорте конфигурации
function convert_import_code(&$code, $new_tables, $new_fields, $new_filters, $new_forms)
{
    foreach ($new_tables as $old_table_id => $new_table_id) {
        $new_table_id .= "o[{(#)}]"; // костыль чтобы не заменялось несколько раз
        $code = str_replace("data_select_field(" . $old_table_id . ",", "data_select_field(" . $new_table_id . ",", $code);
        $code = str_replace("data_select_array(" . $old_table_id . ",", "data_select_array(" . $new_table_id . ",", $code);
        $code = str_replace("data_select(" . $old_table_id . ",", "data_select(" . $new_table_id . ",", $code);
        $code = str_replace("data_insert(" . $old_table_id . ",", "data_insert(" . $new_table_id . ",", $code);
        $code = str_replace("data_update(" . $old_table_id . ",", "data_update(" . $new_table_id . ",", $code);
        $code = str_replace("data_delete(" . $old_table_id . ",", "data_delete(" . $new_table_id . ",", $code);
        $code = str_replace("reset_filters(" . $old_table_id . ")", "reset_filters(" . $new_table_id . ")", $code);
        $code = str_replace("go_table(" . $old_table_id . ")", "go_table(" . $new_table_id . ")", $code);
        $code = str_replace("go_table(" . $old_table_id . ",", "go_table(" . $new_table_id . ",", $code);
        $code = str_replace("go_line(" . $old_table_id . ",", "go_line(" . $new_table_id . ",", $code);
        $code = str_replace("get_table_id(" . $old_table_id . ")", "get_table_id(" . $new_table_id . ")", $code);
        $code = str_replace("record_sublines_status_log(" . $old_table_id . ",", "record_sublines_status_log(" . $new_table_id . ",", $code);
        $code = str_replace("export_data(" . $old_table_id . ",", "export_data(" . $new_table_id . ",", $code);
        $code = str_replace("import_data(" . $old_table_id . ",", "import_data(" . $new_table_id . ",", $code);
    }
    $code = str_replace("o[{(#)}]", "", $code); // снимаем костыли
    foreach ($new_fields as $old_field_id => $new_field_id) {
        $new_field_id .= "o[{(#)}]"; // костыль чтобы не заменялось несколько раз
        $code = preg_replace("/\bf" . $old_field_id . "\b/", "f" . $new_field_id, $code);
        $code = str_replace("\$event['changed'][" . $old_field_id . "]", "\$event['changed'][" . $new_field_id . "]", $code);
        $code = str_replace("\$event['changed']['" . $old_field_id . "']", "\$event['changed'][" . $new_field_id . "]", $code);
        $code = str_replace("set_filter(" . $old_field_id . ",", "set_filter(" . $new_field_id . ",", $code);
        $code = str_replace("get_file_path(" . $old_field_id . ",", "get_file_path(" . $new_field_id . ",", $code);
        $code = str_replace("save_data_file(" . $old_field_id . ",", "save_data_file(" . $new_field_id . ",", $code);
        $code = str_replace("get_field_id(" . $old_field_id . ")", "get_field_id(" . $new_field_id . ")", $code);
        $code = preg_replace("/record_sublines_status_log\((\d+), " . $old_field_id . ",/", "record_sublines_status_log($1, " . $new_field_id . ",", $code);
    }
    $code = str_replace("o[{(#)}]", "", $code); // снимаем костыли
    foreach ($new_filters as $old_filter_id => $new_filter_id) {
        $new_filter_id .= "o[{(#)}]"; // костыль чтобы не заменялось несколько раз
        $code = str_replace("get_filter_id(" . $old_filter_id . ")", "get_field_id(" . $new_filter_id . ")", $code);
    }
    $code = str_replace("o[{(#)}]", "", $code); // снимаем костыли
    foreach ($new_forms as $old_form_id => $new_form_id) {
        $new_form_id .= "o[{(#)}]"; // костыль чтобы не заменялось несколько раз
        $code = str_replace("send_template(" . $old_form_id . ",", "send_template(" . $new_form_id . ",", $code);
        $code = str_replace("get_form_id(" . $old_form_id . ")", "get_form_id(" . $new_form_id . ")", $code);
    }
    $code = str_replace("o[{(#)}]", "", $code); // снимаем костыли
}

// Конвертация javascript при импорте конфигурации
function convert_import_javascript(&$code, $new_fields)
{
    foreach ($new_fields as $old_field_id => $new_field_id) {
        $new_field_id .= "o[{(#)}]"; // костыль чтобы не заменялось несколько раз
        $code = preg_replace("/\bfgroup_view_header" . $old_field_id . "\b/", "fgroup_view_header" . $new_field_id, $code);
        $code = preg_replace("/\bfg_img_view" . $old_field_id . "\b/", "fg_img_view" . $new_field_id, $code);
        $code = preg_replace("/\bfgroup_view" . $old_field_id . "\b/", "fgroup_view" . $new_field_id, $code);
        $code = preg_replace("/\bfield_view" . $old_field_id . "\b/", "field_view" . $new_field_id, $code);
        $code = preg_replace("/\bview_cell_" . $old_field_id . "\b/", "view_cell_" . $new_field_id, $code);
        $code = preg_replace("/\bfgroup_edit_header" . $old_field_id . "\b/", "fgroup_edit_header" . $new_field_id, $code);
        $code = preg_replace("/\bfg_img_edit" . $old_field_id . "\b/", "fg_img_edit" . $new_field_id, $code);
        $code = preg_replace("/\bfgroup_edit" . $old_field_id . "\b/", "fgroup_edit" . $new_field_id, $code);
        $code = preg_replace("/\bfield_edit" . $old_field_id . "\b/", "field_edit" . $new_field_id, $code);
        $code = preg_replace("/\bedit" . $old_field_id . "\b/", "edit" . $new_field_id, $code);
        $code = preg_replace("/\bmain" . $old_field_id . "\b/", "main" . $new_field_id, $code);
        $code = preg_replace("/\bvalue" . $old_field_id . "\b/", "value" . $new_field_id, $code);
        $code = preg_replace("/\bedit_value" . $old_field_id . "\b/", "edit_value" . $new_field_id, $code);
        $code = preg_replace("/\bdel_file" . $old_field_id . "\b/", "del_file" . $new_field_id, $code);
        $code = preg_replace("/\badd_file" . $old_field_id . "\b/", "add_file" . $new_field_id, $code);
        $code = str_replace("select_all(" . $old_field_id . ")", "select_all(" . $new_field_id . ")", $code);
        $code = str_replace("delfile(" . $old_field_id . ",", "delfile(" . $new_field_id . ",", $code);
        $code = str_replace("addfile(" . $old_field_id . ")", "addfile(" . $new_field_id . ")", $code);
        $code = str_replace("display_field(" . $old_field_id . ",", "display_field(" . $new_field_id . ",", $code);
        $code = str_replace("select[field_id='" . $old_field_id . "']", "select[field_id='" . $new_field_id . "']", $code);
    }
    $code = str_replace("o[{(#)}]", "", $code); // снимаем костыли
}

// Конвертация link_fields при импорте конфигурации
function convert_import_links(&$links, $new_tables, $new_fields, $sel_links)
{
    foreach ($links as $key => $value) {
        if (is_array($value)) {
            convert_import_links($links[$key], $new_tables, $new_fields, $sel_links);
        } elseif ($new_tables[$value]) {
            $links[$key] = (string)$new_tables[$value];
        }
        if ($new_fields[$key] && $new_fields[$key] != $key) {
            if ($sel_links[$new_fields[$key]] !== '0') {
                $links[$new_fields[$key]] = $links[$key];
            }
            unset($links[$key]);
        }
    }
}

// болванки для упрощения конвертации кода при переносе
function get_table_id($table_id)
{
    return $table_id;
}
function get_field_id($field_id)
{
    return $field_id;
}
function get_filter_id($filter_id)
{
    return $filter_id;
}
function get_form_id($forms_id)
{
    return $forms_id;
}

// переход в таблицу
function go_table($table_id, $filter_id = 0)
{
    global $config;
    header("Location: " . $config["site_root"] . "/fields.php?table=" . $table_id . ($filter_id ? "&filter=" . $filter_id : ""));
}

// переход в запись
function go_line($table_id, $line_id)
{
    global $config;
    header("Location: " . $config["site_root"] . "/view_line2.php?table=" . $table_id . "&line=" . $line_id);
}

// перевод фраз из конфигурации
function translate($phrase)
{
    global $lang;
    return $lang['conf'][$phrase] ? $lang['conf'][$phrase] : $phrase;
}

// проверка таблицы перед удалением
function test_delete_table($table_id, $addon_parts = array()) {
    global $lang, $serv_link_to_delete;

    $table = get_table($table_id);
    $table_fields = get_table_fields($table);

    // Определяем id служебных таблиц из скрытого дополнения Логи
    $addon_id = sql_fetch_row(sql_select_field(ADDONS_TABLE, 'id', "name = 'Логи' AND inactive = 1"))[0];
    $result = sql_select_field(ADDON_PARTS_TABLE, 'part_id', "part_type = 'table' AND addon_id = ", $addon_id);
    while ($row = sql_fetch_array($result)) {
        $addon_parts['serve_table'][$row['part_id']] = $row['part_id'];
    }
    $err_msg_fields = [];
    foreach ($table_fields as $one_field) {
        if ($err_msg_fld = test_delete_field($one_field, $addon_parts, 1)) {
            $err_msg_fields[] = $err_msg_fld;
        }
        if (cb_count($err_msg_fields) > 5) {
            break;
        }
    }

    $err_msg = '';
    if ($err_msg_fields) { // поля таблицы где-то участвуют
        $err_msg .= '<br><br>' . implode("\n", $err_msg_fields);
    } elseif ($serv_link_to_delete) { // удаляем служебные поля связи
        foreach ($serv_link_to_delete as $field_id) {
            sql_delete(FIELDS_TABLE, 'id = ', $field_id);
        }
    }

    return $err_msg;
}

function test_delete_field($field, $addon_parts = array(), $del_table = 0, $change_type = 0) {
    global $lang, $serv_link_to_delete;

    if (!$del_table) { // не проверяем если удаление поля идет как этап удаления таблицы целиком
        if (!$change_type) { // не проверяем если это проверка при смене типа поля
            // Проверка на наличие сортировки и группировки с данным полем
            $result = sql_select_field(TABLES_TABLE, 'def_sort, group_field, user_table_link', 'id = ', $field['table_id']);
            $row = sql_fetch_array($result);
            if (strpos($row['def_sort'], "`" . $field['int_name'] . "`") !== false) {
                $error_message .= $lang['used_sort_field'] . ", ";
            }
            if ($row['group_field'] == $field['id']) {
                $error_message .= $lang['used_group_field'] . ", ";
            }
        }
        // Проверка на наличие связи с пользователем для данного поля
        $user_table_fields = $row['user_table_link'] ? unserialize($row['user_table_link']) : array();
        foreach ($user_table_fields as $ulf_id) {
            if ($ulf_id == $field['id']) {
                $error_message .= $lang['used_in_user_fields'] . ", ";
                break;
            }
        }
        // Проверка на наличие фильтров, форматирований и напоминаний с данным полем
        $result = sql_select(FILTERS_TABLE, 'table_id = ', $field['table_id']);
        while ($row = sql_fetch_array($result)) {
            if (strpos($row['value'], "`" . $field['int_name'] . "`") !== false) {
                $used_field['filters'][] = '<a href="edit_filter.php?table=' . $row['table_id'] . '&filter=' . $row['id'] . '" target="_blank">"' . $row['name'] . '"</a>';
            }
        }
        $result = sql_select(FIELDS_TABLE, 'table_id = ', $field['table_id']);
        while ($row = sql_fetch_array($result)) {
            if (strpos($row['type_value'], "|-" . $field['id'] . "|") !== false) {
                $used_field['filters'][] = $lang['by_field'] . ' ' . $lang['in'] . ' ' . $lang['field'] . ' <a href="edit_field.php?table=' . $row['table_id'] . '&field=' . $row['id'] . '" target="_blank">"' . $row['name_field'] . '"</a>';
            }
        }
        $result = sql_select(TIPS_TABLE, 'table_id = ', $field['table_id']);
        while ($row = sql_fetch_array($result)) {
            if (strpos($row['cond_value'], "`" . $field['int_name'] . "`") !== false) {
                $used_field['tips'][] = '<a href="edit_tip.php?table=' . $row['table_id'] . '&tip=' . $row['id'] . '" target="_blank">"' . $row['name'] . '"</a>';
            }
        }
        $result = sql_select(FORMAT_TABLE, 'table_id = ', $field['table_id']);
        while ($row = sql_fetch_array($result)) {
            if (strpos($row['cond_value'], "\$cur_line[" . $field['id'] . "]") !== false) {
                $used_field['format'][] = '<a href="edit_format.php?table=' . $row['table_id'] . '&format=' . $row['id'] . '" target="_blank">"' . $row['name'] . '"</a>';
            }
        }
        $result = sql_select(INFORMERS_TABLE, 'table_id = ', $field['table_id']);
        while ($row = sql_fetch_array($result)) {
            if (strpos($row['cond_value'], "`" . $field['int_name'] . "`") !== false) {
                $used_field['informers'][] = '<a href="edit_status.php?table=' . $row['table_id'] . '&informer=' . $row['id'] . '" target="_blank">"' . $row['name'] . '"</a>';
            }
        }
        $result = sql_select(ACC_RULES_TABLE, 'table_id = ', $field['table_id']);
        while ($row = sql_fetch_array($result)) {
            if (strpos($row['condition_php'], "\$line['" . $field['int_name'] . "']") !== false) {
                $used_field['acc_rules'][] = '<a href="edit_group.php?group=' . $row['group_id'] . '&cat_item=t' . $row['table_id'] . '&menu=rules&rules_id=' . $row['id'] . '" target="_blank">"' . $row['name'] . '"</a>';
            }
        }
        // Если это поле связи, смотрим не используется ли оно для связи с родительской в подчиненных таблицах
        if ($field['type_field'] == 5) {
            $result = sql_select(SUBTABLES_TABLE, 'link_field_id = ', $field['id']);
            if ($row = sql_fetch_array($result)) {
                $error_message .= $lang['field_in_subtable'] . ' <a href="edit_subtable.php?table=' . $row['table_id'] . '&subtable=' . $row['id'] . '" target="_blank">"' . $row['name'] . '"</a>, ';
            }
            $result = sql_select(ADDIT_TABLES_TABLE, 'link_field_id = ', $field['id']);
            if ($row = sql_fetch_array($result)) {
                $error_message .= $lang['field_in_addittable'] . ' <a href="edit_addittable.php?table=' . $row['table_id'] . '&addittable=' . $row['id'] . '" target="_blank">"' . $row['name'] . '"</a>, ';
            }
        }
    }

    // Проверка на наличие полей связи со ссылкой на данное поле
    if (!$change_type) { // не проверяем если это проверка при смене типа поля
        $result = sql_query("SELECT a.id, a.name_field, a.table_id, b.name_table, a.type_value FROM " . FIELDS_TABLE . " a, " . TABLES_TABLE . " b " .
                            "WHERE a.table_id=b.id AND type_field=5 AND (type_value like '%|" . $field['id'] . "|%' OR type_value like '%|-" . $field['id'] . "')" .
                            ($del_table ? ' AND table_id != ' . $field['table_id'] : '')); // при удалении таблицы целиком смотрим только связи вне таблицы
        while ($row = sql_fetch_array($result)) {
            if ($addon_parts['table'][$row['table_id']]) continue; // внутри дополнения не проверяем
            if ($addon_parts['serve_table'][$row['table_id']]) { // у служебной таблицы помечаем поле связи к удалению
                $serv_link_to_delete[] = $row['id'];
                continue;
            }
            $link_field_id = explode('|', $row['type_value'])[1];
            if ($link_field_id == $field['id']) {
                $used_field['used_links'][] = $lang['field'] . ' <a href="edit_field.php?table=' . $row['table_id'] . '&field=' . $row['id'] . '" target="_blank">"' . $row['name_field'] . '"</a> ' .
                    $lang['of_table'] . ' <a href="edit_table.php?table=' . $row['table_id'] . '" target="_blank">"' . $row['name_table'] . '"</a>';
            }
        }
    }

    if ($used_field['filters']) {
        $error_message .= $lang['used_in_filters'] . ": " . implode(", ", $used_field['filters']) . ", ";
    }
    if ($used_field['tips']) {
        $error_message .= $lang['used_in_tips'] . ": " . implode(", ", $used_field['tips']) . ", ";
    }
    if ($used_field['format']) {
        $error_message .= $lang['used_in_format'] . ": " . implode(", ", $used_field['format']) . ", ";
    }
    if ($used_field['informers']) {
        $error_message .= $lang['used_in_informers'] . ": " . implode(", ", $used_field['informers']) . ", ";
    }
    if ($used_field['acc_rules']) {
        $error_message .= $lang['in_rules'] . ": " . implode(", ", $used_field['acc_rules']) . ", ";
    }
    if ($used_field['used_links']) {
        $error_message .= $lang['used_in_link_fields'] . ": " . implode(", ", $used_field['used_links']) . ", ";
    }

    // Проверка на наличие кода с данным полем
    $actions = check_field_actions($field['id'], $del_table);
    if ($actions['buttons']) { // Поле присутствует в доп. действиях
        foreach ($actions['buttons'] as $tbl_id => $tbl_data) {
            if ($addon_parts['table'][$tbl_id]) continue; // внутри дополнения не проверяем
            if (count_cb($tbl_data) == 1) {
                $error_message .= $lang['field_in_add'] . ' ';
            } else {
                $error_message .= $lang['field_in_adds'] . ' ';
            }
            foreach ($tbl_data as $one_data) {
                $error_message .= '<a href="edit_button.php?button=' . $one_data['action_id'] . '" target="_blank">"' . $one_data['action_name'] . '"</a>, ';
            }
            $error_message = rtrim(trim($error_message), ', ');
            $error_message .= ' ' . $lang['act_of_table'] . ' <a href="edit_button.php?table=' . $tbl_id . '" target="_blank">"' . $one_data['table_name'] . '"</a>, ';
        }
    }
    if ($actions['calcs']) { // Поле участвует в вычислениях
        foreach ($actions['calcs'] as $tbl_id => $tbl_data) {
            if ($addon_parts['table'][$tbl_id]) continue; // внутри дополнения не проверяем
            if (count_cb($tbl_data) == 1) {
                $error_message .= $lang['field_in_calc'] . ' ';
            } else {
                $error_message .= $lang['field_in_calcs'] . ' ';
            }
            foreach ($tbl_data as $one_data) {
                $error_message .= '<a href="edit_calc.php?calc_id=' . $one_data['calc_id'] . '" target="_blank">"' . $one_data['calc_name'] . '"</a>, ';
            }
            $error_message = rtrim(trim($error_message), ', ');
            $error_message .= ' ' . $lang['act_of_table'] . ' <a href="edit_calc.php?table=' . $tbl_id . '" target="_blank">"' . $one_data['table_name'] . '"</a>, ';
        }
    }
    if ($actions['reports']) { // Поле участвует в отчетах
        foreach ($actions['reports'] as $ct_id => $cat_data) {
            foreach ($cat_data as $k => $one_data) {
                if ($addon_parts['report'][$one_data['report_id']]) unset($cat_data[$k]); // внутри дополнения не проверяем
            }
            if (!$cat_data) continue;
            if (count_cb($cat_data) == 1) {
                $error_message .= $lang['field_in_rep'] . ' ';
            } else {
                $error_message .= $lang['field_in_reps'] . ' ';
            }
            foreach ($cat_data as $one_data) {
                $error_message .= '<a href="edit_report.php?cat=$cat_id&report=' . $one_data['report_id'] . '" target="_blank">"' . $one_data['report_name'] . '"</a>, ';
            }
            $error_message = rtrim(trim($error_message), ', ');
            $error_message .= ' ' . $lang['of_category'] . ' <a href="edit_tabrep.php?cat=$ct_id" target="_blank">"' . $one_data['cat_name'] . '"</a>, ';
        }
    }
    if ($actions['crons']) { // Поле участвует в кроне
        if (count_cb($actions['crons']) == 1) {
            $error_message .= $lang['field_in_cron'] . ' ';
        } else {
            $error_message .= $lang['field_in_crons'] . ' ';
        }
        foreach ($actions['crons'] as $one_data) {
            $error_message .= '<a href="edit_cron.php?cron_id=' . $one_data['cron_id'] . '" target="_blank">"' . $one_data['cron_name'] . '"</a>, ';
        }
    }
    if ($actions['ext_files']) { // Поле участвует во внешних файлах
        $error_message .= $lang['in'] . ' ';
        foreach ($actions['ext_files'] as $one_data) {
            $error_message .= '<a href="" onclick="open_calc(\'ext_file_id=' . $one_data['id'] . '\', 0); return false;">"' . $one_data['name'] . '"</a>, ';
        }
    }
    if ($actions['calendars']) {
        foreach ($actions['calendars'] as $calendar_id => $calendar_data) {
            if ($addon_parts['calendar'][$calendar_id]) continue; // внутри дополнения не проверяем
            if (count_cb($calendar_data) == 1) {
                $error_message .= $lang['field_in_event'] . ' ';
            } else {
                $error_message .= $lang['field_in_event'] . ' ';
            }
            $cal_events = array();
            foreach ($calendar_data as $one_event) {
                $cal_events[] = '<a href="edit_calendar.php?calendar=' . $calendar_id . '&calendar_event=' . $one_event['event_id'] . '" target="_blank">"' . $one_event['event_name'] . '"</a>';
            }
            $error_message .= implode(', ', $cal_events) . ' ' . $lang['field_in_calendar'] . ' <a href="edit_calendar.php?calendar=' . $calendar_id . '" target="_blank">"' . $one_event['calendar_name'] . '"</a>,';
        }
    }
    if ($error_message) {
        $error_message = $lang['Field'] . ' "' . $field['name_field'] . '" ' . $lang['used_in'] . ' ' . rtrim($error_message, ', ') . '.<br>';
    }

    return $error_message;
}

// автодобавление пользователя телефонии
function add_asterisk_user($user_id)
{
    global $user;

    $master_user = sql_select_array(ASTERISK_USERS, "login = '101'");

    $last_num_res = sql_select_field(ASTERISK_USERS, 'max(login) as max_num', 'server_id = 1');
    $last_num_row = sql_fetch_assoc($last_num_res);
    $asterisk_number = intval($last_num_row['max_num']) + 1;

    $asterisk_password = generate_password();

    if ($asterisk_number && $asterisk_password) {
        $submit_url = 'https://' . $ASTERISK_SETTINGS['server'] . '/as/phone.php';
        $submit_vars['action'] = '{"key":"' . $user['open_key'] . '","master":"' . $user['main_server'] . '","login":"101","password":"' . $master_user['password'] . '","action":"add_number","val_phone":"' . $asterisk_number . '","val_password":"' . $asterisk_password . '", "pickup_group":"0", "web_calls":"1"}';
        $result = json_decode(send_asterisk_curl($submit_url, $submit_vars), 1);
        if ($result['status'] == 0) {
            sql_insert(ASTERISK_USERS, [
                'server_id' => 1,
                'user_id' => $user_id,
                'login' => $asterisk_number,
                'password' => $asterisk_password,
                'from_browser' => 0,
                'browser_caller' => 1
            ]);
        }
    }
}

// склонение ФИО по русским падежам
function get_case_name_ru($name, $case)
{
    require_once __DIR__ . '/NameCaseLib/NCLNameCaseRu.php';
    $cases = [
        'и' => NCL::$IMENITLN,
        'р' => NCL::$RODITLN,
        'д' => NCL::$DATELN,
        'в' => NCL::$VINITELN,
        'т' => NCL::$TVORITELN,
        'п' => NCL::$PREDLOGN,
    ];
    $case = $cases[mb_substr($case, 0, 1)];
    return (new NCLNameCaseRu)->q($name, $case);
}

// Массовый запуск вычисления по крону
function run_calc($calc_id, $filter_id = 0, $limit = '', $use_records = [0])
{
    global $tables_cache;
    $tables_cache = array();
    $calc = sql_select_array(CALC_TABLE, 'id = ', $calc_id);
    if ($calc) {
        $table_id = $calc['table_id'];
        $table = get_table($table_id);
        $table_fields = get_table_fields($table);
        $calc['link_fields'] = unserialize($calc['link_fields']);
        $event = [
            'type' => 'cron',
            'table_id' => $table_id,
            'changed' => [],
        ];
        if ($use_records && is_array($use_records)) {
            $status = 'status IN (' . implode(',', $use_records) . ') AND ';
        }
        $where = '1 = 1';
        $filter_id = $filter_id ?: $calc['filter_id'];
        if ($filter_id) {
            $filter = sql_select_array(FILTERS_TABLE, 'id = ', $filter_id);
            if ($filter['value']) {
                $where = '(' . filter_tpl_replace($filter['value']) . ')';
            }
        }
        if ($limit) {
            $limit = ' LIMIT ' . $limit;
        }
        $result = data_select($table_id, $status . $where . $limit);
        while ($line = sql_fetch_assoc($result)) {
            calc_line($table, $line, $calc, $event);
        }
    }
}

// сохранение параметра config в БД
function set_config_parameter($name)
{
    global $config;
    if (is_array($config[$name])) {
        $config[$name] = json_encode($config[$name]);
    }
    if (!sql_select_array(CONFIG_TABLE, "name = '$name'")) {
        sql_insert(CONFIG_TABLE, ['name' => $name, 'value' => $config[$name]]);
    } else {
        sql_update(CONFIG_TABLE, ['value' => $config[$name]], "name = '$name'");
    }
}

// возврат имени источника события
function get_event_subject($event)
{
    global $lang, $user;

    if ($event['calc_id']) { // событие вызвано вычислением или ДД
        global $calc_names_cache, $button_id_cache;
        $calc_name = $calc_names_cache[$event['calc_id']];
        if (!$calc_name) {
            $calc_name = sql_fetch_row(sql_select_field(CALC_TABLE, 'name', 'id = ', $event['calc_id']))[0];
            $words = explode(' ', $calc_name);
            if ($words[0] == 'Button') {
                $calc_name = sql_fetch_row(sql_select_field(BUTTONS_TABLE, 'name', 'id = ', $words[1]))[0];
                $button_id_cache[$event['calc_id']] = $words[1];
            }
            $calc_names_cache[$event['calc_id']] = $calc_name;
        }
        if ($button_id_cache[$event['calc_id']]) {
            $subject = $lang['Additional_action'] . " <a href='edit_button.php?button=" . $button_id_cache[$event['calc_id']] . "'>" . $calc_name . "</a> ";
        } else {
            $subject = $lang['Calc'] . " <a href='edit_calc.php?calc_id=" . $event['calc_id'] . "'>" . $calc_name . "</a> ";
        }
    } elseif ($event['sync_id']) { // событие вызвано синхронизацией
        global $sync_names_cache;
        $sync_name = $sync_names_cache[$event['sync_id']];
        if (!$sync_name) {
            $sync_name = sql_fetch_row(sql_select_field(SYNC_TABLE, 'sync_name', 'id = ', $event['sync_id']))[0];
            $sync_names_cache[$event['sync_id']] = $sync_name;
        }
        $subject = $lang['Sync'] . " <a href='edit_sync.php?sync_id=" . $event['sync_id'] . "'>" . $sync_name . "</a> ";
    } elseif ($event['cron_id']) { // событие вызвано заданием крон
        global $cron_names_cache;
        $cron_name = $cron_names_cache[$event['cron_id']];
        if (!$cron_name) {
            $cron_name = sql_fetch_row(sql_select_field(CRON_TABLE, 'description', 'id = ', $event['cron_id']))[0];
            $cron_names_cache[$event['cron_id']] = $cron_name;
        }
        $subject = $lang['Cron_task'] . " <a href='edit_cron.php?cron_id=" . $event['cron_id'] . "'>" . $cron_name . "</a> ";
    } elseif ($event['qst_id']) { // событие вызвано внешней формой
        global $qst_names_cache;
        $qst_name = $qst_names_cache[$event['qst_id']];
        if (!$qst_name) {
            $qst_name = sql_fetch_row(sql_select_field(QST_TABLE, 'name', 'id = ', $event['qst_id']))[0];
            $qst_names_cache[$event['qst_id']] = $qst_name;
        }
        $subject = $lang['Questionarie'] . " <a href='edit_questionare.php?qst_id=" . $event['qst_id'] . "&table=" . $event['table_id'] . "'>" . $qst_name . "</a> ";
    } elseif ($event['caller'] == '1C') {
        $subject = $lang['Module'] . ' 1С ';
    } else {
        $subject = $lang['User'] . ' "' . $user['fio'] . '" ';
    }
    return $subject;
}

// отправка письма/сообщения по избранному
function send_event_of_favorite_record($table_id, $line_id, $message)
{
    global $config, $lang, $user;

    $result = sql_select(FAVORITES_TABLE, 'table_id = ', $table_id, ' AND line_id = ', $line_id, ' AND user_id != ', $user['id']);
    while ($row = sql_fetch_assoc($result)) {
        if ($row['notify']) {
            $one_user = sql_fetch_assoc(sql_select_field(USERS_TABLE, 'e_mail, phone', 'id = ', $row['user_id']));
            if ($config['send_events_favorites']['email']) {
                sendmail($lang['Favorites_message_title'], $lang['Favorites_message_top'] . '<br><br>' . $message, $one_user['e_mail']);
            }
            if ($config['send_events_favorites']['wazzup']) {
                sendmsg($lang['Favorites_message_top'] . '<br><br>' . $message, $one_user['phone'], '', 'whatsapp');
            }
        }
    }
}

// закрытие сессии в КБ
function cb_session_write_close()
{
    if (!isset($GLOBALS['statistics']) || basename($_SERVER['PHP_SELF']) == 'edit_sql.php') {
        session_write_close();
    }
}

// логирование изменений в защите элементов конфигурации
function set_protect_log($elem_type, $elem_id, $protected, $protect, $table_id = 0, $group_id = 0, $mode = '')
{
    global $config, $lang, $user;

    if ($elem_type == 'category') {
        $elem_url = 'edit_cat.php?cat=' . $elem_id;
        $elem_name = sql_fetch_row(sql_select_field(CATS_TABLE, 'name', 'id = ', $elem_id))[0];
        if ($config['access_protect_mode'] == 2) $protect_acc = 1;
    } elseif ($elem_type == 'table') {
        $elem_url = 'edit_table.php?table=' . $elem_id;
        $elem_name = sql_fetch_row(sql_select_field(TABLES_TABLE, 'name_table', 'id = ', $elem_id))[0];
        if ($config['access_protect_mode'] == 2) $protect_acc = 1;
    } elseif ($elem_type == 'report') {
        $elem_url = 'edit_report.php?report=' . $elem_id;
        $elem_name = sql_fetch_row(sql_select_field(REPORTS_TABLE, 'name', 'id = ', $elem_id))[0];
        if ($config['access_protect_mode'] == 2) $protect_acc = 1;
    } elseif ($elem_type == 'calendar') {
        $elem_url = 'edit_calendar.php?calendar=' . $elem_id;
        $elem_name = sql_fetch_row(sql_select_field(CALENDARS_TABLE, 'name', 'id = ', $elem_id))[0];
        if ($config['access_protect_mode'] == 2) $protect_acc = 1;
    } elseif ($elem_type == 'field') {
        $elem_url = 'edit_field.php?table=' . $table_id . '&field=' . $elem_id;
        $elem_name = sql_fetch_row(sql_select_field(FIELDS_TABLE, 'name_field', 'id = ', $elem_id))[0];
    } elseif ($elem_type == 'format') {
        $elem_url = 'edit_format.php?table=' . $table_id . '&format=' . $elem_id;
        $elem_name = sql_fetch_row(sql_select_field(FORMAT_TABLE, 'name', 'id = ', $elem_id))[0];
    } elseif ($elem_type == 'filter') {
        $elem_url = 'edit_filter.php?table=' . $table_id . '&filter=' . $elem_id;
        $elem_name = sql_fetch_row(sql_select_field(FILTERS_TABLE, 'name', 'id = ', $elem_id))[0];
        if ($config['access_protect_mode'] == 2) $protect_acc = 1;
    } elseif ($elem_type == 'button') {
        $elem_url = 'edit_button.php?table=' . $table_id . '&button=' . $elem_id;
        $elem_name = sql_fetch_row(sql_select_field(BUTTONS_TABLE, 'name', 'id = ', $elem_id))[0];
        if ($config['access_protect_mode'] == 2) $protect_acc = 1;
    } elseif ($elem_type == 'calc') {
        $elem_url = 'edit_calc.php?table=' . $table_id . '&calc_id=' . $elem_id;
        $elem_name = sql_fetch_row(sql_select_field(CALC_TABLE, 'name', 'id = ', $elem_id))[0];
    } elseif ($elem_type == 'questionare') {
        $elem_url = 'edit_questionare.php?table=' . $table_id . '&qst_id=' . $elem_id;
        $elem_name = sql_fetch_row(sql_select_field(QST_TABLE, 'name', 'id = ', $elem_id))[0];
    } elseif ($elem_type == 'form') {
        $elem_url = 'forms.php?table=' . $table_id . '&mode=' . $mode . '&admin&edit&form=' . $elem_id;
        $elem_name = sql_fetch_row(sql_select_field(FORMS_TABLE, 'name_form', 'id = ', $elem_id))[0];
        if ($config['access_protect_mode'] == 2) $protect_acc = 1;
    } elseif ($elem_type == 'tip') {
        $elem_url = 'edit_tip.php?table=' . $table_id . '&tip=' . $elem_id;
        $elem_name = sql_fetch_row(sql_select_field(TIPS_TABLE, 'name', 'id = ', $elem_id))[0];
        if ($config['access_protect_mode'] == 2) $protect_acc = 1;
    } elseif ($elem_type == 'subtable') {
        $elem_url = 'edit_subtable.php?table=' . $table_id . '&subtable=' . $elem_id;
        $elem_name = sql_fetch_row(sql_select_field(SUBTABLES_TABLE, 'name', 'id = ', $elem_id))[0];
        if ($config['access_protect_mode'] == 2) $protect_acc = 1;
    } elseif ($elem_type == 'addittable') {
        $elem_url = 'edit_addittable.php?table=' . $table_id . '&addittable=' . $elem_id;
        $elem_name = sql_fetch_row(sql_select_field(ADDIT_TABLES_TABLE, 'name', 'id = ', $elem_id))[0];
    } elseif ($elem_type == 'informer') {
        $elem_url = 'edit_informer.php?table=' . $table_id . '&informer=' . $elem_id;
        $elem_name = sql_fetch_row(sql_select_field(INFORMERS_TABLE, 'name', 'id = ', $elem_id))[0];
    } elseif ($elem_type == 'rule') {
        $elem_url = 'edit_group.php?group=' . $group_id . '&cat_item=t' . $table_id . '&menu=rules&rules_id=' . $elem_id;
        $elem_name = sql_fetch_row(sql_select_field(ACC_RULES_TABLE, 'name', 'id = ', $elem_id))[0];
    } elseif ($elem_type == 'subtable_rule') {
        $elem_url = 'edit_group.php?group=' . $group_id . '&cat_item=t' . $table_id . '&menu=rules&subtable_id=' . $elem_id;
        $elem_name = sql_fetch_row(sql_select_field(SUBTABLES_TABLE, 'name', 'id = ', $elem_id))[0];
    }

    if ($_POST['protected']) {
        $result = sql_select_field(GROUPS_TABLE, 'id, name', 'id = 1 OR sub_admin = 1');
        while ($group = sql_fetch_assoc($result)) {
            if ($protected[$group['id']]) {
                $old_value = $protect[$group['id']]['view'] + $protect[$group['id']]['edit'];
            } else {
                $old_value = 2;
            }
            $new_value = $_POST['protect_rights'][$group['id']]['view'] + $_POST['protect_rights'][$group['id']]['edit'];
            if ($new_value < $old_value) { // включил защиту (полную или только просмотр)
                insert_log('admin', $lang['Administrator'] . ' "' . $user['fio'] . '" ' . $lang['turn_on_protect'] . ' ' .
                    ($new_value == 1 ? $lang['for_edit'] : $lang['for_view']) . ' ' . $lang['of_' . $elem_type] .
                    ' <a href=' . $elem_url . '>' . $elem_name . '</a>' . ' ' . $lang['for_group'] . $group['name'] . '"');
            } elseif ($new_value > $old_value && $new_value == 1) { // поменял защиту с полной на только просмотр
                insert_log('admin', $lang['Administrator'] . ' "' . $user['fio'] . '" ' . $lang['turn_on_protect'] . ' ' .
                    $lang['for_edit'] . ' ' . $lang['of_' . $elem_type] . ' <a href=' . $elem_url . '>' . $elem_name . '</a>' . ' ' . $lang['for_group'] . $group['name'] . '"');
            } elseif ($new_value > $old_value && $new_value == 2) { // выключил защиту для конкретной группы
                insert_log('admin', $lang['Administrator'] . ' "' . $user['fio'] . '" ' . $lang['turn_off_protect'] . ' ' .
                    $lang['of_' . $elem_type] . ' <a href=' . $elem_url . '>' . $elem_name . '</a>' . ' ' . $lang['for_group'] . $group['name'] . '"');
            }
            if ($protect_acc) { // защита доступа
                if ((int)$_POST['protect_rights'][$group['id']]['acc'] < (int)($protect[$group['id']]['acc'] ?? 1)) { // включил защиту
                    insert_log('admin', $lang['Administrator'] . ' "' . $user['fio'] . '" ' . $lang['turn_on_protect'] . ' ' .
                        $lang['for_access'] . ($elem_type == 'table' ? ' "' . $lang['Visibility'] . '" ' : ' ') . $lang['of_' . $elem_type] . ' <a href=' . $elem_url . '>' . $elem_name . '</a>' . ' ' . $lang['for_group'] . $group['name'] . '"');
                } elseif ((int)$_POST['protect_rights'][$group['id']]['acc'] > (int)($protect[$group['id']]['acc'] ?? 1)) { // выключил защиту для конкретной группы
                    insert_log('admin', $lang['Administrator'] . ' "' . $user['fio'] . '" ' . $lang['turn_off_protect'] . ' ' .
                        $lang['for_access'] . ($elem_type == 'table' ? ' "' . $lang['Visibility'] . '" ' : ' ') . $lang['of_' . $elem_type] . ' <a href=' . $elem_url . '>' . $elem_name . '</a>' . ' ' . $lang['for_group'] . $group['name'] . '"');
                }
            }
            if ($elem_type == 'table' || $elem_type == 'field' || $elem_type == 'subtable') { // расширенная защита доступа
                if ($elem_type == 'table') {
                    $types = [
                        'add_acc'  => $lang['Add_lines'],
                        'del_acc'  => $lang['Delete_lines'],
                        'arc_acc'  => $lang['Archiving'],
                        'imp_acc'  => $lang['Import'],
                        'exp_acc'  => $lang['Export'],
                        'bed_acc'  => $lang['Bulk_edit'],
                    ];
                } elseif ($elem_type == 'field') {
                    $types = [
                        'tab_acc'  => $lang['Table2'],
                        'view_acc' => $lang['View2'],
                        'edit_acc' => $lang['Edit3'],
                        'add_acc'  => $lang['Add2'],
                        'sub_acc'  => $lang['Subtable'],
                        'exp_acc'  => $lang['Export'],
                        'imp_acc'  => $lang['Import'],
                    ];
                } elseif ($elem_type == 'subtable') {
                    $types = [
                        'add_acc'  => $lang['Add_lines'],
                        'del_acc'  => $lang['Delete_lines'],
                        'jump_acc'  => $lang['Jumping_to_record'],
                    ];
                }
                foreach ($types as $key => $type) {
                    if ((int)$_POST['protect_rights'][$group['id']]['ext'][$key] < (int)(isset($protect[$group['id']]) ? $protect[$group['id']]['ext'][$key] : 1)) { // включил защиту
                        insert_log('admin', $lang['Administrator'] . ' "' . $user['fio'] . '" ' . $lang['turn_on_protect'] . ' ' .
                            $lang['for_access'] . ' "' . $type . '" ' . $lang['of_' . $elem_type] . ' <a href=' . $elem_url . '>' . $elem_name . '</a>' . ' ' . $lang['for_group'] . $group['name'] . '"');
                    } elseif ((int)$_POST['protect_rights'][$group['id']]['ext'][$key] > (int)(isset($protect[$group['id']]) ? $protect[$group['id']]['ext'][$key] : 1)) { // выключил защиту для конкретной группы
                        insert_log('admin', $lang['Administrator'] . ' "' . $user['fio'] . '" ' . $lang['turn_off_protect'] . ' ' .
                            $lang['for_access'] . ' "' . $type . '" ' . $lang['of_' . $elem_type] . ' <a href=' . $elem_url . '>' . $elem_name . '</a>' . ' ' . $lang['for_group'] . $group['name'] . '"');
                    }
                }
            }
            if ($elem_type == 'table') { // защита на добавление элементов
                $types = [
                    'field'       => $lang['Fields'],
                    'format'      => $lang['Formatting'],
                    'filter'      => $lang['Filters'],
                    'button'      => $lang['Adds_buttons'],
                    'calc'        => $lang['Computation'],
                    'questionare' => $lang['Questionaries'],
                    'template1'   => $lang['Print_templates'],
                    'template2'   => $lang['Mail_templates'],
                    'template3'   => $lang['SMS_templates'],
                    'template4'   => $lang['Msg_templates'],
                    'tip'         => $lang['Tips'],
                    'subtable'    => $lang['Subtables'],
                    'addittable'  => $lang['Addittables'],
                    'informer'    => $lang['informers'],
                ];
                foreach ($types as $key => $type) {
                    if ((int)$_POST['protect_rights'][$group['id']]['add'][$key] < (int)($protect[$group['id']]['add'][$key] ?? 1)) { // включил защиту
                        insert_log('admin', $lang['Administrator'] . ' "' . $user['fio'] . '" ' . $lang['turn_on_protect'] . ' ' .
                            $lang['for_adding'] . ' "' . $type . '" ' . $lang['of_' . $elem_type] . ' <a href=' . $elem_url . '>' . $elem_name . '</a>' . ' ' . $lang['for_group'] . $group['name'] . '"');
                    } elseif ((int)$_POST['protect_rights'][$group['id']]['add'][$key] > (int)($protect[$group['id']]['add'][$key] ?? 1)) { // выключил защиту для конкретной группы
                        insert_log('admin', $lang['Administrator'] . ' "' . $user['fio'] . '" ' . $lang['turn_off_protect'] . ' ' .
                            $lang['for_adding'] . ' "' . $type . '" ' . $lang['of_' . $elem_type] . ' <a href=' . $elem_url . '>' . $elem_name . '</a>' . ' ' . $lang['for_group'] . $group['name'] . '"');
                    }
                }
            }
        }
    } else { // выключил защиту для всех групп
        $result = sql_select_field(PROTECT_TABLE, 'elem_id', "elem_type = '$elem_type' AND elem_id = ", $elem_id);
        if (sql_num_rows($result)) { // пишем только если защита была
            insert_log('admin', $lang['Administrator'] . ' "' . $user['fio'] . '" ' . $lang['turn_off_protect'] . ' ' .
                $lang['of_' . $elem_type] . ' <a href=' . $elem_url . '>' . $elem_name . '</a>');
        }
    }
}

function send_gpt_prompt($message, $endpoint = 'list') {
    if (is_array($message)) {
        [$key, $code] = $message;
        if (!is_array($response = get_gpt_prompt($key))) {
            return '';
        }
        [$prompt, $repeat] = $response;
        $prompt = defined($key) ? constant($key) : $prompt;
        $message = $prompt . "\n\n" . $code;
    }

    if ($GLOBALS['config']['type'] == 'SAAS') {
        $login = sql_fetch_row(sql_select_field('saas_config', 'value', "`key` = 'login'"))[0];
    } else {
        $login = substr(key_decrypt(file_get_contents($GLOBALS['config']['site_path'] . '/runtime/key.php')), 16, 14);
    }

    for ($i = 1; $i <= ($repeat ?? 1); $i++) {
        $curl = new \CB\Tool\Curl([
            'url' => 'https://gpt.clientbase.ru/api/dev/cbext/clientbase/gpt_proxy/' . $endpoint,
            'method' => 'POST',
            'dataFormat' => 'JSON',
            'headers' => [
                'Authorization' => 'Bearer ' . $login
            ]
        ]);
        $curl->data([
            'message' => $message,
            'param' => [
                'text_model' => 'gpt-5-mini'
            ]
        ]);
        $response = $curl->result();
        if (!empty($response['content'])) {
            $message = $prompt . "\n\n" . $response['content'];
        } else {
            break;
        }
    }
    return $response['content'] ?? $response ?? '';
}

function get_gpt_prompt($key) {
    $curl = new \CB\Tool\Curl([
        'url' => 'https://gpt.clientbase.ru/get_gpt_prompt.php',
        'method' => 'POST',
    ]);
    $curl->data([
        'key' => $key
    ]);
    $response = $curl->result();
    return $response;
}
