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.
my $self = shift;
_add_message($self, $_) foreach @{$self->{messages}};
my $id_table = delete $self->{id_table};
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 ($$) {
}
sub _get_cont_for_id ($$) {
+# 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) = @_;
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...
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;
$c = $ordersub->($c) if scalar @$c > 1;
$cur->{children} = $c; # ...becomes an arrayref
push @q, @$c;