From b39d807600411182da2afb09c73ee09e500f79cf Mon Sep 17 00:00:00 2001 From: mdecimus Date: Mon, 27 Jan 2025 19:31:34 +0100 Subject: [PATCH] IMAP LIST-STATUS (RFC 5819) returns items in wrong order (fixes #1129) --- crates/imap-proto/src/protocol/list.rs | 44 +++++++++++++++++--------- 1 file changed, 29 insertions(+), 15 deletions(-) diff --git a/crates/imap-proto/src/protocol/list.rs b/crates/imap-proto/src/protocol/list.rs index 8bfe7e88..8d0c2c42 100644 --- a/crates/imap-proto/src/protocol/list.rs +++ b/crates/imap-proto/src/protocol/list.rs @@ -150,15 +150,15 @@ impl TryFrom<&str> for Attribute { type Error = (); fn try_from(value: &str) -> Result { - match value { - "archive" => Ok(Attribute::Archive), - "drafts" => Ok(Attribute::Drafts), - "junk" => Ok(Attribute::Junk), - "sent" => Ok(Attribute::Sent), - "trash" => Ok(Attribute::Trash), - "important" => Ok(Attribute::Important), - _ => Err(()), - } + hashify::tiny_map!(value.as_bytes(), + "archive" => Attribute::Archive, + "drafts" => Attribute::Drafts, + "junk" => Attribute::Junk, + "sent" => Attribute::Sent, + "trash" => Attribute::Trash, + "important" => Attribute::Important, + ) + .ok_or(()) } } @@ -249,13 +249,27 @@ impl ImapResponse for Response { fn serialize(self) -> Vec { let mut buf = Vec::with_capacity(100); - for list_item in &self.list_items { - list_item.serialize(&mut buf, self.is_rev2, self.is_lsub); + match (self.list_items.is_empty(), self.status_items.is_empty()) { + (false, false) => { + for (list_item, status_item) in self.list_items.iter().zip(self.status_items.iter()) + { + list_item.serialize(&mut buf, self.is_rev2, self.is_lsub); + status_item.serialize(&mut buf, self.is_rev2); + } + } + (false, true) => { + for list_item in &self.list_items { + list_item.serialize(&mut buf, self.is_rev2, self.is_lsub); + } + } + (true, false) => { + for status_item in &self.status_items { + status_item.serialize(&mut buf, self.is_rev2); + } + } + _ => (), } - for status_item in &self.status_items { - status_item.serialize(&mut buf, self.is_rev2); - } buf } } @@ -365,8 +379,8 @@ mod tests { }; let expected_v2 = concat!( "* LIST (\\Subscribed) \"/\" \"INBOX\"\r\n", - "* LIST () \"/\" \"foo\" (\"CHILDINFO\" (\"SUBSCRIBED\"))\r\n", "* STATUS \"INBOX\" (MESSAGES 17)\r\n", + "* LIST () \"/\" \"foo\" (\"CHILDINFO\" (\"SUBSCRIBED\"))\r\n", "* STATUS \"foo\" (MESSAGES 30 UNSEEN 29)\r\n", ); let expected_v1 = concat!(