Merge branch 'master' into really-fix-477

This commit is contained in:
björn petersen
2019-09-11 19:52:13 +02:00
committed by GitHub
32 changed files with 570 additions and 678 deletions

View File

@@ -233,7 +233,7 @@ pub unsafe extern "C" fn dc_is_configured(context: *mut dc_context_t) -> libc::c
let context = &*context; let context = &*context;
configure::dc_is_configured(context) configure::dc_is_configured(context) as libc::c_int
} }
#[no_mangle] #[no_mangle]
@@ -1188,7 +1188,7 @@ pub unsafe extern "C" fn dc_get_contact_encrinfo(
Contact::get_encrinfo(context, contact_id) Contact::get_encrinfo(context, contact_id)
.map(|s| s.strdup()) .map(|s| s.strdup())
.unwrap_or_else(|e| { .unwrap_or_else(|e| {
error!(context, 0, "{}", e); error!(context, "{}", e);
std::ptr::null_mut() std::ptr::null_mut()
}) })
} }
@@ -2547,7 +2547,7 @@ impl<T: Default, E: std::fmt::Display> ResultExt<T> for Result<T, E> {
match self { match self {
Ok(t) => t, Ok(t) => t,
Err(err) => { Err(err) => {
error!(context, 0, "{}: {}", message, err); error!(context, "{}: {}", message, err);
Default::default() Default::default()
} }
} }
@@ -2555,7 +2555,7 @@ impl<T: Default, E: std::fmt::Display> ResultExt<T> for Result<T, E> {
fn log_err(&self, context: &context::Context, message: &str) { fn log_err(&self, context: &context::Context, message: &str) {
if let Err(err) = self { if let Err(err) = self {
error!(context, 0, "{}: {}", message, err); error!(context, "{}: {}", message, err);
} }
} }
} }

View File

