diff --git a/plugins/wordfilter/wordfilter.pl b/plugins/wordfilter/wordfilter.pl index 6a9f57d..7f326c9 100644 --- a/plugins/wordfilter/wordfilter.pl +++ b/plugins/wordfilter/wordfilter.pl @@ -1,9 +1,11 @@ use POSIX qw(strftime); +use File::stat; my $filename; -my @words; -my $read_date; +my $last_mtime; +my %words_lookup; + my $debug; my $logfile; @@ -12,45 +14,57 @@ sub dolog { return unless $debug; my $ts = strftime("%Y-%m-%d %H:%M:%S", localtime); open(OUT, ">>$logfile"); - print OUT "$ts $str"; + print OUT "$ts $str\n"; close(OUT); } sub refresh_words { - my @now = localtime(); - my $year = $now[5]; - my $mon = $now[4]; - my $mday = $now[3]; - my $dayno = 0 + ($year + 1900) * 10000 + $mon * 100 + $mday; - return unless ($dayno > $read_date); - @words = (); + my ($id) = @_; + + my $stat = stat($filename); + # If the filtered words files doesn't exist, nothing to do + return unless $state; + + # If the filtered words file hasn't been modified, nothing to do + $last_mtime ||= 0; + return unless ($stat->mtime > $last_mtime); + + # The filtered words file has changed. Create a new lookup hash + %words_lookup = (); if (open(my $fh, '<', $filename)) { while (my $row = <$fh>) { chomp($row); next if length($row) < 1; push @words, lc($row); } - dolog("load from " . $filename . ", found " . @words . " words\n"); + dolog("[$id] - '" . $filename . "' modified. Loaded " . scalar(@words) . " words."); close($fh); } - $read_date = $dayno; + + # Create new hash for O(1) lookups + %words_lookup = map { $_ => 1 } @words; + + # update last modified time + $last_mtime = $stat->mtime; } sub create_config { my ($name, $configdata) = @_; $filename = $configdata; - $read_date = 0; - $debug = 1; - $logfile = "/tmp/wordfilter.log"; + $last_mtime = 0; + $debug = 1; + $logfile = "/tmp/wordfilter.log"; } sub check { my ($id, $msg) = @_; - refresh_words; - foreach my $word (@words) { - next unless ($msg =~ /\b${word}\b/); - dolog("reject message " . $id . " containing `" . $word . "' in message: `" . $msg . "'\n"); + refresh_words($id); + my @msg_words = split /\s+/, $msg; + # check each word in the message to see if has any filter words + foreach my $msg_word (@msg_words) { + next unless (exists $words_lookup{lc($msg_word)}); + dolog("[$id] - rejecting message containing '" . $msg_word . "' in message: '" . $msg . "'"); return 8; } return 0;