/* * imap_search() calls imap_do_search() to do its actual work, once it's * 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; int is_in_list = 0; int num_results = 0; /* Strip parentheses. We realize that this method will not work * in all cases, but it seems to work with all currently available * client software. Revisit later... */ for (i=0; i<num_items; ++i) { if (itemlist[i].Key[0] == '(') { TokenCutLeft(&Imap->Cmd, &itemlist[i], 1); } if (itemlist[i].Key[itemlist[i].len-1] == ')') { TokenCutRight(&Imap->Cmd, &itemlist[i], 1); } } /* If there is a BODY search criterion in the query, use our full * 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 (!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) { is_in_list = 0; for (k=0; k<fts_num_msgs; ++k) { if (Imap->msgids[j] == fts_msgs[k]) { ++is_in_list; } } } if (!is_in_list) { 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; } } if (fts_msgs) { free(fts_msgs); } } } /* Now go through the messages and apply all search criteria. */ buffer_output(); 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) { IAPuts(" "); } if (is_uid) { IAPrintf("%ld", Imap->msgids[i]); } else { IAPrintf("%d", i+1); } ++num_results; } } IAPuts("\r\n"); unbuffer_output(); }
/* * Implements the GETACL command. */ void imap_getacl(int num_parms, ConstStr *Params) { char roomname[ROOMNAMELEN]; char savedroom[ROOMNAMELEN]; int msgs, new; int ret; struct ctdluser temp; struct cdbdata *cdbus; int ra; StrBuf *rights; if (num_parms != 3) { IReply("BAD usage error"); return; } /* * Search for the specified room or folder */ ret = imap_grabroom(roomname, Params[2].Key, 1); if (ret != 0) { IReply("NO Invalid mailbox name or access denied"); return; } /* * CtdlUserGoto() formally takes us to the desired room. (If another * folder is selected, save its name so we can return there!!!!!) */ if (IMAP->selected) { strcpy(savedroom, CC->room.QRname); } CtdlUserGoto(roomname, 0, 0, &msgs, &new, NULL, NULL); IAPuts("* ACL "); IPutCParamStr(2); /* * Traverse the userlist */ rights = NewStrBuf(); cdb_rewind(CDB_USERS); while (cdbus = cdb_next_item(CDB_USERS), cdbus != NULL) { memset(&temp, 0, sizeof temp); memcpy(&temp, cdbus->ptr, sizeof temp); cdb_free(cdbus); CtdlRoomAccess(&CC->room, &temp, &ra, NULL); if (!IsEmptyStr(temp.fullname)) { imap_acl_flags(rights, ra); if (StrLength(rights) > 0) { IAPuts(" "); IPutStr(temp.fullname, strlen(temp.fullname)); IAPuts(" "); iaputs(SKEY( rights)); } } } FreeStrBuf(&rights); IAPuts("\r\n"); /* * If another folder is selected, go back to that room so we can resume * our happy day without violent explosions. */ if (IMAP->selected) { CtdlUserGoto(savedroom, 0, 0, &msgs, &new, NULL, NULL); }