From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on dcvr.yhbt.net X-Spam-Level: X-Spam-Status: No, score=-4.0 required=3.0 tests=ALL_TRUSTED,BAYES_00, URIBL_BLOCKED shortcircuit=no autolearn=ham autolearn_force=no version=3.4.2 Received: from localhost (dcvr.yhbt.net [127.0.0.1]) by dcvr.yhbt.net (Postfix) with ESMTP id 80B9A1F66E for ; Sat, 29 Aug 2020 20:32:19 +0000 (UTC) From: Eric Wong To: meta@public-inbox.org Subject: [PATCH] imapd: filter out unusable flags from search Date: Sat, 29 Aug 2020 20:32:19 +0000 Message-Id: <20200829203219.10055-1-e@80x24.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit List-Id: Quiet down logs from -imapd when clients are blindly sending some unsupported flag conditions (e.g. "DRAFT", "DELETED") specified in RFC 3501. --- lib/PublicInbox/IMAPsearchqp.pm | 21 ++++++++++++++++++++- t/imapd.t | 8 +++++++- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/lib/PublicInbox/IMAPsearchqp.pm b/lib/PublicInbox/IMAPsearchqp.pm index 5c82faa5..190fefb9 100644 --- a/lib/PublicInbox/IMAPsearchqp.pm +++ b/lib/PublicInbox/IMAPsearchqp.pm @@ -162,11 +162,24 @@ sub msn_set { uid_set($self, $seq_set); } +# things that should not match +sub impossible { + my ($self) = @_; + push @{$self->{xap}}, 'bytes:..0'; + my $sql = $self->{sql} or return 1; + $$sql .= ' AND num < 0'; +} + my $prd = Parse::RecDescent->new(<<'EOG'); { my $q = $PublicInbox::IMAPsearchqp::q; } search_key : CHARSET(?) search_key1(s) { $return = $q } -search_key1 : "ALL" | "RECENT" | "UNSEEN" | "NEW" + +# n.b. we silently ignore most per-message flags right now; +# they're here for now to not dump parser errors. +search_key1 : "ALL" | "ANSWERED" | "RECENT" | "UNSEEN" | "SEEN" | "NEW" + | "UNANSWERED" | "UNDELETED" | "UNDRAFT" | "UNFLAGGED" + | DELETED | DRAFT | FLAGGED | OLD | OR_search_keys | NOT_search_key | LARGER_number @@ -206,6 +219,12 @@ MSN_set : sequence_set { $q->msn_set($item{sequence_set}) } UID_set : "UID" sequence_set { $q->uid_set($item{sequence_set}) } LARGER_number : "LARGER" number { $q->xap_only("bytes:$item{number}..") } SMALLER_number : "SMALLER" number { $q->xap_only("bytes:..$item{number}") } + +DELETED : "DELETED" { $q->impossible } +OLD : "OLD" { $q->impossible } +FLAGGED : "FLAGGED" { $q->impossible } +DRAFT : "DRAFT" { $q->impossible } + # pass "NOT" through XXX is this right? OP_NOT : "NOT" { $q->xap_only('NOT') } NOT_search_key : OP_NOT search_key1 diff --git a/t/imapd.t b/t/imapd.t index 4d627af7..8db72bd7 100644 --- a/t/imapd.t +++ b/t/imapd.t @@ -122,9 +122,11 @@ $ret = $mic->search('uid 1:1') or BAIL_OUT "SEARCH FAIL $@"; is_deeply($ret, [ 1 ], 'search UID 1:1 works'); $ret = $mic->search('uid 1:*') or BAIL_OUT "SEARCH FAIL $@"; is_deeply($ret, [ 1 ], 'search UID 1:* works'); +$ret = $mic->search('DELETED') or BAIL_OUT "SEARCH FAIL $@"; +is_deeply($ret, [], 'searching for DELETED returns nothing'); SKIP: { - skip 'Xapian missing', 7 if $level eq 'basic'; + skip 'Xapian missing', 8 if $level eq 'basic'; my $x = $mic->search(qw(smaller 99999)); is_deeply($x, [1], 'SMALLER works with Xapian (hit)'); $x = $mic->search(qw(smaller 9)); @@ -137,6 +139,10 @@ SKIP: { $x = $mic->search(qw(HEADER Message-ID testmessage@example.com)); is_deeply($x, [1], 'HEADER Message-ID works'); + + $x = $mic->search(qw(DRAFT HEADER Message-ID testmessage@example.com)); + is_deeply($x, [], 'impossible (DRAFT) key filters out match'); + $x = $mic->search(qw(HEADER Message-ID miss)); is_deeply($x, [], 'HEADER Message-ID can miss');