diff --git a/Userland/Libraries/LibIMAP/Client.cpp b/Userland/Libraries/LibIMAP/Client.cpp index 160b51131c..77570c6ac6 100644 --- a/Userland/Libraries/LibIMAP/Client.cpp +++ b/Userland/Libraries/LibIMAP/Client.cpp @@ -112,6 +112,8 @@ static ReadonlyBytes command_byte_buffer(CommandType command) switch (command) { case CommandType::Noop: return "NOOP"sv.bytes(); + case CommandType::Capability: + return "CAPABILITY"sv.bytes(); } VERIFY_NOT_REACHED(); } diff --git a/Userland/Libraries/LibIMAP/Objects.h b/Userland/Libraries/LibIMAP/Objects.h index 037b9387b5..daaf5fbe55 100644 --- a/Userland/Libraries/LibIMAP/Objects.h +++ b/Userland/Libraries/LibIMAP/Objects.h @@ -17,10 +17,12 @@ namespace IMAP { enum class CommandType { + Capability, Noop, }; enum class ResponseType : unsigned { + Capability = 1u << 0, }; class Parser; @@ -65,8 +67,22 @@ public: m_response_type = m_response_type | static_cast(response_type); } + void add_capabilities(Vector&& capabilities) + { + m_capabilities = move(capabilities); + add_response_type(ResponseType::Capability); + } + + Vector& capabilities() + { + VERIFY(contains_response_type(ResponseType::Capability)); + return m_capabilities; + } + private: unsigned m_response_type; + + Vector m_capabilities; }; class SolidResponse { diff --git a/Userland/Libraries/LibIMAP/Parser.cpp b/Userland/Libraries/LibIMAP/Parser.cpp index 1c872e242a..48e9db7ab5 100644 --- a/Userland/Libraries/LibIMAP/Parser.cpp +++ b/Userland/Libraries/LibIMAP/Parser.cpp @@ -27,6 +27,10 @@ ParseStatus Parser::parse(ByteBuffer&& buffer, bool expecting_tag) return { true, { ContinueRequest { data } } }; } + while (try_consume("*")) { + parse_untagged(); + } + if (expecting_tag) { if (at_end()) { m_incomplete = true; @@ -117,6 +121,30 @@ unsigned Parser::parse_number() return number.value(); } +void Parser::parse_untagged() +{ + consume(" "); + + if (try_consume("CAPABILITY")) { + parse_capability_response(); + } else { + auto x = parse_while([](u8 x) { return x != '\r'; }); + consume("\r\n"); + dbgln("ignored {}", x); + } +} + +void Parser::parse_capability_response() +{ + auto capability = AK::Vector(); + while (!try_consume("\r\n")) { + consume(" "); + auto x = String(parse_atom()); + capability.append(x); + } + m_response.data().add_capabilities(move(capability)); +} + StringView Parser::parse_atom() { auto is_non_atom_char = [](u8 x) { diff --git a/Userland/Libraries/LibIMAP/Parser.h b/Userland/Libraries/LibIMAP/Parser.h index 9a4ee07e5e..e2967ef128 100644 --- a/Userland/Libraries/LibIMAP/Parser.h +++ b/Userland/Libraries/LibIMAP/Parser.h @@ -32,13 +32,22 @@ private: bool try_consume(StringView); bool at_end() { return position >= m_buffer.size(); }; + void parse_response_done(); + void consume(StringView x); + unsigned parse_number(); Optional try_parse_number(); + void parse_untagged(); + StringView parse_atom(); + ResponseStatus parse_status(); + StringView parse_while(Function should_consume); + + void parse_capability_response(); }; }