("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'}, ); 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 = $dbcr->selectrow_hashref("SELECT l.journalid AS 'ownerid', l.posterid, l.eventtime, ls.subject, l.security, l.allowmask, UNIX_TIMESTAMP()-UNIX_TIMESTAMP(l.logtime) AS 'secondsold', l.anum FROM log2 l, logtext2 ls WHERE ls.journalid=$jid AND l.journalid=$jid AND ls.jitemid=l.jitemid AND l.jitemid=$itemid"); if ($oldstyle) { # ditemid was an old-style itemid, so we update it to the new style. $anum = $log->{anum}; $ditemid = $itemid<<8 + $anum; } # 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->{'ownerid'}, [ $itemid ], \%props); if ($props{$itemid}->{'unknown8bit'}) { my $u = LJ::load_userid($log->{'ownerid'}); my ($error, $subj); $subj = LJ::text_convert($log->{'subject'}, $u, \$error); $log->{'subject'} = $subj unless $error; } LJ::text_out(\$log->{'subject'}); } # check to see if it already is memorable (thus we're editing, not adding); $sth = $dbr->prepare("SELECT memid, des, security FROM memorable WHERE ". "userid=? AND journalid=? AND jitemid=?"); $sth->execute($memoryu->{userid}, $oldstyle ? 0 : $jid, $dbitemid); my $memory = $sth->fetchrow_hashref; if ($POST{'mode'} eq "") { my ($des, $keywords); my @all_keywords; my %selected_keyword; $sth = $dbr->prepare("SELECT DISTINCT k.keyword ". "FROM keywords k, memkeyword mk, memorable m ". "WHERE k.kwid=mk.kwid AND mk.memid=m.memid AND m.userid=?"); $sth->execute($memoryu->{userid}); while (my ($kw) = $sth->fetchrow_array) { push @all_keywords, $kw; } @all_keywords = sort @all_keywords; if (defined $memory) { $title = $ML{'.title.edit_memory'}; $des = $memory->{'des'}; $sth = $dbr->prepare("SELECT k.keyword FROM keywords k, memkeyword mk ". "WHERE mk.kwid=k.kwid AND mk.memid=?"); $sth->execute($memory->{memid}); while (my ($kw) = $sth->fetchrow_array) { next if ($kw eq "*"); if ($keywords) { $keywords .= ", "; } $keywords .= $kw; $selected_keyword{$kw} = 1; } if (!$log || ($jid && $log->{'anum'} != $anum)) { my $dbh = LJ::get_db_writer(); $dbh->do("DELETE FROM memorable WHERE memid=$memory->{'memid'}"); $dbh->do("DELETE FROM memkeyword WHERE memid=$memory->{'memid'}"); $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->{'ownerid'}); my $dt = substr($log->{'eventtime'}, 0, 10); $des = "$dt: $user: $log->{'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\n"; $des = LJ::ehtml($des); $keywords = LJ::ehtml($keywords); LJ::text_out(\$des); LJ::text_out(\$keywords); $body .= $ML{'.add_previous'}; my $getextra = "?"; $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; $getextra .= "itemid=$dbitemid&"; chop $getextra; $body .= ""; return; } if ($POST{'mode'} eq "save") { my $dbh = LJ::get_db_writer(); if (! $POST{'des'}) { # then we're deleting. if (defined $memory) { $dbh->do("DELETE FROM memorable WHERE memid=$memory->{'memid'}"); $dbh->do("DELETE FROM memkeyword WHERE memid=$memory->{'memid'}"); $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; foreach my $kw (@keywords) { if (length($kw) > 40) { $title = $ML{'Error'}; $body = " $kw }) . "p?>"; return; } my $kwid = LJ::get_keyword_id($kw); 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'}; ## this is easiest... just delete it, then add it again. if (defined $memory) { $dbh->do("DELETE FROM memkeyword WHERE memid=$memory->{'memid'}"); } my $memid; if (defined $memory) { $memid = $memory->{'memid'}; $sth = $dbh->prepare("UPDATE memorable SET des=?, security=? WHERE memid=?"); $sth->execute($des, $sec, $memid); } else { $sth = $dbh->prepare("INSERT INTO memorable (memid, userid, journalid, jitemid, des, security) ". "VALUES (NULL, ?, ?, ?, ?, ?)"); $sth->execute($memoryu->{userid}, $jid, $dbitemid, $des, $sec); $memid = $dbh->{'mysql_insertid'}; } if (@kwid) { my $sql = "INSERT IGNORE INTO memkeyword (memid, kwid) VALUES "; # IGNORE exists so no error is logged in mysql replication binlog (bad in 3.23.x) $sql .= join(",", map { "($memid,$_)" } @kwid); $dbh->do($sql); } $title = $ML{'.title.added'}; $body = ""; return; } $title = $ML{'Error'}; $body = $ML{'error.unknownmode'}; return; _code?> body<= <=body page?> link: htdocs/login.bml post: htdocs/tools/memadd.bml _c?>