From 083939acb8f1d46a1dc4cab2c3fe1267f1647c73 Mon Sep 17 00:00:00 2001 From: "B. Petersen" Date: Mon, 11 Nov 2019 22:06:59 +0100 Subject: [PATCH 1/9] use bool for exists_before_update --- src/sql.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sql.rs b/src/sql.rs index 2b9fa2aac7..0675bc292c 100644 --- a/src/sql.rs +++ b/src/sql.rs @@ -348,7 +348,7 @@ fn open( } if !readonly { - let mut exists_before_update = 0; + let mut exists_before_update = false; let mut dbversion_before_update = 0; /* Init tables to dbversion=0 */ if !sql.table_exists("config") { @@ -478,7 +478,7 @@ fn open( sql.set_raw_config_int(context, "dbversion", 0)?; } } else { - exists_before_update = 1; + exists_before_update = true; dbversion_before_update = sql .get_raw_config_int(context, "dbversion") .unwrap_or_default(); @@ -735,7 +735,7 @@ fn open( } if dbversion < 50 { info!(context, "[migration] v50"); - if 0 != exists_before_update { + if exists_before_update { sql.set_raw_config_int(context, "show_emails", 2)?; } dbversion = 50; From aa3dad8448deeacd4619aaebc58fb8d45a79bd56 Mon Sep 17 00:00:00 2001 From: "B. Petersen" Date: Mon, 11 Nov 2019 22:21:35 +0100 Subject: [PATCH 2/9] use enum for show_emails --- src/chat.rs | 6 ++++-- src/sql.rs | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/chat.rs b/src/chat.rs index 6accc8ef62..adcf631d6b 100644 --- a/src/chat.rs +++ b/src/chat.rs @@ -1,6 +1,7 @@ use std::path::{Path, PathBuf}; use itertools::Itertools; +use num_traits::FromPrimitive; use crate::blob::{BlobErrorKind, BlobObject}; use crate::chatlist::*; @@ -1012,7 +1013,8 @@ pub fn get_chat_msgs( Ok(ret) }; let success = if chat_id == DC_CHAT_ID_DEADDROP { - let show_emails = context.get_config_int(Config::ShowEmails); + let show_emails = + ShowEmails::from_i32(context.get_config_int(Config::ShowEmails)).unwrap_or_default(); context.sql.query_map( concat!( "SELECT m.id AS id, m.timestamp AS timestamp", @@ -1029,7 +1031,7 @@ pub fn get_chat_msgs( " AND m.msgrmsg>=?", " ORDER BY m.timestamp,m.id;" ), - params![if show_emails == 2 { 0 } else { 1 }], + params![if show_emails == ShowEmails::All { 0 } else { 1 }], process_row, process_rows, ) diff --git a/src/sql.rs b/src/sql.rs index 0675bc292c..8ffd065923 100644 --- a/src/sql.rs +++ b/src/sql.rs @@ -5,6 +5,7 @@ use std::time::Duration; use rusqlite::{Connection, OpenFlags, Statement, NO_PARAMS}; use thread_local_object::ThreadLocal; +use crate::constants::ShowEmails; use crate::context::Context; use crate::dc_tools::*; use crate::error::{Error, Result}; @@ -736,7 +737,7 @@ fn open( if dbversion < 50 { info!(context, "[migration] v50"); if exists_before_update { - sql.set_raw_config_int(context, "show_emails", 2)?; + sql.set_raw_config_int(context, "show_emails", ShowEmails::All as i32)?; } dbversion = 50; sql.set_raw_config_int(context, "dbversion", 50)?; From d633c809e92aa9e17aaf0138edd310ab0bb647cb Mon Sep 17 00:00:00 2001 From: "B. Petersen" Date: Mon, 11 Nov 2019 22:39:30 +0100 Subject: [PATCH 3/9] restore some comments --- src/sql.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/sql.rs b/src/sql.rs index 8ffd065923..03a31b1566 100644 --- a/src/sql.rs +++ b/src/sql.rs @@ -489,6 +489,7 @@ fn open( // this should be done before updates that use high-level objects that // rely themselves on the low-level structure. // -------------------------------------------------------------------- + let mut dbversion = dbversion_before_update; let mut recalc_fingerprints = 0; let mut update_file_paths = 0; @@ -589,6 +590,8 @@ fn open( } if dbversion < 27 { info!(context, "[migration] v27"); + // chat.id=1 and chat.id=2 are the old deaddrops, + // the current ones are defined by chats.blocked=2 sql.execute("DELETE FROM msgs WHERE chat_id=1 OR chat_id=2;", params![])?; sql.execute( "CREATE INDEX chats_contacts_index2 ON chats_contacts (contact_id);", @@ -654,6 +657,9 @@ fn open( params![], )?; if dbversion_before_update == 34 { + // migrate database from the use of verified-flags to verified_key, + // _only_ version 34 (0.17.0) has the fields public_key_verified and gossip_key_verified + // this block can be deleted in half a year or so (created 5/2018) sql.execute( "UPDATE acpeerstates SET verified_key=gossip_key, verified_key_fingerprint=gossip_key_fingerprint WHERE gossip_key_verified=2;", params![] @@ -683,6 +689,8 @@ fn open( } if dbversion < 42 { info!(context, "[migration] v42"); + // older versions set the txt-field to the filenames, for debugging and fulltext search. + // to allow text+attachment compound messages, we need to reset these fields. sql.execute("UPDATE msgs SET txt='' WHERE type!=10", params![])?; dbversion = 42; sql.set_raw_config_int(context, "dbversion", 42)?; @@ -736,6 +744,9 @@ fn open( } if dbversion < 50 { info!(context, "[migration] v50"); + // installations <= 0.100.1 used DC_SHOW_EMAILS_ALL implicitly; + // keep this default and use DC_SHOW_EMAILS_NO + // only for new installations if exists_before_update { sql.set_raw_config_int(context, "show_emails", ShowEmails::All as i32)?; } @@ -744,6 +755,8 @@ fn open( } if dbversion < 53 { info!(context, "[migration] v53"); + // the messages containing _only_ locations + // are also added to the database as _hidden_. sql.execute( "CREATE TABLE locations ( id INTEGER PRIMARY KEY AUTOINCREMENT, latitude REAL DEFAULT 0.0, longitude REAL DEFAULT 0.0, accuracy REAL DEFAULT 0.0, timestamp INTEGER DEFAULT 0, chat_id INTEGER DEFAULT 0, from_id INTEGER DEFAULT 0);", params![] @@ -795,6 +808,10 @@ fn open( sql.set_raw_config_int(context, "dbversion", 55)?; } + // (2) updates that require high-level objects + // (the structure is complete now and all objects are usable) + // -------------------------------------------------------------------- + if 0 != recalc_fingerprints { info!(context, "[migration] recalc fingerprints"); sql.query_map( From 0d3f1b6a560b728b4c5f9158511f5e731b9b7ead Mon Sep 17 00:00:00 2001 From: "B. Petersen" Date: Mon, 11 Nov 2019 22:55:19 +0100 Subject: [PATCH 4/9] change default for bcc_self, preserve values for existing installations --- src/config.rs | 2 +- src/sql.rs | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/config.rs b/src/config.rs index a63e555d62..ab8851714b 100644 --- a/src/config.rs +++ b/src/config.rs @@ -31,7 +31,7 @@ pub enum Config { Displayname, Selfstatus, Selfavatar, - #[strum(props(default = "1"))] + #[strum(props(default = "0"))] BccSelf, #[strum(props(default = "1"))] E2eeEnabled, diff --git a/src/sql.rs b/src/sql.rs index 03a31b1566..bf989142c9 100644 --- a/src/sql.rs +++ b/src/sql.rs @@ -804,9 +804,15 @@ fn open( "ALTER TABLE locations ADD COLUMN independent INTEGER DEFAULT 0;", params![], )?; - sql.set_raw_config_int(context, "dbversion", 55)?; } + if dbversion < 56 { + info!(context, "[migration] v56"); + if exists_before_update && sql.get_raw_config_int(context, "bcc_self").is_none() { + sql.set_raw_config_int(context, "bcc_self", 1)?; + } + sql.set_raw_config_int(context, "dbversion", 56)?; + } // (2) updates that require high-level objects // (the structure is complete now and all objects are usable) From 37dde819e9410b0bff8c8588830df55f8a58c04d Mon Sep 17 00:00:00 2001 From: "B. Petersen" Date: Mon, 11 Nov 2019 23:25:54 +0100 Subject: [PATCH 5/9] add device-msg 'consider enabling bcc_self' if bcc_self is disabled and an autocrypt-setup-message is received --- src/imex.rs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/imex.rs b/src/imex.rs index cbc0d68118..d7c5e4daee 100644 --- a/src/imex.rs +++ b/src/imex.rs @@ -155,6 +155,11 @@ fn do_initiate_key_transfer(context: &Context) -> Result { } } } + // no maybe_add_bcc_self_device_msg() here. + // the ui shows the dialog with the setup code on this device, + // it would be too much noise to have two things popping up at the same time. + // maybe_add_bcc_self_device_msg() is called on the other device + // once the transfer is completed. Ok(setup_code) } @@ -230,6 +235,21 @@ pub fn create_setup_code(_context: &Context) -> String { ret } +fn maybe_add_bcc_self_device_msg(context: &Context) -> Result<()> { + if !context.sql.get_raw_config_bool(context, "bcc_self") { + let mut msg = Message::new(Viewtype::Text); + // TODO: define this as a stockstring once the wording is settled. + msg.text = Some( + "It seems you are using multiple devices with Delta Chat. Great!\n\n\ + If you also want to synchronize outgoing messages accross all devices, \ + go to the settings and enable \"Send copy to self\"." + .to_string(), + ); + chat::add_device_msg(context, &mut msg)?; + } + Ok(()) +} + pub fn continue_key_transfer(context: &Context, msg_id: MsgId, setup_code: &str) -> Result<()> { ensure!(!msg_id.is_special(), "wrong id"); @@ -244,6 +264,7 @@ pub fn continue_key_transfer(context: &Context, msg_id: MsgId, setup_code: &str) let sc = normalize_setup_code(setup_code); let armored_key = decrypt_setup_file(context, &sc, file)?; set_self_key(context, &armored_key, true, true)?; + maybe_add_bcc_self_device_msg(context)?; Ok(()) } else { From 18d25dfd5ba3bb65579fd5e84a9cc63c277ad0fc Mon Sep 17 00:00:00 2001 From: "B. Petersen" Date: Tue, 12 Nov 2019 02:14:21 +0100 Subject: [PATCH 6/9] add device-message only once --- src/chat.rs | 20 +++++++++++++++++++- src/imex.rs | 2 +- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/chat.rs b/src/chat.rs index adcf631d6b..59bb3bf6a4 100644 --- a/src/chat.rs +++ b/src/chat.rs @@ -1929,9 +1929,26 @@ pub fn get_chat_id_by_grpid(context: &Context, grpid: impl AsRef) -> (u32, } pub fn add_device_msg(context: &Context, msg: &mut Message) -> Result { + let label = format!("info-{}", dc_create_id()); + add_device_msg_once(context, &label, msg) +} + +pub fn add_device_msg_once( + context: &Context, + label: &str, + msg: &mut Message, +) -> Result { let (chat_id, _blocked) = create_or_lookup_by_contact_id(context, DC_CONTACT_ID_DEVICE, Blocked::Not)?; - let rfc724_mid = dc_create_outgoing_rfc724_mid(None, "@device"); + let rfc724_mid = format!("{}@device", label); + + if let Ok((_, _, msg_id)) = message::rfc724_mid_exists(context, &rfc724_mid) { + info!( + context, + "device-message {} already exist as {}", label, msg_id + ); + return Ok(msg_id); + } prepare_msg_blob(context, msg)?; unarchive(context, chat_id)?; @@ -1955,6 +1972,7 @@ pub fn add_device_msg(context: &Context, msg: &mut Message) -> Result Result<()> { go to the settings and enable \"Send copy to self\"." .to_string(), ); - chat::add_device_msg(context, &mut msg)?; + chat::add_device_msg_once(context, "bcc-self-hint", &mut msg)?; } Ok(()) } From 01b0ddb4e562d7b2bb66721cdf0ef184eafe24e5 Mon Sep 17 00:00:00 2001 From: "B. Petersen" Date: Tue, 12 Nov 2019 12:22:02 +0100 Subject: [PATCH 7/9] add dc_add_device_msg_once() to fii --- deltachat-ffi/deltachat.h | 22 ++++++++++++++++++++++ deltachat-ffi/src/lib.rs | 21 +++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/deltachat-ffi/deltachat.h b/deltachat-ffi/deltachat.h index fa13b6e5fa..91001b7442 100644 --- a/deltachat-ffi/deltachat.h +++ b/deltachat-ffi/deltachat.h @@ -1113,6 +1113,28 @@ void dc_set_draft (dc_context_t* context, uint32_t ch uint32_t dc_add_device_msg (dc_context_t* context, dc_msg_t* msg); +/** + * Add a message only one time to the device-chat. + * The device-message is defined by a name. + * If a message with the same name was added before, + * the message is not added again. + * Use dc_add_device_msg() to add device-messages unconditionally. + * + * Sends the event #DC_EVENT_MSGS_CHANGED on success. + * + * @memberof dc_context_t + * @param context The context as created by dc_context_new(). + * @param label A unique name for the message to add. + * The label is typically not displayed to the user and + * must be created from the characters `A-Z`, `a-z`, `0-9`, `_` or `-`. + * @param msg Message to be added to the device-chat. + * The message appears to the user as an incoming message. + * @return The ID of the added message, + * this might be the id of an older message with the same name. + */ +uint32_t dc_add_device_msg_once (dc_context_t* context, const char* label, dc_msg_t* msg); + + /** * Get draft for a chat, if any. * See dc_set_draft() for more details about drafts. diff --git a/deltachat-ffi/src/lib.rs b/deltachat-ffi/src/lib.rs index 6c52f09ca4..b7895549d0 100644 --- a/deltachat-ffi/src/lib.rs +++ b/deltachat-ffi/src/lib.rs @@ -828,6 +828,27 @@ pub unsafe extern "C" fn dc_add_device_msg(context: *mut dc_context_t, msg: *mut .unwrap_or(0) } +#[no_mangle] +pub unsafe extern "C" fn dc_add_device_msg_once( + context: *mut dc_context_t, + label: *const libc::c_char, + msg: *mut dc_msg_t, +) -> u32 { + if context.is_null() || label.is_null() || msg.is_null() { + eprintln!("ignoring careless call to dc_add_device_msg_once()"); + return 0; + } + let ffi_context = &mut *context; + let ffi_msg = &mut *msg; + ffi_context + .with_inner(|ctx| { + chat::add_device_msg_once(ctx, &to_string_lossy(label), &mut ffi_msg.message) + .unwrap_or_log_default(ctx, "Failed to add device message once") + }) + .map(|msg_id| msg_id.to_u32()) + .unwrap_or(0) +} + #[no_mangle] pub unsafe extern "C" fn dc_get_draft(context: *mut dc_context_t, chat_id: u32) -> *mut dc_msg_t { if context.is_null() { From 5b5decb1056ce55af3eb33daa46d0816cb9e1b59 Mon Sep 17 00:00:00 2001 From: "B. Petersen" Date: Tue, 12 Nov 2019 13:30:04 +0100 Subject: [PATCH 8/9] use separate column for device-msg-labels --- src/chat.rs | 17 +++++++++++++---- src/imex.rs | 1 + src/sql.rs | 13 ++++++++++--- 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/src/chat.rs b/src/chat.rs index 59bb3bf6a4..aa96657553 100644 --- a/src/chat.rs +++ b/src/chat.rs @@ -1940,9 +1940,17 @@ pub fn add_device_msg_once( ) -> Result { let (chat_id, _blocked) = create_or_lookup_by_contact_id(context, DC_CONTACT_ID_DEVICE, Blocked::Not)?; - let rfc724_mid = format!("{}@device", label); + let rfc724_mid = dc_create_outgoing_rfc724_mid(None, "@device"); - if let Ok((_, _, msg_id)) = message::rfc724_mid_exists(context, &rfc724_mid) { + // chat_id has an sql-index so it makes sense to add this although redundant + if let Ok(msg_id) = context.sql.query_row( + "SELECT id FROM msgs WHERE chat_id=? AND label=?", + params![chat_id, label], + |row| { + let msg_id: MsgId = row.get(0)?; + Ok(msg_id) + }, + ) { info!( context, "device-message {} already exist as {}", label, msg_id @@ -1954,8 +1962,8 @@ pub fn add_device_msg_once( unarchive(context, chat_id)?; context.sql.execute( - "INSERT INTO msgs (chat_id,from_id,to_id, timestamp,type,state, txt,param,rfc724_mid) \ - VALUES (?,?,?, ?,?,?, ?,?,?);", + "INSERT INTO msgs (chat_id,from_id,to_id, timestamp,type,state, txt,param,rfc724_mid,label) \ + VALUES (?,?,?, ?,?,?, ?,?,?,?);", params![ chat_id, DC_CONTACT_ID_DEVICE, @@ -1966,6 +1974,7 @@ pub fn add_device_msg_once( msg.text.as_ref().map_or("", String::as_str), msg.param.to_string(), rfc724_mid, + label, ], )?; diff --git a/src/imex.rs b/src/imex.rs index e7fe1d81cf..0040579962 100644 --- a/src/imex.rs +++ b/src/imex.rs @@ -160,6 +160,7 @@ fn do_initiate_key_transfer(context: &Context) -> Result { // it would be too much noise to have two things popping up at the same time. // maybe_add_bcc_self_device_msg() is called on the other device // once the transfer is completed. + maybe_add_bcc_self_device_msg(context)?; Ok(setup_code) } diff --git a/src/sql.rs b/src/sql.rs index bf989142c9..b1f2102776 100644 --- a/src/sql.rs +++ b/src/sql.rs @@ -806,12 +806,19 @@ fn open( )?; sql.set_raw_config_int(context, "dbversion", 55)?; } - if dbversion < 56 { - info!(context, "[migration] v56"); + if dbversion < 57 { + info!(context, "[migration] v57"); + // label is a unique name and is currently used for device-messages only. + // in contrast to rfc724_mid and other fields, the label is generated on the device + // and allows reliable identifications this way. + sql.execute( + "ALTER TABLE msgs ADD COLUMN label TEXT DEFAULT '';", + params![], + )?; if exists_before_update && sql.get_raw_config_int(context, "bcc_self").is_none() { sql.set_raw_config_int(context, "bcc_self", 1)?; } - sql.set_raw_config_int(context, "dbversion", 56)?; + sql.set_raw_config_int(context, "dbversion", 57)?; } // (2) updates that require high-level objects From fd19be69d22bb6642077878f6e912b95140582d9 Mon Sep 17 00:00:00 2001 From: holger krekel Date: Tue, 12 Nov 2019 14:57:10 +0100 Subject: [PATCH 9/9] fix python tests --- python/tests/test_account.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/python/tests/test_account.py b/python/tests/test_account.py index 750c164140..a71924bf54 100644 --- a/python/tests/test_account.py +++ b/python/tests/test_account.py @@ -21,7 +21,7 @@ def test_getinfo(self, acfactory): d = ac1.get_info() assert d["arch"] assert d["number_of_chats"] == "0" - assert d["bcc_self"] == "1" + assert d["bcc_self"] == "0" def test_is_not_configured(self, acfactory): ac1 = acfactory.get_unconfigured_account() @@ -43,7 +43,7 @@ def test_has_savemime(self, acfactory): def test_has_bccself(self, acfactory): ac1 = acfactory.get_unconfigured_account() assert "bcc_self" in ac1.get_config("sys.config_keys").split() - assert ac1.get_config("bcc_self") == "1" + assert ac1.get_config("bcc_self") == "0" def test_selfcontact_if_unconfigured(self, acfactory): ac1 = acfactory.get_unconfigured_account() @@ -405,6 +405,9 @@ def test_one_account_send_bcc_setting(self, acfactory, lp): wait_successful_IMAP_SMTP_connection(ac1) wait_configuration_progress(ac1, 1000) + lp.sec("ac1: setting bcc_self=1") + ac1.set_config("bcc_self", "1") + lp.sec("send out message with bcc to ourselves") msg_out = chat.send_text("message2") ev = ac1._evlogger.get_matching("DC_EVENT_MSGS_CHANGED")