8 sub page_locked ($$;$) { #{{{
13 my $user=$session->param("name");
14 return if length $user && is_admin($user);
16 foreach my $admin (@{$config{adminuser}}) {
17 my $locked_pages=userinfo_get($admin, "locked_pages");
18 if (globlist_match($page, userinfo_get($admin, "locked_pages"))) {
19 return 1 if $nonfatal;
20 error(htmllink("", $page, 1)." is locked by ".
21 htmllink("", $admin, 1)." and cannot be edited.");
28 sub cgi_recentchanges ($) { #{{{
31 my $template=HTML::Template->new(
32 filename => "$config{templatedir}/recentchanges.tmpl"
35 title => "RecentChanges",
36 indexlink => indexlink(),
37 wikiname => $config{wikiname},
38 changelog => [rcs_recentchanges(100)],
40 print $q->header, $template->output;
43 sub cgi_signin ($$) { #{{{
47 eval q{use CGI::FormBuilder};
48 my $form = CGI::FormBuilder->new(
50 fields => [qw(do title page subpage from name password confirm_password email)],
55 perl => q{eq $form->field("password")},
62 action => $q->request_uri,
64 template => (-e "$config{templatedir}/signin.tmpl" ?
65 "$config{templatedir}/signin.tmpl" : "")
68 $form->field(name => "name", required => 0);
69 $form->field(name => "do", type => "hidden");
70 $form->field(name => "page", type => "hidden");
71 $form->field(name => "title", type => "hidden");
72 $form->field(name => "from", type => "hidden");
73 $form->field(name => "subpage", type => "hidden");
74 $form->field(name => "password", type => "password", required => 0);
75 $form->field(name => "confirm_password", type => "password", required => 0);
76 $form->field(name => "email", required => 0);
77 if ($q->param("do") ne "signin") {
78 $form->text("You need to log in first.");
81 if ($form->submitted) {
82 # Set required fields based on how form was submitted.
84 "Login" => [qw(name password)],
85 "Register" => [qw(name password confirm_password email)],
86 "Mail Password" => [qw(name)],
88 foreach my $opt (@{$required{$form->submitted}}) {
89 $form->field(name => $opt, required => 1);
92 # Validate password differently depending on how
94 if ($form->submitted eq 'Login') {
98 length $form->field("name") &&
99 shift eq userinfo_get($form->field("name"), 'password');
102 $form->field(name => "name", validate => '/^\w+$/');
105 $form->field(name => "password", validate => 'VALUE');
107 # And make sure the entered name exists when logging
108 # in or sending email, and does not when registering.
109 if ($form->submitted eq 'Register') {
115 ! userinfo_get($name, "regdate");
125 userinfo_get($name, "regdate");
131 # First time settings.
132 $form->field(name => "name", comment => "use FirstnameLastName");
133 $form->field(name => "confirm_password", comment => "(only needed");
134 $form->field(name => "email", comment => "for registration)");
135 if ($session->param("name")) {
136 $form->field(name => "name", value => $session->param("name"));
140 if ($form->submitted && $form->validate) {
141 if ($form->submitted eq 'Login') {
142 $session->param("name", $form->field("name"));
143 if (defined $form->field("do") &&
144 $form->field("do") ne 'signin') {
146 "$config{cgiurl}?do=".$form->field("do").
147 "&page=".$form->field("page").
148 "&title=".$form->field("title").
149 "&subpage=".$form->field("subpage").
150 "&from=".$form->field("from"));;
153 print $q->redirect($config{url});
156 elsif ($form->submitted eq 'Register') {
157 my $user_name=$form->field('name');
158 if (userinfo_setall($user_name, {
159 'email' => $form->field('email'),
160 'password' => $form->field('password'),
163 $form->field(name => "confirm_password", type => "hidden");
164 $form->field(name => "email", type => "hidden");
165 $form->text("Registration successful. Now you can Login.");
166 print $session->header();
167 print misctemplate($form->title, $form->render(submit => ["Login"]));
170 error("Error saving registration.");
173 elsif ($form->submitted eq 'Mail Password') {
174 my $user_name=$form->field("name");
175 my $template=HTML::Template->new(
176 filename => "$config{templatedir}/passwordmail.tmpl"
179 user_name => $user_name,
180 user_password => userinfo_get($user_name, "password"),
181 wikiurl => $config{url},
182 wikiname => $config{wikiname},
183 REMOTE_ADDR => $ENV{REMOTE_ADDR},
186 eval q{use Mail::Sendmail};
187 my ($fromhost) = $config{cgiurl} =~ m!/([^/]+)!;
189 To => userinfo_get($user_name, "email"),
190 From => "$config{wikiname} admin <".(getpwuid($>))[0]."@".$fromhost.">",
191 Subject => "$config{wikiname} information",
192 Message => $template->output,
193 ) or error("Failed to send mail");
195 $form->text("Your password has been emailed to you.");
196 $form->field(name => "name", required => 0);
197 print $session->header();
198 print misctemplate($form->title, $form->render(submit => ["Login", "Register", "Mail Password"]));
202 print $session->header();
203 print misctemplate($form->title, $form->render(submit => ["Login", "Register", "Mail Password"]));
207 sub cgi_prefs ($$) { #{{{
211 eval q{use CGI::FormBuilder};
212 my $form = CGI::FormBuilder->new(
213 title => "preferences",
214 fields => [qw(do name password confirm_password email locked_pages)],
218 confirm_password => {
219 perl => q{eq $form->field("password")},
226 action => $q->request_uri,
227 template => (-e "$config{templatedir}/prefs.tmpl" ?
228 "$config{templatedir}/prefs.tmpl" : "")
230 my @buttons=("Save Preferences", "Logout", "Cancel");
232 my $user_name=$session->param("name");
233 $form->field(name => "do", type => "hidden");
234 $form->field(name => "name", disabled => 1,
235 value => $user_name, force => 1);
236 $form->field(name => "password", type => "password");
237 $form->field(name => "confirm_password", type => "password");
238 $form->field(name => "locked_pages", size => 50,
239 comment => "(".htmllink("", "GlobList", 1).")");
241 if (! is_admin($user_name)) {
242 $form->field(name => "locked_pages", type => "hidden");
245 if (! $form->submitted) {
246 $form->field(name => "email", force => 1,
247 value => userinfo_get($user_name, "email"));
248 $form->field(name => "locked_pages", force => 1,
249 value => userinfo_get($user_name, "locked_pages"));
252 if ($form->submitted eq 'Logout') {
254 print $q->redirect($config{url});
257 elsif ($form->submitted eq 'Cancel') {
258 print $q->redirect($config{url});
261 elsif ($form->submitted eq "Save Preferences" && $form->validate) {
262 foreach my $field (qw(password email locked_pages)) {
263 if (length $form->field($field)) {
264 userinfo_set($user_name, $field, $form->field($field)) || error("failed to set $field");
267 $form->text("Preferences saved.");
270 print $session->header();
271 print misctemplate($form->title, $form->render(submit => \@buttons));
274 sub cgi_editpage ($$) { #{{{
278 eval q{use CGI::FormBuilder};
279 my $form = CGI::FormBuilder->new(
280 fields => [qw(do rcsinfo subpage from page content comments)],
286 required => [qw{content}],
289 action => $q->request_uri,
291 template => "$config{templatedir}/editpage.tmpl"
293 my @buttons=("Save Page", "Preview", "Cancel");
295 my ($page)=$form->param('page')=~/$config{wiki_file_regexp}/;
296 if (! defined $page || ! length $page || $page ne $q->param('page') ||
297 $page=~/$config{wiki_file_prune_regexp}/ || $page=~/^\//) {
298 error("bad page name");
302 my $file=$page.$config{default_pageext};
304 if (exists $pagesources{lc($page)}) {
305 $file=$pagesources{lc($page)};
309 $form->field(name => "do", type => 'hidden');
310 $form->field(name => "from", type => 'hidden');
311 $form->field(name => "rcsinfo", type => 'hidden');
312 $form->field(name => "subpage", type => 'hidden');
313 $form->field(name => "page", value => "$page", force => 1);
314 $form->field(name => "comments", type => "text", size => 80);
315 $form->field(name => "content", type => "textarea", rows => 20,
317 $form->tmpl_param("can_commit", $config{rcs});
318 $form->tmpl_param("indexlink", indexlink());
319 $form->tmpl_param("helponformattinglink",
320 htmllink("", "HelpOnFormatting", 1));
321 if (! $form->submitted) {
322 $form->field(name => "rcsinfo", value => rcs_prepedit($file),
326 if ($form->submitted eq "Cancel") {
327 print $q->redirect("$config{url}/".htmlpage($page));
330 elsif ($form->submitted eq "Preview") {
331 require IkiWiki::Render;
332 $form->tmpl_param("page_preview",
333 htmlize($config{default_pageext},
334 linkify($form->field('content'), $page)));
337 $form->tmpl_param("page_preview", "");
339 $form->tmpl_param("page_conflict", "");
341 if (! $form->submitted || $form->submitted eq "Preview" ||
343 if ($form->field("do") eq "create") {
344 if (exists $pagesources{lc($page)}) {
345 # hmm, someone else made the page in the
347 print $q->redirect("$config{url}/".htmlpage($page));
353 my ($from)=$form->param('from')=~/$config{wiki_file_regexp}/;
354 if (! defined $from || ! length $from ||
355 $from ne $form->param('from') ||
356 $from=~/$config{wiki_file_prune_regexp}/ || $from=~/^\//) {
357 @page_locs=$best_loc=$page;
363 if (length $form->param('subpage') ||
364 $page eq 'discussion') {
365 $best_loc="$from/$page";
368 $best_loc=$dir.$page;
371 push @page_locs, $dir.$page;
372 push @page_locs, "$from/$page";
373 while (length $dir) {
375 push @page_locs, $dir.$page;
379 ! exists $pagesources{lc($_)} &&
380 ! page_locked($_, $session, 1)
384 $form->tmpl_param("page_select", 1);
385 $form->field(name => "page", type => 'select',
386 options => \@page_locs, value => $best_loc);
387 $form->title("creating ".pagetitle($page));
389 elsif ($form->field("do") eq "edit") {
390 page_locked($page, $session);
391 if (! defined $form->field('content') ||
392 ! length $form->field('content')) {
394 if (exists $pagesources{lc($page)}) {
395 $content=readfile("$config{srcdir}/$pagesources{lc($page)}");
396 $content=~s/\n/\r\n/g;
398 $form->field(name => "content", value => $content,
401 $form->tmpl_param("page_select", 0);
402 $form->field(name => "page", type => 'hidden');
403 $form->title("editing ".pagetitle($page));
406 print $form->render(submit => \@buttons);
410 page_locked($page, $session);
412 my $content=$form->field('content');
413 $content=~s/\r\n/\n/g;
415 writefile("$config{srcdir}/$file", $content);
417 my $message="web commit ";
418 if (length $session->param("name")) {
419 $message.="by ".$session->param("name");
422 $message.="from $ENV{REMOTE_ADDR}";
424 if (defined $form->field('comments') &&
425 length $form->field('comments')) {
426 $message.=": ".$form->field('comments');
433 # prevent deadlock with post-commit hook
435 # presumably the commit will trigger an update
437 my $conflict=rcs_commit($file, $message,
438 $form->field("rcsinfo"));
440 if (defined $conflict) {
441 $form->field(name => "rcsinfo", value => rcs_prepedit($file),
443 $form->tmpl_param("page_conflict", 1);
444 $form->field("content", value => $conflict, force => 1);
445 $form->field("do", "edit)");
446 $form->tmpl_param("page_select", 0);
447 $form->field(name => "page", type => 'hidden');
448 $form->title("editing $page");
449 print $form->render(submit => \@buttons);
454 require IkiWiki::Render;
459 # The trailing question mark tries to avoid broken
460 # caches and get the most recent version of the page.
461 print $q->redirect("$config{url}/".htmlpage($page)."?updated");
467 eval q{use CGI::Session};
471 my $do=$q->param('do');
472 if (! defined $do || ! length $do) {
473 error("\"do\" parameter missing");
476 # Things that do not need a session.
477 if ($do eq 'recentchanges') {
478 cgi_recentchanges($q);
482 CGI::Session->name("ikiwiki_session");
484 my $oldmask=umask(077);
485 my $session = CGI::Session->new("driver:db_file", $q,
486 { FileName => "$config{wikistatedir}/sessions.db" });
489 # Everything below this point needs the user to be signed in.
490 if ((! $config{anonok} && ! defined $session->param("name") ||
491 ! defined $session->param("name") ||
492 ! userinfo_get($session->param("name"), "regdate")) || $do eq 'signin') {
493 cgi_signin($q, $session);
495 # Force session flush with safe umask.
496 my $oldmask=umask(077);
503 if ($do eq 'create' || $do eq 'edit') {
504 cgi_editpage($q, $session);
506 elsif ($do eq 'prefs') {
507 cgi_prefs($q, $session);
509 elsif ($do eq 'blog') {
510 # munge page name to be valid, no matter what freeform text
512 my $page=lc($q->param('title'));
514 $page=~s/([^-A-Za-z0-9_:+])/"__".ord($1)."__"/eg;
515 # if the page already exist, munge it to be unique
516 my $from=$q->param('from');
518 while (exists $oldpagemtime{"$from/$page$add"}) {
519 $add=1 unless length $add;
522 $q->param('page', $page.$add);
523 # now run same as create
524 $q->param('do', 'create');
525 cgi_editpage($q, $session);
528 error("unknown do parameter");