diff --git a/deltachat-ffi/src/lib.rs b/deltachat-ffi/src/lib.rs index dfd43ec02..a3459e400 100644 --- a/deltachat-ffi/src/lib.rs +++ b/deltachat-ffi/src/lib.rs @@ -11,15 +11,17 @@ extern crate human_panic; extern crate num_traits; -use libc::uintptr_t; -use num_traits::{FromPrimitive, ToPrimitive}; - +use std::collections::HashMap; use std::convert::TryInto; use std::ffi::CString; +use std::fmt::Write; use std::ptr; use std::str::FromStr; use std::sync::RwLock; +use libc::uintptr_t; +use num_traits::{FromPrimitive, ToPrimitive}; + use deltachat::constants::Event; use deltachat::contact::Contact; use deltachat::context::Context; @@ -293,10 +295,21 @@ pub unsafe extern "C" fn dc_get_info(context: *mut dc_context_t) -> *mut libc::c } let ffi_context = &*context; ffi_context - .with_inner(|ctx| context::dc_get_info(ctx)) + .with_inner(|ctx| render_info(ctx.get_info()).unwrap_or_default().strdup()) .unwrap_or_else(|_| "".strdup()) } +fn render_info( + info: HashMap<&'static str, String>, +) -> std::result::Result { + let mut res = String::new(); + for (key, value) in &info { + write!(&mut res, "{}={}\n", key, value)?; + } + + Ok(res) +} + #[no_mangle] pub unsafe extern "C" fn dc_get_oauth2_url( context: *mut dc_context_t, @@ -320,7 +333,7 @@ pub unsafe extern "C" fn dc_get_oauth2_url( #[no_mangle] pub unsafe extern "C" fn dc_get_version_str() -> *mut libc::c_char { - context::dc_get_version_str() + context::get_version_str().strdup() } #[no_mangle] @@ -761,7 +774,7 @@ pub unsafe extern "C" fn dc_get_fresh_msgs( let ffi_context = &*context; ffi_context .with_inner(|ctx| { - let arr = dc_array_t::from(context::dc_get_fresh_msgs(ctx)); + let arr = dc_array_t::from(ctx.get_fresh_msgs()); Box::into_raw(Box::new(arr)) }) .unwrap_or_else(|_| ptr::null_mut()) @@ -927,7 +940,7 @@ pub unsafe extern "C" fn dc_search_msgs( let ffi_context = &*context; ffi_context .with_inner(|ctx| { - let arr = dc_array_t::from(context::dc_search_msgs(ctx, chat_id, query)); + let arr = dc_array_t::from(ctx.search_msgs(chat_id, as_str(query))); Box::into_raw(Box::new(arr)) }) .unwrap_or_else(|_| ptr::null_mut()) diff --git a/examples/repl/cmdline.rs b/examples/repl/cmdline.rs index 0a6ccedc6..40d524d1f 100644 --- a/examples/repl/cmdline.rs +++ b/examples/repl/cmdline.rs @@ -546,7 +546,7 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E println!("{}={:?}", key, val); } "info" => { - println!("{}", to_string(dc_get_info(context))); + println!("{:#?}", context.get_info()); } "maybenetwork" => { maybe_network(context); @@ -847,7 +847,7 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E 0 as libc::c_uint }; - let msglist = dc_search_msgs(context, chat, arg1_c); + let msglist = context.search_msgs(chat, arg1); log_msglist(context, &msglist)?; println!("{} messages.", msglist.len()); @@ -910,7 +910,7 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E println!("{}", as_str(res)); } "listfresh" => { - let msglist = dc_get_fresh_msgs(context); + let msglist = context.get_fresh_msgs(); log_msglist(context, &msglist)?; print!("{} fresh messages.", msglist.len()); diff --git a/examples/simple.rs b/examples/simple.rs index 34cc8f19a..677348379 100644 --- a/examples/simple.rs +++ b/examples/simple.rs @@ -45,10 +45,9 @@ fn main() { let ctx = Context::new(Box::new(cb), "FakeOs".into(), dbfile).expect("Failed to create context"); let running = Arc::new(RwLock::new(true)); - let info = dc_get_info(&ctx); - let info_s = CStr::from_ptr(info); + let info = ctx.get_info(); let duration = time::Duration::from_millis(4000); - println!("info: {}", info_s.to_str().unwrap()); + println!("info: {:#?}", info); let ctx = Arc::new(ctx); let ctx1 = ctx.clone(); diff --git a/src/context.rs b/src/context.rs index cca7426dc..b1938d60e 100644 --- a/src/context.rs +++ b/src/context.rs @@ -1,12 +1,13 @@ -use libc::uintptr_t; +use std::collections::HashMap; use std::ffi::OsString; use std::path::{Path, PathBuf}; use std::sync::{Arc, Condvar, Mutex, RwLock}; +use libc::uintptr_t; + use crate::chat::*; use crate::constants::*; use crate::contact::*; -use crate::dc_tools::*; use crate::error::*; use crate::imap::*; use crate::job::*; @@ -135,6 +136,247 @@ impl Context { pub fn call_cb(&self, event: Event, data1: uintptr_t, data2: uintptr_t) -> uintptr_t { (*self.cb)(self, event, data1, data2) } + + pub fn get_info(&self) -> HashMap<&'static str, String> { + let unset = "0"; + let l = LoginParam::from_database(self, ""); + let l2 = LoginParam::from_database(self, "configured_"); + let displayname = self.sql.get_config(self, "displayname"); + let chats = get_chat_cnt(self) as usize; + let real_msgs = dc_get_real_msg_cnt(self) as usize; + let deaddrop_msgs = dc_get_deaddrop_msg_cnt(self) as usize; + let contacts = Contact::get_real_cnt(self) as usize; + let is_configured = self + .sql + .get_config_int(self, "configured") + .unwrap_or_default(); + let dbversion = self + .sql + .get_config_int(self, "dbversion") + .unwrap_or_default(); + let e2ee_enabled = self + .sql + .get_config_int(self, "e2ee_enabled") + .unwrap_or_else(|| 1); + let mdns_enabled = self + .sql + .get_config_int(self, "mdns_enabled") + .unwrap_or_else(|| 1); + + let prv_key_cnt: Option = + self.sql + .query_get_value(self, "SELECT COUNT(*) FROM keypairs;", rusqlite::NO_PARAMS); + + let pub_key_cnt: Option = self.sql.query_get_value( + self, + "SELECT COUNT(*) FROM acpeerstates;", + rusqlite::NO_PARAMS, + ); + + let fingerprint_str = if let Some(key) = Key::from_self_public(self, &l2.addr, &self.sql) { + key.fingerprint() + } else { + "".into() + }; + + let inbox_watch = self + .sql + .get_config_int(self, "inbox_watch") + .unwrap_or_else(|| 1); + let sentbox_watch = self + .sql + .get_config_int(self, "sentbox_watch") + .unwrap_or_else(|| 1); + let mvbox_watch = self + .sql + .get_config_int(self, "mvbox_watch") + .unwrap_or_else(|| 1); + let mvbox_move = self + .sql + .get_config_int(self, "mvbox_move") + .unwrap_or_else(|| 1); + let folders_configured = self + .sql + .get_config_int(self, "folders_configured") + .unwrap_or_default(); + let configured_sentbox_folder = self + .sql + .get_config(self, "configured_sentbox_folder") + .unwrap_or_else(|| "".to_string()); + let configured_mvbox_folder = self + .sql + .get_config(self, "configured_mvbox_folder") + .unwrap_or_else(|| "".to_string()); + + let mut res = HashMap::new(); + res.insert("deltachat_core_version", format!("v{}", &*DC_VERSION_STR)); + res.insert("sqlite_version", rusqlite::version().to_string()); + res.insert( + "sqlite_thread_safe", + unsafe { rusqlite::ffi::sqlite3_threadsafe() }.to_string(), + ); + res.insert( + "arch", + (::std::mem::size_of::<*mut libc::c_void>()) + .wrapping_mul(8) + .to_string(), + ); + res.insert("number_of_chats", chats.to_string()); + res.insert("number_of_chat_messages", real_msgs.to_string()); + res.insert("messages_in_contact_requests", deaddrop_msgs.to_string()); + res.insert("number_of_contacts", contacts.to_string()); + res.insert("database_dir", self.get_dbfile().display().to_string()); + res.insert("database_version", dbversion.to_string()); + res.insert("blobdir", self.get_blobdir().display().to_string()); + res.insert("display_name", displayname.unwrap_or_else(|| unset.into())); + res.insert("is_configured", is_configured.to_string()); + res.insert("entered_account_settings", l.to_string()); + res.insert("used_account_settings", l2.to_string()); + res.insert("inbox_watch", inbox_watch.to_string()); + res.insert("sentbox_watch", sentbox_watch.to_string()); + res.insert("mvbox_watch", mvbox_watch.to_string()); + res.insert("mvbox_move", mvbox_move.to_string()); + res.insert("folders_configured", folders_configured.to_string()); + res.insert("configured_sentbox_folder", configured_sentbox_folder); + res.insert("configured_mvbox_folder", configured_mvbox_folder); + res.insert("mdns_enabled", mdns_enabled.to_string()); + res.insert("e2ee_enabled", e2ee_enabled.to_string()); + res.insert( + "private_key_count", + prv_key_cnt.unwrap_or_default().to_string(), + ); + res.insert( + "public_key_count", + pub_key_cnt.unwrap_or_default().to_string(), + ); + res.insert("fingerprint", fingerprint_str); + res.insert("level", "awesome".into()); + + res + } + + pub fn get_fresh_msgs(&self) -> Vec { + let show_deaddrop = 0; + + self.sql + .query_map( + "SELECT m.id FROM msgs m LEFT JOIN contacts ct \ + ON m.from_id=ct.id LEFT JOIN chats c ON m.chat_id=c.id WHERE m.state=? \ + AND m.hidden=0 \ + AND m.chat_id>? \ + AND ct.blocked=0 \ + AND (c.blocked=0 OR c.blocked=?) ORDER BY m.timestamp DESC,m.id DESC;", + &[10, 9, if 0 != show_deaddrop { 2 } else { 0 }], + |row| row.get(0), + |rows| { + let mut ret = Vec::new(); + for row in rows { + let id: u32 = row?; + ret.push(id); + } + Ok(ret) + }, + ) + .unwrap() + } + + #[allow(non_snake_case)] + pub fn search_msgs(&self, chat_id: u32, query: impl AsRef) -> Vec { + let real_query = query.as_ref().trim(); + if real_query.is_empty() { + return Vec::new(); + } + let strLikeInText = format!("%{}%", real_query); + let strLikeBeg = format!("{}%", real_query); + + let query = if 0 != chat_id { + "SELECT m.id, m.timestamp FROM msgs m LEFT JOIN contacts ct ON m.from_id=ct.id WHERE m.chat_id=? \ + AND m.hidden=0 \ + AND ct.blocked=0 AND (txt LIKE ? OR ct.name LIKE ?) ORDER BY m.timestamp,m.id;" + } else { + "SELECT m.id, m.timestamp FROM msgs m LEFT JOIN contacts ct ON m.from_id=ct.id \ + LEFT JOIN chats c ON m.chat_id=c.id WHERE m.chat_id>9 AND m.hidden=0 \ + AND (c.blocked=0 OR c.blocked=?) \ + AND ct.blocked=0 AND (m.txt LIKE ? OR ct.name LIKE ?) ORDER BY m.timestamp DESC,m.id DESC;" + }; + + self.sql + .query_map( + query, + params![chat_id as i32, &strLikeInText, &strLikeBeg], + |row| row.get::<_, i32>(0), + |rows| { + let mut ret = Vec::new(); + for id in rows { + ret.push(id? as u32); + } + Ok(ret) + }, + ) + .unwrap_or_default() + } + + pub fn is_inbox(&self, folder_name: impl AsRef) -> bool { + folder_name.as_ref() == "INBOX" + } + + pub fn is_sentbox(&self, folder_name: impl AsRef) -> bool { + let sentbox_name = self.sql.get_config(self, "configured_sentbox_folder"); + if let Some(name) = sentbox_name { + name == folder_name.as_ref() + } else { + false + } + } + + pub fn is_mvbox(&self, folder_name: impl AsRef) -> bool { + let mvbox_name = self.sql.get_config(self, "configured_mvbox_folder"); + + if let Some(name) = mvbox_name { + name == folder_name.as_ref() + } else { + false + } + } + + pub fn do_heuristics_moves(&self, folder: &str, msg_id: u32) { + if self + .sql + .get_config_int(self, "mvbox_move") + .unwrap_or_else(|| 1) + == 0 + { + return; + } + + if !self.is_inbox(folder) && !self.is_sentbox(folder) { + return; + } + + if let Ok(msg) = dc_msg_new_load(self, msg_id) { + if dc_msg_is_setupmessage(&msg) { + // do not move setup messages; + // there may be a non-delta device that wants to handle it + return; + } + + if self.is_mvbox(folder) { + dc_update_msg_move_state(self, msg.rfc724_mid, MoveState::Stay); + } + + // 1 = dc message, 2 = reply to dc message + if 0 != msg.is_dc_message { + job_add( + self, + Action::MoveMsg, + msg.id as libc::c_int, + Params::new(), + 0, + ); + dc_update_msg_move_state(self, msg.rfc724_mid, MoveState::Moving); + } + } + } } impl Drop for Context { @@ -176,277 +418,8 @@ pub struct SmtpState { pub probe_network: bool, } -/* ****************************************************************************** - * INI-handling, Information - ******************************************************************************/ - -pub unsafe fn dc_get_info(context: &Context) -> *mut libc::c_char { - let unset = "0"; - let l = LoginParam::from_database(context, ""); - let l2 = LoginParam::from_database(context, "configured_"); - let displayname = context.sql.get_config(context, "displayname"); - let chats = get_chat_cnt(context) as usize; - let real_msgs = dc_get_real_msg_cnt(context) as usize; - let deaddrop_msgs = dc_get_deaddrop_msg_cnt(context) as usize; - let contacts = Contact::get_real_cnt(context) as usize; - let is_configured = context - .sql - .get_config_int(context, "configured") - .unwrap_or_default(); - let dbversion = context - .sql - .get_config_int(context, "dbversion") - .unwrap_or_default(); - let e2ee_enabled = context - .sql - .get_config_int(context, "e2ee_enabled") - .unwrap_or_else(|| 1); - let mdns_enabled = context - .sql - .get_config_int(context, "mdns_enabled") - .unwrap_or_else(|| 1); - - let prv_key_cnt: Option = context.sql.query_get_value( - context, - "SELECT COUNT(*) FROM keypairs;", - rusqlite::NO_PARAMS, - ); - - let pub_key_cnt: Option = context.sql.query_get_value( - context, - "SELECT COUNT(*) FROM acpeerstates;", - rusqlite::NO_PARAMS, - ); - - let fingerprint_str = if let Some(key) = Key::from_self_public(context, &l2.addr, &context.sql) - { - key.fingerprint() - } else { - "".into() - }; - - let inbox_watch = context - .sql - .get_config_int(context, "inbox_watch") - .unwrap_or_else(|| 1); - let sentbox_watch = context - .sql - .get_config_int(context, "sentbox_watch") - .unwrap_or_else(|| 1); - let mvbox_watch = context - .sql - .get_config_int(context, "mvbox_watch") - .unwrap_or_else(|| 1); - let mvbox_move = context - .sql - .get_config_int(context, "mvbox_move") - .unwrap_or_else(|| 1); - let folders_configured = context - .sql - .get_config_int(context, "folders_configured") - .unwrap_or_default(); - let configured_sentbox_folder = context - .sql - .get_config(context, "configured_sentbox_folder") - .unwrap_or_else(|| "".to_string()); - let configured_mvbox_folder = context - .sql - .get_config(context, "configured_mvbox_folder") - .unwrap_or_else(|| "".to_string()); - - let res = format!( - "deltachat_core_version=v{}\n\ - sqlite_version={}\n\ - sqlite_thread_safe={}\n\ - arch={}\n\ - number_of_chats={}\n\ - number_of_chat_messages={}\n\ - messages_in_contact_requests={}\n\ - number_of_contacts={}\n\ - database_dir={}\n\ - database_version={}\n\ - blobdir={}\n\ - display_name={}\n\ - is_configured={}\n\ - entered_account_settings={}\n\ - used_account_settings={}\n\ - inbox_watch={}\n\ - sentbox_watch={}\n\ - mvbox_watch={}\n\ - mvbox_move={}\n\ - folders_configured={}\n\ - configured_sentbox_folder={}\n\ - configured_mvbox_folder={}\n\ - mdns_enabled={}\n\ - e2ee_enabled={}\n\ - private_key_count={}\n\ - public_key_count={}\n\ - fingerprint={}\n\ - level=awesome\n", - &*DC_VERSION_STR, - rusqlite::version(), - rusqlite::ffi::sqlite3_threadsafe(), - // arch - (::std::mem::size_of::<*mut libc::c_void>()).wrapping_mul(8), - chats, - real_msgs, - deaddrop_msgs, - contacts, - context.get_dbfile().display(), - dbversion, - context.get_blobdir().display(), - displayname.unwrap_or_else(|| unset.into()), - is_configured, - l, - l2, - inbox_watch, - sentbox_watch, - mvbox_watch, - mvbox_move, - folders_configured, - configured_sentbox_folder, - configured_mvbox_folder, - mdns_enabled, - e2ee_enabled, - prv_key_cnt.unwrap_or_default(), - pub_key_cnt.unwrap_or_default(), - fingerprint_str, - ); - - res.strdup() -} - -pub unsafe fn dc_get_version_str() -> *mut libc::c_char { - (&*DC_VERSION_STR).strdup() -} - -pub fn dc_get_fresh_msgs(context: &Context) -> Vec { - let show_deaddrop = 0; - - context - .sql - .query_map( - "SELECT m.id FROM msgs m LEFT JOIN contacts ct \ - ON m.from_id=ct.id LEFT JOIN chats c ON m.chat_id=c.id WHERE m.state=? \ - AND m.hidden=0 \ - AND m.chat_id>? \ - AND ct.blocked=0 \ - AND (c.blocked=0 OR c.blocked=?) ORDER BY m.timestamp DESC,m.id DESC;", - &[10, 9, if 0 != show_deaddrop { 2 } else { 0 }], - |row| row.get(0), - |rows| { - let mut ret = Vec::new(); - for row in rows { - let id: u32 = row?; - ret.push(id); - } - Ok(ret) - }, - ) - .unwrap() -} - -#[allow(non_snake_case)] -pub fn dc_search_msgs(context: &Context, chat_id: u32, query: *const libc::c_char) -> Vec { - if query.is_null() { - return Vec::new(); - } - - let real_query = as_str(query).trim(); - if real_query.is_empty() { - return Vec::new(); - } - let strLikeInText = format!("%{}%", real_query); - let strLikeBeg = format!("{}%", real_query); - - let query = if 0 != chat_id { - "SELECT m.id, m.timestamp FROM msgs m LEFT JOIN contacts ct ON m.from_id=ct.id WHERE m.chat_id=? \ - AND m.hidden=0 \ - AND ct.blocked=0 AND (txt LIKE ? OR ct.name LIKE ?) ORDER BY m.timestamp,m.id;" - } else { - "SELECT m.id, m.timestamp FROM msgs m LEFT JOIN contacts ct ON m.from_id=ct.id \ - LEFT JOIN chats c ON m.chat_id=c.id WHERE m.chat_id>9 AND m.hidden=0 \ - AND (c.blocked=0 OR c.blocked=?) \ - AND ct.blocked=0 AND (m.txt LIKE ? OR ct.name LIKE ?) ORDER BY m.timestamp DESC,m.id DESC;" - }; - - context - .sql - .query_map( - query, - params![chat_id as libc::c_int, &strLikeInText, &strLikeBeg], - |row| row.get::<_, i32>(0), - |rows| { - let mut ret = Vec::new(); - for id in rows { - ret.push(id? as u32); - } - Ok(ret) - }, - ) - .unwrap_or_default() -} - -pub fn dc_is_inbox(_context: &Context, folder_name: impl AsRef) -> bool { - folder_name.as_ref() == "INBOX" -} - -pub fn dc_is_sentbox(context: &Context, folder_name: impl AsRef) -> bool { - let sentbox_name = context.sql.get_config(context, "configured_sentbox_folder"); - if let Some(name) = sentbox_name { - name == folder_name.as_ref() - } else { - false - } -} - -pub fn dc_is_mvbox(context: &Context, folder_name: impl AsRef) -> bool { - let mvbox_name = context.sql.get_config(context, "configured_mvbox_folder"); - - if let Some(name) = mvbox_name { - name == folder_name.as_ref() - } else { - false - } -} - -pub fn do_heuristics_moves(context: &Context, folder: &str, msg_id: u32) { - if context - .sql - .get_config_int(context, "mvbox_move") - .unwrap_or_else(|| 1) - == 0 - { - return; - } - - if !dc_is_inbox(context, folder) && !dc_is_sentbox(context, folder) { - return; - } - - if let Ok(msg) = dc_msg_new_load(context, msg_id) { - if dc_msg_is_setupmessage(&msg) { - // do not move setup messages; - // there may be a non-delta device that wants to handle it - return; - } - - if dc_is_mvbox(context, folder) { - dc_update_msg_move_state(context, msg.rfc724_mid, MoveState::Stay); - } - - // 1 = dc message, 2 = reply to dc message - if 0 != msg.is_dc_message { - job_add( - context, - Action::MoveMsg, - msg.id as libc::c_int, - Params::new(), - 0, - ); - dc_update_msg_move_state(context, msg.rfc724_mid, MoveState::Moving); - } - } +pub fn get_version_str() -> &'static str { + &DC_VERSION_STR } #[cfg(test)] @@ -508,4 +481,12 @@ mod tests { let t = dummy_context(); std::mem::drop(t.ctx); } + + #[test] + fn test_get_info() { + let t = dummy_context(); + + let info = t.ctx.get_info(); + assert_eq!(info.get("level").unwrap(), "awesome"); + } } diff --git a/src/dc_mimefactory.rs b/src/dc_mimefactory.rs index fb8b8bc19..69627708e 100644 --- a/src/dc_mimefactory.rs +++ b/src/dc_mimefactory.rs @@ -15,7 +15,7 @@ use mmime::other::*; use crate::chat::{self, Chat}; use crate::constants::*; use crate::contact::*; -use crate::context::{dc_get_version_str, Context}; +use crate::context::{get_version_str, Context}; use crate::dc_strencode::*; use crate::dc_tools::*; use crate::e2ee::*; @@ -458,19 +458,18 @@ pub unsafe fn dc_mimefactory_render(context: &Context, factory: &mut dc_mimefact .map(|s| format!("/{}", s)) .unwrap_or_default(); let os_part = CString::new(os_part).expect("String -> CString conversion failed"); - let version = dc_get_version_str(); + let version = CString::yolo(get_version_str()); mailimf_fields_add( imf_fields, mailimf_field_new_custom( strdup(b"X-Mailer\x00" as *const u8 as *const libc::c_char), dc_mprintf( b"Delta Chat Core %s%s\x00" as *const u8 as *const libc::c_char, - version, + version.as_ptr(), os_part.as_ptr(), ), ), ); - free(version.cast()); mailimf_fields_add( imf_fields, @@ -955,16 +954,16 @@ pub unsafe fn dc_mimefactory_render(context: &Context, factory: &mut dc_mimefact message_text = format!("{}\r\n", p2).strdup(); let human_mime_part: *mut mailmime = build_body_text(message_text); mailmime_add_part(multipart, human_mime_part); - let version = dc_get_version_str(); + let version = CString::yolo(get_version_str()); message_text2 = dc_mprintf( b"Reporting-UA: Delta Chat %s\r\nOriginal-Recipient: rfc822;%s\r\nFinal-Recipient: rfc822;%s\r\nOriginal-Message-ID: <%s>\r\nDisposition: manual-action/MDN-sent-automatically; displayed\r\n\x00" as *const u8 as *const libc::c_char, - version, + version.as_ptr(), factory.from_addr, factory.from_addr, factory.msg.rfc724_mid ); - free(version.cast()); + let content_type_0: *mut mailmime_content = mailmime_content_new_with_str( b"message/disposition-notification\x00" as *const u8 as *const libc::c_char, ); diff --git a/src/dc_receive_imf.rs b/src/dc_receive_imf.rs index e7f5b9622..523ef04cc 100644 --- a/src/dc_receive_imf.rs +++ b/src/dc_receive_imf.rs @@ -16,7 +16,7 @@ use sha2::{Digest, Sha256}; use crate::chat::{self, Chat}; use crate::constants::*; use crate::contact::*; -use crate::context::{do_heuristics_moves, Context}; +use crate::context::Context; use crate::dc_mimeparser::*; use crate::dc_strencode::*; use crate::dc_tools::*; @@ -736,7 +736,7 @@ unsafe fn add_parts( } } - do_heuristics_moves(context, server_folder.as_ref(), *insert_msg_id); + context.do_heuristics_moves(server_folder.as_ref(), *insert_msg_id); cleanup(mime_in_reply_to, mime_references, txt_raw); Ok(()) diff --git a/src/imap.rs b/src/imap.rs index 4520e2ab5..160b0ae77 100644 --- a/src/imap.rs +++ b/src/imap.rs @@ -8,7 +8,7 @@ use std::sync::{ use std::time::{Duration, SystemTime}; use crate::constants::*; -use crate::context::{do_heuristics_moves, Context}; +use crate::context::Context; use crate::dc_receive_imf::dc_receive_imf; use crate::dc_tools::CStringExt; use crate::dc_tools::*; @@ -1680,7 +1680,7 @@ unsafe fn precheck_imf( if as_str(old_server_folder) != server_folder || old_server_uid != server_uid { dc_update_server_uid(context, rfc724_mid, server_folder, server_uid); } - do_heuristics_moves(context, server_folder, msg_id); + context.do_heuristics_moves(server_folder, msg_id); if 0 != mark_seen { job_add( context,