Merge remote-tracking branch 'origin/master' into flub/send-backup

This commit is contained in:
dignifiedquire
2023-03-16 17:50:00 +01:00
43 changed files with 329 additions and 213 deletions

View File

@@ -334,7 +334,7 @@ async fn set_dkim_works_timestamp(
async fn clear_dkim_works(context: &Context) -> Result<()> {
context
.sql
.execute("DELETE FROM sending_domains", paramsv![])
.execute("DELETE FROM sending_domains", ())
.await?;
Ok(())
}

View File

@@ -418,7 +418,7 @@ impl ChatId {
ProtectionStatus::Protected => match chat.typ {
Chattype::Single | Chattype::Group | Chattype::Broadcast => {
let contact_ids = get_chat_contacts(context, self).await?;
for contact_id in contact_ids.into_iter() {
for contact_id in contact_ids {
let contact = Contact::get_by_id(context, contact_id).await?;
if contact.is_verified(context).await? != VerifiedStatus::BidirectVerified {
bail!("{} is not verified.", contact.get_display_name());
@@ -853,7 +853,7 @@ impl ChatId {
AND c.blocked=0
AND c.archived=1
",
paramsv![],
(),
)
.await?
} else {
@@ -2578,7 +2578,7 @@ pub async fn marknoticed_chat(context: &Context, chat_id: ChatId) -> Result<()>
"SELECT DISTINCT(m.chat_id) FROM msgs m
LEFT JOIN chats c ON m.chat_id=c.id
WHERE m.state=10 AND m.hidden=0 AND m.chat_id>9 AND c.blocked=0 AND c.archived=1",
paramsv![],
(),
|row| row.get::<_, ChatId>(0),
|ids| ids.collect::<Result<Vec<_>, _>>().map_err(Into::into)
)
@@ -3500,10 +3500,7 @@ pub(crate) async fn get_chat_cnt(context: &Context) -> Result<usize> {
// no database, no chats - this is no error (needed eg. for information)
let count = context
.sql
.count(
"SELECT COUNT(*) FROM chats WHERE id>9 AND blocked=0;",
paramsv![],
)
.count("SELECT COUNT(*) FROM chats WHERE id>9 AND blocked=0;", ())
.await?;
Ok(count)
} else {
@@ -3676,17 +3673,14 @@ pub(crate) async fn delete_and_reset_all_device_msgs(context: &Context) -> Resul
paramsv![ContactId::DEVICE],
)
.await?;
context
.sql
.execute("DELETE FROM devmsglabels;", paramsv![])
.await?;
context.sql.execute("DELETE FROM devmsglabels;", ()).await?;
// Insert labels for welcome messages to avoid them being readded on reconfiguration.
context
.sql
.execute(
r#"INSERT INTO devmsglabels (label) VALUES ("core-welcome-image"), ("core-welcome")"#,
paramsv![],
(),
)
.await?;
context.set_config(Config::QuotaExceeding, None).await?;

View File

@@ -1,5 +1,6 @@
//! # Key-value configuration management.
use std::env;
use std::str::FromStr;
use anyhow::{ensure, Context as _, Result};
@@ -317,6 +318,11 @@ impl Context {
/// Get a configuration key. Returns `None` if no value is set, and no default value found.
pub async fn get_config(&self, key: Config) -> Result<Option<String>> {
let env_key = format!("DELTACHAT_{}", key.as_ref().to_uppercase());
if let Ok(value) = env::var(env_key) {
return Ok(Some(value));
}
let value = match key {
Config::Selfavatar => {
let rel_path = self.sql.get_raw_config(key.as_ref()).await?;
@@ -418,7 +424,7 @@ impl Context {
match key {
Config::Selfavatar => {
self.sql
.execute("UPDATE contacts SET selfavatar_sent=0;", paramsv![])
.execute("UPDATE contacts SET selfavatar_sent=0;", ())
.await?;
match value {
Some(value) => {

View File

@@ -727,7 +727,7 @@ impl Contact {
pub async fn add_address_book(context: &Context, addr_book: &str) -> Result<usize> {
let mut modify_cnt = 0;
for (name, addr) in split_address_book(addr_book).into_iter() {
for (name, addr) in split_address_book(addr_book) {
let (name, addr) = sanitize_name_and_addr(name, addr);
let name = normalize_name(&name);
match ContactAddress::new(&addr) {

View File

@@ -622,7 +622,7 @@ impl Context {
.unwrap_or_default();
let journal_mode = self
.sql
.query_get_value("PRAGMA journal_mode;", paramsv![])
.query_get_value("PRAGMA journal_mode;", ())
.await?
.unwrap_or_else(|| "unknown".to_string());
let e2ee_enabled = self.get_config_int(Config::E2eeEnabled).await?;
@@ -630,14 +630,11 @@ impl Context {
let bcc_self = self.get_config_int(Config::BccSelf).await?;
let send_sync_msgs = self.get_config_int(Config::SendSyncMsgs).await?;
let prv_key_cnt = self
.sql
.count("SELECT COUNT(*) FROM keypairs;", paramsv![])
.await?;
let prv_key_cnt = self.sql.count("SELECT COUNT(*) FROM keypairs;", ()).await?;
let pub_key_cnt = self
.sql
.count("SELECT COUNT(*) FROM acpeerstates;", paramsv![])
.count("SELECT COUNT(*) FROM acpeerstates;", ())
.await?;
let fingerprint_str = match SignedPublicKey::load_self(self).await {
Ok(key) => key.fingerprint().hex(),

View File

@@ -68,7 +68,7 @@ use std::num::ParseIntError;
use std::str::FromStr;
use std::time::{Duration, SystemTime, UNIX_EPOCH};
use anyhow::{ensure, Context as _, Result};
use anyhow::{ensure, Result};
use async_channel::Receiver;
use serde::{Deserialize, Serialize};
use tokio::time::timeout;
@@ -433,37 +433,40 @@ pub(crate) async fn delete_expired_messages(context: &Context, now: i64) -> Resu
let rows = select_expired_messages(context, now).await?;
if !rows.is_empty() {
context
info!(context, "Attempting to delete {} messages.", rows.len());
let (msgs_changed, webxdc_deleted) = context
.sql
.execute(
.transaction(|transaction| {
let mut msgs_changed = Vec::with_capacity(rows.len());
let mut webxdc_deleted = Vec::new();
// If you change which information is removed here, also change MsgId::trash() and
// which information receive_imf::add_parts() still adds to the db if the chat_id is TRASH
&format!(
r#"
UPDATE msgs
SET
chat_id=?, txt='', subject='', txt_raw='',
mime_headers='', from_id=0, to_id=0, param=''
WHERE id IN ({})
"#,
sql::repeat_vars(rows.len())
),
rusqlite::params_from_iter(
std::iter::once(&DC_CHAT_ID_TRASH as &dyn crate::ToSql).chain(
rows.iter()
.map(|(msg_id, _chat_id, _viewtype)| msg_id as &dyn crate::ToSql),
),
),
)
.await
.context("update failed")?;
for (msg_id, chat_id, viewtype) in rows {
transaction.execute(
"UPDATE msgs
SET chat_id=?, txt='', subject='', txt_raw='',
mime_headers='', from_id=0, to_id=0, param=''
WHERE id=?",
params![DC_CHAT_ID_TRASH, msg_id],
)?;
for (msg_id, chat_id, viewtype) in rows {
msgs_changed.push((chat_id, msg_id));
if viewtype == Viewtype::Webxdc {
webxdc_deleted.push(msg_id)
}
}
Ok((msgs_changed, webxdc_deleted))
})
.await?;
for (chat_id, msg_id) in msgs_changed {
context.emit_msgs_changed(chat_id, msg_id);
}
if viewtype == Viewtype::Webxdc {
context.emit_event(EventType::WebxdcInstanceDeleted { msg_id });
}
for msg_id in webxdc_deleted {
context.emit_event(EventType::WebxdcInstanceDeleted { msg_id });
}
}
@@ -1170,7 +1173,7 @@ mod tests {
// No other messages are marked for deletion.
assert_eq!(
t.sql
.count("SELECT COUNT(*) FROM imap WHERE target=''", paramsv![],)
.count("SELECT COUNT(*) FROM imap WHERE target=''", ())
.await?,
0
);
@@ -1184,10 +1187,7 @@ mod tests {
.update_download_state(&t, DownloadState::Available)
.await?;
t.sql
.execute(
"UPDATE imap SET target=folder WHERE rfc724_mid='1000'",
paramsv![],
)
.execute("UPDATE imap SET target=folder WHERE rfc724_mid='1000'", ())
.await?;
delete_expired_imap_messages(&t).await?;
test_marked_for_deletion(&t, 1000).await?; // Delete downloadable anyway.
@@ -1198,10 +1198,7 @@ mod tests {
delete_expired_imap_messages(&t).await?;
test_marked_for_deletion(&t, 1010).await?;
t.sql
.execute(
"UPDATE imap SET target=folder WHERE rfc724_mid='1010'",
paramsv![],
)
.execute("UPDATE imap SET target=folder WHERE rfc724_mid='1010'", ())
.await?;
MsgId::new(1010)
@@ -1211,7 +1208,7 @@ mod tests {
// Keep downloadable for now.
assert_eq!(
t.sql
.count("SELECT COUNT(*) FROM imap WHERE target=''", paramsv![],)
.count("SELECT COUNT(*) FROM imap WHERE target=''", ())
.await?,
0
);

View File

@@ -124,7 +124,7 @@ impl HtmlMsgParser {
async move {
match get_mime_multipart_type(&mail.ctype) {
MimeMultipartType::Multiple => {
for cur_data in mail.subparts.iter() {
for cur_data in &mail.subparts {
self.collect_texts_recursive(cur_data).await?
}
Ok(())
@@ -180,7 +180,7 @@ impl HtmlMsgParser {
async move {
match get_mime_multipart_type(&mail.ctype) {
MimeMultipartType::Multiple => {
for cur_data in mail.subparts.iter() {
for cur_data in &mail.subparts {
self.cid_to_data_recursive(context, cur_data).await?;
}
Ok(())
@@ -292,7 +292,10 @@ mod tests {
assert_eq!(
parser.html,
r##"<!DOCTYPE html>
<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head><body>
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="color-scheme" content="light dark" />
</head><body>
This message does not have Content-Type nor Subject.<br/>
<br/>
</body></html>
@@ -308,7 +311,10 @@ This message does not have Content-Type nor Subject.<br/>
assert_eq!(
parser.html,
r##"<!DOCTYPE html>
<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head><body>
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="color-scheme" content="light dark" />
</head><body>
message with a non-UTF-8 encoding: äöüßÄÖÜ<br/>
<br/>
</body></html>
@@ -325,7 +331,10 @@ message with a non-UTF-8 encoding: äöüßÄÖÜ<br/>
assert_eq!(
parser.html,
r##"<!DOCTYPE html>
<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head><body>
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="color-scheme" content="light dark" />
</head><body>
This line ends with a space and will be merged with the next one due to format=flowed.<br/>
<br/>
This line does not end with a space<br/>
@@ -344,7 +353,10 @@ and will be wrapped as usual.<br/>
assert_eq!(
parser.html,
r##"<!DOCTYPE html>
<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head><body>
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="color-scheme" content="light dark" />
</head><body>
mime-modified should not be set set as there is no html and no special stuff;<br/>
although not being a delta-message.<br/>
test some special html-characters as &lt; &gt; and &amp; but also &quot; and &#x27; :)<br/>

View File

@@ -1390,7 +1390,7 @@ impl Imap {
let mut uid_msgs = HashMap::with_capacity(request_uids.len());
let mut count = 0;
for &request_uid in request_uids.iter() {
for &request_uid in &request_uids {
// Check if FETCH response is already in `uid_msgs`.
let mut fetch_response = uid_msgs.remove(&request_uid);

View File

@@ -654,7 +654,7 @@ async fn export_self_keys(context: &Context, dir: &Path) -> Result<()> {
.sql
.query_map(
"SELECT id, public_key, private_key, is_default FROM keypairs;",
paramsv![],
(),
|row| {
let id = row.get(0)?;
let public_key_blob: Vec<u8> = row.get(1)?;

View File

@@ -148,7 +148,7 @@ impl DcKey for SignedSecretKey {
WHERE addr=(SELECT value FROM config WHERE keyname="configured_addr")
AND is_default=1;
"#,
paramsv![],
(),
|row| {
let bytes: Vec<u8> = row.get(0)?;
Ok(bytes)
@@ -302,7 +302,7 @@ pub async fn store_self_keypair(
.context("failed to remove old use of key")?;
if default == KeyPairUse::Default {
transaction
.execute("UPDATE keypairs SET is_default=0;", paramsv![])
.execute("UPDATE keypairs SET is_default=0;", ())
.context("failed to clear default")?;
}
let is_default = match default {
@@ -592,7 +592,7 @@ i8pcjGO+IZffvyZJVRWfVooBJmWWbPB1pueo3tx8w3+fcuzpxz+RLFKaPyqXO+dD
let nrows = || async {
ctx.sql
.count("SELECT COUNT(*) FROM keypairs;", paramsv![])
.count("SELECT COUNT(*) FROM keypairs;", ())
.await
.unwrap()
};

View File

@@ -12,7 +12,10 @@
clippy::wildcard_imports,
clippy::needless_borrow,
clippy::cast_lossless,
clippy::unused_async
clippy::unused_async,
clippy::explicit_iter_loop,
clippy::explicit_into_iter_loop,
clippy::cloned_instead_of_copied
)]
#![allow(
clippy::match_bool,

View File

@@ -434,10 +434,7 @@ fn is_marker(txt: &str) -> bool {
/// Deletes all locations from the database.
pub async fn delete_all(context: &Context) -> Result<()> {
context
.sql
.execute("DELETE FROM locations;", paramsv![])
.await?;
context.sql.execute("DELETE FROM locations;", ()).await?;
context.emit_event(EventType::LocationChanged(None));
Ok(())
}

View File

@@ -1502,7 +1502,7 @@ pub async fn markseen_msgs(context: &Context, msg_ids: Vec<MsgId>) -> Result<()>
curr_rfc724_mid,
curr_blocked,
_curr_ephemeral_timer,
) in msgs.into_iter()
) in msgs
{
if curr_blocked == Blocked::Not
&& (curr_state == MessageState::InFresh || curr_state == MessageState::InNoticed)
@@ -1741,7 +1741,7 @@ pub(crate) async fn handle_ndn(
};
let mut first = true;
for msg in msgs.into_iter() {
for msg in msgs {
let (msg_id, chat_id, chat_type) = msg?;
set_msg_failed(context, msg_id, &error).await;
if first {
@@ -1794,7 +1794,7 @@ pub async fn get_unblocked_msg_cnt(context: &Context) -> usize {
"SELECT COUNT(*) \
FROM msgs m LEFT JOIN chats c ON c.id=m.chat_id \
WHERE m.id>9 AND m.chat_id>9 AND c.blocked=0;",
paramsv![],
(),
)
.await
{
@@ -1814,7 +1814,7 @@ pub async fn get_request_msg_cnt(context: &Context) -> usize {
"SELECT COUNT(*) \
FROM msgs m LEFT JOIN chats c ON c.id=m.chat_id \
WHERE c.blocked=2;",
paramsv![],
(),
)
.await
{

View File

@@ -485,7 +485,7 @@ impl<'a> MimeFactory<'a> {
None
};
for (name, addr) in self.recipients.iter() {
for (name, addr) in &self.recipients {
if let Some(email_to_remove) = email_to_remove {
if email_to_remove == addr {
continue;

View File

@@ -640,7 +640,7 @@ impl MimeMessage {
}
if self.is_forwarded {
for part in self.parts.iter_mut() {
for part in &mut self.parts {
part.param.set_int(Param::Forwarded, 1);
}
}
@@ -943,7 +943,7 @@ impl MimeMessage {
}
// Add all parts (we need another part, preferably text/plain, to show as an error message)
for cur_data in mail.subparts.iter() {
for cur_data in &mail.subparts {
if self
.parse_mime_recursive(context, cur_data, is_related)
.await?
@@ -977,7 +977,7 @@ impl MimeMessage {
_ => {
// Add all parts (in fact, AddSinglePartIfKnown() later check if
// the parts are really supported)
for cur_data in mail.subparts.iter() {
for cur_data in &mail.subparts {
if self
.parse_mime_recursive(context, cur_data, is_related)
.await?

View File

@@ -57,7 +57,7 @@ async fn lookup_host_with_cache(
}
};
for addr in resolved_addrs.iter() {
for addr in &resolved_addrs {
let ip_string = addr.ip().to_string();
if ip_string == hostname {
// IP address resolved into itself, not interesting to cache.

View File

@@ -718,7 +718,7 @@ pub(crate) async fn deduplicate_peerstates(sql: &Sql) -> Result<()> {
FROM acpeerstates
GROUP BY addr
)",
paramsv![],
(),
)
.await?;

View File

@@ -34,8 +34,13 @@ impl PlainText {
let lines = split_lines(&self.text);
let mut ret =
"<!DOCTYPE html>\n<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" /></head><body>\n".to_string();
let mut ret = r#"<!DOCTYPE html>
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="color-scheme" content="light dark" />
</head><body>
"#
.to_string();
for line in lines {
let is_quote = line.starts_with('>');
@@ -118,7 +123,10 @@ http://link-at-start-of-line.org
assert_eq!(
html,
r##"<!DOCTYPE html>
<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head><body>
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="color-scheme" content="light dark" />
</head><body>
line 1<br/>
line 2<br/>
line with <a href="https://link-mid-of-line.org">https://link-mid-of-line.org</a> and <a href="http://link-end-of-line.com/file?foo=bar%20">http://link-end-of-line.com/file?foo=bar%20</a><br/>
@@ -140,7 +148,10 @@ line with <a href="https://link-mid-of-line.org">https://link-mid-of-line.org</a
assert_eq!(
html,
r#"<!DOCTYPE html>
<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head><body>
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="color-scheme" content="light dark" />
</head><body>
line with &lt;<a href="http://encapsulated.link/?foo=_bar">http://encapsulated.link/?foo=_bar</a>&gt; here!<br/>
</body></html>
"#
@@ -158,7 +169,10 @@ line with &lt;<a href="http://encapsulated.link/?foo=_bar">http://encapsulated.l
assert_eq!(
html,
r#"<!DOCTYPE html>
<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head><body>
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="color-scheme" content="light dark" />
</head><body>
line with nohttp://no.link here<br/>
</body></html>
"#
@@ -176,7 +190,10 @@ line with nohttp://no.link here<br/>
assert_eq!(
html,
r#"<!DOCTYPE html>
<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head><body>
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="color-scheme" content="light dark" />
</head><body>
just an address: <a href="mailto:foo@bar.org">foo@bar.org</a> <a href="mailto:another@one.de">another@one.de</a><br/>
</body></html>
"#
@@ -194,7 +211,10 @@ just an address: <a href="mailto:foo@bar.org">foo@bar.org</a> <a href="mailto:an
assert_eq!(
html,
r#"<!DOCTYPE html>
<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head><body>
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="color-scheme" content="light dark" />
</head><body>
line still line<br/>
<em>&gt;quote </em><br/>
<em>&gt;still quote</em><br/>
@@ -215,7 +235,10 @@ line still line<br/>
assert_eq!(
html,
r#"<!DOCTYPE html>
<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head><body>
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="color-scheme" content="light dark" />
</head><body>
linestill line<br/>
<em>&gt;quote </em><br/>
<em>&gt;still quote</em><br/>
@@ -236,7 +259,10 @@ linestill line<br/>
assert_eq!(
html,
r#"<!DOCTYPE html>
<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head><body>
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="color-scheme" content="light dark" />
</head><body>
line <br/>
still line<br/>
<em>&gt;quote </em><br/>

View File

@@ -604,7 +604,7 @@ async fn add_parts(
// to the sender's name, indicating to the user that he/she is not part of the group.
let from = &mime_parser.from;
let name: &str = from.display_name.as_ref().unwrap_or(&from.addr);
for part in mime_parser.parts.iter_mut() {
for part in &mut mime_parser.parts {
part.param.set(Param::OverrideSenderDisplayname, name);
}
}
@@ -668,7 +668,7 @@ async fn add_parts(
// we use name from From:-header as override name
if prevent_rename {
if let Some(name) = &mime_parser.from.display_name {
for part in mime_parser.parts.iter_mut() {
for part in &mut mime_parser.parts {
part.param.set(Param::OverrideSenderDisplayname, name);
}
}
@@ -737,7 +737,7 @@ async fn add_parts(
// the mail is on the IMAP server, probably it is also delivered.
// We cannot recreate other states (read, error).
state = MessageState::OutDelivered;
to_id = to_ids.get(0).cloned().unwrap_or_default();
to_id = to_ids.get(0).copied().unwrap_or_default();
let self_sent =
from_id == ContactId::SELF && to_ids.len() == 1 && to_ids.contains(&ContactId::SELF);
@@ -2162,7 +2162,7 @@ async fn check_verified_properties(
)
.await?;
for (to_addr, mut is_verified) in rows.into_iter() {
for (to_addr, mut is_verified) in rows {
info!(
context,
"check_verified_properties: {:?} self={:?}",

View File

@@ -2085,9 +2085,11 @@ Original signature",
false,
)
.await?;
let one2one_chat_id = t.get_last_msg().await.chat_id;
let msg = t.get_last_msg().await;
let one2one_chat_id = msg.chat_id;
let bob = Contact::load_from_db(&t, bob_id).await?;
assert_eq!(bob.get_status(), "Original signature");
assert!(!msg.has_html());
receive_imf(
&t,

View File

@@ -163,7 +163,7 @@ impl BobState {
// guaranteed to only have one row.
sql.query_row_optional(
"SELECT id, invite, next_step, chat_id FROM bobstate;",
paramsv![],
(),
|row| {
let s = BobState {
id: row.get(0)?,

View File

@@ -80,7 +80,8 @@ pub(crate) struct SimplifiedText {
/// True if the message is forwarded.
pub is_forwarded: bool,
/// True if nonstandard footer was removed.
/// True if nonstandard footer was removed
/// or if the message contains quotes other than `top_quote`.
pub is_cut: bool,
/// Top quote, if any.
@@ -103,7 +104,6 @@ pub(crate) fn simplify(mut input: String, is_chat_message: bool) -> SimplifiedTe
let original_lines = &lines;
let (lines, footer_lines) = remove_message_footer(lines);
let footer = footer_lines.map(|footer_lines| render_message(footer_lines, false));
is_cut = is_cut || footer.is_some();
let text = if is_chat_message {
render_message(lines, false)
@@ -330,7 +330,7 @@ mod tests {
} = simplify(input, true);
assert_eq!(text, "Hi! How are you?\n\n---\n\nI am good.");
assert!(!is_forwarded);
assert!(is_cut);
assert!(!is_cut);
assert_eq!(
footer.unwrap(),
"Sent with my Delta Chat Messenger: https://delta.chat"
@@ -365,7 +365,7 @@ mod tests {
assert_eq!(text, "Forwarded message");
assert!(is_forwarded);
assert!(is_cut);
assert!(!is_cut);
assert_eq!(footer.unwrap(), "Signature goes here");
}
@@ -442,7 +442,7 @@ mod tests {
..
} = simplify(input, true);
assert_eq!(text, "text\n\n--\nno footer");
assert!(is_cut);
assert!(!is_cut);
assert_eq!(footer.unwrap(), "footer");
let input = "text\n\n--\ntreated as footer when unescaped".to_string();
@@ -453,7 +453,7 @@ mod tests {
..
} = simplify(input.clone(), true);
assert_eq!(text, "text"); // see remove_message_footer() for some explanations
assert!(is_cut);
assert!(!is_cut);
assert_eq!(footer.unwrap(), "treated as footer when unescaped");
let escaped = escape_message_footer_marks(&input);
let SimplifiedText {
@@ -495,7 +495,7 @@ mod tests {
..
} = simplify(input.clone(), true);
assert_eq!(text, ""); // see remove_message_footer() for some explanations
assert!(is_cut);
assert!(!is_cut);
assert_eq!(footer.unwrap(), "treated as footer when unescaped");
let escaped = escape_message_footer_marks(&input);

View File

@@ -220,7 +220,7 @@ impl Sql {
let addrs = self
.query_map(
"SELECT addr FROM acpeerstates;",
paramsv![],
(),
|row| row.get::<_, String>(0),
|addrs| {
addrs
@@ -713,12 +713,22 @@ pub async fn housekeeping(context: &Context) -> Result<()> {
// Try to clear the freelist to free some space on the disk. This
// only works if auto_vacuum is enabled.
if let Err(err) = context
match context
.sql
.execute("PRAGMA incremental_vacuum", paramsv![])
.query_row_optional("PRAGMA incremental_vacuum", (), |_row| Ok(()))
.await
{
warn!(context, "Failed to run incremental vacuum: {}", err);
Err(err) => {
warn!(context, "Failed to run incremental vacuum: {err:#}");
}
Ok(Some(())) => {
// Incremental vacuum returns a zero-column result if it did anything.
info!(context, "Successfully ran incremental vacuum.");
}
Ok(None) => {
// Incremental vacuum returned `SQLITE_DONE` immediately,
// there were no pages to remove.
}
}
if let Err(e) = context
@@ -732,7 +742,7 @@ pub async fn housekeeping(context: &Context) -> Result<()> {
.sql
.execute(
"DELETE FROM msgs_mdns WHERE msg_id NOT IN (SELECT id FROM msgs)",
paramsv![],
(),
)
.await
.ok_or_log_msg(context, "failed to remove old MDNs");
@@ -780,7 +790,7 @@ pub async fn remove_unused_files(context: &Context) -> Result<()> {
.sql
.query_map(
"SELECT value FROM config;",
paramsv![],
(),
|row| row.get::<_, String>(0),
|rows| {
for row in rows {
@@ -915,7 +925,7 @@ async fn maybe_add_from_param(
) -> Result<()> {
sql.query_map(
query,
paramsv![],
(),
|row| row.get::<_, String>(0),
|rows| {
for row in rows {

View File

@@ -391,7 +391,7 @@ UPDATE chats SET protected=1, type=120 WHERE type=130;"#,
sql.execute(
r#"
CREATE TABLE imap_sync (folder TEXT PRIMARY KEY, uidvalidity INTEGER DEFAULT 0, uid_next INTEGER DEFAULT 0);"#,
paramsv![]
()
)
.await?;
for c in &[
@@ -690,6 +690,17 @@ CREATE INDEX smtp_messageid ON imap(rfc724_mid);
}
sql.set_db_version(98).await?;
}
if dbversion < 99 {
sql.execute_migration(
"ALTER TABLE msgs DROP COLUMN server_folder;
ALTER TABLE msgs DROP COLUMN server_uid;
ALTER TABLE msgs DROP COLUMN move_state;
ALTER TABLE chats DROP COLUMN draft_timestamp;
ALTER TABLE chats DROP COLUMN draft_txt",
99,
)
.await?;
}
let new_version = sql
.get_raw_config_int(VERSION_CFG)

View File

@@ -155,7 +155,7 @@ impl Context {
.sql
.query_map(
"SELECT id, item FROM multi_device_sync ORDER BY id;",
paramsv![],
(),
|row| Ok((row.get::<_, u32>(0)?, row.get::<_, String>(1)?)),
|rows| {
let mut ids = vec![];
@@ -201,7 +201,7 @@ impl Context {
self.sql
.execute(
&format!("DELETE FROM multi_device_sync WHERE id IN ({ids});"),
paramsv![],
(),
)
.await?;
Ok(())

View File

@@ -403,7 +403,7 @@ impl TestContext {
SELECT id, msg_id, mime, recipients
FROM smtp
ORDER BY id DESC"#,
paramsv![],
(),
|row| {
let rowid: i64 = row.get(0)?;
let msg_id: MsgId = row.get(1)?;
@@ -604,7 +604,6 @@ impl TestContext {
/// [`TestContext::recv_msg`] with the returned [`SentMessage`] if it wants to receive
/// the message.
pub async fn send_msg(&self, chat_id: ChatId, msg: &mut Message) -> SentMessage<'_> {
chat::prepare_msg(self, chat_id, msg).await.unwrap();
let msg_id = chat::send_msg(self, chat_id, msg).await.unwrap();
let res = self.pop_sent_msg().await;
assert_eq!(

View File

@@ -438,7 +438,7 @@ impl Context {
"DELETE FROM smtp_status_updates
WHERE msg_id IN (SELECT msg_id FROM smtp_status_updates LIMIT 1)
RETURNING msg_id, first_serial, last_serial, descr",
paramsv![],
(),
|row| {
let instance_id: MsgId = row.get(0)?;
let first_serial: StatusUpdateSerial = row.get(1)?;
@@ -1195,7 +1195,7 @@ mod tests {
);
assert_eq!(
t.sql
.count("SELECT COUNT(*) FROM msgs_status_updates;", paramsv![],)
.count("SELECT COUNT(*) FROM msgs_status_updates;", ())
.await?,
0
);
@@ -1543,14 +1543,14 @@ mod tests {
assert_eq!(
t.sql
.count("SELECT COUNT(*) FROM smtp_status_updates", paramsv![],)
.count("SELECT COUNT(*) FROM smtp_status_updates", ())
.await?,
1
);
t.flush_status_updates().await?;
assert_eq!(
t.sql
.count("SELECT COUNT(*) FROM smtp_status_updates", paramsv![],)
.count("SELECT COUNT(*) FROM smtp_status_updates", ())
.await?,
0
);
@@ -1580,7 +1580,7 @@ mod tests {
.await?;
assert_eq!(
t.sql
.count("SELECT COUNT(*) FROM smtp_status_updates", paramsv![],)
.count("SELECT COUNT(*) FROM smtp_status_updates", ())
.await?,
3
);
@@ -1606,7 +1606,7 @@ mod tests {
}
assert_eq!(
t.sql
.count("SELECT COUNT(*) FROM smtp_status_updates", paramsv![],)
.count("SELECT COUNT(*) FROM smtp_status_updates", ())
.await?,
2 - i
);
@@ -1648,7 +1648,7 @@ mod tests {
assert_eq!(
alice
.sql
.count("SELECT COUNT(*) FROM smtp_status_updates", paramsv![],)
.count("SELECT COUNT(*) FROM smtp_status_updates", ())
.await?,
0
);
@@ -2438,7 +2438,7 @@ sth_for_the = "future""#
assert_eq!(
alice
.sql
.count("SELECT COUNT(*) FROM msgs_status_updates;", paramsv![],)
.count("SELECT COUNT(*) FROM msgs_status_updates;", ())
.await?,
0
);
@@ -2461,7 +2461,7 @@ sth_for_the = "future""#
assert!(
alice
.sql
.count("SELECT COUNT(*) FROM msgs_status_updates;", paramsv![],)
.count("SELECT COUNT(*) FROM msgs_status_updates;", ())
.await?
> 0
);