{'head'} : \$r_head; my $title = $_[1] ? \$_[1]->{'title'} : \$r_title; my $bodyopts = $_[1] ? \$_[1]->{'bodyopts'} : \$r_bodyopts; return LJ::server_down_html() if $LJ::SERVER_DOWN; my $pics = LJ::Talk::get_subjecticons(); ## workaround mail client bug when don't understand quoted-printable. ## Only correct 'journal' if 'itemid' was also broken, to avoid the ## unlikely clash with a journal name. if ($GET{'itemid'} =~ s/^3D//) { $GET{'journal'} =~ s/^3D//; $GET{'thread'} =~ s/^3D//; } my $r = Apache->request; $r->notes("codepath" => "bml.talkread"); my $uri = BML::get_uri(); my $itemid; if ($uri =~ m!/(\d+)\.html$!) { $itemid = $1; $GET{'itemid'} = $itemid; $GET{'journal'} = $r->notes("_journal"); BML::set_language_scope("/talkread.bml"); } # pre-load common strings for little speed and less typing later # (we're doing this *after* set_language_scope is called, because # two below are relative strings) my %T = qw(postcomments talk.commentpost readcomments talk.commentsread parent talk.parentlink thread talk.threadlink replythis talk.replytothis frozen talk.frozen link talk.commentpermlink deleted .subjectdeleted nosubject .nosubject ); foreach (keys %T) { $T{$_} = $ML{$T{$_}}; } my $init = LJ::Talk::init(\%GET); my $u = $init->{'journalu'}; return $ML{'talk.error.nojournal'} unless $u; my $ditemid = $init->{'ditemid'}+0; # redirect if account was renamed if ($u->{'journaltype'} eq "R") { LJ::load_user_props($u, "renamedto"); if ($u->{'renamedto'} ne "") { return BML::redirect(LJ::journal_base($u->{'renamedto'}) . "/$ditemid.html"); } } # now check for init->error, since we know the account wasn't renamed return "{'error'} p?>" if $init->{'error'}; LJ::load_user_props($u, "opt_blockrobots") if $u->{'statusvis'} eq 'V'; if ($u->{'statusvis'} ne 'V' || $u->{'opt_blockrobots'}) { $$head .= LJ::robot_meta_tags(); } $r->notes("journalid" => $u->{'userid'}); my $thread = $init->{'thread'}; my $dthread = $init->{'dthread'}; $itemid = $init->{'itemid'}+0; my $stylemine = $init->{'style'} eq "mine" ? "style=mine" : ""; ## load the journal item my $item = LJ::Talk::get_journal_item($u, $itemid); ################################################## if ($init->{'oldurl'} && $item) { $init->{'anum'} = $item->{'anum'}; $init->{'ditemid'} = $init->{'itemid'}*256 + $item->{'anum'}; $ditemid = $init->{'ditemid'} + 0; } unless ($item && $item->{'anum'} == $init->{'anum'}) { BML::set_status(404); # 404 Not found return ""; } my $jarg = "journal=$u->{'user'}&"; my $jargent ="journal=$u->{'user'}&"; my $talkurl = LJ::journal_base($u) . "/$ditemid.html"; my $ret = ""; my $props = $item->{'props'}; my $nocomments = $u->{'opt_showtalklinks'} eq "N" ? 1 : $props->{'opt_nocomments'}; my $remote = LJ::get_remote(); ### load users my ($up); # $up = user posted journal item LJ::load_userids_multiple([ $item->{'posterid'} => \$up, ], [ $u ]); LJ::text_out(\$u->{'name'}); # set viewall/viewsome 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: $item->{'itemid'}, statusvis: $u->{'statusvis'}"); $viewall = LJ::check_priv($remote, 'canview', '*'); $viewsome = $viewall || LJ::check_priv($remote, 'canview', 'suspended'); } # check for deleted/suspended/security unless ($viewsome) { # check suspended if ($u->{'statusvis'} eq "S" || $up->{'statusvis'} eq "S") { BML::set_status(403); # 403 Forbidden return ""; } # check deleted if ($u->{'statusvis'} eq "D") { BML::set_status(404); # 404 Not found return ""; } } unless ($viewall) { #### Check security before viewing this post my $errtxt; unless (LJ::Talk::check_viewable($remote, $item, \%GET, \$errtxt)) { BML::set_status(403); # 403 Forbidden return $errtxt; } } ### check If-Modified-Since my $lastmod = $props->{'commentalter'}; my $revisiontime = $props->{' revtime'}; $lastmod = $revisiontime if $revisiontime && $revisiontime > $lastmod; my $ims = $r->header_in("If-Modified-Since"); if ($ims) { my $theirtime = LJ::http_to_time($ims); if ($theirtime >= $lastmod && !$remote) { # only for anonymous: logged users will be checked by Etag for exact match BML::set_status(304); # 304 Not Modified return ""; } } $r->set_last_modified($lastmod); # See if we should inject QuickReply javascript LJ::load_user_props($remote, "opt_no_quickreply"); if (($remote && !$remote->{'opt_no_quickreply'}) && !$nocomments) { $$head .= $LJ::COMMON_CODE{'quickreply'}; $$bodyopts .= 'onload="restore_entry();" onunload="save_entry();"'; } my $showmultiform = $remote && ($remote->{'user'} eq $u->{'user'} || $remote->{'user'} eq $up->{'user'} || LJ::can_manage($remote, $u)); my $multiform_selects = 0; # are there select boxes? don't show form if not. my $event = $item->{'event'}; LJ::CleanHTML::clean_event(\$event, $props->{'opt_preformatted'}); LJ::expand_embedded($u, $ditemid, $remote, \$event); BML::ebml(\$event); # make the title { my $subject = $item->{'subject'} || $event; LJ::CleanHTML::clean_subject_all(\$subject); $subject =~ s/\n.*//s; # yes, the 3 param to text_trim is chars, and length returns bytes, but # it works, as bytes >= chars: $subject = LJ::text_trim($subject, 0, length($item->{'subject'}) || 40); $$title = "$u->{'user'}: $subject"; } $ret .= "

