mirror of
https://github.com/chatmail/core.git
synced 2026-05-17 22:06:33 +03:00
Compare commits
10 Commits
cleanup/jo
...
safer_job
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ddd07b1702 | ||
|
|
34f37ccd9c | ||
|
|
8294b5eb28 | ||
|
|
bf99c0f2ba | ||
|
|
c06cf4eba2 | ||
|
|
fb7c095dad | ||
|
|
d55f6ee7c7 | ||
|
|
8a49ae2361 | ||
|
|
05ec266d9b | ||
|
|
9ec7833a50 |
@@ -505,6 +505,7 @@ int dc_chat_is_sending_locations (const dc_chat_t*);
|
||||
|
||||
dc_msg_t* dc_msg_new (dc_context_t*, int viewtype);
|
||||
void dc_msg_unref (dc_msg_t*);
|
||||
void dc_msg_empty (dc_msg_t*);
|
||||
uint32_t dc_msg_get_id (const dc_msg_t*);
|
||||
uint32_t dc_msg_get_from_id (const dc_msg_t*);
|
||||
uint32_t dc_msg_get_chat_id (const dc_msg_t*);
|
||||
|
||||
@@ -173,7 +173,7 @@ pub unsafe extern "C" fn dc_configure(context: *mut dc_context_t) {
|
||||
assert!(!context.is_null());
|
||||
let context = &*context;
|
||||
|
||||
configure::configure(context)
|
||||
dc_configure::dc_configure(context)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@@ -181,7 +181,7 @@ pub unsafe extern "C" fn dc_is_configured(context: *mut dc_context_t) -> libc::c
|
||||
assert!(!context.is_null());
|
||||
let context = &*context;
|
||||
|
||||
configure::dc_is_configured(context)
|
||||
dc_configure::dc_is_configured(context)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@@ -354,13 +354,12 @@ pub unsafe extern "C" fn dc_get_chat_id_by_contact_id(
|
||||
pub unsafe extern "C" fn dc_prepare_msg(
|
||||
context: *mut dc_context_t,
|
||||
chat_id: u32,
|
||||
msg: *mut dc_msg_t,
|
||||
msg: *mut dc_msg::dc_msg_t,
|
||||
) -> u32 {
|
||||
assert!(!context.is_null());
|
||||
assert!(!msg.is_null());
|
||||
let context = &mut *context;
|
||||
let context = &*context;
|
||||
|
||||
let msg = &mut *msg;
|
||||
chat::prepare_msg(context, chat_id, msg)
|
||||
.unwrap_or_log_default(context, "Failed to prepare message")
|
||||
}
|
||||
@@ -369,12 +368,11 @@ pub unsafe extern "C" fn dc_prepare_msg(
|
||||
pub unsafe extern "C" fn dc_send_msg(
|
||||
context: *mut dc_context_t,
|
||||
chat_id: u32,
|
||||
msg: *mut dc_msg_t,
|
||||
msg: *mut dc_msg::dc_msg_t,
|
||||
) -> u32 {
|
||||
assert!(!context.is_null());
|
||||
assert!(!msg.is_null());
|
||||
let context = &mut *context;
|
||||
let msg = &mut *msg;
|
||||
let context = &*context;
|
||||
|
||||
chat::send_msg(context, chat_id, msg).unwrap_or_log_default(context, "Failed to send message")
|
||||
}
|
||||
@@ -398,11 +396,10 @@ pub unsafe extern "C" fn dc_send_text_msg(
|
||||
pub unsafe extern "C" fn dc_set_draft(
|
||||
context: *mut dc_context_t,
|
||||
chat_id: u32,
|
||||
msg: *mut dc_msg_t,
|
||||
msg: *mut dc_msg::dc_msg_t,
|
||||
) {
|
||||
assert!(!context.is_null());
|
||||
let context = &*context;
|
||||
let msg = if msg.is_null() { None } else { Some(&mut *msg) };
|
||||
|
||||
chat::set_draft(context, chat_id, msg)
|
||||
}
|
||||
@@ -411,11 +408,11 @@ pub unsafe extern "C" fn dc_set_draft(
|
||||
pub unsafe extern "C" fn dc_get_draft<'a>(
|
||||
context: *mut dc_context_t,
|
||||
chat_id: u32,
|
||||
) -> *mut dc_msg_t<'a> {
|
||||
) -> *mut dc_msg::dc_msg_t<'a> {
|
||||
assert!(!context.is_null());
|
||||
let context = &*context;
|
||||
|
||||
chat::get_draft(context, chat_id).into_raw()
|
||||
chat::get_draft(context, chat_id)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@@ -428,8 +425,7 @@ pub unsafe extern "C" fn dc_get_chat_msgs(
|
||||
assert!(!context.is_null());
|
||||
let context = &*context;
|
||||
|
||||
let arr = dc_array_t::from(chat::get_chat_msgs(context, chat_id, flags, marker1before));
|
||||
Box::into_raw(Box::new(arr))
|
||||
dc_array_t::from(chat::get_chat_msgs(context, chat_id, flags, marker1before)).into_raw()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@@ -458,8 +454,7 @@ pub unsafe extern "C" fn dc_get_fresh_msgs(
|
||||
assert!(!context.is_null());
|
||||
let context = &*context;
|
||||
|
||||
let arr = dc_array_t::from(context::dc_get_fresh_msgs(context));
|
||||
Box::into_raw(Box::new(arr))
|
||||
dc_array_t::from(context::dc_get_fresh_msgs(context)).into_raw()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@@ -503,14 +498,14 @@ pub unsafe extern "C" fn dc_get_chat_media(
|
||||
let or_msg_type3 =
|
||||
from_prim(or_msg_type3).expect(&format!("incorrect or_msg_type3 = {}", or_msg_type3));
|
||||
|
||||
let arr = dc_array_t::from(chat::get_chat_media(
|
||||
dc_array_t::from(chat::get_chat_media(
|
||||
context,
|
||||
chat_id,
|
||||
msg_type,
|
||||
or_msg_type2,
|
||||
or_msg_type3,
|
||||
));
|
||||
Box::into_raw(Box::new(arr))
|
||||
))
|
||||
.into_raw()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@@ -570,8 +565,7 @@ pub unsafe extern "C" fn dc_get_chat_contacts(
|
||||
assert!(!context.is_null());
|
||||
let context = &*context;
|
||||
|
||||
let arr = dc_array_t::from(chat::get_chat_contacts(context, chat_id));
|
||||
Box::into_raw(Box::new(arr))
|
||||
dc_array_t::from(chat::get_chat_contacts(context, chat_id)).into_raw()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@@ -584,8 +578,7 @@ pub unsafe extern "C" fn dc_search_msgs(
|
||||
assert!(!query.is_null());
|
||||
let context = &*context;
|
||||
|
||||
let arr = dc_array_t::from(context::dc_search_msgs(context, chat_id, query));
|
||||
Box::into_raw(Box::new(arr))
|
||||
dc_array_t::from(context::dc_search_msgs(context, chat_id, query)).into_raw()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@@ -699,7 +692,7 @@ pub unsafe extern "C" fn dc_get_msg_info(
|
||||
assert!(!context.is_null());
|
||||
let context = &*context;
|
||||
|
||||
message::dc_get_msg_info(context, msg_id)
|
||||
dc_msg::dc_get_msg_info(context, msg_id)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@@ -710,7 +703,7 @@ pub unsafe extern "C" fn dc_get_mime_headers(
|
||||
assert!(!context.is_null());
|
||||
let context = &*context;
|
||||
|
||||
message::dc_get_mime_headers(context, msg_id)
|
||||
dc_msg::dc_get_mime_headers(context, msg_id)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@@ -724,7 +717,7 @@ pub unsafe extern "C" fn dc_delete_msgs(
|
||||
assert!(msg_cnt > 0);
|
||||
let context = &*context;
|
||||
|
||||
message::dc_delete_msgs(context, msg_ids, msg_cnt)
|
||||
dc_msg::dc_delete_msgs(context, msg_ids, msg_cnt)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@@ -762,7 +755,7 @@ pub unsafe extern "C" fn dc_markseen_msgs(
|
||||
assert!(msg_cnt > 0);
|
||||
let context = &*context;
|
||||
|
||||
message::dc_markseen_msgs(context, msg_ids, msg_cnt as usize);
|
||||
dc_msg::dc_markseen_msgs(context, msg_ids, msg_cnt as usize);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@@ -778,18 +771,18 @@ pub unsafe extern "C" fn dc_star_msgs(
|
||||
|
||||
let context = &*context;
|
||||
|
||||
message::dc_star_msgs(context, msg_ids, msg_cnt, star);
|
||||
dc_msg::dc_star_msgs(context, msg_ids, msg_cnt, star);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_get_msg<'a>(
|
||||
context: *mut dc_context_t,
|
||||
msg_id: u32,
|
||||
) -> *mut dc_msg_t<'a> {
|
||||
) -> *mut dc_msg::dc_msg_t<'a> {
|
||||
assert!(!context.is_null());
|
||||
let context = &*context;
|
||||
|
||||
message::dc_get_msg(context, msg_id).into_raw()
|
||||
dc_msg::dc_get_msg(context, msg_id)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@@ -860,7 +853,7 @@ pub unsafe extern "C" fn dc_get_contacts(
|
||||
};
|
||||
|
||||
match Contact::get_all(context, flags, query) {
|
||||
Ok(contacts) => Box::into_raw(Box::new(dc_array_t::from(contacts))),
|
||||
Ok(contacts) => dc_array_t::from(contacts).into_raw(),
|
||||
Err(_) => std::ptr::null_mut(),
|
||||
}
|
||||
}
|
||||
@@ -880,9 +873,7 @@ pub unsafe extern "C" fn dc_get_blocked_contacts(
|
||||
assert!(!context.is_null());
|
||||
let context = &*context;
|
||||
|
||||
Box::into_raw(Box::new(dc_array_t::from(Contact::get_all_blocked(
|
||||
context,
|
||||
))))
|
||||
dc_array_t::from(Contact::get_all_blocked(context)).into_raw()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@@ -995,7 +986,7 @@ pub unsafe extern "C" fn dc_stop_ongoing_process(context: *mut dc_context_t) {
|
||||
assert!(!context.is_null());
|
||||
let context = &*context;
|
||||
|
||||
configure::dc_stop_ongoing_process(context)
|
||||
dc_configure::dc_stop_ongoing_process(context)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@@ -1088,7 +1079,7 @@ pub unsafe extern "C" fn dc_get_locations(
|
||||
timestamp_begin as i64,
|
||||
timestamp_end as i64,
|
||||
);
|
||||
Box::into_raw(Box::new(dc_array_t::from(res)))
|
||||
dc_array_t::from(res).into_raw()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@@ -1108,27 +1099,30 @@ pub type dc_array_t = dc_array::dc_array_t;
|
||||
pub unsafe extern "C" fn dc_array_unref(a: *mut dc_array::dc_array_t) {
|
||||
assert!(!a.is_null());
|
||||
|
||||
Box::from_raw(a);
|
||||
dc_array::dc_array_unref(a)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_array_add_id(array: *mut dc_array_t, item: libc::c_uint) {
|
||||
assert!(!array.is_null());
|
||||
|
||||
(*array).add_id(item);
|
||||
dc_array::dc_array_add_id(array, item)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_array_get_cnt(array: *const dc_array_t) -> libc::size_t {
|
||||
assert!(!array.is_null());
|
||||
|
||||
(*array).len()
|
||||
dc_array::dc_array_get_cnt(array)
|
||||
}
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_array_get_id(array: *const dc_array_t, index: libc::size_t) -> u32 {
|
||||
pub unsafe extern "C" fn dc_array_get_id(
|
||||
array: *const dc_array_t,
|
||||
index: libc::size_t,
|
||||
) -> libc::c_uint {
|
||||
assert!(!array.is_null());
|
||||
|
||||
(*array).get_id(index)
|
||||
dc_array::dc_array_get_id(array, index)
|
||||
}
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_array_get_latitude(
|
||||
@@ -1137,7 +1131,7 @@ pub unsafe extern "C" fn dc_array_get_latitude(
|
||||
) -> libc::c_double {
|
||||
assert!(!array.is_null());
|
||||
|
||||
(*array).get_location(index).latitude
|
||||
(*array).get_latitude(index)
|
||||
}
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_array_get_longitude(
|
||||
@@ -1146,7 +1140,7 @@ pub unsafe extern "C" fn dc_array_get_longitude(
|
||||
) -> libc::c_double {
|
||||
assert!(!array.is_null());
|
||||
|
||||
(*array).get_location(index).longitude
|
||||
(*array).get_longitude(index)
|
||||
}
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_array_get_accuracy(
|
||||
@@ -1155,7 +1149,7 @@ pub unsafe extern "C" fn dc_array_get_accuracy(
|
||||
) -> libc::c_double {
|
||||
assert!(!array.is_null());
|
||||
|
||||
(*array).get_location(index).accuracy
|
||||
(*array).get_accuracy(index)
|
||||
}
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_array_get_timestamp(
|
||||
@@ -1164,7 +1158,7 @@ pub unsafe extern "C" fn dc_array_get_timestamp(
|
||||
) -> i64 {
|
||||
assert!(!array.is_null());
|
||||
|
||||
(*array).get_location(index).timestamp
|
||||
(*array).get_timestamp(index)
|
||||
}
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_array_get_chat_id(
|
||||
@@ -1173,7 +1167,7 @@ pub unsafe extern "C" fn dc_array_get_chat_id(
|
||||
) -> libc::c_uint {
|
||||
assert!(!array.is_null());
|
||||
|
||||
(*array).get_location(index).chat_id
|
||||
(*array).get_chat_id(index)
|
||||
}
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_array_get_contact_id(
|
||||
@@ -1182,7 +1176,7 @@ pub unsafe extern "C" fn dc_array_get_contact_id(
|
||||
) -> libc::c_uint {
|
||||
assert!(!array.is_null());
|
||||
|
||||
(*array).get_location(index).contact_id
|
||||
(*array).get_contact_id(index)
|
||||
}
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_array_get_msg_id(
|
||||
@@ -1191,7 +1185,7 @@ pub unsafe extern "C" fn dc_array_get_msg_id(
|
||||
) -> libc::c_uint {
|
||||
assert!(!array.is_null());
|
||||
|
||||
(*array).get_location(index).msg_id
|
||||
(*array).get_msg_id(index)
|
||||
}
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_array_get_marker(
|
||||
@@ -1200,11 +1194,7 @@ pub unsafe extern "C" fn dc_array_get_marker(
|
||||
) -> *mut libc::c_char {
|
||||
assert!(!array.is_null());
|
||||
|
||||
if let Some(s) = &(*array).get_location(index).marker {
|
||||
s.strdup()
|
||||
} else {
|
||||
std::ptr::null_mut()
|
||||
}
|
||||
dc_array::dc_array_get_marker(array, index)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@@ -1215,27 +1205,16 @@ pub unsafe extern "C" fn dc_array_search_id(
|
||||
) -> libc::c_int {
|
||||
assert!(!array.is_null());
|
||||
|
||||
if let Some(i) = (*array).search_id(needle) {
|
||||
if !ret_index.is_null() {
|
||||
*ret_index = i
|
||||
}
|
||||
1
|
||||
} else {
|
||||
0
|
||||
}
|
||||
dc_array::dc_array_search_id(array, needle, ret_index) as libc::c_int
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_array_get_raw(array: *const dc_array_t) -> *const u32 {
|
||||
assert!(!array.is_null());
|
||||
|
||||
(*array).as_ptr()
|
||||
dc_array::dc_array_get_raw(array)
|
||||
}
|
||||
|
||||
// Return the independent-state of the location at the given index.
|
||||
// Independent locations do not belong to the track of the user.
|
||||
// Returns 1 if location belongs to the track of the user,
|
||||
// 0 if location was reported independently.
|
||||
#[no_mangle]
|
||||
pub unsafe fn dc_array_is_independent(
|
||||
array: *const dc_array_t,
|
||||
@@ -1243,7 +1222,7 @@ pub unsafe fn dc_array_is_independent(
|
||||
) -> libc::c_int {
|
||||
assert!(!array.is_null());
|
||||
|
||||
(*array).get_location(index).independent as libc::c_int
|
||||
dc_array::dc_array_is_independent(array, index)
|
||||
}
|
||||
|
||||
// dc_chatlist_t
|
||||
@@ -1419,326 +1398,300 @@ pub unsafe extern "C" fn dc_chat_is_sending_locations(chat: *mut dc_chat_t) -> l
|
||||
// dc_msg_t
|
||||
|
||||
#[no_mangle]
|
||||
pub type dc_msg_t<'a> = message::Message<'a>;
|
||||
pub type dc_msg_t<'a> = dc_msg::dc_msg_t<'a>;
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_msg_new<'a>(
|
||||
context: *mut dc_context_t,
|
||||
viewtype: libc::c_int,
|
||||
) -> *mut dc_msg_t<'a> {
|
||||
) -> *mut dc_msg::dc_msg_t<'a> {
|
||||
assert!(!context.is_null());
|
||||
let context = &*context;
|
||||
let viewtype = from_prim(viewtype).expect(&format!("invalid viewtype = {}", viewtype));
|
||||
|
||||
Box::into_raw(Box::new(message::dc_msg_new(context, viewtype)))
|
||||
dc_msg::dc_msg_new(context, viewtype)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_msg_unref(msg: *mut dc_msg_t) {
|
||||
pub unsafe extern "C" fn dc_msg_unref(msg: *mut dc_msg::dc_msg_t) {
|
||||
assert!(!msg.is_null());
|
||||
|
||||
Box::from_raw(msg);
|
||||
dc_msg::dc_msg_unref(msg)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_msg_get_id(msg: *mut dc_msg_t) -> u32 {
|
||||
pub unsafe extern "C" fn dc_msg_empty(msg: *mut dc_msg::dc_msg_t) {
|
||||
assert!(!msg.is_null());
|
||||
|
||||
let msg = &*msg;
|
||||
message::dc_msg_get_id(msg)
|
||||
dc_msg::dc_msg_empty(msg)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_msg_get_from_id(msg: *mut dc_msg_t) -> u32 {
|
||||
pub unsafe extern "C" fn dc_msg_get_id(msg: *mut dc_msg::dc_msg_t) -> u32 {
|
||||
assert!(!msg.is_null());
|
||||
|
||||
let msg = &*msg;
|
||||
message::dc_msg_get_from_id(msg)
|
||||
dc_msg::dc_msg_get_id(msg)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_msg_get_chat_id(msg: *mut dc_msg_t) -> u32 {
|
||||
pub unsafe extern "C" fn dc_msg_get_from_id(msg: *mut dc_msg::dc_msg_t) -> u32 {
|
||||
assert!(!msg.is_null());
|
||||
|
||||
let msg = &*msg;
|
||||
message::dc_msg_get_chat_id(msg)
|
||||
dc_msg::dc_msg_get_from_id(msg)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_msg_get_viewtype(msg: *mut dc_msg_t) -> libc::c_int {
|
||||
pub unsafe extern "C" fn dc_msg_get_chat_id(msg: *mut dc_msg::dc_msg_t) -> u32 {
|
||||
assert!(!msg.is_null());
|
||||
|
||||
let msg = &*msg;
|
||||
message::dc_msg_get_viewtype(msg)
|
||||
dc_msg::dc_msg_get_chat_id(msg)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_msg_get_viewtype(msg: *mut dc_msg::dc_msg_t) -> libc::c_int {
|
||||
assert!(!msg.is_null());
|
||||
|
||||
dc_msg::dc_msg_get_viewtype(msg)
|
||||
.to_i64()
|
||||
.expect("impossible: Viewtype -> i64 conversion failed") as libc::c_int
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_msg_get_state(msg: *mut dc_msg_t) -> libc::c_int {
|
||||
pub unsafe extern "C" fn dc_msg_get_state(msg: *mut dc_msg::dc_msg_t) -> libc::c_int {
|
||||
assert!(!msg.is_null());
|
||||
|
||||
let msg = &*msg;
|
||||
message::dc_msg_get_state(msg) as libc::c_int
|
||||
dc_msg::dc_msg_get_state(msg) as libc::c_int
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_msg_get_timestamp(msg: *mut dc_msg_t) -> i64 {
|
||||
pub unsafe extern "C" fn dc_msg_get_timestamp(msg: *mut dc_msg::dc_msg_t) -> i64 {
|
||||
assert!(!msg.is_null());
|
||||
|
||||
let msg = &*msg;
|
||||
message::dc_msg_get_timestamp(msg)
|
||||
dc_msg::dc_msg_get_timestamp(msg)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_msg_get_received_timestamp(msg: *mut dc_msg_t) -> i64 {
|
||||
pub unsafe extern "C" fn dc_msg_get_received_timestamp(msg: *mut dc_msg::dc_msg_t) -> i64 {
|
||||
assert!(!msg.is_null());
|
||||
|
||||
let msg = &*msg;
|
||||
message::dc_msg_get_received_timestamp(msg)
|
||||
dc_msg::dc_msg_get_received_timestamp(msg)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_msg_get_sort_timestamp(msg: *mut dc_msg_t) -> i64 {
|
||||
pub unsafe extern "C" fn dc_msg_get_sort_timestamp(msg: *mut dc_msg::dc_msg_t) -> i64 {
|
||||
assert!(!msg.is_null());
|
||||
|
||||
let msg = &*msg;
|
||||
message::dc_msg_get_sort_timestamp(msg)
|
||||
dc_msg::dc_msg_get_sort_timestamp(msg)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_msg_get_text(msg: *mut dc_msg_t) -> *mut libc::c_char {
|
||||
pub unsafe extern "C" fn dc_msg_get_text(msg: *mut dc_msg::dc_msg_t) -> *mut libc::c_char {
|
||||
assert!(!msg.is_null());
|
||||
|
||||
let msg = &*msg;
|
||||
message::dc_msg_get_text(msg)
|
||||
dc_msg::dc_msg_get_text(msg)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_msg_get_file(msg: *mut dc_msg_t) -> *mut libc::c_char {
|
||||
pub unsafe extern "C" fn dc_msg_get_file(msg: *mut dc_msg::dc_msg_t) -> *mut libc::c_char {
|
||||
assert!(!msg.is_null());
|
||||
|
||||
let msg = &*msg;
|
||||
message::dc_msg_get_file(msg)
|
||||
dc_msg::dc_msg_get_file(msg)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_msg_get_filename(msg: *mut dc_msg_t) -> *mut libc::c_char {
|
||||
pub unsafe extern "C" fn dc_msg_get_filename(msg: *mut dc_msg::dc_msg_t) -> *mut libc::c_char {
|
||||
assert!(!msg.is_null());
|
||||
|
||||
let msg = &*msg;
|
||||
message::dc_msg_get_filename(msg)
|
||||
dc_msg::dc_msg_get_filename(msg)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_msg_get_filemime(msg: *mut dc_msg_t) -> *mut libc::c_char {
|
||||
pub unsafe extern "C" fn dc_msg_get_filemime(msg: *mut dc_msg::dc_msg_t) -> *mut libc::c_char {
|
||||
assert!(!msg.is_null());
|
||||
|
||||
let msg = &*msg;
|
||||
message::dc_msg_get_filemime(msg)
|
||||
dc_msg::dc_msg_get_filemime(msg)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_msg_get_filebytes(msg: *mut dc_msg_t) -> u64 {
|
||||
pub unsafe extern "C" fn dc_msg_get_filebytes(msg: *mut dc_msg::dc_msg_t) -> u64 {
|
||||
assert!(!msg.is_null());
|
||||
|
||||
let msg = &*msg;
|
||||
message::dc_msg_get_filebytes(msg)
|
||||
dc_msg::dc_msg_get_filebytes(msg)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_msg_get_width(msg: *mut dc_msg_t) -> libc::c_int {
|
||||
pub unsafe extern "C" fn dc_msg_get_width(msg: *mut dc_msg::dc_msg_t) -> libc::c_int {
|
||||
assert!(!msg.is_null());
|
||||
|
||||
let msg = &*msg;
|
||||
message::dc_msg_get_width(msg)
|
||||
dc_msg::dc_msg_get_width(msg)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_msg_get_height(msg: *mut dc_msg_t) -> libc::c_int {
|
||||
pub unsafe extern "C" fn dc_msg_get_height(msg: *mut dc_msg::dc_msg_t) -> libc::c_int {
|
||||
assert!(!msg.is_null());
|
||||
|
||||
let msg = &*msg;
|
||||
message::dc_msg_get_height(msg)
|
||||
dc_msg::dc_msg_get_height(msg)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_msg_get_duration(msg: *mut dc_msg_t) -> libc::c_int {
|
||||
pub unsafe extern "C" fn dc_msg_get_duration(msg: *mut dc_msg::dc_msg_t) -> libc::c_int {
|
||||
assert!(!msg.is_null());
|
||||
|
||||
let msg = &*msg;
|
||||
message::dc_msg_get_duration(msg)
|
||||
dc_msg::dc_msg_get_duration(msg)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_msg_get_showpadlock(msg: *mut dc_msg_t) -> libc::c_int {
|
||||
pub unsafe extern "C" fn dc_msg_get_showpadlock(msg: *mut dc_msg::dc_msg_t) -> libc::c_int {
|
||||
assert!(!msg.is_null());
|
||||
|
||||
let msg = &*msg;
|
||||
message::dc_msg_get_showpadlock(msg)
|
||||
dc_msg::dc_msg_get_showpadlock(msg)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_msg_get_summary<'a>(
|
||||
msg: *mut dc_msg_t<'a>,
|
||||
msg: *mut dc_msg::dc_msg_t<'a>,
|
||||
chat: *mut dc_chat_t<'a>,
|
||||
) -> *mut dc_lot_t {
|
||||
assert!(!msg.is_null());
|
||||
let chat = if chat.is_null() { None } else { Some(&*chat) };
|
||||
|
||||
let msg = &mut *msg;
|
||||
|
||||
let lot = message::dc_msg_get_summary(msg, chat);
|
||||
let lot = dc_msg::dc_msg_get_summary(msg, chat);
|
||||
Box::into_raw(Box::new(lot))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_msg_get_summarytext(
|
||||
msg: *mut dc_msg_t,
|
||||
msg: *mut dc_msg::dc_msg_t,
|
||||
approx_characters: libc::c_int,
|
||||
) -> *mut libc::c_char {
|
||||
assert!(!msg.is_null());
|
||||
|
||||
let msg = &mut *msg;
|
||||
message::dc_msg_get_summarytext(msg, approx_characters.try_into().unwrap())
|
||||
dc_msg::dc_msg_get_summarytext(msg, approx_characters.try_into().unwrap())
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_msg_has_deviating_timestamp(msg: *mut dc_msg_t) -> libc::c_int {
|
||||
pub unsafe extern "C" fn dc_msg_has_deviating_timestamp(msg: *mut dc_msg::dc_msg_t) -> libc::c_int {
|
||||
assert!(!msg.is_null());
|
||||
|
||||
let msg = &*msg;
|
||||
message::dc_msg_has_deviating_timestamp(msg)
|
||||
dc_msg::dc_msg_has_deviating_timestamp(msg)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_msg_has_location(msg: *mut dc_msg_t) -> libc::c_int {
|
||||
pub unsafe extern "C" fn dc_msg_has_location(msg: *mut dc_msg::dc_msg_t) -> libc::c_int {
|
||||
assert!(!msg.is_null());
|
||||
|
||||
let msg = &*msg;
|
||||
message::dc_msg_has_location(msg) as libc::c_int
|
||||
dc_msg::dc_msg_has_location(msg) as libc::c_int
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_msg_is_sent(msg: *mut dc_msg_t) -> libc::c_int {
|
||||
pub unsafe extern "C" fn dc_msg_is_sent(msg: *mut dc_msg::dc_msg_t) -> libc::c_int {
|
||||
assert!(!msg.is_null());
|
||||
|
||||
let msg = &*msg;
|
||||
message::dc_msg_is_sent(msg)
|
||||
dc_msg::dc_msg_is_sent(msg)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_msg_is_starred(msg: *mut dc_msg_t) -> libc::c_int {
|
||||
pub unsafe extern "C" fn dc_msg_is_starred(msg: *mut dc_msg::dc_msg_t) -> libc::c_int {
|
||||
assert!(!msg.is_null());
|
||||
|
||||
let msg = &*msg;
|
||||
message::dc_msg_is_starred(msg).into()
|
||||
dc_msg::dc_msg_is_starred(msg).into()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_msg_is_forwarded(msg: *mut dc_msg_t) -> libc::c_int {
|
||||
pub unsafe extern "C" fn dc_msg_is_forwarded(msg: *mut dc_msg::dc_msg_t) -> libc::c_int {
|
||||
assert!(!msg.is_null());
|
||||
|
||||
let msg = &*msg;
|
||||
message::dc_msg_is_forwarded(msg)
|
||||
dc_msg::dc_msg_is_forwarded(msg)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_msg_is_info(msg: *mut dc_msg_t) -> libc::c_int {
|
||||
pub unsafe extern "C" fn dc_msg_is_info(msg: *mut dc_msg::dc_msg_t) -> libc::c_int {
|
||||
assert!(!msg.is_null());
|
||||
|
||||
let msg = &*msg;
|
||||
message::dc_msg_is_info(msg)
|
||||
dc_msg::dc_msg_is_info(msg)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_msg_is_increation(msg: *mut dc_msg_t) -> libc::c_int {
|
||||
pub unsafe extern "C" fn dc_msg_is_increation(msg: *mut dc_msg::dc_msg_t) -> libc::c_int {
|
||||
assert!(!msg.is_null());
|
||||
|
||||
let msg = &*msg;
|
||||
message::dc_msg_is_increation(msg)
|
||||
dc_msg::dc_msg_is_increation(msg)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_msg_is_setupmessage(msg: *mut dc_msg_t) -> libc::c_int {
|
||||
pub unsafe extern "C" fn dc_msg_is_setupmessage(msg: *mut dc_msg::dc_msg_t) -> libc::c_int {
|
||||
assert!(!msg.is_null());
|
||||
|
||||
let msg = &*msg;
|
||||
message::dc_msg_is_setupmessage(msg) as libc::c_int
|
||||
dc_msg::dc_msg_is_setupmessage(msg) as libc::c_int
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_msg_get_setupcodebegin(msg: *mut dc_msg_t) -> *mut libc::c_char {
|
||||
pub unsafe extern "C" fn dc_msg_get_setupcodebegin(
|
||||
msg: *mut dc_msg::dc_msg_t,
|
||||
) -> *mut libc::c_char {
|
||||
assert!(!msg.is_null());
|
||||
|
||||
let msg = &*msg;
|
||||
message::dc_msg_get_setupcodebegin(msg)
|
||||
dc_msg::dc_msg_get_setupcodebegin(msg)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_msg_set_text(msg: *mut dc_msg_t, text: *mut libc::c_char) {
|
||||
pub unsafe extern "C" fn dc_msg_set_text(msg: *mut dc_msg::dc_msg_t, text: *mut libc::c_char) {
|
||||
assert!(!msg.is_null());
|
||||
|
||||
let msg = &mut *msg;
|
||||
// TODO: {text} equal to NULL is treated as "", which is strange. Does anyone rely on it?
|
||||
message::dc_msg_set_text(msg, text)
|
||||
dc_msg::dc_msg_set_text(msg, text)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_msg_set_file(
|
||||
msg: *mut dc_msg_t,
|
||||
msg: *mut dc_msg::dc_msg_t,
|
||||
file: *mut libc::c_char,
|
||||
filemime: *mut libc::c_char,
|
||||
) {
|
||||
assert!(!msg.is_null());
|
||||
|
||||
let msg = &mut *msg;
|
||||
message::dc_msg_set_file(msg, file, filemime)
|
||||
dc_msg::dc_msg_set_file(msg, file, filemime)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_msg_set_dimension(
|
||||
msg: *mut dc_msg_t,
|
||||
msg: *mut dc_msg::dc_msg_t,
|
||||
width: libc::c_int,
|
||||
height: libc::c_int,
|
||||
) {
|
||||
assert!(!msg.is_null());
|
||||
|
||||
let msg = &mut *msg;
|
||||
message::dc_msg_set_dimension(msg, width, height)
|
||||
dc_msg::dc_msg_set_dimension(msg, width, height)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_msg_set_duration(msg: *mut dc_msg_t, duration: libc::c_int) {
|
||||
pub unsafe extern "C" fn dc_msg_set_duration(msg: *mut dc_msg::dc_msg_t, duration: libc::c_int) {
|
||||
assert!(!msg.is_null());
|
||||
|
||||
let msg = &mut *msg;
|
||||
message::dc_msg_set_duration(msg, duration)
|
||||
dc_msg::dc_msg_set_duration(msg, duration)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_msg_set_location(
|
||||
msg: *mut dc_msg_t,
|
||||
msg: *mut dc_msg::dc_msg_t,
|
||||
latitude: libc::c_double,
|
||||
longitude: libc::c_double,
|
||||
) {
|
||||
assert!(!msg.is_null());
|
||||
|
||||
let msg = &mut *msg;
|
||||
message::dc_msg_set_location(msg, latitude, longitude)
|
||||
dc_msg::dc_msg_set_location(msg, latitude, longitude)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_msg_latefiling_mediasize(
|
||||
msg: *mut dc_msg_t,
|
||||
msg: *mut dc_msg::dc_msg_t,
|
||||
width: libc::c_int,
|
||||
height: libc::c_int,
|
||||
duration: libc::c_int,
|
||||
) {
|
||||
assert!(!msg.is_null());
|
||||
|
||||
let msg = &mut *msg;
|
||||
message::dc_msg_latefiling_mediasize(msg, width, height, duration)
|
||||
dc_msg::dc_msg_latefiling_mediasize(msg, width, height, duration)
|
||||
}
|
||||
|
||||
// dc_contact_t
|
||||
@@ -1916,7 +1869,7 @@ fn as_opt_str<'a>(s: *const libc::c_char) -> Option<&'a str> {
|
||||
Some(dc_tools::as_str(s))
|
||||
}
|
||||
|
||||
pub trait ResultExt<T> {
|
||||
pub trait ResultExt<T: Default> {
|
||||
fn unwrap_or_log_default(self, context: &context::Context, message: &str) -> T;
|
||||
fn log_err(&self, context: &context::Context, message: &str);
|
||||
}
|
||||
@@ -1945,16 +1898,3 @@ unsafe fn strdup_opt(s: Option<impl AsRef<str>>) -> *mut libc::c_char {
|
||||
None => ptr::null_mut(),
|
||||
}
|
||||
}
|
||||
|
||||
pub trait ResultNullableExt<T> {
|
||||
fn into_raw(self) -> *mut T;
|
||||
}
|
||||
|
||||
impl<T, E> ResultNullableExt<T> for Result<T, E> {
|
||||
fn into_raw(self) -> *mut T {
|
||||
match self {
|
||||
Ok(t) => Box::into_raw(Box::new(t)),
|
||||
Err(_) => ptr::null_mut(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,18 +4,17 @@ use std::str::FromStr;
|
||||
use deltachat::chat::{self, Chat};
|
||||
use deltachat::chatlist::*;
|
||||
use deltachat::config;
|
||||
use deltachat::configure::*;
|
||||
use deltachat::constants::*;
|
||||
use deltachat::contact::*;
|
||||
use deltachat::context::*;
|
||||
use deltachat::dc_configure::*;
|
||||
use deltachat::dc_imex::*;
|
||||
use deltachat::dc_location::*;
|
||||
use deltachat::dc_msg::*;
|
||||
use deltachat::dc_receive_imf::*;
|
||||
use deltachat::dc_tools::*;
|
||||
use deltachat::error::Error;
|
||||
use deltachat::job::*;
|
||||
use deltachat::lot::LotState;
|
||||
use deltachat::message::*;
|
||||
use deltachat::peerstate::*;
|
||||
use deltachat::qr::*;
|
||||
use deltachat::sql;
|
||||
@@ -211,7 +210,7 @@ unsafe fn poke_spec(context: &Context, spec: *const libc::c_char) -> libc::c_int
|
||||
success
|
||||
}
|
||||
|
||||
unsafe fn log_msg(context: &Context, prefix: impl AsRef<str>, msg: &Message) {
|
||||
unsafe fn log_msg(context: &Context, prefix: impl AsRef<str>, msg: *mut dc_msg_t) {
|
||||
let contact = Contact::get_by_id(context, dc_msg_get_from_id(msg)).expect("invalid contact");
|
||||
let contact_name = contact.get_name();
|
||||
let contact_id = contact.get_id();
|
||||
@@ -261,7 +260,7 @@ unsafe fn log_msg(context: &Context, prefix: impl AsRef<str>, msg: &Message) {
|
||||
free(msgtext as *mut libc::c_void);
|
||||
}
|
||||
|
||||
unsafe fn log_msglist(context: &Context, msglist: &Vec<u32>) -> Result<(), Error> {
|
||||
unsafe fn log_msglist(context: &Context, msglist: &Vec<u32>) {
|
||||
let mut lines_out = 0;
|
||||
for &msg_id in msglist {
|
||||
if msg_id == 9 as libc::c_uint {
|
||||
@@ -280,8 +279,9 @@ unsafe fn log_msglist(context: &Context, msglist: &Vec<u32>) -> Result<(), Error
|
||||
);
|
||||
lines_out += 1
|
||||
}
|
||||
let msg = dc_get_msg(context, msg_id)?;
|
||||
log_msg(context, "Msg", &msg);
|
||||
let msg = dc_get_msg(context, msg_id);
|
||||
log_msg(context, "Msg", msg);
|
||||
dc_msg_unref(msg);
|
||||
}
|
||||
}
|
||||
if lines_out > 0 {
|
||||
@@ -290,7 +290,6 @@ unsafe fn log_msglist(context: &Context, msglist: &Vec<u32>) -> Result<(), Error
|
||||
0, "--------------------------------------------------------------------------------"
|
||||
);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
unsafe fn log_contactlist(context: &Context, contacts: &Vec<u32>) {
|
||||
@@ -497,9 +496,9 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E
|
||||
"get-setupcodebegin" => {
|
||||
ensure!(!arg1.is_empty(), "Argument <msg-id> missing.");
|
||||
let msg_id: u32 = arg1.parse()?;
|
||||
let msg = dc_get_msg(context, msg_id)?;
|
||||
if dc_msg_is_setupmessage(&msg) {
|
||||
let setupcodebegin = dc_msg_get_setupcodebegin(&msg);
|
||||
let msg: *mut dc_msg_t = dc_get_msg(context, msg_id);
|
||||
if dc_msg_is_setupmessage(msg) {
|
||||
let setupcodebegin = dc_msg_get_setupcodebegin(msg);
|
||||
println!(
|
||||
"The setup code for setup message Msg#{} starts with: {}",
|
||||
msg_id,
|
||||
@@ -509,6 +508,7 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E
|
||||
} else {
|
||||
bail!("Msg#{} is no setup message.", msg_id,);
|
||||
}
|
||||
dc_msg_unref(msg);
|
||||
}
|
||||
"continue-key-transfer" => {
|
||||
ensure!(
|
||||
@@ -688,11 +688,12 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E
|
||||
""
|
||||
},
|
||||
);
|
||||
log_msglist(context, &msglist)?;
|
||||
if let Ok(draft) = chat::get_draft(context, sel_chat.get_id()) {
|
||||
log_msg(context, "Draft", &draft);
|
||||
log_msglist(context, &msglist);
|
||||
let draft = chat::get_draft(context, sel_chat.get_id());
|
||||
if !draft.is_null() {
|
||||
log_msg(context, "Draft", draft);
|
||||
dc_msg_unref(draft);
|
||||
}
|
||||
|
||||
println!(
|
||||
"{} messages.",
|
||||
chat::get_msg_cnt(context, sel_chat.get_id())
|
||||
@@ -860,7 +861,7 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E
|
||||
ensure!(sel_chat.is_some(), "No chat selected.");
|
||||
ensure!(!arg1.is_empty() && !arg2.is_empty(), "No file given.");
|
||||
|
||||
let mut msg = dc_msg_new(
|
||||
let msg_0 = dc_msg_new(
|
||||
context,
|
||||
if arg0 == "sendimage" {
|
||||
Viewtype::Image
|
||||
@@ -868,9 +869,10 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E
|
||||
Viewtype::File
|
||||
},
|
||||
);
|
||||
dc_msg_set_file(&mut msg, arg1_c, 0 as *const libc::c_char);
|
||||
dc_msg_set_text(&mut msg, arg2_c);
|
||||
chat::send_msg(context, sel_chat.as_ref().unwrap().get_id(), &mut msg)?;
|
||||
dc_msg_set_file(msg_0, arg1_c, 0 as *const libc::c_char);
|
||||
dc_msg_set_text(msg_0, arg2_c);
|
||||
chat::send_msg(context, sel_chat.as_ref().unwrap().get_id(), msg_0)?;
|
||||
dc_msg_unref(msg_0);
|
||||
}
|
||||
"listmsgs" => {
|
||||
ensure!(!arg1.is_empty(), "Argument <query> missing.");
|
||||
@@ -883,23 +885,24 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E
|
||||
|
||||
let msglist = dc_search_msgs(context, chat, arg1_c);
|
||||
|
||||
log_msglist(context, &msglist)?;
|
||||
log_msglist(context, &msglist);
|
||||
println!("{} messages.", msglist.len());
|
||||
}
|
||||
"draft" => {
|
||||
ensure!(sel_chat.is_some(), "No chat selected.");
|
||||
|
||||
if !arg1.is_empty() {
|
||||
let mut draft = dc_msg_new(context, Viewtype::Text);
|
||||
dc_msg_set_text(&mut draft, arg1_c);
|
||||
let draft_0 = dc_msg_new(context, Viewtype::Text);
|
||||
dc_msg_set_text(draft_0, arg1_c);
|
||||
chat::set_draft(context, sel_chat.as_ref().unwrap().get_id(), draft_0);
|
||||
dc_msg_unref(draft_0);
|
||||
println!("Draft saved.");
|
||||
} else {
|
||||
chat::set_draft(
|
||||
context,
|
||||
sel_chat.as_ref().unwrap().get_id(),
|
||||
Some(&mut draft),
|
||||
0 as *mut dc_msg_t,
|
||||
);
|
||||
println!("Draft saved.");
|
||||
} else {
|
||||
chat::set_draft(context, sel_chat.as_ref().unwrap().get_id(), None);
|
||||
println!("Draft deleted.");
|
||||
}
|
||||
}
|
||||
@@ -946,7 +949,7 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E
|
||||
"listfresh" => {
|
||||
let msglist = dc_get_fresh_msgs(context);
|
||||
|
||||
log_msglist(context, &msglist)?;
|
||||
log_msglist(context, &msglist);
|
||||
print!("{} fresh messages.", msglist.len());
|
||||
}
|
||||
"forward" => {
|
||||
|
||||
@@ -18,9 +18,9 @@ use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::{Arc, Mutex, RwLock};
|
||||
|
||||
use deltachat::config;
|
||||
use deltachat::configure::*;
|
||||
use deltachat::constants::*;
|
||||
use deltachat::context::*;
|
||||
use deltachat::dc_configure::*;
|
||||
use deltachat::dc_securejoin::*;
|
||||
use deltachat::dc_tools::*;
|
||||
use deltachat::job::*;
|
||||
@@ -495,7 +495,7 @@ unsafe fn handle_cmd(line: &str, ctx: Arc<RwLock<Context>>) -> Result<ExitResult
|
||||
}
|
||||
"configure" => {
|
||||
start_threads(ctx.clone());
|
||||
configure(&ctx.read().unwrap());
|
||||
dc_configure(&ctx.read().unwrap());
|
||||
}
|
||||
"oauth2" => {
|
||||
if let Some(addr) = ctx.read().unwrap().get_config(config::Config::Addr) {
|
||||
|
||||
@@ -8,10 +8,10 @@ use tempfile::tempdir;
|
||||
use deltachat::chat;
|
||||
use deltachat::chatlist::*;
|
||||
use deltachat::config;
|
||||
use deltachat::configure::*;
|
||||
use deltachat::constants::Event;
|
||||
use deltachat::contact::*;
|
||||
use deltachat::context::*;
|
||||
use deltachat::dc_configure::*;
|
||||
use deltachat::job::{
|
||||
perform_imap_fetch, perform_imap_idle, perform_imap_jobs, perform_smtp_idle, perform_smtp_jobs,
|
||||
};
|
||||
@@ -87,7 +87,7 @@ fn main() {
|
||||
ctx.set_config(config::Config::Addr, Some("d@testrun.org"))
|
||||
.unwrap();
|
||||
ctx.set_config(config::Config::MailPw, Some(&pw)).unwrap();
|
||||
configure(&ctx);
|
||||
dc_configure(&ctx);
|
||||
|
||||
thread::sleep(duration);
|
||||
|
||||
|
||||
@@ -176,7 +176,7 @@ class Account(object):
|
||||
whose name or e-mail matches query.
|
||||
:param only_verified: if true only return verified contacts.
|
||||
:param with_self: if true the self-contact is also returned.
|
||||
:returns: list of :class:`deltachat.chatting.Contact` objects.
|
||||
:returns: list of :class:`deltachat.message.Message` objects.
|
||||
"""
|
||||
flags = 0
|
||||
query = as_dc_charpointer(query)
|
||||
@@ -377,15 +377,12 @@ class IOThreads:
|
||||
def is_started(self):
|
||||
return len(self._name2thread) > 0
|
||||
|
||||
def start(self, imap=True, smtp=True, mvbox=True):
|
||||
def start(self, imap=True, smtp=True):
|
||||
assert not self.is_started()
|
||||
if imap:
|
||||
self._start_one_thread("inbox", self.inbox_thread_run)
|
||||
self._start_one_thread("imap", self.imap_thread_run)
|
||||
if smtp:
|
||||
self._start_one_thread("smtp", self.smtp_thread_run)
|
||||
if mvbox:
|
||||
self._start_one_thread("mvbox", self.mvbox_thread_run)
|
||||
|
||||
|
||||
def _start_one_thread(self, name, func):
|
||||
self._name2thread[name] = t = threading.Thread(target=func, name=name)
|
||||
@@ -400,20 +397,13 @@ class IOThreads:
|
||||
for name, thread in self._name2thread.items():
|
||||
thread.join()
|
||||
|
||||
def inbox_thread_run(self):
|
||||
self._log_event("py-bindings-info", 0, "INBOX IMAP THREAD START")
|
||||
def imap_thread_run(self):
|
||||
self._log_event("py-bindings-info", 0, "IMAP THREAD START")
|
||||
while not self._thread_quitflag:
|
||||
lib.dc_perform_imap_jobs(self._dc_context)
|
||||
lib.dc_perform_imap_fetch(self._dc_context)
|
||||
lib.dc_perform_imap_idle(self._dc_context)
|
||||
self._log_event("py-bindings-info", 0, "INBOX IMAP THREAD FINISHED")
|
||||
|
||||
def mvbox_thread_run(self):
|
||||
self._log_event("py-bindings-info", 0, "MVBOX IMAP THREAD START")
|
||||
while not self._thread_quitflag:
|
||||
lib.dc_perform_mvbox_fetch(self._dc_context)
|
||||
lib.dc_perform_mvbox_idle(self._dc_context)
|
||||
self._log_event("py-bindings-info", 0, "MVBOX IMAP THREAD FINISHED")
|
||||
self._log_event("py-bindings-info", 0, "IMAP THREAD FINISHED")
|
||||
|
||||
def smtp_thread_run(self):
|
||||
self._log_event("py-bindings-info", 0, "SMTP THREAD START")
|
||||
|
||||
271
src/chat.rs
271
src/chat.rs
@@ -5,10 +5,10 @@ use crate::chatlist::*;
|
||||
use crate::constants::*;
|
||||
use crate::contact::*;
|
||||
use crate::context::Context;
|
||||
use crate::dc_msg::*;
|
||||
use crate::dc_tools::*;
|
||||
use crate::error::Error;
|
||||
use crate::job::*;
|
||||
use crate::message::*;
|
||||
use crate::param::*;
|
||||
use crate::sql::{self, Sql};
|
||||
use crate::stock::StockMessage;
|
||||
@@ -272,7 +272,7 @@ impl<'a> Chat<'a> {
|
||||
unsafe fn prepare_msg_raw(
|
||||
&mut self,
|
||||
context: &Context,
|
||||
msg: &mut Message,
|
||||
msg: *mut dc_msg_t,
|
||||
timestamp: i64,
|
||||
) -> Result<u32, Error> {
|
||||
let mut do_guarantee_e2ee: libc::c_int;
|
||||
@@ -351,7 +351,11 @@ impl<'a> Chat<'a> {
|
||||
.get_config_int(context, "e2ee_enabled")
|
||||
.unwrap_or_else(|| 1);
|
||||
if 0 != e2ee_enabled
|
||||
&& msg.param.get_int(Param::ForcePlaintext).unwrap_or_default() == 0
|
||||
&& (*msg)
|
||||
.param
|
||||
.get_int(Param::ForcePlaintext)
|
||||
.unwrap_or_default()
|
||||
== 0
|
||||
{
|
||||
let mut can_encrypt = 1;
|
||||
let mut all_mutual = 1;
|
||||
@@ -405,9 +409,9 @@ impl<'a> Chat<'a> {
|
||||
}
|
||||
}
|
||||
if 0 != do_guarantee_e2ee {
|
||||
msg.param.set_int(Param::GuranteeE2ee, 1);
|
||||
(*msg).param.set_int(Param::GuranteeE2ee, 1);
|
||||
}
|
||||
msg.param.remove(Param::ErroneousE2ee);
|
||||
(*msg).param.remove(Param::ErroneousE2ee);
|
||||
if !self.is_self_talk()
|
||||
&& self
|
||||
.get_parent_mime_headers(
|
||||
@@ -462,7 +466,7 @@ impl<'a> Chat<'a> {
|
||||
|
||||
// add independent location to database
|
||||
|
||||
if msg.param.exists(Param::SetLatitude) {
|
||||
if (*msg).param.exists(Param::SetLatitude) {
|
||||
if sql::execute(
|
||||
context,
|
||||
&context.sql,
|
||||
@@ -473,8 +477,14 @@ impl<'a> Chat<'a> {
|
||||
timestamp,
|
||||
DC_CONTACT_ID_SELF as i32,
|
||||
self.id as i32,
|
||||
msg.param.get_float(Param::SetLatitude).unwrap_or_default(),
|
||||
msg.param.get_float(Param::SetLongitude).unwrap_or_default(),
|
||||
(*msg)
|
||||
.param
|
||||
.get_float(Param::SetLatitude)
|
||||
.unwrap_or_default(),
|
||||
(*msg)
|
||||
.param
|
||||
.get_float(Param::SetLongitude)
|
||||
.unwrap_or_default(),
|
||||
],
|
||||
)
|
||||
.is_ok()
|
||||
@@ -503,11 +513,11 @@ impl<'a> Chat<'a> {
|
||||
1i32,
|
||||
to_id as i32,
|
||||
timestamp,
|
||||
msg.type_0,
|
||||
msg.state,
|
||||
msg.text,
|
||||
msg.param.to_string(),
|
||||
msg.hidden,
|
||||
(*msg).type_0,
|
||||
(*msg).state,
|
||||
(*msg).text,
|
||||
(*msg).param.to_string(),
|
||||
(*msg).hidden,
|
||||
to_string(new_in_reply_to),
|
||||
to_string(new_references),
|
||||
location_id as i32,
|
||||
@@ -564,20 +574,27 @@ impl<'a> Chat<'a> {
|
||||
pub fn create_by_msg_id(context: &Context, msg_id: u32) -> Result<u32, Error> {
|
||||
let mut chat_id = 0;
|
||||
let mut send_event = false;
|
||||
let msg = unsafe { dc_msg_new_untyped(context) };
|
||||
|
||||
if let Ok(msg) = dc_msg_load_from_db(context, msg_id) {
|
||||
if let Ok(chat) = Chat::load_from_db(context, msg.chat_id) {
|
||||
if dc_msg_load_from_db(msg, context, msg_id) {
|
||||
if let Ok(chat) = Chat::load_from_db(context, unsafe { (*msg).chat_id }) {
|
||||
if chat.id > DC_CHAT_ID_LAST_SPECIAL as u32 {
|
||||
chat_id = chat.id;
|
||||
if chat.blocked != Blocked::Not {
|
||||
unblock(context, chat.id);
|
||||
send_event = true;
|
||||
}
|
||||
Contact::scaleup_origin_by_id(context, msg.from_id, Origin::CreateChat);
|
||||
Contact::scaleup_origin_by_id(
|
||||
context,
|
||||
unsafe { (*msg).from_id },
|
||||
Origin::CreateChat,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe { dc_msg_unref(msg) };
|
||||
|
||||
if send_event {
|
||||
context.call_cb(Event::MSGS_CHANGED, 0, 0);
|
||||
}
|
||||
@@ -704,19 +721,20 @@ pub fn get_by_contact_id(context: &Context, contact_id: u32) -> Result<u32, Erro
|
||||
pub fn prepare_msg<'a>(
|
||||
context: &'a Context,
|
||||
chat_id: u32,
|
||||
msg: &mut Message<'a>,
|
||||
mut msg: *mut dc_msg_t<'a>,
|
||||
) -> Result<u32, Error> {
|
||||
ensure!(!msg.is_null(), "No message provided");
|
||||
ensure!(
|
||||
chat_id > DC_CHAT_ID_LAST_SPECIAL as u32,
|
||||
"Cannot prepare message for special chat"
|
||||
);
|
||||
|
||||
msg.state = MessageState::OutPreparing;
|
||||
unsafe { (*msg).state = MessageState::OutPreparing };
|
||||
let msg_id = prepare_msg_common(context, chat_id, msg)?;
|
||||
context.call_cb(
|
||||
Event::MSGS_CHANGED,
|
||||
msg.chat_id as uintptr_t,
|
||||
msg.id as uintptr_t,
|
||||
unsafe { (*msg).chat_id as uintptr_t },
|
||||
unsafe { (*msg).id as uintptr_t },
|
||||
);
|
||||
|
||||
Ok(msg_id)
|
||||
@@ -737,8 +755,12 @@ pub fn msgtype_has_file(msgtype: Viewtype) -> bool {
|
||||
fn prepare_msg_common<'a>(
|
||||
context: &'a Context,
|
||||
chat_id: u32,
|
||||
msg: &mut Message<'a>,
|
||||
msg: *mut dc_msg_t<'a>,
|
||||
) -> Result<u32, Error> {
|
||||
ensure!(!msg.is_null(), "No message provided");
|
||||
|
||||
let msg = unsafe { &mut *msg };
|
||||
|
||||
msg.id = 0;
|
||||
msg.context = context;
|
||||
|
||||
@@ -859,37 +881,39 @@ pub fn unarchive(context: &Context, chat_id: u32) -> Result<(), Error> {
|
||||
pub unsafe fn send_msg<'a>(
|
||||
context: &'a Context,
|
||||
chat_id: u32,
|
||||
msg: &mut Message<'a>,
|
||||
msg: *mut dc_msg_t<'a>,
|
||||
) -> Result<u32, Error> {
|
||||
if msg.state != MessageState::OutPreparing {
|
||||
ensure!(!msg.is_null(), "Invalid message");
|
||||
|
||||
if (*msg).state != MessageState::OutPreparing {
|
||||
// automatically prepare normal messages
|
||||
prepare_msg_common(context, chat_id, msg)?;
|
||||
} else {
|
||||
// update message state of separately prepared messages
|
||||
ensure!(
|
||||
chat_id == 0 || chat_id == msg.chat_id,
|
||||
chat_id == 0 || chat_id == (*msg).chat_id,
|
||||
"Inconsistent chat ID"
|
||||
);
|
||||
dc_update_msg_state(context, msg.id, MessageState::OutPending);
|
||||
dc_update_msg_state(context, (*msg).id, MessageState::OutPending);
|
||||
}
|
||||
|
||||
ensure!(
|
||||
job_send_msg(context, msg.id) != 0,
|
||||
job_send_msg(context, (*msg).id) != 0,
|
||||
"Failed to initiate send job"
|
||||
);
|
||||
|
||||
context.call_cb(
|
||||
Event::MSGS_CHANGED,
|
||||
msg.chat_id as uintptr_t,
|
||||
msg.id as uintptr_t,
|
||||
(*msg).chat_id as uintptr_t,
|
||||
(*msg).id as uintptr_t,
|
||||
);
|
||||
|
||||
if msg.param.exists(Param::SetLatitude) {
|
||||
if (*msg).param.exists(Param::SetLatitude) {
|
||||
context.call_cb(Event::LOCATION_CHANGED, DC_CONTACT_ID_SELF, 0);
|
||||
}
|
||||
|
||||
if 0 == chat_id {
|
||||
let forwards = msg.param.get(Param::PrepForwards);
|
||||
let forwards = (*msg).param.get(Param::PrepForwards);
|
||||
if let Some(forwards) = forwards {
|
||||
for forward in forwards.split(' ') {
|
||||
let id: i32 = forward.parse().unwrap_or_default();
|
||||
@@ -897,18 +921,20 @@ pub unsafe fn send_msg<'a>(
|
||||
// avoid hanging if user tampers with db
|
||||
break;
|
||||
} else {
|
||||
if let Ok(mut copy) = dc_get_msg(context, id as u32) {
|
||||
let copy = dc_get_msg(context, id as u32);
|
||||
if !copy.is_null() {
|
||||
// TODO: handle cleanup and return early instead
|
||||
send_msg(context, 0, &mut copy).unwrap();
|
||||
send_msg(context, 0, copy).unwrap();
|
||||
}
|
||||
dc_msg_unref(copy);
|
||||
}
|
||||
}
|
||||
msg.param.remove(Param::PrepForwards);
|
||||
(*msg).param.remove(Param::PrepForwards);
|
||||
dc_msg_save_param_to_disk(msg);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(msg.id)
|
||||
Ok((*msg).id)
|
||||
}
|
||||
|
||||
pub unsafe fn send_text_msg(
|
||||
@@ -923,12 +949,11 @@ pub unsafe fn send_text_msg(
|
||||
);
|
||||
|
||||
let mut msg = dc_msg_new(context, Viewtype::Text);
|
||||
msg.text = Some(text_to_send);
|
||||
send_msg(context, chat_id, &mut msg)
|
||||
(*msg).text = Some(text_to_send);
|
||||
send_msg(context, chat_id, msg)
|
||||
}
|
||||
|
||||
// passing `None` as message jsut deletes the draft
|
||||
pub unsafe fn set_draft(context: &Context, chat_id: u32, msg: Option<&mut Message>) {
|
||||
pub unsafe fn set_draft(context: &Context, chat_id: u32, msg: *mut dc_msg_t) {
|
||||
if chat_id <= DC_CHAT_ID_LAST_SPECIAL as u32 {
|
||||
return;
|
||||
}
|
||||
@@ -937,32 +962,31 @@ pub unsafe fn set_draft(context: &Context, chat_id: u32, msg: Option<&mut Messag
|
||||
};
|
||||
}
|
||||
|
||||
// similar to as dc_set_draft() but does not emit an event
|
||||
#[allow(non_snake_case)]
|
||||
unsafe fn set_draft_raw(context: &Context, chat_id: u32, mut msg: Option<&mut Message>) -> bool {
|
||||
unsafe fn set_draft_raw(context: &Context, chat_id: u32, msg: *mut dc_msg_t) -> bool {
|
||||
let mut OK_TO_CONTINUE = true;
|
||||
|
||||
// similar to as dc_set_draft() but does not emit an event
|
||||
let prev_draft_msg_id: u32;
|
||||
let mut sth_changed = false;
|
||||
|
||||
let prev_draft_msg_id = get_draft_msg_id(context, chat_id);
|
||||
prev_draft_msg_id = get_draft_msg_id(context, chat_id);
|
||||
if 0 != prev_draft_msg_id {
|
||||
dc_delete_msg_from_db(context, prev_draft_msg_id);
|
||||
sth_changed = true;
|
||||
}
|
||||
|
||||
if let Some(ref mut msg) = msg {
|
||||
// save new draft
|
||||
if msg.type_0 == Viewtype::Text {
|
||||
OK_TO_CONTINUE = msg.text.as_ref().map_or(false, |s| !s.is_empty());
|
||||
} else if msgtype_has_file(msg.type_0) {
|
||||
if let Some(path_filename) = msg.param.get(Param::File) {
|
||||
// save new draft
|
||||
if !msg.is_null() {
|
||||
if (*msg).type_0 == Viewtype::Text {
|
||||
OK_TO_CONTINUE = (*msg).text.as_ref().map_or(false, |s| !s.is_empty());
|
||||
} else if msgtype_has_file((*msg).type_0) {
|
||||
if let Some(path_filename) = (*msg).param.get(Param::File) {
|
||||
let mut path_filename = path_filename.to_string();
|
||||
if 0 != dc_msg_is_increation(msg) && !dc_is_blobdir_path(context, &path_filename) {
|
||||
OK_TO_CONTINUE = false;
|
||||
} else if !dc_make_rel_and_copy(context, &mut path_filename) {
|
||||
OK_TO_CONTINUE = false;
|
||||
} else {
|
||||
msg.param.set(Param::File, path_filename);
|
||||
(*msg).param.set(Param::File, path_filename);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -978,10 +1002,10 @@ unsafe fn set_draft_raw(context: &Context, chat_id: u32, mut msg: Option<&mut Me
|
||||
chat_id as i32,
|
||||
1,
|
||||
time(),
|
||||
msg.type_0,
|
||||
(*msg).type_0,
|
||||
MessageState::OutDraft,
|
||||
msg.text.as_ref().map(String::as_str).unwrap_or(""),
|
||||
msg.param.to_string(),
|
||||
(*msg).text.as_ref().map(String::as_str).unwrap_or(""),
|
||||
(*msg).param.to_string(),
|
||||
1,
|
||||
],
|
||||
)
|
||||
@@ -991,6 +1015,7 @@ unsafe fn set_draft_raw(context: &Context, chat_id: u32, mut msg: Option<&mut Me
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sth_changed
|
||||
}
|
||||
|
||||
@@ -1006,12 +1031,21 @@ fn get_draft_msg_id(context: &Context, chat_id: u32) -> u32 {
|
||||
.unwrap_or_default() as u32
|
||||
}
|
||||
|
||||
pub unsafe fn get_draft(context: &Context, chat_id: u32) -> Result<Message, Error> {
|
||||
ensure!(chat_id > DC_CHAT_ID_LAST_SPECIAL as u32, "Invalid chat ID");
|
||||
pub unsafe fn get_draft(context: &Context, chat_id: u32) -> *mut dc_msg_t {
|
||||
if chat_id <= DC_CHAT_ID_LAST_SPECIAL as u32 {
|
||||
return ptr::null_mut();
|
||||
}
|
||||
let draft_msg_id = get_draft_msg_id(context, chat_id);
|
||||
ensure!(draft_msg_id != 0, "Invalid draft message ID");
|
||||
if draft_msg_id == 0 {
|
||||
return ptr::null_mut();
|
||||
}
|
||||
let draft_msg = dc_msg_new_untyped(context);
|
||||
if !dc_msg_load_from_db(draft_msg, context, draft_msg_id) {
|
||||
dc_msg_unref(draft_msg);
|
||||
return ptr::null_mut();
|
||||
}
|
||||
|
||||
dc_msg_load_from_db(context, draft_msg_id)
|
||||
draft_msg
|
||||
}
|
||||
|
||||
pub fn get_chat_msgs(context: &Context, chat_id: u32, flags: u32, marker1before: u32) -> Vec<u32> {
|
||||
@@ -1031,7 +1065,7 @@ pub fn get_chat_msgs(context: &Context, chat_id: u32, flags: u32, marker1before:
|
||||
let curr_local_timestamp = ts + cnv_to_local;
|
||||
let curr_day = (curr_local_timestamp / 86400) as libc::c_int;
|
||||
if curr_day != last_day {
|
||||
ret.push(DC_MSG_ID_LAST_SPECIAL);
|
||||
ret.push(DC_MSG_ID_LAST_SPECIAL as u32);
|
||||
last_day = curr_day;
|
||||
}
|
||||
}
|
||||
@@ -1201,15 +1235,15 @@ pub unsafe fn get_next_media(
|
||||
msg_type3: Viewtype,
|
||||
) -> u32 {
|
||||
let mut ret = 0;
|
||||
|
||||
if let Ok(msg) = dc_msg_load_from_db(context, curr_msg_id) {
|
||||
let msg: *mut dc_msg_t = dc_msg_new_untyped(context);
|
||||
if dc_msg_load_from_db(msg, context, curr_msg_id) {
|
||||
let list = get_chat_media(
|
||||
context,
|
||||
msg.chat_id,
|
||||
(*msg).chat_id,
|
||||
if msg_type != Viewtype::Unknown {
|
||||
msg_type
|
||||
} else {
|
||||
msg.type_0
|
||||
(*msg).type_0
|
||||
},
|
||||
msg_type2,
|
||||
msg_type3,
|
||||
@@ -1229,6 +1263,8 @@ pub unsafe fn get_next_media(
|
||||
}
|
||||
}
|
||||
}
|
||||
dc_msg_unref(msg);
|
||||
|
||||
ret
|
||||
}
|
||||
|
||||
@@ -1364,9 +1400,10 @@ pub unsafe fn create_group_chat(
|
||||
|
||||
if chat_id != 0 {
|
||||
if 0 != add_to_chat_contacts_table(context, chat_id, 1) {
|
||||
let mut draft_msg = dc_msg_new(context, Viewtype::Text);
|
||||
dc_msg_set_text(&mut draft_msg, draft_txt.as_ptr());
|
||||
set_draft_raw(context, chat_id, Some(&mut draft_msg));
|
||||
let draft_msg = dc_msg_new(context, Viewtype::Text);
|
||||
dc_msg_set_text(draft_msg, draft_txt.as_ptr());
|
||||
set_draft_raw(context, chat_id, draft_msg);
|
||||
dc_msg_unref(draft_msg);
|
||||
}
|
||||
|
||||
context.call_cb(Event::MSGS_CHANGED, 0 as uintptr_t, 0 as uintptr_t);
|
||||
@@ -1469,21 +1506,21 @@ pub unsafe fn add_contact_to_chat_ex(
|
||||
}
|
||||
if OK_TO_CONTINUE {
|
||||
if chat.param.get_int(Param::Unpromoted).unwrap_or_default() == 0 {
|
||||
msg.type_0 = Viewtype::Text;
|
||||
msg.text = Some(context.stock_system_msg(
|
||||
(*msg).type_0 = Viewtype::Text;
|
||||
(*msg).text = Some(context.stock_system_msg(
|
||||
StockMessage::MsgAddMember,
|
||||
contact.get_addr(),
|
||||
"",
|
||||
DC_CONTACT_ID_SELF as u32,
|
||||
));
|
||||
msg.param.set_int(Param::Cmd, 4);
|
||||
msg.param.set(Param::Arg, contact.get_addr());
|
||||
msg.param.set_int(Param::Arg2, flags);
|
||||
msg.id = send_msg(context, chat_id, &mut msg).unwrap_or_default();
|
||||
(*msg).param.set_int(Param::Cmd, 4);
|
||||
(*msg).param.set(Param::Arg, contact.get_addr());
|
||||
(*msg).param.set_int(Param::Arg2, flags);
|
||||
(*msg).id = send_msg(context, chat_id, msg).unwrap_or_default();
|
||||
context.call_cb(
|
||||
Event::MSGS_CHANGED,
|
||||
chat_id as uintptr_t,
|
||||
msg.id as uintptr_t,
|
||||
(*msg).id as uintptr_t,
|
||||
);
|
||||
}
|
||||
context.call_cb(Event::MSGS_CHANGED, chat_id as uintptr_t, 0 as uintptr_t);
|
||||
@@ -1493,6 +1530,8 @@ pub unsafe fn add_contact_to_chat_ex(
|
||||
}
|
||||
}
|
||||
|
||||
dc_msg_unref(msg);
|
||||
|
||||
success
|
||||
}
|
||||
|
||||
@@ -1580,30 +1619,30 @@ pub unsafe fn remove_contact_from_chat(
|
||||
/* we should respect this - whatever we send to the group, it gets discarded anyway! */
|
||||
if let Ok(contact) = Contact::get_by_id(context, contact_id) {
|
||||
if chat.param.get_int(Param::Unpromoted).unwrap_or_default() == 0 {
|
||||
msg.type_0 = Viewtype::Text;
|
||||
(*msg).type_0 = Viewtype::Text;
|
||||
if contact.id == DC_CONTACT_ID_SELF as u32 {
|
||||
set_group_explicitly_left(context, chat.grpid).unwrap();
|
||||
msg.text = Some(context.stock_system_msg(
|
||||
(*msg).text = Some(context.stock_system_msg(
|
||||
StockMessage::MsgGroupLeft,
|
||||
"",
|
||||
"",
|
||||
DC_CONTACT_ID_SELF as u32,
|
||||
));
|
||||
} else {
|
||||
msg.text = Some(context.stock_system_msg(
|
||||
(*msg).text = Some(context.stock_system_msg(
|
||||
StockMessage::MsgDelMember,
|
||||
contact.get_addr(),
|
||||
"",
|
||||
DC_CONTACT_ID_SELF as u32,
|
||||
));
|
||||
}
|
||||
msg.param.set_int(Param::Cmd, 5);
|
||||
msg.param.set(Param::Arg, contact.get_addr());
|
||||
msg.id = send_msg(context, chat_id, &mut msg).unwrap_or_default();
|
||||
(*msg).param.set_int(Param::Cmd, 5);
|
||||
(*msg).param.set(Param::Arg, contact.get_addr());
|
||||
(*msg).id = send_msg(context, chat_id, msg).unwrap_or_default();
|
||||
context.call_cb(
|
||||
Event::MSGS_CHANGED,
|
||||
chat_id as uintptr_t,
|
||||
msg.id as uintptr_t,
|
||||
(*msg).id as uintptr_t,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1621,6 +1660,8 @@ pub unsafe fn remove_contact_from_chat(
|
||||
}
|
||||
}
|
||||
|
||||
dc_msg_unref(msg);
|
||||
|
||||
if !success {
|
||||
bail!("Failed to remove contact");
|
||||
}
|
||||
@@ -1687,22 +1728,22 @@ pub unsafe fn set_chat_name(
|
||||
.is_ok()
|
||||
{
|
||||
if chat.param.get_int(Param::Unpromoted).unwrap_or_default() == 0 {
|
||||
msg.type_0 = Viewtype::Text;
|
||||
msg.text = Some(context.stock_system_msg(
|
||||
(*msg).type_0 = Viewtype::Text;
|
||||
(*msg).text = Some(context.stock_system_msg(
|
||||
StockMessage::MsgGrpName,
|
||||
&chat.name,
|
||||
new_name.as_ref(),
|
||||
DC_CONTACT_ID_SELF as u32,
|
||||
));
|
||||
msg.param.set_int(Param::Cmd, 2);
|
||||
(*msg).param.set_int(Param::Cmd, 2);
|
||||
if !chat.name.is_empty() {
|
||||
msg.param.set(Param::Arg, &chat.name);
|
||||
(*msg).param.set(Param::Arg, &chat.name);
|
||||
}
|
||||
msg.id = send_msg(context, chat_id, &mut msg).unwrap_or_default();
|
||||
(*msg).id = send_msg(context, chat_id, msg).unwrap_or_default();
|
||||
context.call_cb(
|
||||
Event::MSGS_CHANGED,
|
||||
chat_id as uintptr_t,
|
||||
msg.id as uintptr_t,
|
||||
(*msg).id as uintptr_t,
|
||||
);
|
||||
}
|
||||
context.call_cb(
|
||||
@@ -1715,6 +1756,8 @@ pub unsafe fn set_chat_name(
|
||||
}
|
||||
}
|
||||
|
||||
dc_msg_unref(msg);
|
||||
|
||||
if !success {
|
||||
bail!("Failed to set name");
|
||||
}
|
||||
@@ -1763,12 +1806,12 @@ pub unsafe fn set_chat_profile_image(
|
||||
}
|
||||
if chat.update_param().is_ok() {
|
||||
if chat.param.get_int(Param::Unpromoted).unwrap_or_default() == 0 {
|
||||
msg.param.set_int(Param::Cmd, 3);
|
||||
(*msg).param.set_int(Param::Cmd, 3);
|
||||
if let Some(ref new_image_rel) = new_image_rel {
|
||||
msg.param.set(Param::Arg, new_image_rel);
|
||||
(*msg).param.set(Param::Arg, new_image_rel);
|
||||
}
|
||||
msg.type_0 = Viewtype::Text;
|
||||
msg.text = Some(context.stock_system_msg(
|
||||
(*msg).type_0 = Viewtype::Text;
|
||||
(*msg).text = Some(context.stock_system_msg(
|
||||
if new_image_rel.is_some() {
|
||||
StockMessage::MsgGrpImgChanged
|
||||
} else {
|
||||
@@ -1778,11 +1821,11 @@ pub unsafe fn set_chat_profile_image(
|
||||
"",
|
||||
DC_CONTACT_ID_SELF as u32,
|
||||
));
|
||||
msg.id = send_msg(context, chat_id, &mut msg).unwrap_or_default();
|
||||
(*msg).id = send_msg(context, chat_id, msg).unwrap_or_default();
|
||||
context.call_cb(
|
||||
Event::MSGS_CHANGED,
|
||||
chat_id as uintptr_t,
|
||||
msg.id as uintptr_t,
|
||||
(*msg).id as uintptr_t,
|
||||
);
|
||||
}
|
||||
context.call_cb(
|
||||
@@ -1795,6 +1838,8 @@ pub unsafe fn set_chat_profile_image(
|
||||
}
|
||||
}
|
||||
|
||||
dc_msg_unref(msg);
|
||||
|
||||
if !success {
|
||||
bail!("Failed to set profile image");
|
||||
}
|
||||
@@ -1812,6 +1857,7 @@ pub unsafe fn forward_msgs(
|
||||
return;
|
||||
}
|
||||
|
||||
let msg = dc_msg_new_untyped(context);
|
||||
let mut created_db_entries = Vec::new();
|
||||
let mut curr_timestamp: i64;
|
||||
|
||||
@@ -1841,45 +1887,45 @@ pub unsafe fn forward_msgs(
|
||||
|
||||
for id in ids {
|
||||
let src_msg_id = id;
|
||||
let msg = dc_msg_load_from_db(context, src_msg_id as u32);
|
||||
if msg.is_err() {
|
||||
if !dc_msg_load_from_db(msg, context, src_msg_id as u32) {
|
||||
break;
|
||||
}
|
||||
let mut msg = msg.unwrap();
|
||||
let original_param = msg.param.clone();
|
||||
if msg.from_id != DC_CONTACT_ID_SELF as u32 {
|
||||
msg.param.set_int(Param::Forwarded, 1);
|
||||
let original_param = (*msg).param.clone();
|
||||
if (*msg).from_id != DC_CONTACT_ID_SELF as u32 {
|
||||
(*msg).param.set_int(Param::Forwarded, 1);
|
||||
}
|
||||
msg.param.remove(Param::GuranteeE2ee);
|
||||
msg.param.remove(Param::ForcePlaintext);
|
||||
msg.param.remove(Param::Cmd);
|
||||
(*msg).param.remove(Param::GuranteeE2ee);
|
||||
(*msg).param.remove(Param::ForcePlaintext);
|
||||
(*msg).param.remove(Param::Cmd);
|
||||
|
||||
let new_msg_id: u32;
|
||||
if msg.state == MessageState::OutPreparing {
|
||||
if (*msg).state == MessageState::OutPreparing {
|
||||
let fresh9 = curr_timestamp;
|
||||
curr_timestamp = curr_timestamp + 1;
|
||||
new_msg_id = chat
|
||||
.prepare_msg_raw(context, &mut msg, fresh9)
|
||||
.prepare_msg_raw(context, msg, fresh9)
|
||||
.unwrap_or_default();
|
||||
let save_param = msg.param.clone();
|
||||
msg.param = original_param;
|
||||
msg.id = src_msg_id as u32;
|
||||
let save_param = (*msg).param.clone();
|
||||
(*msg).param = original_param;
|
||||
(*msg).id = src_msg_id as u32;
|
||||
|
||||
if let Some(old_fwd) = msg.param.get(Param::PrepForwards) {
|
||||
if let Some(old_fwd) = (*msg).param.get(Param::PrepForwards) {
|
||||
let new_fwd = format!("{} {}", old_fwd, new_msg_id);
|
||||
msg.param.set(Param::PrepForwards, new_fwd);
|
||||
(*msg).param.set(Param::PrepForwards, new_fwd);
|
||||
} else {
|
||||
msg.param.set(Param::PrepForwards, new_msg_id.to_string());
|
||||
(*msg)
|
||||
.param
|
||||
.set(Param::PrepForwards, new_msg_id.to_string());
|
||||
}
|
||||
|
||||
dc_msg_save_param_to_disk(&mut msg);
|
||||
msg.param = save_param;
|
||||
dc_msg_save_param_to_disk(msg);
|
||||
(*msg).param = save_param;
|
||||
} else {
|
||||
msg.state = MessageState::OutPending;
|
||||
(*msg).state = MessageState::OutPending;
|
||||
let fresh10 = curr_timestamp;
|
||||
curr_timestamp = curr_timestamp + 1;
|
||||
new_msg_id = chat
|
||||
.prepare_msg_raw(context, &mut msg, fresh10)
|
||||
.prepare_msg_raw(context, msg, fresh10)
|
||||
.unwrap_or_default();
|
||||
job_send_msg(context, new_msg_id);
|
||||
}
|
||||
@@ -1895,6 +1941,7 @@ pub unsafe fn forward_msgs(
|
||||
created_db_entries[i + 1] as uintptr_t,
|
||||
);
|
||||
}
|
||||
dc_msg_unref(msg);
|
||||
}
|
||||
|
||||
pub fn get_chat_contact_cnt(context: &Context, chat_id: u32) -> libc::c_int {
|
||||
|
||||
@@ -2,9 +2,9 @@ use crate::chat::*;
|
||||
use crate::constants::*;
|
||||
use crate::contact::*;
|
||||
use crate::context::*;
|
||||
use crate::dc_msg::*;
|
||||
use crate::error::Result;
|
||||
use crate::lot::Lot;
|
||||
use crate::message::*;
|
||||
use crate::stock::StockMessage;
|
||||
|
||||
/// An object representing a single chatlist in memory.
|
||||
@@ -275,36 +275,29 @@ impl<'a> Chatlist<'a> {
|
||||
let mut lastcontact = None;
|
||||
|
||||
let lastmsg = if 0 != lastmsg_id {
|
||||
if let Ok(lastmsg) = dc_msg_load_from_db(self.context, lastmsg_id) {
|
||||
if lastmsg.from_id != 1 as libc::c_uint
|
||||
&& (chat.typ == Chattype::Group || chat.typ == Chattype::VerifiedGroup)
|
||||
{
|
||||
lastcontact = Contact::load_from_db(self.context, lastmsg.from_id).ok();
|
||||
}
|
||||
let lastmsg = dc_msg_new_untyped(self.context);
|
||||
dc_msg_load_from_db(lastmsg, self.context, lastmsg_id);
|
||||
|
||||
Some(lastmsg)
|
||||
} else {
|
||||
None
|
||||
if (*lastmsg).from_id != 1 as libc::c_uint
|
||||
&& (chat.typ == Chattype::Group || chat.typ == Chattype::VerifiedGroup)
|
||||
{
|
||||
lastcontact = Contact::load_from_db(self.context, (*lastmsg).from_id).ok();
|
||||
}
|
||||
lastmsg
|
||||
} else {
|
||||
None
|
||||
std::ptr::null_mut()
|
||||
};
|
||||
|
||||
if chat.id == DC_CHAT_ID_ARCHIVED_LINK as u32 {
|
||||
ret.text2 = None;
|
||||
} else if lastmsg.is_none()
|
||||
|| lastmsg.as_ref().unwrap().from_id == DC_CONTACT_ID_UNDEFINED as u32
|
||||
{
|
||||
} else if lastmsg.is_null() || (*lastmsg).from_id == DC_CONTACT_ID_UNDEFINED as u32 {
|
||||
ret.text2 = Some(self.context.stock_str(StockMessage::NoMessages).to_string());
|
||||
} else {
|
||||
ret.fill(
|
||||
&mut lastmsg.unwrap(),
|
||||
chat,
|
||||
lastcontact.as_ref(),
|
||||
self.context,
|
||||
);
|
||||
ret.fill(lastmsg, chat, lastcontact.as_ref(), self.context);
|
||||
}
|
||||
|
||||
dc_msg_unref(lastmsg);
|
||||
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,224 +0,0 @@
|
||||
use quick_xml;
|
||||
use quick_xml::events::{BytesEnd, BytesStart, BytesText};
|
||||
|
||||
use crate::context::Context;
|
||||
use crate::dc_loginparam::*;
|
||||
use crate::dc_tools::*;
|
||||
use crate::x::*;
|
||||
|
||||
use super::read_autoconf_file;
|
||||
/* ******************************************************************************
|
||||
* Thunderbird's Autoconfigure
|
||||
******************************************************************************/
|
||||
/* documentation: https://developer.mozilla.org/en-US/docs/Mozilla/Thunderbird/Autoconfiguration */
|
||||
#[repr(C)]
|
||||
struct moz_autoconfigure_t<'a> {
|
||||
pub in_0: &'a dc_loginparam_t,
|
||||
pub in_emaildomain: *mut libc::c_char,
|
||||
pub in_emaillocalpart: *mut libc::c_char,
|
||||
pub out: dc_loginparam_t,
|
||||
pub out_imap_set: libc::c_int,
|
||||
pub out_smtp_set: libc::c_int,
|
||||
pub tag_server: libc::c_int,
|
||||
pub tag_config: libc::c_int,
|
||||
}
|
||||
|
||||
pub unsafe fn moz_autoconfigure(
|
||||
context: &Context,
|
||||
url: &str,
|
||||
param_in: &dc_loginparam_t,
|
||||
) -> Option<dc_loginparam_t> {
|
||||
let mut moz_ac = moz_autoconfigure_t {
|
||||
in_0: param_in,
|
||||
in_emaildomain: std::ptr::null_mut(),
|
||||
in_emaillocalpart: std::ptr::null_mut(),
|
||||
out: dc_loginparam_new(),
|
||||
out_imap_set: 0,
|
||||
out_smtp_set: 0,
|
||||
tag_server: 0,
|
||||
tag_config: 0,
|
||||
};
|
||||
|
||||
let url_c = url.strdup();
|
||||
let xml_raw = read_autoconf_file(context, url_c);
|
||||
free(url_c as *mut libc::c_void);
|
||||
if xml_raw.is_null() {
|
||||
return None;
|
||||
}
|
||||
|
||||
moz_ac.in_emaillocalpart = param_in.addr.strdup();
|
||||
let p = strchr(moz_ac.in_emaillocalpart, '@' as i32);
|
||||
|
||||
if p.is_null() {
|
||||
free(xml_raw as *mut libc::c_void);
|
||||
free(moz_ac.in_emaildomain as *mut libc::c_void);
|
||||
free(moz_ac.in_emaillocalpart as *mut libc::c_void);
|
||||
return None;
|
||||
}
|
||||
|
||||
*p = 0 as libc::c_char;
|
||||
moz_ac.in_emaildomain = dc_strdup(p.offset(1isize));
|
||||
|
||||
let mut reader = quick_xml::Reader::from_str(as_str(xml_raw));
|
||||
reader.trim_text(true);
|
||||
|
||||
let mut buf = Vec::new();
|
||||
|
||||
loop {
|
||||
match reader.read_event(&mut buf) {
|
||||
Ok(quick_xml::events::Event::Start(ref e)) => {
|
||||
moz_autoconfigure_starttag_cb(e, &mut moz_ac, &reader)
|
||||
}
|
||||
Ok(quick_xml::events::Event::End(ref e)) => moz_autoconfigure_endtag_cb(e, &mut moz_ac),
|
||||
Ok(quick_xml::events::Event::Text(ref e)) => {
|
||||
moz_autoconfigure_text_cb(e, &mut moz_ac, &reader)
|
||||
}
|
||||
Err(e) => {
|
||||
error!(
|
||||
context,
|
||||
0,
|
||||
"Configure xml: Error at position {}: {:?}",
|
||||
reader.buffer_position(),
|
||||
e
|
||||
);
|
||||
}
|
||||
Ok(quick_xml::events::Event::Eof) => break,
|
||||
_ => (),
|
||||
}
|
||||
buf.clear();
|
||||
}
|
||||
|
||||
if moz_ac.out.mail_server.is_empty()
|
||||
|| moz_ac.out.mail_port == 0
|
||||
|| moz_ac.out.send_server.is_empty()
|
||||
|| moz_ac.out.send_port == 0
|
||||
{
|
||||
let r = dc_loginparam_get_readable(&moz_ac.out);
|
||||
warn!(context, 0, "Bad or incomplete autoconfig: {}", r,);
|
||||
free(xml_raw as *mut libc::c_void);
|
||||
free(moz_ac.in_emaildomain as *mut libc::c_void);
|
||||
free(moz_ac.in_emaillocalpart as *mut libc::c_void);
|
||||
return None;
|
||||
}
|
||||
|
||||
free(xml_raw as *mut libc::c_void);
|
||||
free(moz_ac.in_emaildomain as *mut libc::c_void);
|
||||
free(moz_ac.in_emaillocalpart as *mut libc::c_void);
|
||||
Some(moz_ac.out)
|
||||
}
|
||||
|
||||
fn moz_autoconfigure_text_cb<B: std::io::BufRead>(
|
||||
event: &BytesText,
|
||||
moz_ac: &mut moz_autoconfigure_t,
|
||||
reader: &quick_xml::Reader<B>,
|
||||
) {
|
||||
let val = event.unescape_and_decode(reader).unwrap_or_default();
|
||||
|
||||
let addr = &moz_ac.in_0.addr;
|
||||
let email_local = as_str(moz_ac.in_emaillocalpart);
|
||||
let email_domain = as_str(moz_ac.in_emaildomain);
|
||||
|
||||
let val = val
|
||||
.trim()
|
||||
.replace("%EMAILADDRESS%", addr)
|
||||
.replace("%EMAILLOCALPART%", email_local)
|
||||
.replace("%EMAILDOMAIN%", email_domain);
|
||||
|
||||
if moz_ac.tag_server == 1 {
|
||||
match moz_ac.tag_config {
|
||||
10 => moz_ac.out.mail_server = val,
|
||||
11 => moz_ac.out.mail_port = val.parse().unwrap_or_default(),
|
||||
12 => moz_ac.out.mail_user = val,
|
||||
13 => {
|
||||
let val_lower = val.to_lowercase();
|
||||
if val_lower == "ssl" {
|
||||
moz_ac.out.server_flags |= 0x200
|
||||
}
|
||||
if val_lower == "starttls" {
|
||||
moz_ac.out.server_flags |= 0x100
|
||||
}
|
||||
if val_lower == "plain" {
|
||||
moz_ac.out.server_flags |= 0x400
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
} else if moz_ac.tag_server == 2 {
|
||||
match moz_ac.tag_config {
|
||||
10 => moz_ac.out.send_server = val,
|
||||
11 => moz_ac.out.send_port = val.parse().unwrap_or_default(),
|
||||
12 => moz_ac.out.send_user = val,
|
||||
13 => {
|
||||
let val_lower = val.to_lowercase();
|
||||
if val_lower == "ssl" {
|
||||
moz_ac.out.server_flags |= 0x20000
|
||||
}
|
||||
if val_lower == "starttls" {
|
||||
moz_ac.out.server_flags |= 0x10000
|
||||
}
|
||||
if val_lower == "plain" {
|
||||
moz_ac.out.server_flags |= 0x40000
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn moz_autoconfigure_endtag_cb(event: &BytesEnd, moz_ac: &mut moz_autoconfigure_t) {
|
||||
let tag = String::from_utf8_lossy(event.name()).trim().to_lowercase();
|
||||
|
||||
if tag == "incomingserver" {
|
||||
moz_ac.tag_server = 0;
|
||||
moz_ac.tag_config = 0;
|
||||
moz_ac.out_imap_set = 1;
|
||||
} else if tag == "outgoingserver" {
|
||||
moz_ac.tag_server = 0;
|
||||
moz_ac.tag_config = 0;
|
||||
moz_ac.out_smtp_set = 1;
|
||||
} else {
|
||||
moz_ac.tag_config = 0;
|
||||
}
|
||||
}
|
||||
|
||||
fn moz_autoconfigure_starttag_cb<B: std::io::BufRead>(
|
||||
event: &BytesStart,
|
||||
moz_ac: &mut moz_autoconfigure_t,
|
||||
reader: &quick_xml::Reader<B>,
|
||||
) {
|
||||
let tag = String::from_utf8_lossy(event.name()).trim().to_lowercase();
|
||||
|
||||
if tag == "incomingserver" {
|
||||
moz_ac.tag_server = if let Some(typ) = event.attributes().find(|attr| {
|
||||
attr.as_ref()
|
||||
.map(|a| String::from_utf8_lossy(a.key).trim().to_lowercase() == "type")
|
||||
.unwrap_or_default()
|
||||
}) {
|
||||
let typ = typ
|
||||
.unwrap()
|
||||
.unescape_and_decode_value(reader)
|
||||
.unwrap_or_default()
|
||||
.to_lowercase();
|
||||
|
||||
if typ == "imap" && moz_ac.out_imap_set == 0 {
|
||||
1
|
||||
} else {
|
||||
0
|
||||
}
|
||||
} else {
|
||||
0
|
||||
};
|
||||
moz_ac.tag_config = 0;
|
||||
} else if tag == "outgoingserver" {
|
||||
moz_ac.tag_server = if moz_ac.out_smtp_set == 0 { 2 } else { 0 };
|
||||
moz_ac.tag_config = 0;
|
||||
} else if tag == "hostname" {
|
||||
moz_ac.tag_config = 10;
|
||||
} else if tag == "port" {
|
||||
moz_ac.tag_config = 11;
|
||||
} else if tag == "sockettype" {
|
||||
moz_ac.tag_config = 13;
|
||||
} else if tag == "username" {
|
||||
moz_ac.tag_config = 12;
|
||||
}
|
||||
}
|
||||
@@ -1,213 +0,0 @@
|
||||
use quick_xml;
|
||||
use quick_xml::events::{BytesEnd, BytesStart, BytesText};
|
||||
|
||||
use crate::context::Context;
|
||||
use crate::dc_loginparam::*;
|
||||
use crate::dc_tools::*;
|
||||
use crate::x::*;
|
||||
use std::ptr;
|
||||
|
||||
use super::read_autoconf_file;
|
||||
/* ******************************************************************************
|
||||
* Outlook's Autodiscover
|
||||
******************************************************************************/
|
||||
#[repr(C)]
|
||||
struct outlk_autodiscover_t<'a> {
|
||||
pub in_0: &'a dc_loginparam_t,
|
||||
pub out: dc_loginparam_t,
|
||||
pub out_imap_set: libc::c_int,
|
||||
pub out_smtp_set: libc::c_int,
|
||||
pub tag_config: libc::c_int,
|
||||
pub config: [*mut libc::c_char; 6],
|
||||
pub redirect: *mut libc::c_char,
|
||||
}
|
||||
|
||||
pub unsafe fn outlk_autodiscover(
|
||||
context: &Context,
|
||||
url__: &str,
|
||||
param_in: &dc_loginparam_t,
|
||||
) -> Option<dc_loginparam_t> {
|
||||
let mut xml_raw: *mut libc::c_char = ptr::null_mut();
|
||||
let mut url = url__.strdup();
|
||||
let mut outlk_ad = outlk_autodiscover_t {
|
||||
in_0: param_in,
|
||||
out: dc_loginparam_new(),
|
||||
out_imap_set: 0,
|
||||
out_smtp_set: 0,
|
||||
tag_config: 0,
|
||||
config: [ptr::null_mut(); 6],
|
||||
redirect: ptr::null_mut(),
|
||||
};
|
||||
let ok_to_continue;
|
||||
let mut i = 0;
|
||||
loop {
|
||||
if !(i < 10) {
|
||||
ok_to_continue = true;
|
||||
break;
|
||||
}
|
||||
memset(
|
||||
&mut outlk_ad as *mut outlk_autodiscover_t as *mut libc::c_void,
|
||||
0,
|
||||
::std::mem::size_of::<outlk_autodiscover_t>(),
|
||||
);
|
||||
xml_raw = read_autoconf_file(context, url);
|
||||
if xml_raw.is_null() {
|
||||
ok_to_continue = false;
|
||||
break;
|
||||
}
|
||||
|
||||
let mut reader = quick_xml::Reader::from_str(as_str(xml_raw));
|
||||
reader.trim_text(true);
|
||||
|
||||
let mut buf = Vec::new();
|
||||
|
||||
loop {
|
||||
match reader.read_event(&mut buf) {
|
||||
Ok(quick_xml::events::Event::Start(ref e)) => {
|
||||
outlk_autodiscover_starttag_cb(e, &mut outlk_ad)
|
||||
}
|
||||
Ok(quick_xml::events::Event::End(ref e)) => {
|
||||
outlk_autodiscover_endtag_cb(e, &mut outlk_ad)
|
||||
}
|
||||
Ok(quick_xml::events::Event::Text(ref e)) => {
|
||||
outlk_autodiscover_text_cb(e, &mut outlk_ad, &reader)
|
||||
}
|
||||
Err(e) => {
|
||||
error!(
|
||||
context,
|
||||
0,
|
||||
"Configure xml: Error at position {}: {:?}",
|
||||
reader.buffer_position(),
|
||||
e
|
||||
);
|
||||
}
|
||||
Ok(quick_xml::events::Event::Eof) => break,
|
||||
_ => (),
|
||||
}
|
||||
buf.clear();
|
||||
}
|
||||
|
||||
if !(!outlk_ad.config[5].is_null()
|
||||
&& 0 != *outlk_ad.config[5usize].offset(0isize) as libc::c_int)
|
||||
{
|
||||
ok_to_continue = true;
|
||||
break;
|
||||
}
|
||||
free(url as *mut libc::c_void);
|
||||
url = dc_strdup(outlk_ad.config[5usize]);
|
||||
|
||||
outlk_clean_config(&mut outlk_ad);
|
||||
free(xml_raw as *mut libc::c_void);
|
||||
xml_raw = ptr::null_mut();
|
||||
i += 1;
|
||||
}
|
||||
|
||||
if ok_to_continue {
|
||||
if outlk_ad.out.mail_server.is_empty()
|
||||
|| outlk_ad.out.mail_port == 0
|
||||
|| outlk_ad.out.send_server.is_empty()
|
||||
|| outlk_ad.out.send_port == 0
|
||||
{
|
||||
let r = dc_loginparam_get_readable(&outlk_ad.out);
|
||||
warn!(context, 0, "Bad or incomplete autoconfig: {}", r,);
|
||||
free(url as *mut libc::c_void);
|
||||
free(xml_raw as *mut libc::c_void);
|
||||
outlk_clean_config(&mut outlk_ad);
|
||||
|
||||
return None;
|
||||
}
|
||||
}
|
||||
free(url as *mut libc::c_void);
|
||||
free(xml_raw as *mut libc::c_void);
|
||||
outlk_clean_config(&mut outlk_ad);
|
||||
Some(outlk_ad.out)
|
||||
}
|
||||
|
||||
unsafe fn outlk_clean_config(mut outlk_ad: *mut outlk_autodiscover_t) {
|
||||
for i in 0..6 {
|
||||
free((*outlk_ad).config[i] as *mut libc::c_void);
|
||||
(*outlk_ad).config[i] = 0 as *mut libc::c_char;
|
||||
}
|
||||
}
|
||||
|
||||
fn outlk_autodiscover_text_cb<B: std::io::BufRead>(
|
||||
event: &BytesText,
|
||||
outlk_ad: &mut outlk_autodiscover_t,
|
||||
reader: &quick_xml::Reader<B>,
|
||||
) {
|
||||
let val = event.unescape_and_decode(reader).unwrap_or_default();
|
||||
|
||||
unsafe {
|
||||
free(outlk_ad.config[outlk_ad.tag_config as usize].cast());
|
||||
outlk_ad.config[outlk_ad.tag_config as usize] = val.trim().strdup();
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn outlk_autodiscover_endtag_cb(event: &BytesEnd, outlk_ad: &mut outlk_autodiscover_t) {
|
||||
let tag = String::from_utf8_lossy(event.name()).trim().to_lowercase();
|
||||
|
||||
if tag == "protocol" {
|
||||
if !outlk_ad.config[1].is_null() {
|
||||
let port = dc_atoi_null_is_0(outlk_ad.config[3]);
|
||||
let ssl_on = (!outlk_ad.config[4].is_null()
|
||||
&& strcasecmp(
|
||||
outlk_ad.config[4],
|
||||
b"on\x00" as *const u8 as *const libc::c_char,
|
||||
) == 0) as libc::c_int;
|
||||
let ssl_off = (!outlk_ad.config[4].is_null()
|
||||
&& strcasecmp(
|
||||
outlk_ad.config[4],
|
||||
b"off\x00" as *const u8 as *const libc::c_char,
|
||||
) == 0) as libc::c_int;
|
||||
if strcasecmp(
|
||||
outlk_ad.config[1],
|
||||
b"imap\x00" as *const u8 as *const libc::c_char,
|
||||
) == 0
|
||||
&& outlk_ad.out_imap_set == 0
|
||||
{
|
||||
outlk_ad.out.mail_server = to_string(outlk_ad.config[2]);
|
||||
outlk_ad.out.mail_port = port;
|
||||
if 0 != ssl_on {
|
||||
outlk_ad.out.server_flags |= 0x200
|
||||
} else if 0 != ssl_off {
|
||||
outlk_ad.out.server_flags |= 0x400
|
||||
}
|
||||
outlk_ad.out_imap_set = 1
|
||||
} else if strcasecmp(
|
||||
outlk_ad.config[1usize],
|
||||
b"smtp\x00" as *const u8 as *const libc::c_char,
|
||||
) == 0
|
||||
&& outlk_ad.out_smtp_set == 0
|
||||
{
|
||||
outlk_ad.out.send_server = to_string(outlk_ad.config[2]);
|
||||
outlk_ad.out.send_port = port;
|
||||
if 0 != ssl_on {
|
||||
outlk_ad.out.server_flags |= 0x20000
|
||||
} else if 0 != ssl_off {
|
||||
outlk_ad.out.server_flags |= 0x40000
|
||||
}
|
||||
outlk_ad.out_smtp_set = 1
|
||||
}
|
||||
}
|
||||
outlk_clean_config(outlk_ad);
|
||||
}
|
||||
outlk_ad.tag_config = 0;
|
||||
}
|
||||
|
||||
fn outlk_autodiscover_starttag_cb(event: &BytesStart, outlk_ad: &mut outlk_autodiscover_t) {
|
||||
let tag = String::from_utf8_lossy(event.name()).trim().to_lowercase();
|
||||
|
||||
if tag == "protocol" {
|
||||
unsafe { outlk_clean_config(outlk_ad) };
|
||||
} else if tag == "type" {
|
||||
outlk_ad.tag_config = 1
|
||||
} else if tag == "server" {
|
||||
outlk_ad.tag_config = 2
|
||||
} else if tag == "port" {
|
||||
outlk_ad.tag_config = 3
|
||||
} else if tag == "ssl" {
|
||||
outlk_ad.tag_config = 4
|
||||
} else if tag == "redirecturl" {
|
||||
outlk_ad.tag_config = 5
|
||||
};
|
||||
}
|
||||
@@ -108,7 +108,7 @@ impl Default for Chattype {
|
||||
|
||||
pub const DC_MSG_ID_MARKER1: usize = 1;
|
||||
const DC_MSG_ID_DAYMARKER: usize = 9;
|
||||
pub const DC_MSG_ID_LAST_SPECIAL: u32 = 9;
|
||||
pub const DC_MSG_ID_LAST_SPECIAL: usize = 9;
|
||||
|
||||
/// approx. max. length returned by dc_msg_get_text()
|
||||
const DC_MAX_GET_TEXT_LEN: usize = 30000;
|
||||
@@ -125,19 +125,19 @@ pub const DC_CREATE_MVBOX: usize = 1;
|
||||
#[repr(i32)]
|
||||
#[derive(Debug, Display, Clone, Copy, PartialEq, Eq, FromPrimitive, ToPrimitive, ToSql, FromSql)]
|
||||
pub enum Delay {
|
||||
Default = 0,
|
||||
AtOnce = -1,
|
||||
Do_not_try_again = 0,
|
||||
At_once = -1,
|
||||
Standard = 3,
|
||||
IncreationPoll = 2,
|
||||
Increation_poll = 2,
|
||||
}
|
||||
|
||||
|
||||
// Flags for configuring IMAP and SMTP servers.
|
||||
// These flags are optional
|
||||
// and may be set together with the username, password etc.
|
||||
// via dc_set_config() using the key "server_flags".
|
||||
|
||||
/// Force OAuth2 authorization. This flag does not skip automatic configuration.
|
||||
/// Before calling configure() with DC_LP_AUTH_OAUTH2 set,
|
||||
/// Before calling dc_configure() with DC_LP_AUTH_OAUTH2 set,
|
||||
/// the user has to confirm access at the URL returned by dc_get_oauth2_url().
|
||||
pub const DC_LP_AUTH_OAUTH2: usize = 0x2;
|
||||
|
||||
@@ -291,7 +291,7 @@ pub enum Event {
|
||||
/// As most things are asynchronous, things may go wrong at any time and the user
|
||||
/// should not be disturbed by a dialog or so. Instead, use a bubble or so.
|
||||
///
|
||||
/// However, for ongoing processes (eg. configure())
|
||||
/// However, for ongoing processes (eg. dc_configure())
|
||||
/// or for functions that are expected to fail (eg. dc_continue_key_transfer())
|
||||
/// it might be better to delay showing these events until the function has really
|
||||
/// failed (returned false). It should be sufficient to report only the _last_ error
|
||||
@@ -409,7 +409,7 @@ pub enum Event {
|
||||
/// @return 0
|
||||
LOCATION_CHANGED = 2035,
|
||||
|
||||
/// Inform about the configuration progress started by configure().
|
||||
/// Inform about the configuration progress started by dc_configure().
|
||||
///
|
||||
/// @param data1 (int) 0=error, 1-999=progress in permille, 1000=success and done
|
||||
/// @param data2 0
|
||||
|
||||
@@ -9,10 +9,10 @@ use crate::constants::*;
|
||||
use crate::context::Context;
|
||||
use crate::dc_e2ee::*;
|
||||
use crate::dc_loginparam::*;
|
||||
use crate::dc_msg::MessageState;
|
||||
use crate::dc_tools::*;
|
||||
use crate::error::Result;
|
||||
use crate::key::*;
|
||||
use crate::message::MessageState;
|
||||
use crate::peerstate::*;
|
||||
use crate::sql;
|
||||
use crate::stock::StockMessage;
|
||||
@@ -911,6 +911,7 @@ fn get_first_name<'a>(full_name: &'a str) -> &'a str {
|
||||
/// Returns false if addr is an invalid address, otherwise true.
|
||||
pub fn may_be_valid_addr(addr: &str) -> bool {
|
||||
let res = addr.parse::<EmailAddress>();
|
||||
println!("{:?}", res);
|
||||
res.is_ok()
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ use crate::constants::*;
|
||||
use crate::contact::*;
|
||||
use crate::dc_loginparam::*;
|
||||
use crate::dc_move::*;
|
||||
use crate::dc_msg::*;
|
||||
use crate::dc_receive_imf::*;
|
||||
use crate::dc_tools::*;
|
||||
use crate::imap::*;
|
||||
@@ -12,7 +13,6 @@ use crate::job::*;
|
||||
use crate::job_thread::JobThread;
|
||||
use crate::key::*;
|
||||
use crate::lot::Lot;
|
||||
use crate::message::*;
|
||||
use crate::param::Params;
|
||||
use crate::smtp::*;
|
||||
use crate::sql::Sql;
|
||||
@@ -193,41 +193,43 @@ unsafe fn cb_precheck_imf(
|
||||
server_folder: &str,
|
||||
server_uid: uint32_t,
|
||||
) -> libc::c_int {
|
||||
let rfc724_mid = as_str(rfc724_mid)
|
||||
.trim_start_matches("<")
|
||||
.trim_end_matches(">");
|
||||
|
||||
let mut mark_seen = false;
|
||||
info!(
|
||||
let mut rfc724_mid_exists: libc::c_int = 0i32;
|
||||
let msg_id: uint32_t;
|
||||
let mut old_server_folder: *mut libc::c_char = ptr::null_mut();
|
||||
let mut old_server_uid: uint32_t = 0i32 as uint32_t;
|
||||
let mut mark_seen: libc::c_int = 0i32;
|
||||
msg_id = dc_rfc724_mid_exists(
|
||||
context,
|
||||
0,
|
||||
"cb_precheck_imf rfc724_mid={:?}, server_folder={}, server_uid={}",
|
||||
rfc724_mid,
|
||||
server_folder,
|
||||
server_uid
|
||||
&mut old_server_folder,
|
||||
&mut old_server_uid,
|
||||
);
|
||||
if let Some(res) = dc_rfc724_mid_exists_with_msg_state(context, rfc724_mid) {
|
||||
let (msg_id, _, old_server_folder, old_server_uid) = res;
|
||||
info!(context, 0, "precheck msg_id={}", msg_id);
|
||||
if msg_id != 0 {
|
||||
if old_server_folder.is_empty() {
|
||||
info!(context, 0, "[move] detected bbc-self {}", rfc724_mid,);
|
||||
mark_seen = true;
|
||||
} else if old_server_folder != server_folder {
|
||||
info!(context, 0, "[move] detected moved message {}", rfc724_mid,);
|
||||
}
|
||||
dc_update_msg_move_state(context, rfc724_mid, MoveState::Stay);
|
||||
}
|
||||
if old_server_folder != server_folder || old_server_uid != server_uid {
|
||||
if msg_id != 0i32 as libc::c_uint {
|
||||
rfc724_mid_exists = 1i32;
|
||||
if *old_server_folder.offset(0isize) as libc::c_int == 0i32
|
||||
&& old_server_uid == 0i32 as libc::c_uint
|
||||
{
|
||||
info!(
|
||||
context,
|
||||
0, "precheck updated server_uid for msg_id={}", msg_id
|
||||
0,
|
||||
"[move] detected bbc-self {}",
|
||||
as_str(rfc724_mid),
|
||||
);
|
||||
mark_seen = 1i32
|
||||
} else if as_str(old_server_folder) != server_folder {
|
||||
info!(
|
||||
context,
|
||||
0,
|
||||
"[move] detected moved message {}",
|
||||
as_str(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);
|
||||
job_retry_msg_actions_at_once(context, msg_id);
|
||||
}
|
||||
dc_do_heuristics_moves(context, server_folder, msg_id);
|
||||
if mark_seen {
|
||||
if 0 != mark_seen {
|
||||
job_add(
|
||||
context,
|
||||
Action::MarkseenMsgOnImap,
|
||||
@@ -236,9 +238,9 @@ unsafe fn cb_precheck_imf(
|
||||
0,
|
||||
);
|
||||
}
|
||||
return msg_id as i32;
|
||||
}
|
||||
0
|
||||
free(old_server_folder as *mut libc::c_void);
|
||||
rfc724_mid_exists
|
||||
}
|
||||
|
||||
fn cb_set_config(context: &Context, key: &str, value: Option<&str>) {
|
||||
|
||||
206
src/dc_array.rs
206
src/dc_array.rs
@@ -1,4 +1,5 @@
|
||||
use crate::dc_location::dc_location;
|
||||
use crate::dc_tools::*;
|
||||
use crate::types::*;
|
||||
|
||||
/* * the structure behind dc_array_t */
|
||||
@@ -19,6 +20,10 @@ impl dc_array_t {
|
||||
dc_array_t::Locations(Vec::with_capacity(capacity))
|
||||
}
|
||||
|
||||
pub fn into_raw(self) -> *mut Self {
|
||||
Box::into_raw(Box::new(self))
|
||||
}
|
||||
|
||||
pub fn add_id(&mut self, item: uint32_t) {
|
||||
if let Self::Uint(array) = self {
|
||||
array.push(item);
|
||||
@@ -50,6 +55,34 @@ impl dc_array_t {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_latitude(&self, index: usize) -> libc::c_double {
|
||||
self.get_location(index).latitude
|
||||
}
|
||||
|
||||
pub fn get_longitude(&self, index: size_t) -> libc::c_double {
|
||||
self.get_location(index).longitude
|
||||
}
|
||||
|
||||
pub fn get_accuracy(&self, index: size_t) -> libc::c_double {
|
||||
self.get_location(index).accuracy
|
||||
}
|
||||
|
||||
pub fn get_timestamp(&self, index: size_t) -> i64 {
|
||||
self.get_location(index).timestamp
|
||||
}
|
||||
|
||||
pub fn get_chat_id(&self, index: size_t) -> uint32_t {
|
||||
self.get_location(index).chat_id
|
||||
}
|
||||
|
||||
pub fn get_contact_id(&self, index: size_t) -> uint32_t {
|
||||
self.get_location(index).contact_id
|
||||
}
|
||||
|
||||
pub fn get_msg_id(&self, index: size_t) -> uint32_t {
|
||||
self.get_location(index).msg_id
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
match self {
|
||||
Self::Locations(array) => array.is_empty(),
|
||||
@@ -92,14 +125,6 @@ impl dc_array_t {
|
||||
panic!("Attempt to sort array of something other than uints");
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_ptr(&self) -> *const u32 {
|
||||
if let dc_array_t::Uint(v) = self {
|
||||
v.as_ptr()
|
||||
} else {
|
||||
panic!("Attempt to convert array of something other than uints to raw");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Vec<u32>> for dc_array_t {
|
||||
@@ -114,50 +139,155 @@ impl From<Vec<dc_location>> for dc_array_t {
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn dc_array_unref(array: *mut dc_array_t) {
|
||||
assert!(!array.is_null());
|
||||
Box::from_raw(array);
|
||||
}
|
||||
|
||||
pub unsafe fn dc_array_add_id(array: *mut dc_array_t, item: uint32_t) {
|
||||
assert!(!array.is_null());
|
||||
(*array).add_id(item);
|
||||
}
|
||||
|
||||
pub unsafe fn dc_array_get_cnt(array: *const dc_array_t) -> size_t {
|
||||
assert!(!array.is_null());
|
||||
(*array).len()
|
||||
}
|
||||
|
||||
pub unsafe fn dc_array_get_id(array: *const dc_array_t, index: size_t) -> uint32_t {
|
||||
assert!(!array.is_null());
|
||||
(*array).get_id(index)
|
||||
}
|
||||
|
||||
pub unsafe fn dc_array_get_marker(array: *const dc_array_t, index: size_t) -> *mut libc::c_char {
|
||||
assert!(!array.is_null());
|
||||
|
||||
if let dc_array_t::Locations(v) = &*array {
|
||||
if let Some(s) = &v[index].marker {
|
||||
s.strdup()
|
||||
} else {
|
||||
std::ptr::null_mut()
|
||||
}
|
||||
} else {
|
||||
panic!("Not an array of locations");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the independent-state of the location at the given index.
|
||||
* Independent locations do not belong to the track of the user.
|
||||
*
|
||||
* @memberof dc_array_t
|
||||
* @param array The array object.
|
||||
* @param index Index of the item. Must be between 0 and dc_array_get_cnt()-1.
|
||||
* @return 0=Location belongs to the track of the user,
|
||||
* 1=Location was reported independently.
|
||||
*/
|
||||
pub unsafe fn dc_array_is_independent(array: *const dc_array_t, index: size_t) -> libc::c_int {
|
||||
assert!(!array.is_null());
|
||||
|
||||
if let dc_array_t::Locations(v) = &*array {
|
||||
v[index].independent as libc::c_int
|
||||
} else {
|
||||
panic!("Attempt to get location independent field from array of something other than locations");
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn dc_array_search_id(
|
||||
array: *const dc_array_t,
|
||||
needle: uint32_t,
|
||||
ret_index: *mut size_t,
|
||||
) -> bool {
|
||||
assert!(!array.is_null());
|
||||
|
||||
if let Some(i) = (*array).search_id(needle) {
|
||||
if !ret_index.is_null() {
|
||||
*ret_index = i
|
||||
}
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn dc_array_get_raw(array: *const dc_array_t) -> *const u32 {
|
||||
assert!(!array.is_null());
|
||||
|
||||
if let dc_array_t::Uint(v) = &*array {
|
||||
v.as_ptr()
|
||||
} else {
|
||||
panic!("Attempt to convert array of something other than uints to raw");
|
||||
}
|
||||
}
|
||||
|
||||
pub fn dc_array_new(initsize: size_t) -> *mut dc_array_t {
|
||||
dc_array_t::new(initsize).into_raw()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
unsafe fn dc_array_empty(array: *mut dc_array_t) {
|
||||
assert!(!array.is_null());
|
||||
|
||||
(*array).clear()
|
||||
}
|
||||
|
||||
pub unsafe fn dc_array_duplicate(array: *const dc_array_t) -> *mut dc_array_t {
|
||||
assert!(!array.is_null());
|
||||
|
||||
(*array).clone().into_raw()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_dc_array() {
|
||||
let mut arr = dc_array_t::new(7);
|
||||
assert!(arr.is_empty());
|
||||
unsafe {
|
||||
let arr = dc_array_new(7 as size_t);
|
||||
assert_eq!(dc_array_get_cnt(arr), 0);
|
||||
|
||||
for i in 0..1000 {
|
||||
arr.add_id(i + 2);
|
||||
for i in 0..1000 {
|
||||
dc_array_add_id(arr, (i + 2) as uint32_t);
|
||||
}
|
||||
|
||||
assert_eq!(dc_array_get_cnt(arr), 1000);
|
||||
|
||||
for i in 0..1000 {
|
||||
assert_eq!(
|
||||
dc_array_get_id(arr, i as size_t),
|
||||
(i + 1i32 * 2i32) as libc::c_uint
|
||||
);
|
||||
}
|
||||
|
||||
dc_array_empty(arr);
|
||||
|
||||
assert_eq!(dc_array_get_cnt(arr), 0);
|
||||
|
||||
dc_array_add_id(arr, 13 as uint32_t);
|
||||
dc_array_add_id(arr, 7 as uint32_t);
|
||||
dc_array_add_id(arr, 666 as uint32_t);
|
||||
dc_array_add_id(arr, 0 as uint32_t);
|
||||
dc_array_add_id(arr, 5000 as uint32_t);
|
||||
|
||||
(*arr).sort_ids();
|
||||
|
||||
assert_eq!(dc_array_get_id(arr, 0 as size_t), 0);
|
||||
assert_eq!(dc_array_get_id(arr, 1 as size_t), 7);
|
||||
assert_eq!(dc_array_get_id(arr, 2 as size_t), 13);
|
||||
assert_eq!(dc_array_get_id(arr, 3 as size_t), 666);
|
||||
|
||||
dc_array_unref(arr);
|
||||
}
|
||||
|
||||
assert_eq!(arr.len(), 1000);
|
||||
|
||||
for i in 0..1000 {
|
||||
assert_eq!(arr.get_id(i), (i + 2) as u32);
|
||||
}
|
||||
|
||||
arr.clear();
|
||||
|
||||
assert!(arr.is_empty());
|
||||
|
||||
arr.add_id(13);
|
||||
arr.add_id(7);
|
||||
arr.add_id(666);
|
||||
arr.add_id(0);
|
||||
arr.add_id(5000);
|
||||
|
||||
arr.sort_ids();
|
||||
|
||||
assert_eq!(arr.get_id(0), 0);
|
||||
assert_eq!(arr.get_id(1), 7);
|
||||
assert_eq!(arr.get_id(2), 13);
|
||||
assert_eq!(arr.get_id(3), 666);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_dc_array_out_of_bounds() {
|
||||
let mut arr = dc_array_t::new(7);
|
||||
let arr = dc_array_new(7);
|
||||
for i in 0..1000 {
|
||||
arr.add_id(i + 2);
|
||||
unsafe { dc_array_add_id(arr, (i + 2) as uint32_t) };
|
||||
}
|
||||
arr.get_id(1000);
|
||||
unsafe { dc_array_get_id(arr, 1000) };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
use percent_encoding::{utf8_percent_encode, NON_ALPHANUMERIC};
|
||||
use quick_xml;
|
||||
use quick_xml::events::{BytesEnd, BytesStart, BytesText};
|
||||
|
||||
use crate::constants::Event;
|
||||
use crate::context::Context;
|
||||
@@ -10,11 +12,8 @@ use crate::job::*;
|
||||
use crate::oauth2::*;
|
||||
use crate::param::Params;
|
||||
use crate::types::*;
|
||||
|
||||
mod auto_outlook;
|
||||
use auto_outlook::outlk_autodiscover;
|
||||
mod auto_mozilla;
|
||||
use auto_mozilla::moz_autoconfigure;
|
||||
use crate::x::*;
|
||||
use std::ptr;
|
||||
|
||||
macro_rules! progress {
|
||||
($context:tt, $progress:expr) => {
|
||||
@@ -30,8 +29,47 @@ macro_rules! progress {
|
||||
};
|
||||
}
|
||||
|
||||
/* ******************************************************************************
|
||||
* Configure folders
|
||||
******************************************************************************/
|
||||
#[derive(Copy, Clone)]
|
||||
#[repr(C)]
|
||||
struct dc_imapfolder_t {
|
||||
pub name_to_select: *mut libc::c_char,
|
||||
pub name_utf8: *mut libc::c_char,
|
||||
pub meaning: libc::c_int,
|
||||
}
|
||||
/* ******************************************************************************
|
||||
* Thunderbird's Autoconfigure
|
||||
******************************************************************************/
|
||||
/* documentation: https://developer.mozilla.org/en-US/docs/Mozilla/Thunderbird/Autoconfiguration */
|
||||
#[repr(C)]
|
||||
struct moz_autoconfigure_t<'a> {
|
||||
pub in_0: &'a dc_loginparam_t,
|
||||
pub in_emaildomain: *mut libc::c_char,
|
||||
pub in_emaillocalpart: *mut libc::c_char,
|
||||
pub out: dc_loginparam_t,
|
||||
pub out_imap_set: libc::c_int,
|
||||
pub out_smtp_set: libc::c_int,
|
||||
pub tag_server: libc::c_int,
|
||||
pub tag_config: libc::c_int,
|
||||
}
|
||||
|
||||
/* ******************************************************************************
|
||||
* Outlook's Autodiscover
|
||||
******************************************************************************/
|
||||
#[repr(C)]
|
||||
struct outlk_autodiscover_t<'a> {
|
||||
pub in_0: &'a dc_loginparam_t,
|
||||
pub out: dc_loginparam_t,
|
||||
pub out_imap_set: libc::c_int,
|
||||
pub out_smtp_set: libc::c_int,
|
||||
pub tag_config: libc::c_int,
|
||||
pub config: [*mut libc::c_char; 6],
|
||||
pub redirect: *mut libc::c_char,
|
||||
}
|
||||
// connect
|
||||
pub unsafe fn configure(context: &Context) {
|
||||
pub unsafe fn dc_configure(context: &Context) {
|
||||
if 0 != dc_has_ongoing(context) {
|
||||
warn!(
|
||||
context,
|
||||
@@ -654,6 +692,413 @@ pub unsafe fn dc_free_ongoing(context: &Context) {
|
||||
s.shall_stop_ongoing = true;
|
||||
}
|
||||
|
||||
unsafe fn moz_autoconfigure(
|
||||
context: &Context,
|
||||
url: &str,
|
||||
param_in: &dc_loginparam_t,
|
||||
) -> Option<dc_loginparam_t> {
|
||||
let mut moz_ac = moz_autoconfigure_t {
|
||||
in_0: param_in,
|
||||
in_emaildomain: std::ptr::null_mut(),
|
||||
in_emaillocalpart: std::ptr::null_mut(),
|
||||
out: dc_loginparam_new(),
|
||||
out_imap_set: 0,
|
||||
out_smtp_set: 0,
|
||||
tag_server: 0,
|
||||
tag_config: 0,
|
||||
};
|
||||
|
||||
let url_c = url.strdup();
|
||||
let xml_raw = read_autoconf_file(context, url_c);
|
||||
free(url_c as *mut libc::c_void);
|
||||
if xml_raw.is_null() {
|
||||
return None;
|
||||
}
|
||||
|
||||
moz_ac.in_emaillocalpart = param_in.addr.strdup();
|
||||
let p = strchr(moz_ac.in_emaillocalpart, '@' as i32);
|
||||
|
||||
if p.is_null() {
|
||||
free(xml_raw as *mut libc::c_void);
|
||||
free(moz_ac.in_emaildomain as *mut libc::c_void);
|
||||
free(moz_ac.in_emaillocalpart as *mut libc::c_void);
|
||||
return None;
|
||||
}
|
||||
|
||||
*p = 0 as libc::c_char;
|
||||
moz_ac.in_emaildomain = dc_strdup(p.offset(1isize));
|
||||
|
||||
let mut reader = quick_xml::Reader::from_str(as_str(xml_raw));
|
||||
reader.trim_text(true);
|
||||
|
||||
let mut buf = Vec::new();
|
||||
|
||||
loop {
|
||||
match reader.read_event(&mut buf) {
|
||||
Ok(quick_xml::events::Event::Start(ref e)) => {
|
||||
moz_autoconfigure_starttag_cb(e, &mut moz_ac, &reader)
|
||||
}
|
||||
Ok(quick_xml::events::Event::End(ref e)) => moz_autoconfigure_endtag_cb(e, &mut moz_ac),
|
||||
Ok(quick_xml::events::Event::Text(ref e)) => {
|
||||
moz_autoconfigure_text_cb(e, &mut moz_ac, &reader)
|
||||
}
|
||||
Err(e) => {
|
||||
error!(
|
||||
context,
|
||||
0,
|
||||
"Configure xml: Error at position {}: {:?}",
|
||||
reader.buffer_position(),
|
||||
e
|
||||
);
|
||||
}
|
||||
Ok(quick_xml::events::Event::Eof) => break,
|
||||
_ => (),
|
||||
}
|
||||
buf.clear();
|
||||
}
|
||||
|
||||
if moz_ac.out.mail_server.is_empty()
|
||||
|| moz_ac.out.mail_port == 0
|
||||
|| moz_ac.out.send_server.is_empty()
|
||||
|| moz_ac.out.send_port == 0
|
||||
{
|
||||
let r = dc_loginparam_get_readable(&moz_ac.out);
|
||||
warn!(context, 0, "Bad or incomplete autoconfig: {}", r,);
|
||||
free(xml_raw as *mut libc::c_void);
|
||||
free(moz_ac.in_emaildomain as *mut libc::c_void);
|
||||
free(moz_ac.in_emaillocalpart as *mut libc::c_void);
|
||||
return None;
|
||||
}
|
||||
|
||||
free(xml_raw as *mut libc::c_void);
|
||||
free(moz_ac.in_emaildomain as *mut libc::c_void);
|
||||
free(moz_ac.in_emaillocalpart as *mut libc::c_void);
|
||||
Some(moz_ac.out)
|
||||
}
|
||||
|
||||
fn moz_autoconfigure_text_cb<B: std::io::BufRead>(
|
||||
event: &BytesText,
|
||||
moz_ac: &mut moz_autoconfigure_t,
|
||||
reader: &quick_xml::Reader<B>,
|
||||
) {
|
||||
let val = event.unescape_and_decode(reader).unwrap_or_default();
|
||||
|
||||
let addr = &moz_ac.in_0.addr;
|
||||
let email_local = as_str(moz_ac.in_emaillocalpart);
|
||||
let email_domain = as_str(moz_ac.in_emaildomain);
|
||||
|
||||
let val = val
|
||||
.trim()
|
||||
.replace("%EMAILADDRESS%", addr)
|
||||
.replace("%EMAILLOCALPART%", email_local)
|
||||
.replace("%EMAILDOMAIN%", email_domain);
|
||||
|
||||
if moz_ac.tag_server == 1 {
|
||||
match moz_ac.tag_config {
|
||||
10 => moz_ac.out.mail_server = val,
|
||||
11 => moz_ac.out.mail_port = val.parse().unwrap_or_default(),
|
||||
12 => moz_ac.out.mail_user = val,
|
||||
13 => {
|
||||
let val_lower = val.to_lowercase();
|
||||
if val_lower == "ssl" {
|
||||
moz_ac.out.server_flags |= 0x200
|
||||
}
|
||||
if val_lower == "starttls" {
|
||||
moz_ac.out.server_flags |= 0x100
|
||||
}
|
||||
if val_lower == "plain" {
|
||||
moz_ac.out.server_flags |= 0x400
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
} else if moz_ac.tag_server == 2 {
|
||||
match moz_ac.tag_config {
|
||||
10 => moz_ac.out.send_server = val,
|
||||
11 => moz_ac.out.send_port = val.parse().unwrap_or_default(),
|
||||
12 => moz_ac.out.send_user = val,
|
||||
13 => {
|
||||
let val_lower = val.to_lowercase();
|
||||
if val_lower == "ssl" {
|
||||
moz_ac.out.server_flags |= 0x20000
|
||||
}
|
||||
if val_lower == "starttls" {
|
||||
moz_ac.out.server_flags |= 0x10000
|
||||
}
|
||||
if val_lower == "plain" {
|
||||
moz_ac.out.server_flags |= 0x40000
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn moz_autoconfigure_endtag_cb(event: &BytesEnd, moz_ac: &mut moz_autoconfigure_t) {
|
||||
let tag = String::from_utf8_lossy(event.name()).trim().to_lowercase();
|
||||
|
||||
if tag == "incomingserver" {
|
||||
moz_ac.tag_server = 0;
|
||||
moz_ac.tag_config = 0;
|
||||
moz_ac.out_imap_set = 1;
|
||||
} else if tag == "outgoingserver" {
|
||||
moz_ac.tag_server = 0;
|
||||
moz_ac.tag_config = 0;
|
||||
moz_ac.out_smtp_set = 1;
|
||||
} else {
|
||||
moz_ac.tag_config = 0;
|
||||
}
|
||||
}
|
||||
|
||||
fn moz_autoconfigure_starttag_cb<B: std::io::BufRead>(
|
||||
event: &BytesStart,
|
||||
moz_ac: &mut moz_autoconfigure_t,
|
||||
reader: &quick_xml::Reader<B>,
|
||||
) {
|
||||
let tag = String::from_utf8_lossy(event.name()).trim().to_lowercase();
|
||||
|
||||
if tag == "incomingserver" {
|
||||
moz_ac.tag_server = if let Some(typ) = event.attributes().find(|attr| {
|
||||
attr.as_ref()
|
||||
.map(|a| String::from_utf8_lossy(a.key).trim().to_lowercase() == "type")
|
||||
.unwrap_or_default()
|
||||
}) {
|
||||
let typ = typ
|
||||
.unwrap()
|
||||
.unescape_and_decode_value(reader)
|
||||
.unwrap_or_default()
|
||||
.to_lowercase();
|
||||
|
||||
if typ == "imap" && moz_ac.out_imap_set == 0 {
|
||||
1
|
||||
} else {
|
||||
0
|
||||
}
|
||||
} else {
|
||||
0
|
||||
};
|
||||
moz_ac.tag_config = 0;
|
||||
} else if tag == "outgoingserver" {
|
||||
moz_ac.tag_server = if moz_ac.out_smtp_set == 0 { 2 } else { 0 };
|
||||
moz_ac.tag_config = 0;
|
||||
} else if tag == "hostname" {
|
||||
moz_ac.tag_config = 10;
|
||||
} else if tag == "port" {
|
||||
moz_ac.tag_config = 11;
|
||||
} else if tag == "sockettype" {
|
||||
moz_ac.tag_config = 13;
|
||||
} else if tag == "username" {
|
||||
moz_ac.tag_config = 12;
|
||||
}
|
||||
}
|
||||
|
||||
fn read_autoconf_file(context: &Context, url: *const libc::c_char) -> *mut libc::c_char {
|
||||
info!(context, 0, "Testing {} ...", to_string(url));
|
||||
|
||||
match reqwest::Client::new()
|
||||
.get(as_str(url))
|
||||
.send()
|
||||
.and_then(|mut res| res.text())
|
||||
{
|
||||
Ok(res) => unsafe { res.strdup() },
|
||||
Err(_err) => {
|
||||
info!(context, 0, "Can\'t read file.",);
|
||||
|
||||
std::ptr::null_mut()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn outlk_autodiscover(
|
||||
context: &Context,
|
||||
url__: &str,
|
||||
param_in: &dc_loginparam_t,
|
||||
) -> Option<dc_loginparam_t> {
|
||||
let mut xml_raw: *mut libc::c_char = ptr::null_mut();
|
||||
let mut url = url__.strdup();
|
||||
let mut outlk_ad = outlk_autodiscover_t {
|
||||
in_0: param_in,
|
||||
out: dc_loginparam_new(),
|
||||
out_imap_set: 0,
|
||||
out_smtp_set: 0,
|
||||
tag_config: 0,
|
||||
config: [ptr::null_mut(); 6],
|
||||
redirect: ptr::null_mut(),
|
||||
};
|
||||
let ok_to_continue;
|
||||
let mut i = 0;
|
||||
loop {
|
||||
if !(i < 10) {
|
||||
ok_to_continue = true;
|
||||
break;
|
||||
}
|
||||
memset(
|
||||
&mut outlk_ad as *mut outlk_autodiscover_t as *mut libc::c_void,
|
||||
0,
|
||||
::std::mem::size_of::<outlk_autodiscover_t>(),
|
||||
);
|
||||
xml_raw = read_autoconf_file(context, url);
|
||||
if xml_raw.is_null() {
|
||||
ok_to_continue = false;
|
||||
break;
|
||||
}
|
||||
|
||||
let mut reader = quick_xml::Reader::from_str(as_str(xml_raw));
|
||||
reader.trim_text(true);
|
||||
|
||||
let mut buf = Vec::new();
|
||||
|
||||
loop {
|
||||
match reader.read_event(&mut buf) {
|
||||
Ok(quick_xml::events::Event::Start(ref e)) => {
|
||||
outlk_autodiscover_starttag_cb(e, &mut outlk_ad)
|
||||
}
|
||||
Ok(quick_xml::events::Event::End(ref e)) => {
|
||||
outlk_autodiscover_endtag_cb(e, &mut outlk_ad)
|
||||
}
|
||||
Ok(quick_xml::events::Event::Text(ref e)) => {
|
||||
outlk_autodiscover_text_cb(e, &mut outlk_ad, &reader)
|
||||
}
|
||||
Err(e) => {
|
||||
error!(
|
||||
context,
|
||||
0,
|
||||
"Configure xml: Error at position {}: {:?}",
|
||||
reader.buffer_position(),
|
||||
e
|
||||
);
|
||||
}
|
||||
Ok(quick_xml::events::Event::Eof) => break,
|
||||
_ => (),
|
||||
}
|
||||
buf.clear();
|
||||
}
|
||||
|
||||
if !(!outlk_ad.config[5].is_null()
|
||||
&& 0 != *outlk_ad.config[5usize].offset(0isize) as libc::c_int)
|
||||
{
|
||||
ok_to_continue = true;
|
||||
break;
|
||||
}
|
||||
free(url as *mut libc::c_void);
|
||||
url = dc_strdup(outlk_ad.config[5usize]);
|
||||
|
||||
outlk_clean_config(&mut outlk_ad);
|
||||
free(xml_raw as *mut libc::c_void);
|
||||
xml_raw = ptr::null_mut();
|
||||
i += 1;
|
||||
}
|
||||
|
||||
if ok_to_continue {
|
||||
if outlk_ad.out.mail_server.is_empty()
|
||||
|| outlk_ad.out.mail_port == 0
|
||||
|| outlk_ad.out.send_server.is_empty()
|
||||
|| outlk_ad.out.send_port == 0
|
||||
{
|
||||
let r = dc_loginparam_get_readable(&outlk_ad.out);
|
||||
warn!(context, 0, "Bad or incomplete autoconfig: {}", r,);
|
||||
free(url as *mut libc::c_void);
|
||||
free(xml_raw as *mut libc::c_void);
|
||||
outlk_clean_config(&mut outlk_ad);
|
||||
|
||||
return None;
|
||||
}
|
||||
}
|
||||
free(url as *mut libc::c_void);
|
||||
free(xml_raw as *mut libc::c_void);
|
||||
outlk_clean_config(&mut outlk_ad);
|
||||
Some(outlk_ad.out)
|
||||
}
|
||||
|
||||
unsafe fn outlk_clean_config(mut outlk_ad: *mut outlk_autodiscover_t) {
|
||||
for i in 0..6 {
|
||||
free((*outlk_ad).config[i] as *mut libc::c_void);
|
||||
(*outlk_ad).config[i] = 0 as *mut libc::c_char;
|
||||
}
|
||||
}
|
||||
|
||||
fn outlk_autodiscover_text_cb<B: std::io::BufRead>(
|
||||
event: &BytesText,
|
||||
outlk_ad: &mut outlk_autodiscover_t,
|
||||
reader: &quick_xml::Reader<B>,
|
||||
) {
|
||||
let val = event.unescape_and_decode(reader).unwrap_or_default();
|
||||
|
||||
unsafe {
|
||||
free(outlk_ad.config[outlk_ad.tag_config as usize].cast());
|
||||
outlk_ad.config[outlk_ad.tag_config as usize] = val.trim().strdup();
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn outlk_autodiscover_endtag_cb(event: &BytesEnd, outlk_ad: &mut outlk_autodiscover_t) {
|
||||
let tag = String::from_utf8_lossy(event.name()).trim().to_lowercase();
|
||||
|
||||
if tag == "protocol" {
|
||||
if !outlk_ad.config[1].is_null() {
|
||||
let port = dc_atoi_null_is_0(outlk_ad.config[3]);
|
||||
let ssl_on = (!outlk_ad.config[4].is_null()
|
||||
&& strcasecmp(
|
||||
outlk_ad.config[4],
|
||||
b"on\x00" as *const u8 as *const libc::c_char,
|
||||
) == 0) as libc::c_int;
|
||||
let ssl_off = (!outlk_ad.config[4].is_null()
|
||||
&& strcasecmp(
|
||||
outlk_ad.config[4],
|
||||
b"off\x00" as *const u8 as *const libc::c_char,
|
||||
) == 0) as libc::c_int;
|
||||
if strcasecmp(
|
||||
outlk_ad.config[1],
|
||||
b"imap\x00" as *const u8 as *const libc::c_char,
|
||||
) == 0
|
||||
&& outlk_ad.out_imap_set == 0
|
||||
{
|
||||
outlk_ad.out.mail_server = to_string(outlk_ad.config[2]);
|
||||
outlk_ad.out.mail_port = port;
|
||||
if 0 != ssl_on {
|
||||
outlk_ad.out.server_flags |= 0x200
|
||||
} else if 0 != ssl_off {
|
||||
outlk_ad.out.server_flags |= 0x400
|
||||
}
|
||||
outlk_ad.out_imap_set = 1
|
||||
} else if strcasecmp(
|
||||
outlk_ad.config[1usize],
|
||||
b"smtp\x00" as *const u8 as *const libc::c_char,
|
||||
) == 0
|
||||
&& outlk_ad.out_smtp_set == 0
|
||||
{
|
||||
outlk_ad.out.send_server = to_string(outlk_ad.config[2]);
|
||||
outlk_ad.out.send_port = port;
|
||||
if 0 != ssl_on {
|
||||
outlk_ad.out.server_flags |= 0x20000
|
||||
} else if 0 != ssl_off {
|
||||
outlk_ad.out.server_flags |= 0x40000
|
||||
}
|
||||
outlk_ad.out_smtp_set = 1
|
||||
}
|
||||
}
|
||||
outlk_clean_config(outlk_ad);
|
||||
}
|
||||
outlk_ad.tag_config = 0;
|
||||
}
|
||||
|
||||
fn outlk_autodiscover_starttag_cb(event: &BytesStart, outlk_ad: &mut outlk_autodiscover_t) {
|
||||
let tag = String::from_utf8_lossy(event.name()).trim().to_lowercase();
|
||||
|
||||
if tag == "protocol" {
|
||||
unsafe { outlk_clean_config(outlk_ad) };
|
||||
} else if tag == "type" {
|
||||
outlk_ad.tag_config = 1
|
||||
} else if tag == "server" {
|
||||
outlk_ad.tag_config = 2
|
||||
} else if tag == "port" {
|
||||
outlk_ad.tag_config = 3
|
||||
} else if tag == "ssl" {
|
||||
outlk_ad.tag_config = 4
|
||||
} else if tag == "redirecturl" {
|
||||
outlk_ad.tag_config = 5
|
||||
};
|
||||
}
|
||||
|
||||
pub unsafe fn dc_alloc_ongoing(context: &Context) -> libc::c_int {
|
||||
if 0 != dc_has_ongoing(context) {
|
||||
warn!(
|
||||
@@ -694,20 +1139,3 @@ pub fn dc_connect_to_configured_imap(context: &Context, imap: &Imap) -> libc::c_
|
||||
|
||||
ret_connected
|
||||
}
|
||||
|
||||
pub fn read_autoconf_file(context: &Context, url: *const libc::c_char) -> *mut libc::c_char {
|
||||
info!(context, 0, "Testing {} ...", to_string(url));
|
||||
|
||||
match reqwest::Client::new()
|
||||
.get(as_str(url))
|
||||
.send()
|
||||
.and_then(|mut res| res.text())
|
||||
{
|
||||
Ok(res) => unsafe { res.strdup() },
|
||||
Err(_err) => {
|
||||
info!(context, 0, "Can\'t read file.",);
|
||||
|
||||
std::ptr::null_mut()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,15 +8,15 @@ use rand::{thread_rng, Rng};
|
||||
|
||||
use crate::chat;
|
||||
use crate::config::Config;
|
||||
use crate::configure::*;
|
||||
use crate::constants::*;
|
||||
use crate::context::Context;
|
||||
use crate::dc_configure::*;
|
||||
use crate::dc_e2ee::*;
|
||||
use crate::dc_msg::*;
|
||||
use crate::dc_tools::*;
|
||||
use crate::error::*;
|
||||
use crate::job::*;
|
||||
use crate::key::*;
|
||||
use crate::message::*;
|
||||
use crate::param::*;
|
||||
use crate::pgp::*;
|
||||
use crate::sql::{self, Sql};
|
||||
@@ -102,7 +102,7 @@ pub unsafe fn dc_imex_has_backup(
|
||||
|
||||
pub unsafe fn dc_initiate_key_transfer(context: &Context) -> *mut libc::c_char {
|
||||
let mut setup_file_name: *mut libc::c_char = ptr::null_mut();
|
||||
let mut msg: Message;
|
||||
let mut msg: *mut dc_msg_t = ptr::null_mut();
|
||||
if dc_alloc_ongoing(context) == 0 {
|
||||
return std::ptr::null_mut();
|
||||
}
|
||||
@@ -140,13 +140,14 @@ pub unsafe fn dc_initiate_key_transfer(context: &Context) -> *mut libc::c_char {
|
||||
{
|
||||
if let Ok(chat_id) = chat::create_by_contact_id(context, 1) {
|
||||
msg = dc_msg_new_untyped(context);
|
||||
msg.type_0 = Viewtype::File;
|
||||
msg.param.set(Param::File, as_str(setup_file_name));
|
||||
(*msg).type_0 = Viewtype::File;
|
||||
(*msg).param.set(Param::File, as_str(setup_file_name));
|
||||
|
||||
msg.param
|
||||
(*msg)
|
||||
.param
|
||||
.set(Param::MimeType, "application/autocrypt-setup");
|
||||
msg.param.set_int(Param::Cmd, 6);
|
||||
msg.param.set_int(Param::ForcePlaintext, 2);
|
||||
(*msg).param.set_int(Param::Cmd, 6);
|
||||
(*msg).param.set_int(Param::ForcePlaintext, 2);
|
||||
|
||||
if !context
|
||||
.running_state
|
||||
@@ -155,7 +156,9 @@ pub unsafe fn dc_initiate_key_transfer(context: &Context) -> *mut libc::c_char {
|
||||
.unwrap()
|
||||
.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, msg) {
|
||||
dc_msg_unref(msg);
|
||||
msg = ptr::null_mut();
|
||||
info!(context, 0, "Wait for setup message being sent ...",);
|
||||
loop {
|
||||
if context
|
||||
@@ -168,12 +171,13 @@ pub unsafe fn dc_initiate_key_transfer(context: &Context) -> *mut libc::c_char {
|
||||
break;
|
||||
}
|
||||
std::thread::sleep(std::time::Duration::from_secs(1));
|
||||
if let Ok(msg) = dc_get_msg(context, msg_id) {
|
||||
if 0 != dc_msg_is_sent(&msg) {
|
||||
info!(context, 0, "... setup message sent.",);
|
||||
break;
|
||||
}
|
||||
msg = dc_get_msg(context, msg_id);
|
||||
if 0 != dc_msg_is_sent(msg) {
|
||||
info!(context, 0, "... setup message sent.",);
|
||||
break;
|
||||
}
|
||||
dc_msg_unref(msg);
|
||||
msg = 0 as *mut dc_msg_t
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -183,6 +187,7 @@ pub unsafe fn dc_initiate_key_transfer(context: &Context) -> *mut libc::c_char {
|
||||
}
|
||||
}
|
||||
free(setup_file_name as *mut libc::c_void);
|
||||
dc_msg_unref(msg);
|
||||
dc_free_ongoing(context);
|
||||
|
||||
setup_code.strdup()
|
||||
@@ -279,17 +284,18 @@ pub unsafe fn dc_continue_key_transfer(
|
||||
setup_code: *const libc::c_char,
|
||||
) -> libc::c_int {
|
||||
let mut success: libc::c_int = 0i32;
|
||||
let mut msg: *mut dc_msg_t = ptr::null_mut();
|
||||
let mut filename: *mut libc::c_char = ptr::null_mut();
|
||||
let mut filecontent: *mut libc::c_char = ptr::null_mut();
|
||||
let mut filebytes: size_t = 0i32 as size_t;
|
||||
let mut armored_key: *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()) {
|
||||
let msg = dc_get_msg(context, msg_id);
|
||||
if msg.is_err()
|
||||
|| !dc_msg_is_setupmessage(msg.as_ref().unwrap())
|
||||
msg = dc_get_msg(context, msg_id);
|
||||
if msg.is_null()
|
||||
|| !dc_msg_is_setupmessage(msg)
|
||||
|| {
|
||||
filename = dc_msg_get_file(msg.as_ref().unwrap());
|
||||
filename = dc_msg_get_file(msg);
|
||||
filename.is_null()
|
||||
}
|
||||
|| *filename.offset(0isize) as libc::c_int == 0i32
|
||||
@@ -325,6 +331,7 @@ pub unsafe fn dc_continue_key_transfer(
|
||||
free(armored_key as *mut libc::c_void);
|
||||
free(filecontent as *mut libc::c_void);
|
||||
free(filename as *mut libc::c_void);
|
||||
dc_msg_unref(msg);
|
||||
free(norm_sc as *mut libc::c_void);
|
||||
|
||||
success
|
||||
|
||||
@@ -5,9 +5,9 @@ use crate::chat;
|
||||
use crate::constants::Event;
|
||||
use crate::constants::*;
|
||||
use crate::context::*;
|
||||
use crate::dc_msg::*;
|
||||
use crate::dc_tools::*;
|
||||
use crate::job::*;
|
||||
use crate::message::*;
|
||||
use crate::param::*;
|
||||
use crate::sql;
|
||||
use crate::stock::StockMessage;
|
||||
@@ -70,7 +70,7 @@ impl dc_kml_t {
|
||||
// location streaming
|
||||
pub unsafe fn dc_send_locations_to_chat(context: &Context, chat_id: uint32_t, seconds: i64) {
|
||||
let now = time();
|
||||
let mut msg: Message;
|
||||
let mut msg: *mut dc_msg_t = 0 as *mut dc_msg_t;
|
||||
let is_sending_locations_before: bool;
|
||||
if !(seconds < 0 || chat_id <= 9i32 as libc::c_uint) {
|
||||
is_sending_locations_before = dc_is_sending_locations_to_chat(context, chat_id);
|
||||
@@ -91,10 +91,10 @@ pub unsafe fn dc_send_locations_to_chat(context: &Context, chat_id: uint32_t, se
|
||||
{
|
||||
if 0 != seconds && !is_sending_locations_before {
|
||||
msg = dc_msg_new(context, Viewtype::Text);
|
||||
msg.text =
|
||||
(*msg).text =
|
||||
Some(context.stock_system_msg(StockMessage::MsgLocationEnabled, "", "", 0));
|
||||
msg.param.set_int(Param::Cmd, 8);
|
||||
chat::send_msg(context, chat_id, &mut msg).unwrap();
|
||||
(*msg).param.set_int(Param::Cmd, 8);
|
||||
chat::send_msg(context, chat_id, msg).unwrap();
|
||||
} else if 0 == seconds && is_sending_locations_before {
|
||||
let stock_str =
|
||||
context.stock_system_msg(StockMessage::MsgLocationDisabled, "", "", 0);
|
||||
@@ -117,6 +117,7 @@ pub unsafe fn dc_send_locations_to_chat(context: &Context, chat_id: uint32_t, se
|
||||
}
|
||||
}
|
||||
}
|
||||
dc_msg_unref(msg);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
@@ -679,10 +680,11 @@ pub unsafe fn dc_job_do_DC_JOB_MAYBE_SEND_LOCATIONS(context: &Context, _job: &Jo
|
||||
// (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);
|
||||
(*msg).hidden = 1;
|
||||
(*msg).param.set_int(Param::Cmd, 9);
|
||||
// TODO: handle cleanup on error
|
||||
chat::send_msg(context, chat_id as u32, &mut msg).unwrap();
|
||||
chat::send_msg(context, chat_id as u32, msg).unwrap();
|
||||
dc_msg_unref(msg);
|
||||
}
|
||||
Ok(())
|
||||
},
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,8 +1,7 @@
|
||||
use crate::constants::*;
|
||||
use crate::context::*;
|
||||
use crate::dc_tools::as_str;
|
||||
use crate::dc_msg::*;
|
||||
use crate::job::*;
|
||||
use crate::message::*;
|
||||
use crate::param::Params;
|
||||
|
||||
pub unsafe fn dc_do_heuristics_moves(context: &Context, folder: &str, msg_id: u32) {
|
||||
@@ -19,27 +18,29 @@ pub unsafe fn dc_do_heuristics_moves(context: &Context, folder: &str, msg_id: u3
|
||||
return;
|
||||
}
|
||||
|
||||
if let Ok(msg) = dc_msg_new_load(context, msg_id) {
|
||||
if dc_msg_is_setupmessage(&msg) {
|
||||
// do not move setup messages;
|
||||
// there may be a non-delta device that wants to handle it
|
||||
return;
|
||||
}
|
||||
|
||||
if dc_is_mvbox(context, folder) {
|
||||
dc_update_msg_move_state(context, as_str(msg.rfc724_mid), MoveState::Stay);
|
||||
}
|
||||
|
||||
// 1 = dc message, 2 = reply to dc message
|
||||
if 0 != msg.is_dc_message {
|
||||
job_add(
|
||||
context,
|
||||
Action::MoveMsg,
|
||||
msg.id as libc::c_int,
|
||||
Params::new(),
|
||||
0,
|
||||
);
|
||||
dc_update_msg_move_state(context, as_str(msg.rfc724_mid), MoveState::Moving);
|
||||
}
|
||||
let msg = dc_msg_new_load(context, msg_id);
|
||||
if dc_msg_is_setupmessage(msg) {
|
||||
// do not move setup messages;
|
||||
// there may be a non-delta device that wants to handle it
|
||||
dc_msg_unref(msg);
|
||||
return;
|
||||
}
|
||||
|
||||
if dc_is_mvbox(context, folder) {
|
||||
dc_update_msg_move_state(context, (*msg).rfc724_mid, MoveState::Stay);
|
||||
}
|
||||
|
||||
// 1 = dc message, 2 = reply to dc message
|
||||
if 0 != (*msg).is_dc_message {
|
||||
job_add(
|
||||
context,
|
||||
Action::MoveMsg,
|
||||
(*msg).id as libc::c_int,
|
||||
Params::new(),
|
||||
0,
|
||||
);
|
||||
dc_update_msg_move_state(context, (*msg).rfc724_mid, MoveState::Moving);
|
||||
}
|
||||
|
||||
dc_msg_unref(msg);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -17,12 +17,12 @@ use crate::context::Context;
|
||||
use crate::dc_location::*;
|
||||
use crate::dc_mimeparser::*;
|
||||
use crate::dc_move::*;
|
||||
use crate::dc_msg::*;
|
||||
use crate::dc_securejoin::*;
|
||||
use crate::dc_strencode::*;
|
||||
use crate::dc_tools::*;
|
||||
use crate::error::Result;
|
||||
use crate::job::*;
|
||||
use crate::message::*;
|
||||
use crate::param::*;
|
||||
use crate::peerstate::*;
|
||||
use crate::sql;
|
||||
@@ -343,7 +343,23 @@ unsafe fn add_parts(
|
||||
// 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) */
|
||||
// XXX call precheck?
|
||||
let mut old_server_folder = std::ptr::null_mut();
|
||||
let mut old_server_uid = 0;
|
||||
|
||||
if 0 != dc_rfc724_mid_exists(
|
||||
context,
|
||||
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);
|
||||
}
|
||||
|
||||
free(old_server_folder.cast());
|
||||
cleanup(mime_in_reply_to, mime_references, txt_raw);
|
||||
bail!("Message already in DB");
|
||||
}
|
||||
|
||||
// 1 or 0 for yes/no
|
||||
msgrmsg = mime_parser.is_send_by_messenger;
|
||||
|
||||
@@ -3,17 +3,17 @@ use percent_encoding::{utf8_percent_encode, NON_ALPHANUMERIC};
|
||||
|
||||
use crate::aheader::EncryptPreference;
|
||||
use crate::chat::{self, Chat};
|
||||
use crate::configure::*;
|
||||
use crate::constants::*;
|
||||
use crate::contact::*;
|
||||
use crate::context::Context;
|
||||
use crate::dc_configure::*;
|
||||
use crate::dc_e2ee::*;
|
||||
use crate::dc_mimeparser::*;
|
||||
use crate::dc_msg::*;
|
||||
use crate::dc_token::*;
|
||||
use crate::dc_tools::*;
|
||||
use crate::key::*;
|
||||
use crate::lot::LotState;
|
||||
use crate::message::*;
|
||||
use crate::param::*;
|
||||
use crate::peerstate::*;
|
||||
use crate::qr::check_qr;
|
||||
@@ -293,37 +293,38 @@ unsafe fn send_handshake_msg(
|
||||
fingerprint: *const libc::c_char,
|
||||
grpid: impl AsRef<str>,
|
||||
) {
|
||||
let mut msg = dc_msg_new_untyped(context);
|
||||
msg.type_0 = Viewtype::Text;
|
||||
msg.text = Some(format!("Secure-Join: {}", to_string(step)));
|
||||
msg.hidden = true;
|
||||
msg.param.set_int(Param::Cmd, 7);
|
||||
let mut msg: *mut dc_msg_t = dc_msg_new_untyped(context);
|
||||
(*msg).type_0 = Viewtype::Text;
|
||||
(*msg).text = Some(format!("Secure-Join: {}", to_string(step)));
|
||||
(*msg).hidden = 1;
|
||||
(*msg).param.set_int(Param::Cmd, 7);
|
||||
if step.is_null() {
|
||||
msg.param.remove(Param::Arg);
|
||||
(*msg).param.remove(Param::Arg);
|
||||
} else {
|
||||
msg.param.set(Param::Arg, as_str(step));
|
||||
(*msg).param.set(Param::Arg, as_str(step));
|
||||
}
|
||||
if !param2.as_ref().is_empty() {
|
||||
msg.param.set(Param::Arg2, param2);
|
||||
(*msg).param.set(Param::Arg2, param2);
|
||||
}
|
||||
if !fingerprint.is_null() {
|
||||
msg.param.set(Param::Arg3, as_str(fingerprint));
|
||||
(*msg).param.set(Param::Arg3, as_str(fingerprint));
|
||||
}
|
||||
if !grpid.as_ref().is_empty() {
|
||||
msg.param.set(Param::Arg4, grpid.as_ref());
|
||||
(*msg).param.set(Param::Arg4, grpid.as_ref());
|
||||
}
|
||||
if strcmp(step, b"vg-request\x00" as *const u8 as *const libc::c_char) == 0i32
|
||||
|| strcmp(step, b"vc-request\x00" as *const u8 as *const libc::c_char) == 0i32
|
||||
{
|
||||
msg.param.set_int(
|
||||
(*msg).param.set_int(
|
||||
Param::ForcePlaintext,
|
||||
ForcePlaintext::AddAutocryptHeader as i32,
|
||||
);
|
||||
} else {
|
||||
msg.param.set_int(Param::GuranteeE2ee, 1);
|
||||
(*msg).param.set_int(Param::GuranteeE2ee, 1);
|
||||
}
|
||||
// TODO. handle cleanup on error
|
||||
chat::send_msg(context, contact_chat_id, &mut msg).unwrap();
|
||||
chat::send_msg(context, contact_chat_id, msg).unwrap();
|
||||
dc_msg_unref(msg);
|
||||
}
|
||||
|
||||
unsafe fn chat_id_2_contact_id(context: &Context, contact_chat_id: uint32_t) -> uint32_t {
|
||||
|
||||
559
src/imap.rs
559
src/imap.rs
@@ -12,19 +12,14 @@ use crate::dc_loginparam::*;
|
||||
use crate::dc_tools::CStringExt;
|
||||
use crate::oauth2::dc_get_oauth2_access_token;
|
||||
use crate::types::*;
|
||||
use deltachat_derive::*;
|
||||
|
||||
const DC_IMAP_SEEN: usize = 0x0001;
|
||||
const DC_REGENERATE: usize = 0x01;
|
||||
|
||||
#[repr(usize)]
|
||||
#[derive(Debug, Display, Clone, Copy, PartialEq, Eq, FromPrimitive, ToPrimitive, ToSql, FromSql)]
|
||||
pub enum ImapResult {
|
||||
Success = 3,
|
||||
AlreadyDone = 2,
|
||||
RetryLater = 1,
|
||||
Failed = 0,
|
||||
}
|
||||
const DC_SUCCESS: usize = 3;
|
||||
const DC_ALREADY_DONE: usize = 2;
|
||||
const DC_RETRY_LATER: usize = 1;
|
||||
const DC_FAILED: usize = 0;
|
||||
|
||||
const PREFETCH_FLAGS: &str = "(UID ENVELOPE)";
|
||||
const BODY_FLAGS: &str = "(FLAGS BODY.PEEK[])";
|
||||
@@ -637,30 +632,26 @@ impl Imap {
|
||||
}
|
||||
}
|
||||
|
||||
fn select_folder<S: AsRef<str>>(&self, context: &Context, folder: Option<S>) -> bool {
|
||||
info!(context, 0, "select_folder0");
|
||||
fn select_folder<S: AsRef<str>>(&self, context: &Context, folder: Option<S>) -> usize {
|
||||
if self.session.lock().unwrap().is_none() {
|
||||
// we are in termination, noting useful to be done anymore
|
||||
let mut cfg = self.config.write().unwrap();
|
||||
cfg.selected_folder = None;
|
||||
cfg.selected_folder_needs_expunge = false;
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
info!(context, 0, "select_folder1");
|
||||
|
||||
// if there is a new folder and the new folder is equal to the selected one, there's nothing to do.
|
||||
// if there is _no_ new folder, we continue as we might want to expunge below.
|
||||
if let Some(ref folder) = folder {
|
||||
if let Some(ref selected_folder) = self.config.read().unwrap().selected_folder {
|
||||
if folder.as_ref() == selected_folder {
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
info!(context, 0, "select_folder2");
|
||||
|
||||
// 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 {
|
||||
info!(context, 0, "select_folder3");
|
||||
if let Some(ref folder) = self.config.read().unwrap().selected_folder {
|
||||
info!(context, 0, "Expunge messages in \"{}\".", folder);
|
||||
|
||||
@@ -674,26 +665,22 @@ impl Imap {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
unreachable!();
|
||||
return 0;
|
||||
}
|
||||
self.config.write().unwrap().selected_folder_needs_expunge = false;
|
||||
self.config.write().unwrap().selected_folder_needs_expunge = true;
|
||||
}
|
||||
}
|
||||
info!(context, 0, "select_folder4");
|
||||
|
||||
// select new folder
|
||||
if let Some(ref folder) = folder {
|
||||
if let Some(ref mut session) = &mut *self.session.lock().unwrap() {
|
||||
info!(context, 0, "select_folder5");
|
||||
match session.select(folder) {
|
||||
Ok(mailbox) => {
|
||||
info!(context, 0, "select_folder6");
|
||||
let mut config = self.config.write().unwrap();
|
||||
config.selected_folder = Some(folder.as_ref().to_string());
|
||||
config.selected_mailbox = Some(mailbox);
|
||||
}
|
||||
Err(err) => {
|
||||
info!(context, 0, "select_folder7");
|
||||
info!(
|
||||
context,
|
||||
0,
|
||||
@@ -704,14 +691,15 @@ impl Imap {
|
||||
|
||||
self.config.write().unwrap().selected_folder = None;
|
||||
self.should_reconnect.store(true, Ordering::Relaxed);
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
unreachable!();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
true
|
||||
|
||||
1
|
||||
}
|
||||
|
||||
fn get_config_last_seen_uid<S: AsRef<str>>(&self, context: &Context, folder: S) -> (u32, u32) {
|
||||
@@ -740,7 +728,7 @@ impl Imap {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if !self.select_folder(context, Some(&folder)) {
|
||||
if self.select_folder(context, Some(&folder)) == 0 {
|
||||
info!(
|
||||
context,
|
||||
0,
|
||||
@@ -1018,7 +1006,7 @@ impl Imap {
|
||||
self.setup_handle_if_needed(context);
|
||||
|
||||
let watch_folder = self.config.read().unwrap().watch_folder.clone();
|
||||
if !self.select_folder(context, watch_folder.as_ref()) {
|
||||
if self.select_folder(context, watch_folder.as_ref()) == 0 {
|
||||
warn!(context, 0, "IMAP-IDLE not setup.",);
|
||||
|
||||
return self.fake_idle(context);
|
||||
@@ -1046,17 +1034,14 @@ impl Imap {
|
||||
// if needed, the ui can call dc_imap_interrupt_idle() to trigger a reconnect.
|
||||
idle.set_keepalive(Duration::from_secs(23 * 60));
|
||||
let res = idle.wait_keepalive();
|
||||
eprintln!("idle wait_keepalive returned");
|
||||
|
||||
// Ignoring the error, as this happens when we try sending after the drop
|
||||
let _send_res = sender.send(res);
|
||||
eprintln!("idle sending result");
|
||||
|
||||
// Trigger condvar
|
||||
let mut watch = lock.lock().unwrap();
|
||||
*watch = true;
|
||||
cvar.notify_one();
|
||||
eprintln!("idle spawn thread ending");
|
||||
}
|
||||
});
|
||||
receiver
|
||||
@@ -1179,9 +1164,12 @@ impl Imap {
|
||||
uid: u32,
|
||||
dest_folder: S2,
|
||||
dest_uid: &mut u32,
|
||||
) -> ImapResult {
|
||||
) -> usize {
|
||||
let mut res = DC_RETRY_LATER;
|
||||
let set = format!("{}", uid);
|
||||
|
||||
if uid == 0 {
|
||||
return ImapResult::Failed;
|
||||
res = DC_FAILED;
|
||||
} else if folder.as_ref() == dest_folder.as_ref() {
|
||||
info!(
|
||||
context,
|
||||
@@ -1191,85 +1179,101 @@ impl Imap {
|
||||
uid,
|
||||
dest_folder.as_ref()
|
||||
);
|
||||
return ImapResult::AlreadyDone;
|
||||
}
|
||||
info!(
|
||||
context,
|
||||
0,
|
||||
"Moving message {}/{} to {}...",
|
||||
folder.as_ref(),
|
||||
uid,
|
||||
dest_folder.as_ref()
|
||||
);
|
||||
|
||||
if !self.select_folder(context, Some(folder.as_ref())) {
|
||||
warn!(
|
||||
res = DC_ALREADY_DONE;
|
||||
} else {
|
||||
info!(
|
||||
context,
|
||||
0,
|
||||
"Cannot select folder {} for moving message.",
|
||||
folder.as_ref()
|
||||
"Moving message {}/{} to {}...",
|
||||
folder.as_ref(),
|
||||
uid,
|
||||
dest_folder.as_ref()
|
||||
);
|
||||
return if !self.should_reconnect() {
|
||||
ImapResult::Failed
|
||||
|
||||
if self.select_folder(context, Some(folder.as_ref())) == 0 {
|
||||
warn!(
|
||||
context,
|
||||
0,
|
||||
"Cannot select folder {} for moving message.",
|
||||
folder.as_ref()
|
||||
);
|
||||
} else {
|
||||
ImapResult::RetryLater
|
||||
};
|
||||
}
|
||||
let set = format!("{}", uid);
|
||||
if let Some(ref mut session) = &mut *self.session.lock().unwrap() {
|
||||
match session.uid_mv(&set, &dest_folder) {
|
||||
Ok(_) => {
|
||||
*dest_uid = 0;
|
||||
return ImapResult::Success;
|
||||
}
|
||||
Err(err) => {
|
||||
info!(
|
||||
context,
|
||||
0,
|
||||
"Cannot move message, fallback to COPY/DELETE {}/{} to {}: {}",
|
||||
folder.as_ref(),
|
||||
uid,
|
||||
dest_folder.as_ref(),
|
||||
err
|
||||
);
|
||||
let moved = if let Some(ref mut session) = &mut *self.session.lock().unwrap() {
|
||||
match session.uid_mv(&set, &dest_folder) {
|
||||
Ok(_) => {
|
||||
res = DC_SUCCESS;
|
||||
true
|
||||
}
|
||||
Err(err) => {
|
||||
info!(
|
||||
context,
|
||||
0,
|
||||
"Cannot move message, fallback to COPY/DELETE {}/{} to {}: {}",
|
||||
folder.as_ref(),
|
||||
uid,
|
||||
dest_folder.as_ref(),
|
||||
err
|
||||
);
|
||||
|
||||
false
|
||||
}
|
||||
}
|
||||
} else {
|
||||
unreachable!();
|
||||
};
|
||||
|
||||
if !moved {
|
||||
let copied = if let Some(ref mut session) = &mut *self.session.lock().unwrap() {
|
||||
match session.uid_copy(&set, &dest_folder) {
|
||||
Ok(_) => true,
|
||||
Err(err) => {
|
||||
eprintln!("error copy: {:?}", err);
|
||||
info!(context, 0, "Cannot copy message.",);
|
||||
|
||||
false
|
||||
}
|
||||
}
|
||||
} else {
|
||||
unreachable!();
|
||||
};
|
||||
|
||||
if copied {
|
||||
if self.add_flag(context, uid, "\\Deleted") == 0 {
|
||||
warn!(context, 0, "Cannot mark message as \"Deleted\".",);
|
||||
}
|
||||
self.config.write().unwrap().selected_folder_needs_expunge = true;
|
||||
res = DC_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
unreachable!();
|
||||
};
|
||||
}
|
||||
|
||||
// message was NOT moved, let's try copy
|
||||
if let Some(ref mut session) = &mut *self.session.lock().unwrap() {
|
||||
match session.uid_copy(&set, &dest_folder) {
|
||||
Ok(_) => {}
|
||||
Err(err) => {
|
||||
info!(context, 0, "Cannot copy message. {:?}", err);
|
||||
return ImapResult::Failed;
|
||||
}
|
||||
if res == DC_SUCCESS {
|
||||
// TODO: is this correct?
|
||||
*dest_uid = uid;
|
||||
}
|
||||
|
||||
if res == DC_RETRY_LATER {
|
||||
if self.should_reconnect() {
|
||||
DC_RETRY_LATER
|
||||
} else {
|
||||
DC_FAILED
|
||||
}
|
||||
} else {
|
||||
unreachable!();
|
||||
};
|
||||
|
||||
if self.add_flag(context, uid, "\\Deleted") {
|
||||
self.config.write().unwrap().selected_folder_needs_expunge = true;
|
||||
return ImapResult::Success;
|
||||
res
|
||||
}
|
||||
warn!(context, 0, "Cannot mark message as \"Deleted\".",);
|
||||
return ImapResult::Failed;
|
||||
}
|
||||
|
||||
fn add_flag<S: AsRef<str>>(&self, context: &Context, server_uid: u32, flag: S) -> bool {
|
||||
fn add_flag<S: AsRef<str>>(&self, context: &Context, server_uid: u32, flag: S) -> usize {
|
||||
if server_uid == 0 {
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
if let Some(ref mut session) = &mut *self.session.lock().unwrap() {
|
||||
let set = format!("{}", server_uid);
|
||||
let query = format!("+FLAGS ({})", flag.as_ref());
|
||||
match session.uid_store(&set, &query) {
|
||||
Ok(_) => {
|
||||
return true;
|
||||
}
|
||||
Ok(_) => {}
|
||||
Err(err) => {
|
||||
warn!(
|
||||
context,
|
||||
@@ -1278,21 +1282,22 @@ impl Imap {
|
||||
}
|
||||
}
|
||||
}
|
||||
false
|
||||
|
||||
// All non-connection states are treated as success - the mail may
|
||||
// already be deleted or moved away on the server.
|
||||
if self.should_reconnect() {
|
||||
0
|
||||
} else {
|
||||
1
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_seen<S: AsRef<str>>(&self, context: &Context, folder: S, uid: u32) -> ImapResult {
|
||||
pub fn set_seen<S: AsRef<str>>(&self, context: &Context, folder: S, uid: u32) -> usize {
|
||||
let mut res = DC_RETRY_LATER;
|
||||
|
||||
if uid == 0 {
|
||||
info!(
|
||||
context,
|
||||
0,
|
||||
"set_seen folder={} uid={}",
|
||||
folder.as_ref(),
|
||||
uid
|
||||
);
|
||||
return ImapResult::Failed;
|
||||
}
|
||||
if self.is_connected() {
|
||||
res = DC_FAILED
|
||||
} else if self.is_connected() {
|
||||
info!(
|
||||
context,
|
||||
0,
|
||||
@@ -1301,210 +1306,226 @@ impl Imap {
|
||||
uid,
|
||||
);
|
||||
|
||||
if !self.select_folder(context, Some(folder.as_ref())) {
|
||||
if self.select_folder(context, Some(folder.as_ref())) == 0 {
|
||||
warn!(
|
||||
context,
|
||||
0,
|
||||
"Cannot select folder {} for setting SEEN flag.",
|
||||
folder.as_ref(),
|
||||
);
|
||||
} else if !self.add_flag(context, uid, "\\Seen") {
|
||||
} else if self.add_flag(context, uid, "\\Seen") == 0 {
|
||||
warn!(context, 0, "Cannot mark message as seen.",);
|
||||
} else {
|
||||
info!(
|
||||
context,
|
||||
0,
|
||||
"success marking message {}/{} as seen...",
|
||||
folder.as_ref(),
|
||||
uid,
|
||||
);
|
||||
return ImapResult::Success;
|
||||
res = DC_SUCCESS
|
||||
}
|
||||
}
|
||||
|
||||
if self.should_reconnect() {
|
||||
ImapResult::RetryLater
|
||||
if res == DC_RETRY_LATER {
|
||||
if self.should_reconnect() {
|
||||
DC_RETRY_LATER
|
||||
} else {
|
||||
DC_FAILED
|
||||
}
|
||||
} else {
|
||||
ImapResult::Failed
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_mdnsent<S: AsRef<str>>(&self, context: &Context, folder: S, uid: u32) -> ImapResult {
|
||||
if uid == 0 {
|
||||
return ImapResult::Failed;
|
||||
}
|
||||
if !self.is_connected() {
|
||||
return ImapResult::RetryLater;
|
||||
}
|
||||
info!(
|
||||
context,
|
||||
0,
|
||||
"Marking message {}/{} as $MDNSent...",
|
||||
folder.as_ref(),
|
||||
uid,
|
||||
);
|
||||
|
||||
if !self.select_folder(context, Some(folder.as_ref())) {
|
||||
warn!(
|
||||
context,
|
||||
0,
|
||||
"Cannot select folder {} for setting $MDNSent flag.",
|
||||
folder.as_ref()
|
||||
);
|
||||
return ImapResult::Failed;
|
||||
}
|
||||
// Check if the folder can handle the `$MDNSent` flag (see RFC 3503). If so, and not
|
||||
// set: set the flags and return this information.
|
||||
// If the folder cannot handle the `$MDNSent` flag, we risk duplicated MDNs; it's up
|
||||
// to the receiving MUA to handle this then (eg. Delta Chat has no problem with this).
|
||||
|
||||
let can_create_flag = self
|
||||
.config
|
||||
.read()
|
||||
.unwrap()
|
||||
.selected_mailbox
|
||||
.as_ref()
|
||||
.map(|mbox| {
|
||||
// empty means, everything can be stored
|
||||
mbox.permanent_flags.is_empty()
|
||||
|| mbox
|
||||
.permanent_flags
|
||||
.iter()
|
||||
.find(|flag| match flag {
|
||||
imap::types::Flag::Custom(s) => s == "$MDNSent",
|
||||
_ => false,
|
||||
})
|
||||
.is_some()
|
||||
})
|
||||
.expect("just selected folder");
|
||||
|
||||
if !can_create_flag {
|
||||
info!(
|
||||
context,
|
||||
0, "Cannot store $MDNSent flags, ignoring to prevent duplicate MDN.",
|
||||
);
|
||||
return ImapResult::Success;
|
||||
}
|
||||
|
||||
pub fn set_mdnsent<S: AsRef<str>>(&self, context: &Context, folder: S, uid: u32) -> usize {
|
||||
// returns 0=job should be retried later, 1=job done, 2=job done and flag just set
|
||||
let mut res = DC_RETRY_LATER;
|
||||
let set = format!("{}", uid);
|
||||
|
||||
let fetched_msgs = if let Some(ref mut session) = &mut *self.session.lock().unwrap() {
|
||||
match session.uid_fetch(set, FETCH_FLAGS) {
|
||||
Ok(res) => res,
|
||||
Err(err) => {
|
||||
eprintln!("fetch error: {:?}", err);
|
||||
return ImapResult::Failed;
|
||||
if uid == 0 {
|
||||
res = DC_FAILED;
|
||||
} else if self.is_connected() {
|
||||
info!(
|
||||
context,
|
||||
0,
|
||||
"Marking message {}/{} as $MDNSent...",
|
||||
folder.as_ref(),
|
||||
uid,
|
||||
);
|
||||
|
||||
if self.select_folder(context, Some(folder.as_ref())) == 0 {
|
||||
warn!(
|
||||
context,
|
||||
0,
|
||||
"Cannot select folder {} for setting $MDNSent flag.",
|
||||
folder.as_ref()
|
||||
);
|
||||
} else {
|
||||
// Check if the folder can handle the `$MDNSent` flag (see RFC 3503). If so, and not
|
||||
// set: set the flags and return this information.
|
||||
// If the folder cannot handle the `$MDNSent` flag, we risk duplicated MDNs; it's up
|
||||
// to the receiving MUA to handle this then (eg. Delta Chat has no problem with this).
|
||||
|
||||
let can_create_flag = self
|
||||
.config
|
||||
.read()
|
||||
.unwrap()
|
||||
.selected_mailbox
|
||||
.as_ref()
|
||||
.map(|mbox| {
|
||||
// empty means, everything can be stored
|
||||
mbox.permanent_flags.is_empty()
|
||||
|| mbox
|
||||
.permanent_flags
|
||||
.iter()
|
||||
.find(|flag| match flag {
|
||||
imap::types::Flag::Custom(s) => s == "$MDNSent",
|
||||
_ => false,
|
||||
})
|
||||
.is_some()
|
||||
})
|
||||
.expect("just selected folder");
|
||||
|
||||
if can_create_flag {
|
||||
let fetched_msgs =
|
||||
if let Some(ref mut session) = &mut *self.session.lock().unwrap() {
|
||||
match session.uid_fetch(set, FETCH_FLAGS) {
|
||||
Ok(res) => Some(res),
|
||||
Err(err) => {
|
||||
eprintln!("fetch error: {:?}", err);
|
||||
None
|
||||
}
|
||||
}
|
||||
} else {
|
||||
unreachable!();
|
||||
};
|
||||
|
||||
if let Some(msgs) = fetched_msgs {
|
||||
let flag_set = msgs
|
||||
.first()
|
||||
.map(|msg| {
|
||||
msg.flags()
|
||||
.iter()
|
||||
.find(|flag| match flag {
|
||||
imap::types::Flag::Custom(s) => s == "$MDNSent",
|
||||
_ => false,
|
||||
})
|
||||
.is_some()
|
||||
})
|
||||
.unwrap_or_else(|| false);
|
||||
|
||||
res = if flag_set {
|
||||
DC_ALREADY_DONE
|
||||
} else if self.add_flag(context, uid, "$MDNSent") != 0 {
|
||||
DC_SUCCESS
|
||||
} else {
|
||||
res
|
||||
};
|
||||
|
||||
if res == DC_SUCCESS {
|
||||
info!(context, 0, "$MDNSent just set and MDN will be sent.");
|
||||
} else {
|
||||
info!(context, 0, "$MDNSent already set and MDN already sent.");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
res = DC_SUCCESS;
|
||||
info!(
|
||||
context,
|
||||
0, "Cannot store $MDNSent flags, risk sending duplicate MDN.",
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
unreachable!();
|
||||
};
|
||||
}
|
||||
|
||||
let flag_set = fetched_msgs
|
||||
.first()
|
||||
.map(|msg| {
|
||||
msg.flags()
|
||||
.iter()
|
||||
.find(|flag| match flag {
|
||||
imap::types::Flag::Custom(s) => s == "$MDNSent",
|
||||
_ => false,
|
||||
})
|
||||
.is_some()
|
||||
})
|
||||
.unwrap_or_else(|| false);
|
||||
|
||||
if flag_set {
|
||||
info!(context, 0, "$MDNSent already set and MDN already sent.");
|
||||
ImapResult::AlreadyDone
|
||||
} else if self.add_flag(context, uid, "$MDNSent") {
|
||||
info!(context, 0, "$MDNSent just set and MDN will be sent.");
|
||||
ImapResult::Success
|
||||
} else if self.should_reconnect() {
|
||||
ImapResult::RetryLater
|
||||
if res == DC_RETRY_LATER {
|
||||
if self.should_reconnect() {
|
||||
DC_RETRY_LATER
|
||||
} else {
|
||||
DC_FAILED
|
||||
}
|
||||
} else {
|
||||
ImapResult::Failed
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
// only returns 0 on connection problems; we should try later again in this case *
|
||||
pub fn delete_msg<S1: AsRef<str>, S2: AsRef<str>>(
|
||||
&self,
|
||||
context: &Context,
|
||||
message_id: S1,
|
||||
folder: S2,
|
||||
server_uid: &mut u32,
|
||||
) -> ImapResult {
|
||||
) -> usize {
|
||||
let mut success = false;
|
||||
if *server_uid == 0 {
|
||||
return ImapResult::Failed;
|
||||
}
|
||||
if !self.is_connected() {
|
||||
return ImapResult::RetryLater;
|
||||
}
|
||||
info!(
|
||||
context,
|
||||
0,
|
||||
"Marking message \"{}\", {}/{} for deletion...",
|
||||
message_id.as_ref(),
|
||||
folder.as_ref(),
|
||||
server_uid,
|
||||
);
|
||||
|
||||
if !self.select_folder(context, Some(&folder)) {
|
||||
warn!(
|
||||
success = true
|
||||
} else {
|
||||
info!(
|
||||
context,
|
||||
0,
|
||||
"Cannot select folder {} for deleting message.",
|
||||
folder.as_ref()
|
||||
"Marking message \"{}\", {}/{} for deletion...",
|
||||
message_id.as_ref(),
|
||||
folder.as_ref(),
|
||||
server_uid,
|
||||
);
|
||||
return ImapResult::RetryLater;
|
||||
}
|
||||
let set = format!("{}", server_uid);
|
||||
if let Some(ref mut session) = &mut *self.session.lock().unwrap() {
|
||||
match session.uid_fetch(set, PREFETCH_FLAGS) {
|
||||
Ok(msgs) => {
|
||||
if msgs.is_empty()
|
||||
|| msgs
|
||||
.first()
|
||||
.unwrap()
|
||||
.envelope()
|
||||
.expect("missing envelope")
|
||||
.message_id
|
||||
.expect("missing message id")
|
||||
!= message_id.as_ref()
|
||||
{
|
||||
warn!(
|
||||
context,
|
||||
0,
|
||||
"Cannot delete on IMAP, {}/{} does not match {}.",
|
||||
folder.as_ref(),
|
||||
server_uid,
|
||||
message_id.as_ref(),
|
||||
);
|
||||
*server_uid = 0;
|
||||
return ImapResult::Failed;
|
||||
|
||||
if self.select_folder(context, Some(&folder)) == 0 {
|
||||
warn!(
|
||||
context,
|
||||
0,
|
||||
"Cannot select folder {} for deleting message.",
|
||||
folder.as_ref()
|
||||
);
|
||||
} else {
|
||||
let set = format!("{}", server_uid);
|
||||
if let Some(ref mut session) = &mut *self.session.lock().unwrap() {
|
||||
match session.uid_fetch(set, PREFETCH_FLAGS) {
|
||||
Ok(msgs) => {
|
||||
if msgs.is_empty()
|
||||
|| msgs
|
||||
.first()
|
||||
.unwrap()
|
||||
.envelope()
|
||||
.expect("missing envelope")
|
||||
.message_id
|
||||
.expect("missing message id")
|
||||
!= message_id.as_ref()
|
||||
{
|
||||
warn!(
|
||||
context,
|
||||
0,
|
||||
"Cannot delete on IMAP, {}/{} does not match {}.",
|
||||
folder.as_ref(),
|
||||
server_uid,
|
||||
message_id.as_ref(),
|
||||
);
|
||||
*server_uid = 0;
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
eprintln!("fetch error: {:?}", err);
|
||||
|
||||
warn!(
|
||||
context,
|
||||
0,
|
||||
"Cannot delete on IMAP, {}/{} not found.",
|
||||
folder.as_ref(),
|
||||
server_uid,
|
||||
);
|
||||
*server_uid = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
warn!(
|
||||
context,
|
||||
0,
|
||||
"Cannot delete on IMAP, {}/{}, fetch error {:?}.",
|
||||
folder.as_ref(),
|
||||
server_uid,
|
||||
err
|
||||
);
|
||||
*server_uid = 0;
|
||||
return ImapResult::Failed;
|
||||
|
||||
// mark the message for deletion
|
||||
if self.add_flag(context, *server_uid, "\\Deleted") == 0 {
|
||||
warn!(context, 0, "Cannot mark message as \"Deleted\".");
|
||||
} else {
|
||||
self.config.write().unwrap().selected_folder_needs_expunge = true;
|
||||
success = true
|
||||
}
|
||||
}
|
||||
}
|
||||
// mark the message for deletion
|
||||
if !self.add_flag(context, *server_uid, "\\Deleted") {
|
||||
warn!(context, 0, "Cannot mark message as \"Deleted\".");
|
||||
*server_uid = 0;
|
||||
ImapResult::Failed
|
||||
|
||||
if success {
|
||||
1
|
||||
} else {
|
||||
self.config.write().unwrap().selected_folder_needs_expunge = true;
|
||||
ImapResult::Success
|
||||
self.is_connected() as usize
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
490
src/job.rs
490
src/job.rs
@@ -1,20 +1,21 @@
|
||||
use std::ffi::CStr;
|
||||
use std::ptr;
|
||||
use std::time::Duration;
|
||||
|
||||
use deltachat_derive::{FromSql, ToSql};
|
||||
use rand::{thread_rng, Rng};
|
||||
|
||||
use crate::chat;
|
||||
use crate::configure::*;
|
||||
use crate::constants::*;
|
||||
use crate::context::Context;
|
||||
use crate::dc_configure::*;
|
||||
use crate::dc_imex::*;
|
||||
use crate::dc_location::*;
|
||||
use crate::dc_loginparam::*;
|
||||
use crate::dc_mimefactory::*;
|
||||
use crate::dc_msg::*;
|
||||
use crate::dc_tools::*;
|
||||
use crate::imap::*;
|
||||
use crate::message::*;
|
||||
use crate::param::*;
|
||||
use crate::sql;
|
||||
use crate::types::*;
|
||||
@@ -118,7 +119,7 @@ impl Job {
|
||||
if !connected {
|
||||
self.try_again_later(Delay::Standard, None);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
let filename = self.param.get(Param::File).unwrap_or_default();
|
||||
let body = match dc_read_file_safe(context, filename) {
|
||||
@@ -133,7 +134,7 @@ impl Job {
|
||||
if recipients.is_none() {
|
||||
error!(context, 0, "Missing recipients for job {}", self.job_id,);
|
||||
return;
|
||||
}
|
||||
}
|
||||
let recipients_list = recipients
|
||||
.unwrap()
|
||||
.split("\x1e")
|
||||
@@ -149,27 +150,34 @@ impl Job {
|
||||
this happends if dc_delete_msgs() was called
|
||||
before the generated mime was sent out */
|
||||
if 0 != self.foreign_id {
|
||||
if !dc_msg_exists(context, self.foreign_id) {
|
||||
if 0 == unsafe { dc_msg_exists(context, self.foreign_id) } {
|
||||
warn!(
|
||||
context,
|
||||
0, "Message {} for job {} does not exist", self.foreign_id, self.job_id,
|
||||
0,
|
||||
"Message {} for job {} does not exist",
|
||||
self.foreign_id,
|
||||
self.job_id,
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* send message while holding the smtp lock long enough
|
||||
/* send message while holding the smtp lock long enough
|
||||
to also mark success in the database, to reduce chances
|
||||
of a message getting sent twice.
|
||||
*/
|
||||
let mut sock = context.smtp.lock().unwrap();
|
||||
if 0 == sock.send(context, recipients_list, body) {
|
||||
sock.disconnect();
|
||||
self.try_again_later(Delay::AtOnce, Some(as_str(sock.error)));
|
||||
self.try_again_later(Delay::At_once, Some(as_str(sock.error)));
|
||||
return;
|
||||
}
|
||||
}
|
||||
dc_delete_file(context, filename);
|
||||
if 0 != self.foreign_id {
|
||||
dc_update_msg_state(context, self.foreign_id, MessageState::OutDelivered);
|
||||
dc_update_msg_state(
|
||||
context,
|
||||
self.foreign_id,
|
||||
MessageState::OutDelivered,
|
||||
);
|
||||
let chat_id: i32 = context
|
||||
.sql
|
||||
.query_row_col(
|
||||
@@ -195,154 +203,178 @@ impl Job {
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
fn do_DC_JOB_MOVE_MSG(&mut self, context: &Context) {
|
||||
let ok_to_continue;
|
||||
let msg = unsafe { dc_msg_new_untyped(context) };
|
||||
let mut dest_uid = 0;
|
||||
|
||||
let inbox = context.inbox.read().unwrap();
|
||||
|
||||
if !connect_to_inbox(context, &inbox) {
|
||||
self.try_again_later(Delay::Standard, None);
|
||||
return;
|
||||
}
|
||||
if let Ok(msg) = dc_msg_load_from_db(context, self.foreign_id) {
|
||||
if context
|
||||
.sql
|
||||
.get_config_int(context, "folders_configured")
|
||||
.unwrap_or_default()
|
||||
< 3
|
||||
{
|
||||
inbox.configure_folders(context, 0x1i32);
|
||||
if !inbox.is_connected() {
|
||||
connect_to_inbox(context, &inbox);
|
||||
if !inbox.is_connected() {
|
||||
self.try_again_later(Delay::Standard, None);
|
||||
ok_to_continue = false;
|
||||
} else {
|
||||
ok_to_continue = true;
|
||||
}
|
||||
let dest_folder = context.sql.get_config(context, "configured_mvbox_folder");
|
||||
} else {
|
||||
ok_to_continue = true;
|
||||
}
|
||||
if ok_to_continue {
|
||||
if dc_msg_load_from_db(msg, context, self.foreign_id) {
|
||||
if context
|
||||
.sql
|
||||
.get_config_int(context, "folders_configured")
|
||||
.unwrap_or_default()
|
||||
< 3
|
||||
{
|
||||
inbox.configure_folders(context, 0x1i32);
|
||||
}
|
||||
let dest_folder = context.sql.get_config(context, "configured_mvbox_folder");
|
||||
|
||||
if let Some(dest_folder) = dest_folder {
|
||||
let server_folder = msg.server_folder.as_ref().unwrap();
|
||||
let mut dest_uid = 0;
|
||||
let msg = unsafe { &mut *msg };
|
||||
|
||||
match inbox.mv(
|
||||
context,
|
||||
server_folder,
|
||||
msg.server_uid,
|
||||
&dest_folder,
|
||||
&mut dest_uid,
|
||||
) {
|
||||
ImapResult::RetryLater => {
|
||||
self.try_again_later(Delay::Standard, None);
|
||||
if let Some(dest_folder) = dest_folder {
|
||||
let server_folder = msg.server_folder.as_ref().unwrap();
|
||||
|
||||
match inbox.mv(
|
||||
context,
|
||||
server_folder,
|
||||
msg.server_uid,
|
||||
&dest_folder,
|
||||
&mut dest_uid,
|
||||
) as libc::c_uint
|
||||
{
|
||||
DC_RETRY_LATER => {
|
||||
self.try_again_later(Delay::Standard, None);
|
||||
}
|
||||
DC_SUCCESS => {
|
||||
dc_update_server_uid(context, msg.rfc724_mid, &dest_folder, dest_uid);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
ImapResult::Success => {
|
||||
// TODO: dest_uid is not (yet) set by mv() so remains 0
|
||||
dc_update_server_uid(
|
||||
context,
|
||||
as_str(msg.rfc724_mid),
|
||||
&dest_folder,
|
||||
dest_uid,
|
||||
);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe { dc_msg_unref(msg) };
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
fn do_DC_JOB_DELETE_MSG_ON_IMAP(&mut self, context: &Context) {
|
||||
let mut delete_from_server = 1;
|
||||
let msg = unsafe { dc_msg_new_untyped(context) };
|
||||
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 })
|
||||
{
|
||||
/* eg. device messages have no Message-ID */
|
||||
if dc_rfc724_mid_cnt(context, msg.rfc724_mid) != 1 {
|
||||
info!(
|
||||
context,
|
||||
0, "The message is deleted from the server when all parts are deleted.",
|
||||
);
|
||||
return;
|
||||
}
|
||||
/* if this is the last existing part of the message, we delete the message from the server */
|
||||
if !connect_to_inbox(context, &inbox) {
|
||||
self.try_again_later(Delay::Standard, None);
|
||||
return;
|
||||
}
|
||||
let mid = unsafe { CStr::from_ptr(msg.rfc724_mid).to_str().unwrap() };
|
||||
let server_folder = msg.server_folder.as_ref().unwrap();
|
||||
match inbox.delete_msg(context, mid, server_folder, &mut msg.server_uid) {
|
||||
ImapResult::RetryLater => {
|
||||
self.try_again_later(Delay::AtOnce, None);
|
||||
}
|
||||
_ => {
|
||||
dc_delete_msg_from_db(context, msg.id);
|
||||
if !(!dc_msg_load_from_db(msg, context, self.foreign_id)
|
||||
|| unsafe { (*msg).rfc724_mid.is_null() }
|
||||
|| unsafe { *(*msg).rfc724_mid.offset(0isize) as libc::c_int == 0 })
|
||||
{
|
||||
let ok_to_continue1;
|
||||
/* eg. device messages have no Message-ID */
|
||||
if dc_rfc724_mid_cnt(context, unsafe { (*msg).rfc724_mid }) != 1 {
|
||||
info!(
|
||||
context,
|
||||
0, "The message is deleted from the server when all parts are deleted.",
|
||||
);
|
||||
delete_from_server = 0i32
|
||||
}
|
||||
/* if this is the last existing part of the message, we delete the message from the server */
|
||||
if 0 != delete_from_server {
|
||||
let ok_to_continue;
|
||||
if !inbox.is_connected() {
|
||||
connect_to_inbox(context, &inbox);
|
||||
if !inbox.is_connected() {
|
||||
self.try_again_later(Delay::Standard, None);
|
||||
ok_to_continue = false;
|
||||
} else {
|
||||
ok_to_continue = true;
|
||||
}
|
||||
} else {
|
||||
ok_to_continue = true;
|
||||
}
|
||||
if ok_to_continue {
|
||||
let mid = unsafe { CStr::from_ptr((*msg).rfc724_mid).to_str().unwrap() };
|
||||
let server_folder = unsafe { (*msg).server_folder.as_ref().unwrap() };
|
||||
if 0 == inbox.delete_msg(context, mid, server_folder, unsafe {
|
||||
&mut (*msg).server_uid
|
||||
}) {
|
||||
self.try_again_later(Delay::At_once, None);
|
||||
ok_to_continue1 = false;
|
||||
} else {
|
||||
ok_to_continue1 = true;
|
||||
}
|
||||
} else {
|
||||
ok_to_continue1 = false;
|
||||
}
|
||||
} else {
|
||||
ok_to_continue1 = true;
|
||||
}
|
||||
if ok_to_continue1 {
|
||||
unsafe { dc_delete_msg_from_db(context, (*msg).id) };
|
||||
}
|
||||
}
|
||||
unsafe { dc_msg_unref(msg) }
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
fn do_DC_JOB_MARKSEEN_MSG_ON_IMAP(&mut self, context: &Context) {
|
||||
let ok_to_continue;
|
||||
let msg = unsafe { dc_msg_new_untyped(context) };
|
||||
let inbox = context.inbox.read().unwrap();
|
||||
|
||||
if !connect_to_inbox(context, &inbox) {
|
||||
self.try_again_later(Delay::Standard, None);
|
||||
return;
|
||||
}
|
||||
|
||||
if let Ok(msg) = dc_msg_load_from_db(context, self.foreign_id) {
|
||||
if msg.server_uid == 0 {
|
||||
// the message has likely been moved
|
||||
// try again later
|
||||
if !inbox.is_connected() {
|
||||
connect_to_inbox(context, &inbox);
|
||||
if !inbox.is_connected() {
|
||||
self.try_again_later(Delay::Standard, None);
|
||||
return;
|
||||
ok_to_continue = false;
|
||||
} else {
|
||||
ok_to_continue = true;
|
||||
}
|
||||
let server_folder = msg.server_folder.as_ref().unwrap();
|
||||
info!(context, 0, "job_markseen_msg db id={}", self.foreign_id);
|
||||
match inbox.set_seen(context, server_folder, msg.server_uid) {
|
||||
ImapResult::Failed => {
|
||||
info!(context, 0, "job_markseen_msg failed");
|
||||
return;
|
||||
}
|
||||
ImapResult::RetryLater => {
|
||||
info!(context, 0, "job_markseen_msg retry-later");
|
||||
self.try_again_later(Delay::Standard, None);
|
||||
return;
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
info!(
|
||||
context,
|
||||
0,
|
||||
"set_mdnsent wantsmdn={} mdns_enabled={}",
|
||||
msg.param.get_int(Param::WantsMdn).unwrap_or_default(),
|
||||
context
|
||||
.sql
|
||||
.get_config_int(context, "mdns_enabled")
|
||||
.unwrap_or_else(|| 1)
|
||||
);
|
||||
|
||||
/* XXX
|
||||
if 0 != msg.param.get_int(Param::WantsMdn).unwrap_or_default()
|
||||
&& 0 != context
|
||||
.sql
|
||||
.get_config_int(context, "mdns_enabled")
|
||||
.unwrap_or_else(|| 1)
|
||||
*/
|
||||
{
|
||||
let folder = msg.server_folder.as_ref().unwrap();
|
||||
|
||||
match inbox.set_mdnsent(context, folder, msg.server_uid) {
|
||||
ImapResult::RetryLater => {
|
||||
} else {
|
||||
ok_to_continue = true;
|
||||
}
|
||||
if ok_to_continue {
|
||||
if dc_msg_load_from_db(msg, context, self.foreign_id) {
|
||||
let server_folder = unsafe { (*msg).server_folder.as_ref().unwrap() };
|
||||
match inbox.set_seen(context, server_folder, unsafe { (*msg).server_uid })
|
||||
as libc::c_uint
|
||||
{
|
||||
0 => {}
|
||||
1 => {
|
||||
self.try_again_later(Delay::Standard, None);
|
||||
}
|
||||
ImapResult::Success => {
|
||||
send_mdn(context, msg.id);
|
||||
_ => {
|
||||
if 0 != unsafe { (*msg).param.get_int(Param::WantsMdn).unwrap_or_default() }
|
||||
&& 0 != context
|
||||
.sql
|
||||
.get_config_int(context, "mdns_enabled")
|
||||
.unwrap_or_else(|| 1)
|
||||
{
|
||||
let folder = unsafe { (*msg).server_folder.as_ref().unwrap() };
|
||||
|
||||
match inbox.set_mdnsent(context, folder, unsafe { (*msg).server_uid })
|
||||
as libc::c_uint
|
||||
{
|
||||
1 => {
|
||||
self.try_again_later(Delay::Standard, None);
|
||||
}
|
||||
3 => {
|
||||
send_mdn(context, unsafe { (*msg).id });
|
||||
}
|
||||
0 | 2 | _ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
ImapResult::AlreadyDone => {}
|
||||
ImapResult::Failed => {}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
unsafe { dc_msg_unref(msg) };
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
fn do_DC_JOB_MARKSEEN_MDN_ON_IMAP(&mut self, context: &Context) {
|
||||
let ok_to_continue;
|
||||
let folder = self
|
||||
.param
|
||||
.get(Param::ServerFolder)
|
||||
@@ -352,37 +384,37 @@ impl Job {
|
||||
let mut dest_uid = 0;
|
||||
let inbox = context.inbox.read().unwrap();
|
||||
|
||||
if !connect_to_inbox(context, &inbox) {
|
||||
self.try_again_later(Delay::Standard, None);
|
||||
return;
|
||||
}
|
||||
|
||||
match inbox.set_seen(context, &folder, uid) {
|
||||
ImapResult::RetryLater => {
|
||||
if !inbox.is_connected() {
|
||||
connect_to_inbox(context, &inbox);
|
||||
if !inbox.is_connected() {
|
||||
self.try_again_later(Delay::Standard, None);
|
||||
return;
|
||||
ok_to_continue = false;
|
||||
} else {
|
||||
ok_to_continue = true;
|
||||
}
|
||||
ImapResult::Failed => {
|
||||
return;
|
||||
} else {
|
||||
ok_to_continue = true;
|
||||
}
|
||||
if ok_to_continue {
|
||||
if inbox.set_seen(context, &folder, uid) == 0 {
|
||||
self.try_again_later(Delay::Standard, None);
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
if 0 != self.param.get_int(Param::AlsoMove).unwrap_or_default() {
|
||||
if context
|
||||
.sql
|
||||
.get_config_int(context, "folders_configured")
|
||||
.unwrap_or_default()
|
||||
< 3
|
||||
{
|
||||
inbox.configure_folders(context, 0x1i32);
|
||||
}
|
||||
let dest_folder = context.sql.get_config(context, "configured_mvbox_folder");
|
||||
if let Some(dest_folder) = dest_folder {
|
||||
match inbox.mv(context, folder, uid, dest_folder, &mut dest_uid) {
|
||||
ImapResult::RetryLater => {
|
||||
if 0 != self.param.get_int(Param::AlsoMove).unwrap_or_default() {
|
||||
if context
|
||||
.sql
|
||||
.get_config_int(context, "folders_configured")
|
||||
.unwrap_or_default()
|
||||
< 3
|
||||
{
|
||||
inbox.configure_folders(context, 0x1i32);
|
||||
}
|
||||
let dest_folder = context.sql.get_config(context, "configured_mvbox_folder");
|
||||
if let Some(dest_folder) = dest_folder {
|
||||
if 1 == inbox.mv(context, folder, uid, dest_folder, &mut dest_uid)
|
||||
as libc::c_uint
|
||||
{
|
||||
self.try_again_later(Delay::Standard, None);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -404,7 +436,7 @@ pub fn perform_imap_fetch(context: &Context) {
|
||||
let inbox = context.inbox.read().unwrap();
|
||||
let start = std::time::Instant::now();
|
||||
|
||||
if !connect_to_inbox(context, &inbox) {
|
||||
if 0 == connect_to_inbox(context, &inbox) {
|
||||
return;
|
||||
}
|
||||
if context
|
||||
@@ -426,7 +458,7 @@ pub fn perform_imap_fetch(context: &Context) {
|
||||
context,
|
||||
0,
|
||||
"INBOX-fetch done in {:.4} ms.",
|
||||
start.elapsed().as_nanos() as f64 / 1000.0,
|
||||
start.elapsed().as_millis(),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -609,21 +641,6 @@ pub fn maybe_network(context: &Context) {
|
||||
interrupt_sentbox_idle(context);
|
||||
}
|
||||
|
||||
pub fn job_retry_msg_actions_at_once(context: &Context, msg_id: uint32_t) -> bool {
|
||||
match sql::execute(
|
||||
context,
|
||||
&context.sql,
|
||||
"UPDATE jobs SET desired_timestamp=? WHERE foreign_id=?;",
|
||||
params![time(), msg_id],
|
||||
) {
|
||||
Ok(_) => true,
|
||||
Err(_err) => {
|
||||
info!(context, 0, "job-retry-at-once failed {:?}", _err);
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn job_action_exists(context: &Context, action: Action) -> bool {
|
||||
context
|
||||
.sql
|
||||
@@ -635,38 +652,55 @@ pub fn job_action_exists(context: &Context, action: Action) -> bool {
|
||||
#[allow(non_snake_case)]
|
||||
pub unsafe fn job_send_msg(context: &Context, msg_id: uint32_t) -> libc::c_int {
|
||||
let mut success = 0;
|
||||
let mut mimefactory = dc_mimefactory_t {
|
||||
from_addr: ptr::null_mut(),
|
||||
from_displayname: ptr::null_mut(),
|
||||
selfstatus: ptr::null_mut(),
|
||||
recipients_names: ptr::null_mut(),
|
||||
recipients_addr: ptr::null_mut(),
|
||||
timestamp: 0,
|
||||
rfc724_mid: ptr::null_mut(),
|
||||
loaded: DC_MF_NOTHING_LOADED,
|
||||
msg: ptr::null_mut(),
|
||||
chat: None,
|
||||
increation: 0,
|
||||
in_reply_to: ptr::null_mut(),
|
||||
references: ptr::null_mut(),
|
||||
req_mdn: 0,
|
||||
out: ptr::null_mut(),
|
||||
out_encrypted: 0,
|
||||
out_gossiped: 0,
|
||||
out_last_added_location_id: 0,
|
||||
error: ptr::null_mut(),
|
||||
context,
|
||||
};
|
||||
|
||||
/* load message data */
|
||||
let mimefactory = dc_mimefactory_load_msg(context, msg_id);
|
||||
if mimefactory.is_err() || mimefactory.as_ref().unwrap().from_addr.is_null() {
|
||||
if 0 == dc_mimefactory_load_msg(&mut mimefactory, msg_id) || mimefactory.from_addr.is_null() {
|
||||
warn!(
|
||||
context,
|
||||
0, "Cannot load data to send, maybe the message is deleted in between.",
|
||||
);
|
||||
} else {
|
||||
let mut mimefactory = mimefactory.unwrap();
|
||||
// no redo, no IMAP. moreover, as the data does not exist, there is no need in calling dc_set_msg_failed()
|
||||
if chat::msgtype_has_file(mimefactory.msg.type_0) {
|
||||
let file_param = mimefactory
|
||||
.msg
|
||||
.param
|
||||
.get(Param::File)
|
||||
.map(|s| s.to_string());
|
||||
if let Some(pathNfilename) = file_param {
|
||||
if (mimefactory.msg.type_0 == Viewtype::Image
|
||||
|| mimefactory.msg.type_0 == Viewtype::Gif)
|
||||
&& !mimefactory.msg.param.exists(Param::Width)
|
||||
if chat::msgtype_has_file((*mimefactory.msg).type_0) {
|
||||
if let Some(pathNfilename) = (*mimefactory.msg).param.get(Param::File) {
|
||||
if ((*mimefactory.msg).type_0 == Viewtype::Image
|
||||
|| (*mimefactory.msg).type_0 == Viewtype::Gif)
|
||||
&& !(*mimefactory.msg).param.exists(Param::Width)
|
||||
{
|
||||
mimefactory.msg.param.set_int(Param::Width, 0);
|
||||
mimefactory.msg.param.set_int(Param::Height, 0);
|
||||
(*mimefactory.msg).param.set_int(Param::Width, 0);
|
||||
(*mimefactory.msg).param.set_int(Param::Height, 0);
|
||||
|
||||
if let Some(buf) = dc_read_file_safe(context, pathNfilename) {
|
||||
if let Ok((width, height)) = dc_get_filemeta(&buf) {
|
||||
mimefactory.msg.param.set_int(Param::Width, width as i32);
|
||||
mimefactory.msg.param.set_int(Param::Height, height as i32);
|
||||
(*mimefactory.msg).param.set_int(Param::Width, width as i32);
|
||||
(*mimefactory.msg)
|
||||
.param
|
||||
.set_int(Param::Height, height as i32);
|
||||
}
|
||||
}
|
||||
dc_msg_save_param_to_disk(&mut mimefactory.msg);
|
||||
dc_msg_save_param_to_disk(mimefactory.msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -674,8 +708,7 @@ pub unsafe fn job_send_msg(context: &Context, msg_id: uint32_t) -> libc::c_int {
|
||||
if 0 == dc_mimefactory_render(&mut mimefactory) {
|
||||
dc_set_msg_failed(context, msg_id, as_opt_str(mimefactory.error));
|
||||
} else if 0
|
||||
!= mimefactory
|
||||
.msg
|
||||
!= (*mimefactory.msg)
|
||||
.param
|
||||
.get_int(Param::GuranteeE2ee)
|
||||
.unwrap_or_default()
|
||||
@@ -686,7 +719,7 @@ pub unsafe fn job_send_msg(context: &Context, msg_id: uint32_t) -> libc::c_int {
|
||||
0,
|
||||
"e2e encryption unavailable {} - {:?}",
|
||||
msg_id,
|
||||
mimefactory.msg.param.get_int(Param::GuranteeE2ee),
|
||||
(*mimefactory.msg).param.get_int(Param::GuranteeE2ee),
|
||||
);
|
||||
dc_set_msg_failed(
|
||||
context,
|
||||
@@ -710,32 +743,32 @@ pub unsafe fn job_send_msg(context: &Context, msg_id: uint32_t) -> libc::c_int {
|
||||
);
|
||||
}
|
||||
if 0 != mimefactory.out_gossiped {
|
||||
chat::set_gossiped_timestamp(context, mimefactory.msg.chat_id, time());
|
||||
chat::set_gossiped_timestamp(context, (*mimefactory.msg).chat_id, time());
|
||||
}
|
||||
if 0 != mimefactory.out_last_added_location_id {
|
||||
dc_set_kml_sent_timestamp(context, mimefactory.msg.chat_id, time());
|
||||
if !mimefactory.msg.hidden {
|
||||
dc_set_kml_sent_timestamp(context, (*mimefactory.msg).chat_id, time());
|
||||
if 0 == (*mimefactory.msg).hidden {
|
||||
dc_set_msg_location_id(
|
||||
context,
|
||||
mimefactory.msg.id,
|
||||
(*mimefactory.msg).id,
|
||||
mimefactory.out_last_added_location_id,
|
||||
);
|
||||
}
|
||||
}
|
||||
if 0 != mimefactory.out_encrypted
|
||||
&& mimefactory
|
||||
.msg
|
||||
&& (*mimefactory.msg)
|
||||
.param
|
||||
.get_int(Param::GuranteeE2ee)
|
||||
.unwrap_or_default()
|
||||
== 0
|
||||
{
|
||||
mimefactory.msg.param.set_int(Param::GuranteeE2ee, 1);
|
||||
dc_msg_save_param_to_disk(&mut mimefactory.msg);
|
||||
(*mimefactory.msg).param.set_int(Param::GuranteeE2ee, 1);
|
||||
dc_msg_save_param_to_disk(mimefactory.msg);
|
||||
}
|
||||
success = add_smtp_job(context, Action::SendMsgToSmtp, &mut mimefactory);
|
||||
}
|
||||
}
|
||||
dc_mimefactory_empty(&mut mimefactory);
|
||||
|
||||
success
|
||||
}
|
||||
@@ -785,7 +818,7 @@ fn job_perform(context: &Context, thread: Thread, probe_network: bool) {
|
||||
added_timestamp: row.get(4)?,
|
||||
tries: row.get(6)?,
|
||||
param: row.get::<_, String>(3)?.parse().unwrap_or_default(),
|
||||
try_again: Delay::Default,
|
||||
try_again: Delay::Do_not_try_again,
|
||||
pending_error: None,
|
||||
};
|
||||
|
||||
@@ -817,7 +850,7 @@ fn job_perform(context: &Context, thread: Thread, probe_network: bool) {
|
||||
// some configuration jobs are "exclusive":
|
||||
// - they are always executed in the imap-thread and the smtp-thread is suspended during execution
|
||||
// - they may change the database handle change the database handle; we do not keep old pointers therefore
|
||||
// - they can be re-executed one time AtOnce, but they are not save in the database for later execution
|
||||
// - they can be re-executed one time AT_ONCE, but they are not save in the database for later execution
|
||||
if Action::ConfigureImap == job.action || Action::ImexImap == job.action {
|
||||
job_kill_action(context, job.action);
|
||||
&context
|
||||
@@ -837,8 +870,8 @@ fn job_perform(context: &Context, thread: Thread, probe_network: bool) {
|
||||
|
||||
let mut tries = 0;
|
||||
while tries <= 1 {
|
||||
// this can be modified by a job using try_again_later()
|
||||
job.try_again = Delay::Default;
|
||||
// this can be modified by a job using dc_job_try_again_later()
|
||||
job.try_again = Delay::Do_not_try_again;
|
||||
|
||||
match job.action {
|
||||
Action::SendMsgToSmtp => job.do_DC_JOB_SEND(context),
|
||||
@@ -859,7 +892,7 @@ fn job_perform(context: &Context, thread: Thread, probe_network: bool) {
|
||||
Action::SendMdnOld => {}
|
||||
Action::SendMsgToSmtpOld => {}
|
||||
}
|
||||
if job.try_again != Delay::AtOnce {
|
||||
if job.try_again != Delay::At_once {
|
||||
break;
|
||||
}
|
||||
tries += 1
|
||||
@@ -879,7 +912,7 @@ fn job_perform(context: &Context, thread: Thread, probe_network: bool) {
|
||||
.unsuspend(context);
|
||||
suspend_smtp_thread(context, false);
|
||||
break;
|
||||
} else if job.try_again == Delay::IncreationPoll {
|
||||
} else if job.try_again == Delay::Increation_poll {
|
||||
// just try over next loop unconditionally, the ui typically interrupts idle when the file (video) is ready
|
||||
info!(
|
||||
context,
|
||||
@@ -892,7 +925,7 @@ fn job_perform(context: &Context, thread: Thread, probe_network: bool) {
|
||||
},
|
||||
job.job_id
|
||||
);
|
||||
} else if job.try_again == Delay::AtOnce || job.try_again == Delay::Standard {
|
||||
} else if job.try_again == Delay::At_once || job.try_again == Delay::Standard {
|
||||
let tries = job.tries + 1;
|
||||
if tries < 17 {
|
||||
job.tries = tries;
|
||||
@@ -924,7 +957,9 @@ fn job_perform(context: &Context, thread: Thread, probe_network: bool) {
|
||||
}
|
||||
} else {
|
||||
if job.action == Action::SendMsgToSmtp {
|
||||
dc_set_msg_failed(context, job.foreign_id, job.pending_error.as_ref());
|
||||
unsafe {
|
||||
dc_set_msg_failed(context, job.foreign_id, job.pending_error.as_ref())
|
||||
};
|
||||
}
|
||||
job.delete(context);
|
||||
}
|
||||
@@ -968,25 +1003,42 @@ fn suspend_smtp_thread(context: &Context, suspend: bool) {
|
||||
}
|
||||
}
|
||||
|
||||
fn connect_to_inbox(context: &Context, inbox: &Imap) -> bool {
|
||||
if inbox.is_connected() {
|
||||
true
|
||||
} else {
|
||||
let ret_connected = dc_connect_to_configured_imap(context, inbox);
|
||||
if 0 != ret_connected {
|
||||
inbox.set_watch_folder("INBOX".into());
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
fn connect_to_inbox(context: &Context, inbox: &Imap) -> libc::c_int {
|
||||
let ret_connected = dc_connect_to_configured_imap(context, inbox);
|
||||
if 0 != ret_connected {
|
||||
inbox.set_watch_folder("INBOX".into());
|
||||
}
|
||||
ret_connected
|
||||
}
|
||||
|
||||
pub fn send_mdn(context: &Context, msg_id: uint32_t) {
|
||||
if let Ok(mut mimefactory) = unsafe { dc_mimefactory_load_mdn(context, msg_id) } {
|
||||
if 0 != unsafe { dc_mimefactory_render(&mut mimefactory) } {
|
||||
add_smtp_job(context, Action::SendMdn, &mut mimefactory);
|
||||
}
|
||||
fn send_mdn(context: &Context, msg_id: uint32_t) {
|
||||
let mut mimefactory = dc_mimefactory_t {
|
||||
from_addr: ptr::null_mut(),
|
||||
from_displayname: ptr::null_mut(),
|
||||
selfstatus: ptr::null_mut(),
|
||||
recipients_names: ptr::null_mut(),
|
||||
recipients_addr: ptr::null_mut(),
|
||||
timestamp: 0,
|
||||
rfc724_mid: ptr::null_mut(),
|
||||
loaded: DC_MF_NOTHING_LOADED,
|
||||
msg: ptr::null_mut(),
|
||||
chat: None,
|
||||
increation: 0,
|
||||
in_reply_to: ptr::null_mut(),
|
||||
references: ptr::null_mut(),
|
||||
req_mdn: 0,
|
||||
out: ptr::null_mut(),
|
||||
out_encrypted: 0,
|
||||
out_gossiped: 0,
|
||||
out_last_added_location_id: 0,
|
||||
error: ptr::null_mut(),
|
||||
context,
|
||||
};
|
||||
|
||||
if !(0 == unsafe { dc_mimefactory_load_mdn(&mut mimefactory, msg_id) }
|
||||
|| 0 == unsafe { dc_mimefactory_render(&mut mimefactory) })
|
||||
{
|
||||
add_smtp_job(context, Action::SendMdn, &mut mimefactory);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1042,7 +1094,7 @@ fn add_smtp_job(context: &Context, action: Action, mimefactory: &dc_mimefactory_
|
||||
(if mimefactory.loaded as libc::c_uint
|
||||
== DC_MF_MSG_LOADED as libc::c_int as libc::c_uint
|
||||
{
|
||||
mimefactory.msg.id
|
||||
unsafe { (*mimefactory.msg).id }
|
||||
} else {
|
||||
0
|
||||
}) as libc::c_int,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use std::sync::{Arc, Condvar, Mutex};
|
||||
|
||||
use crate::configure::*;
|
||||
use crate::context::Context;
|
||||
use crate::dc_configure::*;
|
||||
use crate::imap::Imap;
|
||||
|
||||
pub struct JobThread {
|
||||
|
||||
@@ -20,13 +20,12 @@ extern crate strum_macros;
|
||||
#[macro_use]
|
||||
mod log;
|
||||
#[macro_use]
|
||||
pub mod error;
|
||||
mod error;
|
||||
|
||||
mod aheader;
|
||||
pub mod chat;
|
||||
pub mod chatlist;
|
||||
pub mod config;
|
||||
pub mod configure;
|
||||
pub mod constants;
|
||||
pub mod contact;
|
||||
pub mod context;
|
||||
@@ -36,7 +35,6 @@ mod job_thread;
|
||||
pub mod key;
|
||||
pub mod keyring;
|
||||
pub mod lot;
|
||||
pub mod message;
|
||||
pub mod oauth2;
|
||||
mod param;
|
||||
pub mod peerstate;
|
||||
@@ -49,6 +47,7 @@ pub mod types;
|
||||
pub mod x;
|
||||
|
||||
pub mod dc_array;
|
||||
pub mod dc_configure;
|
||||
mod dc_dehtml;
|
||||
mod dc_e2ee;
|
||||
pub mod dc_imex;
|
||||
@@ -57,6 +56,7 @@ mod dc_loginparam;
|
||||
mod dc_mimefactory;
|
||||
pub mod dc_mimeparser;
|
||||
mod dc_move;
|
||||
pub mod dc_msg;
|
||||
pub mod dc_receive_imf;
|
||||
pub mod dc_securejoin;
|
||||
mod dc_simplify;
|
||||
|
||||
@@ -94,7 +94,6 @@ pub enum LotState {
|
||||
MsgInFresh = 10,
|
||||
MsgInNoticed = 13,
|
||||
MsgInSeen = 16,
|
||||
MsgInMDNSent = 17,
|
||||
MsgOutPreparing = 18,
|
||||
MsgOutDraft = 19,
|
||||
MsgOutPending = 20,
|
||||
|
||||
Reference in New Issue
Block a user