Next Generation CMS :: Форум поддержки

Заинтересовала наша система? Тогда этот форум для Вас!

Вы не зашли.

#1 2011-10-12 21:19:01

ikv777vlg
Участник
Откуда Волгоград
Зарегистрирован: 2011-10-10
Сообщений: 137
Рейтинг :   

Защита от накруток в плагине rating, запись IP-адреса юзера в БД

Привет всем! smile
У меня такой вопрос - а как доработать плагин рейтинга новостей, чтобы он не только сохранял печеньку в браузере незарегистрированного юзера когда он проголосует за новость, но и сохранял в базе данных его IP, например там я хз.. - (127.0.0.1 | news id : 346 | news id : 347 | news id : 29) т.е если я правильно понимаю нужно создать таблицу в которой будут записываться IP голосовавших юзеров и ID всех новостей за которые они голосовали.
Или наоборот, в таблице с новостью создать ячейку, куда будут записываться IP голосовавших за нее, и потом читать оттуда. Как лучше - не знаю, как реализовать - тоже не знаю sad
В связи с этим возникают вопросы, на сколько при этом увеличится нагрузка на сервер и размер БД, если, например, посетителей больше 1k и большое количество новостей?

Просьба сильно не пинать, ну не учился я на программиста, есть только минимальнейшие теоретические знания PHP, смотрю я в код rating.php и непонятно что к чему.. yikes
А желание сделать есть, подскажите как чего, тем-более кто-то на форуме этот вопрос пытался поднять, но безрезультатно, или я плохо искал... smile


З.Ы. использую версию Next Generation CMS 0.9.2 Release [SVN646], если что smile

Изменено ikv777vlg (2011-10-12 22:05:45)

Не в сети

#2 2011-10-12 21:59:07

ikv777vlg
Участник
Откуда Волгоград
Зарегистрирован: 2011-10-10
Сообщений: 137
Рейтинг :   

Re: Защита от накруток в плагине rating, запись IP-адреса юзера в БД

Просто у меня есть желание сделать сайт где рейтинг новостей будет практически главным смыслом сайта.

Экспериментально я правил некоторые файлы для достижения нужного результата, и всё вроде работает, что именно правил уже всё не вспомню, кучу файлов, изменения стилей, и т.д. big_smile

Вот, например в rating.form.tpl вот так я изменил принцип голосования:

<a href="#" title="Ужасно" class="b-none" onclick="rating('1', '{post_id}'); alert('Большое спасибо! Ваш голос принят!'); return false;"><img src="{home}/templates/default/img/z1.png" width="70px" height="70px" alt="Ужасно"/></a>
<a href="#" title="Плохо" class="b-none" onclick="rating('25', '{post_id}'); alert('Большое спасибо! Ваш голос принят!'); return false;"><img src="{home}/templates/default/img/z2.png" width="70px" height="70px" alt="Плохо"/></a> 
<a href="#" title="Удовлетворительно" class="b-none" onclick="rating('50', '{post_id}'); alert('Большое спасибо! Ваш голос принят!'); return false;"><img src="{home}/templates/default/img/z3.png" width="70px" height="70px" alt="Удовлетворительно"/></a>
<a href="#" title="Хорошо" class="b-none" onclick="rating('75', '{post_id}'); alert('Большое спасибо! Ваш голос принят!'); return false;"><img src="{home}/templates/default/img/z4.png" width="70px" height="70px" alt="Хорошо"/></a> 
<a href="#" title="Отлично" class="b-none" onclick="rating('100', '{post_id}'); alert('Большое спасибо! Ваш голос принят!'); return false;"><img src="{home}/templates/default/img/z5.png" width="70px" height="70px" alt="Отлично"/></a>

хотя алерт можно вынести в функцию, чтобы 5 раз не писать, и класс можно было упростить на .divclass a{стили} но это пока не критично, я думаю smile

и в rating.php я изменил значение максимальной оценки с 5 до 100:

	// Security protection - limit rating values between 1..5
	$rating = intval($_REQUEST['rating']);
	$post_id = intval($_REQUEST['post_id']);
	if (($rating <1)||($rating >100)) {
		return 'incorrect rating';
	}

В итоге, рейтинг новости в шаблоне теперь имеет числовой вывод оценки, оценка от 1 до 100 - вроде то что нужно smile

Но... что же это за рейтинг такой, проголосовал, очистил куки, опять проголосовал, надо подшаманить как-то... yikes

Не в сети

#3 2011-10-12 23:48:37

ikv777vlg
Участник
Откуда Волгоград
Зарегистрирован: 2011-10-10
Сообщений: 137
Рейтинг :   

Re: Защита от накруток в плагине rating, запись IP-адреса юзера в БД

И с ходу, еще вопрос. smile В rating.php есть участок кода:

	// Ok, everything is fine. Let's update rating.

	@setcookie('rating'.$post_id, 'voted', (time() + 31526000), '/');
	is_array($row = $mysql->record("select * from ".prefix."_news where id = ".db_squote($post_id)));

у меня вопрос, зачем здесь нужна строка

is_array($row = $mysql->record("select * from ".prefix."_news where id = ".db_squote($post_id)));

какие функции она выполняет?? roll

Не в сети

#4 2011-10-13 00:15:08

ROZARD
Модератор
Откуда Россия, Астрахань
Зарегистрирован: 2008-10-13
Сообщений: 1,523
Рейтинг :   82 
Сайт

