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();
   }
Example #2
0
   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);
         }