From 1fe7a99e98d2a59a228e4abd6a25ff90525cbe62 Mon Sep 17 00:00:00 2001 From: Repellent Date: Sat, 3 Jan 2026 21:39:48 +0500 Subject: [PATCH] =?UTF-8?q?=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B0=20=D0=B7=D0=B0=D0=B3=D1=80=D1=83=D0=B7=D0=BA=D0=B0?= =?UTF-8?q?=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 | 35 +++++---- js/comment.js | 129 +++++++++++++++++++------------- templates/comments_tree.tpl | 2 +- templates/comments_tree_sub.tpl | 68 ++++++++++++----- 4 files changed, 150 insertions(+), 84 deletions(-) diff --git a/class/comment.php b/class/comment.php index 301671c..5360040 100644 --- a/class/comment.php +++ b/class/comment.php @@ -648,17 +648,19 @@ function commentPostFormShow($tpl_dir) $mime = finfo_file($finfo, $file['tmp_name']); finfo_close($finfo); - if (in_array($ext, $allowed_extensions) - && $file['size'] > 0 - && $file['size'] <= $max_file_size_bytes - && strpos($mime, 'image/') === 0) - { - $new_name = time() . '_' . rand(100, 999) . '.' . $ext; - if (move_uploaded_file($file['tmp_name'], $upload_path . $new_name)) { - $uploaded_files[] = $new_name; - $processed_hashes[] = $file_hash; - } - } +// Проверки расширения и безопасности +$is_allowed_ext = in_array($ext, $allowed_extensions); +$is_dangerous = in_array($ext, ['php', 'php3', 'php4', 'php5', 'phtml', 'exe', 'pl', 'cgi']); + +// Условие: расширение разрешено, файл не опасен и проходит по размеру +if ($is_allowed_ext && !$is_dangerous && $file['size'] > 0 && $file['size'] <= $max_file_size_bytes) +{ + $new_name = time() . '_' . rand(100, 999) . '.' . $ext; + if (move_uploaded_file($file['tmp_name'], $upload_path . $new_name)) { + $uploaded_files[] = $new_name; + $processed_hashes[] = $file_hash; + } +} } } @@ -850,17 +852,18 @@ function commentPostEdit($comment_id) $mime = finfo_file($finfo, $tmp_name); finfo_close($finfo); - if (in_array($file_ext, $allowed_extensions) - && $file_size > 0 - && $file_size <= ($max_kb * 1024) - && strpos($mime, 'image/') === 0) + // Проверки расширения и опасных файлов + $is_allowed_ext = in_array($file_ext, $allowed_extensions); + $is_dangerous = in_array($file_ext, ['php', 'php3', 'php4', 'php5', 'phtml', 'exe', 'pl', 'cgi']); + + if ($is_allowed_ext && !$is_dangerous && $file_size > 0 && $file_size <= ($max_kb * 1024)) { if (!is_dir($upload_dir)) @mkdir($upload_dir, 0775, true); $new_file_name = 'comm_' . time() . '_' . rand(1000, 9999) . '.' . $file_ext; if (move_uploaded_file($tmp_name, $upload_dir . $new_file_name)) { - $current_files[] = $new_file_name; // Добавляем новый файл к списку + $current_files[] = $new_file_name; } } } diff --git a/js/comment.js b/js/comment.js index 3545308..edc1abb 100644 --- a/js/comment.js +++ b/js/comment.js @@ -494,33 +494,39 @@ $doc.off('click', '.mod_comment_edit').on('click', '.mod_comment_edit', function var cleanText = $textBlock.html().replace(//mg, "\n").trim(); -// --- СБОР ТЕКУЩИХ КАРТИНОК (ТОЧНЫЙ ПОИСК ПО КОНТЕЙНЕРУ) --- +// --- СБОР ТЕКУЩИХ ВЛОЖЕНИЙ --- var existingImagesHtml = ''; - -// Ищем картинки строго внутри контейнера вложений конкретного комментария var $imageContainer = $('#image_container_' + cid); -var $foundImgs = $imageContainer.find('img'); -if ($foundImgs.length > 0) { - existingImagesHtml = '
'; +// Ищем именно "карточки" из твоего шаблона (класс .comment-image-item) +var $foundItems = $imageContainer.find('.comment-image-item'); + +if ($foundItems.length > 0) { + existingImagesHtml = '
'; - $foundImgs.each(function(index) { - var imgSrc = $(this).attr('src'); - if (!imgSrc) return; + $foundItems.each(function(index) { + var $item = $(this); + var $link = $item.find('a'); + var fileUrl = $link.attr('href'); + if (!fileUrl) return; + + var fileName = fileUrl.split('/').pop(); + var fileExt = fileName.split('.').pop().toLowerCase(); + var isImg = ['jpg', 'jpeg', 'png', 'gif', 'webp'].includes(fileExt); + + // Используем твой же стиль превью + var previewContent = isImg + ? `` + : `
${fileExt}
`; - // Извлекаем имя файла из пути для передачи на сервер - var fileName = imgSrc.split('/').pop(); - existingImagesHtml += `
- + ${previewContent}
`; }); @@ -566,7 +572,7 @@ var editHtml = `
- +
@@ -577,9 +583,14 @@ var editHtml = `
`; - $textBlock.hide(); - $attachedImagesBlock.hide(); - $foundImgs.hide(); +// Прячем текст комментария +$textBlock.hide(); + +// Прячем ВЕСЬ контейнер с оригиналами (и картинки, и упрямый ZIP) +$('#image_container_' + cid).attr('style', 'display: none !important;'); + +// Для надежности скрываем всё остальное +$wrapper.find('.mod_comment_attached_images, .comment-files').hide(); $textBlock.after(editHtml); @@ -592,14 +603,10 @@ $('#new_file_' + cid).on('change', function() { var files = this.files; var $input = $(this); var $currentEditForm = $input.closest('.edit-form-container'); - - // ИЩЕМ ТОЛЬКО ПО КЛАССУ ОТНОСИТЕЛЬНО ИНПУТА - var $errorDisplay = $input.prev('.js-file-error'); - + var $errorDisplay = $currentEditForm.find('.js-file-error'); var maxLimit = parseInt(typeof MAX_FILES_COUNT !== 'undefined' ? MAX_FILES_COUNT : 5); if (files) { - // Очищаем при каждом новом выборе $errorDisplay.text('').hide(); $.each(files, function(i, file) { @@ -607,17 +614,17 @@ $('#new_file_' + cid).on('change', function() { var inPending = pendingFiles.filter(f => f !== null).length; if ((alreadyInPost + inPending) >= maxLimit) { - // ВЫВОДИМ ТЕКСТ - $errorDisplay.text(' Лимит: ' + maxLimit + ' шт. Лишние файлы проигнорированы.').show(); - - $input.val(''); + $errorDisplay.text(' Лимит: ' + maxLimit + ' шт.').show(); return false; } - if (!file.type.match('image.*')) return true; + // ПРОВЕРКА ЧЕРЕЗ ФУНКЦИЮ (она теперь берет ALLOWED_EXTENSIONS) + if (!checkFileConsistency(file, $errorDisplay)) return true; pendingFiles.push(file); var currentIndex = pendingFiles.length - 1; + var fileExt = file.name.split('.').pop().toLowerCase(); + var isImage = ['jpg', 'jpeg', 'png', 'gif', 'webp'].includes(fileExt); var reader = new FileReader(); reader.onload = function(e) { @@ -626,15 +633,23 @@ $('#new_file_' + cid).on('change', function() { $input.after(`
`); $previewContainer = $('#new_files_preview_' + cid); } + + var content = isImage + ? `` + : `
${fileExt}
`; + $previewContainer.append(`
- + ${content}
`); }; - reader.readAsDataURL(file); + + if (isImage) reader.readAsDataURL(file); + else reader.onload({target: {result: ''}}); }); } }); @@ -730,18 +745,23 @@ $doc.on('change', 'input[id^="new_file_"]', function() { // Обработка кнопки "Отмена" при редактировании $doc.on('click', '.cancelButton', function() { var $container = $(this).closest('.edit-form-container'); - // Находим главную обертку этого конкретного комментария var $wrapper = $container.closest('[id^="comment_wrapper_"]'); + var cid = $container.data('cid'); // Берем ID для обращения к контейнеру файлов // 1. Возвращаем текст $wrapper.find('.mod_comment_text').show(); // 2. Возвращаем оригинальный блок с картинками - // Ищем все возможные варианты названий блоков, которые мы скрывали - $wrapper.find('.mod_comment_attached_image, .comment-files, .attached-images').show(); + // СНАЧАЛА ЧИСТИМ ИНЛАЙН СТИЛЬ (тот самый !important) + $('#image_container_' + cid).attr('style', ''); + + // Затем стандартный показ + $wrapper.find('.mod_comment_attached_image, .mod_comment_attached_images, .comment-files, .attached-images').show(); // 3. Если мы скрывали изображения напрямую через $foundImgs.hide(), показываем их $wrapper.find('img').show(); + // И ссылки (наш ZIP) тоже на всякий случай + $wrapper.find('a').show(); // 4. Удаляем форму редактирования $container.remove(); @@ -837,19 +857,28 @@ $doc.off('change', '#comment_image').on('change', '#comment_image', function() { var currentIndex = newCommentPendingFiles.length - 1; var reader = new FileReader(); - reader.onload = function(e) { - if ($previewWrapper.find(`[data-index="${currentIndex}"]`).length > 0) return; +reader.onload = function(e) { + if ($previewWrapper.find(`[data-index="${currentIndex}"]`).length > 0) return; - $previewWrapper.removeClass('d-none'); - $previewWrapper.append(` -
- - -
`); - }; + // Определяем, что вставить: картинку или заглушку с текстом расширения + var fileExt = file.name.split('.').pop().toLowerCase(); + var isImage = ['jpg', 'jpeg', 'png', 'gif', 'webp'].includes(fileExt); + + // Формируем контент: либо твой оригинальный img, либо блок с расширением + var content = isImage + ? `` + : `
${fileExt}
`; + + $previewWrapper.removeClass('d-none'); + $previewWrapper.append(` +
+ ${content} + +
`); +}; reader.readAsDataURL(file); }); } diff --git a/templates/comments_tree.tpl b/templates/comments_tree.tpl index ff246b3..4662942 100644 --- a/templates/comments_tree.tpl +++ b/templates/comments_tree.tpl @@ -281,7 +281,7 @@ 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 ALLOWED_EXTENSIONS = '{$comment_allowed_extensions|default:"jpg,jpeg,png,gif,webp"}'; var MAX_FILE_SIZE_KB = '{$comment_max_file_size|default:2048}'; var MAX_FILES_COUNT = '{$comment_max_files|default:5}'; diff --git a/templates/comments_tree_sub.tpl b/templates/comments_tree_sub.tpl index a0d1c24..bdbc601 100644 --- a/templates/comments_tree_sub.tpl +++ b/templates/comments_tree_sub.tpl @@ -64,24 +64,58 @@ {/if} -{* Вывод изображения (ИСПРАВЛЕНО ДЛЯ MULTIPLE) *} - {if !empty($c.comment_file)} -
- {assign var="photos" value=","|explode:$c.comment_file} - {foreach from=$photos item=photo} - {if $photo|trim} -
- - Изображение - -
- {/if} - {/foreach} +{* Вывод файлов (Картинки ПЕРВЫМИ, остальное в КОНЦЕ) *} +{if !empty($c.comment_file)} +
+ {assign var="all_files" value=","|explode:$c.comment_file} + {assign var="img_exts" value=['jpg', 'jpeg', 'png', 'gif', 'webp']} + + {* 1. Сначала выводим только ИЗОБРАЖЕНИЯ *} + {foreach from=$all_files item=file} + {assign var="f_name" value=$file|trim} + {if $f_name} + {assign var="ext_parts" value="."|explode:$f_name} + {assign var="f_ext" value=$ext_parts[$ext_parts|@count-1]|lower} + + {if in_array($f_ext, $img_exts)} + - {/if} + {/if} + {/if} + {/foreach} + + {* 2. Затем выводим все ОСТАЛЬНЫЕ файлы *} + {foreach from=$all_files item=file} + {assign var="f_name" value=$file|trim} + {if $f_name} + {assign var="ext_parts" value="."|explode:$f_name} + {assign var="f_ext" value=$ext_parts[$ext_parts|@count-1]|lower} + + {if !in_array($f_ext, $img_exts)} + + {/if} + {/if} + {/foreach} +
+{/if}