X-Git-Url: https://sipb.mit.edu/gitweb.cgi/ikiwiki.git/blobdiff_plain/35ee7e44a62f9126a83c1243b549d47cc5ca7b43..7cfdb888e5cba93b05b1948e511c467bfa04033a:/IkiWiki/CGI.pm diff --git a/IkiWiki/CGI.pm b/IkiWiki/CGI.pm index 6b5a1e130..53237bcdb 100644 --- a/IkiWiki/CGI.pm +++ b/IkiWiki/CGI.pm @@ -85,7 +85,16 @@ sub cgi_recentchanges ($) { #{{{ my $changelog=[rcs_recentchanges(100)]; foreach my $change (@$changelog) { $change->{when} = concise(ago($change->{when})); - $change->{user} = htmllink("", "", escapeHTML($change->{user}), 1); + + if ($change->{user} =~ m!^https?://! && + eval q{use Net::OpenID::VerifiedIdentity; 1} && !$@) { + # Munge user-urls, as used by eg, OpenID. + my $oid=Net::OpenID::VerifiedIdentity->new(identity => $change->{user}); + $change->{user} = "{user}."\">".escapeHTML($oid->display).""; + } + else { + $change->{user} = htmllink("", "", escapeHTML($change->{user}), 1); + } my $is_excess = exists $change->{pages}[10]; # limit pages to first 10 delete @{$change->{pages}}[10 .. @{$change->{pages}}] if $is_excess; @@ -120,7 +129,7 @@ sub cgi_signin ($$) { #{{{ error($@) if $@; my $form = CGI::FormBuilder->new( title => "signin", - fields => [qw(do title page subpage from name password)], + fields => [qw(do name password openid_url)], header => 1, charset => "utf-8", method => 'POST', @@ -142,39 +151,63 @@ sub cgi_signin ($$) { #{{{ decode_form_utf8($form); - $form->field(name => "name", required => 0); + $form->field(name => "name", required => 0, size => 30); $form->field(name => "do", type => "hidden"); - $form->field(name => "page", type => "hidden"); - $form->field(name => "title", type => "hidden"); - $form->field(name => "from", type => "hidden"); - $form->field(name => "subpage", type => "hidden"); $form->field(name => "password", type => "password", required => 0); + if ($config{openid}) { + $form->field(name => "openid_url", label => "OpenID", size => 30, + comment => '('. + htmllink("", "", "OpenID", 1, 0, "What's this?") + .($config{openidsignup} ? " | Get an OpenID" : "") + .')'); + } + else { + $form->field(name => "openid_url", type => "hidden"); + } if ($form->submitted eq "Register" || $form->submitted eq "Create Account") { $form->title("register"); $form->text(""); - $form->fields(qw(do title page subpage from name password confirm_password email)); + $form->fields(qw(do name password confirm_password email)); $form->field(name => "confirm_password", type => "password"); $form->field(name => "email", type => "text"); + $form->field(name => "openid_url", type => "hidden"); } if ($q->param("do") ne "signin" && !$form->submitted) { $form->text("You need to log in first."); } if ($form->submitted) { + my $submittype=$form->submitted; + # OpenID login uses the Login button, but validates + # differently. + if ($submittype eq "Login" && $config{openid} && + length $form->field("openid_url")) { + $submittype="OpenID"; + + $form->field( + name => "openid_url", + validate => sub { + # FIXME: ugh + IkiWiki::Plugin::openid::validate($q, $session, shift, $form); + }, + ); + } + # Set required fields based on how form was submitted. my %required=( "Login" => [qw(name password)], "Register" => [], "Create Account" => [qw(name password confirm_password email)], "Mail Password" => [qw(name)], + "OpenID" => [qw(openid_url)], ); - foreach my $opt (@{$required{$form->submitted}}) { + foreach my $opt (@{$required{$submittype}}) { $form->field(name => $opt, required => 1); } # Validate password differently depending on how # form was submitted. - if ($form->submitted eq 'Login') { + if ($submittype eq 'Login') { $form->field( name => "password", validate => sub { @@ -184,13 +217,13 @@ sub cgi_signin ($$) { #{{{ ); $form->field(name => "name", validate => '/^\w+$/'); } - else { + elsif ($submittype ne 'OpenID') { $form->field(name => "password", validate => 'VALUE'); } # And make sure the entered name exists when logging # in or sending email, and does not when registering. - if ($form->submitted eq 'Create Account' || - $form->submitted eq 'Register') { + if ($submittype eq 'Create Account' || + $submittype eq 'Register') { $form->field( name => "name", validate => sub { @@ -201,7 +234,7 @@ sub cgi_signin ($$) { #{{{ }, ); } - else { + elsif ($submittype ne 'OpenID') { $form->field( name => "name", validate => sub { @@ -223,19 +256,7 @@ sub cgi_signin ($$) { #{{{ if ($form->submitted && $form->validate) { if ($form->submitted eq 'Login') { $session->param("name", $form->field("name")); - if (defined $form->field("do") && - $form->field("do") ne 'signin') { - redirect($q, cgiurl( - do => $form->field("do"), - page => $form->field("page"), - title => $form->field("title"), - subpage => $form->field("subpage"), - from => $form->field("from"), - )); - } - else { - redirect($q, $config{url}); - } + cgi_postsignin($q, $session); } elsif ($form->submitted eq 'Create Account') { my $user_name=$form->field('name'); @@ -294,6 +315,23 @@ sub cgi_signin ($$) { #{{{ } } #}}} +sub cgi_postsignin ($$) { #{{{ + my $q=shift; + my $session=shift; + + # Continue with whatever was being done before the signin process. + if (defined $q->param("do") && $q->param("do") ne "signin" && + defined $session->param("postsignin")) { + my $postsignin=CGI->new($session->param("postsignin")); + $session->clear("postsignin"); + cgi($postsignin, $session); + exit; + } + else { + redirect($q, $config{url}); + } +} #}}} + sub cgi_prefs ($$) { #{{{ my $q=shift; my $session=shift; @@ -326,7 +364,7 @@ sub cgi_prefs ($$) { #{{{ my $user_name=$session->param("name"); $form->field(name => "do", type => "hidden"); $form->field(name => "name", disabled => 1, - value => $user_name, force => 1); + value => $user_name, force => 1, size => 30); $form->field(name => "password", type => "password"); $form->field(name => "confirm_password", type => "password"); $form->field(name => "subscriptions", size => 50, @@ -645,14 +683,19 @@ sub cgi_editpage ($$) { #{{{ } } #}}} -sub cgi () { #{{{ - eval q{use CGI; use CGI::Session}; - error($@) if $@; - - my $q=CGI->new; +sub cgi (;$$) { #{{{ + my $q=shift; + my $session=shift; + + if (! $q) { + eval q{use CGI; use CGI::Session}; + error($@) if $@; - run_hooks(cgi => sub { shift->($q) }); + $q=CGI->new; + run_hooks(cgi => sub { shift->($q) }); + } + my $do=$q->param('do'); if (! defined $do || ! length $do) { my $error = $q->cgi_error; @@ -673,18 +716,41 @@ sub cgi () { #{{{ cgi_hyperestraier(); } - CGI::Session->name("ikiwiki_session_".encode_utf8($config{wikiname})); + if (! $session) { + 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" }); - umask($oldmask); + my $oldmask=umask(077); + $session = CGI::Session->new("driver:DB_File", $q, + { FileName => "$config{wikistatedir}/sessions.db" }); + umask($oldmask); + } + # Auth hooks can sign a user in. + if ($do ne 'signin' && ! defined $session->param("name")) { + run_hooks(auth => sub { + shift->($q, $session) + }); + if (defined $session->param("name")) { + # Make sure whatever user was authed is in the + # userinfo db. + if (! userinfo_get($session->param("name"), "regdate")) { + userinfo_setall($session->param("name"), { + email => "", + password => "", + regdate => time, + }); + } + } + } + # Everything below this point needs the user to be signed in. if (((! $config{anonok} || $do eq 'prefs') && - (! $config{httpauth}) && (! defined $session->param("name") || - ! userinfo_get($session->param("name"), "regdate"))) || $do eq 'signin') { + ! userinfo_get($session->param("name"), "regdate"))) + || $do eq 'signin') { + if ($do ne 'signin' && ! defined $session->param("postsignin")) { + $session->param(postsignin => $ENV{QUERY_STRING}); + } cgi_signin($q, $session); # Force session flush with safe umask. @@ -694,24 +760,11 @@ sub cgi () { #{{{ return; } - - if ($config{httpauth} && (! defined $session->param("name"))) { - if (! defined $q->remote_user()) { - error("Could not determine authenticated username."); - } - else { - $session->param("name", $q->remote_user()); - if (! userinfo_get($session->param("name"), "regdate")) { - userinfo_setall($session->param("name"), { - email => "", - password => "", - regdate=>time, - }); - } - } + elsif (defined $session->param("postsignin")) { + cgi_postsignin($q, $session); } - if (userinfo_get($session->param("name"), "banned")) { + if (defined $session->param("name") && userinfo_get($session->param("name"), "banned")) { print $q->header(-status => "403 Forbidden"); $session->delete(); print "You are banned.";