From 98b52aa78d7f781fd8d2ffabda4a1b796816c445 Mon Sep 17 00:00:00 2001 From: mdecimus Date: Mon, 25 Nov 2024 18:41:11 +1300 Subject: [PATCH] Fix UTF8 support in IMAP4rev1 (fixes #948) --- crates/imap-proto/src/parser/create.rs | 8 ++++++++ crates/imap-proto/src/receiver.rs | 8 ++++++++ crates/imap-proto/src/utf7.rs | 19 ++++++++++--------- 3 files changed, 26 insertions(+), 9 deletions(-) diff --git a/crates/imap-proto/src/parser/create.rs b/crates/imap-proto/src/parser/create.rs index 789bca2a..683c5eb2 100644 --- a/crates/imap-proto/src/parser/create.rs +++ b/crates/imap-proto/src/parser/create.rs @@ -121,6 +121,14 @@ mod tests { mailbox_role: Some("important"), }, ), + ( + "A142 CREATE \"Test-ąęć-Test\"\r\n", + create::Arguments { + tag: "A142".to_string(), + mailbox_name: "Test-ąęć-Test".to_string(), + mailbox_role: None, + }, + ), ] { assert_eq!( receiver diff --git a/crates/imap-proto/src/receiver.rs b/crates/imap-proto/src/receiver.rs index dacc2a32..568a6115 100644 --- a/crates/imap-proto/src/receiver.rs +++ b/crates/imap-proto/src/receiver.rs @@ -865,6 +865,14 @@ mod tests { ], }], ), + ( + vec!["TAG3 CREATE \"Test-ąęć-Test\"\r\n"], + vec![Request { + tag: "TAG3".to_string(), + command: Command::Create, + tokens: vec![Token::Argument("Test-ąęć-Test".as_bytes().to_vec())], + }], + ), ( vec!["abc LOGIN {0}\r\n", "\r\n"], vec![Request { diff --git a/crates/imap-proto/src/utf7.rs b/crates/imap-proto/src/utf7.rs index 0524e7f5..4af7cdfa 100644 --- a/crates/imap-proto/src/utf7.rs +++ b/crates/imap-proto/src/utf7.rs @@ -20,20 +20,20 @@ static UTF_7_RANK: &[u8] = &[ static UTF_7_MAP: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+,"; -pub fn utf7_decode(text: &[u8]) -> Option { +pub fn utf7_decode(text: &str) -> Option { let mut bytes: Vec = Vec::with_capacity(text.len()); let mut bits = 0; let mut v: u32 = 0; let mut shifted = false; - let mut text = text.iter().peekable(); + let mut text = text.chars().peekable(); - while let Some(&ch) = text.next() { + while let Some(ch) = text.next() { if shifted { - if ch == b'-' { + if ch == '-' { shifted = false; bits = 0; v = 0; - } else if ch > 127 { + } else if ch as usize > 127 { return None; } else { let rank = *UTF_7_RANK.get(ch as usize)?; @@ -50,9 +50,9 @@ pub fn utf7_decode(text: &[u8]) -> Option { bits -= 16; } } - } else if ch == b'&' { + } else if ch == '&' { match text.peek() { - Some(b'-') => { + Some('-') => { bytes.push(b'&' as u16); text.next(); } @@ -126,7 +126,7 @@ pub fn utf7_maybe_decode(text: String, version: ProtocolVersion) -> String { if version.is_rev2() { text } else { - utf7_decode(text.as_bytes()).unwrap_or(text) + utf7_decode(&text).unwrap_or(text) } } @@ -159,9 +159,10 @@ mod tests { "四書五經, 宋元人注, 北京: 中國書店, 1990." ), ), + ("Test-ąęć-Test", "Test-ąęć-Test"), ] { assert_eq!( - super::utf7_decode(input.as_bytes()).expect(input), + super::utf7_decode(input).expect(input), expected_result, "while decoding {:?}", input