X-Git-Url: http://www.git.stargrave.org/?a=blobdiff_plain;f=lib%2FPublicInbox%2FView.pm;h=0b1ec75b31fd3f297bfcf85fdea29364ba5ede8a;hb=ccb66f35d293d3d0e3f9b119f7bd1fa019b93c75;hp=feac601510ff0d021fa1bc07d52f6dc4f3c0ff14;hpb=275dc15b848eb3f51f10eb62fdec2d3ac8404e15;p=public-inbox.git diff --git a/lib/PublicInbox/View.pm b/lib/PublicInbox/View.pm index feac6015..0b1ec75b 100644 --- a/lib/PublicInbox/View.pm +++ b/lib/PublicInbox/View.pm @@ -92,13 +92,13 @@ EOF sub in_reply_to { my ($hdr) = @_; - my $irt = $hdr->header_raw('In-Reply-To'); - - return mid_clean($irt) if defined $irt && $irt ne ''; - - my $refs = $hdr->header_raw('References'); - if ($refs && $refs =~ /<([^>]+)>\s*\z/s) { - return $1; + my %mid = map { $_ => 1 } $hdr->header_raw('Message-ID'); + my @refs = ($hdr->header_raw('References'), + $hdr->header_raw('In-Reply-To')); + @refs = ((join(' ', @refs)) =~ /<([^>]+)>/g); + while (defined(my $irt = pop @refs)) { + next if $mid{"<$irt>"}; + return $irt; } undef; } @@ -201,7 +201,10 @@ sub _th_index_lite { my $rv = ''; my $mapping = $ctx->{mapping} or return $rv; my $pad = ' '; - my ($attr, $node, $idx, $level) = @{$mapping->{$mid_raw}}; + my $mid_map = $mapping->{$mid_raw}; + defined $mid_map or + return 'public-inbox BUG: '.ascii_html($mid_raw).' not mapped'; + my ($attr, $node, $idx, $level) = @$mid_map; my $children = $node->{children}; my $nr_c = scalar @$children; my $nr_s = 0; @@ -260,8 +263,8 @@ sub _th_index_lite { } sub walk_thread { - my ($th, $ctx, $cb) = @_; - my @q = map { (0, $_, -1) } @{$th->{rootset}}; + my ($rootset, $ctx, $cb) = @_; + my @q = map { (0, $_, -1) } @$rootset; while (@q) { my ($level, $node, $i) = splice(@q, 0, 3); defined $node or next; @@ -285,10 +288,10 @@ sub thread_index_entry { } sub stream_thread ($$) { - my ($th, $ctx) = @_; + my ($rootset, $ctx) = @_; my $inbox = $ctx->{-inbox}; my $mime; - my @q = map { (0, $_) } @{$th->{rootset}}; + my @q = map { (0, $_) } @$rootset; my $level; while (@q) { $level = shift @q; @@ -299,7 +302,7 @@ sub stream_thread ($$) { } return missing_thread($ctx) unless $mime; - $mime = Email::MIME->new($mime); + $mime = PublicInbox::MIME->new($mime); $ctx->{-title_html} = ascii_html($mime->header('Subject')); $ctx->{-html_tip} = thread_index_entry($ctx, $level, $mime); PublicInbox::WwwStream->response($ctx, 200, sub { @@ -311,7 +314,7 @@ sub stream_thread ($$) { unshift @q, map { ($cl, $_) } @{$node->{children}}; my $mid = $node->{id}; if ($mime = $inbox->msg_by_smsg($node->{smsg})) { - $mime = Email::MIME->new($mime); + $mime = PublicInbox::MIME->new($mime); return thread_index_entry($ctx, $level, $mime); } else { return ghost_index_entry($ctx, $level, $node); @@ -327,8 +330,9 @@ sub stream_thread ($$) { sub thread_html { my ($ctx) = @_; my $mid = $ctx->{mid}; - my $sres = $ctx->{srch}->get_thread($mid, { asc => 1 }); - my $msgs = load_results($sres); + my $srch = $ctx->{srch}; + my $sres = $srch->get_thread($mid); + my $msgs = load_results($srch, $sres); my $nr = $sres->{total}; return missing_thread($ctx) if $nr == 0; my $skel = '
';
@@ -349,10 +353,10 @@ sub thread_html {
 	$ctx->{mapping} = {};
 	$ctx->{s_nr} = "$nr+ messages in thread";
 
-	my $th = thread_results($msgs);
-	walk_thread($th, $ctx, *pre_thread);
+	my $rootset = thread_results($msgs);
+	walk_thread($rootset, $ctx, *pre_thread);
 	$skel .= '
'; - return stream_thread($th, $ctx) unless $ctx->{flat}; + return stream_thread($rootset, $ctx) unless $ctx->{flat}; # flat display: lazy load the full message from smsg my $inbox = $ctx->{-inbox}; @@ -361,7 +365,7 @@ sub thread_html { $mime = $inbox->msg_by_smsg($mime) and last; } return missing_thread($ctx) unless $mime; - $mime = Email::MIME->new($mime); + $mime = PublicInbox::MIME->new($mime); $ctx->{-title_html} = ascii_html($mime->header('Subject')); $ctx->{-html_tip} = '
'.index_entry($mime, $ctx, scalar @$msgs);
 	$mime = undef;
@@ -371,7 +375,7 @@ sub thread_html {
 			$mime = $inbox->msg_by_smsg($mime) and last;
 		}
 		if ($mime) {
-			$mime = Email::MIME->new($mime);
+			$mime = PublicInbox::MIME->new($mime);
 			return index_entry($mime, $ctx, scalar @$msgs);
 		}
 		$msgs = undef;
@@ -440,7 +444,7 @@ sub attach_link ($$$$;$) {
 
 sub add_text_body {
 	my ($upfx, $p) = @_; # from msg_iter: [ Email::MIME, depth, @idx ]
-	my ($part, $depth, @idx) = @$p;
+	my ($part, $depth) = @$p; # attachment @idx is unused
 	my $ct = $part->content_type || 'text/plain';
 	my $fn = $part->filename;
 
@@ -475,29 +479,26 @@ sub add_text_body {
 	}
 	my @quot;
 	my $l = PublicInbox::Linkify->new;
-	while (defined(my $cur = shift @lines)) {
+	foreach my $cur (@lines) {
 		if ($cur !~ /^>/) {
 			# show the previously buffered quote inline
 			flush_quote(\$s, $l, \@quot) if @quot;
 
 			# regular line, OK
-			$cur = $l->linkify_1($cur);
-			$cur = ascii_html($cur);
-			$s .= $l->linkify_2($cur);
+			$l->linkify_1($cur);
+			$s .= $l->linkify_2(ascii_html($cur));
 		} else {
 			push @quot, $cur;
 		}
 	}
 
-	my $end = "\n";
-	if (@quot) {
-		$end = '';
+	if (@quot) { # ugh, top posted
 		flush_quote(\$s, $l, \@quot);
+	} elsif ($s =~ /\n\z/s) { # common, last line ends with a newline
+		$s;
+	} else { # some editors don't do newlines...
+		$s .= "\n";
 	}
-	$s =~ s/[ \t]+$//sgm; # kill per-line trailing whitespace
-	$s =~ s/\A\n+//s; # kill leading blank lines
-	$s =~ s/\s+\z//s; # kill all trailing spaces
-	$s .= $end;
 }
 
 sub _msg_html_prepare {
@@ -574,7 +575,8 @@ sub thread_skel {
 	$ctx->{prev_attr} = '';
 	$ctx->{prev_level} = 0;
 	$ctx->{dst} = $dst;
-	walk_thread(thread_results(load_results($sres)), $ctx, *skel_dump);
+	$sres = load_results($srch, $sres);
+	walk_thread(thread_results($sres), $ctx, *skel_dump);
 	$ctx->{parent_msg} = $parent;
 }
 
@@ -733,9 +735,9 @@ sub indent_for {
 }
 
 sub load_results {
-	my ($sres) = @_;
-
-	[ map { $_->ensure_metadata; $_ } @{delete $sres->{msgs}} ];
+	my ($srch, $sres) = @_;
+	my $msgs = delete $sres->{msgs};
+	$srch->retry_reopen(sub { [ map { $_->mid; $_ } @$msgs ] });
 }
 
 sub msg_timestamp {
@@ -747,10 +749,7 @@ sub msg_timestamp {
 sub thread_results {
 	my ($msgs) = @_;
 	require PublicInbox::SearchThread;
-	my $th = PublicInbox::SearchThread->new($msgs);
-	$th->thread;
-	$th->order(*sort_ts);
-	$th
+	PublicInbox::SearchThread::thread($msgs, *sort_ts);
 }
 
 sub missing_thread {
@@ -767,8 +766,9 @@ sub _msg_date {
 
 sub fmt_ts { POSIX::strftime('%Y-%m-%d %k:%M', gmtime($_[0])) }
 
-sub _skel_header {
-	my ($ctx, $smsg, $level) = @_;
+sub skel_dump {
+	my ($ctx, $level, $node) = @_;
+	my $smsg = $node->{smsg} or return _skel_ghost($ctx, $level, $node);
 
 	my $dst = $ctx->{dst};
 	my $cur = $ctx->{cur};
@@ -824,32 +824,29 @@ sub _skel_header {
 	$$dst .=  $d . "" . $end;
 }
 
-sub skel_dump {
+sub _skel_ghost {
 	my ($ctx, $level, $node) = @_;
-	if (my $smsg = $node->{smsg}) {
-		_skel_header($ctx, $smsg, $level);
+
+	my $mid = $node->{id};
+	my $d = $ctx->{pct} ? '    [irrelevant] ' # search result
+			    : '     [not found] ';
+	$d .= indent_for($level) . th_pfx($level);
+	my $upfx = $ctx->{-upfx};
+	my $m = PublicInbox::Hval->new_msgid($mid);
+	my $href = $upfx . $m->{href} . '/';
+	my $html = $m->as_html;
+
+	my $mapping = $ctx->{mapping};
+	my $map = $mapping->{$mid} if $mapping;
+	if ($map) {
+		my $id = id_compress($mid, 1);
+		$map->[0] = $d . qq{<$html>\n};
+		$d .= qq{<$html>\n};
 	} else {
-		my $mid = $node->{id};
-		my $dst = $ctx->{dst};
-		my $d = $ctx->{pct} ? '    [irrelevant] ' # search result
-				    : '     [not found] ';
-		$d .= indent_for($level) . th_pfx($level);
-		my $upfx = $ctx->{-upfx};
-		my $m = PublicInbox::Hval->new_msgid($mid);
-		my $href = $upfx . $m->{href} . '/';
-		my $html = $m->as_html;
-
-		my $mapping = $ctx->{mapping};
-		my $map = $mapping->{$mid} if $mapping;
-		if ($map) {
-			my $id = id_compress($mid, 1);
-			$map->[0] = $d . qq{<$html>\n};
-			$d .= qq{<$html>\n};
-		} else {
-			$d .= qq{<$html>\n};
-		}
-		$$dst .= $d;
+		$d .= qq{<$html>\n};
 	}
+	my $dst = $ctx->{dst};
+	$$dst .= $d;
 }
 
 sub sort_ts {
@@ -977,10 +974,11 @@ sub index_topics {
 	my $opts = { offset => $off, limit => 200 };
 
 	$ctx->{order} = [];
-	my $sres = $ctx->{srch}->query('', $opts);
+	my $srch = $ctx->{srch};
+	my $sres = $srch->query('', $opts);
 	my $nr = scalar @{$sres->{msgs}};
 	if ($nr) {
-		$sres = load_results($sres);
+		$sres = load_results($srch, $sres);
 		walk_thread(thread_results($sres), $ctx, *acc_topic);
 	}
 	$ctx->{-next_o} = $off+ $nr;