при голосовании добавлена проверка связкой имя+IP

This commit is contained in:
2025-12-20 23:53:48 +05:00
parent cc9bb25a86
commit f7a4edbac3
2 changed files with 65 additions and 25 deletions

View File

@@ -779,16 +779,21 @@ function commentPostDelete($comment_id)
/**
* Метод для обработки голосования за комментарий
* Защита: ID для залогиненных, Пара (Ключ + IP) для анонимов.
*/
function commentVote()
{
global $AVE_DB;
// Принимаем данные
$comment_id = (int)($_POST['comment_id'] ?? 0);
$vote_value = (int)($_POST['vote'] ?? 0);
$ajax = (isset($_POST['ajax']) && $_POST['ajax'] == 1);
// IP пользователя
$user_ip = $_SERVER['REMOTE_ADDR'] ?? '';
// Базовая проверка значения (от 1 до 5 звезд)
// Базовая валидация
if ($comment_id <= 0 || $vote_value < 1 || $vote_value > 5) {
if ($ajax) {
if (ob_get_length()) ob_end_clean();
@@ -798,18 +803,18 @@ function commentPostDelete($comment_id)
return;
}
// 1. Идентификация пользователя
// 1. Идентификация текущего голосующего
$user_id = empty($_SESSION['user_id']) ? 0 : (int)$_SESSION['user_id'];
$anon_key = $this->_getAnonKey();
// 2. Получаем данные о комментарии (FetchRow исправлен)
$comment_data = $AVE_DB->Query("
SELECT comment_author_id, anon_key
// 2. Получаем данные о комментарии, за который голосуют
$comment_row = $AVE_DB->Query("
SELECT comment_author_id, anon_key, comment_author_ip
FROM " . PREFIX . "_module_comment_info
WHERE Id = '" . $comment_id . "'
")->FetchRow();
if (!$comment_data) {
if (!$comment_row) {
if ($ajax) {
if (ob_get_length()) ob_end_clean();
echo 'error';
@@ -818,10 +823,25 @@ function commentPostDelete($comment_id)
return;
}
// 3. Запрет голосовать за свой же комментарий
$c_author_id = (int)$comment_row->comment_author_id;
// 3. ПРОВЕРКА АВТОРСТВА (Запрет голосовать за свой же комментарий)
$is_author = false;
if ($user_id > 0 && $user_id == $comment_data->comment_author_id) $is_author = true;
if ($user_id == 0 && $anon_key == $comment_data->anon_key) $is_author = true;
if ($user_id > 0) {
// Если залогинен — проверяем только по ID
if ($user_id === $c_author_id) {
$is_author = true;
}
} else {
// Если аноним — проверяем парой (Ключ + IP)
// И только если автор комментария тоже был анонимом
if ($c_author_id === 0 &&
$anon_key === $comment_row->anon_key &&
$user_ip === $comment_row->comment_author_ip) {
$is_author = true;
}
}
if ($is_author) {
if ($ajax) {
@@ -832,12 +852,19 @@ function commentPostDelete($comment_id)
return;
}
// 4. Проверка на повторное голосование
$sql_check = "SELECT id FROM " . PREFIX . "_module_comment_votes WHERE comment_id = '" . $comment_id . "' AND ";
// 4. ПРОВЕРКА ПОВТОРНОГО ГОЛОСОВАНИЯ
// Ищем в истории, голосовал ли уже этот человек
if ($user_id > 0) {
$sql_check .= "user_id = '" . $user_id . "'";
// Для авторизованных поиск по ID
$sql_check = "SELECT id FROM " . PREFIX . "_module_comment_votes
WHERE comment_id = '" . $comment_id . "'
AND user_id = '" . $user_id . "'";
} else {
$sql_check .= "anon_key = '" . $anon_key . "'";
// Для анонимов поиск по связке Ключ + IP
$sql_check = "SELECT id FROM " . PREFIX . "_module_comment_votes
WHERE comment_id = '" . $comment_id . "'
AND anon_key = '" . $anon_key . "'
AND remote_addr = '" . $user_ip . "'";
}
if ($AVE_DB->Query($sql_check)->GetCell()) {
@@ -849,15 +876,20 @@ function commentPostDelete($comment_id)
return;
}
// 5. Записываем голос в лог
// 5. ЗАПИСЬ ГОЛОСА В ЛОГ
$AVE_DB->Query("
INSERT INTO " . PREFIX . "_module_comment_votes
(comment_id, user_id, anon_key, vote_value, date_voted)
(comment_id, user_id, anon_key, remote_addr, vote_value, date_voted)
VALUES
('" . $comment_id . "', '" . $user_id . "', '" . $anon_key . "', '" . $vote_value . "', '" . time() . "')
('" . $comment_id . "',
'" . $user_id . "',
'" . $AVE_DB->escape($anon_key) . "',
'" . $AVE_DB->escape($user_ip) . "',
'" . $vote_value . "',
'" . time() . "')
");
// 6. Обновляем агрегированные данные
// 6. ОБНОВЛЕНИЕ АГРЕГАТОВ В ТАБЛИЦЕ INFO
$AVE_DB->Query("
UPDATE " . PREFIX . "_module_comment_info
SET rating_sum = rating_sum + " . $vote_value . ",
@@ -865,9 +897,9 @@ function commentPostDelete($comment_id)
WHERE Id = '" . $comment_id . "'
");
// 7. ФИНАЛ: Очищаем мусор и отдаем чистый ответ
// 7. ФИНАЛ: Чистый ответ для JS
if ($ajax) {
if (ob_get_length()) ob_end_clean(); // Выбрасываем все Warning-и и HTML
if (ob_get_length()) ob_end_clean();
echo 'success';
exit;
}

20
sql.php
View File

@@ -4,7 +4,7 @@
* AVE.cms - Модуль Комментарии
*
* Обновленная структура с поддержкой рейтинга (звезд),
* идентификации анонимных пользователей и загрузки файлов.
* идентификации анонимных пользователей, загрузки файлов и защиты по IP.
*/
$module_sql_install = array();
@@ -48,7 +48,7 @@ $module_sql_install[] = "CREATE TABLE `%%PRFX%%_module_comment_info` (
`comment_author_email` varchar(255) NOT NULL,
`comment_author_city` varchar(255) NOT NULL,
`comment_author_website` varchar(255) NOT NULL,
`comment_author_ip` varchar(15) NOT NULL,
`comment_author_ip` varchar(45) NOT NULL, /* Увеличено для поддержки IPv6 */
`anon_key` varchar(32) DEFAULT NULL,
`comment_published` int(10) unsigned NOT NULL default '0',
`comment_changed` int(10) unsigned NOT NULL default '0',
@@ -66,18 +66,20 @@ $module_sql_install[] = "CREATE TABLE `%%PRFX%%_module_comment_info` (
KEY `anon_key` (`anon_key`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 PACK_KEYS=0;";
// Таблица для хранения истории голосов (защита от повторов)
// Таблица для хранения истории голосов (Добавлено поле remote_addr для защиты по IP)
$module_sql_install[] = "CREATE TABLE `%%PRFX%%_module_comment_votes` (
`id` int(10) unsigned NOT NULL auto_increment,
`comment_id` int(10) unsigned NOT NULL,
`user_id` int(10) unsigned DEFAULT '0',
`anon_key` varchar(32) DEFAULT '',
`remote_addr` varchar(45) DEFAULT '', /* Поле для хранения IP проголосовавшего */
`vote_value` tinyint(1) NOT NULL,
`date_voted` int(10) unsigned NOT NULL,
PRIMARY KEY (`id`),
KEY `comment_id` (`comment_id`),
KEY `anon_key` (`anon_key`),
KEY `user_id` (`user_id`)
KEY `user_id` (`user_id`),
KEY `remote_addr` (`remote_addr`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;";
$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);";
@@ -99,19 +101,25 @@ $module_sql_update[] = "
// Добавляем поля рейтинга в существующую таблицу
$module_sql_update[] = "ALTER TABLE `%%PRFX%%_module_comment_info` ADD `rating_sum` INT(10) NOT NULL DEFAULT '0';";
$module_sql_update[] = "ALTER TABLE `%%PRFX%%_module_comment_info` ADD `rating_count` INT(10) NOT NULL DEFAULT '0';";
$module_sql_update[] = "ALTER TABLE `%%PRFX%%_module_comment_info` MODIFY `comment_author_ip` VARCHAR(45) NOT NULL;";
// Создаем таблицу голосов, если её еще нет
// Создаем таблицу голосов с полем IP, если её еще нет
$module_sql_update[] = "CREATE TABLE IF NOT EXISTS `%%PRFX%%_module_comment_votes` (
`id` int(10) unsigned NOT NULL auto_increment,
`comment_id` int(10) unsigned NOT NULL,
`user_id` int(10) unsigned DEFAULT '0',
`anon_key` varchar(32) DEFAULT '',
`remote_addr` varchar(45) DEFAULT '',
`vote_value` tinyint(1) NOT NULL,
`date_voted` int(10) unsigned NOT NULL,
PRIMARY KEY (`id`),
KEY `comment_id` (`comment_id`),
KEY `anon_key` (`anon_key`),
KEY `user_id` (`user_id`)
KEY `user_id` (`user_id`),
KEY `remote_addr` (`remote_addr`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;";
// Если таблица уже была, но поля remote_addr в ней нет — добавляем его
$module_sql_update[] = "ALTER TABLE `%%PRFX%%_module_comment_votes` ADD COLUMN IF NOT EXISTS `remote_addr` VARCHAR(45) DEFAULT '' AFTER `anon_key`;";
?>