From c2dafcb4e5e8c9f654c0ad5719607366cf84b75a Mon Sep 17 00:00:00 2001
From: Simon McVittie
Date: Sat, 31 Jan 2009 14:36:23 +0000
Subject: CGI: add cgi_goto(CGI, [page])
This redirects to the given page (or if none is given, the page parameter
given to the CGI), or displays an error with a create link if the page
doesn't exist.
---
IkiWiki/CGI.pm | 41 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 41 insertions(+)
diff --git a/IkiWiki/CGI.pm b/IkiWiki/CGI.pm
index 3fadc462e..a6b485edb 100644
--- a/IkiWiki/CGI.pm
+++ b/IkiWiki/CGI.pm
@@ -291,6 +291,47 @@ sub cgi_savesession ($) {
umask($oldmask);
}
+# 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 = decode_utf8($q->param("page"));
+
+ if (!defined $page) {
+ error("missing page parameter");
+ }
+ }
+
+ loadindex();
+
+ # If the page is internal (like a comment), see if it has a
+ # permalink. Comments do.
+ if (isinternal($page) &&
+ defined $pagestate{$page}{meta}{permalink}) {
+ redirect($q, $pagestate{$page}{meta}{permalink});
+ }
+
+ my $link = bestlink("", $page);
+
+ if (! length $link) {
+ print "Content-type: text/html\n\n";
+ print misctemplate(gettext("missing page"),
+ "
".
+ sprintf(gettext("The page %s does not exist."),
+ htmllink("", "", $page)).
+ "
");
+ }
+ else {
+ redirect($q, urlto($link, undef, 1));
+ }
+
+ exit;
+}
+
sub cgi (;$$) {
my $q=shift;
my $session=shift;
--
cgit v1.2.3
From 18f4aeffb1841f8b455a5e31811695102262a06a Mon Sep 17 00:00:00 2001
From: Simon McVittie ".
- sprintf(gettext("The page %s does not exist."),
- htmllink("", "", $page)).
- "
");
- }
- else {
- IkiWiki::redirect($cgi, urlto($link, undef, 1));
- }
-
- exit;
- }
-}
-
sub sessioncgi ($$) {
my $cgi=shift;
my $session=shift;
--
cgit v1.2.3
From a981d6857f1eab350460116c1b5d868ed0215d29 Mon Sep 17 00:00:00 2001
From: Simon McVittie ".
- sprintf(gettext("The page %s does not exist."),
- htmllink("", "", $page)).
- "
");
- }
- else {
- IkiWiki::redirect($cgi, urlto($link, undef, 1));
- }
-
- exit;
- }
-}
-
sub store ($$$) {
my $change=shift;
@@ -138,7 +95,7 @@ sub store ($$$) {
if (length $config{cgiurl}) {
$_->{link} = " "recentchanges_link",
+ do => "goto",
page => $_->{page}
).
"\" rel=\"nofollow\">".
--
cgit v1.2.3
From 5ce3a0130030f3b07e163727f16d212b2fda6259 Mon Sep 17 00:00:00 2001
From: Simon McVittie
Date: Sat, 31 Jan 2009 15:05:17 +0000
Subject: CGI: document why commenter and recentchanges_link are supported
---
IkiWiki/CGI.pm | 2 ++
1 file changed, 2 insertions(+)
diff --git a/IkiWiki/CGI.pm b/IkiWiki/CGI.pm
index 949390e68..f23d44fd6 100644
--- a/IkiWiki/CGI.pm
+++ b/IkiWiki/CGI.pm
@@ -359,6 +359,8 @@ sub cgi (;$$) {
}
}
+ # goto is the preferred name for this; recentchanges_link and
+ # commenter are for compatibility with any saved URLs
if ($do eq 'goto' || $do eq 'recentchanges_link' ||
$do eq 'commenter') {
cgi_goto($q);
--
cgit v1.2.3
From 78d1b2340eeacdad7bcccb9c7fa450ac47728341 Mon Sep 17 00:00:00 2001
From: Simon McVittie
Date: Sat, 31 Jan 2009 16:51:13 +0000
Subject: CGI: if the page is missing, give the "missing page" a 404 status
---
IkiWiki/CGI.pm | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/IkiWiki/CGI.pm b/IkiWiki/CGI.pm
index f23d44fd6..fe8457262 100644
--- a/IkiWiki/CGI.pm
+++ b/IkiWiki/CGI.pm
@@ -318,7 +318,7 @@ sub cgi_goto ($;$) {
my $link = bestlink("", $page);
if (! length $link) {
- print "Content-type: text/html\n\n";
+ print $q->header(-status => "404 Not Found");
print misctemplate(gettext("missing page"),
"".
sprintf(gettext("The page %s does not exist."),
--
cgit v1.2.3
From 3e290ce7eef9de6bad7d30b5855de14090b5edd2 Mon Sep 17 00:00:00 2001
From: Simon McVittie
Date: Sat, 31 Jan 2009 18:06:44 +0000
Subject: IkiWiki::Wrapper: allow REDIRECT_STATUS and REDIRECT_URL through from
environment
This is useful to act as an Apache 404 ErrorDocument.
---
IkiWiki/Wrapper.pm | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
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";
--
cgit v1.2.3
From 8322b8c9c82941c4052bcc8a0d1824a92d6426a0 Mon Sep 17 00:00:00 2001
From: Simon McVittie
Date: Sat, 31 Jan 2009 18:07:42 +0000
Subject: CGI: add cgi_page_from_404(), which remaps a path like $REDIRECT_URL
to an IkiWiki page name
Also add a regression test
---
IkiWiki/CGI.pm | 40 ++++++++++++++++++++++++++++++++++++++++
t/cgi_page_from_404.t | 43 +++++++++++++++++++++++++++++++++++++++++++
2 files changed, 83 insertions(+)
create mode 100755 t/cgi_page_from_404.t
diff --git a/IkiWiki/CGI.pm b/IkiWiki/CGI.pm
index fe8457262..82cad40c8 100644
--- a/IkiWiki/CGI.pm
+++ b/IkiWiki/CGI.pm
@@ -332,6 +332,46 @@ sub cgi_goto ($;$) {
exit;
}
+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 $q=shift;
my $session=shift;
diff --git a/t/cgi_page_from_404.t b/t/cgi_page_from_404.t
new file mode 100755
index 000000000..adbbdf874
--- /dev/null
+++ b/t/cgi_page_from_404.t
@@ -0,0 +1,43 @@
+#!/usr/bin/perl
+use warnings;
+use strict;
+use Test::More tests => 18;
+
+BEGIN { use_ok("IkiWiki"); }
+BEGIN { use_ok("IkiWiki::CGI"); }
+
+sub cgi_page_from_404 { return IkiWiki::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');
--
cgit v1.2.3
From 170b86a2efb1908355f5812eaa3f3de4a2dcaa49 Mon Sep 17 00:00:00 2001
From: Simon McVittie
Date: Sat, 31 Jan 2009 18:09:24 +0000
Subject: CGI: set up goto hook so that /ikiwiki.cgi?do=goto can be an Apache
ErrorDocument
---
IkiWiki/CGI.pm | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/IkiWiki/CGI.pm b/IkiWiki/CGI.pm
index 82cad40c8..7e968d966 100644
--- a/IkiWiki/CGI.pm
+++ b/IkiWiki/CGI.pm
@@ -403,7 +403,14 @@ sub cgi (;$$) {
# commenter are for compatibility with any saved URLs
if ($do eq 'goto' || $do eq 'recentchanges_link' ||
$do eq 'commenter') {
- cgi_goto($q);
+ my $page = undef;
+
+ if ($ENV{REDIRECT_STATUS} eq '404') {
+ $page = cgi_page_from_404($ENV{REDIRECT_URL},
+ $config{url}, $config{usedirs});
+ }
+
+ cgi_goto($q, $page);
}
# Need to lock the wiki before getting a session.
--
cgit v1.2.3
From dedbe110f27e77051c8e49e0a53b8cdd148dd752 Mon Sep 17 00:00:00 2001
From: Simon McVittie
Date: Sat, 31 Jan 2009 18:26:37 +0000
Subject: CGI: pad error responses with 512 bytes of spaces so IE will display
them
IE displays its own error responses unless the server's was >= 512 bytes.
http://support.microsoft.com/default.aspx?scid=kb;en-us;Q294807
---
IkiWiki/CGI.pm | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/IkiWiki/CGI.pm b/IkiWiki/CGI.pm
index 7e968d966..8734cdd49 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;
}
@@ -323,7 +326,10 @@ sub cgi_goto ($;$) {
"
".
sprintf(gettext("The page %s does not exist."),
htmllink("", "", $page)).
- "
");
+ "".
+ # Internet Explorer won't show custom 404 responses
+ # unless they're >= 512 bytes
+ (" " x 512));
}
else {
redirect($q, urlto($link, undef, 1));
--
cgit v1.2.3
From fb0e3a7dbc7f71f8684c99c20d319671e60354b1 Mon Sep 17 00:00:00 2001
From: Simon McVittie
Date: Sat, 31 Jan 2009 18:27:54 +0000
Subject: Add tip explaining how to use ikiwiki as a 404 handler
---
doc/tips/apache_404_handler.mdwn | 10 ++++++++++
1 file changed, 10 insertions(+)
create mode 100644 doc/tips/apache_404_handler.mdwn
diff --git a/doc/tips/apache_404_handler.mdwn b/doc/tips/apache_404_handler.mdwn
new file mode 100644
index 000000000..0fda759e7
--- /dev/null
+++ b/doc/tips/apache_404_handler.mdwn
@@ -0,0 +1,10 @@
+[[!meta title="Apache 404 handler"]]
+
+Sufficiently recent versions of IkiWiki can be used 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?do=goto
--
cgit v1.2.3
From 46b880f8390ac82d746add01de38a05155743374 Mon Sep 17 00:00:00 2001
From: Simon McVittie
Date: Sat, 31 Jan 2009 22:32:10 +0000
Subject: Split apache404 into an independent plugin
Also make it ignore the 'do' parameter at Joey's suggestion, to have one
less thing to remember when configuring.
---
IkiWiki/CGI.pm | 49 +-------------------------
IkiWiki/Plugin/apache404.pm | 76 ++++++++++++++++++++++++++++++++++++++++
doc/plugins/apache404.mdwn | 11 ++++++
doc/tips/apache_404_handler.mdwn | 10 ------
t/apache404.t | 45 ++++++++++++++++++++++++
t/cgi_page_from_404.t | 43 -----------------------
6 files changed, 133 insertions(+), 101 deletions(-)
create mode 100644 IkiWiki/Plugin/apache404.pm
create mode 100644 doc/plugins/apache404.mdwn
delete mode 100644 doc/tips/apache_404_handler.mdwn
create mode 100755 t/apache404.t
delete mode 100755 t/cgi_page_from_404.t
diff --git a/IkiWiki/CGI.pm b/IkiWiki/CGI.pm
index 8734cdd49..e75ebcd27 100644
--- a/IkiWiki/CGI.pm
+++ b/IkiWiki/CGI.pm
@@ -338,46 +338,6 @@ sub cgi_goto ($;$) {
exit;
}
-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 $q=shift;
my $session=shift;
@@ -409,14 +369,7 @@ sub cgi (;$$) {
# commenter are for compatibility with any saved URLs
if ($do eq 'goto' || $do eq 'recentchanges_link' ||
$do eq 'commenter') {
- my $page = undef;
-
- if ($ENV{REDIRECT_STATUS} eq '404') {
- $page = cgi_page_from_404($ENV{REDIRECT_URL},
- $config{url}, $config{usedirs});
- }
-
- cgi_goto($q, $page);
+ cgi_goto($q);
}
# Need to lock the wiki before getting a session.
diff --git a/IkiWiki/Plugin/apache404.pm b/IkiWiki/Plugin/apache404.pm
new file mode 100644
index 000000000..3ac6b3af5
--- /dev/null
+++ b/IkiWiki/Plugin/apache404.pm
@@ -0,0 +1,76 @@
+#!/usr/bin/perl
+# Copyright © 2009 Simon McVittie
+# 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);
+}
+
+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::cgi_goto($cgi, $page);
+ }
+}
+
+1;
diff --git a/doc/plugins/apache404.mdwn b/doc/plugins/apache404.mdwn
new file mode 100644
index 000000000..bab8fb59d
--- /dev/null
+++ b/doc/plugins/apache404.mdwn
@@ -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
diff --git a/doc/tips/apache_404_handler.mdwn b/doc/tips/apache_404_handler.mdwn
deleted file mode 100644
index 0fda759e7..000000000
--- a/doc/tips/apache_404_handler.mdwn
+++ /dev/null
@@ -1,10 +0,0 @@
-[[!meta title="Apache 404 handler"]]
-
-Sufficiently recent versions of IkiWiki can be used 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?do=goto
diff --git a/t/apache404.t b/t/apache404.t
new file mode 100755
index 000000000..00fc35250
--- /dev/null
+++ b/t/apache404.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');
diff --git a/t/cgi_page_from_404.t b/t/cgi_page_from_404.t
deleted file mode 100755
index adbbdf874..000000000
--- a/t/cgi_page_from_404.t
+++ /dev/null
@@ -1,43 +0,0 @@
-#!/usr/bin/perl
-use warnings;
-use strict;
-use Test::More tests => 18;
-
-BEGIN { use_ok("IkiWiki"); }
-BEGIN { use_ok("IkiWiki::CGI"); }
-
-sub cgi_page_from_404 { return IkiWiki::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');
--
cgit v1.2.3
From c886bea32084a920f3ba26b3f96327681f5db917 Mon Sep 17 00:00:00 2001
From: Simon McVittie
Date: Sat, 31 Jan 2009 23:01:10 +0000
Subject: Split cgi_goto into a goto plugin
---
IkiWiki/CGI.pm | 51 ---------------------------
IkiWiki/Plugin/apache404.pm | 3 +-
IkiWiki/Plugin/comments.pm | 2 ++
IkiWiki/Plugin/goto.pm | 76 +++++++++++++++++++++++++++++++++++++++++
IkiWiki/Plugin/recentchanges.pm | 2 ++
doc/plugins/goto.mdwn | 10 ++++++
6 files changed, 92 insertions(+), 52 deletions(-)
create mode 100644 IkiWiki/Plugin/goto.pm
create mode 100644 doc/plugins/goto.mdwn
diff --git a/IkiWiki/CGI.pm b/IkiWiki/CGI.pm
index e75ebcd27..c91914564 100644
--- a/IkiWiki/CGI.pm
+++ b/IkiWiki/CGI.pm
@@ -294,50 +294,6 @@ sub cgi_savesession ($) {
umask($oldmask);
}
-# 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 = decode_utf8($q->param("page"));
-
- if (!defined $page) {
- error("missing page parameter");
- }
- }
-
- loadindex();
-
- # If the page is internal (like a comment), see if it has a
- # permalink. Comments do.
- if (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 misctemplate(gettext("missing page"),
- "".
- sprintf(gettext("The page %s does not exist."),
- htmllink("", "", $page)).
- "
".
- # Internet Explorer won't show custom 404 responses
- # unless they're >= 512 bytes
- (" " x 512));
- }
- else {
- redirect($q, urlto($link, undef, 1));
- }
-
- exit;
-}
-
sub cgi (;$$) {
my $q=shift;
my $session=shift;
@@ -365,13 +321,6 @@ sub cgi (;$$) {
}
}
- # goto is the preferred name for this; recentchanges_link and
- # commenter are for compatibility with any saved URLs
- if ($do eq 'goto' || $do eq 'recentchanges_link' ||
- $do eq 'commenter') {
- cgi_goto($q);
- }
-
# Need to lock the wiki before getting a session.
lockwiki();
loadindex();
diff --git a/IkiWiki/Plugin/apache404.pm b/IkiWiki/Plugin/apache404.pm
index 3ac6b3af5..e7ce70435 100644
--- a/IkiWiki/Plugin/apache404.pm
+++ b/IkiWiki/Plugin/apache404.pm
@@ -10,6 +10,7 @@ use IkiWiki 3.00;
sub import {
hook(type => "cgi", id => 'apache404', call => \&cgi);
+ IkiWiki::loadplugin("goto");
}
sub getsetup () {
@@ -69,7 +70,7 @@ sub cgi ($) {
if ($ENV{REDIRECT_STATUS} eq '404') {
my $page = cgi_page_from_404($ENV{REDIRECT_URL},
$config{url}, $config{usedirs});
- IkiWiki::cgi_goto($cgi, $page);
+ IkiWiki::Plugin::goto::cgi_goto($cgi, $page);
}
}
diff --git a/IkiWiki/Plugin/comments.pm b/IkiWiki/Plugin/comments.pm
index 995d1f4eb..3cdffe856 100644
--- a/IkiWiki/Plugin/comments.pm
+++ b/IkiWiki/Plugin/comments.pm
@@ -26,6 +26,8 @@ sub import {
hook(type => "htmlize", id => "_comment", call => \&htmlize);
hook(type => "pagetemplate", id => "comments", call => \&pagetemplate);
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");
}
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"),
+ "".
+ sprintf(gettext("The page %s does not exist."),
+ htmllink("", "", $page)).
+ "
".
+ # 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 56e80e7b8..329dd6f32 100644
--- a/IkiWiki/Plugin/recentchanges.pm
+++ b/IkiWiki/Plugin/recentchanges.pm
@@ -13,6 +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);
+ # Load goto to fix up links from recentchanges
+ IkiWiki::loadplugin("goto");
}
sub getsetup () {
diff --git a/doc/plugins/goto.mdwn b/doc/plugins/goto.mdwn
new file mode 100644
index 000000000..21dda16b2
--- /dev/null
+++ b/doc/plugins/goto.mdwn
@@ -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.
--
cgit v1.2.3