6 plan(skip_all => "IPC::Run not available")
17 # Black-box (ish) test for relative linking between CGI and static content
19 my $installed = $ENV{INSTALLED_TESTS};
23 @command = qw(ikiwiki);
26 ok(! system("make -s ikiwiki.out"));
27 @command = qw(perl -I. ./ikiwiki.out
28 --underlaydir=underlays/basewiki
29 --set underlaydirbase=underlays
30 --templatedir=templates);
33 sub parse_cgi_content {
36 if ($content =~ qr{<base href="([^"]+)" */>}) {
39 if ($content =~ qr{href="([^"]+/style.css)"}) {
40 $bits{stylehref} = $1;
42 if ($content =~ qr{class="parentlinks">\s+<a href="([^"]+)">this is the name of my wiki</a>/}s) {
45 if ($content =~ qr{<a[^>]+href="([^"]+)\?do=prefs"}) {
55 writefile($name, "t/tmp/in", $content);
56 ok(utime(333333333, 333333333, "t/tmp/in/$name"));
59 sub write_setup_file {
61 my $urlline = defined $args{url} ? "url: $args{url}" : "";
62 my $w3mmodeline = defined $args{w3mmode} ? "w3mmode: $args{w3mmode}" : "";
63 my $reverseproxyline = defined $args{reverse_proxy} ? "reverse_proxy: $args{reverse_proxy}" : "";
65 writefile("test.setup", "t/tmp", <<EOF
66 # IkiWiki::Setup::Yaml - YAML formatted setup file
67 wikiname: this is the name of my wiki
73 cgi_wrapper: t/tmp/ikiwiki.cgi
76 # make it easier to test previewing
81 ENV: { 'PERL5LIB': 'blib/lib:blib/arch' }
86 sub thoroughly_rebuild {
87 ok(unlink("t/tmp/ikiwiki.cgi") || $!{ENOENT});
88 ok(! system(@command, qw(--setup t/tmp/test.setup --rebuild --wrappers)));
91 sub check_cgi_mode_bits {
92 my (undef, undef, $mode, undef, undef,
93 undef, undef, undef, undef, undef,
94 undef, undef, undef) = stat("t/tmp/ikiwiki.cgi");
95 is($mode & 07777, 0754);
98 sub check_generated_content {
99 my $cgiurl_regex = shift;
100 ok(-e "t/tmp/out/a/b/c/index.html");
101 my $content = readfile("t/tmp/out/a/b/c/index.html");
102 # no <base> on static HTML
103 unlike($content, qr{<base\W});
104 like($content, $cgiurl_regex);
105 # cross-links between static pages are relative
106 like($content, qr{<li>A: <a href="../../">a</a></li>});
107 like($content, qr{<li>B: <a href="../">b</a></li>});
108 like($content, qr{<li>E: <a href="../../d/e/">e</a></li>});
114 my $is_preview = delete $args{is_preview};
115 my $is_https = delete $args{is_https};
117 SCRIPT_NAME => '/cgi-bin/ikiwiki.cgi',
118 HTTP_HOST => 'example.com',
120 if (defined $is_preview) {
121 $defaults{REQUEST_METHOD} = 'POST';
122 $in = 'do=edit&page=a/b/c&Preview';
123 $defaults{CONTENT_LENGTH} = length $in;
125 $defaults{REQUEST_METHOD} = 'GET';
126 $defaults{QUERY_STRING} = 'do=prefs';
128 if (defined $is_https) {
129 $defaults{SERVER_PORT} = '443';
130 $defaults{HTTPS} = 'on';
132 $defaults{SERVER_PORT} = '80';
138 run(["./t/tmp/ikiwiki.cgi"], \$in, \$out, init => sub {
140 $ENV{$_} = $envvars{$_}
148 ok(! system("rm -rf t/tmp"));
149 ok(! system("mkdir t/tmp"));
151 write_old_file("a.mdwn", "A");
152 write_old_file("a/b.mdwn", "B");
153 write_old_file("a/b/c.mdwn",
157 write_old_file("a/d.mdwn", "D");
158 write_old_file("a/d/e.mdwn", "E");
161 sub test_site1_perfectly_ordinary_ikiwiki {
164 url => "http://example.com/wiki/",
165 cgiurl => "http://example.com/cgi-bin/ikiwiki.cgi",
167 thoroughly_rebuild();
168 check_cgi_mode_bits();
169 # url and cgiurl are on the same host so the cgiurl is host-relative
170 check_generated_content(qr{<a[^>]+href="/cgi-bin/ikiwiki.cgi\?do=prefs"});
171 my %bits = parse_cgi_content(run_cgi());
172 is($bits{basehref}, "http://example.com/wiki/");
173 like($bits{stylehref}, qr{^(?:(?:http:)?//example.com)?/wiki/style.css$});
174 like($bits{tophref}, qr{^(?:/wiki|\.)/$});
175 like($bits{cgihref}, qr{^(?:(?:http:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
177 # when accessed via HTTPS, links are secure
178 %bits = parse_cgi_content(run_cgi(is_https => 1));
179 is($bits{basehref}, "https://example.com/wiki/");
180 like($bits{stylehref}, qr{^(?:(?:https:)?//example.com)?/wiki/style.css$});
181 like($bits{tophref}, qr{^(?:/wiki|\.)/$});
182 like($bits{cgihref}, qr{^(?:(?:https:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
184 # when accessed via a different hostname, links stay on that host
185 %bits = parse_cgi_content(run_cgi(HTTP_HOST => 'staging.example.net'));
186 is($bits{basehref}, "http://staging.example.net/wiki/");
187 like($bits{stylehref}, qr{^(?:(?:http:)?//staging.example.net)?/wiki/style.css$});
188 like($bits{tophref}, qr{^(?:/wiki|\.)/$});
189 like($bits{cgihref}, qr{^(?:(?:http:)?//staging.example.net)?/cgi-bin/ikiwiki.cgi$});
192 %bits = parse_cgi_content(run_cgi(is_preview => 1));
193 is($bits{basehref}, "http://example.com/wiki/a/b/c/");
194 like($bits{stylehref}, qr{^(?:(?:http:)?//example.com)?/wiki/style.css$});
195 like($bits{tophref}, qr{^(?:/wiki|\.\./\.\./\.\.)/$});
196 like($bits{cgihref}, qr{^(?:(?:http:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
198 # in html5, the <base> is allowed to be relative, and we take full
202 url => "http://example.com/wiki/",
203 cgiurl => "http://example.com/cgi-bin/ikiwiki.cgi",
205 thoroughly_rebuild();
206 check_cgi_mode_bits();
207 # url and cgiurl are on the same host so the cgiurl is host-relative
208 check_generated_content(qr{<a[^>]+href="/cgi-bin/ikiwiki.cgi\?do=prefs"});
210 %bits = parse_cgi_content(run_cgi());
211 is($bits{basehref}, "/wiki/");
212 is($bits{stylehref}, "/wiki/style.css");
213 is($bits{tophref}, "/wiki/");
214 is($bits{cgihref}, "/cgi-bin/ikiwiki.cgi");
216 # when accessed via HTTPS, links are secure - this is easy because under
217 # html5 they're independent of the URL at which the CGI was accessed
218 %bits = parse_cgi_content(run_cgi(is_https => 1));
219 is($bits{basehref}, "/wiki/");
220 is($bits{stylehref}, "/wiki/style.css");
221 is($bits{tophref}, "/wiki/");
222 is($bits{cgihref}, "/cgi-bin/ikiwiki.cgi");
224 # when accessed via a different hostname, links stay on that host -
225 # this is really easy in html5 because we can use relative URLs
226 %bits = parse_cgi_content(run_cgi(HTTP_HOST => 'staging.example.net'));
227 is($bits{basehref}, "/wiki/");
228 is($bits{stylehref}, "/wiki/style.css");
229 is($bits{tophref}, "/wiki/");
230 is($bits{cgihref}, "/cgi-bin/ikiwiki.cgi");
233 %bits = parse_cgi_content(run_cgi(is_preview => 1));
234 is($bits{basehref}, "/wiki/a/b/c/");
235 is($bits{stylehref}, "/wiki/style.css");
236 like($bits{tophref}, qr{^(?:/wiki|\.\./\.\./\.\.)/$});
237 is($bits{cgihref}, "/cgi-bin/ikiwiki.cgi");
240 sub test_site2_static_content_and_cgi_on_different_servers {
243 url => "http://static.example.com/",
244 cgiurl => "http://cgi.example.com/ikiwiki.cgi",
246 thoroughly_rebuild();
247 check_cgi_mode_bits();
248 # url and cgiurl are not on the same host so the cgiurl has to be
249 # protocol-relative or absolute
250 check_generated_content(qr{<a[^>]+href="(?:http:)?//cgi.example.com/ikiwiki.cgi\?do=prefs"});
252 my %bits = parse_cgi_content(run_cgi(SCRIPT_NAME => '/ikiwiki.cgi', HTTP_HOST => 'cgi.example.com'));
253 like($bits{basehref}, qr{^http://static.example.com/$});
254 like($bits{stylehref}, qr{^(?:(?:http:)?//static.example.com)?/style.css$});
255 like($bits{tophref}, qr{^(?:http:)?//static.example.com/$});
256 like($bits{cgihref}, qr{^(?:(?:http:)?//cgi.example.com)?/ikiwiki.cgi$});
258 # when accessed via HTTPS, links are secure
259 %bits = parse_cgi_content(run_cgi(is_https => 1, SCRIPT_NAME => '/ikiwiki.cgi', HTTP_HOST => 'cgi.example.com'));
260 like($bits{basehref}, qr{^https://static.example.com/$});
261 like($bits{stylehref}, qr{^(?:(?:https:)?//static.example.com)?/style.css$});
262 like($bits{tophref}, qr{^(?:https:)?//static.example.com/$});
263 like($bits{cgihref}, qr{^(?:(?:https:)?//cgi.example.com)?/ikiwiki.cgi$});
265 # when accessed via a different hostname, links to the CGI (only) should
267 %bits = parse_cgi_content(run_cgi(is_preview => 1, SCRIPT_NAME => '/ikiwiki.cgi', HTTP_HOST => 'staging.example.net'));
268 like($bits{basehref}, qr{^http://static.example.com/a/b/c/$});
269 like($bits{stylehref}, qr{^(?:(?:http:)?//static.example.com|\.\./\.\./\.\.)/style.css$});
270 like($bits{tophref}, qr{^(?:(?:http:)?//static.example.com|\.\./\.\./\.\.)/$});
271 like($bits{cgihref}, qr{^(?:(?:http:)?//(?:staging\.example\.net|cgi\.example\.com))?/ikiwiki.cgi$});
273 local $TODO = "use self-referential CGI URL?";
274 like($bits{cgihref}, qr{^(?:(?:http:)?//staging.example.net)?/ikiwiki.cgi$});
279 url => "http://static.example.com/",
280 cgiurl => "http://cgi.example.com/ikiwiki.cgi",
282 thoroughly_rebuild();
283 check_cgi_mode_bits();
284 # url and cgiurl are not on the same host so the cgiurl has to be
285 # protocol-relative or absolute
286 check_generated_content(qr{<a[^>]+href="(?:http:)?//cgi.example.com/ikiwiki.cgi\?do=prefs"});
288 %bits = parse_cgi_content(run_cgi(SCRIPT_NAME => '/ikiwiki.cgi', HTTP_HOST => 'cgi.example.com'));
289 is($bits{basehref}, "//static.example.com/");
290 is($bits{stylehref}, "//static.example.com/style.css");
291 is($bits{tophref}, "//static.example.com/");
292 is($bits{cgihref}, "//cgi.example.com/ikiwiki.cgi");
294 # when accessed via HTTPS, links are secure - in fact they're exactly the
295 # same as when accessed via HTTP
296 %bits = parse_cgi_content(run_cgi(is_https => 1, SCRIPT_NAME => '/ikiwiki.cgi', HTTP_HOST => 'cgi.example.com'));
297 is($bits{basehref}, "//static.example.com/");
298 is($bits{stylehref}, "//static.example.com/style.css");
299 is($bits{tophref}, "//static.example.com/");
300 is($bits{cgihref}, "//cgi.example.com/ikiwiki.cgi");
302 # when accessed via a different hostname, links to the CGI (only) should
304 %bits = parse_cgi_content(run_cgi(is_preview => 1, SCRIPT_NAME => '/ikiwiki.cgi', HTTP_HOST => 'staging.example.net'));
305 is($bits{basehref}, "//static.example.com/a/b/c/");
306 is($bits{stylehref}, "//static.example.com/style.css");
307 is($bits{tophref}, "../../../");
308 like($bits{cgihref}, qr{//(?:staging\.example\.net|cgi\.example\.com)/ikiwiki\.cgi});
310 local $TODO = "use self-referential CGI URL maybe?";
311 is($bits{cgihref}, "//staging.example.net/ikiwiki.cgi");
315 sub test_site3_we_specifically_want_everything_to_be_secure {
318 url => "https://example.com/wiki/",
319 cgiurl => "https://example.com/cgi-bin/ikiwiki.cgi",
321 thoroughly_rebuild();
322 check_cgi_mode_bits();
323 # url and cgiurl are on the same host so the cgiurl is host-relative
324 check_generated_content(qr{<a[^>]+href="/cgi-bin/ikiwiki.cgi\?do=prefs"});
326 # when accessed via HTTPS, links are secure
327 my %bits = parse_cgi_content(run_cgi(is_https => 1));
328 is($bits{basehref}, "https://example.com/wiki/");
329 like($bits{stylehref}, qr{^(?:(?:https:)?//example.com)?/wiki/style.css$});
330 like($bits{tophref}, qr{^(?:/wiki|\.)/$});
331 like($bits{cgihref}, qr{^(?:(?:https:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
333 # when not accessed via HTTPS, links should still be secure
334 # (but if this happens, that's a sign of web server misconfiguration)
335 %bits = parse_cgi_content(run_cgi());
336 like($bits{tophref}, qr{^(?:/wiki|\.)/$});
338 local $TODO = "treat https in configured url, cgiurl as required?";
339 is($bits{basehref}, "https://example.com/wiki/");
340 like($bits{stylehref}, qr{^(?:(?:https:)?//example.com)?/wiki/style.css$});
342 like($bits{cgihref}, qr{^(?:(?:https:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
344 # when accessed via a different hostname, links stay on that host
345 %bits = parse_cgi_content(run_cgi(is_https => 1, HTTP_HOST => 'staging.example.net'));
346 is($bits{basehref}, "https://staging.example.net/wiki/");
347 like($bits{stylehref}, qr{^(?:(?:https:)?//staging.example.net)?/wiki/style.css$});
348 like($bits{tophref}, qr{^(?:/wiki|\.)/$});
349 like($bits{cgihref}, qr{^(?:(?:https:)?//staging.example.net)?/cgi-bin/ikiwiki.cgi$});
352 %bits = parse_cgi_content(run_cgi(is_preview => 1, is_https => 1));
353 is($bits{basehref}, "https://example.com/wiki/a/b/c/");
354 like($bits{stylehref}, qr{^(?:(?:https:)?//example.com)?/wiki/style.css$});
355 like($bits{tophref}, qr{^(?:/wiki|\.\./\.\./\.\.)/$});
356 like($bits{cgihref}, qr{^(?:(?:https:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
358 # not testing html5: 0 here because that ends up identical to site 1
361 sub test_site4_cgi_is_secure_static_content_doesnt_have_to_be {
365 url => "http://example.com/wiki/",
366 cgiurl => "https://example.com/cgi-bin/ikiwiki.cgi",
368 thoroughly_rebuild();
369 check_cgi_mode_bits();
370 # url and cgiurl are on the same host but different schemes
371 check_generated_content(qr{<a[^>]+href="https://example.com/cgi-bin/ikiwiki.cgi\?do=prefs"});
373 # when accessed via HTTPS, links are secure (to avoid mixed-content)
374 my %bits = parse_cgi_content(run_cgi(is_https => 1));
375 is($bits{basehref}, "https://example.com/wiki/");
376 like($bits{stylehref}, qr{^(?:(?:https:)?//example.com)?/wiki/style.css$});
377 like($bits{tophref}, qr{^(?:/wiki|\.)/$});
378 like($bits{cgihref}, qr{^(?:(?:https:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
380 # when not accessed via HTTPS, ???
381 %bits = parse_cgi_content(run_cgi());
382 like($bits{basehref}, qr{^https?://example.com/wiki/$});
383 like($bits{stylehref}, qr{^(?:(?:https?:)?//example.com)?/wiki/style.css$});
384 like($bits{tophref}, qr{^(?:(?:https?://example.com)?/wiki|\.)/$});
385 like($bits{cgihref}, qr{^(?:(?:https:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
387 # when accessed via a different hostname, links stay on that host
388 %bits = parse_cgi_content(run_cgi(is_https => 1, HTTP_HOST => 'staging.example.net'));
389 # because the static and dynamic stuff is on the same server, we assume that
390 # both are also on the staging server
391 like($bits{basehref}, qr{^https://staging.example.net/wiki/$});
392 like($bits{stylehref}, qr{^(?:(?:https:)?//staging.example.net)?/wiki/style.css$});
393 like($bits{tophref}, qr{^(?:(?:(?:https:)?//staging.example.net)?/wiki|\.)/$});
394 like($bits{cgihref}, qr{^(?:(?:https:)?//(?:staging\.example\.net|example\.com))?/cgi-bin/ikiwiki.cgi$});
396 local $TODO = "this should really point back to itself but currently points to example.com";
397 like($bits{cgihref}, qr{^(?:(?:https:)?//staging.example.net)?/cgi-bin/ikiwiki.cgi$});
401 %bits = parse_cgi_content(run_cgi(is_preview => 1, is_https => 1));
402 is($bits{basehref}, "https://example.com/wiki/a/b/c/");
403 like($bits{stylehref}, qr{^(?:(?:https:)?//example.com)?/wiki/style.css$});
404 like($bits{tophref}, qr{^(?:/wiki|\.\./\.\./\.\.)/$});
405 like($bits{cgihref}, qr{^(?:(?:https:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
409 url => "http://example.com/wiki/",
410 cgiurl => "https://example.com/cgi-bin/ikiwiki.cgi",
412 thoroughly_rebuild();
413 check_cgi_mode_bits();
414 # url and cgiurl are on the same host but different schemes
415 check_generated_content(qr{<a[^>]+href="https://example.com/cgi-bin/ikiwiki.cgi\?do=prefs"});
417 # when accessed via HTTPS, links are secure (to avoid mixed-content)
418 %bits = parse_cgi_content(run_cgi(is_https => 1));
419 is($bits{basehref}, "/wiki/");
420 is($bits{stylehref}, "/wiki/style.css");
421 is($bits{tophref}, "/wiki/");
422 like($bits{cgihref}, qr{^(?:(?:https:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
424 # when not accessed via HTTPS, ???
425 %bits = parse_cgi_content(run_cgi());
426 like($bits{basehref}, qr{^(?:https?://example.com)?/wiki/$});
427 like($bits{stylehref}, qr{^(?:(?:https?:)?//example.com)?/wiki/style.css$});
428 like($bits{tophref}, qr{^(?:(?:https?://example.com)?/wiki|\.)/$});
429 like($bits{cgihref}, qr{^(?:(?:https:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
431 # when accessed via a different hostname, links stay on that host
432 %bits = parse_cgi_content(run_cgi(is_https => 1, HTTP_HOST => 'staging.example.net'));
433 # because the static and dynamic stuff is on the same server, we assume that
434 # both are also on the staging server
435 is($bits{basehref}, "/wiki/");
436 is($bits{stylehref}, "/wiki/style.css");
437 like($bits{tophref}, qr{^(?:/wiki|\.)/$});
438 like($bits{cgihref}, qr{^(?:(?:https:)?//(?:example\.com|staging\.example\.net))?/cgi-bin/ikiwiki.cgi$});
440 local $TODO = "this should really point back to itself but currently points to example.com";
441 like($bits{cgihref}, qr{^(?:(?:https:)?//staging.example.net)?/cgi-bin/ikiwiki.cgi$});
445 %bits = parse_cgi_content(run_cgi(is_preview => 1, is_https => 1));
446 is($bits{basehref}, "/wiki/a/b/c/");
447 is($bits{stylehref}, "/wiki/style.css");
448 like($bits{tophref}, qr{^(?:/wiki|\.\./\.\./\.\.)/$});
449 like($bits{cgihref}, qr{^(?:(?:https:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
451 # Deliberately not testing https static content with http cgiurl,
452 # because that makes remarkably little sense.
455 sub test_site5_w3mmode {
456 # as documented in [[w3mmode]]
460 cgiurl => "ikiwiki.cgi",
463 thoroughly_rebuild();
464 check_cgi_mode_bits();
465 # FIXME: does /$LIB/ikiwiki-w3m.cgi work under w3m?
466 check_generated_content(qr{<a[^>]+href="(?:file://)?/\$LIB/ikiwiki-w3m.cgi/ikiwiki.cgi\?do=prefs"});
468 my %bits = parse_cgi_content(run_cgi(PATH_INFO => '/ikiwiki.cgi', SCRIPT_NAME => '/cgi-bin/ikiwiki-w3m.cgi'));
470 like($bits{tophref}, qr{^(?:\Q$pwd\E/t/tmp/out|\.)/$});
471 like($bits{cgihref}, qr{^(?:file://)?/\$LIB/ikiwiki-w3m.cgi/ikiwiki.cgi$});
472 like($bits{basehref}, qr{^(?:(?:file:)?//)?\Q$pwd\E/t/tmp/out/$});
473 like($bits{stylehref}, qr{^(?:(?:(?:file:)?//)?\Q$pwd\E/t/tmp/out|\.)/style.css$});
478 cgiurl => "ikiwiki.cgi",
481 thoroughly_rebuild();
482 check_cgi_mode_bits();
483 # FIXME: does /$LIB/ikiwiki-w3m.cgi work under w3m?
484 check_generated_content(qr{<a[^>]+href="(?:file://)?/\$LIB/ikiwiki-w3m.cgi/ikiwiki.cgi\?do=prefs"});
486 %bits = parse_cgi_content(run_cgi(PATH_INFO => '/ikiwiki.cgi', SCRIPT_NAME => '/cgi-bin/ikiwiki-w3m.cgi'));
487 like($bits{tophref}, qr{^(?:\Q$pwd\E/t/tmp/out|\.)/$});
488 like($bits{cgihref}, qr{^(?:file://)?/\$LIB/ikiwiki-w3m.cgi/ikiwiki.cgi$});
489 like($bits{basehref}, qr{^(?:(?:file:)?//)?\Q$pwd\E/t/tmp/out/$});
490 like($bits{stylehref}, qr{^(?:(?:(?:file:)?//)?\Q$pwd\E/t/tmp/out|\.)/style.css$});
493 sub test_site6_behind_reverse_proxy {
496 url => "https://example.com/wiki/",
497 cgiurl => "https://example.com/cgi-bin/ikiwiki.cgi",
500 thoroughly_rebuild();
501 check_cgi_mode_bits();
502 # url and cgiurl are on the same host so the cgiurl is host-relative
503 check_generated_content(qr{<a[^>]+href="/cgi-bin/ikiwiki.cgi\?do=prefs"});
505 # because we are behind a reverse-proxy we must assume that
506 # we're being accessed by the configured cgiurl
507 my %bits = parse_cgi_content(run_cgi(HTTP_HOST => 'localhost'));
508 like($bits{tophref}, qr{^(?:/wiki|\.)/$});
509 like($bits{cgihref}, qr{^(?:(?:https:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
510 is($bits{basehref}, "https://example.com/wiki/");
511 like($bits{stylehref}, qr{^(?:(?:https:)?//example.com)?/wiki/style.css$});
514 %bits = parse_cgi_content(run_cgi(is_preview => 1, HTTP_HOST => 'localhost'));
515 like($bits{tophref}, qr{^(?:/wiki|\.\./\.\./\.\.)/$});
516 like($bits{cgihref}, qr{^(?:(?:https:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
517 is($bits{basehref}, "https://example.com/wiki/a/b/c/");
518 like($bits{stylehref}, qr{^(?:(?:https:)?//example.com)?/wiki/style.css$});
520 # not testing html5: 1 because it would be the same as site 1 -
521 # the reverse_proxy config option is unnecessary under html5
526 test_site1_perfectly_ordinary_ikiwiki();
527 test_site2_static_content_and_cgi_on_different_servers();
528 test_site3_we_specifically_want_everything_to_be_secure();
529 test_site4_cgi_is_secure_static_content_doesnt_have_to_be();
530 test_site5_w3mmode();
531 test_site6_behind_reverse_proxy();