index-search.c revision e1525829f427579a68152229ceb63e8bd461ce6a
/* Copyright (C) 2002 Timo Sirainen */
#include "lib.h"
#include "ibuffer.h"
#include "obuffer.h"
#include "mmap-util.h"
#include "rfc822-tokenize.h"
#include "rfc822-date.h"
#include "message-size.h"
#include "imap-date.h"
#include "imap-envelope.h"
#include "index-storage.h"
#include "mail-index-util.h"
#include "mail-modifylog.h"
#include "mail-search.h"
#include <stdlib.h>
#include <ctype.h>
STMT_START { \
} STMT_END
typedef struct {
unsigned int client_seq;
typedef struct {
int custom_header;
typedef struct {
const char *msg;
unsigned int max_num)
{
while (*set != '\0') {
if (*set == '*') {
set++;
} else {
num = 0;
set++;
}
}
return TRUE;
if (*set == '\0')
return FALSE;
} else if (*set == ':') {
set++;
if (*set == '*') {
set++;
return TRUE;
} else {
num2 = 0;
set++;
}
return TRUE;
}
if (*set != ',')
return FALSE;
}
set++;
}
return FALSE;
}
{
num = 0;
while (*str != '\0') {
return 0;
}
return num;
}
/* Returns >0 = matched, 0 = not matched, -1 = unknown */
unsigned int client_seq,
{
time_t t;
switch (type) {
case SEARCH_ALL:
return TRUE;
case SEARCH_SET:
case SEARCH_UID:
/* flags */
case SEARCH_ANSWERED:
case SEARCH_DELETED:
case SEARCH_DRAFT:
case SEARCH_FLAGGED:
case SEARCH_SEEN:
case SEARCH_RECENT:
case SEARCH_KEYWORD:
return FALSE;
/* dates */
case SEARCH_BEFORE:
if (!imap_parse_date(value, &t))
return FALSE;
return rec->internal_date < t;
case SEARCH_ON:
if (!imap_parse_date(value, &t))
return FALSE;
return rec->internal_date >= t &&
case SEARCH_SINCE:
if (!imap_parse_date(value, &t))
return FALSE;
return rec->internal_date >= t;
/* sizes, only with fastscanning */
case SEARCH_SMALLER:
/* knowing physical size may be enough */
return 0;
return -1;
case SEARCH_LARGER:
/* knowing physical size may be enough */
return 1;
return -1;
default:
return -1;
}
}
{
case -1:
/* unknown */
break;
case 0:
break;
default:
break;
}
}
const char *sent_value)
{
int timezone_offset;
return 0;
/* NOTE: RFC2060 doesn't specify if timezones should affect
matching, so we ignore them. */
return 0;
switch (type) {
case SEARCH_SENTBEFORE:
return sent_time < search_time;
case SEARCH_SENTON:
return sent_time >= search_time &&
case SEARCH_SENTSINCE:
return sent_time >= search_time;
default:
i_assert(0);
}
}
{
size_t i, needle_len;
/* note: needle is already uppercased */
for (i = 0; haystack[i] != '\0'; i++) {
return 1;
}
return 0;
}
/* Returns >0 = matched, 0 = not matched, -1 = unknown */
{
int ret;
switch (type) {
case SEARCH_SENTBEFORE:
case SEARCH_SENTON:
case SEARCH_SENTSINCE:
break;
case SEARCH_FROM:
break;
case SEARCH_TO:
break;
case SEARCH_CC:
break;
case SEARCH_BCC:
break;
case SEARCH_SUBJECT:
break;
case SEARCH_IN_REPLY_TO:
break;
case SEARCH_MESSAGE_ID:
break;
default:
return -1;
}
t_push();
/* get field from hopefully cached envelope */
else {
}
ret = -1;
else {
switch (type) {
case SEARCH_SENTBEFORE:
case SEARCH_SENTON:
case SEARCH_SENTSINCE:
default:
}
}
t_pop();
return ret;
}
{
case -1:
/* unknown */
break;
case 0:
break;
default:
break;
}
}
/* Returns >0 = matched, 0 = not matched, -1 = unknown */
{
switch (type) {
/* sizes, only with fastscanning */
case SEARCH_SMALLER:
return -1;
case SEARCH_LARGER:
return -1;
default:
return -1;
}
}
{
case -1:
/* unknown */
break;
case 0:
break;
default:
break;
}
}
/* needle must be uppercased */
const char *needle)
{
const char *n;
if (*needle == '\0')
return TRUE;
if (haystack_len < needle_len)
return FALSE;
for (i = 0; i <= max; i++) {
continue;
for (j = i, n = needle; j < haystack_len; j++) {
if (haystack[j] == '\r') {
if (j+1 != haystack_len)
j++;
}
/* long header continuation */
j++;
}
break;
if (*n == '\0')
return 1;
}
}
return -1;
}
{
const char *value;
int ret;
/* first check that the field name matches to argument. */
case SEARCH_SENTBEFORE:
case SEARCH_SENTON:
case SEARCH_SENTSINCE:
/* date is handled differently than others */
}
return;
case SEARCH_FROM:
return;
break;
case SEARCH_TO:
return;
break;
case SEARCH_CC:
return;
break;
case SEARCH_BCC:
return;
break;
case SEARCH_SUBJECT:
return;
break;
case SEARCH_HEADER:
return;
default:
return;
}
/* then check if the value matches */
}
void *context)
{
}
}
{
const char *p;
return;
/* match */
return;
}
}
}
}
{
}
{
}
{
const unsigned char *data;
/* first get the max. search keyword length */
/* do this in blocks: read data, compare it for all search words, skip
for block size - (strlen(largest_searchword)-1) and continue. */
max_searchword_len-1) > 0) {
}
if (size > 0) {
/* last block */
}
}
{
/* first check what we need to use */
return TRUE;
return FALSE;
if (have_headers) {
/* header checks */
search_header, &ctx);
} else if (rec->header_size == 0) {
} else {
}
if (have_text) {
/* need to rewind back to beginning of headers */
if (!i_buffer_seek(inbuf, 0)) {
i_error("i_buffer_seek() failed: %m");
return FALSE;
}
}
}
/* skip over headers */
}
}
return TRUE;
}
{
unsigned int seq;
while (*set != '\0') {
if (*set == '*') {
set++;
} else {
seq = 0;
set++;
}
}
if (seq != 0) {
}
set++;
}
}
{
/* go through everything */
*first_seq = 1;
return;
}
}
}
unsigned int *first_uid,
unsigned int *last_uid)
{
unsigned int uid;
/* SEEN with 0 seen? */
return FALSE;
/* UNSEEN with all seen? */
return FALSE;
/* UNSEEN with lowwater limiting */
}
/* DELETED with 0 deleted? */
return FALSE;
/* UNDELETED with all deleted? */
return FALSE;
/* DELETED with lowwater limiting */
}
}
}
}
{
unsigned int expunges_before;
seq -= expunges_before;
}
unsigned int *first_uid,
unsigned int *last_uid)
{
/* seq_update() should make sure that these can't happen */
if (first_seq > 1) {
if (uid == 0)
return FALSE;
}
if (uid == 0)
return FALSE;
}
if (*first_uid == 0)
*first_uid = 1;
if (*last_uid == 0)
/* UNSEEN and DELETED in root search level may limit the range */
return FALSE;
return TRUE;
}
{
const ModifyLogExpunge *expunges;
int found;
if (ibox->synced_messages_count == 0)
return TRUE;
/* see if we can limit the records we look at */
return TRUE;
&client_seq);
return TRUE;
expunges++;
}
break;
}
}
if (found) {
}
}
}
return TRUE;
}
{
int failed;
return FALSE;
return mail_storage_set_index_error(ibox);
return mail_storage_set_index_error(ibox);
return !failed;
}