X-Git-Url: https://sipb.mit.edu/gitweb.cgi/ikiwiki.git/blobdiff_plain/20052f888277f270ab846bf8b1eb44714c1009d6..d57d2ecca722cb7c43d2b14ed31f38c3e204079c:/IkiWiki.pm diff --git a/IkiWiki.pm b/IkiWiki.pm index dbf50feb4..dcee376ee 100644 --- a/IkiWiki.pm +++ b/IkiWiki.pm @@ -13,13 +13,13 @@ 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 + %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 +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 @@ -152,18 +152,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", @@ -1538,8 +1531,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}) { @@ -1659,39 +1652,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 ($$;@) { @@ -1819,10 +1840,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; @@ -2146,6 +2169,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; @@ -2231,7 +2257,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}; } @@ -2242,6 +2268,13 @@ sub merge_influences { } } +sub remove_influence { + my $this=shift; + my $torm=shift; + + delete $this->[1]{$torm}; +} + package IkiWiki::ErrorReason; our @ISA = 'IkiWiki::FailReason'; @@ -2270,7 +2303,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 { @@ -2286,6 +2323,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);