Back to index

courier  0.68.2
Classes | Functions | Variables
search.c File Reference
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <time.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "rfc822/rfc822.h"
#include "rfc822/rfc822hdr.h"
#include "rfc822/rfc2047.h"
#include "rfc2045/rfc2045.h"
#include "unicode/unicode.h"
#include "numlib/numlib.h"
#include "searchinfo.h"
#include "imapwrite.h"
#include "imaptoken.h"
#include "imapscanclient.h"

Go to the source code of this file.

Classes

struct  fill_search_header_info
struct  fill_search_body_info

Functions

time_t rfc822_parsedt (const char *)
int get_flagname (const char *, struct imapflags *)
void get_message_flags (struct imapscanmessageinfo *, char *, struct imapflags *)
int valid_keyword (const char *kw)
static void fill_search_preparse (struct searchinfo *)
static void fill_search_veryquick (struct searchinfo *, unsigned long, struct imapflags *)
static void fill_search_quick (struct searchinfo *, unsigned long, struct stat *)
static void fill_search_header (struct searchinfo *, const char *, struct rfc2045 *, FILE *, struct imapscanmessageinfo *)
static void fill_search_body (struct searchinfo *, struct rfc2045 *, FILE *, struct imapscanmessageinfo *)
static int search_evaluate (struct searchinfo *)
static void search_callback (struct searchinfo *, struct searchinfo *, int, unsigned long, void *)
void dosearch (struct searchinfo *si, struct searchinfo *sihead, const char *charset, int isuid)
static void search_oneatatime (struct searchinfo *si, unsigned long i, struct searchinfo *sihead, const char *charset, int isuid, void(*callback_func)(struct searchinfo *, struct searchinfo *, int, unsigned long, void *), void *voidarg)
static void search_byKeyword (struct searchinfo *tree, struct searchinfo *keyword, struct searchinfo *sihead, const char *charset, int isuid, void(*callback_func)(struct searchinfo *, struct searchinfo *, int, unsigned long, void *), void *voidarg)
void search_internal (struct searchinfo *si, struct searchinfo *sihead, const char *charset, int isuid, void(*callback_func)(struct searchinfo *, struct searchinfo *, int, unsigned long, void *), void *voidarg)
static int is_in_set (const char *msgset, unsigned long n)
static time_t decode_date (char *p)
static time_t timestamp_to_day (time_t t)
static char * timestamp_for_sorting (time_t t)
static int headerfilter_func (const char *name, const char *value, void *arg)
static int fill_search_header_utf8 (const char *, size_t, void *)
static int fill_search_header_done (const char *, void *)
static int fill_search_body_utf8 (const char *str, size_t n, void *arg)
static int fill_search_body_ucs4 (const char *str, size_t n, void *arg)

Variables

char * current_mailbox

Class Documentation

struct fill_search_header_info

Definition at line 630 of file search.c.

Collaboration diagram for fill_search_header_info:
Class Members
struct searchinfo * si
char * utf8buf
size_t utf8buflen
size_t utf8bufsize
struct fill_search_body_info

Definition at line 972 of file search.c.

Collaboration diagram for fill_search_body_info:
Class Members
struct searchinfo * si
libmail_u_convert_handle_t toucs4_handle

Function Documentation

static time_t decode_date ( char *  p) [static]

Definition at line 305 of file search.c.

