X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=citadel%2Fmodules%2Fimap%2Fimap_search.c;h=efc19920274401a412b275376c29a705af801c6f;hb=7a9b0685e406cc83597171cc39d008c7e5459ca8;hp=9fe72051355b526dbaa665e32af5228631ee1a17;hpb=2b6008f54e8b56b79e24617f47308e469fcaca0e;p=citadel.git diff --git a/citadel/modules/imap/imap_search.c b/citadel/modules/imap/imap_search.c index 9fe720513..efc199202 100644 --- a/citadel/modules/imap/imap_search.c +++ b/citadel/modules/imap/imap_search.c @@ -1,24 +1,15 @@ /* - * $Id$ - * * Implements IMAP's gratuitously complex SEARCH command. * + * Copyright (c) 2001-2020 by the citadel.org team * - * Copyright (c) 2001-2009 by the citadel.org team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. + * This program is open source software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. */ #include "ctdl_module.h" @@ -33,18 +24,7 @@ #include #include #include - -#if TIME_WITH_SYS_TIME -# include -# include -#else -# if HAVE_SYS_TIME_H -# include -# else -# include -# endif -#endif - +#include #include #include #include @@ -57,12 +37,11 @@ #include "support.h" #include "config.h" #include "user_ops.h" -#include "policy.h" #include "database.h" #include "msgbase.h" #include "internet_addressing.h" -#include "imap_tools.h" #include "serv_imap.h" +#include "imap_tools.h" #include "imap_fetch.h" #include "imap_search.h" #include "genstamp.h" @@ -80,6 +59,7 @@ int imap_do_search_msg(int seq, struct CtdlMessage *supplied_msg, int num_items, ConstStr *itemlist, int is_uid) { + citimap *Imap = IMAP; int match = 0; int is_not = 0; int is_or = 0; @@ -116,7 +96,7 @@ int imap_do_search_msg(int seq, struct CtdlMessage *supplied_msg, } else if (!strcasecmp(itemlist[pos].Key, "ANSWERED")) { - if (IMAP->flags[seq-1] & IMAP_ANSWERED) { + if (Imap->flags[seq-1] & IMAP_ANSWERED) { match = 1; } ++pos; @@ -124,11 +104,11 @@ int imap_do_search_msg(int seq, struct CtdlMessage *supplied_msg, else if (!strcasecmp(itemlist[pos].Key, "BCC")) { if (msg == NULL) { - msg = CtdlFetchMessage(IMAP->msgids[seq-1], 1); + msg = CtdlFetchMessage(Imap->msgids[seq-1], 1); need_to_free_msg = 1; } if (msg != NULL) { - fieldptr = rfc822_fetch_field(msg->cm_fields['M'], "Bcc"); + fieldptr = rfc822_fetch_field(msg->cm_fields[eMesageText], "Bcc"); if (fieldptr != NULL) { if (bmstrcasestr(fieldptr, itemlist[pos+1].Key)) { match = 1; @@ -141,13 +121,13 @@ int imap_do_search_msg(int seq, struct CtdlMessage *supplied_msg, else if (!strcasecmp(itemlist[pos].Key, "BEFORE")) { if (msg == NULL) { - msg = CtdlFetchMessage(IMAP->msgids[seq-1], 1); + msg = CtdlFetchMessage(Imap->msgids[seq-1], 1); need_to_free_msg = 1; } if (msg != NULL) { - if (msg->cm_fields['T'] != NULL) { + if (!CM_IsEmpty(msg, eTimestamp)) { if (imap_datecmp(itemlist[pos+1].Key, - atol(msg->cm_fields['T'])) < 0) { + atol(msg->cm_fields[eTimestamp])) < 0) { match = 1; } } @@ -160,18 +140,18 @@ int imap_do_search_msg(int seq, struct CtdlMessage *supplied_msg, /* If fulltext indexing is active, on this server, * all messages have already been qualified. */ - if (config.c_enable_fulltext) { + if (CtdlGetConfigInt("c_enable_fulltext")) { match = 1; } /* Otherwise, we have to do a slow search. */ else { if (msg == NULL) { - msg = CtdlFetchMessage(IMAP->msgids[seq-1], 1); + msg = CtdlFetchMessage(Imap->msgids[seq-1], 1); need_to_free_msg = 1; } if (msg != NULL) { - if (bmstrcasestr(msg->cm_fields['M'], itemlist[pos+1].Key)) { + if (bmstrcasestr(msg->cm_fields[eMesageText], itemlist[pos+1].Key)) { match = 1; } } @@ -182,18 +162,18 @@ int imap_do_search_msg(int seq, struct CtdlMessage *supplied_msg, else if (!strcasecmp(itemlist[pos].Key, "CC")) { if (msg == NULL) { - msg = CtdlFetchMessage(IMAP->msgids[seq-1], 1); + msg = CtdlFetchMessage(Imap->msgids[seq-1], 1); need_to_free_msg = 1; } if (msg != NULL) { - fieldptr = msg->cm_fields['Y']; + fieldptr = msg->cm_fields[eCarbonCopY]; if (fieldptr != NULL) { if (bmstrcasestr(fieldptr, itemlist[pos+1].Key)) { match = 1; } } else { - fieldptr = rfc822_fetch_field(msg->cm_fields['M'], "Cc"); + fieldptr = rfc822_fetch_field(msg->cm_fields[eMesageText], "Cc"); if (fieldptr != NULL) { if (bmstrcasestr(fieldptr, itemlist[pos+1].Key)) { match = 1; @@ -206,21 +186,21 @@ int imap_do_search_msg(int seq, struct CtdlMessage *supplied_msg, } else if (!strcasecmp(itemlist[pos].Key, "DELETED")) { - if (IMAP->flags[seq-1] & IMAP_DELETED) { + if (Imap->flags[seq-1] & IMAP_DELETED) { match = 1; } ++pos; } else if (!strcasecmp(itemlist[pos].Key, "DRAFT")) { - if (IMAP->flags[seq-1] & IMAP_DRAFT) { + if (Imap->flags[seq-1] & IMAP_DRAFT) { match = 1; } ++pos; } else if (!strcasecmp(itemlist[pos].Key, "FLAGGED")) { - if (IMAP->flags[seq-1] & IMAP_FLAGGED) { + if (Imap->flags[seq-1] & IMAP_FLAGGED) { match = 1; } ++pos; @@ -228,14 +208,14 @@ int imap_do_search_msg(int seq, struct CtdlMessage *supplied_msg, else if (!strcasecmp(itemlist[pos].Key, "FROM")) { if (msg == NULL) { - msg = CtdlFetchMessage(IMAP->msgids[seq-1], 1); + msg = CtdlFetchMessage(Imap->msgids[seq-1], 1); need_to_free_msg = 1; } if (msg != NULL) { - if (bmstrcasestr(msg->cm_fields['A'], itemlist[pos+1].Key)) { + if (bmstrcasestr(msg->cm_fields[eAuthor], itemlist[pos+1].Key)) { match = 1; } - if (bmstrcasestr(msg->cm_fields['F'], itemlist[pos+1].Key)) { + if (bmstrcasestr(msg->cm_fields[erFc822Addr], itemlist[pos+1].Key)) { match = 1; } } @@ -250,18 +230,16 @@ int imap_do_search_msg(int seq, struct CtdlMessage *supplied_msg, * examining the message body. */ if (msg == NULL) { - msg = CtdlFetchMessage(IMAP->msgids[seq-1], 1); + msg = CtdlFetchMessage(Imap->msgids[seq-1], 1); need_to_free_msg = 1; } if (msg != NULL) { - CC->redirect_buffer = malloc(SIZ); - CC->redirect_len = 0; - CC->redirect_alloc = SIZ; + CC->redirect_buffer = NewStrBufPlain(NULL, SIZ); CtdlOutputPreLoadedMsg(msg, MT_RFC822, HEADERS_FAST, 0, 1, 0); - fieldptr = rfc822_fetch_field(CC->redirect_buffer, itemlist[pos+1].Key); + fieldptr = rfc822_fetch_field(ChrPtr(CC->redirect_buffer), itemlist[pos+1].Key); if (fieldptr != NULL) { if (bmstrcasestr(fieldptr, itemlist[pos+2].Key)) { match = 1; @@ -269,10 +247,7 @@ int imap_do_search_msg(int seq, struct CtdlMessage *supplied_msg, free(fieldptr); } - free(CC->redirect_buffer); - CC->redirect_buffer = NULL; - CC->redirect_len = 0; - CC->redirect_alloc = 0; + FreeStrBuf(&CC->redirect_buffer); } pos += 3; /* Yes, three */ @@ -285,11 +260,11 @@ int imap_do_search_msg(int seq, struct CtdlMessage *supplied_msg, else if (!strcasecmp(itemlist[pos].Key, "LARGER")) { if (msg == NULL) { - msg = CtdlFetchMessage(IMAP->msgids[seq-1], 1); + msg = CtdlFetchMessage(Imap->msgids[seq-1], 1); need_to_free_msg = 1; } if (msg != NULL) { - if (strlen(msg->cm_fields['M']) > atoi(itemlist[pos+1].Key)) { + if (msg->cm_lengths[eMesageText] > atoi(itemlist[pos+1].Key)) { match = 1; } } @@ -297,14 +272,14 @@ int imap_do_search_msg(int seq, struct CtdlMessage *supplied_msg, } else if (!strcasecmp(itemlist[pos].Key, "NEW")) { - if ( (IMAP->flags[seq-1] & IMAP_RECENT) && (!(IMAP->flags[seq-1] & IMAP_SEEN))) { + if ( (Imap->flags[seq-1] & IMAP_RECENT) && (!(Imap->flags[seq-1] & IMAP_SEEN))) { match = 1; } ++pos; } else if (!strcasecmp(itemlist[pos].Key, "OLD")) { - if (!(IMAP->flags[seq-1] & IMAP_RECENT)) { + if (!(Imap->flags[seq-1] & IMAP_RECENT)) { match = 1; } ++pos; @@ -312,13 +287,13 @@ int imap_do_search_msg(int seq, struct CtdlMessage *supplied_msg, else if (!strcasecmp(itemlist[pos].Key, "ON")) { if (msg == NULL) { - msg = CtdlFetchMessage(IMAP->msgids[seq-1], 1); + msg = CtdlFetchMessage(Imap->msgids[seq-1], 1); need_to_free_msg = 1; } if (msg != NULL) { - if (msg->cm_fields['T'] != NULL) { + if (!CM_IsEmpty(msg, eTimestamp)) { if (imap_datecmp(itemlist[pos+1].Key, - atol(msg->cm_fields['T'])) == 0) { + atol(msg->cm_fields[eTimestamp])) == 0) { match = 1; } } @@ -327,14 +302,14 @@ int imap_do_search_msg(int seq, struct CtdlMessage *supplied_msg, } else if (!strcasecmp(itemlist[pos].Key, "RECENT")) { - if (IMAP->flags[seq-1] & IMAP_RECENT) { + if (Imap->flags[seq-1] & IMAP_RECENT) { match = 1; } ++pos; } else if (!strcasecmp(itemlist[pos].Key, "SEEN")) { - if (IMAP->flags[seq-1] & IMAP_SEEN) { + if (Imap->flags[seq-1] & IMAP_SEEN) { match = 1; } ++pos; @@ -342,13 +317,13 @@ int imap_do_search_msg(int seq, struct CtdlMessage *supplied_msg, else if (!strcasecmp(itemlist[pos].Key, "SENTBEFORE")) { if (msg == NULL) { - msg = CtdlFetchMessage(IMAP->msgids[seq-1], 1); + msg = CtdlFetchMessage(Imap->msgids[seq-1], 1); need_to_free_msg = 1; } if (msg != NULL) { - if (msg->cm_fields['T'] != NULL) { + if (!CM_IsEmpty(msg, eTimestamp)) { if (imap_datecmp(itemlist[pos+1].Key, - atol(msg->cm_fields['T'])) < 0) { + atol(msg->cm_fields[eTimestamp])) < 0) { match = 1; } } @@ -358,13 +333,13 @@ int imap_do_search_msg(int seq, struct CtdlMessage *supplied_msg, else if (!strcasecmp(itemlist[pos].Key, "SENTON")) { if (msg == NULL) { - msg = CtdlFetchMessage(IMAP->msgids[seq-1], 1); + msg = CtdlFetchMessage(Imap->msgids[seq-1], 1); need_to_free_msg = 1; } if (msg != NULL) { - if (msg->cm_fields['T'] != NULL) { + if (!CM_IsEmpty(msg, eTimestamp)) { if (imap_datecmp(itemlist[pos+1].Key, - atol(msg->cm_fields['T'])) == 0) { + atol(msg->cm_fields[eTimestamp])) == 0) { match = 1; } } @@ -374,13 +349,13 @@ int imap_do_search_msg(int seq, struct CtdlMessage *supplied_msg, else if (!strcasecmp(itemlist[pos].Key, "SENTSINCE")) { if (msg == NULL) { - msg = CtdlFetchMessage(IMAP->msgids[seq-1], 1); + msg = CtdlFetchMessage(Imap->msgids[seq-1], 1); need_to_free_msg = 1; } if (msg != NULL) { - if (msg->cm_fields['T'] != NULL) { + if (!CM_IsEmpty(msg, eTimestamp)) { if (imap_datecmp(itemlist[pos+1].Key, - atol(msg->cm_fields['T'])) >= 0) { + atol(msg->cm_fields[eTimestamp])) >= 0) { match = 1; } } @@ -390,13 +365,13 @@ int imap_do_search_msg(int seq, struct CtdlMessage *supplied_msg, else if (!strcasecmp(itemlist[pos].Key, "SINCE")) { if (msg == NULL) { - msg = CtdlFetchMessage(IMAP->msgids[seq-1], 1); + msg = CtdlFetchMessage(Imap->msgids[seq-1], 1); need_to_free_msg = 1; } if (msg != NULL) { - if (msg->cm_fields['T'] != NULL) { + if (!CM_IsEmpty(msg, eTimestamp)) { if (imap_datecmp(itemlist[pos+1].Key, - atol(msg->cm_fields['T'])) >= 0) { + atol(msg->cm_fields[eTimestamp])) >= 0) { match = 1; } } @@ -406,11 +381,11 @@ int imap_do_search_msg(int seq, struct CtdlMessage *supplied_msg, else if (!strcasecmp(itemlist[pos].Key, "SMALLER")) { if (msg == NULL) { - msg = CtdlFetchMessage(IMAP->msgids[seq-1], 1); + msg = CtdlFetchMessage(Imap->msgids[seq-1], 1); need_to_free_msg = 1; } if (msg != NULL) { - if (strlen(msg->cm_fields['M']) < atoi(itemlist[pos+1].Key)) { + if (msg->cm_lengths[eMesageText] < atoi(itemlist[pos+1].Key)) { match = 1; } } @@ -419,11 +394,11 @@ int imap_do_search_msg(int seq, struct CtdlMessage *supplied_msg, else if (!strcasecmp(itemlist[pos].Key, "SUBJECT")) { if (msg == NULL) { - msg = CtdlFetchMessage(IMAP->msgids[seq-1], 1); + msg = CtdlFetchMessage(Imap->msgids[seq-1], 1); need_to_free_msg = 1; } if (msg != NULL) { - if (bmstrcasestr(msg->cm_fields['U'], itemlist[pos+1].Key)) { + if (bmstrcasestr(msg->cm_fields[eMsgSubject], itemlist[pos+1].Key)) { match = 1; } } @@ -432,7 +407,7 @@ int imap_do_search_msg(int seq, struct CtdlMessage *supplied_msg, else if (!strcasecmp(itemlist[pos].Key, "TEXT")) { if (msg == NULL) { - msg = CtdlFetchMessage(IMAP->msgids[seq-1], 1); + msg = CtdlFetchMessage(Imap->msgids[seq-1], 1); need_to_free_msg = 1; } if (msg != NULL) { @@ -447,11 +422,11 @@ int imap_do_search_msg(int seq, struct CtdlMessage *supplied_msg, else if (!strcasecmp(itemlist[pos].Key, "TO")) { if (msg == NULL) { - msg = CtdlFetchMessage(IMAP->msgids[seq-1], 1); + msg = CtdlFetchMessage(Imap->msgids[seq-1], 1); need_to_free_msg = 1; } if (msg != NULL) { - if (bmstrcasestr(msg->cm_fields['R'], itemlist[pos+1].Key)) { + if (bmstrcasestr(msg->cm_fields[eRecipient], itemlist[pos+1].Key)) { match = 1; } } @@ -468,7 +443,7 @@ int imap_do_search_msg(int seq, struct CtdlMessage *supplied_msg, /* FIXME this is b0rken. fix it. */ else if (!strcasecmp(itemlist[pos].Key, "UID")) { - if (is_msg_in_sequence_set(itemlist[pos+1].Key, IMAP->msgids[seq-1])) { + if (is_msg_in_sequence_set(itemlist[pos+1].Key, Imap->msgids[seq-1])) { match = 1; } pos += 2; @@ -480,28 +455,28 @@ int imap_do_search_msg(int seq, struct CtdlMessage *supplied_msg, */ else if (!strcasecmp(itemlist[pos].Key, "UNANSWERED")) { - if ((IMAP->flags[seq-1] & IMAP_ANSWERED) == 0) { + if ((Imap->flags[seq-1] & IMAP_ANSWERED) == 0) { match = 1; } ++pos; } else if (!strcasecmp(itemlist[pos].Key, "UNDELETED")) { - if ((IMAP->flags[seq-1] & IMAP_DELETED) == 0) { + if ((Imap->flags[seq-1] & IMAP_DELETED) == 0) { match = 1; } ++pos; } else if (!strcasecmp(itemlist[pos].Key, "UNDRAFT")) { - if ((IMAP->flags[seq-1] & IMAP_DRAFT) == 0) { + if ((Imap->flags[seq-1] & IMAP_DRAFT) == 0) { match = 1; } ++pos; } else if (!strcasecmp(itemlist[pos].Key, "UNFLAGGED")) { - if ((IMAP->flags[seq-1] & IMAP_FLAGGED) == 0) { + if ((Imap->flags[seq-1] & IMAP_FLAGGED) == 0) { match = 1; } ++pos; @@ -513,7 +488,7 @@ int imap_do_search_msg(int seq, struct CtdlMessage *supplied_msg, } else if (!strcasecmp(itemlist[pos].Key, "UNSEEN")) { - if ((IMAP->flags[seq-1] & IMAP_SEEN) == 0) { + if ((Imap->flags[seq-1] & IMAP_SEEN) == 0) { match = 1; } ++pos; @@ -539,7 +514,7 @@ int imap_do_search_msg(int seq, struct CtdlMessage *supplied_msg, } if (need_to_free_msg) { - CtdlFreeMessage(msg); + CM_Free(msg); } return(match); } @@ -550,6 +525,7 @@ int imap_do_search_msg(int seq, struct CtdlMessage *supplied_msg, * validated and boiled down the request a bit. */ void imap_do_search(int num_items, ConstStr *itemlist, int is_uid) { + citimap *Imap = IMAP; int i, j, k; int fts_num_msgs = 0; long *fts_msgs = NULL; @@ -563,12 +539,12 @@ void imap_do_search(int num_items, ConstStr *itemlist, int is_uid) { for (i=0; iCmd, + TokenCutLeft(&Imap->Cmd, &itemlist[i], 1); } if (itemlist[i].Key[itemlist[i].len-1] == ')') { - TokenCutRight(&IMAP->Cmd, + TokenCutRight(&Imap->Cmd, &itemlist[i], 1); } @@ -578,27 +554,27 @@ void imap_do_search(int num_items, ConstStr *itemlist, int is_uid) { * text index to disqualify messages that don't have any chance of * matching. (Only do this if the index is enabled!!) */ - if (config.c_enable_fulltext) for (i=0; i<(num_items-1); ++i) { + if (CtdlGetConfigInt("c_enable_fulltext")) for (i=0; i<(num_items-1); ++i) { if (!strcasecmp(itemlist[i].Key, "BODY")) { CtdlModuleDoSearch(&fts_num_msgs, &fts_msgs, itemlist[i+1].Key, "fulltext"); if (fts_num_msgs > 0) { - for (j=0; j < IMAP->num_msgs; ++j) { - if (IMAP->flags[j] & IMAP_SELECTED) { + for (j=0; j < Imap->num_msgs; ++j) { + if (Imap->flags[j] & IMAP_SELECTED) { is_in_list = 0; for (k=0; kmsgids[j] == fts_msgs[k]) { + if (Imap->msgids[j] == fts_msgs[k]) { ++is_in_list; } } } if (!is_in_list) { - IMAP->flags[j] = IMAP->flags[j] & ~IMAP_SELECTED; + Imap->flags[j] = Imap->flags[j] & ~IMAP_SELECTED; } } } else { /* no hits on the index; disqualify every message */ - for (j=0; j < IMAP->num_msgs; ++j) { - IMAP->flags[j] = IMAP->flags[j] & ~IMAP_SELECTED; + for (j=0; j < Imap->num_msgs; ++j) { + Imap->flags[j] = Imap->flags[j] & ~IMAP_SELECTED; } } if (fts_msgs) { @@ -609,24 +585,24 @@ void imap_do_search(int num_items, ConstStr *itemlist, int is_uid) { /* Now go through the messages and apply all search criteria. */ buffer_output(); - cprintf("* SEARCH "); - if (IMAP->num_msgs > 0) - for (i = 0; i < IMAP->num_msgs; ++i) - if (IMAP->flags[i] & IMAP_SELECTED) { + IAPuts("* SEARCH "); + if (Imap->num_msgs > 0) + for (i = 0; i < Imap->num_msgs; ++i) + if (Imap->flags[i] & IMAP_SELECTED) { if (imap_do_search_msg(i+1, NULL, num_items, itemlist, is_uid)) { if (num_results != 0) { - cprintf(" "); + IAPuts(" "); } if (is_uid) { - cprintf("%ld", IMAP->msgids[i]); + IAPrintf("%ld", Imap->msgids[i]); } else { - cprintf("%d", i+1); + IAPrintf("%d", i+1); } ++num_results; } } - cprintf("\r\n"); + IAPuts("\r\n"); unbuffer_output(); } @@ -638,7 +614,7 @@ void imap_search(int num_parms, ConstStr *Params) { int i; if (num_parms < 3) { - cprintf("%s BAD invalid parameters\r\n", Params[0].Key); + IReply("BAD invalid parameters"); return; } @@ -647,7 +623,7 @@ void imap_search(int num_parms, ConstStr *Params) { } imap_do_search(num_parms-2, &Params[2], 0); - cprintf("%s OK SEARCH completed\r\n", Params[0].Key); + IReply("OK SEARCH completed"); } /* @@ -657,7 +633,7 @@ void imap_uidsearch(int num_parms, ConstStr *Params) { int i; if (num_parms < 4) { - cprintf("%s BAD invalid parameters\r\n", Params[0].Key); + IReply("BAD invalid parameters"); return; } @@ -666,7 +642,7 @@ void imap_uidsearch(int num_parms, ConstStr *Params) { } imap_do_search(num_parms-3, &Params[3], 1); - cprintf("%s OK UID SEARCH completed\r\n", Params[0].Key); + IReply("OK UID SEARCH completed"); }