From 31e312028ca8a8a546558e21a2aa899f708386f5 Mon Sep 17 00:00:00 2001 From: rvelices Date: Thu, 16 Nov 2006 03:31:57 +0000 Subject: - bug fix: comments_forall and category commentable were not checked during POST and a comment could be inserted - feature 524: anti-spam: - check number of links - check ip address against spamhaus.org block list - action when comment is qualified spam (needs validation or reject) - so far everything is in the config file git-svn-id: http://piwigo.org/svn/trunk@1610 68402e56-0260-453c-a942-63ccdbb3a9ee --- include/config_default.inc.php | 11 ++ include/picture_comment.inc.php | 228 +++++++++++++++++++++++++++------------- 2 files changed, 166 insertions(+), 73 deletions(-) (limited to 'include') diff --git a/include/config_default.inc.php b/include/config_default.inc.php index b70b24e21..56c656451 100644 --- a/include/config_default.inc.php +++ b/include/config_default.inc.php @@ -86,6 +86,17 @@ $conf['top_number'] = 15; // anti-flood_time : number of seconds between 2 comments : 0 to disable $conf['anti-flood_time'] = 60; +// qualified spam comments are not registered (false will register them +// but they will require admin validation) +$conf['comment_spam_reject'] = true; + +// maximum number of links in a comment before it is qualified spam +$conf['comment_spam_max_links'] = 3; + +// if the ip address of a comenteer is in spamhaus.org block list, the +// comment is qualified spam +$conf['comment_spam_check_ip'] = false; + // calendar_datefield : date field of table "images" used for calendar // catgory $conf['calendar_datefield'] = 'date_creation'; diff --git a/include/picture_comment.inc.php b/include/picture_comment.inc.php index 679f6287f..ed8818ff4 100644 --- a/include/picture_comment.inc.php +++ b/include/picture_comment.inc.php @@ -29,96 +29,185 @@ * This file is included by the picture page to manage user comments * */ +//returns string action to perform on a new comment: validate, moderate, reject +function user_comment_check($action, $comment, $picture) +{ + global $conf,$user; + + if ($action=='reject') + return $action; + + $my_action = $conf['comment_spam_reject'] ? 'reject':'moderate'; + if ($action==$my_action) + return $action; + + // we do here only BASIC spam check (plugins can do more) + if ( !$user['is_the_guest'] ) + return $action; + + $link_count = preg_match_all( '/https?:\/\//', + $comment['content'], $matches); + + if ( $link_count>$conf['comment_spam_max_links'] ) + return $my_action; + + if ( isset($comment['ip']) and $conf['comment_spam_check_ip'] ) + { + $rev_ip = implode( '.', array_reverse( explode('.',$comment['ip']) ) ); + $lookup = $rev_ip . '.sbl-xbl.spamhaus.org.'; + $res = gethostbyname( $lookup ); + if ( $lookup != $res ) + return $my_action; + } + + return $action; +} -if ( isset( $_POST['content'] ) and !empty($_POST['content']) ) + + +add_event_handler('user_comment_check', 'user_comment_check', + EVENT_HANDLER_PRIORITY_NEUTRAL, 3); + + +// the picture is commentable if it belongs at least to one category which +// is commentable +$page['show_comments'] = false; +foreach ($related_categories as $category) { - $register_comment = true; - $author = !empty($_POST['author'])?$_POST['author']:$lang['guest']; - // if a guest try to use the name of an already existing user, he must be - // rejected - if ( $author != $user['username'] ) + if ($category['commentable'] == 'true') { - $query = 'SELECT COUNT(*) AS user_exists'; - $query.= ' FROM '.USERS_TABLE; - $query.= ' WHERE '.$conf['user_fields']['username']." = '".$author."'"; - $query.= ';'; - $row = mysql_fetch_array( pwg_query( $query ) ); - if ( $row['user_exists'] == 1 ) + $page['show_comments'] = true; + break; + } +} + +if ( $page['show_comments'] and isset( $_POST['content'] ) ) +{ + if ( $user['is_the_guest'] and !$conf['comments_forall'] ) + { + die ('Session expired'); + } + if (!$conf['comments_validation'] or is_admin()) + { + $comment_action='validate'; //one of validate, moderate, reject + } + else + { + $comment_action='moderate'; //one of validate, moderate, reject + } + + $_POST['content'] = trim( stripslashes($_POST['content']) ); + + if ( $user['is_the_guest'] ) + { + $author = empty($_POST['author'])?'guest':$_POST['author']; + // if a guest try to use the name of an already existing user, he must be + // rejected + if ( $author != 'guest' ) { - $template->assign_block_vars( - 'information', - array('INFORMATION'=>$lang['comment_user_exists'])); - $register_comment = false; + $query = 'SELECT COUNT(*) AS user_exists'; + $query.= ' FROM '.USERS_TABLE; + $query.= ' WHERE '.$conf['user_fields']['username']." = '".$author."'"; + $query.= ';'; + $row = mysql_fetch_assoc( pwg_query( $query ) ); + if ( $row['user_exists'] == 1 ) + { + $template->assign_block_vars( + 'information', + array('INFORMATION'=>$lang['comment_user_exists'])); + $comment_action='reject'; + } } } - - if ( $register_comment ) + else { - // anti-flood system + $author = $user['username']; + } + + $comm = array( + 'author' => $author, + 'content' => $_POST['content'], + 'image_id' => $page['image_id'], + 'ip' => $_SERVER['REMOTE_ADDR'], + 'agent' => $_SERVER['HTTP_USER_AGENT'] + ); + + if ($comment_action!='reject' and empty($comm['content']) ) + { // empty comment content + $comment_action='reject'; + } + + if ($comment_action!='reject' and $conf['anti-flood_time']>0 ) + { // anti-flood system $reference_date = time() - $conf['anti-flood_time']; $query = 'SELECT id FROM '.COMMENTS_TABLE; $query.= ' WHERE date > FROM_UNIXTIME('.$reference_date.')'; - $query.= " AND author = '".$author."'"; + $query.= " AND author = '".$comm['author']."'"; $query.= ';'; - if ( mysql_num_rows( pwg_query( $query ) ) == 0 - or $conf['anti-flood_time'] == 0 ) + if ( mysql_num_rows( pwg_query( $query ) ) > 0 ) { - list($dbnow) = mysql_fetch_row(pwg_query('SELECT NOW();')); - - $data = array(); - $data{'author'} = $author; - $data{'date'} = $dbnow; - $data{'image_id'} = $page['image_id']; - $data{'content'} = htmlspecialchars( $_POST['content'], ENT_QUOTES); - - if (!$conf['comments_validation'] or is_admin()) - { - $data{'validated'} = 'true'; - $data{'validation_date'} = $dbnow; - } - else - { - $data{'validated'} = 'false'; - } + $template->assign_block_vars( + 'information', + array('INFORMATION'=>$lang['comment_anti-flood'])); + $comment_action='reject'; + } + } - include_once(PHPWG_ROOT_PATH.'admin/include/functions.php'); - $fields = array('author', 'date', 'image_id', 'content', 'validated', - 'validation_date'); - mass_inserts(COMMENTS_TABLE, $fields, array($data)); + // perform more spam check + $comment_action = trigger_event('user_comment_check', + $comment_action, $comm, $picture['current'] + ); - // information message - $message = $lang['comment_added']; + if ( $comment_action!='reject' ) + { + list($dbnow) = mysql_fetch_row(pwg_query('SELECT NOW();')); - if (!$conf['comments_validation'] or is_admin()) + $data = $comm; + $data['date'] = $dbnow; + $data['content'] = addslashes( + // this htmlpsecialchars is not good here + htmlspecialchars($comm['content'],ENT_QUOTES) + ); - if ( $conf['comments_validation'] and !is_admin() ) - { - $message.= '
'.$lang['comment_to_validate']; - } - $template->assign_block_vars('information', - array('INFORMATION'=>$message)); + if ($comment_action=='validate') + { + $data['validated'] = 'true'; + $data['validation_date'] = $dbnow; } else { - // information message - $template->assign_block_vars( - 'information', - array('INFORMATION'=>$lang['comment_anti-flood'])); + $data['validated'] = 'false'; } - } -} -// the picture is commentable if it belongs at least to one category which -// is commentable -$page['show_comments'] = false; -foreach ($related_categories as $category) -{ - if ($category['commentable'] == 'true') + include_once(PHPWG_ROOT_PATH.'admin/include/functions.php'); + $fields = array('author', 'date', 'image_id', 'content', 'validated', + 'validation_date'); + mass_inserts(COMMENTS_TABLE, $fields, array($data)); + $comm['id'] = mysql_insert_id(); + + // information message + $message = $lang['comment_added']; + if ($comment_action!='validate') + { + $message.= '
'.$lang['comment_to_validate']; + } + $template->assign_block_vars('information', + array('INFORMATION'=>$message)); + } + else { - $page['show_comments'] = true; + $template->assign_block_vars('information', + array('INFORMATION'=>l10n('comment_not_added') ) + ); } + + // allow plugins to notify what's going on + trigger_action( 'user_comment_insertion', + array_merge($comm, array('action'=>$comment_action) ) + ); } + if ($page['show_comments']) { // number of comment for this picture @@ -204,14 +293,7 @@ SELECT id,author,date,image_id,content { $template->assign_block_vars('comments.add_comment', array()); // display author field if the user is not logged in - if (!$user['is_the_guest']) - { - $template->assign_block_vars( - 'comments.add_comment.author_known', - array('KNOWN_AUTHOR'=>$user['username']) - ); - } - else + if ($user['is_the_guest']) { $template->assign_block_vars( 'comments.add_comment.author_field', array() -- cgit v1.2.3