9 use open qw{:utf8 :std};
15 if ($config{sslcookie}) {
16 print $session->header(-charset => 'utf-8',
17 -cookie => $session->cookie(-httponly => 1, -secure => 1));
19 print $session->header(-charset => 'utf-8',
20 -cookie => $session->cookie(-httponly => 1));
24 sub showform ($$$$;@) {
30 if (exists $hooks{formbuilder}) {
31 run_hooks(formbuilder => sub {
32 shift->(form => $form, cgi => $cgi, session => $session,
37 printheader($session);
38 print misctemplate($form->title, $form->render(submit => $buttons), @_);
44 my $url=URI->new(shift);
45 if (! $config{w3mmode}) {
46 print $q->redirect($url);
49 print "Content-type: text/plain\n";
50 print "W3m-control: GOTO $url\n\n";
54 sub decode_cgi_utf8 ($) {
55 # decode_form_utf8 method is needed for 5.10
58 foreach my $f ($cgi->param) {
59 $cgi->param($f, map { decode_utf8 $_ } $cgi->param($f));
64 sub decode_form_utf8 ($) {
67 foreach my $f ($form->field) {
68 $form->field(name => $f,
69 value => decode_utf8($form->field($f)),
76 # Check if the user is signed in. If not, redirect to the signin form and
77 # save their place to return to later.
82 if (! defined $session->param("name") ||
83 ! userinfo_get($session->param("name"), "regdate")) {
84 $session->param(postsignin => $ENV{QUERY_STRING});
85 cgi_signin($q, $session);
86 cgi_savesession($session);
96 eval q{use CGI::FormBuilder};
98 my $form = CGI::FormBuilder->new(
106 action => $config{cgiurl},
108 template => {type => 'div'},
109 stylesheet => baseurl()."style.css",
111 my $buttons=["Login"];
113 if ($q->param("do") ne "signin" && !$form->submitted) {
114 $form->text(gettext("You need to log in first."));
116 $form->field(name => "do", type => "hidden", value => "signin",
119 decode_form_utf8($form);
120 run_hooks(formbuilder_setup => sub {
121 shift->(form => $form, cgi => $q, session => $session,
122 buttons => $buttons);
124 decode_form_utf8($form);
126 if ($form->submitted) {
130 showform($form, $buttons, $session, $q);
133 sub cgi_postsignin ($$) {
137 # Continue with whatever was being done before the signin process.
138 if (defined $session->param("postsignin")) {
139 my $postsignin=CGI->new($session->param("postsignin"));
140 $session->clear("postsignin");
141 cgi($postsignin, $session);
142 cgi_savesession($session);
146 if ($config{sslcookie} && ! $q->https()) {
147 error(gettext("probable misconfiguration: sslcookie is set, but you are attempting to login via http, not https"));
150 error(gettext("login failed, perhaps you need to turn on cookies?"));
159 needsignin($q, $session);
162 # The session id is stored on the form and checked to
163 # guard against CSRF.
164 my $sid=$q->param('sid');
165 if (! defined $sid) {
168 elsif ($sid ne $session->id) {
169 error(gettext("Your login session has expired."));
172 eval q{use CGI::FormBuilder};
174 my $form = CGI::FormBuilder->new(
175 title => "preferences",
176 name => "preferences",
186 action => $config{cgiurl},
187 template => {type => 'div'},
188 stylesheet => baseurl()."style.css",
190 [login => gettext("Login")],
191 [preferences => gettext("Preferences")],
192 [admin => gettext("Admin")]
195 my $buttons=["Save Preferences", "Logout", "Cancel"];
197 decode_form_utf8($form);
198 run_hooks(formbuilder_setup => sub {
199 shift->(form => $form, cgi => $q, session => $session,
200 buttons => $buttons);
202 decode_form_utf8($form);
204 $form->field(name => "do", type => "hidden", value => "prefs",
206 $form->field(name => "sid", type => "hidden", value => $session->id,
208 $form->field(name => "email", size => 50, fieldset => "preferences");
210 my $user_name=$session->param("name");
212 if (! $form->submitted) {
213 $form->field(name => "email", force => 1,
214 value => userinfo_get($user_name, "email"));
217 if ($form->submitted eq 'Logout') {
219 redirect($q, $config{url});
222 elsif ($form->submitted eq 'Cancel') {
223 redirect($q, $config{url});
226 elsif ($form->submitted eq 'Save Preferences' && $form->validate) {
227 if (defined $form->field('email')) {
228 userinfo_set($user_name, 'email', $form->field('email')) ||
229 error("failed to set email");
232 $form->text(gettext("Preferences saved."));
235 showform($form, $buttons, $session, $q);
238 sub cgi_custom_failure ($$) {
245 # Internet Explod^Hrer won't show custom 404 responses
246 # unless they're >= 512 bytes
252 sub check_banned ($$) {
257 my $name=$session->param("name");
259 grep { $name eq $_ } @{$config{banned_users}}) {
263 foreach my $b (@{$config{banned_users}}) {
264 if (pagespec_match("", $b,
265 ip => $ENV{REMOTE_ADDR},
266 name => defined $name ? $name : "",
275 cgi_savesession($session);
277 $q->header(-status => "403 Forbidden"),
278 gettext("You are banned."));
282 sub cgi_getsession ($) {
285 eval q{use CGI::Session; use HTML::Entities};
287 CGI::Session->name("ikiwiki_session_".encode_entities($config{wikiname}));
289 my $oldmask=umask(077);
291 CGI::Session->new("driver:DB_File", $q,
292 { FileName => "$config{wikistatedir}/sessions.db" })
294 if (! $session || $@) {
295 error($@." ".CGI::Session->errstr());
303 # To guard against CSRF, the user's session id (sid)
304 # can be stored on a form. This function will check
305 # (for logged in users) that the sid on the form matches
306 # the session id in the cookie.
307 sub checksessionexpiry ($$) {
311 if (defined $session->param("name")) {
312 my $sid=$q->param('sid');
313 if (! defined $sid || $sid ne $session->id) {
314 error(gettext("Your login session has expired."));
319 sub cgi_savesession ($) {
322 # Force session flush with safe umask.
323 my $oldmask=umask(077);
334 $CGI::DISABLE_UPLOADS=$config{cgi_disable_uploads};
339 binmode(STDIN, ":utf8");
341 run_hooks(cgi => sub { shift->($q) });
344 my $do=$q->param('do');
345 if (! defined $do || ! length $do) {
346 my $error = $q->cgi_error;
348 error("Request not processed: $error");
351 error("\"do\" parameter missing");
355 # Need to lock the wiki before getting a session.
360 $session=cgi_getsession($q);
363 # Auth hooks can sign a user in.
364 if ($do ne 'signin' && ! defined $session->param("name")) {
365 run_hooks(auth => sub {
366 shift->($q, $session)
368 if (defined $session->param("name")) {
369 # Make sure whatever user was authed is in the
371 if (! userinfo_get($session->param("name"), "regdate")) {
372 userinfo_setall($session->param("name"), {
376 }) || error("failed adding user");
381 check_banned($q, $session);
383 run_hooks(sessioncgi => sub { shift->($q, $session) });
385 if ($do eq 'signin') {
386 cgi_signin($q, $session);
387 cgi_savesession($session);
389 elsif ($do eq 'prefs') {
390 cgi_prefs($q, $session);
392 elsif (defined $session->param("postsignin") || $do eq 'postsignin') {
393 cgi_postsignin($q, $session);
396 error("unknown do parameter");
400 # Does not need to be called directly; all errors will go through here.
404 print "Content-type: text/html\n\n";
405 print misctemplate(gettext("Error"),
406 "<p class=\"error\">".gettext("Error").": $message</p>");