269 lines
10 KiB
Text
269 lines
10 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
|
||
|
|
title=><?_ml .title _ml?>
|
||
|
|
body<=
|
||
|
|
|
||
|
|
<?_code
|
||
|
|
{
|
||
|
|
use strict;
|
||
|
|
use vars qw(%FORM %POST);
|
||
|
|
|
||
|
|
my $r = DW::Request->get;
|
||
|
|
|
||
|
|
my $status = "";
|
||
|
|
|
||
|
|
my $spid = $FORM{'spid'}+0;
|
||
|
|
my $sp = LJ::Support::load_request($spid);
|
||
|
|
|
||
|
|
return "<?h1 $ML{'Error'} h1?><?p $ML{'.unknown.request'} p?>" unless $sp;
|
||
|
|
return "<?h1 $ML{'.closed.title'} h1?><?p $ML{'.closed.text'} p?>"
|
||
|
|
if $sp->{'state'} eq "closed";
|
||
|
|
|
||
|
|
my $remote = LJ::get_remote();
|
||
|
|
LJ::Support::init_remote($remote);
|
||
|
|
|
||
|
|
unless (LJ::Support::can_append($sp, $remote, $FORM{'auth'}) || $remote) {
|
||
|
|
return "<?needlogin?>";
|
||
|
|
}
|
||
|
|
|
||
|
|
my $scat = $sp->{_cat};
|
||
|
|
my $problemarea = $scat->{'catname'};
|
||
|
|
my $catkey = $scat->{'catkey'};
|
||
|
|
|
||
|
|
return LJ::bad_input($ML{'.invalid.noid'}) unless $FORM{'spid'};
|
||
|
|
return LJ::bad_input("<?requirepost?>") unless LJ::did_post();
|
||
|
|
|
||
|
|
$FORM{'summary'} = LJ::trim($FORM{'summary'});
|
||
|
|
return LJ::bad_input($ML{'.invalid.nosummary'})
|
||
|
|
if $FORM{'changesum'} && !$FORM{'summary'};
|
||
|
|
|
||
|
|
### links to show on success
|
||
|
|
my $auth_arg = $FORM{'auth'} ? "&auth=$FORM{'auth'}" : "";
|
||
|
|
my $successlinks = BML::ml('.successlinks2',
|
||
|
|
{ 'number' => $sp->{'spid'},
|
||
|
|
'aopts1' => "href='$LJ::SITEROOT/support/see_request?id=$sp->{'spid'}$auth_arg'",
|
||
|
|
'aopts2' => "href='$LJ::SITEROOT/support/help'",
|
||
|
|
'aopts3' => "href='$LJ::SITEROOT/support/help?cat=$scat->{'catkey'}'",
|
||
|
|
'aopts8' => "href='$LJ::SITEROOT/support/help?cat=$scat->{'catkey'}&state=green'",
|
||
|
|
'aopts4' => "href='$LJ::SITEROOT/support/see_request?id=$sp->{'spid'}&find=prev'",
|
||
|
|
'aopts5' => "href='$LJ::SITEROOT/support/see_request?id=$sp->{'spid'}&find=next'",
|
||
|
|
'aopts6' => "href='$LJ::SITEROOT/support/see_request?id=$sp->{'spid'}&find=cprev'",
|
||
|
|
'aopts7' => "href='$LJ::SITEROOT/support/see_request?id=$sp->{'spid'}&find=cnext'",
|
||
|
|
});
|
||
|
|
|
||
|
|
### insert record
|
||
|
|
my $faqid = $FORM{'faqid'}+0;
|
||
|
|
|
||
|
|
my %answer_types = LJ::Support::get_answer_types($sp, $remote, $FORM{'auth'});
|
||
|
|
|
||
|
|
my $userfacing_action_type = $FORM{replytype};
|
||
|
|
my $internal_action_type = $FORM{internaltype};
|
||
|
|
return LJ::bad_input($ML{'.invalid.type'})
|
||
|
|
if ! $userfacing_action_type && ! $internal_action_type # we need at least one of these to be defined
|
||
|
|
|| $userfacing_action_type && ! defined $answer_types{$userfacing_action_type}
|
||
|
|
|| $internal_action_type && ! defined $answer_types{$internal_action_type};
|
||
|
|
|
||
|
|
## can we do the action we want?
|
||
|
|
return LJ::bad_input($ML{'.internal.approve'})
|
||
|
|
if $FORM{'approveans'} && ($internal_action_type ne "internal" || ! LJ::Support::can_help($sp, $remote));
|
||
|
|
|
||
|
|
return LJ::bad_input($ML{'.internal.changecat'})
|
||
|
|
if $FORM{'changecat'} && ($internal_action_type ne "internal" || ! LJ::Support::can_perform_actions($sp, $remote));
|
||
|
|
|
||
|
|
return LJ::bad_input($ML{'.internal.touch'})
|
||
|
|
if ($FORM{'touch'} || $FORM{'untouch'}) &&
|
||
|
|
($internal_action_type ne "internal" || ! LJ::Support::can_perform_actions($sp, $remote));
|
||
|
|
|
||
|
|
return LJ::bad_input($ML{'.internal.changesum'})
|
||
|
|
if $FORM{'changesum'} && ($internal_action_type ne "internal" || ! LJ::Support::can_change_summary($sp, $remote));
|
||
|
|
|
||
|
|
return LJ::bad_input($ML{'.invalid.blank'})
|
||
|
|
if $FORM{reply} !~ /\S/ && $FORM{internal} !~ /\S/ # no text AND
|
||
|
|
&& !$FORM{'approveans'} && !$FORM{'changecat'} && !$FORM{'changesum'} # no action taken
|
||
|
|
&& !$FORM{'touch'} && !$FORM{'untouch'} && !$FORM{'bounce_email'};
|
||
|
|
|
||
|
|
# Load up vars for approvals
|
||
|
|
my $res;
|
||
|
|
my $splid;
|
||
|
|
if ($FORM{'approveans'}) {
|
||
|
|
$splid = $FORM{'approveans'}+0;
|
||
|
|
$res = LJ::Support::load_response($splid);
|
||
|
|
|
||
|
|
return LJ::bad_input($ML{'.invalid.noanswer'})
|
||
|
|
if ($res->{'spid'} == $spid && $res->{'type'} ne "screened");
|
||
|
|
|
||
|
|
return LJ::bad_input('Invalid type to approve screened response as.')
|
||
|
|
if (($FORM{'approveas'} ne 'answer') && ($FORM{'approveas'} ne 'comment'));
|
||
|
|
}
|
||
|
|
|
||
|
|
# Load up vars for category moves
|
||
|
|
my $newcat;
|
||
|
|
my $cats;
|
||
|
|
if ($FORM{'changecat'}) {
|
||
|
|
$newcat = $FORM{'changecat'}+0;
|
||
|
|
$cats = LJ::Support::load_cats($newcat);
|
||
|
|
|
||
|
|
return LJ::bad_input($ML{'.invalid.notcat'})
|
||
|
|
unless ($cats->{$newcat});
|
||
|
|
}
|
||
|
|
|
||
|
|
# get dbh now, it's always needed
|
||
|
|
my $dbh = LJ::get_db_writer();
|
||
|
|
|
||
|
|
## touch/untouch request
|
||
|
|
if ($FORM{'touch'}) {
|
||
|
|
$dbh->do("UPDATE support SET state='open', timetouched=UNIX_TIMESTAMP(), timeclosed=0, timemodified=UNIX_TIMESTAMP() WHERE spid=$spid");
|
||
|
|
$status .= "(Inserting request into queue)\n\n";
|
||
|
|
}
|
||
|
|
if ($FORM{'untouch'}) {
|
||
|
|
$dbh->do("UPDATE support SET timelasthelp=UNIX_TIMESTAMP(), timemodified=UNIX_TIMESTAMP() WHERE spid=$spid");
|
||
|
|
$status .= "(Removing request from queue)\n\n";
|
||
|
|
}
|
||
|
|
|
||
|
|
## bounce request to email
|
||
|
|
if ($internal_action_type eq 'bounce') {
|
||
|
|
|
||
|
|
return LJ::bad_input($ML{'.bounce.noemail'})
|
||
|
|
unless $FORM{'bounce_email'};
|
||
|
|
|
||
|
|
return LJ::bad_input($ML{'.bounce.notauth'})
|
||
|
|
unless LJ::Support::can_bounce($sp, $remote);
|
||
|
|
|
||
|
|
# check given emails using LJ::check_email
|
||
|
|
my @form_emails = split(/\s*,\s*/, $FORM{'bounce_email'});
|
||
|
|
|
||
|
|
return LJ::bad_input($ML{'.bounce.toomany'})
|
||
|
|
if @form_emails > 5;
|
||
|
|
|
||
|
|
my @emails; # error-checked, good emails
|
||
|
|
my @email_errors;
|
||
|
|
foreach my $email (@form_emails) {
|
||
|
|
|
||
|
|
# see if it's a valid username
|
||
|
|
unless ($email =~ /\@/) {
|
||
|
|
my $eu = LJ::load_user($email); # $email is a username
|
||
|
|
$email = $eu->email_raw if $eu;
|
||
|
|
}
|
||
|
|
|
||
|
|
LJ::check_email( $email, \@email_errors, \%POST );
|
||
|
|
@email_errors = map { "<strong>$email:</strong> $_" } @email_errors;
|
||
|
|
return LJ::bad_input(@email_errors) if @email_errors;
|
||
|
|
|
||
|
|
# push onto our list of valid emails
|
||
|
|
push @emails, $email;
|
||
|
|
}
|
||
|
|
|
||
|
|
# append notice that this message was bounced
|
||
|
|
my $splid = LJ::Support::append_request($sp, {
|
||
|
|
'body' => "(Bouncing mail to '" . join(', ', @emails) . "' and closing)\n\n" . $FORM{'body'},
|
||
|
|
'posterid' => $remote,
|
||
|
|
'type' => 'internal',
|
||
|
|
'uniq' => $r->note('uniq'),
|
||
|
|
'remote' => $remote,
|
||
|
|
});
|
||
|
|
|
||
|
|
# bounce original request to email
|
||
|
|
my $message = $dbh->selectrow_array("SELECT message FROM supportlog " .
|
||
|
|
"WHERE spid=? ORDER BY splid LIMIT 1",
|
||
|
|
undef, $sp->{'spid'});
|
||
|
|
|
||
|
|
LJ::send_mail({
|
||
|
|
'to' => join(", ", @emails),
|
||
|
|
'from' => $sp->{'reqemail'},
|
||
|
|
'fromname' => $sp->{'reqname'},
|
||
|
|
'headers' => { 'X-Bounced-By' => $remote->{'user'} },
|
||
|
|
'subject' => "$sp->{'subject'} (support request #$sp->{'spid'})",
|
||
|
|
'body' => "$message\n\n$LJ::SITEROOT/support/see_request?id=$sp->{'spid'}",
|
||
|
|
});
|
||
|
|
|
||
|
|
# close request, nobody gets credited
|
||
|
|
$dbh->do("UPDATE support SET state='closed', timeclosed=UNIX_TIMESTAMP(), timemodified=UNIX_TIMESTAMP() WHERE spid=?",
|
||
|
|
undef, $sp->{'spid'});
|
||
|
|
|
||
|
|
return BML::ml('.bounced.success', { 'addresslist' => "<strong>".join(', ', @emails)."</strong>" })
|
||
|
|
.$successlinks;
|
||
|
|
}
|
||
|
|
|
||
|
|
$dbh->do("UPDATE support SET state='open', timetouched=UNIX_TIMESTAMP(), timeclosed=0, timemodified=UNIX_TIMESTAMP() WHERE spid=$spid")
|
||
|
|
if LJ::Support::is_poster($sp, $remote, $FORM{'auth'});
|
||
|
|
|
||
|
|
## change category
|
||
|
|
if ($FORM{'changecat'}) {
|
||
|
|
# $newcat, $cats defined above
|
||
|
|
$dbh->do("UPDATE support SET spcatid=$newcat WHERE spid=$spid");
|
||
|
|
$status .= "Changing from $catkey => $cats->{$newcat}->{'catkey'}\n\n";
|
||
|
|
$sp->{'spcatid'} = $newcat; # update category so IC e-mail goes to right place
|
||
|
|
|
||
|
|
LJ::Hooks::run_hook("support_changecat_extra_actions", spid => $spid, catkey => $cats->{$newcat}->{catkey});
|
||
|
|
}
|
||
|
|
|
||
|
|
## approving a screened response
|
||
|
|
if ($FORM{'approveans'}) {
|
||
|
|
# $res, $splid defined above
|
||
|
|
# approve
|
||
|
|
my $qtype = $dbh->quote($FORM{'approveas'});
|
||
|
|
$dbh->do("UPDATE supportlog SET type=$qtype WHERE splid=$splid");
|
||
|
|
$status .= "(Approving $FORM{'approveas'} \#$splid)\n\n";
|
||
|
|
|
||
|
|
LJ::Support::mail_response_to_user($sp, $splid);
|
||
|
|
}
|
||
|
|
|
||
|
|
## change summary
|
||
|
|
if ($FORM{'changesum'}) {
|
||
|
|
$FORM{'summary'} =~ s/[\n\r]//g;
|
||
|
|
my $qnewsub = $dbh->quote($FORM{'summary'});
|
||
|
|
$dbh->do("UPDATE support SET subject=$qnewsub WHERE spid=$spid");
|
||
|
|
$status .= "Changing subject from \"$sp->{'subject'}\" to \"$FORM{'summary'}\".\n\n";
|
||
|
|
}
|
||
|
|
|
||
|
|
my $splid;
|
||
|
|
|
||
|
|
# user-facing
|
||
|
|
if ( $FORM{reply} ) {
|
||
|
|
$splid = LJ::Support::append_request($sp, {
|
||
|
|
'body' => $FORM{reply},
|
||
|
|
'type' => $userfacing_action_type,
|
||
|
|
'faqid' => $faqid,
|
||
|
|
'uniq' => $r->note('uniq'),
|
||
|
|
'remote' => $remote
|
||
|
|
});
|
||
|
|
|
||
|
|
LJ::Support::mail_response_to_user($sp, $splid)
|
||
|
|
unless LJ::Support::is_poster($sp, $remote, $FORM{'auth'});
|
||
|
|
}
|
||
|
|
|
||
|
|
# then any internal status changes
|
||
|
|
if ( $status || $FORM{internal} ) {
|
||
|
|
$splid = LJ::Support::append_request($sp, {
|
||
|
|
'body' => $status . $FORM{internal},
|
||
|
|
'type' => $internal_action_type,
|
||
|
|
'uniq' => $r->note('uniq'),
|
||
|
|
'remote' => $remote
|
||
|
|
});
|
||
|
|
|
||
|
|
LJ::Support::mail_response_to_user($sp, $splid)
|
||
|
|
unless LJ::Support::is_poster($sp, $remote, $FORM{'auth'});
|
||
|
|
}
|
||
|
|
|
||
|
|
return "<?h1 $ML{'.logged.title'} h1?><?p $ML{'.logged.text'} p?>" . $successlinks;
|
||
|
|
}
|
||
|
|
_code?>
|
||
|
|
<?hr?>
|
||
|
|
<?_code return BML::ml('.back.support2', {'aopts' => "href='$LJ::SITEROOT/support/'"}); _code?>
|
||
|
|
|
||
|
|
<=body
|
||
|
|
page?>
|