mirror of
https://github.com/chatmail/core.git
synced 2026-04-23 00:16:34 +03:00
1871 lines
76 KiB
Rust
1871 lines
76 KiB
Rust
use c2rust_bitfields::BitfieldStruct;
|
|
use libc;
|
|
|
|
use crate::dc_array::*;
|
|
use crate::dc_context::dc_context_t;
|
|
use crate::dc_log::*;
|
|
use crate::dc_loginparam::*;
|
|
use crate::dc_oauth2::*;
|
|
use crate::dc_sqlite3::*;
|
|
use crate::dc_stock::*;
|
|
use crate::dc_strbuilder::*;
|
|
use crate::dc_tools::*;
|
|
use crate::types::*;
|
|
use crate::x::*;
|
|
|
|
#[derive(Copy, Clone)]
|
|
#[repr(C)]
|
|
pub struct dc_imap_t {
|
|
pub addr: *mut libc::c_char,
|
|
pub imap_server: *mut libc::c_char,
|
|
pub imap_port: libc::c_int,
|
|
pub imap_user: *mut libc::c_char,
|
|
pub imap_pw: *mut libc::c_char,
|
|
pub server_flags: libc::c_int,
|
|
pub connected: libc::c_int,
|
|
pub etpan: *mut mailimap,
|
|
pub idle_set_up: libc::c_int,
|
|
pub selected_folder: *mut libc::c_char,
|
|
pub selected_folder_needs_expunge: libc::c_int,
|
|
pub should_reconnect: libc::c_int,
|
|
pub can_idle: libc::c_int,
|
|
pub has_xlist: libc::c_int,
|
|
pub imap_delimiter: libc::c_char,
|
|
pub watch_folder: *mut libc::c_char,
|
|
pub watch_cond: pthread_cond_t,
|
|
pub watch_condmutex: pthread_mutex_t,
|
|
pub watch_condflag: libc::c_int,
|
|
pub fetch_type_prefetch: *mut mailimap_fetch_type,
|
|
pub fetch_type_body: *mut mailimap_fetch_type,
|
|
pub fetch_type_flags: *mut mailimap_fetch_type,
|
|
pub get_config: dc_get_config_t,
|
|
pub set_config: dc_set_config_t,
|
|
pub precheck_imf: dc_precheck_imf_t,
|
|
pub receive_imf: dc_receive_imf_t,
|
|
pub userData: *mut libc::c_void,
|
|
pub context: *mut dc_context_t,
|
|
pub log_connect_errors: libc::c_int,
|
|
pub skip_log_capabilities: libc::c_int,
|
|
}
|
|
|
|
pub unsafe fn dc_imap_new(
|
|
mut get_config: dc_get_config_t,
|
|
mut set_config: dc_set_config_t,
|
|
mut precheck_imf: dc_precheck_imf_t,
|
|
mut receive_imf: dc_receive_imf_t,
|
|
mut userData: *mut libc::c_void,
|
|
mut context: *mut dc_context_t,
|
|
) -> *mut dc_imap_t {
|
|
let mut imap: *mut dc_imap_t = 0 as *mut dc_imap_t;
|
|
imap = calloc(
|
|
1i32 as libc::c_ulong,
|
|
::std::mem::size_of::<dc_imap_t>() as libc::c_ulong,
|
|
) as *mut dc_imap_t;
|
|
if imap.is_null() {
|
|
exit(25i32);
|
|
}
|
|
(*imap).log_connect_errors = 1i32;
|
|
(*imap).context = context;
|
|
(*imap).get_config = get_config;
|
|
(*imap).set_config = set_config;
|
|
(*imap).precheck_imf = precheck_imf;
|
|
(*imap).receive_imf = receive_imf;
|
|
(*imap).userData = userData;
|
|
pthread_mutex_init(
|
|
&mut (*imap).watch_condmutex,
|
|
0 as *const pthread_mutexattr_t,
|
|
);
|
|
pthread_cond_init(&mut (*imap).watch_cond, 0 as *const pthread_condattr_t);
|
|
(*imap).watch_folder =
|
|
calloc(1i32 as libc::c_ulong, 1i32 as libc::c_ulong) as *mut libc::c_char;
|
|
(*imap).selected_folder =
|
|
calloc(1i32 as libc::c_ulong, 1i32 as libc::c_ulong) as *mut libc::c_char;
|
|
(*imap).fetch_type_prefetch = mailimap_fetch_type_new_fetch_att_list_empty();
|
|
mailimap_fetch_type_new_fetch_att_list_add(
|
|
(*imap).fetch_type_prefetch,
|
|
mailimap_fetch_att_new_uid(),
|
|
);
|
|
mailimap_fetch_type_new_fetch_att_list_add(
|
|
(*imap).fetch_type_prefetch,
|
|
mailimap_fetch_att_new_envelope(),
|
|
);
|
|
(*imap).fetch_type_body = mailimap_fetch_type_new_fetch_att_list_empty();
|
|
mailimap_fetch_type_new_fetch_att_list_add(
|
|
(*imap).fetch_type_body,
|
|
mailimap_fetch_att_new_flags(),
|
|
);
|
|
mailimap_fetch_type_new_fetch_att_list_add(
|
|
(*imap).fetch_type_body,
|
|
mailimap_fetch_att_new_body_peek_section(mailimap_section_new(
|
|
0 as *mut mailimap_section_spec,
|
|
)),
|
|
);
|
|
(*imap).fetch_type_flags = mailimap_fetch_type_new_fetch_att_list_empty();
|
|
mailimap_fetch_type_new_fetch_att_list_add(
|
|
(*imap).fetch_type_flags,
|
|
mailimap_fetch_att_new_flags(),
|
|
);
|
|
return imap;
|
|
}
|
|
pub unsafe fn dc_imap_unref(mut imap: *mut dc_imap_t) {
|
|
if imap.is_null() {
|
|
return;
|
|
}
|
|
dc_imap_disconnect(imap);
|
|
pthread_cond_destroy(&mut (*imap).watch_cond);
|
|
pthread_mutex_destroy(&mut (*imap).watch_condmutex);
|
|
free((*imap).watch_folder as *mut libc::c_void);
|
|
free((*imap).selected_folder as *mut libc::c_void);
|
|
if !(*imap).fetch_type_prefetch.is_null() {
|
|
mailimap_fetch_type_free((*imap).fetch_type_prefetch);
|
|
}
|
|
if !(*imap).fetch_type_body.is_null() {
|
|
mailimap_fetch_type_free((*imap).fetch_type_body);
|
|
}
|
|
if !(*imap).fetch_type_flags.is_null() {
|
|
mailimap_fetch_type_free((*imap).fetch_type_flags);
|
|
}
|
|
free(imap as *mut libc::c_void);
|
|
}
|
|
pub unsafe fn dc_imap_disconnect(mut imap: *mut dc_imap_t) {
|
|
if imap.is_null() {
|
|
return;
|
|
}
|
|
if 0 != (*imap).connected {
|
|
unsetup_handle(imap);
|
|
free_connect_param(imap);
|
|
(*imap).connected = 0i32
|
|
};
|
|
}
|
|
/* we leave sent_folder set; normally this does not change in a normal reconnect; we'll update this folder if we get errors */
|
|
/* ******************************************************************************
|
|
* Connect/Disconnect
|
|
******************************************************************************/
|
|
unsafe fn free_connect_param(mut imap: *mut dc_imap_t) {
|
|
free((*imap).addr as *mut libc::c_void);
|
|
(*imap).addr = 0 as *mut libc::c_char;
|
|
free((*imap).imap_server as *mut libc::c_void);
|
|
(*imap).imap_server = 0 as *mut libc::c_char;
|
|
free((*imap).imap_user as *mut libc::c_void);
|
|
(*imap).imap_user = 0 as *mut libc::c_char;
|
|
free((*imap).imap_pw as *mut libc::c_void);
|
|
(*imap).imap_pw = 0 as *mut libc::c_char;
|
|
*(*imap).watch_folder.offset(0isize) = 0i32 as libc::c_char;
|
|
*(*imap).selected_folder.offset(0isize) = 0i32 as libc::c_char;
|
|
(*imap).imap_port = 0i32;
|
|
(*imap).can_idle = 0i32;
|
|
(*imap).has_xlist = 0i32;
|
|
}
|
|
unsafe fn unsetup_handle(mut imap: *mut dc_imap_t) {
|
|
if imap.is_null() {
|
|
return;
|
|
}
|
|
if !(*imap).etpan.is_null() {
|
|
if 0 != (*imap).idle_set_up {
|
|
mailstream_unsetup_idle((*(*imap).etpan).imap_stream);
|
|
(*imap).idle_set_up = 0i32
|
|
}
|
|
if !(*(*imap).etpan).imap_stream.is_null() {
|
|
mailstream_close((*(*imap).etpan).imap_stream);
|
|
(*(*imap).etpan).imap_stream = 0 as *mut mailstream
|
|
}
|
|
mailimap_free((*imap).etpan);
|
|
(*imap).etpan = 0 as *mut mailimap;
|
|
dc_log_info(
|
|
(*imap).context,
|
|
0i32,
|
|
b"IMAP disconnected.\x00" as *const u8 as *const libc::c_char,
|
|
);
|
|
}
|
|
*(*imap).selected_folder.offset(0isize) = 0i32 as libc::c_char;
|
|
}
|
|
pub unsafe fn dc_imap_connect(
|
|
mut imap: *mut dc_imap_t,
|
|
mut lp: *const dc_loginparam_t,
|
|
) -> libc::c_int {
|
|
let mut success: libc::c_int = 0i32;
|
|
if imap.is_null()
|
|
|| lp.is_null()
|
|
|| (*lp).mail_server.is_null()
|
|
|| (*lp).mail_user.is_null()
|
|
|| (*lp).mail_pw.is_null()
|
|
{
|
|
return 0i32;
|
|
}
|
|
if 0 != (*imap).connected {
|
|
success = 1i32
|
|
} else {
|
|
(*imap).addr = dc_strdup((*lp).addr);
|
|
(*imap).imap_server = dc_strdup((*lp).mail_server);
|
|
(*imap).imap_port = (*lp).mail_port as libc::c_int;
|
|
(*imap).imap_user = dc_strdup((*lp).mail_user);
|
|
(*imap).imap_pw = dc_strdup((*lp).mail_pw);
|
|
(*imap).server_flags = (*lp).server_flags;
|
|
if !(0 == setup_handle_if_needed(imap)) {
|
|
(*imap).can_idle = mailimap_has_idle((*imap).etpan);
|
|
(*imap).has_xlist = mailimap_has_xlist((*imap).etpan);
|
|
(*imap).can_idle = 0i32;
|
|
if 0 == (*imap).skip_log_capabilities
|
|
&& !(*(*imap).etpan).imap_connection_info.is_null()
|
|
&& !(*(*(*imap).etpan).imap_connection_info)
|
|
.imap_capability
|
|
.is_null()
|
|
{
|
|
(*imap).skip_log_capabilities = 1i32;
|
|
let mut capinfostr: dc_strbuilder_t = dc_strbuilder_t {
|
|
buf: 0 as *mut libc::c_char,
|
|
allocated: 0,
|
|
free: 0,
|
|
eos: 0 as *mut libc::c_char,
|
|
};
|
|
dc_strbuilder_init(&mut capinfostr, 0i32);
|
|
let mut list: *mut clist =
|
|
(*(*(*(*imap).etpan).imap_connection_info).imap_capability).cap_list;
|
|
if !list.is_null() {
|
|
let mut cur: *mut clistiter = 0 as *mut clistiter;
|
|
cur = (*list).first;
|
|
while !cur.is_null() {
|
|
let mut cap: *mut mailimap_capability = (if !cur.is_null() {
|
|
(*cur).data
|
|
} else {
|
|
0 as *mut libc::c_void
|
|
})
|
|
as *mut mailimap_capability;
|
|
if !cap.is_null()
|
|
&& (*cap).cap_type == MAILIMAP_CAPABILITY_NAME as libc::c_int
|
|
{
|
|
dc_strbuilder_cat(
|
|
&mut capinfostr,
|
|
b" \x00" as *const u8 as *const libc::c_char,
|
|
);
|
|
dc_strbuilder_cat(&mut capinfostr, (*cap).cap_data.cap_name);
|
|
}
|
|
cur = if !cur.is_null() {
|
|
(*cur).next
|
|
} else {
|
|
0 as *mut clistcell_s
|
|
}
|
|
}
|
|
}
|
|
dc_log_info(
|
|
(*imap).context,
|
|
0i32,
|
|
b"IMAP-capabilities:%s\x00" as *const u8 as *const libc::c_char,
|
|
capinfostr.buf,
|
|
);
|
|
free(capinfostr.buf as *mut libc::c_void);
|
|
}
|
|
(*imap).connected = 1i32;
|
|
success = 1i32
|
|
}
|
|
}
|
|
if success == 0i32 {
|
|
unsetup_handle(imap);
|
|
free_connect_param(imap);
|
|
}
|
|
return success;
|
|
}
|
|
unsafe fn setup_handle_if_needed(mut imap: *mut dc_imap_t) -> libc::c_int {
|
|
let mut current_block: u64;
|
|
let mut r: libc::c_int = 0i32;
|
|
let mut success: libc::c_int = 0i32;
|
|
if !(imap.is_null() || (*imap).imap_server.is_null()) {
|
|
if 0 != (*imap).should_reconnect {
|
|
unsetup_handle(imap);
|
|
}
|
|
if !(*imap).etpan.is_null() {
|
|
success = 1i32
|
|
} else {
|
|
(*imap).etpan = mailimap_new(0i32 as size_t, None);
|
|
mailimap_set_timeout((*imap).etpan, 10i32 as time_t);
|
|
if 0 != (*imap).server_flags & (0x100i32 | 0x400i32) {
|
|
r = mailimap_socket_connect(
|
|
(*imap).etpan,
|
|
(*imap).imap_server,
|
|
(*imap).imap_port as uint16_t,
|
|
);
|
|
if 0 != dc_imap_is_error(imap, r) {
|
|
dc_log_event_seq(
|
|
(*imap).context,
|
|
401i32,
|
|
&mut (*imap).log_connect_errors as *mut libc::c_int,
|
|
b"Could not connect to IMAP-server %s:%i. (Error #%i)\x00" as *const u8
|
|
as *const libc::c_char,
|
|
(*imap).imap_server,
|
|
(*imap).imap_port as libc::c_int,
|
|
r as libc::c_int,
|
|
);
|
|
current_block = 15811161807000851472;
|
|
} else if 0 != (*imap).server_flags & 0x100i32 {
|
|
r = mailimap_socket_starttls((*imap).etpan);
|
|
if 0 != dc_imap_is_error(imap, r) {
|
|
dc_log_event_seq((*imap).context, 401i32,
|
|
&mut (*imap).log_connect_errors as
|
|
*mut libc::c_int,
|
|
b"Could not connect to IMAP-server %s:%i using STARTTLS. (Error #%i)\x00"
|
|
as *const u8 as
|
|
*const libc::c_char,
|
|
(*imap).imap_server,
|
|
(*imap).imap_port as libc::c_int,
|
|
r as libc::c_int);
|
|
current_block = 15811161807000851472;
|
|
} else {
|
|
dc_log_info(
|
|
(*imap).context,
|
|
0i32,
|
|
b"IMAP-server %s:%i STARTTLS-connected.\x00" as *const u8
|
|
as *const libc::c_char,
|
|
(*imap).imap_server,
|
|
(*imap).imap_port as libc::c_int,
|
|
);
|
|
current_block = 14763689060501151050;
|
|
}
|
|
} else {
|
|
dc_log_info(
|
|
(*imap).context,
|
|
0i32,
|
|
b"IMAP-server %s:%i connected.\x00" as *const u8 as *const libc::c_char,
|
|
(*imap).imap_server,
|
|
(*imap).imap_port as libc::c_int,
|
|
);
|
|
current_block = 14763689060501151050;
|
|
}
|
|
} else {
|
|
r = mailimap_ssl_connect(
|
|
(*imap).etpan,
|
|
(*imap).imap_server,
|
|
(*imap).imap_port as uint16_t,
|
|
);
|
|
if 0 != dc_imap_is_error(imap, r) {
|
|
dc_log_event_seq(
|
|
(*imap).context,
|
|
401i32,
|
|
&mut (*imap).log_connect_errors as *mut libc::c_int,
|
|
b"Could not connect to IMAP-server %s:%i using SSL. (Error #%i)\x00"
|
|
as *const u8 as *const libc::c_char,
|
|
(*imap).imap_server,
|
|
(*imap).imap_port as libc::c_int,
|
|
r as libc::c_int,
|
|
);
|
|
current_block = 15811161807000851472;
|
|
} else {
|
|
dc_log_info(
|
|
(*imap).context,
|
|
0i32,
|
|
b"IMAP-server %s:%i SSL-connected.\x00" as *const u8 as *const libc::c_char,
|
|
(*imap).imap_server,
|
|
(*imap).imap_port as libc::c_int,
|
|
);
|
|
current_block = 14763689060501151050;
|
|
}
|
|
}
|
|
match current_block {
|
|
15811161807000851472 => {}
|
|
_ => {
|
|
if 0 != (*imap).server_flags & 0x2i32 {
|
|
dc_log_info(
|
|
(*imap).context,
|
|
0i32,
|
|
b"IMAP-OAuth2 connect...\x00" as *const u8 as *const libc::c_char,
|
|
);
|
|
let mut access_token: *mut libc::c_char = dc_get_oauth2_access_token(
|
|
(*imap).context,
|
|
(*imap).addr,
|
|
(*imap).imap_pw,
|
|
0i32,
|
|
);
|
|
r = mailimap_oauth2_authenticate(
|
|
(*imap).etpan,
|
|
(*imap).imap_user,
|
|
access_token,
|
|
);
|
|
if 0 != dc_imap_is_error(imap, r) {
|
|
free(access_token as *mut libc::c_void);
|
|
access_token = dc_get_oauth2_access_token(
|
|
(*imap).context,
|
|
(*imap).addr,
|
|
(*imap).imap_pw,
|
|
0x1i32,
|
|
);
|
|
r = mailimap_oauth2_authenticate(
|
|
(*imap).etpan,
|
|
(*imap).imap_user,
|
|
access_token,
|
|
)
|
|
}
|
|
free(access_token as *mut libc::c_void);
|
|
} else {
|
|
r = mailimap_login((*imap).etpan, (*imap).imap_user, (*imap).imap_pw)
|
|
}
|
|
if 0 != dc_imap_is_error(imap, r) {
|
|
let mut msg: *mut libc::c_char = get_error_msg(
|
|
imap,
|
|
b"Cannot login\x00" as *const u8 as *const libc::c_char,
|
|
r,
|
|
);
|
|
dc_log_event_seq(
|
|
(*imap).context,
|
|
401i32,
|
|
&mut (*imap).log_connect_errors as *mut libc::c_int,
|
|
b"%s\x00" as *const u8 as *const libc::c_char,
|
|
msg,
|
|
);
|
|
free(msg as *mut libc::c_void);
|
|
} else {
|
|
dc_log_event(
|
|
(*imap).context,
|
|
102i32,
|
|
0i32,
|
|
b"IMAP-login as %s ok.\x00" as *const u8 as *const libc::c_char,
|
|
(*imap).imap_user,
|
|
);
|
|
success = 1i32
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if success == 0i32 {
|
|
unsetup_handle(imap);
|
|
}
|
|
(*imap).should_reconnect = 0i32;
|
|
return success;
|
|
}
|
|
unsafe fn get_error_msg(
|
|
mut imap: *mut dc_imap_t,
|
|
mut what_failed: *const libc::c_char,
|
|
mut code: libc::c_int,
|
|
) -> *mut libc::c_char {
|
|
let mut stock: *mut libc::c_char = 0 as *mut libc::c_char;
|
|
let mut msg: dc_strbuilder_t = dc_strbuilder_t {
|
|
buf: 0 as *mut libc::c_char,
|
|
allocated: 0,
|
|
free: 0,
|
|
eos: 0 as *mut libc::c_char,
|
|
};
|
|
dc_strbuilder_init(&mut msg, 1000i32);
|
|
match code {
|
|
28 => {
|
|
stock = dc_stock_str_repl_string((*imap).context, 60i32, (*imap).imap_user);
|
|
dc_strbuilder_cat(&mut msg, stock);
|
|
}
|
|
_ => {
|
|
dc_strbuilder_catf(
|
|
&mut msg as *mut dc_strbuilder_t,
|
|
b"%s, IMAP-error #%i\x00" as *const u8 as *const libc::c_char,
|
|
what_failed,
|
|
code,
|
|
);
|
|
}
|
|
}
|
|
free(stock as *mut libc::c_void);
|
|
stock = 0 as *mut libc::c_char;
|
|
if !(*(*imap).etpan).imap_response.is_null() {
|
|
dc_strbuilder_cat(&mut msg, b"\n\n\x00" as *const u8 as *const libc::c_char);
|
|
stock = dc_stock_str_repl_string2(
|
|
(*imap).context,
|
|
61i32,
|
|
(*imap).imap_server,
|
|
(*(*imap).etpan).imap_response,
|
|
);
|
|
dc_strbuilder_cat(&mut msg, stock);
|
|
}
|
|
free(stock as *mut libc::c_void);
|
|
stock = 0 as *mut libc::c_char;
|
|
return msg.buf;
|
|
}
|
|
pub unsafe fn dc_imap_is_error(mut imap: *mut dc_imap_t, mut code: libc::c_int) -> libc::c_int {
|
|
if code == MAILIMAP_NO_ERROR as libc::c_int
|
|
|| code == MAILIMAP_NO_ERROR_AUTHENTICATED as libc::c_int
|
|
|| code == MAILIMAP_NO_ERROR_NON_AUTHENTICATED as libc::c_int
|
|
{
|
|
return 0i32;
|
|
}
|
|
if code == MAILIMAP_ERROR_STREAM as libc::c_int || code == MAILIMAP_ERROR_PARSE as libc::c_int {
|
|
dc_log_info(
|
|
(*imap).context,
|
|
0i32,
|
|
b"IMAP stream lost; we\'ll reconnect soon.\x00" as *const u8 as *const libc::c_char,
|
|
);
|
|
(*imap).should_reconnect = 1i32
|
|
}
|
|
return 1i32;
|
|
}
|
|
pub unsafe extern "C" fn dc_imap_set_watch_folder(
|
|
mut imap: *mut dc_imap_t,
|
|
mut watch_folder: *const libc::c_char,
|
|
) {
|
|
if imap.is_null() || watch_folder.is_null() {
|
|
return;
|
|
}
|
|
free((*imap).watch_folder as *mut libc::c_void);
|
|
(*imap).watch_folder = dc_strdup(watch_folder);
|
|
}
|
|
pub unsafe fn dc_imap_is_connected(mut imap: *const dc_imap_t) -> libc::c_int {
|
|
return (!imap.is_null() && 0 != (*imap).connected) as libc::c_int;
|
|
}
|
|
pub unsafe fn dc_imap_fetch(mut imap: *mut dc_imap_t) -> libc::c_int {
|
|
let mut success: libc::c_int = 0i32;
|
|
if !(imap.is_null() || 0 == (*imap).connected) {
|
|
setup_handle_if_needed(imap);
|
|
while fetch_from_single_folder(imap, (*imap).watch_folder) > 0i32 {}
|
|
success = 1i32
|
|
}
|
|
return success;
|
|
}
|
|
unsafe fn fetch_from_single_folder(
|
|
mut imap: *mut dc_imap_t,
|
|
mut folder: *const libc::c_char,
|
|
) -> libc::c_int {
|
|
let mut current_block: u64;
|
|
let mut r: libc::c_int = 0;
|
|
let mut uidvalidity: uint32_t = 0i32 as uint32_t;
|
|
let mut lastseenuid: uint32_t = 0i32 as uint32_t;
|
|
let mut new_lastseenuid: uint32_t = 0i32 as uint32_t;
|
|
let mut fetch_result: *mut clist = 0 as *mut clist;
|
|
let mut read_cnt: size_t = 0i32 as size_t;
|
|
let mut read_errors: size_t = 0i32 as size_t;
|
|
let mut cur: *mut clistiter = 0 as *mut clistiter;
|
|
let mut set: *mut mailimap_set = 0 as *mut mailimap_set;
|
|
if !imap.is_null() {
|
|
if (*imap).etpan.is_null() {
|
|
dc_log_info(
|
|
(*imap).context,
|
|
0i32,
|
|
b"Cannot fetch from \"%s\" - not connected.\x00" as *const u8
|
|
as *const libc::c_char,
|
|
folder,
|
|
);
|
|
} else if select_folder(imap, folder) == 0i32 {
|
|
dc_log_warning(
|
|
(*imap).context,
|
|
0i32,
|
|
b"Cannot select folder %s for fetching.\x00" as *const u8 as *const libc::c_char,
|
|
folder,
|
|
);
|
|
} else {
|
|
get_config_lastseenuid(imap, folder, &mut uidvalidity, &mut lastseenuid);
|
|
if uidvalidity != (*(*(*imap).etpan).imap_selection_info).sel_uidvalidity {
|
|
/* first time this folder is selected or UIDVALIDITY has changed, init lastseenuid and save it to config */
|
|
if (*(*(*imap).etpan).imap_selection_info).sel_uidvalidity <= 0i32 as libc::c_uint {
|
|
dc_log_error(
|
|
(*imap).context,
|
|
0i32,
|
|
b"Cannot get UIDVALIDITY for folder \"%s\".\x00" as *const u8
|
|
as *const libc::c_char,
|
|
folder,
|
|
);
|
|
current_block = 17288151659885296046;
|
|
} else {
|
|
if 0 != (*(*(*imap).etpan).imap_selection_info).sel_has_exists() {
|
|
if (*(*(*imap).etpan).imap_selection_info).sel_exists
|
|
<= 0i32 as libc::c_uint
|
|
{
|
|
dc_log_info(
|
|
(*imap).context,
|
|
0i32,
|
|
b"Folder \"%s\" is empty.\x00" as *const u8 as *const libc::c_char,
|
|
folder,
|
|
);
|
|
if (*(*(*imap).etpan).imap_selection_info).sel_exists
|
|
== 0i32 as libc::c_uint
|
|
{
|
|
set_config_lastseenuid(
|
|
imap,
|
|
folder,
|
|
(*(*(*imap).etpan).imap_selection_info).sel_uidvalidity,
|
|
0i32 as uint32_t,
|
|
);
|
|
}
|
|
current_block = 17288151659885296046;
|
|
} else {
|
|
set = mailimap_set_new_single(
|
|
(*(*(*imap).etpan).imap_selection_info).sel_exists,
|
|
);
|
|
current_block = 11057878835866523405;
|
|
}
|
|
} else {
|
|
dc_log_info(
|
|
(*imap).context,
|
|
0i32,
|
|
b"EXISTS is missing for folder \"%s\", using fallback.\x00" as *const u8
|
|
as *const libc::c_char,
|
|
folder,
|
|
);
|
|
set = mailimap_set_new_single(0i32 as uint32_t);
|
|
current_block = 11057878835866523405;
|
|
}
|
|
match current_block {
|
|
17288151659885296046 => {}
|
|
_ => {
|
|
r = mailimap_fetch(
|
|
(*imap).etpan,
|
|
set,
|
|
(*imap).fetch_type_prefetch,
|
|
&mut fetch_result,
|
|
);
|
|
if !set.is_null() {
|
|
mailimap_set_free(set);
|
|
set = 0 as *mut mailimap_set
|
|
}
|
|
if 0 != dc_imap_is_error(imap, r) || fetch_result.is_null() {
|
|
fetch_result = 0 as *mut clist;
|
|
dc_log_info(
|
|
(*imap).context,
|
|
0i32,
|
|
b"No result returned for folder \"%s\".\x00" as *const u8
|
|
as *const libc::c_char,
|
|
folder,
|
|
);
|
|
/* this might happen if the mailbox is empty an EXISTS does not work */
|
|
current_block = 17288151659885296046;
|
|
} else {
|
|
cur = (*fetch_result).first;
|
|
if cur.is_null() {
|
|
dc_log_info(
|
|
(*imap).context,
|
|
0i32,
|
|
b"Empty result returned for folder \"%s\".\x00" as *const u8
|
|
as *const libc::c_char,
|
|
folder,
|
|
);
|
|
/* this might happen if the mailbox is empty an EXISTS does not work */
|
|
current_block = 17288151659885296046;
|
|
} else {
|
|
let mut msg_att: *mut mailimap_msg_att = (if !cur.is_null() {
|
|
(*cur).data
|
|
} else {
|
|
0 as *mut libc::c_void
|
|
})
|
|
as *mut mailimap_msg_att;
|
|
lastseenuid = peek_uid(msg_att);
|
|
if !fetch_result.is_null() {
|
|
mailimap_fetch_list_free(fetch_result);
|
|
fetch_result = 0 as *mut clist
|
|
}
|
|
if lastseenuid <= 0i32 as libc::c_uint {
|
|
dc_log_error(
|
|
(*imap).context,
|
|
0i32,
|
|
b"Cannot get largest UID for folder \"%s\"\x00"
|
|
as *const u8
|
|
as *const libc::c_char,
|
|
folder,
|
|
);
|
|
current_block = 17288151659885296046;
|
|
} else {
|
|
if uidvalidity > 0i32 as libc::c_uint
|
|
&& lastseenuid > 1i32 as libc::c_uint
|
|
{
|
|
lastseenuid = (lastseenuid as libc::c_uint)
|
|
.wrapping_sub(1i32 as libc::c_uint)
|
|
as uint32_t
|
|
as uint32_t
|
|
}
|
|
uidvalidity =
|
|
(*(*(*imap).etpan).imap_selection_info).sel_uidvalidity;
|
|
set_config_lastseenuid(
|
|
imap,
|
|
folder,
|
|
uidvalidity,
|
|
lastseenuid,
|
|
);
|
|
dc_log_info(
|
|
(*imap).context,
|
|
0i32,
|
|
b"lastseenuid initialized to %i for %s@%i\x00"
|
|
as *const u8
|
|
as *const libc::c_char,
|
|
lastseenuid as libc::c_int,
|
|
folder,
|
|
uidvalidity as libc::c_int,
|
|
);
|
|
current_block = 2516253395664191498;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
current_block = 2516253395664191498;
|
|
}
|
|
match current_block {
|
|
17288151659885296046 => {}
|
|
_ => {
|
|
set = mailimap_set_new_interval(
|
|
lastseenuid.wrapping_add(1i32 as libc::c_uint),
|
|
0i32 as uint32_t,
|
|
);
|
|
r = mailimap_uid_fetch(
|
|
(*imap).etpan,
|
|
set,
|
|
(*imap).fetch_type_prefetch,
|
|
&mut fetch_result,
|
|
);
|
|
if !set.is_null() {
|
|
mailimap_set_free(set);
|
|
set = 0 as *mut mailimap_set
|
|
}
|
|
if 0 != dc_imap_is_error(imap, r) || fetch_result.is_null() {
|
|
fetch_result = 0 as *mut clist;
|
|
if r == MAILIMAP_ERROR_PROTOCOL as libc::c_int {
|
|
dc_log_info(
|
|
(*imap).context,
|
|
0i32,
|
|
b"Folder \"%s\" is empty\x00" as *const u8 as *const libc::c_char,
|
|
folder,
|
|
);
|
|
} else {
|
|
/* the folder is simply empty, this is no error */
|
|
dc_log_warning(
|
|
(*imap).context,
|
|
0i32,
|
|
b"Cannot fetch message list from folder \"%s\".\x00" as *const u8
|
|
as *const libc::c_char,
|
|
folder,
|
|
);
|
|
}
|
|
} else {
|
|
cur = (*fetch_result).first;
|
|
while !cur.is_null() {
|
|
let mut msg_att_0: *mut mailimap_msg_att = (if !cur.is_null() {
|
|
(*cur).data
|
|
} else {
|
|
0 as *mut libc::c_void
|
|
})
|
|
as *mut mailimap_msg_att;
|
|
let mut cur_uid: uint32_t = peek_uid(msg_att_0);
|
|
if cur_uid > lastseenuid {
|
|
let mut rfc724_mid: *mut libc::c_char =
|
|
unquote_rfc724_mid(peek_rfc724_mid(msg_att_0));
|
|
read_cnt = read_cnt.wrapping_add(1);
|
|
if 0 == (*imap).precheck_imf.expect("non-null function pointer")(
|
|
imap, rfc724_mid, folder, cur_uid,
|
|
) {
|
|
if fetch_single_msg(imap, folder, cur_uid) == 0i32 {
|
|
dc_log_info((*imap).context, 0i32,
|
|
b"Read error for message %s from \"%s\", trying over later.\x00"
|
|
as *const u8 as
|
|
*const libc::c_char,
|
|
rfc724_mid, folder);
|
|
read_errors = read_errors.wrapping_add(1)
|
|
}
|
|
} else {
|
|
dc_log_info(
|
|
(*imap).context,
|
|
0i32,
|
|
b"Skipping message %s from \"%s\" by precheck.\x00"
|
|
as *const u8
|
|
as *const libc::c_char,
|
|
rfc724_mid,
|
|
folder,
|
|
);
|
|
}
|
|
if cur_uid > new_lastseenuid {
|
|
new_lastseenuid = cur_uid
|
|
}
|
|
free(rfc724_mid as *mut libc::c_void);
|
|
}
|
|
cur = if !cur.is_null() {
|
|
(*cur).next
|
|
} else {
|
|
0 as *mut clistcell_s
|
|
}
|
|
}
|
|
if 0 == read_errors && new_lastseenuid > 0i32 as libc::c_uint {
|
|
set_config_lastseenuid(imap, folder, uidvalidity, new_lastseenuid);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/* done */
|
|
if 0 != read_errors {
|
|
dc_log_warning(
|
|
(*imap).context,
|
|
0i32,
|
|
b"%i mails read from \"%s\" with %i errors.\x00" as *const u8 as *const libc::c_char,
|
|
read_cnt as libc::c_int,
|
|
folder,
|
|
read_errors as libc::c_int,
|
|
);
|
|
} else {
|
|
dc_log_info(
|
|
(*imap).context,
|
|
0i32,
|
|
b"%i mails read from \"%s\".\x00" as *const u8 as *const libc::c_char,
|
|
read_cnt as libc::c_int,
|
|
folder,
|
|
);
|
|
}
|
|
if !fetch_result.is_null() {
|
|
mailimap_fetch_list_free(fetch_result);
|
|
fetch_result = 0 as *mut clist
|
|
}
|
|
return read_cnt as libc::c_int;
|
|
}
|
|
unsafe fn set_config_lastseenuid(
|
|
mut imap: *mut dc_imap_t,
|
|
mut folder: *const libc::c_char,
|
|
mut uidvalidity: uint32_t,
|
|
mut lastseenuid: uint32_t,
|
|
) {
|
|
let mut key: *mut libc::c_char = dc_mprintf(
|
|
b"imap.mailbox.%s\x00" as *const u8 as *const libc::c_char,
|
|
folder,
|
|
);
|
|
let mut val: *mut libc::c_char = dc_mprintf(
|
|
b"%lu:%lu\x00" as *const u8 as *const libc::c_char,
|
|
uidvalidity,
|
|
lastseenuid,
|
|
);
|
|
(*imap).set_config.expect("non-null function pointer")(imap, key, val);
|
|
free(val as *mut libc::c_void);
|
|
free(key as *mut libc::c_void);
|
|
}
|
|
unsafe fn peek_rfc724_mid(mut msg_att: *mut mailimap_msg_att) -> *const libc::c_char {
|
|
if msg_att.is_null() {
|
|
return 0 as *const libc::c_char;
|
|
}
|
|
/* search the UID in a list of attributes returned by a FETCH command */
|
|
let mut iter1: *mut clistiter = 0 as *mut clistiter;
|
|
iter1 = (*(*msg_att).att_list).first;
|
|
while !iter1.is_null() {
|
|
let mut item: *mut mailimap_msg_att_item = (if !iter1.is_null() {
|
|
(*iter1).data
|
|
} else {
|
|
0 as *mut libc::c_void
|
|
}) as *mut mailimap_msg_att_item;
|
|
if !item.is_null() {
|
|
if (*item).att_type == MAILIMAP_MSG_ATT_ITEM_STATIC as libc::c_int {
|
|
if (*(*item).att_data.att_static).att_type
|
|
== MAILIMAP_MSG_ATT_ENVELOPE as libc::c_int
|
|
{
|
|
let mut env: *mut mailimap_envelope =
|
|
(*(*item).att_data.att_static).att_data.att_env;
|
|
if !env.is_null() && !(*env).env_message_id.is_null() {
|
|
return (*env).env_message_id;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
iter1 = if !iter1.is_null() {
|
|
(*iter1).next
|
|
} else {
|
|
0 as *mut clistcell_s
|
|
}
|
|
}
|
|
return 0 as *const libc::c_char;
|
|
}
|
|
unsafe fn unquote_rfc724_mid(mut in_0: *const libc::c_char) -> *mut libc::c_char {
|
|
/* remove < and > from the given message id */
|
|
let mut out: *mut libc::c_char = dc_strdup(in_0);
|
|
let mut out_len: libc::c_int = strlen(out) as libc::c_int;
|
|
if out_len > 2i32 {
|
|
if *out.offset(0isize) as libc::c_int == '<' as i32 {
|
|
*out.offset(0isize) = ' ' as i32 as libc::c_char
|
|
}
|
|
if *out.offset((out_len - 1i32) as isize) as libc::c_int == '>' as i32 {
|
|
*out.offset((out_len - 1i32) as isize) = ' ' as i32 as libc::c_char
|
|
}
|
|
dc_trim(out);
|
|
}
|
|
return out;
|
|
}
|
|
/* ******************************************************************************
|
|
* Fetch Messages
|
|
******************************************************************************/
|
|
unsafe fn peek_uid(mut msg_att: *mut mailimap_msg_att) -> uint32_t {
|
|
/* search the UID in a list of attributes returned by a FETCH command */
|
|
let mut iter1: *mut clistiter = 0 as *mut clistiter;
|
|
iter1 = (*(*msg_att).att_list).first;
|
|
while !iter1.is_null() {
|
|
let mut item: *mut mailimap_msg_att_item = (if !iter1.is_null() {
|
|
(*iter1).data
|
|
} else {
|
|
0 as *mut libc::c_void
|
|
}) as *mut mailimap_msg_att_item;
|
|
if !item.is_null() {
|
|
if (*item).att_type == MAILIMAP_MSG_ATT_ITEM_STATIC as libc::c_int {
|
|
if (*(*item).att_data.att_static).att_type == MAILIMAP_MSG_ATT_UID as libc::c_int {
|
|
return (*(*item).att_data.att_static).att_data.att_uid;
|
|
}
|
|
}
|
|
}
|
|
iter1 = if !iter1.is_null() {
|
|
(*iter1).next
|
|
} else {
|
|
0 as *mut clistcell_s
|
|
}
|
|
}
|
|
return 0i32 as uint32_t;
|
|
}
|
|
unsafe fn fetch_single_msg(
|
|
mut imap: *mut dc_imap_t,
|
|
mut folder: *const libc::c_char,
|
|
mut server_uid: uint32_t,
|
|
) -> libc::c_int {
|
|
let mut msg_att: *mut mailimap_msg_att = 0 as *mut mailimap_msg_att;
|
|
/* the function returns:
|
|
0 the caller should try over again later
|
|
or 1 if the messages should be treated as received, the caller should not try to read the message again (even if no database entries are returned) */
|
|
let mut msg_content: *mut libc::c_char = 0 as *mut libc::c_char;
|
|
let mut msg_bytes: size_t = 0i32 as size_t;
|
|
let mut r: libc::c_int = 0i32;
|
|
let mut retry_later: libc::c_int = 0i32;
|
|
let mut deleted: libc::c_int = 0i32;
|
|
let mut flags: uint32_t = 0i32 as uint32_t;
|
|
let mut fetch_result: *mut clist = 0 as *mut clist;
|
|
let mut cur: *mut clistiter = 0 as *mut clistiter;
|
|
if !imap.is_null() {
|
|
if !(*imap).etpan.is_null() {
|
|
let mut set: *mut mailimap_set = mailimap_set_new_single(server_uid);
|
|
r = mailimap_uid_fetch(
|
|
(*imap).etpan,
|
|
set,
|
|
(*imap).fetch_type_body,
|
|
&mut fetch_result,
|
|
);
|
|
if !set.is_null() {
|
|
mailimap_set_free(set);
|
|
set = 0 as *mut mailimap_set
|
|
}
|
|
if 0 != dc_imap_is_error(imap, r) || fetch_result.is_null() {
|
|
fetch_result = 0 as *mut clist;
|
|
dc_log_warning(
|
|
(*imap).context,
|
|
0i32,
|
|
b"Error #%i on fetching message #%i from folder \"%s\"; retry=%i.\x00"
|
|
as *const u8 as *const libc::c_char,
|
|
r as libc::c_int,
|
|
server_uid as libc::c_int,
|
|
folder,
|
|
(*imap).should_reconnect as libc::c_int,
|
|
);
|
|
if 0 != (*imap).should_reconnect {
|
|
retry_later = 1i32
|
|
}
|
|
} else {
|
|
/* this is an error that should be recovered; the caller should try over later to fetch the message again (if there is no such message, we simply get an empty result) */
|
|
cur = (*fetch_result).first;
|
|
if cur.is_null() {
|
|
dc_log_warning(
|
|
(*imap).context,
|
|
0i32,
|
|
b"Message #%i does not exist in folder \"%s\".\x00" as *const u8
|
|
as *const libc::c_char,
|
|
server_uid as libc::c_int,
|
|
folder,
|
|
);
|
|
} else {
|
|
/* server response is fine, however, there is no such message, do not try to fetch the message again */
|
|
msg_att = (if !cur.is_null() {
|
|
(*cur).data
|
|
} else {
|
|
0 as *mut libc::c_void
|
|
}) as *mut mailimap_msg_att;
|
|
peek_body(
|
|
msg_att,
|
|
&mut msg_content,
|
|
&mut msg_bytes,
|
|
&mut flags,
|
|
&mut deleted,
|
|
);
|
|
if !(msg_content.is_null()
|
|
|| msg_bytes <= 0i32 as libc::c_ulong
|
|
|| 0 != deleted)
|
|
{
|
|
/* dc_log_warning(imap->context, 0, "Message #%i in folder \"%s\" is empty or deleted.", (int)server_uid, folder); -- this is a quite usual situation, do not print a warning */
|
|
(*imap).receive_imf.expect("non-null function pointer")(
|
|
imap,
|
|
msg_content,
|
|
msg_bytes,
|
|
folder,
|
|
server_uid,
|
|
flags,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if !fetch_result.is_null() {
|
|
mailimap_fetch_list_free(fetch_result);
|
|
fetch_result = 0 as *mut clist
|
|
}
|
|
return if 0 != retry_later { 0i32 } else { 1i32 };
|
|
}
|
|
unsafe fn peek_body(
|
|
mut msg_att: *mut mailimap_msg_att,
|
|
mut p_msg: *mut *mut libc::c_char,
|
|
mut p_msg_bytes: *mut size_t,
|
|
mut flags: *mut uint32_t,
|
|
mut deleted: *mut libc::c_int,
|
|
) {
|
|
if msg_att.is_null() {
|
|
return;
|
|
}
|
|
/* search body & Co. in a list of attributes returned by a FETCH command */
|
|
let mut iter1: *mut clistiter = 0 as *mut clistiter;
|
|
let mut iter2: *mut clistiter = 0 as *mut clistiter;
|
|
iter1 = (*(*msg_att).att_list).first;
|
|
while !iter1.is_null() {
|
|
let mut item: *mut mailimap_msg_att_item = (if !iter1.is_null() {
|
|
(*iter1).data
|
|
} else {
|
|
0 as *mut libc::c_void
|
|
}) as *mut mailimap_msg_att_item;
|
|
if !item.is_null() {
|
|
if (*item).att_type == MAILIMAP_MSG_ATT_ITEM_DYNAMIC as libc::c_int {
|
|
if !(*(*item).att_data.att_dyn).att_list.is_null() {
|
|
iter2 = (*(*(*item).att_data.att_dyn).att_list).first;
|
|
while !iter2.is_null() {
|
|
let mut flag_fetch: *mut mailimap_flag_fetch = (if !iter2.is_null() {
|
|
(*iter2).data
|
|
} else {
|
|
0 as *mut libc::c_void
|
|
})
|
|
as *mut mailimap_flag_fetch;
|
|
if !flag_fetch.is_null()
|
|
&& (*flag_fetch).fl_type == MAILIMAP_FLAG_FETCH_OTHER as libc::c_int
|
|
{
|
|
let mut flag: *mut mailimap_flag = (*flag_fetch).fl_flag;
|
|
if !flag.is_null() {
|
|
if (*flag).fl_type == MAILIMAP_FLAG_SEEN as libc::c_int {
|
|
*flags = (*flags as libc::c_long | 0x1i64) as uint32_t
|
|
} else if (*flag).fl_type == MAILIMAP_FLAG_DELETED as libc::c_int {
|
|
*deleted = 1i32
|
|
}
|
|
}
|
|
}
|
|
iter2 = if !iter2.is_null() {
|
|
(*iter2).next
|
|
} else {
|
|
0 as *mut clistcell_s
|
|
}
|
|
}
|
|
}
|
|
} else if (*item).att_type == MAILIMAP_MSG_ATT_ITEM_STATIC as libc::c_int {
|
|
if (*(*item).att_data.att_static).att_type
|
|
== MAILIMAP_MSG_ATT_BODY_SECTION as libc::c_int
|
|
{
|
|
*p_msg =
|
|
(*(*(*item).att_data.att_static).att_data.att_body_section).sec_body_part;
|
|
*p_msg_bytes =
|
|
(*(*(*item).att_data.att_static).att_data.att_body_section).sec_length
|
|
}
|
|
}
|
|
}
|
|
iter1 = if !iter1.is_null() {
|
|
(*iter1).next
|
|
} else {
|
|
0 as *mut clistcell_s
|
|
}
|
|
}
|
|
}
|
|
unsafe fn get_config_lastseenuid(
|
|
mut imap: *mut dc_imap_t,
|
|
mut folder: *const libc::c_char,
|
|
mut uidvalidity: *mut uint32_t,
|
|
mut lastseenuid: *mut uint32_t,
|
|
) {
|
|
*uidvalidity = 0i32 as uint32_t;
|
|
*lastseenuid = 0i32 as uint32_t;
|
|
let mut key: *mut libc::c_char = dc_mprintf(
|
|
b"imap.mailbox.%s\x00" as *const u8 as *const libc::c_char,
|
|
folder,
|
|
);
|
|
let mut val1: *mut libc::c_char =
|
|
(*imap).get_config.expect("non-null function pointer")(imap, key, 0 as *const libc::c_char);
|
|
let mut val2: *mut libc::c_char = 0 as *mut libc::c_char;
|
|
let mut val3: *mut libc::c_char = 0 as *mut libc::c_char;
|
|
if !val1.is_null() {
|
|
val2 = strchr(val1, ':' as i32);
|
|
if !val2.is_null() {
|
|
*val2 = 0i32 as libc::c_char;
|
|
val2 = val2.offset(1isize);
|
|
val3 = strchr(val2, ':' as i32);
|
|
if !val3.is_null() {
|
|
*val3 = 0i32 as libc::c_char
|
|
}
|
|
*uidvalidity = atol(val1) as uint32_t;
|
|
*lastseenuid = atol(val2) as uint32_t
|
|
}
|
|
}
|
|
free(val1 as *mut libc::c_void);
|
|
free(key as *mut libc::c_void);
|
|
}
|
|
/* ******************************************************************************
|
|
* Handle folders
|
|
******************************************************************************/
|
|
unsafe fn select_folder(mut imap: *mut dc_imap_t, mut folder: *const libc::c_char) -> libc::c_int {
|
|
if imap.is_null() {
|
|
return 0i32;
|
|
}
|
|
if (*imap).etpan.is_null() {
|
|
*(*imap).selected_folder.offset(0isize) = 0i32 as libc::c_char;
|
|
(*imap).selected_folder_needs_expunge = 0i32;
|
|
return 0i32;
|
|
}
|
|
if !folder.is_null()
|
|
&& 0 != *folder.offset(0isize) as libc::c_int
|
|
&& strcmp((*imap).selected_folder, folder) == 0i32
|
|
{
|
|
return 1i32;
|
|
}
|
|
if 0 != (*imap).selected_folder_needs_expunge {
|
|
if 0 != *(*imap).selected_folder.offset(0isize) {
|
|
dc_log_info(
|
|
(*imap).context,
|
|
0i32,
|
|
b"Expunge messages in \"%s\".\x00" as *const u8 as *const libc::c_char,
|
|
(*imap).selected_folder,
|
|
);
|
|
mailimap_close((*imap).etpan);
|
|
}
|
|
(*imap).selected_folder_needs_expunge = 0i32
|
|
}
|
|
if !folder.is_null() {
|
|
let mut r: libc::c_int = mailimap_select((*imap).etpan, folder);
|
|
if 0 != dc_imap_is_error(imap, r) || (*(*imap).etpan).imap_selection_info.is_null() {
|
|
dc_log_info(
|
|
(*imap).context,
|
|
0i32,
|
|
b"Cannot select folder; code=%i, imap_response=%s\x00" as *const u8
|
|
as *const libc::c_char,
|
|
r,
|
|
if !(*(*imap).etpan).imap_response.is_null() {
|
|
(*(*imap).etpan).imap_response
|
|
} else {
|
|
b"<none>\x00" as *const u8 as *const libc::c_char
|
|
},
|
|
);
|
|
*(*imap).selected_folder.offset(0isize) = 0i32 as libc::c_char;
|
|
return 0i32;
|
|
}
|
|
}
|
|
free((*imap).selected_folder as *mut libc::c_void);
|
|
(*imap).selected_folder = dc_strdup(folder);
|
|
return 1i32;
|
|
}
|
|
pub unsafe fn dc_imap_idle(mut imap: *mut dc_imap_t) {
|
|
let mut current_block: u64;
|
|
let mut r: libc::c_int = 0i32;
|
|
let mut r2: libc::c_int = 0i32;
|
|
if !imap.is_null() {
|
|
if 0 != (*imap).can_idle {
|
|
setup_handle_if_needed(imap);
|
|
if (*imap).idle_set_up == 0i32
|
|
&& !(*imap).etpan.is_null()
|
|
&& !(*(*imap).etpan).imap_stream.is_null()
|
|
{
|
|
r = mailstream_setup_idle((*(*imap).etpan).imap_stream);
|
|
if 0 != dc_imap_is_error(imap, r) {
|
|
dc_log_warning(
|
|
(*imap).context,
|
|
0i32,
|
|
b"IMAP-IDLE: Cannot setup.\x00" as *const u8 as *const libc::c_char,
|
|
);
|
|
fake_idle(imap);
|
|
current_block = 14832935472441733737;
|
|
} else {
|
|
(*imap).idle_set_up = 1i32;
|
|
current_block = 17965632435239708295;
|
|
}
|
|
} else {
|
|
current_block = 17965632435239708295;
|
|
}
|
|
match current_block {
|
|
14832935472441733737 => {}
|
|
_ => {
|
|
if 0 == (*imap).idle_set_up || 0 == select_folder(imap, (*imap).watch_folder) {
|
|
dc_log_warning(
|
|
(*imap).context,
|
|
0i32,
|
|
b"IMAP-IDLE not setup.\x00" as *const u8 as *const libc::c_char,
|
|
);
|
|
fake_idle(imap);
|
|
} else {
|
|
r = mailimap_idle((*imap).etpan);
|
|
if 0 != dc_imap_is_error(imap, r) {
|
|
dc_log_warning(
|
|
(*imap).context,
|
|
0i32,
|
|
b"IMAP-IDLE: Cannot start.\x00" as *const u8 as *const libc::c_char,
|
|
);
|
|
fake_idle(imap);
|
|
} else {
|
|
r = mailstream_wait_idle((*(*imap).etpan).imap_stream, 23i32 * 60i32);
|
|
r2 = mailimap_idle_done((*imap).etpan);
|
|
if r == MAILSTREAM_IDLE_ERROR as libc::c_int
|
|
|| r == MAILSTREAM_IDLE_CANCELLED as libc::c_int
|
|
{
|
|
dc_log_info((*imap).context, 0i32,
|
|
b"IMAP-IDLE wait cancelled, r=%i, r2=%i; we\'ll reconnect soon.\x00"
|
|
as *const u8 as
|
|
*const libc::c_char, r, r2);
|
|
(*imap).should_reconnect = 1i32
|
|
} else if r == MAILSTREAM_IDLE_INTERRUPTED as libc::c_int {
|
|
dc_log_info(
|
|
(*imap).context,
|
|
0i32,
|
|
b"IMAP-IDLE interrupted.\x00" as *const u8
|
|
as *const libc::c_char,
|
|
);
|
|
} else if r == MAILSTREAM_IDLE_HASDATA as libc::c_int {
|
|
dc_log_info(
|
|
(*imap).context,
|
|
0i32,
|
|
b"IMAP-IDLE has data.\x00" as *const u8 as *const libc::c_char,
|
|
);
|
|
} else if r == MAILSTREAM_IDLE_TIMEOUT as libc::c_int {
|
|
dc_log_info(
|
|
(*imap).context,
|
|
0i32,
|
|
b"IMAP-IDLE timeout.\x00" as *const u8 as *const libc::c_char,
|
|
);
|
|
} else {
|
|
dc_log_warning(
|
|
(*imap).context,
|
|
0i32,
|
|
b"IMAP-IDLE returns unknown value r=%i, r2=%i.\x00" as *const u8
|
|
as *const libc::c_char,
|
|
r,
|
|
r2,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
fake_idle(imap);
|
|
}
|
|
};
|
|
}
|
|
unsafe fn fake_idle(mut imap: *mut dc_imap_t) {
|
|
/* Idle using timeouts. This is also needed if we're not yet configured -
|
|
in this case, we're waiting for a configure job */
|
|
let mut fake_idle_start_time: time_t = time(0 as *mut time_t);
|
|
let mut seconds_to_wait: time_t = 0i32 as time_t;
|
|
dc_log_info(
|
|
(*imap).context,
|
|
0i32,
|
|
b"IMAP-fake-IDLEing...\x00" as *const u8 as *const libc::c_char,
|
|
);
|
|
let mut do_fake_idle: libc::c_int = 1i32;
|
|
while 0 != do_fake_idle {
|
|
seconds_to_wait =
|
|
(if time(0 as *mut time_t) - fake_idle_start_time < (3i32 * 60i32) as libc::c_long {
|
|
5i32
|
|
} else {
|
|
60i32
|
|
}) as time_t;
|
|
pthread_mutex_lock(&mut (*imap).watch_condmutex);
|
|
let mut r: libc::c_int = 0i32;
|
|
let mut wakeup_at: timespec = timespec {
|
|
tv_sec: 0,
|
|
tv_nsec: 0,
|
|
};
|
|
memset(
|
|
&mut wakeup_at as *mut timespec as *mut libc::c_void,
|
|
0i32,
|
|
::std::mem::size_of::<timespec>() as libc::c_ulong,
|
|
);
|
|
wakeup_at.tv_sec = time(0 as *mut time_t) + seconds_to_wait;
|
|
while (*imap).watch_condflag == 0i32 && r == 0i32 {
|
|
r = pthread_cond_timedwait(
|
|
&mut (*imap).watch_cond,
|
|
&mut (*imap).watch_condmutex,
|
|
&mut wakeup_at,
|
|
);
|
|
if 0 != (*imap).watch_condflag {
|
|
do_fake_idle = 0i32
|
|
}
|
|
}
|
|
(*imap).watch_condflag = 0i32;
|
|
pthread_mutex_unlock(&mut (*imap).watch_condmutex);
|
|
if do_fake_idle == 0i32 {
|
|
return;
|
|
}
|
|
if 0 != setup_handle_if_needed(imap) {
|
|
if 0 != fetch_from_single_folder(imap, (*imap).watch_folder) {
|
|
do_fake_idle = 0i32
|
|
}
|
|
} else {
|
|
fake_idle_start_time = 0i32 as time_t
|
|
}
|
|
}
|
|
}
|
|
pub unsafe fn dc_imap_interrupt_idle(mut imap: *mut dc_imap_t) {
|
|
if imap.is_null() {
|
|
return;
|
|
}
|
|
if 0 != (*imap).can_idle {
|
|
if !(*imap).etpan.is_null() && !(*(*imap).etpan).imap_stream.is_null() {
|
|
mailstream_interrupt_idle((*(*imap).etpan).imap_stream);
|
|
}
|
|
}
|
|
pthread_mutex_lock(&mut (*imap).watch_condmutex);
|
|
(*imap).watch_condflag = 1i32;
|
|
pthread_cond_signal(&mut (*imap).watch_cond);
|
|
pthread_mutex_unlock(&mut (*imap).watch_condmutex);
|
|
}
|
|
pub unsafe fn dc_imap_move(
|
|
mut imap: *mut dc_imap_t,
|
|
mut folder: *const libc::c_char,
|
|
mut uid: uint32_t,
|
|
mut dest_folder: *const libc::c_char,
|
|
mut dest_uid: *mut uint32_t,
|
|
) -> dc_imap_res {
|
|
let mut current_block: u64;
|
|
let mut res: dc_imap_res = DC_RETRY_LATER;
|
|
let mut r: libc::c_int = 0i32;
|
|
let mut set: *mut mailimap_set = mailimap_set_new_single(uid);
|
|
let mut res_uid: uint32_t = 0i32 as uint32_t;
|
|
let mut res_setsrc: *mut mailimap_set = 0 as *mut mailimap_set;
|
|
let mut res_setdest: *mut mailimap_set = 0 as *mut mailimap_set;
|
|
if imap.is_null()
|
|
|| folder.is_null()
|
|
|| uid == 0i32 as libc::c_uint
|
|
|| dest_folder.is_null()
|
|
|| dest_uid.is_null()
|
|
|| set.is_null()
|
|
{
|
|
res = DC_FAILED
|
|
} else if strcasecmp(folder, dest_folder) == 0i32 {
|
|
dc_log_info(
|
|
(*imap).context,
|
|
0i32,
|
|
b"Skip moving message; message %s/%i is already in %s...\x00" as *const u8
|
|
as *const libc::c_char,
|
|
folder,
|
|
uid as libc::c_int,
|
|
dest_folder,
|
|
);
|
|
res = DC_ALREADY_DONE
|
|
} else {
|
|
dc_log_info(
|
|
(*imap).context,
|
|
0i32,
|
|
b"Moving message %s/%i to %s...\x00" as *const u8 as *const libc::c_char,
|
|
folder,
|
|
uid as libc::c_int,
|
|
dest_folder,
|
|
);
|
|
if select_folder(imap, folder) == 0i32 {
|
|
dc_log_warning(
|
|
(*imap).context,
|
|
0i32,
|
|
b"Cannot select folder %s for moving message.\x00" as *const u8
|
|
as *const libc::c_char,
|
|
folder,
|
|
);
|
|
} else {
|
|
r = mailimap_uidplus_uid_move(
|
|
(*imap).etpan,
|
|
set,
|
|
dest_folder,
|
|
&mut res_uid,
|
|
&mut res_setsrc,
|
|
&mut res_setdest,
|
|
);
|
|
if 0 != dc_imap_is_error(imap, r) {
|
|
if !res_setsrc.is_null() {
|
|
mailimap_set_free(res_setsrc);
|
|
res_setsrc = 0 as *mut mailimap_set
|
|
}
|
|
if !res_setdest.is_null() {
|
|
mailimap_set_free(res_setdest);
|
|
res_setdest = 0 as *mut mailimap_set
|
|
}
|
|
dc_log_info(
|
|
(*imap).context,
|
|
0i32,
|
|
b"Cannot move message, fallback to COPY/DELETE %s/%i to %s...\x00" as *const u8
|
|
as *const libc::c_char,
|
|
folder,
|
|
uid as libc::c_int,
|
|
dest_folder,
|
|
);
|
|
r = mailimap_uidplus_uid_copy(
|
|
(*imap).etpan,
|
|
set,
|
|
dest_folder,
|
|
&mut res_uid,
|
|
&mut res_setsrc,
|
|
&mut res_setdest,
|
|
);
|
|
if 0 != dc_imap_is_error(imap, r) {
|
|
dc_log_info(
|
|
(*imap).context,
|
|
0i32,
|
|
b"Cannot copy message.\x00" as *const u8 as *const libc::c_char,
|
|
);
|
|
current_block = 14415637129417834392;
|
|
} else {
|
|
if add_flag(imap, uid, mailimap_flag_new_deleted()) == 0i32 {
|
|
dc_log_warning(
|
|
(*imap).context,
|
|
0i32,
|
|
b"Cannot mark message as \"Deleted\".\x00" as *const u8
|
|
as *const libc::c_char,
|
|
);
|
|
}
|
|
(*imap).selected_folder_needs_expunge = 1i32;
|
|
current_block = 1538046216550696469;
|
|
}
|
|
} else {
|
|
current_block = 1538046216550696469;
|
|
}
|
|
match current_block {
|
|
14415637129417834392 => {}
|
|
_ => {
|
|
if !res_setdest.is_null() {
|
|
let mut cur: *mut clistiter = (*(*res_setdest).set_list).first;
|
|
if !cur.is_null() {
|
|
let mut item: *mut mailimap_set_item = 0 as *mut mailimap_set_item;
|
|
item = (if !cur.is_null() {
|
|
(*cur).data
|
|
} else {
|
|
0 as *mut libc::c_void
|
|
}) as *mut mailimap_set_item;
|
|
*dest_uid = (*item).set_first
|
|
}
|
|
}
|
|
res = DC_SUCCESS
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if !set.is_null() {
|
|
mailimap_set_free(set);
|
|
set = 0 as *mut mailimap_set
|
|
}
|
|
if !res_setsrc.is_null() {
|
|
mailimap_set_free(res_setsrc);
|
|
res_setsrc = 0 as *mut mailimap_set
|
|
}
|
|
if !res_setdest.is_null() {
|
|
mailimap_set_free(res_setdest);
|
|
res_setdest = 0 as *mut mailimap_set
|
|
}
|
|
return (if res as libc::c_uint == DC_RETRY_LATER as libc::c_int as libc::c_uint {
|
|
(if 0 != (*imap).should_reconnect {
|
|
DC_RETRY_LATER as libc::c_int
|
|
} else {
|
|
DC_FAILED as libc::c_int
|
|
}) as libc::c_uint
|
|
} else {
|
|
res as libc::c_uint
|
|
}) as dc_imap_res;
|
|
}
|
|
unsafe fn add_flag(
|
|
mut imap: *mut dc_imap_t,
|
|
mut server_uid: uint32_t,
|
|
mut flag: *mut mailimap_flag,
|
|
) -> libc::c_int {
|
|
let mut r: libc::c_int = 0i32;
|
|
let mut flag_list: *mut mailimap_flag_list = 0 as *mut mailimap_flag_list;
|
|
let mut store_att_flags: *mut mailimap_store_att_flags = 0 as *mut mailimap_store_att_flags;
|
|
let mut set: *mut mailimap_set = mailimap_set_new_single(server_uid);
|
|
if !(imap.is_null() || (*imap).etpan.is_null()) {
|
|
flag_list = mailimap_flag_list_new_empty();
|
|
mailimap_flag_list_add(flag_list, flag);
|
|
store_att_flags = mailimap_store_att_flags_new_add_flags(flag_list);
|
|
r = mailimap_uid_store((*imap).etpan, set, store_att_flags);
|
|
0 != dc_imap_is_error(imap, r);
|
|
}
|
|
if !store_att_flags.is_null() {
|
|
mailimap_store_att_flags_free(store_att_flags);
|
|
}
|
|
if !set.is_null() {
|
|
mailimap_set_free(set);
|
|
set = 0 as *mut mailimap_set
|
|
}
|
|
return if 0 != (*imap).should_reconnect {
|
|
0i32
|
|
} else {
|
|
1i32
|
|
};
|
|
}
|
|
pub unsafe fn dc_imap_set_seen(
|
|
mut imap: *mut dc_imap_t,
|
|
mut folder: *const libc::c_char,
|
|
mut uid: uint32_t,
|
|
) -> dc_imap_res {
|
|
let mut res: dc_imap_res = DC_RETRY_LATER;
|
|
if imap.is_null() || folder.is_null() || uid == 0i32 as libc::c_uint {
|
|
res = DC_FAILED
|
|
} else if !(*imap).etpan.is_null() {
|
|
dc_log_info(
|
|
(*imap).context,
|
|
0i32,
|
|
b"Marking message %s/%i as seen...\x00" as *const u8 as *const libc::c_char,
|
|
folder,
|
|
uid as libc::c_int,
|
|
);
|
|
if select_folder(imap, folder) == 0i32 {
|
|
dc_log_warning(
|
|
(*imap).context,
|
|
0i32,
|
|
b"Cannot select folder %s for setting SEEN flag.\x00" as *const u8
|
|
as *const libc::c_char,
|
|
folder,
|
|
);
|
|
} else if add_flag(imap, uid, mailimap_flag_new_seen()) == 0i32 {
|
|
dc_log_warning(
|
|
(*imap).context,
|
|
0i32,
|
|
b"Cannot mark message as seen.\x00" as *const u8 as *const libc::c_char,
|
|
);
|
|
} else {
|
|
res = DC_SUCCESS
|
|
}
|
|
}
|
|
return (if res as libc::c_uint == DC_RETRY_LATER as libc::c_int as libc::c_uint {
|
|
(if 0 != (*imap).should_reconnect {
|
|
DC_RETRY_LATER as libc::c_int
|
|
} else {
|
|
DC_FAILED as libc::c_int
|
|
}) as libc::c_uint
|
|
} else {
|
|
res as libc::c_uint
|
|
}) as dc_imap_res;
|
|
}
|
|
pub unsafe fn dc_imap_set_mdnsent(
|
|
mut imap: *mut dc_imap_t,
|
|
mut folder: *const libc::c_char,
|
|
mut uid: uint32_t,
|
|
) -> dc_imap_res {
|
|
let mut can_create_flag: libc::c_int = 0;
|
|
let mut current_block: u64;
|
|
// returns 0=job should be retried later, 1=job done, 2=job done and flag just set
|
|
let mut res: dc_imap_res = DC_RETRY_LATER;
|
|
let mut set: *mut mailimap_set = mailimap_set_new_single(uid);
|
|
let mut fetch_result: *mut clist = 0 as *mut clist;
|
|
if imap.is_null() || folder.is_null() || uid == 0i32 as libc::c_uint || set.is_null() {
|
|
res = DC_FAILED
|
|
} else if !(*imap).etpan.is_null() {
|
|
dc_log_info(
|
|
(*imap).context,
|
|
0i32,
|
|
b"Marking message %s/%i as $MDNSent...\x00" as *const u8 as *const libc::c_char,
|
|
folder,
|
|
uid as libc::c_int,
|
|
);
|
|
if select_folder(imap, folder) == 0i32 {
|
|
dc_log_warning(
|
|
(*imap).context,
|
|
0i32,
|
|
b"Cannot select folder %s for setting $MDNSent flag.\x00" as *const u8
|
|
as *const libc::c_char,
|
|
folder,
|
|
);
|
|
} 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). */
|
|
can_create_flag = 0i32;
|
|
if !(*(*imap).etpan).imap_selection_info.is_null()
|
|
&& !(*(*(*imap).etpan).imap_selection_info)
|
|
.sel_perm_flags
|
|
.is_null()
|
|
{
|
|
let mut iter: *mut clistiter = 0 as *mut clistiter;
|
|
iter = (*(*(*(*imap).etpan).imap_selection_info).sel_perm_flags).first;
|
|
while !iter.is_null() {
|
|
let mut fp: *mut mailimap_flag_perm = (if !iter.is_null() {
|
|
(*iter).data
|
|
} else {
|
|
0 as *mut libc::c_void
|
|
})
|
|
as *mut mailimap_flag_perm;
|
|
if !fp.is_null() {
|
|
if (*fp).fl_type == MAILIMAP_FLAG_PERM_ALL as libc::c_int {
|
|
can_create_flag = 1i32;
|
|
break;
|
|
} else if (*fp).fl_type == MAILIMAP_FLAG_PERM_FLAG as libc::c_int
|
|
&& !(*fp).fl_flag.is_null()
|
|
{
|
|
let mut fl: *mut mailimap_flag = (*fp).fl_flag as *mut mailimap_flag;
|
|
if (*fl).fl_type == MAILIMAP_FLAG_KEYWORD as libc::c_int
|
|
&& !(*fl).fl_data.fl_keyword.is_null()
|
|
&& strcmp(
|
|
(*fl).fl_data.fl_keyword,
|
|
b"$MDNSent\x00" as *const u8 as *const libc::c_char,
|
|
) == 0i32
|
|
{
|
|
can_create_flag = 1i32;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
iter = if !iter.is_null() {
|
|
(*iter).next
|
|
} else {
|
|
0 as *mut clistcell_s
|
|
}
|
|
}
|
|
}
|
|
if 0 != can_create_flag {
|
|
let mut r: libc::c_int = mailimap_uid_fetch(
|
|
(*imap).etpan,
|
|
set,
|
|
(*imap).fetch_type_flags,
|
|
&mut fetch_result,
|
|
);
|
|
if 0 != dc_imap_is_error(imap, r) || fetch_result.is_null() {
|
|
fetch_result = 0 as *mut clist
|
|
} else {
|
|
let mut cur: *mut clistiter = (*fetch_result).first;
|
|
if !cur.is_null() {
|
|
if 0 != peek_flag_keyword(
|
|
(if !cur.is_null() {
|
|
(*cur).data
|
|
} else {
|
|
0 as *mut libc::c_void
|
|
}) as *mut mailimap_msg_att,
|
|
b"$MDNSent\x00" as *const u8 as *const libc::c_char,
|
|
) {
|
|
res = DC_ALREADY_DONE;
|
|
current_block = 14832935472441733737;
|
|
} else if add_flag(
|
|
imap,
|
|
uid,
|
|
mailimap_flag_new_flag_keyword(dc_strdup(
|
|
b"$MDNSent\x00" as *const u8 as *const libc::c_char,
|
|
)),
|
|
) == 0i32
|
|
{
|
|
current_block = 17044610252497760460;
|
|
} else {
|
|
res = DC_SUCCESS;
|
|
current_block = 14832935472441733737;
|
|
}
|
|
match current_block {
|
|
17044610252497760460 => {}
|
|
_ => {
|
|
dc_log_info(
|
|
(*imap).context,
|
|
0i32,
|
|
if res as libc::c_uint
|
|
== DC_SUCCESS as libc::c_int as libc::c_uint
|
|
{
|
|
b"$MDNSent just set and MDN will be sent.\x00" as *const u8
|
|
as *const libc::c_char
|
|
} else {
|
|
b"$MDNSent already set and MDN already sent.\x00"
|
|
as *const u8
|
|
as *const libc::c_char
|
|
},
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
res = DC_SUCCESS;
|
|
dc_log_info(
|
|
(*imap).context,
|
|
0i32,
|
|
b"Cannot store $MDNSent flags, risk sending duplicate MDN.\x00" as *const u8
|
|
as *const libc::c_char,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
if !set.is_null() {
|
|
mailimap_set_free(set);
|
|
set = 0 as *mut mailimap_set
|
|
}
|
|
if !fetch_result.is_null() {
|
|
mailimap_fetch_list_free(fetch_result);
|
|
fetch_result = 0 as *mut clist
|
|
}
|
|
return (if res as libc::c_uint == DC_RETRY_LATER as libc::c_int as libc::c_uint {
|
|
(if 0 != (*imap).should_reconnect {
|
|
DC_RETRY_LATER as libc::c_int
|
|
} else {
|
|
DC_FAILED as libc::c_int
|
|
}) as libc::c_uint
|
|
} else {
|
|
res as libc::c_uint
|
|
}) as dc_imap_res;
|
|
}
|
|
unsafe fn peek_flag_keyword(
|
|
mut msg_att: *mut mailimap_msg_att,
|
|
mut flag_keyword: *const libc::c_char,
|
|
) -> libc::c_int {
|
|
if msg_att.is_null() || (*msg_att).att_list.is_null() || flag_keyword.is_null() {
|
|
return 0i32;
|
|
}
|
|
let mut iter1: *mut clistiter = 0 as *mut clistiter;
|
|
let mut iter2: *mut clistiter = 0 as *mut clistiter;
|
|
iter1 = (*(*msg_att).att_list).first;
|
|
while !iter1.is_null() {
|
|
let mut item: *mut mailimap_msg_att_item = (if !iter1.is_null() {
|
|
(*iter1).data
|
|
} else {
|
|
0 as *mut libc::c_void
|
|
}) as *mut mailimap_msg_att_item;
|
|
if !item.is_null() {
|
|
if (*item).att_type == MAILIMAP_MSG_ATT_ITEM_DYNAMIC as libc::c_int {
|
|
if !(*(*item).att_data.att_dyn).att_list.is_null() {
|
|
iter2 = (*(*(*item).att_data.att_dyn).att_list).first;
|
|
while !iter2.is_null() {
|
|
let mut flag_fetch: *mut mailimap_flag_fetch = (if !iter2.is_null() {
|
|
(*iter2).data
|
|
} else {
|
|
0 as *mut libc::c_void
|
|
})
|
|
as *mut mailimap_flag_fetch;
|
|
if !flag_fetch.is_null()
|
|
&& (*flag_fetch).fl_type == MAILIMAP_FLAG_FETCH_OTHER as libc::c_int
|
|
{
|
|
let mut flag: *mut mailimap_flag = (*flag_fetch).fl_flag;
|
|
if !flag.is_null() {
|
|
if (*flag).fl_type == MAILIMAP_FLAG_KEYWORD as libc::c_int
|
|
&& !(*flag).fl_data.fl_keyword.is_null()
|
|
&& strcmp((*flag).fl_data.fl_keyword, flag_keyword) == 0i32
|
|
{
|
|
return 1i32;
|
|
}
|
|
}
|
|
}
|
|
iter2 = if !iter2.is_null() {
|
|
(*iter2).next
|
|
} else {
|
|
0 as *mut clistcell_s
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
iter1 = if !iter1.is_null() {
|
|
(*iter1).next
|
|
} else {
|
|
0 as *mut clistcell_s
|
|
}
|
|
}
|
|
return 0i32;
|
|
}
|
|
/* only returns 0 on connection problems; we should try later again in this case */
|
|
pub unsafe fn dc_imap_delete_msg(
|
|
mut imap: *mut dc_imap_t,
|
|
mut rfc724_mid: *const libc::c_char,
|
|
mut folder: *const libc::c_char,
|
|
mut server_uid: uint32_t,
|
|
) -> libc::c_int {
|
|
let mut success: libc::c_int = 0i32;
|
|
let mut r: libc::c_int = 0i32;
|
|
let mut fetch_result: *mut clist = 0 as *mut clist;
|
|
let mut is_rfc724_mid: *mut libc::c_char = 0 as *mut libc::c_char;
|
|
let mut new_folder: *mut libc::c_char = 0 as *mut libc::c_char;
|
|
if imap.is_null()
|
|
|| rfc724_mid.is_null()
|
|
|| folder.is_null()
|
|
|| *folder.offset(0isize) as libc::c_int == 0i32
|
|
|| server_uid == 0i32 as libc::c_uint
|
|
{
|
|
success = 1i32
|
|
} else {
|
|
dc_log_info(
|
|
(*imap).context,
|
|
0i32,
|
|
b"Marking message \"%s\", %s/%i for deletion...\x00" as *const u8
|
|
as *const libc::c_char,
|
|
rfc724_mid,
|
|
folder,
|
|
server_uid as libc::c_int,
|
|
);
|
|
if select_folder(imap, folder) == 0i32 {
|
|
dc_log_warning(
|
|
(*imap).context,
|
|
0i32,
|
|
b"Cannot select folder %s for deleting message.\x00" as *const u8
|
|
as *const libc::c_char,
|
|
folder,
|
|
);
|
|
} else {
|
|
let mut cur: *mut clistiter = 0 as *mut clistiter;
|
|
let mut is_quoted_rfc724_mid: *const libc::c_char = 0 as *const libc::c_char;
|
|
let mut set: *mut mailimap_set = mailimap_set_new_single(server_uid);
|
|
r = mailimap_uid_fetch(
|
|
(*imap).etpan,
|
|
set,
|
|
(*imap).fetch_type_prefetch,
|
|
&mut fetch_result,
|
|
);
|
|
if !set.is_null() {
|
|
mailimap_set_free(set);
|
|
set = 0 as *mut mailimap_set
|
|
}
|
|
if 0 != dc_imap_is_error(imap, r) || fetch_result.is_null() {
|
|
fetch_result = 0 as *mut clist;
|
|
dc_log_warning(
|
|
(*imap).context,
|
|
0i32,
|
|
b"Cannot delete on IMAP, %s/%i not found.\x00" as *const u8
|
|
as *const libc::c_char,
|
|
folder,
|
|
server_uid as libc::c_int,
|
|
);
|
|
server_uid = 0i32 as uint32_t
|
|
}
|
|
cur = (*fetch_result).first;
|
|
if cur.is_null()
|
|
|| {
|
|
is_quoted_rfc724_mid = peek_rfc724_mid(
|
|
(if !cur.is_null() {
|
|
(*cur).data
|
|
} else {
|
|
0 as *mut libc::c_void
|
|
}) as *mut mailimap_msg_att,
|
|
);
|
|
is_quoted_rfc724_mid.is_null()
|
|
}
|
|
|| {
|
|
is_rfc724_mid = unquote_rfc724_mid(is_quoted_rfc724_mid);
|
|
is_rfc724_mid.is_null()
|
|
}
|
|
|| strcmp(is_rfc724_mid, rfc724_mid) != 0i32
|
|
{
|
|
dc_log_warning(
|
|
(*imap).context,
|
|
0i32,
|
|
b"Cannot delete on IMAP, %s/%i does not match %s.\x00" as *const u8
|
|
as *const libc::c_char,
|
|
folder,
|
|
server_uid as libc::c_int,
|
|
rfc724_mid,
|
|
);
|
|
server_uid = 0i32 as uint32_t
|
|
}
|
|
/* mark the message for deletion */
|
|
if add_flag(imap, server_uid, mailimap_flag_new_deleted()) == 0i32 {
|
|
dc_log_warning(
|
|
(*imap).context,
|
|
0i32,
|
|
b"Cannot mark message as \"Deleted\".\x00" as *const u8 as *const libc::c_char,
|
|
);
|
|
} else {
|
|
(*imap).selected_folder_needs_expunge = 1i32;
|
|
success = 1i32
|
|
}
|
|
}
|
|
}
|
|
if !fetch_result.is_null() {
|
|
mailimap_fetch_list_free(fetch_result);
|
|
fetch_result = 0 as *mut clist
|
|
}
|
|
free(is_rfc724_mid as *mut libc::c_void);
|
|
free(new_folder as *mut libc::c_void);
|
|
return if 0 != success {
|
|
1i32
|
|
} else {
|
|
dc_imap_is_connected(imap)
|
|
};
|
|
}
|