X-Git-Url: http://www.git.stargrave.org/?a=blobdiff_plain;f=lib%2FPublicInbox%2FIMAPsearchqp.pm;h=190fefb9cd5000420f7b393aa3193f0500e420e5;hb=374e1098fa03756e5626379ff6fe154785e16cfa;hp=fba3baccf50679913733b61f79f6a5513044f1fb;hpb=07caa8528db2ac22d81a0763e1cefd59acd827f1;p=public-inbox.git diff --git a/lib/PublicInbox/IMAPsearchqp.pm b/lib/PublicInbox/IMAPsearchqp.pm index fba3bacc..190fefb9 100644 --- a/lib/PublicInbox/IMAPsearchqp.pm +++ b/lib/PublicInbox/IMAPsearchqp.pm @@ -16,9 +16,9 @@ my %MM = map {; $MoY[$_-1] => sprintf('%02u', $_) } (1..12); # IMAP to Xapian header search key mapping my %IH2X = ( - TEXT => '', SUBJECT => 's:', BODY => 'b:', + # TEXT => undef, # => everything FROM => 'f:', TO => 't:', CC => 'c:', @@ -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 : search_key1(s) { $return = $q } -search_key1 : "ALL" | "RECENT" | "UNSEEN" | "NEW" +search_key : CHARSET(?) search_key1(s) { $return = $q } + +# 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 @@ -183,11 +196,17 @@ search_key1 : "ALL" | "RECENT" | "UNSEEN" | "NEW" | CC_string | BCC_string | SUBJECT_string + | BODY_string + | TEXT_string | UID_set | MSN_set | sub_query | +charset : /\S+/ +CHARSET : 'CHARSET' charset +{ $item{charset} =~ /\A(?:UTF-8|US-ASCII)\z/ ? 1 : die('NO [BADCHARSET]'); } + SENTSINCE_date : 'SENTSINCE' date { $q->SENTSINCE(\%item) } SENTON_date : 'SENTON' date { $q->SENTON(\%item) } SENTBEFORE_date : 'SENTBEFORE' date { $q->SENTBEFORE(\%item) } @@ -200,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 @@ -235,6 +260,8 @@ TO_string : "TO" string { $q->ih2x('TO', $item{string}) } CC_string : "CC" string { $q->ih2x('CC', $item{string}) } BCC_string : "BCC" string { $q->ih2x('BCC', $item{string}) } SUBJECT_string : "SUBJECT" string { $q->ih2x('SUBJECT', $item{string}) } +BODY_string : "BODY" string { $q->ih2x('BODY', $item{string}) } +TEXT_string : "TEXT" string { $q->ih2x(undef, $item{string}) } op_subq_enter : '(' { $q->subq_enter } sub_query : op_subq_enter search_key1(s) ')' { $q->subq_leave } @@ -253,7 +280,7 @@ sub parse { %$q = (sql => \$sql, imap => $imap); # imap = PublicInbox::IMAP obj # $::RD_TRACE = 1; my $res = eval { $prd->search_key(uc($query)) }; - return $@ if $@ && $@ =~ /\ABAD /; + return $@ if $@ && $@ =~ /\A(?:BAD|NO) /; return 'BAD unexpected result' if !$res || $res != $q; if (exists $q->{sql}) { delete $q->{xap};