mirror of
https://github.com/chatmail/core.git
synced 2026-04-26 01:46:34 +03:00
Fix ephemeral timer rollback protection
Implement get_previous_message() that only looks for the last Message-ID in the References: header instead of using get_parent_message() which falls back to using other Message-IDs from References and In-Reply-To field.
This commit is contained in:
@@ -872,19 +872,17 @@ async fn add_parts(
|
||||
chat_id
|
||||
);
|
||||
if is_dc_message == MessengerMessage::Yes
|
||||
&& mime_parser
|
||||
.parts
|
||||
.get(0)
|
||||
.and_then(|part| part.param.get(Param::Quote))
|
||||
.is_none()
|
||||
&& parent.map(|p| p.ephemeral_timer) == Some(ephemeral_timer)
|
||||
&& get_previous_message(context, mime_parser)
|
||||
.await?
|
||||
.map(|p| p.ephemeral_timer)
|
||||
== Some(ephemeral_timer)
|
||||
{
|
||||
// The message is a Delta Chat message without a quote, so it must be a reply to the
|
||||
// last message in the chat as seen by the sender. The timer is the same in both the
|
||||
// received message and its parent, so we know that the sender has not seen any change
|
||||
// of the timer between these messages. As our timer value is different, it means the
|
||||
// sender has not received some timer update that we have seen or sent ourselves, so we
|
||||
// ignore incoming timer to prevent a rollback.
|
||||
// The message is a Delta Chat message, so we know that previous message according to
|
||||
// References header is the last message in the chat as seen by the sender. The timer
|
||||
// is the same in both the received message and the last message, so we know that the
|
||||
// sender has not seen any change of the timer between these messages. As our timer
|
||||
// value is different, it means the sender has not received some timer update that we
|
||||
// have seen or sent ourselves, so we ignore incoming timer to prevent a rollback.
|
||||
warn!(
|
||||
context,
|
||||
"ignoring ephemeral timer change to {:?} for chat {} to avoid rollback",
|
||||
@@ -2148,6 +2146,23 @@ fn set_better_msg(mime_parser: &mut MimeMessage, better_msg: impl AsRef<str>) {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the last message referenced from `References` header if it is in the database.
|
||||
///
|
||||
/// For Delta Chat messages it is the last message in the chat of the sender.
|
||||
async fn get_previous_message(
|
||||
context: &Context,
|
||||
mime_parser: &MimeMessage,
|
||||
) -> Result<Option<Message>> {
|
||||
if let Some(field) = mime_parser.get_header(HeaderDef::References) {
|
||||
if let Some(rfc724mid) = parse_message_ids(field).last() {
|
||||
if let Some((_, _, msg_id)) = rfc724_mid_exists(context, rfc724mid).await? {
|
||||
return Ok(Some(Message::load_from_db(context, msg_id).await?));
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
/// Given a list of Message-IDs, returns the latest message found in the database.
|
||||
async fn get_rfc724_mid_in_list(context: &Context, mid_list: &str) -> Result<Option<Message>> {
|
||||
if mid_list.is_empty() {
|
||||
|
||||
Reference in New Issue
Block a user