From 532f7adfdba3c852487216b0241b25d3de57acc6 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Sun, 5 Oct 2014 15:56:19 +0100 Subject: [PATCH] Use protocol-relative URIs if cgiurl and url differ only by authority (hostname) --- IkiWiki.pm | 11 +++++++++-- ...ocol_relative_urls_for_stylesheet_linking.mdwn | 8 ++++++++ t/relativity.t | 3 --- t/urlto.t | 15 ++++++++++++--- 4 files changed, 29 insertions(+), 8 deletions(-) diff --git a/IkiWiki.pm b/IkiWiki.pm index d5d11ee85..c1518a2ae 100644 --- a/IkiWiki.pm +++ b/IkiWiki.pm @@ -613,12 +613,19 @@ sub checkconfig () { $local_cgiurl = $cgiurl->path; - if ($cgiurl->scheme ne $baseurl->scheme or - $cgiurl->authority ne $baseurl->authority) { + if ($cgiurl->scheme ne $baseurl->scheme) { # too far apart, fall back to absolute URLs $local_url = "$config{url}/"; $local_cgiurl = $config{cgiurl}; } + elsif ($cgiurl->authority ne $baseurl->authority) { + # slightly too far apart, fall back to + # protocol-relative URLs + $local_url = "$config{url}/"; + $local_url =~ s{^https?://}{//}; + $local_cgiurl = $config{cgiurl}; + $local_cgiurl =~ s{^https?://}{//}; + } } $local_url =~ s{//$}{/}; diff --git a/doc/todo/Protocol_relative_urls_for_stylesheet_linking.mdwn b/doc/todo/Protocol_relative_urls_for_stylesheet_linking.mdwn index ccbaf4e73..0ab4814e6 100644 --- a/doc/todo/Protocol_relative_urls_for_stylesheet_linking.mdwn +++ b/doc/todo/Protocol_relative_urls_for_stylesheet_linking.mdwn @@ -26,6 +26,14 @@ but this breaks all sorts of things, like the 404 plugin and wiki rebuilds will > protocol-relative URLs in this situation, but it isn't clear to me how > widely-supported those are. > +>> HTML5 says protocol-relative URLs work, and they seem to be widely +>> supported in practice, so I've changed the rule to: if the url and cgiurl +>> share a scheme (protocol) but differ only by hostname, use `//foo/bar` +>> protocol-relative URLs. This partially addresses this todo. +>> I'm still thinking about what the right thing is for more complicated +>> situations: see [[todo/design for cross-linking between content and CGI]]. +>> --[[smcv]] +> > If you set both the `$config{url}` and `$config{cgiurl}` to https, but make > the resulting HTML available over HTTP as well as HTTPS, that should work > fine - accesses will be over http until the user either explicitly diff --git a/t/relativity.t b/t/relativity.t index eb6cc448a..6c4d1107e 100755 --- a/t/relativity.t +++ b/t/relativity.t @@ -227,13 +227,10 @@ run(["./t/tmp/ikiwiki.cgi"], \undef, \$content, init => sub { $ENV{HTTPS} = 'on'; }); %bits = parse_cgi_content($content); -TODO: { -local $TODO = "avoid mixed content"; like($bits{basehref}, qr{^https://static.example.com/$}); like($bits{stylehref}, qr{^(?:(?:https:)?//static.example.com)?/style.css$}); like($bits{tophref}, qr{^(?:https:)?//static.example.com/$}); like($bits{cgihref}, qr{^(?:(?:https:)?//cgi.example.com)?/ikiwiki.cgi$}); -} # when accessed via a different hostname, links to the CGI (only) should # stay on that host? diff --git a/t/urlto.t b/t/urlto.t index 338632e94..025409b7f 100755 --- a/t/urlto.t +++ b/t/urlto.t @@ -1,7 +1,7 @@ #!/usr/bin/perl use warnings; use strict; -use Test::More tests => 26; +use Test::More tests => 31; BEGIN { use_ok("IkiWiki"); } @@ -41,11 +41,20 @@ is(IkiWiki::urlto('', 'penguin/herring'), "../../"); 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 +# with url and cgiurl on different sites, "local" degrades to protocol-relative $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::cgiurl(), "//dynamic.example.co.uk/~smcv/ikiwiki.cgi"); +is(IkiWiki::baseurl(undef), "//example.co.uk/~smcv/"); +is(IkiWiki::urlto('stoats', undef), "//example.co.uk/~smcv/stoats/"); +is(IkiWiki::urlto('', undef), "//example.co.uk/~smcv/"); + +# with url and cgiurl on different schemes, "local" degrades to absolute +$IkiWiki::config{url} = "http://example.co.uk/~smcv"; +$IkiWiki::config{cgiurl} = "https://dynamic.example.co.uk/~smcv/ikiwiki.cgi"; +is(IkiWiki::checkconfig(), 1); +is(IkiWiki::cgiurl(), "https://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/"); is(IkiWiki::urlto('', undef), "http://example.co.uk/~smcv/");