mirror of
https://github.com/chatmail/core.git
synced 2026-05-16 21:36:30 +03:00
fix: do not ignore I/O errors in BlobObject::store_from_base64
This commit is contained in:
11
src/blob.rs
11
src/blob.rs
@@ -234,8 +234,13 @@ impl<'a> BlobObject<'a> {
|
|||||||
/// If `data` represents an image of known format, this adds the corresponding extension.
|
/// If `data` represents an image of known format, this adds the corresponding extension.
|
||||||
///
|
///
|
||||||
/// Even though this function is not async, it's OK to call it from an async context.
|
/// Even though this function is not async, it's OK to call it from an async context.
|
||||||
pub(crate) fn store_from_base64(context: &Context, data: &str) -> Result<String> {
|
///
|
||||||
let buf = base64::engine::general_purpose::STANDARD.decode(data)?;
|
/// Returns an error if there is an I/O problem,
|
||||||
|
/// but in case of a failure to decode base64 returns `Ok(None)`.
|
||||||
|
pub(crate) fn store_from_base64(context: &Context, data: &str) -> Result<Option<String>> {
|
||||||
|
let Ok(buf) = base64::engine::general_purpose::STANDARD.decode(data) else {
|
||||||
|
return Ok(None);
|
||||||
|
};
|
||||||
let name = if let Ok(format) = image::guess_format(&buf) {
|
let name = if let Ok(format) = image::guess_format(&buf) {
|
||||||
if let Some(ext) = format.extensions_str().first() {
|
if let Some(ext) = format.extensions_str().first() {
|
||||||
format!("file.{ext}")
|
format!("file.{ext}")
|
||||||
@@ -246,7 +251,7 @@ impl<'a> BlobObject<'a> {
|
|||||||
String::new()
|
String::new()
|
||||||
};
|
};
|
||||||
let blob = BlobObject::create_and_deduplicate_from_bytes(context, &buf, &name)?;
|
let blob = BlobObject::create_and_deduplicate_from_bytes(context, &buf, &name)?;
|
||||||
Ok(blob.as_name().to_string())
|
Ok(Some(blob.as_name().to_string()))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Recode image to avatar size.
|
/// Recode image to avatar size.
|
||||||
|
|||||||
@@ -665,7 +665,7 @@ impl Context {
|
|||||||
Config::Selfavatar if value.is_empty() => None,
|
Config::Selfavatar if value.is_empty() => None,
|
||||||
Config::Selfavatar => {
|
Config::Selfavatar => {
|
||||||
config_value = BlobObject::store_from_base64(self, value)?;
|
config_value = BlobObject::store_from_base64(self, value)?;
|
||||||
Some(config_value.as_str())
|
config_value.as_deref()
|
||||||
}
|
}
|
||||||
_ => Some(value),
|
_ => Some(value),
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -369,16 +369,15 @@ async fn import_vcard_contact(context: &Context, contact: &VcardContact) -> Resu
|
|||||||
return Ok(id);
|
return Ok(id);
|
||||||
}
|
}
|
||||||
let path = match &contact.profile_image {
|
let path = match &contact.profile_image {
|
||||||
Some(image) => match BlobObject::store_from_base64(context, image) {
|
Some(image) => match BlobObject::store_from_base64(context, image)? {
|
||||||
Err(e) => {
|
None => {
|
||||||
warn!(
|
warn!(
|
||||||
context,
|
context,
|
||||||
"import_vcard_contact: Could not decode and save avatar for {}: {e:#}.",
|
"import_vcard_contact: Could not decode avatar for {}.", contact.addr
|
||||||
contact.addr
|
|
||||||
);
|
);
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
Ok(path) => Some(path),
|
Some(path) => Some(path),
|
||||||
},
|
},
|
||||||
None => None,
|
None => None,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -714,14 +714,16 @@ impl MimeMessage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Parses avatar action headers.
|
/// Parses avatar action headers.
|
||||||
fn parse_avatar_headers(&mut self, context: &Context) {
|
fn parse_avatar_headers(&mut self, context: &Context) -> Result<()> {
|
||||||
if let Some(header_value) = self.get_header(HeaderDef::ChatGroupAvatar) {
|
if let Some(header_value) = self.get_header(HeaderDef::ChatGroupAvatar) {
|
||||||
self.group_avatar = self.avatar_action_from_header(context, header_value.to_string());
|
self.group_avatar =
|
||||||
|
self.avatar_action_from_header(context, header_value.to_string())?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(header_value) = self.get_header(HeaderDef::ChatUserAvatar) {
|
if let Some(header_value) = self.get_header(HeaderDef::ChatUserAvatar) {
|
||||||
self.user_avatar = self.avatar_action_from_header(context, header_value.to_string());
|
self.user_avatar = self.avatar_action_from_header(context, header_value.to_string())?;
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_videochat_headers(&mut self) {
|
fn parse_videochat_headers(&mut self) {
|
||||||
@@ -828,7 +830,7 @@ impl MimeMessage {
|
|||||||
|
|
||||||
async fn parse_headers(&mut self, context: &Context) -> Result<()> {
|
async fn parse_headers(&mut self, context: &Context) -> Result<()> {
|
||||||
self.parse_system_message_headers(context);
|
self.parse_system_message_headers(context);
|
||||||
self.parse_avatar_headers(context);
|
self.parse_avatar_headers(context)?;
|
||||||
self.parse_videochat_headers();
|
self.parse_videochat_headers();
|
||||||
if self.delivery_report.is_none() {
|
if self.delivery_report.is_none() {
|
||||||
self.squash_attachment_parts();
|
self.squash_attachment_parts();
|
||||||
@@ -930,21 +932,18 @@ impl MimeMessage {
|
|||||||
&mut self,
|
&mut self,
|
||||||
context: &Context,
|
context: &Context,
|
||||||
header_value: String,
|
header_value: String,
|
||||||
) -> Option<AvatarAction> {
|
) -> Result<Option<AvatarAction>> {
|
||||||
if header_value == "0" {
|
let res = if header_value == "0" {
|
||||||
Some(AvatarAction::Delete)
|
Some(AvatarAction::Delete)
|
||||||
} else if let Some(base64) = header_value
|
} else if let Some(base64) = header_value
|
||||||
.split_ascii_whitespace()
|
.split_ascii_whitespace()
|
||||||
.collect::<String>()
|
.collect::<String>()
|
||||||
.strip_prefix("base64:")
|
.strip_prefix("base64:")
|
||||||
{
|
{
|
||||||
match BlobObject::store_from_base64(context, base64) {
|
match BlobObject::store_from_base64(context, base64)? {
|
||||||
Ok(path) => Some(AvatarAction::Change(path)),
|
Some(path) => Some(AvatarAction::Change(path)),
|
||||||
Err(err) => {
|
None => {
|
||||||
warn!(
|
warn!(context, "Could not decode avatar base64");
|
||||||
context,
|
|
||||||
"Could not decode and save avatar to blob file: {:#}", err,
|
|
||||||
);
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -958,7 +957,7 @@ impl MimeMessage {
|
|||||||
if let Some(blob) = part.param.get(Param::File) {
|
if let Some(blob) = part.param.get(Param::File) {
|
||||||
let res = Some(AvatarAction::Change(blob.to_string()));
|
let res = Some(AvatarAction::Change(blob.to_string()));
|
||||||
self.parts.remove(i);
|
self.parts.remove(i);
|
||||||
return res;
|
return Ok(res);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -966,7 +965,8 @@ impl MimeMessage {
|
|||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
};
|
||||||
|
Ok(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if the message was encrypted as defined in
|
/// Returns true if the message was encrypted as defined in
|
||||||
|
|||||||
Reference in New Issue
Block a user