Re: Защита от накруток в плагине rating, запись IP-адреса юзера в БД

Данной проверки в месте где записывает куки я не нашел, данная проверка идет в начале и просто проверяет новость на наличие...

Не в сети

#5 2011-10-13 00:27:53

ikv777vlg
Участник
Откуда Волгоград
Зарегистрирован: 2011-10-10
Сообщений: 137
Рейтинг :   

Re: Защита от накруток в плагине rating, запись IP-адреса юзера в БД

Точно... Это в версии 0.9.2. Я сейчас открыл файл rating.php в архиве 0.9.3 Release Candidate 0 [SVN834], там этой строчки уже нет, однако. Я так и понял что она была лишняя big_smile

Тогда я возьму обновленный плагин из дистрибутива 0.9.3 Release Candidate 0 [SVN834] и буду шаманить его, если найду какие-нибудь баги - сообщу wink

Но, мой вопрос пока остается открытым, кто что может подсказать по этому поводу - излагайте свои мысли smile, и сам я тоже попробую как-нибудь плагин поковырять, заодно может и PHP выучу и научусь с БД работать big_smile

Не в сети

#6 2011-10-13 08:01:01

ikv777vlg
Участник
Откуда Волгоград
Зарегистрирован: 2011-10-10
Сообщений: 137
Рейтинг :   

Re: Защита от накруток в плагине rating, запись IP-адреса юзера в БД

Пока сам не сделаешь - никто не поможет hmm

Короче, я создал таблицу с названием ng_rating, в ней создал две строки,  IP и News_ID.
Чуть-чуть подшаманил файл rating.php, теперь он выдает в шаблон что-то подобное: Рейтинг: 82%.  42 голоса. Изменения слов - голоса, голосов, голос, это я реализовал прямо в rating.php, ключевым моментом является функция ipcheck, которая принимает 3 параметра ($mysql, $post_id, $upd), где $upd: параметр 0 - изменения в БД не вносятся, а только проверяется наличие IP в базе, и проверяется голосовал ли юзер за эту новость;
параметр 1 - всё так-же проверяется, но если юзер не голосовал - в БД вносится его IP и ID новости, и в следующий раз он проголосовать не сможет, даже с отключенными куками.
Функция возвращает 2 параметра:
fail - юзер уже голосовал за определенную новость
ok - юзер не голосовал за эту новость, хотя походу этот параметр я зря создал, используется только "fail" хз smile

Вот сам rating.php как он выглядит у меня:

<?php

// Protect against hack attempts
if (!defined('NGCMS')) die ('HAL');


function ruslang($votes) {
	$votes2=substr($votes, strlen($votes)-1,1);
	if($votes=="11" ||$votes=="12" ||$votes=="13" ||$votes=="14" || $votes2=="0" || $votes2=="5" || 
	$votes2=="6" || $votes2=="7" || $votes2=="8" || $votes2=="9"){$golosov="голосов";}
 elseif($votes2=="1"){$golosov="голос";}
 elseif($votes2=="2" || $votes2=="3" || $votes2=="4"){$golosov="голоса";}
	if($votes=="0"){$votes="Нет";}
 return $votes." ".$golosov;
}


 function ipcheck ($mysql, $post_id, $upd) {
 /* Сначала ищем IP в базе, голосовал-ли юзер вообще */
	if($mysql->record("select ip from ".prefix."_rating where ip = '".$_SERVER['REMOTE_ADDR']."'")) {
	/* IP найден > Далее ищем ID новости в базе, по найденному IP */
 if($mysql->record("select ip from ".prefix."_rating where ip = '".$_SERVER['REMOTE_ADDR']."' and (locate('|".str_replace("'", "", $post_id)."|', News_ID)>0)")) {
 return "fail";
	}
	else { /* ID новости не найден, юзер с этим IP голосует за эту новость */
if($upd){$mysql->query("update ".prefix."_rating set News_ID=concat(News_ID, '".str_replace("'", "", str_replace("'", "", $post_id))."|') where IP = '".$_SERVER['REMOTE_ADDR']."'");}
return "ok";
	} 
}
	else { /* Юзер еще ни разу не голосовал, его IP не найден. Создаем новую строку в таблице с его IP и новостью */
if($upd){$mysql->query("INSERT INTO ".prefix."_rating set ip='".$_SERVER['REMOTE_ADDR']."', News_ID = '|".str_replace("'", "", $post_id)."|'");}
return "ok";
}
}

		
	$show=0; // забыл зачем это нужно xD
	
	

