eb6cc448a7929a3b3e661686941d2a991580f045
[ikiwiki.git] / 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 # make it easier to test previewing
81 add_plugins:
82 - anonok
83 anonok_pagespec: "*"
84 ENV: { 'PERL5LIB': '$PERL5LIB' }
85 EOF
86 );
87
88 ok(unlink("t/tmp/ikiwiki.cgi") || $!{ENOENT});
89 ok(! system("./ikiwiki.out --setup t/tmp/test.setup --rebuild --wrappers"));
90
91 # CGI wrapper should be exactly the requested mode
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);
96
97 ok(-e "t/tmp/out/a/b/c/index.html");
98 $content = readfile("t/tmp/out/a/b/c/index.html");
99 # no <base> on static HTML
100 unlike($content, qr{<base\W});
101 # url and cgiurl are on the same host so the cgiurl is host-relative
102 like($content, qr{<a[^>]+href="/cgi-bin/ikiwiki.cgi\?do=prefs"});
103 # cross-links between static pages are relative
104 like($content, qr{<li>A: <a href="../../">a</a></li>});
105 like($content, qr{<li>B: <a href="../">b</a></li>});
106 like($content, qr{<li>E: <a href="../../d/e/">e</a></li>});
107
108 run(["./t/tmp/ikiwiki.cgi"], \undef, \$content, init => sub {
109         $ENV{REQUEST_METHOD} = 'GET';
110         $ENV{SERVER_PORT} = '80';
111         $ENV{SCRIPT_NAME} = '/cgi-bin/ikiwiki.cgi';
112         $ENV{QUERY_STRING} = 'do=prefs';
113         $ENV{HTTP_HOST} = 'example.com';
114 });
115 %bits = parse_cgi_content($content);
116 is($bits{basehref}, "http://example.com/wiki/");
117 like($bits{stylehref}, qr{^(?:(?:http:)?//example.com)?/wiki/style.css$});
118 like($bits{tophref}, qr{^(?:/wiki|\.)/$});
119 like($bits{cgihref}, qr{^(?:(?:http:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
120
121 # when accessed via HTTPS, links are secure
122 run(["./t/tmp/ikiwiki.cgi"], \undef, \$content, init => sub {
123         $ENV{REQUEST_METHOD} = 'GET';
124         $ENV{SERVER_PORT} = '443';
125         $ENV{SCRIPT_NAME} = '/cgi-bin/ikiwiki.cgi';
126         $ENV{QUERY_STRING} = 'do=prefs';
127         $ENV{HTTP_HOST} = 'example.com';
128         $ENV{HTTPS} = 'on';
129 });
130 %bits = parse_cgi_content($content);
131 is($bits{basehref}, "https://example.com/wiki/");
132 like($bits{stylehref}, qr{^(?:(?:https:)?//example.com)?/wiki/style.css$});
133 like($bits{tophref}, qr{^(?:/wiki|\.)/$});
134 like($bits{cgihref}, qr{^(?:(?:https:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
135
136 # when accessed via a different hostname, links stay on that host
137 run(["./t/tmp/ikiwiki.cgi"], \undef, \$content, init => sub {
138         $ENV{REQUEST_METHOD} = 'GET';
139         $ENV{SERVER_PORT} = '80';
140         $ENV{SCRIPT_NAME} = '/cgi-bin/ikiwiki.cgi';
141         $ENV{QUERY_STRING} = 'do=prefs';
142         $ENV{HTTP_HOST} = 'staging.example.net';
143 });
144 %bits = parse_cgi_content($content);
145 is($bits{basehref}, "http://staging.example.net/wiki/");
146 like($bits{stylehref}, qr{^(?:(?:http:)?//staging.example.net)?/wiki/style.css$});
147 like($bits{tophref}, qr{^(?:/wiki|\.)/$});
148 like($bits{cgihref}, qr{^(?:(?:http:)?//staging.example.net)?/cgi-bin/ikiwiki.cgi$});
149
150 # previewing a page
151 $in = 'do=edit&page=a/b/c&Preview';
152 run(["./t/tmp/ikiwiki.cgi"], \$in, \$content, init => sub {
153         $ENV{REQUEST_METHOD} = 'POST';
154         $ENV{SERVER_PORT} = '80';
155         $ENV{SCRIPT_NAME} = '/cgi-bin/ikiwiki.cgi';
156         $ENV{HTTP_HOST} = 'example.com';
157         $ENV{CONTENT_LENGTH} = length $in;
158 });
159 %bits = parse_cgi_content($content);
160 is($bits{basehref}, "http://example.com/wiki/a/b/c/");
161 like($bits{stylehref}, qr{^(?:(?:http:)?//example.com)?/wiki/style.css$});
162 like($bits{tophref}, qr{^(?:/wiki|\.\./\.\./\.\.)/$});
163 like($bits{cgihref}, qr{^(?:(?:http:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
164
165 #######################################################################
166 # site 2: static content and CGI are on different servers
167
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://static.example.com/"
175 cgiurl: "http://cgi.example.com/ikiwiki.cgi"
176 cgi_wrapper: t/tmp/ikiwiki.cgi
177 cgi_wrappermode: 0754
178 # make it easier to test previewing
179 add_plugins:
180 - anonok
181 anonok_pagespec: "*"
182 ENV: { 'PERL5LIB': '$PERL5LIB' }
183 EOF
184 );
185
186 ok(unlink("t/tmp/ikiwiki.cgi"));
187 ok(! system("./ikiwiki.out --setup t/tmp/test.setup --rebuild --wrappers"));
188
189 # CGI wrapper should be exactly the requested mode
190 (undef, undef, $mode, undef, undef,
191         undef, undef, undef, undef, undef,
192         undef, undef, undef) = stat("t/tmp/ikiwiki.cgi");
193 is($mode & 07777, 0754);
194
195 ok(-e "t/tmp/out/a/b/c/index.html");
196 $content = readfile("t/tmp/out/a/b/c/index.html");
197 # no <base> on static HTML
198 unlike($content, qr{<base\W});
199 # url and cgiurl are not on the same host so the cgiurl has to be
200 # protocol-relative or absolute
201 like($content, qr{<a[^>]+href="(?:http:)?//cgi.example.com/ikiwiki.cgi\?do=prefs"});
202 # cross-links between static pages are still 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} = '/ikiwiki.cgi';
211         $ENV{QUERY_STRING} = 'do=prefs';
212         $ENV{HTTP_HOST} = 'cgi.example.com';
213 });
214 %bits = parse_cgi_content($content);
215 like($bits{basehref}, qr{^http://static.example.com/$});
216 like($bits{stylehref}, qr{^(?:(?:http:)?//static.example.com)?/style.css$});
217 like($bits{tophref}, qr{^(?:http:)?//static.example.com/$});
218 like($bits{cgihref}, qr{^(?:(?:http:)?//cgi.example.com)?/ikiwiki.cgi$});
219
220 # when accessed via HTTPS, links are secure
221 run(["./t/tmp/ikiwiki.cgi"], \undef, \$content, init => sub {
222         $ENV{REQUEST_METHOD} = 'GET';
223         $ENV{SERVER_PORT} = '443';
224         $ENV{SCRIPT_NAME} = '/ikiwiki.cgi';
225         $ENV{QUERY_STRING} = 'do=prefs';
226         $ENV{HTTP_HOST} = 'cgi.example.com';
227         $ENV{HTTPS} = 'on';
228 });
229 %bits = parse_cgi_content($content);
230 TODO: {
231 local $TODO = "avoid mixed content";
232 like($bits{basehref}, qr{^https://static.example.com/$});
233 like($bits{stylehref}, qr{^(?:(?:https:)?//static.example.com)?/style.css$});
234 like($bits{tophref}, qr{^(?:https:)?//static.example.com/$});
235 like($bits{cgihref}, qr{^(?:(?:https:)?//cgi.example.com)?/ikiwiki.cgi$});
236 }
237
238 # when accessed via a different hostname, links to the CGI (only) should
239 # stay on that host?
240 $in = 'do=edit&page=a/b/c&Preview';
241 run(["./t/tmp/ikiwiki.cgi"], \$in, \$content, init => sub {
242         $ENV{REQUEST_METHOD} = 'POST';
243         $ENV{SERVER_PORT} = '80';
244         $ENV{SCRIPT_NAME} = '/ikiwiki.cgi';
245         $ENV{HTTP_HOST} = 'staging.example.net';
246         $ENV{CONTENT_LENGTH} = length $in;
247 });
248 %bits = parse_cgi_content($content);
249 like($bits{basehref}, qr{^http://static.example.com/a/b/c/$});
250 like($bits{stylehref}, qr{^(?:(?:http:)?//static.example.com|\.\./\.\./\.\.)/style.css$});
251 like($bits{tophref}, qr{^(?:(?:http:)?//static.example.com|\.\./\.\./\.\.)/$});
252 TODO: {
253 local $TODO = "use self-referential CGI URL?";
254 like($bits{cgihref}, qr{^(?:(?:http:)?//staging.example.net)?/ikiwiki.cgi$});
255 }
256
257 #######################################################################
258 # site 3: we specifically want everything to be secure
259
260 writefile("test.setup", "t/tmp", <<EOF
261 # IkiWiki::Setup::Yaml - YAML formatted setup file
262 wikiname: this is the name of my wiki
263 srcdir: t/tmp/in
264 destdir: t/tmp/out
265 templatedir: templates
266 url: "https://example.com/wiki/"
267 cgiurl: "https://example.com/cgi-bin/ikiwiki.cgi"
268 cgi_wrapper: t/tmp/ikiwiki.cgi
269 cgi_wrappermode: 0754
270 # make it easier to test previewing
271 add_plugins:
272 - anonok
273 anonok_pagespec: "*"
274 ENV: { 'PERL5LIB': '$PERL5LIB' }
275 EOF
276 );
277
278 ok(unlink("t/tmp/ikiwiki.cgi"));
279 ok(! system("./ikiwiki.out --setup t/tmp/test.setup --rebuild --wrappers"));
280
281 # CGI wrapper should be exactly the requested mode
282 (undef, undef, $mode, undef, undef,
283         undef, undef, undef, undef, undef,
284         undef, undef, undef) = stat("t/tmp/ikiwiki.cgi");
285 is($mode & 07777, 0754);
286
287 ok(-e "t/tmp/out/a/b/c/index.html");
288 $content = readfile("t/tmp/out/a/b/c/index.html");
289 # no <base> on static HTML
290 unlike($content, qr{<base\W});
291 # url and cgiurl are on the same host so the cgiurl is host-relative
292 like($content, qr{<a[^>]+href="/cgi-bin/ikiwiki.cgi\?do=prefs"});
293 # cross-links between static pages are relative
294 like($content, qr{<li>A: <a href="../../">a</a></li>});
295 like($content, qr{<li>B: <a href="../">b</a></li>});
296 like($content, qr{<li>E: <a href="../../d/e/">e</a></li>});
297
298 # when accessed via HTTPS, links are secure
299 run(["./t/tmp/ikiwiki.cgi"], \undef, \$content, init => sub {
300         $ENV{REQUEST_METHOD} = 'GET';
301         $ENV{SERVER_PORT} = '443';
302         $ENV{SCRIPT_NAME} = '/cgi-bin/ikiwiki.cgi';
303         $ENV{QUERY_STRING} = 'do=prefs';
304         $ENV{HTTP_HOST} = 'example.com';
305         $ENV{HTTPS} = 'on';
306 });
307 %bits = parse_cgi_content($content);
308 is($bits{basehref}, "https://example.com/wiki/");
309 like($bits{stylehref}, qr{^(?:(?:https:)?//example.com)?/wiki/style.css$});
310 like($bits{tophref}, qr{^(?:/wiki|\.)/$});
311 like($bits{cgihref}, qr{^(?:(?:https:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
312
313 # when not accessed via HTTPS, links should still be secure
314 # (but if this happens, that's a sign of web server misconfiguration)
315 run(["./t/tmp/ikiwiki.cgi"], \undef, \$content, init => sub {
316         $ENV{REQUEST_METHOD} = 'GET';
317         $ENV{SERVER_PORT} = '80';
318         $ENV{SCRIPT_NAME} = '/cgi-bin/ikiwiki.cgi';
319         $ENV{QUERY_STRING} = 'do=prefs';
320         $ENV{HTTP_HOST} = 'example.com';
321 });
322 %bits = parse_cgi_content($content);
323 like($bits{tophref}, qr{^(?:/wiki|\.)/$});
324 TODO: {
325 local $TODO = "treat https in configured url, cgiurl as required?";
326 is($bits{basehref}, "https://example.com/wiki/");
327 like($bits{stylehref}, qr{^(?:(?:https:)?//example.com)?/wiki/style.css$});
328 }
329 like($bits{cgihref}, qr{^(?:(?:https:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
330
331 # when accessed via a different hostname, links stay on that host
332 run(["./t/tmp/ikiwiki.cgi"], \undef, \$content, init => sub {
333         $ENV{REQUEST_METHOD} = 'GET';
334         $ENV{SERVER_PORT} = '443';
335         $ENV{SCRIPT_NAME} = '/cgi-bin/ikiwiki.cgi';
336         $ENV{QUERY_STRING} = 'do=prefs';
337         $ENV{HTTP_HOST} = 'staging.example.net';
338         $ENV{HTTPS} = 'on';
339 });
340 %bits = parse_cgi_content($content);
341 is($bits{basehref}, "https://staging.example.net/wiki/");
342 like($bits{stylehref}, qr{^(?:(?:https:)?//staging.example.net)?/wiki/style.css$});
343 like($bits{tophref}, qr{^(?:/wiki|\.)/$});
344 like($bits{cgihref}, qr{^(?:(?:https:)?//staging.example.net)?/cgi-bin/ikiwiki.cgi$});
345
346 # previewing a page
347 $in = 'do=edit&page=a/b/c&Preview';
348 run(["./t/tmp/ikiwiki.cgi"], \$in, \$content, init => sub {
349         $ENV{REQUEST_METHOD} = 'POST';
350         $ENV{SERVER_PORT} = '443';
351         $ENV{SCRIPT_NAME} = '/cgi-bin/ikiwiki.cgi';
352         $ENV{HTTP_HOST} = 'example.com';
353         $ENV{CONTENT_LENGTH} = length $in;
354         $ENV{HTTPS} = 'on';
355 });
356 %bits = parse_cgi_content($content);
357 is($bits{basehref}, "https://example.com/wiki/a/b/c/");
358 like($bits{stylehref}, qr{^(?:(?:https:)?//example.com)?/wiki/style.css$});
359 like($bits{tophref}, qr{^(?:/wiki|\.\./\.\./\.\.)/$});
360 like($bits{cgihref}, qr{^(?:(?:https:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
361
362 #######################################################################
363 # site 4 (NetBSD wiki): CGI is secure, static content doesn't have to be
364
365 writefile("test.setup", "t/tmp", <<EOF
366 # IkiWiki::Setup::Yaml - YAML formatted setup file
367 wikiname: this is the name of my wiki
368 srcdir: t/tmp/in
369 destdir: t/tmp/out
370 templatedir: templates
371 url: "http://example.com/wiki/"
372 cgiurl: "https://example.com/cgi-bin/ikiwiki.cgi"
373 cgi_wrapper: t/tmp/ikiwiki.cgi
374 cgi_wrappermode: 0754
375 # make it easier to test previewing
376 add_plugins:
377 - anonok
378 anonok_pagespec: "*"
379 ENV: { 'PERL5LIB': '$PERL5LIB' }
380 EOF
381 );
382
383 ok(unlink("t/tmp/ikiwiki.cgi"));
384 ok(! system("./ikiwiki.out --setup t/tmp/test.setup --rebuild --wrappers"));
385
386 # CGI wrapper should be exactly the requested mode
387 (undef, undef, $mode, undef, undef,
388         undef, undef, undef, undef, undef,
389         undef, undef, undef) = stat("t/tmp/ikiwiki.cgi");
390 is($mode & 07777, 0754);
391
392 ok(-e "t/tmp/out/a/b/c/index.html");
393 $content = readfile("t/tmp/out/a/b/c/index.html");
394 # no <base> on static HTML
395 unlike($content, qr{<base\W});
396 # url and cgiurl are on the same host but different schemes
397 like($content, qr{<a[^>]+href="https://example.com/cgi-bin/ikiwiki.cgi\?do=prefs"});
398 # cross-links between static pages are relative
399 like($content, qr{<li>A: <a href="../../">a</a></li>});
400 like($content, qr{<li>B: <a href="../">b</a></li>});
401 like($content, qr{<li>E: <a href="../../d/e/">e</a></li>});
402
403 # when accessed via HTTPS, links are secure (to avoid mixed-content)
404 run(["./t/tmp/ikiwiki.cgi"], \undef, \$content, init => sub {
405         $ENV{REQUEST_METHOD} = 'GET';
406         $ENV{SERVER_PORT} = '443';
407         $ENV{SCRIPT_NAME} = '/cgi-bin/ikiwiki.cgi';
408         $ENV{QUERY_STRING} = 'do=prefs';
409         $ENV{HTTP_HOST} = 'example.com';
410         $ENV{HTTPS} = 'on';
411 });
412 %bits = parse_cgi_content($content);
413 TODO: {
414 local $TODO = "avoid mixed content";
415 is($bits{basehref}, "https://example.com/wiki/");
416 like($bits{stylehref}, qr{^(?:(?:https:)?//example.com)?/wiki/style.css$});
417 like($bits{tophref}, qr{^(?:/wiki|\.)/$});
418 }
419 like($bits{cgihref}, qr{^(?:(?:https:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
420
421 # when not accessed via HTTPS, ???
422 run(["./t/tmp/ikiwiki.cgi"], \undef, \$content, init => sub {
423         $ENV{REQUEST_METHOD} = 'GET';
424         $ENV{SERVER_PORT} = '80';
425         $ENV{SCRIPT_NAME} = '/cgi-bin/ikiwiki.cgi';
426         $ENV{QUERY_STRING} = 'do=prefs';
427         $ENV{HTTP_HOST} = 'example.com';
428 });
429 %bits = parse_cgi_content($content);
430 like($bits{basehref}, qr{^https?://example.com/wiki/$});
431 like($bits{stylehref}, qr{^(?:(?:https?:)?//example.com)?/wiki/style.css$});
432 like($bits{tophref}, qr{^(?:(?:https?://example.com)?/wiki|\.)/$});
433 like($bits{cgihref}, qr{^(?:(?:https:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
434
435 # when accessed via a different hostname, links stay on that host
436 run(["./t/tmp/ikiwiki.cgi"], \undef, \$content, init => sub {
437         $ENV{REQUEST_METHOD} = 'GET';
438         $ENV{SERVER_PORT} = '443';
439         $ENV{SCRIPT_NAME} = '/cgi-bin/ikiwiki.cgi';
440         $ENV{QUERY_STRING} = 'do=prefs';
441         $ENV{HTTP_HOST} = 'staging.example.net';
442         $ENV{HTTPS} = 'on';
443 });
444 %bits = parse_cgi_content($content);
445 TODO: {
446 local $TODO = "avoid mixed content";
447 like($bits{basehref}, qr{^https://example.com/wiki/$});
448 like($bits{stylehref}, qr{^(?:(?:https:)?//example.com)?/wiki/style.css$});
449 like($bits{tophref}, qr{^(?:(?:(?:https:)?//example.com)?/wiki|\.)/$});
450 like($bits{cgihref}, qr{^(?:(?:https:)?//staging.example.net)?/cgi-bin/ikiwiki.cgi$});
451 }
452
453 # previewing a page
454 $in = 'do=edit&page=a/b/c&Preview';
455 run(["./t/tmp/ikiwiki.cgi"], \$in, \$content, init => sub {
456         $ENV{REQUEST_METHOD} = 'POST';
457         $ENV{SERVER_PORT} = '443';
458         $ENV{SCRIPT_NAME} = '/cgi-bin/ikiwiki.cgi';
459         $ENV{HTTP_HOST} = 'example.com';
460         $ENV{CONTENT_LENGTH} = length $in;
461         $ENV{HTTPS} = 'on';
462 });
463 %bits = parse_cgi_content($content);
464 TODO: {
465 local $TODO = "avoid mixed content";
466 is($bits{basehref}, "https://example.com/wiki/a/b/c/");
467 like($bits{stylehref}, qr{^(?:(?:https:)?//example.com)?/wiki/style.css$});
468 }
469 like($bits{tophref}, qr{^(?:/wiki|\.\./\.\./\.\.)/$});
470 like($bits{cgihref}, qr{^(?:(?:https:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
471
472 # Deliberately not testing https static content with http cgiurl,
473 # because that makes remarkably little sense.
474
475 #######################################################################
476 # site 5: w3mmode, as documented in [[w3mmode]]
477
478 writefile("test.setup", "t/tmp", <<EOF
479 # IkiWiki::Setup::Yaml - YAML formatted setup file
480 wikiname: this is the name of my wiki
481 srcdir: t/tmp/in
482 destdir: t/tmp/out
483 templatedir: templates
484 cgiurl: ikiwiki.cgi
485 w3mmode: 1
486 cgi_wrapper: t/tmp/ikiwiki.cgi
487 cgi_wrappermode: 0754
488 add_plugins:
489 - anonok
490 anonok_pagespec: "*"
491 ENV: { 'PERL5LIB': '$PERL5LIB' }
492 EOF
493 );
494
495 ok(unlink("t/tmp/ikiwiki.cgi"));
496 ok(! system("./ikiwiki.out --setup t/tmp/test.setup --rebuild --wrappers"));
497
498 # CGI wrapper should be exactly the requested mode
499 (undef, undef, $mode, undef, undef,
500         undef, undef, undef, undef, undef,
501         undef, undef, undef) = stat("t/tmp/ikiwiki.cgi");
502 is($mode & 07777, 0754);
503
504 ok(-e "t/tmp/out/a/b/c/index.html");
505 $content = readfile("t/tmp/out/a/b/c/index.html");
506 # no <base> on static HTML
507 unlike($content, qr{<base\W});
508 # FIXME: does /$LIB/ikiwiki-w3m.cgi work under w3m?
509 like($content, qr{<a[^>]+href="(?:file://)?/\$LIB/ikiwiki-w3m.cgi/ikiwiki.cgi\?do=prefs"});
510 # cross-links between static pages are still relative
511 like($content, qr{<li>A: <a href="../../">a</a></li>});
512 like($content, qr{<li>B: <a href="../">b</a></li>});
513 like($content, qr{<li>E: <a href="../../d/e/">e</a></li>});
514
515 run(["./t/tmp/ikiwiki.cgi"], \undef, \$content, init => sub {
516         $ENV{REQUEST_METHOD} = 'GET';
517         $ENV{PATH_INFO} = '/ikiwiki.cgi';
518         $ENV{SCRIPT_NAME} = '/cgi-bin/ikiwiki-w3m.cgi';
519         $ENV{QUERY_STRING} = 'do=prefs';
520 });
521 %bits = parse_cgi_content($content);
522 like($bits{tophref}, qr{^(?:\Q$pwd\E/t/tmp/out|\.)/$});
523 like($bits{cgihref}, qr{^(?:file://)?/\$LIB/ikiwiki-w3m.cgi/ikiwiki.cgi$});
524 like($bits{basehref}, qr{^(?:(?:file:)?//)?\Q$pwd\E/t/tmp/out/$});
525 like($bits{stylehref}, qr{^(?:(?:(?:file:)?//)?\Q$pwd\E/t/tmp/out|\.)/style.css$});
526
527 #######################################################################
528 # site 6: we're behind a reverse-proxy
529
530 writefile("test.setup", "t/tmp", <<EOF
531 # IkiWiki::Setup::Yaml - YAML formatted setup file
532 wikiname: this is the name of my wiki
533 srcdir: t/tmp/in
534 destdir: t/tmp/out
535 templatedir: templates
536 url: "https://example.com/wiki/"
537 cgiurl: "https://example.com/cgi-bin/ikiwiki.cgi"
538 cgi_wrapper: t/tmp/ikiwiki.cgi
539 cgi_wrappermode: 0754
540 # make it easier to test previewing
541 add_plugins:
542 - anonok
543 anonok_pagespec: "*"
544 reverse_proxy: 1
545 ENV: { 'PERL5LIB': '$PERL5LIB' }
546 EOF
547 );
548
549 ok(unlink("t/tmp/ikiwiki.cgi"));
550 ok(! system("./ikiwiki.out --setup t/tmp/test.setup --rebuild --wrappers"));
551
552 # CGI wrapper should be exactly the requested mode
553 (undef, undef, $mode, undef, undef,
554         undef, undef, undef, undef, undef,
555         undef, undef, undef) = stat("t/tmp/ikiwiki.cgi");
556 is($mode & 07777, 0754);
557
558 ok(-e "t/tmp/out/a/b/c/index.html");
559 $content = readfile("t/tmp/out/a/b/c/index.html");
560 # no <base> on static HTML
561 unlike($content, qr{<base\W});
562 # url and cgiurl are on the same host so the cgiurl is host-relative
563 like($content, qr{<a[^>]+href="/cgi-bin/ikiwiki.cgi\?do=prefs"});
564 # cross-links between static pages are relative
565 like($content, qr{<li>A: <a href="../../">a</a></li>});
566 like($content, qr{<li>B: <a href="../">b</a></li>});
567 like($content, qr{<li>E: <a href="../../d/e/">e</a></li>});
568
569 # because we are behind a reverse-proxy we must assume that
570 # we're being accessed by the configured cgiurl
571 run(["./t/tmp/ikiwiki.cgi"], \undef, \$content, init => sub {
572         $ENV{REQUEST_METHOD} = 'GET';
573         $ENV{SERVER_PORT} = '80';
574         $ENV{SCRIPT_NAME} = '/cgi-bin/ikiwiki.cgi';
575         $ENV{QUERY_STRING} = 'do=prefs';
576         $ENV{HTTP_HOST} = 'localhost';
577 });
578 %bits = parse_cgi_content($content);
579 like($bits{tophref}, qr{^(?:/wiki|\.)/$});
580 like($bits{cgihref}, qr{^(?:(?:https:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
581 TODO: {
582 local $TODO = "reverse-proxy support needed";
583 is($bits{basehref}, "https://example.com/wiki/");
584 like($bits{stylehref}, qr{^(?:(?:https:)?//example.com)?/wiki/style.css$});
585 }
586
587 # previewing a page
588 $in = 'do=edit&page=a/b/c&Preview';
589 run(["./t/tmp/ikiwiki.cgi"], \$in, \$content, init => sub {
590         $ENV{REQUEST_METHOD} = 'POST';
591         $ENV{SERVER_PORT} = '80';
592         $ENV{SCRIPT_NAME} = '/cgi-bin/ikiwiki.cgi';
593         $ENV{HTTP_HOST} = 'localhost';
594         $ENV{CONTENT_LENGTH} = length $in;
595 });
596 %bits = parse_cgi_content($content);
597 like($bits{tophref}, qr{^(?:/wiki|\.\./\.\./\.\.)/$});
598 like($bits{cgihref}, qr{^(?:(?:https:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
599 TODO: {
600 local $TODO = "reverse-proxy support needed";
601 is($bits{basehref}, "https://example.com/wiki/a/b/c/");
602 like($bits{stylehref}, qr{^(?:(?:https:)?//example.com)?/wiki/style.css$});
603 }
604
605 done_testing;