aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2017-08-25 16:12:21 +0200
committerSergey Poznyakoff <gray@gnu.org.ua>2017-08-25 16:52:55 +0200
commit74eb0aab7c69281dac351a47d15522957ee0cfdd (patch)
tree84438d114e7a4825724b95630c5311100a1bf3b2
parent211ebaa02706d4355469aba33f3eab4e6f771efc (diff)
downloadsavane-gray-74eb0aab7c69281dac351a47d15522957ee0cfdd.tar.gz
savane-gray-74eb0aab7c69281dac351a47d15522957ee0cfdd.tar.bz2
More work on spam checking.
* frontend/php/include/html.php (html_nextprev): Fix operation when $varpref is passed. * frontend/php/include/spam.php: Style fixes. * frontend/php/siteadmin/spamlist.php: Fix pagination. Print meaningful references in the "incrimnated content" list, instead of mere "here". List resume first, if it is marked as spam. * lib/Savane/DB.pm (db_insert): New function. * lib/Savane/Trackers.pm (GetTrackersContentAsMail): Fix email formatting issues. * db/mysql/table_user.structure (resume_spamscore): New column. * update/gray/new_tables.pl: New file. * update/gray/user.sql: New file. * backend/accounts/sv_usrck: New file. Spamcheck items submitted by a user or users.
-rwxr-xr-xbackend/accounts/sv_usrck585
-rw-r--r--db/mysql/table_user.structure1
-rw-r--r--frontend/php/include/html.php46
-rw-r--r--frontend/php/include/spam.php67
-rw-r--r--frontend/php/siteadmin/spamlist.php251
-rw-r--r--lib/Savane/DB.pm18
-rw-r--r--lib/Savane/Trackers.pm62
-rw-r--r--update/gray/new_tables.pl40
-rw-r--r--update/gray/user.sql1
9 files changed, 864 insertions, 207 deletions
diff --git a/backend/accounts/sv_usrck b/backend/accounts/sv_usrck
new file mode 100755
index 0000000..d295508
--- /dev/null
+++ b/backend/accounts/sv_usrck
@@ -0,0 +1,585 @@
+#! /usr/bin/perl
+# Copyright (C) 2015-2017 Sergey Poznyakoff <gray@gnu.org>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+use strict;
+use Savane;
+use Savane::DB;
+use Savane::Backend;
+use Savane::Trackers;
+use Mail::SpamAssassin::Client;
+use Data::Dumper;
+use File::Temp qw(tempfile);
+use Time::ParseDate;
+use Data::Dumper;
+
+use constant TYPE_SPAM => 0;
+use constant TYPE_HAM => 1;
+use constant TYPE_FORGET => 2;
+
+my $spamc;
+my $repfd;
+my $report_detail;
+my $min_score = 5;
+my $quiet;
+my $learn;
+my $assume_status;
+my $since;
+my $sort;
+my $update_spamscore;
+my $reporter_uid = 101; # FIXME
+
+my %all_trackers = map { $_ => 1 } TrackerNames();
+my $enable_resume;
+my @enable_trackers;
+
+my $sys_spamc_socketpath = GetConf('backend.sv_spamchecker.socket');
+my $sys_spamc_host = GetConf('backend.sv_spamchecker.host');
+my $sys_spamc_port = GetConf('backend.sv_spamchecker.port');
+my $sys_spamc_timeout = GetConf('backend.sv_spamchecker.timeout');
+my $sys_spamc_username = GetConf('backend.sv_spamchecker.user');
+my $sys_https_host = GetConf('core.domain');
+
+sub userlist_collect {
+ my @userlist;
+ my $cond;
+
+ if ($#_ == -1) {
+ $cond = "user.status='A' AND user_group.group_id IS NULL";
+ } else {
+ if ($#_ == 0) {
+ $cond = "user.user_name=?";
+ } else {
+ $cond = "user.user_name IN (" . join(',', ('?') x (@_)) . ')';
+ }
+ }
+ if ($since) {
+ $cond .= qq{ AND user.add_date >= $since};
+ }
+
+ my $order = '';
+ if ($sort) {
+ $order = 'ORDER BY user_name';
+ }
+
+ db_foreach(sub { push @userlist, $_[0] },
+ qq{
+SELECT distinct user.user_id AS user_id,
+ user.user_name AS user_name,
+ user.realname AS realname,
+ user.people_resume AS resume,
+ user.people_view_skills AS view_skills,
+ user.add_date AS date,
+ cache.isspam AS cache_isspam
+FROM user
+LEFT JOIN user_group ON user_group.user_id=user.user_id
+LEFT JOIN trackers_spamcheck_cache cache
+ ON cache.item_id = user.user_id
+ AND cache.artifact = 'resume'
+WHERE $cond
+$order
+ },
+ @_);
+ return @userlist;
+}
+
+# sub check_cache {
+# my ($ref, $ctr) = @_;
+# if (defined($ref->{cache_isspam})) {
+# }
+# }
+
+sub spam_check {
+ my ($msg, $ctr, $tracker, $id) = @_;
+ my $result;
+
+ $ctr->{total}++;
+ if (defined($assume_status)) {
+ return { isspam => $assume_status == TYPE_SPAM ? 'True' : 'False' };
+ }
+
+ if (defined($report_detail)) {
+ $result = $spamc->_filter($msg, $report_detail);
+ } else {
+ $result = $spamc->process($msg);
+ }
+
+ push @{$ctr->{detail}},
+ { tracker => $tracker, item_id => $id, msg => $msg,
+ result => $result }
+ if $repfd;
+
+ $ctr->{sum} += $result->{score};
+ if ($result->{isspam} eq 'True') {
+ ++$ctr->{spam};
+ } else {
+ ++$ctr->{ham};
+ }
+ return $result;
+}
+
+sub update_trackers_spamscore {
+ my ($newscore, $tracker, $user_id, $bug_id, $comment_id) = @_;
+ # Feed the spamscore table
+# db_delete('trackers_spamscore',
+# artifact => $tracker,
+# item_id => $ref->{bug_id},
+# comment_id => $ref->{comment_id});
+ db_modify(q{
+DELETE FROM trackers_spamscore
+WHERE artifact=? AND item_id=? AND comment_id=? AND affected_user_id=?
+},
+ $tracker, $bug_id, $comment_id, $user_id);
+ db_insert('trackers_spamscore',
+ score => $newscore,
+ affected_user_id => $user_id,
+ reporter_user_id => $reporter_uid,
+ artifact => $tracker,
+ item_id => $bug_id,
+ comment_id => $comment_id);
+
+ my $spam = $newscore > 4 ? 'Y' : 'N';
+ db_modify(qq{
+INSERT INTO trackers_spamcheck_cache (artifact, item_id, comment_id, isspam)
+VALUES (?, ?, ?, ?)
+ON DUPLICATE KEY UPDATE isspam=?
+ }, $tracker, $bug_id, $comment_id, $spam, $spam);
+}
+
+sub check_tracker_comment {
+ my ($tracker, $ref, $ctr, $user, $cb) = @_;
+ # FIXME: cache
+ my $msg = GetTrackersContentAsMail($user->{user_id},
+ $ref->{ip},
+ $tracker,
+ $ref->{bug_id},
+ $ref->{comment_id},
+ $ref->{date},
+ $ref->{summary},
+ $ref->{details});
+ my $res = spam_check($msg, $ctr, $tracker, $ref->{bug_id});
+
+ &{$cb} ($msg, $res, $user->{user_name}, "$tracker $ref->{bug_id}")
+ if (ref($cb) eq 'CODE');
+
+ if ($update_spamscore) {
+ my $newscore = savane_adjust_spamscore($ref->{spamscore},
+ $res->{score});
+ my ($q,$id);
+ if ($ref->{comment_id} > 0) {
+ $q = qq{UPDATE ${tracker}_history SET spamscore=? WHERE bug_history_id=?};
+ $id = $ref->{comment_id};
+ } else {
+ $q = qq{UPDATE $tracker SET spamscore=? WHERE bug_id=?};
+ $id = $ref->{bug_id};
+ }
+ db_modify($q, $newscore, $id);
+ update_trackers_spamscore($newscore, $tracker,
+ $user->{user_id},
+ $ref->{bug_id}, $ref->{comment_id});
+ }
+}
+
+sub general_tracker_check {
+ my ($tracker,$uref,$ctr,$cb) = @_;
+ my $uid = $uref->{user_id};
+
+ db_foreach(sub {
+ my $ref = shift;
+ $ref->{comment_id} = 0;
+ check_tracker_comment($tracker, $ref, $ctr, $uref, $cb);
+ },
+ qq{
+SELECT tracker.bug_id AS bug_id,
+ tracker.summary AS summary,
+ tracker.details AS details,
+ tracker.date AS date,
+ tracker.ip AS ip,
+ tracker.spamscore AS spamscore,
+ cache.isspam AS cache_isspam
+FROM $tracker tracker
+LEFT JOIN trackers_spamcheck_cache cache
+ ON tracker.bug_id = cache.item_id
+ AND cache.artifact = ?
+WHERE tracker.submitted_by=?
+ORDER BY t.date
+ }, $tracker, $uid);
+
+ db_foreach(sub {
+ my $ref = shift;
+ check_tracker_comment($tracker, $ref, $ctr, $uref, $cb);
+ },
+ qq{
+SELECT h.bug_history_id AS comment_id,
+ h.bug_id AS bug_id,
+ h.old_value AS details,
+ h.ip AS ip,
+ h.date AS date,
+ h.spamscore AS spamscore,
+ t.summary AS summary,
+ cache.isspam AS isspam
+FROM ${tracker}_history h, $tracker t
+LEFT JOIN trackers_spamcheck_cache cache
+ ON h.bug_id = cache.item_id
+ AND cache.artifact = ?
+WHERE field_name='details' AND mod_by=? AND t.bug_id=h.bug_id
+ORDER BY date},
+ $tracker, $uid);
+
+}
+
+sub resume_check {
+ return unless $enable_resume;
+ # FIXME: cache
+ my $msg = GetTrackersContentAsMail($uref->{user_id},
+ '127.0.0.1',
+ 'resume',
+ $uref->{user_id}, # bug_id
+ '0', # comment_id
+ $uref->{date},
+ 'Resume',
+ $uref->{resume});
+ my $res = spam_check($msg, $ctr, 'resume', 0);
+ &{$cb} ($msg, $res, $uref->{user_name}, 'Resume') if (ref($cb) eq 'CODE');
+
+ if ($update_spamscore) {
+ my $newscore = savane_adjust_spamscore(0, $res->{score});
+ db_modify(q{UPDATE user SET resume_spamscore=? WHERE user_id=?},
+ $newscore, $uref->{user_id});
+ update_trackers_spamscore($newscore, 'resume',
+ $uref->{user_id}, 0, 0);
+ }
+}
+
+sub result_is_spam {
+ my $result = shift;
+ if (defined($min_score)) {
+ return $result->{score} >= $min_score;
+ } else {
+ return $result->{isspam} eq 'True';
+ }
+}
+
+sub report_uid {
+ my ($usr, $ctr) = @_;
+ print $repfd "* $usr->{user_name}: $ctr->{status}\n";
+ print $repfd "total=$ctr->{total}\n";
+ print $repfd "score=$ctr->{score}\n";
+ print $repfd "spam=$ctr->{spam} / $ctr->{ham}\n";
+
+ return unless defined $ctr->{detail};
+
+ my $tracker;
+ foreach my $detail (@{$ctr->{detail}}) {
+ print $repfd "\n";
+
+ my $result = $detail->{result};
+
+ if ($tracker ne $detail->{tracker}) {
+ $tracker = $detail->{tracker};
+ print $repfd "\n** $tracker\n";
+ }
+
+ my $stat = $result->{isspam} eq 'True';
+ print $repfd "\n*** $detail->{item_id}: $stat (score $result->{score})\n";
+ my $print_msg;
+
+ if (exists($result->{message})) {
+ $result->{message} =~ s/.*^(Content analysis details:)/$1/sm;
+ print $repfd "$result->{message}\n\n";
+ $print_msg = 1 if $report_detail;
+ } else {
+ $print_msg = 1;
+ }
+ if ($print_msg) {
+ $detail->{msg} =~ s/\r//g;
+ $detail->{msg} =~ s/^\*/\\*/;
+ print $repfd "$detail->{msg}\n";
+ }
+ }
+ print $repfd "\n\f\n";
+}
+
+sub parsetime {
+ my $s = shift;
+ my $t = 0;
+ if ($s =~ /^\d+$/) {
+ $t = $s;
+ } else {
+ my @keyord = ('Y', 'M', 'd', 'h', 'm', 's');
+ my %timetrans = ('Y' => 365*86400,
+ 'M' => 31*86400,
+ 'd' => 86400,
+ 'h' => 3600,
+ 'm' => 60,
+ 's' => 1);
+ for (my $set = join('', @keyord);
+ $set ne '' && $s =~ /(\d+)\s*([$set])\s*(.*)/;
+ $set = join('', @keyord)) {
+ while (shift(@keyord) ne $2) {}
+ $t += $1 * $timetrans{$2};
+ $s = $3;
+ }
+ abend(EX_USAGE, "time specification error near $s") unless $s eq '';
+ }
+ return $t;
+}
+
+# ####
+my $file;
+my $report;
+my %d2cmd = ( 1 => 'SYMBOLS',
+ symbols => 'SYMBOLS',
+ 2 => 'REPORT',
+ full => 'REPORT' );
+
+my %opts = ("report|r" => \$report,
+ "detail|D=s" => sub {
+ if ($_[1] ne '0') {
+ my $s = lc $_[1];
+ abend(EX_USAGE, "unknown detail level")
+ unless defined $d2cmd{$s};
+ $report_detail = $d2cmd{$s};
+ }
+ $report = 1;
+ },
+ "output|o=s" => \$file,
+ "quiet|q" => \$quiet,
+ "score|s=f" => \$min_score,
+ "learn|l" => \$learn,
+ "update-spamscore" => \$update_spamscore,
+ "assume-status=s" => sub {
+ $assume_status = learntype($_[1]);
+ abend(EX_USAGE, "unrecognized status")
+ unless (defined($assume_status) && $assume_status != TYPE_FORGET);
+ },
+ "resume" => \$enable_resume,
+ "no-resume" => sub { $enable_resume = 0 },
+ "trackers=s" => sub {
+ foreach my $name (split /,/, $_[1]) {
+ push @enable_trackers, $name;
+ }
+ },
+ "no-trackers:s" => sub {
+ if ($_[1] eq '') {
+ %all_trackers = ();
+ } else {
+ foreach my $name (split /,/, $_[1]) {
+ delete $all_trackers{$name};
+ }
+ }
+ },
+ "since:s" => sub { $since = parsedate($_[1]) },
+ "sort" => \$sort
+ );
+backend_setup(descr => "Check active users",
+ cron => GetConf('backend.sv_usrck.cron')||1, # FIXME
+ options => \%opts);
+
+if (defined($assume_status)) {
+ abend(EX_USAGE, "--assume-status is valid only with --learn")
+ unless defined $learn;
+ abend(EX_USAGE, "--update-spamscore is not valid with --assume-status")
+ if $update_spamscore;
+}
+
+$enable_resume = 1 unless defined $enable_resume;
+@enable_trackers = sort keys %all_trackers
+ unless @enable_trackers;
+
+my %spamc_options;
+
+if (defined $sys_spamc_socketpath) {
+ $spamc_options{socketpath} = $sys_spamc_socketpath;
+} elsif (defined $sys_spamc_port) {
+ $spamc_options{port} = $sys_spamc_port;
+ $spamc_options{host} =
+ defined($sys_spamc_host) ? $sys_spamc_host : 'localhost';
+}
+$spamc_options{timeout} = $sys_spamc_timeout;
+$spamc_options{username} = $sys_spamc_username;
+
+$spamc = new Mail::SpamAssassin::Client(\%spamc_options);
+abend(EX_UNAVAILABLE, "can't connect to spamd") unless $spamc->ping();
+
+if ($report) {
+ if (defined($file)) {
+ open($repfd, '>', $file) or
+ abend(EX_CANTCREAT, "can't create file $file");
+ } else {
+ open($repfd, '>&', STDOUT);
+ ++$quiet;
+ }
+}
+
+my $now = time();
+
+# $s = savane_adjust_spamscore($input, $score);
+# Adjusts Savane spamscore $input in accordance with the newly computed
+# SpamAssassin $score.
+sub savane_adjust_spamscore {
+ my ($spam_score, $sa_score) = @_;
+ my $newscore;
+
+ if ($sa_score <= 0) {
+ $newscore = $spam_score - 8;
+ } elsif ($sa_score > 0.0 && $sa_score <= 2.0) {
+ $newscore = $spam_score - 5;
+ } elsif ($sa_score > 2.0 && $sa_score <= 3.0) {
+ $newscore = $spam_score - 4;
+ } elsif ($sa_score > 3.0 && $sa_score <= 5.0) {
+ $newscore = $spam_score - 3;
+ } elsif ($sa_score > 5.0 && $sa_score <= 7.0) {
+ $newscore = $spam_score - 2;
+ } elsif ($sa_score > 7.0 && $sa_score <= 9.0) {
+ $newscore = $spam_score - 1;
+ } else {
+ $newscore = $sa_score;
+ }
+ return $newscore < 0 ? 0 : int($newscore + 0.5);
+}
+
+sub check_user {
+ my $uref = shift;
+
+ my %ctr;
+
+ $ctr{total} = $ctr{spam} = $ctr{ham} = 0;
+ if ($uref->{view_skills}) {
+ debug("$uref->{user_name}: checking resume");
+ resume_check($uref, \%ctr);
+ }
+
+ for my $t (@enable_trackers) {
+ debug("$uref->{user_name}: checking $t");
+ general_tracker_check($t, $uref, \%ctr);
+ }
+ my $s = "$uref->{user_name} ($uref->{realname}): total=$ctr{total}";
+ if ($ctr{total}) {
+ $ctr{score} = $ctr{sum} / $ctr{total};
+ $ctr{status} = ($ctr{score} >= $min_score) ? 'SPAM' : 'OK';
+ $s .= " avg score=$ctr{score}; spam=$ctr{spam}; ham=$ctr{ham}";
+ } else {
+ $ctr{score} = 0.0;
+ $ctr{status} = 'OK';
+ }
+ debug($s);
+
+ print "$uref->{user_name} ($uref->{realname}): $ctr{status}\n"
+ unless $quiet;
+ report_uid($uref, \%ctr) if $report;
+ db_modify(q{UPDATE user SET spamscore=? WHERE user_id=?},
+ savane_adjust_spamscore(8, $ctr{score}), $uref->{user_id})
+ if $update_spamscore;
+}
+
+sub line_count {
+ my $s = shift;
+ return 0 if $s eq '';
+ my $count = 1;
+ $count++ while $s =~ m/$/g;
+ return $count;
+}
+
+sub learntype {
+ my $s = uc shift;
+ my %t = (
+ S => TYPE_SPAM,
+ SPAM => TYPE_SPAM,
+ H => TYPE_HAM,
+ HAM => TYPE_HAM.
+ F => TYPE_FORGET,
+ FORGET => TYPE_FORGET
+ );
+ return $t{$s} if exists $t{$s};
+ return undef;
+}
+
+sub edit {
+ my $filename = shift;
+ my $editor = $ENV{'VISUAL'} || $ENV{'EDITOR'} || 'vi';
+ system("$editor $filename");
+ if ($? == -1) {
+ die "failed to execute $editor: $!";
+ } elsif ($? & 127) {
+ die "$editor died with signal " . ($? & 127) . ' '.
+ (($? & 128) ? 'with' : 'without') .
+ ' coredump';
+ } elsif ($? >> 8) {
+ die "$editor exited with code " . ($? >> 8);
+ }
+}
+
+sub inspect {
+ my ($input, $result, $user, $what) = @_;
+ my ($learntype, $type);
+
+ my ($fh, $filename) = tempfile();
+
+ $type = $result->{isspam} eq 'True' ? TYPE_SPAM : TYPE_HAM;
+
+ print $fh "Status: ".($type == TYPE_SPAM ? "S" : "H")."\n";
+ print $fh "User: $user\n";
+ print $fh "Item: $what\n";
+ print $fh "\n";
+ print $fh $input;
+ close $fh;
+
+ edit($filename);
+
+ open(my $fh, '<', $filename) or
+ abend(EX_NOINPUT, "can't read temp file $filename: $!");
+ while (<$fh>) {
+ chomp;
+ if (/^Status:\s*(.)/) {
+ $learntype = learntype($1);
+ last;
+ }
+ last if (/^\s*$/);
+ }
+ close $fh;
+ unlink $filename;
+
+ if (defined($learntype)
+ && (defined($assume_status) || $learntype != $type)) {
+ print "Learned $learntype\n";
+ my $res = $spamc->learn($input, $learntype);
+ abend(EX_UNAVAILABLE, $spamc->{resp_msg}) unless defined $res;
+ print "RES $res\n";
+ }
+}
+
+sub learn_user {
+ my $uref = shift;
+ print "Inspecting user ".$uref->{user_name}. "\n";
+ my %ctr;
+
+ if ($uref->{view_skills}) {
+ resume_check($uref, \%ctr, \&inspect);
+ }
+
+ for my $t (@enable_trackers) {
+ debug("$uref->{user_name}: checking $t");
+ general_tracker_check($t, $uref, \%ctr, \&inspect);
+ }
+}
+
+my $action = defined($learn) ? \&learn_user : \&check_user;
+
+foreach my $uref (userlist_collect @ARGV) {
+ &{$action}($uref);
+}
+
+backend_done;
diff --git a/db/mysql/table_user.structure b/db/mysql/table_user.structure
index 2d6f7d8..ad62d1b 100644
--- a/db/mysql/table_user.structure
+++ b/db/mysql/table_user.structure
@@ -33,6 +33,7 @@ CREATE TABLE `user` (
`email_new` text,
`people_view_skills` int(11) NOT NULL DEFAULT '0',
`people_resume` text NOT NULL,
+ `resume_spamscore` int(2) NOT NULL DEFAULT '0',
`timezone` varchar(64) DEFAULT 'GMT',
`theme` varchar(15) DEFAULT '',
`email_hide` varchar(3) DEFAULT '0',
diff --git a/frontend/php/include/html.php b/frontend/php/include/html.php
index 12b15e4..40f79a4 100644
--- a/frontend/php/include/html.php
+++ b/frontend/php/include/html.php
@@ -235,39 +235,43 @@ function html_splitpage ($how)
function html_nextprev ($search_url, $rows, $rows_returned, $varprefix=false)
{
- global $offset, $max_rows;
-
if (!$varprefix)
- { $varprefix = ''; }
+ $varprefix = '';
else
- { $varprefix .= '_'; }
+ $varprefix .= '_';
+ $var_offset = $varprefix . 'offset';
+ $var_max_rows = $varprefix . 'max_rows';
+ $var_results = $varprefix . 'results';
+
+ global ${$var_offset}, ${$var_max_rows};
+ $l_offset = ${$var_offset};
+ $l_max_rows = ${$var_max_rows};
- if (($rows_returned > $rows) || ($offset != 0))
+ if (($rows_returned > $rows) || ($l_offset != 0))
{
print "\n<br /><h5 class=\"nextprev\">\n";
- if ($offset != 0)
- {
- print '<a href="'.$search_url.'&amp;'.$varprefix.'offset='.($offset-$rows).'&amp;'.$varprefix.'max_rows='.$max_rows.'#'.$varprefix.'results">';
- print '<img src="'.$GLOBALS['sys_home'].'images/'.SV_THEME.'.theme/arrows/previous.png" border="0" alt="'._("Previous Results").'" />'._("Previous Results").'</a>';
-
- }
+ if ($l_offset != 0)
+ {
+ print '<a href="'.$search_url.'&amp;'.$var_offset.'='.($l_offset-$rows).'&amp;'.$var_max_rows.'='.$l_max_rows.'#'.$var_results.'">';
+ print '<img src="'.$GLOBALS['sys_home'].'images/'.SV_THEME.'.theme/arrows/previous.png" border="0" alt="'._("Previous Results").'" />'._("Previous Results").'</a>';
+ }
else
- {
- print '<img src="'.$GLOBALS['sys_home'].'images/'.SV_THEME.'.theme/arrows/previousgrey.png" border="0" alt="'._("Previous Results").'" /><em>'._("Previous Results").'</em>';
- }
+ {
+ print '<img src="'.$GLOBALS['sys_home'].'images/'.SV_THEME.'.theme/arrows/previousgrey.png" border="0" alt="'._("Previous Results").'" /><em>'._("Previous Results").'</em>';
+ }
print "&nbsp; &nbsp; &nbsp;";
if ($rows_returned > $rows)
- {
- print '<a href="'.$search_url.'&amp;'.$varprefix.'offset='.($offset+$rows).'&amp;'.$varprefix.'max_rows='.$max_rows.'#'.$varprefix.'results">';
- print _("Next Results").' <img src="'.$GLOBALS['sys_home'].'images/'.SV_THEME.'.theme/arrows/next.png" border="0" alt="'._("Next Results").'" /></a>';
- }
+ {
+ print '<a href="'.$search_url.'&amp;'.$var_offset.'='.($l_offset+$rows).'&amp;'.$var_max_rows.'='.$l_max_rows.'#'.$var_results.'">';
+ print _("Next Results").' <img src="'.$GLOBALS['sys_home'].'images/'.SV_THEME.'.theme/arrows/next.png" border="0" alt="'._("Next Results").'" /></a>';
+ }
else
- {
- print '<em>'._("Next Results").'</em> <img src="'.$GLOBALS['sys_home'].'images/'.SV_THEME.'.theme/arrows/nextgrey.png" border="0" alt="'._("Next Results").'" />';
- }
+ {
+ print '<em>'._("Next Results").'</em> <img src="'.$GLOBALS['sys_home'].'images/'.SV_THEME.'.theme/arrows/nextgrey.png" border="0" alt="'._("Next Results").'" />';
+ }
print "</h5>\n";
}
diff --git a/frontend/php/include/spam.php b/frontend/php/include/spam.php
index efe1744..d7103c2 100644
--- a/frontend/php/include/spam.php
+++ b/frontend/php/include/spam.php
@@ -24,20 +24,20 @@
if (!empty($GLOBALS['sys_spamcheck_spamassassin']))
{
if ($GLOBALS['sys_spamcheck_spamassassin'] == 1)
- { $GLOBALS['sys_spamcheck_spamassassin'] = "anonymous"; }
+ $GLOBALS['sys_spamcheck_spamassassin'] = "anonymous";
elseif ($GLOBALS['sys_spamcheck_spamassassin'] == 2)
- { $GLOBALS['sys_spamcheck_spamassassin'] = "all"; }
+ $GLOBALS['sys_spamcheck_spamassassin'] = "all";
}
$GLOBALS['int_probablyspam'] = false;
$GLOBALS['int_delayspamcheck_comment_id'] = false;
-# Function to mark a spam. This assume that checks on whether the user
+# Function to mark a spam. This assumes that checks on whether the user
# has proper rights have been made already.
function spam_flag ($item_id, $comment_id, $score, $group_id, $reporter_user_id=0)
{
if (!$reporter_user_id)
- { $reporter_user_id = user_getid(); }
+ $reporter_user_id = user_getid();
# Check if the reported havent flagged the incriminated comment already
$result = db_execute("SELECT id FROM trackers_spamscore WHERE item_id=?
@@ -101,7 +101,7 @@ function spam_flag ($item_id, $comment_id, $score, $group_id, $reporter_user_id=
# for anonymous post. We fill the database only for real users with positive
# scores
if ($affected_user_id == 100 && $newscore == $score)
- { $newscore += 3; }
+ $newscore += 3;
# Update the item spamscore fields
if ($comment_id)
@@ -115,23 +115,23 @@ function spam_flag ($item_id, $comment_id, $score, $group_id, $reporter_user_id=
{
# Get the current summary
$summary = db_result(db_execute("SELECT summary FROM ".ARTIFACT." WHERE bug_id=?",
- array($item_id)),
- 0, 'summary');
+ array($item_id)),
+ 0, 'summary');
$discussion_lock = array();
if ($newscore > 4)
- {
- if (strpos($summary, '[SPAM]') === FALSE)
- $summary = '[SPAM] '.$summary;
- $discussion_lock = array('discussion_lock' => 1);
- }
+ {
+ if (strpos($summary, '[SPAM]') === FALSE)
+ $summary = '[SPAM] '.$summary;
+ $discussion_lock = array('discussion_lock' => 1);
+ }
db_autoexecute(ARTIFACT,
- array_merge(array('spamscore' => $newscore,
- 'summary' => $summary),
- $discussion_lock),
- DB_AUTOQUERY_UPDATE,
- 'bug_id=?',
- array($item_id));
+ array_merge(array('spamscore' => $newscore,
+ 'summary' => $summary),
+ $discussion_lock),
+ DB_AUTOQUERY_UPDATE,
+ 'bug_id=?',
+ array($item_id));
}
fb(sprintf(_("Flagged (+%s, total spamscore: %s)"), $score, $newscore));
@@ -139,7 +139,7 @@ function spam_flag ($item_id, $comment_id, $score, $group_id, $reporter_user_id=
# If the total spamscore is superior to 4, the content is supposedly
# confirmed spam, then increment the user spamscore
if ($newscore < 5)
- { return true; }
+ return true;
# If the affected_user_id is anonymous, end here, obviously we cannot
# change any personal spamscore
@@ -154,7 +154,7 @@ function spam_flag ($item_id, $comment_id, $score, $group_id, $reporter_user_id=
# (we do not want a single user being able to increment by more than one
# another user spamscore)
if (spam_get_user_score($affected_user_id, $reporter_user_id) > 1)
- { return true; }
+ return true;
# If the reporter is not member of the project that owns the item,
# not increment user spamscore
@@ -169,7 +169,7 @@ function spam_flag ($item_id, $comment_id, $score, $group_id, $reporter_user_id=
# Update the user spamscore field
db_execute("UPDATE user SET spamscore=? WHERE user_id=?",
- array($userscore, $affected_user_id));
+ array($userscore, $affected_user_id));
# No feedback about this last part, one user spamscore is the kind of info
# that belongs to site admins territory.
@@ -195,43 +195,42 @@ function spam_unflag ($item_id, $comment_id, $tracker, $group_id)
{
db_execute("UPDATE ".$tracker."_history SET spamscore=0
WHERE bug_history_id=? AND field_name='details' AND bug_id=?",
- array($comment_id, $item_id));
+ array($comment_id, $item_id));
}
else
{
db_execute("UPDATE $tracker SET spamscore=0
WHERE bug_id=? AND group_id=?",
- array($item_id, $group_id));
+ array($item_id, $group_id));
}
}
-
# Return the total score of a user
function spam_get_user_score ($user_id=0, $set_by_user_id=0)
{
if (!$user_id)
- { $user_id = user_getid(); }
+ $user_id = user_getid();
# Anonymous get always a score of 3 (requires two users to succesfully
# mark as spam something, only one project member)
if ($user_id == 100)
- { return 3; }
+ return 3;
$set_by_user_id_sql = '';
$set_by_user_id_params = array();
- if ($set_by_user_id) {
- $set_by_user_id_sql = " AND reporter_user_id=?";
- $set_by_user_id_params = array($set_by_user_id);
- }
+ if ($set_by_user_id)
+ {
+ $set_by_user_id_sql = " AND reporter_user_id=?";
+ $set_by_user_id_params = array($set_by_user_id);
+ }
# We cannot do a count because it does not allow us to use GROUP BY
$userscore = 0;
- $result = db_execute("SELECT score FROM trackers_spamscore WHERE affected_user_id=? $set_by_user_id_sql GROUP BY reporter_user_id", array_merge(array($user_id), $set_by_user_id_params));
+ $result = db_execute("SELECT score FROM trackers_spamscore WHERE affected_user_id=? $set_by_user_id_sql GROUP BY reporter_user_id",
+ array_merge(array($user_id), $set_by_user_id_params));
while ($entry = db_fetch_array($result))
- {
- $userscore++;
- }
+ $userscore++;
return $userscore;
}
diff --git a/frontend/php/siteadmin/spamlist.php b/frontend/php/siteadmin/spamlist.php
index 4d31766..454ac91 100644
--- a/frontend/php/siteadmin/spamlist.php
+++ b/frontend/php/siteadmin/spamlist.php
@@ -19,7 +19,6 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-
require_once('../include/init.php');
register_globals_off();
@@ -27,42 +26,42 @@ session_require(array('group'=>'1','admin_flags'=>'A'));
###### See if we were asked to perform anything
extract(sane_import('get', array('ban_user_id', 'wash_user_id', 'wash_ip',
- 'max_rows', 'offset')));
+ 'users_max_rows', 'users_offset',
+ 'ip_max_rows', 'ip_offset')));
if ($ban_user_id)
-{
- if (!user_exists($ban_user_id))
- { fb(_("User not found"), 1); }
- else
- {
+ {
+ if (!user_exists($ban_user_id))
+ fb(_("User not found"), 1);
+ else
user_delete($ban_user_id);
- }
-}
+ }
if ($wash_user_id)
-{
- if (!user_exists($wash_user_id))
- { fb(_("User not found"), 1); }
- else
- {
- # Update the user spamscore field
- db_execute("UPDATE user SET spamscore='0' WHERE user_id=?", array($wash_user_id));
-
- # Previous comment flagged as spam will stay as such.
- # We just changed the affected user id that it wont affect this guy
- # any more.
- # We assume that message flagged as spam really were.
- # (we may change that in the future, depending on user experience)
- db_execute("UPDATE trackers_spamscore SET affected_user_id='100' WHERE affected_user_id=?",
- array($wash_user_id));
+ {
+ if (!user_exists($wash_user_id))
+ { fb(_("User not found"), 1); }
+ else
+ {
+ # Update the user spamscore field
+ db_execute("UPDATE user SET spamscore='0' WHERE user_id=?",
+ array($wash_user_id));
+
+ # Previous comment flagged as spam will stay as such.
+ # We just changed the affected user id that it wont affect this guy
+ # any more.
+ # We assume that message flagged as spam really were.
+ # (we may change that in the future, depending on user experience)
+ db_execute("UPDATE trackers_spamscore SET affected_user_id='100' WHERE affected_user_id=?",
+ array($wash_user_id));
- }
+ }
}
if ($wash_ip)
-{
- db_execute("DELETE FROM trackers_spamban WHERE ip=?", array($wash_ip));
-}
+ {
+ db_execute("DELETE FROM trackers_spamban WHERE ip=?", array($wash_ip));
+ }
@@ -80,121 +79,135 @@ $title_arr[]=_("Wash score");
$title_arr[]=_("Incriminated content");
$title_arr[]=_("Flagged by");
-if (!isset($max_rows))
-{ $max_rows = 50; }
+if (!isset($users_max_rows))
+ $users_max_rows = 50;
else
-{ $max_rows = intval($max_rows); }
+ $users_max_rows = intval($users_max_rows);
-if (!isset($offset))
-{ $offset = 0; }
+if (!isset($users_offset))
+ $users_offset = 0;
else
-{ $offset = intval($offset); }
+ $users_offset = intval($users_offset);
-$result = db_execute("SELECT user_name,realname,user_id,spamscore FROM user WHERE status='A' AND spamscore > 0 ORDER BY spamscore DESC LIMIT ?,?", array($offset,($max_rows+1)));
+$result = db_execute("SELECT user_name,realname,user_id,spamscore FROM user WHERE status='A' AND spamscore > 0 ORDER BY spamscore DESC LIMIT ?,?", array($users_offset,($users_max_rows+1)));
if (!db_numrows($result))
-{
- print '<p>'._("No suspects found").'</p>';
-}
+ {
+ print '<p>'._("No suspects found").'</p>';
+ }
else
-{
- print html_build_list_table_top($title_arr);
+ {
+ print html_build_list_table_top($title_arr);
- $i = 0;
- while ($entry = db_fetch_array($result))
- {
- $i++;
-
- # the sql was artificially asked to search more result than the number
- # we print. If $i > $max, it means that there were more results than
- # the max, we wont print these more, but below we will add next/prev
- # links
- if ($i > $max_rows)
- { break; }
-
- $res_score = db_execute("SELECT trackers_spamscore.artifact,trackers_spamscore.item_id,trackers_spamscore.comment_id,user.user_name FROM trackers_spamscore,user WHERE trackers_spamscore.affected_user_id=? AND user.user_id=trackers_spamscore.reporter_user_id LIMIT 50", array($entry['user_id']));
- $flagged_by = '';
- $incriminated_content = '';
- $seen_before = array();
- while ($entry_score = db_fetch_array($res_score))
- {
- if (!isset($seen_before[$entry_score['user_name']]))
- {
- $flagged_by .= utils_user_link($entry_score['user_name']).', ';
- $seen_before[$entry_score['user_name']] = true;
- }
+ $i = 0;
+ while ($entry = db_fetch_array($result))
+ {
+ $i++;
+
+ # the sql was artificially asked to search more result than the number
+ # we print. If $i > $max, it means that there were more results than
+ # the max, we wont print these more, but below we will add next/prev
+ # links
+ if ($i > $users_max_rows)
+ break;
+
+ $res_score = db_execute("SELECT trackers_spamscore.artifact,trackers_spamscore.item_id,trackers_spamscore.comment_id,user.user_name FROM trackers_spamscore,user WHERE trackers_spamscore.affected_user_id=? AND user.user_id=trackers_spamscore.reporter_user_id LIMIT 50", array($entry['user_id']));
+ $flagged_by = '';
+ $incriminated_content = '';
+ $seen_before = array();
+ while ($entry_score = db_fetch_array($res_score))
+ {
+ if (!isset($seen_before[$entry_score['user_name']]))
+ {
+ $flagged_by .= utils_user_link($entry_score['user_name']).', ';
+ $seen_before[$entry_score['user_