diff --git a/spec.md b/spec.md index 98dc91c57..bf25bb77e 100644 --- a/spec.md +++ b/spec.md @@ -1,6 +1,6 @@ # Chat-over-Email specification -Version 0.19.0 +Version 0.20.0 This document describes how emails can be used to implement typical messenger functions @@ -248,11 +248,11 @@ and the message SHOULD appear as a message or action from the sender. A group MAY have a group-image. To change or set the group-image, the messenger MUST attach an image file to a message -and MUST add the header `Chat-Group-Image` +and MUST add the header `Chat-Group-Avatar` with the value set to the image name. To remove the group-image, -the messenger MUST add the header `Chat-Group-Image: 0`. +the messenger MUST add the header `Chat-Group-Avatar: 0`. The messenger SHOULD send an explicit mail for each group image change. The body of the message SHOULD contain @@ -265,7 +265,7 @@ and the message SHOULD appear as a message or action from the sender. Chat-Version: 1.0 Chat-Group-ID: 12345uvwxyZ Chat-Group-Name: Our Group - Chat-Group-Image: image.jpg + Chat-Group-Avatar: image.jpg Message-ID: Gr.12345uvwxyZ.0005@domain Subject: Chat: Our Group: Hello, ... Content-Type: multipart/mixed; boundary="==break==" @@ -283,7 +283,7 @@ and the message SHOULD appear as a message or action from the sender. The image format SHOULD be image/jpeg or image/png. To save data, it is RECOMMENDED -to add a `Chat-Group-Image` only on image changes. +to add a `Chat-Group-Avatar` only on image changes. # Set profile image @@ -291,17 +291,17 @@ to add a `Chat-Group-Image` only on image changes. A user MAY have a profile-image that MAY be spread to their contacts. To change or set the profile-image, the messenger MUST attach an image file to a message -and MUST add the header `Chat-Profile-Image` +and MUST add the header `Chat-User-Avatar` with the value set to the image name. To remove the profile-image, -the messenger MUST add the header `Chat-Profile-Image: 0`. +the messenger MUST add the header `Chat-User-Avatar: 0`. To spread the image, the messenger MAY send the profile image together with the next mail to a given contact (to do this only once, -the messenger has to keep a `profile_image_update_state` somewhere). +the messenger has to keep a `user_avatar_update_state` somewhere). Alternatively, the messenger MAY send an explicit mail for each profile-image change to all contacts using a compatible messenger. The messenger SHOULD NOT send an explicit mail to normal MUAs. @@ -309,7 +309,7 @@ The messenger SHOULD NOT send an explicit mail to normal MUAs. From: sender@domain To: rcpt@domain Chat-Version: 1.0 - Chat-Profile-Image: photo.jpg + Chat-User-Avatar: photo.jpg Subject: Chat: Hello, ... Content-Type: multipart/mixed; boundary="==break==" @@ -325,10 +325,10 @@ The messenger SHOULD NOT send an explicit mail to normal MUAs. --==break==-- The image format SHOULD be image/jpeg or image/png. -Note that `Chat-Profile-Image` may appear together with all other headers, -eg. there may be a `Chat-Profile-Image` and a `Chat-Group-Image` header +Note that `Chat-User-Avatar` may appear together with all other headers, +eg. there may be a `Chat-User-Avatar` and a `Chat-Group-Avatar` header in the same message. -To save data, it is RECOMMENDED to add a `Chat-Profile-Image` header +To save data, it is RECOMMENDED to add a `Chat-User-Avatar` header only on image changes. diff --git a/src/contact.rs b/src/contact.rs index df0c76970..1214adba9 100644 --- a/src/contact.rs +++ b/src/contact.rs @@ -15,7 +15,7 @@ use crate::events::Event; use crate::key::*; use crate::login_param::LoginParam; use crate::message::{MessageState, MsgId}; -use crate::mimeparser::ImageAction; +use crate::mimeparser::AvatarAction; use crate::param::*; use crate::peerstate::*; use crate::sql; @@ -966,21 +966,21 @@ fn set_block_contact(context: &Context, contact_id: u32, new_blocking: bool) { pub fn set_profile_image( context: &Context, contact_id: u32, - profile_image: ImageAction, + profile_image: AvatarAction, ) -> Result<()> { // the given profile image is expected to be already in the blob directory // as profile images can be set only by receiving messages, this should be always the case, however. let mut contact = Contact::load_from_db(context, contact_id)?; let changed = match profile_image { - ImageAction::Change(profile_image) => { + AvatarAction::Change(profile_image) => { contact.param.set(Param::ProfileImage, profile_image); true } - ImageAction::Delete => { + AvatarAction::Delete => { contact.param.remove(Param::ProfileImage); true } - ImageAction::None => false, + AvatarAction::None => false, }; if changed { contact.update_param(context)?; diff --git a/src/dc_receive_imf.rs b/src/dc_receive_imf.rs index 8347e206c..5a0588a04 100644 --- a/src/dc_receive_imf.rs +++ b/src/dc_receive_imf.rs @@ -237,8 +237,8 @@ pub fn dc_receive_imf( ); } - if mime_parser.profile_image != ImageAction::None { - match contact::set_profile_image(&context, from_id, mime_parser.profile_image) { + if mime_parser.user_avatar != AvatarAction::None { + match contact::set_profile_image(&context, from_id, mime_parser.user_avatar) { Ok(()) => { context.call_cb(Event::ChatModified(chat_id)); true @@ -898,13 +898,13 @@ fn create_or_lookup_group( mime_parser.is_system_message = SystemMessage::GroupNameChanged; } else if let Some(value) = mime_parser.get(HeaderDef::ChatContent).cloned() { - if value == "group-avatar-changed" && mime_parser.group_avatar != ImageAction::None + if value == "group-avatar-changed" && mime_parser.group_avatar != AvatarAction::None { // this is just an explicit message containing the group-avatar, // apart from that, the group-avatar is send along with various other messages mime_parser.is_system_message = SystemMessage::GroupImageChanged; better_msg = context.stock_system_msg( - if mime_parser.group_avatar == ImageAction::Delete { + if mime_parser.group_avatar == AvatarAction::Delete { StockMessage::MsgGrpImgDeleted } else { StockMessage::MsgGrpImgChanged @@ -1036,19 +1036,19 @@ fn create_or_lookup_group( } } } - if mime_parser.group_avatar != ImageAction::None { + if mime_parser.group_avatar != AvatarAction::None { info!(context, "group-avatar change for {}", chat_id); if let Ok(mut chat) = Chat::load_from_db(context, chat_id) { match &mime_parser.group_avatar { - ImageAction::Change(profile_image) => { + AvatarAction::Change(profile_image) => { chat.param.set(Param::ProfileImage, profile_image); true } - ImageAction::Delete => { + AvatarAction::Delete => { chat.param.remove(Param::ProfileImage); true } - ImageAction::None => false, + AvatarAction::None => false, }; chat.update_param(context)?; send_EVENT_CHAT_MODIFIED = true; diff --git a/src/headerdef.rs b/src/headerdef.rs index c362a2004..32eb51e91 100644 --- a/src/headerdef.rs +++ b/src/headerdef.rs @@ -20,7 +20,7 @@ pub enum HeaderDef { ChatGroupNameChanged, ChatVerified, ChatGroupAvatar, - ChatProfileImage, + ChatUserAvatar, ChatVoiceMessage, ChatGroupMemberRemoved, ChatGroupMemberAdded, diff --git a/src/mimefactory.rs b/src/mimefactory.rs index 75f114ac2..4705224c5 100644 --- a/src/mimefactory.rs +++ b/src/mimefactory.rs @@ -895,13 +895,11 @@ impl<'a, 'b> MimeFactory<'a, 'b> { Some(path) => match build_selfavatar_file(context, path) { Ok((part, filename)) => { parts.push(part); - protected_headers.push(Header::new("Chat-Profile-Image".into(), filename)) + protected_headers.push(Header::new("Chat-User-Avatar".into(), filename)) } Err(err) => warn!(context, "mimefactory: cannot attach selfavatar: {}", err), }, - None => { - protected_headers.push(Header::new("Chat-Profile-Image".into(), "0".into())) - } + None => protected_headers.push(Header::new("Chat-User-Avatar".into(), "0".into())), } } diff --git a/src/mimeparser.rs b/src/mimeparser.rs index 688f60a05..a9cb7578e 100644 --- a/src/mimeparser.rs +++ b/src/mimeparser.rs @@ -37,15 +37,15 @@ pub struct MimeParser<'a> { pub is_system_message: SystemMessage, pub location_kml: Option, pub message_kml: Option, - pub profile_image: ImageAction, - pub group_avatar: ImageAction, + pub user_avatar: AvatarAction, + pub group_avatar: AvatarAction, reports: Vec, mdns_enabled: bool, parsed_protected_headers: bool, } #[derive(Debug, PartialEq)] -pub enum ImageAction { +pub enum AvatarAction { None, Delete, Change(String), @@ -92,8 +92,8 @@ impl<'a> MimeParser<'a> { is_system_message: SystemMessage::Unknown, location_kml: None, message_kml: None, - profile_image: ImageAction::None, - group_avatar: ImageAction::None, + user_avatar: AvatarAction::None, + group_avatar: AvatarAction::None, mdns_enabled, parsed_protected_headers: false, }; @@ -194,11 +194,11 @@ impl<'a> MimeParser<'a> { } if let Some(header_value) = self.get(HeaderDef::ChatGroupAvatar).cloned() { - self.group_avatar = self.image_action_from_header(header_value); + self.group_avatar = self.avatar_action_from_header(header_value); } - if let Some(header_value) = self.get(HeaderDef::ChatProfileImage).cloned() { - self.profile_image = self.image_action_from_header(header_value); + if let Some(header_value) = self.get(HeaderDef::ChatUserAvatar).cloned() { + self.user_avatar = self.avatar_action_from_header(header_value); } if self.has_chat_version() && self.parts.len() == 2 { @@ -332,9 +332,9 @@ impl<'a> MimeParser<'a> { Ok(()) } - fn image_action_from_header(&mut self, header_value: String) -> ImageAction { + fn avatar_action_from_header(&mut self, header_value: String) -> AvatarAction { if header_value == "0" { - return ImageAction::Delete; + return AvatarAction::Delete; } else { let mut i = 0; while i != self.parts.len() { @@ -342,7 +342,7 @@ impl<'a> MimeParser<'a> { if let Some(part_filename) = &part.org_filename { if part_filename == &header_value { if let Some(blob) = part.param.get(Param::File) { - let res = ImageAction::Change(blob.to_string()); + let res = AvatarAction::Change(blob.to_string()); self.parts.remove(i); return res; } @@ -352,7 +352,7 @@ impl<'a> MimeParser<'a> { i += 1; } } - ImageAction::None + AvatarAction::None } pub fn get_last_nonmeta(&self) -> Option<&Part> { @@ -1164,25 +1164,25 @@ mod tests { } #[test] - fn test_mimeparser_with_profile_image() { + fn test_mimeparser_with_user_avatar() { let t = dummy_context(); let raw = include_bytes!("../test-data/message/mail_attach_txt.eml"); let mimeparser = MimeParser::from_bytes(&t.ctx, &raw[..]).unwrap(); - assert_eq!(mimeparser.profile_image, ImageAction::None); - assert_eq!(mimeparser.group_avatar, ImageAction::None); + assert_eq!(mimeparser.user_avatar, AvatarAction::None); + assert_eq!(mimeparser.group_avatar, AvatarAction::None); - let raw = include_bytes!("../test-data/message/mail_with_profile_image.eml"); + let raw = include_bytes!("../test-data/message/mail_with_user_avatar.eml"); let mimeparser = MimeParser::from_bytes(&t.ctx, &raw[..]).unwrap(); assert_eq!(mimeparser.parts.len(), 1); - assert_ne!(mimeparser.profile_image, ImageAction::None); - assert_ne!(mimeparser.profile_image, ImageAction::Delete); - assert_eq!(mimeparser.group_avatar, ImageAction::None); + assert_ne!(mimeparser.user_avatar, AvatarAction::None); + assert_ne!(mimeparser.user_avatar, AvatarAction::Delete); + assert_eq!(mimeparser.group_avatar, AvatarAction::None); - let raw = include_bytes!("../test-data/message/mail_with_profile_image_deleted.eml"); + let raw = include_bytes!("../test-data/message/mail_with_user_avatar_deleted.eml"); let mimeparser = MimeParser::from_bytes(&t.ctx, &raw[..]).unwrap(); assert_eq!(mimeparser.parts.len(), 1); - assert_eq!(mimeparser.profile_image, ImageAction::Delete); - assert_eq!(mimeparser.group_avatar, ImageAction::None); + assert_eq!(mimeparser.user_avatar, AvatarAction::Delete); + assert_eq!(mimeparser.group_avatar, AvatarAction::None); } } diff --git a/test-data/message/mail_with_profile_image.eml b/test-data/message/mail_with_user_avatar.eml similarity index 98% rename from test-data/message/mail_with_profile_image.eml rename to test-data/message/mail_with_user_avatar.eml index e7f4a21d4..ee9df8458 100644 --- a/test-data/message/mail_with_profile_image.eml +++ b/test-data/message/mail_with_user_avatar.eml @@ -1,4 +1,4 @@ -Chat-Profile-Image: avatar.png +Chat-User-Avatar: avatar.png Subject: =?utf-8?q?Chat=3A_this_is_a_message_with_a_=2E=2E=2E?= Message-ID: Mr.wOBwZNbBTVt.NZpmQDwWoNk@example.org In-Reply-To: Mr.ETXqza5-WpB.zDEYOLECxAw@example.org diff --git a/test-data/message/mail_with_profile_image_deleted.eml b/test-data/message/mail_with_user_avatar_deleted.eml similarity index 94% rename from test-data/message/mail_with_profile_image_deleted.eml rename to test-data/message/mail_with_user_avatar_deleted.eml index 08e4f7dfa..37550901e 100644 --- a/test-data/message/mail_with_profile_image_deleted.eml +++ b/test-data/message/mail_with_user_avatar_deleted.eml @@ -1,5 +1,5 @@ Content-Type: text/plain; charset=utf-8 -Chat-Profile-Image: 0 +Chat-User-Avatar: 0 Subject: =?utf-8?q?Chat=3A_profile_image_deleted?= Message-ID: Mr.tsgoJgn-cBf.0TkFWKJzeSp@example.org Date: Sun, 08 Dec 2019 23:28:30 +0000