494 lines
20 KiB
Plaintext
Executable File
494 lines
20 KiB
Plaintext
Executable File
<?page
|
|
title=><?_ml .title _ml?>
|
|
head<=
|
|
<?_code return $LJ::COMMON_CODE{'autoradio_check'}; _code?>
|
|
<style>
|
|
option.disabled { color: GrayText; }
|
|
</style>
|
|
<=head
|
|
body<=
|
|
|
|
<?_code
|
|
{
|
|
# this file used to be modify_do.bml, but modify.bml died, so we moved this
|
|
# functionality to modify.bml, but we don't want the translators to have to
|
|
# retranslate all of the phrases, so we're still using /modify_do.bml scope
|
|
BML::set_language_scope("/modify_do.bml");
|
|
|
|
use strict;
|
|
use vars qw(%GET %POST);
|
|
|
|
return LJ::server_down_html() if $LJ::SERVER_DOWN;
|
|
|
|
LJ::set_active_crumb('modify');
|
|
|
|
my $remote = LJ::get_remote();
|
|
return LJ::bad_input("You must be logged in to modify your journal")
|
|
unless $remote;
|
|
|
|
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 LJ::get_cap($remote, "readonly");
|
|
|
|
### user is now authenticated ###
|
|
|
|
my $dbr = LJ::get_db_reader();
|
|
my $sth;
|
|
|
|
my $capstyles = LJ::get_cap($u, "styles");
|
|
|
|
LJ::load_user_props($u, "opt_usesharedpic",
|
|
"s1_lastn_style", "s1_calendar_style",
|
|
"s1_day_style", "s1_friends_style",
|
|
"stylesys", "journaldomain");
|
|
|
|
# if a POST, update their info
|
|
if (LJ::did_post()) {
|
|
|
|
return "<?badinput?>" unless LJ::text_in(\%POST);
|
|
|
|
# database error reporting
|
|
my $dberr = sub {
|
|
return "<?h1 $ML{'error'} h1?><?p $ML{'error.dberror'} <b>@_[0]</b> p?>";
|
|
};
|
|
|
|
my $dbh = LJ::get_db_writer();
|
|
|
|
# setup what we're gonna update in the user table:
|
|
my %update = ();
|
|
|
|
# what userprops we'll be setting.
|
|
my %uprop;
|
|
|
|
# journal domains
|
|
my $dom_cap = LJ::get_cap($u, 'userdomain');
|
|
if ((exists $POST{'journaldomain'} && $u->{'journaldomain'} ne $POST{'journaldomain'}) ||
|
|
(! $dom_cap && $POST{'journaldomain_del'}))
|
|
{
|
|
$POST{'journaldomain'} =~ s!^(http://)?(www\.)?!!;
|
|
my $dom = lc($POST{'journaldomain'});
|
|
if (($dom_cap && ! $dom) || (! $dom_cap && $POST{'journaldomain_del'})) {
|
|
$dbh->do("DELETE FROM domains WHERE userid=?", undef, $u->{'userid'});
|
|
} else {
|
|
$dbh->do("INSERT INTO domains VALUES (?, ?)", undef, $dom, $u->{'userid'});
|
|
if ($dbh->err) {
|
|
my $otherid = $dbh->selectrow_array("SELECT userid FROM domains WHERE domain=?",
|
|
undef, $dom);
|
|
return LJ::bad_input($ML{'.error.dupdomainalias'}) if $otherid != $u->{'userid'};
|
|
}
|
|
if ($u->{'journaldomain'}) {
|
|
$dbh->do("DELETE FROM domains WHERE userid=? AND domain <> ?",
|
|
undef, $u->{'userid'}, $dom);
|
|
}
|
|
}
|
|
|
|
# set journaldomain prop if it's been changed
|
|
$uprop{'journaldomain'} = $dom
|
|
unless $POST{'journaldomain'} eq $u->{'journaldomain'};
|
|
}
|
|
|
|
# validate moodthemeid
|
|
# mood theme, make sure they're allowed to use it
|
|
my $moodthemeid = $POST{'moodthemeid'}+0;
|
|
if ($moodthemeid) {
|
|
my ($mownerid, $mpublic) = $dbr->selectrow_array("SELECT ownerid, is_public FROM moodthemes ".
|
|
"WHERE moodthemeid=?", undef, $moodthemeid);
|
|
$moodthemeid = 0 unless $mpublic eq 'Y' || $mownerid == $u->{'userid'};
|
|
}
|
|
$update{'moodthemeid'} = $moodthemeid;
|
|
$update{'opt_forcemoodtheme'} = $POST{'opt_forcemoodtheme'} ? "Y" : "N";
|
|
|
|
|
|
# all of these options should only be processed for S1 users
|
|
if ($u->{'stylesys'} != 2) {
|
|
|
|
# color themes
|
|
$update{'themeid'} = $POST{'themetype'} eq "custom" ? 0 : $POST{'themeid'};
|
|
|
|
if ($POST{'themetype'} eq "custom") {
|
|
my $dig = Digest::MD5::md5_hex(join(",", map { $POST{"theme_cust:$_"} }
|
|
map { $_->[0] } @LJ::S1::themecoltypes));
|
|
if ($dig ne $POST{'themecolors_dig'}) {
|
|
my %cols;
|
|
foreach my $col (@LJ::S1::themecoltypes) {
|
|
my $val = $POST{"theme_cust:$col->[0]"};
|
|
next if length($val) > 20;
|
|
next unless ($val =~ /^\#[a-f0-9]{6,6}$/i ||
|
|
$val !~ /[^\s\w]/);
|
|
$cols{$col->[0]} = $val;
|
|
}
|
|
|
|
return $ML{"error.nodb"} unless $u->writer;
|
|
$u->do("INSERT IGNORE INTO s1usercache (userid) VALUES (?)", undef, $u->{'userid'});
|
|
$u->do("UPDATE s1usercache SET color_stor=? WHERE userid=?", undef,
|
|
Storable::freeze(\%cols), $u->{'userid'});
|
|
LJ::MemCache::delete([$u->{'userid'}, "s1uc:$u->{'userid'}"]);
|
|
|
|
$dbh->do("DELETE FROM themecustom WHERE user=?", undef, $u->{'user'})
|
|
if $dbh->selectrow_array("SELECT user FROM themecustom ".
|
|
"WHERE user=? LIMIT 1", undef, $u->{'user'});
|
|
}
|
|
}
|
|
|
|
# update 'overrides' table
|
|
if ($POST{'overrides'} !~ /\S/) {
|
|
LJ::S1::clear_overrides($u);
|
|
$update{'useoverrides'} = "N";
|
|
|
|
} else {
|
|
|
|
my $oldoverrides = "";
|
|
if ($u->{'useoverrides'} eq "Y") {
|
|
$oldoverrides = LJ::S1::get_overrides($u);
|
|
}
|
|
|
|
# This allows users to keep their current illegal overrides,
|
|
# but they may not create new ones nor edit the ones they already have.
|
|
# They may only delete or keep illegal overrides.
|
|
my %overrides = ();
|
|
my %newoverrides = ();
|
|
LJ::parse_vars(\$oldoverrides,\%overrides);
|
|
LJ::parse_vars(\$POST{'overrides'},\%newoverrides);
|
|
|
|
# head overrides should only have valid head elements in them
|
|
foreach my $a (qw(GLOBAL LASTN FRIENDS CALENDAR DAY)) {
|
|
my $sec = "${a}_HEAD";
|
|
next unless $newoverrides{$sec} ne $overrides{$sec};
|
|
|
|
my $testtag = sub {
|
|
my $tag = lc(shift);
|
|
return "<$tag" if ($tag eq "title" || $tag eq "base" ||
|
|
$tag eq "style" || $tag eq "link" ||
|
|
$tag eq "meta" || $tag eq "xx");
|
|
return "<xx-$tag";
|
|
};
|
|
$newoverrides{$sec} =~ s/\<(\w+)/$testtag->($1)/eig;
|
|
$newoverrides{$sec} =~ s/\<\/head/\<\/xx-head/ig;
|
|
}
|
|
|
|
# load all the properties to see which ones are overridable
|
|
my @vars;
|
|
LJ::load_objects_from_file("vars.dat", \@vars);
|
|
foreach my $v (@vars) {
|
|
my $ov = $v->{'props'}->{'override'};
|
|
if ($ov eq "yes" || $ov eq "only" || $capstyles) {
|
|
my $name = $v->{'name'};
|
|
if (defined $newoverrides{$name}) {
|
|
$overrides{$name} = $newoverrides{$name};
|
|
}
|
|
}
|
|
}
|
|
|
|
# make the new override code we'll put in the database
|
|
my $overr='';
|
|
foreach (keys %overrides) {
|
|
if ($newoverrides{$_}) {
|
|
if ($overrides{$_} =~ /\n/) {
|
|
$overr .= "$_<=\n".$overrides{$_}."\n<=$_\n\n";
|
|
} else {
|
|
$overr .= "$_=>".$overrides{$_}."\n\n";
|
|
}
|
|
}
|
|
}
|
|
|
|
# no value, delete overrides
|
|
if ($overr !~ /\S/) {
|
|
LJ::S1::clear_overrides($u);
|
|
$update{'useoverrides'} = "N";
|
|
|
|
# have a value, update overrides
|
|
} else {
|
|
LJ::S1::save_overrides($u, $overr);
|
|
$update{'useoverrides'} = "Y";
|
|
}
|
|
}
|
|
|
|
# friends view shared pic option for s1
|
|
$uprop{'opt_usesharedpic'} = $POST{'opt_usesharedpic'} ? "1" : "0";
|
|
|
|
# set all the styles
|
|
{
|
|
my @picked = ();
|
|
foreach my $view (@LJ::views) {
|
|
my $sid = $POST{"s1_${view}_style"}+0;
|
|
if ($sid) {
|
|
$uprop{"s1_${view}_style"} = $sid;
|
|
push @picked, $sid;
|
|
}
|
|
}
|
|
|
|
# verify they haven't forged the style numbers
|
|
unless ($capstyles) {
|
|
|
|
# just load whole structure since it should be cached
|
|
my $pubstyles = LJ::S1::get_public_styles();
|
|
my $userstyles = LJ::S1::get_user_styles($u);
|
|
|
|
foreach (@picked) {
|
|
my $type = $userstyles->{$_}->{'type'};
|
|
return LJ::bad_input($ML{'.error.stylenotavailable'})
|
|
unless exists $pubstyles->{$_} ||
|
|
exists $userstyles->{$_} &&
|
|
($capstyles || $_ == $u->{"s1_${type}_style"});
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
# update 'user' table
|
|
foreach (keys %update) {
|
|
delete $update{$_} if $u->{$_} eq $update{$_};
|
|
}
|
|
LJ::update_user($u, \%update) if %update;
|
|
|
|
# change any of the userprops ?
|
|
foreach my $uprop (keys %uprop) {
|
|
next if $POST{$uprop} eq $u->{$uprop};
|
|
LJ::set_userprop($u, $uprop, $uprop{$uprop});
|
|
}
|
|
|
|
# tell the user all is well
|
|
return "<?h1 $ML{'.success.head'} h1?><?p ".BML::ml(".success.text", {'url' => LJ::journal_base($u)})." p?>";
|
|
}
|
|
|
|
# not submitting a post, show edit form
|
|
my $ret;
|
|
|
|
# user switcher
|
|
$ret .= "<form action='modify.bml' method='get'>\n";
|
|
$ret .= LJ::make_authas_select($remote, { 'authas' => $GET{'authas'} });
|
|
$ret .= "</form>\n\n";
|
|
|
|
### journal style
|
|
$ret .= "<?h1 $ML{'.journaloptions.head'} h1?>\n<?p $ML{'.journaloptions.about'} p?>\n\n";
|
|
|
|
###
|
|
### LAYOUT OPTIONS
|
|
###
|
|
|
|
$ret .= "<form method='post' action='modify.bml?authas=$authas'>\n";
|
|
|
|
# using S1, need to take style input
|
|
if ($u->{'stylesys'} != 2)
|
|
{
|
|
my $and = $capstyles ? "" : $ML{'.pagelayoutstyle.warning'};
|
|
$ret .= "<?h2 $ML{'.pagelayoutstyle.head'} h2?><?p $ML{'.pagelayoutstyle.about'} $and p?>\n";
|
|
$ret .= "<table style='margin-left: 30px; margin-bottom: 20px;'>\n";
|
|
$ret .= "<tr bgcolor='#d0d0d0'><td></td><td>$ML{'.availablestyles.head'}</td></tr>\n";
|
|
|
|
my $pubstyles = LJ::S1::get_public_styles();
|
|
my %pubstyles = ();
|
|
foreach (sort { $a->{'styledes'} cmp $b->{'styledes'} } values %$pubstyles) {
|
|
push @{$pubstyles{$_->{'type'}}}, $_;
|
|
}
|
|
|
|
my $userstyles = LJ::S1::get_user_styles($u);
|
|
my %userstyles = ();
|
|
foreach (sort { $a->{'styledes'} cmp $b->{'styledes'} } values %$userstyles) {
|
|
push @{$userstyles{$_->{'type'}}}, $_;
|
|
}
|
|
|
|
foreach my $view (@LJ::views) {
|
|
|
|
$ret .= "<tr><td bgcolor='#d0d0d0'>$LJ::viewinfo{$view}->{'des'}</td><td>";
|
|
|
|
my @list = map { $_->{'styleid'}, $_->{'styledes'} }
|
|
@{$pubstyles{$view} || []};
|
|
|
|
if (@{$userstyles{$view} || []}) {
|
|
|
|
my @user_list = map { $_->{'styleid'}, $_->{'styledes'} }
|
|
grep { $capstyles || $u->{"s1_${view}_style"} == $_->{'styleid'} }
|
|
@{$userstyles{$view} || []};
|
|
push @list, { value => "",
|
|
text => "--- $ML{'.availablestyles.userstyles'} ---",
|
|
disabled => 1 }, @user_list
|
|
if @user_list;
|
|
|
|
my @disabled_list =
|
|
map { { value => $_->{'styleid'},
|
|
text => $_->{'styledes'},
|
|
disabled => 1 } }
|
|
grep { ! $capstyles && $u->{"s1_${view}_style"} != $_->{'styleid'} }
|
|
@{$userstyles{$view} || []};
|
|
push @list, { value => '',
|
|
text => "--- $ML{'.availablestyles.disabledstyles'} ---",
|
|
disabled => 1 }, @disabled_list
|
|
if @disabled_list;
|
|
}
|
|
|
|
$ret .= LJ::html_select({ 'name' => "s1_${view}_style",
|
|
'selected' => $u->{"s1_${view}_style"} }, @list);
|
|
|
|
$ret .= "</td></tr>\n";
|
|
}
|
|
$ret .= "</table>\n\n";
|
|
|
|
###
|
|
### COLOR THEME OPTIONS
|
|
###
|
|
|
|
$ret .= "<?h2 $ML{'.colortheme.head'} h2?><?p $ML{'.colortheme.about'} p?>\n";
|
|
$ret .= "<div style='margin-left: 30px; margin-bottom: 20px;'>\n";
|
|
|
|
$ret .= LJ::html_check({ 'type' => 'radio', 'name' => 'themetype',
|
|
'value' => 'default', 'selected' => $u->{'themeid'} > 0 });
|
|
$ret .= "<b>$ML{'.colortheme.defaulttheme'}</b>: ";
|
|
|
|
my @list;
|
|
$sth = $dbr->prepare("SELECT themeid, name FROM themelist ORDER BY name");
|
|
$sth->execute;
|
|
while ($_ = $sth->fetchrow_hashref) {
|
|
push @list, ($_->{'themeid'}, $_->{'name'});
|
|
}
|
|
$ret .= LJ::html_select({ 'name' => 'themeid', 'selected' => $u->{'themeid'} }, @list) . "<br />\n";
|
|
$ret .= LJ::html_check({ 'type' => 'radio', 'name' => 'themetype', 'id' => 'themetype:custom',
|
|
'value' => 'custom', 'selected' => $u->{'themeid'} == 0 }) . "\n";
|
|
$ret .= "<b>$ML{'.colortheme.customcolors'}</b>:";
|
|
|
|
$ret .= "<table border='1' align='center' cellpadding='2'>\n";
|
|
$ret .= "<tr valign='top' bgcolor='#d0d0d0'><td align='right'><b>$ML{'.colortheme.area.head'}</b></td><td><b>$ML{'.colortheme.color.head1'}</b><br /><font size='-1'>$ML{'.colortheme.color.head2'}</font></td></tr>\n";
|
|
|
|
# get the user's custom colors
|
|
my %custcolors = ();
|
|
|
|
if ($u->{'themeid'} == 0) {
|
|
my $dbcr = LJ::get_cluster_reader($u);
|
|
my $stor = $dbcr->selectrow_array("SELECT color_stor FROM s1usercache WHERE userid=?",
|
|
undef, $u->{'userid'});
|
|
if ($stor) {
|
|
%custcolors = %{ Storable::thaw($stor) };
|
|
} else {
|
|
# ancient table.
|
|
$sth = $dbr->prepare("SELECT coltype, color FROM themecustom WHERE user=?");
|
|
$sth->execute($u->{'user'});
|
|
$custcolors{$_->{'coltype'}} = $_->{'color'} while $_ = $sth->fetchrow_hashref;
|
|
}
|
|
} else {
|
|
$sth = $dbr->prepare("SELECT coltype, color FROM themedata WHERE themeid=?");
|
|
$sth->execute($u->{'themeid'});
|
|
$custcolors{$_->{'coltype'}} = $_->{'color'} while $_ = $sth->fetchrow_hashref;
|
|
}
|
|
|
|
my $dig;
|
|
foreach my $col (@LJ::S1::themecoltypes) {
|
|
$ret .= "<tr><td align='right'>$col->[1]</td><td>";
|
|
$ret .= LJ::html_text({ 'name' => "theme_cust:$col->[0]", 'size' => '20',
|
|
'maxlength' => '30', 'value' => $custcolors{$col->[0]},
|
|
'onchange' => "checkRadioButton('themetype:custom');" });
|
|
$ret .= "</td></tr>\n";
|
|
$dig .= $col->[0];
|
|
}
|
|
$dig = Digest::MD5::md5_hex($dig);
|
|
$ret .= LJ::html_hidden("themecolors_dig", $dig) unless $u->{'themeid'};
|
|
|
|
$ret .= "</table></div>\n\n";
|
|
|
|
###
|
|
### FRIENDS VIEW OPTIONS
|
|
###
|
|
|
|
$ret .= "<?h2 $ML{'.friends.head'} h2?><?p $ML{'.friends.about'} p?>";
|
|
$ret .= "<table style='margin-left: 30px; margin-bottom: 20px;' cellspacing='0'>\n";
|
|
|
|
$ret .= "<tr valign='middle'><td>";
|
|
$ret .= LJ::html_check({ 'type' => 'check', 'name' => 'opt_usesharedpic', 'selected' => $u->{'opt_usesharedpic'} });
|
|
$ret .= "</td><td><b>$ML{'.friends.opt.usesharedpic.head'}</b></td></tr>\n";
|
|
$ret .= "<tr><td> </td><td>$ML{'.friends.opt.usesharedpic.about'}</td></tr>\n";
|
|
|
|
$ret .= "</table>\n\n";
|
|
|
|
###
|
|
### STYLE OVERRIDES
|
|
###
|
|
|
|
# first, load the overrides if they use 'em:
|
|
my $overrides = "";
|
|
if ($u->{'useoverrides'} eq "Y") {
|
|
$overrides = LJ::S1::get_overrides($u);
|
|
LJ::text_out(\$overrides);
|
|
}
|
|
|
|
$ret .= "<div style='margin-bottom: 20px'>\n";
|
|
$ret .= "<?h1 $ML{'.overrides.head'} h1?><?p $ML{'.overrides.about'} p?>\n";
|
|
$ret .= "<?p <font size='+1'><b>$ML{'.overrides.warning'}</b></font> p?>\n";
|
|
$ret .= "<?p $ML{'.overrides.note'} p?>\n";
|
|
$ret .= "<?standout <b>$ML{'.overrides.box.head'}</b><br />";
|
|
$ret .= LJ::html_textarea({ 'name' => 'overrides', 'cols' => '60', 'rows' => '15',
|
|
'wrap' => 'off', 'value' => $overrides }) . " standout?>";
|
|
$ret .= "</div>\n\n";
|
|
}
|
|
|
|
###
|
|
### MOOD THEME OPTIONS
|
|
###
|
|
|
|
$ret .= "<?h2 $ML{'.moodicons.head'} h2?><?p $ML{'.moodicons.about'} p?>\n";
|
|
|
|
$sth = $dbr->prepare("SELECT moodthemeid, name FROM moodthemes WHERE is_public='Y'");
|
|
$sth->execute;
|
|
my @themes = ({ 'moodthemeid' => 0, 'name' => '(None)' });
|
|
push @themes, $_ while ($_ = $sth->fetchrow_hashref);
|
|
|
|
### user's private themes
|
|
{
|
|
my @theme_user;
|
|
$sth = $dbr->prepare("SELECT moodthemeid, name FROM moodthemes WHERE ownerid=? AND is_public='N'");
|
|
$sth->execute($u->{'userid'});
|
|
push @theme_user, $_ while ($_ = $sth->fetchrow_hashref);
|
|
if (@theme_user) {
|
|
push @themes, { 'moodthemeid' => 0, 'name' => "--- $ML{'.moodicons.personal'} ---" };
|
|
push @themes, @theme_user;
|
|
}
|
|
}
|
|
|
|
$ret .= "<div style='margin-left: 30px; margin-bottom: 20px;'><b>$ML{'.moodicons.select'} </b>\n";
|
|
$ret .= LJ::html_select({ 'name' => 'moodthemeid', 'selected' => $u->{'moodthemeid'} },
|
|
map { $_->{'moodthemeid'}, $_->{'name'} } @themes) . "\n";
|
|
|
|
$ret .= "(<a href='$LJ::SITEROOT/moodlist.bml' target='moods'>$ML{'.moodicons.preview'}</a>)\n";
|
|
$ret .= "<br />" . LJ::html_check({ 'type' => 'check', 'name' => 'opt_forcemoodtheme',
|
|
'id' => 'opt_forcemoodtheme',
|
|
'selected' => $u->{'opt_forcemoodtheme'} eq 'Y' }) . "\n";
|
|
$ret .= "<label for='opt_forcemoodtheme'>$ML{'.moodicons.opt.forcefriends.about'}</label></div>\n\n";
|
|
|
|
###
|
|
### JOURNAL DOMAIN OPTIONS
|
|
###
|
|
|
|
my $has_cap = LJ::get_cap($u, 'userdomain');
|
|
my $has_dom = $u->{journaldomain} ? 1 : 0;
|
|
if ($LJ::OTHER_VHOSTS && ($has_cap || $has_dom)) {
|
|
$ret .= "<?h2 $ML{'.domainalias.head'} h2?><?p $ML{'.domainalias.about'} p?>\n";
|
|
|
|
$ret .= "<div style='margin: 20px 0 20px 30px'>";
|
|
$ret .= "<table><tr><td align='left'><b>$ML{'.domainalias.domainname'}</b></td><td>";
|
|
$ret .= LJ::html_text({ 'name' => 'journaldomain', 'size' => '30',
|
|
'maxlength' => '80', 'value' => $u->{'journaldomain'},
|
|
'disabled' => ! $has_cap });
|
|
$ret .= LJ::html_submit('journaldomain_del' => "Remove") unless $has_cap;
|
|
$ret .= "</td></tr>";
|
|
$ret .= "<tr><td> </td><td>$ML{'.domainalias.example'}</td></tr></table>";
|
|
$ret .= "<?p " . BML::ml(".domainalias.helptext", {'sitename' => $LJ::SITENAME})." p?></div>\n\n";
|
|
}
|
|
|
|
### ending submit block
|
|
$ret .= "<?h1 $ML{'.done.head'} h1?><?p $ML{'.done.text'} p?>\n";
|
|
$ret .= "<?standout " . LJ::html_submit(undef, $ML{'.done.btn.savechanges'}) . " standout?>\n";
|
|
$ret .= "</form>\n";
|
|
|
|
return $ret;
|
|
|
|
}
|
|
_code?>
|
|
|
|
<=body
|
|
page?><?_c <LJDEP>
|
|
link: htdocs/moodlist.bml, htdocs/developer/index.bml, htdocs/developer/varlist.bml, htdocs/styles/create.bml
|
|
post: htdocs/modify_do.bml
|
|
</LJDEP> _c?>
|