Записи Alex’а |
| Автор блога: |
![]() |
Все рубрики (4) |
![]() |
Анти-спам (1) |
|
+9
|
|
Файл, который правим: /components/users/messages.php
Что требует улучшения: SQL-запрос, отвечающий за выгрузку входящих сообщений (примерно 28 строка в 1.7RC и примерно 50 в 1.6.*): Код PHP:
$sql = "SELECT m.*, m.senddate as fpubdate, m.from_id as sender_id, u.nickname as author, u.login as author_login, u.is_deleted, p.imageurl
FROM cms_user_msg m
LEFT JOIN cms_users u ON m.from_id = u.id
LEFT JOIN cms_user_profiles p ON m.from_id = p.user_id
WHERE m.to_id = $id
ORDER BY senddate DESC
LIMIT ".(($page-1)*$perpage).", $perpage";
16 комментариев
сообщения, оптимизация бд, 1.7
|
|
+8
|
|
Файл, который мы правим: /includes/bbcode/bbcode.lib.php
При использование бб-тэгов ’email’ в комменатриях возникает следующая ошибка Warning: call_user_func(bbcode::email_2html) [function.call-user-func]: First argument is expected to be a valid callback in /путь/includes/bbcode/bbcode.lib.php on line 981 Ошибка в том, что для email используется обработчик email_2html, однако его просто нет в этом файле. Код PHP: Поэтому мы его быстро допишем: 'email' => array(
'handler' => 'email_2html',
'is_close' => false,
'lbr' => 0,
'rbr' => 0,
'ends' => array('*','align','code','video', 'audio', 'hide','h1','h2','h3','hr',
'list','php','quote','table','td','th','tr'),
'permission_top_level' => true,
'children' => array('b','color','email','font','i','img',
'nobb','s','size','sub','sup','tt','u')
),Код PHP: Вставить это код можно после любого из других обработчиков, например после: function email_2html($elem) {
return '<a href="mailto:'.$this -> get_html($elem['val']).'">'.$this -> get_html($elem['val']).'</a>';
}Код PHP: // Функция - обработчик тега [u]
function u_2html($elem) {
return '<u>'.$this -> get_html($elem['val']).'</u>';
} |
|
+10
|
|
Предыдущая теоретическая тут.
В этой статье рассмотрен наиболее простой способ ограждения юзеров от спама, а именно введение captcha (блокировка отправки сообщений) при жалобах от других пользователей. А также введение captcha при слишком частой отправке. 1. Итак, первое с чего нужно начать, добавить в таблицу с юзерам столбец Spam_detected. Выполняем следующий SQL-запрос Код PHP:
Данное поле будет иметь в нашем случае целочисленный тип.ALTER TABLE cms_users ADD COLUMN spam_detected INT NOT NULL AFTER is_deleted -100 – для администраторов и, например, модераторов, чтобы их случайно не зафильтровать. 0 – означает, что юзер не спаммер. 1 – означает, что есть подозрения, что юзер спаммер (мера воздействия отсутствует) 2 – считаем, что юзер спаммер (мера воздействия: включаем капачи) 4 – считаем, что юзер злостный спаммер (мера воздействия: отключаем возможность писать сообщения) По дефолту полю spam_detected можно назначить либо 0, либо 1. 2. Создаем таблицу cms_user_abuse (жалобы одного пользователя на другого) (id, from_user, to_user, spamdate, msg_id, type, description). from_user – кто пожаловался to_user – на кого пожаловались spamdate – время жалобы msg_id – id мессаги, которую расценили, как спам. Type – это тип жалобы, сразу можно предусмотреть например жалобы не только на спам, но и на мат и т.д. description – в этом поле также можно принимать описание юзера, на что он конкретно жалуется. Выполняем следующий SQL-запрос: Код PHP:
CREATE TABLE IF NOT EXISTS `cms_user_abuse` ( `id` int(11) NOT NULL AUTO_INCREMENT, `from_user` int(11) NOT NULL, `to_user` int (11) NOT NULL, `spamdate` datetime NOT NULL, `msg_id` int(11) NOT NULL, `type` int(11) NOT NULL DEFAULT '1', `description` varchar(200) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=cp1251_general_ci AUTO_INCREMENT=1 3. (необязательно, дабы не перегружать статью все операции над таблицей убраны) Создаем таблицу cms_user_spammer (id, id_user, reg_mail, date_spam, ip, description) Тут, думаю, все понятно. Вообще, стоит добавить, что спаммеры бывает 3-ёх типов. 1) Аккаутн специально созданный для спама 2) Пользователя взломали 3) Пользователь-идиот, который верит в письма счастья и т.д. Ясно, что первых сразу стоит банить, отсылать письмо провайдеру с указанием IP и удалять из таблицы. 2-ой и 3-ий тип нужно заносить в таблицу, чтобы в случае повтора их банить. 4. Добавляем каждому пользователю кнопку для жалоб и обработчики. 4.1. Кнопка в профиль. 4.2. Кнопку к каждой мессаге. 4.3. Кнопка к комментариям. В данной статье мы ограничимся только кнопкой к мессагам, так как она самая сложная, имхо. Все остальные делают аналогично. Остальное делается аналогично. 4.2.1. Начнем с user/frontend.php Допишем туда: Код PHP: 4.2.2. Допишем в user/router.php
/////////////////////////////// SMAP ///////////////////////////////////////////////////////////////////////
if ($do=='spammessage'){
if (usrCheckAuth()){
$sql = "SELECT * FROM cms_user_msg WHERE id = '$id' LIMIT 1";
$result = $inDB->query($sql) ;
if ($inDB->num_rows($result)){
$msg = $inDB->fetch_assoc($result);
if ($msg['to_id']==$inUser->id){
//записываем сообщение в таблицу cms_user_abuse
$message_admin = $msg['message'];
$sql = "INSERT INTO cms_user_abuse (from_user, to_user, spamdate, msg_id, description)
VALUES (".$msg['to_id'].", ".$msg['from_id'].", NOW(), '$id', '$message_admin' )";
$inDB->query($sql) ;
//повышаем уровень spam_detected для отославшего юзера
$inDB->query("UPDATE cms_users SET spam_detected = spam_detected + 1 WHERE id = ".$msg['from_id']." LIMIT 1");
$message_admin ="СПАМ!
[url=/users/".$msg['from_id']."/messages-sent.html]Тут[/url] можно посмотреть исходящие сообщения потенциального спаммера!
--------------------------------------------
".$msg['message']."
--------------------------------------------";
//отсылаем уведомлению админу
$sql = "INSERT INTO cms_user_msg (to_id, from_id, senddate, is_new, message)
VALUES (1, -2, NOW(), 1, '$message_admin')";
$inDB->query($sql);
//удаляем мессагу из входящих
$inDB->query("DELETE FROM cms_user_msg WHERE id = '$id' LIMIT 1") ;
}
}
}
header('location:'.$_SERVER['HTTP_REFERER']);
}//do
///////////////////////////END SPAM//////////////////// Код PHP: 4.2.3 Дополним мессаги кнопкой с жалобой на спам.
//antispam
// RewriteRule ^users/([0-9]*)/spammsg.html$ /index.php?view=users&do=spammessage&id=$1
$routes[] = array(
'_uri' => '/^users\/spammsg([0-9]+).html$/i',
'do' => 'spammessage',
1 => 'id'
);
// end antispam В файле User/messages.php изменяем. Код PHP: Опять же вставить можно в любом месте.if ($opt=='in'){
if ($record['sender_id']>0){
echo '<td class="usr_msg_title" width="80" align="right"><a class="msg_reply" href="/users/'.$record['from_id'].'/reply'.$record['id'].'.html">'.$_LANG['REPLY'].'</a></td>';
echo '<td class="usr_msg_title" width="80" align="right"><a class="msg_history" href="/users/'.$id.'/messages-history'.$record['from_id'].'.html">'.$_LANG['HISTORY'].'</a></td>';
////////////////////Дописано АНТИ-СПАМ
echo '<td class="usr_msg_title" width="90" align="right"><a class="msg_spam" href="/users/spammsg'.$record['id'].'.html">Этом спам!</a></td>';
////////////////////Дописано АНТИ-СПАМ (конец)
}
}4.2.4 В css добавить стиль для msg_spam. Это уже по вкусу. 5. Производим действия над юзерами, подозрительными на спам. 5.1. Выводим captcha (или блокирует отправку) при отправке личных сообщений. А также если юзер пишет чаще, чем раз в минуту, будем показывать captcha. Для этого в файле user/frontend.php ищем процедуру if ($do==’sendmessage’){ И правим ее, чтобы она выглядела так. Код PHP: 5.2. Выводим captcha при добавлении комментариев. if ($do=='sendmessage'){
if (usrCheckAuth() && $inUser->id!=$id || isset($_POST['massmail'])){
$from_id = $inUser->id;
$to_id = $id;
$sql = "SELECT * FROM cms_users WHERE id = '$id'";
$result = $inDB->query($sql) ;
$usr = $inDB->fetch_assoc($result);
if ($usr || isset($_POST['massmail'])){
if (usrCheckAuth()){
////////////////////Дописано АНТИ-СПАМ
// если у юзера spam_detected >=2, то будем показывать ему captcha
$sql = "SELECT spam_detected FROM cms_users WHERE id = '$from_id'";
$result = $inDB->query($sql) ;
$usr1 = $inDB->fetch_assoc($result);
$need_captcha = ($usr1['spam_detected'] > 1);
//также проверяем не слишком ли часто мы шлем месаги
if(!$need_captcha)
{
$sql = "SELECT senddate FROM cms_user_msg WHERE from_id = '$from_id' AND senddate >= DATE_SUB(NOW(), INTERVAL 1 MINUTE)
LIMIT 1";
// Здесь можно изменить "INTERVAL 2 MINUTE" или "INTERVAL 30 SECOND" и т.д. для любителей можно отделить в конфиг
$result = $inDB->query($sql);
$need_captcha = ($inDB->num_rows($result)>0);
}
// если у юзера spam_detected <5, то он еще может отсылать сообщения
$can_send = ($usr1['spam_detected'] < 5);
if($_REQUEST['code']) { $code = $_REQUEST['code']; }
////////////////////Дописано АНТИ-СПАМ (конец)
$inPage->setTitle($_LANG['SEND_MESS']);
$inPage->addPathway($usr['nickname'], cmsUser::getProfileURL($usr['login']));
$inPage->addPathway($_LANG['SEND_MESS'], $_SERVER['REQUEST_URI']);
if(!isset($_POST['gosend'])){
if (isset($_REQUEST['replyid'])) { $replyid = (int)$_REQUEST['replyid']; }
else { $replyid = 0; }
if ($replyid){
$sql = "SELECT m.*, u.*
FROM cms_user_msg m, cms_users u
WHERE m.id = $replyid AND m.from_id = u.id AND m.to_id = $from_id";
$result = $inDB->query($sql) ;
if ($inDB->num_rows($result)>0){
$msg = $inDB->fetch_assoc($result);
echo '<div>';
echo '<div class="con_heading">'.$_LANG['ORIGINAL_MESS'].'</div>';
echo '<div class="usr_msgreply_source">';
echo '<div class="usr_msgreply_sourcetext">'.$msg['message'].'</div>';
echo '<div class="usr_msgreply_author"><a href="'.cmsUser::getProfileURL($msg['login']).'">'.$msg['nickname'].'</a>, '.$msg['senddate'].'</div>';
echo '</div>';
echo '</div>';
} else {
die();
}
}
////////////////////Дописано АНТИ-СПАМ
if ($can_send)
{
////////////////////Дописано АНТИ-СПАМ (конец)
echo '<div class="con_heading">'.$_LANG['SEND_MESS'].'</div>';
echo '<table width="100%" cellpadding="0" cellspacing="5"><tr>';
echo '<td width="200" height="200" valign="top">
<div style="background-color:#FFFFFF;padding:5px;border:solid 1px gray;text-align:center">
'.usrLink(usrImage($usr['id'], 'big'), $usr['login']).'
</div>
<div style="padding:5px;width:100%">
Кому: '.usrLink($usr['nickname'], $usr['login']).'
</div>
</td>';
echo '<td valign="top">';
echo '<form action="" method="POST" name="msgform">';
echo '<div class="usr_msg_bbcodebox">';
echo cmsPage::getBBCodeToolbar('message');
echo '</div>';
echo cmsPage::getSmilesPanel('message');
echo '<textarea style="font-size:18px;border:solid 1px gray;width:100%;height:200px;" name="message" id="message"></textarea>';
if ($inCore->userIsAdmin($inUser->id)){
echo '<input name="massmail" type="checkbox" value="1" /> '.$_LANG['SEND_TO_ALL'];
}
////////////////////Дописано АНТИ-СПАМ
// вставляем капачу если нужна
if ($need_captcha) {echo cmsPage::getCaptcha();}
////////////////////Дописано АНТИ-СПАМ (конец)
echo '<div style="margin-top:6px;"><input type="submit" name="gosend" value="'.$_LANG['SEND'].'" style="font-size:18px"/> ';
echo '<input type="button" name="gosend" value="'.$_LANG['CANCEL'].'" style="font-size:18px" onclick="window.history.go(-1)"/></div>';
echo '</form>';
echo '</td>';
echo '</tr></table>';
////////////////////Дописано АНТИ-СПАМ
}
else
{
echo '<span style="color: red;">Возможность отсылать личные сообщения для Вас приостановлена!<br/>
Возможно, на Вас поступили жалобы от других пользователей! В ближайшее время данный случай рассмотрят модераторы сайта.</span>';
}
////////////////////Дописано АНТИ-СПАМ (конец)
} else {
$message = strip_tags($_POST['message'], '<a><img><b><u><i><table><tr><td>');
$message = htmlspecialchars($message, ENT_QUOTES, 'cp1251');
if (!isset($_POST['massmail'])){
//send private message
////////////////////Дописано АНТИ-СПАМ
//(если нужна captcha и она верна, или не нужна) и мы можем слать мессаги тогда отправляем
if ((($need_captcha && $inCore->checkCaptchaCode($code)) || !$need_captcha) && $can_send)
{
////////////////////Дописано АНТИ-СПАМ (конец)
$sql = "INSERT INTO cms_user_msg (to_id, from_id, senddate, is_new, message)
VALUES ('$to_id', '$from_id', NOW(), 1, '$message')";
$inDB->query($sql) ;
$msg_id = dbLastId('cms_user_msg');
//send email notification, if user want it
$needmail = dbGetField('cms_user_profiles', "user_id='{$to_id}'", 'email_newmsg');
//Проверяем, если юзер онлайн, то уведомление на почту не отправляем.
$isonline = dbGetField('cms_online', "user_id='{$to_id}'", 'id');
if (!$isonline){
if ($needmail){
$inConf = cmsConfig::getInstance();
$postdate = date('d/m/Y H:i:s');
$to_email = dbGetField('cms_users', "id='{$to_id}'", 'email');
$from_nick = dbGetField('cms_users', "id='{$from_id}'", 'nickname');
$answerlink = HOST.'/users/'.$from_id.'/reply'.$msg_id.'.html';
$letter_path = PATH.'/includes/letters/newmessage.txt';
$letter = file_get_contents($letter_path);
$letter= str_replace('{sitename}', $inConf->sitename, $letter);
$letter= str_replace('{answerlink}', $answerlink, $letter);
$letter= str_replace('{date}', $postdate, $letter);
$letter= str_replace('{from}', $from_nick, $letter);
$inCore->mailText($to_email, $_LANG['YOU_HAVE_NEW_MESS'].'! - '.$inConf->sitename, $letter);
}
}
$inCore->redirect('/users/'.$inUser->id.'/messages-sent.html');
////////////////////Дописано АНТИ-СПАМ
}// конец if с капача captcha
else
{
//когда captcha в веден неверно
echo '<span style="color: red;">Вы не правильно ввели проверочный код!<br/>
Пожалуйста, вернитесь назад и повторите отправку!</span>';
}
////////////////////Дописано АНТИ-СПАМ (конец)
} else {
if ($inUser->is_admin){
$userlist = dbGetTable('cms_users', ' id > 0 AND is_locked = 0 AND is_deleted = 0');
foreach ($userlist as $key=>$usr){
$sql = "INSERT INTO cms_user_msg (to_id, from_id, senddate, is_new, message)
VALUES ('".$usr['id']."', '-2', NOW(), 1, '$message')";
$inDB->query($sql) ;
}
}
$inCore->redirect('/users/'.$inUser->id.'/messages-sent.html');
}
}
}
}
} else {
usrAccessDenied();
} //usrCheckAuth
}//do Добавляется аналогично, как и для сообщений, даже проще. 6. Админка Можно также сделать что-то для админки (но честно говоря, я не делал), может быть позже реализую. 6.1. Вынесение всего добра в конфиг и настройка в админке. 6.2. Вывод в админке списка спам-месаг и проч. 7. Что делать с юзерами. Собственно, после того как начнут поступать жалобы на спам, spam_detected будет расти, и как видно из кода алгоритма его уменьшения не предусмотрено. Поэтому каждая жалоба обрабатывается в ручную, если она по дело, то баним юзера. Если нет, то возвращаем юзеру его spam_detected = 0, через БД. Можно написать отдельную кнопку и привязать к ней запрос: $inDB->query("UPDATE cms_users SET spam_detected = 0 WHERE id = ’$id’); Собственно, я надеюсь, что это кому-то будет полезно. Просто по ходу выяснился существенный (на мой взгляд) недостаток сообщений, когда юзер удаляет входящее, автоматически удаляется исходящее, поэтому пришлось это дело переписывать, но это уже совсем другая история... В следствии чего был реализован более сложный алгоритм, с буферными таблицами и прочим (см. теор. часть), но соотв. он ориентирован под мою переделку. Поэтому выкладывать просто не вижу смысла. Если кто-то хочет поучаствовать в дальнейшей разработкой, пишите в личку, буду рад. Поиск багов и косяков приветствуется. У меня вроде все работает, тестировал долго и упорно. 20.08.10 Обновлено, исправлена небольшая ошибка. В if ($do==’sendmessage’). |
|
+8
|
|
Как бороться со спамом – это одна из вечных проблем любой соц. сети. В данной записи постараюсь поделиться своими взглядами и опытом по данной проблеме. Статья носит упрощенный (обзорный) характер, на деле все естественно сложнее.
Рассылка спама бывает 2-ух типов: автоматическая, ручная. Про ручную отправку. Люди в беднейших странах «руками» отправляют сообщения (комментарии, письма и т.д.) и получают по местным меркам хорошие деньги. Если кому-то интересно могу рассказать подробнее. Аналогично, кстати, работает и anticaptcha. Итак, Борьба со спамом подразделяется на 2 части: 1) Выявление спаммера 2) Противодействие спаммеру |
