378 lines
14 KiB
Perl
Executable File
378 lines
14 KiB
Perl
Executable File
#!/usr/bin/perl
|
|
#
|
|
|
|
use strict;
|
|
package LJ::S2;
|
|
|
|
sub EntryPage
|
|
{
|
|
my ($u, $remote, $opts) = @_;
|
|
|
|
my $get = $opts->{'getargs'};
|
|
|
|
my $p = Page($u, $opts);
|
|
$p->{'_type'} = "EntryPage";
|
|
$p->{'view'} = "entry";
|
|
$p->{'comment_pages'} = undef;
|
|
$p->{'comments'} = [];
|
|
$p->{'comment_pages'} = undef;
|
|
|
|
# setup viewall options
|
|
my ($viewall, $viewsome) = (0, 0);
|
|
if ($get->{viewall} && LJ::check_priv($remote, 'canview')) {
|
|
# we don't log here, as we don't know what entry we're viewing yet. the logging
|
|
# is done when we call EntryPage_entry below.
|
|
$viewall = LJ::check_priv($remote, 'canview', '*');
|
|
$viewsome = $viewall || LJ::check_priv($remote, 'canview', 'suspended');
|
|
}
|
|
|
|
my ($entry, $s2entry) = EntryPage_entry($u, $remote, $opts);
|
|
return if $opts->{'suspendeduser'};
|
|
return if $opts->{'handler_return'};
|
|
|
|
$p->{'multiform_on'} = $remote &&
|
|
($remote->{'userid'} == $u->{'userid'} ||
|
|
$remote->{'userid'} == $entry->{'posterid'} ||
|
|
LJ::can_manage($remote, $u));
|
|
|
|
my $itemid = $entry->{'itemid'};
|
|
my $ditemid = $entry->{'itemid'} * 256 + $entry->{'anum'};
|
|
my $permalink = LJ::journal_base($u) . "/$ditemid.html";
|
|
my $stylemine = $get->{'style'} eq "mine" ? "style=mine" : "";
|
|
|
|
if ($u->{'journaltype'} eq "R" && $u->{'renamedto'} ne "") {
|
|
$opts->{'redir'} = LJ::journal_base($u->{'renamedto'}, $opts->{'vhost'}) .
|
|
"/$ditemid.html" . $opts->{'pathextra'};
|
|
return 1;
|
|
}
|
|
|
|
if ($u->{'opt_blockrobots'}) {
|
|
$p->{'head_content'} .= LJ::robot_meta_tags();
|
|
}
|
|
if ($LJ::UNICODE) {
|
|
$p->{'head_content'} .= '<meta http-equiv="Content-Type" content="text/html; charset='.$opts->{'saycharset'}."\" />\n";
|
|
}
|
|
|
|
$p->{'entry'} = $s2entry;
|
|
|
|
# add the comments
|
|
my %userpic;
|
|
my %user;
|
|
my $copts = {
|
|
'thread' => ($get->{'thread'} >> 8),
|
|
'page' => $get->{'page'},
|
|
'view' => $get->{'view'},
|
|
'userpicref' => \%userpic,
|
|
'userref' => \%user,
|
|
# user object is cached from call just made in EntryPage_entry
|
|
'up' => LJ::load_user($s2entry->{'poster'}->{'username'}),
|
|
'viewall' => $viewall,
|
|
};
|
|
|
|
my $userlite_journal = UserLite($u);
|
|
|
|
my @comments = LJ::Talk::load_comments($u, $remote, "L", $itemid, $copts);
|
|
|
|
my $pics = LJ::Talk::get_subjecticons()->{'pic'}; # hashref of imgname => { w, h, img }
|
|
my $convert_comments = sub {
|
|
my ($self, $destlist, $srclist, $depth) = @_;
|
|
|
|
foreach my $com (@$srclist) {
|
|
my $dtalkid = $com->{'talkid'} * 256 + $entry->{'anum'};
|
|
my $text = $com->{'body'};
|
|
if ($get->{'nohtml'}) {
|
|
# quote all non-LJ tags
|
|
$text =~ s{<(?!/?lj)(.*?)>} {<$1>}gi;
|
|
}
|
|
LJ::CleanHTML::clean_comment(\$text, { 'preformatted' => $com->{'props'}->{'opt_preformatted'},
|
|
'anon_comment' => !$com->{posterid}});
|
|
|
|
# local time in mysql format to gmtime
|
|
my $datetime = DateTime_unix(LJ::mysqldate_to_time($com->{'datepost'}));
|
|
|
|
my $subject_icon = undef;
|
|
if (my $si = $com->{'props'}->{'subjecticon'}) {
|
|
my $pic = $pics->{$si};
|
|
$subject_icon = Image("$LJ::IMGPREFIX/talk/$pic->{'img'}",
|
|
$pic->{'w'}, $pic->{'h'}) if $pic;
|
|
}
|
|
|
|
my $comment_userpic;
|
|
if (my $pic = $userpic{$com->{'picid'}}) {
|
|
$comment_userpic = Image("$LJ::USERPIC_ROOT/$com->{'picid'}/$pic->{'userid'}",
|
|
$pic->{'width'}, $pic->{'height'});
|
|
}
|
|
|
|
my $reply_url = LJ::Talk::talkargs($permalink, "replyto=$dtalkid", $stylemine);
|
|
|
|
my $par_url;
|
|
if ($com->{'parenttalkid'}) {
|
|
my $dparent = ($com->{'parenttalkid'} << 8) + $entry->{'anum'};
|
|
$par_url = LJ::Talk::talkargs($permalink, "thread=$dparent", $stylemine) . "#t$dparent";
|
|
}
|
|
|
|
my $poster;
|
|
if ($com->{'posterid'}) {
|
|
if ($user{$com->{'posterid'}}) {
|
|
$poster = UserLite($user{$com->{'posterid'}});
|
|
} else {
|
|
$poster = {
|
|
'_type' => 'UserLite',
|
|
'username' => $com->{'userpost'},
|
|
'name' => $com->{'userpost'}, # we don't have this, so fake it
|
|
'journal_type' => 'P', # fake too, but only people can post, so correct
|
|
};
|
|
}
|
|
}
|
|
|
|
my $s2com = {
|
|
'_type' => 'Comment',
|
|
'journal' => $userlite_journal,
|
|
'metadata' => {
|
|
'picture_keyword' => $com->{'props'}->{'picture_keyword'},
|
|
},
|
|
'permalink_url' => "$permalink?thread=$dtalkid#t$dtalkid",
|
|
'reply_url' => $reply_url,
|
|
'poster' => $poster,
|
|
'replies' => [],
|
|
'subject' => LJ::ehtml($com->{'subject'}),
|
|
'subject_icon' => $subject_icon,
|
|
'talkid' => $dtalkid,
|
|
'text' => $text,
|
|
'userpic' => $comment_userpic,
|
|
'time' => $datetime,
|
|
'tags' => [],
|
|
'full' => $com->{'_loaded'} ? 1 : 0,
|
|
'depth' => $depth,
|
|
'parent_url' => $par_url,
|
|
'screened' => $com->{'state'} eq "S" ? 1 : 0,
|
|
'frozen' => $com->{'state'} eq "F" ? 1 : 0,
|
|
'link_keyseq' => [ 'delete_comment' ],
|
|
'anchor' => "t$dtalkid",
|
|
'dom_id' => "ljcmt$dtalkid",
|
|
};
|
|
|
|
# don't show info from suspended users
|
|
# FIXME: ideally the load_comments should only return these
|
|
# items if there are children, otherwise they should be hidden entirely
|
|
my $pu = $com->{'posterid'} ? $user{$com->{'posterid'}} : undef;
|
|
if ($pu && $pu->{'statusvis'} eq "S" && !$viewsome) {
|
|
$s2com->{'text'} = "";
|
|
$s2com->{'subject'} = "";
|
|
$s2com->{'full'} = 0;
|
|
$s2com->{'subject_icon'} = undef;
|
|
$s2com->{'userpic'} = undef;
|
|
}
|
|
|
|
# Conditionally add more links to the keyseq
|
|
my $link_keyseq = $s2com->{'link_keyseq'};
|
|
push @$link_keyseq, $s2com->{'screened'} ? 'unscreen_comment' : 'screen_comment';
|
|
push @$link_keyseq, $s2com->{'frozen'} ? 'unfreeze_thread' : 'freeze_thread';
|
|
|
|
if (@{$com->{'children'}}) {
|
|
$s2com->{'thread_url'} = LJ::Talk::talkargs($permalink, "thread=$dtalkid", $stylemine) . "#t$dtalkid";
|
|
}
|
|
|
|
# add the poster_ip metadata if remote user has
|
|
# access to see it.
|
|
$s2com->{'metadata'}->{'poster_ip'} = $com->{'props'}->{'poster_ip'} if
|
|
($com->{'props'}->{'poster_ip'} && $remote &&
|
|
($remote->{'userid'} == $entry->{'posterid'} ||
|
|
LJ::can_manage($remote, $u) || $viewall));
|
|
|
|
push @$destlist, $s2com;
|
|
|
|
$self->($self, $s2com->{'replies'}, $com->{'children'}, $depth+1);
|
|
}
|
|
};
|
|
$p->{'comments'} = [];
|
|
$convert_comments->($convert_comments, $p->{'comments'}, \@comments, 1);
|
|
|
|
# prepare the javascript data structure to put in the top of the page
|
|
# if the remote user is a manager of the comments
|
|
my $do_commentmanage_js = $p->{'multiform_on'};
|
|
if ($LJ::DISABLED{'commentmanage'}) {
|
|
if (ref $LJ::DISABLED{'commentmanage'} eq "CODE") {
|
|
$do_commentmanage_js = $LJ::DISABLED{'commentmanage'}->($remote);
|
|
} else {
|
|
$do_commentmanage_js = 0;
|
|
}
|
|
}
|
|
|
|
if ($do_commentmanage_js) {
|
|
my $js = "<script>\n// don't crawl this. read http://www.livejournal.com/developer/exporting.bml\n";
|
|
$js .= "var LJ_cmtinfo = {\n";
|
|
my $canAdmin = LJ::can_manage($remote, $u) ? 1 : 0;
|
|
$js .= "\tjournal: '$u->{user}',\n";
|
|
$js .= "\tcanAdmin: $canAdmin,\n";
|
|
$js .= "\tremote: '$remote->{user}',\n" if $remote;
|
|
my $recurse = sub {
|
|
my ($self, $array) = @_;
|
|
foreach my $i (@$array) {
|
|
my $has_threads = scalar @{$i->{'replies'}};
|
|
my $poster = $i->{'poster'} ? $i->{'poster'}{'username'} : "";
|
|
my $child_ids = join(',', map { $_->{'talkid'} } @{$i->{'replies'}});
|
|
$js .= "\t$i->{'talkid'}: { rc: [$child_ids], u: '$poster' },\n";
|
|
$self->($self, $i->{'replies'}) if $has_threads;
|
|
}
|
|
};
|
|
$recurse->($recurse, $p->{'comments'});
|
|
chop $js; chop $js; # remove final ",\n". stupid javascript.
|
|
$js .= "\n};\n" .
|
|
"var LJVAR;\n".
|
|
"if (!LJVAR) LJVAR = new Object();\n".
|
|
"LJVAR.imgprefix = \"$LJ::IMGPREFIX\";\n".
|
|
"</script>\n";
|
|
$p->{'head_content'} .= $js;
|
|
$p->{'head_content'} .= "<script src='$LJ::SITEROOT/js/commentmanage.js'></script>\n";
|
|
|
|
}
|
|
|
|
|
|
$p->{'viewing_thread'} = $get->{'thread'} ? 1 : 0;
|
|
|
|
# default values if there were no comments, because
|
|
# LJ::Talk::load_comments() doesn't provide them.
|
|
if ($copts->{'out_error'} eq 'noposts') {
|
|
$copts->{'out_pages'} = $copts->{'out_page'} = 1;
|
|
$copts->{'out_items'} = 0;
|
|
$copts->{'out_itemfirst'} = $copts->{'out_itemlast'} = undef;
|
|
}
|
|
|
|
$p->{'comment_pages'} = ItemRange({
|
|
'all_subitems_displayed' => ($copts->{'out_pages'} == 1),
|
|
'current' => $copts->{'out_page'},
|
|
'from_subitem' => $copts->{'out_itemfirst'},
|
|
'num_subitems_displayed' => scalar @comments,
|
|
'to_subitem' => $copts->{'out_itemlast'},
|
|
'total' => $copts->{'out_pages'},
|
|
'total_subitems' => $copts->{'out_items'},
|
|
'_url_of' => sub { return "$permalink?page=" . int($_[0]) .
|
|
($stylemine ? "&$stylemine" : ''); },
|
|
});
|
|
|
|
return $p;
|
|
}
|
|
|
|
sub EntryPage_entry
|
|
{
|
|
my ($u, $remote, $opts) = @_;
|
|
|
|
my $get = $opts->{'getargs'};
|
|
|
|
my $r = $opts->{'r'};
|
|
my $uri = $r->uri;
|
|
|
|
my ($ditemid, $itemid, $anum);
|
|
unless ($uri =~ /(\d+)\.html/) {
|
|
$opts->{'handler_return'} = 404;
|
|
return;
|
|
}
|
|
|
|
$ditemid = $1;
|
|
$anum = $ditemid % 256;
|
|
$itemid = $ditemid >> 8;
|
|
|
|
my $entry = LJ::Talk::get_journal_item($u, $itemid);
|
|
unless ($entry && $entry->{'anum'} == $anum) {
|
|
$opts->{'handler_return'} = 404;
|
|
return;
|
|
}
|
|
|
|
my $userlite_journal = UserLite($u);
|
|
my $userlite_poster = $userlite_journal;
|
|
my $pu = $u;
|
|
if ($entry->{'posterid'} != $entry->{'ownerid'}) {
|
|
$pu = LJ::load_userid($entry->{'posterid'});
|
|
$userlite_poster = UserLite($pu);
|
|
}
|
|
|
|
# do they have the viewall priv?
|
|
my $viewall = 0;
|
|
my $viewsome = 0;
|
|
if ($get->{'viewall'} && LJ::check_priv($remote, "canview")) {
|
|
LJ::statushistory_add($u->{'userid'}, $remote->{'userid'},
|
|
"viewall", "entry: $u->{'user'}, itemid: $itemid, statusvis: $u->{'statusvis'}");
|
|
$viewall = LJ::check_priv($remote, 'canview', '*');
|
|
$viewsome = $viewall || LJ::check_priv($remote, 'canview', 'suspended');
|
|
}
|
|
|
|
# check using normal rules
|
|
unless (LJ::can_view($remote, $entry) || $viewall) {
|
|
$opts->{'handler_return'} = 403;
|
|
return;
|
|
}
|
|
if (($pu && $pu->{'statusvis'} eq 'S') && !$viewsome) {
|
|
$opts->{'suspendeduser'} = 1;
|
|
return;
|
|
}
|
|
|
|
my $replycount = $entry->{'props'}->{'replycount'};
|
|
my $nc = "";
|
|
$nc .= "nc=$replycount" if $replycount && $remote && $remote->{'opt_nctalklinks'};
|
|
|
|
my $stylemine = $get->{'style'} eq "mine" ? "style=mine" : "";
|
|
|
|
my $userpic = Image_userpic($pu, 0, $entry->{'props'}->{'picture_keyword'});
|
|
|
|
my $permalink = LJ::journal_base($u) . "/$ditemid.html";
|
|
my $readurl = LJ::Talk::talkargs($permalink, $nc, $stylemine);
|
|
my $posturl = LJ::Talk::talkargs($permalink, "mode=reply", $stylemine);
|
|
|
|
my $comments = CommentInfo({
|
|
'read_url' => $readurl,
|
|
'post_url' => $posturl,
|
|
'count' => $replycount,
|
|
'maxcomments' => ($replycount >= LJ::get_cap($u, 'maxcomments')) ? 1 : 0,
|
|
'enabled' => ($u->{'opt_showtalklinks'} eq "Y" && !
|
|
$entry->{'props'}->{'opt_nocomments'}) ? 1 : 0,
|
|
'screened' => ($entry->{'props'}->{'hasscreened'} && $remote &&
|
|
($remote->{'user'} eq $u->{'user'} || LJ::can_manage($remote, $u))) ? 1 : 0,
|
|
});
|
|
|
|
# format it
|
|
if ($opts->{'getargs'}->{'nohtml'}) {
|
|
# quote all non-LJ tags
|
|
$entry->{'subject'} =~ s{<(?!/?lj)(.*?)>} {<$1>}gi;
|
|
$entry->{'event'} =~ s{<(?!/?lj)(.*?)>} {<$1>}gi;
|
|
}
|
|
my $raw_subj = $entry->{'subject'};
|
|
LJ::CleanHTML::clean_subject(\$entry->{'subject'});
|
|
LJ::CleanHTML::clean_event(\$entry->{'event'}, $entry->{'props'}->{'opt_preformatted'});
|
|
LJ::expand_embedded($u, $ditemid, $remote, \$entry->{'event'});
|
|
|
|
# load tags
|
|
my @taglist;
|
|
my $tags = LJ::Tags::get_logtags($u, $itemid);
|
|
while (my ($kwid, $kw) = each %{$tags->{$itemid} || {}}) {
|
|
push @taglist, Tag($u, $kwid => $kw);
|
|
}
|
|
@taglist = sort { $a->{name} cmp $b->{name} } @taglist;
|
|
|
|
if ($opts->{enable_tags_compatibility} && @taglist) {
|
|
$entry->{event} .= LJ::S2::get_tags_text($opts->{ctx}, \@taglist);
|
|
}
|
|
|
|
my $s2entry = Entry($u, {
|
|
'_rawsubject' => $raw_subj,
|
|
'subject' => $entry->{'subject'},
|
|
'text' => $entry->{'event'},
|
|
'dateparts' => $entry->{'alldatepart'},
|
|
'security' => $entry->{'security'},
|
|
'props' => $entry->{'props'},
|
|
'itemid' => $ditemid,
|
|
'comments' => $comments,
|
|
'journal' => $userlite_journal,
|
|
'poster' => $userlite_poster,
|
|
'tags' => \@taglist,
|
|
'new_day' => 0,
|
|
'end_day' => 0,
|
|
'userpic' => $userpic,
|
|
'permalink_url' => $permalink,
|
|
});
|
|
|
|
return ($entry, $s2entry);
|
|
}
|
|
|
|
1;
|