* Make auth methods pluggable.
[ikiwiki] / IkiWiki / CGI.pm
1 #!/usr/bin/perl
2
3 use warnings;
4 use strict;
5 use IkiWiki;
6 use IkiWiki::UserInfo;
7 use open qw{:utf8 :std};
8 use Encode;
9
10 package IkiWiki;
11
12 sub printheader ($) { #{{{
13         my $session=shift;
14         
15         if ($config{sslcookie}) {
16                 print $session->header(-charset => 'utf-8',
17                         -cookie => $session->cookie(-secure => 1));
18         } else {
19                 print $session->header(-charset => 'utf-8');
20         }
21
22 } #}}}
23
24 sub redirect ($$) { #{{{
25         my $q=shift;
26         my $url=shift;
27         if (! $config{w3mmode}) {
28                 print $q->redirect($url);
29         }
30         else {
31                 print "Content-type: text/plain\n";
32                 print "W3m-control: GOTO $url\n\n";
33         }
34 } #}}}
35
36 sub page_locked ($$;$) { #{{{
37         my $page=shift;
38         my $session=shift;
39         my $nonfatal=shift;
40         
41         my $user=$session->param("name");
42         return if defined $user && is_admin($user);
43
44         foreach my $admin (@{$config{adminuser}}) {
45                 my $locked_pages=userinfo_get($admin, "locked_pages");
46                 if (pagespec_match($page, userinfo_get($admin, "locked_pages"))) {
47                         return 1 if $nonfatal;
48                         error(htmllink("", "", $page, 1)." is locked by ".
49                               htmllink("", "", $admin, 1)." and cannot be edited.");
50                 }
51         }
52
53         return 0;
54 } #}}}
55
56 sub decode_form_utf8 ($) { #{{{
57         my $form = shift;
58         foreach my $f ($form->field) {
59                 next if Encode::is_utf8(scalar $form->field($f));
60                 $form->field(name  => $f,
61                              value => decode_utf8($form->field($f)),
62                              force => 1,
63                             );
64         }
65 } #}}}
66
67 sub cgi_recentchanges ($) { #{{{
68         my $q=shift;
69         
70         unlockwiki();
71
72         # Optimisation: building recentchanges means calculating lots of
73         # links. Memoizing htmllink speeds it up a lot (can't be memoized
74         # during page builds as the return values may change, but they
75         # won't here.)
76         eval q{use Memoize};
77         error($@) if $@;
78         memoize("htmllink");
79
80         eval q{use Time::Duration};
81         error($@) if $@;
82         eval q{use CGI 'escapeHTML'};
83         error($@) if $@;
84
85         my $changelog=[rcs_recentchanges(100)];
86         foreach my $change (@$changelog) {
87                 $change->{when} = concise(ago($change->{when}));
88                 $change->{user} = htmllink("", "", escapeHTML($change->{user}), 1);
89
90                 my $is_excess = exists $change->{pages}[10]; # limit pages to first 10
91                 delete @{$change->{pages}}[10 .. @{$change->{pages}}] if $is_excess;
92                 $change->{pages} = [
93                         map {
94                                 $_->{link} = htmllink("", "", $_->{page}, 1);
95                                 $_;
96                         } @{$change->{pages}}
97                 ];
98                 push @{$change->{pages}}, { link => '...' } if $is_excess;
99         }
100
101         my $template=template("recentchanges.tmpl"); 
102         $template->param(
103                 title => "RecentChanges",
104                 indexlink => indexlink(),
105                 wikiname => $config{wikiname},
106                 changelog => $changelog,
107                 baseurl => baseurl(),
108         );
109         run_hooks(pagetemplate => sub {
110                 shift->(page => "", destpage => "", template => $template);
111         });
112         print $q->header(-charset => 'utf-8'), $template->output;
113 } #}}}
114
115 sub cgi_signin ($$) { #{{{
116         my $q=shift;
117         my $session=shift;
118
119         eval q{use CGI::FormBuilder};
120         error($@) if $@;
121         my $form = CGI::FormBuilder->new(
122                 title => "signin",
123                 fields => [qw(do title page subpage from name password openid_url)],
124                 header => 1,
125                 charset => "utf-8",
126                 method => 'POST',
127                 validate => {
128                         confirm_password => {
129                                 perl => q{eq $form->field("password")},
130                         },
131                         email => 'EMAIL',
132                 },
133                 required => 'NONE',
134                 javascript => 0,
135                 params => $q,
136                 action => $config{cgiurl},
137                 header => 0,
138                 template => (-e "$config{templatedir}/signin.tmpl" ?
139                              {template_params("signin.tmpl")} : ""),
140                 stylesheet => baseurl()."style.css",
141         );
142                 
143         decode_form_utf8($form);
144         
145         $form->field(name => "name", required => 0);
146         $form->field(name => "do", type => "hidden");
147         $form->field(name => "page", type => "hidden");
148         $form->field(name => "title", type => "hidden");
149         $form->field(name => "from", type => "hidden");
150         $form->field(name => "subpage", type => "hidden");
151         $form->field(name => "password", type => "password", required => 0);
152         if ($config{openid}) {
153                 $form->field(name => "openid_url", label => "OpenID", comment => "to log in via OpenID");
154         }
155         else {
156                 $form->field(name => "openid_url", type => "hidden");
157         }
158         if ($form->submitted eq "Register" || $form->submitted eq "Create Account") {
159                 $form->title("register");
160                 $form->text("");
161                 $form->fields(qw(do title page subpage from name password confirm_password email));
162                 $form->field(name => "confirm_password", type => "password");
163                 $form->field(name => "email", type => "text");
164                 $form->field(name => "openid_url", type => "hidden");
165         }
166         if ($q->param("do") ne "signin" && !$form->submitted) {
167                 $form->text("You need to log in first.");
168         }
169         
170         if ($form->submitted) {
171                 my $submittype=$form->submitted;
172                 # OpenID login uses the Login button, but validates
173                 # differently.
174                 if ($submittype eq "Login" && $config{openid} && 
175                     length $form->field("openid_url")) {
176                         $submittype="OpenID";
177                         
178                         $form->field(
179                                 name => "openid_url",
180                                 validate => sub {
181                                         # FIXME: ugh
182                                         IkiWiki::Plugin::openid::validate($q, $session, $form, shift);
183                                 },
184                         );
185                 }
186
187                 # Set required fields based on how form was submitted.
188                 my %required=(
189                         "Login" => [qw(name password)],
190                         "Register" => [],
191                         "Create Account" => [qw(name password confirm_password email)],
192                         "Mail Password" => [qw(name)],
193                         "OpenID" => [qw(openid_url)],
194                 );
195                 foreach my $opt (@{$required{$submittype}}) {
196                         $form->field(name => $opt, required => 1);
197                 }
198         
199                 # Validate password differently depending on how
200                 # form was submitted.
201                 if ($submittype eq 'Login') {
202                         $form->field(
203                                 name => "password",
204                                 validate => sub {
205                                         length $form->field("name") &&
206                                         shift eq userinfo_get($form->field("name"), 'password');
207                                 },
208                         );
209                         $form->field(name => "name", validate => '/^\w+$/');
210                 }
211                 elsif ($submittype ne 'OpenID') {
212                         $form->field(name => "password", validate => 'VALUE');
213                 }
214                 # And make sure the entered name exists when logging
215                 # in or sending email, and does not when registering.
216                 if ($submittype eq 'Create Account' ||
217                     $submittype eq 'Register') {
218                         $form->field(
219                                 name => "name",
220                                 validate => sub {
221                                         my $name=shift;
222                                         length $name &&
223                                         $name=~/$config{wiki_file_regexp}/ &&
224                                         ! userinfo_get($name, "regdate");
225                                 },
226                         );
227                 }
228                 elsif ($submittype ne 'OpenID') {
229                         $form->field(
230                                 name => "name",
231                                 validate => sub {
232                                         my $name=shift;
233                                         length $name &&
234                                         userinfo_get($name, "regdate");
235                                 },
236                         );
237                 }
238         }
239         else {
240                 # First time settings.
241                 $form->field(name => "name", comment => "use FirstnameLastName");
242                 if ($session->param("name")) {
243                         $form->field(name => "name", value => $session->param("name"));
244                 }
245         }
246
247         if ($form->submitted && $form->validate) {
248                 if ($form->submitted eq 'Login') {
249                         $session->param("name", $form->field("name"));
250                         if (defined $form->field("do") && 
251                             $form->field("do") ne 'signin') {
252                                 redirect($q, cgiurl(
253                                         do => $form->field("do"),
254                                         page => $form->field("page"),
255                                         title => $form->field("title"),
256                                         from => $form->field("from"),
257                                         subpage => $form->field("subpage"),
258                                 ));
259                         }
260                         else {
261                                 redirect($q, $config{url});
262                         }
263                 }
264                 elsif ($form->submitted eq 'Create Account') {
265                         my $user_name=$form->field('name');
266                         if (userinfo_setall($user_name, {
267                                            'email' => $form->field('email'),
268                                            'password' => $form->field('password'),
269                                            'regdate' => time
270                                          })) {
271                                 $form->field(name => "confirm_password", type => "hidden");
272                                 $form->field(name => "email", type => "hidden");
273                                 $form->text("Account creation successful. Now you can Login.");
274                                 printheader($session);
275                                 print misctemplate($form->title, $form->render(submit => ["Login"]));
276                         }
277                         else {
278                                 error("Error creating account.");
279                         }
280                 }
281                 elsif ($form->submitted eq 'Mail Password') {
282                         my $user_name=$form->field("name");
283                         my $template=template("passwordmail.tmpl");
284                         $template->param(
285                                 user_name => $user_name,
286                                 user_password => userinfo_get($user_name, "password"),
287                                 wikiurl => $config{url},
288                                 wikiname => $config{wikiname},
289                                 REMOTE_ADDR => $ENV{REMOTE_ADDR},
290                         );
291                         
292                         eval q{use Mail::Sendmail};
293                         error($@) if $@;
294                         sendmail(
295                                 To => userinfo_get($user_name, "email"),
296                                 From => "$config{wikiname} admin <$config{adminemail}>",
297                                 Subject => "$config{wikiname} information",
298                                 Message => $template->output,
299                         ) or error("Failed to send mail");
300                         
301                         $form->text("Your password has been emailed to you.");
302                         $form->field(name => "name", required => 0);
303                         printheader($session);
304                         print misctemplate($form->title, $form->render(submit => ["Login", "Mail Password"]));
305                 }
306                 elsif ($form->submitted eq "Register") {
307                         printheader($session);
308                         print misctemplate($form->title, $form->render(submit => ["Create Account"]));
309                 }
310         }
311         elsif ($form->submitted eq "Create Account") {
312                 printheader($session);
313                 print misctemplate($form->title, $form->render(submit => ["Create Account"]));
314         }
315         else {
316                 printheader($session);
317                 print misctemplate($form->title, $form->render(submit => ["Login", "Register", "Mail Password"]));
318         }
319 } #}}}
320
321 sub cgi_prefs ($$) { #{{{
322         my $q=shift;
323         my $session=shift;
324
325         eval q{use CGI::FormBuilder};
326         error($@) if $@;
327         my $form = CGI::FormBuilder->new(
328                 title => "preferences",
329                 fields => [qw(do name password confirm_password email 
330                               subscriptions locked_pages)],
331                 header => 0,
332                 charset => "utf-8",
333                 method => 'POST',
334                 validate => {
335                         confirm_password => {
336                                 perl => q{eq $form->field("password")},
337                         },
338                         email => 'EMAIL',
339                 },
340                 required => 'NONE',
341                 javascript => 0,
342                 params => $q,
343                 action => $config{cgiurl},
344                 template => (-e "$config{templatedir}/prefs.tmpl" ?
345                              {template_params("prefs.tmpl")} : ""),
346                 stylesheet => baseurl()."style.css",
347         );
348         my @buttons=("Save Preferences", "Logout", "Cancel");
349         
350         my $user_name=$session->param("name");
351         $form->field(name => "do", type => "hidden");
352         $form->field(name => "name", disabled => 1,
353                 value => $user_name, force => 1);
354         $form->field(name => "password", type => "password");
355         $form->field(name => "confirm_password", type => "password");
356         $form->field(name => "subscriptions", size => 50,
357                 comment => "(".htmllink("", "", "PageSpec", 1).")");
358         $form->field(name => "locked_pages", size => 50,
359                 comment => "(".htmllink("", "", "PageSpec", 1).")");
360         $form->field(name => "banned_users", size => 50);
361         
362         if (! is_admin($user_name)) {
363                 $form->field(name => "locked_pages", type => "hidden");
364                 $form->field(name => "banned_users", type => "hidden");
365         }
366
367         if ($config{httpauth}) {
368                 $form->field(name => "password", type => "hidden");
369                 $form->field(name => "confirm_password", type => "hidden");
370         }
371         
372         if (! $form->submitted) {
373                 $form->field(name => "email", force => 1,
374                         value => userinfo_get($user_name, "email"));
375                 $form->field(name => "subscriptions", force => 1,
376                         value => userinfo_get($user_name, "subscriptions"));
377                 $form->field(name => "locked_pages", force => 1,
378                         value => userinfo_get($user_name, "locked_pages"));
379                 if (is_admin($user_name)) {
380                         $form->field(name => "banned_users", force => 1,
381                                 value => join(" ", get_banned_users()));
382                 }
383         }
384         
385         decode_form_utf8($form);
386         
387         if ($form->submitted eq 'Logout') {
388                 $session->delete();
389                 redirect($q, $config{url});
390                 return;
391         }
392         elsif ($form->submitted eq 'Cancel') {
393                 redirect($q, $config{url});
394                 return;
395         }
396         elsif ($form->submitted eq "Save Preferences" && $form->validate) {
397                 foreach my $field (qw(password email subscriptions locked_pages)) {
398                         if (length $form->field($field)) {
399                                 userinfo_set($user_name, $field, $form->field($field)) || error("failed to set $field");
400                         }
401                 }
402                 if (is_admin($user_name)) {
403                         set_banned_users(grep { ! is_admin($_) }
404                                         split(' ', $form->field("banned_users")));
405                 }
406                 $form->text("Preferences saved.");
407         }
408         
409         printheader($session);
410         print misctemplate($form->title, $form->render(submit => \@buttons));
411 } #}}}
412
413 sub cgi_editpage ($$) { #{{{
414         my $q=shift;
415         my $session=shift;
416
417         my @fields=qw(do rcsinfo subpage from page type editcontent comments);
418         my @buttons=("Save Page", "Preview", "Cancel");
419         
420         eval q{use CGI::FormBuilder; use CGI::FormBuilder::Template::HTML};
421         error($@) if $@;
422         my $renderer=CGI::FormBuilder::Template::HTML->new(
423                 fields => \@fields,
424                 template_params("editpage.tmpl"),
425         );
426         run_hooks(pagetemplate => sub {
427                 shift->(page => "", destpage => "", template => $renderer->engine);
428         });
429         my $form = CGI::FormBuilder->new(
430                 fields => \@fields,
431                 header => 1,
432                 charset => "utf-8",
433                 method => 'POST',
434                 validate => {
435                         editcontent => '/.+/',
436                 },
437                 required => [qw{editcontent}],
438                 javascript => 0,
439                 params => $q,
440                 action => $config{cgiurl},
441                 table => 0,
442                 template => $renderer,
443         );
444         
445         decode_form_utf8($form);
446         
447         # This untaint is safe because titlepage removes any problematic
448         # characters.
449         my ($page)=$form->field('page');
450         $page=titlepage(possibly_foolish_untaint($page));
451         if (! defined $page || ! length $page ||
452             $page=~/$config{wiki_file_prune_regexp}/ || $page=~/^\//) {
453                 error("bad page name");
454         }
455         
456         my $from;
457         if (defined $form->field('from')) {
458                 ($from)=$form->field('from')=~/$config{wiki_file_regexp}/;
459         }
460         
461         my $file;
462         my $type;
463         if (exists $pagesources{$page}) {
464                 $file=$pagesources{$page};
465                 $type=pagetype($file);
466         }
467         else {
468                 $type=$form->param('type');
469                 if (defined $type && length $type && $hooks{htmlize}{$type}) {
470                         $type=possibly_foolish_untaint($type);
471                 }
472                 elsif (defined $from) {
473                         # favor the type of linking page
474                         $type=pagetype($pagesources{$from});
475                 }
476                 $type=$config{default_pageext} unless defined $type;
477                 $file=$page.".".$type;
478         }
479
480         my $newfile=0;
481         if (! -e "$config{srcdir}/$file") {
482                 $newfile=1;
483         }
484
485         $form->field(name => "do", type => 'hidden');
486         $form->field(name => "from", type => 'hidden');
487         $form->field(name => "rcsinfo", type => 'hidden');
488         $form->field(name => "subpage", type => 'hidden');
489         $form->field(name => "page", value => $page, force => 1);
490         $form->field(name => "type", value => $type, force => 1);
491         $form->field(name => "comments", type => "text", size => 80);
492         $form->field(name => "editcontent", type => "textarea", rows => 20,
493                 cols => 80);
494         $form->tmpl_param("can_commit", $config{rcs});
495         $form->tmpl_param("indexlink", indexlink());
496         $form->tmpl_param("helponformattinglink",
497                 htmllink("", "", "HelpOnFormatting", 1));
498         $form->tmpl_param("baseurl", baseurl());
499         if (! $form->submitted) {
500                 $form->field(name => "rcsinfo", value => rcs_prepedit($file),
501                         force => 1);
502         }
503         
504         if ($form->submitted eq "Cancel") {
505                 if ($newfile && defined $from) {
506                         redirect($q, "$config{url}/".htmlpage($from));
507                 }
508                 elsif ($newfile) {
509                         redirect($q, $config{url});
510                 }
511                 else {
512                         redirect($q, "$config{url}/".htmlpage($page));
513                 }
514                 return;
515         }
516         elsif ($form->submitted eq "Preview") {
517                 my $content=$form->field('editcontent');
518                 my $comments=$form->field('comments');
519                 $form->field(name => "editcontent",
520                                 value => $content, force => 1);
521                 $form->field(name => "comments",
522                                 value => $comments, force => 1);
523                 $config{rss}=$config{atom}=0; # avoid preview writing a feed!
524                 $form->tmpl_param("page_preview",
525                         htmlize($page, $type,
526                         linkify($page, "",
527                         preprocess($page, $page,
528                         filter($page, $content)))));
529         }
530         else {
531                 $form->tmpl_param("page_preview", "");
532         }
533         $form->tmpl_param("page_conflict", "");
534         
535         if (! $form->submitted || $form->submitted eq "Preview" || 
536             ! $form->validate) {
537                 if ($form->field("do") eq "create") {
538                         my @page_locs;
539                         my $best_loc;
540                         if (! defined $from || ! length $from ||
541                             $from ne $form->field('from') ||
542                             $from=~/$config{wiki_file_prune_regexp}/ ||
543                             $from=~/^\// ||
544                             $form->submitted eq "Preview") {
545                                 @page_locs=$best_loc=$page;
546                         }
547                         else {
548                                 my $dir=$from."/";
549                                 $dir=~s![^/]+/+$!!;
550                                 
551                                 if ((defined $form->field('subpage') && length $form->field('subpage')) ||
552                                     $page eq 'discussion') {
553                                         $best_loc="$from/$page";
554                                 }
555                                 else {
556                                         $best_loc=$dir.$page;
557                                 }
558                                 
559                                 push @page_locs, $dir.$page;
560                                 push @page_locs, "$from/$page";
561                                 while (length $dir) {
562                                         $dir=~s![^/]+/+$!!;
563                                         push @page_locs, $dir.$page;
564                                 }
565                         }
566
567                         @page_locs = grep {
568                                 ! exists $pagecase{lc $_} &&
569                                 ! page_locked($_, $session, 1)
570                         } @page_locs;
571                         
572                         if (! @page_locs) {
573                                 # hmm, someone else made the page in the
574                                 # meantime?
575                                 redirect($q, "$config{url}/".htmlpage($page));
576                                 return;
577                         }
578                         
579                         my @page_types;
580                         if (exists $hooks{htmlize}) {
581                                 @page_types=keys %{$hooks{htmlize}};
582                         }
583                         
584                         $form->tmpl_param("page_select", 1);
585                         $form->field(name => "page", type => 'select',
586                                 options => \@page_locs, value => $best_loc);
587                         $form->field(name => "type", type => 'select',
588                                 options => \@page_types);
589                         $form->title("creating ".pagetitle($page));
590                 }
591                 elsif ($form->field("do") eq "edit") {
592                         page_locked($page, $session);
593                         if (! defined $form->field('editcontent') || 
594                             ! length $form->field('editcontent')) {
595                                 my $content="";
596                                 if (exists $pagesources{$page}) {
597                                         $content=readfile(srcfile($pagesources{$page}));
598                                         $content=~s/\n/\r\n/g;
599                                 }
600                                 $form->field(name => "editcontent", value => $content,
601                                         force => 1);
602                         }
603                         $form->tmpl_param("page_select", 0);
604                         $form->field(name => "page", type => 'hidden');
605                         $form->field(name => "type", type => 'hidden');
606                         $form->title("editing ".pagetitle($page));
607                 }
608                 
609                 print $form->render(submit => \@buttons);
610         }
611         else {
612                 # save page
613                 page_locked($page, $session);
614                 
615                 my $content=$form->field('editcontent');
616
617                 $content=~s/\r\n/\n/g;
618                 $content=~s/\r/\n/g;
619                 writefile($file, $config{srcdir}, $content);
620                 
621                 my $message="web commit ";
622                 if (defined $session->param("name") && 
623                     length $session->param("name")) {
624                         $message.="by ".$session->param("name");
625                 }
626                 else {
627                         $message.="from $ENV{REMOTE_ADDR}";
628                 }
629                 if (defined $form->field('comments') &&
630                     length $form->field('comments')) {
631                         $message.=": ".$form->field('comments');
632                 }
633                 
634                 if ($config{rcs}) {
635                         if ($newfile) {
636                                 rcs_add($file);
637                         }
638                         # prevent deadlock with post-commit hook
639                         unlockwiki();
640                         # presumably the commit will trigger an update
641                         # of the wiki
642                         my $conflict=rcs_commit($file, $message,
643                                 $form->field("rcsinfo"));
644                 
645                         if (defined $conflict) {
646                                 $form->field(name => "rcsinfo", value => rcs_prepedit($file),
647                                         force => 1);
648                                 $form->tmpl_param("page_conflict", 1);
649                                 $form->field("editcontent", value => $conflict, force => 1);
650                                 $form->field(name => "comments", value => $form->field('comments'), force => 1);
651                                 $form->field("do", "edit)");
652                                 $form->tmpl_param("page_select", 0);
653                                 $form->field(name => "page", type => 'hidden');
654                                 $form->field(name => "type", type => 'hidden');
655                                 $form->title("editing $page");
656                                 print $form->render(submit => \@buttons);
657                                 return;
658                         }
659                 }
660                 else {
661                         require IkiWiki::Render;
662                         refresh();
663                         saveindex();
664                 }
665                 
666                 # The trailing question mark tries to avoid broken
667                 # caches and get the most recent version of the page.
668                 redirect($q, "$config{url}/".htmlpage($page)."?updated");
669         }
670 } #}}}
671
672 sub cgi () { #{{{
673         eval q{use CGI; use CGI::Session};
674         error($@) if $@;
675         
676         my $q=CGI->new;
677         
678         run_hooks(cgi => sub { shift->($q) });
679         
680         my $do=$q->param('do');
681         if (! defined $do || ! length $do) {
682                 my $error = $q->cgi_error;
683                 if ($error) {
684                         error("Request not processed: $error");
685                 }
686                 else {
687                         error("\"do\" parameter missing");
688                 }
689         }
690         
691         # Things that do not need a session.
692         if ($do eq 'recentchanges') {
693                 cgi_recentchanges($q);
694                 return;
695         }
696         elsif ($do eq 'hyperestraier') {
697                 cgi_hyperestraier();
698         }
699         
700         CGI::Session->name("ikiwiki_session_".encode_utf8($config{wikiname}));
701         
702         my $oldmask=umask(077);
703         my $session = CGI::Session->new("driver:DB_File", $q,
704                 { FileName => "$config{wikistatedir}/sessions.db" });
705         umask($oldmask);
706         
707         # Auth hooks can sign a user in.
708         if ($do ne 'signin' && ! defined $session->param("name")) {
709                 run_hooks(auth => sub {
710                         shift->($q, $session)
711                 });
712                 if (defined $session->param("name")) {
713                         # Make sure whatever user was authed is in the
714                         # userinfo db.
715                         if (! userinfo_get($session->param("name"), "regdate")) {
716                                 userinfo_setall($session->param("name"), {
717                                         email => "",
718                                         password => "",
719                                         regdate => time,
720                                 });
721                         }
722                 }
723         }
724
725         # Everything below this point needs the user to be signed in.
726         if (((! $config{anonok} || $do eq 'prefs') &&
727              (! $config{httpauth}) &&
728              (! defined $session->param("name") ||
729              ! userinfo_get($session->param("name"), "regdate")))
730             || $do eq 'signin') {
731                 cgi_signin($q, $session);
732         
733                 # Force session flush with safe umask.
734                 my $oldmask=umask(077);
735                 $session->flush;
736                 umask($oldmask);
737                 
738                 return;
739         }
740
741         if (defined $session->param("name") && userinfo_get($session->param("name"), "banned")) {
742                 print $q->header(-status => "403 Forbidden");
743                 $session->delete();
744                 print "You are banned.";
745                 exit;
746         }
747         
748         if ($do eq 'create' || $do eq 'edit') {
749                 cgi_editpage($q, $session);
750         }
751         elsif ($do eq 'prefs') {
752                 cgi_prefs($q, $session);
753         }
754         elsif ($do eq 'blog') {
755                 my $page=titlepage(decode_utf8($q->param('title')));
756                 # if the page already exists, munge it to be unique
757                 my $from=$q->param('from');
758                 my $add="";
759                 while (exists $pagecase{lc "$from/$page$add"}) {
760                         $add=1 unless length $add;
761                         $add++;
762                 }
763                 $q->param('page', $page.$add);
764                 # now run same as create
765                 $q->param('do', 'create');
766                 cgi_editpage($q, $session);
767         }
768         else {
769                 error("unknown do parameter");
770         }
771 } #}}}
772
773 1