ljr/livejournal/htdocs/editpics.bml

874 lines
37 KiB
Plaintext
Executable File

<?_code
{
use strict;
use vars qw(%GET %POST $title $body @errors);
LJ::set_active_crumb('editpics');
$body = "";
@errors = ();
my $err = sub {
$title = "Error";
$body = LJ::bad_input(@_);
return;
};
unless (LJ::text_in(\%POST)) {
return $err->("Invalid UTF-8 Input");
}
my $remote = LJ::get_remote();
return $err->($ML{'error.noremote'})
unless $remote;
if ($remote->underage) {
return BML::redirect("$LJ::SITEROOT/agecheck/?s=1");
}
my $authas = $GET{'authas'} || $remote->{'user'};
my $u = LJ::get_authas_user($authas);
return $err->($ML{'error.invalidauth'})
unless $u;
# extra arguments for get requests
my $getextra = $authas ne $remote->{'user'} ? "?authas=$authas" : '';
my $returl = LJ::CleanHTML::canonical_url($POST{'ret'});
my $picurl = LJ::CleanHTML::canonical_url($POST{'urlpic'});
my $fotobilder = index($returl, $LJ::FB_SITEROOT) == 0 &&
$picurl =~ m!^$LJ::FB_SITEROOT/~?$remote->{'user'}/pic/!;
if ($fotobilder &&
(LJ::check_referer($returl) || LJ::check_referer('/editpics.bml'))) {
return $err->('Invalid referring site or redirection not allowed')
unless $returl =~ /$LJ::FB_DOMAIN/ && LJ::get_cap($u, 'fb_account');
}
if (LJ::get_cap($u, "readonly")) {
$title = "Read-only mode";
$body = $LJ::MSG_READONLY_USER;
return;
}
# update this user's activated pics
LJ::activate_userpics($u);
my ($dbh, $dbcm, $dbcr, $sth);
# Put $count and $max in larger scope so they can be used in output
my $count;
$dbcm = LJ::get_cluster_master($u);
return $err->($ML{'error.nodb'}) unless $dbcm;
if ($u->{'dversion'} > 6) {
$dbcr = LJ::get_cluster_def_reader($u);
return $err->($ML{'error.nodb'}) unless $dbcr;
$count = $dbcr->selectrow_array("SELECT COUNT(*) FROM userpic2 " .
"WHERE userid=? AND state <> 'X'", undef, $u->{'userid'});
} else {
$dbh = LJ::get_db_writer();
return $err->($ML{'error.nodb'}) unless $dbh;
$count = $dbh->selectrow_array("SELECT COUNT(*) FROM userpic " .
"WHERE userid=? AND state <> 'X'", undef, $u->{'userid'});
}
my $max = LJ::get_cap($u, "userpics");
### save mode
if (LJ::did_post()) {
### save changes to existing pics
if ($POST{'action:save'}) {
# form being posted isn't multipart, since we were able to read from %POST
my %exist_kwids;
if ($u->{'dversion'} > 6) {
$sth = $dbcr->prepare("SELECT kwid, picid FROM userpicmap2 WHERE userid=?");
} else {
$sth = $dbh->prepare("SELECT kwid, picid FROM userpicmap WHERE userid=?");
}
$sth->execute($u->{'userid'});
while (my ($kwid, $picid) = $sth->fetchrow_array) {
push @{$exist_kwids{$picid}}, $kwid;
}
my @inactive_picids;
my @delete;
my %picid_of_kwid;
my %ctype; # picid -> contenttype, for delete mode
my %states; # picid -> state, for setting new default
my %locations; # picid -> location, for deleting
my @comments;
my %exist_comments;
# select all of their userpics and iterate through them
if ($u->{'dversion'} > 6) {
$sth = $dbcr->prepare("SELECT picid, width, height, state, fmt, comment, location " .
"FROM userpic2 WHERE userid=?");
} else {
$sth = $dbh->prepare("SELECT picid, width, height, state, contenttype " .
"FROM userpic WHERE userid=?");
}
$sth->execute($u->{'userid'});
while (my $pic = $sth->fetchrow_hashref)
{
# ignore anything expunged
next if $pic->{state} eq 'X';
# store picture information
$states{$pic->{picid}} = $pic->{state};
$locations{$pic->{picid}} = $pic->{location}
if $u->{dversion} > 6;
$exist_comments{$pic->{picid}} = $pic->{comment};
# delete this pic
if ($POST{"delete_$pic->{'picid'}"}) {
push @delete, $pic->{'picid'};
$ctype{$pic->{picid}} = ($u->{'dversion'} > 6) ? $pic->{'fmt'} : $pic->{'contenttype'};
next;
}
# make a list of inactive picids
if ($pic->{'state'} eq 'I') {
push @inactive_picids, $pic->{'picid'};
next;
}
# we're going to modify keywords on active pictures
my $c = 1;
my @kw_errors;
my @keywords = split(/\s*,\s*/, $POST{"kw_$pic->{'picid'}"});
@keywords = grep { s/^\s+//; s/\s+$//; $_; } @keywords;
foreach my $kw (@keywords) {
my $kwid = ($u->{'dversion'} > 6) ? LJ::get_keyword_id($u, $kw) : LJ::get_keyword_id($kw);
next unless $kwid;
if ($c > $LJ::MAX_USERPIC_KEYWORDS) {
my $ekw = LJ::ehtml($kw);
push @kw_errors, $ekw;
next;
}
if ($picid_of_kwid{$kwid}) {
my $ekw = LJ::ehtml($kw);
push @errors, BML::ml(".error.keywords", {'ekw' => $ekw});
}
$picid_of_kwid{$kwid} = $pic->{'picid'};
$c++;
}
# Let the user know about any we didn't save
if (@kw_errors) {
my $num_words = scalar(@kw_errors);
my $kws = join (", ", @kw_errors);
push @errors, BML::ml(".error.toomanykeywords", {'numwords' => $num_words, 'words' => $kws, 'max' => $LJ::MAX_USERPIC_KEYWORDS});
}
# Find if they changed the comment and then save the new one
if ($u->{'dversion'} > 6 && $POST{"com_$pic->{'picid'}"} ne $exist_comments{$pic->{'picid'}}) {
my $comment = LJ::text_trim($POST{"com_$pic->{'picid'}"}, LJ::BMAX_UPIC_COMMENT, LJ::CMAX_UPIC_COMMENT);
$u->do("UPDATE userpic2 SET comment=? WHERE userid=? AND picid=?",
undef, $comment, $u->{'userid'}, $pic->{'picid'});
}
}
# now, reapply the existing picids to the inactive pics, unless
# that picid has already been assigned to a new active one
foreach my $picid (@inactive_picids) {
next unless $exist_kwids{$picid};
foreach (@{$exist_kwids{$picid}}) {
$picid_of_kwid{$_} ||= $picid;
}
}
if (@delete) {
my $id_in;
if ($u->{'dversion'} > 6) {
$id_in = join(", ", map { $dbcm->quote($_) } @delete);
} else {
$id_in = join(", ", map { $dbh->quote($_) } @delete);
}
# delete data from user cluster
foreach my $picid (@delete) {
my $fmt;
if ($u->{'dversion'} > 6) {
$fmt = {
'G' => 'gif',
'J' => 'jpg',
'P' => 'png',
}->{$ctype{$picid}};
} else {
$fmt = {
'image/gif' => 'gif',
'image/jpeg' => 'jpg',
'image/png' => 'png',
}->{$ctype{$picid}};
}
my $deleted = 0;
# try and delete from either the blob server or database,
# and only after deleting the image do we delete the metadata.
if ($locations{$picid} eq 'mogile') {
$deleted = 1
if LJ::mogclient()->delete($u->mogfs_userpic_key($picid));
} elsif ($LJ::USERPIC_BLOBSERVER &&
LJ::Blob::delete($u, "userpic", $fmt, $picid)) {
$deleted = 1;
} elsif ($u->do("DELETE FROM userpicblob2 WHERE ".
"userid=? AND picid=?", undef,
$u->{userid}, $picid) > 0) {
$deleted = 1;
}
# now delete the metadata if we got the real data
if ($deleted) {
if ($u->{'dversion'} > 6) {
$u->do("DELETE FROM userpic2 WHERE picid=? AND userid=?",
undef, $picid, $u->{'userid'});
} else {
$dbh->do("DELETE FROM userpic WHERE picid=?", undef, $picid);
}
$u->do("DELETE FROM userblob WHERE journalid=? AND blobid=? " .
"AND domain=?", undef, $u->{'userid'}, $picid,
LJ::get_blob_domainid('userpic'));
# decrement $count to reflect deletion
$count--;
}
# if we didn't end up deleting, it's either because of
# some transient error, or maybe there was nothing to delete
# for some bizarre reason, in which case we should verify
# that and make sure they can delete their metadata
if (! $deleted) {
my $present;
if ($locations{$picid} eq 'mogile') {
my $blob = LJ::mogclient()->get_file_data($u->mogfs_userpic_key($picid));
$present = length($blob) ? 1 : 0;
} elsif ($LJ::USERPIC_BLOBSERVER) {
my $blob = LJ::Blob::get($u, "userpic", $fmt, $picid);
$present = length($blob) ? 1 : 0;
}
$present ||= $dbcm->selectrow_array("SELECT COUNT(*) FROM userpicblob2 WHERE ".
"userid=? AND picid=?", undef, $u->{'userid'},
$picid);
if (! int($present)) {
if ($u->{'dversion'} > 6) {
$u->do("DELETE FROM userpic2 WHERE picid=? AND userid=?",
undef, $picid, $u->{'userid'});
} else {
$dbh->do("DELETE FROM userpic WHERE picid=?", undef, $picid);
}
}
}
}
# if any of the userpics they want to delete are active, then we want to
# re-run LJ::activate_userpics() - turns out it's faster to not check to
# see if we need to do this
LJ::activate_userpics($u);
}
if (%picid_of_kwid) {
if ($u->{'dversion'} > 6) {
$u->do("REPLACE INTO userpicmap2 (userid, kwid, picid) VALUES " .
join(",", map { "(" .
join(",",
$dbcm->quote($u->{'userid'}),
$dbcm->quote($_),
$dbcm->quote($picid_of_kwid{$_})) .
")"
}
keys %picid_of_kwid)
);
} else {
$dbh->do("REPLACE INTO userpicmap (userid, kwid, picid) VALUES " .
join(",", map { "(" .
join(",",
$dbh->quote($u->{'userid'}),
$dbh->quote($_),
$dbh->quote($picid_of_kwid{$_})) .
")"
}
keys %picid_of_kwid)
);
}
}
# Delete keywords that are no longer being used
my @kwid_del;
foreach my $kwids (values %exist_kwids) {
foreach my $kwid (@$kwids) {
if (! $picid_of_kwid{$kwid}) {
push @kwid_del, $kwid+0;
}
}
}
if (@kwid_del) {
my $kwid_del = join(",", @kwid_del);
if ($u->{'dversion'} > 6) {
$u->do("DELETE FROM userpicmap2 WHERE userid=$u->{userid} " .
"AND kwid IN ($kwid_del)");
} else {
$dbh->do("DELETE FROM userpicmap WHERE userid=$u->{userid} " .
"AND kwid IN ($kwid_del)");
}
}
my $new_default = $POST{'defaultpic'}+0;
if ($POST{"delete_$POST{'defaultpic'}"}) {
# deleting your default
$new_default = 0;
}
if ($new_default != $u->{'defaultpicid'}) {
# see if they are trying to make an inactive userpic their default
if ($states{$new_default} eq 'N' || !$new_default) {
LJ::update_user($u, { defaultpicid => $new_default });
$u->{'defaultpicid'} = $new_default;
}
}
my $memkey = [$u->{'userid'},"upicinf:$u->{'userid'}"];
LJ::MemCache::delete($memkey);
$memkey = [$u->{'userid'},"upiccom:$u->{'userid'}"];
LJ::MemCache::delete($memkey);
$memkey = [$u->{'userid'},"upicurl:$u->{'userid'}"];
LJ::MemCache::delete($memkey);
}
### no post, so we'll parse the multipart data
unless (%POST) {
my $MAX_UPLOAD = 40960;
my $error;
# Add some slop to account for the size of the form headers etc.
BML::parse_multipart(\%POST, \$error, $MAX_UPLOAD + 2048);
# was there an error parsing the multipart form?
if ($error) {
if ($error =~ /^\[(\S+?)\]/) {
my $code = $1;
if ($code eq "toolarge") {
return $err->(BML::ml('.error.filetoolarge',
{ 'maxsize' => int($MAX_UPLOAD / 1024) .
$ML{'.kilobytes'} }));
}
$error = BML::ml("BML.parse_multipart.$code");
}
return $err->($error) if $error;
}
# error check input contents
if ($POST{'src'} eq "url" && $POST{'urlpic'} !~ /^http:\/\//) {
return $err->($ML{'.error.badurl'});
}
if ($POST{'src'} eq "file") {
# already loaded from multipart parse earlier
} elsif ($POST{'src'} eq "url") {
require LWPx::ParanoidAgent;
my $ua = LWPx::ParanoidAgent->new(
timeout => 10,
max_size => $MAX_UPLOAD + 1024,
);
my $res = $ua->get($POST{urlpic});
$POST{userpic} = $res->content if $res && $res->is_success;
return $err->($ML{'.error.urlerror'}) unless $POST{userpic};
}
if (length($POST{'userpic'}) > $MAX_UPLOAD) {
return $err->(BML::ml('.error.filetoolarge',
{ 'maxsize' => int($MAX_UPLOAD / 1024) .
$ML{'.kilobytes'} }));
}
my ($sx, $sy, $filetype) = Image::Size::imgsize(\$POST{'userpic'});
unless (defined $sx) {
return $err->($ML{'.error.invalidimage'});
}
unless ($filetype eq "GIF" || $filetype eq "JPG" || $filetype eq "PNG") {
return $err->(BML::ml(".error.unsupportedtype",
{ 'filetype' => $filetype }));
}
if ($sx > 100 || $sy > 100) {
return $err->( BML::ml(".error.imagetoolarge",
{ 'imagesize' => "${sx}$ML{'.imagesize.by'}${sy}",
'maxsize' => "100$ML{'.imagesize.by'}100" }) );
}
my $base64 = Digest::MD5::md5_base64($POST{'userpic'});
## see if they have too many pictures uploaded
if ($count >= $max) {
return $err->( BML::ml(".error.toomanypics2",
{ 'maxpics' => $max }) .
LJ::help_icon('userpics', " ", ""));
}
# see if it's a duplicate
my $picid;
my $contenttype;
if ($u->{'dversion'} > 6) {
if ($filetype eq "GIF") { $contenttype = 'G'; }
elsif ($filetype eq "PNG") { $contenttype = 'P'; }
elsif ($filetype eq "JPG") { $contenttype = 'J'; }
$picid = $dbcr->selectrow_array("SELECT picid FROM userpic2 " .
"WHERE userid=? AND fmt=? " .
"AND md5base64=?",
undef, $u->{'userid'}, $contenttype, $base64);
} else {
if ($filetype eq "GIF") { $contenttype = "image/gif"; }
elsif ($filetype eq "PNG") { $contenttype = "image/png"; }
elsif ($filetype eq "JPG") { $contenttype = "image/jpeg"; }
$picid = $dbh->selectrow_array("SELECT picid FROM userpic " .
"WHERE userid=? AND contenttype=? " .
"AND md5base64=?",
undef, $u->{'userid'}, $contenttype, $base64);
}
# if picture isn't a duplicate, insert it
if ($picid == 0) {
# insert the meta-data
# Make a new global picid
$picid = LJ::alloc_global_counter('P') or
return $err->('Unable to allocate new picture id');
# see where we're inserting this
my $target;
if ($u->{dversion} > 6 && $LJ::USERPIC_MOGILEFS) {
$target = 'mogile';
} elsif ($LJ::USERPIC_BLOBSERVER) {
$target = 'blob';
}
my $dberr = 0;
if ($u->{'dversion'} > 6) {
$u->do("INSERT INTO userpic2 (picid, userid, fmt, width, height, " .
"picdate, md5base64, location) VALUES (?, ?, ?, ?, ?, NOW(), ?, ?)",
undef, $picid, $u->{'userid'}, $contenttype, $sx, $sy, $base64, $target);
if ($u->err) {
push @errors, $err->($u->errstr);
$dberr = 1;
}
} else {
$dbh->do("INSERT INTO userpic (picid, userid, contenttype, width, height, " .
"picdate, md5base64) VALUES (?, ?, ?, ?, ?, NOW(), ?)",
undef, $picid, $u->{'userid'}, $contenttype, $sx, $sy, $base64);
if ($dbh->err) {
push @errors, $err->($dbh->errstr);
$dberr = 1;
}
}
my $clean_err = sub {
if ($u->{'dversion'} > 6) {
$u->do("DELETE FROM userpic2 WHERE userid=? AND picid=?",
undef, $u->{'userid'}, $picid) if $picid;
} else {
$dbh->do("DELETE FROM userpic WHERE picid=?", undef, $picid) if $picid;
}
return $err->(@_);
};
### insert the blob
if ($target eq 'mogile' && !$dberr) {
my $fh = LJ::mogclient()->new_file($u->mogfs_userpic_key($picid), 'userpics');
if (defined $fh) {
$fh->print($POST{'userpic'});
my $rv = $fh->close;
push @errors, $clean_err->("Error saving to storage server: $@") unless $rv;
} else {
# fatal error, we couldn't get a filehandle to use
push @errors, $clean_err->("Unable to contact storage server. Your picture has not been saved.");
}
} elsif ($target eq 'blob' && !$dberr) {
my $et;
my $fmt = lc($filetype);
my $rv = LJ::Blob::put($u, "userpic", $fmt, $picid, $POST{'userpic'}, \$et);
push @errors, $clean_err->("Error saving to media server: $et") unless $rv;
} elsif (!$dberr) {
my $dbcm = LJ::get_cluster_master($u);
return $err->($ML{'error.nodb'}) unless $dbcm;
$u->do("INSERT INTO userpicblob2 (userid, picid, imagedata) " .
"VALUES (?, ?, ?)",
undef, $u->{'userid'}, $picid, $POST{'userpic'});
push @errors, $clean_err->($u->errstr) if $u->err;
} else { # We should never get here!
push @errors, "User picture uploading failed for unknown reason";
}
# Not a duplicate, so increment $count
$count++;
}
# make it their default pic?
if ($POST{'make_default'}) {
LJ::update_user($u, { defaultpicid => $picid });
$u->{'defaultpicid'} = $picid;
}
# set default keywords?
if ($POST{'keywords'} ne '') {
if ($u->{'dversion'} > 6) {
$sth = $dbcr->prepare("SELECT kwid, picid FROM userpicmap2 WHERE userid=?");
} else {
$sth = $dbh->prepare("SELECT kwid, picid FROM userpicmap WHERE userid=?");
}
$sth->execute($u->{'userid'});
my @exist_kwids;
while (my ($kwid, $picid) = $sth->fetchrow_array) {
$exist_kwids[$kwid] = $picid;
}
my @keywords = split(/\s*,\s*/, $POST{'keywords'});
@keywords = grep { s/^\s+//; s/\s+$//; $_; } @keywords;
my (@bind, @data, @kw_errors);
my $c = 0;
foreach my $kw (@keywords) {
my $kwid = ($u->{'dversion'} > 6) ? LJ::get_keyword_id($u, $kw) : LJ::get_keyword_id($kw);
next unless $kwid; # Houston we have a problem! This should always return an id.
if ($c > $LJ::MAX_USERPIC_KEYWORDS) {
my $ekw = LJ::ehtml($kw);
push @kw_errors, $ekw;
next;
}
if ($exist_kwids[$kwid]) { # Already used on another picture
my $ekw = LJ::ehtml($kw);
push @errors, BML::ml(".error.keywords", {'ekw' => $ekw});
next;
} else { # New keyword, so save it
push @bind, '(?, ?, ?)';
push @data, $u->{'userid'}, $kwid, $picid;
}
$c++;
}
# Let the user know about any we didn't save
if (@kw_errors) {
my $num_words = scalar(@kw_errors);
my $kws = join (", ", @kw_errors);
push @errors, BML::ml(".error.toomanykeywords", {'numwords' => $num_words, 'words' => $kws, 'max' => $LJ::MAX_USERPIC_KEYWORDS});
}
if (@data && @bind) {
my $bind = join(',', @bind);
if ($u->{'dversion'} > 6) {
$u->do("INSERT INTO userpicmap2 (userid, kwid, picid) VALUES $bind",
undef, @data);
} else {
$dbh->do("INSERT INTO userpicmap (userid, kwid, picid) VALUES $bind",
undef, @data);
}
}
}
# set default comments and the url
if ($u->{'dversion'} > 6) {
my (@data, @set);
if ($POST{'comments'} ne '') {
push @set, 'comment=?';
push @data, LJ::text_trim($POST{'comments'}, LJ::BMAX_UPIC_COMMENT, LJ::CMAX_UPIC_COMMENT);
}
if ($POST{'url'} ne '') {
push @set, 'url=?';
push @data, $POST{'url'};
}
if (@set) {
my $set = join(',', @set);
$u->do("UPDATE userpic2 SET $set WHERE userid=? AND picid=?",
undef, @data, $u->{'userid'}, $picid);
}
}
my $memkey = [$u->{'userid'},"upicinf:$u->{'userid'}"];
LJ::MemCache::delete($memkey);
$returl = LJ::CleanHTML::canonical_url($POST{'ret'});
if ($returl) {
my $redir_host = $1 if $returl =~ m#^http://([\.:\w-]+)#i;
return BML::redirect($returl) if $LJ::REDIRECT_ALLOWED{$redir_host};
}
}
# now fall through to edit page and show the updated userpic info
}
if ($fotobilder && $POST{'md5sum'}) {
my $id;
if ($u->{'dversion'} > 6) {
$id = $dbcm->selectrow_array("SELECT picid FROM userpic2 WHERE userid=? " .
"AND md5base64=?", undef, $u->{'userid'}, $POST{'md5sum'});
} else {
$id = $dbh->selectrow_array("SELECT picid FROM userpic WHERE userid=? " .
"AND md5base64=?", undef, $u->{'userid'}, $POST{'md5sum'});
}
$fotobilder = 0 if $id;
}
# show the form to let people edit
$title = "Edit User Pictures";
# Fixme: Make this work with Fotobilder
if (!$fotobilder) {
# authas switcher form
$body .= "<form method='get' action='editpics.bml'>\n";
$body .= LJ::make_authas_select($remote, { 'authas' => $GET{'authas'} }) . "\n";
$body .= "</form>\n\n";
}
if (@errors) {
$body .= LJ::error_list(@errors);
}
if (!$fotobilder) {
my %keywords = ();
my $dbcr = LJ::get_cluster_def_reader($u);
if ($u->{'dversion'} > 6) {
$sth = $dbcr->prepare("SELECT m.picid, k.keyword FROM userpicmap2 m, userkeywords k ".
"WHERE m.userid=? AND m.kwid=k.kwid AND m.userid=k.userid");
} else {
$sth = $dbh->prepare("SELECT m.picid, k.keyword FROM userpicmap m, keywords k ".
"WHERE m.userid=? AND m.kwid=k.kwid");
}
$sth->execute($u->{'userid'});
while (my ($pic, $keyword) = $sth->fetchrow_array) {
LJ::text_out(\$keyword);
push @{$keywords{$pic}}, $keyword;
}
if ($u->{'dversion'} > 6) {
$sth = $dbcr->prepare("SELECT picid, width, height, state, comment " .
"FROM userpic2 WHERE userid=?");
} else {
$sth = $dbh->prepare("SELECT picid, width, height, state " .
"FROM userpic WHERE userid=?");
}
$sth->execute($u->{'userid'});
my @sortedpics;
push @sortedpics, $_ while $_ = $sth->fetchrow_hashref;
# See if they have any without keywords before we output the display table
foreach (@sortedpics) {
unless ($keywords{$_->{'picid'}}) {
my @w;
if (defined $LJ::HELPURL{'upic_keywords'}) {
push @w, BML::ml('.warning.keywords.faq', {'aopts' => "href='$LJ::HELPURL{'upic_keywords'}'"});
} else {
push @w, $ML{'.warning.keywords'};
}
$body .= LJ::warning_list(@w);
last;
}
}
my $piccount = 0;
foreach my $pic (sort { $a->{picid} <=> $b->{picid} } @sortedpics)
{
my $pid = $pic->{'picid'};
if ($piccount++ == 0) {
$body .= "<?h1 $ML{'.curpics'} h1?><?p $ML{'.curpics.desc'} p?>";
$body .= "<?p <strong>". BML::ml('.piclimitstatus', {current => $count, max => $max}) . "</strong> p?>";
$body .= "<form method='post' action='editpics.bml$getextra'>";
$body .= "<table cellpadding='5' border='0' cellspacing='1' " .
"style='margin-left: 30px'>";
}
$body .= "<tr valign='middle'>";
$body .= "<td align='center'><img src='$LJ::USERPIC_ROOT/$pid/$u->{'userid'}' width='$pic->{'width'}' height='$pic->{'height'}'></td>";
$body .= "<td>\n<table>";
my ($dis, $distxt);
{
$body .= "<tr><td align='right'><b><label for='$pid-def'>$ML{'.label.default'}</label></b></td><td> ";
$body .= LJ::html_check({ 'type' => 'radio', 'name' => 'defaultpic', 'value' => $pid,
'selected' => $u->{'defaultpicid'} == $pid,
'disabled' => $pic->{'state'} eq 'I' });
$body .= "&nbsp;&nbsp;&nbsp;<b><label for='$pid-del'>$ML{'.label.delete'}</label></b> ";
$body .= LJ::html_check({ 'type' => 'checkbox', 'name' => "delete_$pid",
'id' => "$pid-del", 'value' => 1 });
if ($pic->{'state'} eq 'I') {
$body .= " &nbsp;<i>[$ML{'userpic.inactive'}]</i> " . LJ::help_icon('userpic_inactive');
}
$body .= "</td></tr>\n";
}
{
my $keywords;
$keywords = join(", ", sort { lc($a) cmp lc($b) } @{$keywords{$pic->{'picid'}}})
if $keywords{$pid};
$body .= "<tr><td align='right'><b><label for='$pid-key'>$ML{'.label.keywords'}</label></b></td><td> ";
$body .= LJ::html_text({'name' => "kw_$pid", 'id' => "$pid-key",
'size' => '30', 'value' => $keywords,
'disabled' => $pic->{'state'} eq 'I' });
$body .= "</td></tr>\n";
if ($u->{'dversion'} > 6) {
$body .= "<tr><td align='right'><b><label for='$pid-com'>$ML{'.label.comment'}</label></b></td><td> ";
$body .= LJ::html_text({ 'name' => "com_$pid", 'id' => "$pid-com",
'size' => '30', 'value' => $pic->{'comment'},
'maxlength' => LJ::CMAX_UPIC_COMMENT,
'disabled' => $pic->{'state'} eq 'I' });
$body .= "</td></tr>\n";
}
}
$body .= "</table>\n</td></tr>\n";
}
if ($piccount) {
$body .= "<tr><td></td><td align=left>&nbsp;<b><label for='nodefpic'>$ML{'.nodefault'}</label></b>&nbsp;";
$body .= LJ::html_check({ 'name' => 'defaultpic',
'value' => 0,
'type' => 'radio',
'selected' => ! $u->{'defaultpicid'},
'raw' => "id='nodefpic'" });
$body .= "</td><td>&nbsp;</td></tr>\n";
$body .= "<tr><td></td><td>&nbsp;" . LJ::html_submit('action:save', $ML{'.btn.save'}) . "</td></tr>\n";
$body .= "</table>";
$body .= "</form>";
} else {
$body .= "<?h1 $ML{'.nopics'} h1?><?p $ML{'.noneupload'} p?>";
}
}
# let users upload more pics
$body .= "<a name='upload'></a>";
if ($count < $max) {
if ($fotobilder) {
$body .= "<?h1 $ML{'.uploadheader.fb'} h1?>\n";
$body .= "<?p " . BML::ml('.uploaddesc.fb', {'aopts' => "href='$LJ::FB_SITEROOT'", 'sitename' => $LJ::FB_SITENAME}) . " p?>\n\n";
} else {
$body .= "<?h1 $ML{'.uploadheader'} h1?>\n";
$body .= "<?p $ML{'.uploaddesc'} p?>\n\n";
$body .= "<ul>\n";
foreach (qw(filesize imagesize fileformat)) {
$body .= "<li>" . $ML{".restriction.$_"} . "</li>\n";
}
# Keywords is a little different
$body .= "<li>";
if (defined $LJ::HELPURL{'upic_keywords'}) {
$body .= BML::ml('.restriction.keywords.faq', {'aopts' => "href='$LJ::HELPURL{'upic_keywords'}'"});
} else {
$body .= $ML{'.restriction.keywords'};
}
$body .= "</li>";
$body .= "</ul>\n";
}
# upload form
$body .= "<?standout \n";
$body .= "<form action='editpics.bml$getextra' method='post' " .
"enctype='multipart/form-data' style='display: inline;'>\n";
$body .= "<table>\n";
if ($fotobilder) {
$body .= "<tr><td colspan='3' align='center'>\n";
$body .= "<img src='$picurl' />";
my $url = LJ::CleanHTML::canonical_url($POST{'url'});
$body .= LJ::html_hidden('src', 'url', 'urlpic', $picurl, 'url', $url, 'ret' => $returl);
} else {
$body .= "<tr><td align='right'>\n";
$body .= LJ::html_check({ 'type' => 'radio', 'name' => 'src', 'id' => 'radio_file',
'value' => 'file', 'selected' => '1',
'accesskey' => $ML{'.fromfile.key'} });
$body .= "</td><td align='right'>";
$body .= "<label for='radio_file'>$ML{'.fromfile'}</label></td>";
$body .= "<td align='left'><input type='file' name='userpic' size='28' /></td></tr>\n";
$body .= "<tr><td align='right'>";
$body .= LJ::html_check({ 'type' => 'radio', 'name' => 'src', 'value' => 'url',
'id' => 'radio_url', 'accesskey' => $ML{'.fromurl.key'} });
$body .= "</td><td align='right'>";
$body .= "<label for='radio_url'>$ML{'.fromurl'}</label></td><td align='left'>";
$body .= LJ::html_text({ 'name' => 'urlpic', 'size' => '40' }) . "</td></tr>\n";
}
$body .= "<tr><td colspan='3' align='center'><hr></td></tr>";
$body .= "<tr><td align='right'>";
$body .= LJ::help_icon('upic_keywords');
$body .= "</td><td align='right'><label for='keywords'>";
$body .= "$ML{'.label.keywords'}</label></td><td align='left'>";
$body .= LJ::html_text({ 'name' => 'keywords', 'size' => '40' });
$body .= "</td></tr>";
if ($u->{'dversion'} > 6) {
$body .= "<tr><td align='right'>";
$body .= LJ::help_icon('upic_comments');
$body .= "</td><td align='right'><label for='comments'>$ML{'.label.comment'}</label></td><td align='left'>";
my $comments = $POST{'comments'} if $fotobilder;
$body .= LJ::html_text({ 'name' => 'comments', 'size' => '40', 'maxlength' => LJ::CMAX_UPIC_COMMENT, 'value', $comments });
$body .= "</td></tr>";
}
$body .= "<tr><td colspan='2'>&nbsp;</td><td align='left'>";
$body .= LJ::html_check({ 'type' => 'checkbox',
'name' => 'make_default',
'id' => 'make_default',
'selected' => '1', 'value' => '1',
'accesskey' => $ML{'.makedefault.key'} });
$body .= "<label for='make_default'>$ML{'.makedefault'}</label></td></tr>\n";
$body .= "<tr><td colspan='3' align='center'><br />" .LJ::html_submit(undef, $ML{'.btn.proceed'}) . "</td></tr>\n";
$body .= "</table>\n</form>\n";
} else {
$body .= "<?standout \n";
$body .= BML::ml(".error.toomanypics3", { 'max' => $max });
}
$body .= " standout?>\n\n";
return;
}
_code?><?page
title=><?_code return $title; _code?>
body=><?_code return $body; _code?>
page?><?_c <LJDEP>
link: htdocs/login.bml, htdocs/allpics.bml
post: htdocs/editpics.bml
</LJDEP> _c?>