X-Git-Url: http://www.git.stargrave.org/?a=blobdiff_plain;f=lib%2FPublicInbox%2FView.pm;h=9c3ef104f1a83ab28edfce75cf2ce2308ad3af76;hb=6c853f5256f3a324c018a37a9e8a6b9fc8fdc063;hp=138e0c3a217d6173de7049c577fcc0ea72769594;hpb=208450d2347ab92de7dcb9733fb51543df32635a;p=public-inbox.git diff --git a/lib/PublicInbox/View.pm b/lib/PublicInbox/View.pm index 138e0c3a..9c3ef104 100644 --- a/lib/PublicInbox/View.pm +++ b/lib/PublicInbox/View.pm @@ -7,18 +7,19 @@ package PublicInbox::View; use strict; use warnings; use bytes (); # only for bytes::length +use List::Util qw(max); use PublicInbox::MsgTime qw(msg_datestamp); -use PublicInbox::Hval qw(ascii_html obfuscate_addrs prurl mid_href); +use PublicInbox::Hval qw(ascii_html obfuscate_addrs prurl mid_href + ts2str fmt_ts); use PublicInbox::Linkify; use PublicInbox::MID qw(id_compress mids mids_for_index references $MID_EXTRACT); use PublicInbox::MsgIter; use PublicInbox::Address; -use PublicInbox::WwwStream; +use PublicInbox::WwwStream qw(html_oneshot); use PublicInbox::Reply; use PublicInbox::ViewDiff qw(flush_diff); use PublicInbox::Eml; -use POSIX qw(strftime); use Time::Local qw(timegm); use PublicInbox::Smsg qw(subject_normalized); use constant COLS => 72; @@ -33,8 +34,7 @@ sub msg_page_i { $ctx->{smsg} = $ctx->{over}->next_by_mid(@{$ctx->{next_arg}}); $ctx->{mhref} = ($ctx->{nr} || $ctx->{smsg}) ? "../${\mid_href($smsg->{mid})}/" : ''; - my $hdr = $eml->header_obj; - my $obuf = $ctx->{obuf} = _msg_page_prepare_obuf($hdr, $ctx); + my $obuf = $ctx->{obuf} = _msg_page_prepare_obuf($eml, $ctx); multipart_text_as_html($eml, $ctx); delete $ctx->{obuf}; $$obuf .= '
sub eml_entry { - my ($ctx, $eml, $more) = @_; + my ($ctx, $eml) = @_; my $smsg = delete $ctx->{smsg}; my $subj = delete $smsg->{subject}; my $mid_raw = $smsg->{mid}; @@ -204,16 +201,15 @@ sub eml_entry { # Deleting these fields saves about 400K as we iterate across 1K msgs delete @$smsg{qw(ts blob)}; - my $hdr = $eml->header_obj; - my $from = _hdr_names_html($hdr, 'From'); + my $from = _hdr_names_html($eml, 'From'); obfuscate_addrs($obfs_ibx, $from) if $obfs_ibx; $rv .= "From: $from @ ".fmt_ts($ds)." UTC"; my $upfx = $ctx->{-upfx}; my $mhref = $upfx . mid_href($mid_raw) . '/'; $rv .= qq{ (permalink / }; $rv .= qq{raw)\n}; - my $to = fold_addresses(_hdr_names_html($hdr, 'To')); - my $cc = fold_addresses(_hdr_names_html($hdr, 'Cc')); + my $to = fold_addresses(_hdr_names_html($eml, 'To')); + my $cc = fold_addresses(_hdr_names_html($eml, 'Cc')); my ($tlen, $clen) = (length($to), length($cc)); my $to_cc = ''; if (($tlen + $clen) > COLS) { @@ -232,7 +228,7 @@ sub eml_entry { $rv .= $to_cc; my $mapping = $ctx->{mapping}; - if (!$mapping && (defined($irt) || defined($irt = in_reply_to($hdr)))) { + if (!$mapping && (defined($irt) || defined($irt = in_reply_to($eml)))) { my $href = $upfx . mid_href($irt) . '/'; my $html = ascii_html($irt); $rv .= qq(In-Reply-To: <$html>\n) @@ -272,7 +268,8 @@ sub eml_entry { $hr = $ctx->{-hr}; } - $rv .= $more ? '
' : '' if $hr; + # do we have more messages? start a new
if so + $rv .= scalar(@{$ctx->{msgs}}) ? '
' : '' if $hr; $rv; } @@ -373,7 +370,7 @@ sub pre_thread { # walk_thread callback sub thread_eml_entry { my ($ctx, $eml) = @_; my ($beg, $end) = thread_adj_level($ctx, $ctx->{level}); - $beg . '
' . eml_entry($ctx, $eml, 0) . '' . $end; + $beg . '
' . eml_entry($ctx, $eml) . '' . $end; } sub next_in_queue ($$) { @@ -420,16 +417,27 @@ sub stream_thread ($$) { PublicInbox::WwwStream::aresponse($ctx, 200, \&stream_thread_i); } -# /$INBOX/$MESSAGE_ID/t/ +# /$INBOX/$MSGID/t/ and /$INBOX/$MSGID/T/ sub thread_html { my ($ctx) = @_; my $mid = $ctx->{mid}; my $ibx = $ctx->{-inbox}; my ($nr, $msgs) = $ibx->over->get_thread($mid); return missing_thread($ctx) if $nr == 0; + + # link $INBOX_DIR/description text to "index_topics" view around + # the newest message in this thread + my $t = ts2str($ctx->{-t_max} = max(map { delete $_->{ts} } @$msgs)); + my $t_fmt = fmt_ts($ctx->{-t_max}); + my $skel = '
'; $skel .= $nr == 1 ? 'only message in thread' : 'end of thread'; - $skel .= ", back to index\n\n"; + $skel .= <~$t_fmt UTC | newest] + +EOF $skel .= "Thread overview: "; $skel .= $nr == 1 ? '(only message)' : "$nr+ messages"; $skel .= " (download: mbox.gz"; @@ -468,7 +476,7 @@ sub thread_html_i { # PublicInbox::WwwStream::getline callback $ctx->{-title_html} = ascii_html($smsg->{subject}); $ctx->zmore($ctx->html_top); } - return eml_entry($ctx, $eml, scalar @{$ctx->{msgs}}); + return eml_entry($ctx, $eml); } else { while (my $smsg = shift @{$ctx->{msgs}}) { return $smsg if exists($smsg->{blob}); @@ -630,16 +638,16 @@ sub add_text_body { # callback for each_part } sub _msg_page_prepare_obuf { - my ($hdr, $ctx) = @_; + my ($eml, $ctx) = @_; my $over = $ctx->{-inbox}->over; my $obfs_ibx = $ctx->{-obfs_ibx}; my $rv = ''; - my $mids = mids_for_index($hdr); + my $mids = mids_for_index($eml); my $nr = $ctx->{nr}++; if ($nr) { # unlikely $rv .= ' '; } else { - $ctx->{first_hdr} = $hdr; + $ctx->{first_hdr} = $eml->header_obj; if ($ctx->{smsg}) { $rv .= "WARNING: multiple messages have this Message-ID\n"; @@ -648,7 +656,7 @@ sub _msg_page_prepare_obuf { } $ctx->{-upfx} = '../' if $over; my @title; # (Subject[0], From[0]) - for my $v ($hdr->header('From')) { + for my $v ($eml->header('From')) { my @n = PublicInbox::Address::names($v); $v = ascii_html($v); $title[1] //= ascii_html(join(', ', @n)); @@ -659,14 +667,14 @@ sub _msg_page_prepare_obuf { $rv .= "From: $v\n" if $v ne ''; } foreach my $h (qw(To Cc)) { - for my $v ($hdr->header($h)) { + for my $v ($eml->header($h)) { fold_addresses($v); $v = ascii_html($v); obfuscate_addrs($obfs_ibx, $v) if $obfs_ibx; $rv .= "$h: $v\n" if $v ne ''; } } - my @subj = $hdr->header('Subject'); + my @subj = $eml->header('Subject'); if (@subj) { my $v = ascii_html(shift @subj); obfuscate_addrs($obfs_ibx, $v) if $obfs_ibx; @@ -682,7 +690,7 @@ sub _msg_page_prepare_obuf { $rv .= qq() if $over; $title[0] = '(no subject)'; } - for my $v ($hdr->header('Date')) { + for my $v ($eml->header('Date')) { $v = ascii_html($v); obfuscate_addrs($obfs_ibx, $v) if $obfs_ibx; # possible :P $rv .= "Date: $v\n"; @@ -701,12 +709,12 @@ sub _msg_page_prepare_obuf { my $lnk = PublicInbox::Linkify->new; my $s = ''; for my $h (qw(Message-ID X-Alt-Message-ID)) { - $s .= "$h: $_\n" for ($hdr->header_raw($h)); + $s .= "$h: $_\n" for ($eml->header_raw($h)); } $lnk->linkify_mids('..', \$s, 1); $rv .= $s; } - $rv .= _parent_headers($hdr, $over); + $rv .= _parent_headers($eml, $over); $rv .= "\n"; \$rv; } @@ -789,15 +797,22 @@ sub _parent_headers { $rv; } -# returns a string buffer via ->getline +# returns a string buffer sub html_footer { my ($ctx, $hdr) = @_; my $ibx = $ctx->{-inbox}; my $upfx = '../'; - my $skel = " index"; + my $skel; my $rv = ''; if ($ibx->over) { - $skel .= "\n"; + my $t = ts2str($ctx->{-t_max}); + my $t_fmt = fmt_ts($ctx->{-t_max}); + $skel .= <~$t_fmt UTC|newest] +EOF + thread_skel(\$skel, $ctx, $hdr); my ($next, $prev); my $parent = ' '; @@ -828,6 +843,8 @@ sub html_footer { $parent = " parent"; } $rv .= "$next $prev$parent "; + } else { # unindexed inboxes w/o over + $skel = qq( latest); } $rv .= qq(reply); $rv .= $skel; @@ -865,7 +882,7 @@ sub find_mid_root { ++$ctx->{root_idx} if $level == 0; if ($node->{mid} eq $ctx->{mid}) { $ctx->{found_mid_at} = $ctx->{root_idx}; - return 0; + return 0; # stop iterating } 1; } @@ -1149,17 +1166,13 @@ sub dump_topics { 200; } -# only for the t= query parameter passed to overview DB -sub ts2str ($) { strftime('%Y%m%d%H%M%S', gmtime($_[0])) }; - sub str2ts ($) { my ($yyyy, $mon, $dd, $hh, $mm, $ss) = unpack('A4A2A2A2A2A2', $_[0]); - timegm($ss, $mm, $hh, $dd, $mon - 1, $yyyy); + timegm($ss || 0, $mm || 0, $hh || 0, $dd, $mon - 1, $yyyy); } sub pagination_footer ($$) { my ($ctx, $latest) = @_; - delete $ctx->{qp} or return; my $next = $ctx->{next_page} || ''; my $prev = $ctx->{prev_page} || ''; if ($prev) { @@ -1169,12 +1182,6 @@ sub pagination_footer ($$) { " page: $next$prev"; } -sub index_nav { # callback for WwwStream::getline - my ($ctx) = @_; - return $ctx->html_top if exists $ctx->{-html_tip}; - pagination_footer($ctx, '.') -} - sub paginate_recent ($$) { my ($ctx, $lim) = @_; my $t = $ctx->{qp}->{t} || ''; @@ -1217,13 +1224,15 @@ sub paginate_recent ($$) { $msgs; } +# GET /$INBOX - top-level inbox view for indexed inboxes sub index_topics { my ($ctx) = @_; my $msgs = paginate_recent($ctx, 200); # 200 is our window if (@$msgs) { walk_thread(thread_results($ctx, $msgs), $ctx, \&acc_topic); } - PublicInbox::WwwStream::response($ctx, dump_topics($ctx), \&index_nav); + html_oneshot($ctx, dump_topics($ctx), \pagination_footer($ctx, '.')); + } sub thread_adj_level {