From 8f64c69e084c698a389565203bd18bccb33f5d69 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Mon, 22 Nov 2010 23:13:52 +0000 Subject: Compute local paths to the top of the wiki "local" here is short for "locally valid" - the idea is that we can use URLs that are relative in the sense of only having the path part, but absolute in the sense that they start from '/', such as '/~smcv/ikiwiki.cgi'. There's no particularly good name that I can find for these between-relative-and-absolute URLs. They're useful because in the common case where the pages and the CGI script have the same scheme and authority component, each page is identified by the same locally-valid URL when linking from any page or from the CGI, without hard-coding a choice between HTTP and HTTPS, or between multiple virtual hostnames with the same path layout. As such, we can use them in many situations that previously used an absolute URL. If there's no suitable semi-absolute value for local_url (for instance, if your pages and your CGI reside on different servers), we can just fall back to using the absolute URL. I append '/' because $config{url} doesn't end with '/', but the common case for local_url (on all branchable.com sites, for instance) is that it's just '/'. --- IkiWiki.pm | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/IkiWiki.pm b/IkiWiki.pm index f57ef8c6c..1d37e7f8e 100644 --- a/IkiWiki.pm +++ b/IkiWiki.pm @@ -501,6 +501,12 @@ sub defaultconfig () { return @ret; } +# URL to top of wiki as a path starting with /, valid from any wiki page or +# the CGI; if that's not possible, an absolute URL. Either way, it ends with / +my $local_url; +# URL to CGI script, similar to $local_url +my $local_cgiurl; + sub checkconfig () { # locale stuff; avoid LC_ALL since it overrides everything if (defined $ENV{LC_ALL}) { @@ -537,7 +543,30 @@ sub checkconfig () { if ($config{cgi} && ! length $config{url}) { error(gettext("Must specify url to wiki with --url when using --cgi")); } - + + if (length $config{url}) { + eval q{use URI}; + my $baseurl = URI->new($config{url}); + + $local_url = $baseurl->path . "/"; + $local_cgiurl = undef; + + if (length $config{cgiurl}) { + my $cgiurl = URI->new($config{cgiurl}); + + $local_cgiurl = $cgiurl->path; + + if ($cgiurl->scheme ne $baseurl->scheme or + $cgiurl->authority ne $baseurl->authority) { + # too far apart, fall back to absolute URLs + $local_url = "$config{url}/"; + $local_cgiurl = $config{cgiurl}; + } + } + + $local_url =~ s{//$}{/}; + } + $config{wikistatedir}="$config{srcdir}/.ikiwiki" unless exists $config{wikistatedir} && defined $config{wikistatedir}; -- cgit v1.2.3 From 200c599dcaeb4dde77564b84022b67bf71cd6bfa Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Mon, 22 Nov 2010 23:16:59 +0000 Subject: cgiurl: don't append "?" if there are no parameters This means we can use cgiurl() instead of $config{cgiurl} if an absolute URL isn't desired. --- IkiWiki.pm | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/IkiWiki.pm b/IkiWiki.pm index 1d37e7f8e..989f3bee7 100644 --- a/IkiWiki.pm +++ b/IkiWiki.pm @@ -1044,6 +1044,11 @@ sub cgiurl (@) { $cgiurl=$params{cgiurl}; delete $params{cgiurl}; } + + unless (%params) { + return $cgiurl; + } + return $cgiurl."?". join("&", map $_."=".uri_escape_utf8($params{$_}), keys %params); } -- cgit v1.2.3 From 6be4e6d1a501fa10d7894ff46b4a812cddb26d49 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Mon, 22 Nov 2010 23:20:32 +0000 Subject: cgiurl(): return a locally-valid path by default To get an absolute version you can use cgiurl(cgiurl => $config{cgiurl}). The only place in IkiWiki that seems to actually need an absolute URL is the openid plugin, and that already uses the named parameter. --- IkiWiki.pm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/IkiWiki.pm b/IkiWiki.pm index 989f3bee7..41e9e3f82 100644 --- a/IkiWiki.pm +++ b/IkiWiki.pm @@ -1039,7 +1039,8 @@ sub linkpage ($) { sub cgiurl (@) { my %params=@_; - my $cgiurl=$config{cgiurl}; + my $cgiurl=$local_cgiurl; + if (exists $params{cgiurl}) { $cgiurl=$params{cgiurl}; delete $params{cgiurl}; -- cgit v1.2.3 From f032bce79158005032c09e4db75093abaca45751 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Mon, 22 Nov 2010 23:25:45 +0000 Subject: baseurl(): return local path, not absolute URL, if the argument is undef --- IkiWiki.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/IkiWiki.pm b/IkiWiki.pm index 41e9e3f82..a4afef8e0 100644 --- a/IkiWiki.pm +++ b/IkiWiki.pm @@ -1057,7 +1057,7 @@ sub cgiurl (@) { sub baseurl (;$) { my $page=shift; - return "$config{url}/" if ! defined $page; + return $local_url if ! defined $page; $page=htmlpage($page); $page=~s/[^\/]+$//; -- cgit v1.2.3 From 4c224ae143ebc4b13f824fe1782561a5cd165864 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Mon, 22 Nov 2010 23:33:13 +0000 Subject: urlto(): if $from is undef, return a local path, not an absolute URL --- IkiWiki.pm | 6 ++++++ doc/plugins/write.mdwn | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/IkiWiki.pm b/IkiWiki.pm index a4afef8e0..ee0b1f1ea 100644 --- a/IkiWiki.pm +++ b/IkiWiki.pm @@ -1148,6 +1148,12 @@ sub urlto ($$;$) { return $config{url}.beautify_urlpath("/".$to); } + if (! defined $from) { + my $u = $local_url; + $u =~ s{/$}{}; + return $u.beautify_urlpath("/".$to); + } + my $link = abs2rel($to, dirname(htmlpage($from))); return beautify_urlpath($link); diff --git a/doc/plugins/write.mdwn b/doc/plugins/write.mdwn index 6b751f0cd..33db3e707 100644 --- a/doc/plugins/write.mdwn +++ b/doc/plugins/write.mdwn @@ -988,6 +988,10 @@ Construct a relative url to the first parameter from the page named by the second. The first parameter can be either a page name, or some other destination file, as registered by `will_render`. +If the second parameter is `undef`, the URL will be valid from any page on the +wiki, or from the CGI; if possible it'll be a path starting with `/`, but an +absolute URL will be used if the wiki and the CGI are on different servers. + If the third parameter is passed and is true, an absolute url will be constructed instead of the default relative url. -- cgit v1.2.3 From 70bdd57899294fffd30077b7518ba23710c9d55b Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Sat, 2 Oct 2010 14:50:16 +0100 Subject: Add a regression test for urlto, baseurl and cgiurl in relative/local/absolute modes --- t/urlto.t | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100755 t/urlto.t diff --git a/t/urlto.t b/t/urlto.t new file mode 100755 index 000000000..a0b3baa45 --- /dev/null +++ b/t/urlto.t @@ -0,0 +1,44 @@ +#!/usr/bin/perl +use warnings; +use strict; +use Test::More tests => 19; + +BEGIN { use_ok("IkiWiki"); } + +$IkiWiki::config{srcdir} = '/does/not/exist/'; +$IkiWiki::config{usedirs} = 1; +$IkiWiki::config{htmlext} = "HTML"; +$IkiWiki::config{wiki_file_chars} = "A-Za-z0-9._"; + +$IkiWiki::config{url} = "http://smcv.example.co.uk"; +$IkiWiki::config{cgiurl} = "http://smcv.example.co.uk/cgi-bin/ikiwiki.cgi"; +is(IkiWiki::checkconfig(), 1); + +# absolute version +is(IkiWiki::cgiurl(cgiurl => $config{cgiurl}), "http://smcv.example.co.uk/cgi-bin/ikiwiki.cgi"); +is(IkiWiki::cgiurl(cgiurl => $config{cgiurl}, do => 'badger'), "http://smcv.example.co.uk/cgi-bin/ikiwiki.cgi?do=badger"); +is(IkiWiki::urlto('index', undef, 1), "http://smcv.example.co.uk/"); +is(IkiWiki::urlto('stoats', undef, 1), "http://smcv.example.co.uk/stoats/"); + +# "local" (absolute path within site) version (default for cgiurl) +is(IkiWiki::cgiurl(), "/cgi-bin/ikiwiki.cgi"); +is(IkiWiki::cgiurl(do => 'badger'), "/cgi-bin/ikiwiki.cgi?do=badger"); +is(IkiWiki::baseurl(undef), "/"); +is(IkiWiki::urlto('index', undef), "/"); +is(IkiWiki::urlto('stoats', undef), "/stoats/"); + +# fully-relative version (default for urlto and baseurl) +is(IkiWiki::baseurl('badger/mushroom'), "../../"); +is(IkiWiki::urlto('badger/mushroom', 'snake'), "../badger/mushroom/"); + +# explicit cgiurl override +is(IkiWiki::cgiurl(cgiurl => 'https://foo/ikiwiki'), "https://foo/ikiwiki"); +is(IkiWiki::cgiurl(do => 'badger', cgiurl => 'https://foo/ikiwiki'), "https://foo/ikiwiki?do=badger"); + +# with url and cgiurl on different sites, "local" degrades to absolute +$IkiWiki::config{url} = "http://example.co.uk/~smcv"; +$IkiWiki::config{cgiurl} = "http://dynamic.example.co.uk/~smcv/ikiwiki.cgi"; +is(IkiWiki::checkconfig(), 1); +is(IkiWiki::cgiurl(), "http://dynamic.example.co.uk/~smcv/ikiwiki.cgi"); +is(IkiWiki::baseurl(undef), "http://example.co.uk/~smcv/"); +is(IkiWiki::urlto('stoats', undef), "http://example.co.uk/~smcv/stoats/"); -- cgit v1.2.3 From d2e3741a6f289bd25b75683990a0548f41661a85 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Tue, 23 Nov 2010 00:00:11 +0000 Subject: Use local paths for redirection where possible --- IkiWiki/CGI.pm | 4 ++-- IkiWiki/Plugin/comments.pm | 4 ++-- IkiWiki/Plugin/editpage.pm | 10 +++++----- IkiWiki/Plugin/goto.pm | 2 +- IkiWiki/Plugin/openid.pm | 2 +- IkiWiki/Plugin/poll.pm | 4 ++-- IkiWiki/Plugin/remove.pm | 2 +- IkiWiki/Plugin/websetup.pm | 2 +- 8 files changed, 15 insertions(+), 15 deletions(-) diff --git a/IkiWiki/CGI.pm b/IkiWiki/CGI.pm index f2a32a958..ed6959f89 100644 --- a/IkiWiki/CGI.pm +++ b/IkiWiki/CGI.pm @@ -231,11 +231,11 @@ sub cgi_prefs ($$) { if ($form->submitted eq 'Logout') { $session->delete(); - redirect($q, $config{url}); + redirect($q, baseurl(undef)); return; } elsif ($form->submitted eq 'Cancel') { - redirect($q, $config{url}); + redirect($q, baseurl(undef)); return; } elsif ($form->submitted eq 'Save Preferences' && $form->validate) { diff --git a/IkiWiki/Plugin/comments.pm b/IkiWiki/Plugin/comments.pm index a39dab36c..eefd65741 100644 --- a/IkiWiki/Plugin/comments.pm +++ b/IkiWiki/Plugin/comments.pm @@ -386,7 +386,7 @@ sub editcomment ($$) { if ($form->submitted eq CANCEL) { # bounce back to the page they wanted to comment on, and exit. # CANCEL need not be considered in future - IkiWiki::redirect($cgi, urlto($page, undef, 1)); + IkiWiki::redirect($cgi, urlto($page, undef)); exit; } @@ -552,7 +552,7 @@ sub editcomment ($$) { # Jump to the new comment on the page. # The trailing question mark tries to avoid broken # caches and get the most recent version of the page. - IkiWiki::redirect($cgi, urlto($page, undef, 1). + IkiWiki::redirect($cgi, urlto($page, undef). "?updated#".page_to_id($location)); } diff --git a/IkiWiki/Plugin/editpage.pm b/IkiWiki/Plugin/editpage.pm index 1a04a72b5..8915211d4 100644 --- a/IkiWiki/Plugin/editpage.pm +++ b/IkiWiki/Plugin/editpage.pm @@ -156,13 +156,13 @@ sub cgi_editpage ($$) { my $previewing=0; if ($form->submitted eq "Cancel") { if ($form->field("do") eq "create" && defined $from) { - redirect($q, urlto($from, undef, 1)); + redirect($q, urlto($from, undef)); } elsif ($form->field("do") eq "create") { - redirect($q, $config{url}); + redirect($q, baseurl(undef)); } else { - redirect($q, urlto($page, undef, 1)); + redirect($q, urlto($page, undef)); } exit; } @@ -262,7 +262,7 @@ sub cgi_editpage ($$) { @page_locs=$page; } else { - redirect($q, urlto($page, undef, 1)); + redirect($q, urlto($page, undef)); exit; } } @@ -434,7 +434,7 @@ sub cgi_editpage ($$) { else { # The trailing question mark tries to avoid broken # caches and get the most recent version of the page. - redirect($q, urlto($page, undef, 1)."?updated"); + redirect($q, urlto($page, undef)."?updated"); } } diff --git a/IkiWiki/Plugin/goto.pm b/IkiWiki/Plugin/goto.pm index 348a663ef..7f31fa5ca 100644 --- a/IkiWiki/Plugin/goto.pm +++ b/IkiWiki/Plugin/goto.pm @@ -64,7 +64,7 @@ sub cgi_goto ($;$) { ) } else { - IkiWiki::redirect($q, urlto($link, undef, 1)); + IkiWiki::redirect($q, urlto($link, undef)); } exit; diff --git a/IkiWiki/Plugin/openid.pm b/IkiWiki/Plugin/openid.pm index fae9fb77f..3b75c31a2 100644 --- a/IkiWiki/Plugin/openid.pm +++ b/IkiWiki/Plugin/openid.pm @@ -175,7 +175,7 @@ sub auth ($$) { IkiWiki::redirect($q, $setup_url); } elsif ($csr->user_cancel) { - IkiWiki::redirect($q, $config{url}); + IkiWiki::redirect($q, IkiWiki::baseurl(undef)); } elsif (my $vident = $csr->verified_identity) { $session->param(name => $vident->url); diff --git a/IkiWiki/Plugin/poll.pm b/IkiWiki/Plugin/poll.pm index b333e2cdc..988f4c113 100644 --- a/IkiWiki/Plugin/poll.pm +++ b/IkiWiki/Plugin/poll.pm @@ -103,7 +103,7 @@ sub sessioncgi ($$) { my $oldchoice=$session->param($choice_param); if (defined $oldchoice && $oldchoice eq $choice) { # Same vote; no-op. - IkiWiki::redirect($cgi, urlto($page, undef, 1)); + IkiWiki::redirect($cgi, urlto($page, undef)); exit; } @@ -153,7 +153,7 @@ sub sessioncgi ($$) { error($@) if $@; my $cookie = CGI::Cookie->new(-name=> $session->name, -value=> $session->id); print $cgi->redirect(-cookie => $cookie, - -url => urlto($page, undef, 1)); + -url => urlto($page, undef)); exit; } } diff --git a/IkiWiki/Plugin/remove.pm b/IkiWiki/Plugin/remove.pm index 1717c8cf3..ab1897663 100644 --- a/IkiWiki/Plugin/remove.pm +++ b/IkiWiki/Plugin/remove.pm @@ -240,7 +240,7 @@ sub sessioncgi ($$) { if (! exists $pagesources{$parent}) { $parent="index"; } - IkiWiki::redirect($q, urlto($parent, '/', 1)); + IkiWiki::redirect($q, urlto($parent, undef)); } } else { diff --git a/IkiWiki/Plugin/websetup.pm b/IkiWiki/Plugin/websetup.pm index 9c032fdc6..ef9a93886 100644 --- a/IkiWiki/Plugin/websetup.pm +++ b/IkiWiki/Plugin/websetup.pm @@ -344,7 +344,7 @@ sub showform ($$) { IkiWiki::decode_form_utf8($form); if ($form->submitted eq "Cancel") { - IkiWiki::redirect($cgi, $config{url}); + IkiWiki::redirect($cgi, IkiWiki::baseurl(undef)); return; } elsif (($form->submitted eq 'Save Setup' || $form->submitted eq 'Rebuild Wiki') && $form->validate) { -- cgit v1.2.3 From 78c595736ef6903ad8e7bab232875474aedfd328 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Tue, 23 Nov 2010 00:06:07 +0000 Subject: Use local paths when including Javascript --- IkiWiki/Plugin/relativedate.pm | 11 +++++------ IkiWiki/Plugin/toggle.pm | 11 +++++------ IkiWiki/Plugin/wmd.pm | 9 ++++----- 3 files changed, 14 insertions(+), 17 deletions(-) diff --git a/IkiWiki/Plugin/relativedate.pm b/IkiWiki/Plugin/relativedate.pm index 7296889ab..4ae0be861 100644 --- a/IkiWiki/Plugin/relativedate.pm +++ b/IkiWiki/Plugin/relativedate.pm @@ -28,18 +28,17 @@ sub format (@) { if (! ($params{content}=~s!^(]*>)!$1.include_javascript($params{page})!em)) { # no tag, probably in preview mode - $params{content}=include_javascript($params{page}, 1).$params{content}; + $params{content}=include_javascript(undef).$params{content}; } return $params{content}; } -sub include_javascript ($;$) { - my $page=shift; - my $absolute=shift; +sub include_javascript ($) { + my $from=shift; - return ''."\n". - ''; } diff --git a/IkiWiki/Plugin/toggle.pm b/IkiWiki/Plugin/toggle.pm index 1f93f87fe..af4d2ba3a 100644 --- a/IkiWiki/Plugin/toggle.pm +++ b/IkiWiki/Plugin/toggle.pm @@ -70,19 +70,18 @@ sub format (@) { $params{content}=~s/
//g; if (! ($params{content}=~s!^(]*>)!$1.include_javascript($params{page})!em)) { # no tag, probably in preview mode - $params{content}=include_javascript($params{page}, 1).$params{content}; + $params{content}=include_javascript(undef).$params{content}; } } return $params{content}; } -sub include_javascript ($;$) { - my $page=shift; - my $absolute=shift; +sub include_javascript ($) { + my $from=shift; - return ''."\n". - ''; } diff --git a/IkiWiki/Plugin/wmd.pm b/IkiWiki/Plugin/wmd.pm index 71d7c9d17..134cfb910 100644 --- a/IkiWiki/Plugin/wmd.pm +++ b/IkiWiki/Plugin/wmd.pm @@ -31,14 +31,13 @@ sub formbuilder_setup (@) { $form->field("do") eq "comment"; $form->tmpl_param("wmd_preview", "
\n". - include_javascript(undef, 1)); + include_javascript(undef)); } -sub include_javascript ($;$) { - my $page=shift; - my $absolute=shift; +sub include_javascript ($) { + my $from=shift; - my $wmdjs=urlto("wmd/wmd.js", $page, $absolute); + my $wmdjs=urlto("wmd/wmd.js", $from); return <<"EOF"