From c86e4bcd3abf7130e8d3950ca6a3b496ca166107 Mon Sep 17 00:00:00 2001 From: vincent-richard Date: Tue, 11 May 2021 08:31:03 +0200 Subject: #261 Workaround for bad SEARCH response with AOL IMAP server --- src/vmime/net/imap/IMAPParser.hpp | 14 +++++++-- tests/net/imap/IMAPParserTest.cpp | 60 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+), 2 deletions(-) diff --git a/src/vmime/net/imap/IMAPParser.hpp b/src/vmime/net/imap/IMAPParser.hpp index 59bab777..e71b403f 100644 --- a/src/vmime/net/imap/IMAPParser.hpp +++ b/src/vmime/net/imap/IMAPParser.hpp @@ -4252,8 +4252,18 @@ public: VIMAP_PARSER_GET_PUSHBACK(nz_number, search_nz_number_list); - while (VIMAP_PARSER_TRY_CHECK(SPACE)) { - VIMAP_PARSER_GET_PUSHBACK(nz_number, search_nz_number_list); + if (!parser.isStrict()) { + + // Allow extra SPACEs at end of line + while (VIMAP_PARSER_TRY_CHECK(SPACE)) { + VIMAP_PARSER_TRY_GET_PUSHBACK_OR_ELSE(nz_number, search_nz_number_list, { break; }); + } + + } else { + + while (VIMAP_PARSER_TRY_CHECK(SPACE)) { + VIMAP_PARSER_GET_PUSHBACK(nz_number, search_nz_number_list); + } } } diff --git a/tests/net/imap/IMAPParserTest.cpp b/tests/net/imap/IMAPParserTest.cpp index 47880a06..e2a28ccc 100644 --- a/tests/net/imap/IMAPParserTest.cpp +++ b/tests/net/imap/IMAPParserTest.cpp @@ -40,6 +40,7 @@ VMIME_TEST_SUITE_BEGIN(IMAPParserTest) VMIME_TEST(testStarFlagWithoutBackslash) VMIME_TEST(testUnquotedMailboxName) VMIME_TEST(testInvalidCharsInAstring) + VMIME_TEST(testExtraSpaceInSEARCHResponse) VMIME_TEST_LIST_END @@ -483,4 +484,63 @@ VMIME_TEST_SUITE_BEGIN(IMAPParserTest) } } + // Some broken IMAP servers (eg. AOL) put a space before the final CRLF on the line. + // This causes a specific issue with IMAP SEARCH command response. + void testExtraSpaceInSEARCHResponse() { + + const char* respText = + R"END(* SEARCH 1 2 3 4 )END" // note the space just before the CRLF sequence + "\r\n" + R"END(a001 OK Completed.)END" + "\r\n"; + + // Strict mode + { + auto socket = vmime::make_shared (); + auto toh = vmime::make_shared (); + + auto tag = vmime::make_shared (); + + socket->localSend(respText); + + auto parser = vmime::make_shared (); + + parser->setSocket(socket); + parser->setTimeoutHandler(toh); + parser->setStrict(true); + + VASSERT_THROW("strict mode", parser->readResponse(*tag), vmime::exceptions::invalid_response); + } + + // Non-strict mode + { + auto socket = vmime::make_shared (); + auto toh = vmime::make_shared (); + + auto tag = vmime::make_shared (); + + socket->localSend(respText); + + auto parser = vmime::make_shared (); + + parser->setSocket(socket); + parser->setTimeoutHandler(toh); + parser->setStrict(false); + + std::unique_ptr resp; + + VASSERT_NO_THROW("non-strict mode", resp.reset(parser->readResponse(*tag))); + + VASSERT_EQ("resp size", 1, resp->continue_req_or_response_data.size()); + VASSERT("resp data", resp->continue_req_or_response_data[0]->response_data); + VASSERT("mbox data", resp->continue_req_or_response_data[0]->response_data->mailbox_data); + VASSERT_EQ("mbox search type", vmime::net::imap::IMAPParser::mailbox_data::SEARCH, resp->continue_req_or_response_data[0]->response_data->mailbox_data->type); + VASSERT_EQ("mbox search size", 4, resp->continue_req_or_response_data[0]->response_data->mailbox_data->search_nz_number_list.size()); + VASSERT_EQ("mbox search 1", 1, resp->continue_req_or_response_data[0]->response_data->mailbox_data->search_nz_number_list[0]->value); + VASSERT_EQ("mbox search 2", 2, resp->continue_req_or_response_data[0]->response_data->mailbox_data->search_nz_number_list[1]->value); + VASSERT_EQ("mbox search 3", 3, resp->continue_req_or_response_data[0]->response_data->mailbox_data->search_nz_number_list[2]->value); + VASSERT_EQ("mbox search 4", 4, resp->continue_req_or_response_data[0]->response_data->mailbox_data->search_nz_number_list[3]->value); + } + } + VMIME_TEST_SUITE_END -- cgit v1.2.3