mirror of
https://github.com/chatmail/core.git
synced 2026-04-27 02:16:29 +03:00
api!: remove dc_prepare_msg and dc_msg_is_increation
This commit is contained in:
35
src/blob.rs
35
src/blob.rs
@@ -763,7 +763,6 @@ mod tests {
|
||||
use fs::File;
|
||||
|
||||
use super::*;
|
||||
use crate::chat::{self, create_group_chat, ProtectionStatus};
|
||||
use crate::message::{Message, Viewtype};
|
||||
use crate::test_utils::{self, TestContext};
|
||||
|
||||
@@ -1456,38 +1455,4 @@ mod tests {
|
||||
check_image_size(file_saved, width, height);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn test_increation_in_blobdir() -> Result<()> {
|
||||
let t = TestContext::new_alice().await;
|
||||
let chat_id = create_group_chat(&t, ProtectionStatus::Unprotected, "abc").await?;
|
||||
|
||||
let file = t.get_blobdir().join("anyfile.dat");
|
||||
fs::write(&file, b"bla").await?;
|
||||
let mut msg = Message::new(Viewtype::File);
|
||||
msg.set_file(file.to_str().unwrap(), None);
|
||||
let prepared_id = chat::prepare_msg(&t, chat_id, &mut msg).await?;
|
||||
assert_eq!(prepared_id, msg.id);
|
||||
assert!(msg.is_increation());
|
||||
|
||||
let msg = Message::load_from_db(&t, prepared_id).await?;
|
||||
assert!(msg.is_increation());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn test_increation_not_blobdir() -> Result<()> {
|
||||
let t = TestContext::new_alice().await;
|
||||
let chat_id = create_group_chat(&t, ProtectionStatus::Unprotected, "abc").await?;
|
||||
assert_ne!(t.get_blobdir().to_str(), t.dir.path().to_str());
|
||||
|
||||
let file = t.dir.path().join("anyfile.dat");
|
||||
fs::write(&file, b"bla").await?;
|
||||
let mut msg = Message::new(Viewtype::File);
|
||||
msg.set_file(file.to_str().unwrap(), None);
|
||||
assert!(chat::prepare_msg(&t, chat_id, &mut msg).await.is_err());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
269
src/chat.rs
269
src/chat.rs
@@ -888,7 +888,7 @@ impl ChatId {
|
||||
_ => {
|
||||
let blob = msg
|
||||
.param
|
||||
.get_blob(Param::File, context, !msg.is_increation())
|
||||
.get_blob(Param::File, context)
|
||||
.await?
|
||||
.context("no file stored in params")?;
|
||||
msg.param.set(Param::File, blob.as_name());
|
||||
@@ -2677,26 +2677,13 @@ impl ChatIdBlocked {
|
||||
}
|
||||
}
|
||||
|
||||
/// Prepares a message for sending.
|
||||
pub async fn prepare_msg(context: &Context, chat_id: ChatId, msg: &mut Message) -> Result<MsgId> {
|
||||
ensure!(
|
||||
!chat_id.is_special(),
|
||||
"Cannot prepare message for special chat"
|
||||
);
|
||||
|
||||
let msg_id = prepare_msg_common(context, chat_id, msg, MessageState::OutPreparing).await?;
|
||||
context.emit_msgs_changed(msg.chat_id, msg.id);
|
||||
|
||||
Ok(msg_id)
|
||||
}
|
||||
|
||||
async fn prepare_msg_blob(context: &Context, msg: &mut Message) -> Result<()> {
|
||||
if msg.viewtype == Viewtype::Text || msg.viewtype == Viewtype::VideochatInvitation {
|
||||
// the caller should check if the message text is empty
|
||||
} else if msg.viewtype.has_file() {
|
||||
let mut blob = msg
|
||||
.param
|
||||
.get_blob(Param::File, context, !msg.is_increation())
|
||||
.get_blob(Param::File, context)
|
||||
.await?
|
||||
.with_context(|| format!("attachment missing for message of type #{}", msg.viewtype))?;
|
||||
let send_as_is = msg.viewtype == Viewtype::File;
|
||||
@@ -2771,13 +2758,92 @@ async fn prepare_msg_blob(context: &Context, msg: &mut Message) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Returns whether a contact is in a chat or not.
|
||||
pub async fn is_contact_in_chat(
|
||||
context: &Context,
|
||||
chat_id: ChatId,
|
||||
contact_id: ContactId,
|
||||
) -> Result<bool> {
|
||||
// this function works for group and for normal chats, however, it is more useful
|
||||
// for group chats.
|
||||
// ContactId::SELF may be used to check, if the user itself is in a group
|
||||
// chat (ContactId::SELF is not added to normal chats)
|
||||
|
||||
let exists = context
|
||||
.sql
|
||||
.exists(
|
||||
"SELECT COUNT(*) FROM chats_contacts WHERE chat_id=? AND contact_id=?;",
|
||||
(chat_id, contact_id),
|
||||
)
|
||||
.await?;
|
||||
Ok(exists)
|
||||
}
|
||||
|
||||
/// Sends a message object to a chat.
|
||||
///
|
||||
/// Sends the event #DC_EVENT_MSGS_CHANGED on success.
|
||||
/// However, this does not imply, the message really reached the recipient -
|
||||
/// sending may be delayed eg. due to network problems. However, from your
|
||||
/// view, you're done with the message. Sooner or later it will find its way.
|
||||
pub async fn send_msg(context: &Context, chat_id: ChatId, msg: &mut Message) -> Result<MsgId> {
|
||||
ensure!(
|
||||
!chat_id.is_special(),
|
||||
"chat_id cannot be a special chat: {chat_id}"
|
||||
);
|
||||
|
||||
if msg.state != MessageState::Undefined && msg.state != MessageState::OutPreparing {
|
||||
msg.param.remove(Param::GuaranteeE2ee);
|
||||
msg.param.remove(Param::ForcePlaintext);
|
||||
msg.update_param(context).await?;
|
||||
}
|
||||
|
||||
// protect all system messages against RTLO attacks
|
||||
if msg.is_system_message() {
|
||||
msg.text = sanitize_bidi_characters(&msg.text);
|
||||
}
|
||||
|
||||
if !prepare_send_msg(context, chat_id, msg).await?.is_empty() {
|
||||
if !msg.hidden {
|
||||
context.emit_msgs_changed(msg.chat_id, msg.id);
|
||||
}
|
||||
|
||||
if msg.param.exists(Param::SetLatitude) {
|
||||
context.emit_location_changed(Some(ContactId::SELF)).await?;
|
||||
}
|
||||
|
||||
context.scheduler.interrupt_smtp().await;
|
||||
}
|
||||
|
||||
Ok(msg.id)
|
||||
}
|
||||
|
||||
/// Tries to send a message synchronously.
|
||||
///
|
||||
/// Creates jobs in the `smtp` table, then drectly opens an SMTP connection and sends the
|
||||
/// message. If this fails, the jobs remain in the database for later sending.
|
||||
pub async fn send_msg_sync(context: &Context, chat_id: ChatId, msg: &mut Message) -> Result<MsgId> {
|
||||
let rowids = prepare_send_msg(context, chat_id, msg).await?;
|
||||
if rowids.is_empty() {
|
||||
return Ok(msg.id);
|
||||
}
|
||||
let mut smtp = crate::smtp::Smtp::new();
|
||||
for rowid in rowids {
|
||||
send_msg_to_smtp(context, &mut smtp, rowid)
|
||||
.await
|
||||
.context("failed to send message, queued for later sending")?;
|
||||
}
|
||||
context.emit_msgs_changed(msg.chat_id, msg.id);
|
||||
Ok(msg.id)
|
||||
}
|
||||
|
||||
/// Prepares a message to be sent out.
|
||||
async fn prepare_msg_common(
|
||||
///
|
||||
/// Returns row ids of the `smtp` table.
|
||||
async fn prepare_send_msg(
|
||||
context: &Context,
|
||||
chat_id: ChatId,
|
||||
msg: &mut Message,
|
||||
change_state_to: MessageState,
|
||||
) -> Result<MsgId> {
|
||||
) -> Result<Vec<i64>> {
|
||||
let mut chat = Chat::load_from_db(context, chat_id).await?;
|
||||
|
||||
// Check if the chat can be sent to.
|
||||
@@ -2821,7 +2887,7 @@ async fn prepare_msg_common(
|
||||
};
|
||||
|
||||
// ... then change the MessageState in the message object
|
||||
msg.state = change_state_to;
|
||||
msg.state = MessageState::OutPending;
|
||||
|
||||
prepare_msg_blob(context, msg).await?;
|
||||
if !msg.hidden {
|
||||
@@ -2837,125 +2903,6 @@ async fn prepare_msg_common(
|
||||
.await?;
|
||||
msg.chat_id = chat_id;
|
||||
|
||||
Ok(msg.id)
|
||||
}
|
||||
|
||||
/// Returns whether a contact is in a chat or not.
|
||||
pub async fn is_contact_in_chat(
|
||||
context: &Context,
|
||||
chat_id: ChatId,
|
||||
contact_id: ContactId,
|
||||
) -> Result<bool> {
|
||||
// this function works for group and for normal chats, however, it is more useful
|
||||
// for group chats.
|
||||
// ContactId::SELF may be used to check, if the user itself is in a group
|
||||
// chat (ContactId::SELF is not added to normal chats)
|
||||
|
||||
let exists = context
|
||||
.sql
|
||||
.exists(
|
||||
"SELECT COUNT(*) FROM chats_contacts WHERE chat_id=? AND contact_id=?;",
|
||||
(chat_id, contact_id),
|
||||
)
|
||||
.await?;
|
||||
Ok(exists)
|
||||
}
|
||||
|
||||
/// Sends a message object to a chat.
|
||||
///
|
||||
/// Sends the event #DC_EVENT_MSGS_CHANGED on success.
|
||||
/// However, this does not imply, the message really reached the recipient -
|
||||
/// sending may be delayed eg. due to network problems. However, from your
|
||||
/// view, you're done with the message. Sooner or later it will find its way.
|
||||
// TODO: Do not allow ChatId to be 0, if prepare_msg had been called
|
||||
// the caller can get it from msg.chat_id. Forwards would need to
|
||||
// be fixed for this somehow too.
|
||||
pub async fn send_msg(context: &Context, chat_id: ChatId, msg: &mut Message) -> Result<MsgId> {
|
||||
if chat_id.is_unset() {
|
||||
let forwards = msg.param.get(Param::PrepForwards);
|
||||
if let Some(forwards) = forwards {
|
||||
for forward in forwards.split(' ') {
|
||||
if let Ok(msg_id) = forward.parse::<u32>().map(MsgId::new) {
|
||||
if let Ok(mut msg) = Message::load_from_db(context, msg_id).await {
|
||||
send_msg_inner(context, chat_id, &mut msg).await?;
|
||||
};
|
||||
}
|
||||
}
|
||||
msg.param.remove(Param::PrepForwards);
|
||||
msg.update_param(context).await?;
|
||||
}
|
||||
return send_msg_inner(context, chat_id, msg).await;
|
||||
}
|
||||
|
||||
if msg.state != MessageState::Undefined && msg.state != MessageState::OutPreparing {
|
||||
msg.param.remove(Param::GuaranteeE2ee);
|
||||
msg.param.remove(Param::ForcePlaintext);
|
||||
msg.update_param(context).await?;
|
||||
}
|
||||
send_msg_inner(context, chat_id, msg).await
|
||||
}
|
||||
|
||||
/// Tries to send a message synchronously.
|
||||
///
|
||||
/// Creates jobs in the `smtp` table, then drectly opens an SMTP connection and sends the
|
||||
/// message. If this fails, the jobs remain in the database for later sending.
|
||||
pub async fn send_msg_sync(context: &Context, chat_id: ChatId, msg: &mut Message) -> Result<MsgId> {
|
||||
let rowids = prepare_send_msg(context, chat_id, msg).await?;
|
||||
if rowids.is_empty() {
|
||||
return Ok(msg.id);
|
||||
}
|
||||
let mut smtp = crate::smtp::Smtp::new();
|
||||
for rowid in rowids {
|
||||
send_msg_to_smtp(context, &mut smtp, rowid)
|
||||
.await
|
||||
.context("failed to send message, queued for later sending")?;
|
||||
}
|
||||
context.emit_msgs_changed(msg.chat_id, msg.id);
|
||||
Ok(msg.id)
|
||||
}
|
||||
|
||||
async fn send_msg_inner(context: &Context, chat_id: ChatId, msg: &mut Message) -> Result<MsgId> {
|
||||
// protect all system messages against RTLO attacks
|
||||
if msg.is_system_message() {
|
||||
msg.text = sanitize_bidi_characters(&msg.text);
|
||||
}
|
||||
|
||||
if !prepare_send_msg(context, chat_id, msg).await?.is_empty() {
|
||||
if !msg.hidden {
|
||||
context.emit_msgs_changed(msg.chat_id, msg.id);
|
||||
}
|
||||
|
||||
if msg.param.exists(Param::SetLatitude) {
|
||||
context.emit_location_changed(Some(ContactId::SELF)).await?;
|
||||
}
|
||||
|
||||
context.scheduler.interrupt_smtp().await;
|
||||
}
|
||||
|
||||
Ok(msg.id)
|
||||
}
|
||||
|
||||
/// Returns row ids of the `smtp` table.
|
||||
async fn prepare_send_msg(
|
||||
context: &Context,
|
||||
chat_id: ChatId,
|
||||
msg: &mut Message,
|
||||
) -> Result<Vec<i64>> {
|
||||
// prepare_msg() leaves the message state to OutPreparing, we
|
||||
// only have to change the state to OutPending in this case.
|
||||
// Otherwise we still have to prepare the message, which will set
|
||||
// the state to OutPending.
|
||||
if msg.state != MessageState::OutPreparing {
|
||||
// automatically prepare normal messages
|
||||
prepare_msg_common(context, chat_id, msg, MessageState::OutPending).await?;
|
||||
} else {
|
||||
// update message state of separately prepared messages
|
||||
ensure!(
|
||||
chat_id.is_unset() || chat_id == msg.chat_id,
|
||||
"Inconsistent chat ID"
|
||||
);
|
||||
message::update_msg_state(context, msg.id, MessageState::OutPending).await?;
|
||||
}
|
||||
let row_ids = create_send_msg_jobs(context, msg)
|
||||
.await
|
||||
.context("Failed to create send jobs")?;
|
||||
@@ -4173,8 +4120,6 @@ pub async fn forward_msgs(context: &Context, msg_ids: &[MsgId], chat_id: ChatId)
|
||||
bail!("cannot forward drafts.");
|
||||
}
|
||||
|
||||
let original_param = msg.param.clone();
|
||||
|
||||
// we tested a sort of broadcast
|
||||
// by not marking own forwarded messages as such,
|
||||
// however, this turned out to be to confusing and unclear.
|
||||
@@ -4197,33 +4142,13 @@ pub async fn forward_msgs(context: &Context, msg_ids: &[MsgId], chat_id: ChatId)
|
||||
// do not leak data as group names; a default subject is generated by mimefactory
|
||||
msg.subject = "".to_string();
|
||||
|
||||
let new_msg_id: MsgId;
|
||||
if msg.state == MessageState::OutPreparing {
|
||||
new_msg_id = chat
|
||||
.prepare_msg_raw(context, &mut msg, None, curr_timestamp)
|
||||
.await?;
|
||||
curr_timestamp += 1;
|
||||
msg.param = original_param;
|
||||
msg.id = src_msg_id;
|
||||
|
||||
if let Some(old_fwd) = msg.param.get(Param::PrepForwards) {
|
||||
let new_fwd = format!("{} {}", old_fwd, new_msg_id.to_u32());
|
||||
msg.param.set(Param::PrepForwards, new_fwd);
|
||||
} else {
|
||||
msg.param
|
||||
.set(Param::PrepForwards, new_msg_id.to_u32().to_string());
|
||||
}
|
||||
|
||||
msg.update_param(context).await?;
|
||||
} else {
|
||||
msg.state = MessageState::OutPending;
|
||||
new_msg_id = chat
|
||||
.prepare_msg_raw(context, &mut msg, None, curr_timestamp)
|
||||
.await?;
|
||||
curr_timestamp += 1;
|
||||
if !create_send_msg_jobs(context, &mut msg).await?.is_empty() {
|
||||
context.scheduler.interrupt_smtp().await;
|
||||
}
|
||||
msg.state = MessageState::OutPending;
|
||||
let new_msg_id = chat
|
||||
.prepare_msg_raw(context, &mut msg, None, curr_timestamp)
|
||||
.await?;
|
||||
curr_timestamp += 1;
|
||||
if !create_send_msg_jobs(context, &mut msg).await?.is_empty() {
|
||||
context.scheduler.interrupt_smtp().await;
|
||||
}
|
||||
created_chats.push(chat_id);
|
||||
created_msgs.push(new_msg_id);
|
||||
@@ -4866,15 +4791,12 @@ mod tests {
|
||||
assert_eq!(test.text, "hello2".to_string());
|
||||
assert_eq!(test.state, MessageState::OutDraft);
|
||||
|
||||
let id_after_prepare = prepare_msg(&t, *chat_id, &mut msg).await?;
|
||||
assert_eq!(id_after_prepare, id_after_1st_set);
|
||||
let test = Message::load_from_db(&t, id_after_prepare).await?;
|
||||
assert_eq!(test.state, MessageState::OutPreparing);
|
||||
assert!(!test.hidden); // sent draft must no longer be hidden
|
||||
|
||||
let id_after_send = send_msg(&t, *chat_id, &mut msg).await?;
|
||||
assert_eq!(id_after_send, id_after_1st_set);
|
||||
|
||||
let test = Message::load_from_db(&t, id_after_send).await?;
|
||||
assert!(!test.hidden); // sent draft must no longer be hidden
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -5626,7 +5548,6 @@ mod tests {
|
||||
|
||||
let mut msg = Message::new_text("message text".to_string());
|
||||
assert!(send_msg(&t, device_chat_id, &mut msg).await.is_err());
|
||||
assert!(prepare_msg(&t, device_chat_id, &mut msg).await.is_err());
|
||||
|
||||
let msg_id = add_device_msg(&t, None, Some(&mut msg)).await.unwrap();
|
||||
assert!(forward_msgs(&t, &[msg_id], device_chat_id).await.is_err());
|
||||
|
||||
@@ -930,7 +930,6 @@ mod tests {
|
||||
|
||||
// Alice sends a text message.
|
||||
let mut msg = Message::new(Viewtype::Text);
|
||||
chat::prepare_msg(&alice.ctx, chat_alice, &mut msg).await?;
|
||||
chat::send_msg(&alice.ctx, chat_alice, &mut msg).await?;
|
||||
let sent = alice.pop_sent_msg().await;
|
||||
|
||||
@@ -957,14 +956,12 @@ mod tests {
|
||||
|
||||
// Alice sends message to Bob
|
||||
let mut msg = Message::new(Viewtype::Text);
|
||||
chat::prepare_msg(&alice.ctx, chat_alice, &mut msg).await?;
|
||||
chat::send_msg(&alice.ctx, chat_alice, &mut msg).await?;
|
||||
let sent = alice.pop_sent_msg().await;
|
||||
bob.recv_msg(&sent).await;
|
||||
|
||||
// Alice sends second message to Bob, with no timer
|
||||
let mut msg = Message::new(Viewtype::Text);
|
||||
chat::prepare_msg(&alice.ctx, chat_alice, &mut msg).await?;
|
||||
chat::send_msg(&alice.ctx, chat_alice, &mut msg).await?;
|
||||
let sent = alice.pop_sent_msg().await;
|
||||
|
||||
|
||||
@@ -953,18 +953,6 @@ impl Message {
|
||||
cmd != SystemMessage::Unknown
|
||||
}
|
||||
|
||||
/// Whether the message is still being created.
|
||||
///
|
||||
/// Messages with attachments might be created before the
|
||||
/// attachment is ready. In this case some more restrictions on
|
||||
/// the attachment apply, e.g. if the file to be attached is still
|
||||
/// being written to or otherwise will still change it can not be
|
||||
/// copied to the blobdir. Thus those attachments need to be
|
||||
/// created immediately in the blobdir with a valid filename.
|
||||
pub fn is_increation(&self) -> bool {
|
||||
self.viewtype.has_file() && self.state == MessageState::OutPreparing
|
||||
}
|
||||
|
||||
/// Returns true if the message is an Autocrypt Setup Message.
|
||||
pub fn is_setupmessage(&self) -> bool {
|
||||
if self.viewtype != Viewtype::File {
|
||||
@@ -2206,38 +2194,6 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn test_prepare_message_and_send() {
|
||||
let d = test::TestContext::new().await;
|
||||
let ctx = &d.ctx;
|
||||
|
||||
ctx.set_config(Config::ConfiguredAddr, Some("self@example.com"))
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let chat = d.create_chat_with_contact("", "dest@example.com").await;
|
||||
|
||||
let mut msg = Message::new(Viewtype::Text);
|
||||
|
||||
let msg_id = chat::prepare_msg(ctx, chat.id, &mut msg).await.unwrap();
|
||||
|
||||
let _msg2 = Message::load_from_db(ctx, msg_id).await.unwrap();
|
||||
assert_eq!(_msg2.get_filemime(), None);
|
||||
}
|
||||
|
||||
/// Tests that message can be prepared even if account has no configured address.
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn test_prepare_not_configured() {
|
||||
let d = test::TestContext::new().await;
|
||||
let ctx = &d.ctx;
|
||||
|
||||
let chat = d.create_chat_with_contact("", "dest@example.com").await;
|
||||
|
||||
let mut msg = Message::new(Viewtype::Text);
|
||||
|
||||
assert!(chat::prepare_msg(ctx, chat.id, &mut msg).await.is_ok());
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn test_parse_webrtc_instance() {
|
||||
let (webrtc_type, url) = Message::parse_webrtc_instance("basicwebrtc:https://foo/bar");
|
||||
@@ -2357,9 +2313,9 @@ mod tests {
|
||||
|
||||
let mut msg = Message::new_text("Quoted message".to_string());
|
||||
|
||||
// Prepare message for sending, so it gets a Message-Id.
|
||||
// Send message, so it gets a Message-Id.
|
||||
assert!(msg.rfc724_mid.is_empty());
|
||||
let msg_id = chat::prepare_msg(ctx, chat.id, &mut msg).await.unwrap();
|
||||
let msg_id = chat::send_msg(ctx, chat.id, &mut msg).await.unwrap();
|
||||
let msg = Message::load_from_db(ctx, msg_id).await.unwrap();
|
||||
assert!(!msg.rfc724_mid.is_empty());
|
||||
|
||||
|
||||
@@ -1516,7 +1516,7 @@ async fn build_body_file(
|
||||
) -> Result<(PartBuilder, String)> {
|
||||
let blob = msg
|
||||
.param
|
||||
.get_blob(Param::File, context, true)
|
||||
.get_blob(Param::File, context)
|
||||
.await?
|
||||
.context("msg has no file")?;
|
||||
let suffix = blob.suffix().unwrap_or("dat");
|
||||
@@ -1905,7 +1905,7 @@ mod tests {
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
let new_msg = incoming_msg_to_reply_msg(
|
||||
let mut new_msg = incoming_msg_to_reply_msg(
|
||||
b"Received: (Postfix, from userid 1000); Mon, 4 Dec 2006 14:51:39 +0100 (CET)\n\
|
||||
From: bob@example.com\n\
|
||||
To: alice@example.org\n\
|
||||
@@ -1931,6 +1931,9 @@ mod tests {
|
||||
Original-Message-ID: <2893@example.com>\n\
|
||||
Disposition: manual-action/MDN-sent-automatically; displayed\n\
|
||||
\n", &t).await;
|
||||
chat::send_msg(&t, new_msg.chat_id, &mut new_msg)
|
||||
.await
|
||||
.unwrap();
|
||||
let mf = MimeFactory::from_msg(&t, new_msg).await.unwrap();
|
||||
// The subject string should not be "Re: message opened"
|
||||
assert_eq!("Re: Hello, Bob", mf.subject_str(&t).await.unwrap());
|
||||
@@ -2077,7 +2080,7 @@ mod tests {
|
||||
|
||||
let mut new_msg = Message::new_text("Hi".to_string());
|
||||
new_msg.chat_id = chat_id;
|
||||
chat::prepare_msg(&t, chat_id, &mut new_msg).await.unwrap();
|
||||
chat::send_msg(&t, chat_id, &mut new_msg).await.unwrap();
|
||||
|
||||
let mf = MimeFactory::from_msg(&t, new_msg).await.unwrap();
|
||||
|
||||
@@ -2134,7 +2137,7 @@ mod tests {
|
||||
) -> String {
|
||||
let t = TestContext::new_alice().await;
|
||||
let mut new_msg = incoming_msg_to_reply_msg(imf_raw, &t).await;
|
||||
let incoming_msg = get_chat_msg(&t, new_msg.chat_id, 0, 2).await;
|
||||
let incoming_msg = get_chat_msg(&t, new_msg.chat_id, 0, 1).await;
|
||||
|
||||
if delete_original_msg {
|
||||
incoming_msg.id.trash(&t, false).await.unwrap();
|
||||
@@ -2164,6 +2167,9 @@ mod tests {
|
||||
new_msg.set_quote(&t, Some(&incoming_msg)).await.unwrap();
|
||||
}
|
||||
|
||||
chat::send_msg(&t, new_msg.chat_id, &mut new_msg)
|
||||
.await
|
||||
.unwrap();
|
||||
let mf = MimeFactory::from_msg(&t, new_msg).await.unwrap();
|
||||
mf.subject_str(&t).await.unwrap()
|
||||
}
|
||||
@@ -2184,9 +2190,6 @@ mod tests {
|
||||
|
||||
let mut new_msg = Message::new_text("Hi".to_string());
|
||||
new_msg.chat_id = chat_id;
|
||||
chat::prepare_msg(context, chat_id, &mut new_msg)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
new_msg
|
||||
}
|
||||
@@ -2197,7 +2200,7 @@ mod tests {
|
||||
let t = TestContext::new_alice().await;
|
||||
let context = &t;
|
||||
|
||||
let msg = incoming_msg_to_reply_msg(
|
||||
let mut msg = incoming_msg_to_reply_msg(
|
||||
b"Received: (Postfix, from userid 1000); Mon, 4 Dec 2006 14:51:39 +0100 (CET)\n\
|
||||
From: Charlie <charlie@example.com>\n\
|
||||
To: alice@example.org\n\
|
||||
@@ -2210,6 +2213,7 @@ mod tests {
|
||||
context,
|
||||
)
|
||||
.await;
|
||||
chat::send_msg(&t, msg.chat_id, &mut msg).await.unwrap();
|
||||
|
||||
let mimefactory = MimeFactory::from_msg(&t, msg).await.unwrap();
|
||||
|
||||
|
||||
@@ -3091,11 +3091,7 @@ MDYyMDYxNTE1RTlDOEE4Cj4+CnN0YXJ0eHJlZgo4Mjc4CiUlRU9GCg==
|
||||
|
||||
// Make sure the file is there even though the html is wrong:
|
||||
let param = &message.parts[0].param;
|
||||
let blob: BlobObject = param
|
||||
.get_blob(Param::File, &t, false)
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
let blob: BlobObject = param.get_blob(Param::File, &t).await.unwrap().unwrap();
|
||||
let f = tokio::fs::File::open(blob.to_abs_path()).await.unwrap();
|
||||
let size = f.metadata().await.unwrap().len();
|
||||
assert_eq!(size, 154);
|
||||
|
||||
22
src/param.rs
22
src/param.rs
@@ -366,20 +366,16 @@ impl Params {
|
||||
///
|
||||
/// This parses the parameter value as a [ParamsFile] and than
|
||||
/// tries to return a [BlobObject] for that file. If the file is
|
||||
/// not yet a valid blob, one will be created by copying the file
|
||||
/// only if `create` is set to `true`, otherwise an error is
|
||||
/// returned.
|
||||
/// not yet a valid blob, one will be created by copying the file.
|
||||
///
|
||||
/// Note that in the [ParamsFile::FsPath] case the blob can be
|
||||
/// created without copying if the path already refers to a valid
|
||||
/// blob. If so a [BlobObject] will be returned regardless of the
|
||||
/// `create` argument.
|
||||
/// blob. If so a [BlobObject] will be returned.
|
||||
#[allow(clippy::needless_lifetimes)]
|
||||
pub async fn get_blob<'a>(
|
||||
&self,
|
||||
key: Param,
|
||||
context: &'a Context,
|
||||
create: bool,
|
||||
) -> Result<Option<BlobObject<'a>>> {
|
||||
let val = match self.get(key) {
|
||||
Some(val) => val,
|
||||
@@ -387,10 +383,7 @@ impl Params {
|
||||
};
|
||||
let file = ParamsFile::from_param(context, val)?;
|
||||
let blob = match file {
|
||||
ParamsFile::FsPath(path) => match create {
|
||||
true => BlobObject::new_from_path(context, &path).await?,
|
||||
false => BlobObject::from_path(context, &path)?,
|
||||
},
|
||||
ParamsFile::FsPath(path) => BlobObject::new_from_path(context, &path).await?,
|
||||
ParamsFile::Blob(blob) => blob,
|
||||
};
|
||||
Ok(Some(blob))
|
||||
@@ -546,23 +539,20 @@ mod tests {
|
||||
let path: PathBuf = p.get_path(Param::File, &t).unwrap().unwrap();
|
||||
assert_eq!(path, fname);
|
||||
|
||||
// Blob does not exist yet, expect error.
|
||||
assert!(p.get_blob(Param::File, &t, false).await.is_err());
|
||||
|
||||
fs::write(fname, b"boo").await.unwrap();
|
||||
let blob = p.get_blob(Param::File, &t, true).await.unwrap().unwrap();
|
||||
let blob = p.get_blob(Param::File, &t).await.unwrap().unwrap();
|
||||
assert!(blob.as_file_name().starts_with("foo"));
|
||||
|
||||
// Blob in blobdir, expect blob.
|
||||
let bar_path = t.get_blobdir().join("bar");
|
||||
p.set(Param::File, bar_path.to_str().unwrap());
|
||||
let blob = p.get_blob(Param::File, &t, false).await.unwrap().unwrap();
|
||||
let blob = p.get_blob(Param::File, &t).await.unwrap().unwrap();
|
||||
assert_eq!(blob, BlobObject::from_name(&t, "bar".to_string()).unwrap());
|
||||
|
||||
p.remove(Param::File);
|
||||
assert!(p.get_file(Param::File, &t).unwrap().is_none());
|
||||
assert!(p.get_path(Param::File, &t).unwrap().is_none());
|
||||
assert!(p.get_blob(Param::File, &t, false).await.unwrap().is_none());
|
||||
assert!(p.get_blob(Param::File, &t).await.unwrap().is_none());
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
|
||||
@@ -864,7 +864,6 @@ pub async fn remove_unused_files(context: &Context) -> Result<()> {
|
||||
|
||||
if p == blobdir
|
||||
&& (is_file_in_use(&files_in_use, None, &name_s)
|
||||
|| is_file_in_use(&files_in_use, Some(".increation"), &name_s)
|
||||
|| is_file_in_use(&files_in_use, Some(".waveform"), &name_s)
|
||||
|| is_file_in_use(&files_in_use, Some("-preview.jpg"), &name_s))
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user