{
char   *s=malloc(strlen(p)+sizeof(" 00:00:00"));
unsigned        i;
time_t t;

       if (!s)       write_error_exit(0);

        /* Convert to format rfc822_parsedt likes */
 
        for (i=1; p[i] != ' '; i++)
        {
                if (!p[i])  break;
        }
       memcpy(s, p, i);
       strcpy(s+i, " 00:00:00");
       while (i)
       {
              if (s[--i] == '-')
                     s[i]=' ';
       }

       t=rfc822_parsedt(s);
       free(s);
       return (t);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void dosearch ( struct searchinfo si,
struct searchinfo sihead,
const char *  charset,
int  isuid 
)

Definition at line 73 of file search.c.

{
       search_internal(si, sihead, charset, isuid, search_callback, 0);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void fill_search_body ( struct searchinfo si,
struct rfc2045 rfcp,
FILE *  fp,
struct imapscanmessageinfo mi 
) [static]

Definition at line 982 of file search.c.

{
       struct rfc2045src *src;
       struct rfc2045_decodemsgtoutf8_cb decodecb;
       struct fill_search_body_info decodeinfo;
       struct searchinfo *sip;

       src=rfc2045src_init_fd(fileno(fp));

       if (!src)
              return;

       memset(&decodecb, 0, sizeof(decodecb));
       memset(&decodeinfo, 0, sizeof(decodeinfo));

       decodecb.flags=RFC2045_DECODEMSG_NOHEADERS;
       decodecb.output_func=fill_search_body_utf8;
       decodecb.arg=&decodeinfo;

       decodeinfo.si=si;

       if ((decodeinfo.toucs4_handle=
            libmail_u_convert_init("utf-8",
                                libmail_u_ucs4_native,
                                fill_search_body_ucs4,
                                &decodeinfo)) == NULL)
       {
              write_error_exit("libmail_u_convert_init");
       }

       for (sip=decodeinfo.si; sip; sip=sip->next)
              if ((sip->type == search_text || sip->type == search_body)
                  && sip->value <= 0)
              {
                     rfc2045_decodemsgtoutf8(src, rfcp, &decodecb);
                     break;
              }

       libmail_u_convert_deinit(decodeinfo.toucs4_handle, NULL);

       rfc2045src_deinit(src);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int fill_search_body_ucs4 ( const char *  str,
size_t  n,
void *  arg 
) [static]

Definition at line 1035 of file search.c.

{
       struct fill_search_body_info *decodeinfo=
              (struct fill_search_body_info *)arg;
       struct searchinfo *sip;
       const unicode_char *u=(const unicode_char *)str;
       int notfound=1;

       n /= 4;

       for (sip=decodeinfo->si; sip; sip=sip->next)
              if ((sip->type == search_text || sip->type == search_body)
                  && sip->value <= 0)
              {
                     size_t i;

                     notfound=0;

                     for (i=0; i<n; i++)
                     {
                            maildir_search_step_unicode_lc(&sip->sei, u[i]);

                            if (maildir_search_found(&sip->sei))
                            {
                                   sip->value=1;
                                   break;
                            }
                     }
              }

       return notfound;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int fill_search_body_utf8 ( const char *  str,
size_t  n,
void *  arg 
) [static]

Definition at line 1027 of file search.c.

{
       struct fill_search_body_info *decodeinfo=
              (struct fill_search_body_info *)arg;

       return libmail_u_convert(decodeinfo->toucs4_handle, str, n);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void fill_search_header ( struct searchinfo si,
const char *  charset,
struct rfc2045 rfcp,
FILE *  fp,
struct imapscanmessageinfo mi 
) [static]

Definition at line 643 of file search.c.

{
       struct searchinfo *sip;
       struct rfc2045src *src;
       struct rfc2045_decodemsgtoutf8_cb decodecb;
       struct fill_search_header_info decodeinfo;

       /* Consider the following dummy nodes as evaluated */

       for (sip=si; sip; sip=sip->next)
              switch (sip->type) {
              case search_orderedsubj:
              case search_references1:
              case search_references2:
              case search_references3:
              case search_references4:
              case search_cc:
              case search_date:
              case search_from:
              case search_to:
                     sip->value=1;
                     break;
              default:
                     break;
              }

       search_set_charset_conv(si, charset);

       src=rfc2045src_init_fd(fileno(fp));

       if (!src)
              return;

       memset(&decodecb, 0, sizeof(decodecb));
       memset(&decodeinfo, 0, sizeof(decodeinfo));

       decodeinfo.si=si;

       decodecb.flags=RFC2045_DECODEMSG_NOBODY
              | RFC2045_DECODEMSG_NOHEADERNAME;
       decodecb.headerfilter_func=headerfilter_func;
       decodecb.output_func=fill_search_header_utf8;
       decodecb.headerdone_func=fill_search_header_done;
       decodecb.arg=&decodeinfo;

       rfc2045_decodemsgtoutf8(src, rfcp, &decodecb);
       rfc2045src_deinit(src);
       if (decodeinfo.utf8buf)
              free(decodeinfo.utf8buf);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int fill_search_header_done ( const char *  name,
void *  arg 
) [static]

Definition at line 879 of file search.c.

{
       struct fill_search_header_info *decodeinfo=
              (struct fill_search_header_info *)arg;
       struct searchinfo *sip;
       int issubject=rfc822hdr_namecmp(name, "subject");
       size_t j;
       libmail_u_convert_handle_t conv;
       unicode_char *ucptr;
       size_t ucsize;
       int rc;

       if (decodeinfo->utf8buflen &&
           decodeinfo->utf8buf[decodeinfo->utf8buflen-1] == '\n')
              --decodeinfo->utf8buflen;

       fill_search_header_utf8("", 1, arg);

       for (sip=decodeinfo->si; sip; sip=sip->next)
              switch (sip->type) {
              case search_references3:
                     if (issubject == 0 && sip->as == 0)
                     {
                            sip->as=strdup(decodeinfo->utf8buf);
                            if (!sip->as)
                                   write_error_exit(0);
                     }
                     break;
              case search_orderedsubj:

                     if (issubject == 0 && sip->as == 0)
                     {
                            int dummy;

                            sip->as=rfc822_coresubj(decodeinfo->utf8buf,
                                                 &dummy);
                            if (!sip->as)
                                   write_error_exit(0);
                     }
                     break;
              case search_header:

                     if (sip->cs == NULL || rfc822hdr_namecmp(sip->cs, name))
                            break;

                     /* FALLTHRU */

              case search_text:
                     if (sip->value > 0)
                            break;

                     maildir_search_reset(&sip->sei);

                     conv=libmail_u_convert_tou_init("utf-8", &ucptr,
                                                 &ucsize, 0);

                     if (!conv)
                            break;

                     rc=libmail_u_convert(conv, decodeinfo->utf8buf,
                                        decodeinfo->utf8buflen-1);

                     if (libmail_u_convert_deinit(conv, NULL))
                            break;

                     if (rc)
                     {
                            free(ucptr);
                            break;
                     }

                     for (j=0; j<=ucsize; ++j)
                     {
                            maildir_search_step_unicode_lc(&sip->sei,
                                                        j == ucsize
                                                        ? ' ':
                                                        ucptr[j]);
                            if (maildir_search_found(&sip->sei))
                            {
                                   sip->value=1;
                                   break;
                            }
                     }
                     free(ucptr);
                     break;
              default:
                     break;
              }


       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int fill_search_header_utf8 ( const char *  str,
size_t  cnt,
void *  arg 
) [static]

Definition at line 855 of file search.c.

{
       struct fill_search_header_info *decodeinfo=
              (struct fill_search_header_info *)arg;

       if (decodeinfo->utf8bufsize - decodeinfo->utf8buflen < cnt)
       {
              size_t newsize=decodeinfo->utf8buflen + cnt*2;
              char *p=decodeinfo->utf8buf
                     ? realloc(decodeinfo->utf8buf, newsize):
                     malloc(newsize);

              if (!p)
                     write_error_exit(0);
              decodeinfo->utf8buf=p;
              decodeinfo->utf8bufsize=newsize;
       }

       if (cnt)
              memcpy(decodeinfo->utf8buf+decodeinfo->utf8buflen, str, cnt);
       decodeinfo->utf8buflen += cnt;
       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void fill_search_preparse ( struct searchinfo p) [static]

Definition at line 362 of file search.c.

{
       switch (p->type) {
       case search_msgflag:
              {
                     struct imapflags flags;

                     memset(&flags, 0, sizeof(flags));
                     p->ke=NULL;

                     if (get_flagname(p->as, &flags) == 0)
                     {
                            p->bs=malloc(sizeof(flags));

                            if (!p->bs)
                                   write_error_exit(0);

                            memcpy(p->bs, &flags, sizeof(flags));
                     }
              }
              break;

       case search_msgkeyword:
              p->ke=NULL;
              if (valid_keyword(p->as))
                     p->ke=libmail_kweFind(current_maildir_info
                                          .keywordList,
                                          p->as, 0);
              break;
       default:
              break;
       }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void fill_search_quick ( struct searchinfo p,
unsigned long  msgnum,
struct stat stat_buf 
) [static]

Definition at line 470 of file search.c.

{
       switch (p->type)     {
       case search_before:
              p->value=0;
              {
              time_t t=decode_date(p->as);

                     if (t && timestamp_to_day(stat_buf->st_mtime) < t)
                            p->value=1;
              }
              break;
       case search_since:
              p->value=0;
              {
              time_t t=decode_date(p->as);

                     if (t && timestamp_to_day(stat_buf->st_mtime) >= t)
                            p->value=1;
              }
              break;
       case search_on:
              p->value=0;
              {
              time_t t=decode_date(p->as);

                     if (t && timestamp_to_day(stat_buf->st_mtime) == t)
                            p->value=1;
              }
              break;
       case search_smaller:
              p->value=0;
              {
              unsigned long n;

                     if (sscanf(p->as, "%lu", &n) > 0 &&
                            stat_buf->st_size < n)
                            p->value=1;
              }
              break;
       case search_larger:
              p->value=0;
              {
              unsigned long n;

                     if (sscanf(p->as, "%lu", &n) > 0 &&
                            stat_buf->st_size > n)
                            p->value=1;
              }
              break;
       case search_orderedsubj:
       case search_references1:
       case search_references2:
       case search_references3:
       case search_references4:
       case search_arrival:
       case search_cc:
       case search_date:
       case search_from:
       case search_reverse:
       case search_size:
       case search_to:

              /* DUMMY nodes for SORT/THREAD.  Make sure that the
              ** dummy node is CLEARed */

              if (p->as)
              {
                     free(p->as);
                     p->as=0;
              }

              if (p->bs)
              {
                     free(p->bs);
                     p->bs=0;
              }

              switch (p->type)     {
              case search_arrival:
                     p->as=timestamp_for_sorting(stat_buf->st_mtime);
                     p->value=1;
                     break;
              case search_size:
                     {
                     char   buf[NUMBUFSIZE], buf2[NUMBUFSIZE];
                     char *q;

                            libmail_str_size_t(stat_buf->st_size, buf);
                            sprintf(buf2, "%*s", (int)(sizeof(buf2)-1), buf);
                            for (q=buf2; *q == ' '; *q++='0')
                                   ;
                            p->as=my_strdup(buf2);
                            p->value=1;
                     }
                     break;
              default:
                     break;
              }
              break;
       default:
              break;
       }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void fill_search_veryquick ( struct searchinfo p,
unsigned long  msgnum,
struct imapflags flags 
) [static]

Definition at line 398 of file search.c.

{
       switch (p->type) {
       case search_msgflag:
              {
                     struct imapflags *f=(struct imapflags *)p->bs;

                     p->value=0;
                     if (strcmp(p->as, "\\RECENT") == 0 &&
                            current_maildir_info.msgs[msgnum].recentflag)
                            p->value=1;

                     if (f)
                     {
                            if (f->seen && flags->seen)
                                   p->value=1;
                            if (f->answered && flags->answered)
                                   p->value=1;
                            if (f->deleted && flags->deleted)
                                   p->value=1;
                            if (f->flagged && flags->flagged)
                                   p->value=1;
                            if (f->drafts && flags->drafts)
                                   p->value=1;
                     }
                     break;
              }

       case search_msgkeyword:
              p->value=0;
              if (p->ke)
              {
                     struct libmail_kwMessage *km=
                            current_maildir_info.msgs[msgnum]
                            .keywordMsg;
                     struct libmail_kwMessageEntry *kme;

                     for (kme=km ? km->firstEntry:NULL;
                          kme; kme=kme->next)
                            if (strcasecmp(keywordName(kme->
                                                    libmail_keywordEntryPtr),
                                          keywordName(p->ke))==0)
                            {
                                   p->value=1;
                                   break;
                            }
              }
              break;
       case search_messageset:
              if (is_in_set(p->as, msgnum+1))
                     p->value=1;
              else
                     p->value=0;
              break;
       case search_all:
              p->value=1;
              break;
       case search_uid:
              if (is_in_set(p->as, current_maildir_info.msgs[msgnum].uid))
                     p->value=1;
              else
                     p->value=0;
              break;
       case search_reverse:
              p->value=1;
              break;
       default:
              break;
       }
}

Here is the call graph for this function:

Here is the caller graph for this function:

int get_flagname ( const char *  ,
struct imapflags  
)

Definition at line 417 of file imapd.c.

{
       if (strcasecmp(p, "\\SEEN") == 0)
              flags->seen=1;
       else if (strcasecmp(p, "\\ANSWERED") == 0)
              flags->answered=1;
       else if (strcasecmp(p, "\\DRAFT") == 0)
              flags->drafts=1;
       else if (strcasecmp(p, "\\DELETED") == 0)
              flags->deleted=1;
       else if (strcasecmp(p, "\\FLAGGED") == 0)
              flags->flagged=1;
       else return (-1);
       return (0);
}
void get_message_flags ( struct imapscanmessageinfo ,
char *  ,
struct imapflags  
)

Definition at line 479 of file imapd.c.

{
       const char *filename=mi->filename;

       const char *DRAFT="\\Draft";
       const char *FLAGGED="\\Flagged";
       const char *REPLIED="\\Answered";
       const char *SEEN="\\Seen";
       const char *DELETED="\\Deleted";
       const char *RECENT="\\Recent";

       const char *SPC=" ";

       if (buf)
              *buf=0;

       if (flags)
              flags->seen=flags->answered=flags->deleted=flags->flagged
              =flags->recent=flags->drafts=0;

       if ((filename=strrchr(filename, MDIRSEP[0])) == 0
              || strncmp(filename, MDIRSEP "2,", 3))    return;

#if SMAP
       if (smapflag)
       {
              SPC=",";
              DRAFT="DRAFT";
              FLAGGED="MARKED";
              REPLIED="REPLIED";
              SEEN="SEEN";
              DELETED="DELETED";
              RECENT="RECENT";
       }
#endif

       if (strchr(filename, 'D'))
       {
              if (buf) strcat(buf, DRAFT);
              if (flags)  flags->drafts=1;
       }

       if (strchr(filename, 'F'))
       {
              if (buf) strcat(strcat(buf, *buf ? SPC:""), FLAGGED);
              if (flags)    flags->flagged=1;
       }
       if (strchr(filename, 'R'))
       {
              if (buf) strcat(strcat(buf, *buf ? SPC:""), REPLIED);
              if (flags)    flags->answered=1;
       }

       if (strchr(filename, 'S') != NULL)
       {
              if (buf) strcat(strcat(buf, *buf ? SPC:""), SEEN);
              if (flags)    flags->seen=1;
       }

       if (strchr(filename, 'T'))
       {
              if (buf) strcat(strcat(buf, *buf ? SPC:""), DELETED);
              if (flags)    flags->deleted=1;
       }

       if (mi->recentflag)
       {
              if (flags) flags->recent=1;
              if (buf) strcat(strcat(buf, *buf ? SPC:""), RECENT);
       }
}
static int headerfilter_func ( const char *  name,
const char *  value,
void *  arg 
) [static]

Definition at line 697 of file search.c.

{
       struct fill_search_header_info *decodeinfo=
              (struct fill_search_header_info *)arg;
       struct searchinfo *sip;
       const char *p;
       int isto=rfc822hdr_namecmp(name, "to");
       int iscc=rfc822hdr_namecmp(name, "cc");
       int isfrom=rfc822hdr_namecmp(name, "from");
       int isinreplyto=rfc822hdr_namecmp(name, "in-reply-to");
       int isdate=rfc822hdr_namecmp(name, "date");

       int isreferences=rfc822hdr_namecmp(name, "references");
       int ismessageid=rfc822hdr_namecmp(name, "message-id");

       for (sip=decodeinfo->si; sip; sip=sip->next)
       {
              if (sip->type == search_text && sip->value <= 0)
              {
                     /*
                     ** Full message search. Reset the search engine,
                     ** feed it "Headername: "
                     */

                     maildir_search_reset(&sip->sei);

                     for (p=name; *p; p++)
                     {
                            maildir_search_step_unicode_lc(&sip->sei,
                                                        (unsigned char)
                                                        *p);
                            if (maildir_search_found(&sip->sei))
                                   sip->value=1;
                     }
                     for (p=": "; *p; p++)
                     {
                            maildir_search_step_unicode_lc(&sip->sei,
                                                        (unsigned char)
                                                        *p);
                            if (maildir_search_found(&sip->sei))
                                   sip->value=1;
                     }
              }

              if ( (sip->type == search_cc && iscc == 0 && sip->as == 0)
                   ||
                   (sip->type == search_from && isfrom == 0 && sip->as == 0)
                   ||
                   (sip->type == search_to && isto == 0 && sip->as == 0)
                   ||
                   (sip->type == search_references1 && isinreplyto == 0
                    && sip->bs == 0))
              {
                     struct rfc822t *t;
                     struct rfc822a *a;
                     char *s;

                     t=rfc822t_alloc_new(value, NULL, NULL);
                     if (!t) write_error_exit(0);
                     a=rfc822a_alloc(t);
                     if (!a) write_error_exit(0);
                     s=a->naddrs > 0 ? rfc822_getaddr(a, 0):strdup("");
                     rfc822a_free(a);
                     rfc822t_free(t);
                     if (!s) write_error_exit(0);

                     if (sip->type == search_references1)
                     {
                            sip->bs=malloc(strlen(s)+3);
                            if (!sip->bs)
                                   write_error_exit(0);
                            strcat(strcat(strcpy(sip->bs, "<"), s), ">");
                            free(s);
                     }
                     else
                            sip->as=s;
              }

              switch (sip->type) {
              case search_orderedsubj:

                     if (isdate == 0 && sip->bs == 0)
                     {
                            sip->bs=strdup(value);
                            if (!sip->bs)
                                   write_error_exit(0);
                     }
                     break;

              case search_date:

                     if (isdate == 0 && sip->as == 0)
                     {
                            time_t msg_time=rfc822_parsedt(value);

                            sip->as=timestamp_for_sorting(msg_time);
                     }
                     break;

              case search_sentbefore:
              case search_sentsince:
              case search_senton:

                     if (sip->value > 0)
                            break;

                     if (isdate == 0)
                     {
                            time_t given_time=decode_date(sip->as);
                            time_t msg_time=rfc822_parsedt(value);

                            if (given_time == 0 || msg_time == 0)
                                   break;

                            msg_time=timestamp_to_day(msg_time);
                            sip->value=0;
                            if ((sip->type == search_sentbefore &&
                                   msg_time < given_time) ||
                                   (sip->type == search_sentsince&&
                                          msg_time>=given_time)||
                                   (sip->type == search_senton &&
                                          msg_time == given_time))
                                   sip->value=1;
                     }
                     break;

              case search_references1:
                     if (isreferences == 0 && sip->as == 0)
                     {
                            sip->as=strdup(value);
                            if (!sip->as)
                                   write_error_exit(0);
                     }
                     break;
              case search_references2:
                     if (isdate == 0 && sip->as == 0)
                     {
                            sip->as=strdup(value);
                            if (!sip->as)
                                   write_error_exit(0);
                     }
                     break;
              case search_references4:
                     if (ismessageid == 0 && sip->as == 0)
                     {
                            sip->as=strdup(value);
                            if (!sip->as)
                                   write_error_exit(0);
                     }
                     break;
              default:
                     break;
              }
       }
       decodeinfo->utf8buflen=0;
       return 1;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int is_in_set ( const char *  msgset,
unsigned long  n 
) [static]

Definition at line 259 of file search.c.

{
unsigned long i, j;

       while (isdigit((int)(unsigned char)*msgset))
       {
              i=0;
              while (isdigit((int)(unsigned char)*msgset))
              {
                     i=i*10 + (*msgset++-'0');
              }
              if (*msgset != ':')
                     j=i;
              else
              {
                     j=0;
                     ++msgset;
                     if (*msgset == '*')
                     {
                            ++msgset;
                            /*
                            ** Ok, we don't really need to know the upper
                            ** end, just hack it.
                            */
                            j=i;
                            if (j < n)
                                   j=n;
                     }
                     else
                            while (isdigit((int)(unsigned char)*msgset))
                            {
                                   j=j*10 + (*msgset++-'0');
                            }
              }
              if (n >= i && n <= j)       return (1);
              if (*msgset == 0 || *msgset++ != ',')     break;
       }
       return (0);
}

Here is the caller graph for this function:

time_t rfc822_parsedt ( const char *  )

Definition at line 125 of file rfc822_parsedt.c.

{
unsigned day=0, mon=0, year;
int secs;
int offset;
time_t t;
unsigned y;

       /* Ignore day of the week.  Tolerate "Tue, 25 Feb 1997 ... "
       ** without the comma.  Tolerate "Feb 25 1997 ...".
       */

       while (!day || !mon)
       {
              if (!*rfcdt)  return (0);
              if (my_isalpha(*rfcdt))
              {
                     if (mon)      return (0);
                     mon=parsekey(&rfcdt, mnames);
                     if (!mon)
                            while (*rfcdt && my_isalpha(*rfcdt))
                                   ++rfcdt;
                     continue;
              }

              if (my_isdigit(*rfcdt))
              {
                     if (day)      return (0);
                     day=parsedig(&rfcdt);
                     if (!day)     return (0);
                     continue;
              }
              ++rfcdt;
       }

       while (*rfcdt && my_isspace(*rfcdt))
              ++rfcdt;
       if (!my_isdigit(*rfcdt))    return (0);
       year=parsedig(&rfcdt);
       if (year < 70)       year += 2000;
       if (year < 100)      year += 1900;

       while (*rfcdt && my_isspace(*rfcdt))
              ++rfcdt;

       if (day == 0 || mon == 0 || mon > 12 || day > mdays(mon,year))
              return (0);

       secs=parsetime(&rfcdt);
       if (secs < 0) return (0);

       offset=0;

       /* RFC822 sez no parenthesis, but I've seen (EST) */

       while ( *rfcdt )
       {
              if (my_isalnum(*rfcdt) || *rfcdt == '+' || *rfcdt == '-')
                     break;
              ++rfcdt;
       }

       if (my_isalpha((int)(unsigned char)*rfcdt))
       {
       int    n=parsekey(&rfcdt, zonenames);

              if (n > 0)    offset= zoneoffset[n-1];
       }
       else
       {
       int    sign=1;
       unsigned n;

              switch (*rfcdt)      {
              case '-':
                     sign= -1;
              case '+':
                     ++rfcdt;
              }

              if (my_isdigit(*rfcdt))
              {
                     n=parsedig(&rfcdt);
                     if (n > 2359 || (n % 100) > 59)    n=0;
                     offset = sign * ( (n % 100) * 60 + n / 100 * 60 * 60);
              }
       }

       if (year < 1970)     return (0);
       if (year > 9999)     return (0);

       t=0;
       for (y=1970; y<year; y++)
       {
              if ( leap(y) )
              {
                     if (year-y >= 4)
                     {
                            y += 3;
                            t += ( 365*3+366 ) * 24 * 60 * 60;
                            continue;
                     }
                     t += 24 * 60 * 60;
              }
              t += 365 * 24 * 60 * 60;
       }

       for (y=1; y < mon; y++)
              t += mdays(y, year) * 24 * 60 * 60;

       return ( t + (day-1) * 24 * 60 * 60 + secs - offset );
}
static void search_byKeyword ( struct searchinfo tree,
struct searchinfo keyword,
struct searchinfo sihead,
const char *  charset,
int  isuid,
void(*)(struct searchinfo *, struct searchinfo *, int, unsigned long, void *)  callback_func,
void *  voidarg 
) [static]

Definition at line 132 of file search.c.

{
       struct libmail_kwMessageEntry *kme;

       for (kme=keyword->ke->firstMsg; kme; kme=kme->keywordNext)
       {
              unsigned long n=kme->libmail_kwMessagePtr->u.userNum;
              if (!tree)
              {
                     (*callback_func)(keyword, keyword, isuid, n, voidarg);
                     continue;
              }

              search_oneatatime(tree, n, sihead, charset, isuid,
                              callback_func, voidarg);
       }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void search_callback ( struct searchinfo si,
struct searchinfo sihead,
int  isuid,
unsigned long  i,
void *  dummy 
) [static]

Definition at line 79 of file search.c.

{
       writes(" ");
       writen(isuid ? current_maildir_info.msgs[i].uid:i+1);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int search_evaluate ( struct searchinfo si) [static]

Definition at line 582 of file search.c.

{
int    rc, rc2;

       switch (si->type)    {
       case search_orderedsubj:    /* DUMMIES for THREAD and SORT */
       case search_references1:
       case search_references2:
       case search_references3:
       case search_references4:
        case search_arrival:
        case search_cc:
        case search_date:
        case search_from:
        case search_reverse:
        case search_size:
        case search_to:
              rc = search_evaluate(si->a);
              if (rc == 0) return 0;
              if (si->value < 0)  return (-1);
              break;
       case search_not:
              rc=search_evaluate(si->a);
              if (rc >= 0)  rc= 1-rc;
              break;
       case search_and:
              rc=search_evaluate(si->a);
              rc2=search_evaluate(si->b);

              rc=  rc > 0 && rc2 > 0 ? 1:
                     rc == 0 || rc2 == 0 ? 0:-1;
              break;
       case search_or:
              rc=search_evaluate(si->a);
              rc2=search_evaluate(si->b);

              rc=  rc > 0 || rc2 > 0 ? 1:
                     rc == 0 && rc2 == 0 ? 0:-1;
              break;
       default:
              rc=si->value;
              break;
       }
       return (rc);
}

Here is the caller graph for this function:

void search_internal ( struct searchinfo si,
struct searchinfo sihead,
const char *  charset,
int  isuid,
void(*)(struct searchinfo *, struct searchinfo *, int, unsigned long, void *)  callback_func,
void *  voidarg 
)

Definition at line 104 of file search.c.

{
       unsigned long i;
       struct searchinfo *p;

       for (p=sihead; p; p=p->next)
              fill_search_preparse(p);

       /* Shortcuts for keyword-based searches */

       if (si->type == search_msgkeyword && si->bs == NULL && si->ke)
              search_byKeyword(NULL, si, sihead, charset, isuid,
                            callback_func, voidarg);
       else if (si->type == search_and &&
               si->a->type == search_msgkeyword && si->a->bs == NULL
               && si->a->ke)
              search_byKeyword(si->b, si->a, sihead, charset, isuid,
                            callback_func, voidarg);
       else for (i=0; i<current_maildir_info.nmessages; i++)
              search_oneatatime(si, i, sihead, charset, isuid,
                              callback_func, voidarg);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void search_oneatatime ( struct searchinfo si,
unsigned long  i,
struct searchinfo sihead,
const char *  charset,
int  isuid,
void(*)(struct searchinfo *, struct searchinfo *, int, unsigned long, void *)  callback_func,
void *  voidarg 
) [static]

Definition at line 161 of file search.c.

{
struct searchinfo *p;
struct imapflags     flags;
int    fd;
FILE   *fp;
struct stat   stat_buf;
int    rc;

       {
              for (p=sihead; p; p=p->next)
                     p->value= -1; /* Search result unknown */

              /* First, see if non-content search will be sufficient */

              get_message_flags(current_maildir_info.msgs+i, 0, &flags);

              for (p=sihead; p; p=p->next)
                     fill_search_veryquick(p, i, &flags);

              if ((rc=search_evaluate(si)) >= 0)
              {
                     if (rc > 0)
                            (*callback_func)(si, sihead, isuid, i,
                                           voidarg);
                     return;
              }

              fd=imapscan_openfile(current_mailbox,
                     &current_maildir_info, i);
              if (fd < 0)   return;

              if ((fp=fdopen(fd, "r")) == 0)
                     write_error_exit(0);

              if (fstat(fileno(fp), &stat_buf))
              {
                     fclose(fp);
                     return;
              }

              /* First, see if non-content search will be sufficient */

              for (p=sihead; p; p=p->next)
                     fill_search_quick(p, i, &stat_buf);

              if ((rc=search_evaluate(si)) < 0)
              {
                     /* No, search the headers then */
                        /* struct        rfc2045 *rfcp=rfc2045_fromfp(fp); */
                        struct        rfc2045 *rfcp=rfc2045header_fromfp(fp); 

                     fill_search_header(sihead, charset, rfcp, fp,
                                      current_maildir_info.msgs+i);
                     rc=search_evaluate(si);
                        rfc2045_free(rfcp); 

                     if (rc < 0)
                     {
                            /* Ok, search message contents */
                                struct        rfc2045 *rfcp=rfc2045_fromfp(fp);

                            fill_search_body(sihead, rfcp, fp,
                                           current_maildir_info.msgs+i);

                            /*
                            ** If there are still UNKNOWN nodes, change
                            ** them to fail.
                            */

                            for (p=sihead; p; p=p->next)
                                   if (p->value < 0)
                                          p->value=0;

                            rc=search_evaluate(si);
                                rfc2045_free(rfcp);
                     }
                        /* rfc2045_free(rfcp); */
              }

              if (rc > 0)
              {
                     (*callback_func)(si, sihead, isuid, i, voidarg);
              }
              fclose(fp);
              close(fd);
       }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static char* timestamp_for_sorting ( time_t  t) [static]

Definition at line 351 of file search.c.

{
struct tm *tm=localtime(&t);
char   buf[200];

       buf[0]=0;
       if ( strftime(buf, sizeof(buf), "%Y.%m.%d.%H.%M.%S", tm) == 0)
              buf[0]=0;
       return (my_strdup(buf));
}

Here is the call graph for this function:

Here is the caller graph for this function:

static time_t timestamp_to_day ( time_t  t) [static]

Definition at line 336 of file search.c.

{
char   buf1[60], buf2[80];

       rfc822_mkdate_buf(t, buf1); /* Converts to local time */
       (void)strtok(buf1, " ");    /* Skip weekday */
       strcpy(buf2, strtok(0, " "));
       strcat(buf2, " ");
       strcat(buf2, strtok(0, " "));
       strcat(buf2, " ");
       strcat(buf2, strtok(0, " "));
       strcat(buf2, " 00:00:00");
       return (rfc822_parsedt(buf2));
}

Here is the call graph for this function:

Here is the caller graph for this function:

int valid_keyword ( const char *  kw)

Definition at line 433 of file imapd.c.

{
       const char *p;

       if (!keywords())
              return 0;

       /* Check for valid keyword names */

       for (p=kw; *p; p++)
       {
              if ((unsigned char)*p <= ' '
                  || strchr(KEYWORD_IMAPVERBOTTEN, *p))
                     return 0;
       }
       return 1;
}

Variable Documentation

Definition at line 124 of file imapd.c.