X-Git-Url: https://sipb.mit.edu/gitweb.cgi/ikiwiki.git/blobdiff_plain/8e2fb374e03ee2122fcfb678fd851673ca86eefa..ba6b8e5e3e3e5f6749623355a93269f16313eb61:/IkiWiki/CGI.pm diff --git a/IkiWiki/CGI.pm b/IkiWiki/CGI.pm index 144ad2198..65a1d7fa0 100644 --- a/IkiWiki/CGI.pm +++ b/IkiWiki/CGI.pm @@ -21,6 +21,23 @@ sub printheader ($) { #{{{ } #}}} +sub showform ($$$$) { #{{{ + my $form=shift; + my $buttons=shift; + my $session=shift; + my $cgi=shift; + + if (exists $hooks{formbuilder}) { + run_hooks(formbuilder => sub { + shift->(form => $form, cgi => $cgi, session => $session, + buttons => $buttons); + }); + } + + printheader($session); + print misctemplate($form->title, $form->render(submit => $buttons)); +} + sub redirect ($$) { #{{{ my $q=shift; my $url=shift; @@ -43,25 +60,27 @@ sub check_canedit ($$$;$) { #{{{ run_hooks(canedit => sub { return if defined $canedit; my $ret=shift->($page, $q, $session); - if (defined $ret && $ret eq "") { - $canedit=1; - } - elsif (defined $ret) { - $canedit=0; - error($ret) unless $nonfatal; + if (defined $ret) { + if ($ret eq "") { + $canedit=1; + } + elsif (ref $ret eq 'CODE') { + $ret->() unless $nonfatal; + $canedit=0; + } + elsif (defined $ret) { + error($ret) unless $nonfatal; + $canedit=0; + } } }); return $canedit; } #}}} -sub decode_form_utf8 ($) { #{{{ - my $form = shift; - foreach my $f ($form->field) { - next if Encode::is_utf8(scalar $form->field($f)); - $form->field(name => $f, - value => decode_utf8($form->field($f)), - force => 1, - ); +sub decode_cgi_utf8 ($) { #{{{ + my $cgi = shift; + foreach my $f ($cgi->param) { + $cgi->param($f, map { decode_utf8 $_ } $cgi->param($f)); } } #}}} @@ -120,9 +139,7 @@ sub needsignin ($$) { #{{{ if (! defined $session->param("name") || ! userinfo_get($session->param("name"), "regdate")) { - if (! defined $session->param("postsignin")) { - $session->param(postsignin => $ENV{QUERY_STRING}); - } + $session->param(postsignin => $ENV{QUERY_STRING}); cgi_signin($q, $session); cgi_savesession($session); exit; @@ -133,12 +150,12 @@ sub cgi_signin ($$) { #{{{ my $q=shift; my $session=shift; + decode_cgi_utf8($q); eval q{use CGI::FormBuilder}; error($@) if $@; my $form = CGI::FormBuilder->new( title => "signin", name => "signin", - header => 1, charset => "utf-8", method => 'POST', required => 'NONE', @@ -158,24 +175,15 @@ sub cgi_signin ($$) { #{{{ force => 1); run_hooks(formbuilder_setup => sub { - shift->(form => $form, cgi => $q, session => $session); + shift->(form => $form, cgi => $q, session => $session, + buttons => $buttons); }); - - decode_form_utf8($form); - if (exists $hooks{formbuilder}) { - run_hooks(formbuilder => sub { - shift->(form => $form, cgi => $q, session => $session, - buttons => $buttons); - }); - } - else { - if ($form->submitted) { - $form->validate; - } - printheader($session); - print misctemplate($form->title, $form->render(submit => $buttons)); + if ($form->submitted) { + $form->validate; } + + showform($form, $buttons, $session, $q); } #}}} sub cgi_postsignin ($$) { #{{{ @@ -191,9 +199,7 @@ sub cgi_postsignin ($$) { #{{{ exit; } else { - # This can occur, for example, if a user went to the signin - # url via a bookmark. - redirect($q, $config{url}); + error(gettext("login failed, perhaps you need to turn on cookies?")); } } #}}} @@ -203,6 +209,7 @@ sub cgi_prefs ($$) { #{{{ needsignin($q, $session); + decode_cgi_utf8($q); eval q{use CGI::FormBuilder}; error($@) if $@; my $form = CGI::FormBuilder->new( @@ -229,14 +236,15 @@ sub cgi_prefs ($$) { #{{{ my $buttons=["Save Preferences", "Logout", "Cancel"]; run_hooks(formbuilder_setup => sub { - shift->(form => $form, cgi => $q, session => $session); + shift->(form => $form, cgi => $q, session => $session, + buttons => $buttons); }); $form->field(name => "do", type => "hidden"); $form->field(name => "email", size => 50, fieldset => "preferences"); $form->field(name => "subscriptions", size => 50, fieldset => "preferences", - comment => "(".htmllink("", "", "PageSpec", noimageinline => 1).")"); + comment => "(".htmllink("", "", "ikiwiki/PageSpec", noimageinline => 1).")"); $form->field(name => "banned_users", size => 50, fieldset => "admin"); @@ -256,8 +264,6 @@ sub cgi_prefs ($$) { #{{{ } } - decode_form_utf8($form); - if ($form->submitted eq 'Logout') { $session->delete(); redirect($q, $config{url}); @@ -269,7 +275,7 @@ sub cgi_prefs ($$) { #{{{ } elsif ($form->submitted eq 'Save Preferences' && $form->validate) { foreach my $field (qw(email subscriptions)) { - if (defined $form->field($field) && length $form->field($field)) { + if (defined $form->field($field)) { userinfo_set($user_name, $field, $form->field($field)) || error("failed to set $field"); } @@ -283,16 +289,7 @@ sub cgi_prefs ($$) { #{{{ $form->text(gettext("Preferences saved.")); } - if (exists $hooks{formbuilder}) { - run_hooks(formbuilder => sub { - shift->(form => $form, cgi => $q, session => $session, - buttons => $buttons); - }); - } - else { - printheader($session); - print misctemplate($form->title, $form->render(submit => $buttons)); - } + showform($form, $buttons, $session, $q); } #}}} sub cgi_editpage ($$) { #{{{ @@ -302,16 +299,14 @@ sub cgi_editpage ($$) { #{{{ my @fields=qw(do rcsinfo subpage from page type editcontent comments); my @buttons=("Save Page", "Preview", "Cancel"); + decode_cgi_utf8($q); eval q{use CGI::FormBuilder}; error($@) if $@; my $form = CGI::FormBuilder->new( + title => "editpage", fields => \@fields, - header => 1, charset => "utf-8", method => 'POST', - validate => { - editcontent => '/.+/', - }, required => [qw{editcontent}], javascript => 0, params => $q, @@ -323,16 +318,16 @@ sub cgi_editpage ($$) { #{{{ ); run_hooks(formbuilder_setup => sub { - shift->(form => $form, cgi => $q, session => $session); + shift->(form => $form, cgi => $q, session => $session, + buttons => \@buttons); }); - 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)); - if (! defined $page || ! length $page || file_pruned($page, $config{srcdir}) || $page=~/^\//) { + if (! defined $page || ! length $page || + file_pruned($page, $config{srcdir}) || $page=~/^\//) { error("bad page name"); } @@ -353,13 +348,14 @@ sub cgi_editpage ($$) { #{{{ $form->field(name => "rcsinfo", value => rcs_prepedit($file), force => 1); } + $form->field(name => "editcontent", validate => '/.*/'); } else { $type=$form->param('type'); if (defined $type && length $type && $hooks{htmlize}{$type}) { $type=possibly_foolish_untaint($type); } - elsif (defined $from) { + elsif (defined $from && exists $pagesources{$from}) { # favor the type of linking page $type=pagetype($pagesources{$from}); } @@ -368,6 +364,7 @@ sub cgi_editpage ($$) { #{{{ if (! $form->submitted) { $form->field(name => "rcsinfo", value => "", force => 1); } + $form->field(name => "editcontent", validate => '/.+/'); } $form->field(name => "do", type => 'hidden'); @@ -382,7 +379,9 @@ sub cgi_editpage ($$) { #{{{ $form->tmpl_param("can_commit", $config{rcs}); $form->tmpl_param("indexlink", indexlink()); $form->tmpl_param("helponformattinglink", - htmllink("", "", "HelpOnFormatting", noimageinline => 1)); + htmllink("", "", "ikiwiki/formatting", + noimageinline => 1, + linktext => "FormattingHelp")); $form->tmpl_param("baseurl", baseurl()); if ($form->submitted eq "Cancel") { @@ -398,19 +397,27 @@ sub cgi_editpage ($$) { #{{{ return; } elsif ($form->submitted eq "Preview") { + my $content=$form->field('editcontent'); + run_hooks(editcontent => sub { + $content=shift->( + content => $content, + page => $page, + cgi => $q, + session => $session, + ); + }); $form->tmpl_param("page_preview", htmlize($page, $type, linkify($page, "", preprocess($page, $page, - filter($page, $page, $form->field('editcontent')), 0, 1)))); + filter($page, $page, $content), 0, 1)))); } - else { + elsif ($form->submitted eq "Save Page") { $form->tmpl_param("page_preview", ""); } $form->tmpl_param("page_conflict", ""); - if (! $form->submitted || $form->submitted eq "Preview" || - ! $form->validate) { + if ($form->submitted ne "Save Page" || ! $form->validate) { if ($form->field("do") eq "create") { my @page_locs; my $best_loc; @@ -493,26 +500,27 @@ sub cgi_editpage ($$) { #{{{ $form->title(sprintf(gettext("editing %s"), pagetitle($page))); } - printheader($session); - print misctemplate($form->title, $form->render(submit => \@buttons)); + showform($form, \@buttons, $session, $q); + saveindex(); } else { # save page check_canedit($page, $q, $session); - if (! -e "$config{srcdir}/$file" && - $form->field("do") ne "create") { + + my $exists=-e "$config{srcdir}/$file"; + + if ($form->field("do") ne "create" && ! $exists && + ! eval { srcfile($file) }) { $form->tmpl_param("page_gone", 1); $form->field(name => "do", value => "create", force => 1); $form->tmpl_param("page_select", 0); $form->field(name => "page", type => 'hidden'); $form->field(name => "type", type => 'hidden'); $form->title(sprintf(gettext("editing %s"), $page)); - printheader($session); - print misctemplate($form->title, $form->render(submit => \@buttons)); + showform($form, \@buttons, $session, $q); return; } - elsif (-e "$config{srcdir}/$file" && - $form->field("do") eq "create") { + elsif ($form->field("do") eq "create" && $exists) { $form->tmpl_param("creation_conflict", 1); $form->field(name => "do", value => "edit", force => 1); $form->tmpl_param("page_select", 0); @@ -523,15 +531,22 @@ sub cgi_editpage ($$) { #{{{ value => readfile("$config{srcdir}/$file"). "\n\n\n".$form->field("editcontent"), force => 1); - printheader($session); - print misctemplate($form->title, $form->render(submit => \@buttons)); + showform($form, \@buttons, $session, $q); return; } my $content=$form->field('editcontent'); - + run_hooks(editcontent => sub { + $content=shift->( + content => $content, + page => $page, + cgi => $q, + session => $session, + ); + }); $content=~s/\r\n/\n/g; $content=~s/\r/\n/g; + $content.="\n" if $content !~ /\n$/; $config{cgi}=0; # avoid cgi error message eval { writefile($file, $config{srcdir}, $content) }; @@ -546,8 +561,7 @@ sub cgi_editpage ($$) { #{{{ $form->field(name => "page", type => 'hidden'); $form->field(name => "type", type => 'hidden'); $form->title(sprintf(gettext("editing %s"), $page)); - printheader($session); - print misctemplate($form->title, $form->render(submit => \@buttons)); + showform($form, \@buttons, $session, $q); return; } @@ -559,7 +573,7 @@ sub cgi_editpage ($$) { #{{{ $message=$form->field('comments'); } - if ($form->field("do") eq "create") { + if (! $exists) { rcs_add($file); } @@ -578,6 +592,10 @@ sub cgi_editpage ($$) { #{{{ # may have been committed while the post-commit hook was # disabled. require IkiWiki::Render; + # Reload index, since the first time it's loaded is before + # the wiki is locked, and things may have changed in the + # meantime. + loadindex(); refresh(); saveindex(); @@ -591,8 +609,7 @@ sub cgi_editpage ($$) { #{{{ $form->field(name => "page", type => 'hidden'); $form->field(name => "type", type => 'hidden'); $form->title(sprintf(gettext("editing %s"), $page)); - printheader($session); - print misctemplate($form->title, $form->render(submit => \@buttons)); + showform($form, \@buttons, $session, $q); return; } else { @@ -695,32 +712,14 @@ sub cgi (;$$) { #{{{ cgi_signin($q, $session); cgi_savesession($session); } - elsif (defined $session->param("postsignin")) { - cgi_postsignin($q, $session); - } elsif ($do eq 'prefs') { cgi_prefs($q, $session); } elsif ($do eq 'create' || $do eq 'edit') { cgi_editpage($q, $session); } - elsif ($do eq 'blog') { - my $page=decode_utf8($q->param('title')); - $page=~s/\///g; # no slashes in blog posts - # if the page already exists, munge it to be unique - my $from=$q->param('from'); - my $add=""; - while (exists $pagecase{lc($from."/".titlepage($page).$add)}) { - $add=1 unless length $add; - $add++; - } - $q->param('page', $page.$add); - # now run same as create - $q->param('do', 'create'); - cgi_editpage($q, $session); - } - elsif ($do eq 'postsignin') { - error(gettext("login failed, perhaps you need to turn on cookies?")); + elsif (defined $session->param("postsignin") || $do eq 'postsignin') { + cgi_postsignin($q, $session); } else { error("unknown do parameter");