function plugin_rating_update(){  // начинается функция апдейта рейтинга
	global $mysql, $tpl, $userROW;
	
	LoadPluginLang('rating', 'site');
		

	// Security protection - limit rating values between 1..100 :)
	$rating = intval($_REQUEST['rating']);
	$post_id = intval($_REQUEST['post_id']);
	if (($rating <1)||($rating >100)) {
		return 'incorrect rating';
	}

	// Check if referred news exists
	if (!is_array($row = $mysql->record("select * from ".prefix."_news where id = ".db_squote($post_id)))) {
		return 'Referred news not found';
	}

	// Check if we try to make a duplicated rate
 	if ($_COOKIE['rating'.$row['id']] || ipcheck($mysql, db_squote($post_id), 0)=="fail")
		return 'Вы уже голосовали!';

	// Check if we feet "register only" limitation
	if (extra_get_param('rating','regonly') && !is_array($userROW)) {
		return 'only registered users can rate news';
	}

	// Ok, everything is fine. Let's update rating.

	@setcookie('rating'.$post_id, 'voted', (time() + 31526000), '/');
	ipcheck ($mysql, db_squote($post_id), 1); 
	$data = $mysql->record("select rating, votes from ".prefix."_news where id = ".db_squote($post_id));
	$mysql->query("update ".prefix."_news set rating=rating+".$rating.", votes=votes+1 where id = ".db_squote($post_id));
	


 


	
	
	
	
	
	$localskin = extra_get_param('rating', 'localskin');
	if (!$localskin) $localskin='basic';
	$tpath = locatePluginTemplates(array('rating', ':rating.css'), 'rating', extra_get_param('rating', 'localsource'), $localskin);
	register_stylesheet($tpath['url::rating.css'].'/rating.css'); 

	$tvars['vars']['tpl_url'] = $tpath['url::rating.css'];
	$tvars['vars']['home'] = home;
	$tvars['vars']['rating'] = (($data['rating']+$rating) == 0) ? 0 : round((($data['rating']+$rating) / ($data['votes']+1)), 0);
	
 $tvars['vars']['votes']=ruslang(($data['votes']+1)); // супер-функция

	$tpl -> template('rating', $tpath['rating']);
	$tpl -> vars('rating', $tvars);
	return $tpl -> show('rating');
}





function rating_show($newsID, $rating, $votes, $show){
	global $mysql, $tpl, $userROW;

	LoadPluginLang('rating', 'site');
	$localskin = extra_get_param('rating', 'localskin');
	if (!$localskin) $localskin='basic';

	$tpath = locatePluginTemplates(array('rating', 'rating.form', ':rating.css'), 'rating', extra_get_param('rating', 'localsource'), $localskin);
	register_stylesheet($tpath['url::rating.css'].'/rating.css');
	 
	
	$tvars['vars']['tpl_url'] = $tpath['url::rating.css'];
	$tvars['vars']['home'] = home;
	$tvars['vars']['ajax_url'] = generateLink('core', 'plugin', array('plugin' => 'rating'), array());

	$tvars['vars']['post_id'] = $newsID;
	$tvars['vars']['rating'] = (!$rating || !$votes) ? 0 : round(($rating / $votes), 0);
  
 $tvars['vars']['votes']=ruslang($votes); // супер-функция


	if ((isset($_COOKIE['rating'.$newsID]) && $_COOKIE['rating'.$newsID]) || (extra_get_param('rating','regonly') && !is_array($userROW)) || $show==1 || ipcheck($mysql, $newsID, 0)=="fail") {
		// Show
		$tpl -> template('rating', $tpath['rating']);
		$tpl -> vars('rating', $tvars);
		return $tpl -> show('rating');
	} else {
		// Edit
		$tpl -> template('rating.form', $tpath['rating.form']);
		$tpl -> vars('rating.form', $tvars);
		return $tpl -> show('rating.form');
	}
	return;
}

function plugin_rating_screen(){
	global $SUPRESS_TEMPLATE_SHOW, $template;

	@header('Content-type: text/html; charset="windows-1251"');
	if ($_REQUEST['post_id']) {
		$template['vars']['mainblock'] = plugin_rating_update();
		$SUPRESS_TEMPLATE_SHOW = 1;
	} else {
		$template['vars']['mainblock'] = 'unsupported action';
	}
}

//
// ”Ё«мва ­®ў®б⥩ (¤«п Ї®Є §  ३⨭Ј )
//
class RatingNewsFilter extends NewsFilter {
	function showNews($newsID, $SQLnews, &$tvars, $mode = array()) {
		global $tpl, $mysql, $userROW;

		$tvars['vars']['plugin_rating'] = rating_show($SQLnews['id'],$SQLnews['rating'],$SQLnews['votes'],0);
		

		
		
		$tvars['vars']['rating'] = rating_show($SQLnews['id'],$SQLnews['rating'],$SQLnews['votes'],1);

	}
}	


register_filter('news','raing', new RatingNewsFilter);
register_plugin_page('rating','','plugin_rating_screen',0);

код грязнейший, но работает, всю ночь гуглил и писал big_smile Вопросов еще много остается...
Еще несколько правок, и можно официально обновлять плагин, вся соль в ipcheck()! cool

Вот, как-то так, комментируем, обсуждаем...  Очень волнует нагрузка на сервер при таких подходах, хз что будет roll

Не в сети

#7 2011-10-13 11:11:26

ROZARD
Модератор
Откуда Россия, Астрахань
Зарегистрирован: 2008-10-13
Сообщений: 1,523
Рейтинг :   82 
Сайт

Re: Защита от накруток в плагине rating, запись IP-адреса юзера в БД

Что то ты намудрил smile

if($upd){
	$mysql->query("update ".prefix."_rating set News_ID=concat(News_ID, '".str_replace("'", "", str_replace("'", "", $post_id))."|') where IP = '".$_SERVER['REMOTE_ADDR']."'");
}

Тут нужно добавлять запись, а не обновлять у первой попавшейся записи News_ID

И проверку голосовал человек с таким то IP за такую то новость можно сделать один запросом и не делать кучу условий...
Зачем locate?
Зачем concat?

Добавь global $ip; И тогда не придется писать $_SERVER['REMOTE_ADDR'], а просто $ip
Индексы добавил на News_ID, IP? И хорошо бы очищать эту таблицу от старых IP чтобы не перегружать.

