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));
20 print $session->header(-charset => 'utf-8',
21 -cookie => $session->cookie(-httponly => 1));
25 sub showform ($$$$;@) {
31 if (exists $hooks{formbuilder}) {
32 run_hooks(formbuilder => sub {
33 shift->(form => $form, cgi => $cgi, session => $session,
38 printheader($session);
39 print misctemplate($form->title, $form->render(submit => $buttons), @_);
45 my $url=URI->new(shift);
46 if (! $config{w3mmode}) {
47 print $q->redirect($url);
50 print "Content-type: text/plain\n";
51 print "W3m-control: GOTO $url\n\n";
55 sub decode_cgi_utf8 ($) {
56 # decode_form_utf8 method is needed for 5.01
59 foreach my $f ($cgi->param) {
60 $cgi->param($f, map { decode_utf8 $_ } $cgi->param($f));
65 sub decode_form_utf8 ($) {
68 foreach my $f ($form->field) {
69 my @value=map { decode_utf8($_) } $form->field($f);
70 $form->field(name => $f,
78 # Check if the user is signed in. If not, redirect to the signin form and
79 # save their place to return to later.
84 if (! defined $session->param("name") ||
85 ! userinfo_get($session->param("name"), "regdate")) {
86 $session->param(postsignin => $ENV{QUERY_STRING});
87 cgi_signin($q, $session);
88 cgi_savesession($session);
98 eval q{use CGI::FormBuilder};
100 my $form = CGI::FormBuilder->new(
108 action => $config{cgiurl},
110 template => {type => 'div'},
111 stylesheet => baseurl()."style.css",
113 # MITLOGIN: These should be restored when logins are allowed again.
114 #my $buttons=["Login"];
117 if ($q->param("do") ne "signin" && !$form->submitted) {
118 #$form->text(gettext("You need to log in first."));
120 "You must have an MIT personal certificate to edit");
122 $form->field(name => "do", type => "hidden", value => "signin",
125 decode_form_utf8($form);
126 run_hooks(formbuilder_setup => sub {
127 shift->(form => $form, cgi => $q, session => $session,
128 buttons => $buttons);
130 decode_form_utf8($form);
132 if ($form->submitted) {
136 showform($form, $buttons, $session, $q);
139 sub cgi_postsignin ($$) {
143 # Continue with whatever was being done before the signin process.
144 if (defined $session->param("postsignin")) {
145 my $postsignin=CGI->new($session->param("postsignin"));
146 $session->clear("postsignin");
147 cgi($postsignin, $session);
148 cgi_savesession($session);
152 if ($config{sslcookie} && ! $q->https()) {
153 error(gettext("probable misconfiguration: sslcookie is set, but you are attempting to login via http, not https"));
156 error(gettext("login failed, perhaps you need to turn on cookies?"));
165 needsignin($q, $session);
168 # The session id is stored on the form and checked to
169 # guard against CSRF.
170 my $sid=$q->param('sid');
171 if (! defined $sid) {
174 elsif ($sid ne $session->id) {
175 error(gettext("Your login session has expired."));
178 eval q{use CGI::FormBuilder};
180 my $form = CGI::FormBuilder->new(
181 title => "preferences",
182 name => "preferences",
192 action => $config{cgiurl},
193 template => {type => 'div'},
194 stylesheet => baseurl()."style.css",
196 [login => gettext("Login")],
197 [preferences => gettext("Preferences")],
198 [admin => gettext("Admin")]
201 my $buttons=["Save Preferences", "Logout", "Cancel"];
203 decode_form_utf8($form);
204 run_hooks(formbuilder_setup => sub {
205 shift->(form => $form, cgi => $q, session => $session,
206 buttons => $buttons);
208 decode_form_utf8($form);
210 $form->field(name => "do", type => "hidden", value => "prefs",
212 $form->field(name => "sid", type => "hidden", value => $session->id,
214 #$form->field(name => "email", size => 50, fieldset => "preferences");
215 $form->field(name => "realname", size => 50, fieldset => "preferences");
217 my $user_name=$session->param("name");
219 if (! $form->submitted) {
220 #$form->field(name => "email", force => 1,
221 #value => userinfo_get($user_name, "email"));
222 $form->field(name => "realname", force => 1,
223 value => userinfo_get($user_name, "realname"));
226 if ($form->submitted eq 'Logout') {
228 redirect($q, $config{url});
231 elsif ($form->submitted eq 'Cancel') {
232 redirect($q, $config{url});
235 elsif ($form->submitted eq 'Save Preferences' && $form->validate) {
236 if (defined $form->field('email')) {
237 userinfo_set($user_name, 'email', $form->field('email')) ||
238 error("failed to set email");
240 if (defined $form->field('realname')) {
241 userinfo_set($user_name, 'realname', $form->field('realname')) ||
242 error("failed to set realname");
244 $form->text(gettext("Preferences saved."));
247 showform($form, $buttons, $session, $q);
250 sub cgi_custom_failure ($$$) {
252 my $httpstatus=shift;
256 -status => $httpstatus,
261 # Internet Explod^Hrer won't show custom 404 responses
262 # unless they're >= 512 bytes
268 sub check_banned ($$) {
273 my $name=$session->param("name");
275 grep { $name eq $_ } @{$config{banned_users}}) {
279 foreach my $b (@{$config{banned_users}}) {
280 if (pagespec_match("", $b,
281 ip => $ENV{REMOTE_ADDR},
282 name => defined $name ? $name : "",
291 cgi_savesession($session);
294 gettext("You are banned."));
298 sub cgi_getsession ($) {
301 eval q{use CGI::Session; use HTML::Entities};
303 CGI::Session->name("ikiwiki_session_".encode_entities($config{wikiname}));
305 my $oldmask=umask(077);
307 CGI::Session->new("driver:DB_File", $q,
308 { FileName => "$config{wikistatedir}/sessions.db" })
310 if (! $session || $@) {
311 error($@." ".CGI::Session->errstr());
319 # To guard against CSRF, the user's session id (sid)
320 # can be stored on a form. This function will check
321 # (for logged in users) that the sid on the form matches
322 # the session id in the cookie.
323 sub checksessionexpiry ($$) {
327 if (defined $session->param("name")) {
328 my $sid=$q->param('sid');
329 if (! defined $sid || $sid ne $session->id) {
330 error(gettext("Your login session has expired."));
335 sub cgi_savesession ($) {
338 # Force session flush with safe umask.
339 my $oldmask=umask(077);
350 $CGI::DISABLE_UPLOADS=$config{cgi_disable_uploads};
355 binmode(STDIN, ":utf8");
357 run_hooks(cgi => sub { shift->($q) });
360 my $do=$q->param('do');
361 if (! defined $do || ! length $do) {
362 my $error = $q->cgi_error;
364 error("Request not processed: $error");
367 error("\"do\" parameter missing");
371 # Need to lock the wiki before getting a session.
376 $session=cgi_getsession($q);
379 # Auth hooks can sign a user in.
380 if ($do ne 'signin' && ! defined $session->param("name")) {
381 run_hooks(auth => sub {
382 shift->($q, $session)
384 if (defined $session->param("name")) {
385 # Make sure whatever user was authed is in the
387 if (! userinfo_get($session->param("name"), "regdate")) {
388 userinfo_setall($session->param("name"), {
392 }) || error("failed adding user");
397 check_banned($q, $session);
399 run_hooks(sessioncgi => sub { shift->($q, $session) });
401 if ($do eq 'signin') {
402 cgi_signin($q, $session);
403 cgi_savesession($session);
405 elsif ($do eq 'prefs') {
406 cgi_prefs($q, $session);
408 elsif (defined $session->param("postsignin") || $do eq 'postsignin') {
409 cgi_postsignin($q, $session);
412 error("unknown do parameter");
416 # Does not need to be called directly; all errors will go through here.
420 print "Content-type: text/html\n\n";
421 print misctemplate(gettext("Error"),
422 "<p class=\"error\">".gettext("Error").": $message</p>");