1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
extern crate base64;
extern crate encoding_rs;
extern crate regex;
use encoding_rs::UTF_16BE;
use regex::Regex;
pub fn decode_utf7_imap(text: String) -> String {
let re = Regex::new(r"&[^&-]*-").unwrap();
let mut result = text.clone();
for cap in re.captures_iter(&text) {
let encoded_text = cap.get(0).map_or("", |m| m.as_str());
let decoded_text = decode_utf7_part(String::from(encoded_text));
result = result.replace(&encoded_text, &decoded_text);
}
return result;
}
fn decode_utf7_part(text: String) -> String {
if text == "&-" {
return String::from("&");
}
let text_mb64 = &text[1..text.len() - 1];
let mut text_b64 = text_mb64.replace(",", "/");
while (text_b64.len() % 4) != 0 {
text_b64 += "=";
}
let text_u16 = base64::decode(text_b64).unwrap();
let (cow, _encoding_used, _had_errors) = UTF_16BE.decode(&text_u16);
let result = cow.as_ref();
return String::from(result);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn decode_test() {
let test_string = String::from("&BB4EQgQ,BEAEMAQyBDsENQQ9BD0ESwQ1-");
assert_eq!(decode_utf7_imap(test_string), "Отправленные");
}
#[test]
fn decode_test_split() {
let test_string = String::from("&AWA-iuk&AWE-liad&ARcBfgEX-");
assert_eq!(decode_utf7_imap(test_string), "Šiukšliadėžė")
}
}