Не в сети

#8 2011-10-13 11:55:44

Wolverine
Модератор
Откуда Домодедово
Зарегистрирован: 2008-10-13
Сообщений: 3,538
Рейтинг :   160 
Сайт

Re: Защита от накруток в плагине rating, запись IP-адреса юзера в БД

ROZARD пишет:

Что то ты намудрил smile

if($upd){
	$mysql->query("update ".prefix."_rating set News_ID=concat(News_ID, '".str_replace("'", "", str_replace("'", "", $post_id))."|') where IP = '".$_SERVER['REMOTE_ADDR']."'");
}

Тут нужно добавлять запись, а не обновлять у первой попавшейся записи News_ID

Все верно сделал, у него запись имеет структуру "IP, СПИСОК_ID_НОВОСТЕЙ_ЧЕРЕЗ_РАЗДЕЛИТЕЛЬ"

Не в сети

#9 2011-10-13 12:01:55

ROZARD
Модератор
Откуда Россия, Астрахань
Зарегистрирован: 2008-10-13
Сообщений: 1,523
Рейтинг :   82 
Сайт

Re: Защита от накруток в плагине rating, запись IP-адреса юзера в БД

Тогда я извиняюсь за своё не знание locate, concat smile

Не в сети

#10 2011-10-13 18:33:05

ikv777vlg
Участник
Откуда Волгоград
Зарегистрирован: 2011-10-10
Сообщений: 137
Рейтинг :   

Re: Защита от накруток в плагине rating, запись IP-адреса юзера в БД

ROZARD пишет:

Добавь global $ip; И тогда не придется писать $_SERVER['REMOTE_ADDR'], а просто $ip

Не знал, исправлю wink

ROZARD пишет:

Индексы добавил на News_ID, IP? И хорошо бы очищать эту таблицу от старых IP чтобы не перегружать.

Я об этом тоже подумал, надо это обязательно как-то реализовать, но как - пока непонятно...

Wolverine, да, через разделитель. При первом запросе с нового IP, функция создает в индексе
IP=127.0.0.1, News_ID=|24| где 24 - id новости, за который голосует юзер с IP 127.0.0.1, т.е. добавляет в ячейку News_ID идентификатор новости с символами "|" по бокам - |24|.
А если же юзер с этим-же IP голосует за другую новость, информация в таблице обновляется таким образом - добавляется ID текущей новости, и символ "|" только справа 25| и получается |24|25|26|139|4| и т.д.
И по этому в таблице все ID новостей будут иметь по бокам эти символы "|" - |139|, |25|, и т.д.
Это как-бы справка для всех новых посетителей форума, чтобы было понятно как это работает, может кому пригодится. wink

С разделителем придумал сам, а вот решение с locate и concat я нагло слизал с какого-то сайта, и даже не допер до конца зачем оно big_smile

Не в сети

#11 2011-10-13 20:29:48

ikv777vlg
Участник
Откуда Волгоград
Зарегистрирован: 2011-10-10
Сообщений: 137
Рейтинг :   

Re: Защита от накруток в плагине rating, запись IP-адреса юзера в БД

Так, ну это я делал для себя, а теперь для сообщества wink

Вот цивильный, модифицированный rating.php:
(для использования, просто замените содержимое rating.php на это)

<?php

// Protect against hack attempts
if (!defined('NGCMS')) die ('HAL');


/* проверка IP  -  START */	
	function ipcheck ($post_id, $upd) {
 global $ip, $mysql;
	/* Сначала ищем IP в базе, голосовал-ли юзер вообще */
	if($mysql->record("select ip from ".prefix."_rating where ip = '".$ip."'")) {
	/* IP найден > Далее ищем ID новости в базе, по найденному IP */
 if($mysql->record("select ip from ".prefix."_rating where ip = '".$ip."' and (locate('|".str_replace("'", "", $post_id)."|', News_ID)>0)")) {
 return "fail";
	}
	else { /* ID новости не найден, юзер с этим IP голосует за эту новость */
if($upd){$mysql->query("update ".prefix."_rating set News_ID=concat(News_ID, '".str_replace("'", "", str_replace("'", "", $post_id))."|') where IP = '".$ip."'");}
return "ok";
	} 
}
	else { /* Юзер еще ни разу не голосовал, его IP не найден. Создаем новую строку в таблице с его IP и новостью */
if($upd){$mysql->query("INSERT INTO ".prefix."_rating set ip='".$ip."', News_ID = '|".str_replace("'", "", $post_id)."|'");}
return "ok";
}
}
/* проверка IP  -  END */	


