("Invalid UTF-8 Input"); } my $remote = LJ::get_remote(); return $err->($ML{'error.noremote'}) unless $remote; my $authas = $GET{'authas'} || $remote->{'user'}; my $memoryu = LJ::get_authas_user($authas); return $err->($ML{'error.invalidauth'}) unless $memoryu; my %secopts = ( 'public' => $ML{'label.security.public'}, 'friends' => $ML{'label.security.friends'}, 'private' => $ML{'label.security.private'}, ); if ($memoryu->{'journaltype'} eq "C") { $secopts{'private'} = $ML{'label.security.maintainers'}; $secopts{'friends'} = $ML{'label.security.members'}; } my $sth; my $journal = $GET{'journal'}; my $ditemid = $GET{'itemid'}+0; # OK. the memories schema is weird and stores *display* itemids in the database. # additionally, we distinguish precluster itemids because they're stored without a userid. # it's too late to fix it in the db, so we just work around it-- # all new memories still get userid+ditemid because we can't change the ditemid/itemid problem, # but old-style itemids get fixed up to userid+ditemid. # *however*, when editing old itemids we need to keep around # the old-style ditemid so we can still edit it. # to keep this all sorted out, we fixup variables like this: # - itemid -- real, new-style itemid # - ditemid -- display itemid (with anum) # - dbitemid -- itemid that is in the database; # usually same as ditemid, but different for old-style itemids. my $dbitemid = $ditemid; my $itemid; my $oldstyle = 0; my $ju; my $jid; my $anum; if ($journal) { $ju = LJ::load_user($journal); $jid = $ju->{'userid'}; $anum = $ditemid % 256; $itemid = int($ditemid / 256); } else { # old-style item url? my $newids = LJ::get_newids('L', $ditemid); if ($newids) { ($jid, $itemid) = @$newids; $ju = LJ::load_userid($jid); $oldstyle = 1; } } unless ($ju && $itemid) { $title = $ML{'Error'}; $body = $ML{'error.nojournal'}; return; } my $dbcr = LJ::get_cluster_reader($ju); my $log = LJ::get_log2_row($ju, $itemid); unless ($log) { $title = $ML{'Error'}; $body = "Error retrieving data to add a memory."; return; } my $subject = LJ::get_logtext2($ju, $itemid)->{$log->{jitemid}}[0]; # if the entry is pre-UTF-8 conversion, the # subject may need conversion into UTF-8 if ($LJ::UNICODE) { my %props = (); LJ::load_log_props2($dbcr, $log->{'journalid'}, [ $itemid ], \%props); if ($props{$itemid}->{'unknown8bit'}) { my $u = LJ::load_userid($log->{'journalid'}); my ($error, $subj); $subj = LJ::text_convert($subject, $u, \$error); $subject = $subj unless $error; } LJ::text_out(\$subject); } # check to see if it already is memorable (thus we're editing, not adding); my $memory = LJ::Memories::get_by_ditemid($memoryu, $oldstyle ? 0 : $jid, $ditemid); if ($oldstyle) { # ditemid was an old-style itemid, so we update it to the new style. $anum = $log->{anum}; $ditemid = $itemid<<8 + $anum; } # get keywords user has used my $exist_kw = LJ::Memories::get_keywords($memoryu); unless ($exist_kw) { $title = $ML{'Error'}; $body = "Error fetching existing keywords."; return; } if ($POST{'mode'} eq "") { my ($des, $keywords); my @all_keywords; my %selected_keyword; @all_keywords = sort values %$exist_kw; if (defined $memory) { $title = $ML{'.title.edit_memory'}; $des = $memory->{'des'}; my $kwids = LJ::Memories::get_keywordids($memoryu, $memory->{memid}) || []; foreach my $kwid (@$kwids) { my $kw = $exist_kw->{$kwid}; next if ($kw eq "*"); if ($keywords) { $keywords .= ", "; } $keywords .= $kw; $selected_keyword{$kw} = 1; } if (!$log || ($jid && $log->{'anum'} != $anum)) { LJ::Memories::delete_by_id($memoryu, $memory->{memid}); LJ::Memories::updated_keywords($memoryu); $title = $ML{'Error'}; $body = $ML{'.error.entry_deleted'}; return; } } elsif (!$log || ($jid && $log->{'anum'} != $anum)) { $title = $ML{'Error'}; $body = $ML{'error.noentry'}; return; } else { $title = $ML{'.title.add_memory'}; # this is a new memory. my $user = LJ::get_username($log->{'journalid'}); my $dt = substr($log->{'eventtime'}, 0, 10); $des = "$dt: $user: $subject"; } # it'd be nice to only show the authas form when adding an entry and not # when editing one, but if user u is logged in and has post p as a memory # already then wants to add it to community c, when u clicks the "add memory" # link on p, u gets the "edit entry" page and they need to be able to switch # to c. $body .= "
\n"; $body .= LJ::make_authas_select($remote, { 'authas' => $GET{'authas'} }) . "\n"; $body .= LJ::html_hidden(journal => $GET{journal}) if $GET{journal}; $body .= LJ::html_hidden(itemid => $GET{itemid}); $body .= "
\n\n"; LJ::text_out(\$des); LJ::text_out(\$keywords); $body .= $ML{'.add_previous'}; my $getextra = "?itemid=$dbitemid"; $getextra .= "&authas=$authas" if $authas ne $remote->{'user'}; # we still need to pass the dbitemid and not the itemid to ourself. $getextra .= "&journal=$journal" unless $oldstyle; $body .= "
"; $body .= LJ::html_hidden(mode => "save"); $body .= ""; $body .= ""; $body .= "\n"; $body .= "
$ML{'.description'}"; $body .= LJ::html_text({name => 'des', value => $des, maxlength => LJ::CMAX_MEMORY, size => 40}); $body .= "
$ML{'.description.text'}
$ML{'.keywords'}"; $body .= LJ::html_text({name => 'keywords', maxlength => LJ::CMAX_KEYWORD, size => 40, value => $keywords}); $body .= "
$ML{'.keywords.text'}
"; if (@all_keywords) { my $size = scalar(@all_keywords); $size = 15 if $size > 15; $body .= "$ML{'.keywords.select'}
"; $body .= LJ::html_select( { name => 'oldkeywords', size => $size, multiple => 1, selected => [ keys %selected_keyword ], noescape => 1 }, map { (LJ::ehtml($_), LJ::ehtml($_)) } @all_keywords); $body .= "
$ML{'.multiple_selections'}"; } else { $body .= "$ML{'.keywords.example'}"; } $body .= "
$ML{'.security'}"; $body .= LJ::html_select({name => 'security', selected => defined $memory ? $memory->{'security'} : undef}, map { ($_, $secopts{$_}) } qw(public friends private)); if ($memoryu->{'journaltype'} eq "C") { $body .= "
$ML{'.whocansee.comm'}
\n"; } else { $body .= "
$ML{'.whocansee'}
\n"; } $body .= LJ::html_submit(undef, $ML{'.form.submit'}); $body .= LJ::html_submit(undef, $ML{'.form.reset'}, {type => 'reset'}) if defined $memory; $body .= "
"; return; } if ($POST{'mode'} eq "save") { my $dbh = LJ::get_db_writer(); if (! $POST{'des'}) { # then we're deleting. if (defined $memory) { LJ::Memories::delete_by_id($memoryu, $memory->{memid}); LJ::Memories::updated_keywords($memoryu); $title = $ML{'.title.deleted'}; $body = " $memory->{'des'} }) . "p?>"; return; } else { $title = $ML{'Error'}; $body = ""; return; } } #### we're inserting/replacing now into memories my @keywords; { my %kws; foreach (split(/\s*,\s*/, $POST{'keywords'})) { $kws{$_} = 1; } # oldkeywords were split at the beginning foreach (@{$POST{'oldkeywords'}}) { $kws{$_} = 1; } @keywords = keys %kws; } if (scalar(@keywords) > 5) { $title = $ML{'Error'}; $body = ""; return; } @keywords = grep { $_ } map { s/\s\s+/ /g; LJ::trim($_); } @keywords; push @keywords, "*" unless (@keywords); my @kwid; my $needflush = 0; foreach my $kw (@keywords) { if (length($kw) > 40) { $title = $ML{'Error'}; $body = " LJ::ehtml($kw) }) . "p?>"; return; } my $kwid = LJ::get_keyword_id($memoryu, $kw); $needflush = 1 unless defined $exist_kw->{$kwid}; push @kwid, $kwid; } unless (exists $secopts{$POST{'security'}}) { $title = $ML{'Error'}; $body = $ML{'.error.invalid_security'}; return; } my $des = LJ::text_trim($POST{'des'}, LJ::BMAX_MEMORY, LJ::CMAX_MEMORY); my $sec = $POST{'security'}; # handle edits by deleting the old memory and recreating LJ::Memories::delete_by_id($memoryu, $memory->{memid}) if defined $memory; LJ::Memories::create($memoryu, { journalid => $jid, ditemid => $ditemid, des => $des, security => $sec, }, \@kwid); LJ::Memories::updated_keywords($memoryu) if $needflush; $title = $ML{'.title.added'}; $body = "{user}, $itemid, $anum); $body .= BML::ml('.body.added.body2', {'aopts' => "href='$backlink'"}); $body .= " p?>"; return; } $title = $ML{'Error'}; $body = $ML{'error.unknownmode'}; return; _code?> body=> page?> link: htdocs/login.bml post: htdocs/tools/memadd.bml _c?>