IMAPResult IMAPCommandSEARCH::ExecuteCommand(std::shared_ptr<IMAPConnection> pConnection, std::shared_ptr<IMAPCommandArgument> pArgument) { if (is_sort_ && !Configuration::Instance()->GetIMAPConfiguration()->GetUseIMAPSort()) return IMAPResult(IMAPResult::ResultNo, "IMAP SORT is not enabled."); if (!pConnection->IsAuthenticated()) return IMAPResult(IMAPResult::ResultNo, "Authenticate first"); if (!pConnection->GetCurrentFolder()) return IMAPResult(IMAPResult::ResultNo, "No folder selected."); if (!pArgument) return IMAPResult(IMAPResult::ResultNo, "Internal error IMAP-SEARCH-1."); { // The IMAP Search parser should not parse // the beginning of the command, UID SEARCH // or SEARCH String sCommand = pArgument->Command(); int iCommandStartPos; if (is_uid_) iCommandStartPos = sCommand.Find(_T(" "), 4) + 1; else iCommandStartPos = sCommand.Find(_T(" ")) + 1; sCommand = sCommand.Mid(iCommandStartPos); // 3 as in UID pArgument->Command(sCommand); } std::shared_ptr<IMAPSearchParser> pParser = std::shared_ptr<IMAPSearchParser>(new IMAPSearchParser()); IMAPResult result = pParser->ParseCommand(pArgument, is_sort_); if (result.GetResult() != IMAPResult::ResultOK) return result; if (is_sort_ && !pParser->GetSortParser()) return IMAPResult(IMAPResult::ResultBad, "Incorrect search commands."); // Mails in current box std::shared_ptr<IMAPFolder> pCurFolder = pConnection->GetCurrentFolder(); if (!pCurFolder) return IMAPResult(IMAPResult::ResultBad, "No selected folder"); std::vector<std::shared_ptr<Message>> messages = pCurFolder->GetMessages()->GetCopy(); std::vector<String> sMatchingVec; if (messages.size() > 0) { // Iterate through the messages and see which ones match. std::vector<std::pair<int, std::shared_ptr<Message> > > vecMatchingMessages; int index = 0; for(std::shared_ptr<Message> pMessage : messages) { const String fileName = PersistentMessage::GetFileName(pConnection->GetAccount(), pMessage); index++; if (pMessage && DoesMessageMatch_(pParser->GetCriteria(), fileName, pMessage, index)) { // Yup we got a match. vecMatchingMessages.push_back(make_pair(index, pMessage)); } } if (is_sort_) { IMAPSort oSorter; oSorter.Sort(pConnection, vecMatchingMessages, pParser->GetSortParser()); // Sort the message vector } typedef std::pair<int, std::shared_ptr<Message> > MessagePair; for(MessagePair messagePair : vecMatchingMessages) { int index = messagePair.first; std::shared_ptr<Message> pMessage = messagePair.second; String sID; if (is_uid_) sID.Format(_T("%u"), pMessage->GetUID()); else sID.Format(_T("%d"), index); sMatchingVec.push_back(sID); } } // Send response String sMatching; if (sMatchingVec.size() > 0) { // If we don't find any matches, we shouldn't return a whitespace // after SEARCH/SORT below. That's why we add the white space here. sMatching = " " + StringParser::JoinVector(sMatchingVec, " ") ; } String sResponse; if (is_sort_) sResponse = "* SORT" + sMatching + "\r\n"; else sResponse = "* SEARCH" + sMatching + "\r\n"; if (!is_uid_) // if this is a UID command, IMAPCommandUID takes care of the below line. sResponse += pArgument->Tag() + " OK Search completed\r\n"; pConnection->SendAsciiData(sResponse); return IMAPResult(); }
IMAPResult IMAPCommandSEARCH::ExecuteCommand(shared_ptr<IMAPConnection> pConnection, shared_ptr<IMAPCommandArgument> pArgument) { if (m_bIsSort && !Configuration::Instance()->GetIMAPConfiguration()->GetUseIMAPSort()) return IMAPResult(IMAPResult::ResultNo, "IMAP SORT is not enabled."); if (!pConnection->IsAuthenticated()) return IMAPResult(IMAPResult::ResultNo, "Authenticate first"); if (!pConnection->GetCurrentFolder()) return IMAPResult(IMAPResult::ResultNo, "No folder selected."); if (!pArgument) return IMAPResult(IMAPResult::ResultNo, "Internal error IMAP-SEARCH-1."); { // The IMAP Search parser should not parse // the beginning of the command, UID SEARCH // or SEARCH String sCommand = pArgument->Command(); int iCommandStartPos; if (m_bIsUID) iCommandStartPos = sCommand.Find(_T(" "), 4) + 1; else iCommandStartPos = sCommand.Find(_T(" ")) + 1; sCommand = sCommand.Mid(iCommandStartPos); // 3 as in UID pArgument->Command(sCommand); } shared_ptr<IMAPSearchParser> pParser = shared_ptr<IMAPSearchParser>(new IMAPSearchParser()); IMAPResult result = pParser->ParseCommand(pArgument, m_bIsSort); if (result.GetResult() != IMAPResult::ResultOK) return result; if (m_bIsSort && !pParser->GetSortParser()) return IMAPResult(IMAPResult::ResultBad, "Incorrect search commands."); // Mails in current box shared_ptr<IMAPFolder> pCurFolder = pConnection->GetCurrentFolder(); if (!pCurFolder) return IMAPResult(IMAPResult::ResultBad, "No selected folder"); vector<shared_ptr<Message>> messages = pCurFolder->GetMessages()->GetCopy(); std::vector<String> sMatchingVec; if (messages.size() > 0) { // Iterate through the messages and see which ones match. vector<pair<int, shared_ptr<Message> > > vecMatchingMessages; int index = 0; boost_foreach(shared_ptr<Message> pMessage, messages) { const String fileName = PersistentMessage::GetFileName(pConnection->GetAccount(), pMessage); index++; if (pMessage && _DoesMessageMatch(pParser->GetCriteria(), fileName, pMessage, index)) { // Yup we got a match. vecMatchingMessages.push_back(make_pair(index, pMessage)); } } if (m_bIsSort) { IMAPSort oSorter; oSorter.Sort(pConnection, vecMatchingMessages, pParser->GetSortParser()); // Sort the message vector } typedef pair<int, shared_ptr<Message> > MessagePair; boost_foreach(MessagePair messagePair, vecMatchingMessages) { int index = messagePair.first; shared_ptr<Message> pMessage = messagePair.second; String sID; if (m_bIsUID) sID.Format(_T("%u"), pMessage->GetUID()); else sID.Format(_T("%d"), index); sMatchingVec.push_back(sID); }