function plugin_rating_update(){
	global $mysql, $tpl, $userROW;

	LoadPluginLang('rating', 'site');
	
		// Security protection - limit rating values between 1..5
	$rating = intval($_REQUEST['rating']);
	$post_id = intval($_REQUEST['post_id']);
	if (($rating <1)||($rating >5)) {
		return 'incorrect rating';
	}

	// Check if referred news exists
	if (!is_array($row = $mysql->record("select * from ".prefix."_news where id = ".db_squote($post_id)))) {
		return 'referred news not found';
	}

	// Check if we try to make a duplicated rate
	if ($_COOKIE['rating'.$row['id']] || ipcheck(db_squote($post_id), 0)=="fail")  // изменение 1
		return 'you already made your rate';

	// Check if we feet "register only" limitation
	if (extra_get_param('rating','regonly') && !is_array($userROW)) {
		return 'only registered users can rate news';
	}


	// Ok, everything is fine. Let's update rating.

	@setcookie('rating'.$post_id, 'voted', (time() + 31526000), '/');
	$mysql->query("update ".prefix."_news set rating=rating+".$rating.", votes=votes+1 where id = ".db_squote($post_id));
	$data = $mysql->record("select rating, votes from ".prefix."_news where id = ".db_squote($post_id));
	ipcheck (db_squote($post_id), 1); // изменение 2

	$localskin = extra_get_param('rating', 'localskin');
	if (!$localskin) $localskin='basic';
	$tpath = locatePluginTemplates(array('rating', ':rating.css'), 'rating', extra_get_param('rating', 'localsource'), $localskin);
	register_stylesheet($tpath['url::rating.css'].'/rating.css'); 

	$tvars['vars']['tpl_url'] = $tpath['url::rating.css'];
	$tvars['vars']['home'] = home;
	$tvars['vars']['rating'] = ($data['rating'] == 0) ? 0 : round(($data['rating'] / $data['votes']), 0);
	$tvars['vars']['votes'] = $data['votes'];

	$tpl -> template('rating', $tpath['rating']);
	$tpl -> vars('rating', $tvars);
	return $tpl -> show('rating');
}

function rating_show($newsID, $rating, $votes){
	global $tpl, $userROW;

	LoadPluginLang('rating', 'site');
	$localskin = extra_get_param('rating', 'localskin');
	if (!$localskin) $localskin='basic';

	$tpath = locatePluginTemplates(array('rating', 'rating.form', ':rating.css'), 'rating', extra_get_param('rating', 'localsource'), $localskin);
	register_stylesheet($tpath['url::rating.css'].'/rating.css'); 
	
	$tvars['vars']['tpl_url'] = $tpath['url::rating.css'];
	$tvars['vars']['home'] = home;
	$tvars['vars']['ajax_url'] = generateLink('core', 'plugin', array('plugin' => 'rating'), array());

	$tvars['vars']['post_id'] = $newsID;
	$tvars['vars']['rating'] = (!$rating || !$votes) ? 0 : round(($rating / $votes), 0);
	$tvars['vars']['votes'] = $votes;

	if ((isset($_COOKIE['rating'.$newsID]) && $_COOKIE['rating'.$newsID]) || (extra_get_param('rating','regonly') && !is_array($userROW)) || ipcheck($newsID, 0)=="fail") { // изменение 3
		// Show
		$tpl -> template('rating', $tpath['rating']);
		$tpl -> vars('rating', $tvars);
		return $tpl -> show('rating');
	} else {
		// Edit
		$tpl -> template('rating.form', $tpath['rating.form']);
		$tpl -> vars('rating.form', $tvars);
		return $tpl -> show('rating.form');
	}
	return;
}

function plugin_rating_screen(){
	global $SUPRESS_TEMPLATE_SHOW, $template;

	@header('Content-type: text/html; charset="windows-1251"');
	if ($_REQUEST['post_id']) {
		$template['vars']['mainblock'] = plugin_rating_update();
		$SUPRESS_TEMPLATE_SHOW = 1;
	} else {
		$template['vars']['mainblock'] = 'unsupported action';
	}
}

//
// ”Ё«мва ­®ў®б⥩ (¤«п Ї®Є §  ३⨭Ј )
//
class RatingNewsFilter extends NewsFilter {
	function showNews($newsID, $SQLnews, &$tvars, $mode = array()) {
		global $tpl, $mysql, $userROW;

		$tvars['vars']['plugin_rating'] = rating_show($SQLnews['id'],$SQLnews['rating'],$SQLnews['votes']);
	}
}	


register_filter('news','raing', new RatingNewsFilter);
register_plugin_page('rating','','plugin_rating_screen',0);

Тестировал на NG CMS 0.9.3 Release Candidate 0 [SVN834], но и в  0.9.2 у меня тоже всё работает tongue
Если кому не трудно, протестируйте на хосте, а то на локалке не интересно!! И киньте ссылку пожалуйста, у меня IP динамический, я потестирую тоже, с отключенными куками. wink

--------------------------

А теперь вопросы...
Во первых, почему в файле <?php в конце не закрыт(?>), это так задумано, или просто забыли? На сколько я знаю, <?php закрывать не обязательно, но надо-же, наверное, для цивильности big_smile

Во вторых, вопрос про БД... Я конечно извиняюсь, но какие типы данных использовать для полей IP и News_ID, если учитывать что в IP будет храниться IP, а в News_ID может храниться длиннющий список идентификаторов новостей с разделителями? (прикрепил скриншот)

И третий вопрос, один из самых важных, как организовать удаление старых записей из БД? Если юзер проголосовал, ему ставится печенька на год, я правильно понял? Так я думаю за год в базе скопится слишком много, СЛИШКОМ МНОГО IP-адресов с идентификаторами... Так-что я думаю, месяца 2-3 вполне хватит, потом ID у этого IP можно удалять, а если кончились ID, то и IP мы удаляем. Мысль ясна? big_smile
Как это реализовать - непонятно.. Помогите!


