Merge remote branch 'smcv/ready/sslcookie-auto'
authorJoey Hess <joey@kitenet.net>
Mon, 29 Nov 2010 20:31:25 +0000 (16:31 -0400)
committerJoey Hess <joey@kitenet.net>
Mon, 29 Nov 2010 20:31:25 +0000 (16:31 -0400)
38 files changed:
IkiWiki.pm
IkiWiki/CGI.pm
IkiWiki/Plugin/comments.pm
IkiWiki/Plugin/editpage.pm
IkiWiki/Plugin/git.pm
IkiWiki/Plugin/goto.pm
IkiWiki/Plugin/img.pm
IkiWiki/Plugin/inline.pm
IkiWiki/Plugin/openid.pm
IkiWiki/Plugin/parentlinks.pm
IkiWiki/Plugin/pinger.pm
IkiWiki/Plugin/poll.pm
IkiWiki/Plugin/recentchanges.pm
IkiWiki/Plugin/relativedate.pm
IkiWiki/Plugin/remove.pm
IkiWiki/Plugin/rename.pm
IkiWiki/Plugin/search.pm
IkiWiki/Plugin/toggle.pm
IkiWiki/Plugin/websetup.pm
IkiWiki/Plugin/wmd.pm
debian/changelog
doc/bugs/__34__Currently_enabled_SSH_keys:__34___shows_only_first_139_characters_of_each_key.mdwn [new file with mode: 0644]
doc/bugs/git_commit_adds_files_that_were_not_tracked.mdwn [new file with mode: 0644]
doc/bugs/rename_fixup_not_attributed_to_author.mdwn [new file with mode: 0644]
doc/forum/Need_something_more_powerful_than_Exclude/comment_2_f577ab6beb9912471949d8d18c790267._comment [new file with mode: 0644]
doc/news/version_3.20100915.mdwn [deleted file]
doc/news/version_3.20101129.mdwn [new file with mode: 0644]
doc/plugins/autoindex/discussion.mdwn
doc/plugins/write.mdwn
doc/todo/auto-create_tag_pages_according_to_a_template.mdwn
doc/todo/autoindex_should_use_add__95__autofile.mdwn
doc/todo/transient_pages.mdwn [moved from doc/todo/transient_in-memory_pages.mdwn with 100% similarity]
doc/todo/use_secure_cookies_for_ssl_logins.mdwn [new file with mode: 0644]
doc/todo/want_to_avoid_ikiwiki_using_http_or_https_in_urls_to_allow_serving_both.mdwn
doc/users/Remy.mdwn [new file with mode: 0644]
ikiwiki.spec
po/ikiwiki.pot
t/urlto.t [new file with mode: 0755]

index f57ef8c6c89d169cf8523d5f588b939f62d8d540..97946bfcf888a185a193cf5d4ef2f2c353cdb058 100644 (file)
@@ -501,6 +501,12 @@ sub defaultconfig () {
        return @ret;
 }
 
