X-Git-Url: http://www.git.stargrave.org/?a=blobdiff_plain;f=lib%2FPublicInbox%2FView.pm;h=9c3ef104f1a83ab28edfce75cf2ce2308ad3af76;hb=6c853f5256f3a324c018a37a9e8a6b9fc8fdc063;hp=60dad6bac0ec96679c0fb81b91f4f4a6824b73e9;hpb=5afb24f06627641e3fed608e807b5ab628cda348;p=public-inbox.git diff --git a/lib/PublicInbox/View.pm b/lib/PublicInbox/View.pm index 60dad6ba..9c3ef104 100644 --- a/lib/PublicInbox/View.pm +++ b/lib/PublicInbox/View.pm @@ -7,8 +7,10 @@ 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); @@ -18,7 +20,6 @@ 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 .= '
'; @@ -50,14 +50,13 @@ sub no_over_html ($) { my ($ctx) = @_; my $bref = $ctx->{-inbox}->msg_by_mid($ctx->{mid}) or return; # 404 my $eml = PublicInbox::Eml->new($bref); - my $hdr = $eml->header_obj; $ctx->{mhref} = ''; PublicInbox::WwwStream::init($ctx); - 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 .= '
'; - eval { $$obuf .= html_footer($ctx, $hdr) }; + eval { $$obuf .= html_footer($ctx, $eml) }; html_oneshot($ctx, 200, $obuf); } @@ -70,7 +69,13 @@ sub msg_page { my $over = $ctx->{over} = $ibx->over or return no_over_html($ctx); my ($id, $prev); my $next_arg = $ctx->{next_arg} = [ $ctx->{mid}, \$id, \$prev ]; - $ctx->{smsg} = $over->next_by_mid(@$next_arg) or return; # undef == 404 + + my $smsg = $ctx->{smsg} = $over->next_by_mid(@$next_arg) or + return; # undef == 404 + + # allow user to easily browse the range around this message if + # they have ->over + $ctx->{-t_max} = $smsg->{ts}; PublicInbox::WwwStream::aresponse($ctx, 200, \&msg_page_i); } @@ -170,13 +175,10 @@ sub nr_to_s ($$$) { $nr == 1 ? "$nr $singular" : "$nr $plural"; } -# human-friendly format -sub fmt_ts ($) { strftime('%Y-%m-%d %k:%M', gmtime($_[0])) } - # Displays the text of of the message for /$INBOX/$MSGID/[Tt]/ endpoint # this is already inside a
 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};
@@ -199,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) {
@@ -227,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)
@@ -267,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; } @@ -368,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 ($$) { @@ -422,9 +424,20 @@ sub thread_html { 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";
@@ -463,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});
@@ -625,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
"; @@ -643,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)); @@ -654,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; @@ -677,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"; @@ -696,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; } @@ -784,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 = '       ';
@@ -823,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;
@@ -860,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;
 }
@@ -1144,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) {
@@ -1206,6 +1224,7 @@ 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