]> sipb.mit.edu Git - ikiwiki.git/blob - IkiWiki/Plugin/remove.pm
e56a4a99c36d43043ca9608e5a4ac3e5962b0522
[ikiwiki.git] / IkiWiki / Plugin / remove.pm
1 #!/usr/bin/perl
2 package IkiWiki::Plugin::remove;
3
4 use warnings;
5 use strict;
6 use IkiWiki 2.00;
7
8 sub import { #{{{
9         hook(type => "formbuilder_setup", id => "remove", call => \&formbuilder_setup);
10         hook(type => "formbuilder", id => "remove", call => \&formbuilder);
11         hook(type => "sessioncgi", id => "remove", call => \&sessioncgi);
12
13 } # }}}
14
15 sub formbuilder_setup (@) { #{{{
16         my %params=@_;
17         my $form=$params{form};
18         my $q=$params{cgi};
19
20         if (defined $form->field("do") && $form->field("do") eq "edit") {
21                 # Removal button for the page, and also for attachments.
22                 push @{$params{buttons}}, "Remove";
23                 $form->tmpl_param("field-remove" => '<input name="_submit" type="submit" value="Remove Attachments" />');
24         }
25 } #}}}
26
27 sub confirmation_form ($$) { #{{{ 
28         my $q=shift;
29         my $session=shift;
30
31         eval q{use CGI::FormBuilder};
32         error($@) if $@;
33         my @fields=qw(do page);
34         my $f = CGI::FormBuilder->new(
35                 name => "remove",
36                 header => 0,
37                 charset => "utf-8",
38                 method => 'POST',
39                 javascript => 0,
40                 params => $q,
41                 action => $config{cgiurl},
42                 stylesheet => IkiWiki::baseurl()."style.css",
43                 fields => \@fields,
44         );
45         
46         $f->field(name => "do", type => "hidden", value => "remove", force => 1);
47
48         return $f, ["Remove", "Cancel"];
49 } #}}}
50
51 sub removal_confirm ($$@) {
52         my $q=shift;
53         my $session=shift;
54         my $attachment=shift;
55         my @pages=@_;
56
57         # Save current form state to allow returning to it later
58         # without losing any edits.
59         # (But don't save what button was submitted, to avoid
60         # looping back to here.)
61         # Note: "_submit" is CGI::FormBuilder internals.
62         $q->param(-name => "_submit", -value => "");
63         $session->param(postremove => scalar $q->Vars);
64         IkiWiki::cgi_savesession($session);
65         
66         my ($f, $buttons)=confirmation_form($q, $session);
67         $f->title(sprintf(gettext("confirm removal of %s"),
68                 join(", ", map { IkiWiki::pagetitle($_) } @pages)));
69         $f->field(name => "page", type => "hidden", value => \@pages, force => 1);
70         if (defined $attachment) {
71                 $f->field(name => "attachment", type => "hidden",
72                         value => $attachment, force => 1);
73         }
74
75         IkiWiki::showform($f, $buttons, $session, $q);
76         exit 0;
77 }
78
79 sub postremove ($) {
80         my $session=shift;
81
82         # Load saved form state and return to edit form.
83         my $postremove=CGI->new($session->param("postremove"));
84         $session->clear("postremove");
85         IkiWiki::cgi_savesession($session);
86         IkiWiki::cgi($postremove, $session);
87 }
88
89 sub formbuilder (@) { #{{{
90         my %params=@_;
91         my $form=$params{form};
92
93         if (defined $form->field("do") && $form->field("do") eq "edit") {
94                 my $q=$params{cgi};
95                 my $session=$params{session};
96
97                 if ($form->submitted eq "Remove") {
98                         removal_confirm($q, $session, 0, $form->field("page"));
99                 }
100                 elsif ($form->submitted eq "Remove Attachments") {
101                         removal_confirm($q, $session, 1, $q->param("attachment_select"));
102                 }
103         }
104 } #}}}
105
106 sub sessioncgi ($$) { #{{{
107         my $q=shift;
108
109         if ($q->param("do") eq 'remove') {
110                 my $session=shift;
111                 my ($form, $buttons)=confirmation_form($q, $session);
112                 IkiWiki::decode_form_utf8($form);
113
114                 if ($form->submitted eq 'Cancel') {
115                         postremove($session);
116                 }
117                 elsif ($form->submitted eq 'Remove' && $form->validate) {
118                         my @pages=$q->param("page");
119                         my @files = map { $pagesources{$_} } @pages;
120         
121                         # Validate removal by checking that the page exists,
122                         # and that the user is allowed to edit(/remove) it.
123                         my @files;
124                         foreach my $page (@pages) {
125                                 if (! exists $pagesources{$page}) {
126                                         error(sprintf(gettext("%s does not exist"),
127                                         htmllink("", "", $page, noimageinline => 1)));
128                                 }
129                                 IkiWiki::check_canedit($page, $q, $session);
130
131                                 my $file=$pagesources{$_};
132                                 if (! -e "$config{srcdir}/$file") {
133                                         error(sprintf(gettext("%s is not in the srcdir, so it cannot be deleted"), $file));
134                                 }
135                                 elsif (! -f "$config{srcdir}/$file") {
136                                         error(sprintf(gettext("%s is not a file"), $file));
137                                 }
138
139                                 # This untaint is safe because we've
140                                 # verified the file is a known source file,
141                                 # and is in the srcdir, and is a regular
142                                 # file.
143                                 push @files, possibly_foolish_untaint($file);
144                         }
145
146                         # Do removal, and update the wiki.
147                         require IkiWiki::Render;
148                         if ($config{rcs}) {
149                                 IkiWiki::disable_commit_hook();
150                                 foreach my $file (@files) {
151                                         my $token=IkiWiki::rcs_prepedit($file);
152                                         IkiWiki::rcs_remove($file);
153                                         IkiWiki::rcs_commit($file, gettext("removed"),
154                                                 $token, $session->param("name"), $ENV{REMOTE_ADDR});
155                                 }
156                                 IkiWiki::enable_commit_hook();
157                                 IkiWiki::rcs_update();
158                         }
159                         else {
160                                 foreach my $file (@files) {
161                                         IkiWiki::prune("$config{srcdir}/$file");
162                                 }
163                         }
164                         foreach my $file (@files) {
165                                 delete $IkiWiki::pagecase{$file};
166                                 print STDERR "delete $file\n";
167                                 delete $IkiWiki::links{$file};
168                         }
169                         IkiWiki::refresh();
170                         IkiWiki::saveindex();
171
172                         if ($q->param("attachment")) {
173                                 # Attachments were deleted, so redirect
174                                 # back to the edit form.
175                                 postremove($session);
176                         }
177                         else {
178                                 # The page is gone, so redirect to parent
179                                 # of the page.
180                                 my $parent=IkiWiki::dirname($pages[0]);
181                                 if (! exists $pagesources{$parent}) {
182                                         $parent="index";
183                                 }
184                                 IkiWiki::redirect($q, $config{url}."/".htmlpage($parent));
185                         }
186                 }
187                 else {
188                         IkiWiki::showform($form, $buttons, $session, $q);
189                 }
190
191                 exit 0;
192         }
193 }
194
195 1