"; $ret .= ""; my $picid = LJ::get_picid_from_keyword($up, $props->{'picture_keyword'}); my %userpics; if ($picid) { LJ::load_userpics(\%userpics, [ $u, $picid ]); my $alt = $up->{'name'}; if ($props->{'picture_keyword'}) { $alt .= ": $props->{'picture_keyword'}"; } LJ::text_out(\$alt); $alt = LJ::ehtml($alt); $ret .= ""; } $ret .= "
"; my $is_shared = $u->{'journaltype'} eq 'C' || $u->{'journaltype'} eq 'S'; if ($is_shared) { $ret .= BML::ml("talk.somebodywrote_comm", { 'realname' => LJ::ehtml($up->{'name'}), 'userlink' => LJ::ljuser($up), 'commlink' => LJ::ljuser($u) }); } else { $ret .= BML::ml("talk.somebodywrote", { 'realname' => LJ::ehtml($up->{'name'}), 'userlink' => LJ::ljuser($up) }); } my $etime = $item->{'eventtime'}; $etime =~ s!(\d\d\d\d)-(\d\d)-(\d\d)!LJ::date_to_view_links($u, $&)!e; $ret .= "
@ $etime"; $ret .= "
"; ## standout bar $ret .= LJ::Talk::link_bar({ 'u' => $u, 'up' => $up, 'headref' => $head, 'remote' => $remote, 'itemid' => $ditemid, }); ## dump the log entry, unless we're browsing a thread. my %current; if ($props->{'current_mood'} || $props->{'current_moodid'}) { $current{'Mood'} = LJ::current_mood_str($up->{'moodthemeid'}, $props->{'current_moodid'}, $props->{'current_mood'}); } if ($props->{'current_music'}) { $current{'Music'} = LJ::current_music_str($props->{'current_music'}); } # my $tags = $props->{'tags'}; # if ($tags && values %$tags) { # my $base = LJ::journal_base($u); # $current{'Tags'} = join(', ', # map { "" . LJ::ehtml($_) . "" } # sort values %$tags} # ); # } my $logtags = LJ::Tags::get_logtags($u, $itemid); if ($logtags->{$itemid} && %{$logtags->{$itemid}}) { my $base = LJ::journal_base($u); $current{'Tags'} = join(', ', map { "" . LJ::ehtml($_) . "" } sort values %{$logtags->{$itemid}} ); } $ret .= "

"; if (%current) { $ret .= "\n"; foreach (sort keys %current) { my $curkey = "talk.curname_" . $_; my $curname = BML::ml($curkey); $curname = "Current $_:" unless $curname; $ret .= "\n"; } $ret .= "
$curname$current{$_}

