use warnings;
use strict;
use IkiWiki 3.00;
+use Encode;
-my $defaulturl='http://test.blogspam.net:8888/';
+my $defaulturl='http://test.blogspam.net:9999/';
+my $client;
sub import {
hook(type => "getsetup", id => "blogspam", call => \&getsetup);
+ hook(type => "checkconfig", id => "blogspam", call => \&checkconfig);
hook(type => "checkcontent", id => "blogspam", call => \&checkcontent);
}
plugin => {
safe => 1,
rebuild => 0,
+ section => "auth",
},
blogspam_pagespec => {
type => 'pagespec',
type => "string",
example => "blacklist=1.2.3.4,blacklist=8.7.6.5,max-links=10",
description => "options to send to blogspam server",
- link => "http://blogspam.net/api/testComment.html#options",
+ link => "http://blogspam.net/api/2.0/testComment.html#options",
safe => 1,
rebuild => 0,
},
blogspam_server => {
type => "string",
default => $defaulturl,
- description => "blogspam server XML-RPC url",
+ description => "blogspam server JSON url",
safe => 1,
rebuild => 0,
},
}
-sub checkcontent (@) {
- my %params=@_;
-
+sub checkconfig () {
+ # This is done at checkconfig time because printing an error
+ # if the module is missing when a spam is posted would not
+ # let the admin know about the problem.
eval q{
- use RPC::XML;
- use RPC::XML::Client;
+ use JSON;
+ use HTTP::Request;
};
- if ($@) {
- warn($@);
- return undef;
- }
+ error $@ if $@;
+
+ # Using the for_url parameter makes sure we crash if used
+ # with an older IkiWiki.pm that didn't automatically try
+ # to use LWPx::ParanoidAgent.
+ $client=useragent(for_url => $config{blogspam_server});
+}
+
+sub checkcontent (@) {
+ my %params=@_;
+ my $session=$params{session};
- if (exists $config{blogspam_pagespec}) {
- return undef
- if ! pagespec_match($params{page}, $config{blogspam_pagespec},
- location => $params{page});
+ my $spec='!admin()';
+ if (exists $config{blogspam_pagespec} &&
+ length $config{blogspam_pagespec}) {
+ $spec.=" and (".$config{blogspam_pagespec}.")";
}
+ my $user=$session->param("name");
+ return undef unless pagespec_match($params{page}, $spec,
+ (defined $user ? (user => $user) : ()),
+ (defined $session->remote_addr() ? (ip => $session->remote_addr()) : ()),
+ location => $params{page});
+
my $url=$defaulturl;
- $url = $params{blogspam_server} if exists $params{blogspam_server};
- my $client = RPC::XML::Client->new($url);
+ $url = $config{blogspam_server} if exists $config{blogspam_server};
- my @options = split(",", $params{blogspam_options})
- if exists $params{blogspam_options};
+ my @options = split(",", $config{blogspam_options})
+ if exists $config{blogspam_options};
# Allow short comments and whitespace-only edits, unless the user
# has overridden min-words themselves.
# and "buy".
push @options, "exclude=stopwords";
- # blogspam API does not have a field for author url, so put it in
- # the content to be checked.
- if (exists $params{url}) {
- $params{content}.="\n".$params{url};
- }
-
- my $res = $client->send_request('testComment', {
- ip => $ENV{REMOTE_ADDR},
- comment => $params{content},
- subject => defined $params{subject} ? $params{subject} : "",
- name => defined $params{author} ? $params{author} : "",
+ my %req=(
+ ip => $session->remote_addr(),
+ comment => encode_utf8(defined $params{diff} ? $params{diff} : $params{content}),
+ subject => encode_utf8(defined $params{subject} ? $params{subject} : ""),
+ name => encode_utf8(defined $params{author} ? $params{author} : ""),
+ link => encode_utf8(exists $params{url} ? $params{url} : ""),
options => join(",", @options),
- site => $config{url},
+ site => encode_utf8($config{url}),
version => "ikiwiki ".$IkiWiki::version,
- });
+ );
+ eval q{use JSON; use HTTP::Request}; # errors handled in checkconfig()
+ my $res = $client->request(
+ HTTP::Request->new(
+ 'POST',
+ $url,
+ [ 'Content-Type' => 'application/json' ],
+ to_json(\%req),
+ ),
+ );
- if (! ref $res || ! defined $res->value) {
+ if (! ref $res || ! $res->is_success()) {
debug("failed to get response from blogspam server ($url)");
return undef;
}
- elsif ($res->value =~ /^SPAM:(.*)/) {
- return gettext("Sorry, but that looks like spam to <a href=\"http://blogspam.net/\">blogspam</a>: ").$1;
+ my $details = from_json($res->content);
+ if ($details->{result} eq 'SPAM') {
+ eval q{use Data::Dumper};
+ debug("blogspam server reports $details->{reason}: ".Dumper(\%req));
+ return gettext("Sorry, but that looks like spam to <a href=\"http://blogspam.net/\">blogspam</a>: ").$details->{reason};
}
- elsif ($res->value ne 'OK') {
- debug(gettext("blogspam server failure: ").$res->value);
+ elsif ($details->{result} ne 'OK') {
+ debug("blogspam server failure: ".$res->content);
return undef;
}
else {