From: Joey Hess Date: Tue, 6 May 2008 23:06:53 +0000 (-0400) Subject: pinger/pingee now tested and working X-Git-Url: https://sipb.mit.edu/gitweb.cgi/ikiwiki.git/commitdiff_plain/b144831e462e0d2ba8225f6e5f7d9138efb03c77?ds=sidebyside pinger/pingee now tested and working --- 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 diff --git a/debian/changelog b/debian/changelog index f131691b9..4eeb6d0ef 100644 --- a/debian/changelog +++ b/debian/changelog @@ -3,6 +3,8 @@ ikiwiki (2.46) UNRELEASED; urgency=low * aggregate: Add support for web-based triggering of aggregation for people stuck on shared hosting without cron. (Sheesh.) Enabled via the `aggregate_webtrigger` configuration optiom. + * Add pinger and pingee plugins, which allow setting up mirrors and branched + wikis that automatically ping one another to stay up to date. -- Joey Hess Mon, 05 May 2008 19:34:51 -0400 diff --git a/doc/ikiwiki.setup b/doc/ikiwiki.setup index 33710d1d7..a151050e7 100644 --- a/doc/ikiwiki.setup +++ b/doc/ikiwiki.setup @@ -99,7 +99,7 @@ use IkiWiki::Setup::Standard { # Allow generating feeds even if not generated by default? #allowrss => 1, #allowatom => 1, - # Urls to ping with XML-RPC when rss feeds are updated + # Urls to ping with XML-RPC when feeds are updated #pingurl => [qw{http://rpc.technorati.com/rpc/ping}], # Include discussion links on all pages? discussion => 1, @@ -167,4 +167,8 @@ use IkiWiki::Setup::Standard { # For use with the aggregate plugin, to allow aggregation to be # triggered via the web. #aggregate_webtrigger => 1, + + # For use with the pinger plugin, how many seconds to wait before + # timing out. + #pinger_timeout => 15. } diff --git a/doc/plugins/pingee.mdwn b/doc/plugins/pingee.mdwn new file mode 100644 index 000000000..03eeb581c --- /dev/null +++ b/doc/plugins/pingee.mdwn @@ -0,0 +1,11 @@ +[[template id=plugin name=pingee author="[[Joey]]"]] +[[tag type/special-purpose]] + +This plugin causes ikiwiki to listen for pings, typically delivered from +another ikiwiki instance using the [[pinger]] plugin. When a ping is +recieved, ikiwiki will update the wiki, the same as if `ikiwiki --refresh` +were ran at the command line. + +An url such as the following is used to trigger a ping: + + http://mywiki.com/ikiwiki.cgi?do=ping diff --git a/doc/plugins/pinger.mdwn b/doc/plugins/pinger.mdwn new file mode 100644 index 000000000..f747a9f0b --- /dev/null +++ b/doc/plugins/pinger.mdwn @@ -0,0 +1,26 @@ +[[template id=plugin name=pinger author="[[Joey]]"]] +[[tag type/special-purpose]] + +This plugin allows ikiwiki to be configured to hit a URL each time it +updates the wiki. One way to use this is in conjunction with the [[pingee]] +plugin to set up a loosely coupled mirror network, or a branched version of +a wiki. By pinging the mirror or branch each time the main wiki changes, it +can be kept up-to-date. + + \[[!ping from="http://mywiki.com/" + to="http://otherwiki.com/ikiwiki.cgi?do=ping"]] + +The "from" parameter must be identical to the url of the wiki that is doing +the pinging. This is used to prevent ping loops. + +The "to" parameter is the url to ping. The example shows how to ping +another ikiwiki instance. + +The [[cpan LWP]] perl module is used for pinging. Or the [[cpan +LWPx::ParanoidAgent]] perl module is used if available, for added security. +Finally, the [[cpan Crypt::SSLeay]] perl module is needed to support pinging +"https" urls. + +By default the pinger will try to ping a site for 15 seconds before timing +out. This timeout can be changed by setting the `pinger_timeout` +configuration setting in the setup file. diff --git a/po/ikiwiki.pot b/po/ikiwiki.pot index 38a677eae..f8834be1c 100644 --- a/po/ikiwiki.pot +++ b/po/ikiwiki.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2008-05-05 20:05-0400\n" +"POT-Creation-Date: 2008-05-06 18:15-0400\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -71,67 +71,75 @@ msgstr "" msgid "You are banned." msgstr "" -#: ../IkiWiki/Plugin/aggregate.pm:126 +#: ../IkiWiki/Plugin/aggregate.pm:53 +msgid "Aggregation triggered via web." +msgstr "" + +#: ../IkiWiki/Plugin/aggregate.pm:62 +msgid "Nothing to do right now, all feeds are up-to-date!" +msgstr "" + +#: ../IkiWiki/Plugin/aggregate.pm:134 #, perl-format msgid "missing %s parameter" msgstr "" -#: ../IkiWiki/Plugin/aggregate.pm:153 +#: ../IkiWiki/Plugin/aggregate.pm:161 msgid "new feed" msgstr "" -#: ../IkiWiki/Plugin/aggregate.pm:167 +#: ../IkiWiki/Plugin/aggregate.pm:175 msgid "posts" msgstr "" -#: ../IkiWiki/Plugin/aggregate.pm:169 +#: ../IkiWiki/Plugin/aggregate.pm:177 msgid "new" msgstr "" -#: ../IkiWiki/Plugin/aggregate.pm:332 +#: ../IkiWiki/Plugin/aggregate.pm:340 #, perl-format msgid "expiring %s (%s days old)" msgstr "" -#: ../IkiWiki/Plugin/aggregate.pm:339 +#: ../IkiWiki/Plugin/aggregate.pm:347 #, perl-format msgid "expiring %s" msgstr "" -#: ../IkiWiki/Plugin/aggregate.pm:366 +#: ../IkiWiki/Plugin/aggregate.pm:374 #, perl-format msgid "processed ok at %s" msgstr "" -#: ../IkiWiki/Plugin/aggregate.pm:370 +#: ../IkiWiki/Plugin/aggregate.pm:378 #, perl-format msgid "checking feed %s ..." msgstr "" -#: ../IkiWiki/Plugin/aggregate.pm:375 +#: ../IkiWiki/Plugin/aggregate.pm:383 #, perl-format msgid "could not find feed at %s" msgstr "" -#: ../IkiWiki/Plugin/aggregate.pm:390 +#: ../IkiWiki/Plugin/aggregate.pm:398 msgid "feed not found" msgstr "" -#: ../IkiWiki/Plugin/aggregate.pm:401 +#: ../IkiWiki/Plugin/aggregate.pm:409 #, perl-format msgid "(invalid UTF-8 stripped from feed)" msgstr "" -#: ../IkiWiki/Plugin/aggregate.pm:407 +#: ../IkiWiki/Plugin/aggregate.pm:415 #, perl-format msgid "(feed entities escaped)" msgstr "" -#: ../IkiWiki/Plugin/aggregate.pm:413 +#: ../IkiWiki/Plugin/aggregate.pm:421 msgid "feed crashed XML::Feed!" msgstr "" -#: ../IkiWiki/Plugin/aggregate.pm:487 +#: ../IkiWiki/Plugin/aggregate.pm:495 #, perl-format msgid "creating new page %s" msgstr "" @@ -300,6 +308,24 @@ msgstr "" msgid "Your password has been emailed to you." msgstr "" +#: ../IkiWiki/Plugin/pingee.pm:21 +msgid "Ping received." +msgstr "" + +#: ../IkiWiki/Plugin/pinger.pm:39 +#, perl-format +msgid "Updates will ping %s" +msgstr "" + +#: ../IkiWiki/Plugin/pinger.pm:42 +#, perl-format +msgid "Ignoring ping directive for wiki %s" +msgstr "" + +#: ../IkiWiki/Plugin/pinger.pm:58 +msgid "LWP not found, not pinging" +msgstr "" + #: ../IkiWiki/Plugin/poll.pm:64 msgid "vote" msgstr ""