X-Git-Url: http://git.vanrenterghem.biz/git.ikiwiki.info.git/blobdiff_plain/64a8c828b8cfa342118dd6e28b9dff43d83c6311..2cbf60a431d41b3cb0767f1c0fb1ecf50103bcb0:/IkiWiki/Plugin/meta.pm diff --git a/IkiWiki/Plugin/meta.pm b/IkiWiki/Plugin/meta.pm index 849a13e37..55c9ddbd1 100644 --- a/IkiWiki/Plugin/meta.pm +++ b/IkiWiki/Plugin/meta.pm @@ -4,21 +4,31 @@ package IkiWiki::Plugin::meta; use warnings; use strict; -use IkiWiki 2.00; +use IkiWiki 3.00; my %metaheaders; -sub import { #{{{ +sub import { + hook(type => "getsetup", id => "meta", call => \&getsetup); hook(type => "needsbuild", id => "meta", call => \&needsbuild); hook(type => "preprocess", id => "meta", call => \&preprocess, scan => 1); hook(type => "pagetemplate", id => "meta", call => \&pagetemplate); -} # }}} +} + +sub getsetup () { + return + plugin => { + safe => 1, + rebuild => undef, + }, +} -sub needsbuild (@) { #{{{ +sub needsbuild (@) { my $needsbuild=shift; foreach my $page (keys %pagestate) { if (exists $pagestate{$page}{meta}) { - if (grep { $_ eq $pagesources{$page} } @$needsbuild) { + if (exists $pagesources{$page} && + grep { $_ eq $pagesources{$page} } @$needsbuild) { # remove state, it will be re-added # if the preprocessor directive is still # there during the rebuild @@ -28,25 +38,37 @@ sub needsbuild (@) { #{{{ } } -sub scrub ($) { #{{{ +sub scrub ($$) { if (IkiWiki::Plugin::htmlscrubber->can("sanitize")) { - return IkiWiki::Plugin::htmlscrubber::sanitize(content => shift); + return IkiWiki::Plugin::htmlscrubber::sanitize( + content => shift, destpage => shift); } else { return shift; } -} #}}} +} + +sub safeurl ($) { + my $url=shift; + if (exists $IkiWiki::Plugin::htmlscrubber::{safe_url_regexp} && + defined $IkiWiki::Plugin::htmlscrubber::safe_url_regexp) { + return $url=~/$IkiWiki::Plugin::htmlscrubber::safe_url_regexp/; + } + else { + return 1; + } +} -sub htmlize ($$$) { #{{{ +sub htmlize ($$$) { my $page = shift; my $destpage = shift; - return IkiWiki::htmlize($page, pagetype($pagesources{$page}), + return IkiWiki::htmlize($page, $destpage, pagetype($pagesources{$page}), IkiWiki::linkify($page, $destpage, IkiWiki::preprocess($page, $destpage, shift))); } -sub preprocess (@) { #{{{ +sub preprocess (@) { return "" unless @_; my %params=@_; my $key=shift; @@ -66,6 +88,15 @@ sub preprocess (@) { #{{{ # Metadata collection that needs to happen during the scan pass. if ($key eq 'title') { $pagestate{$page}{meta}{title}=HTML::Entities::encode_numeric($value); + return ""; + } + elsif ($key eq 'description') { + $pagestate{$page}{meta}{description}=HTML::Entities::encode_numeric($value); + # fallthrough + } + elsif ($key eq 'guid') { + $pagestate{$page}{meta}{guid}=HTML::Entities::encode_numeric($value); + # fallthrough } elsif ($key eq 'license') { push @{$metaheaders{$page}}, ''; @@ -79,7 +110,7 @@ sub preprocess (@) { #{{{ } elsif ($key eq 'link' && ! %params) { # hidden WikiLink - push @{$links{$page}}, $value; + add_link($page, $value); return ""; } elsif ($key eq 'author') { @@ -87,26 +118,38 @@ sub preprocess (@) { #{{{ # fallthorough } elsif ($key eq 'authorurl') { - $pagestate{$page}{meta}{authorurl}=$value; + $pagestate{$page}{meta}{authorurl}=$value if safeurl($value); # fallthrough } - - if (! defined wantarray) { - # avoid collecting duplicate data during scan pass - return; + elsif ($key eq 'permalink') { + $pagestate{$page}{meta}{permalink}=$value if safeurl($value); + # fallthrough } - - # Metadata collection that happens only during preprocessing pass. - if ($key eq 'date') { + elsif ($key eq 'date') { eval q{use Date::Parse}; if (! $@) { my $time = str2time($value); $IkiWiki::pagectime{$page}=$time if defined $time; } } - elsif ($key eq 'permalink') { - $pagestate{$page}{meta}{permalink}=$value; - push @{$metaheaders{$page}}, scrub(''); + elsif ($key eq 'updated') { + eval q{use Date::Parse}; + if (! $@) { + my $time = str2time($value); + $pagestate{$page}{meta}{updated}=$time if defined $time; + } + } + + if (! defined wantarray) { + # avoid collecting duplicate data during scan pass + return; + } + + # Metadata handling that happens only during preprocessing pass. + if ($key eq 'permalink') { + if (safeurl($value)) { + push @{$metaheaders{$page}}, scrub('', $destpage); + } } elsif ($key eq 'stylesheet') { my $rel=exists $params{rel} ? $params{rel} : "alternate stylesheet"; @@ -115,7 +158,7 @@ sub preprocess (@) { #{{{ # editable page as a stylesheet my $stylesheet=bestlink($page, $value.".css"); if (! length $stylesheet) { - return "[[meta ".gettext("stylesheet not found")."]]"; + error gettext("stylesheet not found") } push @{$metaheaders{$page}}, '"; } elsif ($key eq 'openid') { - if (exists $params{server}) { + my $delegate=0; # both by default + if (exists $params{delegate}) { + $delegate = 1 if lc $params{delegate} eq 'openid'; + $delegate = 2 if lc $params{delegate} eq 'openid2'; + } + if (exists $params{server} && safeurl($params{server})) { + push @{$metaheaders{$page}}, '' if $delegate ne 2; push @{$metaheaders{$page}}, ''; + '" rel="openid2.provider" />' if $delegate ne 1; + } + if (safeurl($value)) { + push @{$metaheaders{$page}}, '' if $delegate ne 2; + push @{$metaheaders{$page}}, '' if $delegate ne 1; + } + if (exists $params{"xrds-location"} && safeurl($params{"xrds-location"})) { + push @{$metaheaders{$page}}, ''; } - push @{$metaheaders{$page}}, ''; } elsif ($key eq 'redir') { return "" if $page ne $destpage; @@ -136,11 +194,11 @@ sub preprocess (@) { #{{{ if ($value !~ /^\w+:\/\//) { my ($redir_page, $redir_anchor) = split /\#/, $value; - add_depends($page, $redir_page); my $link=bestlink($page, $redir_page); if (! length $link) { - return "[[meta ".gettext("redir page not found")."]]"; + error gettext("redir page not found") } + add_depends($page, $link, deptype("presence")); $value=urlto($link, $page); $value.='#'.$redir_anchor if defined $redir_anchor; @@ -152,7 +210,7 @@ sub preprocess (@) { #{{{ my %seen; while (exists $pagestate{$at}{meta}{redir}) { if ($seen{$at}) { - return "[[meta ".gettext("redir cycle is not allowed")."]]"; + error gettext("redir cycle is not allowed") } $seen{$at}=1; $at=$pagestate{$at}{meta}{redir}; @@ -162,9 +220,9 @@ sub preprocess (@) { #{{{ $value=encode_entities($value); } my $delay=int(exists $params{delay} ? $params{delay} : 0); - my $redir=""; + my $redir=""; if (! $safe) { - $redir=scrub($redir); + $redir=scrub($redir, $destpage); } push @{$metaheaders{$page}}, $redir; } @@ -174,18 +232,26 @@ sub preprocess (@) { #{{{ join(" ", map { encode_entities($_)."=\"".encode_entities(decode_entities($params{$_}))."\"" } keys %params). - " />\n"); + " />\n", $destpage); } } + elsif ($key eq 'robots') { + push @{$metaheaders{$page}}, ''; + } + elsif ($key eq 'description') { + push @{$metaheaders{$page}}, ''; + } else { push @{$metaheaders{$page}}, scrub(''); + '" content="'.encode_entities($value).'" />', $destpage); } return ""; -} # }}} +} -sub pagetemplate (@) { #{{{ +sub pagetemplate (@) { my %params=@_; my $page=$params{page}; my $destpage=$params{destpage}; @@ -201,7 +267,7 @@ sub pagetemplate (@) { #{{{ $template->param(title_overridden => 1); } - foreach my $field (qw{author authorurl permalink}) { + foreach my $field (qw{author authorurl description permalink}) { $template->param($field => $pagestate{$page}{meta}{$field}) if exists $pagestate{$page}{meta}{$field} && $template->query(name => $field); } @@ -213,58 +279,56 @@ sub pagetemplate (@) { #{{{ $template->param($field => htmlize($page, $destpage, $pagestate{$page}{meta}{$field})); } } -} # }}} +} -sub match { #{{{ +sub match { my $field=shift; my $page=shift; # turn glob into a safe regexp - my $re=quotemeta(shift); - $re=~s/\\\*/.*/g; - $re=~s/\\\?/./g; + my $re=IkiWiki::glob2re(shift); my $val; if (exists $pagestate{$page}{meta}{$field}) { $val=$pagestate{$page}{meta}{$field}; } elsif ($field eq 'title') { - $val=pagetitle($page); + $val = pagetitle($page); } if (defined $val) { if ($val=~/^$re$/i) { - return IkiWiki::SuccessReason->new("$re matches $field of $page"); + return IkiWiki::SuccessReason->new("$re matches $field of $page", $page => $IkiWiki::DEPEND_CONTENT, "" => 1); } else { - return IkiWiki::FailReason->new("$re does not match $field of $page"); + return IkiWiki::FailReason->new("$re does not match $field of $page", "" => 1); } } else { - return IkiWiki::FailReason->new("$page does not have a $field"); + return IkiWiki::FailReason->new("$page does not have a $field", "" => 1); } -} #}}} +} package IkiWiki::PageSpec; -sub match_title ($$;@) { #{{{ - IkiWiki::Plugin::meta::match("title", @_); -} #}}} +sub match_title ($$;@) { + IkiWiki::Plugin::meta::match("title", @_); +} -sub match_author ($$;@) { #{{{ +sub match_author ($$;@) { IkiWiki::Plugin::meta::match("author", @_); -} #}}} +} -sub match_authorurl ($$;@) { #{{{ +sub match_authorurl ($$;@) { IkiWiki::Plugin::meta::match("authorurl", @_); -} #}}} +} -sub match_license ($$;@) { #{{{ +sub match_license ($$;@) { IkiWiki::Plugin::meta::match("license", @_); -} #}}} +} -sub match_copyright ($$;@) { #{{{ +sub match_copyright ($$;@) { IkiWiki::Plugin::meta::match("copyright", @_); -} #}}} +} 1