@@ -28,10 +28,10 @@ use num_traits::FromPrimitive;
/// Argument is a bitmask, executing single or multiple actions in one call. /// Argument is a bitmask, executing single or multiple actions in one call.
/// e.g. bitmask 7 triggers actions definded with bits 1, 2 and 4. /// e.g. bitmask 7 triggers actions definded with bits 1, 2 and 4.
pub unsafe fn dc_reset_tables(context: &Context, bits: i32) -> i32 { pub unsafe fn dc_reset_tables(context: &Context, bits: i32) -> i32 {
info!(context, 0, "Resetting tables ({})...", bits); info!(context, "Resetting tables ({})...", bits);
if 0 != bits & 1 { if 0 != bits & 1 {
sql::execute(context, &context.sql, "DELETE FROM jobs;", params![]).unwrap(); sql::execute(context, &context.sql, "DELETE FROM jobs;", params![]).unwrap();
info!(context, 0, "(1) Jobs reset."); info!(context, "(1) Jobs reset.");
} }
if 0 != bits & 2 { if 0 != bits & 2 {
sql::execute( sql::execute(
@@ -41,11 +41,11 @@ pub unsafe fn dc_reset_tables(context: &Context, bits: i32) -> i32 {
params![], params![],
) )
.unwrap(); .unwrap();
info!(context, 0, "(2) Peerstates reset."); info!(context, "(2) Peerstates reset.");
} }
if 0 != bits & 4 { if 0 != bits & 4 {
sql::execute(context, &context.sql, "DELETE FROM keypairs;", params![]).unwrap(); sql::execute(context, &context.sql, "DELETE FROM keypairs;", params![]).unwrap();
info!(context, 0, "(4) Private keypairs reset."); info!(context, "(4) Private keypairs reset.");
} }
if 0 != bits & 8 { if 0 != bits & 8 {
sql::execute( sql::execute(
@@ -84,7 +84,7 @@ pub unsafe fn dc_reset_tables(context: &Context, bits: i32) -> i32 {
) )
.unwrap(); .unwrap();
sql::execute(context, &context.sql, "DELETE FROM leftgrps;", params![]).unwrap(); sql::execute(context, &context.sql, "DELETE FROM leftgrps;", params![]).unwrap();
info!(context, 0, "(8) Rest but server config reset."); info!(context, "(8) Rest but server config reset.");
} }
context.call_cb(Event::MSGS_CHANGED, 0, 0); context.call_cb(Event::MSGS_CHANGED, 0, 0);
@@ -122,7 +122,7 @@ unsafe fn dc_poke_eml_file(context: &Context, filename: *const libc::c_char) ->
/// @return 1=success, 0=error. /// @return 1=success, 0=error.
unsafe fn poke_spec(context: &Context, spec: *const libc::c_char) -> libc::c_int { unsafe fn poke_spec(context: &Context, spec: *const libc::c_char) -> libc::c_int {
if !context.sql.is_open() { if !context.sql.is_open() {
error!(context, 0, "Import: Database not opened."); error!(context, "Import: Database not opened.");
return 0; return 0;
} }
@@ -143,7 +143,7 @@ unsafe fn poke_spec(context: &Context, spec: *const libc::c_char) -> libc::c_int
} else { } else {
let rs = context.sql.get_config(context, "import_spec"); let rs = context.sql.get_config(context, "import_spec");
if rs.is_none() { if rs.is_none() {
error!(context, 0, "Import: No file or folder given."); error!(context, "Import: No file or folder given.");
ok_to_continue = false; ok_to_continue = false;
} else { } else {
ok_to_continue = true; ok_to_continue = true;
@@ -166,7 +166,6 @@ unsafe fn poke_spec(context: &Context, spec: *const libc::c_char) -> libc::c_int
if dir.is_err() { if dir.is_err() {
error!( error!(
context, context,
0,
"Import: Cannot open directory \"{}\".", "Import: Cannot open directory \"{}\".",
as_str(real_spec), as_str(real_spec),
); );
@@ -182,7 +181,7 @@ unsafe fn poke_spec(context: &Context, spec: *const libc::c_char) -> libc::c_int
let name = name_f.to_string_lossy(); let name = name_f.to_string_lossy();
if name.ends_with(".eml") { if name.ends_with(".eml") {
let path_plus_name = format!("{}/{}", as_str(real_spec), name); let path_plus_name = format!("{}/{}", as_str(real_spec), name);
info!(context, 0, "Import: {}", path_plus_name); info!(context, "Import: {}", path_plus_name);
let path_plus_name_c = CString::yolo(path_plus_name); let path_plus_name_c = CString::yolo(path_plus_name);
if 0 != dc_poke_eml_file(context, path_plus_name_c.as_ptr()) { if 0 != dc_poke_eml_file(context, path_plus_name_c.as_ptr()) {
read_cnt += 1 read_cnt += 1
@@ -195,7 +194,6 @@ unsafe fn poke_spec(context: &Context, spec: *const libc::c_char) -> libc::c_int
if ok_to_continue2 { if ok_to_continue2 {
info!( info!(
context, context,
0,
"Import: {} items read from \"{}\".", "Import: {} items read from \"{}\".",
read_cnt, read_cnt,
as_str(real_spec) as_str(real_spec)
@@ -228,7 +226,6 @@ unsafe fn log_msg(context: &Context, prefix: impl AsRef<str>, msg: &Message) {
let msgtext = dc_msg_get_text(msg); let msgtext = dc_msg_get_text(msg);
info!( info!(
context, context,
0,
"{}#{}{}{}: {} (Contact#{}): {} {}{}{}{} [{}]", "{}#{}{}{}: {} (Contact#{}): {} {}{}{}{} [{}]",
prefix.as_ref(), prefix.as_ref(),
dc_msg_get_id(msg) as libc::c_int, dc_msg_get_id(msg) as libc::c_int,
@@ -268,7 +265,6 @@ unsafe fn log_msglist(context: &Context, msglist: &Vec<u32>) -> Result<(), Error
if msg_id == 9 as libc::c_uint { if msg_id == 9 as libc::c_uint {
info!( info!(
context, context,
0,
"--------------------------------------------------------------------------------" "--------------------------------------------------------------------------------"
); );
@@ -276,7 +272,7 @@ unsafe fn log_msglist(context: &Context, msglist: &Vec<u32>) -> Result<(), Error
} else if msg_id > 0 { } else if msg_id > 0 {
if lines_out == 0 { if lines_out == 0 {
info!( info!(
context, 0, context,
"--------------------------------------------------------------------------------", "--------------------------------------------------------------------------------",
); );
lines_out += 1 lines_out += 1
@@ -288,7 +284,7 @@ unsafe fn log_msglist(context: &Context, msglist: &Vec<u32>) -> Result<(), Error
if lines_out > 0 { if lines_out > 0 {
info!( info!(
context, context,
0, "--------------------------------------------------------------------------------" "--------------------------------------------------------------------------------"
); );
} }
Ok(()) Ok(())
@@ -337,7 +333,7 @@ unsafe fn log_contactlist(context: &Context, contacts: &Vec<u32>) {
); );
} }
info!(context, 0, "Contact#{}: {}{}", contact_id, line, line2); info!(context, "Contact#{}: {}{}", contact_id, line, line2);
} }
} }
} }
@@ -579,7 +575,7 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E
let cnt = chatlist.len(); let cnt = chatlist.len();
if cnt > 0 { if cnt > 0 {
info!( info!(
context, 0, context,
"================================================================================" "================================================================================"
); );
@@ -589,7 +585,6 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E
let temp_name = chat.get_name(); let temp_name = chat.get_name();
info!( info!(
context, context,
0,
"{}#{}: {} [{}] [{} fresh]", "{}#{}: {} [{}] [{} fresh]",
chat_prefix(&chat), chat_prefix(&chat),
chat.get_id(), chat.get_id(),
@@ -614,7 +609,6 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E
let text2 = lot.get_text2(); let text2 = lot.get_text2();
info!( info!(
context, context,
0,
"{}{}{}{} [{}]{}", "{}{}{}{} [{}]{}",
text1.unwrap_or(""), text1.unwrap_or(""),
if text1.is_some() { ": " } else { "" }, if text1.is_some() { ": " } else { "" },
@@ -628,13 +622,13 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E
}, },
); );
info!( info!(
context, 0, context,
"================================================================================" "================================================================================"
); );
} }
} }
if location::is_sending_locations_to_chat(context, 0 as uint32_t) { if location::is_sending_locations_to_chat(context, 0 as uint32_t) {
info!(context, 0, "Location streaming enabled."); info!(context, "Location streaming enabled.");
} }
println!("{} chats", cnt); println!("{} chats", cnt);
} }
@@ -657,7 +651,6 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E
let temp_name = sel_chat.get_name(); let temp_name = sel_chat.get_name();
info!( info!(
context, context,
0,
"{}#{}: {} [{}]{}", "{}#{}: {} [{}]{}",
chat_prefix(sel_chat), chat_prefix(sel_chat),
sel_chat.get_id(), sel_chat.get_id(),
@@ -753,7 +746,7 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E
ensure!(sel_chat.is_some(), "No chat selected."); ensure!(sel_chat.is_some(), "No chat selected.");
let contacts = chat::get_chat_contacts(context, sel_chat.as_ref().unwrap().get_id()); let contacts = chat::get_chat_contacts(context, sel_chat.as_ref().unwrap().get_id());
info!(context, 0, "Memberlist:"); info!(context, "Memberlist:");
log_contactlist(context, &contacts); log_contactlist(context, &contacts);
println!( println!(
@@ -781,7 +774,6 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E
let marker = location.marker.as_ref().unwrap_or(&default_marker); let marker = location.marker.as_ref().unwrap_or(&default_marker);
info!( info!(
context, context,
0,
"Loc#{}: {}: lat={} lng={} acc={} Chat#{} Contact#{} Msg#{} {}", "Loc#{}: {}: lat={} lng={} acc={} Chat#{} Contact#{} Msg#{} {}",
location.location_id, location.location_id,
dc_timestamp_to_str(location.timestamp), dc_timestamp_to_str(location.timestamp),
@@ -795,7 +787,7 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E
); );
} }
if locations.is_empty() { if locations.is_empty() {
info!(context, 0, "No locations."); info!(context, "No locations.");
} }
} }
"sendlocations" => { "sendlocations" => {

View File

@@ -65,7 +65,7 @@ Afterwards ``which python`` tells you that it comes out of the "venv"
directory that contains all python install artifacts. Let's first directory that contains all python install artifacts. Let's first
install test tools:: install test tools::
pip install pytest pytest-timeout requests pip install pytest pytest-timeout pytest-rerunfailures requests
then cargo-build and install the deltachat bindings:: then cargo-build and install the deltachat bindings::

View File

@@ -16,7 +16,10 @@ passenv =
DCC_PY_LIVECONFIG DCC_PY_LIVECONFIG
deps = deps =
pytest pytest
pytest-faulthandler pytest-rerunfailures
pytest-timeout
pytest-xdist
auditwheel
pdbpp pdbpp
requests requests
@@ -51,11 +54,12 @@ commands =
[pytest] [pytest]
addopts = -v -rs addopts = -v -rs --reruns 3 --reruns-delay 2
python_files = tests/test_*.py python_files = tests/test_*.py
norecursedirs = .tox norecursedirs = .tox
xfail_strict=true xfail_strict=true
timeout = 60 timeout = 60
timeout_method = thread
[flake8] [flake8]
max-line-length = 120 max-line-length = 120

View File

@@ -65,7 +65,7 @@ impl<'a> Chat<'a> {
_ => { _ => {
error!( error!(
context, context,
0, "chat: failed to load from db {}: {:?}", chat_id, err "chat: failed to load from db {}: {:?}", chat_id, err
); );
Err(err) Err(err)
} }
@@ -260,7 +260,7 @@ impl<'a> Chat<'a> {
|| self.typ == Chattype::Group || self.typ == Chattype::Group
|| self.typ == Chattype::VerifiedGroup) || self.typ == Chattype::VerifiedGroup)
{ {
error!(context, 0, "Cannot send to chat type #{}.", self.typ,); error!(context, "Cannot send to chat type #{}.", self.typ,);
return Ok(0); return Ok(0);
} }
@@ -296,7 +296,7 @@ impl<'a> Chat<'a> {
} else { } else {
error!( error!(
context, context,
0, "Cannot send message, contact for chat #{} not found.", self.id, "Cannot send message, contact for chat #{} not found.", self.id,
); );
return Ok(0); return Ok(0);
} }
@@ -338,7 +338,6 @@ impl<'a> Chat<'a> {
if prefer_encrypted != 1 { if prefer_encrypted != 1 {
info!( info!(
context, context,
0,
"[autocrypt] peerstate for {} is {}", "[autocrypt] peerstate for {} is {}",
state, state,
if prefer_encrypted == 0 { if prefer_encrypted == 0 {
@@ -350,7 +349,7 @@ impl<'a> Chat<'a> {
all_mutual = 0; all_mutual = 0;
} }
} else { } else {
info!(context, 0, "[autocrypt] no peerstate for {}", state,); info!(context, "[autocrypt] no peerstate for {}", state,);
can_encrypt = 0; can_encrypt = 0;
all_mutual = 0; all_mutual = 0;
} }
@@ -360,7 +359,7 @@ impl<'a> Chat<'a> {
match res { match res {
Ok(_) => {} Ok(_) => {}
Err(err) => { Err(err) => {
warn!(context, 0, "chat: failed to load peerstates: {:?}", err); warn!(context, "chat: failed to load peerstates: {:?}", err);
} }
} }
@@ -464,13 +463,12 @@ impl<'a> Chat<'a> {
} else { } else {
error!( error!(
context, context,
0,
"Cannot send message, cannot insert to database (chat #{}).", "Cannot send message, cannot insert to database (chat #{}).",
self.id, self.id,
); );
} }
} else { } else {
error!(context, 0, "Cannot send message, not configured.",); error!(context, "Cannot send message, not configured.",);
} }
Ok(msg_id) Ok(msg_id)
@@ -541,7 +539,7 @@ pub fn create_by_contact_id(context: &Context, contact_id: u32) -> Result<u32, E
{ {
warn!( warn!(
context, context,
0, "Cannot create chat, contact {} does not exist.", contact_id, "Cannot create chat, contact {} does not exist.", contact_id,
); );
return Err(err); return Err(err);
} else { } else {
@@ -718,7 +716,7 @@ fn prepare_msg_common<'a>(
} }
info!( info!(
context, context,
0, "Attaching \"{}\" for message type #{}.", &path_filename, msg.type_0 "Attaching \"{}\" for message type #{}.", &path_filename, msg.type_0
); );
} else { } else {
bail!("Cannot send messages of type #{}.", msg.type_0); bail!("Cannot send messages of type #{}.", msg.type_0);
@@ -751,7 +749,7 @@ fn last_msg_in_chat_encrypted(context: &Context, sql: &Sql, chat_id: u32) -> boo
match packed.parse::<Params>() { match packed.parse::<Params>() {
Ok(param) => param.exists(Param::GuranteeE2ee), Ok(param) => param.exists(Param::GuranteeE2ee),
Err(err) => { Err(err) => {
error!(context, 0, "invalid params stored: '{}', {:?}", packed, err); error!(context, "invalid params stored: '{}', {:?}", packed, err);
false false
} }
} }
@@ -1385,7 +1383,7 @@ pub fn add_contact_to_chat_ex(
if chat.typ == Chattype::VerifiedGroup { if chat.typ == Chattype::VerifiedGroup {
if contact.is_verified() != VerifiedStatus::BidirectVerified { if contact.is_verified() != VerifiedStatus::BidirectVerified {
error!( error!(
context, 0, context,
"Only bidirectional verified contacts can be added to verified groups." "Only bidirectional verified contacts can be added to verified groups."
); );
OK_TO_CONTINUE = false; OK_TO_CONTINUE = false;
@@ -1451,7 +1449,7 @@ pub fn set_gossiped_timestamp(context: &Context, chat_id: u32, timestamp: i64) {
if 0 != chat_id { if 0 != chat_id {
info!( info!(
context, context,
0, "set gossiped_timestamp for chat #{} to {}.", chat_id, timestamp, "set gossiped_timestamp for chat #{} to {}.", chat_id, timestamp,
); );
sql::execute( sql::execute(
@@ -1464,7 +1462,7 @@ pub fn set_gossiped_timestamp(context: &Context, chat_id: u32, timestamp: i64) {
} else { } else {
info!( info!(
context, context,
0, "set gossiped_timestamp for all chats to {}.", timestamp, "set gossiped_timestamp for all chats to {}.", timestamp,
); );
sql::execute( sql::execute(
context, context,

View File

@@ -69,7 +69,6 @@ pub unsafe fn moz_autoconfigure(
Err(e) => { Err(e) => {
error!( error!(
context, context,
0,
"Configure xml: Error at position {}: {:?}", "Configure xml: Error at position {}: {:?}",
reader.buffer_position(), reader.buffer_position(),
e e
@@ -87,7 +86,7 @@ pub unsafe fn moz_autoconfigure(
|| moz_ac.out.send_port == 0 || moz_ac.out.send_port == 0
{ {
let r = moz_ac.out.to_string(); let r = moz_ac.out.to_string();
warn!(context, 0, "Bad or incomplete autoconfig: {}", r,); warn!(context, "Bad or incomplete autoconfig: {}", r,);
free(xml_raw as *mut libc::c_void); free(xml_raw as *mut libc::c_void);
return None; return None;
} }

View File

@@ -75,7 +75,6 @@ pub unsafe fn outlk_autodiscover(
Err(e) => { Err(e) => {
error!( error!(
context, context,
0,
"Configure xml: Error at position {}: {:?}", "Configure xml: Error at position {}: {:?}",
reader.buffer_position(), reader.buffer_position(),
e e
@@ -109,7 +108,7 @@ pub unsafe fn outlk_autodiscover(
|| outlk_ad.out.send_port == 0 || outlk_ad.out.send_port == 0
{ {
let r = outlk_ad.out.to_string(); let r = outlk_ad.out.to_string();
warn!(context, 0, "Bad or incomplete autoconfig: {}", r,); warn!(context, "Bad or incomplete autoconfig: {}", r,);
free(url as *mut libc::c_void); free(url as *mut libc::c_void);
free(xml_raw as *mut libc::c_void); free(xml_raw as *mut libc::c_void);
outlk_clean_config(&mut outlk_ad); outlk_clean_config(&mut outlk_ad);

View File

@@ -34,10 +34,7 @@ macro_rules! progress {
// connect // connect
pub unsafe fn configure(context: &Context) { pub unsafe fn configure(context: &Context) {
if dc_has_ongoing(context) { if dc_has_ongoing(context) {
warn!( warn!(context, "There is already another ongoing process running.",);
context,
0, "There is already another ongoing process running.",
);
return; return;
} }
job_kill_action(context, Action::ConfigureImap); job_kill_action(context, Action::ConfigureImap);
@@ -45,17 +42,8 @@ pub unsafe fn configure(context: &Context) {
} }
/// Check if the context is already configured. /// Check if the context is already configured.
pub fn dc_is_configured(context: &Context) -> libc::c_int { pub fn dc_is_configured(context: &Context) -> bool {
if context context.sql.get_config_bool(context, "configured")
.sql
.get_config_int(context, "configured")
.unwrap_or_default()
> 0
{
1
} else {
0
}
} }
/******************************************************************************* /*******************************************************************************
@@ -73,7 +61,7 @@ pub unsafe fn dc_job_do_DC_JOB_CONFIGURE_IMAP(context: &Context, _job: &Job) {
if dc_alloc_ongoing(context) { if dc_alloc_ongoing(context) {
ongoing_allocated_here = true; ongoing_allocated_here = true;
if !context.sql.is_open() { if !context.sql.is_open() {
error!(context, 0, "Cannot configure, database not opened.",); error!(context, "Cannot configure, database not opened.",);
} else { } else {
context.inbox.read().unwrap().disconnect(context); context.inbox.read().unwrap().disconnect(context);
context context
@@ -89,7 +77,7 @@ pub unsafe fn dc_job_do_DC_JOB_CONFIGURE_IMAP(context: &Context, _job: &Job) {
.imap .imap
.disconnect(context); .disconnect(context);
context.smtp.clone().lock().unwrap().disconnect(); context.smtp.clone().lock().unwrap().disconnect();
info!(context, 0, "Configure ...",); info!(context, "Configure ...",);
let s_a = context.running_state.clone(); let s_a = context.running_state.clone();
let s = s_a.read().unwrap(); let s = s_a.read().unwrap();
@@ -113,7 +101,7 @@ pub unsafe fn dc_job_do_DC_JOB_CONFIGURE_IMAP(context: &Context, _job: &Job) {
1 => { 1 => {
progress!(context, 1); progress!(context, 1);
if param.addr.is_empty() { if param.addr.is_empty() {
error!(context, 0, "Please enter an email address.",); error!(context, "Please enter an email address.",);
} }
!param.addr.is_empty() !param.addr.is_empty()
} }
@@ -146,7 +134,7 @@ pub unsafe fn dc_job_do_DC_JOB_CONFIGURE_IMAP(context: &Context, _job: &Job) {
utf8_percent_encode(&param.addr, NON_ALPHANUMERIC).to_string(); utf8_percent_encode(&param.addr, NON_ALPHANUMERIC).to_string();
true true
} else { } else {
error!(context, 0, "Bad email-address."); error!(context, "Bad email-address.");
false false
} }
} }
@@ -256,7 +244,7 @@ pub unsafe fn dc_job_do_DC_JOB_CONFIGURE_IMAP(context: &Context, _job: &Job) {
12 => { 12 => {
progress!(context, 500); progress!(context, 500);
if let Some(ref cfg) = param_autoconfig { if let Some(ref cfg) = param_autoconfig {
info!(context, 0, "Got autoconfig: {}", &cfg); info!(context, "Got autoconfig: {}", &cfg);
if !cfg.mail_user.is_empty() { if !cfg.mail_user.is_empty() {
param.mail_user = cfg.mail_user.clone(); param.mail_user = cfg.mail_user.clone();
} }
@@ -340,7 +328,7 @@ pub unsafe fn dc_job_do_DC_JOB_CONFIGURE_IMAP(context: &Context, _job: &Job) {
|| param.send_pw.is_empty() || param.send_pw.is_empty()
|| param.server_flags == 0 || param.server_flags == 0
{ {
error!(context, 0, "Account settings incomplete."); error!(context, "Account settings incomplete.");
false false
} else { } else {
true true
@@ -357,7 +345,7 @@ pub unsafe fn dc_job_do_DC_JOB_CONFIGURE_IMAP(context: &Context, _job: &Job) {
ok_to_continue8 = true; ok_to_continue8 = true;
break; break;
} }
info!(context, 0, "Trying: {}", &param); info!(context, "Trying: {}", &param);
if context.inbox.read().unwrap().connect(context, &param) { if context.inbox.read().unwrap().connect(context, &param) {
ok_to_continue8 = true; ok_to_continue8 = true;
@@ -375,7 +363,7 @@ pub unsafe fn dc_job_do_DC_JOB_CONFIGURE_IMAP(context: &Context, _job: &Job) {
progress!(context, 650 + username_variation * 30); progress!(context, 650 + username_variation * 30);
param.server_flags &= !(0x100 | 0x200 | 0x400); param.server_flags &= !(0x100 | 0x200 | 0x400);
param.server_flags |= 0x100; param.server_flags |= 0x100;
info!(context, 0, "Trying: {}", &param); info!(context, "Trying: {}", &param);
if context.inbox.read().unwrap().connect(context, &param) { if context.inbox.read().unwrap().connect(context, &param) {
ok_to_continue8 = true; ok_to_continue8 = true;
@@ -388,7 +376,7 @@ pub unsafe fn dc_job_do_DC_JOB_CONFIGURE_IMAP(context: &Context, _job: &Job) {
} }
progress!(context, 660 + username_variation * 30); progress!(context, 660 + username_variation * 30);
param.mail_port = 143; param.mail_port = 143;
info!(context, 0, "Trying: {}", &param); info!(context, "Trying: {}", &param);
if context.inbox.read().unwrap().connect(context, &param) { if context.inbox.read().unwrap().connect(context, &param) {
ok_to_continue8 = true; ok_to_continue8 = true;
@@ -443,7 +431,7 @@ pub unsafe fn dc_job_do_DC_JOB_CONFIGURE_IMAP(context: &Context, _job: &Job) {
param.server_flags &= !(0x10000 | 0x20000 | 0x40000); param.server_flags &= !(0x10000 | 0x20000 | 0x40000);
param.server_flags |= 0x10000; param.server_flags |= 0x10000;
param.send_port = 587; param.send_port = 587;
info!(context, 0, "Trying: {}", &param); info!(context, "Trying: {}", &param);
if !context if !context
.smtp .smtp
@@ -459,7 +447,7 @@ pub unsafe fn dc_job_do_DC_JOB_CONFIGURE_IMAP(context: &Context, _job: &Job) {
param.server_flags &= !(0x10000 | 0x20000 | 0x40000); param.server_flags &= !(0x10000 | 0x20000 | 0x40000);
param.server_flags |= 0x10000; param.server_flags |= 0x10000;
param.send_port = 25; param.send_port = 25;
info!(context, 0, "Trying: {}", &param); info!(context, "Trying: {}", &param);
if !context if !context
.smtp .smtp
@@ -518,7 +506,7 @@ pub unsafe fn dc_job_do_DC_JOB_CONFIGURE_IMAP(context: &Context, _job: &Job) {
) )
.ok(); .ok();
context.sql.set_config_int(context, "configured", 1).ok(); context.sql.set_config_bool(context, "configured", true);
true true
} }
18 => { 18 => {
@@ -528,13 +516,13 @@ pub unsafe fn dc_job_do_DC_JOB_CONFIGURE_IMAP(context: &Context, _job: &Job) {
// (~30 seconds on a Moto G4 play) and might looks as if message sending is always that slow. // (~30 seconds on a Moto G4 play) and might looks as if message sending is always that slow.
e2ee::ensure_secret_key_exists(context); e2ee::ensure_secret_key_exists(context);
success = true; success = true;
info!(context, 0, "Configure completed."); info!(context, "Configure completed.");
progress!(context, 940); progress!(context, 940);
break; // We are done here break; // We are done here
} }
_ => { _ => {
error!(context, 0, "Internal error: step counter out of bound",); error!(context, "Internal error: step counter out of bound",);
break; break;
} }
}; };
@@ -582,10 +570,7 @@ pub unsafe fn dc_job_do_DC_JOB_CONFIGURE_IMAP(context: &Context, _job: &Job) {
pub fn dc_alloc_ongoing(context: &Context) -> bool { pub fn dc_alloc_ongoing(context: &Context) -> bool {
if dc_has_ongoing(context) { if dc_has_ongoing(context) {
warn!( warn!(context, "There is already another ongoing process running.",);
context,
0, "There is already another ongoing process running.",
);
false false
} else { } else {
@@ -628,7 +613,7 @@ pub fn dc_connect_to_configured_imap(context: &Context, imap: &Imap) -> libc::c_
.unwrap_or_default() .unwrap_or_default()
== 0 == 0
{ {
warn!(context, 0, "Not configured, cannot connect.",); warn!(context, "Not configured, cannot connect.",);
} else { } else {
let param = LoginParam::from_database(context, "configured_"); let param = LoginParam::from_database(context, "configured_");
// the trailing underscore is correct // the trailing underscore is correct
@@ -651,15 +636,15 @@ pub fn dc_stop_ongoing_process(context: &Context) {
let mut s = s_a.write().unwrap(); let mut s = s_a.write().unwrap();
if s.ongoing_running && !s.shall_stop_ongoing { if s.ongoing_running && !s.shall_stop_ongoing {
info!(context, 0, "Signaling the ongoing process to stop ASAP.",); info!(context, "Signaling the ongoing process to stop ASAP.",);
s.shall_stop_ongoing = true; s.shall_stop_ongoing = true;
} else { } else {
info!(context, 0, "No ongoing process to stop.",); info!(context, "No ongoing process to stop.",);
}; };
} }
pub fn read_autoconf_file(context: &Context, url: &str) -> *mut libc::c_char { pub fn read_autoconf_file(context: &Context, url: &str) -> *mut libc::c_char {
info!(context, 0, "Testing {} ...", url); info!(context, "Testing {} ...", url);
match reqwest::Client::new() match reqwest::Client::new()
.get(url) .get(url)
@@ -668,7 +653,7 @@ pub fn read_autoconf_file(context: &Context, url: &str) -> *mut libc::c_char {
{ {
Ok(res) => unsafe { res.strdup() }, Ok(res) => unsafe { res.strdup() },
Err(_err) => { Err(_err) => {
info!(context, 0, "Can\'t read file.",); info!(context, "Can\'t read file.",);
std::ptr::null_mut() std::ptr::null_mut()
} }

View File

@@ -308,7 +308,6 @@ impl<'a> Contact<'a> {
if !may_be_valid_addr(&addr) { if !may_be_valid_addr(&addr) {
warn!( warn!(
context, context,
0,
"Bad address \"{}\" for contact \"{}\".", "Bad address \"{}\" for contact \"{}\".",
addr, addr,
if !name.as_ref().is_empty() { if !name.as_ref().is_empty() {
@@ -404,7 +403,7 @@ impl<'a> Contact<'a> {
row_id = sql::get_rowid(context, &context.sql, "contacts", "addr", addr); row_id = sql::get_rowid(context, &context.sql, "contacts", "addr", addr);
sth_modified = Modifier::Created; sth_modified = Modifier::Created;
} else { } else {
error!(context, 0, "Cannot add contact."); error!(context, "Cannot add contact.");
} }
} }
@@ -683,7 +682,7 @@ impl<'a> Contact<'a> {
return Ok(()); return Ok(());
} }
Err(err) => { Err(err) => {
error!(context, 0, "delete_contact {} failed ({})", contact_id, err); error!(context, "delete_contact {} failed ({})", contact_id, err);
return Err(err); return Err(err);
} }
} }
@@ -691,7 +690,7 @@ impl<'a> Contact<'a> {
info!( info!(
context, context,
0, "could not delete contact {}, there are {} messages with it", contact_id, count_msgs "could not delete contact {}, there are {} messages with it", contact_id, count_msgs
); );
bail!("Could not delete contact with messages in it"); bail!("Could not delete contact with messages in it");
} }

View File

@@ -208,17 +208,11 @@ unsafe fn cb_precheck_imf(
if *old_server_folder.offset(0isize) as libc::c_int == 0i32 if *old_server_folder.offset(0isize) as libc::c_int == 0i32
&& old_server_uid == 0i32 as libc::c_uint && old_server_uid == 0i32 as libc::c_uint
{ {
info!( info!(context, "[move] detected bbc-self {}", as_str(rfc724_mid),);
context,
0,
"[move] detected bbc-self {}",
as_str(rfc724_mid),
);
mark_seen = 1i32 mark_seen = 1i32
} else if as_str(old_server_folder) != server_folder { } else if as_str(old_server_folder) != server_folder {
info!( info!(
context, context,
0,
"[move] detected moved message {}", "[move] detected moved message {}",
as_str(rfc724_mid), as_str(rfc724_mid),
); );
@@ -258,16 +252,16 @@ fn cb_get_config(context: &Context, key: &str) -> Option<String> {
} }
pub unsafe fn dc_close(context: &Context) { pub unsafe fn dc_close(context: &Context) {
info!(context, 0, "disconnecting INBOX-watch",); info!(context, "disconnecting INBOX-watch",);
context.inbox.read().unwrap().disconnect(context); context.inbox.read().unwrap().disconnect(context);
info!(context, 0, "disconnecting sentbox-thread",); info!(context, "disconnecting sentbox-thread",);
context context
.sentbox_thread .sentbox_thread
.read() .read()
.unwrap() .unwrap()
.imap .imap
.disconnect(context); .disconnect(context);
info!(context, 0, "disconnecting mvbox-thread",); info!(context, "disconnecting mvbox-thread",);
context context
.mvbox_thread .mvbox_thread
.read() .read()
@@ -275,7 +269,7 @@ pub unsafe fn dc_close(context: &Context) {
.imap .imap
.disconnect(context); .disconnect(context);
info!(context, 0, "disconnecting SMTP"); info!(context, "disconnecting SMTP");
context.smtp.clone().lock().unwrap().disconnect(); context.smtp.clone().lock().unwrap().disconnect();
context.sql.close(context); context.sql.close(context);

View File

@@ -58,7 +58,6 @@ pub unsafe fn dc_imex_has_backup(
if dir_iter.is_err() { if dir_iter.is_err() {
info!( info!(
context, context,
0,
"Backup check: Cannot open directory \"{}\".\x00", "Backup check: Cannot open directory \"{}\".\x00",
dir_name.display(), dir_name.display(),
); );
@@ -92,7 +91,7 @@ pub unsafe fn dc_imex_has_backup(
Some(path) => match path.to_c_string() { Some(path) => match path.to_c_string() {
Ok(cstr) => dc_strdup(cstr.as_ptr()), Ok(cstr) => dc_strdup(cstr.as_ptr()),
Err(err) => { Err(err) => {
error!(context, 0, "Invalid backup filename: {}", err); error!(context, "Invalid backup filename: {}", err);
std::ptr::null_mut() std::ptr::null_mut()
} }
}, },
@@ -156,7 +155,7 @@ pub unsafe fn dc_initiate_key_transfer(context: &Context) -> *mut libc::c_char {
.shall_stop_ongoing .shall_stop_ongoing
{ {
if let Ok(msg_id) = chat::send_msg(context, chat_id, &mut msg) { if let Ok(msg_id) = chat::send_msg(context, chat_id, &mut msg) {
info!(context, 0, "Wait for setup message being sent ...",); info!(context, "Wait for setup message being sent ...",);
loop { loop {
if context if context
.running_state .running_state
@@ -170,7 +169,7 @@ pub unsafe fn dc_initiate_key_transfer(context: &Context) -> *mut libc::c_char {
std::thread::sleep(std::time::Duration::from_secs(1)); std::thread::sleep(std::time::Duration::from_secs(1));
if let Ok(msg) = dc_get_msg(context, msg_id) { if let Ok(msg) = dc_get_msg(context, msg_id) {
if 0 != dc_msg_is_sent(&msg) { if 0 != dc_msg_is_sent(&msg) {
info!(context, 0, "... setup message sent.",); info!(context, "... setup message sent.",);
break; break;
} }
} }
@@ -208,12 +207,8 @@ pub fn dc_render_setup_file(context: &Context, passphrase: &str) -> Result<Strin
_ => Some(("Autocrypt-Prefer-Encrypt", "mutual")), _ => Some(("Autocrypt-Prefer-Encrypt", "mutual")),
}; };
let private_key_asc = private_key.to_asc(ac_headers); let private_key_asc = private_key.to_asc(ac_headers);
let encr = { let encr = dc_pgp_symm_encrypt(&passphrase, private_key_asc.as_bytes())
let private_key_asc_c = CString::yolo(private_key_asc); .ok_or(format_err!("Failed to encrypt private key."))?;
let passphrase_c = CString::yolo(passphrase);
dc_pgp_symm_encrypt(passphrase_c.as_ptr(), private_key_asc_c.as_bytes())
.ok_or(format_err!("Failed to encrypt private key."))?
};
let replacement = format!( let replacement = format!(
concat!( concat!(
"-----BEGIN PGP MESSAGE-----\r\n", "-----BEGIN PGP MESSAGE-----\r\n",
@@ -279,44 +274,46 @@ pub unsafe fn dc_continue_key_transfer(
let mut filebytes: size_t = 0i32 as size_t; let mut filebytes: size_t = 0i32 as size_t;
let mut armored_key: *mut libc::c_char = ptr::null_mut(); let mut armored_key: *mut libc::c_char = ptr::null_mut();
let mut norm_sc: *mut libc::c_char = ptr::null_mut(); let mut norm_sc: *mut libc::c_char = ptr::null_mut();
if !(msg_id <= 9i32 as libc::c_uint || setup_code.is_null()) { if msg_id <= 9i32 as libc::c_uint || setup_code.is_null() {
let msg = dc_get_msg(context, msg_id); return false;
if msg.is_err() }
|| !dc_msg_is_setupmessage(msg.as_ref().unwrap()) let msg = dc_get_msg(context, msg_id);
|| { if msg.is_err()
filename = dc_msg_get_file(msg.as_ref().unwrap()); || !dc_msg_is_setupmessage(msg.as_ref().unwrap())
filename.is_null() || {
} filename = dc_msg_get_file(msg.as_ref().unwrap());
|| *filename.offset(0isize) as libc::c_int == 0i32 filename.is_null()
{ }
error!(context, 0, "Message is no Autocrypt Setup Message.",); || *filename.offset(0isize) as libc::c_int == 0i32
} else if 0 {
== dc_read_file( error!(context, "Message is no Autocrypt Setup Message.",);
context, } else if 0
filename, == dc_read_file(
&mut filecontent as *mut *mut libc::c_char as *mut *mut libc::c_void, context,
&mut filebytes, filename,
) &mut filecontent as *mut *mut libc::c_char as *mut *mut libc::c_void,
|| filecontent.is_null() &mut filebytes,
|| filebytes <= 0 )
{ || filecontent.is_null()
error!(context, 0, "Cannot read Autocrypt Setup Message file.",); || filebytes <= 0
{
error!(context, "Cannot read Autocrypt Setup Message file.",);
} else {
norm_sc = dc_normalize_setup_code(context, setup_code);
if norm_sc.is_null() {
warn!(context, "Cannot normalize Setup Code.",);
} else { } else {
norm_sc = dc_normalize_setup_code(context, setup_code); armored_key = dc_decrypt_setup_file(context, norm_sc, filecontent);
if norm_sc.is_null() { if armored_key.is_null() {
warn!(context, 0, "Cannot normalize Setup Code.",); warn!(context, "Cannot decrypt Autocrypt Setup Message.",);
} else { } else if set_self_key(context, armored_key, 1) {
armored_key = dc_decrypt_setup_file(context, norm_sc, filecontent); /*set default*/
if armored_key.is_null() { /* error already logged */
warn!(context, 0, "Cannot decrypt Autocrypt Setup Message.",); success = true
} else if set_self_key(context, armored_key, 1) {
/*set default*/
/* error already logged */
success = true
}
} }
} }
} }
free(armored_key as *mut libc::c_void); free(armored_key as *mut libc::c_void);
free(filecontent as *mut libc::c_void); free(filecontent as *mut libc::c_void);
free(filename as *mut libc::c_void); free(filename as *mut libc::c_void);
@@ -338,7 +335,7 @@ fn set_self_key(
.and_then(|(k, h)| k.split_key().map(|pub_key| (k, pub_key, h))); .and_then(|(k, h)| k.split_key().map(|pub_key| (k, pub_key, h)));
if keys.is_none() { if keys.is_none() {
error!(context, 0, "File does not contain a valid private key.",); error!(context, "File does not contain a valid private key.",);
return false; return false;
} }
@@ -368,13 +365,13 @@ fn set_self_key(
return false; return false;
} }
} else { } else {
error!(context, 0, "File does not contain a private key.",); error!(context, "File does not contain a private key.",);
} }
let self_addr = context.sql.get_config(context, "configured_addr"); let self_addr = context.sql.get_config(context, "configured_addr");
if self_addr.is_none() { if self_addr.is_none() {
error!(context, 0, "Missing self addr"); error!(context, "Missing self addr");
return false; return false;
} }
@@ -386,7 +383,7 @@ fn set_self_key(
set_default, set_default,
&context.sql, &context.sql,
) { ) {
error!(context, 0, "Cannot save keypair."); error!(context, "Cannot save keypair.");
return false; return false;
} }
@@ -445,7 +442,7 @@ pub unsafe fn dc_decrypt_setup_file(
{ {
/* decrypt symmetrically */ /* decrypt symmetrically */
if let Some(plain) = dc_pgp_symm_decrypt( if let Some(plain) = dc_pgp_symm_decrypt(
passphrase, as_str(passphrase),
std::slice::from_raw_parts(binary as *const u8, binary_bytes), std::slice::from_raw_parts(binary as *const u8, binary_bytes),
) { ) {
let payload_c = CString::new(plain).unwrap(); let payload_c = CString::new(plain).unwrap();
@@ -507,19 +504,18 @@ pub unsafe fn dc_job_do_DC_JOB_IMEX_IMAP(context: &Context, job: &Job) {
let _param2 = CString::yolo(job.param.get(Param::Arg2).unwrap_or_default()); let _param2 = CString::yolo(job.param.get(Param::Arg2).unwrap_or_default());
if strlen(param1.as_ptr()) == 0 { if strlen(param1.as_ptr()) == 0 {
error!(context, 0, "No Import/export dir/file given.",); error!(context, "No Import/export dir/file given.",);
} else { } else {
info!(context, 0, "Import/export process started.",); info!(context, "Import/export process started.",);
context.call_cb(Event::IMEX_PROGRESS, 10 as uintptr_t, 0 as uintptr_t); context.call_cb(Event::IMEX_PROGRESS, 10 as uintptr_t, 0 as uintptr_t);
if !context.sql.is_open() { if !context.sql.is_open() {
error!(context, 0, "Import/export: Database not opened.",); error!(context, "Import/export: Database not opened.",);
} else { } else {
if what == 1 || what == 11 { if what == 1 || what == 11 {
/* before we export anything, make sure the private key exists */ /* before we export anything, make sure the private key exists */
if e2ee::ensure_secret_key_exists(context).is_err() { if e2ee::ensure_secret_key_exists(context).is_err() {
error!( error!(
context, context,
0,
"Import/export: Cannot create private key or private key not available.", "Import/export: Cannot create private key or private key not available.",
); );
ok_to_continue = false; ok_to_continue = false;
@@ -531,25 +527,25 @@ pub unsafe fn dc_job_do_DC_JOB_IMEX_IMAP(context: &Context, job: &Job) {
match what { match what {
1 => { 1 => {
if 0 != export_self_keys(context, param1.as_ptr()) { if 0 != export_self_keys(context, param1.as_ptr()) {
info!(context, 0, "Import/export completed.",); info!(context, "Import/export completed.",);
success = 1 success = 1
} }
} }
2 => { 2 => {
if 0 != import_self_keys(context, param1.as_ptr()) { if 0 != import_self_keys(context, param1.as_ptr()) {
info!(context, 0, "Import/export completed.",); info!(context, "Import/export completed.",);
success = 1 success = 1
} }
} }
11 => { 11 => {
if 0 != export_backup(context, param1.as_ptr()) { if 0 != export_backup(context, param1.as_ptr()) {
info!(context, 0, "Import/export completed.",); info!(context, "Import/export completed.",);
success = 1 success = 1
} }
} }
12 => { 12 => {
if 0 != import_backup(context, param1.as_ptr()) { if 0 != import_backup(context, param1.as_ptr()) {
info!(context, 0, "Import/export completed.",); info!(context, "Import/export completed.",);
success = 1 success = 1
} }
} }
@@ -576,7 +572,6 @@ pub unsafe fn dc_job_do_DC_JOB_IMEX_IMAP(context: &Context, job: &Job) {
unsafe fn import_backup(context: &Context, backup_to_import: *const libc::c_char) -> libc::c_int { unsafe fn import_backup(context: &Context, backup_to_import: *const libc::c_char) -> libc::c_int {
info!( info!(
context, context,
0,
"Import \"{}\" to \"{}\".", "Import \"{}\" to \"{}\".",
as_str(backup_to_import), as_str(backup_to_import),
context context
@@ -585,8 +580,8 @@ unsafe fn import_backup(context: &Context, backup_to_import: *const libc::c_char
.map_or("<<None>>", |p| p.to_str().unwrap()) .map_or("<<None>>", |p| p.to_str().unwrap())
); );
if 0 != dc_is_configured(context) { if dc_is_configured(context) {
error!(context, 0, "Cannot import backups to accounts in use."); error!(context, "Cannot import backups to accounts in use.");
return 0; return 0;
} }
&context.sql.close(&context); &context.sql.close(&context);
@@ -594,7 +589,7 @@ unsafe fn import_backup(context: &Context, backup_to_import: *const libc::c_char
if dc_file_exist(context, context.get_dbfile().unwrap()) { if dc_file_exist(context, context.get_dbfile().unwrap()) {
error!( error!(
context, context,
0, "Cannot import backups: Cannot delete the old file.", "Cannot import backups: Cannot delete the old file.",
); );
return 0; return 0;
} }
@@ -621,7 +616,7 @@ unsafe fn import_backup(context: &Context, backup_to_import: *const libc::c_char
.unwrap_or_default() as usize; .unwrap_or_default() as usize;
info!( info!(
context, context,
0, "***IMPORT-in-progress: total_files_cnt={:?}", total_files_cnt, "***IMPORT-in-progress: total_files_cnt={:?}", total_files_cnt,
); );
let res = context.sql.query_map( let res = context.sql.query_map(
@@ -669,7 +664,6 @@ unsafe fn import_backup(context: &Context, backup_to_import: *const libc::c_char
} }
error!( error!(
context, context,
0,
"Storage full? Cannot write file {} with {} bytes.", "Storage full? Cannot write file {} with {} bytes.",
&pathNfilename, &pathNfilename,
file_blob.len(), file_blob.len(),
@@ -716,7 +710,7 @@ unsafe fn export_backup(context: &Context, dir: *const libc::c_char) -> libc::c_
let buffer = CString::yolo(res); let buffer = CString::yolo(res);
let dest_pathNfilename = dc_get_fine_pathNfilename(context, dir, buffer.as_ptr()); let dest_pathNfilename = dc_get_fine_pathNfilename(context, dir, buffer.as_ptr());
if dest_pathNfilename.is_null() { if dest_pathNfilename.is_null() {
error!(context, 0, "Cannot get backup file name.",); error!(context, "Cannot get backup file name.",);
return success; return success;
} }
@@ -728,7 +722,6 @@ unsafe fn export_backup(context: &Context, dir: *const libc::c_char) -> libc::c_
let mut closed = true; let mut closed = true;
info!( info!(
context, context,
0,
"Backup \"{}\" to \"{}\".", "Backup \"{}\" to \"{}\".",
context context
.get_dbfile() .get_dbfile()
@@ -772,7 +765,7 @@ unsafe fn export_backup(context: &Context, dir: *const libc::c_char) -> libc::c_
if let Ok(dir_handle) = std::fs::read_dir(dir) { if let Ok(dir_handle) = std::fs::read_dir(dir) {
total_files_cnt += dir_handle.filter(|r| r.is_ok()).count(); total_files_cnt += dir_handle.filter(|r| r.is_ok()).count();
info!(context, 0, "EXPORT: total_files_cnt={}", total_files_cnt); info!(context, "EXPORT: total_files_cnt={}", total_files_cnt);
if total_files_cnt > 0 { if total_files_cnt > 0 {
// scan directory, pass 2: copy files // scan directory, pass 2: copy files
if let Ok(dir_handle) = std::fs::read_dir(dir) { if let Ok(dir_handle) = std::fs::read_dir(dir) {
@@ -818,7 +811,7 @@ unsafe fn export_backup(context: &Context, dir: *const libc::c_char) -> libc::c_
{ {
continue; continue;
} else { } else {
info!(context, 0, "EXPORTing filename={}", name); info!(context, "EXPORTing filename={}", name);
let curr_pathNfilename = format!( let curr_pathNfilename = format!(
"{}/{}", "{}/{}",
as_str(context.get_blobdir()), as_str(context.get_blobdir()),
@@ -834,7 +827,6 @@ unsafe fn export_backup(context: &Context, dir: *const libc::c_char) -> libc::c_
if stmt.execute(params![name, buf]).is_err() { if stmt.execute(params![name, buf]).is_err() {
error!( error!(
context, context,
0,
"Disk full? Cannot add file \"{}\" to backup.", "Disk full? Cannot add file \"{}\" to backup.",
&curr_pathNfilename, &curr_pathNfilename,
); );
@@ -854,13 +846,12 @@ unsafe fn export_backup(context: &Context, dir: *const libc::c_char) -> libc::c_
} else { } else {
error!( error!(
context, context,
0,
"Backup: Cannot copy from blob-directory \"{}\".", "Backup: Cannot copy from blob-directory \"{}\".",
as_str(context.get_blobdir()), as_str(context.get_blobdir()),
); );
} }
} else { } else {
info!(context, 0, "Backup: No files to copy.",); info!(context, "Backup: No files to copy.",);
ok_to_continue = true; ok_to_continue = true;
} }
if ok_to_continue { if ok_to_continue {
@@ -879,7 +870,6 @@ unsafe fn export_backup(context: &Context, dir: *const libc::c_char) -> libc::c_
} else { } else {
error!( error!(
context, context,
0,
"Backup: Cannot get info for blob-directory \"{}\".", "Backup: Cannot get info for blob-directory \"{}\".",
as_str(context.get_blobdir()) as_str(context.get_blobdir())
); );
@@ -944,7 +934,7 @@ unsafe fn import_self_keys(context: &Context, dir_name: *const libc::c_char) ->
dir_name, dir_name,
name_c.as_ptr(), name_c.as_ptr(),
); );
info!(context, 0, "Checking: {}", as_str(path_plus_name)); info!(context, "Checking: {}", as_str(path_plus_name));
free(buf as *mut libc::c_void); free(buf as *mut libc::c_void);
buf = ptr::null_mut(); buf = ptr::null_mut();
if 0 == dc_read_file( if 0 == dc_read_file(
@@ -988,7 +978,6 @@ unsafe fn import_self_keys(context: &Context, dir_name: *const libc::c_char) ->
{ {
info!( info!(
context, context,
0,
"Treating \"{}\" as a legacy private key.", "Treating \"{}\" as a legacy private key.",
as_str(path_plus_name), as_str(path_plus_name),
); );
@@ -1002,7 +991,6 @@ unsafe fn import_self_keys(context: &Context, dir_name: *const libc::c_char) ->
if imported_cnt == 0i32 { if imported_cnt == 0i32 {
error!( error!(
context, context,
0,
"No private keys found in \"{}\".", "No private keys found in \"{}\".",
as_str(dir_name), as_str(dir_name),
); );
@@ -1010,7 +998,6 @@ unsafe fn import_self_keys(context: &Context, dir_name: *const libc::c_char) ->
} else { } else {
error!( error!(
context, context,
0,
"Import: Cannot open directory \"{}\".", "Import: Cannot open directory \"{}\".",
as_str(dir_name), as_str(dir_name),
); );
@@ -1110,10 +1097,10 @@ unsafe fn export_key_to_asc_file(
id, id,
) )
} }
info!(context, 0, "Exporting key {}", as_str(file_name),); info!(context, "Exporting key {}", as_str(file_name),);
dc_delete_file(context, as_path(file_name)); dc_delete_file(context, as_path(file_name));
if !key.write_asc_to_file(file_name, context) { if !key.write_asc_to_file(file_name, context) {
error!(context, 0, "Cannot write key to {}", as_str(file_name),); error!(context, "Cannot write key to {}", as_str(file_name),);
} else { } else {
context.call_cb( context.call_cb(
Event::IMEX_FILE_WRITTEN, Event::IMEX_FILE_WRITTEN,

View File

@@ -225,7 +225,7 @@ pub unsafe fn dc_mimefactory_load_msg(
Err(err) => { Err(err) => {
error!( error!(
context, context,
0, "mimefactory: failed to load mime_in_reply_to: {:?}", err "mimefactory: failed to load mime_in_reply_to: {:?}", err
); );
} }
} }
@@ -587,7 +587,6 @@ pub unsafe fn dc_mimefactory_render(factory: &mut dc_mimefactory_t) -> libc::c_i
if 0 != msg.param.get_int(Param::Arg2).unwrap_or_default() & 0x1 { if 0 != msg.param.get_int(Param::Arg2).unwrap_or_default() & 0x1 {
info!( info!(
msg.context, msg.context,
0,
"sending secure-join message \'{}\' >>>>>>>>>>>>>>>>>>>>>>>>>", "sending secure-join message \'{}\' >>>>>>>>>>>>>>>>>>>>>>>>>",
"vg-member-added", "vg-member-added",
); );
@@ -656,7 +655,6 @@ pub unsafe fn dc_mimefactory_render(factory: &mut dc_mimefactory_t) -> libc::c_i
if strlen(step) > 0 { if strlen(step) > 0 {
info!( info!(
msg.context, msg.context,
0,
"sending secure-join message \'{}\' >>>>>>>>>>>>>>>>>>>>>>>>>", "sending secure-join message \'{}\' >>>>>>>>>>>>>>>>>>>>>>>>>",
as_str(step), as_str(step),
); );
@@ -726,7 +724,7 @@ pub unsafe fn dc_mimefactory_render(factory: &mut dc_mimefactory_t) -> libc::c_i
} }
} }
if let Some(grpimage) = grpimage { if let Some(grpimage) = grpimage {
info!(factory.context, 0, "setting group image '{}'", grpimage); info!(factory.context, "setting group image '{}'", grpimage);
let mut meta = dc_msg_new_untyped(factory.context); let mut meta = dc_msg_new_untyped(factory.context);
meta.type_0 = Viewtype::Image; meta.type_0 = Viewtype::Image;
meta.param.set(Param::File, grpimage); meta.param.set(Param::File, grpimage);

View File

@@ -132,15 +132,9 @@ pub unsafe fn dc_mimeparser_parse<'a>(context: &'a Context, body: &[u8]) -> dc_m
dc_mimeparser_parse_mime_recursive(mimeparser_ref, mimeparser_ref.mimeroot); dc_mimeparser_parse_mime_recursive(mimeparser_ref, mimeparser_ref.mimeroot);
let field: *mut mailimf_field = dc_mimeparser_lookup_field(&mimeparser, "Subject"); let field: *mut mailimf_field = dc_mimeparser_lookup_field(&mimeparser, "Subject");
if !field.is_null() && (*field).fld_type == MAILIMF_FIELD_SUBJECT as libc::c_int { if !field.is_null() && (*field).fld_type == MAILIMF_FIELD_SUBJECT as libc::c_int {
let decoded = dc_decode_header_words((*(*field).fld_data.fld_subject).sbj_value); let subj = (*(*field).fld_data.fld_subject).sbj_value;
if decoded.is_null()
/* XXX: can it happen? */ mimeparser.subject = as_opt_str(subj).map(dc_decode_header_words_safe);
{
mimeparser.subject = None
} else {
mimeparser.subject = Some(to_string_lossy(decoded));
free(decoded.cast());
}
} }
if !dc_mimeparser_lookup_optional_field(&mut mimeparser, "Chat-Version").is_null() { if !dc_mimeparser_lookup_optional_field(&mut mimeparser, "Chat-Version").is_null() {
mimeparser.is_send_by_messenger = true mimeparser.is_send_by_messenger = true
@@ -460,7 +454,7 @@ unsafe fn dc_mimeparser_parse_mime_recursive(
{ {
info!( info!(
mimeparser.context, mimeparser.context,
0, "Protected headers found in text/rfc822-headers attachment: Will be ignored.", "Protected headers found in text/rfc822-headers attachment: Will be ignored.",
); );
return 0i32; return 0i32;
} }
@@ -474,7 +468,7 @@ unsafe fn dc_mimeparser_parse_mime_recursive(
) != MAILIMF_NO_ERROR as libc::c_int ) != MAILIMF_NO_ERROR as libc::c_int
|| mimeparser.header_protected.is_null() || mimeparser.header_protected.is_null()
{ {
warn!(mimeparser.context, 0, "Protected headers parsing error.",); warn!(mimeparser.context, "Protected headers parsing error.",);
} else { } else {
hash_header( hash_header(
&mut mimeparser.header, &mut mimeparser.header,
@@ -485,7 +479,6 @@ unsafe fn dc_mimeparser_parse_mime_recursive(
} else { } else {
info!( info!(
mimeparser.context, mimeparser.context,
0,
"Protected headers found in MIME header: Will be ignored as we already found an outer one." "Protected headers found in MIME header: Will be ignored as we already found an outer one."
); );
} }
@@ -667,7 +660,6 @@ unsafe fn dc_mimeparser_parse_mime_recursive(
if plain_cnt == 1i32 && html_cnt == 1i32 { if plain_cnt == 1i32 && html_cnt == 1i32 {
warn!( warn!(
mimeparser.context, mimeparser.context,
0i32,
"HACK: multipart/mixed message found with PLAIN and HTML, we\'ll skip the HTML part as this seems to be unwanted." "HACK: multipart/mixed message found with PLAIN and HTML, we\'ll skip the HTML part as this seems to be unwanted."
); );
skip_part = html_part skip_part = html_part
@@ -1072,7 +1064,7 @@ unsafe fn dc_mimeparser_add_single_part_if_known(
); );
let (res, _, _) = encoding.decode(data); let (res, _, _) = encoding.decode(data);
info!(mimeparser.context, 0, "decoded message: '{}'", res); info!(mimeparser.context, "decoded message: '{}'", res);
if res.is_empty() { if res.is_empty() {
/* no error - but nothing to add */ /* no error - but nothing to add */
ok_to_continue = false; ok_to_continue = false;
@@ -1085,7 +1077,6 @@ unsafe fn dc_mimeparser_add_single_part_if_known(
} else { } else {
warn!( warn!(
mimeparser.context, mimeparser.context,
0,
"Cannot convert {} bytes from \"{}\" to \"utf-8\".", "Cannot convert {} bytes from \"{}\" to \"utf-8\".",
decoded_data_bytes as libc::c_int, decoded_data_bytes as libc::c_int,
as_str(charset), as_str(charset),

View File

@@ -41,7 +41,6 @@ pub unsafe fn dc_receive_imf(
) { ) {
info!( info!(
context, context,
0,
"Receiving message {}/{}...", "Receiving message {}/{}...",
if !server_folder.as_ref().is_empty() { if !server_folder.as_ref().is_empty() {
server_folder.as_ref() server_folder.as_ref()
@@ -61,7 +60,7 @@ pub unsafe fn dc_receive_imf(
if mime_parser.header.is_empty() { if mime_parser.header.is_empty() {
// Error - even adding an empty record won't help as we do not know the message ID // Error - even adding an empty record won't help as we do not know the message ID
info!(context, 0, "No header."); info!(context, "No header.");
return; return;
} }
@@ -189,7 +188,7 @@ pub unsafe fn dc_receive_imf(
&mut created_db_entries, &mut created_db_entries,
&mut create_event_to_send, &mut create_event_to_send,
) { ) {
info!(context, 0, "{}", err); info!(context, "{}", err);
cleanup( cleanup(
context, context,
@@ -243,7 +242,6 @@ pub unsafe fn dc_receive_imf(
info!( info!(
context, context,
0,
"received message {} has Message-Id: {}", "received message {} has Message-Id: {}",
server_uid, server_uid,
to_string(rfc724_mid) to_string(rfc724_mid)
@@ -447,10 +445,7 @@ unsafe fn add_parts(
// check if the message belongs to a mailing list // check if the message belongs to a mailing list
if dc_mimeparser_is_mailinglist_message(mime_parser) { if dc_mimeparser_is_mailinglist_message(mime_parser) {
*chat_id = 3; *chat_id = 3;
info!( info!(context, "Message belongs to a mailing list and is ignored.",);
context,
0, "Message belongs to a mailing list and is ignored.",
);
} }
} }
@@ -482,7 +477,7 @@ unsafe fn add_parts(
Contact::scaleup_origin_by_id(context, *from_id, Origin::IncomingReplyTo); Contact::scaleup_origin_by_id(context, *from_id, Origin::IncomingReplyTo);
info!( info!(
context, context,
0, "Message is a reply to a known message, mark sender as known.", "Message is a reply to a known message, mark sender as known.",
); );
if !incoming_origin.is_verified() { if !incoming_origin.is_verified() {
*incoming_origin = Origin::IncomingReplyTo; *incoming_origin = Origin::IncomingReplyTo;
@@ -642,7 +637,8 @@ unsafe fn add_parts(
} }
} }
if part.type_0 == Viewtype::Text { if part.type_0 == Viewtype::Text {
let msg_raw = CString::yolo(part.msg_raw.as_ref().cloned().unwrap_or_default()); let msg_raw =
CString::yolo(part.msg_raw.as_ref().cloned().unwrap_or_default());
let subject_c = CString::yolo( let subject_c = CString::yolo(
mime_parser mime_parser
.subject .subject
@@ -723,7 +719,7 @@ unsafe fn add_parts(
info!( info!(
context, context,
0, "Message has {} parts and is assigned to chat #{}.", icnt, *chat_id, "Message has {} parts and is assigned to chat #{}.", icnt, *chat_id,
); );
// check event to send // check event to send
@@ -961,7 +957,7 @@ fn save_locations(
insert_msg_id, insert_msg_id,
newest_location_id, newest_location_id,
) { ) {
error!(context, 0, "Failed to set msg_location_id: {:?}", err); error!(context, "Failed to set msg_location_id: {:?}", err);
} }
} }
send_event = true; send_event = true;
@@ -1316,7 +1312,7 @@ unsafe fn create_or_lookup_group(
if !X_MrAddToGrp.is_null() || !X_MrRemoveFromGrp.is_null() { if !X_MrAddToGrp.is_null() || !X_MrRemoveFromGrp.is_null() {
recreate_member_list = 1; recreate_member_list = 1;
} else if 0 != X_MrGrpNameChanged && !grpname.is_null() && strlen(grpname) < 200 { } else if 0 != X_MrGrpNameChanged && !grpname.is_null() && strlen(grpname) < 200 {
info!(context, 0, "updating grpname for chat {}", chat_id); info!(context, "updating grpname for chat {}", chat_id);
if sql::execute( if sql::execute(
context, context,
&context.sql, &context.sql,
@@ -1331,7 +1327,7 @@ unsafe fn create_or_lookup_group(
if !X_MrGrpImageChanged.is_empty() { if !X_MrGrpImageChanged.is_empty() {
info!( info!(
context, context,
0, "grp-image-change {} chat {}", X_MrGrpImageChanged, chat_id "grp-image-change {} chat {}", X_MrGrpImageChanged, chat_id
); );
let mut changed = false; let mut changed = false;
let mut grpimage = "".to_string(); let mut grpimage = "".to_string();
@@ -1345,13 +1341,13 @@ unsafe fn create_or_lookup_group(
.get(Param::File) .get(Param::File)
.map(|s| s.to_string()) .map(|s| s.to_string())
.unwrap_or_else(|| "".to_string()); .unwrap_or_else(|| "".to_string());
info!(context, 0, "found image {:?}", grpimage); info!(context, "found image {:?}", grpimage);
changed = true; changed = true;
} }
} }
} }
if changed { if changed {
info!(context, 0, "New group image set to '{}'.", grpimage); info!(context, "New group image set to '{}'.", grpimage);
if let Ok(mut chat) = Chat::load_from_db(context, chat_id) { if let Ok(mut chat) = Chat::load_from_db(context, chat_id) {
if grpimage.is_empty() { if grpimage.is_empty() {
chat.param.remove(Param::ProfileImage); chat.param.remove(Param::ProfileImage);
@@ -1740,7 +1736,7 @@ unsafe fn check_verified_properties(
) -> libc::c_int { ) -> libc::c_int {
let verify_fail = |reason: String| { let verify_fail = |reason: String| {
*failure_reason = format!("{}. See \"Info\" for details.", reason).strdup(); *failure_reason = format!("{}. See \"Info\" for details.", reason).strdup();
warn!(context, 0, "{}", reason); warn!(context, "{}", reason);
}; };
let contact = match Contact::load_from_db(context, from_id) { let contact = match Contact::load_from_db(context, from_id) {
@@ -1811,13 +1807,7 @@ unsafe fn check_verified_properties(
|| peerstate.verified_key_fingerprint != peerstate.public_key_fingerprint || peerstate.verified_key_fingerprint != peerstate.public_key_fingerprint
&& peerstate.verified_key_fingerprint != peerstate.gossip_key_fingerprint && peerstate.verified_key_fingerprint != peerstate.gossip_key_fingerprint
{ {
info!( info!(context, "{} has verfied {}.", contact.get_addr(), to_addr,);
context,
0,
"{} has verfied {}.",
contact.get_addr(),
to_addr,
);
let fp = peerstate.gossip_key_fingerprint.clone(); let fp = peerstate.gossip_key_fingerprint.clone();
if let Some(fp) = fp { if let Some(fp) = fp {
peerstate.set_verified(0, &fp, 2); peerstate.set_verified(0, &fp, 2);

View File

@@ -12,6 +12,20 @@ use crate::dc_tools::*;
use crate::types::*; use crate::types::*;
use crate::x::*; use crate::x::*;
/**
* Encode non-ascii-strings as `=?UTF-8?Q?Bj=c3=b6rn_Petersen?=`.
* Belongs to RFC 2047: https://tools.ietf.org/html/rfc2047
*
* We do not fold at position 72; this would result in empty words as `=?utf-8?Q??=` which are correct,
* but cannot be displayed by some mail programs (eg. Android Stock Mail).
* however, this is not needed, as long as _one_ word is not longer than 72 characters.
* _if_ it is, the display may get weird. This affects the subject only.
* the best solution wor all this would be if libetpan encodes the line as only libetpan knowns when a header line is full.
*
* @param to_encode Null-terminated UTF-8-string to encode.
* @return Returns the encoded string which must be free()'d when no longed needed.
* On errors, NULL is returned.
*/
pub unsafe fn dc_encode_header_words(to_encode: *const libc::c_char) -> *mut libc::c_char { pub unsafe fn dc_encode_header_words(to_encode: *const libc::c_char) -> *mut libc::c_char {
let mut ok_to_continue = true; let mut ok_to_continue = true;
let mut ret_str: *mut libc::c_char = ptr::null_mut(); let mut ret_str: *mut libc::c_char = ptr::null_mut();
@@ -224,6 +238,31 @@ pub unsafe fn dc_decode_header_words(in_0: *const libc::c_char) -> *mut libc::c_
out out
} }
pub fn dc_decode_header_words_safe(input: &str) -> String {
static FROM_ENCODING: &[u8] = b"iso-8859-1\x00";
static TO_ENCODING: &[u8] = b"utf-8\x00";
let mut out = ptr::null_mut();
let mut cur_token = 0;
let input_c = CString::yolo(input);
unsafe {
let r = mailmime_encoded_phrase_parse(
FROM_ENCODING.as_ptr().cast(),
input_c.as_ptr(),
input.len(),
&mut cur_token,
TO_ENCODING.as_ptr().cast(),
&mut out,
);
if r as u32 != MAILIMF_NO_ERROR || out.is_null() {
input.to_string()
} else {
let res = to_string(out);
free(out.cast());
res
}
}
}
pub fn dc_needs_ext_header(to_check: impl AsRef<str>) -> bool { pub fn dc_needs_ext_header(to_check: impl AsRef<str>) -> bool {
let to_check = to_check.as_ref(); let to_check = to_check.as_ref();

View File

@@ -843,16 +843,19 @@ pub fn dc_get_filebytes(context: &Context, path: impl AsRef<std::path::Path>) ->
pub fn dc_delete_file(context: &Context, path: impl AsRef<std::path::Path>) -> bool { pub fn dc_delete_file(context: &Context, path: impl AsRef<std::path::Path>) -> bool {
let path_abs = dc_get_abs_path_safe(context, &path); let path_abs = dc_get_abs_path_safe(context, &path);
let res = if path_abs.is_file() { if !path_abs.is_file() {
fs::remove_file(path_abs) warn!(
} else { context,
fs::remove_dir_all(path_abs) "Will not delete directory \"{}\".",
}; path.as_ref().display()
);
return false;
}
match res { match fs::remove_file(path_abs) {
Ok(_) => true, Ok(_) => true,
Err(_err) => { Err(_err) => {
warn!(context, 0, "Cannot delete \"{}\".", path.as_ref().display()); warn!(context, "Cannot delete \"{}\".", path.as_ref().display());
false false
} }
} }
@@ -870,7 +873,6 @@ pub fn dc_copy_file(
Err(_) => { Err(_) => {
error!( error!(
context, context,
0,
"Cannot copy \"{}\" to \"{}\".", "Cannot copy \"{}\" to \"{}\".",
src.as_ref().display(), src.as_ref().display(),
dest.as_ref().display(), dest.as_ref().display(),
@@ -888,7 +890,6 @@ pub fn dc_create_folder(context: &Context, path: impl AsRef<std::path::Path>) ->
Err(_err) => { Err(_err) => {
warn!( warn!(
context, context,
0,
"Cannot create directory \"{}\".", "Cannot create directory \"{}\".",
path.as_ref().display(), path.as_ref().display(),
); );
@@ -921,7 +922,6 @@ pub fn dc_write_file_safe<P: AsRef<std::path::Path>>(
if let Err(_err) = fs::write(&path_abs, buf) { if let Err(_err) = fs::write(&path_abs, buf) {
warn!( warn!(
context, context,
0,
"Cannot write {} bytes to \"{}\".", "Cannot write {} bytes to \"{}\".",
buf.len(), buf.len(),
path.as_ref().display(), path.as_ref().display(),
@@ -959,7 +959,6 @@ pub fn dc_read_file_safe<P: AsRef<std::path::Path>>(context: &Context, path: P)
Err(_err) => { Err(_err) => {
warn!( warn!(
context, context,
0,
"Cannot read \"{}\" or file is empty.", "Cannot read \"{}\" or file is empty.",
path.as_ref().display() path.as_ref().display()
); );

View File

@@ -91,7 +91,7 @@ impl E2eeHelper {
if let Some(addr) = addr { if let Some(addr) = addr {
let pubkey_ret = load_or_generate_self_public_key(context, &addr).map_err(|err| { let pubkey_ret = load_or_generate_self_public_key(context, &addr).map_err(|err| {
error!(context, 0, "Failed to load public key: {}", err); error!(context, "Failed to load public key: {}", err);
err err
}); });
if let Ok(public_key) = pubkey_ret { if let Ok(public_key) = pubkey_ret {
@@ -113,7 +113,7 @@ impl E2eeHelper {
let peerstate = peerstate.unwrap(); let peerstate = peerstate.unwrap();
info!( info!(
context, context,
0, "dc_e2ee_encrypt {} has peerstate", recipient_addr "dc_e2ee_encrypt {} has peerstate", recipient_addr
); );
if let Some(key) = peerstate.peek_key(min_verified as usize) { if let Some(key) = peerstate.peek_key(min_verified as usize) {
keyring.add_owned(key.clone()); keyring.add_owned(key.clone());
@@ -122,7 +122,6 @@ impl E2eeHelper {
} else { } else {
info!( info!(
context, context,
0,
"dc_e2ee_encrypt {} HAS NO peerstate {}", "dc_e2ee_encrypt {} HAS NO peerstate {}",
recipient_addr, recipient_addr,
peerstate.is_some() peerstate.is_some()
@@ -608,7 +607,7 @@ fn load_or_generate_self_public_key(context: &Context, self_addr: impl AsRef<str
let start = std::time::Instant::now(); let start = std::time::Instant::now();
info!( info!(
context, context,
0, "Generating keypair with {} bits, e={} ...", 2048, 65537, "Generating keypair with {} bits, e={} ...", 2048, 65537,
); );
match dc_pgp_create_keypair(&self_addr) { match dc_pgp_create_keypair(&self_addr) {
Some((public_key, private_key)) => { Some((public_key, private_key)) => {
@@ -623,7 +622,6 @@ fn load_or_generate_self_public_key(context: &Context, self_addr: impl AsRef<str
true => { true => {
info!( info!(
context, context,
0,
"Keypair generated in {:.3}s.", "Keypair generated in {:.3}s.",
start.elapsed().as_secs() start.elapsed().as_secs()
); );
@@ -691,7 +689,6 @@ unsafe fn update_gossip_peerstates(
} else { } else {
info!( info!(
context, context,
0,
"Ignoring gossipped \"{}\" as the address is not in To/Cc list.", "Ignoring gossipped \"{}\" as the address is not in To/Cc list.",
&header.addr, &header.addr,
); );

View File

@@ -472,12 +472,9 @@ impl Imap {
} }
fn unsetup_handle(&self, context: &Context) { fn unsetup_handle(&self, context: &Context) {
info!(context, 0, "IMAP unsetup_handle starts"); info!(context, "IMAP unsetup_handle starts");
info!( info!(context, "IMAP unsetup_handle step 1 (closing down stream).");
context,
0, "IMAP unsetup_handle step 1 (closing down stream)."
);
let stream = self.stream.write().unwrap().take(); let stream = self.stream.write().unwrap().take();
if let Some(stream) = stream { if let Some(stream) = stream {
if let Err(err) = stream.shutdown(net::Shutdown::Both) { if let Err(err) = stream.shutdown(net::Shutdown::Both) {
@@ -487,7 +484,7 @@ impl Imap {
info!( info!(
context, context,
0, "IMAP unsetup_handle step 2 (acquiring session.lock)" "IMAP unsetup_handle step 2 (acquiring session.lock)"
); );
if let Some(mut session) = self.session.lock().unwrap().take() { if let Some(mut session) = self.session.lock().unwrap().take() {
if let Err(err) = session.close() { if let Err(err) = session.close() {
@@ -495,10 +492,10 @@ impl Imap {
} }
} }
info!(context, 0, "IMAP unsetup_handle step 3 (clearing config)."); info!(context, "IMAP unsetup_handle step 3 (clearing config).");
self.config.write().unwrap().selected_folder = None; self.config.write().unwrap().selected_folder = None;
self.config.write().unwrap().selected_mailbox = None; self.config.write().unwrap().selected_mailbox = None;
info!(context, 0, "IMAP unsetup_handle step 4 (disconnected).",); info!(context, "IMAP unsetup_handle step 4 (disconnected).",);
} }
fn free_connect_params(&self) { fn free_connect_params(&self) {
@@ -551,7 +548,7 @@ impl Imap {
Some(ref mut session) => match session.capabilities() { Some(ref mut session) => match session.capabilities() {
Ok(caps) => { Ok(caps) => {
if !context.sql.is_open() { if !context.sql.is_open() {
warn!(context, 0, "IMAP-LOGIN as {} ok but ABORTING", lp.mail_user,); warn!(context, "IMAP-LOGIN as {} ok but ABORTING", lp.mail_user,);
(true, false, false) (true, false, false)
} else { } else {
let can_idle = caps.has_str("IDLE"); let can_idle = caps.has_str("IDLE");
@@ -571,7 +568,7 @@ impl Imap {
} }
} }
Err(err) => { Err(err) => {
info!(context, 0, "CAPABILITY command error: {}", err); info!(context, "CAPABILITY command error: {}", err);
(true, false, false) (true, false, false)
} }
}, },
@@ -647,7 +644,7 @@ impl Imap {
// deselect existing folder, if needed (it's also done implicitly by SELECT, however, without EXPUNGE then) // deselect existing folder, if needed (it's also done implicitly by SELECT, however, without EXPUNGE then)
if self.config.read().unwrap().selected_folder_needs_expunge { if self.config.read().unwrap().selected_folder_needs_expunge {
if let Some(ref folder) = self.config.read().unwrap().selected_folder { if let Some(ref folder) = self.config.read().unwrap().selected_folder {
info!(context, 0, "Expunge messages in \"{}\".", folder); info!(context, "Expunge messages in \"{}\".", folder);
// A CLOSE-SELECT is considerably faster than an EXPUNGE-SELECT, see // A CLOSE-SELECT is considerably faster than an EXPUNGE-SELECT, see
// https://tools.ietf.org/html/rfc3501#section-6.4.2 // https://tools.ietf.org/html/rfc3501#section-6.4.2
@@ -677,7 +674,6 @@ impl Imap {
Err(err) => { Err(err) => {
info!( info!(
context, context,
0,
"Cannot select folder: {}; {:?}.", "Cannot select folder: {}; {:?}.",
folder.as_ref(), folder.as_ref(),
err err
@@ -714,7 +710,6 @@ impl Imap {
if !self.is_connected() { if !self.is_connected() {
info!( info!(
context, context,
0,
"Cannot fetch from \"{}\" - not connected.", "Cannot fetch from \"{}\" - not connected.",
folder.as_ref() folder.as_ref()
); );
@@ -725,7 +720,6 @@ impl Imap {
if self.select_folder(context, Some(&folder)) == 0 { if self.select_folder(context, Some(&folder)) == 0 {
info!( info!(
context, context,
0,
"Cannot select folder \"{}\" for fetching.", "Cannot select folder \"{}\" for fetching.",
folder.as_ref() folder.as_ref()
); );
@@ -742,7 +736,6 @@ impl Imap {
if mailbox.uid_validity.is_none() { if mailbox.uid_validity.is_none() {
error!( error!(
context, context,
0,
"Cannot get UIDVALIDITY for folder \"{}\".", "Cannot get UIDVALIDITY for folder \"{}\".",
folder.as_ref(), folder.as_ref(),
); );
@@ -754,7 +747,7 @@ impl Imap {
// first time this folder is selected or UIDVALIDITY has changed, init lastseenuid and save it to config // first time this folder is selected or UIDVALIDITY has changed, init lastseenuid and save it to config
if mailbox.exists == 0 { if mailbox.exists == 0 {
info!(context, 0, "Folder \"{}\" is empty.", folder.as_ref()); info!(context, "Folder \"{}\" is empty.", folder.as_ref());
// set lastseenuid=0 for empty folders. // set lastseenuid=0 for empty folders.
// id we do not do this here, we'll miss the first message // id we do not do this here, we'll miss the first message
@@ -773,7 +766,6 @@ impl Imap {
self.should_reconnect.store(true, Ordering::Relaxed); self.should_reconnect.store(true, Ordering::Relaxed);
info!( info!(
context, context,
0,
"No result returned for folder \"{}\".", "No result returned for folder \"{}\".",
folder.as_ref() folder.as_ref()
); );
@@ -796,7 +788,6 @@ impl Imap {
self.set_config_last_seen_uid(context, &folder, uid_validity, last_seen_uid); self.set_config_last_seen_uid(context, &folder, uid_validity, last_seen_uid);
info!( info!(
context, context,
0,
"lastseenuid initialized to {} for {}@{}", "lastseenuid initialized to {} for {}@{}",
last_seen_uid, last_seen_uid,
folder.as_ref(), folder.as_ref(),
@@ -815,7 +806,7 @@ impl Imap {
match session.uid_fetch(set, PREFETCH_FLAGS) { match session.uid_fetch(set, PREFETCH_FLAGS) {
Ok(list) => list, Ok(list) => list,
Err(err) => { Err(err) => {
warn!(context, 0, "failed to fetch uids: {}", err); warn!(context, "failed to fetch uids: {}", err);
return 0; return 0;
} }
} }
@@ -843,7 +834,6 @@ impl Imap {
if self.fetch_single_msg(context, &folder, cur_uid) == 0 { if self.fetch_single_msg(context, &folder, cur_uid) == 0 {
info!( info!(
context, context,
0,
"Read error for message {} from \"{}\", trying over later.", "Read error for message {} from \"{}\", trying over later.",
message_id, message_id,
folder.as_ref() folder.as_ref()
@@ -855,7 +845,6 @@ impl Imap {
// check failed // check failed
info!( info!(
context, context,
0,
"Skipping message {} from \"{}\" by precheck.", "Skipping message {} from \"{}\" by precheck.",
message_id, message_id,
folder.as_ref(), folder.as_ref(),
@@ -876,7 +865,6 @@ impl Imap {
if read_errors > 0 { if read_errors > 0 {
warn!( warn!(
context, context,
0,
"{} mails read from \"{}\" with {} errors.", "{} mails read from \"{}\" with {} errors.",
read_cnt, read_cnt,
folder.as_ref(), folder.as_ref(),
@@ -885,7 +873,6 @@ impl Imap {
} else { } else {
info!( info!(
context, context,
0,
"{} mails read from \"{}\".", "{} mails read from \"{}\".",
read_cnt, read_cnt,
folder.as_ref() folder.as_ref()
@@ -930,7 +917,6 @@ impl Imap {
self.should_reconnect.store(true, Ordering::Relaxed); self.should_reconnect.store(true, Ordering::Relaxed);
warn!( warn!(
context, context,
0,
"Error on fetching message #{} from folder \"{}\"; retry={}; error={}.", "Error on fetching message #{} from folder \"{}\"; retry={}; error={}.",
server_uid, server_uid,
folder.as_ref(), folder.as_ref(),
@@ -947,7 +933,6 @@ impl Imap {
if msgs.is_empty() { if msgs.is_empty() {
warn!( warn!(
context, context,
0,
"Message #{} does not exist in folder \"{}\".", "Message #{} does not exist in folder \"{}\".",
server_uid, server_uid,
folder.as_ref() folder.as_ref()
@@ -1001,7 +986,7 @@ impl Imap {
let watch_folder = self.config.read().unwrap().watch_folder.clone(); let watch_folder = self.config.read().unwrap().watch_folder.clone();
if self.select_folder(context, watch_folder.as_ref()) == 0 { if self.select_folder(context, watch_folder.as_ref()) == 0 {
warn!(context, 0, "IMAP-IDLE not setup.",); warn!(context, "IMAP-IDLE not setup.",);
return self.fake_idle(context); return self.fake_idle(context);
} }
@@ -1011,7 +996,7 @@ impl Imap {
let (sender, receiver) = std::sync::mpsc::channel(); let (sender, receiver) = std::sync::mpsc::channel();
let v = self.watch.clone(); let v = self.watch.clone();
info!(context, 0, "IMAP-IDLE SPAWNING"); info!(context, "IMAP-IDLE SPAWNING");
std::thread::spawn(move || { std::thread::spawn(move || {
let &(ref lock, ref cvar) = &*v; let &(ref lock, ref cvar) = &*v;
if let Some(ref mut session) = &mut *session.lock().unwrap() { if let Some(ref mut session) = &mut *session.lock().unwrap() {
@@ -1046,18 +1031,15 @@ impl Imap {
let handle_res = |res| match res { let handle_res = |res| match res {
Ok(()) => { Ok(()) => {
info!(context, 0, "IMAP-IDLE has data."); info!(context, "IMAP-IDLE has data.");
} }
Err(err) => match err { Err(err) => match err {
imap::error::Error::ConnectionLost => { imap::error::Error::ConnectionLost => {
info!( info!(context, "IMAP-IDLE wait cancelled, we will reconnect soon.");
context,
0, "IMAP-IDLE wait cancelled, we will reconnect soon."
);
self.should_reconnect.store(true, Ordering::Relaxed); self.should_reconnect.store(true, Ordering::Relaxed);
} }
_ => { _ => {
warn!(context, 0, "IMAP-IDLE returns unknown value: {}", err); warn!(context, "IMAP-IDLE returns unknown value: {}", err);
} }
}, },
}; };
@@ -1073,7 +1055,7 @@ impl Imap {
if let Ok(res) = worker.as_ref().unwrap().try_recv() { if let Ok(res) = worker.as_ref().unwrap().try_recv() {
handle_res(res); handle_res(res);
} else { } else {
info!(context, 0, "IMAP-IDLE interrupted"); info!(context, "IMAP-IDLE interrupted");
} }
drop(worker.take()); drop(worker.take());
@@ -1091,7 +1073,7 @@ impl Imap {
let fake_idle_start_time = SystemTime::now(); let fake_idle_start_time = SystemTime::now();
let mut wait_long = false; let mut wait_long = false;
info!(context, 0, "IMAP-fake-IDLEing..."); info!(context, "IMAP-fake-IDLEing...");
let mut do_fake_idle = true; let mut do_fake_idle = true;
while do_fake_idle { while do_fake_idle {
@@ -1167,7 +1149,6 @@ impl Imap {
} else if folder.as_ref() == dest_folder.as_ref() { } else if folder.as_ref() == dest_folder.as_ref() {
info!( info!(
context, context,
0,
"Skip moving message; message {}/{} is already in {}...", "Skip moving message; message {}/{} is already in {}...",
folder.as_ref(), folder.as_ref(),
uid, uid,
@@ -1178,7 +1159,6 @@ impl Imap {
} else { } else {
info!( info!(
context, context,
0,
"Moving message {}/{} to {}...", "Moving message {}/{} to {}...",
folder.as_ref(), folder.as_ref(),
uid, uid,
@@ -1188,7 +1168,6 @@ impl Imap {
if self.select_folder(context, Some(folder.as_ref())) == 0 { if self.select_folder(context, Some(folder.as_ref())) == 0 {
warn!( warn!(
context, context,
0,
"Cannot select folder {} for moving message.", "Cannot select folder {} for moving message.",
folder.as_ref() folder.as_ref()
); );
@@ -1202,7 +1181,6 @@ impl Imap {
Err(err) => { Err(err) => {
info!( info!(
context, context,
0,
"Cannot move message, fallback to COPY/DELETE {}/{} to {}: {}", "Cannot move message, fallback to COPY/DELETE {}/{} to {}: {}",
folder.as_ref(), folder.as_ref(),
uid, uid,
@@ -1223,7 +1201,7 @@ impl Imap {
Ok(_) => true, Ok(_) => true,
Err(err) => { Err(err) => {
eprintln!("error copy: {:?}", err); eprintln!("error copy: {:?}", err);
info!(context, 0, "Cannot copy message.",); info!(context, "Cannot copy message.",);
false false
} }
@@ -1234,7 +1212,7 @@ impl Imap {
if copied { if copied {
if self.add_flag(context, uid, "\\Deleted") == 0 { if self.add_flag(context, uid, "\\Deleted") == 0 {
warn!(context, 0, "Cannot mark message as \"Deleted\".",); warn!(context, "Cannot mark message as \"Deleted\".",);
} }
self.config.write().unwrap().selected_folder_needs_expunge = true; self.config.write().unwrap().selected_folder_needs_expunge = true;
res = DC_SUCCESS; res = DC_SUCCESS;
@@ -1271,7 +1249,7 @@ impl Imap {
Err(err) => { Err(err) => {
warn!( warn!(
context, context,
0, "IMAP failed to store: ({}, {}) {:?}", set, query, err "IMAP failed to store: ({}, {}) {:?}", set, query, err
); );
} }
} }
@@ -1294,7 +1272,6 @@ impl Imap {
} else if self.is_connected() { } else if self.is_connected() {
info!( info!(
context, context,
0,
"Marking message {}/{} as seen...", "Marking message {}/{} as seen...",
folder.as_ref(), folder.as_ref(),
uid, uid,
@@ -1303,12 +1280,11 @@ impl Imap {
if self.select_folder(context, Some(folder.as_ref())) == 0 { if self.select_folder(context, Some(folder.as_ref())) == 0 {
warn!( warn!(
context, context,
0,
"Cannot select folder {} for setting SEEN flag.", "Cannot select folder {} for setting SEEN flag.",
folder.as_ref(), folder.as_ref(),
); );
} else if self.add_flag(context, uid, "\\Seen") == 0 { } else if self.add_flag(context, uid, "\\Seen") == 0 {
warn!(context, 0, "Cannot mark message as seen.",); warn!(context, "Cannot mark message as seen.",);
} else { } else {
res = DC_SUCCESS res = DC_SUCCESS
} }
@@ -1335,7 +1311,6 @@ impl Imap {
} else if self.is_connected() { } else if self.is_connected() {
info!( info!(
context, context,
0,
"Marking message {}/{} as $MDNSent...", "Marking message {}/{} as $MDNSent...",
folder.as_ref(), folder.as_ref(),
uid, uid,
@@ -1344,7 +1319,6 @@ impl Imap {
if self.select_folder(context, Some(folder.as_ref())) == 0 { if self.select_folder(context, Some(folder.as_ref())) == 0 {
warn!( warn!(
context, context,
0,
"Cannot select folder {} for setting $MDNSent flag.", "Cannot select folder {} for setting $MDNSent flag.",
folder.as_ref() folder.as_ref()
); );
@@ -1411,16 +1385,16 @@ impl Imap {
}; };
if res == DC_SUCCESS { if res == DC_SUCCESS {
info!(context, 0, "$MDNSent just set and MDN will be sent."); info!(context, "$MDNSent just set and MDN will be sent.");
} else { } else {
info!(context, 0, "$MDNSent already set and MDN already sent."); info!(context, "$MDNSent already set and MDN already sent.");
} }
} }
} else { } else {
res = DC_SUCCESS; res = DC_SUCCESS;
info!( info!(
context, context,
0, "Cannot store $MDNSent flags, risk sending duplicate MDN.", "Cannot store $MDNSent flags, risk sending duplicate MDN.",
); );
} }
} }
@@ -1451,7 +1425,6 @@ impl Imap {
} else { } else {
info!( info!(
context, context,
0,
"Marking message \"{}\", {}/{} for deletion...", "Marking message \"{}\", {}/{} for deletion...",
message_id.as_ref(), message_id.as_ref(),
folder.as_ref(), folder.as_ref(),
@@ -1461,7 +1434,6 @@ impl Imap {
if self.select_folder(context, Some(&folder)) == 0 { if self.select_folder(context, Some(&folder)) == 0 {
warn!( warn!(
context, context,
0,
"Cannot select folder {} for deleting message.", "Cannot select folder {} for deleting message.",
folder.as_ref() folder.as_ref()
); );
@@ -1482,7 +1454,6 @@ impl Imap {
{ {
warn!( warn!(
context, context,
0,
"Cannot delete on IMAP, {}/{} does not match {}.", "Cannot delete on IMAP, {}/{} does not match {}.",
folder.as_ref(), folder.as_ref(),
server_uid, server_uid,
@@ -1496,7 +1467,6 @@ impl Imap {
warn!( warn!(
context, context,
0,
"Cannot delete on IMAP, {}/{} not found.", "Cannot delete on IMAP, {}/{} not found.",
folder.as_ref(), folder.as_ref(),
server_uid, server_uid,
@@ -1508,7 +1478,7 @@ impl Imap {
// mark the message for deletion // mark the message for deletion
if self.add_flag(context, *server_uid, "\\Deleted") == 0 { if self.add_flag(context, *server_uid, "\\Deleted") == 0 {
warn!(context, 0, "Cannot mark message as \"Deleted\"."); warn!(context, "Cannot mark message as \"Deleted\".");
} else { } else {
self.config.write().unwrap().selected_folder_needs_expunge = true; self.config.write().unwrap().selected_folder_needs_expunge = true;
success = true success = true
@@ -1528,7 +1498,7 @@ impl Imap {
return; return;
} }
info!(context, 0, "Configuring IMAP-folders."); info!(context, "Configuring IMAP-folders.");
let folders = self.list_folders(context).unwrap(); let folders = self.list_folders(context).unwrap();
let delimiter = self.config.read().unwrap().imap_delimiter; let delimiter = self.config.read().unwrap().imap_delimiter;
@@ -1547,21 +1517,19 @@ impl Imap {
}); });
if mvbox_folder.is_none() && 0 != (flags as usize & DC_CREATE_MVBOX) { if mvbox_folder.is_none() && 0 != (flags as usize & DC_CREATE_MVBOX) {
info!(context, 0, "Creating MVBOX-folder \"DeltaChat\"...",); info!(context, "Creating MVBOX-folder \"DeltaChat\"...",);
if let Some(ref mut session) = &mut *self.session.lock().unwrap() { if let Some(ref mut session) = &mut *self.session.lock().unwrap() {
match session.create("DeltaChat") { match session.create("DeltaChat") {
Ok(_) => { Ok(_) => {
mvbox_folder = Some("DeltaChat".into()); mvbox_folder = Some("DeltaChat".into());
info!(context, 0, "MVBOX-folder created.",); info!(context, "MVBOX-folder created.",);
} }
Err(err) => { Err(err) => {
warn!( warn!(
context, context,
0, "Cannot create MVBOX-folder, using trying INBOX subfolder. ({})", err
"Cannot create MVBOX-folder, using trying INBOX subfolder. ({})",
err
); );
match session.create(&fallback_folder) { match session.create(&fallback_folder) {
@@ -1569,11 +1537,11 @@ impl Imap {
mvbox_folder = Some(fallback_folder); mvbox_folder = Some(fallback_folder);
info!( info!(
context, context,
0, "MVBOX-folder created as INBOX subfolder. ({})", err "MVBOX-folder created as INBOX subfolder. ({})", err
); );
} }
Err(err) => { Err(err) => {
warn!(context, 0, "Cannot create MVBOX-folder. ({})", err); warn!(context, "Cannot create MVBOX-folder. ({})", err);
} }
} }
} }
@@ -1619,13 +1587,13 @@ impl Imap {
match session.list(Some(""), Some("*")) { match session.list(Some(""), Some("*")) {
Ok(list) => { Ok(list) => {
if list.is_empty() { if list.is_empty() {
warn!(context, 0, "Folder list is empty.",); warn!(context, "Folder list is empty.",);
} }
Some(list) Some(list)
} }
Err(err) => { Err(err) => {
eprintln!("list error: {:?}", err); eprintln!("list error: {:?}", err);
warn!(context, 0, "Cannot get folder list.",); warn!(context, "Cannot get folder list.",);
None None
} }

View File

@@ -159,7 +159,7 @@ impl Job {
if 0 != self.foreign_id && !dc_msg_exists(context, self.foreign_id) { if 0 != self.foreign_id && !dc_msg_exists(context, self.foreign_id) {
warn!( warn!(
context, context,
0, "Message {} for job {} does not exist", self.foreign_id, self.job_id, "Message {} for job {} does not exist", self.foreign_id, self.job_id,
); );
return; return;
}; };
@@ -197,7 +197,7 @@ impl Job {
} }
} }
} else { } else {
warn!(context, 0, "Missing recipients for job {}", self.job_id,); warn!(context, "Missing recipients for job {}", self.job_id,);
} }
} }
} }
@@ -277,7 +277,7 @@ impl Job {
if dc_rfc724_mid_cnt(context, msg.rfc724_mid) != 1 { if dc_rfc724_mid_cnt(context, msg.rfc724_mid) != 1 {
info!( info!(
context, context,
0, "The message is deleted from the server when all parts are deleted.", "The message is deleted from the server when all parts are deleted.",
); );
delete_from_server = 0i32 delete_from_server = 0i32
} }
@@ -440,18 +440,17 @@ pub fn perform_imap_fetch(context: &Context) {
.unwrap_or_else(|| 1) .unwrap_or_else(|| 1)
== 0 == 0
{ {
info!(context, 0, "INBOX-watch disabled.",); info!(context, "INBOX-watch disabled.",);
return; return;
} }
info!(context, 0, "INBOX-fetch started...",); info!(context, "INBOX-fetch started...",);
inbox.fetch(context); inbox.fetch(context);
if inbox.should_reconnect() { if inbox.should_reconnect() {
info!(context, 0, "INBOX-fetch aborted, starting over...",); info!(context, "INBOX-fetch aborted, starting over...",);
inbox.fetch(context); inbox.fetch(context);
} }
info!( info!(
context, context,
0,
"INBOX-fetch done in {:.4} ms.", "INBOX-fetch done in {:.4} ms.",
start.elapsed().as_nanos() as f64 / 1000.0, start.elapsed().as_nanos() as f64 / 1000.0,
); );
@@ -465,13 +464,13 @@ pub fn perform_imap_idle(context: &Context) {
if *context.perform_inbox_jobs_needed.clone().read().unwrap() { if *context.perform_inbox_jobs_needed.clone().read().unwrap() {
info!( info!(
context, context,
0, "INBOX-IDLE will not be started because of waiting jobs." "INBOX-IDLE will not be started because of waiting jobs."
); );
return; return;
} }
info!(context, 0, "INBOX-IDLE started..."); info!(context, "INBOX-IDLE started...");
inbox.idle(context); inbox.idle(context);
info!(context, 0, "INBOX-IDLE ended."); info!(context, "INBOX-IDLE ended.");
} }
pub fn perform_mvbox_fetch(context: &Context) { pub fn perform_mvbox_fetch(context: &Context) {
@@ -548,16 +547,16 @@ pub fn perform_smtp_jobs(context: &Context) {
state.perform_jobs_needed = 0; state.perform_jobs_needed = 0;
if state.suspended { if state.suspended {
info!(context, 0, "SMTP-jobs suspended.",); info!(context, "SMTP-jobs suspended.",);
return; return;
} }
state.doing_jobs = true; state.doing_jobs = true;
probe_smtp_network probe_smtp_network
}; };
info!(context, 0, "SMTP-jobs started...",); info!(context, "SMTP-jobs started...",);
job_perform(context, Thread::Smtp, probe_smtp_network); job_perform(context, Thread::Smtp, probe_smtp_network);
info!(context, 0, "SMTP-jobs ended."); info!(context, "SMTP-jobs ended.");
{ {
let &(ref lock, _) = &*context.smtp_state.clone(); let &(ref lock, _) = &*context.smtp_state.clone();
@@ -568,7 +567,7 @@ pub fn perform_smtp_jobs(context: &Context) {
} }
pub fn perform_smtp_idle(context: &Context) { pub fn perform_smtp_idle(context: &Context) {
info!(context, 0, "SMTP-idle started...",); info!(context, "SMTP-idle started...",);
{ {
let &(ref lock, ref cvar) = &*context.smtp_state.clone(); let &(ref lock, ref cvar) = &*context.smtp_state.clone();
let mut state = lock.lock().unwrap(); let mut state = lock.lock().unwrap();
@@ -576,7 +575,7 @@ pub fn perform_smtp_idle(context: &Context) {
if state.perform_jobs_needed == 1 { if state.perform_jobs_needed == 1 {
info!( info!(
context, context,
0, "SMTP-idle will not be started because of waiting jobs.", "SMTP-idle will not be started because of waiting jobs.",
); );
} else { } else {
let dur = get_next_wakeup_time(context, Thread::Smtp); let dur = get_next_wakeup_time(context, Thread::Smtp);
@@ -594,7 +593,7 @@ pub fn perform_smtp_idle(context: &Context) {
} }
} }
info!(context, 0, "SMTP-idle ended.",); info!(context, "SMTP-idle ended.",);
} }
fn get_next_wakeup_time(context: &Context, thread: Thread) -> Duration { fn get_next_wakeup_time(context: &Context, thread: Thread) -> Duration {
@@ -653,7 +652,7 @@ pub unsafe fn job_send_msg(context: &Context, msg_id: uint32_t) -> libc::c_int {
if mimefactory.is_err() || mimefactory.as_ref().unwrap().from_addr.is_null() { if mimefactory.is_err() || mimefactory.as_ref().unwrap().from_addr.is_null() {
warn!( warn!(
context, context,
0, "Cannot load data to send, maybe the message is deleted in between.", "Cannot load data to send, maybe the message is deleted in between.",
); );
} else { } else {
let mut mimefactory = mimefactory.unwrap(); let mut mimefactory = mimefactory.unwrap();
@@ -695,7 +694,6 @@ pub unsafe fn job_send_msg(context: &Context, msg_id: uint32_t) -> libc::c_int {
{ {
warn!( warn!(
context, context,
0,
"e2e encryption unavailable {} - {:?}", "e2e encryption unavailable {} - {:?}",
msg_id, msg_id,
mimefactory.msg.param.get_int(Param::GuranteeE2ee), mimefactory.msg.param.get_int(Param::GuranteeE2ee),
@@ -726,7 +724,7 @@ pub unsafe fn job_send_msg(context: &Context, msg_id: uint32_t) -> libc::c_int {
if let Err(err) = if let Err(err) =
location::set_kml_sent_timestamp(context, mimefactory.msg.chat_id, time()) location::set_kml_sent_timestamp(context, mimefactory.msg.chat_id, time())
{ {
error!(context, 0, "Failed to set kml sent_timestamp: {:?}", err); error!(context, "Failed to set kml sent_timestamp: {:?}", err);
} }
if !mimefactory.msg.hidden { if !mimefactory.msg.hidden {
if let Err(err) = location::set_msg_location_id( if let Err(err) = location::set_msg_location_id(
@@ -734,7 +732,7 @@ pub unsafe fn job_send_msg(context: &Context, msg_id: uint32_t) -> libc::c_int {
mimefactory.msg.id, mimefactory.msg.id,
mimefactory.out_last_added_location_id, mimefactory.out_last_added_location_id,
) { ) {
error!(context, 0, "Failed to set msg_location_id: {:?}", err); error!(context, "Failed to set msg_location_id: {:?}", err);
} }
} }
} }
@@ -757,14 +755,14 @@ pub unsafe fn job_send_msg(context: &Context, msg_id: uint32_t) -> libc::c_int {
} }
pub fn perform_imap_jobs(context: &Context) { pub fn perform_imap_jobs(context: &Context) {
info!(context, 0, "dc_perform_imap_jobs starting.",); info!(context, "dc_perform_imap_jobs starting.",);
let probe_imap_network = *context.probe_imap_network.clone().read().unwrap(); let probe_imap_network = *context.probe_imap_network.clone().read().unwrap();
*context.probe_imap_network.write().unwrap() = false; *context.probe_imap_network.write().unwrap() = false;
*context.perform_inbox_jobs_needed.write().unwrap() = false; *context.perform_inbox_jobs_needed.write().unwrap() = false;
job_perform(context, Thread::Imap, probe_imap_network); job_perform(context, Thread::Imap, probe_imap_network);
info!(context, 0, "dc_perform_imap_jobs ended.",); info!(context, "dc_perform_imap_jobs ended.",);
} }
fn job_perform(context: &Context, thread: Thread, probe_network: bool) { fn job_perform(context: &Context, thread: Thread, probe_network: bool) {
@@ -812,14 +810,13 @@ fn job_perform(context: &Context, thread: Thread, probe_network: bool) {
match jobs { match jobs {
Ok(ref _res) => {} Ok(ref _res) => {}
Err(ref err) => { Err(ref err) => {
info!(context, 0, "query failed: {:?}", err); info!(context, "query failed: {:?}", err);
} }
} }
for mut job in jobs.unwrap_or_default() { for mut job in jobs.unwrap_or_default() {
info!( info!(
context, context,
0,
"{}-job #{}, action {} started...", "{}-job #{}, action {} started...",
if thread == Thread::Imap { if thread == Thread::Imap {
"INBOX" "INBOX"
@@ -858,7 +855,7 @@ fn job_perform(context: &Context, thread: Thread, probe_network: bool) {
match job.action { match job.action {
Action::Unknown => { Action::Unknown => {
warn!(context, 0, "Unknown job id found"); warn!(context, "Unknown job id found");
} }
Action::SendMsgToSmtp => job.do_DC_JOB_SEND(context), Action::SendMsgToSmtp => job.do_DC_JOB_SEND(context),
Action::DeleteMsgOnImap => job.do_DC_JOB_DELETE_MSG_ON_IMAP(context), Action::DeleteMsgOnImap => job.do_DC_JOB_DELETE_MSG_ON_IMAP(context),
@@ -902,7 +899,6 @@ fn job_perform(context: &Context, thread: Thread, probe_network: bool) {
// just try over next loop unconditionally, the ui typically interrupts idle when the file (video) is ready // just try over next loop unconditionally, the ui typically interrupts idle when the file (video) is ready
info!( info!(
context, context,
0,
"{}-job #{} not yet ready and will be delayed.", "{}-job #{} not yet ready and will be delayed.",
if thread == Thread::Imap { if thread == Thread::Imap {
"INBOX" "INBOX"
@@ -920,7 +916,6 @@ fn job_perform(context: &Context, thread: Thread, probe_network: bool) {
job.update(context); job.update(context);
info!( info!(
context, context,
0,
"{}-job #{} not succeeded on try #{}, retry in ADD_TIME+{} (in {} seconds).", "{}-job #{} not succeeded on try #{}, retry in ADD_TIME+{} (in {} seconds).",
if thread == Thread::Imap { if thread == Thread::Imap {
"INBOX" "INBOX"
@@ -1019,7 +1014,6 @@ fn add_smtp_job(context: &Context, action: Action, mimefactory: &dc_mimefactory_
if pathNfilename.is_null() { if pathNfilename.is_null() {
error!( error!(
context, context,
0,
"Could not find free file name for message with ID <{}>.", "Could not find free file name for message with ID <{}>.",
to_string(mimefactory.rfc724_mid), to_string(mimefactory.rfc724_mid),
); );
@@ -1035,7 +1029,6 @@ fn add_smtp_job(context: &Context, action: Action, mimefactory: &dc_mimefactory_
{ {
error!( error!(
context, context,
0,
"Could not write message <{}> to \"{}\".", "Could not write message <{}> to \"{}\".",
to_string(mimefactory.rfc724_mid), to_string(mimefactory.rfc724_mid),
as_str(pathNfilename), as_str(pathNfilename),
@@ -1079,7 +1072,7 @@ pub fn job_add(
delay_seconds: i64, delay_seconds: i64,
) { ) {
if action == Action::Unknown { if action == Action::Unknown {
error!(context, 0, "Invalid action passed to job_add"); error!(context, "Invalid action passed to job_add");
return; return;
} }
@@ -1108,7 +1101,7 @@ pub fn job_add(
} }
pub fn interrupt_smtp_idle(context: &Context) { pub fn interrupt_smtp_idle(context: &Context) {
info!(context, 0, "Interrupting SMTP-idle...",); info!(context, "Interrupting SMTP-idle...",);
let &(ref lock, ref cvar) = &*context.smtp_state.clone(); let &(ref lock, ref cvar) = &*context.smtp_state.clone();
let mut state = lock.lock().unwrap(); let mut state = lock.lock().unwrap();
@@ -1119,7 +1112,7 @@ pub fn interrupt_smtp_idle(context: &Context) {
} }
pub fn interrupt_imap_idle(context: &Context) { pub fn interrupt_imap_idle(context: &Context) {
info!(context, 0, "Interrupting IMAP-IDLE...",); info!(context, "Interrupting IMAP-IDLE...",);
*context.perform_inbox_jobs_needed.write().unwrap() = true; *context.perform_inbox_jobs_needed.write().unwrap() = true;
context.inbox.read().unwrap().interrupt_idle(); context.inbox.read().unwrap().interrupt_idle();

View File

@@ -30,7 +30,7 @@ impl JobThread {
} }
pub fn suspend(&self, context: &Context) { pub fn suspend(&self, context: &Context) {
info!(context, 0, "Suspending {}-thread.", self.name,); info!(context, "Suspending {}-thread.", self.name,);
{ {
self.state.0.lock().unwrap().suspended = true; self.state.0.lock().unwrap().suspended = true;
} }
@@ -45,7 +45,7 @@ impl JobThread {
} }
pub fn unsuspend(&self, context: &Context) { pub fn unsuspend(&self, context: &Context) {
info!(context, 0, "Unsuspending {}-thread.", self.name); info!(context, "Unsuspending {}-thread.", self.name);
let &(ref lock, ref cvar) = &*self.state.clone(); let &(ref lock, ref cvar) = &*self.state.clone();
let mut state = lock.lock().unwrap(); let mut state = lock.lock().unwrap();
@@ -60,7 +60,7 @@ impl JobThread {
self.state.0.lock().unwrap().jobs_needed = 1; self.state.0.lock().unwrap().jobs_needed = 1;
} }
info!(context, 0, "Interrupting {}-IDLE...", self.name); info!(context, "Interrupting {}-IDLE...", self.name);
self.imap.interrupt_idle(); self.imap.interrupt_idle();
@@ -86,16 +86,15 @@ impl JobThread {
if use_network { if use_network {
let start = std::time::Instant::now(); let start = std::time::Instant::now();
if self.connect_to_imap(context) { if self.connect_to_imap(context) {
info!(context, 0, "{}-fetch started...", self.name); info!(context, "{}-fetch started...", self.name);
self.imap.fetch(context); self.imap.fetch(context);
if self.imap.should_reconnect() { if self.imap.should_reconnect() {
info!(context, 0, "{}-fetch aborted, starting over...", self.name,); info!(context, "{}-fetch aborted, starting over...", self.name,);
self.imap.fetch(context); self.imap.fetch(context);
} }
info!( info!(
context, context,
0,
"{}-fetch done in {:.3} ms.", "{}-fetch done in {:.3} ms.",
self.name, self.name,
start.elapsed().as_millis(), start.elapsed().as_millis(),
@@ -142,7 +141,6 @@ impl JobThread {
if 0 != state.jobs_needed { if 0 != state.jobs_needed {
info!( info!(
context, context,
0,
"{}-IDLE will not be started as it was interrupted while not ideling.", "{}-IDLE will not be started as it was interrupted while not ideling.",
self.name, self.name,
); );
@@ -172,9 +170,9 @@ impl JobThread {
} }
self.connect_to_imap(context); self.connect_to_imap(context);
info!(context, 0, "{}-IDLE started...", self.name,); info!(context, "{}-IDLE started...", self.name,);
self.imap.idle(context); self.imap.idle(context);
info!(context, 0, "{}-IDLE ended.", self.name); info!(context, "{}-IDLE ended.", self.name);
self.state.0.lock().unwrap().using_handle = false; self.state.0.lock().unwrap().using_handle = false;
} }

View File

@@ -1,7 +1,6 @@
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::ffi::{CStr, CString}; use std::ffi::{CStr, CString};
use std::io::Cursor; use std::io::Cursor;
use std::slice;
use libc; use libc;
use pgp::composed::{Deserializable, SignedPublicKey, SignedSecretKey}; use pgp::composed::{Deserializable, SignedPublicKey, SignedSecretKey};
@@ -106,15 +105,6 @@ impl Key {
} }
} }
pub fn from_binary(data: *const u8, len: libc::c_int, key_type: KeyType) -> Option<Self> {
if data.is_null() || len == 0 {
return None;
}
let bytes = unsafe { slice::from_raw_parts(data, len as usize) };
Self::from_slice(bytes, key_type)
}
pub fn from_armored_string( pub fn from_armored_string(
data: &str, data: &str,
key_type: KeyType, key_type: KeyType,
@@ -245,7 +235,7 @@ impl Key {
file_content_c.as_bytes().len(), file_content_c.as_bytes().len(),
) )
} { } {
error!(context, 0, "Cannot write key to {}", to_string(file)); error!(context, "Cannot write key to {}", to_string(file));
false false
} else { } else {
true true
@@ -449,6 +439,27 @@ i8pcjGO+IZffvyZJVRWfVooBJmWWbPB1pueo3tx8w3+fcuzpxz+RLFKaPyqXO+dD
assert_eq!(private_key, private_key2); assert_eq!(private_key, private_key2);
} }
#[test]
fn test_from_slice_bad_data() {
let mut bad_data: [u8; 4096] = [0; 4096];
for i in 0..4096 {
bad_data[i] = (i & 0xff) as u8;
}
for j in 0..(4096 / 40) {
let bad_key = Key::from_slice(
&bad_data[j..j + 4096 / 2 + j],
if 0 != j & 1 {
KeyType::Public
} else {
KeyType::Private
},
);
assert!(bad_key.is_none());
}
}
#[test] #[test]
#[ignore] // is too expensive #[ignore] // is too expensive
fn test_ascii_roundtrip() { fn test_ascii_roundtrip() {

View File

@@ -84,7 +84,6 @@ impl Kml {
Err(e) => { Err(e) => {
error!( error!(
context, context,
0,
"Location parsing: Error at position {}: {:?}", "Location parsing: Error at position {}: {:?}",
reader.buffer_position(), reader.buffer_position(),
e e
@@ -266,16 +265,16 @@ pub fn set(context: &Context, latitude: f64, longitude: f64, accuracy: f64) -> l
if latitude == 0.0 && longitude == 0.0 { if latitude == 0.0 && longitude == 0.0 {
return 1; return 1;
} }
let mut continue_streaming = false;
context.sql.query_map( if let Ok(chats) = context.sql.query_map(
"SELECT id FROM chats WHERE locations_send_until>?;", "SELECT id FROM chats WHERE locations_send_until>?;",
params![time()], |row| row.get::<_, i32>(0), params![time()],
|chats| { |row| row.get::<_, i32>(0),
let mut continue_streaming = false; |chats| chats.collect::<Result<Vec<_>, _>>().map_err(Into::into),
) {
for chat in chats { for chat_id in chats {
let chat_id = chat?; if let Err(err) = context.sql.execute(
context.sql.execute(
"INSERT INTO locations \ "INSERT INTO locations \
(latitude, longitude, accuracy, timestamp, chat_id, from_id) VALUES (?,?,?,?,?,?);", (latitude, longitude, accuracy, timestamp, chat_id, from_id) VALUES (?,?,?,?,?,?);",
params![ params![
@@ -286,16 +285,19 @@ pub fn set(context: &Context, latitude: f64, longitude: f64, accuracy: f64) -> l
chat_id, chat_id,
1, 1,
] ]
)?; ) {
warn!(context, "failed to store location {:?}", err);
} else {
continue_streaming = true; continue_streaming = true;
} }
if continue_streaming {
context.call_cb(Event::LOCATION_CHANGED, 1, 0);
};
schedule_MAYBE_SEND_LOCATIONS(context, 0);
Ok(continue_streaming as libc::c_int)
} }
).unwrap_or_default() if continue_streaming {
context.call_cb(Event::LOCATION_CHANGED, 1, 0);
};
schedule_MAYBE_SEND_LOCATIONS(context, 0);
}
continue_streaming as libc::c_int
} }
pub fn get_range( pub fn get_range(
@@ -546,76 +548,81 @@ pub fn job_do_DC_JOB_MAYBE_SEND_LOCATIONS(context: &Context, _job: &Job) {
let mut continue_streaming: libc::c_int = 1; let mut continue_streaming: libc::c_int = 1;
info!( info!(
context, context,
0, " ----------------- MAYBE_SEND_LOCATIONS -------------- ", " ----------------- MAYBE_SEND_LOCATIONS -------------- ",
); );
context if let Ok(rows) = context.sql.query_map(
.sql "SELECT id, locations_send_begin, locations_last_sent \
.query_map( FROM chats \
"SELECT id, locations_send_begin, locations_last_sent \ WHERE locations_send_until>?;",
FROM chats \ params![now],
WHERE locations_send_until>?;", |row| {
params![now], let chat_id: i32 = row.get(0)?;
|row| { let locations_send_begin: i64 = row.get(1)?;
let chat_id: i32 = row.get(0)?; let locations_last_sent: i64 = row.get(2)?;
let locations_send_begin: i64 = row.get(1)?; continue_streaming = 1;
let locations_last_sent: i64 = row.get(2)?;
continue_streaming = 1;
// be a bit tolerant as the timer may not align exactly with time(NULL) // be a bit tolerant as the timer may not align exactly with time(NULL)
if now - locations_last_sent < (60 - 3) { if now - locations_last_sent < (60 - 3) {
Ok(None) Ok(None)
} else { } else {
Ok(Some((chat_id, locations_send_begin, locations_last_sent))) Ok(Some((chat_id, locations_send_begin, locations_last_sent)))
} }
}, },
|rows| { |rows| {
context.sql.prepare( rows.filter_map(|v| v.transpose())
"SELECT id \ .collect::<Result<Vec<_>, _>>()
FROM locations \ .map_err(Into::into)
WHERE from_id=? \ },
AND timestamp>=? \ ) {
AND timestamp>? \ let msgs = context
AND independent=0 \ .sql
ORDER BY timestamp;", .prepare(
|mut stmt_locations, _| { "SELECT id \
for (chat_id, locations_send_begin, locations_last_sent) in FROM locations \
rows.filter_map(|r| match r { WHERE from_id=? \
Ok(Some(v)) => Some(v), AND timestamp>=? \
_ => None, AND timestamp>? \
}) AND independent=0 \
{ ORDER BY timestamp;",
// TODO: do I need to reset? |mut stmt_locations, _| {
let msgs = rows
.into_iter()
.filter_map(|(chat_id, locations_send_begin, locations_last_sent)| {
if !stmt_locations if !stmt_locations
.exists(params![1, locations_send_begin, locations_last_sent,]) .exists(params![1, locations_send_begin, locations_last_sent,])
.unwrap_or_default() .unwrap_or_default()
{ {
// if there is no new location, there's nothing to send. // if there is no new location, there's nothing to send.
// however, maybe we want to bypass this test eg. 15 minutes // however, maybe we want to bypass this test eg. 15 minutes
continue; None
} else {
// pending locations are attached automatically to every message,
// so also to this empty text message.
// DC_CMD_LOCATION is only needed to create a nicer subject.
//
// for optimisation and to avoid flooding the sending queue,
// we could sending these messages only if we're really online.
// the easiest way to determine this, is to check for an empty message queue.
// (might not be 100%, however, as positions are sent combined later
// and dc_set_location() is typically called periodically, this is ok)
let mut msg = dc_msg_new(context, Viewtype::Text);
msg.hidden = true;
msg.param.set_int(Param::Cmd, 9);
Some((chat_id, msg))
} }
// pending locations are attached automatically to every message, })
// so also to this empty text message. .collect::<Vec<_>>();
// DC_CMD_LOCATION is only needed to create a nicer subject. Ok(msgs)
// },
// for optimisation and to avoid flooding the sending queue, )
// we could sending these messages only if we're really online. .unwrap_or_default(); // TODO: Better error handling
// the easiest way to determine this, is to check for an empty message queue.
// (might not be 100%, however, as positions are sent combined later
// and dc_set_location() is typically called periodically, this is ok)
let mut msg = dc_msg_new(context, Viewtype::Text);
msg.hidden = true;
msg.param.set_int(Param::Cmd, 9);
// TODO: handle cleanup on error
chat::send_msg(context, chat_id as u32, &mut msg).unwrap();
}
Ok(())
},
)
},
)
.unwrap(); // TODO: Better error handling
for (chat_id, mut msg) in msgs.into_iter() {
// TODO: better error handling
chat::send_msg(context, chat_id as u32, &mut msg).unwrap();
}
}
if 0 != continue_streaming { if 0 != continue_streaming {
schedule_MAYBE_SEND_LOCATIONS(context, 0x1); schedule_MAYBE_SEND_LOCATIONS(context, 0x1);
} }

View File

@@ -1,46 +1,31 @@
#[macro_export] #[macro_export]
macro_rules! info { macro_rules! info {
($ctx:expr, $data1:expr, $msg:expr) => { ($ctx:expr, $msg:expr) => {
info!($ctx, $data1, $msg,) info!($ctx, $msg,)
};
($ctx:expr, $msg:expr, $($args:expr),* $(,)?) => {
log_event!($ctx, $crate::constants::Event::INFO, 0, $msg, $($args),*);
}; };
($ctx:expr, $data1:expr, $msg:expr, $($args:expr),* $(,)?) => {
#[allow(unused_unsafe)]
unsafe {
let formatted = format!($msg, $($args),*);
let formatted_c = std::ffi::CString::new(formatted).unwrap();
$ctx.call_cb($crate::constants::Event::INFO, $data1 as libc::uintptr_t,
formatted_c.as_ptr() as libc::uintptr_t);
}};
} }
#[macro_export] #[macro_export]
macro_rules! warn { macro_rules! warn {
($ctx:expr, $data1:expr, $msg:expr) => { ($ctx:expr, $msg:expr) => {
warn!($ctx, $data1, $msg,) warn!($ctx, $msg,)
};
($ctx:expr, $msg:expr, $($args:expr),* $(,)?) => {
log_event!($ctx, $crate::constants::Event::WARNING, 0, $msg, $($args),*);
}; };
($ctx:expr, $data1:expr, $msg:expr, $($args:expr),* $(,)?) => {
#[allow(unused_unsafe)]
unsafe {
let formatted = format!($msg, $($args),*);
let formatted_c = std::ffi::CString::new(formatted).unwrap();
$ctx.call_cb($crate::constants::Event::WARNING, $data1 as libc::uintptr_t,
formatted_c.as_ptr() as libc::uintptr_t);
}};
} }
#[macro_export] #[macro_export]
macro_rules! error { macro_rules! error {
($ctx:expr, $data1:expr, $msg:expr) => { ($ctx:expr, $msg:expr) => {
error!($ctx, $data1, $msg,) error!($ctx, $msg,)
};
($ctx:expr, $msg:expr, $($args:expr),* $(,)?) => {
log_event!($ctx, $crate::constants::Event::ERROR, 0, $msg, $($args),*);
}; };
($ctx:expr, $data1:expr, $msg:expr, $($args:expr),* $(,)?) => {
#[allow(unused_unsafe)]
unsafe {
let formatted = format!($msg, $($args),*);
let formatted_c = std::ffi::CString::new(formatted).unwrap();
$ctx.call_cb($crate::constants::Event::ERROR, $data1 as libc::uintptr_t,
formatted_c.as_ptr() as libc::uintptr_t);
}};
} }
#[macro_export] #[macro_export]
@@ -49,13 +34,11 @@ macro_rules! log_event {
log_event!($ctx, $data1, $msg,) log_event!($ctx, $data1, $msg,)
}; };
($ctx:expr, $event:expr, $data1:expr, $msg:expr, $($args:expr),* $(,)?) => { ($ctx:expr, $event:expr, $data1:expr, $msg:expr, $($args:expr),* $(,)?) => {
#[allow(unused_unsafe)] let formatted = format!($msg, $($args),*);
unsafe { let formatted_c = std::ffi::CString::new(formatted).unwrap();
let formatted = format!($msg, $($args),*); $ctx.call_cb($event, $data1 as libc::uintptr_t,
let formatted_c = std::ffi::CString::new(formatted).unwrap(); formatted_c.as_ptr() as libc::uintptr_t);
$ctx.call_cb($event, $data1 as libc::uintptr_t, };
formatted_c.as_ptr() as libc::uintptr_t);
}};
} }
#[macro_export] #[macro_export]

View File

@@ -477,7 +477,7 @@ pub fn dc_msg_load_from_db<'a>(context: &'a Context, id: u32) -> Result<Message<
if let Ok(t) = String::from_utf8(buf.to_vec()) { if let Ok(t) = String::from_utf8(buf.to_vec()) {
text = t; text = t;
} else { } else {
warn!(context, 0, "dc_msg_load_from_db: could not get text column as non-lossy utf8 id {}", id); warn!(context, "dc_msg_load_from_db: could not get text column as non-lossy utf8 id {}", id);
text = String::from_utf8_lossy(buf).into_owned(); text = String::from_utf8_lossy(buf).into_owned();
} }
} else { } else {
@@ -579,7 +579,7 @@ pub fn dc_markseen_msgs(context: &Context, msg_ids: *const u32, msg_cnt: usize)
); );
if msgs.is_err() { if msgs.is_err() {
warn!(context, 0, "markseen_msgs failed: {:?}", msgs); warn!(context, "markseen_msgs failed: {:?}", msgs);
return false; return false;
} }
let mut send_event = false; let mut send_event = false;
@@ -589,7 +589,7 @@ pub fn dc_markseen_msgs(context: &Context, msg_ids: *const u32, msg_cnt: usize)
if curr_blocked == Blocked::Not { if curr_blocked == Blocked::Not {
if curr_state == MessageState::InFresh || curr_state == MessageState::InNoticed { if curr_state == MessageState::InFresh || curr_state == MessageState::InNoticed {
dc_update_msg_state(context, id, MessageState::InSeen); dc_update_msg_state(context, id, MessageState::InSeen);
info!(context, 0, "Seen message #{}.", id); info!(context, "Seen message #{}.", id);
job_add( job_add(
context, context,
@@ -1074,7 +1074,7 @@ pub fn dc_set_msg_failed(context: &Context, msg_id: u32, error: Option<impl AsRe
} }
if let Some(error) = error { if let Some(error) = error {
msg.param.set(Param::Error, error.as_ref()); msg.param.set(Param::Error, error.as_ref());
error!(context, 0, "{}", error.as_ref()); error!(context, "{}", error.as_ref());
} }
if sql::execute( if sql::execute(
@@ -1203,7 +1203,7 @@ pub fn dc_get_real_msg_cnt(context: &Context) -> libc::c_int {
) { ) {
Ok(res) => res, Ok(res) => res,
Err(err) => { Err(err) => {
error!(context, 0, "dc_get_real_msg_cnt() failed. {}", err); error!(context, "dc_get_real_msg_cnt() failed. {}", err);
0 0
} }
} }
@@ -1219,7 +1219,7 @@ pub fn dc_get_deaddrop_msg_cnt(context: &Context) -> size_t {
) { ) {
Ok(res) => res as size_t, Ok(res) => res as size_t,
Err(err) => { Err(err) => {
error!(context, 0, "dc_get_deaddrop_msg_cnt() failed. {}", err); error!(context, "dc_get_deaddrop_msg_cnt() failed. {}", err);
0 0
} }
} }
@@ -1234,7 +1234,7 @@ pub fn dc_rfc724_mid_cnt(context: &Context, rfc724_mid: *const libc::c_char) ->
) { ) {
Ok(res) => res, Ok(res) => res,
Err(err) => { Err(err) => {
error!(context, 0, "dc_get_rfc724_mid_cnt() failed. {}", err); error!(context, "dc_get_rfc724_mid_cnt() failed. {}", err);
0 0
} }
} }
@@ -1288,7 +1288,7 @@ pub fn dc_update_server_uid(
) { ) {
Ok(_) => {} Ok(_) => {}
Err(err) => { Err(err) => {
warn!(context, 0, "msg: failed to update server_uid: {}", err); warn!(context, "msg: failed to update server_uid: {}", err);
} }
} }
} }

View File

@@ -97,10 +97,7 @@ pub fn dc_get_oauth2_access_token(
let (redirect_uri, token_url, update_redirect_uri_on_success) = let (redirect_uri, token_url, update_redirect_uri_on_success) =
if refresh_token.is_none() || refresh_token_for != code.as_ref() { if refresh_token.is_none() || refresh_token_for != code.as_ref() {
info!( info!(context, "Generate OAuth2 refresh_token and access_token...",);
context,
0, "Generate OAuth2 refresh_token and access_token...",
);
( (
context context
.sql .sql
@@ -112,7 +109,7 @@ pub fn dc_get_oauth2_access_token(
} else { } else {
info!( info!(
context, context,
0, "Regenerate OAuth2 access_token by refresh_token...", "Regenerate OAuth2 access_token by refresh_token...",
); );
( (
context context
@@ -134,7 +131,7 @@ pub fn dc_get_oauth2_access_token(
if response.is_err() { if response.is_err() {
warn!( warn!(
context, context,
0, "Error calling OAuth2 at {}: {:?}", token_url, response "Error calling OAuth2 at {}: {:?}", token_url, response
); );
return None; return None;
} }
@@ -142,7 +139,6 @@ pub fn dc_get_oauth2_access_token(
if !response.status().is_success() { if !response.status().is_success() {
warn!( warn!(
context, context,
0,
"Error calling OAuth2 at {}: {:?}", "Error calling OAuth2 at {}: {:?}",
token_url, token_url,
response.status() response.status()
@@ -154,7 +150,7 @@ pub fn dc_get_oauth2_access_token(
if parsed.is_err() { if parsed.is_err() {
warn!( warn!(
context, context,
0, "Failed to parse OAuth2 JSON response from {}: error: {:?}", token_url, parsed "Failed to parse OAuth2 JSON response from {}: error: {:?}", token_url, parsed
); );
return None; return None;
} }
@@ -195,12 +191,12 @@ pub fn dc_get_oauth2_access_token(
.ok(); .ok();
} }
} else { } else {
warn!(context, 0, "Failed to find OAuth2 access token"); warn!(context, "Failed to find OAuth2 access token");
} }
response.access_token response.access_token
} else { } else {
warn!(context, 0, "Internal OAuth2 error: 2"); warn!(context, "Internal OAuth2 error: 2");
None None
} }
@@ -268,17 +264,12 @@ impl Oauth2 {
// } // }
let response = reqwest::Client::new().get(&userinfo_url).send(); let response = reqwest::Client::new().get(&userinfo_url).send();
if response.is_err() { if response.is_err() {
warn!(context, 0, "Error getting userinfo: {:?}", response); warn!(context, "Error getting userinfo: {:?}", response);
return None; return None;
} }
let mut response = response.unwrap(); let mut response = response.unwrap();
if !response.status().is_success() { if !response.status().is_success() {
warn!( warn!(context, "Error getting userinfo: {:?}", response.status());
context,
0,
"Error getting userinfo: {:?}",
response.status()
);
return None; return None;
} }
@@ -286,19 +277,19 @@ impl Oauth2 {
if parsed.is_err() { if parsed.is_err() {
warn!( warn!(
context, context,
0, "Failed to parse userinfo JSON response: {:?}", parsed "Failed to parse userinfo JSON response: {:?}", parsed
); );
return None; return None;
} }
if let Ok(response) = parsed { if let Ok(response) = parsed {
let addr = response.get("email"); let addr = response.get("email");
if addr.is_none() { if addr.is_none() {
warn!(context, 0, "E-mail missing in userinfo."); warn!(context, "E-mail missing in userinfo.");
} }
addr.map(|addr| addr.to_string()) addr.map(|addr| addr.to_string())
} else { } else {
warn!(context, 0, "Failed to parse userinfo."); warn!(context, "Failed to parse userinfo.");
None None
} }
} }

View File

@@ -1,6 +1,5 @@
use std::collections::HashSet; use std::collections::HashSet;
use std::convert::TryInto; use std::convert::TryInto;
use std::ffi::CStr;
use std::io::Cursor; use std::io::Cursor;
use std::ptr; use std::ptr;
@@ -274,32 +273,25 @@ pub fn dc_pgp_pk_decrypt(
} }
/// Symmetric encryption. /// Symmetric encryption.
pub fn dc_pgp_symm_encrypt(passphrase: *const libc::c_char, plain: &[u8]) -> Option<String> { pub fn dc_pgp_symm_encrypt(passphrase: &str, plain: &[u8]) -> Option<String> {
assert!(!passphrase.is_null(), "invalid passphrase");
let pw = unsafe { CStr::from_ptr(passphrase).to_str().unwrap() };
let mut rng = thread_rng(); let mut rng = thread_rng();
let lit_msg = Message::new_literal_bytes("", plain); let lit_msg = Message::new_literal_bytes("", plain);
let s2k = StringToKey::new_default(&mut rng); let s2k = StringToKey::new_default(&mut rng);
let msg = lit_msg.encrypt_with_password(&mut rng, s2k, Default::default(), || pw.into()); let msg =
lit_msg.encrypt_with_password(&mut rng, s2k, Default::default(), || passphrase.into());
msg.and_then(|msg| msg.to_armored_string(None)).ok() msg.and_then(|msg| msg.to_armored_string(None)).ok()
} }
/// Symmetric decryption. /// Symmetric decryption.
pub fn dc_pgp_symm_decrypt(passphrase: *const libc::c_char, ctext: &[u8]) -> Option<Vec<u8>> { pub fn dc_pgp_symm_decrypt(passphrase: &str, ctext: &[u8]) -> Option<Vec<u8>> {
assert!(!passphrase.is_null(), "invalid passphrase");
let pw = unsafe { CStr::from_ptr(passphrase).to_str().unwrap() };
let enc_msg = Message::from_bytes(Cursor::new(ctext)); let enc_msg = Message::from_bytes(Cursor::new(ctext));
enc_msg enc_msg
.and_then(|msg| { .and_then(|msg| {
let mut decryptor = msg let mut decryptor = msg
.decrypt_with_password(|| pw.into()) .decrypt_with_password(|| passphrase.into())
.expect("failed decryption"); .expect("failed decryption");
decryptor.next().expect("no message") decryptor.next().expect("no message")
}) })

View File

@@ -37,7 +37,7 @@ impl Into<Lot> for Error {
pub fn check_qr(context: &Context, qr: impl AsRef<str>) -> Lot { pub fn check_qr(context: &Context, qr: impl AsRef<str>) -> Lot {
let qr = qr.as_ref(); let qr = qr.as_ref();
info!(context, 0, "Scanned QR code: {}", qr); info!(context, "Scanned QR code: {}", qr);
if qr.starts_with(OPENPGP4FPR_SCHEME) { if qr.starts_with(OPENPGP4FPR_SCHEME) {
decode_openpgp(context, qr) decode_openpgp(context, qr)

View File

@@ -85,7 +85,7 @@ pub fn dc_get_securejoin_qr(context: &Context, group_chat_id: uint32_t) -> Optio
let self_addr = match context.sql.get_config(context, "configured_addr") { let self_addr = match context.sql.get_config(context, "configured_addr") {
Some(addr) => addr, Some(addr) => addr,
None => { None => {
error!(context, 0, "Not configured, cannot generate QR code.",); error!(context, "Not configured, cannot generate QR code.",);
return None; return None;
} }
}; };
@@ -123,10 +123,7 @@ pub fn dc_get_securejoin_qr(context: &Context, group_chat_id: uint32_t) -> Optio
&auth, &auth,
)) ))
} else { } else {
error!( error!(context, "Cannot get QR-code for chat-id {}", group_chat_id,);
context,
0, "Cannot get QR-code for chat-id {}", group_chat_id,
);
return None; return None;
} }
} else { } else {
@@ -136,7 +133,7 @@ pub fn dc_get_securejoin_qr(context: &Context, group_chat_id: uint32_t) -> Optio
)) ))
}; };
info!(context, 0, "Generated QR code: {}", qr.as_ref().unwrap()); info!(context, "Generated QR code: {}", qr.as_ref().unwrap());
qr qr
} }
@@ -182,7 +179,7 @@ pub fn dc_join_securejoin(context: &Context, qr: &str) -> uint32_t {
let mut contact_chat_id: uint32_t = 0; let mut contact_chat_id: uint32_t = 0;
let mut join_vg: bool = false; let mut join_vg: bool = false;
info!(context, 0, "Requesting secure-join ...",); info!(context, "Requesting secure-join ...",);
ensure_secret_key_exists(context).ok(); ensure_secret_key_exists(context).ok();
if !dc_alloc_ongoing(context) { if !dc_alloc_ongoing(context) {
return cleanup(&context, contact_chat_id, false, join_vg); return cleanup(&context, contact_chat_id, false, join_vg);
@@ -190,12 +187,12 @@ pub fn dc_join_securejoin(context: &Context, qr: &str) -> uint32_t {
let qr_scan = check_qr(context, &qr); let qr_scan = check_qr(context, &qr);
if qr_scan.state != LotState::QrAskVerifyContact && qr_scan.state != LotState::QrAskVerifyGroup if qr_scan.state != LotState::QrAskVerifyContact && qr_scan.state != LotState::QrAskVerifyGroup
{ {
error!(context, 0, "Unknown QR code.",); error!(context, "Unknown QR code.",);
return cleanup(&context, contact_chat_id, true, join_vg); return cleanup(&context, contact_chat_id, true, join_vg);
} }
contact_chat_id = chat::create_by_contact_id(context, qr_scan.id).unwrap_or_default(); contact_chat_id = chat::create_by_contact_id(context, qr_scan.id).unwrap_or_default();
if contact_chat_id == 0 { if contact_chat_id == 0 {
error!(context, 0, "Unknown contact.",); error!(context, "Unknown contact.",);
return cleanup(&context, contact_chat_id, true, join_vg); return cleanup(&context, contact_chat_id, true, join_vg);
} }
if check_exit(context) { if check_exit(context) {
@@ -221,7 +218,7 @@ pub fn dc_join_securejoin(context: &Context, qr: &str) -> uint32_t {
.unwrap(), .unwrap(),
contact_chat_id, contact_chat_id,
) { ) {
info!(context, 0, "Taking protocol shortcut."); info!(context, "Taking protocol shortcut.");
context.bob.write().unwrap().expects = DC_VC_CONTACT_CONFIRM; context.bob.write().unwrap().expects = DC_VC_CONTACT_CONFIRM;
joiner_progress!(context, chat_id_2_contact_id(context, contact_chat_id), 400); joiner_progress!(context, chat_id_2_contact_id(context, contact_chat_id), 400);
let own_fingerprint = get_self_fingerprint(context).unwrap(); let own_fingerprint = get_self_fingerprint(context).unwrap();
@@ -359,7 +356,7 @@ pub fn handle_securejoin_handshake(
}; };
info!( info!(
context, context,
0, ">>>>>>>>>>>>>>>>>>>>>>>>> secure-join message \'{}\' received", step, ">>>>>>>>>>>>>>>>>>>>>>>>> secure-join message \'{}\' received", step,
); );
let (contact_chat_id, contact_chat_id_blocked) = let (contact_chat_id, contact_chat_id_blocked) =
chat::create_or_lookup_by_contact_id(context, contact_id, Blocked::Not).unwrap_or_default(); chat::create_or_lookup_by_contact_id(context, contact_id, Blocked::Not).unwrap_or_default();
@@ -383,15 +380,15 @@ pub fn handle_securejoin_handshake(
let invitenumber = match lookup_field(mimeparser, "Secure-Join-Invitenumber") { let invitenumber = match lookup_field(mimeparser, "Secure-Join-Invitenumber") {
Some(n) => n, Some(n) => n,
None => { None => {
warn!(context, 0, "Secure-join denied (invitenumber missing).",); warn!(context, "Secure-join denied (invitenumber missing).",);
return ret; return ret;
} }
}; };
if !token::exists(context, token::Namespace::InviteNumber, &invitenumber) { if !token::exists(context, token::Namespace::InviteNumber, &invitenumber) {
warn!(context, 0, "Secure-join denied (bad invitenumber).",); warn!(context, "Secure-join denied (bad invitenumber).",);
return ret; return ret;
} }
info!(context, 0, "Secure-join requested.",); info!(context, "Secure-join requested.",);
inviter_progress!(context, contact_id, 300); inviter_progress!(context, contact_id, 300);
send_handshake_msg( send_handshake_msg(
@@ -413,7 +410,7 @@ pub fn handle_securejoin_handshake(
}; };
if cond { if cond {
warn!(context, 0, "auth-required message out of sync.",); warn!(context, "auth-required message out of sync.",);
// no error, just aborted somehow or a mail from another handshake // no error, just aborted somehow or a mail from another handshake
return ret; return ret;
} }
@@ -442,7 +439,7 @@ pub fn handle_securejoin_handshake(
end_bobs_joining(context, DC_BOB_ERROR); end_bobs_joining(context, DC_BOB_ERROR);
return ret; return ret;
} }
info!(context, 0, "Fingerprint verified.",); info!(context, "Fingerprint verified.",);
own_fingerprint = get_self_fingerprint(context).unwrap(); own_fingerprint = get_self_fingerprint(context).unwrap();
joiner_progress!(context, contact_id, 400); joiner_progress!(context, contact_id, 400);
context.bob.write().unwrap().expects = DC_VC_CONTACT_CONFIRM; context.bob.write().unwrap().expects = DC_VC_CONTACT_CONFIRM;
@@ -494,7 +491,7 @@ pub fn handle_securejoin_handshake(
); );
return ret; return ret;
} }
info!(context, 0, "Fingerprint verified.",); info!(context, "Fingerprint verified.",);
// verify that the `Secure-Join-Auth:`-header matches the secret written to the QR code // verify that the `Secure-Join-Auth:`-header matches the secret written to the QR code
let auth_0 = match lookup_field(mimeparser, "Secure-Join-Auth") { let auth_0 = match lookup_field(mimeparser, "Secure-Join-Auth") {
Some(auth) => auth, Some(auth) => auth,
@@ -520,7 +517,7 @@ pub fn handle_securejoin_handshake(
return ret; return ret;
} }
Contact::scaleup_origin_by_id(context, contact_id, Origin::SecurejoinInvited); Contact::scaleup_origin_by_id(context, contact_id, Origin::SecurejoinInvited);
info!(context, 0, "Auth verified.",); info!(context, "Auth verified.",);
secure_connection_established(context, contact_chat_id); secure_connection_established(context, contact_chat_id);
emit_event!(context, Event::CONTACTS_CHANGED, contact_id, 0); emit_event!(context, Event::CONTACTS_CHANGED, contact_id, 0);
inviter_progress!(context, contact_id, 600); inviter_progress!(context, contact_id, 600);
@@ -528,7 +525,7 @@ pub fn handle_securejoin_handshake(
let field_grpid = lookup_field(mimeparser, "Secure-Join-Group").unwrap_or_default(); let field_grpid = lookup_field(mimeparser, "Secure-Join-Group").unwrap_or_default();
let (group_chat_id, _, _) = chat::get_chat_id_by_grpid(context, &field_grpid); let (group_chat_id, _, _) = chat::get_chat_id_by_grpid(context, &field_grpid);
if group_chat_id == 0 { if group_chat_id == 0 {
error!(context, 0, "Chat {} not found.", &field_grpid); error!(context, "Chat {} not found.", &field_grpid);
return ret; return ret;
} else { } else {
chat::add_contact_to_chat_ex(context, group_chat_id, contact_id, 0x1i32); chat::add_contact_to_chat_ex(context, group_chat_id, contact_id, 0x1i32);
@@ -543,7 +540,7 @@ pub fn handle_securejoin_handshake(
ret = DC_HANDSHAKE_CONTINUE_NORMAL_PROCESSING; ret = DC_HANDSHAKE_CONTINUE_NORMAL_PROCESSING;
} }
if context.bob.read().unwrap().expects != DC_VC_CONTACT_CONFIRM { if context.bob.read().unwrap().expects != DC_VC_CONTACT_CONFIRM {
info!(context, 0, "Message belongs to a different handshake.",); info!(context, "Message belongs to a different handshake.",);
return ret; return ret;
} }
let cond = { let cond = {
@@ -554,7 +551,7 @@ pub fn handle_securejoin_handshake(
if cond { if cond {
warn!( warn!(
context, context,
0, "Message out of sync or belongs to a different handshake.", "Message out of sync or belongs to a different handshake.",
); );
return ret; return ret;
} }
@@ -597,7 +594,7 @@ pub fn handle_securejoin_handshake(
let cg_member_added = let cg_member_added =
lookup_field(mimeparser, "Chat-Group-Member-Added").unwrap_or_default(); lookup_field(mimeparser, "Chat-Group-Member-Added").unwrap_or_default();
if join_vg && !addr_equals_self(context, cg_member_added) { if join_vg && !addr_equals_self(context, cg_member_added) {
info!(context, 0, "Message belongs to a different handshake (scaled up contact anyway to allow creation of group)."); info!(context, "Message belongs to a different handshake (scaled up contact anyway to allow creation of group).");
return ret; return ret;
} }
secure_connection_established(context, contact_chat_id); secure_connection_established(context, contact_chat_id);
@@ -621,18 +618,18 @@ pub fn handle_securejoin_handshake(
============================================================ */ ============================================================ */
if let Ok(contact) = Contact::get_by_id(context, contact_id) { if let Ok(contact) = Contact::get_by_id(context, contact_id) {
if contact.is_verified() == VerifiedStatus::Unverified { if contact.is_verified() == VerifiedStatus::Unverified {
warn!(context, 0, "vg-member-added-received invalid.",); warn!(context, "vg-member-added-received invalid.",);
return ret; return ret;
} }
inviter_progress!(context, contact_id, 800); inviter_progress!(context, contact_id, 800);
inviter_progress!(context, contact_id, 1000); inviter_progress!(context, contact_id, 1000);
} else { } else {
warn!(context, 0, "vg-member-added-received invalid.",); warn!(context, "vg-member-added-received invalid.",);
return ret; return ret;
} }
} }
_ => { _ => {
warn!(context, 0, "invalid step: {}", step); warn!(context, "invalid step: {}", step);
} }
} }
if ret == DC_HANDSHAKE_STOP_NORMAL_PROCESSING { if ret == DC_HANDSHAKE_STOP_NORMAL_PROCESSING {
@@ -694,7 +691,7 @@ fn could_not_establish_secure_connection(
); );
chat::add_device_msg(context, contact_chat_id, &msg); chat::add_device_msg(context, contact_chat_id, &msg);
error!(context, 0, "{} ({})", &msg, details); error!(context, "{} ({})", &msg, details);
} }
fn mark_peer_as_verified(context: &Context, fingerprint: impl AsRef<str>) -> Result<(), Error> { fn mark_peer_as_verified(context: &Context, fingerprint: impl AsRef<str>) -> Result<(), Error> {
@@ -723,13 +720,13 @@ fn encrypted_and_signed(
expected_fingerprint: impl AsRef<str>, expected_fingerprint: impl AsRef<str>,
) -> bool { ) -> bool {
if !mimeparser.e2ee_helper.encrypted { if !mimeparser.e2ee_helper.encrypted {
warn!(mimeparser.context, 0, "Message not encrypted.",); warn!(mimeparser.context, "Message not encrypted.",);
false false
} else if mimeparser.e2ee_helper.signatures.len() <= 0 { } else if mimeparser.e2ee_helper.signatures.len() <= 0 {
warn!(mimeparser.context, 0, "Message not signed.",); warn!(mimeparser.context, "Message not signed.",);
false false
} else if expected_fingerprint.as_ref().is_empty() { } else if expected_fingerprint.as_ref().is_empty() {
warn!(mimeparser.context, 0, "Fingerprint for comparison missing.",); warn!(mimeparser.context, "Fingerprint for comparison missing.",);
false false
} else if !mimeparser } else if !mimeparser
.e2ee_helper .e2ee_helper
@@ -738,7 +735,6 @@ fn encrypted_and_signed(
{ {
warn!( warn!(
mimeparser.context, mimeparser.context,
0,
"Message does not match expected fingerprint {}.", "Message does not match expected fingerprint {}.",
expected_fingerprint.as_ref(), expected_fingerprint.as_ref(),
); );

View File

@@ -45,7 +45,7 @@ impl Smtp {
/// Connect using the provided login params /// Connect using the provided login params
pub fn connect(&mut self, context: &Context, lp: &LoginParam) -> bool { pub fn connect(&mut self, context: &Context, lp: &LoginParam) -> bool {
if self.is_connected() { if self.is_connected() {
warn!(context, 0, "SMTP already connected."); warn!(context, "SMTP already connected.");
return true; return true;
} }
@@ -119,7 +119,7 @@ impl Smtp {
true true
} }
Err(err) => { Err(err) => {
warn!(context, 0, "SMTP: failed to establish connection {:?}", err); warn!(context, "SMTP: failed to establish connection {:?}", err);
false false
} }
} }
@@ -151,7 +151,7 @@ impl Smtp {
1 1
} }
Err(err) => { Err(err) => {
warn!(context, 0, "SMTP failed to send message: {}", err); warn!(context, "SMTP failed to send message: {}", err);
self.error = Some(format!("{}", err)); self.error = Some(format!("{}", err));
0 0
} }

View File

@@ -35,7 +35,7 @@ impl Sql {
self.in_use.remove(); self.in_use.remove();
// drop closes the connection // drop closes the connection
info!(context, 0, "Database closed."); info!(context, "Database closed.");
} }
// return true on success, false on failure // return true on success, false on failure
@@ -176,7 +176,7 @@ impl Sql {
rusqlite::types::Type::Null, rusqlite::types::Type::Null,
))) => None, ))) => None,
Err(err) => { Err(err) => {
error!(context, 0, "sql: Failed query_row: {}", err); error!(context, "sql: Failed query_row: {}", err);
None None
} }
} }
@@ -193,7 +193,7 @@ impl Sql {
value: Option<&str>, value: Option<&str>,
) -> Result<()> { ) -> Result<()> {
if !self.is_open() { if !self.is_open() {
error!(context, 0, "set_config(): Database not ready."); error!(context, "set_config(): Database not ready.");
return Err(Error::SqlNoConnection); return Err(Error::SqlNoConnection);
} }
@@ -227,7 +227,7 @@ impl Sql {
match res { match res {
Ok(_) => Ok(()), Ok(_) => Ok(()),
Err(err) => { Err(err) => {
error!(context, 0, "set_config(): Cannot change value. {:?}", &err); error!(context, "set_config(): Cannot change value. {:?}", &err);
Err(err.into()) Err(err.into())
} }
} }
@@ -259,6 +259,20 @@ impl Sql {
self.get_config(context, key).and_then(|s| s.parse().ok()) self.get_config(context, key).and_then(|s| s.parse().ok())
} }
pub fn get_config_bool(&self, context: &Context, key: impl AsRef<str>) -> bool {
// Not the most obvious way to encode bool as string, but it is matter
// of backward compatibility.
self.get_config_int(context, key).unwrap_or_default() > 0
}
pub fn set_config_bool<T>(&self, context: &Context, key: T, value: bool) -> Result<()>
where
T: AsRef<str>,
{
let value = if value { Some("1") } else { None };
self.set_config(context, key, value)
}
pub fn set_config_int64( pub fn set_config_int64(
&self, &self,
context: &Context, context: &Context,
@@ -303,7 +317,6 @@ fn open(
if sql.is_open() { if sql.is_open() {
error!( error!(
context, context,
0,
"Cannot open, database \"{:?}\" already opened.", "Cannot open, database \"{:?}\" already opened.",
dbfile.as_ref(), dbfile.as_ref(),
); );
@@ -337,7 +350,6 @@ fn open(
if !sql.table_exists("config") { if !sql.table_exists("config") {
info!( info!(
context, context,
0,
"First time init: creating tables in {:?}.", "First time init: creating tables in {:?}.",
dbfile.as_ref(), dbfile.as_ref(),
); );
@@ -453,7 +465,6 @@ fn open(
{ {
error!( error!(
context, context,
0,
"Cannot create tables in new database \"{:?}\".", "Cannot create tables in new database \"{:?}\".",
dbfile.as_ref(), dbfile.as_ref(),
); );
@@ -674,7 +685,7 @@ fn open(
sql.set_config_int(context, "dbversion", 46)?; sql.set_config_int(context, "dbversion", 46)?;
} }
if dbversion < 47 { if dbversion < 47 {
info!(context, 0, "[migration] v47"); info!(context, "[migration] v47");
sql.execute( sql.execute(
"ALTER TABLE jobs ADD COLUMN tries INTEGER DEFAULT 0;", "ALTER TABLE jobs ADD COLUMN tries INTEGER DEFAULT 0;",
params![], params![],
@@ -683,7 +694,7 @@ fn open(
sql.set_config_int(context, "dbversion", 47)?; sql.set_config_int(context, "dbversion", 47)?;
} }
if dbversion < 48 { if dbversion < 48 {
info!(context, 0, "[migration] v48"); info!(context, "[migration] v48");
sql.execute( sql.execute(
"ALTER TABLE msgs ADD COLUMN move_state INTEGER DEFAULT 1;", "ALTER TABLE msgs ADD COLUMN move_state INTEGER DEFAULT 1;",
params![], params![],
@@ -693,7 +704,7 @@ fn open(
sql.set_config_int(context, "dbversion", 48)?; sql.set_config_int(context, "dbversion", 48)?;
} }
if dbversion < 49 { if dbversion < 49 {
info!(context, 0, "[migration] v49"); info!(context, "[migration] v49");
sql.execute( sql.execute(
"ALTER TABLE chats ADD COLUMN gossiped_timestamp INTEGER DEFAULT 0;", "ALTER TABLE chats ADD COLUMN gossiped_timestamp INTEGER DEFAULT 0;",
params![], params![],
@@ -702,7 +713,7 @@ fn open(
sql.set_config_int(context, "dbversion", 49)?; sql.set_config_int(context, "dbversion", 49)?;
} }
if dbversion < 50 { if dbversion < 50 {
info!(context, 0, "[migration] v50"); info!(context, "[migration] v50");
if 0 != exists_before_update { if 0 != exists_before_update {
sql.set_config_int(context, "show_emails", 2)?; sql.set_config_int(context, "show_emails", 2)?;
} }
@@ -710,7 +721,7 @@ fn open(
sql.set_config_int(context, "dbversion", 50)?; sql.set_config_int(context, "dbversion", 50)?;
} }
if dbversion < 53 { if dbversion < 53 {
info!(context, 0, "[migration] v53"); info!(context, "[migration] v53");
sql.execute( 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);", "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![] params![]
@@ -743,7 +754,7 @@ fn open(
sql.set_config_int(context, "dbversion", 53)?; sql.set_config_int(context, "dbversion", 53)?;
} }
if dbversion < 54 { if dbversion < 54 {
info!(context, 0, "[migration] v54"); info!(context, "[migration] v54");
sql.execute( sql.execute(
"ALTER TABLE msgs ADD COLUMN location_id INTEGER DEFAULT 0;", "ALTER TABLE msgs ADD COLUMN location_id INTEGER DEFAULT 0;",
params![], params![],
@@ -783,7 +794,7 @@ fn open(
// for newer versions, we copy files always to the blob directory and store relative paths. // for newer versions, we copy files always to the blob directory and store relative paths.
// this snippet converts older databases and can be removed after some time. // this snippet converts older databases and can be removed after some time.
info!(context, 0, "[open] update file paths"); info!(context, "[open] update file paths");
let repl_from = sql let repl_from = sql
.get_config(context, "backup_for") .get_config(context, "backup_for")
@@ -810,7 +821,7 @@ fn open(
} }
} }
info!(context, 0, "Opened {:?}.", dbfile.as_ref(),); info!(context, "Opened {:?}.", dbfile.as_ref(),);
Ok(()) Ok(())
} }
@@ -825,7 +836,6 @@ where
Err(err) => { Err(err) => {
error!( error!(
context, context,
0,
"execute failed: {:?} for {}", "execute failed: {:?} for {}",
&err, &err,
querystr.as_ref() querystr.as_ref()
@@ -842,7 +852,6 @@ pub fn try_execute(context: &Context, sql: &Sql, querystr: impl AsRef<str>) -> R
Err(err) => { Err(err) => {
warn!( warn!(
context, context,
0,
"Try-execute for \"{}\" failed: {}", "Try-execute for \"{}\" failed: {}",
querystr.as_ref(), querystr.as_ref(),
&err, &err,
@@ -886,7 +895,7 @@ pub fn get_rowid_with_conn(
Err(err) => { Err(err) => {
error!( error!(
context, context,
0, "sql: Failed to retrieve rowid: {} in {}", err, query "sql: Failed to retrieve rowid: {} in {}", err, query
); );
0 0
} }
@@ -933,7 +942,7 @@ pub fn get_rowid2_with_conn(
) { ) {
Ok(id) => id, Ok(id) => id,
Err(err) => { Err(err) => {
error!(context, 0, "sql: Failed to retrieve rowid2: {}", err); error!(context, "sql: Failed to retrieve rowid2: {}", err);
0 0
} }
} }
@@ -943,7 +952,7 @@ pub fn housekeeping(context: &Context) {
let mut files_in_use = HashSet::new(); let mut files_in_use = HashSet::new();
let mut unreferenced_count = 0; let mut unreferenced_count = 0;
info!(context, 0, "Start housekeeping..."); info!(context, "Start housekeeping...");
maybe_add_from_param( maybe_add_from_param(
context, context,
&mut files_in_use, &mut files_in_use,
@@ -983,10 +992,10 @@ pub fn housekeeping(context: &Context) {
}, },
) )
.unwrap_or_else(|err| { .unwrap_or_else(|err| {
warn!(context, 0, "sql: failed query: {}", err); warn!(context, "sql: failed query: {}", err);
}); });
info!(context, 0, "{} files in use.", files_in_use.len(),); info!(context, "{} files in use.", files_in_use.len(),);
/* go through directory and delete unused files */ /* go through directory and delete unused files */
let p = std::path::Path::new(as_str(context.get_blobdir())); let p = std::path::Path::new(as_str(context.get_blobdir()));
match std::fs::read_dir(p) { match std::fs::read_dir(p) {
@@ -1025,7 +1034,6 @@ pub fn housekeeping(context: &Context) {
if recently_created || recently_modified || recently_accessed { if recently_created || recently_modified || recently_accessed {
info!( info!(
context, context,
0,
"Housekeeping: Keeping new unreferenced file #{}: {:?}", "Housekeeping: Keeping new unreferenced file #{}: {:?}",
unreferenced_count, unreferenced_count,
entry.file_name(), entry.file_name(),
@@ -1037,7 +1045,6 @@ pub fn housekeeping(context: &Context) {
} }
info!( info!(
context, context,
0,
"Housekeeping: Deleting unreferenced file #{}: {:?}", "Housekeeping: Deleting unreferenced file #{}: {:?}",
unreferenced_count, unreferenced_count,
entry.file_name() entry.file_name()
@@ -1049,7 +1056,6 @@ pub fn housekeeping(context: &Context) {
Err(err) => { Err(err) => {
warn!( warn!(
context, context,
0,
"Housekeeping: Cannot open {}. ({})", "Housekeeping: Cannot open {}. ({})",
as_str(context.get_blobdir()), as_str(context.get_blobdir()),
err err
@@ -1057,7 +1063,7 @@ pub fn housekeeping(context: &Context) {
} }
} }
info!(context, 0, "Housekeeping done.",); info!(context, "Housekeeping done.",);
} }
fn is_file_in_use(files_in_use: &HashSet<String>, namespc_opt: Option<&str>, name: &str) -> bool { fn is_file_in_use(files_in_use: &HashSet<String>, namespc_opt: Option<&str>, name: &str) -> bool {
@@ -1105,7 +1111,7 @@ fn maybe_add_from_param(
}, },
) )
.unwrap_or_else(|err| { .unwrap_or_else(|err| {
warn!(context, 0, "sql: failed to add_from_param: {}", err); warn!(context, "sql: failed to add_from_param: {}", err);
}); });
} }

View File

@@ -6,13 +6,15 @@ import os
import re import re
if __name__ == "__main__": if __name__ == "__main__":
if Path('src/top_evil_rs.py').exists():
os.chdir('src')
filestats = [] filestats = []
for fn in Path(".").glob("**/*.rs"): for fn in Path(".").glob("**/*.rs"):
s = fn.read_text() s = fn.read_text()
s = re.sub(r"(?m)///.*$", "", s) # remove comments s = re.sub(r"(?m)///.*$", "", s) # remove comments
unsafe = s.count("unsafe") unsafe = s.count("unsafe")
free = s.count("free(") free = s.count("free(")
gotoblocks = s.count("ok_to_continue") gotoblocks = s.count("ok_to_continue") + s.count('OK_TO_CONTINUE')
filestats.append((fn, unsafe, free, gotoblocks)) filestats.append((fn, unsafe, free, gotoblocks))
sum_unsafe, sum_free, sum_gotoblocks = 0, 0, 0 sum_unsafe, sum_free, sum_gotoblocks = 0, 0, 0

View File

@@ -12,7 +12,6 @@ use deltachat::contact::*;
use deltachat::context::*; use deltachat::context::*;
use deltachat::dc_imex::*; use deltachat::dc_imex::*;
use deltachat::dc_tools::*; use deltachat::dc_tools::*;
use deltachat::key::*;
use deltachat::keyring::*; use deltachat::keyring::*;
use deltachat::oauth2::*; use deltachat::oauth2::*;
use deltachat::pgp::*; use deltachat::pgp::*;
@@ -91,7 +90,7 @@ unsafe fn stress_functions(context: &Context) {
assert!(dc_delete_file(context, "$BLOBDIR/dada")); assert!(dc_delete_file(context, "$BLOBDIR/dada"));
assert!(dc_create_folder(context, "$BLOBDIR/foobar-folder")); assert!(dc_create_folder(context, "$BLOBDIR/foobar-folder"));
assert!(dc_file_exist(context, "$BLOBDIR/foobar-folder",)); assert!(dc_file_exist(context, "$BLOBDIR/foobar-folder",));
assert!(dc_delete_file(context, "$BLOBDIR/foobar-folder")); assert!(!dc_delete_file(context, "$BLOBDIR/foobar-folder"));
let fn0: *mut libc::c_char = dc_get_fine_pathNfilename( let fn0: *mut libc::c_char = dc_get_fine_pathNfilename(
context, context,
b"$BLOBDIR\x00" as *const u8 as *const libc::c_char, b"$BLOBDIR\x00" as *const u8 as *const libc::c_char,
@@ -461,136 +460,111 @@ unsafe fn stress_functions(context: &Context) {
#[test] #[test]
#[ignore] // is too expensive #[ignore] // is too expensive
fn test_encryption_decryption() { fn test_encryption_decryption() {
unsafe { let (public_key, private_key) = dc_pgp_create_keypair("foo@bar.de").unwrap();
let mut bad_data: [libc::c_uchar; 4096] = [0; 4096];
let mut i_0: libc::c_int = 0i32;
while i_0 < 4096i32 {
bad_data[i_0 as usize] = (i_0 & 0xffi32) as libc::c_uchar;
i_0 += 1
}
let mut j: libc::c_int = 0i32;
while j < 4096 / 40 { private_key.split_key().unwrap();
let bad_key = Key::from_binary(
&mut *bad_data.as_mut_ptr().offset(j as isize) as *const u8,
4096 / 2 + j,
if 0 != j & 1 {
KeyType::Public
} else {
KeyType::Private
},
);
assert!(bad_key.is_none()); let (public_key2, private_key2) = dc_pgp_create_keypair("two@zwo.de").unwrap();
j += 1
}
let (public_key, private_key) = dc_pgp_create_keypair("foo@bar.de").unwrap(); assert_ne!(public_key, public_key2);
private_key.split_key().unwrap(); let original_text = b"This is a test";
let mut keyring = Keyring::default();
keyring.add_owned(public_key.clone());
keyring.add_ref(&public_key2);
let (public_key2, private_key2) = dc_pgp_create_keypair("two@zwo.de").unwrap(); let ctext_signed = dc_pgp_pk_encrypt(original_text, &keyring, Some(&private_key)).unwrap();
assert!(!ctext_signed.is_empty());
assert!(ctext_signed.starts_with("-----BEGIN PGP MESSAGE-----"));
assert_ne!(public_key, public_key2); let ctext_unsigned = dc_pgp_pk_encrypt(original_text, &keyring, None).unwrap();
assert!(!ctext_unsigned.is_empty());
assert!(ctext_unsigned.starts_with("-----BEGIN PGP MESSAGE-----"));
let original_text = b"This is a test"; let mut keyring = Keyring::default();
let mut keyring = Keyring::default(); keyring.add_owned(private_key);
keyring.add_owned(public_key.clone());
keyring.add_ref(&public_key2);
let ctext_signed = dc_pgp_pk_encrypt(original_text, &keyring, Some(&private_key)).unwrap(); let mut public_keyring = Keyring::default();
assert!(!ctext_signed.is_empty()); public_keyring.add_ref(&public_key);
assert!(ctext_signed.starts_with("-----BEGIN PGP MESSAGE-----"));
let ctext_unsigned = dc_pgp_pk_encrypt(original_text, &keyring, None).unwrap(); let mut public_keyring2 = Keyring::default();
assert!(!ctext_unsigned.is_empty()); public_keyring2.add_owned(public_key2.clone());
assert!(ctext_unsigned.starts_with("-----BEGIN PGP MESSAGE-----"));
let mut keyring = Keyring::default(); let mut valid_signatures: HashSet<String> = Default::default();
keyring.add_owned(private_key);
let mut public_keyring = Keyring::default(); let plain = dc_pgp_pk_decrypt(
public_keyring.add_ref(&public_key); ctext_signed.as_bytes(),
&keyring,
&public_keyring,
Some(&mut valid_signatures),
)
.unwrap();
let mut public_keyring2 = Keyring::default(); assert_eq!(plain, original_text,);
public_keyring2.add_owned(public_key2.clone()); assert_eq!(valid_signatures.len(), 1);
let mut valid_signatures: HashSet<String> = Default::default(); valid_signatures.clear();
let plain = dc_pgp_pk_decrypt( let empty_keyring = Keyring::default();
ctext_signed.as_bytes(), let plain = dc_pgp_pk_decrypt(
&keyring, ctext_signed.as_bytes(),
&public_keyring, &keyring,
Some(&mut valid_signatures), &empty_keyring,
) Some(&mut valid_signatures),
.unwrap(); )
.unwrap();
assert_eq!(plain, original_text);
assert_eq!(valid_signatures.len(), 0);
assert_eq!(plain, original_text,); valid_signatures.clear();
assert_eq!(valid_signatures.len(), 1);
valid_signatures.clear(); let plain = dc_pgp_pk_decrypt(
ctext_signed.as_bytes(),
&keyring,
&public_keyring2,
Some(&mut valid_signatures),
)
.unwrap();
assert_eq!(plain, original_text);
assert_eq!(valid_signatures.len(), 0);
let empty_keyring = Keyring::default(); valid_signatures.clear();
let plain = dc_pgp_pk_decrypt(
ctext_signed.as_bytes(),
&keyring,
&empty_keyring,
Some(&mut valid_signatures),
)
.unwrap();
assert_eq!(plain, original_text);
assert_eq!(valid_signatures.len(), 0);
valid_signatures.clear(); public_keyring2.add_ref(&public_key);
let plain = dc_pgp_pk_decrypt( let plain = dc_pgp_pk_decrypt(
ctext_signed.as_bytes(), ctext_signed.as_bytes(),
&keyring, &keyring,
&public_keyring2, &public_keyring2,
Some(&mut valid_signatures), Some(&mut valid_signatures),
) )
.unwrap(); .unwrap();
assert_eq!(plain, original_text); assert_eq!(plain, original_text);
assert_eq!(valid_signatures.len(), 0); assert_eq!(valid_signatures.len(), 1);
valid_signatures.clear(); valid_signatures.clear();
public_keyring2.add_ref(&public_key); let plain = dc_pgp_pk_decrypt(
ctext_unsigned.as_bytes(),
&keyring,
&public_keyring,
Some(&mut valid_signatures),
)
.unwrap();
let plain = dc_pgp_pk_decrypt( assert_eq!(plain, original_text);
ctext_signed.as_bytes(),
&keyring,
&public_keyring2,
Some(&mut valid_signatures),
)
.unwrap();
assert_eq!(plain, original_text);
assert_eq!(valid_signatures.len(), 1);
valid_signatures.clear(); valid_signatures.clear();
let plain = dc_pgp_pk_decrypt( let mut keyring = Keyring::default();
ctext_unsigned.as_bytes(), keyring.add_ref(&private_key2);
&keyring, let mut public_keyring = Keyring::default();
&public_keyring, public_keyring.add_ref(&public_key);
Some(&mut valid_signatures),
)
.unwrap();
assert_eq!(plain, original_text); let plain =
dc_pgp_pk_decrypt(ctext_signed.as_bytes(), &keyring, &public_keyring, None).unwrap();
valid_signatures.clear(); assert_eq!(plain, original_text);
let mut keyring = Keyring::default();
keyring.add_ref(&private_key2);
let mut public_keyring = Keyring::default();
public_keyring.add_ref(&public_key);
let plain =
dc_pgp_pk_decrypt(ctext_signed.as_bytes(), &keyring, &public_keyring, None).unwrap();
assert_eq!(plain, original_text);
}
} }
unsafe extern "C" fn cb( unsafe extern "C" fn cb(