X-Git-Url: http://www.git.stargrave.org/?a=blobdiff_plain;f=lib%2FPublicInbox%2FMID.pm;h=c82e84013ec0d68730423ab4b691074c5b690dc5;hb=1cb230c4d47c8ef5d03f0b8de2f8ad93c303d816;hp=4ccb704da7e3d783f61a3ded49a970349ebcb86e;hpb=af2e250ca2704d06afe0a7ed862dcfca7f740de7;p=public-inbox.git diff --git a/lib/PublicInbox/MID.pm b/lib/PublicInbox/MID.pm index 4ccb704d..c82e8401 100644 --- a/lib/PublicInbox/MID.pm +++ b/lib/PublicInbox/MID.pm @@ -10,7 +10,10 @@ our @EXPORT_OK = qw/mid_clean id_compress mid2path mid_mime mid_escape MID_ESC mids references/; use URI::Escape qw(uri_escape_utf8); use Digest::SHA qw/sha1_hex/; -use constant MID_MAX => 40; # SHA-1 hex length +use constant { + MID_MAX => 40, # SHA-1 hex length # TODO: get rid of this + MAX_MID_SIZE => 244, # max term size (Xapian limitation) - length('Q') +}; sub mid_clean { my ($mid) = @_; @@ -47,31 +50,53 @@ sub mid2path { "$x2/$x38"; } -sub mid_mime ($) { $_[0]->header_obj->header_raw('Message-ID') } +# Only for v1 code paths: +sub mid_mime ($) { mids($_[0]->header_obj)->[0] } -sub uniq_mids { - my ($hdr, @fields) = @_; - my %seen; - my @raw; - foreach my $f (@fields) { - push @raw, $hdr->header_raw($f); - } - my @mids = (join(' ', @raw) =~ /<([^>]+)>/g); - my $mids = scalar(@mids) == 0 ? \@raw: \@mids; - my @ret; - foreach (@$mids) { - next if $seen{$_}; - push @ret, $_; - $seen{$_} = 1; +sub mids ($) { + my ($hdr) = @_; + my @mids; + my @v = $hdr->header_raw('Message-Id'); + foreach my $v (@v) { + my @cur = ($v =~ /<([^>]+)>/sg); + if (@cur) { + push(@mids, @cur); + } else { + push(@mids, $v); + } } - \@ret; + uniq_mids(\@mids); } -sub mids { uniq_mids($_[0], 'Message-Id') } - # last References should be IRT, but some mail clients do things # out of order, so trust IRT over References iff IRT exists -sub references { uniq_mids($_[0], 'References', 'In-Reply-To') } +sub references ($) { + my ($hdr) = @_; + my @mids; + foreach my $f (qw(References In-Reply-To)) { + my @v = $hdr->header_raw($f); + foreach my $v (@v) { + push(@mids, ($v =~ /<([^>]+)>/sg)); + } + } + uniq_mids(\@mids); +} + +sub uniq_mids ($) { + my ($mids) = @_; + my @ret; + my %seen; + foreach my $mid (@$mids) { + if (length($mid) > MAX_MID_SIZE) { + warn "Message-ID: <$mid> too long, truncating\n"; + $mid = substr($mid, 0, MAX_MID_SIZE); + } + next if $seen{$mid}; + push @ret, $mid; + $seen{$mid} = 1; + } + \@ret; +} # RFC3986, section 3.3: sub MID_ESC () { '^A-Za-z0-9\-\._~!\$\&\';\(\)\*\+,;=:@' }