mourningdove/htdocs/inbox/compose.bml

335 lines
12 KiB
Text
Raw Normal View History

2026-05-24 01:03:05 +00:00
<?_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?>