Merge commit 'smcv/goto'
commit
3be69a0fe4
|
@ -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();
|
||||
|
|
|
@ -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;
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
|
@ -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\">".
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
[[!template id=plugin name=apache404 author="[[Simon_McVittie|smcv]]"]]
|
||||
[[!tag type/useful]]
|
||||
|
||||
This plugin lets you use the IkiWiki CGI script as an Apache 404 handler,
|
||||
to give the behaviour of various other wiki engines where visiting a
|
||||
nonexistent page provides you with a link to create it.
|
||||
|
||||
To achieve this, put something like this in the wiki's Apache configuration
|
||||
file:
|
||||
|
||||
ErrorDocument 404 /cgi-bin/ikiwiki.cgi
|
|
@ -0,0 +1,10 @@
|
|||
[[!template id=plugin name=goto author="[[Simon_McVittie|smcv]]"]]
|
||||
[[!tag type/useful]]
|
||||
|
||||
This plugin adds a `do=goto` mode for the IkiWiki CGI script. It's mainly
|
||||
for internal use by the [[apache404]], [[comments]] and [[recentchanges]]
|
||||
plugins, which enable it automatically.
|
||||
|
||||
With this plugin enabled you can link to `ikiwiki.cgi?do=goto&page=some/where`
|
||||
to make a link that will redirect to the page `/some/where` if it exists, or
|
||||
offer a link to create it if it doesn't.
|
|
@ -0,0 +1,45 @@
|
|||
#!/usr/bin/perl
|
||||
use warnings;
|
||||
use strict;
|
||||
use Test::More tests => 17;
|
||||
|
||||
BEGIN { use_ok("IkiWiki::Plugin::apache404"); }
|
||||
|
||||
sub cgi_page_from_404 {
|
||||
return IkiWiki::Plugin::apache404::cgi_page_from_404(shift, shift,
|
||||
shift);
|
||||
}
|
||||
|
||||
$IkiWiki::config{htmlext} = 'html';
|
||||
|
||||
is(cgi_page_from_404('/', 'http://example.com', 1), 'index');
|
||||
is(cgi_page_from_404('/index.html', 'http://example.com', 0), 'index');
|
||||
is(cgi_page_from_404('/', 'http://example.com/', 1), 'index');
|
||||
is(cgi_page_from_404('/index.html', 'http://example.com/', 0), 'index');
|
||||
|
||||
is(cgi_page_from_404('/~user/foo/bar', 'http://example.com/~user', 1),
|
||||
'foo/bar');
|
||||
is(cgi_page_from_404('/~user/foo/bar/index.html', 'http://example.com/~user', 1),
|
||||
'foo/bar');
|
||||
is(cgi_page_from_404('/~user/foo/bar/', 'http://example.com/~user', 1),
|
||||
'foo/bar');
|
||||
is(cgi_page_from_404('/~user/foo/bar.html', 'http://example.com/~user', 0),
|
||||
'foo/bar');
|
||||
|
||||
is(cgi_page_from_404('/~user/foo/bar', 'http://example.com/~user/', 1),
|
||||
'foo/bar');
|
||||
is(cgi_page_from_404('/~user/foo/bar/index.html', 'http://example.com/~user/', 1),
|
||||
'foo/bar');
|
||||
is(cgi_page_from_404('/~user/foo/bar/', 'http://example.com/~user/', 1),
|
||||
'foo/bar');
|
||||
is(cgi_page_from_404('/~user/foo/bar.html', 'http://example.com/~user/', 0),
|
||||
'foo/bar');
|
||||
|
||||
is(cgi_page_from_404('/~user/foo', 'https://example.com/~user', 1),
|
||||
'foo');
|
||||
is(cgi_page_from_404('/~user/foo/index.html', 'https://example.com/~user', 1),
|
||||
'foo');
|
||||
is(cgi_page_from_404('/~user/foo/', 'https://example.com/~user', 1),
|
||||
'foo');
|
||||
is(cgi_page_from_404('/~user/foo.html', 'https://example.com/~user', 0),
|
||||
'foo');
|
Loading…
Reference in New Issue