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

View File

@@ -0,0 +1,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'} &rarr;") . "</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?>

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

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

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

View 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>"}) . "&nbsp;&nbsp;";
$ret .= BML::ml('Actionlink', {
'link'=>"<a href='/community/settings.bml?comm=$user'>$ML{'.commlist.actsettings2'}</a>"}) . "&nbsp;&nbsp;";
$ret .= BML::ml('Actionlink', {
'link'=>"<a href='/community/sentinvites.bml?comm=$user'>$ML{'.commlist.actinvites'}</a>"}) . "&nbsp;&nbsp;";
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"}) . "&nbsp;&nbsp;";
}
$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?>

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

View 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&amp;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 .= "&nbsp;&nbsp;<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?>

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

View File

@@ -0,0 +1,165 @@
<?_info
localblocks<=
crit<=
{F}
<tr bgcolor='<?emcolor?>'>
<td align='left' colspan='2'><b>%%name%%</b>
</tr>
<tr><td>&nbsp;</td><td>%%form%%</td></tr>
<=crit
bar<=
{F}
<tr bgcolor='<?emcolor?>'>
<td>&nbsp;</td>
<td><b>%%name%%</b>
</tr>
<tr><td>&nbsp;</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?>

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

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

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