+# URL to top of wiki as a path starting with /, valid from any wiki page or
+# the CGI; if that's not possible, an absolute URL. Either way, it ends with /
+my $local_url;
+# URL to CGI script, similar to $local_url
+my $local_cgiurl;
+
 sub checkconfig () {
        # locale stuff; avoid LC_ALL since it overrides everything
        if (defined $ENV{LC_ALL}) {
@@ -537,7 +543,33 @@ sub checkconfig () {
        if ($config{cgi} && ! length $config{url}) {
                error(gettext("Must specify url to wiki with --url when using --cgi"));
        }
-       
+
+       if (length $config{url}) {
+               eval q{use URI};
+               my $baseurl = URI->new($config{url});
+
+               $local_url = $baseurl->path . "/";
+               $local_cgiurl = undef;
+
+               if (length $config{cgiurl}) {
+                       my $cgiurl = URI->new($config{cgiurl});
+
+                       $local_cgiurl = $cgiurl->path;
+
+                       if ($cgiurl->scheme ne $baseurl->scheme or
+                               $cgiurl->authority ne $baseurl->authority) {
+                               # too far apart, fall back to absolute URLs
+                               $local_url = "$config{url}/";
+                               $local_cgiurl = $config{cgiurl};
+                       }
+               }
+
+               $local_url =~ s{//$}{/};
+       }
+       else {
+               $local_cgiurl = $config{cgiurl};
+       }
+
        $config{wikistatedir}="$config{srcdir}/.ikiwiki"
                unless exists $config{wikistatedir} && defined $config{wikistatedir};
 
@@ -1010,11 +1042,17 @@ sub linkpage ($) {
 sub cgiurl (@) {
        my %params=@_;
 
-       my $cgiurl=$config{cgiurl};
+       my $cgiurl=$local_cgiurl;
+
        if (exists $params{cgiurl}) {
                $cgiurl=$params{cgiurl};
                delete $params{cgiurl};
        }
+
+       unless (%params) {
+               return $cgiurl;
+       }
+
        return $cgiurl."?".
                join("&amp;", map $_."=".uri_escape_utf8($params{$_}), keys %params);
 }
@@ -1022,7 +1060,7 @@ sub cgiurl (@) {
 sub baseurl (;$) {
        my $page=shift;
 
-       return "$config{url}/" if ! defined $page;
+       return $local_url if ! defined $page;
        
        $page=htmlpage($page);
        $page=~s/[^\/]+$//;
@@ -1096,7 +1134,7 @@ sub beautify_urlpath ($) {
        return $url;
 }
 
-sub urlto ($$;$) {
+sub urlto ($;$$) {
        my $to=shift;
        my $from=shift;
        my $absolute=shift;
@@ -1113,6 +1151,12 @@ sub urlto ($$;$) {
                return $config{url}.beautify_urlpath("/".$to);
        }
 
+       if (! defined $from) {
+               my $u = $local_url;
+               $u =~ s{/$}{};
+               return $u.beautify_urlpath("/".$to);
+       }
+
        my $link = abs2rel($to, dirname(htmlpage($from)));
 
        return beautify_urlpath($link);
@@ -1201,7 +1245,7 @@ sub userpage ($) {
 sub openiduser ($) {
        my $user=shift;
 
-       if ($user =~ m!^https?://! &&
+       if (defined $user && $user =~ m!^https?://! &&
            eval q{use Net::OpenID::VerifiedIdentity; 1} && !$@) {
                my $display;
 
index 14193c33ae8a82fd2f69ad38ae176a33647cddfa..ede194ff9aee945dc0fb471bedaa47bf93eda829 100644 (file)
@@ -116,7 +116,7 @@ sub cgi_signin ($$;$) {
                required => 'NONE',
                javascript => 0,
                params => $q,
-               action => $config{cgiurl},
+               action => cgiurl(),
                header => 0,
                template => {type => 'div'},
                stylesheet => 1,
@@ -198,7 +198,7 @@ sub cgi_prefs ($$) {
                required => 'NONE',
                javascript => 0,
                params => $q,
-               action => $config{cgiurl},
+               action => cgiurl(),
                template => {type => 'div'},
                stylesheet => 1,
                fieldsets => [
@@ -231,11 +231,11 @@ sub cgi_prefs ($$) {
        
        if ($form->submitted eq 'Logout') {
                $session->delete();
-               redirect($q, $config{url});
+               redirect($q, baseurl(undef));
                return;
        }
        elsif ($form->submitted eq 'Cancel') {
-               redirect($q, $config{url});
+               redirect($q, baseurl(undef));
                return;
        }
        elsif ($form->submitted eq 'Save Preferences' && $form->validate) {
index a39dab36cdb81e6c06049d9c0bc312a6e58b1dd2..68ac4cfae4844dd7de3b44e7af9956d00ab3ac75 100644 (file)
@@ -237,7 +237,7 @@ sub preprocess {
        }
 
        if ($params{page} =~ m/\/\Q$config{comments_pagename}\E\d+_/) {
-               $pagestate{$page}{meta}{permalink} = urlto(IkiWiki::dirname($params{page}), undef, 1).
+               $pagestate{$page}{meta}{permalink} = urlto(IkiWiki::dirname($params{page})).
                        "#".page_to_id($params{page});
        }
 
@@ -301,7 +301,7 @@ sub editcomment ($$) {
                required => [qw{editcontent}],
                javascript => 0,
                params => $cgi,
-               action => $config{cgiurl},
+               action => IkiWiki::cgiurl(),
                header => 0,
                table => 0,
                template => { template('editcomment.tmpl') },
@@ -372,7 +372,7 @@ sub editcomment ($$) {
                error(gettext("bad page name"));
        }
 
-       my $baseurl = urlto($page, undef, 1);
+       my $baseurl = urlto($page);
 
        $form->title(sprintf(gettext("commenting on %s"),
                        IkiWiki::pagetitle($page)));
@@ -385,8 +385,7 @@ sub editcomment ($$) {
 
        if ($form->submitted eq CANCEL) {
                # bounce back to the page they wanted to comment on, and exit.
-               # CANCEL need not be considered in future
-               IkiWiki::redirect($cgi, urlto($page, undef, 1));
+               IkiWiki::redirect($cgi, $baseurl);
                exit;
        }
 
@@ -552,7 +551,7 @@ sub editcomment ($$) {
                # Jump to the new comment on the page.
                # The trailing question mark tries to avoid broken
                # caches and get the most recent version of the page.
-               IkiWiki::redirect($cgi, urlto($page, undef, 1).
+               IkiWiki::redirect($cgi, urlto($page).
                        "?updated#".page_to_id($location));
 
        }
@@ -656,6 +655,7 @@ sub commentmoderation ($$) {
        $template->param(
                sid => $session->id,
                comments => \@comments,
+               cgiurl => IkiWiki::cgiurl(),
        );
        IkiWiki::printheader($session);
        my $out=$template->output;
@@ -810,14 +810,14 @@ sub pagetemplate (@) {
        if ($shown) {
                if ($template->query(name => 'commentsurl')) {
                        $template->param(commentsurl =>
-                               urlto($page, undef, 1).'#comments');
+                               urlto($page).'#comments');
                }
 
                if ($template->query(name => 'atomcommentsurl') && $config{usedirs}) {
                        # This will 404 until there are some comments, but I
                        # think that's probably OK...
                        $template->param(atomcommentsurl =>
-                               urlto($page, undef, 1).'comments.atom');
+                               urlto($page).'comments.atom');
                }
 
                if ($template->query(name => 'commentslink')) {
index 1a04a72b5568f2980d8a7e00d0eaaa06a62e0e0d..da071d4920fe0e5fcafde8f20419925522278d31 100644 (file)
@@ -75,7 +75,7 @@ sub cgi_editpage ($$) {
                required => [qw{editcontent}],
                javascript => 0,
                params => $q,
-               action => $config{cgiurl},
+               action => IkiWiki::cgiurl(),
                header => 0,
                table => 0,
                template => { template("editpage.tmpl") },
@@ -98,7 +98,7 @@ sub cgi_editpage ($$) {
                error(gettext("bad page name"));
        }
 
-       my $baseurl = urlto($page, undef, 1);
+       my $baseurl = urlto($page);
 
        my $from;
        if (defined $form->field('from')) {
@@ -156,13 +156,13 @@ sub cgi_editpage ($$) {
        my $previewing=0;
        if ($form->submitted eq "Cancel") {
                if ($form->field("do") eq "create" && defined $from) {
-                       redirect($q, urlto($from, undef, 1));
+                       redirect($q, urlto($from));
                }
                elsif ($form->field("do") eq "create") {
-                       redirect($q, $config{url});
+                       redirect($q, baseurl(undef));
                }
                else {
-                       redirect($q, urlto($page, undef, 1));
+                       redirect($q, $baseurl);
                }
                exit;
        }
@@ -262,7 +262,7 @@ sub cgi_editpage ($$) {
                                        @page_locs=$page;
                                }
                                else {
-                                       redirect($q, urlto($page, undef, 1));
+                                       redirect($q, $baseurl);
                                        exit;
                                }
                        }
@@ -434,7 +434,7 @@ sub cgi_editpage ($$) {
                else {
                        # The trailing question mark tries to avoid broken
                        # caches and get the most recent version of the page.
-                       redirect($q, urlto($page, undef, 1)."?updated");
+                       redirect($q, $baseurl."?updated");
                }
        }
 
index 3fa29b22f78b6f47ea27b2f79950782b9ef03223..3db4af7291b0d11dcdf8bc89386b93133c963e10 100644 (file)
@@ -496,16 +496,16 @@ sub rcs_commit (@) {
                return $conflict if defined $conflict;
        }
 
-       rcs_add($params{file});
-       return rcs_commit_staged(
-               message => $params{message},
-               session => $params{session},
-       );
+       return rcs_commit_helper(@_);
 }
 
 sub rcs_commit_staged (@) {
        # Commits all staged changes. Changes can be staged using rcs_add,
        # rcs_remove, and rcs_rename.
+       return rcs_commit_helper(@_);
+}
+
+sub rcs_commit_helper (@) {
        my %params=@_;
        
        my %env=%ENV;
@@ -546,10 +546,12 @@ sub rcs_commit_staged (@) {
                        $params{message}.=".";
                }
        }
-       push @opts, '-q';
-       # git commit returns non-zero if file has not been really changed.
-       # so we should ignore its exit status (hence run_or_non).
-       if (run_or_non('git', 'commit', @opts, '-m', $params{message})) {
+       if (exists $params{file}) {
+               push @opts, '--', $params{file};
+       }
+       # git commit returns non-zero if nothing really changed.
+       # So we should ignore its exit status (hence run_or_non).
+       if (run_or_non('git', 'commit', '-m', $params{message}, '-q', @opts)) {
                if (length $config{gitorigin_branch}) {
                        run_or_cry('git', 'push', $config{gitorigin_branch});
                }
@@ -797,7 +799,7 @@ sub git_parse_changes {
                                eval q{use File::Temp};
                                die $@ if $@;
                                my $fh;
-                               ($fh, $path)=File::Temp::tempfile("XXXXXXXXXX", UNLINK => 1);
+                               ($fh, $path)=File::Temp::tempfile(undef, UNLINK => 1);
                                my $cmd = "cd $git_dir && ".
                                          "git show $detail->{sha1_to} > '$path'";
                                if (system($cmd) != 0) {
index 348a663efdd936d5004e0735ad41e4c393568c3e..0eb83fc208de611d05a016ff8fc63c2c6913f1c8 100644 (file)
@@ -64,7 +64,7 @@ sub cgi_goto ($;$) {
                )
        }
        else {
-               IkiWiki::redirect($q, urlto($link, undef, 1));
+               IkiWiki::redirect($q, urlto($link));
        }
 
        exit;
index bd527c8c82c79eb5a8ef1a2ae6aa694f0279121d..103f6b2b3510067f10a5eddf86f8e657ba96fe29 100644 (file)
@@ -152,8 +152,8 @@ sub preprocess (@) {
                $imgurl=urlto($imglink, $params{destpage});
        }
        else {
-               $fileurl="$config{url}/$file";
-               $imgurl="$config{url}/$imglink";
+               $fileurl=urlto($file);
+               $imgurl=urlto($imglink);
        }
 
        if (! exists $params{class}) {
index 1fe40a5eab4235f82c46cbd0499032c84103e091..76527156406159e381164835b4c1dc3015cb346f 100644 (file)
@@ -300,7 +300,7 @@ sub preprocess_inline (@) {
            IkiWiki->can("cgi_editpage")) {
                # Add a blog post form, with feed buttons.
                my $formtemplate=template_depends("blogpost.tmpl", $params{page}, blind_cache => 1);
-               $formtemplate->param(cgiurl => $config{cgiurl});
+               $formtemplate->param(cgiurl => IkiWiki::cgiurl());
                $formtemplate->param(rootpage => rootpage(%params));
                $formtemplate->param(rssurl => $rssurl) if $feeds && $rss;
                $formtemplate->param(atomurl => $atomurl) if $feeds && $atom;
index fae9fb77f8388a9e750b1d8e7dfdcee700f76a92..0220a3cf67e7e78adf83c52ca4dbe09a312fa3cd 100644 (file)
@@ -77,7 +77,7 @@ sub openid_selector {
 
        my $template=IkiWiki::template("openid-selector.tmpl");
        $template->param(
-               cgiurl => $config{cgiurl},
+               cgiurl => IkiWiki::cgiurl(),
                (defined $openid_error ? (openid_error => $openid_error) : ()),
                (defined $openid_url ? (openid_url => $openid_url) : ()),
                ($real_cgi_signin ? (nonopenidform => $real_cgi_signin->($q, $session, 1)) : ()),
@@ -148,7 +148,7 @@ sub validate ($$$;$) {
        }
 
        my $cgiurl=$config{openid_cgiurl};
-       $cgiurl=$config{cgiurl} if ! defined $cgiurl;
+       $cgiurl=IkiWiki::cgiurl() if ! defined $cgiurl;
 
        my $trust_root=$config{openid_realm};
        $trust_root=$cgiurl if ! defined $trust_root;
@@ -175,7 +175,7 @@ sub auth ($$) {
                        IkiWiki::redirect($q, $setup_url);
                }
                elsif ($csr->user_cancel) {
-                       IkiWiki::redirect($q, $config{url});
+                       IkiWiki::redirect($q, IkiWiki::baseurl(undef));
                }
                elsif (my $vident = $csr->verified_identity) {
                        $session->param(name => $vident->url);
@@ -249,7 +249,7 @@ sub getobj ($$) {
        }
        
        my $cgiurl=$config{openid_cgiurl};
-       $cgiurl=$config{cgiurl} if ! defined $cgiurl;
+       $cgiurl=IkiWiki::cgiurl() if ! defined $cgiurl;
 
        return Net::OpenID::Consumer->new(
                ua => $ua,
index bbd2c5752f58ac4aa94dc932ac4345a5226266a7..203ea13b649e288fe4935d2743469721c15eb1e1 100644 (file)
@@ -27,7 +27,7 @@ sub parentlinks ($) {
        if (! length $page) {
                # dynamic page
                return {
-                       url => $config{url},
+                       url => IkiWiki::baseurl(undef),
                        page => $config{wikiname},
                };
        }
index cc9f52d2b50e7e880882ff56b89d8bafba5c274d..932619496c3d3c7634cb1a550a920dae106140a2 100644 (file)
@@ -106,6 +106,8 @@ sub ping {
                        # only ping when a page was changed, so a ping loop
                        # will still be avoided.
                        next if $url=~/^\Q$config{cgiurl}\E/;
+                       my $local_cgiurl = IkiWiki::cgiurl();
+                       next if $url=~/^\Q$local_cgiurl\E/;
                        
                        $ua->get($url);
                }
index b333e2cdcff485edd81f4df426e1865c261a1199..2773486a6c69560fdd0a2236607b800dc88b15e6 100644 (file)
@@ -52,7 +52,7 @@ sub preprocess (@) {
        foreach my $choice (@choices) {
                if ($open && exists $config{cgiurl}) {
                        # use POST to avoid robots
-                       $ret.="<form method=\"POST\" action=\"$config{cgiurl}\">\n";
+                       $ret.="<form method=\"POST\" action=\"".IkiWiki::cgiurl()."\">\n";
                }
                my $percent=$total > 0 ? int($choices{$choice} / $total * 100) : 0;
                $ret.="<p>\n";
@@ -103,7 +103,7 @@ sub sessioncgi ($$) {
                my $oldchoice=$session->param($choice_param);
                if (defined $oldchoice && $oldchoice eq $choice) {
                        # Same vote; no-op.
-                       IkiWiki::redirect($cgi, urlto($page, undef, 1));
+                       IkiWiki::redirect($cgi, urlto($page));
                        exit;
                }
 
@@ -153,7 +153,7 @@ sub sessioncgi ($$) {
                error($@) if $@;
                my $cookie = CGI::Cookie->new(-name=> $session->name, -value=> $session->id);
                print $cgi->redirect(-cookie => $cookie,
-                       -url => urlto($page, undef, 1));
+                       -url => urlto($page));
                exit;
        }
 }
index 562f61d40f3cc4729f5da0f01e3d6b2c4a20660d..6fccd16f6df6c72590863626042166abaca5f51c 100644 (file)
@@ -84,7 +84,7 @@ sub sessioncgi ($$) {
                method => 'POST',
                javascript => 0,
                params => $q,
-               action => $config{cgiurl},
+               action => IkiWiki::cgiurl(),
                stylesheet => 1,
                template => { template('revert.tmpl') },
                fields => [qw{revertmessage do sid rev}],
@@ -127,7 +127,7 @@ sub sessioncgi ($$) {
                exit 0;
        }
 
-       IkiWiki::redirect($q, urlto($config{recentchangespage}, ''));
+       IkiWiki::redirect($q, urlto($config{recentchangespage}));
        exit 0;
 }
 
@@ -178,7 +178,7 @@ sub store ($$$) {
                        else {
                                $_->{link} = pagetitle($_->{page});
                        }
-                       $_->{baseurl}="$config{url}/" if length $config{url};
+                       $_->{baseurl}=IkiWiki::baseurl(undef) if length $config{url};
 
                        $_;
                } @{$change->{pages}}
@@ -226,7 +226,7 @@ sub store ($$$) {
                wikiname => $config{wikiname},
        );
        
-       $template->param(permalink => "$config{url}/$config{recentchangespage}/#change-".titlepage($change->{rev}))
+       $template->param(permalink => urlto($config{recentchangespage}, undef)."#change-".titlepage($change->{rev}))
                if exists $config{url};
        
        IkiWiki::run_hooks(pagetemplate => sub {
index 7296889ab28f21c9c642e468d503dc502428ede7..4ae0be8615852db38222ebd892fd5c216bd5b4bf 100644 (file)
@@ -28,18 +28,17 @@ sub format (@) {
 
        if (! ($params{content}=~s!^(<body[^>]*>)!$1.include_javascript($params{page})!em)) {
                # no <body> tag, probably in preview mode
-               $params{content}=include_javascript($params{page}, 1).$params{content};
+               $params{content}=include_javascript(undef).$params{content};
        }
        return $params{content};
 }
 
-sub include_javascript ($;$) {
-       my $page=shift;
-       my $absolute=shift;
+sub include_javascript ($) {
+       my $from=shift;
        
-       return '<script src="'.urlto("ikiwiki/ikiwiki.js", $page, $absolute).
+       return '<script src="'.urlto("ikiwiki/ikiwiki.js", $from).
                '" type="text/javascript" charset="utf-8"></script>'."\n".
-               '<script src="'.urlto("ikiwiki/relativedate.js", $page, $absolute).
+               '<script src="'.urlto("ikiwiki/relativedate.js", $from).
                '" type="text/javascript" charset="utf-8"></script>';
 }
 
index 1717c8cf3759e07724098390387dedf177ddcbaa..bc481502a7dc8ecaa179e781d4a2c4dc3348d7b2 100644 (file)
@@ -100,7 +100,7 @@ sub confirmation_form ($$) {
                method => 'POST',
                javascript => 0,
                params => $q,
-               action => $config{cgiurl},
+               action => IkiWiki::cgiurl(),
                stylesheet => 1,
                fields => [qw{do page}],
        );
@@ -240,7 +240,7 @@ sub sessioncgi ($$) {
                                if (! exists $pagesources{$parent}) {
                                        $parent="index";
                                }
-                               IkiWiki::redirect($q, urlto($parent, '/', 1));
+                               IkiWiki::redirect($q, urlto($parent));
                        }
                }
                else {
index ad5e726458cedbbb63a069297372e3bb739fe486..57747d3c9df00141a1ade61e823c453a2ecbcc33 100644 (file)
@@ -126,7 +126,7 @@ sub rename_form ($$$) {
                method => 'POST',
                javascript => 0,
                params => $q,
-               action => $config{cgiurl},
+               action => IkiWiki::cgiurl(),
                stylesheet => 1,
                fields => [qw{do page new_name attachment}],
        );
@@ -574,11 +574,10 @@ sub fixlinks ($$$) {
                                eval { writefile($file, $config{srcdir}, $content) };
                                next if $@;
                                my $conflict=IkiWiki::rcs_commit(
-                                       $file,
-                                       sprintf(gettext("update for rename of %s to %s"), $rename->{srcfile}, $rename->{destfile}),
-                                       $token,
-                                       $session->param("name"),
-                                       $session->remote_addr(),
+                                       file => $file,
+                                       message => sprintf(gettext("update for rename of %s to %s"), $rename->{srcfile}, $rename->{destfile}),
+                                       token => $token,
+                                       session => $session,
                                );
                                push @fixedlinks, $page if ! defined $conflict;
                        }
index 8fb9dff0ca082bb16b6332c052e848408db162b8..78eb750b5f670caabe5840a51f589319eccf1204 100644 (file)
@@ -58,7 +58,7 @@ sub pagetemplate (@) {
        if ($template->query(name => "searchform")) {
                if (! defined $form) {
                        my $searchform = template("searchform.tmpl", blind_cache => 1);
-                       $searchform->param(searchaction => $config{cgiurl});
+                       $searchform->param(searchaction => IkiWiki::cgiurl());
                        $searchform->param(html5 => $config{html5});
                        $form=$searchform->output;
                }
@@ -176,7 +176,7 @@ sub cgi ($) {
                # only works for GET requests
                chdir("$config{wikistatedir}/xapian") || error("chdir: $!");
                $ENV{OMEGA_CONFIG_FILE}="./omega.conf";
-               $ENV{CGIURL}=$config{cgiurl},
+               $ENV{CGIURL}=IkiWiki::cgiurl();
                IkiWiki::loadindex();
                $ENV{HELPLINK}=htmllink("", "", "ikiwiki/searching",
                        noimageinline => 1, linktext => "Help");
index 1f93f87fe5f714e4b22e195cdc9b780311c14c65..af4d2ba3a858774ac6b77be58479fb2a4a18d69c 100644 (file)
@@ -70,19 +70,18 @@ sub format (@) {
                $params{content}=~s/<div class="toggleableend">//g;
                if (! ($params{content}=~s!^(<body[^>]*>)!$1.include_javascript($params{page})!em)) {
                        # no <body> tag, probably in preview mode
-                       $params{content}=include_javascript($params{page}, 1).$params{content};
+                       $params{content}=include_javascript(undef).$params{content};
                }
        }
        return $params{content};
 }
 
-sub include_javascript ($;$) {
-       my $page=shift;
-       my $absolute=shift;
+sub include_javascript ($) {
+       my $from=shift;
        
-       return '<script src="'.urlto("ikiwiki/ikiwiki.js", $page, $absolute).
+       return '<script src="'.urlto("ikiwiki/ikiwiki.js", $from).
                '" type="text/javascript" charset="utf-8"></script>'."\n".
-               '<script src="'.urlto("ikiwiki/toggle.js", $page, $absolute).
+               '<script src="'.urlto("ikiwiki/toggle.js", $from).
                '" type="text/javascript" charset="utf-8"></script>';
 }
 
index 9c032fdc6780884c86b13bdece90a9f972efc7f1..6a51903016830c17339f2130a964f87708ae15b0 100644 (file)
@@ -288,7 +288,7 @@ sub showform ($$) {
                fieldsets => [
                        [main => gettext("main")], 
                ],
-               action => $config{cgiurl},
+               action => IkiWiki::cgiurl(),
                template => {type => 'div'},
                stylesheet => 1,
        );
@@ -344,7 +344,7 @@ sub showform ($$) {
        IkiWiki::decode_form_utf8($form);
        
        if ($form->submitted eq "Cancel") {
-               IkiWiki::redirect($cgi, $config{url});
+               IkiWiki::redirect($cgi, IkiWiki::baseurl(undef));
                return;
        }
        elsif (($form->submitted eq 'Save Setup' || $form->submitted eq 'Rebuild Wiki') && $form->validate) {
index 71d7c9d17f51e49ec17aee087e984f3e8a7b9b79..134cfb9101b51d48bbabc6a47b7aaba1b73ff699 100644 (file)
@@ -31,14 +31,13 @@ sub formbuilder_setup (@) {
                        $form->field("do") eq "comment";
 
        $form->tmpl_param("wmd_preview", "<div class=\"wmd-preview\"></div>\n".
-               include_javascript(undef, 1));
+               include_javascript(undef));
 }
 
-sub include_javascript ($;$) {
-       my $page=shift;
-       my $absolute=shift;
+sub include_javascript ($) {
+       my $from=shift;
 
-       my $wmdjs=urlto("wmd/wmd.js", $page, $absolute);
+       my $wmdjs=urlto("wmd/wmd.js", $from);
        return <<"EOF"
 <script type="text/javascript">
 wmd_options = {
index d236361d22b540608e9b7bf3b3f4ee26afab8528..ec995a08aaa731d599badc17b720d8bbe59ca4f6 100644 (file)
@@ -1,4 +1,16 @@
-ikiwiki (3.20101113) UNRELEASED; urgency=low
+ikiwiki (3.20101130) UNRELEASED; urgency=low
+
+  * Better support for serving the same site by both http and https.
+    Links generated by the CGI will now remain on https if it was accessed
+    via https.
+    (Thanks, smcv)
+  * API: urlto without a defined second parameter now generates an url
+    that starts with "/" (when possible; eg when the site's url and cgiurl
+    are on the same domain).
+
+ -- Joey Hess <joeyh@debian.org>  Mon, 29 Nov 2010 14:44:13 -0400
+
+ikiwiki (3.20101129) unstable; urgency=low
 
   * websetup: Fix encoding problem when restoring old setup file.
   * more: Add pages parameter to limit where the more is displayed.
@@ -13,8 +25,13 @@ ikiwiki (3.20101113) UNRELEASED; urgency=low
     of the highlight package.
   * edittemplate: Fix crash if using a .tmpl file or other non-page file
     as a template for a new page.
+  * git: Fix temp file location.
+  * rename: Fix to pass named parameters to rcs_commit.
+  * git: Avoid adding files when committing, so as not to implicitly add
+    files like recentchanges files that are not normally checked in,
+    when fixing links after rename.
 
- -- Joey Hess <joeyh@debian.org>  Tue, 16 Nov 2010 14:23:47 -0400
+ -- Joey Hess <joeyh@debian.org>  Mon, 29 Nov 2010 13:59:10 -0400
 
 ikiwiki (3.20101112) unstable; urgency=HIGH
 
diff --git a/doc/bugs/__34__Currently_enabled_SSH_keys:__34___shows_only_first_139_characters_of_each_key.mdwn b/doc/bugs/__34__Currently_enabled_SSH_keys:__34___shows_only_first_139_characters_of_each_key.mdwn
new file mode 100644 (file)
index 0000000..3c3352f
--- /dev/null
@@ -0,0 +1,12 @@
+At least at http://free-thursday.pieni.net/ikiwiki.cgi the "SSH keys" page shows only the first 139 characters of each SSH key. I'm using iceweasel in 1024x768 resolution and there are not scrollbars visible.
+
+Please contact me at timo.lindfors@iki.fi
+
+> I have access to the same wiki, and do not see the problem Timo sees. I see 380 chars of the SSH keys, and do have a scrollbar.
+> Weird. --liw
+
+> Also, that's a Branchable.com site and the bug, if any is
+> in ikiwiki-hosting's plugin, not ikiwiki proper. Moved
+> [here](http://ikiwiki-hosting.branchable.com/bugs/__34__Currently_enabled_SSH_keys:__34___shows_only_first_139_characters_of_each_key/) --[[Joey]] 
+
+[[!tag done]]
diff --git a/doc/bugs/git_commit_adds_files_that_were_not_tracked.mdwn b/doc/bugs/git_commit_adds_files_that_were_not_tracked.mdwn
new file mode 100644 (file)
index 0000000..587650c
--- /dev/null
@@ -0,0 +1,19 @@
+Commit 3650d0265bc501219bc6d5cd4fa91a6b6ecd793a seems to have been caused by
+a bug in ikiwiki. recentchanges/* was added to the git repo incorrectly.
+
+Part of the problem seems to be that git's `rcs_commit` does a git add followed
+by a `rcs_commit_staged`, and so calling `rcs_commit` on files that were
+not checked in before adds them, incorrectly.
+
+I'm unsure yet why the recentchanges files were being committed. Possibly
+because of the link fixup code run when renaming a page. --[[Joey]] 
+
+> See also [[bugs/rename fixup not attributed to author]]. --[[smcv]]
+
+> Ok, there was a call to `rcs_commit` that was still using non-named
+> parameters, which confused it thuroughly, and I think caused
+> 'git add .' to be called. I've fixed that.
+> 
+> I think there is still potential for the problem I described above to
+> occur during a rename or possibly otherwise. Ok.. fixed `rcs_commit`
+> to not add too. [[done]] --[[Joey]] 
diff --git a/doc/bugs/rename_fixup_not_attributed_to_author.mdwn b/doc/bugs/rename_fixup_not_attributed_to_author.mdwn
new file mode 100644 (file)
index 0000000..bcfafac
--- /dev/null
@@ -0,0 +1,12 @@
+When I renamed `todo/transient_in-memory_pages` to [[todo/transient pages]],
+`rename::fixlinks` was meant to blame me for the link-fixing commit, and title it
+`update for rename of %s to %s`. Instead, it blamed Joey for the commit,
+and didn't set a commit message.
+
+(It also committed a pile of recentchanges pages which shouldn't have
+been committed, for which see [[bugs/git_commit_adds_files_that_were_not_tracked]].)
+
+--[[smcv]]
+
+> It was calling `rcs_commit` old-style, and so not passing the session
+> object that is used to get the user's name. [[fixed|done]] --[[Joey]] 
diff --git a/doc/forum/Need_something_more_powerful_than_Exclude/comment_2_f577ab6beb9912471949d8d18c790267._comment b/doc/forum/Need_something_more_powerful_than_Exclude/comment_2_f577ab6beb9912471949d8d18c790267._comment
new file mode 100644 (file)
index 0000000..bd964d5
--- /dev/null
@@ -0,0 +1,11 @@
+[[!comment format=mdwn
+ username="http://kerravonsen.dreamwidth.org/"
+ ip="60.241.8.244"
+ subject="Missed It By That Much"
+ date="2010-11-25T02:55:20Z"
+ content="""
+I discovered that I not only needed to change the regexp, but I also needed to delete .ikiwiki/indexdb because `file_pruned` only gets called for files that aren't in the `%pagesources` hash, and since the file in question was already there because it had been put there before the exclude regex was changed, it wasn't even being checked!
+
+[[KathrynAndersen]]
+
+"""]]
diff --git a/doc/news/version_3.20100915.mdwn b/doc/news/version_3.20100915.mdwn
deleted file mode 100644 (file)
index 90c5cc3..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-ikiwiki 3.20100915 released with [[!toggle text="these changes"]]
-[[!toggleable text="""
-   * needsbuild hook interface changed; the hooks should now return
-     the modified array of things that need built. (Backwards compatibility
-     code keeps plugins using the old interface working.)
-   * Remove PATH overriding code in ikiwiki script that was present to make
-     perl taint checking happy, but taint checking is disabled.
-   * teximg: Use Unicode UTF-8 encoding by default. Closes: #[596067](http://bugs.debian.org/596067)
-     Thanks, Paul Menzel.
-   * po: Make the po\_master\_language use a langpair like "en|English",
-     so it can be configured via the web.
-   * po: Allow enabling via web setup.
-   * po: Auto-upgrade old format settings to new formats when writing
-     setup file.
-   * Pass array of names of files that have been deleted to needsbuild hook
-     as second parameter, to allow for plugins that needs access to this
-     information earlier than the delete hook.
-   * actiontabs: Improve tab padding.
-   * blueview: Fix display of links to translated pages in the page header.
-   * Set isPermaLink="no" for guids in rss feeds.
-   * blogspam: Fix crash when content contained utf-8.
-   * external: Disable RPC::XML's "smart" encoding, which sent ints
-     for strings that contained only a number, fixing a longstanding crash
-     of the rst plugin.
-   * git: When updating from remote, use git pull --prune, to avoid possible
-     errors from conflicting obsolete remote branches.
-   * cutpaste: Fix bug that occured in some cases involving inlines when
-     text was pasted on a page before being cut."""]]
\ No newline at end of file
diff --git a/doc/news/version_3.20101129.mdwn b/doc/news/version_3.20101129.mdwn
new file mode 100644 (file)
index 0000000..366ad6e
--- /dev/null
@@ -0,0 +1,20 @@
+ikiwiki 3.20101129 released with [[!toggle text="these changes"]]
+[[!toggleable text="""
+   * websetup: Fix encoding problem when restoring old setup file.
+   * more: Add pages parameter to limit where the more is displayed.
+     (thanks, dark)
+   * Fix escaping of filenames in historyurl. (Thanks, aj)
+   * inline: Improve RSS url munging to use a proper html parser,
+     and support all elements that HTML::Tagset knows about.
+     (Which doesn't include html5 just yet, but then the old version
+     didn't either.) Bonus: 4 times faster than old regexp method.
+   * Optimise glob() pagespec. (Thanks, Kathryn and smcv)
+   * highlight: Support new format of filetypes.conf used by version 3.2
+     of the highlight package.
+   * edittemplate: Fix crash if using a .tmpl file or other non-page file
+     as a template for a new page.
+   * git: Fix temp file location.
+   * rename: Fix to pass named parameters to rcs\_commit.
+   * git: Avoid adding files when committing, so as not to implicitly add
+     files like recentchanges files that are not normally checked in,
+     when fixing links after rename."""]]
\ No newline at end of file
index 6b13d2342fa62ccc48671f0f30d2479b085dd38f..76d09cd3c32bf8d5804d8454f99d256cc516980b 100644 (file)
@@ -6,7 +6,7 @@ for the html output and not place the markdown files in the wiki source?
 > writing them out, as [[JoeRayhawk]] suggests below? I think
 > add_autofile would be the way to do this.
 > I've added this to [[todo]] as [[todo/autoindex should use add__95__autofile]]
-> and [[todo/transient in-memory pages]]. --[[smcv]]
+> and [[todo/transient_pages]]. --[[smcv]]
 
 The reason being that I have a lot of directories which need to be autoindexed,
 but I would prefer if the index files didn't clutter up my git repository.
index 6b751f0cd639bf042c7fba2c4813cc918f914e31..3cab7588ec99c7a83fa6755fe3870fc93d6fb4d3 100644 (file)
@@ -1,4 +1,4 @@
-Ikiwiki's plugin interface allows all kinds of useful [[plugins]] to be
+lkiwiki's plugin interface allows all kinds of useful [[plugins]] to be
 written to extend ikiwiki in many ways. Despite the length of this page,
 it's not really hard. This page is a complete reference to everything a
 plugin might want to do. There is also a quick [[tutorial]].
@@ -982,14 +982,19 @@ This is the standard gettext function, although slightly optimised.
 
 This is the standard ngettext function, although slightly optimised.
 
-### `urlto($$;$)`
+### `urlto($;$$)`
 
 Construct a relative url to the first parameter from the page named by the
 second. The first parameter can be either a page name, or some other
 destination file, as registered by `will_render`.
 
-If the third parameter is passed and is true, an absolute url will be
-constructed instead of the default relative url.
+If the second parameter is not specified (or `undef`), the URL will be
+valid from any page on the wiki, or from the CGI; if possible it'll
+be a path starting with `/`, but an absolute URL will be used if
+the wiki and the CGI are on different domains.
+
+If the third parameter is passed and is true, the url will be a fully
+absolute url. This is useful when generating an url to publish elsewhere.
 
 ### `newpagefile($$)`
 
index e065c4a3d6646cd4ede0ec96e93bd32d8f4f3a55..16dc78fb2a64ffcfb42a34399b0b85b0e1b1d3f8 100644 (file)
@@ -260,8 +260,8 @@ required to implement [[todo/alias directive]], which couldn't be easily done
 by writing to the RCS as the page's contents can change depending on which
 other pages claim it as an alias. --[[chrysn]]
 
-I agree with [[chrysn]]. In fact, is there any good reason that the core tag plugin doesn't do this? The current usability is horrible, to the point that I have gone 2.5 years with Ikiwiki and haven't yet started using tags. -- [[Eric|http://wiki.pdxhub.org/people/eric]]
+I agree with [[chrysn]]. In fact, is there any good reason that the core tag plugin doesn't do this? The current usability is horrible, to the point that I have gone 2.5 years with Ikiwiki and haven't yet started using tags. -- 
 
-> See [[todo/transient in-memory pages]] for progress on this. --[[smcv]]
+> See [[todo/transient_pages]] for progress on this. --[[smcv]]
 
 [[!tag done]]
index 64f81c82e3970ea09784097d39be481fd61d16b0..19c5004f889559f9a9c0277314362a2d19518f1e 100644 (file)
@@ -1,4 +1,4 @@
 `add_autofile` is a generic version of [[plugins/autoindex]]'s code,
 so the latter should probably use the former. --[[smcv]]
 
-> See [[todo/transient in-memory pages]] for progress on this. --[[smcv]]
+> See [[todo/transient_pages]] for progress on this. --[[smcv]]
diff --git a/doc/todo/use_secure_cookies_for_ssl_logins.mdwn b/doc/todo/use_secure_cookies_for_ssl_logins.mdwn
new file mode 100644 (file)
index 0000000..f72b2d2
--- /dev/null
@@ -0,0 +1,34 @@
+[[!template id=gitbranch branch=smcv/ready/sslcookie-auto author="[[smcv]]"]]
+[[!tag patch]]
+
+At the moment `sslcookie => 0` never creates secure cookies, so if you log in
+with SSL, your browser will send the session cookie even over plain HTTP.
+Meanwhile `sslcookie => 1` always creates secure cookies, so you can't
+usefully log in over plain http.
+
+This branch adds `sslcookie => 0, sslcookie_auto => 1` as an option; this
+uses the `HTTPS` environment variable, so if you log in over SSL you'll
+get a secure session cookie, but if you log in over HTTP, you won't.
+(The syntax for the setup file is pretty rubbish - any other suggestions?)
+
+> Does this need to be a configurable option at all? The behavior could
+> just be changed in the sslcookie = 0 case. It seems sorta reasonable
+> that, once I've logged in via https, I need to re-login if I then
+> switch to http.
+
+>> Even better. I've amended the branch to have this behaviour, which
+>> turns it into a one-line patch. --[[smcv]]
+
+> And, if your change is made, the sslcookie option could probably itself
+> be dropped too -- at least I don't see a real use case for it if ikiwiki
+> is more paranoid about cookies by default.
+
+>> I haven't done that; it might make sense to do so, but I think it'd be
+>> better to leave it in as a safety-catch (or in case someone's
+>> using a webserver that doesn't put `$HTTPS` in the environment). --s
+
+> Might be best to fix
+> [[todo/want_to_avoid_ikiwiki_using_http_or_https_in_urls_to_allow_serving_both]]
+> first, so that dual https/http sites can better be set up. --[[Joey]]
+
+>> Thanks for merging that! :-) --s
index 8b0501041379278330dbdb52c3232dc26fef5d2c..f7938b0615cc68174c393c0c07e3a4fc774f67f4 100644 (file)
@@ -147,7 +147,7 @@ you don't like my approach:
 
 ----
 
-[[!template id=gitbranch branch=smcv/localurl author="[[smcv]]"]]
+[[!template id=gitbranch branch=smcv/ready/localurl author="[[smcv]]"]]
 [[!tag patch]]
 
 OK, here's an alternative approach, closer in spirit to what was initially
@@ -171,10 +171,10 @@ support that.
 fully relative nor fully absolute, and there doesn't seem to be a good name
 for them...
 
-I tested an earlier version on a demo website with the CGI enabled, and it seemed to
+I've tested this on a demo website with the CGI enabled, and it seemed to
 work nicely (there might be bugs in some plugins, I didn't try all of them).
-I haven't yet re-tested with my updated branch, which is why it's not `ready/`
-yet.
+The branch at [[todo/use secure cookies for SSL logins]] goes well with
+this one.
 
 The `$config{url}` and `$config{cgiurl}` are both HTTP, but if I enable
 `httpauth`, set `cgiauthurl` to a HTTPS version of the same site and log
@@ -319,3 +319,5 @@ Potential future things:
   >> core code (IkiWiki, CGI, Render and the pseudo-core part of editpage)
   >> and 5 in plugins, since I used it for things like redirection back
   >> to the top of the wiki --[[smcv]]
+
+[[merged|done]] --[[Joey]] 
diff --git a/doc/users/Remy.mdwn b/doc/users/Remy.mdwn
new file mode 100644 (file)
index 0000000..5cde4c4
--- /dev/null
@@ -0,0 +1 @@
+Test page
index 5ef43903dd336b4c21c502f2f47b26dc26bb3a4d..b0826d64e969fdcc612633c4f00fc6e4754326ba 100644 (file)
@@ -1,5 +1,5 @@
 Name:           ikiwiki
-Version: 3.20101112
+Version: 3.20101129
 Release:        1%{?dist}
 Summary:        A wiki compiler
 
index e4274d0f666933efd56d4fffd8e26cb1c129f484..492222b86f3ea3d1803fb72660d6e7a2d58d70dd 100644 (file)
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2010-11-12 00:37-0400\n"
+"POT-Creation-Date: 2010-11-29 14:01-0400\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -129,7 +129,7 @@ msgstr ""
 msgid "creating new page %s"
 msgstr ""
 
-#: ../IkiWiki/Plugin/aggregate.pm:652 ../IkiWiki/Plugin/edittemplate.pm:133
+#: ../IkiWiki/Plugin/aggregate.pm:652 ../IkiWiki/Plugin/edittemplate.pm:135
 msgid "failed to process template:"
 msgstr ""
 
@@ -359,26 +359,26 @@ msgstr ""
 msgid "%s is an attachment, not a page."
 msgstr ""
 
-#: ../IkiWiki/Plugin/git.pm:764 ../IkiWiki/Plugin/git.pm:827
+#: ../IkiWiki/Plugin/git.pm:766 ../IkiWiki/Plugin/git.pm:829
 #: ../IkiWiki.pm:1580
 #, perl-format
 msgid "you are not allowed to change %s"
 msgstr ""
 
-#: ../IkiWiki/Plugin/git.pm:786
+#: ../IkiWiki/Plugin/git.pm:788
 #, perl-format
 msgid "you cannot act on a file with mode %s"
 msgstr ""
 
-#: ../IkiWiki/Plugin/git.pm:790
+#: ../IkiWiki/Plugin/git.pm:792
 msgid "you are not allowed to change file modes"
 msgstr ""
 
-#: ../IkiWiki/Plugin/git.pm:861
+#: ../IkiWiki/Plugin/git.pm:863
 msgid "you are not allowed to revert a merge"
 msgstr ""
 
-#: ../IkiWiki/Plugin/git.pm:877
+#: ../IkiWiki/Plugin/git.pm:879
 #, perl-format
 msgid "Failed to revert commit %s"
 msgstr ""
@@ -406,7 +406,7 @@ msgstr ""
 msgid "Source code: %s"
 msgstr ""
 
-#: ../IkiWiki/Plugin/highlight.pm:140
+#: ../IkiWiki/Plugin/highlight.pm:155
 msgid ""
 "warning: highlight perl module not available; falling back to pass through"
 msgstr ""
@@ -465,7 +465,7 @@ msgstr ""
 msgid "failed to process template %s"
 msgstr ""
 
-#: ../IkiWiki/Plugin/inline.pm:630
+#: ../IkiWiki/Plugin/inline.pm:663
 msgid "RPC::XML::Client not found, not pinging"
 msgstr ""
 
diff --git a/t/urlto.t b/t/urlto.t
new file mode 100755 (executable)
index 0000000..2544557
--- /dev/null
+++ b/t/urlto.t
@@ -0,0 +1,46 @@
+#!/usr/bin/perl
+use warnings;
+use strict;
+use Test::More tests => 21;
+
+BEGIN { use_ok("IkiWiki"); }
+
+$IkiWiki::config{srcdir} = '/does/not/exist/';
+$IkiWiki::config{usedirs} = 1;
+$IkiWiki::config{htmlext} = "HTML";
+$IkiWiki::config{wiki_file_chars} = "A-Za-z0-9._";
+
+$IkiWiki::config{url} = "http://smcv.example.co.uk";
+$IkiWiki::config{cgiurl} = "http://smcv.example.co.uk/cgi-bin/ikiwiki.cgi";
+is(IkiWiki::checkconfig(), 1);
+
+# absolute version
+is(IkiWiki::cgiurl(cgiurl => $config{cgiurl}), "http://smcv.example.co.uk/cgi-bin/ikiwiki.cgi");
+is(IkiWiki::cgiurl(cgiurl => $config{cgiurl}, do => 'badger'), "http://smcv.example.co.uk/cgi-bin/ikiwiki.cgi?do=badger");
+is(IkiWiki::urlto('index', undef, 1), "http://smcv.example.co.uk/");
+is(IkiWiki::urlto('stoats', undef, 1), "http://smcv.example.co.uk/stoats/");
+
+# "local" (absolute path within site) version (default for cgiurl)
+is(IkiWiki::cgiurl(), "/cgi-bin/ikiwiki.cgi");
+is(IkiWiki::cgiurl(do => 'badger'), "/cgi-bin/ikiwiki.cgi?do=badger");
+is(IkiWiki::baseurl(undef), "/");
+is(IkiWiki::urlto('index', undef), "/");
+is(IkiWiki::urlto('index'), "/");
+is(IkiWiki::urlto('stoats', undef), "/stoats/");
+is(IkiWiki::urlto('stoats'), "/stoats/");
+
+# fully-relative version (default for urlto and baseurl)
+is(IkiWiki::baseurl('badger/mushroom'), "../../");
+is(IkiWiki::urlto('badger/mushroom', 'snake'), "../badger/mushroom/");
+
+# explicit cgiurl override
+is(IkiWiki::cgiurl(cgiurl => 'https://foo/ikiwiki'), "https://foo/ikiwiki");
+is(IkiWiki::cgiurl(do => 'badger', cgiurl => 'https://foo/ikiwiki'), "https://foo/ikiwiki?do=badger");
+
+# with url and cgiurl on different sites, "local" degrades to absolute
+$IkiWiki::config{url} = "http://example.co.uk/~smcv";
+$IkiWiki::config{cgiurl} = "http://dynamic.example.co.uk/~smcv/ikiwiki.cgi";
+is(IkiWiki::checkconfig(), 1);
+is(IkiWiki::cgiurl(), "http://dynamic.example.co.uk/~smcv/ikiwiki.cgi");
+is(IkiWiki::baseurl(undef), "http://example.co.uk/~smcv/");
+is(IkiWiki::urlto('stoats', undef), "http://example.co.uk/~smcv/stoats/");