Variant f_imap_search(const Resource& imap_stream, const String& criteria, int64_t options /* = 0 */, const String& charset /* = "" */) { ImapStream *obj = imap_stream.getTyped<ImapStream>(); char *search_criteria = (char*)criteria.data(); IMAPG(messages) = IMAPG(messages_tail) = NIL; SEARCHPGM *pgm = mail_criteria(search_criteria); mail_search_full(obj->m_stream, (charset.empty() ? NIL : (char*)charset.data()), pgm, options); if (pgm && !(options & SE_FREE)) { mail_free_searchpgm(&pgm); } if (IMAPG(messages) == NIL) { return false; } Array ret(Array::Create()); MESSAGELIST *cur = IMAPG(messages); while (cur != NIL) { ret.append((int64_t)cur->msgid); cur = cur->next; } mail_free_messagelist(&IMAPG(messages), &IMAPG(messages_tail)); return ret; }
std::vector<long> ImapClient::search(const std::string& aHost, const std::string& aUsername, const std::string& aPassword, const std::string& aMailbox, const std::string& aCriteria, bool aUid) { #include "linkage.c" /* IMPORTANT: make sure that the vector of found sequence numbers is empty! */ theFoundSequenceNumbers.clear(); MAILSTREAM* lSource = getMailStream(aHost, aUsername, aPassword, aMailbox, true); checkMailStream(lSource); mail_ping(lSource); /* First, tokenize the criteria so that we can work on it */ std::stringstream lToTokenize(aCriteria); std::string lBuffer; std::vector<std::string> lTokens; SEARCHPGM * lSearchProgram; while(lToTokenize >> lBuffer) { lTokens.push_back(lBuffer); } lSearchProgram = search_criteria(lTokens); mail_search_full(lSource, NIL, lSearchProgram, (aUid ? SE_UID : NIL) | SE_NOPREFETCH); /* clean up, don't leave a mess */ mail_free_searchpgm(&lSearchProgram); return theFoundSequenceNumbers; }
SEARCHPGM *prune_criteria (char *criteria) { SEARCHPGM *pgm = NIL; char *criterion,*r,tmp[MAILTMPLEN]; int f; if (criteria) { /* only if criteria defined */ /* make writeable copy of criteria */ criteria = cpystr (criteria); /* for each criterion */ for (pgm = mail_newsearchpgm (), criterion = strtok_r (criteria," ",&r); criterion; (criterion = strtok_r (NIL," ",&r))) { f = NIL; /* init then scan the criterion */ switch (*ucase (criterion)) { case 'A': /* possible ALL, ANSWERED */ if (!strcmp (criterion+1,"LL")) f = T; else if (!strcmp (criterion+1,"NSWERED")) f = pgm->answered = T; break; case 'B': /* possible BCC, BEFORE, BODY */ if (!strcmp (criterion+1,"CC")) f = mail_criteria_string (&pgm->bcc,&r); else if (!strcmp (criterion+1,"EFORE")) f = mail_criteria_date (&pgm->before,&r); else if (!strcmp (criterion+1,"ODY")) f = mail_criteria_string (&pgm->body,&r); break; case 'C': /* possible CC */ if (!strcmp (criterion+1,"C")) f = mail_criteria_string (&pgm->cc,&r); break; case 'D': /* possible DELETED, DRAFT */ if (!strcmp (criterion+1,"ELETED")) f = pgm->deleted = T; else if (!strcmp (criterion+1,"RAFT")) f = pgm->draft = T; break; case 'F': /* possible FLAGGED, FROM */ if (!strcmp (criterion+1,"LAGGED")) f = pgm->flagged = T; else if (!strcmp (criterion+1,"ROM")) f = mail_criteria_string (&pgm->from,&r); break; case 'K': /* possible KEYWORD */ if (!strcmp (criterion+1,"EYWORD")) f = mail_criteria_string (&pgm->keyword,&r); break; case 'L': /* possible LARGER */ if (!strcmp (criterion+1,"ARGER")) f = prune_criteria_number (&pgm->larger,&r); case 'N': /* possible NEW */ if (!strcmp (criterion+1,"EW")) f = pgm->recent = pgm->unseen = T; break; case 'O': /* possible OLD, ON */ if (!strcmp (criterion+1,"LD")) f = pgm->old = T; else if (!strcmp (criterion+1,"N")) f = mail_criteria_date (&pgm->on,&r); break; case 'R': /* possible RECENT */ if (!strcmp (criterion+1,"ECENT")) f = pgm->recent = T; break; case 'S': /* possible SEEN, SENT*, SINCE, SMALLER, SUBJECT */ if (!strcmp (criterion+1,"EEN")) f = pgm->seen = T; else if (!strncmp (criterion+1,"ENT",3)) { if (!strcmp (criterion+4,"BEFORE")) f = mail_criteria_date (&pgm->sentbefore,&r); else if (!strcmp (criterion+4,"ON")) f = mail_criteria_date (&pgm->senton,&r); else if (!strcmp (criterion+4,"SINCE")) f = mail_criteria_date (&pgm->sentsince,&r); } else if (!strcmp (criterion+1,"INCE")) f = mail_criteria_date (&pgm->since,&r); else if (!strcmp (criterion+1,"MALLER")) f = prune_criteria_number (&pgm->smaller,&r); else if (!strcmp (criterion+1,"UBJECT")) f = mail_criteria_string (&pgm->subject,&r); break; case 'T': /* possible TEXT, TO */ if (!strcmp (criterion+1,"EXT")) f = mail_criteria_string (&pgm->text,&r); else if (!strcmp (criterion+1,"O")) f = mail_criteria_string (&pgm->to,&r); break; case 'U': /* possible UN* */ if (criterion[1] == 'N') { if (!strcmp (criterion+2,"ANSWERED")) f = pgm->unanswered = T; else if (!strcmp (criterion+2,"DELETED")) f = pgm->undeleted = T; else if (!strcmp (criterion+2,"DRAFT")) f = pgm->undraft = T; else if (!strcmp (criterion+2,"FLAGGED")) f = pgm->unflagged = T; else if (!strcmp (criterion+2,"KEYWORD")) f = mail_criteria_string (&pgm->unkeyword,&r); else if (!strcmp (criterion+2,"SEEN")) f = pgm->unseen = T; } break; default: /* we will barf below */ break; } if (!f) { /* if can't identify criterion */ sprintf (tmp,"Unknown search criterion: %.30s",criterion); MM_LOG (tmp,ERROR); mail_free_searchpgm (&pgm); break; } } /* no longer need copy of criteria */ fs_give ((void **) &criteria); } return pgm; }