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,623 @@
# LiveJournal.com-specific library
#
# This file is NOT licensed under the GPL. As with everything in the
# "ljcom" CVS repository, this file is the property of Danga
# Interactive and is made available to the public only as a reference
# as to the best way to modify/extend the base LiveJournal server code
# (which is licensed under the GPL).
#
# Feel free to read and learn from things in "ljcom", but don't use
# our schemes because we don't want your site looking like
# LiveJournal.com (our logo and site scheme are our identity and we
# don't want to confuse users)
#
# Instead, use/modify one of the schemes in the "livejournal" repository.
# (Ideally you'd make your own entirely)
#
_parent=>global.look
help=>{Ds}<a href="%%data%%"><img src="<?imgprefix?>/help.gif" alt="(<?_ml Help _ml?>)" title="(<?_ml Help _ml?>)" width='14' height='14' hspace='2' align='absmiddle' border='0'></a>
h1=>{D}<p><span class="heading">%%data%%</span>
h1/follow_choices=>{D}<span class="heading">%%data%%</span>
h2=>{D}<p><span class="heading2">%%data%%</span>
# Banner Header: search results banner, content desriptor, etc...
bh=>{D}<p align="center"><font face="Arial,Helvetica" color="#cc0000" size="-1"><b>%%data%%</b></font>
grin=>{S}&lt;grin&gt;
hr=>{S}<p align="center"><font color=#660066>*</font></p>
newline=>{S}<br />&nbsp;&nbsp;&nbsp;&nbsp;
p=>{DRp}<br />%%data%%
p/follow_p=>{DRps}<br /><img src="<?imgprefix?>/dot.gif" width="1" vspace="6" height="1"><br />%%data%%
emcolor=>{S}#a7c7e8
emcolorlite=>{S}#d9e9f9
altcolor1=>{S}#d9e9f9
altcolor2=>{S}#a7c7e8
de=>{DRp}<span style="color:#909090;">%%data%%</span>
standout<=
{DRps}<center><font size="1"><br /></font>
<table cellspacing="0" cellpadding="0" border="0" bgcolor="<?emcolor?>">
<tr align="left">
<td width="7" align="left" valign="top">
<img width="7" height="7" src="<?imgprefix?>/dys/corn_nw.gif" alt="/"></td>
<td height="7">
<img height="7" src="<?imgprefix?>/dot.gif" alt=""></td>
<td width="7" valign="top" align="right">
<img height="7" src="<?imgprefix?>/dys/corn_ne.gif" alt="\"></td>
</tr><tr align="left">
<td width="7">
<img width="7" height="1" src="<?imgprefix?>/dot.gif" alt=""></td>
<td valign="top">
%%data%%
</td>
<td width="7">
<img width="7" height="1" src="<?imgprefix?>/dot.gif" alt=""></td>
</tr><tr>
<td width="7" align=left valign=top>
<img width="7" height="7" src="<?imgprefix?>/dys/corn_sw.gif" alt="\"></td>
<td height="7">
<img height="7" src="<?imgprefix?>/dot.gif" alt=""></td>
<td width="7" valign=top align=right>
<img height="7" src="<?imgprefix?>/dys/corn_se.gif" alt="/"></td>
</tr>
</table>
</center>
<=standout
warningbar<=
{DRps}<div class="warningbar" style="background-image: URL('<?imgprefix?>/message-warning.gif');">
%%data%%
</div>
<=warningbar
errorbar<=
{DRps}<div class="errorbar" style="background-image: URL('<?imgprefix?>/message-error.gif');">
%%data%%
</div>
<=errorbar
soerror=><div style='background-color:#d0eef9; color:red; font-weight:bold; text-align:center'>%%data%%</div>
emailex=><div style='width: 50%; font-family: courier; background-color: #efefef; border: dotted #cdcdcd 2px; padding: 5px;'>%%data%%</div>
######################### choices stuff
choice=>{PRps}<dt><img src="<?imgprefix?>/dys/b_purp.gif" align="absmiddle" width="8" height="8"> <a href="%%data2%%"><font face="Arial,Helvetica"><b>%%data1%%</b></font></a><dd><font size="2">%%data3%%</font>
choices<=
{FRp}<p><div class="choice"><table width="100%" cellpadding="2" cellspacing="5">
<tr>
<td valign="top" width="50%">
<dl>
%%items%%
</dl>
</td>
<td valign="top" width="50%">
<dl>
%%itemsb%%
</dl>
</td>
</tr>
</table></div>
<=choices
ENTRYFORMCSS<=
{Ss}
<style type="text/css">
#EntryForm #MetaInfo {
width: 100%;
}
#EntryForm th {
font-size: .85em;
}
#EntryForm #SubmitBar {
background-color: #dfdfdf;
padding: 5px;
text-align: center;
border: 1px outset #000;
margin-left: auto; margin-right: auto;
}
#MetaInfo tr {
padding-bottom: 10px;
}
#metainfo th {
text-align: left;
}
#mood_preview {
display: none;
}
#datetime_box input, #datetime_box select {
margin-right: 2px;
}
#EntryForm legend {
font-weight: bold;
}
#EntryForm #Options {
margin-left: 0; margin-right: 0; padding: 0;
background-color: #dfdfdf;
border: 1px outset #000;
}
#EntryForm #Options th {
text-align: left;
}
#EntryForm #infobox {
text-align: center;
}
#EntryForm #infobox table {
background-color: #dfdfdf;
border: 2px solid <?emcolor?>;
}
#EntryForm textarea {
border: 1px inset #000;
padding: 2px;
}
#EntryForm #Security option {
padding-left: 18px;
}
#EntryForm #security_public {
background-image: url("<?imgprefix?>/userinfo.gif");
background-repeat: no-repeat;
}
#EntryForm #security_private {
background-image: url("<?imgprefix?>/icon_private.gif");
background-repeat: no-repeat;
}
#EntryForm #security_friends, #EntryForm #security_custom {
background-image: url("<?imgprefix?>/icon_protected.gif");
background-repeat: no-repeat;
}
#EntryForm #UserpicPreviewImage {
border: 1px solid #000;
}
#EntryForm {
width: 100%;
}
</style>
<=ENTRYFORMCSS
##################################################################################
################################### MAIN PAGE ####################################
##################################################################################
PAGE<=
{Fps}<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html>
<?_code
{
my $remote = LJ::get_remote(); # will be requested later and returned from cache
return LJ::LJcom::expresslane_html_comment($remote, $_[0]->{r});
}
_code?>
<head>
<link rel="SHORTCUT ICON" href="<?siteroot?>/favicon.ico">
<link rel="home" title="Home" href="/" />
<link rel="contents" title="Site Map" href="/site/" />
<link rel="help" title="Technical Support" href="/support/" />
<title><?_code {
my $elhash = $_[2];
return $elhash->{'WINDOWTITLE'} || $elhash->{'TITLE'};
} _code?></title>
<?_code LJ::res_includes() _code?>
<?metactype?>
<style type="text/css">
<!--
p, td { font-size: 12px; font-family: Verdana, Arial, Helvetica, sans-serif; }
li { font-size: 12px; font-family: Verdana, Arial, Helvetica, sans-serif; }
body { font-size: 12px; font-family: Verdana, Arial, Helvetica, sans-serif; margin: 0px; }
.navtext { font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 11px; color: #FF9900; font-weight: bold}
.navlinks { font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 11px; color: #FFFFFF; text-decoration: underline}
a:link { font-family: Verdana, Arial, Helvetica, sans-serif; color: #000066; }
a:visited { font-family: Verdana, Arial, Helvetica, sans-serif; color: #000066; }
a:active { font-family: Verdana, Arial, Helvetica, sans-serif; color: #006699; }
.wtext { font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 11px; font-weight: bold; color: #FFFFFF}
.login { font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 11px}
.wtextunbld { font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 11px; color: #FFFFFF }
.copy { font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 11px; color: #000000}
.heading { font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 13px; color: #660066; font-weight: bold}
.heading2 { font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 13px; color: #660066; font-style: italic }
.talk-comment { margin-top: 1em; }
.lesstop { margin-top: 2px; }
.formitem { color: #343434; font-size: 1em; }
.formnumber { font-weight: bold; margin-top: 1.8em; font-size: .9em; }
.formitemName { font-weight: bold; font-size: .9em; margin-top: 1.8em; }
.formitemDesc { margin-top: .4em; margin-bottom: .4em; color: #505050; }
.formitemNote { color: #da6320; font-size: .9em; margin-top: .4em; margin-bottom: .4em; }
.formitemFlag { color: #CE0000; font-size: .9em; margin-top: .4em; margin-bottom: .4em; }
.borderedtable { border: solid 1px black; }
.borderedtable th { background-color: #dddddd; border-bottom: solid 1px black; padding-left: 10px; padding-right: 10px; white-space: nowrap; font-size: 0.8em; }
#Comments q { padding-left: 2.5em; font-style: italic; }
.errorbar {
color: #000;
font: 12px Verdana, Arial, Sans-Serif;
background-color: #FFEEEE;
background-repeat: repeat-x;
border: 1px solid #FF9999;
padding: 8px;
margin-top: auto; margin-bottom: auto;
margin-left: auto; margin-right: auto;
width: auto;
text-align: left;
}
.warningbar {
color: #000;
font: 12px Verdana, Arial, Sans-Serif;
background-color: #FFFFDD;
background-repeat: repeat-x;
border: 1px solid #FFCC33;
padding: 8px;
margin-top: auto; margin-bottom: auto;
margin-left: auto; margin-right: auto;
width: auto;
text-align: left;
}
-->
</style>
<script language="JavaScript">
window.onerror = null; // damn javascript.
</script>
<?_code return (! LJ::get_remote() &&
! $LJ::IS_SSL &&
! $LJ::REQ_HEAD_HAS{'chalresp_js'}++) ?
$LJ::COMMON_CODE{'chalresp_js'} : "";
_code?>
<?_code
use strict;
my $crumb_up;
if(LJ::get_active_crumb() ne '')
{
my $parentcrumb = LJ::get_parent_crumb();
$crumb_up = "<link rel='up' title='$parentcrumb->[0]' href='$parentcrumb->[1]' />";
}
return $crumb_up;
_code?>
%%head%%
</head>
<body bgcolor="#FFFFFF" background="<?imgprefix?>/dys/bg.gif" leftmargin="0" topmargin="0" marginwidth="0" marginheight="0" text="#000000" link="#660066" vlink="#000066" alink="#CC6600" %%bodyopts%%>
<basefont face="Verdana,Arial,Helvetica">
<table width="100%" border="0" cellspacing="0" cellpadding="0">
<tr align="left" valign="top">
<td colspan='2'>
<table width='100%' border="0" cellspacing="0" cellpadding="0" background="<?imgprefix?>/dys/bg_top.gif">
<tr>
<td><a href="<?siteroot?>/"><img src="<?imgprefix?>/dys/logo1.gif" width="122" height="51" border="0"></a></td>
<td width="163" align="left" valign="top"><a href="<?siteroot?>/"><img src="<?imgprefix?>/dys/logo2.gif" width="170" height="51" border="0"></a></td>
<td background="<?imgprefix?>/dys/bg_top.gif" align="left" valign="top" width="244">&nbsp;</td>
<td background="<?imgprefix?>/dys/bg_top.gif" align="left" valign="top" width="100%">&nbsp;</td>
</tr>
</table>
</td>
</tr>
<!-- logo, then search & logged in links bar stack on top of each other -->
<tr align="left" valign="top">
<td width="<?_ml dystopia.nav.width _ml?>" height="49"
><?_code
unless ($BML::COOKIE{'langpref'}) {
return '<img src="<?imgprefix?>/dys/logo3-lang.gif" width="122" height="52" border="0" ismap="ismap" usemap="#setlang"><map name="setlang"><area href="/manage/siteopts.bml" shape="rect" coords="50,25,122,50"></map>';
} else {
return '<img src="<?imgprefix?>/dys/logo3.gif" width="122" height="52" border="0">';
}
_code?></td>
<td height="49">
<table width="100%" border="0" cellspacing="0" cellpadding="0">
<colgroup span="3">
<col width="19%" />
<col width="34%" />
<col width="47%" />
</colgroup>
<!-- search bar -->
<tr valign="top">
<td height="24" width="19%" align="left">&nbsp;</td>
<form action="/multisearch.bml">
<td height="24" align="right" valign="middle" colspan="2" nowrap="nowrap">
<font face="verdana, arial, sans-serif" color=#333333 size=-2>
<span class="wtextunbld"><label for='searchlj'><?_ml dystopia.searchlj _ml?></label>&nbsp;</span>
<?_code
#BML:cache
my $ret;
my ($cur, $val) = ("user", "");
my ($uri, $args) = (BML::get_uri(), BML::get_query_string());
if ($uri eq '/interests.bml' && $args =~ /int=(.+?)(&|$)/) {
$cur = "int";
$val = LJ::durl($1);
}
if ($FORM{'s_loc'}) {
$cur = "region";
}
my $hval = LJ::ehtml($val);
$ret .= "<input id='searchlj' type='text' name='q' size='15' class='login' value='$hval'> ";
$ret .= '<select style="FONT-SIZE: 10px; FONT-FAMILY: verdana, arial, helvetica" name=type>';
foreach my $it (
["user", BML::ml("Username")],
["email", BML::ml("Email")],
["region", BML::ml("dystopia.search.region")],
["int", BML::ml("dystopia.search.int")],
["aolim", BML::ml("dystopia.search.aolim")],
["icq", BML::ml("dystopia.search.icq")],
["yahoo", BML::ml("dystopia.search.yahoo")],
["msn", BML::ml("dystopia.search.msn")],
["jabber", BML::ml("dystopia.search.jabber")],
) {
next if ($it->[0] eq "region" && $LJ::DISABLED{'directory'});
my $sel = $cur eq $it->[0] ? " SELECTED" : "";
$ret .= "<option value=$it->[0]$sel>$it->[1]";
}
return BML::noparse($ret);
_code?>
</select>
<img src="<?imgprefix?>/dot.gif" width="1" height="5">
<input type=submit value="<?_ml btn.search _ml?>" class="login">
</font>
</td></form>
</tr>
<!-- /search livejournal bar -->
<!-- logged in bar -->
<tr>
<td height="27" class="wtext" width="53%" colspan="2" nowrap="nowrap" valign="middle">
<?_code
#BML:cache
if (LJ::get_remote()) {
return BML::noparse(BML::ml("dystopia.hello_loggedin", { 'username' => LJ::get_remote()->{'user'} }));
} else {
return BML::noparse(BML::ml("dystopia.hello_anonymous"))
}
_code?></td>
<td height="27" width="47%" nowrap="nowrap" align="right" valign="middle">
<a href="/"><span class="navlinks"><?_ml dystopia.nav.home _ml?></span></a> <span class="navtext">|</span>
<a href="/site/"><span class="navlinks"><?_ml dystopia.nav.sitemap _ml?></span></a> <span class="navtext">|</span>
<a href="/news.bml"><span class="navlinks"><?_ml dystopia.nav.news _ml?></span></a> <span class="navtext">|</span>
<a href="/manage/siteopts.bml"><span class="navlinks"><?_ml dystopia.nav.siteopts _ml?></span></a> <span class="navtext">|</span>
<a href="/support/"><span class="navlinks"><?_ml Help _ml?></span></a>
<?_code
#BML:cache
my $r = LJ::get_remote();
if ($r) {
return BML::noparse(' <span class="navtext">|</span> <a href="/logout.bml?user=' . "$r->{'user'}&amp;sessid=$r->{'_session'}->{'sessid'}" . '"><span class="navlinks">' . BML::ml("dystopia.nav.logout") . '</span></a>');
}
return;
_code?>
<img src="<?imgprefix?>/dys/5x5.gif" width="10" height="5"></td>
</tr>
<!-- /logged in bar -->
</table>
</td>
</tr>
<!-- /logo, search, logged in bar -->
<!-- left sidebar and body -->
<tr align="left" valign="top">
<td bgcolor="#336699" width="<?_ml dystopia.nav.width _ml?>" height="813">
<table width="<?_ml dystopia.nav.width _ml?>" border="0" cellspacing="0" cellpadding="10">
<?_code
#BML:cache
my @nav;
my $remote = LJ::get_remote();
if ($remote) {
push @nav, { 'name' => BML::ml('dystopia.navhead.journal'),
'links' => [ { 'url' => '/update.bml',
'text' => BML::ml('dystopia.nav.updatejournal'), },
{ 'url' => "/users/$remote->{'user'}/",
'text' => BML::ml('dystopia.nav.journalrecent'), },
{ 'url' => "/users/$remote->{'user'}/calendar",
'text' => BML::ml('dystopia.nav.journalcalendar'), },
{ 'url' => "/users/$remote->{'user'}/friends",
'text' => BML::ml('dystopia.nav.journalfriends'),
'extra' => '/friends/filter.bml', },
{ 'url' => "/userinfo.bml?user=$remote->{'user'}",
'text' => BML::ml('dystopia.nav.journalinfo'),
'extra' => "/userinfo.bml?user=$remote->{'user'}&mode=full",
},
{ 'url' => "/tools/memories.bml?user=$remote->{'user'}",
'text' => BML::ml('dystopia.nav.memories'), },
{ 'url' => "/editjournal.bml",
'text' => BML::ml('dystopia.nav.editentries'), },
],
};
push @nav, { 'name' => BML::ml('dystopia.navhead.settings'),
'links' => [ { 'url' => '/manage/',
'text' => BML::ml('dystopia.nav.manage') },
{ 'url' => '/editinfo.bml',
'text' => BML::ml('dystopia.nav.personalinfo') },
{ 'url' => "/friends/edit.bml",
'text' => BML::ml('dystopia.nav.editfriends'), },
{ 'url' => "/editpics.bml",
'text' => BML::ml('dystopia.nav.editpics'), },
{ 'url' => "/changepassword.bml",
'text' => BML::ml('dystopia.nav.editpassword'), },
{ 'url' => "/modify.bml",
'text' => BML::ml('dystopia.nav.modifyjournal'), },
{ 'url' => "/styles/edit.bml",
'text' => BML::ml('dystopia.nav.editstyle'), },
],
};
}
else
{
push @nav, { 'name' => BML::ml('dystopia.navhead.welcome'),
'links' => [
{ 'url' => '/login.bml',
'text' => BML::ml('dystopia.nav.login'), },
{ 'url' => '/create.bml',
'text' => BML::ml('dystopia.nav.createjournal'), },
{ 'url' => "/update.bml",
'text' => BML::ml('dystopia.nav.updatejournal'), },
],
};
}
push @nav, { 'name' => BML::ml('dystopia.navhead.findusers'),
'links' => [
{ 'url' => '/random.bml',
'text' => BML::ml('dystopia.nav.findrandom'), },
$LJ::DISABLED{'directory'} ? () :
(
{ 'url' => '/directory.bml',
'text' => BML::ml('dystopia.nav.findregion'), }
),
{ 'url' => '/community/',
'text' => BML::ml('dystopia.nav.findcomm'), },
{ 'url' => '/interests.bml',
'text' => BML::ml('dystopia.nav.findint'), },
$LJ::DISABLED{'directory'} ? () :
(
{ 'url' => '/directorysearch.bml',
'text' => BML::ml('dystopia.nav.finddir'), }
),
],
};
push @nav, { 'name' => 'LiveJournal',
'links' => [
{ 'url' => '/download/',
'text' => BML::ml('dystopia.nav.download'), },
{ 'url' => '/paidaccounts/',
'text' => BML::ml('dystopia.nav.paidaccts'), },
{ 'url' => '/pay/',
'text' => BML::ml('dystopia.nav.paymentarea'), },
],
};
push @nav, { 'name' => BML::ml('dystopia.navhead.help'),
'links' => [ { 'url' => '/support/faq.bml',
'text' => BML::ml('dystopia.nav.faq'), },
{ 'url' => '/support/',
'text' => BML::ml('dystopia.nav.support'), },
{ 'url' => '/lostinfo.bml',
'text' => BML::ml('dystopia.nav.lostinfo'), },
{ 'url' => '/developer/',
'text' => BML::ml('dystopia.nav.developer'), },
{ 'url' => '/press/staff.bml',
'text' => BML::ml('dystopia.nav.contact'), },
],
};
push @nav, { 'name' => BML::ml('dystopia.navhead.legal'),
'links' => [ { 'url' => '/legal/tos.bml',
'text' => BML::ml('dystopia.nav.legaltos'), },
{ 'url' => '/legal/privacy.bml',
'text' => BML::ml('dystopia.nav.legalprivacy'), },
{ 'url' => '/legal/dmca.bml',
'text' => BML::ml('dystopia.nav.legaldmca'), },
],
};
my $ret = $LJ::DYS_LEFT_TOP;
foreach my $sec (@nav) {
$ret .= "<tr align=left valign=top><td><p><span class=navtext>$sec->{'name'}</span><br />";
foreach my $l (@{$sec->{'links'}}) {
$ret .= "<a href=\"$l->{'url'}\"><span class=navlinks>$l->{'text'}</span></a>";
if ($l->{'extra'}) {
$ret .= " <a href=\"$l->{'extra'}\"><span class=navlinks>...</span></a>";
}
$ret .= "<br />";
}
$ret .= "</td></tr>";
}
return BML::noparse($ret);
_code?>
<tr align="left" valign="top">
<td>&nbsp;</td>
</tr>
<tr align="left" valign="top">
<td>&nbsp;</td>
</tr>
<tr align="left" valign="top">
<td>&nbsp;</td>
</tr>
</table>
<p>&nbsp;</p>
<p>&nbsp;</p>
</td>
<td height="813" bgcolor="#FFFFFF">
<table width="100%" border="0" cellspacing="0" cellpadding="0">
<!-- login bar -->
<?_code
#BML:cache
#WITHPORTAL: unless ($remote || BML::get_uri() eq "/") {
my $remote = LJ::get_remote();
unless ($remote || BML::get_uri eq '/login.bml') {
my $button;
my $logincaption = BML::ml('dystopia.btn.login');
if ($logincaption eq 'LOGIN') {
if (! $LJ::IS_SSL) {
$button = "<input type=image onclick='return sendForm()' src='$LJ::IMGPREFIX/dys/login_but.gif' width='48' height='15' border='0'>";
} else {
$button = "<input type=image src='$LJ::IMGPREFIX/dys/login_but.gif' width='48' height='15' border='0'>";
}
} else {
if (! $LJ::IS_SSL) {
$button = "<input type='submit' onclick='return sendForm()' value='$ML{'dystopia.btn.login'}' style='margin-top: 0px; margin-bottom: 1px; font-weight: bold; height: 19px; border: 1px solid #ffffff; background: #336699 none; color: #ffffff; padding-left: 0px; padding-right: 0px'></td>";
} else {
$button = "<input type='submit' value='$ML{'dystopia.btn.login'}' style='margin-top: 0px; margin-bottom: 1px; font-weight: bold; height: 19px; border: 1px solid #ffffff; background: #336699 none; color: #ffffff; padding-left: 0px; padding-right: 0px'></td>";
}
}
my $chal = LJ::challenge_generate(300);
return <<"END_LOGIN_BAR";
<form action="/login.bml" method="post" id='login'>
<input type="hidden" name="mode" value="login" />
<input type='hidden' name='chal' id='login_chal' value='$chal' />
<input type='hidden' name='response' id='login_response' value='' />
<tr>
<td align="right" valign="top" bgcolor="#FFFFFF">
<table border='0' cellspacing='0' cellpadding='0' width='200' align='right'>
<tr>
<td align="left" valign="bottom" bgcolor="#660066"><img src="<?imgprefix?>/dys/lg_crnrgif.gif" width="14" height="23"></td>
<td align="right" valign="middle" bgcolor="#660066" class="wtextunbld" nowrap="nowrap">&nbsp;$ML{'Username'}:&nbsp;</td>
<td align="center" valign="top" bgcolor="#660066" class="wtext" nowrap="nowrap"><input type="text" name="user" size="15" maxlength="15" class="login" style="<?loginboxstyle?>"></td>
<td align="right" valign="middle" bgcolor="#660066" class="wtextunbld" nowrap="nowrap">&nbsp;$ML{'Password'}:&nbsp;</td>
<td align="center" valign="top" bgcolor="#660066" class="wtext" nowrap="nowrap"><input type="password" name="password" size="10" id='xc_password' class="login"></td>
<td align="center" valign="middle" bgcolor="#660066" nowrap="nowrap">&nbsp;$button</tr>
</table>
</td></tr>
</form>
END_LOGIN_BAR
}
return;
_code?>
<!-- /login bar -->
<tr align="left" valign="top" bgcolor="#ffffff">
<td height="585" colspan="7">
<!-- body area -->
<table border="0" cellspacing="0" cellpadding="10" width="100%"><tr><td>
<?breadcrumbs?>
%%pretitle%%
<font size="+2" face="Verdana, Arial, Helvetica" color=#000066>%%title%%</font><p>
%%body%%
</td></tr></table>
<!-- /body area -->
</td></tr></table>
</td></tr></table>
</body></html>
<=PAGE

View File

@@ -0,0 +1,213 @@
# SSL scheme
# LiveJournal.com-specific library
#
# This file is NOT licensed under the GPL. As with everything in the
# "ljcom" CVS repository, this file is the property of Danga
# Interactive and is made available to the public only as a reference
# as to the best way to modify/extend the base LiveJournal server code
# (which is licensed under the GPL).
#
# Feel free to read and learn from things in "ljcom", but don't use our styles
# because we don't want your site looking like LiveJournal.com (our logo
# and site scheme are our identity and we don't want to confuse users)
#
######################### little stuff
_parent=>global.look
imgprefix=>{S}/img
statprefix=>{S}/stc
help=>{Ds}<a href="%%data%%"><img src="/img/help.gif" alt="(<?_ml Help _ml?>)" title="(<?_ml Help _ml?>)" width='14' height='14' hspace='2' align='absmiddle' border='0'></a>
h1=>{D}<p><span class="heading">%%data%%</span>
h1/follow_choices=>{D}<span class="heading">%%data%%</span>
h2=>{D}<p><span class="heading2">%%data%%</span>
# Banner Header: search results banner, content desriptor, etc...
bh=>{D}<p align="center"><font face="Arial,Helvetica" color="#cc0000" size="-1"><b>%%data%%</b></font>
grin=>{S}&lt;grin&gt;
hr=>{S}<p align="center"><font color=#660066>*</font></p>
newline=>{S}<br />&nbsp;&nbsp;&nbsp;&nbsp;
p=>{DRp}<br />%%data%%
p/follow_p=>{DRps}<br /><img src="/img/dot.gif" width="1" vspace="6" height="1"><br />%%data%%
emcolor=>{S}#a7c7e8
emcolorlite=>{S}#d9e9f9
de=>{DRp}<span style="color:#909090;">%%data%%</span>
standout<=
{DRps}<center><font size="1"><br /></font>
<table cellspacing="0" cellpadding="0" border="0" bgcolor="<?emcolor?>">
<tr align="left">
<td width="7" align="left" valign="top">
<img width="7" height="7" src="/img/dys/corn_nw.gif" alt="/"></td>
<td height="7">
<img height="7" src="/img/dot.gif" alt=""></td>
<td width="7" valign="top" align="right">
<img height="7" src="/img/dys/corn_ne.gif" alt="\"></td>
</tr><tr align="left">
<td width="7">
<img width="7" height="1" src="/img/dot.gif" alt=""></td>
<td valign="top">
%%data%%
</td>
<td width="7">
<img width="7" height="1" src="/img/dot.gif" alt=""></td>
</tr><tr>
<td width="7" align=left valign=top>
<img width="7" height="7" src="/img/dys/corn_sw.gif" alt="\"></td>
<td height="7">
<img height="7" src="/img/dot.gif" alt=""></td>
<td width="7" valign=top align=right>
<img height="7" src="/img/dys/corn_se.gif" alt="/"></td>
</tr>
</table>
</center>
<=standout
######################### choices stuff
choice=>{PRps}<dt><img src="/img/dys/b_purp.gif" align="absmiddle" width="8" height="8"> <a href="%%data2%%"><font face="Arial,Helvetica"><b>%%data1%%</b></font></a><dd><font size="2">%%data3%%</font>
choices<=
{FRp}<p><div class="choice"><table width="100%" cellpadding="2" cellspacing="5">
<tr>
<td valign="top" width="50%">
<dl>
%%items%%
</dl>
</td>
<td valign="top" width="50%">
<dl>
%%itemsb%%
</dl>
</td>
</tr>
</table></div>
<=choices
##################################################################################
################################### MAIN PAGE ####################################
##################################################################################
PAGE<=
{Fps}<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html>
<head>
<link rel="SHORTCUT ICON" href="<?siteroot?>/favicon.ico">
<title>%%title%%</title>
<?metactype?>
<style type="text/css">
<!--
p, td { font-size: 12px; font-family: Verdana, Arial, Helvetica, sans-serif; }
li { font-size: 12px; font-family: Verdana, Arial, Helvetica, sans-serif; }
body { font-size: 12px; font-family: Verdana, Arial, Helvetica, sans-serif; margin: 0px; }
.navtext { font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 11px; color: #FF9900; font-weight: bold}
.navlinks { font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 11px; color: #FFFFFF; text-decoration: underline}
a:link { font-family: Verdana, Arial, Helvetica, sans-serif; color: #000066; }
a:visited { font-family: Verdana, Arial, Helvetica, sans-serif; color: #000066; }
a:active { font-family: Verdana, Arial, Helvetica, sans-serif; color: #006699; }
.wtext { font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 11px; font-weight: bold; color: #FFFFFF}
.login { font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 11px}
.wtextunbld { font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 11px; color: #FFFFFF }
.copy { font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 11px; color: #000000}
.heading { font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 13px; color: #660066; font-weight: bold}
.heading2 { font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 13px; color: #660066; font-style: italic }
-->
</style>
<script language="JavaScript">
window.onerror = null; // damn javascript.
</script>
%%head%%
</head>
<?_code
$BML::Dys::remote = LJ::get_remote();
return;
_code?>
<body bgcolor="#FFFFFF" background="/img/dys/bg.gif" leftmargin="0" topmargin="0" marginwidth="0" marginheight="0" text="#000000" link="#660066" vlink="#000066" alink="#CC6600" %%bodyopts%%>
<basefont face="Verdana,Arial,Helvetica">
<table width="100%" border="0" cellspacing="0" cellpadding="0">
<tr align="left" valign="top">
<td colspan='2'>
<table width='100%' border="0" cellspacing="0" cellpadding="0" background="/img/dys/bg_top.gif">
<tr>
<td><a href="<?siteroot?>/"><img src="/img/dys/logo1.gif" width="122" height="51" border="0"></a></td>
<td width="163" align="left" valign="top"><a href="<?siteroot?>/"><img src="/img/dys/logo2.gif" width="170" height="51" border="0"></a></td>
<td background="/img/dys/bg_top.gif" align="left" valign="top" width="244">&nbsp;</td>
<td background="/img/dys/bg_top.gif" align="left" valign="top" width="100%">&nbsp;</td>
</tr>
</table>
</td>
</tr>
<!-- logo, then search & logged in links bar stack on top of each other -->
<tr align="left" valign="top">
<td width="<?_ml dystopia.nav.width _ml?>" height="49"><img
src="/img/dys/logo3.gif" width="122" height="52" border="0"></td>
<td height="49">
<table width="100%" border="0" cellspacing="0" cellpadding="0">
<!-- search bar -->
<tr valign="top">
<td height="24" width="19%" align="left">&nbsp;</td>
<td height="24" align="right" valign="middle" nowrap>
</td>
</tr>
<!-- /search livejournal bar -->
<!-- logged in bar -->
<tr>
<td height="27" class="wtext" width="53%" colspan="2" align='right' nowrap="nowrap" valign="middle">
LiveJournal Secure Site <img src='/img/dys/lock.gif' width='14' height='15' hspace='2'>
</td>
</tr>
<!-- /logged in bar -->
</table>
</td>
</tr>
<!-- /logo, search, logged in bar -->
<!-- left sidebar and body -->
<tr align="left" valign="top">
<td height="813" colspan='2' bgcolor="#FFFFFF">
<table width="100%" border="0" cellspacing="0" cellpadding="0">
<tr align="left" valign="top" bgcolor="#ffffff">
<td height="585" colspan="7">
<!-- body area -->
<table border="0" cellspacing="0" cellpadding="10" width="100%"><tr><td>
%%pretitle%%
<div style='margin-left: 40px'>
<font size="+2" face="Verdana, Arial, Helvetica" color=#000066>%%title%%</font><p>
%%body%%
</div>
</td></tr></table>
<!-- /body area -->
</td></tr></table>
</td></tr></table>
</body></html>
<=PAGE

View File

@@ -0,0 +1,838 @@
#!/usr/bin/perl
#
package LJ::Con;
my $success = sub {
my ($out, $msg) = @_;
push @$out, [ "", $msg ];
return 1;
};
my $fail = sub {
my ($out, $msg) = @_;
push @$out, [ "error", $msg ];
return 0;
};
my $usage = sub {
my ($out, $cmdname) = @_;
return $fail->($out, "usage: $cmdname $cmd{$cmdname}{argsummary}");
};
$cmd{'contrib'} = {
'handler' => \&contrib_edit,
'des' => "Adds/Acks Contributions.",
'argsummary' => '<command> [<username>/<ackid>] [<contribtype>] [<msg>] [<url>]',
'args' => [
'command' => "Either 'ack' to ack a contrib, 'add' to add a contrib.",
'username' => "The username for the contribution to add.",
'ackid' => "Id of the contribution to ack.",
'contribtype' => "'code' for Coding, 'doc' for documentation, 'creative' for artwork, 'biz' for buisness, 'other' for other",
'msg' => "description of what they did",
'url' => "[optional] url with more information",
],
};
$cmd{'payment_credit'} = {
'handler' => \&payment_credit,
'privs' => [qw(moneyenter)],
'des' => "Give payment credit to an existing user from either an account code or a payid. Marks the associated code as then used by that username.",
'argsummary' => '<thing> <id> to <username>',
'args' => [
'thing' => "Either 'code' or 'payment'.",
'id' => "If code, the code; if payment, the payid.",
'username' => "The username to give the time to.",
],
};
$cmd{'unpay'} = {
'handler' => \&unpay,
'privs' => [qw(moneyenter)],
'des' => "Takes away paid time from a user for a bogus/accidental payment, while also changing the payment record to 0 months and 0 dollars, and making a note in the statushistory table why the payment was removed, and what the payment's old values were.",
'argsummary' => '<user> <payid> <reason>',
'args' => [
'user' => 'Username of person to remove time from. Or, use "!" (without the quotes) for no user, when you just want to zero out a payment and/or its associated account code.',
'payid' => 'Payment ID# to delete',
'reason' => 'The reason the payment is being deleted. Not sent to user, only put in user\'s statushistory.',
],
};
$cmd{'inventory'} = {
'handler' => \&inventory,
'privs' => [qw(moneyenter shipping)],
'des' => "View or modify inventory.",
'argsummary' => '<command> [<item> <value>]',
'args' => [
'command' => 'Either "show" to show current inventory, "add" to add &lt;value&gt; units of &lt;item&gt;, or "remove" to remove &lt;value&gt; units of &lt;item&gt;, or "price" to change the price of &lt;item&gt; to &lt;value&gt;.',
'item' => 'Inventory code.',
'value' => 'Number to change inventory by, or new cost.',
],
};
sub unpay
{
my ($dbh, $remote, $args, $out) = @_;
my $user = LJ::canonical_username($args->[1]);
if ($args->[1] eq "!") { $user = "!"; }
my $payid = $args->[2];
my $reason = $args->[3];
my $err = sub {
my $err = shift;
my $lock = shift;
push @$out, [ "error", $err ];
if ($lock) {
my $qlock = $dbh->quote($lock);
$dbh->do("SELECT RELEASE_LOCK($qlock)");
}
return 0;
};
return $err->("$remote->{'user'}, you are not authorized to use this command.")
unless (LJ::check_priv($dbh, $remote, "moneyenter"));
return $err->("No reason given")
unless $reason;
return $err->("Invalid or missing username argument")
unless $user;
return $err->("Invalid payid format (not a number")
unless ($payid =~ /^\d+$/);
my $p = $dbh->selectrow_hashref("SELECT * FROM payments WHERE payid=$payid");
my $u;
if ($user eq "!") {
$u = {
'userid' => 0,
};
} else {
$u = LJ::load_user($user, "force");
}
return $err->("The unpay command doesn't work with the new payment system")
if $p->{'forwhat'} eq "cart";
return $err->("Payment not found")
unless $p;
return $err->("User not found")
unless $u;
return $err->("That payment doesn't belong to that user")
unless ($p->{'userid'} == $u->{'userid'});
return $err->("That payment has no months or money associated with it.")
unless ($p->{'amount'} ne "0.00" || $p->{'months'});
my $lockname = "unpay-$user-$payid";
my $status;
# start pseudo-transaction
$status = $dbh->selectrow_array("SELECT GET_LOCK('$lockname',10)");
return $err->("Failed to get lock on necessary tables to do unpay, try again.")
unless $status;
my $months = $p->{'months'}+0;
my $logtext = ("Removing payid \#$payid ($p->{'months'} months & $p->{'amount'} ".
"dollars). Reason: " . $reason);
# add to status history
if ($u->{'userid'}) {
$status = LJ::statushistory_add($dbh, $u->{'userid'}, $remote->{'userid'},
"unpay", $logtext);
} else {
$dbh->do("UPDATE payments SET notes=concat(notes, ?) WHERE payid=$payid", undef,
"\nUNPAY: $logtext");
}
$err->("Couldn't append statushistory table, aborting", $lockname)
unless $status;
# update payment record
$dbh->do("UPDATE payments SET months=0, amount=0, used='Y' WHERE payid=$payid");
$err->("Couldn't update payment record, aborting", $lockname)
if $dbh->err;
# subtract time from user
$dbh->do("UPDATE paiduser SET paiduntil=DATE_SUB(paiduntil, INTERVAL $months MONTH) WHERE userid=$p->{'userid'}");
$err->("Couldn't subtract time from user, aborting", $lockname)
if $dbh->err;
# end transaction
$dbh->do("SELECT RELEASE_LOCK('$lockname')");
push @$out, [ "", "Done." ];
}
sub payment_credit
{
my ($dbh, $remote, $args, $out) = @_;
my $thing = $args->[1];
my $id = $args->[2];
my $to = $args->[3];
my $username = $args->[4];
unless ($remote->{'priv'}->{'moneyenter'}) {
push @$out, [ "error", "$remote->{'user'}, you are not authorized to use this command." ];
return 0;
}
unless ($thing eq "code" || $thing eq "payment") {
push @$out, [ "error", "Invalid first argument." ];
return 0;
}
unless ($to eq "to") {
push @$out, [ "error", "Third argument isn't 'to'" ];
return 0;
}
my $u = LJ::load_user($username, "force");
unless ($u) {
push @$out, [ "error", "User doesn't exist." ];
return 0;
}
my $payid;
my $acid;
if ($thing eq "code")
{
my $code = $id;
($acid, undef) = LJ::acct_code_decode($code);
my $err;
unless (LJ::acct_code_check($dbh, $code, \$err)) {
push @$out, [ "error", "Bad code: $err." ];
return 0;
}
my $sth = $dbh->prepare("SELECT payid FROM acctpay WHERE acid=$acid");
$sth->execute;
($payid) = $sth->fetchrow_array;
unless ($payid) {
push @$out, [ "error", "This code doesn't have an associated payment." ];
return 0;
}
}
if ($thing eq "payment") {
$payid = $id+0;
my $sth = $dbh->prepare("SELECT acid FROM acctpay WHERE payid=$payid");
$sth->execute;
($acid) = $sth->fetchrow_array;
unless ($acid) {
push @$out, [ "error", "This payment doesn't have an associated code." ];
return 0;
}
}
my $sth = $dbh->prepare("SELECT * FROM payments WHERE payid=$payid");
$sth->execute;
my $p = $sth->fetchrow_hashref;
unless ($p) {
push @$out, [ "error", "Payment not found." ];
return 0;
}
unless ($p->{'userid'} == 0) {
push @$out, [ "error", "Payment already assigned... not open." ];
return 0;
}
# guess everything's good.
$dbh->do("UPDATE payments SET userid=$u->{'userid'} WHERE payid=$payid");
$dbh->do("UPDATE acctcode SET rcptid=$u->{'userid'} WHERE acid=$acid");
push @$out, [ "", "Done." ];
}
sub contrib_edit
{
my ($dbh, $remote, $args, $out) = @_;
my $err = sub { push @$out, [ "error", $_[0] ]; 0; };
return $err->("This command has 2 or more arguments") unless @$args >= 2;
return $err->("Must be logged in.") unless $remote;
my $cmd = $args->[1];
if ($cmd eq "add")
{
return $err->("Not enough arguments for add.")
unless @$args == 5 or @$args == 6;
my $user = $args->[2];
my $cat = $args->[3];
my $des = $args->[4];
my $url = $args->[5];
my $u = LJ::load_user($user, "force");
return $err->("Invalid user $user") unless $u;
my $userid = $u->{'userid'};
return $err->("type can only be: 'code','doc','creative','biz','other'") unless
($cat eq "code" or $cat eq "doc" or $cat eq "creative" or
$cat eq "biz" or $cat eq "other");
$dbh->do("INSERT INTO contributed (userid, cat, des, url, dateadd) ".
"VALUES (?,?,?,?,NOW())", undef, $userid, $cat, $des, $url);
return $err->("error adding contribution") if $dbh->err;
} elsif ($cmd eq "ack") {
return $err->("Not enough arguments for ack.") unless @$args == 3;
return $err->("You have to be an acknowledged contributor before you can acknowledge other people.")
unless LJ::Contrib::is_acked($remote->{'userid'});
my $coid = $args->[2]+0;
LJ::Contrib::ack($coid, $remote->{'userid'});
} else {
return $err->("Unknown Command Type");
}
push @$out, [ '', "Success." ];
return 1;
}
sub inventory
{
my ($dbh, $remote, $args, $out) = @_;
my $cmd = $args->[1];
my $item = $args->[2];
my $val = $args->[3];
unless ($remote->{'priv'}->{'moneyenter'} || $remote->{'priv'}->{'shipping'}) {
push @$out, [ "error", "$remote->{'user'}, you are not authorized to use this command." ];
return 0;
}
unless ($cmd =~ /show|add|remove|price/) {
push @$out, [ "error", "Invalid inventory command." ];
return 0;
}
if ($cmd eq "show") {
my $sth = $dbh->prepare("SELECT item, subitem, qty, avail, price FROM inventory ".
"ORDER BY item, subitem");
$sth->execute;
push @$out, [ '', "qty avl price item" ];
push @$out, [ '', "==== ==== ====== =============================" ];
while ($_ = $sth->fetchrow_hashref) {
push @$out, [ '', sprintf("%4d %4d \$%5.02f %s-%s",
$_->{'qty'}, $_->{'avail'}, $_->{'price'},
$_->{'item'}, $_->{'subitem'}) ];
}
return 1;
}
my $subitem;
unless ($item =~ /^(\w+?)-(.+)$/) {
push @$out, [ "error", "Invalid item format." ];
return 0;
}
($item, $subitem) = ($1, $2);
if ($cmd eq "add" || $cmd eq "remove") {
my $dir = $cmd eq "add" ? "+" : "-";
my $ro = $dbh->do("UPDATE inventory SET qty=qty $dir ?, avail=avail $dir ? ".
"WHERE item=? AND subitem=?",
undef, $val, $val, $item, $subitem);
if ($ro > 0) {
push @$out, [ "", "$item-$subitem changed." ];
return 1;
}
push @$out, [ "error", "No change made." ];
return 0;
}
if ($cmd eq "price") {
my $price = $val;
$price =~ s/\$//;
unless ($price =~ /^(\d+)(\.\d\d)?$/ && $1) {
push @$out, [ "error", "Invalid price." ];
return 0
}
my $ro = $dbh->do("UPDATE inventory SET price=? ".
"WHERE item=? AND subitem=?",
undef, $price, $item, $subitem);
if ($ro > 0) {
push @$out, [ "", "$item-$subitem price changed." ];
return 1;
}
push @$out, [ "error", "No change made." ];
return 0;
}
return 0;
}
$cmd{'allow_pay'} =
{
des => "Permit or deny a user's ability to pay.",
privs => [qw(moneyenter)],
argsummary => '<action> <usernames>',
args => [
action => "'permit', or 'deny'",
username => "Username to allow to pay (with permit) or block payments (with deny)",
],
handler => sub {
my ($dbh, $remote, $args, $out) = @_;
return $fail->($out, "Not logged in.") unless $remote;
return $fail->($out, "You don't have privileges needed to run this command.")
unless $remote->{'priv'}->{'moneyenter'};
# check syntax and parse out some information
my $myname = shift @$args;
my $action = shift @$args or return $usage->($out, $myname);
my $user = shift @$args or return $usage->($out, $myname);
my $act = $action eq 'permit' ? 'Y' : 'N';
return $usage->($out, $myname) unless $args;
return $usage->($out, $myname) unless $action =~ /^(permit|deny)$/;
return $usage->($out, $myname) unless $user;
# make changes and revoke
my $userid = LJ::get_userid($dbh, $user);
return $fail->($out, "Skipping invalid username: '$_'") unless $userid;
LJ::set_userprop($userid, 'allow_pay', $act)
or return $fail->($out, "Error setting 'allow_pay' userprop. Database Unavailable?");
# log to statushistory
LJ::statushistory_add($userid, $remote->{userid}, "allow_pay", ucfirst($action) . "ing payments");
$success->($out, ucfirst($action) . "ing payment for user $user");
return 1;
}
};
$cmd{'got_assignment'} =
{
des => "Mark a user as sending in the assignment agreement paperwork for the bazaar.",
privs => [qw(moneyenter)],
argsummary => '<user>',
args => [
user => "Username who sent in the assignment agreement.",
],
handler => sub {
my ($dbh, $remote, $args, $out) = @_;
return $fail->($out, "Not logged in.") unless $remote;
return $fail->($out, "You don't have privileges needed to run this command.")
unless $remote->{'priv'}->{'moneyenter'};
# check syntax and parse out some information
my $myname = shift @$args;
my $user = shift @$args or return $usage->($out, $myname);
my $u = LJ::load_user($user, "force");
return $fail->($out, "User not found") unless $u;
LJ::set_userprop($u, "legal_assignagree", 1)
or return $fail->($out, "Error setting userprop. Database unavailable?");
$success->($out, "Assignment agreement flag set for $u->{'user'}");
return 1;
}
};
$cmd{'bazaar_pay'} =
{
des => "Subtract money from a user's bazaar balance.",
privs => [qw(moneyenter)],
argsummary => '<user> <amt>',
args => [
user => "Username to subtract balance from.",
amt => "Amount to subtract.",
],
handler => sub {
my ($dbh, $remote, $args, $out) = @_;
return $fail->($out, "Not logged in.") unless $remote;
return $fail->($out, "You don't have privileges needed to run this command.")
unless $remote->{'priv'}->{'moneyenter'};
# check syntax and parse out some information
my $myname = shift @$args;
my $user = shift @$args;
my $amt = shift @$args;
unless ($user ne "" && $amt =~ /^\d+(\.\d\d)?$/) {
return $usage->($out, $myname);
}
my $u = LJ::load_user($user, "force");
return $fail->($out, "User not found") unless $u;
LJ::load_user_props($u, "legal_assignagree");
unless ($u->{'legal_assignagree'}) {
return $fail->($out, "Error: no assignment agreement from $u->{'user'}. Use the 'got_assignment' command if you have it.");
}
if (LJ::Pay::bazaar_remove_balance($u, $amt)) {
LJ::statushistory_add($u->{'userid'}, $remote->{'userid'}, "bzrbaldecr", "Removing \$$amt");
return $success->($out, "Success.");
}
return $fail->($out, "Error: balance wasn't large enough?");
}
};
$cmd{'bazaar_status'} =
{
des => "Show who's owed how much for the bazaar.",
privs => [qw(moneyenter)],
argsummary => '',
args => [ ],
handler => sub {
my ($dbh, $remote, $args, $out) = @_;
return $fail->($out, "Not logged in.") unless $remote;
return $fail->($out, "You don't have privileges needed to run this command.")
unless $remote->{'priv'}->{'moneyenter'};
LJ::Pay::bazaar_do_expirations();
my $sth = $dbh->prepare("SELECT u.user, SUM(b.owed) FROM user u, bzrbalance b ".
"WHERE u.userid=b.userid AND b.owed > 0 GROUP BY 1");
$sth->execute;
while (my ($user, $sum) = $sth->fetchrow_array) {
push @$out, [ "", sprintf("%-20s = \$%7.02f", $user, $sum) ];
}
return $success->($out, "[end]");
}
};
$cmd{'rename_redir'} =
{
des => "Change redirection option of a previously done redirect",
privs => [qw(moneyenter)],
argsummary => '<action> <from_username> <to_username>',
args => [
action => "'add' to do redirections, or 'remove' if redirections should not be done",
from_username => "Source journal which was renamed",
to_username => "Destination journal to which from_username was renamed"
],
handler => sub {
my ($dbh, $remote, $args, $out) = @_;
return $fail->($out, "Not logged in.") unless $remote;
return $fail->($out, "You don't have privileges needed to run this command.")
unless $remote->{'priv'}->{'moneyenter'};
shift @$args; # remove command name
my ($action, $from_username, $to_username) = @$args;
return $fail->($out, "Invalid action: '$action'")
unless $action eq 'add' || $action eq 'remove';
my $from_user = LJ::load_user($from_username);
return $fail->($out, "Invalid from_username")
unless $from_user;
$from_username = $from_user->{'user'};
my $to_user = LJ::load_user($to_username);
return $fail->($out, "Invalid to_username")
unless $to_user;
$to_username = $to_user->{'user'};
return $fail->($out, "'$from_username' has already been marked as expunged'")
if $from_user->{'statusvis'} eq 'X';
return $fail->($out, "'$from_username' was never renamed to '$to_username'")
unless $dbh->selectrow_array("SELECT COUNT(*) FROM renames " .
"WHERE fromuser=? AND touser=?",
undef, $from_username, $to_username);
LJ::load_user_props($from_user, 'renamedto');
# create a redirection link
if ($action eq 'add') {
return $fail->($out, "'$from_username' already redirects to '$to_username'")
if $from_user->{'renamedto'} eq $to_username && $from_user->{'statusvis'} eq 'R';
return $fail->($out, "'$from_username' redirects to another journal?")
if $from_user->{'statusvis'} eq 'R' && $from_user->{'renamedto'} &&
$from_user->{'renamedto'} ne $to_username;
# set renamedto prop
LJ::set_userprop($from_user, "renamedto", $to_username)
or return $fail->($out, "Error setting userprop. Database unavailable?");
# update user, undelete (checked to see if already expunged earlier)
LJ::update_user($from_user,
{ raw => "journaltype='R', statusvis='R', statusvisdate=NOW()" });
# update email aliases if applicable
if (LJ::get_cap($from_user, "useremail")) {
$dbh->do("INSERT INTO email_aliases VALUES (?,?)", undef,
"$to_username\@$LJ::USER_DOMAIN", $to_user->{'email'});
}
return $success->($out, "Redirection added for $from_username => $to_username rename action");
}
# remove a redirection link
if ($action eq 'remove') {
return $fail->($out, "'$from_username' does not redirect to '$to_username'")
unless $from_user->{'renamedto'} eq $to_username &&
$from_user->{'statusvis'} eq 'R';
# delete renamedto prop
LJ::set_userprop($from_user, "renamedto", undef)
or return $fail->($out, "Error setting userprop. Database unavailable?");
# update user, set deleted
LJ::update_user($from_user,
{ raw => "journaltype='R', statusvis='D', statusvisdate=NOW()" });
# update email aliases if applicable
$dbh->do("DELETE FROM email_aliases WHERE rcpt=?",
undef, "$from_username\@$LJ::USER_DOMAIN");
return $success->($out, "Redirection removed for $from_username => $to_username rename action");
}
}
};
$cmd{'rename_show'} =
{
des => "View information about a rename.",
privs => [qw(moneyenter)],
argsummary => '<value>',
args => [
'value' => "A hex or decimal tokenid, a full token string, or the username of a user who was renamed (source user)."
],
handler => sub {
my ($dbh, $remote, $args, $out) = @_;
return $fail->($out, "Not logged in.") unless $remote;
return $fail->($out, "You don't have privileges needed to run this command.")
unless $remote->{'priv'}->{'moneyenter'};
shift @$args; # remove command name
my $value = shift @$args;
return $fail->($out, "You must enter a value")
unless $value;
my @ren;
my $hashref_array = sub {
return values %{
$dbh->selectall_hashref(shift(), 'renid', undef, @_) || {}
}
};
# they probably have this form of the token
if ($value =~ /^([0-9a-f]{6})(\w{10})$/) {
push @ren, $hashref_array->("SELECT * FROM renames WHERE renid=? AND token=?", hex $1, $2);
# or maybe they have the tokenid?
} elsif ($value =~ /^([0-9a-f]{1,6})/) {
# try decimal, hex tokenids (user could enter either)
push @ren, $hashref_array->("SELECT * FROM renames WHERE renid=? OR renid=?", $1, hex $1);
# perhaps they have the token itself?
} elsif ($value =~ /^(\w{10})$/) {
push @ren, $hashref_array->("SELECT * FROM renames WHERE token=?", $1);
# explicitly disallow special tokens ([movedaway], [manual], etc)
# Note: "----------" is also a special token, but it's a valid username
# so we allow searching for it,
} elsif ($value =~ /^\[\w+\]$/) {
return $fail->($out, "Cannot search for special tokens");
}
# if no ren, then maybe they gave a username
push @ren, $hashref_array->("SELECT * FROM renames WHERE fromuser=?",
LJ::canonical_username($value))
unless @ren;
return $fail->($out, "Could not find a matching rename.")
unless @ren;
foreach my $ren (@ren) {
push @$out, map { [ '', "$_: $ren->{$_}" ] } sort keys %$ren;
push @$out, [ '', '' ];
}
return $success->($out, "[end]");
}
};
$cmd{'rename_reset'} =
{
des => "Lets account admins modify friends properties if selected incorrectly during a rename.",
privs => [qw(moneyenter)],
argsummary => '<mode> <user>',
args => [
'mode' => "'friends' to reset friends, 'friendofs' to reset friends-ofs.",
'user' => "The username whose friends list should be cleared."
],
handler => sub {
my ($dbh, $remote, $args, $out) = @_;
return $fail->($out, "Not logged in.") unless $remote;
return $fail->($out, "You don't have privileges needed to run this command.")
unless $remote->{'priv'}->{'moneyenter'};
shift @$args; # remove command name
my $mode = shift @$args;
my $user = shift @$args;
return $fail->($out, "Invalid mode, valid modes are 'friends' and 'friendofs'")
unless $mode eq 'friends' || $mode eq 'friendofs';
return $fail->($out, "You must enter a username")
unless $user;
my $u = LJ::load_user($user);
return $fail->($out, "Invalid username")
unless $u;
if ($mode eq 'friends') {
# TAG:FR:console:rename_reset:clear_friends
# clear the given user's friends
# delete existing friends
my $friends = LJ::get_friends($cid, undef, undef, 'force') || {};
if (LJ::remove_friend($cid, [ keys %$friends ])) {
return $success->($out, "Success, friends modified.");
}
# some failure?
return $fail->($out, "Error modifying friends for user: '$user'");
}
if ($mode eq 'friendofs') {
# TAG:FR:console:rename_reset:clear_friendofs
# who lists this user as a friend?
my $ids = $dbh->selectcol_arrayref("SELECT userid FROM friends WHERE friendid=?",
undef, $u->{'userid'}) || [];
# delete friend edges with this user as the target
if ($dbh->do("DELETE FROM friends WHERE friendid=?", undef, $u->{'userid'})) {
# clear memcache for all friend-ofs
LJ::memcache_kill($_, "friends") foreach @$ids;
return $success->($out, "Success, friend-ofs modified.");
}
# some failure?
return $fail->($out, "Error modifying friend-ofs for user: '$user'");
}
}
};
$cmd{'fraud_watch'} =
{
des => "Set or unset the fraud_watch userprop for a given user",
privs => [qw(moneyenter)],
argsummary => '<action> <username>',
args => [
username => "Username who should have faud_watch set/unset",
action => "Optional. Either 'add' or 'remove' to set/unset the watch respectively. Defaults to 'add'.",
],
handler => sub {
my ($dbh, $remote, $args, $out) = @_;
return $fail->($out, "Not logged in.") unless $remote;
return $fail->($out, "You don't have privileges needed to run this command.")
unless $remote->{'priv'}->{'moneyenter'};
shift @$args; # remove command name
my ($action, $user) = @$args;
return $fail->($out, "Invalid action: '$action'")
unless $action eq 'add' || $action eq 'remove';
my $u = LJ::load_user($user);
return $fail->($out, "Invalid username: $user")
unless $u;
my $propval = $action eq 'add' ? 1 : 0;
my $verb = $propval ? 'added' : 'removed';
LJ::load_user_props($u, 'fraud_watch');
return $fail->($out, "Fraud watch already $verb, nothing to do. [$u->{fraud_watch}]")
if $u->{fraud_watch} == $propval;
# set userprop
LJ::set_userprop($u, "fraud_watch", $propval)
or return $fail->($out, "Error setting 'fraud_watch' userprop. Database unavailable?");
# log to statushistory
LJ::statushistory_add($u->{userid}, $remote->{userid}, 'fraud_watch', "fraud watch $verb");
return $success->($out, "Fraud watch $verb for $u->{user}");
}
};
$cmd{'coupon_revoke'} =
{
des => "Revoke an unused coupon that was given out by the system (for a promo, etc)",
privs => [qw(moneyenter)],
argsummary => '<username> <coupon_token>',
args => [
username => "Username that owns the coupon to be revoked.",
coupon => "Coupon token. A full coupon token string to be revoked.",
],
handler => sub {
my ($dbh, $remote, $args, $out) = @_;
return $fail->($out, "Not logged in.") unless $remote;
return $fail->($out, "You don't have privileges needed to run this command.")
unless $remote->{'priv'}->{'moneyenter'};
shift @$args; # remove command name
my ($user, $coupon) = @$args;
my $u = LJ::load_user($user);
return $fail->($out, "Invalid username: $user")
unless $u;
return $fail->($out, "Invalid coupon format")
unless $coupon =~ /^(\d+)-(.+)$/;
my ($cpid, $auth) = ($1, $2);
my $cp = $dbh->selectrow_hashref
("SELECT * FROM coupon WHERE cpid=? AND auth=?",
undef, $cpid, $auth);
return $fail->($out, "Invalid coupon, already revoked?") unless $cp;
return $fail->($out, "Coupon owner does not match '$user'")
unless $cp->{rcptid} == $u->{userid};
return $fail->($out, "This command can only revoke coupons generated automatically " .
"by the system.")
unless $cp->{ppayid} == 0;
return $fail->($out, "This coupon has already been used in a cart.")
unless $cp->{payid} == 0;
$dbh->do("DELETE FROM coupon WHERE cpid=? AND auth=? AND rcptid=?",
undef, $cpid, $auth, $u->{userid});
return $fail->($out, "Database Error: " . $dbh->errstr) if $dbh->err;
# log to statushistory
LJ::statushistory_add
($u->{userid}, $remote->{userid}, 'coupon_revoke', "Coupon revoked: $coupon");
return $success->($out, "Coupon revoked: $coupon ($u->{user})");
}
};
1;

View File

@@ -0,0 +1,10 @@
need to install on clients:
apt-get install libcrypt-cracklib-perl
to make the dictionary indexes, need to do:
# apt-get install cracklib-runtime wenglish
$ /usr/sbin/crack_mkdict /usr/share/dict/words | /usr/sbin/crack_packer $LJHOME/cgi-bin/cracklib/dict

View File

@@ -0,0 +1,48 @@
#!/usr/bin/perl
#
# Stores all local crumbs and adds to the crumbs hash
%LJ::CRUMBS_LOCAL = (
'about' => ['About LiveJournal', '/site/about.bml', 'home'],
'abusereport' => ['Report Abuse', '/abuse/report.bml', 'support'],
'acctfeatures' => ['Features By Account Type', '/site/accounts.bml', 'about'],
'advsearch' => ['Advanced', '/directorysearch.bml', 'search'],
'banners' => ['Advertising Banners', '/banners.bml', 'home'],
'code' => ['LiveJournal Code', '/code/index.bml', 'about'],
'contributors' => ['Contributors', '/site/contributors.bml', 'press'],
'coppa' => ['COPPA', '/legal/coppa.bml', 'legal'],
'dmca' => ['DMCA Information', '/legal/dmca.bml', 'legal'],
'download' => ['Download a Client', '/download/index.bml', 'about'],
'filemanager' => ['File Manager', '/manage/files.bml', 'manage'],
'goat' => ['About Frank', '/site/goat.bml', 'home'],
'guidingprinciples' => ['Our Guiding Principles', '/legal/principles.bml', 'about'],
'itsfree' => ['It\'s Free?', '/site/free.bml', 'paidaccounts'],
'legal' => ['Legal Information', '/legal/index.bml', 'home'],
'ljhome' => ['Home', 'http://www.livejournal.com/', ''],
'paidaccounts' => ['Paid Accounts', '/paidaccounts/index.bml', 'about'],
'paidacctstatus' => ['Paid Account Status', '/paidaccounts/status.bml', 'paidaccounts'],
'press' => ['LiveJournal Press Area', '/press/index.bml', 'about'],
'pressarticles' => ['LiveJournal in the Press', '/press/articles.bml', 'press'],
'privacy' => ['Privacy Policy', '/legal/privacy.bml', 'legal'],
'search' => ['Search', '/site/search.bml', 'home'],
'searchinterests' => ['By Interest', '/interests.bml', 'search'],
'searchregion' => ['By Region', '/directory.bml', 'search'],
'securechangepass' => ['Change Password', '/changepassword.bml', 'securemanage'],
'securecreatejournal' => ['Create Journal', '/create.bml', 'ljhome'],
'securelogin' => ['Login', '/login.bml', 'ljhome'],
'securemanage' => ['Manage Accounts', 'http://www.livejournal.com/manage/', 'ljhome'],
'singles' => ['LiveJournal Singles', '/singles/', 'home'],
'singlesopts' => ['Modify Availability', '/singles/mod.bml', 'singles'],
'singlessearch' => ['Search for Singles', '/singles/search.bml', 'singles'],
'sitemap' => ['Site Map', '/site/index.bml', 'home'],
'sizechart' => ['Sizing Chart', '/store/sizechart.bml', 'store'],
'staff' => ['Senior Staff', '/press/staff.bml', 'press'],
'stats' => ['Statistics', '/stats.bml', 'press'],
'store' => ['LiveJournal Store', '/store/', 'home'],
'storeitem' => ['View Item Detail', '', 'store'],
'suggestions' => ['Suggestions Generator', '/suggestions/generator.bml', 'suggview'],
'suggview' => ['Suggestions', '/suggestions/index.bml', 'home'],
'tos' => ['Terms of Service', '/legal/tos.bml', 'legal'],
);
1;

1604
ljcom/cgi-bin/ljcom.pl Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,6 @@
#!/usr/bin/perl
#
require "$ENV{'LJHOME'}/cgi-bin/ljcom.pl";
1;

View File

@@ -0,0 +1,41 @@
#!/usr/bin/perl
#
use strict;
use lib "$ENV{'LJHOME'}/cgi-bin";
use Apache;
use Apache::LiveJournal;
Apache->httpd_conf("DocumentRoot $LJ::HOME/ssldocs");
Apache->httpd_conf("ServerAdmin $LJ::ADMIN_EMAIL")
if $LJ::ADMIN_EMAIL;
Apache->httpd_conf(qq{
<IfModule mod_userdir.c>
UserDir disabled
</IfModule>
PerlInitHandler +Apache::LiveJournal
PerlFixupHandler +Apache::CompressClientFixup
DirectoryIndex index.html index.bml
});
unless ($LJ::SERVER_TOTALLY_DOWN)
{
Apache->httpd_conf(qq{
# BML support:
PerlModule Apache::BML
<Files ~ "\\.bml\$">
SetHandler perl-script
PerlHandler Apache::BML
</Files>
# User-friendly error messages
ErrorDocument 404 /404-error.html
ErrorDocument 500 /500-error.html
});
}
1;

View File

@@ -0,0 +1,23 @@
#!/usr/bin/perl
#
# site-local version of modperl_subs.pl
package LJ::ModPerl;
use strict;
# pull in a lot of useful stuff before we fork children
use lib "$ENV{'LJHOME'}/cgi-bin";
use XMLRPC::Lite; # for cmdbuf:pay_fb_xmlrpc hook
require "phonepost.pl";
require "paylib.pl";
$LJ::OPTMOD_CRACKLIB = eval "use Crypt::Cracklib qw(); 1;";
$Crypt::Cracklib::DICT = "$ENV{'LJHOME'}/cgi-bin/cracklib/dict";
$LJ::OPTMOD_GEOIP = eval "use Geo::IP::PurePerl (); 1;";
1;

2946
ljcom/cgi-bin/paylib.pl Normal file

File diff suppressed because it is too large Load Diff

321
ljcom/cgi-bin/phonepost.pl Normal file
View File

@@ -0,0 +1,321 @@
#!/usr/bin/perl
# vim: set ts=4 sw=4 et :
# some variable names:
# - phonepostid, bid, blobid: all refer to a blob id.
# - dppid: display phonepost id; comparable to a ditemid, but for a phone post.
use strict;
use lib "$ENV{'LJHOME'}/cgi-bin";
use LJ::Blob;
package LJ::PhonePost;
my $datatypes = {
0 => { ext => 'mp3', mime => 'audio/mp3' },
1 => { ext => 'ogg', mime => 'application/ogg' },
2 => { ext => 'wav', mime => 'audio/wav' },
};
sub may_transcribe {
my ($u, $remote) = @_;
return 0 if $remote && $remote->{journaltype} ne 'P';
return 1 if $remote && $remote->{userid} == $u->{userid};
LJ::load_user_props($u, 'pp_transallow');
return 0 if $u->{pp_transallow} == -1;
my $groupmask = LJ::get_groupmask($u, $remote);
return 1 if ! $u->{pp_transallow} && $groupmask;
return ($groupmask & (1 << $u->{pp_transallow})) ? 1 : 0;
}
sub get_phonepost_entry {
my ($u, $bid) = @_;
my ($ppe, $memkey);
$memkey = [$u->{userid}, "ppe:$u->{userid}:$bid"];
$ppe = LJ::MemCache::get($memkey);
return $ppe if $ppe;
my $dbcr = LJ::get_cluster_def_reader($u);
$ppe = $dbcr->selectrow_hashref(qq{
SELECT ppe.jitemid, ppe.posttime, ppe.anum,
ppe.filetype, ub.length, ppe.lengthsecs, ppe.location
FROM phonepostentry ppe, userblob ub
WHERE ub.journalid=? AND ppe.userid=ub.journalid
AND ub.domain=? AND ub.blobid=? AND ppe.blobid=ub.blobid
}, undef, $u->{'userid'}, LJ::get_blob_domainid("phonepost"), $bid);
LJ::MemCache::set($memkey, $ppe || 0);
return $ppe;
}
sub apache_content {
my ($r, $u, $dppid) = @_;
my $bid = $dppid >> 8;
my $ppe = get_phonepost_entry($u, $bid);
return 404 unless $ppe && $ppe->{jitemid} && $ppe->{anum} == $dppid % 256;
# check security of item
my $logrow = LJ::get_log2_row($u, $ppe->{jitemid});
return 404 unless $logrow;
if ($u->{statusvis} eq 'S' || $logrow->{security} ne "public") {
# get the remote, ignoring IP, since the request is coming
# from Akamai/Speedera/etc and the IP won't match
my $remote = LJ::get_remote({ ignore_ip => 1 });
my %GET = $r->args;
my $viewall = 0;
my $viewsome = 0;
if ($remote && $GET{viewall} && LJ::check_priv($remote, "canview")) {
LJ::statushistory_add($u->{'userid'}, $remote->{'userid'},
"viewall", "phonepost: $u->{user}, itemid: $ppe->{jitemid}, statusvis: $u->{'statusvis'}");
$viewall = LJ::check_priv($remote, 'canview', '*');
$viewsome = $viewall || LJ::check_priv($remote, 'canview', 'suspended');
}
unless ($viewall || $viewsome && $logrow->{security} eq 'public') {
return 403 unless LJ::can_view($remote, $logrow);
}
}
# future: if length is NULL, then it's an external reference and we redirect
$r->header_out("Cache-Control", "must-revalidate, private");
$r->header_out("Content-Length", $ppe->{length});
$r->content_type( $datatypes->{ $ppe->{filetype} }->{mime} );
# handle IMS requests
my $last_mod = LJ::time_to_http($ppe->{posttime});
if (my $ims = $r->header_in("If-Modified-Since")) {
return 304 if $ims eq $last_mod;
}
$r->header_out("Last-Modified", $last_mod);
if ($r->header_only) {
$r->send_http_header();
return 200;
}
my $buffer;
if ($ppe->{location} eq 'mogile') {
# Mogile
if ( !$LJ::REPROXY_DISABLE{phoneposts} &&
$r->header_in('X-Proxy-Capabilities') &&
$r->header_in('X-Proxy-Capabilities') =~ /\breproxy-file\b/i )
{
my @paths = LJ::mogclient()->get_paths( "pp:$u->{userid}:$bid", 1 );
# reproxy url
if ($paths[0] =~ m/^http:/) {
$r->header_out('X-REPROXY-URL', join(' ', @paths));
}
# reproxy file
else {
$r->header_out('X-REPROXY-FILE', $paths[0]);
}
$r->send_http_header();
}
else {
$buffer = LJ::mogclient()->get_file_data("pp:$u->{userid}:$bid");
$r->send_http_header();
return 500 unless $buffer && ref $buffer;
$r->print($$buffer);
}
}
else {
# BlobServer
$r->send_http_header();
my $ret = LJ::Blob::get_stream($u, 'phonepost',
$datatypes->{ $ppe->{filetype} }->{ext}, $bid, sub {
$buffer .= $_[0];
if (length($buffer) > 50_000) {
$r->print($buffer);
undef $buffer;
}
});
$r->print($buffer) if length($buffer);
return 500 unless $ret;
}
return 200;
}
# if $u_embed and $ditemid are given, they represent an entry
# in which a phonepost tag has been embedded.
sub make_link {
my ($remote, $uuid, $phonepostid, $mode, $u_embed, $ditemid) = @_;
$phonepostid += 0;
# mode can either be 'notrans', 'bare', or 'rss'
$mode = "notrans" if $mode && $mode !~ /bare|rss/;
my $u = ref $uuid ? $uuid : LJ::load_userid($uuid);
return $mode eq 'rss' ? "" : "<b>[Invalid user]</b>" unless $u;
my $userid = $u->{'userid'};
my $ppe = get_phonepost_entry($u, $phonepostid);
return $mode eq 'rss' ? "" : "<b>[Invalid audio link]</b>" unless $ppe;
if ($u_embed && $ditemid) {
# have to check whether the link is embeddable in this entry
if ($u_embed->{'userid'} == $userid &&
$ditemid>>8 == $ppe->{'jitemid'}) {
# it's the original entry, we're ok
} else {
my $accdenied = "<b>[Access to audio link denied]</b>";
# log2 row in which the tag is embedded
my $row = LJ::get_log2_row($u_embed, $ditemid >> 8);
# the original log2 row of this tag
my $row_orig = LJ::get_log2_row($u, $ppe->{'jitemid'});
return $mode eq 'rss' ? "" : $accdenied unless $row && $row_orig;
if ($row_orig->{'security'} eq "public" &&
$row->{'posterid'} == $userid &&
$u_embed->{'userid'} != $userid) {
# it's public and moved by the same
# user to a different journal, we're okay
} else {
return $mode eq 'rss' ? "" : $accdenied;
}
}
}
my $link;
my $dppid = ($phonepostid << 8) + $ppe->{anum};
my $ext = $datatypes->{ $ppe->{filetype} }->{ext};
my $path = LJ::run_hook("url_phonepost", $u, $dppid, $ext) ||
LJ::journal_base($u) . "/data/phonepost/$dppid.$ext";
# make link and just return that if in bare mode
$link = $ppe->{location} eq 'none' ?
"<img src='$LJ::IMGPREFIX/phonepost2.gif' alt='' width='35' height='33' />" :
"<a href='$path'><img src='$LJ::IMGPREFIX/phonepost2.gif' alt='' " .
"width='35' height='33' border='0' /></a>";
return $link if $mode eq 'bare';
my $K = $ppe->{length} ? int($ppe->{length} / 1024) . "K" : "";
my $secs = $ppe->{lengthsecs};
my $duration = $secs ? sprintf("%d:%02d", int($secs/60), $secs%60) : "";
# support rss 'enclosures' - podcasting.
if ($mode eq 'rss') {
$link = "<enclosure url=\"$path\" length=\"$ppe->{length}\" " .
"type=\"$datatypes->{ $ppe->{filetype} }->{mime}\" />";
return $link;
}
# return full table
my $ret = "<table cellspacing='5' cellpadding='0' border='0' class='ljphonepost'><tr>";
$ret .= "<td valign='top'>$link</td>";
$ret .= "<td valign='top'><strong>";
$ret .= $ppe->{location} eq 'none' ? "PhonePost" : "<a href='$path'>PhonePost</a>";
$ret .= "</strong><br /><em>$K</em>&nbsp;$duration</td>";
unless ($mode eq 'notrans') {
my $trans_url = "$LJ::SITEROOT/phonepost/transcribe.bml?user=$u->{user}&amp;ppid=$dppid";
$ret .= "<td valign='top'><a href='$LJ::SITEROOT/phonepost/about.bml'><img src='$LJ::IMGPREFIX/help.gif' width='14' height='14' border='0' alt='(Help)' /></a></td>";
my $trans = LJ::PhonePost::get_latest_trans($u, $phonepostid);
if ($trans) {
my $by;
if ($trans->{revid} == 1) {
$by = LJ::ljuser(LJ::get_username($trans->{posterid}));
} else {
# multiple users transcribing, or just multiple transcriptions of one user?
my $memkey = [$u->{userid},"ppetu:$u->{userid}:$phonepostid"];
my $tu = LJ::MemCache::get($memkey);
unless (defined $tu) {
my $dbr = LJ::get_cluster_reader($u);
$tu = $dbr->selectrow_array("SELECT COUNT(DISTINCT(posterid)) " .
"FROM phoneposttrans " .
"WHERE journalid=? AND blobid=?",
undef, $u->{'userid'}, $phonepostid + 0);
LJ::MemCache::set($memkey, $tu);
}
$by = ($tu == 1) ? LJ::ljuser(LJ::get_username($trans->{posterid})) : "multiple users";
}
my $text = LJ::ehtml($trans->{body});
$text =~ s/\n/<br \/>/g;
$ret .= "<td valign='top'><blockquote cite='$path'>&ldquo;$text&rdquo;</blockquote><br />".
"<a href='$trans_url'>Transcribed</a> by: $by</td>";
} elsif (LJ::PhonePost::may_transcribe($u, $remote)) {
$ret .= "<td valign='top'>(<a href='$trans_url'>transcribe</a>)</td>";
} else {
$ret .= "<td valign='top'>(no transcription available)</td>";
}
}
$ret .= "</tr></table>";
return $ret;
}
sub get_latest_trans {
my ($u, $id) = @_;
$id += 0;
my $memkey = [$u->{userid},"ppelt:$u->{userid}:$id"];
my $lt = LJ::MemCache::get($memkey);
unless (defined $lt) {
my $dbcr = LJ::get_cluster_def_reader($u);
return undef unless $dbcr;
$lt = "";
my $latest = $dbcr->selectrow_array("SELECT MAX(revid) FROM phoneposttrans ".
"WHERE journalid=? AND blobid=?", undef,
$u->{userid}, $id);
if ($latest) {
$lt = $dbcr->selectrow_hashref("SELECT revid,posterid,posttime,subject,body ".
"FROM phoneposttrans WHERE journalid=? ".
"AND blobid=? AND revid=?", undef,
$u->{userid}, $id, $latest);
}
LJ::MemCache::set($memkey, $lt);
}
return $lt;
}
sub show_phoneposts {
my ($u_embed, $ditemid, $remote, $eventref) = @_;
my $replace = sub {
my $tag = shift;
my ($user, $userid, $uobj, $phid, $blobid, $dpid);
# old tag <lj-phonepost user='foo' phonepostid='1' />
# new tag <lj-phonepost journalid='1234567' dpid='10000422' />
if ($tag =~ m!^journalid=['"](\d+)['"]\s*dpid=['"](\d+)['"]\s*/?$!) {
($userid, $dpid)=($1,$2);
# prefer phonepostid and userid
$phid = $dpid >> 8 if $dpid;
} elsif ($tag =~ m!^(user=['"](\S+)['"])?\s*(phonepostid=['"](\d+)['"])?\s*(userid=['"](\d+)['"])?\s*(blobid=['"](\d+)['"])?\s*/?$!) {
($user,$phid,$userid,$blobid)=($2,$4,$6,$8);
# prefer phonepostid and userid
$phid = $blobid >> 8
unless $phid or not $blobid;
do {
$uobj = LJ::load_user($user);
$userid = $uobj->{'userid'};
} unless $userid or $user eq "";
}
return "<b>[Invalid audio link]</b>" unless $phid and $userid;
return make_link($remote, $userid, $phid, 0, $u_embed, $ditemid);
};
$$eventref =~ s!<lj-phonepost\s*([^>]*)>!$replace->($1)!eg;
}
1;

View File

@@ -0,0 +1,125 @@
#!/usr/bin/perl
#
use strict;
package LJ::Portal;
use vars qw(%box);
$box{'newtolj'} =
{
'name' => '<?_ml portal.newtolj.name _ml?>',
'small' => 1,
'large' => 0,
'handler' => sub {
my ($remote, $opts, $box) = @_;
my $b = $opts->{'body'};
box_start($b, $box, { 'title' => "About $LJ::SITENAME",
'align' => "left",
'url' => '/site/about.bml', });
$$b .= "New to $LJ::SITENAME?";
my @links = ("What is $LJ::SITENAME?", "/site/about.bml",
"Create an account!", "/create.bml");
while (@links) {
my $link = shift @links;
my $url = shift @links;
$$b .= "<li><a href=\"$url\"><b>$link</b></a>\n";
}
box_end($b, $box);
$$b .= "</form>\n";
},
};
############################################################################
$box{'goat'} =
{
'name' => '<?_ml portal.goat.name _ml?>',
'small' => 1,
'large' => 0,
'opts' => [ { 'key' => 'misbehaved',
'name' => '<?_ml portal.misbehaved.name _ml?>',
'des' => '<?_ml portal.misbehaved.des _ml?>',
'type' => 'check',
'value' => 1,
'default' => 0, },
{ 'key' => 'goattext',
'name' => '<?_ml portal.goattext.name _ml?>',
'des' => '<?_ml portal.goattext.des _ml?>',
'type' => 'text',
'default' => "Baaaaah",
'size' => 40,
'maxlength' => 40, },
],
'handler' => sub {
my ($remote, $opts, $box) = @_;
my $b = $opts->{'body'};
my $bo = $opts->{'bodyopts'};
my $h = $opts->{'head'};
my $pic;
if ($opts->{'form'}->{'frank'} eq "urinate" || $box->{'args'}->{'misbehaved'}) {
$pic = "pee";
} else {
$pic = "hover";
}
box_start($b, $box, { 'title' => "Frank",
'align' => "center",
'url' => "/site/goat.bml", });
my $imgname = "frankani" . $box->{'uniq'};
my $goattext = $box->{'args'}->{'goattext'} || "Baaaah";
$$b .= <<"GOAT_STUFF";
<a onmouseout="MM_swapImgRestore()" onmouseover="MM_swapImage('$imgname','','$LJ::IMGPREFIX/goat-$pic.gif',1)" href="/site/goat.bml"><img name="$imgname" src="$LJ::IMGPREFIX/goat-normal.gif" width='110' height='101' hspace='2' vspace='2' border='0' alt="Frank, the LiveJournal mascot goat."></a><br />
<b><i>"$goattext"</i> says Frank.
GOAT_STUFF
box_end($b, $box);
$opts->{'onload'}->{"MM_preloadImages('$LJ::IMGPREFIX/goat-$pic.gif');"} = 1;
unless ($opts->{'did'}->{'image_javascript'})
{
$opts->{'did'}->{'image_javascript'} = 1;
$$h .= <<'JAVASCRIPT';
<script language="JavaScript">
<!--
function MM_swapImgRestore() { //v3.0
var i,x,a=document.MM_sr; for(i=0;a&&i<a.length&&(x=a[i])&&x.oSrc;i++) x.src=x.oSrc;
}
function MM_preloadImages() { //v3.0
var d=document; if(d.images){ if(!d.MM_p) d.MM_p=new Array();
var i,j=d.MM_p.length,a=MM_preloadImages.arguments; for(i=0; i<a.length; i++)
if (a[i].indexOf("#")!=0){ d.MM_p[j]=new Image; d.MM_p[j++].src=a[i];}}
}
function MM_findObj(n, d) { //v3.0
var p,i,x; if(!d) d=document; if((p=n.indexOf("?"))>0&&parent.frames.length) {
d=parent.frames[n.substring(p+1)].document; n=n.substring(0,p);}
if(!(x=d[n])&&d.all) x=d.all[n]; for (i=0;!x&&i<d.forms.length;i++) x=d.forms[i][n];
for(i=0;!x&&d.layers&&i<d.layers.length;i++) x=MM_findObj(n,d.layers[i].document); return x;
}
function MM_swapImage() { //v3.0
var i,j=0,x,a=MM_swapImage.arguments; document.MM_sr=new Array; for(i=0;i<(a.length-2);i+=3)
if ((x=MM_findObj(a[i]))!=null){document.MM_sr[j++]=x; if(!x.oSrc) x.oSrc=x.src; x.src=a[i+2];}
}
//-->
</script>
JAVASCRIPT
} # end unless
}, # end handler
};
############################################################################

View File

@@ -0,0 +1,12 @@
/legal/coppa.bml /legal/privacy.bml
/site/contract.bml /legal/principles.bml
/todo.bml /todo/?user=lj_biz
/press.bml /press/
/site/map.bml /site/
/goat.bml /site/goat.bml
/clients /download/
/download/win32/source.bml /code/clients/win32/
/sitemap.bml /site/
/contributors.bml /site/contributors.bml
/supporters.bml /paidaccounts/
/free.bml /site/about.bml