Далее, я конечно дико извиняюсь за то что не в тему, но после чистой установки  NG CMS 0.9.3 Release Candidate 0 [SVN834] на денвер, сразу заметил несколько багов..
1) Внизу в админке не работают кнопки добавить новость и редактировать
2) Ссылки Сделать стартовой | Добавить в избранное в опере 11.51 не работают, но у меня есть скрипт для этого дела, работает в осле, лисе, опере, но в хроме не работает, а просто выводит алерт с текстом "нажмите ctrl+d", если что - могу найти wink
3) В админке при добавлении новости, или при добавлении коммента на сайте смайлы не вставляются, хотя ББ-коды вставляются нормально neutral

У меня в 0.9.2 смайлы и бб-коды тоже отвалились почему-то только в комментах, я отключил комменты, и заюзал социальный плагин "комментарии" от вконтакте, и нормально big_smile
Вот так..

Изменено ikv777vlg (2011-10-13 20:50:52)

Не в сети

#12 2011-10-13 20:59:32

ikv777vlg
Участник
Откуда Волгоград
Зарегистрирован: 2011-10-10
Сообщений: 137
Рейтинг :   

Re: Защита от накруток в плагине rating, запись IP-адреса юзера в БД

Ах да, забыл.. Все строки return "ok"; из функции ipcheck() можно удалить, оно не надо smile

Не в сети

#13 2011-10-13 21:00:57

ROZARD
Модератор
Откуда Россия, Астрахань
Зарегистрирован: 2008-10-13
Сообщений: 1,523
Рейтинг :   82 
Сайт

Re: Защита от накруток в плагине rating, запись IP-адреса юзера в БД

ikv777vlg пишет:

А теперь вопросы...
Во первых, почему в файле <?php в конце не закрыт(?>), это так задумано, или просто забыли? На сколько я знаю, <?php закрывать не обязательно, но надо-же, наверное, для цивильности big_smile

Без него проще...

ikv777vlg пишет:

Во вторых, вопрос про БД... Я конечно извиняюсь, но какие типы данных использовать для полей IP и News_ID, если учитывать что в IP будет храниться IP, а в News_ID может храниться длиннющий список идентификаторов новостей с разделителями? (добавил вложение)

Для IP подойдет varchar(15), а для News_ID text должно хватить...

ikv777vlg пишет:

И третий вопрос, один из самых важных, как организовать удаление старых записей из БД? Если юзер проголосовал, ему ставится печенька на год, я правильно понял? Так я думаю за год в базе скопится слишком много, СЛИШКОМ МНОГО IP-адресов с идентификаторами... Так-что я думаю, месяца 2-3 вполне хватит, потом ID у этого IP можно удалять, а если кончились ID, то и IP мы удаляем. Мысль ясна? big_smile
Как это реализовать - непонятно.. Помогите!

Добавить ещё одно поле date куда при добавлении будет добавляться время и сравнивать разницу и по ней удалять, но при твоей структуре с этим проблематично получится) Я думаю лучше добавить кнопку чтобы можно было нажать и вся таблица очиститься)

Не в сети

#14 2011-10-13 21:34:04

ikv777vlg
Участник
Откуда Волгоград
Зарегистрирован: 2011-10-10
Сообщений: 137
Рейтинг :   

Re: Защита от накруток в плагине rating, запись IP-адреса юзера в БД

ROZARD пишет:

Без него проще...

Сэкономить лишние 2 символа в принципе тоже правильно, хоть и бессмысленно big_smile
Ладно, с этим разобрались.

ROZARD пишет:

Для IP подойдет varchar(15), а для News_ID text должно хватить...

text точно хватит? Даже если, допустим при 1000 новостей, у меня просто голова кругом от этих типов данных yikes

ROZARD пишет:

Добавить ещё одно поле date куда при добавлении будет добавляться время и сравнивать разницу и по ней удалять, но при твоей структуре с этим проблематично получится)

А как по другому? Так вроде бы оптимальнее всего, но я согласен, придется всё переписывать, и создавать новые поля, и куда-нибудь вставлять даты. Надо подумать... hmm

ROZARD пишет:

Я думаю лучше добавить кнопку чтобы можно было нажать и вся таблица очиститься)

А кнопку нажимать после того как сервер упадет от высокой нагрузки, и хостер забанит? Шучу я конечно lol
Нет, надо как-то автоматически это реализовать.

