diff --git a/crates/imap-proto/src/parser/acl.rs b/crates/imap-proto/src/parser/acl.rs index 7829fb35..08390f4d 100644 --- a/crates/imap-proto/src/parser/acl.rs +++ b/crates/imap-proto/src/parser/acl.rs @@ -22,8 +22,12 @@ */ use crate::{ - protocol::acl::{self, ModRights, ModRightsOp, Rights}, + protocol::{ + acl::{self, ModRights, ModRightsOp, Rights}, + ProtocolVersion, + }, receiver::Request, + utf7::utf7_maybe_decode, Command, }; @@ -45,7 +49,7 @@ use super::PushUnique; */ impl Request { - pub fn parse_acl(self) -> crate::Result { + pub fn parse_acl(self, version: ProtocolVersion) -> crate::Result { let (has_identifier, has_mod_rights) = match self.command { Command::SetAcl => (true, true), Command::DeleteAcl | Command::ListRights => (true, false), @@ -53,11 +57,14 @@ impl Request { _ => unreachable!(), }; let mut tokens = self.tokens.into_iter(); - let mailbox_name = tokens - .next() - .ok_or((self.tag.as_str(), "Missing mailbox name."))? - .unwrap_string() - .map_err(|v| (self.tag.as_str(), v))?; + let mailbox_name = utf7_maybe_decode( + tokens + .next() + .ok_or((self.tag.as_str(), "Missing mailbox name."))? + .unwrap_string() + .map_err(|v| (self.tag.as_str(), v))?, + version, + ); let identifier = if has_identifier { tokens .next() @@ -138,7 +145,10 @@ impl ModRights { mod tests { use crate::{ - protocol::acl::{self, ModRights, ModRightsOp, Rights}, + protocol::{ + acl::{self, ModRights, ModRightsOp, Rights}, + ProtocolVersion, + }, receiver::Receiver, }; @@ -222,7 +232,7 @@ mod tests { receiver .parse(&mut command.as_bytes().iter()) .unwrap() - .parse_acl() + .parse_acl(ProtocolVersion::Rev1) .unwrap(), arguments, "{:?}", diff --git a/crates/imap-proto/src/parser/append.rs b/crates/imap-proto/src/parser/append.rs index a48f293c..7ba1fc40 100644 --- a/crates/imap-proto/src/parser/append.rs +++ b/crates/imap-proto/src/parser/append.rs @@ -24,9 +24,10 @@ use crate::{ protocol::{ append::{self, Message}, - Flag, + Flag, ProtocolVersion, }, receiver::{Request, Token}, + utf7::utf7_maybe_decode, Command, }; @@ -40,17 +41,20 @@ enum State { } impl Request { - pub fn parse_append(self) -> crate::Result { + pub fn parse_append(self, version: ProtocolVersion) -> crate::Result { match self.tokens.len() { 0 | 1 => Err(self.into_error("Missing arguments.")), _ => { // Obtain mailbox name let mut tokens = self.tokens.into_iter().peekable(); - let mailbox_name = tokens - .next() - .unwrap() - .unwrap_string() - .map_err(|v| (self.tag.as_str(), v))?; + let mailbox_name = utf7_maybe_decode( + tokens + .next() + .unwrap() + .unwrap_string() + .map_err(|v| (self.tag.as_str(), v))?, + version, + ); let mut messages = Vec::new(); while tokens.peek().is_some() { @@ -166,7 +170,7 @@ mod tests { use crate::{ protocol::{ append::{self, Message}, - Flag, + Flag, ProtocolVersion, }, receiver::{Error, Receiver}, }; @@ -265,7 +269,7 @@ mod tests { receiver .parse(&mut command.as_bytes().iter()) .expect(command) - .parse_append() + .parse_append(ProtocolVersion::Rev1) .expect(command), arguments, "{:?}", @@ -298,7 +302,7 @@ mod tests { match receiver.parse(&mut line.as_bytes().iter()) { Ok(request) => { assert_eq!( - request.parse_append().unwrap(), + request.parse_append(ProtocolVersion::Rev1).unwrap(), append::Arguments { tag: "A003".to_string(), mailbox_name: "saved-messages".to_string(), diff --git a/crates/imap-proto/src/parser/copy_move.rs b/crates/imap-proto/src/parser/copy_move.rs index de055fdf..46fb2562 100644 --- a/crates/imap-proto/src/parser/copy_move.rs +++ b/crates/imap-proto/src/parser/copy_move.rs @@ -21,12 +21,17 @@ * for more details. */ -use crate::{protocol::copy_move, receiver::Request, Command}; +use crate::{ + protocol::{copy_move, ProtocolVersion}, + receiver::Request, + utf7::utf7_maybe_decode, + Command, +}; use super::parse_sequence_set; impl Request { - pub fn parse_copy_move(self) -> crate::Result { + pub fn parse_copy_move(self, version: ProtocolVersion) -> crate::Result { if self.tokens.len() > 1 { let mut tokens = self.tokens.into_iter(); @@ -38,11 +43,14 @@ impl Request { .unwrap_bytes(), ) .map_err(|v| (self.tag.as_str(), v))?, - mailbox_name: tokens - .next() - .ok_or((self.tag.as_str(), "Missing mailbox name."))? - .unwrap_string() - .map_err(|v| (self.tag.as_str(), v))?, + mailbox_name: utf7_maybe_decode( + tokens + .next() + .ok_or((self.tag.as_str(), "Missing mailbox name."))? + .unwrap_string() + .map_err(|v| (self.tag.as_str(), v))?, + version, + ), tag: self.tag, }) } else { @@ -54,7 +62,7 @@ impl Request { #[cfg(test)] mod tests { use crate::{ - protocol::{copy_move, Sequence}, + protocol::{copy_move, ProtocolVersion, Sequence}, receiver::Receiver, }; @@ -66,7 +74,7 @@ mod tests { receiver .parse(&mut "A003 COPY 2:4 MEETING\r\n".as_bytes().iter()) .unwrap() - .parse_copy_move() + .parse_copy_move(ProtocolVersion::Rev1) .unwrap(), copy_move::Arguments { sequence_set: Sequence::Range { @@ -77,5 +85,20 @@ mod tests { tag: "A003".to_string(), } ); + assert_eq!( + receiver + .parse(&mut "A003 COPY 2:4 \"You &- Me\"\r\n".as_bytes().iter()) + .unwrap() + .parse_copy_move(ProtocolVersion::Rev1) + .unwrap(), + copy_move::Arguments { + sequence_set: Sequence::Range { + start: 2.into(), + end: 4.into(), + }, + mailbox_name: "You & Me".to_string(), + tag: "A003".to_string(), + } + ); } } diff --git a/crates/imap/src/op/acl.rs b/crates/imap/src/op/acl.rs index 66dc89e2..bef68105 100644 --- a/crates/imap/src/op/acl.rs +++ b/crates/imap/src/op/acl.rs @@ -51,7 +51,7 @@ use crate::core::{MailboxId, Session, SessionData}; impl Session { pub async fn handle_get_acl(&mut self, request: Request) -> crate::OpResult { - match request.parse_acl() { + match request.parse_acl(self.version) { Ok(arguments) => { let data = self.state.session_data(); let is_rev2 = self.version.is_rev2(); @@ -165,7 +165,7 @@ impl Session { } pub async fn handle_my_rights(&mut self, request: Request) -> crate::OpResult { - match request.parse_acl() { + match request.parse_acl(self.version) { Ok(arguments) => { let data = self.state.session_data(); let is_rev2 = self.version.is_rev2(); @@ -265,7 +265,7 @@ impl Session { pub async fn handle_set_acl(&mut self, request: Request) -> crate::OpResult { let command = request.command; - match request.parse_acl() { + match request.parse_acl(self.version) { Ok(arguments) => { let data = self.state.session_data(); @@ -489,7 +489,7 @@ impl Session { } pub async fn handle_list_rights(&mut self, request: Request) -> crate::OpResult { - match request.parse_acl() { + match request.parse_acl(self.version) { Ok(arguments) => { self.write_bytes( StatusResponse::completed(Command::ListRights) diff --git a/crates/imap/src/op/append.rs b/crates/imap/src/op/append.rs index 90c33417..184bcf5a 100644 --- a/crates/imap/src/op/append.rs +++ b/crates/imap/src/op/append.rs @@ -36,7 +36,7 @@ use crate::core::{MailboxId, SelectedMailbox, Session, SessionData}; impl Session { pub async fn handle_append(&mut self, request: Request) -> crate::OpResult { - match request.parse_append() { + match request.parse_append(self.version) { Ok(arguments) => { let (data, selected_mailbox) = self.state.session_mailbox_state(); diff --git a/crates/imap/src/op/copy_move.rs b/crates/imap/src/op/copy_move.rs index 2edd9f57..5e2abf69 100644 --- a/crates/imap/src/op/copy_move.rs +++ b/crates/imap/src/op/copy_move.rs @@ -48,7 +48,7 @@ impl Session { is_move: bool, is_uid: bool, ) -> crate::OpResult { - match request.parse_copy_move() { + match request.parse_copy_move(self.version) { Ok(arguments) => { let (data, src_mailbox) = self.state.mailbox_state();