]> git.vanrenterghem.biz Git - git.ikiwiki.info.git/blobdiff - IkiWiki/CGI.pm
New bug and patch - close stderr when forking a sub process to run git
[git.ikiwiki.info.git] / IkiWiki / CGI.pm
index 5fccfb4741d4375760777a530916fa535e0273c2..d805506aa9dd1a62940d82599375b8b284fde262 100644 (file)
@@ -1,5 +1,7 @@
 #!/usr/bin/perl
 
 #!/usr/bin/perl
 
+package IkiWiki;
+
 use warnings;
 use strict;
 use IkiWiki;
 use warnings;
 use strict;
 use IkiWiki;
@@ -7,8 +9,6 @@ use IkiWiki::UserInfo;
 use open qw{:utf8 :std};
 use Encode;
 
 use open qw{:utf8 :std};
 use Encode;
 
-package IkiWiki;
-
 sub printheader ($) { #{{{
        my $session=shift;
        
 sub printheader ($) { #{{{
        my $session=shift;
        
@@ -77,13 +77,25 @@ sub check_canedit ($$$;$) { #{{{
        return $canedit;
 } #}}}
 
        return $canedit;
 } #}}}
 
+sub decode_cgi_utf8 ($) { #{{{
+       # decode_form_utf8 method is needed for 5.10
+       if ($] < 5.01) {
+               my $cgi = shift;
+               foreach my $f ($cgi->param) {
+                       $cgi->param($f, map { decode_utf8 $_ } $cgi->param($f));
+               }
+       }
+} #}}}
+
 sub decode_form_utf8 ($) { #{{{
 sub decode_form_utf8 ($) { #{{{
-       my $form = shift;
-       foreach my $f ($form->field) {
-               $form->field(name  => $f,
-                            value => decode_utf8($form->field($f)),
-                            force => 1,
-               );
+       if ($] >= 5.01) {
+               my $form = shift;
+               foreach my $f ($form->field) {
+                       $form->field(name  => $f,
+                                    value => decode_utf8($form->field($f)),
+                                    force => 1,
+                       );
+               }
        }
 } #}}}
 
        }
 } #}}}
 
