about summary refs log tree commit homepage
diff options
context:
space:
mode:
authorEric Wong <e@80x24.org>2016-12-10 01:09:49 +0000
committerEric Wong <e@80x24.org>2016-12-10 03:23:46 +0000
commitdecbc59daa3b08e58e749b5bd88a9d0cbbb7e14a (patch)
tree5219e989d5c2da630bea9fa43129397da2e01a5e
parent43288c0a9de93d0e73af57e9525f2053f29f10bb (diff)
downloadpublic-inbox-decbc59daa3b08e58e749b5bd88a9d0cbbb7e14a.tar.gz
Otherwise, a malicious or broken client could populate the
thread skeleton with invalid References.  We only care about
ghosts which messages correctly refer to, not totally bogus ones
which may be the result of long line or token truncation +
wrapping in MUA headers.
-rw-r--r--lib/PublicInbox/SearchThread.pm15
1 files changed, 12 insertions, 3 deletions
diff --git a/lib/PublicInbox/SearchThread.pm b/lib/PublicInbox/SearchThread.pm
index 5774a956..ee35f0d0 100644
--- a/lib/PublicInbox/SearchThread.pm
+++ b/lib/PublicInbox/SearchThread.pm
@@ -33,7 +33,8 @@ sub thread {
         my $self = shift;
         _add_message($self, $_) foreach @{$self->{messages}};
         my $id_table = delete $self->{id_table};
-        $self->{rootset} = [ grep { !delete $_->{parent} } values %$id_table ];
+        $self->{rootset} = [ grep {
+                !delete($_->{parent}) && $_->visible } values %$id_table ];
 }
 
 sub _get_cont_for_id ($$) {
@@ -133,15 +134,23 @@ sub has_descendent {
         0;
 }
 
+# Do not show/keep ghosts iff they have no children.  Sometimes
+# a ghost Message-ID is the result of a long header line
+# being folded/mangled by a MUA, and not a missing message.
+sub visible ($) {
+        my ($self) = @_;
+        $self->{smsg} || scalar values %{$self->{children}};
+}
+
 sub order_children {
         my ($cur, $ordersub) = @_;
 
-        my %seen = ($cur => 1);
+        my %seen = ($cur => 1); # self-referential loop prevention
         my @q = ($cur);
         while (defined($cur = shift @q)) {
                 my $c = $cur->{children}; # The hashref here...
 
-                $c = [ grep { !$seen{$_}++ } values %$c ]; # spot/break loops
+                $c = [ grep { !$seen{$_}++ && visible($_) } values %$c ];
                 $c = $ordersub->($c) if scalar @$c > 1;
                 $cur->{children} = $c; # ...becomes an arrayref
                 push @q, @$c;