733 lines
24 KiB
Perl
733 lines
24 KiB
Perl
#!/usr/bin/perl
|
|
#
|
|
# DW::Controller::Inbox
|
|
#
|
|
# Pages for exporting journal content.
|
|
#
|
|
# Authors:
|
|
# Ruth Hatch <ruth.s.hatch@gmail.com>
|
|
#
|
|
# Copyright (c) 2015-2020 by Dreamwidth Studios, LLC.
|
|
#
|
|
# This program is free software; you may redistribute it and/or modify it under
|
|
# the same terms as Perl itself. For a copy of the license, please reference
|
|
# 'perldoc perlartistic' or 'perldoc perlgpl'.
|
|
#
|
|
|
|
package DW::Controller::Inbox;
|
|
|
|
use v5.10;
|
|
use strict;
|
|
use warnings;
|
|
|
|
use DW::Controller;
|
|
use DW::Routing;
|
|
use DW::Template;
|
|
use DW::FormErrors;
|
|
use LJ::Hooks;
|
|
|
|
DW::Routing->register_string( '/inbox/new', \&index_handler, app => 1 );
|
|
DW::Routing->register_string( '/inbox/new/compose', \&compose_handler, app => 1 );
|
|
DW::Routing->register_string( '/inbox/new/markspam', \&markspam_handler, app => 1 );
|
|
DW::Routing->register_rpc( 'inbox_actions', \&action_handler, format => 'json' );
|
|
|
|
my $PAGE_LIMIT = 15;
|
|
|
|
sub index_handler {
|
|
my ( $ok, $rv ) = controller( form_auth => 1 );
|
|
return $rv unless $ok;
|
|
|
|
my $r = $rv->{r};
|
|
my $POST = $r->post_args;
|
|
my $GET = $r->get_args;
|
|
my $remote = $rv->{remote};
|
|
my $vars;
|
|
my $scope = '/inbox/index.tt';
|
|
my $errors = DW::FormErrors->new;
|
|
|
|
return error_ml("$scope.error.not_ready") unless $remote->can_use_esn;
|
|
|
|
my $inbox = $remote->notification_inbox
|
|
or return error_ml( "$scope.error.couldnt_retrieve_inbox", { user => $remote->{user} } );
|
|
|
|
# Take a supplied filter but default it to undef unless it is valid
|
|
my $view = $GET->{view} || $POST->{view} || undef;
|
|
$view = undef if $view && $view =~ /\W/;
|
|
$view = undef if $view eq 'archive' && !LJ::is_enabled('esn_archive');
|
|
$view = undef if $view && !LJ::NotificationInbox->can("${view}_items");
|
|
$view ||= 'all';
|
|
|
|
my $itemid = $view eq "singleentry" ? int( $POST->{itemid} || $GET->{itemid} || 0 ) : 0;
|
|
my $expand = $GET->{expand};
|
|
|
|
my $page = int( $POST->{page} || $GET->{page} || 1 );
|
|
if ( $r->did_post ) {
|
|
my $action;
|
|
|
|
if ( $POST->{mark_read} ) {
|
|
$action = 'mark_read';
|
|
}
|
|
elsif ( $POST->{mark_unread} ) {
|
|
$action = 'mark_unread';
|
|
}
|
|
elsif ( $POST->{delete_all} ) {
|
|
$action = 'delete_all';
|
|
}
|
|
elsif ( $POST->{mark_all} ) {
|
|
$action = 'mark_all';
|
|
}
|
|
elsif ( $POST->{delete} ) {
|
|
$action = 'delete';
|
|
}
|
|
my @item_ids;
|
|
for my $key ( keys %{$POST} ) {
|
|
next unless $key =~ /check_(\d+)/;
|
|
push @item_ids, $POST->{$key};
|
|
}
|
|
my $res = handle_post( $remote, $action, $view, $itemid, \@item_ids );
|
|
unless ( $res->{success} ) {
|
|
for my $error ( @{ $res->{errors} } ) {
|
|
$errors->add( undef, $error );
|
|
}
|
|
}
|
|
}
|
|
|
|
# Allow bookmarking to work without Javascript
|
|
# or before JS events are bound
|
|
if ( $GET->{bookmark_off} && $GET->{bookmark_off} =~ /^\d+$/ ) {
|
|
$errors->add( undef, "$scope.error.max_bookmarks" )
|
|
unless $inbox->add_bookmark( $GET->{bookmark_off} );
|
|
}
|
|
if ( $GET->{bookmark_on} && $GET->{bookmark_on} =~ /^\d+$/ ) {
|
|
$inbox->remove_bookmark( $GET->{bookmark_on} );
|
|
}
|
|
|
|
# Pagination
|
|
|
|
my $viewarg = $view ? "&view=$view" : "";
|
|
my $itemidarg = $itemid ? "&itemid=$itemid" : "";
|
|
|
|
# Filter by view if specified
|
|
my @all_items = @{ items_by_view( $inbox, $view, $itemid ) };
|
|
|
|
my $itemcount = scalar @all_items;
|
|
$vars->{view} = $view;
|
|
$vars->{itemcount} = $itemcount;
|
|
|
|
# pagination
|
|
|
|
$page = 1 if $page < 1;
|
|
my $last_page = POSIX::ceil( ( scalar @all_items ) / $PAGE_LIMIT );
|
|
$last_page ||= 1;
|
|
$page = $last_page if $page > $last_page;
|
|
|
|
$vars->{page} = $page;
|
|
$vars->{last_page} = $last_page;
|
|
|
|
$vars->{item_html} = render_items( $page, $view, $remote, \@all_items, $expand );
|
|
$vars->{folder_html} = render_folders( $remote, $view );
|
|
|
|
# choose button text depending on whether user is viewing all emssages or only a subfolder
|
|
# to avoid any confusion as to what deleting and marking read will do
|
|
my $mark_all_text = "";
|
|
my $delete_all_text = "";
|
|
if ( $view eq "all" ) {
|
|
$mark_all_text = "widget.inbox.menu.mark_all_read.btn";
|
|
$delete_all_text = "widget.inbox.menu.delete_all.btn";
|
|
}
|
|
elsif ( $view eq "singleentry" ) {
|
|
$mark_all_text = "widget.inbox.menu.mark_all_read.entry.btn";
|
|
$delete_all_text = "widget.inbox.menu.delete_all.entry.btn";
|
|
$vars->{itemid} = $itemid;
|
|
}
|
|
else {
|
|
$mark_all_text = "widget.inbox.menu.mark_all_read.subfolder.btn";
|
|
$delete_all_text = "widget.inbox.menu.delete_all.subfolder.btn";
|
|
}
|
|
|
|
$vars->{mark_all} = $mark_all_text;
|
|
$vars->{delete_all} = $delete_all_text;
|
|
$vars->{errors} = $errors;
|
|
|
|
# TODO: Remove this when beta is over
|
|
$vars->{dw_beta} = LJ::load_user('dw_beta');
|
|
|
|
return DW::Template->render_template( 'inbox/index.tt', $vars );
|
|
}
|
|
|
|
sub render_items {
|
|
my ( $page, $view, $remote, $items_ref, $expand ) = @_;
|
|
|
|
my $inbox = $remote->notification_inbox
|
|
or return error_ml( "/inbox/index.tt.error.couldnt_retrieve_inbox",
|
|
{ 'user' => $remote->{user} } );
|
|
my $starting_index = ( $page - 1 ) * $PAGE_LIMIT;
|
|
my $ending_index = $starting_index - 1 + $PAGE_LIMIT;
|
|
my @display_items = @$items_ref;
|
|
@display_items = sort { $b->when_unixtime <=> $a->when_unixtime } @display_items;
|
|
@display_items = @display_items[ $starting_index .. $ending_index ];
|
|
|
|
my @cleaned_items;
|
|
foreach my $item (@display_items) {
|
|
last unless $item;
|
|
my $cleaned = {
|
|
'qid' => $item->qid,
|
|
'title' => $item->title,
|
|
'read' => ( $item->read ? "read" : "unread" ),
|
|
|
|
};
|
|
my $bookmark = 'bookmark_' . ( $inbox->is_bookmark( $item->qid ) ? "on" : "off" );
|
|
$cleaned->{bookmark_img} = LJ::img( $bookmark, "", { 'class' => 'item_bookmark' } );
|
|
$cleaned->{bookmark} = $bookmark;
|
|
|
|
# For clarity, we display both a relative time (e.g. "5 days ago")
|
|
# and an absolute time (e.g. "2019-05-11 14:34 UTC") in the
|
|
# notification list.
|
|
my $event_time = $item->when_unixtime;
|
|
$cleaned->{rel_time} = LJ::diff_ago_text($event_time);
|
|
$cleaned->{abs_time} = LJ::S2::sitescheme_secs_to_iso( $event_time, { tz => "UTC" } );
|
|
|
|
my $contents = $item->as_html || '';
|
|
|
|
my $expanded = '';
|
|
|
|
if ($contents) {
|
|
LJ::ehtml( \$contents );
|
|
|
|
my $is_expanded = $expand && $expand == $item->qid;
|
|
$is_expanded ||= $remote->prop('esn_inbox_default_expand');
|
|
$is_expanded = 0 if $item->read;
|
|
|
|
$is_expanded = 1 if ( $view eq "usermsg_sent_last" );
|
|
$expanded = $is_expanded ? "inbox_expand" : "inbox_collapse";
|
|
|
|
}
|
|
$cleaned->{expanded_img} = LJ::img( $expanded, "", { 'class' => 'item_expand' } );
|
|
$cleaned->{expanded} = $expanded;
|
|
$cleaned->{contents} = $contents;
|
|
push @cleaned_items, $cleaned;
|
|
|
|
}
|
|
|
|
my $vars = {
|
|
messages => \@cleaned_items,
|
|
page => $page,
|
|
view => $view
|
|
};
|
|
|
|
return DW::Template->template_string( 'inbox/msg_list.tt', $vars );
|
|
|
|
}
|
|
|
|
sub render_folders {
|
|
my ( $remote, $view ) = @_;
|
|
my $user_messsaging = LJ::is_enabled('user_messaging');
|
|
my $inbox = $remote->notification_inbox
|
|
or return error_ml( "/inbox/index.tt.error.couldnt_retrieve_inbox",
|
|
{ 'user' => $remote->{user} } );
|
|
|
|
my $vars;
|
|
|
|
my @children = (
|
|
{
|
|
view => 'circle',
|
|
label => 'circle_updates',
|
|
unread => $inbox->circle_event_count,
|
|
children => [
|
|
{ view => 'birthday', label => 'birthdays' },
|
|
{ view => 'encircled', label => 'encircled' }
|
|
]
|
|
},
|
|
{
|
|
view => 'entrycomment',
|
|
label => 'entries_and_comments',
|
|
unread => $inbox->entrycomment_event_count
|
|
},
|
|
{ view => 'pollvote', label => 'poll_votes', unread => $inbox->pollvote_event_count },
|
|
{
|
|
view => 'communitymembership',
|
|
label => 'community_membership',
|
|
unread => $inbox->communitymembership_event_count
|
|
},
|
|
{
|
|
view => 'sitenotices',
|
|
label => 'site_notices',
|
|
unread => $inbox->sitenotices_event_count
|
|
}
|
|
|
|
);
|
|
|
|
if ($user_messsaging) {
|
|
|
|
# push links for recieved PMs and sent PMs to the beginning and end of the list, respectively
|
|
unshift @children,
|
|
{
|
|
view => 'usermsg_recvd',
|
|
label => 'messages',
|
|
unread => $inbox->usermsg_recvd_event_count
|
|
};
|
|
push @children,
|
|
{ view => 'usermsg_sent', label => 'sent', unread => $inbox->usermsg_sent_event_count };
|
|
}
|
|
|
|
# put 'unread' at the very top
|
|
unshift @children, { view => 'unread', label => 'unread', unread => $inbox->all_event_count };
|
|
push @children, { view => 'bookmark', label => 'bookmarks', unread => $inbox->bookmark_count };
|
|
push @children, { view => 'archived', label => 'archive' } if LJ::is_enabled('esn_archive');
|
|
|
|
$vars->{folder_links} = {
|
|
view => 'all',
|
|
label => 'all',
|
|
unread => $inbox->all_event_count,
|
|
children => \@children
|
|
};
|
|
$vars->{user_messaging} = $user_messsaging;
|
|
$vars->{view} = $view;
|
|
return DW::Template->template_string( 'inbox/folders.tt', $vars );
|
|
}
|
|
|
|
sub action_handler {
|
|
my ( $ok, $rv ) = controller();
|
|
return $rv unless $ok;
|
|
|
|
# gets the request and args
|
|
my $r = $rv->{r};
|
|
my $args = $r->json;
|
|
my $action = $args->{action};
|
|
my $ids = $args->{'ids'};
|
|
my $view = $args->{view} || 'all';
|
|
my $page = $args->{page} || 1;
|
|
my $itemid = $args->{itemid} || 0;
|
|
my $remote = $rv->{remote};
|
|
my $form_auth = $args->{lj_form_auth};
|
|
my $expand;
|
|
|
|
if ( $action eq 'expand' ) {
|
|
$expand = $ids;
|
|
}
|
|
else {
|
|
return DW::RPC->err( LJ::Lang::ml('/inbox/index.tt.error.invalidform') )
|
|
unless LJ::check_form_auth($form_auth);
|
|
my $res = handle_post( $remote, $action, $view, $itemid, $ids );
|
|
unless ( $res->{success} ) {
|
|
return DW::RPC->out( errors => $res->{errors} );
|
|
}
|
|
}
|
|
|
|
my $getextra = {};
|
|
if ( $view eq 'singleentry' ) {
|
|
$getextra->{view} = $view;
|
|
$getextra->{itemid} = $itemid;
|
|
|
|
}
|
|
elsif ( $view ne 'all' ) {
|
|
$getextra->{view} = $view;
|
|
}
|
|
|
|
my $inbox = $remote->notification_inbox;
|
|
my $folder_html = render_folders( $remote, $view );
|
|
|
|
# if we've removed items from the view, we need to rebuild the list and recalculate pages
|
|
if ( $action eq 'delete' || $action eq 'delete_all' ) {
|
|
|
|
my $display_items = items_by_view( $inbox, $view, $itemid );
|
|
my $last_page = POSIX::ceil( ( scalar @$display_items ) / $PAGE_LIMIT );
|
|
$last_page ||= 1;
|
|
$page = $last_page if $page > $last_page;
|
|
|
|
my $items_html = render_items( $page, $view, $remote, $display_items, $expand );
|
|
my $path = "/inbox/new";
|
|
my $pages_html = DW::Template->template_string( 'components/pagination.tt',
|
|
{ current => $page, total_pages => $last_page, path => $path, cur_args => $getextra } );
|
|
|
|
return DW::RPC->out(
|
|
success => {
|
|
items => $items_html,
|
|
folders => $folder_html,
|
|
pages => $pages_html,
|
|
unread_count => $inbox->unread_count
|
|
}
|
|
);
|
|
}
|
|
else {
|
|
return DW::RPC->out(
|
|
success => {
|
|
unread_count => $inbox->unread_count,
|
|
folders => $folder_html,
|
|
}
|
|
);
|
|
}
|
|
}
|
|
|
|
sub handle_post {
|
|
my ( $remote, $action, $view, $itemid, $item_ids ) = @_;
|
|
my @errors;
|
|
|
|
my $inbox = $remote->notification_inbox
|
|
or return error_ml( "/inbox/index.tt.error.couldnt_retrieve_inbox",
|
|
{ 'user' => $remote->{user} } );
|
|
return { 'errors' => ["No action specified!"] } unless $action;
|
|
|
|
if ( $action eq 'mark_all' ) {
|
|
$inbox->mark_all_read( $view, itemid => $itemid );
|
|
}
|
|
elsif ( $action eq 'delete_all' ) {
|
|
$inbox->delete_all( $view, itemid => $itemid );
|
|
}
|
|
elsif ( $action eq 'bookmark_off' ) {
|
|
push @errors, LJ::Lang::ml("/inbox/index.tt.error.max_bookmarks")
|
|
unless $inbox->add_bookmark($item_ids);
|
|
}
|
|
elsif ( $action eq 'bookmark_on' ) {
|
|
$inbox->remove_bookmark($item_ids);
|
|
}
|
|
else {
|
|
foreach my $id (@$item_ids) {
|
|
my $item = LJ::NotificationItem->new( $remote, $id );
|
|
next unless $item->valid;
|
|
|
|
if ( $action eq 'mark_read' ) {
|
|
$item->mark_read;
|
|
}
|
|
elsif ( $action eq 'mark_unread' ) {
|
|
$item->mark_unread;
|
|
}
|
|
elsif ( $action eq 'delete' ) {
|
|
$item->delete;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
if (@errors) {
|
|
return { 'errors' => \@errors };
|
|
}
|
|
else {
|
|
return { 'success' => 1 };
|
|
}
|
|
|
|
}
|
|
|
|
sub items_by_view {
|
|
my ( $inbox, $view, $itemid ) = @_;
|
|
|
|
$itemid ||= 0;
|
|
my @all_items;
|
|
if ($view) {
|
|
if ( $view eq "singleentry" ) {
|
|
@all_items = $inbox->singleentry_items($itemid);
|
|
}
|
|
else {
|
|
@all_items = eval "\$inbox->${view}_items";
|
|
}
|
|
}
|
|
else {
|
|
@all_items = $inbox->all_items;
|
|
}
|
|
|
|
return \@all_items;
|
|
}
|
|
|
|
sub compose_handler {
|
|
my ( $ok, $rv ) = controller( form_auth => 1 );
|
|
return $rv unless $ok;
|
|
|
|
# gets the request and args
|
|
my $r = $rv->{r};
|
|
my $POST = $r->post_args;
|
|
my $GET = $r->get_args;
|
|
my $remote = $rv->{remote};
|
|
my $errors = DW::FormErrors->new;
|
|
|
|
return $r->msg_redirect(
|
|
LJ::Lang::ml(
|
|
'protocol.not_validated', { sitename => $LJ::SITENAMESHORT, siteroot => $LJ::SITEROOT }
|
|
),
|
|
$r->ERROR,
|
|
"$LJ::SITEROOT/inbox"
|
|
) unless LJ::is_enabled('user_messaging');
|
|
|
|
return $r->msg_redirect( LJ::Lang::ml('.suspended.cannot.send'), $r->ERROR,
|
|
"$LJ::SITEROOT/inbox" )
|
|
if $remote->is_suspended;
|
|
|
|
my $remote_id = $remote->{userid};
|
|
my $reply_to; # User replying to
|
|
my $reply_u; # User replying to
|
|
my $disabled_to = 0; # disable To field if sending a reply message
|
|
my $msg_subject = ''; # reply subject
|
|
my $msg_body = ''; # reply body
|
|
my $msg_parent = ''; # Hidden msg field containing id of parent message
|
|
my $msg_limit = $remote->count_usermessage_length;
|
|
my $subject_limit = 255;
|
|
my $force = 0; # flag for if user wants to force an empty PM
|
|
my $scope = '/inbox/compose.tt';
|
|
|
|
# Submitted message
|
|
if ( $r->did_post ) {
|
|
my $mode = $POST->{'mode'};
|
|
|
|
if ( $mode eq 'send' ) {
|
|
|
|
# test encoding
|
|
my $msg_subject_text = $POST->{'msg_subject'};
|
|
$errors->add( 'msg_subject', "$scope.error.text.encoding.subject" )
|
|
unless LJ::text_in($msg_subject_text);
|
|
my ( $subject_length_b, $subject_length_c ) = LJ::text_length($msg_subject_text);
|
|
$errors->add(
|
|
'msg_subject',
|
|
"$scope.error.subject.length",
|
|
{
|
|
subject_length => LJ::commafy($subject_length_c),
|
|
subject_limit => LJ::commafy($subject_limit),
|
|
}
|
|
) unless $subject_length_c <= $subject_limit;
|
|
|
|
# test encoding and length
|
|
my $msg_body_text = $POST->{'msg_body'};
|
|
$errors->add( 'msg_body', "$scope.error.text.encoding.text" )
|
|
unless LJ::text_in($msg_body_text);
|
|
my ( $msg_len_b, $msg_len_c ) = LJ::text_length($msg_body_text);
|
|
$errors->add(
|
|
'msg_body',
|
|
".error.message.length",
|
|
{
|
|
msg_length => LJ::commafy($msg_len_c),
|
|
msg_limit => LJ::commafy($msg_limit)
|
|
}
|
|
) unless ( $msg_len_c <= $msg_limit );
|
|
|
|
# checks if the PM is empty (no text)
|
|
$force = $POST->{'force'};
|
|
unless ( $msg_len_c > 0 || $force ) {
|
|
$errors->add( 'msg_body', '.warning.empty.message' );
|
|
$force = 1;
|
|
}
|
|
|
|
# Get list of recipients
|
|
my $to_field = $POST->{'msg_to'};
|
|
$to_field =~ s/\s//g;
|
|
|
|
# Get recipient list without duplicates
|
|
my %to_hash = map { lc($_), 1 } split( ",", $to_field );
|
|
my @to_list = keys %to_hash;
|
|
|
|
# must be at least one username
|
|
$errors->add( 'msg_to', "$scope.error.no.username" ) unless ( scalar(@to_list) > 0 );
|
|
|
|
push @to_list, $remote->username if $POST->{'cc_msg'};
|
|
my @msg_list;
|
|
|
|
# persist the default value of the cc_msg option
|
|
$remote->cc_msg( $POST->{'cc_msg'} ? 1 : 0 );
|
|
|
|
# Check each user being sent a message
|
|
foreach my $to (@to_list) {
|
|
|
|
# Check the To field
|
|
my $tou = LJ::load_user_or_identity($to);
|
|
unless ($tou) {
|
|
$errors->add( 'msg_to', "$scope.error.invalid.username", { to => $to } );
|
|
next;
|
|
}
|
|
|
|
# Can only send to other individual users
|
|
unless ( $tou->is_person || $tou->is_identity || $tou->is_renamed ) {
|
|
$errors->add( 'msg_to', 'error.message.individual',
|
|
{ ljuser => $tou->ljuser_display } );
|
|
next;
|
|
}
|
|
|
|
# Can't send to unvalidated users
|
|
unless ( $tou->is_validated || $remote->has_priv( "siteadmin", "*" ) ) {
|
|
$errors->add( 'msg_to', 'error.message.unvalidated',
|
|
{ ljuser => $tou->ljuser_display } );
|
|
next;
|
|
}
|
|
|
|
# Will target user accept messages from sender
|
|
unless ( $tou->can_receive_message($remote) ) {
|
|
|
|
errors->add( 'msg_to', 'error.message.canreceive',
|
|
{ ljuser => $tou->ljuser_display } );
|
|
next;
|
|
}
|
|
|
|
my $msguserpic;
|
|
$msguserpic = $POST->{'prop_picture_keyword'}
|
|
if ( defined $POST->{'prop_picture_keyword'} );
|
|
|
|
push @msg_list,
|
|
LJ::Message->new(
|
|
{
|
|
journalid => $remote_id,
|
|
otherid => $tou->{userid},
|
|
subject => $msg_subject_text,
|
|
body => $msg_body_text,
|
|
parent_msgid => $POST->{'msg_parent'} || undef,
|
|
userpic => $msguserpic,
|
|
}
|
|
);
|
|
|
|
}
|
|
|
|
# Check that the rate limit will not be exceeded
|
|
# This is only necessary if there are multiple recipients
|
|
if ( scalar(@msg_list) > 1 ) {
|
|
my $up;
|
|
$up = LJ::Hooks::run_hook( 'upgrade_message', $remote, 'message' );
|
|
$up = "<br />$up" if ($up);
|
|
$errors->add( undef, ".error.rate.limit", { up => $up } )
|
|
unless LJ::Message::ratecheck_multi(
|
|
userid => $remote_id,
|
|
msg_list => \@msg_list
|
|
);
|
|
}
|
|
|
|
# check if any of the messages will throw an error
|
|
unless ( $errors->exist ) {
|
|
my @errors;
|
|
foreach my $msg (@msg_list) {
|
|
$msg->can_send( \@errors );
|
|
}
|
|
foreach my $error (@errors) {
|
|
$error->add( undef, $error );
|
|
}
|
|
}
|
|
|
|
# send all the messages and display confirmation
|
|
unless ( $errors->exist ) {
|
|
my @errors;
|
|
foreach my $msg (@msg_list) {
|
|
$msg->send( \@errors );
|
|
}
|
|
foreach my $error (@errors) {
|
|
$error->add( undef, $error );
|
|
}
|
|
return $r->msg_redirect( LJ::Lang::ml("$scope.message.sent"),
|
|
$r->SUCCESS, "$LJ::SITEROOT/inbox" )
|
|
unless $errors->exist;
|
|
}
|
|
}
|
|
}
|
|
|
|
# Sending a reply to a message
|
|
if ( ( $GET->{mode} && $GET->{mode} eq 'reply' ) || $POST->{'msgid'} ) {
|
|
my $msgid = $GET->{'msgid'} || $POST->{'msgid'};
|
|
next unless $msgid;
|
|
|
|
my $msg = LJ::Message->load( { msgid => $msgid, journalid => $remote_id } );
|
|
|
|
return $r->msg_redirect( LJ::Lang::ml("$scope.error.cannot.reply"),
|
|
$r->ERROR, "$LJ::SITEROOT/inbox" )
|
|
unless $msg->can_reply( $msgid, $remote_id );
|
|
|
|
$reply_u = $msg->other_u;
|
|
$reply_to = $reply_u->display_name;
|
|
$disabled_to = 1;
|
|
$msg_subject = $msg->subject_raw || "(no subject)";
|
|
$msg_subject = "Re: " . $msg_subject
|
|
unless $msg_subject =~ /Re: /;
|
|
$msg_body = $msg->body_raw;
|
|
$msg_body =~ s/(.{70}[^\s]*)\s+/$1\n/g;
|
|
$msg_body =~ s/(^.*)/\> $1/gm;
|
|
$msg_body = "\n\n--- $reply_to wrote:\n" . $msg_body;
|
|
$msg_parent .= LJ::html_hidden(
|
|
{
|
|
name => 'msg_parent',
|
|
value => "$msgid",
|
|
}
|
|
);
|
|
}
|
|
|
|
# autocomplete To field with trusted and watched people
|
|
my @flist = ();
|
|
if ( LJ::isu($remote) ) {
|
|
my %trusted_and_watched_userids =
|
|
map { $_ => 1 } ( $remote->trusted_userids, $remote->watched_userids );
|
|
my $us = LJ::load_userids( keys %trusted_and_watched_userids );
|
|
@flist =
|
|
map { $us->{$_}->display_name }
|
|
grep { $us->{$_}->is_personal || $us->{$_}->is_identity }
|
|
keys %trusted_and_watched_userids;
|
|
}
|
|
|
|
# Are we sending a copy of the message to the user?
|
|
my $cc_msg_option = $remote->cc_msg;
|
|
|
|
my $vars = {
|
|
errors => $errors,
|
|
formdata => $POST || { msg_to => ( $GET->{'user'} || undef ) },
|
|
msg_body => $msg_body,
|
|
msg_subject => $msg_subject,
|
|
msg_parent => $msg_parent,
|
|
reply_u => $reply_u,
|
|
reply_to => $reply_to,
|
|
autocomplete => \@flist,
|
|
cc_msg_option => $cc_msg_option,
|
|
folder_html => render_folders($remote),
|
|
commafy => \&LJ::commafy,
|
|
remote => $remote,
|
|
msg_limit => $msg_limit
|
|
};
|
|
|
|
return DW::Template->render_template( 'inbox/compose.tt', $vars );
|
|
|
|
}
|
|
|
|
sub markspam_handler {
|
|
my ( $ok, $rv ) = controller( form_auth => 1 );
|
|
return $rv unless $ok;
|
|
|
|
# gets the request and args
|
|
my $r = $rv->{r};
|
|
my $POST = $r->post_args;
|
|
my $GET = $r->get_args;
|
|
my $remote = $rv->{remote};
|
|
my $errors = DW::FormErrors->new;
|
|
|
|
my $remote_id = $remote->{'userid'};
|
|
my $msg_id = $GET->{msgid} || $POST->{msgid};
|
|
my $msg = LJ::Message->load( { msgid => $msg_id, journalid => $remote_id } );
|
|
|
|
return $r->msg_redirect( "Message cannot be loaded.", $r->ERROR, "$LJ::SITEROOT/inbox" )
|
|
unless $msg && $msg->valid;
|
|
|
|
return $r->msg_redirect( "You cannot report a message you sent as spam.",
|
|
$r->ERROR, "$LJ::SITEROOT/inbox" )
|
|
if $msg->type eq "out";
|
|
|
|
return $r->msg_redirect( "You are not allowed to report messages as spam.",
|
|
$r->ERROR, "$LJ::SITEROOT/inbox" )
|
|
if LJ::sysban_check( 'spamreport', $remote->user );
|
|
|
|
if ( $r->did_post && $POST->{'confirm'} ) {
|
|
|
|
# Some action must be selected
|
|
$errors->add( undef, 'No action selected' )
|
|
unless ( $POST->{spam} || $POST->{'ban'} );
|
|
|
|
# Mark as spam
|
|
if ( $POST->{spam} ) {
|
|
$r->add_msg( "Message marked as spam.", $r->SUCCESS )
|
|
if $msg->mark_as_spam;
|
|
}
|
|
|
|
# Ban user
|
|
if ( $POST->{'ban'} ) {
|
|
LJ::set_rel( $remote_id, $msg->otherid, 'B' );
|
|
$remote->log_event( 'ban_set', { actiontarget => $msg->otherid, remote => $remote } );
|
|
$r->add_msg( "User banned.", $r->SUCCESS );
|
|
}
|
|
return $r->redirect("$LJ::SITEROOT/inbox");
|
|
}
|
|
my $vars = {
|
|
errors => $errors,
|
|
msg_user => $msg->other_u,
|
|
msgid => $msg_id,
|
|
};
|
|
|
|
return DW::Template->render_template( 'inbox/markspam.tt', $vars );
|
|
|
|
}
|
|
1;
|