335 lines
12 KiB
Text
335 lines
12 KiB
Text
|
|
<?_c
|
||
|
|
# This code was forked from the LiveJournal project owned and operated
|
||
|
|
# by Live Journal, Inc. The code has been modified and expanded by
|
||
|
|
# Dreamwidth Studios, LLC. These files were originally licensed under
|
||
|
|
# the terms of the license supplied by Live Journal, Inc, which can
|
||
|
|
# currently be found at:
|
||
|
|
#
|
||
|
|
# http://code.livejournal.org/trac/livejournal/browser/trunk/LICENSE-LiveJournal.txt
|
||
|
|
#
|
||
|
|
# In accordance with the original license, this code and all its
|
||
|
|
# modifications are provided under the GNU General Public License.
|
||
|
|
# A copy of that license can be found in the LICENSE file included as
|
||
|
|
# part of this distribution.
|
||
|
|
_c?>
|
||
|
|
<?page
|
||
|
|
body<=
|
||
|
|
<?_code
|
||
|
|
{
|
||
|
|
use strict;
|
||
|
|
use vars qw(%GET %POST);
|
||
|
|
|
||
|
|
use warnings;
|
||
|
|
use LJ::Message;
|
||
|
|
use LJ::JSUtil;
|
||
|
|
|
||
|
|
return $ML{'.messaging.disabled'} unless LJ::is_enabled( 'user_messaging' );
|
||
|
|
|
||
|
|
my $remote = LJ::get_remote() or return "<?needlogin?>";
|
||
|
|
my $remote_id = $remote->{'userid'};
|
||
|
|
|
||
|
|
return "<?p " . BML::ml('protocol.not_validated', { sitename => $LJ::SITENAMESHORT, siteroot => $LJ::SITEROOT }) . " p?>"
|
||
|
|
unless $remote->is_validated;
|
||
|
|
|
||
|
|
# $_[1] is a pre-request scratch area
|
||
|
|
# put variables here so that we can access them later
|
||
|
|
# outside of this _code block
|
||
|
|
my $head = \$_[1]->{'head'};
|
||
|
|
|
||
|
|
my $body = '';
|
||
|
|
|
||
|
|
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 @errors;
|
||
|
|
|
||
|
|
push @errors, $ML{'.suspended.cannot.send'} if $remote->is_suspended;
|
||
|
|
|
||
|
|
# Submitted message
|
||
|
|
if (LJ::did_post()) {
|
||
|
|
my $mode = $POST{'mode'};
|
||
|
|
|
||
|
|
push @errors, $ML{'error.invalidform'}
|
||
|
|
unless LJ::check_form_auth();
|
||
|
|
|
||
|
|
if ($mode eq 'send') {
|
||
|
|
# test encoding
|
||
|
|
my $msg_subject_text = $POST{'msg_subject'};
|
||
|
|
push @errors, $ML{'.error.text.encoding.subject'}
|
||
|
|
unless LJ::text_in($msg_subject_text);
|
||
|
|
my ( $subject_length_b, $subject_length_c ) = LJ::text_length( $msg_subject_text );
|
||
|
|
push @errors, BML::ml( ".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'};
|
||
|
|
push @errors, $ML{'.error.text.encoding.text'}
|
||
|
|
unless LJ::text_in($msg_body_text);
|
||
|
|
my ($msg_len_b, $msg_len_c) = LJ::text_length($msg_body_text);
|
||
|
|
push @errors, BML::ml( ".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 ) {
|
||
|
|
push @errors, $ML{'.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;
|
||
|
|
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 );
|
||
|
|
|
||
|
|
# must be at least one username
|
||
|
|
push @errors, $ML{'.error.no.username'} unless ( scalar( @to_list ) > 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) {
|
||
|
|
push @errors, BML::ml( '.error.invalid.username',
|
||
|
|
{ to => $to } );
|
||
|
|
next;
|
||
|
|
}
|
||
|
|
|
||
|
|
# Can only send to other individual users
|
||
|
|
unless ($tou->is_person || $tou->is_identity || $tou->is_renamed) {
|
||
|
|
push @errors, BML::ml( 'error.message.individual', { ljuser => $tou->ljuser_display } );
|
||
|
|
next;
|
||
|
|
}
|
||
|
|
|
||
|
|
# Can't send to unvalidated users
|
||
|
|
unless ( $tou->is_validated || $remote->has_priv( "siteadmin", "*" ) ) {
|
||
|
|
push @errors, BML::ml( 'error.message.unvalidated',
|
||
|
|
{ ljuser => $tou->ljuser_display } );
|
||
|
|
next;
|
||
|
|
}
|
||
|
|
|
||
|
|
# Will target user accept messages from sender
|
||
|
|
unless ($tou->can_receive_message($remote)) {
|
||
|
|
push @errors, BML::ml( '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);
|
||
|
|
push @errors, BML::ml( ".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) {
|
||
|
|
foreach my $msg (@msg_list) {
|
||
|
|
$msg->can_send(\@errors);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
# send all the messages and display confirmation
|
||
|
|
unless (@errors) {
|
||
|
|
foreach my $msg (@msg_list) {
|
||
|
|
$msg->send(\@errors);
|
||
|
|
}
|
||
|
|
|
||
|
|
unless (@errors) {
|
||
|
|
$body .= $ML{'.message.sent'};
|
||
|
|
$body .= "<?p $ML{'.message.sent.options'} <ul>";
|
||
|
|
$body .= "<li><a href='$LJ::SITEROOT/inbox/?page=0&view=usermsg_sent_last'>$ML{'.link.view.message'}</a> $ML{'.link.view.warning'}</li>";
|
||
|
|
$body .= "<li><a href='$LJ::SITEROOT/inbox/compose'>$ML{'.link.send.message'}</a></li>";
|
||
|
|
$body .= "<li><a href='$LJ::SITEROOT/inbox/'>$ML{'.link.inbox'}</a></li>";
|
||
|
|
$body .= "<li><a href='$LJ::SITEROOT/'>$ML{'.link.home'}</a></li>";
|
||
|
|
$body .= "</ul> p?>\n";
|
||
|
|
return $body;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
# Display errors
|
||
|
|
$body .= LJ::error_list(@errors) if (@errors);
|
||
|
|
|
||
|
|
# 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});
|
||
|
|
push @errors, $ML{'.error.cannot.reply'}
|
||
|
|
unless ($msg->can_reply($msgid, $remote_id));
|
||
|
|
|
||
|
|
if (@errors) {
|
||
|
|
$body .= LJ::error_list(@errors);
|
||
|
|
return $body;
|
||
|
|
}
|
||
|
|
|
||
|
|
$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",
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
my @userpics = LJ::Userpic->load_user_userpics($remote);
|
||
|
|
my @pickws;
|
||
|
|
foreach my $pic (@userpics) {
|
||
|
|
push @pickws, map { ($_, $_) } $pic->keywords;
|
||
|
|
}
|
||
|
|
|
||
|
|
# Inbox Nav
|
||
|
|
$body .= qq{
|
||
|
|
<table summary='' class='inbox-compose'><tr><td style="padding-right: 12px">};
|
||
|
|
$body .= LJ::Widget::InboxFolderNav->render();
|
||
|
|
$body .= qq{
|
||
|
|
</td>
|
||
|
|
<td width="1" height="100%" style="border-left: 1px solid #ccc"><img src="$LJ::IMGPREFIX/spacer.gif" alt="" /></td>
|
||
|
|
<td valign="top" style="padding-left: 10px; width: 100%;">
|
||
|
|
};
|
||
|
|
|
||
|
|
$body .= '<form action="./compose" method="POST" id="compose">';
|
||
|
|
|
||
|
|
$body .= LJ::form_auth();
|
||
|
|
my $pic = ''; # displays chosen/default pic
|
||
|
|
my $picform = ''; # displays form drop-down
|
||
|
|
LJ::Widget::UserpicSelector->render(
|
||
|
|
picargs => [ $remote, \$$head, \$pic, \$picform ],
|
||
|
|
prop_picture_keyword => $POST{prop_picture_keyword} );
|
||
|
|
$body .= $pic;
|
||
|
|
|
||
|
|
$body .= "<div id='metainfo'>";
|
||
|
|
$body .= '<p class="pkg"><label class="left">To:</label> ';
|
||
|
|
|
||
|
|
if ($disabled_to) {
|
||
|
|
$body .= $reply_u->ljuser_display;
|
||
|
|
$body .= LJ::html_hidden({
|
||
|
|
name => 'msg_to',
|
||
|
|
value => $reply_u->username,
|
||
|
|
});
|
||
|
|
} else {
|
||
|
|
$body .= LJ::html_text({
|
||
|
|
name => 'msg_to',
|
||
|
|
size => '15',
|
||
|
|
id => 'msg_to',
|
||
|
|
value => $POST{'msg_to'} || $GET{'user'} || undef,
|
||
|
|
raw => "autocomplete='off'",
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
$body .= LJ::html_hidden( { name => 'force',
|
||
|
|
value => $force,
|
||
|
|
id => 'force' } );
|
||
|
|
$body .= "</p>\n";
|
||
|
|
# 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;
|
||
|
|
}
|
||
|
|
$body .= LJ::JSUtil::autocomplete(field => 'msg_to', list => \@flist);
|
||
|
|
|
||
|
|
# The drop-down userpic menu
|
||
|
|
$body .= $picform;
|
||
|
|
|
||
|
|
# Are we sending a copy of the message to the user?
|
||
|
|
my $cc_msg_option = $remote->cc_msg;
|
||
|
|
|
||
|
|
$body .= LJ::html_check( {
|
||
|
|
name => 'cc_msg',
|
||
|
|
id => 'cc_msg',
|
||
|
|
value => 1,
|
||
|
|
selected => $cc_msg_option,
|
||
|
|
} );
|
||
|
|
$body .= " <label for='cc_msg' style='font-weight: normal; font-size: smaller; font-style:italic;'>" . BML::ml( '.form.label.cc' ) . "</label></div>";
|
||
|
|
|
||
|
|
$body .= "<div class='inbox_formmes'><p><label class='subj-l'>Subject:</label> ";
|
||
|
|
$body .= LJ::html_text({
|
||
|
|
name => 'msg_subject',
|
||
|
|
size => '50',
|
||
|
|
maxlength => $subject_limit,
|
||
|
|
value => $POST{'msg_subject'} || $msg_subject,
|
||
|
|
class => 'subj-t'
|
||
|
|
});
|
||
|
|
$body .= "</p>\n";
|
||
|
|
$body .= "<div class='msg_txt'>";
|
||
|
|
$body .= "<textarea name='msg_body' rows=6 cols=55 wrap=soft>";
|
||
|
|
$body .= LJ::ehtml( $POST{'msg_body'} || $msg_body );
|
||
|
|
$body .= "</textarea><br />";
|
||
|
|
$body .= "<span class='helper'>Up to " . LJ::commafy($msg_limit) . " characters. Plain text, no HTML.";
|
||
|
|
$body .= "</span></div>\n";
|
||
|
|
|
||
|
|
$body .= $msg_parent;
|
||
|
|
$body .= LJ::html_hidden({
|
||
|
|
name => 'mode',
|
||
|
|
value => 'send',
|
||
|
|
});
|
||
|
|
|
||
|
|
$body .= LJ::html_submit("Send");
|
||
|
|
$body .= "</form></div>";
|
||
|
|
$body .= qq{
|
||
|
|
</td></tr></table>
|
||
|
|
};
|
||
|
|
|
||
|
|
|
||
|
|
return $body;
|
||
|
|
}
|
||
|
|
_code?>
|
||
|
|
<=body
|
||
|
|
title=><?_code return "Compose Message"; _code?>
|
||
|
|
head<=
|
||
|
|
<?_code
|
||
|
|
use strict;
|
||
|
|
|
||
|
|
my $ret = $_[1]->{'head'};
|
||
|
|
|
||
|
|
return $ret;
|
||
|
|
_code?>
|
||
|
|
<=head
|
||
|
|
page?>
|