init
This commit is contained in:
169
livejournal/htdocs/support/act.bml
Executable file
169
livejournal/htdocs/support/act.bml
Executable file
@@ -0,0 +1,169 @@
|
||||
<?_code
|
||||
|
||||
LJ::set_active_crumb('supportact');
|
||||
|
||||
my $cmd = BML::get_query_string();
|
||||
if ($cmd =~ /^(\w+);(\d+);(\w{15})(?:;(\d+))?$/) {
|
||||
($action, $spid, $authcode, $splid) = ($1, $2, $3, $4);
|
||||
}
|
||||
$title = "Error";
|
||||
if ($action =~ /(?:touch|close|unlock|lock)/) {
|
||||
$title = "Request #$spid";
|
||||
}
|
||||
return;
|
||||
|
||||
_code?><?page
|
||||
title=><?_code return $title; _code?>
|
||||
body<=
|
||||
<?_code
|
||||
|
||||
if ($title eq "Error") {
|
||||
return "<?h1 Error h1?><?p Improper arguments. p?>";
|
||||
}
|
||||
my $remote = LJ::get_remote();
|
||||
|
||||
LJ::Support::init_remote($remote);
|
||||
my $sp = LJ::Support::load_request($spid);
|
||||
|
||||
if ($sp->{'authcode'} ne $authcode) {
|
||||
return "<?h1 Error h1?><?p Invalid authcode. p?>";
|
||||
}
|
||||
|
||||
if ($action eq "touch") {
|
||||
return "<?h1 Error h1?><?p That request has been locked and cannot be reopened. p?>"
|
||||
if LJ::Support::is_locked($sp);
|
||||
|
||||
LJ::Support::touch_request($spid)
|
||||
or return "<?h1 Error h1?><?p Touch failed. p?>";
|
||||
|
||||
$ret .= ("<?h1 Touched h1?><?p Your support request ".
|
||||
($sp->{'state'} eq "open" ? "will stay open now."
|
||||
: "has been re-opened now.").
|
||||
" Please comment back telling us why you've touched this request:".
|
||||
" p?>");
|
||||
|
||||
my $auth = LJ::Support::mini_auth($sp);
|
||||
|
||||
$ret .= '<br /><form method="post" action="append_request.bml">';
|
||||
# hidden values
|
||||
$ret .= "<input type=\"hidden\" name=\"spid\" value=\"$spid\" />\n";
|
||||
$ret .= "<input type=\"hidden\" name=\"auth\" value=\"$auth\" />\n";
|
||||
$ret .= "<table border='0'>\n";
|
||||
|
||||
$ret .= '<tr valign="middle"><td align="right">From:</td><td>';
|
||||
if ($remote && $remote->{'userid'}) {
|
||||
$ret .= "<?ljuser $remote->{'user'} ljuser?>";
|
||||
} else {
|
||||
$ret .= "(not logged in)";
|
||||
}
|
||||
$ret .= "</td></tr>\n";
|
||||
|
||||
$ret .= "<tr><td align='right'>Reply Type:</td><td>";
|
||||
$ret .= '<input type="hidden" name="replytype" value="comment" />';
|
||||
$ret .= "<b>More Information</b>";
|
||||
|
||||
$ret .= "</td></tr>";
|
||||
|
||||
# textarea for their message body
|
||||
$ret .= '<tr valign="top"><td align="right">Message:</td><td colspan="2">';
|
||||
$ret .= '<textarea rows="10" cols="50" name="body"></textarea><br />';
|
||||
$ret .= "\n<?de No HTML allowed, so don't worry about about escaping < and ><br />URLs are automatically link-ified, so just reference those. de?><br />\n";
|
||||
$ret .= '<input type="submit" name="submitpost" value="Post Comment/Solution" />';
|
||||
$ret .= "\n</td></tr></table></form>";
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
if ($action eq 'lock') {
|
||||
return "<?h1 Error h1?><?p You are not allowed to lock this request. p?>"
|
||||
unless $remote && LJ::Support::can_lock($sp, $remote);
|
||||
return "<?h1 Error h1?><?p That request has already been locked. p?>"
|
||||
if LJ::Support::is_locked($sp);
|
||||
|
||||
# close this request and IC on it
|
||||
LJ::Support::lock($sp);
|
||||
LJ::Support::append_request($sp, {
|
||||
body => '(Locking request.)',
|
||||
remote => $remote,
|
||||
type => 'internal',
|
||||
});
|
||||
return "<?h1 Success h1?><?p The <a href='/support/see_request.bml?id=$sp->{spid}'>request</a> has been locked. p?>";
|
||||
}
|
||||
|
||||
if ($action eq 'unlock') {
|
||||
return "<?h1 Error h1?><?p You are not allowed to unlock this request. p?>"
|
||||
unless $remote && LJ::Support::can_lock($sp, $remote);
|
||||
return "<?h1 Error h1?><?p That request is not locked. p?>"
|
||||
unless LJ::Support::is_locked($sp);
|
||||
|
||||
# reopen this request and IC on it
|
||||
LJ::Support::unlock($sp);
|
||||
LJ::Support::append_request($sp, {
|
||||
body => '(Unlocking request.)',
|
||||
remote => $remote,
|
||||
type => 'internal',
|
||||
});
|
||||
return "<?h1 Success h1?><?p This <a href='/support/see_request.bml?id=$sp->{spid}'>request</a> has been unlocked. p?>";
|
||||
}
|
||||
|
||||
if ($action eq "close") {
|
||||
if ($sp->{'state'} eq "open") {
|
||||
my $dbh = LJ::get_db_writer();
|
||||
$splid += 0;
|
||||
if ($splid) {
|
||||
$sth = $dbh->prepare("SELECT userid, timelogged, spid, type FROM supportlog WHERE splid=$splid");
|
||||
$sth->execute;
|
||||
my ($userid, $timelogged, $aspid, $type) = $sth->fetchrow_array;
|
||||
|
||||
if ($aspid != $spid) {
|
||||
return "<?h1 Error h1?><?p The answer you credited for helping you out was not a response to your support request. If you copied a URL to get here, make sure you copied the entire URL correctly.p?>";
|
||||
}
|
||||
|
||||
## can't credit yourself.
|
||||
if ($userid != $sp->{'requserid'} && $type eq "answer") {
|
||||
my $cats = LJ::Support::load_cats($sp->{'spcatid'});
|
||||
my $secold = $timelogged - $sp->{'timecreate'};
|
||||
my $points = LJ::Support::calc_points($sp, $secold);
|
||||
LJ::Support::set_points($spid, $userid, $points);
|
||||
}
|
||||
}
|
||||
$dbh->do("UPDATE support SET state='closed', timeclosed=UNIX_TIMESTAMP() WHERE spid=$spid");
|
||||
}
|
||||
|
||||
my $remote = LJ::get_remote();
|
||||
my $is_admin = LJ::check_priv($remote, "supportclose");
|
||||
if ($is_admin)
|
||||
{
|
||||
my $dbr = LJ::get_db_reader();
|
||||
my $catid = $sp->{'_cat'}->{'spcatid'};
|
||||
my $sql = "SELECT MIN(spid) FROM support WHERE spcatid=$catid AND state='open' AND timelasthelp>timetouched AND spid>$spid";
|
||||
my $sth = $dbr->prepare($sql);
|
||||
$sth->execute;
|
||||
my $next = $sth->fetchrow_array;
|
||||
if ($next) {
|
||||
return BML::redirect("$LJ::SITEROOT/support/see_request.bml?id=$next");
|
||||
} else {
|
||||
return "<?h1 Closed h1?>
|
||||
<ul>
|
||||
<li>Go back to <a href='see_request.bml?id=$sp->{'spid'}'>Request #$sp->{'spid'}</a></li>
|
||||
<li>Go back to the <a href='help.bml'>open support requests</a></li>
|
||||
<li>Go back to the <a href='help.bml?cat=$sp->{'_cat'}->{'catkey'}'>open support requests in the the same category</a></li>
|
||||
<li>Go to <a href='see_request.bml?id=$sp->{'spid'}&find=prev'>previous</a> /
|
||||
<a href='see_request.bml?id=$sp->{'spid'}&find=next'>next</a> open request</li>
|
||||
<li>Go to <a href='see_request.bml?id=$sp->{'spid'}&find=cprev'>previous</a> /
|
||||
<a href='see_request.bml?id=$sp->{'spid'}&find=cnext'>next</a> open request in the same category</li>
|
||||
</ul>";
|
||||
}
|
||||
}
|
||||
|
||||
return "<?h1 Closed h1?><?p The support request has been closed. p?>";
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
_code?>
|
||||
|
||||
<=body
|
||||
page?><?_c <LJDEP>
|
||||
link: htdocs/support/see_request.bml
|
||||
</LJDEP> _c?>
|
||||
82
livejournal/htdocs/support/actmulti.bml
Executable file
82
livejournal/htdocs/support/actmulti.bml
Executable file
@@ -0,0 +1,82 @@
|
||||
<?page
|
||||
title=>Support Request Management
|
||||
body<=
|
||||
<?_code
|
||||
{
|
||||
use strict;
|
||||
use vars qw(%POST);
|
||||
|
||||
my $remote = LJ::get_remote();
|
||||
return "<?needlogin?>" unless $remote;
|
||||
|
||||
my $spcatid = $POST{spcatid};
|
||||
my $cat = LJ::Support::load_cats($spcatid);
|
||||
return "<?h1 Error h1?><?p That category doesn't exist. p?>" unless $cat;
|
||||
|
||||
# get ids of requests
|
||||
my @ids = map { $_+0 } grep { $POST{"check_$_"} } split(':', $POST{ids});
|
||||
return "<?h1 Error h1?><?p No request ids were provided to act on. p?>" unless @ids;
|
||||
|
||||
# just to be sane, limit it to 1000 requests
|
||||
@ids = splice @ids, 0, 1000 if scalar @ids > 1000;
|
||||
|
||||
# what action are they trying to take?
|
||||
if ($POST{'action:close'}) {
|
||||
my $can_close = 0;
|
||||
$can_close = 1 if LJ::check_priv($remote, 'supportclose', $cat->{catkey});
|
||||
$can_close = 1 if $cat->{public_read} && LJ::check_priv($remote, 'supportclose', '');
|
||||
return "<?h1 Error h1?><?p You don't have access to close requests in that category. p?>" unless $can_close;
|
||||
|
||||
# now close all of these requests
|
||||
my $dbh = LJ::get_db_writer();
|
||||
my $in = join ',', @ids;
|
||||
$dbh->do("UPDATE support SET state='closed', timeclosed=UNIX_TIMESTAMP() " .
|
||||
"WHERE spid IN ($in) AND spcatid = ?", undef, $spcatid);
|
||||
|
||||
# and now insert a log comment for all of these... note that we're not using
|
||||
# LJ::Support::append_request because that'd require us to load a bunch of requests
|
||||
# and then do a bunch of individual queries, and that sucks.
|
||||
my @stmts;
|
||||
foreach (@ids) {
|
||||
push @stmts, "($_, UNIX_TIMESTAMP(), 'internal', $remote->{userid}, " .
|
||||
"'(Request closed as part of mass closure.)')";
|
||||
}
|
||||
my $sql = "INSERT INTO supportlog (spid, timelogged, type, userid, message) VALUES ";
|
||||
$sql .= join ',', @stmts;
|
||||
$dbh->do($sql);
|
||||
|
||||
# return redirection back? or success message otherwise
|
||||
return BML::redirect($POST{ret}) if $POST{ret};
|
||||
return "<?h1 Success h1?><?p The requests you have specified have been closed. p?>";
|
||||
} elsif ($POST{'action:move'}) {
|
||||
return "<?h1 Error h1?><?p You don't have access to move requests out of this category. p?>"
|
||||
unless LJ::Support::can_perform_actions({ _cat => $cat }, $remote);
|
||||
|
||||
my $newcat = $POST{'changecat'} + 0;
|
||||
my $cats = LJ::Support::load_cats();
|
||||
return "<?h1 Error h1?><?p Category invalid. p?>" unless $cats->{$newcat};
|
||||
|
||||
# now move all of these requests
|
||||
my $dbh = LJ::get_db_writer();
|
||||
my $in = join ',', @ids;
|
||||
$dbh->do("UPDATE support SET spcatid = ? WHERE spid IN ($in) AND spcatid = ?",
|
||||
undef, $newcat, $spcatid);
|
||||
|
||||
# now add movement notices
|
||||
my @stmts;
|
||||
foreach (@ids) {
|
||||
push @stmts, "($_, UNIX_TIMESTAMP(), 'internal', $remote->{userid}, " .
|
||||
"'(Mass move from $cats->{$spcatid}->{catname} to $cats->{$newcat}->{catname}.)')";
|
||||
}
|
||||
my $sql = "INSERT INTO supportlog (spid, timelogged, type, userid, message) VALUES ";
|
||||
$sql .= join ',', @stmts;
|
||||
$dbh->do($sql);
|
||||
|
||||
# done now
|
||||
return BML::redirect($POST{ret}) if $POST{ret};
|
||||
return "<?h1 Success h1?><?p The requests have been moved. p?>";
|
||||
}
|
||||
}
|
||||
_code?>
|
||||
<=body
|
||||
page?>
|
||||
246
livejournal/htdocs/support/append_request.bml
Executable file
246
livejournal/htdocs/support/append_request.bml
Executable file
@@ -0,0 +1,246 @@
|
||||
<?page
|
||||
title=>Append Request
|
||||
body<=
|
||||
|
||||
<?_code
|
||||
{
|
||||
use strict;
|
||||
use vars qw(%FORM);
|
||||
|
||||
LJ::set_active_crumb('supportappend');
|
||||
|
||||
my $apache_req = shift;
|
||||
my $r = $apache_req->{'r'};
|
||||
|
||||
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 LJ::bad_input($ML{'.login.required'});
|
||||
}
|
||||
|
||||
if ($remote && ! $remote->tosagree_verify) {
|
||||
my $ret = "<?h1 " . LJ::tosagree_str('support' => 'title') . " h1?>";
|
||||
|
||||
my $html_str = LJ::tosagree_str('support' => 'html');
|
||||
if ($html_str) {
|
||||
$ret .= "<?p $html_str p?>";
|
||||
} else {
|
||||
$ret .= BML::ml
|
||||
('tos.mustread',
|
||||
{ aopts => "target='_new' href='$LJ::SITEROOT/legal/tos.bml'" });
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
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();
|
||||
return LJ::bad_input($ML{'.invalid.nosummary'})
|
||||
if $FORM{'changesum'} && ! LJ::trim($FORM{'summary'});
|
||||
|
||||
### links to show on success
|
||||
my $auth_arg = $FORM{'auth'} ? "&auth=$FORM{'auth'}" : "";
|
||||
my $successlinks = BML::ml('.successlinks',
|
||||
{ 'number' => $sp->{'spid'},
|
||||
'back' => "see_request.bml?id=$sp->{'spid'}$auth_arg",
|
||||
'open' => "help.bml",
|
||||
'opencat' => "help.bml?cat=$scat->{'catkey'}",
|
||||
'prevopen' => "see_request.bml?id=$sp->{'spid'}&find=prev",
|
||||
'nextopen' => "see_request.bml?id=$sp->{'spid'}&find=next",
|
||||
'cprevopen' => "see_request.bml?id=$sp->{'spid'}&find=cprev",
|
||||
'cnextopen' => "see_request.bml?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 $type = $FORM{'replytype'};
|
||||
return LJ::bad_input($ML{'.invalid.type'}) unless defined $answer_types{$type};
|
||||
|
||||
## can we do the action we want?
|
||||
return LJ::bad_input($ML{'.internal.approve'})
|
||||
if $FORM{'approveans'} && ($type ne "internal" || ! LJ::Support::can_help($sp, $remote));
|
||||
|
||||
return LJ::bad_input($ML{'.internal.changecat'})
|
||||
if $FORM{'changecat'} && ($type ne "internal" || ! LJ::Support::can_perform_actions($sp, $remote));
|
||||
|
||||
return LJ::bad_input($ML{'.internal.touch'})
|
||||
if ($FORM{'touch'} || $FORM{'untouch'}) &&
|
||||
($type ne "internal" || ! LJ::Support::can_perform_actions($sp, $remote));
|
||||
|
||||
return LJ::bad_input($ML{'.internal.changesum'})
|
||||
if $FORM{'changesum'} && ($type ne "internal" || ! LJ::Support::can_change_summary($sp, $remote));
|
||||
|
||||
return LJ::bad_input($ML{'.invalid.blank'})
|
||||
if $FORM{'body'} !~ /\S/ && !$FORM{'approveans'} && !$FORM{'changecat'} &&
|
||||
!$FORM{'touch'} && !$FORM{'untouch'} && !$FORM{'changesum'};
|
||||
|
||||
# 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 WHERE spid=$spid");
|
||||
$status .= "(Inserting request into queue)\n\n";
|
||||
}
|
||||
if ($FORM{'untouch'}) {
|
||||
$dbh->do("UPDATE support SET timelasthelp=UNIX_TIMESTAMP() WHERE spid=$spid");
|
||||
$status .= "(Removing request from queue)\n\n";
|
||||
}
|
||||
|
||||
## bounce request to email
|
||||
if ($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 lj username
|
||||
unless ($email =~ /\@/) {
|
||||
my $eu = LJ::load_user($email); # $email is a username
|
||||
$email = $eu->{'email'} if $eu;
|
||||
}
|
||||
|
||||
LJ::check_email($email, \@email_errors);
|
||||
@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->notes('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.bml?id=$sp->{'spid'}",
|
||||
});
|
||||
|
||||
# close request, nobody gets credited
|
||||
$dbh->do("UPDATE support SET state='closed', timeclosed=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 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
|
||||
}
|
||||
|
||||
## 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 = LJ::Support::append_request($sp, {
|
||||
'body' => $status . $FORM{'body'},
|
||||
'type' => $type,
|
||||
'faqid' => $faqid,
|
||||
'uniq' => $r->notes('uniq'),
|
||||
'remote' => $remote,
|
||||
});
|
||||
|
||||
LJ::Support::mail_response_to_user($sp, $splid);
|
||||
|
||||
return "<?h1 $ML{'.logged.title'} h1?><?p $ML{'.logged.text'} p?>" . $successlinks;
|
||||
}
|
||||
_code?>
|
||||
<?hr?>
|
||||
Back to the <A HREF="help.bml">list of open requests</A>.<BR>
|
||||
Back to the <A HREF="./">support area</A>.
|
||||
|
||||
<=body
|
||||
page?><?_c <LJDEP>
|
||||
link: htdocs/login.bml, htdocs/support/see_request.bml, htdocs/support/help.bml
|
||||
link: htdocs/support/index.bml
|
||||
</LJDEP> _c?>
|
||||
106
livejournal/htdocs/support/changenotify.bml
Executable file
106
livejournal/htdocs/support/changenotify.bml
Executable file
@@ -0,0 +1,106 @@
|
||||
<?_info
|
||||
nocache=>1
|
||||
_info?><?page
|
||||
title=>Change Notifications
|
||||
body<=
|
||||
|
||||
<?_code
|
||||
|
||||
LJ::set_active_crumb('supportnotify');
|
||||
|
||||
my @errors = ();
|
||||
|
||||
my $remote = LJ::get_remote();
|
||||
my $mode = $FORM{'mode'} || "modify";
|
||||
|
||||
unless ($remote) {
|
||||
push @errors, "You must first <a href=\"/login.bml?ret=1\">login</a>.";
|
||||
}
|
||||
if ($mode eq "save" && ! LJ::did_post) {
|
||||
push @errors, "<?requirepost?>";
|
||||
}
|
||||
return LJ::bad_input(@errors) if @errors;
|
||||
|
||||
LJ::Support::init_remote($remote);
|
||||
my $cats = LJ::Support::load_cats();
|
||||
my @filter_cats = LJ::Support::filter_cats($remote, $cats);
|
||||
|
||||
if ($mode eq "modify")
|
||||
{
|
||||
my $ret = "";
|
||||
$ret .= "<form method='post' action='changenotify.bml'>\n";
|
||||
$ret .= "<input type='hidden' name='mode' value='save' />\n";
|
||||
|
||||
$ret .= "<?h1 Change Notification Settings h1?><?p Here you may select what categories of support requests you'd like to be notified about. Choices are <b>off</b> (the default), <b>new</b> (you'll get notifications when a new support request in that category is posted) or <b>all</b> (you'll get notifications and then a copy of each comment/solution posted). p?>";
|
||||
|
||||
my %notify;
|
||||
my $dbr = LJ::get_db_reader();
|
||||
$sth = $dbr->prepare("SELECT spcatid, level FROM supportnotify WHERE userid=$remote->{'userid'}");
|
||||
$sth->execute;
|
||||
while (my ($spcatid, $level) = $sth->fetchrow_array) {
|
||||
## if user used to be able to read a category, subscribed, then lost
|
||||
## privs, this ensures any future save will turn off things they
|
||||
## don't have access to:
|
||||
if (LJ::Support::can_read_cat($cats->{$spcatid}, $remote)) {
|
||||
$notify{$spcatid} = $level;
|
||||
}
|
||||
}
|
||||
|
||||
my %valname = ("off" => "Off.",
|
||||
"new" => "New only.",
|
||||
"all" => "All",
|
||||
);
|
||||
|
||||
$ret .= "<div style='margin-left: 30px'>\n";
|
||||
foreach my $cat (@filter_cats) {
|
||||
$ret .= "<p><select name='spcatid_$cat->{'spcatid'}'>";
|
||||
foreach my $val ("off", "new", "all") {
|
||||
my $sel = "";
|
||||
if ($notify{$cat->{'spcatid'}} eq $val) { $sel = " selected='selected'"; }
|
||||
$ret .= "<option value='$val'$sel>$valname{$val}</option>\n";
|
||||
}
|
||||
$ret .= "</select> $cat->{'catname'}</p>\n";
|
||||
}
|
||||
$ret .= "</div>\n";
|
||||
|
||||
|
||||
### ending submit block
|
||||
$ret .= "<?h1 Done? h1?><?p When done, press the \"Save Changes\" button below... p?>\n";
|
||||
$ret .= "<?standout <input type='submit' value='Save Changes' /> standout?>\n";
|
||||
$ret .= "</form>\n";
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
if ($mode eq "save")
|
||||
{
|
||||
my $dbh = LJ::get_db_writer();
|
||||
$dbh->do("DELETE FROM supportnotify WHERE userid=$remote->{'userid'}");
|
||||
my $sql;
|
||||
|
||||
foreach my $cat (@filter_cats)
|
||||
{
|
||||
my $id = $cat->{'spcatid'};
|
||||
my $setting = $FORM{"spcatid_$id"};
|
||||
if ($setting eq "all" ||
|
||||
$setting eq "new")
|
||||
{
|
||||
if ($sql) { $sql .= ", "; }
|
||||
else { $sql .= "REPLACE INTO supportnotify (spcatid, userid, level) VALUES "; }
|
||||
$sql .= "($id, $remote->{'userid'}, '$setting')";
|
||||
}
|
||||
}
|
||||
if ($sql) { $dbh->do($sql); }
|
||||
|
||||
return "<?h1 Success h1?><?p Your notification settings have been updated. p?>";
|
||||
}
|
||||
|
||||
return "Unknown mode."
|
||||
|
||||
_code?>
|
||||
|
||||
<=body
|
||||
page?><?_c <LJDEP>
|
||||
link: htdocs/login.bml
|
||||
post: htdocs/support/changenotify.bml
|
||||
</LJDEP> _c?>
|
||||
19
livejournal/htdocs/support/encodings.bml
Executable file
19
livejournal/htdocs/support/encodings.bml
Executable file
@@ -0,0 +1,19 @@
|
||||
<?_code
|
||||
|
||||
LJ::set_active_crumb('encodings');
|
||||
|
||||
$title = $ML{'.title'};
|
||||
$body = "";
|
||||
|
||||
$body .= "<?h1 $ML{'.overview.header'} h1?>$ML{'.overview.text'}";
|
||||
$body .= "<?h1 $ML{'.edit.header'} h1?>$ML{'.edit.text'}";
|
||||
$body .= "<?h1 $ML{'.editcl.header'} h1?>$ML{'.editcl.text'}";
|
||||
$body .= "<?h1 $ML{'.groups.header'} h1?>$ML{'.groups.text'}";
|
||||
$body .= "<?h1 $ML{'.still.header'} h1?>$ML{'.still.text'}";
|
||||
|
||||
return;
|
||||
|
||||
_code?><?page
|
||||
title=><?_code return $title; _code?>
|
||||
body=><?_code return $body; _code?>
|
||||
page?>
|
||||
95
livejournal/htdocs/support/faq.bml
Executable file
95
livejournal/htdocs/support/faq.bml
Executable file
@@ -0,0 +1,95 @@
|
||||
<?page
|
||||
title=>FAQ
|
||||
body<=
|
||||
|
||||
<?h1 Frequently Asked Questions h1?>
|
||||
<?p
|
||||
Below are some frequently asked questions, and answers, too! Oh boy. Try to read this before you ask a new question. If you know something we should add to this, let us know.
|
||||
p?>
|
||||
|
||||
<?_code
|
||||
|
||||
use strict;
|
||||
use vars qw(%GET);
|
||||
|
||||
LJ::set_active_crumb('faq');
|
||||
|
||||
my $curlang = BML::get_language();
|
||||
my $deflang = BML::get_language_default();
|
||||
my $altlang = $curlang ne $deflang;
|
||||
my ($mll, $mld);
|
||||
if ($altlang) {
|
||||
$mll = LJ::Lang::get_lang($curlang);
|
||||
$mld = LJ::Lang::get_dom("faq");
|
||||
$altlang = 0 unless $mll && $mld;
|
||||
}
|
||||
|
||||
my $dbr = LJ::get_db_reader(); my $sth;
|
||||
my %faqcat; my %faqq;
|
||||
my $ret = "";
|
||||
if ($altlang) {
|
||||
my $sql = "SELECT fc.faqcat, t.text AS 'faqcatname', fc.catorder FROM faqcat fc, ".
|
||||
"ml_text t, ml_latest l, ml_items i WHERE ".
|
||||
"t.dmid=$mld->{'dmid'} AND l.dmid=$mld->{'dmid'} AND i.dmid=$mld->{'dmid'} AND ".
|
||||
"l.lnid=$mll->{'lnid'} AND l.itid=i.itid AND i.itcode=CONCAT('cat.', fc.faqcat) ".
|
||||
"AND l.txtid=t.txtid AND fc.faqcat<>'int-abuse'";
|
||||
$sth = $dbr->prepare($sql);
|
||||
} else {
|
||||
$sth = $dbr->prepare("SELECT faqcat, faqcatname, catorder FROM faqcat ".
|
||||
"WHERE faqcat<>'int-abuse'");
|
||||
}
|
||||
$sth->execute;
|
||||
while ($_ = $sth->fetchrow_hashref) {
|
||||
$faqcat{$_->{'faqcat'}} = $_;
|
||||
}
|
||||
|
||||
if ($altlang) {
|
||||
my $sql = "SELECT f.faqid, t.text AS 'question', f.sortorder, ".
|
||||
"f.faqcat, f.lastmodtime FROM faq f, ".
|
||||
"ml_text t, ml_latest l, ml_items i WHERE ".
|
||||
"t.dmid=$mld->{'dmid'} AND l.dmid=$mld->{'dmid'} AND i.dmid=$mld->{'dmid'} AND ".
|
||||
"l.lnid=$mll->{'lnid'} AND l.itid=i.itid AND i.itcode=CONCAT(f.faqid, '.1question') ".
|
||||
"AND l.txtid=t.txtid AND f.faqcat<>'int-abuse'";
|
||||
$sth = $dbr->prepare($sql);
|
||||
} else {
|
||||
$sth = $dbr->prepare("SELECT faqid, question, sortorder, faqcat, lastmodtime ".
|
||||
"FROM faq WHERE faqcat<>'int-abuse'");
|
||||
}
|
||||
$sth->execute;
|
||||
while ($_ = $sth->fetchrow_hashref) {
|
||||
$faqq{$_->{'faqid'}} = $_;
|
||||
}
|
||||
|
||||
foreach my $faqcat (sort { $faqcat{$a}->{'catorder'} <=>
|
||||
$faqcat{$b}->{'catorder'} } keys %faqcat)
|
||||
{
|
||||
next if $GET{'cat'} && $GET{'cat'} ne $faqcat;
|
||||
$ret .= "<?h2 ";
|
||||
$ret .= LJ::ehtml($faqcat{$faqcat}->{'faqcatname'});
|
||||
$ret .= " (<a href='faqbrowse.bml?faqcat=$faqcat'>";
|
||||
$ret .= "view all";
|
||||
$ret .= "</a>) h2?>\n";
|
||||
$ret .= "<ul>\n";
|
||||
foreach my $faqid (sort { $faqq{$a}->{'sortorder'} <=> $faqq{$b}->{'sortorder'} } grep { $faqq{$_}->{'faqcat'} eq $faqcat } keys %faqq)
|
||||
{
|
||||
next unless ($faqq{$faqid}->{'question'});
|
||||
BML::note_mod_time($faqq{$faqid}->{'lastmodtime'});
|
||||
my $q = LJ::ehtml($faqq{$faqid}->{'question'});
|
||||
$q =~ s/^\s+//; $q =~ s/\s+$//;
|
||||
$q =~ s!\n!<br />!g;
|
||||
$ret .= "<li><a href='faqbrowse.bml?faqid=$faqid'>$q</a></li>\n";
|
||||
}
|
||||
$ret .= "</ul>\n";
|
||||
}
|
||||
|
||||
return $ret;
|
||||
|
||||
_code?>
|
||||
|
||||
<?hr?>
|
||||
<p>Back to <a href="./">the support area</a>.</p>
|
||||
|
||||
<=body
|
||||
page?><?_c <LJDEP>
|
||||
link: htdocs/support/faqbrowse.bml, htdocs/support/index.bml
|
||||
</LJDEP> _c?>
|
||||
141
livejournal/htdocs/support/faqbrowse.bml
Executable file
141
livejournal/htdocs/support/faqbrowse.bml
Executable file
@@ -0,0 +1,141 @@
|
||||
<?page
|
||||
body<=
|
||||
<?_code
|
||||
{
|
||||
use strict;
|
||||
use vars qw(%GET);
|
||||
|
||||
# make title and body references to BML scratch area
|
||||
my $title = \$_[1]->{'title'};
|
||||
my $body = \$_[1]->{'body'};
|
||||
$$body = '';
|
||||
$$title = '';
|
||||
|
||||
# get faqid and redirect to faq.bml if none
|
||||
my $faqid = $GET{'faqid'} + 0;
|
||||
my $faqcat = $GET{'faqcat'};
|
||||
|
||||
my $where;
|
||||
|
||||
my $dbr = LJ::get_db_reader();
|
||||
# loading single faqid
|
||||
if ($faqid) {
|
||||
$$title = BML::ml('.title_num', { 'num' => $faqid });
|
||||
$where = "faqid=$faqid";
|
||||
|
||||
# loading entire faqcat
|
||||
} elsif ($faqcat) {
|
||||
my $catname = $dbr->selectrow_array("SELECT faqcatname FROM faqcat WHERE faqcat=?",
|
||||
undef, $faqcat);
|
||||
$$title = BML::ml('.title_cat', { 'catname' => LJ::ehtml($catname) });
|
||||
|
||||
$where = "faqcat=" . $dbr->quote($faqcat);
|
||||
|
||||
# no faqid or faqcat specified, redirect
|
||||
} else {
|
||||
return BML::redirect("faq.bml");
|
||||
}
|
||||
|
||||
my $remote = LJ::get_remote();
|
||||
|
||||
# get language settings
|
||||
my $curlang = BML::get_language();
|
||||
my $deflang = BML::get_language_default();
|
||||
my $altlang = $curlang ne $deflang;
|
||||
my $mld;
|
||||
if ($altlang) {
|
||||
my $mll = LJ::Lang::get_lang($curlang);
|
||||
$mld = LJ::Lang::get_dom("faq");
|
||||
$altlang = 0 unless $mll && $mld;
|
||||
}
|
||||
|
||||
# query db and get data
|
||||
my $sth = $dbr->prepare("SELECT faqid, question, answer, faqcat, lastmoduserid, ".
|
||||
"DATE_FORMAT(lastmodtime, '%Y-%m-%d'), ".
|
||||
"UNIX_TIMESTAMP(lastmodtime) FROM faq ".
|
||||
"WHERE $where ORDER BY sortorder");
|
||||
$sth->execute;
|
||||
if ($dbr->err) {
|
||||
$$title = $ML{'Error'};
|
||||
$$body = "$ML{'error.dberror'} <ul><li>" . $dbr->errstr . "</li></ul>\n";
|
||||
return;
|
||||
}
|
||||
|
||||
my $count = 0;
|
||||
my $dbh;
|
||||
my $backfaqcat;
|
||||
while (my ($faqid, $question, $answer, $faqcat, $lastmoduserid,
|
||||
$lastmodtime, $unixmodtime) = $sth->fetchrow_array)
|
||||
{
|
||||
|
||||
$dbh ||= LJ::get_db_writer();
|
||||
|
||||
# log this faq view
|
||||
if ($remote && ! $LJ::DISABLED{faquses}) {
|
||||
$dbh->do("REPLACE INTO faquses (faqid, userid, dateview) ".
|
||||
"VALUES ($faqid, ?, NOW())", undef, $remote->{'userid'});
|
||||
}
|
||||
|
||||
BML::note_mod_time($unixmodtime);
|
||||
|
||||
# it'd be better to load them in a batch, but this works for now:
|
||||
if ($altlang) {
|
||||
$question = LJ::Lang::get_text($curlang, "$faqid.1question", $mld->{'dmid'});
|
||||
$answer = LJ::Lang::get_text($curlang, "$faqid.2answer", $mld->{'dmid'});
|
||||
}
|
||||
|
||||
# escape question and answers
|
||||
my $q = LJ::ehtml($question);
|
||||
$q =~ s/^\s+//; $q =~ s/\s+$//;
|
||||
$q =~ s/\n/<br \/>/g;
|
||||
|
||||
my $a = LJ::ehtml($answer);
|
||||
$a =~ s/^\s+//; $a =~ s/\s+$//;
|
||||
$a =~ s/\n( +)/"\n" . " "x length($1)/eg;
|
||||
$a =~ s/\n/<br \/>/g;
|
||||
|
||||
$a = LJ::auto_linkify($a);
|
||||
|
||||
# display output
|
||||
$$body .= "<?h1";
|
||||
if ($faqcat) {
|
||||
$$body .= " <a style='text-decoration: none;' " .
|
||||
"href='faqbrowse.bml?faqid=$faqid'>»</a>";
|
||||
}
|
||||
$$body .= " $q h1?><div style='margin-left: 20px;'>$a</div>";
|
||||
|
||||
my $lastmodwho = LJ::get_username($lastmoduserid);
|
||||
if ($lastmodwho) {
|
||||
$$body .= "<p align=\"right\"><b>$ML{'.lastupdated'}</b><br />$lastmodwho, $lastmodtime</p>";
|
||||
}
|
||||
if (LJ::check_priv($remote, "faqedit", "*") ||
|
||||
LJ::check_priv($remote, "faqedit", $faqcat))
|
||||
{
|
||||
$$body .= "<p align=\"right\"><a href=\"/admin/faq/faqedit.bml?id=$faqid\">$ML{'.edit.faq'}</a></p>";
|
||||
}
|
||||
|
||||
$count++;
|
||||
$backfaqcat = $faqcat;
|
||||
}
|
||||
|
||||
# nothing found?
|
||||
unless ($count) {
|
||||
$$title = $ML{'Error'};
|
||||
$$body .= "<p><b>$ML{'.error.nofaq'}</b></p>\n";
|
||||
}
|
||||
|
||||
$$body .= "<?hr?>";
|
||||
$$body .= BML::ml('.backfaqcat',{'faqcat'=>$backfaqcat,}) . "<br />" if $backfaqcat && $faqid;
|
||||
$$body .= "$ML{'.backfaq'}<br />$ML{'.backsupport'}";
|
||||
|
||||
# we're dynamic, set title as crumb title
|
||||
LJ::set_dynamic_crumb($_[1]->{'title'}, 'faq');
|
||||
|
||||
return $_[1]->{'body'};
|
||||
}
|
||||
_code?>
|
||||
<=body
|
||||
title=><?_code return $_[1]->{'title'}; _code?>
|
||||
page?><?_c <LJDEP>
|
||||
link: htdocs/support/index.bml, htdocs/support/faq.bml
|
||||
</LJDEP> _c?>
|
||||
40
livejournal/htdocs/support/faqpop.bml
Executable file
40
livejournal/htdocs/support/faqpop.bml
Executable file
@@ -0,0 +1,40 @@
|
||||
<?page
|
||||
title=>Popular FAQs
|
||||
body<=
|
||||
|
||||
<?h1 Popular Frequently Asked Questions h1?>
|
||||
<?p
|
||||
The following is a list of what questions people have been interested in during the past week, followed by the number of people that have read the answers:
|
||||
p?>
|
||||
|
||||
<?_code
|
||||
|
||||
LJ::set_active_crumb('popfaqs');
|
||||
|
||||
my $dbr = LJ::get_db_reader();
|
||||
$sth = $dbr->prepare("SELECT f.faqid, f.question, s.statval AS 'uses'".
|
||||
"FROM faq f, stats s WHERE f.faqcat<>'int-abuse' AND s.statcat='popfaq' ".
|
||||
"AND s.statkey=f.faqid ORDER BY s.statval DESC LIMIT 50");
|
||||
$sth->execute;
|
||||
|
||||
$ret .= "<ul>";
|
||||
while (my $f = $sth->fetchrow_hashref)
|
||||
{
|
||||
my $q = LJ::ehtml($f->{'question'});
|
||||
$q =~ s/^\s+//; $q =~ s/\s+$//;
|
||||
$q =~ s!\n!<br />!g;
|
||||
$ret .= "<li><a href=\"faqbrowse.bml?faqid=$f->{'faqid'}\">$q</a> <i>($f->{'uses'})</i></li>\n";
|
||||
}
|
||||
$ret .= "</ul>\n";
|
||||
|
||||
return $ret;
|
||||
|
||||
_code?>
|
||||
|
||||
<?hr?>
|
||||
<p>Back to <a href="./">the support area</a>.</p>
|
||||
|
||||
<=body
|
||||
page?><?_c <LJDEP>
|
||||
link: htdocs/support/faqbrowse.bml, htdocs/support/index.bml
|
||||
</LJDEP> _c?>
|
||||
351
livejournal/htdocs/support/help.bml
Executable file
351
livejournal/htdocs/support/help.bml
Executable file
@@ -0,0 +1,351 @@
|
||||
<?page
|
||||
head<=
|
||||
<style type='text/css'>
|
||||
.green {
|
||||
background-color: #d0eed0;
|
||||
}
|
||||
.yellow {
|
||||
background-color: #eeeed0;
|
||||
}
|
||||
.red {
|
||||
background-color: #eed0d0;
|
||||
}
|
||||
.clicked {
|
||||
background-color: #d0d0ee;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script type='text/javascript'>
|
||||
<!--
|
||||
|
||||
function doClick(spid) {
|
||||
if (!document.getElementById) { return; }
|
||||
var row = document.getElementById('r' + spid);
|
||||
var check = document.getElementById('check_' + spid);
|
||||
check.checked = !check.checked;
|
||||
if (check.checked) {
|
||||
row.className = 'clicked';
|
||||
} else {
|
||||
var hid = document.getElementById('c' + spid);
|
||||
row.className = hid.value;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// -->
|
||||
</script>
|
||||
<=head
|
||||
title=>Support Requests
|
||||
body<=
|
||||
|
||||
<?_code
|
||||
use strict;
|
||||
use vars qw(%FORM);
|
||||
|
||||
LJ::set_active_crumb('supporthelp');
|
||||
|
||||
my ($ret, $sth);
|
||||
my $dbr = LJ::get_db_reader();
|
||||
my $r = Apache->request;
|
||||
|
||||
my $remote = LJ::get_remote();
|
||||
LJ::Support::init_remote($remote);
|
||||
|
||||
return $ML{'.interim'} if
|
||||
(!$remote || !$remote->{'_priv'}) &&
|
||||
$r->header_in("Referer") eq "$LJ::SITEROOT/support/";
|
||||
|
||||
my $cats = LJ::Support::load_cats();
|
||||
|
||||
my $state = $FORM{'state'};
|
||||
$state = 'open' unless $state =~ /^(?:open|closed|green|youreplied)$/;
|
||||
|
||||
my $filtercat = $FORM{'cat'};
|
||||
$filtercat = "" unless ($filtercat =~ /^[\w\-]+$/);
|
||||
my $fcat = LJ::Support::get_cat_by_key($cats, $filtercat);
|
||||
my $can_read = LJ::Support::can_read_cat($fcat, $remote);
|
||||
|
||||
# determine if user can close stuff
|
||||
my $can_close = 0;
|
||||
if ($remote && $state =~ /(?:green|open)/ && $filtercat) {
|
||||
$can_close = 1 if LJ::check_priv($remote, 'supportclose', $filtercat); # private cats/only this cat
|
||||
$can_close = 1 if $fcat->{public_read} && LJ::check_priv($remote, 'supportclose', ''); # public cats
|
||||
}
|
||||
|
||||
my $append;
|
||||
if ($state eq "closed") {
|
||||
$ret .= "<?h1 Recently Closed Support Requests h1?><?p Below are all support requests " .
|
||||
"that have been recently closed. To return to the open requests, " .
|
||||
"<a href=\"$LJ::SITEROOT/support/help.bml?cat=$filtercat\">click here</a>. p?>";
|
||||
} elsif ($state eq "youreplied") {
|
||||
return "<?h1 Error h1?><?p You must be logged in to filter on requests that you've replied to. p?>"
|
||||
unless $remote;
|
||||
$ret .= "<?h1 Requests you replied to h1?><?p This shows all open requests you've replied to. p?>";
|
||||
} else {
|
||||
$ret .= "<?h1 Open Support Requests h1?><?p Below are all support requests that are open " .
|
||||
"(they just came in and haven't been touched yet) or answered (either awaiting to be " .
|
||||
"closed by the person needing help, or the person requested they still need help). " .
|
||||
"The <a href=\"$LJ::SITEROOT/support/help.bml?state=closed&cat=$filtercat\">closed reports</a> are also " .
|
||||
"available. If you help somebody out and they confirm you helped them, you get the number " .
|
||||
"of points indicated in the status column. These points will show up on your userinfo page. p?>";
|
||||
$append = 1;
|
||||
}
|
||||
|
||||
my @support_log;
|
||||
|
||||
# if we have a cat to filter to and we have abstracts for it
|
||||
my $rct = 0;
|
||||
my $abstracts = 0;
|
||||
if ($filtercat && $LJ::SUPPORT_ABSTRACTS{$filtercat} && $fcat && $can_read && $state ne 'youreplied') {
|
||||
# yes, we should show abstracts for this category, so do so
|
||||
if ($state eq "closed") {
|
||||
$sth = $dbr->prepare("SELECT s.*, SUBSTRING(sl.message, 1, 200) AS 'message' " .
|
||||
"FROM support s, supportlog sl " .
|
||||
"WHERE s.state='closed' AND s.spid = sl.spid AND sl.type = 'req' " .
|
||||
"AND s.timeclosed > (UNIX_TIMESTAMP() - (3600*24)) " .
|
||||
"AND s.spcatid = ?");
|
||||
} else { # triggers on green, open
|
||||
$sth = $dbr->prepare("SELECT s.*, SUBSTRING(sl.message, 1, 200) AS 'message' " .
|
||||
"FROM support s, supportlog sl " .
|
||||
"WHERE s.state='open' AND s.spid = sl.spid AND sl.type = 'req' " .
|
||||
"AND s.spcatid = ?");
|
||||
}
|
||||
$sth->execute($fcat->{spcatid});
|
||||
push @support_log, $_ while $_ = $sth->fetchrow_hashref();
|
||||
$rct = scalar(@support_log);
|
||||
$abstracts = 1;
|
||||
} else {
|
||||
my $filterwhere;
|
||||
|
||||
if ($filtercat eq "_nonpublic") {
|
||||
$filterwhere = " AND s.spcatid IN (0";
|
||||
foreach my $cat (values %$cats) {
|
||||
$filterwhere .= ", $cat->{'spcatid'}"
|
||||
if !$cat->{'public_read'} && LJ::Support::can_read_cat($cat, $remote);
|
||||
}
|
||||
$filterwhere .= ")";
|
||||
} elsif ($filtercat eq "_nonprivate") {
|
||||
$filterwhere = " AND s.spcatid IN (0";
|
||||
foreach my $cat (values %$cats) {
|
||||
$filterwhere .= ", $cat->{'spcatid'}" if $cat->{public_read};
|
||||
}
|
||||
$filterwhere .= ")";
|
||||
} else {
|
||||
if ($can_read) {
|
||||
$filterwhere = " AND s.spcatid=$fcat->{'spcatid'}";
|
||||
} else {
|
||||
$filtercat = "";
|
||||
}
|
||||
}
|
||||
|
||||
my $dbr = LJ::get_db_reader();
|
||||
if ($state eq "closed") {
|
||||
$sth = $dbr->prepare("SELECT s.* FROM support s WHERE s.state='closed' AND " .
|
||||
"s.timeclosed>UNIX_TIMESTAMP()-(3600*24) $filterwhere");
|
||||
} elsif ($state eq "youreplied") {
|
||||
$sth = $dbr->prepare("SELECT s.* FROM support s, support_youreplied yr " .
|
||||
"WHERE yr.userid=$remote->{'userid'} AND s.spid=yr.spid $filterwhere " .
|
||||
"AND (s.state='open' OR (s.state='closed' AND s.timeclosed>UNIX_TIMESTAMP()-(3600*24)))");
|
||||
} else { # triggers on green, open
|
||||
$sth = $dbr->prepare("SELECT s.* FROM support s WHERE s.state='open' $filterwhere");
|
||||
}
|
||||
$sth->execute;
|
||||
|
||||
# For the You Replied filter, we might be getting some rows multiple times (when
|
||||
# multiple log rows exist for $remote), which is still better than using DISTINCT
|
||||
# in the query which uses a temporary table, so ensure uniqueness here.
|
||||
my %spids_seen;
|
||||
while (my $sprow = $sth->fetchrow_hashref) {
|
||||
next if $spids_seen{$sprow->{'spid'}};
|
||||
$spids_seen{$sprow->{'spid'}} = 1;
|
||||
push @support_log, $sprow;
|
||||
$rct++;
|
||||
}
|
||||
}
|
||||
|
||||
my $sort = $FORM{sort};
|
||||
$sort = 'date' unless $sort =~ /^id|summary|area|date$/;
|
||||
|
||||
$ret .= "<p>[<b>$rct</b> total open requests]</p>" if $append;
|
||||
if ($sort eq 'id') {
|
||||
@support_log = sort { $a->{spid} <=> $b->{spid} } @support_log;
|
||||
} elsif ($sort eq 'date') {
|
||||
@support_log = sort { $b->{timecreate} <=> $a->{timecreate} } @support_log;
|
||||
} elsif ($sort eq 'summary') {
|
||||
@support_log = sort { $a->{subject} cmp $b->{subject} } @support_log;
|
||||
} elsif ($sort eq 'area') {
|
||||
@support_log = sort { $cats->{$a->{spcatid}}->{catname} cmp $cats->{$b->{spcatid}}->{catname} } @support_log;
|
||||
}
|
||||
|
||||
# filter line:
|
||||
$ret .= "<form method='get' action='help.bml'>Show only ";
|
||||
$ret .= "<input type='hidden' name='sort' value='$sort' />";
|
||||
$ret .= "<select name='state'>";
|
||||
{
|
||||
my @states = ("" => "Open",
|
||||
"closed" => "Closed",
|
||||
"green" => "Green");
|
||||
if ($remote) {
|
||||
push @states, ("youreplied", "You Replied");
|
||||
}
|
||||
while (@states) {
|
||||
my ($skey, $sname) = splice(@states, 0, 2);
|
||||
my $sel = $state eq $skey ? " selected='selected'" : "";
|
||||
$ret .= "<option value=\"$skey\"$sel>$sname</option>";
|
||||
}
|
||||
}
|
||||
$ret .= "</select>";
|
||||
|
||||
$ret .= " requests of type: <select name='cat'>";
|
||||
$ret .= "<option value=\"\">(All)</option>";
|
||||
my @filter_cats = LJ::Support::filter_cats($remote, $cats);
|
||||
if (LJ::check_priv($remote, "supportread")) {
|
||||
unshift @filter_cats, { 'catkey' => '_nonpublic',
|
||||
'catname' => '(Private)' };
|
||||
unshift @filter_cats, { 'catkey' => '_nonprivate',
|
||||
'catname' => '(Public)' };
|
||||
}
|
||||
foreach my $cat (@filter_cats)
|
||||
{
|
||||
my $sel = $filtercat eq $cat->{'catkey'} ? " selected='selected'" : "";
|
||||
$ret .= "<option value=\"$cat->{'catkey'}\"$sel>$cat->{'catname'}</option>";
|
||||
}
|
||||
$ret .= "</select>\n";
|
||||
$ret .= "<input type=submit value=\"Filter\" /></form>";
|
||||
# /filter line
|
||||
|
||||
# mass closing table
|
||||
$ret .= "<form method='post' action='/support/actmulti.bml'>" if $can_close;
|
||||
|
||||
# start the rest of the table
|
||||
my $uri = "$LJ::SITEROOT/support/help.bml?cat=$filtercat&state=$state";
|
||||
$ret .= "<p><table cellpadding='4' cellspacing='1' border='1' bgcolor='#ffffff'><tr bgcolor='#d0d0d0'>\n";
|
||||
$ret .= "<td> <b>X</b></td>\n" if $can_close;
|
||||
my @headers = ( id => "ID#", summary => "Summary", area => "Problem Area", date => "Posted" );
|
||||
while (my ($sorttype, $desc) = splice(@headers, 0, 2)) {
|
||||
if ($sort eq $sorttype) {
|
||||
$ret .= "<td><b>$desc</b></td>\n";
|
||||
} else {
|
||||
$ret .= "<td><b><a href='$uri&sort=$sorttype'>$desc</a></b></td>\n";
|
||||
}
|
||||
}
|
||||
$ret .= "<td><b>Status</b></td>\n";
|
||||
$ret .= "</tr>";
|
||||
|
||||
foreach my $sp (@support_log)
|
||||
{
|
||||
LJ::Support::fill_request_with_cat($sp, $cats);
|
||||
next unless (LJ::Support::can_read($sp, $remote));
|
||||
|
||||
my $status = "open";
|
||||
my $barbg = "green";
|
||||
if ($sp->{'timeclosed'}) {
|
||||
$status = "closed";
|
||||
$barbg = "red";
|
||||
}
|
||||
elsif ($sp->{'timelasthelp'} > $sp->{'timetouched'}+5) {
|
||||
$status = "answered<br />awaiting close";
|
||||
$barbg = "yellow";
|
||||
}
|
||||
elsif ($sp->{'timelasthelp'} && $sp->{'timetouched'} > $sp->{'timelasthelp'}+5) {
|
||||
$status = "answered<br /><b>still needs help</b>";
|
||||
$barbg = "green";
|
||||
}
|
||||
|
||||
next if $state eq "green" && $barbg ne "green";
|
||||
|
||||
# fix up the subject if needed
|
||||
eval {
|
||||
if ($sp->{'subject'} =~ /^=\?(utf-8)?/i) {
|
||||
my @subj_data;
|
||||
@subj_data = MIME::Words::decode_mimewords($sp->{'subject'});
|
||||
if (scalar(@subj_data)) {
|
||||
if (!$1) {
|
||||
$sp->{'subject'} = Unicode::MapUTF8::to_utf8({-string=>$subj_data[0][0], -charset=>$subj_data[0][1]});
|
||||
} else {
|
||||
$sp->{'subject'} = $subj_data[0][0];
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
# fix up the message if we have one
|
||||
my $temp = LJ::text_trim($sp->{message}, 0, 100); # 100 character max
|
||||
if ($temp ne $sp->{message}) {
|
||||
$sp->{message} = LJ::ehtml($temp) . " ...";
|
||||
} else {
|
||||
$sp->{message} = LJ::ehtml($sp->{message}) . " <b>¶</b>";
|
||||
}
|
||||
my $des = $abstracts ? "<br /><i>$sp->{message}</i>" : '';
|
||||
|
||||
# other content for this request
|
||||
my $summary = LJ::ehtml($sp->{'subject'});
|
||||
my $secold = time() - $sp->{'timecreate'};
|
||||
my $age = LJ::ago_text($secold);
|
||||
my $probarea = $sp->{_cat}->{'catname'};
|
||||
my $points = LJ::Support::calc_points($sp, $secold);
|
||||
|
||||
unless ($status eq "closed") {
|
||||
$status .= "<br />($points point";
|
||||
if ($points > 1) { $status .= "s"; }
|
||||
$status .= ")";
|
||||
}
|
||||
|
||||
my ($style, $js) = ("class='$barbg'", '');
|
||||
if ($can_close) {
|
||||
$js = "id='r$sp->{spid}' onclick='doClick($sp->{spid});'";
|
||||
}
|
||||
|
||||
# generate the HTML for this row
|
||||
$ret .= "<tr valign='top' $style $js>\n";
|
||||
if ($can_close) {
|
||||
$ret .= "<td>" . LJ::html_check({ name => "check_$sp->{spid}", id => "check_$sp->{spid}",
|
||||
onclick => "doClick($sp->{spid});", }) .
|
||||
"<input type='hidden' name='c$sp->{spid}' id='c$sp->{spid}' value='$barbg' /></td>\n";
|
||||
$js = "onclick='return doClick($sp->{spid});'";
|
||||
}
|
||||
$ret .= "<td><b><a href=\"$LJ::SITEROOT/support/see_request.bml?id=$sp->{'spid'}\" $js>$sp->{'spid'}</a></b></td>";
|
||||
$ret .= "<td><b>$summary</b>$des</td>\n";
|
||||
$ret .= "<td>$probarea</td>\n";
|
||||
$ret .= "<td nowrap='nowrap'><font size='-1'>$age</font></td>\n";
|
||||
$ret .= "<td nowrap='nowrap'><font size='-1'>$status</font></td>\n";
|
||||
$ret .= "</tr>";
|
||||
|
||||
}
|
||||
$ret .= "</table>\n";
|
||||
|
||||
# mass close button
|
||||
if ($can_close && $rct) {
|
||||
my $time = time();
|
||||
$ret .= LJ::html_hidden('ids', join(':', map { $_->{spid} } @support_log),
|
||||
'spcatid', $fcat->{spcatid},
|
||||
'ret', "/support/help.bml?state=$state&cat=$filtercat&time=$time");
|
||||
$ret .= "<br />";
|
||||
$ret .= LJ::html_submit('action:move', 'Move Marked Requests');
|
||||
$ret .= " to ";
|
||||
$ret .= LJ::html_select({ 'name' => 'changecat', selected => '' },
|
||||
'', '(no change)',
|
||||
map { $_->{'spcatid'}, "---> $_->{'catname'}" }
|
||||
LJ::Support::sorted_cats($cats));
|
||||
|
||||
|
||||
$ret .= "<br /><br />";
|
||||
$ret .= LJ::html_submit('action:close', 'Close Marked Requests',
|
||||
{ onclick => 'return confirm("Are you sure you want to close the marked requests?");' });
|
||||
$ret .= " (this is permanent)";
|
||||
$ret .= "</form>";
|
||||
}
|
||||
|
||||
return $ret;
|
||||
|
||||
_code?>
|
||||
|
||||
<?hr?>
|
||||
<p>Back to the <a href="<?siteroot?>/support/">support area</a>.</p>
|
||||
|
||||
<=body
|
||||
page?><?_c <LJDEP>
|
||||
link: htdocs/support/help.bml, htdocs/support/see_request.bml
|
||||
link: htdocs/support/index.bml
|
||||
form: htdocs/support/help.bml
|
||||
</LJDEP> _c?>
|
||||
107
livejournal/htdocs/support/highscores.bml
Executable file
107
livejournal/htdocs/support/highscores.bml
Executable file
@@ -0,0 +1,107 @@
|
||||
<?page
|
||||
title=>High Scores
|
||||
head=><?_code return LJ::robot_meta_tags(); _code?>
|
||||
body<=
|
||||
|
||||
The following people have helped other users in the support area:
|
||||
|
||||
<?_code
|
||||
use strict;
|
||||
use vars qw(%GET);
|
||||
|
||||
LJ::set_active_crumb('supportscores');
|
||||
|
||||
my $dbr = LJ::get_db_reader();
|
||||
|
||||
my $sth;
|
||||
my %rank;
|
||||
|
||||
$sth = $dbr->prepare("SELECT statcat, statkey, statval FROM stats ".
|
||||
"WHERE statcat IN ('supportrank', 'supportrank_prev')");
|
||||
$sth->execute;
|
||||
|
||||
while (my ($cat, $userid, $rank) = $sth->fetchrow_array) {
|
||||
if ($cat eq "supportrank") {
|
||||
$rank{$userid}->{'now'} = $rank;
|
||||
} else {
|
||||
$rank{$userid}->{'last'} = $rank;
|
||||
}
|
||||
}
|
||||
return "<blockquote>Support high score data is not available.</blockquote>"
|
||||
unless %rank;
|
||||
|
||||
$sth = $dbr->prepare("SELECT u.userid, u.user, u.name, sp.totpoints AS 'points', sp.lastupdate ".
|
||||
"FROM user u, supportpointsum sp WHERE u.userid=sp.userid");
|
||||
$sth->execute;
|
||||
my @rows;
|
||||
push @rows, $_ while $_ = $sth->fetchrow_hashref;
|
||||
if ($GET{'sort'} eq "lastupdate") {
|
||||
@rows = sort { $b->{lastupdate} <=> $a->{lastupdate} } @rows;
|
||||
} else {
|
||||
@rows = sort { $b->{points} <=> $a->{points} } @rows;
|
||||
}
|
||||
|
||||
my $page = $GET{page}+0;
|
||||
my $shown = 100 * ($page - 1) - 1;
|
||||
my $rank = 0;
|
||||
my $lastpoints = 0;
|
||||
my $buildup = 0;
|
||||
foreach (@rows[0..$shown]) {
|
||||
if ($_->{'points'} != $lastpoints) {
|
||||
$lastpoints = $_->{'points'};
|
||||
$rank += (1 + $buildup);
|
||||
$buildup = 0;
|
||||
} else {
|
||||
$buildup++;
|
||||
}
|
||||
}
|
||||
my $total = scalar(@rows);
|
||||
|
||||
my %items = BML::paging(\@rows, $GET{'page'}, 100);
|
||||
my $navbar = LJ::paging_bar($items{'page'}, $items{'pages'});
|
||||
@rows = @{$items{'items'}};
|
||||
|
||||
my $ret = $navbar;
|
||||
$ret .= "<table>";
|
||||
my $count = 0;
|
||||
foreach (@rows)
|
||||
{
|
||||
$count++;
|
||||
my $userid = $_->{'userid'};
|
||||
if ($_->{'points'} != $lastpoints) {
|
||||
$lastpoints = $_->{'points'};
|
||||
$rank += (1 + $buildup);
|
||||
$buildup = 0;
|
||||
} else {
|
||||
$buildup++;
|
||||
}
|
||||
my $change = "";
|
||||
if ($rank{$userid}->{'now'} && $rank{$userid}->{'last'}) {
|
||||
$change = $rank{$userid}->{'last'} - $rank{$userid}->{'now'}; # from 5th to 4th is 5-4 = 1 (+1 for increase)
|
||||
if ($change == 0) {
|
||||
$change = "";
|
||||
} elsif ($change > 0) {
|
||||
$change = "<font color=\"#00dd00\">(+$change)</font>";
|
||||
} else {
|
||||
$change = "<font color=\"#dd0000\">($change)</font>";
|
||||
}
|
||||
}
|
||||
my $pts = $_->{'points'};
|
||||
my $s = $pts > 1 ? "s" : "";
|
||||
|
||||
my $name = LJ::ehtml($_->{'name'});
|
||||
$ret .= "<tr><td align=\"right\">$rank.</td><td>$change</td><td><?ljuser $_->{'user'} ljuser?> - $name</td><td><b>$_->{'points'} point$s</b></td></tr>\n";
|
||||
}
|
||||
$ret .= "</table>";
|
||||
$ret .= "<p><b>$total</b> total supporting users, <b>$count</b> displayed.</p>";
|
||||
$ret .= $navbar;
|
||||
return $ret;
|
||||
|
||||
_code?>
|
||||
<?hr?>
|
||||
Back to the <A HREF="./">support area</A>.
|
||||
|
||||
<=body
|
||||
page?><?_c <LJDEP>
|
||||
link: htdocs/admin/priv/index.bml, htdocs/support/index.bml
|
||||
</LJDEP> _c?>
|
||||
117
livejournal/htdocs/support/history.bml
Executable file
117
livejournal/htdocs/support/history.bml
Executable file
@@ -0,0 +1,117 @@
|
||||
<?page
|
||||
title=>Support Request History
|
||||
body<=
|
||||
<?_code
|
||||
{
|
||||
use strict;
|
||||
use vars qw(%GET);
|
||||
|
||||
my $remote = LJ::get_remote();
|
||||
return "<?needlogin?>" unless $remote;
|
||||
|
||||
# supporthelp anywhere lets them in
|
||||
return "You are not authorized to view this page."
|
||||
unless LJ::check_priv($remote, 'supporthelp');
|
||||
|
||||
my $ret;
|
||||
if ($GET{user} || $GET{email} || $GET{userid}) {
|
||||
my $dbr = LJ::get_db_reader();
|
||||
return "Failed to get database handle."
|
||||
unless $dbr;
|
||||
|
||||
my $reqlist;
|
||||
if ($GET{user} || $GET{userid}) {
|
||||
# get requests by a user, regardless of email (only gets user requests)
|
||||
my $userid = $GET{userid} ? $GET{userid}+0 : LJ::get_userid(LJ::trim($GET{user}));
|
||||
return "Invalid user to search on." unless $userid;
|
||||
$reqlist = $dbr->selectall_arrayref('SELECT spid, subject, state, spcatid, requserid, timecreate, reqemail ' .
|
||||
'FROM support WHERE reqtype = \'user\' AND requserid = ?',
|
||||
undef, $userid);
|
||||
} elsif ($GET{email}) {
|
||||
# try by email, note that this gets requests opened by users and anonymous
|
||||
# requests, so we can view them all
|
||||
my $email = LJ::trim($GET{email});
|
||||
return "Invalid email to search on." unless $email =~ /^.+\@.+$/;
|
||||
$reqlist = $dbr->selectall_arrayref('SELECT spid, subject, state, spcatid, requserid, timecreate, reqemail ' .
|
||||
'FROM support WHERE reqemail = ?',
|
||||
undef, $email);
|
||||
}
|
||||
|
||||
if (@{$reqlist || []}) {
|
||||
# construct a list of people who have answered these requests
|
||||
my @ids;
|
||||
foreach (@$reqlist) {
|
||||
next unless $_->[2] eq 'closed';
|
||||
push @ids, $_->[0];
|
||||
}
|
||||
my $idlist = join ',', map { $_+0 } @ids;
|
||||
my $winners = $dbr->selectall_arrayref('SELECT sp.spid, u.user, sp.points FROM useridmap u, supportpoints sp ' .
|
||||
"WHERE u.userid = sp.userid AND sp.spid IN ($idlist)");
|
||||
my %points;
|
||||
$points{$_->[0]+0} = [ $_->[1], $_->[2]+0 ] foreach @{$winners || []};
|
||||
|
||||
# now construct the request blocks
|
||||
my %reqs;
|
||||
my @userids;
|
||||
foreach my $row (@$reqlist) {
|
||||
$reqs{$row->[0]} = {
|
||||
spid => $row->[0],
|
||||
winner => $points{$row->[0]}->[0],
|
||||
points => $points{$row->[0]}->[1]+0,
|
||||
subject => LJ::ehtml($row->[1]),
|
||||
state => $row->[2],
|
||||
spcatid => $row->[3],
|
||||
requserid => $row->[4],
|
||||
timecreate => LJ::mysql_time($row->[5]),
|
||||
reqemail => LJ::ehtml($row->[6]),
|
||||
};
|
||||
push @userids, $row->[4] if $row->[4];
|
||||
}
|
||||
my $us = LJ::load_userids(@userids) if @userids;
|
||||
|
||||
# get categories
|
||||
my $cats = LJ::Support::load_cats();
|
||||
|
||||
$ret .= '<table><tr><th>Summary</th><th>State</th><th>Answered By</th>' .
|
||||
'<th>Category</th><th>Opened By</th><th>Time Opened</th></tr>';
|
||||
foreach my $id (sort { $a <=> $b } keys %reqs) {
|
||||
# verify user can see this category (public_read or has supportread in it)
|
||||
next unless $cats->{$reqs{$id}->{spcatid}}{public_read} ||
|
||||
LJ::Support::can_read_cat($cats->{$reqs{$id}->{spcatid}}, $remote);
|
||||
|
||||
# print out this request row
|
||||
$ret .= '<tr>';
|
||||
$ret .= "<td><a href=\"see_request.bml?id=$reqs{$id}->{spid}\">$reqs{$id}->{subject}</a></td>\n";
|
||||
$ret .= "<td align='center'>$reqs{$id}->{state}</td>\n";
|
||||
$ret .= '<td align="center">';
|
||||
if ($reqs{$id}->{state} eq 'closed' && $reqs{$id}->{winner}) {
|
||||
$ret .= LJ::ljuser($reqs{$id}->{winner}) . " ($reqs{$id}->{points})";
|
||||
} else {
|
||||
$ret .= '-';
|
||||
}
|
||||
$ret .= "</td>\n";
|
||||
$ret .= "<td align='center'>$cats->{$reqs{$id}->{spcatid}}{catname}</td>\n<td align='center'>";
|
||||
$ret .= $reqs{$id}->{requserid} ? LJ::ljuser($us->{$reqs{$id}->{requserid}}) : $reqs{$id}->{reqemail};
|
||||
$ret .= "</td>\n<td align='center'>$reqs{$id}->{timecreate}</td>\n";
|
||||
$ret .= '</tr>';
|
||||
}
|
||||
$ret .= '</table><br /><br />';
|
||||
} else {
|
||||
$ret .= "No results found for the search terms you entered.<br /><br />";
|
||||
}
|
||||
}
|
||||
|
||||
$ret .= "<table><tr><th colspan='2'>Search for Requests</th></tr>";
|
||||
$ret .= "<form method='get' action='history.bml'>";
|
||||
$ret .= "<tr><td>By Email:</td><td><input type='text' name='email'></td></tr>";
|
||||
$ret .= "<tr><td>By Username:</td><td><input type='text' name='user'></td></tr>";
|
||||
$ret .= "<tr><td>By Userid:</td><td><input type='text' name='userid'></td></tr>";
|
||||
$ret .= "<tr><td colspan='2'><input type='submit' value='Perform Search'></td></tr>";
|
||||
$ret .= "<tr><td colspan='2'>Please fill out only one of the search fields.</td></tr>";
|
||||
$ret .= "</form></table>";
|
||||
return $ret;
|
||||
|
||||
}
|
||||
_code?>
|
||||
<=body
|
||||
page?>
|
||||
57
livejournal/htdocs/support/index.bml
Executable file
57
livejournal/htdocs/support/index.bml
Executable file
@@ -0,0 +1,57 @@
|
||||
<?page
|
||||
title=>LiveJournal Support
|
||||
body<=
|
||||
<?_code
|
||||
LJ::set_active_crumb('support');
|
||||
_code?>
|
||||
<?h1 Welcome! h1?>
|
||||
<?p
|
||||
Welcome to the LiveJournal community support center. Listed below are
|
||||
some of the most frequent questions people ask. If you don't find
|
||||
what you're looking for, you can submit a support request below.
|
||||
p?>
|
||||
|
||||
<?_include
|
||||
bml=>1
|
||||
code=>0
|
||||
file=>support-currentproblems
|
||||
_include?>
|
||||
|
||||
<?_include
|
||||
bml=>0
|
||||
code=>0
|
||||
file=>support-links
|
||||
_include?>
|
||||
|
||||
<?h1 Support Areas h1?>
|
||||
<?p
|
||||
Here are the three major things you can do here in the support area.
|
||||
p?>
|
||||
|
||||
<ul>
|
||||
<li><font size='+1'><b><a href="faq.bml">Read the Frequently Asked Questions</a></b></font><br />
|
||||
Try and solve the problem first by yourself before asking other people. You'll probably get the answer faster, too!</li>
|
||||
|
||||
<li style='margin-top: 1em'><font size='+1'><b><a href="submit.bml">Ask a question</a></b></font><br />
|
||||
Is your question not in the FAQ? Click "Ask a question" and you can submit a new support request and somebody in the LiveJournal community will read it and get back to you with an answer. If they don't help you, your support request stays open until somebody does help and you confirm that your problem is solved.</li>
|
||||
|
||||
<li style='margin-top: 1em'><font size='+1'><b><a href="help.bml">Help somebody out</a></b></font><br />
|
||||
Got some extra time on your hands? Help out a LiveJournal user that has an open support request. Users that help other users out will get "support points" that will show up on your userinfo page. There are multiple reasons for helping other users out:
|
||||
|
||||
<ul style='margin-top: 0.8em'>
|
||||
<li>Just to be nice</li>
|
||||
<li>To get points just for fun and competition</li>
|
||||
</ul>
|
||||
<p>If you're curious, check out the list of <A HREF="highscores.bml">high scores</A>, showing who helps the most.</p>
|
||||
<p>If you want to be notified when new support requests come in, <a href="changenotify.bml">set your notification settings</a>.</p>
|
||||
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
<=body
|
||||
page?><?_c <LJDEP>
|
||||
link: htdocs/support/faq.bml, htdocs/support/submit.bml, htdocs/support/help.bml
|
||||
link: htdocs/support/highscores.bml, htdocs/support/changenotify.bml
|
||||
</LJDEP> _c?>
|
||||
60
livejournal/htdocs/support/see_overrides.bml
Executable file
60
livejournal/htdocs/support/see_overrides.bml
Executable file
@@ -0,0 +1,60 @@
|
||||
<?page
|
||||
title=><?_ml .title _ml?>
|
||||
body<=
|
||||
<?_code
|
||||
{
|
||||
use strict;
|
||||
use vars qw(%GET);
|
||||
|
||||
LJ::set_active_crumb('seeoverrides');
|
||||
|
||||
my $remote = LJ::get_remote();
|
||||
return LJ::bad_input($ML{'error.noremote'})
|
||||
unless $remote;
|
||||
|
||||
my $user = LJ::canonical_username($GET{'user'} || $remote->{'user'});
|
||||
return LJ::bad_input(BML::ml("error.malformeduser"))
|
||||
unless $user;
|
||||
|
||||
# check for privs
|
||||
unless ($remote->{'user'} eq $user ||
|
||||
LJ::check_priv($remote, "supportviewscreened") ||
|
||||
LJ::check_priv($remote, "supporthelp")) {
|
||||
|
||||
return LJ::bad_input(BML::ml(".error.noprivs"));
|
||||
}
|
||||
|
||||
# remote is authenticated, now load $u
|
||||
my $u = $remote->{'user'} eq $user ? $remote : LJ::load_user($user);
|
||||
return LJ::bad_input($ML{'error.username_notfound'})
|
||||
unless $u;
|
||||
|
||||
# see if they're using s2
|
||||
LJ::load_user_props($u, "stylesys");
|
||||
return LJ::bad_input(BML::ml(".error.nos1", { 'user' => $user }))
|
||||
if $u->{'stylesys'} == 2;
|
||||
|
||||
### no errors
|
||||
|
||||
# no overrides?
|
||||
return "<?p " . BML::ml(".nooverrides", {'user' => $user}) . " p?>"
|
||||
unless $u->{'useoverrides'} eq "Y";
|
||||
|
||||
# first, load the overrides if they use 'em:
|
||||
my $overrides = LJ::S1::get_overrides($u);
|
||||
LJ::text_out(\$overrides);
|
||||
|
||||
# textarea
|
||||
my $ret;
|
||||
$ret .= "<?h1 " . BML::ml(".header", {'user' => $user}) . " h1?>";
|
||||
$ret .= "<br /><form action='#'>";
|
||||
$ret .= LJ::html_textarea({ 'name' => 'overrides', 'style' => 'width: 100%',
|
||||
'cols' => '60', 'rows' => '16', 'wrap' => 'off',
|
||||
'value' => $overrides });
|
||||
$ret .= "</form>";
|
||||
|
||||
return $ret;
|
||||
}
|
||||
_code?>
|
||||
<=body
|
||||
page?>
|
||||
720
livejournal/htdocs/support/see_request.bml
Executable file
720
livejournal/htdocs/support/see_request.bml
Executable file
@@ -0,0 +1,720 @@
|
||||
<?page
|
||||
title=>Request #<?_code return ($FORM{'id'}+0); _code?>
|
||||
head<=
|
||||
<?_code return LJ::robot_meta_tags(); _code?>
|
||||
<script language="JavaScript"><!--
|
||||
function check_replytype (e) {
|
||||
if (! e) var e = window.event;
|
||||
if (! document.getElementById) return false;
|
||||
|
||||
f = document.supportForm;
|
||||
if (! f) return false;
|
||||
|
||||
var replytype = f.replytype;
|
||||
if (! replytype) return false;
|
||||
|
||||
var bounce_email = document.getElementById('bounce_email');
|
||||
if (! bounce_email) return false;
|
||||
|
||||
if (replytype.value == 'bounce')
|
||||
bounce_email.style.display = 'inline';
|
||||
else
|
||||
bounce_email.style.display = 'none';
|
||||
|
||||
if (e) {
|
||||
e.cancelBubble = true;
|
||||
if (e.stopPropagation) e.stopPropagation();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function updateFaqLink () {
|
||||
if (! document.getElementById) return false;
|
||||
|
||||
f = document.supportForm;
|
||||
if (! f) return false;
|
||||
|
||||
var faqDropdown = f.faqid;
|
||||
if (! faqDropdown) return false;
|
||||
|
||||
var faqUrl = document.getElementById('faqlink');
|
||||
if (! faqUrl) return false;
|
||||
|
||||
if (faqDropdown.value == 0)
|
||||
faqUrl.style.display = 'none';
|
||||
else
|
||||
{
|
||||
faqUrl.style.display = 'inline';
|
||||
faqUrl.href = 'faqbrowse.bml?faqid=' + faqDropdown.value;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
// -->
|
||||
</script>
|
||||
<=head
|
||||
bodyopts=>onLoad="check_replytype();updateFaqLink();"
|
||||
body<=
|
||||
|
||||
<?_code
|
||||
{
|
||||
use strict;
|
||||
use vars qw(%FORM);
|
||||
|
||||
LJ::set_dynamic_crumb('Request #' . ($FORM{'id'}+0), 'supporthelp');
|
||||
|
||||
my $spid = $FORM{'id'}+0;
|
||||
my $sp = LJ::Support::load_request($spid);
|
||||
my $props = LJ::Support::load_props($spid);
|
||||
my $cats = LJ::Support::load_cats();
|
||||
my $remote = LJ::get_remote();
|
||||
LJ::Support::init_remote($remote);
|
||||
|
||||
if ($FORM{'find'}) {
|
||||
my $find = $FORM{'find'};
|
||||
my $op = '<';
|
||||
my $sort = 'DESC';
|
||||
if ($find eq 'next' || $find eq 'cnext' || $find eq 'first') {
|
||||
$op = '>';
|
||||
$sort = 'ASC';
|
||||
}
|
||||
my $spcatand = '';
|
||||
if ($sp && ($find eq 'cnext' || $find eq 'cprev')) {
|
||||
my $spcatid = $sp->{_cat}->{'spcatid'} + 0;
|
||||
$spcatand = "AND spcatid=$spcatid";
|
||||
} else {
|
||||
my @filter_cats = LJ::Support::filter_cats($remote, $cats);
|
||||
return "<?h1 Error h1?><?p You do not appear to have permission to read any support categories. p?>"
|
||||
unless @filter_cats;
|
||||
my $cats_in = join(",", map { $_->{'spcatid'} } @filter_cats);
|
||||
$spcatand = "AND spcatid IN ($cats_in)";
|
||||
}
|
||||
my $clause = "";
|
||||
$clause = "AND spid$op$spid" unless ($find eq 'first' || $find eq 'last');
|
||||
my $dbr = LJ::get_db_reader();
|
||||
my ($foundspid) = $dbr->selectrow_array("SELECT spid FROM support WHERE state='open' $spcatand $clause ".
|
||||
"ORDER BY spid $sort LIMIT 1");
|
||||
if ($foundspid) {
|
||||
return BML::redirect("see_request.bml?id=$foundspid");
|
||||
} else {
|
||||
my $goback = "<?p Go back to <a href='see_request.bml?id=$spid'>Request #$spid</a> p?>" if $sp;
|
||||
my $what = $find eq 'next' || $find eq 'cnext' ? 'next' : 'previous';
|
||||
my $cat = "in the same category" if $find eq 'cnext' || $find eq 'cprev';
|
||||
return "<?h1 Error h1?><?p No $what open request $cat found. p?>$goback";
|
||||
}
|
||||
}
|
||||
|
||||
unless ($sp) { return "<?h1 Error h1?><?p Unknown support number. p?>"; }
|
||||
my $sth;
|
||||
my $auth = $FORM{'auth'};
|
||||
|
||||
my $email = $sp->{'reqemail'};
|
||||
|
||||
my $u = {};
|
||||
my $clusterdown = 0;
|
||||
if ($sp->{'reqtype'} eq "user") {
|
||||
$u = LJ::load_userid($sp->{'requserid'});
|
||||
|
||||
# now do a check for a down cluster?
|
||||
my $dbr = LJ::get_cluster_reader($u);
|
||||
$clusterdown = 1 unless $dbr;
|
||||
|
||||
$email = $u->{'email'};
|
||||
LJ::load_user_props($u, "s1_lastn_style", "s1_calendar_style", "s1_day_style",
|
||||
"s1_friends_style", "stylesys", "s2_style", )
|
||||
unless $clusterdown;
|
||||
}
|
||||
|
||||
my $winner; # who closed it?
|
||||
if ($sp->{'state'} eq "closed") {
|
||||
my $dbr = LJ::get_db_reader();
|
||||
$sth = $dbr->prepare("SELECT u.user, sp.points FROM useridmap u, supportpoints sp ".
|
||||
"WHERE u.userid=sp.userid AND sp.spid=?");
|
||||
$sth->execute($spid);
|
||||
$winner = $sth->fetchrow_hashref;
|
||||
}
|
||||
|
||||
# load category this request is in
|
||||
my $problemarea = $sp->{_cat}->{'catname'};
|
||||
my $catkey = $sp->{_cat}->{'catkey'};
|
||||
|
||||
unless (LJ::Support::can_read($sp, $remote, $auth)) {
|
||||
return "<?h1 Error h1?><?p You don't have the necessary privilege to view this request. p?>";
|
||||
}
|
||||
|
||||
# helper variables for commonly called methods
|
||||
my $owner_mode = LJ::Support::can_close($sp, $remote, $auth) ? 1 : 0;
|
||||
my $helper_mode = LJ::Support::can_help($sp, $remote) ? 1 : 0;
|
||||
my $is_poster = LJ::Support::is_poster($sp, $remote, $auth) ? 1 : 0;
|
||||
|
||||
# fix up the subject if needed
|
||||
eval {
|
||||
if ($sp->{'subject'} =~ /^=\?(utf-8)?/i) {
|
||||
my @subj_data;
|
||||
@subj_data = MIME::Words::decode_mimewords($sp->{'subject'});
|
||||
if (scalar(@subj_data)) {
|
||||
if (!$1) {
|
||||
$sp->{'subject'} = Unicode::MapUTF8::to_utf8({-string=>$subj_data[0][0], -charset=>$subj_data[0][1]});
|
||||
} else {
|
||||
$sp->{'subject'} = $subj_data[0][0];
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
### request info table
|
||||
|
||||
my $ret = "";
|
||||
$ret .= "<table>\n";
|
||||
$ret .= "<tr><td valign='bottom' align='right'><b>From:</b></td><td>";
|
||||
if ($u->{'defaultpicid'} && $u->{'statusvis'} ne 'S') {
|
||||
my %pic;
|
||||
my $picid = $u->{'defaultpicid'};
|
||||
LJ::load_userpics(\%pic, [ $u, $picid ]);
|
||||
$ret .= "<a href='$LJ::SITEROOT/allpics.bml?user=$u->{'user'}'>";
|
||||
$ret .= "<img align='baseline' src='$LJ::USERPIC_ROOT/$picid/$u->{'userid'}' width='$pic{$picid}->{'width'}' ".
|
||||
"height='$pic{$picid}->{'height'}' align='absmiddle' hspace='3' border='0' alt='$u->{'user'}' />";
|
||||
$ret .= "</a>";
|
||||
}
|
||||
|
||||
# show requester name + email
|
||||
{
|
||||
my $visemail = $email;
|
||||
if ($sp->{_cat}->{'public_read'}) {
|
||||
$visemail =~ s/^.+\@/********\@/;
|
||||
}
|
||||
my $ename = $sp->{'reqtype'} eq 'user' ? LJ::ljuser($u) : LJ::ehtml($sp->{reqname});
|
||||
|
||||
# we show links to the history page if the user is a helper in this category or if it's a
|
||||
# private category and the person has supporthelp somewhere (which is the general rule of
|
||||
# thumb to use the history viewer)
|
||||
my $show_history = !$sp->{_cat}->{public_read} && LJ::check_priv($remote, 'supporthelp');
|
||||
if ($helper_mode || $show_history) {
|
||||
$ret .= $sp->{reqtype} eq 'user' ?
|
||||
"$ename <a href=\"history.bml?user=$u->{user}\">$u->{name}</a>" :
|
||||
"$ename";
|
||||
$ret .= $owner_mode || $show_history ?
|
||||
" (<a href=\"history.bml?email=" . LJ::eurl($email) . "\">$visemail</a>)" :
|
||||
" ($visemail)";
|
||||
} else {
|
||||
# default view
|
||||
$ret .= "$ename ($visemail)";
|
||||
}
|
||||
}
|
||||
$ret .= "</td></tr>\n";
|
||||
|
||||
# uniq
|
||||
if (LJ::check_priv($remote, 'sysban', 'uniq') || LJ::check_priv($remote, 'sysban', '*')) {
|
||||
my $uniq = $props->{'uniq'} || "<i>none</i>";
|
||||
$ret .= "<tr><td valign='bottom' align='right'><b>Uniq:</b></td><td>$uniq</td></tr>\n";
|
||||
}
|
||||
|
||||
# account type
|
||||
$ret .= "<tr><td align='right' valign='top'><b><a href='$LJ::SITEROOT/support/faqbrowse.bml?faqid=38'><span style='white-space: nowrap'>Account type</span></a>:</b></td><td>";
|
||||
$ret .= LJ::name_caps($u->{'caps'}) || "<i>Unknown</i>";
|
||||
$ret .= "</td></tr>\n";
|
||||
|
||||
$ret .= "<tr valign='top'><td align='right'><b>$LJ::SITENAMESHORT:</b></td><td>";
|
||||
if ($clusterdown) {
|
||||
$ret .= "<span style='color: red; font-weight: bold;'>" .
|
||||
"(unable to connect to cluster, some data temporarily unavailable)</span><br />";
|
||||
}
|
||||
|
||||
# check isu because requests don't always come from users and sometimes we
|
||||
# fake the user hash
|
||||
if (LJ::isu($u) && $u->readonly) {
|
||||
$ret .= "<span style='color: red; font-weight: bold;'>" .
|
||||
"(this user is currently in read-only mode)</span><br />";
|
||||
}
|
||||
|
||||
|
||||
if ($u->{'userid'}) {
|
||||
$ret .= "username: <?ljuserf $u->{'user'} ljuserf?>";
|
||||
$ret .= "<br />style: ";
|
||||
if ($u->{'stylesys'} == 2) {
|
||||
$ret .= "(S2) ";
|
||||
if ($u->{'s2_style'}) {
|
||||
my $s2style = LJ::S2::load_style($u->{'s2_style'});
|
||||
my $pub = LJ::S2::get_public_layers(); # cached
|
||||
foreach my $lay (sort { $a cmp $b } keys %{$s2style->{'layer'}}) {
|
||||
my $lid = $s2style->{'layer'}->{$lay};
|
||||
$ret .= "$lay: <a href='$LJ::SITEROOT/customize/advanced/layerbrowse.bml?id=$lid'>";
|
||||
$ret .= (defined $pub->{$lid} ? 'public' : 'user') . "</a>, ";
|
||||
}
|
||||
} else {
|
||||
$ret .= "none";
|
||||
}
|
||||
} else {
|
||||
$ret .= "(S1) ";
|
||||
foreach my $view (@LJ::views) {
|
||||
my $styid = $u->{"s1_${view}_style"};
|
||||
my $viewuri = $view eq "lastn" ? "/users/$u->{'user'}/" : "/users/$u->{'user'}/$view";
|
||||
if ($view eq "day") {
|
||||
my (undef,undef,undef,$dday,$dmon,$dyear) = localtime(time); $dyear+=1900; $dmon++;
|
||||
$dmon = $dmon <= 9 ? "0$dmon" : $dmon; $dday = $dday <= 9 ? "0$dday" : $dday;
|
||||
$viewuri = "/users/$u->{'user'}/$dyear/$dmon/$dday/";
|
||||
}
|
||||
$ret .= "<a href='$viewuri'>$view</a>: <a href='$LJ::SITEROOT/styles/browse/styleinfo.bml?styleid=$styid'>$styid</a> ";
|
||||
}
|
||||
if ($u->{'useoverrides'} eq 'Y') {
|
||||
$ret .= "<br />overrides: <a href='see_overrides.bml?user=$u->{'user'}'>view</a> ";
|
||||
}
|
||||
}
|
||||
|
||||
# if the user has siteadmin:users or siteadmin:* show them link to resend validation email?
|
||||
my $extraval = sub {
|
||||
return '' unless LJ::check_priv($remote, 'siteadmin', 'users') ||
|
||||
LJ::check_priv($remote, 'siteadmin', '*');
|
||||
return " (<a href='$LJ::SITEROOT/register.bml?foruser=$u->{user}'>resend validation email</a>)";
|
||||
};
|
||||
|
||||
$ret .= "<br />email validated? ";
|
||||
if ($u->{'status'} eq "A") { $ret .= "<b>yes</b>"; }
|
||||
if ($u->{'status'} eq "N") { $ret .= "<b>no</b>" . $extraval->(); }
|
||||
if ($u->{'status'} eq "T") { $ret .= "<b>transitioning</b> (used to be validated, but changed email addresses and hasn't reconfirmed)" . $extraval->(); }
|
||||
if ($u->{clusterid}) { $ret .= "<br />cluster: " . LJ::get_cluster_description($u->{clusterid}, 1); }
|
||||
$ret .= "<br />data version: <b>$u->{dversion}</b>";
|
||||
$ret .= "<br />underage? ";
|
||||
if ($clusterdown) {
|
||||
$ret .= "<strong>cluster unavailable</strong>";
|
||||
} else {
|
||||
if ($u->underage) {
|
||||
$ret .= "<strong>yes because of ";
|
||||
$ret .= "birthday" if $u->underage_status eq 'Y';
|
||||
$ret .= "unique cookie" if $u->underage_status eq 'O';
|
||||
$ret .= "manual set" if $u->underage_status eq 'M';
|
||||
$ret .= "</strong>";
|
||||
} else {
|
||||
$ret .= "<strong>no";
|
||||
if ($u->underage_status) {
|
||||
$ret .= "; was by ";
|
||||
$ret .= "birthday" if $u->underage_status eq 'Y';
|
||||
$ret .= "unique cookie" if $u->underage_status eq 'O';
|
||||
$ret .= "manual set" if $u->underage_status eq 'M';
|
||||
}
|
||||
$ret .= "</strong>";
|
||||
}
|
||||
}
|
||||
|
||||
if (LJ::check_priv($remote, 'historyview')) {
|
||||
$ret .= "<br />view: ";
|
||||
$ret .= "<a href='$LJ::SITEROOT/admin/statushistory.bml?user=$u->{user}'>statushistory</a>";
|
||||
}
|
||||
} else {
|
||||
$ret .= "<i>not a user</i>";
|
||||
}
|
||||
$ret .= "</td></tr>\n";
|
||||
$ret .= "<tr><td align='right' nowrap='nowrap'><b>Support category:</b></td><td>";
|
||||
if (LJ::Support::can_read_cat($sp->{_cat}, $remote)) {
|
||||
$ret .= "<a href='$LJ::SITEROOT/support/help.bml?cat=$sp->{_cat}->{'catkey'}'>$problemarea</a>";
|
||||
$ret .= " [<a href='$LJ::SITEROOT/support/see_request.bml?id=$sp->{'spid'}&find=cprev'>previous</a>|";
|
||||
$ret .= "<a href='$LJ::SITEROOT/support/see_request.bml?id=$sp->{'spid'}&find=cnext'>next</a>]";
|
||||
} else {
|
||||
$ret .= $problemarea;
|
||||
}
|
||||
$ret .= "</td></tr>\n";
|
||||
|
||||
my $timecreate = LJ::time_to_http($sp->{'timecreate'});
|
||||
my $age = LJ::ago_text(time() - $sp->{'timecreate'});
|
||||
$ret .= "<tr><td align='right'><b>Time posted:</b></td><td>$timecreate ($age)</td></tr>\n";
|
||||
my $state = $sp->{'state'};
|
||||
if ($state eq "open") {
|
||||
# check if it's still open or needing help or what
|
||||
if ($sp->{'timelasthelp'} > ($sp->{'timetouched'}+5)) {
|
||||
# open, answered
|
||||
$state = "<b><span style='color: #ff0000;'>answered</span></b> (awaiting close)";
|
||||
} elsif ($sp->{'timelasthelp'} && $sp->{'timetouched'} > $sp->{'timelasthelp'}+5) {
|
||||
# open, still needs help
|
||||
$state = "<b><span style='color: #ff0000;'>answered</span></b> (<b>still needs help</b>)";
|
||||
} else {
|
||||
# default
|
||||
$state = "<b><span style='color: #ff0000;'>open</span></b>";
|
||||
}
|
||||
}
|
||||
if ($state eq "closed" && $winner && LJ::Support::can_see_helper($sp, $remote)) {
|
||||
my $s = $winner->{'points'} > 1 ? "s" : "";
|
||||
my $wuser = $winner->{'user'};
|
||||
$state .= " (<b>$winner->{'points'}</b> point$s to ";
|
||||
$state .= LJ::ljuser($wuser, { 'full' => 1 }) . ")";
|
||||
}
|
||||
$ret .= "<tr><td align='right'><b>Status:</b></td><td>$state";
|
||||
if ($owner_mode) {
|
||||
$ret .= $sp->{'state'} eq "open" ? ", <a href='act.bml?close;$sp->{'spid'};$sp->{'authcode'}'><b>close without credit</b></a>" : "";
|
||||
if ($sp->{state} eq 'closed') {
|
||||
my $permastatus = LJ::Support::is_locked($sp);
|
||||
$ret .= $sp->{'state'} eq "closed" && !$permastatus ?
|
||||
", <a href='act.bml?touch;$sp->{'spid'};$sp->{'authcode'}'><b>reopen this request</b></a>" : "";
|
||||
if (LJ::Support::can_lock($sp, $remote)) {
|
||||
$ret .= $permastatus ?
|
||||
", <a href='act.bml?unlock;$sp->{spid};$sp->{authcode}'><b>unlock request</b></a>" :
|
||||
", <a href='act.bml?lock;$sp->{spid};$sp->{authcode}'><b>lock request</b></a>";
|
||||
}
|
||||
}
|
||||
}
|
||||
$ret .= "</td></tr>\n";
|
||||
$ret .= "<tr><td align='right'><b>Summary:</b></td><td><span style='font-size: 1.1em'><b>" . LJ::ehtml($sp->{'subject'}) . "</b></span></td></tr>\n";
|
||||
$ret .= "</table>\n";
|
||||
|
||||
### end request info table
|
||||
|
||||
LJ::run_hooks("support_see_request_html", {
|
||||
'u' => $u,
|
||||
'email' => $email,
|
||||
'sp' => $sp,
|
||||
'retref' => \$ret,
|
||||
'remote' => $remote,
|
||||
});
|
||||
|
||||
# put in a "this is private!" box if this is a private request and the user viewing
|
||||
# this page is the person who opened the request
|
||||
if (!$sp->{_cat}->{public_read} && $is_poster) {
|
||||
$ret .= "<div style='margin-top: 15px; margin-bottom: 15px; padding: 5px; " .
|
||||
"text-align: center; background-color: #ffff00; border: solid 2px red;'>" .
|
||||
"<b>This is a private request.</b> It is not publicly visible.</div>";
|
||||
}
|
||||
|
||||
my %userpics; # id -> {..}
|
||||
|
||||
my @screened;
|
||||
|
||||
### reply loop
|
||||
my $dbr = LJ::get_db_reader();
|
||||
$sth = $dbr->prepare("SELECT splid, timelogged, UNIX_TIMESTAMP()-timelogged AS 'age', type, faqid, userid, message " .
|
||||
"FROM supportlog WHERE spid=? ORDER BY timelogged");
|
||||
$sth->execute($spid);
|
||||
while (my $le = $sth->fetchrow_hashref)
|
||||
{
|
||||
next if ($le->{'type'} eq "internal" && ! (LJ::Support::can_read_internal($sp, $remote) ||
|
||||
($remote && $remote->{'userid'} == $le->{'userid'} )));
|
||||
next if ($le->{'type'} eq "screened" && ! (LJ::Support::can_read_screened($sp, $remote) ||
|
||||
($remote && $remote->{'userid'} == $le->{'userid'} )));
|
||||
|
||||
if ($le->{'type'} eq "screened") {
|
||||
push @screened, $le;
|
||||
}
|
||||
|
||||
my $message = $le->{'message'};
|
||||
my %url;
|
||||
my $urlN = 0;
|
||||
|
||||
$message = LJ::ehtml($message);
|
||||
$message =~ s/^\s+//;
|
||||
$message =~ s/\s+$//;
|
||||
$message =~ s/\n( +)/"\n" . " "x length($1)/eg;
|
||||
$message =~ s/\n/<br \/>\n/g;
|
||||
$message = LJ::auto_linkify($message);
|
||||
|
||||
# special case: original request
|
||||
if ($le->{'type'} eq "req") {
|
||||
# insert support diagnostics from props
|
||||
$message .= "<?hr?><strong>Diagnostics:</strong> $props->{useragent}" if $props->{useragent};
|
||||
|
||||
$ret .= "<div style='margin-top: 15px;'>\n";
|
||||
$ret .= "<b>Original Request:</b><br />\n";
|
||||
$ret .= "<div style='border: 3px solid #000000; margin-left: auto; margin-right: auto; padding: 3px;'>\n$message\n</div></div>";
|
||||
next;
|
||||
}
|
||||
|
||||
# reply header
|
||||
my $header = "";
|
||||
if ($le->{'userid'} && LJ::Support::can_see_helper($sp, $remote)) {
|
||||
my $up = LJ::load_userid($le->{'userid'});
|
||||
my $picid = $up->{'defaultpicid'};
|
||||
$userpics{$picid} or LJ::load_userpics(\%userpics, [[ $up, $picid ]]);
|
||||
$header = "<table style='margin-top: 15px;'><tr valign='bottom'>";
|
||||
if ($picid && $up->{'statusvis'} ne 'S') {
|
||||
$header .= "<td><img src='$LJ::USERPIC_ROOT/$picid/$up->{'userid'}' width='$userpics{$picid}->{'width'}' height='$userpics{$picid}->{'height'}' hspace='3' alt='$up->{'user'}'/></td>";
|
||||
}
|
||||
$header .= "<td>" . LJ::ljuser($up->{'user'}, { 'full' => 1 });
|
||||
if ($up->{'statusvis'} ne 'S') {
|
||||
$header .= " - " . LJ::ehtml($up->{'name'});
|
||||
}
|
||||
$header .= "</td></tr></table>\n"
|
||||
}
|
||||
|
||||
my $what = "Answer";
|
||||
if ($le->{'type'} eq "internal") { $what = "Internal Comment"; }
|
||||
elsif ($le->{'type'} eq "comment") { $what = "Comment"; }
|
||||
elsif ($le->{'type'} eq "screened") { $what = "Screened Response"; }
|
||||
|
||||
$header .= "<span style='font-size: 0.9em;'><b>$what</b> (\#$le->{'splid'})</span><br />";
|
||||
my $timehelped = LJ::time_to_http($le->{'timelogged'});
|
||||
my $age = LJ::ago_text($le->{'age'});
|
||||
$header .= "<b>Posted:</b> $timehelped ($age)";
|
||||
if ($owner_mode && $sp->{'state'} eq "open" && $le->{'type'} eq "answer") {
|
||||
$header .= ", <a href='act.bml?close;$sp->{'spid'};$sp->{'authcode'};$le->{'splid'}'><b>credit fix here</b></a>";
|
||||
}
|
||||
|
||||
my $bordercolor = "#000000";
|
||||
if ($le->{'type'} eq "internal") { $bordercolor = "#ff0000"; }
|
||||
if ($le->{'type'} eq "answer") { $bordercolor = "#00c000"; }
|
||||
if ($le->{'type'} eq "screened") { $bordercolor = "#afaf00"; }
|
||||
|
||||
# reply
|
||||
$ret .= "$header<br />\n";
|
||||
$ret .= "<table align='center' style='margin-top: 5px; border: 3px solid $bordercolor;' cellpadding='3' width='100%'>\n";
|
||||
$ret .= "<tr><td align='center'>\n";
|
||||
if ($le->{'faqid'}) {
|
||||
# faq question
|
||||
my $dbr = LJ::get_db_reader();
|
||||
my $sth = $dbr->prepare("SELECT question FROM faq WHERE faqid=?");
|
||||
$sth->execute($le->{'faqid'});
|
||||
my $faqname = $sth->fetchrow_array;
|
||||
$ret .= "<div style='display: table; padding: 3px; background: <?emcolor?>; border: 1px solid #000000; margin-left: auto; margin-right: auto;'>\n";
|
||||
# whitespace between these two DIVs is necessary for proper
|
||||
# rendering in IE 5 for Mac OS < X
|
||||
$ret .= "<div style='text-align:center;'>";
|
||||
$ret .= "<b>FAQ Reference:</b><br /><a href='faqbrowse.bml?faqid=$le->{'faqid'}'>$faqname</a></div></div>\n";
|
||||
}
|
||||
$ret .= "<p align='left' style='margin-top: 0px; margin-bottom: 0px;'>$message</p>\n";
|
||||
$ret .= "</td></tr></table>\n";
|
||||
}
|
||||
### end reply loop
|
||||
|
||||
# return if support item is closed
|
||||
if ($sp->{'state'} eq "closed") {
|
||||
return $ret;
|
||||
}
|
||||
|
||||
# underage users can't interact with this
|
||||
return $ret if $remote && $remote->underage;
|
||||
|
||||
$ret .= "<p style='margin-bottom: 0px;'><b>Post a comment or solution:</b></p>\n";
|
||||
|
||||
unless ($remote || $is_poster) {
|
||||
$ret .= "You must <a href='$LJ::SITEROOT/login.bml?ret=1'>login</a> to help people out.\n";
|
||||
return $ret;
|
||||
}
|
||||
|
||||
unless (LJ::Support::can_append($sp, $remote, $auth))
|
||||
{
|
||||
$ret .= "Sorry, you do not have access to answer people's support requests in this category.\n";
|
||||
return $ret;
|
||||
}
|
||||
|
||||
my @ans_type = LJ::Support::get_answer_types($sp, $remote, $auth);
|
||||
my %ans_type = @ans_type;
|
||||
|
||||
if ($ans_type{'answer'} || $ans_type{'screened'})
|
||||
{
|
||||
$ret .= "<?standout <b>Important Notes:</b>";
|
||||
$ret .= "<ul>";
|
||||
$ret .= "<li>Before answering somebody's question, read the <b><a href='$LJ::SITEROOT/doc/guide/support.bml'>support guide</a></b>.</li>";
|
||||
$ret .= "<li>Do <b>NOT</b> answer people if you're not sure of your answer. Don't answer if your solution is just a guess. Only answer if you really know what you're talking about ... guessing only makes other people in the support area think you might be right and spread the misinformation further, until it's accepted as truth.</li>";
|
||||
if ($LJ::LJDOTCOM) {
|
||||
$ret .= "<li>Never recommend asking someone else, or somewhere else. That qualifies as not knowing the answer. If a support request is open for a day or two, one of the support leaders will find out the answer and reply, and likely post about it in <?ljuser lj_support ljuser?> so all the support people will know the answer in the future.</li>";
|
||||
}
|
||||
$ret .= "</ul>Thanks! standout?>\n";
|
||||
}
|
||||
|
||||
# append_request form
|
||||
|
||||
$ret .= "<br /><form method='post' action='append_request.bml' name='supportForm'>\n";
|
||||
|
||||
# hidden values
|
||||
$ret .= LJ::html_hidden('spid', $spid, 'auth', $auth) . "\n";
|
||||
|
||||
# form
|
||||
$ret .= "<table border='0'>\n";
|
||||
$ret .= "<tr valign='middle'><td align='right'>From:</td><td>";
|
||||
if ($remote && $remote->{'userid'}) {
|
||||
$ret .= "<?ljuser $remote->{'user'} ljuser?>";
|
||||
} else {
|
||||
$ret .= "(not logged in)";
|
||||
}
|
||||
$ret .= "</td></tr>\n";
|
||||
|
||||
if ($ans_type{'answer'} || $ans_type{'screened'})
|
||||
{
|
||||
my $dbr = LJ::get_db_reader();
|
||||
# FAQ reference
|
||||
$ret .= "<tr valign='middle'><td align='right'>Reference <a href='faq.bml'>FAQ</a>:</td><td colspan='2'>\n";
|
||||
|
||||
my %faqcat;
|
||||
my %faqq;
|
||||
$sth = $dbr->prepare("SELECT faqcat, faqcatname, catorder FROM faqcat WHERE faqcat<>'int-abuse'");
|
||||
$sth->execute;
|
||||
while ($_ = $sth->fetchrow_hashref) {
|
||||
$faqcat{$_->{'faqcat'}} = $_;
|
||||
}
|
||||
|
||||
$sth = $dbr->prepare("SELECT faqid, question, sortorder, faqcat, lastmodtime FROM faq WHERE faqcat<>'int-abuse'");
|
||||
$sth->execute;
|
||||
while ($_ = $sth->fetchrow_hashref) {
|
||||
$faqq{$_->{'faqid'}} = $_;
|
||||
}
|
||||
|
||||
my @faqlist = ('0', "(don't reference FAQ)");
|
||||
foreach my $faqcat (sort { $faqcat{$a}->{'catorder'} <=> $faqcat{$b}->{'catorder'} } keys %faqcat)
|
||||
{
|
||||
push @faqlist, ('0', "[ $faqcat{$faqcat}->{'faqcatname'} ]");
|
||||
foreach my $faqid (sort { $faqq{$a}->{'sortorder'} <=> $faqq{$b}->{'sortorder'} }
|
||||
grep { $faqq{$_}->{'faqcat'} eq $faqcat } keys %faqq)
|
||||
{
|
||||
next unless ($faqq{$faqid}->{'question'});
|
||||
my $q = "... $faqq{$faqid}->{'question'}";
|
||||
$q =~ s/^\s+//;
|
||||
$q =~ s/\s+$//;
|
||||
$q =~ s/\n/ /g;
|
||||
if (length($q) > 50) {
|
||||
$q = substr($q, 0, 50) . "...";
|
||||
}
|
||||
push @faqlist, ($faqid, $q);
|
||||
}
|
||||
}
|
||||
$ret .= LJ::html_select({ 'name' => 'faqid', 'onchange' => 'updateFaqLink()' }, @faqlist) . "\n";
|
||||
$ret .= qq(<script language="JavaScript"><!--
|
||||
if (document.getElementById)
|
||||
document.write("<a href='faq.bml' id='faqlink'>View FAQ</a>");
|
||||
//--></script>);
|
||||
$ret .= "</td></tr>\n";
|
||||
}
|
||||
|
||||
# answer type
|
||||
{
|
||||
$ret .= "<tr><td align='right'>Reply Type:</td><td>";
|
||||
|
||||
# if less than 2, remote is the person filing the request
|
||||
# so all they can do is add more info
|
||||
if (@ans_type > 2) {
|
||||
$ret .= LJ::html_select({ 'name' => 'replytype',
|
||||
'onchange' => "check_replytype()" },
|
||||
@ans_type) . "\n";
|
||||
$ret .= "<div id='bounce_email' style='display:none'>";
|
||||
$ret .= " Email/User: " . LJ::html_text({ 'name' => 'bounce_email', 'size' => '25' });
|
||||
$ret .= "</div>";
|
||||
} else {
|
||||
$ret .= LJ::html_hidden('replytype', $ans_type[0]) . "\n";
|
||||
$ret .= "<b>$ans_type[1]</b>";
|
||||
}
|
||||
$ret .= "</td></tr>\n";
|
||||
}
|
||||
|
||||
# helpers can do actions:
|
||||
if (LJ::Support::can_perform_actions($sp, $remote) && ! $is_poster)
|
||||
{
|
||||
$ret .= "<tr><td align='right'></td><td>\n";
|
||||
|
||||
$ret .= "<table cellpadding='5'>";
|
||||
|
||||
$ret .= "<tr><td>Change Category:<br />";
|
||||
$ret .= LJ::html_select({ 'name' => 'changecat' },
|
||||
('', $sp->{'_cat'}->{'catname'}),
|
||||
map { $_->{'spcatid'}, "---> $_->{'catname'}" }
|
||||
LJ::Support::sorted_cats($cats));
|
||||
$ret .= "</td>";
|
||||
|
||||
if (@screened && $helper_mode) {
|
||||
$ret .= "<td>Approve Screened Response:<br />";
|
||||
$ret .= LJ::html_select({ 'name' => 'approveans' },
|
||||
('', ''),
|
||||
map { $_->{'splid'}, "\#$_->{'splid'} (" . LJ::get_username($_->{'userid'}) . ")" }
|
||||
@screened);
|
||||
$ret .= LJ::html_select({ 'name' => 'approveas' },
|
||||
("answer" => "as answer", "comment" => "as comment",));
|
||||
$ret .= "</td>";
|
||||
}
|
||||
$ret .= "</tr></table>\n";
|
||||
|
||||
$ret .= "</td></tr>\n";
|
||||
if ($sp->{'timelasthelp'} > ($sp->{'timetouched'}+5)) {
|
||||
$ret .= "<tr><td align='right'>Put in Queue:</td><td>";
|
||||
$ret .= LJ::html_check({ 'type' => 'checkbox', 'name' => 'touch' });
|
||||
$ret .= "<?de (Use this to re-open the request.) de?>\n";
|
||||
$ret .= "</td></tr>\n";
|
||||
} else {
|
||||
$ret .= "<tr><td align='right'>Take out of Queue:</td><td>";
|
||||
$ret .= LJ::html_check({ 'type' => 'checkbox', 'name' => 'untouch' });
|
||||
$ret .= "<?de (Use this to change status to "awaiting close".) de?>\n";
|
||||
$ret .= "</td></tr>\n";
|
||||
}
|
||||
if (LJ::Support::can_change_summary($sp, $remote)) {
|
||||
$ret .= "<tr><td>Change summary:</td><td>";
|
||||
$ret .= LJ::html_check({ 'type' => 'checkbox', 'name' => 'changesum' });
|
||||
$ret .= LJ::html_text({ 'type' => 'text', 'name' => 'summary', 'size' => '50', 'maxlength' => '80', 'value' => $sp->{'subject'} });
|
||||
$ret .= "</td></tr>\n";
|
||||
$ret .= "<tr><td> </td><td>";
|
||||
$ret .= "<?de (Use this to change the request summary.) de?>\n";
|
||||
$ret .= "</td></tr>\n";
|
||||
}
|
||||
}
|
||||
# Prefill an e-mail validation nag, if needed.
|
||||
my $validationnag;
|
||||
if (!(LJ::isu($u) && ($u->underage && $u->{'status'} eq 'T')) &&
|
||||
($u->{'status'} eq "N" || $u->{'status'} eq "T") &&
|
||||
! $is_poster) {
|
||||
my $reminder = LJ::load_include('validationreminder');
|
||||
$validationnag .= "\n\n$reminder" if $reminder;
|
||||
}
|
||||
|
||||
# add in canned answers if there are any for this category and the user can use them
|
||||
if ($helper_mode && ! $is_poster) {
|
||||
my $rows = $dbr->selectall_arrayref('SELECT subject, body FROM support_answers WHERE spcatid = ? ORDER BY subject',
|
||||
undef, $sp->{_cat}->{spcatid});
|
||||
if ($rows && @$rows) {
|
||||
$ret .= "<tr valign='top'><td align='right'>Stock answers:</td><td colspan='2'>\n";
|
||||
$ret .= "<script type='text/javascript'>\n";
|
||||
$ret .= "var Iarr = new Array();\n";
|
||||
my $i = 0;
|
||||
foreach my $row (@$rows) {
|
||||
$ret .= "Iarr[$i] = '" . LJ::ejs($row->[1]) . "';\n";
|
||||
$i++;
|
||||
}
|
||||
$ret .= "function insertCanned(i) {\n";
|
||||
$ret .= " var obj = document.getElementById('body');\n";
|
||||
$ret .= " var canned = document.getElementById('canned');\n";
|
||||
$ret .= " if (canned && canned.value > -1 && obj) {\n";
|
||||
$ret .= " obj.value = obj.value + Iarr[canned.value];\n";
|
||||
$ret .= " }\n";
|
||||
$ret .= "}\n";
|
||||
$ret .= "</script>\n";
|
||||
$ret .= "<select id='canned' onChange='insertCanned();'>\n";
|
||||
$ret .= "<option value='-1' selected>( select canned to insert )</option>\n";
|
||||
$i = 0;
|
||||
foreach my $row (@$rows) {
|
||||
$ret .= "<option value='$i'>$row->[0]</option>\n";
|
||||
$i++;
|
||||
}
|
||||
$ret .= "</input>\n";
|
||||
$ret .= "</td></tr>";
|
||||
}
|
||||
}
|
||||
|
||||
# textarea for their message body
|
||||
$ret .= "<tr valign='top'><td align='right'>Message:</td><td colspan='2'>";
|
||||
$ret .= LJ::html_textarea({ 'rows' => '12', 'cols' => '80', 'wrap' => 'virtual', 'id' => 'body', 'name' => 'body', 'value' => $validationnag }) . "<br />";
|
||||
$ret .= "<?de No HTML allowed, so don't worry about about escaping < and ><br />URLs are automatically link-ified, so just reference those. de?><br />";
|
||||
$ret .= LJ::html_submit('submitpost', "Post Comment/Solution");
|
||||
$ret .= "</td></tr></table>\n";
|
||||
|
||||
$ret .= "</form>\n";
|
||||
|
||||
return $ret;
|
||||
|
||||
}
|
||||
_code?>
|
||||
<?hr?>
|
||||
<?_code
|
||||
{
|
||||
use strict;
|
||||
use vars qw(%FORM);
|
||||
return '' if $FORM{'find'};
|
||||
my $spid = $FORM{'id'}+0;
|
||||
return "Go to: <a href='$LJ::SITEROOT/support/see_request.bml?id=$spid&find=prev'>previous open request</a>, " .
|
||||
"<a href='$LJ::SITEROOT/support/see_request.bml?id=$spid&find=next'>next open request</a>"
|
||||
}
|
||||
_code?>
|
||||
<br />
|
||||
Back to the <a href="help.bml">list of open requests</a>.<br />
|
||||
Back to the <a href="./">support area</a>.
|
||||
|
||||
<=body
|
||||
page?><?_c <LJDEP>
|
||||
link: htdocs/support/faqbrowse.bml, htdocs/styles/browse/styleinfo.bml
|
||||
link: htdocs/support/help.bml, htdocs/support/act.bml, htdocs/login.bml
|
||||
link: htdocs/guide/support.bml, htdocs/support/faq.bml, htdocs/support/index.bml
|
||||
link: htdocs/allpics.bml
|
||||
img: htdocs/userpic
|
||||
post: htdocs/support/append_request.bml
|
||||
</LJDEP> _c?>
|
||||
207
livejournal/htdocs/support/stock_answers.bml
Executable file
207
livejournal/htdocs/support/stock_answers.bml
Executable file
@@ -0,0 +1,207 @@
|
||||
<?page
|
||||
title=>Support Stock Answers
|
||||
body<=
|
||||
<?_code
|
||||
{
|
||||
use strict;
|
||||
use vars qw($GET $POST);
|
||||
|
||||
# must be logged in to access this page
|
||||
my $remote = LJ::get_remote();
|
||||
return "<?needlogin?>" unless $remote;
|
||||
|
||||
# most things have a category id
|
||||
my $spcatid = ($GET{spcatid} || $POST{spcatid} || 0) + 0;
|
||||
my $cats = LJ::Support::load_cats();
|
||||
return "<?h1 Error h1?><?p Requested category doesn't exist. p?>"
|
||||
unless !$spcatid || $cats->{$spcatid};
|
||||
|
||||
# editing is based on ability to grant supporthelp. and throw an error if they
|
||||
# posted but can't edit.
|
||||
my $canedit = ($spcatid && LJ::check_priv($remote, 'admin', "supporthelp/$cats->{$spcatid}->{catkey}")) ||
|
||||
LJ::check_priv($remote, 'admin', 'supporthelp') ||
|
||||
LJ::check_priv($remote, 'admin', '*');
|
||||
return "<?h1 Error h1?><?p You do not have access to perform actions here. p?>"
|
||||
if LJ::did_post() && ! $canedit;
|
||||
|
||||
# viewing is based on having supporthelp over the particular category you're viewing.
|
||||
my %canview; # spcatid => 0/1
|
||||
foreach my $cat (values %$cats) {
|
||||
$canview{$cat->{spcatid}} = 1
|
||||
if LJ::Support::can_help({ _cat => $cat }, $remote);
|
||||
}
|
||||
return "<?h1 Error h1?><?p You do not have access to view any stock answers. p?>"
|
||||
unless %canview;
|
||||
return "<?h1 Error h1?><?p You do not have access to view stock answers in that category. p?>"
|
||||
if $spcatid && ! $canview{$spcatid};
|
||||
|
||||
# filter down the category list
|
||||
$cats = { map { $_->{spcatid}, $_ } grep { $canview{$_->{spcatid}} } values %$cats };
|
||||
|
||||
my $ansid = ($GET{ansid} || 0) + 0;
|
||||
|
||||
my $ret = "<?h1 Stock Answers h1?>";
|
||||
my $self = "$LJ::SITEROOT/support/stock_answers.bml";
|
||||
|
||||
if ($POST{'action:delete'}) {
|
||||
my $dbh = LJ::get_db_writer();
|
||||
return "<?h1 Error h1?><?p Unable to get database handle. Please try again. p?>"
|
||||
unless $dbh;
|
||||
|
||||
my $ct = $dbh->do("DELETE FROM support_answers WHERE ansid = ? AND spcatid = ?",
|
||||
undef, $ansid, $spcatid);
|
||||
return "<?h1 Error h1?><?p Error: " . $dbh->errstr . " p?>" if $dbh->err;
|
||||
return "<?h1 Error h1?><?p No answer was found to delete? p?>" unless $ct;
|
||||
return BML::redirect("$self?spcatid=$spcatid&deleted=1");
|
||||
}
|
||||
|
||||
if ($POST{'action:new'} || $POST{'action:save'}) {
|
||||
my ($subj, $body) = ($POST{subject}, $POST{body});
|
||||
|
||||
foreach my $ref (\$subj, \$body) {
|
||||
$$ref =~ s/^\s+//;
|
||||
$$ref =~ s/\s+$//;
|
||||
# FIXME: more stuff to clean it up?
|
||||
}
|
||||
|
||||
return "<?h1 Error h1?><?p Please fill out all fields. p?>"
|
||||
unless $spcatid && $subj && $body;
|
||||
|
||||
my $dbh = LJ::get_db_writer();
|
||||
return "<?h1 Error h1?><?p Unable to get database handle. Please try again. p?>"
|
||||
unless $dbh;
|
||||
|
||||
if ($POST{'action:new'}) {
|
||||
my $newid = LJ::alloc_global_counter('A');
|
||||
return "<?h1 Error h1?><?p Unable to allocate counter. Please try again. p?>"
|
||||
unless $newid;
|
||||
|
||||
$dbh->do("INSERT INTO support_answers (ansid, spcatid, subject, body, lastmodtime, lastmoduserid) " .
|
||||
"VALUES (?, ?, ?, ?, UNIX_TIMESTAMP(), ?)",
|
||||
undef, $newid, $spcatid, $subj, $body, $remote->{userid});
|
||||
return "<?h1 Error h1?><?p Error: " . $dbh->errstr . " p?>" if $dbh->err;
|
||||
|
||||
return BML::redirect("$self?user=$remote->{user}&spcatid=$spcatid&ansid=$newid&added=1");
|
||||
} else {
|
||||
return "<?h1 Error h1?><?p No answer id provided. p?>" unless $ansid;
|
||||
|
||||
$dbh->do("UPDATE support_answers SET subject = ?, body = ?, lastmodtime = UNIX_TIMESTAMP(), " .
|
||||
"lastmoduserid = ? WHERE ansid = ?", undef,
|
||||
$subj, $body, $remote->{userid}, $ansid);
|
||||
return "<?h1 Error h1?><?p Error: " . $dbh->errstr . " p?>" if $dbh->err;
|
||||
|
||||
return BML::redirect("$self?user=$remote->{user}&spcatid=$spcatid&ansid=$ansid&saved=1");
|
||||
}
|
||||
}
|
||||
|
||||
if ($GET{new}) {
|
||||
$ret .= "<form method='post' action='$self'>";
|
||||
|
||||
$ret .= "<?p Please fill out the following form to create a new stock answer. p?>";
|
||||
$ret .= "<?p Category: " . LJ::html_select({ name => 'spcatid', selected => $spcatid },
|
||||
0, "( please select )",
|
||||
map { $_, $cats->{$_}->{catname} }
|
||||
grep { $canview{$_} }
|
||||
sort { $cats->{$a}->{catname} cmp $cats->{$b}->{catname} }
|
||||
keys %$cats) . "<br />";
|
||||
$ret .= "Subject: " . LJ::html_text({ name => 'subject', maxlength => 255, size => 40 }) . "<br />";
|
||||
$ret .= LJ::html_textarea({ name => 'body', rows => 15, cols => 80 }) . "<br />";
|
||||
$ret .= LJ::html_submit('action:new', "Save Answer");
|
||||
$ret .= "</form> p?>";
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
my $dbr = LJ::get_db_reader();
|
||||
return "<?h1 Error h1?><?p No database available. p?>" unless $dbr;
|
||||
|
||||
my $cols = "ansid, spcatid, subject, lastmodtime, lastmoduserid";
|
||||
$cols .= ", body" if $ansid;
|
||||
|
||||
my $sql = "SELECT $cols FROM support_answers";
|
||||
my @bind = ();
|
||||
|
||||
if ($spcatid || $ansid) {
|
||||
$sql .= " WHERE ";
|
||||
if ($spcatid) {
|
||||
$sql .= "spcatid = ?";
|
||||
push @bind, $spcatid;
|
||||
}
|
||||
if ($ansid) {
|
||||
$sql .= ($spcatid ? " AND " : "") . "ansid = ?";
|
||||
push @bind, $ansid;
|
||||
}
|
||||
}
|
||||
|
||||
my $sth = $dbr->prepare($sql);
|
||||
$sth->execute(@bind);
|
||||
return "<?h1 Error h1?><?p Error: " . $sth->errstr . " p?>" if $sth->err;
|
||||
|
||||
$ret .= "<form method='get' action='$self'>";
|
||||
$ret .= "<?p Filter: ";
|
||||
$ret .= LJ::html_select({ name => 'spcatid', selected => $spcatid },
|
||||
0, "( none )",
|
||||
map { $_, $cats->{$_}->{catname} }
|
||||
sort { $cats->{$a}->{catname} cmp $cats->{$b}->{catname} } keys %$cats);
|
||||
$ret .= LJ::html_submit(undef, "Show") . "</form> p?>";
|
||||
|
||||
my %answers;
|
||||
while (my $row = $sth->fetchrow_hashref) {
|
||||
$answers{$row->{spcatid}}->{$row->{ansid}} = {
|
||||
subject => $row->{subject},
|
||||
body => $row->{body},
|
||||
lastmodtime => $row->{lastmodtime},
|
||||
lastmoduser => LJ::load_userid($row->{lastmoduserid}),
|
||||
};
|
||||
}
|
||||
|
||||
$ret .= "<?p [ <a href='$self'>View All</a> ]";
|
||||
$ret .= " [ <a href='$self?new=1&spcatid=$spcatid'>Add New Answer</a> ]" if $canedit;
|
||||
$ret .= " p?>";
|
||||
|
||||
if ($GET{added}) {
|
||||
$ret .= "<?p <strong>Answer added!</strong> p?>";
|
||||
} elsif ($GET{saved}) {
|
||||
$ret .= "<?p <strong>Changes saved!</strong> p?>";
|
||||
} elsif ($GET{deleted}) {
|
||||
$ret .= "<?p <strong>Answer deleted!</strong> p?>";
|
||||
}
|
||||
|
||||
# bilevel sort, fun and messy
|
||||
foreach my $spcatid (sort { $cats->{$a}->{catname} cmp $cats->{$b}->{catname} } keys %$cats) {
|
||||
next unless %{$answers{$spcatid} || {}};
|
||||
|
||||
$ret .= "<?h2 <a href='$self?spcatid=$spcatid'>$cats->{$spcatid}->{catname}</a> h2?>";
|
||||
$ret .= "<ul>";
|
||||
foreach my $ansid (sort {
|
||||
$answers{$spcatid}->{$a}->{subject} cmp $answers{$spcatid}->{$b}->{subject}
|
||||
} keys %{$answers{$spcatid}}) {
|
||||
my ($subj, $body, $lmu, $lmt) =
|
||||
map { $answers{$spcatid}->{$ansid}->{$_} } qw(subject body lastmoduser lastmodtime);
|
||||
if ($body) {
|
||||
$ret .= "<li>";
|
||||
$ret .= "<form method='post' action='$self?ansid=$ansid&spcatid=$spcatid'>";
|
||||
$ret .= LJ::html_text({ name => 'subject', value => $subj, size => 40, maxlength => 255 });
|
||||
$ret .= "<br />";
|
||||
$ret .= LJ::html_textarea({ name => 'body', value => $body, rows => 15, cols => 80 });
|
||||
$ret .= "<br />";
|
||||
$ret .= "Last modified by " . LJ::ljuser($lmu) . " on " . LJ::mysql_time($lmt) . ".<br />";
|
||||
if ($canedit) {
|
||||
$ret .= LJ::html_submit('action:save', "Save Changes");
|
||||
$ret .= LJ::html_submit('action:delete', "Delete Answer",
|
||||
{ onClick => 'return confirm("Are you sure you want to delete this stock answer?");' });
|
||||
}
|
||||
$ret .= "</form></li>";
|
||||
} else {
|
||||
$ret .= "<li><a href='$self?spcatid=$spcatid&ansid=$ansid'>$subj</a></li>";
|
||||
}
|
||||
}
|
||||
$ret .= "</ul>";
|
||||
}
|
||||
|
||||
|
||||
return $ret;
|
||||
}
|
||||
_code?>
|
||||
<=body
|
||||
page?>
|
||||
96
livejournal/htdocs/support/submit.bml
Executable file
96
livejournal/htdocs/support/submit.bml
Executable file
@@ -0,0 +1,96 @@
|
||||
<?page
|
||||
title=>Submit Support Request
|
||||
body<=
|
||||
|
||||
<?_include
|
||||
bml=>1
|
||||
code=>0
|
||||
file=>support-currentproblems
|
||||
_include?>
|
||||
|
||||
<p>From here you can ask a question about <?_code return $LJ::SITENAMESHORT; _code?>. Make sure you've already checked the <a href="faq.bml"><b>Frequently Asked Questions</b></a>.</p>
|
||||
|
||||
<form method="post" action="submit_do.bml">
|
||||
|
||||
<?_code
|
||||
|
||||
my $remote = LJ::get_remote();
|
||||
my $ret;
|
||||
|
||||
LJ::set_active_crumb('supportsubmit');
|
||||
|
||||
my $u;
|
||||
my %eh;
|
||||
if ($remote) {
|
||||
my $userid = $remote->{'userid'}+0;
|
||||
$u = LJ::load_userid($userid);
|
||||
|
||||
foreach (qw(user name)) {
|
||||
$eh{$_} = LJ::ehtml($u->{$_});
|
||||
}
|
||||
|
||||
$eh{'password'} = "_REMOTE";
|
||||
}
|
||||
|
||||
$ret .= <<"END";
|
||||
<p><b>Your name:</b><br />
|
||||
<input name="reqname" size='40' maxlength='50' value=\"$eh{'name'}\" /></p>
|
||||
<p><b>Are you a $LJ::SITENAMESHORT user?</b><br />
|
||||
<table>
|
||||
<tr valign='top'>
|
||||
<td rowspan='2'><input type='radio' name='reqtype' value='user' checked='checked' /></td><td>Yes.</td></tr>
|
||||
<tr><td>Username: <input name='user' size='15' maxlength='15' value='$eh{'user'}' /> Password: <input type='password' name='password' size='15' value='$eh{'password'}' /><br />
|
||||
<?de (Replies to your request will be sent to the e-mail address associated with your $LJ::SITENAMESHORT account) de?></td></tr>
|
||||
<tr valign='top'>
|
||||
<td rowspan='2'><input type="radio" name="reqtype" value="email" /></td><td>No.</td></tr>
|
||||
<tr><td>Your email address: <input name="email" size='30' maxlength='70' /> (not shown to the public)</td></tr>
|
||||
</table>
|
||||
END
|
||||
|
||||
return $ret;
|
||||
|
||||
_code?>
|
||||
|
||||
<p><b>Problem Area</b><br />
|
||||
Select what in particular you're having a problem with:
|
||||
<div style='margin-left: 30px'><select name="spcatid">
|
||||
<?_code
|
||||
use strict;
|
||||
use vars qw(%GET);
|
||||
|
||||
my $ret = "";
|
||||
my $dbr = LJ::get_db_reader();
|
||||
my $sth = $dbr->prepare("SELECT spcatid, catkey, catname FROM supportcat ".
|
||||
"WHERE is_selectable='1' ORDER BY sortorder");
|
||||
$sth->execute;
|
||||
|
||||
while ($_ = $sth->fetchrow_hashref) {
|
||||
my $selected = $GET{'category'} eq $_->{'catkey'} ? "selected='selected'" : " ";
|
||||
$ret .= "<option value='$_->{'spcatid'}' $selected>$_->{'catname'}</option>\n";
|
||||
}
|
||||
return $ret;
|
||||
_code?>
|
||||
</select></div></p>
|
||||
|
||||
<p><b>Problem summary</b><br />
|
||||
Enter a descriptive one-line summary of the problem you're having. A good example would be "Client crashes in friends dialog". A bad example would be "URGENT! plz hlp me!!!! THX!!!".
|
||||
<div style='margin-left: 30px'>
|
||||
<input name="subject" size='40' maxlength='80' />
|
||||
</div></p>
|
||||
|
||||
<p><b>Problem</b><br />
|
||||
And finally, enter your support request. If you want an intelligent fast answer, please <b>provide as much detail as possible</b>. The only rule is do <b>NOT GIVE OUT YOUR PASSWORD</b> because many people could read this request, not just <?_code return $LJ::SITENAMESHORT; _code?> staff.
|
||||
<div style='margin-left: 30px'>
|
||||
<textarea name="message" rows='20' cols='50'></textarea>
|
||||
</div></p>
|
||||
|
||||
<p><b>Done?</b><br />When done, press <input type='submit' value="Submit" />.</p></form>
|
||||
|
||||
<?hr?>
|
||||
<p>Back to the <a href="./">support area</a>.</p>
|
||||
|
||||
<=body
|
||||
page?><?_c <LJDEP>
|
||||
link: htdocs/support/faq.bml, htdocs/support/index.bml
|
||||
post: htdocs/support/submit_do.bml
|
||||
</LJDEP> _c?>
|
||||
81
livejournal/htdocs/support/submit_do.bml
Executable file
81
livejournal/htdocs/support/submit_do.bml
Executable file
@@ -0,0 +1,81 @@
|
||||
<?page
|
||||
title=>Submit Request
|
||||
body<=
|
||||
|
||||
<?_code
|
||||
{
|
||||
use strict;
|
||||
use vars qw(%POST);
|
||||
|
||||
LJ::set_active_crumb('supportsubmit');
|
||||
|
||||
my $apache_req = shift;
|
||||
my $r = $apache_req->{'r'};
|
||||
|
||||
my @errors = ();
|
||||
|
||||
unless (LJ::did_post() && LJ::check_referer('/support/submit.bml')) { push @errors, "<?requirepost?>"; }
|
||||
|
||||
my $u;
|
||||
my $user;
|
||||
my $remote;
|
||||
|
||||
my %req; # the request we're building to submit
|
||||
|
||||
if ($POST{'reqtype'} eq "user")
|
||||
{
|
||||
$req{'reqtype'} = "user";
|
||||
$user = LJ::canonical_username($POST{'user'});
|
||||
if ($POST{'password'} eq "_REMOTE") {
|
||||
$remote = LJ::get_remote();
|
||||
if ($remote && $remote->{'user'} eq $user) {
|
||||
$u = LJ::load_user($remote->{'user'});
|
||||
$req{'requserid'} = $remote->{'userid'};
|
||||
}
|
||||
}
|
||||
unless ($req{'requserid'}) {
|
||||
$u = LJ::load_user($user);
|
||||
push @errors, "Invalid username" unless $u;
|
||||
if (LJ::auth_okay($u, $POST{'password'}, $POST{'hpassword'})) {
|
||||
$req{'requserid'} = $u->{'userid'};
|
||||
} else {
|
||||
push @errors, "Invalid password";
|
||||
}
|
||||
}
|
||||
$req{'reqemail'} = $u->{'email'};
|
||||
}
|
||||
elsif ($POST{'reqtype'} eq "email")
|
||||
{
|
||||
$req{'reqtype'} = "email";
|
||||
$req{'reqemail'} = $POST{'email'};
|
||||
|
||||
LJ::check_email($POST{'email'}, \@errors);
|
||||
}
|
||||
|
||||
$req{'reqname'} = $POST{'reqname'};
|
||||
$req{'body'} = $POST{'message'};
|
||||
$req{'subject'} = $POST{'subject'};
|
||||
$req{'spcatid'} = $POST{'spcatid'};
|
||||
$req{'uniq'} = $r->notes('uniq');
|
||||
|
||||
# insert diagnostic information
|
||||
$req{useragent} = BML::get_client_header('User-Agent')
|
||||
if $LJ::SUPPORT_DIAGNOSTICS{track_useragent};
|
||||
|
||||
return LJ::bad_input(@errors) if @errors;
|
||||
my $spid = LJ::Support::file_request(\@errors, \%req);
|
||||
return LJ::bad_input(@errors) if @errors;
|
||||
|
||||
my $url = "$LJ::SITEROOT/support/see_request.bml?id=$spid";
|
||||
|
||||
return "Your $LJ::SITENAMESHORT support request has been filed and will be answered as soon as possible. Your request tracking number is <B>$spid</B>. You can track its progress here: <div style='margin-left: 30px'><a href='$url'>$url</a></div>";
|
||||
}
|
||||
_code?>
|
||||
|
||||
<?hr?>
|
||||
<p>Back to the <a href="./">support area</a>.</p>
|
||||
|
||||
<=body
|
||||
page?><?_c <LJDEP>
|
||||
link: htdocs/support/see_request.bml, htdocs/support/index.bml
|
||||
</LJDEP> _c?>
|
||||
Reference in New Issue
Block a user