<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">#!/usr/bin/perl
package IkiWiki::Plugin::pinger;

use warnings;
use strict;
use IkiWiki 3.00;

my %pages;
my $pinged=0;

sub import {
	hook(type =&gt; "getsetup", id =&gt; "pinger", call =&gt; \&amp;getsetup);
	hook(type =&gt; "needsbuild", id =&gt; "pinger", call =&gt; \&amp;needsbuild);
	hook(type =&gt; "preprocess", id =&gt; "ping", call =&gt; \&amp;preprocess);
	hook(type =&gt; "delete", id =&gt; "pinger", call =&gt; \&amp;ping);
	hook(type =&gt; "change", id =&gt; "pinger", call =&gt; \&amp;ping);
}

sub getsetup () {
	return
		plugin =&gt; {
			safe =&gt; 1,
			rebuild =&gt; 0,
		},
		pinger_timeout =&gt; {
			type =&gt; "integer",
			example =&gt; 15,
			description =&gt; "how many seconds to try pinging before timing out",
			safe =&gt; 1,
			rebuild =&gt; 0,
		},
}

sub needsbuild (@) {
	my $needsbuild=shift;
	foreach my $page (keys %pagestate) {
		if (exists $pagestate{$page}{pinger}) {
			$pages{$page}=1;
			if (exists $pagesources{$page} &amp;&amp;
			    grep { $_ eq $pagesources{$page} } @$needsbuild) {
				# remove state, will be re-added if
				# the ping directive is still present
				# on rebuild.
				delete $pagestate{$page}{pinger};
			}
		}
	}
	return $needsbuild;
}

sub preprocess (@) {
	my %params=@_;
	if (! exists $params{from} || ! exists $params{to}) {
		error 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 &amp;&amp; %pages) {
		$pinged=1;
		
		my $ua;
		eval q{use LWPx::ParanoidAgent};
		if (!$@) {
			$ua=LWPx::ParanoidAgent-&gt;new;
		}
		else {
			eval q{use LWP};
			if ($@) {
				debug(gettext("LWP not found, not pinging"));
				return;
			}
			$ua=LWP::UserAgent-&gt;new;
		}
		$ua-&gt;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, '&gt;/dev/null';
		POSIX::setsid() or error("Can't start a new session: $!");
		open STDERR, '&gt;&amp;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-&gt;get($url);
		}
		
		exit 0;
	}
}

1
</pre></body></html>