\n"; } ### security indicator my $sec = ""; if ($item->{'security'} eq "private") { $sec = BML::fill_template("securityprivate"); } elsif ($item->{'security'} eq "usemask") { $sec = BML::fill_template("securityprotected"); } $sec .= "
\n" unless $sec eq "" or $item->{'subject'}; $ret .= $sec; ### if ($item->{'subject'}) { my $subject = $item->{'subject'}; LJ::CleanHTML::clean_subject(\$subject); BML::ebml(\$subject); $ret .= "$subject
\n"; } $ret .= $event; $ret .= "

"; $ret .= "

"; my %user; my $opts = { 'thread' => $thread, 'page' => $GET{'page'}, 'view' => $GET{'view'}, 'userpicref' => \%userpics, 'userref' => \%user, 'up' => $up, 'viewall' => $viewall, # Okuklivanie tredov - daem upravlenie pol'zovatelyu - 'page_size' => $GET{'page_size'}, 'max_subjects' => $GET{'max_subjects'}, 'threading_point' => $GET{'threading_point'}, 'uncollapse' => $GET{'uncollapse'}, }; my @comments = LJ::Talk::load_comments($u, $remote, "L", $itemid, $opts); return $ML{'error.nodbmaintenance'} if $opts->{'out_error'} eq "nodb"; my $page = $opts->{'out_page'}; my $pages = $opts->{'out_pages'}; ########## make the navcrap my $navcrap; $navcrap .= ""; if ($pages > 1) { $navcrap .= ""; $navcrap .= ""; my $left = "<<"; if ($page > 1) { $left = " $page-1 }) . "#comments'>$left"; } my $right = ">>"; if ($page < $pages) { $right = " $page+1 }) . "#comments'>$right"; } $navcrap .= ""; $navcrap .= "
"; $navcrap .= BML::ml('ljlib.pageofpages',{'page'=>$page, 'total'=>$pages}); $navcrap .= "
$left"; for (my $i=1; $i<=$pages; $i++) { my $link = "[$i]"; if ($i != $page) { $link = " $i }) . "#comments'>$link"; } else { $link = "$link"; } $navcrap .= "$link "; if ($i == 11) { $navcrap .= "
"; } elsif ($i > 10 && $i % 10 == 0) { $navcrap .= "
"; } } $navcrap .= "
$right
\n"; $navcrap = BML::fill_template("standout", { 'DATA' => $navcrap }); } ####### end navcrap # Quick reply variables. Not always set. my ($last_talkid, $last_jid) = LJ::get_lastcomment(); my %LJ_cmtinfo; # data structure to give to javascript for commentmanage $LJ_cmtinfo{'journal'} = $u->{user}; $LJ_cmtinfo{'canAdmin'} = LJ::can_manage($remote, $u) ? 1 : 0; $LJ_cmtinfo{'remote'} = $remote ? $remote->{user} : ""; my $recurse_post = sub { my ($self_sub, $post, $opts) = @_; $opts ||= { 'depth' => 0 }; my $tid = $post->{'talkid'}; my $dtid = $tid * 256 + $init->{'anum'}; my $LJci = $LJ_cmtinfo{$dtid} = { rc => [], u => '' }; my $datepost = "" . substr($post->{'datepost'}, 0, 16) . ""; my $bgcolor = ($opts->{'depth'} % 2) ? "emcolorlite" : "emcolor"; $bgcolor = BML::get_template_def($bgcolor); if ($post->{'state'} eq "S") { $bgcolor = BML::get_template_def("screenedbarcolor") || $bgcolor; } elsif ($last_talkid == $dtid && $last_jid == $u->{'userid'}) { $bgcolor = BML::get_template_def("altcolor1"); } my $pu = $post->{'posterid'} ? $user{$post->{'posterid'}} : undef; $LJci->{u} = $pu->{user} if $pu; my $userpost = $post->{'userpost'}; my $upost = $post->{'upost'}; my $user; if ($post->{'props'}->{'deleted_poster'}) { $user = BML::ml('.deleteduser', {'username'=>$post->{'deleted_poster'}}); } else { $user = $ML{'.anonuser'}; } if ($post->{'state'} eq "D") { $ret .= "

"; $ret .= ""; $ret .= "
$ML{'.deletedpost'}
\n"; } elsif ($post->{'state'} eq "S" && !$post->{'_loaded'} && !$post->{'_show'}) { $ret .= "

"; $ret .= ""; my $screenedtext = $ML{'.screenedpost'}; $ret .= "
$screenedtext
\n"; # Here is a place to show commens from suspended journals # HACK: I added "&& 0" here so that suspended poster's comments are seen } elsif ($pu && 0 && $pu->{'statusvis'} eq "S" && !$viewsome) { $ret .= "

"; $ret .= ""; $ret .= "
$ML{'.replysuspended'}"; if (LJ::Talk::can_delete($remote, $u, $up, $userpost)) { $ret .= " " . LJ::img("btn_del", "", { 'align' => 'absmiddle', 'hspace' => 2, 'vspace' => }) . ""; } if ($post->{state} ne 'F' && LJ::Talk::can_freeze($remote, $u, $up, $userpost)) { $ret .= "" . LJ::img("btn_freeze", "", { align => 'absmiddle', hspace => 2, vspace => }) . ""; } if ($post->{state} eq 'F' && LJ::Talk::can_unfreeze($remote, $u, $up, $userpost)) { $ret .= "" . LJ::img("btn_unfreeze", "", { align => 'absmiddle', hspace => 2, vspace => }) . ""; } $ret .= "
\n"; } else { if ($upost) { $user = LJ::ljuser($upost); } my $icon = LJ::Talk::show_image($pics, $post->{'props'}->{'subjecticon'}); if ($post->{'_loaded'}) { $ret .= ""; $ret .= ""; $ret .= "
"; if (my $picid = $post->{'picid'}) { my $alt = $pu->{'name'}; if ($post->{'props'}->{'picture_keyword'}) { $alt .= ": $post->{'props'}->{'picture_keyword'}"; } $alt = LJ::ehtml($alt); my ($w, $h) = ($userpics{$picid}->{'width'}, $userpics{$picid}->{'height'}); $ret .= "{'subject'}); $ret .= "$cleansubject $icon"; $ret .= "
$user\n"; $ret .= "
$datepost\n"; if ($post->{'props'}->{'poster_ip'} && $remote && ($remote->{'user'} eq $up->{'user'} || LJ::can_manage($remote, $u) || $viewall)) { $ret .= BML::ml('.fromip', {'ip'=>$post->{'props'}->{'poster_ip'}}); } $ret .= " ($T{'link'}) "; if (LJ::Talk::can_delete($remote, $u, $up, $userpost)) { $ret .= "" . LJ::img("btn_del", "", { 'align' => 'absmiddle', 'hspace' => 2, 'vspace' => }) . ""; } if ($post->{'state'} ne 'F' && LJ::Talk::can_freeze($remote, $u, $up, $userpost)) { $ret .= "" . LJ::img("btn_freeze", "", { align => 'absmiddle', hspace => 2, vspace => }) . ""; } if ($post->{'state'} eq 'F' && LJ::Talk::can_unfreeze($remote, $u, $up, $userpost)) { $ret .= "" . LJ::img("btn_unfreeze", "", { align => 'absmiddle', hspace => 2, vspace => }) . ""; } if ($post->{'state'} ne 'S' && LJ::Talk::can_screen($remote, $u, $up, $userpost)) { $ret .= "" . LJ::img("btn_scr", "", { 'align' => 'absmiddle', 'hspace' => 2, 'vspace' => }) . ""; } if ($post->{'state'} eq 'S' && LJ::Talk::can_unscreen($remote, $u, $up, $userpost)) { $ret .= "" . LJ::img("btn_unscr", "", { 'align' => 'absmiddle', 'hspace' => 2, 'vspace' => }) . ""; } if ($showmultiform) { $ret .= " "; $ret .= " "; $multiform_selects = 1; } # Comment Posted Notice $ret .= "
$ML{'.posted'}" if $last_talkid == $dtid && $last_jid == $u->{'userid'}; $ret .= "
"; LJ::CleanHTML::clean_comment(\$post->{'body'}, { 'preformatted' => $post->{'props'}->{'opt_preformatted'}, 'anon_comment' => (!$pu || $pu->{_identity}) } ); BML::ebml(\$post->{'body'}); $ret .= $post->{'body'}; $ret .= "

