6 plan(skip_all => "IPC::Run not available")
17 my $PERL5LIB = 'blib/lib:blib/arch';
20 # Black-box (ish) test for relative linking between CGI and static content
23 my ($content, $in, %bits);
25 sub parse_cgi_content {
27 if ($content =~ qr{<base href="([^"]+)" */>}) {
30 if ($content =~ qr{href="([^"]+/style.css)"}) {
31 $bits{stylehref} = $1;
33 if ($content =~ qr{class="parentlinks">\s+<a href="([^"]+)">this is the name of my wiki</a>/}s) {
36 if ($content =~ qr{<a[^>]+href="([^"]+)\?do=prefs"}) {
42 ok(! system("make -s ikiwiki.out"));
43 ok(! system("rm -rf t/tmp"));
44 ok(! system("mkdir t/tmp"));
50 writefile($name, "t/tmp/in", $content);
51 ok(utime(333333333, 333333333, "t/tmp/in/$name"));
54 write_old_file("a.mdwn", "A");
55 write_old_file("a/b.mdwn", "B");
56 write_old_file("a/b/c.mdwn",
60 write_old_file("a/d.mdwn", "D");
61 write_old_file("a/d/e.mdwn", "E");
63 #######################################################################
64 # site 1: a perfectly ordinary ikiwiki
66 writefile("test.setup", "t/tmp", <<EOF
67 # IkiWiki::Setup::Yaml - YAML formatted setup file
68 wikiname: this is the name of my wiki
71 templatedir: templates
72 url: "http://example.com/wiki/"
73 cgiurl: "http://example.com/cgi-bin/ikiwiki.cgi"
74 cgi_wrapper: t/tmp/ikiwiki.cgi
77 # make it easier to test previewing
81 ENV: { 'PERL5LIB': '$PERL5LIB' }
85 ok(unlink("t/tmp/ikiwiki.cgi") || $!{ENOENT});
86 ok(! system("./ikiwiki.out --setup t/tmp/test.setup --rebuild --wrappers"));
88 # CGI wrapper should be exactly the requested mode
89 my (undef, undef, $mode, undef, undef,
90 undef, undef, undef, undef, undef,
91 undef, undef, undef) = stat("t/tmp/ikiwiki.cgi");
92 is($mode & 07777, 0754);
94 ok(-e "t/tmp/out/a/b/c/index.html");
95 $content = readfile("t/tmp/out/a/b/c/index.html");
96 # no <base> on static HTML
97 unlike($content, qr{<base\W});
98 # url and cgiurl are on the same host so the cgiurl is host-relative
99 like($content, qr{<a[^>]+href="/cgi-bin/ikiwiki.cgi\?do=prefs"});
100 # cross-links between static pages are relative
101 like($content, qr{<li>A: <a href="../../">a</a></li>});
102 like($content, qr{<li>B: <a href="../">b</a></li>});
103 like($content, qr{<li>E: <a href="../../d/e/">e</a></li>});
105 run(["./t/tmp/ikiwiki.cgi"], \undef, \$content, init => sub {
106 $ENV{REQUEST_METHOD} = 'GET';
107 $ENV{SERVER_PORT} = '80';
108 $ENV{SCRIPT_NAME} = '/cgi-bin/ikiwiki.cgi';
109 $ENV{QUERY_STRING} = 'do=prefs';
110 $ENV{HTTP_HOST} = 'example.com';
112 %bits = parse_cgi_content($content);
113 is($bits{basehref}, "http://example.com/wiki/");
114 like($bits{stylehref}, qr{^(?:(?:http:)?//example.com)?/wiki/style.css$});
115 like($bits{tophref}, qr{^(?:/wiki|\.)/$});
116 like($bits{cgihref}, qr{^(?:(?:http:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
118 # when accessed via HTTPS, links are secure
119 run(["./t/tmp/ikiwiki.cgi"], \undef, \$content, init => sub {
120 $ENV{REQUEST_METHOD} = 'GET';
121 $ENV{SERVER_PORT} = '443';
122 $ENV{SCRIPT_NAME} = '/cgi-bin/ikiwiki.cgi';
123 $ENV{QUERY_STRING} = 'do=prefs';
124 $ENV{HTTP_HOST} = 'example.com';
127 %bits = parse_cgi_content($content);
128 is($bits{basehref}, "https://example.com/wiki/");
129 like($bits{stylehref}, qr{^(?:(?:https:)?//example.com)?/wiki/style.css$});
130 like($bits{tophref}, qr{^(?:/wiki|\.)/$});
131 like($bits{cgihref}, qr{^(?:(?:https:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
133 # when accessed via a different hostname, links stay on that host
134 run(["./t/tmp/ikiwiki.cgi"], \undef, \$content, init => sub {
135 $ENV{REQUEST_METHOD} = 'GET';
136 $ENV{SERVER_PORT} = '80';
137 $ENV{SCRIPT_NAME} = '/cgi-bin/ikiwiki.cgi';
138 $ENV{QUERY_STRING} = 'do=prefs';
139 $ENV{HTTP_HOST} = 'staging.example.net';
141 %bits = parse_cgi_content($content);
142 is($bits{basehref}, "http://staging.example.net/wiki/");
143 like($bits{stylehref}, qr{^(?:(?:http:)?//staging.example.net)?/wiki/style.css$});
144 like($bits{tophref}, qr{^(?:/wiki|\.)/$});
145 like($bits{cgihref}, qr{^(?:(?:http:)?//staging.example.net)?/cgi-bin/ikiwiki.cgi$});
148 $in = 'do=edit&page=a/b/c&Preview';
149 run(["./t/tmp/ikiwiki.cgi"], \$in, \$content, init => sub {
150 $ENV{REQUEST_METHOD} = 'POST';
151 $ENV{SERVER_PORT} = '80';
152 $ENV{SCRIPT_NAME} = '/cgi-bin/ikiwiki.cgi';
153 $ENV{HTTP_HOST} = 'example.com';
154 $ENV{CONTENT_LENGTH} = length $in;
156 %bits = parse_cgi_content($content);
157 is($bits{basehref}, "http://example.com/wiki/a/b/c/");
158 like($bits{stylehref}, qr{^(?:(?:http:)?//example.com)?/wiki/style.css$});
159 like($bits{tophref}, qr{^(?:/wiki|\.\./\.\./\.\.)/$});
160 like($bits{cgihref}, qr{^(?:(?:http:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
162 # in html5, the <base> is allowed to be relative, and we take full
164 writefile("test.setup", "t/tmp", <<EOF
165 # IkiWiki::Setup::Yaml - YAML formatted setup file
166 wikiname: this is the name of my wiki
169 templatedir: templates
170 url: "http://example.com/wiki/"
171 cgiurl: "http://example.com/cgi-bin/ikiwiki.cgi"
172 cgi_wrapper: t/tmp/ikiwiki.cgi
173 cgi_wrappermode: 0754
175 # make it easier to test previewing
179 ENV: { 'PERL5LIB': '$PERL5LIB' }
183 ok(unlink("t/tmp/ikiwiki.cgi") || $!{ENOENT});
184 ok(! system("./ikiwiki.out --setup t/tmp/test.setup --rebuild --wrappers"));
186 # CGI wrapper should be exactly the requested mode
187 (undef, undef, $mode, undef, undef,
188 undef, undef, undef, undef, undef,
189 undef, undef, undef) = stat("t/tmp/ikiwiki.cgi");
190 is($mode & 07777, 0754);
192 ok(-e "t/tmp/out/a/b/c/index.html");
193 $content = readfile("t/tmp/out/a/b/c/index.html");
194 # no <base> on static HTML
195 unlike($content, qr{<base\W});
196 # url and cgiurl are on the same host so the cgiurl is host-relative
197 like($content, qr{<a[^>]+href="/cgi-bin/ikiwiki.cgi\?do=prefs"});
198 # cross-links between static pages are relative
199 like($content, qr{<li>A: <a href="../../">a</a></li>});
200 like($content, qr{<li>B: <a href="../">b</a></li>});
201 like($content, qr{<li>E: <a href="../../d/e/">e</a></li>});
203 run(["./t/tmp/ikiwiki.cgi"], \undef, \$content, init => sub {
204 $ENV{REQUEST_METHOD} = 'GET';
205 $ENV{SERVER_PORT} = '80';
206 $ENV{SCRIPT_NAME} = '/cgi-bin/ikiwiki.cgi';
207 $ENV{QUERY_STRING} = 'do=prefs';
208 $ENV{HTTP_HOST} = 'example.com';
210 %bits = parse_cgi_content($content);
211 is($bits{basehref}, "/wiki/");
212 is($bits{stylehref}, "/wiki/style.css");
213 is($bits{tophref}, "/wiki/");
214 is($bits{cgihref}, "/cgi-bin/ikiwiki.cgi");
216 # when accessed via HTTPS, links are secure - this is easy because under
217 # html5 they're independent of the URL at which the CGI was accessed
218 run(["./t/tmp/ikiwiki.cgi"], \undef, \$content, init => sub {
219 $ENV{REQUEST_METHOD} = 'GET';
220 $ENV{SERVER_PORT} = '443';
221 $ENV{SCRIPT_NAME} = '/cgi-bin/ikiwiki.cgi';
222 $ENV{QUERY_STRING} = 'do=prefs';
223 $ENV{HTTP_HOST} = 'example.com';
226 %bits = parse_cgi_content($content);
227 is($bits{basehref}, "/wiki/");
228 is($bits{stylehref}, "/wiki/style.css");
229 is($bits{tophref}, "/wiki/");
230 is($bits{cgihref}, "/cgi-bin/ikiwiki.cgi");
232 # when accessed via a different hostname, links stay on that host -
233 # this is really easy in html5 because we can use relative URLs
234 run(["./t/tmp/ikiwiki.cgi"], \undef, \$content, init => sub {
235 $ENV{REQUEST_METHOD} = 'GET';
236 $ENV{SERVER_PORT} = '80';
237 $ENV{SCRIPT_NAME} = '/cgi-bin/ikiwiki.cgi';
238 $ENV{QUERY_STRING} = 'do=prefs';
239 $ENV{HTTP_HOST} = 'staging.example.net';
241 %bits = parse_cgi_content($content);
242 is($bits{basehref}, "/wiki/");
243 is($bits{stylehref}, "/wiki/style.css");
244 is($bits{tophref}, "/wiki/");
245 is($bits{cgihref}, "/cgi-bin/ikiwiki.cgi");
248 $in = 'do=edit&page=a/b/c&Preview';
249 run(["./t/tmp/ikiwiki.cgi"], \$in, \$content, init => sub {
250 $ENV{REQUEST_METHOD} = 'POST';
251 $ENV{SERVER_PORT} = '80';
252 $ENV{SCRIPT_NAME} = '/cgi-bin/ikiwiki.cgi';
253 $ENV{HTTP_HOST} = 'example.com';
254 $ENV{CONTENT_LENGTH} = length $in;
256 %bits = parse_cgi_content($content);
257 is($bits{basehref}, "/wiki/a/b/c/");
258 is($bits{stylehref}, "/wiki/style.css");
259 like($bits{tophref}, qr{^(?:/wiki|\.\./\.\./\.\.)/$});
260 is($bits{cgihref}, "/cgi-bin/ikiwiki.cgi");
262 #######################################################################
263 # site 2: static content and CGI are on different servers
265 writefile("test.setup", "t/tmp", <<EOF
266 # IkiWiki::Setup::Yaml - YAML formatted setup file
267 wikiname: this is the name of my wiki
270 templatedir: templates
271 url: "http://static.example.com/"
272 cgiurl: "http://cgi.example.com/ikiwiki.cgi"
273 cgi_wrapper: t/tmp/ikiwiki.cgi
274 cgi_wrappermode: 0754
276 # make it easier to test previewing
280 ENV: { 'PERL5LIB': '$PERL5LIB' }
284 ok(unlink("t/tmp/ikiwiki.cgi"));
285 ok(! system("./ikiwiki.out --setup t/tmp/test.setup --rebuild --wrappers"));
287 # CGI wrapper should be exactly the requested mode
288 (undef, undef, $mode, undef, undef,
289 undef, undef, undef, undef, undef,
290 undef, undef, undef) = stat("t/tmp/ikiwiki.cgi");
291 is($mode & 07777, 0754);
293 ok(-e "t/tmp/out/a/b/c/index.html");
294 $content = readfile("t/tmp/out/a/b/c/index.html");
295 # no <base> on static HTML
296 unlike($content, qr{<base\W});
297 # url and cgiurl are not on the same host so the cgiurl has to be
298 # protocol-relative or absolute
299 like($content, qr{<a[^>]+href="(?:http:)?//cgi.example.com/ikiwiki.cgi\?do=prefs"});
300 # cross-links between static pages are still relative
301 like($content, qr{<li>A: <a href="../../">a</a></li>});
302 like($content, qr{<li>B: <a href="../">b</a></li>});
303 like($content, qr{<li>E: <a href="../../d/e/">e</a></li>});
305 run(["./t/tmp/ikiwiki.cgi"], \undef, \$content, init => sub {
306 $ENV{REQUEST_METHOD} = 'GET';
307 $ENV{SERVER_PORT} = '80';
308 $ENV{SCRIPT_NAME} = '/ikiwiki.cgi';
309 $ENV{QUERY_STRING} = 'do=prefs';
310 $ENV{HTTP_HOST} = 'cgi.example.com';
312 %bits = parse_cgi_content($content);
313 like($bits{basehref}, qr{^http://static.example.com/$});
314 like($bits{stylehref}, qr{^(?:(?:http:)?//static.example.com)?/style.css$});
315 like($bits{tophref}, qr{^(?:http:)?//static.example.com/$});
316 like($bits{cgihref}, qr{^(?:(?:http:)?//cgi.example.com)?/ikiwiki.cgi$});
318 # when accessed via HTTPS, links are secure
319 run(["./t/tmp/ikiwiki.cgi"], \undef, \$content, init => sub {
320 $ENV{REQUEST_METHOD} = 'GET';
321 $ENV{SERVER_PORT} = '443';
322 $ENV{SCRIPT_NAME} = '/ikiwiki.cgi';
323 $ENV{QUERY_STRING} = 'do=prefs';
324 $ENV{HTTP_HOST} = 'cgi.example.com';
327 %bits = parse_cgi_content($content);
328 like($bits{basehref}, qr{^https://static.example.com/$});
329 like($bits{stylehref}, qr{^(?:(?:https:)?//static.example.com)?/style.css$});
330 like($bits{tophref}, qr{^(?:https:)?//static.example.com/$});
331 like($bits{cgihref}, qr{^(?:(?:https:)?//cgi.example.com)?/ikiwiki.cgi$});
333 # when accessed via a different hostname, links to the CGI (only) should
335 $in = 'do=edit&page=a/b/c&Preview';
336 run(["./t/tmp/ikiwiki.cgi"], \$in, \$content, init => sub {
337 $ENV{REQUEST_METHOD} = 'POST';
338 $ENV{SERVER_PORT} = '80';
339 $ENV{SCRIPT_NAME} = '/ikiwiki.cgi';
340 $ENV{HTTP_HOST} = 'staging.example.net';
341 $ENV{CONTENT_LENGTH} = length $in;
343 %bits = parse_cgi_content($content);
344 like($bits{basehref}, qr{^http://static.example.com/a/b/c/$});
345 like($bits{stylehref}, qr{^(?:(?:http:)?//static.example.com|\.\./\.\./\.\.)/style.css$});
346 like($bits{tophref}, qr{^(?:(?:http:)?//static.example.com|\.\./\.\./\.\.)/$});
347 like($bits{cgihref}, qr{^(?:(?:http:)?//(?:staging\.example\.net|cgi\.example\.com))?/ikiwiki.cgi$});
349 local $TODO = "use self-referential CGI URL?";
350 like($bits{cgihref}, qr{^(?:(?:http:)?//staging.example.net)?/ikiwiki.cgi$});
353 writefile("test.setup", "t/tmp", <<EOF
354 # IkiWiki::Setup::Yaml - YAML formatted setup file
355 wikiname: this is the name of my wiki
358 templatedir: templates
359 url: "http://static.example.com/"
360 cgiurl: "http://cgi.example.com/ikiwiki.cgi"
361 cgi_wrapper: t/tmp/ikiwiki.cgi
362 cgi_wrappermode: 0754
364 # make it easier to test previewing
368 ENV: { 'PERL5LIB': '$PERL5LIB' }
372 ok(unlink("t/tmp/ikiwiki.cgi"));
373 ok(! system("./ikiwiki.out --setup t/tmp/test.setup --rebuild --wrappers"));
375 # CGI wrapper should be exactly the requested mode
376 (undef, undef, $mode, undef, undef,
377 undef, undef, undef, undef, undef,
378 undef, undef, undef) = stat("t/tmp/ikiwiki.cgi");
379 is($mode & 07777, 0754);
381 ok(-e "t/tmp/out/a/b/c/index.html");
382 $content = readfile("t/tmp/out/a/b/c/index.html");
383 # no <base> on static HTML
384 unlike($content, qr{<base\W});
385 # url and cgiurl are not on the same host so the cgiurl has to be
386 # protocol-relative or absolute
387 like($content, qr{<a[^>]+href="(?:http:)?//cgi.example.com/ikiwiki.cgi\?do=prefs"});
388 # cross-links between static pages are still relative
389 like($content, qr{<li>A: <a href="../../">a</a></li>});
390 like($content, qr{<li>B: <a href="../">b</a></li>});
391 like($content, qr{<li>E: <a href="../../d/e/">e</a></li>});
393 run(["./t/tmp/ikiwiki.cgi"], \undef, \$content, init => sub {
394 $ENV{REQUEST_METHOD} = 'GET';
395 $ENV{SERVER_PORT} = '80';
396 $ENV{SCRIPT_NAME} = '/ikiwiki.cgi';
397 $ENV{QUERY_STRING} = 'do=prefs';
398 $ENV{HTTP_HOST} = 'cgi.example.com';
400 %bits = parse_cgi_content($content);
401 is($bits{basehref}, "//static.example.com/");
402 is($bits{stylehref}, "//static.example.com/style.css");
403 is($bits{tophref}, "//static.example.com/");
404 is($bits{cgihref}, "//cgi.example.com/ikiwiki.cgi");
406 # when accessed via HTTPS, links are secure - in fact they're exactly the
407 # same as when accessed via HTTP
408 run(["./t/tmp/ikiwiki.cgi"], \undef, \$content, init => sub {
409 $ENV{REQUEST_METHOD} = 'GET';
410 $ENV{SERVER_PORT} = '443';
411 $ENV{SCRIPT_NAME} = '/ikiwiki.cgi';
412 $ENV{QUERY_STRING} = 'do=prefs';
413 $ENV{HTTP_HOST} = 'cgi.example.com';
416 %bits = parse_cgi_content($content);
417 is($bits{basehref}, "//static.example.com/");
418 is($bits{stylehref}, "//static.example.com/style.css");
419 is($bits{tophref}, "//static.example.com/");
420 is($bits{cgihref}, "//cgi.example.com/ikiwiki.cgi");
422 # when accessed via a different hostname, links to the CGI (only) should
424 $in = 'do=edit&page=a/b/c&Preview';
425 run(["./t/tmp/ikiwiki.cgi"], \$in, \$content, init => sub {
426 $ENV{REQUEST_METHOD} = 'POST';
427 $ENV{SERVER_PORT} = '80';
428 $ENV{SCRIPT_NAME} = '/ikiwiki.cgi';
429 $ENV{HTTP_HOST} = 'staging.example.net';
430 $ENV{CONTENT_LENGTH} = length $in;
432 %bits = parse_cgi_content($content);
433 is($bits{basehref}, "//static.example.com/a/b/c/");
434 is($bits{stylehref}, "//static.example.com/style.css");
435 is($bits{tophref}, "../../../");
436 like($bits{cgihref}, qr{//(?:staging\.example\.net|cgi\.example\.com)/ikiwiki\.cgi});
438 local $TODO = "use self-referential CGI URL maybe?";
439 is($bits{cgihref}, "//staging.example.net/ikiwiki.cgi");
442 #######################################################################
443 # site 3: we specifically want everything to be secure
445 writefile("test.setup", "t/tmp", <<EOF
446 # IkiWiki::Setup::Yaml - YAML formatted setup file
447 wikiname: this is the name of my wiki
450 templatedir: templates
451 url: "https://example.com/wiki/"
452 cgiurl: "https://example.com/cgi-bin/ikiwiki.cgi"
453 cgi_wrapper: t/tmp/ikiwiki.cgi
454 cgi_wrappermode: 0754
456 # make it easier to test previewing
460 ENV: { 'PERL5LIB': '$PERL5LIB' }
464 ok(unlink("t/tmp/ikiwiki.cgi"));
465 ok(! system("./ikiwiki.out --setup t/tmp/test.setup --rebuild --wrappers"));
467 # CGI wrapper should be exactly the requested mode
468 (undef, undef, $mode, undef, undef,
469 undef, undef, undef, undef, undef,
470 undef, undef, undef) = stat("t/tmp/ikiwiki.cgi");
471 is($mode & 07777, 0754);
473 ok(-e "t/tmp/out/a/b/c/index.html");
474 $content = readfile("t/tmp/out/a/b/c/index.html");
475 # no <base> on static HTML
476 unlike($content, qr{<base\W});
477 # url and cgiurl are on the same host so the cgiurl is host-relative
478 like($content, qr{<a[^>]+href="/cgi-bin/ikiwiki.cgi\?do=prefs"});
479 # cross-links between static pages are relative
480 like($content, qr{<li>A: <a href="../../">a</a></li>});
481 like($content, qr{<li>B: <a href="../">b</a></li>});
482 like($content, qr{<li>E: <a href="../../d/e/">e</a></li>});
484 # when accessed via HTTPS, links are secure
485 run(["./t/tmp/ikiwiki.cgi"], \undef, \$content, init => sub {
486 $ENV{REQUEST_METHOD} = 'GET';
487 $ENV{SERVER_PORT} = '443';
488 $ENV{SCRIPT_NAME} = '/cgi-bin/ikiwiki.cgi';
489 $ENV{QUERY_STRING} = 'do=prefs';
490 $ENV{HTTP_HOST} = 'example.com';
493 %bits = parse_cgi_content($content);
494 is($bits{basehref}, "https://example.com/wiki/");
495 like($bits{stylehref}, qr{^(?:(?:https:)?//example.com)?/wiki/style.css$});
496 like($bits{tophref}, qr{^(?:/wiki|\.)/$});
497 like($bits{cgihref}, qr{^(?:(?:https:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
499 # when not accessed via HTTPS, links should still be secure
500 # (but if this happens, that's a sign of web server misconfiguration)
501 run(["./t/tmp/ikiwiki.cgi"], \undef, \$content, init => sub {
502 $ENV{REQUEST_METHOD} = 'GET';
503 $ENV{SERVER_PORT} = '80';
504 $ENV{SCRIPT_NAME} = '/cgi-bin/ikiwiki.cgi';
505 $ENV{QUERY_STRING} = 'do=prefs';
506 $ENV{HTTP_HOST} = 'example.com';
508 %bits = parse_cgi_content($content);
509 like($bits{tophref}, qr{^(?:/wiki|\.)/$});
511 local $TODO = "treat https in configured url, cgiurl as required?";
512 is($bits{basehref}, "https://example.com/wiki/");
513 like($bits{stylehref}, qr{^(?:(?:https:)?//example.com)?/wiki/style.css$});
515 like($bits{cgihref}, qr{^(?:(?:https:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
517 # when accessed via a different hostname, links stay on that host
518 run(["./t/tmp/ikiwiki.cgi"], \undef, \$content, init => sub {
519 $ENV{REQUEST_METHOD} = 'GET';
520 $ENV{SERVER_PORT} = '443';
521 $ENV{SCRIPT_NAME} = '/cgi-bin/ikiwiki.cgi';
522 $ENV{QUERY_STRING} = 'do=prefs';
523 $ENV{HTTP_HOST} = 'staging.example.net';
526 %bits = parse_cgi_content($content);
527 is($bits{basehref}, "https://staging.example.net/wiki/");
528 like($bits{stylehref}, qr{^(?:(?:https:)?//staging.example.net)?/wiki/style.css$});
529 like($bits{tophref}, qr{^(?:/wiki|\.)/$});
530 like($bits{cgihref}, qr{^(?:(?:https:)?//staging.example.net)?/cgi-bin/ikiwiki.cgi$});
533 $in = 'do=edit&page=a/b/c&Preview';
534 run(["./t/tmp/ikiwiki.cgi"], \$in, \$content, init => sub {
535 $ENV{REQUEST_METHOD} = 'POST';
536 $ENV{SERVER_PORT} = '443';
537 $ENV{SCRIPT_NAME} = '/cgi-bin/ikiwiki.cgi';
538 $ENV{HTTP_HOST} = 'example.com';
539 $ENV{CONTENT_LENGTH} = length $in;
542 %bits = parse_cgi_content($content);
543 is($bits{basehref}, "https://example.com/wiki/a/b/c/");
544 like($bits{stylehref}, qr{^(?:(?:https:)?//example.com)?/wiki/style.css$});
545 like($bits{tophref}, qr{^(?:/wiki|\.\./\.\./\.\.)/$});
546 like($bits{cgihref}, qr{^(?:(?:https:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
548 # not testing html5: 0 here because that ends up identical to site 1
550 #######################################################################
551 # site 4 (NetBSD wiki): CGI is secure, static content doesn't have to be
553 writefile("test.setup", "t/tmp", <<EOF
554 # IkiWiki::Setup::Yaml - YAML formatted setup file
555 wikiname: this is the name of my wiki
558 templatedir: templates
559 url: "http://example.com/wiki/"
560 cgiurl: "https://example.com/cgi-bin/ikiwiki.cgi"
561 cgi_wrapper: t/tmp/ikiwiki.cgi
562 cgi_wrappermode: 0754
564 # make it easier to test previewing
568 ENV: { 'PERL5LIB': '$PERL5LIB' }
572 ok(unlink("t/tmp/ikiwiki.cgi"));
573 ok(! system("./ikiwiki.out --setup t/tmp/test.setup --rebuild --wrappers"));
575 # CGI wrapper should be exactly the requested mode
576 (undef, undef, $mode, undef, undef,
577 undef, undef, undef, undef, undef,
578 undef, undef, undef) = stat("t/tmp/ikiwiki.cgi");
579 is($mode & 07777, 0754);
581 ok(-e "t/tmp/out/a/b/c/index.html");
582 $content = readfile("t/tmp/out/a/b/c/index.html");
583 # no <base> on static HTML
584 unlike($content, qr{<base\W});
585 # url and cgiurl are on the same host but different schemes
586 like($content, qr{<a[^>]+href="https://example.com/cgi-bin/ikiwiki.cgi\?do=prefs"});
587 # cross-links between static pages are relative
588 like($content, qr{<li>A: <a href="../../">a</a></li>});
589 like($content, qr{<li>B: <a href="../">b</a></li>});
590 like($content, qr{<li>E: <a href="../../d/e/">e</a></li>});
592 # when accessed via HTTPS, links are secure (to avoid mixed-content)
593 run(["./t/tmp/ikiwiki.cgi"], \undef, \$content, init => sub {
594 $ENV{REQUEST_METHOD} = 'GET';
595 $ENV{SERVER_PORT} = '443';
596 $ENV{SCRIPT_NAME} = '/cgi-bin/ikiwiki.cgi';
597 $ENV{QUERY_STRING} = 'do=prefs';
598 $ENV{HTTP_HOST} = 'example.com';
601 %bits = parse_cgi_content($content);
602 is($bits{basehref}, "https://example.com/wiki/");
603 like($bits{stylehref}, qr{^(?:(?:https:)?//example.com)?/wiki/style.css$});
604 like($bits{tophref}, qr{^(?:/wiki|\.)/$});
605 like($bits{cgihref}, qr{^(?:(?:https:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
607 # when not accessed via HTTPS, ???
608 run(["./t/tmp/ikiwiki.cgi"], \undef, \$content, init => sub {
609 $ENV{REQUEST_METHOD} = 'GET';
610 $ENV{SERVER_PORT} = '80';
611 $ENV{SCRIPT_NAME} = '/cgi-bin/ikiwiki.cgi';
612 $ENV{QUERY_STRING} = 'do=prefs';
613 $ENV{HTTP_HOST} = 'example.com';
615 %bits = parse_cgi_content($content);
616 like($bits{basehref}, qr{^https?://example.com/wiki/$});
617 like($bits{stylehref}, qr{^(?:(?:https?:)?//example.com)?/wiki/style.css$});
618 like($bits{tophref}, qr{^(?:(?:https?://example.com)?/wiki|\.)/$});
619 like($bits{cgihref}, qr{^(?:(?:https:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
621 # when accessed via a different hostname, links stay on that host
622 run(["./t/tmp/ikiwiki.cgi"], \undef, \$content, init => sub {
623 $ENV{REQUEST_METHOD} = 'GET';
624 $ENV{SERVER_PORT} = '443';
625 $ENV{SCRIPT_NAME} = '/cgi-bin/ikiwiki.cgi';
626 $ENV{QUERY_STRING} = 'do=prefs';
627 $ENV{HTTP_HOST} = 'staging.example.net';
630 %bits = parse_cgi_content($content);
631 # because the static and dynamic stuff is on the same server, we assume that
632 # both are also on the staging server
633 like($bits{basehref}, qr{^https://staging.example.net/wiki/$});
634 like($bits{stylehref}, qr{^(?:(?:https:)?//staging.example.net)?/wiki/style.css$});
635 like($bits{tophref}, qr{^(?:(?:(?:https:)?//staging.example.net)?/wiki|\.)/$});
636 like($bits{cgihref}, qr{^(?:(?:https:)?//(?:staging\.example\.net|example\.com))?/cgi-bin/ikiwiki.cgi$});
638 local $TODO = "this should really point back to itself but currently points to example.com";
639 like($bits{cgihref}, qr{^(?:(?:https:)?//staging.example.net)?/cgi-bin/ikiwiki.cgi$});
643 $in = 'do=edit&page=a/b/c&Preview';
644 run(["./t/tmp/ikiwiki.cgi"], \$in, \$content, init => sub {
645 $ENV{REQUEST_METHOD} = 'POST';
646 $ENV{SERVER_PORT} = '443';
647 $ENV{SCRIPT_NAME} = '/cgi-bin/ikiwiki.cgi';
648 $ENV{HTTP_HOST} = 'example.com';
649 $ENV{CONTENT_LENGTH} = length $in;
652 %bits = parse_cgi_content($content);
653 is($bits{basehref}, "https://example.com/wiki/a/b/c/");
654 like($bits{stylehref}, qr{^(?:(?:https:)?//example.com)?/wiki/style.css$});
655 like($bits{tophref}, qr{^(?:/wiki|\.\./\.\./\.\.)/$});
656 like($bits{cgihref}, qr{^(?:(?:https:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
658 writefile("test.setup", "t/tmp", <<EOF
659 # IkiWiki::Setup::Yaml - YAML formatted setup file
660 wikiname: this is the name of my wiki
663 templatedir: templates
664 url: "http://example.com/wiki/"
665 cgiurl: "https://example.com/cgi-bin/ikiwiki.cgi"
666 cgi_wrapper: t/tmp/ikiwiki.cgi
667 cgi_wrappermode: 0754
669 # make it easier to test previewing
673 ENV: { 'PERL5LIB': '$PERL5LIB' }
677 ok(unlink("t/tmp/ikiwiki.cgi"));
678 ok(! system("./ikiwiki.out --setup t/tmp/test.setup --rebuild --wrappers"));
680 # CGI wrapper should be exactly the requested mode
681 (undef, undef, $mode, undef, undef,
682 undef, undef, undef, undef, undef,
683 undef, undef, undef) = stat("t/tmp/ikiwiki.cgi");
684 is($mode & 07777, 0754);
686 ok(-e "t/tmp/out/a/b/c/index.html");
687 $content = readfile("t/tmp/out/a/b/c/index.html");
688 # no <base> on static HTML
689 unlike($content, qr{<base\W});
690 # url and cgiurl are on the same host but different schemes
691 like($content, qr{<a[^>]+href="https://example.com/cgi-bin/ikiwiki.cgi\?do=prefs"});
692 # cross-links between static pages are relative
693 like($content, qr{<li>A: <a href="../../">a</a></li>});
694 like($content, qr{<li>B: <a href="../">b</a></li>});
695 like($content, qr{<li>E: <a href="../../d/e/">e</a></li>});
697 # when accessed via HTTPS, links are secure (to avoid mixed-content)
698 run(["./t/tmp/ikiwiki.cgi"], \undef, \$content, init => sub {
699 $ENV{REQUEST_METHOD} = 'GET';
700 $ENV{SERVER_PORT} = '443';
701 $ENV{SCRIPT_NAME} = '/cgi-bin/ikiwiki.cgi';
702 $ENV{QUERY_STRING} = 'do=prefs';
703 $ENV{HTTP_HOST} = 'example.com';
706 %bits = parse_cgi_content($content);
707 is($bits{basehref}, "/wiki/");
708 is($bits{stylehref}, "/wiki/style.css");
709 is($bits{tophref}, "/wiki/");
710 like($bits{cgihref}, qr{^(?:(?:https:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
712 # when not accessed via HTTPS, ???
713 run(["./t/tmp/ikiwiki.cgi"], \undef, \$content, init => sub {
714 $ENV{REQUEST_METHOD} = 'GET';
715 $ENV{SERVER_PORT} = '80';
716 $ENV{SCRIPT_NAME} = '/cgi-bin/ikiwiki.cgi';
717 $ENV{QUERY_STRING} = 'do=prefs';
718 $ENV{HTTP_HOST} = 'example.com';
720 %bits = parse_cgi_content($content);
721 like($bits{basehref}, qr{^(?:https?://example.com)?/wiki/$});
722 like($bits{stylehref}, qr{^(?:(?:https?:)?//example.com)?/wiki/style.css$});
723 like($bits{tophref}, qr{^(?:(?:https?://example.com)?/wiki|\.)/$});
724 like($bits{cgihref}, qr{^(?:(?:https:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
726 # when accessed via a different hostname, links stay on that host
727 run(["./t/tmp/ikiwiki.cgi"], \undef, \$content, init => sub {
728 $ENV{REQUEST_METHOD} = 'GET';
729 $ENV{SERVER_PORT} = '443';
730 $ENV{SCRIPT_NAME} = '/cgi-bin/ikiwiki.cgi';
731 $ENV{QUERY_STRING} = 'do=prefs';
732 $ENV{HTTP_HOST} = 'staging.example.net';
735 %bits = parse_cgi_content($content);
736 # because the static and dynamic stuff is on the same server, we assume that
737 # both are also on the staging server
738 is($bits{basehref}, "/wiki/");
739 is($bits{stylehref}, "/wiki/style.css");
740 like($bits{tophref}, qr{^(?:/wiki|\.)/$});
741 like($bits{cgihref}, qr{^(?:(?:https:)?//(?:example\.com|staging\.example\.net))?/cgi-bin/ikiwiki.cgi$});
743 local $TODO = "this should really point back to itself but currently points to example.com";
744 like($bits{cgihref}, qr{^(?:(?:https:)?//staging.example.net)?/cgi-bin/ikiwiki.cgi$});
748 $in = 'do=edit&page=a/b/c&Preview';
749 run(["./t/tmp/ikiwiki.cgi"], \$in, \$content, init => sub {
750 $ENV{REQUEST_METHOD} = 'POST';
751 $ENV{SERVER_PORT} = '443';
752 $ENV{SCRIPT_NAME} = '/cgi-bin/ikiwiki.cgi';
753 $ENV{HTTP_HOST} = 'example.com';
754 $ENV{CONTENT_LENGTH} = length $in;
757 %bits = parse_cgi_content($content);
758 is($bits{basehref}, "/wiki/a/b/c/");
759 is($bits{stylehref}, "/wiki/style.css");
760 like($bits{tophref}, qr{^(?:/wiki|\.\./\.\./\.\.)/$});
761 like($bits{cgihref}, qr{^(?:(?:https:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
763 # Deliberately not testing https static content with http cgiurl,
764 # because that makes remarkably little sense.
766 #######################################################################
767 # site 5: w3mmode, as documented in [[w3mmode]]
769 writefile("test.setup", "t/tmp", <<EOF
770 # IkiWiki::Setup::Yaml - YAML formatted setup file
771 wikiname: this is the name of my wiki
774 templatedir: templates
777 cgi_wrapper: t/tmp/ikiwiki.cgi
778 cgi_wrappermode: 0754
783 ENV: { 'PERL5LIB': '$PERL5LIB' }
787 ok(unlink("t/tmp/ikiwiki.cgi"));
788 ok(! system("./ikiwiki.out --setup t/tmp/test.setup --rebuild --wrappers"));
790 # CGI wrapper should be exactly the requested mode
791 (undef, undef, $mode, undef, undef,
792 undef, undef, undef, undef, undef,
793 undef, undef, undef) = stat("t/tmp/ikiwiki.cgi");
794 is($mode & 07777, 0754);
796 ok(-e "t/tmp/out/a/b/c/index.html");
797 $content = readfile("t/tmp/out/a/b/c/index.html");
798 # no <base> on static HTML
799 unlike($content, qr{<base\W});
800 # FIXME: does /$LIB/ikiwiki-w3m.cgi work under w3m?
801 like($content, qr{<a[^>]+href="(?:file://)?/\$LIB/ikiwiki-w3m.cgi/ikiwiki.cgi\?do=prefs"});
802 # cross-links between static pages are still relative
803 like($content, qr{<li>A: <a href="../../">a</a></li>});
804 like($content, qr{<li>B: <a href="../">b</a></li>});
805 like($content, qr{<li>E: <a href="../../d/e/">e</a></li>});
807 run(["./t/tmp/ikiwiki.cgi"], \undef, \$content, init => sub {
808 $ENV{REQUEST_METHOD} = 'GET';
809 $ENV{PATH_INFO} = '/ikiwiki.cgi';
810 $ENV{SCRIPT_NAME} = '/cgi-bin/ikiwiki-w3m.cgi';
811 $ENV{QUERY_STRING} = 'do=prefs';
813 %bits = parse_cgi_content($content);
814 like($bits{tophref}, qr{^(?:\Q$pwd\E/t/tmp/out|\.)/$});
815 like($bits{cgihref}, qr{^(?:file://)?/\$LIB/ikiwiki-w3m.cgi/ikiwiki.cgi$});
816 like($bits{basehref}, qr{^(?:(?:file:)?//)?\Q$pwd\E/t/tmp/out/$});
817 like($bits{stylehref}, qr{^(?:(?:(?:file:)?//)?\Q$pwd\E/t/tmp/out|\.)/style.css$});
819 writefile("test.setup", "t/tmp", <<EOF
820 # IkiWiki::Setup::Yaml - YAML formatted setup file
821 wikiname: this is the name of my wiki
824 templatedir: templates
827 cgi_wrapper: t/tmp/ikiwiki.cgi
828 cgi_wrappermode: 0754
833 ENV: { 'PERL5LIB': '$PERL5LIB' }
837 ok(unlink("t/tmp/ikiwiki.cgi"));
838 ok(! system("./ikiwiki.out --setup t/tmp/test.setup --rebuild --wrappers"));
840 # CGI wrapper should be exactly the requested mode
841 (undef, undef, $mode, undef, undef,
842 undef, undef, undef, undef, undef,
843 undef, undef, undef) = stat("t/tmp/ikiwiki.cgi");
844 is($mode & 07777, 0754);
846 ok(-e "t/tmp/out/a/b/c/index.html");
847 $content = readfile("t/tmp/out/a/b/c/index.html");
848 # no <base> on static HTML
849 unlike($content, qr{<base\W});
850 # FIXME: does /$LIB/ikiwiki-w3m.cgi work under w3m?
851 like($content, qr{<a[^>]+href="(?:file://)?/\$LIB/ikiwiki-w3m.cgi/ikiwiki.cgi\?do=prefs"});
852 # cross-links between static pages are still relative
853 like($content, qr{<li>A: <a href="../../">a</a></li>});
854 like($content, qr{<li>B: <a href="../">b</a></li>});
855 like($content, qr{<li>E: <a href="../../d/e/">e</a></li>});
857 run(["./t/tmp/ikiwiki.cgi"], \undef, \$content, init => sub {
858 $ENV{REQUEST_METHOD} = 'GET';
859 $ENV{PATH_INFO} = '/ikiwiki.cgi';
860 $ENV{SCRIPT_NAME} = '/cgi-bin/ikiwiki-w3m.cgi';
861 $ENV{QUERY_STRING} = 'do=prefs';
863 %bits = parse_cgi_content($content);
864 like($bits{tophref}, qr{^(?:\Q$pwd\E/t/tmp/out|\.)/$});
865 like($bits{cgihref}, qr{^(?:file://)?/\$LIB/ikiwiki-w3m.cgi/ikiwiki.cgi$});
866 like($bits{basehref}, qr{^(?:(?:file:)?//)?\Q$pwd\E/t/tmp/out/$});
867 like($bits{stylehref}, qr{^(?:(?:(?:file:)?//)?\Q$pwd\E/t/tmp/out|\.)/style.css$});
869 #######################################################################
870 # site 6: we're behind a reverse-proxy
872 writefile("test.setup", "t/tmp", <<EOF
873 # IkiWiki::Setup::Yaml - YAML formatted setup file
874 wikiname: this is the name of my wiki
877 templatedir: templates
878 url: "https://example.com/wiki/"
879 cgiurl: "https://example.com/cgi-bin/ikiwiki.cgi"
880 cgi_wrapper: t/tmp/ikiwiki.cgi
881 cgi_wrappermode: 0754
883 # make it easier to test previewing
888 ENV: { 'PERL5LIB': '$PERL5LIB' }
892 ok(unlink("t/tmp/ikiwiki.cgi"));
893 ok(! system("./ikiwiki.out --setup t/tmp/test.setup --rebuild --wrappers"));
895 # CGI wrapper should be exactly the requested mode
896 (undef, undef, $mode, undef, undef,
897 undef, undef, undef, undef, undef,
898 undef, undef, undef) = stat("t/tmp/ikiwiki.cgi");
899 is($mode & 07777, 0754);
901 ok(-e "t/tmp/out/a/b/c/index.html");
902 $content = readfile("t/tmp/out/a/b/c/index.html");
903 # no <base> on static HTML
904 unlike($content, qr{<base\W});
905 # url and cgiurl are on the same host so the cgiurl is host-relative
906 like($content, qr{<a[^>]+href="/cgi-bin/ikiwiki.cgi\?do=prefs"});
907 # cross-links between static pages are relative
908 like($content, qr{<li>A: <a href="../../">a</a></li>});
909 like($content, qr{<li>B: <a href="../">b</a></li>});
910 like($content, qr{<li>E: <a href="../../d/e/">e</a></li>});
912 # because we are behind a reverse-proxy we must assume that
913 # we're being accessed by the configured cgiurl
914 run(["./t/tmp/ikiwiki.cgi"], \undef, \$content, init => sub {
915 $ENV{REQUEST_METHOD} = 'GET';
916 $ENV{SERVER_PORT} = '80';
917 $ENV{SCRIPT_NAME} = '/cgi-bin/ikiwiki.cgi';
918 $ENV{QUERY_STRING} = 'do=prefs';
919 $ENV{HTTP_HOST} = 'localhost';
921 %bits = parse_cgi_content($content);
922 like($bits{tophref}, qr{^(?:/wiki|\.)/$});
923 like($bits{cgihref}, qr{^(?:(?:https:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
924 is($bits{basehref}, "https://example.com/wiki/");
925 like($bits{stylehref}, qr{^(?:(?:https:)?//example.com)?/wiki/style.css$});
928 $in = 'do=edit&page=a/b/c&Preview';
929 run(["./t/tmp/ikiwiki.cgi"], \$in, \$content, init => sub {
930 $ENV{REQUEST_METHOD} = 'POST';
931 $ENV{SERVER_PORT} = '80';
932 $ENV{SCRIPT_NAME} = '/cgi-bin/ikiwiki.cgi';
933 $ENV{HTTP_HOST} = 'localhost';
934 $ENV{CONTENT_LENGTH} = length $in;
936 %bits = parse_cgi_content($content);
937 like($bits{tophref}, qr{^(?:/wiki|\.\./\.\./\.\.)/$});
938 like($bits{cgihref}, qr{^(?:(?:https:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
939 is($bits{basehref}, "https://example.com/wiki/a/b/c/");
940 like($bits{stylehref}, qr{^(?:(?:https:)?//example.com)?/wiki/style.css$});
942 # not testing html5: 1 because it would be the same as site 1 -
943 # the reverse_proxy config option is unnecessary under html5