In html5 mode, generate a host- or protocol-relative <base> for the CGI
[ikiwiki] / t / relativity.t
1 #!/usr/bin/perl
2 use warnings;
3 use strict;
4
5 use Cwd qw(getcwd);
6 use Errno qw(ENOENT);
7
8 BEGIN {
9         if (!eval q{
10                 use IPC::Run qw(run);
11                 1;
12         }) {
13                 eval q{use Test::More skip_all => "IPC::Run not available"};
14         }
15         else {
16                 eval q{use Test::More};
17         }
18         use_ok("IkiWiki");
19 }
20
21 my $PERL5LIB = 'blib/lib:blib/arch';
22 my $pwd = getcwd();
23
24 # Black-box (ish) test for relative linking between CGI and static content
25
26 my $blob;
27 my ($content, $in, %bits);
28
29 sub parse_cgi_content {
30         my %bits;
31         if ($content =~ qr{<base href="([^"]+)" */>}) {
32                 $bits{basehref} = $1;
33         }
34         if ($content =~ qr{href="([^"]+/style.css)"}) {
35                 $bits{stylehref} = $1;
36         }
37         if ($content =~ qr{class="parentlinks">\s+<a href="([^"]+)">this is the name of my wiki</a>/}s) {
38                 $bits{tophref} = $1;
39         }
40         if ($content =~ qr{<a[^>]+href="([^"]+)\?do=prefs"}) {
41                 $bits{cgihref} = $1;
42         }
43         return %bits;
44 }
45
46 ok(! system("make -s ikiwiki.out"));
47 ok(! system("rm -rf t/tmp"));
48 ok(! system("mkdir t/tmp"));
49
50 sub write_old_file {
51         my $name = shift;
52         my $content = shift;
53
54         writefile($name, "t/tmp/in", $content);
55         ok(utime(333333333, 333333333, "t/tmp/in/$name"));
56 }
57
58 write_old_file("a.mdwn", "A");
59 write_old_file("a/b.mdwn", "B");
60 write_old_file("a/b/c.mdwn",
61 "* A: [[a]]\n".
62 "* B: [[b]]\n".
63 "* E: [[a/d/e]]\n");
64 write_old_file("a/d.mdwn", "D");
65 write_old_file("a/d/e.mdwn", "E");
66
67 #######################################################################
68 # site 1: a perfectly ordinary ikiwiki
69
70 writefile("test.setup", "t/tmp", <<EOF
71 # IkiWiki::Setup::Yaml - YAML formatted setup file
72 wikiname: this is the name of my wiki
73 srcdir: t/tmp/in
74 destdir: t/tmp/out
75 templatedir: templates
76 url: "http://example.com/wiki/"
77 cgiurl: "http://example.com/cgi-bin/ikiwiki.cgi"
78 cgi_wrapper: t/tmp/ikiwiki.cgi
79 cgi_wrappermode: 0754
80 html5: 0
81 # make it easier to test previewing
82 add_plugins:
83 - anonok
84 anonok_pagespec: "*"
85 ENV: { 'PERL5LIB': '$PERL5LIB' }
86 EOF
87 );
88
89 ok(unlink("t/tmp/ikiwiki.cgi") || $!{ENOENT});
90 ok(! system("./ikiwiki.out --setup t/tmp/test.setup --rebuild --wrappers"));
91
92 # CGI wrapper should be exactly the requested mode
93 my (undef, undef, $mode, undef, undef,
94         undef, undef, undef, undef, undef,
95         undef, undef, undef) = stat("t/tmp/ikiwiki.cgi");
96 is($mode & 07777, 0754);
97
98 ok(-e "t/tmp/out/a/b/c/index.html");
99 $content = readfile("t/tmp/out/a/b/c/index.html");
100 # no <base> on static HTML
101 unlike($content, qr{<base\W});
102 # url and cgiurl are on the same host so the cgiurl is host-relative
103 like($content, qr{<a[^>]+href="/cgi-bin/ikiwiki.cgi\?do=prefs"});
104 # cross-links between static pages are relative
105 like($content, qr{<li>A: <a href="../../">a</a></li>});
106 like($content, qr{<li>B: <a href="../">b</a></li>});
107 like($content, qr{<li>E: <a href="../../d/e/">e</a></li>});
108
109 run(["./t/tmp/ikiwiki.cgi"], \undef, \$content, init => sub {
110         $ENV{REQUEST_METHOD} = 'GET';
111         $ENV{SERVER_PORT} = '80';
112         $ENV{SCRIPT_NAME} = '/cgi-bin/ikiwiki.cgi';
113         $ENV{QUERY_STRING} = 'do=prefs';
114         $ENV{HTTP_HOST} = 'example.com';
115 });
116 %bits = parse_cgi_content($content);
117 is($bits{basehref}, "http://example.com/wiki/");
118 like($bits{stylehref}, qr{^(?:(?:http:)?//example.com)?/wiki/style.css$});
119 like($bits{tophref}, qr{^(?:/wiki|\.)/$});
120 like($bits{cgihref}, qr{^(?:(?:http:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
121
122 # when accessed via HTTPS, links are secure
123 run(["./t/tmp/ikiwiki.cgi"], \undef, \$content, init => sub {
124         $ENV{REQUEST_METHOD} = 'GET';
125         $ENV{SERVER_PORT} = '443';
126         $ENV{SCRIPT_NAME} = '/cgi-bin/ikiwiki.cgi';
127         $ENV{QUERY_STRING} = 'do=prefs';
128         $ENV{HTTP_HOST} = 'example.com';
129         $ENV{HTTPS} = 'on';
130 });
131 %bits = parse_cgi_content($content);
132 is($bits{basehref}, "https://example.com/wiki/");
133 like($bits{stylehref}, qr{^(?:(?:https:)?//example.com)?/wiki/style.css$});
134 like($bits{tophref}, qr{^(?:/wiki|\.)/$});
135 like($bits{cgihref}, qr{^(?:(?:https:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
136
137 # when accessed via a different hostname, links stay on that host
138 run(["./t/tmp/ikiwiki.cgi"], \undef, \$content, init => sub {
139         $ENV{REQUEST_METHOD} = 'GET';
140         $ENV{SERVER_PORT} = '80';
141         $ENV{SCRIPT_NAME} = '/cgi-bin/ikiwiki.cgi';
142         $ENV{QUERY_STRING} = 'do=prefs';
143         $ENV{HTTP_HOST} = 'staging.example.net';
144 });
145 %bits = parse_cgi_content($content);
146 is($bits{basehref}, "http://staging.example.net/wiki/");
147 like($bits{stylehref}, qr{^(?:(?:http:)?//staging.example.net)?/wiki/style.css$});
148 like($bits{tophref}, qr{^(?:/wiki|\.)/$});
149 like($bits{cgihref}, qr{^(?:(?:http:)?//staging.example.net)?/cgi-bin/ikiwiki.cgi$});
150
151 # previewing a page
152 $in = 'do=edit&page=a/b/c&Preview';
153 run(["./t/tmp/ikiwiki.cgi"], \$in, \$content, init => sub {
154         $ENV{REQUEST_METHOD} = 'POST';
155         $ENV{SERVER_PORT} = '80';
156         $ENV{SCRIPT_NAME} = '/cgi-bin/ikiwiki.cgi';
157         $ENV{HTTP_HOST} = 'example.com';
158         $ENV{CONTENT_LENGTH} = length $in;
159 });
160 %bits = parse_cgi_content($content);
161 is($bits{basehref}, "http://example.com/wiki/a/b/c/");
162 like($bits{stylehref}, qr{^(?:(?:http:)?//example.com)?/wiki/style.css$});
163 like($bits{tophref}, qr{^(?:/wiki|\.\./\.\./\.\.)/$});
164 like($bits{cgihref}, qr{^(?:(?:http:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
165
166 # in html5, the <base> is allowed to be relative, and we take full
167 # advantage of that
168 writefile("test.setup", "t/tmp", <<EOF
169 # IkiWiki::Setup::Yaml - YAML formatted setup file
170 wikiname: this is the name of my wiki
171 srcdir: t/tmp/in
172 destdir: t/tmp/out
173 templatedir: templates
174 url: "http://example.com/wiki/"
175 cgiurl: "http://example.com/cgi-bin/ikiwiki.cgi"
176 cgi_wrapper: t/tmp/ikiwiki.cgi
177 cgi_wrappermode: 0754
178 html5: 1
179 # make it easier to test previewing
180 add_plugins:
181 - anonok
182 anonok_pagespec: "*"
183 ENV: { 'PERL5LIB': '$PERL5LIB' }
184 EOF
185 );
186
187 ok(unlink("t/tmp/ikiwiki.cgi") || $!{ENOENT});
188 ok(! system("./ikiwiki.out --setup t/tmp/test.setup --rebuild --wrappers"));
189
190 # CGI wrapper should be exactly the requested mode
191 (undef, undef, $mode, undef, undef,
192         undef, undef, undef, undef, undef,
193         undef, undef, undef) = stat("t/tmp/ikiwiki.cgi");
194 is($mode & 07777, 0754);
195
196 ok(-e "t/tmp/out/a/b/c/index.html");
197 $content = readfile("t/tmp/out/a/b/c/index.html");
198 # no <base> on static HTML
199 unlike($content, qr{<base\W});
200 # url and cgiurl are on the same host so the cgiurl is host-relative
201 like($content, qr{<a[^>]+href="/cgi-bin/ikiwiki.cgi\?do=prefs"});
202 # cross-links between static pages are relative
203 like($content, qr{<li>A: <a href="../../">a</a></li>});
204 like($content, qr{<li>B: <a href="../">b</a></li>});
205 like($content, qr{<li>E: <a href="../../d/e/">e</a></li>});
206
207 run(["./t/tmp/ikiwiki.cgi"], \undef, \$content, init => sub {
208         $ENV{REQUEST_METHOD} = 'GET';
209         $ENV{SERVER_PORT} = '80';
210         $ENV{SCRIPT_NAME} = '/cgi-bin/ikiwiki.cgi';
211         $ENV{QUERY_STRING} = 'do=prefs';
212         $ENV{HTTP_HOST} = 'example.com';
213 });
214 %bits = parse_cgi_content($content);
215 is($bits{basehref}, "/wiki/");
216 is($bits{stylehref}, "/wiki/style.css");
217 is($bits{tophref}, "/wiki/");
218 is($bits{cgihref}, "/cgi-bin/ikiwiki.cgi");
219
220 # when accessed via HTTPS, links are secure - this is easy because under
221 # html5 they're independent of the URL at which the CGI was accessed
222 run(["./t/tmp/ikiwiki.cgi"], \undef, \$content, init => sub {
223         $ENV{REQUEST_METHOD} = 'GET';
224         $ENV{SERVER_PORT} = '443';
225         $ENV{SCRIPT_NAME} = '/cgi-bin/ikiwiki.cgi';
226         $ENV{QUERY_STRING} = 'do=prefs';
227         $ENV{HTTP_HOST} = 'example.com';
228         $ENV{HTTPS} = 'on';
229 });
230 %bits = parse_cgi_content($content);
231 is($bits{basehref}, "/wiki/");
232 is($bits{stylehref}, "/wiki/style.css");
233 is($bits{tophref}, "/wiki/");
234 is($bits{cgihref}, "/cgi-bin/ikiwiki.cgi");
235
236 # when accessed via a different hostname, links stay on that host -
237 # this is really easy in html5 because we can use relative URLs
238 run(["./t/tmp/ikiwiki.cgi"], \undef, \$content, init => sub {
239         $ENV{REQUEST_METHOD} = 'GET';
240         $ENV{SERVER_PORT} = '80';
241         $ENV{SCRIPT_NAME} = '/cgi-bin/ikiwiki.cgi';
242         $ENV{QUERY_STRING} = 'do=prefs';
243         $ENV{HTTP_HOST} = 'staging.example.net';
244 });
245 %bits = parse_cgi_content($content);
246 is($bits{basehref}, "/wiki/");
247 is($bits{stylehref}, "/wiki/style.css");
248 is($bits{tophref}, "/wiki/");
249 is($bits{cgihref}, "/cgi-bin/ikiwiki.cgi");
250
251 # previewing a page
252 $in = 'do=edit&page=a/b/c&Preview';
253 run(["./t/tmp/ikiwiki.cgi"], \$in, \$content, init => sub {
254         $ENV{REQUEST_METHOD} = 'POST';
255         $ENV{SERVER_PORT} = '80';
256         $ENV{SCRIPT_NAME} = '/cgi-bin/ikiwiki.cgi';
257         $ENV{HTTP_HOST} = 'example.com';
258         $ENV{CONTENT_LENGTH} = length $in;
259 });
260 %bits = parse_cgi_content($content);
261 is($bits{basehref}, "/wiki/a/b/c/");
262 is($bits{stylehref}, "/wiki/style.css");
263 like($bits{tophref}, qr{^(?:/wiki|\.\./\.\./\.\.)/$});
264 is($bits{cgihref}, "/cgi-bin/ikiwiki.cgi");
265
266 #######################################################################
267 # site 2: static content and CGI are on different servers
268
269 writefile("test.setup", "t/tmp", <<EOF
270 # IkiWiki::Setup::Yaml - YAML formatted setup file
271 wikiname: this is the name of my wiki
272 srcdir: t/tmp/in
273 destdir: t/tmp/out
274 templatedir: templates
275 url: "http://static.example.com/"
276 cgiurl: "http://cgi.example.com/ikiwiki.cgi"
277 cgi_wrapper: t/tmp/ikiwiki.cgi
278 cgi_wrappermode: 0754
279 html5: 0
280 # make it easier to test previewing
281 add_plugins:
282 - anonok
283 anonok_pagespec: "*"
284 ENV: { 'PERL5LIB': '$PERL5LIB' }
285 EOF
286 );
287
288 ok(unlink("t/tmp/ikiwiki.cgi"));
289 ok(! system("./ikiwiki.out --setup t/tmp/test.setup --rebuild --wrappers"));
290
291 # CGI wrapper should be exactly the requested mode
292 (undef, undef, $mode, undef, undef,
293         undef, undef, undef, undef, undef,
294         undef, undef, undef) = stat("t/tmp/ikiwiki.cgi");
295 is($mode & 07777, 0754);
296
297 ok(-e "t/tmp/out/a/b/c/index.html");
298 $content = readfile("t/tmp/out/a/b/c/index.html");
299 # no <base> on static HTML
300 unlike($content, qr{<base\W});
301 # url and cgiurl are not on the same host so the cgiurl has to be
302 # protocol-relative or absolute
303 like($content, qr{<a[^>]+href="(?:http:)?//cgi.example.com/ikiwiki.cgi\?do=prefs"});
304 # cross-links between static pages are still relative
305 like($content, qr{<li>A: <a href="../../">a</a></li>});
306 like($content, qr{<li>B: <a href="../">b</a></li>});
307 like($content, qr{<li>E: <a href="../../d/e/">e</a></li>});
308
309 run(["./t/tmp/ikiwiki.cgi"], \undef, \$content, init => sub {
310         $ENV{REQUEST_METHOD} = 'GET';
311         $ENV{SERVER_PORT} = '80';
312         $ENV{SCRIPT_NAME} = '/ikiwiki.cgi';
313         $ENV{QUERY_STRING} = 'do=prefs';
314         $ENV{HTTP_HOST} = 'cgi.example.com';
315 });
316 %bits = parse_cgi_content($content);
317 like($bits{basehref}, qr{^http://static.example.com/$});
318 like($bits{stylehref}, qr{^(?:(?:http:)?//static.example.com)?/style.css$});
319 like($bits{tophref}, qr{^(?:http:)?//static.example.com/$});
320 like($bits{cgihref}, qr{^(?:(?:http:)?//cgi.example.com)?/ikiwiki.cgi$});
321
322 # when accessed via HTTPS, links are secure
323 run(["./t/tmp/ikiwiki.cgi"], \undef, \$content, init => sub {
324         $ENV{REQUEST_METHOD} = 'GET';
325         $ENV{SERVER_PORT} = '443';
326         $ENV{SCRIPT_NAME} = '/ikiwiki.cgi';
327         $ENV{QUERY_STRING} = 'do=prefs';
328         $ENV{HTTP_HOST} = 'cgi.example.com';
329         $ENV{HTTPS} = 'on';
330 });
331 %bits = parse_cgi_content($content);
332 like($bits{basehref}, qr{^https://static.example.com/$});
333 like($bits{stylehref}, qr{^(?:(?:https:)?//static.example.com)?/style.css$});
334 like($bits{tophref}, qr{^(?:https:)?//static.example.com/$});
335 like($bits{cgihref}, qr{^(?:(?:https:)?//cgi.example.com)?/ikiwiki.cgi$});
336
337 # when accessed via a different hostname, links to the CGI (only) should
338 # stay on that host?
339 $in = 'do=edit&page=a/b/c&Preview';
340 run(["./t/tmp/ikiwiki.cgi"], \$in, \$content, init => sub {
341         $ENV{REQUEST_METHOD} = 'POST';
342         $ENV{SERVER_PORT} = '80';
343         $ENV{SCRIPT_NAME} = '/ikiwiki.cgi';
344         $ENV{HTTP_HOST} = 'staging.example.net';
345         $ENV{CONTENT_LENGTH} = length $in;
346 });
347 %bits = parse_cgi_content($content);
348 like($bits{basehref}, qr{^http://static.example.com/a/b/c/$});
349 like($bits{stylehref}, qr{^(?:(?:http:)?//static.example.com|\.\./\.\./\.\.)/style.css$});
350 like($bits{tophref}, qr{^(?:(?:http:)?//static.example.com|\.\./\.\./\.\.)/$});
351 like($bits{cgihref}, qr{^(?:(?:http:)?//(?:staging\.example\.net|cgi\.example\.com))?/ikiwiki.cgi$});
352 TODO: {
353 local $TODO = "use self-referential CGI URL?";
354 like($bits{cgihref}, qr{^(?:(?:http:)?//staging.example.net)?/ikiwiki.cgi$});
355 }
356
357 writefile("test.setup", "t/tmp", <<EOF
358 # IkiWiki::Setup::Yaml - YAML formatted setup file
359 wikiname: this is the name of my wiki
360 srcdir: t/tmp/in
361 destdir: t/tmp/out
362 templatedir: templates
363 url: "http://static.example.com/"
364 cgiurl: "http://cgi.example.com/ikiwiki.cgi"
365 cgi_wrapper: t/tmp/ikiwiki.cgi
366 cgi_wrappermode: 0754
367 html5: 1
368 # make it easier to test previewing
369 add_plugins:
370 - anonok
371 anonok_pagespec: "*"
372 ENV: { 'PERL5LIB': '$PERL5LIB' }
373 EOF
374 );
375
376 ok(unlink("t/tmp/ikiwiki.cgi"));
377 ok(! system("./ikiwiki.out --setup t/tmp/test.setup --rebuild --wrappers"));
378
379 # CGI wrapper should be exactly the requested mode
380 (undef, undef, $mode, undef, undef,
381         undef, undef, undef, undef, undef,
382         undef, undef, undef) = stat("t/tmp/ikiwiki.cgi");
383 is($mode & 07777, 0754);
384
385 ok(-e "t/tmp/out/a/b/c/index.html");
386 $content = readfile("t/tmp/out/a/b/c/index.html");
387 # no <base> on static HTML
388 unlike($content, qr{<base\W});
389 # url and cgiurl are not on the same host so the cgiurl has to be
390 # protocol-relative or absolute
391 like($content, qr{<a[^>]+href="(?:http:)?//cgi.example.com/ikiwiki.cgi\?do=prefs"});
392 # cross-links between static pages are still relative
393 like($content, qr{<li>A: <a href="../../">a</a></li>});
394 like($content, qr{<li>B: <a href="../">b</a></li>});
395 like($content, qr{<li>E: <a href="../../d/e/">e</a></li>});
396
397 run(["./t/tmp/ikiwiki.cgi"], \undef, \$content, init => sub {
398         $ENV{REQUEST_METHOD} = 'GET';
399         $ENV{SERVER_PORT} = '80';
400         $ENV{SCRIPT_NAME} = '/ikiwiki.cgi';
401         $ENV{QUERY_STRING} = 'do=prefs';
402         $ENV{HTTP_HOST} = 'cgi.example.com';
403 });
404 %bits = parse_cgi_content($content);
405 is($bits{basehref}, "//static.example.com/");
406 is($bits{stylehref}, "//static.example.com/style.css");
407 is($bits{tophref}, "//static.example.com/");
408 is($bits{cgihref}, "//cgi.example.com/ikiwiki.cgi");
409
410 # when accessed via HTTPS, links are secure - in fact they're exactly the
411 # same as when accessed via HTTP
412 run(["./t/tmp/ikiwiki.cgi"], \undef, \$content, init => sub {
413         $ENV{REQUEST_METHOD} = 'GET';
414         $ENV{SERVER_PORT} = '443';
415         $ENV{SCRIPT_NAME} = '/ikiwiki.cgi';
416         $ENV{QUERY_STRING} = 'do=prefs';
417         $ENV{HTTP_HOST} = 'cgi.example.com';
418         $ENV{HTTPS} = 'on';
419 });
420 %bits = parse_cgi_content($content);
421 is($bits{basehref}, "//static.example.com/");
422 is($bits{stylehref}, "//static.example.com/style.css");
423 is($bits{tophref}, "//static.example.com/");
424 is($bits{cgihref}, "//cgi.example.com/ikiwiki.cgi");
425
426 # when accessed via a different hostname, links to the CGI (only) should
427 # stay on that host?
428 $in = 'do=edit&page=a/b/c&Preview';
429 run(["./t/tmp/ikiwiki.cgi"], \$in, \$content, init => sub {
430         $ENV{REQUEST_METHOD} = 'POST';
431         $ENV{SERVER_PORT} = '80';
432         $ENV{SCRIPT_NAME} = '/ikiwiki.cgi';
433         $ENV{HTTP_HOST} = 'staging.example.net';
434         $ENV{CONTENT_LENGTH} = length $in;
435 });
436 %bits = parse_cgi_content($content);
437 is($bits{basehref}, "//static.example.com/a/b/c/");
438 is($bits{stylehref}, "//static.example.com/style.css");
439 is($bits{tophref}, "../../../");
440 like($bits{cgihref}, qr{//(?:staging\.example\.net|cgi\.example\.com)/ikiwiki\.cgi});
441 TODO: {
442 local $TODO = "use self-referential CGI URL maybe?";
443 is($bits{cgihref}, "//staging.example.net/ikiwiki.cgi");
444 }
445
446 #######################################################################
447 # site 3: we specifically want everything to be secure
448
449 writefile("test.setup", "t/tmp", <<EOF
450 # IkiWiki::Setup::Yaml - YAML formatted setup file
451 wikiname: this is the name of my wiki
452 srcdir: t/tmp/in
453 destdir: t/tmp/out
454 templatedir: templates
455 url: "https://example.com/wiki/"
456 cgiurl: "https://example.com/cgi-bin/ikiwiki.cgi"
457 cgi_wrapper: t/tmp/ikiwiki.cgi
458 cgi_wrappermode: 0754
459 html5: 0
460 # make it easier to test previewing
461 add_plugins:
462 - anonok
463 anonok_pagespec: "*"
464 ENV: { 'PERL5LIB': '$PERL5LIB' }
465 EOF
466 );
467
468 ok(unlink("t/tmp/ikiwiki.cgi"));
469 ok(! system("./ikiwiki.out --setup t/tmp/test.setup --rebuild --wrappers"));
470
471 # CGI wrapper should be exactly the requested mode
472 (undef, undef, $mode, undef, undef,
473         undef, undef, undef, undef, undef,
474         undef, undef, undef) = stat("t/tmp/ikiwiki.cgi");
475 is($mode & 07777, 0754);
476
477 ok(-e "t/tmp/out/a/b/c/index.html");
478 $content = readfile("t/tmp/out/a/b/c/index.html");
479 # no <base> on static HTML
480 unlike($content, qr{<base\W});
481 # url and cgiurl are on the same host so the cgiurl is host-relative
482 like($content, qr{<a[^>]+href="/cgi-bin/ikiwiki.cgi\?do=prefs"});
483 # cross-links between static pages are relative
484 like($content, qr{<li>A: <a href="../../">a</a></li>});
485 like($content, qr{<li>B: <a href="../">b</a></li>});
486 like($content, qr{<li>E: <a href="../../d/e/">e</a></li>});
487
488 # when accessed via HTTPS, links are secure
489 run(["./t/tmp/ikiwiki.cgi"], \undef, \$content, init => sub {
490         $ENV{REQUEST_METHOD} = 'GET';
491         $ENV{SERVER_PORT} = '443';
492         $ENV{SCRIPT_NAME} = '/cgi-bin/ikiwiki.cgi';
493         $ENV{QUERY_STRING} = 'do=prefs';
494         $ENV{HTTP_HOST} = 'example.com';
495         $ENV{HTTPS} = 'on';
496 });
497 %bits = parse_cgi_content($content);
498 is($bits{basehref}, "https://example.com/wiki/");
499 like($bits{stylehref}, qr{^(?:(?:https:)?//example.com)?/wiki/style.css$});
500 like($bits{tophref}, qr{^(?:/wiki|\.)/$});
501 like($bits{cgihref}, qr{^(?:(?:https:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
502
503 # when not accessed via HTTPS, links should still be secure
504 # (but if this happens, that's a sign of web server misconfiguration)
505 run(["./t/tmp/ikiwiki.cgi"], \undef, \$content, init => sub {
506         $ENV{REQUEST_METHOD} = 'GET';
507         $ENV{SERVER_PORT} = '80';
508         $ENV{SCRIPT_NAME} = '/cgi-bin/ikiwiki.cgi';
509         $ENV{QUERY_STRING} = 'do=prefs';
510         $ENV{HTTP_HOST} = 'example.com';
511 });
512 %bits = parse_cgi_content($content);
513 like($bits{tophref}, qr{^(?:/wiki|\.)/$});
514 TODO: {
515 local $TODO = "treat https in configured url, cgiurl as required?";
516 is($bits{basehref}, "https://example.com/wiki/");
517 like($bits{stylehref}, qr{^(?:(?:https:)?//example.com)?/wiki/style.css$});
518 }
519 like($bits{cgihref}, qr{^(?:(?:https:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
520
521 # when accessed via a different hostname, links stay on that host
522 run(["./t/tmp/ikiwiki.cgi"], \undef, \$content, init => sub {
523         $ENV{REQUEST_METHOD} = 'GET';
524         $ENV{SERVER_PORT} = '443';
525         $ENV{SCRIPT_NAME} = '/cgi-bin/ikiwiki.cgi';
526         $ENV{QUERY_STRING} = 'do=prefs';
527         $ENV{HTTP_HOST} = 'staging.example.net';
528         $ENV{HTTPS} = 'on';
529 });
530 %bits = parse_cgi_content($content);
531 is($bits{basehref}, "https://staging.example.net/wiki/");
532 like($bits{stylehref}, qr{^(?:(?:https:)?//staging.example.net)?/wiki/style.css$});
533 like($bits{tophref}, qr{^(?:/wiki|\.)/$});
534 like($bits{cgihref}, qr{^(?:(?:https:)?//staging.example.net)?/cgi-bin/ikiwiki.cgi$});
535
536 # previewing a page
537 $in = 'do=edit&page=a/b/c&Preview';
538 run(["./t/tmp/ikiwiki.cgi"], \$in, \$content, init => sub {
539         $ENV{REQUEST_METHOD} = 'POST';
540         $ENV{SERVER_PORT} = '443';
541         $ENV{SCRIPT_NAME} = '/cgi-bin/ikiwiki.cgi';
542         $ENV{HTTP_HOST} = 'example.com';
543         $ENV{CONTENT_LENGTH} = length $in;
544         $ENV{HTTPS} = 'on';
545 });
546 %bits = parse_cgi_content($content);
547 is($bits{basehref}, "https://example.com/wiki/a/b/c/");
548 like($bits{stylehref}, qr{^(?:(?:https:)?//example.com)?/wiki/style.css$});
549 like($bits{tophref}, qr{^(?:/wiki|\.\./\.\./\.\.)/$});
550 like($bits{cgihref}, qr{^(?:(?:https:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
551
552 # not testing html5: 0 here because that ends up identical to site 1
553
554 #######################################################################
555 # site 4 (NetBSD wiki): CGI is secure, static content doesn't have to be
556
557 writefile("test.setup", "t/tmp", <<EOF
558 # IkiWiki::Setup::Yaml - YAML formatted setup file
559 wikiname: this is the name of my wiki
560 srcdir: t/tmp/in
561 destdir: t/tmp/out
562 templatedir: templates
563 url: "http://example.com/wiki/"
564 cgiurl: "https://example.com/cgi-bin/ikiwiki.cgi"
565 cgi_wrapper: t/tmp/ikiwiki.cgi
566 cgi_wrappermode: 0754
567 html5: 0
568 # make it easier to test previewing
569 add_plugins:
570 - anonok
571 anonok_pagespec: "*"
572 ENV: { 'PERL5LIB': '$PERL5LIB' }
573 EOF
574 );
575
576 ok(unlink("t/tmp/ikiwiki.cgi"));
577 ok(! system("./ikiwiki.out --setup t/tmp/test.setup --rebuild --wrappers"));
578
579 # CGI wrapper should be exactly the requested mode
580 (undef, undef, $mode, undef, undef,
581         undef, undef, undef, undef, undef,
582         undef, undef, undef) = stat("t/tmp/ikiwiki.cgi");
583 is($mode & 07777, 0754);
584
585 ok(-e "t/tmp/out/a/b/c/index.html");
586 $content = readfile("t/tmp/out/a/b/c/index.html");
587 # no <base> on static HTML
588 unlike($content, qr{<base\W});
589 # url and cgiurl are on the same host but different schemes
590 like($content, qr{<a[^>]+href="https://example.com/cgi-bin/ikiwiki.cgi\?do=prefs"});
591 # cross-links between static pages are relative
592 like($content, qr{<li>A: <a href="../../">a</a></li>});
593 like($content, qr{<li>B: <a href="../">b</a></li>});
594 like($content, qr{<li>E: <a href="../../d/e/">e</a></li>});
595
596 # when accessed via HTTPS, links are secure (to avoid mixed-content)
597 run(["./t/tmp/ikiwiki.cgi"], \undef, \$content, init => sub {
598         $ENV{REQUEST_METHOD} = 'GET';
599         $ENV{SERVER_PORT} = '443';
600         $ENV{SCRIPT_NAME} = '/cgi-bin/ikiwiki.cgi';
601         $ENV{QUERY_STRING} = 'do=prefs';
602         $ENV{HTTP_HOST} = 'example.com';
603         $ENV{HTTPS} = 'on';
604 });
605 %bits = parse_cgi_content($content);
606 is($bits{basehref}, "https://example.com/wiki/");
607 like($bits{stylehref}, qr{^(?:(?:https:)?//example.com)?/wiki/style.css$});
608 like($bits{tophref}, qr{^(?:/wiki|\.)/$});
609 like($bits{cgihref}, qr{^(?:(?:https:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
610
611 # when not accessed via HTTPS, ???
612 run(["./t/tmp/ikiwiki.cgi"], \undef, \$content, init => sub {
613         $ENV{REQUEST_METHOD} = 'GET';
614         $ENV{SERVER_PORT} = '80';
615         $ENV{SCRIPT_NAME} = '/cgi-bin/ikiwiki.cgi';
616         $ENV{QUERY_STRING} = 'do=prefs';
617         $ENV{HTTP_HOST} = 'example.com';
618 });
619 %bits = parse_cgi_content($content);
620 like($bits{basehref}, qr{^https?://example.com/wiki/$});
621 like($bits{stylehref}, qr{^(?:(?:https?:)?//example.com)?/wiki/style.css$});
622 like($bits{tophref}, qr{^(?:(?:https?://example.com)?/wiki|\.)/$});
623 like($bits{cgihref}, qr{^(?:(?:https:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
624
625 # when accessed via a different hostname, links stay on that host
626 run(["./t/tmp/ikiwiki.cgi"], \undef, \$content, init => sub {
627         $ENV{REQUEST_METHOD} = 'GET';
628         $ENV{SERVER_PORT} = '443';
629         $ENV{SCRIPT_NAME} = '/cgi-bin/ikiwiki.cgi';
630         $ENV{QUERY_STRING} = 'do=prefs';
631         $ENV{HTTP_HOST} = 'staging.example.net';
632         $ENV{HTTPS} = 'on';
633 });
634 %bits = parse_cgi_content($content);
635 # because the static and dynamic stuff is on the same server, we assume that
636 # both are also on the staging server
637 like($bits{basehref}, qr{^https://staging.example.net/wiki/$});
638 like($bits{stylehref}, qr{^(?:(?:https:)?//staging.example.net)?/wiki/style.css$});
639 like($bits{tophref}, qr{^(?:(?:(?:https:)?//staging.example.net)?/wiki|\.)/$});
640 like($bits{cgihref}, qr{^(?:(?:https:)?//(?:staging\.example\.net|example\.com))?/cgi-bin/ikiwiki.cgi$});
641 TODO: {
642 local $TODO = "this should really point back to itself but currently points to example.com";
643 like($bits{cgihref}, qr{^(?:(?:https:)?//staging.example.net)?/cgi-bin/ikiwiki.cgi$});
644 }
645
646 # previewing a page
647 $in = 'do=edit&page=a/b/c&Preview';
648 run(["./t/tmp/ikiwiki.cgi"], \$in, \$content, init => sub {
649         $ENV{REQUEST_METHOD} = 'POST';
650         $ENV{SERVER_PORT} = '443';
651         $ENV{SCRIPT_NAME} = '/cgi-bin/ikiwiki.cgi';
652         $ENV{HTTP_HOST} = 'example.com';
653         $ENV{CONTENT_LENGTH} = length $in;
654         $ENV{HTTPS} = 'on';
655 });
656 %bits = parse_cgi_content($content);
657 is($bits{basehref}, "https://example.com/wiki/a/b/c/");
658 like($bits{stylehref}, qr{^(?:(?:https:)?//example.com)?/wiki/style.css$});
659 like($bits{tophref}, qr{^(?:/wiki|\.\./\.\./\.\.)/$});
660 like($bits{cgihref}, qr{^(?:(?:https:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
661
662 writefile("test.setup", "t/tmp", <<EOF
663 # IkiWiki::Setup::Yaml - YAML formatted setup file
664 wikiname: this is the name of my wiki
665 srcdir: t/tmp/in
666 destdir: t/tmp/out
667 templatedir: templates
668 url: "http://example.com/wiki/"
669 cgiurl: "https://example.com/cgi-bin/ikiwiki.cgi"
670 cgi_wrapper: t/tmp/ikiwiki.cgi
671 cgi_wrappermode: 0754
672 html5: 1
673 # make it easier to test previewing
674 add_plugins:
675 - anonok
676 anonok_pagespec: "*"
677 ENV: { 'PERL5LIB': '$PERL5LIB' }
678 EOF
679 );
680
681 ok(unlink("t/tmp/ikiwiki.cgi"));
682 ok(! system("./ikiwiki.out --setup t/tmp/test.setup --rebuild --wrappers"));
683
684 # CGI wrapper should be exactly the requested mode
685 (undef, undef, $mode, undef, undef,
686         undef, undef, undef, undef, undef,
687         undef, undef, undef) = stat("t/tmp/ikiwiki.cgi");
688 is($mode & 07777, 0754);
689
690 ok(-e "t/tmp/out/a/b/c/index.html");
691 $content = readfile("t/tmp/out/a/b/c/index.html");
692 # no <base> on static HTML
693 unlike($content, qr{<base\W});
694 # url and cgiurl are on the same host but different schemes
695 like($content, qr{<a[^>]+href="https://example.com/cgi-bin/ikiwiki.cgi\?do=prefs"});
696 # cross-links between static pages are relative
697 like($content, qr{<li>A: <a href="../../">a</a></li>});
698 like($content, qr{<li>B: <a href="../">b</a></li>});
699 like($content, qr{<li>E: <a href="../../d/e/">e</a></li>});
700
701 # when accessed via HTTPS, links are secure (to avoid mixed-content)
702 run(["./t/tmp/ikiwiki.cgi"], \undef, \$content, init => sub {
703         $ENV{REQUEST_METHOD} = 'GET';
704         $ENV{SERVER_PORT} = '443';
705         $ENV{SCRIPT_NAME} = '/cgi-bin/ikiwiki.cgi';
706         $ENV{QUERY_STRING} = 'do=prefs';
707         $ENV{HTTP_HOST} = 'example.com';
708         $ENV{HTTPS} = 'on';
709 });
710 %bits = parse_cgi_content($content);
711 is($bits{basehref}, "/wiki/");
712 is($bits{stylehref}, "/wiki/style.css");
713 is($bits{tophref}, "/wiki/");
714 like($bits{cgihref}, qr{^(?:(?:https:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
715
716 # when not accessed via HTTPS, ???
717 run(["./t/tmp/ikiwiki.cgi"], \undef, \$content, init => sub {
718         $ENV{REQUEST_METHOD} = 'GET';
719         $ENV{SERVER_PORT} = '80';
720         $ENV{SCRIPT_NAME} = '/cgi-bin/ikiwiki.cgi';
721         $ENV{QUERY_STRING} = 'do=prefs';
722         $ENV{HTTP_HOST} = 'example.com';
723 });
724 %bits = parse_cgi_content($content);
725 like($bits{basehref}, qr{^(?:https?://example.com)?/wiki/$});
726 like($bits{stylehref}, qr{^(?:(?:https?:)?//example.com)?/wiki/style.css$});
727 like($bits{tophref}, qr{^(?:(?:https?://example.com)?/wiki|\.)/$});
728 like($bits{cgihref}, qr{^(?:(?:https:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
729
730 # when accessed via a different hostname, links stay on that host
731 run(["./t/tmp/ikiwiki.cgi"], \undef, \$content, init => sub {
732         $ENV{REQUEST_METHOD} = 'GET';
733         $ENV{SERVER_PORT} = '443';
734         $ENV{SCRIPT_NAME} = '/cgi-bin/ikiwiki.cgi';
735         $ENV{QUERY_STRING} = 'do=prefs';
736         $ENV{HTTP_HOST} = 'staging.example.net';
737         $ENV{HTTPS} = 'on';
738 });
739 %bits = parse_cgi_content($content);
740 # because the static and dynamic stuff is on the same server, we assume that
741 # both are also on the staging server
742 is($bits{basehref}, "/wiki/");
743 is($bits{stylehref}, "/wiki/style.css");
744 like($bits{tophref}, qr{^(?:/wiki|\.)/$});
745 like($bits{cgihref}, qr{^(?:(?:https:)?//(?:example\.com|staging\.example\.net))?/cgi-bin/ikiwiki.cgi$});
746 TODO: {
747 local $TODO = "this should really point back to itself but currently points to example.com";
748 like($bits{cgihref}, qr{^(?:(?:https:)?//staging.example.net)?/cgi-bin/ikiwiki.cgi$});
749 }
750
751 # previewing a page
752 $in = 'do=edit&page=a/b/c&Preview';
753 run(["./t/tmp/ikiwiki.cgi"], \$in, \$content, init => sub {
754         $ENV{REQUEST_METHOD} = 'POST';
755         $ENV{SERVER_PORT} = '443';
756         $ENV{SCRIPT_NAME} = '/cgi-bin/ikiwiki.cgi';
757         $ENV{HTTP_HOST} = 'example.com';
758         $ENV{CONTENT_LENGTH} = length $in;
759         $ENV{HTTPS} = 'on';
760 });
761 %bits = parse_cgi_content($content);
762 is($bits{basehref}, "/wiki/a/b/c/");
763 is($bits{stylehref}, "/wiki/style.css");
764 like($bits{tophref}, qr{^(?:/wiki|\.\./\.\./\.\.)/$});
765 like($bits{cgihref}, qr{^(?:(?:https:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
766
767 # Deliberately not testing https static content with http cgiurl,
768 # because that makes remarkably little sense.
769
770 #######################################################################
771 # site 5: w3mmode, as documented in [[w3mmode]]
772
773 writefile("test.setup", "t/tmp", <<EOF
774 # IkiWiki::Setup::Yaml - YAML formatted setup file
775 wikiname: this is the name of my wiki
776 srcdir: t/tmp/in
777 destdir: t/tmp/out
778 templatedir: templates
779 cgiurl: ikiwiki.cgi
780 w3mmode: 1
781 cgi_wrapper: t/tmp/ikiwiki.cgi
782 cgi_wrappermode: 0754
783 html5: 0
784 add_plugins:
785 - anonok
786 anonok_pagespec: "*"
787 ENV: { 'PERL5LIB': '$PERL5LIB' }
788 EOF
789 );
790
791 ok(unlink("t/tmp/ikiwiki.cgi"));
792 ok(! system("./ikiwiki.out --setup t/tmp/test.setup --rebuild --wrappers"));
793
794 # CGI wrapper should be exactly the requested mode
795 (undef, undef, $mode, undef, undef,
796         undef, undef, undef, undef, undef,
797         undef, undef, undef) = stat("t/tmp/ikiwiki.cgi");
798 is($mode & 07777, 0754);
799
800 ok(-e "t/tmp/out/a/b/c/index.html");
801 $content = readfile("t/tmp/out/a/b/c/index.html");
802 # no <base> on static HTML
803 unlike($content, qr{<base\W});
804 # FIXME: does /$LIB/ikiwiki-w3m.cgi work under w3m?
805 like($content, qr{<a[^>]+href="(?:file://)?/\$LIB/ikiwiki-w3m.cgi/ikiwiki.cgi\?do=prefs"});
806 # cross-links between static pages are still relative
807 like($content, qr{<li>A: <a href="../../">a</a></li>});
808 like($content, qr{<li>B: <a href="../">b</a></li>});
809 like($content, qr{<li>E: <a href="../../d/e/">e</a></li>});
810
811 run(["./t/tmp/ikiwiki.cgi"], \undef, \$content, init => sub {
812         $ENV{REQUEST_METHOD} = 'GET';
813         $ENV{PATH_INFO} = '/ikiwiki.cgi';
814         $ENV{SCRIPT_NAME} = '/cgi-bin/ikiwiki-w3m.cgi';
815         $ENV{QUERY_STRING} = 'do=prefs';
816 });
817 %bits = parse_cgi_content($content);
818 like($bits{tophref}, qr{^(?:\Q$pwd\E/t/tmp/out|\.)/$});
819 like($bits{cgihref}, qr{^(?:file://)?/\$LIB/ikiwiki-w3m.cgi/ikiwiki.cgi$});
820 like($bits{basehref}, qr{^(?:(?:file:)?//)?\Q$pwd\E/t/tmp/out/$});
821 like($bits{stylehref}, qr{^(?:(?:(?:file:)?//)?\Q$pwd\E/t/tmp/out|\.)/style.css$});
822
823 writefile("test.setup", "t/tmp", <<EOF
824 # IkiWiki::Setup::Yaml - YAML formatted setup file
825 wikiname: this is the name of my wiki
826 srcdir: t/tmp/in
827 destdir: t/tmp/out
828 templatedir: templates
829 cgiurl: ikiwiki.cgi
830 w3mmode: 1
831 cgi_wrapper: t/tmp/ikiwiki.cgi
832 cgi_wrappermode: 0754
833 html5: 1
834 add_plugins:
835 - anonok
836 anonok_pagespec: "*"
837 ENV: { 'PERL5LIB': '$PERL5LIB' }
838 EOF
839 );
840
841 ok(unlink("t/tmp/ikiwiki.cgi"));
842 ok(! system("./ikiwiki.out --setup t/tmp/test.setup --rebuild --wrappers"));
843
844 # CGI wrapper should be exactly the requested mode
845 (undef, undef, $mode, undef, undef,
846         undef, undef, undef, undef, undef,
847         undef, undef, undef) = stat("t/tmp/ikiwiki.cgi");
848 is($mode & 07777, 0754);
849
850 ok(-e "t/tmp/out/a/b/c/index.html");
851 $content = readfile("t/tmp/out/a/b/c/index.html");
852 # no <base> on static HTML
853 unlike($content, qr{<base\W});
854 # FIXME: does /$LIB/ikiwiki-w3m.cgi work under w3m?
855 like($content, qr{<a[^>]+href="(?:file://)?/\$LIB/ikiwiki-w3m.cgi/ikiwiki.cgi\?do=prefs"});
856 # cross-links between static pages are still relative
857 like($content, qr{<li>A: <a href="../../">a</a></li>});
858 like($content, qr{<li>B: <a href="../">b</a></li>});
859 like($content, qr{<li>E: <a href="../../d/e/">e</a></li>});
860
861 run(["./t/tmp/ikiwiki.cgi"], \undef, \$content, init => sub {
862         $ENV{REQUEST_METHOD} = 'GET';
863         $ENV{PATH_INFO} = '/ikiwiki.cgi';
864         $ENV{SCRIPT_NAME} = '/cgi-bin/ikiwiki-w3m.cgi';
865         $ENV{QUERY_STRING} = 'do=prefs';
866 });
867 %bits = parse_cgi_content($content);
868 like($bits{tophref}, qr{^(?:\Q$pwd\E/t/tmp/out|\.)/$});
869 like($bits{cgihref}, qr{^(?:file://)?/\$LIB/ikiwiki-w3m.cgi/ikiwiki.cgi$});
870 like($bits{basehref}, qr{^(?:(?:file:)?//)?\Q$pwd\E/t/tmp/out/$});
871 like($bits{stylehref}, qr{^(?:(?:(?:file:)?//)?\Q$pwd\E/t/tmp/out|\.)/style.css$});
872
873 #######################################################################
874 # site 6: we're behind a reverse-proxy
875
876 writefile("test.setup", "t/tmp", <<EOF
877 # IkiWiki::Setup::Yaml - YAML formatted setup file
878 wikiname: this is the name of my wiki
879 srcdir: t/tmp/in
880 destdir: t/tmp/out
881 templatedir: templates
882 url: "https://example.com/wiki/"
883 cgiurl: "https://example.com/cgi-bin/ikiwiki.cgi"
884 cgi_wrapper: t/tmp/ikiwiki.cgi
885 cgi_wrappermode: 0754
886 html5: 0
887 # make it easier to test previewing
888 add_plugins:
889 - anonok
890 anonok_pagespec: "*"
891 reverse_proxy: 1
892 ENV: { 'PERL5LIB': '$PERL5LIB' }
893 EOF
894 );
895
896 ok(unlink("t/tmp/ikiwiki.cgi"));
897 ok(! system("./ikiwiki.out --setup t/tmp/test.setup --rebuild --wrappers"));
898
899 # CGI wrapper should be exactly the requested mode
900 (undef, undef, $mode, undef, undef,
901         undef, undef, undef, undef, undef,
902         undef, undef, undef) = stat("t/tmp/ikiwiki.cgi");
903 is($mode & 07777, 0754);
904
905 ok(-e "t/tmp/out/a/b/c/index.html");
906 $content = readfile("t/tmp/out/a/b/c/index.html");
907 # no <base> on static HTML
908 unlike($content, qr{<base\W});
909 # url and cgiurl are on the same host so the cgiurl is host-relative
910 like($content, qr{<a[^>]+href="/cgi-bin/ikiwiki.cgi\?do=prefs"});
911 # cross-links between static pages are relative
912 like($content, qr{<li>A: <a href="../../">a</a></li>});
913 like($content, qr{<li>B: <a href="../">b</a></li>});
914 like($content, qr{<li>E: <a href="../../d/e/">e</a></li>});
915
916 # because we are behind a reverse-proxy we must assume that
917 # we're being accessed by the configured cgiurl
918 run(["./t/tmp/ikiwiki.cgi"], \undef, \$content, init => sub {
919         $ENV{REQUEST_METHOD} = 'GET';
920         $ENV{SERVER_PORT} = '80';
921         $ENV{SCRIPT_NAME} = '/cgi-bin/ikiwiki.cgi';
922         $ENV{QUERY_STRING} = 'do=prefs';
923         $ENV{HTTP_HOST} = 'localhost';
924 });
925 %bits = parse_cgi_content($content);
926 like($bits{tophref}, qr{^(?:/wiki|\.)/$});
927 like($bits{cgihref}, qr{^(?:(?:https:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
928 is($bits{basehref}, "https://example.com/wiki/");
929 like($bits{stylehref}, qr{^(?:(?:https:)?//example.com)?/wiki/style.css$});
930
931 # previewing a page
932 $in = 'do=edit&page=a/b/c&Preview';
933 run(["./t/tmp/ikiwiki.cgi"], \$in, \$content, init => sub {
934         $ENV{REQUEST_METHOD} = 'POST';
935         $ENV{SERVER_PORT} = '80';
936         $ENV{SCRIPT_NAME} = '/cgi-bin/ikiwiki.cgi';
937         $ENV{HTTP_HOST} = 'localhost';
938         $ENV{CONTENT_LENGTH} = length $in;
939 });
940 %bits = parse_cgi_content($content);
941 like($bits{tophref}, qr{^(?:/wiki|\.\./\.\./\.\.)/$});
942 like($bits{cgihref}, qr{^(?:(?:https:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
943 is($bits{basehref}, "https://example.com/wiki/a/b/c/");
944 like($bits{stylehref}, qr{^(?:(?:https:)?//example.com)?/wiki/style.css$});
945
946 # not testing html5: 1 because it would be the same as site 1 -
947 # the reverse_proxy config option is unnecessary under html5
948
949 done_testing;