mirror of
https://github.com/chatmail/core.git
synced 2026-04-17 21:46:35 +03:00
275 lines
8.8 KiB
Rust
275 lines
8.8 KiB
Rust
use chrono::TimeZone as _;
|
|
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn test_vcard_thunderbird() {
|
|
let contacts = parse_vcard(
|
|
"BEGIN:VCARD
|
|
VERSION:4.0
|
|
FN:'Alice Mueller'
|
|
EMAIL;PREF=1:alice.mueller@posteo.de
|
|
UID:a8083264-ca47-4be7-98a8-8ec3db1447ca
|
|
END:VCARD
|
|
BEGIN:VCARD
|
|
VERSION:4.0
|
|
FN:'bobzzz@freenet.de'
|
|
EMAIL;PREF=1:bobzzz@freenet.de
|
|
UID:cac4fef4-6351-4854-bbe4-9b6df857eaed
|
|
END:VCARD
|
|
",
|
|
);
|
|
|
|
assert_eq!(contacts[0].addr, "alice.mueller@posteo.de".to_string());
|
|
assert_eq!(contacts[0].authname, "Alice Mueller".to_string());
|
|
assert_eq!(contacts[0].key, None);
|
|
assert_eq!(contacts[0].profile_image, None);
|
|
assert!(contacts[0].timestamp.is_err());
|
|
|
|
assert_eq!(contacts[1].addr, "bobzzz@freenet.de".to_string());
|
|
assert_eq!(contacts[1].authname, "".to_string());
|
|
assert_eq!(contacts[1].key, None);
|
|
assert_eq!(contacts[1].profile_image, None);
|
|
assert!(contacts[1].timestamp.is_err());
|
|
|
|
assert_eq!(contacts.len(), 2);
|
|
}
|
|
|
|
#[test]
|
|
fn test_vcard_simple_example() {
|
|
let contacts = parse_vcard(
|
|
"BEGIN:VCARD
|
|
VERSION:4.0
|
|
FN:Alice Wonderland
|
|
N:Wonderland;Alice;;;Ms.
|
|
GENDER:W
|
|
EMAIL;TYPE=work:alice@example.com
|
|
KEY;TYPE=PGP;ENCODING=b:[base64-data]
|
|
REV:20240418T184242Z
|
|
|
|
END:VCARD",
|
|
);
|
|
|
|
assert_eq!(contacts[0].addr, "alice@example.com".to_string());
|
|
assert_eq!(contacts[0].authname, "Alice Wonderland".to_string());
|
|
assert_eq!(contacts[0].key, Some("[base64-data]".to_string()));
|
|
assert_eq!(contacts[0].profile_image, None);
|
|
assert_eq!(*contacts[0].timestamp.as_ref().unwrap(), 1713465762);
|
|
|
|
assert_eq!(contacts.len(), 1);
|
|
}
|
|
|
|
#[test]
|
|
fn test_vcard_with_trailing_newline() {
|
|
let contacts = parse_vcard(
|
|
"BEGIN:VCARD\r
|
|
VERSION:4.0\r
|
|
FN:Alice Wonderland\r
|
|
N:Wonderland;Alice;;;Ms.\r
|
|
GENDER:W\r
|
|
EMAIL;TYPE=work:alice@example.com\r
|
|
KEY;TYPE=PGP;ENCODING=b:[base64-data]\r
|
|
REV:20240418T184242Z\r
|
|
END:VCARD\r
|
|
\r",
|
|
);
|
|
|
|
assert_eq!(contacts[0].addr, "alice@example.com".to_string());
|
|
assert_eq!(contacts[0].authname, "Alice Wonderland".to_string());
|
|
assert_eq!(contacts[0].key, Some("[base64-data]".to_string()));
|
|
assert_eq!(contacts[0].profile_image, None);
|
|
assert_eq!(*contacts[0].timestamp.as_ref().unwrap(), 1713465762);
|
|
|
|
assert_eq!(contacts.len(), 1);
|
|
}
|
|
|
|
#[test]
|
|
fn test_make_and_parse_vcard() {
|
|
let contacts = [
|
|
VcardContact {
|
|
addr: "alice@example.org".to_string(),
|
|
authname: "Alice Wonderland".to_string(),
|
|
key: Some("[base64-data]".to_string()),
|
|
profile_image: Some("image in Base64".to_string()),
|
|
timestamp: Ok(1713465762),
|
|
},
|
|
VcardContact {
|
|
addr: "bob@example.com".to_string(),
|
|
authname: "".to_string(),
|
|
key: None,
|
|
profile_image: None,
|
|
timestamp: Ok(0),
|
|
},
|
|
];
|
|
let items = [
|
|
"BEGIN:VCARD\r\n\
|
|
VERSION:4.0\r\n\
|
|
EMAIL:alice@example.org\r\n\
|
|
FN:Alice Wonderland\r\n\
|
|
KEY:data:application/pgp-keys;base64,[base64-data]\r\n\
|
|
PHOTO:data:image/jpeg;base64,image in Base64\r\n\
|
|
REV:20240418T184242Z\r\n\
|
|
END:VCARD\r\n",
|
|
"BEGIN:VCARD\r\n\
|
|
VERSION:4.0\r\n\
|
|
EMAIL:bob@example.com\r\n\
|
|
FN:bob@example.com\r\n\
|
|
REV:19700101T000000Z\r\n\
|
|
END:VCARD\r\n",
|
|
];
|
|
let mut expected = "".to_string();
|
|
for len in 0..=contacts.len() {
|
|
let contacts = &contacts[0..len];
|
|
let vcard = make_vcard(contacts);
|
|
if len > 0 {
|
|
expected += items[len - 1];
|
|
}
|
|
assert_eq!(vcard, expected);
|
|
let parsed = parse_vcard(&vcard);
|
|
assert_eq!(parsed.len(), contacts.len());
|
|
for i in 0..parsed.len() {
|
|
assert_eq!(parsed[i].addr, contacts[i].addr);
|
|
assert_eq!(parsed[i].authname, contacts[i].authname);
|
|
assert_eq!(parsed[i].key, contacts[i].key);
|
|
assert_eq!(parsed[i].profile_image, contacts[i].profile_image);
|
|
assert_eq!(
|
|
parsed[i].timestamp.as_ref().unwrap(),
|
|
contacts[i].timestamp.as_ref().unwrap()
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn test_vcard_android() {
|
|
let contacts = parse_vcard(
|
|
"BEGIN:VCARD
|
|
VERSION:2.1
|
|
N:;Bob;;;
|
|
FN:Bob
|
|
TEL;CELL:+1-234-567-890
|
|
EMAIL;HOME:bob@example.org
|
|
END:VCARD
|
|
BEGIN:VCARD
|
|
VERSION:2.1
|
|
N:;Alice;;;
|
|
FN:Alice
|
|
EMAIL;HOME:alice@example.org
|
|
END:VCARD
|
|
",
|
|
);
|
|
|
|
assert_eq!(contacts[0].addr, "bob@example.org".to_string());
|
|
assert_eq!(contacts[0].authname, "Bob".to_string());
|
|
assert_eq!(contacts[0].key, None);
|
|
assert_eq!(contacts[0].profile_image, None);
|
|
|
|
assert_eq!(contacts[1].addr, "alice@example.org".to_string());
|
|
assert_eq!(contacts[1].authname, "Alice".to_string());
|
|
assert_eq!(contacts[1].key, None);
|
|
assert_eq!(contacts[1].profile_image, None);
|
|
|
|
assert_eq!(contacts.len(), 2);
|
|
}
|
|
|
|
#[test]
|
|
fn test_vcard_local_datetime() {
|
|
let contacts = parse_vcard(
|
|
"BEGIN:VCARD\n\
|
|
VERSION:4.0\n\
|
|
FN:Alice Wonderland\n\
|
|
EMAIL;TYPE=work:alice@example.org\n\
|
|
REV:20240418T184242\n\
|
|
END:VCARD",
|
|
);
|
|
assert_eq!(contacts.len(), 1);
|
|
assert_eq!(contacts[0].addr, "alice@example.org".to_string());
|
|
assert_eq!(contacts[0].authname, "Alice Wonderland".to_string());
|
|
assert_eq!(
|
|
*contacts[0].timestamp.as_ref().unwrap(),
|
|
chrono::offset::Local
|
|
.with_ymd_and_hms(2024, 4, 18, 18, 42, 42)
|
|
.unwrap()
|
|
.timestamp()
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn test_vcard_with_base64_avatar() {
|
|
// This is not an actual base64-encoded avatar, it's just to test the parsing.
|
|
// This one is Android-like.
|
|
let vcard0 = "BEGIN:VCARD
|
|
VERSION:2.1
|
|
N:;Bob;;;
|
|
FN:Bob
|
|
EMAIL;HOME:bob@example.org
|
|
PHOTO;ENCODING=BASE64;JPEG:/9j/4AAQSkZJRgABAQAAAQABAAD/4gIoSUNDX1BST0ZJTEU
|
|
AAQEAAAIYAAAAAAQwAABtbnRyUkdCIFhZWiAAAAAAAAAAAAAAAABhY3NwAAAAAAAAAAAAAAAA
|
|
L8bRuAJYoZUYrI4ZY3VWwxw4Ay28AAGBISScmf/2Q==
|
|
|
|
END:VCARD
|
|
";
|
|
// This one is DOS-like.
|
|
let vcard1 = vcard0.replace('\n', "\r\n");
|
|
for vcard in [vcard0, vcard1.as_str()] {
|
|
let contacts = parse_vcard(vcard);
|
|
assert_eq!(contacts.len(), 1);
|
|
assert_eq!(contacts[0].addr, "bob@example.org".to_string());
|
|
assert_eq!(contacts[0].authname, "Bob".to_string());
|
|
assert_eq!(contacts[0].key, None);
|
|
assert_eq!(contacts[0].profile_image.as_deref().unwrap(), "/9j/4AAQSkZJRgABAQAAAQABAAD/4gIoSUNDX1BST0ZJTEUAAQEAAAIYAAAAAAQwAABtbnRyUkdCIFhZWiAAAAAAAAAAAAAAAABhY3NwAAAAAAAAAAAAAAAAL8bRuAJYoZUYrI4ZY3VWwxw4Ay28AAGBISScmf/2Q==");
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn test_protonmail_vcard() {
|
|
let contacts = parse_vcard(
|
|
"BEGIN:VCARD
|
|
VERSION:4.0
|
|
FN;PREF=1:Alice Wonderland
|
|
UID:proton-web-03747582-328d-38dc-5ddd-000000000000
|
|
ITEM1.EMAIL;PREF=1:alice@example.org
|
|
ITEM1.KEY;PREF=1:data:application/pgp-keys;base64,aaaaaaaaaaaaaaaaaaaaaaaaa
|
|
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
|
ITEM1.KEY;PREF=2:data:application/pgp-keys;base64,bbbbbbbbbbbbbbbbbbbbbbbbb
|
|
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
|
|
ITEM1.X-PM-ENCRYPT:true
|
|
ITEM1.X-PM-SIGN:true
|
|
END:VCARD",
|
|
);
|
|
|
|
assert_eq!(contacts.len(), 1);
|
|
assert_eq!(&contacts[0].addr, "alice@example.org");
|
|
assert_eq!(&contacts[0].authname, "Alice Wonderland");
|
|
assert_eq!(contacts[0].key.as_ref().unwrap(), "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
|
|
assert!(contacts[0].timestamp.is_err());
|
|
assert_eq!(contacts[0].profile_image, None);
|
|
}
|
|
|
|
/// Proton at some point slightly changed the format of their vcards
|
|
#[test]
|
|
fn test_protonmail_vcard2() {
|
|
let contacts = parse_vcard(
|
|
r"BEGIN:VCARD
|
|
VERSION:4.0
|
|
FN;PREF=1:Alice
|
|
PHOTO;PREF=1:data:image/jpeg;base64,/9aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
|
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
|
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/Z
|
|
REV:Invalid Date
|
|
ITEM1.EMAIL;PREF=1:alice@example.org
|
|
KEY;PREF=1:data:application/pgp-keys;base64,xsaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
|
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
|
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa==
|
|
UID:proton-web-aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa
|
|
END:VCARD",
|
|
);
|
|
|
|
assert_eq!(contacts.len(), 1);
|
|
assert_eq!(&contacts[0].addr, "alice@example.org");
|
|
assert_eq!(&contacts[0].authname, "Alice");
|
|
assert_eq!(contacts[0].key.as_ref().unwrap(), "xsaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa==");
|
|
assert!(contacts[0].timestamp.is_err());
|
|
assert_eq!(contacts[0].profile_image.as_ref().unwrap(), "/9aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/Z");
|
|
}
|