1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 13:57:35 +00:00

LibIMAP: Support for CAPABILITY command & response

This involves parsing messages with untagged responses
This commit is contained in:
x-yl 2021-06-01 17:42:12 +04:00 committed by Ali Mohammad Pur
parent ac712b07f9
commit 0f42ea6770
4 changed files with 55 additions and 0 deletions

View file

@ -112,6 +112,8 @@ static ReadonlyBytes command_byte_buffer(CommandType command)
switch (command) { switch (command) {
case CommandType::Noop: case CommandType::Noop:
return "NOOP"sv.bytes(); return "NOOP"sv.bytes();
case CommandType::Capability:
return "CAPABILITY"sv.bytes();
} }
VERIFY_NOT_REACHED(); VERIFY_NOT_REACHED();
} }

View file

@ -17,10 +17,12 @@
namespace IMAP { namespace IMAP {
enum class CommandType { enum class CommandType {
Capability,
Noop, Noop,
}; };
enum class ResponseType : unsigned { enum class ResponseType : unsigned {
Capability = 1u << 0,
}; };
class Parser; class Parser;
@ -65,8 +67,22 @@ public:
m_response_type = m_response_type | static_cast<unsigned>(response_type); m_response_type = m_response_type | static_cast<unsigned>(response_type);
} }
void add_capabilities(Vector<String>&& capabilities)
{
m_capabilities = move(capabilities);
add_response_type(ResponseType::Capability);
}
Vector<String>& capabilities()
{
VERIFY(contains_response_type(ResponseType::Capability));
return m_capabilities;
}
private: private:
unsigned m_response_type; unsigned m_response_type;
Vector<String> m_capabilities;
}; };
class SolidResponse { class SolidResponse {

View file

@ -27,6 +27,10 @@ ParseStatus Parser::parse(ByteBuffer&& buffer, bool expecting_tag)
return { true, { ContinueRequest { data } } }; return { true, { ContinueRequest { data } } };
} }
while (try_consume("*")) {
parse_untagged();
}
if (expecting_tag) { if (expecting_tag) {
if (at_end()) { if (at_end()) {
m_incomplete = true; m_incomplete = true;
@ -117,6 +121,30 @@ unsigned Parser::parse_number()
return number.value(); 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<String>();
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() StringView Parser::parse_atom()
{ {
auto is_non_atom_char = [](u8 x) { auto is_non_atom_char = [](u8 x) {

View file

@ -32,13 +32,22 @@ private:
bool try_consume(StringView); bool try_consume(StringView);
bool at_end() { return position >= m_buffer.size(); }; bool at_end() { return position >= m_buffer.size(); };
void parse_response_done(); void parse_response_done();
void consume(StringView x); void consume(StringView x);
unsigned parse_number(); unsigned parse_number();
Optional<unsigned> try_parse_number(); Optional<unsigned> try_parse_number();
void parse_untagged(); void parse_untagged();
StringView parse_atom(); StringView parse_atom();
ResponseStatus parse_status(); ResponseStatus parse_status();
StringView parse_while(Function<bool(u8)> should_consume); StringView parse_while(Function<bool(u8)> should_consume);
void parse_capability_response();
}; };
} }