This commit is contained in:
2019-02-06 00:49:12 +03:00
commit 8dbb1bb605
4796 changed files with 506072 additions and 0 deletions

View 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 &lt; and &gt;<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'}&amp;find=prev'>previous</a> /
<a href='see_request.bml?id=$sp->{'spid'}&amp;find=next'>next</a> open request</li>
<li>Go to <a href='see_request.bml?id=$sp->{'spid'}&amp;find=cprev'>previous</a> /
<a href='see_request.bml?id=$sp->{'spid'}&amp;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?>

View 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?>

View 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'} ? "&amp;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'}&amp;find=prev",
'nextopen' => "see_request.bml?id=$sp->{'spid'}&amp;find=next",
'cprevopen' => "see_request.bml?id=$sp->{'spid'}&amp;find=cprev",
'cnextopen' => "see_request.bml?id=$sp->{'spid'}&amp;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?>

View 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?>

View 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?>

View 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?>

View 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" . "&nbsp;&nbsp;"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'>&#x00bb;</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?>

View 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?>

View 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&amp;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>&nbsp;<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>&#x00b6;</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?>

View 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?>

View 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?>

View 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?>

View 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?>

View 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'}&amp;find=cprev'>previous</a>|";
$ret .= "<a href='$LJ::SITEROOT/support/see_request.bml?id=$sp->{'spid'}&amp;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" . "&nbsp;&nbsp;"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 .= "&nbsp;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 &quot;awaiting close&quot;.) 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>&nbsp;</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 &lt; and &gt;<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&amp;find=prev'>previous open request</a>, " .
"<a href='$LJ::SITEROOT/support/see_request.bml?id=$spid&amp;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?>

View 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?>

View 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&#39;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?>

View 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?>