"; my $replyurl = LJ::Talk::talkargs($talkurl, "replyto=$dtid", $stylemine); if ($post->{'state'} eq 'F') { $ret .= "($T{'frozen'}) "; } elsif ($remote) { $ret .= "(" . LJ::make_qr_link($dtid, $post->{'subject'}, $T{'replythis'}, $replyurl) . ")"; } else { $ret .= "($T{'replythis'}) "; } if ($post->{'parenttalkid'} != 0) { my $dpid = $post->{'parenttalkid'} * 256 + $init->{'anum'}; $ret .= "($T{'parent'}) "; } if ($post->{'children'} && @{$post->{'children'}}) { my $url = LJ::Talk::talkargs($talkurl, "thread=$dtid", $stylemine) . "#t$dtid"; $ret .= "($T{'thread'})"; } $ret .= "

"; $ret .= LJ::make_qr_target($dtid) if $remote; $ret .= "
\n"; # close colored table } else { # link to message $ret .= ""; $ret .= ""; $ret .= "
" . LJ::ehtml($post->{'subject'} || $T{'nosubject'}) . " - $user, $post->{'datepost'}"; # Comment Posted Notice $ret .= " - $ML{'.posted'}" if $last_talkid == $dtid && $last_jid == $u->{'userid'}; $ret .= "
\n"; } } if ($post->{'children'}) { foreach my $childpost (@{$post->{'children'}}) { push @{$LJci->{rc}}, $childpost->{talkid} * 256 + $init->{'anum'}; $self_sub->($self_sub, $childpost, { "depth" => $opts->{'depth'} + 1}); } } }; if ($props->{'syn_link'}) { my $posturl; my $rs = LJR::Distributed::match_remote_server($props->{'syn_link'}); if ($rs->{"servertype"} eq "lj") { $posturl = $props->{'syn_link'} . "?mode=reply"; } else { $posturl = $props->{'syn_link'} . "?mode=reply"; } $ret .= "

