init
62
livejournal/htdocs/500-error.html
Executable file
@@ -0,0 +1,62 @@
|
||||
<h1>Sorry</h1>
|
||||
<p>We're currently working on something. The site will be back up shortly.
|
||||
|
||||
|
||||
<!--
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
-->
|
||||
|
||||
15
livejournal/htdocs/_config.bml
Executable file
@@ -0,0 +1,15 @@
|
||||
LookRoot $LJHOME/cgi-bin/bml/scheme
|
||||
DefaultScheme bluewhite
|
||||
DefaultLanguage en
|
||||
IncludePath inc/
|
||||
|
||||
AllowOldSyntax 0
|
||||
ExtraConfig _config-local.bml, $LJHOME/cgi-bin/lj-bml-init.pl
|
||||
AllowCode 1
|
||||
AllowTemplateCode 1
|
||||
|
||||
SubConfig: guide/, clients/, files/
|
||||
AllowCode 0
|
||||
|
||||
|
||||
|
||||
94
livejournal/htdocs/accountstatus.bml
Executable file
@@ -0,0 +1,94 @@
|
||||
<?page
|
||||
title=><?_ml .title _ml?>
|
||||
body<=
|
||||
<?_code
|
||||
{
|
||||
use strict;
|
||||
use vars qw(%GET %POST);
|
||||
|
||||
LJ::set_active_crumb('acctstatus');
|
||||
|
||||
my $remote = LJ::get_remote();
|
||||
return LJ::bad_input($ML{'error.noremote'})
|
||||
unless $remote;
|
||||
|
||||
my $authas = $GET{'authas'} || $remote->{'user'};
|
||||
my $u = LJ::get_authas_user($authas);
|
||||
return LJ::bad_input($ML{'error.invalidauth'})
|
||||
unless $u;
|
||||
|
||||
# visibility status name mappings
|
||||
my %statusvis = ( "V" => "$ML{'.journalstatus.select.activated'}",
|
||||
"D" => "$ML{'.journalstatus.select.deleted'}" );
|
||||
if ($u->{'statusvis'} eq "S") {
|
||||
%statusvis = ("S" => "$ML{'.journalstatus.select.suspended'}");
|
||||
}
|
||||
|
||||
# process form submission
|
||||
if (LJ::did_post() && LJ::check_referer('/accountstatus.bml')) {
|
||||
|
||||
my $ok = sub {
|
||||
return "<?h1 $ML{'.header.success'} h1?>\n<?p " . $_[0] . " p?>";
|
||||
};
|
||||
|
||||
my $dberr = sub {
|
||||
return "<?h1 $ML{'Error'} h1?>\n<?p " . $_[0] . " p?>";
|
||||
};
|
||||
|
||||
# are they suspended?
|
||||
return LJ::bad_input($ML{'.error.nochange.suspend'})
|
||||
if $u->{'statusvis'} eq 'S';
|
||||
|
||||
# are they expunged?
|
||||
return LJ::bad_input($ML{'.error.nochange.expunged'})
|
||||
if $u->{'statusvis'} eq 'X';
|
||||
|
||||
# invalid statusvis
|
||||
return LJ::bad_input($ML{'.error.invalid'})
|
||||
unless $POST{'statusvis'} eq 'D' || $POST{'statusvis'} eq 'V';
|
||||
|
||||
# no need to change?
|
||||
return $ok->(BML::ml('.message.nochange', {'statusvis' => $statusvis{$POST{'statusvis'}} }))
|
||||
if $u->{'statusvis'} eq $POST{'statusvis'};
|
||||
|
||||
# do update
|
||||
my $res = LJ::update_user($u, { 'statusvis' => $POST{'statusvis'},
|
||||
'raw' => 'statusvisdate=NOW()' });
|
||||
|
||||
# error updating?
|
||||
return $dberr->($ML{'.error.db'})
|
||||
unless $res;
|
||||
|
||||
# success
|
||||
return $ok->(BML::ml('.message.success', {'statusvis' => $statusvis{$POST{'statusvis'}} }));
|
||||
|
||||
}
|
||||
|
||||
# update form
|
||||
|
||||
my $ret;
|
||||
|
||||
# authas switcher form
|
||||
$ret .= "<form method='get' action='accountstatus.bml'>\n";
|
||||
$ret .= LJ::make_authas_select($remote, { 'authas' => $GET{'authas'} }) . "\n";
|
||||
$ret .= "</form>\n\n";
|
||||
|
||||
my $getextra = "?authas=$authas" unless $authas eq $remote->{'user'};
|
||||
$ret .= "<form method='post' action='accountstatus.bml$getextra'>\n";
|
||||
|
||||
$ret .= "<?h1 $ML{'.journalstatus.head'} h1?><?p $ML{'.journalstatus.about'} p?>\n";
|
||||
$ret .= "<div style='margin-left: 30px'>$ML{'.journalstatus.select.head'}\n";
|
||||
$ret .= LJ::html_select({ 'name' => 'statusvis', 'selected' => $u->{'statusvis'} },
|
||||
map { $_, $statusvis{$_} }
|
||||
reverse sort keys %statusvis) . "\n";
|
||||
|
||||
$ret .= LJ::html_submit(undef, $ML{'.btn.status'},
|
||||
{ 'disabled' => $u->{'statusvis'} eq 'S' }) . "\n";
|
||||
$ret .= "</div>\n</form>\n";
|
||||
|
||||
return $ret;
|
||||
}
|
||||
_code?>
|
||||
<=body
|
||||
page?>
|
||||
|
||||
104
livejournal/htdocs/admin/capedit.bml
Executable file
@@ -0,0 +1,104 @@
|
||||
<?_code
|
||||
|
||||
use strict;
|
||||
use vars qw(%FORM);
|
||||
|
||||
my ($sth, $ret);
|
||||
my $mode = $FORM{'mode'};
|
||||
|
||||
my $remote = LJ::get_remote();
|
||||
|
||||
$mode ||= $FORM{'user'} ? "viewuser" : "intro";
|
||||
|
||||
my $user = LJ::canonical_username($FORM{'user'});
|
||||
my $u;
|
||||
$u = LJ::load_user($user) if $user;
|
||||
|
||||
if ($mode eq "intro")
|
||||
{
|
||||
$ret .= "<h1>capability class management</h1>\n";
|
||||
$ret .= "<form method='get'>";
|
||||
$ret .= "Modify capabilities for user: <input name='user' size='15'> <input type='submit' value=\"Load\">";
|
||||
$ret .= "</form>";
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
if ($mode eq "save")
|
||||
{
|
||||
return "<b>Error:</b> requires post"
|
||||
unless (LJ::did_post());
|
||||
|
||||
return"<b>Error:</b> You don't have access to change a user's capability class."
|
||||
unless (LJ::check_priv($remote, "admin", "*"));
|
||||
|
||||
unless ($u) {
|
||||
$ret .= "Unknown user.\n";
|
||||
return $ret;
|
||||
}
|
||||
|
||||
my @cap_add = ();
|
||||
my @cap_del = ();
|
||||
my $newcaps = $u->{caps};
|
||||
foreach my $n (sort { $a <=> $b } keys %LJ::CAP) {
|
||||
if ($FORM{"class_$n"}) {
|
||||
push @cap_add, $n;
|
||||
$newcaps |= (1 << $n);
|
||||
} else {
|
||||
push @cap_del, $n;
|
||||
$newcaps &= ~(1 << $n);
|
||||
}
|
||||
}
|
||||
|
||||
# note which caps were changed and log $logmsg to statushistory
|
||||
my $add_txt = join(",", @cap_add);
|
||||
my $del_txt = join(",", @cap_del);
|
||||
LJ::statushistory_add($u->{'userid'}, $remote->{'userid'},
|
||||
"capedit", "add: $add_txt, del: $del_txt\n");
|
||||
|
||||
LJ::modify_caps($u, \@cap_add, \@cap_del)
|
||||
or return"<b>Error:</b> Unable to modify caps.";
|
||||
|
||||
# $u->{caps} is now updated in memory for later in this request
|
||||
$u->{caps} = $newcaps;
|
||||
|
||||
$ret .= "Saved.";
|
||||
$mode = "viewuser";
|
||||
}
|
||||
|
||||
if ($mode eq "viewuser")
|
||||
{
|
||||
$ret .= "<h1><a href='capedit.bml'><<</a> edit user '$user'</h1>\n";
|
||||
|
||||
unless ($u) {
|
||||
$ret .= "Unknown user.\n";
|
||||
return $ret;
|
||||
}
|
||||
|
||||
$ret .= "<form method='post'>";
|
||||
$ret .= "<input type='hidden' name='mode' value='save'>\n";
|
||||
$ret .= "<input type='hidden' name='user' value='$user'>\n";
|
||||
foreach my $n (sort { $a <=> $b } keys %LJ::CAP)
|
||||
{
|
||||
my $on = ($u->{'caps'}+0) & (1 << $n);
|
||||
my $checked = $on ? " checked='1'" : "";
|
||||
$ret .= "<p><input type='checkbox' name='class_$n' value='1' id='class_$n' $checked> ";
|
||||
my $name = $LJ::CAP{$n}->{'_name'} || "Unnamed capability class \#$n";
|
||||
if ($on) { $ret .= "<b>"; }
|
||||
$ret .= "<label for='class_$n'>$name</label>";
|
||||
if ($on) { $ret .= "</b>"; }
|
||||
}
|
||||
|
||||
$ret .= "<p><input type='submit' value='Save'>\n";
|
||||
$ret .= "</form>";
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
return "Unknown mode.";
|
||||
|
||||
_code?><?_c <LJDEP>
|
||||
lib: cgi-bin/ljlib.pl
|
||||
form: htdocs/admin/capedit.bml
|
||||
post: htdocs/admin/capedit.bml
|
||||
</LJDEP _c?>
|
||||
47
livejournal/htdocs/admin/clusterstatus.bml
Executable file
@@ -0,0 +1,47 @@
|
||||
<?page
|
||||
title=>Cluster Status
|
||||
body<=
|
||||
<?_code
|
||||
{
|
||||
use strict;
|
||||
|
||||
my $remote = LJ::get_remote();
|
||||
return "<?needlogin?>" unless $remote;
|
||||
return "<?h1 Error h1?><?p You do not have the necessary privilege (supporthelp) to use this page. p?>"
|
||||
unless LJ::check_priv($remote, 'supporthelp');
|
||||
|
||||
my $ret;
|
||||
foreach my $cid (@LJ::CLUSTERS) {
|
||||
my $name = LJ::get_cluster_description($cid) || 'no name';
|
||||
|
||||
$ret .= "<b>$name</b>: ";
|
||||
|
||||
my $check = 0;
|
||||
if ($LJ::READONLY_CLUSTER{$cid}) {
|
||||
$ret .= "<strong>read-only for all users</strong>";
|
||||
} elsif ($LJ::READONLY_CLUSTER_ADVISORY{$cid} eq 'when_needed') {
|
||||
$ret .= "<strong>read-only for free users during load</strong>",
|
||||
} elsif ($LJ::READONLY_CLUSTER_ADVISORY{$cid}) {
|
||||
$ret .= "<strong>read-only for free users</strong>";
|
||||
} else {
|
||||
$ret .= "no known issues";
|
||||
$check = 1;
|
||||
}
|
||||
|
||||
if ($check) {
|
||||
my $dbcm = LJ::get_cluster_master($cid);
|
||||
if ($dbcm) {
|
||||
$ret .= "; available";
|
||||
} else {
|
||||
$ret .= "; <span style='color: red;'>unavailable</a>";
|
||||
}
|
||||
}
|
||||
|
||||
$ret .= "<br />";
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
_code?>
|
||||
<=body
|
||||
page?>
|
||||
104
livejournal/htdocs/admin/console/index.bml
Executable file
@@ -0,0 +1,104 @@
|
||||
<html>
|
||||
<head><title>Admin Console</title></head>
|
||||
<body>
|
||||
<?_code
|
||||
|
||||
use strict;
|
||||
use vars qw(%POST %cmd);
|
||||
|
||||
my ($ret, $sth);
|
||||
|
||||
my $commands = $POST{'commands'};
|
||||
my $remote = LJ::get_remote();
|
||||
|
||||
if ($commands)
|
||||
{
|
||||
unless (LJ::did_post()) {
|
||||
return "<b>Error:</b> requires post.";
|
||||
}
|
||||
|
||||
if ($remote && $remote->{'user'} ne $POST{'remoteuser'}) {
|
||||
return "<b>Error:</b> invalid user.";
|
||||
}
|
||||
|
||||
$ret .= "[ <A HREF=\"./\">console</A> | <A HREF=\"reference.bml\">reference</A> ]<P>";
|
||||
|
||||
foreach my $cmd (split(/\n/, $commands))
|
||||
{
|
||||
my @args = LJ::Con::parse_line($cmd);
|
||||
next unless @args;
|
||||
|
||||
my $first = 1;
|
||||
$ret .= "<P><TABLE BORDER=1 CELLPADDING=5><TR>";
|
||||
foreach (@args) {
|
||||
my $arg = BML::eall($_);
|
||||
if ($first) {
|
||||
$ret .= "<TD><B>$arg</B></TD>";
|
||||
$first = 0;
|
||||
} else {
|
||||
$ret .= "<TD>$arg</TD>";
|
||||
}
|
||||
}
|
||||
$ret .= "</TR></TABLE>";
|
||||
|
||||
my @output;
|
||||
my $rv;
|
||||
|
||||
# TODO: make the entire console library not take $db args.
|
||||
my $dbh = LJ::get_db_writer();
|
||||
$rv = LJ::Con::execute($dbh, $remote, \@args, \@output);
|
||||
|
||||
unless ($rv) { $ret .= "<P><B><FONT COLOR=#FF0000>Failed!</FONT></B>"; }
|
||||
if (@output) {
|
||||
$ret .= "<PRE><B>";
|
||||
foreach my $line (@output) {
|
||||
my $color = "#000000";
|
||||
if ($line->[0] eq "error") {
|
||||
$color = "#FF0000";
|
||||
}
|
||||
if ($line->[0] eq "info") {
|
||||
$color = "#008800";
|
||||
}
|
||||
|
||||
$ret .= "<FONT COLOR=$color>".LJ::eall($line->[1])."</FONT>\n";
|
||||
|
||||
}
|
||||
$ret .= "</B></PRE>";
|
||||
}
|
||||
}
|
||||
|
||||
$ret .= "<form method=post><p>";
|
||||
$ret .= "<tt>enter commands:</tt><br>";
|
||||
$ret .= LJ::html_hidden('remoteuser', $remote->{'user'}) if $remote;
|
||||
$ret .= "<textarea name=commands rows=3 cols=60 wrap=off></textarea> ";
|
||||
$ret .= "<input type=submit value=\"execute\"></form>\n";
|
||||
|
||||
return $ret;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
$ret .= "[ console | <A HREF=\"reference.bml\">reference</A> ]<P>";
|
||||
|
||||
$ret .= "<FORM METHOD=POST>";
|
||||
$ret .= LJ::html_hidden('remoteuser', $remote->{'user'}) if $remote;
|
||||
$ret .= "<TABLE WIDTH=400><TR VALIGN=BOTTOM>";
|
||||
$ret .= "<TD><IMG SRC=\"$LJ::IMGPREFIX/nerd_small.jpg\" WIDTH=167 HEIGHT=169 HSPACE=2 VSPACE=2></TD>";
|
||||
$ret .= "<TD><B><TT>command console.</TT></B>";
|
||||
$ret .= "<P>welcome to the livejournal console. from here administrators can do administrative type things. you will forget the commands, so there is a <A HREF=\"reference.bml\">reference</A>.</TD>";
|
||||
$ret .= "</TR>";
|
||||
$ret .= "<TR><TD COLSPAN=2>";
|
||||
$ret .= "<P><tt>enter commands:</tt><BR>";
|
||||
$ret .= "<TEXTAREA NAME=commands ROWS=10 COLS=60 WRAP=OFF></TEXTAREA></TD></TR>\n";
|
||||
$ret .= "<TR><TD COLSPAN=2 ALIGN=RIGHT><INPUT TYPE=SUBMIT VALUE=\"execute\"></P></TD></TR></TABLE></FORM>\n";
|
||||
return $ret;
|
||||
}
|
||||
|
||||
_code?>
|
||||
</body>
|
||||
</html>
|
||||
<?_c <LJDEP>
|
||||
lib: cgi-bin/console.pl, cgi-bin/ljlib.pl
|
||||
link: htdocs/admin/console/reference.bml
|
||||
post: htdocs/admin/console/index.bml
|
||||
</LJDEP> _c?>
|
||||
49
livejournal/htdocs/admin/console/reference.bml
Executable file
@@ -0,0 +1,49 @@
|
||||
<html><head><title>Console Reference</title></head>
|
||||
<body>
|
||||
|
||||
[ <a href="./">console</a> | reference ]
|
||||
|
||||
<P><B>Grammar</B>
|
||||
<BR>Think of this like a DOS or <tt>bash</tt> prompt. The first word is a command. Every word after that is an argument to that command. Every command has a different number of required and optional parameters. White space delimits arguments. If you need a space in an argument, put double quotes around the whole thing. If you need double quotes and spaces in an argument, escape the quote with a backslash (\) first. If you need to do a backslash, escape that with a backslash.
|
||||
<P>It's pretty straight-forward. If you're confused, ask.
|
||||
|
||||
<P><B>Command Reference</B>
|
||||
<BR>Arguments in <angle brackets> are required. Arguments in [brackets] are optional. If there is more than one optional argument, you can't skip one and provide one after it. Once you skip one, you have to skip the rest.
|
||||
|
||||
<?_code
|
||||
|
||||
use strict;
|
||||
use vars qw(%cmd);
|
||||
|
||||
my ($ret, $sth);
|
||||
|
||||
$ret .= "<dl>";
|
||||
foreach my $cmdname (sort keys %LJ::Con::cmd)
|
||||
{
|
||||
my $cmd = $LJ::Con::cmd{$cmdname};
|
||||
next if ($cmd->{'hidden'});
|
||||
|
||||
my $args = LJ::ehtml($cmd->{'argsummary'});
|
||||
my $anchor = "cmd.$cmdname";
|
||||
$ret .= "<a name='$anchor'><dt><p><table width=100% cellpadding=2><tr><td bgcolor=#d0d0d0>";
|
||||
$ret .= "<tt><a style='text-decoration: none' href='\#$anchor'><b>$cmdname</b></a> $args</tt></td></tr></table>";
|
||||
$ret .= "</dt><dd><p>$cmd->{'des'}";
|
||||
if ($cmd->{'args'}) {
|
||||
my @des = @{$cmd->{'args'}};
|
||||
$ret .= "<p><dl>";
|
||||
while (my ($arg, $des) = splice(@des, 0, 2)) {
|
||||
$ret .= "<dt><b><i>$arg</i></b></dt><dd>$des</dd>";
|
||||
}
|
||||
$ret .= "</dl>";
|
||||
}
|
||||
$ret .= "</dd></a>";
|
||||
}
|
||||
$ret .= "</dl>";
|
||||
return $ret;
|
||||
|
||||
_code?>
|
||||
|
||||
</body></html><?_c <LJDEP>
|
||||
lib: cgi-bin/console.pl, cgi-bin/ljlib.pl
|
||||
link: htdocs/admin/console/index.bml
|
||||
</LJDEP> _c?>
|
||||
200
livejournal/htdocs/admin/dbadmin.bml
Executable file
@@ -0,0 +1,200 @@
|
||||
<html>
|
||||
<head><title>DB Admin - <?sitename?></title>
|
||||
<style>
|
||||
p, td { font-size: 9pt; font-family: sans-serif; }
|
||||
input { font-size: 8pt; font-family: sans-serif; }
|
||||
</style>
|
||||
</head>
|
||||
<body bgcolor='#000000' text='#ffffff' link='#eeeeee' vlink='#eeeeee'>
|
||||
<?_code
|
||||
|
||||
use strict;
|
||||
use vars qw(%FORM);
|
||||
|
||||
my $dbh = LJ::get_db_writer();
|
||||
my $remote = LJ::get_remote($dbh);
|
||||
|
||||
return"<b>Error:</b> You don't have access to administer databases."
|
||||
unless (LJ::check_priv($dbh, $remote, "siteadmin", "dbweightview"));
|
||||
|
||||
my $can_save = LJ::check_priv($dbh, $remote, "siteadmin", "dbweightchange");
|
||||
|
||||
my $view = $FORM{'view'} eq "role" ? "role" : "host";
|
||||
|
||||
my %dbinfo; # dbid
|
||||
my %slaves; # dbid
|
||||
my $sth;
|
||||
$sth = $dbh->prepare("SELECT dbid, name, fdsn, masterid FROM dbinfo");
|
||||
$sth->execute;
|
||||
while ($_ = $sth->fetchrow_hashref) {
|
||||
next unless $_->{'dbid'};
|
||||
$dbinfo{$_->{'dbid'}} = $_;
|
||||
push @{$slaves{$_->{'masterid'}}}, $_->{'dbid'};
|
||||
}
|
||||
|
||||
my %weights;
|
||||
my %role;
|
||||
my %roletweight;
|
||||
$sth = $dbh->prepare("SELECT dbid, role, norm, curr FROM dbweights");
|
||||
$sth->execute;
|
||||
while ($_ = $sth->fetchrow_hashref) {
|
||||
next unless defined $dbinfo{$_->{'dbid'}};
|
||||
$weights{$_->{'dbid'}}->{$_->{'role'}} = $_;
|
||||
push @{$role{$_->{'role'}}}, $_->{'dbid'};
|
||||
$roletweight{$_->{'role'}} += $_->{'curr'};
|
||||
}
|
||||
|
||||
my $ret;
|
||||
my $p = sub { $ret .= shift; };
|
||||
my $status;
|
||||
|
||||
if ($can_save && defined $FORM{'action:save'}) {
|
||||
return "<b>Error:</b> Not a POST request." unless LJ::did_post();
|
||||
|
||||
my $curr_changed = 0;
|
||||
foreach my $k (keys %FORM) {
|
||||
next unless $k =~ /^set-(\d+)-(\w+?)-(\w+)$/;
|
||||
my ($sid, $role, $what) = ($1, $2, $3);
|
||||
next unless $what eq "norm" or $what eq "curr";
|
||||
next unless defined $weights{$sid};
|
||||
next unless defined $weights{$sid}->{$role};
|
||||
my $val = $FORM{$k}+0;
|
||||
my $old = $weights{$sid}->{$role}->{$what};
|
||||
next if $val == $old;
|
||||
|
||||
$dbh->do("UPDATE dbweights SET $what=$val WHERE ".
|
||||
"dbid=$sid AND role='$role'");
|
||||
$weights{$sid}->{$role}->{$what} = $val;
|
||||
if ($what eq "curr") {
|
||||
$curr_changed = 1;
|
||||
$roletweight{$role} += $val - $old;
|
||||
}
|
||||
}
|
||||
|
||||
if ($curr_changed) {
|
||||
if ($LJ::DBCONFIG_WRITE_CONFIG) {
|
||||
my $good = 1;
|
||||
my $newcfg = "# auto-generated config from /admin/dbadmin.bml. changes will be overwritten!\n";
|
||||
$newcfg .= "%LJ::DBINFO = (\n";
|
||||
foreach my $id (sort keys %dbinfo) {
|
||||
next unless $id > 0;
|
||||
my $dbinf = $dbinfo{$id};
|
||||
my $name = $dbinf->{'name'};
|
||||
if ($dbinf->{'masterid'} == 0) { $name = "master"; }
|
||||
$newcfg .= "\t'$name' => {\n";
|
||||
$newcfg .= "\t\t'_fdsn' => \"$dbinf->{fdsn}\",\n";
|
||||
$newcfg .= "\t\t'role' => {\n";
|
||||
foreach my $role (sort keys %{$weights{$id} || {}}) {
|
||||
$newcfg .= "\t\t\t'$role' => $weights{$id}->{$role}->{'curr'},\n";
|
||||
}
|
||||
$newcfg .= "\t\t},\n";
|
||||
$newcfg .= "\t},\n";
|
||||
}
|
||||
$newcfg .= ");\n";
|
||||
$newcfg .= "\$LJ::DBINFO{'master'}->{'role'}->{'master'} = 1;\n";
|
||||
$newcfg .= "1;\n";
|
||||
|
||||
if (open(CFG, ">$ENV{'LJHOME'}/cgi-bin/dbconfig.pl")) {
|
||||
print CFG $newcfg;
|
||||
close CFG;
|
||||
open (TCH, ">>$ENV{'LJHOME'}/cgi-bin/ljconfig.pl");
|
||||
close TCH;
|
||||
}
|
||||
|
||||
$status .= "<p>Wrote config.</p>";
|
||||
} else {
|
||||
my $newserial = LJ::procnotify_add("DBI::Role::reload");
|
||||
$status .= "<p>New Serial: $newserial</p>\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
my $single = sub {
|
||||
my $role = shift;
|
||||
return @{$role{$role}} == 1;
|
||||
};
|
||||
|
||||
my $slaveroleperc = sub {
|
||||
my $sid = shift;
|
||||
my $role = shift;
|
||||
return sprintf("%0.1f%%", 100*$weights{$sid}->{$role}->{'curr'}/($roletweight{$role}||1));
|
||||
};
|
||||
|
||||
my $dumpslaves = sub
|
||||
{
|
||||
my $mid = shift;
|
||||
my $depth = shift;
|
||||
my $rec = shift;
|
||||
return unless $slaves{$mid};
|
||||
|
||||
my $indent = " " x ($depth*5);
|
||||
|
||||
foreach my $sid (sort { $#{$slaves{$a}} <=> $#{$slaves{$b}} } @{$slaves{$mid}}) {
|
||||
my $db = $dbinfo{$sid};
|
||||
$p->("<tr bgcolor='#404070'><td colspan='4'><b>$indent$db->{'name'}</b> ($sid)</td></tr>");
|
||||
|
||||
foreach my $role (sort keys %{$weights{$sid}}) {
|
||||
my $r = $weights{$sid}->{$role};
|
||||
my $col;
|
||||
if ($r->{'norm'} != $r->{'curr'}) {
|
||||
$col = "bgcolor='#800000'";
|
||||
}
|
||||
$p->("<tr valign='bottom' $col><td>$indent$role</td>");
|
||||
$p->("<td align='center'><input size='3' name='set-$sid-$role-norm' value='$r->{'norm'}'></td>");
|
||||
$p->("<td align='center'><input size='3' name='set-$sid-$role-curr' value='$r->{'curr'}'></td>");
|
||||
$p->("<td>" . $slaveroleperc->($sid, $role) . "</td>");
|
||||
$p->("</tr>");
|
||||
}
|
||||
$rec->($sid, $depth+1, $rec);
|
||||
}
|
||||
};
|
||||
|
||||
my $dumprole = sub
|
||||
{
|
||||
my $role = shift;
|
||||
return if $single->($role);
|
||||
$p->("<tr bgcolor='#404070'><td colspan='4'><b>$role</b></td></tr>");
|
||||
|
||||
foreach my $sid (sort { $weights{$b}->{$role}->{'curr'} <=> $weights{$a}->{$role}->{'curr'} } @{$role{$role}})
|
||||
{
|
||||
my $r = $weights{$sid}->{$role};
|
||||
my $col;
|
||||
$col = "bgcolor='#800000'" if $r->{'norm'} != $r->{'curr'};
|
||||
$p->("<tr valign='bottom' $col><td>$dbinfo{$sid}->{'name'}</td>");
|
||||
$p->("<td align='center'><input size='3' name='set-$sid-$role-norm' value='$r->{'norm'}'></td>");
|
||||
$p->("<td align='center'><input size='3' name='set-$sid-$role-curr' value='$r->{'curr'}'></td>");
|
||||
$p->("<td>" . $slaveroleperc->($sid, $role) . "</td>");
|
||||
$p->("</tr>");
|
||||
}
|
||||
};
|
||||
|
||||
$p->('<form method="post" action="dbadmin.bml">');
|
||||
$p->("<input type='hidden' name='view' value='$view'>");
|
||||
$p->('<table cellpadding="1" border="0" bgcolor="#606060">');
|
||||
|
||||
my $hr = "<b>Host</b> / <a href='dbadmin.bml?view=role'>Role</a>";
|
||||
if ($view eq "role") {
|
||||
$hr = "<a href='dbadmin.bml?view=host'>Host</a> / <b>Role</b>";
|
||||
}
|
||||
|
||||
$p->("<tr bgcolor='#404040'><td>$hr</td><td><b>Norm</b></td><td><b>Curr</b></td><td>%</td></tr>");
|
||||
if ($view eq "role") {
|
||||
foreach my $role (sort keys %role) {
|
||||
$dumprole->($role);
|
||||
}
|
||||
} else {
|
||||
$dumpslaves->(0, 0, $dumpslaves); # root
|
||||
}
|
||||
if ($can_save) {
|
||||
$p->('<tr><td colspan="4" align="center" bgcolor="#404040"><input type="submit" name="action:refresh" value="Refresh"> ');
|
||||
$p->('<input type="submit" name="action:save" value="Save"></td></tr>');
|
||||
}
|
||||
$p->('</table>');
|
||||
$p->('</form>');
|
||||
$p->($status);
|
||||
|
||||
return $ret;
|
||||
|
||||
_code?>
|
||||
</body>
|
||||
</html>
|
||||
100
livejournal/htdocs/admin/faq/faqedit.bml
Executable file
@@ -0,0 +1,100 @@
|
||||
<?_info
|
||||
nocache=>1
|
||||
_info?><?page
|
||||
title=><?_code return $FORM{'id'} ? "Edit FAQ Item #$FORM{'id'}" : "Add to FAQ"; _code?>
|
||||
body<=
|
||||
|
||||
<CENTER>
|
||||
<A HREF="./"><B>(Back to FAQ Index)</B></A>
|
||||
</CENTER>
|
||||
|
||||
|
||||
<FORM ACTION="faqedit_do.bml" METHOD=POST>
|
||||
<?_code
|
||||
|
||||
$id = $FORM{'id'} + 0;
|
||||
$ret = "";
|
||||
|
||||
my $dbh = LJ::get_db_writer();
|
||||
|
||||
my $remote = LJ::get_remote();
|
||||
my %ac_edit;
|
||||
my %ac_add;
|
||||
LJ::remote_has_priv($remote, "faqadd", \%ac_add);
|
||||
|
||||
if ($id)
|
||||
{
|
||||
LJ::remote_has_priv($remote, "faqedit", \%ac_edit);
|
||||
my $sth = $dbh->prepare("SELECT question, answer, faqcat, sortorder FROM faq WHERE faqid=$id");
|
||||
$sth->execute;
|
||||
($question, $answer, $faqcat, $sortorder) = $sth->fetchrow_array or
|
||||
return "<b>Error:</b> FAQ #$id does not exist.";
|
||||
|
||||
$q = LJ::ehtml($question);
|
||||
$a = LJ::ehtml($answer);
|
||||
|
||||
unless ($ac_edit{'*'} || $ac_edit{$faqcat}) {
|
||||
if (%ac_edit) {
|
||||
return "<B>Error: </B> You do not have access to edit a FAQ question in the \"$faqcat\" category.";
|
||||
} else {
|
||||
return "<B>Error: </B> You do not have access to edit the FAQ.";
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
unless (%ac_add) {
|
||||
return "<B>Error: </B> You do not have access to add to the FAQ.";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$sortorder += 0;
|
||||
$sortorder ||= 50;
|
||||
|
||||
$ret .= "<INPUT TYPE=HIDDEN NAME=id VALUE=$id>\n";
|
||||
$ret .= "<P>Category: <SELECT NAME=\"faqcat\"><OPTION VALUE=\"\">\n";
|
||||
|
||||
my $sth = $dbh->prepare("SELECT faqcat, faqcatname FROM faqcat ORDER BY catorder");
|
||||
$sth->execute;
|
||||
while (($fc, $fcname) = $sth->fetchrow_array)
|
||||
{
|
||||
if ($id) {
|
||||
next unless ($ac_add{'*'} || $ac_add{$fc} || ($fc eq $faqcat));
|
||||
} else {
|
||||
next unless ($ac_add{'*'} || $ac_add{$fc});
|
||||
}
|
||||
$selected = ($fc eq $faqcat) ? " SELECTED" : "";
|
||||
$ret .= "<OPTION VALUE=\"$fc\"$selected>" . LJ::ehtml($fcname) . "\n";
|
||||
}
|
||||
|
||||
$ret .= "</SELECT>";
|
||||
$ret .= "SortOrder (1-100): <INPUT NAME=sortorder SIZE=5 MAXLENGTH=4 VALUE=$sortorder>";
|
||||
$ret .= "<BR><FONT SIZE=-1>(sort order is how to sort within the category. categories themselves are also sorted.)</FONT>";
|
||||
|
||||
$ret .= "<P><B>Question:</B> (as brief as possible, do not span multiple lines)<BR><TEXTAREA NAME=\"q\" ROWS=3 COLS=70 WRAP=SOFT>$q</TEXTAREA><BR><FONT SIZE=-1>(erase question to delete FAQ entry)</FONT>\n";
|
||||
$ret .= "<P><B>Answer:</B> (long as you want, give URLs to links, not HTML)<BR><TEXTAREA NAME=\"a\" ROWS=15 COLS=70 WRAP=SOFT>$a</TEXTAREA>\n";
|
||||
|
||||
my $faqd = LJ::Lang::get_dom("faq");
|
||||
if ($faqd) {
|
||||
$ret .= "<p><b>Select modification level:</b> ";
|
||||
$ret .= LJ::html_select({ 'name' => "sev", "selected" => 1 },
|
||||
0 => "Typo/etc (no notify)",
|
||||
1 => "Minor (notify translators)",
|
||||
2 => "Major (require translation updates)");
|
||||
$ret .= "</p>";
|
||||
}
|
||||
|
||||
|
||||
$ret .= "<P><INPUT TYPE=SUBMIT VALUE=\"Add/Edit FAQ Item\">";
|
||||
return $ret;
|
||||
|
||||
_code?>
|
||||
|
||||
</FORM>
|
||||
|
||||
<=body
|
||||
page?><?_c <LJDEP>
|
||||
lib: cgi-bin/ljlib.pl
|
||||
post: htdocs/admin/faq/faqedit_do.bml
|
||||
</LJDEP> _c?>
|
||||
109
livejournal/htdocs/admin/faq/faqedit_do.bml
Executable file
@@ -0,0 +1,109 @@
|
||||
<?_info
|
||||
nocache=>1
|
||||
_info?><?page
|
||||
title=><?_code return $FORM{'id'} ? "Edit FAQ Item #$FORM{'id'}" : "Add to FAQ"; _code?>
|
||||
body<=
|
||||
|
||||
<CENTER>
|
||||
<A HREF="./"><B>(Back to FAQ Index)</B></A>
|
||||
</CENTER>
|
||||
<P>
|
||||
|
||||
<?_code
|
||||
|
||||
my $dbh = LJ::get_db_writer();
|
||||
|
||||
my $remote = LJ::get_remote();
|
||||
my %ac_edit;
|
||||
my %ac_add;
|
||||
|
||||
$id = $FORM{'id'} + 0;
|
||||
$ret = "";
|
||||
|
||||
$qq = $dbh->quote($FORM{'q'});
|
||||
$qa = $dbh->quote($FORM{'a'});
|
||||
$qfaqcat = $dbh->quote($FORM{'faqcat'});
|
||||
|
||||
$sortorder = $FORM{'sortorder'}+0 || 50;
|
||||
|
||||
return "<?requirepost?>" unless LJ::did_post();
|
||||
|
||||
if ($id)
|
||||
{
|
||||
LJ::remote_has_priv($remote, "faqedit", \%ac_edit);
|
||||
my $sth = $dbh->prepare("SELECT faqcat FROM faq WHERE faqid=$id");
|
||||
$sth->execute;
|
||||
my ($faqcat) = $sth->fetchrow_array;
|
||||
|
||||
unless ($ac_edit{'*'} || $ac_edit{$faqcat}) {
|
||||
if (%ac_edit) {
|
||||
return "<B>Error: </B> You do not have access to edit a FAQ question in the \"$faqcat\" category.";
|
||||
} else {
|
||||
return "<B>Error: </B> You do not have access to edit the FAQ.";
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LJ::remote_has_priv($remote, "faqadd", \%ac_add);
|
||||
unless ($ac_add{'*'} || $ac_add{$FORM{'faqcat'}}) {
|
||||
return "<B>Error: </B> You do not have access to add FAQ questions in this category";
|
||||
}
|
||||
}
|
||||
|
||||
my $faqd = LJ::Lang::get_dom("faq");
|
||||
my $rlang = LJ::Lang::get_root_lang($faqd);
|
||||
unless ($rlang) { undef $faqd; }
|
||||
my $opts = {
|
||||
'changeseverity' => $FORM{'sev'}+0,
|
||||
};
|
||||
my $do_trans = sub {
|
||||
my $id = shift;
|
||||
return unless $faqd;
|
||||
LJ::Lang::set_text($dbh, $faqd->{'dmid'}, $rlang->{'lncode'},
|
||||
"$id.1question", $FORM{'q'}, $opts);
|
||||
LJ::Lang::set_text($dbh, $faqd->{'dmid'}, $rlang->{'lncode'},
|
||||
"$id.2answer", $FORM{'a'}, $opts);
|
||||
};
|
||||
|
||||
unless ($id)
|
||||
{
|
||||
unless ($FORM{'faqcat'})
|
||||
{
|
||||
return "<B>Error: </B> You did not select a FAQ category.";
|
||||
}
|
||||
$dbh->do("INSERT INTO faq (faqid, question, answer, faqcat, sortorder, lastmoduserid, lastmodtime) VALUES (NULL, $qq, $qa, $qfaqcat, $sortorder, $remote->{'userid'}, NOW())");
|
||||
$id = $dbh->{'mysql_insertid'};
|
||||
$ret .= $dbh->errstr || "Added FAQ item. All good.";
|
||||
|
||||
$opts->{'childrenlatest'} = 1;
|
||||
$do_trans->($id) if $id;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
if ($FORM{'q'} =~ /\S/)
|
||||
{
|
||||
$dbh->do("UPDATE faq SET question=$qq, answer=$qa, faqcat=$qfaqcat, lastmoduserid=$remote->{'userid'}, lastmodtime=NOW(), sortorder=$sortorder WHERE faqid=$id");
|
||||
$ret .= "Updated FAQ item. All good. faqid is <b><a href='$LJ::SITEROOT/support/faqbrowse.bml?faqid=$id'>$id</a></b>";
|
||||
|
||||
$do_trans->($id);
|
||||
}
|
||||
else
|
||||
{
|
||||
$dbh->do("DELETE FROM faq WHERE faqid=$id");
|
||||
$ret .= "FAQ item deleted.";
|
||||
|
||||
# TODO: delete translation from ml_* ?
|
||||
}
|
||||
}
|
||||
|
||||
return $ret;
|
||||
|
||||
_code?>
|
||||
|
||||
<=body
|
||||
page?><?_c <LJDEP>
|
||||
lib: cgi-bin/ljlib.pl
|
||||
link: htdocs/admin/faq/index.bml
|
||||
</LJDEP> _c?>
|
||||
67
livejournal/htdocs/admin/faq/index.bml
Executable file
@@ -0,0 +1,67 @@
|
||||
<?_info
|
||||
nocache=>1
|
||||
_info?><?page
|
||||
title=>FAQ
|
||||
body<=
|
||||
|
||||
<?_code
|
||||
|
||||
my $dbh = LJ::get_db_writer();
|
||||
|
||||
my $remote = LJ::get_remote();
|
||||
my %ac_add;
|
||||
my %ac_edit;
|
||||
LJ::remote_has_priv($remote, "faqadd", \%ac_add);
|
||||
LJ::remote_has_priv($remote, "faqedit", \%ac_edit);
|
||||
|
||||
$ret = "";
|
||||
if (%ac_add)
|
||||
{
|
||||
$ret .= "<A HREF=\"faqedit.bml\">[Add to FAQ]</A>\n";
|
||||
}
|
||||
|
||||
my %faqcat;
|
||||
my %faqq;
|
||||
$sth = $dbh->prepare("SELECT faqcat, faqcatname, catorder FROM faqcat");
|
||||
$sth->execute;
|
||||
while ($_ = $sth->fetchrow_hashref)
|
||||
{
|
||||
$faqcat{$_->{'faqcat'}} = $_;
|
||||
}
|
||||
|
||||
$sth = $dbh->prepare("SELECT faqid, question, sortorder, faqcat, lastmodtime FROM faq");
|
||||
$sth->execute;
|
||||
while ($_ = $sth->fetchrow_hashref)
|
||||
{
|
||||
$faqq{$_->{'faqcat'}}->{$_->{'faqid'}} = $_;
|
||||
}
|
||||
|
||||
foreach my $faqcat (sort { $faqcat{$a}->{'catorder'} <=> $faqcat{$b}->{'catorder'} } keys %faqcat)
|
||||
{
|
||||
$ret .= "<H2><A HREF=\"readcat.bml?faqcat=$faqcat\">" . LJ::ehtml($faqcat{$faqcat}->{'faqcatname'}) . "</A></H2>\n";
|
||||
$ret .= "<UL>\n";
|
||||
foreach my $faqid (sort { $faqq{$faqcat}->{$a}->{'sortorder'} <=> $faqq{$faqcat}->{$b}->{'sortorder'} } keys %{$faqq{$faqcat}})
|
||||
{
|
||||
my $fe = $faqq{$faqcat}->{$faqid};
|
||||
next unless ($fe->{'question'});
|
||||
my $q = LJ::ehtml($fe->{'question'});
|
||||
$q =~ s/^\s+//; $q =~ s/\s+$//;
|
||||
$q =~ s/\n/<BR>/g;
|
||||
$ret .= "<LI>";
|
||||
if ($ac_edit{'*'} || $ac_edit{$faqcat}) {
|
||||
$ret .= "<A HREF=\"faqedit.bml?id=$faqid\">[edit]</A> ($fe->{'sortorder'}) ";
|
||||
}
|
||||
$ret .= "<B>{$faqid}</B> $q\n";
|
||||
}
|
||||
$ret .= "</UL>\n";
|
||||
}
|
||||
|
||||
return $ret;
|
||||
|
||||
_code?>
|
||||
|
||||
<=body
|
||||
page?><?_c <LJDEP>
|
||||
lib: cgi-bin/ljlib.pl
|
||||
link: htdocs/admin/faq/readcat.bml, htdocs/admin/faq/faqedit.bml
|
||||
</LJDEP> _c?>
|
||||
63
livejournal/htdocs/admin/faq/readcat.bml
Executable file
@@ -0,0 +1,63 @@
|
||||
<?_info
|
||||
nocache=>1
|
||||
_info?><?page
|
||||
title=>Read FAQ
|
||||
body<=
|
||||
|
||||
<CENTER>
|
||||
<A HREF="./"><B>(Back to FAQ Index)</B></A>
|
||||
</CENTER>
|
||||
|
||||
<?_code
|
||||
|
||||
my $dbh = LJ::get_db_writer();
|
||||
|
||||
$ret = "";
|
||||
|
||||
my $qfaqcat = $dbh->quote($FORM{'faqcat'});
|
||||
|
||||
my %faqcat;
|
||||
my %faqq;
|
||||
$sth = $dbh->prepare("SELECT faqcat, faqcatname, catorder FROM faqcat WHERE faqcat=$qfaqcat");
|
||||
$sth->execute;
|
||||
while ($_ = $sth->fetchrow_hashref)
|
||||
{
|
||||
$faqcat{$_->{'faqcat'}} = $_;
|
||||
}
|
||||
|
||||
$sth = $dbh->prepare("SELECT faqid, question, sortorder, faqcat, answer, lastmodtime FROM faq WHERE faqcat=$qfaqcat");
|
||||
$sth->execute;
|
||||
while ($_ = $sth->fetchrow_hashref)
|
||||
{
|
||||
$faqq{$_->{'faqid'}} = $_;
|
||||
}
|
||||
|
||||
foreach my $faqcat (sort { $faqcat{$a}->{'catorder'} <=> $faqcat{$b}->{'catorder'} } keys %faqcat)
|
||||
{
|
||||
$ret .= "<h2>" . LJ::ehtml($faqcat{$faqcat}->{'faqcatname'}) . "</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;
|
||||
my $a = LJ::ehtml($faqq{$faqid}->{'answer'});
|
||||
$a =~ s/^\s+//; $a =~ s/\s+$//;
|
||||
$a =~ s/\n( +)/"\n" . " "x length($1)/eg;
|
||||
$a =~ s!\n!<br />!g;
|
||||
$ret .= "<p><table bgcolor='#c0c0c0'><tr><td><b>$q</b></td></tr></table>" . LJ::auto_linkify($a);
|
||||
}
|
||||
$ret .= "</ul>\n";
|
||||
}
|
||||
|
||||
return $ret;
|
||||
|
||||
_code?>
|
||||
|
||||
<=body
|
||||
page?><?_c <LJDEP>
|
||||
lib: cgi-bin/ljlib.pl
|
||||
link: htdocs/admin/faq/index.bml
|
||||
</LJDEP> _c?>
|
||||
150
livejournal/htdocs/admin/fileedit/index.bml
Executable file
@@ -0,0 +1,150 @@
|
||||
<?_code
|
||||
|
||||
my ($ret, $sth);
|
||||
|
||||
my $DEF_ROW = 30;
|
||||
my $DEF_COL = 80;
|
||||
|
||||
my $remote = LJ::get_remote();
|
||||
|
||||
my %files = (); # keys: files remote user has access to, value: 1
|
||||
my $INC_DIR = $LJ::BML_INC_DIR_ADMIN || $LJ::BML_INC_DIR || "$LJ::HTDOCS/inc";
|
||||
|
||||
unless (LJ::remote_has_priv($remote, "fileedit", \%files)) {
|
||||
return "You don't have access to edit any files, or you're not logged in.";
|
||||
}
|
||||
|
||||
my $valid_filename = sub
|
||||
{
|
||||
my $filename = shift;
|
||||
return ($filename =~ /^[a-zA-Z0-9-\_]{1,80}$/);
|
||||
};
|
||||
|
||||
my $save_file = sub
|
||||
{
|
||||
my ($filename, $content) = @_;
|
||||
return 0 unless $valid_filename->($filename);
|
||||
|
||||
if ($LJ::FILEEDIT_VIA_DB || $LJ::FILEEDIT_VIA_DB{$filename}) {
|
||||
my $dbh = LJ::get_db_writer();
|
||||
$dbh->do("REPLACE INTO includetext (incname, inctext, updatetime) ".
|
||||
"VALUES (?, ?, UNIX_TIMESTAMP())", undef, $filename, $content);
|
||||
return 0 if $dbh->err;
|
||||
LJ::MemCache::set("includefile:$filename", $content);
|
||||
return 1;
|
||||
}
|
||||
|
||||
open (FILE, ">$INC_DIR/$filename") or return 0;
|
||||
print FILE $content;
|
||||
close FILE;
|
||||
return 1;
|
||||
};
|
||||
|
||||
my $load_file = sub
|
||||
{
|
||||
my ($filename) = @_;
|
||||
return undef unless $valid_filename->($filename);
|
||||
|
||||
my $contents;
|
||||
if ($LJ::FILEEDIT_VIA_DB || $LJ::FILEEDIT_VIA_DB{$filename}) {
|
||||
my $dbh = LJ::get_db_writer();
|
||||
$contents = $dbh->selectrow_array("SELECT inctext FROM includetext WHERE incname=?", undef, $filename);
|
||||
return $contents if defined $contents;
|
||||
}
|
||||
|
||||
open (FILE, "$INC_DIR/$filename") or return undef;
|
||||
while (<FILE>) { $contents .= $_; }
|
||||
close FILE;
|
||||
return $contents;
|
||||
};
|
||||
|
||||
if ($files{'*'})
|
||||
{
|
||||
# if user has access to edit all files, find what those files are!
|
||||
delete $files{'*'};
|
||||
opendir (DIR, $INC_DIR);
|
||||
while (my $file = readdir(DIR)) {
|
||||
$files{$file} = 1;
|
||||
}
|
||||
closedir (DIR);
|
||||
}
|
||||
|
||||
## get rid of files that don't match our safe pattern
|
||||
{
|
||||
my @del;
|
||||
foreach my $k (keys %files) {
|
||||
push @del, $k
|
||||
unless $valid_filename->($k);
|
||||
}
|
||||
foreach my $k (@del) { delete $files{$k}; }
|
||||
}
|
||||
|
||||
my $mode = $FORM{'mode'};
|
||||
unless ($mode) {
|
||||
$mode = $FORM{'file'} ? "edit" : "pick";
|
||||
}
|
||||
|
||||
if ($mode eq "pick")
|
||||
{
|
||||
$ret .= "<FORM METHOD=GET>\n";
|
||||
$ret .= "Pick file to edit: <SELECT NAME=\"file\">";
|
||||
foreach my $file (sort keys %files) {
|
||||
$ret .= "<OPTION VALUE=\"$file\">$file\n";
|
||||
}
|
||||
$ret .= "</SELECT> <INPUT TYPE=SUBMIT VALUE=\"load...\"><BR>";
|
||||
$ret .= "Wordwrap? <INPUT TYPE=CHECKBOX VALUE=1 NAME=w> ";
|
||||
$ret .= "Rows: <INPUT SIZE=3 NAME=r VALUE=$DEF_ROW> ";
|
||||
$ret .= "Cols: <INPUT SIZE=3 NAME=c VALUE=$DEF_COL> ";
|
||||
$ret .= "</FORM>";
|
||||
return $ret;
|
||||
}
|
||||
|
||||
my $file = $FORM{'file'};
|
||||
unless ($files{$file}) {
|
||||
return "<B>ERROR!</B> you don't have access to this document.";
|
||||
}
|
||||
|
||||
if ($mode eq "edit")
|
||||
{
|
||||
$ret .= "<B>Editing:</B> <tt>$file</tt><P>";
|
||||
my $contents = $load_file->($file);
|
||||
|
||||
return "<B>Error:</B> Couldn't open file"
|
||||
unless defined $contents;
|
||||
|
||||
my $r = ($FORM{'r'}+0) || $DEF_ROW;
|
||||
my $c = ($FORM{'c'}+0) || $DEF_COL;
|
||||
my $wrap = $FORM{'w'} ? "SOFT" : "OFF";
|
||||
|
||||
$ret .= "<FORM METHOD=POST>\n";
|
||||
$ret .= "<INPUT TYPE=HIDDEN NAME=mode VALUE=\"save\">";
|
||||
$ret .= "<INPUT TYPE=HIDDEN NAME=file VALUE=\"$file\">";
|
||||
$ret .= "<TEXTAREA ROWS=$r COLS=$c WRAP=$wrap NAME=contents>";
|
||||
$ret .= BML::eall($contents);
|
||||
$ret .= "</TEXTAREA><P><INPUT TYPE=SUBMIT VALUE=\"Save\"> (no undo.. are you sure?)";
|
||||
$ret .= "</FORM>\n";
|
||||
return $ret;
|
||||
}
|
||||
|
||||
if ($mode eq "save")
|
||||
{
|
||||
unless (LJ::did_post()) {
|
||||
return "<b>Error:</b> requires post";
|
||||
}
|
||||
|
||||
$ret .= "<B>Saving:</B> <tt>$file</tt><p>";
|
||||
if ($save_file->($file, $FORM{'contents'})) {
|
||||
$ret .= "saved.";
|
||||
} else {
|
||||
$ret .= "<b>Error saving</b>";
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
return "unknown mode";
|
||||
|
||||
_code?><?_c <LJDEP>
|
||||
lib: cgi-bin/ljlib.pl
|
||||
form: htdocs/admin/fileedit/index.bml
|
||||
post: htdocs/admin/fileedit/index.bml
|
||||
</LJDEP> _c?>
|
||||
170
livejournal/htdocs/admin/memcache.bml
Executable file
@@ -0,0 +1,170 @@
|
||||
<?_code
|
||||
{
|
||||
#line 3
|
||||
use strict;
|
||||
no strict 'refs';
|
||||
use vars qw(%GET);
|
||||
use Data::Dumper;
|
||||
use Time::HiRes ();
|
||||
|
||||
my $u = LJ::get_remote();
|
||||
return "You must be logged in to view this tool." unless $u;
|
||||
return "You don't have 'siteadmin' priv." unless LJ::check_priv($u, "siteadmin");
|
||||
|
||||
my $prev_hits = $u ? LJ::MemCache::get([$u->{'userid'},"mcrate:$u->{'userid'}"]) : undef;
|
||||
|
||||
my $ret;
|
||||
|
||||
my $mode = $GET{'mode'};
|
||||
if ($GET{'host'}) {
|
||||
$mode ||= "host";
|
||||
}
|
||||
$mode ||= "overview";
|
||||
|
||||
$ret .= "<div class='topbar'>[<a href='memcache.bml'>Overview</a>]\n";
|
||||
|
||||
if ($mode eq "overview") {
|
||||
$ret .= <<"END_TOP";
|
||||
</div>
|
||||
<h1>Memory Cache Overview</h1>
|
||||
<table border='1' cellpadding='5'>
|
||||
<tr><th>Host</th><th>Hit Rate</th><th>Curr/Max Size</th><th><span title='Utilization'>Utlz %</span></th><th>Uptime</th><th>Version</th></tr>
|
||||
END_TOP
|
||||
}
|
||||
|
||||
my %now_hits;
|
||||
if ($prev_hits) { %now_hits = %$prev_hits; }
|
||||
|
||||
my ($tot_hits, $tot_misses) = ();
|
||||
|
||||
foreach my $entry (@LJ::MEMCACHE_SERVERS) {
|
||||
my $host = ref $entry ? $entry->[0] : $entry;
|
||||
next if $mode eq "host" && $host ne $GET{'host'};
|
||||
|
||||
LJ::MemCache::forget_dead_hosts();
|
||||
my $sock = Cache::Memcached::sock_to_host($host);
|
||||
|
||||
my $t1 = Time::HiRes::time();
|
||||
|
||||
my $log;
|
||||
my %stat;
|
||||
my @cmds = ("", "malloc", "items", "slabs");
|
||||
my $cmd;
|
||||
if ($sock) {
|
||||
while (defined($cmd = shift @cmds)) {
|
||||
my $realcmd = "stats" . ($cmd ? " $cmd" : "");
|
||||
$log .= "<b>$realcmd</b>\n";
|
||||
foreach (LJ::MemCache::run_command($sock, "$realcmd\r\n")) {
|
||||
last if $_ eq "END\r\n";
|
||||
$log .= $_;
|
||||
next if $cmd eq "maps";
|
||||
if (/^STAT (\S+) (\S+)/) {
|
||||
$stat{$cmd}{$1} = $2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
my $t2 = Time::HiRes::time();
|
||||
|
||||
my $cpu = 0;
|
||||
foreach my $key (qw(rusage_user rusage_system)) {
|
||||
my $sec = $stat{''}{$key};
|
||||
$sec =~ s/:/\./;
|
||||
$cpu += $sec;
|
||||
#$ret .= "Host $host was $stat{''}{$key} = $sec, cpu = $cpu<br />\n";
|
||||
}
|
||||
|
||||
$now_hits{$host} = [ $stat{''}{'get_hits'}, $stat{''}{'get_misses'}, $cpu ];
|
||||
|
||||
my $hit_rate = sprintf("%0.02f%%", $stat{''}{'get_hits'}/($stat{''}{'get_hits'}+$stat{''}{'get_misses'}||1)*100);
|
||||
|
||||
if ($mode eq "overview") {
|
||||
$ret .= "<tr><td><a href='memcache.bml?host=$host'>$host</a></td>\n";
|
||||
$ret .= "<td>$hit_rate";
|
||||
if ($prev_hits && $prev_hits->{$host}) {
|
||||
my $nh = $now_hits{$host};
|
||||
my $ph = $prev_hits->{$host};
|
||||
|
||||
my $new_hits = $now_hits{$host}[0] - $prev_hits->{$host}[0];
|
||||
my $new_misses = $now_hits{$host}[1] - $prev_hits->{$host}[1];
|
||||
$tot_hits += $new_hits;
|
||||
$tot_misses += $new_misses;
|
||||
my $new_whatev = $new_hits + $new_misses;
|
||||
my $new_rate = $new_hits / ($new_whatev || 1);
|
||||
|
||||
my $cpu = sprintf("%0.6f", $nh->[2] - $ph->[2]);
|
||||
$ret .= sprintf(" [%0.02f%% {$new_whatev} $cpu]", $new_rate * 100);
|
||||
}
|
||||
$ret .= sprintf(" %0.02f", $t2-$t1);
|
||||
$ret .= "</td>";
|
||||
my $gb_used = ($stat{'malloc'}{'mmapped_space'} + $stat{'malloc'}{'arena_size'}) / (1024*1024*1024);
|
||||
my $gb_max = $stat{''}{'limit_maxbytes'} / (1024*1024*1024);
|
||||
if ($gb_used >= $gb_max) {
|
||||
$ret .= sprintf("<td align='center'>%0.01fG</td>", $gb_max);
|
||||
} else {
|
||||
$ret .= sprintf("<td>%0.02f/%0.01fG (%0.02f%%)</td>", $gb_used, $gb_max, $gb_used*100/($gb_max||1));
|
||||
}
|
||||
|
||||
my $utiliz = $stat{''}{'bytes'} /
|
||||
(($stat{'malloc'}{'mmapped_space'} + $stat{'malloc'}{'arena_size'}) || 1);
|
||||
$ret .= sprintf("<td>%0.02f%%</td>", $utiliz*100);
|
||||
|
||||
my $up = $stat{''}{'uptime'};
|
||||
my $upstring;
|
||||
foreach my $u ([86400,"d"],[3600,"h"],[60,"m"],[1,"s"]) {
|
||||
if ($up / $u->[0] > 1) {
|
||||
my $v = int($up / $u->[0]);
|
||||
$upstring .= "${v}$u->[1] ";
|
||||
$up -= $v * $u->[0];
|
||||
}
|
||||
}
|
||||
$ret .= "<td>$upstring</td>";
|
||||
$ret .= "<td>$stat{''}{'version'}</td>";
|
||||
$ret .= "</tr>";
|
||||
}
|
||||
|
||||
if ($mode eq "host" && $host eq $GET{'host'}) {
|
||||
$ret .= "[<a href='memcache.bml?host=$host&mode=raw'>Raw Data</a>]</div>";
|
||||
$ret .= "<h1>Details for $host</h1>";
|
||||
|
||||
$ret .= "<h2>Slab classes</h2>";
|
||||
$ret .= "<table border='1' cellpadding='2'>";
|
||||
$ret .= "<tr><th>class</th><th>size</th><th>used</th><th>total</th><th colspan='2'>free</th><th>pages</th><th>max age</th></tr>\n";
|
||||
foreach my $cls (0..31) {
|
||||
my $size = $stat{'slabs'}{"$cls:chunk_size"};
|
||||
next unless $size;
|
||||
$ret .= "<tr><td>$cls</td>"
|
||||
. join('', map { "<td>" . $stat{'slabs'}{"$cls:$_"} . "</td>" }
|
||||
qw(chunk_size used_chunks total_chunks free_chunks free_chunks_end total_pages));
|
||||
my $age = $stat{'items'}{"items:$cls:age"};
|
||||
$ret .= "<td>$age</td>";
|
||||
$ret .= "</tr>";
|
||||
}
|
||||
$ret .= "</table>\n";
|
||||
|
||||
}
|
||||
|
||||
if ($mode eq "raw" && $host eq $GET{'host'}) {
|
||||
$ret .= "[<a href='memcache.bml?host=$host'>Host Stats</a>]</div>";
|
||||
$ret .= "<h1>Raw data for $host</h1>";
|
||||
$ret .= "<pre>$log</pre>";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
LJ::MemCache::set([$u->{'userid'},"mcrate:$u->{'userid'}"], \%now_hits)
|
||||
if $u;
|
||||
|
||||
if ($mode eq "overview") {
|
||||
$ret .= "</table>\n";
|
||||
|
||||
my $new_whatev = $tot_hits + $tot_misses;
|
||||
my $new_rate = $tot_hits / ($new_whatev || 1);
|
||||
$ret .= sprintf("Global [%0.02f%% {$new_whatev}]", $new_rate * 100);
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
_code?>
|
||||
|
||||
275
livejournal/htdocs/admin/memcache_view.bml
Executable file
@@ -0,0 +1,275 @@
|
||||
<html>
|
||||
<head><title>Memcache view</title>
|
||||
<body>
|
||||
<?_code
|
||||
|
||||
use strict;
|
||||
use vars qw(%GET %POST);
|
||||
use Data::Dumper;
|
||||
my $ret;
|
||||
|
||||
|
||||
my $remote = LJ::get_remote();
|
||||
|
||||
return "<b>Error:</b> You don't have access to viewing memcache info."
|
||||
unless (LJ::check_priv($remote, "siteadmin", "memcacheview"));
|
||||
|
||||
return "<b>Error:</b> No memcache servers defined."
|
||||
unless @LJ::MEMCACHE_SERVERS;
|
||||
|
||||
my $uid = sub {
|
||||
my $u = LJ::load_user(shift);
|
||||
return $u ? $u->{'userid'} : "";
|
||||
};
|
||||
my $cuid = sub {
|
||||
my $u = LJ::load_user(shift);
|
||||
return $u ? "$u->{'clusterid'}:$u->{'userid'}" : "";
|
||||
};
|
||||
|
||||
# key: unique prefix of a memcache key
|
||||
# value: number n, means the n-th component of the key when
|
||||
# split by ':' is the hash key. 0 means no hash key.
|
||||
# the default, when absent from this hash, is "n=2 if the 2nd component
|
||||
# is a number".
|
||||
|
||||
my %MEMC_HASHKEYS = (
|
||||
'uidof:' => 0,
|
||||
'talksubject:' => 3,
|
||||
'talkbody:' => 3,
|
||||
'logtext:' => 3,
|
||||
's1pubstyc:' => 0,
|
||||
'popsyn:' => 0,
|
||||
'rate_eperr:' => 0,
|
||||
'rate:' => 0,
|
||||
'ml.' => 0,
|
||||
);
|
||||
|
||||
my $get_hashkey = sub {
|
||||
my $key = shift;
|
||||
return undef unless $key;
|
||||
|
||||
my $hk;
|
||||
my $component;
|
||||
|
||||
foreach (keys %MEMC_HASHKEYS) {
|
||||
if ($key =~ /^$_/) {
|
||||
$component = $MEMC_HASHKEYS{$_};
|
||||
}
|
||||
}
|
||||
return undef if defined ($component) and $component == 0;
|
||||
my $sep = ':';
|
||||
$sep = '.' if $key =~ /userpic\./; #special case
|
||||
my @els = split (/\Q$sep\E/, $key);
|
||||
$hk = $els[defined($component) ? $component-1 : 2-1];
|
||||
$hk = undef
|
||||
unless defined($component) || int($hk)==$hk;
|
||||
return $hk;
|
||||
};
|
||||
|
||||
my $display = sub {
|
||||
my ($key, $val) = @_;
|
||||
|
||||
# first, transform array->hash if necessary
|
||||
$val = LJ::MemCache::array_to_hash("user", $val)
|
||||
if $key =~ /^user:/
|
||||
or $key =~ /^userid:/;
|
||||
|
||||
# blot out passwords
|
||||
if (ref $val eq 'HASH' && defined($val->{'password'})) {
|
||||
$val->{'password'} = '*' x 8;
|
||||
}
|
||||
|
||||
# unpack packed data
|
||||
if ($key =~ /^talk2:/) {
|
||||
my $newval;
|
||||
my $n = (length($val) - 1) / 16;
|
||||
for (my $i=0; $i<$n; $i++) {
|
||||
my ($f1, $par, $poster, $time) = unpack("NNNN",substr($val,$i*16+1,16));
|
||||
my $state = chr($f1 & 255);
|
||||
my $talkid = $f1 >> 8;
|
||||
$newval->{$talkid} = {
|
||||
talkid => $talkid,
|
||||
state => $state,
|
||||
posterid => $poster,
|
||||
datepost => LJ::mysql_time($time),
|
||||
parenttalkid => $par,
|
||||
};
|
||||
}
|
||||
$val = [substr($val,0,1), $newval];
|
||||
}
|
||||
|
||||
if ($key =~ /^log2:/) {
|
||||
my $item = {};
|
||||
@$item{'posterid', 'eventtime', 'logtime', 'allowmask', 'ditemid'} = unpack("NNNNN", $val);
|
||||
$item->{'security'} = ($item->{'allowmask'} == 0 ? 'private' :
|
||||
($item->{'allowmask'} == 2**31 ? 'public' : 'usemask'));
|
||||
@$item{'jitemid', 'anum'} = ($item->{'ditemid'} >> 8, $item->{'ditemid'} % 256);
|
||||
$item->{'eventtime'} = LJ::mysql_time($item->{'eventtime'}, 1);
|
||||
$item->{'logtime'} = LJ::mysql_time($item->{'logtime'}, 1);
|
||||
$val = $item;
|
||||
}
|
||||
|
||||
if ($key =~ /^log2lt:/) {
|
||||
my $items = [];
|
||||
my $ver = substr($val, 0, 1);
|
||||
my $offset = {1=>1, 2=>5, 3=>5}->{$ver};
|
||||
my $newval;
|
||||
|
||||
push @$newval, $ver;
|
||||
push @$newval, unpack("N", substr($val, 1, 4))
|
||||
if $ver>=2;
|
||||
|
||||
my $n = (length($val) - $offset )/20;
|
||||
for (my $i=0; $i<$n; $i++) {
|
||||
my ($posterid, $eventtime, $rlogtime, $allowmask, $ditemid) =
|
||||
unpack("NNNNN", substr($val, $i*20+$offset, 20));
|
||||
$eventtime = LJ::mysql_time($eventtime, 1);
|
||||
my $security = $allowmask == 0 ? 'private' :
|
||||
($allowmask == 2**31 ? 'public' : 'usemask');
|
||||
my ($jitemid, $anum) = ($ditemid >> 8, $ditemid % 256);
|
||||
my $item = {};
|
||||
@$item{'posterid','eventtime','rlogtime','allowmask','ditemid',
|
||||
'security', 'jitemid', 'anum'} =
|
||||
($posterid, $eventtime, $rlogtime, $allowmask,
|
||||
$ditemid, $security, $jitemid, $anum);
|
||||
push @$items, $item;
|
||||
}
|
||||
push @$newval, $items;
|
||||
$val = $newval;
|
||||
}
|
||||
|
||||
if ($key =~ /^fgrp:/) {
|
||||
my $newval = [];
|
||||
my $ver = shift @$val;
|
||||
push @$newval, $ver;
|
||||
foreach(@$val) {
|
||||
push @$newval, LJ::MemCache::array_to_hash("fgrp", [$ver, @$_]);
|
||||
}
|
||||
$val = $newval;
|
||||
}
|
||||
|
||||
if ($key =~ /^upicinf:(\d+)$/) {
|
||||
my $userid = $1;
|
||||
my ($ver, $picstr, $kwstr) = @$val;
|
||||
my $info = {
|
||||
'version' => $ver,
|
||||
'pic' => {},
|
||||
'kw' => {},
|
||||
};
|
||||
|
||||
while (length $picstr >= 7) {
|
||||
my $pic = { userid => $userid };
|
||||
($pic->{picid},
|
||||
$pic->{width}, $pic->{height},
|
||||
$pic->{state}) = unpack "NCCA", substr($picstr, 0, 7, '');
|
||||
$info->{pic}{$pic->{picid}} = $pic;
|
||||
}
|
||||
|
||||
my ($pos, $nulpos);
|
||||
$pos = $nulpos = 0;
|
||||
while (($nulpos = index($kwstr, "\0", $pos)) > 0) {
|
||||
my $kw = substr($kwstr, $pos, $nulpos-$pos);
|
||||
my $id = unpack("N", substr($kwstr, $nulpos+1, 4));
|
||||
$pos = $nulpos + 5; # skip NUL + 4 bytes.
|
||||
$info->{kw}{$kw} = $info->{pic}{$id} if $info;
|
||||
}
|
||||
$val = $info;
|
||||
}
|
||||
|
||||
if ($key =~ /^friends:/) {
|
||||
my $ver = substr($val, 0, 1, '');
|
||||
my $packfmt = "NH6H6NC";
|
||||
my $packlen = 15;
|
||||
my @cols = qw(friendid fgcolor bgcolor groupmask showbydefault);
|
||||
my %friends;
|
||||
|
||||
while (length($val) >= $packlen) {
|
||||
my @row = unpack($packfmt, substr($val, 0, $packlen, ''));
|
||||
|
||||
# add "#" to beginning of colors
|
||||
$row[$_] = "\#$row[$_]" foreach 1..2;
|
||||
|
||||
# turn unpacked row into hashref
|
||||
my $fid = $row[0];
|
||||
my $idx = 1;
|
||||
foreach my $col (@cols[1..$#cols]) {
|
||||
$friends{$fid}->{$col} = $row[$idx];
|
||||
$idx++;
|
||||
}
|
||||
}
|
||||
$val = [$ver, \%friends];
|
||||
}
|
||||
|
||||
if ($key =~ /^tu:/) {
|
||||
$val = unpack("N", $val);
|
||||
}
|
||||
# just in case this remains a packed scalar
|
||||
if (not ref $val) {
|
||||
$val =~ s/([\x00-\x1f])/sprintf("\\x%02x", $1)/eg;
|
||||
}
|
||||
$ret .= "<b>Data: </b>";
|
||||
|
||||
my $dumper = Data::Dumper->new([$val],["Value"]);
|
||||
$dumper->Terse(1);
|
||||
$dumper->Indent(2);
|
||||
my $d = $dumper->Dump();
|
||||
|
||||
$ret.= "<pre>" . LJ::ehtml($d) . "</pre>";
|
||||
|
||||
return;
|
||||
};
|
||||
|
||||
|
||||
if ($POST{'query'}) {
|
||||
foreach my $key (split(/\r\n/, $POST{'query'})) {
|
||||
|
||||
next unless $key =~ /\S/;
|
||||
# shortcuts
|
||||
$key =~ s/(##)(\w+)/$cuid->($2)/eg;
|
||||
$key =~ s/(#)(\w+)/$uid->($2)/eg;
|
||||
$key =~ s!\((\d+)\)!int($1/256)!eg;
|
||||
|
||||
my $sock = LJ::MemCache::_get_sock($key);
|
||||
$ret .= "<p><b>Key: </b>$key<br />";
|
||||
|
||||
unless ($sock) {
|
||||
$ret .= "<b>Error: </b>Could not connect to server<br /></p>";
|
||||
next;
|
||||
}
|
||||
|
||||
if ($POST{'sock'}) {
|
||||
$ret .= "<b>Socket:</b> $sock<br />";
|
||||
}
|
||||
|
||||
my $hashkey = $get_hashkey->($key);
|
||||
if ($hashkey) {
|
||||
$ret .= "<b>Hashkey:</b> $hashkey<br />";
|
||||
}
|
||||
my $pars = defined($hashkey) ? [$hashkey, $key] : $key;
|
||||
my $val = LJ::MemCache::get($pars);
|
||||
unless (defined $val) {
|
||||
$ret .= "<b>Data:</b> not found</br ></p>";
|
||||
next;
|
||||
}
|
||||
$display->($key, $val);
|
||||
$ret .= "</p>";
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
$ret .= "<p>Enter your memcache query(-ies) below.</p>";
|
||||
$ret .= '<p>Here\'s the <a href="http://cvs.livejournal.org/browse.cgi/livejournal/doc/raw/memcache-keys.txt?rev=.&content-type=text/x-cvsweb-markup">reference</a> of key names.</p>';
|
||||
$ret .= "<p>Shortcuts: <blockquote>#username -> userid<br /> ##username -> cid:userid<br />(number) -> number/256 </blockquote></p>";
|
||||
|
||||
$ret .= '<form method="post" action="memcache_view.bml">';
|
||||
$ret .= "<textarea name=query rows=3 cols=60 wrap=off></textarea> ";
|
||||
$ret .= "<p>" . LJ::html_check({ 'type' => 'check', 'name' => 'sock', 'id' => 'sock' });
|
||||
$ret .= "<label for='sock'>Show host/port per key.</label></p>";
|
||||
|
||||
$ret .= "<input type='submit' value='Submit'>";
|
||||
return $ret;
|
||||
|
||||
|
||||
_code?>
|
||||
</body>
|
||||
</html>
|
||||
129
livejournal/htdocs/admin/mysql_status.bml
Executable file
@@ -0,0 +1,129 @@
|
||||
<?_code
|
||||
|
||||
my $format = $FORM{'format'} || "html";
|
||||
|
||||
my $remote = LJ::get_remote();
|
||||
return"<b>Error:</b> You don't have access to administer databases."
|
||||
unless (LJ::check_priv($remote, "siteadmin", "mysqlstatus"));
|
||||
|
||||
my $dbh = LJ::get_db_writer();
|
||||
|
||||
if ($format eq "text") {
|
||||
BML::set_content_type("text/plain");
|
||||
}
|
||||
|
||||
my ($sth, $ret);
|
||||
|
||||
if ($format eq "html") {
|
||||
$ret .= "<style>\ntd { font-family: arial; font-size: 11px };\n</style>\n";
|
||||
}
|
||||
|
||||
my @modes = qw(status variables tables);
|
||||
my $mode = $FORM{'mode'} || "status";
|
||||
foreach my $m (@modes) {
|
||||
if ($mode eq $m) {
|
||||
$mode = $m;
|
||||
$ret .= "<b>[ $mode ]</b> " if ($format eq "html");
|
||||
} else {
|
||||
if ($format eq "html") {
|
||||
$ret .= "<b>[</b> <a href=\"" . BML::self_link({'mode' => $m});
|
||||
$ret .= "\">$m</a> <b>]</b> ";
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($format eq "html") {
|
||||
$ret .= "<p>Or, view <a href=\"mysql_status.bml?mode=$mode&format=text\">as text</a>.<p>";
|
||||
}
|
||||
|
||||
if ($mode eq "status")
|
||||
{
|
||||
$sth = $dbh->prepare("SHOW STATUS");
|
||||
$sth->execute;
|
||||
my %s;
|
||||
while (my ($k, $v) = $sth->fetchrow_array) {
|
||||
$s{$k} = $v;
|
||||
}
|
||||
|
||||
$sth = $dbh->prepare("SHOW STATUS");
|
||||
$sth->execute;
|
||||
if ($format eq "html") {
|
||||
$ret .= "<table cellpadding=2 border=1 cellspacing=1>";
|
||||
}
|
||||
while (my ($k, $v) = $sth->fetchrow_array) {
|
||||
my $delta = $v - $s{$k};
|
||||
if ($delta == 0) {
|
||||
$delta = "";
|
||||
} elsif ($delta > 0) {
|
||||
$delta = "+$delta";
|
||||
} else {
|
||||
$delta = "-$delta";
|
||||
}
|
||||
if ($format eq "html") {
|
||||
$ret .= "<tr><td><b>$k</b></td><td>$v</td><td>$delta</td></tr>\n";
|
||||
} elsif ($format eq "text") {
|
||||
$ret .= "$k,$v,$delta\n";
|
||||
}
|
||||
}
|
||||
$ret .= "</table>\n" if ($format eq "html");
|
||||
return $ret;
|
||||
}
|
||||
|
||||
if ($mode eq "variables")
|
||||
{
|
||||
$sth = $dbh->prepare("SHOW VARIABLES");
|
||||
$sth->execute;
|
||||
|
||||
$ret .= "<table cellpadding=2 border=1 cellspacing=1>" if ($format eq "html");
|
||||
while (my ($k, $v) = $sth->fetchrow_array) {
|
||||
if ($format eq "html") {
|
||||
$ret .= "<tr><td><b>$k</b></td><td>$v</td></tr>\n";
|
||||
} else {
|
||||
$ret .= "$k,$v\n";
|
||||
}
|
||||
}
|
||||
$ret .= "</table>\n" if ($format eq "html");
|
||||
return $ret;
|
||||
}
|
||||
|
||||
if ($mode eq "tables")
|
||||
{
|
||||
$sth = $dbh->prepare("SHOW TABLE STATUS");
|
||||
$sth->execute;
|
||||
|
||||
if ($format eq "html") {
|
||||
$ret .= "<table cellpadding=2 border=1 cellspacing=1>";
|
||||
$ret .= "<tr>";
|
||||
}
|
||||
my @cols = @{$sth->{'NAME'}};
|
||||
foreach (@cols) {
|
||||
if ($format eq "html") {
|
||||
$ret .= "<td><b>$_</b></td>";
|
||||
} else {
|
||||
$ret .= "$_,";
|
||||
}
|
||||
}
|
||||
if ($format eq "html") {
|
||||
$ret .= "</tr>\n";
|
||||
} else {
|
||||
$ret .= "\n";
|
||||
}
|
||||
while (my $t = $sth->fetchrow_hashref) {
|
||||
$ret .= "<tr>" if ($format eq "html");
|
||||
foreach my $c (@cols) {
|
||||
if ($format eq "html") {
|
||||
$ret .= "<td>$t->{$c}</td>";
|
||||
} elsif ($format eq "text") {
|
||||
$ret .= "$t->{$c},";
|
||||
}
|
||||
}
|
||||
if ($format eq "html") {
|
||||
$ret .= "</tr>";
|
||||
} elsif ($format eq "text") {
|
||||
$ret .= "\n";
|
||||
}
|
||||
}
|
||||
$ret .= "</table>\n" if ($format eq "html");
|
||||
return $ret;
|
||||
}
|
||||
|
||||
_code?>
|
||||
338
livejournal/htdocs/admin/priv/index.bml
Executable file
@@ -0,0 +1,338 @@
|
||||
<html><head>
|
||||
<meta name="robots" content="noindex, nofollow, noarchive" />
|
||||
<meta name="googlebot" content="nosnippet" />
|
||||
<title>Privilege Management</title>
|
||||
</head><body>
|
||||
<?_code
|
||||
|
||||
use strict;
|
||||
use vars qw(%FORM);
|
||||
|
||||
my $dbh = LJ::get_db_writer;
|
||||
|
||||
my ($sth, $ret);
|
||||
my $mode = $FORM{'mode'};
|
||||
|
||||
my $remote = LJ::get_remote();
|
||||
LJ::load_user_privs($remote, 'admin') if $remote;
|
||||
|
||||
my @privs;
|
||||
my %priv;
|
||||
my %pcode2id;
|
||||
$sth = $dbh->prepare("SELECT prlid, privcode, privname, des, is_public, scope FROM priv_list ORDER BY privcode");
|
||||
$sth->execute;
|
||||
while ($_ = $sth->fetchrow_hashref) {
|
||||
push @privs, $_;
|
||||
$priv{$_->{'prlid'}} = $_;
|
||||
$pcode2id{$_->{'privcode'}} = $_->{'prlid'};
|
||||
}
|
||||
|
||||
if (LJ::did_post()) {
|
||||
return "<p><b>ERROR:</b> Invalid form submission" unless LJ::check_form_auth();
|
||||
}
|
||||
|
||||
unless ($mode)
|
||||
{
|
||||
if ($FORM{'user'}) { $mode = "viewuser"; }
|
||||
elsif ($FORM{'priv'}) { $mode = "viewpriv"; }
|
||||
}
|
||||
|
||||
if ($FORM{'devmode'}) {
|
||||
return "not in dev mode" unless $LJ::IS_DEV_SERVER;
|
||||
my $userid = $remote->{userid};
|
||||
if ($dbh->do("INSERT INTO priv_map (userid, prlid, arg) SELECT ?, prlid, ? FROM priv_list WHERE privcode=?",
|
||||
undef, $userid, $FORM{arg}, $FORM{priv})) {
|
||||
LJ::statushistory_add($dbh, $userid, $userid, "privadd", "DEVMODE Granting: \"$FORM{priv}\" with arg \"$FORM{arg}\"");
|
||||
return "done.";
|
||||
} else {
|
||||
return "fail.";
|
||||
}
|
||||
}
|
||||
|
||||
unless ($mode)
|
||||
{
|
||||
$ret .= "<h1>Privilege Management</h1>\n";
|
||||
$ret .= "<form method='get' action='index.bml'>";
|
||||
$ret .= "<p>View all privileges of user <input name='user' size='15' /> <input type='submit' value=\"Load\" /></p></form>";
|
||||
|
||||
$ret .= "<p>Or, show all users with privilege:</p><dl>";
|
||||
foreach my $priv (@privs) {
|
||||
my ($des, $args) = split(/arg=/, $priv->{'des'});
|
||||
$ret .= "<dt><strong><a href='./?priv=$priv->{'privcode'}'>$priv->{'privcode'}</a>: $priv->{'privname'}</strong>";
|
||||
$ret .= " <i>(Site Specific)</i>" if $priv->{'scope'} eq 'local';
|
||||
$ret .= "</dt>";
|
||||
$ret .= "<dd>$des\n";
|
||||
$ret .= "<br /><strong>Argument:</strong> $args" if $args;
|
||||
$ret .= "</dd>";
|
||||
}
|
||||
$ret .= "</dl>";
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
# Returns true if the remote user can grant the given priv
|
||||
sub remote_can_grant
|
||||
{
|
||||
my ($remote, $priv, $arg) = @_;
|
||||
return 0 unless defined $priv;
|
||||
return LJ::check_priv($remote, 'admin', $priv) || LJ::check_priv($remote, 'admin', '*') || LJ::check_priv($remote, 'admin', "$priv/$arg");
|
||||
}
|
||||
|
||||
if ($mode eq "userchange" || $mode eq "privchange")
|
||||
{
|
||||
unless (LJ::did_post()) {
|
||||
return "<p><b>Error:</b> requires post</p>";
|
||||
}
|
||||
|
||||
unless ($FORM{'submit:refresh'}) {
|
||||
foreach my $key (keys %FORM) {
|
||||
if ($key =~ /^revoke:(\d+):(\d+)$/) {
|
||||
my $prmid = $1;
|
||||
my $del_userid1 = $2;
|
||||
my $sth = $dbh->prepare("SELECT userid, prlid, arg FROM priv_map WHERE prmid=$prmid");
|
||||
$sth->execute;
|
||||
my ($del_userid2, $prlid, $arg) = $sth->fetchrow_array;
|
||||
|
||||
unless (remote_can_grant($remote, $priv{$prlid}->{'privcode'}, $arg)) {
|
||||
$ret .= "ERROR: Invalid access to remove priv $priv{$prlid}->{'privcode'}.<br />";
|
||||
} else {
|
||||
if ($del_userid1 && $del_userid1 == $del_userid2)
|
||||
{
|
||||
$dbh->do("DELETE FROM priv_map WHERE prmid=$prmid");
|
||||
my $privcode = $priv{$prlid}->{'privcode'};
|
||||
LJ::statushistory_add($dbh, $del_userid1, $remote->{'userid'}, "privdel",
|
||||
"Denying: \"$privcode\" with arg \"$arg\"");
|
||||
$ret .= "Privilege removed.<br />\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($FORM{'grantpriv'}) {
|
||||
my $u = LJ::load_user($FORM{'user'});
|
||||
return "ERROR: Invalid user." unless $u;
|
||||
my $userid = $u->{'userid'};
|
||||
my $qpriv = $FORM{'grantpriv'}+0;
|
||||
my $privcode = $priv{$qpriv}->{'privcode'};
|
||||
my $arg = $FORM{'arg'};
|
||||
|
||||
if ($privcode) {
|
||||
if (remote_can_grant($remote, $privcode, $arg)) {
|
||||
if (LJ::check_priv($u, $privcode, $arg)) {
|
||||
$ret .= "ERROR: User already has specified priv <b>$privcode $arg</b>.<br />";
|
||||
} else {
|
||||
my $qarg = $dbh->quote($arg);
|
||||
$dbh->do("INSERT INTO priv_map (prmid, userid, prlid, arg) VALUES (NULL, $userid, $qpriv, $qarg)");
|
||||
LJ::statushistory_add($dbh, $userid, $remote->{'userid'}, "privadd", "Granting: \"$privcode\" with arg \"$arg\"");
|
||||
$ret .= "Privilege <b>$privcode $arg</b> granted.<br />\n";
|
||||
}
|
||||
} else {
|
||||
$ret .= "ERROR: You don't have access to grant <b>$privcode $arg</b>.<br />\n";
|
||||
}
|
||||
} else {
|
||||
$ret .= "ERROR: Unknown privilege.<br />\n";
|
||||
}
|
||||
}
|
||||
if ($FORM{'grantuser'}) {
|
||||
my $u = LJ::load_user($FORM{'grantuser'});
|
||||
return "ERROR: Invalid user." unless $u;
|
||||
my $userid = $u->{'userid'};
|
||||
my $privid = $pcode2id{$FORM{'priv'}};
|
||||
my $arg = $FORM{'arg'};
|
||||
my $qarg = $dbh->quote($arg);
|
||||
my $privcode = $priv{$privid}->{'privcode'};
|
||||
if ($privcode) {
|
||||
if (remote_can_grant($remote, $privcode, $arg)) {
|
||||
if (LJ::check_priv($u, $privcode, $arg)) {
|
||||
$ret .= "ERROR: User already has specified priv <b>$privcode $arg</b>.<br />";
|
||||
}
|
||||
elsif ($userid && $privid) {
|
||||
my $qarg = $dbh->quote($FORM{'arg'});
|
||||
$dbh->do("INSERT INTO priv_map (prmid, userid, prlid, arg) VALUES (NULL, $userid, $privid, $qarg)");
|
||||
LJ::statushistory_add($dbh, $userid, $remote->{'userid'}, "privadd", "Granting: \"$privcode\" with arg \"$FORM{'arg'}\"");
|
||||
$ret .= "Privilege added.<br />\n";
|
||||
}
|
||||
else {
|
||||
my $euser = LJ::ehtml($FORM{'grantuser'});
|
||||
unless ($userid) {
|
||||
$ret .= "ERROR: cannot grant priv to non-existent user <b>$euser</b><br />";
|
||||
}
|
||||
else { $ret .= "privid is 0!<br />"; }
|
||||
}
|
||||
} else {
|
||||
$ret .= "ERROR: You don't have access to grant <B>$privcode</B> with argument '$arg'.<br />\n";
|
||||
}
|
||||
} else {
|
||||
$ret .= "ERROR: Unknown privilege.<br />\n";
|
||||
}
|
||||
} # end if grantuser
|
||||
}
|
||||
|
||||
if ($mode eq "userchange") { $mode = "viewuser"; }
|
||||
if ($mode eq "privchange") { $mode = "viewpriv"; }
|
||||
}
|
||||
|
||||
if ($mode eq "viewuser")
|
||||
{
|
||||
my $user = LJ::canonical_username($FORM{'user'});
|
||||
my $userid = LJ::get_userid($user);
|
||||
|
||||
$ret .= "<h1><a href='./'><<</a> view user \"$user\"</h1>\n";
|
||||
unless ($userid) {
|
||||
$ret .= "<b>Error:</b> non-existent user\n";
|
||||
return $ret;
|
||||
}
|
||||
|
||||
$ret .= "<form method='post' action='./'>\n";
|
||||
$ret .= LJ::form_auth();
|
||||
$ret .= "<input type='hidden' name='mode' value='userchange' />\n";
|
||||
$ret .= "<input type='hidden' name='user' value='$user' />\n";
|
||||
$sth = $dbh->prepare("SELECT pm.prmid, pm.prlid, pm.arg FROM priv_map pm, priv_list pl WHERE pm.prlid=pl.prlid AND pm.userid=$userid ORDER BY pl.privcode,pm.arg");
|
||||
$sth->execute;
|
||||
$ret .= "<table cellpadding='5' cellspacing='1' border='1'><tr><td><b>Revoke</b></td><td><b>Privilege</b></td><td><b>Arg</b></td></tr>\n";
|
||||
while (my ($prmid, $prlid, $arg) = $sth->fetchrow_array)
|
||||
{
|
||||
my $prec = $priv{$prlid};
|
||||
my $pcode = $priv{$prlid}->{'privcode'};
|
||||
my $can_grant = remote_can_grant($remote, $pcode, $arg);
|
||||
|
||||
next unless ($prec->{'is_public'} || ($remote && $remote->{'userid'} == $userid) || $can_grant);
|
||||
|
||||
$ret .= "<tr><td align='center'>";
|
||||
if ($can_grant) {
|
||||
$ret .= "<input type='checkbox' name='revoke:$prmid:$userid' />";
|
||||
} else {
|
||||
$ret .= "--";
|
||||
}
|
||||
|
||||
$ret .= "</td><td><a href='./?priv=$pcode'>$pcode</a></td>";
|
||||
if ($arg)
|
||||
{
|
||||
$ret .= "<td><a href='./?priv=$pcode&viewarg=$arg'>$arg</a></td></tr>\n";
|
||||
} else {
|
||||
$ret .= "<td> </td></tr>\n";
|
||||
}
|
||||
}
|
||||
$ret .= "</table>";
|
||||
|
||||
if (LJ::check_priv($remote, 'admin')) {
|
||||
$ret .= "<p>Grant <b>$user</b> privilege:<div style='margin-left: 20px;'>\n";
|
||||
$ret .= "<select name='grantpriv'><option value='' selected='1'></option>";
|
||||
foreach my $priv (@privs) {
|
||||
$ret .= "<option value='$priv->{'prlid'}'>$priv->{'privcode'}</option>";
|
||||
}
|
||||
$ret .= "</select>\n";
|
||||
$ret .= "Arg: <input name='arg' size='10' maxlength='40' /></div>\n";
|
||||
} else {
|
||||
$ret .= "<p><i>(you do not have access to grant any privileges)</i></p>\n";
|
||||
}
|
||||
|
||||
$ret .= "<p>\n";
|
||||
if (LJ::check_priv($remote, 'admin')) {
|
||||
$ret .= "<input type=\"submit\" value=\"Make Changes\" />";
|
||||
}
|
||||
$ret .= " <input type=\"submit\" name=\"submit:refresh\" value=\"Just Refresh\" />";
|
||||
$ret .= "</form>";
|
||||
return $ret;
|
||||
}
|
||||
|
||||
if ($mode eq "viewpriv") {
|
||||
my $priv = $pcode2id{$FORM{'priv'}};
|
||||
my $prec = $priv{$priv};
|
||||
my $pcode = $prec->{'privcode'};
|
||||
my $skip = $FORM{'skip'} + 0;
|
||||
my $limit = 100;
|
||||
|
||||
my $viewarg;
|
||||
if ($FORM{'viewarg'}) {
|
||||
$viewarg = " AND pm.arg=" . $dbh->quote($FORM{'viewarg'});
|
||||
}
|
||||
|
||||
my $privname = join(' ', grep { $_ } $priv{$priv}->{'privcode'}, $FORM{'viewarg'});
|
||||
$ret .= "<h1><a href=\"./\"><<</a> view priv \"$privname\"</h1>\n";
|
||||
$ret .= "<p><b>Privilege Name:</b> $priv{$priv}->{'privname'}";
|
||||
my ($des, $args) = split(/arg=/, $priv{$priv}->{'des'});
|
||||
$ret .= "<br /><b>Description:</b> $des" if $des;
|
||||
$ret .= "<br /><b>Argument:</b> $args" if $args;
|
||||
$ret .= "</p>";
|
||||
|
||||
my ($check_priv, $check_arg) = split("/", $FORM{'viewarg'});
|
||||
unless ($prec->{'is_public'} || remote_can_grant($remote, $check_priv, $check_arg)) {
|
||||
$ret .= "<p><b>ERROR:</b> This privilege's access list is not public.</p>\n";
|
||||
return $ret;
|
||||
}
|
||||
|
||||
$ret .= "<form style='display: inline;' action='./' method='post'>\n";
|
||||
$ret .= LJ::form_auth();
|
||||
$ret .= "<p><b>View only privs with arg:</b> ";
|
||||
$ret .= "<input name='viewarg' size='10' /> ";
|
||||
$ret .= "<input type='submit' name='submit:load' value='Load' /></p>\n";
|
||||
|
||||
$ret .= "<input type='hidden' name='mode' value='privchange' />\n";
|
||||
$ret .= "<input type='hidden' name='priv' value='$pcode' />";
|
||||
$sth = $dbh->prepare("SELECT pm.prmid, u.user, u.userid, pm.arg ".
|
||||
"FROM priv_map pm, useridmap u WHERE pm.prlid=$priv AND pm.userid=u.userid$viewarg ".
|
||||
"ORDER BY u.user,pm.arg LIMIT $skip,$limit");
|
||||
$sth->execute;
|
||||
$ret .= "<table cellpadding='5' cellspacing='1' border='1'><tr><td><b>Revoke</b></td><td><b>User</b></td><td><b>Arg</b></td></tr>\n";
|
||||
|
||||
my $showgrant = remote_can_grant($remote, $pcode, $FORM{'viewarg'});
|
||||
my $foundcount = 0;
|
||||
|
||||
while ($_ = $sth->fetchrow_hashref)
|
||||
{
|
||||
$foundcount++;
|
||||
$ret .= "<tr><td align='center'>";
|
||||
if (remote_can_grant($remote, $priv{$priv}->{'privcode'}, $_->{'arg'}))
|
||||
{
|
||||
$ret .= "<input type='checkbox' name=\"revoke:$_->{'prmid'}:$_->{'userid'}\" />";
|
||||
} else {
|
||||
$ret .= "--";
|
||||
}
|
||||
$ret .= "</td><td><a href=\"./?user=$_->{'user'}\">$_->{'user'}</a></td>";
|
||||
if ($_->{'arg'} ne "")
|
||||
{
|
||||
$ret .= "<td><a href=\"./?priv=$priv{$priv}->{'privcode'}&viewarg=$_->{'arg'}\">$_->{'arg'}</a></td></tr>\n";
|
||||
} else {
|
||||
$ret .= "<td> </td></tr>\n";
|
||||
}
|
||||
}
|
||||
$ret .= "<tr><td colspan='3'><b>$foundcount users</b></td></tr>\n";
|
||||
$ret .= "</table>";
|
||||
|
||||
if ($foundcount >= $limit) {
|
||||
$ret .= "<a href='" . BML::self_link({'skip'=>($skip +$limit)}) . "'>See more...</a>\n";
|
||||
}
|
||||
|
||||
if ($showgrant) {
|
||||
$ret .= "<p>Grant <b>$privname</b> privilege to:<ul>";
|
||||
$ret .= "User: <input name='grantuser' size='15' maxlength='15' /> ";
|
||||
$ret .= "Arg: <input name='arg' size='10' maxlength='40' value='$FORM{'viewarg'}'/></ul>\n";
|
||||
} else {
|
||||
$ret .= "<p><i>(you don't have access to grant this privilege to other users)</i></p>\n";
|
||||
}
|
||||
|
||||
if ($showgrant) {
|
||||
$ret .= "<input name=\"submit:change\" type='submit' value=\"Make Changes\" />\n";
|
||||
}
|
||||
$ret .= "</form>\n";
|
||||
|
||||
$ret .= "<form style='display: inline;' method='post' action='./'>\n";
|
||||
$ret .= LJ::form_auth();
|
||||
$ret .= LJ::html_hidden('mode', 'privchange',
|
||||
'priv', $pcode,
|
||||
'viewarg', $FORM{'viewarg'}) . "\n";
|
||||
$ret .= "<input type='submit' name=\"submit:refresh\" value=\"Just Refresh\" />\n";
|
||||
$ret .= "</form>\n";
|
||||
return $ret;
|
||||
}
|
||||
|
||||
return "Unknown mode.";
|
||||
|
||||
_code?>
|
||||
</body>
|
||||
</html>
|
||||
<?_c <LJDEP>
|
||||
lib: cgi-bin/ljlib.pl
|
||||
link: htdocs/admin/priv/index.bml
|
||||
post: htdocs/admin/priv/index.bml
|
||||
</LJDEP _c?>
|
||||
60
livejournal/htdocs/admin/recent_comments.bml
Executable file
@@ -0,0 +1,60 @@
|
||||
<html>
|
||||
<head><title>Comment view</title>
|
||||
<body>
|
||||
<?_code
|
||||
{
|
||||
use strict;
|
||||
use vars qw(%GET %POST);
|
||||
my $ret;
|
||||
my $remote = LJ::get_remote();
|
||||
|
||||
return "<b>Error:</b> You don't have access to viewing recent comments."
|
||||
unless LJ::check_priv($remote, "siteadmin", "commentview");
|
||||
|
||||
my $user = $GET{'user'};
|
||||
my $u;
|
||||
if ($user =~ /^\#(\d+)/) {
|
||||
$u = LJ::load_userid($1);
|
||||
} elsif ($user) {
|
||||
$u = LJ::load_user($user);
|
||||
}
|
||||
unless ($u) {
|
||||
return "<form method='GET'>Username or (#userid) to view comments of: ".
|
||||
"<input name='user' size='15' /><input type='submit' value='Load' /></form>";
|
||||
}
|
||||
$user = $u->{'user'};
|
||||
$ret .= "<a href='recent_comments.bml'><<</a> <b>Recent comments of " . LJ::ljuser($u) . "</b> (\#$u->{userid})<br />\n";
|
||||
|
||||
my $dbcr = LJ::get_cluster_reader($u);
|
||||
return "Error: can't get DB for user" unless $dbcr;
|
||||
|
||||
my $now = time();
|
||||
|
||||
my $sth = $dbcr->prepare("SELECT posttime, journalid, nodetype, nodeid, jtalkid, publicitem ".
|
||||
"FROM talkleft ".
|
||||
"WHERE userid=? ORDER BY posttime DESC LIMIT 250");
|
||||
$sth->execute($u->{'userid'});
|
||||
my %jcount; # jid -> ct
|
||||
while (my $r = $sth->fetchrow_hashref) {
|
||||
$jcount{$r->{'journalid'}}++;
|
||||
next unless $r->{'nodetype'} eq "L"; # log2 comment
|
||||
|
||||
my $ju = LJ::load_userid($r->{'journalid'});
|
||||
my $lrow = LJ::get_log2_row($ju, $r->{'nodeid'});
|
||||
my $hr_ago = sprintf("%.1f", ($now - $r->{'posttime'}) / 3600);
|
||||
|
||||
if ($lrow) {
|
||||
my $talkid = ($r->{'jtalkid'} << 8) + $lrow->{'anum'};
|
||||
my $url = "$LJ::SITEROOT/users/$ju->{user}/$lrow->{ditemid}.html?thread=$talkid\#t$talkid";
|
||||
$ret .= "$hr_ago hr ago in " . LJ::ljuser($ju) . ": <a href='$url'>$url</a><br />\n";
|
||||
} else {
|
||||
$ret .= "$hr_ago hr ago in " . LJ::ljuser($ju) . ": link unavailable<br />";
|
||||
}
|
||||
}
|
||||
|
||||
return $ret;
|
||||
|
||||
}
|
||||
_code?>
|
||||
</body>
|
||||
</html>
|
||||
278
livejournal/htdocs/admin/schema/index.bml
Executable file
@@ -0,0 +1,278 @@
|
||||
<?_code
|
||||
|
||||
use strict;
|
||||
|
||||
$title = "Schema Browser";
|
||||
$body = "";
|
||||
|
||||
my $dbh = LJ::get_db_writer();
|
||||
my $sth;
|
||||
|
||||
my $remote = LJ::get_remote();
|
||||
|
||||
my $can_doc = 0;
|
||||
if (LJ::remote_has_priv($remote, "schemadoc")) { $can_doc = 1; }
|
||||
unless ($can_doc) {
|
||||
my $url = "/doc/server/ljp.dbschema.ref.html";
|
||||
$body = "This page is for editing <a href=\"$url\">schema documentation</a>, ";
|
||||
$body .= "but you don't have the 'schemadoc' priv.";
|
||||
return;
|
||||
}
|
||||
|
||||
sub magic_links
|
||||
{
|
||||
my $des = shift;
|
||||
$$des =~ s!\[dbtable\[(\w+?)\]\]!<a href="./?mode=viewtable&table=$1">$1</a>!g;
|
||||
}
|
||||
|
||||
if ($FORM{'mode'} eq "")
|
||||
{
|
||||
my %table;
|
||||
$sth = $dbh->prepare("SELECT tablename, public_browsable, des FROM schematables");
|
||||
$sth->execute;
|
||||
while (my ($name, $public, $des) = $sth->fetchrow_array) {
|
||||
$table{$name} = { 'public' => $public, 'des' => $des };
|
||||
}
|
||||
|
||||
$body .= "<?h1 Tables h1?><?p Click a table for more information. p?><p><table cellpadding=4><tr bgcolor=<?emcolor?>><td><b>Table</b></td><td><b>Description</b></td></tr>\n";
|
||||
$sth = $dbh->prepare("SHOW TABLES");
|
||||
$sth->execute;
|
||||
while (my ($table) = $sth->fetchrow_array) {
|
||||
my $des = $table{$table}->{'des'} || "<i>no description, yet</i>";
|
||||
magic_links(\$des);
|
||||
$body .= "<tr valign=top><td nowrap><b><a href=\"./?mode=viewtable&table=$table\">$table</a></b>";
|
||||
if ($table{$table}->{'public'}) {
|
||||
$body .= " (<a href=\"./?mode=viewdata&table=$table\">data</a>)";
|
||||
}
|
||||
$body .= "</td><td>$des</td></tr>\n";
|
||||
}
|
||||
$body .= "</table>\n";
|
||||
return;
|
||||
}
|
||||
|
||||
if ($FORM{'mode'} eq "viewtable")
|
||||
{
|
||||
my $table = $FORM{'table'};
|
||||
if ($table !~ /^\w+$/) { $body = "Invalid table name!\n"; return; }
|
||||
my $qtable = $dbh->quote($table);
|
||||
|
||||
$sth = $dbh->prepare("SELECT des, public_browsable FROM schematables WHERE tablename=$qtable");
|
||||
$sth->execute;
|
||||
my ($tabledes, $browsable) = $sth->fetchrow_array;
|
||||
|
||||
$body .= "<a href=\"./\"><< Tables</a>";
|
||||
if ($browsable) {
|
||||
$body .= " | <a href=\"./?mode=viewdata&table=$table\">View Data</a>";
|
||||
}
|
||||
if ($can_doc) {
|
||||
$body .= " | <a href=\"./?mode=doc&table=$table\">Edit Documentation</a>";
|
||||
}
|
||||
$body .= "<?h1 Table: $table h1?><?p ";
|
||||
|
||||
|
||||
if ($tabledes) {
|
||||
&magic_links(\$tabledes);
|
||||
$body .= $tabledes;
|
||||
} else {
|
||||
$body .= "Below are the columns and descriptions for the <b>$table</b> table.";
|
||||
}
|
||||
$body .= " p?><p>\n";
|
||||
|
||||
my %coldes;
|
||||
$sth = $dbh->prepare("SELECT colname, des FROM schemacols WHERE tablename=$qtable");
|
||||
$sth->execute;
|
||||
while (my ($col, $des) = $sth->fetchrow_array) { $coldes{$col} = $des; }
|
||||
|
||||
$sth = $dbh->prepare("DESCRIBE $table");
|
||||
$sth->execute;
|
||||
$body .= "<table cellpadding=3><tr bgcolor=<?emcolor?>>";
|
||||
$body .= "<td><b>Key?</b></td>";
|
||||
$body .= "<td><b>Column</b></td>";
|
||||
$body .= "<td><b>Type</b></td>";
|
||||
$body .= "<td><b>Null</b></td>";
|
||||
$body .= "<td><b>Default</b></td>";
|
||||
$body .= "<td><b>Description</b></td>";
|
||||
$body .= "</tr>\n";
|
||||
while (my $row = $sth->fetchrow_hashref)
|
||||
{
|
||||
my $name = $row->{'Field'};
|
||||
my $type = $row->{'Type'};
|
||||
my $key = $row->{'Key'};
|
||||
my $null = $row->{'Null'};
|
||||
my $def = $row->{'Default'};
|
||||
my $des = BML::eall($coldes{$name});
|
||||
|
||||
magic_links(\$des);
|
||||
|
||||
$type =~ s/int\(\d+\)/int/g;
|
||||
|
||||
$body .= "<tr valign=top>";
|
||||
$body .= "<td align=center>$key</td>";
|
||||
$body .= "<td><b>$name</b></td>";
|
||||
$body .= "<td>$type</td>";
|
||||
$body .= "<td align=center>$null</td>";
|
||||
$body .= "<td align=center>$def</td>";
|
||||
$body .= "<td>$des</td>";
|
||||
$body .= "</tr>\n";
|
||||
}
|
||||
$body .= "</table>\n";
|
||||
return;
|
||||
}
|
||||
|
||||
if ($FORM{'mode'} eq "viewdata") {
|
||||
my $table = $FORM{'table'};
|
||||
if ($table !~ /^\w+$/) { $body = "Invalid table name!\n"; return; }
|
||||
|
||||
my $MAX_ROWS = 100;
|
||||
|
||||
$body .= "<a href=\"./\"><< Tables</a><br><a href=\"./?mode=viewtable&table=$table\"><< Table: $table</a><?h1 Data: $table h1?><?p Below are the rows in the <b>$table</b> table. If the table has more than $MAX_ROWS records, only the top $MAX_ROWS are shown. p?><p>\n";
|
||||
|
||||
$sth = $dbh->prepare("SELECT tablename, public_browsable, des FROM schematables WHERE tablename='$table'");
|
||||
$sth->execute;
|
||||
my ($tablename, $public, $des) = $sth->fetchrow_array;
|
||||
unless ($public) { $body .= "This table's data is not public.\n"; return; }
|
||||
|
||||
$sth = $dbh->prepare("SELECT * FROM $table LIMIT $MAX_ROWS");
|
||||
$sth->execute;
|
||||
$body .= "<table cellpadding=3><tr bgcolor=<?emcolor?>>";
|
||||
foreach my $col (@{$sth->{'NAME'}}) {
|
||||
$body .= "<td><b>$col</b></td>\n";
|
||||
}
|
||||
$body .= "</tr>\n";
|
||||
|
||||
while (my $row = $sth->fetchrow_arrayref) {
|
||||
$body .= "<tr valign=top>\n";
|
||||
foreach my $val (@$row) {
|
||||
$body .= "<td>$val</td>\n";
|
||||
}
|
||||
$body .= "</tr>\n";
|
||||
}
|
||||
$body .= "</table>\n";
|
||||
return;
|
||||
}
|
||||
|
||||
# show form to enter documentation
|
||||
if ($FORM{'mode'} eq "doc")
|
||||
{
|
||||
unless ($can_doc) { $body .= "You don't have permissions to document the schema."; return; }
|
||||
my $table = $FORM{'table'};
|
||||
if ($table !~ /^\w+$/) { $body = "Invalid table name!\n"; return; }
|
||||
|
||||
$body .= "<a href=\"./\"><< Tables</a><?h1 Document Table: $table h1?>";
|
||||
|
||||
my $qtable = $dbh->quote($table);
|
||||
my $sth;
|
||||
|
||||
$sth = $dbh->prepare("SELECT des FROM schematables WHERE tablename=$qtable");
|
||||
$sth->execute;
|
||||
my ($tabledes) = $sth->fetchrow_array;
|
||||
|
||||
my %coldes;
|
||||
$sth = $dbh->prepare("SELECT colname, des FROM schemacols WHERE tablename=$qtable");
|
||||
$sth->execute;
|
||||
while (my ($col, $des) = $sth->fetchrow_array) { $coldes{$col} = $des; }
|
||||
|
||||
$body .= "<form method=post action=\"./\">\n";
|
||||
$body .= "<input type=hidden name=table value=\"$table\">\n";
|
||||
$body .= "<input type=hidden name=mode value=\"docsave\">\n";
|
||||
$body .= "<p><b>Description:</b><br><textarea name=\"table-des\" rows=10 cols=40 wrap=soft>";
|
||||
$body .= BML::eall($tabledes) . "</textarea>";
|
||||
|
||||
$sth = $dbh->prepare("DESCRIBE $table");
|
||||
$sth->execute;
|
||||
$body .= "<p><table cellpadding=3><tr bgcolor=<?emcolor?>>";
|
||||
$body .= "<td><b>Column</b></td>";
|
||||
$body .= "<td><b>Type</b></td>";
|
||||
$body .= "<td><b>Description</b></td>";
|
||||
$body .= "</tr>\n";
|
||||
while (my $row = $sth->fetchrow_hashref)
|
||||
{
|
||||
my $name = $row->{'Field'};
|
||||
my $type = $row->{'Type'};
|
||||
$type =~ s/int\(\d+\)/int/g;
|
||||
|
||||
$body .= "<tr valign=top>";
|
||||
$body .= "<td><b>$name</b></td>";
|
||||
$body .= "<td>$type</td>";
|
||||
$body .= "<td><input name=\"col-$name\" size=60 maxlength=255 value=\"" . BML::eall($coldes{$name}) . "\"></td>";
|
||||
$body .= "</tr>\n";
|
||||
}
|
||||
$body .= "</table>\n";
|
||||
$body .= "<p><input type=submit value=\"Save Changes\"></form>";
|
||||
return;
|
||||
}
|
||||
|
||||
# save documentation
|
||||
if ($FORM{'mode'} eq "docsave")
|
||||
{
|
||||
unless ($can_doc) { $body .= "You don't have permissions to document the schema."; return; }
|
||||
my $table = $FORM{'table'};
|
||||
if ($table !~ /^\w+$/) { $body = "Invalid table name!\n"; return; }
|
||||
|
||||
$body .= "<a href=\"./\"><< Tables</a><?h1 Document Table: $table h1?>";
|
||||
|
||||
my $qtable = $dbh->quote($table);
|
||||
my $sth;
|
||||
|
||||
$sth = $dbh->prepare("SELECT tablename, des FROM schematables WHERE tablename=$qtable");
|
||||
$sth->execute;
|
||||
my ($tablename, $tabledes) = $sth->fetchrow_array;
|
||||
$FORM{'table-des'} =~ s/\r//;
|
||||
my $qdes = $dbh->quote($FORM{'table-des'});
|
||||
if ($tablename) {
|
||||
# row exists, update.
|
||||
$dbh->do("UPDATE schematables SET des=$qdes WHERE tablename=$qtable");
|
||||
} else {
|
||||
# no row exists, so insert
|
||||
$dbh->do("INSERT INTO schematables (tablename, public_browsable, des) VALUES ($qtable, '0', $qdes)");
|
||||
}
|
||||
if ($dbh->err) { $body .= $dbh->errstr; return; }
|
||||
|
||||
my %olddes;
|
||||
my %newdes;
|
||||
|
||||
### load old descriptions
|
||||
$sth = $dbh->prepare("SELECT colname, des FROM schemacols WHERE tablename=$qtable");
|
||||
$sth->execute;
|
||||
while (my ($col, $des) = $sth->fetchrow_array) { $olddes{$col} = $des; }
|
||||
|
||||
### check new descriptions (only for valid columns)
|
||||
$sth = $dbh->prepare("DESCRIBE $table");
|
||||
$sth->execute;
|
||||
if ($dbh->err) { $body .= $dbh->errstr; return; }
|
||||
while (my $row = $sth->fetchrow_hashref)
|
||||
{
|
||||
my $name = $row->{'Field'};
|
||||
my $type = $row->{'Type'};
|
||||
|
||||
$FORM{"col-$name"} =~ s/\r//;
|
||||
if ($FORM{"col-$name"} ne $olddes{$name}) {
|
||||
$newdes{$name} = $FORM{"col-$name"};
|
||||
}
|
||||
}
|
||||
if (%newdes) {
|
||||
my $sql = "REPLACE INTO schemacols (tablename, colname, des) VALUES ";
|
||||
foreach my $col (keys %newdes) {
|
||||
my $qcol = $dbh->quote($col);
|
||||
my $qdes = $dbh->quote($newdes{$col});
|
||||
$sql .= "($qtable, $qcol, $qdes),";
|
||||
}
|
||||
chop $sql;
|
||||
$dbh->do($sql);
|
||||
if ($dbh->err) { $body .= "[3] ($sql)<p>" . $dbh->errstr; return; }
|
||||
}
|
||||
|
||||
$body .= "<?h1 Success h1?><?p Documentation saved. <a href=\"./?mode=viewtable&table=$table\">View</a>. p?>";
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
return;
|
||||
|
||||
_code?><?page
|
||||
title=><?_code return $title; _code?>
|
||||
body=><?_code return $body; _code?>
|
||||
page?><?_c <LJDEP>
|
||||
link: htdocs/admin/scheme/index.bml
|
||||
</LJDEP> _c?>
|
||||
276
livejournal/htdocs/admin/spamreports.bml
Executable file
@@ -0,0 +1,276 @@
|
||||
<?_code
|
||||
{
|
||||
use strict;
|
||||
use vars qw($title $body %GET %POST);
|
||||
|
||||
$title = "Spam Reports";
|
||||
$body = "";
|
||||
|
||||
my $error = sub {
|
||||
$title = "Error";
|
||||
$body = join '', @_;
|
||||
return undef;
|
||||
};
|
||||
my $makelink = sub {
|
||||
my ($by, $what, $state, $reporttime, $etext) = @_;
|
||||
$by = LJ::eurl($by);
|
||||
$what = LJ::eurl($what);
|
||||
$state = LJ::eurl($state);
|
||||
$reporttime = LJ::mysql_time($reporttime);
|
||||
$reporttime = $etext if $etext;
|
||||
return "<a href=\"spamreports.bml?mode=view&by=$by&what=$what&state=$state\">$reporttime</a>";
|
||||
};
|
||||
my $dellink = sub {
|
||||
my ($by, $what, $text) = @_;
|
||||
return "<form method=\"post\" action=\"spamreports.bml\">" .
|
||||
LJ::html_hidden('mode', $by) .
|
||||
LJ::html_hidden('what', $what) .
|
||||
LJ::html_hidden('ret', "spamreports.bml?" . join('&', map { "$_=" . LJ::eurl($GET{$_}) } keys %GET)) .
|
||||
LJ::html_submit('submit', $text) .
|
||||
"</form>";
|
||||
};
|
||||
|
||||
# login check
|
||||
my $remote = LJ::get_remote();
|
||||
return $error->("You must be logged in to be here.")
|
||||
unless $remote;
|
||||
|
||||
# priv check
|
||||
return $error->("You do not have the necessary privilege to be here.")
|
||||
unless LJ::check_priv($remote, 'siteadmin', 'spamreports');
|
||||
|
||||
# show the top 10 spam reports by IP
|
||||
my $mode = lc($GET{mode} || $POST{mode});
|
||||
$mode = '' if $mode =~ /^del/ && !LJ::did_post() && !LJ::check_referer('/admin/spamreports.bml');
|
||||
|
||||
# combined/user/anon viewing?
|
||||
my $view = $mode =~ /_([cua])$/ ? $1 : 'c';
|
||||
my ($extrawhere, $extratitle);
|
||||
if ($view eq 'c') { $extrawhere = '1'; }
|
||||
elsif ($view eq 'u') { $extrawhere = 'posterid > 0'; $extratitle = " - Users Only"; }
|
||||
elsif ($view eq 'a') { $extrawhere = 'posterid = 0'; $extratitle = " - Anonymous Only"; }
|
||||
$mode =~ s/_[cua]$//; # strip out viewing option
|
||||
|
||||
my $dbr = LJ::get_db_reader();
|
||||
return $error->("Unable to get database reader handle.") unless $dbr;
|
||||
my @rows;
|
||||
my @headers;
|
||||
if ($mode eq 'top10ip') {
|
||||
# top 10 by ip
|
||||
$title = "Spam Reports - Top 10 by IP Address";
|
||||
@headers = ('Number of Reports', 'IP Address', 'Most Recent Report');
|
||||
my $res = $dbr->selectall_arrayref('SELECT COUNT(ip) AS num, ip, MAX(reporttime) FROM spamreports ' .
|
||||
"WHERE state = 'open' AND ip IS NOT NULL " .
|
||||
'GROUP BY ip ORDER BY num DESC LIMIT 10');
|
||||
foreach (@$res) {
|
||||
push @rows, [ $_->[0], $_->[1], $makelink->('ip', $_->[1], 'open', $_->[2]) ];
|
||||
}
|
||||
|
||||
} elsif ($mode eq 'top10user') {
|
||||
# top 10 by user
|
||||
$title = "Spam Reports - Top 10 by User";
|
||||
@headers = ('Number of Reports', 'Posted By User', 'Most Recent Report');
|
||||
my $res = $dbr->selectall_arrayref('SELECT COUNT(posterid) AS num, posterid, MAX(reporttime) FROM spamreports ' .
|
||||
"WHERE state = 'open' AND posterid > 0 " .
|
||||
'GROUP BY posterid ORDER BY num DESC LIMIT 10');
|
||||
foreach (@$res) {
|
||||
my $u = LJ::load_userid($_->[1]);
|
||||
push @rows, [ $_->[0], LJ::ljuser($u), $makelink->('posterid', $_->[1], 'open', $_->[2]) ];
|
||||
}
|
||||
|
||||
} elsif ($mode eq 'tlast10') {
|
||||
# most recent 10 reports
|
||||
$title = "Spam Reports - Last 10$extratitle";
|
||||
@headers = ('Posted By', 'Posted In', 'Report Time');
|
||||
my $res = $dbr->selectall_arrayref('SELECT posterid, ip, journalid, reporttime FROM spamreports ' .
|
||||
"WHERE state = 'open' AND $extrawhere ORDER BY reporttime DESC LIMIT 10");
|
||||
foreach (@$res) {
|
||||
my $u2 = LJ::load_userid($_->[2]);
|
||||
if ($_->[0] > 0) {
|
||||
my $u = LJ::load_userid($_->[0]);
|
||||
push @rows, [ LJ::ljuser($u), LJ::ljuser($u2), $makelink->('posterid', $_->[0], 'open', $_->[3]) ];
|
||||
} else {
|
||||
push @rows, [ "$_->[1]", LJ::ljuser($u2), $makelink->('ip', $_->[1], 'open', $_->[3]) ];
|
||||
}
|
||||
}
|
||||
|
||||
} elsif ($mode =~ /^last(\d+)hr$/) {
|
||||
# reports in last X hours
|
||||
my $hours = $1+0;
|
||||
my $secs = $hours * 3600; # seconds in an hour
|
||||
$title = "Spam Reports - Last $hours Hour" . ($hours == 1 ? '' : 's') . $extratitle;
|
||||
@headers = ('Number of Reports', 'Posted By', 'Report Time');
|
||||
my $res = $dbr->selectall_arrayref('SELECT journalid, ip, posterid, reporttime FROM spamreports ' .
|
||||
"WHERE $extrawhere AND reporttime > (UNIX_TIMESTAMP() - $secs) LIMIT 1000");
|
||||
|
||||
# count up items and their most recent report
|
||||
my %hits;
|
||||
my %times;
|
||||
foreach (@$res) {
|
||||
my $key;
|
||||
if ($_->[2] > 0) {
|
||||
my $u = LJ::load_userid($_->[2]);
|
||||
next unless $u;
|
||||
$key = $u->{userid};
|
||||
} else {
|
||||
next unless $_->[1];
|
||||
$key = $_->[1];
|
||||
}
|
||||
$hits{$key}++;
|
||||
$times{$key} = $_->[3] unless $times{$key} gt $_->[3];
|
||||
}
|
||||
|
||||
# now reverse to number => item list
|
||||
my %revhits;
|
||||
foreach (keys %hits) {
|
||||
if ($revhits{$hits{$_}}) {
|
||||
push @{$revhits{$hits{$_}}}, $_;
|
||||
} else {
|
||||
$revhits{$hits{$_}} = [ $_ ];
|
||||
}
|
||||
}
|
||||
|
||||
# now push them onto @rows
|
||||
foreach (sort { $b <=> $a } keys %revhits) {
|
||||
my $r = $revhits{$_};
|
||||
foreach (@$r) {
|
||||
my $isip = $_ =~ /\./ ? 1 : 0;
|
||||
push @rows, [ $hits{$_}, $isip ? $_ : LJ::ljuser(LJ::load_userid($_)),
|
||||
$makelink->($isip ? 'ip' : 'posterid', $_, 'open', $times{$_}) ];
|
||||
}
|
||||
}
|
||||
|
||||
} elsif ($mode eq 'view') {
|
||||
# view a particular report
|
||||
my ($by, $what, $state) = (lc($GET{by}), $GET{what}, lc($GET{state}));
|
||||
$by = '' unless $by =~ /^(?:ip|poster(?:id)?)$/;
|
||||
$state = 'open' unless $state =~ /^(?:open|closed)$/;
|
||||
$body .= "<?p [ <a href=\"spamreports.bml\"><< Front Page</a> ] ";
|
||||
|
||||
# open/closed links
|
||||
my $eargs = LJ::eurl("?by=$by&what=$what&state");
|
||||
if ($state eq 'open') {
|
||||
$body .= " [ " . $makelink->($by, $what, 'closed', undef, "View Closed Reports") . " ]";
|
||||
} else {
|
||||
$body .= " [ " . $makelink->($by, $what, 'open', undef, "View Open Reports") . " ]";
|
||||
}
|
||||
$body .= " p?>\n";
|
||||
|
||||
# setup title and verify that the data is right
|
||||
if ($by eq 'posterid') {
|
||||
$what += 0;
|
||||
my $u = LJ::load_userid($what);
|
||||
return $error->('No such posterid.') unless $u;
|
||||
$title = "Spam Reports - By $u->{user} ($state)";
|
||||
} elsif ($by eq 'poster') {
|
||||
my $u = LJ::load_user($what);
|
||||
return $error->('No such user.') unless $u;
|
||||
$title = "Spam Reports - Comments By $u->{user}";
|
||||
|
||||
# Now just pretend that user used 'posterid'
|
||||
$by = 'posterid';
|
||||
$what = $u->{userid};
|
||||
} elsif ($by eq 'ip') {
|
||||
# check for right format x.x.x.x, not necessarily a valid IP
|
||||
return $error->('No such IP.') if $what !~ /^\d+\.\d+\.\d+\.\d+$/ or length $what > 15;
|
||||
$title = "Spam Reports - By IP $what ($state)";
|
||||
}
|
||||
|
||||
# see if we should call a hook for extra actions?
|
||||
$body .= LJ::run_hook('spamreport_notification', $remote, { $by => $what })
|
||||
if $state eq 'open' && $by eq 'posterid';
|
||||
|
||||
# now the general info gathering
|
||||
my $res = $dbr->selectall_arrayref('SELECT reporttime, journalid, subject, body, ip, posttime, report_type ' .
|
||||
"FROM spamreports WHERE state=? AND $by=? ORDER BY reporttime DESC LIMIT 1000",
|
||||
undef, $state, $what);
|
||||
unless ($res && @$res) {
|
||||
$body .= "No reports found.";
|
||||
return undef;
|
||||
}
|
||||
$body .= '<table>';
|
||||
foreach (@$res) {
|
||||
my $u2 = LJ::load_userid($_->[1]);
|
||||
my $x = $by eq 'ip' ? 4 : 1;
|
||||
my $comment_body = $_->[3];
|
||||
LJ::text_uncompress(\$comment_body);
|
||||
my $spamlocation = ($_->[6] eq 'entry') ? 'Entry' : 'Comment';
|
||||
$body .= '<tr><td>' . ($state eq 'open' ? $dellink->("del$by", "$_->[0]:$_->[$x]", 'Close') : '') . '</td><td>' .
|
||||
"<strong>$spamlocation in:</strong> " . LJ::ljuser($u2) . '<br />' .
|
||||
'<strong>Report Time:</strong> ' . LJ::mysql_time($_->[0]) . '<br />' .
|
||||
"<strong>$spamlocation Time:</strong> " . ($_->[5] ? LJ::mysql_time($_->[5]) : 'not recorded') . '<br />' .
|
||||
'<strong>Subject:</strong> ' . LJ::ehtml($_->[2] || 'no subject') . '<br />' .
|
||||
'<strong>Body:</strong> ' . LJ::ehtml($comment_body || 'no body') . '<br />' .
|
||||
'</td></tr><tr><td> </td></tr>';
|
||||
}
|
||||
$body .= "</table><br />" . ($state eq 'open' ? $dellink->("delby$by", $what, 'Close All') : '');
|
||||
|
||||
} elsif ($mode =~ /^del/) {
|
||||
# figure out our combination
|
||||
my $dbh = LJ::get_db_writer();
|
||||
return $error->("Unable to get database writer handle.") unless $dbh;
|
||||
my ($sql, $count, $backlink);
|
||||
if ($mode =~ /^delby/) {
|
||||
# enmasse deletion
|
||||
my $where = $mode =~ /ip$/ ? 'ip' : 'posterid';
|
||||
$sql = "UPDATE spamreports SET state='closed' WHERE $where=?";
|
||||
$count = $dbh->do($sql, undef, $POST{what});
|
||||
return $error->($dbh->errstr) if $dbh->err;
|
||||
} else {
|
||||
# single item deletion
|
||||
my $where = $mode =~ /ip$/ ? 'ip' : 'journalid';
|
||||
my ($time, $data) = ($1, $2)
|
||||
if $POST{what} =~ /^(\d+):(.+)$/;
|
||||
$data ||= $POST{what};
|
||||
$count = $dbh->do("UPDATE spamreports SET state='closed' WHERE reporttime=? AND $where=? AND state='open'", undef, $time, $data);
|
||||
return $error->($dbh->errstr) if $dbh->err;
|
||||
$backlink = "[ <a href='$POST{ret}'><< Go Back</a> ]";
|
||||
}
|
||||
$title = "Close Reports";
|
||||
$body .= "<?p [ <a href=\"spamreports.bml\"><< Front Page</a> ] $backlink p?>\n";
|
||||
my $s = $count == 1 ? '' : 's';
|
||||
$body .= "Closed $count report$s.\n";
|
||||
|
||||
} else {
|
||||
# standard
|
||||
my %modes = (top10user => 'Top 10 by User', top10ip => 'Top 10 by IP Address', tlast10 => 'Last 10 Reports',
|
||||
last01hr => 'Last 1 Hour', last06hr => 'Last 6 Hours', last24hr => 'Last 24 Hours');
|
||||
$body .= "<?p Available reports: p?>\n<ul>";
|
||||
foreach (sort keys %modes) {
|
||||
$body .= "<li><a href=\"spamreports.bml?mode=$_\">$modes{$_}</a>";
|
||||
if ($_ =~ /last/) {
|
||||
# this is a last view, so we have other options
|
||||
$body .= " [<a href=\"spamreports.bml?mode=${_}_u\">users</a>, ";
|
||||
$body .= "<a href=\"spamreports.bml?mode=${_}_a\">anonymous</a>]";
|
||||
}
|
||||
$body .= "</li>";
|
||||
}
|
||||
$body .= qq{<li><form method="GET" action="spamreports.bml" style="display: inline; margin: 0;">
|
||||
<label for="repu">Reports for user:
|
||||
<input type="text" name="what" size="15" maxlength="15" id="repu" />
|
||||
<input type="hidden" name="by" value="poster" />
|
||||
<input type="hidden" name="mode" value="view" />
|
||||
</label></form></li>
|
||||
};
|
||||
$body .= "</ul>\n<?p Please select one of the above reports to view. Actions can be taken when viewing a report. p?>";
|
||||
}
|
||||
|
||||
# now spit out the requested table
|
||||
return unless @headers;
|
||||
$body .= "<?p [ <a href=\"spamreports.bml\"><< Front Page</a> ] p?>";
|
||||
$body .= "<table width=\"50%\">\n<tr>";
|
||||
$body .= "<th align=\"center\">$_</th>" foreach @headers;
|
||||
$body .= "</tr>\n";
|
||||
foreach (@rows) {
|
||||
$body .= "<tr>";
|
||||
$body .= "<td align=\"center\">$_</td>" foreach @$_;
|
||||
$body .= "</tr>\n";
|
||||
}
|
||||
$body .= "</table>\n";
|
||||
|
||||
return;
|
||||
}
|
||||
_code?><?page
|
||||
title=><?_code return $title; _code?>
|
||||
body=><?_code return $body; _code?>
|
||||
page?>
|
||||
122
livejournal/htdocs/admin/statushistory.bml
Executable file
@@ -0,0 +1,122 @@
|
||||
<html>
|
||||
<head><title>Status History</title></head>
|
||||
<body>
|
||||
<?_code
|
||||
{
|
||||
use strict;
|
||||
use vars qw(%FORM);
|
||||
|
||||
my $dbr = LJ::get_db_reader();
|
||||
|
||||
# check privs
|
||||
my $remote = LJ::get_remote();
|
||||
unless (LJ::check_priv($remote, "historyview")) {
|
||||
return "Sorry, you don't have access to view this page.";
|
||||
}
|
||||
|
||||
my $ret;
|
||||
|
||||
$ret .= "Fill in at least one field below:";
|
||||
$ret .= "<form method='post' action='statushistory.bml'>\n";
|
||||
$ret .= LJ::html_hidden('orderby', $FORM{'orderby'}, 'flow', $FORM{'flow'}) . "\n";
|
||||
$ret .= "User: " . LJ::html_text({ 'name' => 'user', 'size' => '15', 'maxlength' => '15' }) . "\n";
|
||||
$ret .= "Admin: " . LJ::html_text({ 'name' => 'admin', 'size' => '15', 'maxlength' => '15' }) . "\n";
|
||||
$ret .= "Type: " . LJ::html_text({ 'name' => 'type', 'size' => '20', 'maxlength' => '20' }) . "\n";
|
||||
$ret .= LJ::html_submit('query_submit', 'Search');
|
||||
$ret .= "</form>\n\n";
|
||||
|
||||
return $ret unless ($FORM{'user'} || $FORM{'admin'} || $FORM{'type'});
|
||||
|
||||
$ret .= "<hr size='1'>\n\n";
|
||||
|
||||
# build query
|
||||
my @where;
|
||||
if ($FORM{'user'} ne "") {
|
||||
my $userid = LJ::get_userid($FORM{'user'});
|
||||
unless ($userid) { return "unknown user"; }
|
||||
push @where, "s.userid=$userid";
|
||||
}
|
||||
|
||||
if ($FORM{'admin'} ne "") {
|
||||
my $userid = LJ::get_userid($FORM{'admin'});
|
||||
unless ($userid) { return "unknown admin"; }
|
||||
push @where, "s.adminid=$userid";
|
||||
}
|
||||
|
||||
if ($FORM{'type'} ne "") {
|
||||
my $qt = $dbr->quote($FORM{'type'});
|
||||
push @where, "s.shtype=$qt";
|
||||
}
|
||||
|
||||
my $where = "WHERE " . join(" AND ", @where) . " " if @where;
|
||||
|
||||
my $orderby = 'shdate';
|
||||
foreach (qw(user admin shdate shtype notes)) {
|
||||
$orderby = "u.$_", next if $FORM{'orderby'} eq $_ && $_ eq 'user';
|
||||
$orderby = "ua.$_", next if $FORM{'orderby'} eq $_ && $_ eq 'admin';
|
||||
$orderby = "s.$_" if $FORM{'orderby'} eq $_;
|
||||
}
|
||||
my $flow = $FORM{'flow'} eq 'asc' ? 'ASC' : 'DESC';
|
||||
|
||||
my $sth = $dbr->prepare("SELECT u.user, ua.user AS admin, s.shtype, s.shdate, s.notes " .
|
||||
"FROM statushistory s " .
|
||||
"LEFT JOIN useridmap ua ON s.adminid=ua.userid " .
|
||||
"LEFT JOIN useridmap u ON s.userid=u.userid " .
|
||||
$where .
|
||||
"ORDER BY $orderby $flow LIMIT 1000");
|
||||
$sth->execute;
|
||||
return $dbr->errstr if $dbr->err;
|
||||
|
||||
# column headings w/ sort links
|
||||
$ret .= "<p><b>Query:";
|
||||
foreach (qw(user admin type)) {
|
||||
$ret .= " $_=" . LJ::eall($FORM{$_}) if $FORM{$_}
|
||||
}
|
||||
$ret .= "</b></p>\n";
|
||||
$ret .= "<table border='1' cellpadding='5' width='100%'>\n<tr>";
|
||||
foreach (qw(user admin shtype shdate notes)) {
|
||||
my $link = "statushistory.bml?user=$FORM{'user'}&admin=$FORM{'admin'}&type=$FORM{'type'}&orderby=$_";
|
||||
$link .= $FORM{'orderby'} eq $_ && $FORM{'flow'} eq 'asc' ? "&flow=desc" : "&flow=asc";
|
||||
$ret .= "<td><b><a href='$link'>$_</a></b></td>";
|
||||
}
|
||||
$ret .= "</tr>\n";
|
||||
|
||||
# query built above
|
||||
my $ct = 0;
|
||||
while (my $hist = $sth->fetchrow_hashref) {
|
||||
# see if they can see this item: either they have unarged historyview or
|
||||
# they have historyview:shtype
|
||||
next unless LJ::check_priv($remote, 'historyview', '') ||
|
||||
LJ::check_priv($remote, 'historyview', $hist->{shtype});
|
||||
|
||||
$ret .= "<tr>";
|
||||
foreach (qw(user admin shtype shdate notes)) {
|
||||
|
||||
$ret .= "<td>";
|
||||
if ($hist->{$_} && ($_ eq 'user' || $_ eq 'admin')) {
|
||||
$ret .= LJ::ljuser($hist->{$_});
|
||||
} elsif ($_ eq 'notes') {
|
||||
# notes need to be ehtml'd, but afterwards, we can convert \n to <br />
|
||||
my $enotes = LJ::ehtml($hist->{$_});
|
||||
$enotes =~ s!\n!<br />\n!g;
|
||||
$ret .= $enotes;
|
||||
} else {
|
||||
$ret .= LJ::ehtml($hist->{$_});
|
||||
}
|
||||
$ret .= "</td>";
|
||||
}
|
||||
$ret .= "</tr>\n";
|
||||
$ct++;
|
||||
}
|
||||
|
||||
$ret .= "<tr><td colspan='5'><b>$ct rows in set";
|
||||
$ret .= "[truncated]" if $ct >= 1000;
|
||||
$ret .= "</b></td></tr>\n";
|
||||
$ret .= "</table>\n\n";
|
||||
|
||||
return $ret;
|
||||
}
|
||||
_code?>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
1
livejournal/htdocs/admin/topics/blank.bml
Executable file
@@ -0,0 +1 @@
|
||||
|
||||
34
livejournal/htdocs/admin/topics/index.bml
Executable file
@@ -0,0 +1,34 @@
|
||||
<?page
|
||||
title=>Topic Directory Administration
|
||||
body<=
|
||||
|
||||
<?_code
|
||||
|
||||
use strict;
|
||||
|
||||
my $ret;
|
||||
|
||||
my $remote = LJ::get_remote();
|
||||
|
||||
if (LJ::remote_has_priv($remote, "topicaddtopic")) {
|
||||
$ret .= "<P><A HREF=\"screentop.bml\"><B>Screen Topic Submissions</B></A> that are awaiting approval into a category.";
|
||||
}
|
||||
|
||||
if (LJ::remote_has_priv($remote, "topicscreencat")) {
|
||||
$ret .= "<P><A HREF=\"screen.html\"><B>Screen Entry Submissions</B></A> that are awaiting approval into a topic.";
|
||||
}
|
||||
|
||||
unless ($ret) {
|
||||
$ret .= "You have no administrative priviledges in this area, or you are not logged in.";
|
||||
}
|
||||
|
||||
return $ret;
|
||||
|
||||
_code?>
|
||||
|
||||
|
||||
<=body
|
||||
page?><?_c <LJDEP>
|
||||
link: htdocs/admin/topics/screentop.bml, htdocs/admin/topics/screen.html
|
||||
</LJDEP> _c?>
|
||||
|
||||
30
livejournal/htdocs/admin/topics/links.bml
Executable file
@@ -0,0 +1,30 @@
|
||||
<?_code
|
||||
|
||||
return "This page is old and uses a horrendous database query. It won't likely return.";
|
||||
|
||||
my $user = $FORM{'user'};
|
||||
|
||||
my $dbh = LJ::get_db_writer();
|
||||
my $sth = $dbh->prepare("SELECT styleid, user, styledes, type, is_embedded, is_colorfree FROM style WHERE is_public='Y' ORDER BY user");
|
||||
$sth->execute;
|
||||
|
||||
my $ret = "";
|
||||
my $last = "";
|
||||
while ($sty = $sth->fetchrow_hashref) {
|
||||
if ($last ne $sty->{'user'}) {
|
||||
$last = $sty->{'user'};
|
||||
$ret .= "<B>$last</B><BR>\n";
|
||||
}
|
||||
if ($user) {
|
||||
$ret .= " - <A TARGET=\"main\" HREF=\"/customview.cgi?styleid=$sty->{'styleid'}&user=$user\">$sty->{'styledes'}</A><BR>\n";
|
||||
} else {
|
||||
$ret .= " - <A TARGET=\"main\" HREF=\"styleinfo.bml?styleid=$sty->{'styleid'}\">$sty->{'styledes'}</A><BR>\n";
|
||||
}
|
||||
}
|
||||
|
||||
return $ret;
|
||||
|
||||
_code?><?_c <LJDEP>
|
||||
link: htdocs/customview.cgi, htdocs/admin/topics/styleinfo.bml
|
||||
</LJDEP> _c?>
|
||||
|
||||
17
livejournal/htdocs/admin/topics/screen.html
Executable file
@@ -0,0 +1,17 @@
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<TITLE>Topic Directory Administration</TITLE>
|
||||
</HEAD>
|
||||
|
||||
<FRAMESET COLS="150,100%">
|
||||
<FRAME NAME="links" SRC="screen_links.bml">
|
||||
<FRAME NAME="main" SRC="screen_instructions.bml">
|
||||
</FRAMESET>
|
||||
|
||||
|
||||
</HTML>
|
||||
<!--
|
||||
<?_c <LJDEP>
|
||||
post: htdocs/admin/topics/screen_links.bml, htdocs/admin/topics/screen_instructions.bml
|
||||
</LJDEP> _c?>
|
||||
-->
|
||||
50
livejournal/htdocs/admin/topics/screen_do.bml
Executable file
@@ -0,0 +1,50 @@
|
||||
<?_code
|
||||
|
||||
use strict;
|
||||
use vars qw(%FORM);
|
||||
|
||||
my $remote = LJ::get_remote();
|
||||
return $ML{'error.noremote'} unless $remote;
|
||||
|
||||
return "You don't have access to do this."
|
||||
unless LJ::remote_has_priv($remote, "topicscreencat");
|
||||
|
||||
my $dbh = LJ::get_db_writer();
|
||||
|
||||
my $ret;
|
||||
foreach my $field (keys %FORM)
|
||||
{
|
||||
my $act = $FORM{$field};
|
||||
next if ($act eq "L");
|
||||
next unless ($field =~ /^action:(\d+):(\d+)$/);
|
||||
my $topid = $1;
|
||||
my $itemid = $2;
|
||||
|
||||
if ($act eq "A") {
|
||||
my $sth = $dbh->prepare("UPDATE topic_map SET status='on', screendate=NOW(), " .
|
||||
"screenuserid=? WHERE tptopid=? AND itemid=? AND status='new'");
|
||||
$sth->execute($remote->{'userid'}, $topid, $itemid);
|
||||
if ($sth->rows) {
|
||||
$ret .= "<b>$itemid</b> approved.<br />\n";
|
||||
} else {
|
||||
$ret .= "<b>$itemid</b> already acted on.<br />\n";
|
||||
}
|
||||
}
|
||||
if ($act eq "D") {
|
||||
my $sth = $dbh->prepare("UPDATE topic_map SET status='deny', screendate=NOW(), " .
|
||||
"screenuserid=? WHERE tptopid=? AND itemid=? AND status='new'");
|
||||
$sth->execute($remote->{'userid'}, $topid, $itemid);
|
||||
if ($sth->rows) {
|
||||
$ret .= "<B>$itemid</B> denied.<BR>\n";
|
||||
} else {
|
||||
$ret .= "<B>$itemid</B> already acted on.<BR>\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $ret;
|
||||
|
||||
_code?><?_c <LJDEP>
|
||||
# None
|
||||
</LJDEP> _c?>
|
||||
|
||||
6
livejournal/htdocs/admin/topics/screen_instructions.bml
Executable file
@@ -0,0 +1,6 @@
|
||||
Click an item on the left and it will appear here. Read it, decide if it's applicable to the category, and then select "Approve" or "Deny".
|
||||
<!--
|
||||
<?_c <LJDEP>
|
||||
# None
|
||||
</LJDEP> _c?>
|
||||
-->
|
||||
106
livejournal/htdocs/admin/topics/screen_links.bml
Executable file
@@ -0,0 +1,106 @@
|
||||
<?_code
|
||||
|
||||
my ($ret, $sth);
|
||||
|
||||
my $remote = LJ::get_remote();
|
||||
my %cataccess;
|
||||
|
||||
unless (LJ::remote_has_priv($remote, "topicscreencat", \%cataccess)) {
|
||||
return "You don't have access to do this, or you're not logged in.";
|
||||
}
|
||||
|
||||
my $dbh = LJ::get_db_writer();
|
||||
|
||||
my $and_cat_in = "";
|
||||
unless ($cataccess{'all'}) {
|
||||
my $in = join(", ", map { $dbh->quote($_); } keys %cataccess);
|
||||
$and_cat_in = "AND tl.tpcatid IN ($in)";
|
||||
}
|
||||
|
||||
$sth = $dbh->prepare("SELECT tm.tpmapid, tm.tptopid, tm.itemid FROM topic_map tm, topic_list tl WHERE tm.tptopid=tl.tptopid AND tm.status='new' $and_cat_in LIMIT 50");
|
||||
$sth->execute;
|
||||
if ($dbh->err) { return $dbh->errstr; }
|
||||
my %topic;
|
||||
while (my $map = $sth->fetchrow_hashref)
|
||||
{
|
||||
push @maps, $map;
|
||||
$topic{$map->{'tptopid'}} = undef;
|
||||
}
|
||||
|
||||
unless (@maps) {
|
||||
return "<B>Empty!</B> ... no items are awaiting approval";
|
||||
}
|
||||
|
||||
my $top_in = join(",", keys %topic);
|
||||
$sth = $dbh->prepare("SELECT tptopid, tpcatid, topname FROM topic_list WHERE tptopid IN ($top_in)");
|
||||
$sth->execute;
|
||||
if ($dbh->err) { return $dbh->errstr; }
|
||||
my %cat;
|
||||
while (my $top = $sth->fetchrow_hashref)
|
||||
{
|
||||
$topic{$top->{'tptopid'}} = $top;
|
||||
$cat{$top->{'tpcatid'}} = undef;
|
||||
}
|
||||
|
||||
my $cat_in = join(",", keys %cat);
|
||||
$sth = $dbh->prepare("SELECT tpcatid, parent, catname FROM topic_cats WHERE tpcatid IN ($cat_in)");
|
||||
$sth->execute;
|
||||
if ($dbh->err) { return $dbh->errstr; }
|
||||
while (my $cat = $sth->fetchrow_hashref)
|
||||
{
|
||||
$cat{$cat->{'tpcatid'}} = $cat;
|
||||
}
|
||||
|
||||
$ret .= "<FORM METHOD=POST ACTION=\"screen_do.bml\">";
|
||||
|
||||
foreach my $map (@maps)
|
||||
{
|
||||
my $catid = $topic{$map->{'tptopid'}}->{'tpcatid'};
|
||||
next unless ($cataccess{'all'} || $cataccess{$catid});
|
||||
&load_cats_up($catid, \%cat);
|
||||
$ret .= "<P>";
|
||||
my $fullcat;
|
||||
my $catup = $catid;
|
||||
while ($catup) {
|
||||
$fullcat = "$cat{$catup}->{'catname'} : $fullcat";
|
||||
$catup = $cat{$catup}->{'parent'};
|
||||
}
|
||||
$fullcat .= $topic{$map->{'tptopid'}}->{'topname'};
|
||||
$ret .= "<B><FONT SIZE=-1>[$fullcat]</FONT></B>";
|
||||
$ret .= "<BR><A HREF=\"/talkread.bml?itemid=$map->{'itemid'}\" TARGET=\"main\">$map->{'itemid'}</A>";
|
||||
my %opts = ("L" => "Leave", "A" => "Approve", "D" => "Deny");
|
||||
foreach (qw(L A D)) {
|
||||
$ret .= "<BR><INPUT TYPE=RADIO NAME=\"action:$map->{'tptopid'}:$map->{'itemid'}\" VALUE=\"$_\">$opts{$_}\n";
|
||||
}
|
||||
}
|
||||
|
||||
$ret .= "<P><INPUT TYPE=SUBMIT VALUE=\"Submit\"></FORM>";
|
||||
|
||||
return $ret;
|
||||
|
||||
sub load_cats_up
|
||||
{
|
||||
my $catid = shift;
|
||||
my $hashref = shift;
|
||||
$catid += 0;
|
||||
while ($catid)
|
||||
{
|
||||
unless ($hashref->{$catid}) {
|
||||
$sth = $dbh->prepare("SELECT parent, catname FROM topic_cats WHERE tpcatid=$catid");
|
||||
$sth->execute;
|
||||
my $cat = $sth->fetchrow_hashref;
|
||||
if ($cat) {
|
||||
$hashref->{$catid} = $cat;
|
||||
$catid = $cat->{'parent'}
|
||||
}
|
||||
} else {
|
||||
$catid = $hashref->{$catid}->{'parent'};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_code?><?_c <LJDEP>
|
||||
link: htdocs/talkpost.bml
|
||||
post: htdocs/admin/topics/screen_links.bml
|
||||
</LJDEP> _c?>
|
||||
|
||||
87
livejournal/htdocs/admin/topics/screentop.bml
Executable file
@@ -0,0 +1,87 @@
|
||||
<?page
|
||||
title=>Screen Topics
|
||||
body<=
|
||||
|
||||
<?_code
|
||||
|
||||
my $dbh = LJ::get_db_writer();
|
||||
|
||||
my ($ret, $sth);
|
||||
|
||||
my $remote = LJ::get_remote();
|
||||
my %cataccess;
|
||||
unless (LJ::remote_has_priv($remote, "topicscreencat", \%cataccess)) {
|
||||
return "You don't have access to do this, or you're not logged in.";
|
||||
}
|
||||
my $and_cat_in = "";
|
||||
unless ($cataccess{'all'}) {
|
||||
my $in = join(", ", map { $dbh->quote($_); } keys %cataccess);
|
||||
$and_cat_in = "AND tpcatid IN ($in)";
|
||||
}
|
||||
|
||||
$sth = $dbh->prepare("SELECT tptopid, tpcatid, topname FROM topic_list WHERE status='new' $and_cat_in");
|
||||
$sth->execute;
|
||||
if ($dbh->err) { return $dbh->errstr; }
|
||||
|
||||
@new = ();
|
||||
push @new, $_ while ($_ = $sth->fetchrow_hashref);
|
||||
|
||||
unless (@new) {
|
||||
return "<B>Empty!</B> ... no topics are awaiting approval";
|
||||
}
|
||||
|
||||
$ret .= "<FORM METHOD=POST ACTION=\"screentop_do.bml\">";
|
||||
|
||||
my $count = 0;
|
||||
foreach my $new (@new)
|
||||
{
|
||||
next if (++$count > 50);
|
||||
&load_cats_up($new->{'tpcatid'}, \%cat);
|
||||
$ret .= "<P>";
|
||||
my $fullcat;
|
||||
my $catup = $new->{'tpcatid'};
|
||||
while ($catup) {
|
||||
$fullcat = "$cat{$catup}->{'catname'} : $fullcat";
|
||||
$catup = $cat{$catup}->{'parent'};
|
||||
}
|
||||
$fullcat =~ s/\s+:\s+$//;
|
||||
$ret .= "<B><FONT SIZE=-1>[$fullcat]</FONT></B>";
|
||||
$ret .= "<BR>$new->{'topname'}";
|
||||
my %opts = ("L" => "Leave", "A" => "Approve", "D" => "Deny");
|
||||
foreach (qw(L A D)) {
|
||||
$ret .= "<BR><INPUT TYPE=RADIO NAME=\"action:$new->{'tptopid'}\" VALUE=\"$_\">$opts{$_}\n";
|
||||
}
|
||||
}
|
||||
|
||||
$ret .= "<P><INPUT TYPE=SUBMIT VALUE=\"Submit\"></FORM>";
|
||||
|
||||
return $ret;
|
||||
|
||||
sub load_cats_up
|
||||
{
|
||||
my $catid = shift;
|
||||
my $hashref = shift;
|
||||
$catid += 0;
|
||||
while ($catid)
|
||||
{
|
||||
unless ($hashref->{$catid}) {
|
||||
$sth = $dbh->prepare("SELECT parent, catname FROM topic_cats WHERE tpcatid=$catid");
|
||||
$sth->execute;
|
||||
my $cat = $sth->fetchrow_hashref;
|
||||
if ($cat) {
|
||||
$hashref->{$catid} = $cat;
|
||||
$catid = $cat->{'parent'}
|
||||
}
|
||||
} else {
|
||||
$catid = $hashref->{$catid}->{'parent'};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
_code?>
|
||||
<=body
|
||||
page?><?_c <LJDEP>
|
||||
post: htdocs/admin/topics/screentop_do.bml
|
||||
</LJDEP> _c?>
|
||||
|
||||
18
livejournal/htdocs/admin/topics/screentop.html
Executable file
@@ -0,0 +1,18 @@
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<TITLE>Topic Directory Administration</TITLE>
|
||||
</HEAD>
|
||||
|
||||
<FRAMESET COLS="150,100%">
|
||||
<FRAME NAME="links" SRC="screen_links.bml">
|
||||
<FRAME NAME="main" SRC="screen_instructions.bml">
|
||||
</FRAMESET>
|
||||
|
||||
|
||||
</HTML>
|
||||
|
||||
<!--
|
||||
<?_c <LJDEP>
|
||||
link: htdocs/admin/topics/screen_links.bml, htdocs/admin/topics/screen_instructions.bml
|
||||
</LJDEP> _c?>
|
||||
-->
|
||||
49
livejournal/htdocs/admin/topics/screentop_do.bml
Executable file
@@ -0,0 +1,49 @@
|
||||
<?_code
|
||||
|
||||
my $remote = LJ::get_remote();
|
||||
|
||||
unless (LJ::remote_has_priv($remote, "topicaddtopic")) {
|
||||
return "You don't have access to do this, or you're not logged in.";
|
||||
}
|
||||
|
||||
my $dbh = LJ::get_db_writer();
|
||||
my $sth;
|
||||
|
||||
my $ret;
|
||||
|
||||
foreach my $field (keys %FORM)
|
||||
{
|
||||
next unless ($field =~ /^action:(\d+)$/);
|
||||
my $act = $FORM{$field};
|
||||
next if ($act eq "L");
|
||||
|
||||
my $topid = $1;
|
||||
|
||||
if ($act eq "A") {
|
||||
$sth = $dbh->prepare("UPDATE topic_list SET status='on' WHERE tptopid=$topid AND status='new'");
|
||||
$sth->execute;
|
||||
if ($sth->rows) {
|
||||
$ret .= "<B>$topid</B> approved.<BR>\n";
|
||||
} else {
|
||||
$ret .= "<B>$topid</B> already acted on.<BR>\n";
|
||||
}
|
||||
}
|
||||
if ($act eq "D") {
|
||||
$sth = $dbh->prepare("UPDATE topic_list SET status='deny' WHERE tptopid=$topid AND status='new'");
|
||||
$sth->execute;
|
||||
if ($sth->rows) {
|
||||
$ret .= "<B>$topid</B> denied.<BR>\n";
|
||||
} else {
|
||||
$ret .= "<B>$topid</B> already acted on.<BR>\n";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return $ret;
|
||||
|
||||
_code?><?_c <LJDEP>
|
||||
# None
|
||||
</LJDEP> _c?>
|
||||
|
||||
12
livejournal/htdocs/admin/topics/start.bml
Executable file
@@ -0,0 +1,12 @@
|
||||
<FORM TARGET="links" ACTION="links.bml" METHOD=GET>
|
||||
Username to preview:
|
||||
<INPUT NAME="user" SIZE=15 MAXLENGTH=15>
|
||||
|
||||
<P><INPUT TYPE="SUBMIT" VALUE="Make links">
|
||||
</FORM>
|
||||
|
||||
<!--
|
||||
<?_c <LJDEP>
|
||||
post: htdocs/admin/topics/links.bml
|
||||
</LJDEP> _c?>
|
||||
-->
|
||||
111
livejournal/htdocs/admin/userlog.bml
Executable file
@@ -0,0 +1,111 @@
|
||||
<?page
|
||||
title=>User Log Viewer
|
||||
head<=
|
||||
<style>
|
||||
<!--
|
||||
td.logrow {
|
||||
border: solid 1px rgb(230,230,230);
|
||||
padding: 2px;
|
||||
margin: 0px;
|
||||
}
|
||||
th.logrow {
|
||||
border: solid 1px rgb(180,180,180);
|
||||
padding: 2px;
|
||||
margin: 0px;
|
||||
text-weight: bold;
|
||||
}
|
||||
-->
|
||||
</style>
|
||||
<=head
|
||||
body<=
|
||||
<?_code
|
||||
{
|
||||
use strict;
|
||||
use vars qw($GET $POST);
|
||||
|
||||
my $remote = LJ::get_remote();
|
||||
return "<?needlogin?>" unless $remote;
|
||||
|
||||
my $err = sub {
|
||||
return "<?h1 Error h1?><?p $_[0] p?>";
|
||||
};
|
||||
|
||||
return $err->("You do not have the necessary privilege to view this page.")
|
||||
unless LJ::check_priv($remote, 'canview', 'userlog') ||
|
||||
LJ::check_priv($remote, 'canview', '*');
|
||||
|
||||
my $user = LJ::canonical_username($POST{user});
|
||||
|
||||
my $ret = <<FORM;
|
||||
<form method='post' action='userlog.bml'>
|
||||
Username: <input type='text' name='user' value='$user' maxlength='15' size='15' /> <input type='submit' value='View' />
|
||||
</form>
|
||||
FORM
|
||||
return $ret unless $user;
|
||||
|
||||
my $u = LJ::load_user($user);
|
||||
return $err->("User does not exist.")
|
||||
unless $u;
|
||||
|
||||
my $dbcr = LJ::get_cluster_reader($u);
|
||||
return $err->("Unable to get user cluster reader.")
|
||||
unless $dbcr;
|
||||
|
||||
my $sth = $dbcr->prepare('SELECT * FROM userlog WHERE userid = ? ORDER BY logtime DESC LIMIT 1000');
|
||||
$sth->execute($u->{userid});
|
||||
return $err->("Database error: " . $sth->errstr)
|
||||
if $sth->err;
|
||||
|
||||
$ret .= "<?p Latest log entries for " . LJ::ljuser($u) . ". p?>";
|
||||
$ret .= "<table style='border: solid 1px black; width: 95%;'>\n";
|
||||
$ret .= "<tr>";
|
||||
$ret .= join('', map { "<th class='logrow'>$_</th>" } ("Date and Time", "Action", "Initiator", "IP Address", "Uniq Cookie"));
|
||||
$ret .= "</tr>\n";
|
||||
|
||||
while (my $row = $sth->fetchrow_hashref) {
|
||||
my $extra = {};
|
||||
LJ::decode_url_string($row->{extra}, $extra);
|
||||
|
||||
my $action = "Action undefined for: $row->{action}";
|
||||
if ($row->{action} eq 'delete_entry') {
|
||||
$action = "Deleted entry $row->{actiontarget} via $extra->{method}";
|
||||
} elsif ($row->{action} eq 'account_create') {
|
||||
$action = "Account created";
|
||||
} elsif ($row->{action} eq 'ban_set') {
|
||||
my $u = LJ::load_userid($row->{actiontarget});
|
||||
$action = "Banned " . LJ::ljuser($u) if $u;
|
||||
} elsif ($row->{action} eq 'ban_unset') {
|
||||
my $u = LJ::load_userid($row->{actiontarget});
|
||||
$action = "Unbanned " . LJ::ljuser($u) if $u;
|
||||
} elsif ($row->{action} eq 'maintainer_add') {
|
||||
my $u = LJ::load_userid($row->{actiontarget});
|
||||
$action = "Added maintainer " . LJ::ljuser($u) if $u;
|
||||
} elsif ($row->{action} eq 'maintainer_remove') {
|
||||
my $u = LJ::load_userid($row->{actiontarget});
|
||||
$action = "Removed maintainer " . LJ::ljuser($u) if $u;
|
||||
} else {
|
||||
$action = "Unknown action ($row->{action})";
|
||||
}
|
||||
|
||||
my $time = LJ::mysql_time($row->{logtime});
|
||||
|
||||
my $actor;
|
||||
if ($row->{remoteid}) {
|
||||
my $u = LJ::load_userid($row->{remoteid});
|
||||
$actor = LJ::ljuser($u);
|
||||
} else {
|
||||
$actor = "<em>not recorded</em>";
|
||||
}
|
||||
|
||||
my $ip = $row->{ip} || "<em>not recorded</em>";
|
||||
my $uniq = $row->{uniq} || "<em>not recorded</em>";
|
||||
|
||||
$ret .= "<tr>" . join('', map { "<td class='logrow'>$_</td>" } ($time, $action, $actor, $ip, $uniq)) . "</tr>\n";
|
||||
}
|
||||
|
||||
$ret .= "</table>";
|
||||
return $ret;
|
||||
}
|
||||
_code?>
|
||||
<=body
|
||||
page?>
|
||||
184
livejournal/htdocs/allpics.bml
Executable file
@@ -0,0 +1,184 @@
|
||||
<?_code
|
||||
{
|
||||
use strict;
|
||||
use vars qw(%GET $title $body $head);
|
||||
|
||||
$title = "$ML{'.title'}";
|
||||
$body = "";
|
||||
$head = "";
|
||||
|
||||
my $user = LJ::canonical_username($GET{'user'});
|
||||
my $remote = LJ::get_remote();
|
||||
my $u = ! $user || $remote && $remote->{'user'} eq $user ? $remote : LJ::load_user($user);
|
||||
|
||||
unless ($u) {
|
||||
$body = "<?h1 $ML{'Error'} h1?><?p $ML{'.error.noparam'} p?>";
|
||||
return;
|
||||
}
|
||||
|
||||
LJ::load_user_props($u, "opt_blockrobots") if $u->{'statusvis'} eq 'V';
|
||||
if ($u->{'statusvis'} ne 'V' || $u->{'opt_blockrobots'}) {
|
||||
$head .= LJ::robot_meta_tags();
|
||||
}
|
||||
|
||||
# no need for viewsome, due to the fact that none of this is private anyway. just
|
||||
# allow anybody with any version of viewall to see userpics for non-V statusvis users
|
||||
if ($GET{viewall} && LJ::check_priv($remote, 'canview')) {
|
||||
LJ::statushistory_add($u->{'userid'}, $remote->{'userid'},
|
||||
"viewall", "allpics: $u->{'user'}, statusvis: $u->{'statusvis'}");
|
||||
} else {
|
||||
if ($u->{'statusvis'} eq "S") {
|
||||
$title = $ML{'error.suspended.title'};
|
||||
$body = "<?h1 $ML{'error.suspended.name'} h1?><?p " .
|
||||
BML::ml('error.suspended.text', { 'user' => LJ::ljuser($u),
|
||||
'sitename' => $LJ::SITENAME }) . " p?>";
|
||||
return;
|
||||
}
|
||||
|
||||
if ($u->{'statusvis'} eq "D") {
|
||||
$title = $ML{'error.deleted.title'};
|
||||
$body = "<?h1 $ML{'error.deleted.name'} h1?><?p " .
|
||||
BML::ml('error.deleted.text', { 'user' => LJ::ljuser($u) }) .
|
||||
" p?>";
|
||||
return;
|
||||
}
|
||||
|
||||
if ($u->{'statusvis'} eq "X") {
|
||||
$title = $ML{'error.purged.title'};
|
||||
$body = "<?h1 $ML{'error.purged.name'} h1?><?p " .
|
||||
BML::ml('error.purged.text', { 'user' => LJ::ljuser($u) }) .
|
||||
" p?>";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
# redirect renamed users
|
||||
if ($u->{'journaltype'} eq "R") {
|
||||
LJ::load_user_props($u, "renamedto");
|
||||
return BML::redirect("$LJ::SITEROOT/allpics.bml?user=$u->{'renamedto'}")
|
||||
if $u->{'renamedto'};
|
||||
}
|
||||
|
||||
my ($can_manage, $getextra);
|
||||
if ($remote) {
|
||||
$can_manage = LJ::can_manage($remote, $u->{'userid'});
|
||||
$getextra = $can_manage && $remote->{'user'} ne $u->{'user'} ? "?authas=$u->{'user'}" : '';
|
||||
}
|
||||
|
||||
#### show pictures
|
||||
|
||||
my $info = LJ::get_userpic_info($u, {'load_comments' => 1, 'load_urls' => 1});
|
||||
|
||||
my %keywords = ();
|
||||
while (my ($kw, $pic) = each %{$info->{'kw'}}) {
|
||||
LJ::text_out(\$kw);
|
||||
push @{$keywords{$pic->{'picid'}}}, $kw;
|
||||
}
|
||||
|
||||
my %comments = ();
|
||||
while (my ($pic, $comment) = each %{$info->{'comment'}}) {
|
||||
LJ::text_out(\$comment);
|
||||
$comments{$pic} = $comment;
|
||||
}
|
||||
|
||||
my $piccount = 0;
|
||||
|
||||
my @pics;
|
||||
my $defaultpicid = $u ? $u->{'defaultpicid'} : undef;
|
||||
push @pics, $info->{'pic'}->{$u->{'defaultpicid'}} if $defaultpicid;
|
||||
push @pics, map { $info->{'pic'}->{$_} } sort { $a <=> $b }
|
||||
grep { $_ != $defaultpicid && ($info->{'pic'}->{$_}->{'state'} eq 'N' || $can_manage) &&
|
||||
$info->{'pic'}->{$_}->{'state'} ne 'X' }
|
||||
keys %{$info->{'pic'}};
|
||||
|
||||
foreach my $pic (@pics) {
|
||||
|
||||
if ($piccount++ == 0) {
|
||||
$body .= "<?h1 $ML{'.current'} h1?><?p ";
|
||||
$body .= BML::ml('.pics', {'user'=> LJ::ljuser($u)});
|
||||
if ($can_manage) {
|
||||
$body .= ' ' . BML::ml('.edit2',
|
||||
{ 'editlink' => "$LJ::SITEROOT/editpics.bml$getextra",
|
||||
'uploadlink' => "$LJ::SITEROOT/editpics.bml$getextra#upload" });
|
||||
}
|
||||
$body .= " p?><div style='margin-left: 50px;'><table cellpadding='5' border='0' cellspacing='1'>";
|
||||
}
|
||||
|
||||
### Keywords
|
||||
my $eh_keywords = join(", ", sort { lc($a) cmp lc($b) } @{$keywords{$pic->{'picid'}}||[]});
|
||||
$eh_keywords = LJ::ehtml($eh_keywords);
|
||||
|
||||
if ($piccount % 2 == 1) {
|
||||
$body .= "<tr valign='middle'>";
|
||||
}
|
||||
|
||||
$body .= "<td align='center'>";
|
||||
|
||||
my ($apre, $apost);
|
||||
if ($pic->{'url'}) {
|
||||
$apre = "<a href='" . LJ::ehtml($pic->{'url'}) . "'>";
|
||||
$apost = "</a>";
|
||||
}
|
||||
|
||||
$body .= "$apre<img src='$LJ::USERPIC_ROOT/$pic->{'picid'}/$u->{'userid'}' ";
|
||||
$body .= "width='$pic->{'width'}' height='$pic->{'height'}' alt='' border='0'/>$apost</td><td>";
|
||||
|
||||
if ($u->{'defaultpicid'} == $pic->{'picid'}) {
|
||||
$body .= "$ML{'.default'}<br />";
|
||||
}
|
||||
|
||||
if ($can_manage && $pic->{'state'} eq 'I') {
|
||||
$body .= "<i>[$ML{'userpic.inactive'}]</i> " . LJ::help_icon('userpic_inactive') . "<br />";
|
||||
}
|
||||
|
||||
if ($eh_keywords) {
|
||||
$body .= "<b>$ML{'.keywords'}</b> $eh_keywords<br />";
|
||||
}
|
||||
|
||||
# Comments
|
||||
my $eh_comments = $comments{$pic->{'picid'}};
|
||||
if ($eh_comments) {
|
||||
LJ::CleanHTML::clean(\$eh_comments, {
|
||||
'wordlength' => 40,
|
||||
'addbreaks' => 0,
|
||||
'tablecheck' => 1,
|
||||
'mode' => 'deny',
|
||||
});
|
||||
|
||||
$body .= "$eh_comments\n";
|
||||
}
|
||||
|
||||
$body .= "</td>";
|
||||
|
||||
if ($piccount % 2 == 1) {
|
||||
$body .= "<td width='50px'></td>";
|
||||
} else {
|
||||
$body .= "</tr>\n";
|
||||
}
|
||||
}
|
||||
|
||||
if ($piccount) {
|
||||
if ($piccount % 2 == 1) {
|
||||
# finish off this row.
|
||||
# we need 2 columns: the pic and the text.
|
||||
$body .= "<td colspan='2'></td></tr>";
|
||||
}
|
||||
$body .= "</table></div>";
|
||||
} else {
|
||||
if ($can_manage) {
|
||||
$body = "<?h1 $ML{'.nopics.title'} h1?><?p ";
|
||||
$body .= BML::ml('.nopics.text2', { 'link' => "$LJ::SITEROOT/editpics.bml$getextra#upload" }) . " p?>";
|
||||
} else {
|
||||
$body = "<?h1 $ML{'.nopics.title'} h1?><?p $ML{'.nopics.text.other'} p?>";
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
_code?><?page
|
||||
title=><?_code return $title; _code?>
|
||||
head=><?_code return $head; _code?>
|
||||
body=><?_code return $body; _code?>
|
||||
page?><?_c <LJDEP>
|
||||
link: htdocs/editpics.bml
|
||||
</LJDEP> _c?>
|
||||
112
livejournal/htdocs/approve.bml
Executable file
@@ -0,0 +1,112 @@
|
||||
<?_info
|
||||
nocache=>1
|
||||
_info?><?page
|
||||
title=><?_ml .title _ml?>
|
||||
|
||||
body<=
|
||||
<?_code
|
||||
{
|
||||
use strict;
|
||||
|
||||
my $qs = BML::get_query_string();
|
||||
return LJ::bad_input($ML{'.error.invalidargument'})
|
||||
unless $qs && $qs =~ /^(\d+)\.(.+)$/;
|
||||
|
||||
my ($aaid, $auth) = ($1, $2);
|
||||
my $aa = LJ::is_valid_authaction($aaid, $auth);
|
||||
return LJ::bad_input($ML{'.error.invalidargument'})
|
||||
unless $aa;
|
||||
return LJ::bad_input($ML{'.error.actionperformed'})
|
||||
if $aa->{'used'} eq 'Y';
|
||||
|
||||
my $arg = {};
|
||||
LJ::decode_url_string($aa->{'arg1'}, $arg);
|
||||
|
||||
### perform actions according to the action type
|
||||
|
||||
# invite users to communities
|
||||
if ($aa->{'action'} eq 'comm_invite') {
|
||||
|
||||
my $dbh = LJ::get_db_writer();
|
||||
|
||||
my $targetid = $arg->{'targetid'};
|
||||
return LJ::bad_input($ML{'.error.internerr.invalidaction'}) unless $targetid;
|
||||
|
||||
# add to community
|
||||
if ($arg->{'member'}) {
|
||||
LJ::add_friend($aa->{userid}, $targetid);
|
||||
}
|
||||
|
||||
# set up rels with this community
|
||||
my @rels = ();
|
||||
push @rels, 'A' if $arg->{'admin'};
|
||||
push @rels, 'P' if $arg->{'post'};
|
||||
push @rels, 'M' if $arg->{'moderate'};
|
||||
push @rels, 'N' if $arg->{'preapprove'};
|
||||
|
||||
if (@rels) {
|
||||
LJ::set_rel_multi( map { [$aa->{userid}, $targetid, $_] } @rels );
|
||||
}
|
||||
|
||||
# mark this authaction as used
|
||||
$dbh->do("UPDATE authactions SET used='Y' WHERE aaid=?", undef, $aa->{'aaid'});
|
||||
|
||||
# return success
|
||||
my $username = LJ::get_username($aa->{'userid'});
|
||||
return "<?h1 $ML{'.comm.success'} h1?>".
|
||||
'<?p '.BML::ml('.comm.text',
|
||||
{'comm'=>LJ::ljuser($username, { 'type' => 'C' }),
|
||||
'aopts'=>'href="'.$LJ::SITEROOT.'/friends/add.bml?user='.$username.'"'}).
|
||||
' p?>';
|
||||
}
|
||||
|
||||
# invite users to shared journals
|
||||
if ($aa->{'action'} eq 'shared_invite') {
|
||||
my $dbh = LJ::get_db_writer();
|
||||
|
||||
my $targetid = $arg->{'targetid'};
|
||||
return LJ::bad_input($ML{'.error.internerr.invalidaction'}) unless $targetid;
|
||||
|
||||
LJ::set_rel($aa->{'userid'}, $targetid, 'P');
|
||||
|
||||
# mark this authaction as used
|
||||
$dbh->do("UPDATE authactions SET used='Y' WHERE aaid=?", undef, $aa->{'aaid'});
|
||||
|
||||
my $username = LJ::get_username($aa->{'userid'});
|
||||
return "<?h1 $ML{'.shared.success'} h1?>".
|
||||
'<?p '.BML::ml('.shared.text',
|
||||
{'shared'=>LJ::ljuser($username, { 'type' => 'S' }),
|
||||
'aopts'=>'href="'.$LJ::SITEROOT.'/friends/add.bml?user='.$username.'"'}).
|
||||
' p?>';
|
||||
}
|
||||
|
||||
# approve someone joining a community
|
||||
if ($aa->{action} eq 'comm_join_request') {
|
||||
my $dbh = LJ::get_db_writer();
|
||||
|
||||
# get user we're adding
|
||||
my $targetid = $arg->{targetid};
|
||||
return LJ::bad_input($ML{'.error.internerr.invalidaction'}) unless $targetid;
|
||||
|
||||
# add to community
|
||||
return "<?h1 $ML{'Error'} h1?><?p $ML{'.error.approving'} p?>"
|
||||
unless LJ::approve_pending_member($aa->{userid}, $targetid);
|
||||
|
||||
# return success
|
||||
my $commname = LJ::get_username($aa->{userid});
|
||||
my $username = LJ::get_username($targetid);
|
||||
return "<?h1 $ML{'.comm.success'} h1?>".
|
||||
'<?p ' . BML::ml('.commjoin.text', {
|
||||
user => LJ::ljuser($username, { type => 'P' }),
|
||||
comm => LJ::ljuser($commname, { type => 'C' }),
|
||||
aopts => "href=\"$LJ::SITEROOT/community/members.bml?comm=$commname\"",
|
||||
}) . ' p?>';
|
||||
}
|
||||
|
||||
# not other action types right now
|
||||
return LJ::bad_input($ML{'.error.unknownactiontype'});
|
||||
}
|
||||
_code?>
|
||||
|
||||
<=body
|
||||
page?>
|
||||
92
livejournal/htdocs/birthdays.bml
Executable file
@@ -0,0 +1,92 @@
|
||||
<?page
|
||||
title=><?_ml .title _ml?>
|
||||
body<=
|
||||
<?_code
|
||||
{
|
||||
use strict;
|
||||
use vars qw(%GET);
|
||||
|
||||
LJ::set_active_crumb('birthdays');
|
||||
|
||||
my $remote = LJ::get_remote();
|
||||
return "<?needlogin?>" unless $remote;
|
||||
|
||||
my $u;
|
||||
if ($GET{user}) {
|
||||
$u = LJ::load_user($GET{user});
|
||||
return BML::ml('.error.invaliduser', { user => LJ::ehtml($GET{user}) })
|
||||
unless $u;
|
||||
return BML::ml('.error.badstatus', { user => LJ::ljuser($u->{user}) })
|
||||
if $u->{statusvis} ne 'V';
|
||||
}
|
||||
|
||||
my $body;
|
||||
my $lastmon = 0;
|
||||
|
||||
$body .= "<?p $ML{'.findothers'} p?>";
|
||||
$body .= "<form method='get' action='$LJ::SITEROOT/birthdays.bml'>";
|
||||
$body .= LJ::html_text({ name => 'user', maxlength => 15, size => 15 });
|
||||
$body .= LJ::html_submit(undef, $ML{'.view'});
|
||||
$body .= "</form>";
|
||||
|
||||
$body .= '<?p ';
|
||||
if ($u) {
|
||||
$body .= BML::ml('.description.others', { user => LJ::ljuser($u) });
|
||||
} else {
|
||||
$body .= $ML{'.description'};
|
||||
}
|
||||
$body .= ' p?>';
|
||||
|
||||
# TAG:fr:bml_birthdays:get_bdays
|
||||
my $dbr = LJ::get_db_reader();
|
||||
my $sth = $dbr->prepare(
|
||||
qq|SELECT u.user, u.name, MONTH(bdate) AS 'month', DAYOFMONTH(bdate) AS 'day'
|
||||
FROM friends f, user u
|
||||
WHERE f.userid = ?
|
||||
AND f.friendid = u.userid
|
||||
AND u.journaltype = 'P'
|
||||
AND u.statusvis = 'V'
|
||||
AND u.allow_infoshow = 'Y'
|
||||
AND MONTH(bdate) != 0
|
||||
AND DAYOFMONTH(bdate) != 0
|
||||
LIMIT 750|);
|
||||
$sth->execute($u ? $u->{userid} : $remote->{userid});
|
||||
|
||||
my @bdays;
|
||||
push @bdays, $_ while $_ = $sth->fetchrow_hashref;
|
||||
@bdays = sort {
|
||||
($a->{'month'} <=> $b->{'month'}) ||
|
||||
($a->{'day'} <=> $b->{'day'}) ||
|
||||
($a->{'user'} cmp $b->{'user'})
|
||||
} @bdays;
|
||||
|
||||
foreach my $bday (@bdays) {
|
||||
LJ::text_out(\$bday->{'name'});
|
||||
|
||||
if ($bday->{'month'} != $lastmon) {
|
||||
if ($lastmon) { $body .= "</ul>\n"; }
|
||||
$lastmon = $bday->{'month'};
|
||||
$body .= "<?h1 " . LJ::Lang::month_long($lastmon) . " h1?><ul>\n";
|
||||
}
|
||||
|
||||
my $day = sprintf("%2s", $bday->{'day'});
|
||||
$day =~ s/ / /;
|
||||
|
||||
my $name = LJ::ehtml($bday->{'name'});
|
||||
$body .= "<b><tt>$day</tt></b>: " . LJ::ljuser($bday->{'user'}) . " - $name<br />\n";
|
||||
}
|
||||
|
||||
if (@bdays) {
|
||||
$body .= "</ul>\n";
|
||||
} else {
|
||||
$body .= "<?p $ML{'.nobirthdays'} p?>";
|
||||
}
|
||||
|
||||
return $body;
|
||||
}
|
||||
_code?>
|
||||
<=body
|
||||
page?><?_c <LJDEP>
|
||||
link: htdocs/login.bml
|
||||
</LJDEP> _c?>
|
||||
|
||||
35
livejournal/htdocs/captcha/audio.bml
Executable file
@@ -0,0 +1,35 @@
|
||||
<?_code
|
||||
{
|
||||
my ($capid, $anum) = ($GET{capid}, $GET{anum});
|
||||
($capid, $anum) = LJ::Captcha::session($GET{chal}, 'audio', $GET{cid}) if $GET{chal};
|
||||
return "Error" unless $capid && $anum;
|
||||
|
||||
# determine if we are talking to someone interested in reproxying for us
|
||||
my $can_reproxy = 0;
|
||||
unless ($LJ::REPROXY_DISABLE{captchas}) {
|
||||
my $hdr = BML::get_client_header('X-Proxy-Capabilities');
|
||||
$can_reproxy = $hdr && $hdr =~ m{\breproxy-file\b}i;
|
||||
}
|
||||
|
||||
my $wav;
|
||||
eval { $wav = LJ::Captcha::get_audio_data($capid, $anum, $can_reproxy); };
|
||||
print STDERR "$can_reproxy\n";
|
||||
if (ref $wav eq 'ARRAY') {
|
||||
return "Error: unable to handle array without reproxy\n" unless $can_reproxy;
|
||||
return "Error: captcha not available (no paths)\n" unless scalar @$wav;
|
||||
if ($wav->[0] =~ m!http://!) {
|
||||
Apache->request->header_out('X-REPROXY-URL', join(' ', @$wav));
|
||||
} else {
|
||||
Apache->request->header_out('X-REPROXY-FILE', $wav->[0]);
|
||||
}
|
||||
BML::set_content_type("audio/x-wav");
|
||||
|
||||
} elsif ($wav) {
|
||||
BML::set_content_type("audio/x-wav");
|
||||
return BML::noparse($wav);
|
||||
} else {
|
||||
return "Error: $@";
|
||||
}
|
||||
|
||||
}
|
||||
_code?>
|
||||
34
livejournal/htdocs/captcha/image.bml
Executable file
@@ -0,0 +1,34 @@
|
||||
<?_code
|
||||
{
|
||||
my ($capid, $anum) = ($GET{capid}, $GET{anum});
|
||||
($capid, $anum) = LJ::Captcha::session($GET{chal}, 'image', $GET{cid}) if $GET{chal};
|
||||
return "Error" unless $capid && $anum;
|
||||
|
||||
# determine if we are talking to someone interested in reproxying for us
|
||||
my $can_reproxy = 0;
|
||||
unless ($LJ::REPROXY_DISABLE{captchas}) {
|
||||
my $hdr = BML::get_client_header('X-Proxy-Capabilities');
|
||||
$can_reproxy = $hdr && $hdr =~ m{\breproxy-file\b}i;
|
||||
}
|
||||
|
||||
my $png;
|
||||
eval { $png = LJ::Captcha::get_visual_data($capid, $anum, $can_reproxy); };
|
||||
if (ref $png eq 'ARRAY') {
|
||||
return "Error: unable to handle array without reproxy\n" unless $can_reproxy;
|
||||
return "Error: captcha not available (no paths)\n" unless scalar @$png;
|
||||
if ($png->[0] =~ m!http://!) {
|
||||
Apache->request->header_out('X-REPROXY-URL', join(' ', @$png));
|
||||
} else {
|
||||
Apache->request->header_out('X-REPROXY-FILE', $png->[0]);
|
||||
}
|
||||
BML::set_content_type("image/png");
|
||||
|
||||
} elsif ($png) {
|
||||
BML::set_content_type("image/png");
|
||||
return BML::noparse($png);
|
||||
} else {
|
||||
return "Error: $@";
|
||||
}
|
||||
|
||||
}
|
||||
_code?>
|
||||
165
livejournal/htdocs/changepassword.bml
Executable file
@@ -0,0 +1,165 @@
|
||||
<?page
|
||||
title=><?_ml .title _ml?>
|
||||
body<=
|
||||
<?_code
|
||||
|
||||
use strict;
|
||||
|
||||
my $body;
|
||||
|
||||
if ($LJ::SERVER_DOWN) {
|
||||
$body = LJ::server_down_html();
|
||||
return $body;
|
||||
}
|
||||
|
||||
if ($LJ::USE_SSL && ! $LJ::IS_SSL && $FORM{'ssl'} ne "no") {
|
||||
return BML::redirect("$LJ::SSLROOT/changepassword.bml");
|
||||
}
|
||||
|
||||
my $crumb = $LJ::IS_SSL ? 'securechangepass' : 'changepass';
|
||||
LJ::set_active_crumb($crumb);
|
||||
|
||||
my $update_form = sub {
|
||||
my $ret;
|
||||
|
||||
# else, show the form to change:
|
||||
$ret .= "<form action='changepassword.bml' method='post'>\n";
|
||||
$ret .= LJ::html_hidden(mode => 'submit',
|
||||
ssl => $GET{'ssl'});
|
||||
|
||||
$ret .= "<?h1 $ML{'.changepassword.header'} h1?>\n";
|
||||
$ret .= "<?p $ML{'.changepassword.instructions'} p?>\n";
|
||||
|
||||
my $remote = LJ::get_remote();
|
||||
|
||||
# Warn them if logged in and not validated
|
||||
if (!LJ::did_post() && $remote && $remote->{'status'} ne 'A') {
|
||||
$ret .= "<?warningbar <b>$ML{'label.warning'}</b> $ML{'.error.notvalidated'} warningbar?>";
|
||||
$ret .= "<br />";
|
||||
}
|
||||
|
||||
$ret .= "<?standout\n";
|
||||
$ret .= "$ML{'Username'}:<br />\n";
|
||||
|
||||
# we make the field for the new password *longer* than the max length
|
||||
# for a password - that way we can tell if someone is trying to use an
|
||||
# excessively long password, instead of silently truncating it.
|
||||
|
||||
my $hval = LJ::ehtml($remote ? $remote->{'user'} : $POST{'user'});
|
||||
$ret .= "<input name='user' size='30' maxlength='15' value='$hval' /><br />\n";
|
||||
$ret .= "$ML{'.oldpassword'}<br />\n";
|
||||
$ret .= "<input type='password' name='password' size='30' maxlength='30' /><br />\n";
|
||||
$ret .= "$ML{'.newpassword'}<br />\n";
|
||||
$ret .= "<input type='password' name='newpass1' size='30' maxlength='31' /><br />\n";
|
||||
$ret .= "$ML{'.newpasswordagain'}<br />\n";
|
||||
$ret .= "<input type='password' name='newpass2' size='30' maxlength='31' /><br />\n";
|
||||
$ret .= "standout?>\n";
|
||||
|
||||
$ret .= "<?h1 $ML{'Proceed'} h1?>\n";
|
||||
$ret .= "<?p $ML{'.proceed.instructions'} p?>\n";
|
||||
|
||||
$ret .= "<?standout\n";
|
||||
$ret .= "<input type='submit' value='$ML{'.btn.proceed'}' />\n";
|
||||
$ret .= "standout?>\n";
|
||||
$ret .= "</form>\n";
|
||||
return $ret;
|
||||
};
|
||||
|
||||
unless (LJ::did_post()) {
|
||||
$body .= $update_form->();
|
||||
} elsif ($POST{'mode'} eq 'submit') {
|
||||
my $user = LJ::canonical_username($POST{'user'});
|
||||
my $password = $POST{'password'};
|
||||
my $newpass1 = LJ::trim($POST{'newpass1'});
|
||||
my $newpass2 = LJ::trim($POST{'newpass2'});
|
||||
|
||||
my $remote = LJ::get_remote();
|
||||
my $u = LJ::load_user($user);
|
||||
|
||||
my @errors = ();
|
||||
if ($user eq "test") { push @errors, $ML{'.error.changetestaccount'}; }
|
||||
unless ($user) {
|
||||
push @errors, $ML{'.error.mustenterusername'};
|
||||
} else {
|
||||
unless (defined $u) {
|
||||
push @errors, BML::ml('.error.invaliduser', {'user' => $user} );
|
||||
} else {
|
||||
if (LJ::login_ip_banned($u)) {
|
||||
push @errors, $ML{'error.ipbanned'};
|
||||
} elsif ($u->{'password'} eq "" || $u->{'password'} ne $password) {
|
||||
push @errors, $ML{'.error.badoldpassword'};
|
||||
LJ::handle_bad_login($u);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($newpass1 ne $newpass2) {
|
||||
push @errors, $ML{'.error.badnewpassword'};
|
||||
} else {
|
||||
if ($newpass1 eq "") {
|
||||
push @errors, $ML{'.error.blankpassword'};
|
||||
} elsif (length $newpass1 > 30) {
|
||||
push @errors, $ML{'.error.characterlimit'};
|
||||
} else {
|
||||
|
||||
my @checkpass = LJ::run_hooks("bad_password",
|
||||
{ 'user' => $u->{'user'}, 'password' => $newpass1,
|
||||
'name' => $u->{'name'}, 'email' => $u->{'email'} });
|
||||
if (@checkpass && $checkpass[0]->[0]) {
|
||||
push @errors, BML::ml('.error.badcheck', {'error' => $checkpass[0]->[0]});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# don't allow changes if email address is not validated
|
||||
unless ($u->{'status'} eq 'A') {
|
||||
push @errors, $ML{'.error.notvalidated'};
|
||||
}
|
||||
|
||||
unless (LJ::is_ascii($newpass1)) {
|
||||
push @errors, $ML{'.error.nonascii'};
|
||||
}
|
||||
|
||||
if (@errors) {
|
||||
$body .= LJ::error_list(@errors);
|
||||
$body .= $update_form->();
|
||||
return $body;
|
||||
}
|
||||
|
||||
## make note of changed password
|
||||
my $dbh = LJ::get_db_writer();
|
||||
my $oldval = Digest::MD5::md5_hex($u->{'password'} . "change");
|
||||
LJ::infohistory_add($u, 'password', $oldval);
|
||||
|
||||
LJ::update_user($u, { password => $POST{'newpass1'} });
|
||||
|
||||
# Kill all sessions, forcing user to relogin
|
||||
$u->kill_all_sessions;
|
||||
|
||||
LJ::send_mail({
|
||||
'to' => $u->{'email'},
|
||||
'from' => $LJ::ADMIN_EMAIL,
|
||||
'fromname' => $LJ::SITENAME,
|
||||
'charset' => 'utf-8',
|
||||
'subject' => $ML{'.email.subject'},
|
||||
'body' => BML::ml('.email.body', {'sitename'=>$LJ::SITENAME, 'siteroot'=>$LJ::SITEROOT})});
|
||||
|
||||
$body = "<?h1 $ML{'Success'} h1?><?p $ML{'.success.text'} p?>";
|
||||
|
||||
# if they were logged in, tell them to relogin
|
||||
$body .= "<?p " . BML::ml('.relogin', { 'aopts' => "href='/login.bml'" }) . " p?>" if $remote;
|
||||
|
||||
LJ::run_hooks("post_changepassword", {
|
||||
"u" => $u,
|
||||
"newpassword" => $POST{'newpass1'},
|
||||
"oldpassword" => $u->{'password'},
|
||||
});
|
||||
}
|
||||
|
||||
return $body;
|
||||
_code?>
|
||||
<=body
|
||||
page?><?_c <LJDEP>
|
||||
post: htdocs/changepassword.bml
|
||||
lib: Digest::MD5
|
||||
hook: post_changepassword
|
||||
</LJDEP> _c?>
|
||||
269
livejournal/htdocs/community/create.bml
Executable file
@@ -0,0 +1,269 @@
|
||||
<?page
|
||||
title=><?_ml .title _ml?>
|
||||
body<=
|
||||
<?_code
|
||||
{
|
||||
use strict;
|
||||
use vars qw(%GET %POST);
|
||||
|
||||
LJ::set_active_crumb('createcommunity');
|
||||
|
||||
return LJ::server_down_html() if $LJ::SERVER_DOWN;
|
||||
return "<?badinput?>" unless LJ::text_in(\%POST);
|
||||
|
||||
my $mode = $POST{mode} || 'getinfo';
|
||||
|
||||
my $remote = LJ::get_remote();
|
||||
return "<?needlogin?>" if !$remote;
|
||||
return "<?h1 $ML{'Error'} h1?><?p $ML{'.error.notperson'} p?>"
|
||||
if $remote->{journaltype} ne 'P';
|
||||
return "<?h1 $ML{'Error'} h1?><?p $ML{'.error.notactive'} p?>"
|
||||
unless $remote->{statusvis} eq 'V';
|
||||
|
||||
if ($remote->underage) {
|
||||
return BML::redirect("$LJ::SITEROOT/agecheck/?s=1");
|
||||
}
|
||||
|
||||
# fix up the incoming data (is used in getinfo mode and submit mode so it's here)
|
||||
$POST{membership} = 'open'
|
||||
unless $POST{membership} =~ m/^(?:open|moderated|closed)$/;
|
||||
$POST{postlevel} = 'members'
|
||||
unless $POST{postlevel} =~ m/^(?:members|select)$/;
|
||||
$POST{nonmember_posting} = '0'
|
||||
unless $POST{nonmember_posting} =~ m/^[01]$/;
|
||||
$POST{moderated} = '0'
|
||||
unless $POST{moderated} =~ m/^[01]$/;
|
||||
|
||||
# MODE: submit - try to create an account. might change mode
|
||||
# if there are errors, we'll populate $error and
|
||||
# return to "getinfo" mode below
|
||||
my $error;
|
||||
SUBMIT:
|
||||
while ($mode eq 'submit') # using while instead of if so we can 'last' out of it
|
||||
{
|
||||
return "<b>$ML{'Error'}</b>: $ML{'.error.postrequired'}" unless LJ::did_post();
|
||||
|
||||
my $user = LJ::canonical_username($POST{user});
|
||||
my $title = $POST{title} || $user;
|
||||
|
||||
# reject this email?
|
||||
return LJ::sysban_block(0, "Create user blocked based on email",
|
||||
{ new_user => $user, email => $remote->{email}, name => $user })
|
||||
if LJ::sysban_check('email', $remote->{email});
|
||||
|
||||
$error = "$ML{'error.usernamelong'}" if length($user) > 15;
|
||||
$error = "$ML{'error.usernameinvalid'}" if $POST{user} && !$user;
|
||||
$error = "$ML{'.error.username.mustenter'}" unless $POST{user};
|
||||
|
||||
foreach my $re ("^system\$", @LJ::PROTECTED_USERNAMES) {
|
||||
next unless $user =~ /$re/;
|
||||
|
||||
# you can give people sharedjournal priv ahead of time to create
|
||||
# reserved communities:
|
||||
next if LJ::check_priv($remote, "sharedjournal", $user);
|
||||
|
||||
$error = "$ML{'.error.username.reserved'}";
|
||||
}
|
||||
|
||||
my $u = LJ::load_user($user);
|
||||
my $second_submit = 0;
|
||||
if ($u) {
|
||||
my $in_use = 1;
|
||||
|
||||
if ($u->{email} eq $remote->{email}) {
|
||||
if (LJ::login_ip_banned($u)) {
|
||||
# brute-force possible going on
|
||||
} else {
|
||||
if ($u->{password} eq $remote->{password}) {
|
||||
# oh, they double-clicked the submit button
|
||||
$second_submit = 1;
|
||||
|
||||
# if we found a comm and everything matches, they double hit. if
|
||||
# we found a person/etc, then they tried to recreate their community,
|
||||
# which isn't allowed anymore
|
||||
$in_use = $u->{journaltype} eq 'C' ? 0 : 1;
|
||||
} else {
|
||||
LJ::handle_bad_login($u);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($in_use) {
|
||||
$error = "$ML{'.error.username.inuse'}";
|
||||
}
|
||||
}
|
||||
|
||||
last SUBMIT if $error;
|
||||
|
||||
my $qclusterid = LJ::new_account_cluster() + 0;
|
||||
die "Cluster 0 not supported" unless $qclusterid;
|
||||
|
||||
my $userid = ref $u ? $u->{userid} : 0;
|
||||
unless ($second_submit) {
|
||||
my $dbh = LJ::get_db_writer();
|
||||
$dbh->do("INSERT INTO user (user, email, status, caps, name, clusterid, dversion, journaltype) ".
|
||||
"VALUES (?, ?, ?, ?, ?, ?, $LJ::MAX_DVERSION, 'C')",
|
||||
undef, $user, $remote->{email}, $remote->{status}, int($LJ::NEWUSER_CAPS), $title, $qclusterid);
|
||||
if ($dbh->err) {
|
||||
return "<?h1 $ML{'Error'} h1?><?p $ML{'error.procrequest'} <b>" . $dbh->errstr . "</b> p?>";
|
||||
}
|
||||
$userid = $dbh->{'mysql_insertid'};
|
||||
$dbh->do("REPLACE INTO useridmap (userid, user) VALUES (?, ?)", undef, $userid, $user);
|
||||
$dbh->do("REPLACE INTO userusage (userid, timecreate) VALUES (?, NOW())", undef, $userid);
|
||||
|
||||
# set any properties that get set in new users
|
||||
$u = LJ::load_userid($userid);
|
||||
while (my ($name, $val) = each %LJ::USERPROP_INIT) {
|
||||
LJ::set_userprop($u, $name, $val);
|
||||
}
|
||||
|
||||
# since they're a community, let's do more setup
|
||||
$dbh->do("REPLACE INTO community (userid, membership, postlevel) VALUES (?, ?, ?)",
|
||||
undef, $userid, $POST{membership}, $POST{postlevel});
|
||||
LJ::set_userprop($u, 'nonmember_posting', $POST{nonmember_posting} + 0);
|
||||
LJ::set_userprop($u, 'moderated', $POST{moderated} + 0);
|
||||
LJ::set_rel($userid, $remote->{userid}, 'M') if $POST{moderated}; # moderator if moderated
|
||||
LJ::set_rel($userid, $remote->{userid}, 'A'); # maintainer
|
||||
LJ::join_community($remote, $u, 0, 1); # make them a member of the community
|
||||
|
||||
LJ::run_hooks("post_create", {
|
||||
'userid' => $userid,
|
||||
'user' => $user,
|
||||
});
|
||||
}
|
||||
|
||||
my $nu = LJ::load_userid($userid, "force");
|
||||
|
||||
# log creation
|
||||
$nu->log_event('account_create', { remote => $remote });
|
||||
|
||||
# local sites may want to override what happens at this point
|
||||
my $ret;
|
||||
my $redirect;
|
||||
my $stop_output;
|
||||
LJ::run_hooks("create.bml_postsession", {
|
||||
post => \%POST,
|
||||
u => $nu,
|
||||
type => 'community',
|
||||
redirect => \$redirect,
|
||||
ret => \$ret,
|
||||
stop_output => \$stop_output,
|
||||
});
|
||||
return BML::redirect($redirect) if $redirect;
|
||||
return $ret if $stop_output;
|
||||
|
||||
$ret = "<?h1 $ML{'.success.head'} h1?><?p $ML{'.success.text1'} p?>";
|
||||
my $uri = LJ::journal_base($nu);
|
||||
$ret .= "<?p $ML{'.success.text2'} p?>\n";
|
||||
$ret .= "<?standout <font size='+1' face='arial'><b><a href='$uri'>$uri/</a></b></font> standout?>\n";
|
||||
$ret .= "<?p $ML{'.success.text3'} p?>\n";
|
||||
|
||||
$ret .= "<form method='get' action='$LJ::SITEROOT/editinfo.bml?authas=$nu->{user}'>";
|
||||
$ret .= "<p align='center'>" . LJ::html_submit(undef, "$ML{'.success.btn.enterinfo'} →") . "</p>";
|
||||
$ret .= "</form>\n";
|
||||
|
||||
return $ret;
|
||||
|
||||
}
|
||||
|
||||
if ($mode eq "getinfo" || $error)
|
||||
{
|
||||
my $ret;
|
||||
|
||||
if ($error) {
|
||||
$ret .= "<?errorbar <strong>$ML{'.errors.label'}</strong><ul>";
|
||||
$ret .= "<li>$error</li>";
|
||||
$ret .= "</ul> errorbar?>";
|
||||
}
|
||||
|
||||
$ret .= "<?p $ML{'.create.text'} p?>" unless $error;
|
||||
$ret .= "<form action=\"create.bml\" method=\"post\">\n";
|
||||
$ret .= LJ::html_hidden(mode => 'submit', ssl => $FORM{'ssl'});
|
||||
|
||||
$ret .= "<ol>";
|
||||
|
||||
# username
|
||||
my $v = LJ::ehtml($FORM{'user'});
|
||||
$ret .= "<li><div class='formitem'><div class='formitemName'>$ML{'.username.head'}</div>";
|
||||
$ret .= "<p class='formitemFlag'>$error</p>";
|
||||
$ret .= "<div class='formitemDesc'>" . BML::ml(".username.text", { sitename => $LJ::SITENAME }) . "</div>";
|
||||
$ret .= LJ::html_text({'name' => 'user', 'size' => 15, 'maxlength' => 15, 'value' => $v, raw => 'style="<?commloginboxstyle?>"' });
|
||||
$ret .= "<br />" . BML::ml('.person', { aopts => "href='$LJ::SITEROOT/create.bml'" });
|
||||
$ret .= "<div class='formitemNote'>$ML{'.username.charsallowed'}</div>" unless $error;
|
||||
$ret .= "</div></li>";
|
||||
|
||||
# account title
|
||||
$v = LJ::ehtml($FORM{'title'});
|
||||
$ret .= "<li><div class='formitem'><div class='formitemName'>$ML{'.name.head'}</div>";
|
||||
$ret .= "<div class='formitemDesc'>$ML{'.name.text'}</div>";
|
||||
$ret .= LJ::html_text({ name => 'title', style => 'width: 60%;', maxlength => 80, value => $v, });
|
||||
$ret .= "</div></li>";
|
||||
|
||||
# membership levels
|
||||
$ret .= "<li><div class='formitem'><div class='formitemName'>$ML{'/community/settings.bml.label.membership'}" .
|
||||
"</div><div class='formitemDesc'>$ML{'/community/settings.bml.label.whocanjoin'}</div><div><p>";
|
||||
$ret .= LJ::html_check({ type => 'radio', name => 'membership', id => 'memopen',
|
||||
value => 'open', selected => ($POST{membership} eq 'open' ? 1 : 0)});
|
||||
$ret .= "<label for='memopen' $ML{'/community/settings.bml.label.openmemb'}</label><br /></p><p>";
|
||||
$ret .= LJ::html_check({ type => 'radio', name => 'membership', id => 'memmoderated',
|
||||
value => 'moderated', selected => ($POST{membership} eq 'moderated' ? 1 : 0)});
|
||||
$ret .= "<label for='memmoderated' $ML{'/community/settings.bml.label.moderatedmemb'}</label></p><p>";
|
||||
$ret .= LJ::html_check({ type => 'radio', name => 'membership', id => 'memclosed',
|
||||
value => 'closed', selected => ($POST{membership} eq 'closed' ? 1 : 0)});
|
||||
$ret .= "<label for='memclosed' $ML{'/community/settings.bml.label.closedmemb2'}</label></p>";
|
||||
$ret .= "</div></div></li>";
|
||||
|
||||
# posting access options
|
||||
$ret .= "<li><div class='formitem'><div class='formitemName'>$ML{'/community/settings.bml.label.postaccess'}" .
|
||||
"</div><div class='formitemDesc'>$ML{'/community/settings.bml.label.whocanpost'}</div><div><p>";
|
||||
$ret .= LJ::html_check({ type => 'radio', name => 'postlevel', id => 'postopen',
|
||||
value => 'members', selected => ($POST{postlevel} eq 'members' ? 1 : 0)});
|
||||
$ret .= "<label for='postopen'>$ML{'/community/settings.bml.label.anybodycan'}</label></p><p>";
|
||||
$ret .= LJ::html_check({ type => 'radio', name => 'postlevel', id => 'postclosed',
|
||||
value => 'select', selected => ($POST{postlevel} eq 'select' ? 1 : 0)});
|
||||
$ret .= "<label for='postclosed'>$ML{'/community/settings.bml.label.selcan'}</label></p>";
|
||||
$ret .= "</div></div></li>";
|
||||
|
||||
# nonmember posting options
|
||||
$ret .= "<li><div class='formitem'><div class='formitemName'>$ML{'/community/settings.bml.label.nmheader'}" .
|
||||
"</div><div class='formitemDesc'>$ML{'/community/settings.bml.label.nmtext'}</div><div><p>";
|
||||
$ret .= LJ::html_check({ type => 'radio', name => 'nonmember_posting', id => 'nonopen',
|
||||
value => '0', selected => ($POST{nonmember_posting} eq '0' ? 1 : 0)});
|
||||
$ret .= "<label for='nonopen'>$ML{'/community/settings.bml.label.nmcant'}</label></p><p>";
|
||||
$ret .= LJ::html_check({ type => 'radio', name => 'nonmember_posting', id => 'nonclosed',
|
||||
value => '1', selected => ($POST{nonmember_posting} eq '1' ? 1 : 0)});
|
||||
$ret .= "<label for='nonclosed'>$ML{'/community/settings.bml.label.nmcan'}</label></p>";
|
||||
$ret .= "</div></div></li>";
|
||||
|
||||
# moderated options
|
||||
$ret .= "<li><div class='formitem'><div class='formitemName'>$ML{'/community/settings.bml.label.modheader'}" .
|
||||
"</div><div class='formitemDesc'>$ML{'/community/settings.bml.label.modtext'}</div><div><p>";
|
||||
$ret .= LJ::html_check({ type => 'radio', name => 'moderated', id => 'radunmod',
|
||||
value => '0', selected => ($POST{moderated} eq '0' ? 1 : 0)});
|
||||
$ret .= "<label for='radunmod'>$ML{'/community/settings.bml.label.modisnt'}</label></p><p>";
|
||||
$ret .= LJ::html_check({ type => 'radio', name => 'moderated', id => 'radmod',
|
||||
value => '1', selected => ($POST{moderated} eq '1' ? 1 : 0)});
|
||||
$ret .= "<label for='radmod'>$ML{'/community/settings.bml.label.modis'}</label></p>";
|
||||
$ret .= "</div></div></li>";
|
||||
|
||||
LJ::run_hooks("create.bml_opts", {
|
||||
post => \%POST,
|
||||
get => \%GET,
|
||||
ret => \$ret,
|
||||
});
|
||||
|
||||
$ret .= "</ol>";
|
||||
|
||||
$ret .= "<div style='width:600; text-align: center'>";
|
||||
$ret .= "<input type='submit' value=\"$ML{'.btn.create'}\">";
|
||||
$ret .= "</div>";
|
||||
$ret .= "</form>";
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
return "$ML{'error.unknownmode'}: <b>$mode</b>";
|
||||
}
|
||||
_code?>
|
||||
<=body
|
||||
page?>
|
||||
12
livejournal/htdocs/community/index.bml
Executable file
@@ -0,0 +1,12 @@
|
||||
<?page
|
||||
title=><?_ml .title _ml?>
|
||||
body<=
|
||||
<?_code
|
||||
LJ::set_active_crumb('community');
|
||||
return $ML{'.main'};
|
||||
_code?>
|
||||
<=body
|
||||
page?><?_c <LJDEP>
|
||||
# NONE
|
||||
</LJDEP> _c?>
|
||||
|
||||
134
livejournal/htdocs/community/join.bml
Executable file
@@ -0,0 +1,134 @@
|
||||
<?_code
|
||||
|
||||
LJ::set_active_crumb('joincomm');
|
||||
|
||||
$title = $ML{'.title'};
|
||||
$body = "";
|
||||
|
||||
# is there a user out there?
|
||||
my $remote = LJ::get_remote();
|
||||
unless ($remote) {
|
||||
$body = "<?h1 $ML{'Sorry'}.. h1?><?p $ML{'.label.loginfirst'} p?>";
|
||||
return;
|
||||
}
|
||||
|
||||
# bad statusvis?
|
||||
unless ($remote->{statusvis} eq 'V') {
|
||||
$body = "<?h1 $ML{'.error.statusvis.title'} h1?><?p $ML{'.error.statusvis.body'} p?>";
|
||||
return;
|
||||
}
|
||||
|
||||
# get info about the community
|
||||
my $cuserid = $FORM{'cuserid'}+0;
|
||||
my $cu = $FORM{comm} ?
|
||||
LJ::load_user($FORM{comm}) : # they gave us the comm name
|
||||
LJ::load_userid($cuserid); # they gave us the comm id
|
||||
|
||||
# NOTE: we wrapped this in an eval due to code going live; the library isn't going to go
|
||||
# live at the same time as the BML file, and we don't want weird things happening, so we
|
||||
# verify that this is all good and return an error if it's not okay.
|
||||
my $ci;
|
||||
eval { $ci = LJ::get_community_row($cu); };
|
||||
if ($@) {
|
||||
$body = "<?h1 Temporarily Disabled h1?><?p This page is disabled while we update the site. Please try again later. p?>";
|
||||
return;
|
||||
}
|
||||
$cuserid = $ci->{'userid'};
|
||||
|
||||
LJ::text_out(\$ci->{'name'});
|
||||
my $ecname = LJ::ehtml($ci->{'name'});
|
||||
|
||||
# does this community even exit?
|
||||
unless ($cu) {
|
||||
$body .= "<?h1 $ML{'Error'} h1?><?p $ML{'.label.errorcomminfo'} p?>";
|
||||
return;
|
||||
}
|
||||
|
||||
# make sure a community doesn't join a community (that's confusing
|
||||
# or something)
|
||||
unless ($remote->{'journaltype'} eq "P") {
|
||||
$body .= "<?h1 $ML{'Error'} h1?><?p $ML{'.label.commlogged'} p?>";
|
||||
return;
|
||||
}
|
||||
|
||||
# ensure this user isn't banned
|
||||
if (LJ::is_banned($remote, $cuserid)) {
|
||||
$body .= "<?h1 $ML{'Sorry'} h1?><?p $ML{'.label.banned'} p?>";
|
||||
return;
|
||||
}
|
||||
|
||||
# and make sure they're not already a member
|
||||
if (LJ::is_friend($cuserid, $remote->{userid})) {
|
||||
$body .= "<?h1 $ML{'Error'} h1?><?p $ML{'.error.already.member'} p?>";
|
||||
return;
|
||||
}
|
||||
|
||||
# get the list of maintainers and their usernames
|
||||
my $dbr = LJ::get_db_reader();
|
||||
my $admins = $dbr->selectcol_arrayref("SELECT u.user FROM useridmap u, reluser r ".
|
||||
"WHERE r.userid=$cuserid AND r.targetid=u.userid AND r.type='A'") || [];
|
||||
my $list = "<ul>";
|
||||
foreach (sort @$admins) { $list .= "<li><?ljuser $_ ljuser?></li>"};
|
||||
$list .= "</ul>";
|
||||
|
||||
# can't join closed communities
|
||||
if ($ci->{membership} eq 'closed') {
|
||||
$body .= "<?h1 $ML{'Sorry'} h1?><?p " .
|
||||
BML::ml('.error.closed', { admins => $list }) .
|
||||
" p?>";
|
||||
return;
|
||||
}
|
||||
|
||||
# now do the join
|
||||
if ($POST{confirm}) {
|
||||
# can members join this community openly?
|
||||
if ($ci->{membership} ne 'open') {
|
||||
# hit up the maintainers to let them know a join was requested
|
||||
LJ::comm_join_request($cu, $remote);
|
||||
$body .= "<?h1 $ML{'.reqsubmitted.title'} h1?><?p $ML{'.reqsubmitted.body'} $list p?>";
|
||||
return;
|
||||
}
|
||||
|
||||
# make remote user a friend of the community
|
||||
LJ::join_community($remote, $cu, $FORM{addfriend});
|
||||
|
||||
# success message
|
||||
$body .= "<?h1 $ML{'.success'} h1?><?p " . BML::ml('.label.membernow',
|
||||
{ username => $ci->{user}, commname => $ecname}) . " p?>";
|
||||
|
||||
# if community permits it, tell the user they have access
|
||||
if ($ci->{postlevel} eq "members") {
|
||||
$body .= "<?p $ML{'.label.allowposting'} p?>";
|
||||
} else {
|
||||
$body .= "<?p " . BML::ml('.label.auth', { admins => $list }) . " p?>";
|
||||
}
|
||||
} else {
|
||||
if ($ci->{membership} ne 'open') {
|
||||
$body .= "<?h1 $ML{'.request.title'} h1?><?p ";
|
||||
$body .= BML::ml('.request.body', { comm => LJ::ljuser($cu) }) . "<br /> p?>";
|
||||
$body .= "<div style='margin-left: 30px;'><form method='post' action='join.bml'>";
|
||||
$body .= "<input type='hidden' name='cuserid' value='$ci->{userid}' />";
|
||||
$body .= "<input type='hidden' name='confirm' value='1' />";
|
||||
$body .= "<input type='submit' value=\"$ML{'.button.join'}\" /></form></div>";
|
||||
return;
|
||||
}
|
||||
|
||||
$body .= "<?h1 $ML{'.label.sure'} h1?><?p " . BML::ml('.label.expls', { maintainer => $ecname });
|
||||
$body .= "<form method='post' action='join.bml'>";
|
||||
$body .= "<input type='hidden' name='cuserid' value='$ci->{'userid'}' />";
|
||||
$body .= "<input type='hidden' name='confirm' value='1' /><center>";
|
||||
$body .= "<input type='checkbox' name='addfriend' checked>";
|
||||
$body .= BML::ml('.label.addtofriends', { maintainer => $ecname });
|
||||
$body .= "<br><input type='submit' value=\"$ML{'.button.join'}\" /></center></form> p?>";
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
_code?><?page
|
||||
title=><?_code return $title; _code?>
|
||||
body=><?_code return $body; _code?>
|
||||
page?><?_c <LJDEP>
|
||||
link: htdocs/login.bml, htdocs/userinfo.bml
|
||||
post: htdocs/community/join.bml
|
||||
</LJDEP> _c?>
|
||||
|
||||
68
livejournal/htdocs/community/leave.bml
Executable file
@@ -0,0 +1,68 @@
|
||||
<?_code
|
||||
{
|
||||
use strict;
|
||||
use vars qw($title $body);
|
||||
|
||||
LJ::set_active_crumb('leavecomm');
|
||||
|
||||
$title = $ML{'.title'};
|
||||
$body = "";
|
||||
|
||||
my $error = sub {
|
||||
$body = "<?h1 $ML{'Error'} h1?><?p $_[0] p?>";
|
||||
return;
|
||||
};
|
||||
|
||||
my $remote = LJ::get_remote();
|
||||
return $error->($ML{'.label.logoutfirst'}) unless $remote;
|
||||
|
||||
# get info about the community
|
||||
my $cuserid = $FORM{'cuserid'}+0;
|
||||
my $cu = $FORM{comm} ?
|
||||
LJ::load_user($FORM{comm}) : # they gave us the comm name
|
||||
LJ::load_userid($cuserid); # they gave us the comm id
|
||||
|
||||
# error check
|
||||
return $error->($ML{'.label.infoerror'})
|
||||
unless $cu && $cu->{journaltype} =~ /[CS]/;
|
||||
|
||||
# used in both paths below
|
||||
my $ecname = LJ::ehtml($cu->{'name'});
|
||||
|
||||
if ($FORM{confirm}) {
|
||||
# get current list of maintainers to make sure the last one doesn't leave
|
||||
my $maintids = LJ::load_rel_user($cu->{userid}, 'A');
|
||||
return $error->($ML{'error.nodb'}) unless ref $maintids eq 'ARRAY';
|
||||
|
||||
# error if we're a maintainer and there are no others
|
||||
my $ismaint = grep { $_ == $remote->{userid} } @$maintids;
|
||||
my $othermaints = grep { $_ != $remote->{userid} } @$maintids;
|
||||
return $error->($ML{'.label.lastmaintainer'}) if $ismaint && !$othermaints;
|
||||
|
||||
# remove user from community's friends list
|
||||
LJ::leave_community($remote, $cu, $FORM{removefriend});
|
||||
|
||||
# success message
|
||||
$body .= "<?h1 $ML{'.success'} h1?><?p " .
|
||||
BML::ml('.label.removed', { commuser => $cu->{user}, commname => $ecname }) .
|
||||
" p?>";
|
||||
} else {
|
||||
# show a confirmation form
|
||||
$body .= "<?h1 $ML{'.sure'} h1?><?p " . BML::ml('.label.buttontoleave', { commname => $ecname }) . " p?>";
|
||||
$body .= '<form method="post" action="leave.bml">';
|
||||
$body .= LJ::html_hidden("cuserid", $cu->{userid}, "confirm", 1) . "<p align='center'>";
|
||||
$body .= LJ::html_check({ name => 'removefriend', selected => 1, value => 1 }) . " ";
|
||||
$body .= BML::ml('.label.removefromfriends', { user => $ecname });
|
||||
$body .= '<br /><br />' . LJ::html_submit(undef, $ML{'.button.leave'}) . '</p></form>';
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
_code?><?page
|
||||
title=><?_code return $title; _code?>
|
||||
body=><?_code return $body; _code?>
|
||||
page?><?_c <LJDEP>
|
||||
link: htdocs/login.bml, htdocs/userinfo.bml
|
||||
post: htdocs/community/leave.bml
|
||||
</LJDEP> _c?>
|
||||
|
||||
189
livejournal/htdocs/community/manage.bml
Executable file
@@ -0,0 +1,189 @@
|
||||
<?page
|
||||
title=><?_ml .title _ml?>
|
||||
body<=
|
||||
<?_code
|
||||
|
||||
use strict;
|
||||
use vars qw(%GET %POST);
|
||||
|
||||
return LJ::server_down_html() if ($LJ::SERVER_DOWN);
|
||||
|
||||
LJ::set_active_crumb('managecommunity');
|
||||
|
||||
my $dbr = LJ::get_db_reader();
|
||||
|
||||
my $ret;
|
||||
my $remote = LJ::get_remote();
|
||||
|
||||
unless ($remote) {
|
||||
return "<?needlogin?>";
|
||||
}
|
||||
|
||||
return "<?h1 $ML{'Error'} h1?><?p $ML{'.error.badaccounttype'} p?>"
|
||||
unless $remote->{journaltype} eq 'P';
|
||||
|
||||
$ret .= "<?h1 $ML{'.commlist.header'} h1?><?p $ML{'.commlist.text'} p?>";
|
||||
$ret .= "<div style='margin: 15px 0 15px 40px'>";
|
||||
|
||||
my %show;
|
||||
|
||||
# what communities does remote
|
||||
my $cids = LJ::load_rel_target($remote, 'A');
|
||||
my %admin;
|
||||
if ($cids) { foreach (@$cids) { $admin{$_} = $show{$_} = 1; } }
|
||||
|
||||
# keep track of what communities remote moderates
|
||||
my $mods = LJ::load_rel_target($remote, 'M');
|
||||
my %mods;
|
||||
my %modcount;
|
||||
if ($mods) { foreach (@$mods) { $mods{$_} = $show{$_} = 1; } }
|
||||
|
||||
my %names = ();
|
||||
my %pending = ();
|
||||
if (%show) {
|
||||
my $in = join(',', keys %show);
|
||||
my $us = LJ::load_userids(keys %show);
|
||||
|
||||
my $sth = $dbr->prepare("SELECT userid, membership FROM community ".
|
||||
"WHERE userid IN ($in)");
|
||||
$sth->execute;
|
||||
my $udbr;
|
||||
while (my ($uid, $membership) = $sth->fetchrow_array) {
|
||||
my $cu = $us->{$uid};
|
||||
next unless $cu && $cu->{statusvis} eq "V";
|
||||
$names{$uid} = [ $cu->{user}, $cu->{name}, -1 ];
|
||||
if ($mods{$uid}) {
|
||||
$udbr = LJ::get_cluster_reader($cu);
|
||||
my $sql = "SELECT COUNT(*) FROM modlog WHERE journalid=$uid";
|
||||
$modcount{$uid} = $names{$uid}[2] = $udbr->selectrow_array($sql) || 0;
|
||||
}
|
||||
if ($membership eq 'moderated') {
|
||||
my $ids = LJ::get_pending_members($uid) || [];
|
||||
$pending{$uid} = scalar @$ids;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# deleted and expunged communities won't show up in this
|
||||
if (%names) {
|
||||
|
||||
# Make up the first table row, linking to the other sort methods
|
||||
my @snames;
|
||||
$ret .= "<table cellpadding='5'><tr style='text-align: left;'>";
|
||||
|
||||
if (!defined $GET{'sortby'} || $GET{'sortby'} eq 'username') {
|
||||
$ret .= "<th>$ML{'.commlist.username'}</th>";
|
||||
@snames = sort { $names{$a}->[0] cmp $names{$b}->[0] } keys %names;
|
||||
} else {
|
||||
$ret .= "<th><a href='".BML::self_link({'sortby' => 'username'}) . "'>$ML{'.commlist.username'}</a></th>";
|
||||
}
|
||||
|
||||
if ($GET{'sortby'} eq 'title') {
|
||||
$ret .= "<th>$ML{'.commlist.title'}</th>";
|
||||
@snames = sort { $names{$a}->[1] cmp $names{$b}->[1] } keys %names;
|
||||
} else {
|
||||
$ret .= "<th><a href='".BML::self_link({'sortby' => 'title'}) . "'>$ML{'.commlist.title'}</a></th>";
|
||||
}
|
||||
|
||||
$ret .= "<th>$ML{'.commlist.actions'}</th>";
|
||||
|
||||
if ($GET{'sortby'} eq 'mod') {
|
||||
$ret .= "<th>$ML{'.commlist.moderation'}</th>";
|
||||
@snames = sort { $names{$b}->[2] <=> $names{$a}->[2] } keys %names;
|
||||
} elsif (@$mods) {
|
||||
$ret .= "<th><a href='".BML::self_link({'sortby' => 'mod'}) . "'>$ML{'.commlist.moderation'}</a></th>";
|
||||
}
|
||||
|
||||
foreach my $id (@snames) {
|
||||
my $user = $names{$id}->[0];
|
||||
my $name = $names{$id}->[1];
|
||||
$ret .= "<tr><td><?ljcomm $user ljcomm?></td><td>" . LJ::eall($name) . "</td><td nowrap='nowrap'>";
|
||||
if ($admin{$id}) {
|
||||
$ret .= BML::ml('Actionlink', {
|
||||
'link'=>"<a href='/editinfo.bml?authas=$user'>$ML{'.commlist.actinfo'}</a>"}) . " ";
|
||||
$ret .= BML::ml('Actionlink', {
|
||||
'link'=>"<a href='/community/settings.bml?comm=$user'>$ML{'.commlist.actsettings2'}</a>"}) . " ";
|
||||
$ret .= BML::ml('Actionlink', {
|
||||
'link'=>"<a href='/community/sentinvites.bml?comm=$user'>$ML{'.commlist.actinvites'}</a>"}) . " ";
|
||||
my $pend = $pending{$id} ? BML::ml('.commlist.actpending', { num => $pending{$id},
|
||||
aopts => "href=\"/community/pending.bml?comm=$user\"" }) : '';
|
||||
$ret .= BML::ml('Actionlink', {
|
||||
'link'=>"<a href='/community/members.bml?comm=$user'>$ML{'.commlist.actmembers2'}</a>$pend"}) . " ";
|
||||
}
|
||||
$ret .= "</td><td align='center'>";
|
||||
if ($mods{$id}) {
|
||||
my $num = $modcount{$id} || "0"; # relying on this to be <b>-wrapped
|
||||
$ret .= BML::ml('.commlist.moderation.num', { num => $num,
|
||||
link => "/community/moderate.bml?comm=$user" });
|
||||
}
|
||||
$ret .= "</td></tr>";
|
||||
}
|
||||
$ret .= "</table>";
|
||||
} else {
|
||||
$ret .= "$ML{'.commlist.none'}";
|
||||
}
|
||||
|
||||
$ret .= "</div>";
|
||||
|
||||
# save any changes
|
||||
if (LJ::did_post()) {
|
||||
my $op = $POST{email};
|
||||
$op = '' if $op && $op !~ /[N]/; # add D back in here when Digest goes live
|
||||
LJ::set_userprop($remote, 'opt_communityjoinemail', $op);
|
||||
|
||||
my $mod_emails = $POST{modemail} ? 1 : 0;
|
||||
LJ::set_userprop($remote, 'opt_nomodemail', $mod_emails ? undef : 1);
|
||||
}
|
||||
|
||||
# load up our userprop
|
||||
LJ::load_user_props($remote, 'opt_communityjoinemail', 'opt_nomodemail');
|
||||
my $op = $remote->{opt_communityjoinemail};
|
||||
$op ||= 'Y';
|
||||
my $mod_emails = $remote->{opt_nomodemail} ? 0 : 1;
|
||||
|
||||
# form for setting email option
|
||||
$ret .= "<?h1 $ML{'.joinmail.title'} h1?>";
|
||||
$ret .= "<?p $ML{'.joinmail.body'} p?>";
|
||||
$ret .= "<form method='post' action='manage.bml'>";
|
||||
$ret .= "<div style='margin-left: 30px;'>";
|
||||
$ret .= LJ::html_check({ type => 'radio', name => 'email', id => 'email_all',
|
||||
value => '', selected => ($op eq 'Y') });
|
||||
$ret .= "<label for='email_all'>$ML{'.joinmail.email.all'}</label><br />";
|
||||
if (0) {
|
||||
# we don't do this right now, because the maintenance job to send email isn't
|
||||
# ready for use on LJ. this will be removed and the option enabled when that
|
||||
# task is rewritten. NOTE: add D up above in did_post() block.
|
||||
$ret .= LJ::html_check({ type => 'radio', name => 'email', id => 'email_digest',
|
||||
value => 'D', selected => ($op eq 'D') });
|
||||
$ret .= "<label for='email_digest'>$ML{'.joinmail.email.digest'}</label><br />";
|
||||
}
|
||||
$ret .= LJ::html_check({ type => 'radio', name => 'email', id => 'email_none',
|
||||
value => 'N', selected => ($op eq 'N') });
|
||||
$ret .= "<label for='email_none'>$ML{'.joinmail.email.none'}</label><br />";
|
||||
$ret .= "</div>";
|
||||
|
||||
# options for getting moderation emails
|
||||
$ret .= "<?p $ML{'.modemail.body'} p?>";
|
||||
$ret .= "<div style='margin-left: 30px;'>";
|
||||
|
||||
$ret .= LJ::html_check({ type => 'radio', name => 'modemail', id => 'modemail_yes',
|
||||
value => '1', selected => $mod_emails });
|
||||
$ret .= "<label for='modemail_yes'>$ML{'.modemail.yes'}</label><br />";
|
||||
|
||||
$ret .= LJ::html_check({ type => 'radio', name => 'modemail', id => 'modemail_no',
|
||||
value => '0', selected => !$mod_emails });
|
||||
$ret .= "<label for='modemail_no'>$ML{'.modemail.no'}</label><br />";
|
||||
$ret .= "</div><?p ";
|
||||
$ret .= LJ::html_submit($ML{'.joinmail.save'});
|
||||
$ret .= " p?></form>";
|
||||
|
||||
$ret .= "<?h1 $ML{'.create.header'} h1?>";
|
||||
$ret .= "<?p " . BML::ml('.create.text', {'link'=>'/community/create.bml'}) . " p?>";
|
||||
|
||||
return $ret;
|
||||
|
||||
_code?>
|
||||
|
||||
<=body
|
||||
page?>
|
||||
|
||||
455
livejournal/htdocs/community/members.bml
Executable file
@@ -0,0 +1,455 @@
|
||||
<?page
|
||||
title=><?_ml .title _ml?>
|
||||
body<=
|
||||
<?_code
|
||||
{
|
||||
use strict;
|
||||
use vars qw(%GET %POST);
|
||||
|
||||
LJ::set_active_crumb('commmembers');
|
||||
|
||||
return LJ::server_down_html() if $LJ::SERVER_DOWN;
|
||||
|
||||
# always have links at top
|
||||
my $ret = BML::ml('Backlink', {
|
||||
'link' => '/community/manage.bml',
|
||||
'text' => $ML{'.manage2'},
|
||||
});
|
||||
|
||||
# get remote
|
||||
my $remote = LJ::get_remote();
|
||||
unless ($remote) {
|
||||
$ret .= "<?h1 $ML{'Error'} h1?><?p $ML{'error.noremote'} p?>";
|
||||
return $ret;
|
||||
}
|
||||
|
||||
my $cname = $GET{'comm'};
|
||||
return BML::redirect("$LJ::SITEROOT/community/manage.bml") unless $cname;
|
||||
|
||||
# get $c object
|
||||
my $c = LJ::load_user($cname);
|
||||
unless ($c) {
|
||||
$ret .= "<?h1 $ML{'Error'} h1?><?p $ML{'.error.nocomm'} p?>";
|
||||
return $ret;
|
||||
}
|
||||
my $cid = $c->{'userid'};
|
||||
|
||||
# is $remote an admin?
|
||||
unless (LJ::can_manage_other($remote, $c)) {
|
||||
$ret .= "<?h1 $ML{'Error'} h1?><?p ";
|
||||
$ret .= BML::ml('.error.noaccess',
|
||||
{ 'comm' => LJ::ljuser($cname, { 'type' => 'C' }) });
|
||||
$ret .= " p?>";
|
||||
return $ret;
|
||||
}
|
||||
|
||||
my @allattribs = ('member', 'post', 'preapprove', 'moderate', 'admin');
|
||||
my %attrshort = ( X => 'member', P => 'post', N => 'preapprove', M => 'moderate', A => 'admin');
|
||||
my %attrshort_r = ( map { $attrshort{$_} => $_ } keys %attrshort ); # reversed
|
||||
|
||||
# saving a form submission
|
||||
if ($POST{'action:update'}) {
|
||||
# validate form auth
|
||||
return "<?h1 $ML{'Error'} h1?><?p $ML{'error.invalidform'} p?>"
|
||||
unless LJ::check_form_auth();
|
||||
|
||||
my @userids = split(',', $POST{'ids'});
|
||||
my @saveattribs = split(',', $POST{'attribs'});
|
||||
|
||||
# now we need to create our 'was' list
|
||||
my %was; # ( userid => { attrib => 1; } )
|
||||
my %users; # ( userid => username )
|
||||
foreach my $row (split ';', $POST{was}) { # UID:UNAME:MNPX;UID:UNAME:MX;UID:UNAME:AM
|
||||
# if this row matches...
|
||||
if ($row =~ /^(\d+):(\w+):(\w+)$/) {
|
||||
my ($uid, $name, $attrs) = ($1, $2, $3);
|
||||
$uid += 0;
|
||||
next unless $uid && $name && $attrs;
|
||||
|
||||
# split attrs and setup
|
||||
$was{$uid}->{$attrshort{$_}} = 1 foreach split '', $attrs;
|
||||
$users{$uid} = $name;
|
||||
}
|
||||
}
|
||||
|
||||
# invite new users
|
||||
my @to_add;
|
||||
my @add_errors;
|
||||
foreach my $num (1..5) {
|
||||
$POST{"add_$num"} = LJ::trim($POST{"add_$num"});
|
||||
next unless $POST{"add_$num"} =~ /^\w+$/;
|
||||
|
||||
my $target = LJ::load_user($POST{"add_$num"});
|
||||
unless ($target) {
|
||||
push @add_errors, BML::ml('.error.nouser',
|
||||
{ 'user' => $POST{"add_$num"} });
|
||||
next;
|
||||
}
|
||||
|
||||
unless ($target->{statusvis} eq 'V') {
|
||||
push @add_errors, BML::ml('.error.notactive',
|
||||
{ 'user' => LJ::ljuser($POST{"add_$num"}) });
|
||||
next;
|
||||
}
|
||||
|
||||
my @attr = grep { defined $POST{"add_${num}_$_"} } @saveattribs;
|
||||
unless (@attr) {
|
||||
push @add_errors, BML::ml('.error.noattr',
|
||||
{ 'user' => LJ::ljuser($POST{"add_$num"},
|
||||
{ 'type' => $target->{'journaltype'} }) });
|
||||
next;
|
||||
}
|
||||
|
||||
unless ($target->{'journaltype'} eq 'P') {
|
||||
push @add_errors, BML::ml('.error.invaliduser',
|
||||
{ 'user' => LJ::ljuser($POST{"add_$num"},
|
||||
{ 'type' => $target->{'journaltype'} }) });
|
||||
next;
|
||||
}
|
||||
|
||||
if (grep { $target->{'userid'} == $_ } @userids) {
|
||||
push @add_errors, BML::ml('.error.alreadyadded',
|
||||
{ 'user' => LJ::ljuser($POST{"add_$num"},
|
||||
{ 'type' => $target->{'journaltype'} }) });
|
||||
next;
|
||||
}
|
||||
|
||||
# insert authactions row
|
||||
push @to_add, [ $target, \@attr ];
|
||||
}
|
||||
return LJ::bad_input(@add_errors) if @add_errors;
|
||||
|
||||
# now do the additions if any were needed
|
||||
my @fail;
|
||||
my @invited;
|
||||
if (@to_add) {
|
||||
foreach my $row (@to_add) {
|
||||
# good, let's extend an invite to this person
|
||||
my ($target, $attrs) = @$row;
|
||||
if (LJ::send_comm_invite($target, $c, $remote, $attrs)) {
|
||||
push @invited, $row;
|
||||
} else {
|
||||
push @fail, [ $target, LJ::last_error_code() ];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (@fail) {
|
||||
my @bad;
|
||||
foreach (@fail) {
|
||||
if ($_->[1] eq 'comm_user_has_banned') {
|
||||
push @bad, BML::ml('.error.adding', { user => LJ::ljuser($_->[0], { type => 'P' }) });
|
||||
} elsif ($_->[1] eq 'comm_invite_limit') {
|
||||
push @bad, BML::ml('.error.limit', { user => LJ::ljuser($_->[0], { type => 'P' }) });
|
||||
} else {
|
||||
push @bad, BML::ml('.error.unknown', { user => LJ::ljuser($_->[0], { type => 'P' }) });
|
||||
}
|
||||
}
|
||||
return LJ::bad_input(@bad);
|
||||
}
|
||||
|
||||
# initialize lists of users to update and delete
|
||||
# keyed on attribute type
|
||||
my %add = ();
|
||||
my %delete = ();
|
||||
foreach (@allattribs) {
|
||||
$add{$_} = {};
|
||||
$delete{$_} = {};
|
||||
}
|
||||
|
||||
# need a db handle now
|
||||
my $dbh = LJ::get_db_writer();
|
||||
|
||||
# if we have $other_maints, then there are maintainers not in our
|
||||
# current view, so they will not be modified, so the user can delete
|
||||
# all maintainers from the current view
|
||||
my $in = join(',', map { $dbh->quote($_) } @userids);
|
||||
my $other_maints = $dbh->selectrow_array("SELECT COUNT(*) FROM reluser " .
|
||||
"WHERE userid=? AND type='A' " .
|
||||
"AND targetid NOT IN ($in)",
|
||||
undef, $cid);
|
||||
|
||||
# users already in community
|
||||
my $maints = 0;
|
||||
my (%addr, %delr); # store additions and removals sorted by userid
|
||||
foreach my $id (@userids) {
|
||||
$id = $id + 0;
|
||||
my $str;
|
||||
foreach (@allattribs) {
|
||||
if ($POST{"edit_${id}_$_"}) {
|
||||
unless ($was{$id}->{$_}) {
|
||||
$add{$_}->{$id} = 1;
|
||||
$addr{$id}->{$_} = 1;
|
||||
}
|
||||
} else {
|
||||
if ($was{$id}->{$_}) {
|
||||
$delete{$_}->{$id} = 1;
|
||||
$delr{$id}->{$_} = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
$maints++ if $POST{"edit_${id}_admin"};
|
||||
}
|
||||
|
||||
# can't remove ALL maintainers, give them an error so they can
|
||||
# go back and decide who to keep
|
||||
if (! $other_maints && $maints < 1) {
|
||||
$ret .= "<?h1 $ML{'Error'} h1?><?p Your community, " .
|
||||
LJ::ljuser($cname, { 'type' => 'C' }) .
|
||||
", must have at least one maintainer. " .
|
||||
"Please <a href='" . BML::get_uri() . "?comm=$cname'>" .
|
||||
"go back</a> and add a maintainer. p?>";
|
||||
return $ret;
|
||||
}
|
||||
|
||||
# delete members
|
||||
if (%{$delete{'member'}}) {
|
||||
# TAG:FR:bml_comm_members:del_members
|
||||
LJ::remove_friend($cid, [ keys %{$delete{'member'}} ]);
|
||||
}
|
||||
|
||||
# log maintainer deletions
|
||||
foreach my $uid (keys %{$delete{admin} || {}}) {
|
||||
$c->log_event('maintainer_remove', { actiontarget => $uid, remote => $remote });
|
||||
}
|
||||
|
||||
# delete other rel edges
|
||||
LJ::clear_rel_multi(
|
||||
(map { [$cid, $_, 'A'] } keys %{$delete{admin} || {}}),
|
||||
(map { [$cid, $_, 'P'] } keys %{$delete{post} || {}}),
|
||||
(map { [$cid, $_, 'M'] } keys %{$delete{moderate} || {}}),
|
||||
(map { [$cid, $_, 'N'] } keys %{$delete{preapprove} || {}}),
|
||||
);
|
||||
|
||||
# perform additions
|
||||
my @msgs;
|
||||
if (%{$add{'member'}}) {
|
||||
foreach my $id (keys %{$add{'member'}}) {
|
||||
next if $was{$id}->{'member'};
|
||||
my $u = LJ::load_userid($id);
|
||||
if (LJ::u_equals($u, $remote)) {
|
||||
# you're allowed to add yourself as member
|
||||
LJ::join_community($remote, $c);
|
||||
} else {
|
||||
if (LJ::send_comm_invite($u, $c, $remote, [ 'member' ])) {
|
||||
# if it succeeded, push the reinvited information
|
||||
push @msgs, BML::ml('.reinvited2',
|
||||
{ user => LJ::ljuser($u, { type => 'P' }),
|
||||
aopts => "href='$LJ::SITEROOT/manage/invites.bml'" });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# log maintainer additions
|
||||
foreach my $uid (keys %{$add{admin} || {}}) {
|
||||
$c->log_event('maintainer_add', { actiontarget => $uid, remote => $remote });
|
||||
}
|
||||
|
||||
# set rels in db/memcache
|
||||
LJ::set_rel_multi( (map { [$cid, $_, 'A'] } keys %{$add{admin} || {}}),
|
||||
(map { [$cid, $_, 'P'] } keys %{$add{post} || {}}),
|
||||
(map { [$cid, $_, 'M'] } keys %{$add{moderate} || {}}),
|
||||
(map { [$cid, $_, 'N'] } keys %{$add{preapprove} || {}}),
|
||||
);
|
||||
|
||||
# create some other messages
|
||||
my %done; # keep track of who we've done
|
||||
foreach my $id (keys %addr, keys %delr) {
|
||||
next if $done{$id}++;
|
||||
|
||||
my ($str, @astr, @dstr);
|
||||
push @astr, $ML{"/manage/invites.bml.label.$_"}
|
||||
foreach keys %{$addr{$id} || {}};
|
||||
push @dstr, $ML{"/manage/invites.bml.label.$_"}
|
||||
foreach keys %{$delr{$id} || {}};
|
||||
$str .= "<li>" . BML::ml('.success.added', { list => join(', ', @astr) }) . "</li>\n" if @astr;
|
||||
$str .= "<li>" . BML::ml('.success.deleted', { list => join(', ', @dstr) }) . "</li>\n" if @dstr;
|
||||
push @msgs, LJ::ljuser($users{$id}, { type => 'P' }) . ":<ul>$str</ul>" if $str;
|
||||
}
|
||||
|
||||
$ret .= "<?h1 $ML{'.success.header'} h1?>";
|
||||
if (@msgs) {
|
||||
$ret .= "<?p $ML{'.success.message2'} p?>\n<ul>";
|
||||
$ret .= "<li>$_</li>\n" foreach @msgs;
|
||||
$ret .= "</ul>";
|
||||
}
|
||||
if (@invited) {
|
||||
$ret .= "<?p ";
|
||||
$ret .= BML::ml('.success.invited2',
|
||||
{ aopts => "href='$LJ::SITEROOT/manage/invites.bml'" });
|
||||
$ret .= " p?><ul>";
|
||||
foreach my $row (@invited) {
|
||||
$ret .= "<li>" . LJ::ljuser($row->[0], { type => 'P' }) . ": ";
|
||||
$ret .= "$ML{\"/manage/invites.bml.label.$_\"}, " foreach @{$row->[1] || []};
|
||||
chop $ret; chop $ret;
|
||||
$ret .= "</li>\n";
|
||||
}
|
||||
$ret .= "</ul>";
|
||||
}
|
||||
$ret .= "<?p $ML{'.success.nochanges'} p?>" unless @msgs || @invited;
|
||||
$ret .= "<?p " . BML::ml(".success.return", { 'link' => BML::get_uri() . "?comm=$cname" }) . " p?>";
|
||||
|
||||
return $ret;
|
||||
|
||||
}
|
||||
|
||||
# browsing mode
|
||||
|
||||
# now get lists of: members, admins, able to post, moderators
|
||||
my %users = ();
|
||||
|
||||
# need a dbr now
|
||||
my $dbr = LJ::get_db_reader();
|
||||
|
||||
# get community members
|
||||
# TAG:FR:bml_comm_members:get_members
|
||||
my $sth = $dbr->prepare("SELECT u.userid, u.user FROM useridmap u, friends f " .
|
||||
"WHERE u.userid=f.friendid AND f.userid=?");
|
||||
$sth->execute($cid);
|
||||
|
||||
while (my ($id, $user) = $sth->fetchrow_array) {
|
||||
$users{$id}->{'userid'} = $id;
|
||||
$users{$id}->{'name'} = $user;
|
||||
$users{$id}->{'member'} = 1;
|
||||
}
|
||||
|
||||
my $sth = $dbr->prepare("SELECT r.targetid, r.type, u.user FROM reluser r, useridmap u " .
|
||||
"WHERE r.targetid = u.userid AND r.userid=? AND r.type IN ('A','P','M','N')");
|
||||
$sth->execute($cid);
|
||||
|
||||
my %count;
|
||||
while (my ($id, $type, $user) = $sth->fetchrow_array) {
|
||||
$users{$id}->{'userid'} = $id;
|
||||
$users{$id}->{'name'} = $user;
|
||||
my $key = {'A'=>'admin','P'=>'post','M'=>'moderate','N'=>'preapprove'}->{$type};
|
||||
$users{$id}->{$key} = 1;
|
||||
$count{$type}++;
|
||||
}
|
||||
|
||||
# columns of our table, excluding username
|
||||
my @attribs = ('member', 'post');
|
||||
LJ::load_user_props($c, 'moderated');
|
||||
push @attribs, ('preapprove')
|
||||
if $c->{'moderated'} || $count{'N'};
|
||||
push @attribs, ('moderate')
|
||||
if $c->{'moderated'} || $count{'M'};
|
||||
push @attribs, 'admin';
|
||||
|
||||
# sorting method;
|
||||
my $method = $GET{'sort'};
|
||||
|
||||
my $cmp = sub {$a->{'name'} cmp $b->{'name'}};
|
||||
$cmp = sub {$b->{'member'} <=> $a->{'member'}} if $method eq 'member';
|
||||
$cmp = sub {$b->{'admin'} <=> $a->{'admin'}} if $method eq 'admin';
|
||||
$cmp = sub {$b->{'post'} <=> $a->{'post'}} if $method eq 'post';
|
||||
$cmp = sub {$b->{'moderate'} <=> $a->{'moderate'}} if $method eq 'moderate';
|
||||
$cmp = sub {$b->{'preapprove'} <=> $a->{'preapprove'}} if $method eq 'preapprove';
|
||||
|
||||
my @users = sort $cmp values %users;
|
||||
my $page_size = 100; # change to adjust page size
|
||||
|
||||
# are we going to jump to a specific user ?
|
||||
my $jumppage;
|
||||
my $jumpuser;
|
||||
if (@users > $page_size && $POST{'jumpto'} =~ /^\w+$/) {
|
||||
my $ct;
|
||||
foreach (@users) {
|
||||
$jumppage++ if $ct % $page_size == 0;
|
||||
if ($POST{'jumpto'} eq $_->{'name'}) {
|
||||
$jumpuser = $_->{'name'};
|
||||
last;
|
||||
}
|
||||
$ct++;
|
||||
}
|
||||
undef $jumppage unless $jumpuser;
|
||||
}
|
||||
|
||||
# how to make links back to this page
|
||||
my $self_link = sub {
|
||||
my $sort = "&sort=$GET{'sort'}" if $GET{'sort'};
|
||||
return "members.bml?comm=$cname&page=$_[0]$sort";
|
||||
};
|
||||
|
||||
my %items = BML::paging(\@users, $jumppage || $GET{'page'}, $page_size);
|
||||
my $navbar = LJ::paging_bar($items{'page'}, $items{'pages'},
|
||||
{ 'self_link' => $self_link });
|
||||
@users = @{$items{'items'}};
|
||||
|
||||
# output starts here
|
||||
$ret .= "<?p " . BML::ml('.name', { 'name' => LJ::ljuser($cname, { 'type' => 'C' }) });
|
||||
$ret .= " " . BML::ml('.settings', { 'link' => "settings.bml?comm=$cname"}) . " p?>";
|
||||
|
||||
$ret .= "<form method='post' action='members.bml?comm=$cname'>";
|
||||
$ret .= LJ::form_auth();
|
||||
|
||||
# jump to user
|
||||
if ($items{'pages'} > 1) {
|
||||
$ret .= "<div style='margin-left: 30px;'>Jump to user: ";
|
||||
$ret .= LJ::html_text({ 'name' => 'jumpto', 'value' => $POST{'jumpto'},
|
||||
'size' => '10', 'maxlength' => '15' }) . " ";
|
||||
$ret .= LJ::html_submit(undef, 'Go') . "</div>";
|
||||
|
||||
$ret .= $navbar;
|
||||
}
|
||||
|
||||
my $sortlink = BML::get_uri() . "?comm=$cname&sort=";
|
||||
$ret .= "<br /><div align='center'><table class='borderedtable' cellpadding='2' cellspacing='0'>\n<tr>" .
|
||||
"<th><a href='${sortlink}name'>$ML{'.key.user'}</a></th>";
|
||||
$ret .= "<th><a href='${sortlink}$_'>".$ML{".key.$_"}."</a></th>" for (@attribs);
|
||||
$ret .= "</tr>\n";
|
||||
|
||||
# rows for existing users
|
||||
my $rc = 0;
|
||||
my @wstrs;
|
||||
foreach(@users) {
|
||||
my $rstyle = ($rc++ & 1) ? "<?altcolor1?>" : "<?altcolor2?>";
|
||||
$ret .= "<tr style='background-color: $rstyle;'><td>" . LJ::ljuser($_->{'name'}) . "</td>";
|
||||
my $wstr;
|
||||
foreach my $key (@attribs) {
|
||||
$ret .= "<td align='center'>";
|
||||
$ret .= LJ::html_check({ 'name' => "edit_$_->{'userid'}_$key",
|
||||
'selected' => $_->{$key} });
|
||||
$wstr .= $attrshort_r{$key} if $_->{$key};
|
||||
$ret .= "</td>";
|
||||
}
|
||||
push @wstrs, "$_->{userid}:$_->{name}:$wstr" if $wstr;
|
||||
$ret .= "</tr>\n";
|
||||
}
|
||||
|
||||
# if on the last page, let users add to the list
|
||||
if ($items{'page'} == $items{'pages'}) {
|
||||
foreach(1..5) {
|
||||
my $rstyle = ($rc++ & 1) ? "<?altcolor1?>" : "<?altcolor2?>";
|
||||
$ret .= "<tr style='background-color: $rstyle;'><td>";
|
||||
$ret .= LJ::html_text({ 'name' => "add_$_", 'size' => '10', 'maxlength' => '15' }) . "</td>";
|
||||
foreach my $key (@attribs) {
|
||||
$ret .= "<td align='center'>";
|
||||
if ($key eq 'member' || $key eq 'post') {
|
||||
$ret .= LJ::html_check({ name => "add_${_}_$key", selected => 1, });
|
||||
} else {
|
||||
$ret .= LJ::html_check({ name => "add_${_}_$key" });
|
||||
}
|
||||
$ret .= "</td>";
|
||||
}
|
||||
$ret .= "</tr>\n";
|
||||
}
|
||||
}
|
||||
|
||||
# some hidden values
|
||||
$ret .= "</table>";
|
||||
$ret .= LJ::html_hidden('ids', join(',', map { $_->{'userid'}} @users),
|
||||
'attribs', join(',', @attribs),
|
||||
'was', join(';', @wstrs)) . "\n";
|
||||
|
||||
$ret .= "<p>" . LJ::html_submit('action:update', $ML{'.update'}) . "</p>\n";
|
||||
$ret .= "</form></div>\n\n";
|
||||
|
||||
$ret .= $navbar;
|
||||
|
||||
return $ret;
|
||||
|
||||
}
|
||||
_code?>
|
||||
|
||||
<=body
|
||||
page?>
|
||||
425
livejournal/htdocs/community/moderate.bml
Executable file
@@ -0,0 +1,425 @@
|
||||
<?page
|
||||
title=><?_ml .title _ml?>
|
||||
body<=
|
||||
<?_code
|
||||
|
||||
{
|
||||
use strict;
|
||||
use vars qw(%GET %POST);
|
||||
LJ::set_active_crumb('moderate');
|
||||
return LJ::server_down_html() if ($LJ::SERVER_DOWN);
|
||||
|
||||
my $ret;
|
||||
my $remote = LJ::get_remote();
|
||||
|
||||
unless ($remote) {
|
||||
$ret .= "<?h1 $ML{'Error'} h1?><?p $ML{'error.noremote'} p?>";
|
||||
return $ret;
|
||||
}
|
||||
|
||||
my $mode = $POST{'mode'};
|
||||
my ($saved_comm, $saved_modid) = ("", 0);
|
||||
|
||||
if (LJ::did_post() && ($mode eq 'approve_do' || $mode eq 'reject_do')) {
|
||||
my $cid = $POST{'cid'}+0;
|
||||
my $modid = $POST{'modid'}+0;
|
||||
|
||||
my $c = LJ::load_userid($cid);
|
||||
unless ($c) {
|
||||
$ret .= "<?h1 $ML{'Error'} h1?><?p $ML{'.error.notfound'} p?>";
|
||||
return $ret;
|
||||
}
|
||||
my $dbcm = LJ::get_cluster_master($c);
|
||||
|
||||
unless (LJ::check_rel($c, $remote, 'M')) {
|
||||
$ret .= "<?h1 $ML{'Error'} h1?><?p " .
|
||||
BML::ml('.error.noaccess', {'comm'=>"<?ljcomm $c->{'user'} ljcomm?>"}) . " p?>";
|
||||
return $ret;
|
||||
}
|
||||
# use dbcm to read to minimize collisions between moderators due to replication lag
|
||||
my $entry = $dbcm->selectrow_hashref("SELECT * FROM modlog WHERE journalid=? AND modid=?",
|
||||
undef, $c->{'userid'}, $modid);
|
||||
my $frozen = $dbcm->selectrow_array("SELECT request_stor FROM modblob WHERE journalid=? AND modid=?",
|
||||
undef, $c->{'userid'}, $modid);
|
||||
|
||||
my $req = Storable::thaw($frozen) if $frozen;
|
||||
unless ($frozen && $entry && $req->{'_moderate'}->{'authcode'} && $req->{'_moderate'}->{'authcode'} eq $POST{'auth'}) {
|
||||
$ret .= "<?h1 $ML{'Error'} h1?><?p $ML{'.error.noentry'} p?>";
|
||||
return $ret;
|
||||
}
|
||||
|
||||
my $poster = LJ::load_userid($entry->{'posterid'});
|
||||
my ($success, $do_mail) = (0, 0);
|
||||
my $why_mail;
|
||||
my $prot_err;
|
||||
my $posturl;
|
||||
|
||||
if ($mode eq 'approve_do') {
|
||||
my $res = LJ::Protocol::do_request('postevent', $req, \$prot_err, {'nomod'=>1, 'noauth'=>1});
|
||||
if ($res) { # succeeded
|
||||
$success = 1;
|
||||
$ret .= "<?h1 $ML{'.posted.header'} h1?><?p $ML{'.posted.text'} p?>";
|
||||
# does the poster want to know? if they have working email and notification on
|
||||
($do_mail, $why_mail) = (1, 'success')
|
||||
if ($poster->{'opt_gettalkemail'} eq "Y" && $poster->{'status'} eq "A");
|
||||
$posturl = LJ::item_link($c, $res->{'itemid'}, $res->{'anum'}) . "\n\n";
|
||||
} else {
|
||||
$prot_err = LJ::Protocol::error_message($prot_err) if $prot_err;
|
||||
$ret .= "<?h1 $ML{'Error'} h1?><?p " .
|
||||
BML::ml('.posted.proterror', {'err'=>"<b>$prot_err</b>"}) . " p?>";
|
||||
($do_mail, $why_mail) = (1, 'proterror')
|
||||
if $poster->{'status'} eq "A";
|
||||
}
|
||||
if ($POST{'preapprove'}) {
|
||||
LJ::set_rel($c, $poster, 'N');
|
||||
$ret .= "<?h1 $ML{'.posted.appheader'} h1?><?p " .
|
||||
BML::ml('.posted.apptext', {'user'=>"<?ljuser $poster->{'user'} ljuser?>"}) . " p?>";
|
||||
}
|
||||
}
|
||||
if ($mode eq 'reject_do') {
|
||||
$success = 1;
|
||||
$ret .= "<?h1 $ML{'.rejected.header'} h1?><?p $ML{'.rejected.text'} p?>";
|
||||
($do_mail, $why_mail) = (1, 'reject')
|
||||
if $poster->{'status'} eq 'A';
|
||||
}
|
||||
|
||||
$do_mail = 1 unless $poster->{'statusvis'} eq 'V';
|
||||
|
||||
# mail the poster
|
||||
if ($do_mail) {
|
||||
my $subject="Moderated submission notification";
|
||||
my $to = $poster->{'email'};
|
||||
my $body = "Your message submitted to the moderated community $c->{'user'} ";
|
||||
if ($why_mail eq 'success') {
|
||||
$body .= "has been approved and successfully posted.\n\n$posturl";
|
||||
} elsif ($why_mail eq 'proterror') {
|
||||
$body .= "has been approved, but failed to be posted due to the following protocol error:\n$prot_err\n\n";
|
||||
} elsif ($why_mail eq 'reject') {
|
||||
$body .= "has been rejected by a moderator of that community.\n\nPlease note that replies to this email are not sent to the community's moderator(s). If you would like to discuss the reasons for your entry's rejection, you will need to contact a moderator directly.\n\n";
|
||||
}
|
||||
if ($why_mail eq 'reject' && $POST{'why'}) {
|
||||
$body .= "Here are the reasons for the rejection as provided by the moderator: \n\n" . $POST{'why'} . "\n\n";
|
||||
}
|
||||
unless ($why_mail eq 'success') {
|
||||
$body .= "This is the message you submitted:\n\n";
|
||||
my $etime = sprintf("%04d-%02d-%02d %02d:%02d",
|
||||
$req->{'year'}, $req->{'mon'},
|
||||
$req->{'day'}, $req->{'hour'},
|
||||
$req->{'min'});
|
||||
$body .= "Time: $etime\n";
|
||||
$body .= "Subject: " . $req->{'subject'} . "\n";
|
||||
if ($req->{'props'}->{'current_music'}) {
|
||||
$body .= "Current Music: " . $req->{'props'}->{'current_music'} . "\n";
|
||||
}
|
||||
if ($req->{'props'}->{'current_mood'}) {
|
||||
$body .= "Current Mood: " . $req->{'props'}->{'current_mood'} . "\n";
|
||||
}
|
||||
if ($req->{'props'}->{'picture_keyword'}) {
|
||||
$body .= "Picture Keyword: " . $req->{'props'}->{'picture_keyword'} . "\n";
|
||||
}
|
||||
$body .= "Text:\n" . $req->{'event'} . "\n\n";
|
||||
$body .= "Regards,\n$LJ::SITENAME Team\n\n$LJ::SITEROOT/\n";
|
||||
}
|
||||
LJ::send_mail({
|
||||
'to' => $to,
|
||||
'from' => $LJ::BOGUS_EMAIL,
|
||||
'charset' => 'utf-8',
|
||||
'subject' => $subject,
|
||||
'body' => $body,
|
||||
});
|
||||
}
|
||||
|
||||
if ($success) {
|
||||
$saved_comm = $c->{'user'};
|
||||
$saved_modid = 0;
|
||||
|
||||
# Delete this moderated entry from the list
|
||||
$c->do("DELETE FROM modlog WHERE journalid=? AND modid=?",
|
||||
undef, $c->{'userid'}, $modid);
|
||||
$c->do("DELETE FROM modblob WHERE journalid=? AND modid=?",
|
||||
undef, $c->{'userid'}, $modid);
|
||||
|
||||
# FALL THROUGH to showing the list of entries in this community
|
||||
} else {
|
||||
$ret .= "<p>";
|
||||
$ret .= BML::ml('Backlink', {
|
||||
'link'=>'/community/manage.bml',
|
||||
'text'=>$ML{'.manage'},
|
||||
}) . "<br />";
|
||||
$ret .= BML::ml('Backlink', {
|
||||
'link'=>"/community/moderate.bml?comm=$c->{'user'}",
|
||||
'text'=>$ML{'.moderate'},
|
||||
}) . "<br />";
|
||||
$ret .= "</p>";
|
||||
return $ret;
|
||||
}
|
||||
}
|
||||
|
||||
my $comm = $saved_comm || ($mode eq 'action' ? $POST{'comm'} : $GET{'comm'});
|
||||
my $modid = $saved_modid || ($mode eq 'action' ? $POST{'modid'} : $GET{'modid'});
|
||||
$modid += 0;
|
||||
|
||||
# redirect to community/manage if a GET request with no arg
|
||||
return BML::redirect("manage.bml") unless $comm;
|
||||
|
||||
my $c = LJ::load_user($comm);
|
||||
unless ($c) {
|
||||
$ret .= "<?h1 $ML{'Error'} h1?><?p $ML{'.error.notfound'} p?>";
|
||||
return $ret;
|
||||
}
|
||||
my $dbcr = LJ::get_cluster_def_reader($c);
|
||||
|
||||
unless (LJ::check_rel($c, $remote, 'M')) {
|
||||
$ret .= "<?h1 $ML{'Error'} h1?><?p " .
|
||||
BML::ml('.error.noaccess', {'comm'=>"<?ljcomm $comm ljcomm?>"}) . " p?>";
|
||||
return $ret;
|
||||
}
|
||||
|
||||
if ($mode eq 'action' && $POST{'action:approve'}) {
|
||||
my ($posterid, $frreq);
|
||||
if ($modid) {
|
||||
($posterid, $frreq) = $dbcr->selectrow_array
|
||||
("SELECT l.posterid, b.request_stor FROM modlog l, modblob b " .
|
||||
"WHERE l.journalid=? AND l.modid=? AND l.journalid=b.journalid AND l.modid=b.modid",
|
||||
undef, $c->{'userid'}, $modid);
|
||||
}
|
||||
unless ($posterid) {
|
||||
$ret .= "<?h1 $ML{'Error'} h1?><?p $ML{'.error.noentry'} p?>";
|
||||
return $ret;
|
||||
}
|
||||
my $req = Storable::thaw($frreq);
|
||||
my $poster = LJ::load_userid($posterid);
|
||||
$ret .= "<?h1 $ML{'.approve.header'} h1?><?p $ML{'.approve.text'} p?>";
|
||||
$ret .= "<p><form method='post' action='/community/moderate.bml'><center>";
|
||||
$ret .= "<input type='hidden' name='mode' value='approve_do'>";
|
||||
$ret .= "<input type='hidden' name='cid' value='$c->{'userid'}'>";
|
||||
$ret .= "<input type='hidden' name='modid' value='$modid'>";
|
||||
$ret .= "<input type='hidden' name='auth' value='" . $req->{'_moderate'}->{'authcode'} . "'>";
|
||||
$ret .= "<input type='submit' value='$ML{'.approve.button'}'>";
|
||||
$ret .= "</center>";
|
||||
$ret .= "<p><input type='checkbox' name='preapprove'> " .
|
||||
BML::ml('.approve.preapprove', {'user'=>"<?ljuser $poster->{'user'} ljuser?>"});
|
||||
$ret .= "</form>";
|
||||
return $ret;
|
||||
}
|
||||
|
||||
if ($mode eq 'action' && $POST{'action:reject'}) {
|
||||
my ($posterid, $frreq);
|
||||
if ($modid) {
|
||||
($posterid, $frreq) = $dbcr->selectrow_array
|
||||
("SELECT l.posterid, b.request_stor FROM modlog l, modblob b " .
|
||||
"WHERE l.journalid=? AND l.modid=? AND l.journalid=b.journalid AND l.modid=b.modid",
|
||||
undef, $c->{'userid'}, $modid);
|
||||
}
|
||||
unless ($posterid) {
|
||||
$ret .= "<?h1 $ML{'Error'} h1?><?p $ML{'.error.noentry'} p?>";
|
||||
return $ret;
|
||||
}
|
||||
my $req = Storable::thaw($frreq);
|
||||
my $poster = LJ::load_userid($posterid);
|
||||
$ret .= "<?h1 $ML{'.reject.header'} h1?><?p $ML{'.reject.text'} p?>";
|
||||
$ret .= "<p><form method='post' action='/community/moderate.bml'><center>";
|
||||
$ret .= "<input type='hidden' name='mode' value='reject_do'>";
|
||||
$ret .= "<input type='hidden' name='cid' value='$c->{'userid'}'>";
|
||||
$ret .= "<input type='hidden' name='modid' value='$modid'>";
|
||||
$ret .= "<input type='hidden' name='auth' value='" . $req->{'_moderate'}->{'authcode'} . "'>";
|
||||
$ret .= "<input type='submit' value='$ML{'.reject.button'}'>";
|
||||
$ret .= "</center>";
|
||||
if ($poster->{'status'} eq 'A') {
|
||||
$ret .= "<?p $ML{'.reject.reason'} p?>";
|
||||
$ret .= "<?p <textarea rows='10' cols='60' wrap='soft' name='why'></textarea> p?>";
|
||||
}
|
||||
$ret .= "</form>";
|
||||
return $ret;
|
||||
}
|
||||
|
||||
# browse either the list of entries or an entry
|
||||
unless ($modid) {
|
||||
# present a list of entries
|
||||
$ret .= "<?h1 $ML{'.browse.header'} h1?><?p " .
|
||||
BML::ml('.browse.text', {'link'=>"<?ljcomm $comm ljcomm?>"}) . " p?>";
|
||||
$ret .= "<div style='margin: 10px 0 10px 40px'>";
|
||||
my @entries;
|
||||
my $sth = $dbcr->prepare("SELECT * FROM modlog WHERE journalid=$c->{'userid'}");
|
||||
$sth->execute;
|
||||
while ($_ = $sth->fetchrow_hashref) {
|
||||
push @entries, $_;
|
||||
}
|
||||
unless (@entries) {
|
||||
$ret .= "<i>$ML{'.browse.empty'}</i>";
|
||||
} else {
|
||||
$ret .= "<table cellpadding='5'><tr><td><b>$ML{'.brlist.time'}</b></td>" .
|
||||
"<td><b>$ML{'.brlist.poster'}</b></td><td><b>$ML{'.brlist.subject'}</b></td>" .
|
||||
"<td><b>$ML{'.brlist.actions'}</b></td></tr>";
|
||||
|
||||
my %users;
|
||||
LJ::load_userids_multiple([ map { $_->{'posterid'}, \$users{$_->{'posterid'}} } @entries ]);
|
||||
foreach (sort { $a->{'logtime'} lt $b->{'logtime'} } @entries) {
|
||||
my $link = "/community/moderate.bml?comm=$comm&modid=" . $_->{'modid'};
|
||||
my $subject = $_->{'subject'} ? LJ::eall($_->{'subject'}) : "<i>[No Subject]</i>";
|
||||
$ret .= "<tr><td>$_->{'logtime'}</td>" .
|
||||
"<td><?ljuser " . $users{$_->{'posterid'}}->{'user'} . " ljuser?></td>" .
|
||||
"<td><a href='$link'>$subject</a></td>" .
|
||||
"<td>" .
|
||||
BML::ml('Actionlink', {
|
||||
'link'=>"<a href='$link'>$ML{'.brlist.view'}</a>"
|
||||
}) . "</td></tr>";
|
||||
}
|
||||
$ret .= "</table>";
|
||||
}
|
||||
$ret .= "</div>";
|
||||
$ret .= BML::ml('Backlink', {
|
||||
'link'=>'/community/manage.bml',
|
||||
'text'=>$ML{'.manage'},
|
||||
}) . "<br />";
|
||||
|
||||
} else {
|
||||
# view an entry
|
||||
my $frozen = $dbcr->selectrow_array("SELECT request_stor FROM modblob WHERE journalid=? AND modid=?",
|
||||
undef, $c->{'userid'}, $modid);
|
||||
unless ($frozen) {
|
||||
$ret .= "<?h1 $ML{'Error'} h1?><?p $ML{'.error.noentry'} p?>";
|
||||
return $ret;
|
||||
}
|
||||
my $req = Storable::thaw($frozen);
|
||||
|
||||
# cleaning
|
||||
my $event = $req->{'event'};
|
||||
$event =~ s/^\s+//;
|
||||
$event =~ s/\s+$//;
|
||||
if ($req->{'lineendings'} eq "mac") {
|
||||
$event =~ s/\r/\n/g;
|
||||
} else {
|
||||
$event =~ s/\r//g;
|
||||
}
|
||||
my $etime = sprintf("%04d-%02d-%02d %02d:%02d",
|
||||
$req->{'year'}, $req->{'mon'},
|
||||
$req->{'day'}, $req->{'hour'},
|
||||
$req->{'min'});
|
||||
my $subject = $req->{'subject'};
|
||||
my $props = $req->{'props'};
|
||||
my $up = LJ::load_user($req->{'username'});
|
||||
my $posterid = $up->{'userid'};
|
||||
my $error;
|
||||
my @polls = LJ::Poll::parse(\$event, \$error, {
|
||||
'journalid' => $c->{'userid'},
|
||||
'posterid' => $posterid,
|
||||
});
|
||||
$event =~ s/<lj-poll-placeholder>/LJ::Poll::preview(shift @polls);/eg;
|
||||
LJ::CleanHTML::clean_event(\$event, {'preformatted' => $req->{'props'}->{'opt_preformatted'},
|
||||
'cutpreview' => 1,
|
||||
'cuturl' => '#',
|
||||
});
|
||||
BML::ebml(\$event);
|
||||
|
||||
$ret .= "<p>";
|
||||
$ret .= BML::ml('Backlink', {
|
||||
'link'=>'/community/manage.bml',
|
||||
'text'=>$ML{'.manage'},
|
||||
}) . "<br />";
|
||||
$ret .= BML::ml('Backlink', {
|
||||
'link'=>"/community/moderate.bml?comm=$comm",
|
||||
'text'=>$ML{'.moderate'},
|
||||
}) . "<br />";
|
||||
$ret .= "</p>";
|
||||
|
||||
$ret .= "<p>";
|
||||
$ret .= "<table><tr valign='middle'>";
|
||||
|
||||
my $picid = LJ::get_picid_from_keyword($up, $props->{'picture_keyword'});
|
||||
|
||||
my %userpics;
|
||||
if ($picid) {
|
||||
LJ::load_userpics(\%userpics, [ $up, $picid ]);
|
||||
my $alt = $up->{'name'};
|
||||
if ($props->{'picture_keyword'}) {
|
||||
$alt .= ": $props->{'picture_keyword'}";
|
||||
}
|
||||
$alt = LJ::ehtml($alt);
|
||||
$ret .= "<td><img src='$LJ::USERPIC_ROOT/$picid/$up->{'userid'}' width='$userpics{$picid}->{'width'}' ".
|
||||
"height='$userpics{$picid}->{'height'}' align='absmiddle' ".
|
||||
"hspace='3' title='$alt' alt=''></td>";
|
||||
}
|
||||
|
||||
$ret .= "<td>";
|
||||
$ret .= BML::ml("talk.somebodywrote_comm", { 'realname' => BML::eall($up->{'name'}),
|
||||
'userlink' => LJ::ljuser($up->{'user'}),
|
||||
'commlink' => "<?ljcomm $c->{'user'} ljcomm?>" });
|
||||
|
||||
$etime =~ s!(\d\d\d\d)-(\d\d)-(\d\d)!LJ::date_to_view_links($c, $&)!e;
|
||||
$ret .= "<br /><font size='-1'>@ $etime</font>";
|
||||
$ret .= "</td></tr></table>";
|
||||
|
||||
|
||||
my $actions .= "<input type='hidden' name='mode' value='action' />";
|
||||
$actions .= "<input type='hidden' name='comm' value='$comm' />";
|
||||
$actions .= "<input type='hidden' name='modid' value='$modid' />";
|
||||
$actions .= "<input type='submit' name='action:approve' value='$ML{'.choice.approve'}' style='font-size: 15pt; background: $ML{'.choice.bkapprove'}; color: #000000' />";
|
||||
$actions .= " <input type='submit' name='action:reject' value='$ML{'.choice.reject'}' style='font-size: 15pt; background: $ML{'.choice.bkreject'}; color: #000000' />";
|
||||
|
||||
$ret .= "<form method='post' action='/community/moderate.bml'>";
|
||||
$ret .= BML::fill_template("standout", {'DATA'=> $actions});
|
||||
$ret .= "</form>";
|
||||
|
||||
my %current;
|
||||
if ($props->{'current_mood'} || $props->{'current_moodid'}) {
|
||||
$current{'Mood'} = $props->{'current_mood'};
|
||||
LJ::CleanHTML::clean_subject(\$current{'Mood'});
|
||||
my $mid = $props->{'current_moodid'};
|
||||
if ($mid) {
|
||||
my $theme = $up->{'moodthemeid'};
|
||||
my %pic;
|
||||
my $name = LJ::mood_name($mid);
|
||||
if (LJ::get_mood_picture($theme, $mid, \%pic)) {
|
||||
$current{'Mood'} = "<img src='$pic{'pic'}' align='absmiddle' width='$pic{'w'}' height='$pic{'h'}' vspace='1'> $name";
|
||||
} else {
|
||||
$current{'Mood'} = $name;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($props->{'current_music'}) {
|
||||
$current{'Music'} = $props->{'current_music'};
|
||||
LJ::CleanHTML::clean_subject(\$current{'Music'});
|
||||
}
|
||||
$ret .= "<div style='margin-left: 30px'>";
|
||||
if (%current)
|
||||
{
|
||||
$ret .= "<table border=0>\n";
|
||||
foreach (sort keys %current) {
|
||||
my $curkey = "talk.curname_" . $_;
|
||||
my $curname = BML::ml($curkey);
|
||||
$curname = "<b>Current $_:</b>" unless $curname;
|
||||
$ret .= "<tr><td align=right>$curname</td><td>$current{$_}</td></tr>\n";
|
||||
}
|
||||
$ret .= "</table><p>\n";
|
||||
}
|
||||
|
||||
### security indicator
|
||||
my $sec = "";
|
||||
if ($req->{'security'} eq "private") {
|
||||
$sec = "<?securityprivate?>";
|
||||
} elsif ($req->{'security'} eq "usemask") {
|
||||
$sec = "<?securityprotected?>";
|
||||
}
|
||||
|
||||
$sec .= "<br />\n" unless $sec eq "" or $subject;
|
||||
$ret .= $sec;
|
||||
|
||||
if ($subject) {
|
||||
LJ::CleanHTML::clean_subject(\$subject);
|
||||
BML::ebml(\$subject);
|
||||
$ret .= "<font face='Arial,Helvetica' size='+1'><i><b>$subject</b></i></font><br />\n";
|
||||
}
|
||||
$ret .= $event;
|
||||
$ret .= "</div>";
|
||||
$ret .= "<br clear='all' /><hr width='100%' size='2' align='center' />";
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
_code?>
|
||||
|
||||
<=body
|
||||
page?>
|
||||
|
||||
135
livejournal/htdocs/community/pending.bml
Executable file
@@ -0,0 +1,135 @@
|
||||
<?page
|
||||
title=><?_ml .title _ml?>
|
||||
body<=
|
||||
<?_code
|
||||
{
|
||||
use strict;
|
||||
use vars qw(%GET %POST);
|
||||
|
||||
LJ::set_active_crumb('commpending');
|
||||
|
||||
return LJ::server_down_html() if $LJ::SERVER_DOWN;
|
||||
|
||||
# always have links at top
|
||||
my $ret = BML::ml('Backlink', {
|
||||
'link' => '/community/manage.bml',
|
||||
'text' => $ML{'/community/members.bml.manage2'},
|
||||
});
|
||||
|
||||
# get remote
|
||||
my $remote = LJ::get_remote();
|
||||
return "<?h1 $ML{'Error'} h1?><?p $ML{'error.noremote'} p?>"
|
||||
unless $remote;
|
||||
|
||||
my $cname = $GET{'comm'};
|
||||
return BML::redirect("$LJ::SITEROOT/community/manage.bml") unless $cname;
|
||||
|
||||
# get $c object
|
||||
my $c = LJ::load_user($cname);
|
||||
return "<?h1 $ML{'Error'} h1?><?p $ML{'/community/members.bml.error.nocomm'} p?>"
|
||||
unless $c;
|
||||
my $cid = $c->{'userid'};
|
||||
|
||||
# is $remote an admin?
|
||||
unless (LJ::can_manage($remote, $c)) {
|
||||
$ret .= "<?h1 $ML{'Error'} h1?><?p ";
|
||||
$ret .= BML::ml('/community/members.bml.error.noaccess',
|
||||
{ comm => LJ::ljuser($cname, { type => 'C' }) });
|
||||
$ret .= " p?>";
|
||||
return $ret;
|
||||
}
|
||||
|
||||
# hit up the database to find pending members
|
||||
my $pendids = LJ::get_pending_members($c) || [];
|
||||
my $us = LJ::load_userids(@$pendids);
|
||||
|
||||
# nothing pending?
|
||||
return "<?h1 $ML{'.nopending.title'} h1?><?p $ML{'.nopending.body'} p?>"
|
||||
unless @$pendids || LJ::did_post();
|
||||
|
||||
# saving a form submission
|
||||
if ($POST{'action:update'}) {
|
||||
my @userids = split(',', $POST{'ids'});
|
||||
|
||||
# need a db handle now
|
||||
my $dbh = LJ::get_db_writer();
|
||||
|
||||
# hit up each user to find out what to do with them
|
||||
my ($added, $rejected, $ignored, $previous);
|
||||
foreach my $id (@userids) {
|
||||
unless ($us->{$id}) {
|
||||
$previous++;
|
||||
next;
|
||||
}
|
||||
if ($POST{"pending_$id"} eq 'yes') {
|
||||
LJ::approve_pending_member($cid, $id);
|
||||
$added++;
|
||||
} elsif ($POST{"pending_$id"} eq 'no') {
|
||||
LJ::reject_pending_member($cid, $id);
|
||||
$rejected++;
|
||||
} else {
|
||||
$ignored++;
|
||||
}
|
||||
}
|
||||
|
||||
$ret .= "<?h1 $ML{'/community/members.bml.success.header'} h1?><?p $ML{'/community/members.bml.success.message'} p?>";
|
||||
$ret .= "<?p " . BML::ml('.success.added', { num => $added }) . " p?>" if $added;
|
||||
$ret .= "<?p " . BML::ml('.success.rejected', { num => $rejected }) . " p?>" if $rejected;
|
||||
$ret .= "<?p " . BML::ml('.success.ignored', { num => $ignored }) . " p?>" if $ignored;
|
||||
$ret .= "<?p " . BML::ml('.success.previous', { num => $previous }) . " p?>" if $previous;
|
||||
$ret .= "<?p " . BML::ml("/community/members.bml.success.return", { 'link' => BML::get_uri() . "?comm=$cname" }) . " p?>";
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
my @users = sort { $a->{user} cmp $b->{user} } values %$us;
|
||||
my $page_size = 100; # change to adjust page size
|
||||
|
||||
# how to make links back to this page
|
||||
my $self_link = sub {
|
||||
return "pending.bml?comm=$cname&page=$_[0]";
|
||||
};
|
||||
|
||||
my %items = BML::paging(\@users, $GET{page}, $page_size);
|
||||
my $navbar = LJ::paging_bar($items{page}, $items{pages},
|
||||
{ self_link => $self_link });
|
||||
@users = @{$items{items}};
|
||||
|
||||
# output starts here
|
||||
$ret .= "<?p " . BML::ml('/community/members.bml.name', { name => LJ::ljuser($cname, { type => 'C' }) });
|
||||
$ret .= " " . BML::ml('/community/members.bml.settings', { 'link' => "settings.bml?comm=$cname"}) . " p?>";
|
||||
|
||||
$ret .= "<form method='post' action='pending.bml?comm=$cname'>";
|
||||
|
||||
# table headers
|
||||
$ret .= "<br /><div align='center'><table class='borderedtable' cellspacing='0' cellpadding='2'>\n<tr>" .
|
||||
"<th>$ML{'/community/members.bml.key.user'}</th><th colspan='2'>$ML{'.approve.title'}</th></tr>\n";
|
||||
|
||||
# rows for existing users
|
||||
my $rc = 0;
|
||||
foreach (@users) {
|
||||
my $rstyle = ($rc++ & 1) ? '<?altcolor1?>' : '<?altcolor2?>';
|
||||
$ret .= "<tr style='background-color: $rstyle;'><td>" . LJ::ljuser($_->{user}) . "</td>";
|
||||
$ret .= "<td>" . LJ::html_check({ type => 'radio', name => "pending_$_->{userid}",
|
||||
id => "pending_$_->{userid}_yes", value => 'yes' });
|
||||
$ret .= " <label for='pending_$_->{userid}_yes'>$ML{'.yes'}</label></td>\n";
|
||||
$ret .= "<td>" . LJ::html_check({ type => 'radio', name => "pending_$_->{userid}",
|
||||
id => "pending_$_->{userid}_no", value => 'no' });
|
||||
$ret .= " <label for='pending_$_->{userid}_no'>$ML{'.no'}</label></td>\n";
|
||||
$ret .= "</tr>\n";
|
||||
}
|
||||
|
||||
# some hidden values
|
||||
$ret .= LJ::html_hidden('ids', join(',', map { $_->{userid}} @users)) . "\n";
|
||||
$ret .= "</table><p>" . LJ::html_submit('action:update', $ML{'/community/members.bml.update'}) . "</p>\n";
|
||||
$ret .= "</div></form>\n\n";
|
||||
|
||||
$ret .= $navbar;
|
||||
|
||||
return $ret;
|
||||
|
||||
}
|
||||
_code?>
|
||||
|
||||
<=body
|
||||
page?>
|
||||
165
livejournal/htdocs/community/search.bml
Executable file
@@ -0,0 +1,165 @@
|
||||
<?_info
|
||||
localblocks<=
|
||||
crit<=
|
||||
{F}
|
||||
<tr bgcolor='<?emcolor?>'>
|
||||
<td align='left' colspan='2'><b>%%name%%</b>
|
||||
</tr>
|
||||
<tr><td> </td><td>%%form%%</td></tr>
|
||||
<=crit
|
||||
bar<=
|
||||
{F}
|
||||
<tr bgcolor='<?emcolor?>'>
|
||||
<td> </td>
|
||||
<td><b>%%name%%</b>
|
||||
</tr>
|
||||
<tr><td> </td><td>%%form%%</td></tr>
|
||||
<=bar
|
||||
<=localblocks
|
||||
_info?><?page
|
||||
title=><?_ml .title _ml?>
|
||||
body<=
|
||||
|
||||
<?h1 <?_ml .label.searchcomm _ml?> h1?>
|
||||
<?p
|
||||
<?_ml .label.selecriteria _ml?>
|
||||
p?>
|
||||
|
||||
<?hr?>
|
||||
|
||||
<CENTER>
|
||||
|
||||
<form action="/directory.bml">
|
||||
<input type='hidden' name="com_do" value='1' />
|
||||
|
||||
<table cellpadding='4' cellspacing='0' border='0'>
|
||||
|
||||
<!--- location --->
|
||||
<?crit
|
||||
name=><?_ml .label.bylocation _ml?>
|
||||
code=>s_loc
|
||||
form<=
|
||||
|
||||
<table>
|
||||
<tr><td align='right'><?_ml .label.country _ml?></td><td>
|
||||
<?_code
|
||||
{
|
||||
use strict;
|
||||
LJ::set_active_crumb('commsearch');
|
||||
|
||||
my %countries = ();
|
||||
LJ::load_codes({ "country" => \%countries });
|
||||
return LJ::html_select({ 'name' => 'loc_cn', },
|
||||
'', '',
|
||||
map { $_, $countries{$_} }
|
||||
("US", sort { $countries{$a} cmp $countries{$b} } keys %countries));
|
||||
}
|
||||
_code?>
|
||||
</td></tr>
|
||||
<tr><td align='right'><?_ml .label.stateprovince _ml?></td><td><input name="loc_st" /></td></tr>
|
||||
<tr><td align='right'><?_ml .label.city _ml?></td><td><input name="loc_ci" /></td></tr>
|
||||
</table>
|
||||
|
||||
<=form
|
||||
crit?>
|
||||
|
||||
<!---- update time ----->
|
||||
<?crit
|
||||
name=><?_ml .label.bytime _ml?>
|
||||
code=>s_ut
|
||||
form<=
|
||||
<?_ml .label.updated _ml?>
|
||||
<select name="ut_days">
|
||||
<option value="">-------</option>
|
||||
<option value="1"><?_ml .sel.day _ml?></option>
|
||||
<option value="7"><?_ml .sel.week _ml?></option>
|
||||
<option value="30"><?_ml .sel.month _ml?></option>
|
||||
</select>
|
||||
<=form
|
||||
crit?>
|
||||
|
||||
<!---- interest ----->
|
||||
<?crit
|
||||
name=><?_ml .label.byinterest _ml?>
|
||||
code=>s_int
|
||||
form<=
|
||||
Community interest: <input name="int_like" size='30' />
|
||||
<=form
|
||||
crit?>
|
||||
|
||||
<!---- has member ----->
|
||||
<?crit
|
||||
name=><?_ml .label.hasmember _ml?>
|
||||
code=>s_fr
|
||||
form<=
|
||||
Contains user <input name="fr_user" size='15' maxlength='15' /> as a member.
|
||||
<=form
|
||||
crit?>
|
||||
|
||||
<?bar
|
||||
name=><?_ml .label.othercriteria _ml?>
|
||||
form<=
|
||||
<input type='checkbox' name="s_withpic" value='1' /> <?_ml .checkbox.onlywithpics _ml?>
|
||||
<=form
|
||||
bar?>
|
||||
|
||||
<!---- output formatting ----->
|
||||
<?bar
|
||||
name=><?_ml .label.displayoptions _ml?>
|
||||
form<=
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td align='right'>
|
||||
<?_ml .label.outputformat _ml?>
|
||||
</td><td>
|
||||
<select name="opt_format">
|
||||
<option value="com" selected='selected'><?_ml .sel.commview _ml?></option>
|
||||
<option value="pics"><?_ml .sel.bypicture _ml?></option>
|
||||
<option value="simple"><?_ml .sel.simple _ml?></option>
|
||||
</select>
|
||||
</td></tr>
|
||||
|
||||
<tr>
|
||||
<td align='right'>
|
||||
<?_ml .label.sortmethod _ml?>
|
||||
</td><td>
|
||||
<select name="opt_sort">
|
||||
<option value="user" selected='selected'><?_ml .sel.username _ml?></option>
|
||||
<option value="name"><?_ml .sel.communityname _ml?></option>
|
||||
<option value="ut"><?_ml .sel.updatetime _ml?></option>
|
||||
</select>
|
||||
</td></tr>
|
||||
|
||||
<tr>
|
||||
<td align='right'>
|
||||
<?_ml .label.records _ml?>
|
||||
</td><td>
|
||||
<select name="opt_pagesize">
|
||||
<option value="25">25</option>
|
||||
<option value="50">50</option>
|
||||
<option value="100" selected='selected'>100</option>
|
||||
<option value="200">200</option>
|
||||
</select>
|
||||
</td></tr>
|
||||
|
||||
</table>
|
||||
<=form
|
||||
bar?>
|
||||
|
||||
<!--- submit --->
|
||||
<tr bgcolor='<?emcolor?>'><td colspan='2' align='center'>
|
||||
<input type='submit' value="<?_ml .button.search _ml?>" />
|
||||
<input type='reset' value="<?_ml .button.clear _ml?>" />
|
||||
</td></tr>
|
||||
|
||||
</table>
|
||||
</form>
|
||||
|
||||
</center>
|
||||
|
||||
<=body
|
||||
page?>
|
||||
<?_c <LJDEP>
|
||||
form: htdocs/directory.bml
|
||||
</LJDEP> _c?>
|
||||
208
livejournal/htdocs/community/sentinvites.bml
Executable file
@@ -0,0 +1,208 @@
|
||||
<?page
|
||||
title=><?_ml .title _ml?>
|
||||
body<=
|
||||
<?_code
|
||||
{
|
||||
use strict;
|
||||
use vars qw(%GET %POST);
|
||||
|
||||
LJ::set_active_crumb('commsentinvites');
|
||||
|
||||
return LJ::server_down_html() if $LJ::SERVER_DOWN;
|
||||
|
||||
# always have links at top
|
||||
my $ret = BML::ml('Backlink', {
|
||||
'link' => '/community/manage.bml',
|
||||
'text' => $ML{'/community/members.bml.manage2'},
|
||||
});
|
||||
|
||||
# get remote
|
||||
my $remote = LJ::get_remote();
|
||||
unless ($remote) {
|
||||
$ret .= "<?h1 $ML{'Error'} h1?><?p $ML{'error.noremote'} p?>";
|
||||
return $ret;
|
||||
}
|
||||
|
||||
my $cname = $GET{comm};
|
||||
return BML::redirect("$LJ::SITEROOT/community/manage.bml") unless $cname;
|
||||
|
||||
# get $c object
|
||||
my $c = LJ::load_user($cname);
|
||||
unless ($c) {
|
||||
$ret .= "<?h1 $ML{'Error'} h1?><?p $ML{'/community/members.bml.error.nocomm'} p?>";
|
||||
return $ret;
|
||||
}
|
||||
my $cid = $c->{'userid'};
|
||||
|
||||
# is $remote an admin?
|
||||
unless (LJ::can_manage_other($remote, $c)) {
|
||||
$ret .= "<?h1 $ML{'Error'} h1?><?p ";
|
||||
$ret .= BML::ml('/community/members.bml.error.noaccess',
|
||||
{ 'comm' => LJ::ljuser($cname, { 'type' => 'C' }) });
|
||||
$ret .= " p?>";
|
||||
return $ret;
|
||||
}
|
||||
|
||||
# columns of our table, excluding username
|
||||
my @attribs = ('post');
|
||||
my @titleattribs = ('P');
|
||||
LJ::load_user_props($c, 'moderated');
|
||||
if ($c->{moderated}) {
|
||||
push @attribs, ('preapprove', 'moderate');
|
||||
push @titleattribs, ('U', 'M');
|
||||
}
|
||||
push @attribs, 'admin';
|
||||
push @titleattribs, 'A';
|
||||
|
||||
# now get sent invites and the users involved
|
||||
my $sent = LJ::get_sent_invites($c) || [];
|
||||
my @ids;
|
||||
push @ids, ($_->{userid}, $_->{maintid}) foreach @$sent;
|
||||
my $us = LJ::load_userids(@ids);
|
||||
|
||||
# populate %users hash
|
||||
my %users = ();
|
||||
foreach my $invite (@$sent) {
|
||||
my $id = $invite->{userid};
|
||||
next if $GET{show} && $GET{show} ne 'all' && $invite->{status} ne $GET{show};
|
||||
$users{$id}{userid} = $id;
|
||||
$users{$id}{maintainer} = $us->{$invite->{maintid}}{user};
|
||||
$users{$id}{user} = $us->{$id}{user};
|
||||
$users{$id}{$_} = 1 foreach keys %{$invite->{args}};
|
||||
$users{$id}{status} = $invite->{status};
|
||||
$users{$id}{date} = LJ::mysql_time($invite->{recvtime});
|
||||
$users{$id}{date} =~ s/\s.+$//; # we just want the date, ignore time
|
||||
}
|
||||
|
||||
# hop out if there were no invites
|
||||
unless (%users) {
|
||||
return "$ret<?h1 $ML{'.none.title'} h1?><?p " .
|
||||
BML::ml('.none.body', { aopts => "href='/community/members.bml?comm=$c->{user}'" }) .
|
||||
" p?>";
|
||||
}
|
||||
|
||||
# sorting method;
|
||||
my $method = $GET{'sort'};
|
||||
|
||||
my $cmp = sub {$a->{'user'} cmp $b->{'user'}};
|
||||
$cmp = sub {$b->{'admin'} <=> $a->{'admin'}} if $method eq 'A';
|
||||
$cmp = sub {$b->{'post'} <=> $a->{'post'}} if $method eq 'P';
|
||||
$cmp = sub {$b->{'moderate'} <=> $a->{'moderate'}} if $method eq 'M';
|
||||
$cmp = sub {$b->{'preapprove'} <=> $a->{'preapprove'}} if $method eq 'U';
|
||||
$cmp = sub {$a->{'status'} cmp $b->{'status'}} if $method eq 'status';
|
||||
$cmp = sub {$b->{'date'} cmp $a->{'date'}} if $method eq 'date';
|
||||
$cmp = sub {$b->{'maintainer'} cmp $a->{'maintainer'}} if $method eq 'maint';
|
||||
|
||||
my @users = sort $cmp values %users;
|
||||
my $page_size = 100; # change to adjust page size
|
||||
|
||||
# are we going to jump to a specific user ?
|
||||
my $jumppage;
|
||||
my $jumpuser;
|
||||
if (@users > $page_size && $POST{'jumpto'} =~ /^\w+$/) {
|
||||
my $ct;
|
||||
foreach (@users) {
|
||||
$jumppage++ if $ct % $page_size == 0;
|
||||
if ($POST{'jumpto'} eq $_->{'name'}) {
|
||||
$jumpuser = $_->{'name'};
|
||||
last;
|
||||
}
|
||||
$ct++;
|
||||
}
|
||||
undef $jumppage unless $jumpuser;
|
||||
}
|
||||
|
||||
# how to make links back to this page
|
||||
my $self_link = sub {
|
||||
my $sort = "&sort=$GET{'sort'}" if $GET{'sort'};
|
||||
my $filter = "&show=$GET{'show'}" if $GET{'show'};
|
||||
return "sentinvites.bml?comm=$cname&page=$_[0]$sort$filter";
|
||||
};
|
||||
|
||||
my %items = BML::paging(\@users, $jumppage || $GET{'page'}, $page_size);
|
||||
my $navbar = LJ::paging_bar($items{'page'}, $items{'pages'},
|
||||
{ 'self_link' => $self_link });
|
||||
@users = @{$items{'items'}};
|
||||
|
||||
# output starts here
|
||||
$ret .= "<?p " . BML::ml('/community/members.bml.name', { 'name' => LJ::ljuser($cname, { 'type' => 'C' }) });
|
||||
$ret .= " " . BML::ml('/community/members.bml.settings', { 'link' => "settings.bml?comm=$cname"}) . " p?>";
|
||||
|
||||
# jump to user
|
||||
if ($items{'pages'} > 1) {
|
||||
$ret .= "<form method='post' action='sentinvites.bml?comm=$cname'>";
|
||||
$ret .= "<div style='margin-left: 30px;'>Jump to user: ";
|
||||
$ret .= LJ::html_text({ 'name' => 'jumpto', 'value' => $POST{'jumpto'},
|
||||
'size' => '10', 'maxlength' => '15' }) . " ";
|
||||
$ret .= LJ::html_submit(undef, 'Go') . "</div>";
|
||||
$ret .= "</form>";
|
||||
$ret .= $navbar;
|
||||
}
|
||||
|
||||
# setup showlinks
|
||||
my $showlinks = "<form method='get' action='/community/sentinvites.bml'>";
|
||||
$showlinks .= LJ::html_hidden('comm', $c->{user});
|
||||
$showlinks .= "Filter to: ";
|
||||
$showlinks .= LJ::html_select({ name => 'show', selected => $GET{show} }, map { $_, $_ } qw(all accepted outstanding rejected));
|
||||
$showlinks .= LJ::html_submit(undef, 'Refresh');
|
||||
$showlinks .= "</form>";
|
||||
|
||||
my $filter = "&show=$GET{show}" if $GET{show};
|
||||
my $sortlink = BML::get_uri() . "?comm=$cname$filter&sort=";
|
||||
$ret .= "<br /><div align='center'>$showlinks";
|
||||
$ret .= <<END;
|
||||
<table class='borderedtable' cellpadding='2' cellspacing='0'>
|
||||
<tr style="background-color: <?altcolor1?>; border-bottom: solid 1px black;">
|
||||
<th style='border-right: solid 1px black;'>P</th>
|
||||
<td style='border-bottom: solid 1px black; border-right: solid 1px black;'>Posting Access</td>
|
||||
<th style='border-right: solid 1px black;'>U</th>
|
||||
<td style='border-bottom: solid 1px black;'>Unmoderated</td>
|
||||
</tr>
|
||||
<tr style="background-color: <?altcolor2?>; border-bottom: solid 1px black;">
|
||||
<th style='border-right: solid 1px black; border-bottom: none;'>M</th>
|
||||
<td style='border-right: solid 1px black;'>Moderator</td>
|
||||
<th style='border-right: solid 1px black; border-bottom: none;'>A</th>
|
||||
<td>Maintainer</td>
|
||||
</tr>
|
||||
</table>
|
||||
<br />
|
||||
END
|
||||
$ret .= "<table class='borderedtable' cellpadding='2' cellspacing='0'>\n<tr>" .
|
||||
"<th><a href='${sortlink}name'>$ML{'/community/members.bml.key.user'}</a></th>";
|
||||
$ret .= "<th><a href='${sortlink}$_'>$_</a></th>" foreach @titleattribs;
|
||||
$ret .= "<th><a href='${sortlink}maint'>$ML{'.key.sentby'}</a></th>";
|
||||
$ret .= "<th><a href='${sortlink}date'>$ML{'.key.date'}</a></th>";
|
||||
$ret .= "<th><a href='${sortlink}status'>$ML{'.key.status'}</a></th>";
|
||||
$ret .= "</tr>\n";
|
||||
|
||||
# checkboxes and such
|
||||
my $yes = '<img src="/img/blue_check.gif" width="15" height="15" border="0">';
|
||||
my $no = '-';
|
||||
|
||||
# rows for existing users
|
||||
my $rc = 0;
|
||||
foreach(@users) {
|
||||
my $rstyle = ($rc++ & 1) ? "<?altcolor1?>" : "<?altcolor2?>";
|
||||
$ret .= "<tr style='background-color: $rstyle;'><td>" . LJ::ljuser($_->{user}) . "</td>";
|
||||
foreach my $key (@attribs) {
|
||||
$ret .= "<td align='center'>";
|
||||
$ret .= $_->{$key} ? $yes : $no;
|
||||
$ret .= "</td>";
|
||||
}
|
||||
$ret .= "<td>" . LJ::ljuser($_->{maintainer}, { type => 'P' }) . "</td>";
|
||||
$ret .= "<td>$_->{date}</td>";
|
||||
$ret .= "<td>$_->{status}</td>";
|
||||
$ret .= "</tr>\n";
|
||||
}
|
||||
|
||||
$ret .= "</table>\n";
|
||||
$ret .= "<br /><a href='/community/members.bml?comm=$c->{user}'>$ML{'.send'}</a>";
|
||||
$ret .= "</div>\n\n";
|
||||
$ret .= $navbar;
|
||||
return $ret;
|
||||
|
||||
}
|
||||
_code?>
|
||||
|
||||
<=body
|
||||
page?>
|
||||
252
livejournal/htdocs/community/settings.bml
Executable file
@@ -0,0 +1,252 @@
|
||||
<?page
|
||||
title<=
|
||||
<?_code
|
||||
if ($GET{'mode'} eq 'create') {
|
||||
return $ML{'.title.create'};
|
||||
}
|
||||
else {
|
||||
return $ML{'.title.modify'};
|
||||
}
|
||||
_code?>
|
||||
<=title
|
||||
head<=
|
||||
<style type='text/css'>
|
||||
div.opts { margin: 10px 0 10px 30px; }
|
||||
</style>
|
||||
<=head
|
||||
body<=
|
||||
<?_code
|
||||
|
||||
use strict;
|
||||
use vars qw(%GET %POST);
|
||||
|
||||
# always have links at top
|
||||
my $ret = BML::ml('Backlink', {
|
||||
'link' => '/community/manage.bml',
|
||||
'text' => $ML{'/community/members.bml.manage2'},
|
||||
});
|
||||
my %errors;
|
||||
|
||||
my $remote = LJ::get_remote();
|
||||
|
||||
unless ($remote) {
|
||||
$ret .= "<?h1 $ML{'Error'} h1?><?p $ML{'error.noremote'} p?>";
|
||||
return $ret;
|
||||
}
|
||||
|
||||
unless ($remote->{'journaltype'} eq 'P') {
|
||||
$ret .= "<?h1 $ML{'Error'} h1?><?p $ML{'.error.maintainertype'} p?>";
|
||||
return $ret;
|
||||
}
|
||||
|
||||
my $mode = "modify";
|
||||
$mode = "create" if $GET{'mode'} eq 'create';
|
||||
|
||||
if (LJ::did_post())
|
||||
{
|
||||
my $sth;
|
||||
my $cuser = LJ::canonical_username($POST{'cuser'});
|
||||
my $cu = LJ::load_user($cuser);
|
||||
|
||||
unless ($cu) {
|
||||
$errors{'username'} = $ML{'.error.notfound'};
|
||||
}
|
||||
|
||||
if ($cu && $cu->{'userid'} == $remote->{'userid'}) {
|
||||
$errors{'username'} = $ML{'.error.samenames'};
|
||||
}
|
||||
|
||||
# if we're changing rather than creating, check that we can
|
||||
if ($mode eq 'modify' && !LJ::can_manage_other($remote, $cu)) {
|
||||
$errors{'username'} = BML::ml('.error.noaccess', {'comm'=>$cuser});
|
||||
}
|
||||
|
||||
# if we're creating, community password must match
|
||||
if ($mode eq 'create' && $cu && !LJ::auth_okay($cu, $POST{'cpassword'})) {
|
||||
$errors{'password'} = $ML{'.error.badpassword'};
|
||||
}
|
||||
|
||||
# disallow changing the journal type if the journal has entries
|
||||
if ($mode eq 'create' && !%errors && !LJ::check_priv($remote, "changejournaltype", "")) {
|
||||
my $count;
|
||||
my $userid=$cu->{'userid'}+0;
|
||||
|
||||
my $dbcr = LJ::get_cluster_reader($cu);
|
||||
$count = $dbcr->selectrow_array("SELECT COUNT(*) FROM log2 WHERE journalid=$userid AND posterid=journalid");
|
||||
|
||||
$errors{'username'} = $ML{'.error.hasentries'} if $count;
|
||||
}
|
||||
|
||||
# if it's already a community, don't let them turn it into a community
|
||||
if ($mode eq 'create' && !%errors && $cu->{journaltype} eq 'C') {
|
||||
$errors{'username'} = $ML{'.error.alreadycomm'};
|
||||
}
|
||||
|
||||
# if we found errors, we'll redisplay the form below. otherwise,
|
||||
# proceed.
|
||||
unless (%errors) {
|
||||
my $dbh = LJ::get_db_writer();
|
||||
my $cid = $cu->{'userid'};
|
||||
my $qmembership = $POST{membership};
|
||||
$qmembership = 'closed' unless $qmembership =~ m/(?:open|moderated|closed)/;
|
||||
$qmembership = $dbh->quote($qmembership);
|
||||
my $qpostlevel = $dbh->quote($POST{'postlevel'} eq "members" ? "members" : "select");
|
||||
|
||||
LJ::update_user($cu, { journaltype => 'C' });
|
||||
if ($mode eq 'create') {
|
||||
$dbh->do("REPLACE INTO community (userid, membership, postlevel) VALUES ($cid, $qmembership, $qpostlevel)");
|
||||
LJ::set_rel($cu, $remote, 'A');
|
||||
|
||||
# delete existing friends
|
||||
my $friends = LJ::get_friends($cid, undef, undef, 'force') || {};
|
||||
LJ::remove_friend($cid, [ keys %$friends ]);
|
||||
|
||||
} else {
|
||||
$dbh->do("UPDATE community SET membership=$qmembership, postlevel=$qpostlevel WHERE userid=$cid");
|
||||
}
|
||||
|
||||
my $nonmembers = $POST{'nonmember_posting'} + 0;
|
||||
my $moderated = $POST{'moderated'} + 0;
|
||||
|
||||
LJ::set_userprop($cu, 'nonmember_posting', $nonmembers);
|
||||
LJ::set_userprop($cu, 'moderated', $moderated);
|
||||
|
||||
if ($moderated && ! LJ::load_rel_user($cu->{'userid'}, 'M')->[0]) {
|
||||
LJ::set_rel($cu->{'userid'}, $remote->{'userid'}, 'M');
|
||||
}
|
||||
|
||||
$ret .= "<?h1 $ML{'.success'} h1?>";
|
||||
if ($mode eq 'create') {
|
||||
$ret .= "<?p $ML{'.label.commcreated'} p?>";
|
||||
} else {
|
||||
$ret .= "<?p $ML{'.label.commchanged'} p?>";
|
||||
}
|
||||
|
||||
$ret .= "<?p $ML{'.label.rellinks'} <ul><li><a href='$LJ::SITEROOT/community/$cu->{'user'}/'>$ML{'.label.commsite'}</a></li>";
|
||||
$ret .= "<li><a href='/userinfo.bml?user=$cu->{'user'}'>$ML{'.label.comminfo'}</a></li><li>"
|
||||
. BML::ml('.label.managepage', { 'aopts' => 'href="/community/manage.bml"' }) . "</li></ul> p?>";
|
||||
|
||||
return $ret;
|
||||
}
|
||||
}
|
||||
|
||||
# we're either creating a new community or modifying settings of an existing one
|
||||
# based on whether $mode is 'create' or 'modify'. Most of the page is the same in
|
||||
# either case, and additionally we must preload existing settings when modifying.
|
||||
|
||||
my ($cname, $c);
|
||||
|
||||
$cname = $POST{'cuser'}; # if we're falling through with errors when creating
|
||||
|
||||
my %info = (
|
||||
'membership'=>$POST{'membership'} || 'open',
|
||||
'postlevel'=>$POST{'postlevel'} || 'members',
|
||||
'nonmember_posting'=>$POST{'nonmember_posting'} || 0,
|
||||
'moderated'=>$POST{'moderated'} || 0,
|
||||
);
|
||||
|
||||
if ($mode eq 'modify') {
|
||||
$cname = LJ::canonical_username($GET{'comm'});
|
||||
$c = LJ::load_user($cname);
|
||||
unless ($c) {
|
||||
# if no community was specified, redirect to manage.bml
|
||||
return BML::redirect("$LJ::SITEROOT/community/manage.bml");
|
||||
}
|
||||
unless ($c->{'journaltype'} eq 'C') {
|
||||
$ret = "<?h1 $ML{'Error'} h1?><?p $ML{'.error.notcomm'} p?>";
|
||||
return $ret;
|
||||
}
|
||||
my $dbr = LJ::get_db_reader();
|
||||
($info{'membership'},$info{'postlevel'}) =
|
||||
$dbr->selectrow_array("SELECT membership, postlevel FROM community WHERE userid=$c->{'userid'}");
|
||||
LJ::load_user_props($c, "nonmember_posting", "moderated");
|
||||
$info{'nonmember_posting'} = $c->{'nonmember_posting'} ? 1 : 0;
|
||||
$info{'moderated'} = $c->{'moderated'} ? 1 : 0;
|
||||
}
|
||||
|
||||
$ret .= "<form method='post' action='settings.bml?mode=$mode'>";
|
||||
|
||||
if ($mode eq 'modify') {
|
||||
$ret .= "<?h1 $ML{'.label.changeheader'} h1?><?p $ML{'.label.changetext'} p?>";
|
||||
} else {
|
||||
$ret .= "<?h1 $ML{'.label.createheader'} h1?><?p $ML{'.label.createtext'} p?>";
|
||||
}
|
||||
|
||||
if ($mode eq 'create') {
|
||||
LJ::set_active_crumb('createcommunity');
|
||||
$ret .= "<?h2 $ML{'.label.commheader'} h2?>" .
|
||||
($mode eq 'modify' ? "<?p $ML{'.label.commchange'} p?>" : "<?p $ML{'.label.commcreate'} p?>");
|
||||
$ret .= "<?standout <table width='350' cellpadding='7'><tr valign='top'><td><b>$ML{'.label.maintainer'}</b></td>";
|
||||
$ret .= "<td><?ljuser $remote->{'user'} ljuser?><br />$ML{'.label.maintainer.login'}</td></tr>";
|
||||
$ret .= "<tr valign='top'><td><b>$ML{'.label.community'}</b></td>";
|
||||
$ret .= "<td>$ML{'.label.username'}<br /><input name='cuser' maxlength='15' value='$cname' /><br />";
|
||||
$ret .= "<?inerr $errors{'username'} inerr?><br />";
|
||||
$ret .= "$ML{'.label.password'}<br /><input name='cpassword' type='password' /><br />";
|
||||
$ret .= "<?inerr $errors{'password'} inerr?></td></tr></table> standout?>";
|
||||
} else {
|
||||
LJ::set_active_crumb('commsettings');
|
||||
$ret .= LJ::html_hidden('cuser', $cname);
|
||||
$ret .= "<?p " . BML::ml('.name',{'name'=>"<?ljcomm $cname ljcomm?>"});
|
||||
$ret .= " " . BML::ml('.members',{'link'=>"/community/members.bml?comm=$cname"}) . " p?>";
|
||||
}
|
||||
|
||||
$ret .= "<?h1 $ML{'.label.commopts'} h1?><?p $ML{'.label.howoperates'} p?>";
|
||||
$ret .= "<?h2 $ML{'.label.membership'} h2?><?p $ML{'.label.whocanjoin'} p?><div class='opts'>";
|
||||
|
||||
# membership levels
|
||||
$ret .= "<p>";
|
||||
$ret .= LJ::html_check({ type => 'radio', name => 'membership', id => 'memopen',
|
||||
value => 'open', selected => ($info{membership} eq 'open' ? 1 : 0)});
|
||||
$ret .= "<label for='memopen' $ML{'.label.openmemb'}</label></p><p>";
|
||||
$ret .= LJ::html_check({ type => 'radio', name => 'membership', id => 'memmoderated',
|
||||
value => 'moderated', selected => ($info{membership} eq 'moderated' ? 1 : 0)});
|
||||
$ret .= "<label for='memmoderated' $ML{'.label.moderatedmemb'}</label></p><p>";
|
||||
$ret .= LJ::html_check({ type => 'radio', name => 'membership', id => 'memclosed',
|
||||
value => 'closed', selected => ($info{membership} eq 'closed' ? 1 : 0)});
|
||||
$ret .= "<label for='memclosed' $ML{'.label.closedmemb2'}</label></p>";
|
||||
$ret .= "</div>";
|
||||
|
||||
my ($optopen,$optclosed);
|
||||
if ($info{'postlevel'} eq 'members') {
|
||||
($optopen,$optclosed)=(" checked='checked'","");
|
||||
} else {
|
||||
($optopen,$optclosed)=("", " checked='checked'");
|
||||
}
|
||||
|
||||
$ret .= "<?h2 $ML{'.label.postaccess'} h2?><?p $ML{'.label.whocanpost'} p?><div class='opts'>";
|
||||
$ret .= "<input type='radio' id='postopen' name='postlevel' value='members'$optopen /><label for='postopen'> $ML{'.label.anybodycan'}</label>";
|
||||
$ret .= "<p><input type='radio' id='postclosed' name='postlevel' value='select'$optclosed /><label for='postclosed'> $ML{'.label.selcan'}</label>";
|
||||
$ret .= "</div>";
|
||||
|
||||
if ($info{'nonmember_posting'}) {
|
||||
($optopen,$optclosed)=(" checked='checked'","");
|
||||
} else {
|
||||
($optopen,$optclosed)=("", " checked='checked'");
|
||||
}
|
||||
|
||||
$ret .= "<?h2 $ML{'.label.nmheader'} h2?><?p $ML{'.label.nmtext'} p?><div class='opts'>";
|
||||
$ret .= "<input type='radio' id='nonopen' name='nonmember_posting' value='0'$optclosed /><label for='nonopen'> $ML{'.label.nmcant'}</label>";
|
||||
$ret .= "<p><input type='radio' id='nonclosed' name='nonmember_posting' value='1'$optopen /><label for='nonclosed'> $ML{'.label.nmcan'}</label>";
|
||||
$ret .= "</div>";
|
||||
|
||||
if ($info{'moderated'}) {
|
||||
($optopen,$optclosed)=(" checked='checked'","");
|
||||
} else {
|
||||
($optopen,$optclosed)=("", " checked='checked'");
|
||||
}
|
||||
|
||||
$ret .= "<?h2 $ML{'.label.modheader'} h2?><?p $ML{'.label.modtext'} p?><div class='opts'>";
|
||||
$ret .= "<input type='radio' id='radunmod' name='moderated' value='0'$optclosed /><label for='radunmod'> $ML{'.label.modisnt'}</label>";
|
||||
$ret .= "<p><input type='radio' id='radmod' name='moderated' value='1'$optopen /><label for='radmod'> $ML{'.label.modis'}</label>";
|
||||
$ret .= "</div>\n";
|
||||
|
||||
$ret .= "<center><input type='submit' value='" .
|
||||
($mode eq 'create' ? "$ML{'.button.createcommunity'}" : "$ML{'.button.changecommunity'}") .
|
||||
"' /></center></form>";
|
||||
|
||||
return $ret;
|
||||
|
||||
_code?>
|
||||
|
||||
<=body
|
||||
page?>
|
||||
66
livejournal/htdocs/community/transfer.bml
Executable file
@@ -0,0 +1,66 @@
|
||||
<?_code
|
||||
{
|
||||
LJ::set_active_crumb('transfercomm');
|
||||
|
||||
$title = $ML{'.title'};
|
||||
$body = "";
|
||||
|
||||
# is there a user out there?
|
||||
my $remote = LJ::get_remote();
|
||||
return "<?needlogin?>" unless $remote;
|
||||
|
||||
# bad statusvis?
|
||||
unless ($remote->{statusvis} eq 'V') {
|
||||
$body = "<?h1 $ML{'.badstatus.title'} h1?><?p $ML{'.badstatus.body'} p?>";
|
||||
return;
|
||||
}
|
||||
|
||||
# see if they posted and perform actions if so
|
||||
if (LJ::did_post()) {
|
||||
# get info about the community
|
||||
my $cu = LJ::load_user($POST{comm});
|
||||
$errors{username} = $ML{'.error.notfound'} unless $cu;
|
||||
|
||||
# the rest of the errors assume a community exists
|
||||
if ($cu) {
|
||||
# status/type errors
|
||||
$errors{username} = $ML{'.error.notcomm'} unless $cu->{journaltype} eq 'C';
|
||||
$errors{username} = $ML{'.error.badstatus'} if !%errors && $cu->{statusvis} !~ /[VD]/;
|
||||
|
||||
# are they already a maintainer?
|
||||
$errors{username} = $ML{'.error.alreadyadmin'} if !%errors && LJ::can_manage($remote, $cu);
|
||||
|
||||
# check the password last
|
||||
$errors{password} = $ML{'.error.nopassword'} if !%errors && !$POST{password};
|
||||
$errors{password} = $ML{'.error.mismatch'} if !%errors && !LJ::auth_okay($cu, $POST{password});
|
||||
}
|
||||
|
||||
# everything checks out, transfer it
|
||||
unless (%errors) {
|
||||
$cu->log_event('maintainer_add', { actiontarget => $remote->{userid}, remote => $remote });
|
||||
LJ::set_rel($cu, $remote, 'A');
|
||||
$body = "<?h1 $ML{'.success.title'} h1?><?p ";
|
||||
$body .= BML::ml('.success.body', { comm => LJ::ljuser($cu, { type => 'C' }) });
|
||||
$body .= " p?>";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
# setup the form to transfer the community
|
||||
$body .= "<?h1 $ML{'.title'} h1?><?p $ML{'.body'} p?>";
|
||||
$body .= "<form method='post' action='/community/transfer.bml'>";
|
||||
$body .= "<table><tr><td>$ML{'.account'}</td>";
|
||||
$body .= "<td>" . LJ::html_text({ name => 'comm', id => 'comm', value => $POST{comm} }) . "</td></tr>\n";
|
||||
$body .= "<tr><td></td><td><?inerr $errors{username} inerr?></td></tr>" if $errors{username};
|
||||
$body .= "<tr><td>$ML{'.password'}</td>";
|
||||
$body .= "<td>" . LJ::html_text({ type => 'password', name => 'password', id => 'password' }) . "</td></tr>\n";
|
||||
$body .= "<tr><td></td><td><?inerr $errors{password} inerr?></td></tr>" if $errors{password};
|
||||
$body .= "<tr><td></td><td>" . LJ::html_submit(undef, $ML{'.button.title'}) . "</td></tr>";
|
||||
$body .= "</table></form>";
|
||||
|
||||
return;
|
||||
}
|
||||
_code?><?page
|
||||
title=><?_code return $title; _code?>
|
||||
body=><?_code return $body; _code?>
|
||||
page?>
|
||||
620
livejournal/htdocs/create.bml
Executable file
@@ -0,0 +1,620 @@
|
||||
<?page
|
||||
title=><?_ml .title _ml?>
|
||||
head<=
|
||||
<style type="text/css">
|
||||
|
||||
|
||||
.tablecontent {
|
||||
border-top: 1px solid #dfdfdf;
|
||||
border-bottom: 1px solid #dfdfdf;
|
||||
padding-top: 5px;
|
||||
padding-bottom: 5px;
|
||||
text-align: center;
|
||||
width: 8%;
|
||||
}
|
||||
|
||||
.tablelabel {
|
||||
border-top: 1px solid #dfdfdf;
|
||||
border-bottom: 1px solid #dfdfdf;
|
||||
padding-top: 5px;
|
||||
padding-bottom: 5px;
|
||||
width: 20%;
|
||||
font-size: .9em;
|
||||
}
|
||||
|
||||
.tablehead {
|
||||
border-bottom: 1px solid #dfdfdf;
|
||||
padding-top: 5px;
|
||||
padding-bottom: 5px;
|
||||
font-weight: bold;
|
||||
white-space: nowrap;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.tablebottom {
|
||||
border-top: 1px solid #dfdfdf;
|
||||
padding-top: 5px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
</style>
|
||||
<=head
|
||||
body<=
|
||||
<?_code
|
||||
|
||||
my $crumb = $LJ::IS_SSL ? 'securecreatejournal' : 'createjournal';
|
||||
LJ::set_active_crumb($crumb);
|
||||
|
||||
return LJ::server_down_html() if ($LJ::SERVER_DOWN);
|
||||
|
||||
return "<?badinput?>" unless LJ::text_in(\%POST);
|
||||
|
||||
my $mode = $POST{'mode'};
|
||||
my $code = $POST{'code'} || $GET{'code'};
|
||||
|
||||
if ($LJ::USE_SSL && ! $LJ::IS_SSL && $FORM{'ssl'} ne "no") {
|
||||
return BML::redirect("$LJ::SSLROOT/create.bml");
|
||||
}
|
||||
|
||||
# with no mode, decide which screen the user sees first, based
|
||||
# on whether or not this LJ installation lets in free users
|
||||
if ($mode eq "") {
|
||||
$mode = $LJ::USE_ACCT_CODES ?
|
||||
($code ? "codesubmit" : "entercode")
|
||||
: "getinfo";
|
||||
}
|
||||
|
||||
my $remote = LJ::get_remote();
|
||||
|
||||
my %errors;
|
||||
my $error_msg = sub {
|
||||
my $key = shift;
|
||||
my $pre = shift;
|
||||
my $post = shift;
|
||||
my $msg = $errors{$key};
|
||||
return unless $msg;
|
||||
return "$pre $msg $post";
|
||||
};
|
||||
|
||||
# Flag to indicate they've submitted with 'audio' as the answer to the spambot
|
||||
# challenge.
|
||||
my $wants_audio = 0;
|
||||
|
||||
# Captcha id
|
||||
my ($capid, $anum);
|
||||
|
||||
# validate a code they've entered and throw them back to entercode
|
||||
# mode if it's invalid
|
||||
if ($code && $mode eq "submit" || # account codes turned off, but one specified anyway
|
||||
$LJ::USE_ACCT_CODES && ($mode eq "codesubmit" || $mode eq "submit")) # account codes required
|
||||
{
|
||||
my $error;
|
||||
my $userid = 0; # acceptable userid for double-click protection
|
||||
if ($mode eq "submit") {
|
||||
my $u = LJ::load_user($POST{'user'});
|
||||
$userid = $u->{'userid'};
|
||||
}
|
||||
$errors{'code'} = $error
|
||||
unless (LJ::acct_code_check($code, \$error, $userid));
|
||||
if (%errors) {
|
||||
$mode = "entercode";
|
||||
} elsif ($mode eq "codesubmit") {
|
||||
$mode = "getinfo";
|
||||
}
|
||||
}
|
||||
|
||||
# MODE: entercode - enter an account code to proceed making an account
|
||||
if ($LJ::USE_ACCT_CODES && $mode eq "entercode")
|
||||
{
|
||||
my $ret;
|
||||
my $v;
|
||||
|
||||
$ret .= "<form method=\"post\" action=\"create.bml\">\n";
|
||||
$ret .= LJ::html_hidden(mode => 'codesubmit',
|
||||
ssl => $FORM{'ssl'});
|
||||
|
||||
$ret .= "<?h1 $ML{'.useacctcodes.welcome'} h1?><?p $ML{'.useacctcodes.entercode'} p?>";
|
||||
|
||||
$v = LJ::ehtml($code);
|
||||
$ret .= "<?standout Code: <input type=\"text\" name=\"code\" value=\"$v\" size=\"13\" maxlength=\"12\"> <input type=\"submit\" value=\"$ML{'.btn.proceed'}\">";
|
||||
$ret .= $error_msg->('code', '<br>');
|
||||
$ret .= " standout?>";
|
||||
$ret .= "</form>\n";
|
||||
|
||||
open (REM, "$LJ::HOME/htdocs/inc/account-codes");
|
||||
while (<REM>) {
|
||||
$ret .= $_;
|
||||
}
|
||||
close REM;
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
# MODE: submit - if they've given 'audio' as the answer to the spambot-blocker,
|
||||
# reset the mode to 'getinfo' and set the audio flag
|
||||
if ( $LJ::HUMAN_CHECK{create} && $mode eq 'submit' && lc($POST{answer}) eq 'audio' )
|
||||
{
|
||||
$mode = 'getinfo';
|
||||
$wants_audio = 1;
|
||||
}
|
||||
|
||||
# MODE: submit - try to create an account. might change mode
|
||||
# if there are errors, we'll populate %errors and
|
||||
# return to "getinfo" mode below
|
||||
SUBMIT:
|
||||
while ($mode eq "submit") # using while instead of if so we can 'last' out of it
|
||||
{
|
||||
return "<b>$ML{'Error'}</b>: $ML{'.error.postrequired'}" unless LJ::did_post();
|
||||
|
||||
my $user = LJ::canonical_username($POST{'user'});
|
||||
my $email = LJ::trim(lc($POST{'email'}));
|
||||
|
||||
# setup global things that can be used to modify the user later
|
||||
my $is_underage = 0; # turn on if the user should be marked as underage
|
||||
my $ofage = 0; # turn on to note that the user is over 13 in actuality
|
||||
# (but is_underage might be on which just means that their
|
||||
# account is being marked as underage--even if they're old
|
||||
# enough [unique cookie check])
|
||||
|
||||
# reject this email?
|
||||
return LJ::sysban_block(0, "Create user blocked based on email",
|
||||
{ 'new_user' => $user, 'email' => $email, 'name' => $user })
|
||||
if LJ::sysban_check('email', $email);
|
||||
|
||||
my $dbh = LJ::get_db_writer();
|
||||
|
||||
if (length($user) > 15) {
|
||||
$errors{'username'} = "$ML{'error.usernamelong'}";
|
||||
}
|
||||
if ($POST{'user'} && ! $user) {
|
||||
$errors{'username'} = "$ML{'error.usernameinvalid'}";
|
||||
}
|
||||
unless ($POST{'user'}) {
|
||||
$errors{'username'} = "$ML{'.error.username.mustenter'}";
|
||||
}
|
||||
foreach my $re ("^system\$", @LJ::PROTECTED_USERNAMES) {
|
||||
next unless ($user =~ /$re/);
|
||||
|
||||
# you can give people sharedjournal priv ahead of time to create
|
||||
# reserved communities:
|
||||
next if LJ::check_priv($remote, "sharedjournal", $user);
|
||||
|
||||
$errors{'username'} = "$ML{'.error.username.reserved'}";
|
||||
}
|
||||
|
||||
# see if they're confused and entered a valid account code
|
||||
# for their username (happens often)
|
||||
if ($LJ::USE_ACCT_CODES && $user =~ /^.....a[ab].....$/) {
|
||||
# see if the acctcode is valid and unused
|
||||
my ($acid, $auth) = LJ::acct_code_decode($user);
|
||||
my $is_valid = $dbh->selectrow_array("SELECT COUNT(*) FROM acctcode ".
|
||||
"WHERE acid=? AND rcptid=0",
|
||||
undef, $acid);
|
||||
$errors{'username'} = "$ML{'.error.username.iscode'}"
|
||||
if $is_valid;
|
||||
}
|
||||
|
||||
my $u = LJ::load_user($user);
|
||||
my $second_submit = 0;
|
||||
if ($u) {
|
||||
my $in_use = 1;
|
||||
|
||||
if ($u->{'email'} eq $POST{'email'}) {
|
||||
if (LJ::login_ip_banned($u)) {
|
||||
# brute-force possible going on
|
||||
} else {
|
||||
if ($u->{'password'} eq $POST{'password1'}) {
|
||||
# oh, they double-clicked the submit button
|
||||
$second_submit = 1;
|
||||
$in_use = 0;
|
||||
} else {
|
||||
LJ::handle_bad_login($u);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($in_use) {
|
||||
$errors{'username'} = "$ML{'.error.username.inuse'}";
|
||||
}
|
||||
}
|
||||
|
||||
$POST{'password1'} = LJ::trim($POST{'password1'});
|
||||
$POST{'password2'} = LJ::trim($POST{'password2'});
|
||||
|
||||
if ($POST{'password1'} ne $POST{'password2'}) {
|
||||
$errors{'password'} = "$ML{'.error.password.nomatch'}";
|
||||
} else {
|
||||
my @checkpass = LJ::run_hooks("bad_password",
|
||||
{ 'user' => $user, 'name' => $user,
|
||||
'email' => $email, 'password' => $POST{'password1'} });
|
||||
if (@checkpass && $checkpass[0]->[0]) {
|
||||
$errors{'password'} = "Bad password: $checkpass[0]->[0]";
|
||||
}
|
||||
}
|
||||
if (! $POST{'password1'}) {
|
||||
$errors{'password'} = "$ML{'.error.password.blank'}";
|
||||
} elsif (length $POST{'password1'} > 30) {
|
||||
$errors{'password'} = "$ML{'password.max30'}";
|
||||
}
|
||||
|
||||
unless (LJ::is_ascii($POST{'password1'})) {
|
||||
$errors{'password'} = "$ML{'.error.password.asciionly'}";
|
||||
}
|
||||
|
||||
### start COPPA_CHECK
|
||||
# age checking to determine how old they are
|
||||
if ($LJ::COPPA_CHECK) {
|
||||
my $uniq;
|
||||
if ($LJ::UNIQ_COOKIES) {
|
||||
$uniq = Apache->request->notes('uniq');
|
||||
if ($uniq) {
|
||||
my $timeof = $dbh->selectrow_array('SELECT timeof FROM underage WHERE uniq = ?', undef, $uniq);
|
||||
$is_underage = 1 if $timeof && $timeof > 0;
|
||||
}
|
||||
}
|
||||
|
||||
my ($year, $mon, $day) = ( $POST{"bday_yyyy"}+0, $POST{"bday_mm"}+0, $POST{"bday_dd"}+0 );
|
||||
if ($year < 100) {
|
||||
$POST{'bday_yyyy'} += 1900;
|
||||
$year += 1900;
|
||||
}
|
||||
|
||||
# get current time
|
||||
my ($nday, $nmon, $nyear) = (gmtime())[3, 4, 5];
|
||||
$nyear += 1900;
|
||||
$nmon += 1;
|
||||
|
||||
# require dates in the 1900s (or beyond)
|
||||
if ($year && $mon && $day && $year >= 1900 && $year <= $nyear) {
|
||||
# now see how many years back they are
|
||||
my $ofageyear = $year + 13;
|
||||
if ($ofageyear > $nyear) {
|
||||
$is_underage = 1;
|
||||
} elsif ($ofageyear == $nyear) {
|
||||
# years match, see if they were born after this month
|
||||
if ($mon > $nmon) {
|
||||
$is_underage = 1;
|
||||
} elsif ($mon == $nmon) {
|
||||
# now check the day
|
||||
if ($day > $nday) {
|
||||
$is_underage = 1;
|
||||
} else {
|
||||
$ofage = 1;
|
||||
}
|
||||
} else {
|
||||
$ofage = 1;
|
||||
}
|
||||
} else {
|
||||
$ofage = 1;
|
||||
}
|
||||
} else {
|
||||
$errors{'bday'} = "$ML{'.error.birthday.invalid'}";
|
||||
}
|
||||
|
||||
# note this unique cookie as underage (if we have a unique cookie)
|
||||
if ($is_underage && $uniq) {
|
||||
$dbh->do("REPLACE INTO underage (uniq, timeof) VALUES (?, UNIX_TIMESTAMP())", undef, $uniq);
|
||||
}
|
||||
}
|
||||
### end COPPA_CHECK
|
||||
|
||||
if ($LJ::TOS_CHECK && ! $POST{'agree_tos'}) {
|
||||
$errors{'agree_tos'} = $ML{'tos.error'};
|
||||
}
|
||||
|
||||
# check the email address
|
||||
{
|
||||
my @email_errors;
|
||||
LJ::check_email($email, \@email_errors);
|
||||
if ($LJ::USER_EMAIL and $email =~ /\@\Q$LJ::USER_DOMAIN\E$/i) {
|
||||
push @email_errors, BML::ml(".error.email.lj_domain",
|
||||
{domain => $LJ::USER_DOMAIN});
|
||||
}
|
||||
$errors{'email'} = join(", ", @email_errors) if @email_errors;
|
||||
}
|
||||
|
||||
# Check the turing test answer if it's turned on
|
||||
if ($LJ::HUMAN_CHECK{create}) {
|
||||
($capid, $anum) = LJ::Captcha::session_check_code($POST{captcha_chal}, $POST{answer});
|
||||
$errors{'captcha'} = $ML{'.captcha.invalid'} unless $capid && $anum;
|
||||
}
|
||||
last SUBMIT if %errors;
|
||||
|
||||
my $clusterid = ($LJ::ALLOW_CLUSTER_SELECT
|
||||
? $POST{'cluster_id'}
|
||||
: LJ::new_account_cluster()) + 0;
|
||||
die "Cluster 0 not supported" unless $clusterid;
|
||||
|
||||
my $userid = $u ? $u->{'userid'}+0 : 0;
|
||||
unless ($second_submit)
|
||||
{
|
||||
my $caps = int($LJ::NEWUSER_CAPS);
|
||||
my $status = ($LJ::EVERYONE_VALID ? 'A' : 'N');
|
||||
$dbh->do("INSERT INTO user (user, email, password, status, caps, name, clusterid, dversion) ".
|
||||
"VALUES (?, ?, ?, ?, ?, ?, ?, ?)",
|
||||
undef, $user, $email, $POST{'password1'}, $status, $caps,
|
||||
$user, $clusterid, $LJ::MAX_DVERSION);
|
||||
if ($dbh->err) {
|
||||
return "<?h1 $ML{'Error'} h1?><?p $ML{'error.procrequest'} <b>" . $dbh->errstr . "</b> p?>";
|
||||
}
|
||||
$userid = $dbh->{'mysql_insertid'};
|
||||
$dbh->do("REPLACE INTO useridmap (userid, user) VALUES (?, ?)", undef, $userid, $user);
|
||||
$dbh->do("REPLACE INTO userusage (userid, timecreate) VALUES (?, NOW())", undef, $userid);
|
||||
|
||||
# if we're using account codes on this site, mark the code as used
|
||||
if ($code) {
|
||||
my ($acid, $auth) = LJ::acct_code_decode($code);
|
||||
$dbh->do("UPDATE acctcode SET rcptid=$userid WHERE acid=$acid");
|
||||
if ($dbh->err) { return $dbh->errstr; }
|
||||
}
|
||||
|
||||
# if we have initial friends for new accounts, add them.
|
||||
foreach my $friend (@LJ::INITIAL_FRIENDS) {
|
||||
my $friendid = LJ::get_userid($friend);
|
||||
LJ::add_friend($userid, $friendid) if $friendid;
|
||||
}
|
||||
foreach my $friend (@LJ::INITIAL_OPTIONAL_FRIENDS) {
|
||||
my $friendid = LJ::get_userid($friend);
|
||||
LJ::add_friend($userid, $friendid) if $friendid and $POST{"initial_optional_friend_$friend"};
|
||||
}
|
||||
|
||||
# Set any properties that get set in new users
|
||||
while (my ($name, $val) = each %LJ::USERPROP_INIT) {
|
||||
LJ::set_userprop($userid, $name, $val);
|
||||
}
|
||||
|
||||
# Mark the turing test for deletion
|
||||
if ($LJ::HUMAN_CHECK{create}) {
|
||||
LJ::Captcha::expire($capid, $anum, $userid);
|
||||
}
|
||||
|
||||
LJ::run_hooks("post_create", {
|
||||
'userid' => $userid,
|
||||
'user' => $user,
|
||||
'code' => $code,
|
||||
});
|
||||
}
|
||||
|
||||
# send welcome mail... unless they're underage
|
||||
unless ($is_underage) {
|
||||
my $aa = {};
|
||||
if ($userid) {
|
||||
$aa = LJ::register_authaction($userid, "validateemail", $email);
|
||||
}
|
||||
|
||||
my $body = BML::ml('email.newacct2.body', {
|
||||
"email" => $email,
|
||||
"regurl" => "$LJ::SITEROOT/confirm/$aa->{'aaid'}.$aa->{'authcode'}",
|
||||
"username" => $user,
|
||||
"sitename" => $LJ::SITENAME,
|
||||
"siteroot" => $LJ::SITEROOT,
|
||||
"admin_email" => $LJ::ADMIN_EMAIL,
|
||||
"bogus_email" => $LJ::BOGUS_EMAIL,
|
||||
});
|
||||
|
||||
LJ::send_mail({
|
||||
'to' => $email,
|
||||
'from' => $LJ::ADMIN_EMAIL,
|
||||
'fromname' => $LJ::SITENAME,
|
||||
'charset' => 'utf-8',
|
||||
'subject' => BML::ml('email.newacct.subject', {'sitename' => $LJ::SITENAME}),
|
||||
'body' => $body,
|
||||
});
|
||||
}
|
||||
|
||||
my $nu = LJ::load_userid($userid, "force");
|
||||
|
||||
# now flag as underage (and set O to mean was old or Y to mean was young)
|
||||
$nu->underage(1, $ofage ? 'O' : 'Y', 'account creation') if $is_underage;
|
||||
|
||||
if ($LJ::TOS_CHECK) {
|
||||
my $err = "";
|
||||
$nu->tosagree_set(\$err)
|
||||
or return LJ::bad_input($err);
|
||||
}
|
||||
|
||||
# record create information
|
||||
$nu->log_event('account_create', { remote => $remote });
|
||||
|
||||
$nu->make_login_session;
|
||||
|
||||
# local sites may want to override what happens at this point
|
||||
my $redirect = undef;
|
||||
my $stop_output;
|
||||
LJ::run_hooks("create.bml_postsession", {
|
||||
post => \%POST,
|
||||
u => $nu,
|
||||
redirect => \$redirect,
|
||||
ret => \$ret,
|
||||
stop_output => \$stop_output,
|
||||
});
|
||||
return BML::redirect($redirect) if $redirect;
|
||||
return $ret if $stop_output;
|
||||
|
||||
$ret = "<?h1 $ML{'.success.head'} h1?><?p ".BML::ml(".success.text1", {'email' => $email, 'username' => $user}) ." p?>";
|
||||
my $uri = LJ::journal_base($nu);
|
||||
$ret .= "<?p $ML{'.success.text2'} p?>\n";
|
||||
$ret .= "<?standout <font size='+1' face='arial'><b><a href='$uri'>$uri/</a></b></font> standout?>\n";
|
||||
$ret .= "<?p $ML{'.success.text3'} p?>\n";
|
||||
|
||||
$ret .= "<form method='get' action='$LJ::SITEROOT/editinfo.bml?authas=$user'>";
|
||||
$ret .= "<p align='center'>" . LJ::html_submit(undef, "$ML{'.success.btn.enterinfo'} →") . "</p>";
|
||||
$ret .= "</form>\n";
|
||||
|
||||
return $ret;
|
||||
|
||||
}
|
||||
|
||||
if ($mode eq "getinfo" || %errors)
|
||||
{
|
||||
my $ret;
|
||||
my $v;
|
||||
|
||||
if (%errors) {
|
||||
my @errors_order = ('code', 'username', 'email', 'password', 'agree_tos', 'captcha');
|
||||
my %errors_def;
|
||||
$errors_def{$_} = 1 for @errors_order;
|
||||
foreach my $key (keys %errors) { push @errors_order, $key unless $errors_def{$key}; }
|
||||
$ret .= "<?standout <strong>$ML{'.errors.label'}</strong><ul><li>";
|
||||
$ret .= join ("</li><li>", grep { $_ } map { $errors{$_} } @errors_order);
|
||||
$ret .= "</li></ul> standout?>";
|
||||
}
|
||||
|
||||
$ret .= "<?p $ML{'.create.text'} p?>" unless %errors;
|
||||
$ret .= "<form action=\"create.bml\" method=\"post\">\n";
|
||||
$ret .= LJ::html_hidden(mode => 'submit',
|
||||
code => $code,
|
||||
ssl => $FORM{'ssl'});
|
||||
|
||||
$ret .= "<ol>";
|
||||
|
||||
### username
|
||||
$v = LJ::ehtml($FORM{'user'});
|
||||
$ret .= "<li><div class='formitem'><div class='formitemName'>$ML{'.username.box.head'}</div>";
|
||||
$ret .= $error_msg->('username', '<p class="formitemFlag">', '</p>');
|
||||
$ret .= "<div class='formitemDesc'>" . BML::ml(".username.text", {'sitename' => $LJ::SITENAME}) . "</div>";
|
||||
$ret .= LJ::html_text({'name' => 'user', 'size' => 15, 'maxlength' => 15, 'value' => $v, raw => 'style="<?loginboxstyle?>"' });
|
||||
$ret .= "<br />" . BML::ml('.community', { aopts => "href='$LJ::SITEROOT/community/create.bml'" });
|
||||
$ret .= "<div class='formitemNote'>$ML{'.username.charsallowed'}</div>" if (!%errors || exists $errors{'username'});
|
||||
$ret .= "</div></li>";
|
||||
|
||||
### email address
|
||||
$v = LJ::ehtml($FORM{'email'});
|
||||
$ret .= "<li><div class='formitem'><div class='formitemName'>$ML{'.email.input.head'}</div>";
|
||||
$ret .= $error_msg->('email', '<p class="formitemFlag">', '</p>');
|
||||
$ret .= "<div class='formitemDesc'>" . BML::ml('.email.text3', {
|
||||
aopts => "target='_new' href='$LJ::SITEROOT/legal/privacy.bml'",
|
||||
}) . "</div>";
|
||||
$ret .= LJ::html_text({'name' => 'email', 'size' => 40, 'maxlength' => 50, 'value' => $v,});
|
||||
$ret .= "</div></li>";
|
||||
|
||||
$ret .= "<li><div class='formitem'><div class='formitemName'>$ML{'.password.input.head1'}</div>";
|
||||
$ret .= $error_msg->('password', '<p class="formitemFlag">', '</p>');
|
||||
$ret .= "<div class='formitemFlag'>$ML{'.password.secure'}</div>" if exists $errors{'password'};
|
||||
$ret .= "<div class='formitemDesc'>$ML{'.password.text'}</div>";
|
||||
my $pass_value = $errors{'password'} ? "" : $POST{'password1'};
|
||||
$ret .= LJ::html_text({'name' => 'password1', 'size' => 30, 'maxlength' => 31, 'type' => "password",
|
||||
value => $pass_value, });
|
||||
$ret .= "<div class='formitemDesc'>$ML{'.password.input.head2'}</div>";
|
||||
$ret .= LJ::html_text({'name' => 'password2', 'size' => 30, 'maxlength' => 31, 'type' => "password",
|
||||
value => $pass_value, });
|
||||
$ret .= "</div></li>";
|
||||
|
||||
if (@LJ::INITIAL_OPTIONAL_FRIENDS) {
|
||||
$ret .= "<li><div class='formitem'><div class='formitemName'>$ML{'.initialfriends.heading'}</div>";
|
||||
$ret .= "<div class='formitemDesc'>$ML{'.initialfriends'}</div>";
|
||||
$ret .= "<div>";
|
||||
foreach my $friend (@LJ::INITIAL_OPTIONAL_FRIENDS) {
|
||||
$ret .= LJ::html_check({'name' => "initial_optional_friend_$friend",
|
||||
'value' => 1,
|
||||
'selected' => $POST{"initial_optional_friend_$friend"},
|
||||
'id' => "optfriend_$friend",
|
||||
});
|
||||
$ret .= "<label for='optfriend_$friend'>" .
|
||||
LJ::ljuser($friend) . " " . $ML{".initial.friend.$friend"} .
|
||||
"</label><br />";
|
||||
}
|
||||
$ret .= "</div></div></li>";
|
||||
}
|
||||
|
||||
if ($LJ::COPPA_CHECK)
|
||||
{
|
||||
$ret .= "<li><div class='formitem'><div class='formitemName'>$ML{'.birthday.head'}</div>";
|
||||
$ret .= "<div class='formitemFlag'>$errors{'bday'}</div>" if exists $errors{'bday'};
|
||||
$ret .= "<div class='formitemDesc'>$ML{'.birthday.question'}</div><div>";
|
||||
$ret .= "<table><tr><td><span style='font-weight: bold;'>$ML{'.birthday.birthdate'}</span></td><td>";
|
||||
$ret .= LJ::html_datetime({ name => 'bday', notime => 1,
|
||||
default => sprintf("%04d-%02d-%02d", $POST{bday_yyyy}, $POST{bday_mm}, $POST{bday_dd}) });
|
||||
$ret .= "</td><td><span style='font-style: italic;'>$ML{'.birthday.required'}</span></td></tr>";
|
||||
$ret .= "</table></div></div></li>";
|
||||
}
|
||||
|
||||
LJ::run_hooks("create.bml_opts", {
|
||||
post => \%POST,
|
||||
get => \%GET,
|
||||
ret => \$ret,
|
||||
});
|
||||
|
||||
if ($LJ::TOS_CHECK)
|
||||
{
|
||||
$ret .= "<li><div class='formitem'><div class='formitemName'>$ML{'.tos.heading'}</div>";
|
||||
$ret .= LJ::tosagree_widget($POST{agree_tos}, $errors->{agree_tos});
|
||||
$ret .= "</div></li>";
|
||||
}
|
||||
|
||||
if ($LJ::ALLOW_CLUSTER_SELECT) {
|
||||
$ret .= "<li><div class='formitem'><div class='formitemName'>$ML{'.clusterselect.head'}</div>";
|
||||
$ret .= "<div class='formitemDesc'>$ML{'.clusterselect.text'}</div>";
|
||||
$ret .= LJ::html_select({ 'name' => 'cluster_id' },
|
||||
"0", "$BML{'.clusterselect.nocluster'}",
|
||||
map { $_, BML::ml(".clusterselect.clusternum", {'number' => $_}) } @LJ::CLUSTERS);
|
||||
|
||||
$ret .= "<div class='formitemNote'>$ML{'.clusterselect.cluster'}</div>";
|
||||
$ret .= "</div></li>";
|
||||
}
|
||||
|
||||
if ($LJ::HUMAN_CHECK{create}) {
|
||||
my ($captcha_chal, $captcha_sess);
|
||||
$captcha_chal = $POST{captcha_chal} || LJ::challenge_generate(900);
|
||||
$captcha_sess = LJ::get_challenge_attributes($captcha_chal);
|
||||
|
||||
my $answer = $POST{answer};
|
||||
undef $answer if $errors{'captcha'} || $wants_audio;
|
||||
|
||||
|
||||
my $try = 0;
|
||||
if ($form->{captcha_chal}) {
|
||||
my $dbcm = LJ::get_cluster_reader();
|
||||
$try = $dbcm->selectrow_array('SELECT trynum FROM captcha_session ' .
|
||||
'WHERE sess=?', undef, $captcha_sess);
|
||||
}
|
||||
|
||||
$ret .= "<li><div class='formitem'><div class='formitemName'>$ML{'.captcha.prove'}</div>";
|
||||
|
||||
# Visual challenge
|
||||
unless ( $wants_audio || $POST{audio_chal} ) {
|
||||
$ret .= "<div class='formitemDesc'>$ML{'.captcha.desc'}</div>";
|
||||
if ($capid && $anum) { # previously entered correctly
|
||||
$ret .= "<img src='/captcha/image.bml?capid=$capid&anum=$anum' width='175' height='35' />";
|
||||
} else {
|
||||
$ret .= "<img src='/captcha/image.bml?chal=$captcha_chal&try=$try' width='175' height='35' />";
|
||||
}
|
||||
}
|
||||
|
||||
# Audio challenge
|
||||
else {
|
||||
$ret .= "<div class='formitemDesc'>$ML{'.captcha.audiodesc'}</div>";
|
||||
if ($capid && $anum) {
|
||||
$ret .= "<a href='/captcha/audio.bml?capid=$capid&anum=$anum'>$ML{'.captcha.play'}</a>";
|
||||
} else {
|
||||
$ret .= "<a href='/captcha/audio.bml?chal=$captcha_chal&try=$try'>$ML{'.captcha.play'}</a>";
|
||||
}
|
||||
$ret .= LJ::html_hidden(audio_chal => 1);
|
||||
}
|
||||
|
||||
$ret .= "<br /><br />$ML{'.captcha.answer'}";
|
||||
$ret .= LJ::html_text({ name => 'answer', size => 15, value => $answer });
|
||||
$ret .= LJ::html_hidden(captcha_chal => $captcha_chal);
|
||||
$ret .= $error_msg->('captcha', '<p class="formitemFlag">', '</p>');
|
||||
$ret .= "</div></li>";
|
||||
}
|
||||
|
||||
$ret .= "</ol>";
|
||||
|
||||
$ret .= "<div style='width:600; text-align: center'>";
|
||||
$ret .= "<input type=\"submit\" value=\"$ML{'.btn.create'}\">";
|
||||
$ret .= "</div>";
|
||||
$ret .= "</form>";
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
return "$ML{'error.unknownmode'}: <b>$mode</b>";
|
||||
|
||||
_code?>
|
||||
<=body
|
||||
page?><?_c <LJDEP>
|
||||
link: htdocs/legal/privacy.bml
|
||||
post: htdocs/create.bml, htdocs/editinfo.bml
|
||||
file: htdocs/inc/account-codes
|
||||
hook: post_create
|
||||
</LJDEP> _c?>
|
||||
29
livejournal/htdocs/customize/advanced/index.bml
Executable file
@@ -0,0 +1,29 @@
|
||||
<?page
|
||||
title=>Advanced Customization
|
||||
body<=
|
||||
<?_code
|
||||
LJ::set_active_crumb('advcustomize');
|
||||
return;
|
||||
_code?>
|
||||
|
||||
<?h1 Disclaimer h1?>
|
||||
<?p
|
||||
Unless you're a programmer or web designer, most users should stay away from this area and use
|
||||
the <a href="/customize/">main customization area</a>, which is designed for anybody to use.
|
||||
p?>
|
||||
|
||||
<?h1 Documentation h1?>
|
||||
<?p Before you jump into tweaking/programming S2, you should understand how it works. p?>
|
||||
<ul>
|
||||
<li><a href="/doc/s2/">S2 Documentation</a> -- under construction, but some good content</li>
|
||||
<li><a href="layerbrowse.bml">Public Layers</a> -- system layers (good reference & place to learn)</li>
|
||||
</ul>
|
||||
|
||||
<?h1 Advanced Options h1?>
|
||||
<ul>
|
||||
<li><a href="layers.bml">Your Layers</a> -- create/manage your layers</li>
|
||||
<li><a href="styles.bml">Your Styles</a> -- create/manage your styles</li>
|
||||
</ul>
|
||||
|
||||
<=body
|
||||
page?>
|
||||
308
livejournal/htdocs/customize/advanced/layerbrowse.bml
Executable file
@@ -0,0 +1,308 @@
|
||||
<?_code # -*-bml-*-
|
||||
{
|
||||
use strict;
|
||||
use vars qw(%GET %POST $title $body);
|
||||
|
||||
LJ::set_active_crumb('layerbrowse');
|
||||
|
||||
# start of content
|
||||
$body = BML::ml("Backlink", {
|
||||
'link' => './',
|
||||
'text' => 'Advanced Customization',
|
||||
});
|
||||
|
||||
my $err = sub {
|
||||
$title = "Error";
|
||||
$body = shift;
|
||||
return;
|
||||
};
|
||||
|
||||
my $pub = LJ::S2::get_public_layers();
|
||||
|
||||
my $id;
|
||||
if ($GET{'id'} =~ /^\d+$/) { # numeric
|
||||
$id = $GET{'id'};
|
||||
} elsif ($GET{'id'}) { # redist_uniq
|
||||
$id = $pub->{$GET{'id'}}->{'s2lid'};
|
||||
}
|
||||
|
||||
my $dbr = LJ::get_db_reader();
|
||||
my $remote = LJ::get_remote();
|
||||
|
||||
# show the public layers
|
||||
unless ($id) {
|
||||
$title = "Public Layers";
|
||||
my %layerinfo;
|
||||
my @to_load = grep { /^\d+$/ } keys %$pub;
|
||||
LJ::S2::load_layer_info(\%layerinfo, \@to_load);
|
||||
|
||||
my $recurse = sub {
|
||||
my $self = shift;
|
||||
my $lid = shift; # layer id
|
||||
my $lay = $pub->{$lid};
|
||||
return unless $lay;
|
||||
|
||||
# set to true if the layer is not core and is not a layout
|
||||
my $is_child = $lay->{'type'} ne 'core' && $lay->{'type'} ne 'layout';
|
||||
|
||||
my $typedes = " ($lay->{'type'}" . (! $is_child ? ": <b>$lid</b>" : '') . ")";
|
||||
|
||||
# show link to detailed view
|
||||
$body .= "<li><a href='layerbrowse.bml?id=$lay->{'uniq'}'>" . LJ::ehtml($layerinfo{$lid}->{'name'});
|
||||
$body .= "</a>$typedes</li>";
|
||||
|
||||
# done unless there are children to recurse through
|
||||
return unless ! $is_child && $lay->{'children'};
|
||||
|
||||
# if we're not expanding these children, stop and show a link
|
||||
if ($lay->{'type'} eq 'layout' && $GET{'expand'} != $lid) {
|
||||
$body .= "<ul><li>[<a href='layerbrowse.bml?expand=$lid'>";
|
||||
$body .= scalar(@{$lay->{'children'}}) . " children...</a>]</li></ul>";
|
||||
return;
|
||||
}
|
||||
|
||||
# expand children
|
||||
$body .= "<ul>";
|
||||
foreach (@{$lay->{'children'}}) {
|
||||
$self->($self, $_);
|
||||
}
|
||||
$body .= "</ul>";
|
||||
|
||||
return;
|
||||
};
|
||||
|
||||
# iterate through core layers
|
||||
$body .= "<ul>";
|
||||
foreach (grep { $pub->{$_}->{'b2lid'} == 0 } grep { /^\d+$/ } keys %$pub) {
|
||||
$recurse->($recurse, $_); # start from the top
|
||||
}
|
||||
$body .= "</ul>";
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
### details on a specific layer ###
|
||||
|
||||
my $xlink = sub {
|
||||
my $r = shift;
|
||||
$$r =~ s/\[class\[(\w+)\]\]/<a href=\"\#class.$1\">$1<\/a>/g;
|
||||
$$r =~ s/\[method\[(.+?)\]\]/<a href=\"\#meth.$1\">$1<\/a>/g;
|
||||
$$r =~ s/\[function\[(.+?)\]\]/<a href=\"\#func.$1\">$1<\/a>/g;
|
||||
$$r =~ s/\[member\[(.+?)\]\]/<a href=\"\#member.$1\">$1<\/a>/g;
|
||||
};
|
||||
|
||||
# load layer info
|
||||
my $layer = defined $pub->{$id} ? $pub->{$id} : LJ::S2::load_layer($id);
|
||||
return $err->("The specified layer does not exist.")
|
||||
unless $layer;
|
||||
|
||||
my $layerinfo = {};
|
||||
LJ::S2::load_layer_info($layerinfo, [ $id ]);
|
||||
my $srcview = exists $layerinfo->{$id}->{'source_viewable'} ?
|
||||
$layerinfo->{$id}->{'source_viewable'} : undef;
|
||||
|
||||
# do they have access?
|
||||
my $isadmin = !defined $pub->{$id} && # public styles are pulled from the system
|
||||
(LJ::check_priv($remote, 'canview', 'styles') || # account, so we don't want to check privileges
|
||||
LJ::check_priv($remote, 'canview', '*')); # in case they're private styles
|
||||
return $err->("You are not authorized to view this layer.")
|
||||
unless defined $pub->{$id} || $srcview == 1 ||
|
||||
LJ::can_manage($remote, $layer->{'userid'}) ||
|
||||
$isadmin;
|
||||
|
||||
LJ::S2::load_layers($id);
|
||||
my $s2info = S2::get_layer_all($id);
|
||||
my $class = $s2info->{'class'} || {};
|
||||
|
||||
my $xlink_args = sub {
|
||||
my $r = shift;
|
||||
return unless
|
||||
$$r =~ /^(.+?\()(.*)\)$/;
|
||||
my ($new, @args) = ($1, split(/\s*\,\s*/, $2));
|
||||
foreach (@args) {
|
||||
s/^(\w+)/defined $class->{$1} ? "[class[$1]]" : $1/eg;
|
||||
}
|
||||
$new .= join(", ", @args) . ")";
|
||||
$$r = $new;
|
||||
$xlink->($r);
|
||||
};
|
||||
|
||||
$body .= "<br />";
|
||||
# link to layer list if this is a public layer, otherwise user's layer list
|
||||
if (defined $pub->{$id}) {
|
||||
$body .= BML::ml('backlink', { 'link' => 'layerbrowse.bml', 'text' => 'Public Layers' }) . "\n";
|
||||
} else {
|
||||
$body .= BML::ml('backlink', { 'link' => "layers.bml", 'text' => 'Your Layers' }) . "\n";
|
||||
$body .= BML::ml('actionlink', { 'link' => "<a href='layeredit.bml?id=$id'>Edit Layer</a>" }) . "\n";
|
||||
}
|
||||
|
||||
if ($layer->{'b2lid'}) {
|
||||
$body .= "[<a href=\"layerbrowse.bml?id=$layer->{'b2lid'}\">Parent Layer</a>]\n";
|
||||
}
|
||||
if (defined $pub->{$id} && (! defined $srcview || $srcview != 0) ||
|
||||
$srcview == 1 ||
|
||||
LJ::can_manage($remote, $layer->{'userid'}) ||
|
||||
$isadmin) {
|
||||
|
||||
$body .= "[<a href=\"layersource.bml?id=$id\">Download</a>]\n";
|
||||
$body .= "[<a href=\"layersource.bml?id=$id&fmt=html\">View as HTML</a>]\n";
|
||||
}
|
||||
|
||||
# layerinfo
|
||||
if (my $info = $s2info->{'info'}) {
|
||||
$body .= "<?h1 Layer Info h1?>";
|
||||
$body .= "<table style='margin-bottom: 10px' border='1' cellpadding='2'>";
|
||||
foreach my $k (sort keys %$info) {
|
||||
my ($ek, $ev) = map { LJ::ehtml($_) } ($k, $info->{$k});
|
||||
$title = $ev if $k eq "name";
|
||||
$body .= "<tr><td><b>$ek</b></td><td>$ev</td></tr>\n";
|
||||
}
|
||||
$body .= "</table>";
|
||||
}
|
||||
|
||||
# sets
|
||||
if (my $set = $s2info->{'set'}) {
|
||||
$body .= "<?h1 Properties Set h1?>";
|
||||
$body .= "<table style='margin-bottom: 10px' border='1' cellpadding='2'>";
|
||||
foreach my $k (sort keys %$set) {
|
||||
my $v = $set->{$k};
|
||||
if (ref $v eq "HASH") {
|
||||
if ($v->{'_type'} eq "Color") {
|
||||
$v = "<span style=\"border: 1px solid #000000; padding-left: 2em; background-color: $v->{'as_string'}\"> </span> <tt>$v->{'as_string'}</tt>";
|
||||
} else {
|
||||
$v = "[unknown object type]";
|
||||
}
|
||||
} elsif (ref $v eq "ARRAY") {
|
||||
$v = "<i>List:</i> (" . join(", ", map { LJ::ehtml($_) } @$v) . ")";
|
||||
} else {
|
||||
$v = LJ::ehtml($v);
|
||||
}
|
||||
$body .= "<tr><td><b>$k</b></td><td>$v</td></tr>\n";
|
||||
}
|
||||
$body .= "</table>";
|
||||
}
|
||||
|
||||
# global functions
|
||||
my $gb = $s2info->{'global'};
|
||||
if (ref $gb eq "HASH" && %$gb) {
|
||||
$body .= "<?h1 Global Functions h1?>";
|
||||
$body .= "<table style='margin-bottom: 10px' border='1' cellpadding='2'>";
|
||||
foreach my $fname (sort keys %$gb) {
|
||||
my $rt = $gb->{$fname}->{'returntype'};
|
||||
if (defined $class->{$rt}) {
|
||||
$rt = "[class[$rt]]";
|
||||
}
|
||||
$xlink->(\$rt);
|
||||
my $ds = LJ::ehtml($gb->{$fname}->{'docstring'});
|
||||
$xlink->(\$ds);
|
||||
|
||||
my $args = $gb->{$fname}->{'args'};
|
||||
$xlink_args->(\$args);
|
||||
|
||||
$body .= "<tr><td><nobr><a name='func.$fname'><tt>$args : $rt</tt></a></nobr></td><td>$ds</td></tr>";
|
||||
}
|
||||
$body .= "</table>";
|
||||
}
|
||||
|
||||
|
||||
if (%$class)
|
||||
{
|
||||
# class index
|
||||
$body .= "<?h1 Classes h1?>";
|
||||
$body .= "<table style='margin-bottom: 10px'><tr valign='top' align='left'>";
|
||||
$body .= "<td width='50%'>Alphabetical";
|
||||
$body .= "<ul>";
|
||||
foreach my $cname (sort { lc($a) cmp lc($b) } keys %$class) {
|
||||
$body .= "<li><a href='#class.$cname'><b>$cname</b></a></li>\n";
|
||||
}
|
||||
$body .= "</ul>";
|
||||
$body .= "</td>";
|
||||
$body .= "<td width='50%'>Hierarchical";
|
||||
my $dumpsub = sub {
|
||||
my $self = shift;
|
||||
my $parent = shift;
|
||||
$body .= "<li><a href='#class.$parent'><b>$parent</b></a></li>\n"
|
||||
if $parent;
|
||||
my $didul = 0;
|
||||
foreach my $cname (sort { lc($a) cmp lc($b) } keys %$class) {
|
||||
next unless $class->{$cname}->{'parent'} eq $parent;
|
||||
unless ($didul++) { $body .= "<ul>"; }
|
||||
$self->($self, $cname);
|
||||
}
|
||||
if ($didul) { $body .= "</ul>"; }
|
||||
};
|
||||
$dumpsub->($dumpsub, "");
|
||||
$body .= "</td></tr></table>";
|
||||
|
||||
# classes
|
||||
foreach my $cname (sort { lc($a) cmp lc($b) } keys %$class) {
|
||||
$body .= "<a name='class.$cname'><?h1 $cname Class h1?></a>";
|
||||
my $ds = LJ::ehtml($class->{$cname}->{'docstring'});
|
||||
if ($class->{$cname}->{'parent'}) {
|
||||
$ds = "Child class of [class[$class->{$cname}->{'parent'}]]. $ds";
|
||||
}
|
||||
if ($ds) {
|
||||
$xlink->(\$ds);
|
||||
$body .= "<?p $ds p?>";
|
||||
}
|
||||
|
||||
# build functions & methods
|
||||
my (%func, %var);
|
||||
my $add = sub {
|
||||
my ($self, $aname) = @_;
|
||||
foreach (keys %{$class->{$aname}->{'funcs'}}) {
|
||||
$func{$_} = $class->{$aname}->{'funcs'}->{$_};
|
||||
$func{$_}->{'_declclass'} = $aname;
|
||||
}
|
||||
foreach (keys %{$class->{$aname}->{'vars'}}) {
|
||||
$var{$_} = $class->{$aname}->{'vars'}->{$_};
|
||||
$var{$_}->{'_declclass'} = $aname;
|
||||
}
|
||||
|
||||
my $parent = $class->{$aname}->{'parent'};
|
||||
$self->($self, $parent) if $parent;
|
||||
};
|
||||
$add->($add, $cname);
|
||||
|
||||
$body .= "<table style='margin-bottom: 10px' border='1' cellpadding='2'><?h2 Members h2?>" if %var;
|
||||
foreach (sort keys %var) {
|
||||
my $type = $var{$_}->{'type'};
|
||||
$type =~ s/(\w+)/defined $class->{$1} ? "[class[$1]]" : $1/eg;
|
||||
$xlink->(\$type);
|
||||
|
||||
my $ds = LJ::ehtml($var{$_}->{'docstring'});
|
||||
$xlink->(\$ds);
|
||||
|
||||
if ($var{$_}->{'readonly'}) {
|
||||
$ds = "<i>(Read-only)</i> $ds";
|
||||
}
|
||||
|
||||
$body .= "<tr><td><nobr><a name='member.${cname}.$_'><tt>$type $_</tt></a></nobr></td><td>$ds</td></tr>";
|
||||
}
|
||||
$body .= "</table>" if %var;
|
||||
|
||||
$body .= "<table style='margin-bottom: 10px' border='1' cellpadding='2'><?h2 Methods h2?>" if %func;
|
||||
foreach (sort keys %func) {
|
||||
my $rt = $func{$_}->{'returntype'};
|
||||
if (defined $class->{$rt}) {
|
||||
$rt = "[class[$rt]]";
|
||||
}
|
||||
$xlink->(\$rt);
|
||||
my $ds = LJ::ehtml($func{$_}->{'docstring'});
|
||||
$xlink->(\$ds);
|
||||
|
||||
my $args = $_;
|
||||
$xlink_args->(\$args);
|
||||
|
||||
$body .= "<tr><td><nobr><a name='meth.${cname}::$_'><tt>$args : $rt</tt></a></nobr></td><td>$ds</td></tr>";
|
||||
}
|
||||
$body .= "</table>" if %func;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
_code?><?page title=><?_code return $title; _code?>
|
||||
body=><?_code return $body; _code?>
|
||||
page?>
|
||||
|
||||
139
livejournal/htdocs/customize/advanced/layeredit.bml
Executable file
@@ -0,0 +1,139 @@
|
||||
<style>
|
||||
em.error { font-weight: bold; color: red; font-style: normal; }
|
||||
textarea.s2code { width: 100%; display: block; clear: both; padding: 2px; }
|
||||
</style>
|
||||
<?_code # -*-bml-*-
|
||||
{
|
||||
use strict;
|
||||
use vars qw(%GET %POST);
|
||||
|
||||
# for error reporting
|
||||
my $err = sub {
|
||||
return "<title>Error</title>\n<h2>Error</h2>" . shift;
|
||||
};
|
||||
|
||||
# we need a valid id
|
||||
my $id = $GET{'id'} if $GET{'id'} =~ /^\d+$/;
|
||||
return $err->("You have not specified a layer to edit.")
|
||||
unless $id;
|
||||
|
||||
# authenticate user;
|
||||
my $remote = LJ::get_remote();
|
||||
return $err->("You must be logged in to edit layers.")
|
||||
unless $remote;
|
||||
|
||||
# load layer
|
||||
my $lay = LJ::S2::load_layer($id);
|
||||
return $err->("The specified layer does not exist.")
|
||||
unless $lay;
|
||||
|
||||
# if the b2lid of this layer has been remapped to a new layerid
|
||||
# then update the b2lid mapping for this layer
|
||||
my $b2lid = $lay->{b2lid};
|
||||
if ($b2lid && $LJ::S2LID_REMAP{$b2lid}) {
|
||||
LJ::S2::b2lid_remap($remote, $id, $b2lid);
|
||||
$lay->{b2lid} = $LJ::S2LID_REMAP{$b2lid};
|
||||
}
|
||||
|
||||
# is authorized admin for this layer?
|
||||
return $err->('You are not authorized to edit this layer.')
|
||||
unless LJ::can_manage($remote, $lay->{'userid'});
|
||||
|
||||
# get u of user they are acting as
|
||||
my $u = $lay->{'userid'} == $remote->{'userid'} ? $remote : LJ::load_userid($lay->{'userid'});
|
||||
|
||||
# check priv and ownership
|
||||
return $err->("You are not authorized to edit styles.")
|
||||
unless LJ::get_cap($u, "s2styles");
|
||||
|
||||
# at this point, they are authorized, allow viewing & editing
|
||||
my $ret;
|
||||
$ret .= "<form method='post' action='layeredit.bml?id=$id'>\n";
|
||||
$ret .= BML::ml('backlink', { 'text' => 'Your Layers', 'link' => "layers.bml?authas=$u->{'user'}" }) . "\n";
|
||||
|
||||
# get s2 code from db - use writer so we know it's up-to-date
|
||||
my $dbh = LJ::get_db_writer();
|
||||
my $s2code = $POST{'s2code'};
|
||||
$s2code = $dbh->selectrow_array("SELECT s2code FROM s2source WHERE s2lid=?",
|
||||
undef, $lay->{'s2lid'}) unless $s2code;
|
||||
|
||||
# we tried to compile something
|
||||
if ($POST{'action'} eq "compile") {
|
||||
$ret .= "<div style='margin: 20px 0 20px 40px'>\n";
|
||||
$ret .= "<b>S2 Compiler Output</b> <em>at " . scalar(localtime) . "</em><br />\n";
|
||||
|
||||
my $error;
|
||||
$POST{'s2code'} =~ s/\r//g; # just in case
|
||||
unless (LJ::S2::layer_compile($lay, \$error, { 's2ref' => \$POST{'s2code'} })) {
|
||||
|
||||
$error =~ s/LJ::S2,.+//s;
|
||||
$error =~ s!, .+?(src/s2|cgi-bin)/!, !g;
|
||||
|
||||
$ret .= "Error compiling layer:\n<pre style=\"border-left: 1px red solid\">$error</pre>";
|
||||
|
||||
# display error with helpful context
|
||||
if ($error =~ /^compile error: line (\d+)/i) {
|
||||
my $errline = $1;
|
||||
my $kill = $errline - 5 < 0 ? 0 : $errline - 5;
|
||||
my $prehilite = $errline - 1 > 4 ? 4: $errline - 1;
|
||||
my $snippet = $s2code;
|
||||
|
||||
# make sure there's a newlilne at the end
|
||||
chomp $snippet;
|
||||
$snippet .= "\n";
|
||||
|
||||
# and now, fun with regular expressions
|
||||
my $ct = 0;
|
||||
$snippet =~ s!(.*?)\n!sprintf("%3d", ++$ct) . ": " .
|
||||
$1 . "\n"!ge; # add line breaks and numbering
|
||||
$snippet = LJ::ehtml($snippet);
|
||||
$snippet =~ s!^((?:.*?\n){$kill,$kill}) # kill before relevant lines
|
||||
((?:.*?\n){$prehilite,$prehilite}) # capture context before error
|
||||
(.*?\n){0,1} # capture error
|
||||
((?:.*?\n){0,4}) # capture context after error
|
||||
.* # kill after relevant lines
|
||||
!$2<em class='error'>$3</em>$4!sx;
|
||||
|
||||
$ret .= "<b>Context</b><br /><pre>$snippet</pre>\n";
|
||||
}
|
||||
|
||||
} else {
|
||||
$ret .= "No errors\n";
|
||||
}
|
||||
$ret .= "</div>\n\n";
|
||||
}
|
||||
|
||||
$ret .= LJ::html_hidden("action", "compile") . "\n";
|
||||
$ret .= "<p>" . LJ::html_submit('submit', 'Compile', {
|
||||
'style' => 'float: right; margin-bottom: 2px',
|
||||
'accesskey' => 'c',
|
||||
'title' => 'alt-C: compile',
|
||||
} ) . "\n";
|
||||
$ret .= "<b>Edit layer source</b>\n";
|
||||
$ret .= LJ::html_textarea({ 'name' => 's2code', 'class' => 's2code', 'wrap' => 'off',
|
||||
'cols' => '50', 'rows' => '40', 'value' => $s2code }) . "\n";
|
||||
$ret .= LJ::html_submit('submit', 'Compile') . "\n";
|
||||
$ret .= "</p></form>\n";
|
||||
|
||||
# load layer info
|
||||
my $layinf = {};
|
||||
LJ::S2::load_layer_info($layinf, [ $id ]);
|
||||
|
||||
# find a title to display on this page
|
||||
my $type = $layinf->{$id}->{'type'};
|
||||
my $name = $layinf->{$id}->{'name'};
|
||||
|
||||
# find name of parent layer if this is a child layer
|
||||
if (! $name && $type =~ /^(user|theme|i18n)$/) {
|
||||
my $par = $lay->{'b2lid'} + 0;
|
||||
LJ::S2::load_layer_info($layinf, [$par]);
|
||||
$name = $layinf->{$par}->{'name'};
|
||||
}
|
||||
|
||||
# Only use the layer name if there is one and it's more than just whitespace
|
||||
my $title = "[$type] ";
|
||||
$title .= $name && $name =~ /[^\s]/ ? "$name [\#$id]" : "Layer \#$id";
|
||||
|
||||
return "<title>" . LJ::ehtml($title) . " - Edit</title>\n" . $ret;
|
||||
}
|
||||
_code?>
|
||||
260
livejournal/htdocs/customize/advanced/layers.bml
Executable file
@@ -0,0 +1,260 @@
|
||||
<?_code # -*-bml-*-
|
||||
{
|
||||
use strict;
|
||||
use vars qw(%GET %POST $title $body);
|
||||
|
||||
LJ::set_active_crumb('yourlayers');
|
||||
|
||||
my $remote;
|
||||
|
||||
# authas switcher form
|
||||
my $authasform = sub {
|
||||
$body .= "<form method='get' action='styles.bml'>\n";
|
||||
$body .= LJ::make_authas_select($remote, { 'authas' => $GET{'authas'} }) . "\n";
|
||||
$body .= "</form>\n\n";
|
||||
};
|
||||
|
||||
# used for error messages
|
||||
my $err = sub {
|
||||
$title = "Error";
|
||||
$body = '';
|
||||
$authasform->() if $remote;
|
||||
$body .= "<?p $_[0] p?>";
|
||||
return;
|
||||
};
|
||||
|
||||
# id is optional
|
||||
my $id = $POST{'id'} if $POST{'id'} =~ /^\d+$/;
|
||||
|
||||
# this catches core_hidden if it's set
|
||||
$POST{'parid'} ||= $POST{'parid_hidden'};
|
||||
|
||||
# authenticate user
|
||||
$remote = LJ::get_remote();
|
||||
return $err->('You must be logged in to view your layers.')
|
||||
unless $remote;
|
||||
|
||||
my $authas = $GET{'authas'} || $remote->{'user'};
|
||||
my $u = LJ::get_authas_user($authas);
|
||||
|
||||
# if we don't have a u, maybe they're an admin and can view stuff anyway?
|
||||
my $noactions = 0;
|
||||
if ($GET{user} && (LJ::check_priv($remote, 'canview', 'styles') ||
|
||||
LJ::check_priv($remote, 'canview', '*'))) {
|
||||
return $err->('This privilege cannot be used on the system account.')
|
||||
if $GET{user} eq 'system';
|
||||
$u = LJ::load_user($GET{user});
|
||||
$noactions = 1; # don't let admins change anything
|
||||
}
|
||||
return $err->('You could not be authenticated as the specified user.')
|
||||
unless $u;
|
||||
|
||||
# load user and public layers
|
||||
my $pub = LJ::S2::get_public_layers();
|
||||
my $ulay = LJ::S2::get_layers_of_user($u);
|
||||
|
||||
my $has_priv = LJ::get_cap($u, 's2styles');
|
||||
return $err->($remote->{user} eq $u->{user} ?
|
||||
'Your account type does not allow advanced customization.' :
|
||||
'The selected user\'s account type does not allow advanced customization.' )
|
||||
unless $has_priv;
|
||||
|
||||
# start of output
|
||||
$title = "Your Layers";
|
||||
$body .= BML::ml("backlink", {
|
||||
'link' => './',
|
||||
'text' => 'Advanced Customization',
|
||||
}) . "\n";
|
||||
$body .= BML::ml("actionlink", {
|
||||
'link' => "<a href='styles.bml?authas=$authas'>Your Styles</a>",
|
||||
}) . "\n";
|
||||
|
||||
|
||||
### perform actions ###
|
||||
|
||||
# create
|
||||
if ($POST{'action:create'} && !$noactions) {
|
||||
return $err->("You have reached your maximum number of allowed layers")
|
||||
if keys %$ulay >= LJ::get_cap($u, 's2layersmax');
|
||||
|
||||
my $err_badparid = "No/bogus parent layer ID given (for layouts and core languages, use core parent ID; for themes and layout languages, use layout ID)";
|
||||
my $type = $POST{'type'} or return $err->("No layer type selected.");
|
||||
my $parid = $POST{'parid'}+0 or return $err->($err_badparid);
|
||||
return $err->("Invalid layer type") unless $type =~ /^layout|theme|user|i18nc?$/;
|
||||
my $parent_type = ($type eq "theme" || $type eq "i18n" || $type eq "user") ? "layout" : "core";
|
||||
|
||||
# parent ID is public layer
|
||||
if ($pub->{$parid}) {
|
||||
# of the wrong type
|
||||
return $err->($err_badparid) if $pub->{$parid}->{'type'} ne $parent_type;
|
||||
|
||||
# parent ID is user layer, or completely invalid
|
||||
} else {
|
||||
return $err->($err_badparid) if
|
||||
! $ulay->{$parid} || $ulay->{$parid}->{'type'} != $parent_type;
|
||||
}
|
||||
|
||||
my $id = LJ::S2::create_layer($u, $parid, $type);
|
||||
return $err->("Error creating layer") unless $id;
|
||||
|
||||
my $lay = {
|
||||
'userid' => $u->{'userid'},
|
||||
'type' => $type,
|
||||
'b2lid' => $parid,
|
||||
's2lid' => $id,
|
||||
};
|
||||
|
||||
# help user out a bit, creating the beginning of their layer.
|
||||
my $s2 = "layerinfo \"type\" = \"$type\";\n";
|
||||
$s2 .= "layerinfo \"name\" = \"\";\n\n";
|
||||
my $error;
|
||||
unless (LJ::S2::layer_compile($lay, \$error, { 's2ref' => \$s2 })) {
|
||||
return $err->("Error setting up & compiling layer: $error");
|
||||
}
|
||||
|
||||
# redirect so they can't refresh and create a new layer again
|
||||
return BML::redirect("layers.bml?authas=$authas");
|
||||
}
|
||||
|
||||
# delete
|
||||
if ($POST{'action:del'} && !$noactions) {
|
||||
my $id = $POST{'id'}+0;
|
||||
my $lay = LJ::S2::load_layer($id);
|
||||
return $err->("The specified layer does not exist")
|
||||
unless $lay;
|
||||
|
||||
return $err->("You do not own the specified layer")
|
||||
unless $lay->{'userid'} == $u->{'userid'};
|
||||
|
||||
unless ($POST{'confirm'}) {
|
||||
my $layerinfo = {};
|
||||
LJ::S2::load_layer_info($layerinfo, [ $id ]);
|
||||
my $name = $layerinfo->{$id}->{'name'} ? "'$layerinfo->{$id}->{'name'}'" : "#$id";
|
||||
$name = LJ::ehtml($name);
|
||||
|
||||
$title = "Deleting layer $name";
|
||||
$body .= "<br /> ";
|
||||
$body .= BML::ml("backlink", {
|
||||
'link' => "layers.bml?authas=$authas",
|
||||
'text' => 'Your Layers',
|
||||
}) . "\n";
|
||||
$body .= "<form method='post' action='layers.bml?authas=$authas'>";
|
||||
$body .= LJ::html_hidden('action:del', '1', 'id', $id);
|
||||
|
||||
$body .= "Are you sure you want to delete $lay->{'type'} layer $name?";
|
||||
$body .= "<p>" . LJ::html_submit('confirm', 'Delete') . "</p>\n";;
|
||||
$body .= "</form>\n";
|
||||
return;
|
||||
}
|
||||
|
||||
LJ::S2::delete_layer($u, $id);
|
||||
return BML::redirect("layers.bml?authas=$authas");
|
||||
}
|
||||
|
||||
# authas switcher form
|
||||
unless ($noactions) {
|
||||
$authasform->();
|
||||
}
|
||||
|
||||
# show list of layers
|
||||
$body .= "<?h1 Your Layers h1?>\n";
|
||||
if (%$ulay) {
|
||||
$body .= "<table style='margin-bottom: 10px' cellpadding='3' border='1'>\n";
|
||||
$body .= "<tr><td><b>LayerID</b></td><td><b>Type</b></td><td><b>Name</b></td><td><b>Actions</b></td></tr>\n";
|
||||
my $lastbase = 0;
|
||||
foreach my $lid (sort { $ulay->{$a}->{'b2lid'} <=> $ulay->{$b}->{'b2lid'} || $a <=> $b }
|
||||
keys %$ulay)
|
||||
{
|
||||
my $bid = $ulay->{$lid}->{'b2lid'};
|
||||
if ($bid != $lastbase) {
|
||||
$lastbase = $bid;
|
||||
my $parlay = $ulay->{$bid} || $pub->{$bid};
|
||||
my $pname = LJ::ehtml($parlay->{'name'});
|
||||
$body .= "<tr><td colspan='4'><small>Child of <a href='layerbrowse.bml?id=$bid'>layer $bid</a>: $pname</small></td></tr>\n";
|
||||
}
|
||||
my $lay = $ulay->{$lid};
|
||||
my $name = LJ::ehtml($lay->{'name'}) || "<i>(none)</i>";
|
||||
$body .= "<tr><td><a href='layerbrowse.bml?id=$lid'>$lid</a></td><td>$lay->{'type'}</td><td>$name</td><td>";
|
||||
$body .= "<form method='post' style='display:inline' action='layeredit.bml?id=$lid'>";
|
||||
$body .= LJ::html_submit('action:edit', 'Edit...', { disabled => $noactions });
|
||||
$body .= "</form>";
|
||||
|
||||
$body .= "<form method='post' style='display:inline' action='layers.bml?authas=$authas'>";
|
||||
$body .= LJ::html_hidden('id', $lid);
|
||||
$body .= LJ::html_submit('action:del', 'Delete...', { disabled => $noactions });
|
||||
$body .= "</form>";
|
||||
$body .= "</td></tr>\n"
|
||||
}
|
||||
$body .= "</table>\n\n";
|
||||
} else {
|
||||
$body .= "<?p <i>None</i> p?>\n\n";
|
||||
}
|
||||
|
||||
# jump out if we're just viewing
|
||||
return if $noactions;
|
||||
|
||||
# create layer
|
||||
$body .= "<?h1 Create Layer h1?>\n";
|
||||
|
||||
$body .= "<div style='margin-top: 10px;'>\n";
|
||||
$body .= "<?h2 Create top-level layer h2?>\n";
|
||||
$body .= "<form method='post' action='layers.bml?authas=$authas'>\n";
|
||||
|
||||
$body .= "Type: " . LJ::html_select({ 'name' => 'type' },
|
||||
"" => "",
|
||||
"layout" => "Layout",
|
||||
"i18nc" => "Language",
|
||||
) . "\n";
|
||||
|
||||
my @corelayers = map { $_, $pub->{$_}->{'majorversion'} }
|
||||
sort { $pub->{$b}->{'majorversion'} <=> $pub->{$a}->{'majorversion'} }
|
||||
grep { $pub->{$_}->{'b2lid'} == 0 && $pub->{$_}->{'type'} eq 'core' && /^\d+$/}
|
||||
keys %$pub;
|
||||
$body .= " Core Version: " . LJ::html_select({ 'name' => 'parid',
|
||||
'selected' => $corelayers[0],
|
||||
'disabled' => @corelayers > 2 ? 0: 1 },
|
||||
@corelayers ) . "\n";
|
||||
|
||||
# store value in hidden to later be copied to 'parid' if necessary
|
||||
# defaults to $corelayers[0] which should be the highest numbered core
|
||||
$body .= LJ::html_hidden("parid_hidden", $POST{'parid'} || $corelayers[0]) . "\n";
|
||||
$body .= LJ::html_submit("action:create", "Create") . "\n";
|
||||
$body .= "</form>\n";
|
||||
$body .= "</div>\n\n";
|
||||
|
||||
$body .= "<?h2 Create layout-specific layer h2?>\n";
|
||||
$body .= "<form method='post' action='layers.bml?authas=$authas'>\n";
|
||||
|
||||
$body .= "Type: " . LJ::html_select({ 'name' => 'type' },
|
||||
"" => "",
|
||||
"theme" => "Theme",
|
||||
"i18n" => "Language",
|
||||
"user" => "User"
|
||||
) . "\n";
|
||||
|
||||
my @layouts = ('', '');
|
||||
push @layouts, map { $_, $pub->{$_}->{'name'} }
|
||||
sort { $pub->{$a}->{'name'} cmp $pub->{$b}->{'name'} || $a <=> $b}
|
||||
grep { $pub->{$_}->{'type'} eq 'layout' && /^\d+$/}
|
||||
keys %$pub;
|
||||
if (%$ulay) {
|
||||
my @ulayouts = ();
|
||||
push @ulayouts, map { $_, "$ulay->{$_}->{'name'} (#$_)" }
|
||||
sort { $ulay->{$a}->{'name'} cmp $ulay->{$b}->{'name'} || $a <=> $b}
|
||||
grep { $ulay->{$_}->{'type'} eq 'layout' }
|
||||
keys %$ulay;
|
||||
push @layouts, ('', '---', @ulayouts) if @ulayouts;
|
||||
}
|
||||
|
||||
$body .= "Layout: " . LJ::html_select({ 'name' => 'parid' }, @layouts) . "\n";
|
||||
|
||||
$body .= LJ::html_submit("action:create", "Create") . "\n";
|
||||
$body .= "</form>\n\n";
|
||||
|
||||
return;
|
||||
}
|
||||
_code?><?page
|
||||
title=><?_code return $title; _code?>
|
||||
body=><?_code return $body; _code?>
|
||||
page?>
|
||||
|
||||
78
livejournal/htdocs/customize/advanced/layersource.bml
Executable file
@@ -0,0 +1,78 @@
|
||||
<?_code # -*-bml-*-
|
||||
{
|
||||
use strict;
|
||||
use vars qw(%GET);
|
||||
|
||||
my $pub = LJ::S2::get_public_layers();
|
||||
|
||||
# for error reporting
|
||||
my $err = sub {
|
||||
return "<h2>Error</h2>" . shift;
|
||||
};
|
||||
|
||||
my $dbr = LJ::get_db_reader();
|
||||
my $remote = LJ::get_remote();
|
||||
|
||||
my $id = $GET{'id'};
|
||||
return BML::redirect('layerbrowse.bml') unless $id =~ /^\d+$/;
|
||||
|
||||
my $lay = defined $pub->{$id} ? $pub->{$id} : LJ::S2::load_layer($id);
|
||||
return $err->("The specified layer does not exist.")
|
||||
unless $lay;
|
||||
|
||||
my $layerinfo = {};
|
||||
LJ::S2::load_layer_info($layerinfo, [ $id ]);
|
||||
my $srcview = exists $layerinfo->{$id}->{'source_viewable'} ?
|
||||
$layerinfo->{$id}->{'source_viewable'} : undef;
|
||||
|
||||
# authorized to view this layer?
|
||||
my $isadmin = !defined $pub->{$id} && # public styles are pulled from the system
|
||||
(LJ::check_priv($remote, 'canview', 'styles') || # account, so we don't want to check privileges
|
||||
LJ::check_priv($remote, 'canview', '*')); # in case they're private styles
|
||||
return $err->("You are not authorized to view this layer.")
|
||||
unless defined $pub->{$id} && (! defined $srcview || $srcview != 0) ||
|
||||
$srcview == 1 ||
|
||||
LJ::can_manage($remote, $lay->{'userid'}) ||
|
||||
$isadmin;
|
||||
|
||||
my $s2code = $dbr->selectrow_array("SELECT s2code FROM s2source WHERE s2lid=?", undef, $id);
|
||||
|
||||
# get html version of the code?
|
||||
if ($GET{'fmt'} eq "html") {
|
||||
my $html;
|
||||
my ($md5, $save_cache);
|
||||
if ($pub->{$id}) {
|
||||
# let's see if we have it cached
|
||||
$md5 = Digest::MD5::md5_hex($s2code);
|
||||
my $cache = $dbr->selectrow_array("SELECT value FROM blobcache WHERE bckey='s2html-$id'");
|
||||
if ($cache =~ s/^\[$md5\]//) {
|
||||
$html = $cache;
|
||||
} else {
|
||||
$save_cache = 1;
|
||||
}
|
||||
}
|
||||
|
||||
unless ($html) {
|
||||
my $cr = new S2::Compiler;
|
||||
$cr->compile_source({
|
||||
'source' => \$s2code,
|
||||
'output' => \$html,
|
||||
'format' => "html",
|
||||
'type' => $pub->{$id}->{'type'},
|
||||
});
|
||||
}
|
||||
|
||||
if ($save_cache) {
|
||||
my $dbh = LJ::get_db_writer();
|
||||
$dbh->do("REPLACE INTO blobcache (bckey, dateupdate, value) VALUES (?,NOW(),?)",
|
||||
undef, "s2html-$id", "[$md5]$html");
|
||||
}
|
||||
return $html;
|
||||
}
|
||||
|
||||
# return text version
|
||||
BML::set_content_type("text/plain");
|
||||
BML::noparse();
|
||||
return $s2code;
|
||||
}
|
||||
_code?>
|
||||
465
livejournal/htdocs/customize/advanced/styles.bml
Executable file
@@ -0,0 +1,465 @@
|
||||
<?_code # -*-bml-*-
|
||||
{
|
||||
use strict;
|
||||
use vars qw(%GET %POST $title $body);
|
||||
|
||||
LJ::set_active_crumb('yourstyles');
|
||||
|
||||
my $remote;
|
||||
|
||||
# authas switcher form
|
||||
my $authasform = sub {
|
||||
$body .= "<form method='get' action='styles.bml'>\n";
|
||||
$body .= LJ::make_authas_select($remote, { 'authas' => $GET{'authas'} }) . "\n";
|
||||
$body .= "</form>\n\n";
|
||||
};
|
||||
|
||||
# used for error messages
|
||||
my $err = sub {
|
||||
$title = "Error";
|
||||
$body = '';
|
||||
$authasform->() if $remote;
|
||||
$body .= "<?p $_[0] p?>";
|
||||
return;
|
||||
};
|
||||
|
||||
# authenticate user
|
||||
$remote = LJ::get_remote();
|
||||
return $err->('You must be logged in to view your styles.')
|
||||
unless $remote;
|
||||
|
||||
my $authas = $GET{'authas'} || $remote->{'user'};
|
||||
my $u = LJ::get_authas_user($authas);
|
||||
return $err->('You could not be authenticated as the specified user.')
|
||||
unless $u;
|
||||
|
||||
return $err->($remote->{user} eq $u->{user} ?
|
||||
'Your account type does not allow advanced customization.' :
|
||||
'The selected user\'s account type does not allow advanced customization.' )
|
||||
unless LJ::get_cap($u, 's2styles');
|
||||
|
||||
# extra arguments for get requests
|
||||
my $getextra = $authas ne $remote->{'user'} ? "?authas=$authas" : '';
|
||||
my $getextra_amp = "&authas=$authas" if $getextra;
|
||||
|
||||
# style id to edit, if we have one
|
||||
# if we have this we're assumed to be in 'edit' mode
|
||||
my $id = $GET{'id'}+0;
|
||||
|
||||
my $dbh = LJ::get_db_writer();
|
||||
|
||||
# variables declared here, but only filled in if $id
|
||||
my ($core, $layout); # scalars
|
||||
my ($pub, $ulay, $style); # hashrefs
|
||||
|
||||
# start of output
|
||||
$title = "Styles";
|
||||
$body = BML::ml("backlink", {
|
||||
'link' => './',
|
||||
'text' => 'Advanced Customization',
|
||||
}) . "\n";
|
||||
$body .= BML::ml("actionlink", {
|
||||
'link' => "<a href='layers.bml$getextra'>Your Layers</a>",
|
||||
}) . "\n";
|
||||
|
||||
# edit mode
|
||||
if ($id) {
|
||||
|
||||
# load style
|
||||
$style = LJ::S2::load_style($id);
|
||||
return $err->('Style not found') unless $style;
|
||||
|
||||
# check that they own the style
|
||||
return $err->("You do not own this style.")
|
||||
unless $style->{'userid'} == $u->{'userid'};
|
||||
|
||||
# use selected style
|
||||
if ($POST{'action:usestyle'}) {
|
||||
|
||||
# save to db and update user object
|
||||
LJ::set_userprop($u, "stylesys", '2');
|
||||
LJ::set_userprop($u, "s2_style", $id);
|
||||
return BML::redirect("styles.bml$getextra");
|
||||
}
|
||||
|
||||
# get public layers
|
||||
$pub = LJ::S2::get_public_layers();
|
||||
|
||||
# get user layers
|
||||
$ulay = LJ::S2::get_layers_of_user($u);
|
||||
|
||||
# find effective layerids being used
|
||||
my %eff_layer = ();
|
||||
my @other_layers = ();
|
||||
foreach (qw(i18nc layout theme i18n user)) {
|
||||
my $lid = $POST{$_} eq "_other" ? $POST{"other_$_"} : $POST{$_};
|
||||
next unless $lid;
|
||||
$eff_layer{$_} = $lid;
|
||||
|
||||
unless ($ulay->{$eff_layer{$_}} || $pub->{$eff_layer{$_}}) {
|
||||
push @other_layers, $lid;
|
||||
}
|
||||
}
|
||||
|
||||
# core lid (can't use user core layer)
|
||||
$POST{'core'} ||= $POST{'core_hidden'};
|
||||
$core = defined $POST{'core'} ? $POST{'core'} : $style->{'layer'}->{'core'};
|
||||
unless ($core) { # default to highest numbered core
|
||||
map { $core = $_ if $pub->{$_}->{'type'} eq 'core' && /^\d+$/ &&
|
||||
$pub->{$_}->{'majorversion'} > $pub->{$core}->{'majorversion'} } keys %$pub;
|
||||
|
||||
# update in POST to keep things in sync
|
||||
$POST{'core'} = $core;
|
||||
}
|
||||
|
||||
# layout lid
|
||||
$layout = $POST{'action:change'} ? $eff_layer{'layout'} : $style->{'layer'}->{'layout'};
|
||||
|
||||
# if we're changing core, clear everything
|
||||
if ($POST{'core'} && $style->{'layer'}->{'core'} &&
|
||||
$POST{'core'} != $style->{'layer'}->{'core'}) {
|
||||
foreach (qw(i18nc layout theme i18n user)) {
|
||||
delete $eff_layer{$_};
|
||||
}
|
||||
undef $layout;
|
||||
}
|
||||
|
||||
# if we're changing layout, clear everything below
|
||||
if ($eff_layer{'layout'} && $style->{'layer'}->{'layout'} &&
|
||||
$eff_layer{'layout'} != $style->{'layer'}->{'layout'}) {
|
||||
foreach (qw(theme i18n user)) {
|
||||
delete $eff_layer{$_};
|
||||
}
|
||||
}
|
||||
|
||||
# set up start of output
|
||||
$title = "Edit Style";
|
||||
$body .= "<br />" . BML::ml('backlink', { 'text' => 'Your Styles', 'link' => "styles.bml$getextra" }) . "\n";
|
||||
|
||||
### process edit actions
|
||||
|
||||
# delete
|
||||
if ($POST{'action:delete'}) {
|
||||
LJ::S2::delete_user_style($u, $id);
|
||||
undef $id; # don't show form below
|
||||
return BML::redirect("styles.bml$getextra");
|
||||
}
|
||||
|
||||
# save changes
|
||||
if ($POST{'action:change'} || $POST{'action:savechanges'}) {
|
||||
|
||||
# are they renaming their style?
|
||||
if ($POST{'stylename'} && $style->{'name'} &&
|
||||
$POST{'stylename'} ne $style->{'name'}) {
|
||||
|
||||
# update db
|
||||
my $styleid = $style->{'styleid'};
|
||||
$dbh->do("UPDATE s2styles SET name=? WHERE styleid=? AND userid=?",
|
||||
undef, $POST{'stylename'}, $styleid, $u->{'userid'});
|
||||
LJ::MemCache::delete([$styleid, "s2s:$styleid"]);
|
||||
|
||||
# update style object
|
||||
$style->{'name'} = $POST{'stylename'};
|
||||
}
|
||||
|
||||
# load layer info of any "other" layers
|
||||
my %other_info = ();
|
||||
if (@other_layers) {
|
||||
LJ::S2::load_layer_info(\%other_info, \@other_layers);
|
||||
foreach (@other_layers) {
|
||||
return $err->("Layer not found: $_") unless exists $other_info{$_};
|
||||
return $err->("Layer not public: $_") unless $other_info{$_}->{'is_public'};
|
||||
}
|
||||
}
|
||||
|
||||
# error check layer modifications
|
||||
my $get_layername = sub {
|
||||
my $lid = shift;
|
||||
|
||||
my $name;
|
||||
$name = $pub->{$lid}->{'name'} if $pub->{$lid};
|
||||
$name ||= $ulay->{$lid}->{'name'} if $ulay->{$lid};
|
||||
$name ||= "#$lid";
|
||||
|
||||
return $name;
|
||||
};
|
||||
|
||||
# check layer hierarchy
|
||||
my $error_check = sub {
|
||||
my ($type, $parentid) = @_;
|
||||
|
||||
my $lid = $eff_layer{$type};
|
||||
next if ! $lid;
|
||||
|
||||
my $layer = $ulay->{$lid} || $pub->{$lid} || LJ::S2::load_layer($lid);
|
||||
my $parentname = $get_layername->($parentid);
|
||||
my $layername = $get_layername->($lid);
|
||||
|
||||
# is valid layer type?
|
||||
return "Invalid layer type: <i>$layername</i> is not a $type layer"
|
||||
if $layer->{'type'} ne $type;
|
||||
|
||||
# is a child?
|
||||
return "Layer hierarchy mismatch: <i>$layername</i> is not a child $type layer of <i>$parentname</i>"
|
||||
unless $layer->{'b2lid'} == $parentid;
|
||||
|
||||
return undef;
|
||||
};
|
||||
|
||||
# check child layers of core
|
||||
foreach my $type (qw(i18nc layout)) {
|
||||
my $errmsg = $error_check->($type, $core);
|
||||
return $err->($errmsg) if $errmsg;
|
||||
}
|
||||
|
||||
# don't check sub-layout layers if there's no layout
|
||||
if ($layout) {
|
||||
|
||||
# check child layers of selected layout
|
||||
foreach my $type (qw(theme i18n user)) {
|
||||
my $errmsg = $error_check->($type, $layout);
|
||||
return $err->($errmsg) if $errmsg;
|
||||
}
|
||||
}
|
||||
|
||||
# save in database
|
||||
my @layers = ( 'core' => $core );
|
||||
push @layers, map { $_, $eff_layer{$_} } qw(i18nc layout i18n theme user);
|
||||
LJ::S2::set_style_layers($u, $style->{'styleid'}, @layers);
|
||||
|
||||
# redirect if they clicked the bottom button
|
||||
return BML::redirect("styles.bml$getextra") if $POST{'action:savechanges'};
|
||||
}
|
||||
|
||||
# no style id, process actions for non-edit mode
|
||||
# and load in data necessary for style list
|
||||
} else {
|
||||
|
||||
# load user styles
|
||||
my $ustyle = LJ::S2::load_user_styles($u);
|
||||
|
||||
# process create action
|
||||
if ($POST{'action:create'} && $POST{'stylename'}) {
|
||||
|
||||
return $err->('You have reached your maximum number of styles.')
|
||||
if scalar(keys %$ustyle) >= LJ::get_cap($u, 's2stylesmax');
|
||||
|
||||
my $styleid = LJ::S2::create_style($u, $POST{'stylename'});
|
||||
return $err->('Style not created: Database error') unless $styleid;
|
||||
|
||||
return BML::redirect("styles.bml?id=$styleid$getextra_amp");
|
||||
}
|
||||
|
||||
# load style currently in use
|
||||
LJ::load_user_props($u, 's2_style');
|
||||
|
||||
# set up page header
|
||||
$title = "Your Styles";
|
||||
|
||||
$authasform->();
|
||||
|
||||
$body .= "<div><?h1 Your Styles h1?></div>\n";
|
||||
|
||||
# show style listing
|
||||
$body .= "<table style='margin-left: 40px'>\n";
|
||||
if (%$ustyle) {
|
||||
my $journalbase = LJ::journal_base($u);
|
||||
foreach my $styleid (sort { $ustyle->{$a} cmp $ustyle->{$b} || $a <=> $b} keys %$ustyle) {
|
||||
$body .= "<tr><td><form style='display:inline' method='post' action='styles.bml?id=$styleid$getextra_amp'>";
|
||||
my @b = $styleid == $u->{'s2_style'} ? "<b>" : "</b>";
|
||||
$body .= $b[0] . LJ::ehtml($ustyle->{$styleid});
|
||||
$body .= " (<a href='$journalbase/?s2id=$styleid'>\#$styleid</a>)$b[1] ";
|
||||
$body .= "</td><td>";
|
||||
$body .= LJ::html_submit('action:edit', 'Edit') . " ";
|
||||
$body .= LJ::html_submit('action:delete', 'Delete',
|
||||
{ 'onclick' => "return confirm('Are you sure you want to delete style \#$styleid?')" }) . " ";
|
||||
$body .= LJ::html_submit('action:usestyle', 'Use', { 'disabled' => $styleid == $u->{'s2_style'} }),
|
||||
$body .= "</form></td></tr>\n";
|
||||
}
|
||||
} else {
|
||||
$body .= "<tr><td><i>none</i></td></tr>\n";
|
||||
}
|
||||
$body .= "</table>\n";
|
||||
}
|
||||
|
||||
|
||||
### show create / edit form
|
||||
|
||||
my $extra = $id ? "?id=$id" : '';
|
||||
$extra .= $extra ? $getextra_amp : $getextra;
|
||||
$body .= "<form name='styleForm' method='post' action='styles.bml$extra'>";
|
||||
|
||||
# create a new style, or change the name of the style currently being edited
|
||||
# note: this little bit of code appears whether there is an id passed or not.
|
||||
# the textbox just has a different purpose depending on the context.
|
||||
$body .= "<?h1 " . ($id ? "Style Options" : "Create Style") . " h1?>\n";
|
||||
$body .= "<table style='margin-bottom: 10px'>\n";
|
||||
$body .= "<tr><td>Name: </td><td>";
|
||||
$body .= LJ::html_text({ 'name' => 'stylename', 'size' => '30', 'maxlength' => '255',
|
||||
'value' => defined $POST{'stylename'} ? $POST{'stylename'} : $style->{'name'} });
|
||||
$body .= " " . LJ::html_submit('action:create', 'Create') unless $id;
|
||||
$body .= "</td></tr>\n";
|
||||
$body .= "</table>\n";
|
||||
|
||||
# if no id to edit, we're finished
|
||||
$body .= "</form>\n", return unless $id;
|
||||
|
||||
# from here on we have $pub, $ulay, and $style filled in
|
||||
|
||||
# sub to take a layer type, core, and parent layout
|
||||
# and return a list of options to feed to LJ::html_select()
|
||||
my $layerselect = sub {
|
||||
my ($type, $b2lid) = @_;
|
||||
|
||||
my @opts = ();
|
||||
|
||||
# returns html_select to caller
|
||||
my $html_select = sub {
|
||||
my $dis = scalar(@opts) > 2 ? 0 : 1;
|
||||
|
||||
my $lid = $POST{'action:change'} ? $POST{$type} : $style->{'layer'}->{$type};
|
||||
$lid = $POST{"other_$type"} if $lid eq "_other";
|
||||
my $sel = ($lid && ! $pub->{$lid} && ! $ulay->{$lid}) ? "_other" : $lid;
|
||||
return [ LJ::html_select({ 'name' => $type, 'id' => "select_$type",
|
||||
'onChange' => "showOther('$type')",
|
||||
'selected' => $sel,
|
||||
'disabled' => $dis }, @opts), { 'disabled' => $dis, } ];
|
||||
};
|
||||
|
||||
# greps, and sorts a list
|
||||
my $greplist = sub {
|
||||
my $ref = shift;
|
||||
return sort { $ref->{$a}->{'name'} cmp $ref->{$b}->{'name'} || $a <=> $b}
|
||||
grep { $ref->{$_}->{'type'} eq $type && $ref->{$_}->{'b2lid'} == $b2lid && /^\d+$/}
|
||||
keys %$ref;
|
||||
};
|
||||
|
||||
# public layers
|
||||
my $name = $type eq 'core' ? 'majorversion' : 'name';
|
||||
push @opts, map { $_, $pub->{$_}->{$name} } $greplist->($pub);
|
||||
|
||||
# no user core layers
|
||||
return $html_select->() if $type eq 'core';
|
||||
|
||||
# user layers
|
||||
push @opts, ('', '---');
|
||||
my $startsize = scalar(@opts);
|
||||
push @opts, map { $_, "$ulay->{$_}->{'name'} (\#$_)" } $greplist->($ulay);
|
||||
|
||||
# if we didn't push anything above, remove dividing line
|
||||
pop @opts, pop @opts unless scalar(@opts) > $startsize;
|
||||
|
||||
# add option for other layerids
|
||||
push @opts, ('_other', 'Other ...');
|
||||
|
||||
# add blank option to beginning of list
|
||||
unshift @opts, ('', @opts ? '' : ' ');
|
||||
|
||||
return $html_select->();
|
||||
};
|
||||
|
||||
my $layerother = sub {
|
||||
my $name = shift;
|
||||
|
||||
my $olid = $POST{'action:change'} ? $POST{"other_$name"} : $style->{'layer'}->{$name};
|
||||
my $disp = 'none';
|
||||
my $val;
|
||||
if ($olid && ! $pub->{$olid} && ! $ulay->{$olid}) {
|
||||
$disp = 'inline';
|
||||
$val = $olid;
|
||||
}
|
||||
|
||||
return "<div id='layer_$name' style='margin-left: 5px; display: $disp;'>Layerid: " .
|
||||
LJ::html_text({ 'name' => "other_$name", 'id' => "other_$name",
|
||||
'size' => 6, 'value' => $val }) .
|
||||
"</div>";
|
||||
};
|
||||
|
||||
### core version
|
||||
|
||||
$body .= "<?h1 Style Layers h1?>\n";
|
||||
$body .= "<table>\n";
|
||||
$body .= "<tr><td>Core Version: </td><td>";
|
||||
my $coresel = $layerselect->('core', 0);
|
||||
$body .= $coresel->[0];
|
||||
$body .= LJ::html_hidden('core_hidden', $core);
|
||||
my $dis = $coresel->[1]->{'disabled'} ? { 'disabled' => 'disabled' } : undef;
|
||||
$body .= " " . LJ::html_submit('action:change', 'Change', $dis) . "</td></tr>\n";
|
||||
$body .= "</table>\n";
|
||||
|
||||
### i18nc / layout
|
||||
|
||||
$body .= "<table style='margin: 10px 0 0 40px'>\n";
|
||||
|
||||
# i18nc
|
||||
$body .= "<tr><td>Language (i18nc): </td><td>";
|
||||
$body .= $layerselect->('i18nc', $core)->[0];
|
||||
$body .= $layerother->('i18nc');
|
||||
$body .= "</td></tr>\n";
|
||||
|
||||
# layout
|
||||
$body .= "<tr><td>Layout: </td><td>";
|
||||
my $layoutsel = $layerselect->('layout', $core);
|
||||
$body .= $layoutsel->[0];
|
||||
$body .= $layerother->('layout');
|
||||
my $dis = $layoutsel->[1]->{'disabled'} ? { 'disabled' => 'disabled' } : undef;
|
||||
$body .= " " . LJ::html_submit("action:change", "Change", $dis) . " </td></tr>\n";
|
||||
$body .= "</table>\n";
|
||||
|
||||
# do we need to show the rest of the form?
|
||||
$body .= "</form>\n", return unless $layout;
|
||||
|
||||
### theme / i18n / user
|
||||
|
||||
# theme
|
||||
$body .= "<table style='margin: 10px 0 0 80px'>\n";
|
||||
$body .= "<tr><td>Language (i18n): </td><td>";
|
||||
$body .= $layerselect->('i18n', $layout)->[0];
|
||||
$body .= $layerother->('i18n') . "</td></tr>\n";
|
||||
$body .= "<tr><td>Theme: </td><td>";
|
||||
$body .= $layerselect->('theme', $layout)->[0];
|
||||
$body .= $layerother->('theme') . "</td></tr>\n";
|
||||
$body .= "<tr><td>User: </td><td>";
|
||||
$body .= $layerselect->('user', $layout)->[0];
|
||||
$body .= $layerother->('user') . "</td></tr>\n";
|
||||
$body .= "<tr><td> </td><td>";
|
||||
$body .= LJ::html_submit('action:savechanges', 'Save Changes') . "</td></tr>\n";
|
||||
$body .= "</table>\n";
|
||||
|
||||
# end edit form
|
||||
$body .= "</form>\n";
|
||||
|
||||
return;
|
||||
}
|
||||
_code?><?page
|
||||
title=><?_code return $title; _code?>
|
||||
head<=
|
||||
<script language="JavaScript">
|
||||
function showOther (name) {
|
||||
if (! document.getElementById) return false;
|
||||
var box = document.getElementById("other_" + name);
|
||||
var list = document.getElementById("select_" + name);
|
||||
var div = document.getElementById("layer_" + name);
|
||||
if (div && box) {
|
||||
div.style.display =
|
||||
(list.value == "_other" && box.value != '' || list.value == "_other")
|
||||
? "inline" : "none";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function pageload () {
|
||||
if (!document.getElementById) return false;
|
||||
|
||||
var layers = new Array('i18nc', 'layout', 'i18n', 'theme', 'user');
|
||||
for (var i=0; i<layers.length; i++) {
|
||||
showOther(layers[i]);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
</script>
|
||||
<=head
|
||||
body=><?_code return $body; _code?>
|
||||
bodyopts=>onLoad="pageload();"
|
||||
page?>
|
||||
|
||||
361
livejournal/htdocs/customize/index.bml
Executable file
@@ -0,0 +1,361 @@
|
||||
<?page
|
||||
title=><?_ml .title _ml?>
|
||||
head<=
|
||||
<style>
|
||||
option.disabled { color: GrayText; }
|
||||
</style>
|
||||
<=head
|
||||
|
||||
body<=
|
||||
<?_code
|
||||
{
|
||||
use strict;
|
||||
use vars qw(%GET %POST %FORM);
|
||||
|
||||
LJ::set_active_crumb('customize');
|
||||
|
||||
my $remote = LJ::get_remote();
|
||||
return LJ::bad_input($ML{'error.noremote'})
|
||||
unless $remote;
|
||||
|
||||
my $authas = $GET{'journal'} || $GET{'authas'} || $remote->{'user'};
|
||||
my $u = LJ::get_authas_user($authas);
|
||||
return LJ::bad_input($ML{'error.invalidauth'})
|
||||
unless $u;
|
||||
|
||||
my $userid = $u->{'userid'};
|
||||
my $has_cap = LJ::get_cap($u, "s2styles");
|
||||
|
||||
return $LJ::MSG_READONLY_USER if LJ::get_cap($u, "readonly");
|
||||
|
||||
my $ret;
|
||||
|
||||
# authas switcher form
|
||||
$ret .= "<form method='get' action='index.bml'>\n";
|
||||
$ret .= LJ::make_authas_select($remote, { 'authas' => $GET{'authas'} || $GET{'journal'} }) . "\n";
|
||||
$ret .= "</form>\n\n";
|
||||
|
||||
LJ::load_user_props($u, "stylesys", "s2_style");
|
||||
$u->{'stylesys'} ||= 1;
|
||||
|
||||
my $pub = LJ::S2::get_public_layers();
|
||||
my $userlay = LJ::S2::get_layers_of_user($u);
|
||||
my %style = LJ::S2::get_style($u, "verify");
|
||||
|
||||
my $get_lang = sub {
|
||||
my $styleid = shift;
|
||||
foreach ($userlay, $pub) {
|
||||
return $_->{$styleid}->{'langcode'} if
|
||||
$_->{$styleid} && $_->{$styleid}->{'langcode'};
|
||||
}
|
||||
return undef;
|
||||
};
|
||||
my $langcode = $get_lang->($style{'i18n'}) || $get_lang->($style{'i18nc'});
|
||||
|
||||
if ($POST{'save:stylesys'}) {
|
||||
my $num = $POST{'stylesys'} == 2 ? 2 : 1;
|
||||
LJ::set_userprop($u, "stylesys", $num);
|
||||
return BML::redirect("/customize/?journal=$u->{'user'}");
|
||||
}
|
||||
|
||||
my $implicit_style_create = sub {
|
||||
|
||||
# create new style if necessary
|
||||
unless ($u->{'s2_style'}) {
|
||||
my $layid = $style{'layout'};
|
||||
my $lay = $pub->{$layid} || $userlay->{$layid};
|
||||
my $uniq = (split("/", $lay->{'uniq'}))[0] || $lay->{'s2lid'};
|
||||
|
||||
unless ($u->{'s2_style'} = LJ::S2::create_style($u, "wizard-$uniq")) {
|
||||
die "<?h1 $ML{'Error'} h1?><?p $ML{'.error.fail_create_style'} p?>";
|
||||
}
|
||||
LJ::set_userprop($u, "s2_style", $u->{'s2_style'});
|
||||
}
|
||||
|
||||
# save values in %style to db
|
||||
LJ::S2::set_style_layers($u, $u->{'s2_style'}, %style);
|
||||
};
|
||||
|
||||
if ($POST{'save:layout'}) {
|
||||
my $layid = $POST{'layoutid'}+0;
|
||||
return BML::redirect("/customize/?journal=$u->{'user'}")
|
||||
if $layid == $style{'layout'};
|
||||
|
||||
my $lay = $pub->{$layid};
|
||||
return "<?h1 $ML{'Error'} h1?><?p $ML{'.error.disallowed_user_layer'} p?>"
|
||||
if ! $lay and $lay ||= $userlay->{$layid} and ! $has_cap;
|
||||
return "<?h1 $ML{'Error'} h1?><?p $ML{'.error.not_your_layout'} p?>"
|
||||
unless $lay && LJ::S2::can_use_layer($u, $lay->{'uniq'});
|
||||
|
||||
my $coreid = $lay->{'b2lid'};
|
||||
return "<?h1 $ML{'Error'} h1?><?p $ML{'.error.no_core_parent'} p?>"
|
||||
unless $coreid;
|
||||
|
||||
# delete s2_style and replace it with a new
|
||||
# or existing style for this layout
|
||||
delete $u->{'s2_style'};
|
||||
|
||||
my $uniq = (split("/", $lay->{'uniq'}))[0] || $lay->{'s2lid'};
|
||||
my $usersty = LJ::S2::load_user_styles($u);
|
||||
foreach (keys %$usersty) {
|
||||
next unless $usersty->{$_} eq "wizard-$uniq";
|
||||
|
||||
$u->{'s2_style'} = $_;
|
||||
LJ::set_userprop($u, "s2_style", $u->{'s2_style'});
|
||||
|
||||
# now we have to populate %style from this style, but not core and layout,
|
||||
# as those are reset below
|
||||
my $stylay = LJ::S2::get_style_layers($u, $u->{'s2_style'});
|
||||
foreach my $layer (qw(user theme i18nc i18n)) {
|
||||
$style{$layer} = exists $stylay->{$layer} ? $stylay->{$layer} : 0;
|
||||
}
|
||||
|
||||
last;
|
||||
}
|
||||
|
||||
# no existing style found, create a new one
|
||||
unless ($u->{'s2_style'}) {
|
||||
$style{'user'} = $style{'theme'} = $style{'i18nc'} = $style{'i18n'} = 0;
|
||||
}
|
||||
|
||||
# even if we're using an existing style that we found by name (uniq), we need to
|
||||
# set layout and core layers to make sure the style still has the proper layout
|
||||
$style{'layout'} = $layid;
|
||||
$style{'core'} = $coreid;
|
||||
|
||||
$implicit_style_create->();
|
||||
|
||||
return BML::redirect("/customize/?journal=$u->{'user'}");
|
||||
}
|
||||
|
||||
if ($POST{'action:deluser'}) {
|
||||
LJ::S2::delete_layer($style{'user'});
|
||||
LJ::S2::set_style_layers($u, $u->{'s2_style'}, "user", 0) if $style{'user'};
|
||||
return BML::redirect("/customize/?journal=$u->{'user'}");
|
||||
}
|
||||
|
||||
if ($POST{'action:edituser'}) {
|
||||
|
||||
unless ($style{'user'}) {
|
||||
$style{'user'} = LJ::S2::create_layer($u, $style{'layout'}, "user");
|
||||
return "<?h1 $ML{'Error'} h1?> <?p $ML{'.error.cant_generate_user_layer'} p?>"
|
||||
unless $style{'user'};
|
||||
}
|
||||
|
||||
$implicit_style_create->();
|
||||
|
||||
return BML::redirect("/customize/layer.bml?w=user&journal=$authas");
|
||||
}
|
||||
|
||||
if ($POST{'save:theme'}) {
|
||||
my $themeid = $POST{'themeid'}+0;
|
||||
return BML::redirect("/customize/?journal=$u->{'user'}")
|
||||
if $themeid == $style{'theme'};
|
||||
|
||||
my $lay = $pub->{$themeid};
|
||||
return "<?h1 $ML{'Error'} h1?><?p $ML{'.error.disallowed_theme_layer'} p?>"
|
||||
if ! $lay and $lay ||= $userlay->{$themeid} and ! $has_cap;
|
||||
return "<?h1 $ML{'Error'} h1?><?p $ML{'.error.not_your_theme'} p?>" if $themeid && ! $lay;
|
||||
$style{'theme'} = $themeid;
|
||||
|
||||
$implicit_style_create->();
|
||||
|
||||
# TODO: conflict resolution. check if there
|
||||
# exists a user layer, and ask user if they want to
|
||||
# override it using the theme exclusively.
|
||||
return BML::redirect("/customize/?journal=$u->{'user'}");
|
||||
}
|
||||
|
||||
if ($POST{'save:langcode'}) {
|
||||
my $langcode = $POST{'langcode'};
|
||||
return BML::redirect("/customize/?journal=$u->{'user'}")
|
||||
if $langcode eq 'custom';
|
||||
|
||||
my @langs = LJ::S2::get_layout_langs($pub, $style{'layout'});
|
||||
my ($i18n, $i18nc);
|
||||
|
||||
# scan for an i18n user layer
|
||||
foreach (values %$userlay) {
|
||||
last if
|
||||
$_->{'b2lid'} == $style{'layout'} &&
|
||||
$_->{'type'} eq 'i18n' &&
|
||||
$_->{'langcode'} eq $langcode &&
|
||||
($i18n = $_->{'s2lid'});
|
||||
}
|
||||
|
||||
# scan for i18nc public layer and i18n layer if necessary
|
||||
foreach (values %$pub) {
|
||||
last if $i18nc && $i18n;
|
||||
|
||||
next if
|
||||
! $i18nc &&
|
||||
$_->{'type'} eq 'i18nc' &&
|
||||
$_->{'langcode'} eq $langcode &&
|
||||
($i18nc = $_->{'s2lid'});
|
||||
|
||||
next if
|
||||
! $i18n &&
|
||||
$_->{'b2lid'} == $style{'layout'} &&
|
||||
$_->{'type'} eq 'i18n' &&
|
||||
$_->{'langcode'} eq $langcode &&
|
||||
($i18n = $_->{'s2lid'});
|
||||
}
|
||||
|
||||
$style{'i18nc'} = $i18nc;
|
||||
$style{'i18n'} = $i18n;
|
||||
|
||||
$implicit_style_create->();
|
||||
|
||||
# TODO: conflict resolution. check if there
|
||||
# exists a user layer, and ask user if they want to
|
||||
# override it using the theme exclusively.
|
||||
return BML::redirect("/customize/?journal=$u->{'user'}");
|
||||
}
|
||||
|
||||
# choose style system
|
||||
$ret .= "<form method='post' action='./?journal=$u->{'user'}'>";
|
||||
$ret .= "<?h1 $ML{'.choose.header'} h1?><?p $ML{'.choose'} p?>";
|
||||
$ret .= "<blockquote>";
|
||||
$ret .= LJ::html_select({ 'name' => 'stylesys', 'selected' => $u->{'stylesys'} },
|
||||
1, "$ML{'.choose.s1'}",
|
||||
2, "$ML{'.choose.s2'}");
|
||||
$ret .= " <input type='submit' name='save:stylesys' value='$ML{'.change'}'>";
|
||||
$ret .= "</blockquote>";
|
||||
|
||||
# no more options if they're using S1.
|
||||
if ($u->{'stylesys'} == 1) {
|
||||
$ret .= "<?h1 $ML{'.s1.header'} h1?><?p ";
|
||||
$ret .= BML::ml('.s1.2', { aopts => "href='$LJ::SITEROOT/modify.bml?authas=$authas'" });
|
||||
$ret .= " p?></form>";
|
||||
return $ret;
|
||||
}
|
||||
|
||||
# choose layout
|
||||
my @layouts = map { $_, $pub->{$_}->{'name'} }
|
||||
sort { $pub->{$a}->{'name'} cmp $pub->{$b}->{'name'} }
|
||||
grep { my $tmp = $_;
|
||||
$tmp =~ /^\d+$/ &&
|
||||
$pub->{$tmp}->{'type'} eq "layout" &&
|
||||
LJ::S2::can_use_layer($u, $pub->{$tmp}->{'uniq'}) &&
|
||||
($_ = $tmp)
|
||||
} keys %$pub;
|
||||
|
||||
# custom layers can will be shown in the "Custom Layers" and "Disabled Layers" groups
|
||||
# depending on the user's account status. if they don't have the s2styles cap, then
|
||||
# they will have all layers disabled, except for the one they are currently using.
|
||||
my $custom_layer_list = sub {
|
||||
my ($type, $ptype) = @_;
|
||||
my @layers = ();
|
||||
|
||||
my @user = map { $_, $userlay->{$_}->{'name'} ? $userlay->{$_}->{'name'} : "\#$_" }
|
||||
sort { $userlay->{$a}->{'name'} cmp $userlay->{$b}->{'name'} || $a <=> $b }
|
||||
grep { /^\d+$/ && $userlay->{$_}->{'b2lid'} == $style{$ptype} &&
|
||||
$userlay->{$_}->{'type'} eq $type &&
|
||||
($has_cap || $_ == $style{$type}) }
|
||||
keys %$userlay;
|
||||
if (@user) {
|
||||
push @layers, { value => "",
|
||||
text => "--- Custom Layers: ---",
|
||||
disabled => 1 }, @user;
|
||||
}
|
||||
|
||||
unless ($has_cap) {
|
||||
my @disabled =
|
||||
map { { value => $_,
|
||||
text => $userlay->{$_}->{'name'} ? $userlay->{$_}->{'name'} : "\#$_",
|
||||
disabled => 1 } }
|
||||
sort { $userlay->{$a}->{'name'} cmp $userlay->{$b}->{'name'} ||
|
||||
$userlay->{$a}->{'s2lid'} <=> $userlay->{$b}->{'s2lid'} }
|
||||
grep { /^\d+$/ && $userlay->{$_}->{'b2lid'} == $style{$ptype} &&
|
||||
$userlay->{$_}->{'type'} eq $type && $_ != $style{$type} }
|
||||
keys %$userlay;
|
||||
if (@disabled) {
|
||||
push @layers, { value => "",
|
||||
text => "--- Disabled Layers: ---",
|
||||
disabled => 1 }, @disabled;
|
||||
}
|
||||
}
|
||||
|
||||
return @layers;
|
||||
};
|
||||
|
||||
# add user/disabled ones
|
||||
push @layouts, $custom_layer_list->('layout', 'core');
|
||||
|
||||
$ret .= "<?h1 $ML{'.s2.layout.header'} h1?><?p $ML{'.s2.layout'} p?>";
|
||||
$ret .= "<blockquote>";
|
||||
$ret .= LJ::html_select({ 'name' => 'layoutid',
|
||||
'selected' => $style{'layout'}, },
|
||||
@layouts);
|
||||
$ret .= " <input type='submit' name='save:layout' value='$ML{'.change'}'> <a href=\"preview.bml?journal=$u->{'user'}\">$ML{'.previews'}</a>";
|
||||
$ret .= "</blockquote>";
|
||||
|
||||
# pick other stuff
|
||||
$ret .= "<?h1 $ML{'.s2.customize.header'} h1?>";
|
||||
$ret .= "<?p $ML{'.s2.customize'} p?>";
|
||||
|
||||
# langauge
|
||||
my @langs = LJ::S2::get_layout_langs($pub, $style{'layout'});
|
||||
|
||||
# they have set a custom i18n layer
|
||||
if ($style{'i18n'} &&
|
||||
($style{'i18nc'} != $style{'i18n'} || ! defined $pub->{$style{'i18n'}})) {
|
||||
push @langs, 'custom', $ML{'.s2.customize.language.custom'};
|
||||
$langcode = 'custom';
|
||||
}
|
||||
|
||||
$ret .= "<?h2 $ML{'.s2.customize.language.header'} h2?><?p $ML{'.s2.customize.language'} p?>";
|
||||
$ret .= "<blockquote>";
|
||||
$ret .= LJ::html_select({ 'name' => 'langcode',
|
||||
'selected' => $langcode, },
|
||||
0 => $ML{'.s2.customize.language.default'},
|
||||
@langs);
|
||||
$ret .= " <input type='submit' name='save:langcode' value='$ML{'.change'}'>";
|
||||
$ret .= "</blockquote>";
|
||||
|
||||
# theme
|
||||
my @themes = LJ::S2::get_layout_themes_select([$pub], $style{'layout'});
|
||||
|
||||
# add user/disabled ones
|
||||
push @themes, $custom_layer_list->('theme', 'layout');
|
||||
|
||||
$ret .= "<?h2 $ML{'.s2.customize.themes.header'} h2?><?p p?>";
|
||||
$ret .= "<blockquote>";
|
||||
$ret .= LJ::html_select({ 'name' => 'themeid',
|
||||
'selected' => $style{'theme'}, },
|
||||
'0' => $ML{'.s2.customize.themes.default'},
|
||||
@themes);
|
||||
$ret .= " <input type='submit' name='save:theme' value='$ML{'.change'}'> <a href=\"themes.bml?journal=$u->{'user'}\">$ML{'.previews'}</a>";
|
||||
$ret .= "</blockquote>";
|
||||
|
||||
# customize
|
||||
$ret .= "<?h2 $ML{'.s2.customize.settings.header'} h2?><?p $ML{'.s2.customize.settings'} p?>";
|
||||
$ret .= "<blockquote>";
|
||||
if ($style{'user'}) {
|
||||
$ret .= LJ::html_submit('action:edituser', $ML{'.s2.customize.settings.edit'});
|
||||
$ret .= LJ::html_submit('action:deluser', $ML{'.s2.customize.settings.delete'},
|
||||
{ 'onclick' => "return confirm('" . LJ::ejs($ML{'.s2.customize.settings.delete.confirm'}) . "')" });
|
||||
} else {
|
||||
$ret .= "<input type='submit' name='action:edituser' value='$ML{'.s2.customize.settings.new'}'>\n";
|
||||
}
|
||||
$ret .= "</blockquote>";
|
||||
|
||||
$ret .= "</form>";
|
||||
|
||||
$ret .= "<?h1 $ML{'.s2.related.header'} h1?>";
|
||||
$ret .= "<dl><dt>$ML{'.s2.advanced.header'}</dt><dd>";
|
||||
$ret .= $has_cap ? $ML{'.s2.advanced.permitted'} : $ML{'.s2.advanced.denied'};
|
||||
$ret .= "</dd><dt><a href='/manage/links.bml?authas=$authas'>$ML{'/manage/links.bml.title'}</a></dt><dd>$ML{'.s2.related.links.about'}</dd>";
|
||||
$ret .= "<dt><a href='/modify.bml?authas=$authas'>$ML{'/modify.bml.title'}</a></dt><dd>$ML{'.s2.related.modify.about'}</dd>";
|
||||
$ret .= "<dt><a href='/editinfo.bml?authas=$authas'>$ML{'/editinfo.bml.title'}</a></dt><dd>$ML{'.s2.related.editinfo.about'}</dd></dl>";
|
||||
|
||||
return $ret;
|
||||
}
|
||||
_code?>
|
||||
<=body
|
||||
head<=
|
||||
<style type='text/css'>
|
||||
dt { font-weight: bold }
|
||||
</style>
|
||||
<=head
|
||||
page?>
|
||||
438
livejournal/htdocs/customize/layer.bml
Executable file
@@ -0,0 +1,438 @@
|
||||
<?_code # -*-bml-*-
|
||||
{
|
||||
use strict;
|
||||
use vars qw(%POST %GET $title $body $js);
|
||||
|
||||
my $dbh = LJ::get_db_writer();
|
||||
|
||||
my $remote = LJ::get_remote();
|
||||
return "<?h1 Login Required h1?><?p Before you customize your journal, you must first <a href='/login.bml'>login</a>. p?>"
|
||||
unless $remote;
|
||||
|
||||
my @journals = ($remote->{'user'});
|
||||
push @journals, LJ::get_shared_journals($remote);
|
||||
my $journal = $GET{'journal'} || $remote->{'user'};
|
||||
unless (grep { $_ eq $journal } @journals) { return BML::redirect("/customize/"); }
|
||||
|
||||
my $u = $remote;
|
||||
$u = LJ::load_user($journal) unless $journal eq $remote->{'user'};
|
||||
my $userid = $u->{'userid'};
|
||||
|
||||
LJ::load_user_props($u, "stylesys", "s2_style");
|
||||
|
||||
$body = "";
|
||||
$title = "Customize";
|
||||
$js = "";
|
||||
|
||||
my $err = sub {
|
||||
$title = "Error";
|
||||
$body = shift;
|
||||
return;
|
||||
};
|
||||
|
||||
my ($style, $layer);
|
||||
my $save_arg;
|
||||
my $save_redir;
|
||||
|
||||
# when given 'w' argument, load user's current style, and edit the user layer.
|
||||
# this is the mode redirected to from /customize/ (the simple customization UI)
|
||||
if ($GET{'w'} eq "user" && $u->{'stylesys'} == 2)
|
||||
{
|
||||
$style = LJ::S2::load_style($u->{'s2_style'});
|
||||
return $err->("Style not found.") unless $style && $style->{'userid'} == $u->{'userid'};
|
||||
$layer = LJ::S2::load_layer($dbh, $style->{'layer'}->{'user'});
|
||||
|
||||
# if the b2lid of this layer has been remapped to a new layerid
|
||||
# then update the b2lid mapping for this layer
|
||||
my $b2lid = $layer->{b2lid};
|
||||
if ($b2lid && $LJ::S2LID_REMAP{$b2lid}) {
|
||||
LJ::S2::b2lid_remap($u, $style->{'layer'}->{'user'}, $b2lid);
|
||||
$layer->{b2lid} = $LJ::S2LID_REMAP{$b2lid};
|
||||
}
|
||||
|
||||
$save_arg = "w=user&journal=$journal";
|
||||
$save_redir = "/customize/?journal=$journal";
|
||||
}
|
||||
|
||||
return BML::redirect("/customize/") unless $layer;
|
||||
return $err->("Layer belongs to another user.") unless $layer->{'userid'} == $u->{'userid'};
|
||||
return $err->("Layer isn't of type user or theme.")
|
||||
unless $layer->{'type'} eq "user" || $layer->{'type'} eq "theme";
|
||||
|
||||
my $lyr_layout = LJ::S2::load_layer($dbh, $layer->{'b2lid'});
|
||||
return $err->("Layout layer for this $layer->{'type'} layer not found.")
|
||||
unless $lyr_layout;
|
||||
my $lyr_core = LJ::S2::load_layer($dbh, $lyr_layout->{'b2lid'});
|
||||
return $err->("Core layer for layout not found.")
|
||||
unless $lyr_core;
|
||||
|
||||
$lyr_layout->{'uniq'} = $dbh->selectrow_array("SELECT value FROM s2info WHERE s2lid=? AND infokey=?",
|
||||
undef, $lyr_layout->{'s2lid'}, "redist_uniq");
|
||||
|
||||
my ($lid_i18nc, $lid_theme, $lid_i18n);
|
||||
$lid_i18nc = $style->{'layer'}->{'i18nc'};
|
||||
$lid_theme = $style->{'layer'}->{'theme'};
|
||||
$lid_i18n = $style->{'layer'}->{'i18n'};
|
||||
|
||||
my $layerid = $layer->{'s2lid'};
|
||||
|
||||
my @layers;
|
||||
push @layers, ([ 'core' => $lyr_core->{'s2lid'} ],
|
||||
[ 'i18nc' => $lid_i18nc ],
|
||||
[ 'layout' => $lyr_layout->{'s2lid'} ],
|
||||
[ 'i18n' => $lid_i18n ]);
|
||||
if ($layer->{'type'} eq "user" && $lid_theme) {
|
||||
push @layers, [ 'theme' => $lid_theme ];
|
||||
}
|
||||
push @layers, [ $layer->{'type'} => $layer->{'s2lid'} ];
|
||||
|
||||
my @layerids = grep { $_ } map { $_->[1] } @layers;
|
||||
LJ::S2::load_layers(@layerids);
|
||||
|
||||
my %layerinfo;
|
||||
|
||||
# load the language and layout choices for core.
|
||||
LJ::S2::load_layer_info(\%layerinfo, \@layerids);
|
||||
|
||||
# action path
|
||||
if (LJ::did_post()) {
|
||||
# prevent spoofing:
|
||||
return BML::redirect("/customize")
|
||||
unless $POST{'userid'} == $u->{'userid'};
|
||||
|
||||
my %override;
|
||||
foreach my $prop (S2::get_properties($lyr_layout->{'s2lid'}))
|
||||
{
|
||||
$prop = S2::get_property($lyr_core->{'s2lid'}, $prop)
|
||||
unless ref $prop;
|
||||
next unless ref $prop;
|
||||
next if $prop->{'noui'};
|
||||
my $name = $prop->{'name'};
|
||||
next unless $POST{"$name:override"};
|
||||
next unless LJ::S2::can_use_prop($u, $lyr_layout->{'uniq'}, $name);
|
||||
$override{$name} = [ $prop, $POST{"${name}_value"} ];
|
||||
}
|
||||
|
||||
if (LJ::S2::layer_compile_user($layer, \%override)) {
|
||||
return BML::redirect($save_redir) if $save_redir;
|
||||
$body = "Saved.";
|
||||
return;
|
||||
} else {
|
||||
my $error = LJ::last_error();
|
||||
$body = "Error saving layer:<pre>$error</pre>";
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
$body .= "<form method='post' action='layer.bml?$save_arg'>";
|
||||
$body .= LJ::html_hidden("userid", $u->{'userid'});
|
||||
|
||||
my %prop; # name -> hashref, deleted when added to a category
|
||||
my @propnames;
|
||||
foreach my $prop (S2::get_properties($lyr_layout->{'s2lid'})) {
|
||||
unless (ref $prop) {
|
||||
$prop = S2::get_property($lyr_core->{'s2lid'}, $prop);
|
||||
next unless ref $prop;
|
||||
}
|
||||
$prop{$prop->{'name'}} = $prop;
|
||||
push @propnames, $prop->{'name'};
|
||||
}
|
||||
|
||||
my @groups = S2::get_property_groups($lyr_layout->{'s2lid'});
|
||||
my $misc_group;
|
||||
my %groupprops; # gname -> [ propname ]
|
||||
my %propgroup; # pname -> gname;
|
||||
|
||||
foreach my $gname (@groups) {
|
||||
if ($gname eq "misc" || $gname eq "other") { $misc_group = $gname; }
|
||||
foreach my $pname (S2::get_property_group_props($lyr_layout->{'s2lid'}, $gname)) {
|
||||
my $prop = $prop{$pname};
|
||||
next if ! $prop || $propgroup{$pname};
|
||||
$propgroup{$pname} = $gname;
|
||||
push @{$groupprops{$gname}}, $pname;
|
||||
}
|
||||
}
|
||||
# put unsorted props into an existing or new unsorted/misc group
|
||||
if (@groups) {
|
||||
my @unsorted;
|
||||
foreach my $pname (@propnames) {
|
||||
my $prop = $prop{$pname};
|
||||
next if ! $prop || $propgroup{$pname};
|
||||
push @unsorted, $pname;
|
||||
}
|
||||
if (@unsorted) {
|
||||
unless ($misc_group) {
|
||||
$misc_group = "misc";
|
||||
push @groups, "misc";
|
||||
}
|
||||
push @{$groupprops{$misc_group}}, @unsorted;
|
||||
}
|
||||
}
|
||||
|
||||
my $group_name = sub {
|
||||
my $gname = shift;
|
||||
foreach my $lid ($lid_i18n, $lyr_layout->{'s2lid'}, $lid_i18nc, $lyr_core->{'s2lid'}) {
|
||||
next unless $lid;
|
||||
my $name = S2::get_property_group_name($lid, $gname);
|
||||
return LJ::ehtml($name) if $name;
|
||||
}
|
||||
return "Misc" if $gname eq "misc";
|
||||
return $gname;
|
||||
};
|
||||
|
||||
my $prop_js = "";
|
||||
my $output_prop = sub {
|
||||
my $name = shift;
|
||||
my $prop = $prop{$name};
|
||||
return if ! $prop || $prop->{'noui'};
|
||||
|
||||
my $name = $prop->{'name'};
|
||||
my $type = $prop->{'type'};
|
||||
|
||||
my $can_use = LJ::S2::can_use_prop($u, $lyr_layout->{'uniq'}, $name);
|
||||
|
||||
# figure out existing value (if there was no user/theme layer)
|
||||
my $existing;
|
||||
foreach my $lid (reverse @layerids) {
|
||||
next if $lid == $layerid;
|
||||
$existing = S2::get_set($lid, $name);
|
||||
last if defined $existing;
|
||||
}
|
||||
|
||||
if (ref $existing eq "HASH") { $existing = $existing->{'as_string'}; }
|
||||
|
||||
if ($type eq "bool") {
|
||||
$prop->{'values'} ||= "1|Yes|0|No";
|
||||
}
|
||||
|
||||
my %values = split(/\|/, $prop->{'values'});
|
||||
my $existing_display = defined $values{$existing} ?
|
||||
$values{$existing} : $existing;
|
||||
|
||||
$existing_display = LJ::eall($existing_display);
|
||||
|
||||
my $override = S2::get_set($layerid, $name);
|
||||
my $had_override = defined $override;
|
||||
$override = $existing unless defined $override;
|
||||
|
||||
if (ref $override eq "HASH") { $override = $override->{'as_string'}; }
|
||||
|
||||
$body .= "<?h1 " . LJ::eall($prop->{'des'}) . " h1?>";
|
||||
{
|
||||
my $t = "";
|
||||
$t .= LJ::eall($prop->{'note'}) if $prop->{'note'};
|
||||
$t .= "<?help " . $LJ::HELPPURL{"s2opt_$name"} . " help?>" if $LJ::HELPURL{"s2opt_$name"};
|
||||
$body .= "<?p $t p?>" if $t;
|
||||
}
|
||||
$body .= "<div class='inset'>\n";
|
||||
$body .= LJ::html_check({ 'name' => "$name:override", 'id' => "$name:override",
|
||||
'selected' => $had_override, 'disabled' => ! $can_use,
|
||||
'onchange' => "toggleOverride('$name');" });
|
||||
my $offhelp = ! $can_use ? LJ::help_icon('s2propoff', ' ') : "";
|
||||
$body .= "<label for='$name:override'> Override default</label>$offhelp<br />\n";
|
||||
$body .= "<dl class='hidedt'>\n<dt>Default:</dt>\n<dd id='$name:default_value' style='font-family: monospace'>\n";
|
||||
if ($type eq "int" || $type eq "string") {
|
||||
if ($existing_display ne "") {
|
||||
$body .= $existing_display;
|
||||
} else {
|
||||
$body .= "<i>(nothing)</i>";
|
||||
}
|
||||
} elsif ($type eq "Color") {
|
||||
$body .= "<span style=\"border: 1px solid #000000; padding-left: 2em; ".
|
||||
"background-color: $existing;\"> </span> <tt>$existing_display</tt>";
|
||||
} elsif ($type eq "bool") {
|
||||
$body .= $existing_display;
|
||||
}
|
||||
$body .= "</dd>\n<dt>Override:</dt>\n<dd id='$name:user_value'>\n";
|
||||
if ($prop->{'values'}) {
|
||||
$body .= LJ::html_select({ 'name' => "${name}_value",
|
||||
'disabled' => ! $can_use,
|
||||
'selected' => $override },
|
||||
split(/\|/, $prop->{'values'}));
|
||||
} elsif ($type eq "int") {
|
||||
$body .= LJ::html_text({ 'name' => "${name}_value",
|
||||
'disabled' => ! $can_use,
|
||||
'value' => $override,
|
||||
'maxlength' => 5,
|
||||
'size' => 7 });
|
||||
} elsif ($type eq "string") {
|
||||
my ($rows, $cols) = ($prop->{'rows'} + 0,
|
||||
$prop->{'cols'} + 0);
|
||||
if ($rows > 0 && $cols > 0) {
|
||||
$body .= LJ::html_textarea({ 'name' => "${name}_value",
|
||||
'disabled' => ! $can_use,
|
||||
'value' => $override,
|
||||
'onfocus' => "toggleOverride('$name');",
|
||||
'rows' => $rows,
|
||||
'cols' => $cols });
|
||||
} else {
|
||||
my ($size, $maxlength) = ($prop->{'size'} || 30,
|
||||
$prop->{'maxlength'} || 255);
|
||||
$body .= LJ::html_text({ 'name' => "${name}_value",
|
||||
'disabled' => ! $can_use,
|
||||
'value' => $override,
|
||||
'maxlength' => $maxlength,
|
||||
'size' => $size });
|
||||
}
|
||||
} elsif ($type eq "Color") {
|
||||
$body .= LJ::html_color({ 'name' => "${name}_value",
|
||||
'disabled' => ! $can_use,
|
||||
'default' => $override,
|
||||
'des' => $prop->{'des'} });
|
||||
}
|
||||
$body .= "</dd></dl>\n</div>\n";
|
||||
$prop_js .= "toggleOverride('$name');\n";
|
||||
};
|
||||
|
||||
if (@groups) {
|
||||
$body .= "<div id='propgroupstab'>";
|
||||
my $num = 0;
|
||||
foreach my $gname (@groups) {
|
||||
my $name = $group_name->($gname);
|
||||
$num++;
|
||||
my $class = $num == 1 ? "propgrouptabsel" : "propgrouptab";
|
||||
$js .= " propgroups[$num] = \"$gname\";\n";
|
||||
$body .= "<span class='$class' id='pgroup_tab_$gname'><a href='#pgroup$gname' onclick=\"return showPropGroup('$gname')\">$name</a></span>\n";
|
||||
}
|
||||
$body .= "</div>";
|
||||
$body .= "<div id='propgroupsbody'>";
|
||||
|
||||
|
||||
foreach my $gname (@groups) {
|
||||
$body .= "<a name='pgroup$gname'></a>\n";
|
||||
$body .= "<div id='pgroup_body_$gname'>\n";
|
||||
foreach my $pname (@{$groupprops{$gname}}) {
|
||||
$output_prop->($pname);
|
||||
}
|
||||
$body .= "</div>";
|
||||
}
|
||||
$body .= "</div>\n";
|
||||
|
||||
$body .= "<script language='JavaScript'>showPropGroup('$groups[0]');</script>\n";
|
||||
|
||||
} else {
|
||||
foreach my $pname (@propnames) {
|
||||
$output_prop->($pname);
|
||||
}
|
||||
}
|
||||
|
||||
$body .= "<script type='text/javascript' language='JavaScript'><!--\n$prop_js// --></script>";
|
||||
|
||||
$body .= "<?h1 Finished? h1?><?p When done, click the save button below. p?><center>";
|
||||
$body .= LJ::html_submit('action:save', "Save");
|
||||
$body .= "</center>";
|
||||
|
||||
$body .= "</form>";
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
_code?><?page
|
||||
title=><?_code return $title; _code?>
|
||||
body=><?_code return $body; _code?>
|
||||
head<=
|
||||
<script language="JavaScript" src="<?_code return $LJ::JSPREFIX; _code?>/colorpicker.js"></script>
|
||||
<script language="JavaScript">
|
||||
colPic_set_imgprefix("<?_code return $LJ::IMGPREFIX; _code?>");
|
||||
|
||||
var propgroups = new Array();
|
||||
function showPropGroup (name) {
|
||||
if (! document.getElementById) { return true; }
|
||||
for (var i=0; i<propgroups.length; i++) {
|
||||
var gname = propgroups[i];
|
||||
var tab = document.getElementById("pgroup_tab_" + gname);
|
||||
if (tab && tab.setAttribute) {
|
||||
tab.setAttribute("class", (gname == name) ? "propgrouptabsel" : "propgrouptab");
|
||||
}
|
||||
var div = document.getElementById("pgroup_body_" + gname);
|
||||
if (div) {
|
||||
div.style.display = (gname == name) ? "block" : "none";
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function toggleOverride (name) {
|
||||
if (!name) return true;
|
||||
if (!document.getElementById) return true;
|
||||
var ocheck = document.getElementById(name + ':override');
|
||||
if (!ocheck) return true;
|
||||
|
||||
var def_vals = document.getElementById(name + ':default_value');
|
||||
if (!def_vals) return true;
|
||||
var usr_vals = document.getElementById(name + ':user_value');
|
||||
if (!usr_vals) return true;
|
||||
|
||||
var disp_def = ocheck.checked ? 'none' : 'block';
|
||||
var disp_usr = ocheck.checked ? 'block' : 'none';
|
||||
|
||||
def_vals.style.display = disp_def;
|
||||
usr_vals.style.display = disp_usr;
|
||||
}
|
||||
<?_code return $js; _code?>
|
||||
</script>
|
||||
|
||||
|
||||
<style type='text/css'>
|
||||
#propgroupstab {
|
||||
font-size: 1.2em;
|
||||
font-weight: bold;
|
||||
font-decoration: none;
|
||||
border-bottom: 2px solid black;
|
||||
margin: 0; padding: 0;
|
||||
}
|
||||
#propgroupsbody {
|
||||
border-left: 2px solid black;
|
||||
border-right: 2px solid black;
|
||||
border-bottom: 2px solid black;
|
||||
margin: 0; padding: 0.5em;
|
||||
}
|
||||
|
||||
span.propgrouptabsel, span.propgrouptab {
|
||||
margin: 0 0.2em 0 0.8em;
|
||||
padding: 0.25em;
|
||||
border-top: 2px solid black;
|
||||
border-left: 2px solid black;
|
||||
border-right: 2px solid black;
|
||||
}
|
||||
|
||||
span.propgrouptab {
|
||||
background: #ddd;
|
||||
color: black;
|
||||
}
|
||||
span.propgrouptab a {
|
||||
text-decoration: none;
|
||||
color: black;
|
||||
}
|
||||
|
||||
span.propgrouptabsel {
|
||||
color: #ddd;
|
||||
background: black;
|
||||
}
|
||||
span.propgrouptabsel a {
|
||||
text-decoration: none;
|
||||
color: #ddd;
|
||||
}
|
||||
div.inset {
|
||||
margin-left: 2em;
|
||||
margin-top: 0.5em;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
dl.hidedt {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
dl.hidedt dt { font-weight: bold; }
|
||||
noscript { display: inline; }
|
||||
</style>
|
||||
<script type='text/javascript' language='JavaScript'>
|
||||
// Only hide if we do the JS-switchy thing
|
||||
if (document.getElementById)
|
||||
document.write("<style type='text/css'>" +
|
||||
"dl.hidedt dd { margin: 0; padding: 0; }" +
|
||||
"dl.hidedt dt { display: none; }" +
|
||||
"noscript { display: none; }" +
|
||||
"</style>");
|
||||
</script>
|
||||
|
||||
<=head
|
||||
page?>
|
||||
39
livejournal/htdocs/customize/preview.bml
Executable file
@@ -0,0 +1,39 @@
|
||||
<?page
|
||||
title=>Layout Previews
|
||||
body<=
|
||||
<?_code
|
||||
{
|
||||
use strict;
|
||||
use vars qw(%GET %POST);
|
||||
|
||||
LJ::set_active_crumb('preview');
|
||||
|
||||
my $ret;
|
||||
my $remote = LJ::get_remote();
|
||||
my $journal = LJ::canonical_username($GET{'journal'});
|
||||
|
||||
$ret .= "<p>[<< <a href='/customize/?journal=$journal'>Back</a>]</p>";
|
||||
|
||||
my $pub = LJ::S2::get_public_layers();
|
||||
|
||||
my @layouts =
|
||||
sort { $a->{'name'} cmp $b->{'name'} }
|
||||
map { $pub->{$_} } grep { /^\d+$/ && $pub->{$_}->{'type'} eq "layout" } keys %$pub;
|
||||
|
||||
foreach my $l (@layouts) {
|
||||
$ret .= "<?h1 " . LJ::eall($l->{'name'}) . " h1?>";
|
||||
unless ($l->{'_previews'}) {
|
||||
$ret .= "<?p <i>No preview available.</i> p?>";
|
||||
next;
|
||||
}
|
||||
foreach (split(/\,/, $l->{'_previews'})) {
|
||||
my ($img, $w, $h) = split(/\|/, $_);
|
||||
$ret .= "<p style='margin-left: 20px'><img src=\"$LJ::IMGPREFIX/s2preview/$img\" width=\"$w\" height=\"$h\"></p>";
|
||||
}
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
_code?>
|
||||
<=body
|
||||
page?>
|
||||
79
livejournal/htdocs/customize/themes.bml
Executable file
@@ -0,0 +1,79 @@
|
||||
<?page
|
||||
title=>Theme Previews
|
||||
body<=
|
||||
<?_code
|
||||
{
|
||||
use strict;
|
||||
use vars qw(%GET %POST);
|
||||
|
||||
LJ::set_active_crumb('themes');
|
||||
|
||||
my $ret;
|
||||
my $dbr = LJ::get_db_reader();
|
||||
|
||||
my $remote = LJ::get_remote();
|
||||
|
||||
return "<?h1 Login Required h1?><?p Before you customize your journal, you must first <a href='/login.bml?ret=1'>login</a>. p?>"
|
||||
unless $remote;
|
||||
|
||||
my @journals = ($remote->{'user'});
|
||||
push @journals, LJ::get_shared_journals($remote);
|
||||
my $journal = $GET{'journal'} || $remote->{'user'};
|
||||
unless (grep { $_ eq $journal } @journals) { return BML::redirect("/customize/"); }
|
||||
|
||||
$ret .= "<p>[<< <a href='/customize/?journal=$journal'>Back</a>]</p>";
|
||||
|
||||
my $u = $remote;
|
||||
$u = LJ::load_user($journal) unless $journal eq $remote->{'user'};
|
||||
my $userid = $u->{'userid'};
|
||||
|
||||
LJ::load_user_props($u, "stylesys", "s2_style");
|
||||
$u->{'stylesys'} ||= 1;
|
||||
my $pub = LJ::S2::get_public_layers();
|
||||
my $userlay = {}; # TODO: add API call to fetch these
|
||||
my %style = LJ::S2::get_style($u->{'s2_style'});
|
||||
|
||||
return "S2 required" unless $u->{'stylesys'} == 2 && $style{'layout'};
|
||||
|
||||
# get themes for this layer
|
||||
my @themes = LJ::S2::get_layout_themes([$pub, $userlay], $style{'layout'});
|
||||
|
||||
# make the context, without the theme
|
||||
my @layers;
|
||||
foreach (qw(core i18nc layout i18n)) {
|
||||
push @layers, $style{$_} if $style{$_};
|
||||
}
|
||||
LJ::S2::load_layers(@layers, map { $_->{'s2lid'} } @themes);
|
||||
|
||||
my $cleaner = new HTMLCleaner ('output' => sub { $ret .= $_[0]; });
|
||||
my $out_straight = sub { $ret .= $_[0]; };
|
||||
my $out_clean = sub { $cleaner->parse($_[0]); };
|
||||
|
||||
$LJ::S2::CURR_PAGE = undef;
|
||||
|
||||
foreach my $t (0, @themes) {
|
||||
my $id = ref $t ? $t->{'s2lid'} : 0;
|
||||
my $name = ref $t ? LJ::eall($t->{'name'}) : "Layout Default";
|
||||
my $ctx = S2::make_context(@layers, $id);
|
||||
LJ::S2::escape_context_props($ctx);
|
||||
LJ::S2::populate_system_props($ctx);
|
||||
|
||||
S2::set_output(sub {}); # printing suppressed
|
||||
S2::set_output_safe(sub {});
|
||||
eval { S2::run_code($ctx, "prop_init()"); };
|
||||
S2::set_output($out_straight);
|
||||
S2::set_output_safe($out_straight);
|
||||
$ret .= "<?h1 $name h1?>";
|
||||
$ret .= "<div>";
|
||||
eval { S2::run_code($ctx, "print_theme_preview()"); };
|
||||
$ret .= "</div>";
|
||||
|
||||
}
|
||||
$cleaner->eof if $cleaner; # flush any remaining text/tag not yet spit out
|
||||
|
||||
return $ret;
|
||||
|
||||
}
|
||||
_code?>
|
||||
<=body
|
||||
page?>
|
||||
159
livejournal/htdocs/customize/viewuser.bml
Executable file
@@ -0,0 +1,159 @@
|
||||
<?_code # -*-bml-*-
|
||||
{
|
||||
use strict;
|
||||
use vars qw(%POST %GET $title $body);
|
||||
|
||||
my $dbh = LJ::get_db_writer();
|
||||
|
||||
my $remote = LJ::get_remote();
|
||||
return "<?h1 Login Required h1?><?p You must first <a href='/login.bml?ret=1'>login</a>. p?>"
|
||||
unless $remote;
|
||||
|
||||
my @journals = ($remote->{'user'});
|
||||
push @journals, LJ::get_shared_journals($remote);
|
||||
my $journal = $GET{'journal'} || $remote->{'user'};
|
||||
unless (grep { $_ eq $journal } @journals) { return BML::redirect("/customize/"); }
|
||||
|
||||
my $u = $remote;
|
||||
$u = LJ::load_user($journal) unless $journal eq $remote->{'user'};
|
||||
my $userid = $u->{'userid'};
|
||||
|
||||
LJ::load_user_props($u, "stylesys", "s2_style");
|
||||
|
||||
$body = "";
|
||||
$title = "User Layer";
|
||||
|
||||
if (@journals > 1) {
|
||||
$body .= "<form method='get' action='viewuser.bml'>";
|
||||
$body .= "Work with journal: ";
|
||||
$body .= LJ::html_select({
|
||||
'name' => 'journal',
|
||||
'selected' => $journal,
|
||||
}, map { $_, $_ } @journals);
|
||||
$body .= " <input type='submit' value='Switch'> </form>";
|
||||
}
|
||||
|
||||
$body .= "<< <a href='/customize/?journal=$journal'>customize</a><p>";
|
||||
|
||||
my $err = sub {
|
||||
$title = "Error";
|
||||
$body = shift;
|
||||
return;
|
||||
};
|
||||
|
||||
my ($style, $layer);
|
||||
my $save_arg;
|
||||
my $save_redir;
|
||||
|
||||
# when given 'w' argument, load user's current style, and edit the user layer.
|
||||
# this is the mode redirected to from /customize/ (the simple customization UI)
|
||||
if ($u->{'stylesys'} == 2)
|
||||
{
|
||||
$style = LJ::S2::load_style($u->{'s2_style'});
|
||||
return $err->("Style not found.") unless $style && $style->{'userid'} == $u->{'userid'};
|
||||
$layer = LJ::S2::load_layer($dbh, $style->{'layer'}->{'user'});
|
||||
}
|
||||
|
||||
unless ($layer) {
|
||||
$body .= "No user layer";
|
||||
return;
|
||||
}
|
||||
|
||||
return $err->("Layer belongs to another user.") unless $layer->{'userid'} == $u->{'userid'};
|
||||
return $err->("Layer isn't of type user or theme.")
|
||||
unless $layer->{'type'} eq "user";
|
||||
|
||||
my $lyr_layout = LJ::S2::load_layer($dbh, $layer->{'b2lid'});
|
||||
return $err->("Layout layer for this $layer->{'type'} layer not found.")
|
||||
unless $lyr_layout;
|
||||
my $lyr_core = LJ::S2::load_layer($dbh, $lyr_layout->{'b2lid'});
|
||||
return $err->("Core layer for layout not found.")
|
||||
unless $lyr_core;
|
||||
|
||||
$lyr_layout->{'uniq'} = $dbh->selectrow_array("SELECT value FROM s2info WHERE s2lid=? AND infokey=?",
|
||||
undef, $lyr_layout->{'s2lid'}, "redist_uniq");
|
||||
|
||||
my ($lid_i18nc, $lid_theme, $lid_i18n);
|
||||
$lid_i18nc = $style->{'layer'}->{'i18nc'};
|
||||
$lid_theme = $style->{'layer'}->{'theme'};
|
||||
$lid_i18n = $style->{'layer'}->{'i18n'};
|
||||
|
||||
my $layerid = $layer->{'s2lid'};
|
||||
|
||||
my @layers;
|
||||
push @layers, ([ 'core' => $lyr_core->{'s2lid'} ],
|
||||
[ 'i18nc' => $lid_i18nc ],
|
||||
[ 'layout' => $lyr_layout->{'s2lid'} ],
|
||||
[ 'i18n' => $lid_i18n ]);
|
||||
if ($layer->{'type'} eq "user" && $lid_theme) {
|
||||
push @layers, [ 'theme' => $lid_theme ];
|
||||
}
|
||||
push @layers, [ $layer->{'type'} => $layer->{'s2lid'} ];
|
||||
|
||||
my @layerids = grep { $_ } map { $_->[1] } @layers;
|
||||
LJ::S2::load_layers(@layerids);
|
||||
|
||||
my %layerinfo;
|
||||
|
||||
# load the language and layout choices for core.
|
||||
LJ::S2::load_layer_info(\%layerinfo, \@layerids);
|
||||
|
||||
$body .= "<a href='viewuser.bml?journal=$journal'>Raw</a> | ";
|
||||
$body .= "<a href='viewuser.bml?journal=$journal&as=theme'>As Theme</a>\n";
|
||||
|
||||
$body .= "<p><textarea rows='40' cols='60' wrap='off'>";
|
||||
|
||||
$body .= "# for layout: $lyr_layout->{'s2lid'} ($lyr_layout->{'uniq'})\n";
|
||||
|
||||
if ($GET{'as'} eq "") {
|
||||
$body .= "layerinfo type = user;\n\n";
|
||||
} elsif ($GET{'as'} eq "theme") {
|
||||
$body .= "layerinfo type = theme;\nlayerinfo name = \"\";\n\n";
|
||||
}
|
||||
|
||||
foreach my $prop (S2::get_properties($lyr_layout->{'s2lid'}))
|
||||
{
|
||||
$prop = S2::get_property($lyr_core->{'s2lid'}, $prop)
|
||||
unless ref $prop;
|
||||
next unless ref $prop;
|
||||
next if $prop->{'noui'};
|
||||
|
||||
my $name = $prop->{'name'};
|
||||
my $type = $prop->{'type'};
|
||||
|
||||
# figure out existing value (if there was no user/theme layer)
|
||||
my $existing;
|
||||
foreach my $lid (reverse @layerids) {
|
||||
next if $lid == $layerid;
|
||||
$existing = S2::get_set($lid, $name);
|
||||
last if defined $existing;
|
||||
}
|
||||
|
||||
if (ref $existing eq "HASH") { $existing = $existing->{'as_string'}; }
|
||||
my $val = S2::get_set($layerid, $name);
|
||||
my $had_override = defined $val;
|
||||
$val = $existing unless $had_override;
|
||||
if (ref $val eq "HASH") { $val = $val->{'as_string'}; }
|
||||
|
||||
next if $GET{'as'} eq "" && ! $had_override;
|
||||
next if $GET{'as'} eq "theme" && $type ne "Color";
|
||||
|
||||
if ($prop->{'type'} eq "int") {
|
||||
$val = int($val);
|
||||
} elsif ($prop->{'type'} eq "bool") {
|
||||
$val = $val ? "true" : "false";
|
||||
} else {
|
||||
$val =~ s/[\\\$\"]/\\$&/g;
|
||||
$val = "\"$val\"";
|
||||
}
|
||||
$body .= "set $name = $val;\n";
|
||||
}
|
||||
$body .= "</textarea>";
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
_code?><?page
|
||||
title=><?_code return $title; _code?>
|
||||
body=><?_code return $body; _code?>
|
||||
page?>
|
||||
174
livejournal/htdocs/delcomment.bml
Executable file
@@ -0,0 +1,174 @@
|
||||
<?_info
|
||||
nocache=>1
|
||||
_info?><?_code
|
||||
{
|
||||
use strict;
|
||||
use vars qw(%GET %POST);
|
||||
use vars qw($body);
|
||||
|
||||
my $jsmode = $GET{mode} eq "js";
|
||||
$body = "";
|
||||
|
||||
my $error = sub {
|
||||
if ($jsmode) {
|
||||
BML::finish();
|
||||
return "alert('" . LJ::ejs($_[0]) . "'); 0;";
|
||||
}
|
||||
$body = "<?h1 $ML{'Error'} h1?><?p $_[0] p?>";
|
||||
return;
|
||||
};
|
||||
my $bad_input = sub {
|
||||
return $error->("Bad input: $_[0]") if $jsmode;
|
||||
$body = LJ::bad_input($_[0]);
|
||||
return;
|
||||
};
|
||||
|
||||
LJ::set_active_crumb('delcomment');
|
||||
|
||||
my $remote = LJ::get_remote();
|
||||
return $bad_input->($ML{'error.noremote'})
|
||||
unless $remote;
|
||||
|
||||
return $error->("Missing parameters.") unless $GET{'journal'} ne "" && $GET{'id'};
|
||||
|
||||
# $u is user object of journal that owns the talkpost
|
||||
my $u = LJ::load_user($GET{'journal'});
|
||||
return $bad_input->($ML{'error.nojournal'})
|
||||
unless $u;
|
||||
|
||||
# can't delete if you're suspended
|
||||
return $bad_input->($ML{'.error.suspended'})
|
||||
if $remote->{statusvis} eq 'S';
|
||||
|
||||
return $error->($LJ::MSG_READONLY_USER) if LJ::get_cap($u, "readonly");
|
||||
|
||||
my $dbcr = LJ::get_cluster_def_reader($u);
|
||||
return $error->($ML{'error.nodb'})
|
||||
unless $dbcr;
|
||||
|
||||
# $tp is a hashref of info about this individual talkpost row
|
||||
my $tpid = $GET{'id'} >> 8;
|
||||
my $tp = $dbcr->selectrow_hashref("SELECT jtalkid AS 'talkid', nodetype, state, " .
|
||||
"nodeid AS 'itemid', parenttalkid, journalid, posterid " .
|
||||
"FROM talk2 ".
|
||||
"WHERE journalid=? AND jtalkid=?",
|
||||
undef, $u->{'userid'}, $tpid);
|
||||
|
||||
return $bad_input->($ML{'.error.nocomment'})
|
||||
unless $tp;
|
||||
|
||||
return $bad_input->($ML{'.error.invalidtype'})
|
||||
unless $tp->{'nodetype'} eq 'L';
|
||||
|
||||
return $bad_input->($ML{'.error.alreadydeleted'})
|
||||
if $tp->{'state'} eq "D";
|
||||
|
||||
# get username of poster
|
||||
$tp->{'userpost'} = LJ::get_username($tp->{'posterid'});
|
||||
|
||||
# userid of user who posted journal entry
|
||||
my $jposterid = $dbcr->selectrow_array("SELECT posterid FROM log2 WHERE " .
|
||||
"journalid=? AND jitemid=?",
|
||||
undef, $u->{'userid'}, $tp->{'itemid'});
|
||||
my $jposter = LJ::load_userid($jposterid);
|
||||
|
||||
# can $remote delete this comment?
|
||||
unless (LJ::Talk::can_delete($remote, $u, $jposter, $tp->{'userpost'})) {
|
||||
my $err = $u->{'journaltype'} eq 'C' ? $ML{'.error.cantdelete.comm'} : $ML{'.error.cantdelete'};
|
||||
return $error->($err);
|
||||
}
|
||||
|
||||
my $can_manage = LJ::can_manage($remote, $u);
|
||||
|
||||
# can ban if can manage and the comment is by someone else and not anon
|
||||
my $can_ban = $can_manage && $tp->{'posterid'}
|
||||
&& $remote && $remote->{'userid'} != $tp->{'posterid'};
|
||||
my $can_delthread = $can_manage || $jposterid == $remote->{userid};
|
||||
|
||||
### perform actions
|
||||
if (LJ::did_post() && $POST{'confirm'}) {
|
||||
# mark this as spam?
|
||||
LJ::Talk::mark_comment_as_spam($u, $tp->{talkid})
|
||||
if $POST{spam};
|
||||
|
||||
# delete entire thread? or just the one comment?
|
||||
if ($POST{delthread} && $can_delthread) {
|
||||
# delete entire thread ...
|
||||
LJ::Talk::delete_thread($u, $tp->{'itemid'}, $tpid);
|
||||
} else {
|
||||
# delete single comment...
|
||||
|
||||
# if it's screened, unscreen it first to properly adjust
|
||||
# replycount and the hasscreened logprop
|
||||
LJ::Talk::unscreen_comment($u, $tp->{'itemid'}, $tpid)
|
||||
if $tp->{'state'} eq 'S';
|
||||
|
||||
# now do the deletion
|
||||
my $num = LJ::delete_comments($u, "L", $tp->{'itemid'}, $tpid);
|
||||
LJ::replycount_do($u, $tp->{'itemid'}, "decr", $num);
|
||||
LJ::Talk::update_commentalter($u, $tp->{'itemid'});
|
||||
}
|
||||
|
||||
# ban the user, if selected
|
||||
my $msg;
|
||||
if ($POST{'ban'} && $can_ban) {
|
||||
LJ::set_rel($u->{'userid'}, $tp->{'posterid'}, 'B');
|
||||
$msg = BML::ml('.success.andban', { 'user' => LJ::ljuser($tp->{'userpost'}) });
|
||||
}
|
||||
$msg ||= $ML{'.success.noban'};
|
||||
$msg .= "<?p $ML{'.success.spam'} p?>" if $POST{spam};
|
||||
|
||||
if ($jsmode) {
|
||||
BML::finish();
|
||||
return "1;";
|
||||
} else {
|
||||
$body = "<?h1 $ML{'.success.head'} h1?><?p $msg p?>";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
### show confirmation form
|
||||
|
||||
$body .= "<?h1 $ML{'.confirm.head'} h1?>";
|
||||
$body .= "<?p $ML{'.confirm.body'} p?>";
|
||||
$body .= "<form method='post' action='delcomment.bml?";
|
||||
$body .= "journal=$u->{'user'}&id=$GET{'id'}'>\n";
|
||||
$body .= "<?standout ";
|
||||
|
||||
$body .= "<div align='center' style='margin: 8px'>" . LJ::html_submit('confirm', $ML{'.confirm.submit'}) . "</div>\n";
|
||||
|
||||
if ($can_ban) {
|
||||
$body .= "<div>" . LJ::html_check({ 'type' => 'check', 'name' => 'ban', 'id' => 'ban' });
|
||||
$body .= "<label for='ban'>";
|
||||
$body .= BML::ml('.confirm.banuser', { 'user' => LJ::ljuser($tp->{'userpost'}) });
|
||||
$body .= "</label></div>";
|
||||
}
|
||||
|
||||
if ($tp->{'posterid'} != $remote->{'userid'}) { # Despite the idea of natural selection, don't let users report their own comments as spam
|
||||
$body .= "<div>" . LJ::html_check({name => 'spam', id => 'spam'});
|
||||
$body .= "<label for='spam'>$ML{'.confirm.spam'}</label></div>";
|
||||
}
|
||||
|
||||
if ($can_delthread) {
|
||||
$body .= "<div>" . LJ::html_check({name => 'delthread', id => 'delthread'});
|
||||
$body .= "<label for='delthread'>$ML{'.confirm.delthread'}</label></div>";
|
||||
}
|
||||
|
||||
$body .= " standout?>";
|
||||
|
||||
if ($can_manage) {
|
||||
my $msg = BML::ml('.changeoptions', { 'link' =>
|
||||
"<a href='/editinfo.bml?authas=$u->{'user'}'>$ML{'/editinfo.bml.title'}</a>" });
|
||||
$body .= "<?p $msg p?>";
|
||||
}
|
||||
|
||||
$body .= "</form>\n";
|
||||
return;
|
||||
}
|
||||
_code?><?page
|
||||
title=><?_ml .title _ml?>
|
||||
body=><?_code return $body; _code?>
|
||||
page?><?_c <LJDEP>
|
||||
link: htdocs/editinfo.bml
|
||||
post: htdocs/delcomment.bml
|
||||
</LJDEP> _c?>
|
||||
85
livejournal/htdocs/dev/userlist.bml
Executable file
@@ -0,0 +1,85 @@
|
||||
<?page
|
||||
title=>Users on this server
|
||||
body<=
|
||||
<?_code
|
||||
{
|
||||
use strict;
|
||||
use vars qw(%GET);
|
||||
return "Not a dev server." unless $LJ::IS_DEV_SERVER;
|
||||
|
||||
my $pagesize = 250;
|
||||
|
||||
$GET{'page'} ||= 1;
|
||||
my $page = $GET{'page'} - 1;
|
||||
my $offset = $page * $pagesize;
|
||||
my $ret = "";
|
||||
my $dbr = LJ::get_db_reader();
|
||||
my %ss;
|
||||
my $orderby = $GET{'sort'} eq 'user' ? "user" :
|
||||
$GET{'sort'} eq 'jt' ? "journaltype,user" :
|
||||
$GET{'sort'} eq 'sv' ? "statusvis,user" : "userid";
|
||||
my $pagesizeplus1 = $pagesize + 1;
|
||||
my $h = $dbr->prepare("SELECT userid,user,journaltype,statusvis FROM user ORDER BY $orderby LIMIT $offset,$pagesizeplus1");
|
||||
$h->execute;
|
||||
my @userids;
|
||||
while (my $row = $h->fetchrow_hashref) {
|
||||
$ss{$row->{'userid'}} = $row;
|
||||
push @userids, $row->{'userid'};
|
||||
}
|
||||
my $islastpage = 1;
|
||||
if (scalar(@userids) > $pagesize) {
|
||||
pop @userids;
|
||||
$islastpage = 0;
|
||||
}
|
||||
my $inclause = join (",", @userids);
|
||||
$h = $dbr->prepare("SELECT * FROM reluser WHERE userid IN ($inclause)");
|
||||
$h->execute;
|
||||
while (my $row = $h->fetchrow_hashref) {
|
||||
push @{$ss{$row->{'userid'}}->{'reluser'}}, $row;
|
||||
}
|
||||
|
||||
# sort bar
|
||||
my $pagearg = $GET{'page'} > 1 ? "&page=$GET{'page'}" : "";
|
||||
my $pagearg2 = $GET{'page'} > 1 ? "?page=$GET{'page'}" : "";
|
||||
$ret .= "<?p <strong>Sort by:</strong> [<a href='userlist.bml$pagearg2'> User ID
|
||||
</a>|<a href='userlist.bml?sort=user$pagearg'> Username
|
||||
</a>|<a href='userlist.bml?sort=jt$pagearg'> Journal Type
|
||||
</a>|<a href='userlist.bml?sort=sv$pagearg'> Status Vis
|
||||
</a>] p?>";
|
||||
|
||||
# page bar
|
||||
my $next = $page + 2;
|
||||
$pagearg = $page > 1 ? "&page=$page" : "";
|
||||
$ret .= "<?p [" if $page || !$islastpage;
|
||||
$ret .= "<a href='userlist.bml?sort=$GET{'sort'}$pagearg'> Previous Page </a>" if $page;
|
||||
$ret .= "|" if $page && !$islastpage;
|
||||
$ret .= "<a href='userlist.bml?sort=$GET{'sort'}&page=$next'> Next Page </a>" if !$islastpage;
|
||||
$ret .= "] p?>" if $page || !$islastpage;
|
||||
|
||||
$ret .= "<br /><br /> <table width='100%' border='1'>
|
||||
<tr valign='bottom'><td><b>User ID</b></td><td><b>Username</b></td>
|
||||
<td><b>T/S</b></td><td><b>Reluser Edges</b></td></tr>";
|
||||
|
||||
foreach my $userid (@userids) {
|
||||
my $hr = $ss{$userid};
|
||||
$ret .= "<tr><td><b>$userid</b></td><td>";
|
||||
$ret .= LJ::ljuser($hr->{'user'}, {type=> $hr->{'journaltype'}});
|
||||
$ret .= "</td><td><b>$hr->{'journaltype'}</b>/<b>$hr->{'statusvis'}</b></td><td>";
|
||||
if ($hr->{'reluser'} && scalar(@{$hr->{'reluser'}})) {
|
||||
my $c = 0;
|
||||
foreach my $t (sort { $a->{'type'} cmp $b->{'type'} }
|
||||
@{$hr->{'reluser'}}) {
|
||||
$ret .= "; " if $c;
|
||||
$ret .= "<b>$t->{'type'}</b>/";
|
||||
$ret .= LJ::ljuser($ss{$t->{'targetid'}}->{'user'}, {type=>
|
||||
$ss{$t->{'targetid'}}->{'journaltype'}});
|
||||
$c = 1;
|
||||
}
|
||||
}
|
||||
$ret .= "</td></tr>";
|
||||
}
|
||||
$ret .= "</table>";
|
||||
return $ret;
|
||||
}
|
||||
_code?>
|
||||
page?>
|
||||
380
livejournal/htdocs/directory.bml
Executable file
@@ -0,0 +1,380 @@
|
||||
<?_code $head = ""; _code?><?page
|
||||
title=>Search Results
|
||||
body<=
|
||||
|
||||
<?_code
|
||||
|
||||
return LJ::server_down_html() if ($LJ::SERVER_DOWN);
|
||||
|
||||
LJ::set_active_crumb('searchregion');
|
||||
|
||||
my @errors = ();
|
||||
my @filters = LJ::Dir::validate(\%FORM, \@errors);
|
||||
return LJ::bad_input(@errors) if @errors;
|
||||
|
||||
my $dbr = LJ::get_db_reader();
|
||||
|
||||
# the common case (small installations), people want the directory
|
||||
# to just work. so we'll support that by default. but on big sites,
|
||||
# you don't want the directory ever getting near the other databases,
|
||||
# so we provide a flag to make sure the code can't.
|
||||
my @extraroles = ("slave", "master");
|
||||
if ($LJ::DIRECTORY_SEPARATE) { @extraroles = (); }
|
||||
|
||||
my $dbdir = LJ::get_dbh("directory", @extraroles);
|
||||
return "Directory database not available." unless $dbdir;
|
||||
my @matches;
|
||||
my %info;
|
||||
my $ret = "";
|
||||
|
||||
if (BML::get_query_string() eq "")
|
||||
{
|
||||
LJ::load_codes({ state => \%state, country => \%country });
|
||||
$ret = "";
|
||||
$ret .= "<?h1 $ML{'.browse.usa.title'} h1?><?p $ML{'.browse.usa.desc'} p?>\n";
|
||||
$ret .= "<form action='get' name=\"stateForm\"><p align='center'>";
|
||||
$ret .= "<script language=\"JavaScript\" type='text/javascript'><!--\n document.write('<input name=\"s\" type=\"text\" size=\"30\"><br />'); \n// --></script>\n";
|
||||
|
||||
$ret .= "<script language=\"JavaScript\" type='text/javascript'><!--\nfunction updateStatus (text) { self.status = text; document.stateForm.s.value=text; return true; } \n// --></script>\n";
|
||||
|
||||
$ret .= "<img alt='US Map' src=\"$LJ::IMGPREFIX/us_map.gif\" width='489' height='315' border='0' usemap=\"#state_test\" ismap='ismap' /></p></form><map name='state_test' id='state_test'>\n";
|
||||
|
||||
$sth = $dbr->prepare("SELECT statcat, statkey, statval FROM stats WHERE statcat IN ('country', 'stateus')");
|
||||
$sth->execute;
|
||||
while ($_ = $sth->fetchrow_hashref) {
|
||||
$count{$_->{'statcat'}}->{$_->{'statkey'}} = $_->{'statval'};
|
||||
}
|
||||
|
||||
my @shapes = (
|
||||
"1,235,1,309,108,309,108,235,18,235,1,235", "AK",
|
||||
"328,196,328,236,355,235,345,195,328,196,328,196", "AL",
|
||||
"267,182,272,215,294,216,293,206,300,182,267,182,267,182", "AR",
|
||||
"86,162,72,205,113,225,124,167,86,162,86,162", "AZ",
|
||||
"14,86,6,110,22,166,54,198,69,189,29,123,38,90,14,86,14,86", "CA",
|
||||
"137,122,133,160,191,169,191,128,137,122,137,122", "CO",
|
||||
"444,91,443,99,456,92,456,88,444,91,444,91", "CT",
|
||||
"445,158,460,158,460,168,445,158", "DC",
|
||||
"428,122,433,134,436,132,430,121,428,122", "DE",
|
||||
"450,126,464,135", "DE",
|
||||
"335,240,335,244,371,242,391,259,410,293,414,279,390,238,335,240,335,240", "FL",
|
||||
"352,194,366,234,388,233,389,216,364,192,352,194,352,194", "GA",
|
||||
"119,269,185,312", "HI",
|
||||
"248,101,254,126,289,126,286,97,248,101,248,101", "IA",
|
||||
"86,24,73,90,114,99,118,76,100,72,86,24,86,24", "ID",
|
||||
"302,111,293,135,313,162,321,147,316,111,302,111,302,111", "IL",
|
||||
"326,119,328,154,344,143,343,114,326,119,326,119", "IN",
|
||||
"199,140,196,167,257,170,254,141,199,140,199,140", "KS",
|
||||
"325,172,324,161,341,160,348,148,366,149,367,164,325,172,325,172", "KY",
|
||||
"274,224,277,255,307,254,307,244,290,244,291,221,274,224,274,224", "LA",
|
||||
"471,79,488,88", "MA",
|
||||
"442,82,442,89,458,84,464,89,466,87,457,79,442,82,442,82", "MA",
|
||||
"465,142,483,153", "MD",
|
||||
"397,128,426,122,432,135,437,136,431,142,419,138,420,128,411,128,409,126,397,129,397,128", "MD",
|
||||
"462,27,457,52,461,64,476,38,469,25,462,27,462,27", "ME",
|
||||
"309,56,361,61,359,107,331,110,309,56,309,56", "MI",
|
||||
"243,36,250,92,277,92,268,65,283,46,243,36,243,36", "MN",
|
||||
"260,134,267,173,308,173,283,133,260,134,260,134", "MO",
|
||||
"322,196,321,240,299,237,301,204,322,196,322,196", "MS",
|
||||
"96,22,111,64,176,73,180,33,96,22,96,22", "MT",
|
||||
"388,171,374,181,415,186,423,166,388,171,388,171", "NC",
|
||||
"189,33,186,59,240,63,236,36,189,33,189,33", "ND",
|
||||
"184,104,182,119,200,121,200,134,248,135,237,108,184,104,184,104", "NE",
|
||||
"453,51,459,74,449,79,450,61,452,60,452,51,453,51,453,51", "NH",
|
||||
"435,27,452,36", "NH",
|
||||
"432,102,431,109,436,114,431,121,437,125,441,111,437,111,438,103,432,102,432,102", "NJ",
|
||||
"132,170,125,221,176,227,180,174,132,170,132,170", "NM",
|
||||
"45,93,37,122,72,173,82,102,45,93,45,93", "NV",
|
||||
"433,59,439,77,440,99,430,98,429,91,391,100,401,87,417,78,419,63,433,59", "NY",
|
||||
"450,99,440,106,445,109,455,100,450,99", "NY",
|
||||
"379,112,350,116,352,139,368,143,381,127,379,112,379,112", "OH",
|
||||
"186,172,186,175,212,177,214,201,259,207,259,174,186,172,186,172", "OK",
|
||||
"27,42,13,75,64,91,72,51,27,42,27,42", "OR",
|
||||
"386,106,388,125,428,117,425,99,386,106,386,106", "PA",
|
||||
"421,229,485,260", "PR",
|
||||
"472,100,482,110", "RI",
|
||||
"458,86,457,94,461,89,458,86", "RI",
|
||||
"375,191,395,210,410,193,375,191,375,191", "SC",
|
||||
"187,69,183,97,240,101,241,71,187,69,187,69", "SD",
|
||||
"315,180,311,190,355,188,372,172,315,180,315,180", "TN",
|
||||
"188,180,183,235,151,230,174,258,184,250,202,254,223,292,242,263,266,252,266,216,204,205,207,181,188,180,188,180", "TX",
|
||||
"97,103,86,153,126,160,131,120,112,119,114,106,97,103,97,103", "UT",
|
||||
"411,135,383,163,425,158,411,135,411,135", "VA",
|
||||
"454,272,481,307", "VI",
|
||||
"416,34,430,43", "VT",
|
||||
"437,58,442,80,446,79,447,54,437,58,437,58", "VT",
|
||||
"41,6,82,17,75,45,34,37,41,6,41,6", "WA",
|
||||
"282,62,283,81,293,87,297,103,313,102,308,66,282,62,282,62", "WI",
|
||||
"385,133,374,148,383,156,401,133,385,133,385,133", "WV",
|
||||
"126,73,122,111,174,120,178,80,126,73,126,73", "WY",
|
||||
);
|
||||
|
||||
while (my ($coords, $state) = splice(@shapes, 0, 2))
|
||||
{
|
||||
next unless ($count{'stateus'}->{$state});
|
||||
my $shape = "poly";
|
||||
if ($coords =~ /^[^,]+,[^,]+,[^,]+,[^,]+$/) { $shape = "RECTANGLE"; }
|
||||
$ret .= "<area shape='$shape' alt='$state' coords=\"$coords\" href=\"/directory.bml?loc_cn=US&loc_st=$state&opt_sort=ut\" onmouseover=\"updateStatus('";
|
||||
$ret .= BML::eall($state{$state});
|
||||
$ret .= " - ";
|
||||
$ret .= ($count{'stateus'}->{$state}+0);
|
||||
$s = $count{'stateus'}->{$state} != 1 ? "s" : "";
|
||||
$ret .= " Journal$s'); return true;\" onmouseout=\"updateStatus(''); return true;\" />\n";
|
||||
}
|
||||
|
||||
$ret .= "</map>\n";
|
||||
|
||||
# by country
|
||||
$ret .= "<?h1 $ML{'.browse.country.title'} h1?><?p $ML{'.browse.country.desc'} p?>";
|
||||
$ret .= "<table style='margin-left: 20px' cellpadding='5'><tr valign='top'><td align='left'><ul>";
|
||||
my $total = scalar(keys %{$count{'country'}});
|
||||
my $count = 0;
|
||||
my $col = 0;
|
||||
foreach (sort { $country{$a} cmp $country{$b} } keys %{$count{'country'}})
|
||||
{
|
||||
$count++;
|
||||
$ret .= "<li><a href=\"/directory.bml?loc_cn=$_&opt_sort=ut\">$country{$_}</a> <i>($count{'country'}->{$_})</i></li>\n";
|
||||
if ($col==0 && $count > ($total/2)) { $ret .= "</ul></td><td align='left'><ul>"; $col = 1; }
|
||||
}
|
||||
$ret .= "</ul></td></tr></table>\n";
|
||||
return $ret;
|
||||
}
|
||||
|
||||
my $remote = LJ::get_remote();
|
||||
|
||||
unless (LJ::check_priv($remote, "betatest", "directory") ||
|
||||
LJ::get_cap($remote, "directory") ||
|
||||
(@filters == 1 && $filters[0] eq "int" && $GET{'opt_format'} eq "simple"))
|
||||
{
|
||||
return $ML{'.error.accounttype'};
|
||||
}
|
||||
|
||||
unless (LJ::Dir::do_search($dbr, $dbdir, \%FORM, \@matches, \%info)) {
|
||||
return "<?h1 $ML{'Error'} h1?><?p $ML{'Error'}: $info{'errmsg'} p?>";
|
||||
}
|
||||
|
||||
# opt_format and opt_sort might've been modified by do_search,
|
||||
# filling in appropriate defaults based on other parameters
|
||||
my $opt_format = $FORM{'opt_format'};
|
||||
my $opt_sort = $FORM{'opt_sort'};
|
||||
|
||||
$info{'allwhat'} ||= "users";
|
||||
|
||||
if ($info{'searching'}) {
|
||||
my ($uri, $args) = (BML::get_uri(), BML::get_query_string());
|
||||
$uri .= '?' . $args if $args;
|
||||
$head .= "<meta http-equiv='Refresh' content='3;URL=" . LJ::ehtml($LJ::SITEROOT . $uri) . "' />\n";
|
||||
return "<center><b>$ML{'.search.title'}<img src='$LJ::IMGPREFIX/searchingdots.gif' alt='...' width='18' height='12' /></b><p>$ML{'.search.monkey'}</p></center>";
|
||||
}
|
||||
|
||||
if ($POST{'com_do'} || $GET{'com_do'}) {
|
||||
$ret .= "<a href=\"/community/search.bml\"><< $ML{'.search.new'}</a><p>\n";
|
||||
} else {
|
||||
$ret .= "<a href=\"/directorysearch.bml\"><< $ML{'.search.new'}</a><p>\n";
|
||||
}
|
||||
unless (@{$info{'english'}}) {
|
||||
push @{$info{'english'}}, "wish to be listed in the public directory";
|
||||
}
|
||||
|
||||
$ret .= "Below are all $info{'allwhat'} that ";
|
||||
|
||||
my $count_preds = @{$info{'english'}};
|
||||
|
||||
### remove consecutive "are"s
|
||||
my $last_are = 0;
|
||||
foreach (@{$info{'english'}}) {
|
||||
if (/^are /) {
|
||||
if ($last_are) {
|
||||
s/^are //;
|
||||
}
|
||||
$last_are = 1;
|
||||
} else {
|
||||
$last_are = 0;
|
||||
}
|
||||
}
|
||||
my $last = pop @{$info{'english'}};
|
||||
if (@{$info{'english'}}) {
|
||||
$ret .= join(", ", map { LJ::ehtml($_) } @{$info{'english'}}) . ", and ";
|
||||
}
|
||||
$ret .= LJ::ehtml($last) . ".\n";
|
||||
|
||||
if ($info{'overflow'}) {
|
||||
$ret .= BML::ml(".search.overflow", {'count' => $info{'count'}});
|
||||
}
|
||||
|
||||
if ($count_preds == 1 && $GET{'int_like'}) {
|
||||
my $intid = $dbr->selectrow_array("SELECT intid FROM interests WHERE interest=?",
|
||||
undef, $GET{'int_like'});
|
||||
LJ::run_hooks("interests_bml", {
|
||||
'intid' => $intid,
|
||||
'int' => $interest,
|
||||
'ret' => \$ret,
|
||||
}) if $intid;
|
||||
}
|
||||
|
||||
########## make the navcrap
|
||||
my $navcrap;
|
||||
$navcrap .= "<?standout <CENTER><FONT FACE=\"Arial,Helvetica\" SIZE=-1><B>".BML::ml(".navcrap.matches", {'count' => $info{'count'}})."</B>";
|
||||
if ($info{'count'}) {
|
||||
if ($info{'pages'} > 1) {
|
||||
$navcrap .= "<BR>";
|
||||
$navcrap .= BML::ml(".navcrap.xofy", {'curpage' => $info{'page'}, 'totpages' => $info{'pages'}, 'reca' => $info{'first'}, 'recb' => $info{'last'}});
|
||||
$navcrap .= "<BR>";
|
||||
my $left = "<B><<</B>";
|
||||
if ($info{'page'} > 1) { $left = "<A HREF=\"" . BML::self_link({ 'page' => $info{'page'}-1 }) . "\">$left</A>"; }
|
||||
my $right = "<B>>></B>";
|
||||
if ($info{'page'} < $info{'pages'}) { $right = "<A HREF=\"" . BML::self_link({ 'page' => $info{'page'}+1 }) . "\">$right</A>"; }
|
||||
$navcrap .= $left . " ";
|
||||
for (my $i=1; $i<=$info{'pages'}; $i++) {
|
||||
my $link = "[$i]";
|
||||
if ($i != $info{'page'}) { $link = "<A HREF=\"" . BML::self_link({ 'page' => $i }) . "\">$link</A>"; }
|
||||
else { $link = "<FONT SIZE=+1><B>$link</B></FONT>"; }
|
||||
$navcrap .= "$link ";
|
||||
}
|
||||
$navcrap .= "$right";
|
||||
}
|
||||
$navcrap .= "</FONT></CENTER> standout?>\n";
|
||||
} else {
|
||||
$navcrap .= "</CENTER> standout?>\n";
|
||||
}
|
||||
####### end navcrap
|
||||
|
||||
$ret .= $navcrap . "<P>";
|
||||
|
||||
unless ($info{'count'}) { return $ret; }
|
||||
|
||||
if ($opt_sort eq "loc") {
|
||||
LJ::load_codes({ state => \%state, country => \%country });
|
||||
}
|
||||
|
||||
if ($opt_format eq "simple")
|
||||
{
|
||||
my $showloc = $GET{'opt_sort'} eq "loc" ? 1 : 0;
|
||||
my %last = ();
|
||||
$ret .= "<ul>\n";
|
||||
foreach my $rec (@matches)
|
||||
{
|
||||
if ($showloc) {
|
||||
if ($last{'country'} ne $rec->{'country'} ||
|
||||
$last{'state'} ne $rec->{'state'} ||
|
||||
$last{'city'} ne $rec->{'city'}) {
|
||||
foreach (qw(country state city)) { $last{$_} = $rec->{$_}; }
|
||||
my $country = $country{$rec->{'country'}};
|
||||
my ($state, $city);
|
||||
if ($rec->{'state'}) {
|
||||
$state = ", " . ($rec->{'country'} eq "US" ? $state{$rec->{'state'}} : $rec->{'state'});
|
||||
}
|
||||
if ($rec->{'city'}) {
|
||||
$city = ", $rec->{'city'}";
|
||||
}
|
||||
$ret .= "<?h1 $country$state$city h1?><BR>";
|
||||
}
|
||||
}
|
||||
|
||||
$ret .= "<a href=\"/userinfo.bml?user=$rec->{'user'}\">";
|
||||
if ($rec->{'journaltype'} eq "C") {
|
||||
$ret .= "<img border='0' src=\"$LJ::IMGPREFIX/community.gif\" width='16' height='16' align='absmiddle'>";
|
||||
} else {
|
||||
$ret .= "<img border='0' src=\"$LJ::IMGPREFIX/userinfo.gif\" width='17' height='17' align='absmiddle'>";
|
||||
}
|
||||
$ret .= "</a> ";
|
||||
$ret .= "<a href=\"/users/$rec->{'user'}/\">$rec->{'user'}</A> - <b>" . LJ::ehtml($rec->{'name'}) . "</b>, <font size='-1' face=\"Arial\"><i>Updated ";
|
||||
$ret .= LJ::ago_text($rec->{'secondsold'});
|
||||
$ret .= "</i></font><br />\n";
|
||||
}
|
||||
$ret .= "</ul>\n";
|
||||
}
|
||||
|
||||
if ($opt_format eq "com")
|
||||
{
|
||||
$ret .= "<TABLE CELLSPACING=3>\n";
|
||||
$ret .= "<TR><TD> </TD><TD><B>$ML{'.user'}</B></TD><TD><B>$ML{'.community'}</B></TD><TD><B>$ML{'.open'}</B></TD><TD><B>$ML{'.post'}</B></TD></TR>\n";
|
||||
foreach my $rec (@matches)
|
||||
{
|
||||
$ret .= "<TR VALIGN=TOP>";
|
||||
$ret .= "<TD NOWRAP><A HREF=\"/userinfo.bml?user=$rec->{'user'}\">";
|
||||
if ($rec->{'journaltype'} eq "C") {
|
||||
$ret .= "<IMG BORDER=0 SRC=\"$LJ::IMGPREFIX/community.gif\" WIDTH=16 HEIGHT=16 ALIGN=ABSMIDDLE>";
|
||||
} else {
|
||||
$ret .= "<IMG BORDER=0 SRC=\"$LJ::IMGPREFIX/userinfo.gif\" WIDTH=17 HEIGHT=17 ALIGN=ABSMIDDLE>";
|
||||
}
|
||||
$ret .= "</A></TD>";
|
||||
$ret .= "<TD><B><A HREF=\"/community/$rec->{'user'}/\">$rec->{'user'}</A></B></TD>";
|
||||
$ret .= "<td>" . LJ::ehtml($rec->{'name'}) . "</td>";
|
||||
|
||||
my $color;
|
||||
if ($rec->{'membership'} eq "open") { $color = "green"; } else { $color = "red"; }
|
||||
$ret .= "<TD ALIGN=CENTER><IMG SRC=\"$LJ::IMGPREFIX/dot_$color.gif\" WIDTH=14 HEIGHT=14></TD>";
|
||||
if ($rec->{'postlevel'} eq "members") { $color = "green"; } else { $color = "red"; }
|
||||
$ret .= "<TD ALIGN=CENTER><IMG SRC=\"$LJ::IMGPREFIX/dot_$color.gif\" WIDTH=14 HEIGHT=14></TD>";
|
||||
|
||||
$ret .= "</TR>";
|
||||
}
|
||||
$ret .= "</TABLE>\n";
|
||||
}
|
||||
|
||||
if ($opt_format eq "pics")
|
||||
{
|
||||
my $showloc = $GET{'opt_sort'} eq "loc" ? 1 : 0;
|
||||
my %last = ();
|
||||
|
||||
my %pic;
|
||||
my @picids = map { [$_, $_->{'defaultpicid'}] } @matches;
|
||||
LJ::load_userpics(\%pic, \@picids);
|
||||
|
||||
my $count = 0;
|
||||
my $pos = 0;
|
||||
my $more_to_show = 0;
|
||||
$ret .= "<TABLE CELLPADDING=3>\n";
|
||||
foreach my $rec (@matches)
|
||||
{
|
||||
if ($pos==5) { $ret .= "</TR>\n"; }
|
||||
$pos++; $pos %= 5;
|
||||
|
||||
if ($showloc) {
|
||||
if ($last{'country'} ne $rec->{'country'} ||
|
||||
$last{'state'} ne $rec->{'state'} ||
|
||||
$last{'city'} ne $rec->{'city'}) {
|
||||
foreach (qw(country state city)) { $last{$_} = $rec->{$_}; }
|
||||
my $country = $country{$rec->{'country'}};
|
||||
my ($state, $city);
|
||||
if ($rec->{'state'}) {
|
||||
$state = ", " . ($rec->{'country'} eq "US" ? $state{$rec->{'state'}} : $rec->{'state'});
|
||||
}
|
||||
if ($rec->{'city'}) {
|
||||
$city = ", $rec->{'city'}";
|
||||
}
|
||||
if ($pos > 1) { $ret .= "</TR>"; $pos = 1; }
|
||||
$ret .= "</TABLE>";
|
||||
$ret .= "<?h1 $country$state$city h1?><BR>";
|
||||
$ret .= "<TABLE CELLPADDING=3>\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ($pos==1) { $ret .= "<TR ALIGN=CENTER VALIGN=BOTTOM>\n"; }
|
||||
my $picid = $rec->{'defaultpicid'};
|
||||
my $updateago = LJ::ago_text($rec->{'secondsold'});
|
||||
my $img;
|
||||
if ($picid) {
|
||||
$img = "<IMG SRC=\"$LJ::USERPIC_ROOT/$picid/$rec->{'userid'}\" ALT=\"$_->{'user'}\" WIDTH=$pic{$picid}->{'width'} HEIGHT=$pic{$picid}->{'height'} BORDER=0><BR>";
|
||||
}
|
||||
$ret .= "<TD>";
|
||||
$ret .= $img;
|
||||
$ret .= LJ::ljuser($rec->{'user'});
|
||||
$ret .= "<BR><FONT SIZE=-1><B>$Ml{'.update'} </B> $updateago</FONT></TD>\n";
|
||||
}
|
||||
$ret .= "</TR></TABLE>\n";
|
||||
}
|
||||
|
||||
if ($info{'pages'} > 1) { $ret .= $navcrap; }
|
||||
return $ret;
|
||||
|
||||
|
||||
_code?>
|
||||
|
||||
<=body
|
||||
head<=
|
||||
<meta name="robots" content="noindex,nofollow" />
|
||||
<?_code return $head; _code?>
|
||||
<=head
|
||||
page?>
|
||||
205
livejournal/htdocs/directorysearch.bml
Executable file
@@ -0,0 +1,205 @@
|
||||
<?_info
|
||||
localblocks<=
|
||||
crit<=
|
||||
{FpRs}<tr bgcolor='<?emcolor?>'>
|
||||
<td align='left' colspan='2'><b>%%name%%</b>
|
||||
</tr>
|
||||
<tr align='left'><td> </td><td>%%form%%</td></tr>
|
||||
<=crit
|
||||
bar<=
|
||||
{FpRs}<tr bgcolor='<?emcolor?>' align='left'>
|
||||
<td> </td>
|
||||
<td><b>%%name%%</b></td>
|
||||
</tr>
|
||||
<tr align='left'><td> </td><td>%%form%%</td></tr>
|
||||
<=bar
|
||||
<=localblocks
|
||||
_info?><?page
|
||||
title=>Directory Search
|
||||
body<=
|
||||
<?_code
|
||||
LJ::set_active_crumb('advsearch');
|
||||
_code?>
|
||||
|
||||
<?h1 Search Directory h1?>
|
||||
<?p
|
||||
Fill in criteria below that you'd like to find user journals by. The results returned are the intersection of all search criteria. In other words, each restriction means "AND", not "OR".
|
||||
p?>
|
||||
|
||||
<center>
|
||||
|
||||
<form style='margin-top: 1.5em' action='/directory.bml' method='get'>
|
||||
|
||||
<table cellpadding='4' cellspacing='0' border='0'>
|
||||
|
||||
<!--- location --->
|
||||
<?crit
|
||||
name=>By Location
|
||||
code=>s_loc
|
||||
form<=
|
||||
|
||||
<table>
|
||||
<tr><td align='right'>Country:</td><td align='left'>
|
||||
<?_code
|
||||
|
||||
LJ::load_codes({ "country" => \%countries });
|
||||
return LJ::html_select({
|
||||
'name' => 'loc_cn',
|
||||
}, "", "", map { $_, $countries{$_} } "US", sort { $countries{$a} cmp $countries{$b} } keys %countries);
|
||||
|
||||
_code?>
|
||||
</td></tr>
|
||||
<tr><td align='right'>State/Province:</td><td align='left'><input name="loc_st" /></td></tr>
|
||||
<tr><td align='right'>City:</td><td align='left'><input name="loc_ci" /></td></tr>
|
||||
</table>
|
||||
|
||||
<=form
|
||||
crit?>
|
||||
|
||||
<!---- update time ----->
|
||||
<?crit
|
||||
name=>By Journal Update Time
|
||||
code=>s_ut
|
||||
form<=
|
||||
Updated in last
|
||||
<select name="ut_days">
|
||||
<option value="">-------</option>
|
||||
<option value="1">day</option>
|
||||
<option value="7">week</option>
|
||||
<option value="30">month</option>
|
||||
</select>
|
||||
<=form
|
||||
crit?>
|
||||
|
||||
<!---- age ----->
|
||||
<?crit
|
||||
name=>By Age
|
||||
code=>s_age
|
||||
form<=
|
||||
Between
|
||||
<input name="age_min" size='3' maxlength='3' /> and
|
||||
<input name="age_max" size='3' maxlength='3' /> years old.
|
||||
<=form
|
||||
crit?>
|
||||
|
||||
<?_c DISABLED because of privacy policy. add later when 'public gender' option
|
||||
<!---- gender ----->
|
||||
<?crit
|
||||
name=>By Gender
|
||||
code=>s_gen
|
||||
form<=
|
||||
User is: <select name="gen_sel">
|
||||
<option></option>
|
||||
<option value="M">Male</option>
|
||||
<option value="F">Female</option>
|
||||
</select>
|
||||
<=form
|
||||
crit?>
|
||||
_c?>
|
||||
|
||||
<!---- interest ----->
|
||||
<?crit
|
||||
name=>By Interest
|
||||
code=>s_int
|
||||
form<=
|
||||
User likes: <input name="int_like" size='30' />
|
||||
<=form
|
||||
crit?>
|
||||
|
||||
<!---- has friend ----->
|
||||
<?crit
|
||||
name=>Has Friend
|
||||
code=>s_fr
|
||||
form<=
|
||||
User lists <input name="fr_user" size='15' maxlength='15' /> as a friend.
|
||||
<=form
|
||||
crit?>
|
||||
|
||||
<!---- friend of ----->
|
||||
<?crit
|
||||
name=>Friend of
|
||||
code=>s_fro
|
||||
form<=
|
||||
<input name="fro_user" size='15' maxlength='15' /> lists user as a friend.
|
||||
<=form
|
||||
crit?>
|
||||
|
||||
<?_c dead for now
|
||||
<!---- client used ----->
|
||||
<?crit
|
||||
name=>Client Usage
|
||||
code=>s_client
|
||||
form<=
|
||||
Has used update client named: <input name="client_match" SIZE='20' />
|
||||
<=form
|
||||
crit?>
|
||||
_c?>
|
||||
|
||||
<?_c no index on this yet. need a userprop boolean.
|
||||
<!----- other ------>
|
||||
<?bar
|
||||
name=>Other Criteria
|
||||
form<=
|
||||
<input type='checkbox' name="s_withpic" value='1' /> Only users with pictures
|
||||
<=form
|
||||
bar?>
|
||||
_c?>
|
||||
|
||||
<!---- output formatting ----->
|
||||
<?bar
|
||||
name=>Display Options
|
||||
form<=
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td align='right'>
|
||||
Output Format:
|
||||
</td><td>
|
||||
<select name="opt_format">
|
||||
<option value="pics">By Picture</option>
|
||||
<option value="simple">Simple</option>
|
||||
</select>
|
||||
</td></tr>
|
||||
|
||||
<tr>
|
||||
<td align='right'>
|
||||
Sorting Method:
|
||||
</td><td>
|
||||
<select name="opt_sort">
|
||||
<option value="ut">Update Time</option>
|
||||
<option value="user">User Name</option>
|
||||
<option value="loc">Location</option>
|
||||
</select>
|
||||
</td></tr>
|
||||
|
||||
<tr>
|
||||
<td align='right'>
|
||||
Records per page:
|
||||
</td><td>
|
||||
<select name="opt_pagesize">
|
||||
<option value="25">25</option>
|
||||
<option value="50">50</option>
|
||||
<option value="100" selected='selected'>100</option>
|
||||
<option value="200">200</option>
|
||||
</select>
|
||||
</td></tr>
|
||||
|
||||
</table>
|
||||
<=form
|
||||
bar?>
|
||||
|
||||
<!--- submit --->
|
||||
<tr bgcolor='<?emcolor?>'><td colspan='2' align='center'>
|
||||
<input type='submit' value="Search!" />
|
||||
<input type='reset' value="Clear Form" />
|
||||
</td></tr>
|
||||
|
||||
</table>
|
||||
</form>
|
||||
|
||||
</center>
|
||||
|
||||
<=body
|
||||
page?><?_c <LJDEP>
|
||||
form: htdocs/directory.bml
|
||||
</LJDEP> _c?>
|
||||
3
livejournal/htdocs/doc/.placeholder
Executable file
@@ -0,0 +1,3 @@
|
||||
This file exists to make sure the directory is created.
|
||||
Other things (like doc/raw/build/generate.pl) depend
|
||||
on this directory existing, and populating into it.
|
||||
886
livejournal/htdocs/editinfo.bml
Executable file
@@ -0,0 +1,886 @@
|
||||
<?page
|
||||
title=><?_ml .title _ml?>
|
||||
body<=
|
||||
<?_code
|
||||
LJ::set_active_crumb('editinfo');
|
||||
return;
|
||||
_code?>
|
||||
|
||||
<?_code
|
||||
{
|
||||
use strict;
|
||||
use vars qw(%POST %GET);
|
||||
|
||||
return LJ::server_down_html() if $LJ::SERVER_DOWN;
|
||||
|
||||
my $remote = LJ::get_remote();
|
||||
return LJ::bad_input("You must be logged in to edit your info.")
|
||||
unless $remote;
|
||||
|
||||
if ($remote->underage) {
|
||||
return BML::redirect("$LJ::SITEROOT/agecheck/?s=1");
|
||||
}
|
||||
|
||||
my $authas = $GET{'authas'} || $remote->{'user'};
|
||||
my $u = LJ::get_authas_user($authas);
|
||||
return LJ::bad_input("You could not be authenticated as the specified user.")
|
||||
unless $u;
|
||||
|
||||
return $LJ::MSG_READONLY_USER if $u->readonly;
|
||||
|
||||
# extra arguments for get requests
|
||||
my $getextra = $authas ne $remote->{'user'} ? "?authas=$authas" : '';
|
||||
|
||||
### user is now authenticated ###
|
||||
|
||||
my $dbr = LJ::get_db_reader();
|
||||
my $sth;
|
||||
|
||||
# load user props
|
||||
LJ::load_user_props($u, { use_master => 1 }, "opt_whatemailshow",
|
||||
"country", "state", "city",
|
||||
"zip", "icq", "aolim", "yahoo", "msn", "url",
|
||||
"urlname", "gender", "jabber", "opt_blockrobots",
|
||||
"opt_logcommentips",
|
||||
"howhear", "opt_bdaymail", "opt_hidefriendofs",
|
||||
"sidx_bdate", "sidx_loc", "mailencoding", "opt_nctalklinks",
|
||||
"opt_whoscreened", "journaltitle", "journalsubtitle",
|
||||
"friendspagetitle", "opt_weblogscom", "opt_stylemine",
|
||||
"opt_imagelinks", "opt_getselfemail", "external_foaf_url",
|
||||
"opt_showmutualfriends",
|
||||
);
|
||||
|
||||
# to store values before they undergo normalisation
|
||||
my %saved = ();
|
||||
$saved{'name'} = $u->{'name'};
|
||||
|
||||
# clean userprops
|
||||
foreach (values %$u) { LJ::text_out(\$_); }
|
||||
|
||||
# load and clean bio
|
||||
$u->{'bio'} = LJ::get_bio($u);
|
||||
$saved{'bio'} = $u->{'bio'};
|
||||
LJ::text_out(\$u->{'bio'}, "force");
|
||||
|
||||
# load interests
|
||||
my $uints = LJ::get_interests($u, { forceids => 1 });
|
||||
my %interests = ();
|
||||
foreach (@$uints) {
|
||||
$interests{$_->[1]} = $_->[0]; # $interests{name} = intid
|
||||
}
|
||||
|
||||
# load state and country codes
|
||||
my %countries;
|
||||
my %states;
|
||||
LJ::load_codes({ "country" => \%countries, "state" => \%states });
|
||||
|
||||
|
||||
###
|
||||
### no post, show edit form
|
||||
###
|
||||
|
||||
unless (LJ::did_post()) {
|
||||
|
||||
my $ret;
|
||||
|
||||
# user switcher
|
||||
$ret .= "<form method='get' action='editinfo.bml'>\n";
|
||||
$ret .= LJ::make_authas_select($remote, { 'authas' => $GET{'authas'} });
|
||||
$ret .= "</form>\n\n";
|
||||
|
||||
$ret .= "<form method='post' action='editinfo.bml$getextra'>\n";
|
||||
$ret .= LJ::form_auth();
|
||||
|
||||
# personal information
|
||||
$ret .= "<?h1 $ML{'.persinfo.header'} h1?><?p $ML{'.persinfo.disclaimer'} p?>\n";
|
||||
|
||||
$ret .= "<table width='100%'>\n";
|
||||
|
||||
# name
|
||||
$ret .= "<tr><td align='right' bgcolor='<?emcolor?>'>$ML{'.name.title'}</td>";
|
||||
if (LJ::text_in($saved{'name'})) {
|
||||
$ret .= "<td>" . LJ::html_text({ 'name' => 'name', 'value' => $u->{'name'},
|
||||
'maxlength' => '50' }) . "</td></tr>\n";
|
||||
} else {
|
||||
$ret .= "<td>" . LJ::html_hidden('name_absent', 'yes');
|
||||
$ret .= "<?inerr $ML{'.error.invalidname'} inerr?></td></tr>\n";
|
||||
}
|
||||
|
||||
# birthday
|
||||
$ret .= "<tr><td align='right' bgcolor='<?emcolor?>'>$ML{'.bday.title'}</td><td>";
|
||||
my %bdpart;
|
||||
if ($u->{'bdate'} =~ /^(\d\d\d\d)-(\d\d)-(\d\d)$/) {
|
||||
($bdpart{'year'}, $bdpart{'month'}, $bdpart{'day'}) = ($1, $2, $3);
|
||||
if ($bdpart{'year'} eq "0000") { $bdpart{'year'} = ""; }
|
||||
if ($bdpart{'day'} eq "00") { $bdpart{'day'} = ""; }
|
||||
}
|
||||
$ret .= LJ::html_select({ 'name' => 'month', 'selected' => int($bdpart{'month'}) },
|
||||
'', '', map { $_, $ML{LJ::Lang::month_long_langcode($_)} } (1..12)) . " ";
|
||||
|
||||
$ret .= LJ::html_text({ 'name' => 'day', 'value' => $bdpart{'day'}, 'size' => '3', 'maxlength' => '2' }) . " ";
|
||||
$ret .= LJ::html_text({ 'name' => 'year', 'value' => $bdpart{'year'}, 'size' => '5', 'maxlength' => '4' });
|
||||
$ret .= " ($ML{'.bday.year.opt'})";
|
||||
|
||||
$ret .= "</td></tr>\n";
|
||||
|
||||
# gender
|
||||
$ret .= "<tr><td align='right' bgcolor='<?emcolor?>'>$ML{'.gender.title'}</td><td>";
|
||||
$ret .= LJ::html_select({ 'name' => 'gender', 'selected' => $u->{'gender'} },
|
||||
'U' => "(Unspecified)", 'M' => "Male", 'F' => "Female" );
|
||||
$ret .= "</td></tr>\n";
|
||||
|
||||
# email
|
||||
$ret .= "<tr><td align='right' bgcolor='<?emcolor?>'>$ML{'.email.title'}</td><td>";
|
||||
$ret .= LJ::html_text({ 'name' => 'email', 'value' => $u->{'email'}, 'size' => '40', 'maxlength' => '50' });
|
||||
$ret .= "</td></tr>\n";
|
||||
|
||||
# url
|
||||
$ret .= "<tr><td align='right' bgcolor='<?emcolor?>'>$ML{'.webpageurl.title'}</td><td>";
|
||||
$ret .= LJ::html_text({ 'name' => 'url', 'value' => $u->{'url'}, 'size' => '40', 'maxlength' => '255' });
|
||||
$ret .= " ($ML{'.optional'})</td></tr>\n";
|
||||
|
||||
# urlname
|
||||
$ret .= "<tr><td align='right' bgcolor='<?emcolor?>'>$ML{'.webpagename.title'}</td><td>";
|
||||
$ret .= LJ::html_text({ 'name' => 'urlname', 'value' => $u->{'urlname'}, 'size' => '40', 'maxlength' => '255' });
|
||||
$ret .= " ($ML{'.optional'})</td></tr>\n";
|
||||
|
||||
# chat thingies
|
||||
foreach my $p (["aolim", $ML{'.chat.aolim.title'}, 28], ["icq", $ML{'.chat.icquin.title'}, 12],
|
||||
["yahoo", $ML{'.chat.yahooid.title'}, 33], ["msn", $ML{'.chat.msnusername.title'}, 60],
|
||||
["jabber", $ML{'.chat.jabber.title'}, 60])
|
||||
{
|
||||
$ret .= "<tr><td align='right' bgcolor='<?emcolor?>'>$p->[1]</td><td>";
|
||||
$ret .= LJ::html_text({ 'name' => $p->[0], 'value' => $u->{$p->[0]}, 'size' => '20', 'maxlength' => $p->[2] });
|
||||
$ret .= " ($ML{'.optional'})</td></tr>\n";
|
||||
}
|
||||
|
||||
# country
|
||||
$ret .= "<tr><td align='right' bgcolor='<?emcolor?>'>$ML{'.country.title'}</td><td>";
|
||||
$ret .= LJ::html_select({ 'name' => 'country', 'selected' => $u->{'country'} },
|
||||
'', $ML{'.country.choose'},
|
||||
'US', 'United States',
|
||||
map { $_, $countries{$_} } sort { $countries{$a} cmp $countries{$b} } keys %countries );
|
||||
$ret .= "</td></tr>\n";
|
||||
|
||||
# city
|
||||
$ret .= "<tr><td align='right' bgcolor='<?emcolor?>'>$ML{'.city.title'}</td><td>";
|
||||
$ret .= LJ::html_text({ 'name' => 'city', 'value' => $u->{'city'}, 'size' => '20', 'maxlength' => '255' });
|
||||
$ret .= "</td></tr>\n";
|
||||
|
||||
# state
|
||||
$ret .= "<tr valign='top'><td align='right' bgcolor='<?emcolor?>'>$ML{'.state.title'}</td><td>";
|
||||
$ret .= LJ::html_select({ 'name' => 'statedrop', 'selected' => $u->{'state'} },
|
||||
'', "($ML{'.state.us'})",
|
||||
map { $_, $states{$_} } sort { $states{$a} cmp $states{$b} } keys %states );
|
||||
|
||||
# other state?
|
||||
$ret .= "<br />$ML{'.state.other'}: ";
|
||||
$ret .= LJ::html_text({ 'name' => 'stateother', 'size' => '20', 'maxlength' => '50',
|
||||
'value' => defined $states{$u->{'state'}} ? '' : $u->{'state'} });
|
||||
$ret .= "</td></tr>\n";
|
||||
|
||||
# zip
|
||||
$ret .= "<tr><td align='right' bgcolor='<?emcolor?>'>$ML{'.zip.title'}</td><td>";
|
||||
$ret .= LJ::html_text({ 'name' => 'zip', 'value' => $u->{'zip'}, 'size' => '6', 'maxlength' => '5' });
|
||||
$ret .= " ($ML{'.zip.usonly'})</td></tr>\n";
|
||||
|
||||
# text messaging
|
||||
if (LJ::get_cap($u, "textmessaging"))
|
||||
{
|
||||
$sth = $dbr->prepare("SELECT provider, number, security FROM txtmsg WHERE userid=?");
|
||||
$sth->execute($u->{'userid'});
|
||||
my $tminfo = $sth->fetchrow_hashref;
|
||||
foreach (values %$tminfo) { LJ::text_out(\$_); }
|
||||
|
||||
# text messaging
|
||||
$ret .= "<tr valign='top'><td align='right' bgcolor='<?emcolor?>'>";
|
||||
$ret .= LJ::help_icon('textmessage', "", " ");
|
||||
$ret .= "$ML{'.tm.title'}</td><td>\n<table>\n<tr><td>";
|
||||
$ret .= LJ::html_check({ 'type' => 'check', 'name' => 'use_txtmsg', 'id' => 'use_txtmsg',
|
||||
'selected' => $u->{'txtmsg_status'} eq 'on' });
|
||||
|
||||
$ret .= "</td><td colspan='2'><b><label for='use_txtmsg'>$ML{'.tm.sec.about'}</label></b></td></tr>\n";
|
||||
$ret .= "<tr><td rowspan='3'> </td><td>$ML{'.tm.sec.title'}</td><td>";
|
||||
|
||||
$ret .= LJ::html_select({ 'name' => 'txtmsg_security', 'selected' => $tminfo->{'security'} },
|
||||
"all" => BML::ml(".security.visibility.anybody"),
|
||||
"reg" => BML::ml(".security.visibility.regusers"),
|
||||
"friends" => BML::ml(".security.visibility.friends") );
|
||||
$ret .= "</td></tr>\n";
|
||||
$ret .= "<tr><td>$ML{'.tm.servprov'}</td><td>";
|
||||
{
|
||||
my @opts = ("", "");
|
||||
foreach my $p (LJ::TextMessage::providers()) {
|
||||
my $info = LJ::TextMessage::provider_info($p);
|
||||
push @opts, ($p, $info->{'name'});
|
||||
}
|
||||
$ret .= LJ::html_select({ 'name' => 'txtmsg_provider',
|
||||
'selected' => $tminfo->{'provider'}, },
|
||||
@opts);
|
||||
}
|
||||
|
||||
$ret .= " ($ML{'.tm.details'})</td></tr>\n";
|
||||
$ret .= "<tr><td>$ML{'.tm.phonenum'}</td><td>";
|
||||
$ret .= LJ::html_text({ 'name' => 'txtmsg_number', 'value' => $tminfo->{'number'},
|
||||
'size' => '15', 'maxlength' => '40' });
|
||||
$ret .= "</td></tr>\n";
|
||||
$ret .= "</table>\n</td></tr>\n";
|
||||
}
|
||||
|
||||
# end personal info
|
||||
$ret .= "</table>\n\n";
|
||||
|
||||
### User bio
|
||||
$ret .= "<?h1 $ML{'.bio.header'} h1?><?p $ML{'.bio.about'} p?>";
|
||||
if (LJ::text_in($saved{'bio'})) {
|
||||
$ret .= "<div style='margin-left: 30px; margin-bottom: 20px'>";
|
||||
$ret .= LJ::html_textarea({ 'name' => 'bio', 'rows' => '10', 'cols' => '50',
|
||||
'wrap' => 'soft', 'value' => $u->{'bio'}, 'style' => "width: 90%", }) . "</div>\n";
|
||||
} else {
|
||||
$ret .= LJ::html_hidden('bio_absent', 'yes');
|
||||
$ret .= "<?p <?inerr $ML{'.error.invalidbio'} inerr?> p?>\n";
|
||||
}
|
||||
|
||||
### How heard Settings
|
||||
unless ($u->{'howhear'}) {
|
||||
$ret .= "<?h1 $ML{'.howhear.header'} h1?>\n";
|
||||
$ret .= "<?p " . BML::ml(".howhear.about", { 'sitename' => $LJ::SITENAME }) . " p?>\n";
|
||||
$ret .= "<div style='margin-left: 30px; margin-bottom: 20px;'>";
|
||||
$ret .= LJ::html_text({ 'name' => 'howhear', 'size' => '60', 'maxlength' => '100' });
|
||||
$ret .= "</div>\n\n";
|
||||
}
|
||||
|
||||
{
|
||||
### Interests
|
||||
$ret .= "<?h1 $ML{'.int.header'} h1?>\n";
|
||||
my @eintsl;
|
||||
foreach (sort keys %interests) {
|
||||
push @eintsl, $_ if LJ::text_in($_);
|
||||
}
|
||||
|
||||
$ret .= "<?p $ML{'.int.about'} p?>";
|
||||
$ret .= "<?p $ML{'.int.ex.good'} p?>";
|
||||
$ret .= "<?p $ML{'.int.ex.bad'} p?>";
|
||||
$ret .= "<div style='margin-left: 30px; margin-bottom: 20px;'>";
|
||||
$ret .= LJ::html_textarea({ 'name' => 'interests', 'value' => join(", ", @eintsl),
|
||||
'rows' => '10', 'cols' => '50', 'wrap' => 'soft' });
|
||||
$ret .= "</div>\n\n";
|
||||
}
|
||||
|
||||
### Picture Settings
|
||||
$ret .= "<?h1 $ML{'.userpic.header'} h1?>\n<?p $ML{'.userpic.about'} p?>\n";
|
||||
$ret .= "<p align='center'>";
|
||||
if ($u->{'defaultpicid'})
|
||||
{
|
||||
my $picid = $u->{'defaultpicid'};
|
||||
my %userpics = ();
|
||||
LJ::load_userpics(\%userpics, [ $u, $picid ]);
|
||||
$ret .= "<a href='editpics.bml$getextra'><img src=\"$LJ::USERPIC_ROOT/$picid/$u->{'userid'}\" width='$userpics{$picid}->{'width'}' height='$userpics{$picid}->{'height'} alt='$u->{'user'}' border='0'></a>";
|
||||
} else
|
||||
{
|
||||
$ret .= "<i>($ML{'.userpic.none'})</i>";
|
||||
}
|
||||
$ret .= "</p><p>$ML{'.userpic.edit'}</p>\n\n";
|
||||
|
||||
|
||||
###
|
||||
### Journal Options
|
||||
###
|
||||
|
||||
$ret .= "<?h1 $ML{'.settings.header'} h1?>\n";
|
||||
|
||||
|
||||
### display options
|
||||
$ret .= "<?p $ML{'.settings.about'} p?>\n";
|
||||
$ret .= "<table style='margin-left: 30px; margin-bottom: 20px'>\n";
|
||||
|
||||
# journaltitle
|
||||
$ret .= "<tr><td><b>$ML{'.settings.journal.title'} </b></td>";
|
||||
$ret .= "<td>" . LJ::html_text({ 'name' => 'journaltitle', 'value' => $u->{'journaltitle'}, 'size' => '30', 'maxlength' => '80' }) . " </td></tr>\n";
|
||||
|
||||
# journalsubtitle
|
||||
$ret .= "<tr><td><b>$ML{'.settings.journal.subtitle'} </b></td>";
|
||||
$ret .= "<td>" . LJ::html_text({ 'name' => 'journalsubtitle', 'value' => $u->{'journalsubtitle'}, 'size' => '30', 'maxlength' => '80' }) . " </td></tr>\n";
|
||||
$ret .= "<tr><td colspan='2'>$ML{'.settings.journal.subtitle.optional'}</td></tr>\n";
|
||||
|
||||
# friendspagetitle
|
||||
$ret .= "<tr><td><b>$ML{'.settings.friendspage.title'} </b></td>";
|
||||
$ret .= "<td>" . LJ::html_text({ 'name' => 'friendspagetitle', 'value' => $u->{'friendspagetitle'}, 'size' => '30', 'maxlength' => '80' }) . "</td></tr>\n";
|
||||
$ret .= "<tr><td colspan='2'>$ML{'.settings.friendspage.title.optional'}</td></tr>\n";
|
||||
$ret .= "</table>\n\n";
|
||||
|
||||
### privacy options
|
||||
$ret .= "<?h2 $ML{'.settings.privacy.header'} h2?><?p $ML{'.settings.privacy.about'} p?>\n";
|
||||
$ret .= "<table style='margin: 10px 0 20px 30px'>\n";
|
||||
|
||||
# allow_contactshow
|
||||
$ret .= "<tr valign=middle><td>";
|
||||
$ret .= LJ::html_check({ 'type' => 'check', 'name' => 'allow_contactshow', 'id' => 'allow_contactshow',
|
||||
'selected' => $u->{'allow_contactshow'} ne 'N' });
|
||||
$ret .= "</td><td><b><label for='allow_contactshow'>$ML{'.allowshowcontact.title'}</label></b></td></tr>\n";
|
||||
$ret .= "<tr><td> </td><td>$ML{'.allowshowcontact.about'}";
|
||||
|
||||
{
|
||||
# contactshow_sec
|
||||
$ret .= "\n<p><b>$ML{'.security.header'}</b> ";
|
||||
$ret .= LJ::html_select({ 'name' => 'contactshow_sec',
|
||||
'selected' => $u->{'allow_contactshow'} },
|
||||
"Y" => BML::ml(".security.visibility.everybody"),
|
||||
"F" => BML::ml(".security.visibility.friends") );
|
||||
$ret .= "</p>\n";
|
||||
|
||||
# opt_whatemailshow
|
||||
$ret .= "<p><b>$ML{'.allowshowcontact.email'}</b>\n";
|
||||
$ret .= "<div style='margin-left: 30px; margin-bottom: 20px;'>";
|
||||
my $cur = $u->{'opt_whatemailshow'} || "N";
|
||||
my @vals = ( ($LJ::USER_EMAIL && LJ::get_cap($u, "useremail"))
|
||||
? ("B" => BML::ml(".allowshowcontact.email.both", { 'domain' => $LJ::USER_DOMAIN}),
|
||||
"A" => BML::ml(".allowshowcontact.email.actual_only"),
|
||||
"L" => BML::ml(".allowshowcontact.email.lj_only"),
|
||||
"N" => BML::ml(".allowshowcontact.email.neither"))
|
||||
: ("A" => BML::ml(".allowshowcontact.email.show"),
|
||||
"N" => BML::ml(".allowshowcontact.email.no_show")));
|
||||
$ret .= LJ::html_select({ 'name' => 'opt_whatemailshow', 'selected' => $cur }, @vals) . "\n";
|
||||
|
||||
$ret .= "<p>" . ($LJ::USER_EMAIL
|
||||
? $ML{'.allowshowcontact.email.withdomainaddr'}
|
||||
: $ML{'.allowshowcontact.email.withoutdomainaddr'}) . "</p>\n</div>\n";
|
||||
|
||||
# opt_mangleemail
|
||||
$ret .= "<table style='margin-bottom: 20px;'>\n<tr valign='middle'><td>";
|
||||
$ret .= LJ::html_check({ 'type' => 'check', 'name' => 'opt_mangleemail', 'id' => 'opt_mangleemail',
|
||||
'selected' => $u->{'opt_mangleemail'} eq 'Y' });
|
||||
$ret .= "</td><td><b><label for='opt_mangleemail'>$ML{'.mangleaddress.header'}</label></b></td></tr>\n";
|
||||
$ret .= "<tr><td> </td><td>$ML{'.mangleaddress.about'}</td></tr>\n</table>\n";
|
||||
|
||||
}
|
||||
$ret .= "</td></tr>\n";
|
||||
|
||||
# allow_infoshow
|
||||
$ret .= "<tr valign='middle'><td>";
|
||||
$ret .= LJ::html_check({ 'type' => 'check', 'name' => 'allow_infoshow', 'id' => 'allow_infoshow',
|
||||
'selected' => $u->{'allow_infoshow'} eq 'Y' });
|
||||
$ret .= "</td><td><b><label for='allow_infoshow'>$ML{'.allowshowinfo.title'}</label></b></td></tr>\n";
|
||||
$ret .= "<tr><td> </td><td>$ML{'.allowshowinfo.about'}</td></tr>\n";
|
||||
|
||||
# opt_blockrobots
|
||||
$ret .= "<tr valign='middle'><td>";
|
||||
$ret .= LJ::html_check({ 'type' => 'check', 'name' => 'opt_blockrobots', 'id' => 'opt_blockrobots',
|
||||
'selected' => $u->{'opt_blockrobots'} });
|
||||
$ret .= "</td><td><b><label for='opt_blockrobots'>$ML{'.blockrobots.header'}</label></b></td></tr>\n";
|
||||
$ret .= "<tr><td> </td><td>$ML{'.blockrobots.about'}</td></tr>\n";
|
||||
|
||||
# opt_weblogscom
|
||||
if (LJ::get_cap($u, "weblogscom")) {
|
||||
$ret .= "<tr valign='middle'><td>";
|
||||
$ret .= LJ::html_check({ 'type' => 'check', 'name' => 'opt_weblogscom', 'id' => 'opt_weblogscom',
|
||||
'selected' => $u->{'opt_weblogscom'} });
|
||||
$ret .= "</td><td><b><label for='opt_weblogscom'>$ML{'.weblogscom.header'}</label></b></td></tr>\n";
|
||||
$ret .= "<tr><td> </td><td>$ML{'.weblogscom.about'}</td></tr>\n";
|
||||
}
|
||||
|
||||
# opt_showmutualfriends
|
||||
$ret .= "<tr valign='middle'><td>";
|
||||
$ret .= LJ::html_check({ 'type' => 'check', 'name' => 'opt_showmutualfriends', 'id' => 'opt_showmutualfriends',
|
||||
'selected' => $u->{'opt_showmutualfriends'} });
|
||||
$ret .= "</td><td><b><label for='opt_showmutualfriends'>$ML{'.mutualfriends.header'}</label></b></td></tr>\n";
|
||||
$ret .= "<tr><td> </td><td>$ML{'.mutualfriends.about'}</td></tr>\n";
|
||||
|
||||
# opt_hidefriendofs
|
||||
$ret .= "<tr valign='middle'><td>";
|
||||
$ret .= LJ::html_check({ 'type' => 'check', 'name' => 'opt_hidefriendofs', 'id' => 'opt_hidefriendofs',
|
||||
'selected' => $u->{'opt_hidefriendofs'} });
|
||||
$ret .= "</td><td><b><label for='opt_hidefriendofs'>$ML{'.hidefriendof.header'}</label></b></td></tr>\n";
|
||||
$ret .= "<tr><td> </td><td>$ML{'.hidefriendof.about'}</td></tr>\n";
|
||||
|
||||
|
||||
# allow_getljnews
|
||||
$ret .= "<tr valign='middle'><td>";
|
||||
$ret .= LJ::html_check({ 'type' => 'check', 'name' => 'allow_getljnews', 'id' => 'allow_getljnews',
|
||||
'selected' => $u->{'allow_getljnews'} eq 'Y' });
|
||||
$ret .= "</td><td><b><label for='allow_getljnews'>$ML{'.opt_in.header'}</label></b></td></tr>\n";
|
||||
$ret .= "<tr><td> </td><td>$ML{'.opt_in.about'}</td></tr>\n";
|
||||
|
||||
# opt_bdaymail
|
||||
$ret .= "<tr valign='middle'><td>";
|
||||
$ret .= LJ::html_check({ 'type' => 'check', 'name' => 'opt_bdaymail', 'id' => 'opt_bdaymail',
|
||||
'selected' => $u->{'opt_bdaymail'} });
|
||||
$ret .= "</td><td><b><label for='opt_bdaymail'>$ML{'.bdayreminders.header'}</label></b></td></tr>\n";
|
||||
$ret .= "<tr><td> </td><td>$ML{'.bdayreminders.about'}</td></tr>\n";
|
||||
|
||||
# opt_imagelinks
|
||||
my ($maxwidth, $maxheight) = (0, 0);
|
||||
($maxwidth, $maxheight) = ($1, $2)
|
||||
if ($u->{'opt_imagelinks'} =~ m/^(\d+)\|(\d+)$/);
|
||||
my $is_stock = {'320|240' => 1, '640|480' => 1, '0|0' => 1, '' => 1}->{$u->{'opt_imagelinks'}};
|
||||
my $extra = $is_stock ? '' : BML::ml('.imagelinks.size.custom',
|
||||
{'width' => $maxwidth, 'height' => $maxheight});
|
||||
$ret .= "<tr valign='middle'><td>";
|
||||
$ret .= LJ::html_check({ 'type' => 'check', 'name' => 'opt_imagelinks_on', 'id' => 'opt_imagelinks_on',
|
||||
'selected' => $u->{'opt_imagelinks'} });
|
||||
$ret .= "</td><td><b><label for='opt_imagelinks_on'>$ML{'.imagelinks.header'}</label></b></td></tr>\n";
|
||||
$ret .= "<tr><td> </td><td>$ML{'.imagelinks.about'}</td></tr>\n";
|
||||
$ret .= "<tr><td> </td><td>";
|
||||
$ret .= LJ::html_select({'name' => 'opt_imagelinks', 'selected' => $u->{'opt_imagelinks'}},
|
||||
'0|0', BML::ml('.imagelinks.size.all'),
|
||||
'320|240', BML::ml('.imagelinks.size.small', {'width' => 320, 'height' => 240}),
|
||||
'640|480', BML::ml('.imagelinks.size.medium', {'width' => 640, 'height' => 480}),
|
||||
$extra ? ("$maxwidth|$maxheight", $extra) : ());
|
||||
$ret .= "</td></tr>\n";
|
||||
|
||||
# opt_getselfemail
|
||||
$ret .= "<tr valign='middle'><td>";
|
||||
$ret .= LJ::html_check({ 'type' => 'check', 'name' => 'opt_getselfemail', 'id' => 'opt_getselfemail',
|
||||
'selected' => $u->{'opt_getselfemail'},
|
||||
'disabled' => !LJ::get_cap($u, 'getselfemail') });
|
||||
$ret .= "</td><td><b><label for='opt_getselfemail'>$ML{'.getselfemails.header'}</label></b></td></tr>\n";
|
||||
$ret .= "<tr><td> </td><td>$ML{'.getselfemails.about'}</td></tr>\n";
|
||||
|
||||
# opt_showtalklinks
|
||||
$ret .= "<tr valign='middle'><td>";
|
||||
$ret .= LJ::html_check({ 'type' => 'check', 'name' => 'opt_showtalklinks', 'id' => 'opt_showtalklinks',
|
||||
'selected' => $u->{'opt_showtalklinks'} eq 'Y' });
|
||||
$ret .= "</td><td><b><label for='opt_showtalklinks'>$ML{'.enableboards.header'}</label></b></td></tr>\n";
|
||||
$ret .= "<tr><td> </td><td>$ML{'.enableboards.about'}";
|
||||
|
||||
{
|
||||
# opt_whocanreply
|
||||
$ret .= "\n<p><b>$ML{'.whoreply.header'}</b> ";
|
||||
$ret .= LJ::html_select({ 'name' => 'opt_whocanreply', 'selected' => $u->{'opt_whocanreply'} },
|
||||
"all" => BML::ml(".security.visibility.anybody"),
|
||||
"reg" => BML::ml(".security.visibility.regusers"),
|
||||
"friends" => BML::ml(".security.visibility.friends"));
|
||||
$ret .= "</p>\n";
|
||||
|
||||
# opt_logcommentips
|
||||
$ret .= "<p><b>$ML{'.logip.header'}</b> ";
|
||||
$ret .= LJ::html_select({ 'name' => 'opt_logcommentips', 'selected' => $u->{'opt_logcommentips'} },
|
||||
"N" => BML::ml(".donotlog"),
|
||||
"S" => BML::ml(".logip.anon_only"),
|
||||
"A" => BML::ml(".logip.always") );
|
||||
$ret .= "</p>\n";
|
||||
|
||||
# opt_whoscreened
|
||||
$ret .= "<p><b>$ML{'.screen.header'}</b> ";
|
||||
$ret .= LJ::html_select({ 'name' => 'opt_whoscreened', 'selected' => $u->{'opt_whoscreened'} },
|
||||
"N" => $ML{'.screen.none'},
|
||||
"R" => $ML{'.screen.anon'},
|
||||
"F" => ($u->{'journaltype'} eq 'C' ? $ML{'.screen.nonmembers'} : $ML{'.screen.nonfriends'}),
|
||||
"A" => $ML{'.screen.all'} );
|
||||
$ret .= "</p>\n";
|
||||
|
||||
$ret .= "<table>\n";
|
||||
|
||||
# opt_nctalklinks
|
||||
$ret .= "<tr valign='middle'><td>";
|
||||
$ret .= LJ::html_check({ 'type' => 'check', 'name' => 'opt_nctalklinks', 'id' => 'opt_nctalklinks',
|
||||
'selected' => $u->{'opt_nctalklinks'} });
|
||||
$ret .= "</td><td><b><label for='opt_nctalklinks'>$ML{'.numcomments.header'}</label></b></td></tr>\n";
|
||||
$ret .= "<tr><td> </td><td>$ML{'.numcomments.about'}</td></tr>\n";
|
||||
|
||||
# stylemine
|
||||
$ret .= "<tr valign='middle'><td>";
|
||||
$ret .= LJ::html_check({ 'type' => 'check', 'name' => 'opt_stylemine', 'id' => 'opt_stylemine',
|
||||
'value' => 1, 'selected' => $u->{'opt_stylemine'} });
|
||||
$ret .= "</td><td><b><label for='opt_stylemine'>$ML{'.stylemine.header'}</label></b></td></tr>\n";
|
||||
$ret .= "<tr><td> </td><td>$ML{'.stylemine.about'}</td></tr>\n";
|
||||
|
||||
# opt_gettalkemail
|
||||
$ret .= "<tr valign='middle'><td>";
|
||||
$ret .= LJ::html_check({ 'type' => 'check', 'name' => 'opt_gettalkemail', 'id' => 'opt_gettalkemail',
|
||||
'selected' => $u->{'opt_gettalkemail'} eq 'Y' });
|
||||
$ret .= "</td><td><b><label for='opt_gettalkemail'>$ML{'.getreplies.header'}</label></b></td></tr>\n";
|
||||
$ret .= "<tr><td> </td><td>$ML{'.getreplies.about'}</td></tr>\n";
|
||||
|
||||
# opt_htmlemail
|
||||
$ret .= "<tr valign='middle'><td>";
|
||||
$ret .= LJ::html_check({ 'type' => 'check', 'name' => 'opt_htmlemail', 'id' => 'opt_htmlemail',
|
||||
'selected' => $u->{'opt_htmlemail'} eq 'Y' });
|
||||
$ret .= "</td><td><b><label for='opt_htmlemail'>$ML{'.htmlemail.header'}</label></b></td></tr>\n";
|
||||
$ret .= "<tr><td> </td><td>$ML{'.htmlemail.about'}</td></tr>\n";
|
||||
|
||||
$ret .= "</table>\n";
|
||||
|
||||
}
|
||||
$ret .= "</td></tr>\n";
|
||||
$ret .= "</table>\n\n";
|
||||
|
||||
### advanced options
|
||||
$ret .= "<?h1 $ML{'.advanced.title'} h1?><?p $ML{'.advanced.about'} p?>\n";
|
||||
$ret .= "<table style='margin: 10px 0 20px 30px;'>\n";
|
||||
|
||||
# external foaf link
|
||||
$ret .= "<tr><td><b>$ML{'.foafurl.title'}</b></td><td>";
|
||||
$ret .= LJ::html_text({ 'name' => 'external_foaf_url',
|
||||
'value' => $u->{'external_foaf_url'}, 'size' => '40', 'maxlength' => '255' });
|
||||
$ret .= "</td></tr><tr><td colspan='2'>$ML{'.foafurl.about'}</td></tr>";
|
||||
|
||||
# done
|
||||
$ret .= "</table>\n";
|
||||
|
||||
### unicode options
|
||||
if ($LJ::UNICODE) {
|
||||
my (%old_encnames, %mail_encnames, %encodings);
|
||||
LJ::load_codes({ "encoding" => \%encodings } );
|
||||
LJ::load_codes({ "encname" => \%old_encnames } );
|
||||
%mail_encnames = %old_encnames;
|
||||
|
||||
# which encodings to show? For now, we just delete utf-8 from the old encodings
|
||||
# list because it doesn't make sense there.
|
||||
foreach my $id (keys %encodings) {
|
||||
delete $old_encnames{$id} if lc($encodings{$id}) eq 'utf-8';
|
||||
}
|
||||
|
||||
$ret .= "<?h2 $ML{'.encoding.header'} h2?><?p $ML{'.encoding.about'} p?>\n";
|
||||
$ret .= "<table style='margin: 10px 0 20px 30px;'>\n";
|
||||
$ret .= "<tr><td><b>$ML{'.autotranslate.header'}</b></td>";
|
||||
$ret .= "<td>" . LJ::html_select({ 'name' => 'oldenc', 'selected' => $u->{'oldenc'}},
|
||||
map { $_, $old_encnames{$_} } sort keys %old_encnames ) . "</td></tr>\n";
|
||||
$ret .= "<tr><td colspan='2'>" . $ML{'.autotranslate.about'} . "</td></tr>";
|
||||
|
||||
if ($u->{journaltype} eq 'P') {
|
||||
$ret .= "<tr><td><b>$ML{'.translatemailto.header'}</b></td>";
|
||||
$ret .= "<td>" . LJ::html_select({ 'name' => 'mailencoding', 'selected' => $u->{'mailencoding'}},
|
||||
map { $_, $mail_encnames{$_} } sort keys %mail_encnames ) . "</td></tr>\n";
|
||||
$ret .= "<tr><td colspan='2'>$ML{'.translatemailto.about'}</td></tr>";
|
||||
}
|
||||
|
||||
$ret .= "</table>\n";
|
||||
}
|
||||
|
||||
### let them un-ban users if they've banned users
|
||||
my $banned = LJ::load_rel_user($u, 'B');
|
||||
if ($banned && @$banned) {
|
||||
my $us = LJ::load_userids(@$banned);
|
||||
|
||||
$ret .= "<?h1 $ML{'.unbanusers.header'} h1?><?p $ML{'.unbanusers.about'} p?>\n";
|
||||
$ret .= "<div style='margin: 10px 0 20px 30px'>\n";
|
||||
foreach (@$banned) {
|
||||
my $bu = $us->{$_};
|
||||
next unless $bu;
|
||||
$ret .= LJ::html_check({ 'type' => 'check', 'name' => 'unban', 'id' => "unban-$bu->{'user'}",
|
||||
'value' => $bu->{'userid'} });
|
||||
$ret .= " <label for='unban-$bu->{'user'}'>$bu->{'user'}</label><br />\n";
|
||||
}
|
||||
$ret .= "</div>\n";
|
||||
}
|
||||
|
||||
# ending submit block
|
||||
$ret .= "<?h1 $ML{'.finished.header'} h1?><?p $ML{'.finished.about'} p?>\n";
|
||||
$ret .= "<?standout " . LJ::html_submit(undef, $ML{'.finished.save_button'}) . " standout?>\n";
|
||||
$ret .= "</form>\n";
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
###
|
||||
### we have a post, process edits
|
||||
###
|
||||
|
||||
if (LJ::did_post()) {
|
||||
return "<?h1 $ML{'Error'} h1?><?p $ML{'error.invalidform'} p?>" unless LJ::check_form_auth();
|
||||
|
||||
$POST{'unban'} =~ s/\0/,/g;
|
||||
return "<?badinput?>" unless LJ::text_in(\%POST);
|
||||
|
||||
my @errors = ();
|
||||
|
||||
# name
|
||||
unless ($POST{'name'} || defined($POST{'name_absent'})) {
|
||||
push @errors, $ML{'.error.noname'};
|
||||
}
|
||||
|
||||
# state and zip
|
||||
my ($zipcity, $zipstate);
|
||||
if ($POST{'country'} eq "US") {
|
||||
$sth = $dbr->prepare("SELECT city, state FROM zip WHERE zip=?");
|
||||
$sth->execute($POST{'zip'});
|
||||
($zipcity, $zipstate) = $sth->fetchrow_array;
|
||||
}
|
||||
|
||||
# country
|
||||
if ($POST{'country'} ne "US" && $POST{'zip'}) {
|
||||
push @errors, $ML{'.error.locale.zip_requires_us'};
|
||||
}
|
||||
|
||||
if ($POST{'country'} eq "US" && $POST{'stateother'}) {
|
||||
push @errors, $ML{'.error.locale.country_ne_state'};
|
||||
} elsif ($POST{'country'} && $POST{'country'} ne "US" && $POST{'statedrop'}) {
|
||||
push @errors, $ML{'.error.locale.state_ne_country'};
|
||||
}
|
||||
|
||||
# zip-code validation stuff
|
||||
if ($POST{'country'} eq "US") {
|
||||
if ($POST{'statedrop'} && $zipstate && $POST{'statedrop'} ne $zipstate) {
|
||||
push @errors, $ML{'.error.locale.zip_ne_state'};
|
||||
}
|
||||
if ($zipcity) {
|
||||
$POST{'statedrop'} = $zipstate;
|
||||
$POST{'city'} = $zipcity;
|
||||
}
|
||||
}
|
||||
|
||||
if ($POST{'country'} && !defined($countries{$POST{'country'}})) {
|
||||
push @errors, $ML{'.error.locale.invalid_country'};
|
||||
}
|
||||
|
||||
# birthday
|
||||
my $this_year = (localtime())[5]+1900;
|
||||
|
||||
if ($POST{'year'} && $POST{'year'} < 100) {
|
||||
push @errors, $ML{'.error.year.notenoughdigits'};
|
||||
}
|
||||
|
||||
if ($POST{'year'} && $POST{'year'} >= 100 && ($POST{'year'} < 1890 || $POST{'year'} > $this_year)) {
|
||||
push @errors, $ML{'.error.year.outofrange'};
|
||||
}
|
||||
|
||||
if ($POST{'month'} && ($POST{'month'} < 1 || $POST{'month'} > 12)) {
|
||||
push @errors, $ML{'.error.month.outofrange'};
|
||||
}
|
||||
|
||||
if ($POST{'day'} && ($POST{'day'} < 1 || $POST{'day'} > 31)) {
|
||||
push @errors, $ML{'.error.day.outofrange'};
|
||||
}
|
||||
|
||||
if (@errors == 0 && $POST{'day'} > LJ::days_in_month($POST{'month'}, $POST{'year'})) {
|
||||
push @errors, $ML{'.error.day.notinmonth'};
|
||||
}
|
||||
|
||||
# email
|
||||
unless ($POST{'email'}) {
|
||||
push @errors, $ML{'.error.email.none'};
|
||||
}
|
||||
|
||||
if ($LJ::USER_EMAIL and $POST{'email'} =~ /\@\Q$LJ::USER_DOMAIN\E$/i) {
|
||||
push @errors, BML::ml(".error.email.lj_domain", { 'user' => $u->{'user'}, 'domain' => $LJ::USER_DOMAIN, });
|
||||
}
|
||||
|
||||
if ($POST{'email'} =~ /\s/) {
|
||||
push @errors, $ML{'.error.email.no_space'};
|
||||
}
|
||||
|
||||
unless (@errors) {
|
||||
LJ::check_email($POST{'email'}, \@errors);
|
||||
}
|
||||
|
||||
# text messaging
|
||||
if ($POST{'use_txtmsg'}) {
|
||||
unless ($POST{'txtmsg_provider'}) {
|
||||
push @errors, $ML{'.error.tm.require_provider'};
|
||||
}
|
||||
unless ($POST{'txtmsg_number'}) {
|
||||
push @errors, $ML{'.error.tm.require.number'};
|
||||
}
|
||||
}
|
||||
|
||||
return LJ::bad_input(@errors) if @errors;
|
||||
|
||||
### no errors
|
||||
|
||||
my $dbh = LJ::get_db_writer();
|
||||
|
||||
my $email_changed = ($u->{'email'} ne $POST{'email'});
|
||||
if ($email_changed) {
|
||||
# record old email address;
|
||||
LJ::infohistory_add($u, 'email', $u->{email}, $u->{status});
|
||||
}
|
||||
|
||||
$POST{'url'} =~ s/\s+$//; $POST{'url'} =~ s/^\s+//;
|
||||
if ($POST{'url'} && $POST{'url'} !~ /^https?:\/\//) {
|
||||
$POST{'url'} =~ s/^http\W*//;
|
||||
$POST{'url'} = "http://$POST{'url'}";
|
||||
}
|
||||
|
||||
my $newname = defined $POST{'name_absent'} ? $saved{'name'} : $POST{'name'};
|
||||
$newname =~ s/[\n\r]//g;
|
||||
$newname = LJ::text_trim($newname, LJ::BMAX_NAME, LJ::CMAX_NAME);
|
||||
|
||||
my $newbio = defined($POST{'bio_absent'}) ? $saved{'bio'} : $POST{'bio'};
|
||||
my $has_bio = ($newbio =~ /\S/) ? "Y" : "N";
|
||||
my $txtmsg_status = $POST{'use_txtmsg'} ? "on" : "off";
|
||||
# setup what we're gonna update in the user table:
|
||||
my %update = (
|
||||
'name' => $newname,
|
||||
'bdate' => sprintf("%04d-%02d-%02d", $POST{'year'}, $POST{'month'}, $POST{'day'}),
|
||||
'email' => $POST{'email'},
|
||||
'status' => ($email_changed && $u->{'status'} eq "A") ? "T" : $u->{'status'},
|
||||
'has_bio' => $has_bio,
|
||||
'allow_infoshow' => $POST{'allow_infoshow'} ? "Y" : "N",
|
||||
'allow_getljnews' => $POST{'allow_getljnews'} ? "Y" : "N",
|
||||
'opt_showtalklinks' => $POST{'opt_showtalklinks'} ? "Y" : "N",
|
||||
'opt_gettalkemail' => $POST{'opt_gettalkemail'} ? "Y" : "N",
|
||||
'opt_htmlemail' => $POST{'opt_htmlemail'} ? "Y" : "N",
|
||||
'opt_mangleemail' => $POST{'opt_mangleemail'} ? "Y" : "N",
|
||||
'opt_whocanreply' => $POST{'opt_whocanreply'},
|
||||
'txtmsg_status' => $txtmsg_status,
|
||||
);
|
||||
|
||||
if ($POST{'allow_contactshow'}) {
|
||||
$update{'allow_contactshow'} = "Y";
|
||||
$update{'allow_contactshow'} = "F" if $POST{'contactshow_sec'} eq "F";
|
||||
} else {
|
||||
$update{'allow_contactshow'} = "N";
|
||||
}
|
||||
|
||||
if (defined $POST{'oldenc'}) {
|
||||
$update{'oldenc'} = $POST{'oldenc'};
|
||||
}
|
||||
|
||||
LJ::update_user($u, \%update);
|
||||
|
||||
### change any of the userprops ?
|
||||
{
|
||||
# journal / friends titles
|
||||
$POST{'journaltitle'} = LJ::text_trim($POST{'journaltitle'}, 0, 80) if $POST{'journaltitle'};
|
||||
$POST{'journalsubtitle'} = LJ::text_trim($POST{'journalsubtitle'}, 0, 80) if $POST{'journalsubtitle'};
|
||||
$POST{'friendspagetitle'} = LJ::text_trim($POST{'friendspagetitle'}, 0, 80) if $POST{'friendspagetitle'};
|
||||
|
||||
# opts
|
||||
$POST{'opt_showmutualfriends'} = $POST{'opt_showmutualfriends'} ? 1 : 0;
|
||||
$POST{'opt_getselfemail'} = $POST{'opt_getselfemail'} ? 1 : 0;
|
||||
$POST{'opt_stylemine'} = $POST{'opt_stylemine'} ? 1 : 0;
|
||||
$POST{'opt_blockrobots'} = $POST{'opt_blockrobots'} ? 1 : 0;
|
||||
$POST{'opt_bdaymail'} = $POST{'opt_bdaymail'} ? 1 : 0;
|
||||
$POST{'opt_hidefriendofs'} = $POST{'opt_hidefriendofs'} ? 1 : 0;
|
||||
$POST{'opt_nctalklinks'} = $POST{'opt_nctalklinks'} ? 1 : 0;
|
||||
$POST{'opt_weblogscom'} = $POST{'opt_weblogscom'} ? 1 : 0;
|
||||
if ($POST{'opt_logcommentips'} ne "N" &&
|
||||
$POST{'opt_logcommentips'} ne "S" &&
|
||||
$POST{'opt_logcommentips'} ne "A") { $POST{'opt_logcommentips'} = "N"; }
|
||||
$POST{'opt_whoscreened'} = "N" unless $POST{'opt_whoscreened'} =~ m/^(N|R|F|A)$/;
|
||||
$POST{'opt_imagelinks'} = 0 unless $POST{'opt_imagelinks_on'} &&
|
||||
$POST{'opt_imagelinks'} =~ m/^(\d+)\|(\d+)$/;
|
||||
|
||||
# for the directory.
|
||||
$POST{'sidx_bdate'} = "";
|
||||
$POST{'sidx_loc'} = "";
|
||||
$POST{'state'} = $POST{'statedrop'} || $POST{'stateother'};
|
||||
if ($update{'allow_infoshow'} eq 'Y') {
|
||||
if ($POST{'year'}) {
|
||||
$POST{'sidx_bdate'} = sprintf("%04d-%02d-%02d", map { $POST{$_} }
|
||||
qw(year month day));
|
||||
}
|
||||
|
||||
if ($POST{'country'}) {
|
||||
my $state;
|
||||
if ($POST{'country'} eq "US") {
|
||||
$state = $POST{'statedrop'};
|
||||
} else {
|
||||
$state = $POST{'stateother'};
|
||||
}
|
||||
$POST{'sidx_loc'} = sprintf("%2s-%s-%s",
|
||||
$POST{'country'},
|
||||
$state,
|
||||
$POST{'city'});
|
||||
}
|
||||
}
|
||||
|
||||
my @uprops = (
|
||||
"opt_whatemailshow",
|
||||
"country", "state", "city", "zip", "icq",
|
||||
"aolim", "yahoo", "msn", "url", "urlname",
|
||||
"gender", "jabber", "opt_blockrobots",
|
||||
"opt_logcommentips",
|
||||
"opt_bdaymail", "opt_hidefriendofs",
|
||||
"sidx_bdate", "sidx_loc", "mailencoding", "opt_nctalklinks",
|
||||
"opt_whoscreened", "journaltitle", "journalsubtitle", "friendspagetitle",
|
||||
"opt_stylemine", "opt_imagelinks", "opt_getselfemail",
|
||||
"external_foaf_url", "opt_showmutualfriends",
|
||||
);
|
||||
|
||||
# weblogs.com requires a special cap
|
||||
push @uprops, 'opt_weblogscom' if LJ::get_cap($u, 'weblogscom');
|
||||
|
||||
# this is only done once, then never appears again.
|
||||
push @uprops, 'howhear' if $POST{'howhear'};
|
||||
|
||||
# set userprops
|
||||
foreach my $uprop (@uprops) {
|
||||
my $eff_val = $POST{$uprop}; # effective value, since 0 isn't stored
|
||||
$eff_val = "" unless $eff_val;
|
||||
my $mem_only = $eff_val eq $u->{$uprop};
|
||||
LJ::set_userprop($u, $uprop, $eff_val, $mem_only);
|
||||
}
|
||||
}
|
||||
|
||||
# update their bio text
|
||||
if (($u->{'bio'} ne $POST{'bio'}) && !defined($POST{'bio_absent'})) {
|
||||
if ($has_bio eq "N") {
|
||||
$u->do("DELETE FROM userbio WHERE userid=?", undef, $u->{'userid'});
|
||||
$u->dudata_set('B', 0, 0);
|
||||
} else {
|
||||
$u->do("REPLACE INTO userbio (userid, bio) VALUES (?, ?)",
|
||||
undef, $u->{'userid'}, $POST{'bio'});
|
||||
$u->dudata_set('B', 0, length($POST{'bio'}));
|
||||
}
|
||||
LJ::MemCache::set([$u->{'userid'}, "bio:$u->{'userid'}"], $POST{'bio'});
|
||||
}
|
||||
|
||||
# update their text messaging info
|
||||
if ($txtmsg_status eq "off" && $u->{'txtmsg_status'} eq "on") {
|
||||
$dbh->do("DELETE FROM txtmsg WHERE userid=?", undef, $u->{'userid'});
|
||||
} elsif ($txtmsg_status eq "on") {
|
||||
$dbh->do("REPLACE INTO txtmsg (userid, provider, number, security) VALUES (?, ?, ?, ?)",
|
||||
undef, $u->{'userid'}, $POST{'txtmsg_provider'}, $POST{'txtmsg_number'}, $POST{'txtmsg_security'});
|
||||
}
|
||||
|
||||
# update interests
|
||||
unless ($POST{'interests_absent'}) {
|
||||
$POST{'interests'} =~ s/^\s+//;
|
||||
$POST{'interests'} =~ s/\s+$//;
|
||||
$POST{'interests'} =~ s/\n/,/g;
|
||||
$POST{'interests'} =~ s/\s+/ /g; #Strip duplicate spaces from the interest
|
||||
my @ints = split (/\s*,\s*/, $POST{'interests'});
|
||||
my $intcount = scalar(@ints);
|
||||
if ($intcount > 150) {
|
||||
return LJ::bad_input(BML::ml(".error.excessive_int", {'intcount' => $intcount}));
|
||||
}
|
||||
LJ::set_interests($u, \%interests, \@ints);
|
||||
}
|
||||
|
||||
# now unban users they selected to be unbanned
|
||||
if ($POST{'unban'}) {
|
||||
my $bannedin = join(",", map { $dbh->quote($_); } split(/,/, $POST{'unban'}));
|
||||
$dbh->do("DELETE FROM reluser WHERE userid=? AND type='B' AND targetid IN ($bannedin)", undef, $u->{'userid'});
|
||||
}
|
||||
|
||||
# actions if email changed
|
||||
if ($email_changed) {
|
||||
my $aa = {};
|
||||
$aa = LJ::register_authaction($u->{'userid'},
|
||||
"validateemail", $POST{'email'});
|
||||
|
||||
LJ::send_mail({
|
||||
'to' => $POST{'email'},
|
||||
'from' => $LJ::ADMIN_EMAIL,
|
||||
'charset' => 'utf-8',
|
||||
'subject' => $ML{'.newemail.subject'},
|
||||
'body' => BML::ml('.newemail.body2',
|
||||
{ username => $u->{user},
|
||||
sitename => $LJ::SITENAME,
|
||||
sitelink => $LJ::SITEROOT,
|
||||
conflink => "$LJ::SITEROOT/confirm/$aa->{'aaid'}.$aa->{'authcode'}" }),
|
||||
});
|
||||
}
|
||||
|
||||
# tell the user all is well
|
||||
return "<?h1 $ML{'.success.header'} h1?>\n" .
|
||||
"<?p " . BML::ml(".success.message", { 'user' => $u->{'user'}, }) . " p?>";
|
||||
}
|
||||
|
||||
# should never happen
|
||||
return "<?h1 $ML{'Error'} h1?><?p $ML{'error.unknownmode'} p?>";
|
||||
|
||||
}
|
||||
_code?>
|
||||
|
||||
<=body
|
||||
page?><?_c <LJDEP>
|
||||
lib: LJ::TextMessage, cgi-bin/ljlib.pl, cgi-bin/ljlang.pl
|
||||
link: htdocs/legal/privacy.bml, htdocs/support/faqbrowse.bml, htdocs/tools/textmessage.bml, htdocs/uploadpic.bml
|
||||
link: htdocs/paidaccounts/index.bml, htdocs/users, htdocs/userinfo.bml
|
||||
post: htdocs/editinfo.bml
|
||||
img: htdocs/userpic
|
||||
</LJDEP> _c?>
|
||||
413
livejournal/htdocs/editjournal.bml
Executable file
@@ -0,0 +1,413 @@
|
||||
<?page
|
||||
title=><?_ML .title _ML?>
|
||||
body<=
|
||||
<?_code
|
||||
{
|
||||
use strict;
|
||||
use vars qw(%GET %POST);
|
||||
|
||||
my $head = \$_[1]->{'head'};
|
||||
my $bodyopts = \$_[1]->{'bodyopts'};
|
||||
|
||||
LJ::set_active_crumb('editentries');
|
||||
|
||||
my $remote = LJ::get_remote();
|
||||
return LJ::bad_input($ML{'error.noremote'})
|
||||
unless $remote;
|
||||
|
||||
if ($remote->underage) {
|
||||
return BML::redirect("$LJ::SITEROOT/agecheck/?s=1");
|
||||
}
|
||||
|
||||
my $mode = $GET{'mode'} || $POST{'mode'} || "init";
|
||||
if ($GET{'itemid'} || $POST{'itemid'}) { $mode = "edit"; }
|
||||
|
||||
my $ret;
|
||||
my $getextra = "?authas=$GET{'authas'}" if $GET{'authas'};
|
||||
|
||||
# are they asking to be authed as someone else?
|
||||
my $authas = $GET{'authas'} || $remote->{'user'};
|
||||
my $u = LJ::get_authas_user($authas);
|
||||
return LJ::bad_input("You could not be authenticated as the specified user.")
|
||||
unless $u;
|
||||
return LJ::bad_input("You must be authenticated as a person.")
|
||||
unless $u->{'journaltype'} eq 'P';
|
||||
|
||||
if ($mode eq "edit")
|
||||
{
|
||||
# are we modify a community post?
|
||||
my $usejournal = $GET{'usejournal'} || $POST{'usejournal'} || $GET{'journal'};
|
||||
undef $usejournal if $usejournal eq $u->{'user'}; # ignore if it's the user
|
||||
|
||||
# user object for community if we're modifying one
|
||||
my $usejournal_u;
|
||||
if ($usejournal) {
|
||||
$usejournal_u = LJ::load_user($usejournal);
|
||||
return LJ::bad_input("The community you selected does not exist.")
|
||||
unless $usejournal_u;
|
||||
}
|
||||
|
||||
# extra get arguments
|
||||
my $getextra;
|
||||
$getextra .= "authas=$authas&" if $authas ne $u->{'user'};
|
||||
$getextra .= "usejournal=$usejournal&" if $usejournal;
|
||||
chop $getextra;
|
||||
$getextra = "?$getextra" if $getextra;
|
||||
|
||||
###
|
||||
### HAVE AN ITEMID TO EDIT
|
||||
###
|
||||
|
||||
if ($GET{'itemid'} || $POST{'itemid'}) {
|
||||
|
||||
# the 'itemid' form element is really an 'itemid'
|
||||
my $ditemid = $GET{'itemid'} || $POST{'itemid'};
|
||||
my $anum = $ditemid % 256;
|
||||
my $itemid = $ditemid >> 8;
|
||||
|
||||
# do getevents request
|
||||
my %res = ();
|
||||
LJ::do_request({ 'mode' => 'getevents',
|
||||
'selecttype' => 'one',
|
||||
'ver' => $LJ::PROTOCOL_VER,
|
||||
'user' => $u->{'user'},
|
||||
'usejournal' => $usejournal,
|
||||
'itemid' => $itemid },
|
||||
\%res,
|
||||
{ "noauth" => 1,
|
||||
'u' => $u }
|
||||
);
|
||||
|
||||
# was there a protocol error?
|
||||
return "<?h1 $ML{'Error'} h1?><?p $res{'errmsg'} p?>"
|
||||
unless $res{'success'} eq 'OK';
|
||||
|
||||
# does the requested entry exist?
|
||||
return "<?h1 $ML{'Error'} h1?><?p $ML{'.error.nofind'} p?>"
|
||||
unless $res{'events_count'} && $res{'events_1_anum'} == $anum;
|
||||
|
||||
# are we authorized to edit other peoples' posts in this community?
|
||||
my $disabled_save = 0;
|
||||
my $disabled_delete = 0;
|
||||
my $disabled_spamdelete = 0;
|
||||
if ($usejournal && $res{'events_1_poster'} ne $u->{'user'}) {
|
||||
$disabled_delete = ! LJ::can_delete_journal_item($u, $usejournal_u);
|
||||
$disabled_save++;
|
||||
}
|
||||
$disabled_spamdelete = $disabled_delete || !$usejournal || ($res{'events_1_poster'} eq $u->{'user'});
|
||||
|
||||
###
|
||||
### SAVE EDITS
|
||||
###
|
||||
|
||||
# are we spellchecking before we post?
|
||||
my $spellcheck_html;
|
||||
my $did_spellcheck;
|
||||
if ($LJ::SPELLER && $POST{'action:spellcheck'}) {
|
||||
$did_spellcheck++;
|
||||
my $s = new LJ::SpellCheck { 'spellcommand' => $LJ::SPELLER,
|
||||
'color' => '<?hotcolor?>', };
|
||||
my $event = LJ::ehtml($POST{'event'});
|
||||
$spellcheck_html = $s->check_html(\$event);
|
||||
$spellcheck_html = "<?inerr $ML{'entryform.spellcheck.noerrors'} inerr?>" unless $spellcheck_html ne "";
|
||||
}
|
||||
|
||||
# they clicked the save or delete button
|
||||
if (!$spellcheck_html && ($POST{'action:save'} || $POST{'action:delete'} || $POST{'action:deletespam'})) {
|
||||
return LJ::bad_input($ML{'error.invalidform'}) unless LJ::check_form_auth();
|
||||
|
||||
my %req = ( 'mode' => 'editevent',
|
||||
'ver' => $LJ::PROTOCOL_VER,
|
||||
'user' => $u->{'user'},
|
||||
'usejournal' => $usejournal,
|
||||
'itemid' => $itemid,
|
||||
);
|
||||
LJ::entry_form_decode(\%req, \%POST);
|
||||
|
||||
# Delete
|
||||
$req{'event'} = '' if $POST{'action:delete'} || $POST{'action:deletespam'};
|
||||
|
||||
# mark as spam, if need be
|
||||
LJ::mark_entry_as_spam($usejournal_u, $itemid) if $POST{'action:deletespam'};
|
||||
|
||||
# if the action is to delete it, then let's note that
|
||||
if ($POST{'action:delete'} || $POST{'action:deletespam'}) {
|
||||
# now log the event created above
|
||||
($usejournal ? $usejournal_u : $u)->log_event('delete_entry', {
|
||||
remote => $remote,
|
||||
actiontarget => $ditemid,
|
||||
method => 'web',
|
||||
});
|
||||
}
|
||||
|
||||
# do editevent request
|
||||
LJ::do_request(\%req, \%res, { 'noauth' => 1, 'u' => $u });
|
||||
|
||||
# check response
|
||||
unless ($res{'success'} eq "OK") {
|
||||
return "<?h1 $ML{'Error'} h1?><?p $ML{'.error.modify'} <ul><li><b>$res{'errmsg'}</b></li></ul> p?>";
|
||||
}
|
||||
|
||||
# deleted
|
||||
unless ($req{'event'}) {
|
||||
my $result = "<?h1 $ML{'.success.head'} h1?><?p $ML{'.success.delete'} p?>";
|
||||
$result .= "<?p $ML{'.success.deletespam'} p?>" if $POST{'action:deletespam'};
|
||||
return $result;
|
||||
}
|
||||
|
||||
# modified
|
||||
return BML::redirect(LJ::item_link($usejournal ? $usejournal_u : $u, $itemid, $res{'anum'}));
|
||||
}
|
||||
|
||||
|
||||
###
|
||||
### SHOW EDIT FORM
|
||||
###
|
||||
|
||||
my $auth = "<tr><th>$ML{'.auth.poster'}</th><td>";
|
||||
$auth .= $usejournal ? LJ::ljuser($res{'events_1_poster'}) . " in community " . LJ::ljuser($usejournal) :
|
||||
LJ::ljuser($remote);
|
||||
$auth .= "</td></tr>";
|
||||
|
||||
|
||||
my ($year, $mon, $mday, $hour, $min) = split(/\D/, $res{"events_1_eventtime"});
|
||||
my $datetime; my $date = LJ::html_datetime_decode({ 'name' => "date_ymd", }, \%POST);
|
||||
if ($date ne "0000-00-00 00:00:00") {
|
||||
my ($date, $time) = split( / /, $date);
|
||||
$datetime = "$date $POST{'hour'}:$POST{'min'}";
|
||||
} else {
|
||||
$datetime = "$year-$mon-$mday $hour:$min";
|
||||
}
|
||||
|
||||
my $subject = $POST{'subject'} || $res{'events_1_subject'};
|
||||
my $event = $POST{'event'} || $res{'events_1_event'};
|
||||
|
||||
my $curmask = $res{'events_1_allowmask'};
|
||||
my $cursec = $res{'events_1_security'} || $POST{'security'};
|
||||
if ($cursec eq 'usemask') {
|
||||
$cursec = $curmask == 1 ? "friends" : "custom";
|
||||
}
|
||||
|
||||
# start edit form
|
||||
my $ret; my $js;
|
||||
$ret .= "<div style='width: 100%'><form method='post' action='editjournal.bml$getextra' id='updateForm' name='updateForm'>";
|
||||
$ret .= LJ::form_auth();
|
||||
$ret .= LJ::html_hidden('itemid', $ditemid,'mode','edit','edited',1) . "\n";
|
||||
|
||||
my $entry = {
|
||||
'mode' => "edit",
|
||||
'auth_as_remote' => 1,
|
||||
'subject' => $subject,
|
||||
'event' => $event,
|
||||
'datetime' => $datetime,
|
||||
'usejournal' => $usejournal,
|
||||
'security' => $cursec,
|
||||
'security_mask' => $curmask,
|
||||
'auth' => $auth,
|
||||
'remote' => $remote,
|
||||
'spellcheck_html' => $spellcheck_html,
|
||||
'richtext' => 0,
|
||||
'mood' => $res{'events_1_'},
|
||||
'disabled_save' => $disabled_save,
|
||||
'disabled_delete' => $disabled_delete,
|
||||
'disabled_spamdelete' => $disabled_spamdelete,
|
||||
};
|
||||
for (my $i = 1; $i <= $res{'prop_count'}; $i++) {
|
||||
$entry->{"prop_" . $res{"prop_${i}_name"}} = $res{"prop_${i}_value"};
|
||||
}
|
||||
foreach ( keys %POST ) { $entry->{$_} = %POST->{$_}; }
|
||||
|
||||
my $onload = "shift_contents(); ";
|
||||
$ret .= LJ::entry_form($entry, \$$head, \$onload);
|
||||
$ret .= "</form></div>";
|
||||
|
||||
$$bodyopts .= "onload='$onload' onresize='shift_contents();' ";
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
###
|
||||
### NO ITEMID - SELECT ENTRY TO EDIT
|
||||
###
|
||||
|
||||
### already authenticated from above
|
||||
|
||||
return BML::redirect("$LJ::SITEROOT/editjournal.bml")
|
||||
unless LJ::did_post();
|
||||
|
||||
my %res;
|
||||
my %req = (
|
||||
'mode' => 'getevents',
|
||||
'ver' => $LJ::PROTOCOL_VER,
|
||||
'user' => $u->{'user'},
|
||||
'usejournal' => $usejournal,
|
||||
'truncate' => 300,
|
||||
'noprops' => 1,
|
||||
);
|
||||
|
||||
# last 1
|
||||
if ($POST{'selecttype'} eq "last") {
|
||||
$req{'selecttype'} = 'one';
|
||||
$req{'itemid'} = -1;
|
||||
|
||||
# last n
|
||||
} elsif ($POST{'selecttype'} eq 'lastn') {
|
||||
$req{'selecttype'} = 'lastn';
|
||||
$req{'howmany'} = $POST{'howmany'};
|
||||
|
||||
# day
|
||||
} elsif ($POST{'selecttype'} eq 'day') {
|
||||
$req{'selecttype'} = 'day';
|
||||
$req{$_} = $POST{$_} foreach qw(year month day);
|
||||
}
|
||||
|
||||
# do getevents request
|
||||
LJ::do_request(\%req, \%res, { 'noauth' => 1, 'u' => $u });
|
||||
|
||||
# check response
|
||||
unless ($res{'success'} eq "OK") {
|
||||
return "<?h1 $ML{'Error'} h1?>\n" .
|
||||
"<?p $ML{'.error.getting'} <ul><li><b><?_eh $res{'errmsg'} _eh?></b></li></ul> p?>";
|
||||
}
|
||||
|
||||
# only one item returned? go directly to edit it
|
||||
if ($res{'events_count'} == 1) {
|
||||
my $ditemid = ($res{'events_1_itemid'} << 8) + $res{'events_1_anum'};
|
||||
my $ditemid_get = $getextra ? "$getextra&itemid=$ditemid" : "?itemid=$ditemid";
|
||||
return BML::redirect("$LJ::SITEROOT/editjournal.bml$ditemid_get");
|
||||
}
|
||||
|
||||
# how many results did we get?
|
||||
my $ev_count = $res{'events_count'};
|
||||
unless ($ev_count) {
|
||||
if ($req{'selecttype'} eq 'lastn') {
|
||||
return "<?h1 No Entries Found h1?>\n" .
|
||||
"<?p The selected journal has no entries. p?>\n";
|
||||
}
|
||||
|
||||
return "<?h1 No Entries Found h1?>\n" .
|
||||
"<?p No entries match the criteria you specified. Please go back and adjust your search. p?>\n";
|
||||
}
|
||||
|
||||
### display results
|
||||
my $ret;
|
||||
$ret .= "<?h1 $ML{'.pickentry.head'} h1?><?p $ML{'.pickentry.text'} p?>\n";
|
||||
|
||||
my %props = ();
|
||||
for (my $i=1; $i<=$res{'prop_count'}; $i++) {
|
||||
$props{$res{"prop_${i}_itemid"}}->{$res{"prop_${i}_name"}} = $res{"prop_${i}_value"};
|
||||
}
|
||||
|
||||
for (my $i=1; $i<=$ev_count; $i++) {
|
||||
my $itemid = $res{"events_${i}_itemid"};
|
||||
my $ditemid = $itemid * 256 + $res{"events_${i}_anum"};
|
||||
|
||||
$ret .= "<?hr?><table><tr valign='top'><td align='middle'>";
|
||||
$ret .= "<form method='post' action='editjournal.bml$getextra'>\n";
|
||||
$ret .= LJ::html_hidden('itemid',$ditemid,'mode',"edit");
|
||||
$ret .= LJ::html_submit('itemid-$ditemid','Edit this Entry');
|
||||
$ret .= "</form>";
|
||||
$ret .= "</td><td>";
|
||||
|
||||
$ret .= " <b><label for='itemid-$ditemid'>" . $res{"events_${i}_eventtime"} . "</label></b>";
|
||||
$ret .= " (Posted by: " . LJ::ljuser($res{"events_${i}_poster"}) . ")" if $usejournal;
|
||||
|
||||
### security indicator
|
||||
my $sec = ' ';
|
||||
if ($res{"events_${i}_security"} eq "private") {
|
||||
$sec .= BML::fill_template("securityprivate");
|
||||
} elsif ($res{"events_${i}_security"} eq "usemask") {
|
||||
$sec .= BML::fill_template("securityprotected");
|
||||
}
|
||||
$ret .= $sec;
|
||||
|
||||
if (my $subj = $res{"events_${i}_subject"}) {
|
||||
LJ::CleanHTML::clean_subject_all(\$subj);
|
||||
$ret .= " <i>" . LJ::ehtml($subj) . "</i>";
|
||||
}
|
||||
$ret .= "<br />\n";
|
||||
|
||||
my $event = LJ::ehtml(LJ::durl($res{"events_${i}_event"}));
|
||||
$event =~ s!\n!<br />!g;
|
||||
$ret .= $event;
|
||||
|
||||
$ret .= "</td></tr></table>\n";
|
||||
}
|
||||
return $ret;
|
||||
} elsif ($mode eq "init") {
|
||||
# no authentication needs to be done on this page, it's just a form anyway
|
||||
|
||||
# user switcher
|
||||
$ret .= "<form action='editjournal.bml' method='get'>\n";
|
||||
$ret .= LJ::make_authas_select($remote, { 'authas' => $GET{'authas'}, 'type' => 'P' });
|
||||
$ret .= "</form>\n\n";
|
||||
|
||||
# header
|
||||
$ret .= "<?p $ML{'.desc'} p?>\n";
|
||||
|
||||
# edit form
|
||||
$ret .= "<form action='editjournal.bml$getextra' method='post'>\n";
|
||||
$ret .= LJ::html_hidden("mode","edit");
|
||||
$ret .= "<?standout <table>\n";
|
||||
|
||||
# view type
|
||||
$ret .= "<tr valign=\"top\"><td>$ML{'.viewwhat'}</td>\n<td>\n";
|
||||
$ret .= LJ::html_check({ 'type' => 'radio', 'name' => 'selecttype', 'id' => 'selecttype-last',
|
||||
'value' => 'last', 'selected' => 1 });
|
||||
$ret .= "<label for='selecttype-last'>$ML{'.recententry'}</label><br />\n";
|
||||
|
||||
$ret .= LJ::html_check({ 'type' => 'radio', 'name' => 'selecttype',
|
||||
'id' => 'selecttype-lastn', 'value' => 'lastn' }) . " ";
|
||||
$ret .= LJ::html_text({ 'name' => 'howmany', 'size' => '3', 'maxlength' => '2', 'value' => '20',
|
||||
'onchange' => "checkRadioButton('selecttype-lastn');" }) . " ";
|
||||
$ret .= "<label for='selecttype-lastn'>$ML{'.recententries'}</label><br />\n";
|
||||
|
||||
$ret .= LJ::html_check({ 'type' => 'radio', 'name' => 'selecttype',
|
||||
'id' => 'selecttype-day', 'value' => 'day' });
|
||||
$ret .= "<label for='selecttype-day'>$ML{'.certainday'}</label>";
|
||||
|
||||
my @time = localtime(time);
|
||||
my $mday = sprintf("%02d", $time[3]);
|
||||
my $mon = sprintf("%02d", $time[4] + 1);
|
||||
my $year = $time[5] + 1900;
|
||||
|
||||
$ret .= LJ::html_text({ 'name' => 'year', 'size' => '5', 'maxlength' => '4', 'value' => $year,
|
||||
'onchange' => "checkRadioButton('selecttype-day');" }) . "-";
|
||||
$ret .= LJ::html_text({ 'name' => 'month', 'size' => '3', 'maxlength' => '2', 'value' => $mon,
|
||||
'onchange' => "checkRadioButton('selecttype-day');" }) . "-";
|
||||
$ret .= LJ::html_text({ 'name' => 'day', 'size' => '3', 'maxlength' => '2', 'value' => $mday,
|
||||
'onchange' => "checkRadioButton('selecttype-day');" }) . "\n";
|
||||
|
||||
$ret .= "</td></tr>\n";
|
||||
|
||||
# use journal
|
||||
$ret .= "<tr valign=\"top\"><td align='right'>$ML{'.in'}</td>\n<td>\n";
|
||||
$ret .= LJ::html_text({ 'name' => 'usejournal', 'size' => '20', 'maxlength' => '15', 'value' => $GET{'usejournal'} }) . " ";
|
||||
$ret .= " (optional)</td></tr>";
|
||||
|
||||
# submit button
|
||||
$ret .= "<tr><td> </td><td>" . LJ::html_submit(undef, $ML{'.btn.proceed'}) . "</td></tr>\n";
|
||||
|
||||
$ret .= "</table> standout?>\n";
|
||||
$ret .= "</form>\n";
|
||||
|
||||
return $ret;
|
||||
}
|
||||
}
|
||||
_code?>
|
||||
<=body
|
||||
|
||||
bodyopts=><?_code return $_[1]->{'bodyopts'}; _code?>
|
||||
head<=
|
||||
|
||||
<?entryformcss?>
|
||||
<?_code return $_[1]->{'head'}; _code?>
|
||||
<script type="text/javascript" language="JavaScript" src="/js/entry.js"></script>
|
||||
<?_code return $LJ::COMMON_CODE{'autoradio_check'}; _code?>
|
||||
|
||||
<=head
|
||||
page?><?_c <LJDEP>
|
||||
post: htdocs/editjournal.bml
|
||||
link: htdocs/lostinfo.bml
|
||||
</LJDEP> _c?>
|
||||
|
||||
873
livejournal/htdocs/editpics.bml
Executable file
@@ -0,0 +1,873 @@
|
||||
<?_code
|
||||
{
|
||||
use strict;
|
||||
use vars qw(%GET %POST $title $body @errors);
|
||||
|
||||
LJ::set_active_crumb('editpics');
|
||||
|
||||
$body = "";
|
||||
@errors = ();
|
||||
|
||||
my $err = sub {
|
||||
$title = "Error";
|
||||
$body = LJ::bad_input(@_);
|
||||
return;
|
||||
};
|
||||
|
||||
unless (LJ::text_in(\%POST)) {
|
||||
return $err->("Invalid UTF-8 Input");
|
||||
}
|
||||
|
||||
my $remote = LJ::get_remote();
|
||||
return $err->($ML{'error.noremote'})
|
||||
unless $remote;
|
||||
|
||||
if ($remote->underage) {
|
||||
return BML::redirect("$LJ::SITEROOT/agecheck/?s=1");
|
||||
}
|
||||
|
||||
my $authas = $GET{'authas'} || $remote->{'user'};
|
||||
my $u = LJ::get_authas_user($authas);
|
||||
return $err->($ML{'error.invalidauth'})
|
||||
unless $u;
|
||||
|
||||
# extra arguments for get requests
|
||||
my $getextra = $authas ne $remote->{'user'} ? "?authas=$authas" : '';
|
||||
|
||||
my $returl = LJ::CleanHTML::canonical_url($POST{'ret'});
|
||||
my $picurl = LJ::CleanHTML::canonical_url($POST{'urlpic'});
|
||||
my $fotobilder = index($returl, $LJ::FB_SITEROOT) == 0 &&
|
||||
$picurl =~ m!^$LJ::FB_SITEROOT/~?$remote->{'user'}/pic/!;
|
||||
|
||||
if ($fotobilder &&
|
||||
(LJ::check_referer($returl) || LJ::check_referer('/editpics.bml'))) {
|
||||
|
||||
return $err->('Invalid referring site or redirection not allowed')
|
||||
unless $returl =~ /$LJ::FB_DOMAIN/ && LJ::get_cap($u, 'fb_account');
|
||||
}
|
||||
|
||||
if (LJ::get_cap($u, "readonly")) {
|
||||
$title = "Read-only mode";
|
||||
$body = $LJ::MSG_READONLY_USER;
|
||||
return;
|
||||
}
|
||||
|
||||
# update this user's activated pics
|
||||
LJ::activate_userpics($u);
|
||||
|
||||
my ($dbh, $dbcm, $dbcr, $sth);
|
||||
|
||||
# Put $count and $max in larger scope so they can be used in output
|
||||
my $count;
|
||||
$dbcm = LJ::get_cluster_master($u);
|
||||
return $err->($ML{'error.nodb'}) unless $dbcm;
|
||||
|
||||
if ($u->{'dversion'} > 6) {
|
||||
$dbcr = LJ::get_cluster_def_reader($u);
|
||||
return $err->($ML{'error.nodb'}) unless $dbcr;
|
||||
$count = $dbcr->selectrow_array("SELECT COUNT(*) FROM userpic2 " .
|
||||
"WHERE userid=? AND state <> 'X'", undef, $u->{'userid'});
|
||||
} else {
|
||||
$dbh = LJ::get_db_writer();
|
||||
return $err->($ML{'error.nodb'}) unless $dbh;
|
||||
$count = $dbh->selectrow_array("SELECT COUNT(*) FROM userpic " .
|
||||
"WHERE userid=? AND state <> 'X'", undef, $u->{'userid'});
|
||||
}
|
||||
my $max = LJ::get_cap($u, "userpics");
|
||||
|
||||
### save mode
|
||||
if (LJ::did_post()) {
|
||||
|
||||
### save changes to existing pics
|
||||
if ($POST{'action:save'}) {
|
||||
# form being posted isn't multipart, since we were able to read from %POST
|
||||
|
||||
my %exist_kwids;
|
||||
if ($u->{'dversion'} > 6) {
|
||||
$sth = $dbcr->prepare("SELECT kwid, picid FROM userpicmap2 WHERE userid=?");
|
||||
} else {
|
||||
$sth = $dbh->prepare("SELECT kwid, picid FROM userpicmap WHERE userid=?");
|
||||
}
|
||||
$sth->execute($u->{'userid'});
|
||||
while (my ($kwid, $picid) = $sth->fetchrow_array) {
|
||||
push @{$exist_kwids{$picid}}, $kwid;
|
||||
}
|
||||
|
||||
my @inactive_picids;
|
||||
my @delete;
|
||||
my %picid_of_kwid;
|
||||
my %ctype; # picid -> contenttype, for delete mode
|
||||
my %states; # picid -> state, for setting new default
|
||||
my %locations; # picid -> location, for deleting
|
||||
my @comments;
|
||||
my %exist_comments;
|
||||
|
||||
# select all of their userpics and iterate through them
|
||||
if ($u->{'dversion'} > 6) {
|
||||
$sth = $dbcr->prepare("SELECT picid, width, height, state, fmt, comment, location " .
|
||||
"FROM userpic2 WHERE userid=?");
|
||||
} else {
|
||||
$sth = $dbh->prepare("SELECT picid, width, height, state, contenttype " .
|
||||
"FROM userpic WHERE userid=?");
|
||||
}
|
||||
$sth->execute($u->{'userid'});
|
||||
while (my $pic = $sth->fetchrow_hashref)
|
||||
{
|
||||
# ignore anything expunged
|
||||
next if $pic->{state} eq 'X';
|
||||
|
||||
# store picture information
|
||||
$states{$pic->{picid}} = $pic->{state};
|
||||
$locations{$pic->{picid}} = $pic->{location}
|
||||
if $u->{dversion} > 6;
|
||||
$exist_comments{$pic->{picid}} = $pic->{comment};
|
||||
|
||||
# delete this pic
|
||||
if ($POST{"delete_$pic->{'picid'}"}) {
|
||||
push @delete, $pic->{'picid'};
|
||||
$ctype{$pic->{picid}} = ($u->{'dversion'} > 6) ? $pic->{'fmt'} : $pic->{'contenttype'};
|
||||
next;
|
||||
}
|
||||
|
||||
# make a list of inactive picids
|
||||
if ($pic->{'state'} eq 'I') {
|
||||
push @inactive_picids, $pic->{'picid'};
|
||||
next;
|
||||
}
|
||||
|
||||
# we're going to modify keywords on active pictures
|
||||
my $c = 1;
|
||||
my @kw_errors;
|
||||
|
||||
my @keywords = split(/\s*,\s*/, $POST{"kw_$pic->{'picid'}"});
|
||||
@keywords = grep { s/^\s+//; s/\s+$//; $_; } @keywords;
|
||||
foreach my $kw (@keywords) {
|
||||
my $kwid = ($u->{'dversion'} > 6) ? LJ::get_keyword_id($u, $kw) : LJ::get_keyword_id($kw);
|
||||
next unless $kwid;
|
||||
|
||||
if ($c > $LJ::MAX_USERPIC_KEYWORDS) {
|
||||
my $ekw = LJ::ehtml($kw);
|
||||
push @kw_errors, $ekw;
|
||||
next;
|
||||
}
|
||||
|
||||
if ($picid_of_kwid{$kwid}) {
|
||||
my $ekw = LJ::ehtml($kw);
|
||||
push @errors, BML::ml(".error.keywords", {'ekw' => $ekw});
|
||||
}
|
||||
$picid_of_kwid{$kwid} = $pic->{'picid'};
|
||||
$c++;
|
||||
}
|
||||
|
||||
# Let the user know about any we didn't save
|
||||
if (@kw_errors) {
|
||||
my $num_words = scalar(@kw_errors);
|
||||
my $kws = join (", ", @kw_errors);
|
||||
push @errors, BML::ml(".error.toomanykeywords", {'numwords' => $num_words, 'words' => $kws, 'max' => $LJ::MAX_USERPIC_KEYWORDS});
|
||||
}
|
||||
|
||||
# Find if they changed the comment and then save the new one
|
||||
if ($u->{'dversion'} > 6 && $POST{"com_$pic->{'picid'}"} ne $exist_comments{$pic->{'picid'}}) {
|
||||
my $comment = LJ::text_trim($POST{"com_$pic->{'picid'}"}, LJ::BMAX_UPIC_COMMENT, LJ::CMAX_UPIC_COMMENT);
|
||||
$u->do("UPDATE userpic2 SET comment=? WHERE userid=? AND picid=?",
|
||||
undef, $comment, $u->{'userid'}, $pic->{'picid'});
|
||||
}
|
||||
}
|
||||
|
||||
# now, reapply the existing picids to the inactive pics, unless
|
||||
# that picid has already been assigned to a new active one
|
||||
foreach my $picid (@inactive_picids) {
|
||||
next unless $exist_kwids{$picid};
|
||||
|
||||
foreach (@{$exist_kwids{$picid}}) {
|
||||
$picid_of_kwid{$_} ||= $picid;
|
||||
}
|
||||
}
|
||||
|
||||
if (@delete) {
|
||||
my $id_in;
|
||||
if ($u->{'dversion'} > 6) {
|
||||
$id_in = join(", ", map { $dbcm->quote($_) } @delete);
|
||||
} else {
|
||||
$id_in = join(", ", map { $dbh->quote($_) } @delete);
|
||||
}
|
||||
|
||||
# delete data from user cluster
|
||||
foreach my $picid (@delete) {
|
||||
my $fmt;
|
||||
if ($u->{'dversion'} > 6) {
|
||||
$fmt = {
|
||||
'G' => 'gif',
|
||||
'J' => 'jpg',
|
||||
'P' => 'png',
|
||||
}->{$ctype{$picid}};
|
||||
} else {
|
||||
$fmt = {
|
||||
'image/gif' => 'gif',
|
||||
'image/jpeg' => 'jpg',
|
||||
'image/png' => 'png',
|
||||
}->{$ctype{$picid}};
|
||||
}
|
||||
|
||||
my $deleted = 0;
|
||||
|
||||
# try and delete from either the blob server or database,
|
||||
# and only after deleting the image do we delete the metadata.
|
||||
if ($locations{$picid} eq 'mogile') {
|
||||
$deleted = 1
|
||||
if LJ::mogclient()->delete($u->mogfs_userpic_key($picid));
|
||||
} elsif ($LJ::USERPIC_BLOBSERVER &&
|
||||
LJ::Blob::delete($u, "userpic", $fmt, $picid)) {
|
||||
$deleted = 1;
|
||||
} elsif ($u->do("DELETE FROM userpicblob2 WHERE ".
|
||||
"userid=? AND picid=?", undef,
|
||||
$u->{userid}, $picid) > 0) {
|
||||
$deleted = 1;
|
||||
}
|
||||
|
||||
# now delete the metadata if we got the real data
|
||||
if ($deleted) {
|
||||
if ($u->{'dversion'} > 6) {
|
||||
$u->do("DELETE FROM userpic2 WHERE picid=? AND userid=?",
|
||||
undef, $picid, $u->{'userid'});
|
||||
} else {
|
||||
$dbh->do("DELETE FROM userpic WHERE picid=?", undef, $picid);
|
||||
}
|
||||
$u->do("DELETE FROM userblob WHERE journalid=? AND blobid=? " .
|
||||
"AND domain=?", undef, $u->{'userid'}, $picid,
|
||||
LJ::get_blob_domainid('userpic'));
|
||||
|
||||
# decrement $count to reflect deletion
|
||||
$count--;
|
||||
}
|
||||
|
||||
# if we didn't end up deleting, it's either because of
|
||||
# some transient error, or maybe there was nothing to delete
|
||||
# for some bizarre reason, in which case we should verify
|
||||
# that and make sure they can delete their metadata
|
||||
if (! $deleted) {
|
||||
my $present;
|
||||
if ($locations{$picid} eq 'mogile') {
|
||||
my $blob = LJ::mogclient()->get_file_data($u->mogfs_userpic_key($picid));
|
||||
$present = length($blob) ? 1 : 0;
|
||||
} elsif ($LJ::USERPIC_BLOBSERVER) {
|
||||
my $blob = LJ::Blob::get($u, "userpic", $fmt, $picid);
|
||||
$present = length($blob) ? 1 : 0;
|
||||
}
|
||||
$present ||= $dbcm->selectrow_array("SELECT COUNT(*) FROM userpicblob2 WHERE ".
|
||||
"userid=? AND picid=?", undef, $u->{'userid'},
|
||||
$picid);
|
||||
if (! int($present)) {
|
||||
if ($u->{'dversion'} > 6) {
|
||||
$u->do("DELETE FROM userpic2 WHERE picid=? AND userid=?",
|
||||
undef, $picid, $u->{'userid'});
|
||||
} else {
|
||||
$dbh->do("DELETE FROM userpic WHERE picid=?", undef, $picid);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# if any of the userpics they want to delete are active, then we want to
|
||||
# re-run LJ::activate_userpics() - turns out it's faster to not check to
|
||||
# see if we need to do this
|
||||
LJ::activate_userpics($u);
|
||||
}
|
||||
|
||||
if (%picid_of_kwid) {
|
||||
if ($u->{'dversion'} > 6) {
|
||||
$u->do("REPLACE INTO userpicmap2 (userid, kwid, picid) VALUES " .
|
||||
join(",", map { "(" .
|
||||
join(",",
|
||||
$dbcm->quote($u->{'userid'}),
|
||||
$dbcm->quote($_),
|
||||
$dbcm->quote($picid_of_kwid{$_})) .
|
||||
")"
|
||||
}
|
||||
keys %picid_of_kwid)
|
||||
);
|
||||
} else {
|
||||
$dbh->do("REPLACE INTO userpicmap (userid, kwid, picid) VALUES " .
|
||||
join(",", map { "(" .
|
||||
join(",",
|
||||
$dbh->quote($u->{'userid'}),
|
||||
$dbh->quote($_),
|
||||
$dbh->quote($picid_of_kwid{$_})) .
|
||||
")"
|
||||
}
|
||||
keys %picid_of_kwid)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
# Delete keywords that are no longer being used
|
||||
my @kwid_del;
|
||||
|
||||
foreach my $kwids (values %exist_kwids) {
|
||||
foreach my $kwid (@$kwids) {
|
||||
if (! $picid_of_kwid{$kwid}) {
|
||||
push @kwid_del, $kwid+0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (@kwid_del) {
|
||||
my $kwid_del = join(",", @kwid_del);
|
||||
if ($u->{'dversion'} > 6) {
|
||||
$u->do("DELETE FROM userpicmap2 WHERE userid=$u->{userid} " .
|
||||
"AND kwid IN ($kwid_del)");
|
||||
} else {
|
||||
$dbh->do("DELETE FROM userpicmap WHERE userid=$u->{userid} " .
|
||||
"AND kwid IN ($kwid_del)");
|
||||
}
|
||||
}
|
||||
|
||||
my $new_default = $POST{'defaultpic'}+0;
|
||||
if ($POST{"delete_$POST{'defaultpic'}"}) {
|
||||
# deleting your default
|
||||
$new_default = 0;
|
||||
}
|
||||
if ($new_default != $u->{'defaultpicid'}) {
|
||||
|
||||
# see if they are trying to make an inactive userpic their default
|
||||
if ($states{$new_default} eq 'N' || !$new_default) {
|
||||
LJ::update_user($u, { defaultpicid => $new_default });
|
||||
$u->{'defaultpicid'} = $new_default;
|
||||
}
|
||||
}
|
||||
|
||||
my $memkey = [$u->{'userid'},"upicinf:$u->{'userid'}"];
|
||||
LJ::MemCache::delete($memkey);
|
||||
$memkey = [$u->{'userid'},"upiccom:$u->{'userid'}"];
|
||||
LJ::MemCache::delete($memkey);
|
||||
$memkey = [$u->{'userid'},"upicurl:$u->{'userid'}"];
|
||||
LJ::MemCache::delete($memkey);
|
||||
}
|
||||
|
||||
### no post, so we'll parse the multipart data
|
||||
unless (%POST) {
|
||||
|
||||
my $MAX_UPLOAD = 40960;
|
||||
|
||||
my $error;
|
||||
# Add some slop to account for the size of the form headers etc.
|
||||
BML::parse_multipart(\%POST, \$error, $MAX_UPLOAD + 2048);
|
||||
|
||||
# was there an error parsing the multipart form?
|
||||
if ($error) {
|
||||
if ($error =~ /^\[(\S+?)\]/) {
|
||||
my $code = $1;
|
||||
if ($code eq "toolarge") {
|
||||
return $err->(BML::ml('.error.filetoolarge',
|
||||
{ 'maxsize' => int($MAX_UPLOAD / 1024) .
|
||||
$ML{'.kilobytes'} }));
|
||||
}
|
||||
$error = BML::ml("BML.parse_multipart.$code");
|
||||
}
|
||||
return $err->($error) if $error;
|
||||
}
|
||||
|
||||
# error check input contents
|
||||
if ($POST{'src'} eq "url" && $POST{'urlpic'} !~ /^http:\/\//) {
|
||||
return $err->($ML{'.error.badurl'});
|
||||
}
|
||||
|
||||
if ($POST{'src'} eq "file") {
|
||||
|
||||
# already loaded from multipart parse earlier
|
||||
|
||||
} elsif ($POST{'src'} eq "url") {
|
||||
require LWPx::ParanoidAgent;
|
||||
my $ua = LWPx::ParanoidAgent->new(
|
||||
timeout => 10,
|
||||
max_size => $MAX_UPLOAD + 1024,
|
||||
);
|
||||
my $res = $ua->get($POST{urlpic});
|
||||
$POST{userpic} = $res->content if $res && $res->is_success;
|
||||
return $err->($ML{'.error.urlerror'}) unless $POST{userpic};
|
||||
}
|
||||
|
||||
if (length($POST{'userpic'}) > $MAX_UPLOAD) {
|
||||
return $err->(BML::ml('.error.filetoolarge',
|
||||
{ 'maxsize' => int($MAX_UPLOAD / 1024) .
|
||||
$ML{'.kilobytes'} }));
|
||||
}
|
||||
|
||||
my ($sx, $sy, $filetype) = Image::Size::imgsize(\$POST{'userpic'});
|
||||
unless (defined $sx) {
|
||||
return $err->($ML{'.error.invalidimage'});
|
||||
}
|
||||
|
||||
unless ($filetype eq "GIF" || $filetype eq "JPG" || $filetype eq "PNG") {
|
||||
return $err->(BML::ml(".error.unsupportedtype",
|
||||
{ 'filetype' => $filetype }));
|
||||
}
|
||||
|
||||
if ($sx > 100 || $sy > 100) {
|
||||
return $err->( BML::ml(".error.imagetoolarge",
|
||||
{ 'imagesize' => "${sx}$ML{'.imagesize.by'}${sy}",
|
||||
'maxsize' => "100$ML{'.imagesize.by'}100" }) );
|
||||
}
|
||||
|
||||
my $base64 = Digest::MD5::md5_base64($POST{'userpic'});
|
||||
|
||||
## see if they have too many pictures uploaded
|
||||
if ($count >= $max) {
|
||||
return $err->( BML::ml(".error.toomanypics2",
|
||||
{ 'maxpics' => $max }) .
|
||||
LJ::help_icon('userpics', " ", ""));
|
||||
}
|
||||
|
||||
# see if it's a duplicate
|
||||
my $picid;
|
||||
my $contenttype;
|
||||
if ($u->{'dversion'} > 6) {
|
||||
if ($filetype eq "GIF") { $contenttype = 'G'; }
|
||||
elsif ($filetype eq "PNG") { $contenttype = 'P'; }
|
||||
elsif ($filetype eq "JPG") { $contenttype = 'J'; }
|
||||
|
||||
$picid = $dbcr->selectrow_array("SELECT picid FROM userpic2 " .
|
||||
"WHERE userid=? AND fmt=? " .
|
||||
"AND md5base64=?",
|
||||
undef, $u->{'userid'}, $contenttype, $base64);
|
||||
} else {
|
||||
if ($filetype eq "GIF") { $contenttype = "image/gif"; }
|
||||
elsif ($filetype eq "PNG") { $contenttype = "image/png"; }
|
||||
elsif ($filetype eq "JPG") { $contenttype = "image/jpeg"; }
|
||||
|
||||
$picid = $dbh->selectrow_array("SELECT picid FROM userpic " .
|
||||
"WHERE userid=? AND contenttype=? " .
|
||||
"AND md5base64=?",
|
||||
undef, $u->{'userid'}, $contenttype, $base64);
|
||||
}
|
||||
# if picture isn't a duplicate, insert it
|
||||
if ($picid == 0) {
|
||||
|
||||
# insert the meta-data
|
||||
# Make a new global picid
|
||||
$picid = LJ::alloc_global_counter('P') or
|
||||
return $err->('Unable to allocate new picture id');
|
||||
|
||||
# see where we're inserting this
|
||||
my $target;
|
||||
if ($u->{dversion} > 6 && $LJ::USERPIC_MOGILEFS) {
|
||||
$target = 'mogile';
|
||||
} elsif ($LJ::USERPIC_BLOBSERVER) {
|
||||
$target = 'blob';
|
||||
}
|
||||
|
||||
my $dberr = 0;
|
||||
if ($u->{'dversion'} > 6) {
|
||||
$u->do("INSERT INTO userpic2 (picid, userid, fmt, width, height, " .
|
||||
"picdate, md5base64, location) VALUES (?, ?, ?, ?, ?, NOW(), ?, ?)",
|
||||
undef, $picid, $u->{'userid'}, $contenttype, $sx, $sy, $base64, $target);
|
||||
if ($u->err) {
|
||||
push @errors, $err->($u->errstr);
|
||||
$dberr = 1;
|
||||
}
|
||||
} else {
|
||||
$dbh->do("INSERT INTO userpic (picid, userid, contenttype, width, height, " .
|
||||
"picdate, md5base64) VALUES (?, ?, ?, ?, ?, NOW(), ?)",
|
||||
undef, $picid, $u->{'userid'}, $contenttype, $sx, $sy, $base64);
|
||||
if ($dbh->err) {
|
||||
push @errors, $err->($dbh->errstr);
|
||||
$dberr = 1;
|
||||
}
|
||||
}
|
||||
|
||||
my $clean_err = sub {
|
||||
if ($u->{'dversion'} > 6) {
|
||||
$u->do("DELETE FROM userpic2 WHERE userid=? AND picid=?",
|
||||
undef, $u->{'userid'}, $picid) if $picid;
|
||||
} else {
|
||||
$dbh->do("DELETE FROM userpic WHERE picid=?", undef, $picid) if $picid;
|
||||
}
|
||||
return $err->(@_);
|
||||
};
|
||||
|
||||
### insert the blob
|
||||
if ($target eq 'mogile' && !$dberr) {
|
||||
my $fh = LJ::mogclient()->new_file($u->mogfs_userpic_key($picid), 'userpics');
|
||||
if (defined $fh) {
|
||||
$fh->print($POST{'userpic'});
|
||||
my $rv = $fh->close;
|
||||
push @errors, $clean_err->("Error saving to storage server: $@") unless $rv;
|
||||
} else {
|
||||
# fatal error, we couldn't get a filehandle to use
|
||||
push @errors, $clean_err->("Unable to contact storage server. Your picture has not been saved.");
|
||||
}
|
||||
} elsif ($target eq 'blob' && !$dberr) {
|
||||
my $et;
|
||||
my $fmt = lc($filetype);
|
||||
my $rv = LJ::Blob::put($u, "userpic", $fmt, $picid, $POST{'userpic'}, \$et);
|
||||
push @errors, $clean_err->("Error saving to media server: $et") unless $rv;
|
||||
} elsif (!$dberr) {
|
||||
my $dbcm = LJ::get_cluster_master($u);
|
||||
return $err->($ML{'error.nodb'}) unless $dbcm;
|
||||
$u->do("INSERT INTO userpicblob2 (userid, picid, imagedata) " .
|
||||
"VALUES (?, ?, ?)",
|
||||
undef, $u->{'userid'}, $picid, $POST{'userpic'});
|
||||
push @errors, $clean_err->($u->errstr) if $u->err;
|
||||
} else { # We should never get here!
|
||||
push @errors, "User picture uploading failed for unknown reason";
|
||||
}
|
||||
|
||||
# Not a duplicate, so increment $count
|
||||
$count++;
|
||||
}
|
||||
|
||||
# make it their default pic?
|
||||
if ($POST{'make_default'}) {
|
||||
LJ::update_user($u, { defaultpicid => $picid });
|
||||
$u->{'defaultpicid'} = $picid;
|
||||
}
|
||||
|
||||
# set default keywords?
|
||||
if ($POST{'keywords'} ne '') {
|
||||
if ($u->{'dversion'} > 6) {
|
||||
$sth = $dbcr->prepare("SELECT kwid, picid FROM userpicmap2 WHERE userid=?");
|
||||
} else {
|
||||
$sth = $dbh->prepare("SELECT kwid, picid FROM userpicmap WHERE userid=?");
|
||||
}
|
||||
$sth->execute($u->{'userid'});
|
||||
|
||||
my @exist_kwids;
|
||||
while (my ($kwid, $picid) = $sth->fetchrow_array) {
|
||||
$exist_kwids[$kwid] = $picid;
|
||||
}
|
||||
|
||||
my @keywords = split(/\s*,\s*/, $POST{'keywords'});
|
||||
@keywords = grep { s/^\s+//; s/\s+$//; $_; } @keywords;
|
||||
|
||||
my (@bind, @data, @kw_errors);
|
||||
my $c = 0;
|
||||
|
||||
foreach my $kw (@keywords) {
|
||||
my $kwid = ($u->{'dversion'} > 6) ? LJ::get_keyword_id($u, $kw) : LJ::get_keyword_id($kw);
|
||||
next unless $kwid; # Houston we have a problem! This should always return an id.
|
||||
|
||||
if ($c > $LJ::MAX_USERPIC_KEYWORDS) {
|
||||
my $ekw = LJ::ehtml($kw);
|
||||
push @kw_errors, $ekw;
|
||||
next;
|
||||
}
|
||||
|
||||
if ($exist_kwids[$kwid]) { # Already used on another picture
|
||||
my $ekw = LJ::ehtml($kw);
|
||||
push @errors, BML::ml(".error.keywords", {'ekw' => $ekw});
|
||||
next;
|
||||
} else { # New keyword, so save it
|
||||
push @bind, '(?, ?, ?)';
|
||||
push @data, $u->{'userid'}, $kwid, $picid;
|
||||
}
|
||||
$c++;
|
||||
}
|
||||
|
||||
# Let the user know about any we didn't save
|
||||
if (@kw_errors) {
|
||||
my $num_words = scalar(@kw_errors);
|
||||
my $kws = join (", ", @kw_errors);
|
||||
push @errors, BML::ml(".error.toomanykeywords", {'numwords' => $num_words, 'words' => $kws, 'max' => $LJ::MAX_USERPIC_KEYWORDS});
|
||||
}
|
||||
|
||||
if (@data && @bind) {
|
||||
my $bind = join(',', @bind);
|
||||
|
||||
if ($u->{'dversion'} > 6) {
|
||||
$u->do("INSERT INTO userpicmap2 (userid, kwid, picid) VALUES $bind",
|
||||
undef, @data);
|
||||
} else {
|
||||
$dbh->do("INSERT INTO userpicmap (userid, kwid, picid) VALUES $bind",
|
||||
undef, @data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# set default comments and the url
|
||||
if ($u->{'dversion'} > 6) {
|
||||
my (@data, @set);
|
||||
if ($POST{'comments'} ne '') {
|
||||
push @set, 'comment=?';
|
||||
push @data, LJ::text_trim($POST{'comments'}, LJ::BMAX_UPIC_COMMENT, LJ::CMAX_UPIC_COMMENT);
|
||||
}
|
||||
|
||||
if ($POST{'url'} ne '') {
|
||||
push @set, 'url=?';
|
||||
push @data, $POST{'url'};
|
||||
}
|
||||
|
||||
if (@set) {
|
||||
my $set = join(',', @set);
|
||||
|
||||
$u->do("UPDATE userpic2 SET $set WHERE userid=? AND picid=?",
|
||||
undef, @data, $u->{'userid'}, $picid);
|
||||
}
|
||||
}
|
||||
|
||||
my $memkey = [$u->{'userid'},"upicinf:$u->{'userid'}"];
|
||||
LJ::MemCache::delete($memkey);
|
||||
|
||||
$returl = LJ::CleanHTML::canonical_url($POST{'ret'});
|
||||
if ($returl) {
|
||||
my $redir_host = $1 if $returl =~ m#^http://([\.:\w-]+)#i;
|
||||
return BML::redirect($returl) if $LJ::REDIRECT_ALLOWED{$redir_host};
|
||||
}
|
||||
}
|
||||
|
||||
# now fall through to edit page and show the updated userpic info
|
||||
}
|
||||
|
||||
if ($fotobilder && $POST{'md5sum'}) {
|
||||
my $id;
|
||||
if ($u->{'dversion'} > 6) {
|
||||
$id = $dbcm->selectrow_array("SELECT picid FROM userpic2 WHERE userid=? " .
|
||||
"AND md5base64=?", undef, $u->{'userid'}, $POST{'md5sum'});
|
||||
} else {
|
||||
$id = $dbh->selectrow_array("SELECT picid FROM userpic WHERE userid=? " .
|
||||
"AND md5base64=?", undef, $u->{'userid'}, $POST{'md5sum'});
|
||||
}
|
||||
|
||||
$fotobilder = 0 if $id;
|
||||
}
|
||||
|
||||
# show the form to let people edit
|
||||
$title = "Edit User Pictures";
|
||||
|
||||
# Fixme: Make this work with Fotobilder
|
||||
if (!$fotobilder) {
|
||||
# authas switcher form
|
||||
$body .= "<form method='get' action='editpics.bml'>\n";
|
||||
$body .= LJ::make_authas_select($remote, { 'authas' => $GET{'authas'} }) . "\n";
|
||||
$body .= "</form>\n\n";
|
||||
}
|
||||
|
||||
if (@errors) {
|
||||
$body .= LJ::error_list(@errors);
|
||||
}
|
||||
|
||||
if (!$fotobilder) {
|
||||
my %keywords = ();
|
||||
my $dbcr = LJ::get_cluster_def_reader($u);
|
||||
if ($u->{'dversion'} > 6) {
|
||||
$sth = $dbcr->prepare("SELECT m.picid, k.keyword FROM userpicmap2 m, userkeywords k ".
|
||||
"WHERE m.userid=? AND m.kwid=k.kwid AND m.userid=k.userid");
|
||||
} else {
|
||||
$sth = $dbh->prepare("SELECT m.picid, k.keyword FROM userpicmap m, keywords k ".
|
||||
"WHERE m.userid=? AND m.kwid=k.kwid");
|
||||
}
|
||||
$sth->execute($u->{'userid'});
|
||||
while (my ($pic, $keyword) = $sth->fetchrow_array) {
|
||||
LJ::text_out(\$keyword);
|
||||
push @{$keywords{$pic}}, $keyword;
|
||||
}
|
||||
|
||||
if ($u->{'dversion'} > 6) {
|
||||
$sth = $dbcr->prepare("SELECT picid, width, height, state, comment " .
|
||||
"FROM userpic2 WHERE userid=?");
|
||||
} else {
|
||||
$sth = $dbh->prepare("SELECT picid, width, height, state " .
|
||||
"FROM userpic WHERE userid=?");
|
||||
}
|
||||
$sth->execute($u->{'userid'});
|
||||
my @sortedpics;
|
||||
push @sortedpics, $_ while $_ = $sth->fetchrow_hashref;
|
||||
|
||||
|
||||
# See if they have any without keywords before we output the display table
|
||||
foreach (@sortedpics) {
|
||||
unless ($keywords{$_->{'picid'}}) {
|
||||
my @w;
|
||||
if (defined $LJ::HELPURL{'upic_keywords'}) {
|
||||
push @w, BML::ml('.warning.keywords.faq', {'aopts' => "href='$LJ::HELPURL{'upic_keywords'}'"});
|
||||
} else {
|
||||
push @w, $ML{'.warning.keywords'};
|
||||
}
|
||||
|
||||
$body .= LJ::warning_list(@w);
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
my $piccount = 0;
|
||||
foreach my $pic (sort { $a->{picid} <=> $b->{picid} } @sortedpics)
|
||||
{
|
||||
my $pid = $pic->{'picid'};
|
||||
|
||||
if ($piccount++ == 0) {
|
||||
$body .= "<?h1 $ML{'.curpics'} h1?><?p $ML{'.curpics.desc'} p?>";
|
||||
$body .= "<?p <strong>". BML::ml('.piclimitstatus', {current => $count, max => $max}) . "</strong> p?>";
|
||||
|
||||
$body .= "<form method='post' action='editpics.bml$getextra'>";
|
||||
$body .= "<table cellpadding='5' border='0' cellspacing='1' " .
|
||||
"style='margin-left: 30px'>";
|
||||
}
|
||||
$body .= "<tr valign='middle'>";
|
||||
$body .= "<td align='center'><img src='$LJ::USERPIC_ROOT/$pid/$u->{'userid'}' width='$pic->{'width'}' height='$pic->{'height'}'></td>";
|
||||
$body .= "<td>\n<table>";
|
||||
|
||||
my ($dis, $distxt);
|
||||
{
|
||||
$body .= "<tr><td align='right'><b><label for='$pid-def'>$ML{'.label.default'}</label></b></td><td> ";
|
||||
$body .= LJ::html_check({ 'type' => 'radio', 'name' => 'defaultpic', 'value' => $pid,
|
||||
'selected' => $u->{'defaultpicid'} == $pid,
|
||||
'disabled' => $pic->{'state'} eq 'I' });
|
||||
|
||||
$body .= " <b><label for='$pid-del'>$ML{'.label.delete'}</label></b> ";
|
||||
$body .= LJ::html_check({ 'type' => 'checkbox', 'name' => "delete_$pid",
|
||||
'id' => "$pid-del", 'value' => 1 });
|
||||
|
||||
if ($pic->{'state'} eq 'I') {
|
||||
$body .= " <i>[$ML{'userpic.inactive'}]</i> " . LJ::help_icon('userpic_inactive');
|
||||
}
|
||||
|
||||
$body .= "</td></tr>\n";
|
||||
}
|
||||
|
||||
{
|
||||
my $keywords;
|
||||
$keywords = join(", ", sort { lc($a) cmp lc($b) } @{$keywords{$pic->{'picid'}}})
|
||||
if $keywords{$pid};
|
||||
|
||||
$body .= "<tr><td align='right'><b><label for='$pid-key'>$ML{'.label.keywords'}</label></b></td><td> ";
|
||||
$body .= LJ::html_text({'name' => "kw_$pid", 'id' => "$pid-key",
|
||||
'size' => '30', 'value' => $keywords,
|
||||
'disabled' => $pic->{'state'} eq 'I' });
|
||||
|
||||
$body .= "</td></tr>\n";
|
||||
|
||||
if ($u->{'dversion'} > 6) {
|
||||
$body .= "<tr><td align='right'><b><label for='$pid-com'>$ML{'.label.comment'}</label></b></td><td> ";
|
||||
$body .= LJ::html_text({ 'name' => "com_$pid", 'id' => "$pid-com",
|
||||
'size' => '30', 'value' => $pic->{'comment'},
|
||||
'maxlength' => LJ::CMAX_UPIC_COMMENT,
|
||||
'disabled' => $pic->{'state'} eq 'I' });
|
||||
|
||||
$body .= "</td></tr>\n";
|
||||
}
|
||||
}
|
||||
|
||||
$body .= "</table>\n</td></tr>\n";
|
||||
}
|
||||
|
||||
if ($piccount) {
|
||||
$body .= "<tr><td></td><td align=left> <b><label for='nodefpic'>$ML{'.nodefault'}</label></b> ";
|
||||
$body .= LJ::html_check({ 'name' => 'defaultpic',
|
||||
'value' => 0,
|
||||
'type' => 'radio',
|
||||
'selected' => ! $u->{'defaultpicid'},
|
||||
'raw' => "id='nodefpic'" });
|
||||
|
||||
$body .= "</td><td> </td></tr>\n";
|
||||
$body .= "<tr><td></td><td> " . LJ::html_submit('action:save', $ML{'.btn.save'}) . "</td></tr>\n";
|
||||
$body .= "</table>";
|
||||
$body .= "</form>";
|
||||
} else {
|
||||
$body .= "<?h1 $ML{'.nopics'} h1?><?p $ML{'.noneupload'} p?>";
|
||||
}
|
||||
}
|
||||
|
||||
# let users upload more pics
|
||||
$body .= "<a name='upload'></a>";
|
||||
|
||||
if ($count < $max) {
|
||||
if ($fotobilder) {
|
||||
$body .= "<?h1 $ML{'.uploadheader.fb'} h1?>\n";
|
||||
$body .= "<?p " . BML::ml('.uploaddesc.fb', {'aopts' => "href='$LJ::FB_SITEROOT'", 'sitename' => $LJ::FB_SITENAME}) . " p?>\n\n";
|
||||
} else {
|
||||
$body .= "<?h1 $ML{'.uploadheader'} h1?>\n";
|
||||
$body .= "<?p $ML{'.uploaddesc'} p?>\n\n";
|
||||
|
||||
$body .= "<ul>\n";
|
||||
foreach (qw(filesize imagesize fileformat)) {
|
||||
$body .= "<li>" . $ML{".restriction.$_"} . "</li>\n";
|
||||
}
|
||||
|
||||
# Keywords is a little different
|
||||
$body .= "<li>";
|
||||
if (defined $LJ::HELPURL{'upic_keywords'}) {
|
||||
$body .= BML::ml('.restriction.keywords.faq', {'aopts' => "href='$LJ::HELPURL{'upic_keywords'}'"});
|
||||
} else {
|
||||
$body .= $ML{'.restriction.keywords'};
|
||||
}
|
||||
|
||||
$body .= "</li>";
|
||||
$body .= "</ul>\n";
|
||||
}
|
||||
|
||||
# upload form
|
||||
$body .= "<?standout \n";
|
||||
$body .= "<form action='editpics.bml$getextra' method='post' " .
|
||||
"enctype='multipart/form-data' style='display: inline;'>\n";
|
||||
|
||||
$body .= "<table>\n";
|
||||
|
||||
if ($fotobilder) {
|
||||
$body .= "<tr><td colspan='3' align='center'>\n";
|
||||
$body .= "<img src='$picurl' />";
|
||||
my $url = LJ::CleanHTML::canonical_url($POST{'url'});
|
||||
$body .= LJ::html_hidden('src', 'url', 'urlpic', $picurl, 'url', $url, 'ret' => $returl);
|
||||
} else {
|
||||
$body .= "<tr><td align='right'>\n";
|
||||
$body .= LJ::html_check({ 'type' => 'radio', 'name' => 'src', 'id' => 'radio_file',
|
||||
'value' => 'file', 'selected' => '1',
|
||||
'accesskey' => $ML{'.fromfile.key'} });
|
||||
$body .= "</td><td align='right'>";
|
||||
$body .= "<label for='radio_file'>$ML{'.fromfile'}</label></td>";
|
||||
$body .= "<td align='left'><input type='file' name='userpic' size='28' /></td></tr>\n";
|
||||
|
||||
$body .= "<tr><td align='right'>";
|
||||
$body .= LJ::html_check({ 'type' => 'radio', 'name' => 'src', 'value' => 'url',
|
||||
'id' => 'radio_url', 'accesskey' => $ML{'.fromurl.key'} });
|
||||
$body .= "</td><td align='right'>";
|
||||
$body .= "<label for='radio_url'>$ML{'.fromurl'}</label></td><td align='left'>";
|
||||
$body .= LJ::html_text({ 'name' => 'urlpic', 'size' => '40' }) . "</td></tr>\n";
|
||||
}
|
||||
|
||||
$body .= "<tr><td colspan='3' align='center'><hr></td></tr>";
|
||||
|
||||
$body .= "<tr><td align='right'>";
|
||||
$body .= LJ::help_icon('upic_keywords');
|
||||
$body .= "</td><td align='right'><label for='keywords'>";
|
||||
$body .= "$ML{'.label.keywords'}</label></td><td align='left'>";
|
||||
$body .= LJ::html_text({ 'name' => 'keywords', 'size' => '40' });
|
||||
$body .= "</td></tr>";
|
||||
|
||||
if ($u->{'dversion'} > 6) {
|
||||
$body .= "<tr><td align='right'>";
|
||||
$body .= LJ::help_icon('upic_comments');
|
||||
$body .= "</td><td align='right'><label for='comments'>$ML{'.label.comment'}</label></td><td align='left'>";
|
||||
my $comments = $POST{'comments'} if $fotobilder;
|
||||
$body .= LJ::html_text({ 'name' => 'comments', 'size' => '40', 'maxlength' => LJ::CMAX_UPIC_COMMENT, 'value', $comments });
|
||||
$body .= "</td></tr>";
|
||||
}
|
||||
|
||||
$body .= "<tr><td colspan='2'> </td><td align='left'>";
|
||||
$body .= LJ::html_check({ 'type' => 'checkbox',
|
||||
'name' => 'make_default',
|
||||
'id' => 'make_default',
|
||||
'selected' => '1', 'value' => '1',
|
||||
'accesskey' => $ML{'.makedefault.key'} });
|
||||
|
||||
$body .= "<label for='make_default'>$ML{'.makedefault'}</label></td></tr>\n";
|
||||
|
||||
$body .= "<tr><td colspan='3' align='center'><br />" .LJ::html_submit(undef, $ML{'.btn.proceed'}) . "</td></tr>\n";
|
||||
$body .= "</table>\n</form>\n";
|
||||
} else {
|
||||
$body .= "<?standout \n";
|
||||
$body .= BML::ml(".error.toomanypics3", { 'max' => $max });
|
||||
}
|
||||
|
||||
$body .= " standout?>\n\n";
|
||||
|
||||
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
_code?><?page
|
||||
title=><?_code return $title; _code?>
|
||||
body=><?_code return $body; _code?>
|
||||
page?><?_c <LJDEP>
|
||||
link: htdocs/login.bml, htdocs/allpics.bml
|
||||
post: htdocs/editpics.bml
|
||||
</LJDEP> _c?>
|
||||
124
livejournal/htdocs/edittags.bml
Executable file
@@ -0,0 +1,124 @@
|
||||
<?page
|
||||
title=><?_code $ML{'.title'} _code?>
|
||||
body<=
|
||||
<?_code
|
||||
{
|
||||
use strict;
|
||||
use vars qw($GET $POST);
|
||||
|
||||
my $remote = LJ::get_remote();
|
||||
return "<?needlogin?>" unless $remote;
|
||||
|
||||
my $err = sub { return "<?h1 $ML{'Error'} h1?><?p $_[0] p?>"; };
|
||||
return $err->($ML{'.disabled'})
|
||||
if $LJ::DISABLED{tags};
|
||||
|
||||
my ($ret, $msg);
|
||||
|
||||
return $err->($ML{'.invalid.link'})
|
||||
unless LJ::did_post() || ($GET{journal} && $GET{itemid});
|
||||
|
||||
my $journal = $GET{journal} || $POST{journal};
|
||||
my $u = LJ::load_user($journal);
|
||||
return $err->($ML{'.invalid.journal'}) unless $u;
|
||||
|
||||
my $ditemid = ($GET{itemid} || $POST{itemid})+0;
|
||||
my $anum = $ditemid % 256;
|
||||
my $jitemid = $ditemid >> 8;
|
||||
return $err->($ML{'.invalid.entry'}) unless $jitemid;
|
||||
|
||||
my $logrow = LJ::get_log2_row($u, $jitemid);
|
||||
return $err->($ML{'.invalid.entry'}) unless $logrow;
|
||||
return $err->($ML{'.invalid.entry'}) unless $logrow->{anum} == $anum;
|
||||
return $err->($ML{'.invalid.notauthorized'})
|
||||
unless LJ::can_view($remote, $logrow);
|
||||
|
||||
if (LJ::did_post()) {
|
||||
return $err->($ML{'.invalid.link'})
|
||||
unless LJ::check_form_auth();
|
||||
|
||||
LJ::Tags::update_logtags($u, $jitemid, {
|
||||
set_string => $POST{edittags},
|
||||
remote => $remote,
|
||||
});
|
||||
|
||||
BML::redirect( LJ::journal_base($u) . "/$ditemid.html" );
|
||||
#$msg = "<div class='update_good'>Tags successfully updated.</div>";
|
||||
}
|
||||
|
||||
my $lt2 = LJ::get_logtext2($u, $jitemid);
|
||||
my ($subj, $evt) = @{$lt2->{$jitemid} || []};
|
||||
return $err->($ML{'.error.db'}) unless $evt;
|
||||
|
||||
LJ::CleanHTML::clean_subject(\$subj);
|
||||
LJ::CleanHTML::clean_event(\$evt);
|
||||
|
||||
my $logtags = LJ::Tags::get_logtags($u, $jitemid);
|
||||
my $usertags = LJ::Tags::get_usertags($u, { remote => $remote }) || {};
|
||||
$logtags = $logtags->{$jitemid} || {};
|
||||
my $logtagstr = join ', ', map { LJ::ejs($_) } sort values %$logtags;
|
||||
|
||||
$ret .= "<?p $ML{'.intro'} p?><br />";
|
||||
$ret .= "<script type='text/javascript'> var cur_taglist = '$logtagstr'; </script>";
|
||||
|
||||
$ret .= '<table class="edittbl" cellpadding="0" cellspacing="0" width="50%">';
|
||||
$ret .= "<tr><td class='l'>$ML{'.subject'}</td><td>$subj</td></tr>" if $subj;
|
||||
$ret .= "<tr><td class='l'>$ML{'.entry'}</td><td>$evt</td></tr>";
|
||||
$ret .= "<tr><td class='l'> </td><td> </td></tr>"; # spacer
|
||||
|
||||
$ret .= "<tr><td class='l'>$ML{'.current'}</td>";
|
||||
$ret .= '<form method="POST" action="/edittags.bml" id="edit_tagform">';
|
||||
$ret .= LJ::form_auth();
|
||||
$ret .= "<td class='sep'>";
|
||||
if ( LJ::Tags::can_add_tags($u, $remote) ) {
|
||||
$ret .= LJ::html_text(
|
||||
{
|
||||
name => 'edittags',
|
||||
value => (join ', ', sort values %$logtags),
|
||||
size => 40,
|
||||
class => 'tagfield',
|
||||
id => 'tagfield',
|
||||
}
|
||||
);
|
||||
$ret .= ' ';
|
||||
$ret .= LJ::html_submit( 'save', $ML{'.button.save'}, { class => 'btn' });
|
||||
$ret .= $msg if $msg;
|
||||
} else {
|
||||
# no widgets
|
||||
$ret .= $ML{'.permissions.none'};
|
||||
}
|
||||
$ret .= "</td></tr>";
|
||||
|
||||
$ret .= "<tr><td class='l'>$ML{'.users'}</td><td class='curtags'>";
|
||||
|
||||
if ( scalar keys %$usertags ) {
|
||||
$ret .= "<select name='tags' multiple='multiple' class='tagbox_nohist' " .
|
||||
"onChange='edit_tagselect(this)'>";
|
||||
foreach (sort { $a->{name} cmp $b->{name} } values %$usertags) {
|
||||
$ret .= "<option value='" . LJ::ehtml($_->{name}) . "'>" . LJ::ehtml($_->{name}) . "</option>";
|
||||
}
|
||||
$ret .= "</select>";
|
||||
} else {
|
||||
$ret .= "none"
|
||||
}
|
||||
|
||||
$ret .= "<br /><br />";
|
||||
$ret .= "$ML{'.permissions.add.yes'}<br />" if LJ::Tags::can_add_tags($u, $remote);
|
||||
$ret .= "$ML{'.permissions.control.yes'}<br />" if LJ::Tags::can_control_tags($u, $remote);
|
||||
$ret .= BML::ml('.view', { aopts => 'href="' . LJ::journal_base($u) . "/$ditemid.html" . '"' });
|
||||
$ret .= "</td></tr>";
|
||||
|
||||
$ret .= '</table>';
|
||||
$ret .= LJ::html_hidden('journal', $journal);
|
||||
$ret .= LJ::html_hidden('itemid', $GET{itemid} || $POST{itemid});
|
||||
$ret .= '</form>';
|
||||
|
||||
return $ret;
|
||||
}
|
||||
_code?>
|
||||
<=body
|
||||
head<=
|
||||
<link rel='stylesheet' type='text/css' href='/styles/tags.css' />
|
||||
<script type="text/javascript" src="/js/tags.js"></script>
|
||||
<=head
|
||||
page?>
|
||||
109
livejournal/htdocs/export.bml
Executable file
@@ -0,0 +1,109 @@
|
||||
<?page
|
||||
title=><?_ml .title _ml?>
|
||||
|
||||
body<=
|
||||
|
||||
<?_code
|
||||
{
|
||||
use strict;
|
||||
use vars qw(%GET);
|
||||
|
||||
LJ::set_active_crumb('export');
|
||||
|
||||
my $remote = LJ::get_remote();
|
||||
return "<?needlogin?>"
|
||||
unless $remote;
|
||||
|
||||
my $ret;
|
||||
my $authas = $GET{'authas'} || $remote->{'user'};
|
||||
|
||||
# no authentication needs to be done on this page, it's just a form anyway
|
||||
|
||||
# user switcher
|
||||
$ret .= "<form action='export.bml' method='get'>\n";
|
||||
$ret .= LJ::make_authas_select($remote, { 'authas' => $GET{'authas'} });
|
||||
$ret .= "</form>\n\n";
|
||||
|
||||
$ret .= "<?h1 <?_ml .title _ml?> h1?>\n";
|
||||
$ret .= "<?p <?_ml .description _ml?> p?>\n";
|
||||
|
||||
$ret .= "<form action='export_do.bml?authas=$authas' method='post'>\n";
|
||||
|
||||
# main form
|
||||
$ret .= <<'HTMLBLOCK';
|
||||
|
||||
<?standout
|
||||
<table>
|
||||
<tr valign='top'><td><?_ml .label.what _ml?></td>
|
||||
<td>
|
||||
<select name="what" id="what">
|
||||
<option value="journal"><?_ml .what.entries _ml?></option>
|
||||
</select>
|
||||
</td></tr>
|
||||
|
||||
<tr valign='middle'><td><?_ml .label.month _ml?></td>
|
||||
<td>
|
||||
<?_ml .label.month.year _ml?> <input name="year" size='4' maxlength='4' /> -
|
||||
<?_ml .label.month.month _ml?> <input name="month" size='2' maxlength='2' />
|
||||
</td></tr>
|
||||
|
||||
<tr valign='top'><td><?_ml .label.format _ml?></td>
|
||||
<td>
|
||||
<select name="format">
|
||||
<option value="csv"><?_ml .format.csv _ml?></option>
|
||||
<option value="xml"><?_ml .format.xml _ml?></option>
|
||||
</select><br />
|
||||
<input type='checkbox' name="header" id="header" checked='checked' /> <label for="header"><?_ml .label.header _ml?></label><br />
|
||||
<?_ml .label.encoding _ml?>
|
||||
HTMLBLOCK
|
||||
|
||||
# unicode encoding selection
|
||||
if ($LJ::UNICODE) {
|
||||
my (%encodings, %encnames);
|
||||
LJ::load_codes({ "encoding" => \%encodings } );
|
||||
LJ::load_codes({ "encname" => \%encnames } );
|
||||
my $selected = 0;
|
||||
foreach my $id (keys %encodings) {
|
||||
$selected = $id if lc($encodings{$id}) eq 'utf-8';
|
||||
delete $encnames{$id} if lc($encodings{$id}) eq 'none';
|
||||
}
|
||||
$ret .= LJ::html_select({'name'=>'encid', 'selected'=>$selected},
|
||||
map { $_, $encnames{$_} } sort keys %encnames);
|
||||
} else {
|
||||
$ret .= "<input type='text' name='encoding' size='15' maxlength='15' value='iso-8859-1' />";
|
||||
}
|
||||
$ret .= "<br />\n";
|
||||
|
||||
$ret .= <<'HTMLBLOCK';
|
||||
|
||||
<input type='checkbox' name="notranslation" id="notranslation" /> <label for="notranslation"><?_ml .label.notranslation _ml?></label><br />
|
||||
|
||||
</td></tr>
|
||||
<tr><td colspan='2'><hr /></td></tr>
|
||||
<tr valign='top'><td><?_ml .fields _ml?></td>
|
||||
<td>
|
||||
<input type='checkbox' name="field_itemid" id="field_itemid" checked='checked' /> <label for="field_itemid"><?_ml .label.field.itemid _ml?></label><br />
|
||||
<input type='checkbox' name="field_eventtime" id="field_eventtime" checked='checked' /> <label for="field_eventtime"><?_ml .label.field.eventtime _ml?></label><br />
|
||||
<input type='checkbox' name="field_logtime" id="field_logtime" checked='checked' /> <label for="field_logtime"><?_ml .label.field.logtime _ml?></label><br />
|
||||
<input type='checkbox' name="field_subject" id="field_subject" checked='checked' /> <label for="field_subject"><?_ml .label.field.subject _ml?></label><br />
|
||||
<input type='checkbox' name="field_event" id="field_event" checked='checked' /> <label for="field_event"><?_ml .label.field.event _ml?></label><br />
|
||||
<input type='checkbox' name="field_security" id="field_security" checked='checked' /> <label for="field_security"><?_ml .label.field.security _ml?></label><br />
|
||||
<input type='checkbox' name="field_allowmask" id="field_allowmask" checked='checked' /> <label for="field_allowmask"><?_ml .label.field.allowmask _ml?></label><br />
|
||||
<input type='checkbox' name='field_currents' id="field_currents" checked='checked' /> <label for="field_currents"><?_ml .label.field.currents _ml?></label><br />
|
||||
</td></tr>
|
||||
|
||||
<tr><td></td><td><input type="submit" value="<?_ml .btn.proceed _ml?>" /></td></tr>
|
||||
</table>
|
||||
standout?>
|
||||
</form>
|
||||
|
||||
<?h1 <?_ml lostinfo.head _ml?> h1?>
|
||||
<?p <?_ml lostinfo.text _ml?> p?>
|
||||
HTMLBLOCK
|
||||
|
||||
}
|
||||
_code?>
|
||||
<=body
|
||||
page?><?_c <LJDEP>
|
||||
post: htdocs/export_do.bml
|
||||
</LJDEP> _c?>
|
||||
158
livejournal/htdocs/export_comments.bml
Executable file
@@ -0,0 +1,158 @@
|
||||
<?_code
|
||||
{
|
||||
use strict;
|
||||
use vars qw(%GET);
|
||||
|
||||
my $req = shift;
|
||||
my $r = $req->{'r'};
|
||||
|
||||
my $remote = LJ::get_remote();
|
||||
return "<?needlogin?>" unless $remote;
|
||||
|
||||
my $authas = $GET{'authas'} || $remote->{'user'};
|
||||
my $u = LJ::get_authas_user($authas);
|
||||
return LJ::bad_input($ML{'error.invalidauth'}) unless $u;
|
||||
|
||||
my @errors = ();
|
||||
|
||||
my $dbcr = LJ::get_cluster_reader($u);
|
||||
push @errors, $ML{'error.nodb'} unless $dbcr;
|
||||
|
||||
# don't let people hit us with silly GET attacks
|
||||
push @errors, "This page can't be viewed except via POST."
|
||||
if BML::get_client_header('Referer') && !LJ::did_post();
|
||||
|
||||
my $mode = $GET{get};
|
||||
push @errors, "Invalid mode."
|
||||
unless $mode =~ m/^comment_(?:meta|body)$/;
|
||||
|
||||
# error stuff
|
||||
return LJ::bad_input(@errors) if @errors;
|
||||
|
||||
# from now on, we manage our own output
|
||||
BML::suppress_headers();
|
||||
BML::suppress_content();
|
||||
|
||||
# print top
|
||||
$r->content_type("text/xml; charset=utf-8");
|
||||
$r->send_http_header();
|
||||
$r->print("<?xml version=\"1.0\" encoding='utf-8'?>\n<livejournal>\n");
|
||||
|
||||
# startid specified?
|
||||
my $gather = $mode eq 'comment_meta' ? 10000 : 1000;
|
||||
my $startid = $GET{startid}+0;
|
||||
my $endid = $startid + $gather;
|
||||
|
||||
# get metadata
|
||||
my $rows = $dbcr->selectall_arrayref('SELECT jtalkid, nodeid, parenttalkid, posterid, state, datepost ' .
|
||||
"FROM talk2 WHERE nodetype = 'L' AND journalid = ? AND " .
|
||||
" jtalkid >= $startid AND jtalkid < $endid",
|
||||
undef, $u->{userid});
|
||||
|
||||
# now let's gather them all together while making a list of posterids
|
||||
my %posterids;
|
||||
my %comments;
|
||||
foreach my $r (@{$rows || []}) {
|
||||
$comments{$r->[0]} = {
|
||||
nodeid => $r->[1],
|
||||
parenttalkid => $r->[2],
|
||||
posterid => $r->[3],
|
||||
state => $r->[4],
|
||||
datepost => $r->[5],
|
||||
};
|
||||
$posterids{$r->[3]} = 1 if $r->[3]; # don't include 0 (anonymous)
|
||||
}
|
||||
|
||||
# now we have two choices: comments themselves or metadata
|
||||
if ($mode eq 'comment_meta') {
|
||||
# meta data is easy :)
|
||||
my $max = $dbcr->selectrow_array('SELECT MAX(jtalkid) FROM talk2 ' .
|
||||
"WHERE journalid = ? AND nodetype = 'L'",
|
||||
undef, $u->{userid});
|
||||
$max += 0;
|
||||
$r->print("<maxid>$max</maxid>\n");
|
||||
|
||||
# load posterids
|
||||
my $us = LJ::load_userids(keys %posterids);
|
||||
|
||||
# now spit out the metadata
|
||||
$r->print("<comments>\n");
|
||||
while (my ($id, $data) = each %comments) {
|
||||
my $ret = "<comment id='$id'";
|
||||
$ret .= " posterid='$data->{posterid}'" if $data->{posterid};
|
||||
$ret .= " state='$data->{state}'" if $data->{state} ne 'A';
|
||||
$ret .= " />\n";
|
||||
$r->print($ret);
|
||||
}
|
||||
$r->print("</comments>\n<usermaps>\n");
|
||||
|
||||
# now spit out usermap
|
||||
my $ret = '';
|
||||
while (my ($id, $user) = each %$us) {
|
||||
$ret .= "<usermap id='$id' user='$user->{user}' />\n";
|
||||
}
|
||||
$r->print($ret);
|
||||
$r->print("</usermaps>\n");
|
||||
|
||||
# comment data also presented in glorious XML:
|
||||
} elsif ($mode eq 'comment_body') {
|
||||
# get real comments from startid to a limit of 10k data, however far that takes us
|
||||
my @ids = sort { $a <=> $b } keys %comments;
|
||||
|
||||
# call a load to get comment text
|
||||
my $texts = LJ::get_talktext2($u, @ids);
|
||||
|
||||
# get props if we need to
|
||||
my $props = {};
|
||||
if ($GET{'props'}) {
|
||||
LJ::load_talk_props2($u->{userid}, \@ids, $props);
|
||||
}
|
||||
|
||||
# now start spitting out data
|
||||
$r->print("<comments>\n");
|
||||
foreach my $id (@ids) {
|
||||
# get text for this comment
|
||||
my $data = $comments{$id};
|
||||
my $text = $texts->{$id};
|
||||
my ($subject, $body) = @{$text || []};
|
||||
|
||||
# only spit out valid UTF8, and make sure it fits in XML, and uncompress it
|
||||
LJ::text_uncompress(\$body);
|
||||
LJ::text_out(\$subject);
|
||||
LJ::text_out(\$body);
|
||||
$subject = LJ::exml($subject);
|
||||
$body = LJ::exml($body);
|
||||
|
||||
# setup the date to be GMT and formatted per W3C specs
|
||||
my $date = LJ::mysqldate_to_time($data->{datepost});
|
||||
$date = LJ::time_to_w3c($date, 'Z');
|
||||
|
||||
# print the data
|
||||
my $ret = "<comment id='$id' jitemid='$data->{nodeid}'";
|
||||
$ret .= " posterid='$data->{posterid}'" if $data->{posterid};
|
||||
$ret .= " state='$data->{state}'" if $data->{state} ne 'A';
|
||||
$ret .= " parentid='$data->{parenttalkid}'" if $data->{parenttalkid};
|
||||
if ($data->{state} eq 'D') {
|
||||
$ret .= " />\n";
|
||||
} else {
|
||||
$ret .= ">\n";
|
||||
$ret .= "<subject>$subject</subject>\n" if $subject;
|
||||
$ret .= "<body>$body</body>\n" if $body;
|
||||
$ret .= "<date>$date</date>\n";
|
||||
foreach my $propkey (keys %{$props->{$id} || {}}) {
|
||||
$ret .= "<property name='$propkey'>";
|
||||
$ret .= LJ::exml($props->{$id}->{$propkey});
|
||||
$ret .= "</property>\n";
|
||||
}
|
||||
$ret .= "</comment>\n";
|
||||
}
|
||||
$r->print($ret);
|
||||
}
|
||||
$r->print("</comments>\n");
|
||||
}
|
||||
|
||||
# all done
|
||||
$r->print("</livejournal>\n");
|
||||
}
|
||||
_code?><?_c <LJDEP>
|
||||
</LJDEP> _c?>
|
||||
203
livejournal/htdocs/export_do.bml
Executable file
@@ -0,0 +1,203 @@
|
||||
<?_code
|
||||
|
||||
LJ::set_active_crumb('export');
|
||||
|
||||
my $req = shift;
|
||||
my $r = $req->{'r'};
|
||||
|
||||
my $remote = LJ::get_remote();
|
||||
return "<?needlogin?>"
|
||||
unless $remote;
|
||||
|
||||
my $authas = $GET{'authas'} || $remote->{'user'};
|
||||
my $u = LJ::get_authas_user($authas);
|
||||
return LJ::bad_input($ML{'error.invalidauth'})
|
||||
unless $u;
|
||||
|
||||
my @errors = ();
|
||||
|
||||
my $year = $POST{'year'}+0;
|
||||
my $month = $POST{'month'}+0;
|
||||
|
||||
my $dbcr = LJ::get_cluster_reader($u);
|
||||
push @errors, $ML{'error.nodb'} unless $dbcr;
|
||||
|
||||
my $encoding;
|
||||
|
||||
if ($POST{'encid'}) {
|
||||
my %encodings;
|
||||
LJ::load_codes({ "encoding" => \%encodings } );
|
||||
$encoding = $encodings{$POST{'encid'}};
|
||||
}
|
||||
|
||||
$encoding ||= $POST{'encoding'};
|
||||
$encoding ||= $LJ::UNICODE ? 'utf-8' : 'iso-8859-1';
|
||||
|
||||
if ($LJ::UNICODE && lc($encoding) ne "utf-8" &&
|
||||
! Unicode::MapUTF8::utf8_supported_charset($encoding)) {
|
||||
push @errors, $ML{'.error.encoding'};
|
||||
}
|
||||
|
||||
if (@errors) {
|
||||
return LJ::bad_input(@errors);
|
||||
}
|
||||
|
||||
# from now on, we manage our own output
|
||||
BML::suppress_headers();
|
||||
BML::suppress_content();
|
||||
|
||||
my $opts = {}; # information needed by printing routines
|
||||
|
||||
##### figure out what fields we're exporting
|
||||
|
||||
my @fields;
|
||||
foreach my $f (qw(itemid eventtime logtime subject event security allowmask)) {
|
||||
if ($POST{"field_${f}"}) {
|
||||
push @fields, $f;
|
||||
}
|
||||
}
|
||||
|
||||
if ($POST{'field_currents'}) {
|
||||
push @fields, ("current_music", "current_mood");
|
||||
$opts->{'currents'} = 1;
|
||||
}
|
||||
|
||||
#### do file-format specific initialization
|
||||
|
||||
if ($POST{'format'} eq "csv") {
|
||||
$opts->{'format'} = "csv";
|
||||
$r->content_type("text/plain");
|
||||
$r->send_http_header();
|
||||
if ($POST{'header'}) {
|
||||
$r->print(join(",",@fields) . "\n");
|
||||
}
|
||||
}
|
||||
if ($POST{'format'} eq "xml") {
|
||||
$opts->{'format'} = "xml";
|
||||
my $lenc = lc($encoding);
|
||||
$r->content_type("text/xml; charset=$lenc");
|
||||
$r->send_http_header();
|
||||
$r->print("<?xml version=\"1.0\" encoding='$lenc'?>\n");
|
||||
$r->print("<livejournal>\n");
|
||||
}
|
||||
|
||||
$opts->{'fields'} = \@fields;
|
||||
$opts->{'encoding'} = $encoding;
|
||||
$opts->{'notranslation'} = 1
|
||||
if $POST{'notranslation'};
|
||||
|
||||
$sth = $dbcr->prepare("SELECT jitemid, anum, eventtime, logtime, security, allowmask FROM log2 ".
|
||||
"WHERE journalid=$u->{'userid'} AND year=$year AND month=$month");
|
||||
$sth->execute;
|
||||
if ($dbcr->err) { $r->print($dbcr->errstr); return; }
|
||||
my @buffer;
|
||||
while ($_ = $sth->fetchrow_hashref) {
|
||||
$_->{'ritemid'} = $_->{'jitemid'} || $_->{'itemid'};
|
||||
$_->{'itemid'} = $_->{'jitemid'} * 256 + $_->{'anum'} if $_->{'jitemid'};
|
||||
push @buffer, $_;
|
||||
if (@buffer == 20) {
|
||||
load_and_dump_buffer($u, \@buffer, $opts);
|
||||
@buffer = ();
|
||||
}
|
||||
|
||||
}
|
||||
load_and_dump_buffer($u, \@buffer, $opts);
|
||||
|
||||
if ($opts->{'format'} eq "xml") {
|
||||
$r->print("</livejournal>\n");
|
||||
}
|
||||
return;
|
||||
|
||||
sub load_and_dump_buffer
|
||||
{
|
||||
my ($u, $buf, $opts) = @_;
|
||||
my $lt;
|
||||
my %props;
|
||||
my @ids = map { $_->{'ritemid'} } @{$buf};
|
||||
|
||||
$lt = LJ::get_logtext2($u, @ids);
|
||||
LJ::load_log_props2($dbcr, $u->{'userid'}, \@ids, \%props);
|
||||
|
||||
foreach my $e (@{$buf}) {
|
||||
$e->{'subject'} = $lt->{$e->{'ritemid'}}->[0];
|
||||
$e->{'event'} = $lt->{$e->{'ritemid'}}->[1];
|
||||
|
||||
my $eprops = $props{$e->{'ritemid'}};
|
||||
|
||||
# convert to UTF-8 if necessary
|
||||
if ($LJ::UNICODE && $eprops->{'unknown8bit'} && !$opts->{'notranslation'}) {
|
||||
my $error;
|
||||
$e->{'subject'} = LJ::text_convert($e->{'subject'}, $u, \$error);
|
||||
$e->{'event'} = LJ::text_convert($e->{'event'}, $u, \$error);
|
||||
foreach (keys %{$eprops}) {
|
||||
$eprops->{$_} = LJ::text_convert($eprops->{$_}, $u, \$error);
|
||||
}
|
||||
}
|
||||
|
||||
if ($opts->{'currents'}) {
|
||||
$e->{'current_music'} = $eprops->{'current_music'};
|
||||
$e->{'current_mood'} = $eprops->{'current_mood'};
|
||||
if ($eprops->{'current_moodid'}) {
|
||||
my $mood = LJ::mood_name($eprops->{'current_moodid'})
|
||||
if $eprops->{'current_moodid'};
|
||||
$e->{'current_mood'} = $mood if $mood;
|
||||
}
|
||||
}
|
||||
|
||||
my $entry = dump_entry($e, $opts);
|
||||
|
||||
# now translate this to the chosen encoding but only if this is a
|
||||
# Unicode environment. In a pre-Unicode environment the chosen encoding
|
||||
# is merely a label.
|
||||
|
||||
if ($LJ::UNICODE && lc($opts->{'encoding'}) ne 'utf-8' && !$opts->{'notranslation'}) {
|
||||
$entry = Unicode::MapUTF8::from_utf8({-string=>$entry,
|
||||
-charset=>$opts->{'encoding'}});
|
||||
}
|
||||
|
||||
$r->print($entry);
|
||||
}
|
||||
}
|
||||
|
||||
sub dump_entry
|
||||
{
|
||||
my $e = shift;
|
||||
my $opts = shift;
|
||||
my $format = $opts->{'format'};
|
||||
my $entry = "";
|
||||
|
||||
my @vals = ();
|
||||
if ($format eq "xml") {
|
||||
$entry .= "<entry>\n";
|
||||
}
|
||||
|
||||
foreach my $f (@{$opts->{'fields'}})
|
||||
{
|
||||
my $v = $e->{$f};
|
||||
if ($format eq "csv") {
|
||||
if ($v =~ /[\"\n\,]/) {
|
||||
$v =~ s/\"/\"\"/g;
|
||||
$v = "\"$v\"";
|
||||
}
|
||||
}
|
||||
if ($format eq "xml") {
|
||||
$v = LJ::exml($v);
|
||||
}
|
||||
push @vals, $v;
|
||||
}
|
||||
if ($format eq "csv") {
|
||||
$entry .= join(",", @vals) . "\n";
|
||||
}
|
||||
if ($format eq "xml") {
|
||||
foreach my $f (@{$opts->{'fields'}}) {
|
||||
my $v = shift @vals;
|
||||
$entry .= "<$f>" . $v . "</$f>\n";
|
||||
}
|
||||
$entry .= "</entry>\n";
|
||||
}
|
||||
return $entry;
|
||||
}
|
||||
|
||||
|
||||
_code?><?_c <LJDEP>
|
||||
</LJDEP> _c?>
|
||||
1
livejournal/htdocs/files/.placeholder
Executable file
@@ -0,0 +1 @@
|
||||
This file exists to make sure the directory is created.
|
||||
209
livejournal/htdocs/friends/add.bml
Executable file
@@ -0,0 +1,209 @@
|
||||
<?_code
|
||||
|
||||
my $remote = LJ::get_remote();
|
||||
my $user = $FORM{'user'};
|
||||
my $u = LJ::load_user($user);
|
||||
my $userid = $u->{userid};
|
||||
$body = "";
|
||||
|
||||
LJ::set_active_crumb('addfriends');
|
||||
|
||||
unless ($remote)
|
||||
{
|
||||
$title = $ML{'.error1.title'};
|
||||
$body = "<?h1 $ML{'.error1.header'} h1?><?p $ML{'.error1.text'} p?>";
|
||||
return;
|
||||
}
|
||||
|
||||
unless ($user && $userid)
|
||||
{
|
||||
$title = $ML{'Error'};
|
||||
$body = $ML{'.error2.text'};
|
||||
return;
|
||||
}
|
||||
|
||||
if ($FORM{'mode'} eq "add")
|
||||
{
|
||||
unless (LJ::did_post()) {
|
||||
$title = $ML{'Error'};
|
||||
$body = "<?h1 $ML{'Error'} h1?><?p <?requirepost?> p?>";
|
||||
return;
|
||||
}
|
||||
|
||||
unless ($remote->{'userid'} == $FORM{'remid'}) {
|
||||
$title = $ML{'Error'};
|
||||
$body = "<?h1 $ML{'Error'} h1?><?p Session info changed. Try again. p?>";
|
||||
return;
|
||||
}
|
||||
|
||||
my $gmask = 1;
|
||||
foreach my $bit (1..30) {
|
||||
next unless $FORM{"bit_$bit"};
|
||||
$gmask |= (1 << $bit);
|
||||
}
|
||||
|
||||
my $req = {
|
||||
"user" => $remote->{'user'},
|
||||
"mode" => "editfriends",
|
||||
"ver" => $LJ::PROTOCOL_VER,
|
||||
};
|
||||
|
||||
|
||||
if ($FORM{'action:delete'}) {
|
||||
$req->{"editfriend_delete_$user"} = 1;
|
||||
} else {
|
||||
$req->{"editfriend_add_1_user"} = $user;
|
||||
$req->{"editfriend_add_1_fg"} = $FORM{'editfriend_add_1_fg'};
|
||||
$req->{"editfriend_add_1_bg"} = $FORM{'editfriend_add_1_bg'};
|
||||
$req->{"editfriend_add_1_groupmask"} = $gmask;
|
||||
}
|
||||
|
||||
my %res = ();
|
||||
LJ::do_request($req, \%res,
|
||||
{ "noauth" => 1, "userid" => $remote->{'userid'} } );
|
||||
|
||||
if ($res{'success'} eq "OK")
|
||||
{
|
||||
if ($FORM{'action:delete'}) {
|
||||
$title = $ML{'.remove.title'};
|
||||
$body = "<?h1 $ML{'.remove.header'} h1?><?p " .
|
||||
BML::ml('.remove.text', {'user'=>$user,
|
||||
'ljuser' => LJ::ljuser($u),
|
||||
'url'=>"$LJ::SITEROOT/users/$remote->{'user'}/friends"}) .
|
||||
" p?>";
|
||||
} else {
|
||||
$title = $ML{'.add.title'};
|
||||
$body = "<?h1 $ML{'.add.header'} h1?><?p " .
|
||||
BML::ml('.add.text', { 'user' => $user,
|
||||
'ljuser' => LJ::ljuser($u),
|
||||
'url' => "$LJ::SITEROOT/users/$remote->{'user'}/friends", }) .
|
||||
" p?>";
|
||||
}
|
||||
} else {
|
||||
$title = $ML{'Error'};
|
||||
$body = "<?h1 $ML{'Error'} h1?><?p $res{'errmsg'} p?>";
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
# check to see if user is already a friend.
|
||||
# TAG:fr:bml_friends_add:check_is_friend
|
||||
my $dbr = LJ::get_db_reader();
|
||||
$sth = $dbr->prepare("SELECT * FROM friends WHERE userid=$remote->{'userid'} AND friendid=$userid");
|
||||
$sth->execute;
|
||||
my $fr = $sth->fetchrow_hashref;
|
||||
|
||||
if ($fr) {
|
||||
$title .= $ML{'.error3.title'};
|
||||
$body .= "<?h1 $ML{'.error3.title'} h1?><?p " .
|
||||
BML::ml('.error3.text', {'user'=>$user}) . " p?>";
|
||||
} else {
|
||||
# was this a syndicated add?
|
||||
if ($u->{journaltype} eq 'Y') {
|
||||
$title = $ML{'.confirm.syn.title'};
|
||||
$body .= "<?h1 " . BML::ml('.confirm.syn.header', { user => $user }) . " h1?>";
|
||||
} else {
|
||||
$title .= $ML{'.confirm.title'};
|
||||
$body .= "<?h1 " . BML::ml(".confirm.header", { 'user' => $user }) . " h1?>";
|
||||
}
|
||||
$body .= "<?p " . BML::ml(".confirm.text", { 'user' => $user }) . " p?>";
|
||||
}
|
||||
|
||||
$body .= "<form method='post' action='add.bml'>";
|
||||
$body .= LJ::html_hidden(mode => 'add',
|
||||
user => $user,
|
||||
remid => $remote->{userid});
|
||||
|
||||
if ($fr) {
|
||||
$body .= "<center><input type='submit' value=\"$ML{'.btn.modify'}\">";
|
||||
$body .= " - <input type='submit' name='action:delete' value=\"$ML{'.btn.remove'}\"></center>";
|
||||
} else {
|
||||
$body .= "<center><input type='submit' value=\"" .
|
||||
BML::ml('.btn.add', {'user'=>$user}) . "\"></center>";
|
||||
}
|
||||
|
||||
## let them pick friend groups
|
||||
$body .= "<?h1 $ML{'.groups.header'} h1?><?p $ML{'.groups.text'} p?><blockquote>";
|
||||
my $err;
|
||||
my $greq = LJ::Protocol::do_request("getfriendgroups", {
|
||||
'username' => $remote->{'user'},
|
||||
'ver' => $LJ::PROTOCOL_VER,
|
||||
}, \$err, { 'noauth' => 1 });
|
||||
|
||||
if (@{$greq->{'friendgroups'}}) {
|
||||
foreach my $g (@{$greq->{'friendgroups'}}) {
|
||||
my $ck = ($fr && ($fr->{'groupmask'} & (1 << $g->{'id'}))) ?
|
||||
"checked='1'" : "";
|
||||
|
||||
# by default, newly added friends are in default view unless unchecked
|
||||
$ck = "checked='1'" if (! $fr && $g->{'name'} eq "Default View");
|
||||
|
||||
$body .= "<input type='checkbox' value='1' name='bit_$g->{'id'}' $ck> ";
|
||||
$body .= LJ::ehtml($g->{'name'}) . "<br />\n";
|
||||
}
|
||||
} else {
|
||||
$body .= "<i>$ML{'.groups.nogroup'}</i>";
|
||||
}
|
||||
$body .= "</blockquote>";
|
||||
|
||||
## let them pick the colors
|
||||
$body .= "<?h1 $ML{'.colors.header'} h1?><?p " .
|
||||
BML::ml('.colors.text', {'user'=>$user}) . " p?>";
|
||||
|
||||
$ret = "";
|
||||
$ret .= "<P><CENTER><TABLE CELLPADDING=4><TR><TD><B>$ML{'.colors.fg'}</B></TD><TD><B>$ML{'.colors.bg'}</B></TD></TR>\n";
|
||||
|
||||
my @color = ();
|
||||
LJ::load_codes({ "color" => \@color });
|
||||
|
||||
my $sel = $fr || { 'fgcolor' => hex '000000',
|
||||
'bgcolor' => hex 'FFFFFF', };
|
||||
|
||||
$ret .= "<TR>";
|
||||
$ret .= "<TD><SELECT NAME=\"editfriend_add_1_fg\">";
|
||||
foreach (@color) {
|
||||
my $color_int = hex (substr($_->{'code'},1));
|
||||
my $selected = $color_int eq $sel->{'fgcolor'} ? " SELECTED" : "";
|
||||
$ret .= "<OPTION VALUE=\"$_->{'code'}\"$selected>$_->{'item'}\n";
|
||||
}
|
||||
$ret .= "</SELECT></TD>\n";
|
||||
$ret .= "<TD><SELECT NAME=\"editfriend_add_1_bg\">";
|
||||
foreach (@color) {
|
||||
my $color_int = hex (substr($_->{'code'},1));
|
||||
my $selected = $color_int eq $sel->{'bgcolor'} ? " SELECTED" : "";
|
||||
$ret .= "<OPTION VALUE=\"$_->{'code'}\"$selected>$_->{'item'}\n";
|
||||
}
|
||||
$ret .= "</SELECT></TD>\n";
|
||||
$ret .= "</TR>\n";
|
||||
$ret .= "</TABLE>\n";
|
||||
|
||||
### color swatch
|
||||
my $col = 0;
|
||||
$ret .= "<P><TABLE border=0 cellspacing=0 cellpadding=0>";
|
||||
foreach (@color) {
|
||||
if ($col==0) { $ret .= "<TR>\n"; }
|
||||
$col++;
|
||||
my $ecolor = LJ::ehtml($_->{'item'});
|
||||
$ret .= "<TD bgcolor=$_->{'code'}><IMG SRC=\"/img/dot.gif\" WIDTH=14 HEIGHT=14 TITLE=\"$ecolor\" ALT=\"$ecolor\"></TD>\n";
|
||||
if ($col==23) { $ret .= "</TR>\n"; $col==0; }
|
||||
}
|
||||
if ($col) { $ret .= "</TR>\n"; $col==0; }
|
||||
$ret .= "</TABLE>\n";
|
||||
$ret .= "<FONT SIZE=-2 FACE=\"Arial,Helvetica\">$ML{'.colors.hover'}</FONT>";
|
||||
|
||||
$ret .= "</CENTER>\n";
|
||||
$body .= $ret;
|
||||
|
||||
$body .= "</form>";
|
||||
|
||||
return;
|
||||
|
||||
_code?>
|
||||
<?page
|
||||
title=><?_code return $title; _code?>
|
||||
body=><?_code return $body; _code?>
|
||||
page?><?_c <LJDEP>
|
||||
link: htdocs/login.bml, htdocs/create.bml, htdocs/friends/edit.bml, htdocs/users
|
||||
img: htdocs/img/dot.gif
|
||||
post: htdocs/friends/add.bml
|
||||
</LJDEP> _c?>
|
||||
290
livejournal/htdocs/friends/edit.bml
Executable file
@@ -0,0 +1,290 @@
|
||||
<?page
|
||||
title=><?_ML .title _ML?>
|
||||
body<=
|
||||
<?_code
|
||||
{
|
||||
use strict;
|
||||
use vars qw(%GET %POST);
|
||||
|
||||
return LJ::server_down_html() if ($LJ::SERVER_DOWN);
|
||||
return "<?badinput?>" unless LJ::text_in(\%POST);
|
||||
|
||||
LJ::set_active_crumb('editfriends');
|
||||
|
||||
# this file used to be edit_do.bml, but edit.bml died, so we moved this
|
||||
# functionality to edit.bml, but we don't want the translators to have to
|
||||
# retranslate all of the phrases, so we're still using /edit_do.bml scope
|
||||
BML::set_language_scope("/friends/edit_do.bml");
|
||||
|
||||
my $remote = LJ::get_remote();
|
||||
return LJ::bad_input($ML{'error.noremote'})
|
||||
unless $remote;
|
||||
|
||||
my $authas = $GET{'authas'} || $remote->{'user'};
|
||||
my $getextra = $authas ne $remote->{'user'} ? "?authas=$authas" : '';
|
||||
|
||||
my $u = LJ::get_authas_user($authas);
|
||||
return LJ::bad_input("You could not be authenticated as the specified user.")
|
||||
unless $u;
|
||||
return BML::redirect("$LJ::SITEROOT/community/members.bml?comm=$u->{'user'}")
|
||||
if $u->{'journaltype'} eq 'C';
|
||||
return LJ::bad_input("Cannot modify friends of this journal type.")
|
||||
unless $u->{'journaltype'} =~ /^[PSI]$/;
|
||||
|
||||
my $ret;
|
||||
|
||||
# no post, show edit form
|
||||
unless (LJ::did_post()) {
|
||||
|
||||
# user switcher
|
||||
$ret .= "<form action='edit.bml' method='get'>\n";
|
||||
$ret .= LJ::make_authas_select($remote,
|
||||
{ 'authas' => $GET{'authas'},
|
||||
'type' => ['P', 'S'] });
|
||||
$ret .= "</form>\n\n";
|
||||
|
||||
$ret .= "<form method='post' name='editFriends' action='edit.bml$getextra'>\n";
|
||||
|
||||
### who has you defined as a friend?
|
||||
my %res = ();
|
||||
LJ::do_request({
|
||||
"user" => $u->{'user'},
|
||||
"mode" => "friendof",
|
||||
"ver" => $LJ::PROTOCOL_VER,
|
||||
}, \%res, { "noauth" => 1, 'u' => $u });
|
||||
|
||||
### who do you have defined as a friend?
|
||||
my %resf = ();
|
||||
LJ::do_request({
|
||||
"user" => $u->{'user'},
|
||||
"mode" => "getfriends",
|
||||
"ver" => $LJ::PROTOCOL_VER,
|
||||
}, \%resf, { "noauth" => 1, 'u' => $u });
|
||||
|
||||
# build hash for checking if user is friend
|
||||
my %isfriend = map { $resf{"friend_${_}_user"}, 1 } 1..$resf{'friend_count'};
|
||||
|
||||
### table of friend-ofs
|
||||
if ($res{'friendof_count'}) {
|
||||
$ret .= "<?h1 $ML{'.fellowfriends.head'} h1?><?p $ML{'.fellowfriends.text'} p?>\n";
|
||||
$ret .= "<table style='margin-top: 20px;' align='center'>\n";
|
||||
$ret .= "<tr bgcolor='<?emcolor?>'><td width='150'><b>$ML{'.user'}</b></td>";
|
||||
$ret .= "<td width='200'><b>$ML{'.name'}</b></td>";
|
||||
$ret .= "<td align='center'><b>$ML{'.opt.addtolist'}</b></td></tr>";
|
||||
|
||||
my $friendnum = 6; # 1-5 are new friends from the add form
|
||||
for my $i (1..$res{'friendof_count'}) {
|
||||
my $fo_user = $res{"friendof_${i}_user"};
|
||||
$ret .= "<tr align='left'><td>" . LJ::ljuser($fo_user) . "</td>";
|
||||
$ret .= "<td><label for='editfriend_add_${friendnum}_user'>";
|
||||
$ret .= LJ::ehtml($res{"friendof_${i}_name"}) . "</label></td><td align='center'>";
|
||||
my $dis = $isfriend{$fo_user} ? 1 : 0;
|
||||
$ret .= LJ::html_check({ 'type' => 'check',
|
||||
'name' => "editfriend_add_${friendnum}_user",
|
||||
'id' => "editfriend_add_${friendnum}_user",
|
||||
'value' => $fo_user, 'disabled' => $dis });
|
||||
$friendnum++;
|
||||
$ret .= "</td></tr>";
|
||||
}
|
||||
$ret .= "</table>";
|
||||
}
|
||||
|
||||
### table of friends
|
||||
if ($resf{'friend_count'}) {
|
||||
$ret .= "<?h1 $ML{'.yourfriends.head'} h1?><?p $ML{'.yourfriends.text'} p?>\n";
|
||||
$ret .= "<p align='center'><table style='margin-top: 20px;' align='center'>";
|
||||
$ret .= "<tr bgcolor='<?emcolor?>'><td width='150'><b>$ML{'.friend'}</b></td>";
|
||||
$ret .= "<td width='250'><b>$ML{'.name'}</b></td>";
|
||||
$ret .= "<td align='center'><b>$ML{'.opt.delete'}</b></td></tr>\n";
|
||||
|
||||
foreach my $i (1..$resf{'friend_count'}) {
|
||||
my $fruser = $resf{"friend_${i}_user"};
|
||||
$isfriend{$fruser} = 1;
|
||||
my $bgcolor = $resf{"friend_${i}_bg"} || "#FFFFFF";
|
||||
my $fgcolor = $resf{"friend_${i}_fg"} || "#000000";
|
||||
my $status = $resf{"friend_${i}_status"};
|
||||
my $userlink = LJ::ljuser($fruser);
|
||||
if ($status eq 'deleted' || $status eq 'purged' || $status eq 'suspended') {
|
||||
$userlink = "<strike>$userlink</strike>";
|
||||
}
|
||||
|
||||
$ret .= "<tr align='left'><td>$userlink</td>";
|
||||
$ret .= "<td bgcolor='$bgcolor'><font color='$fgcolor'>";
|
||||
$ret .= "<label for='editfriend_delete_${fruser}'>";
|
||||
$ret .= LJ::ehtml($resf{"friend_${i}_name"}) . "</label>";
|
||||
$ret .= "</font></td><td align='center'>";
|
||||
$ret .= LJ::html_check({ 'type' => 'check',
|
||||
'name' => "editfriend_delete_${fruser}",
|
||||
'id' => "editfriend_delete_${fruser}"});
|
||||
$ret .= "</td></tr>\n";
|
||||
}
|
||||
$ret .= "</table></p>\n\n";
|
||||
|
||||
} else {
|
||||
$ret .= "<?h1 $ML{'.nofriends.head'} h1?><?p $ML{'.nofriends.text'} p?>\n\n";
|
||||
}
|
||||
|
||||
### add friends
|
||||
$ret .= "<?h1 $ML{'.addfriends.head'} h1?><?p $ML{'.addfriends.text'} p?>\n";
|
||||
$ret .= "<p align='center'><input type='button' value='" . LJ::ehtml($ML{'.btn.toggle'}) . "' ";
|
||||
$ret .= "onClick='togglePreview(); return true;'></p>\n";
|
||||
|
||||
$ret .= "<table cellpadding='4' align='center'>\n";
|
||||
$ret .= "<tr><td><b>$ML{'.friend'}</b></td><td><b>$ML{'.foreground'}</b></td><td><b>$ML{'.background'}</b></td></tr>\n";
|
||||
|
||||
# load the colors
|
||||
my @color = ();
|
||||
LJ::load_codes({ "color" => \@color });
|
||||
|
||||
foreach my $i (1..5) {
|
||||
$ret .= "<tr><td>";
|
||||
$ret .= LJ::html_text({ 'name' => "editfriend_add_${i}_user",
|
||||
'size' => '15', 'maxlength' => '15',
|
||||
'onchange' => "updatePreview(); return true;",
|
||||
'onfocus' => "setFriend($i);" });
|
||||
$ret .= "</td><td>";
|
||||
$ret .= LJ::html_select({ 'name' => "editfriend_add_${i}_fg",
|
||||
'selected' => '#000000',
|
||||
'onchange' => "updatePreview(); return true;",
|
||||
'onfocus' => "setFriend($i);" },
|
||||
map { lc($_->{'code'}), $_->{'item'} } @color );
|
||||
$ret .= "</td><td>";
|
||||
$ret .= LJ::html_select({ 'name' => "editfriend_add_${i}_bg",
|
||||
'selected' => '#ffffff',
|
||||
'onchange' => "updatePreview(); return true;",
|
||||
'onfocus' => "setFriend($i);" },
|
||||
map { lc($_->{'code'}), $_->{'item'} } @color );
|
||||
|
||||
$ret .= "</td></tr>\n";
|
||||
}
|
||||
$ret .= "</table>";
|
||||
|
||||
### color swatch
|
||||
my $col = 0;
|
||||
$ret .= "<table border='0' cellspacing='0' cellpadding='0' align='center'>";
|
||||
foreach (@color) {
|
||||
if ($col==0) { $ret .= "<tr>\n"; }
|
||||
$col++;
|
||||
my $ecolor = LJ::ehtml($_->{'item'});
|
||||
$ret .= "<td bgcolor='$_->{'code'}'><img src='/img/dot.gif' width='14' height='14' title='$ecolor' alt='$ecolor' /></td>";
|
||||
if ($col==23) { $ret .= "</tr>\n"; $col==0; }
|
||||
}
|
||||
|
||||
if ($col) { $ret .= "</tr>\n"; $col==0; }
|
||||
$ret .= "<tr><td colspan='23' align='center'><font size='-2' face='Arial,Helvetica'>($ML{'.hover'})</font></td></tr>";
|
||||
$ret .= "</table>";
|
||||
|
||||
$ret .= "<p>$ML{'.needmore'}</p>\n";
|
||||
|
||||
### ending submit block
|
||||
$ret .= "<?h1 $ML{'.done.head'} h1?><?p $ML{'.done.text'} p?>\n";
|
||||
$ret .= "<?standout " . LJ::html_submit($ML{'.btn.save'}) . " standout?>\n";
|
||||
$ret .= "</form>\n";
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
# if they did a post, then process their changes
|
||||
if (LJ::did_post()) {
|
||||
|
||||
my %request = ();
|
||||
$request{'mode'} = "editfriends";
|
||||
$request{'ver'} = $LJ::PROTOCOL_VER;
|
||||
$request{'user'} = $u->{'user'};
|
||||
foreach (grep { /^editfriend_/ } keys %POST) {
|
||||
$request{$_} = $POST{$_};
|
||||
}
|
||||
|
||||
my %response = ();
|
||||
LJ::do_request(\%request, \%response, { 'noauth' => 1, 'u' => $u });
|
||||
|
||||
if ($response{'success'} eq "OK") {
|
||||
# tell the user all is well
|
||||
return "<?h1 $ML{'.success.head'} h1?><?p ".BML::ml(".success.text", {'url' => LJ::journal_base($u) . "/friends"})." p?>";
|
||||
} else {
|
||||
return "<?h1 $ML{'Error'} h1?><?p $ML{'.error.updating'} <ul><li><b>$response{'errmsg'}</b></ul> p?>\n";
|
||||
}
|
||||
}
|
||||
|
||||
return $ML{'error.unknownmode'};
|
||||
}
|
||||
_code?>
|
||||
<=body
|
||||
|
||||
head<=
|
||||
<?_code
|
||||
{
|
||||
use strict;
|
||||
BML::set_language_scope("/friends/edit_do.bml");
|
||||
|
||||
my %ejs = map { $_, LJ::ejs($ML{".$_"}) } qw(mrcolor viewer textcolor bgcolor btn.close);
|
||||
|
||||
return qq{
|
||||
<script language="JavaScript"><!--
|
||||
|
||||
previewOn = 0;
|
||||
lastFriend = 0;
|
||||
|
||||
function setFriend (curfriend)
|
||||
{
|
||||
lastFriend = curfriend;
|
||||
}
|
||||
|
||||
function togglePreview()
|
||||
{
|
||||
if (previewOn==0 || winPreview.closed) {
|
||||
winPreview = window.open("", "preview", "toolbar=0,location=0,directories=0,status=0,menubar=0,scrollbars=0,resizable=0,copyhistory=0,width=400,height=270");
|
||||
previewOn = 1;
|
||||
updatePreview();
|
||||
} else {
|
||||
winPreview.close();
|
||||
previewOn = 0;
|
||||
}
|
||||
}
|
||||
|
||||
function updatePreview () {
|
||||
|
||||
if (previewOn == 0 || winPreview.closed) { return; }
|
||||
|
||||
frm = document.editFriends;
|
||||
|
||||
dropdown = frm["editfriend_add_"+lastFriend+"_fg"]
|
||||
fg_color = dropdown.options[dropdown.selectedIndex].value;
|
||||
fg_color_text = dropdown.options[dropdown.selectedIndex].text;
|
||||
|
||||
dropdown = frm["editfriend_add_"+lastFriend+"_bg"]
|
||||
bg_color = dropdown.options[dropdown.selectedIndex].value;
|
||||
bg_color_text = dropdown.options[dropdown.selectedIndex].text;
|
||||
|
||||
user_name = frm["editfriend_add_"+lastFriend+"_user"].value;
|
||||
if (user_name.length==0) { user_name = "username"; }
|
||||
|
||||
d = winPreview.document;
|
||||
d.open();
|
||||
d.write("<html><head><title>$ejs{'mrcolor'}</title></head><body bgcolor='#ffffff' text='#000000'>");
|
||||
d.write("<b><font face='Trebuchet MS, Arial, Helvetica' size='4' color='#000066'><i>$ejs{'viewer'}</i></font></b><hr />");
|
||||
d.write("<br /><table width='350' align='center' cellpadding='5'><tr valign='middle'>");
|
||||
d.write("<td width='80%'><b><font face='Arial, Helvetica' size='2'>");
|
||||
d.write("$ejs{'textcolor'} <font color='#000066'>" + fg_color_text);
|
||||
d.write("</font></b><br /></td><td width='20%' bgcolor=" + fg_color + "> </td>");
|
||||
d.write("</tr><tr><td width='80%'><b><font face='Arial, Helvetica' size='2'>");
|
||||
d.write("$ejs{'bgcolor'} <font color='#000066'>" + bg_color_text + "");
|
||||
d.write("</font></b><br></td><td width='20%' bgcolor=" + bg_color + "> </td>");
|
||||
d.write("</tr><tr><td><br /></tr><tr><td colspan='3' bgcolor=" + bg_color + "><font color=" + fg_color + ">");
|
||||
d.write("<b>" + user_name + "</b></td></tr></table><br />");
|
||||
d.write("<hr><form><div align='center'><input type='button' value='$ejs{'btn.close'}' onClick='self.close();'></div></form>");
|
||||
d.write("</body></html>");
|
||||
d.close();
|
||||
}
|
||||
// -->
|
||||
</script>
|
||||
}; # end qq{ }
|
||||
|
||||
}
|
||||
_code?>
|
||||
<=head
|
||||
|
||||
page?><?_c <LJDEP>
|
||||
link: htdocs/create.bml, htdocs/lostinfo.bml
|
||||
post: htdocs/friends/edit.bml
|
||||
</LJDEP> _c?>
|
||||
425
livejournal/htdocs/friends/editgroups.bml
Executable file
@@ -0,0 +1,425 @@
|
||||
<?_code
|
||||
{
|
||||
use strict;
|
||||
use vars qw(%GET %POST $title $body);
|
||||
|
||||
LJ::set_active_crumb('editfriendgrps');
|
||||
|
||||
$title = $ML{'.title'};
|
||||
$body = "";
|
||||
|
||||
my $err = sub {
|
||||
$title = "Error";
|
||||
$body = LJ::bad_input(@_);
|
||||
return;
|
||||
};
|
||||
|
||||
# these are only used by the client-side for JS to play with.
|
||||
# we delete them because they may contain embedded NULLs, which
|
||||
# text_in won't like.
|
||||
delete $POST{'list_in'};
|
||||
delete $POST{'list_out'};
|
||||
|
||||
unless (LJ::text_in(\%POST)) {
|
||||
$body = "<?badinput?>";
|
||||
return;
|
||||
}
|
||||
|
||||
my $remote = LJ::get_remote();
|
||||
return $err->($ML{'error.noremote'})
|
||||
unless $remote;
|
||||
|
||||
my $authas = $GET{'authas'} || $remote->{'user'};
|
||||
my $u = LJ::get_authas_user($authas);
|
||||
return $err->($ML{'error.invalidauth'})
|
||||
unless $u;
|
||||
|
||||
# extra arguments for get requests
|
||||
my $getextra = $authas ne $remote->{'user'} ? "?authas=$authas" : '';
|
||||
|
||||
if ($POST{'mode'} eq "save") {
|
||||
my %res;
|
||||
$POST{'mode'} = "editfriendgroups";
|
||||
$POST{'user'} = $u->{'user'};
|
||||
$POST{'ver'} = $LJ::PROTOCOL_VER;
|
||||
LJ::do_request(\%POST, \%res, {
|
||||
'u' => $u,
|
||||
'noauth' => 1,
|
||||
});
|
||||
|
||||
if ($res{'success'} eq "OK") {
|
||||
$body .= "<?h1 $ML{'.saved.header'} h1?><?p $ML{'.saved.text'} p?>";
|
||||
} else {
|
||||
$body .= "<?h1 $ML{'Error'} h1?><?p $ML{'.error.text'} p?><?p $res{'errmsg'} p?>";
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
my %res;
|
||||
LJ::do_request({ 'mode' => 'getfriends',
|
||||
'user' => $u->{'user'},
|
||||
'ver' => $LJ::PROTOCOL_VER,
|
||||
'includegroups' => 1 },
|
||||
\%res, { 'u' => $u,
|
||||
'noauth' => 1, });
|
||||
my @num_used;
|
||||
my @num_free;
|
||||
|
||||
# authas switcher form
|
||||
$body .= "<form method='get' action='editgroups.bml'>\n";
|
||||
$body .= LJ::make_authas_select($remote, { 'authas' => $GET{'authas'} }) . "\n";
|
||||
$body .= "</form>\n\n";
|
||||
|
||||
$body .= "<?h1 $ML{'.title'} h1?><?p $ML{'.text'} p?><?p $ML{'.text.sec'} p?><p>";
|
||||
$body .= "<form method='post' name='fg' action='editgroups.bml$getextra'>";
|
||||
$body .= "<input type='hidden' name='mode' value='save' />";
|
||||
for (my $i=1; $i<=30; $i++) {
|
||||
my $sort = 255;
|
||||
my $name = "";
|
||||
my $public = 0;
|
||||
if ($res{"frgrp_${i}_name"}) {
|
||||
$sort = $res{"frgrp_${i}_sortorder"}+0;
|
||||
$name = LJ::ehtml($res{"frgrp_${i}_name"});
|
||||
$public = $res{"frgrp_${i}_public"}+0;
|
||||
push @num_used, $i;
|
||||
} else {
|
||||
push @num_free, $i;
|
||||
}
|
||||
$body .= "<input type='hidden' name='efg_set_${i}_name' value='$name' />";
|
||||
$body .= "<input type='hidden' name='efg_set_${i}_sort' value='$sort' />";
|
||||
$body .= "<input type='hidden' name='efg_delete_${i}' value='0' />";
|
||||
$body .= "<input type='hidden' name='efg_set_${i}_public' value='$public' />";
|
||||
}
|
||||
for (my $i=1; $i<=$res{'friend_count'}; $i++) {
|
||||
my $user = $res{"friend_${i}_user"};
|
||||
my $mask = $res{"friend_${i}_groupmask"} || 1;
|
||||
$body .= "<input type='hidden' name='editfriend_groupmask_$user' value='$mask' />";
|
||||
}
|
||||
|
||||
# escape strings for JavaScript
|
||||
my %T = qw(public .group.public
|
||||
rename .prompt.rename
|
||||
newname .prompt.newname
|
||||
delete .confirm.delete
|
||||
max30 .error.max30
|
||||
);
|
||||
foreach (keys %T) { $T{$_} = LJ::ejs($ML{$T{$_}}); }
|
||||
|
||||
$body .= <<"END_JS";
|
||||
<SCRIPT LANGUAGE="JavaScript"><!--
|
||||
|
||||
var selectedGroup = 0;
|
||||
|
||||
function eraseList (list)
|
||||
{
|
||||
while (list.length) {
|
||||
list.options[0] = null;
|
||||
}
|
||||
}
|
||||
|
||||
function groupClicked ()
|
||||
{
|
||||
var selIndex;
|
||||
|
||||
var form = document.fg;
|
||||
var grouplist = form.list_groups;
|
||||
var inlist = form.list_in;
|
||||
var outlist = form.list_out;
|
||||
|
||||
// figure out what they clicked, and bring their focus up to first free blank
|
||||
|
||||
selIndex = grouplist.selectedIndex;
|
||||
if (selIndex == -1) { return; }
|
||||
var groupname = grouplist.options[selIndex].text;
|
||||
|
||||
var newSelGroup = grouplist.options[selIndex].value;
|
||||
if (newSelGroup == selectedGroup) { return; }
|
||||
selectedGroup = newSelGroup;
|
||||
|
||||
// clears the other "not in" and "in" boxes
|
||||
eraseList(inlist);
|
||||
eraseList(outlist);
|
||||
|
||||
// iterate over all friends, putting them in one group or the other
|
||||
var i;
|
||||
for (i=0; i<form.elements.length; i++) {
|
||||
var name = form.elements[i].name;
|
||||
var mask = form.elements[i].value;
|
||||
if (name.substring(0, 21) == "editfriend_groupmask_") {
|
||||
var user = name.substring(21, name.length);
|
||||
|
||||
var list = mask & (1 << selectedGroup) ? inlist : outlist;
|
||||
var optionName = new Option(user, user, false, false)
|
||||
list.options[list.length] = optionName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function moveItems (from, to, bitstatus)
|
||||
{
|
||||
var selindex;
|
||||
while ((selindex=from.selectedIndex) != -1)
|
||||
{
|
||||
var i;
|
||||
var item = new Option(from.options[selindex].text,
|
||||
from.options[selindex].value,
|
||||
false, true);
|
||||
|
||||
from.options[selindex] = null;
|
||||
//to.options[to.options.length] = item;
|
||||
|
||||
// find spot to put new item
|
||||
for (i=0; i<to.options.length && to.options[i].text < item.text; i++) { }
|
||||
var newindex = i;
|
||||
|
||||
// move everything else down
|
||||
for (i=to.options.length; i>newindex; i--) {
|
||||
to.options[i] = new Option(to.options[i-1].text,
|
||||
to.options[i-1].value,
|
||||
false,
|
||||
to.options[i-1].selected);
|
||||
}
|
||||
to.options[newindex] = item;
|
||||
|
||||
// turn the groupmask bit on or off
|
||||
var user = item.value;
|
||||
var element = document.fg["editfriend_groupmask_"+user];
|
||||
var mask = element.value;
|
||||
if (bitstatus) {
|
||||
mask |= (1 << selectedGroup);
|
||||
} else {
|
||||
mask &= ~(1 << selectedGroup);
|
||||
}
|
||||
element.value = mask;
|
||||
}
|
||||
}
|
||||
|
||||
function moveIn ()
|
||||
{
|
||||
if (! selectedGroup) { return; }
|
||||
var form = document.fg;
|
||||
var inlist = form.list_in;
|
||||
var outlist = form.list_out;
|
||||
moveItems(document.fg.list_out, document.fg.list_in, true);
|
||||
}
|
||||
function moveOut ()
|
||||
{
|
||||
if (! selectedGroup) { return; }
|
||||
moveItems(document.fg.list_in, document.fg.list_out, false);
|
||||
}
|
||||
|
||||
function moveGroup (dir)
|
||||
{
|
||||
var list = document.fg.list_groups;
|
||||
var selindex = list.selectedIndex;
|
||||
if (selindex==-1) { return; }
|
||||
var toindex = selindex+dir;
|
||||
if (toindex < 0 || toindex >= list.options.length) { return; }
|
||||
var selopt = new Option(list.options[selindex].text,
|
||||
list.options[selindex].value,
|
||||
false,
|
||||
list.options[selindex].selected);
|
||||
var toopt = new Option(list.options[toindex].text,
|
||||
list.options[toindex].value,
|
||||
false,
|
||||
list.options[toindex].selected);
|
||||
list.options[toindex] = selopt;
|
||||
list.options[selindex] = toopt;
|
||||
|
||||
// stupid mozilla necessity:
|
||||
list.selectedIndex = toindex;
|
||||
|
||||
setSortOrders();
|
||||
}
|
||||
|
||||
function setSortOrders ()
|
||||
{
|
||||
var list = document.fg.list_groups;
|
||||
|
||||
// set all their sort orders now
|
||||
var i;
|
||||
for (i=0; i<list.options.length; i++) {
|
||||
var item = list.options[i];
|
||||
var key = "efg_set_"+item.value+"_sort";
|
||||
document.fg[key].value = (i+1)*5;
|
||||
}
|
||||
}
|
||||
|
||||
function realName (name)
|
||||
{
|
||||
var rname = name;
|
||||
var index = name.lastIndexOf(" $T{'public'}");
|
||||
if (index != -1) {
|
||||
rname = name.substr(0, index);
|
||||
}
|
||||
return rname;
|
||||
}
|
||||
|
||||
function renameGroup ()
|
||||
{
|
||||
var list = document.fg.list_groups;
|
||||
var selindex = list.selectedIndex;
|
||||
if (selindex==-1) { return; }
|
||||
var item = list.options[selindex];
|
||||
|
||||
var newtext = realName(item.text);
|
||||
newtext = prompt("$T{'rename'}", newtext);
|
||||
if (newtext==null || newtext == "") { return; }
|
||||
|
||||
var gnum = item.value;
|
||||
document.fg["efg_set_"+gnum+"_name"].value = newtext;
|
||||
if (document.fg["efg_set_"+gnum+"_public"].value == 1) {
|
||||
newtext = newtext + " $T{'public'}";
|
||||
}
|
||||
item.text = newtext;
|
||||
}
|
||||
|
||||
function deleteGroup ()
|
||||
{
|
||||
var list = document.fg.list_groups;
|
||||
var selindex = list.selectedIndex;
|
||||
if (selindex==-1) { return; }
|
||||
var item = list.options[selindex];
|
||||
|
||||
var conf = confirm("$T{'delete'}");
|
||||
if (!conf) { return; }
|
||||
|
||||
// mark it to be deleted later
|
||||
var gnum = item.value;
|
||||
document.fg["efg_delete_"+gnum].value = "1";
|
||||
document.fg["efg_set_"+gnum+"_name"].value = "";
|
||||
|
||||
// as per the protocol documentation, unset bit on all friends
|
||||
var i;
|
||||
var form = document.fg;
|
||||
for (i=0; i<form.elements.length; i++) {
|
||||
var name = form.elements[i].name;
|
||||
if (name.substring(0, 21) == "editfriend_groupmask_") {
|
||||
var user = name.substring(21, name.length);
|
||||
var mask = form.elements[i].value;
|
||||
mask &= ~(1 << gnum);
|
||||
form.elements[i].value = mask;
|
||||
}
|
||||
}
|
||||
|
||||
// clean up the UI
|
||||
list.options[selindex] = null;
|
||||
eraseList(document.fg.list_in);
|
||||
eraseList(document.fg.list_out);
|
||||
}
|
||||
|
||||
function makePublic ()
|
||||
{
|
||||
var list = document.fg.list_groups;
|
||||
var selindex = list.selectedIndex;
|
||||
if (selindex==-1) { return; }
|
||||
var item = list.options[selindex];
|
||||
|
||||
var name = realName(item.text);
|
||||
item.text = name + " $T{'public'}";
|
||||
|
||||
var gnum = item.value;
|
||||
document.fg["efg_set_"+gnum+"_public"].value = "1";
|
||||
}
|
||||
|
||||
function makePrivate ()
|
||||
{
|
||||
var list = document.fg.list_groups;
|
||||
var selindex = list.selectedIndex;
|
||||
if (selindex==-1) { return; }
|
||||
var item = list.options[selindex];
|
||||
|
||||
var name = realName(item.text);
|
||||
item.text = name;
|
||||
|
||||
var gnum = item.value;
|
||||
document.fg["efg_set_"+gnum+"_public"].value = "0";
|
||||
}
|
||||
|
||||
function newGroup ()
|
||||
{
|
||||
var form = document.fg;
|
||||
var i;
|
||||
var foundg = false;
|
||||
for (i=1; i<=30; i++) {
|
||||
if (form["efg_delete_"+i].value==1) { continue; }
|
||||
if (form["efg_set_"+i+"_name"].value!="") { continue; }
|
||||
foundg = true;
|
||||
break;
|
||||
}
|
||||
if (! foundg) {
|
||||
alert("$T{'max30'}");
|
||||
return;
|
||||
}
|
||||
var gnum = i;
|
||||
var groupname = prompt("$T{'newname'}", "");
|
||||
if (groupname==null || groupname=="") { return; }
|
||||
|
||||
form["efg_set_"+gnum+"_name"].value = groupname;
|
||||
var item = new Option(groupname, gnum, false, true);
|
||||
var list = form.list_groups;
|
||||
list.options[list.options.length] = item;
|
||||
list.options.selectedIndex = list.options.length-1;
|
||||
setSortOrders();
|
||||
groupClicked();
|
||||
}
|
||||
|
||||
// --></SCRIPT>
|
||||
END_JS
|
||||
|
||||
$body .= "<table cellspacing='5'><tr valign='bottom'>";
|
||||
$body .= "<td nowrap='1' colspan='2'><strong>$ML{'.yourgroups'}</strong></td>";
|
||||
$body .= "<td nowrap='1' colspan='2'><strong>$ML{'.ingroup.not'}</strong></td>";
|
||||
$body .= "<td nowrap='1'><strong>$ML{'.ingroup'}</strong></td></tr>";
|
||||
|
||||
$body .= "<tr valign='top'>";
|
||||
$body .= "<td><select name='list_groups' style='width: 150px;' size='15' onchange='groupClicked();'>";
|
||||
foreach my $num (sort { $res{"frgrp_${a}_sortorder"} <=>
|
||||
$res{"frgrp_${b}_sortorder"} } @num_used) {
|
||||
|
||||
my $listname = $res{"frgrp_${num}_name"};
|
||||
$listname .= " $ML{'.group.public'}" if $res{"frgrp_${num}_public"};
|
||||
$body .= "<option value='$num'>" . LJ::ehtml($listname);
|
||||
}
|
||||
|
||||
$body .= "</select></td>";
|
||||
|
||||
$body .= "<td valign='middle'>";
|
||||
$body .= "<input type='button' value='$ML{'.btn.mv.up'}' onClick='moveGroup(-1);' /><br /><br />";
|
||||
$body .= "<input type='button' value='$ML{'.btn.mv.down'}' onClick='moveGroup(1);' /></td>";
|
||||
|
||||
$body .= "<td><select name='list_out' multiple='1' size='15'>";
|
||||
$body .= "<option value=''>---------------</option></select></td>";
|
||||
|
||||
$body .= "<td valign='middle'>";
|
||||
$body .= "<input type='button' onClick='moveIn();' value='>>' /><br /><br />";
|
||||
$body .= "<input type='button' onClick='moveOut();' value='<<' /></td>";
|
||||
|
||||
$body .= "<td><select name='list_in' multiple='1' size='15'>";
|
||||
$body .= "<option value=''>---------------</option></select></td>";
|
||||
|
||||
$body .= "</tr><tr><td colspan='2'>";
|
||||
$body .= "<nobr>";
|
||||
$body .= "<input type='button' value='$ML{'.btn.ge.new'}' onClick='newGroup();' /> ";
|
||||
$body .= "<input type='button' value='$ML{'.btn.ge.del'}' onClick='deleteGroup();' /> ";
|
||||
$body .= "<input type='button' value='$ML{'.btn.ge.ren'}' onClick='renameGroup();' />";
|
||||
$body .= "</nobr><br /><nobr>";
|
||||
$body .= "<input type='button' value='$ML{'.btn.gs.public'}' onClick='makePublic();' /> ";
|
||||
$body .= "<input type='button' value='$ML{'.btn.gs.private'}' onClick='makePrivate();' />";
|
||||
$body .= "</nobr></td><td></td><td></td><td></td>";
|
||||
|
||||
$body .= "</tr></table>";
|
||||
|
||||
$body .= "<?h1 $ML{'.done.header'} h1?><?p $ML{'.done.text'} p?>";
|
||||
$body .= "<?p <input type='submit' value='$ML{'.done.btn'}' /> p?>";
|
||||
$body .= "</form>";
|
||||
|
||||
return;
|
||||
}
|
||||
_code?><?page
|
||||
title=><?_code return $title; _code?>
|
||||
body=><?_code return $body; _code?>
|
||||
page?><?_c <LJDEP>
|
||||
link: htdocs/login.bml
|
||||
post: htdocs/friends/editgroups.bml
|
||||
</LJDEP> _c?>
|
||||
74
livejournal/htdocs/friends/filter.bml
Executable file
@@ -0,0 +1,74 @@
|
||||
<?_code
|
||||
|
||||
$title = $ML{'.title'};
|
||||
$body = "";
|
||||
|
||||
LJ::set_active_crumb('friendsfilter');
|
||||
|
||||
if ($FORM{'mode'} eq "view")
|
||||
{
|
||||
my $user = lc($FORM{'user'});
|
||||
my $filter = 0;
|
||||
foreach my $k (keys %FORM) {
|
||||
next unless ($k =~ /^bit_(\d+)$/);
|
||||
my $bit = $1;
|
||||
next if ($bit < 1 || $bit > 30);
|
||||
$filter |= (1 << $bit);
|
||||
}
|
||||
my $extra = "?filter=$filter";
|
||||
|
||||
return BML::redirect("$LJ::SITEROOT/users/$user/friends${extra}");
|
||||
}
|
||||
|
||||
my $remote = LJ::get_remote();
|
||||
|
||||
unless ($remote) { $body .= "<?needlogin?>"; return; }
|
||||
|
||||
my %res;
|
||||
# FIXME: make this use LJ::Protocol::do_request
|
||||
LJ::do_request({ 'mode' => 'getfriendgroups',
|
||||
'ver' => $LJ::PROTOCOL_VER,
|
||||
'user' => $remote->{'user'}, },
|
||||
\%res, { 'noauth' => 1, 'userid' => $remote->{'userid'} });
|
||||
|
||||
|
||||
unless ($res{'frgrp_maxnum'}) {
|
||||
$body = "<?h1 $ML{'.error.nogroups.header'} h1?><?p $ML{'.error.nogroups'} p?>";
|
||||
return;
|
||||
}
|
||||
|
||||
my %group;
|
||||
foreach $k (keys %res) {
|
||||
if ($k =~ /^frgrp_(\d+)_name/) {
|
||||
$group{$1}->{'name'} = $res{$k};
|
||||
}
|
||||
elsif ($k =~ /^frgrp_(\d+)_sortorder/) {
|
||||
$group{$1}->{'sortorder'} = $res{$k};
|
||||
}
|
||||
}
|
||||
|
||||
$body .= "<?h1 $ML{'.select.header'} h1?><?p $ML{'.select'} p?>";
|
||||
$body .= "<form method='post' style='display: inline' action='filter.bml'>\n";
|
||||
$body .= LJ::html_hidden("user", $remote->{'user'},
|
||||
"mode", "view");
|
||||
$body .= "<div style='margin-left: 30px'>";
|
||||
|
||||
foreach my $g (sort { $group{$a}->{'sortorder'} <=> $group{$b}->{'sortorder'} } keys %group)
|
||||
{
|
||||
my $url = "$LJ::SITEROOT/users/$remote->{'user'}/friends/" . LJ::eurl($group{$g}->{'name'});
|
||||
$body .= "<input type='checkbox' value='1' name=\"bit_$g\" /> <a href=\"$url\">" . LJ::ehtml($group{$g}->{'name'}) . "</a><br />\n";
|
||||
}
|
||||
|
||||
$body .= "<input type='submit' value=\"$ML{'.submit'}\"> <input type='reset' value=\"$ML{'.reset'}\"></div>";
|
||||
$body .= "<?p " . BML::ml('.editgroups', { 'link' => "<a href='editgroups.bml'>$ML{'/friends/editgroups.bml.title'}</a>" }) . " p?>";
|
||||
$body .= "</form>";
|
||||
|
||||
return;
|
||||
|
||||
_code?><?page
|
||||
title=><?_code return $title; _code?>
|
||||
body=><?_code return $body; _code?>
|
||||
page?><?_c <LJDEP>
|
||||
link: htdocs/users, htdocs/friends/editgroups.bml
|
||||
post: htdocs/friends/filter.bml
|
||||
</LJDEP> _c?>
|
||||
27
livejournal/htdocs/friends/graph.bml
Executable file
@@ -0,0 +1,27 @@
|
||||
<?_info
|
||||
nocache=>1
|
||||
_info?><?_code
|
||||
|
||||
if (BML::get_path_info() =~ m!^/(\w+)\.dot(\.txt)?$!) {
|
||||
BML::set_content_type("text/plain");
|
||||
return "# dot file for $1:\n" . LJ::make_graphviz_dot_file($1);
|
||||
}
|
||||
|
||||
my $u = LJ::load_user($FORM{'user'});
|
||||
unless ($u) {
|
||||
return "<?h1 Unknown user h1?><?p No user with that username. Sorry. p?>";
|
||||
}
|
||||
my $user = $u->{'user'};
|
||||
|
||||
my $ret = "";
|
||||
$ret .= "User: <B>$user</B> (<A HREF=\"/userinfo.bml?user=$user\">user info</A>)<BR><I>If image doesn't load, press reload.</I><P>";
|
||||
|
||||
$ret .= "<A HREF=http://www.research.att.com/~north/cgi-bin/webdot.cgi/";
|
||||
$ret .= "$LJ::SITEROOT/friends/graph.bml/$user.dot.map>";
|
||||
$ret .= "<IMG SRC=http://www.research.att.com/~north/cgi-bin/webdot.cgi/";
|
||||
$ret .= "$LJ::SITEROOT/friends/graph.bml/$user.dot.gif ismap border=0>";
|
||||
$ret .= "</A>\n";
|
||||
|
||||
return $ret;
|
||||
|
||||
_code?>
|
||||
34
livejournal/htdocs/friends/index.bml
Executable file
@@ -0,0 +1,34 @@
|
||||
<?page
|
||||
title=><?_ml .title _ml?>
|
||||
body<=
|
||||
<?_code
|
||||
LJ::set_active_crumb('friends');
|
||||
_code?>
|
||||
|
||||
<?p <?_ml .about _ml?> p?>
|
||||
<?h1 <?_ml .tools _ml?> h1?>
|
||||
<dl>
|
||||
<dt><a href="edit.bml"><?_ml /friends/edit.bml.title _ml?></a></dt>
|
||||
<dd><?_ml .edit.about _ml?></dd>
|
||||
</dl>
|
||||
<?p <?_ml .groups _ml?> p?>
|
||||
<dl>
|
||||
<dt><a href="editgroups.bml"><?_ml /friends/editgroups.bml.title _ml?></a></dt>
|
||||
<dd><?_ml .editgroups.about _ml?></dd>
|
||||
</dl>
|
||||
<?p <?_ml .filter _ml?> p?>
|
||||
<dl>
|
||||
<dt><a href="filter.bml"><?_ml /friends/filter.bml.title _ml?></a></dt>
|
||||
<dd><?_ml .filter.about _ml?></dd>
|
||||
</dl>
|
||||
<?h1 <?_ml .security.header _ml?> h1?>
|
||||
<?p <?_ml .security _ml?> p?>
|
||||
<ul>
|
||||
<li><?_ml .security.only _ml?></li>
|
||||
<li><?_ml .security.custom _ml?></li>
|
||||
</ul>
|
||||
<=body
|
||||
page?><?_c <LJDEP>
|
||||
link: htdocs/friends/edit.bml, htdocs/friends/editgroups.bml
|
||||
link: htdocs/friends/filter.bml, htdocs/download/index.bml
|
||||
</LJDEP> _c?>
|
||||
60
livejournal/htdocs/go.bml
Executable file
@@ -0,0 +1,60 @@
|
||||
<?_code
|
||||
{
|
||||
use strict;
|
||||
use vars qw($title $body %GET %POST);
|
||||
|
||||
$title = $ML{'.defaulttitle'};
|
||||
$body = $ML{'.defaultbody'};
|
||||
|
||||
# S2 Redirector
|
||||
if ($POST{'redir_type'} eq "monthview") {
|
||||
my $user = LJ::canonical_username($POST{'redir_user'});
|
||||
my $vhost;
|
||||
$vhost = $POST{'redir_vhost'} if $POST{'redir_vhost'}=~/users|tilde|community|front|other/;
|
||||
if ($vhost eq "other") {
|
||||
# FIXME: lookup their domain alias, and make vhost be "other:domain.com";
|
||||
}
|
||||
my $base = LJ::journal_base($user, $vhost);
|
||||
return $ML{'.error.redirkey'} unless $POST{'redir_key'} =~/^(\d\d\d\d)(\d\d)$/;
|
||||
my ($year, $month) = ($1, $2);
|
||||
return BML::redirect("$base/$year/$month/");
|
||||
}
|
||||
|
||||
# prev/next talkread links
|
||||
my $itemid = $GET{'itemid'}+0;
|
||||
if ($GET{'journal'} && $itemid)
|
||||
{
|
||||
my $journal = $GET{'journal'};
|
||||
my $u = LJ::load_user($journal);
|
||||
|
||||
# sanity check
|
||||
unless ($u) {
|
||||
$body = $ML{'.error.usernotfound'};
|
||||
return;
|
||||
}
|
||||
my $journalid = $u->{'userid'}+0;
|
||||
|
||||
$itemid = int($itemid / 256);
|
||||
|
||||
my $jumpid = 0;
|
||||
$title = $ML{'.error.noentrytitle'};
|
||||
|
||||
if ($GET{'dir'} eq "next") {
|
||||
$jumpid = LJ::get_itemid_after2($u, $itemid);
|
||||
$body = $ML{'.error.noentry.next'};
|
||||
} elsif ($GET{'dir'} eq "prev") {
|
||||
$jumpid = LJ::get_itemid_before2($u, $itemid);
|
||||
$body = $ML{'.error.noentry.prev'};
|
||||
}
|
||||
|
||||
if ($jumpid) {
|
||||
return BML::redirect(LJ::journal_base($u) . "/$jumpid.html");
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
_code?><?page
|
||||
title=><?_code return $title; _code?>
|
||||
body=><?_code return $body; _code?>
|
||||
page?>
|
||||
BIN
livejournal/htdocs/img/addfriend.gif
Executable file
|
After Width: | Height: | Size: 905 B |
BIN
livejournal/htdocs/img/anonymous.gif
Executable file
|
After Width: | Height: | Size: 229 B |
BIN
livejournal/htdocs/img/blackdot.gif
Executable file
|
After Width: | Height: | Size: 35 B |
BIN
livejournal/htdocs/img/bluedot.gif
Executable file
|
After Width: | Height: | Size: 799 B |
BIN
livejournal/htdocs/img/bluewhite/bluefade.jpg
Executable file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
livejournal/htdocs/img/bluewhite/bullet.gif
Executable file
|
After Width: | Height: | Size: 116 B |
BIN
livejournal/htdocs/img/bluewhite/hline.gif
Executable file
|
After Width: | Height: | Size: 79 B |
BIN
livejournal/htdocs/img/bluewhite/home.gif
Executable file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
livejournal/htdocs/img/bluewhite/hr_divdot.gif
Executable file
|
After Width: | Height: | Size: 166 B |
BIN
livejournal/htdocs/img/bluewhite/linetop.gif
Executable file
|
After Width: | Height: | Size: 117 B |
BIN
livejournal/htdocs/img/bluewhite/sidebarfade.gif
Executable file
|
After Width: | Height: | Size: 284 B |
BIN
livejournal/htdocs/img/bluewhite/sidebarfade_line.gif
Executable file
|
After Width: | Height: | Size: 428 B |
BIN
livejournal/htdocs/img/bluewhite/title.gif
Executable file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
livejournal/htdocs/img/bluewhite/vline.gif
Executable file
|
After Width: | Height: | Size: 115 B |
BIN
livejournal/htdocs/img/btn_addfriend.gif
Executable file
|
After Width: | Height: | Size: 1006 B |
BIN
livejournal/htdocs/img/btn_del.gif
Executable file
|
After Width: | Height: | Size: 907 B |
BIN
livejournal/htdocs/img/btn_dn.gif
Executable file
|
After Width: | Height: | Size: 598 B |