From 572b3f562be4abdc22d6fa0e8173c091a712284c Mon Sep 17 00:00:00 2001 From: Repellent Date: Mon, 29 Dec 2025 08:52:09 +0500 Subject: [PATCH] =?UTF-8?q?=D0=B2=20=D0=B0=D0=B4=D0=BC=D0=B8=D0=BD=D0=BA?= =?UTF-8?q?=D1=83=20=D0=B2=D1=8B=D0=BD=D0=B5=D1=81=D0=B5=D0=BD=D0=BE=20?= =?UTF-8?q?=D1=83=D0=BF=D1=80=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20?= =?UTF-8?q?=D1=80=D0=B0=D1=81=D1=88=D0=B8=D1=80=D0=B5=D0=BD=D0=B8=D1=8F?= =?UTF-8?q?=D0=BC=D0=B8=20=D0=B8=20=D1=80=D0=B0=D0=B7=D0=BC=D0=B5=D1=80?= =?UTF-8?q?=D0=BE=D0=BC=20=D1=84=D0=B0=D0=B9=D0=BB=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- class/comment.php | 156 +++++++++++++++++++++----------- js/comment.js | 170 +++++++++++++++++++++++++---------- sql.php | 20 +++-- templates/admin_settings.tpl | 12 ++- templates/comments_tree.tpl | 51 ++++++----- 5 files changed, 279 insertions(+), 130 deletions(-) diff --git a/class/comment.php b/class/comment.php index 76fa546..6584053 100644 --- a/class/comment.php +++ b/class/comment.php @@ -255,7 +255,8 @@ function commentListShow($tpl_dir) { $assign['comment_max_chars'] = $settings['comment_max_chars']; $assign['im'] = $settings['comment_use_antispam']; - + $assign['comment_allowed_extensions'] = $settings['comment_allowed_extensions'] ?? 'jpg,jpeg,png,gif'; + $assign['comment_max_file_size'] = $settings['comment_max_file_size'] ?? 2048; $comments = array(); if ($settings['comment_use_page_nav'] == 1) @@ -483,12 +484,12 @@ function commentListShow($tpl_dir) { $upload_path = BASE_DIR . '/uploads/comments/'; -// Создаем папку, если её нет -if (!is_dir($upload_path)) { - @mkdir($upload_path, 0775, true); + // Создаем папку, если её нет + if (!is_dir($upload_path)) { + @mkdir($upload_path, 0775, true); - // Содержимое для защитного файла index.php - $index_content = ""; - // Создаем index.php для безопасности (запрет листинга папки и редирект) - @file_put_contents($upload_path . 'index.php', $index_content); -} - - $allowed_mime = ['image/jpeg', 'image/png', 'image/gif']; - $file_info = @getimagesize($_FILES['comment_image']['tmp_name']); - $file_size = $_FILES['comment_image']['size']; - - // Проверка: это реально картинка и её размер не более 2Мб - if ($file_info && in_array($file_info['mime'], $allowed_mime) && $file_size <= 2 * 1024 * 1024) - { - $ext = pathinfo($_FILES['comment_image']['name'], PATHINFO_EXTENSION); - $comment_file_name = time() . '_' . rand(100, 999) . '.' . $ext; - - if (!move_uploaded_file($_FILES['comment_image']['tmp_name'], $upload_path . $comment_file_name)) { - $comment_file_name = ''; // Сбрасываем, если не удалось переместить - } + // Создаем index.php для безопасности (запрет листинга папки и редирект) + @file_put_contents($upload_path . 'index.php', $index_content); } + + // ---ДИНАМИЧЕСКАЯ ПРОВЕРКА РАСШИРЕНИЯ И РАЗМЕРА --- +$ext = strtolower(pathinfo($_FILES['comment_image']['name'], PATHINFO_EXTENSION)); +$allowed_ext_str = $settings['comment_allowed_extensions'] ?? 'jpg,jpeg,png,gif,webp'; +$allowed_extensions = array_map('trim', explode(',', strtolower($allowed_ext_str))); + +$max_file_size_kb = (int)($settings['comment_max_file_size'] ?? 2048); +$max_file_size_bytes = $max_file_size_kb * 1024; +$file_size = $_FILES['comment_image']['size']; + +// Дополнительная проверка: действительно ли это изображение по содержимому +$finfo = finfo_open(FILEINFO_MIME_TYPE); +$mime = finfo_file($finfo, $_FILES['comment_image']['tmp_name']); +finfo_close($finfo); + +if (in_array($ext, $allowed_extensions) + && $file_size > 0 + && $file_size <= $max_file_size_bytes + && strpos($mime, 'image/') === 0) // Проверяем, что MIME начинается с image/ +{ + $comment_file_name = time() . '_' . rand(100, 999) . '.' . $ext; + if (!move_uploaded_file($_FILES['comment_image']['tmp_name'], $upload_path . $comment_file_name)) { + $comment_file_name = ''; + } +} else { + // Если файл не прошел проверку, можно выдать ошибку (для AJAX) + if ($ajax) { echo 'error_file_validation'; exit; } +} } // --- ПОДГОТОВКА ДАННЫХ ДЛЯ БД --- @@ -546,7 +560,7 @@ exit; $user_rating = (int)($_POST['comment_user_rating'] ?? 0); // Если это ответ (parent_id > 0) И в настройках выключено "Использовать в ответах" if ($parent_id > 0 && (!isset($settings['comment_show_user_rating_replies']) || $settings['comment_show_user_rating_replies'] == 0)) { - $user_rating = 0; // Принудительно сбрасываем оценку для ответов + $user_rating = 0; // Принудительно сбрасываем оценку для ответов } if ($user_rating < 0) $user_rating = 0; if ($user_rating > 5) $user_rating = 5; $new_comment['user_rating'] = $user_rating; @@ -585,21 +599,21 @@ exit; if ($ajax) { // 1. Получаем аватар как обычно -$new_comment['avatar'] = (isset($new_comment['comment_author_id']) && $new_comment['comment_author_id'] > 0) ? getAvatar($new_comment['comment_author_id'], 48) : ''; + $new_comment['avatar'] = (isset($new_comment['comment_author_id']) && $new_comment['comment_author_id'] > 0) ? getAvatar($new_comment['comment_author_id'], 48) : ''; -// 2. Очищаем, если это системный user.png -if (!empty($new_comment['avatar']) && strpos($new_comment['avatar'], 'user.png') !== false) -{ - $new_comment['avatar'] = ''; -} + // 2. Очищаем, если это системный user.png + if (!empty($new_comment['avatar']) && strpos($new_comment['avatar'], 'user.png') !== false) + { + $new_comment['avatar'] = ''; + } -// 3. Если аватара нет — генерируем данные для буквы -if (empty($new_comment['avatar'])) -{ - $name = !empty($new_comment['comment_author_name']) ? stripslashes($new_comment['comment_author_name']) : 'Guest'; - $new_comment['first_letter'] = mb_substr(trim($name), 0, 1, 'UTF-8'); - $new_comment['avatar_color_index'] = (abs(crc32($name)) % 12) + 1; -} + // 3. Если аватара нет — генерируем данные для буквы + if (empty($new_comment['avatar'])) + { + $name = !empty($new_comment['comment_author_name']) ? stripslashes($new_comment['comment_author_name']) : 'Guest'; + $new_comment['first_letter'] = mb_substr(trim($name), 0, 1, 'UTF-8'); + $new_comment['avatar_color_index'] = (abs(crc32($name)) % 12) + 1; + } $new_comment['comment_changed'] = 0; // Передаем флаги для мгновенной активации управления в шаблоне @@ -633,14 +647,16 @@ function commentPostEdit($comment_id) if ($comment_id <= 0 || $user_group <= 0) exit('INVALID_ID'); // 2. Получаем данные комментария и настройки модуля (JOIN) - // ДОБАВИЛ: cmnt.comment_edit_time в выборку SQL + // ДОБАВИЛ: выборку новых полей (allowed_extensions и max_file_size) $row = $AVE_DB->Query(" SELECT msg.*, cmnt.comment_max_chars, cmnt.comment_need_approve, cmnt.comment_user_groups, - cmnt.comment_edit_time + cmnt.comment_edit_time, + cmnt.comment_allowed_extensions, + cmnt.comment_max_file_size FROM " . PREFIX . "_module_comment_info AS msg JOIN " . PREFIX . "_module_comments AS cmnt ON cmnt.Id = 1 WHERE msg.Id = '" . $comment_id . "' @@ -655,12 +671,10 @@ function commentPostEdit($comment_id) $is_author = ($user_id > 0 && $user_id == $row['comment_author_id']) || ($row['comment_author_id'] == 0 && !empty($row['anon_key']) && $row['anon_key'] == $anon_key); - // ИСПРАВЛЕНО: Теперь берем лимит времени ПРЯМО из БД ($row), а не из переменной класса $time_limit = (isset($row['comment_edit_time'])) ? (int)$row['comment_edit_time'] : 60; $time_passed = time() - (int)$row['comment_published']; $is_time_ok = ($time_passed < $time_limit); - // Если не админ, проверяем: автор ли это и не вышло ли время if (!$is_admin) { if (!$is_author) exit('NOT_AUTHOR'); if (!$is_time_ok) { @@ -669,7 +683,7 @@ function commentPostEdit($comment_id) } } - // 4. Обработка текста (без изменений...) + // 4. Обработка текста $comment_text = $_POST['text'] ?? ''; $comment_text = preg_replace_callback('/&#x([0-9a-f]{1,7});/i', function($matches) { return chr(hexdec($matches[1])); }, $comment_text); @@ -683,30 +697,51 @@ function commentPostEdit($comment_id) $comment_text_cut = mb_substr($comment_text, 0, $max); if (mb_strlen($comment_text) > $max) $comment_text_cut .= '…'; - // 5. Работа с изображениями (без изменений...) - $new_file_sql = ""; - $upload_dir = BASE_DIR . '/uploads/comments/'; - if (isset($_FILES['comment_image']) && $_FILES['comment_image']['error'] == UPLOAD_ERR_OK) { +// 5. Работа с изображениями (С МАКСИМАЛЬНОЙ ЗАЩИТОЙ) +$new_file_sql = ""; +$upload_dir = BASE_DIR . '/uploads/comments/'; + +if (isset($_FILES['comment_image']) && $_FILES['comment_image']['error'] == UPLOAD_ERR_OK) { + + // Настройки из БД + $file_ext = strtolower(pathinfo($_FILES['comment_image']['name'], PATHINFO_EXTENSION)); + $allowed_ext_str = $row['comment_allowed_extensions'] ?? 'jpg,jpeg,png,gif,webp'; + $allowed_extensions = array_map('trim', explode(',', strtolower($allowed_ext_str))); + + $max_kb = (int)($row['comment_max_file_size'] ?? 2048); + $file_size = $_FILES['comment_image']['size']; + + // --- НОВОЕ: Проверка MIME-типа (защита от переименованных скриптов) --- + $finfo = finfo_open(FILEINFO_MIME_TYPE); + $mime = finfo_file($finfo, $_FILES['comment_image']['tmp_name']); + finfo_close($finfo); + + // ПРОВЕРКА: расширение + размер + MIME-тип + if (in_array($file_ext, $allowed_extensions) + && $file_size > 0 + && $file_size <= ($max_kb * 1024) + && strpos($mime, 'image/') === 0) // Файл действительно картинка + { if (!is_dir($upload_dir)) @mkdir($upload_dir, 0775, true); + // Удаляем старый файл, если он был if (!empty($row['comment_file']) && file_exists($upload_dir . $row['comment_file'])) { @unlink($upload_dir . $row['comment_file']); } - $file_ext = strtolower(pathinfo($_FILES['comment_image']['name'], PATHINFO_EXTENSION)); + // Генерируем новое имя $new_file_name = 'comm_' . time() . '_' . rand(100, 999) . '.' . $file_ext; if (move_uploaded_file($_FILES['comment_image']['tmp_name'], $upload_dir . $new_file_name)) { $new_file_sql = ", comment_file = '" . addslashes($new_file_name) . "'"; } - } - elseif (isset($_POST['delete_image']) && $_POST['delete_image'] == 1) { - if (!empty($row['comment_file']) && file_exists($upload_dir . $row['comment_file'])) { - @unlink($upload_dir . $row['comment_file']); - } - $new_file_sql = ", comment_file = ''"; + } else { + // Если файл не прошел серверную проверку + echo "FILE_ERROR"; + exit; } +} $user_rating = isset($_POST['user_rating']) ? (int)$_POST['user_rating'] : (int)$row['user_rating']; @@ -1281,6 +1316,11 @@ function commentAdminSettingsEdit($tpl_dir) // Настройки рейтинга и файлов $post_allow_files = $_POST['comment_allow_files'] ?? 0; $post_allow_files_anon = $_POST['comment_allow_files_anon'] ?? 0; + + /* НОВОЕ: Настройки расширений и максимального размера файла */ + $post_allowed_extensions = $_POST['comment_allowed_extensions'] ?? 'jpg,jpeg,png,gif'; + $post_max_file_size = $_POST['comment_max_file_size'] ?? 2048; + $post_rating_type = $_POST['comment_rating_type'] ?? 0; $post_show_user_rating = $_POST['comment_show_user_rating'] ?? 0; @@ -1308,9 +1348,12 @@ function commentAdminSettingsEdit($tpl_dir) { $max_chars = (empty($post_max_chars) || $post_max_chars < 50) ? 50 : $post_max_chars; - // Подготовка имен полей + // Подготовка имен полей и настроек файлов $clean_name_f1 = htmlspecialchars(stripslashes($post_name_f1), ENT_QUOTES); $clean_name_f2 = htmlspecialchars(stripslashes($post_name_f2), ENT_QUOTES); + + // Очищаем строку расширений от пробелов и лишних запятых + $clean_extensions = implode(',', array_filter(array_map('trim', explode(',', $post_allowed_extensions)))); $AVE_DB->Query(" UPDATE " . PREFIX . "_module_comments @@ -1325,6 +1368,11 @@ function commentAdminSettingsEdit($tpl_dir) comment_page_nav_count = '" . (int)$post_page_nav_count . "', comment_allow_files = '" . (int)$post_allow_files . "', comment_allow_files_anon = '" . (int)$post_allow_files_anon . "', + + /* СОХРАНЕНИЕ НОВЫХ ПОЛЕЙ */ + comment_allowed_extensions = '" . addslashes($clean_extensions) . "', + comment_max_file_size = '" . (int)$post_max_file_size . "', + comment_rating_type = '" . (int)$post_rating_type . "', comment_show_user_rating = '" . (int)$post_show_user_rating . "', comment_show_user_rating_replies = '" . (int)$post_show_user_rating_replies . "', diff --git a/js/comment.js b/js/comment.js index 38d32b9..7dcd031 100644 --- a/js/comment.js +++ b/js/comment.js @@ -89,6 +89,34 @@ function initCommentTimers() { // ВАЛИДАЦИЯ ПОЛЕЙ + // Функция для проверки файла (расширение и размер) + function checkFileConsistency(file, $errorDisplay) { + if (!file) return true; + + // Получаем настройки из шаблона (те переменные, что мы добавили в тег script) + var allowedExts = (typeof ALLOWED_EXTENSIONS !== 'undefined') ? ALLOWED_EXTENSIONS.toLowerCase().split(',') : ['jpg', 'jpeg', 'png', 'gif']; + var maxSizeKb = (typeof MAX_FILE_SIZE_KB !== 'undefined') ? parseInt(MAX_FILE_SIZE_KB) : 2048; + + var fileName = file.name.toLowerCase(); + var fileExt = fileName.split('.').pop(); + var fileSizeKb = file.size / 1024; + + // Проверка расширения + if ($.inArray(fileExt, allowedExts) === -1) { + $errorDisplay.text('Тип файла .' + fileExt + ' не разрешен.').removeClass('d-none'); + return false; + } + + // Проверка размера + if (fileSizeKb > maxSizeKb) { + $errorDisplay.text('Файл слишком большой (' + Math.round(fileSizeKb) + ' Кб). Максимум: ' + maxSizeKb + ' Кб').removeClass('d-none'); + return false; + } + + $errorDisplay.addClass('d-none').text(''); + return true; +} + function validate(form) { var isValid = true; @@ -127,6 +155,16 @@ function initCommentTimers() { // Проверка Текста setInvalid($(form.comment_text), !form.comment_text.value.trim(), "Введите текст комментария"); + // Проверка файла в основной форме +var $fileInput = $(form).find('#comment_image'); +if ($fileInput.length && $fileInput[0].files[0]) { + var isFileOk = checkFileConsistency($fileInput[0].files[0], $('#file_error')); + if (!isFileOk) { + $fileInput.addClass('is-invalid'); + isValid = false; + } +} + if (!isValid) { // Скроллим к первой ошибке $('html, body').animate({ @@ -189,18 +227,28 @@ function initCommentTimers() { // Счетчик: Количество оставшихся символов 1000 для формы создания комментария $('#in_message').limit(1000, '#charsLeft_new'); - // --- ЛОГИКА ПРЕДПРОСМОТРА ИЗОБРАЖЕНИЯ (НОВАЯ ФОРМА) --- - $doc.on('change', '#comment_image', function() { - var input = this; - if (input.files && input.files[0]) { - var reader = new FileReader(); - reader.onload = function(e) { - $('#image_preview_img').attr('src', e.target.result); - $('#image_preview_wrapper').removeClass('d-none'); - } - reader.readAsDataURL(input.files[0]); - } - }); +$doc.on('change', '#comment_image', function() { + var input = this; + var $errorBox = $('#file_error'); + + if (input.files && input.files[0]) { + // Сначала проверяем файл + if (!checkFileConsistency(input.files[0], $errorBox)) { + $(input).val('').addClass('is-invalid'); + $('#image_preview_wrapper').addClass('d-none'); + return; + } + + // Если файл прошел проверку — показываем превью + var reader = new FileReader(); + reader.onload = function(e) { + $('#image_preview_img').attr('src', e.target.result); + $('#image_preview_wrapper').removeClass('d-none'); + $(input).removeClass('is-invalid'); + } + reader.readAsDataURL(input.files[0]); + } +}); $doc.on('click', '#remove_image_btn', function() { $('#comment_image').val(''); @@ -418,24 +466,35 @@ $doc.on('mouseleave', '.rating-edit-block, #rating_wrapper', function() { `; } - var fileInputHtml = ''; - if (typeof UGROUP !== 'undefined' && (UGROUP != '2' || (typeof ALLOW_FILES_ANON !== 'undefined' && ALLOW_FILES_ANON == '1'))) { - fileInputHtml = ` -
- - -
-
- Превью - -
-
-
-
`; - } +var fileInputHtml = ''; +if (typeof UGROUP !== 'undefined' && (UGROUP != '2' || (typeof ALLOW_FILES_ANON !== 'undefined' && ALLOW_FILES_ANON == '1'))) { + // Получаем значения для подсказки (те же, что и в основной форме) + var allowedText = (typeof ALLOWED_EXTENSIONS !== 'undefined') ? ALLOWED_EXTENSIONS : 'jpg,jpeg,png,gif,webp'; + var sizeText = (typeof MAX_FILE_SIZE_KB !== 'undefined') ? MAX_FILE_SIZE_KB : '2048'; + + fileInputHtml = ` +
+ + +
+ Разрешены: ${allowedText}. + Макс. размер: ${sizeText} Кб. +
+ + +
+
+
+ Превью + +
+
+
+
`; +} var editHtml = `
@@ -461,22 +520,41 @@ $doc.on('mouseleave', '.rating-edit-block, #rating_wrapper', function() { $('#del_img_' + cid).prop('checked', true); // Помечаем скрытый чекбокс на удаление }); - // Обработка выбора НОВОГО файла при редактировании - $doc.on('change', 'input[id^="new_file_"]', function() { - var cid = $(this).attr('id').replace('new_file_', ''); - var input = this; - if (input.files && input.files[0]) { - var reader = new FileReader(); - reader.onload = function(e) { - $('#edit_preview_img_' + cid).attr('src', e.target.result); - $('#edit_preview_wrapper_' + cid).removeClass('d-none'); - // Если выбрали новый файл, старое превью логично скрыть - $('#existing_preview_wrapper_' + cid).addClass('d-none'); - $('#del_img_' + cid).prop('checked', true); - } - reader.readAsDataURL(input.files[0]); - } - }); +// Обработка выбора НОВОГО файла при редактировании +$doc.on('change', 'input[id^="new_file_"]', function() { + var cid = $(this).attr('id').replace('new_file_', ''); + var input = this; + + // Создаем или находим блок для ошибки + if ($('#file_error_' + cid).length === 0) { + $(input).after('
'); + } + var $errorBox = $('#file_error_' + cid); + + // Сбрасываем старые ошибки + $errorBox.addClass('d-none').text(''); + $(input).removeClass('is-invalid'); + + if (input.files && input.files[0]) { + // 1. Проверяем файл функцией checkFileConsistency + if (!checkFileConsistency(input.files[0], $errorBox)) { + $(input).val('').addClass('is-invalid'); + $('#edit_preview_wrapper_' + cid).addClass('d-none'); + $errorBox.removeClass('d-none'); + return; + } + + // 2. Если всё ОК — показываем превью + var reader = new FileReader(); + reader.onload = function(e) { + $('#edit_preview_img_' + cid).attr('src', e.target.result); + $('#edit_preview_wrapper_' + cid).removeClass('d-none'); + $('#existing_preview_wrapper_' + cid).addClass('d-none'); + $('#del_img_' + cid).prop('checked', true); + } + reader.readAsDataURL(input.files[0]); + } +}); // Удаление НОВОГО выбранного файла в режиме редактирования $doc.on('click', '.remove-edit-new-img', function() { diff --git a/sql.php b/sql.php index 82afc55..5a4106d 100644 --- a/sql.php +++ b/sql.php @@ -5,7 +5,8 @@ * * Обновленная структура с поддержкой выбора типа рейтинга, * идентификации анонимов, загрузки файлов и защиты по IP. - * ДОБАВЛЕНО: Настройка отображения авторской оценки в ответах. + * ДОБАВЛЕНО: Управление расширениями и максимальным размером файлов. + * СИНХРОНИЗАЦИЯ: Добавлен формат webp по умолчанию. */ $module_sql_install = array(); @@ -36,10 +37,10 @@ $module_sql_install[] = "CREATE TABLE `%%PRFX%%_module_comments` ( `comment_req_f2` tinyint(1) NOT NULL default '0', `comment_name_f2` varchar(255) NOT NULL default '', `comment_allow_files` tinyint(1) NOT NULL default '0', - `comment_file_max_size` int(10) NOT NULL default '2048', + `comment_allowed_extensions` varchar(255) NOT NULL default 'jpg,jpeg,png,gif,webp', + `comment_max_file_size` int(10) NOT NULL default '2048', `comment_rating_type` tinyint(1) NOT NULL default '0', `comment_show_user_rating` tinyint(1) NOT NULL default '0', - /* НОВОЕ ПОЛЕ: Показывать оценку автора в ответах */ `comment_show_user_rating_replies` tinyint(1) NOT NULL default '0', `comment_rating_anon_vote` tinyint(1) NOT NULL default '0', `comment_rating_anon_set` tinyint(1) NOT NULL default '0', @@ -49,7 +50,7 @@ $module_sql_install[] = "CREATE TABLE `%%PRFX%%_module_comments` ( PRIMARY KEY (`Id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8;"; -// Таблица info (без изменений авторской оценки, она уже есть: user_rating) +// Таблица info $module_sql_install[] = "CREATE TABLE `%%PRFX%%_module_comment_info` ( `Id` int(10) unsigned NOT NULL auto_increment, `parent_id` int(10) unsigned NOT NULL default '0', @@ -92,8 +93,8 @@ $module_sql_install[] = "CREATE TABLE `%%PRFX%%_module_comment_votes` ( KEY `remote_addr` (`remote_addr`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8;"; -/* Настройки по умолчанию (добавлено 0 перед 0, 0, 0, 60, 30) */ -$module_sql_install[] = "INSERT INTO `%%PRFX%%_module_comments` VALUES (1, 1000, '1,3', '1,2,3,4', '0', '1', '1' , '0', '', 1, 0, '', 1, 0, '', 0, 2048, 0, 1, 0, 0, 0, 0, 60, 30);"; +/* Настройки по умолчанию */ +$module_sql_install[] = "INSERT INTO `%%PRFX%%_module_comments` VALUES (1, 1000, '1,3', '1,2,3,4', '0', '1', '1' , '0', '', 1, 0, '', 1, 0, '', 0, 'jpg,jpeg,png,gif,webp', 2048, 0, 1, 0, 0, 0, 0, 60, 30);"; // ================================================================================= // 2. ОБНОВЛЕНИЕ МОДУЛЯ (ALTER TABLE) @@ -103,12 +104,13 @@ $module_sql_update[] = "ALTER TABLE `%%PRFX%%_module_comments` ADD COLUMN IF NOT $module_sql_update[] = "ALTER TABLE `%%PRFX%%_module_comments` ADD COLUMN IF NOT EXISTS `comment_cookie_life` INT(11) NOT NULL DEFAULT '30';"; $module_sql_update[] = "ALTER TABLE `%%PRFX%%_module_comments` ADD COLUMN IF NOT EXISTS `comment_rating_type` TINYINT(1) NOT NULL DEFAULT '0';"; $module_sql_update[] = "ALTER TABLE `%%PRFX%%_module_comments` ADD COLUMN IF NOT EXISTS `comment_show_user_rating` TINYINT(1) NOT NULL DEFAULT '0';"; - -/* Добавляем настройку отображения рейтинга автора в ответах */ $module_sql_update[] = "ALTER TABLE `%%PRFX%%_module_comments` ADD COLUMN IF NOT EXISTS `comment_show_user_rating_replies` TINYINT(1) NOT NULL DEFAULT '0';"; - $module_sql_update[] = "ALTER TABLE `%%PRFX%%_module_comments` ADD COLUMN IF NOT EXISTS `comment_rating_anon_vote` TINYINT(1) NOT NULL DEFAULT '0';"; $module_sql_update[] = "ALTER TABLE `%%PRFX%%_module_comments` ADD COLUMN IF NOT EXISTS `comment_rating_anon_set` TINYINT(1) NOT NULL DEFAULT '0';"; $module_sql_update[] = "ALTER TABLE `%%PRFX%%_module_comments` ADD COLUMN IF NOT EXISTS `comment_allow_files_anon` TINYINT(1) NOT NULL DEFAULT '0';"; +/* Новые поля для файлов при обновлении */ +$module_sql_update[] = "ALTER TABLE `%%PRFX%%_module_comments` ADD COLUMN IF NOT EXISTS `comment_allowed_extensions` VARCHAR(255) NOT NULL DEFAULT 'jpg,jpeg,png,gif,webp';"; +$module_sql_update[] = "ALTER TABLE `%%PRFX%%_module_comments` ADD COLUMN IF NOT EXISTS `comment_max_file_size` INT(10) NOT NULL DEFAULT '2048';"; + ?> \ No newline at end of file diff --git a/templates/admin_settings.tpl b/templates/admin_settings.tpl index 02b5680..41e5f4c 100644 --- a/templates/admin_settings.tpl +++ b/templates/admin_settings.tpl @@ -166,7 +166,6 @@  Включить "Авторские звезды" - {* Новая позиция для управления в ответах *} + + Допустимые расширения: + + + + Макс. размер файла (Кб): + + + KB + + diff --git a/templates/comments_tree.tpl b/templates/comments_tree.tpl index 6d5e4e1..b69ad5e 100644 --- a/templates/comments_tree.tpl +++ b/templates/comments_tree.tpl @@ -141,26 +141,34 @@ {#COMMENT_CHARS_LEFT#}

- {if $comment_allow_files == 1} - {if $smarty.session.user_group != '2' || $comment_allow_files_anon == 1} -
- - -
- Предпросмотр - -
-
-
-
-
-
-
-
- {/if} - {/if} +{if $comment_allow_files == 1} + {if $smarty.session.user_group != '2' || $comment_allow_files_anon == 1} +
+ + +
+ Разрешены: {$comment_allowed_extensions|default:'jpg, png, gif'}. + Макс. размер: {$comment_max_file_size|default:'2048'} Кб. +
+ + + +
+ Предпросмотр + +
+ +
+
+
+
+
+
+
+ {/if} +{/if} {if $im}
@@ -259,6 +267,9 @@ var SHOW_USER_RATING_REPLIES = '{$comment_show_user_rating_replies|default:0}'; var RATING_ANON_SET = '{$comment_rating_anon_set|default:0}'; var ALLOW_FILES_ANON = '{$comment_allow_files_anon|default:0}'; + // --- ПЕРЕМЕННЫЕ ДЛЯ ВАЛИДАЦИИ ФАЙЛОВ --- + var ALLOWED_EXTENSIONS = '{$comment_allowed_extensions|default:"jpg,jpeg,png,gif"}'; + var MAX_FILE_SIZE_KB = '{$comment_max_file_size|default:2048}';