sequence. To output the next number in the sequence, all a user has to do
is write this on a wiki page:
- [[!fib]]
+ \[[!fib]]
When the page is built, the [[ikiwiki/directive]] will be
replaced by the next number in the sequence.
use warnings;
use strict;
- use IkiWiki 2.00;
+ use IkiWiki 3.00;
Ok, boilerplate is out of the way. Now to add the one function that ikiwiki
expects to find in any module: `import`. The import function is called when
sub fib {
my $num=shift;
- return 0 if $num == 1;
- return 1 if $num == 2;
+ return 0 if $num == 0;
+ return 1 if $num == 1;
return fib($num - 1) + fib($num - 2);
}
sub preprocess {
my %params=@_;
- my $num=$last++;
+ my $num=++$last;
return fib($num);
}
Looks like it works ok, doesn't it? That creates a page that lists:
- 1, 1, 3, 5, 8
+ 1, 1, 2, 3, 5
But what happens if there are two pages that both use fib? Try it out.
If ikiwiki builds both pages in one pass, the sequence will continue
and the standalone page another. The numbers might even skip over part of
the sequence in some cases.
-Obviously, using a global `$last` veriable was a bad idea. It would
+Obviously, using a global `$last` variable was a bad idea. It would
work ok in a more regular cgi-based wiki, which only outputs one page per
run. But since ikiwiki is a wiki *compiler*, things are a bit more
complicated. It's not very hard to fix, though, if we do want the sequence
sub preprocess {
my %params=@_;
my $page=$params{destpage};
- my $num=$last{$page}++;
+ my $num=++$last{$page};
return fib($num);
}
spot:
if (exists $params{seed}) {
- $last{$page}=$params{seed}-1;
+ $last{$page}=$params{seed};
}
But this highlights another issue with the plugin. The `fib()` function is
but that's not the focus of this tutorial. Instead, let's concentrate on
making the plugin use the existing function safely. A good first step would
be a guard on how high it will go.
-
+
my %last;
sub preprocess {
if (exists $params{seed}) {
$last{$page}=$params{seed}-1;
}
- my $num=$last{$page}++;
+ my $num=++$last{$page};
if ($num > 25) {
error "can only calculate the first 25 numbers in the sequence";
}
so that the user can look at the built page and see what went wrong.
Are we done? Nope, there's still a security hole. Consider what `fib()`
-does for numbers less than 1. Or for any number that's not an integer. In
+does for numbers less than 0. Or for any number that's not an integer. In
either case, it will run forever. Here's one way to fix that:
- if (int($num) != $num || $num < 1) {
+ if (int($num) != $num || $num < 0) {
error "positive integers only, please";
}