"; $ret .= "($T{'readcomments'})"; $ret .= " ($T{'postcomments'})"; $ret .= "

"; } unless ($nocomments) { $ret .= "
"; $ret .= "$navcrap" if $navcrap; my $readlink; if ($dthread && $pages == 1) { my $readurl = LJ::Talk::talkargs($talkurl, $stylemine); $readlink = "($T{'readcomments'}) - "; } my $posturl = LJ::Talk::talkargs($talkurl, "mode=reply", $stylemine); $ret .= "
"; # Quick Reply when posting a new top level comment # requires setup when logged in. $ret .= "

$readlink"; if ($remote) { $ret .= "(" . LJ::make_qr_link('top', '', $T{'postcomments'}, $posturl) . ")"; } else { $ret .= "($T{'postcomments'})"; } $ret .= "

"; $ret .= "
" . LJ::make_qr_target('top') . "
" if $remote; my $stylemine = $GET{'style'} eq 'mine' ? 1 : 0; my $viewing_thread; if (defined $GET{'thread'}) { $viewing_thread = $GET{'thread'}; } $ret .= LJ::create_qr_div($u, $ditemid, $stylemine, $GET{'prop_picture_keyword'}, $viewing_thread); $ret .= LJ::html_hidden("ditemid", $ditemid); $ret .= LJ::html_hidden("journal", $u->{'user'}); # Print out each comment if (@comments > 0) { $recurse_post->($recurse_post, $_, { "depth" => 0 }) foreach (@comments); my $do_commentmanage_js = $showmultiform; 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) { $$head .= "\n"; my $js_screen_color = "\"" . LJ::ejs(BML::get_template_def("screenedbarcolor") || BML::get_template_def("emcolor")) . "\""; my $js_normal_color = "\"" . LJ::ejs(BML::get_template_def("emcolor")) . "\""; $$head .= "\n"; } $ret .= "

$readlink"; $ret .= "(" . LJ::make_qr_link('bottom', '', $T{'postcomments'}, $posturl) . ")" if $remote; $ret .= "

"; $ret .= "
" . LJ::make_qr_target('bottom') . "
" if $remote; if ($showmultiform && $multiform_selects) { $ret .= "

$ML{'.talkmulti.des'} "; $ret .= LJ::html_select({'name' => 'mode' }, "" => "", "unscreen" => $ML{'.talkmulti.unscreen'}, "screen" => $ML{'.talkmulti.screen'}, "delete" => $ML{'.talkmulti.delete'}); $ret .= " " . LJ::html_submit('', $ML{'.talkmulti.submit'}, { "onclick" => "return (document.multiform.mode.value != \"delete\") " . "|| confirm(\"" . LJ::ejs($ML{'.confirm.action'}) . "\");" }); $ret .= "

"; } } $ret .= "
"; if ($navcrap) { $ret .= "

$navcrap

"; } $ret .= "
"; } BML::noparse(); return $ret; _code?> <=body windowtitle=>{'title'} : $r_title _code?> head=>{'head'} : $r_head _code?> bodyopts=>{'bodyopts'}; _code?> page?> link: htdocs/talkpost.bml, htdocs/talkread.bml, htdocs/delcomment.bml img: htdocs/img/dot.gif, htdocs/img/delcomment.gif _c?>