diff --git a/Cargo.toml b/Cargo.toml index 0db069ab1..30f181907 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,6 +23,7 @@ num-derive = "0.2.5" num-traits = "0.2.6" native-tls = "0.2.3" lettre = "0.9.0" +imap = "1.0.1" [dev-dependencies] tempfile = "3.0.7" @@ -42,4 +43,4 @@ path = "examples/repl/main.rs" [features] default = [] -vendored = ["native-tls/vendored"] \ No newline at end of file +vendored = ["native-tls/vendored"] diff --git a/examples/repl/cmdline.rs b/examples/repl/cmdline.rs index 677dee0f7..b88ab78f2 100644 --- a/examples/repl/cmdline.rs +++ b/examples/repl/cmdline.rs @@ -648,7 +648,7 @@ pub unsafe extern "C" fn dc_cmdline( ) } } else if strcmp(cmd, b"has-backup\x00" as *const u8 as *const libc::c_char) == 0i32 { - ret = dc_imex_has_backup(&context, context.blobdir); + ret = dc_imex_has_backup(&context, context.get_blobdir()); if ret.is_null() { ret = dc_strdup(b"No backup found.\x00" as *const u8 as *const libc::c_char) } @@ -657,7 +657,12 @@ pub unsafe extern "C" fn dc_cmdline( b"export-backup\x00" as *const u8 as *const libc::c_char, ) == 0i32 { - dc_imex(&context, 11i32, context.blobdir, 0 as *const libc::c_char); + dc_imex( + &context, + 11i32, + context.get_blobdir(), + 0 as *const libc::c_char, + ); ret = 2i32 as *mut libc::c_char } else if strcmp( cmd, @@ -673,16 +678,26 @@ pub unsafe extern "C" fn dc_cmdline( ) } } else if strcmp(cmd, b"export-keys\x00" as *const u8 as *const libc::c_char) == 0i32 { - dc_imex(&context, 1i32, context.blobdir, 0 as *const libc::c_char); + dc_imex( + &context, + 1i32, + context.get_blobdir(), + 0 as *const libc::c_char, + ); ret = 2i32 as *mut libc::c_char } else if strcmp(cmd, b"import-keys\x00" as *const u8 as *const libc::c_char) == 0i32 { - dc_imex(&context, 2i32, context.blobdir, 0 as *const libc::c_char); + dc_imex( + &context, + 2i32, + context.get_blobdir(), + 0 as *const libc::c_char, + ); ret = 2i32 as *mut libc::c_char } else if strcmp(cmd, b"export-setup\x00" as *const u8 as *const libc::c_char) == 0i32 { let mut setup_code_0: *mut libc::c_char = dc_create_setup_code(&context); let mut file_name: *mut libc::c_char = dc_mprintf( b"%s/autocrypt-setup-message.html\x00" as *const u8 as *const libc::c_char, - context.blobdir, + context.get_blobdir(), ); let mut file_content: *mut libc::c_char = 0 as *mut libc::c_char; file_content = dc_render_setup_file(&context, setup_code_0); diff --git a/examples/repl/main.rs b/examples/repl/main.rs index 43feb7ced..255e18d20 100644 --- a/examples/repl/main.rs +++ b/examples/repl/main.rs @@ -150,7 +150,7 @@ unsafe extern "C" fn receive_event( let mut ret: *mut libc::c_char = 0 as *mut libc::c_char; let mut tempFile: *mut libc::c_char = dc_get_fine_pathNfilename( context, - (*context).blobdir, + context.get_blobdir(), b"curl.result\x00" as *const u8 as *const libc::c_char, ); let mut cmd: *mut libc::c_char = if event == Event::HTTP_GET { @@ -279,12 +279,16 @@ unsafe fn start_threads( run_threads = 1; let context = c.clone(); let h1 = std::thread::spawn(move || { - let ctx = context.clone(); - let context = ctx.read().unwrap(); while 0 != run_threads { + let ctx = context.clone(); + let context = ctx.read().unwrap(); + + println!("-- imap jobs"); dc_perform_imap_jobs(&context); + println!("-- imap fetch"); dc_perform_imap_fetch(&context); if 0 != run_threads { + println!("-- imap idle"); dc_perform_imap_idle(&context); } } @@ -292,38 +296,38 @@ unsafe fn start_threads( let context = c.clone(); let h2 = std::thread::spawn(move || { - let ctx = context.clone(); - let context = ctx.read().unwrap(); - while 0 != run_threads { - dc_perform_mvbox_fetch(&context); - if 0 != run_threads { - dc_perform_mvbox_idle(&context); - } - } + // let ctx = context.clone(); + // let context = ctx.read().unwrap(); + // while 0 != run_threads { + // dc_perform_mvbox_fetch(&context); + // if 0 != run_threads { + // dc_perform_mvbox_idle(&context); + // } + // } }); let context = c.clone(); let h3 = std::thread::spawn(move || { - let ctx = context.clone(); - let context = ctx.read().unwrap(); - while 0 != run_threads { - dc_perform_sentbox_fetch(&context); - if 0 != run_threads { - dc_perform_sentbox_idle(&context); - } - } + // let ctx = context.clone(); + // let context = ctx.read().unwrap(); + // while 0 != run_threads { + // dc_perform_sentbox_fetch(&context); + // if 0 != run_threads { + // dc_perform_sentbox_idle(&context); + // } + // } }); let context = c.clone(); let h4 = std::thread::spawn(move || { - let ctx = context.clone(); - let context = ctx.read().unwrap(); - while 0 != run_threads { - dc_perform_smtp_jobs(&context); - if 0 != run_threads { - dc_perform_smtp_idle(&context); - } - } + // let ctx = context.clone(); + // let context = ctx.read().unwrap(); + // while 0 != run_threads { + // dc_perform_smtp_jobs(&context); + // if 0 != run_threads { + // dc_perform_smtp_idle(&context); + // } + // } }); (h1, h2, h3, h4) @@ -391,8 +395,6 @@ unsafe fn main_0(mut argc: libc::c_int, mut argv: *mut *mut libc::c_char) -> lib let ctx = Arc::new(RwLock::new(context)); loop { - let ctx = ctx.clone(); - /* read command */ let cmdline = read_cmd(); free(cmd as *mut libc::c_void); @@ -426,10 +428,7 @@ unsafe fn main_0(mut argc: libc::c_int, mut argv: *mut *mut libc::c_char) -> lib dc_perform_imap_jobs(&ctx.read().unwrap()); } } else if strcmp(cmd, b"configure\x00" as *const u8 as *const libc::c_char) == 0i32 { - handles = { - let ctx = ctx.clone(); - Some(start_threads(ctx)) - }; + handles = { Some(start_threads(ctx.clone())) }; dc_configure(&ctx.read().unwrap()); } else if strcmp(cmd, b"oauth2\x00" as *const u8 as *const libc::c_char) == 0i32 { let mut addr: *mut libc::c_char = dc_get_config( @@ -463,10 +462,7 @@ unsafe fn main_0(mut argc: libc::c_int, mut argv: *mut *mut libc::c_char) -> lib } else if strcmp(cmd, b"getqr\x00" as *const u8 as *const libc::c_char) == 0i32 || strcmp(cmd, b"getbadqr\x00" as *const u8 as *const libc::c_char) == 0i32 { - handles = { - let ctx = ctx.clone(); - Some(start_threads(ctx)) - }; + handles = Some(start_threads(ctx.clone())); let mut qrstr: *mut libc::c_char = dc_get_securejoin_qr( &ctx.read().unwrap(), (if !arg1.is_null() { atoi(arg1) } else { 0i32 }) as uint32_t, @@ -491,10 +487,7 @@ unsafe fn main_0(mut argc: libc::c_int, mut argv: *mut *mut libc::c_char) -> lib } free(qrstr as *mut libc::c_void); } else if strcmp(cmd, b"joinqr\x00" as *const u8 as *const libc::c_char) == 0i32 { - handles = { - let ctx = ctx.clone(); - Some(start_threads(ctx)) - }; + handles = Some(start_threads(ctx.clone())); if !arg1.is_null() { dc_join_securejoin(&ctx.read().unwrap(), arg1); } diff --git a/examples/simple.rs b/examples/simple.rs index 646797ddb..9037e2666 100644 --- a/examples/simple.rs +++ b/examples/simple.rs @@ -1,7 +1,7 @@ extern crate deltachat; use std::ffi::{CStr, CString}; -use std::sync::{Arc, RwLock}; +use std::sync::Arc; use tempfile::tempdir; use deltachat::constants::Event; @@ -20,6 +20,10 @@ extern "C" fn cb(_ctx: &dc_context_t, event: Event, data1: usize, data2: usize) println!("[{:?}]", event); match event { + Event::CONFIGURE_PROGRESS => { + println!(" progress: {}", data1); + 0 + } Event::HTTP_GET => { let url = unsafe { CStr::from_ptr(data1 as *const _).to_str().unwrap() }; @@ -56,19 +60,20 @@ fn main() { let info_s = CStr::from_ptr(info); println!("info: {}", info_s.to_str().unwrap()); - let ctx = Arc::new(RwLock::new(ctx)); - + let ctx = Arc::new(ctx); let ctx1 = ctx.clone(); let t1 = std::thread::spawn(move || loop { - dc_perform_imap_jobs(&ctx1.clone().read().unwrap()); - dc_perform_imap_fetch(&ctx1.clone().read().unwrap()); - dc_perform_imap_idle(&ctx1.clone().read().unwrap()); + dc_perform_imap_jobs(&ctx1); + dc_perform_imap_fetch(&ctx1); + std::thread::sleep_ms(1000); + + // dc_perform_imap_idle(&ctx1); }); let ctx1 = ctx.clone(); let t2 = std::thread::spawn(move || loop { - dc_perform_smtp_jobs(&ctx1.clone().read().unwrap()); - dc_perform_smtp_idle(&ctx1.clone().read().unwrap()); + // dc_perform_smtp_jobs(&ctx1); + // dc_perform_smtp_idle(&ctx1); }); let dir = tempdir().unwrap(); @@ -76,42 +81,31 @@ fn main() { println!("opening database {:?}", dbfile); - dc_open( - &mut ctx.clone().write().unwrap(), - dbfile.as_ptr(), - std::ptr::null(), - ); + dc_open(&ctx, dbfile.as_ptr(), std::ptr::null()); println!("configuring"); dc_set_config( - &ctx.clone().read().unwrap(), + &ctx, CString::new("addr").unwrap().as_ptr(), CString::new("d@testrun.org").unwrap().as_ptr(), ); dc_set_config( - &ctx.clone().read().unwrap(), + &ctx, CString::new("mail_pw").unwrap().as_ptr(), CString::new("***").unwrap().as_ptr(), ); - dc_configure(&ctx.clone().read().unwrap()); + dc_configure(&ctx); std::thread::sleep_ms(4000); let email = CString::new("dignifiedquire@gmail.com").unwrap(); println!("sending a message"); - let contact_id = dc_create_contact( - &ctx.clone().read().unwrap(), - std::ptr::null(), - email.as_ptr(), - ); - let chat_id = dc_create_chat_by_contact_id(&ctx.clone().read().unwrap(), contact_id); + let contact_id = dc_create_contact(&ctx, std::ptr::null(), email.as_ptr()); + let chat_id = dc_create_chat_by_contact_id(&ctx, contact_id); let msg_text = CString::new("Hi, here is my first message!").unwrap(); - dc_send_text_msg(&ctx.clone().read().unwrap(), chat_id, msg_text.as_ptr()); + dc_send_text_msg(&ctx, chat_id, msg_text.as_ptr()); println!("fetching chats.."); - let ctx1 = ctx.clone(); - let ctx = ctx1.read().unwrap(); - let chats = dc_get_chatlist(&ctx, 0, std::ptr::null(), 0); for i in 0..dc_chatlist_get_cnt(chats) { @@ -134,7 +128,7 @@ fn main() { } dc_chatlist_unref(chats); - // let msglist = dc_get_chat_msgs(&ctx.clone().read().unwrap(), chat_id, 0, 0); + // let msglist = dc_get_chat_msgs(&ctx, chat_id, 0, 0); // for i in 0..dc_array_get_cnt(msglist) { // let msg_id = dc_array_get_id(msglist, i); // let msg = dc_get_msg(context, msg_id); diff --git a/src/dc_configure.rs b/src/dc_configure.rs index 8dc380343..16176ac5e 100644 --- a/src/dc_configure.rs +++ b/src/dc_configure.rs @@ -136,62 +136,37 @@ pub unsafe fn dc_job_do_DC_JOB_CONFIGURE_IMAP(context: &dc_context_t, _job: *mut b"Cannot configure, database not opened.\x00" as *const u8 as *const libc::c_char, ); } else { - dc_imap_disconnect(context, &mut context.inbox.clone().lock().unwrap()); - dc_imap_disconnect( - context, - &mut context - .sentbox_thread - .clone() - .lock() - .unwrap() - .imap - .clone() - .lock() - .unwrap(), - ); - dc_imap_disconnect( - context, - &mut context - .mvbox_thread - .clone() - .lock() - .unwrap() - .imap - .clone() - .lock() - .unwrap(), - ); - context.smtp.clone().lock().unwrap().disconnect(); - context.inbox.clone().lock().unwrap().log_connect_errors = 1i32; + context.inbox.read().unwrap().disconnect(context); context .sentbox_thread - .clone() .lock() .unwrap() .imap - .clone() .lock() .unwrap() - .log_connect_errors = 1i32; + .disconnect(context); context .mvbox_thread - .clone() .lock() .unwrap() .imap - .clone() .lock() .unwrap() - .log_connect_errors = 1i32; + .disconnect(context); + context.smtp.clone().lock().unwrap().disconnect(); dc_log_info( context, 0i32, b"Configure ...\x00" as *const u8 as *const libc::c_char, ); + + println!("configure lock"); let s_a = context.running_state.clone(); let s = s_a.read().unwrap(); - if s.shall_stop_ongoing { + println!("ongoing: {:?}", s); + if !s.shall_stop_ongoing { + println!("configure progress"); (context.cb)( context, Event::CONFIGURE_PROGRESS, @@ -205,12 +180,15 @@ pub unsafe fn dc_job_do_DC_JOB_CONFIGURE_IMAP(context: &dc_context_t, _job: *mut 0i32 as uintptr_t, ); param = dc_loginparam_new(); + println!("reading params"); dc_loginparam_read( context, param, &context.sql.clone().read().unwrap(), b"\x00" as *const u8 as *const libc::c_char, ); + println!("got params"); + if (*param).addr.is_null() { dc_log_error( context, @@ -846,11 +824,12 @@ pub unsafe fn dc_job_do_DC_JOB_CONFIGURE_IMAP(context: &dc_context_t, _job: *mut r_0, ); free(r_0 as *mut libc::c_void); - if 0 != dc_imap_connect( - context, - &mut context.inbox.clone().lock().unwrap(), - param, - ) { + if 0 != context + .inbox + .read() + .unwrap() + .connect(context, param) + { current_block = 14187386403465544025; break; } @@ -894,11 +873,12 @@ pub unsafe fn dc_job_do_DC_JOB_CONFIGURE_IMAP(context: &dc_context_t, _job: *mut r_1, ); free(r_1 as *mut libc::c_void); - if 0 != dc_imap_connect( - context, - &mut context.inbox.clone().lock().unwrap(), - param, - ) { + if 0 != context + .inbox + .read() + .unwrap() + .connect(context, param) + { current_block = 14187386403465544025; break; } @@ -936,11 +916,12 @@ pub unsafe fn dc_job_do_DC_JOB_CONFIGURE_IMAP(context: &dc_context_t, _job: *mut r_2, ); free(r_2 as *mut libc::c_void); - if 0 != dc_imap_connect( - context, - &mut context.inbox.clone().lock().unwrap(), - param, - ) { + if 0 != context + .inbox + .read() + .unwrap() + .connect(context, param) + { current_block = 14187386403465544025; break; } @@ -1184,15 +1165,14 @@ pub unsafe fn dc_job_do_DC_JOB_CONFIGURE_IMAP(context: &dc_context_t, _job: *mut } else { 0i32 }; - dc_configure_folders( - context, - &mut context - .inbox - .clone() - .lock() - .unwrap(), - flags, - ); + + context + .inbox + .read() + .unwrap() + .configure_folders( + context, flags, + ); if !s.shall_stop_ongoing { (context.cb)(context, Event::CONFIGURE_PROGRESS, @@ -1303,7 +1283,7 @@ pub unsafe fn dc_job_do_DC_JOB_CONFIGURE_IMAP(context: &dc_context_t, _job: *mut } if 0 != imap_connected_here { - dc_imap_disconnect(context, &mut context.inbox.clone().lock().unwrap()); + context.inbox.read().unwrap().disconnect(context); } if 0 != smtp_connected_here { context.smtp.clone().lock().unwrap().disconnect(); @@ -1331,123 +1311,6 @@ pub unsafe fn dc_free_ongoing(context: &dc_context_t) { s.shall_stop_ongoing = true; } -pub unsafe fn dc_configure_folders( - context: &dc_context_t, - imap: &mut dc_imap_t, - flags: libc::c_int, -) { - let mut folder_list: *mut clist = 0 as *mut clist; - let mut iter: *mut clistiter = 0 as *mut clistiter; - let mut mvbox_folder: *mut libc::c_char = 0 as *mut libc::c_char; - let mut sentbox_folder: *mut libc::c_char = 0 as *mut libc::c_char; - let mut fallback_folder: *mut libc::c_char = 0 as *mut libc::c_char; - if !(*imap).etpan.is_null() { - dc_log_info( - context, - 0i32, - b"Configuring IMAP-folders.\x00" as *const u8 as *const libc::c_char, - ); - folder_list = list_folders(context, imap); - fallback_folder = dc_mprintf( - b"INBOX%c%s\x00" as *const u8 as *const libc::c_char, - (*imap).imap_delimiter as libc::c_int, - b"DeltaChat\x00" as *const u8 as *const libc::c_char, - ); - iter = (*folder_list).first; - while !iter.is_null() { - let mut folder: *mut dc_imapfolder_t = (if !iter.is_null() { - (*iter).data - } else { - 0 as *mut libc::c_void - }) as *mut dc_imapfolder_t; - if strcmp( - (*folder).name_utf8, - b"DeltaChat\x00" as *const u8 as *const libc::c_char, - ) == 0i32 - || strcmp((*folder).name_utf8, fallback_folder) == 0i32 - { - if mvbox_folder.is_null() { - mvbox_folder = dc_strdup((*folder).name_to_select) - } - } - if (*folder).meaning == 1i32 { - if sentbox_folder.is_null() { - sentbox_folder = dc_strdup((*folder).name_to_select) - } - } - iter = if !iter.is_null() { - (*iter).next - } else { - 0 as *mut clistcell_s - } - } - if mvbox_folder.is_null() && 0 != flags & 0x1i32 { - dc_log_info( - context, - 0i32, - b"Creating MVBOX-folder \"%s\"...\x00" as *const u8 as *const libc::c_char, - b"DeltaChat\x00" as *const u8 as *const libc::c_char, - ); - let mut r: libc::c_int = mailimap_create( - (*imap).etpan, - b"DeltaChat\x00" as *const u8 as *const libc::c_char, - ); - if 0 != dc_imap_is_error(context, imap, r) { - dc_log_warning( - context, - 0i32, - b"Cannot create MVBOX-folder, using trying INBOX subfolder.\x00" as *const u8 - as *const libc::c_char, - ); - r = mailimap_create((*imap).etpan, fallback_folder); - if 0 != dc_imap_is_error(context, imap, r) { - dc_log_warning( - context, - 0i32, - b"Cannot create MVBOX-folder.\x00" as *const u8 as *const libc::c_char, - ); - } else { - mvbox_folder = dc_strdup(fallback_folder); - dc_log_info( - context, - 0i32, - b"MVBOX-folder created as INBOX subfolder.\x00" as *const u8 - as *const libc::c_char, - ); - } - } else { - mvbox_folder = dc_strdup(b"DeltaChat\x00" as *const u8 as *const libc::c_char); - dc_log_info( - context, - 0i32, - b"MVBOX-folder created.\x00" as *const u8 as *const libc::c_char, - ); - } - mailimap_subscribe((*imap).etpan, mvbox_folder); - } - dc_sqlite3_set_config_int( - context, - &context.sql.clone().read().unwrap(), - b"folders_configured\x00" as *const u8 as *const libc::c_char, - 3i32, - ); - dc_sqlite3_set_config( - context, - &context.sql.clone().read().unwrap(), - b"configured_mvbox_folder\x00" as *const u8 as *const libc::c_char, - mvbox_folder, - ); - dc_sqlite3_set_config( - context, - &context.sql.clone().read().unwrap(), - b"configured_sentbox_folder\x00" as *const u8 as *const libc::c_char, - sentbox_folder, - ); - } - free_folders(folder_list); - free(mvbox_folder as *mut libc::c_void); - free(fallback_folder as *mut libc::c_void); -} unsafe fn free_folders(mut folders: *mut clist) { if !folders.is_null() { let mut iter1: *mut clistiter = 0 as *mut clistiter; @@ -1470,173 +1333,7 @@ unsafe fn free_folders(mut folders: *mut clist) { clist_free(folders); }; } -unsafe fn list_folders(context: &dc_context_t, imap: &mut dc_imap_t) -> *mut clist { - let mut imap_list: *mut clist = 0 as *mut clist; - let mut iter1: *mut clistiter = 0 as *mut clistiter; - let mut ret_list: *mut clist = clist_new(); - let mut r: libc::c_int = 0i32; - let mut xlist_works: libc::c_int = 0i32; - if !(*imap).etpan.is_null() { - if 0 != (*imap).has_xlist { - r = mailimap_xlist( - (*imap).etpan, - b"\x00" as *const u8 as *const libc::c_char, - b"*\x00" as *const u8 as *const libc::c_char, - &mut imap_list, - ) - } else { - r = mailimap_list( - (*imap).etpan, - b"\x00" as *const u8 as *const libc::c_char, - b"*\x00" as *const u8 as *const libc::c_char, - &mut imap_list, - ) - } - if 0 != dc_imap_is_error(context, imap, r) || imap_list.is_null() { - imap_list = 0 as *mut clist; - dc_log_warning( - context, - 0i32, - b"Cannot get folder list.\x00" as *const u8 as *const libc::c_char, - ); - } else if (*imap_list).count <= 0i32 { - dc_log_warning( - context, - 0i32, - b"Folder list is empty.\x00" as *const u8 as *const libc::c_char, - ); - } else { - (*imap).imap_delimiter = '.' as i32 as libc::c_char; - iter1 = (*imap_list).first; - while !iter1.is_null() { - let mut imap_folder: *mut mailimap_mailbox_list = (if !iter1.is_null() { - (*iter1).data - } else { - 0 as *mut libc::c_void - }) - as *mut mailimap_mailbox_list; - if 0 != (*imap_folder).mb_delimiter { - (*imap).imap_delimiter = (*imap_folder).mb_delimiter - } - let mut ret_folder: *mut dc_imapfolder_t = - calloc(1, ::std::mem::size_of::()) as *mut dc_imapfolder_t; - if strcasecmp( - (*imap_folder).mb_name, - b"INBOX\x00" as *const u8 as *const libc::c_char, - ) == 0i32 - { - (*ret_folder).name_to_select = - dc_strdup(b"INBOX\x00" as *const u8 as *const libc::c_char) - } else { - (*ret_folder).name_to_select = dc_strdup((*imap_folder).mb_name) - } - (*ret_folder).name_utf8 = dc_decode_modified_utf7((*imap_folder).mb_name, 0i32); - (*ret_folder).meaning = get_folder_meaning((*imap_folder).mb_flag); - if (*ret_folder).meaning == 2i32 || (*ret_folder).meaning == 1i32 { - xlist_works = 1i32 - } - clist_insert_after(ret_list, (*ret_list).last, ret_folder as *mut libc::c_void); - iter1 = if !iter1.is_null() { - (*iter1).next - } else { - 0 as *mut clistcell_s - } - } - if 0 == xlist_works { - iter1 = (*ret_list).first; - while !iter1.is_null() { - let mut ret_folder_0: *mut dc_imapfolder_t = (if !iter1.is_null() { - (*iter1).data - } else { - 0 as *mut libc::c_void - }) - as *mut dc_imapfolder_t; - (*ret_folder_0).meaning = get_folder_meaning_by_name((*ret_folder_0).name_utf8); - iter1 = if !iter1.is_null() { - (*iter1).next - } else { - 0 as *mut clistcell_s - } - } - } - } - } - if !imap_list.is_null() { - mailimap_list_result_free(imap_list); - } - return ret_list; -} -unsafe fn get_folder_meaning_by_name(mut folder_name: *const libc::c_char) -> libc::c_int { - // try to get the folder meaning by the name of the folder. - // only used if the server does not support XLIST. - let mut ret_meaning: libc::c_int = 0i32; - // TODO: lots languages missing - maybe there is a list somewhere on other MUAs? - // however, if we fail to find out the sent-folder, - // only watching this folder is not working. at least, this is no show stopper. - // CAVE: if possible, take care not to add a name here that is "sent" in one language - // but sth. different in others - a hard job. - static mut sent_names: *const libc::c_char = - b",sent,sent objects,gesendet,\x00" as *const u8 as *const libc::c_char; - let mut lower: *mut libc::c_char = - dc_mprintf(b",%s,\x00" as *const u8 as *const libc::c_char, folder_name); - dc_strlower_in_place(lower); - if !strstr(sent_names, lower).is_null() { - ret_meaning = 1i32 - } - free(lower as *mut libc::c_void); - return ret_meaning; -} -unsafe fn get_folder_meaning(mut flags: *mut mailimap_mbx_list_flags) -> libc::c_int { - let mut ret_meaning: libc::c_int = 0i32; - if !flags.is_null() { - let mut iter2: *mut clistiter = 0 as *mut clistiter; - iter2 = (*(*flags).mbf_oflags).first; - while !iter2.is_null() { - let mut oflag: *mut mailimap_mbx_list_oflag = (if !iter2.is_null() { - (*iter2).data - } else { - 0 as *mut libc::c_void - }) - as *mut mailimap_mbx_list_oflag; - match (*oflag).of_type { - 2 => { - if strcasecmp( - (*oflag).of_flag_ext, - b"spam\x00" as *const u8 as *const libc::c_char, - ) == 0i32 - || strcasecmp( - (*oflag).of_flag_ext, - b"trash\x00" as *const u8 as *const libc::c_char, - ) == 0i32 - || strcasecmp( - (*oflag).of_flag_ext, - b"drafts\x00" as *const u8 as *const libc::c_char, - ) == 0i32 - || strcasecmp( - (*oflag).of_flag_ext, - b"junk\x00" as *const u8 as *const libc::c_char, - ) == 0i32 - { - ret_meaning = 2i32 - } else if strcasecmp( - (*oflag).of_flag_ext, - b"sent\x00" as *const u8 as *const libc::c_char, - ) == 0i32 - { - ret_meaning = 1i32 - } - } - _ => {} - } - iter2 = if !iter2.is_null() { - (*iter2).next - } else { - 0 as *mut clistcell_s - } - } - } - return ret_meaning; -} + unsafe fn moz_autoconfigure( mut context: &dc_context_t, mut url: *const libc::c_char, @@ -1714,6 +1411,7 @@ unsafe fn moz_autoconfigure( free(moz_ac.in_emaillocalpart as *mut libc::c_void); return moz_ac.out; } + unsafe fn moz_autoconfigure_text_cb( userdata: *mut libc::c_void, text: *const libc::c_char, @@ -2096,11 +1794,12 @@ pub unsafe fn dc_alloc_ongoing(context: &dc_context_t) -> libc::c_int { pub unsafe fn dc_connect_to_configured_imap( context: &dc_context_t, - imap: &mut dc_imap_t, + imap: &dc_imap_t, ) -> libc::c_int { + println!("connect to imap"); let mut ret_connected: libc::c_int = 0i32; let mut param: *mut dc_loginparam_t = dc_loginparam_new(); - if 0 != dc_imap_is_connected(imap) { + if imap.is_connected() { ret_connected = 1i32 } else if dc_sqlite3_get_config_int( context, @@ -2122,10 +1821,11 @@ pub unsafe fn dc_connect_to_configured_imap( b"configured_\x00" as *const u8 as *const libc::c_char, ); /*the trailing underscore is correct*/ - if !(0 == dc_imap_connect(context, imap, param)) { + if !(0 == imap.connect(context, param)) { ret_connected = 2i32 } } dc_loginparam_unref(param); - return ret_connected; + println!("done, {}", ret_connected); + ret_connected } diff --git a/src/dc_context.rs b/src/dc_context.rs index 5a6441ed6..5ba0ee5e4 100644 --- a/src/dc_context.rs +++ b/src/dc_context.rs @@ -26,10 +26,10 @@ use crate::x::*; #[repr(C)] pub struct dc_context_t { pub userdata: *mut libc::c_void, - pub dbfile: *mut libc::c_char, - pub blobdir: *mut libc::c_char, + pub dbfile: Arc>, + pub blobdir: Arc>, pub sql: Arc>, - pub inbox: Arc>, + pub inbox: Arc>, pub perform_inbox_jobs_needed: Arc>, pub probe_imap_network: Arc>, pub sentbox_thread: Arc>, @@ -54,6 +54,24 @@ pub struct RunningState { pub shall_stop_ongoing: bool, } +impl dc_context_t { + pub fn has_dbfile(&self) -> bool { + !self.get_dbfile().is_null() + } + + pub fn has_blobdir(&self) -> bool { + !self.get_blobdir().is_null() + } + + pub fn get_dbfile(&self) -> *const libc::c_char { + *self.dbfile.clone().read().unwrap() + } + + pub fn get_blobdir(&self) -> *const libc::c_char { + *self.blobdir.clone().read().unwrap() + } +} + impl Default for RunningState { fn default() -> Self { RunningState { @@ -112,9 +130,9 @@ pub fn dc_context_new( os_name: *const libc::c_char, ) -> dc_context_t { dc_context_t { - blobdir: std::ptr::null_mut(), - dbfile: std::ptr::null_mut(), - inbox: Arc::new(Mutex::new(unsafe { + blobdir: Arc::new(RwLock::new(std::ptr::null_mut())), + dbfile: Arc::new(RwLock::new(std::ptr::null_mut())), + inbox: Arc::new(RwLock::new({ dc_imap_new( Some(cb_get_config), Some(cb_set_config), @@ -261,32 +279,6 @@ pub unsafe fn dc_context_unref(context: &mut dc_context_t) { if 0 != dc_is_open(context) { dc_close(context); } - dc_imap_unref(context, &mut context.inbox.clone().lock().unwrap()); - dc_imap_unref( - context, - &mut context - .sentbox_thread - .clone() - .lock() - .unwrap() - .imap - .clone() - .lock() - .unwrap(), - ); - dc_imap_unref( - context, - &mut context - .mvbox_thread - .clone() - .lock() - .unwrap() - .imap - .clone() - .lock() - .unwrap(), - ); - dc_sqlite3_unref(context, &mut context.sql.clone().write().unwrap()); dc_jobthread_exit(&mut context.sentbox_thread.clone().lock().unwrap()); @@ -295,41 +287,36 @@ pub unsafe fn dc_context_unref(context: &mut dc_context_t) { free(context.os_name as *mut libc::c_void); } -pub unsafe fn dc_close(context: &mut dc_context_t) { - dc_imap_disconnect(context, &mut context.inbox.clone().lock().unwrap()); - dc_imap_disconnect( - context, - &mut context - .sentbox_thread - .clone() - .lock() - .unwrap() - .imap - .clone() - .lock() - .unwrap(), - ); - dc_imap_disconnect( - context, - &mut context - .mvbox_thread - .clone() - .lock() - .unwrap() - .imap - .clone() - .lock() - .unwrap(), - ); +pub unsafe fn dc_close(context: &dc_context_t) { + context.inbox.read().unwrap().disconnect(context); + context + .sentbox_thread + .lock() + .unwrap() + .imap + .lock() + .unwrap() + .disconnect(context); + context + .mvbox_thread + .lock() + .unwrap() + .imap + .lock() + .unwrap() + .disconnect(context); + context.smtp.clone().lock().unwrap().disconnect(); if 0 != dc_sqlite3_is_open(&context.sql.clone().read().unwrap()) { dc_sqlite3_close(context, &mut context.sql.clone().write().unwrap()); } - free(context.dbfile as *mut libc::c_void); - context.dbfile = 0 as *mut libc::c_char; - free(context.blobdir as *mut libc::c_void); - context.blobdir = 0 as *mut libc::c_char; + let mut dbfile = context.dbfile.write().unwrap(); + free(*dbfile as *mut libc::c_void); + *dbfile = 0 as *mut libc::c_char; + let mut blobdir = context.blobdir.write().unwrap(); + free(*blobdir as *mut libc::c_void); + *blobdir = 0 as *mut libc::c_char; } pub unsafe fn dc_is_open(context: &dc_context_t) -> libc::c_int { @@ -341,7 +328,7 @@ pub unsafe fn dc_get_userdata(context: &mut dc_context_t) -> *mut libc::c_void { } pub unsafe fn dc_open( - context: &mut dc_context_t, + context: &dc_context_t, dbfile: *const libc::c_char, blobdir: *const libc::c_char, ) -> libc::c_int { @@ -350,24 +337,18 @@ pub unsafe fn dc_open( return 0; } if !dbfile.is_null() { - context.dbfile = dc_strdup(dbfile); + *context.dbfile.write().unwrap() = dc_strdup(dbfile); if !blobdir.is_null() && 0 != *blobdir.offset(0isize) as libc::c_int { - context.blobdir = dc_strdup(blobdir); - dc_ensure_no_slash(context.blobdir); + let dir = dc_strdup(blobdir); + dc_ensure_no_slash(dir); + *context.blobdir.write().unwrap() = dir; } else { - context.blobdir = - dc_mprintf(b"%s-blobs\x00" as *const u8 as *const libc::c_char, dbfile); - dc_create_folder(context, context.blobdir); + let dir = dc_mprintf(b"%s-blobs\x00" as *const u8 as *const libc::c_char, dbfile); + dc_create_folder(context, dir); + *context.blobdir.write().unwrap() = dir; } // Create/open sqlite database, this may already use the blobdir - if !(0 - == dc_sqlite3_open( - context, - &mut context.sql.clone().write().unwrap(), - dbfile, - 0i32, - )) - { + if !(0 == dc_sqlite3_open(context, &mut context.sql.write().unwrap(), dbfile, 0i32)) { success = 1i32 } } @@ -378,7 +359,7 @@ pub unsafe fn dc_open( } pub unsafe fn dc_get_blobdir(context: &dc_context_t) -> *mut libc::c_char { - dc_strdup((*context).blobdir) + dc_strdup(*context.blobdir.clone().read().unwrap()) } pub unsafe fn dc_set_config( @@ -836,14 +817,14 @@ pub unsafe fn dc_get_info(context: &dc_context_t) -> *mut libc::c_char { real_msgs, deaddrop_msgs, contacts, - if !context.dbfile.is_null() { - context.dbfile + if context.has_dbfile() { + context.get_dbfile() } else { unset }, dbversion, - if !context.blobdir.is_null() { - context.blobdir + if context.has_blobdir() { + context.get_blobdir() } else { unset }, diff --git a/src/dc_imap.rs b/src/dc_imap.rs index c225e22f7..f078b2c95 100644 --- a/src/dc_imap.rs +++ b/src/dc_imap.rs @@ -1,29 +1,120 @@ -use std::sync::{Arc, Condvar, Mutex}; +use std::ffi::CStr; +use std::sync::{Arc, Condvar, Mutex, RwLock}; use std::time::{Duration, SystemTime}; use libc; -use crate::constants::Event; +use crate::constants::*; use crate::dc_context::dc_context_t; use crate::dc_log::*; use crate::dc_loginparam::*; -use crate::dc_oauth2::*; -use crate::dc_stock::*; -use crate::dc_strbuilder::*; use crate::dc_tools::*; use crate::types::*; use crate::x::*; #[repr(C)] pub struct dc_imap_t { - pub addr: *mut libc::c_char, - pub imap_server: *mut libc::c_char, - pub imap_port: i32, - pub imap_user: *mut libc::c_char, - pub imap_pw: *mut libc::c_char, - pub server_flags: i32, + pub config: Arc>, + pub watch: Arc<(Mutex, Condvar)>, + + 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, + + session: Arc>>, +} + +#[derive(Debug)] +pub enum FolderMeaning { + Unknown, + SentObjects, + Other, +} + +pub enum Client { + Secure(imap::Client>), + Insecure(imap::Client), +} + +pub enum Session { + Secure(imap::Session>), + Insecure(imap::Session), +} + +impl From>> for Client { + fn from(client: imap::Client>) -> Self { + Client::Secure(client) + } +} + +impl From> for Client { + fn from(client: imap::Client) -> Self { + Client::Insecure(client) + } +} + +impl From>> for Session { + fn from(session: imap::Session>) -> Self { + Session::Secure(session) + } +} + +impl From> for Session { + fn from(session: imap::Session) -> Self { + Session::Insecure(session) + } +} + +impl Client { + pub fn login, P: AsRef>( + self, + username: U, + password: P, + ) -> Result { + match self { + Client::Secure(i) => i + .login(username, password) + .map(Into::into) + .map_err(|(e, c)| (e, c.into())), + Client::Insecure(i) => i + .login(username, password) + .map(Into::into) + .map_err(|(e, c)| (e, c.into())), + } + } +} + +impl Session { + pub fn capabilities( + &mut self, + ) -> imap::error::Result> { + match self { + Session::Secure(i) => i.capabilities(), + Session::Insecure(i) => i.capabilities(), + } + } + + pub fn list( + &mut self, + reference_name: Option<&str>, + mailbox_pattern: Option<&str>, + ) -> imap::error::Result>> { + match self { + Session::Secure(i) => i.list(reference_name, mailbox_pattern), + Session::Insecure(i) => i.list(reference_name, mailbox_pattern), + } + } +} + +pub struct ImapConfig { + pub addr: Option, + pub imap_server: Option, + pub imap_port: Option, + pub imap_user: Option, + pub imap_pw: Option, + pub server_flags: Option, pub connected: i32, - pub etpan: *mut mailimap, pub idle_set_up: i32, pub selected_folder: *mut libc::c_char, pub selected_folder_needs_expunge: i32, @@ -32,1817 +123,1945 @@ pub struct dc_imap_t { pub has_xlist: i32, pub imap_delimiter: libc::c_char, pub watch_folder: *mut libc::c_char, - pub watch: Arc<(Mutex, Condvar)>, 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 log_connect_errors: i32, pub skip_log_capabilities: i32, } -pub unsafe fn dc_imap_new( +impl Default for ImapConfig { + fn default() -> Self { + let mut cfg = ImapConfig { + addr: None, + imap_server: None, + imap_port: None, + imap_user: None, + imap_pw: None, + server_flags: None, + connected: 0, + idle_set_up: 0, + selected_folder: unsafe { calloc(1, 1) as *mut libc::c_char }, + selected_folder_needs_expunge: 0, + should_reconnect: 0, + can_idle: 0, + has_xlist: 0, + imap_delimiter: 0 as libc::c_char, + watch_folder: unsafe { calloc(1, 1) as *mut libc::c_char }, + fetch_type_prefetch: unsafe { mailimap_fetch_type_new_fetch_att_list_empty() }, + fetch_type_body: unsafe { mailimap_fetch_type_new_fetch_att_list_empty() }, + fetch_type_flags: unsafe { mailimap_fetch_type_new_fetch_att_list_empty() }, + log_connect_errors: 1, + skip_log_capabilities: 0, + }; + + unsafe { + mailimap_fetch_type_new_fetch_att_list_add( + cfg.fetch_type_prefetch, + mailimap_fetch_att_new_uid(), + ); + mailimap_fetch_type_new_fetch_att_list_add( + cfg.fetch_type_prefetch, + mailimap_fetch_att_new_envelope(), + ); + + mailimap_fetch_type_new_fetch_att_list_add( + cfg.fetch_type_body, + mailimap_fetch_att_new_flags(), + ); + mailimap_fetch_type_new_fetch_att_list_add( + cfg.fetch_type_body, + mailimap_fetch_att_new_body_peek_section(mailimap_section_new( + 0 as *mut mailimap_section_spec, + )), + ); + mailimap_fetch_type_new_fetch_att_list_add( + cfg.fetch_type_flags, + mailimap_fetch_att_new_flags(), + ); + } + cfg + } +} + +pub fn dc_imap_new( get_config: dc_get_config_t, set_config: dc_set_config_t, precheck_imf: dc_precheck_imf_t, receive_imf: dc_receive_imf_t, ) -> dc_imap_t { - let mut imap = dc_imap_t { - addr: std::ptr::null_mut(), - imap_server: std::ptr::null_mut(), - imap_port: 0, - imap_user: std::ptr::null_mut(), - imap_pw: std::ptr::null_mut(), - server_flags: 0, - connected: 0, - etpan: std::ptr::null_mut(), - idle_set_up: 0, - selected_folder: calloc(1, 1) as *mut libc::c_char, - selected_folder_needs_expunge: 0, - should_reconnect: 0, - can_idle: 0, - has_xlist: 0, - imap_delimiter: 0 as libc::c_char, - watch_folder: calloc(1, 1) as *mut libc::c_char, - watch: Arc::new((Mutex::new(false), Condvar::new())), - fetch_type_prefetch: mailimap_fetch_type_new_fetch_att_list_empty(), - fetch_type_body: mailimap_fetch_type_new_fetch_att_list_empty(), - fetch_type_flags: mailimap_fetch_type_new_fetch_att_list_empty(), - get_config, - set_config, - precheck_imf, - receive_imf, - log_connect_errors: 1, - skip_log_capabilities: 0, - }; - 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(), - ); - - 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, - )), - ); - mailimap_fetch_type_new_fetch_att_list_add( - imap.fetch_type_flags, - mailimap_fetch_att_new_flags(), - ); - - imap + dc_imap_t::new(get_config, set_config, precheck_imf, receive_imf) } -pub unsafe fn dc_imap_unref(context: &dc_context_t, imap: &mut dc_imap_t) { - dc_imap_disconnect(context, imap); - 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); - } -} - -pub unsafe fn dc_imap_disconnect(context: &dc_context_t, imap: &mut dc_imap_t) { - if 0 != imap.connected { - unsetup_handle(context, imap); - free_connect_param(imap); - imap.connected = 0 - }; -} - -/* ****************************************************************************** - * Connect/Disconnect - ******************************************************************************/ - -unsafe fn free_connect_param(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) = 0 as libc::c_char; - *imap.selected_folder.offset(0isize) = 0 as libc::c_char; - imap.imap_port = 0; - imap.can_idle = 0; - imap.has_xlist = 0; -} - -unsafe fn unsetup_handle(context: &dc_context_t, imap: &mut dc_imap_t) { - if !imap.etpan.is_null() { - if 0 != imap.idle_set_up { - mailstream_unsetup_idle((*imap.etpan).imap_stream); - imap.idle_set_up = 0 - } - 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( - context, - 0, - b"IMAP disconnected.\x00" as *const u8 as *const libc::c_char, - ); - } - *imap.selected_folder.offset(0isize) = 0 as libc::c_char; -} - -pub unsafe fn dc_imap_connect( - context: &dc_context_t, - imap: &mut dc_imap_t, - lp: *const dc_loginparam_t, -) -> libc::c_int { - let mut success: libc::c_int = 0; - if lp.is_null() - || (*lp).mail_server.is_null() - || (*lp).mail_user.is_null() - || (*lp).mail_pw.is_null() - { - return 0; - } - if 0 != imap.connected { - success = 1 - } 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(context, imap)) { - imap.can_idle = mailimap_has_idle(imap.etpan); - imap.has_xlist = mailimap_has_xlist(imap.etpan); - imap.can_idle = 0; - 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 = 1; - 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, 0); - 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( - context, - 0, - 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 = 1; - success = 1 - } - } - if success == 0 { - unsetup_handle(context, imap); - free_connect_param(imap); - } - success -} - -unsafe fn setup_handle_if_needed(context: &dc_context_t, imap: &mut dc_imap_t) -> libc::c_int { - let mut current_block: u64; - let mut r: libc::c_int = 0; - let mut success: libc::c_int = 0; - if !(imap.imap_server.is_null()) { - if 0 != imap.should_reconnect { - unsetup_handle(context, imap); - } - if !imap.etpan.is_null() { - success = 1 - } else { - imap.etpan = mailimap_new(0 as size_t, None); - mailimap_set_timeout(imap.etpan, 10 as time_t); - if 0 != imap.server_flags & (0x100 | 0x400) { - r = mailimap_socket_connect( - imap.etpan, - imap.imap_server, - imap.imap_port as uint16_t, - ); - if 0 != dc_imap_is_error(context, imap, r) { - dc_log_event_seq( - context, - Event::ERROR_NETWORK, - &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 & 0x100 { - r = mailimap_socket_starttls(imap.etpan); - if 0 != dc_imap_is_error(context, imap, r) { - dc_log_event_seq(context, Event::ERROR_NETWORK, - &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( - context, - 0, - 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( - context, - 0, - 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(context, imap, r) { - dc_log_event_seq( - context, - Event::ERROR_NETWORK, - &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( - context, - 0, - 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 & 0x2 { - dc_log_info( - context, - 0, - 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(context, imap.addr, imap.imap_pw, 0); - r = mailimap_oauth2_authenticate(imap.etpan, imap.imap_user, access_token); - if 0 != dc_imap_is_error(context, imap, r) { - free(access_token as *mut libc::c_void); - access_token = - dc_get_oauth2_access_token(context, imap.addr, imap.imap_pw, 0x1); - 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(context, imap, r) { - let mut msg: *mut libc::c_char = get_error_msg( - context, - imap, - b"Cannot login\x00" as *const u8 as *const libc::c_char, - r, - ); - dc_log_event_seq( - context, - Event::ERROR_NETWORK, - &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( - context, - Event::IMAP_CONNECTED, - 0, - b"IMAP-login as %s ok.\x00" as *const u8 as *const libc::c_char, - imap.imap_user, - ); - success = 1 - } - } - } - } - } - if success == 0 { - unsetup_handle(context, imap); - } - imap.should_reconnect = 0; - success -} - -unsafe fn get_error_msg( - context: &dc_context_t, - imap: &mut dc_imap_t, - what_failed: *const libc::c_char, - 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, 1000); - match code { - 28 => { - stock = dc_stock_str_repl_string(context, 60, 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(context, 61, 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; - msg.buf -} - -pub unsafe fn dc_imap_is_error( - context: &dc_context_t, - imap: &mut dc_imap_t, - 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 0; - } - if code == MAILIMAP_ERROR_STREAM as libc::c_int || code == MAILIMAP_ERROR_PARSE as libc::c_int { - dc_log_info( - context, - 0, - b"IMAP stream lost; we\'ll reconnect soon.\x00" as *const u8 as *const libc::c_char, - ); - imap.should_reconnect = 1 - } - 1 -} - -pub unsafe extern "C" fn dc_imap_set_watch_folder( - imap: &mut dc_imap_t, - watch_folder: *const libc::c_char, -) { - if 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(imap: &dc_imap_t) -> libc::c_int { - (0 != imap.connected) as libc::c_int -} - -pub unsafe fn dc_imap_fetch(context: &dc_context_t, imap: &mut dc_imap_t) -> libc::c_int { - let mut success = 0; - if 0 != imap.connected { - setup_handle_if_needed(context, imap); - while fetch_from_single_folder(context, imap, imap.watch_folder) > 0 {} - success = 1; - } - success -} - -unsafe fn fetch_from_single_folder( - context: &dc_context_t, - imap: &mut dc_imap_t, - 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 = 0 as uint32_t; - let mut lastseenuid: uint32_t = 0 as uint32_t; - let mut new_lastseenuid: uint32_t = 0 as uint32_t; - let mut fetch_result: *mut clist = 0 as *mut clist; - let mut read_cnt: size_t = 0 as size_t; - let mut read_errors: size_t = 0 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.etpan.is_null() { - dc_log_info( - context, - 0, - b"Cannot fetch from \"%s\" - not connected.\x00" as *const u8 as *const libc::c_char, - folder, - ); - } else if select_folder(context, imap, folder) == 0 { - dc_log_warning( - context, - 0, - b"Cannot select folder %s for fetching.\x00" as *const u8 as *const libc::c_char, - folder, - ); - } else { - get_config_lastseenuid(context, 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 <= 0 as libc::c_uint { - dc_log_error( - context, - 0, - 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 <= 0 as libc::c_uint { - dc_log_info( - context, - 0, - b"Folder \"%s\" is empty.\x00" as *const u8 as *const libc::c_char, - folder, - ); - if (*(*imap.etpan).imap_selection_info).sel_exists == 0 as libc::c_uint { - set_config_lastseenuid( - context, - imap, - folder, - (*(*imap.etpan).imap_selection_info).sel_uidvalidity, - 0 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( - context, - 0, - b"EXISTS is missing for folder \"%s\", using fallback.\x00" as *const u8 - as *const libc::c_char, - folder, - ); - set = mailimap_set_new_single(0 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(context, imap, r) || fetch_result.is_null() { - fetch_result = 0 as *mut clist; - dc_log_info( - context, - 0, - 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( - context, - 0, - 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 <= 0 as libc::c_uint { - dc_log_error( - context, - 0, - b"Cannot get largest UID for folder \"%s\"\x00" as *const u8 - as *const libc::c_char, - folder, - ); - current_block = 17288151659885296046; - } else { - if uidvalidity > 0 as libc::c_uint - && lastseenuid > 1 as libc::c_uint - { - lastseenuid = (lastseenuid as libc::c_uint) - .wrapping_sub(1 as libc::c_uint) - as uint32_t - as uint32_t - } - uidvalidity = - (*(*imap.etpan).imap_selection_info).sel_uidvalidity; - set_config_lastseenuid( - context, - imap, - folder, - uidvalidity, - lastseenuid, - ); - dc_log_info( - context, - 0, - 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(1 as libc::c_uint), - 0 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(context, imap, r) || fetch_result.is_null() { - fetch_result = 0 as *mut clist; - if r == MAILIMAP_ERROR_PROTOCOL as libc::c_int { - dc_log_info( - context, - 0, - 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( - context, - 0, - 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")( - context, rfc724_mid, folder, cur_uid, - ) { - if fetch_single_msg(context, imap, folder, cur_uid) == 0 { - dc_log_info(context, 0, - 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( - context, - 0, - 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 > 0 as libc::c_uint { - set_config_lastseenuid(context, imap, folder, uidvalidity, new_lastseenuid); - } - } - } +impl dc_imap_t { + pub fn new( + get_config: dc_get_config_t, + set_config: dc_set_config_t, + precheck_imf: dc_precheck_imf_t, + receive_imf: dc_receive_imf_t, + ) -> Self { + dc_imap_t { + session: Arc::new(Mutex::new(None)), + config: Arc::new(RwLock::new(ImapConfig::default())), + watch: Arc::new((Mutex::new(false), Condvar::new())), + get_config, + set_config, + precheck_imf, + receive_imf, } } - /* done */ - if 0 != read_errors { - dc_log_warning( - context, - 0, - 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( - 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 + pub fn is_connected(&self) -> bool { + self.session.lock().unwrap().is_some() } - read_cnt as libc::c_int -} - -unsafe fn set_config_lastseenuid( - context: &dc_context_t, - imap: &mut dc_imap_t, - folder: *const libc::c_char, - uidvalidity: uint32_t, - 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")(context, key, val); - free(val as *mut libc::c_void); - free(key as *mut libc::c_void); -} - -unsafe fn peek_rfc724_mid(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(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 > 2 { - if *out.offset(0isize) as libc::c_int == '<' as i32 { - *out.offset(0isize) = ' ' as i32 as libc::c_char - } - if *out.offset((out_len - 1) as isize) as libc::c_int == '>' as i32 { - *out.offset((out_len - 1) as isize) = ' ' as i32 as libc::c_char - } - dc_trim(out); - } - out -} - -/* ****************************************************************************** - * Fetch Messages - ******************************************************************************/ - -unsafe fn peek_uid(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 - } - } - 0 as uint32_t -} - -unsafe fn fetch_single_msg( - context: &dc_context_t, - imap: &mut dc_imap_t, - folder: *const libc::c_char, - 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 = 0 as size_t; - let mut r: libc::c_int = 0; - let mut retry_later: libc::c_int = 0; - let mut deleted: libc::c_int = 0; - let mut flags: uint32_t = 0 as uint32_t; - let mut fetch_result: *mut clist = 0 as *mut clist; - let mut cur: *mut clistiter = 0 as *mut clistiter; - 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(context, imap, r) || fetch_result.is_null() { - fetch_result = 0 as *mut clist; - dc_log_warning( - context, - 0, - 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 = 1 - } - } 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( - context, - 0, - 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 <= 0 || 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")( - context, - msg_content, - msg_bytes, - folder, - server_uid, - flags, - ); - } - } - } + pub fn should_reconnect(&self) -> bool { + unimplemented!(); } - if !fetch_result.is_null() { - mailimap_fetch_list_free(fetch_result); - fetch_result = 0 as *mut clist - } - if 0 != retry_later { - 0 - } else { - 1 - } -} - -unsafe fn peek_body( - msg_att: *mut mailimap_msg_att, - p_msg: *mut *mut libc::c_char, - p_msg_bytes: *mut size_t, - flags: *mut uint32_t, - 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 | 0x1) as uint32_t - } else if (*flag).fl_type == MAILIMAP_FLAG_DELETED as libc::c_int { - *deleted = 1 - } - } - } - 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( - context: &dc_context_t, - imap: &mut dc_imap_t, - folder: *const libc::c_char, - uidvalidity: *mut uint32_t, - lastseenuid: *mut uint32_t, -) { - *uidvalidity = 0 as uint32_t; - *lastseenuid = 0 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")(context, 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 = 0 as libc::c_char; - val2 = val2.offset(1isize); - val3 = strchr(val2, ':' as i32); - if !val3.is_null() { - *val3 = 0 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( - context: &dc_context_t, - imap: &mut dc_imap_t, - folder: *const libc::c_char, -) -> libc::c_int { - if imap.etpan.is_null() { - *imap.selected_folder.offset(0isize) = 0 as libc::c_char; - imap.selected_folder_needs_expunge = 0; - return 0; - } - if !folder.is_null() - && 0 != *folder.offset(0isize) as libc::c_int - && strcmp(imap.selected_folder, folder) == 0 - { - return 1; - } - if 0 != imap.selected_folder_needs_expunge { - if 0 != *imap.selected_folder.offset(0isize) { - dc_log_info( - context, - 0, - 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 = 0 - } - if !folder.is_null() { - let mut r: libc::c_int = mailimap_select(imap.etpan, folder); - if 0 != dc_imap_is_error(context, imap, r) || (*imap.etpan).imap_selection_info.is_null() { - dc_log_info( - context, - 0, - 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"\x00" as *const u8 as *const libc::c_char - }, - ); - *imap.selected_folder.offset(0isize) = 0 as libc::c_char; + pub fn connect(&self, context: &dc_context_t, lp: *const dc_loginparam_t) -> libc::c_int { + if lp.is_null() { return 0; } - } - free(imap.selected_folder as *mut libc::c_void); - imap.selected_folder = dc_strdup(folder); - 1 -} - -pub unsafe fn dc_imap_idle(context: &dc_context_t, imap: &mut dc_imap_t) { - let mut current_block: u64; - let mut r: libc::c_int = 0; - let mut r2: libc::c_int = 0; - if 0 != imap.can_idle { - setup_handle_if_needed(context, imap); - if imap.idle_set_up == 0 && !imap.etpan.is_null() && !(*imap.etpan).imap_stream.is_null() { - r = mailstream_setup_idle((*imap.etpan).imap_stream); - if 0 != dc_imap_is_error(context, imap, r) { - dc_log_warning( - context, - 0, - b"IMAP-IDLE: Cannot setup.\x00" as *const u8 as *const libc::c_char, - ); - fake_idle(context, imap); - current_block = 14832935472441733737; - } else { - imap.idle_set_up = 1; - current_block = 17965632435239708295; - } - } else { - current_block = 17965632435239708295; + let lp = unsafe { *lp }; + if lp.mail_server.is_null() || lp.mail_user.is_null() || lp.mail_pw.is_null() { + return 0; } - match current_block { - 14832935472441733737 => {} - _ => { - if 0 == imap.idle_set_up || 0 == select_folder(context, imap, imap.watch_folder) { - dc_log_warning( - context, - 0, - b"IMAP-IDLE not setup.\x00" as *const u8 as *const libc::c_char, - ); - fake_idle(context, imap); - } else { - r = mailimap_idle(imap.etpan); - if 0 != dc_imap_is_error(context, imap, r) { - dc_log_warning( - context, - 0, - b"IMAP-IDLE: Cannot start.\x00" as *const u8 as *const libc::c_char, - ); - fake_idle(context, imap); + + if self.is_connected() { + return 1; + } + + let addr = to_str(lp.addr); + let imap_server = to_str(lp.mail_server); + let imap_port = lp.mail_port as u16; + let imap_user = to_str(lp.mail_user); + let imap_pw = to_str(lp.mail_pw); + let server_flags = lp.server_flags as usize; + + let connection_res: imap::error::Result = + if (server_flags & (DC_LP_IMAP_SOCKET_STARTTLS | DC_LP_IMAP_SOCKET_PLAIN)) != 0 { + println!("insecure"); + imap::connect_insecure((imap_server, imap_port)).and_then(|client| { + if (server_flags & DC_LP_IMAP_SOCKET_STARTTLS) != 0 { + let tls = native_tls::TlsConnector::builder().build().unwrap(); + client.secure(imap_server, &tls).map(Into::into) } else { - r = mailstream_wait_idle((*imap.etpan).imap_stream, 23 * 60); - r2 = mailimap_idle_done(imap.etpan); - if r == MAILSTREAM_IDLE_ERROR as libc::c_int - || r == MAILSTREAM_IDLE_CANCELLED as libc::c_int - { + Ok(client.into()) + } + }) + } else { + println!("secure: {}:{} - {}", imap_server, imap_port, imap_server); + let tls = native_tls::TlsConnector::builder() + // FIXME: unfortunately this is needed to make things work on macos + testrun.org + .danger_accept_invalid_hostnames(true) + .build() + .unwrap(); + imap::connect((imap_server, imap_port), imap_server, &tls).map(Into::into) + }; + + match connection_res { + Ok(client) => { + println!("imap: connected - {} - {}", imap_user, imap_pw); + // TODO: handle oauth2 + match client.login(imap_user, imap_pw) { + Ok(mut session) => { + println!("imap: logged in"); + // TODO: error handling + let caps = session.capabilities().unwrap(); + let can_idle = caps.has("IDLE"); + let has_xlist = caps.has("XLIST"); + + let caps_list = caps.iter().fold(String::new(), |mut s, c| { + s += " "; + s += c; + s + }); + let caps_list_c = std::ffi::CString::new(caps_list).unwrap(); + + unsafe { dc_log_info( context, 0, - 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 = 1 - } else if r == MAILSTREAM_IDLE_INTERRUPTED as libc::c_int { - dc_log_info( + b"IMAP-capabilities:%s\x00" as *const u8 as *const libc::c_char, + caps_list_c.as_ptr(), + ) + }; + + let mut config = self.config.write().unwrap(); + config.can_idle = can_idle as i32; + config.has_xlist = has_xlist as i32; + + *self.session.lock().unwrap() = Some(session); + + 1 + } + Err((err, _)) => { + eprintln!("failed to login: {:?}", err); + + unsafe { + dc_log_event_seq( context, - 0, - 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( - context, - 0, - 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( - context, - 0, - b"IMAP-IDLE timeout.\x00" as *const u8 as *const libc::c_char, - ); - } else { - dc_log_warning( - context, - 0, - b"IMAP-IDLE returns unknown value r=%i, r2=%i.\x00" as *const u8 - as *const libc::c_char, - r, - r2, - ); - } + Event::ERROR_NETWORK, + &mut 0 as *mut i32, + b"Cannot login\x00" as *const u8 as *const libc::c_char, + ) + }; + + 0 } } } + Err(err) => { + eprintln!("failed to connect: {:?}", err); + unsafe { + dc_log_event_seq( + context, + Event::ERROR_NETWORK, + &mut 0 as *mut i32, + b"Could not connect to IMAP-server %s:%i.\x00" as *const u8 + as *const libc::c_char, + imap_server, + imap_port as usize as libc::c_int, + ) + }; + + 0 + } } - } else { - fake_idle(context, imap); } -} -unsafe fn fake_idle(context: &dc_context_t, 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 = SystemTime::now(); + pub fn disconnect(&self, context: &dc_context_t) { + // unimplemented!(); + println!("disconnecting"); + } - dc_log_info( - context, - 0, - b"IMAP-fake-IDLEing...\x00" as *const u8 as *const libc::c_char, - ); - let mut do_fake_idle: libc::c_int = 1; - while 0 != do_fake_idle { - let seconds_to_wait = if fake_idle_start_time.elapsed().unwrap() < Duration::new(3 * 60, 0) - { - Duration::new(5, 0) - } else { - Duration::new(60, 0) - }; + // unsafe fn get_error_msg( + // context: &dc_context_t, + // imap: &dc_imap_t, + // what_failed: *const libc::c_char, + // 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, 1000); + // match code { + // 28 => { + // stock = dc_stock_str_repl_string(context, 60, 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( + // context, + // 61, + // 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; + // msg.buf + // } - let &(ref lock, ref cvar) = &*imap.watch.clone(); + // pub unsafe fn dc_imap_is_error( + // context: &dc_context_t, + // imap: &dc_imap_t, + // 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 0; + // } + // if code == MAILIMAP_ERROR_STREAM as libc::c_int + // || code == MAILIMAP_ERROR_PARSE as libc::c_int + // { + // dc_log_info( + // context, + // 0, + // b"IMAP stream lost; we\'ll reconnect soon.\x00" as *const u8 as *const libc::c_char, + // ); + // imap.should_reconnect = 1 + // } + // 1 + // } - let mut watch = lock.lock().unwrap(); + pub fn set_watch_folder(&self, watch_folder: *const libc::c_char) { + unimplemented!() + } - loop { - let res = cvar.wait_timeout(watch, seconds_to_wait).unwrap(); - watch = res.0; - if *watch { - do_fake_idle = 0; - } - if *watch || res.1.timed_out() { - break; - } - } + // pub unsafe extern "C" fn dc_imap_set_watch_folder( + // imap: &dc_imap_t, + // watch_folder: *const libc::c_char, + // ) { + // if watch_folder.is_null() { + // return; + // } + // free(imap.watch_folder as *mut libc::c_void); + // imap.watch_folder = dc_strdup(watch_folder); + // } - *watch = false; - if do_fake_idle == 0 { + // pub unsafe fn dc_imap_is_connected(imap: &dc_imap_t) -> libc::c_int { + // (0 != imap.connected) as libc::c_int + // } + + pub fn fetch(&self, context: &dc_context_t) -> libc::c_int { + unimplemented!() + } + + // pub unsafe fn dc_imap_fetch(context: &dc_context_t, imap: &dc_imap_t) -> libc::c_int { + // println!("dc_imap_fetch"); + // let mut success = 0; + // if 0 != imap.connected { + // setup_handle_if_needed(context, imap); + // let mut cnt = fetch_from_single_folder(context, imap, imap.watch_folder); + // while cnt > 0 { + // println!(" -- fetching {}", cnt); + // cnt = fetch_from_single_folder(context, imap, imap.watch_folder); + // } + // success = 1; + // } + + // println!("dc_imap_fetch done {}", success); + // success + // } + + pub fn fetch_from_single_folder( + &self, + context: &dc_context_t, + folder: *const libc::c_char, + ) -> libc::c_int { + unimplemented!() + } + + // unsafe fn fetch_from_single_folder( + // context: &dc_context_t, + // imap: &dc_imap_t, + // 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 = 0 as uint32_t; + // let mut lastseenuid: uint32_t = 0 as uint32_t; + // let mut new_lastseenuid: uint32_t = 0 as uint32_t; + // let mut fetch_result: *mut clist = 0 as *mut clist; + // let mut read_cnt: size_t = 0 as size_t; + // let mut read_errors: size_t = 0 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.etpan.is_null() { + // dc_log_info( + // context, + // 0, + // b"Cannot fetch from \"%s\" - not connected.\x00" as *const u8 + // as *const libc::c_char, + // folder, + // ); + // } else if select_folder(context, imap, folder) == 0 { + // dc_log_warning( + // context, + // 0, + // b"Cannot select folder %s for fetching.\x00" as *const u8 as *const libc::c_char, + // folder, + // ); + // } else { + // println!( + // "fetching from folder {}", + // std::ffi::CStr::from_ptr(folder).to_str().unwrap() + // ); + // get_config_lastseenuid(context, 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 <= 0 as libc::c_uint { + // dc_log_error( + // context, + // 0, + // 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 <= 0 as libc::c_uint { + // dc_log_info( + // context, + // 0, + // b"Folder \"%s\" is empty.\x00" as *const u8 as *const libc::c_char, + // folder, + // ); + // if (*(*imap.etpan).imap_selection_info).sel_exists == 0 as libc::c_uint + // { + // set_config_lastseenuid( + // context, + // imap, + // folder, + // (*(*imap.etpan).imap_selection_info).sel_uidvalidity, + // 0 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( + // context, + // 0, + // b"EXISTS is missing for folder \"%s\", using fallback.\x00" as *const u8 + // as *const libc::c_char, + // folder, + // ); + // set = mailimap_set_new_single(0 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(context, imap, r) || fetch_result.is_null() { + // fetch_result = 0 as *mut clist; + // dc_log_info( + // context, + // 0, + // 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( + // context, + // 0, + // 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 <= 0 as libc::c_uint { + // dc_log_error( + // context, + // 0, + // b"Cannot get largest UID for folder \"%s\"\x00" + // as *const u8 + // as *const libc::c_char, + // folder, + // ); + // current_block = 17288151659885296046; + // } else { + // if uidvalidity > 0 as libc::c_uint + // && lastseenuid > 1 as libc::c_uint + // { + // lastseenuid = (lastseenuid as libc::c_uint) + // .wrapping_sub(1 as libc::c_uint) + // as uint32_t + // as uint32_t + // } + // uidvalidity = + // (*(*imap.etpan).imap_selection_info).sel_uidvalidity; + // set_config_lastseenuid( + // context, + // imap, + // folder, + // uidvalidity, + // lastseenuid, + // ); + // dc_log_info( + // context, + // 0, + // 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(1 as libc::c_uint), + // 0 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(context, imap, r) || fetch_result.is_null() { + // fetch_result = 0 as *mut clist; + // if r == MAILIMAP_ERROR_PROTOCOL as libc::c_int { + // dc_log_info( + // context, + // 0, + // 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( + // context, + // 0, + // 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")( + // context, rfc724_mid, folder, cur_uid, + // ) { + // if fetch_single_msg(context, imap, folder, cur_uid) == 0 { + // dc_log_info(context, 0, + // 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( + // context, + // 0, + // 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 > 0 as libc::c_uint { + // set_config_lastseenuid( + // context, + // imap, + // folder, + // uidvalidity, + // new_lastseenuid, + // ); + // } + // } + // } + // } + // } + + // /* done */ + // if 0 != read_errors { + // dc_log_warning( + // context, + // 0, + // 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( + // 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 + // } + + // read_cnt as libc::c_int + // } + + // unsafe fn set_config_lastseenuid( + // context: &dc_context_t, + // imap: &dc_imap_t, + // folder: *const libc::c_char, + // uidvalidity: uint32_t, + // 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")(context, key, val); + // free(val as *mut libc::c_void); + // free(key as *mut libc::c_void); + // } + + // unsafe fn peek_rfc724_mid(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(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 > 2 { + // if *out.offset(0isize) as libc::c_int == '<' as i32 { + // *out.offset(0isize) = ' ' as i32 as libc::c_char + // } + // if *out.offset((out_len - 1) as isize) as libc::c_int == '>' as i32 { + // *out.offset((out_len - 1) as isize) = ' ' as i32 as libc::c_char + // } + // dc_trim(out); + // } + // out + // } + + // /* ****************************************************************************** + // * Fetch Messages + // ******************************************************************************/ + // unsafe fn peek_uid(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 + // } + // } + // 0 as uint32_t + // } + + // unsafe fn fetch_single_msg( + // context: &dc_context_t, + // imap: &dc_imap_t, + // folder: *const libc::c_char, + // 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 = 0 as size_t; + // let mut r: libc::c_int = 0; + // let mut retry_later: libc::c_int = 0; + // let mut deleted: libc::c_int = 0; + // let mut flags: uint32_t = 0 as uint32_t; + // let mut fetch_result: *mut clist = 0 as *mut clist; + // let mut cur: *mut clistiter = 0 as *mut clistiter; + // 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(context, imap, r) || fetch_result.is_null() { + // fetch_result = 0 as *mut clist; + // dc_log_warning( + // context, + // 0, + // 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 = 1 + // } + // } 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( + // context, + // 0, + // 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 <= 0 || 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")( + // context, + // 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 + // } + // if 0 != retry_later { + // 0 + // } else { + // 1 + // } + // } + + // unsafe fn peek_body( + // msg_att: *mut mailimap_msg_att, + // p_msg: *mut *mut libc::c_char, + // p_msg_bytes: *mut size_t, + // flags: *mut uint32_t, + // 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 | 0x1) as uint32_t + // } else if (*flag).fl_type + // == MAILIMAP_FLAG_DELETED as libc::c_int + // { + // *deleted = 1 + // } + // } + // } + // 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( + // context: &dc_context_t, + // imap: &dc_imap_t, + // folder: *const libc::c_char, + // uidvalidity: *mut uint32_t, + // lastseenuid: *mut uint32_t, + // ) { + // *uidvalidity = 0 as uint32_t; + // *lastseenuid = 0 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")( + // context, + // 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 = 0 as libc::c_char; + // val2 = val2.offset(1isize); + // val3 = strchr(val2, ':' as i32); + // if !val3.is_null() { + // *val3 = 0 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( + // context: &dc_context_t, + // imap: &dc_imap_t, + // folder: *const libc::c_char, + // ) -> libc::c_int { + // if imap.etpan.is_null() { + // *imap.selected_folder.offset(0isize) = 0 as libc::c_char; + // imap.selected_folder_needs_expunge = 0; + // return 0; + // } + // if !folder.is_null() + // && 0 != *folder.offset(0isize) as libc::c_int + // && strcmp(imap.selected_folder, folder) == 0 + // { + // return 1; + // } + // if 0 != imap.selected_folder_needs_expunge { + // if 0 != *imap.selected_folder.offset(0isize) { + // dc_log_info( + // context, + // 0, + // 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 = 0 + // } + // if !folder.is_null() { + // let mut r: libc::c_int = mailimap_select(imap.etpan, folder); + // if 0 != dc_imap_is_error(context, imap, r) + // || (*imap.etpan).imap_selection_info.is_null() + // { + // dc_log_info( + // context, + // 0, + // 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"\x00" as *const u8 as *const libc::c_char + // }, + // ); + // *imap.selected_folder.offset(0isize) = 0 as libc::c_char; + // return 0; + // } + // } + // free(imap.selected_folder as *mut libc::c_void); + // imap.selected_folder = dc_strdup(folder); + // 1 + // } + + pub fn idle(&self, context: &dc_context_t) { + // unimplemented!() + println!("starting to idle"); + } + // let mut current_block: u64; + // let mut r: libc::c_int = 0; + // let mut r2: libc::c_int = 0; + // if 0 != imap.can_idle { + // setup_handle_if_needed(context, imap); + // if imap.idle_set_up == 0 + // && !imap.etpan.is_null() + // && !(*imap.etpan).imap_stream.is_null() + // { + // r = mailstream_setup_idle((*imap.etpan).imap_stream); + // if 0 != dc_imap_is_error(context, imap, r) { + // dc_log_warning( + // context, + // 0, + // b"IMAP-IDLE: Cannot setup.\x00" as *const u8 as *const libc::c_char, + // ); + // fake_idle(context, imap); + // current_block = 14832935472441733737; + // } else { + // imap.idle_set_up = 1; + // current_block = 17965632435239708295; + // } + // } else { + // current_block = 17965632435239708295; + // } + // match current_block { + // 14832935472441733737 => {} + // _ => { + // if 0 == imap.idle_set_up || 0 == select_folder(context, imap, imap.watch_folder) + // { + // dc_log_warning( + // context, + // 0, + // b"IMAP-IDLE not setup.\x00" as *const u8 as *const libc::c_char, + // ); + // fake_idle(context, imap); + // } else { + // r = mailimap_idle(imap.etpan); + // if 0 != dc_imap_is_error(context, imap, r) { + // dc_log_warning( + // context, + // 0, + // b"IMAP-IDLE: Cannot start.\x00" as *const u8 as *const libc::c_char, + // ); + // fake_idle(context, imap); + // } else { + // r = mailstream_wait_idle((*imap.etpan).imap_stream, 23 * 60); + // 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( + // context, + // 0, + // 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 = 1 + // } else if r == MAILSTREAM_IDLE_INTERRUPTED as libc::c_int { + // dc_log_info( + // context, + // 0, + // 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( + // context, + // 0, + // 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( + // context, + // 0, + // b"IMAP-IDLE timeout.\x00" as *const u8 as *const libc::c_char, + // ); + // } else { + // dc_log_warning( + // context, + // 0, + // b"IMAP-IDLE returns unknown value r=%i, r2=%i.\x00" as *const u8 + // as *const libc::c_char, + // r, + // r2, + // ); + // } + // } + // } + // } + // } + // } else { + // fake_idle(context, imap); + // } + // } + + // unsafe fn fake_idle(context: &dc_context_t, imap: &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 = SystemTime::now(); + + // dc_log_info( + // context, + // 0, + // b"IMAP-fake-IDLEing...\x00" as *const u8 as *const libc::c_char, + // ); + // let mut do_fake_idle: libc::c_int = 1; + // while 0 != do_fake_idle { + // let seconds_to_wait = + // if fake_idle_start_time.elapsed().unwrap() < Duration::new(3 * 60, 0) { + // Duration::new(5, 0) + // } else { + // Duration::new(60, 0) + // }; + + // let &(ref lock, ref cvar) = &*imap.watch.clone(); + + // let mut watch = lock.lock().unwrap(); + + // loop { + // let res = cvar.wait_timeout(watch, seconds_to_wait).unwrap(); + // watch = res.0; + // if *watch { + // do_fake_idle = 0; + // } + // if *watch || res.1.timed_out() { + // break; + // } + // } + + // *watch = false; + // if do_fake_idle == 0 { + // return; + // } + // if 0 != setup_handle_if_needed(context, imap) { + // if 0 != fetch_from_single_folder(context, imap, imap.watch_folder) { + // do_fake_idle = 0; + // } + // } + // } + // } + + pub fn interrupt_idle(&self) { + // unimplemented!(); + println!("interrupt idle"); + } + + // println!("imap interrupt"); + // if 0 != imap.can_idle { + // if !imap.etpan.is_null() && !(*imap.etpan).imap_stream.is_null() { + // mailstream_interrupt_idle((*imap.etpan).imap_stream); + // } + // } + + // println!("waiting for lock"); + // let &(ref lock, ref cvar) = &*imap.watch.clone(); + // let mut watch = lock.lock().unwrap(); + + // *watch = true; + // println!("notify"); + // cvar.notify_one(); + // } + + pub fn mv( + &self, + context: &dc_context_t, + folder: *const libc::c_char, + uid: uint32_t, + dest_folder: *const libc::c_char, + dest_uid: *mut uint32_t, + ) -> dc_imap_res { + unimplemented!() + } + // let mut current_block: u64; + // let mut res: dc_imap_res = DC_RETRY_LATER; + // let mut r: libc::c_int = 0; + // let mut set: *mut mailimap_set = mailimap_set_new_single(uid); + // let mut res_uid: uint32_t = 0 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 folder.is_null() + // || uid == 0 as libc::c_uint + // || dest_folder.is_null() + // || dest_uid.is_null() + // || set.is_null() + // { + // res = DC_FAILED + // } else if strcasecmp(folder, dest_folder) == 0 { + // dc_log_info( + // context, + // 0, + // 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( + // context, + // 0, + // 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(context, imap, folder) == 0 { + // dc_log_warning( + // context, + // 0, + // 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(context, 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( + // context, + // 0, + // 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(context, imap, r) { + // dc_log_info( + // context, + // 0, + // 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()) == 0 { + // dc_log_warning( + // context, + // 0, + // b"Cannot mark message as \"Deleted\".\x00" as *const u8 + // as *const libc::c_char, + // ); + // } + // imap.selected_folder_needs_expunge = 1; + // 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( + // imap: &dc_imap_t, + // server_uid: uint32_t, + // flag: *mut mailimap_flag, + // ) -> libc::c_int { + // 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.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); + // mailimap_uid_store(imap.etpan, set, store_att_flags); + // } + // 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 + // } + // if 0 != imap.should_reconnect { + // 0 + // } else { + // 1 + // } + // } + + pub fn set_seen( + &self, + context: &dc_context_t, + folder: *const libc::c_char, + uid: uint32_t, + ) -> dc_imap_res { + unimplemented!() + } + // let mut res: dc_imap_res = DC_RETRY_LATER; + // if folder.is_null() || uid == 0 as libc::c_uint { + // res = DC_FAILED + // } else if !imap.etpan.is_null() { + // dc_log_info( + // context, + // 0, + // 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(context, imap, folder) == 0 { + // dc_log_warning( + // context, + // 0, + // 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()) == 0 { + // dc_log_warning( + // context, + // 0, + // 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 fn set_mdnsent( + &self, + context: &dc_context_t, + folder: *const libc::c_char, + uid: uint32_t, + ) -> dc_imap_res { + unimplemented!(); + } + + // 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 folder.is_null() || uid == 0 as libc::c_uint || set.is_null() { + // res = DC_FAILED + // } else if !imap.etpan.is_null() { + // dc_log_info( + // context, + // 0, + // 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(context, imap, folder) == 0 { + // dc_log_warning( + // context, + // 0, + // 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 = 0; + // 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 = 1; + // 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, + // ) == 0 + // { + // can_create_flag = 1; + // 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(context, 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, + // )), + // ) == 0 + // { + // current_block = 17044610252497760460; + // } else { + // res = DC_SUCCESS; + // current_block = 14832935472441733737; + // } + // match current_block { + // 17044610252497760460 => {} + // _ => { + // dc_log_info( + // context, + // 0, + // 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( + // context, + // 0, + // 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 + // } + + // (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( + // msg_att: *mut mailimap_msg_att, + // 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 0; + // } + // 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) == 0 + // { + // return 1; + // } + // } + // } + // 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 + // } + // } + // 0 + // } + + // only returns 0 on connection problems; we should try later again in this case * + pub unsafe fn delete_msg( + &self, + context: &dc_context_t, + rfc724_mid: *const libc::c_char, + folder: *const libc::c_char, + mut server_uid: uint32_t, + ) -> libc::c_int { + unimplemented!() + } + // let mut success: libc::c_int = 0; + // let mut r: libc::c_int = 0; + // 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 rfc724_mid.is_null() + // || folder.is_null() + // || *folder.offset(0isize) as libc::c_int == 0 + // || server_uid == 0 as libc::c_uint + // { + // success = 1 + // } else { + // dc_log_info( + // context, + // 0, + // 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(context, imap, folder) == 0 { + // dc_log_warning( + // context, + // 0, + // 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(context, imap, r) || fetch_result.is_null() { + // fetch_result = 0 as *mut clist; + // dc_log_warning( + // context, + // 0, + // 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 = 0 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) != 0 + // { + // dc_log_warning( + // context, + // 0, + // 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 = 0 as uint32_t + // } + // /* mark the message for deletion */ + // if add_flag(imap, server_uid, mailimap_flag_new_deleted()) == 0 { + // dc_log_warning( + // context, + // 0, + // b"Cannot mark message as \"Deleted\".\x00" as *const u8 + // as *const libc::c_char, + // ); + // } else { + // imap.selected_folder_needs_expunge = 1; + // success = 1 + // } + // } + // } + // 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); + + // if 0 != success { + // 1 + // } else { + // dc_imap_is_connected(imap) + // } + // } + + pub fn configure_folders(&self, context: &dc_context_t, flags: libc::c_int) { + if !self.is_connected() { return; } - if 0 != setup_handle_if_needed(context, imap) { - if 0 != fetch_from_single_folder(context, imap, imap.watch_folder) { - do_fake_idle = 0; - } - } - } -} -pub unsafe fn dc_imap_interrupt_idle(imap: &mut dc_imap_t) { - if 0 != imap.can_idle { - if !imap.etpan.is_null() && !(*imap.etpan).imap_stream.is_null() { - mailstream_interrupt_idle((*imap.etpan).imap_stream); - } - } - - let &(ref lock, ref cvar) = &*imap.watch.clone(); - let mut watch = lock.lock().unwrap(); - - *watch = true; - cvar.notify_one(); -} - -pub unsafe fn dc_imap_move( - context: &dc_context_t, - imap: &mut dc_imap_t, - folder: *const libc::c_char, - uid: uint32_t, - dest_folder: *const libc::c_char, - 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 = 0; - let mut set: *mut mailimap_set = mailimap_set_new_single(uid); - let mut res_uid: uint32_t = 0 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 folder.is_null() - || uid == 0 as libc::c_uint - || dest_folder.is_null() - || dest_uid.is_null() - || set.is_null() - { - res = DC_FAILED - } else if strcasecmp(folder, dest_folder) == 0 { - dc_log_info( - context, - 0, - 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( - context, - 0, - 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(context, imap, folder) == 0 { - dc_log_warning( + unsafe { + dc_log_info( context, 0, - 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(context, imap, r) { - if !res_setsrc.is_null() { - mailimap_set_free(res_setsrc); - res_setsrc = 0 as *mut mailimap_set + b"Configuring IMAP-folders.\x00" as *const u8 as *const libc::c_char, + ) + }; + + let folders = self.list_folders(context).unwrap(); + let delimiter = self.config.read().unwrap().imap_delimiter; + let fallback_folder = format!("INBOX{}DeltaChat", delimiter); + + for folder in folders.iter() { + let meaning = get_folder_meaning(folder); + println!("{} - {:?}", folder.name(), meaning); + } + // let iter = (*folder_list).first; + // while !iter.is_null() { + // let mut folder: *mut dc_imapfolder_t = (if !iter.is_null() { + // (*iter).data + // } else { + // 0 as *mut libc::c_void + // }) as *mut dc_imapfolder_t; + // if strcmp( + // (*folder).name_utf8, + // b"DeltaChat\x00" as *const u8 as *const libc::c_char, + // ) == 0i32 + // || strcmp((*folder).name_utf8, fallback_folder) == 0i32 + // { + // if mvbox_folder.is_null() { + // mvbox_folder = dc_strdup((*folder).name_to_select) + // } + // } + // if (*folder).meaning == 1i32 { + // if sentbox_folder.is_null() { + // sentbox_folder = dc_strdup((*folder).name_to_select) + // } + // } + // iter = if !iter.is_null() { + // (*iter).next + // } else { + // 0 as *mut clistcell_s + // } + // } + // if mvbox_folder.is_null() && 0 != flags & 0x1i32 { + // dc_log_info( + // context, + // 0i32, + // b"Creating MVBOX-folder \"%s\"...\x00" as *const u8 as *const libc::c_char, + // b"DeltaChat\x00" as *const u8 as *const libc::c_char, + // ); + // let mut r: libc::c_int = mailimap_create( + // (*imap).etpan, + // b"DeltaChat\x00" as *const u8 as *const libc::c_char, + // ); + // if 0 != dc_imap_is_error(context, imap, r) { + // dc_log_warning( + // context, + // 0i32, + // b"Cannot create MVBOX-folder, using trying INBOX subfolder.\x00" as *const u8 + // as *const libc::c_char, + // ); + // r = mailimap_create((*imap).etpan, fallback_folder); + // if 0 != dc_imap_is_error(context, imap, r) { + // dc_log_warning( + // context, + // 0i32, + // b"Cannot create MVBOX-folder.\x00" as *const u8 as *const libc::c_char, + // ); + // } else { + // mvbox_folder = dc_strdup(fallback_folder); + // dc_log_info( + // context, + // 0i32, + // b"MVBOX-folder created as INBOX subfolder.\x00" as *const u8 + // as *const libc::c_char, + // ); + // } + // } else { + // mvbox_folder = dc_strdup(b"DeltaChat\x00" as *const u8 as *const libc::c_char); + // dc_log_info( + // context, + // 0i32, + // b"MVBOX-folder created.\x00" as *const u8 as *const libc::c_char, + // ); + // } + // mailimap_subscribe((*imap).etpan, mvbox_folder); + // } + // dc_sqlite3_set_config_int( + // context, + // &context.sql.clone().read().unwrap(), + // b"folders_configured\x00" as *const u8 as *const libc::c_char, + // 3i32, + // ); + // dc_sqlite3_set_config( + // context, + // &context.sql.clone().read().unwrap(), + // b"configured_mvbox_folder\x00" as *const u8 as *const libc::c_char, + // mvbox_folder, + // ); + // dc_sqlite3_set_config( + // context, + // &context.sql.clone().read().unwrap(), + // b"configured_sentbox_folder\x00" as *const u8 as *const libc::c_char, + // sentbox_folder, + // ); + } + + fn list_folders( + &self, + context: &dc_context_t, + ) -> Option>> { + if let Some(ref mut session) = *self.session.lock().unwrap() { + // TODO: use xlist when available + match session.list(Some(""), Some("*")) { + Ok(list) => { + if list.is_empty() { + unsafe { + dc_log_warning( + context, + 0i32, + b"Folder list is empty.\x00" as *const u8 as *const libc::c_char, + ) + }; + } + Some(list) } - if !res_setdest.is_null() { - mailimap_set_free(res_setdest); - res_setdest = 0 as *mut mailimap_set - } - dc_log_info( - context, - 0, - 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(context, imap, r) { - dc_log_info( - context, - 0, - 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()) == 0 { + Err(err) => { + eprintln!("list error: {:?}", err); + unsafe { dc_log_warning( context, - 0, - b"Cannot mark message as \"Deleted\".\x00" as *const u8 - as *const libc::c_char, - ); - } - imap.selected_folder_needs_expunge = 1; - 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 + 0i32, + b"Cannot get folder list.\x00" as *const u8 as *const libc::c_char, + ) + }; + None } } - } - } - 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( - imap: &mut dc_imap_t, - server_uid: uint32_t, - flag: *mut mailimap_flag, -) -> libc::c_int { - 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.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); - mailimap_uid_store(imap.etpan, set, store_att_flags); - } - 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 - } - if 0 != imap.should_reconnect { - 0 - } else { - 1 + None + } } } -pub unsafe fn dc_imap_set_seen( - context: &dc_context_t, - imap: &mut dc_imap_t, - folder: *const libc::c_char, - uid: uint32_t, -) -> dc_imap_res { - let mut res: dc_imap_res = DC_RETRY_LATER; - if folder.is_null() || uid == 0 as libc::c_uint { - res = DC_FAILED - } else if !imap.etpan.is_null() { - dc_log_info( - context, - 0, - 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(context, imap, folder) == 0 { - dc_log_warning( - context, - 0, - 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()) == 0 { - dc_log_warning( - context, - 0, - 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; +fn to_string(str: *const libc::c_char) -> String { + unsafe { CStr::from_ptr(str).to_str().unwrap().to_string() } } -pub unsafe fn dc_imap_set_mdnsent( - context: &dc_context_t, - imap: &mut dc_imap_t, - folder: *const libc::c_char, - 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 folder.is_null() || uid == 0 as libc::c_uint || set.is_null() { - res = DC_FAILED - } else if !imap.etpan.is_null() { - dc_log_info( - context, - 0, - 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(context, imap, folder) == 0 { - dc_log_warning( - context, - 0, - 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 = 0; - 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 = 1; - 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, - ) == 0 - { - can_create_flag = 1; - 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(context, 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, - )), - ) == 0 - { - current_block = 17044610252497760460; - } else { - res = DC_SUCCESS; - current_block = 14832935472441733737; - } - match current_block { - 17044610252497760460 => {} - _ => { - dc_log_info( - context, - 0, - 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( - context, - 0, - 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 - } - - (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 +fn to_str<'a>(str: *const libc::c_char) -> &'a str { + unsafe { CStr::from_ptr(str).to_str().unwrap() } } -unsafe fn peek_flag_keyword( - msg_att: *mut mailimap_msg_att, - 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 0; +/// Try to get the folder meaning by the name of the folder only used if the server does not support XLIST. +// TODO: lots languages missing - maybe there is a list somewhere on other MUAs? +// however, if we fail to find out the sent-folder, +// only watching this folder is not working. at least, this is no show stopper. +// CAVE: if possible, take care not to add a name here that is "sent" in one language +// but sth. different in others - a hard job. +fn get_folder_meaning_by_name(folder_name: &imap::types::Name) -> FolderMeaning { + let sent_names = vec!["sent", "sent objects", "gesendet"]; + let lower = folder_name.name().to_lowercase(); + + if sent_names.into_iter().find(|s| *s == lower).is_some() { + FolderMeaning::SentObjects + } else { + FolderMeaning::Unknown } - 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) == 0 - { - return 1; - } - } - } - 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 - } - } - 0 } -/* only returns 0 on connection problems; we should try later again in this case */ -pub unsafe fn dc_imap_delete_msg( - context: &dc_context_t, - imap: &mut dc_imap_t, - rfc724_mid: *const libc::c_char, - folder: *const libc::c_char, - mut server_uid: uint32_t, -) -> libc::c_int { - let mut success: libc::c_int = 0; - let mut r: libc::c_int = 0; - 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 rfc724_mid.is_null() - || folder.is_null() - || *folder.offset(0isize) as libc::c_int == 0 - || server_uid == 0 as libc::c_uint - { - success = 1 - } else { - dc_log_info( - context, - 0, - 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(context, imap, folder) == 0 { - dc_log_warning( - context, - 0, - 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(context, imap, r) || fetch_result.is_null() { - fetch_result = 0 as *mut clist; - dc_log_warning( - context, - 0, - 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 = 0 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() +fn get_folder_meaning(folder_name: &imap::types::Name) -> FolderMeaning { + if folder_name.attributes().is_empty() { + return FolderMeaning::Unknown; + } + + let mut res = FolderMeaning::Unknown; + let special_names = vec!["\\Spam", "\\Trash", "\\Drafts", "\\Junk"]; + + for attr in folder_name.attributes() { + println!("attr: {:?} - {}", attr, folder_name.name()); + match attr { + imap::types::NameAttribute::Custom(ref label) => { + if special_names.iter().find(|s| *s == label).is_some() { + res = FolderMeaning::Other; + } else if label == "\\Sent" { + res = FolderMeaning::SentObjects } - || { - is_rfc724_mid = unquote_rfc724_mid(is_quoted_rfc724_mid); - is_rfc724_mid.is_null() - } - || strcmp(is_rfc724_mid, rfc724_mid) != 0 - { - dc_log_warning( - context, - 0, - 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 = 0 as uint32_t - } - /* mark the message for deletion */ - if add_flag(imap, server_uid, mailimap_flag_new_deleted()) == 0 { - dc_log_warning( - context, - 0, - b"Cannot mark message as \"Deleted\".\x00" as *const u8 as *const libc::c_char, - ); - } else { - imap.selected_folder_needs_expunge = 1; - success = 1 } + _ => {} } } - 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); - if 0 != success { - 1 - } else { - dc_imap_is_connected(imap) + match res { + FolderMeaning::Unknown => get_folder_meaning_by_name(folder_name), + _ => res, } } diff --git a/src/dc_imex.rs b/src/dc_imex.rs index 8bd30b127..cb4e3333d 100644 --- a/src/dc_imex.rs +++ b/src/dc_imex.rs @@ -977,7 +977,7 @@ unsafe fn import_backup( 0i32, b"Import \"%s\" to \"%s\".\x00" as *const u8 as *const libc::c_char, backup_to_import, - context.dbfile, + context.get_dbfile(), ); if 0 != dc_is_configured(context) { dc_log_error( @@ -989,22 +989,22 @@ unsafe fn import_backup( if 0 != dc_sqlite3_is_open(&context.sql.clone().read().unwrap()) { dc_sqlite3_close(context, &mut context.sql.clone().write().unwrap()); } - dc_delete_file(context, context.dbfile); - if 0 != dc_file_exist(context, context.dbfile) { + dc_delete_file(context, context.get_dbfile()); + if 0 != dc_file_exist(context, context.get_dbfile()) { dc_log_error( context, 0i32, b"Cannot import backups: Cannot delete the old file.\x00" as *const u8 as *const libc::c_char, ); - } else if !(0 == dc_copy_file(context, backup_to_import, context.dbfile)) { + } else if !(0 == dc_copy_file(context, backup_to_import, context.get_dbfile())) { /* error already logged */ /* re-open copied database file */ if !(0 == dc_sqlite3_open( context, &mut context.sql.clone().write().unwrap(), - context.dbfile, + context.get_dbfile(), 0i32, )) { @@ -1062,7 +1062,7 @@ unsafe fn import_backup( free(pathNfilename as *mut libc::c_void); pathNfilename = dc_mprintf( b"%s/%s\x00" as *const u8 as *const libc::c_char, - context.blobdir, + context.get_blobdir(), file_name, ); if !(0 @@ -1168,15 +1168,15 @@ unsafe fn export_backup(mut context: &dc_context_t, mut dir: *const libc::c_char context, 0i32, b"Backup \"%s\" to \"%s\".\x00" as *const u8 as *const libc::c_char, - context.dbfile, + context.get_dbfile(), dest_pathNfilename, ); - if !(0 == dc_copy_file(context, context.dbfile, dest_pathNfilename)) { + if !(0 == dc_copy_file(context, context.get_dbfile(), dest_pathNfilename)) { /* error already logged */ dc_sqlite3_open( context, &mut context.sql.clone().write().unwrap(), - context.dbfile, + context.get_dbfile(), 0i32, ); closed = 0i32; @@ -1205,7 +1205,7 @@ unsafe fn export_backup(mut context: &dc_context_t, mut dir: *const libc::c_char 11487273724841241105 => {} _ => { total_files_cnt = 0i32; - dir_handle = opendir(context.blobdir); + dir_handle = opendir(context.get_blobdir()); if dir_handle.is_null() { dc_log_error( context, @@ -1213,7 +1213,7 @@ unsafe fn export_backup(mut context: &dc_context_t, mut dir: *const libc::c_char b"Backup: Cannot get info for blob-directory \"%s\".\x00" as *const u8 as *const libc::c_char, - context.blobdir, + context.get_blobdir(), ); } else { loop { @@ -1227,7 +1227,7 @@ unsafe fn export_backup(mut context: &dc_context_t, mut dir: *const libc::c_char dir_handle = 0 as *mut DIR; if total_files_cnt > 0i32 { /* scan directory, pass 2: copy files */ - dir_handle = opendir(context.blobdir); + dir_handle = opendir(context.get_blobdir()); if dir_handle.is_null() { dc_log_error( context, @@ -1235,7 +1235,7 @@ unsafe fn export_backup(mut context: &dc_context_t, mut dir: *const libc::c_char b"Backup: Cannot copy from blob-directory \"%s\".\x00" as *const u8 as *const libc::c_char, - context.blobdir, + context.get_blobdir(), ); current_block = 11487273724841241105; } else { @@ -1312,7 +1312,7 @@ unsafe fn export_backup(mut context: &dc_context_t, mut dir: *const libc::c_char curr_pathNfilename = dc_mprintf( b"%s/%s\x00" as *const u8 as *const libc::c_char, - context.blobdir, + context.get_blobdir(), name, ); free(buf); @@ -1359,7 +1359,7 @@ unsafe fn export_backup(mut context: &dc_context_t, mut dir: *const libc::c_char 0i32, b"Backup: No files to copy.\x00" as *const u8 as *const libc::c_char, - context.blobdir, + context.get_blobdir(), ); current_block = 2631791190359682872; } @@ -1395,7 +1395,7 @@ unsafe fn export_backup(mut context: &dc_context_t, mut dir: *const libc::c_char dc_sqlite3_open( context, &mut context.sql.clone().write().unwrap(), - context.dbfile, + context.get_dbfile(), 0i32, ); } diff --git a/src/dc_job.rs b/src/dc_job.rs index 5eb397e3c..0d81f8cf9 100644 --- a/src/dc_job.rs +++ b/src/dc_job.rs @@ -68,6 +68,7 @@ unsafe fn dc_job_perform( mut thread: libc::c_int, mut probe_network: libc::c_int, ) { + println!("perform job"); let mut select_stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; let mut job: dc_job_t = dc_job_t { job_id: 0, @@ -470,9 +471,12 @@ unsafe fn dc_job_do_DC_JOB_MOVE_MSG(mut context: &dc_context_t, mut job: *mut dc let mut msg: *mut dc_msg_t = dc_msg_new_untyped(context); let mut dest_folder: *mut libc::c_char = 0 as *mut libc::c_char; let mut dest_uid: uint32_t = 0i32 as uint32_t; - if 0 == dc_imap_is_connected(&mut context.inbox.clone().lock().unwrap()) { - connect_to_inbox(context); - if 0 == dc_imap_is_connected(&mut context.inbox.clone().lock().unwrap()) { + + let inbox = context.inbox.read().unwrap(); + + if !inbox.is_connected() { + connect_to_inbox(context, &inbox); + if !inbox.is_connected() { dc_job_try_again_later(job, 3i32, 0 as *const libc::c_char); current_block = 2238328302157162973; } else { @@ -491,11 +495,7 @@ unsafe fn dc_job_do_DC_JOB_MOVE_MSG(mut context: &dc_context_t, mut job: *mut dc 0i32, ) < 3i32 { - dc_configure_folders( - context, - &mut context.inbox.clone().lock().unwrap(), - 0x1i32, - ); + inbox.configure_folders(context, 0x1i32); } dest_folder = dc_sqlite3_get_config( context, @@ -503,9 +503,8 @@ unsafe fn dc_job_do_DC_JOB_MOVE_MSG(mut context: &dc_context_t, mut job: *mut dc b"configured_mvbox_folder\x00" as *const u8 as *const libc::c_char, 0 as *const libc::c_char, ); - match dc_imap_move( + match inbox.mv( context, - &mut context.inbox.clone().lock().unwrap(), (*msg).server_folder, (*msg).server_uid, dest_folder, @@ -556,31 +555,28 @@ unsafe fn dc_job_do_DC_JOB_MOVE_MSG(mut context: &dc_context_t, mut job: *mut dc /* ****************************************************************************** * IMAP-jobs ******************************************************************************/ -unsafe fn connect_to_inbox(mut context: &dc_context_t) -> libc::c_int { +unsafe fn connect_to_inbox(context: &dc_context_t, inbox: &dc_imap_t) -> libc::c_int { let mut ret_connected: libc::c_int = 0i32; - ret_connected = - dc_connect_to_configured_imap(context, &mut context.inbox.clone().lock().unwrap()); + + ret_connected = dc_connect_to_configured_imap(context, inbox); if !(0 == ret_connected) { - dc_imap_set_watch_folder( - &mut context.inbox.clone().lock().unwrap(), - b"INBOX\x00" as *const u8 as *const libc::c_char, - ); + inbox.set_watch_folder(b"INBOX\x00" as *const u8 as *const libc::c_char); } - return ret_connected; + ret_connected } -unsafe fn dc_job_do_DC_JOB_MARKSEEN_MDN_ON_IMAP( - mut context: &dc_context_t, - mut job: *mut dc_job_t, -) { + +unsafe fn dc_job_do_DC_JOB_MARKSEEN_MDN_ON_IMAP(context: &dc_context_t, job: *mut dc_job_t) { let mut current_block: u64; let mut folder: *mut libc::c_char = dc_param_get((*job).param, 'Z' as i32, 0 as *const libc::c_char); let mut uid: uint32_t = dc_param_get_int((*job).param, 'z' as i32, 0i32) as uint32_t; let mut dest_folder: *mut libc::c_char = 0 as *mut libc::c_char; let mut dest_uid: uint32_t = 0i32 as uint32_t; - if 0 == dc_imap_is_connected(&mut context.inbox.clone().lock().unwrap()) { - connect_to_inbox(context); - if 0 == dc_imap_is_connected(&mut context.inbox.clone().lock().unwrap()) { + let mut inbox = context.inbox.read().unwrap(); + + if !inbox.is_connected() { + connect_to_inbox(context, &inbox); + if !inbox.is_connected() { dc_job_try_again_later(job, 3i32, 0 as *const libc::c_char); current_block = 2670689566614003383; } else { @@ -591,14 +587,7 @@ unsafe fn dc_job_do_DC_JOB_MARKSEEN_MDN_ON_IMAP( } match current_block { 11006700562992250127 => { - if dc_imap_set_seen( - context, - &mut context.inbox.clone().lock().unwrap(), - folder, - uid, - ) as libc::c_uint - == 0i32 as libc::c_uint - { + if inbox.set_seen(context, folder, uid) as libc::c_uint == 0i32 as libc::c_uint { dc_job_try_again_later(job, 3i32, 0 as *const libc::c_char); } if 0 != dc_param_get_int((*job).param, 'M' as i32, 0i32) { @@ -609,11 +598,7 @@ unsafe fn dc_job_do_DC_JOB_MARKSEEN_MDN_ON_IMAP( 0i32, ) < 3i32 { - dc_configure_folders( - context, - &mut context.inbox.clone().lock().unwrap(), - 0x1i32, - ); + inbox.configure_folders(context, 0x1i32); } dest_folder = dc_sqlite3_get_config( context, @@ -621,15 +606,7 @@ unsafe fn dc_job_do_DC_JOB_MARKSEEN_MDN_ON_IMAP( b"configured_mvbox_folder\x00" as *const u8 as *const libc::c_char, 0 as *const libc::c_char, ); - match dc_imap_move( - context, - &mut context.inbox.clone().lock().unwrap(), - folder, - uid, - dest_folder, - &mut dest_uid, - ) as libc::c_uint - { + match inbox.mv(context, folder, uid, dest_folder, &mut dest_uid) as libc::c_uint { 1 => { dc_job_try_again_later(job, 3i32, 0 as *const libc::c_char); } @@ -648,9 +625,11 @@ unsafe fn dc_job_do_DC_JOB_MARKSEEN_MSG_ON_IMAP( ) { let mut current_block: u64; let mut msg: *mut dc_msg_t = dc_msg_new_untyped(context); - if 0 == dc_imap_is_connected(&mut context.inbox.clone().lock().unwrap()) { - connect_to_inbox(context); - if 0 == dc_imap_is_connected(&mut context.inbox.clone().lock().unwrap()) { + let inbox = context.inbox.read().unwrap(); + + if !inbox.is_connected() { + connect_to_inbox(context, &inbox); + if !inbox.is_connected() { dc_job_try_again_later(job, 3i32, 0 as *const libc::c_char); current_block = 17792648348530113339; } else { @@ -662,12 +641,8 @@ unsafe fn dc_job_do_DC_JOB_MARKSEEN_MSG_ON_IMAP( match current_block { 15240798224410183470 => { if !(0 == dc_msg_load_from_db(msg, context, (*job).foreign_id)) { - match dc_imap_set_seen( - context, - &mut context.inbox.clone().lock().unwrap(), - (*msg).server_folder, - (*msg).server_uid, - ) as libc::c_uint + match inbox.set_seen(context, (*msg).server_folder, (*msg).server_uid) + as libc::c_uint { 0 => {} 1 => { @@ -685,9 +660,8 @@ unsafe fn dc_job_do_DC_JOB_MARKSEEN_MSG_ON_IMAP( 1i32, ) { - match dc_imap_set_mdnsent( + match inbox.set_mdnsent( context, - &mut context.inbox.clone().lock().unwrap(), (*msg).server_folder, (*msg).server_uid, ) as libc::c_uint @@ -743,9 +717,8 @@ unsafe fn dc_job_do_DC_JOB_MARKSEEN_MSG_ON_IMAP( 1i32, ) { - match dc_imap_set_mdnsent( + match inbox.set_mdnsent( context, - &mut context.inbox.clone().lock().unwrap(), (*msg).server_folder, (*msg).server_uid, ) as libc::c_uint @@ -965,21 +938,25 @@ pub unsafe fn dc_interrupt_smtp_idle(mut context: &dc_context_t) { cvar.notify_one(); } -pub unsafe fn dc_interrupt_imap_idle(mut context: &dc_context_t) { +pub unsafe fn dc_interrupt_imap_idle(context: &dc_context_t) { dc_log_info( context, 0i32, b"Interrupting IMAP-IDLE...\x00" as *const u8 as *const libc::c_char, ); - *context.perform_inbox_jobs_needed.clone().write().unwrap() = 1; - dc_imap_interrupt_idle(&mut context.inbox.clone().lock().unwrap()); + println!("inbox lock"); + *context.perform_inbox_jobs_needed.write().unwrap() = 1; + println!("imap lock"); + context.inbox.read().unwrap().interrupt_idle(); } unsafe fn dc_job_do_DC_JOB_DELETE_MSG_ON_IMAP(mut context: &dc_context_t, mut job: *mut dc_job_t) { let mut current_block: u64; let mut delete_from_server: libc::c_int = 1i32; let mut msg: *mut dc_msg_t = dc_msg_new_untyped(context); + let inbox = context.inbox.read().unwrap(); + if !(0 == dc_msg_load_from_db(msg, context, (*job).foreign_id) || (*msg).rfc724_mid.is_null() || *(*msg).rfc724_mid.offset(0isize) as libc::c_int == 0i32) @@ -996,9 +973,9 @@ unsafe fn dc_job_do_DC_JOB_DELETE_MSG_ON_IMAP(mut context: &dc_context_t, mut jo } /* if this is the last existing part of the message, we delete the message from the server */ if 0 != delete_from_server { - if 0 == dc_imap_is_connected(&mut context.inbox.clone().lock().unwrap()) { - connect_to_inbox(context); - if 0 == dc_imap_is_connected(&mut context.inbox.clone().lock().unwrap()) { + if !inbox.is_connected() { + connect_to_inbox(context, &inbox); + if !inbox.is_connected() { dc_job_try_again_later(job, 3i32, 0 as *const libc::c_char); current_block = 8913536887710889399; } else { @@ -1010,9 +987,8 @@ unsafe fn dc_job_do_DC_JOB_DELETE_MSG_ON_IMAP(mut context: &dc_context_t, mut jo match current_block { 8913536887710889399 => {} _ => { - if 0 == dc_imap_delete_msg( + if 0 == inbox.delete_msg( context, - &mut context.inbox.clone().lock().unwrap(), (*msg).rfc724_mid, (*msg).server_folder, (*msg).server_uid, @@ -1049,9 +1025,11 @@ pub unsafe fn dc_job_kill_action(mut context: &dc_context_t, mut action: libc::c sqlite3_finalize(stmt); } -pub unsafe fn dc_perform_imap_fetch(mut context: &dc_context_t) { +pub unsafe fn dc_perform_imap_fetch(context: &dc_context_t) { + let inbox = context.inbox.read().unwrap(); + let mut start: libc::clock_t = clock(); - if 0 == connect_to_inbox(context) { + if 0 == connect_to_inbox(context, &inbox) { return; } if dc_sqlite3_get_config_int( @@ -1073,14 +1051,14 @@ pub unsafe fn dc_perform_imap_fetch(mut context: &dc_context_t) { 0i32, b"INBOX-fetch started...\x00" as *const u8 as *const libc::c_char, ); - dc_imap_fetch(context, &mut context.inbox.clone().lock().unwrap()); - if 0 != context.inbox.clone().lock().unwrap().should_reconnect { + inbox.fetch(context); + if inbox.should_reconnect() { dc_log_info( context, 0i32, b"INBOX-fetch aborted, starting over...\x00" as *const u8 as *const libc::c_char, ); - dc_imap_fetch(context, &mut context.inbox.clone().lock().unwrap()); + inbox.fetch(context); } dc_log_info( context, @@ -1089,8 +1067,11 @@ pub unsafe fn dc_perform_imap_fetch(mut context: &dc_context_t) { clock().wrapping_sub(start) as libc::c_double * 1000.0f64 / 1000000i32 as libc::c_double, ); } + pub unsafe fn dc_perform_imap_idle(context: &dc_context_t) { - connect_to_inbox(context); + let inbox = context.inbox.read().unwrap(); + + connect_to_inbox(context, &inbox); if 0 != *context.perform_inbox_jobs_needed.clone().read().unwrap() { dc_log_info( @@ -1106,7 +1087,7 @@ pub unsafe fn dc_perform_imap_idle(context: &dc_context_t) { 0i32, b"INBOX-IDLE started...\x00" as *const u8 as *const libc::c_char, ); - dc_imap_idle(context, &mut context.inbox.clone().lock().unwrap()); + inbox.idle(context); dc_log_info( context, 0i32, diff --git a/src/dc_jobthread.rs b/src/dc_jobthread.rs index c911c43f5..88b039b7c 100644 --- a/src/dc_jobthread.rs +++ b/src/dc_jobthread.rs @@ -104,7 +104,8 @@ pub unsafe extern "C" fn dc_jobthread_interrupt_idle( jobthread.name, ); - dc_imap_interrupt_idle(&mut jobthread.imap.clone().lock().unwrap()); + println!("jobthread interrupt, waiting for lock"); + jobthread.imap.lock().unwrap().interrupt_idle(); let &(ref lock, ref cvar) = &*jobthread.state.clone(); let mut state = lock.lock().unwrap(); @@ -140,16 +141,16 @@ pub unsafe fn dc_jobthread_fetch( b"%s-fetch started...\x00" as *const u8 as *const libc::c_char, jobthread.name, ); - dc_imap_fetch(context, &mut jobthread.imap.clone().lock().unwrap()); + jobthread.imap.lock().unwrap().fetch(context); - if 0 != jobthread.imap.clone().lock().unwrap().should_reconnect { + if jobthread.imap.lock().unwrap().should_reconnect() { dc_log_info( context, 0i32, b"%s-fetch aborted, starting over...\x00" as *const u8 as *const libc::c_char, jobthread.name, ); - dc_imap_fetch(context, &mut jobthread.imap.clone().lock().unwrap()); + jobthread.imap.lock().unwrap().fetch(context); } dc_log_info( context, @@ -173,7 +174,7 @@ unsafe fn connect_to_imap(context: &dc_context_t, jobthread: &mut dc_jobthread_t let mut ret_connected: libc::c_int = 0i32; let mut mvbox_name: *mut libc::c_char = 0 as *mut libc::c_char; - if 0 != dc_imap_is_connected(&mut jobthread.imap.clone().lock().unwrap()) { + if jobthread.imap.lock().unwrap().is_connected() { ret_connected = 1 } else { ret_connected = @@ -186,7 +187,11 @@ unsafe fn connect_to_imap(context: &dc_context_t, jobthread: &mut dc_jobthread_t 0, ) < 3 { - dc_configure_folders(context, &mut jobthread.imap.clone().lock().unwrap(), 0x1); + jobthread + .imap + .lock() + .unwrap() + .configure_folders(context, 0x1); } mvbox_name = dc_sqlite3_get_config( context, @@ -195,10 +200,10 @@ unsafe fn connect_to_imap(context: &dc_context_t, jobthread: &mut dc_jobthread_t 0 as *const libc::c_char, ); if mvbox_name.is_null() { - dc_imap_disconnect(context, &mut jobthread.imap.clone().lock().unwrap()); + jobthread.imap.lock().unwrap().disconnect(context); ret_connected = 0; } else { - dc_imap_set_watch_folder(&mut jobthread.imap.clone().lock().unwrap(), mvbox_name); + jobthread.imap.lock().unwrap().set_watch_folder(mvbox_name); } } } @@ -256,7 +261,7 @@ pub unsafe fn dc_jobthread_idle( b"%s-IDLE started...\x00" as *const u8 as *const libc::c_char, jobthread.name, ); - dc_imap_idle(context, &mut jobthread.imap.clone().lock().unwrap()); + jobthread.imap.lock().unwrap().idle(context); dc_log_info( context, 0i32, diff --git a/src/dc_receive_imf.rs b/src/dc_receive_imf.rs index a2668e2d7..174ffa6db 100644 --- a/src/dc_receive_imf.rs +++ b/src/dc_receive_imf.rs @@ -56,7 +56,7 @@ pub unsafe fn dc_receive_imf( let mut sort_timestamp: time_t = -1i32 as time_t; let mut sent_timestamp: time_t = -1i32 as time_t; let mut rcvd_timestamp: time_t = -1i32 as time_t; - let mut mime_parser: *mut dc_mimeparser_t = dc_mimeparser_new((*context).blobdir, context); + let mut mime_parser: *mut dc_mimeparser_t = dc_mimeparser_new(context.get_blobdir(), context); let mut field: *const mailimf_field = 0 as *const mailimf_field; let mut mime_in_reply_to: *mut libc::c_char = 0 as *mut libc::c_char; let mut mime_references: *mut libc::c_char = 0 as *mut libc::c_char; diff --git a/src/dc_sqlite3.rs b/src/dc_sqlite3.rs index b7cdce76c..ff740c46c 100644 --- a/src/dc_sqlite3.rs +++ b/src/dc_sqlite3.rs @@ -936,7 +936,7 @@ pub unsafe fn dc_sqlite3_open( context, sql, b"backup_for\x00" as *const u8 as *const libc::c_char, - context.blobdir, + context.get_blobdir(), ); dc_ensure_no_slash(repl_from); if 0 != !('f' as i32 == 'f' as i32) as libc::c_int as libc::c_long { @@ -1478,13 +1478,13 @@ pub unsafe fn dc_housekeeping(context: &dc_context_t) { files_in_use.count as libc::c_int, ); /* go through directory and delete unused files */ - dir_handle = opendir(context.blobdir); + dir_handle = opendir(context.get_blobdir()); if dir_handle.is_null() { dc_log_warning( context, 0, b"Housekeeping: Cannot open %s.\x00" as *const u8 as *const libc::c_char, - context.blobdir, + context.get_blobdir(), ); } else { /* avoid deletion of files that are just created to build a message object */ @@ -1529,7 +1529,7 @@ pub unsafe fn dc_housekeeping(context: &dc_context_t) { free(path as *mut libc::c_void); path = dc_mprintf( b"%s/%s\x00" as *const u8 as *const libc::c_char, - context.blobdir, + context.get_blobdir(), name, ); diff --git a/src/dc_tools.rs b/src/dc_tools.rs index 60729efd7..3814034d4 100644 --- a/src/dc_tools.rs +++ b/src/dc_tools.rs @@ -1281,13 +1281,13 @@ pub unsafe fn dc_get_abs_path( 8, ) == 0i32 { - if context.blobdir.is_null() { + if !context.has_blobdir() { current_block = 3805228753452640762; } else { dc_str_replace( &mut pathNfilename_abs, b"$BLOBDIR\x00" as *const u8 as *const libc::c_char, - context.blobdir, + context.get_blobdir(), ); current_block = 6937071982253665452; } @@ -1600,7 +1600,7 @@ pub unsafe fn dc_is_blobdir_path( mut context: &dc_context_t, mut path: *const libc::c_char, ) -> libc::c_int { - if strncmp(path, context.blobdir, strlen(context.blobdir)) == 0i32 + if strncmp(path, context.get_blobdir(), strlen(context.get_blobdir())) == 0i32 || strncmp(path, b"$BLOBDIR\x00" as *const u8 as *const libc::c_char, 8) == 0i32 { return 1i32; @@ -1612,10 +1612,10 @@ pub unsafe fn dc_make_rel_path(mut context: &dc_context_t, mut path: *mut *mut l if path.is_null() || (*path).is_null() { return; } - if strncmp(*path, context.blobdir, strlen(context.blobdir)) == 0i32 { + if strncmp(*path, context.get_blobdir(), strlen(context.get_blobdir())) == 0i32 { dc_str_replace( path, - context.blobdir, + context.get_blobdir(), b"$BLOBDIR\x00" as *const u8 as *const libc::c_char, ); }; diff --git a/src/x.rs b/src/x.rs index db0a9981f..66b5a4fe2 100644 --- a/src/x.rs +++ b/src/x.rs @@ -415,8 +415,8 @@ extern "C" { ) -> libc::c_int; pub fn mailimap_idle(session: *mut mailimap) -> libc::c_int; pub fn mailimap_idle_done(session: *mut mailimap) -> libc::c_int; - pub fn mailimap_has_idle(session: *mut mailimap) -> libc::c_int; - pub fn mailimap_has_xlist(session: *mut mailimap) -> libc::c_int; + pub fn mailimap_has_idle(session: *const mailimap) -> libc::c_int; + pub fn mailimap_has_xlist(session: *const mailimap) -> libc::c_int; pub fn mailimap_oauth2_authenticate( session: *mut mailimap, auth_user: *const libc::c_char, diff --git a/tests/stress.rs b/tests/stress.rs index 5e3af825a..8ef437ad1 100644 --- a/tests/stress.rs +++ b/tests/stress.rs @@ -338,7 +338,7 @@ unsafe extern "C" fn stress_functions(context: &dc_context_t) { }; let mut abs_path: *mut libc::c_char = dc_mprintf( b"%s/%s\x00" as *const u8 as *const libc::c_char, - (*context).blobdir, + context.get_blobdir(), b"foobar\x00" as *const u8 as *const libc::c_char, ); if 0 != (0 == dc_is_blobdir_path(context, abs_path)) as libc::c_int as libc::c_long { @@ -749,7 +749,7 @@ unsafe extern "C" fn stress_functions(context: &dc_context_t) { } else { }; mailmime_free(mime); - let mut mimeparser: *mut dc_mimeparser_t = dc_mimeparser_new((*context).blobdir, context); + let mut mimeparser: *mut dc_mimeparser_t = dc_mimeparser_new(context.get_blobdir(), context); let mut raw: *const libc::c_char = b"Content-Type: multipart/mixed; boundary=\"==break==\";\nSubject: outer-subject\nX-Special-A: special-a\nFoo: Bar\nChat-Version: 0.0\n\n--==break==\nContent-Type: text/plain; protected-headers=\"v1\";\nSubject: inner-subject\nX-Special-B: special-b\nFoo: Xy\nChat-Version: 1.0\n\ntest1\n\n--==break==--\n\n\x00" as *const u8 as *const libc::c_char;