diff options
Diffstat (limited to 'IkiWiki/Plugin')
-rw-r--r-- | IkiWiki/Plugin/pingee.pm | 33 | ||||
-rw-r--r-- | IkiWiki/Plugin/pinger.pm | 100 |
2 files changed, 133 insertions, 0 deletions
diff --git a/IkiWiki/Plugin/pingee.pm b/IkiWiki/Plugin/pingee.pm new file mode 100644 index 000000000..ee799a57a --- /dev/null +++ b/IkiWiki/Plugin/pingee.pm @@ -0,0 +1,33 @@ +#!/usr/bin/perl +package IkiWiki::Plugin::pingee; + +use warnings; +use strict; +use IkiWiki 2.00; + +sub import { #{{{ + hook(type => "cgi", id => "aggregate", call => \&cgi); +} # }}} + +sub cgi ($) { #{{{ + my $cgi=shift; + + if (defined $cgi->param('do') && $cgi->param("do") eq "ping") { + $|=1; + print "Content-Type: text/plain\n\n"; + $config{cgi}=0; + $config{verbose}=1; + $config{syslog}=0; + print gettext("Ping received.")."\n\n"; + + IkiWiki::lockwiki(); + IkiWiki::loadindex(); + require IkiWiki::Render; + IkiWiki::rcs_update(); + IkiWiki::refresh(); + IkiWiki::saveindex(); + exit 0; + } +} #}}} + +1 diff --git a/IkiWiki/Plugin/pinger.pm b/IkiWiki/Plugin/pinger.pm new file mode 100644 index 000000000..c6fa76e3f --- /dev/null +++ b/IkiWiki/Plugin/pinger.pm @@ -0,0 +1,100 @@ +#!/usr/bin/perl +package IkiWiki::Plugin::pinger; + +use warnings; +use strict; +use IkiWiki 2.00; + +my %pages; +my $pinged=0; + +sub import { #{{{ + hook(type => "needsbuild", id => "pinger", call => \&needsbuild); + hook(type => "preprocess", id => "ping", call => \&preprocess); + hook(type => "delete", id => "pinger", call => \&ping); + hook(type => "change", id => "pinger", call => \&ping); +} # }}} + +sub needsbuild (@) { #{{{ + my $needsbuild=shift; + foreach my $page (keys %pagestate) { + if (exists $pagestate{$page}{pinger}) { + $pages{$page}=1; + if (exists $pagesources{$page} && + grep { $_ eq $pagesources{$page} } @$needsbuild) { + # remove state, will be re-added if + # the ping directive is still present + # on rebuild. + delete $pagestate{$page}{pinger}; + } + } + } +} # }}} + +sub preprocess (@) { #{{{ + my %params=@_; + if (! exists $params{from} || ! exists $params{to}) { + return "[[ping ".gettext("requires 'from' and 'to' parameters")."]]"; + } + if ($params{from} eq $config{url}) { + $pagestate{$params{destpage}}{pinger}{$params{to}}=1; + $pages{$params{destpage}}=1; + return sprintf(gettext("Will ping %s"), $params{to}); + } + else { + return sprintf(gettext("Ignoring ping directive for wiki %s (this wiki is %s)"), $params{from}, $config{url}); + } +} # }}} + +sub ping { + if (! $pinged && %pages) { + $pinged=1; + + my $ua; + eval q{use LWPx::ParanoidAgent}; + if (!$@) { + $ua=LWPx::ParanoidAgent->new; + } + else { + eval q{use LWP}; + if ($@) { + debug(gettext("LWP not found, not pinging")); + return; + } + $ua=LWP::UserAgent->new; + } + $ua->timeout($config{pinger_timeout} || 15); + + # daemonise here so slow pings don't slow down wiki updates + defined(my $pid = fork) or error("Can't fork: $!"); + return if $pid; + chdir '/'; + open STDIN, '/dev/null'; + open STDOUT, '>/dev/null'; + POSIX::setsid() or error("Can't start a new session: $!"); + open STDERR, '>&STDOUT' or error("Can't dup stdout: $!"); + + # Don't need to keep a lock on the wiki as a daemon. + IkiWiki::unlockwiki(); + + my %urls; + foreach my $page (%pages) { + if (exists $pagestate{$page}{pinger}) { + $urls{$_}=1 foreach keys %{$pagestate{$page}{pinger}}; + } + } + foreach my $url (keys %urls) { + # Try to avoid pinging ourselves. If this check + # fails, it's not the end of the world, since we + # only ping when a page was changed, so a ping loop + # will still be avoided. + next if $url=~/^\Q$config{cgiurl}\E/; + + $ua->head($url); + } + + exit 0; + } +} + +1 |