diff options
Diffstat (limited to 'IkiWiki')
-rw-r--r-- | IkiWiki/CGI.pm | 5 | ||||
-rw-r--r-- | IkiWiki/Plugin/apache404.pm | 77 | ||||
-rw-r--r-- | IkiWiki/Plugin/comments.pm | 34 | ||||
-rw-r--r-- | IkiWiki/Plugin/goto.pm | 76 | ||||
-rw-r--r-- | IkiWiki/Plugin/recentchanges.pm | 47 | ||||
-rw-r--r-- | IkiWiki/Wrapper.pm | 3 |
6 files changed, 165 insertions, 77 deletions
diff --git a/IkiWiki/CGI.pm b/IkiWiki/CGI.pm index 3fadc462e..c91914564 100644 --- a/IkiWiki/CGI.pm +++ b/IkiWiki/CGI.pm @@ -239,6 +239,9 @@ sub check_banned ($$) { print $q->header(-status => "403 Forbidden"); $session->delete(); print gettext("You are banned."); + # Internet Explorer won't show custom 404 responses + # unless they're >= 512 bytes + print " " x 512; cgi_savesession($session); exit; } @@ -317,7 +320,7 @@ sub cgi (;$$) { error("\"do\" parameter missing"); } } - + # Need to lock the wiki before getting a session. lockwiki(); loadindex(); diff --git a/IkiWiki/Plugin/apache404.pm b/IkiWiki/Plugin/apache404.pm new file mode 100644 index 000000000..e7ce70435 --- /dev/null +++ b/IkiWiki/Plugin/apache404.pm @@ -0,0 +1,77 @@ +#!/usr/bin/perl +# Copyright © 2009 Simon McVittie <http://smcv.pseudorandom.co.uk/> +# Licensed under the GNU GPL, version 2, or any later version published by the +# Free Software Foundation +package IkiWiki::Plugin::apache404; + +use warnings; +use strict; +use IkiWiki 3.00; + +sub import { + hook(type => "cgi", id => 'apache404', call => \&cgi); + IkiWiki::loadplugin("goto"); +} + +sub getsetup () { + return + plugin => { + # not really a matter of safety, but enabling/disabling + # through a web interface is useless - it needs web + # server admin action too + safe => 0, + rebuild => 0, + } +} + +sub cgi_page_from_404 ($$$) { + my $path = shift; + my $baseurl = shift; + my $usedirs = shift; + + # fail if missing from environment or whatever + return undef unless defined $path; + return undef unless defined $baseurl; + + # with usedirs on, path is like /~fred/foo/bar/ or /~fred/foo/bar or + # /~fred/foo/bar/index.html + # with usedirs off, path is like /~fred/foo/bar.html + # baseurl is like 'http://people.example.com/~fred' + + # convert baseurl to ~fred + unless ($baseurl =~ s{^https?://[^/]+/?}{}) { + return undef; + } + + # convert path to /~fred/foo/bar + if ($usedirs) { + $path =~ s/\/*(?:index\.$config{htmlext})?$//; + } + else { + $path =~ s/\.$config{htmlext}$//; + } + + # remove /~fred/ + unless ($path =~ s{^/*\Q$baseurl\E/*}{}) { + return undef; + } + + # special case for the index + unless ($path) { + return 'index'; + } + + return $path; +} + +sub cgi ($) { + my $cgi=shift; + + if ($ENV{REDIRECT_STATUS} eq '404') { + my $page = cgi_page_from_404($ENV{REDIRECT_URL}, + $config{url}, $config{usedirs}); + IkiWiki::Plugin::goto::cgi_goto($cgi, $page); + } +} + +1; diff --git a/IkiWiki/Plugin/comments.pm b/IkiWiki/Plugin/comments.pm index cbb3374c2..3cdffe856 100644 --- a/IkiWiki/Plugin/comments.pm +++ b/IkiWiki/Plugin/comments.pm @@ -25,8 +25,9 @@ sub import { hook(type => "sessioncgi", id => 'comment', call => \&sessioncgi); hook(type => "htmlize", id => "_comment", call => \&htmlize); hook(type => "pagetemplate", id => "comments", call => \&pagetemplate); - hook(type => "cgi", id => "comments", call => \&linkcgi); hook(type => "formbuilder_setup", id => "comments", call => \&formbuilder_setup); + # Load goto to fix up user page links for logged-in commenters + IkiWiki::loadplugin("goto"); IkiWiki::loadplugin("inline"); } @@ -167,7 +168,7 @@ sub preprocess { } else { $commentauthorurl = IkiWiki::cgiurl( - do => 'commenter', + do => 'goto', page => (length $config{userdir} ? "$config{userdir}/$commentuser" : "$commentuser")); @@ -235,35 +236,6 @@ sub preprocess { return $content; } -# This is exactly the same as recentchanges_link :-( -sub linkcgi ($) { - my $cgi=shift; - if (defined $cgi->param('do') && $cgi->param('do') eq "commenter") { - - my $page=decode_utf8($cgi->param("page")); - if (! defined $page) { - error("missing page parameter"); - } - - IkiWiki::loadindex(); - - my $link=bestlink("", $page); - if (! length $link) { - print "Content-type: text/html\n\n"; - print IkiWiki::misctemplate(gettext(gettext("missing page")), - "<p>". - sprintf(gettext("The page %s does not exist."), - htmllink("", "", $page)). - "</p>"); - } - else { - IkiWiki::redirect($cgi, urlto($link, undef, 1)); - } - - exit; - } -} - sub sessioncgi ($$) { my $cgi=shift; my $session=shift; diff --git a/IkiWiki/Plugin/goto.pm b/IkiWiki/Plugin/goto.pm new file mode 100644 index 000000000..9e7a2621f --- /dev/null +++ b/IkiWiki/Plugin/goto.pm @@ -0,0 +1,76 @@ +#!/usr/bin/perl +package IkiWiki::Plugin::goto; + +use warnings; +use strict; +use IkiWiki 3.00; + +sub import { + hook(type => "cgi", id => 'goto', call => \&cgi); +} + +sub getsetup () { + return + plugin => { + safe => 1, + rebuild => 0, + } +} + +# cgi_goto(CGI, [page]) +# Redirect to a specified page, or display "not found". If not specified, +# the page param from the CGI object is used. +sub cgi_goto ($;$) { + my $q = shift; + my $page = shift; + + if (!defined $page) { + $page = IkiWiki::decode_utf8($q->param("page")); + + if (!defined $page) { + error("missing page parameter"); + } + } + + IkiWiki::loadindex(); + + # If the page is internal (like a comment), see if it has a + # permalink. Comments do. + if (IkiWiki::isinternal($page) && + defined $pagestate{$page}{meta}{permalink}) { + redirect($q, $pagestate{$page}{meta}{permalink}); + } + + my $link = bestlink("", $page); + + if (! length $link) { + print $q->header(-status => "404 Not Found"); + print IkiWiki::misctemplate(gettext("missing page"), + "<p>". + sprintf(gettext("The page %s does not exist."), + htmllink("", "", $page)). + "</p>". + # Internet Explorer won't show custom 404 responses + # unless they're >= 512 bytes + (" " x 512)); + } + else { + IkiWiki::redirect($q, urlto($link, undef, 1)); + } + + exit; +} + +sub cgi ($) { + my $cgi=shift; + my $do = $cgi->param('do'); + + if (defined $do && ($do eq 'goto' || $do eq 'commenter' || + $do eq 'recentchanged_link')) { + # goto is the preferred name for this; recentchanges_link and + # commenter are for compatibility with any saved URLs + cgi_goto($cgi); + } +} + +1; diff --git a/IkiWiki/Plugin/recentchanges.pm b/IkiWiki/Plugin/recentchanges.pm index ef108b3f0..329dd6f32 100644 --- a/IkiWiki/Plugin/recentchanges.pm +++ b/IkiWiki/Plugin/recentchanges.pm @@ -13,7 +13,8 @@ sub import { hook(type => "refresh", id => "recentchanges", call => \&refresh); hook(type => "pagetemplate", id => "recentchanges", call => \&pagetemplate); hook(type => "htmlize", id => "_change", call => \&htmlize); - hook(type => "cgi", id => "recentchanges", call => \&cgi); + # Load goto to fix up links from recentchanges + IkiWiki::loadplugin("goto"); } sub getsetup () { @@ -79,48 +80,6 @@ sub htmlize (@) { return $params{content}; } -sub cgi ($) { - my $cgi=shift; - if (defined $cgi->param('do') && $cgi->param('do') eq "recentchanges_link") { - # This is a link from a change page to some - # other page. Since the change pages are only generated - # once, statically, links on them won't be updated if the - # page they link to is deleted, or newly created, or - # changes for whatever reason. So this CGI handles that - # dynamic linking stuff. - my $page=decode_utf8($cgi->param("page")); - if (!defined $page) { - error("missing page parameter"); - } - - IkiWiki::loadindex(); - - # If the page is internal (like a comment), see if it has a - # permalink. Comments do. - if (IkiWiki::isinternal($page) && - defined $pagestate{$page}{meta}{permalink}) { - IkiWiki::redirect($cgi, - $pagestate{$page}{meta}{permalink}); - exit; - } - - my $link=bestlink("", $page); - if (! length $link) { - print "Content-type: text/html\n\n"; - print IkiWiki::misctemplate(gettext(gettext("missing page")), - "<p>". - sprintf(gettext("The page %s does not exist."), - htmllink("", "", $page)). - "</p>"); - } - else { - IkiWiki::redirect($cgi, urlto($link, undef, 1)); - } - - exit; - } -} - sub store ($$$) { my $change=shift; @@ -138,7 +97,7 @@ sub store ($$$) { if (length $config{cgiurl}) { $_->{link} = "<a href=\"". IkiWiki::cgiurl( - do => "recentchanges_link", + do => "goto", page => $_->{page} ). "\" rel=\"nofollow\">". diff --git a/IkiWiki/Wrapper.pm b/IkiWiki/Wrapper.pm index dd9971a34..8a6340f58 100644 --- a/IkiWiki/Wrapper.pm +++ b/IkiWiki/Wrapper.pm @@ -28,7 +28,8 @@ sub gen_wrapper () { my @envsave; push @envsave, qw{REMOTE_ADDR QUERY_STRING REQUEST_METHOD REQUEST_URI CONTENT_TYPE CONTENT_LENGTH GATEWAY_INTERFACE - HTTP_COOKIE REMOTE_USER HTTPS} if $config{cgi}; + HTTP_COOKIE REMOTE_USER HTTPS REDIRECT_STATUS + REDIRECT_URL} if $config{cgi}; my $envsave=""; foreach my $var (@envsave) { $envsave.=<<"EOF"; |