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