@@ -106,6 +118,7 @@ sub cgi_signin ($$) { #{{{
        my $q=shift;
        my $session=shift;
 
        my $q=shift;
        my $session=shift;
 
+       decode_cgi_utf8($q);
        eval q{use CGI::FormBuilder};
        error($@) if $@;
        my $form = CGI::FormBuilder->new(
        eval q{use CGI::FormBuilder};
        error($@) if $@;
        my $form = CGI::FormBuilder->new(
@@ -165,6 +178,7 @@ sub cgi_prefs ($$) { #{{{
        my $session=shift;
 
        needsignin($q, $session);
        my $session=shift;
 
        needsignin($q, $session);
+       decode_cgi_utf8($q);
        
        # The session id is stored on the form and checked to
        # guard against CSRF.
        
        # The session id is stored on the form and checked to
        # guard against CSRF.
@@ -260,12 +274,13 @@ sub cgi_editpage ($$) { #{{{
        my $q=shift;
        my $session=shift;
        
        my $q=shift;
        my $session=shift;
        
+       decode_cgi_utf8($q);
+
        my @fields=qw(do rcsinfo subpage from page type editcontent comments);
        my @buttons=("Save Page", "Preview", "Cancel");
        eval q{use CGI::FormBuilder};
        error($@) if $@;
        my $form = CGI::FormBuilder->new(
        my @fields=qw(do rcsinfo subpage from page type editcontent comments);
        my @buttons=("Save Page", "Preview", "Cancel");
        eval q{use CGI::FormBuilder};
        error($@) if $@;
        my $form = CGI::FormBuilder->new(
-               title => "editpage",
                fields => \@fields,
                charset => "utf-8",
                method => 'POST',
                fields => \@fields,
                charset => "utf-8",
                method => 'POST',
@@ -286,12 +301,12 @@ sub cgi_editpage ($$) { #{{{
        });
        decode_form_utf8($form);
        
        });
        decode_form_utf8($form);
        
-       # This untaint is safe because titlepage removes any problematic
-       # characters.
-       my ($page)=$form->field('page');
-       $page=titlepage(possibly_foolish_untaint($page));
+       # This untaint is safe because we check file_pruned.
+       my $page=$form->field('page');
+       $page=possibly_foolish_untaint($page);
+       my $absolute=($page =~ s#^/+##);
        if (! defined $page || ! length $page ||
        if (! defined $page || ! length $page ||
-           file_pruned($page, $config{srcdir}) || $page=~/^\//) {
+           file_pruned($page, $config{srcdir})) {
                error("bad page name");
        }
 
                error("bad page name");
        }
 
@@ -339,7 +354,7 @@ sub cgi_editpage ($$) { #{{{
        $form->field(name => "from", type => 'hidden');
        $form->field(name => "rcsinfo", type => 'hidden');
        $form->field(name => "subpage", type => 'hidden');
        $form->field(name => "from", type => 'hidden');
        $form->field(name => "rcsinfo", type => 'hidden');
        $form->field(name => "subpage", type => 'hidden');
-       $form->field(name => "page", value => pagetitle($page, 1), force => 1);
+       $form->field(name => "page", value => $page, force => 1);
        $form->field(name => "type", value => $type, force => 1);
        $form->field(name => "comments", type => "text", size => 80);
        $form->field(name => "editcontent", type => "textarea", rows => 20,
        $form->field(name => "type", value => $type, force => 1);
        $form->field(name => "comments", type => "text", size => 80);
        $form->field(name => "editcontent", type => "textarea", rows => 20,
@@ -380,11 +395,17 @@ sub cgi_editpage ($$) { #{{{
                                session => $session,
                        );
                });
                                session => $session,
                        );
                });
-               $form->tmpl_param("page_preview",
-                       htmlize($page, $type,
+               my $preview=htmlize($page, $page, $type,
                        linkify($page, $page,
                        preprocess($page, $page,
                        linkify($page, $page,
                        preprocess($page, $page,
-                       filter($page, $page, $content), 0, 1))));
+                       filter($page, $page, $content), 0, 1)));
+               run_hooks(format => sub {
+                       $preview=shift->(
+                               page => $page,
+                               content => $preview,
+                       );
+               });
+               $form->tmpl_param("page_preview", $preview);
        
                if ($new) {
                        delete $pagesources{$page};
        
                if ($new) {
                        delete $pagesources{$page};
@@ -404,7 +425,8 @@ sub cgi_editpage ($$) { #{{{
                        if (! defined $from || ! length $from ||
                            $from ne $form->field('from') ||
                            file_pruned($from, $config{srcdir}) ||
                        if (! defined $from || ! length $from ||
                            $from ne $form->field('from') ||
                            file_pruned($from, $config{srcdir}) ||
-                           $from=~/^\// ||
+                           $from=~/^\// || 
+                           $absolute ||
                            $form->submitted eq "Preview") {
                                @page_locs=$best_loc=$page;
                        }
                            $form->submitted eq "Preview") {
                                @page_locs=$best_loc=$page;
                        }
@@ -465,8 +487,8 @@ sub cgi_editpage ($$) { #{{{
                        
                        $form->tmpl_param("page_select", 1);
                        $form->field(name => "page", type => 'select',
                        
                        $form->tmpl_param("page_select", 1);
                        $form->field(name => "page", type => 'select',
-                               options => [ map { pagetitle($_, 1) } @editable_locs ],
-                               value => pagetitle($best_loc, 1));
+                               options => [ map { [ $_, pagetitle($_, 1) ] } @editable_locs ],
+                               value => $best_loc);
                        $form->field(name => "type", type => 'select',
                                options => \@page_types);
                        $form->title(sprintf(gettext("creating %s"), pagetitle($page)));
                        $form->field(name => "type", type => 'select',
                                options => \@page_types);
                        $form->title(sprintf(gettext("creating %s"), pagetitle($page)));
@@ -621,11 +643,18 @@ sub cgi_getsession ($) { #{{{
        my $q=shift;
 
        eval q{use CGI::Session};
        my $q=shift;
 
        eval q{use CGI::Session};
+       error($@) if $@;
        CGI::Session->name("ikiwiki_session_".encode_utf8($config{wikiname}));
        
        my $oldmask=umask(077);
        CGI::Session->name("ikiwiki_session_".encode_utf8($config{wikiname}));
        
        my $oldmask=umask(077);
-       my $session = CGI::Session->new("driver:DB_File", $q,
-               { FileName => "$config{wikistatedir}/sessions.db" });
+       my $session = eval {
+               CGI::Session->new("driver:DB_File", $q,
+                       { FileName => "$config{wikistatedir}/sessions.db" })
+       };
+       if (! $session || $@) {
+               error($@." ".CGI::Session->errstr());
+       }
+       
        umask($oldmask);
 
        return $session;
        umask($oldmask);
 
        return $session;
@@ -644,10 +673,11 @@ sub cgi (;$$) { #{{{
        my $q=shift;
        my $session=shift;
 
        my $q=shift;
        my $session=shift;
 
+       eval q{use CGI};
+       error($@) if $@;
+       $CGI::DISABLE_UPLOADS=$config{cgi_disable_uploads};
+
        if (! $q) {
        if (! $q) {
-               eval q{use CGI};
-               error($@) if $@;
-       
                binmode(STDIN);
                $q=CGI->new;
                binmode(STDIN, ":utf8");
                binmode(STDIN);
                $q=CGI->new;
                binmode(STDIN, ":utf8");
@@ -720,4 +750,14 @@ sub cgi (;$$) { #{{{
        }
 } #}}}
 
        }
 } #}}}
 
+# Does not need tobe called directly; all errors will go through here.
+sub cgierror ($) { #{{{
+       my $message=shift;
+
+       print "Content-type: text/html\n\n";
+       print misctemplate(gettext("Error"),
+               "<p class=\"error\">".gettext("Error").": $message</p>");
+       die $@;
+} #}}}
+
 1
 1