Compare commits

..

8 Commits

Author SHA1 Message Date
holger krekel
b2747a629d address @dignifiedquire comment 2019-09-19 19:28:39 +02:00
holger krekel
724ba6776e refactor rfc724_mid parsing and creation to avoid char*, add tests 2019-09-19 16:38:47 +02:00
holger krekel
89eef0158d more rfc724_mid cleanup 2019-09-19 15:02:46 +02:00
holger krekel
8e13f33467 factory.rfc724_mid is a String now (instead of C-Char*) 2019-09-19 13:56:07 +02:00
holger krekel
0ceab61a05 make dc_create_outgoing_rfc724_mid safe and simplify call sites 2019-09-19 13:46:30 +02:00
Friedel Ziegelmayer
83f3e23297 improve python caching (#468)
(@dignifiedquire and @hpk42) 
- introduce rust-caching to python test runs 
- skip release and ffi runs, they are check using python bindings
- shuffle files such that ci_scripts/ contains all the ci scripts
- partly parallelize python tox runs
2019-09-19 13:10:19 +02:00
B. Petersen
4f880932ae change oder of typedefs, function-definitions and defines
as c is top-down, we start with the typedefs
so that functions can use them freely.
after that, the functions are declared
and finally the #defines (for less noise in the function sections).
grouping is done by classes.
2019-09-19 12:58:26 +02:00
B. Petersen
62e8c2497c add missing doxygen commands, fix typo 2019-09-19 12:58:26 +02:00
11 changed files with 285 additions and 280 deletions

View File

@@ -11,6 +11,16 @@ extern "C" {
#endif
typedef struct _dc_context dc_context_t;
typedef struct _dc_array dc_array_t;
typedef struct _dc_chatlist dc_chatlist_t;
typedef struct _dc_chat dc_chat_t;
typedef struct _dc_msg dc_msg_t;
typedef struct _dc_contact dc_contact_t;
typedef struct _dc_lot dc_lot_t;
typedef struct _dc_provider dc_provider_t;
/**
* @mainpage Getting started
*
@@ -189,13 +199,6 @@ extern "C" {
* SQLite database for offline functionality and for account-related
* settings.
*/
typedef struct _dc_context dc_context_t;
typedef struct _dc_array dc_array_t;
typedef struct _dc_chatlist dc_chatlist_t;
typedef struct _dc_chat dc_chat_t;
typedef struct _dc_msg dc_msg_t;
typedef struct _dc_contact dc_contact_t;
typedef struct _dc_lot dc_lot_t;
/**
@@ -442,112 +445,6 @@ char* dc_get_info (dc_context_t* context);
*/
char* dc_get_oauth2_url (dc_context_t* context, const char* addr, const char* redirect_uri);
/**
* Opaque object containing information about one single email provider.
*/
typedef struct _dc_provider dc_provider_t;
/**
* Create a provider struct for the given domain.
*
* @param doamin The domain to get provider info for.
* @return a dc_provider_t struct which can be used with the dc_provider_get_*
* accessor functions. If no provider info is found, NULL will be
* returned.
*/
dc_provider_t* dc_provider_new_from_domain (char* domain);
/**
* Create a provider struct for the given email address.
*
* The provider is extracted from the email address and it's information is returned.
*
* @param email The user's email address to extract the provider info form.
* @return a dc_provider_t struct which can be used with the dc_provider_get_*
* accessor functions. If no provider info is found, NULL will be
* returned.
*/
dc_provider_t* dc_provider_new_from_email (char* email);
/**
* URL of the overview page.
*
* This URL allows linking to the providers page on providers.delta.chat.
*
* @param provider The dc_provider_t struct.
* @return A string which must be free()d.
*/
char* dc_provider_get_overview_page (const dc_provider_t* provider);
/**
* The provider's name.
*
* The name of the provider, e.g. "POSTEO".
*
* @param provider The dc_provider_t struct.
* @return A string which must be free()d.
*/
char* dc_provider_get_name (const dc_provider_t* provider);
/**
* The markdown content of the providers page.
*
* This contains the preparation steps or additional information if the status
* is DC_PROVIDER_STATUS_BROKEN.
*
* @param provider The dc_provider_t struct.
* @return A string which must be free()d.
*/
char* dc_provider_get_markdown (const dc_provider_t* provider);
/**
* Date of when the state was last checked/updated.
*
* This is returned as a string.
*
* @param provider The dc_provider_t struct.
* @return A string which must be free()d.
*/
char* dc_provider_get_status_date (const dc_provider_t* provider);
/**
* Whether DC works with this provider.
*
* Can be one of @ref DC_PROVIDER_STATUS_OK, @ref
* DC_PROVIDER_STATUS_PREPARATION and @ref DC_PROVIDER_STATUS_BROKEN.
*
* @param provider The dc_provider_t struct.
* @return The status as a constant number.
*/
int dc_provider_get_status (const dc_provider_t* provider);
/**
* Free the provider info struct.
*
* @param provider The dc_provider_t struct.
*/
void dc_provider_unref (const dc_provider_t* provider);
/**
* Provider status returned by dc_provider_get_status().
*
* Works right out of the box without any preperation steps needed
*/
#define DC_PROVIDER_STATUS_OK 1
/**
* Provider status returned by dc_provider_get_status().
*
* Works, but preparation steps are needed
*/
#define DC_PROVIDER_STATUS_PREPARATION 2
/**
* Provider status returned by dc_provider_get_status().
*
* Doesn't work (too unstable to use falls also in this category)
*/
#define DC_PROVIDER_STATUS_BROKEN 3
// connect
@@ -3524,6 +3421,110 @@ int dc_contact_is_blocked (const dc_contact_t* contact);
int dc_contact_is_verified (dc_contact_t* contact);
/**
* @class dc_provider_t
*
* Opaque object containing information about one single email provider.
*/
/**
* Create a provider struct for the given domain.
*
* @memberof dc_provider_t
* @param domain The domain to get provider info for.
* @return a dc_provider_t struct which can be used with the dc_provider_get_*
* accessor functions. If no provider info is found, NULL will be
* returned.
*/
dc_provider_t* dc_provider_new_from_domain (char* domain);
/**
* Create a provider struct for the given email address.
*
* The provider is extracted from the email address and it's information is returned.
*
* @memberof dc_provider_t
* @param email The user's email address to extract the provider info form.
* @return a dc_provider_t struct which can be used with the dc_provider_get_*
* accessor functions. If no provider info is found, NULL will be
* returned.
*/
dc_provider_t* dc_provider_new_from_email (char* email);
/**
* URL of the overview page.
*
* This URL allows linking to the providers page on providers.delta.chat.
*
* @memberof dc_provider_t
* @param provider The dc_provider_t struct.
* @return A string which must be free()d.
*/
char* dc_provider_get_overview_page (const dc_provider_t* provider);
/**
* The provider's name.
*
* The name of the provider, e.g. "POSTEO".
*
* @memberof dc_provider_t
* @param provider The dc_provider_t struct.
* @return A string which must be free()d.
*/
char* dc_provider_get_name (const dc_provider_t* provider);
/**
* The markdown content of the providers page.
*
* This contains the preparation steps or additional information if the status
* is @ref DC_PROVIDER_STATUS_BROKEN.
*
* @memberof dc_provider_t
* @param provider The dc_provider_t struct.
* @return A string which must be free()d.
*/
char* dc_provider_get_markdown (const dc_provider_t* provider);
/**
* Date of when the state was last checked/updated.
*
* This is returned as a string.
*
* @memberof dc_provider_t
* @param provider The dc_provider_t struct.
* @return A string which must be free()d.
*/
char* dc_provider_get_status_date (const dc_provider_t* provider);
/**
* Whether DC works with this provider.
*
* Can be one of @ref DC_PROVIDER_STATUS_OK, @ref
* DC_PROVIDER_STATUS_PREPARATION and @ref DC_PROVIDER_STATUS_BROKEN.
*
* @memberof dc_provider_t
* @param provider The dc_provider_t struct.
* @return The status as a constant number.
*/
int dc_provider_get_status (const dc_provider_t* provider);
/**
* Free the provider info struct.
*
* @memberof dc_provider_t
* @param provider The dc_provider_t struct.
*/
void dc_provider_unref (const dc_provider_t* provider);
/**
* @class dc_lot_t
*
@@ -4131,6 +4132,41 @@ void dc_array_add_id (dc_array_t*, uint32_t); // depreca
#define DC_SHOW_EMAILS_ALL 2
/**
* @defgroup DC_PROVIDER_STATUS DC_PROVIDER_STATUS
*
* These constants are used as return values for dc_provider_get_status().
*
* @addtogroup DC_PROVIDER_STATUS
* @{
*/
/**
* Provider status returned by dc_provider_get_status().
*
* Works right out of the box without any preperation steps needed
*/
#define DC_PROVIDER_STATUS_OK 1
/**
* Provider status returned by dc_provider_get_status().
*
* Works, but preparation steps are needed
*/
#define DC_PROVIDER_STATUS_PREPARATION 2
/**
* Provider status returned by dc_provider_get_status().
*
* Doesn't work (too unstable to use falls also in this category)
*/
#define DC_PROVIDER_STATUS_BROKEN 3
/**
* @}
*/
/*
* TODO: Strings need some doumentation about used placeholders.
*

View File

@@ -1,6 +1,5 @@
use std::ffi::CString;
use std::path::{Path, PathBuf};
use std::ptr;
use crate::chatlist::*;
use crate::config::*;
@@ -16,7 +15,6 @@ use crate::message::*;
use crate::param::*;
use crate::sql::{self, Sql};
use crate::stock::StockMessage;
use crate::x::*;
/// An object representing a single chat in memory.
/// Chat objects are created using eg. `Chat::load_from_db`
@@ -272,7 +270,7 @@ impl Chat {
Chattype::Group | Chattype::VerifiedGroup => Some(self.grpid.as_str()),
_ => None,
};
dc_create_outgoing_rfc724_mid_safe(grpid, &from)
dc_create_outgoing_rfc724_mid(grpid, &from)
};
if self.typ == Chattype::Single {
@@ -1840,12 +1838,7 @@ pub fn get_chat_id_by_grpid(context: &Context, grpid: impl AsRef<str>) -> (u32,
}
pub fn add_device_msg(context: &Context, chat_id: u32, text: impl AsRef<str>) {
let rfc724_mid = unsafe {
dc_create_outgoing_rfc724_mid(
ptr::null(),
b"@device\x00" as *const u8 as *const libc::c_char,
)
};
let rfc724_mid = dc_create_outgoing_rfc724_mid(None, "@device");
if context.sql.execute(
"INSERT INTO msgs (chat_id,from_id,to_id, timestamp,type,state, txt,rfc724_mid) VALUES (?,?,?, ?,?,?, ?,?);",
@@ -1857,21 +1850,13 @@ pub fn add_device_msg(context: &Context, chat_id: u32, text: impl AsRef<str>) {
Viewtype::Text,
MessageState::InNoticed,
text.as_ref(),
as_str(rfc724_mid),
rfc724_mid,
]
).is_err() {
unsafe { free(rfc724_mid as *mut libc::c_void) };
return;
}
let msg_id = sql::get_rowid(
context,
&context.sql,
"msgs",
"rfc724_mid",
as_str(rfc724_mid),
);
unsafe { free(rfc724_mid as *mut libc::c_void) };
let msg_id = sql::get_rowid(context, &context.sql, "msgs", "rfc724_mid", &rfc724_mid);
context.call_cb(Event::MsgsChanged { chat_id, msg_id });
}

View File

@@ -362,7 +362,7 @@ impl Context {
}
if self.is_mvbox(folder) {
dc_update_msg_move_state(self, msg.rfc724_mid, MoveState::Stay);
dc_update_msg_move_state(self, &msg.rfc724_mid, MoveState::Stay);
}
// 1 = dc message, 2 = reply to dc message
@@ -374,7 +374,7 @@ impl Context {
Params::new(),
0,
);
dc_update_msg_move_state(self, msg.rfc724_mid, MoveState::Moving);
dc_update_msg_move_state(self, &msg.rfc724_mid, MoveState::Moving);
}
}
}

View File

@@ -36,7 +36,7 @@ pub struct dc_mimefactory_t<'a> {
pub recipients_names: *mut clist,
pub recipients_addr: *mut clist,
pub timestamp: i64,
pub rfc724_mid: *mut libc::c_char,
pub rfc724_mid: String,
pub loaded: dc_mimefactory_loaded_t,
pub msg: Message,
pub chat: Option<Chat>,
@@ -57,7 +57,6 @@ impl<'a> Drop for dc_mimefactory_t<'a> {
unsafe {
free(self.from_addr as *mut libc::c_void);
free(self.from_displayname as *mut libc::c_void);
free(self.rfc724_mid as *mut libc::c_void);
if !self.recipients_names.is_null() {
clist_free_content(self.recipients_names);
clist_free(self.recipients_names);
@@ -98,7 +97,7 @@ pub unsafe fn dc_mimefactory_load_msg(
recipients_names: clist_new(),
recipients_addr: clist_new(),
timestamp: 0,
rfc724_mid: ptr::null_mut(),
rfc724_mid: String::default(),
loaded: DC_MF_NOTHING_LOADED,
msg,
chat: Some(chat),
@@ -232,7 +231,7 @@ pub unsafe fn dc_mimefactory_load_msg(
factory.loaded = DC_MF_MSG_LOADED;
factory.timestamp = factory.msg.timestamp_sort;
factory.rfc724_mid = dc_strdup(factory.msg.rfc724_mid);
factory.rfc724_mid = factory.msg.rfc724_mid.clone();
factory.increation = dc_msg_is_increation(&factory.msg);
Ok(factory)
@@ -288,7 +287,7 @@ pub unsafe fn dc_mimefactory_load_mdn<'a>(
recipients_names: clist_new(),
recipients_addr: clist_new(),
timestamp: 0,
rfc724_mid: ptr::null_mut(),
rfc724_mid: String::default(),
loaded: DC_MF_NOTHING_LOADED,
msg,
chat: None,
@@ -330,7 +329,7 @@ pub unsafe fn dc_mimefactory_load_mdn<'a>(
);
load_from(&mut factory);
factory.timestamp = dc_create_smeared_timestamp(factory.context);
factory.rfc724_mid = dc_create_outgoing_rfc724_mid(0 as *const libc::c_char, factory.from_addr);
factory.rfc724_mid = dc_create_outgoing_rfc724_mid(None, as_str(factory.from_addr));
factory.loaded = DC_MF_MDN_LOADED;
Ok(factory)
@@ -447,7 +446,7 @@ pub unsafe fn dc_mimefactory_render(context: &Context, factory: &mut dc_mimefact
to,
ptr::null_mut(),
ptr::null_mut(),
dc_strdup(factory.rfc724_mid),
factory.rfc724_mid.strdup(),
in_reply_to_list,
references_list,
ptr::null_mut(),
@@ -951,7 +950,7 @@ pub unsafe fn dc_mimefactory_render(context: &Context, factory: &mut dc_mimefact
version,
as_str(factory.from_addr),
as_str(factory.from_addr),
as_str(factory.msg.rfc724_mid)
factory.msg.rfc724_mid
).strdup();
let content_type_0: *mut mailmime_content = mailmime_content_new_with_str(

View File

@@ -995,6 +995,19 @@ impl<'a> MimeParser<'a> {
assert_eq!(self.parts.len(), 1);
}
pub fn get_rfc724_mid(&mut self) -> Option<String> {
// get Message-ID from header
if let Some(field) = self.lookup_field_typ("Message-ID", MAILIMF_FIELD_MESSAGE_ID) {
unsafe {
let fld_message_id = (*field).fld_data.fld_message_id;
if !fld_message_id.is_null() {
return Some(to_string((*fld_message_id).mid_value));
}
}
}
None
}
}
impl<'a> Drop for MimeParser<'a> {
@@ -1641,6 +1654,27 @@ mod tests {
}
}
#[test]
fn test_get_rfc724_mid_exists() {
let context = dummy_context();
let raw = include_bytes!("../test-data/message/mail_with_message_id.txt");
let mut mimeparser = MimeParser::new(&context.ctx);
unsafe { mimeparser.parse(&raw[..]) };
assert_eq!(
mimeparser.get_rfc724_mid(),
Some("2dfdbde7@example.org".into())
);
}
#[test]
fn test_get_rfc724_mid_not_exists() {
let context = dummy_context();
let raw = include_bytes!("../test-data/message/issue_523.txt");
let mut mimeparser = MimeParser::new(&context.ctx);
unsafe { mimeparser.parse(&raw[..]) };
assert_eq!(mimeparser.get_rfc724_mid(), None);
}
#[test]
fn test_mimeparser_with_context() {
unsafe {

View File

@@ -85,8 +85,6 @@ pub unsafe fn dc_receive_imf(
let mut add_delete_job: libc::c_int = 0;
let mut insert_msg_id = 0;
// Message-ID from the header
let rfc724_mid = std::ptr::null_mut();
let mut sent_timestamp = 0;
let mut created_db_entries = Vec::new();
let mut create_event_to_send = Some(CreateEvent::MsgsChanged);
@@ -96,12 +94,9 @@ pub unsafe fn dc_receive_imf(
// helper method to handle early exit and memory cleanup
let cleanup = |context: &Context,
rfc724_mid: *mut libc::c_char,
create_event_to_send: &Option<CreateEvent>,
created_db_entries: &Vec<(usize, usize)>,
rr_event_to_send: &Vec<(u32, u32)>| {
free(rfc724_mid.cast());
if let Some(create_event_to_send) = create_event_to_send {
for (chat_id, msg_id) in created_db_entries {
let event = match create_event_to_send {
@@ -184,6 +179,28 @@ pub unsafe fn dc_receive_imf(
}
// Add parts
let rfc724_mid = match mime_parser.get_rfc724_mid() {
Some(x) => x,
None => {
// missing Message-IDs may come if the mail was set from this account with another
// client that relies in the SMTP server to generate one.
// true eg. for the Webmailer used in all-inkl-KAS
match dc_create_incoming_rfc724_mid(sent_timestamp, from_id, &to_ids) {
Some(x) => x.to_string(),
None => {
error!(context, "can not create incoming rfc724_mid");
cleanup(
context,
&create_event_to_send,
&created_db_entries,
&rr_event_to_send,
);
return;
}
}
}
};
if mime_parser.get_last_nonmeta().is_some() {
if let Err(err) = add_parts(
context,
@@ -195,7 +212,7 @@ pub unsafe fn dc_receive_imf(
server_folder.as_ref(),
server_uid,
&mut to_ids,
rfc724_mid,
&rfc724_mid,
&mut sent_timestamp,
&mut from_id,
from_id_blocked,
@@ -213,7 +230,6 @@ pub unsafe fn dc_receive_imf(
cleanup(
context,
rfc724_mid,
&create_event_to_send,
&created_db_entries,
&rr_event_to_send,
@@ -263,14 +279,11 @@ pub unsafe fn dc_receive_imf(
info!(
context,
"received message {} has Message-Id: {}",
server_uid,
to_string(rfc724_mid)
"received message {} has Message-Id: {}", server_uid, rfc724_mid
);
cleanup(
context,
rfc724_mid,
&create_event_to_send,
&created_db_entries,
&rr_event_to_send,
@@ -287,7 +300,7 @@ unsafe fn add_parts(
server_folder: impl AsRef<str>,
server_uid: u32,
to_ids: &mut Vec<u32>,
mut rfc724_mid: *mut libc::c_char,
rfc724_mid: &str,
sent_timestamp: &mut i64,
from_id: &mut u32,
from_id_blocked: i32,
@@ -336,25 +349,6 @@ unsafe fn add_parts(
}
}
// get Message-ID; if the header is lacking one, generate one based on fields that do never
// change. (missing Message-IDs may come if the mail was set from this account with another
// client that relies in the SMTP server to generate one.
// true eg. for the Webmailer used in all-inkl-KAS)
if let Some(field) = mime_parser.lookup_field_typ("Message-ID", MAILIMF_FIELD_MESSAGE_ID) {
let fld_message_id = (*field).fld_data.fld_message_id;
if !fld_message_id.is_null() {
rfc724_mid = dc_strdup((*fld_message_id).mid_value)
}
}
if rfc724_mid.is_null() {
rfc724_mid = dc_create_incoming_rfc724_mid(*sent_timestamp, *from_id, to_ids);
if rfc724_mid.is_null() {
cleanup(mime_in_reply_to, mime_references);
bail!("Cannot create Message-ID");
}
}
// check, if the mail is already in our database - if so, just update the folder/uid
// (if the mail was moved around) and finish. (we may get a mail twice eg. if it is
// moved between folders. make sure, this check is done eg. before securejoin-processing) */
@@ -363,12 +357,12 @@ unsafe fn add_parts(
if 0 != dc_rfc724_mid_exists(
context,
rfc724_mid,
&rfc724_mid,
&mut old_server_folder,
&mut old_server_uid,
) {
if as_str(old_server_folder) != server_folder.as_ref() || old_server_uid != server_uid {
dc_update_server_uid(context, rfc724_mid, server_folder.as_ref(), server_uid);
dc_update_server_uid(context, &rfc724_mid, server_folder.as_ref(), server_uid);
}
free(old_server_folder.cast());
@@ -667,7 +661,7 @@ unsafe fn add_parts(
}
stmt.execute(params![
as_str(rfc724_mid),
rfc724_mid,
server_folder.as_ref(),
server_uid as libc::c_int,
*chat_id as libc::c_int,
@@ -698,13 +692,8 @@ unsafe fn add_parts(
])?;
txt_raw = None;
*insert_msg_id = sql::get_rowid_with_conn(
context,
conn,
"msgs",
"rfc724_mid",
as_str(rfc724_mid),
);
*insert_msg_id =
sql::get_rowid_with_conn(context, conn, "msgs", "rfc724_mid", &rfc724_mid);
created_db_entries.push((*chat_id as usize, *insert_msg_id as usize));
}
Ok(())
@@ -867,7 +856,7 @@ unsafe fn handle_reports(
if 0 != dc_mdn_from_ext(
context,
from_id,
rfc724_mid_0,
as_str(rfc724_mid_0),
sent_timestamp,
&mut chat_id_0,
&mut msg_id,
@@ -1870,11 +1859,11 @@ unsafe fn is_msgrmsg_rfc724_mid_in_list(context: &Context, mid_list: *const clis
while !cur.is_null() {
if 0 != is_msgrmsg_rfc724_mid(
context,
(if !cur.is_null() {
(*cur).data
if !cur.is_null() {
as_str((*cur).data as *const libc::c_char)
} else {
ptr::null_mut()
}) as *const libc::c_char,
""
},
) {
return 1;
}
@@ -1889,15 +1878,15 @@ unsafe fn is_msgrmsg_rfc724_mid_in_list(context: &Context, mid_list: *const clis
}
/// Check if a message is a reply to any messenger message.
fn is_msgrmsg_rfc724_mid(context: &Context, rfc724_mid: *const libc::c_char) -> libc::c_int {
if rfc724_mid.is_null() {
fn is_msgrmsg_rfc724_mid(context: &Context, rfc724_mid: &str) -> libc::c_int {
if rfc724_mid.is_empty() {
return 0;
}
context
.sql
.exists(
"SELECT id FROM msgs WHERE rfc724_mid=? AND msgrmsg!=0 AND chat_id>9;",
params![as_str(rfc724_mid)],
params![rfc724_mid],
)
.unwrap_or_default() as libc::c_int
}

View File

@@ -572,9 +572,9 @@ pub fn dc_create_incoming_rfc724_mid(
message_timestamp: i64,
contact_id_from: u32,
contact_ids_to: &Vec<u32>,
) -> *mut libc::c_char {
) -> Option<String> {
if contact_ids_to.is_empty() {
return ptr::null_mut();
return None;
}
/* find out the largest receiver ID (we could also take the smallest, but it should be unique) */
let largest_id_to = contact_ids_to.iter().max().copied().unwrap_or_default();
@@ -583,37 +583,14 @@ pub fn dc_create_incoming_rfc724_mid(
"{}-{}-{}@stub",
message_timestamp, contact_id_from, largest_id_to
);
unsafe { result.strdup() }
Some(result)
}
/// Function generates a Message-ID that can be used for a new outgoing message.
/// - this function is called for all outgoing messages.
/// - the message ID should be globally unique
/// - do not add a counter or any private data as as this may give unneeded information to the receiver
pub unsafe fn dc_create_outgoing_rfc724_mid(
grpid: *const libc::c_char,
from_addr: *const libc::c_char,
) -> *mut libc::c_char {
let rand2 = dc_create_id();
let at_hostname = as_opt_str(strchr(from_addr, '@' as i32)).unwrap_or_else(|| "@nohost");
let ret = if !grpid.is_null() {
format!("Gr.{}.{}{}", as_str(grpid), rand2, at_hostname,)
} else {
let rand1 = dc_create_id();
format!("Mr.{}.{}{}", rand1, rand2, at_hostname)
};
ret.strdup()
}
/// Generate globally-unique message-id for a new outgoing message.
///
/// Note: Do not add a counter or any private data as as this may give
/// unneeded information to the receiver
pub fn dc_create_outgoing_rfc724_mid_safe(grpid: Option<&str>, from_addr: &str) -> String {
/// - do not add a counter or any private data as this leaks information unncessarily
pub fn dc_create_outgoing_rfc724_mid(grpid: Option<&str>, from_addr: &str) -> String {
let hostname = from_addr
.find('@')
.map(|k| &from_addr[k..])
@@ -1813,10 +1790,6 @@ mod tests {
#[test]
fn test_dc_create_incoming_rfc724_mid() {
let res = dc_create_incoming_rfc724_mid(123, 45, &vec![6, 7]);
assert_eq!(as_str(res), "123-45-7@stub");
unsafe {
free(res.cast());
}
assert_eq!(res, Some("123-45-7@stub".into()));
}
}

View File

@@ -1,4 +1,3 @@
use std::ffi::CString;
use std::net;
use std::ptr;
use std::sync::{
@@ -10,7 +9,6 @@ use std::time::{Duration, SystemTime};
use crate::constants::*;
use crate::context::Context;
use crate::dc_receive_imf::dc_receive_imf;
use crate::dc_tools::CStringExt;
use crate::dc_tools::*;
use crate::events::Event;
use crate::job::{job_add, Action};
@@ -821,10 +819,7 @@ impl Imap {
.message_id
.expect("missing message id");
if 0 == unsafe {
let message_id_c = CString::yolo(message_id);
precheck_imf(context, message_id_c.as_ptr(), folder.as_ref(), cur_uid)
} {
if 0 == unsafe { precheck_imf(context, &message_id, folder.as_ref(), cur_uid) } {
// check passed, go fetch the rest
if self.fetch_single_msg(context, &folder, cur_uid) == 0 {
info!(
@@ -1645,7 +1640,7 @@ fn get_folder_meaning(folder_name: &imap::types::Name) -> FolderMeaning {
unsafe fn precheck_imf(
context: &Context,
rfc724_mid: *const libc::c_char,
rfc724_mid: &str,
server_folder: &str,
server_uid: u32,
) -> libc::c_int {
@@ -1656,7 +1651,7 @@ unsafe fn precheck_imf(
let mut mark_seen: libc::c_int = 0i32;
msg_id = dc_rfc724_mid_exists(
context,
rfc724_mid,
&rfc724_mid,
&mut old_server_folder,
&mut old_server_uid,
);
@@ -1665,18 +1660,14 @@ unsafe fn precheck_imf(
if *old_server_folder.offset(0isize) as libc::c_int == 0i32
&& old_server_uid == 0i32 as libc::c_uint
{
info!(context, "[move] detected bbc-self {}", as_str(rfc724_mid),);
info!(context, "[move] detected bbc-self {}", rfc724_mid,);
mark_seen = 1i32
} else if as_str(old_server_folder) != server_folder {
info!(
context,
"[move] detected moved message {}",
as_str(rfc724_mid),
);
dc_update_msg_move_state(context, rfc724_mid, MoveState::Stay);
info!(context, "[move] detected moved message {}", rfc724_mid,);
dc_update_msg_move_state(context, &rfc724_mid, MoveState::Stay);
}
if as_str(old_server_folder) != server_folder || old_server_uid != server_uid {
dc_update_server_uid(context, rfc724_mid, server_folder, server_uid);
dc_update_server_uid(context, &rfc724_mid, server_folder, server_uid);
}
context.do_heuristics_moves(server_folder, msg_id);
if 0 != mark_seen {

View File

@@ -1,4 +1,3 @@
use std::ffi::CStr;
use std::ptr;
use std::time::Duration;
@@ -253,7 +252,7 @@ impl Job {
self.try_again_later(3i32, None);
}
3 => {
dc_update_server_uid(context, msg.rfc724_mid, &dest_folder, dest_uid);
dc_update_server_uid(context, &msg.rfc724_mid, &dest_folder, dest_uid);
}
0 | 2 | _ => {}
}
@@ -268,12 +267,10 @@ impl Job {
let inbox = context.inbox.read().unwrap();
if let Ok(mut msg) = dc_msg_load_from_db(context, self.foreign_id) {
if !(msg.rfc724_mid.is_null()
|| unsafe { *msg.rfc724_mid.offset(0isize) as libc::c_int == 0 })
{
if !msg.rfc724_mid.is_empty() {
let ok_to_continue1;
/* eg. device messages have no Message-ID */
if dc_rfc724_mid_cnt(context, msg.rfc724_mid) != 1 {
if dc_rfc724_mid_cnt(context, &msg.rfc724_mid) != 1 {
info!(
context,
"The message is deleted from the server when all parts are deleted.",
@@ -295,9 +292,10 @@ impl Job {
ok_to_continue = true;
}
if ok_to_continue {
let mid = unsafe { CStr::from_ptr(msg.rfc724_mid).to_str().unwrap() };
let mid = msg.rfc724_mid;
let server_folder = msg.server_folder.as_ref().unwrap();
if 0 == inbox.delete_msg(context, mid, server_folder, &mut msg.server_uid) {
if 0 == inbox.delete_msg(context, &mid, server_folder, &mut msg.server_uid)
{
self.try_again_later(-1i32, None);
ok_to_continue1 = false;
} else {
@@ -1001,8 +999,7 @@ fn add_smtp_job(context: &Context, action: Action, mimefactory: &dc_mimefactory_
let mut success: libc::c_int = 0i32;
let mut recipients: *mut libc::c_char = ptr::null_mut();
let mut param = Params::new();
let path_filename =
dc_get_fine_path_filename(context, "$BLOBDIR", as_str(mimefactory.rfc724_mid));
let path_filename = dc_get_fine_path_filename(context, "$BLOBDIR", &mimefactory.rfc724_mid);
let bytes = unsafe {
std::slice::from_raw_parts(
(*mimefactory.out).str_0 as *const u8,
@@ -1013,7 +1010,7 @@ fn add_smtp_job(context: &Context, action: Action, mimefactory: &dc_mimefactory_
error!(
context,
"Could not write message <{}> to \"{}\".",
to_string(mimefactory.rfc724_mid),
mimefactory.rfc724_mid,
path_filename.display(),
);
} else {

View File

@@ -151,7 +151,7 @@ pub struct Message {
pub timestamp_sent: i64,
pub timestamp_rcvd: i64,
pub text: Option<String>,
pub rfc724_mid: *mut libc::c_char,
pub rfc724_mid: String,
pub in_reply_to: Option<String>,
pub server_folder: Option<String>,
pub server_uid: u32,
@@ -292,8 +292,8 @@ pub unsafe fn dc_get_msg_info(context: &Context, msg_id: u32) -> *mut libc::c_ch
if !rawtxt.is_empty() {
ret += &format!("\n{}\n", rawtxt);
}
if !msg.rfc724_mid.is_null() && 0 != *msg.rfc724_mid.offset(0) as libc::c_int {
ret += &format!("\nMessage-ID: {}", as_str(msg.rfc724_mid));
if !msg.rfc724_mid.is_empty() {
ret += &format!("\nMessage-ID: {}", msg.rfc724_mid);
}
if let Some(ref server_folder) = msg.server_folder {
if server_folder != "" {
@@ -322,7 +322,7 @@ pub fn dc_msg_new(viewtype: Viewtype) -> Message {
timestamp_sent: 0,
timestamp_rcvd: 0,
text: None,
rfc724_mid: std::ptr::null_mut(),
rfc724_mid: String::default(),
in_reply_to: None,
server_folder: None,
server_uid: 0,
@@ -334,14 +334,6 @@ pub fn dc_msg_new(viewtype: Viewtype) -> Message {
}
}
impl Drop for Message {
fn drop(&mut self) {
unsafe {
free(self.rfc724_mid.cast());
}
}
}
pub fn dc_msg_get_filemime(msg: &Message) -> String {
if let Some(m) = msg.param.get(Param::MimeType) {
return m.to_string();
@@ -438,7 +430,7 @@ pub fn dc_msg_load_from_db(context: &Context, id: u32) -> Result<Message, Error>
unsafe {
let mut msg = dc_msg_new_untyped();
msg.id = row.get::<_, i32>(0)? as u32;
msg.rfc724_mid = row.get::<_, String>(1)?.strdup();
msg.rfc724_mid = row.get::<_, String>(1)?;
msg.in_reply_to = row.get::<_, Option<String>>(2)?;
msg.server_folder = row.get::<_, Option<String>>(3)?;
msg.server_uid = row.get(4)?;
@@ -996,18 +988,14 @@ pub fn dc_msg_exists(context: &Context, msg_id: u32) -> bool {
}
}
pub fn dc_update_msg_move_state(
context: &Context,
rfc724_mid: *const libc::c_char,
state: MoveState,
) -> bool {
pub fn dc_update_msg_move_state(context: &Context, rfc724_mid: &str, state: MoveState) -> bool {
// we update the move_state for all messages belonging to a given Message-ID
// so that the state stay intact when parts are deleted
sql::execute(
context,
&context.sql,
"UPDATE msgs SET move_state=? WHERE rfc724_mid=?;",
params![state as i32, as_str(rfc724_mid)],
params![state as i32, rfc724_mid],
)
.is_ok()
}
@@ -1042,13 +1030,13 @@ pub fn dc_set_msg_failed(context: &Context, msg_id: u32, error: Option<impl AsRe
pub unsafe fn dc_mdn_from_ext(
context: &Context,
from_id: u32,
rfc724_mid: *const libc::c_char,
rfc724_mid: &str,
timestamp_sent: i64,
ret_chat_id: *mut u32,
ret_msg_id: *mut u32,
) -> libc::c_int {
if from_id <= 9
|| rfc724_mid.is_null()
|| rfc724_mid.is_empty()
|| ret_chat_id.is_null()
|| ret_msg_id.is_null()
|| *ret_chat_id != 0
@@ -1064,7 +1052,7 @@ pub unsafe fn dc_mdn_from_ext(
LEFT JOIN chats c ON m.chat_id=c.id \
WHERE rfc724_mid=? AND from_id=1 \
ORDER BY m.id;",
params![as_str(rfc724_mid)],
params![rfc724_mid],
|row| {
Ok((
row.get::<_, i32>(0)?,
@@ -1168,11 +1156,11 @@ pub fn dc_get_deaddrop_msg_cnt(context: &Context) -> libc::size_t {
}
}
pub fn dc_rfc724_mid_cnt(context: &Context, rfc724_mid: *const libc::c_char) -> libc::c_int {
pub fn dc_rfc724_mid_cnt(context: &Context, rfc724_mid: &str) -> libc::c_int {
/* check the number of messages with the same rfc724_mid */
match context.sql.query_row(
"SELECT COUNT(*) FROM msgs WHERE rfc724_mid=?;",
&[as_str(rfc724_mid)],
&[rfc724_mid],
|row| row.get(0),
) {
Ok(res) => res,
@@ -1185,16 +1173,16 @@ pub fn dc_rfc724_mid_cnt(context: &Context, rfc724_mid: *const libc::c_char) ->
pub fn dc_rfc724_mid_exists(
context: &Context,
rfc724_mid: *const libc::c_char,
rfc724_mid: &str,
ret_server_folder: *mut *mut libc::c_char,
ret_server_uid: *mut u32,
) -> u32 {
if rfc724_mid.is_null() || unsafe { *rfc724_mid.offset(0) as libc::c_int } == 0 {
if rfc724_mid.is_empty() {
return 0;
}
match context.sql.query_row(
"SELECT server_folder, server_uid, id FROM msgs WHERE rfc724_mid=?",
&[as_str(rfc724_mid)],
&[rfc724_mid],
|row| {
if !ret_server_folder.is_null() {
unsafe { *ret_server_folder = row.get::<_, String>(0)?.strdup() };
@@ -1221,13 +1209,13 @@ pub fn dc_rfc724_mid_exists(
pub fn dc_update_server_uid(
context: &Context,
rfc724_mid: *const libc::c_char,
rfc724_mid: &str,
server_folder: impl AsRef<str>,
server_uid: u32,
) {
match context.sql.execute(
"UPDATE msgs SET server_folder=?, server_uid=? WHERE rfc724_mid=?;",
params![server_folder.as_ref(), server_uid, as_str(rfc724_mid)],
params![server_folder.as_ref(), server_uid, rfc724_mid],
) {
Ok(_) => {}
Err(err) => {

View File

@@ -0,0 +1,13 @@
Return-Path: <x@testrun.org>
Received: from hq5.merlinux.eu
by hq5.merlinux.eu (Dovecot) with LMTP id yRKOBakcfV1AewAAPzvFDg
; Sat, 14 Sep 2019 19:00:25 +0200
Received: from localhost (unknown 7.165.105.24])
by hq5.merlinux.eu (Postfix) with ESMTPSA id 8D9844E023;
Sat, 14 Sep 2019 19:00:22 +0200 (CEST)
message-id: <2dfdbde7@example.org>
Date: Sat, 14 Sep 2019 19:00:13 +0200
From: lmn <x@tux.org>
To: abc <abc@bcd.com>, def <def@def.de>,
jik