Поле date.. это мысль конечно. Синхронно с ID новости в другое поле через разделитель писать timestamp или сразу дд-мм-гггг? И синхронно читать? А размер БД увеличится в таком случае, это же сколько timestamp`ов придется писать в таблицу... yikes
Если делать так, то как связать IP+ID с датой?
А как считать, а как сравнить даты чтобы узнать что прошло больше 2-х месяцев, я не пойму.


Буду думать, может еще кто что подскажет roll

Не в сети

#15 2011-10-13 21:52:51

ROZARD
Модератор
Откуда Россия, Астрахань
Зарегистрирован: 2008-10-13
Сообщений: 1,523
Рейтинг :   82 
Сайт

Re: Защита от накруток в плагине rating, запись IP-адреса юзера в БД

ikv777vlg пишет:
ROZARD пишет:

Без него проще...

Сэкономить лишние 2 символа в принципе тоже правильно, хоть и бессмысленно big_smile
Ладно, с этим разобрались.

Дело не в символах, а если после этого знака вставишь случайно символ у тебя будут проблемы с хеадором и отсюда уже другие проблемы и была как то темя связанная с безопасность...

ikv777vlg пишет:
ROZARD пишет:

Для IP подойдет varchar(15), а для News_ID text должно хватить...

text точно хватит? Даже если, допустим при 1000 новостей, у меня просто голова кругом от этих типов данных yikes

Тогда наверняка longtext он поддерживает объем чуть больше 4 миллиардов)

По поводу даты лучше тогда через условие:

if('ДАТА_ПОСЛЕ_КОТОРОЙ НУЖНО ОЧИСТИТЬ ТАБЛИЦУ' <= 'ВРЕМЯ_В ДАННЫЙ МОМЕНТ')
     $mysql->query("delete from ".prefix."_rating");

Не в сети

#16 2011-10-13 22:23:08

vitaly
Администратор
Откуда Россия
Зарегистрирован: 2008-10-08
Сообщений: 2,823
Рейтинг :   118 

Re: Защита от накруток в плагине rating, запись IP-адреса юзера в БД

ikv777vlg пишет:

Во первых, почему в файле <?php в конце не закрыт(?>), это так задумано, или просто забыли? На сколько я знаю, <?php закрывать не обязательно, но надо-же, наверное, для цивильности big_smile

Оставленный после "?>" пробел создаёт массу проблем и его визуально не видно.
Уже были преценденты, после этого во всех файлах целенаправленно данный символ был убран.

ikv777vlg пишет:

Во вторых, вопрос про БД... Я конечно извиняюсь, но какие типы данных использовать для полей IP и News_ID, если учитывать что в IP будет храниться IP, а в News_ID может храниться длиннющий список идентификаторов новостей с разделителями? (прикрепил скриншот)

Imho, правильней хранить данные о каждом голосе.
newsID, userID, IP, voteDate
для незарегенного юзера userID будет нулевым.
тогда и проблема очистки будет решаться намного проще и конфликтов вида "двое нажали одновременно на <голосовать>, но только один из голосов появился в таблице" (если несколько человек сидят на одном сайте за NAT'ом) не будет


ikv777vlg пишет:

И третий вопрос, один из самых важных, как организовать удаление старых записей из БД? Если юзер проголосовал, ему ставится печенька на год, я правильно понял? Так я думаю за год в базе скопится слишком много, СЛИШКОМ МНОГО IP-адресов с идентификаторами... Так-что я думаю, месяца 2-3 вполне хватит, потом ID у этого IP можно удалять, а если кончились ID, то и IP мы удаляем. Мысль ясна? big_smile
Как это реализовать - непонятно.. Помогите!

см. п. 2.

Не в сети

#17 2011-10-13 23:35:21

ikv777vlg
Участник
Откуда Волгоград
Зарегистрирован: 2011-10-10
Сообщений: 137
Рейтинг :   

Re: Защита от накруток в плагине rating, запись IP-адреса юзера в БД

На счет "<?php" и "?>" - убедили, учту на будущее, спасибо! smile

vitaly пишет:

Imho, правильней хранить данные о каждом голосе.
newsID, userID, IP, voteDate
для незарегенного юзера userID будет нулевым.
тогда и проблема очистки будет решаться намного проще и конфликтов вида "двое нажали одновременно на <голосовать>, но только один из голосов появился в таблице" (если несколько человек сидят на одном сайте за NAT'ом) не будет

Вот, озадачил... smile У меня просто возможность регистрации запрещена, по этому я не обращаю внимание на залогиненность юзера smile
Допустим.. Если мы храним в voteDate timestamp.

Если я правильно понял - в таблице мы имеем такие строки(timestamp и IP - для наглядного примера):
______________________________________
| newsID | userID |        IP       |   voteDate   |
|    45            0         127.0.0.1    789000001  |
|    49            0         127.0.0.1    789000004  |
|    41           67        127.0.0.1    789000007  |
|    41            0         127.0.0.8    789000008  |
|_____________________________________|

Хорошо, допустим я сделал скрипт, который сохраняет инфу в БД о каждом голосе, как я показал выше..
Если, например условно считать что timestamp равный 789000008 - это сегодня и сейчас, а 789000004 - это ровно 2 месяца назад, соответственно 789000001 - это более 2-х месяцев назад, 789000007 - это около месяца.
Скрипт должен найти и удалить все строки с меньшим или равным 789000004 timestamp в поле voteDate.

Вопрос: как составить такой запрос к БД?? yikes

Не в сети

#18 2011-10-13 23:41:10

Wolverine
Модератор
Откуда Домодедово
Зарегистрирован: 2008-10-13
Сообщений: 3,538
Рейтинг :   160 
Сайт

Re: Защита от накруток в плагине rating, запись IP-адреса юзера в БД

Вот кусок из who_online

# clear old records
	if (pluginGetVariable('who_online', 'last_clear') < time() - intval(pluginGetVariable('who_online', 'time_clear'))){
		$mysql->query('DELETE FROM `'.prefix.'_online` WHERE `lasttime` < '.$tm.';');
		pluginSetVariable('who_online', 'last_clear', time());
		pluginsSaveConfig();
	}

где pluginGetVariable('who_online', 'last_clear') - время последней очистки БД
     pluginGetVariable('who_online', 'time_clear') - промежуток времени в секундах, спустя который включается очистка, чтобы не производить ее постоянно. Раз в день вполне сойдет.
     $tm = time() - intval(pluginGetVariable('who_online', 'timeout')); - все записи меньше этого промежутка будут очищены,

Не в сети

#19 2011-10-14 00:17:41

ikv777vlg
Участник
Откуда Волгоград
Зарегистрирован: 2011-10-10
Сообщений: 137
Рейтинг :   

Re: Защита от накруток в плагине rating, запись IP-адреса юзера в БД

Wolverine, вот по моему это мне и нужно

WHERE `lasttime` < '.$tm.';'

Я просто не знал что так, с условием "больше меньше или равно", можно сделать запрос к базе данных! roll
Попробую реализовать... tongue

Не в сети

#20 2011-10-14 00:42:00

vitaly
Администратор
Откуда Россия
Зарегистрирован: 2008-10-08
Сообщений: 2,823
Рейтинг :   118 

Re: Защита от накруток в плагине rating, запись IP-адреса юзера в БД

ikv777vlg, можно.
а дату хранить в формате datetime (либо int), при insert'е туда просто писать now() (либо time() из php)

Плюс не помешает тогда уж сохранить значение голоса человека (что он там навыбирал) и вуаля smile

Не в сети

#21 2011-10-14 01:13:37

ikv777vlg
Участник
Откуда Волгоград
Зарегистрирован: 2011-10-10
Сообщений: 137
Рейтинг :   

Re: Защита от накруток в плагине rating, запись IP-адреса юзера в БД

vitaly пишет:

а дату хранить в формате datetime (либо int), при insert'е туда просто писать now() (либо time() из php)

Если написать echo now(); то я вижу

Fatal error: Call to undefined function now() in Z:\home\c2.ru\www\engine\plugins\rating\rating.php on line 44

Нету такой функции smile
Походу версии PHP не сошлись, а time() - естественно работает, его и заюзаю.

Не в сети

#22 2011-10-14 01:23:53

ROZARD
Модератор
Откуда Россия, Астрахань
Зарегистрирован: 2008-10-13
Сообщений: 1,523
Рейтинг :   82 
Сайт

Re: Защита от накруток в плагине rating, запись IP-адреса юзера в БД

ikv777vlg, now() пишется в самом запросе...

Не в сети

#23 2011-10-14 01:40:06

ikv777vlg
Участник
Откуда Волгоград
Зарегистрирован: 2011-10-10
Сообщений: 137
Рейтинг :   

Re: Защита от накруток в плагине rating, запись IP-адреса юзера в БД

ROZARD пишет:

ikv777vlg, now() пишется в самом запросе...

Не знал...
Можно и time(), только придется писать ".time()." а now() нужно без кавычек, и использоваться он может только при запросе к БД mysql... Надеюсь что я правильно понял smile

А now() и time() выдают один и тот-же результат - timestamp? Не "дд-мм-гггг"? (я просто еще не дошел до этого участка кода, не могу проверить)

Не в сети

#24 2011-10-14 08:43:51

ikv777vlg
Участник
Откуда Волгоград
Зарегистрирован: 2011-10-10
Сообщений: 137
Рейтинг :   

Re: Защита от накруток в плагине rating, запись IP-адреса юзера в БД

Ну вот smile
Я не стал искать проблем на причинное место, и решил не выходить за пределы моей функции ipcheck(), и всё реализовать в ней, и вот что получилось:

function ipcheck ($news_id, $upd) {
global $ip, $mysql, $userROW;
	/* Ищем в базе строку с текущими IP, User ID и News ID */
	if($mysql->record("select * from ".prefix."_rating where user_id='".intval(is_array($userROW))."' and news_id='".$news_id."' and ip='".$ip."'")) {
	return true; /* Юзер уже голосовал за эту новость, возвращаем истину */
	}
 else { 
	/* Юзер еще не голосовал за эту новость, если параметр $upd = 1 голосуем и возвращаем ложь(на всякий случай), 
	а если $upd = 0 не голосуем, просто возвращаем ложь и в БД ничего не изменяем */
 if($upd){
	$mysql->query('DELETE FROM `'.prefix.'_rating` WHERE `vote_date` < '.(time()-5184000).';'); // удаляем старые записи
 // далее голосуем
	$mysql->query("INSERT INTO ".prefix."_rating set user_id='".intval(is_array($userROW))."', vote_date=".time().", ip='".$ip."', news_id='".$news_id."'");
	}
	return false;
}
}

Она удаляет за собой старые записи в БД(более 2-х месяцев)!!! tongue

Структуру таблицы ng_rating, которую использует эта функция, можно посмотреть в прикрепленном скриншоте.
Везде кроме IP я решил использовать INT(11), я думаю что этого хватит за глаза smile


Если я где-то ошибся - поправьте меня!
А вот мне интересно, (по совету Wolverine) при каждом успешном голосовании выполняется

$mysql->query('DELETE FROM `'.prefix.'_rating` WHERE `vote_date` < '.(time()-5184000).';');

Правильно ли это? Не создаст лишнюю нагрузку?

Не в сети

#25 2011-10-14 10:21:14

Wolverine
Модератор
Откуда Домодедово
Зарегистрирован: 2008-10-13
Сообщений: 3,538
Рейтинг :   160 
Сайт

Re: Защита от накруток в плагине rating, запись IP-адреса юзера в БД

Создаст конечно, я же написал, что производить очистку оптимально раз в день, каждый раз делать удаление смысла нет, особенно если голосуют активно, так как после первого удаления запрос будет работать практически вхолостую, ничего уже не удаляя.

Не в сети

Подвал раздела

Работает на FluxBB