X-Git-Url: https://scripts.mit.edu/gitweb/www/ikiwiki.git/blobdiff_plain/0fa25a361cbb49711938599d6cf06201ce0cc79a..0a139aba823ece3166d29ff2daee0b5c9507b52f:/IkiWiki.pm
diff --git a/IkiWiki.pm b/IkiWiki.pm
index ba2c09c36..5ff1a5ae6 100644
--- a/IkiWiki.pm
+++ b/IkiWiki.pm
@@ -5,26 +5,26 @@ package IkiWiki;
use warnings;
use strict;
use Encode;
-use HTML::Entities;
use URI::Escape q{uri_escape_utf8};
use POSIX ();
use Storable;
use open qw{:utf8 :std};
use vars qw{%config %links %oldlinks %pagemtime %pagectime %pagecase
- %pagestate %wikistate %renderedfiles %oldrenderedfiles
- %pagesources %destsources %depends %depends_simple %hooks
- %forcerebuild %loaded_plugins %typedlinks %oldtypedlinks};
+ %pagestate %wikistate %renderedfiles %oldrenderedfiles
+ %pagesources %destsources %depends %depends_simple @mass_depends
+ %hooks %forcerebuild %loaded_plugins %typedlinks %oldtypedlinks
+ %autofiles};
use Exporter q{import};
-our @EXPORT = qw(hook debug error template htmlpage deptype
- add_depends pagespec_match pagespec_match_list bestlink
- htmllink readfile writefile pagetype srcfile pagename
- displaytime will_render gettext ngettext urlto targetpage
- add_underlay pagetitle titlepage linkpage newpagefile
- inject add_link
- %config %links %pagestate %wikistate %renderedfiles
- %pagesources %destsources %typedlinks);
+our @EXPORT = qw(hook debug error htmlpage template template_depends
+ deptype add_depends pagespec_match pagespec_match_list bestlink
+ htmllink readfile writefile pagetype srcfile pagename
+ displaytime will_render gettext ngettext urlto targetpage
+ add_underlay pagetitle titlepage linkpage newpagefile
+ inject add_link add_autofile
+ %config %links %pagestate %wikistate %renderedfiles
+ %pagesources %destsources %typedlinks);
our $VERSION = 3.00; # plugin interface version, next is ikiwiki version
our $version='unknown'; # VERSION_AUTOREPLACE done by Makefile, DNE
our $installdir='/usr'; # INSTALLDIR_AUTOREPLACE done by Makefile, DNE
@@ -151,18 +151,11 @@ sub getsetup () {
templatedir => {
type => "string",
default => "$installdir/share/ikiwiki/templates",
- description => "location of template files",
+ description => "additional directory to search for template files",
advanced => 1,
safe => 0, # path
rebuild => 1,
},
- templatedirs => {
- type => "internal",
- default => [],
- description => "additional directories containing template files",
- safe => 0,
- rebuild => 0,
- },
underlaydir => {
type => "string",
default => "$installdir/share/ikiwiki/basewiki",
@@ -1089,11 +1082,11 @@ sub htmllink ($$$;@) {
my $cgilink = "";
if (length $config{cgiurl}) {
$cgilink = " "create",
- page => lc($link),
- from => $lpage
- )."\" rel=\"nofollow\">?";
+ cgiurl(
+ do => "create",
+ page => lc($link),
+ from => $lpage
+ )."\" rel=\"nofollow\">?";
}
return "$cgilink$linktext"
}
@@ -1537,8 +1530,8 @@ sub loadindex () {
my $d=$pages->{$src};
my $page=pagename($src);
$pagectime{$page}=$d->{ctime};
+ $pagesources{$page}=$src;
if (! $config{rebuild}) {
- $pagesources{$page}=$src;
$pagemtime{$page}=$d->{mtime};
$renderedfiles{$page}=$d->{dest};
if (exists $d->{links} && ref $d->{links}) {
@@ -1658,39 +1651,67 @@ sub saveindex () {
}
sub template_file ($) {
- my $template=shift;
+ my $name=shift;
+
+ my $tpage=($name =~ s/^\///) ? $name : "templates/$name";
+ if ($name !~ /\.tmpl$/ && exists $pagesources{$tpage}) {
+ $tpage=$pagesources{$tpage};
+ $name.=".tmpl";
+ }
- foreach my $dir ($config{templatedir}, @{$config{templatedirs}},
- "$installdir/share/ikiwiki/templates") {
- return "$dir/$template" if -e "$dir/$template";
+ my $template=srcfile($tpage, 1);
+ if (defined $template) {
+ return $template, $tpage, 1 if wantarray;
+ return $template;
+ }
+ else {
+ $name=~s:/::; # avoid path traversal
+ foreach my $dir ($config{templatedir},
+ "$installdir/share/ikiwiki/templates") {
+ if (-e "$dir/$name") {
+ $template="$dir/$name";
+ last;
+ }
+ }
+ if (defined $template) {
+ return $template, $tpage if wantarray;
+ return $template;
+ }
}
+
return;
}
-sub template_params (@) {
- my $filename=template_file(shift);
-
- if (! defined $filename) {
- return if wantarray;
- return "";
+sub template_depends ($$;@) {
+ my $name=shift;
+ my $page=shift;
+
+ my ($filename, $tpage, $untrusted)=template_file($name);
+ if (defined $page && defined $tpage) {
+ add_depends($page, $tpage);
}
- my @ret=(
+ return unless defined $filename;
+
+ my @opts=(
filter => sub {
my $text_ref = shift;
${$text_ref} = decode_utf8(${$text_ref});
},
- filename => $filename,
loop_context_vars => 1,
die_on_bad_params => 0,
- @_
+ filename => $filename,
+ @_,
+ ($untrusted ? (no_includes => 1) : ()),
);
- return wantarray ? @ret : {@ret};
+ return @opts if wantarray;
+
+ require HTML::Template;
+ return HTML::Template->new(@opts);
}
sub template ($;@) {
- require HTML::Template;
- return HTML::Template->new(template_params(@_));
+ template_depends(shift, undef, @_);
}
sub misctemplate ($$;@) {
@@ -1818,10 +1839,12 @@ sub add_depends ($$;$) {
foreach my $p (keys %pagesources) {
my $r=$sub->($p, location => $page);
my $i=$r->influences;
+ my $static=$r->influences_static;
foreach my $k (keys %$i) {
+ next unless $r || $static || $k eq $page;
$depends_simple{$page}{lc $k} |= $i->{$k};
}
- last if $r->influences_static;
+ last if $static;
}
$depends{$page}{$pagespec} |= $deptype;
@@ -1885,7 +1908,7 @@ sub define_gettext () {
return shift;
}
};
- *ngettext=sub {
+ *ngettext=sub {
$getobj->() if $getobj;
if ($gettext_obj) {
$gettext_obj->nget(@_);
@@ -1950,6 +1973,15 @@ sub add_link ($$;$) {
}
}
+sub add_autofile ($$$) {
+ my $file=shift;
+ my $plugin=shift;
+ my $generator=shift;
+
+ $autofiles{$file}{plugin}=$plugin;
+ $autofiles{$file}{generator}=$generator;
+}
+
sub sortspec_translate ($$) {
my $spec = shift;
my $reverse = shift;
@@ -2136,6 +2168,9 @@ sub pagespec_match_list ($$;@) {
my $r=$sub->($p, %params, location => $page);
error(sprintf(gettext("cannot match pages: %s"), $r))
if $r->isa("IkiWiki::ErrorReason");
+ unless ($r || $r->influences_static) {
+ $r->remove_influence($p);
+ }
$accum |= $r;
if ($r) {
push @matches, $p;
@@ -2221,7 +2256,7 @@ sub merge_influences {
my $anded=shift;
if (! $anded || (($this || %{$this->[1]}) &&
- ($other || %{$other->[1]}))) {
+ ($other || %{$other->[1]}))) {
foreach my $influence (keys %{$other->[1]}) {
$this->[1]{$influence} |= $other->[1]{$influence};
}
@@ -2232,6 +2267,13 @@ sub merge_influences {
}
}
+sub remove_influence {
+ my $this=shift;
+ my $torm=shift;
+
+ delete $this->[1]{$torm};
+}
+
package IkiWiki::ErrorReason;
our @ISA = 'IkiWiki::FailReason';
@@ -2245,7 +2287,7 @@ sub derel ($$) {
if ($path =~ m!^\./!) {
$from=~s#/?[^/]+$## if defined $from;
$path=~s#^\./##;
- $path="$from/$path" if length $from;
+ $path="$from/$path" if defined $from && length $from;
}
return $path;
@@ -2260,7 +2302,11 @@ sub match_glob ($$;@) {
my $regexp=IkiWiki::glob2re($glob);
if ($page=~/^$regexp$/i) {
- if (! IkiWiki::isinternal($page) || $params{internal}) {
+ if ($params{onlypage} &&
+ ! defined IkiWiki::pagetype($IkiWiki::pagesources{$page})) {
+ return IkiWiki::FailReason->new("$page is not a page");
+ }
+ elsif (! IkiWiki::isinternal($page) || $params{internal}) {
return IkiWiki::SuccessReason->new("$glob matches $page");
}
else {
@@ -2276,6 +2322,10 @@ sub match_internal ($$;@) {
return match_glob($_[0], $_[1], @_, internal => 1)
}
+sub match_page ($$;@) {
+ return match_glob($_[0], $_[1], @_, onlypage => 1)
+}
+
sub match_link ($$;@) {
my $page=shift;
my $link=lc(shift);