LJSUP-17669: Login.bml form refactoring
[livejournal.git] / htdocs / delcomment.bml
blobd3066987476d0aede25951f40dc137e472abf0ee
1 <?_info
2 nocache=>1
3 _info?><?_code
4 #line 5
5     use strict;
6     use warnings;
8     use LJ::Auth;
10     # because this BML may be called as __rpc_delcomment too
11     BML::set_language_scope('/delcomment.bml');
13     my $check_form_auth;
14     my $mode = LJ::Request->get_param('mode') || 'html';
15     $mode = 'html' unless $mode =~ /^(?:html|js|jsonp|json)$/;
17     if ( LJ::is_enabled('new_comments') ) {
18         my $format = $GET{'format'} || $POST{'format'};
19         $check_form_auth = 1;
20         $mode = 'json' if $format and $format eq 'json';
21     }
23     # LJSUP-15424: Forbid embedding delcomment.bml to iframe
24     LJ::Request->header_out("X-Frame-Options" => 'deny');
26     # helper subroutines
28     my $site_scheme_wrap = sub {
29         my ($body) = @_;
31         LJ::set_active_crumb('delcomment');
33         return BML::render_page({
34             'title' => LJ::Lang::ml('/delcomment.bml.title'),
35             'body' => $body,
36         });
37     };
39     my $jsonp_wrap = sub {
40         my ($struct) = @_;
41         my $struct_out = LJ::JSON->to_json($struct);
43         my $callback = LJ::Request->get_param('callback') || 'JSONP';
45         return "$callback($struct_out);";
46     };
48     my $error = sub {
49         my ($why) = @_;
51         if ( $mode eq 'html' ) {
52             my $ml_error = LJ::Lang::ml('Error');
54             return $site_scheme_wrap->( qq{<h1>$ml_error</h1><p>$why</p>} );
55         } elsif ( $mode eq 'js' ) {
56             return "alert('" . LJ::ejs($why) . "'); 0;";
57         } elsif ( $mode eq 'jsonp' ) {
58             return $jsonp_wrap->({
59                 'success'   => 0,
60                 'error'     => $why,
61             });
62         } elsif ( $mode eq 'json' ) {
63             BML::finish();
64             return LJ::JSON->to_json({
65                 status  => 'error',
66                 message => $why,
67             });
68         }
69     };
71     my $ok = sub {
72         if ( $mode eq 'json' ) {
73             BML::finish();
74             return LJ::JSON->to_json({
75                 status  => 'ok',
76             });
77         }
78     };
80     my $bad_input = sub {
81         my ($why) = @_;
83         if ( $mode eq 'html' ) {
84             return $site_scheme_wrap->( LJ::bad_input($why) );
85         } else {
86             return $error->("Bad input: $why");
87         }
88     };
90     # basic initialization: who is working with us, and which comment
91     # they are working with
92     my $dtalkid             = LJ::Request->get_param('id') || LJ::Request->get_param('talkid');
93     my $journal_username    = LJ::Request->get_param('journal');
94     return $error->('Missing parameters.')
95         unless $dtalkid and $journal_username ne '';
97     my $journal = LJ::load_user( $journal_username );
98     return $bad_input->( LJ::Lang::ml('error.nojournal') )
99         unless $journal;
101     my $comment = LJ::Comment->new( $journal, 'dtalkid' => $dtalkid );
102     return $bad_input->( LJ::Lang::ml('/delcomment.bml.error.nocomment') )
103         unless $comment and $comment->valid;
105     my $poster = $comment->poster;
106     my $entry  = $comment->entry;
108     my $remote = LJ::get_remote();
109     unless ($remote) {
110         if ( $mode eq 'html' ) {
111             return LJ::needlogin_redirect();
112         } else {
113             my $ml_var = '/delcomment.bml.error.notloggedin';
114             return $error->( LJ::Lang::ml($ml_var) );
115         }
116     }
118     # what are we supposed to do? we can show form, or we can delete
119     # the comment, depending on the form parameters
120     my $method = 'form';
122     if ( LJ::Request->did_post && LJ::Request->post_param('confirm') ) {
123         return $error->( LJ::Lang::ml('error.invalidform') )
124             if $check_form_auth and not LJ::check_form_auth();
126         $method = 'delete';
127     } elsif ( $mode =~ m!jsonp! && LJ::Request->get_param('confirm') ) {
128         my %vars = (
129             'auth_token' => LJ::Request->get_param('auth_token'),
130             'journal'    => $journal->username,
131             'jitemid'    => $entry->jitemid,
132         );
134         return $error->( LJ::Lang::ml('error.invalidform') )
135             unless LJ::Auth->check_ajax_auth_token(
136                 $remote, '/delcomment.bml', %vars
137             );
139         $method = 'delete';
140     }
142     # additional error checking: comment already deleted, something is
143     # suspended or read-only, they are trying to delete something
144     # they cannot, etc.
146     return $bad_input->( LJ::Lang::ml('/delcomment.bml.error.suspended') )
147         if $remote->is_suspended;
149     return $error->( $LJ::MSG_READONLY_USER )
150         if LJ::get_cap( $journal, "readonly" );
152     return $bad_input->( LJ::Lang::ml('/delcomment.bml.error.invalidtype') )
153         unless $comment->nodetype eq 'L';
155     return $bad_input->( LJ::Lang::ml('/delcomment.bml.error.alreadydeleted') )
156         if $comment->is_deleted;
158     unless ( $comment->user_can_delete($remote) ) {
159         my $ml_var = $journal->is_community ? '.error.cantdelete.comm'
160                                             : '.error.cantdelete';
162         return $error->( LJ::Lang::ml( '/delcomment.bml' . $ml_var ) );
163     }
165     # now, let's find out what remote can actually do with the comment
166     my $can_manage = $remote->can_manage($journal);
167     my $can_mark_spam = LJ::is_enabled('spam_button') && 
168                         LJ::Talk::can_mark_spam($remote, $journal, $poster, $comment);
169     my $can_sweep     = ($remote && $poster && $remote->can_sweep($journal));
171     my %can = (
172         'manage_journal' => $can_manage,
174         # they cannot delete the thread if there is no thread
175         'delete_thread'  => $comment->has_children && $can_manage,
177         # they can ban the comment author if they are the journal owner
178         # and there is an author; also, they will not be able to ban
179         # themselves
180         'ban'            => ($can_manage || $can_sweep) && $poster && ( $remote != $poster ),
182         # they can mark as spam unless the comment is their own;
183         # they don't need to be the community maintainer to do that
184         'mark_spam'      => $can_mark_spam && $poster && ( $remote != $poster ),
186         # they can delete all comments posted by the same author
187         # if they are the entry author, and the comment being deleted
188         # has not been posted anonymously
189         'delete_author'  => $poster && ( $can_manage || ( $remote == $entry->poster ) ),
190     );
192     # so now that we have prepared everything, let's actually
193     # do something
195     if ( $method eq 'form' ) {
196         my $template = LJ::HTML::Template->new(
197             { 'use_expr' => 1 }, # force HTML::Template::Pro with Expr support
198             'filename' => "$ENV{'LJHOME'}/templates/Comments/Delete.tmpl",
199         );
201         $template->param(
202             'form_action' => "$LJ::SITEROOT/delcomment.bml?" .
203                              'journal=' . LJ::eurl($journal_username) . '&' .
204                              'id=' . int($dtalkid),
205             'form_auth'   => LJ::form_auth(),
206         );
208         if ( $can{'ban'} ) {
209             $template->param(
210                 'ml_confirm_ban' => LJ::Lang::ml(
211                     '/delcomment.bml.confirm.banuser',
212                     { 'user' => $poster->ljuser_display }
213                 ),
214             );
215         }
217         if ( $can{'delete_author'} ) {
218             my $ml_var = ( $poster == $remote ) ? '.confirm.delauthor.my'
219                                                 : '.confirm.delauthor';
221             $template->param(
222                 'ml_confirm_delauthor' => LJ::Lang::ml(
223                     '/delcomment.bml' . $ml_var,
224                     { 'user' => $poster->ljuser_display }
225                 ),
226             );
227         }
229         if ( $can_manage ) {
230             my $link_title = LJ::Lang::ml('/manage/comments/index.bml.title');
231             my $link_addr = "$LJ::SITEROOT/manage/comments/?" .
232                             'authas=' . $remote->username;
234             $template->param(
235                 'ml_changeoptions' => LJ::Lang::ml(
236                     '/delcomment.bml.changeoptions',
237                     { 'link' => qq{<a href="$link_addr">$link_title</a>} }
238                 ),
239             );
240         }
242         $template->param( "can_$_" => $can{$_} )
243             foreach keys %can;
245         return $site_scheme_wrap->( $template->output );
246     }
248     if ( $method eq 'delete' ) {
249         my %actions;
251         # mark as spam before this comment gets deleted
252         my $mark_as_spam = LJ::Request->get_param('spam') || 
253                            LJ::Request->post_param('spam');
254         if ( $can{'mark_spam'} and $mark_as_spam ) {
255             LJ::Talk::mark_comment_as_spam( $journal, $comment->jtalkid );
256             LJ::set_rel($journal, $poster, 'D');
258             LJ::User::UserlogRecord::SpamSet->create( $journal,
259                 'spammerid' => $poster->userid, 'remote' => $remote );
261             LJ::run_hook('auto_suspender_for_spam', $poster->{userid});
262             $actions{'marked_spam'} = 1;
263         }
265         # then, delete the thread if requested
266         if ( $can{'delete_thread'} and LJ::Request->post_param('delthread') )
267         {
268             LJ::Talk::delete_thread( $journal,
269                                      $entry->jitemid,
270                                      $comment->jtalkid );
271             $actions{'thread_deleted'} = 1;
272         }
274         # then, delete all the comments by the author if requested
275         if ( $can{'delete_author'} and LJ::Request->post_param('delauthor') )
276         {
277             LJ::Talk::delete_author( $journal,
278                                      $entry->jitemid,
279                                      $poster->userid );
281             $actions{'author_deleted'} = 1;
282         }
284         # now, if we haven't deleted the comment in question as a part
285         # of the thread or along with the other comments by the same
286         # author, let's actually delete it
287         unless ( $actions{'thread_deleted'} || $actions{'author_deleted'} ) {
288             LJ::Talk::delete_comment( $journal,
289                                       $entry->jitemid,
290                                       $comment->jtalkid,
291                                       $comment->state );
292         }
294         # now, ban the user if requested
295         if ( $can{'ban'} and LJ::Request->post_param('ban') ) {
296             $journal->ban_user($poster);
297             $actions{'banned'} = 1;
298         }
300         # finally, let's return something to the caller
301         if ( $mode eq 'html' ) {
302             my @messages;
304             if ( $actions{'banned'} ) {
305                 push @messages, LJ::Lang::ml(
306                     '/delcomment.bml.success.andban',
307                     { 'user' => $poster->ljuser_display }
308                 );
309             } else {
310                 push @messages, LJ::Lang::ml('/delcomment.bml.success.noban');
311             }
313             if ( $actions{'marked_spam'} ) {
314                 push @messages, LJ::Lang::ml('/delcomment.bml.success.spam');
315             }
317             my $messages = join( '', map { "<p>$_</p>" } @messages );
319             my $body = qq{
320                 $messages
321             };
323             return $site_scheme_wrap->($body);
324         } elsif ( $mode eq 'js' ) {
325             return "1;";
326         } elsif ( $mode eq 'jsonp' ) {
327             return $jsonp_wrap->({ 'success' => 1 });
328         } elsif ( $mode eq 'json' ) {
329             return $ok->();
330         }
331     }
332 _code?>