diff --git a/.circleci/config.yml b/.circleci/config.yml index 2d6d2ac53..c6915d3a5 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,6 +1,4 @@ # copied from http://koushiro.me/2019/04/30/Building-and-Testing-Rust-projects-on-CircleCI/ -# TODO remove things that aren't needed for apt -# TODO might want to create our own docker image for this and get rid of apt stuff version: 2.1 jobs: @@ -14,38 +12,15 @@ jobs: - checkout - run: - name: Setup build environment (TODO move this to custom docker container) + name: Setup build environment command: | apt update - apt install -y sudo curl build-essential git pkg-config zlib1g-dev python libssl-dev autoconf libtool + apt install -y curl build-essential autoconf libtool git python pkg-config zlib1g-dev libssl-dev libetpan-dev libsasl2-dev # this will pick default toolchain from `rust-toolchain` file curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- --no-modify-path --default-toolchain none -y; source $HOME/.cargo/env no_output_timeout: 1800s - - run: - name: build etpan (TODO move this to custom docker container) - command: | - curl -L -o libetpan-1.9.1.tar.gz https://github.com/dinhviethoa/libetpan/archive/1.9.1.tar.gz - tar xzf libetpan-1.9.1.tar.gz - cd libetpan-1.9.1 - ./autogen.sh - ./configure --disable-silent-rules --enable-ipv6 --enable-iconv --disable-db --with-openssl --with-sasl --with-zlib --without-curl --without-expat - make -j $(nproc) - sudo make install - sudo ldconfig -v - - - run: - name: build sasl2 (TODO move this to custom docker container) - command: | - curl -O https://www.cyrusimap.org/releases/cyrus-sasl-2.1.27.tar.gz - tar zxf cyrus-sasl-2.1.27.tar.gz - cd cyrus-sasl-2.1.27 - ./configure --enable-shared --disable-cmulocal --disable-sample --disable-obsolete_cram_attr --disable-obsolete_digest_attr --disable-alwaystrue --enable-checkapop --enable-cram --enable-digest --enable-scram --enable-plain --enable-anon --enable-login - make -j $(nproc) - sudo make install - sudo ldconfig -v - - run: name: Format command: | @@ -60,6 +35,13 @@ jobs: export RUST_BACKTRACE=1 cargo test + - run: + name: Build deltachat-ffi + command: | + export PATH=~/.cargo/bin:$PATH + export RUST_BACKTRACE=1 + cargo build --release -p deltachat_ffi + workflows: version: 2.1 build: diff --git a/Cargo.toml b/Cargo.toml index 7cd62daac..18b502809 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,6 +21,12 @@ libsqlite3-sys = { version = "0.14.0", features = ["bundled"] } reqwest = "0.9.15" num-derive = "0.2.5" num-traits = "0.2.6" +native-tls = "0.2.3" +lettre = "0.9.0" +imap = "1.0.1" +# rental = "0.5.3" +mmime = { git = "https://github.com/dignifiedquire/mmime" } +base64 = "0.10.1" [dev-dependencies] tempfile = "3.0.7" @@ -37,3 +43,7 @@ name = "simple" name = "repl" path = "examples/repl/main.rs" + +[features] +default = [] +vendored = ["native-tls/vendored"] diff --git a/build.rs b/build.rs index 91b08f231..8c5ffb7fb 100644 --- a/build.rs +++ b/build.rs @@ -1,9 +1,5 @@ extern crate cc; -fn link_dylib(lib: &str) { - println!("cargo:rustc-link-lib=dylib={}", lib); -} - fn link_static(lib: &str) { println!("cargo:rustc-link-lib=static={}", lib); } @@ -29,57 +25,12 @@ fn main() { build_tools(); add_search_path("/usr/local/lib"); - add_search_path("./include/include"); - add_search_path("./include/libs"); let target = std::env::var("TARGET").unwrap(); if target.contains("-apple") || target.contains("-darwin") { - link_static("etpan"); - link_dylib("iconv"); - link_framework("CoreFoundation"); link_framework("CoreServices"); link_framework("Security"); - - link_dylib("sasl2"); - link_dylib("z"); - link_dylib("pthread"); - } else if target.contains("-android") { - add_search_path("./include/cyrus-sasl-android-4/include"); - add_search_path("./include/openssl-android-3/include"); - add_search_path("./include/iconv-android-1/include"); - - let arch = if target.contains("x86") { - "x86" - } else if target.contains("64") { - "arm64-v8a" - } else if target.contains("v7") { - "armeabi-v7a" - } else { - "armeabi" - }; - - add_search_path(&format!("./include/libs/{}", arch)); - add_search_path(&format!("./include/iconv-android-1/libs/{}", arch)); - add_search_path(&format!("./include/openssl-android-3/libs/{}", arch)); - add_search_path(&format!("./include/cyrus-sasl-android-4/libs/{}", arch)); - - // dependencies for libetpan - link_static("crypto"); - link_static("sasl2"); - link_static("iconv"); - link_static("ssl"); - link_dylib("z"); - - // libetpan iteself - link_static("etpan"); - } else if target.contains("-linux") { - link_dylib("etpan"); - link_dylib("sasl2"); - link_dylib("z"); - link_dylib("pthread"); - } else { - panic!("unsupported target"); } // local tools diff --git a/deltachat-ffi/src/lib.rs b/deltachat-ffi/src/lib.rs index 19d547439..5b3cdfa28 100644 --- a/deltachat-ffi/src/lib.rs +++ b/deltachat-ffi/src/lib.rs @@ -28,11 +28,14 @@ pub unsafe extern "C" fn dc_context_new( userdata: *mut libc::c_void, os_name: *const libc::c_char, ) -> *mut dc_context_t { - dc_context::dc_context_new(cb, userdata, os_name) + let ctx = dc_context::dc_context_new(cb, userdata, os_name); + Box::into_raw(Box::new(ctx)) } #[no_mangle] pub unsafe extern "C" fn dc_context_unref(context: *mut dc_context_t) { + assert!(!context.is_null()); + let context = &mut *context; dc_context::dc_context_unref(context) } @@ -40,6 +43,9 @@ pub unsafe extern "C" fn dc_context_unref(context: *mut dc_context_t) { pub unsafe extern "C" fn dc_get_userdata( context: *mut dc_context::dc_context_t, ) -> *mut libc::c_void { + assert!(!context.is_null()); + let context = &mut *context; + dc_context::dc_get_userdata(context) } @@ -49,16 +55,23 @@ pub unsafe extern "C" fn dc_open( dbfile: *mut libc::c_char, blobdir: *mut libc::c_char, ) -> libc::c_int { + assert!(!context.is_null()); + let context = &mut *context; + dc_context::dc_open(context, dbfile, blobdir) } #[no_mangle] pub unsafe extern "C" fn dc_close(context: *mut dc_context::dc_context_t) { + assert!(!context.is_null()); + let context = &mut *context; dc_context::dc_close(context) } #[no_mangle] pub unsafe extern "C" fn dc_is_open(context: *mut dc_context::dc_context_t) -> libc::c_int { + assert!(!context.is_null()); + let context = &mut *context; dc_context::dc_is_open(context) } @@ -66,6 +79,9 @@ pub unsafe extern "C" fn dc_is_open(context: *mut dc_context::dc_context_t) -> l pub unsafe extern "C" fn dc_get_blobdir( context: *mut dc_context::dc_context_t, ) -> *mut libc::c_char { + assert!(!context.is_null()); + let context = &*context; + dc_context::dc_get_blobdir(context) } @@ -75,6 +91,9 @@ pub unsafe extern "C" fn dc_set_config( key: *mut libc::c_char, value: *mut libc::c_char, ) -> libc::c_int { + assert!(!context.is_null()); + let context = &*context; + dc_context::dc_set_config(context, key, value) } @@ -83,11 +102,17 @@ pub unsafe extern "C" fn dc_get_config( context: *mut dc_context::dc_context_t, key: *mut libc::c_char, ) -> *mut libc::c_char { + assert!(!context.is_null()); + let context = &*context; + dc_context::dc_get_config(context, key) } #[no_mangle] pub unsafe extern "C" fn dc_get_info(context: *mut dc_context::dc_context_t) -> *mut libc::c_char { + assert!(!context.is_null()); + let context = &*context; + dc_context::dc_get_info(context) } @@ -97,6 +122,9 @@ pub unsafe extern "C" fn dc_get_oauth2_url( addr: *mut libc::c_char, redirect: *mut libc::c_char, ) -> *mut libc::c_char { + assert!(!context.is_null()); + let context = &*context; + dc_oauth2::dc_get_oauth2_url(context, addr, redirect) } @@ -107,91 +135,142 @@ pub unsafe extern "C" fn dc_get_version_str() -> *mut libc::c_char { #[no_mangle] pub unsafe extern "C" fn dc_configure(context: *mut dc_context::dc_context_t) { + assert!(!context.is_null()); + let context = &*context; + dc_configure::dc_configure(context) } #[no_mangle] pub unsafe extern "C" fn dc_is_configured(context: *mut dc_context::dc_context_t) -> libc::c_int { + assert!(!context.is_null()); + let context = &*context; + dc_configure::dc_is_configured(context) } #[no_mangle] pub unsafe extern "C" fn dc_perform_imap_jobs(context: *mut dc_context::dc_context_t) { + assert!(!context.is_null()); + let context = &*context; + dc_job::dc_perform_imap_jobs(context) } #[no_mangle] pub unsafe extern "C" fn dc_perform_imap_fetch(context: *mut dc_context::dc_context_t) { + assert!(!context.is_null()); + let context = &*context; + dc_job::dc_perform_imap_fetch(context) } #[no_mangle] pub unsafe extern "C" fn dc_perform_imap_idle(context: *mut dc_context::dc_context_t) { + assert!(!context.is_null()); + let context = &*context; + dc_job::dc_perform_imap_idle(context) } #[no_mangle] pub unsafe extern "C" fn dc_interrupt_imap_idle(context: *mut dc_context::dc_context_t) { + assert!(!context.is_null()); + let context = &*context; + dc_job::dc_interrupt_imap_idle(context) } #[no_mangle] pub unsafe extern "C" fn dc_perform_mvbox_fetch(context: *mut dc_context::dc_context_t) { + assert!(!context.is_null()); + let context = &*context; + dc_job::dc_perform_mvbox_fetch(context) } #[no_mangle] pub unsafe extern "C" fn dc_perform_mvbox_idle(context: *mut dc_context::dc_context_t) { + assert!(!context.is_null()); + let context = &*context; + dc_job::dc_perform_mvbox_idle(context) } #[no_mangle] pub unsafe extern "C" fn dc_interrupt_mvbox_idle(context: *mut dc_context::dc_context_t) { + assert!(!context.is_null()); + let context = &*context; + dc_job::dc_interrupt_mvbox_idle(context) } #[no_mangle] pub unsafe extern "C" fn dc_perform_sentbox_fetch(context: *mut dc_context::dc_context_t) { + assert!(!context.is_null()); + let context = &*context; + dc_job::dc_perform_sentbox_fetch(context) } #[no_mangle] pub unsafe extern "C" fn dc_perform_sentbox_idle(context: *mut dc_context::dc_context_t) { + assert!(!context.is_null()); + let context = &*context; + dc_job::dc_perform_sentbox_idle(context) } #[no_mangle] pub unsafe extern "C" fn dc_interrupt_sentbox_idle(context: *mut dc_context::dc_context_t) { + assert!(!context.is_null()); + let context = &*context; + dc_job::dc_interrupt_sentbox_idle(context) } #[no_mangle] pub unsafe extern "C" fn dc_perform_smtp_jobs(context: *mut dc_context::dc_context_t) { + assert!(!context.is_null()); + let context = &*context; + dc_job::dc_perform_smtp_jobs(context) } #[no_mangle] pub unsafe extern "C" fn dc_perform_smtp_idle(context: *mut dc_context::dc_context_t) { + assert!(!context.is_null()); + let context = &*context; + dc_job::dc_perform_smtp_idle(context) } #[no_mangle] pub unsafe extern "C" fn dc_interrupt_smtp_idle(context: *mut dc_context::dc_context_t) { + assert!(!context.is_null()); + let context = &*context; + dc_job::dc_interrupt_smtp_idle(context) } #[no_mangle] pub unsafe extern "C" fn dc_maybe_network(context: *mut dc_context::dc_context_t) { + assert!(!context.is_null()); + let context = &*context; + dc_job::dc_maybe_network(context) } #[no_mangle] -pub unsafe extern "C" fn dc_get_chatlist( +pub unsafe extern "C" fn dc_get_chatlist<'a>( context: *mut dc_context::dc_context_t, flags: libc::c_int, query_str: *mut libc::c_char, query_id: libc::uint32_t, -) -> *mut dc_chatlist::dc_chatlist_t { +) -> *mut dc_chatlist::dc_chatlist_t<'a> { + assert!(!context.is_null()); + let context = &*context; + dc_chatlist::dc_get_chatlist(context, flags, query_str, query_id) } @@ -200,6 +279,9 @@ pub unsafe extern "C" fn dc_create_chat_by_msg_id( context: *mut dc_context::dc_context_t, msg_id: libc::uint32_t, ) -> libc::uint32_t { + assert!(!context.is_null()); + let context = &*context; + dc_chat::dc_create_chat_by_msg_id(context, msg_id) } @@ -208,6 +290,9 @@ pub unsafe extern "C" fn dc_create_chat_by_contact_id( context: *mut dc_context::dc_context_t, contact_id: libc::uint32_t, ) -> libc::uint32_t { + assert!(!context.is_null()); + let context = &*context; + dc_chat::dc_create_chat_by_contact_id(context, contact_id) } @@ -216,6 +301,9 @@ pub unsafe extern "C" fn dc_get_chat_id_by_contact_id( context: *mut dc_context::dc_context_t, contact_id: libc::uint32_t, ) -> libc::uint32_t { + assert!(!context.is_null()); + let context = &*context; + dc_chat::dc_get_chat_id_by_contact_id(context, contact_id) } @@ -225,6 +313,9 @@ pub unsafe extern "C" fn dc_prepare_msg( chat_id: libc::uint32_t, msg: *mut dc_msg::dc_msg_t, ) -> libc::uint32_t { + assert!(!context.is_null()); + let context = &*context; + dc_chat::dc_prepare_msg(context, chat_id, msg) } @@ -234,6 +325,9 @@ pub unsafe extern "C" fn dc_send_msg( chat_id: libc::uint32_t, msg: *mut dc_msg::dc_msg_t, ) -> libc::uint32_t { + assert!(!context.is_null()); + let context = &*context; + dc_chat::dc_send_msg(context, chat_id, msg) } @@ -243,6 +337,9 @@ pub unsafe extern "C" fn dc_send_text_msg( chat_id: libc::uint32_t, text_to_send: *mut libc::c_char, ) -> libc::uint32_t { + assert!(!context.is_null()); + let context = &*context; + dc_chat::dc_send_text_msg(context, chat_id, text_to_send) } @@ -252,14 +349,20 @@ pub unsafe extern "C" fn dc_set_draft( chat_id: libc::uint32_t, msg: *mut dc_msg::dc_msg_t, ) { + assert!(!context.is_null()); + let context = &*context; + dc_chat::dc_set_draft(context, chat_id, msg) } #[no_mangle] -pub unsafe extern "C" fn dc_get_draft( +pub unsafe extern "C" fn dc_get_draft<'a>( context: *mut dc_context::dc_context_t, chat_id: libc::uint32_t, -) -> *mut dc_msg::dc_msg_t { +) -> *mut dc_msg::dc_msg_t<'a> { + assert!(!context.is_null()); + let context = &*context; + dc_chat::dc_get_draft(context, chat_id) } @@ -270,6 +373,9 @@ pub unsafe extern "C" fn dc_get_chat_msgs( flags: libc::uint32_t, marker1before: libc::uint32_t, ) -> *mut dc_array::dc_array_t { + assert!(!context.is_null()); + let context = &*context; + dc_chat::dc_get_chat_msgs(context, chat_id, flags, marker1before) } @@ -278,6 +384,9 @@ pub unsafe extern "C" fn dc_get_msg_cnt( context: *mut dc_context::dc_context_t, chat_id: libc::uint32_t, ) -> libc::c_int { + assert!(!context.is_null()); + let context = &*context; + dc_chat::dc_get_msg_cnt(context, chat_id) } @@ -286,6 +395,9 @@ pub unsafe extern "C" fn dc_get_fresh_msg_cnt( context: *mut dc_context::dc_context_t, chat_id: libc::uint32_t, ) -> libc::c_int { + assert!(!context.is_null()); + let context = &*context; + dc_chat::dc_get_fresh_msg_cnt(context, chat_id) } @@ -293,6 +405,9 @@ pub unsafe extern "C" fn dc_get_fresh_msg_cnt( pub unsafe extern "C" fn dc_get_fresh_msgs( context: *mut dc_context::dc_context_t, ) -> *mut dc_array::dc_array_t { + assert!(!context.is_null()); + let context = &*context; + dc_context::dc_get_fresh_msgs(context) } @@ -301,11 +416,17 @@ pub unsafe extern "C" fn dc_marknoticed_chat( context: *mut dc_context::dc_context_t, chat_id: libc::uint32_t, ) { + assert!(!context.is_null()); + let context = &*context; + dc_chat::dc_marknoticed_chat(context, chat_id) } #[no_mangle] pub unsafe extern "C" fn dc_marknoticed_all_chats(context: *mut dc_context::dc_context_t) { + assert!(!context.is_null()); + let context = &*context; + dc_chat::dc_marknoticed_all_chats(context) } @@ -317,6 +438,9 @@ pub unsafe extern "C" fn dc_get_chat_media( or_msg_type2: libc::c_int, or_msg_type3: libc::c_int, ) -> *mut dc_array::dc_array_t { + assert!(!context.is_null()); + let context = &*context; + dc_chat::dc_get_chat_media(context, chat_id, msg_type, or_msg_type2, or_msg_type3) } @@ -329,6 +453,9 @@ pub unsafe extern "C" fn dc_get_next_media( or_msg_type2: libc::c_int, or_msg_type3: libc::c_int, ) -> libc::uint32_t { + assert!(!context.is_null()); + let context = &*context; + dc_chat::dc_get_next_media(context, msg_id, dir, msg_type, or_msg_type2, or_msg_type3) } @@ -338,6 +465,9 @@ pub unsafe extern "C" fn dc_archive_chat( chat_id: libc::uint32_t, archive: libc::c_int, ) { + assert!(!context.is_null()); + let context = &*context; + dc_chat::dc_archive_chat(context, chat_id, archive) } @@ -346,6 +476,9 @@ pub unsafe extern "C" fn dc_delete_chat( context: *mut dc_context::dc_context_t, chat_id: libc::uint32_t, ) { + assert!(!context.is_null()); + let context = &*context; + dc_chat::dc_delete_chat(context, chat_id) } @@ -354,6 +487,9 @@ pub unsafe extern "C" fn dc_get_chat_contacts( context: *mut dc_context::dc_context_t, chat_id: libc::uint32_t, ) -> *mut dc_array::dc_array_t { + assert!(!context.is_null()); + let context = &*context; + dc_chat::dc_get_chat_contacts(context, chat_id) } @@ -363,14 +499,20 @@ pub unsafe extern "C" fn dc_search_msgs( chat_id: libc::uint32_t, query: *mut libc::c_char, ) -> *mut dc_array::dc_array_t { + assert!(!context.is_null()); + let context = &*context; + dc_context::dc_search_msgs(context, chat_id, query) } #[no_mangle] -pub unsafe extern "C" fn dc_get_chat( +pub unsafe extern "C" fn dc_get_chat<'a>( context: *mut dc_context::dc_context_t, chat_id: libc::uint32_t, -) -> *mut dc_chat::dc_chat_t { +) -> *mut dc_chat::dc_chat_t<'a> { + assert!(!context.is_null()); + let context = &*context; + dc_chat::dc_get_chat(context, chat_id) } @@ -380,6 +522,9 @@ pub unsafe extern "C" fn dc_create_group_chat( verified: libc::c_int, name: *mut libc::c_char, ) -> libc::uint32_t { + assert!(!context.is_null()); + let context = &*context; + dc_chat::dc_create_group_chat(context, verified, name) } @@ -389,6 +534,9 @@ pub unsafe extern "C" fn dc_is_contact_in_chat( chat_id: libc::uint32_t, contact_id: libc::uint32_t, ) -> libc::c_int { + assert!(!context.is_null()); + let context = &*context; + dc_chat::dc_is_contact_in_chat(context, chat_id, contact_id) } @@ -398,6 +546,9 @@ pub unsafe extern "C" fn dc_add_contact_to_chat( chat_id: libc::uint32_t, contact_id: libc::uint32_t, ) -> libc::c_int { + assert!(!context.is_null()); + let context = &*context; + dc_chat::dc_add_contact_to_chat(context, chat_id, contact_id) } @@ -407,6 +558,9 @@ pub unsafe extern "C" fn dc_remove_contact_from_chat( chat_id: libc::uint32_t, contact_id: libc::uint32_t, ) -> libc::c_int { + assert!(!context.is_null()); + let context = &*context; + dc_chat::dc_remove_contact_from_chat(context, chat_id, contact_id) } @@ -416,6 +570,9 @@ pub unsafe extern "C" fn dc_set_chat_name( chat_id: libc::uint32_t, name: *mut libc::c_char, ) -> libc::c_int { + assert!(!context.is_null()); + let context = &*context; + dc_chat::dc_set_chat_name(context, chat_id, name) } @@ -425,6 +582,9 @@ pub unsafe extern "C" fn dc_set_chat_profile_image( chat_id: libc::uint32_t, image: *mut libc::c_char, ) -> libc::c_int { + assert!(!context.is_null()); + let context = &*context; + dc_chat::dc_set_chat_profile_image(context, chat_id, image) } @@ -433,6 +593,9 @@ pub unsafe extern "C" fn dc_get_msg_info( context: *mut dc_context::dc_context_t, msg_id: libc::uint32_t, ) -> *mut libc::c_char { + assert!(!context.is_null()); + let context = &*context; + dc_msg::dc_get_msg_info(context, msg_id) } @@ -441,6 +604,9 @@ pub unsafe extern "C" fn dc_get_mime_headers( context: *mut dc_context::dc_context_t, msg_id: libc::uint32_t, ) -> *mut libc::c_char { + assert!(!context.is_null()); + let context = &*context; + dc_msg::dc_get_mime_headers(context, msg_id) } @@ -450,6 +616,9 @@ pub unsafe extern "C" fn dc_delete_msgs( msg_ids: *const libc::uint32_t, msg_cnt: libc::c_int, ) { + assert!(!context.is_null()); + let context = &*context; + dc_msg::dc_delete_msgs(context, msg_ids, msg_cnt) } @@ -460,6 +629,9 @@ pub unsafe extern "C" fn dc_forward_msgs( msg_cnt: libc::c_int, chat_id: libc::uint32_t, ) { + assert!(!context.is_null()); + let context = &*context; + dc_chat::dc_forward_msgs(context, msg_ids, msg_cnt, chat_id) } @@ -468,6 +640,9 @@ pub unsafe extern "C" fn dc_marknoticed_contact( context: *mut dc_context::dc_context_t, contact_id: libc::uint32_t, ) { + assert!(!context.is_null()); + let context = &*context; + dc_contact::dc_marknoticed_contact(context, contact_id) } @@ -477,6 +652,9 @@ pub unsafe extern "C" fn dc_markseen_msgs( msg_ids: *const libc::uint32_t, msg_cnt: libc::c_int, ) { + assert!(!context.is_null()); + let context = &*context; + dc_msg::dc_markseen_msgs(context, msg_ids, msg_cnt) } @@ -487,14 +665,20 @@ pub unsafe extern "C" fn dc_star_msgs( msg_cnt: libc::c_int, star: libc::c_int, ) { + assert!(!context.is_null()); + let context = &*context; + dc_msg::dc_star_msgs(context, msg_ids, msg_cnt, star) } #[no_mangle] -pub unsafe extern "C" fn dc_get_msg( +pub unsafe extern "C" fn dc_get_msg<'a>( context: *mut dc_context::dc_context_t, msg_id: libc::uint32_t, -) -> *mut dc_msg::dc_msg_t { +) -> *mut dc_msg::dc_msg_t<'a> { + assert!(!context.is_null()); + let context = &*context; + dc_msg::dc_get_msg(context, msg_id) } @@ -508,6 +692,9 @@ pub unsafe extern "C" fn dc_lookup_contact_id_by_addr( context: *mut dc_context::dc_context_t, addr: *mut libc::c_char, ) -> libc::uint32_t { + assert!(!context.is_null()); + let context = &*context; + dc_contact::dc_lookup_contact_id_by_addr(context, addr) } @@ -517,6 +704,9 @@ pub unsafe extern "C" fn dc_create_contact( name: *mut libc::c_char, addr: *mut libc::c_char, ) -> libc::uint32_t { + assert!(!context.is_null()); + let context = &*context; + dc_contact::dc_create_contact(context, name, addr) } @@ -525,6 +715,9 @@ pub unsafe extern "C" fn dc_add_address_book( context: *mut dc_context::dc_context_t, addr_book: *mut libc::c_char, ) -> libc::c_int { + assert!(!context.is_null()); + let context = &*context; + dc_contact::dc_add_address_book(context, addr_book) } @@ -534,11 +727,17 @@ pub unsafe extern "C" fn dc_get_contacts( flags: libc::uint32_t, query: *mut libc::c_char, ) -> *mut dc_array::dc_array_t { + assert!(!context.is_null()); + let context = &*context; + dc_contact::dc_get_contacts(context, flags, query) } #[no_mangle] pub unsafe extern "C" fn dc_get_blocked_cnt(context: *mut dc_context::dc_context_t) -> libc::c_int { + assert!(!context.is_null()); + let context = &*context; + dc_contact::dc_get_blocked_cnt(context) } @@ -546,6 +745,9 @@ pub unsafe extern "C" fn dc_get_blocked_cnt(context: *mut dc_context::dc_context pub unsafe extern "C" fn dc_get_blocked_contacts( context: *mut dc_context::dc_context_t, ) -> *mut dc_array::dc_array_t { + assert!(!context.is_null()); + let context = &*context; + dc_contact::dc_get_blocked_contacts(context) } @@ -555,6 +757,9 @@ pub unsafe extern "C" fn dc_block_contact( contact_id: libc::uint32_t, block: libc::c_int, ) { + assert!(!context.is_null()); + let context = &*context; + dc_contact::dc_block_contact(context, contact_id, block) } @@ -563,6 +768,9 @@ pub unsafe extern "C" fn dc_get_contact_encrinfo( context: *mut dc_context::dc_context_t, contact_id: libc::uint32_t, ) -> *mut libc::c_char { + assert!(!context.is_null()); + let context = &*context; + dc_contact::dc_get_contact_encrinfo(context, contact_id) } @@ -571,14 +779,20 @@ pub unsafe extern "C" fn dc_delete_contact( context: *mut dc_context::dc_context_t, contact_id: libc::uint32_t, ) -> libc::c_int { + assert!(!context.is_null()); + let context = &*context; + dc_contact::dc_delete_contact(context, contact_id) } #[no_mangle] -pub unsafe extern "C" fn dc_get_contact( +pub unsafe extern "C" fn dc_get_contact<'a>( context: *mut dc_context::dc_context_t, contact_id: libc::uint32_t, -) -> *mut dc_contact::dc_contact_t { +) -> *mut dc_contact::dc_contact_t<'a> { + assert!(!context.is_null()); + let context = &*context; + dc_contact::dc_get_contact(context, contact_id) } @@ -589,6 +803,9 @@ pub unsafe extern "C" fn dc_imex( param1: *mut libc::c_char, param2: *mut libc::c_char, ) { + assert!(!context.is_null()); + let context = &*context; + dc_imex::dc_imex(context, what, param1, param2) } @@ -597,6 +814,9 @@ pub unsafe extern "C" fn dc_imex_has_backup( context: *mut dc_context::dc_context_t, dir: *mut libc::c_char, ) -> *mut libc::c_char { + assert!(!context.is_null()); + let context = &*context; + dc_imex::dc_imex_has_backup(context, dir) } @@ -604,6 +824,9 @@ pub unsafe extern "C" fn dc_imex_has_backup( pub unsafe extern "C" fn dc_initiate_key_transfer( context: *mut dc_context::dc_context_t, ) -> *mut libc::c_char { + assert!(!context.is_null()); + let context = &*context; + dc_imex::dc_initiate_key_transfer(context) } @@ -613,11 +836,17 @@ pub unsafe extern "C" fn dc_continue_key_transfer( msg_id: libc::uint32_t, setup_code: *mut libc::c_char, ) -> libc::c_int { + assert!(!context.is_null()); + let context = &*context; + dc_imex::dc_continue_key_transfer(context, msg_id, setup_code) } #[no_mangle] pub unsafe extern "C" fn dc_stop_ongoing_process(context: *mut dc_context::dc_context_t) { + assert!(!context.is_null()); + let context = &*context; + dc_configure::dc_stop_ongoing_process(context) } @@ -626,6 +855,9 @@ pub unsafe extern "C" fn dc_check_qr( context: *mut dc_context::dc_context_t, qr: *mut libc::c_char, ) -> *mut dc_lot::dc_lot_t { + assert!(!context.is_null()); + let context = &*context; + dc_qr::dc_check_qr(context, qr) } @@ -634,6 +866,9 @@ pub unsafe extern "C" fn dc_get_securejoin_qr( context: *mut dc_context::dc_context_t, chat_id: libc::uint32_t, ) -> *mut libc::c_char { + assert!(!context.is_null()); + let context = &*context; + dc_securejoin::dc_get_securejoin_qr(context, chat_id) } @@ -642,6 +877,9 @@ pub unsafe extern "C" fn dc_join_securejoin( context: *mut dc_context::dc_context_t, qr: *mut libc::c_char, ) -> libc::uint32_t { + assert!(!context.is_null()); + let context = &*context; + dc_securejoin::dc_join_securejoin(context, qr) } @@ -651,6 +889,9 @@ pub unsafe extern "C" fn dc_send_locations_to_chat( chat_id: libc::uint32_t, seconds: libc::c_int, ) { + assert!(!context.is_null()); + let context = &*context; + dc_location::dc_send_locations_to_chat(context, chat_id, seconds) } @@ -659,6 +900,9 @@ pub unsafe extern "C" fn dc_is_sending_locations_to_chat( context: *mut dc_context::dc_context_t, chat_id: libc::uint32_t, ) -> libc::c_int { + assert!(!context.is_null()); + let context = &*context; + dc_location::dc_is_sending_locations_to_chat(context, chat_id) } @@ -669,6 +913,9 @@ pub unsafe extern "C" fn dc_set_location( longitude: libc::c_double, accuracy: libc::c_double, ) -> libc::c_int { + assert!(!context.is_null()); + let context = &*context; + dc_location::dc_set_location(context, latitude, longitude, accuracy) } @@ -680,11 +927,17 @@ pub unsafe extern "C" fn dc_get_locations( timestamp_begin: libc::time_t, timestamp_end: libc::time_t, ) -> *mut dc_array::dc_array_t { + assert!(!context.is_null()); + let context = &*context; + dc_location::dc_get_locations(context, chat_id, contact_id, timestamp_begin, timestamp_end) } #[no_mangle] pub unsafe extern "C" fn dc_delete_all_locations(context: *mut dc_context::dc_context_t) { + assert!(!context.is_null()); + let context = &*context; + dc_location::dc_delete_all_locations(context) } @@ -809,7 +1062,7 @@ pub unsafe extern "C" fn dc_array_get_raw(array: *const dc_array_t) -> *const li // dc_chatlist_t #[no_mangle] -pub type dc_chatlist_t = dc_chatlist::dc_chatlist_t; +pub type dc_chatlist_t<'a> = dc_chatlist::dc_chatlist_t<'a>; #[no_mangle] pub unsafe extern "C" fn dc_chatlist_unref(chatlist: *mut dc_chatlist::dc_chatlist_t) { @@ -840,10 +1093,10 @@ pub unsafe extern "C" fn dc_chatlist_get_msg_id( } #[no_mangle] -pub unsafe extern "C" fn dc_chatlist_get_summary( - chatlist: *mut dc_chatlist::dc_chatlist_t, +pub unsafe extern "C" fn dc_chatlist_get_summary<'a>( + chatlist: *mut dc_chatlist::dc_chatlist_t<'a>, index: libc::size_t, - chat: *mut dc_chat::dc_chat_t, + chat: *mut dc_chat::dc_chat_t<'a>, ) -> *mut dc_lot::dc_lot_t { dc_chatlist::dc_chatlist_get_summary(chatlist, index, chat) } @@ -851,14 +1104,15 @@ pub unsafe extern "C" fn dc_chatlist_get_summary( #[no_mangle] pub unsafe extern "C" fn dc_chatlist_get_context( chatlist: *mut dc_chatlist::dc_chatlist_t, -) -> *mut dc_context::dc_context_t { - dc_chatlist::dc_chatlist_get_context(chatlist) +) -> *const dc_context::dc_context_t { + assert!(!chatlist.is_null()); + (*chatlist).context as *const _ } // dc_chat_t #[no_mangle] -pub type dc_chat_t = dc_chat::dc_chat_t; +pub type dc_chat_t<'a> = dc_chat::dc_chat_t<'a>; #[no_mangle] pub unsafe extern "C" fn dc_chat_unref(chat: *mut dc_chat::dc_chat_t) { @@ -927,13 +1181,16 @@ pub unsafe extern "C" fn dc_chat_is_sending_locations( // dc_msg_t #[no_mangle] -pub type dc_msg_t = dc_msg::dc_msg_t; +pub type dc_msg_t<'a> = dc_msg::dc_msg_t<'a>; #[no_mangle] -pub unsafe extern "C" fn dc_msg_new( +pub unsafe extern "C" fn dc_msg_new<'a>( context: *mut dc_context::dc_context_t, viewtype: libc::c_int, -) -> *mut dc_msg::dc_msg_t { +) -> *mut dc_msg::dc_msg_t<'a> { + assert!(!context.is_null()); + let context = &*context; + dc_msg::dc_msg_new(context, viewtype) } @@ -1145,7 +1402,7 @@ pub unsafe extern "C" fn dc_msg_latefiling_mediasize( // dc_contact_t #[no_mangle] -pub type dc_contact_t = dc_contact::dc_contact_t; +pub type dc_contact_t<'a> = dc_contact::dc_contact_t<'a>; #[no_mangle] pub unsafe extern "C" fn dc_contact_unref(contact: *mut dc_contact::dc_contact_t) { diff --git a/examples/repl/cmdline.rs b/examples/repl/cmdline.rs index 6abd069e1..bec3bae92 100644 --- a/examples/repl/cmdline.rs +++ b/examples/repl/cmdline.rs @@ -1,4 +1,5 @@ -use std::ffi::CString; +use std::ffi::{CStr, CString}; +use std::sync::{Arc, RwLock}; use deltachat::constants::*; use deltachat::dc_aheader::*; @@ -45,7 +46,6 @@ use deltachat::dc_token::*; use deltachat::dc_tools::*; use deltachat::types::*; use deltachat::x::*; -use libc; use num_traits::FromPrimitive; /* @@ -55,14 +55,7 @@ use num_traits::FromPrimitive; * * e.g. bitmask 7 triggers actions definded with bits 1, 2 and 4. */ -#[no_mangle] -pub unsafe extern "C" fn dc_reset_tables( - mut context: *mut dc_context_t, - mut bits: libc::c_int, -) -> libc::c_int { - if context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint { - return 0i32; - } +pub unsafe fn dc_reset_tables(mut context: &dc_context_t, mut bits: libc::c_int) -> libc::c_int { dc_log_info( context, 0i32, @@ -71,7 +64,8 @@ pub unsafe extern "C" fn dc_reset_tables( ); if 0 != bits & 1i32 { dc_sqlite3_execute( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"DELETE FROM jobs;\x00" as *const u8 as *const libc::c_char, ); dc_log_info( @@ -82,7 +76,8 @@ pub unsafe extern "C" fn dc_reset_tables( } if 0 != bits & 2i32 { dc_sqlite3_execute( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"DELETE FROM acpeerstates;\x00" as *const u8 as *const libc::c_char, ); dc_log_info( @@ -93,7 +88,8 @@ pub unsafe extern "C" fn dc_reset_tables( } if 0 != bits & 4i32 { dc_sqlite3_execute( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"DELETE FROM keypairs;\x00" as *const u8 as *const libc::c_char, ); dc_log_info( @@ -104,28 +100,34 @@ pub unsafe extern "C" fn dc_reset_tables( } if 0 != bits & 8i32 { dc_sqlite3_execute( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"DELETE FROM contacts WHERE id>9;\x00" as *const u8 as *const libc::c_char, ); dc_sqlite3_execute( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"DELETE FROM chats WHERE id>9;\x00" as *const u8 as *const libc::c_char, ); dc_sqlite3_execute( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"DELETE FROM chats_contacts;\x00" as *const u8 as *const libc::c_char, ); dc_sqlite3_execute( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"DELETE FROM msgs WHERE id>9;\x00" as *const u8 as *const libc::c_char, ); dc_sqlite3_execute( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"DELETE FROM config WHERE keyname LIKE \'imap.%\' OR keyname LIKE \'configured%\';\x00" as *const u8 as *const libc::c_char, ); dc_sqlite3_execute( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"DELETE FROM leftgrps;\x00" as *const u8 as *const libc::c_char, ); dc_log_info( @@ -134,7 +136,7 @@ pub unsafe extern "C" fn dc_reset_tables( b"(8) Rest but server config reset.\x00" as *const u8 as *const libc::c_char, ); } - ((*context).cb)( + (context.cb)( context, Event::MSGS_CHANGED, 0i32 as uintptr_t, @@ -142,41 +144,14 @@ pub unsafe extern "C" fn dc_reset_tables( ); return 1i32; } -/* - * Clean up the contacts table. This function is called from Core cmdline. - * - * All contacts not involved in a chat, not blocked and not being a deaddrop - * are removed. - * - * Deleted contacts from the OS address book normally stay in the contacts - * database. With this cleanup, they are also removed, as well as all - * auto-added contacts, unless they are used in a chat or for blocking purpose. - */ -unsafe extern "C" fn dc_cleanup_contacts(mut context: *mut dc_context_t) -> libc::c_int { - if context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint { - return 0i32; - } - dc_log_info( - context, - 0i32, - b"Cleaning up contacts ...\x00" as *const u8 as *const libc::c_char, - ); - dc_sqlite3_execute((*context).sql, - b"DELETE FROM contacts WHERE id>9 AND blocked=0 AND NOT EXISTS (SELECT contact_id FROM chats_contacts where contacts.id = chats_contacts.contact_id) AND NOT EXISTS (select from_id from msgs WHERE msgs.from_id = contacts.id);\x00" - as *const u8 as *const libc::c_char); - return 1i32; -} -unsafe extern "C" fn dc_poke_eml_file( - mut context: *mut dc_context_t, +unsafe fn dc_poke_eml_file( + mut context: &dc_context_t, mut filename: *const libc::c_char, ) -> libc::c_int { /* mainly for testing, may be called by dc_import_spec() */ let mut success: libc::c_int = 0i32; let mut data: *mut libc::c_char = 0 as *mut libc::c_char; let mut data_bytes: size_t = 0; - if context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint { - return 0i32; - } if !(dc_read_file( context, filename, @@ -197,43 +172,6 @@ unsafe extern "C" fn dc_poke_eml_file( free(data as *mut libc::c_void); return success; } -unsafe extern "C" fn poke_public_key( - mut context: *mut dc_context_t, - mut addr: *const libc::c_char, - mut public_key_file: *const libc::c_char, -) -> libc::c_int { - /* mainly for testing: if the partner does not support Autocrypt, - encryption is disabled as soon as the first messages comes from the partner */ - let mut header: *mut dc_aheader_t = dc_aheader_new(); - let mut peerstate: *mut dc_apeerstate_t = dc_apeerstate_new(context); - let mut success: libc::c_int = 0i32; - if !(addr.is_null() || public_key_file.is_null() || peerstate.is_null() || header.is_null()) { - (*header).addr = dc_strdup(addr); - (*header).prefer_encrypt = 1i32; - if 0 == dc_key_set_from_file((*header).public_key, public_key_file, context) - || 0 == dc_pgp_is_valid_key(context, (*header).public_key) - { - dc_log_warning( - context, - 0i32, - b"No valid key found in \"%s\".\x00" as *const u8 as *const libc::c_char, - public_key_file, - ); - } else { - if 0 != dc_apeerstate_load_by_addr(peerstate, (*context).sql, addr) { - dc_apeerstate_apply_header(peerstate, header, time(0 as *mut time_t)); - dc_apeerstate_save_to_db(peerstate, (*context).sql, 0i32); - } else { - dc_apeerstate_init_from_header(peerstate, header, time(0 as *mut time_t)); - dc_apeerstate_save_to_db(peerstate, (*context).sql, 1i32); - } - success = 1i32 - } - } - dc_apeerstate_unref(peerstate); - dc_aheader_unref(header); - return success; -} /* * * Import a file to the database. * For testing, import a folder with eml-files, a single eml-file, e-mail plus public key and so on. @@ -244,22 +182,16 @@ unsafe extern "C" fn poke_public_key( * @param spec The file or directory to import. NULL for the last command. * @return 1=success, 0=error. */ -unsafe extern "C" fn poke_spec( - mut context: *mut dc_context_t, - mut spec: *const libc::c_char, -) -> libc::c_int { +unsafe fn poke_spec(mut context: &dc_context_t, mut spec: *const libc::c_char) -> libc::c_int { let mut current_block: u64; let mut success: libc::c_int = 0i32; let mut real_spec: *mut libc::c_char = 0 as *mut libc::c_char; let mut suffix: *mut libc::c_char = 0 as *mut libc::c_char; let mut dir: *mut DIR = 0 as *mut DIR; - let mut dir_entry: *mut dirent = 0 as *mut dirent; + let mut dir_entry: *mut dirent; let mut read_cnt: libc::c_int = 0i32; - let mut name: *mut libc::c_char = 0 as *mut libc::c_char; - if context.is_null() { - return 0i32; - } - if 0 == dc_sqlite3_is_open((*context).sql) { + let mut name: *mut libc::c_char; + if 0 == dc_sqlite3_is_open(&context.sql.clone().read().unwrap()) { dc_log_error( context, 0i32, @@ -270,14 +202,16 @@ unsafe extern "C" fn poke_spec( if !spec.is_null() { real_spec = dc_strdup(spec); dc_sqlite3_set_config( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"import_spec\x00" as *const u8 as *const libc::c_char, real_spec, ); current_block = 7149356873433890176; } else { real_spec = dc_sqlite3_get_config( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"import_spec\x00" as *const u8 as *const libc::c_char, 0 as *const libc::c_char, ); @@ -303,28 +237,6 @@ unsafe extern "C" fn poke_spec( read_cnt += 1 } current_block = 1622411330066726685; - } else if !suffix.is_null() - && (strcmp(suffix, b"pem\x00" as *const u8 as *const libc::c_char) == 0i32 - || strcmp(suffix, b"asc\x00" as *const u8 as *const libc::c_char) == 0i32) - { - /* import a publix key */ - let mut separator: *mut libc::c_char = strchr(real_spec, ' ' as i32); - if separator.is_null() { - dc_log_error( - context, - 0i32, - b"Import: Key files must be specified as \" \".\x00" - as *const u8 as *const libc::c_char, - ); - current_block = 8522321847195001863; - } else { - *separator = 0i32 as libc::c_char; - if 0 != poke_public_key(context, real_spec, separator.offset(1isize)) { - read_cnt += 1 - } - *separator = ' ' as i32 as libc::c_char; - current_block = 1622411330066726685; - } } else { /* import a directory */ dir = opendir(real_spec); @@ -382,7 +294,7 @@ unsafe extern "C" fn poke_spec( real_spec, ); if read_cnt > 0i32 { - ((*context).cb)( + (context.cb)( context, Event::MSGS_CHANGED, 0i32 as uintptr_t, @@ -402,8 +314,8 @@ unsafe extern "C" fn poke_spec( free(suffix as *mut libc::c_void); return success; } -unsafe extern "C" fn log_msg( - mut context: *mut dc_context_t, +unsafe fn log_msg( + mut context: &dc_context_t, mut prefix: *const libc::c_char, mut msg: *mut dc_msg_t, ) { @@ -466,11 +378,10 @@ unsafe extern "C" fn log_msg( free(contact_name as *mut libc::c_void); dc_contact_unref(contact); } -unsafe extern "C" fn log_msglist(mut context: *mut dc_context_t, mut msglist: *mut dc_array_t) { +unsafe fn log_msglist(mut context: &dc_context_t, mut msglist: *mut dc_array_t) { let mut i: libc::c_int = 0; let mut cnt: libc::c_int = dc_array_get_cnt(msglist) as libc::c_int; let mut lines_out: libc::c_int = 0i32; - i = 0i32; while i < cnt { let mut msg_id: uint32_t = dc_array_get_id(msglist, i as size_t); if msg_id == 9i32 as libc::c_uint { @@ -500,11 +411,8 @@ unsafe extern "C" fn log_msglist(mut context: *mut dc_context_t, mut msglist: *m ); }; } -unsafe extern "C" fn log_contactlist( - mut context: *mut dc_context_t, - mut contacts: *mut dc_array_t, -) { - let mut contact: *mut dc_contact_t = 0 as *mut dc_contact_t; +unsafe fn log_contactlist(mut context: &dc_context_t, mut contacts: *mut dc_array_t) { + let mut contact: *mut dc_contact_t; let mut peerstate: *mut dc_apeerstate_t = dc_apeerstate_new(context); if 0 == dc_array_search_id(contacts, 1i32 as uint32_t, 0 as *mut size_t) { dc_array_add_id(contacts, 1i32 as uint32_t); @@ -512,7 +420,7 @@ unsafe extern "C" fn log_contactlist( let mut i = 0; while i < dc_array_get_cnt(contacts) { let mut contact_id: uint32_t = dc_array_get_id(contacts, i as size_t); - let mut line: *mut libc::c_char = 0 as *mut libc::c_char; + let mut line: *mut libc::c_char; let mut line2: *mut libc::c_char = 0 as *mut libc::c_char; contact = dc_get_contact(context, contact_id); if !contact.is_null() { @@ -543,9 +451,9 @@ unsafe extern "C" fn log_contactlist( }, ); let mut peerstate_ok: libc::c_int = - dc_apeerstate_load_by_addr(peerstate, (*context).sql, addr); + dc_apeerstate_load_by_addr(peerstate, &context.sql.clone().read().unwrap(), addr); if 0 != peerstate_ok && contact_id != 1i32 as libc::c_uint { - let mut pe: *mut libc::c_char = 0 as *mut libc::c_char; + let mut pe: *mut libc::c_char; match (*peerstate).prefer_encrypt { 1 => pe = dc_strdup(b"mutual\x00" as *const u8 as *const libc::c_char), 0 => pe = dc_strdup(b"no-preference\x00" as *const u8 as *const libc::c_char), @@ -586,11 +494,11 @@ unsafe extern "C" fn log_contactlist( dc_apeerstate_unref(peerstate); } static mut s_is_auth: libc::c_int = 0i32; -#[no_mangle] -pub unsafe extern "C" fn dc_cmdline_skip_auth() { + +pub unsafe fn dc_cmdline_skip_auth() { s_is_auth = 1i32; } -unsafe extern "C" fn chat_prefix(mut chat: *const dc_chat_t) -> *const libc::c_char { +unsafe fn chat_prefix(mut chat: *const dc_chat_t) -> *const libc::c_char { if (*chat).type_0 == 120i32 { return b"Group\x00" as *const u8 as *const libc::c_char; } else if (*chat).type_0 == 130i32 { @@ -599,455 +507,540 @@ unsafe extern "C" fn chat_prefix(mut chat: *const dc_chat_t) -> *const libc::c_c return b"Single\x00" as *const u8 as *const libc::c_char; }; } -#[no_mangle] -pub unsafe extern "C" fn dc_cmdline( - mut context: *mut dc_context_t, - cmdline: &str, -) -> *mut libc::c_char { - let mut cmd: *mut libc::c_char = 0 as *mut libc::c_char; - let mut arg1: *mut libc::c_char = 0 as *mut libc::c_char; + +pub unsafe fn dc_cmdline(context: &dc_context_t, cmdline: &str) -> *mut libc::c_char { let mut ret: *mut libc::c_char = 1i32 as *mut libc::c_char; - let mut sel_chat: *mut dc_chat_t = 0 as *mut dc_chat_t; - if !context.is_null() { - if 0 != (*context).cmdline_sel_chat_id { - sel_chat = dc_get_chat(context, (*context).cmdline_sel_chat_id) - } - cmd = dc_strdup(CString::new(cmdline).unwrap().as_ptr()); - arg1 = strchr(cmd, ' ' as i32); - if !arg1.is_null() { - *arg1 = 0i32 as libc::c_char; - arg1 = arg1.offset(1isize) - } - if strcmp(cmd, b"help\x00" as *const u8 as *const libc::c_char) == 0i32 - || strcmp(cmd, b"?\x00" as *const u8 as *const libc::c_char) == 0i32 - { - if !arg1.is_null() - && strcmp(arg1, b"imex\x00" as *const u8 as *const libc::c_char) == 0i32 - { - ret = + let chat_id = *context.cmdline_sel_chat_id.read().unwrap(); + + let mut sel_chat = if chat_id > 0 { + dc_get_chat(context, chat_id) + } else { + std::ptr::null_mut() + }; + + let mut args = cmdline.split_whitespace(); + let arg0 = args.next().unwrap_or_default(); + let cmd = dc_strdup(CString::new(arg0).unwrap().as_ptr()); + + let arg1 = args.next().unwrap_or_default(); + let arg1_c = CString::new(arg1).unwrap(); + let arg2 = args.next().unwrap_or_default(); + let arg2_c = CString::new(arg2).unwrap(); + + if cmdline == "help" || cmdline == "?" { + if arg1 == "imex" { + ret = dc_strdup(b"====================Import/Export commands==\ninitiate-key-transfer\nget-setupcodebegin \ncontinue-key-transfer \nhas-backup\nexport-backup\nimport-backup \nexport-keys\nimport-keys\nexport-setup\npoke [|| ]\nreset \nstop\n=============================================\x00" as *const u8 as *const libc::c_char) - } else { - ret = + } else { + ret = dc_strdup(b"==========================Database commands==\ninfo\nopen \nclose\nset []\nget \noauth2\nconfigure\nconnect\ndisconnect\nmaybenetwork\nhousekeeping\nhelp imex (Import/Export)\n==============================Chat commands==\nlistchats []\nlistarchived\nchat [|0]\ncreatechat \ncreatechatbymsg \ncreategroup \ncreateverified \naddmember \nremovemember \ngroupname \ngroupimage []\nchatinfo\nsendlocations \nsetlocation \ndellocations\ngetlocations []\nsend \nsendimage []\nsendfile \ndraft []\nlistmedia\narchive \nunarchive \ndelchat \n===========================Message commands==\nlistmsgs \nmsginfo \nlistfresh\nforward \nmarkseen \nstar \nunstar \ndelmsg \n===========================Contact commands==\nlistcontacts []\nlistverified []\naddcontact [] \ncontactinfo \ndelcontact \ncleanupcontacts\n======================================Misc.==\ngetqr []\ngetbadqr\ncheckqr \nevent \nfileinfo \nclear -- clear screen\nexit\n=============================================\x00" as *const u8 as *const libc::c_char) - } - } else if 0 == s_is_auth { - if strcmp(cmd, b"auth\x00" as *const u8 as *const libc::c_char) == 0i32 { - let mut is_pw: *mut libc::c_char = - dc_get_config(context, b"mail_pw\x00" as *const u8 as *const libc::c_char); - if strcmp(arg1, is_pw) == 0i32 { - s_is_auth = 1i32; - ret = 2i32 as *mut libc::c_char - } else { - ret = b"Bad password.\x00" as *const u8 as *const libc::c_char - as *mut libc::c_char - } - } else { - ret = dc_strdup( - b"Please authorize yourself using: auth \x00" as *const u8 - as *const libc::c_char, - ) - } - } else if strcmp(cmd, b"auth\x00" as *const u8 as *const libc::c_char) == 0i32 { - ret = dc_strdup(b"Already authorized.\x00" as *const u8 as *const libc::c_char) - } else if strcmp(cmd, b"open\x00" as *const u8 as *const libc::c_char) == 0i32 { - if !arg1.is_null() { - dc_close(context); - ret = if 0 != dc_open(context, arg1, 0 as *const libc::c_char) { - 2i32 as *mut libc::c_char - } else { - 1i32 as *mut libc::c_char - } - } else { - ret = dc_strdup( - b"ERROR: Argument missing.\x00" as *const u8 as *const libc::c_char, - ) - } - } else if strcmp(cmd, b"close\x00" as *const u8 as *const libc::c_char) == 0i32 { - dc_close(context); - ret = 2i32 as *mut libc::c_char - } else if strcmp( - cmd, - b"initiate-key-transfer\x00" as *const u8 as *const libc::c_char, - ) == 0i32 - { - let mut setup_code: *mut libc::c_char = dc_initiate_key_transfer(context); - ret = if !setup_code.is_null() { - dc_mprintf( - b"Setup code for the transferred setup message: %s\x00" as *const u8 - as *const libc::c_char, - setup_code, - ) - } else { - 1i32 as *mut libc::c_char - }; - free(setup_code as *mut libc::c_void); - } else if strcmp( - cmd, - b"get-setupcodebegin\x00" as *const u8 as *const libc::c_char, - ) == 0i32 - { - if !arg1.is_null() { - let mut msg_id: uint32_t = atoi(arg1) as uint32_t; - let mut msg: *mut dc_msg_t = dc_get_msg(context, msg_id); - if 0 != dc_msg_is_setupmessage(msg) { - let mut setupcodebegin: *mut libc::c_char = dc_msg_get_setupcodebegin(msg); - ret = dc_mprintf( - b"The setup code for setup message Msg#%i starts with: %s\x00" as *const u8 - as *const libc::c_char, - msg_id, - setupcodebegin, - ); - free(setupcodebegin as *mut libc::c_void); - } else { - ret = dc_mprintf( - b"ERROR: Msg#%i is no setup message.\x00" as *const u8 - as *const libc::c_char, - msg_id, - ) - } - dc_msg_unref(msg); - } else { - ret = dc_strdup( - b"ERROR: Argument missing.\x00" as *const u8 as *const libc::c_char, - ) - } - } else if strcmp( - cmd, - b"continue-key-transfer\x00" as *const u8 as *const libc::c_char, - ) == 0i32 - { - let mut arg2: *mut libc::c_char = 0 as *mut libc::c_char; - if !arg1.is_null() { - arg2 = strrchr(arg1, ' ' as i32) - } - if !arg1.is_null() && !arg2.is_null() { - *arg2 = 0i32 as libc::c_char; - arg2 = arg2.offset(1isize); - ret = if 0 != dc_continue_key_transfer(context, atoi(arg1) as uint32_t, arg2) { - 2i32 as *mut libc::c_char - } else { - 1i32 as *mut libc::c_char - } - } else { - ret = dc_strdup( - b"ERROR: Arguments expected.\x00" as *const u8 - as *const libc::c_char, - ) - } - } 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); - if ret.is_null() { - ret = dc_strdup(b"No backup found.\x00" as *const u8 as *const libc::c_char) - } - } else if strcmp( - cmd, - 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); - ret = 2i32 as *mut libc::c_char - } else if strcmp( - cmd, - b"import-backup\x00" as *const u8 as *const libc::c_char, - ) == 0i32 - { - if !arg1.is_null() { - dc_imex(context, 12i32, arg1, 0 as *const libc::c_char); + } + } else if 0 == s_is_auth { + if strcmp(cmd, b"auth\x00" as *const u8 as *const libc::c_char) == 0i32 { + let mut is_pw = + dc_get_config(context, b"mail_pw\x00" as *const u8 as *const libc::c_char); + if arg1 == CStr::from_ptr(is_pw).to_str().unwrap() { + s_is_auth = 1; ret = 2i32 as *mut libc::c_char } else { - ret = dc_strdup( - b"ERROR: Argument missing.\x00" as *const u8 - as *const libc::c_char, - ) + ret = b"Bad password.\x00" as *const u8 as *const libc::c_char as *mut libc::c_char } - } 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); - 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); - 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, - ); - let mut file_content: *mut libc::c_char = 0 as *mut libc::c_char; - file_content = dc_render_setup_file(context, setup_code_0); - if !file_content.is_null() - && 0 != dc_write_file( - context, - file_name, - file_content as *const libc::c_void, - strlen(file_content), - ) - { - ret = dc_mprintf( - b"Setup message written to: %s\nSetup code: %s\x00" as *const u8 - as *const libc::c_char, - file_name, - setup_code_0, - ) - } else { - ret = 1i32 as *mut libc::c_char - } - free(file_content as *mut libc::c_void); - free(file_name as *mut libc::c_void); - free(setup_code_0 as *mut libc::c_void); - } else if strcmp(cmd, b"poke\x00" as *const u8 as *const libc::c_char) == 0i32 { - ret = if 0 != poke_spec(context, arg1) { + } else { + ret = dc_strdup( + b"Please authorize yourself using: auth \x00" as *const u8 + as *const libc::c_char, + ) + } + } else if strcmp(cmd, b"auth\x00" as *const u8 as *const libc::c_char) == 0i32 { + ret = dc_strdup(b"Already authorized.\x00" as *const u8 as *const libc::c_char) + } else if strcmp(cmd, b"open\x00" as *const u8 as *const libc::c_char) == 0i32 { + if !arg1.is_empty() { + dc_close(context); + ret = if 0 != dc_open(context, arg1_c.as_ptr(), 0 as *const libc::c_char) { 2i32 as *mut libc::c_char } else { 1i32 as *mut libc::c_char } - } else if strcmp(cmd, b"reset\x00" as *const u8 as *const libc::c_char) == 0i32 { - if !arg1.is_null() { - let mut bits: libc::c_int = atoi(arg1); - if bits > 15i32 { - ret = dc_strdup( - b"ERROR: must be lower than 16.\x00" as *const u8 - as *const libc::c_char, - ) - } else { - ret = if 0 != dc_reset_tables(context, bits) { - 2i32 as *mut libc::c_char - } else { - 1i32 as *mut libc::c_char - } - } + } else { + ret = dc_strdup( + b"ERROR: Argument missing.\x00" as *const u8 as *const libc::c_char, + ) + } + } else if strcmp(cmd, b"close\x00" as *const u8 as *const libc::c_char) == 0i32 { + dc_close(context); + ret = 2i32 as *mut libc::c_char + } else if strcmp( + cmd, + b"initiate-key-transfer\x00" as *const u8 as *const libc::c_char, + ) == 0i32 + { + let mut setup_code: *mut libc::c_char = dc_initiate_key_transfer(context); + ret = if !setup_code.is_null() { + dc_mprintf( + b"Setup code for the transferred setup message: %s\x00" as *const u8 + as *const libc::c_char, + setup_code, + ) + } else { + 1i32 as *mut libc::c_char + }; + free(setup_code as *mut libc::c_void); + } else if strcmp( + cmd, + b"get-setupcodebegin\x00" as *const u8 as *const libc::c_char, + ) == 0i32 + { + if !arg1.is_empty() { + let mut msg_id: u32 = arg1.parse().unwrap(); + let mut msg: *mut dc_msg_t = dc_get_msg(context, msg_id); + if 0 != dc_msg_is_setupmessage(msg) { + let mut setupcodebegin: *mut libc::c_char = dc_msg_get_setupcodebegin(msg); + ret = dc_mprintf( + b"The setup code for setup message Msg#%i starts with: %s\x00" as *const u8 + as *const libc::c_char, + msg_id, + setupcodebegin, + ); + free(setupcodebegin as *mut libc::c_void); } else { - ret = - dc_strdup(b"ERROR: Argument missing: 1=jobs, 2=peerstates, 4=private keys, 8=rest but server config\x00" - as *const u8 as *const libc::c_char) + ret = dc_mprintf( + b"ERROR: Msg#%i is no setup message.\x00" as *const u8 as *const libc::c_char, + msg_id, + ) } - } else if strcmp(cmd, b"stop\x00" as *const u8 as *const libc::c_char) == 0i32 { - dc_stop_ongoing_process(context); + dc_msg_unref(msg); + } else { + ret = dc_strdup( + b"ERROR: Argument missing.\x00" as *const u8 as *const libc::c_char, + ) + } + } else if strcmp( + cmd, + b"continue-key-transfer\x00" as *const u8 as *const libc::c_char, + ) == 0i32 + { + if !arg1.is_empty() && !arg2.is_empty() { + ret = if 0 != dc_continue_key_transfer(context, arg1.parse().unwrap(), arg2_c.as_ptr()) + { + 2i32 as *mut libc::c_char + } else { + 1i32 as *mut libc::c_char + } + } else { + ret = dc_strdup( + b"ERROR: Arguments expected.\x00" as *const u8 + as *const libc::c_char, + ) + } + } else if strcmp(cmd, b"has-backup\x00" as *const u8 as *const libc::c_char) == 0i32 { + 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) + } + } else if strcmp( + cmd, + b"export-backup\x00" as *const u8 as *const libc::c_char, + ) == 0i32 + { + dc_imex( + context, + 11i32, + context.get_blobdir(), + 0 as *const libc::c_char, + ); + ret = 2i32 as *mut libc::c_char + } else if strcmp( + cmd, + b"import-backup\x00" as *const u8 as *const libc::c_char, + ) == 0i32 + { + if !arg1.is_empty() { + dc_imex(context, 12i32, arg1_c.as_ptr(), 0 as *const libc::c_char); ret = 2i32 as *mut libc::c_char - } else if strcmp(cmd, b"set\x00" as *const u8 as *const libc::c_char) == 0i32 { - if !arg1.is_null() { - let mut arg2_0: *mut libc::c_char = strchr(arg1, ' ' as i32); - if !arg2_0.is_null() { - *arg2_0 = 0i32 as libc::c_char; - arg2_0 = arg2_0.offset(1isize) - } - ret = if 0 != dc_set_config(context, arg1, arg2_0) { + } else { + ret = dc_strdup( + b"ERROR: Argument missing.\x00" as *const u8 as *const libc::c_char, + ) + } + } else if strcmp(cmd, b"export-keys\x00" as *const u8 as *const libc::c_char) == 0i32 { + 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.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.get_blobdir(), + ); + let mut file_content: *mut libc::c_char; + file_content = dc_render_setup_file(context, setup_code_0); + if !file_content.is_null() + && 0 != dc_write_file( + context, + file_name, + file_content as *const libc::c_void, + strlen(file_content), + ) + { + ret = dc_mprintf( + b"Setup message written to: %s\nSetup code: %s\x00" as *const u8 + as *const libc::c_char, + file_name, + setup_code_0, + ) + } else { + ret = 1i32 as *mut libc::c_char + } + free(file_content as *mut libc::c_void); + free(file_name as *mut libc::c_void); + free(setup_code_0 as *mut libc::c_void); + } else if strcmp(cmd, b"poke\x00" as *const u8 as *const libc::c_char) == 0i32 { + ret = if 0 != poke_spec(context, arg1_c.as_ptr()) { + 2i32 as *mut libc::c_char + } else { + 1i32 as *mut libc::c_char + } + } else if strcmp(cmd, b"reset\x00" as *const u8 as *const libc::c_char) == 0i32 { + if !arg1.is_empty() { + let mut bits: libc::c_int = arg1.parse().unwrap(); + if bits > 15i32 { + ret = dc_strdup( + b"ERROR: must be lower than 16.\x00" as *const u8 as *const libc::c_char, + ) + } else { + ret = if 0 != dc_reset_tables(context, bits) { 2i32 as *mut libc::c_char } else { 1i32 as *mut libc::c_char } + } + } else { + ret = + dc_strdup(b"ERROR: Argument missing: 1=jobs, 2=peerstates, 4=private keys, 8=rest but server config\x00" + as *const u8 as *const libc::c_char) + } + } else if strcmp(cmd, b"stop\x00" as *const u8 as *const libc::c_char) == 0i32 { + dc_stop_ongoing_process(context); + ret = 2i32 as *mut libc::c_char + } else if strcmp(cmd, b"set\x00" as *const u8 as *const libc::c_char) == 0i32 { + if !arg1.is_empty() { + ret = if 0 != dc_set_config(context, arg1_c.as_ptr(), arg2_c.as_ptr()) { + 2i32 as *mut libc::c_char } else { - ret = dc_strdup( - b"ERROR: Argument missing.\x00" as *const u8 as *const libc::c_char, - ) + 1i32 as *mut libc::c_char } - } else if strcmp(cmd, b"get\x00" as *const u8 as *const libc::c_char) == 0i32 { - if !arg1.is_null() { - let mut val: *mut libc::c_char = dc_get_config(context, arg1); - ret = dc_mprintf(b"%s=%s\x00" as *const u8 as *const libc::c_char, arg1, val); - free(val as *mut libc::c_void); + } else { + ret = + dc_strdup(b"ERROR: Argument missing.\x00" as *const u8 as *const libc::c_char) + } + } else if strcmp(cmd, b"get\x00" as *const u8 as *const libc::c_char) == 0i32 { + if !arg1.is_empty() { + let mut val: *mut libc::c_char = dc_get_config(context, arg1_c.as_ptr()); + ret = dc_mprintf( + b"%s=%s\x00" as *const u8 as *const libc::c_char, + arg1_c.as_ptr(), + val, + ); + free(val as *mut libc::c_void); + } else { + ret = + dc_strdup(b"ERROR: Argument missing.\x00" as *const u8 as *const libc::c_char) + } + } else if strcmp(cmd, b"info\x00" as *const u8 as *const libc::c_char) == 0i32 { + ret = dc_get_info(context); + if ret.is_null() { + ret = 1i32 as *mut libc::c_char + } + } else if strcmp(cmd, b"maybenetwork\x00" as *const u8 as *const libc::c_char) == 0i32 { + dc_maybe_network(context); + ret = 2i32 as *mut libc::c_char + } else if strcmp(cmd, b"housekeeping\x00" as *const u8 as *const libc::c_char) == 0i32 { + dc_housekeeping(context); + ret = 2i32 as *mut libc::c_char + } else if strcmp(cmd, b"listchats\x00" as *const u8 as *const libc::c_char) == 0i32 + || strcmp(cmd, b"listarchived\x00" as *const u8 as *const libc::c_char) == 0i32 + || strcmp(cmd, b"chats\x00" as *const u8 as *const libc::c_char) == 0i32 + { + let mut listflags: libc::c_int = + if strcmp(cmd, b"listarchived\x00" as *const u8 as *const libc::c_char) == 0i32 { + 0x1i32 } else { - ret = dc_strdup( - b"ERROR: Argument missing.\x00" as *const u8 as *const libc::c_char, - ) - } - } else if strcmp(cmd, b"info\x00" as *const u8 as *const libc::c_char) == 0i32 { - ret = dc_get_info(context); - if ret.is_null() { - ret = 1i32 as *mut libc::c_char - } - } else if strcmp(cmd, b"maybenetwork\x00" as *const u8 as *const libc::c_char) == 0i32 { - dc_maybe_network(context); - ret = 2i32 as *mut libc::c_char - } else if strcmp(cmd, b"housekeeping\x00" as *const u8 as *const libc::c_char) == 0i32 { - dc_housekeeping(context); - ret = 2i32 as *mut libc::c_char - } else if strcmp(cmd, b"listchats\x00" as *const u8 as *const libc::c_char) == 0i32 - || strcmp(cmd, b"listarchived\x00" as *const u8 as *const libc::c_char) == 0i32 - || strcmp(cmd, b"chats\x00" as *const u8 as *const libc::c_char) == 0i32 - { - let mut listflags: libc::c_int = - if strcmp(cmd, b"listarchived\x00" as *const u8 as *const libc::c_char) == 0i32 { - 0x1i32 - } else { - 0i32 - }; - let mut chatlist: *mut dc_chatlist_t = - dc_get_chatlist(context, listflags, arg1, 0i32 as uint32_t); - if !chatlist.is_null() { - let mut i: libc::c_int = 0; - let mut cnt: libc::c_int = dc_chatlist_get_cnt(chatlist) as libc::c_int; - if cnt > 0i32 { - dc_log_info(context, 0i32, + 0i32 + }; + + let mut chatlist: *mut dc_chatlist_t = + dc_get_chatlist(context, listflags, arg1_c.as_ptr(), 0i32 as uint32_t); + if !chatlist.is_null() { + let mut i: libc::c_int; + let mut cnt: libc::c_int = dc_chatlist_get_cnt(chatlist) as libc::c_int; + if cnt > 0i32 { + dc_log_info(context, 0i32, b"================================================================================\x00" as *const u8 as *const libc::c_char); - i = cnt - 1i32; - while i >= 0i32 { - let mut chat: *mut dc_chat_t = - dc_get_chat(context, dc_chatlist_get_chat_id(chatlist, i as size_t)); - let mut temp_subtitle: *mut libc::c_char = dc_chat_get_subtitle(chat); - let mut temp_name: *mut libc::c_char = dc_chat_get_name(chat); - dc_log_info( - context, - 0i32, - b"%s#%i: %s [%s] [%i fresh]\x00" as *const u8 as *const libc::c_char, - chat_prefix(chat), - dc_chat_get_id(chat) as libc::c_int, - temp_name, - temp_subtitle, - dc_get_fresh_msg_cnt(context, dc_chat_get_id(chat)) as libc::c_int, - ); - free(temp_subtitle as *mut libc::c_void); - free(temp_name as *mut libc::c_void); - let mut lot: *mut dc_lot_t = - dc_chatlist_get_summary(chatlist, i as size_t, chat); - let mut statestr: *const libc::c_char = - b"\x00" as *const u8 as *const libc::c_char; - if 0 != dc_chat_get_archived(chat) { - statestr = b" [Archived]\x00" as *const u8 as *const libc::c_char - } else { - match dc_lot_get_state(lot) { - 20 => statestr = b" o\x00" as *const u8 as *const libc::c_char, - 26 => { - statestr = - b" \xe2\x88\x9a\x00" as *const u8 as *const libc::c_char - } - 28 => { - statestr = b" \xe2\x88\x9a\xe2\x88\x9a\x00" as *const u8 - as *const libc::c_char - } - 24 => statestr = b" !!\x00" as *const u8 as *const libc::c_char, - _ => {} - } - } - let mut timestr: *mut libc::c_char = - dc_timestamp_to_str(dc_lot_get_timestamp(lot)); - let mut text1: *mut libc::c_char = dc_lot_get_text1(lot); - let mut text2: *mut libc::c_char = dc_lot_get_text2(lot); - dc_log_info( - context, - 0i32, - b"%s%s%s%s [%s]%s\x00" as *const u8 as *const libc::c_char, - if !text1.is_null() { - text1 - } else { - b"\x00" as *const u8 as *const libc::c_char - }, - if !text1.is_null() { - b": \x00" as *const u8 as *const libc::c_char - } else { - b"\x00" as *const u8 as *const libc::c_char - }, - if !text2.is_null() { - text2 - } else { - b"\x00" as *const u8 as *const libc::c_char - }, - statestr, - timestr, - if 0 != dc_chat_is_sending_locations(chat) { - b"\xf0\x9f\x93\x8d\x00" as *const u8 as *const libc::c_char - } else { - b"\x00" as *const u8 as *const libc::c_char - }, - ); - free(text1 as *mut libc::c_void); - free(text2 as *mut libc::c_void); - free(timestr as *mut libc::c_void); - dc_lot_unref(lot); - dc_chat_unref(chat); - dc_log_info(context, 0i32, - b"================================================================================\x00" - as *const u8 as *const libc::c_char); - i -= 1 - } - } - if 0 != dc_is_sending_locations_to_chat(context, 0i32 as uint32_t) { + i = cnt - 1i32; + + while i >= 0i32 { + let mut chat: *mut dc_chat_t = + dc_get_chat(context, dc_chatlist_get_chat_id(chatlist, i as size_t)); + let mut temp_subtitle: *mut libc::c_char = dc_chat_get_subtitle(chat); + let mut temp_name: *mut libc::c_char = dc_chat_get_name(chat); dc_log_info( context, 0i32, - b"Location streaming enabled.\x00" as *const u8 as *const libc::c_char, + b"%s#%i: %s [%s] [%i fresh]\x00" as *const u8 as *const libc::c_char, + chat_prefix(chat), + dc_chat_get_id(chat) as libc::c_int, + temp_name, + temp_subtitle, + dc_get_fresh_msg_cnt(context, dc_chat_get_id(chat)) as libc::c_int, ); - } - ret = dc_mprintf( - b"%i chats.\x00" as *const u8 as *const libc::c_char, - cnt as libc::c_int, - ); - dc_chatlist_unref(chatlist); - } else { - ret = 1i32 as *mut libc::c_char - } - } else if strcmp(cmd, b"chat\x00" as *const u8 as *const libc::c_char) == 0i32 { - if !arg1.is_null() && 0 != *arg1.offset(0isize) as libc::c_int { - if !sel_chat.is_null() { - dc_chat_unref(sel_chat); - sel_chat = 0 as *mut dc_chat_t - } - (*context).cmdline_sel_chat_id = atoi(arg1) as uint32_t; - sel_chat = dc_get_chat(context, (*context).cmdline_sel_chat_id); - if sel_chat.is_null() { - (*context).cmdline_sel_chat_id = 0i32 as uint32_t + free(temp_subtitle as *mut libc::c_void); + free(temp_name as *mut libc::c_void); + let mut lot: *mut dc_lot_t = + dc_chatlist_get_summary(chatlist, i as size_t, chat); + let mut statestr: *const libc::c_char = + b"\x00" as *const u8 as *const libc::c_char; + if 0 != dc_chat_get_archived(chat) { + statestr = b" [Archived]\x00" as *const u8 as *const libc::c_char + } else { + match dc_lot_get_state(lot) { + 20 => statestr = b" o\x00" as *const u8 as *const libc::c_char, + 26 => { + statestr = b" \xe2\x88\x9a\x00" as *const u8 as *const libc::c_char + } + 28 => { + statestr = b" \xe2\x88\x9a\xe2\x88\x9a\x00" as *const u8 + as *const libc::c_char + } + 24 => statestr = b" !!\x00" as *const u8 as *const libc::c_char, + _ => {} + } + } + let mut timestr: *mut libc::c_char = + dc_timestamp_to_str(dc_lot_get_timestamp(lot)); + let mut text1: *mut libc::c_char = dc_lot_get_text1(lot); + let mut text2: *mut libc::c_char = dc_lot_get_text2(lot); + dc_log_info( + context, + 0i32, + b"%s%s%s%s [%s]%s\x00" as *const u8 as *const libc::c_char, + if !text1.is_null() { + text1 + } else { + b"\x00" as *const u8 as *const libc::c_char + }, + if !text1.is_null() { + b": \x00" as *const u8 as *const libc::c_char + } else { + b"\x00" as *const u8 as *const libc::c_char + }, + if !text2.is_null() { + text2 + } else { + b"\x00" as *const u8 as *const libc::c_char + }, + statestr, + timestr, + if 0 != dc_chat_is_sending_locations(chat) { + b"\xf0\x9f\x93\x8d\x00" as *const u8 as *const libc::c_char + } else { + b"\x00" as *const u8 as *const libc::c_char + }, + ); + free(text1 as *mut libc::c_void); + free(text2 as *mut libc::c_void); + free(timestr as *mut libc::c_void); + dc_lot_unref(lot); + dc_chat_unref(chat); + dc_log_info(context, 0i32, + b"================================================================================\x00" + as *const u8 as *const libc::c_char); + i -= 1 } } - if !sel_chat.is_null() { - let mut msglist: *mut dc_array_t = dc_get_chat_msgs( - context, - dc_chat_get_id(sel_chat), - 0x1i32 as uint32_t, - 0i32 as uint32_t, - ); - let mut temp2: *mut libc::c_char = dc_chat_get_subtitle(sel_chat); - let mut temp_name_0: *mut libc::c_char = dc_chat_get_name(sel_chat); + if 0 != dc_is_sending_locations_to_chat(context, 0i32 as uint32_t) { dc_log_info( context, 0i32, - b"%s#%i: %s [%s]%s\x00" as *const u8 as *const libc::c_char, - chat_prefix(sel_chat), - dc_chat_get_id(sel_chat), - temp_name_0, - temp2, - if 0 != dc_chat_is_sending_locations(sel_chat) { - b"\xf0\x9f\x93\x8d\x00" as *const u8 as *const libc::c_char - } else { - b"\x00" as *const u8 as *const libc::c_char - }, + b"Location streaming enabled.\x00" as *const u8 as *const libc::c_char, ); - free(temp_name_0 as *mut libc::c_void); - free(temp2 as *mut libc::c_void); - if !msglist.is_null() { - log_msglist(context, msglist); - dc_array_unref(msglist); - } - let mut draft: *mut dc_msg_t = dc_get_draft(context, dc_chat_get_id(sel_chat)); - if !draft.is_null() { - log_msg( - context, - b"Draft\x00" as *const u8 as *const libc::c_char, - draft, - ); - dc_msg_unref(draft); - } - ret = dc_mprintf( - b"%i messages.\x00" as *const u8 as *const libc::c_char, - dc_get_msg_cnt(context, dc_chat_get_id(sel_chat)), - ); - dc_marknoticed_chat(context, dc_chat_get_id(sel_chat)); - } else { - ret = dc_strdup(b"No chat selected.\x00" as *const u8 as *const libc::c_char) } - } else if strcmp(cmd, b"createchat\x00" as *const u8 as *const libc::c_char) == 0i32 { - if !arg1.is_null() { - let mut contact_id: libc::c_int = atoi(arg1); - let mut chat_id: libc::c_int = - dc_create_chat_by_contact_id(context, contact_id as uint32_t) as libc::c_int; - ret = if chat_id != 0i32 { - dc_mprintf( - b"Single#%lu created successfully.\x00" as *const u8 as *const libc::c_char, - chat_id, - ) + ret = dc_mprintf( + b"%i chats.\x00" as *const u8 as *const libc::c_char, + cnt as libc::c_int, + ); + dc_chatlist_unref(chatlist); + } else { + ret = 1i32 as *mut libc::c_char + } + } else if strcmp(cmd, b"chat\x00" as *const u8 as *const libc::c_char) == 0i32 { + if !arg1.is_empty() { + if !sel_chat.is_null() { + dc_chat_unref(sel_chat); + } + + let chat_id = arg1.parse().unwrap(); + sel_chat = dc_get_chat(context, chat_id); + *context.cmdline_sel_chat_id.write().unwrap() = chat_id; + } + if !sel_chat.is_null() { + let mut msglist: *mut dc_array_t = dc_get_chat_msgs( + context, + dc_chat_get_id(sel_chat), + 0x1i32 as uint32_t, + 0i32 as uint32_t, + ); + let mut temp2: *mut libc::c_char = dc_chat_get_subtitle(sel_chat); + let mut temp_name_0: *mut libc::c_char = dc_chat_get_name(sel_chat); + dc_log_info( + context, + 0i32, + b"%s#%i: %s [%s]%s\x00" as *const u8 as *const libc::c_char, + chat_prefix(sel_chat), + dc_chat_get_id(sel_chat), + temp_name_0, + temp2, + if 0 != dc_chat_is_sending_locations(sel_chat) { + b"\xf0\x9f\x93\x8d\x00" as *const u8 as *const libc::c_char } else { - 1i32 as *mut libc::c_char + b"\x00" as *const u8 as *const libc::c_char + }, + ); + free(temp_name_0 as *mut libc::c_void); + free(temp2 as *mut libc::c_void); + if !msglist.is_null() { + log_msglist(context, msglist); + dc_array_unref(msglist); + } + let mut draft: *mut dc_msg_t = dc_get_draft(context, dc_chat_get_id(sel_chat)); + if !draft.is_null() { + log_msg( + context, + b"Draft\x00" as *const u8 as *const libc::c_char, + draft, + ); + dc_msg_unref(draft); + } + ret = dc_mprintf( + b"%i messages.\x00" as *const u8 as *const libc::c_char, + dc_get_msg_cnt(context, dc_chat_get_id(sel_chat)), + ); + dc_marknoticed_chat(context, dc_chat_get_id(sel_chat)); + } else { + ret = dc_strdup(b"No chat selected.\x00" as *const u8 as *const libc::c_char) + } + } else if strcmp(cmd, b"createchat\x00" as *const u8 as *const libc::c_char) == 0i32 { + if !arg1.is_empty() { + let mut contact_id: libc::c_int = arg1.parse().unwrap(); + let mut chat_id: libc::c_int = + dc_create_chat_by_contact_id(context, contact_id as uint32_t) as libc::c_int; + ret = if chat_id != 0i32 { + dc_mprintf( + b"Single#%lu created successfully.\x00" as *const u8 as *const libc::c_char, + chat_id, + ) + } else { + 1i32 as *mut libc::c_char + } + } else { + ret = dc_strdup( + b"ERROR: Argument missing.\x00" as *const u8 as *const libc::c_char, + ) + } + } else if strcmp( + cmd, + b"createchatbymsg\x00" as *const u8 as *const libc::c_char, + ) == 0i32 + { + if !arg1.is_empty() { + let mut msg_id_0: libc::c_int = arg1.parse().unwrap(); + let mut chat_id_0: libc::c_int = + dc_create_chat_by_msg_id(context, msg_id_0 as uint32_t) as libc::c_int; + if chat_id_0 != 0i32 { + let mut chat_0: *mut dc_chat_t = dc_get_chat(context, chat_id_0 as uint32_t); + ret = dc_mprintf( + b"%s#%lu created successfully.\x00" as *const u8 as *const libc::c_char, + chat_prefix(chat_0), + chat_id_0, + ); + dc_chat_unref(chat_0); + } else { + ret = 1i32 as *mut libc::c_char + } + } else { + ret = dc_strdup( + b"ERROR: Argument missing.\x00" as *const u8 as *const libc::c_char, + ) + } + } else if strcmp(cmd, b"creategroup\x00" as *const u8 as *const libc::c_char) == 0i32 { + if !arg1.is_empty() { + let mut chat_id_1: libc::c_int = + dc_create_group_chat(context, 0i32, arg1_c.as_ptr()) as libc::c_int; + ret = if chat_id_1 != 0i32 { + dc_mprintf( + b"Group#%lu created successfully.\x00" as *const u8 as *const libc::c_char, + chat_id_1, + ) + } else { + 1i32 as *mut libc::c_char + } + } else { + ret = dc_strdup( + b"ERROR: Argument missing.\x00" as *const u8 as *const libc::c_char, + ) + } + } else if strcmp( + cmd, + b"createverified\x00" as *const u8 as *const libc::c_char, + ) == 0i32 + { + if !arg1.is_empty() { + let mut chat_id_2: libc::c_int = + dc_create_group_chat(context, 1i32, arg1_c.as_ptr()) as libc::c_int; + ret = if chat_id_2 != 0i32 { + dc_mprintf( + b"VerifiedGroup#%lu created successfully.\x00" as *const u8 + as *const libc::c_char, + chat_id_2, + ) + } else { + 1i32 as *mut libc::c_char + } + } else { + ret = dc_strdup( + b"ERROR: Argument missing.\x00" as *const u8 as *const libc::c_char, + ) + } + } else if strcmp(cmd, b"addmember\x00" as *const u8 as *const libc::c_char) == 0i32 { + if !sel_chat.is_null() { + if !arg1.is_empty() { + let mut contact_id_0: libc::c_int = arg1.parse().unwrap(); + if 0 != dc_add_contact_to_chat( + context, + dc_chat_get_id(sel_chat), + contact_id_0 as uint32_t, + ) { + ret = + dc_strdup(b"Contact added to chat.\x00" as *const u8 as *const libc::c_char) + } else { + ret = dc_strdup( + b"ERROR: Cannot add contact to chat.\x00" as *const u8 + as *const libc::c_char, + ) } } else { ret = dc_strdup( @@ -1055,746 +1048,617 @@ pub unsafe extern "C" fn dc_cmdline( as *const libc::c_char, ) } - } else if strcmp( - cmd, - b"createchatbymsg\x00" as *const u8 as *const libc::c_char, - ) == 0i32 - { - if !arg1.is_null() { - let mut msg_id_0: libc::c_int = atoi(arg1); - let mut chat_id_0: libc::c_int = - dc_create_chat_by_msg_id(context, msg_id_0 as uint32_t) as libc::c_int; - if chat_id_0 != 0i32 { - let mut chat_0: *mut dc_chat_t = dc_get_chat(context, chat_id_0 as uint32_t); - ret = dc_mprintf( - b"%s#%lu created successfully.\x00" as *const u8 as *const libc::c_char, - chat_prefix(chat_0), - chat_id_0, - ); - dc_chat_unref(chat_0); - } else { - ret = 1i32 as *mut libc::c_char - } - } else { - ret = dc_strdup( - b"ERROR: Argument missing.\x00" as *const u8 as *const libc::c_char, - ) - } - } else if strcmp(cmd, b"creategroup\x00" as *const u8 as *const libc::c_char) == 0i32 { - if !arg1.is_null() { - let mut chat_id_1: libc::c_int = - dc_create_group_chat(context, 0i32, arg1) as libc::c_int; - ret = if chat_id_1 != 0i32 { - dc_mprintf( - b"Group#%lu created successfully.\x00" as *const u8 as *const libc::c_char, - chat_id_1, - ) - } else { - 1i32 as *mut libc::c_char - } - } else { - ret = dc_strdup( - b"ERROR: Argument missing.\x00" as *const u8 as *const libc::c_char, - ) - } - } else if strcmp( - cmd, - b"createverified\x00" as *const u8 as *const libc::c_char, - ) == 0i32 - { - if !arg1.is_null() { - let mut chat_id_2: libc::c_int = - dc_create_group_chat(context, 1i32, arg1) as libc::c_int; - ret = if chat_id_2 != 0i32 { - dc_mprintf( - b"VerifiedGroup#%lu created successfully.\x00" as *const u8 - as *const libc::c_char, - chat_id_2, - ) - } else { - 1i32 as *mut libc::c_char - } - } else { - ret = dc_strdup( - b"ERROR: Argument missing.\x00" as *const u8 as *const libc::c_char, - ) - } - } else if strcmp(cmd, b"addmember\x00" as *const u8 as *const libc::c_char) == 0i32 { - if !sel_chat.is_null() { - if !arg1.is_null() { - let mut contact_id_0: libc::c_int = atoi(arg1); - if 0 != dc_add_contact_to_chat( - context, - dc_chat_get_id(sel_chat), - contact_id_0 as uint32_t, - ) { - ret = dc_strdup( - b"Contact added to chat.\x00" as *const u8 as *const libc::c_char, - ) - } else { - ret = dc_strdup( - b"ERROR: Cannot add contact to chat.\x00" as *const u8 - as *const libc::c_char, - ) - } + } else { + ret = dc_strdup(b"No chat selected.\x00" as *const u8 as *const libc::c_char) + } + } else if strcmp(cmd, b"removemember\x00" as *const u8 as *const libc::c_char) == 0i32 { + if !sel_chat.is_null() { + if !arg1.is_empty() { + let mut contact_id_1: libc::c_int = arg1.parse().unwrap(); + if 0 != dc_remove_contact_from_chat( + context, + dc_chat_get_id(sel_chat), + contact_id_1 as uint32_t, + ) { + ret = + dc_strdup(b"Contact added to chat.\x00" as *const u8 as *const libc::c_char) } else { ret = dc_strdup( - b"ERROR: Argument missing.\x00" as *const u8 + b"ERROR: Cannot remove member from chat.\x00" as *const u8 as *const libc::c_char, ) } } else { - ret = dc_strdup(b"No chat selected.\x00" as *const u8 as *const libc::c_char) + ret = dc_strdup( + b"ERROR: Argument missing.\x00" as *const u8 + as *const libc::c_char, + ) } - } else if strcmp(cmd, b"removemember\x00" as *const u8 as *const libc::c_char) == 0i32 { - if !sel_chat.is_null() { - if !arg1.is_null() { - let mut contact_id_1: libc::c_int = atoi(arg1); - if 0 != dc_remove_contact_from_chat( - context, - dc_chat_get_id(sel_chat), - contact_id_1 as uint32_t, - ) { - ret = dc_strdup( - b"Contact added to chat.\x00" as *const u8 as *const libc::c_char, - ) - } else { - ret = dc_strdup( - b"ERROR: Cannot remove member from chat.\x00" as *const u8 - as *const libc::c_char, - ) - } - } else { - ret = dc_strdup( - b"ERROR: Argument missing.\x00" as *const u8 - as *const libc::c_char, - ) - } - } else { - ret = dc_strdup(b"No chat selected.\x00" as *const u8 as *const libc::c_char) - } - } else if strcmp(cmd, b"groupname\x00" as *const u8 as *const libc::c_char) == 0i32 { - if !sel_chat.is_null() { - if !arg1.is_null() && 0 != *arg1.offset(0isize) as libc::c_int { - ret = if 0 != dc_set_chat_name(context, dc_chat_get_id(sel_chat), arg1) { - 2i32 as *mut libc::c_char - } else { - 1i32 as *mut libc::c_char - } - } else { - ret = dc_strdup( - b"ERROR: Argument missing.\x00" as *const u8 as *const libc::c_char, - ) - } - } else { - ret = dc_strdup(b"No chat selected.\x00" as *const u8 as *const libc::c_char) - } - } else if strcmp(cmd, b"groupimage\x00" as *const u8 as *const libc::c_char) == 0i32 { - if !sel_chat.is_null() { - ret = if 0 - != dc_set_chat_profile_image( - context, - dc_chat_get_id(sel_chat), - if !arg1.is_null() && 0 != *arg1.offset(0isize) as libc::c_int { - arg1 - } else { - 0 as *mut libc::c_char - }, - ) { + } else { + ret = dc_strdup(b"No chat selected.\x00" as *const u8 as *const libc::c_char) + } + } else if strcmp(cmd, b"groupname\x00" as *const u8 as *const libc::c_char) == 0i32 { + if !sel_chat.is_null() { + if !arg1.is_empty() { + ret = if 0 != dc_set_chat_name(context, dc_chat_get_id(sel_chat), arg1_c.as_ptr()) { 2i32 as *mut libc::c_char } else { 1i32 as *mut libc::c_char } } else { - ret = dc_strdup(b"No chat selected.\x00" as *const u8 as *const libc::c_char) + ret = dc_strdup( + b"ERROR: Argument missing.\x00" as *const u8 as *const libc::c_char, + ) } - } else if strcmp(cmd, b"chatinfo\x00" as *const u8 as *const libc::c_char) == 0i32 { - if !sel_chat.is_null() { - let mut contacts: *mut dc_array_t = - dc_get_chat_contacts(context, dc_chat_get_id(sel_chat)); - if !contacts.is_null() { - dc_log_info( - context, - 0i32, - b"Memberlist:\x00" as *const u8 as *const libc::c_char, - ); - log_contactlist(context, contacts); - ret = dc_mprintf( - b"%i contacts\nLocation streaming: %i\x00" as *const u8 - as *const libc::c_char, - dc_array_get_cnt(contacts) as libc::c_int, - dc_is_sending_locations_to_chat(context, dc_chat_get_id(sel_chat)), - ); - dc_array_unref(contacts); - } else { - ret = 1i32 as *mut libc::c_char - } - } else { - ret = dc_strdup(b"No chat selected.\x00" as *const u8 as *const libc::c_char) - } - } else if strcmp(cmd, b"getlocations\x00" as *const u8 as *const libc::c_char) == 0i32 { - let mut contact_id_2: libc::c_int = if !arg1.is_null() { atoi(arg1) } else { 0i32 }; - let mut loc: *mut dc_array_t = dc_get_locations( - context, - dc_chat_get_id(sel_chat), - contact_id_2 as uint32_t, - 0i32 as time_t, - 0i32 as time_t, - ); - let mut j = 0; - while j < dc_array_get_cnt(loc) { - let mut timestr_0: *mut libc::c_char = - dc_timestamp_to_str(dc_array_get_timestamp(loc, j as size_t)); - let mut marker: *mut libc::c_char = dc_array_get_marker(loc, j as size_t); - dc_log_info( + } else { + ret = dc_strdup(b"No chat selected.\x00" as *const u8 as *const libc::c_char) + } + } else if strcmp(cmd, b"groupimage\x00" as *const u8 as *const libc::c_char) == 0i32 { + if !sel_chat.is_null() { + ret = if 0 + != dc_set_chat_profile_image( context, - 0i32, - b"Loc#%i: %s: lat=%f lng=%f acc=%f Chat#%i Contact#%i Msg#%i %s\x00" - as *const u8 as *const libc::c_char, - dc_array_get_id(loc, j as size_t), - timestr_0, - dc_array_get_latitude(loc, j as size_t), - dc_array_get_longitude(loc, j as size_t), - dc_array_get_accuracy(loc, j as size_t), - dc_array_get_chat_id(loc, j as size_t), - dc_array_get_contact_id(loc, j as size_t), - dc_array_get_msg_id(loc, j as size_t), - if !marker.is_null() { - marker + dc_chat_get_id(sel_chat), + if !arg1.is_empty() { + arg1_c.as_ptr() } else { - b"-\x00" as *const u8 as *const libc::c_char + 0 as *mut libc::c_char }, - ); - free(timestr_0 as *mut libc::c_void); - free(marker as *mut libc::c_void); - j += 1 + ) { + 2i32 as *mut libc::c_char + } else { + 1i32 as *mut libc::c_char } - if dc_array_get_cnt(loc) == 0 { + } else { + ret = dc_strdup(b"No chat selected.\x00" as *const u8 as *const libc::c_char) + } + } else if strcmp(cmd, b"chatinfo\x00" as *const u8 as *const libc::c_char) == 0i32 { + if !sel_chat.is_null() { + let mut contacts: *mut dc_array_t = + dc_get_chat_contacts(context, dc_chat_get_id(sel_chat)); + if !contacts.is_null() { dc_log_info( context, 0i32, - b"No locations.\x00" as *const u8 as *const libc::c_char, + b"Memberlist:\x00" as *const u8 as *const libc::c_char, ); + log_contactlist(context, contacts); + ret = dc_mprintf( + b"%i contacts\nLocation streaming: %i\x00" as *const u8 as *const libc::c_char, + dc_array_get_cnt(contacts) as libc::c_int, + dc_is_sending_locations_to_chat(context, dc_chat_get_id(sel_chat)), + ); + dc_array_unref(contacts); + } else { + ret = 1i32 as *mut libc::c_char } - dc_array_unref(loc); - ret = 2i32 as *mut libc::c_char - } else if strcmp( - cmd, - b"sendlocations\x00" as *const u8 as *const libc::c_char, - ) == 0i32 - { - if !sel_chat.is_null() { - if !arg1.is_null() && 0 != *arg1.offset(0isize) as libc::c_int { - let mut seconds: libc::c_int = atoi(arg1); - dc_send_locations_to_chat(context, dc_chat_get_id(sel_chat), seconds); - ret = + } else { + ret = dc_strdup(b"No chat selected.\x00" as *const u8 as *const libc::c_char) + } + } else if strcmp(cmd, b"getlocations\x00" as *const u8 as *const libc::c_char) == 0i32 { + let mut contact_id_2: libc::c_int = if !arg1.is_empty() { + arg1.parse().unwrap() + } else { + 0i32 + }; + let mut loc: *mut dc_array_t = dc_get_locations( + context, + dc_chat_get_id(sel_chat), + contact_id_2 as uint32_t, + 0i32 as time_t, + 0i32 as time_t, + ); + let mut j = 0; + while j < dc_array_get_cnt(loc) { + let mut timestr_0: *mut libc::c_char = + dc_timestamp_to_str(dc_array_get_timestamp(loc, j as size_t)); + let mut marker: *mut libc::c_char = dc_array_get_marker(loc, j as size_t); + dc_log_info( + context, + 0i32, + b"Loc#%i: %s: lat=%f lng=%f acc=%f Chat#%i Contact#%i Msg#%i %s\x00" as *const u8 + as *const libc::c_char, + dc_array_get_id(loc, j as size_t), + timestr_0, + dc_array_get_latitude(loc, j as size_t), + dc_array_get_longitude(loc, j as size_t), + dc_array_get_accuracy(loc, j as size_t), + dc_array_get_chat_id(loc, j as size_t), + dc_array_get_contact_id(loc, j as size_t), + dc_array_get_msg_id(loc, j as size_t), + if !marker.is_null() { + marker + } else { + b"-\x00" as *const u8 as *const libc::c_char + }, + ); + free(timestr_0 as *mut libc::c_void); + free(marker as *mut libc::c_void); + j += 1 + } + if dc_array_get_cnt(loc) == 0 { + dc_log_info( + context, + 0i32, + b"No locations.\x00" as *const u8 as *const libc::c_char, + ); + } + dc_array_unref(loc); + ret = 2i32 as *mut libc::c_char + } else if strcmp( + cmd, + b"sendlocations\x00" as *const u8 as *const libc::c_char, + ) == 0i32 + { + if !sel_chat.is_null() { + if !arg1.is_empty() { + let mut seconds: libc::c_int = arg1.parse().unwrap(); + dc_send_locations_to_chat(context, dc_chat_get_id(sel_chat), seconds); + ret = dc_mprintf(b"Locations will be sent to Chat#%i for %i seconds. Use \'setlocation \' to play around.\x00" as *const u8 as *const libc::c_char, dc_chat_get_id(sel_chat), seconds) - } else { - ret = dc_strdup( - b"ERROR: No timeout given.\x00" as *const u8 as *const libc::c_char, - ) - } } else { - ret = dc_strdup(b"No chat selected.\x00" as *const u8 as *const libc::c_char) + ret = dc_strdup(b"ERROR: No timeout given.\x00" as *const u8 as *const libc::c_char) } - } else if strcmp(cmd, b"setlocation\x00" as *const u8 as *const libc::c_char) == 0i32 { - let mut arg2_1: *mut libc::c_char = 0 as *mut libc::c_char; - if !arg1.is_null() { - arg2_1 = strrchr(arg1, ' ' as i32) - } - if !arg1.is_null() && !arg2_1.is_null() { - *arg2_1 = 0i32 as libc::c_char; - arg2_1 = arg2_1.offset(1isize); - let mut latitude: libc::c_double = atof(arg1); - let mut longitude: libc::c_double = atof(arg2_1); - let mut continue_streaming: libc::c_int = - dc_set_location(context, latitude, longitude, 0.0f64); - ret = dc_strdup(if 0 != continue_streaming { - b"Success, streaming should be continued.\x00" as *const u8 - as *const libc::c_char - } else { - b"Success, streaming can be stoppped.\x00" as *const u8 as *const libc::c_char - }) + } else { + ret = dc_strdup(b"No chat selected.\x00" as *const u8 as *const libc::c_char) + } + } else if strcmp(cmd, b"setlocation\x00" as *const u8 as *const libc::c_char) == 0i32 { + if !arg1.is_empty() && !arg2.is_empty() { + let mut latitude: libc::c_double = arg1.parse().unwrap(); + let mut longitude: libc::c_double = arg2.parse().unwrap(); + let mut continue_streaming: libc::c_int = + dc_set_location(context, latitude, longitude, 0.0f64); + ret = dc_strdup(if 0 != continue_streaming { + b"Success, streaming should be continued.\x00" as *const u8 as *const libc::c_char } else { - ret = dc_strdup( - b"ERROR: Latitude or longitude not given.\x00" as *const u8 - as *const libc::c_char, - ) - } - } else if strcmp(cmd, b"dellocations\x00" as *const u8 as *const libc::c_char) == 0i32 { - dc_delete_all_locations(context); - ret = 2i32 as *mut libc::c_char - } else if strcmp(cmd, b"send\x00" as *const u8 as *const libc::c_char) == 0i32 { - if !sel_chat.is_null() { - if !arg1.is_null() && 0 != *arg1.offset(0isize) as libc::c_int { - if 0 != dc_send_text_msg(context, dc_chat_get_id(sel_chat), arg1) { - ret = dc_strdup(b"Message sent.\x00" as *const u8 as *const libc::c_char) - } else { - ret = dc_strdup( - b"ERROR: Sending failed.\x00" as *const u8 as *const libc::c_char, - ) - } - } else { - ret = dc_strdup( - b"ERROR: No message text given.\x00" as *const u8 as *const libc::c_char, - ) - } - } else { - ret = dc_strdup(b"No chat selected.\x00" as *const u8 as *const libc::c_char) - } - } else if strcmp(cmd, b"sendempty\x00" as *const u8 as *const libc::c_char) == 0i32 { - if !sel_chat.is_null() { - if 0 != dc_send_text_msg( - context, - dc_chat_get_id(sel_chat), - b"\x00" as *const u8 as *const libc::c_char, - ) { + b"Success, streaming can be stoppped.\x00" as *const u8 as *const libc::c_char + }) + } else { + ret = dc_strdup( + b"ERROR: Latitude or longitude not given.\x00" as *const u8 as *const libc::c_char, + ) + } + } else if strcmp(cmd, b"dellocations\x00" as *const u8 as *const libc::c_char) == 0i32 { + dc_delete_all_locations(context); + ret = 2i32 as *mut libc::c_char + } else if strcmp(cmd, b"send\x00" as *const u8 as *const libc::c_char) == 0i32 { + if !sel_chat.is_null() { + if !arg1.is_empty() { + if 0 != dc_send_text_msg(context, dc_chat_get_id(sel_chat), arg1_c.as_ptr()) { ret = dc_strdup(b"Message sent.\x00" as *const u8 as *const libc::c_char) } else { ret = dc_strdup(b"ERROR: Sending failed.\x00" as *const u8 as *const libc::c_char) } - } else { - ret = dc_strdup(b"No chat selected.\x00" as *const u8 as *const libc::c_char) - } - } else if strcmp(cmd, b"sendimage\x00" as *const u8 as *const libc::c_char) == 0i32 - || strcmp(cmd, b"sendfile\x00" as *const u8 as *const libc::c_char) == 0i32 - { - if !sel_chat.is_null() { - if !arg1.is_null() && 0 != *arg1.offset(0isize) as libc::c_int { - let mut arg2_2: *mut libc::c_char = strchr(arg1, ' ' as i32); - if !arg2_2.is_null() { - *arg2_2 = 0i32 as libc::c_char; - arg2_2 = arg2_2.offset(1isize) - } - let mut msg_0: *mut dc_msg_t = dc_msg_new( - context, - if strcmp(cmd, b"sendimage\x00" as *const u8 as *const libc::c_char) == 0i32 - { - 20i32 - } else { - 60i32 - }, - ); - dc_msg_set_file(msg_0, arg1, 0 as *const libc::c_char); - dc_msg_set_text(msg_0, arg2_2); - dc_send_msg(context, dc_chat_get_id(sel_chat), msg_0); - dc_msg_unref(msg_0); - ret = 2i32 as *mut libc::c_char - } else { - ret = - dc_strdup(b"ERROR: No file given.\x00" as *const u8 as *const libc::c_char) - } - } else { - ret = dc_strdup(b"No chat selected.\x00" as *const u8 as *const libc::c_char) - } - } else if strcmp(cmd, b"listmsgs\x00" as *const u8 as *const libc::c_char) == 0i32 { - if !arg1.is_null() { - let mut msglist_0: *mut dc_array_t = dc_search_msgs( - context, - if !sel_chat.is_null() { - dc_chat_get_id(sel_chat) - } else { - 0i32 as libc::c_uint - }, - arg1, - ); - if !msglist_0.is_null() { - log_msglist(context, msglist_0); - ret = dc_mprintf( - b"%i messages.\x00" as *const u8 as *const libc::c_char, - dc_array_get_cnt(msglist_0) as libc::c_int, - ); - dc_array_unref(msglist_0); - } } else { ret = dc_strdup( - b"ERROR: Argument missing.\x00" as *const u8 as *const libc::c_char, + b"ERROR: No message text given.\x00" as *const u8 as *const libc::c_char, ) } - } else if strcmp(cmd, b"draft\x00" as *const u8 as *const libc::c_char) == 0i32 { - if !sel_chat.is_null() { - if !arg1.is_null() && 0 != *arg1.offset(0isize) as libc::c_int { - let mut draft_0: *mut dc_msg_t = dc_msg_new(context, 10i32); - dc_msg_set_text(draft_0, arg1); - dc_set_draft(context, dc_chat_get_id(sel_chat), draft_0); - dc_msg_unref(draft_0); - ret = dc_strdup(b"Draft saved.\x00" as *const u8 as *const libc::c_char) - } else { - dc_set_draft(context, dc_chat_get_id(sel_chat), 0 as *mut dc_msg_t); - ret = dc_strdup(b"Draft deleted.\x00" as *const u8 as *const libc::c_char) - } - } else { - ret = dc_strdup(b"No chat selected.\x00" as *const u8 as *const libc::c_char) - } - } else if strcmp(cmd, b"listmedia\x00" as *const u8 as *const libc::c_char) == 0i32 { - if !sel_chat.is_null() { - let mut images: *mut dc_array_t = - dc_get_chat_media(context, dc_chat_get_id(sel_chat), 20i32, 21i32, 50i32); - let mut i_0: libc::c_int = 0; - let mut icnt: libc::c_int = dc_array_get_cnt(images) as libc::c_int; - ret = dc_mprintf( - b"%i images or videos: \x00" as *const u8 as *const libc::c_char, - icnt, - ); - i_0 = 0i32; - while i_0 < icnt { - let mut temp: *mut libc::c_char = dc_mprintf( - b"%s%sMsg#%i\x00" as *const u8 as *const libc::c_char, - if 0 != i_0 { - b", \x00" as *const u8 as *const libc::c_char - } else { - b"\x00" as *const u8 as *const libc::c_char - }, - ret, - dc_array_get_id(images, i_0 as size_t) as libc::c_int, - ); - free(ret as *mut libc::c_void); - ret = temp; - i_0 += 1 - } - dc_array_unref(images); - } else { - ret = dc_strdup(b"No chat selected.\x00" as *const u8 as *const libc::c_char) - } - } else if strcmp(cmd, b"archive\x00" as *const u8 as *const libc::c_char) == 0i32 - || strcmp(cmd, b"unarchive\x00" as *const u8 as *const libc::c_char) == 0i32 - { - if !arg1.is_null() { - let mut chat_id_3: libc::c_int = atoi(arg1); - dc_archive_chat( - context, - chat_id_3 as uint32_t, - if strcmp(cmd, b"archive\x00" as *const u8 as *const libc::c_char) == 0i32 { - 1i32 - } else { - 0i32 - }, - ); - ret = 2i32 as *mut libc::c_char - } else { - ret = dc_strdup( - b"ERROR: Argument missing.\x00" as *const u8 as *const libc::c_char, - ) - } - } else if strcmp(cmd, b"delchat\x00" as *const u8 as *const libc::c_char) == 0i32 { - if !arg1.is_null() { - let mut chat_id_4: libc::c_int = atoi(arg1); - dc_delete_chat(context, chat_id_4 as uint32_t); - ret = 2i32 as *mut libc::c_char - } else { - ret = dc_strdup( - b"ERROR: Argument missing.\x00" as *const u8 as *const libc::c_char, - ) - } - } else if strcmp(cmd, b"msginfo\x00" as *const u8 as *const libc::c_char) == 0i32 { - if !arg1.is_null() { - let mut id: libc::c_int = atoi(arg1); - ret = dc_get_msg_info(context, id as uint32_t) - } else { - ret = dc_strdup( - b"ERROR: Argument missing.\x00" as *const u8 as *const libc::c_char, - ) - } - } else if strcmp(cmd, b"listfresh\x00" as *const u8 as *const libc::c_char) == 0i32 { - let mut msglist_1: *mut dc_array_t = dc_get_fresh_msgs(context); - if !msglist_1.is_null() { - log_msglist(context, msglist_1); - ret = dc_mprintf( - b"%i fresh messages.\x00" as *const u8 as *const libc::c_char, - dc_array_get_cnt(msglist_1) as libc::c_int, - ); - dc_array_unref(msglist_1); - } - } else if strcmp(cmd, b"forward\x00" as *const u8 as *const libc::c_char) == 0i32 { - let mut arg2_3: *mut libc::c_char = 0 as *mut libc::c_char; - if !arg1.is_null() { - arg2_3 = strrchr(arg1, ' ' as i32) - } - if !arg1.is_null() && !arg2_3.is_null() { - *arg2_3 = 0i32 as libc::c_char; - arg2_3 = arg2_3.offset(1isize); - let mut msg_ids: [uint32_t; 1] = [0; 1]; - let mut chat_id_5: uint32_t = atoi(arg2_3) as uint32_t; - msg_ids[0usize] = atoi(arg1) as uint32_t; - dc_forward_msgs(context, msg_ids.as_mut_ptr(), 1i32, chat_id_5); - ret = 2i32 as *mut libc::c_char - } else { - ret = dc_strdup( - b"ERROR: Arguments expected.\x00" as *const u8 - as *const libc::c_char, - ) - } - } else if strcmp(cmd, b"markseen\x00" as *const u8 as *const libc::c_char) == 0i32 { - if !arg1.is_null() { - let mut msg_ids_0: [uint32_t; 1] = [0; 1]; - msg_ids_0[0usize] = atoi(arg1) as uint32_t; - dc_markseen_msgs(context, msg_ids_0.as_mut_ptr(), 1i32); - ret = 2i32 as *mut libc::c_char - } else { - ret = dc_strdup( - b"ERROR: Argument missing.\x00" as *const u8 as *const libc::c_char, - ) - } - } else if strcmp(cmd, b"star\x00" as *const u8 as *const libc::c_char) == 0i32 - || strcmp(cmd, b"unstar\x00" as *const u8 as *const libc::c_char) == 0i32 - { - if !arg1.is_null() { - let mut msg_ids_1: [uint32_t; 1] = [0; 1]; - msg_ids_1[0usize] = atoi(arg1) as uint32_t; - dc_star_msgs( - context, - msg_ids_1.as_mut_ptr(), - 1i32, - if strcmp(cmd, b"star\x00" as *const u8 as *const libc::c_char) == 0i32 { - 1i32 - } else { - 0i32 - }, - ); - ret = 2i32 as *mut libc::c_char - } else { - ret = dc_strdup( - b"ERROR: Argument missing.\x00" as *const u8 as *const libc::c_char, - ) - } - } else if strcmp(cmd, b"delmsg\x00" as *const u8 as *const libc::c_char) == 0i32 { - if !arg1.is_null() { - let mut ids: [uint32_t; 1] = [0; 1]; - ids[0usize] = atoi(arg1) as uint32_t; - dc_delete_msgs(context, ids.as_mut_ptr(), 1i32); - ret = 2i32 as *mut libc::c_char - } else { - ret = dc_strdup( - b"ERROR: Argument missing.\x00" as *const u8 as *const libc::c_char, - ) - } - } else if strcmp(cmd, b"listcontacts\x00" as *const u8 as *const libc::c_char) == 0i32 - || strcmp(cmd, b"contacts\x00" as *const u8 as *const libc::c_char) == 0i32 - || strcmp(cmd, b"listverified\x00" as *const u8 as *const libc::c_char) == 0i32 - { - let mut contacts_0: *mut dc_array_t = dc_get_contacts( + } else { + ret = dc_strdup(b"No chat selected.\x00" as *const u8 as *const libc::c_char) + } + } else if strcmp(cmd, b"sendempty\x00" as *const u8 as *const libc::c_char) == 0i32 { + if !sel_chat.is_null() { + if 0 != dc_send_text_msg( context, - (if strcmp(cmd, b"listverified\x00" as *const u8 as *const libc::c_char) == 0i32 { - 0x1i32 | 0x2i32 - } else { - 0x2i32 - }) as uint32_t, - arg1, - ); - if !contacts_0.is_null() { - log_contactlist(context, contacts_0); - ret = dc_mprintf( - b"%i contacts.\x00" as *const u8 as *const libc::c_char, - dc_array_get_cnt(contacts_0) as libc::c_int, - ); - dc_array_unref(contacts_0); + dc_chat_get_id(sel_chat), + b"\x00" as *const u8 as *const libc::c_char, + ) { + ret = dc_strdup(b"Message sent.\x00" as *const u8 as *const libc::c_char) } else { - ret = 1i32 as *mut libc::c_char + ret = dc_strdup(b"ERROR: Sending failed.\x00" as *const u8 as *const libc::c_char) } - } else if strcmp(cmd, b"addcontact\x00" as *const u8 as *const libc::c_char) == 0i32 { - let mut arg2_4: *mut libc::c_char = 0 as *mut libc::c_char; - if !arg1.is_null() { - arg2_4 = strrchr(arg1, ' ' as i32) - } - if !arg1.is_null() && !arg2_4.is_null() { - *arg2_4 = 0i32 as libc::c_char; - arg2_4 = arg2_4.offset(1isize); - let mut book: *mut libc::c_char = dc_mprintf( - b"%s\n%s\x00" as *const u8 as *const libc::c_char, - arg1, - arg2_4, - ); - dc_add_address_book(context, book); - ret = 2i32 as *mut libc::c_char; - free(book as *mut libc::c_void); - } else if !arg1.is_null() { - ret = if 0 != dc_create_contact(context, 0 as *const libc::c_char, arg1) { - 2i32 as *mut libc::c_char - } else { - 1i32 as *mut libc::c_char - } - } else { - ret = dc_strdup( - b"ERROR: Arguments [] expected.\x00" as *const u8 - as *const libc::c_char, - ) - } - } else if strcmp(cmd, b"contactinfo\x00" as *const u8 as *const libc::c_char) == 0i32 { - if !arg1.is_null() { - let mut contact_id_3: libc::c_int = atoi(arg1); - let mut strbuilder: 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 strbuilder, 0i32); - let mut contact: *mut dc_contact_t = - dc_get_contact(context, contact_id_3 as uint32_t); - let mut nameNaddr: *mut libc::c_char = dc_contact_get_name_n_addr(contact); - dc_strbuilder_catf( - &mut strbuilder as *mut dc_strbuilder_t, - b"Contact info for: %s:\n\n\x00" as *const u8 as *const libc::c_char, - nameNaddr, - ); - free(nameNaddr as *mut libc::c_void); - dc_contact_unref(contact); - let mut encrinfo: *mut libc::c_char = - dc_get_contact_encrinfo(context, contact_id_3 as uint32_t); - dc_strbuilder_cat(&mut strbuilder, encrinfo); - free(encrinfo as *mut libc::c_void); - let mut chatlist_0: *mut dc_chatlist_t = dc_get_chatlist( + } else { + ret = dc_strdup(b"No chat selected.\x00" as *const u8 as *const libc::c_char) + } + } else if strcmp(cmd, b"sendimage\x00" as *const u8 as *const libc::c_char) == 0i32 + || strcmp(cmd, b"sendfile\x00" as *const u8 as *const libc::c_char) == 0i32 + { + if !sel_chat.is_null() { + if !arg1.is_empty() && !arg2.is_empty() { + let mut msg_0: *mut dc_msg_t = dc_msg_new( context, - 0i32, - 0 as *const libc::c_char, - contact_id_3 as uint32_t, + if strcmp(cmd, b"sendimage\x00" as *const u8 as *const libc::c_char) == 0i32 { + 20i32 + } else { + 60i32 + }, ); - let mut chatlist_cnt: libc::c_int = dc_chatlist_get_cnt(chatlist_0) as libc::c_int; - if chatlist_cnt > 0i32 { - dc_strbuilder_catf( - &mut strbuilder as *mut dc_strbuilder_t, - b"\n\n%i chats shared with Contact#%i: \x00" as *const u8 - as *const libc::c_char, - chatlist_cnt, - contact_id_3, - ); - let mut i_1: libc::c_int = 0i32; - while i_1 < chatlist_cnt { - if 0 != i_1 { - dc_strbuilder_cat( - &mut strbuilder, - b", \x00" as *const u8 as *const libc::c_char, - ); - } - let mut chat_1: *mut dc_chat_t = dc_get_chat( - context, - dc_chatlist_get_chat_id(chatlist_0, i_1 as size_t), - ); - dc_strbuilder_catf( - &mut strbuilder as *mut dc_strbuilder_t, - b"%s#%i\x00" as *const u8 as *const libc::c_char, - chat_prefix(chat_1), - dc_chat_get_id(chat_1), - ); - dc_chat_unref(chat_1); - i_1 += 1 - } - } - dc_chatlist_unref(chatlist_0); - ret = strbuilder.buf + dc_msg_set_file(msg_0, arg1_c.as_ptr(), 0 as *const libc::c_char); + dc_msg_set_text(msg_0, arg2_c.as_ptr()); + dc_send_msg(context, dc_chat_get_id(sel_chat), msg_0); + dc_msg_unref(msg_0); + ret = 2i32 as *mut libc::c_char } else { - ret = dc_strdup( - b"ERROR: Argument missing.\x00" as *const u8 - as *const libc::c_char, - ) + ret = dc_strdup(b"ERROR: No file given.\x00" as *const u8 as *const libc::c_char) } - } else if strcmp(cmd, b"delcontact\x00" as *const u8 as *const libc::c_char) == 0i32 { - if !arg1.is_null() { - ret = if 0 != dc_delete_contact(context, atoi(arg1) as uint32_t) { - 2i32 as *mut libc::c_char + } else { + ret = dc_strdup(b"No chat selected.\x00" as *const u8 as *const libc::c_char) + } + } else if strcmp(cmd, b"listmsgs\x00" as *const u8 as *const libc::c_char) == 0i32 { + if !arg1.is_empty() { + let mut msglist_0: *mut dc_array_t = dc_search_msgs( + context, + if !sel_chat.is_null() { + dc_chat_get_id(sel_chat) } else { - 1i32 as *mut libc::c_char - } - } else { - ret = dc_strdup( - b"ERROR: Argument missing.\x00" as *const u8 - as *const libc::c_char, - ) + 0i32 as libc::c_uint + }, + arg1_c.as_ptr(), + ); + if !msglist_0.is_null() { + log_msglist(context, msglist_0); + ret = dc_mprintf( + b"%i messages.\x00" as *const u8 as *const libc::c_char, + dc_array_get_cnt(msglist_0) as libc::c_int, + ); + dc_array_unref(msglist_0); } - } else if strcmp( - cmd, - b"cleanupcontacts\x00" as *const u8 as *const libc::c_char, - ) == 0i32 - { - ret = if 0 != dc_cleanup_contacts(context) { + } else { + ret = dc_strdup( + b"ERROR: Argument missing.\x00" as *const u8 as *const libc::c_char, + ) + } + } else if strcmp(cmd, b"draft\x00" as *const u8 as *const libc::c_char) == 0i32 { + if !sel_chat.is_null() { + if !arg1.is_empty() { + let mut draft_0: *mut dc_msg_t = dc_msg_new(context, 10i32); + dc_msg_set_text(draft_0, arg1_c.as_ptr()); + dc_set_draft(context, dc_chat_get_id(sel_chat), draft_0); + dc_msg_unref(draft_0); + ret = dc_strdup(b"Draft saved.\x00" as *const u8 as *const libc::c_char) + } else { + dc_set_draft(context, dc_chat_get_id(sel_chat), 0 as *mut dc_msg_t); + ret = dc_strdup(b"Draft deleted.\x00" as *const u8 as *const libc::c_char) + } + } else { + ret = dc_strdup(b"No chat selected.\x00" as *const u8 as *const libc::c_char) + } + } else if strcmp(cmd, b"listmedia\x00" as *const u8 as *const libc::c_char) == 0i32 { + if !sel_chat.is_null() { + let mut images: *mut dc_array_t = + dc_get_chat_media(context, dc_chat_get_id(sel_chat), 20i32, 21i32, 50i32); + let mut i_0: libc::c_int; + let mut icnt: libc::c_int = dc_array_get_cnt(images) as libc::c_int; + ret = dc_mprintf( + b"%i images or videos: \x00" as *const u8 as *const libc::c_char, + icnt, + ); + i_0 = 0i32; + while i_0 < icnt { + let mut temp: *mut libc::c_char = dc_mprintf( + b"%s%sMsg#%i\x00" as *const u8 as *const libc::c_char, + if 0 != i_0 { + b", \x00" as *const u8 as *const libc::c_char + } else { + b"\x00" as *const u8 as *const libc::c_char + }, + ret, + dc_array_get_id(images, i_0 as size_t) as libc::c_int, + ); + free(ret as *mut libc::c_void); + ret = temp; + i_0 += 1 + } + dc_array_unref(images); + } else { + ret = dc_strdup(b"No chat selected.\x00" as *const u8 as *const libc::c_char) + } + } else if strcmp(cmd, b"archive\x00" as *const u8 as *const libc::c_char) == 0i32 + || strcmp(cmd, b"unarchive\x00" as *const u8 as *const libc::c_char) == 0i32 + { + if !arg1.is_empty() { + let mut chat_id_3: libc::c_int = arg1.parse().unwrap(); + dc_archive_chat( + context, + chat_id_3 as uint32_t, + if strcmp(cmd, b"archive\x00" as *const u8 as *const libc::c_char) == 0i32 { + 1i32 + } else { + 0i32 + }, + ); + ret = 2i32 as *mut libc::c_char + } else { + ret = dc_strdup( + b"ERROR: Argument missing.\x00" as *const u8 as *const libc::c_char, + ) + } + } else if strcmp(cmd, b"delchat\x00" as *const u8 as *const libc::c_char) == 0i32 { + if !arg1.is_empty() { + let mut chat_id_4: libc::c_int = arg1.parse().unwrap(); + dc_delete_chat(context, chat_id_4 as uint32_t); + ret = 2i32 as *mut libc::c_char + } else { + ret = dc_strdup( + b"ERROR: Argument missing.\x00" as *const u8 as *const libc::c_char, + ) + } + } else if strcmp(cmd, b"msginfo\x00" as *const u8 as *const libc::c_char) == 0i32 { + if !arg1.is_empty() { + let mut id: libc::c_int = arg1.parse().unwrap(); + ret = dc_get_msg_info(context, id as uint32_t) + } else { + ret = dc_strdup( + b"ERROR: Argument missing.\x00" as *const u8 as *const libc::c_char, + ) + } + } else if strcmp(cmd, b"listfresh\x00" as *const u8 as *const libc::c_char) == 0i32 { + let mut msglist_1: *mut dc_array_t = dc_get_fresh_msgs(context); + if !msglist_1.is_null() { + log_msglist(context, msglist_1); + ret = dc_mprintf( + b"%i fresh messages.\x00" as *const u8 as *const libc::c_char, + dc_array_get_cnt(msglist_1) as libc::c_int, + ); + dc_array_unref(msglist_1); + } + } else if strcmp(cmd, b"forward\x00" as *const u8 as *const libc::c_char) == 0i32 { + if !arg1.is_empty() && !arg2.is_empty() { + let mut msg_ids: [uint32_t; 1] = [0; 1]; + let mut chat_id_5: uint32_t = arg2.parse().unwrap(); + msg_ids[0usize] = arg1.parse().unwrap(); + dc_forward_msgs(context, msg_ids.as_mut_ptr(), 1i32, chat_id_5); + ret = 2i32 as *mut libc::c_char + } else { + ret = dc_strdup( + b"ERROR: Arguments expected.\x00" as *const u8 + as *const libc::c_char, + ) + } + } else if strcmp(cmd, b"markseen\x00" as *const u8 as *const libc::c_char) == 0i32 { + if !arg1.is_empty() { + let mut msg_ids_0: [uint32_t; 1] = [0; 1]; + msg_ids_0[0usize] = arg1.parse().unwrap(); + dc_markseen_msgs(context, msg_ids_0.as_mut_ptr(), 1i32); + ret = 2i32 as *mut libc::c_char + } else { + ret = dc_strdup( + b"ERROR: Argument missing.\x00" as *const u8 as *const libc::c_char, + ) + } + } else if strcmp(cmd, b"star\x00" as *const u8 as *const libc::c_char) == 0i32 + || strcmp(cmd, b"unstar\x00" as *const u8 as *const libc::c_char) == 0i32 + { + if !arg1.is_empty() { + let mut msg_ids_1: [uint32_t; 1] = [0; 1]; + msg_ids_1[0] = arg1.parse().unwrap(); + dc_star_msgs( + context, + msg_ids_1.as_mut_ptr(), + 1i32, + if strcmp(cmd, b"star\x00" as *const u8 as *const libc::c_char) == 0i32 { + 1i32 + } else { + 0i32 + }, + ); + ret = 2i32 as *mut libc::c_char + } else { + ret = dc_strdup( + b"ERROR: Argument missing.\x00" as *const u8 as *const libc::c_char, + ) + } + } else if strcmp(cmd, b"delmsg\x00" as *const u8 as *const libc::c_char) == 0i32 { + if !arg1.is_empty() { + let mut ids: [uint32_t; 1] = [0; 1]; + ids[0usize] = arg1.parse().unwrap(); + dc_delete_msgs(context, ids.as_mut_ptr(), 1i32); + ret = 2i32 as *mut libc::c_char + } else { + ret = dc_strdup( + b"ERROR: Argument missing.\x00" as *const u8 as *const libc::c_char, + ) + } + } else if strcmp(cmd, b"listcontacts\x00" as *const u8 as *const libc::c_char) == 0i32 + || strcmp(cmd, b"contacts\x00" as *const u8 as *const libc::c_char) == 0i32 + || strcmp(cmd, b"listverified\x00" as *const u8 as *const libc::c_char) == 0i32 + { + let mut contacts_0: *mut dc_array_t = dc_get_contacts( + context, + (if strcmp(cmd, b"listverified\x00" as *const u8 as *const libc::c_char) == 0i32 { + 0x1i32 | 0x2i32 + } else { + 0x2i32 + }) as uint32_t, + arg1_c.as_ptr(), + ); + if !contacts_0.is_null() { + log_contactlist(context, contacts_0); + ret = dc_mprintf( + b"%i contacts.\x00" as *const u8 as *const libc::c_char, + dc_array_get_cnt(contacts_0) as libc::c_int, + ); + dc_array_unref(contacts_0); + } else { + ret = 1i32 as *mut libc::c_char + } + } else if strcmp(cmd, b"addcontact\x00" as *const u8 as *const libc::c_char) == 0i32 { + if !arg1.is_empty() && !arg2.is_empty() { + let mut book: *mut libc::c_char = dc_mprintf( + b"%s\n%s\x00" as *const u8 as *const libc::c_char, + arg1_c.as_ptr(), + arg2_c.as_ptr(), + ); + dc_add_address_book(context, book); + ret = 2i32 as *mut libc::c_char; + free(book as *mut libc::c_void); + } else if !arg1.is_empty() { + ret = if 0 != dc_create_contact(context, 0 as *const libc::c_char, arg1_c.as_ptr()) { 2i32 as *mut libc::c_char } else { 1i32 as *mut libc::c_char } - } else if strcmp(cmd, b"getqr\x00" as *const u8 as *const libc::c_char) == 0i32 { - ret = dc_get_securejoin_qr( - context, - (if !arg1.is_null() { atoi(arg1) } else { 0i32 }) as uint32_t, + } else { + ret = dc_strdup( + b"ERROR: Arguments [] expected.\x00" as *const u8 + as *const libc::c_char, + ) + } + } else if strcmp(cmd, b"contactinfo\x00" as *const u8 as *const libc::c_char) == 0i32 { + if !arg1.is_empty() { + let mut contact_id_3: libc::c_int = arg1.parse().unwrap(); + let mut strbuilder: 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 strbuilder, 0i32); + let mut contact: *mut dc_contact_t = dc_get_contact(context, contact_id_3 as uint32_t); + let mut nameNaddr: *mut libc::c_char = dc_contact_get_name_n_addr(contact); + dc_strbuilder_catf( + &mut strbuilder as *mut dc_strbuilder_t, + b"Contact info for: %s:\n\n\x00" as *const u8 as *const libc::c_char, + nameNaddr, ); - if ret.is_null() || *ret.offset(0isize) as libc::c_int == 0i32 { - free(ret as *mut libc::c_void); - ret = 1i32 as *mut libc::c_char - } - } else if strcmp(cmd, b"checkqr\x00" as *const u8 as *const libc::c_char) == 0i32 { - if !arg1.is_null() { - let mut res: *mut dc_lot_t = dc_check_qr(context, arg1); - ret = dc_mprintf( - b"state=%i, id=%i, text1=%s, text2=%s\x00" as *const u8 as *const libc::c_char, - (*res).state as libc::c_int, - (*res).id, - if !(*res).text1.is_null() { - (*res).text1 - } else { - b"\x00" as *const u8 as *const libc::c_char - }, - if !(*res).text2.is_null() { - (*res).text2 - } else { - b"\x00" as *const u8 as *const libc::c_char - }, - ); - dc_lot_unref(res); - } else { - ret = dc_strdup( - b"ERROR: Argument missing.\x00" as *const u8 + free(nameNaddr as *mut libc::c_void); + dc_contact_unref(contact); + let mut encrinfo: *mut libc::c_char = + dc_get_contact_encrinfo(context, contact_id_3 as uint32_t); + dc_strbuilder_cat(&mut strbuilder, encrinfo); + free(encrinfo as *mut libc::c_void); + let mut chatlist_0: *mut dc_chatlist_t = dc_get_chatlist( + context, + 0i32, + 0 as *const libc::c_char, + contact_id_3 as uint32_t, + ); + let mut chatlist_cnt: libc::c_int = dc_chatlist_get_cnt(chatlist_0) as libc::c_int; + if chatlist_cnt > 0i32 { + dc_strbuilder_catf( + &mut strbuilder as *mut dc_strbuilder_t, + b"\n\n%i chats shared with Contact#%i: \x00" as *const u8 as *const libc::c_char, - ) - } - } else if strcmp(cmd, b"event\x00" as *const u8 as *const libc::c_char) == 0i32 { - if !arg1.is_null() { - let mut event = Event::from_u32(atoi(arg1) as u32).unwrap(); - let mut r: uintptr_t = - ((*context).cb)(context, event, 0i32 as uintptr_t, 0i32 as uintptr_t); - ret = dc_mprintf( - b"Sending event %i, received value %i.\x00" as *const u8 as *const libc::c_char, - event as libc::c_int, - r as libc::c_int, - ) - } else { - ret = dc_strdup( - b"ERROR: Argument missing.\x00" as *const u8 as *const libc::c_char, - ) - } - } else if strcmp(cmd, b"fileinfo\x00" as *const u8 as *const libc::c_char) == 0i32 { - if !arg1.is_null() { - let mut buf: *mut libc::c_uchar = 0 as *mut libc::c_uchar; - let mut buf_bytes: size_t = 0; - let mut w: uint32_t = 0; - let mut h: uint32_t = 0; - if 0 != dc_read_file( - context, - arg1, - &mut buf as *mut *mut libc::c_uchar as *mut *mut libc::c_void, - &mut buf_bytes, - ) { - dc_get_filemeta(buf as *const libc::c_void, buf_bytes, &mut w, &mut h); - ret = dc_mprintf( - b"width=%i, height=%i\x00" as *const u8 as *const libc::c_char, - w as libc::c_int, - h as libc::c_int, - ) - } else { - ret = - dc_strdup(b"ERROR: Command failed.\x00" as *const u8 as *const libc::c_char) + chatlist_cnt, + contact_id_3, + ); + let mut i_1: libc::c_int = 0i32; + while i_1 < chatlist_cnt { + if 0 != i_1 { + dc_strbuilder_cat( + &mut strbuilder, + b", \x00" as *const u8 as *const libc::c_char, + ); + } + let mut chat_1: *mut dc_chat_t = + dc_get_chat(context, dc_chatlist_get_chat_id(chatlist_0, i_1 as size_t)); + dc_strbuilder_catf( + &mut strbuilder as *mut dc_strbuilder_t, + b"%s#%i\x00" as *const u8 as *const libc::c_char, + chat_prefix(chat_1), + dc_chat_get_id(chat_1), + ); + dc_chat_unref(chat_1); + i_1 += 1 } - free(buf as *mut libc::c_void); + } + dc_chatlist_unref(chatlist_0); + ret = strbuilder.buf + } else { + ret = dc_strdup( + b"ERROR: Argument missing.\x00" as *const u8 as *const libc::c_char, + ) + } + } else if strcmp(cmd, b"delcontact\x00" as *const u8 as *const libc::c_char) == 0i32 { + if !arg1.is_empty() { + ret = if 0 != dc_delete_contact(context, arg1.parse().unwrap()) { + 2i32 as *mut libc::c_char } else { - ret = dc_strdup( - b"ERROR: Argument missing.\x00" as *const u8 as *const libc::c_char, - ) + 1i32 as *mut libc::c_char } } else { - ret = 3i32 as *mut libc::c_char + ret = dc_strdup( + b"ERROR: Argument missing.\x00" as *const u8 as *const libc::c_char, + ) } + } else if strcmp(cmd, b"getqr\x00" as *const u8 as *const libc::c_char) == 0i32 { + ret = dc_get_securejoin_qr( + context, + (if !arg1.is_empty() { + arg1.parse().unwrap() + } else { + 0i32 + }) as uint32_t, + ); + if ret.is_null() || *ret.offset(0isize) as libc::c_int == 0i32 { + free(ret as *mut libc::c_void); + ret = 1i32 as *mut libc::c_char + } + } else if strcmp(cmd, b"checkqr\x00" as *const u8 as *const libc::c_char) == 0i32 { + if !arg1.is_empty() { + let mut res: *mut dc_lot_t = dc_check_qr(context, arg1_c.as_ptr()); + ret = dc_mprintf( + b"state=%i, id=%i, text1=%s, text2=%s\x00" as *const u8 as *const libc::c_char, + (*res).state as libc::c_int, + (*res).id, + if !(*res).text1.is_null() { + (*res).text1 + } else { + b"\x00" as *const u8 as *const libc::c_char + }, + if !(*res).text2.is_null() { + (*res).text2 + } else { + b"\x00" as *const u8 as *const libc::c_char + }, + ); + dc_lot_unref(res); + } else { + ret = dc_strdup( + b"ERROR: Argument missing.\x00" as *const u8 as *const libc::c_char, + ) + } + } else if strcmp(cmd, b"event\x00" as *const u8 as *const libc::c_char) == 0i32 { + if !arg1.is_empty() { + let mut event = Event::from_u32(arg1.parse().unwrap()).unwrap(); + let mut r: uintptr_t = + (context.cb)(context, event, 0i32 as uintptr_t, 0i32 as uintptr_t); + ret = dc_mprintf( + b"Sending event %i, received value %i.\x00" as *const u8 as *const libc::c_char, + event as libc::c_int, + r as libc::c_int, + ) + } else { + ret = + dc_strdup(b"ERROR: Argument missing.\x00" as *const u8 as *const libc::c_char) + } + } else if strcmp(cmd, b"fileinfo\x00" as *const u8 as *const libc::c_char) == 0i32 { + if !arg1.is_empty() { + let mut buf: *mut libc::c_uchar = 0 as *mut libc::c_uchar; + let mut buf_bytes: size_t = 0; + let mut w: uint32_t = 0; + let mut h: uint32_t = 0; + + if 0 != dc_read_file( + context, + arg1_c.as_ptr(), + &mut buf as *mut *mut libc::c_uchar as *mut *mut libc::c_void, + &mut buf_bytes, + ) { + dc_get_filemeta(buf as *const libc::c_void, buf_bytes, &mut w, &mut h); + ret = dc_mprintf( + b"width=%i, height=%i\x00" as *const u8 as *const libc::c_char, + w as libc::c_int, + h as libc::c_int, + ) + } else { + ret = dc_strdup(b"ERROR: Command failed.\x00" as *const u8 as *const libc::c_char) + } + free(buf as *mut libc::c_void); + } else { + ret = dc_strdup( + b"ERROR: Argument missing.\x00" as *const u8 as *const libc::c_char, + ) + } + } else { + ret = 3i32 as *mut libc::c_char } + if ret == 2i32 as *mut libc::c_char { ret = dc_strdup(b"Command executed successfully.\x00" as *const u8 as *const libc::c_char) } else if ret == 1i32 as *mut libc::c_char { @@ -1808,8 +1672,7 @@ pub unsafe extern "C" fn dc_cmdline( } if !sel_chat.is_null() { dc_chat_unref(sel_chat); - sel_chat = 0 as *mut dc_chat_t } free(cmd as *mut libc::c_void); - return ret; + ret } diff --git a/examples/repl/main.rs b/examples/repl/main.rs index 9dda5a618..b53b2d2cb 100644 --- a/examples/repl/main.rs +++ b/examples/repl/main.rs @@ -11,7 +11,6 @@ non_camel_case_types, non_snake_case, non_upper_case_globals, - unused_assignments, unused_mut, unused_attributes, non_upper_case_globals, @@ -21,6 +20,7 @@ use std::ffi::CString; use std::io::{self, Write}; +use std::sync::{Arc, RwLock}; use deltachat::constants::*; use deltachat::dc_aheader::*; @@ -67,35 +67,28 @@ use deltachat::dc_token::*; use deltachat::dc_tools::*; use deltachat::types::*; use deltachat::x::*; -use libc; - mod cmdline; -mod stress; use self::cmdline::*; -use self::stress::*; /* ****************************************************************************** * Event Handler ******************************************************************************/ -static mut s_do_log_info: libc::c_int = 1i32; unsafe extern "C" fn receive_event( - mut context: *mut dc_context_t, - mut event: Event, - mut data1: uintptr_t, - mut data2: uintptr_t, + context: &dc_context_t, + event: Event, + data1: uintptr_t, + data2: uintptr_t, ) -> uintptr_t { match event as u32 { 2091 => {} 100 => { /* do not show the event as this would fill the screen */ - if 0 != s_do_log_info { - printf( - b"%s\n\x00" as *const u8 as *const libc::c_char, - data2 as *mut libc::c_char, - ); - } + printf( + b"%s\n\x00" as *const u8 as *const libc::c_char, + data2 as *mut libc::c_char, + ); } 101 => { printf( @@ -154,7 +147,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 { @@ -270,111 +263,88 @@ unsafe extern "C" fn receive_event( /* ****************************************************************************** * Threads for waiting for messages and for jobs ******************************************************************************/ -static mut inbox_thread: pthread_t = 0 as pthread_t; static mut run_threads: libc::c_int = 0i32; -unsafe extern "C" fn inbox_thread_entry_point( - mut entry_arg: *mut libc::c_void, -) -> *mut libc::c_void { - let mut context: *mut dc_context_t = entry_arg as *mut dc_context_t; - while 0 != run_threads { - dc_perform_imap_jobs(context); - dc_perform_imap_fetch(context); - if 0 != run_threads { - dc_perform_imap_idle(context); +unsafe fn start_threads( + c: Arc>, +) -> ( + std::thread::JoinHandle<()>, + std::thread::JoinHandle<()>, + std::thread::JoinHandle<()>, + std::thread::JoinHandle<()>, +) { + run_threads = 1; + + let ctx = c.clone(); + let h1 = std::thread::spawn(move || { + let context = ctx.read().unwrap(); + while 0 != run_threads { + dc_perform_imap_jobs(&context); + dc_perform_imap_fetch(&context); + if 0 != run_threads { + dc_perform_imap_idle(&context); + } } - } - return 0 as *mut libc::c_void; -} -static mut mvbox_thread: pthread_t = 0 as pthread_t; -unsafe extern "C" fn mvbox_thread_entry_point( - mut entry_arg: *mut libc::c_void, -) -> *mut libc::c_void { - let mut context: *mut dc_context_t = entry_arg as *mut dc_context_t; - while 0 != run_threads { - dc_perform_mvbox_fetch(context); - if 0 != run_threads { - dc_perform_mvbox_idle(context); + }); + + let ctx = c.clone(); + let h2 = std::thread::spawn(move || { + let context = ctx.read().unwrap(); + while 0 != run_threads { + dc_perform_mvbox_fetch(&context); + if 0 != run_threads { + dc_perform_mvbox_idle(&context); + } } - } - return 0 as *mut libc::c_void; -} -static mut sentbox_thread: pthread_t = 0 as pthread_t; -unsafe extern "C" fn sentbox_thread_entry_point( - mut entry_arg: *mut libc::c_void, -) -> *mut libc::c_void { - let mut context: *mut dc_context_t = entry_arg as *mut dc_context_t; - while 0 != run_threads { - dc_perform_sentbox_fetch(context); - if 0 != run_threads { - dc_perform_sentbox_idle(context); + }); + + let ctx = c.clone(); + let h3 = std::thread::spawn(move || { + let context = ctx.read().unwrap(); + while 0 != run_threads { + dc_perform_sentbox_fetch(&context); + if 0 != run_threads { + dc_perform_sentbox_idle(&context); + } } - } - return 0 as *mut libc::c_void; -} -static mut smtp_thread: pthread_t = 0 as pthread_t; -unsafe extern "C" fn smtp_thread_entry_point( - mut entry_arg: *mut libc::c_void, -) -> *mut libc::c_void { - let mut context: *mut dc_context_t = entry_arg as *mut dc_context_t; - while 0 != run_threads { - dc_perform_smtp_jobs(context); - if 0 != run_threads { - dc_perform_smtp_idle(context); + }); + + let ctx = c.clone(); + let h4 = std::thread::spawn(move || { + let context = ctx.read().unwrap(); + while 0 != run_threads { + dc_perform_smtp_jobs(&context); + if 0 != run_threads { + dc_perform_smtp_idle(&context); + } } - } - return 0 as *mut libc::c_void; + }); + + (h1, h2, h3, h4) } -unsafe extern "C" fn start_threads(mut context: *mut dc_context_t) { - run_threads = 1i32; - if inbox_thread == 0 { - pthread_create( - &mut inbox_thread, - 0 as *const pthread_attr_t, - Some(inbox_thread_entry_point), - context as *mut libc::c_void, - ); - } - if mvbox_thread == 0 { - pthread_create( - &mut mvbox_thread, - 0 as *const pthread_attr_t, - Some(mvbox_thread_entry_point), - context as *mut libc::c_void, - ); - } - if sentbox_thread == 0 { - pthread_create( - &mut sentbox_thread, - 0 as *const pthread_attr_t, - Some(sentbox_thread_entry_point), - context as *mut libc::c_void, - ); - } - if smtp_thread == 0 { - pthread_create( - &mut smtp_thread, - 0 as *const pthread_attr_t, - Some(smtp_thread_entry_point), - context as *mut libc::c_void, - ); - }; -} -unsafe extern "C" fn stop_threads(mut context: *mut dc_context_t) { + +unsafe fn stop_threads( + context: &dc_context_t, + handles: Option<( + std::thread::JoinHandle<()>, + std::thread::JoinHandle<()>, + std::thread::JoinHandle<()>, + std::thread::JoinHandle<()>, + )>, +) { run_threads = 0i32; dc_interrupt_imap_idle(context); dc_interrupt_mvbox_idle(context); dc_interrupt_sentbox_idle(context); dc_interrupt_smtp_idle(context); - pthread_join(inbox_thread, 0 as *mut *mut libc::c_void); - pthread_join(mvbox_thread, 0 as *mut *mut libc::c_void); - pthread_join(sentbox_thread, 0 as *mut *mut libc::c_void); - pthread_join(smtp_thread, 0 as *mut *mut libc::c_void); - inbox_thread = 0 as pthread_t; - mvbox_thread = 0 as pthread_t; - sentbox_thread = 0 as pthread_t; - smtp_thread = 0 as pthread_t; + if let Some((h1, h2, h3, h4)) = handles { + h1.join().unwrap(); + h2.join().unwrap(); + h3.join().unwrap(); + h4.join().unwrap(); + } } + /* ****************************************************************************** * The main loop ******************************************************************************/ @@ -387,24 +357,18 @@ fn read_cmd() -> String { input.trim_end().to_string() } -#[cfg(not(target_os = "android"))] unsafe fn main_0(mut argc: libc::c_int, mut argv: *mut *mut libc::c_char) -> libc::c_int { let mut cmd: *mut libc::c_char = 0 as *mut libc::c_char; - let mut context: *mut dc_context_t = dc_context_new( + let mut context = dc_context_new( receive_event, 0 as *mut libc::c_void, b"CLI\x00" as *const u8 as *const libc::c_char, ); - let mut stresstest_only: libc::c_int = 0i32; + dc_cmdline_skip_auth(); + if argc == 2i32 { - if strcmp( - *argv.offset(1isize), - b"--stress\x00" as *const u8 as *const libc::c_char, - ) == 0i32 - { - stresstest_only = 1i32 - } else if 0 == dc_open(context, *argv.offset(1isize), 0 as *const libc::c_char) { + if 0 == dc_open(&mut context, *argv.offset(1isize), 0 as *const libc::c_char) { printf( b"ERROR: Cannot open %s.\n\x00" as *const u8 as *const libc::c_char, *argv.offset(1isize), @@ -413,13 +377,13 @@ unsafe fn main_0(mut argc: libc::c_int, mut argv: *mut *mut libc::c_char) -> lib } else if argc != 1i32 { printf(b"ERROR: Bad arguments\n\x00" as *const u8 as *const libc::c_char); } - s_do_log_info = 0i32; - stress_functions(context); - s_do_log_info = 1i32; - if 0 != stresstest_only { - return 0i32; - } + printf(b"Delta Chat Core is awaiting your commands.\n\x00" as *const u8 as *const libc::c_char); + + let mut handles = None; + + let ctx = Arc::new(RwLock::new(context)); + loop { /* read command */ let cmdline = read_cmd(); @@ -431,9 +395,10 @@ unsafe fn main_0(mut argc: libc::c_int, mut argv: *mut *mut libc::c_char) -> lib arg1 = arg1.offset(1isize) } if strcmp(cmd, b"connect\x00" as *const u8 as *const libc::c_char) == 0i32 { - start_threads(context); + handles = Some(start_threads(ctx.clone())); } else if strcmp(cmd, b"disconnect\x00" as *const u8 as *const libc::c_char) == 0i32 { - stop_threads(context); + stop_threads(&ctx.read().unwrap(), handles); + handles = None; } else if strcmp(cmd, b"smtp-jobs\x00" as *const u8 as *const libc::c_char) == 0i32 { if 0 != run_threads { printf( @@ -441,7 +406,7 @@ unsafe fn main_0(mut argc: libc::c_int, mut argv: *mut *mut libc::c_char) -> lib as *const libc::c_char, ); } else { - dc_perform_smtp_jobs(context); + dc_perform_smtp_jobs(&ctx.read().unwrap()); } } else if strcmp(cmd, b"imap-jobs\x00" as *const u8 as *const libc::c_char) == 0i32 { if 0 != run_threads { @@ -450,19 +415,21 @@ unsafe fn main_0(mut argc: libc::c_int, mut argv: *mut *mut libc::c_char) -> lib as *const libc::c_char, ); } else { - dc_perform_imap_jobs(context); + dc_perform_imap_jobs(&ctx.read().unwrap()); } } else if strcmp(cmd, b"configure\x00" as *const u8 as *const libc::c_char) == 0i32 { - start_threads(context); - dc_configure(context); + 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(context, b"addr\x00" as *const u8 as *const libc::c_char); + let mut addr: *mut libc::c_char = dc_get_config( + &ctx.read().unwrap(), + b"addr\x00" as *const u8 as *const libc::c_char, + ); if addr.is_null() || *addr.offset(0isize) as libc::c_int == 0i32 { printf(b"oauth2: set addr first.\n\x00" as *const u8 as *const libc::c_char); } else { let mut oauth2_url: *mut libc::c_char = dc_get_oauth2_url( - context, + &ctx.read().unwrap(), addr, b"chat.delta:/com.b44t.messenger\x00" as *const u8 as *const libc::c_char, ); @@ -485,9 +452,9 @@ 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 { - start_threads(context); + handles = Some(start_threads(ctx.clone())); let mut qrstr: *mut libc::c_char = dc_get_securejoin_qr( - context, + &ctx.read().unwrap(), (if !arg1.is_null() { atoi(arg1) } else { 0i32 }) as uint32_t, ); if !qrstr.is_null() && 0 != *qrstr.offset(0isize) as libc::c_int { @@ -510,16 +477,17 @@ 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 { - start_threads(context); + handles = Some(start_threads(ctx.clone())); if !arg1.is_null() { - dc_join_securejoin(context, arg1); + dc_join_securejoin(&ctx.read().unwrap(), arg1); } } else { if strcmp(cmd, b"exit\x00" as *const u8 as *const libc::c_char) == 0i32 { break; } if !(*cmd.offset(0isize) as libc::c_int == 0i32) { - let mut execute_result: *mut libc::c_char = dc_cmdline(context, &cmdline); + let mut execute_result: *mut libc::c_char = + dc_cmdline(&ctx.read().unwrap(), &cmdline); if !execute_result.is_null() { printf( b"%s\n\x00" as *const u8 as *const libc::c_char, @@ -530,12 +498,17 @@ unsafe fn main_0(mut argc: libc::c_int, mut argv: *mut *mut libc::c_char) -> lib } } } - free(cmd as *mut libc::c_void); - stop_threads(context); - dc_close(context); - dc_context_unref(context); - context = 0 as *mut dc_context_t; - return 0i32; + + let ctx = ctx.clone(); + + { + let mut ctx = ctx.write().unwrap(); + free(cmd as *mut libc::c_void); + stop_threads(&ctx, handles); + dc_close(&mut ctx); + dc_context_unref(&mut ctx); + } + 0 } pub fn main() { diff --git a/examples/simple.rs b/examples/simple.rs index fbfb70525..5d892dd73 100644 --- a/examples/simple.rs +++ b/examples/simple.rs @@ -1,7 +1,8 @@ extern crate deltachat; use std::ffi::{CStr, CString}; -use std::ptr::NonNull; +use std::sync::Arc; +use std::{thread, time}; use tempfile::tempdir; use deltachat::constants::Event; @@ -16,10 +17,14 @@ use deltachat::dc_job::{ }; use deltachat::dc_lot::*; -extern "C" fn cb(_ctx: *mut dc_context_t, event: Event, data1: usize, data2: usize) -> usize { +extern "C" fn cb(_ctx: &dc_context_t, event: Event, data1: usize, data2: usize) -> 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() }; @@ -49,61 +54,60 @@ extern "C" fn cb(_ctx: *mut dc_context_t, event: Event, data1: usize, data2: usi } } -struct Wrapper(NonNull); - -unsafe impl std::marker::Send for Wrapper {} -unsafe impl std::marker::Sync for Wrapper {} - fn main() { unsafe { let ctx = dc_context_new(cb, std::ptr::null_mut(), std::ptr::null_mut()); - let info = dc_get_info(ctx); + let info = dc_get_info(&ctx); let info_s = CStr::from_ptr(info); + let duration = time::Duration::from_millis(4000); println!("info: {}", info_s.to_str().unwrap()); - let sendable_ctx = Wrapper(NonNull::new(ctx).unwrap()); - let t1 = std::thread::spawn(move || loop { - dc_perform_imap_jobs(sendable_ctx.0.as_ptr()); - dc_perform_imap_fetch(sendable_ctx.0.as_ptr()); - dc_perform_imap_idle(sendable_ctx.0.as_ptr()); + let ctx = Arc::new(ctx); + let ctx1 = ctx.clone(); + let t1 = thread::spawn(move || loop { + dc_perform_imap_jobs(&ctx1); + dc_perform_imap_fetch(&ctx1); + dc_perform_imap_idle(&ctx1); }); - let sendable_ctx = Wrapper(NonNull::new(ctx).unwrap()); - let t2 = std::thread::spawn(move || loop { - dc_perform_smtp_jobs(sendable_ctx.0.as_ptr()); - dc_perform_smtp_idle(sendable_ctx.0.as_ptr()); + let ctx1 = ctx.clone(); + let t2 = thread::spawn(move || loop { + dc_perform_smtp_jobs(&ctx1); + dc_perform_smtp_idle(&ctx1); }); let dir = tempdir().unwrap(); let dbfile = CString::new(dir.path().join("db.sqlite").to_str().unwrap()).unwrap(); println!("opening database {:?}", dbfile); - dc_open(ctx, dbfile.as_ptr(), std::ptr::null()); + + dc_open(&ctx, dbfile.as_ptr(), std::ptr::null()); println!("configuring"); + let pw = std::env::args().collect::>()[1].clone(); dc_set_config( - ctx, + &ctx, CString::new("addr").unwrap().as_ptr(), CString::new("d@testrun.org").unwrap().as_ptr(), ); dc_set_config( - ctx, + &ctx, CString::new("mail_pw").unwrap().as_ptr(), - CString::new("***").unwrap().as_ptr(), + CString::new(pw).unwrap().as_ptr(), ); - dc_configure(ctx); + dc_configure(&ctx); - std::thread::sleep_ms(4000); + thread::sleep(duration); let email = CString::new("dignifiedquire@gmail.com").unwrap(); println!("sending a message"); - 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 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, chat_id, msg_text.as_ptr()); + dc_send_text_msg(&ctx, chat_id, msg_text.as_ptr()); println!("fetching chats.."); - let chats = dc_get_chatlist(ctx, 0, std::ptr::null(), 0); + let chats = dc_get_chatlist(&ctx, 0, std::ptr::null(), 0); for i in 0..dc_chatlist_get_cnt(chats) { let summary = dc_chatlist_get_summary(chats, 0, std::ptr::null_mut()); @@ -125,7 +129,7 @@ fn main() { } dc_chatlist_unref(chats); - // let msglist = dc_get_chat_msgs(ctx, 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/constants.rs b/src/constants.rs index b1790e904..e2c2e5cc5 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -2,6 +2,11 @@ pub const VERSION: &'static [u8; 7] = b"0.43.0\x00"; +pub const DC_MOVE_STATE_MOVING: u32 = 3; +pub const DC_MOVE_STATE_STAY: u32 = 2; +pub const DC_MOVE_STATE_PENDING: u32 = 1; +pub const DC_MOVE_STATE_UNDEFINED: u32 = 0; + pub const DC_GCL_ARCHIVED_ONLY: usize = 0x01; pub const DC_GCL_NO_SPECIALS: usize = 0x02; pub const DC_GCL_ADD_ALLDONE_HINT: usize = 0x04; @@ -88,6 +93,8 @@ pub const DC_TEXT1_DRAFT: usize = 1; pub const DC_TEXT1_USERNAME: usize = 2; pub const DC_TEXT1_SELF: usize = 3; +pub const DC_CREATE_MVBOX: usize = 1; + /// Text message. /// The text of the message is set using dc_msg_set_text() /// and retrieved with dc_msg_get_text(). diff --git a/src/dc_aheader.rs b/src/dc_aheader.rs index 79a36b78a..b23d75532 100644 --- a/src/dc_aheader.rs +++ b/src/dc_aheader.rs @@ -1,4 +1,4 @@ -use libc; +use mmime::mailimf_types::*; use crate::dc_contact::*; use crate::dc_key::*; @@ -34,7 +34,7 @@ pub unsafe fn dc_aheader_new_from_imffields( mut wanted_from: *const libc::c_char, mut header: *const mailimf_fields, ) -> *mut dc_aheader_t { - let mut cur = 0 as *mut clistiter; + let mut cur; let mut fine_header = 0 as *mut dc_aheader_t; if wanted_from.is_null() || header.is_null() { @@ -78,7 +78,7 @@ pub unsafe fn dc_aheader_new_from_imffields( cur = if !cur.is_null() { (*cur).next } else { - 0 as *mut clistcell_s + 0 as *mut clistcell } } @@ -105,10 +105,10 @@ pub unsafe fn dc_aheader_set_from_string( (b) for the key, non-base64-characters are ignored and (c) for parsing, we ignore `\r\n` as well as tabs for spaces */ let mut header_str = 0 as *mut libc::c_char; - let mut p = 0 as *mut libc::c_char; - let mut beg_attr_name = 0 as *mut libc::c_char; - let mut after_attr_name = 0 as *mut libc::c_char; - let mut beg_attr_value = 0 as *mut libc::c_char; + let mut p; + let mut beg_attr_name; + let mut after_attr_name; + let mut beg_attr_value; let mut success: libc::c_int = 0; dc_aheader_empty(aheader); @@ -263,12 +263,8 @@ pub unsafe fn dc_aheader_render(mut aheader: *const dc_aheader_t) -> *mut libc:: // TODO replace 78 with enum /rtn /* adds a whitespace every 78 characters, this allows libEtPan to wrap the lines according to RFC 5322 (which may insert a linebreak before every whitespace) */ - keybase64_wrapped = dc_key_render_base64( - (*aheader).public_key, - 78, - b" \x00" as *const u8 as *const libc::c_char, - 0, - ); + keybase64_wrapped = dc_key_render_base64((*aheader).public_key, 78); + if !keybase64_wrapped.is_null() { /*no checksum*/ dc_strbuilder_cat(&mut ret, keybase64_wrapped); diff --git a/src/dc_apeerstate.rs b/src/dc_apeerstate.rs index 71857bff4..ef538d5ee 100644 --- a/src/dc_apeerstate.rs +++ b/src/dc_apeerstate.rs @@ -1,5 +1,3 @@ -use libc; - use crate::dc_aheader::*; use crate::dc_chat::*; use crate::dc_context::dc_context_t; @@ -11,14 +9,14 @@ use crate::types::*; use crate::x::*; /* prefer-encrypt states */ -/* * +/** * @class dc_apeerstate_t * Library-internal. */ #[derive(Copy, Clone)] #[repr(C)] -pub struct dc_apeerstate_t { - pub context: *mut dc_context_t, +pub struct dc_apeerstate_t<'a> { + pub context: &'a dc_context_t, pub addr: *mut libc::c_char, pub last_seen: time_t, pub last_seen_autocrypt: time_t, @@ -35,20 +33,23 @@ pub struct dc_apeerstate_t { } /* the returned pointer is ref'd and must be unref'd after usage */ -pub unsafe fn dc_apeerstate_new(mut context: *mut dc_context_t) -> *mut dc_apeerstate_t { - let mut peerstate: *mut dc_apeerstate_t = 0 as *mut dc_apeerstate_t; +pub unsafe fn dc_apeerstate_new<'a>(context: &'a dc_context_t) -> *mut dc_apeerstate_t<'a> { + let mut peerstate: *mut dc_apeerstate_t; peerstate = calloc(1, ::std::mem::size_of::()) as *mut dc_apeerstate_t; if peerstate.is_null() { exit(43i32); } (*peerstate).context = context; - return peerstate; + + peerstate } + pub unsafe fn dc_apeerstate_unref(mut peerstate: *mut dc_apeerstate_t) { dc_apeerstate_empty(peerstate); free(peerstate as *mut libc::c_void); } -/* ****************************************************************************** + +/******************************************************************************* * dc_apeerstate_t represents the state of an Autocrypt peer - Load/save ******************************************************************************/ unsafe fn dc_apeerstate_empty(mut peerstate: *mut dc_apeerstate_t) { @@ -76,6 +77,8 @@ unsafe fn dc_apeerstate_empty(mut peerstate: *mut dc_apeerstate_t) { (*peerstate).verified_key = 0 as *mut dc_key_t; (*peerstate).degrade_event = 0i32; } + +// TODO should return bool /rtn pub unsafe fn dc_apeerstate_init_from_header( mut peerstate: *mut dc_apeerstate_t, mut header: *const dc_aheader_t, @@ -93,8 +96,11 @@ pub unsafe fn dc_apeerstate_init_from_header( (*peerstate).public_key = dc_key_new(); dc_key_set_from_key((*peerstate).public_key, (*header).public_key); dc_apeerstate_recalc_fingerprint(peerstate); - return 1i32; + + 1 } + +// TODO should return bool /rtn pub unsafe fn dc_apeerstate_recalc_fingerprint(mut peerstate: *mut dc_apeerstate_t) -> libc::c_int { let mut success: libc::c_int = 0i32; let mut old_public_fingerprint: *mut libc::c_char = 0 as *mut libc::c_char; @@ -102,7 +108,8 @@ pub unsafe fn dc_apeerstate_recalc_fingerprint(mut peerstate: *mut dc_apeerstate if !peerstate.is_null() { if !(*peerstate).public_key.is_null() { old_public_fingerprint = (*peerstate).public_key_fingerprint; - (*peerstate).public_key_fingerprint = dc_key_get_fingerprint((*peerstate).public_key); + (*peerstate).public_key_fingerprint = + dc_key_get_fingerprint((*peerstate).context, (*peerstate).public_key); if old_public_fingerprint.is_null() || *old_public_fingerprint.offset(0isize) as libc::c_int == 0i32 || (*peerstate).public_key_fingerprint.is_null() @@ -119,7 +126,8 @@ pub unsafe fn dc_apeerstate_recalc_fingerprint(mut peerstate: *mut dc_apeerstate } if !(*peerstate).gossip_key.is_null() { old_gossip_fingerprint = (*peerstate).gossip_key_fingerprint; - (*peerstate).gossip_key_fingerprint = dc_key_get_fingerprint((*peerstate).gossip_key); + (*peerstate).gossip_key_fingerprint = + dc_key_get_fingerprint((*peerstate).context, (*peerstate).gossip_key); if old_gossip_fingerprint.is_null() || *old_gossip_fingerprint.offset(0isize) as libc::c_int == 0i32 || (*peerstate).gossip_key_fingerprint.is_null() @@ -136,10 +144,14 @@ pub unsafe fn dc_apeerstate_recalc_fingerprint(mut peerstate: *mut dc_apeerstate } success = 1i32 } + free(old_public_fingerprint as *mut libc::c_void); free(old_gossip_fingerprint as *mut libc::c_void); - return success; + + success } + +// TODO should return bool /rtn pub unsafe extern "C" fn dc_apeerstate_init_from_gossip( mut peerstate: *mut dc_apeerstate_t, mut gossip_header: *const dc_aheader_t, @@ -155,8 +167,11 @@ pub unsafe extern "C" fn dc_apeerstate_init_from_gossip( (*peerstate).gossip_key = dc_key_new(); dc_key_set_from_key((*peerstate).gossip_key, (*gossip_header).public_key); dc_apeerstate_recalc_fingerprint(peerstate); - return 1i32; + + 1 } + +// TODO should return bool /rtn pub unsafe fn dc_apeerstate_degrade_encryption( mut peerstate: *mut dc_apeerstate_t, mut message_time: time_t, @@ -170,8 +185,10 @@ pub unsafe fn dc_apeerstate_degrade_encryption( (*peerstate).prefer_encrypt = 20i32; (*peerstate).last_seen = message_time; (*peerstate).to_save |= 0x2i32; - return 1i32; + + 1 } + pub unsafe fn dc_apeerstate_apply_header( mut peerstate: *mut dc_apeerstate_t, mut header: *const dc_aheader_t, @@ -209,6 +226,7 @@ pub unsafe fn dc_apeerstate_apply_header( } }; } + pub unsafe fn dc_apeerstate_apply_gossip( mut peerstate: *mut dc_apeerstate_t, mut gossip_header: *const dc_aheader_t, @@ -236,6 +254,7 @@ pub unsafe fn dc_apeerstate_apply_gossip( } }; } + pub unsafe fn dc_apeerstate_render_gossip_header( mut peerstate: *const dc_apeerstate_t, mut min_verified: libc::c_int, @@ -249,8 +268,9 @@ pub unsafe fn dc_apeerstate_render_gossip_header( ret = dc_aheader_render(autocryptheader) } dc_aheader_unref(autocryptheader); - return ret; + ret } + pub unsafe fn dc_apeerstate_peek_key( mut peerstate: *const dc_apeerstate_t, mut min_verified: libc::c_int, @@ -274,8 +294,10 @@ pub unsafe fn dc_apeerstate_peek_key( if !(*peerstate).public_key.is_null() { return (*peerstate).public_key; } - return (*peerstate).gossip_key; + (*peerstate).gossip_key } + +// TODO should return bool /rtn pub unsafe fn dc_apeerstate_set_verified( mut peerstate: *mut dc_apeerstate_t, mut which_key: libc::c_int, @@ -307,19 +329,24 @@ pub unsafe fn dc_apeerstate_set_verified( success = 1i32 } } - return success; + + success } + +// TODO should return bool /rtn pub unsafe fn dc_apeerstate_load_by_addr( mut peerstate: *mut dc_apeerstate_t, - mut sql: *mut dc_sqlite3_t, + mut sql: &dc_sqlite3_t, mut addr: *const libc::c_char, ) -> libc::c_int { let mut success: libc::c_int = 0i32; let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; - if !(peerstate.is_null() || sql.is_null() || addr.is_null()) { + if !(peerstate.is_null() || addr.is_null()) { dc_apeerstate_empty(peerstate); stmt = - dc_sqlite3_prepare(sql, + dc_sqlite3_prepare( + (*peerstate).context, + sql, b"SELECT addr, last_seen, last_seen_autocrypt, prefer_encrypted, public_key, gossip_timestamp, gossip_key, public_key_fingerprint, gossip_key_fingerprint, verified_key, verified_key_fingerprint FROM acpeerstates WHERE addr=? COLLATE NOCASE;\x00" as *const u8 as *const libc::c_char); sqlite3_bind_text(stmt, 1i32, addr, -1i32, None); @@ -329,8 +356,9 @@ pub unsafe fn dc_apeerstate_load_by_addr( } } sqlite3_finalize(stmt); - return success; + success } + unsafe fn dc_apeerstate_set_from_stmt( mut peerstate: *mut dc_apeerstate_t, mut stmt: *mut sqlite3_stmt, @@ -359,18 +387,22 @@ unsafe fn dc_apeerstate_set_from_stmt( dc_key_set_from_stmt((*peerstate).verified_key, stmt, 9i32, 0i32); }; } + +// TODO should return bool /rtn pub unsafe fn dc_apeerstate_load_by_fingerprint( mut peerstate: *mut dc_apeerstate_t, - mut sql: *mut dc_sqlite3_t, + mut sql: &dc_sqlite3_t, mut fingerprint: *const libc::c_char, ) -> libc::c_int { let mut success: libc::c_int = 0i32; let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; - if !(peerstate.is_null() || sql.is_null() || fingerprint.is_null()) { + if !(peerstate.is_null() || fingerprint.is_null()) { dc_apeerstate_empty(peerstate); stmt = - dc_sqlite3_prepare(sql, - b"SELECT addr, last_seen, last_seen_autocrypt, prefer_encrypted, public_key, gossip_timestamp, gossip_key, public_key_fingerprint, gossip_key_fingerprint, verified_key, verified_key_fingerprint FROM acpeerstates WHERE public_key_fingerprint=? COLLATE NOCASE OR gossip_key_fingerprint=? COLLATE NOCASE ORDER BY public_key_fingerprint=? DESC;\x00" + dc_sqlite3_prepare( + (*peerstate).context, + sql, + b"SELECT addr, last_seen, last_seen_autocrypt, prefer_encrypted, public_key, gossip_timestamp, gossip_key, public_key_fingerprint, gossip_key_fingerprint, verified_key, verified_key_fingerprint FROM acpeerstates WHERE public_key_fingerprint=? COLLATE NOCASE OR gossip_key_fingerprint=? COLLATE NOCASE ORDER BY public_key_fingerprint=? DESC;\x00" as *const u8 as *const libc::c_char); sqlite3_bind_text(stmt, 1i32, fingerprint, -1i32, None); sqlite3_bind_text(stmt, 2i32, fingerprint, -1i32, None); @@ -381,21 +413,24 @@ pub unsafe fn dc_apeerstate_load_by_fingerprint( } } sqlite3_finalize(stmt); - return success; + success } + +// TODO should return bool /rtn pub unsafe fn dc_apeerstate_save_to_db( mut peerstate: *const dc_apeerstate_t, - mut sql: *mut dc_sqlite3_t, + mut sql: &dc_sqlite3_t, mut create: libc::c_int, ) -> libc::c_int { let mut current_block: u64; let mut success: libc::c_int = 0i32; let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; - if peerstate.is_null() || sql.is_null() || (*peerstate).addr.is_null() { + if peerstate.is_null() || (*peerstate).addr.is_null() { return 0i32; } if 0 != create { stmt = dc_sqlite3_prepare( + (*peerstate).context, sql, b"INSERT INTO acpeerstates (addr) VALUES(?);\x00" as *const u8 as *const libc::c_char, ); @@ -406,7 +441,8 @@ pub unsafe fn dc_apeerstate_save_to_db( } if 0 != (*peerstate).to_save & 0x2i32 || 0 != create { stmt = - dc_sqlite3_prepare(sql, + dc_sqlite3_prepare( + (*peerstate).context,sql, b"UPDATE acpeerstates SET last_seen=?, last_seen_autocrypt=?, prefer_encrypted=?, public_key=?, gossip_timestamp=?, gossip_key=?, public_key_fingerprint=?, gossip_key_fingerprint=?, verified_key=?, verified_key_fingerprint=? WHERE addr=?;\x00" as *const u8 as *const libc::c_char); sqlite3_bind_int64(stmt, 1i32, (*peerstate).last_seen as sqlite3_int64); @@ -481,7 +517,8 @@ pub unsafe fn dc_apeerstate_save_to_db( } } else if 0 != (*peerstate).to_save & 0x1i32 { stmt = - dc_sqlite3_prepare(sql, + dc_sqlite3_prepare( + (*peerstate).context,sql, b"UPDATE acpeerstates SET last_seen=?, last_seen_autocrypt=?, gossip_timestamp=? WHERE addr=?;\x00" as *const u8 as *const libc::c_char); sqlite3_bind_int64(stmt, 1i32, (*peerstate).last_seen as sqlite3_int64); @@ -512,8 +549,11 @@ pub unsafe fn dc_apeerstate_save_to_db( _ => {} } sqlite3_finalize(stmt); - return success; + + success } + +// TODO should return bool /rtn pub unsafe fn dc_apeerstate_has_verified_key( mut peerstate: *const dc_apeerstate_t, mut fingerprints: *const dc_hash_t, @@ -532,5 +572,6 @@ pub unsafe fn dc_apeerstate_has_verified_key( { return 1i32; } - return 0i32; + + 0 } diff --git a/src/dc_array.rs b/src/dc_array.rs index 5550f2a7c..cf03b0b60 100644 --- a/src/dc_array.rs +++ b/src/dc_array.rs @@ -1,5 +1,3 @@ -use libc; - use crate::dc_context::*; use crate::dc_tools::*; use crate::types::*; @@ -10,14 +8,13 @@ use crate::x::*; #[repr(C)] pub struct dc_array_t { pub magic: uint32_t, - pub context: *mut dc_context_t, pub allocated: size_t, pub count: size_t, pub type_0: libc::c_int, pub array: *mut uintptr_t, } -/* * +/** * @class dc_array_t * * An object containing a simple array. @@ -36,6 +33,7 @@ pub unsafe fn dc_array_unref(mut array: *mut dc_array_t) { (*array).magic = 0i32 as uint32_t; free(array as *mut libc::c_void); } + pub unsafe fn dc_array_free_ptr(mut array: *mut dc_array_t) { if array.is_null() || (*array).magic != 0xa11aai32 as libc::c_uint { return; @@ -53,6 +51,7 @@ pub unsafe fn dc_array_free_ptr(mut array: *mut dc_array_t) { i = i.wrapping_add(1) } } + pub unsafe fn dc_array_add_uint(mut array: *mut dc_array_t, mut item: uintptr_t) { if array.is_null() || (*array).magic != 0xa11aai32 as libc::c_uint { return; @@ -71,24 +70,29 @@ pub unsafe fn dc_array_add_uint(mut array: *mut dc_array_t, mut item: uintptr_t) *(*array).array.offset((*array).count as isize) = item; (*array).count = (*array).count.wrapping_add(1); } + pub unsafe fn dc_array_add_id(mut array: *mut dc_array_t, mut item: uint32_t) { dc_array_add_uint(array, item as uintptr_t); } + pub unsafe fn dc_array_add_ptr(mut array: *mut dc_array_t, mut item: *mut libc::c_void) { dc_array_add_uint(array, item as uintptr_t); } + pub unsafe fn dc_array_get_cnt(mut array: *const dc_array_t) -> size_t { if array.is_null() || (*array).magic != 0xa11aai32 as libc::c_uint { return 0i32 as size_t; } - return (*array).count; + (*array).count } + pub unsafe fn dc_array_get_uint(mut array: *const dc_array_t, mut index: size_t) -> uintptr_t { if array.is_null() || (*array).magic != 0xa11aai32 as libc::c_uint || index >= (*array).count { return 0i32 as uintptr_t; } - return *(*array).array.offset(index as isize); + *(*array).array.offset(index as isize) } + pub unsafe fn dc_array_get_id(mut array: *const dc_array_t, mut index: size_t) -> uint32_t { if array.is_null() || (*array).magic != 0xa11aai32 as libc::c_uint || index >= (*array).count { return 0i32 as uint32_t; @@ -96,8 +100,9 @@ pub unsafe fn dc_array_get_id(mut array: *const dc_array_t, mut index: size_t) - if (*array).type_0 == 1i32 { return (*(*(*array).array.offset(index as isize) as *mut _dc_location)).location_id; } - return *(*array).array.offset(index as isize) as uint32_t; + *(*array).array.offset(index as isize) as uint32_t } + pub unsafe fn dc_array_get_ptr( mut array: *const dc_array_t, mut index: size_t, @@ -105,8 +110,9 @@ pub unsafe fn dc_array_get_ptr( if array.is_null() || (*array).magic != 0xa11aai32 as libc::c_uint || index >= (*array).count { return 0 as *mut libc::c_void; } - return *(*array).array.offset(index as isize) as *mut libc::c_void; + *(*array).array.offset(index as isize) as *mut libc::c_void } + pub unsafe fn dc_array_get_latitude( mut array: *const dc_array_t, mut index: size_t, @@ -119,8 +125,9 @@ pub unsafe fn dc_array_get_latitude( { return 0i32 as libc::c_double; } - return (*(*(*array).array.offset(index as isize) as *mut _dc_location)).latitude; + (*(*(*array).array.offset(index as isize) as *mut _dc_location)).latitude } + pub unsafe fn dc_array_get_longitude( mut array: *const dc_array_t, mut index: size_t, @@ -133,8 +140,9 @@ pub unsafe fn dc_array_get_longitude( { return 0i32 as libc::c_double; } - return (*(*(*array).array.offset(index as isize) as *mut _dc_location)).longitude; + (*(*(*array).array.offset(index as isize) as *mut _dc_location)).longitude } + pub unsafe fn dc_array_get_accuracy( mut array: *const dc_array_t, mut index: size_t, @@ -147,8 +155,9 @@ pub unsafe fn dc_array_get_accuracy( { return 0i32 as libc::c_double; } - return (*(*(*array).array.offset(index as isize) as *mut _dc_location)).accuracy; + (*(*(*array).array.offset(index as isize) as *mut _dc_location)).accuracy } + pub unsafe fn dc_array_get_timestamp(mut array: *const dc_array_t, mut index: size_t) -> time_t { if array.is_null() || (*array).magic != 0xa11aai32 as libc::c_uint @@ -158,8 +167,9 @@ pub unsafe fn dc_array_get_timestamp(mut array: *const dc_array_t, mut index: si { return 0i32 as time_t; } - return (*(*(*array).array.offset(index as isize) as *mut _dc_location)).timestamp; + (*(*(*array).array.offset(index as isize) as *mut _dc_location)).timestamp } + pub unsafe fn dc_array_get_chat_id(mut array: *const dc_array_t, mut index: size_t) -> uint32_t { if array.is_null() || (*array).magic != 0xa11aai32 as libc::c_uint @@ -169,8 +179,9 @@ pub unsafe fn dc_array_get_chat_id(mut array: *const dc_array_t, mut index: size { return 0i32 as uint32_t; } - return (*(*(*array).array.offset(index as isize) as *mut _dc_location)).chat_id; + (*(*(*array).array.offset(index as isize) as *mut _dc_location)).chat_id } + pub unsafe fn dc_array_get_contact_id(mut array: *const dc_array_t, mut index: size_t) -> uint32_t { if array.is_null() || (*array).magic != 0xa11aai32 as libc::c_uint @@ -180,8 +191,9 @@ pub unsafe fn dc_array_get_contact_id(mut array: *const dc_array_t, mut index: s { return 0i32 as uint32_t; } - return (*(*(*array).array.offset(index as isize) as *mut _dc_location)).contact_id; + (*(*(*array).array.offset(index as isize) as *mut _dc_location)).contact_id } + pub unsafe fn dc_array_get_msg_id(mut array: *const dc_array_t, mut index: size_t) -> uint32_t { if array.is_null() || (*array).magic != 0xa11aai32 as libc::c_uint @@ -191,8 +203,9 @@ pub unsafe fn dc_array_get_msg_id(mut array: *const dc_array_t, mut index: size_ { return 0i32 as uint32_t; } - return (*(*(*array).array.offset(index as isize) as *mut _dc_location)).msg_id; + (*(*(*array).array.offset(index as isize) as *mut _dc_location)).msg_id } + pub unsafe fn dc_array_get_marker( mut array: *const dc_array_t, mut index: size_t, @@ -205,9 +218,7 @@ pub unsafe fn dc_array_get_marker( { return 0 as *mut libc::c_char; } - return dc_strdup_keep_null( - (*(*(*array).array.offset(index as isize) as *mut _dc_location)).marker, - ); + dc_strdup_keep_null((*(*(*array).array.offset(index as isize) as *mut _dc_location)).marker) } /** @@ -233,6 +244,7 @@ pub unsafe fn dc_array_is_independent(array: *const dc_array_t, index: size_t) - (*(*(*array).array.offset(index as isize) as *mut _dc_location)).independent as libc::c_int } +// TODO should return bool /rtn pub unsafe fn dc_array_search_id( mut array: *const dc_array_t, mut needle: uint32_t, @@ -244,7 +256,6 @@ pub unsafe fn dc_array_search_id( let mut data: *mut uintptr_t = (*array).array; let mut i: size_t = 0; let mut cnt: size_t = (*array).count; - i = 0i32 as size_t; while i < cnt { if *data.offset(i as isize) == needle as size_t { if !ret_index.is_null() { @@ -254,32 +265,30 @@ pub unsafe fn dc_array_search_id( } i = i.wrapping_add(1) } - return 0i32; + 0 } + pub unsafe fn dc_array_get_raw(mut array: *const dc_array_t) -> *const uintptr_t { if array.is_null() || (*array).magic != 0xa11aai32 as libc::c_uint { return 0 as *const uintptr_t; } - return (*array).array; + (*array).array } -pub unsafe fn dc_array_new( - mut context: *mut dc_context_t, - mut initsize: size_t, -) -> *mut dc_array_t { - return dc_array_new_typed(context, 0i32, initsize); + +pub unsafe fn dc_array_new(initsize: size_t) -> *mut dc_array_t { + dc_array_new_typed(0, initsize) } + pub unsafe extern "C" fn dc_array_new_typed( - mut context: *mut dc_context_t, mut type_0: libc::c_int, mut initsize: size_t, ) -> *mut dc_array_t { - let mut array: *mut dc_array_t = 0 as *mut dc_array_t; + let mut array: *mut dc_array_t; array = calloc(1, ::std::mem::size_of::()) as *mut dc_array_t; if array.is_null() { exit(47i32); } (*array).magic = 0xa11aai32 as uint32_t; - (*array).context = context; (*array).count = 0i32 as size_t; (*array).allocated = if initsize < 1 { 1 } else { initsize }; (*array).type_0 = type_0; @@ -291,20 +300,22 @@ pub unsafe extern "C" fn dc_array_new_typed( if (*array).array.is_null() { exit(48i32); } - return array; + array } + pub unsafe fn dc_array_empty(mut array: *mut dc_array_t) { if array.is_null() || (*array).magic != 0xa11aai32 as libc::c_uint { return; } (*array).count = 0i32 as size_t; } + pub unsafe fn dc_array_duplicate(mut array: *const dc_array_t) -> *mut dc_array_t { - let mut ret: *mut dc_array_t = 0 as *mut dc_array_t; + let mut ret: *mut dc_array_t; if array.is_null() || (*array).magic != 0xa11aai32 as libc::c_uint { return 0 as *mut dc_array_t; } - ret = dc_array_new((*array).context, (*array).allocated); + ret = dc_array_new((*array).allocated); (*ret).count = (*array).count; memcpy( (*ret).array as *mut libc::c_void, @@ -313,8 +324,9 @@ pub unsafe fn dc_array_duplicate(mut array: *const dc_array_t) -> *mut dc_array_ .count .wrapping_mul(::std::mem::size_of::()), ); - return ret; + ret } + pub unsafe fn dc_array_sort_ids(mut array: *mut dc_array_t) { if array.is_null() || (*array).magic != 0xa11aai32 as libc::c_uint || (*array).count <= 1 { return; @@ -326,6 +338,7 @@ pub unsafe fn dc_array_sort_ids(mut array: *mut dc_array_t) { Some(cmp_intptr_t), ); } + unsafe extern "C" fn cmp_intptr_t( mut p1: *const libc::c_void, mut p2: *const libc::c_void, @@ -340,6 +353,7 @@ unsafe extern "C" fn cmp_intptr_t( 0i32 }; } + pub unsafe fn dc_array_sort_strings(mut array: *mut dc_array_t) { if array.is_null() || (*array).magic != 0xa11aai32 as libc::c_uint || (*array).count <= 1 { return; @@ -351,19 +365,22 @@ pub unsafe fn dc_array_sort_strings(mut array: *mut dc_array_t) { Some(cmp_strings_t), ); } + unsafe extern "C" fn cmp_strings_t( mut p1: *const libc::c_void, mut p2: *const libc::c_void, ) -> libc::c_int { let mut v1: *const libc::c_char = *(p1 as *mut *const libc::c_char); let mut v2: *const libc::c_char = *(p2 as *mut *const libc::c_char); - return strcmp(v1, v2); + + strcmp(v1, v2) } + pub unsafe fn dc_array_get_string( mut array: *const dc_array_t, mut sep: *const libc::c_char, ) -> *mut libc::c_char { - let mut ret: *mut libc::c_char = 0 as *mut libc::c_char; + let mut ret: *mut libc::c_char; if array.is_null() || (*array).magic != 0xa11aai32 as libc::c_uint || sep.is_null() { return dc_strdup(b"\x00" as *const u8 as *const libc::c_char); } @@ -378,7 +395,6 @@ pub unsafe fn dc_array_get_string( exit(35i32); } *ret.offset(0isize) = 0i32 as libc::c_char; - i = 0; while i < (*array).count { if 0 != i { strcat(ret, sep); @@ -390,19 +406,21 @@ pub unsafe fn dc_array_get_string( ); i += 1 } - return ret; + + ret } + pub unsafe fn dc_arr_to_string( mut arr: *const uint32_t, mut cnt: libc::c_int, ) -> *mut libc::c_char { /* return comma-separated value-string from integer array */ - let mut ret: *mut libc::c_char = 0 as *mut libc::c_char; + let mut ret: *mut libc::c_char; let mut sep: *const libc::c_char = b",\x00" as *const u8 as *const libc::c_char; if arr.is_null() || cnt <= 0i32 { return dc_strdup(b"\x00" as *const u8 as *const libc::c_char); } - let mut i: libc::c_int = 0; + let mut i: libc::c_int; ret = malloc( (cnt as usize) .wrapping_mul((11usize).wrapping_add(strlen(sep))) @@ -424,5 +442,6 @@ pub unsafe fn dc_arr_to_string( ); i += 1 } - return ret; + + ret } diff --git a/src/dc_chat.rs b/src/dc_chat.rs index ad40eacc7..24bba36c9 100644 --- a/src/dc_chat.rs +++ b/src/dc_chat.rs @@ -1,5 +1,3 @@ -use libc; - use crate::constants::*; use crate::dc_array::*; use crate::dc_chatlist::*; @@ -19,13 +17,13 @@ use crate::x::*; /* * the structure behind dc_chat_t */ #[derive(Copy, Clone)] #[repr(C)] -pub struct dc_chat_t { +pub struct dc_chat_t<'a> { pub magic: uint32_t, pub id: uint32_t, pub type_0: libc::c_int, pub name: *mut libc::c_char, pub archived: libc::c_int, - pub context: *mut dc_context_t, + pub context: &'a dc_context_t, pub grpid: *mut libc::c_char, pub blocked: libc::c_int, pub param: *mut dc_param_t, @@ -35,39 +33,39 @@ pub struct dc_chat_t { // handle chats pub unsafe fn dc_create_chat_by_msg_id( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut msg_id: uint32_t, ) -> uint32_t { let mut chat_id: uint32_t = 0i32 as uint32_t; let mut send_event: libc::c_int = 0i32; let mut msg: *mut dc_msg_t = dc_msg_new_untyped(context); let mut chat: *mut dc_chat_t = dc_chat_new(context); - if !(context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint) { - if !(0 == dc_msg_load_from_db(msg, context, msg_id) - || 0 == dc_chat_load_from_db(chat, (*msg).chat_id) - || (*chat).id <= 9i32 as libc::c_uint) - { - chat_id = (*chat).id; - if 0 != (*chat).blocked { - dc_unblock_chat(context, (*chat).id); - send_event = 1i32 - } - dc_scaleup_contact_origin(context, (*msg).from_id, 0x800i32); + if !(0 == dc_msg_load_from_db(msg, context, msg_id) + || 0 == dc_chat_load_from_db(chat, (*msg).chat_id) + || (*chat).id <= 9i32 as libc::c_uint) + { + chat_id = (*chat).id; + if 0 != (*chat).blocked { + dc_unblock_chat(context, (*chat).id); + send_event = 1i32 } + dc_scaleup_contact_origin(context, (*msg).from_id, 0x800i32); } + dc_msg_unref(msg); dc_chat_unref(chat); if 0 != send_event { - ((*context).cb)( + (context.cb)( context, Event::MSGS_CHANGED, 0i32 as uintptr_t, 0i32 as uintptr_t, ); } - return chat_id; + chat_id } -/* * + +/** * @class dc_chat_t * * An object representing a single chat in memory. @@ -82,20 +80,16 @@ pub unsafe fn dc_create_chat_by_msg_id( // only an indicator in a chatlist // only an indicator in a chatlist // larger chat IDs are "real" chats, their messages are "real" messages. -pub unsafe fn dc_chat_new(mut context: *mut dc_context_t) -> *mut dc_chat_t { - let mut chat: *mut dc_chat_t = 0 as *mut dc_chat_t; - if context.is_null() || { - chat = calloc(1, ::std::mem::size_of::()) as *mut dc_chat_t; - chat.is_null() - } { - exit(14i32); - } +pub unsafe fn dc_chat_new<'a>(context: &'a dc_context_t) -> *mut dc_chat_t<'a> { + let mut chat: *mut dc_chat_t; + chat = calloc(1, ::std::mem::size_of::()) as *mut dc_chat_t; (*chat).magic = 0xc4a7c4a7u32; (*chat).context = context; (*chat).type_0 = 0i32; (*chat).param = dc_param_new(); - return chat; + chat } + pub unsafe fn dc_chat_unref(mut chat: *mut dc_chat_t) { if chat.is_null() || (*chat).magic != 0xc4a7c4a7u32 { return; @@ -105,6 +99,7 @@ pub unsafe fn dc_chat_unref(mut chat: *mut dc_chat_t) { (*chat).magic = 0i32 as uint32_t; free(chat as *mut libc::c_void); } + pub unsafe fn dc_chat_empty(mut chat: *mut dc_chat_t) { if chat.is_null() || (*chat).magic != 0xc4a7c4a7u32 { return; @@ -119,20 +114,20 @@ pub unsafe fn dc_chat_empty(mut chat: *mut dc_chat_t) { (*chat).gossiped_timestamp = 0i32 as time_t; dc_param_set_packed((*chat).param, 0 as *const libc::c_char); } -pub unsafe fn dc_unblock_chat(mut context: *mut dc_context_t, mut chat_id: uint32_t) { + +pub unsafe fn dc_unblock_chat(mut context: &dc_context_t, mut chat_id: uint32_t) { dc_block_chat(context, chat_id, 0i32); } + pub unsafe fn dc_block_chat( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut chat_id: uint32_t, mut new_blocking: libc::c_int, ) { - let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; - if context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint { - return; - } + let mut stmt: *mut sqlite3_stmt; stmt = dc_sqlite3_prepare( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"UPDATE chats SET blocked=? WHERE id=?;\x00" as *const u8 as *const libc::c_char, ); sqlite3_bind_int(stmt, 1i32, new_blocking); @@ -140,16 +135,22 @@ pub unsafe fn dc_block_chat( sqlite3_step(stmt); sqlite3_finalize(stmt); } + +// TODO should return bool /rtn pub unsafe fn dc_chat_load_from_db(mut chat: *mut dc_chat_t, mut chat_id: uint32_t) -> libc::c_int { let mut success: libc::c_int = 0i32; let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; if !(chat.is_null() || (*chat).magic != 0xc4a7c4a7u32) { dc_chat_empty(chat); - stmt = - dc_sqlite3_prepare((*(*chat).context).sql, - b"SELECT c.id,c.type,c.name, c.grpid,c.param,c.archived, c.blocked, c.gossiped_timestamp, c.locations_send_until FROM chats c WHERE c.id=?;\x00" - as *const u8 as *const libc::c_char); - sqlite3_bind_int(stmt, 1i32, chat_id as libc::c_int); + stmt = dc_sqlite3_prepare( + (*chat).context, + &(*chat).context.sql.read().unwrap(), + b"SELECT c.id,c.type,c.name, c.grpid,c.param,c.archived, \ + c.blocked, c.gossiped_timestamp, c.locations_send_until \ + FROM chats c WHERE c.id=?;\x00" as *const u8 as *const libc::c_char, + ); + sqlite3_bind_int(stmt, 1, chat_id as libc::c_int); + if !(sqlite3_step(stmt) != 100i32) { if !(0 == set_from_stmt(chat, stmt)) { success = 1i32 @@ -157,8 +158,9 @@ pub unsafe fn dc_chat_load_from_db(mut chat: *mut dc_chat_t, mut chat_id: uint32 } } sqlite3_finalize(stmt); - return success; + success } + unsafe fn set_from_stmt(mut chat: *mut dc_chat_t, mut row: *mut sqlite3_stmt) -> libc::c_int { let mut row_offset: libc::c_int = 0i32; if chat.is_null() || (*chat).magic != 0xc4a7c4a7u32 || row.is_null() { @@ -216,18 +218,16 @@ unsafe fn set_from_stmt(mut chat: *mut dc_chat_t, mut row: *mut sqlite3_stmt) -> free((*chat).name as *mut libc::c_void); (*chat).name = dc_stock_str((*chat).context, 2i32) } - return row_offset; + row_offset } + pub unsafe fn dc_create_chat_by_contact_id( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut contact_id: uint32_t, ) -> uint32_t { let mut chat_id: uint32_t = 0i32 as uint32_t; let mut chat_blocked: libc::c_int = 0i32; let mut send_event: libc::c_int = 0i32; - if context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint { - return 0i32 as uint32_t; - } dc_lookup_real_nchat_by_contact_id(context, contact_id, &mut chat_id, &mut chat_blocked); if 0 != chat_id { if 0 != chat_blocked { @@ -258,17 +258,18 @@ pub unsafe fn dc_create_chat_by_contact_id( dc_scaleup_contact_origin(context, contact_id, 0x800i32); } if 0 != send_event { - ((*context).cb)( + (context.cb)( context, Event::MSGS_CHANGED, 0i32 as uintptr_t, 0i32 as uintptr_t, ); } - return chat_id; + chat_id } + pub unsafe fn dc_create_or_lookup_nchat_by_contact_id( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut contact_id: uint32_t, mut create_blocked: libc::c_int, mut ret_chat_id: *mut uint32_t, @@ -276,8 +277,8 @@ pub unsafe fn dc_create_or_lookup_nchat_by_contact_id( ) { let mut chat_id: uint32_t = 0i32 as uint32_t; let mut chat_blocked: libc::c_int = 0i32; - let mut contact: *mut dc_contact_t = 0 as *mut dc_contact_t; - let mut chat_name: *mut libc::c_char = 0 as *mut libc::c_char; + let mut contact: *mut dc_contact_t; + let mut chat_name: *mut libc::c_char; let mut q: *mut libc::c_char = 0 as *mut libc::c_char; let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; if !ret_chat_id.is_null() { @@ -286,10 +287,7 @@ pub unsafe fn dc_create_or_lookup_nchat_by_contact_id( if !ret_chat_blocked.is_null() { *ret_chat_blocked = 0i32 } - if context.is_null() - || (*context).magic != 0x11a11807i32 as libc::c_uint - || (*(*context).sql).cobj.is_null() - { + if context.sql.read().unwrap().cobj.is_null() { return; } if contact_id == 0i32 as libc::c_uint { @@ -306,7 +304,7 @@ pub unsafe fn dc_create_or_lookup_nchat_by_contact_id( return; } contact = dc_contact_new(context); - if !(0 == dc_contact_load_from_db(contact, (*context).sql, contact_id)) { + if !(0 == dc_contact_load_from_db(contact, &context.sql.clone().read().unwrap(), contact_id)) { chat_name = if !(*contact).name.is_null() && 0 != *(*contact).name.offset(0isize) as libc::c_int { (*contact).name @@ -338,26 +336,25 @@ pub unsafe fn dc_create_or_lookup_nchat_by_contact_id( ); } else { }; - stmt = dc_sqlite3_prepare((*context).sql, q); + stmt = dc_sqlite3_prepare(context, &context.sql.clone().read().unwrap(), q); if !stmt.is_null() { if !(sqlite3_step(stmt) != 101i32) { chat_id = dc_sqlite3_get_rowid( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"chats\x00" as *const u8 as *const libc::c_char, b"grpid\x00" as *const u8 as *const libc::c_char, (*contact).addr, ); sqlite3_free(q as *mut libc::c_void); - q = 0 as *mut libc::c_char; sqlite3_finalize(stmt); - stmt = 0 as *mut sqlite3_stmt; q = sqlite3_mprintf( b"INSERT INTO chats_contacts (chat_id, contact_id) VALUES(%i, %i)\x00" as *const u8 as *const libc::c_char, chat_id, contact_id, ); - stmt = dc_sqlite3_prepare((*context).sql, q); + stmt = dc_sqlite3_prepare(context, &context.sql.clone().read().unwrap(), q); if !(sqlite3_step(stmt) != 101i32) { sqlite3_free(q as *mut libc::c_void); q = 0 as *mut libc::c_char; @@ -377,29 +374,29 @@ pub unsafe fn dc_create_or_lookup_nchat_by_contact_id( *ret_chat_blocked = create_blocked }; } + pub unsafe fn dc_lookup_real_nchat_by_contact_id( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut contact_id: uint32_t, mut ret_chat_id: *mut uint32_t, mut ret_chat_blocked: *mut libc::c_int, ) { /* checks for "real" chats or self-chat */ - let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; + let mut stmt: *mut sqlite3_stmt; if !ret_chat_id.is_null() { *ret_chat_id = 0i32 as uint32_t } if !ret_chat_blocked.is_null() { *ret_chat_blocked = 0i32 } - if context.is_null() - || (*context).magic != 0x11a11807i32 as libc::c_uint - || (*(*context).sql).cobj.is_null() - { + if context.sql.clone().read().unwrap().cobj.is_null() { return; } stmt = - dc_sqlite3_prepare((*context).sql, - b"SELECT c.id, c.blocked FROM chats c INNER JOIN chats_contacts j ON c.id=j.chat_id WHERE c.type=100 AND c.id>9 AND j.contact_id=?;\x00" + dc_sqlite3_prepare( + context, + &context.sql.clone().read().unwrap(), + b"SELECT c.id, c.blocked FROM chats c INNER JOIN chats_contacts j ON c.id=j.chat_id WHERE c.type=100 AND c.id>9 AND j.contact_id=?;\x00" as *const u8 as *const libc::c_char); sqlite3_bind_int(stmt, 1i32, contact_id as libc::c_int); if sqlite3_step(stmt) == 100i32 { @@ -412,15 +409,13 @@ pub unsafe fn dc_lookup_real_nchat_by_contact_id( } sqlite3_finalize(stmt); } + pub unsafe fn dc_get_chat_id_by_contact_id( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut contact_id: uint32_t, ) -> uint32_t { let mut chat_id: uint32_t = 0i32 as uint32_t; let mut chat_id_blocked: libc::c_int = 0i32; - if context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint { - return 0i32 as uint32_t; - } dc_lookup_real_nchat_by_contact_id(context, contact_id, &mut chat_id, &mut chat_id_blocked); return if 0 != chat_id_blocked { 0i32 as libc::c_uint @@ -428,21 +423,18 @@ pub unsafe fn dc_get_chat_id_by_contact_id( chat_id }; } -pub unsafe fn dc_prepare_msg( - mut context: *mut dc_context_t, + +pub unsafe fn dc_prepare_msg<'a>( + mut context: &'a dc_context_t, mut chat_id: uint32_t, - mut msg: *mut dc_msg_t, + mut msg: *mut dc_msg_t<'a>, ) -> uint32_t { - if context.is_null() - || (*context).magic != 0x11a11807i32 as libc::c_uint - || msg.is_null() - || chat_id <= 9i32 as libc::c_uint - { + if msg.is_null() || chat_id <= 9i32 as libc::c_uint { return 0i32 as uint32_t; } (*msg).state = 18i32; let mut msg_id: uint32_t = prepare_msg_common(context, chat_id, msg); - ((*context).cb)( + (context.cb)( context, Event::MSGS_CHANGED, (*msg).chat_id as uintptr_t, @@ -450,10 +442,11 @@ pub unsafe fn dc_prepare_msg( ); return msg_id; } -unsafe fn prepare_msg_common( - mut context: *mut dc_context_t, + +unsafe fn prepare_msg_common<'a>( + mut context: &'a dc_context_t, mut chat_id: uint32_t, - mut msg: *mut dc_msg_t, + mut msg: *mut dc_msg_t<'a>, ) -> uint32_t { let mut current_block: u64; let mut pathNfilename: *mut libc::c_char = 0 as *mut libc::c_char; @@ -531,7 +524,6 @@ unsafe fn prepare_msg_common( match current_block { 17281240262373992796 => { dc_unarchive_chat(context, chat_id); - (*(*context).smtp).log_connect_errors = 1i32; chat = dc_chat_new(context); if 0 != dc_chat_load_from_db(chat, chat_id) { if (*msg).state != 18i32 { @@ -547,16 +539,18 @@ unsafe fn prepare_msg_common( /* potential error already logged */ dc_chat_unref(chat); free(pathNfilename as *mut libc::c_void); - return (*msg).id; + + (*msg).id } + unsafe fn prepare_msg_raw( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut chat: *mut dc_chat_t, mut msg: *const dc_msg_t, mut timestamp: time_t, ) -> uint32_t { - let mut do_guarantee_e2ee: libc::c_int = 0; - let mut e2ee_enabled: libc::c_int = 0; + let mut do_guarantee_e2ee: libc::c_int; + let mut e2ee_enabled: libc::c_int; let mut current_block: u64; let mut parent_rfc724_mid: *mut libc::c_char = 0 as *mut libc::c_char; let mut parent_references: *mut libc::c_char = 0 as *mut libc::c_char; @@ -587,7 +581,8 @@ unsafe fn prepare_msg_raw( ); } else { let mut from: *mut libc::c_char = dc_sqlite3_get_config( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"configured_addr\x00" as *const u8 as *const libc::c_char, 0 as *const libc::c_char, ); @@ -609,7 +604,8 @@ unsafe fn prepare_msg_raw( free(from as *mut libc::c_void); if (*chat).type_0 == 100i32 { stmt = dc_sqlite3_prepare( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"SELECT contact_id FROM chats_contacts WHERE chat_id=?;\x00" as *const u8 as *const libc::c_char, ); @@ -647,7 +643,8 @@ unsafe fn prepare_msg_raw( we do not send the message out at all */ do_guarantee_e2ee = 0i32; e2ee_enabled = dc_sqlite3_get_config_int( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"e2ee_enabled\x00" as *const u8 as *const libc::c_char, 1i32, ); @@ -656,7 +653,7 @@ unsafe fn prepare_msg_raw( let mut can_encrypt: libc::c_int = 1i32; let mut all_mutual: libc::c_int = 1i32; stmt = - dc_sqlite3_prepare((*context).sql, + dc_sqlite3_prepare(context, &context.sql.clone().read().unwrap(), b"SELECT ps.prefer_encrypted, c.addr FROM chats_contacts cc LEFT JOIN contacts c ON cc.contact_id=c.id LEFT JOIN acpeerstates ps ON c.addr=ps.addr WHERE cc.chat_id=? AND cc.contact_id>9;\x00" as *const u8 as *const libc::c_char); @@ -693,11 +690,16 @@ unsafe fn prepare_msg_raw( } } sqlite3_finalize(stmt); - stmt = 0 as *mut sqlite3_stmt; if 0 != can_encrypt { if 0 != all_mutual { do_guarantee_e2ee = 1i32 - } else if 0 != last_msg_in_chat_encrypted((*context).sql, (*chat).id) { + } else if 0 + != last_msg_in_chat_encrypted( + context, + &context.sql.clone().read().unwrap(), + (*chat).id, + ) + { do_guarantee_e2ee = 1i32 } } @@ -720,7 +722,7 @@ unsafe fn prepare_msg_raw( new_in_reply_to = dc_strdup(parent_rfc724_mid) } if !parent_references.is_null() { - let mut space: *mut libc::c_char = 0 as *mut libc::c_char; + let mut space: *mut libc::c_char; space = strchr(parent_references, ' ' as i32); if !space.is_null() { *space = 0i32 as libc::c_char @@ -761,7 +763,8 @@ unsafe fn prepare_msg_raw( if 0 != dc_param_exists((*msg).param, DC_PARAM_SET_LATITUDE as libc::c_int) { stmt = dc_sqlite3_prepare( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"INSERT INTO locations \ (timestamp,from_id,chat_id, latitude,longitude,independent)\ VALUES (?,?,?, ?,?,1);\x00" as *const u8 @@ -790,10 +793,10 @@ unsafe fn prepare_msg_raw( ); sqlite3_step(stmt); sqlite3_finalize(stmt); - stmt = 0 as *mut sqlite3_stmt; location_id = dc_sqlite3_get_rowid2( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"locations\x00" as *const u8 as *const libc::c_char, b"timestamp\x00" as *const u8 as *const libc::c_char, timestamp as u64, @@ -805,7 +808,8 @@ unsafe fn prepare_msg_raw( // add message to the database stmt = - dc_sqlite3_prepare((*context).sql, + dc_sqlite3_prepare( + context,&context.sql.clone().read().unwrap(), b"INSERT INTO msgs (rfc724_mid, chat_id, from_id, to_id, timestamp, type, state, txt, param, hidden, mime_in_reply_to, mime_references, location_id) VALUES (?,?,?,?,?, ?,?,?,?,?, ?,?,?);\x00" as *const u8 as *const libc::c_char); @@ -842,7 +846,8 @@ unsafe fn prepare_msg_raw( ); } else { msg_id = dc_sqlite3_get_rowid( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"msgs\x00" as *const u8 as *const libc::c_char, b"rfc724_mid\x00" as *const u8 as *const libc::c_char, new_rfc724_mid, @@ -859,8 +864,11 @@ unsafe fn prepare_msg_raw( free(new_in_reply_to as *mut libc::c_void); free(new_references as *mut libc::c_void); sqlite3_finalize(stmt); - return msg_id; + + msg_id } + +// TODO should return bool /rtn unsafe fn get_parent_mime_headers( mut chat: *const dc_chat_t, mut parent_rfc724_mid: *mut *mut libc::c_char, @@ -875,7 +883,8 @@ unsafe fn get_parent_mime_headers( || parent_references.is_null()) { stmt = - dc_sqlite3_prepare((*(*chat).context).sql, + dc_sqlite3_prepare( + (*chat).context,&mut (*chat).context.sql.clone().read().unwrap(), b"SELECT rfc724_mid, mime_in_reply_to, mime_references FROM msgs WHERE timestamp=(SELECT max(timestamp) FROM msgs WHERE chat_id=? AND from_id!=?);\x00" as *const u8 as *const libc::c_char); sqlite3_bind_int(stmt, 1i32, (*chat).id as libc::c_int); @@ -890,7 +899,8 @@ unsafe fn get_parent_mime_headers( stmt = 0 as *mut sqlite3_stmt; if 0 == success { stmt = - dc_sqlite3_prepare((*(*chat).context).sql, + dc_sqlite3_prepare( + (*chat).context,&mut (*chat).context.sql.clone().read().unwrap(), b"SELECT rfc724_mid, mime_in_reply_to, mime_references FROM msgs WHERE timestamp=(SELECT min(timestamp) FROM msgs WHERE chat_id=? AND from_id==?);\x00" as *const u8 as *const libc::c_char); sqlite3_bind_int(stmt, 1i32, (*chat).id as libc::c_int); @@ -907,24 +917,29 @@ unsafe fn get_parent_mime_headers( } } sqlite3_finalize(stmt); - return success; + success } + pub unsafe fn dc_chat_is_self_talk(mut chat: *const dc_chat_t) -> libc::c_int { if chat.is_null() || (*chat).magic != 0xc4a7c4a7u32 { return 0i32; } - return dc_param_exists((*chat).param, 'K' as i32); + dc_param_exists((*chat).param, 'K' as i32) } -/* ****************************************************************************** + +/******************************************************************************* * Sending messages ******************************************************************************/ +// TODO should return bool /rtn unsafe fn last_msg_in_chat_encrypted( - mut sql: *mut dc_sqlite3_t, - mut chat_id: uint32_t, + context: &dc_context_t, + sql: &dc_sqlite3_t, + chat_id: uint32_t, ) -> libc::c_int { let mut last_is_encrypted: libc::c_int = 0i32; let mut stmt: *mut sqlite3_stmt = - dc_sqlite3_prepare(sql, + dc_sqlite3_prepare( + context,sql, b"SELECT param FROM msgs WHERE timestamp=(SELECT MAX(timestamp) FROM msgs WHERE chat_id=?) ORDER BY id DESC;\x00" as *const u8 as *const libc::c_char); sqlite3_bind_int(stmt, 1i32, chat_id as libc::c_int); @@ -940,12 +955,15 @@ unsafe fn last_msg_in_chat_encrypted( dc_param_unref(msg_param); } sqlite3_finalize(stmt); - return last_is_encrypted; + last_is_encrypted } + +// TODO should return bool /rtn pub unsafe fn dc_chat_update_param(mut chat: *mut dc_chat_t) -> libc::c_int { - let mut success: libc::c_int = 0i32; + let mut success: libc::c_int; let mut stmt: *mut sqlite3_stmt = dc_sqlite3_prepare( - (*(*chat).context).sql, + (*chat).context, + &mut (*chat).context.sql.clone().read().unwrap(), b"UPDATE chats SET param=? WHERE id=?\x00" as *const u8 as *const libc::c_char, ); sqlite3_bind_text(stmt, 1i32, (*(*chat).param).packed, -1i32, None); @@ -956,49 +974,54 @@ pub unsafe fn dc_chat_update_param(mut chat: *mut dc_chat_t) -> libc::c_int { 0i32 }; sqlite3_finalize(stmt); - return success; + success } + pub unsafe fn dc_is_contact_in_chat( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut chat_id: uint32_t, mut contact_id: uint32_t, ) -> libc::c_int { /* this function works for group and for normal chats, however, it is more useful for group chats. DC_CONTACT_ID_SELF may be used to check, if the user itself is in a group chat (DC_CONTACT_ID_SELF is not added to normal chats) */ - let mut ret: libc::c_int = 0i32; - let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; - if !(context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint) { - stmt = dc_sqlite3_prepare( - (*context).sql, - b"SELECT contact_id FROM chats_contacts WHERE chat_id=? AND contact_id=?;\x00" - as *const u8 as *const libc::c_char, - ); - sqlite3_bind_int(stmt, 1i32, chat_id as libc::c_int); - sqlite3_bind_int(stmt, 2i32, contact_id as libc::c_int); - ret = if sqlite3_step(stmt) == 100i32 { - 1i32 - } else { - 0i32 - } - } + let mut ret: libc::c_int; + let mut stmt: *mut sqlite3_stmt; + + stmt = dc_sqlite3_prepare( + context, + &context.sql.clone().read().unwrap(), + b"SELECT contact_id FROM chats_contacts WHERE chat_id=? AND contact_id=?;\x00" as *const u8 + as *const libc::c_char, + ); + sqlite3_bind_int(stmt, 1i32, chat_id as libc::c_int); + sqlite3_bind_int(stmt, 2i32, contact_id as libc::c_int); + ret = if sqlite3_step(stmt) == 100i32 { + 1i32 + } else { + 0i32 + }; + sqlite3_finalize(stmt); - return ret; + ret } -pub unsafe fn dc_unarchive_chat(mut context: *mut dc_context_t, mut chat_id: uint32_t) { + +pub unsafe fn dc_unarchive_chat(mut context: &dc_context_t, mut chat_id: uint32_t) { let mut stmt: *mut sqlite3_stmt = dc_sqlite3_prepare( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"UPDATE chats SET archived=0 WHERE id=?\x00" as *const u8 as *const libc::c_char, ); sqlite3_bind_int(stmt, 1i32, chat_id as libc::c_int); sqlite3_step(stmt); sqlite3_finalize(stmt); } -pub unsafe fn dc_send_msg( - mut context: *mut dc_context_t, + +pub unsafe fn dc_send_msg<'a>( + mut context: &'a dc_context_t, mut chat_id: uint32_t, - mut msg: *mut dc_msg_t, + mut msg: *mut dc_msg_t<'a>, ) -> uint32_t { - if context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint || msg.is_null() { + if msg.is_null() { return 0i32 as uint32_t; } if (*msg).state != 18i32 { @@ -1014,7 +1037,7 @@ pub unsafe fn dc_send_msg( if 0 == dc_job_send_msg(context, (*msg).id) { return 0i32 as uint32_t; } - ((*context).cb)( + (context.cb)( context, Event::MSGS_CHANGED, (*msg).chat_id as uintptr_t, @@ -1022,7 +1045,7 @@ pub unsafe fn dc_send_msg( ); if 0 != dc_param_exists((*msg).param, DC_PARAM_SET_LATITUDE as libc::c_int) { - ((*context).cb)(context, Event::LOCATION_CHANGED, DC_CONTACT_ID_SELF, 0); + (context.cb)(context, Event::LOCATION_CHANGED, DC_CONTACT_ID_SELF, 0); } if 0 == chat_id { @@ -1048,39 +1071,35 @@ pub unsafe fn dc_send_msg( } free(forwards as *mut libc::c_void); } - return (*msg).id; + + (*msg).id } + pub unsafe fn dc_send_text_msg( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut chat_id: uint32_t, mut text_to_send: *const libc::c_char, ) -> uint32_t { let mut msg: *mut dc_msg_t = dc_msg_new(context, 10i32); let mut ret: uint32_t = 0i32 as uint32_t; - if !(context.is_null() - || (*context).magic != 0x11a11807i32 as libc::c_uint - || chat_id <= 9i32 as libc::c_uint - || text_to_send.is_null()) - { + if !(chat_id <= 9i32 as libc::c_uint || text_to_send.is_null()) { (*msg).text = dc_strdup(text_to_send); ret = dc_send_msg(context, chat_id, msg) } dc_msg_unref(msg); - return ret; + ret } + pub unsafe fn dc_set_draft( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut chat_id: uint32_t, mut msg: *mut dc_msg_t, ) { - if context.is_null() - || (*context).magic != 0x11a11807i32 as libc::c_uint - || chat_id <= 9i32 as libc::c_uint - { + if chat_id <= 9i32 as libc::c_uint { return; } if 0 != set_draft_raw(context, chat_id, msg) { - ((*context).cb)( + (context.cb)( context, Event::MSGS_CHANGED, chat_id as uintptr_t, @@ -1088,8 +1107,10 @@ pub unsafe fn dc_set_draft( ); }; } + +// TODO should return bool /rtn unsafe fn set_draft_raw( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut chat_id: uint32_t, mut msg: *mut dc_msg_t, ) -> libc::c_int { @@ -1097,7 +1118,7 @@ unsafe fn set_draft_raw( // similar to as dc_set_draft() but does not emit an event let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; let mut pathNfilename: *mut libc::c_char = 0 as *mut libc::c_char; - let mut prev_draft_msg_id: uint32_t = 0i32 as uint32_t; + let mut prev_draft_msg_id: uint32_t; let mut sth_changed: libc::c_int = 0i32; prev_draft_msg_id = get_draft_msg_id(context, chat_id); if 0 != prev_draft_msg_id { @@ -1139,7 +1160,8 @@ unsafe fn set_draft_raw( 14513523936503887211 => {} _ => { stmt = - dc_sqlite3_prepare((*context).sql, + dc_sqlite3_prepare( + context,&context.sql.clone().read().unwrap(), b"INSERT INTO msgs (chat_id, from_id, timestamp, type, state, txt, param, hidden) VALUES (?,?,?, ?,?,?,?,?);\x00" as *const u8 as *const libc::c_char); @@ -1169,12 +1191,14 @@ unsafe fn set_draft_raw( } sqlite3_finalize(stmt); free(pathNfilename as *mut libc::c_void); - return sth_changed; + sth_changed } -unsafe fn get_draft_msg_id(mut context: *mut dc_context_t, mut chat_id: uint32_t) -> uint32_t { + +unsafe fn get_draft_msg_id(mut context: &dc_context_t, mut chat_id: uint32_t) -> uint32_t { let mut draft_msg_id: uint32_t = 0i32 as uint32_t; let mut stmt: *mut sqlite3_stmt = dc_sqlite3_prepare( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"SELECT id FROM msgs WHERE chat_id=? AND state=?;\x00" as *const u8 as *const libc::c_char, ); sqlite3_bind_int(stmt, 1i32, chat_id as libc::c_int); @@ -1183,15 +1207,13 @@ unsafe fn get_draft_msg_id(mut context: *mut dc_context_t, mut chat_id: uint32_t draft_msg_id = sqlite3_column_int(stmt, 0i32) as uint32_t } sqlite3_finalize(stmt); - return draft_msg_id; + draft_msg_id } -pub unsafe fn dc_get_draft(mut context: *mut dc_context_t, mut chat_id: uint32_t) -> *mut dc_msg_t { - let mut draft_msg_id: uint32_t = 0i32 as uint32_t; - let mut draft_msg: *mut dc_msg_t = 0 as *mut dc_msg_t; - if context.is_null() - || (*context).magic != 0x11a11807i32 as libc::c_uint - || chat_id <= 9i32 as libc::c_uint - { + +pub unsafe fn dc_get_draft(mut context: &dc_context_t, mut chat_id: uint32_t) -> *mut dc_msg_t { + let mut draft_msg_id: uint32_t; + let mut draft_msg: *mut dc_msg_t; + if chat_id <= 9i32 as libc::c_uint { return 0 as *mut dc_msg_t; } draft_msg_id = get_draft_msg_id(context, chat_id); @@ -1203,43 +1225,49 @@ pub unsafe fn dc_get_draft(mut context: *mut dc_context_t, mut chat_id: uint32_t dc_msg_unref(draft_msg); return 0 as *mut dc_msg_t; } - return draft_msg; + + draft_msg } + pub unsafe fn dc_get_chat_msgs( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut chat_id: uint32_t, mut flags: uint32_t, mut marker1before: uint32_t, ) -> *mut dc_array_t { //clock_t start = clock(); let mut success: libc::c_int = 0i32; - let mut ret: *mut dc_array_t = dc_array_new(context, 512i32 as size_t); + let mut ret: *mut dc_array_t = dc_array_new(512i32 as size_t); let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; - let mut curr_id: uint32_t = 0; - let mut curr_local_timestamp: time_t = 0; - let mut curr_day: libc::c_int = 0; + let mut curr_id: uint32_t; + let mut curr_local_timestamp: time_t; + let mut curr_day: libc::c_int; let mut last_day: libc::c_int = 0i32; let mut cnv_to_local: libc::c_long = dc_gm2local_offset(); - if !(context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint || ret.is_null()) { + if !ret.is_null() { if chat_id == 1i32 as libc::c_uint { let mut show_emails: libc::c_int = dc_sqlite3_get_config_int( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"show_emails\x00" as *const u8 as *const libc::c_char, 0i32, ); stmt = - dc_sqlite3_prepare((*context).sql, + dc_sqlite3_prepare( + context,&context.sql.clone().read().unwrap(), b"SELECT m.id, m.timestamp FROM msgs m LEFT JOIN chats ON m.chat_id=chats.id LEFT JOIN contacts ON m.from_id=contacts.id WHERE m.from_id!=1 AND m.from_id!=2 AND m.hidden=0 AND chats.blocked=2 AND contacts.blocked=0 AND m.msgrmsg>=? ORDER BY m.timestamp,m.id;\x00" as *const u8 as *const libc::c_char); sqlite3_bind_int(stmt, 1i32, if show_emails == 2i32 { 0i32 } else { 1i32 }); } else if chat_id == 5i32 as libc::c_uint { stmt = - dc_sqlite3_prepare((*context).sql, + dc_sqlite3_prepare( + context,&context.sql.clone().read().unwrap(), b"SELECT m.id, m.timestamp FROM msgs m LEFT JOIN contacts ct ON m.from_id=ct.id WHERE m.starred=1 AND m.hidden=0 AND ct.blocked=0 ORDER BY m.timestamp,m.id;\x00" as *const u8 as *const libc::c_char) } else { stmt = - dc_sqlite3_prepare((*context).sql, + dc_sqlite3_prepare( + context,&context.sql.clone().read().unwrap(), b"SELECT m.id, m.timestamp FROM msgs m WHERE m.chat_id=? AND m.hidden=0 ORDER BY m.timestamp,m.id;\x00" as *const u8 as *const libc::c_char); sqlite3_bind_int(stmt, 1i32, chat_id as libc::c_int); @@ -1271,110 +1299,115 @@ pub unsafe fn dc_get_chat_msgs( return 0 as *mut dc_array_t; }; } -pub unsafe fn dc_get_msg_cnt(mut context: *mut dc_context_t, mut chat_id: uint32_t) -> libc::c_int { + +pub unsafe fn dc_get_msg_cnt(mut context: &dc_context_t, mut chat_id: uint32_t) -> libc::c_int { let mut ret: libc::c_int = 0i32; - let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; - if !(context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint) { - stmt = dc_sqlite3_prepare( - (*context).sql, - b"SELECT COUNT(*) FROM msgs WHERE chat_id=?;\x00" as *const u8 as *const libc::c_char, - ); - sqlite3_bind_int(stmt, 1i32, chat_id as libc::c_int); - if !(sqlite3_step(stmt) != 100i32) { - ret = sqlite3_column_int(stmt, 0i32) - } + let mut stmt: *mut sqlite3_stmt; + stmt = dc_sqlite3_prepare( + context, + &context.sql.clone().read().unwrap(), + b"SELECT COUNT(*) FROM msgs WHERE chat_id=?;\x00" as *const u8 as *const libc::c_char, + ); + sqlite3_bind_int(stmt, 1i32, chat_id as libc::c_int); + if !(sqlite3_step(stmt) != 100i32) { + ret = sqlite3_column_int(stmt, 0i32); } + sqlite3_finalize(stmt); - return ret; + ret } + pub unsafe fn dc_get_fresh_msg_cnt( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut chat_id: uint32_t, ) -> libc::c_int { let mut ret: libc::c_int = 0i32; - let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; - if !(context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint) { - stmt = dc_sqlite3_prepare( - (*context).sql, - b"SELECT COUNT(*) FROM msgs WHERE state=10 AND hidden=0 AND chat_id=?;\x00" - as *const u8 as *const libc::c_char, - ); - sqlite3_bind_int(stmt, 1i32, chat_id as libc::c_int); - if !(sqlite3_step(stmt) != 100i32) { - ret = sqlite3_column_int(stmt, 0i32) - } + let mut stmt: *mut sqlite3_stmt; + stmt = dc_sqlite3_prepare( + context, + &context.sql.clone().read().unwrap(), + b"SELECT COUNT(*) FROM msgs WHERE state=10 AND hidden=0 AND chat_id=?;\x00" + as *const u8 as *const libc::c_char, + ); + sqlite3_bind_int(stmt, 1i32, chat_id as libc::c_int); + if !(sqlite3_step(stmt) != 100i32) { + ret = sqlite3_column_int(stmt, 0i32); } sqlite3_finalize(stmt); - return ret; + ret } -pub unsafe fn dc_marknoticed_chat(mut context: *mut dc_context_t, mut chat_id: uint32_t) { - let mut check: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; + +pub unsafe fn dc_marknoticed_chat(mut context: &dc_context_t, mut chat_id: uint32_t) { + let mut check: *mut sqlite3_stmt; let mut update: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; - if !(context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint) { - check = dc_sqlite3_prepare( - (*context).sql, - b"SELECT id FROM msgs WHERE chat_id=? AND state=10;\x00" as *const u8 + + check = dc_sqlite3_prepare( + context, + &context.sql.clone().read().unwrap(), + b"SELECT id FROM msgs WHERE chat_id=? AND state=10;\x00" as *const u8 + as *const libc::c_char, + ); + sqlite3_bind_int(check, 1i32, chat_id as libc::c_int); + if !(sqlite3_step(check) != 100i32) { + update = dc_sqlite3_prepare( + context, + &context.sql.clone().read().unwrap(), + b"UPDATE msgs SET state=13 WHERE chat_id=? AND state=10;\x00" as *const u8 as *const libc::c_char, ); - sqlite3_bind_int(check, 1i32, chat_id as libc::c_int); - if !(sqlite3_step(check) != 100i32) { - update = dc_sqlite3_prepare( - (*context).sql, - b"UPDATE msgs SET state=13 WHERE chat_id=? AND state=10;\x00" as *const u8 - as *const libc::c_char, - ); - sqlite3_bind_int(update, 1i32, chat_id as libc::c_int); - sqlite3_step(update); - ((*context).cb)( - context, - Event::MSGS_CHANGED, - 0i32 as uintptr_t, - 0i32 as uintptr_t, - ); - } - } - sqlite3_finalize(check); - sqlite3_finalize(update); -} -pub unsafe fn dc_marknoticed_all_chats(mut context: *mut dc_context_t) { - let mut check: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; - let mut update: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; - if !(context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint) { - check = dc_sqlite3_prepare( - (*context).sql, - b"SELECT id FROM msgs WHERE state=10;\x00" as *const u8 as *const libc::c_char, + sqlite3_bind_int(update, 1i32, chat_id as libc::c_int); + sqlite3_step(update); + (context.cb)( + context, + Event::MSGS_CHANGED, + 0i32 as uintptr_t, + 0i32 as uintptr_t, ); - if !(sqlite3_step(check) != 100i32) { - update = dc_sqlite3_prepare( - (*context).sql, - b"UPDATE msgs SET state=13 WHERE state=10;\x00" as *const u8 - as *const libc::c_char, - ); - sqlite3_step(update); - ((*context).cb)( - context, - Event::MSGS_CHANGED, - 0i32 as uintptr_t, - 0i32 as uintptr_t, - ); - } } + sqlite3_finalize(check); sqlite3_finalize(update); } + +pub unsafe fn dc_marknoticed_all_chats(mut context: &dc_context_t) { + let mut check: *mut sqlite3_stmt; + let mut update: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; + + check = dc_sqlite3_prepare( + context, + &context.sql.clone().read().unwrap(), + b"SELECT id FROM msgs WHERE state=10;\x00" as *const u8 as *const libc::c_char, + ); + if !(sqlite3_step(check) != 100i32) { + update = dc_sqlite3_prepare( + context, + &context.sql.clone().read().unwrap(), + b"UPDATE msgs SET state=13 WHERE state=10;\x00" as *const u8 as *const libc::c_char, + ); + sqlite3_step(update); + (context.cb)( + context, + Event::MSGS_CHANGED, + 0i32 as uintptr_t, + 0i32 as uintptr_t, + ); + } + + sqlite3_finalize(check); + sqlite3_finalize(update); +} + pub unsafe fn dc_get_chat_media( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut chat_id: uint32_t, mut msg_type: libc::c_int, mut msg_type2: libc::c_int, mut msg_type3: libc::c_int, ) -> *mut dc_array_t { - if context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint { - return 0 as *mut dc_array_t; - } - let mut ret: *mut dc_array_t = dc_array_new(context, 100i32 as size_t); + let mut ret: *mut dc_array_t = dc_array_new(100i32 as size_t); let mut stmt: *mut sqlite3_stmt = - dc_sqlite3_prepare((*context).sql, + dc_sqlite3_prepare( + context,&context.sql.clone().read().unwrap(), b"SELECT id FROM msgs WHERE chat_id=? AND (type=? OR type=? OR type=?) ORDER BY timestamp, id;\x00" as *const u8 as *const libc::c_char); sqlite3_bind_int(stmt, 1i32, chat_id as libc::c_int); @@ -1401,10 +1434,11 @@ pub unsafe fn dc_get_chat_media( dc_array_add_id(ret, sqlite3_column_int(stmt, 0i32) as uint32_t); } sqlite3_finalize(stmt); - return ret; + ret } + pub unsafe fn dc_get_next_media( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut curr_msg_id: uint32_t, mut dir: libc::c_int, mut msg_type: libc::c_int, @@ -1414,62 +1448,60 @@ pub unsafe fn dc_get_next_media( let mut ret_msg_id: uint32_t = 0i32 as uint32_t; let mut msg: *mut dc_msg_t = dc_msg_new_untyped(context); let mut list: *mut dc_array_t = 0 as *mut dc_array_t; - let mut i: libc::c_int = 0i32; - let mut cnt: libc::c_int = 0i32; - if !(context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint) { - if !(0 == dc_msg_load_from_db(msg, context, curr_msg_id)) { - list = dc_get_chat_media( - context, - (*msg).chat_id, - if msg_type > 0i32 { - msg_type - } else { - (*msg).type_0 - }, - msg_type2, - msg_type3, - ); - if !list.is_null() { - cnt = dc_array_get_cnt(list) as libc::c_int; - i = 0i32; - while i < cnt { - if curr_msg_id == dc_array_get_id(list, i as size_t) { - if dir > 0i32 { - if i + 1i32 < cnt { - ret_msg_id = dc_array_get_id(list, (i + 1i32) as size_t) - } - } else if dir < 0i32 { - if i - 1i32 >= 0i32 { - ret_msg_id = dc_array_get_id(list, (i - 1i32) as size_t) - } + let mut i: libc::c_int; + let mut cnt: libc::c_int; + + if !(0 == dc_msg_load_from_db(msg, context, curr_msg_id)) { + list = dc_get_chat_media( + context, + (*msg).chat_id, + if msg_type > 0i32 { + msg_type + } else { + (*msg).type_0 + }, + msg_type2, + msg_type3, + ); + if !list.is_null() { + cnt = dc_array_get_cnt(list) as libc::c_int; + i = 0i32; + while i < cnt { + if curr_msg_id == dc_array_get_id(list, i as size_t) { + if dir > 0i32 { + if i + 1i32 < cnt { + ret_msg_id = dc_array_get_id(list, (i + 1i32) as size_t) + } + } else if dir < 0i32 { + if i - 1i32 >= 0i32 { + ret_msg_id = dc_array_get_id(list, (i - 1i32) as size_t) } - break; - } else { - i += 1 } + break; + } else { + i += 1 } } } } + dc_array_unref(list); dc_msg_unref(msg); - return ret_msg_id; + ret_msg_id } + pub unsafe fn dc_archive_chat( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut chat_id: uint32_t, mut archive: libc::c_int, ) { - if context.is_null() - || (*context).magic != 0x11a11807i32 as libc::c_uint - || chat_id <= 9i32 as libc::c_uint - || archive != 0i32 && archive != 1i32 - { + if chat_id <= 9i32 as libc::c_uint || archive != 0i32 && archive != 1i32 { return; } if 0 != archive { let mut stmt: *mut sqlite3_stmt = dc_sqlite3_prepare( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"UPDATE msgs SET state=13 WHERE chat_id=? AND state=10;\x00" as *const u8 as *const libc::c_char, ); @@ -1478,66 +1510,64 @@ pub unsafe fn dc_archive_chat( sqlite3_finalize(stmt); } let mut stmt_0: *mut sqlite3_stmt = dc_sqlite3_prepare( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"UPDATE chats SET archived=? WHERE id=?;\x00" as *const u8 as *const libc::c_char, ); sqlite3_bind_int(stmt_0, 1i32, archive); sqlite3_bind_int(stmt_0, 2i32, chat_id as libc::c_int); sqlite3_step(stmt_0); sqlite3_finalize(stmt_0); - ((*context).cb)( + (context.cb)( context, Event::MSGS_CHANGED, 0i32 as uintptr_t, 0i32 as uintptr_t, ); } -pub unsafe fn dc_delete_chat(mut context: *mut dc_context_t, mut chat_id: uint32_t) { + +pub unsafe fn dc_delete_chat(mut context: &dc_context_t, mut chat_id: uint32_t) { /* Up to 2017-11-02 deleting a group also implied leaving it, see above why we have changed this. */ - let mut pending_transaction: libc::c_int = 0i32; let mut obj: *mut dc_chat_t = dc_chat_new(context); let mut q3: *mut libc::c_char = 0 as *mut libc::c_char; - if !(context.is_null() - || (*context).magic != 0x11a11807i32 as libc::c_uint - || chat_id <= 9i32 as libc::c_uint) - { + if !(chat_id <= 9i32 as libc::c_uint) { if !(0 == dc_chat_load_from_db(obj, chat_id)) { - dc_sqlite3_begin_transaction((*context).sql); - pending_transaction = 1i32; q3 = sqlite3_mprintf( b"DELETE FROM msgs_mdns WHERE msg_id IN (SELECT id FROM msgs WHERE chat_id=%i);\x00" as *const u8 as *const libc::c_char, chat_id, ); - if !(0 == dc_sqlite3_execute((*context).sql, q3)) { + if !(0 == dc_sqlite3_execute(context, &context.sql.clone().read().unwrap(), q3)) { sqlite3_free(q3 as *mut libc::c_void); - q3 = 0 as *mut libc::c_char; q3 = sqlite3_mprintf( b"DELETE FROM msgs WHERE chat_id=%i;\x00" as *const u8 as *const libc::c_char, chat_id, ); - if !(0 == dc_sqlite3_execute((*context).sql, q3)) { + if !(0 == dc_sqlite3_execute(context, &context.sql.clone().read().unwrap(), q3)) { sqlite3_free(q3 as *mut libc::c_void); - q3 = 0 as *mut libc::c_char; q3 = sqlite3_mprintf( b"DELETE FROM chats_contacts WHERE chat_id=%i;\x00" as *const u8 as *const libc::c_char, chat_id, ); - if !(0 == dc_sqlite3_execute((*context).sql, q3)) { + if !(0 == dc_sqlite3_execute(context, &context.sql.clone().read().unwrap(), q3)) + { sqlite3_free(q3 as *mut libc::c_void); - q3 = 0 as *mut libc::c_char; q3 = sqlite3_mprintf( b"DELETE FROM chats WHERE id=%i;\x00" as *const u8 as *const libc::c_char, chat_id, ); - if !(0 == dc_sqlite3_execute((*context).sql, q3)) { + if !(0 + == dc_sqlite3_execute( + context, + &context.sql.clone().read().unwrap(), + q3, + )) + { sqlite3_free(q3 as *mut libc::c_void); q3 = 0 as *mut libc::c_char; - dc_sqlite3_commit((*context).sql); - pending_transaction = 0i32; - ((*context).cb)( + (context.cb)( context, Event::MSGS_CHANGED, 0i32 as uintptr_t, @@ -1551,44 +1581,44 @@ pub unsafe fn dc_delete_chat(mut context: *mut dc_context_t, mut chat_id: uint32 } } } - if 0 != pending_transaction { - dc_sqlite3_rollback((*context).sql); - } dc_chat_unref(obj); sqlite3_free(q3 as *mut libc::c_void); } + pub unsafe fn dc_get_chat_contacts( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut chat_id: uint32_t, ) -> *mut dc_array_t { /* Normal chats do not include SELF. Group chats do (as it may happen that one is deleted from a groupchat but the chats stays visible, moreover, this makes displaying lists easier) */ - let mut ret: *mut dc_array_t = dc_array_new(context, 100i32 as size_t); + let mut ret: *mut dc_array_t = dc_array_new(100i32 as size_t); let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; - if !(context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint) { - if !(chat_id == 1i32 as libc::c_uint) { - /* we could also create a list for all contacts in the deaddrop by searching contacts belonging to chats with chats.blocked=2, however, currently this is not needed */ - stmt = - dc_sqlite3_prepare((*context).sql, - b"SELECT cc.contact_id FROM chats_contacts cc LEFT JOIN contacts c ON c.id=cc.contact_id WHERE cc.chat_id=? ORDER BY c.id=1, LOWER(c.name||c.addr), c.id;\x00" - as *const u8 as *const libc::c_char); - sqlite3_bind_int(stmt, 1i32, chat_id as libc::c_int); - while sqlite3_step(stmt) == 100i32 { - dc_array_add_id(ret, sqlite3_column_int(stmt, 0i32) as uint32_t); - } + + if !(chat_id == 1i32 as libc::c_uint) { + /* we could also create a list for all contacts in the deaddrop by searching contacts belonging to chats with chats.blocked=2, however, currently this is not needed */ + stmt = + dc_sqlite3_prepare( + context,&context.sql.clone().read().unwrap(), + b"SELECT cc.contact_id FROM chats_contacts cc LEFT JOIN contacts c ON c.id=cc.contact_id WHERE cc.chat_id=? ORDER BY c.id=1, LOWER(c.name||c.addr), c.id;\x00" + as *const u8 as *const libc::c_char); + sqlite3_bind_int(stmt, 1i32, chat_id as libc::c_int); + while sqlite3_step(stmt) == 100i32 { + dc_array_add_id(ret, sqlite3_column_int(stmt, 0i32) as uint32_t); } } + sqlite3_finalize(stmt); - return ret; + ret } -pub unsafe fn dc_get_chat(mut context: *mut dc_context_t, mut chat_id: uint32_t) -> *mut dc_chat_t { + +pub unsafe fn dc_get_chat(mut context: &dc_context_t, mut chat_id: uint32_t) -> *mut dc_chat_t { let mut success: libc::c_int = 0i32; let mut obj: *mut dc_chat_t = dc_chat_new(context); - if !(context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint) { - if !(0 == dc_chat_load_from_db(obj, chat_id)) { - success = 1i32 - } + + if !(0 == dc_chat_load_from_db(obj, chat_id)) { + success = 1i32 } + if 0 != success { return obj; } else { @@ -1596,28 +1626,26 @@ pub unsafe fn dc_get_chat(mut context: *mut dc_context_t, mut chat_id: uint32_t) return 0 as *mut dc_chat_t; }; } + // handle group chats pub unsafe fn dc_create_group_chat( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut verified: libc::c_int, mut chat_name: *const libc::c_char, ) -> uint32_t { let mut chat_id: uint32_t = 0i32 as uint32_t; - let mut draft_txt: *mut libc::c_char = 0 as *mut libc::c_char; + let mut draft_txt: *mut libc::c_char; let mut draft_msg: *mut dc_msg_t = 0 as *mut dc_msg_t; - let mut grpid: *mut libc::c_char = 0 as *mut libc::c_char; - let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; - if context.is_null() - || (*context).magic != 0x11a11807i32 as libc::c_uint - || chat_name.is_null() - || *chat_name.offset(0isize) as libc::c_int == 0i32 - { + let mut grpid: *mut libc::c_char; + let mut stmt: *mut sqlite3_stmt; + if chat_name.is_null() || *chat_name.offset(0isize) as libc::c_int == 0i32 { return 0i32 as uint32_t; } draft_txt = dc_stock_str_repl_string(context, 14i32, chat_name); grpid = dc_create_id(); stmt = dc_sqlite3_prepare( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"INSERT INTO chats (type, name, grpid, param) VALUES(?, ?, ?, \'U=1\');\x00" as *const u8 as *const libc::c_char, ); @@ -1626,7 +1654,8 @@ pub unsafe fn dc_create_group_chat( sqlite3_bind_text(stmt, 3i32, grpid, -1i32, None); if !(sqlite3_step(stmt) != 101i32) { chat_id = dc_sqlite3_get_rowid( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"chats\x00" as *const u8 as *const libc::c_char, b"grpid\x00" as *const u8 as *const libc::c_char, grpid, @@ -1644,26 +1673,30 @@ pub unsafe fn dc_create_group_chat( dc_msg_unref(draft_msg); free(grpid as *mut libc::c_void); if 0 != chat_id { - ((*context).cb)( + (context.cb)( context, Event::MSGS_CHANGED, 0i32 as uintptr_t, 0i32 as uintptr_t, ); } - return chat_id; + + chat_id } + /* you MUST NOT modify this or the following strings */ // Context functions to work with chats +// TODO should return bool /rtn pub unsafe fn dc_add_to_chat_contacts_table( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut chat_id: uint32_t, mut contact_id: uint32_t, ) -> libc::c_int { /* add a contact to a chat; the function does not check the type or if any of the record exist or are already added to the chat! */ - let mut ret: libc::c_int = 0i32; + let mut ret: libc::c_int; let mut stmt: *mut sqlite3_stmt = dc_sqlite3_prepare( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"INSERT INTO chats_contacts (chat_id, contact_id) VALUES(?, ?)\x00" as *const u8 as *const libc::c_char, ); @@ -1675,17 +1708,20 @@ pub unsafe fn dc_add_to_chat_contacts_table( 0i32 }; sqlite3_finalize(stmt); - return ret; + ret } + pub unsafe fn dc_add_contact_to_chat( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut chat_id: uint32_t, mut contact_id: uint32_t, ) -> libc::c_int { - return dc_add_contact_to_chat_ex(context, chat_id, contact_id, 0i32); + dc_add_contact_to_chat_ex(context, chat_id, contact_id, 0i32) } + +// TODO should return bool /rtn pub unsafe fn dc_add_contact_to_chat_ex( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut chat_id: uint32_t, mut contact_id: uint32_t, mut flags: libc::c_int, @@ -1696,11 +1732,7 @@ pub unsafe fn dc_add_contact_to_chat_ex( let mut chat: *mut dc_chat_t = dc_chat_new(context); let mut msg: *mut dc_msg_t = dc_msg_new_untyped(context); let mut self_addr: *mut libc::c_char = 0 as *mut libc::c_char; - if !(context.is_null() - || (*context).magic != 0x11a11807i32 as libc::c_uint - || contact.is_null() - || chat_id <= 9i32 as libc::c_uint) - { + if !(contact.is_null() || chat_id <= 9i32 as libc::c_uint) { dc_reset_gossiped_timestamp(context, chat_id); /*this also makes sure, not contacts are added to special or normal chats*/ if !(0i32 == real_group_exists(context, chat_id) @@ -1724,7 +1756,8 @@ pub unsafe fn dc_add_contact_to_chat_ex( dc_chat_update_param(chat); } self_addr = dc_sqlite3_get_config( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"configured_addr\x00" as *const u8 as *const libc::c_char, b"\x00" as *const u8 as *const libc::c_char, ); @@ -1781,14 +1814,14 @@ pub unsafe fn dc_add_contact_to_chat_ex( dc_param_set((*msg).param, 'E' as i32, (*contact).addr); dc_param_set_int((*msg).param, 'F' as i32, flags); (*msg).id = dc_send_msg(context, chat_id, msg); - ((*context).cb)( + (context.cb)( context, Event::MSGS_CHANGED, chat_id as uintptr_t, (*msg).id as uintptr_t, ); } - ((*context).cb)( + (context.cb)( context, Event::MSGS_CHANGED, chat_id as uintptr_t, @@ -1805,21 +1838,21 @@ pub unsafe fn dc_add_contact_to_chat_ex( dc_contact_unref(contact); dc_msg_unref(msg); free(self_addr as *mut libc::c_void); - return success; + + success } -unsafe fn real_group_exists(mut context: *mut dc_context_t, mut chat_id: uint32_t) -> libc::c_int { + +// TODO should return bool /rtn +unsafe fn real_group_exists(mut context: &dc_context_t, mut chat_id: uint32_t) -> libc::c_int { // check if a group or a verified group exists under the given ID - let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; + let mut stmt: *mut sqlite3_stmt; let mut ret: libc::c_int = 0i32; - if context.is_null() - || (*context).magic != 0x11a11807i32 as libc::c_uint - || (*(*context).sql).cobj.is_null() - || chat_id <= 9i32 as libc::c_uint - { + if (*context.sql.clone().read().unwrap()).cobj.is_null() || chat_id <= 9i32 as libc::c_uint { return 0i32; } stmt = dc_sqlite3_prepare( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"SELECT id FROM chats WHERE id=? AND (type=120 OR type=130);\x00" as *const u8 as *const libc::c_char, ); @@ -1828,17 +1861,19 @@ unsafe fn real_group_exists(mut context: *mut dc_context_t, mut chat_id: uint32_ ret = 1i32 } sqlite3_finalize(stmt); - return ret; + ret } -pub unsafe fn dc_reset_gossiped_timestamp(mut context: *mut dc_context_t, mut chat_id: uint32_t) { + +pub unsafe fn dc_reset_gossiped_timestamp(mut context: &dc_context_t, mut chat_id: uint32_t) { dc_set_gossiped_timestamp(context, chat_id, 0i32 as time_t); } + pub unsafe fn dc_set_gossiped_timestamp( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut chat_id: uint32_t, mut timestamp: time_t, ) { - let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; + let mut stmt: *mut sqlite3_stmt; if 0 != chat_id { dc_log_info( context, @@ -1848,7 +1883,8 @@ pub unsafe fn dc_set_gossiped_timestamp( timestamp as libc::c_int, ); stmt = dc_sqlite3_prepare( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"UPDATE chats SET gossiped_timestamp=? WHERE id=?;\x00" as *const u8 as *const libc::c_char, ); @@ -1862,7 +1898,8 @@ pub unsafe fn dc_set_gossiped_timestamp( timestamp as libc::c_int, ); stmt = dc_sqlite3_prepare( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"UPDATE chats SET gossiped_timestamp=?;\x00" as *const u8 as *const libc::c_char, ); sqlite3_bind_int64(stmt, 1i32, timestamp as sqlite3_int64); @@ -1870,8 +1907,10 @@ pub unsafe fn dc_set_gossiped_timestamp( sqlite3_step(stmt); sqlite3_finalize(stmt); } + +// TODO should return bool /rtn pub unsafe fn dc_remove_contact_from_chat( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut chat_id: uint32_t, mut contact_id: uint32_t, ) -> libc::c_int { @@ -1880,9 +1919,7 @@ pub unsafe fn dc_remove_contact_from_chat( let mut chat: *mut dc_chat_t = dc_chat_new(context); let mut msg: *mut dc_msg_t = dc_msg_new_untyped(context); let mut q3: *mut libc::c_char = 0 as *mut libc::c_char; - if !(context.is_null() - || (*context).magic != 0x11a11807i32 as libc::c_uint - || chat_id <= 9i32 as libc::c_uint + if !(chat_id <= 9i32 as libc::c_uint || contact_id <= 9i32 as libc::c_uint && contact_id != 1i32 as libc::c_uint) { /* we do not check if "contact_id" exists but just delete all records with the id from chats_contacts */ @@ -1924,7 +1961,7 @@ pub unsafe fn dc_remove_contact_from_chat( dc_param_set_int((*msg).param, 'S' as i32, 5i32); dc_param_set((*msg).param, 'E' as i32, (*contact).addr); (*msg).id = dc_send_msg(context, chat_id, msg); - ((*context).cb)( + (context.cb)( context, Event::MSGS_CHANGED, chat_id as uintptr_t, @@ -1938,8 +1975,8 @@ pub unsafe fn dc_remove_contact_from_chat( chat_id, contact_id, ); - if !(0 == dc_sqlite3_execute((*context).sql, q3)) { - ((*context).cb)( + if !(0 == dc_sqlite3_execute(context, &context.sql.clone().read().unwrap(), q3)) { + (context.cb)( context, Event::CHAT_MODIFIED, chat_id as uintptr_t, @@ -1954,15 +1991,18 @@ pub unsafe fn dc_remove_contact_from_chat( dc_chat_unref(chat); dc_contact_unref(contact); dc_msg_unref(msg); - return success; + + success } + pub unsafe fn dc_set_group_explicitly_left( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut grpid: *const libc::c_char, ) { if 0 == dc_is_group_explicitly_left(context, grpid) { let mut stmt: *mut sqlite3_stmt = dc_sqlite3_prepare( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"INSERT INTO leftgrps (grpid) VALUES(?);\x00" as *const u8 as *const libc::c_char, ); sqlite3_bind_text(stmt, 1i32, grpid, -1i32, None); @@ -1970,21 +2010,26 @@ pub unsafe fn dc_set_group_explicitly_left( sqlite3_finalize(stmt); }; } + +// TODO should return bool /rtn pub unsafe fn dc_is_group_explicitly_left( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut grpid: *const libc::c_char, ) -> libc::c_int { let mut stmt: *mut sqlite3_stmt = dc_sqlite3_prepare( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"SELECT id FROM leftgrps WHERE grpid=?;\x00" as *const u8 as *const libc::c_char, ); sqlite3_bind_text(stmt, 1i32, grpid, -1i32, None); let mut ret: libc::c_int = (sqlite3_step(stmt) == 100i32) as libc::c_int; sqlite3_finalize(stmt); - return ret; + ret } + +// TODO should return bool /rtn pub unsafe fn dc_set_chat_name( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut chat_id: uint32_t, mut new_name: *const libc::c_char, ) -> libc::c_int { @@ -1993,9 +2038,7 @@ pub unsafe fn dc_set_chat_name( let mut chat: *mut dc_chat_t = dc_chat_new(context); let mut msg: *mut dc_msg_t = dc_msg_new_untyped(context); let mut q3: *mut libc::c_char = 0 as *mut libc::c_char; - if !(context.is_null() - || (*context).magic != 0x11a11807i32 as libc::c_uint - || new_name.is_null() + if !(new_name.is_null() || *new_name.offset(0isize) as libc::c_int == 0i32 || chat_id <= 9i32 as libc::c_uint) { @@ -2020,7 +2063,7 @@ pub unsafe fn dc_set_chat_name( new_name, chat_id, ); - if !(0 == dc_sqlite3_execute((*context).sql, q3)) { + if !(0 == dc_sqlite3_execute(context, &context.sql.clone().read().unwrap(), q3)) { if dc_param_get_int((*chat).param, 'U' as i32, 0i32) == 0i32 { (*msg).type_0 = 10i32; (*msg).text = dc_stock_system_msg( @@ -2033,14 +2076,14 @@ pub unsafe fn dc_set_chat_name( dc_param_set_int((*msg).param, 'S' as i32, 2i32); dc_param_set((*msg).param, 'E' as i32, (*chat).name); (*msg).id = dc_send_msg(context, chat_id, msg); - ((*context).cb)( + (context.cb)( context, Event::MSGS_CHANGED, chat_id as uintptr_t, (*msg).id as uintptr_t, ); } - ((*context).cb)( + (context.cb)( context, Event::CHAT_MODIFIED, chat_id as uintptr_t, @@ -2051,13 +2094,17 @@ pub unsafe fn dc_set_chat_name( } } } + sqlite3_free(q3 as *mut libc::c_void); dc_chat_unref(chat); dc_msg_unref(msg); - return success; + + success } + +// TODO should return bool /rtn pub unsafe fn dc_set_chat_profile_image( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut chat_id: uint32_t, mut new_image: *const libc::c_char, ) -> libc::c_int { @@ -2066,10 +2113,7 @@ pub unsafe fn dc_set_chat_profile_image( let mut chat: *mut dc_chat_t = dc_chat_new(context); let mut msg: *mut dc_msg_t = dc_msg_new_untyped(context); let mut new_image_rel: *mut libc::c_char = 0 as *mut libc::c_char; - if !(context.is_null() - || (*context).magic != 0x11a11807i32 as libc::c_uint - || chat_id <= 9i32 as libc::c_uint) - { + if !(chat_id <= 9i32 as libc::c_uint) { if !(0i32 == real_group_exists(context, chat_id) || 0i32 == dc_chat_load_from_db(chat, chat_id)) { @@ -2114,14 +2158,14 @@ pub unsafe fn dc_set_chat_profile_image( 1i32 as uint32_t, ); (*msg).id = dc_send_msg(context, chat_id, msg); - ((*context).cb)( + (context.cb)( context, Event::MSGS_CHANGED, chat_id as uintptr_t, (*msg).id as uintptr_t, ); } - ((*context).cb)( + (context.cb)( context, Event::CHAT_MODIFIED, chat_id as uintptr_t, @@ -2134,38 +2178,31 @@ pub unsafe fn dc_set_chat_profile_image( } } } + dc_chat_unref(chat); dc_msg_unref(msg); free(new_image_rel as *mut libc::c_void); - return success; + + success } + pub unsafe fn dc_forward_msgs( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut msg_ids: *const uint32_t, mut msg_cnt: libc::c_int, mut chat_id: uint32_t, ) { - let mut current_block: u64; let mut msg: *mut dc_msg_t = dc_msg_new_untyped(context); let mut chat: *mut dc_chat_t = dc_chat_new(context); let mut contact: *mut dc_contact_t = dc_contact_new(context); - let mut transaction_pending: libc::c_int = 0i32; let mut created_db_entries: *mut carray = carray_new(16i32 as libc::c_uint); let mut idsstr: *mut libc::c_char = 0 as *mut libc::c_char; let mut q3: *mut libc::c_char = 0 as *mut libc::c_char; let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; - let mut curr_timestamp: time_t = 0i32 as time_t; + let mut curr_timestamp: time_t; let mut original_param: *mut dc_param_t = dc_param_new(); - if !(context.is_null() - || (*context).magic != 0x11a11807i32 as libc::c_uint - || msg_ids.is_null() - || msg_cnt <= 0i32 - || chat_id <= 9i32 as libc::c_uint) - { - dc_sqlite3_begin_transaction((*context).sql); - transaction_pending = 1i32; + if !(msg_ids.is_null() || msg_cnt <= 0i32 || chat_id <= 9i32 as libc::c_uint) { dc_unarchive_chat(context, chat_id); - (*(*context).smtp).log_connect_errors = 1i32; if !(0 == dc_chat_load_from_db(chat, chat_id)) { curr_timestamp = dc_create_smeared_timestamps(context, msg_cnt); idsstr = dc_arr_to_string(msg_ids, msg_cnt); @@ -2174,15 +2211,13 @@ pub unsafe fn dc_forward_msgs( as *const libc::c_char, idsstr, ); - stmt = dc_sqlite3_prepare((*context).sql, q3); + stmt = dc_sqlite3_prepare(context, &context.sql.clone().read().unwrap(), q3); loop { if !(sqlite3_step(stmt) == 100i32) { - current_block = 10758786907990354186; break; } let mut src_msg_id: libc::c_int = sqlite3_column_int(stmt, 0i32); if 0 == dc_msg_load_from_db(msg, context, src_msg_id as uint32_t) { - current_block = 2015322633586469911; break; } dc_param_set_packed(original_param, (*(*msg).param).packed); @@ -2192,7 +2227,7 @@ pub unsafe fn dc_forward_msgs( dc_param_set((*msg).param, 'c' as i32, 0 as *const libc::c_char); dc_param_set((*msg).param, 'u' as i32, 0 as *const libc::c_char); dc_param_set((*msg).param, 'S' as i32, 0 as *const libc::c_char); - let mut new_msg_id: uint32_t = 0; + let mut new_msg_id: uint32_t; if (*msg).state == 18i32 { let fresh9 = curr_timestamp; curr_timestamp = curr_timestamp + 1; @@ -2233,23 +2268,13 @@ pub unsafe fn dc_forward_msgs( 0 as *mut libc::c_uint, ); } - match current_block { - 2015322633586469911 => {} - _ => { - dc_sqlite3_commit((*context).sql); - transaction_pending = 0i32 - } - } } } - if 0 != transaction_pending { - dc_sqlite3_rollback((*context).sql); - } if !created_db_entries.is_null() { let mut i = 0u32; let mut icnt = carray_count(created_db_entries); while i < icnt { - ((*context).cb)( + (context.cb)( context, Event::MSGS_CHANGED, carray_get(created_db_entries, i) as uintptr_t, @@ -2267,24 +2292,28 @@ pub unsafe fn dc_forward_msgs( sqlite3_free(q3 as *mut libc::c_void); dc_param_unref(original_param); } + pub unsafe fn dc_chat_get_id(mut chat: *const dc_chat_t) -> uint32_t { if chat.is_null() || (*chat).magic != 0xc4a7c4a7u32 { return 0i32 as uint32_t; } - return (*chat).id; + (*chat).id } + pub unsafe fn dc_chat_get_type(mut chat: *const dc_chat_t) -> libc::c_int { if chat.is_null() || (*chat).magic != 0xc4a7c4a7u32 { return 0i32; } - return (*chat).type_0; + (*chat).type_0 } + pub unsafe fn dc_chat_get_name(mut chat: *const dc_chat_t) -> *mut libc::c_char { if chat.is_null() || (*chat).magic != 0xc4a7c4a7u32 { return dc_strdup(b"Err\x00" as *const u8 as *const libc::c_char); } - return dc_strdup((*chat).name); + dc_strdup((*chat).name) } + pub unsafe extern "C" fn dc_chat_get_subtitle(mut chat: *const dc_chat_t) -> *mut libc::c_char { /* returns either the address or the number of chat members */ let mut ret: *mut libc::c_char = 0 as *mut libc::c_char; @@ -2294,9 +2323,10 @@ pub unsafe extern "C" fn dc_chat_get_subtitle(mut chat: *const dc_chat_t) -> *mu if (*chat).type_0 == 100i32 && 0 != dc_param_exists((*chat).param, 'K' as i32) { ret = dc_stock_str((*chat).context, 50i32) } else if (*chat).type_0 == 100i32 { - let mut r: libc::c_int = 0; + let mut r: libc::c_int; let mut stmt: *mut sqlite3_stmt = - dc_sqlite3_prepare((*(*chat).context).sql, + dc_sqlite3_prepare( + (*chat).context,&mut (*chat).context.sql.clone().read().unwrap(), b"SELECT c.addr FROM chats_contacts cc LEFT JOIN contacts c ON c.id=cc.contact_id WHERE cc.chat_id=?;\x00" as *const u8 as *const libc::c_char); sqlite3_bind_int(stmt, 1i32, (*chat).id as libc::c_int); @@ -2306,7 +2336,7 @@ pub unsafe extern "C" fn dc_chat_get_subtitle(mut chat: *const dc_chat_t) -> *mu } sqlite3_finalize(stmt); } else if (*chat).type_0 == 120i32 || (*chat).type_0 == 130i32 { - let mut cnt: libc::c_int = 0i32; + let mut cnt: libc::c_int; if (*chat).id == 1i32 as libc::c_uint { ret = dc_stock_str((*chat).context, 8i32) } else { @@ -2320,13 +2350,15 @@ pub unsafe extern "C" fn dc_chat_get_subtitle(mut chat: *const dc_chat_t) -> *mu dc_strdup(b"Err\x00" as *const u8 as *const libc::c_char) }; } + pub unsafe fn dc_get_chat_contact_cnt( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut chat_id: uint32_t, ) -> libc::c_int { let mut ret: libc::c_int = 0i32; let mut stmt: *mut sqlite3_stmt = dc_sqlite3_prepare( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"SELECT COUNT(*) FROM chats_contacts WHERE chat_id=?;\x00" as *const u8 as *const libc::c_char, ); @@ -2335,8 +2367,9 @@ pub unsafe fn dc_get_chat_contact_cnt( ret = sqlite3_column_int(stmt, 0i32) } sqlite3_finalize(stmt); - return ret; + ret } + pub unsafe fn dc_chat_get_profile_image(mut chat: *const dc_chat_t) -> *mut libc::c_char { let mut image_rel: *mut libc::c_char = 0 as *mut libc::c_char; let mut image_abs: *mut libc::c_char = 0 as *mut libc::c_char; @@ -2357,11 +2390,14 @@ pub unsafe fn dc_chat_get_profile_image(mut chat: *const dc_chat_t) -> *mut libc } } } + free(image_rel as *mut libc::c_void); dc_array_unref(contacts); dc_contact_unref(contact); - return image_abs; + + image_abs } + pub unsafe fn dc_chat_get_color(mut chat: *const dc_chat_t) -> uint32_t { let mut color: uint32_t = 0i32 as uint32_t; let mut contacts: *mut dc_array_t = 0 as *mut dc_array_t; @@ -2380,44 +2416,53 @@ pub unsafe fn dc_chat_get_color(mut chat: *const dc_chat_t) -> uint32_t { color = dc_str_to_color((*chat).name) as uint32_t } } + dc_array_unref(contacts); dc_contact_unref(contact); - return color; + + color } + +// TODO should return bool /rtn pub unsafe fn dc_chat_get_archived(mut chat: *const dc_chat_t) -> libc::c_int { if chat.is_null() || (*chat).magic != 0xc4a7c4a7u32 { return 0i32; } - return (*chat).archived; + (*chat).archived } + +// TODO should return bool /rtn pub unsafe fn dc_chat_is_unpromoted(mut chat: *const dc_chat_t) -> libc::c_int { if chat.is_null() || (*chat).magic != 0xc4a7c4a7u32 { return 0i32; } - return dc_param_get_int((*chat).param, 'U' as i32, 0i32); + dc_param_get_int((*chat).param, 'U' as i32, 0i32) } + +// TODO should return bool /rtn pub unsafe fn dc_chat_is_verified(mut chat: *const dc_chat_t) -> libc::c_int { if chat.is_null() || (*chat).magic != 0xc4a7c4a7u32 { return 0i32; } - return ((*chat).type_0 == 130i32) as libc::c_int; + ((*chat).type_0 == 130i32) as libc::c_int } + +// TODO should return bool /rtn pub unsafe fn dc_chat_is_sending_locations(mut chat: *const dc_chat_t) -> libc::c_int { if chat.is_null() || (*chat).magic != 0xc4a7c4a7u32 { return 0i32; } - return (*chat).is_sending_locations; + (*chat).is_sending_locations } -pub unsafe fn dc_get_chat_cnt(mut context: *mut dc_context_t) -> size_t { + +pub unsafe fn dc_get_chat_cnt(mut context: &dc_context_t) -> size_t { let mut ret: size_t = 0i32 as size_t; let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; - if !(context.is_null() - || (*context).magic != 0x11a11807i32 as libc::c_uint - || (*(*context).sql).cobj.is_null()) - { + if !(*context.sql.clone().read().unwrap()).cobj.is_null() { /* no database, no chats - this is no error (needed eg. for information) */ stmt = dc_sqlite3_prepare( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"SELECT COUNT(*) FROM chats WHERE id>9 AND blocked=0;\x00" as *const u8 as *const libc::c_char, ); @@ -2426,56 +2471,60 @@ pub unsafe fn dc_get_chat_cnt(mut context: *mut dc_context_t) -> size_t { } } sqlite3_finalize(stmt); - return ret; + ret } + pub unsafe fn dc_get_chat_id_by_grpid( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut grpid: *const libc::c_char, mut ret_blocked: *mut libc::c_int, mut ret_verified: *mut libc::c_int, ) -> uint32_t { let mut chat_id: uint32_t = 0i32 as uint32_t; - let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; + let mut stmt: *mut sqlite3_stmt; if !ret_blocked.is_null() { *ret_blocked = 0i32 } if !ret_verified.is_null() { *ret_verified = 0i32 } - if !(context.is_null() || grpid.is_null()) { - stmt = dc_sqlite3_prepare( - (*context).sql, - b"SELECT id, blocked, type FROM chats WHERE grpid=?;\x00" as *const u8 - as *const libc::c_char, - ); - sqlite3_bind_text(stmt, 1i32, grpid, -1i32, None); - if sqlite3_step(stmt) == 100i32 { - chat_id = sqlite3_column_int(stmt, 0i32) as uint32_t; - if !ret_blocked.is_null() { - *ret_blocked = sqlite3_column_int(stmt, 1i32) - } - if !ret_verified.is_null() { - *ret_verified = (sqlite3_column_int(stmt, 2i32) == 130i32) as libc::c_int - } + + stmt = dc_sqlite3_prepare( + context, + &context.sql.clone().read().unwrap(), + b"SELECT id, blocked, type FROM chats WHERE grpid=?;\x00" as *const u8 + as *const libc::c_char, + ); + sqlite3_bind_text(stmt, 1i32, grpid, -1i32, None); + if sqlite3_step(stmt) == 100i32 { + chat_id = sqlite3_column_int(stmt, 0i32) as uint32_t; + if !ret_blocked.is_null() { + *ret_blocked = sqlite3_column_int(stmt, 1i32) + } + if !ret_verified.is_null() { + *ret_verified = (sqlite3_column_int(stmt, 2i32) == 130i32) as libc::c_int } } + sqlite3_finalize(stmt); - return chat_id; + chat_id } + pub unsafe fn dc_add_device_msg( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut chat_id: uint32_t, mut text: *const libc::c_char, ) { - let mut msg_id: uint32_t = 0i32 as uint32_t; + let mut msg_id: uint32_t; let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; let mut rfc724_mid: *mut libc::c_char = dc_create_outgoing_rfc724_mid( 0 as *const libc::c_char, b"@device\x00" as *const u8 as *const libc::c_char, ); - if !(context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint || text.is_null()) { + if !text.is_null() { stmt = - dc_sqlite3_prepare((*context).sql, + dc_sqlite3_prepare( + context,&context.sql.clone().read().unwrap(), b"INSERT INTO msgs (chat_id,from_id,to_id, timestamp,type,state, txt,rfc724_mid) VALUES (?,?,?, ?,?,?, ?,?);\x00" as *const u8 as *const libc::c_char); sqlite3_bind_int(stmt, 1i32, chat_id as libc::c_int); @@ -2492,12 +2541,13 @@ pub unsafe fn dc_add_device_msg( sqlite3_bind_text(stmt, 8i32, rfc724_mid, -1i32, None); if !(sqlite3_step(stmt) != 101i32) { msg_id = dc_sqlite3_get_rowid( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"msgs\x00" as *const u8 as *const libc::c_char, b"rfc724_mid\x00" as *const u8 as *const libc::c_char, rfc724_mid, ); - ((*context).cb)( + (context.cb)( context, Event::MSGS_CHANGED, chat_id as uintptr_t, diff --git a/src/dc_chatlist.rs b/src/dc_chatlist.rs index dba84afe8..bf3d7b10a 100644 --- a/src/dc_chatlist.rs +++ b/src/dc_chatlist.rs @@ -1,5 +1,3 @@ -use libc; - use crate::dc_array::*; use crate::dc_chat::*; use crate::dc_contact::*; @@ -15,27 +13,27 @@ use crate::x::*; /* * the structure behind dc_chatlist_t */ #[derive(Copy, Clone)] #[repr(C)] -pub struct dc_chatlist_t { +pub struct dc_chatlist_t<'a> { pub magic: uint32_t, - pub context: *mut dc_context_t, + pub context: &'a dc_context_t, pub cnt: size_t, pub chatNlastmsg_ids: *mut dc_array_t, } // handle chatlists -pub unsafe fn dc_get_chatlist( - mut context: *mut dc_context_t, +pub unsafe fn dc_get_chatlist<'a>( + mut context: &'a dc_context_t, mut listflags: libc::c_int, mut query_str: *const libc::c_char, mut query_id: uint32_t, -) -> *mut dc_chatlist_t { +) -> *mut dc_chatlist_t<'a> { let mut success: libc::c_int = 0i32; let mut obj: *mut dc_chatlist_t = dc_chatlist_new(context); - if !(context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint) { - if !(0 == dc_chatlist_load_from_db(obj, listflags, query_str, query_id)) { - success = 1i32 - } + + if !(0 == dc_chatlist_load_from_db(obj, listflags, query_str, query_id)) { + success = 1i32 } + if 0 != success { return obj; } else { @@ -43,7 +41,8 @@ pub unsafe fn dc_get_chatlist( return 0 as *mut dc_chatlist_t; }; } -/* * + +/** * @class dc_chatlist_t * * An object representing a single chatlist in memory. @@ -81,20 +80,21 @@ pub unsafe fn dc_get_chatlist( * Rendering the deaddrop in the described way * would not add extra work in the UI then. */ -pub unsafe fn dc_chatlist_new(mut context: *mut dc_context_t) -> *mut dc_chatlist_t { - let mut chatlist: *mut dc_chatlist_t = 0 as *mut dc_chatlist_t; +pub unsafe fn dc_chatlist_new(mut context: &dc_context_t) -> *mut dc_chatlist_t { + let mut chatlist: *mut dc_chatlist_t; chatlist = calloc(1, ::std::mem::size_of::()) as *mut dc_chatlist_t; if chatlist.is_null() { exit(20i32); } (*chatlist).magic = 0xc4a71157u32; (*chatlist).context = context; - (*chatlist).chatNlastmsg_ids = dc_array_new(context, 128i32 as size_t); + (*chatlist).chatNlastmsg_ids = dc_array_new(128i32 as size_t); if (*chatlist).chatNlastmsg_ids.is_null() { exit(32i32); } - return chatlist; + chatlist } + pub unsafe fn dc_chatlist_unref(mut chatlist: *mut dc_chatlist_t) { if chatlist.is_null() || (*chatlist).magic != 0xc4a71157u32 { return; @@ -104,6 +104,7 @@ pub unsafe fn dc_chatlist_unref(mut chatlist: *mut dc_chatlist_t) { (*chatlist).magic = 0i32 as uint32_t; free(chatlist as *mut libc::c_void); } + pub unsafe fn dc_chatlist_empty(mut chatlist: *mut dc_chatlist_t) { if chatlist.is_null() || (*chatlist).magic != 0xc4a71157u32 { return; @@ -111,11 +112,13 @@ pub unsafe fn dc_chatlist_empty(mut chatlist: *mut dc_chatlist_t) { (*chatlist).cnt = 0i32 as size_t; dc_array_empty((*chatlist).chatNlastmsg_ids); } -/* * + +/** * Load a chatlist from the database to the chatlist object. * * @private @memberof dc_chatlist_t */ +// TODO should return bool /rtn unsafe fn dc_chatlist_load_from_db( mut chatlist: *mut dc_chatlist_t, mut listflags: libc::c_int, @@ -129,8 +132,7 @@ unsafe fn dc_chatlist_load_from_db( let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; let mut strLikeCmd: *mut libc::c_char = 0 as *mut libc::c_char; let mut query: *mut libc::c_char = 0 as *mut libc::c_char; - if !(chatlist.is_null() || (*chatlist).magic != 0xc4a71157u32 || (*chatlist).context.is_null()) - { + if !(chatlist.is_null() || (*chatlist).magic != 0xc4a71157u32) { dc_chatlist_empty(chatlist); // select with left join and minimum: // - the inner select must use `hidden` and _not_ `m.hidden` @@ -144,15 +146,20 @@ unsafe fn dc_chatlist_load_from_db( // shown at all permanent in the chatlist. if 0 != query_contact_id { stmt = - dc_sqlite3_prepare((*(*chatlist).context).sql, - b"SELECT c.id, m.id FROM chats c LEFT JOIN msgs m ON c.id=m.chat_id AND m.timestamp=( SELECT MAX(timestamp) FROM msgs WHERE chat_id=c.id AND (hidden=0 OR (hidden=1 AND state=19))) WHERE c.id>9 AND c.blocked=0 AND c.id IN(SELECT chat_id FROM chats_contacts WHERE contact_id=?) GROUP BY c.id ORDER BY IFNULL(m.timestamp,0) DESC, m.id DESC;\x00" - as *const u8 as *const libc::c_char); + dc_sqlite3_prepare( + (*chatlist).context, + &mut (*chatlist).context.sql.clone().read().unwrap(), + b"SELECT c.id, m.id FROM chats c LEFT JOIN msgs m ON c.id=m.chat_id AND m.timestamp=( SELECT MAX(timestamp) FROM msgs WHERE chat_id=c.id AND (hidden=0 OR (hidden=1 AND state=19))) WHERE c.id>9 AND c.blocked=0 AND c.id IN(SELECT chat_id FROM chats_contacts WHERE contact_id=?) GROUP BY c.id ORDER BY IFNULL(m.timestamp,0) DESC, m.id DESC;\x00" + as *const u8 as *const libc::c_char + ); sqlite3_bind_int(stmt, 1i32, query_contact_id as libc::c_int); current_block = 3437258052017859086; } else if 0 != listflags & 0x1i32 { stmt = - dc_sqlite3_prepare((*(*chatlist).context).sql, - b"SELECT c.id, m.id FROM chats c LEFT JOIN msgs m ON c.id=m.chat_id AND m.timestamp=( SELECT MAX(timestamp) FROM msgs WHERE chat_id=c.id AND (hidden=0 OR (hidden=1 AND state=19))) WHERE c.id>9 AND c.blocked=0 AND c.archived=1 GROUP BY c.id ORDER BY IFNULL(m.timestamp,0) DESC, m.id DESC;\x00" + dc_sqlite3_prepare( + (*chatlist).context, + &mut (*chatlist).context.sql.clone().read().unwrap(), + b"SELECT c.id, m.id FROM chats c LEFT JOIN msgs m ON c.id=m.chat_id AND m.timestamp=( SELECT MAX(timestamp) FROM msgs WHERE chat_id=c.id AND (hidden=0 OR (hidden=1 AND state=19))) WHERE c.id>9 AND c.blocked=0 AND c.archived=1 GROUP BY c.id ORDER BY IFNULL(m.timestamp,0) DESC, m.id DESC;\x00" as *const u8 as *const libc::c_char); current_block = 3437258052017859086; } else if query__.is_null() { @@ -166,7 +173,9 @@ unsafe fn dc_chatlist_load_from_db( add_archived_link_item = 1i32 } stmt = - dc_sqlite3_prepare((*(*chatlist).context).sql, + dc_sqlite3_prepare( + (*chatlist).context, + &mut (*chatlist).context.sql.clone().read().unwrap(), b"SELECT c.id, m.id FROM chats c LEFT JOIN msgs m ON c.id=m.chat_id AND m.timestamp=( SELECT MAX(timestamp) FROM msgs WHERE chat_id=c.id AND (hidden=0 OR (hidden=1 AND state=19))) WHERE c.id>9 AND c.blocked=0 AND c.archived=0 GROUP BY c.id ORDER BY IFNULL(m.timestamp,0) DESC, m.id DESC;\x00" as *const u8 as *const libc::c_char); current_block = 3437258052017859086; @@ -179,8 +188,10 @@ unsafe fn dc_chatlist_load_from_db( } else { strLikeCmd = dc_mprintf(b"%%%s%%\x00" as *const u8 as *const libc::c_char, query); stmt = - dc_sqlite3_prepare((*(*chatlist).context).sql, - b"SELECT c.id, m.id FROM chats c LEFT JOIN msgs m ON c.id=m.chat_id AND m.timestamp=( SELECT MAX(timestamp) FROM msgs WHERE chat_id=c.id AND (hidden=0 OR (hidden=1 AND state=19))) WHERE c.id>9 AND c.blocked=0 AND c.name LIKE ? GROUP BY c.id ORDER BY IFNULL(m.timestamp,0) DESC, m.id DESC;\x00" + dc_sqlite3_prepare( + (*chatlist).context, + &mut (*chatlist).context.sql.clone().read().unwrap(), + b"SELECT c.id, m.id FROM chats c LEFT JOIN msgs m ON c.id=m.chat_id AND m.timestamp=( SELECT MAX(timestamp) FROM msgs WHERE chat_id=c.id AND (hidden=0 OR (hidden=1 AND state=19))) WHERE c.id>9 AND c.blocked=0 AND c.name LIKE ? GROUP BY c.id ORDER BY IFNULL(m.timestamp,0) DESC, m.id DESC;\x00" as *const u8 as *const libc::c_char); sqlite3_bind_text(stmt, 1i32, strLikeCmd, -1i32, None); @@ -218,13 +229,15 @@ unsafe fn dc_chatlist_load_from_db( sqlite3_finalize(stmt); free(query as *mut libc::c_void); free(strLikeCmd as *mut libc::c_void); - return success; + success } + // Context functions to work with chatlist -pub unsafe fn dc_get_archived_cnt(mut context: *mut dc_context_t) -> libc::c_int { +pub unsafe fn dc_get_archived_cnt(mut context: &dc_context_t) -> libc::c_int { let mut ret: libc::c_int = 0i32; let mut stmt: *mut sqlite3_stmt = dc_sqlite3_prepare( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"SELECT COUNT(*) FROM chats WHERE blocked=0 AND archived=1;\x00" as *const u8 as *const libc::c_char, ); @@ -232,28 +245,33 @@ pub unsafe fn dc_get_archived_cnt(mut context: *mut dc_context_t) -> libc::c_int ret = sqlite3_column_int(stmt, 0i32) } sqlite3_finalize(stmt); - return ret; + ret } -unsafe fn get_last_deaddrop_fresh_msg(mut context: *mut dc_context_t) -> uint32_t { + +unsafe fn get_last_deaddrop_fresh_msg(mut context: &dc_context_t) -> uint32_t { let mut ret: uint32_t = 0i32 as uint32_t; - let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; + let mut stmt: *mut sqlite3_stmt; stmt = - dc_sqlite3_prepare((*context).sql, - b"SELECT m.id FROM msgs m LEFT JOIN chats c ON c.id=m.chat_id WHERE m.state=10 AND m.hidden=0 AND c.blocked=2 ORDER BY m.timestamp DESC, m.id DESC;\x00" + dc_sqlite3_prepare( + context, + &context.sql.clone().read().unwrap(), + b"SELECT m.id FROM msgs m LEFT JOIN chats c ON c.id=m.chat_id WHERE m.state=10 AND m.hidden=0 AND c.blocked=2 ORDER BY m.timestamp DESC, m.id DESC;\x00" as *const u8 as *const libc::c_char); /* we have an index over the state-column, this should be sufficient as there are typically only few fresh messages */ if !(sqlite3_step(stmt) != 100i32) { ret = sqlite3_column_int(stmt, 0i32) as uint32_t } sqlite3_finalize(stmt); - return ret; + ret } + pub unsafe fn dc_chatlist_get_cnt(mut chatlist: *const dc_chatlist_t) -> size_t { if chatlist.is_null() || (*chatlist).magic != 0xc4a71157u32 { return 0i32 as size_t; } - return (*chatlist).cnt; + (*chatlist).cnt } + pub unsafe fn dc_chatlist_get_chat_id( mut chatlist: *const dc_chatlist_t, mut index: size_t, @@ -265,8 +283,9 @@ pub unsafe fn dc_chatlist_get_chat_id( { return 0i32 as uint32_t; } - return dc_array_get_id((*chatlist).chatNlastmsg_ids, index.wrapping_mul(2)); + dc_array_get_id((*chatlist).chatNlastmsg_ids, index.wrapping_mul(2)) } + pub unsafe fn dc_chatlist_get_msg_id( mut chatlist: *const dc_chatlist_t, mut index: size_t, @@ -278,15 +297,16 @@ pub unsafe fn dc_chatlist_get_msg_id( { return 0i32 as uint32_t; } - return dc_array_get_id( + dc_array_get_id( (*chatlist).chatNlastmsg_ids, index.wrapping_mul(2).wrapping_add(1), - ); + ) } -pub unsafe fn dc_chatlist_get_summary( - mut chatlist: *const dc_chatlist_t, + +pub unsafe fn dc_chatlist_get_summary<'a>( + mut chatlist: *const dc_chatlist_t<'a>, mut index: size_t, - mut chat: *mut dc_chat_t, + mut chat: *mut dc_chat_t<'a>, ) -> *mut dc_lot_t { let mut current_block: u64; /* The summary is created by the chat, not by the last message. @@ -296,7 +316,7 @@ pub unsafe fn dc_chatlist_get_summary( message. */ /* the function never returns NULL */ let mut ret: *mut dc_lot_t = dc_lot_new(); - let mut lastmsg_id: uint32_t = 0i32 as uint32_t; + let mut lastmsg_id: uint32_t; let mut lastmsg: *mut dc_msg_t = 0 as *mut dc_msg_t; let mut lastcontact: *mut dc_contact_t = 0 as *mut dc_contact_t; let mut chat_to_delete: *mut dc_chat_t = 0 as *mut dc_chat_t; @@ -335,7 +355,7 @@ pub unsafe fn dc_chatlist_get_summary( lastcontact = dc_contact_new((*chatlist).context); dc_contact_load_from_db( lastcontact, - (*(*chatlist).context).sql, + &mut (*chatlist).context.sql.clone().read().unwrap(), (*lastmsg).from_id, ); } @@ -353,11 +373,5 @@ pub unsafe fn dc_chatlist_get_summary( dc_msg_unref(lastmsg); dc_contact_unref(lastcontact); dc_chat_unref(chat_to_delete); - return ret; -} -pub unsafe fn dc_chatlist_get_context(mut chatlist: *mut dc_chatlist_t) -> *mut dc_context_t { - if chatlist.is_null() || (*chatlist).magic != 0xc4a71157u32 { - return 0 as *mut dc_context_t; - } - return (*chatlist).context; + ret } diff --git a/src/dc_configure.rs b/src/dc_configure.rs index c13226f17..53a34e995 100644 --- a/src/dc_configure.rs +++ b/src/dc_configure.rs @@ -1,5 +1,3 @@ -use libc; - use crate::constants::Event; use crate::dc_context::dc_context_t; use crate::dc_e2ee::*; @@ -9,7 +7,6 @@ use crate::dc_log::*; use crate::dc_loginparam::*; use crate::dc_oauth2::*; use crate::dc_saxparser::*; -use crate::dc_smtp::*; use crate::dc_sqlite3::*; use crate::dc_strencode::*; use crate::dc_tools::*; @@ -58,7 +55,7 @@ pub struct outlk_autodiscover_t { pub redirect: *mut libc::c_char, } // connect -pub unsafe fn dc_configure(mut context: *mut dc_context_t) { +pub unsafe fn dc_configure(mut context: &dc_context_t) { if 0 != dc_has_ongoing(context) { dc_log_warning( context, @@ -71,23 +68,21 @@ pub unsafe fn dc_configure(mut context: *mut dc_context_t) { dc_job_kill_action(context, 900i32); dc_job_add(context, 900i32, 0i32, 0 as *const libc::c_char, 0i32); } -pub unsafe fn dc_has_ongoing(mut context: *mut dc_context_t) -> libc::c_int { - if context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint { - return 0i32; - } - return if 0 != (*context).ongoing_running || (*context).shall_stop_ongoing == 0i32 { - 1i32 +pub unsafe fn dc_has_ongoing(mut context: &dc_context_t) -> libc::c_int { + let s_a = context.running_state.clone(); + let s = s_a.read().unwrap(); + + if s.ongoing_running || !s.shall_stop_ongoing { + 1 } else { - 0i32 - }; -} -pub unsafe fn dc_is_configured(mut context: *const dc_context_t) -> libc::c_int { - if context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint { - return 0i32; + 0 } +} +pub unsafe fn dc_is_configured(mut context: &dc_context_t) -> libc::c_int { return if 0 != dc_sqlite3_get_config_int( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"configured\x00" as *const u8 as *const libc::c_char, 0i32, ) { @@ -96,17 +91,17 @@ pub unsafe fn dc_is_configured(mut context: *const dc_context_t) -> libc::c_int 0i32 }; } -pub unsafe fn dc_stop_ongoing_process(mut context: *mut dc_context_t) { - if context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint { - return; - } - if 0 != (*context).ongoing_running && (*context).shall_stop_ongoing == 0i32 { +pub unsafe fn dc_stop_ongoing_process(context: &dc_context_t) { + let s_a = context.running_state.clone(); + let mut s = s_a.write().unwrap(); + + if s.ongoing_running && !s.shall_stop_ongoing { dc_log_info( context, 0i32, b"Signaling the ongoing process to stop ASAP.\x00" as *const u8 as *const libc::c_char, ); - (*context).shall_stop_ongoing = 1i32 + s.shall_stop_ongoing = true; } else { dc_log_info( context, @@ -116,8 +111,8 @@ pub unsafe fn dc_stop_ongoing_process(mut context: *mut dc_context_t) { }; } // the other dc_job_do_DC_JOB_*() functions are declared static in the c-file -pub unsafe fn dc_job_do_DC_JOB_CONFIGURE_IMAP(context: *mut dc_context_t, _job: *mut dc_job_t) { - let mut flags: libc::c_int = 0; +pub unsafe fn dc_job_do_DC_JOB_CONFIGURE_IMAP(context: &dc_context_t, _job: *mut dc_job_t) { + let mut flags: libc::c_int; let mut current_block: u64; let mut success: libc::c_int = 0i32; let mut imap_connected_here: libc::c_int = 0i32; @@ -126,1162 +121,1135 @@ pub unsafe fn dc_job_do_DC_JOB_CONFIGURE_IMAP(context: *mut dc_context_t, _job: let mut mvbox_folder: *mut libc::c_char = 0 as *mut libc::c_char; let mut param: *mut dc_loginparam_t = 0 as *mut dc_loginparam_t; /* just a pointer inside param, must not be freed! */ - let mut param_domain: *mut libc::c_char = 0 as *mut libc::c_char; + let mut param_domain: *mut libc::c_char; let mut param_addr_urlencoded: *mut libc::c_char = 0 as *mut libc::c_char; let mut param_autoconfig: *mut dc_loginparam_t = 0 as *mut dc_loginparam_t; - if !(context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint) { - if !(0 == dc_alloc_ongoing(context)) { - ongoing_allocated_here = 1i32; - if 0 == dc_sqlite3_is_open((*context).sql) { - dc_log_error( + + if !(0 == dc_alloc_ongoing(context)) { + ongoing_allocated_here = 1i32; + if 0 == dc_sqlite3_is_open(&context.sql.clone().read().unwrap()) { + dc_log_error( + context, + 0i32, + b"Cannot configure, database not opened.\x00" as *const u8 as *const libc::c_char, + ); + } else { + context.inbox.read().unwrap().disconnect(context); + context + .sentbox_thread + .lock() + .unwrap() + .imap + .disconnect(context); + context + .mvbox_thread + .lock() + .unwrap() + .imap + .disconnect(context); + context.smtp.clone().lock().unwrap().disconnect(); + dc_log_info( + context, + 0i32, + b"Configure ...\x00" as *const u8 as *const libc::c_char, + ); + + let s_a = context.running_state.clone(); + let s = s_a.read().unwrap(); + + if !s.shall_stop_ongoing { + (context.cb)( context, - 0i32, - b"Cannot configure, database not opened.\x00" as *const u8 - as *const libc::c_char, - ); - } else { - dc_imap_disconnect((*context).inbox); - dc_imap_disconnect((*context).sentbox_thread.imap); - dc_imap_disconnect((*context).mvbox_thread.imap); - dc_smtp_disconnect((*context).smtp); - (*(*context).smtp).log_connect_errors = 1i32; - (*(*context).inbox).log_connect_errors = 1i32; - (*(*context).sentbox_thread.imap).log_connect_errors = 1i32; - (*(*context).mvbox_thread.imap).log_connect_errors = 1i32; - dc_log_info( - context, - 0i32, - b"Configure ...\x00" as *const u8 as *const libc::c_char, - ); - if !(0 != (*context).shall_stop_ongoing) { - ((*context).cb)( - context, - Event::CONFIGURE_PROGRESS, - (if 0i32 < 1i32 { - 1i32 - } else if 0i32 > 999i32 { - 999i32 - } else { - 0i32 - }) as uintptr_t, - 0i32 as uintptr_t, - ); - param = dc_loginparam_new(); - dc_loginparam_read( - param, - (*context).sql, - b"\x00" as *const u8 as *const libc::c_char, - ); - if (*param).addr.is_null() { - dc_log_error( - context, - 0i32, - b"Please enter the email address.\x00" as *const u8 - as *const libc::c_char, - ); + Event::CONFIGURE_PROGRESS, + (if 0i32 < 1i32 { + 1i32 + } else if 0i32 > 999i32 { + 999i32 } else { - dc_trim((*param).addr); - if 0 != (*param).server_flags & 0x2i32 { - // the used oauth2 addr may differ, check this. - // if dc_get_oauth2_addr() is not available in the oauth2 implementation, - // just use the given one. - if 0 != (*context).shall_stop_ongoing { + 0i32 + }) as uintptr_t, + 0i32 as uintptr_t, + ); + param = dc_loginparam_new(); + dc_loginparam_read( + context, + param, + &context.sql.clone().read().unwrap(), + b"\x00" as *const u8 as *const libc::c_char, + ); + + if (*param).addr.is_null() { + dc_log_error( + context, + 0i32, + b"Please enter the email address.\x00" as *const u8 as *const libc::c_char, + ); + } else { + dc_trim((*param).addr); + if 0 != (*param).server_flags & 0x2i32 { + // the used oauth2 addr may differ, check this. + // if dc_get_oauth2_addr() is not available in the oauth2 implementation, + // just use the given one. + if s.shall_stop_ongoing { + current_block = 2927484062889439186; + } else { + (context.cb)( + context, + Event::CONFIGURE_PROGRESS, + (if 10i32 < 1i32 { + 1i32 + } else if 10i32 > 999i32 { + 999i32 + } else { + 10i32 + }) as uintptr_t, + 0i32 as uintptr_t, + ); + let mut oauth2_addr: *mut libc::c_char = + dc_get_oauth2_addr(context, (*param).addr, (*param).mail_pw); + if !oauth2_addr.is_null() { + free((*param).addr as *mut libc::c_void); + (*param).addr = oauth2_addr; + dc_sqlite3_set_config( + context, + &context.sql.clone().read().unwrap(), + b"addr\x00" as *const u8 as *const libc::c_char, + (*param).addr, + ); + } + if s.shall_stop_ongoing { current_block = 2927484062889439186; } else { - ((*context).cb)( + (context.cb)( context, Event::CONFIGURE_PROGRESS, - (if 10i32 < 1i32 { + (if 20i32 < 1i32 { 1i32 - } else if 10i32 > 999i32 { + } else if 20i32 > 999i32 { 999i32 } else { - 10i32 + 20i32 }) as uintptr_t, 0i32 as uintptr_t, ); - let mut oauth2_addr: *mut libc::c_char = - dc_get_oauth2_addr(context, (*param).addr, (*param).mail_pw); - if !oauth2_addr.is_null() { - free((*param).addr as *mut libc::c_void); - (*param).addr = oauth2_addr; - dc_sqlite3_set_config( - (*context).sql, - b"addr\x00" as *const u8 as *const libc::c_char, - (*param).addr, - ); + current_block = 7746103178988627676; + } + } + } else { + current_block = 7746103178988627676; + } + match current_block { + 2927484062889439186 => {} + _ => { + param_domain = strchr((*param).addr, '@' as i32); + if param_domain.is_null() + || *param_domain.offset(0isize) as libc::c_int == 0i32 + { + dc_log_error( + context, + 0i32, + b"Bad email-address.\x00" as *const u8 as *const libc::c_char, + ); + } else { + param_domain = param_domain.offset(1isize); + param_addr_urlencoded = dc_urlencode((*param).addr); + if (*param).mail_pw.is_null() { + (*param).mail_pw = dc_strdup(0 as *const libc::c_char) } - if 0 != (*context).shall_stop_ongoing { - current_block = 2927484062889439186; - } else { - ((*context).cb)( + if !s.shall_stop_ongoing { + (context.cb)( context, Event::CONFIGURE_PROGRESS, - (if 20i32 < 1i32 { + (if 200i32 < 1i32 { 1i32 - } else if 20i32 > 999i32 { + } else if 200i32 > 999i32 { 999i32 } else { - 20i32 + 200i32 }) as uintptr_t, 0i32 as uintptr_t, ); - current_block = 7746103178988627676; - } - } - } else { - current_block = 7746103178988627676; - } - match current_block { - 2927484062889439186 => {} - _ => { - param_domain = strchr((*param).addr, '@' as i32); - if param_domain.is_null() - || *param_domain.offset(0isize) as libc::c_int == 0i32 - { - dc_log_error( - context, - 0i32, - b"Bad email-address.\x00" as *const u8 - as *const libc::c_char, - ); - } else { - param_domain = param_domain.offset(1isize); - param_addr_urlencoded = dc_urlencode((*param).addr); - if (*param).mail_pw.is_null() { - (*param).mail_pw = dc_strdup(0 as *const libc::c_char) - } - if !(0 != (*context).shall_stop_ongoing) { - ((*context).cb)( - context, - Event::CONFIGURE_PROGRESS, - (if 200i32 < 1i32 { - 1i32 - } else if 200i32 > 999i32 { - 999i32 - } else { - 200i32 - }) - as uintptr_t, - 0i32 as uintptr_t, - ); - /* 2. Autoconfig - **************************************************************************/ - if (*param).mail_server.is_null() - && (*param).mail_port == 0i32 - && (*param).send_server.is_null() - && (*param).send_port == 0i32 - && (*param).send_user.is_null() - && (*param).server_flags & !0x2i32 == 0i32 - { - /*&¶m->mail_user ==NULL -- the user can enter a loginname which is used by autoconfig then */ - /*&¶m->send_pw ==NULL -- the password cannot be auto-configured and is no criterion for autoconfig or not */ - /* flags but OAuth2 avoid autoconfig */ - let mut keep_flags: libc::c_int = - (*param).server_flags & 0x2i32; - /* A. Search configurations from the domain used in the email-address, prefer encrypted */ - if param_autoconfig.is_null() { - let mut url: - *mut libc::c_char = - dc_mprintf(b"https://autoconfig.%s/mail/config-v1.1.xml?emailaddress=%s\x00" - as - *const u8 - as - *const libc::c_char, - param_domain, - param_addr_urlencoded); - param_autoconfig = - moz_autoconfigure(context, url, param); - free(url as *mut libc::c_void); - if 0 != (*context).shall_stop_ongoing { - current_block = 2927484062889439186; - } else { - ((*context).cb)( - context, - Event::CONFIGURE_PROGRESS, - (if 300i32 < 1i32 { - 1i32 - } else if 300i32 > 999i32 { - 999i32 - } else { - 300i32 - }) - as uintptr_t, - 0i32 as uintptr_t, - ); - current_block = 13325891313334703151; - } + /* 2. Autoconfig + **************************************************************************/ + if (*param).mail_server.is_null() + && (*param).mail_port == 0i32 + && (*param).send_server.is_null() + && (*param).send_port == 0i32 + && (*param).send_user.is_null() + && (*param).server_flags & !0x2i32 == 0i32 + { + /*&¶m->mail_user ==NULL -- the user can enter a loginname which is used by autoconfig then */ + /*&¶m->send_pw ==NULL -- the password cannot be auto-configured and is no criterion for autoconfig or not */ + /* flags but OAuth2 avoid autoconfig */ + let mut keep_flags: libc::c_int = + (*param).server_flags & 0x2i32; + /* A. Search configurations from the domain used in the email-address, prefer encrypted */ + if param_autoconfig.is_null() { + let mut url: + *mut libc::c_char = + dc_mprintf(b"https://autoconfig.%s/mail/config-v1.1.xml?emailaddress=%s\x00" + as + *const u8 + as + *const libc::c_char, + param_domain, + param_addr_urlencoded); + param_autoconfig = + moz_autoconfigure(context, url, param); + free(url as *mut libc::c_void); + if s.shall_stop_ongoing { + current_block = 2927484062889439186; } else { + (context.cb)( + context, + Event::CONFIGURE_PROGRESS, + (if 300i32 < 1i32 { + 1i32 + } else if 300i32 > 999i32 { + 999i32 + } else { + 300i32 + }) + as uintptr_t, + 0i32 as uintptr_t, + ); current_block = 13325891313334703151; } - match current_block { - 2927484062889439186 => {} - _ => { - if param_autoconfig.is_null() { - // the doc does not mention `emailaddress=`, however, Thunderbird adds it, see https://releases.mozilla.org/pub/thunderbird/ , which makes some sense - let mut url_0: - *mut libc::c_char = - dc_mprintf(b"https://%s/.well-known/autoconfig/mail/config-v1.1.xml?emailaddress=%s\x00" - as - *const u8 - as - *const libc::c_char, - param_domain, - param_addr_urlencoded); - param_autoconfig = moz_autoconfigure( - context, url_0, param, - ); - free(url_0 as *mut libc::c_void); - if 0 != (*context).shall_stop_ongoing { - current_block = 2927484062889439186; - } else { - ((*context).cb)( - context, - Event::CONFIGURE_PROGRESS, - (if 310i32 < 1i32 { - 1i32 - } else if 310i32 > 999i32 { - 999i32 - } else { - 310i32 - }) - as uintptr_t, - 0i32 as uintptr_t, - ); - current_block = 5597585068398118923; - } - } else { - current_block = 5597585068398118923; - } - match current_block { - 2927484062889439186 => {} - _ => { - let mut i: libc::c_int = 0i32; - loop { - if !(i <= 1i32) { - current_block = - 12961834331865314435; - break; - } - if param_autoconfig.is_null() { - /* Outlook uses always SSL but different domains */ - let mut url_1: - *mut libc::c_char = - dc_mprintf(b"https://%s%s/autodiscover/autodiscover.xml\x00" - as - *const u8 - as - *const libc::c_char, - if i - == - 0i32 - { - b"\x00" - as - *const u8 - as - *const libc::c_char - } else { - b"autodiscover.\x00" - as - *const u8 - as - *const libc::c_char - }, - param_domain); - param_autoconfig = - outlk_autodiscover( - context, url_1, param, - ); - free( - url_1 as *mut libc::c_void, - ); - if 0 != (*context) - .shall_stop_ongoing - { - current_block = - 2927484062889439186; - break; - } - ((*context).cb)( - context, - Event::CONFIGURE_PROGRESS, - (if 320i32 + i * 10i32 - < 1i32 - { - 1i32 - } else if 320i32 + i * 10i32 - > 999i32 - { - 999i32 - } else { - 320i32 + i * 10i32 - }) - as uintptr_t, - 0i32 as uintptr_t, - ); - } - i += 1 - } - match current_block { - 2927484062889439186 => {} - _ => { - if param_autoconfig.is_null() { - let mut url_2: - *mut libc::c_char = - dc_mprintf(b"http://autoconfig.%s/mail/config-v1.1.xml?emailaddress=%s\x00" - as - *const u8 - as - *const libc::c_char, - param_domain, - param_addr_urlencoded); - param_autoconfig = - moz_autoconfigure( - context, url_2, - param, - ); - free(url_2 - as - *mut libc::c_void); - if 0 != (*context) - .shall_stop_ongoing - { - current_block = - 2927484062889439186; - } else { - ((*context).cb)( - context, - Event::CONFIGURE_PROGRESS, - (if 340i32 - < - 1i32 - { - 1i32 - } else if 340i32 - > - 999i32 - { - 999i32 - } else { - 340i32 - }) - as - uintptr_t, - 0i32 - as - uintptr_t - ); - current_block - = - 10778260831612459202; - } - } else { - current_block = - 10778260831612459202; - } - match current_block { - 2927484062889439186 => {} - _ => { - if param_autoconfig - .is_null() - { - // do not transfer the email-address unencrypted - let mut url_3: - *mut libc::c_char = - dc_mprintf(b"http://%s/.well-known/autoconfig/mail/config-v1.1.xml\x00" - as - *const u8 - as - *const libc::c_char, - param_domain); - param_autoconfig - = - moz_autoconfigure(context, - url_3, - param); - free(url_3 - as - *mut libc::c_void); - if 0 - != - (*context).shall_stop_ongoing - { - current_block - = - 2927484062889439186; - } else { - ((*context).cb)(context, - Event::CONFIGURE_PROGRESS, - (if 350i32 - < - 1i32 - { - 1i32 - } else if 350i32 - > - 999i32 - { - 999i32 - } else { - 350i32 - }) - as - uintptr_t, - 0i32 - as - uintptr_t); - current_block - = - 5207889489643863322; - } - } else { - current_block - = - 5207889489643863322; - } - match current_block - { - 2927484062889439186 - => - { - } - _ - => - { - /* B. If we have no configuration yet, search configuration in Thunderbird's centeral database */ - if param_autoconfig.is_null() - { - /* always SSL for Thunderbird's database */ - let mut url_4: - *mut libc::c_char = - dc_mprintf(b"https://autoconfig.thunderbird.net/v1.1/%s\x00" - as - *const u8 - as - *const libc::c_char, - param_domain); - param_autoconfig - = - moz_autoconfigure(context, - url_4, - param); - free(url_4 - as - *mut libc::c_void); - if 0 - != - (*context).shall_stop_ongoing - { - current_block - = - 2927484062889439186; - } else { - ((*context).cb)(context, - Event::CONFIGURE_PROGRESS, - (if 500i32 - < - 1i32 - { - 1i32 - } else if 500i32 - > - 999i32 - { - 999i32 - } else { - 500i32 - }) - as - uintptr_t, - 0i32 - as - uintptr_t); - current_block - = - 2798392256336243897; - } - } else { - current_block - = - 2798392256336243897; - } - match current_block - { - 2927484062889439186 - => - { - } - _ - => - { - if !param_autoconfig.is_null() - { - let mut r: - *mut libc::c_char = - dc_loginparam_get_readable(param_autoconfig); - dc_log_info(context, - 0i32, - b"Got autoconfig: %s\x00" - as - *const u8 - as - *const libc::c_char, - r); - free(r - as - *mut libc::c_void); - if !(*param_autoconfig).mail_user.is_null() - { - free((*param).mail_user - as - *mut libc::c_void); - (*param).mail_user - = - dc_strdup_keep_null((*param_autoconfig).mail_user) - } - (*param).mail_server - = - dc_strdup_keep_null((*param_autoconfig).mail_server); - (*param).mail_port - = - (*param_autoconfig).mail_port; - (*param).send_server - = - dc_strdup_keep_null((*param_autoconfig).send_server); - (*param).send_port - = - (*param_autoconfig).send_port; - (*param).send_user - = - dc_strdup_keep_null((*param_autoconfig).send_user); - (*param).server_flags - = - (*param_autoconfig).server_flags - } - (*param).server_flags - |= - keep_flags; - current_block - = - 3024367268842933116; - } - } - } - } - } - } - } - } - } - } - } - } } else { - current_block = 3024367268842933116; + current_block = 13325891313334703151; } match current_block { 2927484062889439186 => {} _ => { - if (*param).mail_server.is_null() { - (*param).mail_server = dc_mprintf( - b"imap.%s\x00" as *const u8 - as *const libc::c_char, - param_domain, - ) - } - if (*param).mail_port == 0i32 { - (*param).mail_port = if 0 - != (*param).server_flags - & (0x100i32 | 0x400i32) - { - 143i32 + if param_autoconfig.is_null() { + // the doc does not mention `emailaddress=`, however, Thunderbird adds it, see https://releases.mozilla.org/pub/thunderbird/ , which makes some sense + let mut url_0: + *mut libc::c_char = + dc_mprintf(b"https://%s/.well-known/autoconfig/mail/config-v1.1.xml?emailaddress=%s\x00" + as + *const u8 + as + *const libc::c_char, + param_domain, + param_addr_urlencoded); + param_autoconfig = + moz_autoconfigure(context, url_0, param); + free(url_0 as *mut libc::c_void); + if s.shall_stop_ongoing { + current_block = 2927484062889439186; } else { - 993i32 - } - } - if (*param).mail_user.is_null() { - (*param).mail_user = dc_strdup((*param).addr) - } - if (*param).send_server.is_null() - && !(*param).mail_server.is_null() - { - (*param).send_server = - dc_strdup((*param).mail_server); - if strncmp( - (*param).send_server, - b"imap.\x00" as *const u8 - as *const libc::c_char, - 5, - ) == 0i32 - { - memcpy( - (*param).send_server - as *mut libc::c_void, - b"smtp\x00" as *const u8 - as *const libc::c_char - as *const libc::c_void, - 4, - ); - } - } - if (*param).send_port == 0i32 { - (*param).send_port = - if 0 != (*param).server_flags & 0x10000i32 { - 587i32 - } else if 0 - != (*param).server_flags & 0x40000i32 - { - 25i32 - } else { - 465i32 - } - } - if (*param).send_user.is_null() - && !(*param).mail_user.is_null() - { - (*param).send_user = - dc_strdup((*param).mail_user) - } - if (*param).send_pw.is_null() - && !(*param).mail_pw.is_null() - { - (*param).send_pw = dc_strdup((*param).mail_pw) - } - if 0 == dc_exactly_one_bit_set( - (*param).server_flags & (0x2i32 | 0x4i32), - ) { - (*param).server_flags &= !(0x2i32 | 0x4i32); - (*param).server_flags |= 0x4i32 - } - if 0 == dc_exactly_one_bit_set( - (*param).server_flags - & (0x100i32 | 0x200i32 | 0x400i32), - ) { - (*param).server_flags &= - !(0x100i32 | 0x200i32 | 0x400i32); - (*param).server_flags |= - if (*param).send_port == 143i32 { - 0x100i32 - } else { - 0x200i32 - } - } - if 0 == dc_exactly_one_bit_set( - (*param).server_flags - & (0x10000i32 | 0x20000i32 | 0x40000i32), - ) { - (*param).server_flags &= - !(0x10000i32 | 0x20000i32 | 0x40000i32); - (*param).server_flags |= - if (*param).send_port == 587i32 { - 0x10000i32 - } else if (*param).send_port == 25i32 { - 0x40000i32 - } else { - 0x20000i32 - } - } - /* do we have a complete configuration? */ - if (*param).addr.is_null() - || (*param).mail_server.is_null() - || (*param).mail_port == 0i32 - || (*param).mail_user.is_null() - || (*param).mail_pw.is_null() - || (*param).send_server.is_null() - || (*param).send_port == 0i32 - || (*param).send_user.is_null() - || (*param).send_pw.is_null() - || (*param).server_flags == 0i32 - { - dc_log_error( - context, - 0i32, - b"Account settings incomplete.\x00" - as *const u8 - as *const libc::c_char, - ); - } else if !(0 != (*context).shall_stop_ongoing) { - ((*context).cb)( - context, - Event::CONFIGURE_PROGRESS, - (if 600i32 < 1i32 { - 1i32 - } else if 600i32 > 999i32 { - 999i32 - } else { - 600i32 - }) - as uintptr_t, - 0i32 as uintptr_t, - ); - /* try to connect to IMAP - if we did not got an autoconfig, - do some further tries with different settings and username variations */ - let mut username_variation: libc::c_int = 0i32; - loop { - if !(username_variation <= 1i32) { - current_block = 14187386403465544025; - break; - } - let mut r_0: *mut libc::c_char = - dc_loginparam_get_readable(param); - dc_log_info( - context, - 0i32, - b"Trying: %s\x00" as *const u8 - as *const libc::c_char, - r_0, - ); - free(r_0 as *mut libc::c_void); - if 0 != dc_imap_connect( - (*context).inbox, - param, - ) { - current_block = 14187386403465544025; - break; - } - if !param_autoconfig.is_null() { - current_block = 2927484062889439186; - break; - } - // probe STARTTLS/993 - if 0 != (*context).shall_stop_ongoing { - current_block = 2927484062889439186; - break; - } - ((*context).cb)( + (context.cb)( context, Event::CONFIGURE_PROGRESS, - (if 650i32 + username_variation * 30i32 - < 1i32 - { + (if 310i32 < 1i32 { 1i32 - } else if 650i32 - + username_variation * 30i32 - > 999i32 - { + } else if 310i32 > 999i32 { 999i32 } else { - 650i32 + username_variation * 30i32 + 310i32 }) as uintptr_t, 0i32 as uintptr_t, ); - (*param).server_flags &= - !(0x100i32 | 0x200i32 | 0x400i32); - (*param).server_flags |= 0x100i32; - let mut r_1: *mut libc::c_char = - dc_loginparam_get_readable(param); - dc_log_info( - context, - 0i32, - b"Trying: %s\x00" as *const u8 - as *const libc::c_char, - r_1, - ); - free(r_1 as *mut libc::c_void); - if 0 != dc_imap_connect( - (*context).inbox, - param, - ) { - current_block = 14187386403465544025; - break; - } - // probe STARTTLS/143 - if 0 != (*context).shall_stop_ongoing { - current_block = 2927484062889439186; - break; - } - ((*context).cb)( - context, - Event::CONFIGURE_PROGRESS, - (if 660i32 + username_variation * 30i32 - < 1i32 - { - 1i32 - } else if 660i32 - + username_variation * 30i32 - > 999i32 - { - 999i32 - } else { - 660i32 + username_variation * 30i32 - }) - as uintptr_t, - 0i32 as uintptr_t, - ); - (*param).mail_port = 143i32; - let mut r_2: *mut libc::c_char = - dc_loginparam_get_readable(param); - dc_log_info( - context, - 0i32, - b"Trying: %s\x00" as *const u8 - as *const libc::c_char, - r_2, - ); - free(r_2 as *mut libc::c_void); - if 0 != dc_imap_connect( - (*context).inbox, - param, - ) { - current_block = 14187386403465544025; - break; - } - if 0 != username_variation { - current_block = 2927484062889439186; - break; - } - // next probe round with only the localpart of the email-address as the loginname - if 0 != (*context).shall_stop_ongoing { - current_block = 2927484062889439186; - break; - } - ((*context).cb)( - context, - Event::CONFIGURE_PROGRESS, - (if 670i32 + username_variation * 30i32 - < 1i32 - { - 1i32 - } else if 670i32 - + username_variation * 30i32 - > 999i32 - { - 999i32 - } else { - 670i32 + username_variation * 30i32 - }) - as uintptr_t, - 0i32 as uintptr_t, - ); - (*param).server_flags &= - !(0x100i32 | 0x200i32 | 0x400i32); - (*param).server_flags |= 0x200i32; - (*param).mail_port = 993i32; - let mut at: *mut libc::c_char = - strchr((*param).mail_user, '@' as i32); - if !at.is_null() { - *at = 0i32 as libc::c_char - } - at = strchr((*param).send_user, '@' as i32); - if !at.is_null() { - *at = 0i32 as libc::c_char - } - username_variation += 1 + current_block = 5597585068398118923; } - match current_block { - 2927484062889439186 => {} - _ => { - imap_connected_here = 1i32; - if !(0 != (*context).shall_stop_ongoing) - { - ((*context).cb)( + } else { + current_block = 5597585068398118923; + } + match current_block { + 2927484062889439186 => {} + _ => { + let mut i: libc::c_int = 0i32; + loop { + if !(i <= 1i32) { + current_block = + 12961834331865314435; + break; + } + if param_autoconfig.is_null() { + /* Outlook uses always SSL but different domains */ + let mut url_1: + *mut libc::c_char = + dc_mprintf(b"https://%s%s/autodiscover/autodiscover.xml\x00" + as + *const u8 + as + *const libc::c_char, + if i + == + 0i32 + { + b"\x00" + as + *const u8 + as + *const libc::c_char + } else { + b"autodiscover.\x00" + as + *const u8 + as + *const libc::c_char + }, + param_domain); + param_autoconfig = + outlk_autodiscover( + context, url_1, param, + ); + free(url_1 as *mut libc::c_void); + if s.shall_stop_ongoing { + current_block = + 2927484062889439186; + break; + } + (context.cb)( context, Event::CONFIGURE_PROGRESS, - (if 800i32 < 1i32 { + (if 320i32 + i * 10i32 < 1i32 { 1i32 - } else if 800i32 > 999i32 { + } else if 320i32 + i * 10i32 + > 999i32 + { 999i32 } else { - 800i32 + 320i32 + i * 10i32 }) as uintptr_t, 0i32 as uintptr_t, ); - /* try to connect to SMTP - if we did not got an autoconfig, the first try was SSL-465 and we do a second try with STARTTLS-587 */ - if 0 == dc_smtp_connect( - (*context).smtp, - param, - ) { - if !param_autoconfig.is_null() { - current_block = - 2927484062889439186; - } else if 0 - != (*context) - .shall_stop_ongoing - { + } + i += 1 + } + match current_block { + 2927484062889439186 => {} + _ => { + if param_autoconfig.is_null() { + let mut url_2: + *mut libc::c_char = + dc_mprintf(b"http://autoconfig.%s/mail/config-v1.1.xml?emailaddress=%s\x00" + as + *const u8 + as + *const libc::c_char, + param_domain, + param_addr_urlencoded); + param_autoconfig = + moz_autoconfigure( + context, url_2, param, + ); + free( + url_2 as *mut libc::c_void, + ); + + if s.shall_stop_ongoing { current_block = 2927484062889439186; } else { - ((*context).cb)(context, - Event::CONFIGURE_PROGRESS, - (if 850i32 - < - 1i32 - { - 1i32 - } else if 850i32 - > - 999i32 - { - 999i32 - } else { - 850i32 - }) - as - uintptr_t, - 0i32 - as - uintptr_t); - (*param).server_flags &= - !(0x10000i32 - | 0x20000i32 - | 0x40000i32); - (*param).server_flags |= - 0x10000i32; - (*param).send_port = 587i32; - let mut r_3: - *mut libc::c_char = - dc_loginparam_get_readable(param); - dc_log_info(context, - 0i32, - b"Trying: %s\x00" - as - *const u8 - as - *const libc::c_char, - r_3); - free(r_3 - as - *mut libc::c_void); - if 0 == dc_smtp_connect( - (*context).smtp, - param, - ) { - if 0 != (*context) - .shall_stop_ongoing + (context.cb)( + context, + Event::CONFIGURE_PROGRESS, + (if 340i32 + < + 1i32 + { + 1i32 + } else if 340i32 + > + 999i32 + { + 999i32 + } else { + 340i32 + }) + as + uintptr_t, + 0i32 + as + uintptr_t + ); + current_block = + 10778260831612459202; + } + } else { + current_block = + 10778260831612459202; + } + match current_block { + 2927484062889439186 => {} + _ => { + if param_autoconfig + .is_null() + { + // do not transfer the email-address unencrypted + let mut url_3: + *mut libc::c_char = + dc_mprintf(b"http://%s/.well-known/autoconfig/mail/config-v1.1.xml\x00" + as + *const u8 + as + *const libc::c_char, + param_domain); + param_autoconfig = + moz_autoconfigure( + context, url_3, + param, + ); + free(url_3 + as + *mut libc::c_void); + if s.shall_stop_ongoing { current_block = 2927484062889439186; } else { - ((*context).cb)(context, - Event::CONFIGURE_PROGRESS, - (if 860i32 - < - 1i32 - { - 1i32 - } else if 860i32 - > - 999i32 - { - 999i32 - } else { - 860i32 - }) - as - uintptr_t, - 0i32 - as - uintptr_t); - (*param).server_flags - &= - !(0x10000i32 - | - 0x20000i32 - | - 0x40000i32); - (*param).server_flags - |= - 0x10000i32; - (*param) - .send_port = - 25i32; - let mut r_4: - *mut libc::c_char = - dc_loginparam_get_readable(param); - dc_log_info(context, - 0i32, - b"Trying: %s\x00" - as - *const u8 - as - *const libc::c_char, - r_4); - free(r_4 - as - *mut libc::c_void); - if 0 - == - dc_smtp_connect((*context).smtp, - param) - { - current_block - = - 2927484062889439186; - } else { - current_block - = - 5083741289379115417; - } + (context.cb)(context, + Event::CONFIGURE_PROGRESS, + (if 350i32 + < + 1i32 + { + 1i32 + } else if 350i32 + > + 999i32 + { + 999i32 + } else { + 350i32 + }) + as + uintptr_t, + 0i32 + as + uintptr_t); + current_block + = + 5207889489643863322; } } else { current_block = - 5083741289379115417; + 5207889489643863322; + } + match current_block { + 2927484062889439186 => { + } + _ => { + /* B. If we have no configuration yet, search configuration in Thunderbird's centeral database */ + if param_autoconfig + .is_null() + { + /* always SSL for Thunderbird's database */ + let mut url_4: + *mut libc::c_char = + dc_mprintf(b"https://autoconfig.thunderbird.net/v1.1/%s\x00" + as + *const u8 + as + *const libc::c_char, + param_domain); + param_autoconfig + = + moz_autoconfigure(context, + url_4, + param); + free(url_4 + as + *mut libc::c_void); + if s.shall_stop_ongoing + { + current_block + = + 2927484062889439186; + } else { + (context.cb)(context, + Event::CONFIGURE_PROGRESS, + (if 500i32 + < + 1i32 + { + 1i32 + } else if 500i32 + > + 999i32 + { + 999i32 + } else { + 500i32 + }) + as + uintptr_t, + 0i32 + as + uintptr_t); + current_block + = + 2798392256336243897; + } + } else { + current_block + = + 2798392256336243897; + } + match current_block + { + 2927484062889439186 + => + { + } + _ + => + { + if !param_autoconfig.is_null() + { + let mut r: + *mut libc::c_char = + dc_loginparam_get_readable(param_autoconfig); + dc_log_info(context, + 0i32, + b"Got autoconfig: %s\x00" + as + *const u8 + as + *const libc::c_char, + r); + free(r + as + *mut libc::c_void); + if !(*param_autoconfig).mail_user.is_null() + { + free((*param).mail_user + as + *mut libc::c_void); + (*param).mail_user + = + dc_strdup_keep_null((*param_autoconfig).mail_user) + } + (*param).mail_server + = + dc_strdup_keep_null((*param_autoconfig).mail_server); + (*param).mail_port + = + (*param_autoconfig).mail_port; + (*param).send_server + = + dc_strdup_keep_null((*param_autoconfig).send_server); + (*param).send_port + = + (*param_autoconfig).send_port; + (*param).send_user + = + dc_strdup_keep_null((*param_autoconfig).send_user); + (*param).server_flags + = + (*param_autoconfig).server_flags + } + (*param).server_flags + |= + keep_flags; + current_block + = + 3024367268842933116; + } + } + } } } - } else { - current_block = - 5083741289379115417; } - match current_block { - 2927484062889439186 => {} - _ => { - smtp_connected_here = 1i32; - if !(0 - != (*context) - .shall_stop_ongoing) - { - ((*context).cb)(context, - Event::CONFIGURE_PROGRESS, - (if 900i32 - < - 1i32 - { - 1i32 - } else if 900i32 - > - 999i32 - { - 999i32 - } else { - 900i32 - }) - as - uintptr_t, - 0i32 - as - uintptr_t); - flags - = - if 0 - != - dc_sqlite3_get_config_int((*context).sql, - b"mvbox_watch\x00" - as - *const u8 - as - *const libc::c_char, - 1i32) - || - 0 - != - dc_sqlite3_get_config_int((*context).sql, - b"mvbox_move\x00" - as - *const u8 - as - *const libc::c_char, - 1i32) + } + } + } + } + } + } + } else { + current_block = 3024367268842933116; + } + match current_block { + 2927484062889439186 => {} + _ => { + if (*param).mail_server.is_null() { + (*param).mail_server = dc_mprintf( + b"imap.%s\x00" as *const u8 + as *const libc::c_char, + param_domain, + ) + } + if (*param).mail_port == 0i32 { + (*param).mail_port = if 0 + != (*param).server_flags & (0x100i32 | 0x400i32) + { + 143i32 + } else { + 993i32 + } + } + if (*param).mail_user.is_null() { + (*param).mail_user = dc_strdup((*param).addr) + } + if (*param).send_server.is_null() + && !(*param).mail_server.is_null() + { + (*param).send_server = + dc_strdup((*param).mail_server); + if strncmp( + (*param).send_server, + b"imap.\x00" as *const u8 + as *const libc::c_char, + 5, + ) == 0i32 + { + memcpy( + (*param).send_server as *mut libc::c_void, + b"smtp\x00" as *const u8 + as *const libc::c_char + as *const libc::c_void, + 4, + ); + } + } + if (*param).send_port == 0i32 { + (*param).send_port = if 0 + != (*param).server_flags & 0x10000i32 + { + 587i32 + } else if 0 != (*param).server_flags & 0x40000i32 { + 25i32 + } else { + 465i32 + } + } + if (*param).send_user.is_null() + && !(*param).mail_user.is_null() + { + (*param).send_user = dc_strdup((*param).mail_user) + } + if (*param).send_pw.is_null() + && !(*param).mail_pw.is_null() + { + (*param).send_pw = dc_strdup((*param).mail_pw) + } + if 0 == dc_exactly_one_bit_set( + (*param).server_flags & (0x2i32 | 0x4i32), + ) { + (*param).server_flags &= !(0x2i32 | 0x4i32); + (*param).server_flags |= 0x4i32 + } + if 0 == dc_exactly_one_bit_set( + (*param).server_flags + & (0x100i32 | 0x200i32 | 0x400i32), + ) { + (*param).server_flags &= + !(0x100i32 | 0x200i32 | 0x400i32); + (*param).server_flags |= + if (*param).send_port == 143i32 { + 0x100i32 + } else { + 0x200i32 + } + } + if 0 == dc_exactly_one_bit_set( + (*param).server_flags + & (0x10000i32 | 0x20000i32 | 0x40000i32), + ) { + (*param).server_flags &= + !(0x10000i32 | 0x20000i32 | 0x40000i32); + (*param).server_flags |= + if (*param).send_port == 587i32 { + 0x10000i32 + } else if (*param).send_port == 25i32 { + 0x40000i32 + } else { + 0x20000i32 + } + } + /* do we have a complete configuration? */ + if (*param).addr.is_null() + || (*param).mail_server.is_null() + || (*param).mail_port == 0i32 + || (*param).mail_user.is_null() + || (*param).mail_pw.is_null() + || (*param).send_server.is_null() + || (*param).send_port == 0i32 + || (*param).send_user.is_null() + || (*param).send_pw.is_null() + || (*param).server_flags == 0i32 + { + dc_log_error( + context, + 0i32, + b"Account settings incomplete.\x00" as *const u8 + as *const libc::c_char, + ); + } else if !s.shall_stop_ongoing { + (context.cb)( + context, + Event::CONFIGURE_PROGRESS, + (if 600i32 < 1i32 { + 1i32 + } else if 600i32 > 999i32 { + 999i32 + } else { + 600i32 + }) + as uintptr_t, + 0i32 as uintptr_t, + ); + /* try to connect to IMAP - if we did not got an autoconfig, + do some further tries with different settings and username variations */ + let mut username_variation: libc::c_int = 0i32; + loop { + if !(username_variation <= 1i32) { + current_block = 14187386403465544025; + break; + } + let mut r_0: *mut libc::c_char = + dc_loginparam_get_readable(param); + dc_log_info( + context, + 0i32, + b"Trying: %s\x00" as *const u8 + as *const libc::c_char, + r_0, + ); + free(r_0 as *mut libc::c_void); + if 0 != context + .inbox + .read() + .unwrap() + .connect(context, param) + { + current_block = 14187386403465544025; + break; + } + if !param_autoconfig.is_null() { + current_block = 2927484062889439186; + break; + } + // probe STARTTLS/993 + if s.shall_stop_ongoing { + current_block = 2927484062889439186; + break; + } + (context.cb)( + context, + Event::CONFIGURE_PROGRESS, + (if 650i32 + username_variation * 30i32 + < 1i32 + { + 1i32 + } else if 650i32 + + username_variation * 30i32 + > 999i32 + { + 999i32 + } else { + 650i32 + username_variation * 30i32 + }) + as uintptr_t, + 0i32 as uintptr_t, + ); + (*param).server_flags &= + !(0x100i32 | 0x200i32 | 0x400i32); + (*param).server_flags |= 0x100i32; + let mut r_1: *mut libc::c_char = + dc_loginparam_get_readable(param); + dc_log_info( + context, + 0i32, + b"Trying: %s\x00" as *const u8 + as *const libc::c_char, + r_1, + ); + free(r_1 as *mut libc::c_void); + if 0 != context + .inbox + .read() + .unwrap() + .connect(context, param) + { + current_block = 14187386403465544025; + break; + } + // probe STARTTLS/143 + if s.shall_stop_ongoing { + current_block = 2927484062889439186; + break; + } + (context.cb)( + context, + Event::CONFIGURE_PROGRESS, + (if 660i32 + username_variation * 30i32 + < 1i32 + { + 1i32 + } else if 660i32 + + username_variation * 30i32 + > 999i32 + { + 999i32 + } else { + 660i32 + username_variation * 30i32 + }) + as uintptr_t, + 0i32 as uintptr_t, + ); + (*param).mail_port = 143i32; + let mut r_2: *mut libc::c_char = + dc_loginparam_get_readable(param); + dc_log_info( + context, + 0i32, + b"Trying: %s\x00" as *const u8 + as *const libc::c_char, + r_2, + ); + free(r_2 as *mut libc::c_void); + if 0 != context + .inbox + .read() + .unwrap() + .connect(context, param) + { + current_block = 14187386403465544025; + break; + } + if 0 != username_variation { + current_block = 2927484062889439186; + break; + } + // next probe round with only the localpart of the email-address as the loginname + if s.shall_stop_ongoing { + current_block = 2927484062889439186; + break; + } + (context.cb)( + context, + Event::CONFIGURE_PROGRESS, + (if 670i32 + username_variation * 30i32 + < 1i32 + { + 1i32 + } else if 670i32 + + username_variation * 30i32 + > 999i32 + { + 999i32 + } else { + 670i32 + username_variation * 30i32 + }) + as uintptr_t, + 0i32 as uintptr_t, + ); + (*param).server_flags &= + !(0x100i32 | 0x200i32 | 0x400i32); + (*param).server_flags |= 0x200i32; + (*param).mail_port = 993i32; + let mut at: *mut libc::c_char = + strchr((*param).mail_user, '@' as i32); + if !at.is_null() { + *at = 0i32 as libc::c_char + } + at = strchr((*param).send_user, '@' as i32); + if !at.is_null() { + *at = 0i32 as libc::c_char + } + username_variation += 1 + } + match current_block { + 2927484062889439186 => {} + _ => { + imap_connected_here = 1i32; + if !s.shall_stop_ongoing { + (context.cb)( + context, + Event::CONFIGURE_PROGRESS, + (if 800i32 < 1i32 { + 1i32 + } else if 800i32 > 999i32 { + 999i32 + } else { + 800i32 + }) + as uintptr_t, + 0i32 as uintptr_t, + ); + /* try to connect to SMTP - if we did not got an autoconfig, the first try was SSL-465 and we do a second try with STARTTLS-587 */ + if 0 == context + .smtp + .clone() + .lock() + .unwrap() + .connect(context, param) + { + if !param_autoconfig.is_null() { + current_block = + 2927484062889439186; + } else if s.shall_stop_ongoing { + current_block = + 2927484062889439186; + } else { + (context.cb)( + context, + Event::CONFIGURE_PROGRESS, + (if 850i32 < 1i32 { + 1i32 + } else if 850i32 > 999i32 { + 999i32 + } else { + 850i32 + }) + as uintptr_t, + 0i32 as uintptr_t, + ); + (*param).server_flags &= + !(0x10000i32 + | 0x20000i32 + | 0x40000i32); + (*param).server_flags |= + 0x10000i32; + (*param).send_port = 587i32; + let mut r_3: *mut libc::c_char = + dc_loginparam_get_readable( + param, + ); + dc_log_info( + context, + 0i32, + b"Trying: %s\x00" + as *const u8 + as *const libc::c_char, + r_3, + ); + free(r_3 as *mut libc::c_void); + if 0 == context + .smtp + .clone() + .lock() + .unwrap() + .connect(context, param) + { + if s.shall_stop_ongoing { + current_block = + 2927484062889439186; + } else { + (context.cb)(context, + Event::CONFIGURE_PROGRESS, + (if 860i32 + < + 1i32 + { + 1i32 + } else if 860i32 + > + 999i32 + { + 999i32 + } else { + 860i32 + }) + as + uintptr_t, + 0i32 + as + uintptr_t); + (*param) + .server_flags &= + !(0x10000i32 + | 0x20000i32 + | 0x40000i32); + (*param) + .server_flags |= + 0x10000i32; + (*param).send_port = + 25i32; + let mut r_4: + *mut libc::c_char = + dc_loginparam_get_readable(param); + dc_log_info(context, + 0i32, + b"Trying: %s\x00" + as + *const u8 + as + *const libc::c_char, + r_4); + free(r_4 + as + *mut libc::c_void); + if 0 == context + .smtp + .clone() + .lock() + .unwrap() + .connect( + context, param, + ) { - 0x1i32 + current_block + = + 2927484062889439186; } else { - 0i32 - }; - dc_configure_folders( - context, - (*context).inbox, - flags, + current_block + = + 5083741289379115417; + } + } + } else { + current_block = + 5083741289379115417; + } + } + } else { + current_block = 5083741289379115417; + } + match current_block { + 2927484062889439186 => {} + _ => { + smtp_connected_here = 1i32; + if !s.shall_stop_ongoing { + (context.cb)(context, + Event::CONFIGURE_PROGRESS, + (if 900i32 + < + 1i32 + { + 1i32 + } else if 900i32 + > + 999i32 + { + 999i32 + } else { + 900i32 + }) + as + uintptr_t, + 0i32 + as + uintptr_t); + flags + = + if 0 + != + dc_sqlite3_get_config_int(context, &context.sql.clone().read().unwrap(), + b"mvbox_watch\x00" + as + *const u8 + as + *const libc::c_char, + 1i32) + || + 0 + != + dc_sqlite3_get_config_int(context, &context.sql.clone().read().unwrap(), + b"mvbox_move\x00" + as + *const u8 + as + *const libc::c_char, + 1i32) + { + 0x1i32 + } else { + 0i32 + }; + + context + .inbox + .read() + .unwrap() + .configure_folders( + context, flags, ); - if !(0 != (*context) - .shall_stop_ongoing) - { - ((*context).cb)(context, - Event::CONFIGURE_PROGRESS, - (if 910i32 - < - 1i32 - { - 1i32 - } else if 910i32 - > - 999i32 - { - 999i32 - } else { - 910i32 - }) - as - uintptr_t, - 0i32 - as - uintptr_t); - dc_loginparam_write(param, - (*context).sql, - b"configured_\x00" - as - *const u8 - as - *const libc::c_char); - dc_sqlite3_set_config_int((*context).sql, - b"configured\x00" - as - *const u8 - as - *const libc::c_char, - 1i32); - if !(0 - != - (*context).shall_stop_ongoing) - { - ((*context).cb)(context, - Event::CONFIGURE_PROGRESS, - (if 920i32 - < - 1i32 - { - 1i32 - } else if 920i32 - > - 999i32 - { - 999i32 - } else { - 920i32 - }) - as - uintptr_t, - 0i32 - as - uintptr_t); - dc_ensure_secret_key_exists(context); - success - = - 1i32; - dc_log_info(context, - 0i32, - b"Configure completed.\x00" + if !s.shall_stop_ongoing { + (context.cb)(context, + Event::CONFIGURE_PROGRESS, + (if 910i32 + < + 1i32 + { + 1i32 + } else if 910i32 + > + 999i32 + { + 999i32 + } else { + 910i32 + }) + as + uintptr_t, + 0i32 + as + uintptr_t); + dc_loginparam_write(context, param, + &context.sql.clone().read().unwrap(), + b"configured_\x00" as *const u8 as *const libc::c_char); - if !(0 - != - (*context).shall_stop_ongoing) - { - ((*context).cb)(context, - Event::CONFIGURE_PROGRESS, - (if 940i32 - < - 1i32 - { - 1i32 - } else if 940i32 - > - 999i32 - { - 999i32 - } else { - 940i32 - }) - as - uintptr_t, - 0i32 - as - uintptr_t); - } + dc_sqlite3_set_config_int(context, &context.sql.clone().read().unwrap(), + b"configured\x00" + as + *const u8 + as + *const libc::c_char, + 1i32); + if !s.shall_stop_ongoing + { + (context.cb)(context, + Event::CONFIGURE_PROGRESS, + (if 920i32 + < + 1i32 + { + 1i32 + } else if 920i32 + > + 999i32 + { + 999i32 + } else { + 920i32 + }) + as + uintptr_t, + 0i32 + as + uintptr_t); + dc_ensure_secret_key_exists(context); + success = 1i32; + dc_log_info(context, + 0i32, + b"Configure completed.\x00" + as + *const u8 + as + *const libc::c_char); + if !s.shall_stop_ongoing + { + (context.cb)(context, + Event::CONFIGURE_PROGRESS, + (if 940i32 + < + 1i32 + { + 1i32 + } else if 940i32 + > + 999i32 + { + 999i32 + } else { + 940i32 + }) + as + uintptr_t, + 0i32 + as + uintptr_t); } } } @@ -1302,11 +1270,12 @@ pub unsafe fn dc_job_do_DC_JOB_CONFIGURE_IMAP(context: *mut dc_context_t, _job: } } } + if 0 != imap_connected_here { - dc_imap_disconnect((*context).inbox); + context.inbox.read().unwrap().disconnect(context); } if 0 != smtp_connected_here { - dc_smtp_disconnect((*context).smtp); + context.smtp.clone().lock().unwrap().disconnect(); } dc_loginparam_unref(param); dc_loginparam_unref(param_autoconfig); @@ -1315,7 +1284,7 @@ pub unsafe fn dc_job_do_DC_JOB_CONFIGURE_IMAP(context: *mut dc_context_t, _job: dc_free_ongoing(context); } free(mvbox_folder as *mut libc::c_void); - ((*context).cb)( + (context.cb)( context, Event::CONFIGURE_PROGRESS, (if 0 != success { 1000i32 } else { 0i32 }) as uintptr_t, @@ -1323,329 +1292,22 @@ pub unsafe fn dc_job_do_DC_JOB_CONFIGURE_IMAP(context: *mut dc_context_t, _job: ); } -pub unsafe fn dc_free_ongoing(mut context: *mut dc_context_t) { - if context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint { - return; - } - (*context).ongoing_running = 0i32; - (*context).shall_stop_ongoing = 1i32; -} -pub unsafe fn dc_configure_folders( - mut context: *mut dc_context_t, - mut imap: *mut dc_imap_t, - mut 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.is_null() || (*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(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(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(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).sql, - b"folders_configured\x00" as *const u8 as *const libc::c_char, - 3i32, - ); - dc_sqlite3_set_config( - (*context).sql, - b"configured_mvbox_folder\x00" as *const u8 as *const libc::c_char, - mvbox_folder, - ); - dc_sqlite3_set_config( - (*context).sql, - 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; - iter1 = (*folders).first; - while !iter1.is_null() { - let mut ret_folder: *mut dc_imapfolder_t = (if !iter1.is_null() { - (*iter1).data - } else { - 0 as *mut libc::c_void - }) as *mut dc_imapfolder_t; - free((*ret_folder).name_to_select as *mut libc::c_void); - free((*ret_folder).name_utf8 as *mut libc::c_void); - free(ret_folder as *mut libc::c_void); - iter1 = if !iter1.is_null() { - (*iter1).next - } else { - 0 as *mut clistcell_s - } - } - clist_free(folders); - }; -} -unsafe fn list_folders(mut 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.is_null() || (*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(imap, r) || imap_list.is_null() { - imap_list = 0 as *mut clist; - dc_log_warning( - (*imap).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( - (*imap).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; +pub unsafe fn dc_free_ongoing(context: &dc_context_t) { + let s_a = context.running_state.clone(); + let mut s = s_a.write().unwrap(); + + s.ongoing_running = false; + s.shall_stop_ongoing = true; } + unsafe fn moz_autoconfigure( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut url: *const libc::c_char, mut param_in: *const dc_loginparam_t, ) -> *mut dc_loginparam_t { - let mut p: *mut libc::c_char = 0 as *mut libc::c_char; - let mut saxparser: dc_saxparser_t = dc_saxparser_t { - starttag_cb: None, - endtag_cb: None, - text_cb: None, - userdata: 0 as *mut libc::c_void, - }; - let mut xml_raw: *mut libc::c_char = 0 as *mut libc::c_char; + let mut p: *mut libc::c_char; + let mut saxparser: dc_saxparser_t; + let mut xml_raw: *mut libc::c_char; let mut moz_ac: moz_autoconfigure_t = moz_autoconfigure_t { in_0: 0 as *const dc_loginparam_t, in_emaildomain: 0 as *mut libc::c_char, @@ -1710,6 +1372,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, @@ -1859,17 +1522,17 @@ unsafe fn moz_autoconfigure_starttag_cb( }; } unsafe fn read_autoconf_file( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut url: *const libc::c_char, ) -> *mut libc::c_char { - let mut filecontent: *mut libc::c_char = 0 as *mut libc::c_char; + let mut filecontent: *mut libc::c_char; dc_log_info( context, 0i32, b"Testing %s ...\x00" as *const u8 as *const libc::c_char, url, ); - filecontent = ((*context).cb)( + filecontent = (context.cb)( context, Event::HTTP_GET, url as uintptr_t, @@ -1887,9 +1550,9 @@ unsafe fn read_autoconf_file( return filecontent; } unsafe fn outlk_autodiscover( - mut context: *mut dc_context_t, - mut url__: *const libc::c_char, - mut param_in: *const dc_loginparam_t, + context: &dc_context_t, + url__: *const libc::c_char, + param_in: *const dc_loginparam_t, ) -> *mut dc_loginparam_t { let mut current_block: u64; let mut xml_raw: *mut libc::c_char = 0 as *mut libc::c_char; @@ -1904,7 +1567,6 @@ unsafe fn outlk_autodiscover( redirect: 0 as *mut libc::c_char, }; let mut i: libc::c_int = 0; - i = 0i32; loop { if !(i < 10i32) { current_block = 11584701595673473500; @@ -1981,7 +1643,6 @@ unsafe fn outlk_autodiscover( } unsafe fn outlk_clean_config(mut outlk_ad: *mut outlk_autodiscover_t) { let mut i: libc::c_int = 0; - i = 0i32; while i < 6i32 { free((*outlk_ad).config[i as usize] as *mut libc::c_void); (*outlk_ad).config[i as usize] = 0 as *mut libc::c_char; @@ -2071,10 +1732,7 @@ unsafe fn outlk_autodiscover_starttag_cb( (*outlk_ad).tag_config = 5i32 }; } -pub unsafe fn dc_alloc_ongoing(mut context: *mut dc_context_t) -> libc::c_int { - if context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint { - return 0i32; - } +pub unsafe fn dc_alloc_ongoing(context: &dc_context_t) -> libc::c_int { if 0 != dc_has_ongoing(context) { dc_log_warning( context, @@ -2084,46 +1742,44 @@ pub unsafe fn dc_alloc_ongoing(mut context: *mut dc_context_t) -> libc::c_int { ); return 0i32; } - (*context).ongoing_running = 1i32; - (*context).shall_stop_ongoing = 0i32; - return 1i32; + let s_a = context.running_state.clone(); + let mut s = s_a.write().unwrap(); + + s.ongoing_running = true; + s.shall_stop_ongoing = false; + + 1 } -pub unsafe fn dc_connect_to_configured_imap( - mut context: *mut dc_context_t, - mut imap: *mut dc_imap_t, -) -> libc::c_int { + +pub unsafe fn dc_connect_to_configured_imap(context: &dc_context_t, imap: &Imap) -> libc::c_int { let mut ret_connected: libc::c_int = 0i32; let mut param: *mut dc_loginparam_t = dc_loginparam_new(); - if context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint || imap.is_null() { - dc_log_warning( - (*imap).context, - 0i32, - b"Cannot connect to IMAP: Bad parameters.\x00" as *const u8 as *const libc::c_char, - ); - } else if 0 != dc_imap_is_connected(imap) { + if imap.is_connected() { ret_connected = 1i32 } else if dc_sqlite3_get_config_int( - (*(*imap).context).sql, + context, + &context.sql.clone().read().unwrap(), b"configured\x00" as *const u8 as *const libc::c_char, 0i32, ) == 0i32 { dc_log_warning( - (*imap).context, + context, 0i32, b"Not configured, cannot connect.\x00" as *const u8 as *const libc::c_char, ); } else { dc_loginparam_read( + context, param, - (*(*imap).context).sql, + &context.sql.clone().read().unwrap(), b"configured_\x00" as *const u8 as *const libc::c_char, ); /*the trailing underscore is correct*/ - if !(0 == dc_imap_connect(imap, param)) { + if !(0 == imap.connect(context, param)) { ret_connected = 2i32 } } dc_loginparam_unref(param); - return ret_connected; + ret_connected } diff --git a/src/dc_contact.rs b/src/dc_contact.rs index f61967833..6e35c22e3 100644 --- a/src/dc_contact.rs +++ b/src/dc_contact.rs @@ -1,5 +1,3 @@ -use libc; - use crate::constants::Event; use crate::dc_apeerstate::*; use crate::dc_array::*; @@ -9,7 +7,6 @@ use crate::dc_e2ee::*; use crate::dc_key::*; use crate::dc_log::*; use crate::dc_loginparam::*; -use crate::dc_pgp::*; use crate::dc_sqlite3::*; use crate::dc_stock::*; use crate::dc_strbuilder::*; @@ -19,9 +16,9 @@ use crate::x::*; #[derive(Copy, Clone)] #[repr(C)] -pub struct dc_contact_t { +pub struct dc_contact_t<'a> { pub magic: uint32_t, - pub context: *mut dc_context_t, + pub context: &'a dc_context_t, pub id: uint32_t, pub name: *mut libc::c_char, pub authname: *mut libc::c_char, @@ -30,12 +27,10 @@ pub struct dc_contact_t { pub origin: libc::c_int, } -pub unsafe fn dc_marknoticed_contact(mut context: *mut dc_context_t, mut contact_id: uint32_t) { - if context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint { - return; - } +pub unsafe fn dc_marknoticed_contact(context: &dc_context_t, contact_id: uint32_t) { let mut stmt: *mut sqlite3_stmt = dc_sqlite3_prepare( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"UPDATE msgs SET state=13 WHERE from_id=? AND state=10;\x00" as *const u8 as *const libc::c_char, ); @@ -49,7 +44,9 @@ pub unsafe fn dc_marknoticed_contact(mut context: *mut dc_context_t, mut contact 0i32 as uintptr_t, ); } + // handle contacts +// TODO should return bool /rtn pub unsafe extern "C" fn dc_may_be_valid_addr(mut addr: *const libc::c_char) -> libc::c_int { if addr.is_null() { return 0i32; @@ -66,24 +63,23 @@ pub unsafe extern "C" fn dc_may_be_valid_addr(mut addr: *const libc::c_char) -> { return 0i32; } - return 1i32; + + 1 } + pub unsafe fn dc_lookup_contact_id_by_addr( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut addr: *const libc::c_char, ) -> uint32_t { let mut contact_id: libc::c_int = 0i32; let mut addr_normalized: *mut libc::c_char = 0 as *mut libc::c_char; let mut addr_self: *mut libc::c_char = 0 as *mut libc::c_char; let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; - if !(context.is_null() - || (*context).magic != 0x11a11807i32 as libc::c_uint - || addr.is_null() - || *addr.offset(0isize) as libc::c_int == 0i32) - { + if !(addr.is_null() || *addr.offset(0isize) as libc::c_int == 0i32) { addr_normalized = dc_addr_normalize(addr); addr_self = dc_sqlite3_get_config( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"configured_addr\x00" as *const u8 as *const libc::c_char, b"\x00" as *const u8 as *const libc::c_char, ); @@ -91,7 +87,8 @@ pub unsafe fn dc_lookup_contact_id_by_addr( contact_id = 1i32 } else { stmt = - dc_sqlite3_prepare((*context).sql, + dc_sqlite3_prepare( + context,&context.sql.clone().read().unwrap(), b"SELECT id FROM contacts WHERE addr=?1 COLLATE NOCASE AND id>?2 AND origin>=?3 AND blocked=0;\x00" as *const u8 as *const libc::c_char); sqlite3_bind_text( @@ -111,8 +108,10 @@ pub unsafe fn dc_lookup_contact_id_by_addr( sqlite3_finalize(stmt); free(addr_normalized as *mut libc::c_void); free(addr_self as *mut libc::c_void); - return contact_id as uint32_t; + + contact_id as uint32_t } + pub unsafe fn dc_addr_normalize(mut addr: *const libc::c_char) -> *mut libc::c_char { let mut addr_normalized: *mut libc::c_char = dc_strdup(addr); dc_trim(addr_normalized); @@ -127,21 +126,19 @@ pub unsafe fn dc_addr_normalize(mut addr: *const libc::c_char) -> *mut libc::c_c free(old as *mut libc::c_void); dc_trim(addr_normalized); } - return addr_normalized; + + addr_normalized } + pub unsafe fn dc_create_contact( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut name: *const libc::c_char, mut addr: *const libc::c_char, ) -> uint32_t { let mut contact_id: uint32_t = 0i32 as uint32_t; let mut sth_modified: libc::c_int = 0i32; - let mut blocked: libc::c_int = 0i32; - if !(context.is_null() - || (*context).magic != 0x11a11807i32 as libc::c_uint - || addr.is_null() - || *addr.offset(0isize) as libc::c_int == 0i32) - { + let mut blocked: libc::c_int; + if !(addr.is_null() || *addr.offset(0isize) as libc::c_int == 0i32) { contact_id = dc_add_or_lookup_contact(context, name, addr, 0x4000000i32, &mut sth_modified); blocked = dc_is_contact_blocked(context, contact_id); ((*context).cb)( @@ -158,10 +155,12 @@ pub unsafe fn dc_create_contact( dc_block_contact(context, contact_id, 0i32); } } - return contact_id; + + contact_id } + pub unsafe fn dc_block_contact( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut contact_id: uint32_t, mut new_blocking: libc::c_int, ) { @@ -169,15 +168,13 @@ pub unsafe fn dc_block_contact( let mut send_event: libc::c_int = 0i32; let mut contact: *mut dc_contact_t = dc_contact_new(context); let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; - if !(context.is_null() - || (*context).magic != 0x11a11807i32 as libc::c_uint - || contact_id <= 9i32 as libc::c_uint) - { - if 0 != dc_contact_load_from_db(contact, (*context).sql, contact_id) + if !(contact_id <= 9i32 as libc::c_uint) { + if 0 != dc_contact_load_from_db(contact, &context.sql.clone().read().unwrap(), contact_id) && (*contact).blocked != new_blocking { stmt = dc_sqlite3_prepare( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"UPDATE contacts SET blocked=? WHERE id=?;\x00" as *const u8 as *const libc::c_char, ); @@ -187,9 +184,9 @@ pub unsafe fn dc_block_contact( current_block = 5249903830285462583; } else { sqlite3_finalize(stmt); - stmt = 0 as *mut sqlite3_stmt; stmt = - dc_sqlite3_prepare((*context).sql, + dc_sqlite3_prepare( + context,&context.sql.clone().read().unwrap(), b"UPDATE chats SET blocked=? WHERE type=? AND id IN (SELECT chat_id FROM chats_contacts WHERE contact_id=?);\x00" as *const u8 as *const libc::c_char); @@ -224,7 +221,8 @@ pub unsafe fn dc_block_contact( sqlite3_finalize(stmt); dc_contact_unref(contact); } -/* * + +/** * @class dc_contact_t * * An object representing a single contact in memory. @@ -243,17 +241,19 @@ pub unsafe fn dc_block_contact( * dc_create_contact() or dc_add_address_book()) * only affect the given-name. */ -pub unsafe fn dc_contact_new(mut context: *mut dc_context_t) -> *mut dc_contact_t { - let mut contact: *mut dc_contact_t = 0 as *mut dc_contact_t; +pub unsafe fn dc_contact_new<'a>(context: &'a dc_context_t) -> *mut dc_contact_t<'a> { + let mut contact: *mut dc_contact_t; contact = calloc(1, ::std::mem::size_of::()) as *mut dc_contact_t; if contact.is_null() { exit(19i32); } (*contact).magic = 0xc047ac7i32 as uint32_t; (*contact).context = context; - return contact; + + contact } -pub unsafe fn dc_contact_unref(mut contact: *mut dc_contact_t) { + +pub unsafe fn dc_contact_unref(contact: *mut dc_contact_t) { if contact.is_null() || (*contact).magic != 0xc047ac7i32 as libc::c_uint { return; } @@ -261,6 +261,7 @@ pub unsafe fn dc_contact_unref(mut contact: *mut dc_contact_t) { (*contact).magic = 0i32 as uint32_t; free(contact as *mut libc::c_void); } + pub unsafe fn dc_contact_empty(mut contact: *mut dc_contact_t) { if contact.is_null() || (*contact).magic != 0xc047ac7i32 as libc::c_uint { return; @@ -275,6 +276,7 @@ pub unsafe fn dc_contact_empty(mut contact: *mut dc_contact_t) { (*contact).origin = 0i32; (*contact).blocked = 0i32; } + /* From: of incoming messages of unknown sender */ /* Cc: of incoming messages of unknown sender */ /* To: of incoming messages of unknown sender */ @@ -294,20 +296,22 @@ pub unsafe fn dc_contact_empty(mut contact: *mut dc_contact_t) { /* contacts with at least this origin value are shown in the contact list */ /* contacts with at least this origin value are verified and known not to be spam */ /* contacts with at least this origin value start a new "normal" chat, defaults to off */ +// TODO should return bool /rtn pub unsafe fn dc_contact_load_from_db( - mut contact: *mut dc_contact_t, - mut sql: *mut dc_sqlite3_t, - mut contact_id: uint32_t, + contact: *mut dc_contact_t, + sql: &dc_sqlite3_t, + contact_id: uint32_t, ) -> libc::c_int { let mut current_block: u64; let mut success: libc::c_int = 0i32; let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; - if !(contact.is_null() || (*contact).magic != 0xc047ac7i32 as libc::c_uint || sql.is_null()) { + if !(contact.is_null() || (*contact).magic != 0xc047ac7i32 as libc::c_uint) { dc_contact_empty(contact); if contact_id == 1i32 as libc::c_uint { (*contact).id = contact_id; (*contact).name = dc_stock_str((*contact).context, 2i32); (*contact).addr = dc_sqlite3_get_config( + (*contact).context, sql, b"configured_addr\x00" as *const u8 as *const libc::c_char, b"\x00" as *const u8 as *const libc::c_char, @@ -315,7 +319,8 @@ pub unsafe fn dc_contact_load_from_db( current_block = 5143058163439228106; } else { stmt = - dc_sqlite3_prepare(sql, + dc_sqlite3_prepare( + (*contact).context,sql, b"SELECT c.name, c.addr, c.origin, c.blocked, c.authname FROM contacts c WHERE c.id=?;\x00" as *const u8 as *const libc::c_char); sqlite3_bind_int(stmt, 1i32, contact_id as libc::c_int); @@ -338,25 +343,30 @@ pub unsafe fn dc_contact_load_from_db( } } sqlite3_finalize(stmt); - return success; + + success } + +// TODO should return bool /rtn pub unsafe fn dc_is_contact_blocked( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut contact_id: uint32_t, ) -> libc::c_int { let mut is_blocked: libc::c_int = 0i32; let mut contact: *mut dc_contact_t = dc_contact_new(context); - if 0 != dc_contact_load_from_db(contact, (*context).sql, contact_id) { + if 0 != dc_contact_load_from_db(contact, &context.sql.clone().read().unwrap(), contact_id) { if 0 != (*contact).blocked { is_blocked = 1i32 } } dc_contact_unref(contact); - return is_blocked; + + is_blocked } + /*can be NULL*/ pub unsafe fn dc_add_or_lookup_contact( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut name: *const libc::c_char, mut addr__: *const libc::c_char, mut origin: libc::c_int, @@ -374,14 +384,11 @@ pub unsafe fn dc_add_or_lookup_contact( sth_modified = &mut dummy } *sth_modified = 0i32; - if !(context.is_null() - || (*context).magic != 0x11a11807i32 as libc::c_uint - || addr__.is_null() - || origin <= 0i32) - { + if !(addr__.is_null() || origin <= 0i32) { addr = dc_addr_normalize(addr__); addr_self = dc_sqlite3_get_config( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"configured_addr\x00" as *const u8 as *const libc::c_char, b"\x00" as *const u8 as *const libc::c_char, ); @@ -401,12 +408,13 @@ pub unsafe fn dc_add_or_lookup_contact( ); } else { stmt = - dc_sqlite3_prepare((*context).sql, + dc_sqlite3_prepare( + context,&context.sql.clone().read().unwrap(), b"SELECT id, name, addr, origin, authname FROM contacts WHERE addr=? COLLATE NOCASE;\x00" as *const u8 as *const libc::c_char); sqlite3_bind_text(stmt, 1i32, addr as *const libc::c_char, -1i32, None); if sqlite3_step(stmt) == 100i32 { - let mut row_origin: libc::c_int = 0; + let mut row_origin: libc::c_int; let mut update_addr: libc::c_int = 0i32; let mut update_name: libc::c_int = 0i32; let mut update_authname: libc::c_int = 0i32; @@ -438,7 +446,8 @@ pub unsafe fn dc_add_or_lookup_contact( || origin > row_origin { stmt = dc_sqlite3_prepare( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"UPDATE contacts SET name=?, addr=?, origin=?, authname=? WHERE id=?;\x00" as *const u8 as *const libc::c_char, ); @@ -482,7 +491,8 @@ pub unsafe fn dc_add_or_lookup_contact( stmt = 0 as *mut sqlite3_stmt; if 0 != update_name { stmt = - dc_sqlite3_prepare((*context).sql, + dc_sqlite3_prepare( + context,&context.sql.clone().read().unwrap(), b"UPDATE chats SET name=? WHERE type=? AND id IN(SELECT chat_id FROM chats_contacts WHERE contact_id=?);\x00" as *const u8 as *const libc::c_char); @@ -495,9 +505,9 @@ pub unsafe fn dc_add_or_lookup_contact( } } else { sqlite3_finalize(stmt); - stmt = 0 as *mut sqlite3_stmt; stmt = dc_sqlite3_prepare( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"INSERT INTO contacts (name, addr, origin) VALUES(?, ?, ?);\x00" as *const u8 as *const libc::c_char, ); @@ -516,7 +526,8 @@ pub unsafe fn dc_add_or_lookup_contact( sqlite3_bind_int(stmt, 3i32, origin); if sqlite3_step(stmt) == 101i32 { row_id = dc_sqlite3_get_rowid( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"contacts\x00" as *const u8 as *const libc::c_char, b"addr\x00" as *const u8 as *const libc::c_char, addr, @@ -538,24 +549,22 @@ pub unsafe fn dc_add_or_lookup_contact( free(row_name as *mut libc::c_void); free(row_authname as *mut libc::c_void); sqlite3_finalize(stmt); - return row_id; + + row_id } + pub unsafe fn dc_add_address_book( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut adr_book: *const libc::c_char, ) -> libc::c_int { let mut lines: *mut carray = 0 as *mut carray; - let mut i: size_t = 0i32 as size_t; - let mut iCnt: size_t = 0i32 as size_t; + let mut i: size_t; + let mut iCnt: size_t; let mut sth_modified: libc::c_int = 0i32; let mut modify_cnt: libc::c_int = 0i32; - if !(context.is_null() - || (*context).magic != 0x11a11807i32 as libc::c_uint - || adr_book.is_null()) - { + if !(adr_book.is_null()) { lines = dc_split_into_lines(adr_book); if !lines.is_null() { - dc_sqlite3_begin_transaction((*context).sql); iCnt = carray_count(lines) as size_t; i = 0i32 as size_t; while i.wrapping_add(1) < iCnt { @@ -570,7 +579,6 @@ pub unsafe fn dc_add_address_book( } i = (i as libc::c_ulong).wrapping_add(2i32 as libc::c_ulong) as size_t as size_t } - dc_sqlite3_commit((*context).sql); if 0 != modify_cnt { ((*context).cb)( context, @@ -582,8 +590,10 @@ pub unsafe fn dc_add_address_book( } } dc_free_splitted_lines(lines); - return modify_cnt; + + modify_cnt } + // Working with names pub unsafe fn dc_normalize_name(mut full_name: *mut libc::c_char) { if full_name.is_null() { @@ -618,145 +628,151 @@ pub unsafe fn dc_normalize_name(mut full_name: *mut libc::c_char) { dc_trim(full_name); }; } + pub unsafe fn dc_get_contacts( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut listflags: uint32_t, mut query: *const libc::c_char, ) -> *mut dc_array_t { let mut current_block: u64; - let mut self_addr: *mut libc::c_char = 0 as *mut libc::c_char; + let mut self_addr: *mut libc::c_char; let mut self_name: *mut libc::c_char = 0 as *mut libc::c_char; let mut self_name2: *mut libc::c_char = 0 as *mut libc::c_char; let mut add_self: libc::c_int = 0i32; - let mut ret: *mut dc_array_t = dc_array_new(context, 100i32 as size_t); + let mut ret: *mut dc_array_t = dc_array_new(100i32 as size_t); let mut s3strLikeCmd: *mut libc::c_char = 0 as *mut libc::c_char; let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; - if !(context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint) { - self_addr = dc_sqlite3_get_config( - (*context).sql, - b"configured_addr\x00" as *const u8 as *const libc::c_char, - b"\x00" as *const u8 as *const libc::c_char, - ); - if 0 != listflags & 0x1i32 as libc::c_uint || !query.is_null() { - s3strLikeCmd = sqlite3_mprintf( - b"%%%s%%\x00" as *const u8 as *const libc::c_char, - if !query.is_null() { - query - } else { - b"\x00" as *const u8 as *const libc::c_char - }, - ); - if s3strLikeCmd.is_null() { - current_block = 7597307149762829253; + + self_addr = dc_sqlite3_get_config( + context, + &context.sql.clone().read().unwrap(), + b"configured_addr\x00" as *const u8 as *const libc::c_char, + b"\x00" as *const u8 as *const libc::c_char, + ); + if 0 != listflags & 0x1i32 as libc::c_uint || !query.is_null() { + s3strLikeCmd = sqlite3_mprintf( + b"%%%s%%\x00" as *const u8 as *const libc::c_char, + if !query.is_null() { + query } else { - stmt = - dc_sqlite3_prepare((*context).sql, + b"\x00" as *const u8 as *const libc::c_char + }, + ); + if s3strLikeCmd.is_null() { + current_block = 7597307149762829253; + } else { + stmt = + dc_sqlite3_prepare( + context,&context.sql.clone().read().unwrap(), b"SELECT c.id FROM contacts c LEFT JOIN acpeerstates ps ON c.addr=ps.addr WHERE c.addr!=?1 AND c.id>?2 AND c.origin>=?3 AND c.blocked=0 AND (c.name LIKE ?4 OR c.addr LIKE ?5) AND (1=?6 OR LENGTH(ps.verified_key_fingerprint)!=0) ORDER BY LOWER(c.name||c.addr),c.id;\x00" as *const u8 as *const libc::c_char); - sqlite3_bind_text(stmt, 1i32, self_addr, -1i32, None); - sqlite3_bind_int(stmt, 2i32, 9i32); - sqlite3_bind_int(stmt, 3i32, 0x100i32); - sqlite3_bind_text(stmt, 4i32, s3strLikeCmd, -1i32, None); - sqlite3_bind_text(stmt, 5i32, s3strLikeCmd, -1i32, None); - sqlite3_bind_int( - stmt, - 6i32, - if 0 != listflags & 0x1i32 as libc::c_uint { - 0i32 - } else { - 1i32 - }, - ); - self_name = dc_sqlite3_get_config( - (*context).sql, - b"displayname\x00" as *const u8 as *const libc::c_char, - b"\x00" as *const u8 as *const libc::c_char, - ); - self_name2 = dc_stock_str(context, 2i32); - if query.is_null() - || 0 != dc_str_contains(self_addr, query) - || 0 != dc_str_contains(self_name, query) - || 0 != dc_str_contains(self_name2, query) - { - add_self = 1i32 - } - current_block = 15768484401365413375; - } - } else { - stmt = - dc_sqlite3_prepare((*context).sql, - b"SELECT id FROM contacts WHERE addr!=?1 AND id>?2 AND origin>=?3 AND blocked=0 ORDER BY LOWER(name||addr),id;\x00" - as *const u8 as *const libc::c_char); sqlite3_bind_text(stmt, 1i32, self_addr, -1i32, None); sqlite3_bind_int(stmt, 2i32, 9i32); sqlite3_bind_int(stmt, 3i32, 0x100i32); - add_self = 1i32; + sqlite3_bind_text(stmt, 4i32, s3strLikeCmd, -1i32, None); + sqlite3_bind_text(stmt, 5i32, s3strLikeCmd, -1i32, None); + sqlite3_bind_int( + stmt, + 6i32, + if 0 != listflags & 0x1i32 as libc::c_uint { + 0i32 + } else { + 1i32 + }, + ); + self_name = dc_sqlite3_get_config( + context, + &context.sql.clone().read().unwrap(), + b"displayname\x00" as *const u8 as *const libc::c_char, + b"\x00" as *const u8 as *const libc::c_char, + ); + self_name2 = dc_stock_str(context, 2i32); + if query.is_null() + || 0 != dc_str_contains(self_addr, query) + || 0 != dc_str_contains(self_name, query) + || 0 != dc_str_contains(self_name2, query) + { + add_self = 1i32 + } current_block = 15768484401365413375; } - match current_block { - 7597307149762829253 => {} - _ => { - while sqlite3_step(stmt) == 100i32 { - dc_array_add_id(ret, sqlite3_column_int(stmt, 0i32) as uint32_t); - } - if 0 != listflags & 0x2i32 as libc::c_uint && 0 != add_self { - dc_array_add_id(ret, 1i32 as uint32_t); - } + } else { + stmt = + dc_sqlite3_prepare( + context,&context.sql.clone().read().unwrap(), + b"SELECT id FROM contacts WHERE addr!=?1 AND id>?2 AND origin>=?3 AND blocked=0 ORDER BY LOWER(name||addr),id;\x00" + as *const u8 as *const libc::c_char); + sqlite3_bind_text(stmt, 1i32, self_addr, -1i32, None); + sqlite3_bind_int(stmt, 2i32, 9i32); + sqlite3_bind_int(stmt, 3i32, 0x100i32); + add_self = 1i32; + current_block = 15768484401365413375; + } + match current_block { + 7597307149762829253 => {} + _ => { + while sqlite3_step(stmt) == 100i32 { + dc_array_add_id(ret, sqlite3_column_int(stmt, 0i32) as uint32_t); + } + if 0 != listflags & 0x2i32 as libc::c_uint && 0 != add_self { + dc_array_add_id(ret, 1i32 as uint32_t); } } } + sqlite3_finalize(stmt); sqlite3_free(s3strLikeCmd as *mut libc::c_void); free(self_addr as *mut libc::c_void); free(self_name as *mut libc::c_void); free(self_name2 as *mut libc::c_void); - return ret; + + ret } -pub unsafe fn dc_get_blocked_cnt(mut context: *mut dc_context_t) -> libc::c_int { + +pub unsafe fn dc_get_blocked_cnt(context: &dc_context_t) -> libc::c_int { let mut ret: libc::c_int = 0i32; - let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; - if !(context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint) { - stmt = dc_sqlite3_prepare( - (*context).sql, - b"SELECT COUNT(*) FROM contacts WHERE id>? AND blocked!=0\x00" as *const u8 - as *const libc::c_char, - ); - sqlite3_bind_int(stmt, 1i32, 9i32); - if !(sqlite3_step(stmt) != 100i32) { - ret = sqlite3_column_int(stmt, 0i32) - } + let mut stmt: *mut sqlite3_stmt; + + stmt = dc_sqlite3_prepare( + context, + &context.sql.clone().read().unwrap(), + b"SELECT COUNT(*) FROM contacts WHERE id>? AND blocked!=0\x00" as *const u8 + as *const libc::c_char, + ); + sqlite3_bind_int(stmt, 1i32, 9i32); + if !(sqlite3_step(stmt) != 100i32) { + ret = sqlite3_column_int(stmt, 0i32) } + sqlite3_finalize(stmt); - return ret; + ret } -pub unsafe fn dc_get_blocked_contacts(mut context: *mut dc_context_t) -> *mut dc_array_t { - let mut ret: *mut dc_array_t = dc_array_new(context, 100i32 as size_t); - let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; - if !(context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint) { - stmt = dc_sqlite3_prepare( - (*context).sql, - b"SELECT id FROM contacts WHERE id>? AND blocked!=0 ORDER BY LOWER(name||addr),id;\x00" - as *const u8 as *const libc::c_char, - ); - sqlite3_bind_int(stmt, 1i32, 9i32); - while sqlite3_step(stmt) == 100i32 { - dc_array_add_id(ret, sqlite3_column_int(stmt, 0i32) as uint32_t); - } + +pub unsafe fn dc_get_blocked_contacts(mut context: &dc_context_t) -> *mut dc_array_t { + let mut ret: *mut dc_array_t = dc_array_new(100i32 as size_t); + let mut stmt: *mut sqlite3_stmt; + + stmt = dc_sqlite3_prepare( + context, + &context.sql.clone().read().unwrap(), + b"SELECT id FROM contacts WHERE id>? AND blocked!=0 ORDER BY LOWER(name||addr),id;\x00" + as *const u8 as *const libc::c_char, + ); + sqlite3_bind_int(stmt, 1i32, 9i32); + while sqlite3_step(stmt) == 100i32 { + dc_array_add_id(ret, sqlite3_column_int(stmt, 0i32) as uint32_t); } + sqlite3_finalize(stmt); - return ret; + ret } + pub unsafe fn dc_get_contact_encrinfo( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut contact_id: uint32_t, ) -> *mut libc::c_char { - let mut ret: dc_strbuilder_t = dc_strbuilder_t { - buf: 0 as *mut libc::c_char, - allocated: 0, - free: 0, - eos: 0 as *mut libc::c_char, - }; + let mut ret: dc_strbuilder_t; let mut loginparam: *mut dc_loginparam_t = dc_loginparam_new(); let mut contact: *mut dc_contact_t = dc_contact_new(context); let mut peerstate: *mut dc_apeerstate_t = dc_apeerstate_new(context); @@ -764,93 +780,103 @@ pub unsafe fn dc_get_contact_encrinfo( let mut fingerprint_self: *mut libc::c_char = 0 as *mut libc::c_char; let mut fingerprint_other_verified: *mut libc::c_char = 0 as *mut libc::c_char; let mut fingerprint_other_unverified: *mut libc::c_char = 0 as *mut libc::c_char; - let mut p: *mut libc::c_char = 0 as *mut libc::c_char; - if !(context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint) { - ret = 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 ret, 0i32); - if !(0 == dc_contact_load_from_db(contact, (*context).sql, contact_id)) { - dc_apeerstate_load_by_addr(peerstate, (*context).sql, (*contact).addr); - dc_loginparam_read( - loginparam, - (*context).sql, - b"configured_\x00" as *const u8 as *const libc::c_char, - ); - dc_key_load_self_public(self_key, (*loginparam).addr, (*context).sql); - if !dc_apeerstate_peek_key(peerstate, 0i32).is_null() { - p = dc_stock_str( - context, - if (*peerstate).prefer_encrypt == 1i32 { - 34i32 - } else { - 25i32 - }, - ); - dc_strbuilder_cat(&mut ret, p); - free(p as *mut libc::c_void); - if (*self_key).binary.is_null() { - dc_pgp_rand_seed( - context, - (*peerstate).addr as *const libc::c_void, - strlen((*peerstate).addr), - ); - dc_ensure_secret_key_exists(context); - dc_key_load_self_public(self_key, (*loginparam).addr, (*context).sql); - } - dc_strbuilder_cat(&mut ret, b" \x00" as *const u8 as *const libc::c_char); - p = dc_stock_str(context, 30i32); - dc_strbuilder_cat(&mut ret, p); - free(p as *mut libc::c_void); - dc_strbuilder_cat(&mut ret, b":\x00" as *const u8 as *const libc::c_char); - fingerprint_self = dc_key_get_formatted_fingerprint(self_key); - fingerprint_other_verified = - dc_key_get_formatted_fingerprint(dc_apeerstate_peek_key(peerstate, 2i32)); - fingerprint_other_unverified = - dc_key_get_formatted_fingerprint(dc_apeerstate_peek_key(peerstate, 0i32)); - if strcmp((*loginparam).addr, (*peerstate).addr) < 0i32 { - cat_fingerprint( - &mut ret, - (*loginparam).addr, - fingerprint_self, - 0 as *const libc::c_char, - ); - cat_fingerprint( - &mut ret, - (*peerstate).addr, - fingerprint_other_verified, - fingerprint_other_unverified, - ); + let mut p: *mut libc::c_char; + + ret = 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 ret, 0i32); + if !(0 == dc_contact_load_from_db(contact, &context.sql.clone().read().unwrap(), contact_id)) { + dc_apeerstate_load_by_addr( + peerstate, + &context.sql.clone().read().unwrap(), + (*contact).addr, + ); + dc_loginparam_read( + context, + loginparam, + &context.sql.clone().read().unwrap(), + b"configured_\x00" as *const u8 as *const libc::c_char, + ); + dc_key_load_self_public( + context, + self_key, + (*loginparam).addr, + &context.sql.clone().read().unwrap(), + ); + if !dc_apeerstate_peek_key(peerstate, 0i32).is_null() { + p = dc_stock_str( + context, + if (*peerstate).prefer_encrypt == 1i32 { + 34i32 } else { - cat_fingerprint( - &mut ret, - (*peerstate).addr, - fingerprint_other_verified, - fingerprint_other_unverified, - ); - cat_fingerprint( - &mut ret, - (*loginparam).addr, - fingerprint_self, - 0 as *const libc::c_char, - ); - } - } else if 0 == (*loginparam).server_flags & 0x400i32 - && 0 == (*loginparam).server_flags & 0x40000i32 - { - p = dc_stock_str(context, 27i32); - dc_strbuilder_cat(&mut ret, p); - free(p as *mut libc::c_void); - } else { - p = dc_stock_str(context, 28i32); - dc_strbuilder_cat(&mut ret, p); - free(p as *mut libc::c_void); + 25i32 + }, + ); + dc_strbuilder_cat(&mut ret, p); + free(p as *mut libc::c_void); + if (*self_key).binary.is_null() { + dc_ensure_secret_key_exists(context); + dc_key_load_self_public( + context, + self_key, + (*loginparam).addr, + &context.sql.clone().read().unwrap(), + ); } + dc_strbuilder_cat(&mut ret, b" \x00" as *const u8 as *const libc::c_char); + p = dc_stock_str(context, 30i32); + dc_strbuilder_cat(&mut ret, p); + free(p as *mut libc::c_void); + dc_strbuilder_cat(&mut ret, b":\x00" as *const u8 as *const libc::c_char); + fingerprint_self = dc_key_get_formatted_fingerprint(context, self_key); + fingerprint_other_verified = + dc_key_get_formatted_fingerprint(context, dc_apeerstate_peek_key(peerstate, 2i32)); + fingerprint_other_unverified = + dc_key_get_formatted_fingerprint(context, dc_apeerstate_peek_key(peerstate, 0i32)); + if strcmp((*loginparam).addr, (*peerstate).addr) < 0i32 { + cat_fingerprint( + &mut ret, + (*loginparam).addr, + fingerprint_self, + 0 as *const libc::c_char, + ); + cat_fingerprint( + &mut ret, + (*peerstate).addr, + fingerprint_other_verified, + fingerprint_other_unverified, + ); + } else { + cat_fingerprint( + &mut ret, + (*peerstate).addr, + fingerprint_other_verified, + fingerprint_other_unverified, + ); + cat_fingerprint( + &mut ret, + (*loginparam).addr, + fingerprint_self, + 0 as *const libc::c_char, + ); + } + } else if 0 == (*loginparam).server_flags & 0x400i32 + && 0 == (*loginparam).server_flags & 0x40000i32 + { + p = dc_stock_str(context, 27i32); + dc_strbuilder_cat(&mut ret, p); + free(p as *mut libc::c_void); + } else { + p = dc_stock_str(context, 28i32); + dc_strbuilder_cat(&mut ret, p); + free(p as *mut libc::c_void); } } + dc_apeerstate_unref(peerstate); dc_contact_unref(contact); dc_loginparam_unref(loginparam); @@ -858,8 +884,10 @@ pub unsafe fn dc_get_contact_encrinfo( free(fingerprint_self as *mut libc::c_void); free(fingerprint_other_verified as *mut libc::c_void); free(fingerprint_other_unverified as *mut libc::c_void); - return ret.buf; + + ret.buf } + unsafe fn cat_fingerprint( mut ret: *mut dc_strbuilder_t, mut addr: *const libc::c_char, @@ -894,27 +922,27 @@ unsafe fn cat_fingerprint( dc_strbuilder_cat(ret, fingerprint_unverified); }; } + +// TODO should return bool /rtn pub unsafe fn dc_delete_contact( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut contact_id: uint32_t, ) -> libc::c_int { let mut success: libc::c_int = 0i32; let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; - if !(context.is_null() - || (*context).magic != 0x11a11807i32 as libc::c_uint - || contact_id <= 9i32 as libc::c_uint) - { + if !contact_id <= 9i32 as libc::c_uint { stmt = dc_sqlite3_prepare( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"SELECT COUNT(*) FROM chats_contacts WHERE contact_id=?;\x00" as *const u8 as *const libc::c_char, ); sqlite3_bind_int(stmt, 1i32, contact_id as libc::c_int); if !(sqlite3_step(stmt) != 100i32 || sqlite3_column_int(stmt, 0i32) >= 1i32) { sqlite3_finalize(stmt); - stmt = 0 as *mut sqlite3_stmt; stmt = dc_sqlite3_prepare( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"SELECT COUNT(*) FROM msgs WHERE from_id=? OR to_id=?;\x00" as *const u8 as *const libc::c_char, ); @@ -922,9 +950,9 @@ pub unsafe fn dc_delete_contact( sqlite3_bind_int(stmt, 2i32, contact_id as libc::c_int); if !(sqlite3_step(stmt) != 100i32 || sqlite3_column_int(stmt, 0i32) >= 1i32) { sqlite3_finalize(stmt); - stmt = 0 as *mut sqlite3_stmt; stmt = dc_sqlite3_prepare( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"DELETE FROM contacts WHERE id=?;\x00" as *const u8 as *const libc::c_char, ); sqlite3_bind_int(stmt, 1i32, contact_id as libc::c_int); @@ -941,37 +969,43 @@ pub unsafe fn dc_delete_contact( } } sqlite3_finalize(stmt); - return success; + + success } + pub unsafe fn dc_get_contact( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut contact_id: uint32_t, ) -> *mut dc_contact_t { let mut ret: *mut dc_contact_t = dc_contact_new(context); - if 0 == dc_contact_load_from_db(ret, (*context).sql, contact_id) { + if 0 == dc_contact_load_from_db(ret, &context.sql.clone().read().unwrap(), contact_id) { dc_contact_unref(ret); ret = 0 as *mut dc_contact_t } - return ret; + ret } + pub unsafe fn dc_contact_get_id(mut contact: *const dc_contact_t) -> uint32_t { if contact.is_null() || (*contact).magic != 0xc047ac7i32 as libc::c_uint { return 0i32 as uint32_t; } - return (*contact).id; + (*contact).id } + pub unsafe fn dc_contact_get_addr(mut contact: *const dc_contact_t) -> *mut libc::c_char { if contact.is_null() || (*contact).magic != 0xc047ac7i32 as libc::c_uint { return dc_strdup(0 as *const libc::c_char); } - return dc_strdup((*contact).addr); + dc_strdup((*contact).addr) } + pub unsafe fn dc_contact_get_name(mut contact: *const dc_contact_t) -> *mut libc::c_char { if contact.is_null() || (*contact).magic != 0xc047ac7i32 as libc::c_uint { return dc_strdup(0 as *const libc::c_char); } - return dc_strdup((*contact).name); + dc_strdup((*contact).name) } + pub unsafe fn dc_contact_get_display_name(mut contact: *const dc_contact_t) -> *mut libc::c_char { if contact.is_null() || (*contact).magic != 0xc047ac7i32 as libc::c_uint { return dc_strdup(0 as *const libc::c_char); @@ -979,8 +1013,9 @@ pub unsafe fn dc_contact_get_display_name(mut contact: *const dc_contact_t) -> * if !(*contact).name.is_null() && 0 != *(*contact).name.offset(0isize) as libc::c_int { return dc_strdup((*contact).name); } - return dc_strdup((*contact).addr); + dc_strdup((*contact).addr) } + pub unsafe fn dc_contact_get_name_n_addr(mut contact: *const dc_contact_t) -> *mut libc::c_char { if contact.is_null() || (*contact).magic != 0xc047ac7i32 as libc::c_uint { return dc_strdup(0 as *const libc::c_char); @@ -992,8 +1027,9 @@ pub unsafe fn dc_contact_get_name_n_addr(mut contact: *const dc_contact_t) -> *m (*contact).addr, ); } - return dc_strdup((*contact).addr); + dc_strdup((*contact).addr) } + pub unsafe fn dc_contact_get_first_name(mut contact: *const dc_contact_t) -> *mut libc::c_char { if contact.is_null() || (*contact).magic != 0xc047ac7i32 as libc::c_uint { return dc_strdup(0 as *const libc::c_char); @@ -1001,8 +1037,9 @@ pub unsafe fn dc_contact_get_first_name(mut contact: *const dc_contact_t) -> *mu if !(*contact).name.is_null() && 0 != *(*contact).name.offset(0isize) as libc::c_int { return dc_get_first_name((*contact).name); } - return dc_strdup((*contact).addr); + dc_strdup((*contact).addr) } + pub unsafe fn dc_get_first_name(mut full_name: *const libc::c_char) -> *mut libc::c_char { let mut first_name: *mut libc::c_char = dc_strdup(full_name); let mut p1: *mut libc::c_char = strchr(first_name, ' ' as i32); @@ -1014,8 +1051,9 @@ pub unsafe fn dc_get_first_name(mut full_name: *const libc::c_char) -> *mut libc first_name = dc_strdup(full_name) } } - return first_name; + first_name } + pub unsafe fn dc_contact_get_profile_image(mut contact: *const dc_contact_t) -> *mut libc::c_char { let mut selfavatar: *mut libc::c_char = 0 as *mut libc::c_char; let mut image_abs: *mut libc::c_char = 0 as *mut libc::c_char; @@ -1032,26 +1070,30 @@ pub unsafe fn dc_contact_get_profile_image(mut contact: *const dc_contact_t) -> } // TODO: else get image_abs from contact param free(selfavatar as *mut libc::c_void); - return image_abs; + image_abs } + pub unsafe fn dc_contact_get_color(mut contact: *const dc_contact_t) -> uint32_t { if contact.is_null() || (*contact).magic != 0xc047ac7i32 as libc::c_uint { return 0i32 as uint32_t; } - return dc_str_to_color((*contact).addr) as uint32_t; + dc_str_to_color((*contact).addr) as uint32_t } + pub unsafe fn dc_contact_is_blocked(mut contact: *const dc_contact_t) -> libc::c_int { if contact.is_null() || (*contact).magic != 0xc047ac7i32 as libc::c_uint { return 0i32; } - return (*contact).blocked; + (*contact).blocked } + pub unsafe fn dc_contact_is_verified(mut contact: *mut dc_contact_t) -> libc::c_int { - return dc_contact_is_verified_ex(contact, 0 as *const dc_apeerstate_t); + dc_contact_is_verified_ex(contact, 0 as *mut dc_apeerstate_t) } -pub unsafe fn dc_contact_is_verified_ex( - mut contact: *mut dc_contact_t, - mut peerstate: *const dc_apeerstate_t, + +pub unsafe fn dc_contact_is_verified_ex<'a>( + contact: *mut dc_contact_t<'a>, + mut peerstate: *mut dc_apeerstate_t<'a>, ) -> libc::c_int { let mut current_block: u64; let mut contact_verified: libc::c_int = 0i32; @@ -1065,7 +1107,7 @@ pub unsafe fn dc_contact_is_verified_ex( peerstate_to_delete = dc_apeerstate_new((*contact).context); if 0 == dc_apeerstate_load_by_addr( peerstate_to_delete, - (*(*contact).context).sql, + &mut (*contact).context.sql.clone().read().unwrap(), (*contact).addr, ) { current_block = 8667923638376902112; @@ -1089,8 +1131,9 @@ pub unsafe fn dc_contact_is_verified_ex( } } dc_apeerstate_unref(peerstate_to_delete); - return contact_verified; + contact_verified } + // Working with e-mail-addresses pub unsafe fn dc_addr_cmp( mut addr1: *const libc::c_char, @@ -1101,19 +1144,21 @@ pub unsafe fn dc_addr_cmp( let mut ret: libc::c_int = strcasecmp(addr1, addr2); free(norm1 as *mut libc::c_void); free(norm2 as *mut libc::c_void); - return ret; + ret } + pub unsafe fn dc_addr_equals_self( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut addr: *const libc::c_char, ) -> libc::c_int { let mut ret: libc::c_int = 0i32; let mut normalized_addr: *mut libc::c_char = 0 as *mut libc::c_char; let mut self_addr: *mut libc::c_char = 0 as *mut libc::c_char; - if !(context.is_null() || addr.is_null()) { + if !addr.is_null() { normalized_addr = dc_addr_normalize(addr); self_addr = dc_sqlite3_get_config( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"configured_addr\x00" as *const u8 as *const libc::c_char, 0 as *const libc::c_char, ); @@ -1127,17 +1172,19 @@ pub unsafe fn dc_addr_equals_self( } free(self_addr as *mut libc::c_void); free(normalized_addr as *mut libc::c_void); - return ret; + ret } + +// TODO should return bool /rtn pub unsafe fn dc_addr_equals_contact( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut addr: *const libc::c_char, mut contact_id: uint32_t, ) -> libc::c_int { let mut addr_are_equal: libc::c_int = 0i32; if !addr.is_null() { let mut contact: *mut dc_contact_t = dc_contact_new(context); - if 0 != dc_contact_load_from_db(contact, (*context).sql, contact_id) { + if 0 != dc_contact_load_from_db(contact, &context.sql.clone().read().unwrap(), contact_id) { if !(*contact).addr.is_null() { let mut normalized_addr: *mut libc::c_char = dc_addr_normalize(addr); if strcasecmp((*contact).addr, normalized_addr) == 0i32 { @@ -1148,18 +1195,17 @@ pub unsafe fn dc_addr_equals_contact( } dc_contact_unref(contact); } - return addr_are_equal; + addr_are_equal } + // Context functions to work with contacts -pub unsafe fn dc_get_real_contact_cnt(mut context: *mut dc_context_t) -> size_t { +pub unsafe fn dc_get_real_contact_cnt(mut context: &dc_context_t) -> size_t { let mut ret: size_t = 0i32 as size_t; let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; - if !(context.is_null() - || (*context).magic != 0x11a11807i32 as libc::c_uint - || (*(*context).sql).cobj.is_null()) - { + if !context.sql.clone().read().unwrap().cobj.is_null() { stmt = dc_sqlite3_prepare( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"SELECT COUNT(*) FROM contacts WHERE id>?;\x00" as *const u8 as *const libc::c_char, ); sqlite3_bind_int(stmt, 1i32, 9i32); @@ -1168,10 +1214,11 @@ pub unsafe fn dc_get_real_contact_cnt(mut context: *mut dc_context_t) -> size_t } } sqlite3_finalize(stmt); - return ret; + ret } + pub unsafe fn dc_get_contact_origin( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut contact_id: uint32_t, mut ret_blocked: *mut libc::c_int, ) -> libc::c_int { @@ -1182,7 +1229,7 @@ pub unsafe fn dc_get_contact_origin( } let mut contact: *mut dc_contact_t = dc_contact_new(context); *ret_blocked = 0i32; - if !(0 == dc_contact_load_from_db(contact, (*context).sql, contact_id)) { + if !(0 == dc_contact_load_from_db(contact, &context.sql.clone().read().unwrap(), contact_id)) { /* we could optimize this by loading only the needed fields */ if 0 != (*contact).blocked { *ret_blocked = 1i32 @@ -1191,21 +1238,20 @@ pub unsafe fn dc_get_contact_origin( } } dc_contact_unref(contact); - return ret; + ret } + +// TODO should return bool /rtn pub unsafe fn dc_real_contact_exists( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut contact_id: uint32_t, ) -> libc::c_int { let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; let mut ret: libc::c_int = 0i32; - if !(context.is_null() - || (*context).magic != 0x11a11807i32 as libc::c_uint - || (*(*context).sql).cobj.is_null() - || contact_id <= 9i32 as libc::c_uint) - { + if !(context.sql.clone().read().unwrap().cobj.is_null() || contact_id <= 9i32 as libc::c_uint) { stmt = dc_sqlite3_prepare( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"SELECT id FROM contacts WHERE id=?;\x00" as *const u8 as *const libc::c_char, ); sqlite3_bind_int(stmt, 1i32, contact_id as libc::c_int); @@ -1214,18 +1260,17 @@ pub unsafe fn dc_real_contact_exists( } } sqlite3_finalize(stmt); - return ret; + ret } + pub unsafe fn dc_scaleup_contact_origin( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut contact_id: uint32_t, mut origin: libc::c_int, ) { - if context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint { - return; - } let mut stmt: *mut sqlite3_stmt = dc_sqlite3_prepare( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"UPDATE contacts SET origin=? WHERE id=? AND origin>, + pub blobdir: Arc>, + pub sql: Arc>, + pub inbox: Arc>, + pub perform_inbox_jobs_needed: Arc>, + pub probe_imap_network: Arc>, + pub sentbox_thread: Arc>, + pub mvbox_thread: Arc>, + pub smtp: Arc>, + pub smtp_state: Arc<(Mutex, Condvar)>, + pub oauth2_critical: Arc>, pub cb: dc_callback_t, pub os_name: *mut libc::c_char, - pub cmdline_sel_chat_id: uint32_t, - pub bob_expects: libc::c_int, - pub bobs_status: libc::c_int, - pub bobs_qr_scan: *mut dc_lot_t, - pub bobs_qr_critical: pthread_mutex_t, - pub last_smeared_timestamp: time_t, - pub smear_critical: pthread_mutex_t, - pub ongoing_running: libc::c_int, - pub shall_stop_ongoing: libc::c_int, + pub cmdline_sel_chat_id: Arc>, + pub bob: Arc>, + pub last_smeared_timestamp: Arc>, + pub running_state: Arc>, } -unsafe impl Send for dc_context_t {} -unsafe impl Sync for dc_context_t {} +unsafe impl std::marker::Send for dc_context_t {} +unsafe impl std::marker::Sync for dc_context_t {} + +#[derive(Debug)] +pub struct RunningState { + pub ongoing_running: bool, + 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 { + ongoing_running: false, + shall_stop_ongoing: true, + } + } +} + +#[derive(Debug)] +pub struct BobStatus { + pub expects: i32, + pub status: i32, + pub qr_scan: *mut dc_lot_t, +} + +impl Default for BobStatus { + fn default() -> Self { + BobStatus { + expects: 0, + status: 0, + qr_scan: std::ptr::null_mut(), + } + } +} + +#[derive(Default, Debug)] +pub struct SmtpState { + pub idle: bool, + pub suspended: i32, + pub doing_jobs: i32, + pub perform_jobs_needed: i32, + pub probe_network: i32, +} // location handling #[derive(Copy, Clone)] @@ -79,111 +123,70 @@ pub struct _dc_location { } // create/open/config/information -pub unsafe fn dc_context_new( - mut cb: dc_callback_t, - mut userdata: *mut libc::c_void, - mut os_name: *const libc::c_char, -) -> *mut dc_context_t { - let mut context: *mut dc_context_t = 0 as *mut dc_context_t; - context = calloc(1, ::std::mem::size_of::()) as *mut dc_context_t; - if context.is_null() { - exit(23i32); +pub fn dc_context_new( + cb: dc_callback_t, + userdata: *mut libc::c_void, + os_name: *const libc::c_char, +) -> dc_context_t { + dc_context_t { + blobdir: Arc::new(RwLock::new(std::ptr::null_mut())), + dbfile: Arc::new(RwLock::new(std::ptr::null_mut())), + inbox: Arc::new(RwLock::new({ + Imap::new( + cb_get_config, + cb_set_config, + cb_precheck_imf, + cb_receive_imf, + ) + })), + userdata, + cb, + os_name: unsafe { dc_strdup_keep_null(os_name) }, + running_state: Arc::new(RwLock::new(Default::default())), + sql: Arc::new(RwLock::new(dc_sqlite3_new())), + smtp: Arc::new(Mutex::new(Smtp::new())), + smtp_state: Arc::new((Mutex::new(Default::default()), Condvar::new())), + oauth2_critical: Arc::new(Mutex::new(())), + bob: Arc::new(RwLock::new(Default::default())), + last_smeared_timestamp: Arc::new(RwLock::new(0 as time_t)), + cmdline_sel_chat_id: Arc::new(RwLock::new(0)), + sentbox_thread: Arc::new(Mutex::new(unsafe { + dc_jobthread_init( + b"SENTBOX\x00" as *const u8 as *const libc::c_char, + b"configured_sentbox_folder\x00" as *const u8 as *const libc::c_char, + Imap::new( + cb_get_config, + cb_set_config, + cb_precheck_imf, + cb_receive_imf, + ), + ) + })), + mvbox_thread: Arc::new(Mutex::new(unsafe { + dc_jobthread_init( + b"MVBOX\x00" as *const u8 as *const libc::c_char, + b"configured_mvbox_folder\x00" as *const u8 as *const libc::c_char, + Imap::new( + cb_get_config, + cb_set_config, + cb_precheck_imf, + cb_receive_imf, + ), + ) + })), + probe_imap_network: Arc::new(RwLock::new(0)), + perform_inbox_jobs_needed: Arc::new(RwLock::new(0)), } - pthread_mutex_init( - &mut (*context).smear_critical, - 0 as *const pthread_mutexattr_t, - ); - pthread_mutex_init( - &mut (*context).bobs_qr_critical, - 0 as *const pthread_mutexattr_t, - ); - pthread_mutex_init( - &mut (*context).inboxidle_condmutex, - 0 as *const pthread_mutexattr_t, - ); - dc_jobthread_init( - &mut (*context).sentbox_thread, - context, - b"SENTBOX\x00" as *const u8 as *const libc::c_char, - b"configured_sentbox_folder\x00" as *const u8 as *const libc::c_char, - ); - dc_jobthread_init( - &mut (*context).mvbox_thread, - context, - b"MVBOX\x00" as *const u8 as *const libc::c_char, - b"configured_mvbox_folder\x00" as *const u8 as *const libc::c_char, - ); - pthread_mutex_init( - &mut (*context).smtpidle_condmutex, - 0 as *const pthread_mutexattr_t, - ); - pthread_cond_init( - &mut (*context).smtpidle_cond, - 0 as *const pthread_condattr_t, - ); - pthread_mutex_init( - &mut (*context).oauth2_critical, - 0 as *const pthread_mutexattr_t, - ); - (*context).magic = 0x11a11807i32 as uint32_t; - (*context).userdata = userdata; - (*context).cb = cb; - (*context).os_name = dc_strdup_keep_null(os_name); - (*context).shall_stop_ongoing = 1i32; - - dc_pgp_init(); - (*context).sql = dc_sqlite3_new(context); - (*context).inbox = dc_imap_new( - Some(cb_get_config), - Some(cb_set_config), - Some(cb_precheck_imf), - Some(cb_receive_imf), - context as *mut libc::c_void, - context, - ); - (*context).sentbox_thread.imap = dc_imap_new( - Some(cb_get_config), - Some(cb_set_config), - Some(cb_precheck_imf), - Some(cb_receive_imf), - context as *mut libc::c_void, - context, - ); - (*context).mvbox_thread.imap = dc_imap_new( - Some(cb_get_config), - Some(cb_set_config), - Some(cb_precheck_imf), - Some(cb_receive_imf), - context as *mut libc::c_void, - context, - ); - (*context).smtp = dc_smtp_new(context); - /* Random-seed. An additional seed with more random data is done just before key generation - (the timespan between this call and the key generation time is typically random. - Moreover, later, we add a hash of the first message data to the random-seed - (it would be okay to seed with even more sensible data, the seed values cannot be recovered from the PRNG output, see OpenSSL's RAND_seed()) */ - let mut seed: [uintptr_t; 5] = [0; 5]; - seed[0usize] = time(0 as *mut time_t) as uintptr_t; - seed[1usize] = seed.as_mut_ptr() as uintptr_t; - seed[2usize] = context as uintptr_t; - seed[3usize] = pthread_self() as uintptr_t; - seed[4usize] = libc::getpid() as uintptr_t; - dc_pgp_rand_seed( - context, - seed.as_mut_ptr() as *const libc::c_void, - ::std::mem::size_of::<[uintptr_t; 5]>(), - ); - return context; } + unsafe fn cb_receive_imf( - mut imap: *mut dc_imap_t, - mut imf_raw_not_terminated: *const libc::c_char, - mut imf_raw_bytes: size_t, - mut server_folder: *const libc::c_char, - mut server_uid: uint32_t, - mut flags: uint32_t, + context: &dc_context_t, + imf_raw_not_terminated: *const libc::c_char, + imf_raw_bytes: size_t, + server_folder: *const libc::c_char, + server_uid: uint32_t, + flags: uint32_t, ) { - let mut context: *mut dc_context_t = (*imap).userData as *mut dc_context_t; dc_receive_imf( context, imf_raw_not_terminated, @@ -193,19 +196,20 @@ unsafe fn cb_receive_imf( flags, ); } + unsafe fn cb_precheck_imf( - mut imap: *mut dc_imap_t, - mut rfc724_mid: *const libc::c_char, - mut server_folder: *const libc::c_char, - mut server_uid: uint32_t, + context: &dc_context_t, + rfc724_mid: *const libc::c_char, + server_folder: *const libc::c_char, + server_uid: uint32_t, ) -> libc::c_int { let mut rfc724_mid_exists: libc::c_int = 0i32; - let mut msg_id: uint32_t = 0i32 as uint32_t; + let mut msg_id: uint32_t; let mut old_server_folder: *mut libc::c_char = 0 as *mut libc::c_char; let mut old_server_uid: uint32_t = 0i32 as uint32_t; let mut mark_seen: libc::c_int = 0i32; msg_id = dc_rfc724_mid_exists( - (*imap).context, + context, rfc724_mid, &mut old_server_folder, &mut old_server_uid, @@ -216,7 +220,7 @@ unsafe fn cb_precheck_imf( && old_server_uid == 0i32 as libc::c_uint { dc_log_info( - (*imap).context, + context, 0i32, b"[move] detected bbc-self %s\x00" as *const u8 as *const libc::c_char, rfc724_mid, @@ -224,20 +228,20 @@ unsafe fn cb_precheck_imf( mark_seen = 1i32 } else if strcmp(old_server_folder, server_folder) != 0i32 { dc_log_info( - (*imap).context, + context, 0i32, b"[move] detected moved message %s\x00" as *const u8 as *const libc::c_char, rfc724_mid, ); - dc_update_msg_move_state((*imap).context, rfc724_mid, DC_MOVE_STATE_STAY); + dc_update_msg_move_state(context, rfc724_mid, DC_MOVE_STATE_STAY); } if strcmp(old_server_folder, server_folder) != 0i32 || old_server_uid != server_uid { - dc_update_server_uid((*imap).context, rfc724_mid, server_folder, server_uid); + dc_update_server_uid(context, rfc724_mid, server_folder, server_uid); } - dc_do_heuristics_moves((*imap).context, server_folder, msg_id); + dc_do_heuristics_moves(context, server_folder, msg_id); if 0 != mark_seen { dc_job_add( - (*imap).context, + context, 130i32, msg_id as libc::c_int, 0 as *const libc::c_char, @@ -248,14 +252,15 @@ unsafe fn cb_precheck_imf( free(old_server_folder as *mut libc::c_void); return rfc724_mid_exists; } + unsafe fn cb_set_config( - mut imap: *mut dc_imap_t, - mut key: *const libc::c_char, - mut value: *const libc::c_char, + context: &dc_context_t, + key: *const libc::c_char, + value: *const libc::c_char, ) { - let mut context: *mut dc_context_t = (*imap).userData as *mut dc_context_t; - dc_sqlite3_set_config((*context).sql, key, value); + dc_sqlite3_set_config(context, &context.sql.clone().read().unwrap(), key, value); } + /* * * The following three callback are given to dc_imap_new() to read/write configuration * and to handle received messages. As the imap-functions are typically used in @@ -264,144 +269,133 @@ unsafe fn cb_set_config( * @private @memberof dc_context_t */ unsafe fn cb_get_config( - mut imap: *mut dc_imap_t, - mut key: *const libc::c_char, - mut def: *const libc::c_char, + context: &dc_context_t, + key: *const libc::c_char, + def: *const libc::c_char, ) -> *mut libc::c_char { - let mut context: *mut dc_context_t = (*imap).userData as *mut dc_context_t; - return dc_sqlite3_get_config((*context).sql, key, def); + dc_sqlite3_get_config(context, &context.sql.clone().read().unwrap(), key, def) } -pub unsafe fn dc_context_unref(mut context: *mut dc_context_t) { - if context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint { - return; - } - dc_pgp_exit(); +pub unsafe fn dc_context_unref(context: &mut dc_context_t) { if 0 != dc_is_open(context) { dc_close(context); } - dc_imap_unref((*context).inbox); - dc_imap_unref((*context).sentbox_thread.imap); - dc_imap_unref((*context).mvbox_thread.imap); - dc_smtp_unref((*context).smtp); - dc_sqlite3_unref((*context).sql); + dc_sqlite3_unref(context, &mut context.sql.clone().write().unwrap()); - pthread_mutex_destroy(&mut (*context).smear_critical); - pthread_mutex_destroy(&mut (*context).bobs_qr_critical); - pthread_mutex_destroy(&mut (*context).inboxidle_condmutex); - dc_jobthread_exit(&mut (*context).sentbox_thread); - dc_jobthread_exit(&mut (*context).mvbox_thread); - pthread_cond_destroy(&mut (*context).smtpidle_cond); - pthread_mutex_destroy(&mut (*context).smtpidle_condmutex); - pthread_mutex_destroy(&mut (*context).oauth2_critical); - free((*context).os_name as *mut libc::c_void); - (*context).magic = 0i32 as uint32_t; - free(context as *mut libc::c_void); + dc_jobthread_exit(&mut context.sentbox_thread.clone().lock().unwrap()); + dc_jobthread_exit(&mut context.mvbox_thread.clone().lock().unwrap()); + + free(context.os_name as *mut libc::c_void); } -pub unsafe fn dc_close(mut context: *mut dc_context_t) { - if context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint { - return; + +pub unsafe fn dc_close(context: &dc_context_t) { + context.inbox.read().unwrap().disconnect(context); + context + .sentbox_thread + .lock() + .unwrap() + .imap + .disconnect(context); + context + .mvbox_thread + .lock() + .unwrap() + .imap + .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()); } - dc_imap_disconnect((*context).inbox); - dc_imap_disconnect((*context).sentbox_thread.imap); - dc_imap_disconnect((*context).mvbox_thread.imap); - dc_smtp_disconnect((*context).smtp); - if 0 != dc_sqlite3_is_open((*context).sql) { - dc_sqlite3_close((*context).sql); - } - 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(mut context: *const dc_context_t) -> libc::c_int { - if context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint { - return 0i32; - } - return dc_sqlite3_is_open((*context).sql); + +pub unsafe fn dc_is_open(context: &dc_context_t) -> libc::c_int { + dc_sqlite3_is_open(&context.sql.clone().read().unwrap()) } -pub unsafe fn dc_get_userdata(mut context: *mut dc_context_t) -> *mut libc::c_void { - if context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint { - return 0 as *mut libc::c_void; - } - return (*context).userdata; + +pub unsafe fn dc_get_userdata(context: &mut dc_context_t) -> *mut libc::c_void { + context.userdata as *mut _ } + pub unsafe fn dc_open( - mut context: *mut dc_context_t, - mut dbfile: *const libc::c_char, - mut blobdir: *const libc::c_char, + context: &dc_context_t, + dbfile: *const libc::c_char, + blobdir: *const libc::c_char, ) -> libc::c_int { - let mut success: libc::c_int = 0i32; + let mut success = 0; if 0 != dc_is_open(context) { - return 0i32; + return 0; } - if !(context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint || dbfile.is_null()) - { - (*context).dbfile = dc_strdup(dbfile); + if !dbfile.is_null() { + *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).sql, dbfile, 0i32)) { + // Create/open sqlite database, this may already use the blobdir + if !(0 == dc_sqlite3_open(context, &mut context.sql.write().unwrap(), dbfile, 0i32)) { success = 1i32 } } if 0 == success { dc_close(context); } - return success; + success } -pub unsafe fn dc_get_blobdir(mut context: *const dc_context_t) -> *mut libc::c_char { - if context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint { - return dc_strdup(0 as *const libc::c_char); - } - return dc_strdup((*context).blobdir); + +pub unsafe fn dc_get_blobdir(context: &dc_context_t) -> *mut libc::c_char { + dc_strdup(*context.blobdir.clone().read().unwrap()) } + pub unsafe fn dc_set_config( - mut context: *mut dc_context_t, - mut key: *const libc::c_char, - mut value: *const libc::c_char, + context: &dc_context_t, + key: *const libc::c_char, + value: *const libc::c_char, ) -> libc::c_int { - let mut ret: libc::c_int = 0i32; - let mut rel_path: *mut libc::c_char = 0 as *mut libc::c_char; - if context.is_null() - || (*context).magic != 0x11a11807i32 as libc::c_uint - || key.is_null() - || 0 == is_settable_config_key(key) - { - return 0i32; + let mut ret = 0; + let mut rel_path = 0 as *mut libc::c_char; + + if key.is_null() || 0 == is_settable_config_key(key) { + return 0; } - if strcmp(key, b"selfavatar\x00" as *const u8 as *const libc::c_char) == 0i32 - && !value.is_null() - { + if strcmp(key, b"selfavatar\x00" as *const u8 as *const libc::c_char) == 0 && !value.is_null() { rel_path = dc_strdup(value); if !(0 == dc_make_rel_and_copy(context, &mut rel_path)) { - ret = dc_sqlite3_set_config((*context).sql, key, rel_path) + ret = + dc_sqlite3_set_config(context, &context.sql.clone().read().unwrap(), key, rel_path) } - } else if strcmp(key, b"inbox_watch\x00" as *const u8 as *const libc::c_char) == 0i32 { - ret = dc_sqlite3_set_config((*context).sql, key, value); + } else if strcmp(key, b"inbox_watch\x00" as *const u8 as *const libc::c_char) == 0 { + ret = dc_sqlite3_set_config(context, &context.sql.clone().read().unwrap(), key, value); dc_interrupt_imap_idle(context); } else if strcmp( key, b"sentbox_watch\x00" as *const u8 as *const libc::c_char, - ) == 0i32 + ) == 0 { - ret = dc_sqlite3_set_config((*context).sql, key, value); + ret = dc_sqlite3_set_config(context, &context.sql.clone().read().unwrap(), key, value); dc_interrupt_sentbox_idle(context); - } else if strcmp(key, b"mvbox_watch\x00" as *const u8 as *const libc::c_char) == 0i32 { - ret = dc_sqlite3_set_config((*context).sql, key, value); + } else if strcmp(key, b"mvbox_watch\x00" as *const u8 as *const libc::c_char) == 0 { + ret = dc_sqlite3_set_config(context, &context.sql.clone().read().unwrap(), key, value); dc_interrupt_mvbox_idle(context); - } else if strcmp(key, b"selfstatus\x00" as *const u8 as *const libc::c_char) == 0i32 { - let mut def: *mut libc::c_char = dc_stock_str(context, 13i32); + } else if strcmp(key, b"selfstatus\x00" as *const u8 as *const libc::c_char) == 0 { + let mut def = dc_stock_str(context, 13); ret = dc_sqlite3_set_config( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), key, - if value.is_null() || strcmp(value, def) == 0i32 { + if value.is_null() || strcmp(value, def) == 0 { 0 as *const libc::c_char } else { value @@ -409,27 +403,30 @@ pub unsafe fn dc_set_config( ); free(def as *mut libc::c_void); } else { - ret = dc_sqlite3_set_config((*context).sql, key, value) + ret = dc_sqlite3_set_config(context, &context.sql.clone().read().unwrap(), key, value); } free(rel_path as *mut libc::c_void); - return ret; + ret } + /* ****************************************************************************** * INI-handling, Information ******************************************************************************/ -unsafe fn is_settable_config_key(mut key: *const libc::c_char) -> libc::c_int { + +unsafe fn is_settable_config_key(key: *const libc::c_char) -> libc::c_int { let mut i = 0; while i < (::std::mem::size_of::<[*const libc::c_char; 33]>()) .wrapping_div(::std::mem::size_of::<*mut libc::c_char>()) { - if strcmp(key, config_keys[i as usize]) == 0i32 { - return 1i32; + if strcmp(key, config_keys[i as usize]) == 0 { + return 1; } i += 1 } - return 0i32; + 0 } + static mut config_keys: [*const libc::c_char; 33] = [ b"addr\x00" as *const u8 as *const libc::c_char, b"mail_server\x00" as *const u8 as *const libc::c_char, @@ -465,11 +462,9 @@ static mut config_keys: [*const libc::c_char; 33] = [ b"configured_server_flags\x00" as *const u8 as *const libc::c_char, b"configured\x00" as *const u8 as *const libc::c_char, ]; -pub unsafe fn dc_get_config( - mut context: *mut dc_context_t, - mut key: *const libc::c_char, -) -> *mut libc::c_char { - let mut value: *mut libc::c_char = 0 as *mut libc::c_char; + +pub unsafe fn dc_get_config(context: &dc_context_t, key: *const libc::c_char) -> *mut libc::c_char { + let mut value = 0 as *mut libc::c_char; if !key.is_null() && *key.offset(0isize) as libc::c_int == 's' as i32 && *key.offset(1isize) as libc::c_int == 'y' as i32 @@ -478,101 +473,116 @@ pub unsafe fn dc_get_config( { return get_sys_config_str(key); } - if context.is_null() - || (*context).magic != 0x11a11807i32 as libc::c_uint - || key.is_null() - || 0 == is_gettable_config_key(key) - { + + if key.is_null() || 0 == is_gettable_config_key(key) { return dc_strdup(b"\x00" as *const u8 as *const libc::c_char); } - if strcmp(key, b"selfavatar\x00" as *const u8 as *const libc::c_char) == 0i32 { - let mut rel_path: *mut libc::c_char = - dc_sqlite3_get_config((*context).sql, key, 0 as *const libc::c_char); + + if strcmp(key, b"selfavatar\x00" as *const u8 as *const libc::c_char) == 0 { + let mut rel_path: *mut libc::c_char = dc_sqlite3_get_config( + context, + &context.sql.clone().read().unwrap(), + key, + 0 as *const libc::c_char, + ); if !rel_path.is_null() { value = dc_get_abs_path(context, rel_path); free(rel_path as *mut libc::c_void); } } else { - value = dc_sqlite3_get_config((*context).sql, key, 0 as *const libc::c_char) + value = dc_sqlite3_get_config( + context, + &context.sql.clone().read().unwrap(), + key, + 0 as *const libc::c_char, + ) } + if value.is_null() { - if strcmp(key, b"e2ee_enabled\x00" as *const u8 as *const libc::c_char) == 0i32 { - value = dc_mprintf(b"%i\x00" as *const u8 as *const libc::c_char, 1i32) - } else if strcmp(key, b"mdns_enabled\x00" as *const u8 as *const libc::c_char) == 0i32 { - value = dc_mprintf(b"%i\x00" as *const u8 as *const libc::c_char, 1i32) - } else if strcmp(key, b"imap_folder\x00" as *const u8 as *const libc::c_char) == 0i32 { + if strcmp(key, b"e2ee_enabled\x00" as *const u8 as *const libc::c_char) == 0 { + value = dc_mprintf(b"%i\x00" as *const u8 as *const libc::c_char, 1) + } else if strcmp(key, b"mdns_enabled\x00" as *const u8 as *const libc::c_char) == 0 { + value = dc_mprintf(b"%i\x00" as *const u8 as *const libc::c_char, 1) + } else if strcmp(key, b"imap_folder\x00" as *const u8 as *const libc::c_char) == 0 { value = dc_strdup(b"INBOX\x00" as *const u8 as *const libc::c_char) - } else if strcmp(key, b"inbox_watch\x00" as *const u8 as *const libc::c_char) == 0i32 { - value = dc_mprintf(b"%i\x00" as *const u8 as *const libc::c_char, 1i32) + } else if strcmp(key, b"inbox_watch\x00" as *const u8 as *const libc::c_char) == 0 { + value = dc_mprintf(b"%i\x00" as *const u8 as *const libc::c_char, 1) } else if strcmp( key, b"sentbox_watch\x00" as *const u8 as *const libc::c_char, - ) == 0i32 + ) == 0 { - value = dc_mprintf(b"%i\x00" as *const u8 as *const libc::c_char, 1i32) - } else if strcmp(key, b"mvbox_watch\x00" as *const u8 as *const libc::c_char) == 0i32 { - value = dc_mprintf(b"%i\x00" as *const u8 as *const libc::c_char, 1i32) - } else if strcmp(key, b"mvbox_move\x00" as *const u8 as *const libc::c_char) == 0i32 { - value = dc_mprintf(b"%i\x00" as *const u8 as *const libc::c_char, 1i32) - } else if strcmp(key, b"show_emails\x00" as *const u8 as *const libc::c_char) == 0i32 { - value = dc_mprintf(b"%i\x00" as *const u8 as *const libc::c_char, 0i32) - } else if strcmp(key, b"selfstatus\x00" as *const u8 as *const libc::c_char) == 0i32 { - value = dc_stock_str(context, 13i32) + value = dc_mprintf(b"%i\x00" as *const u8 as *const libc::c_char, 1) + } else if strcmp(key, b"mvbox_watch\x00" as *const u8 as *const libc::c_char) == 0 { + value = dc_mprintf(b"%i\x00" as *const u8 as *const libc::c_char, 1) + } else if strcmp(key, b"mvbox_move\x00" as *const u8 as *const libc::c_char) == 0 { + value = dc_mprintf(b"%i\x00" as *const u8 as *const libc::c_char, 1) + } else if strcmp(key, b"show_emails\x00" as *const u8 as *const libc::c_char) == 0 { + value = dc_mprintf(b"%i\x00" as *const u8 as *const libc::c_char, 0) + } else if strcmp(key, b"selfstatus\x00" as *const u8 as *const libc::c_char) == 0 { + value = dc_stock_str(context, 13) } else { value = dc_mprintf(b"\x00" as *const u8 as *const libc::c_char) } } - return value; + + value } -unsafe fn is_gettable_config_key(mut key: *const libc::c_char) -> libc::c_int { + +unsafe fn is_gettable_config_key(key: *const libc::c_char) -> libc::c_int { let mut i = 0; while i < (::std::mem::size_of::<[*const libc::c_char; 3]>()) .wrapping_div(::std::mem::size_of::<*mut libc::c_char>()) { - if strcmp(key, sys_config_keys[i as usize]) == 0i32 { - return 1i32; + if strcmp(key, sys_config_keys[i as usize]) == 0 { + return 1; } i += 1 } - return is_settable_config_key(key); + + is_settable_config_key(key) } + // deprecated static mut sys_config_keys: [*const libc::c_char; 3] = [ b"sys.version\x00" as *const u8 as *const libc::c_char, b"sys.msgsize_max_recommended\x00" as *const u8 as *const libc::c_char, b"sys.config_keys\x00" as *const u8 as *const libc::c_char, ]; -unsafe fn get_sys_config_str(mut key: *const libc::c_char) -> *mut libc::c_char { - if strcmp(key, b"sys.version\x00" as *const u8 as *const libc::c_char) == 0i32 { + +unsafe fn get_sys_config_str(key: *const libc::c_char) -> *mut libc::c_char { + if strcmp(key, b"sys.version\x00" as *const u8 as *const libc::c_char) == 0 { return dc_strdup(VERSION as *const u8 as *const libc::c_char); } else if strcmp( key, b"sys.msgsize_max_recommended\x00" as *const u8 as *const libc::c_char, - ) == 0i32 + ) == 0 { return dc_mprintf( b"%i\x00" as *const u8 as *const libc::c_char, - 24i32 * 1024i32 * 1024i32 / 4i32 * 3i32, + 24 * 1024 * 1024 / 4 * 3, ); } else if strcmp( key, b"sys.config_keys\x00" as *const u8 as *const libc::c_char, - ) == 0i32 + ) == 0 { return get_config_keys_str(); } else { return dc_strdup(0 as *const libc::c_char); }; } + unsafe fn get_config_keys_str() -> *mut libc::c_char { - let mut ret: dc_strbuilder_t = dc_strbuilder_t { - buf: 0 as *mut libc::c_char, + let mut ret = dc_strbuilder_t { + buf: std::ptr::null_mut(), allocated: 0, free: 0, - eos: 0 as *mut libc::c_char, + eos: std::ptr::null_mut(), }; - dc_strbuilder_init(&mut ret, 0i32); + dc_strbuilder_init(&mut ret, 0); + let mut i = 0; while i < (::std::mem::size_of::<[*const libc::c_char; 33]>()) @@ -584,72 +594,75 @@ unsafe fn get_config_keys_str() -> *mut libc::c_char { dc_strbuilder_cat(&mut ret, config_keys[i as usize]); i += 1 } - let mut i_0 = 0; - while i_0 + + let mut i = 0; + while i < (::std::mem::size_of::<[*const libc::c_char; 3]>()) .wrapping_div(::std::mem::size_of::<*mut libc::c_char>()) { if strlen(ret.buf) > 0 { dc_strbuilder_cat(&mut ret, b" \x00" as *const u8 as *const libc::c_char); } - dc_strbuilder_cat(&mut ret, sys_config_keys[i_0 as usize]); - i_0 += 1 + dc_strbuilder_cat(&mut ret, sys_config_keys[i as usize]); + i += 1 } - return ret.buf; + + ret.buf } -pub unsafe fn dc_get_info(mut context: *mut dc_context_t) -> *mut libc::c_char { - let mut unset: *const libc::c_char = b"0\x00" as *const u8 as *const libc::c_char; - let mut displayname: *mut libc::c_char = 0 as *mut libc::c_char; - let mut temp: *mut libc::c_char = 0 as *mut libc::c_char; - let mut l_readable_str: *mut libc::c_char = 0 as *mut libc::c_char; - let mut l2_readable_str: *mut libc::c_char = 0 as *mut libc::c_char; - let mut fingerprint_str: *mut libc::c_char = 0 as *mut libc::c_char; - let mut l: *mut dc_loginparam_t = 0 as *mut dc_loginparam_t; - let mut l2: *mut dc_loginparam_t = 0 as *mut dc_loginparam_t; - let mut inbox_watch: libc::c_int = 0i32; - let mut sentbox_watch: libc::c_int = 0i32; - let mut mvbox_watch: libc::c_int = 0i32; - let mut mvbox_move: libc::c_int = 0i32; - let mut folders_configured: libc::c_int = 0i32; - let mut configured_sentbox_folder: *mut libc::c_char = 0 as *mut libc::c_char; - let mut configured_mvbox_folder: *mut libc::c_char = 0 as *mut libc::c_char; - let mut contacts: libc::c_int = 0i32; - let mut chats: libc::c_int = 0i32; - let mut real_msgs: libc::c_int = 0i32; - let mut deaddrop_msgs: libc::c_int = 0i32; - let mut is_configured: libc::c_int = 0i32; - let mut dbversion: libc::c_int = 0i32; - let mut mdns_enabled: libc::c_int = 0i32; - let mut e2ee_enabled: libc::c_int = 0i32; - let mut prv_key_cnt: libc::c_int = 0i32; - let mut pub_key_cnt: libc::c_int = 0i32; - let mut self_public: *mut dc_key_t = dc_key_new(); - let mut rpgp_enabled: libc::c_int = 0i32; - rpgp_enabled = 1i32; - let mut ret: dc_strbuilder_t = dc_strbuilder_t { + +pub unsafe fn dc_get_info(context: &dc_context_t) -> *mut libc::c_char { + let mut unset = b"0\x00" as *const u8 as *const libc::c_char; + let mut displayname; + let mut temp; + let mut l_readable_str; + let mut l2_readable_str; + let mut fingerprint_str; + let mut l; + let mut l2; + let mut inbox_watch; + let mut sentbox_watch; + let mut mvbox_watch; + let mut mvbox_move; + let mut folders_configured; + let mut configured_sentbox_folder; + let mut configured_mvbox_folder; + let mut contacts; + let mut chats; + let mut real_msgs; + let mut deaddrop_msgs; + let mut is_configured; + let mut dbversion; + let mut mdns_enabled; + let mut e2ee_enabled; + let mut prv_key_cnt; + let mut pub_key_cnt; + let mut self_public = dc_key_new(); + let mut rpgp_enabled = 1; + + let mut ret = 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 ret, 0i32); - if context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint { - return dc_strdup(b"ErrBadPtr\x00" as *const u8 as *const libc::c_char); - } + dc_strbuilder_init(&mut ret, 0); l = dc_loginparam_new(); l2 = dc_loginparam_new(); dc_loginparam_read( + context, l, - (*context).sql, + &context.sql.clone().read().unwrap(), b"\x00" as *const u8 as *const libc::c_char, ); dc_loginparam_read( + context, l2, - (*context).sql, + &context.sql.clone().read().unwrap(), b"configured_\x00" as *const u8 as *const libc::c_char, ); displayname = dc_sqlite3_get_config( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"displayname\x00" as *const u8 as *const libc::c_char, 0 as *const libc::c_char, ); @@ -658,78 +671,96 @@ pub unsafe fn dc_get_info(mut context: *mut dc_context_t) -> *mut libc::c_char { deaddrop_msgs = dc_get_deaddrop_msg_cnt(context) as libc::c_int; contacts = dc_get_real_contact_cnt(context) as libc::c_int; is_configured = dc_sqlite3_get_config_int( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"configured\x00" as *const u8 as *const libc::c_char, - 0i32, + 0, ); dbversion = dc_sqlite3_get_config_int( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"dbversion\x00" as *const u8 as *const libc::c_char, - 0i32, + 0, ); e2ee_enabled = dc_sqlite3_get_config_int( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"e2ee_enabled\x00" as *const u8 as *const libc::c_char, - 1i32, + 1, ); mdns_enabled = dc_sqlite3_get_config_int( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"mdns_enabled\x00" as *const u8 as *const libc::c_char, - 1i32, + 1, ); let mut stmt: *mut sqlite3_stmt = dc_sqlite3_prepare( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"SELECT COUNT(*) FROM keypairs;\x00" as *const u8 as *const libc::c_char, ); sqlite3_step(stmt); - prv_key_cnt = sqlite3_column_int(stmt, 0i32); + prv_key_cnt = sqlite3_column_int(stmt, 0); sqlite3_finalize(stmt); stmt = dc_sqlite3_prepare( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"SELECT COUNT(*) FROM acpeerstates;\x00" as *const u8 as *const libc::c_char, ); sqlite3_step(stmt); - pub_key_cnt = sqlite3_column_int(stmt, 0i32); + pub_key_cnt = sqlite3_column_int(stmt, 0); sqlite3_finalize(stmt); - if 0 != dc_key_load_self_public(self_public, (*l2).addr, (*context).sql) { - fingerprint_str = dc_key_get_fingerprint(self_public) + if 0 != dc_key_load_self_public( + context, + self_public, + (*l2).addr, + &context.sql.clone().read().unwrap(), + ) { + fingerprint_str = dc_key_get_fingerprint(context, self_public) } else { fingerprint_str = dc_strdup(b"\x00" as *const u8 as *const libc::c_char) } l_readable_str = dc_loginparam_get_readable(l); l2_readable_str = dc_loginparam_get_readable(l2); inbox_watch = dc_sqlite3_get_config_int( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"inbox_watch\x00" as *const u8 as *const libc::c_char, - 1i32, + 1, ); sentbox_watch = dc_sqlite3_get_config_int( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"sentbox_watch\x00" as *const u8 as *const libc::c_char, - 1i32, + 1, ); mvbox_watch = dc_sqlite3_get_config_int( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"mvbox_watch\x00" as *const u8 as *const libc::c_char, - 1i32, + 1, ); mvbox_move = dc_sqlite3_get_config_int( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"mvbox_move\x00" as *const u8 as *const libc::c_char, - 1i32, + 1, ); folders_configured = dc_sqlite3_get_config_int( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"folders_configured\x00" as *const u8 as *const libc::c_char, - 0i32, + 0, ); configured_sentbox_folder = dc_sqlite3_get_config( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"configured_sentbox_folder\x00" as *const u8 as *const libc::c_char, b"\x00" as *const u8 as *const libc::c_char, ); configured_mvbox_folder = dc_sqlite3_get_config( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"configured_mvbox_folder\x00" as *const u8 as *const libc::c_char, b"\x00" as *const u8 as *const libc::c_char, ); @@ -769,8 +800,9 @@ pub unsafe fn dc_get_info(mut context: *mut dc_context_t) -> *mut libc::c_char { VERSION as *const u8 as *const libc::c_char, libsqlite3_sys::SQLITE_VERSION as *const u8 as *const libc::c_char, sqlite3_threadsafe(), - libetpan_get_version_major(), - libetpan_get_version_minor(), + // no libetpan + 0, + 0, // openssl (none used, so setting to 0) 0 as libc::c_int, 0 as libc::c_int, @@ -783,14 +815,14 @@ pub unsafe fn dc_get_info(mut context: *mut 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 }, @@ -827,51 +859,58 @@ pub unsafe fn dc_get_info(mut context: *mut dc_context_t) -> *mut libc::c_char { free(configured_mvbox_folder as *mut libc::c_void); free(fingerprint_str as *mut libc::c_void); dc_key_unref(self_public); - return ret.buf; + + ret.buf } + pub unsafe fn dc_get_version_str() -> *mut libc::c_char { - return dc_strdup(VERSION as *const u8 as *const libc::c_char); + dc_strdup(VERSION as *const u8 as *const libc::c_char) } -pub unsafe fn dc_get_fresh_msgs(mut context: *mut dc_context_t) -> *mut dc_array_t { - let mut show_deaddrop: libc::c_int = 0i32; - let mut ret: *mut dc_array_t = dc_array_new(context, 128i32 as size_t); - let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; - if !(context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint || ret.is_null()) { - stmt = - dc_sqlite3_prepare((*context).sql, - b"SELECT m.id FROM msgs m LEFT JOIN contacts ct ON m.from_id=ct.id LEFT JOIN chats c ON m.chat_id=c.id WHERE m.state=? AND m.hidden=0 AND m.chat_id>? AND ct.blocked=0 AND (c.blocked=0 OR c.blocked=?) ORDER BY m.timestamp DESC,m.id DESC;\x00" - as *const u8 as *const libc::c_char); - sqlite3_bind_int(stmt, 1i32, 10i32); - sqlite3_bind_int(stmt, 2i32, 9i32); - sqlite3_bind_int(stmt, 3i32, if 0 != show_deaddrop { 2i32 } else { 0i32 }); - while sqlite3_step(stmt) == 100i32 { - dc_array_add_id(ret, sqlite3_column_int(stmt, 0i32) as uint32_t); + +pub unsafe fn dc_get_fresh_msgs(context: &dc_context_t) -> *mut dc_array_t { + let mut show_deaddrop = 0; + let mut ret = dc_array_new(128 as size_t); + let mut stmt = 0 as *mut sqlite3_stmt; + if !ret.is_null() { + stmt = dc_sqlite3_prepare( + context, + &context.sql.clone().read().unwrap(), + b"SELECT m.id FROM msgs m LEFT JOIN contacts ct \ + ON m.from_id=ct.id LEFT JOIN chats c ON m.chat_id=c.id WHERE m.state=? \ + AND m.hidden=0 \ + AND m.chat_id>? \ + AND ct.blocked=0 \ + AND (c.blocked=0 OR c.blocked=?) ORDER BY m.timestamp DESC,m.id DESC;\x00" + as *const u8 as *const libc::c_char, + ); + sqlite3_bind_int(stmt, 1, 10); + sqlite3_bind_int(stmt, 2, 9); + sqlite3_bind_int(stmt, 3, if 0 != show_deaddrop { 2 } else { 0 }); + while sqlite3_step(stmt) == 100 { + dc_array_add_id(ret, sqlite3_column_int(stmt, 0) as uint32_t); } } sqlite3_finalize(stmt); - return ret; + ret } + pub unsafe fn dc_search_msgs( - mut context: *mut dc_context_t, - mut chat_id: uint32_t, - mut query: *const libc::c_char, + context: &dc_context_t, + chat_id: uint32_t, + query: *const libc::c_char, ) -> *mut dc_array_t { - //clock_t start = clock(); - let mut success: libc::c_int = 0i32; - let mut ret: *mut dc_array_t = dc_array_new(context, 100i32 as size_t); - let mut strLikeInText: *mut libc::c_char = 0 as *mut libc::c_char; - let mut strLikeBeg: *mut libc::c_char = 0 as *mut libc::c_char; - let mut real_query: *mut libc::c_char = 0 as *mut libc::c_char; - let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; - if !(context.is_null() - || (*context).magic != 0x11a11807i32 as libc::c_uint - || ret.is_null() - || query.is_null()) - { + let mut success = 0; + let mut ret = dc_array_new(100 as size_t); + let mut strLikeInText = 0 as *mut libc::c_char; + let mut strLikeBeg = 0 as *mut libc::c_char; + let mut real_query = 0 as *mut libc::c_char; + let mut stmt = 0 as *mut sqlite3_stmt; + + if !(ret.is_null() || query.is_null()) { real_query = dc_strdup(query); dc_trim(real_query); - if *real_query.offset(0isize) as libc::c_int == 0i32 { - success = 1i32 + if *real_query.offset(0isize) as libc::c_int == 0 { + success = 1 } else { strLikeInText = dc_mprintf( b"%%%s%%\x00" as *const u8 as *const libc::c_char, @@ -879,100 +918,110 @@ pub unsafe fn dc_search_msgs( ); strLikeBeg = dc_mprintf(b"%s%%\x00" as *const u8 as *const libc::c_char, real_query); if 0 != chat_id { - stmt = - dc_sqlite3_prepare((*context).sql, - b"SELECT m.id, m.timestamp FROM msgs m LEFT JOIN contacts ct ON m.from_id=ct.id WHERE m.chat_id=? AND m.hidden=0 AND ct.blocked=0 AND (txt LIKE ? OR ct.name LIKE ?) ORDER BY m.timestamp,m.id;\x00" - as *const u8 as - *const libc::c_char); - sqlite3_bind_int(stmt, 1i32, chat_id as libc::c_int); - sqlite3_bind_text(stmt, 2i32, strLikeInText, -1i32, None); - sqlite3_bind_text(stmt, 3i32, strLikeBeg, -1i32, None); + stmt = dc_sqlite3_prepare( + context, + &context.sql.clone().read().unwrap(), + b"SELECT m.id, m.timestamp FROM msgs m LEFT JOIN contacts ct ON m.from_id=ct.id WHERE m.chat_id=? \ + AND m.hidden=0 \ + AND ct.blocked=0 AND (txt LIKE ? OR ct.name LIKE ?) ORDER BY m.timestamp,m.id;\x00" + as *const u8 as *const libc::c_char + ); + sqlite3_bind_int(stmt, 1, chat_id as libc::c_int); + sqlite3_bind_text(stmt, 2, strLikeInText, -1, None); + sqlite3_bind_text(stmt, 3, strLikeBeg, -1, None); } else { - let mut show_deaddrop: libc::c_int = 0i32; - stmt = - dc_sqlite3_prepare((*context).sql, - b"SELECT m.id, m.timestamp FROM msgs m LEFT JOIN contacts ct ON m.from_id=ct.id LEFT JOIN chats c ON m.chat_id=c.id WHERE m.chat_id>9 AND m.hidden=0 AND (c.blocked=0 OR c.blocked=?) AND ct.blocked=0 AND (m.txt LIKE ? OR ct.name LIKE ?) ORDER BY m.timestamp DESC,m.id DESC;\x00" - as *const u8 as - *const libc::c_char); - sqlite3_bind_int(stmt, 1i32, if 0 != show_deaddrop { 2i32 } else { 0i32 }); - sqlite3_bind_text(stmt, 2i32, strLikeInText, -1i32, None); - sqlite3_bind_text(stmt, 3i32, strLikeBeg, -1i32, None); + let mut show_deaddrop = 0; + stmt = dc_sqlite3_prepare( + context, + &context.sql.clone().read().unwrap(), + b"SELECT m.id, m.timestamp FROM msgs m LEFT JOIN contacts ct ON m.from_id=ct.id \ + LEFT JOIN chats c ON m.chat_id=c.id WHERE m.chat_id>9 AND m.hidden=0 \ + AND (c.blocked=0 OR c.blocked=?) \ + AND ct.blocked=0 AND (m.txt LIKE ? OR ct.name LIKE ?) ORDER BY m.timestamp DESC,m.id DESC;\x00" + as *const u8 as *const libc::c_char + ); + sqlite3_bind_int(stmt, 1, if 0 != show_deaddrop { 2 } else { 0 }); + sqlite3_bind_text(stmt, 2, strLikeInText, -1, None); + sqlite3_bind_text(stmt, 3, strLikeBeg, -1, None); } - while sqlite3_step(stmt) == 100i32 { - dc_array_add_id(ret, sqlite3_column_int(stmt, 0i32) as uint32_t); + while sqlite3_step(stmt) == 100 { + dc_array_add_id(ret, sqlite3_column_int(stmt, 0) as uint32_t); } - success = 1i32 + success = 1 } } + free(strLikeInText as *mut libc::c_void); free(strLikeBeg as *mut libc::c_void); free(real_query as *mut libc::c_void); sqlite3_finalize(stmt); + if 0 != success { - return ret; + ret } else { if !ret.is_null() { dc_array_unref(ret); } - return 0 as *mut dc_array_t; - }; + 0 as *mut dc_array_t + } } pub unsafe fn dc_is_inbox( - _context: *mut dc_context_t, + _context: &dc_context_t, folder_name: *const libc::c_char, ) -> libc::c_int { - let mut is_inbox: libc::c_int = 0i32; + let mut is_inbox = 0; if !folder_name.is_null() { is_inbox = if strcasecmp( b"INBOX\x00" as *const u8 as *const libc::c_char, folder_name, - ) == 0i32 + ) == 0 { - 1i32 + 1 } else { - 0i32 + 0 } } - return is_inbox; + is_inbox } + pub unsafe fn dc_is_sentbox( - mut context: *mut dc_context_t, - mut folder_name: *const libc::c_char, + context: &dc_context_t, + folder_name: *const libc::c_char, ) -> libc::c_int { - let mut sentbox_name: *mut libc::c_char = dc_sqlite3_get_config( - (*context).sql, + let mut sentbox_name = dc_sqlite3_get_config( + context, + &context.sql.clone().read().unwrap(), b"configured_sentbox_folder\x00" as *const u8 as *const libc::c_char, 0 as *const libc::c_char, ); - let mut is_sentbox: libc::c_int = 0i32; + let mut is_sentbox = 0; if !sentbox_name.is_null() && !folder_name.is_null() { - is_sentbox = if strcasecmp(sentbox_name, folder_name) == 0i32 { - 1i32 + is_sentbox = if strcasecmp(sentbox_name, folder_name) == 0 { + 1 } else { - 0i32 + 0 } } free(sentbox_name as *mut libc::c_void); - return is_sentbox; + is_sentbox } -pub unsafe fn dc_is_mvbox( - mut context: *mut dc_context_t, - mut folder_name: *const libc::c_char, -) -> libc::c_int { - let mut mvbox_name: *mut libc::c_char = dc_sqlite3_get_config( - (*context).sql, + +pub unsafe fn dc_is_mvbox(context: &dc_context_t, folder_name: *const libc::c_char) -> libc::c_int { + let mut mvbox_name = dc_sqlite3_get_config( + context, + &context.sql.clone().read().unwrap(), b"configured_mvbox_folder\x00" as *const u8 as *const libc::c_char, 0 as *const libc::c_char, ); - let mut is_mvbox: libc::c_int = 0i32; + let mut is_mvbox = 0; if !mvbox_name.is_null() && !folder_name.is_null() { - is_mvbox = if strcasecmp(mvbox_name, folder_name) == 0i32 { - 1i32 + is_mvbox = if strcasecmp(mvbox_name, folder_name) == 0 { + 1 } else { - 0i32 + 0 } } free(mvbox_name as *mut libc::c_void); - return is_mvbox; + is_mvbox } diff --git a/src/dc_dehtml.rs b/src/dc_dehtml.rs index 082063a0d..dd270dacc 100644 --- a/src/dc_dehtml.rs +++ b/src/dc_dehtml.rs @@ -1,5 +1,3 @@ -use libc; - use crate::dc_saxparser::*; use crate::dc_strbuilder::*; use crate::dc_tools::*; diff --git a/src/dc_e2ee.rs b/src/dc_e2ee.rs index e0a80fa0b..d6e5ac0ea 100644 --- a/src/dc_e2ee.rs +++ b/src/dc_e2ee.rs @@ -1,4 +1,15 @@ -use libc; +use mmime::clist::*; +use mmime::mailimf::*; +use mmime::mailimf_types::*; +use mmime::mailimf_types_helper::*; +use mmime::mailmime::*; +use mmime::mailmime_content::*; +use mmime::mailmime_types::*; +use mmime::mailmime_types_helper::*; +use mmime::mailmime_write_mem::*; +use mmime::mailprivacy_prepare_mime; +use mmime::mmapstring::*; +use mmime::{mailmime_substitute, MAILIMF_NO_ERROR, MAIL_NO_ERROR}; use crate::dc_aheader::*; use crate::dc_apeerstate::*; @@ -33,7 +44,7 @@ pub struct dc_e2ee_helper_t { } pub unsafe fn dc_e2ee_encrypt( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut recipients_addr: *const clist, mut force_unencrypted: libc::c_int, mut e2ee_guaranteed: libc::c_int, @@ -42,19 +53,19 @@ pub unsafe fn dc_e2ee_encrypt( mut in_out_message: *mut mailmime, mut helper: *mut dc_e2ee_helper_t, ) { - let mut p_0: *mut libc::c_char = 0 as *mut libc::c_char; + let mut p_0: *mut libc::c_char; let mut current_block: u64; let mut col: libc::c_int = 0i32; let mut do_encrypt: libc::c_int = 0i32; let mut autocryptheader: *mut dc_aheader_t = dc_aheader_new(); /*just a pointer into mailmime structure, must not be freed*/ - let mut imffields_unprotected: *mut mailimf_fields = 0 as *mut mailimf_fields; + let mut imffields_unprotected: *mut mailimf_fields; let mut keyring: *mut dc_keyring_t = dc_keyring_new(); let mut sign_key: *mut dc_key_t = dc_key_new(); let mut plain: *mut MMAPString = mmap_string_new(b"\x00" as *const u8 as *const libc::c_char); let mut ctext: *mut libc::c_char = 0 as *mut libc::c_char; let mut ctext_bytes: size_t = 0i32 as size_t; - let mut peerstates: *mut dc_array_t = dc_array_new(0 as *mut dc_context_t, 10i32 as size_t); + let mut peerstates = dc_array_new(10i32 as size_t); if !helper.is_null() { memset( helper as *mut libc::c_void, @@ -62,9 +73,7 @@ pub unsafe fn dc_e2ee_encrypt( ::std::mem::size_of::(), ); } - if !(context.is_null() - || (*context).magic != 0x11a11807i32 as libc::c_uint - || recipients_addr.is_null() + if !(recipients_addr.is_null() || in_out_message.is_null() || !(*in_out_message).mm_parent.is_null() || autocryptheader.is_null() @@ -76,14 +85,16 @@ pub unsafe fn dc_e2ee_encrypt( /* libEtPan's pgp_encrypt_mime() takes the parent as the new root. We just expect the root as being given to this function. */ (*autocryptheader).prefer_encrypt = 0i32; if 0 != dc_sqlite3_get_config_int( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"e2ee_enabled\x00" as *const u8 as *const libc::c_char, 1i32, ) { (*autocryptheader).prefer_encrypt = 1i32 } (*autocryptheader).addr = dc_sqlite3_get_config( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"configured_addr\x00" as *const u8 as *const libc::c_char, 0 as *const libc::c_char, ); @@ -99,7 +110,7 @@ pub unsafe fn dc_e2ee_encrypt( /*only for random-seed*/ if (*autocryptheader).prefer_encrypt == 1i32 || 0 != e2ee_guaranteed { do_encrypt = 1i32; - let mut iter1: *mut clistiter = 0 as *mut clistiter; + let mut iter1: *mut clistiter; iter1 = (*recipients_addr).first; while !iter1.is_null() { let mut recipient_addr: *const libc::c_char = (if !iter1.is_null() { @@ -113,7 +124,7 @@ pub unsafe fn dc_e2ee_encrypt( if !(strcasecmp(recipient_addr, (*autocryptheader).addr) == 0i32) { if 0 != dc_apeerstate_load_by_addr( peerstate, - (*context).sql, + &context.sql.clone().read().unwrap(), recipient_addr, ) && { key_to_use = dc_apeerstate_peek_key(peerstate, min_verified); @@ -132,16 +143,17 @@ pub unsafe fn dc_e2ee_encrypt( iter1 = if !iter1.is_null() { (*iter1).next } else { - 0 as *mut clistcell_s + 0 as *mut clistcell } } } if 0 != do_encrypt { dc_keyring_add(keyring, (*autocryptheader).public_key); if 0 == dc_key_load_self_private( + context, sign_key, (*autocryptheader).addr, - (*context).sql, + &context.sql.clone().read().unwrap(), ) { do_encrypt = 0i32 } @@ -247,7 +259,7 @@ pub unsafe fn dc_e2ee_encrypt( cur = if !cur.is_null() { (*cur).next } else { - 0 as *mut clistcell_s + 0 as *mut clistcell } } } @@ -393,7 +405,8 @@ pub unsafe fn dc_e2ee_encrypt( } dc_array_unref(peerstates); } -/* ****************************************************************************** + +/******************************************************************************* * Tools ******************************************************************************/ unsafe fn new_data_part( @@ -404,15 +417,15 @@ unsafe fn new_data_part( ) -> *mut mailmime { let mut current_block: u64; //char basename_buf[PATH_MAX]; - let mut encoding: *mut mailmime_mechanism = 0 as *mut mailmime_mechanism; - let mut content: *mut mailmime_content = 0 as *mut mailmime_content; - let mut mime: *mut mailmime = 0 as *mut mailmime; + let mut encoding: *mut mailmime_mechanism; + let mut content: *mut mailmime_content; + let mut mime: *mut mailmime; //int r; //char * dup_filename; - let mut mime_fields: *mut mailmime_fields = 0 as *mut mailmime_fields; - let mut encoding_type: libc::c_int = 0; - let mut content_type_str: *mut libc::c_char = 0 as *mut libc::c_char; - let mut do_encoding: libc::c_int = 0; + let mut mime_fields: *mut mailmime_fields; + let mut encoding_type: libc::c_int; + let mut content_type_str: *mut libc::c_char; + let mut do_encoding: libc::c_int; encoding = 0 as *mut mailmime_mechanism; if default_content_type.is_null() { content_type_str = @@ -426,7 +439,7 @@ unsafe fn new_data_part( } else { do_encoding = 1i32; if (*(*content).ct_type).tp_type == MAILMIME_TYPE_COMPOSITE_TYPE as libc::c_int { - let mut composite: *mut mailmime_composite_type = 0 as *mut mailmime_composite_type; + let mut composite: *mut mailmime_composite_type; composite = (*(*content).ct_type).tp_data.tp_composite_type; match (*composite).ct_type { 1 => { @@ -501,11 +514,13 @@ unsafe fn new_data_part( } return 0 as *mut mailmime; } -/* ****************************************************************************** + +/******************************************************************************* * Generate Keypairs ******************************************************************************/ +// TODO should return bool /rtn unsafe fn load_or_generate_self_public_key( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut public_key: *mut dc_key_t, mut self_addr: *const libc::c_char, mut random_data_mime: *mut mailmime, @@ -513,44 +528,30 @@ unsafe fn load_or_generate_self_public_key( let mut current_block: u64; /* avoid double creation (we unlock the database during creation) */ static mut s_in_key_creation: libc::c_int = 0i32; - let mut key_created: libc::c_int = 0i32; + let mut key_created: libc::c_int; let mut success: libc::c_int = 0i32; let mut key_creation_here: libc::c_int = 0i32; - if !(context.is_null() - || (*context).magic != 0x11a11807i32 as libc::c_uint - || public_key.is_null()) - { - if 0 == dc_key_load_self_public(public_key, self_addr, (*context).sql) { + if !public_key.is_null() { + if 0 == dc_key_load_self_public( + context, + public_key, + self_addr, + &context.sql.clone().read().unwrap(), + ) { /* create the keypair - this may take a moment, however, as this is in a thread, this is no big deal */ if 0 != s_in_key_creation { current_block = 10496152961502316708; } else { key_creation_here = 1i32; s_in_key_creation = 1i32; - /* seed the random generator */ - let mut seed: [uintptr_t; 4] = [0; 4]; - seed[0usize] = time(0 as *mut time_t) as uintptr_t; - seed[1usize] = seed.as_mut_ptr() as uintptr_t; - seed[2usize] = public_key as uintptr_t; - seed[3usize] = pthread_self() as uintptr_t; - dc_pgp_rand_seed( - context, - seed.as_mut_ptr() as *const libc::c_void, - ::std::mem::size_of::<[uintptr_t; 4]>(), - ); if !random_data_mime.is_null() { - let mut random_data_mmap: *mut MMAPString = 0 as *mut MMAPString; + let mut random_data_mmap: *mut MMAPString; let mut col: libc::c_int = 0i32; random_data_mmap = mmap_string_new(b"\x00" as *const u8 as *const libc::c_char); if random_data_mmap.is_null() { current_block = 10496152961502316708; } else { mailmime_write_mem(random_data_mmap, &mut col, random_data_mime); - dc_pgp_rand_seed( - context, - (*random_data_mmap).str_0 as *const libc::c_void, - (*random_data_mmap).len, - ); mmap_string_free(random_data_mmap); current_block = 26972500619410423; } @@ -591,11 +592,12 @@ unsafe fn load_or_generate_self_public_key( current_block = 10496152961502316708; } else if 0 == dc_key_save_self_keypair( + context, public_key, private_key, self_addr, 1i32, - (*context).sql, + &context.sql.clone().read().unwrap(), ) { /*set default*/ @@ -631,15 +633,17 @@ unsafe fn load_or_generate_self_public_key( if 0 != key_creation_here { s_in_key_creation = 0i32 } - return success; + + success } + /* returns 1 if sth. was decrypted, 0 in other cases */ pub unsafe fn dc_e2ee_decrypt( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut in_out_message: *mut mailmime, mut helper: *mut dc_e2ee_helper_t, ) { - let mut iterations: libc::c_int = 0; + let mut iterations: libc::c_int; /* return values: 0=nothing to decrypt/cannot decrypt, 1=sth. decrypted (to detect parts that could not be decrypted, simply look for left "multipart/encrypted" MIME types */ /*just a pointer into mailmime structure, must not be freed*/ @@ -659,12 +663,7 @@ pub unsafe fn dc_e2ee_decrypt( ::std::mem::size_of::(), ); } - if !(context.is_null() - || (*context).magic != 0x11a11807i32 as libc::c_uint - || in_out_message.is_null() - || helper.is_null() - || imffields.is_null()) - { + if !(in_out_message.is_null() || helper.is_null() || imffields.is_null()) { if !imffields.is_null() { let mut field: *mut mailimf_field = mailimf_find_field(imffields, MAILIMF_FIELD_FROM as libc::c_int); @@ -692,37 +691,47 @@ pub unsafe fn dc_e2ee_decrypt( } } if message_time > 0i32 as libc::c_long && !from.is_null() { - if 0 != dc_apeerstate_load_by_addr(peerstate, (*context).sql, from) { + if 0 != dc_apeerstate_load_by_addr( + peerstate, + &context.sql.clone().read().unwrap(), + from, + ) { if !autocryptheader.is_null() { dc_apeerstate_apply_header(peerstate, autocryptheader, message_time); - dc_apeerstate_save_to_db(peerstate, (*context).sql, 0i32); + dc_apeerstate_save_to_db(peerstate, &context.sql.clone().read().unwrap(), 0i32); } else if message_time > (*peerstate).last_seen_autocrypt && 0 == contains_report(in_out_message) { dc_apeerstate_degrade_encryption(peerstate, message_time); - dc_apeerstate_save_to_db(peerstate, (*context).sql, 0i32); + dc_apeerstate_save_to_db(peerstate, &context.sql.clone().read().unwrap(), 0i32); } } else if !autocryptheader.is_null() { dc_apeerstate_init_from_header(peerstate, autocryptheader, message_time); - dc_apeerstate_save_to_db(peerstate, (*context).sql, 1i32); + dc_apeerstate_save_to_db(peerstate, &context.sql.clone().read().unwrap(), 1i32); } } /* load private key for decryption */ self_addr = dc_sqlite3_get_config( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"configured_addr\x00" as *const u8 as *const libc::c_char, 0 as *const libc::c_char, ); if !self_addr.is_null() { if !(0 == dc_keyring_load_self_private_for_decrypting( + context, private_keyring, self_addr, - (*context).sql, + &context.sql.clone().read().unwrap(), )) { if (*peerstate).last_seen == 0i32 as libc::c_long { - dc_apeerstate_load_by_addr(peerstate, (*context).sql, from); + dc_apeerstate_load_by_addr( + peerstate, + &context.sql.clone().read().unwrap(), + from, + ); } if 0 != (*peerstate).degrade_event { dc_handle_degrade_event(context, peerstate); @@ -768,13 +777,14 @@ pub unsafe fn dc_e2ee_decrypt( free(from as *mut libc::c_void); free(self_addr as *mut libc::c_void); } + unsafe fn update_gossip_peerstates( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut message_time: time_t, mut imffields: *mut mailimf_fields, mut gossip_headers: *const mailimf_fields, ) -> *mut dc_hash_t { - let mut cur1: *mut clistiter = 0 as *mut clistiter; + let mut cur1: *mut clistiter; let mut recipients: *mut dc_hash_t = 0 as *mut dc_hash_t; let mut gossipped_addr: *mut dc_hash_t = 0 as *mut dc_hash_t; cur1 = (*(*gossip_headers).fld_list).first; @@ -811,14 +821,22 @@ unsafe fn update_gossip_peerstates( let mut peerstate: *mut dc_apeerstate_t = dc_apeerstate_new(context); if 0 == dc_apeerstate_load_by_addr( peerstate, - (*context).sql, + &context.sql.clone().read().unwrap(), (*gossip_header).addr, ) { dc_apeerstate_init_from_gossip(peerstate, gossip_header, message_time); - dc_apeerstate_save_to_db(peerstate, (*context).sql, 1i32); + dc_apeerstate_save_to_db( + peerstate, + &context.sql.clone().read().unwrap(), + 1i32, + ); } else { dc_apeerstate_apply_gossip(peerstate, gossip_header, message_time); - dc_apeerstate_save_to_db(peerstate, (*context).sql, 0i32); + dc_apeerstate_save_to_db( + peerstate, + &context.sql.clone().read().unwrap(), + 0i32, + ); } if 0 != (*peerstate).degrade_event { dc_handle_degrade_event(context, peerstate); @@ -851,17 +869,20 @@ unsafe fn update_gossip_peerstates( cur1 = if !cur1.is_null() { (*cur1).next } else { - 0 as *mut clistcell_s + 0 as *mut clistcell } } if !recipients.is_null() { dc_hash_clear(recipients); free(recipients as *mut libc::c_void); } - return gossipped_addr; + + gossipped_addr } + +// TODO should return bool /rtn unsafe fn decrypt_recursive( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut mime: *mut mailmime, mut private_keyring: *const dc_keyring_t, mut public_keyring_for_validate: *const dc_keyring_t, @@ -869,9 +890,9 @@ unsafe fn decrypt_recursive( mut ret_gossip_headers: *mut *mut mailimf_fields, mut ret_has_unencrypted_parts: *mut libc::c_int, ) -> libc::c_int { - let mut ct: *mut mailmime_content = 0 as *mut mailmime_content; - let mut cur: *mut clistiter = 0 as *mut clistiter; - if context.is_null() || mime.is_null() { + let mut ct: *mut mailmime_content; + let mut cur: *mut clistiter; + if mime.is_null() { return 0i32; } if (*mime).mm_type == MAILMIME_MULTIPLE as libc::c_int { @@ -919,7 +940,7 @@ unsafe fn decrypt_recursive( cur = if !cur.is_null() { (*cur).next } else { - 0 as *mut clistcell_s + 0 as *mut clistcell } } *ret_has_unencrypted_parts = 1i32 @@ -944,7 +965,7 @@ unsafe fn decrypt_recursive( cur = if !cur.is_null() { (*cur).next } else { - 0 as *mut clistcell_s + 0 as *mut clistcell } } } @@ -963,19 +984,21 @@ unsafe fn decrypt_recursive( } else { *ret_has_unencrypted_parts = 1i32 } - return 0i32; + + 0 } + unsafe fn decrypt_part( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut mime: *mut mailmime, mut private_keyring: *const dc_keyring_t, mut public_keyring_for_validate: *const dc_keyring_t, mut ret_valid_signatures: *mut dc_hash_t, mut ret_decrypted_mime: *mut *mut mailmime, ) -> libc::c_int { - let mut add_signatures: *mut dc_hash_t = 0 as *mut dc_hash_t; + let mut add_signatures: *mut dc_hash_t; let mut current_block: u64; - let mut mime_data: *mut mailmime_data = 0 as *mut mailmime_data; + let mut mime_data: *mut mailmime_data; let mut mime_transfer_encoding: libc::c_int = MAILMIME_MECHANISM_BINARY as libc::c_int; /* mmap_string_unref()'d if set */ let mut transfer_decoding_buffer: *mut libc::c_char = 0 as *mut libc::c_char; @@ -993,7 +1016,7 @@ unsafe fn decrypt_part( || (*mime_data).dt_data.dt_text.dt_length <= 0) { if !(*mime).mm_mime_fields.is_null() { - let mut cur: *mut clistiter = 0 as *mut clistiter; + let mut cur: *mut clistiter; cur = (*(*(*mime).mm_mime_fields).fld_list).first; while !cur.is_null() { let mut field: *mut mailmime_field = (if !cur.is_null() { @@ -1011,7 +1034,7 @@ unsafe fn decrypt_part( cur = if !cur.is_null() { (*cur).next } else { - 0 as *mut clistcell_s + 0 as *mut clistcell } } } @@ -1029,7 +1052,7 @@ unsafe fn decrypt_part( current_block = 4488286894823169796; } } else { - let mut r: libc::c_int = 0; + let mut r: libc::c_int; let mut current_index: size_t = 0i32 as size_t; r = mailmime_part_parse( (*mime_data).dt_data.dt_text.dt_data, @@ -1104,11 +1127,14 @@ unsafe fn decrypt_part( if !transfer_decoding_buffer.is_null() { mmap_string_unref(transfer_decoding_buffer); } - return sth_decrypted; + + sth_decrypted } -/* ****************************************************************************** + +/******************************************************************************* * Decrypt ******************************************************************************/ +// TODO should return bool /rtn unsafe fn has_decrypted_pgp_armor( mut str__: *const libc::c_char, mut str_bytes: libc::c_int, @@ -1132,9 +1158,11 @@ unsafe fn has_decrypted_pgp_armor( { return 1; } - return 0; + + 0 } -/* * + +/** * Check if a MIME structure contains a multipart/report part. * * As reports are often unencrypted, we do not reset the Autocrypt header in @@ -1148,6 +1176,7 @@ unsafe fn has_decrypted_pgp_armor( * @param mime The mime struture to check * @return 1=multipart/report found in MIME, 0=no multipart/report found */ +// TODO should return bool /rtn unsafe fn contains_report(mut mime: *mut mailmime) -> libc::c_int { if (*mime).mm_type == MAILMIME_MULTIPLE as libc::c_int { if (*(*(*mime).mm_content_type).ct_type).tp_type @@ -1164,7 +1193,7 @@ unsafe fn contains_report(mut mime: *mut mailmime) -> libc::c_int { { return 1i32; } - let mut cur: *mut clistiter = 0 as *mut clistiter; + let mut cur: *mut clistiter; cur = (*(*mime).mm_data.mm_multipart.mm_mp_list).first; while !cur.is_null() { if 0 != contains_report( @@ -1179,7 +1208,7 @@ unsafe fn contains_report(mut mime: *mut mailmime) -> libc::c_int { cur = if !cur.is_null() { (*cur).next } else { - 0 as *mut clistcell_s + 0 as *mut clistcell } } } else if (*mime).mm_type == MAILMIME_MESSAGE as libc::c_int { @@ -1187,8 +1216,10 @@ unsafe fn contains_report(mut mime: *mut mailmime) -> libc::c_int { return 1i32; } } - return 0i32; + + 0 } + /* frees data referenced by "mailmime" but not freed by mailmime_free(). After calling this function, in_out_message cannot be used any longer! */ pub unsafe fn dc_e2ee_thanks(mut helper: *mut dc_e2ee_helper_t) { if helper.is_null() { @@ -1207,19 +1238,19 @@ pub unsafe fn dc_e2ee_thanks(mut helper: *mut dc_e2ee_helper_t) { (*helper).signatures = 0 as *mut dc_hash_t }; } + /* makes sure, the private key exists, needed only for exporting keys and the case no message was sent before */ -pub unsafe fn dc_ensure_secret_key_exists(mut context: *mut dc_context_t) -> libc::c_int { +// TODO should return bool /rtn +pub unsafe fn dc_ensure_secret_key_exists(mut context: &dc_context_t) -> libc::c_int { /* normally, the key is generated as soon as the first mail is send (this is to gain some extra-random-seed by the message content and the timespan between program start and message sending) */ let mut success: libc::c_int = 0i32; let mut public_key: *mut dc_key_t = dc_key_new(); let mut self_addr: *mut libc::c_char = 0 as *mut libc::c_char; - if !(context.is_null() - || (*context).magic != 0x11a11807i32 as libc::c_uint - || public_key.is_null()) - { + if !public_key.is_null() { self_addr = dc_sqlite3_get_config( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"configured_addr\x00" as *const u8 as *const libc::c_char, 0 as *const libc::c_char, ); @@ -1239,5 +1270,6 @@ pub unsafe fn dc_ensure_secret_key_exists(mut context: *mut dc_context_t) -> lib } dc_key_unref(public_key); free(self_addr as *mut libc::c_void); - return success; + + success } diff --git a/src/dc_hash.rs b/src/dc_hash.rs index 533a52d8e..a0e76d535 100644 --- a/src/dc_hash.rs +++ b/src/dc_hash.rs @@ -1,5 +1,3 @@ -use libc; - use crate::types::*; use crate::x::*; @@ -21,13 +19,16 @@ pub struct dc_hash_t { pub htsize: libc::c_int, pub ht: *mut _ht, } + #[derive(Copy, Clone)] #[repr(C)] pub struct _ht { pub count: libc::c_int, pub chain: *mut dc_hashelem_t, } + pub type dc_hashelem_t = _dc_hashelem; + /* Each element in the hash table is an instance of the following * structure. All elements are stored on a single doubly-linked list. * @@ -43,6 +44,7 @@ pub struct _dc_hashelem { pub pKey: *mut libc::c_void, pub nKey: libc::c_int, } + /* * There are 4 different modes of operation for a hash table: * @@ -102,6 +104,7 @@ pub unsafe fn dc_hash_init( (*pNew).htsize = 0i32; (*pNew).ht = 0 as *mut _ht; } + pub unsafe fn dc_hash_insert( mut pH: *mut dc_hash_t, mut pKey: *const libc::c_void, @@ -109,15 +112,15 @@ pub unsafe fn dc_hash_insert( mut data: *mut libc::c_void, ) -> *mut libc::c_void { /* Raw hash value of the key */ - let mut hraw: libc::c_int = 0; + let mut hraw: libc::c_int; /* the hash of the key modulo hash table size */ - let mut h: libc::c_int = 0; + let mut h: libc::c_int; /* Used to loop thru the element list */ - let mut elem: *mut dc_hashelem_t = 0 as *mut dc_hashelem_t; + let mut elem: *mut dc_hashelem_t; /* New element added to the pH */ - let mut new_elem: *mut dc_hashelem_t = 0 as *mut dc_hashelem_t; + let mut new_elem: *mut dc_hashelem_t; /* The hash function */ - let mut xHash: Option libc::c_int> = None; + let mut xHash: Option libc::c_int>; if 0 != pH.is_null() as libc::c_int as libc::c_long { __assert_rtn( (*::std::mem::transmute::<&[u8; 15], &[libc::c_char; 15]>(b"dc_hash_insert\x00")) @@ -215,8 +218,10 @@ pub unsafe fn dc_hash_insert( h = hraw & (*pH).htsize - 1i32; insertElement(pH, &mut *(*pH).ht.offset(h as isize), new_elem); (*new_elem).data = data; - return 0 as *mut libc::c_void; + + 0 as *mut libc::c_void } + /* Link an element into the hash table */ unsafe extern "C" fn insertElement( @@ -225,7 +230,7 @@ unsafe extern "C" fn insertElement( mut pNew: *mut dc_hashelem_t, ) { /* First element already in pEntry */ - let mut pHead: *mut dc_hashelem_t = 0 as *mut dc_hashelem_t; + let mut pHead: *mut dc_hashelem_t; pHead = (*pEntry).chain; if !pHead.is_null() { (*pNew).next = pHead; @@ -247,18 +252,19 @@ unsafe extern "C" fn insertElement( (*pEntry).count += 1; (*pEntry).chain = pNew; } + /* Resize the hash table so that it cantains "new_size" buckets. * "new_size" must be a power of 2. The hash table might fail * to resize if sjhashMalloc() fails. */ unsafe fn rehash(mut pH: *mut dc_hash_t, mut new_size: libc::c_int) { /* The new hash table */ - let mut new_ht: *mut _ht = 0 as *mut _ht; + let mut new_ht: *mut _ht; /* For looping over existing elements */ - let mut elem: *mut dc_hashelem_t = 0 as *mut dc_hashelem_t; - let mut next_elem: *mut dc_hashelem_t = 0 as *mut dc_hashelem_t; + let mut elem: *mut dc_hashelem_t; + let mut next_elem: *mut dc_hashelem_t; /* The hash function */ - let mut xHash: Option libc::c_int> = None; + let mut xHash: Option libc::c_int>; if 0 != !(new_size & new_size - 1i32 == 0i32) as libc::c_int as libc::c_long { __assert_rtn( (*::std::mem::transmute::<&[u8; 7], &[libc::c_char; 7]>(b"rehash\x00")).as_ptr(), @@ -290,6 +296,7 @@ unsafe fn rehash(mut pH: *mut dc_hash_t, mut new_size: libc::c_int) { elem = next_elem } } + /* Return a pointer to the appropriate hash function given the key class. * * About the syntax: @@ -309,8 +316,10 @@ unsafe fn hashFunction( 4 => return Some(binHash), _ => {} } - return None; + + None } + /* Hash and comparison functions when the mode is SJHASH_BINARY */ unsafe fn binHash(mut pKey: *const libc::c_void, mut nKey: libc::c_int) -> libc::c_int { @@ -326,13 +335,16 @@ unsafe fn binHash(mut pKey: *const libc::c_void, mut nKey: libc::c_int) -> libc: z = z.offset(1); h = h << 3i32 ^ h ^ *fresh1 as libc::c_int } - return h & 0x7fffffffi32; + + h & 0x7fffffffi32 } + /* Hash and comparison functions when the mode is SJHASH_STRING */ unsafe fn strHash(mut pKey: *const libc::c_void, mut nKey: libc::c_int) -> libc::c_int { - return sjhashNoCase(pKey as *const libc::c_char, nKey); + sjhashNoCase(pKey as *const libc::c_char, nKey) } + /* This function computes a hash on the name of a keyword. * Case is not significant. */ @@ -347,8 +359,10 @@ unsafe fn sjhashNoCase(mut z: *const libc::c_char, mut n: libc::c_int) -> libc:: h = h << 3i32 ^ h ^ sjhashUpperToLower[*fresh2 as libc::c_uchar as usize] as libc::c_int; n -= 1 } - return h & 0x7fffffffi32; + + h & 0x7fffffffi32 } + /* An array to map all upper-case characters into their corresponding * lower-case character. */ @@ -610,17 +624,20 @@ static mut sjhashUpperToLower: [libc::c_uchar; 256] = [ 254i32 as libc::c_uchar, 255i32 as libc::c_uchar, ]; + /* Hash and comparison functions when the mode is SJHASH_POINTER */ unsafe fn ptrHash(pKey: *const libc::c_void, _nKey: libc::c_int) -> libc::c_int { let mut x: uintptr_t = pKey as uintptr_t; - return (x ^ x << 8i32 ^ x >> 8i32) as libc::c_int; + (x ^ x << 8i32 ^ x >> 8i32) as libc::c_int } + /* Hash and comparison functions when the mode is SJHASH_INT */ unsafe fn intHash(_pKey: *const libc::c_void, mut nKey: libc::c_int) -> libc::c_int { - return nKey ^ nKey << 8i32 ^ nKey >> 8i32; + nKey ^ nKey << 8i32 ^ nKey >> 8i32 } + /* ** Based upon hash.c from sqlite which author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: @@ -636,6 +653,7 @@ unsafe fn sjhashMalloc(mut bytes: libc::c_int) -> *mut libc::c_void { } p } + /* Remove a single entry from the hash table given a pointer to that * element and a hash on the element's key. */ @@ -644,7 +662,7 @@ unsafe fn removeElementGivenHash( mut elem: *mut dc_hashelem_t, mut h: libc::c_int, ) { - let mut pEntry: *mut _ht = 0 as *mut _ht; + let mut pEntry: *mut _ht; if !(*elem).prev.is_null() { (*(*elem).prev).next = (*elem).next } else { @@ -667,6 +685,7 @@ unsafe fn removeElementGivenHash( free(elem as *mut libc::c_void); (*pH).count -= 1; } + /* This function (for internal use only) locates an element in an * hash table that matches the given key. The hash for this key has * already been computed and is passed as the 4th parameter. @@ -678,9 +697,9 @@ unsafe fn findElementGivenHash( mut h: libc::c_int, ) -> *mut dc_hashelem_t { /* Used to loop thru the element list */ - let mut elem: *mut dc_hashelem_t = 0 as *mut dc_hashelem_t; + let mut elem: *mut dc_hashelem_t; /* Number of elements left to test */ - let mut count: libc::c_int = 0; + let mut count: libc::c_int; /* comparison function */ let mut xCompare: Option< unsafe fn( @@ -689,7 +708,7 @@ unsafe fn findElementGivenHash( _: *const libc::c_void, _: libc::c_int, ) -> libc::c_int, - > = None; + >; if !(*pH).ht.is_null() { let mut pEntry: *mut _ht = &mut *(*pH).ht.offset(h as isize) as *mut _ht; elem = (*pEntry).chain; @@ -709,8 +728,10 @@ unsafe fn findElementGivenHash( elem = (*elem).next } } - return 0 as *mut dc_hashelem_t; + + 0 as *mut dc_hashelem_t } + /* Return a pointer to the appropriate hash function given the key class. */ unsafe fn compareFunction( @@ -730,8 +751,9 @@ unsafe fn compareFunction( 4 => return Some(binCompare), _ => {} } - return None; + None } + unsafe fn binCompare( mut pKey1: *const libc::c_void, mut n1: libc::c_int, @@ -741,8 +763,9 @@ unsafe fn binCompare( if n1 != n2 { return 1i32; } - return memcmp(pKey1, pKey2, n1 as libc::size_t); + memcmp(pKey1, pKey2, n1 as libc::size_t) } + unsafe fn strCompare( mut pKey1: *const libc::c_void, mut n1: libc::c_int, @@ -752,12 +775,13 @@ unsafe fn strCompare( if n1 != n2 { return 1i32; } - return sjhashStrNICmp( + sjhashStrNICmp( pKey1 as *const libc::c_char, pKey2 as *const libc::c_char, n1, - ); + ) } + /* Some systems have stricmp(). Others have strcasecmp(). Because * there is no consistency, we will define our own. */ @@ -766,8 +790,8 @@ unsafe fn sjhashStrNICmp( mut zRight: *const libc::c_char, mut N: libc::c_int, ) -> libc::c_int { - let mut a: *mut libc::c_uchar = 0 as *mut libc::c_uchar; - let mut b: *mut libc::c_uchar = 0 as *mut libc::c_uchar; + let mut a: *mut libc::c_uchar; + let mut b: *mut libc::c_uchar; a = zLeft as *mut libc::c_uchar; b = zRight as *mut libc::c_uchar; loop { @@ -790,6 +814,7 @@ unsafe fn sjhashStrNICmp( - sjhashUpperToLower[*b as usize] as libc::c_int }; } + unsafe fn ptrCompare( pKey1: *const libc::c_void, _n1: libc::c_int, @@ -820,11 +845,11 @@ pub unsafe fn dc_hash_find( mut nKey: libc::c_int, ) -> *mut libc::c_void { /* A hash on key */ - let mut h: libc::c_int = 0; + let mut h: libc::c_int; /* The element that matches key */ - let mut elem: *mut dc_hashelem_t = 0 as *mut dc_hashelem_t; + let mut elem: *mut dc_hashelem_t; /* The hash function */ - let mut xHash: Option libc::c_int> = None; + let mut xHash: Option libc::c_int>; if pH.is_null() || (*pH).ht.is_null() { return 0 as *mut libc::c_void; } @@ -857,9 +882,10 @@ pub unsafe fn dc_hash_find( 0 as *mut libc::c_void }; } + pub unsafe fn dc_hash_clear(mut pH: *mut dc_hash_t) { /* For looping over all elements of the table */ - let mut elem: *mut dc_hashelem_t = 0 as *mut dc_hashelem_t; + let mut elem: *mut dc_hashelem_t; if pH.is_null() { return; } diff --git a/src/dc_imap.rs b/src/dc_imap.rs index caf40429f..75f93c2bb 100644 --- a/src/dc_imap.rs +++ b/src/dc_imap.rs @@ -1,1858 +1,1556 @@ -use libc; +use std::ffi::{CStr, CString}; +use std::sync::{Arc, Condvar, Mutex, RwLock}; +use std::time::{Duration, SystemTime}; -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::dc_sqlite3::*; use crate::types::*; -use crate::x::*; -#[derive(Copy, Clone)] +pub const DC_IMAP_SEEN: usize = 0x0001; + +pub const DC_SUCCESS: usize = 3; +pub const DC_ALREADY_DONE: usize = 2; +pub const DC_RETRY_LATER: usize = 1; +pub const DC_FAILED: usize = 0; + +const PREFETCH_FLAGS: &'static str = "(UID ENVELOPE)"; +const BODY_FLAGS: &'static str = "(FLAGS BODY.PEEK[])"; +const FETCH_FLAGS: &'static str = "(FLAGS)"; + #[repr(C)] -pub struct dc_imap_t { - pub addr: *mut libc::c_char, - pub imap_server: *mut libc::c_char, - pub imap_port: libc::c_int, - pub imap_user: *mut libc::c_char, - pub imap_pw: *mut libc::c_char, - pub server_flags: libc::c_int, - pub connected: libc::c_int, - pub etpan: *mut mailimap, - pub idle_set_up: libc::c_int, - pub selected_folder: *mut libc::c_char, - pub selected_folder_needs_expunge: libc::c_int, - pub should_reconnect: libc::c_int, - pub can_idle: libc::c_int, - pub has_xlist: libc::c_int, - pub imap_delimiter: libc::c_char, - pub watch_folder: *mut libc::c_char, - pub watch_cond: pthread_cond_t, - pub watch_condmutex: pthread_mutex_t, - pub watch_condflag: libc::c_int, - pub fetch_type_prefetch: *mut mailimap_fetch_type, - pub fetch_type_body: *mut mailimap_fetch_type, - pub fetch_type_flags: *mut mailimap_fetch_type, - pub get_config: dc_get_config_t, - pub set_config: dc_set_config_t, - pub precheck_imf: dc_precheck_imf_t, - pub receive_imf: dc_receive_imf_t, - pub userData: *mut libc::c_void, - pub context: *mut dc_context_t, - pub log_connect_errors: libc::c_int, - pub skip_log_capabilities: libc::c_int, +pub struct Imap { + config: Arc>, + watch: Arc<(Mutex, Condvar)>, + + get_config: dc_get_config_t, + set_config: dc_set_config_t, + precheck_imf: dc_precheck_imf_t, + receive_imf: dc_receive_imf_t, + + session: Arc>>, + // idle: Arc>>, } -pub unsafe fn dc_imap_new( - mut get_config: dc_get_config_t, - mut set_config: dc_set_config_t, - mut precheck_imf: dc_precheck_imf_t, - mut receive_imf: dc_receive_imf_t, - mut userData: *mut libc::c_void, - mut context: *mut dc_context_t, -) -> *mut dc_imap_t { - let mut imap: *mut dc_imap_t = 0 as *mut dc_imap_t; - imap = calloc(1, ::std::mem::size_of::()) as *mut dc_imap_t; - if imap.is_null() { - exit(25i32); - } - (*imap).log_connect_errors = 1i32; - (*imap).context = context; - (*imap).get_config = get_config; - (*imap).set_config = set_config; - (*imap).precheck_imf = precheck_imf; - (*imap).receive_imf = receive_imf; - (*imap).userData = userData; - pthread_mutex_init( - &mut (*imap).watch_condmutex, - 0 as *const pthread_mutexattr_t, - ); - pthread_cond_init(&mut (*imap).watch_cond, 0 as *const pthread_condattr_t); - (*imap).watch_folder = calloc(1, 1) as *mut libc::c_char; - (*imap).selected_folder = calloc(1, 1) as *mut libc::c_char; - (*imap).fetch_type_prefetch = mailimap_fetch_type_new_fetch_att_list_empty(); - mailimap_fetch_type_new_fetch_att_list_add( - (*imap).fetch_type_prefetch, - mailimap_fetch_att_new_uid(), - ); - mailimap_fetch_type_new_fetch_att_list_add( - (*imap).fetch_type_prefetch, - mailimap_fetch_att_new_envelope(), - ); - (*imap).fetch_type_body = mailimap_fetch_type_new_fetch_att_list_empty(); - mailimap_fetch_type_new_fetch_att_list_add( - (*imap).fetch_type_body, - mailimap_fetch_att_new_flags(), - ); - mailimap_fetch_type_new_fetch_att_list_add( - (*imap).fetch_type_body, - mailimap_fetch_att_new_body_peek_section(mailimap_section_new( - 0 as *mut mailimap_section_spec, - )), - ); - (*imap).fetch_type_flags = mailimap_fetch_type_new_fetch_att_list_empty(); - mailimap_fetch_type_new_fetch_att_list_add( - (*imap).fetch_type_flags, - mailimap_fetch_att_new_flags(), - ); - return imap; +// rental! { +// pub mod rent { +// use crate::dc_imap::{Session, IdleHandle}; + +// #[rental_mut] +// pub struct RentSession { +// session: Box, +// idle: IdleHandle<'session>, +// } +// } +// } + +// use rent::*; + +#[derive(Debug)] +pub enum FolderMeaning { + Unknown, + SentObjects, + Other, } -pub unsafe fn dc_imap_unref(mut imap: *mut dc_imap_t) { - if imap.is_null() { - return; - } - dc_imap_disconnect(imap); - pthread_cond_destroy(&mut (*imap).watch_cond); - pthread_mutex_destroy(&mut (*imap).watch_condmutex); - free((*imap).watch_folder as *mut libc::c_void); - free((*imap).selected_folder as *mut libc::c_void); - if !(*imap).fetch_type_prefetch.is_null() { - mailimap_fetch_type_free((*imap).fetch_type_prefetch); - } - if !(*imap).fetch_type_body.is_null() { - mailimap_fetch_type_free((*imap).fetch_type_body); - } - if !(*imap).fetch_type_flags.is_null() { - mailimap_fetch_type_free((*imap).fetch_type_flags); - } - free(imap as *mut libc::c_void); + +pub enum Client { + Secure(imap::Client>), + Insecure(imap::Client), } -pub unsafe fn dc_imap_disconnect(mut imap: *mut dc_imap_t) { - if imap.is_null() { - return; - } - if 0 != (*imap).connected { - unsetup_handle(imap); - free_connect_param(imap); - (*imap).connected = 0i32 - }; + +pub enum Session { + Secure(imap::Session>), + Insecure(imap::Session), } -/* we leave sent_folder set; normally this does not change in a normal reconnect; we'll update this folder if we get errors */ -/* ****************************************************************************** - * Connect/Disconnect - ******************************************************************************/ -unsafe fn free_connect_param(mut imap: *mut dc_imap_t) { - free((*imap).addr as *mut libc::c_void); - (*imap).addr = 0 as *mut libc::c_char; - free((*imap).imap_server as *mut libc::c_void); - (*imap).imap_server = 0 as *mut libc::c_char; - free((*imap).imap_user as *mut libc::c_void); - (*imap).imap_user = 0 as *mut libc::c_char; - free((*imap).imap_pw as *mut libc::c_void); - (*imap).imap_pw = 0 as *mut libc::c_char; - *(*imap).watch_folder.offset(0isize) = 0i32 as libc::c_char; - *(*imap).selected_folder.offset(0isize) = 0i32 as libc::c_char; - (*imap).imap_port = 0i32; - (*imap).can_idle = 0i32; - (*imap).has_xlist = 0i32; + +pub enum IdleHandle<'a> { + Secure(imap::extensions::idle::Handle<'a, native_tls::TlsStream>), + Insecure(imap::extensions::idle::Handle<'a, std::net::TcpStream>), } -unsafe fn unsetup_handle(mut imap: *mut dc_imap_t) { - if imap.is_null() { - return; + +impl From>> for Client { + fn from(client: imap::Client>) -> Self { + Client::Secure(client) } - if !(*imap).etpan.is_null() { - if 0 != (*imap).idle_set_up { - mailstream_unsetup_idle((*(*imap).etpan).imap_stream); - (*imap).idle_set_up = 0i32 +} + +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<'a> From>> + for IdleHandle<'a> +{ + fn from( + handle: imap::extensions::idle::Handle<'a, native_tls::TlsStream>, + ) -> Self { + IdleHandle::Secure(handle) + } +} + +impl<'a> From> for IdleHandle<'a> { + fn from(handle: imap::extensions::idle::Handle<'a, std::net::TcpStream>) -> Self { + IdleHandle::Insecure(handle) + } +} + +impl<'a> IdleHandle<'a> { + pub fn set_keepalive(&mut self, interval: Duration) { + match self { + IdleHandle::Secure(i) => i.set_keepalive(interval), + IdleHandle::Insecure(i) => i.set_keepalive(interval), + } + } + + pub fn wait_keepalive(self) -> imap::error::Result<()> { + match self { + IdleHandle::Secure(i) => i.wait_keepalive(), + IdleHandle::Insecure(i) => i.wait_keepalive(), } - if !(*(*imap).etpan).imap_stream.is_null() { - mailstream_close((*(*imap).etpan).imap_stream); - (*(*imap).etpan).imap_stream = 0 as *mut mailstream - } - mailimap_free((*imap).etpan); - (*imap).etpan = 0 as *mut mailimap; - dc_log_info( - (*imap).context, - 0i32, - b"IMAP disconnected.\x00" as *const u8 as *const libc::c_char, - ); } - *(*imap).selected_folder.offset(0isize) = 0i32 as libc::c_char; } -pub unsafe fn dc_imap_connect( - mut imap: *mut dc_imap_t, - mut lp: *const dc_loginparam_t, -) -> libc::c_int { - let mut success: libc::c_int = 0i32; - if imap.is_null() - || lp.is_null() - || (*lp).mail_server.is_null() - || (*lp).mail_user.is_null() - || (*lp).mail_pw.is_null() + +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 fn create>(&mut self, mailbox_name: S) -> imap::error::Result<()> { + match self { + Session::Secure(i) => i.subscribe(mailbox_name), + Session::Insecure(i) => i.subscribe(mailbox_name), + } + } + + pub fn subscribe>(&mut self, mailbox: S) -> imap::error::Result<()> { + match self { + Session::Secure(i) => i.subscribe(mailbox), + Session::Insecure(i) => i.subscribe(mailbox), + } + } + + pub fn close(&mut self) -> imap::error::Result<()> { + match self { + Session::Secure(i) => i.close(), + Session::Insecure(i) => i.close(), + } + } + + pub fn select>( + &mut self, + mailbox_name: S, + ) -> imap::error::Result { + match self { + Session::Secure(i) => i.select(mailbox_name), + Session::Insecure(i) => i.select(mailbox_name), + } + } + + pub fn fetch( + &mut self, + sequence_set: S1, + query: S2, + ) -> imap::error::Result>> + where + S1: AsRef, + S2: AsRef, { - return 0i32; - } - if 0 != (*imap).connected { - success = 1i32 - } else { - (*imap).addr = dc_strdup((*lp).addr); - (*imap).imap_server = dc_strdup((*lp).mail_server); - (*imap).imap_port = (*lp).mail_port as libc::c_int; - (*imap).imap_user = dc_strdup((*lp).mail_user); - (*imap).imap_pw = dc_strdup((*lp).mail_pw); - (*imap).server_flags = (*lp).server_flags; - if !(0 == setup_handle_if_needed(imap)) { - (*imap).can_idle = mailimap_has_idle((*imap).etpan); - (*imap).has_xlist = mailimap_has_xlist((*imap).etpan); - (*imap).can_idle = 0i32; - if 0 == (*imap).skip_log_capabilities - && !(*(*imap).etpan).imap_connection_info.is_null() - && !(*(*(*imap).etpan).imap_connection_info) - .imap_capability - .is_null() - { - (*imap).skip_log_capabilities = 1i32; - let mut capinfostr: dc_strbuilder_t = dc_strbuilder_t { - buf: 0 as *mut libc::c_char, - allocated: 0, - free: 0, - eos: 0 as *mut libc::c_char, - }; - dc_strbuilder_init(&mut capinfostr, 0i32); - let mut list: *mut clist = - (*(*(*(*imap).etpan).imap_connection_info).imap_capability).cap_list; - if !list.is_null() { - let mut cur: *mut clistiter = 0 as *mut clistiter; - cur = (*list).first; - while !cur.is_null() { - let mut cap: *mut mailimap_capability = (if !cur.is_null() { - (*cur).data - } else { - 0 as *mut libc::c_void - }) - as *mut mailimap_capability; - if !cap.is_null() - && (*cap).cap_type == MAILIMAP_CAPABILITY_NAME as libc::c_int - { - dc_strbuilder_cat( - &mut capinfostr, - b" \x00" as *const u8 as *const libc::c_char, - ); - dc_strbuilder_cat(&mut capinfostr, (*cap).cap_data.cap_name); - } - cur = if !cur.is_null() { - (*cur).next - } else { - 0 as *mut clistcell_s - } - } - } - dc_log_info( - (*imap).context, - 0i32, - b"IMAP-capabilities:%s\x00" as *const u8 as *const libc::c_char, - capinfostr.buf, - ); - free(capinfostr.buf as *mut libc::c_void); - } - (*imap).connected = 1i32; - success = 1i32 + match self { + Session::Secure(i) => i.fetch(sequence_set, query), + Session::Insecure(i) => i.fetch(sequence_set, query), } } - if success == 0i32 { - unsetup_handle(imap); - free_connect_param(imap); - } - return success; -} -unsafe fn setup_handle_if_needed(mut imap: *mut dc_imap_t) -> libc::c_int { - let mut current_block: u64; - let mut r: libc::c_int = 0i32; - let mut success: libc::c_int = 0i32; - if !(imap.is_null() || (*imap).imap_server.is_null()) { - if 0 != (*imap).should_reconnect { - unsetup_handle(imap); - } - if !(*imap).etpan.is_null() { - success = 1i32 - } else { - (*imap).etpan = mailimap_new(0i32 as size_t, None); - mailimap_set_timeout((*imap).etpan, 10i32 as time_t); - if 0 != (*imap).server_flags & (0x100i32 | 0x400i32) { - r = mailimap_socket_connect( - (*imap).etpan, - (*imap).imap_server, - (*imap).imap_port as uint16_t, - ); - if 0 != dc_imap_is_error(imap, r) { - dc_log_event_seq( - (*imap).context, - 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 & 0x100i32 { - r = mailimap_socket_starttls((*imap).etpan); - if 0 != dc_imap_is_error(imap, r) { - dc_log_event_seq((*imap).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( - (*imap).context, - 0i32, - b"IMAP-server %s:%i STARTTLS-connected.\x00" as *const u8 - as *const libc::c_char, - (*imap).imap_server, - (*imap).imap_port as libc::c_int, - ); - current_block = 14763689060501151050; - } - } else { - dc_log_info( - (*imap).context, - 0i32, - b"IMAP-server %s:%i connected.\x00" as *const u8 as *const libc::c_char, - (*imap).imap_server, - (*imap).imap_port as libc::c_int, - ); - current_block = 14763689060501151050; - } - } else { - r = mailimap_ssl_connect( - (*imap).etpan, - (*imap).imap_server, - (*imap).imap_port as uint16_t, - ); - if 0 != dc_imap_is_error(imap, r) { - dc_log_event_seq( - (*imap).context, - 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( - (*imap).context, - 0i32, - b"IMAP-server %s:%i SSL-connected.\x00" as *const u8 as *const libc::c_char, - (*imap).imap_server, - (*imap).imap_port as libc::c_int, - ); - current_block = 14763689060501151050; - } - } - match current_block { - 15811161807000851472 => {} - _ => { - if 0 != (*imap).server_flags & 0x2i32 { - dc_log_info( - (*imap).context, - 0i32, - b"IMAP-OAuth2 connect...\x00" as *const u8 as *const libc::c_char, - ); - let mut access_token: *mut libc::c_char = dc_get_oauth2_access_token( - (*imap).context, - (*imap).addr, - (*imap).imap_pw, - 0i32, - ); - r = mailimap_oauth2_authenticate( - (*imap).etpan, - (*imap).imap_user, - access_token, - ); - if 0 != dc_imap_is_error(imap, r) { - free(access_token as *mut libc::c_void); - access_token = dc_get_oauth2_access_token( - (*imap).context, - (*imap).addr, - (*imap).imap_pw, - 0x1i32, - ); - r = mailimap_oauth2_authenticate( - (*imap).etpan, - (*imap).imap_user, - access_token, - ) - } - free(access_token as *mut libc::c_void); - } else { - r = mailimap_login((*imap).etpan, (*imap).imap_user, (*imap).imap_pw) - } - if 0 != dc_imap_is_error(imap, r) { - let mut msg: *mut libc::c_char = get_error_msg( - imap, - b"Cannot login\x00" as *const u8 as *const libc::c_char, - r, - ); - dc_log_event_seq( - (*imap).context, - 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( - (*imap).context, - Event::IMAP_CONNECTED, - 0i32, - b"IMAP-login as %s ok.\x00" as *const u8 as *const libc::c_char, - (*imap).imap_user, - ); - success = 1i32 - } - } - } - } - } - if success == 0i32 { - unsetup_handle(imap); - } - (*imap).should_reconnect = 0i32; - return success; -} -unsafe fn get_error_msg( - mut imap: *mut dc_imap_t, - mut what_failed: *const libc::c_char, - mut code: libc::c_int, -) -> *mut libc::c_char { - let mut stock: *mut libc::c_char = 0 as *mut libc::c_char; - let mut msg: dc_strbuilder_t = dc_strbuilder_t { - buf: 0 as *mut libc::c_char, - allocated: 0, - free: 0, - eos: 0 as *mut libc::c_char, - }; - dc_strbuilder_init(&mut msg, 1000i32); - match code { - 28 => { - stock = dc_stock_str_repl_string((*imap).context, 60i32, (*imap).imap_user); - dc_strbuilder_cat(&mut msg, stock); - } - _ => { - dc_strbuilder_catf( - &mut msg as *mut dc_strbuilder_t, - b"%s, IMAP-error #%i\x00" as *const u8 as *const libc::c_char, - what_failed, - code, - ); - } - } - free(stock as *mut libc::c_void); - stock = 0 as *mut libc::c_char; - if !(*(*imap).etpan).imap_response.is_null() { - dc_strbuilder_cat(&mut msg, b"\n\n\x00" as *const u8 as *const libc::c_char); - stock = dc_stock_str_repl_string2( - (*imap).context, - 61i32, - (*imap).imap_server, - (*(*imap).etpan).imap_response, - ); - dc_strbuilder_cat(&mut msg, stock); - } - free(stock as *mut libc::c_void); - stock = 0 as *mut libc::c_char; - return msg.buf; -} -pub unsafe fn dc_imap_is_error(mut imap: *mut dc_imap_t, mut code: libc::c_int) -> libc::c_int { - if code == MAILIMAP_NO_ERROR as libc::c_int - || code == MAILIMAP_NO_ERROR_AUTHENTICATED as libc::c_int - || code == MAILIMAP_NO_ERROR_NON_AUTHENTICATED as libc::c_int + + pub fn uid_fetch( + &mut self, + uid_set: S1, + query: S2, + ) -> imap::error::Result>> + where + S1: AsRef, + S2: AsRef, { - return 0i32; - } - if code == MAILIMAP_ERROR_STREAM as libc::c_int || code == MAILIMAP_ERROR_PARSE as libc::c_int { - dc_log_info( - (*imap).context, - 0i32, - b"IMAP stream lost; we\'ll reconnect soon.\x00" as *const u8 as *const libc::c_char, - ); - (*imap).should_reconnect = 1i32 - } - return 1i32; -} -pub unsafe extern "C" fn dc_imap_set_watch_folder( - mut imap: *mut dc_imap_t, - mut watch_folder: *const libc::c_char, -) { - if imap.is_null() || watch_folder.is_null() { - return; - } - free((*imap).watch_folder as *mut libc::c_void); - (*imap).watch_folder = dc_strdup(watch_folder); -} -pub unsafe fn dc_imap_is_connected(mut imap: *const dc_imap_t) -> libc::c_int { - return (!imap.is_null() && 0 != (*imap).connected) as libc::c_int; -} -pub unsafe fn dc_imap_fetch(mut imap: *mut dc_imap_t) -> libc::c_int { - let mut success: libc::c_int = 0i32; - if !(imap.is_null() || 0 == (*imap).connected) { - setup_handle_if_needed(imap); - while fetch_from_single_folder(imap, (*imap).watch_folder) > 0i32 {} - success = 1i32 - } - return success; -} -unsafe fn fetch_from_single_folder( - mut imap: *mut dc_imap_t, - mut folder: *const libc::c_char, -) -> libc::c_int { - let mut current_block: u64; - let mut r: libc::c_int = 0; - let mut uidvalidity: uint32_t = 0i32 as uint32_t; - let mut lastseenuid: uint32_t = 0i32 as uint32_t; - let mut new_lastseenuid: uint32_t = 0i32 as uint32_t; - let mut fetch_result: *mut clist = 0 as *mut clist; - let mut read_cnt: size_t = 0i32 as size_t; - let mut read_errors: size_t = 0i32 as size_t; - let mut cur: *mut clistiter = 0 as *mut clistiter; - let mut set: *mut mailimap_set = 0 as *mut mailimap_set; - if !imap.is_null() { - if (*imap).etpan.is_null() { - dc_log_info( - (*imap).context, - 0i32, - b"Cannot fetch from \"%s\" - not connected.\x00" as *const u8 - as *const libc::c_char, - folder, - ); - } else if select_folder(imap, folder) == 0i32 { - dc_log_warning( - (*imap).context, - 0i32, - b"Cannot select folder %s for fetching.\x00" as *const u8 as *const libc::c_char, - folder, - ); - } else { - get_config_lastseenuid(imap, folder, &mut uidvalidity, &mut lastseenuid); - if uidvalidity != (*(*(*imap).etpan).imap_selection_info).sel_uidvalidity { - /* first time this folder is selected or UIDVALIDITY has changed, init lastseenuid and save it to config */ - if (*(*(*imap).etpan).imap_selection_info).sel_uidvalidity <= 0i32 as libc::c_uint { - dc_log_error( - (*imap).context, - 0i32, - b"Cannot get UIDVALIDITY for folder \"%s\".\x00" as *const u8 - as *const libc::c_char, - folder, - ); - current_block = 17288151659885296046; - } else { - if 0 != (*(*(*imap).etpan).imap_selection_info).sel_has_exists() { - if (*(*(*imap).etpan).imap_selection_info).sel_exists - <= 0i32 as libc::c_uint - { - dc_log_info( - (*imap).context, - 0i32, - b"Folder \"%s\" is empty.\x00" as *const u8 as *const libc::c_char, - folder, - ); - if (*(*(*imap).etpan).imap_selection_info).sel_exists - == 0i32 as libc::c_uint - { - set_config_lastseenuid( - imap, - folder, - (*(*(*imap).etpan).imap_selection_info).sel_uidvalidity, - 0i32 as uint32_t, - ); - } - current_block = 17288151659885296046; - } else { - set = mailimap_set_new_single( - (*(*(*imap).etpan).imap_selection_info).sel_exists, - ); - current_block = 11057878835866523405; - } - } else { - dc_log_info( - (*imap).context, - 0i32, - b"EXISTS is missing for folder \"%s\", using fallback.\x00" as *const u8 - as *const libc::c_char, - folder, - ); - set = mailimap_set_new_single(0i32 as uint32_t); - current_block = 11057878835866523405; - } - match current_block { - 17288151659885296046 => {} - _ => { - r = mailimap_fetch( - (*imap).etpan, - set, - (*imap).fetch_type_prefetch, - &mut fetch_result, - ); - if !set.is_null() { - mailimap_set_free(set); - set = 0 as *mut mailimap_set - } - if 0 != dc_imap_is_error(imap, r) || fetch_result.is_null() { - fetch_result = 0 as *mut clist; - dc_log_info( - (*imap).context, - 0i32, - b"No result returned for folder \"%s\".\x00" as *const u8 - as *const libc::c_char, - folder, - ); - /* this might happen if the mailbox is empty an EXISTS does not work */ - current_block = 17288151659885296046; - } else { - cur = (*fetch_result).first; - if cur.is_null() { - dc_log_info( - (*imap).context, - 0i32, - b"Empty result returned for folder \"%s\".\x00" as *const u8 - as *const libc::c_char, - folder, - ); - /* this might happen if the mailbox is empty an EXISTS does not work */ - current_block = 17288151659885296046; - } else { - let mut msg_att: *mut mailimap_msg_att = (if !cur.is_null() { - (*cur).data - } else { - 0 as *mut libc::c_void - }) - as *mut mailimap_msg_att; - lastseenuid = peek_uid(msg_att); - if !fetch_result.is_null() { - mailimap_fetch_list_free(fetch_result); - fetch_result = 0 as *mut clist - } - if lastseenuid <= 0i32 as libc::c_uint { - dc_log_error( - (*imap).context, - 0i32, - b"Cannot get largest UID for folder \"%s\"\x00" - as *const u8 - as *const libc::c_char, - folder, - ); - current_block = 17288151659885296046; - } else { - if uidvalidity > 0i32 as libc::c_uint - && lastseenuid > 1i32 as libc::c_uint - { - lastseenuid = (lastseenuid as libc::c_uint) - .wrapping_sub(1i32 as libc::c_uint) - as uint32_t - as uint32_t - } - uidvalidity = - (*(*(*imap).etpan).imap_selection_info).sel_uidvalidity; - set_config_lastseenuid( - imap, - folder, - uidvalidity, - lastseenuid, - ); - dc_log_info( - (*imap).context, - 0i32, - b"lastseenuid initialized to %i for %s@%i\x00" - as *const u8 - as *const libc::c_char, - lastseenuid as libc::c_int, - folder, - uidvalidity as libc::c_int, - ); - current_block = 2516253395664191498; - } - } - } - } - } - } - } else { - current_block = 2516253395664191498; - } - match current_block { - 17288151659885296046 => {} - _ => { - set = mailimap_set_new_interval( - lastseenuid.wrapping_add(1i32 as libc::c_uint), - 0i32 as uint32_t, - ); - r = mailimap_uid_fetch( - (*imap).etpan, - set, - (*imap).fetch_type_prefetch, - &mut fetch_result, - ); - if !set.is_null() { - mailimap_set_free(set); - set = 0 as *mut mailimap_set - } - if 0 != dc_imap_is_error(imap, r) || fetch_result.is_null() { - fetch_result = 0 as *mut clist; - if r == MAILIMAP_ERROR_PROTOCOL as libc::c_int { - dc_log_info( - (*imap).context, - 0i32, - b"Folder \"%s\" is empty\x00" as *const u8 as *const libc::c_char, - folder, - ); - } else { - /* the folder is simply empty, this is no error */ - dc_log_warning( - (*imap).context, - 0i32, - b"Cannot fetch message list from folder \"%s\".\x00" as *const u8 - as *const libc::c_char, - folder, - ); - } - } else { - cur = (*fetch_result).first; - while !cur.is_null() { - let mut msg_att_0: *mut mailimap_msg_att = (if !cur.is_null() { - (*cur).data - } else { - 0 as *mut libc::c_void - }) - as *mut mailimap_msg_att; - let mut cur_uid: uint32_t = peek_uid(msg_att_0); - if cur_uid > lastseenuid { - let mut rfc724_mid: *mut libc::c_char = - unquote_rfc724_mid(peek_rfc724_mid(msg_att_0)); - read_cnt = read_cnt.wrapping_add(1); - if 0 == (*imap).precheck_imf.expect("non-null function pointer")( - imap, rfc724_mid, folder, cur_uid, - ) { - if fetch_single_msg(imap, folder, cur_uid) == 0i32 { - dc_log_info((*imap).context, 0i32, - b"Read error for message %s from \"%s\", trying over later.\x00" - as *const u8 as - *const libc::c_char, - rfc724_mid, folder); - read_errors = read_errors.wrapping_add(1) - } - } else { - dc_log_info( - (*imap).context, - 0i32, - b"Skipping message %s from \"%s\" by precheck.\x00" - as *const u8 - as *const libc::c_char, - rfc724_mid, - folder, - ); - } - if cur_uid > new_lastseenuid { - new_lastseenuid = cur_uid - } - free(rfc724_mid as *mut libc::c_void); - } - cur = if !cur.is_null() { - (*cur).next - } else { - 0 as *mut clistcell_s - } - } - if 0 == read_errors && new_lastseenuid > 0i32 as libc::c_uint { - set_config_lastseenuid(imap, folder, uidvalidity, new_lastseenuid); - } - } - } - } + match self { + Session::Secure(i) => i.uid_fetch(uid_set, query), + Session::Insecure(i) => i.uid_fetch(uid_set, query), } } - /* done */ - if 0 != read_errors { - dc_log_warning( - (*imap).context, - 0i32, - b"%i mails read from \"%s\" with %i errors.\x00" as *const u8 as *const libc::c_char, - read_cnt as libc::c_int, - folder, - read_errors as libc::c_int, - ); - } else { - dc_log_info( - (*imap).context, - 0i32, - b"%i mails read from \"%s\".\x00" as *const u8 as *const libc::c_char, - read_cnt as libc::c_int, - folder, - ); - } - if !fetch_result.is_null() { - mailimap_fetch_list_free(fetch_result); - fetch_result = 0 as *mut clist - } - return read_cnt as libc::c_int; -} -unsafe fn set_config_lastseenuid( - mut imap: *mut dc_imap_t, - mut folder: *const libc::c_char, - mut uidvalidity: uint32_t, - mut lastseenuid: uint32_t, -) { - let mut key: *mut libc::c_char = dc_mprintf( - b"imap.mailbox.%s\x00" as *const u8 as *const libc::c_char, - folder, - ); - let mut val: *mut libc::c_char = dc_mprintf( - b"%lu:%lu\x00" as *const u8 as *const libc::c_char, - uidvalidity, - lastseenuid, - ); - (*imap).set_config.expect("non-null function pointer")(imap, key, val); - free(val as *mut libc::c_void); - free(key as *mut libc::c_void); -} -unsafe fn peek_rfc724_mid(mut msg_att: *mut mailimap_msg_att) -> *const libc::c_char { - if msg_att.is_null() { - return 0 as *const libc::c_char; - } - /* search the UID in a list of attributes returned by a FETCH command */ - let mut iter1: *mut clistiter = 0 as *mut clistiter; - iter1 = (*(*msg_att).att_list).first; - while !iter1.is_null() { - let mut item: *mut mailimap_msg_att_item = (if !iter1.is_null() { - (*iter1).data - } else { - 0 as *mut libc::c_void - }) as *mut mailimap_msg_att_item; - if !item.is_null() { - if (*item).att_type == MAILIMAP_MSG_ATT_ITEM_STATIC as libc::c_int { - if (*(*item).att_data.att_static).att_type - == MAILIMAP_MSG_ATT_ENVELOPE as libc::c_int - { - let mut env: *mut mailimap_envelope = - (*(*item).att_data.att_static).att_data.att_env; - if !env.is_null() && !(*env).env_message_id.is_null() { - return (*env).env_message_id; - } - } - } - } - iter1 = if !iter1.is_null() { - (*iter1).next - } else { - 0 as *mut clistcell_s + + pub fn idle(&mut self) -> imap::error::Result { + match self { + Session::Secure(i) => i.idle().map(Into::into), + Session::Insecure(i) => i.idle().map(Into::into), } } - return 0 as *const libc::c_char; -} -unsafe fn unquote_rfc724_mid(mut in_0: *const libc::c_char) -> *mut libc::c_char { - /* remove < and > from the given message id */ - let mut out: *mut libc::c_char = dc_strdup(in_0); - let mut out_len: libc::c_int = strlen(out) as libc::c_int; - if out_len > 2i32 { - if *out.offset(0isize) as libc::c_int == '<' as i32 { - *out.offset(0isize) = ' ' as i32 as libc::c_char - } - if *out.offset((out_len - 1i32) as isize) as libc::c_int == '>' as i32 { - *out.offset((out_len - 1i32) as isize) = ' ' as i32 as libc::c_char - } - dc_trim(out); - } - return out; -} -/* ****************************************************************************** - * Fetch Messages - ******************************************************************************/ -unsafe fn peek_uid(mut msg_att: *mut mailimap_msg_att) -> uint32_t { - /* search the UID in a list of attributes returned by a FETCH command */ - let mut iter1: *mut clistiter = 0 as *mut clistiter; - iter1 = (*(*msg_att).att_list).first; - while !iter1.is_null() { - let mut item: *mut mailimap_msg_att_item = (if !iter1.is_null() { - (*iter1).data - } else { - 0 as *mut libc::c_void - }) as *mut mailimap_msg_att_item; - if !item.is_null() { - if (*item).att_type == MAILIMAP_MSG_ATT_ITEM_STATIC as libc::c_int { - if (*(*item).att_data.att_static).att_type == MAILIMAP_MSG_ATT_UID as libc::c_int { - return (*(*item).att_data.att_static).att_data.att_uid; - } - } - } - iter1 = if !iter1.is_null() { - (*iter1).next - } else { - 0 as *mut clistcell_s - } - } - return 0i32 as uint32_t; -} -unsafe fn fetch_single_msg( - mut imap: *mut dc_imap_t, - mut folder: *const libc::c_char, - mut server_uid: uint32_t, -) -> libc::c_int { - let mut msg_att: *mut mailimap_msg_att = 0 as *mut mailimap_msg_att; - /* the function returns: - 0 the caller should try over again later - or 1 if the messages should be treated as received, the caller should not try to read the message again (even if no database entries are returned) */ - let mut msg_content: *mut libc::c_char = 0 as *mut libc::c_char; - let mut msg_bytes: size_t = 0i32 as size_t; - let mut r: libc::c_int = 0i32; - let mut retry_later: libc::c_int = 0i32; - let mut deleted: libc::c_int = 0i32; - let mut flags: uint32_t = 0i32 as uint32_t; - let mut fetch_result: *mut clist = 0 as *mut clist; - let mut cur: *mut clistiter = 0 as *mut clistiter; - if !imap.is_null() { - if !(*imap).etpan.is_null() { - let mut set: *mut mailimap_set = mailimap_set_new_single(server_uid); - r = mailimap_uid_fetch( - (*imap).etpan, - set, - (*imap).fetch_type_body, - &mut fetch_result, - ); - if !set.is_null() { - mailimap_set_free(set); - set = 0 as *mut mailimap_set - } - if 0 != dc_imap_is_error(imap, r) || fetch_result.is_null() { - fetch_result = 0 as *mut clist; - dc_log_warning( - (*imap).context, - 0i32, - b"Error #%i on fetching message #%i from folder \"%s\"; retry=%i.\x00" - as *const u8 as *const libc::c_char, - r as libc::c_int, - server_uid as libc::c_int, - folder, - (*imap).should_reconnect as libc::c_int, - ); - if 0 != (*imap).should_reconnect { - retry_later = 1i32 - } - } else { - /* this is an error that should be recovered; the caller should try over later to fetch the message again (if there is no such message, we simply get an empty result) */ - cur = (*fetch_result).first; - if cur.is_null() { - dc_log_warning( - (*imap).context, - 0i32, - b"Message #%i does not exist in folder \"%s\".\x00" as *const u8 - as *const libc::c_char, - server_uid as libc::c_int, - folder, - ); - } else { - /* server response is fine, however, there is no such message, do not try to fetch the message again */ - msg_att = (if !cur.is_null() { - (*cur).data - } else { - 0 as *mut libc::c_void - }) as *mut mailimap_msg_att; - peek_body( - msg_att, - &mut msg_content, - &mut msg_bytes, - &mut flags, - &mut deleted, - ); - if !(msg_content.is_null() || msg_bytes <= 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")( - imap, - msg_content, - msg_bytes, - folder, - server_uid, - flags, - ); - } - } - } - } - } - if !fetch_result.is_null() { - mailimap_fetch_list_free(fetch_result); - fetch_result = 0 as *mut clist - } - return if 0 != retry_later { 0i32 } else { 1i32 }; -} -unsafe fn peek_body( - mut msg_att: *mut mailimap_msg_att, - mut p_msg: *mut *mut libc::c_char, - mut p_msg_bytes: *mut size_t, - mut flags: *mut uint32_t, - mut deleted: *mut libc::c_int, -) { - if msg_att.is_null() { - return; - } - /* search body & Co. in a list of attributes returned by a FETCH command */ - let mut iter1: *mut clistiter = 0 as *mut clistiter; - let mut iter2: *mut clistiter = 0 as *mut clistiter; - iter1 = (*(*msg_att).att_list).first; - while !iter1.is_null() { - let mut item: *mut mailimap_msg_att_item = (if !iter1.is_null() { - (*iter1).data - } else { - 0 as *mut libc::c_void - }) as *mut mailimap_msg_att_item; - if !item.is_null() { - if (*item).att_type == MAILIMAP_MSG_ATT_ITEM_DYNAMIC as libc::c_int { - if !(*(*item).att_data.att_dyn).att_list.is_null() { - iter2 = (*(*(*item).att_data.att_dyn).att_list).first; - while !iter2.is_null() { - let mut flag_fetch: *mut mailimap_flag_fetch = (if !iter2.is_null() { - (*iter2).data - } else { - 0 as *mut libc::c_void - }) - as *mut mailimap_flag_fetch; - if !flag_fetch.is_null() - && (*flag_fetch).fl_type == MAILIMAP_FLAG_FETCH_OTHER as libc::c_int - { - let mut flag: *mut mailimap_flag = (*flag_fetch).fl_flag; - if !flag.is_null() { - if (*flag).fl_type == MAILIMAP_FLAG_SEEN as libc::c_int { - *flags = (*flags as libc::c_long | 0x1) as uint32_t - } else if (*flag).fl_type == MAILIMAP_FLAG_DELETED as libc::c_int { - *deleted = 1i32 - } - } - } - iter2 = if !iter2.is_null() { - (*iter2).next - } else { - 0 as *mut clistcell_s - } - } - } - } else if (*item).att_type == MAILIMAP_MSG_ATT_ITEM_STATIC as libc::c_int { - if (*(*item).att_data.att_static).att_type - == MAILIMAP_MSG_ATT_BODY_SECTION as libc::c_int - { - *p_msg = - (*(*(*item).att_data.att_static).att_data.att_body_section).sec_body_part; - *p_msg_bytes = - (*(*(*item).att_data.att_static).att_data.att_body_section).sec_length - } - } - } - iter1 = if !iter1.is_null() { - (*iter1).next - } else { - 0 as *mut clistcell_s - } - } -} -unsafe fn get_config_lastseenuid( - mut imap: *mut dc_imap_t, - mut folder: *const libc::c_char, - mut uidvalidity: *mut uint32_t, - mut lastseenuid: *mut uint32_t, -) { - *uidvalidity = 0i32 as uint32_t; - *lastseenuid = 0i32 as uint32_t; - let mut key: *mut libc::c_char = dc_mprintf( - b"imap.mailbox.%s\x00" as *const u8 as *const libc::c_char, - folder, - ); - let mut val1: *mut libc::c_char = - (*imap).get_config.expect("non-null function pointer")(imap, key, 0 as *const libc::c_char); - let mut val2: *mut libc::c_char = 0 as *mut libc::c_char; - let mut val3: *mut libc::c_char = 0 as *mut libc::c_char; - if !val1.is_null() { - val2 = strchr(val1, ':' as i32); - if !val2.is_null() { - *val2 = 0i32 as libc::c_char; - val2 = val2.offset(1isize); - val3 = strchr(val2, ':' as i32); - if !val3.is_null() { - *val3 = 0i32 as libc::c_char - } - *uidvalidity = atol(val1) as uint32_t; - *lastseenuid = atol(val2) as uint32_t - } - } - free(val1 as *mut libc::c_void); - free(key as *mut libc::c_void); -} -/* ****************************************************************************** - * Handle folders - ******************************************************************************/ -unsafe fn select_folder(mut imap: *mut dc_imap_t, mut folder: *const libc::c_char) -> libc::c_int { - if imap.is_null() { - return 0i32; - } - if (*imap).etpan.is_null() { - *(*imap).selected_folder.offset(0isize) = 0i32 as libc::c_char; - (*imap).selected_folder_needs_expunge = 0i32; - return 0i32; - } - if !folder.is_null() - && 0 != *folder.offset(0isize) as libc::c_int - && strcmp((*imap).selected_folder, folder) == 0i32 + + pub fn uid_store( + &mut self, + uid_set: S1, + query: S2, + ) -> imap::error::Result>> + where + S1: AsRef, + S2: AsRef, { - return 1i32; - } - if 0 != (*imap).selected_folder_needs_expunge { - if 0 != *(*imap).selected_folder.offset(0isize) { - dc_log_info( - (*imap).context, - 0i32, - b"Expunge messages in \"%s\".\x00" as *const u8 as *const libc::c_char, - (*imap).selected_folder, - ); - mailimap_close((*imap).etpan); - } - (*imap).selected_folder_needs_expunge = 0i32 - } - if !folder.is_null() { - let mut r: libc::c_int = mailimap_select((*imap).etpan, folder); - if 0 != dc_imap_is_error(imap, r) || (*(*imap).etpan).imap_selection_info.is_null() { - dc_log_info( - (*imap).context, - 0i32, - b"Cannot select folder; code=%i, imap_response=%s\x00" as *const u8 - as *const libc::c_char, - r, - if !(*(*imap).etpan).imap_response.is_null() { - (*(*imap).etpan).imap_response - } else { - b"\x00" as *const u8 as *const libc::c_char - }, - ); - *(*imap).selected_folder.offset(0isize) = 0i32 as libc::c_char; - return 0i32; + match self { + Session::Secure(i) => i.uid_store(uid_set, query), + Session::Insecure(i) => i.uid_store(uid_set, query), + } + } + + pub fn uid_mv, S2: AsRef>( + &mut self, + uid_set: S1, + mailbox_name: S2, + ) -> imap::error::Result<()> { + match self { + Session::Secure(i) => i.uid_mv(uid_set, mailbox_name), + Session::Insecure(i) => i.uid_mv(uid_set, mailbox_name), + } + } + + pub fn uid_copy, S2: AsRef>( + &mut self, + uid_set: S1, + mailbox_name: S2, + ) -> imap::error::Result<()> { + match self { + Session::Secure(i) => i.uid_copy(uid_set, mailbox_name), + Session::Insecure(i) => i.uid_copy(uid_set, mailbox_name), } } - free((*imap).selected_folder as *mut libc::c_void); - (*imap).selected_folder = dc_strdup(folder); - return 1i32; } -pub unsafe fn dc_imap_idle(mut imap: *mut dc_imap_t) { - let mut current_block: u64; - let mut r: libc::c_int = 0i32; - let mut r2: libc::c_int = 0i32; - if !imap.is_null() { - if 0 != (*imap).can_idle { - setup_handle_if_needed(imap); - if (*imap).idle_set_up == 0i32 - && !(*imap).etpan.is_null() - && !(*(*imap).etpan).imap_stream.is_null() - { - r = mailstream_setup_idle((*(*imap).etpan).imap_stream); - if 0 != dc_imap_is_error(imap, r) { - dc_log_warning( - (*imap).context, - 0i32, - b"IMAP-IDLE: Cannot setup.\x00" as *const u8 as *const libc::c_char, - ); - fake_idle(imap); - current_block = 14832935472441733737; - } else { - (*imap).idle_set_up = 1i32; - current_block = 17965632435239708295; - } - } else { - current_block = 17965632435239708295; - } - match current_block { - 14832935472441733737 => {} - _ => { - if 0 == (*imap).idle_set_up || 0 == select_folder(imap, (*imap).watch_folder) { - dc_log_warning( - (*imap).context, - 0i32, - b"IMAP-IDLE not setup.\x00" as *const u8 as *const libc::c_char, - ); - fake_idle(imap); - } else { - r = mailimap_idle((*imap).etpan); - if 0 != dc_imap_is_error(imap, r) { - dc_log_warning( - (*imap).context, - 0i32, - b"IMAP-IDLE: Cannot start.\x00" as *const u8 as *const libc::c_char, - ); - fake_idle(imap); - } else { - r = mailstream_wait_idle((*(*imap).etpan).imap_stream, 23i32 * 60i32); - r2 = mailimap_idle_done((*imap).etpan); - if r == MAILSTREAM_IDLE_ERROR as libc::c_int - || r == MAILSTREAM_IDLE_CANCELLED as libc::c_int - { - dc_log_info((*imap).context, 0i32, - b"IMAP-IDLE wait cancelled, r=%i, r2=%i; we\'ll reconnect soon.\x00" - as *const u8 as - *const libc::c_char, r, r2); - (*imap).should_reconnect = 1i32 - } else if r == MAILSTREAM_IDLE_INTERRUPTED as libc::c_int { - dc_log_info( - (*imap).context, - 0i32, - b"IMAP-IDLE interrupted.\x00" as *const u8 - as *const libc::c_char, - ); - } else if r == MAILSTREAM_IDLE_HASDATA as libc::c_int { - dc_log_info( - (*imap).context, - 0i32, - b"IMAP-IDLE has data.\x00" as *const u8 as *const libc::c_char, - ); - } else if r == MAILSTREAM_IDLE_TIMEOUT as libc::c_int { - dc_log_info( - (*imap).context, - 0i32, - b"IMAP-IDLE timeout.\x00" as *const u8 as *const libc::c_char, - ); - } else { - dc_log_warning( - (*imap).context, - 0i32, - b"IMAP-IDLE returns unknown value r=%i, r2=%i.\x00" as *const u8 - as *const libc::c_char, - r, - r2, - ); - } - } - } - } - } - } else { - fake_idle(imap); - } - }; + +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 selected_folder: Option, + pub selected_mailbox: Option, + pub selected_folder_needs_expunge: bool, + pub should_reconnect: bool, + pub can_idle: bool, + pub has_xlist: bool, + pub imap_delimiter: char, + pub watch_folder: Option, } -unsafe fn fake_idle(mut imap: *mut dc_imap_t) { - /* Idle using timeouts. This is also needed if we're not yet configured - - in this case, we're waiting for a configure job */ - let mut fake_idle_start_time: time_t = time(0 as *mut time_t); - let mut seconds_to_wait: time_t = 0i32 as time_t; - dc_log_info( - (*imap).context, - 0i32, - b"IMAP-fake-IDLEing...\x00" as *const u8 as *const libc::c_char, - ); - let mut do_fake_idle: libc::c_int = 1i32; - while 0 != do_fake_idle { - seconds_to_wait = - (if time(0 as *mut time_t) - fake_idle_start_time < (3i32 * 60i32) as libc::c_long { - 5i32 - } else { - 60i32 - }) as time_t; - pthread_mutex_lock(&mut (*imap).watch_condmutex); - let mut r: libc::c_int = 0i32; - let mut wakeup_at: timespec = timespec { - tv_sec: 0, - tv_nsec: 0, + +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, + selected_folder: None, + selected_mailbox: None, + selected_folder_needs_expunge: false, + should_reconnect: false, + can_idle: false, + has_xlist: false, + imap_delimiter: '.', + watch_folder: None, }; - memset( - &mut wakeup_at as *mut timespec as *mut libc::c_void, - 0, - ::std::mem::size_of::(), - ); - wakeup_at.tv_sec = time(0 as *mut time_t) + seconds_to_wait; - while (*imap).watch_condflag == 0i32 && r == 0i32 { - r = pthread_cond_timedwait( - &mut (*imap).watch_cond, - &mut (*imap).watch_condmutex, - &mut wakeup_at, - ); - if 0 != (*imap).watch_condflag { - do_fake_idle = 0i32 + + cfg + } +} + +impl Imap { + 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 { + Imap { + session: Arc::new(Mutex::new(None)), + // idle: 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, + } + } + + pub fn is_connected(&self) -> bool { + self.session.lock().unwrap().is_some() + } + + pub fn should_reconnect(&self) -> bool { + self.config.read().unwrap().should_reconnect + } + + pub fn connect(&self, context: &dc_context_t, lp: *const dc_loginparam_t) -> libc::c_int { + if lp.is_null() { + return 0; + } + let lp = unsafe { *lp }; + if lp.mail_server.is_null() || lp.mail_user.is_null() || lp.mail_pw.is_null() { + return 0; + } + + 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 { + 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 { + Ok(client.into()) + } + }) + } else { + 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) => { + // TODO: handle oauth2 + match client.login(imap_user, imap_pw) { + Ok(mut session) => { + // 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(); + + info!(context, 0, "IMAP-capabilities:%s", caps_list_c.as_ptr()); + + let mut config = self.config.write().unwrap(); + config.can_idle = can_idle; + config.has_xlist = has_xlist; + config.addr = Some(addr.into()); + config.imap_server = Some(imap_server.into()); + config.imap_port = Some(imap_port.into()); + config.imap_user = Some(imap_user.into()); + config.imap_pw = Some(imap_pw.into()); + config.server_flags = Some(server_flags); + + *self.session.lock().unwrap() = Some(session); + + 1 + } + Err((err, _)) => { + eprintln!("failed to login: {:?}", err); + + unsafe { + dc_log_event_seq( + context, + 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 } } - (*imap).watch_condflag = 0i32; - pthread_mutex_unlock(&mut (*imap).watch_condmutex); - if do_fake_idle == 0i32 { + } + + pub fn disconnect(&self, context: &dc_context_t) { + let mut session = self.session.lock().unwrap().take(); + if session.is_some() { + match session.unwrap().close() { + Ok(_) => {} + Err(err) => { + eprintln!("failed to close connection: {:?}", err); + } + } + } + + let mut cfg = self.config.write().unwrap(); + + cfg.addr = None; + cfg.imap_server = None; + cfg.imap_user = None; + cfg.imap_pw = None; + cfg.imap_port = None; + + cfg.can_idle = false; + cfg.has_xlist = false; + + cfg.watch_folder = None; + cfg.selected_folder = None; + cfg.selected_mailbox = None; + info!(context, 0, "IMAP disconnected.",); + } + + pub fn set_watch_folder(&self, watch_folder: *const libc::c_char) { + self.config.write().unwrap().watch_folder = Some(to_string(watch_folder)); + } + + pub fn fetch(&self, context: &dc_context_t) -> libc::c_int { + let mut success = 0; + + let watch_folder = self.config.read().unwrap().watch_folder.to_owned(); + if self.is_connected() && watch_folder.is_some() { + let watch_folder = watch_folder.unwrap(); + loop { + let cnt = self.fetch_from_single_folder(context, &watch_folder); + if cnt == 0 { + break; + } + } + success = 1; + } + + success + } + + fn select_folder>(&self, context: &dc_context_t, folder: Option) -> usize { + if !self.is_connected() { + let mut cfg = self.config.write().unwrap(); + cfg.selected_folder = None; + cfg.selected_folder_needs_expunge = false; + return 0; + } + + // if there is a new folder and the new folder is equal to the selected one, there's nothing to do. + // if there is _no_ new folder, we continue as we might want to expunge below. + if let Some(ref folder) = folder { + if let Some(ref selected_folder) = self.config.read().unwrap().selected_folder { + if folder.as_ref() == selected_folder { + return 1; + } + } + } + + // deselect existing folder, if needed (it's also done implicitly by SELECT, however, without EXPUNGE then) + if self.config.read().unwrap().selected_folder_needs_expunge { + if let Some(ref folder) = self.config.read().unwrap().selected_folder { + info!( + context, + 0, + "Expunge messages in \"%s\".", + CString::new(folder.to_owned()).unwrap().as_ptr() + ); + + // a CLOSE-SELECT is considerably faster than an EXPUNGE-SELECT, see https://tools.ietf.org/html/rfc3501#section-6.4.2 + if let Some(ref mut session) = *self.session.lock().unwrap() { + session.close().expect("failed to expunge"); + } else { + return 0; + } + } + } + + // select new folder + if let Some(folder) = folder { + if let Some(ref mut session) = *self.session.lock().unwrap() { + match session.select(folder) { + Ok(mailbox) => { + self.config.write().unwrap().selected_mailbox = Some(mailbox); + } + Err(err) => { + eprintln!("select error: {:?}", err); + info!(context, 0, "Cannot select folder."); + self.config.write().unwrap().selected_folder = None; + } + } + } else { + return 0; + } + } + + 1 + } + + fn get_config_last_seen_uid>( + &self, + context: &dc_context_t, + folder: S, + ) -> (u32, u32) { + let key = format!("imap.mailbox.{}", folder.as_ref()); + let val1 = unsafe { + (self.get_config)( + context, + CString::new(key).unwrap().as_ptr(), + 0 as *const libc::c_char, + ) + }; + if val1.is_null() { + return (0, 0); + } + let entry = to_str(val1); + + // the entry has the format `imap.mailbox.=:` + let mut parts = entry.split(':'); + ( + parts.next().unwrap().parse().unwrap_or_else(|_| 0), + parts.next().unwrap().parse().unwrap_or_else(|_| 0), + ) + } + + fn fetch_from_single_folder>(&self, context: &dc_context_t, folder: S) -> usize { + if !self.is_connected() { + info!( + context, + 0, + "Cannot fetch from \"%s\" - not connected.", + CString::new(folder.as_ref().to_owned()).unwrap().as_ptr(), + ); + + return 0; + } + + if self.select_folder(context, Some(&folder)) == 0 { + info!( + context, + 0, + "Cannot select folder \"%s\" for fetching.", + CString::new(folder.as_ref().to_owned()).unwrap().as_ptr(), + ); + + return 0; + } + + let (mut uid_validity, mut last_seen_uid) = self.get_config_last_seen_uid(context, &folder); + + let config = self.config.read().unwrap(); + let mailbox = config.selected_mailbox.as_ref().expect("just selected"); + + if mailbox.uid_validity.is_none() { + error!( + context, + 0, + "Cannot get UIDVALIDITY for folder \"%s\".", + CString::new(folder.as_ref().to_owned()).unwrap().as_ptr(), + ); + + return 0; + } + + if mailbox.uid_validity.unwrap() != uid_validity { + // first time this folder is selected or UIDVALIDITY has changed, init lastseenuid and save it to config + + if mailbox.exists == 0 { + info!( + context, + 0, + "Folder \"%s\" is empty.", + CString::new(folder.as_ref().to_owned()).unwrap().as_ptr() + ); + + // set lastseenuid=0 for empty folders. + // id we do not do this here, we'll miss the first message + // as we will get in here again and fetch from lastseenuid+1 then + + self.set_config_last_seen_uid(context, &folder, mailbox.uid_validity.unwrap(), 0); + return 0; + } + + let list = if let Some(ref mut session) = *self.session.lock().unwrap() { + // `FETCH (UID)` + let set = format!("{}", mailbox.exists); + match session.fetch(set, PREFETCH_FLAGS) { + Ok(list) => list, + Err(err) => { + eprintln!("fetch error: {:?}", err); + info!( + context, + 0, + "No result returned for folder \"%s\".", + CString::new(folder.as_ref().to_owned()).unwrap().as_ptr() + ); + + return 0; + } + } + } else { + return 0; + }; + + last_seen_uid = list[0].uid.unwrap_or_else(|| 0); + + // if the UIDVALIDITY has _changed_, decrease lastseenuid by one to avoid gaps (well add 1 below + if uid_validity > 0 && last_seen_uid > 1 { + last_seen_uid -= 1; + } + + uid_validity = mailbox.uid_validity.unwrap(); + self.set_config_last_seen_uid(context, &folder, uid_validity, last_seen_uid); + info!( + context, + 0, + "lastseenuid initialized to %i for %s@%i", + last_seen_uid as libc::c_int, + CString::new(folder.as_ref().to_owned()).unwrap().as_ptr(), + uid_validity as libc::c_int + ); + } + + let mut read_cnt = 0; + let mut read_errors = 0; + let mut new_last_seen_uid = 0; + + let list = if let Some(ref mut session) = *self.session.lock().unwrap() { + // fetch messages with larger UID than the last one seen + // (`UID FETCH lastseenuid+1:*)`, see RFC 4549 + let set = format!("{}:*", last_seen_uid + 1); + match session.uid_fetch(set, PREFETCH_FLAGS) { + Ok(list) => list, + Err(err) => { + eprintln!("fetch err: {:?}", err); + return 0; + } + } + } else { + return 0; + }; + + // go through all mails in folder (this is typically _fast_ as we already have the whole list) + + for msg in &list { + let cur_uid = msg.uid.unwrap_or_else(|| 0); + if cur_uid > last_seen_uid { + read_cnt += 1; + + let message_id = msg + .envelope() + .expect("missing envelope") + .message_id + .expect("missing message id"); + + let message_id_c = CString::new(message_id).unwrap(); + let folder_c = CString::new(folder.as_ref().to_owned()).unwrap(); + if 0 == unsafe { + (self.precheck_imf)(context, message_id_c.as_ptr(), folder_c.as_ptr(), cur_uid) + } { + // check passed, go fetch the rest + if self.fetch_single_msg(context, &folder, cur_uid) == 0 { + info!( + context, + 0, + "Read error for message %s from \"%s\", trying over later.", + message_id_c.as_ptr(), + folder_c.as_ptr() + ); + + read_errors += 1; + } + } else { + // check failed + info!( + context, + 0, + "Skipping message %s from \"%s\" by precheck.", + message_id_c.as_ptr(), + folder_c.as_ptr() + ); + } + if cur_uid > new_last_seen_uid { + new_last_seen_uid = cur_uid + } + } + } + + if 0 == read_errors && new_last_seen_uid > 0 { + // TODO: it might be better to increase the lastseenuid also on partial errors. + // however, this requires to sort the list before going through it above. + self.set_config_last_seen_uid(context, &folder, uid_validity, new_last_seen_uid); + } + + if read_errors > 0 { + warn!( + context, + 0, + "%i mails read from \"%s\" with %i errors.", + read_cnt as libc::c_int, + CString::new(folder.as_ref().to_owned()).unwrap().as_ptr(), + read_errors as libc::c_int, + ); + } else { + info!( + context, + 0, + "%i mails read from \"%s\".", + read_cnt as libc::c_int, + CString::new(folder.as_ref().to_owned()).unwrap().as_ptr() + ); + } + + read_cnt + } + + fn set_config_last_seen_uid>( + &self, + context: &dc_context_t, + folder: S, + uidvalidity: u32, + lastseenuid: u32, + ) { + let key = format!("imap.mailbox.{}", folder.as_ref()); + let val = format!("{}:{}", uidvalidity, lastseenuid); + + unsafe { + (self.set_config)( + context, + CString::new(key).unwrap().as_ptr(), + CString::new(val).unwrap().as_ptr(), + ) + }; + } + + fn fetch_single_msg>( + &self, + context: &dc_context_t, + folder: S, + server_uid: u32, + ) -> usize { + // 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) + if !self.is_connected() { + return 0; + } + + let mut retry_later = false; + + let msgs = if let Some(ref mut session) = *self.session.lock().unwrap() { + let set = format!("{}", server_uid); + match session.uid_fetch(set, BODY_FLAGS) { + Ok(msgs) => msgs, + Err(err) => { + eprintln!("error fetch single: {:?}", err); + warn!( + context, + 0, + "Error on fetching message #%i from folder \"%s\"; retry=%i.", + server_uid as libc::c_int, + CString::new(folder.as_ref().to_owned()).unwrap().as_ptr(), + self.should_reconnect() as libc::c_int, + ); + + if self.should_reconnect() { + retry_later = true; + } + + return if retry_later { 0 } else { 1 }; + } + } + } else { + return if retry_later { 0 } else { 1 }; + }; + + if msgs.is_empty() { + warn!( + context, + 0, + "Message #%i does not exist in folder \"%s\".", + server_uid as libc::c_int, + CString::new(folder.as_ref().to_owned()).unwrap().as_ptr(), + ); + } else { + let msg = &msgs[0]; + + let is_deleted = msg + .flags() + .iter() + .find(|flag| match flag { + imap::types::Flag::Deleted => true, + _ => false, + }) + .is_some(); + let is_seen = msg + .flags() + .iter() + .find(|flag| match flag { + imap::types::Flag::Seen => true, + _ => false, + }) + .is_some(); + + let flags = if is_seen { DC_IMAP_SEEN } else { 0 }; + + if !is_deleted && msg.body().is_some() { + unsafe { + let folder_c = CString::new(folder.as_ref().to_owned()).unwrap(); + (self.receive_imf)( + context, + msg.body().unwrap().as_ptr() as *const libc::c_char, + msg.body().unwrap().len(), + folder_c.as_ptr(), + server_uid, + flags as u32, + ); + } + } + } + + if retry_later { + 0 + } else { + 1 + } + } + + pub fn idle(&self, context: &dc_context_t) { + if !self.config.read().unwrap().can_idle { + return self.fake_idle(context); + } + + // TODO: reconnect in all methods that need it + if !self.is_connected() { return; } - if 0 != setup_handle_if_needed(imap) { - if 0 != fetch_from_single_folder(imap, (*imap).watch_folder) { - do_fake_idle = 0i32 + + let watch_folder = self.config.read().unwrap().watch_folder.clone(); + if self.select_folder(context, watch_folder.as_ref()) == 0 { + warn!(context, 0, "IMAP-IDLE not setup.",); + + return self.fake_idle(context); + } + + // let mut session = self.session.lock().unwrap().take().unwrap(); + + // match RentSession::try_new(Box::new(session), |session| session.idle()) { + // Ok(idle) => { + // *self.idle.lock().unwrap() = Some(idle); + // } + // Err(err) => { + // eprintln!("imap idle error: {:?}", err.0); + // unsafe { + // dc_log_warning( + // context, + // 0, + // b"IMAP-IDLE: Cannot start.\x00" as *const u8 as *const libc::c_char, + // ); + // } + + // // put session back + // *self.session.lock().unwrap() = Some(*err.1); + + // return self.fake_idle(context); + // } + // } + + let mut session = self.session.lock().unwrap().take().unwrap(); + let mut idle = match session.idle() { + Ok(idle) => idle, + Err(err) => { + eprintln!("imap idle error: {:?}", err); + warn!(context, 0, "IMAP-IDLE: Cannot start.",); + + return self.fake_idle(context); + } + }; + + // most servers do not allow more than ~28 minutes; stay clearly below that. + // a good value that is also used by other MUAs is 23 minutes. + // if needed, the ui can call dc_imap_interrupt_idle() to trigger a reconnect. + idle.set_keepalive(Duration::from_secs(23 * 60)); + + // TODO: proper logging of different states + // TODO: reconnect if we timed out + match idle.wait_keepalive() { + Ok(_) => {} + Err(err) => { + eprintln!("idle error: {:?}", err); } - } else { - fake_idle_start_time = 0i32 as time_t } + + // put session back + *self.session.lock().unwrap() = Some(session); } -} -pub unsafe fn dc_imap_interrupt_idle(mut imap: *mut dc_imap_t) { - if imap.is_null() { - return; - } - if 0 != (*imap).can_idle { - if !(*imap).etpan.is_null() && !(*(*imap).etpan).imap_stream.is_null() { - mailstream_interrupt_idle((*(*imap).etpan).imap_stream); - } - } - pthread_mutex_lock(&mut (*imap).watch_condmutex); - (*imap).watch_condflag = 1i32; - pthread_cond_signal(&mut (*imap).watch_cond); - pthread_mutex_unlock(&mut (*imap).watch_condmutex); -} -pub unsafe fn dc_imap_move( - mut imap: *mut dc_imap_t, - mut folder: *const libc::c_char, - mut uid: uint32_t, - mut dest_folder: *const libc::c_char, - mut dest_uid: *mut uint32_t, -) -> dc_imap_res { - let mut current_block: u64; - let mut res: dc_imap_res = DC_RETRY_LATER; - let mut r: libc::c_int = 0i32; - let mut set: *mut mailimap_set = mailimap_set_new_single(uid); - let mut res_uid: uint32_t = 0i32 as uint32_t; - let mut res_setsrc: *mut mailimap_set = 0 as *mut mailimap_set; - let mut res_setdest: *mut mailimap_set = 0 as *mut mailimap_set; - if imap.is_null() - || folder.is_null() - || uid == 0i32 as libc::c_uint - || dest_folder.is_null() - || dest_uid.is_null() - || set.is_null() - { - res = DC_FAILED - } else if strcasecmp(folder, dest_folder) == 0i32 { - dc_log_info( - (*imap).context, - 0i32, - b"Skip moving message; message %s/%i is already in %s...\x00" as *const u8 - as *const libc::c_char, - folder, - uid as libc::c_int, - dest_folder, - ); - res = DC_ALREADY_DONE - } else { - dc_log_info( - (*imap).context, - 0i32, - b"Moving message %s/%i to %s...\x00" as *const u8 as *const libc::c_char, - folder, - uid as libc::c_int, - dest_folder, - ); - if select_folder(imap, folder) == 0i32 { - dc_log_warning( - (*imap).context, - 0i32, - b"Cannot select folder %s for moving message.\x00" as *const u8 - as *const libc::c_char, - folder, - ); - } else { - r = mailimap_uidplus_uid_move( - (*imap).etpan, - set, - dest_folder, - &mut res_uid, - &mut res_setsrc, - &mut res_setdest, - ); - if 0 != dc_imap_is_error(imap, r) { - if !res_setsrc.is_null() { - mailimap_set_free(res_setsrc); - res_setsrc = 0 as *mut mailimap_set - } - if !res_setdest.is_null() { - mailimap_set_free(res_setdest); - res_setdest = 0 as *mut mailimap_set - } - dc_log_info( - (*imap).context, - 0i32, - b"Cannot move message, fallback to COPY/DELETE %s/%i to %s...\x00" as *const u8 - as *const libc::c_char, - folder, - uid as libc::c_int, - dest_folder, - ); - r = mailimap_uidplus_uid_copy( - (*imap).etpan, - set, - dest_folder, - &mut res_uid, - &mut res_setsrc, - &mut res_setdest, - ); - if 0 != dc_imap_is_error(imap, r) { - dc_log_info( - (*imap).context, - 0i32, - b"Cannot copy message.\x00" as *const u8 as *const libc::c_char, - ); - current_block = 14415637129417834392; + + fn fake_idle(&self, context: &dc_context_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(); + + info!(context, 0, "IMAP-fake-IDLEing..."); + + let mut do_fake_idle = true; + while do_fake_idle { + let seconds_to_wait = + if fake_idle_start_time.elapsed().unwrap() < Duration::new(3 * 60, 0) { + Duration::new(5, 0) } else { - if add_flag(imap, uid, mailimap_flag_new_deleted()) == 0i32 { - dc_log_warning( - (*imap).context, - 0i32, - b"Cannot mark message as \"Deleted\".\x00" as *const u8 - as *const libc::c_char, - ); - } - (*imap).selected_folder_needs_expunge = 1i32; - current_block = 1538046216550696469; + Duration::new(60, 0) + }; + + let &(ref lock, ref cvar) = &*self.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 = false; } + if *watch || res.1.timed_out() { + break; + } + } + + *watch = false; + + if !do_fake_idle { + return; + } + + // TODO: connect if needed + if let Some(ref watch_folder) = self.config.read().unwrap().watch_folder { + if 0 != self.fetch_from_single_folder(context, watch_folder) { + do_fake_idle = false; + } + } + } + } + + pub fn interrupt_idle(&self) { + // TODO: interrupt real idle + // ref: https://github.com/jonhoo/rust-imap/issues/121 + + let &(ref lock, ref cvar) = &*self.watch.clone(); + let mut watch = lock.lock().unwrap(); + + *watch = true; + cvar.notify_one(); + } + + pub fn mv, S2: AsRef>( + &self, + context: &dc_context_t, + folder: S1, + uid: u32, + dest_folder: S2, + dest_uid: &mut u32, + ) -> usize { + let mut res = DC_RETRY_LATER; + let set = format!("{}", uid); + + if uid == 0 { + res = DC_FAILED; + } else if folder.as_ref() == dest_folder.as_ref() { + info!( + context, + 0, + "Skip moving message; message %s/%i is already in %s...", + CString::new(folder.as_ref().to_owned()).unwrap().as_ptr(), + uid as libc::c_int, + CString::new(dest_folder.as_ref().to_owned()) + .unwrap() + .as_ptr() + ); + + res = DC_ALREADY_DONE; + } else { + info!( + context, + 0, + "Moving message %s/%i to %s...", + CString::new(folder.as_ref().to_owned()).unwrap().as_ptr(), + uid as libc::c_int, + CString::new(dest_folder.as_ref().to_owned()) + .unwrap() + .as_ptr() + ); + + if self.select_folder(context, Some(folder.as_ref())) == 0 { + warn!( + context, + 0, + "Cannot select folder %s for moving message.", + CString::new(folder.as_ref().to_owned()).unwrap().as_ptr(), + ); } else { - current_block = 1538046216550696469; - } - match current_block { - 14415637129417834392 => {} - _ => { - if !res_setdest.is_null() { - let mut cur: *mut clistiter = (*(*res_setdest).set_list).first; - if !cur.is_null() { - let mut item: *mut mailimap_set_item = 0 as *mut mailimap_set_item; - item = (if !cur.is_null() { - (*cur).data - } else { - 0 as *mut libc::c_void - }) as *mut mailimap_set_item; - *dest_uid = (*item).set_first - } - } - res = DC_SUCCESS - } - } - } - } - if !set.is_null() { - mailimap_set_free(set); - set = 0 as *mut mailimap_set - } - if !res_setsrc.is_null() { - mailimap_set_free(res_setsrc); - res_setsrc = 0 as *mut mailimap_set - } - if !res_setdest.is_null() { - mailimap_set_free(res_setdest); - res_setdest = 0 as *mut mailimap_set - } - return (if res as libc::c_uint == DC_RETRY_LATER as libc::c_int as libc::c_uint { - (if 0 != (*imap).should_reconnect { - DC_RETRY_LATER as libc::c_int - } else { - DC_FAILED as libc::c_int - }) as libc::c_uint - } else { - res as libc::c_uint - }) as dc_imap_res; -} -unsafe fn add_flag( - mut imap: *mut dc_imap_t, - mut server_uid: uint32_t, - mut flag: *mut mailimap_flag, -) -> libc::c_int { - let mut flag_list: *mut mailimap_flag_list = 0 as *mut mailimap_flag_list; - let mut store_att_flags: *mut mailimap_store_att_flags = 0 as *mut mailimap_store_att_flags; - let mut set: *mut mailimap_set = mailimap_set_new_single(server_uid); - if !(imap.is_null() || (*imap).etpan.is_null()) { - flag_list = mailimap_flag_list_new_empty(); - mailimap_flag_list_add(flag_list, flag); - store_att_flags = mailimap_store_att_flags_new_add_flags(flag_list); - 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 { - 0i32 - } else { - 1i32 - } -} -pub unsafe fn dc_imap_set_seen( - mut imap: *mut dc_imap_t, - mut folder: *const libc::c_char, - mut uid: uint32_t, -) -> dc_imap_res { - let mut res: dc_imap_res = DC_RETRY_LATER; - if imap.is_null() || folder.is_null() || uid == 0i32 as libc::c_uint { - res = DC_FAILED - } else if !(*imap).etpan.is_null() { - dc_log_info( - (*imap).context, - 0i32, - b"Marking message %s/%i as seen...\x00" as *const u8 as *const libc::c_char, - folder, - uid as libc::c_int, - ); - if select_folder(imap, folder) == 0i32 { - dc_log_warning( - (*imap).context, - 0i32, - b"Cannot select folder %s for setting SEEN flag.\x00" as *const u8 - as *const libc::c_char, - folder, - ); - } else if add_flag(imap, uid, mailimap_flag_new_seen()) == 0i32 { - dc_log_warning( - (*imap).context, - 0i32, - b"Cannot mark message as seen.\x00" as *const u8 as *const libc::c_char, - ); - } else { - res = DC_SUCCESS - } - } - return (if res as libc::c_uint == DC_RETRY_LATER as libc::c_int as libc::c_uint { - (if 0 != (*imap).should_reconnect { - DC_RETRY_LATER as libc::c_int - } else { - DC_FAILED as libc::c_int - }) as libc::c_uint - } else { - res as libc::c_uint - }) as dc_imap_res; -} -pub unsafe fn dc_imap_set_mdnsent( - mut imap: *mut dc_imap_t, - mut folder: *const libc::c_char, - mut uid: uint32_t, -) -> dc_imap_res { - let mut can_create_flag: libc::c_int = 0; - let mut current_block: u64; - // returns 0=job should be retried later, 1=job done, 2=job done and flag just set - let mut res: dc_imap_res = DC_RETRY_LATER; - let mut set: *mut mailimap_set = mailimap_set_new_single(uid); - let mut fetch_result: *mut clist = 0 as *mut clist; - if imap.is_null() || folder.is_null() || uid == 0i32 as libc::c_uint || set.is_null() { - res = DC_FAILED - } else if !(*imap).etpan.is_null() { - dc_log_info( - (*imap).context, - 0i32, - b"Marking message %s/%i as $MDNSent...\x00" as *const u8 as *const libc::c_char, - folder, - uid as libc::c_int, - ); - if select_folder(imap, folder) == 0i32 { - dc_log_warning( - (*imap).context, - 0i32, - b"Cannot select folder %s for setting $MDNSent flag.\x00" as *const u8 - as *const libc::c_char, - folder, - ); - } else { - /* Check if the folder can handle the `$MDNSent` flag (see RFC 3503). If so, and not set: set the flags and return this information. - If the folder cannot handle the `$MDNSent` flag, we risk duplicated MDNs; it's up to the receiving MUA to handle this then (eg. Delta Chat has no problem with this). */ - can_create_flag = 0i32; - if !(*(*imap).etpan).imap_selection_info.is_null() - && !(*(*(*imap).etpan).imap_selection_info) - .sel_perm_flags - .is_null() - { - let mut iter: *mut clistiter = 0 as *mut clistiter; - iter = (*(*(*(*imap).etpan).imap_selection_info).sel_perm_flags).first; - while !iter.is_null() { - let mut fp: *mut mailimap_flag_perm = (if !iter.is_null() { - (*iter).data - } else { - 0 as *mut libc::c_void - }) - as *mut mailimap_flag_perm; - if !fp.is_null() { - if (*fp).fl_type == MAILIMAP_FLAG_PERM_ALL as libc::c_int { - can_create_flag = 1i32; - break; - } else if (*fp).fl_type == MAILIMAP_FLAG_PERM_FLAG as libc::c_int - && !(*fp).fl_flag.is_null() - { - let mut fl: *mut mailimap_flag = (*fp).fl_flag as *mut mailimap_flag; - if (*fl).fl_type == MAILIMAP_FLAG_KEYWORD as libc::c_int - && !(*fl).fl_data.fl_keyword.is_null() - && strcmp( - (*fl).fl_data.fl_keyword, - b"$MDNSent\x00" as *const u8 as *const libc::c_char, - ) == 0i32 - { - can_create_flag = 1i32; - break; - } - } - } - iter = if !iter.is_null() { - (*iter).next - } else { - 0 as *mut clistcell_s - } - } - } - if 0 != can_create_flag { - let mut r: libc::c_int = mailimap_uid_fetch( - (*imap).etpan, - set, - (*imap).fetch_type_flags, - &mut fetch_result, - ); - if 0 != dc_imap_is_error(imap, r) || fetch_result.is_null() { - fetch_result = 0 as *mut clist - } else { - let mut cur: *mut clistiter = (*fetch_result).first; - if !cur.is_null() { - if 0 != peek_flag_keyword( - (if !cur.is_null() { - (*cur).data - } else { - 0 as *mut libc::c_void - }) as *mut mailimap_msg_att, - b"$MDNSent\x00" as *const u8 as *const libc::c_char, - ) { - res = DC_ALREADY_DONE; - current_block = 14832935472441733737; - } else if add_flag( - imap, - uid, - mailimap_flag_new_flag_keyword(dc_strdup( - b"$MDNSent\x00" as *const u8 as *const libc::c_char, - )), - ) == 0i32 - { - current_block = 17044610252497760460; - } else { + let moved = if let Some(ref mut session) = *self.session.lock().unwrap() { + match session.uid_mv(&set, &dest_folder) { + Ok(_) => { res = DC_SUCCESS; - current_block = 14832935472441733737; + true } - match current_block { - 17044610252497760460 => {} - _ => { - dc_log_info( - (*imap).context, - 0i32, - if res as libc::c_uint - == DC_SUCCESS as libc::c_int as libc::c_uint - { - b"$MDNSent just set and MDN will be sent.\x00" as *const u8 - as *const libc::c_char - } else { - b"$MDNSent already set and MDN already sent.\x00" - as *const u8 - as *const libc::c_char - }, - ); - } + Err(err) => { + eprintln!("move error: {:?}", err); + info!( + context, + 0, + "Cannot move message, fallback to COPY/DELETE %s/%i to %s...", + CString::new(folder.as_ref().to_owned()).unwrap().as_ptr(), + uid as libc::c_int, + CString::new(dest_folder.as_ref().to_owned()) + .unwrap() + .as_ptr() + ); + + false } } + } else { + unreachable!(); + }; + + if !moved { + let copied = if let Some(ref mut session) = *self.session.lock().unwrap() { + match session.uid_copy(&set, &dest_folder) { + Ok(_) => true, + Err(err) => { + eprintln!("error copy: {:?}", err); + info!(context, 0, "Cannot copy message.",); + + false + } + } + } else { + unreachable!(); + }; + + if copied { + if self.add_flag(uid, "\\Deleted") == 0 { + warn!(context, 0, "Cannot mark message as \"Deleted\".",); + } + self.config.write().unwrap().selected_folder_needs_expunge = true; + res = DC_SUCCESS; + } } + } + } + + if res == DC_SUCCESS { + // TODO: is this correct? + *dest_uid = uid; + } + + if res == DC_RETRY_LATER { + if self.should_reconnect() { + DC_RETRY_LATER } else { - res = DC_SUCCESS; - dc_log_info( - (*imap).context, - 0i32, - b"Cannot store $MDNSent flags, risk sending duplicate MDN.\x00" as *const u8 - as *const libc::c_char, - ); + DC_FAILED } + } else { + res } } - if !set.is_null() { - mailimap_set_free(set); - set = 0 as *mut mailimap_set - } - if !fetch_result.is_null() { - mailimap_fetch_list_free(fetch_result); - fetch_result = 0 as *mut clist - } - return (if res as libc::c_uint == DC_RETRY_LATER as libc::c_int as libc::c_uint { - (if 0 != (*imap).should_reconnect { - DC_RETRY_LATER as libc::c_int - } else { - DC_FAILED as libc::c_int - }) as libc::c_uint - } else { - res as libc::c_uint - }) as dc_imap_res; -} -unsafe fn peek_flag_keyword( - mut msg_att: *mut mailimap_msg_att, - mut flag_keyword: *const libc::c_char, -) -> libc::c_int { - if msg_att.is_null() || (*msg_att).att_list.is_null() || flag_keyword.is_null() { - return 0i32; - } - let mut iter1: *mut clistiter = 0 as *mut clistiter; - let mut iter2: *mut clistiter = 0 as *mut clistiter; - iter1 = (*(*msg_att).att_list).first; - while !iter1.is_null() { - let mut item: *mut mailimap_msg_att_item = (if !iter1.is_null() { - (*iter1).data - } else { - 0 as *mut libc::c_void - }) as *mut mailimap_msg_att_item; - if !item.is_null() { - if (*item).att_type == MAILIMAP_MSG_ATT_ITEM_DYNAMIC as libc::c_int { - if !(*(*item).att_data.att_dyn).att_list.is_null() { - iter2 = (*(*(*item).att_data.att_dyn).att_list).first; - while !iter2.is_null() { - let mut flag_fetch: *mut mailimap_flag_fetch = (if !iter2.is_null() { - (*iter2).data - } else { - 0 as *mut libc::c_void - }) - as *mut mailimap_flag_fetch; - if !flag_fetch.is_null() - && (*flag_fetch).fl_type == MAILIMAP_FLAG_FETCH_OTHER as libc::c_int - { - let mut flag: *mut mailimap_flag = (*flag_fetch).fl_flag; - if !flag.is_null() { - if (*flag).fl_type == MAILIMAP_FLAG_KEYWORD as libc::c_int - && !(*flag).fl_data.fl_keyword.is_null() - && strcmp((*flag).fl_data.fl_keyword, flag_keyword) == 0i32 - { - return 1i32; - } - } - } - iter2 = if !iter2.is_null() { - (*iter2).next - } else { - 0 as *mut clistcell_s - } - } + + fn add_flag>(&self, server_uid: u32, flag: S) -> usize { + if let Some(ref mut session) = *self.session.lock().unwrap() { + let set = format!("{}", server_uid); + let query = format!("+ FLAGS ({})", flag.as_ref()); + match session.uid_store(set, query) { + Ok(_) => {} + Err(err) => { + eprintln!("imap store error {:?}", err); } } } - iter1 = if !iter1.is_null() { - (*iter1).next + + if self.should_reconnect() { + 0 } else { - 0 as *mut clistcell_s + 1 } } - return 0i32; -} -/* only returns 0 on connection problems; we should try later again in this case */ -pub unsafe fn dc_imap_delete_msg( - mut imap: *mut dc_imap_t, - mut rfc724_mid: *const libc::c_char, - mut folder: *const libc::c_char, - mut server_uid: uint32_t, -) -> libc::c_int { - let mut success: libc::c_int = 0i32; - let mut r: libc::c_int = 0i32; - let mut fetch_result: *mut clist = 0 as *mut clist; - let mut is_rfc724_mid: *mut libc::c_char = 0 as *mut libc::c_char; - let mut new_folder: *mut libc::c_char = 0 as *mut libc::c_char; - if imap.is_null() - || rfc724_mid.is_null() - || folder.is_null() - || *folder.offset(0isize) as libc::c_int == 0i32 - || server_uid == 0i32 as libc::c_uint - { - success = 1i32 - } else { - dc_log_info( - (*imap).context, - 0i32, - b"Marking message \"%s\", %s/%i for deletion...\x00" as *const u8 - as *const libc::c_char, - rfc724_mid, - folder, - server_uid as libc::c_int, - ); - if select_folder(imap, folder) == 0i32 { - dc_log_warning( - (*imap).context, - 0i32, - b"Cannot select folder %s for deleting message.\x00" as *const u8 - as *const libc::c_char, - folder, + + pub fn set_seen>(&self, context: &dc_context_t, folder: S, uid: u32) -> usize { + let mut res = DC_RETRY_LATER; + + if uid == 0 { + res = DC_FAILED + } else if self.is_connected() { + let folder_c = CString::new(folder.as_ref().to_owned()).unwrap(); + + info!( + context, + 0, + "Marking message %s/%i as seen...", + folder_c.as_ptr(), + uid as libc::c_int ); - } else { - let mut cur: *mut clistiter = 0 as *mut clistiter; - let mut is_quoted_rfc724_mid: *const libc::c_char = 0 as *const libc::c_char; - let mut set: *mut mailimap_set = mailimap_set_new_single(server_uid); - r = mailimap_uid_fetch( - (*imap).etpan, - set, - (*imap).fetch_type_prefetch, - &mut fetch_result, - ); - if !set.is_null() { - mailimap_set_free(set); - set = 0 as *mut mailimap_set - } - if 0 != dc_imap_is_error(imap, r) || fetch_result.is_null() { - fetch_result = 0 as *mut clist; - dc_log_warning( - (*imap).context, - 0i32, - b"Cannot delete on IMAP, %s/%i not found.\x00" as *const u8 - as *const libc::c_char, - folder, - server_uid as libc::c_int, + + if self.select_folder(context, Some(folder)) == 0 { + warn!( + context, + 0, + "Cannot select folder %s for setting SEEN flag.", + folder_c.as_ptr(), ); - server_uid = 0i32 as uint32_t + } else if self.add_flag(uid, "\\Seen") == 0 { + warn!(context, 0, "Cannot mark message as seen.",); + } else { + res = DC_SUCCESS } - cur = (*fetch_result).first; - if cur.is_null() - || { - is_quoted_rfc724_mid = peek_rfc724_mid( - (if !cur.is_null() { - (*cur).data + } + + if res == DC_RETRY_LATER { + if self.should_reconnect() { + DC_RETRY_LATER + } else { + DC_FAILED + } + } else { + res + } + } + + pub fn set_mdnsent>(&self, context: &dc_context_t, folder: S, uid: u32) -> usize { + // returns 0=job should be retried later, 1=job done, 2=job done and flag just set + let mut res = DC_RETRY_LATER; + let mut set = format!("{}", uid); + + if uid == 0 { + res = DC_FAILED; + } else if self.is_connected() { + let folder_c = CString::new(folder.as_ref().to_owned()).unwrap(); + info!( + context, + 0, + "Marking message %s/%i as $MDNSent...", + folder_c.as_ptr(), + uid as libc::c_int + ); + + if self.select_folder(context, Some(folder)) == 0 { + warn!( + context, + 0, + "Cannot select folder %s for setting $MDNSent flag.", + folder_c.as_ptr(), + ); + } else { + // Check if the folder can handle the `$MDNSent` flag (see RFC 3503). If so, and not + // set: set the flags and return this information. + // If the folder cannot handle the `$MDNSent` flag, we risk duplicated MDNs; it's up + // to the receiving MUA to handle this then (eg. Delta Chat has no problem with this). + + let can_create_flag = self + .config + .read() + .unwrap() + .selected_mailbox + .as_ref() + .map(|mbox| { + // empty means, everything can be stored + mbox.permanent_flags.is_empty() + || mbox + .permanent_flags + .iter() + .find(|flag| match flag { + imap::types::Flag::Custom(s) => s == "$MDNSent", + _ => false, + }) + .is_some() + }) + .expect("just selected folder"); + + if can_create_flag { + let fetched_msgs = if let Some(ref mut session) = *self.session.lock().unwrap() + { + match session.uid_fetch(set, FETCH_FLAGS) { + Ok(res) => Some(res), + Err(err) => { + eprintln!("fetch error: {:?}", err); + None + } + } + } else { + unreachable!(); + }; + + if let Some(msgs) = fetched_msgs { + let flag_set = msgs + .first() + .map(|msg| { + msg.flags() + .iter() + .find(|flag| match flag { + imap::types::Flag::Custom(s) => s == "$MDNSent", + _ => false, + }) + .is_some() + }) + .unwrap_or_else(|| false); + + res = if flag_set { + DC_ALREADY_DONE + } else if self.add_flag(uid, "$MDNSent") != 0 { + DC_SUCCESS } else { - 0 as *mut libc::c_void - }) as *mut mailimap_msg_att, + res + }; + + let msg = if res == DC_SUCCESS { + "$MDNSent just set and MDN will be sent." + } else { + "$MDNSent already set and MDN already sent." + }; + + info!(context, 0, msg); + } + } else { + res = DC_SUCCESS; + info!( + context, + 0, "Cannot store $MDNSent flags, risk sending duplicate MDN.", ); - is_quoted_rfc724_mid.is_null() } - || { - is_rfc724_mid = unquote_rfc724_mid(is_quoted_rfc724_mid); - is_rfc724_mid.is_null() - } - || strcmp(is_rfc724_mid, rfc724_mid) != 0i32 - { - dc_log_warning( - (*imap).context, - 0i32, - b"Cannot delete on IMAP, %s/%i does not match %s.\x00" as *const u8 - as *const libc::c_char, - folder, - server_uid as libc::c_int, - rfc724_mid, - ); - server_uid = 0i32 as uint32_t } - /* mark the message for deletion */ - if add_flag(imap, server_uid, mailimap_flag_new_deleted()) == 0i32 { - dc_log_warning( - (*imap).context, - 0i32, - b"Cannot mark message as \"Deleted\".\x00" as *const u8 as *const libc::c_char, + } + + if res == DC_RETRY_LATER { + if self.should_reconnect() { + DC_RETRY_LATER + } else { + DC_FAILED + } + } else { + res + } + } + + // only returns 0 on connection problems; we should try later again in this case * + pub fn delete_msg, S2: AsRef>( + &self, + context: &dc_context_t, + message_id: S1, + folder: S2, + server_uid: &mut u32, + ) -> usize { + let mut success = false; + if *server_uid == 0 { + success = true + } else { + info!( + context, + 0, + "Marking message \"%s\", %s/%i for deletion...", + &message_id, + CString::new(folder.as_ref().to_owned()).unwrap().as_ptr(), + *server_uid as libc::c_int + ); + + if self.select_folder(context, Some(&folder)) == 0 { + warn!( + context, + 0, + "Cannot select folder %s for deleting message.", + CString::new(folder.as_ref().to_owned()).unwrap().as_ptr(), ); } else { - (*imap).selected_folder_needs_expunge = 1i32; - success = 1i32 + let set = format!("{}", server_uid); + if let Some(ref mut session) = *self.session.lock().unwrap() { + match session.uid_fetch(set, PREFETCH_FLAGS) { + Ok(msgs) => { + if msgs.is_empty() + || msgs + .first() + .unwrap() + .envelope() + .expect("missing envelope") + .message_id + .expect("missing message id") + != message_id.as_ref() + { + warn!( + context, + 0, + "Cannot delete on IMAP, %s/%i does not match %s.", + CString::new(folder.as_ref().to_owned()).unwrap().as_ptr(), + *server_uid as libc::c_int, + message_id, + ); + *server_uid = 0; + } + } + Err(err) => { + eprintln!("fetch error: {:?}", err); + + warn!( + context, + 0, + "Cannot delete on IMAP, %s/%i not found.", + CString::new(folder.as_ref().to_owned()).unwrap().as_ptr(), + *server_uid as libc::c_int, + ); + *server_uid = 0; + } + } + } + + // mark the message for deletion + if self.add_flag(*server_uid, "\\Deleted") == 0 { + warn!(context, 0, "Cannot mark message as \"Deleted\"."); + } else { + self.config.write().unwrap().selected_folder_needs_expunge = true; + success = true + } + } + } + + if success { + 1 + } else { + self.is_connected() as usize + } + } + + pub fn configure_folders(&self, context: &dc_context_t, flags: libc::c_int) { + if !self.is_connected() { + return; + } + + info!(context, 0, "Configuring IMAP-folders."); + + let folders = self.list_folders(context).unwrap(); + let delimiter = self.config.read().unwrap().imap_delimiter; + let fallback_folder = format!("INBOX{}DeltaChat", delimiter); + + let mut mvbox_folder = folders + .iter() + .find(|folder| folder.name() == "DeltaChat" || folder.name() == fallback_folder) + .map(|n| n.name().to_string()); + + let mut sentbox_folder = folders + .iter() + .find(|folder| match get_folder_meaning(folder) { + FolderMeaning::SentObjects => true, + _ => false, + }); + + if mvbox_folder.is_none() && 0 != (flags as usize & DC_CREATE_MVBOX) { + info!( + context, + 0, + "Creating MVBOX-folder \"%s\"...", + b"DeltaChat\x00" as *const u8 as *const libc::c_char + ); + + if let Some(ref mut session) = *self.session.lock().unwrap() { + match session.create("DeltaChat") { + Ok(_) => { + mvbox_folder = Some("DeltaChat".into()); + + info!(context, 0, "MVBOX-folder created.",); + } + Err(err) => { + eprintln!("create error: {:?}", err); + warn!( + context, + 0, "Cannot create MVBOX-folder, using trying INBOX subfolder." + ); + + match session.create(&fallback_folder) { + Ok(_) => { + mvbox_folder = Some(fallback_folder); + info!(context, 0, "MVBOX-folder created as INBOX subfolder.",); + } + Err(err) => { + eprintln!("create error: {:?}", err); + warn!(context, 0, "Cannot create MVBOX-folder.",); + } + } + } + } + // SUBSCRIBE is needed to make the folder visible to the LSUB command + // that may be used by other MUAs to list folders. + // for the LIST command, the folder is always visible. + if let Some(ref mvbox) = mvbox_folder { + // TODO: better error handling + session.subscribe(mvbox).expect("failed to subscribe"); + } + } + } + + unsafe { + dc_sqlite3_set_config_int( + context, + &context.sql.read().unwrap(), + b"folders_configured\x00" as *const u8 as *const libc::c_char, + 3, + ); + if let Some(ref mvbox_folder) = mvbox_folder { + dc_sqlite3_set_config( + context, + &context.sql.read().unwrap(), + b"configured_mvbox_folder\x00" as *const u8 as *const libc::c_char, + CString::new(mvbox_folder.clone()).unwrap().as_ptr(), + ); + } + if let Some(ref sentbox_folder) = sentbox_folder { + dc_sqlite3_set_config( + context, + &context.sql.read().unwrap(), + b"configured_sentbox_folder\x00" as *const u8 as *const libc::c_char, + CString::new(sentbox_folder.name()).unwrap().as_ptr(), + ); } } } - if !fetch_result.is_null() { - mailimap_fetch_list_free(fetch_result); - fetch_result = 0 as *mut clist + + 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() { + warn!(context, 0, "Folder list is empty.",); + } + Some(list) + } + Err(err) => { + eprintln!("list error: {:?}", err); + warn!(context, 0, "Cannot get folder list.",); + + None + } + } + } else { + None + } + } +} + +fn to_string(str: *const libc::c_char) -> String { + unsafe { CStr::from_ptr(str).to_str().unwrap().to_string() } +} + +fn to_str<'a>(str: *const libc::c_char) -> &'a str { + unsafe { CStr::from_ptr(str).to_str().unwrap() } +} + +/// 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 + } +} + +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() { + 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 + } + } + _ => {} + } + } + + match res { + FolderMeaning::Unknown => get_folder_meaning_by_name(folder_name), + _ => res, } - free(is_rfc724_mid as *mut libc::c_void); - free(new_folder as *mut libc::c_void); - return if 0 != success { - 1i32 - } else { - dc_imap_is_connected(imap) - }; } diff --git a/src/dc_imex.rs b/src/dc_imex.rs index f72850c8e..3f2a0a001 100644 --- a/src/dc_imex.rs +++ b/src/dc_imex.rs @@ -1,4 +1,6 @@ -use libc; +use mmime::mailmime_content::*; +use mmime::mmapstring::*; +use mmime::other::*; use rand::{thread_rng, Rng}; use crate::constants::Event; @@ -26,7 +28,7 @@ use crate::x::*; // param1 is a directory where the backup is written to // param1 is the file with the backup to import pub unsafe fn dc_imex( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut what: libc::c_int, mut param1: *const libc::c_char, mut param2: *const libc::c_char, @@ -39,21 +41,19 @@ pub unsafe fn dc_imex( dc_job_add(context, 910i32, 0i32, (*param).packed, 0i32); dc_param_unref(param); } + pub unsafe fn dc_imex_has_backup( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut dir_name: *const libc::c_char, ) -> *mut libc::c_char { let mut ret: *mut libc::c_char = 0 as *mut libc::c_char; let mut ret_backup_time: time_t = 0i32 as time_t; - let mut dir_handle: *mut DIR = 0 as *mut DIR; - let mut dir_entry: *mut dirent = 0 as *mut dirent; + let mut dir_handle: *mut DIR; + let mut dir_entry: *mut dirent; let mut prefix_len = strlen(b"delta-chat\x00" as *const u8 as *const libc::c_char); let mut suffix_len = strlen(b"bak\x00" as *const u8 as *const libc::c_char); let mut curr_pathNfilename: *mut libc::c_char = 0 as *mut libc::c_char; - let mut test_sql: *mut dc_sqlite3_t = 0 as *mut dc_sqlite3_t; - if context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint { - return 0 as *mut libc::c_char; - } + let mut test_sql: Option = None; dir_handle = opendir(dir_name); if dir_handle.is_null() { dc_log_info( @@ -89,12 +89,15 @@ pub unsafe fn dc_imex_has_backup( dir_name, name, ); - dc_sqlite3_unref(test_sql); - test_sql = dc_sqlite3_new(context); - if !test_sql.is_null() && 0 != dc_sqlite3_open(test_sql, curr_pathNfilename, 0x1i32) - { + if test_sql.is_some() { + let mut test_sql = test_sql.take().unwrap(); + dc_sqlite3_unref(context, &mut test_sql); + } + let mut sql = dc_sqlite3_new(); + if 0 != dc_sqlite3_open(context, &mut sql, curr_pathNfilename, 0x1i32) { let mut curr_backup_time: time_t = dc_sqlite3_get_config_int( - test_sql, + context, + &mut sql, b"backup_time\x00" as *const u8 as *const libc::c_char, 0i32, ) as time_t; @@ -106,6 +109,7 @@ pub unsafe fn dc_imex_has_backup( curr_pathNfilename = 0 as *mut libc::c_char } } + test_sql = Some(sql); } } } @@ -113,11 +117,14 @@ pub unsafe fn dc_imex_has_backup( closedir(dir_handle); } free(curr_pathNfilename as *mut libc::c_void); - dc_sqlite3_unref(test_sql); - return ret; + if let Some(ref mut sql) = test_sql { + dc_sqlite3_unref(context, sql); + } + ret } + pub unsafe fn dc_check_password( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut test_pw: *const libc::c_char, ) -> libc::c_int { /* Check if the given password matches the configured mail_pw. @@ -125,46 +132,61 @@ pub unsafe fn dc_check_password( When we start supporting OAuth some day, we should think this over, maybe force the user to re-authenticate himself with the Android password. */ let mut loginparam: *mut dc_loginparam_t = dc_loginparam_new(); let mut success: libc::c_int = 0i32; - if !(context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint) { - dc_loginparam_read( - loginparam, - (*context).sql, - b"configured_\x00" as *const u8 as *const libc::c_char, - ); - if ((*loginparam).mail_pw.is_null() - || *(*loginparam).mail_pw.offset(0isize) as libc::c_int == 0i32) - && (test_pw.is_null() || *test_pw.offset(0isize) as libc::c_int == 0i32) - { - success = 1i32 - } else if (*loginparam).mail_pw.is_null() || test_pw.is_null() { - success = 0i32 - } else if strcmp((*loginparam).mail_pw, test_pw) == 0i32 { - success = 1i32 - } + + dc_loginparam_read( + context, + loginparam, + &context.sql.clone().read().unwrap(), + b"configured_\x00" as *const u8 as *const libc::c_char, + ); + if ((*loginparam).mail_pw.is_null() + || *(*loginparam).mail_pw.offset(0isize) as libc::c_int == 0i32) + && (test_pw.is_null() || *test_pw.offset(0isize) as libc::c_int == 0i32) + { + success = 1i32 + } else if (*loginparam).mail_pw.is_null() || test_pw.is_null() { + success = 0i32 + } else if strcmp((*loginparam).mail_pw, test_pw) == 0i32 { + success = 1i32 } + dc_loginparam_unref(loginparam); - return success; + + success } -pub unsafe fn dc_initiate_key_transfer(mut context: *mut dc_context_t) -> *mut libc::c_char { + +pub unsafe fn dc_initiate_key_transfer(mut context: &dc_context_t) -> *mut libc::c_char { let mut current_block: u64; let mut success: libc::c_int = 0i32; - let mut setup_code: *mut libc::c_char = 0 as *mut libc::c_char; + let mut setup_code: *mut libc::c_char; let mut setup_file_content: *mut libc::c_char = 0 as *mut libc::c_char; let mut setup_file_name: *mut libc::c_char = 0 as *mut libc::c_char; - let mut chat_id: uint32_t = 0i32 as uint32_t; + let mut chat_id: uint32_t; let mut msg: *mut dc_msg_t = 0 as *mut dc_msg_t; - let mut msg_id: uint32_t = 0i32 as uint32_t; + let mut msg_id: uint32_t; if 0 == dc_alloc_ongoing(context) { return 0 as *mut libc::c_char; } setup_code = dc_create_setup_code(context); if !setup_code.is_null() { /* this may require a keypair to be created. this may take a second ... */ - if !(0 != (*context).shall_stop_ongoing) { + if !context + .running_state + .clone() + .read() + .unwrap() + .shall_stop_ongoing + { setup_file_content = dc_render_setup_file(context, setup_code); if !setup_file_content.is_null() { /* encrypting may also take a while ... */ - if !(0 != (*context).shall_stop_ongoing) { + if !context + .running_state + .clone() + .read() + .unwrap() + .shall_stop_ongoing + { setup_file_name = dc_get_fine_pathNfilename( context, b"$BLOBDIR\x00" as *const u8 as *const libc::c_char, @@ -191,7 +213,13 @@ pub unsafe fn dc_initiate_key_transfer(mut context: *mut dc_context_t) -> *mut l ); dc_param_set_int((*msg).param, 'S' as i32, 6i32); dc_param_set_int((*msg).param, 'u' as i32, 2i32); - if !(0 != (*context).shall_stop_ongoing) { + if !context + .running_state + .clone() + .read() + .unwrap() + .shall_stop_ongoing + { msg_id = dc_send_msg(context, chat_id, msg); if !(msg_id == 0i32 as libc::c_uint) { dc_msg_unref(msg); @@ -203,7 +231,13 @@ pub unsafe fn dc_initiate_key_transfer(mut context: *mut dc_context_t) -> *mut l as *const libc::c_char, ); loop { - if 0 != (*context).shall_stop_ongoing { + if context + .running_state + .clone() + .read() + .unwrap() + .shall_stop_ongoing + { current_block = 6116957410927263949; break; } @@ -244,10 +278,12 @@ pub unsafe fn dc_initiate_key_transfer(mut context: *mut dc_context_t) -> *mut l free(setup_file_content as *mut libc::c_void); dc_msg_unref(msg); dc_free_ongoing(context); - return setup_code; + + setup_code } + pub unsafe extern "C" fn dc_render_setup_file( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut passphrase: *const libc::c_char, ) -> *mut libc::c_char { let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; @@ -256,33 +292,35 @@ pub unsafe extern "C" fn dc_render_setup_file( let mut passphrase_begin: [libc::c_char; 8] = [0; 8]; let mut encr_string: *mut libc::c_char = 0 as *mut libc::c_char; let mut ret_setupfilecontent: *mut libc::c_char = 0 as *mut libc::c_char; - if !(context.is_null() - || (*context).magic != 0x11a11807i32 as libc::c_uint - || passphrase.is_null() - || strlen(passphrase) < 2 - || curr_private_key.is_null()) - { + if !(passphrase.is_null() || strlen(passphrase) < 2 || curr_private_key.is_null()) { strncpy(passphrase_begin.as_mut_ptr(), passphrase, 2); passphrase_begin[2usize] = 0i32 as libc::c_char; /* create the payload */ if !(0 == dc_ensure_secret_key_exists(context)) { self_addr = dc_sqlite3_get_config( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"configured_addr\x00" as *const u8 as *const libc::c_char, 0 as *const libc::c_char, ); - dc_key_load_self_private(curr_private_key, self_addr, (*context).sql); + dc_key_load_self_private( + context, + curr_private_key, + self_addr, + &context.sql.clone().read().unwrap(), + ); let mut e2ee_enabled: libc::c_int = dc_sqlite3_get_config_int( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"e2ee_enabled\x00" as *const u8 as *const libc::c_char, 1i32, ); let mut payload_key_asc: *mut libc::c_char = dc_key_render_asc( curr_private_key, if 0 != e2ee_enabled { - b"Autocrypt-Prefer-Encrypt: mutual\r\n\x00" as *const u8 as *const libc::c_char + Some(("Autocrypt-Prefer-Encrypt", "mutual")) } else { - 0 as *const libc::c_char + None }, ); if !payload_key_asc.is_null() { @@ -333,11 +371,13 @@ pub unsafe extern "C" fn dc_render_setup_file( dc_key_unref(curr_private_key); free(encr_string as *mut libc::c_void); free(self_addr as *mut libc::c_void); - return ret_setupfilecontent; + + ret_setupfilecontent } -pub unsafe fn dc_create_setup_code(_context: *mut dc_context_t) -> *mut libc::c_char { - let mut random_val: uint16_t = 0i32 as uint16_t; - let mut i: libc::c_int = 0i32; + +pub unsafe fn dc_create_setup_code(_context: &dc_context_t) -> *mut libc::c_char { + let mut random_val: uint16_t; + let mut i: libc::c_int; let mut ret: dc_strbuilder_t = dc_strbuilder_t { buf: 0 as *mut libc::c_char, allocated: 0, @@ -367,10 +407,13 @@ pub unsafe fn dc_create_setup_code(_context: *mut dc_context_t) -> *mut libc::c_ ); i += 1 } - return ret.buf; + + ret.buf } + +// TODO should return bool /rtn pub unsafe fn dc_continue_key_transfer( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut msg_id: uint32_t, mut setup_code: *const libc::c_char, ) -> libc::c_int { @@ -381,11 +424,7 @@ pub unsafe fn dc_continue_key_transfer( let mut filebytes: size_t = 0i32 as size_t; let mut armored_key: *mut libc::c_char = 0 as *mut libc::c_char; let mut norm_sc: *mut libc::c_char = 0 as *mut libc::c_char; - if !(context.is_null() - || (*context).magic != 0x11a11807i32 as libc::c_uint - || msg_id <= 9i32 as libc::c_uint - || setup_code.is_null()) - { + if !(msg_id <= 9i32 as libc::c_uint || setup_code.is_null()) { msg = dc_get_msg(context, msg_id); if msg.is_null() || 0 == dc_msg_is_setupmessage(msg) @@ -446,15 +485,18 @@ pub unsafe fn dc_continue_key_transfer( free(filename as *mut libc::c_void); dc_msg_unref(msg); free(norm_sc as *mut libc::c_void); - return success; + + success } + +// TODO should return bool /rtn unsafe fn set_self_key( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut armored: *const libc::c_char, mut set_default: libc::c_int, ) -> libc::c_int { let mut success: libc::c_int = 0i32; - let mut buf: *mut libc::c_char = 0 as *mut libc::c_char; + let mut buf: *mut libc::c_char; // pointer inside buf, MUST NOT be free()'d let mut buf_headerline: *const libc::c_char = 0 as *const libc::c_char; // - " - @@ -494,7 +536,8 @@ unsafe fn set_self_key( ); } else { stmt = dc_sqlite3_prepare( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"DELETE FROM keypairs WHERE public_key=? OR private_key=?;\x00" as *const u8 as *const libc::c_char, ); @@ -511,21 +554,24 @@ unsafe fn set_self_key( stmt = 0 as *mut sqlite3_stmt; if 0 != set_default { dc_sqlite3_execute( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"UPDATE keypairs SET is_default=0;\x00" as *const u8 as *const libc::c_char, ); } self_addr = dc_sqlite3_get_config( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"configured_addr\x00" as *const u8 as *const libc::c_char, 0 as *const libc::c_char, ); if 0 == dc_key_save_self_keypair( + context, public_key, private_key, self_addr, set_default, - (*context).sql, + &context.sql.clone().read().unwrap(), ) { dc_log_error( context, @@ -540,7 +586,8 @@ unsafe fn set_self_key( ) == 0i32 { dc_sqlite3_set_config_int( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"e2ee_enabled\x00" as *const u8 as *const libc::c_char, 0i32, ); @@ -550,7 +597,8 @@ unsafe fn set_self_key( ) == 0i32 { dc_sqlite3_set_config_int( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"e2ee_enabled\x00" as *const u8 as *const libc::c_char, 1i32, ); @@ -564,14 +612,16 @@ unsafe fn set_self_key( free(self_addr as *mut libc::c_void); dc_key_unref(private_key); dc_key_unref(public_key); - return success; + + success } + pub unsafe fn dc_decrypt_setup_file( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut passphrase: *const libc::c_char, mut filecontent: *const libc::c_char, ) -> *mut libc::c_char { - let mut fc_buf: *mut libc::c_char = 0 as *mut libc::c_char; + let mut fc_buf: *mut libc::c_char; let mut fc_headerline: *const libc::c_char = 0 as *const libc::c_char; let mut fc_base64: *const libc::c_char = 0 as *const libc::c_char; let mut binary: *mut libc::c_char = 0 as *mut libc::c_char; @@ -628,10 +678,12 @@ pub unsafe fn dc_decrypt_setup_file( if !binary.is_null() { mmap_string_unref(binary); } - return payload; + + payload } + pub unsafe fn dc_normalize_setup_code( - _context: *mut dc_context_t, + _context: &dc_context_t, in_0: *const libc::c_char, ) -> *mut libc::c_char { if in_0.is_null() { @@ -644,7 +696,7 @@ pub unsafe fn dc_normalize_setup_code( eos: 0 as *mut libc::c_char, }; dc_strbuilder_init(&mut out, 0i32); - let mut outlen: libc::c_int = 0i32; + let mut outlen: libc::c_int; let mut p1: *const libc::c_char = in_0; while 0 != *p1 { if *p1 as libc::c_int >= '0' as i32 && *p1 as libc::c_int <= '9' as i32 { @@ -668,278 +720,278 @@ pub unsafe fn dc_normalize_setup_code( } p1 = p1.offset(1isize) } - return out.buf; + + out.buf } -pub unsafe fn dc_job_do_DC_JOB_IMEX_IMAP(mut context: *mut dc_context_t, mut job: *mut dc_job_t) { + +pub unsafe fn dc_job_do_DC_JOB_IMEX_IMAP(mut context: &dc_context_t, mut job: *mut dc_job_t) { let mut current_block: u64; let mut success: libc::c_int = 0i32; let mut ongoing_allocated_here: libc::c_int = 0i32; - let mut what: libc::c_int = 0i32; + let mut what: libc::c_int; let mut param1: *mut libc::c_char = 0 as *mut libc::c_char; let mut param2: *mut libc::c_char = 0 as *mut libc::c_char; - if !(context.is_null() - || (*context).magic != 0x11a11807i32 as libc::c_uint - || (*context).sql.is_null()) - { - if !(0 == dc_alloc_ongoing(context)) { - ongoing_allocated_here = 1i32; - what = dc_param_get_int((*job).param, 'S' as i32, 0i32); - param1 = dc_param_get((*job).param, 'E' as i32, 0 as *const libc::c_char); - param2 = dc_param_get((*job).param, 'F' as i32, 0 as *const libc::c_char); - if param1.is_null() { + if !(0 == dc_alloc_ongoing(context)) { + ongoing_allocated_here = 1i32; + what = dc_param_get_int((*job).param, 'S' as i32, 0i32); + param1 = dc_param_get((*job).param, 'E' as i32, 0 as *const libc::c_char); + param2 = dc_param_get((*job).param, 'F' as i32, 0 as *const libc::c_char); + if param1.is_null() { + dc_log_error( + context, + 0i32, + b"No Import/export dir/file given.\x00" as *const u8 as *const libc::c_char, + ); + } else { + dc_log_info( + context, + 0i32, + b"Import/export process started.\x00" as *const u8 as *const libc::c_char, + ); + (context.cb)( + context, + Event::IMEX_PROGRESS, + 10i32 as uintptr_t, + 0i32 as uintptr_t, + ); + if 0 == dc_sqlite3_is_open(&context.sql.clone().read().unwrap()) { dc_log_error( context, 0i32, - b"No Import/export dir/file given.\x00" as *const u8 as *const libc::c_char, + b"Import/export: Database not opened.\x00" as *const u8 as *const libc::c_char, ); } else { - dc_log_info( - context, - 0i32, - b"Import/export process started.\x00" as *const u8 as *const libc::c_char, - ); - ((*context).cb)( - context, - Event::IMEX_PROGRESS, - 10i32 as uintptr_t, - 0i32 as uintptr_t, - ); - if 0 == dc_sqlite3_is_open((*context).sql) { - dc_log_error( - context, - 0i32, - b"Import/export: Database not opened.\x00" as *const u8 - as *const libc::c_char, - ); - } else { - if what == 1i32 || what == 11i32 { - /* before we export anything, make sure the private key exists */ - if 0 == dc_ensure_secret_key_exists(context) { - dc_log_error(context, 0i32, + if what == 1i32 || what == 11i32 { + /* before we export anything, make sure the private key exists */ + if 0 == dc_ensure_secret_key_exists(context) { + dc_log_error(context, 0i32, b"Import/export: Cannot create private key or private key not available.\x00" as *const u8 as *const libc::c_char); - current_block = 3568988166330621280; - } else { - dc_create_folder(context, param1); - current_block = 4495394744059808450; - } + current_block = 3568988166330621280; } else { + dc_create_folder(context, param1); current_block = 4495394744059808450; } - match current_block { - 3568988166330621280 => {} - _ => match what { - 1 => { - current_block = 10991094515395304355; - match current_block { - 2973387206439775448 => { - if 0 == import_backup(context, param1) { - current_block = 3568988166330621280; - } else { - current_block = 1118134448028020070; - } - } - 11250025114629486028 => { - if 0 == import_self_keys(context, param1) { - current_block = 3568988166330621280; - } else { - current_block = 1118134448028020070; - } - } - 12669919903773909120 => { - if 0 == export_backup(context, param1) { - current_block = 3568988166330621280; - } else { - current_block = 1118134448028020070; - } - } - _ => { - if 0 == export_self_keys(context, param1) { - current_block = 3568988166330621280; - } else { - current_block = 1118134448028020070; - } + } else { + current_block = 4495394744059808450; + } + match current_block { + 3568988166330621280 => {} + _ => match what { + 1 => { + current_block = 10991094515395304355; + match current_block { + 2973387206439775448 => { + if 0 == import_backup(context, param1) { + current_block = 3568988166330621280; + } else { + current_block = 1118134448028020070; } } - match current_block { - 3568988166330621280 => {} - _ => { - dc_log_info( - context, - 0i32, - b"Import/export completed.\x00" as *const u8 - as *const libc::c_char, - ); - success = 1i32 + 11250025114629486028 => { + if 0 == import_self_keys(context, param1) { + current_block = 3568988166330621280; + } else { + current_block = 1118134448028020070; + } + } + 12669919903773909120 => { + if 0 == export_backup(context, param1) { + current_block = 3568988166330621280; + } else { + current_block = 1118134448028020070; + } + } + _ => { + if 0 == export_self_keys(context, param1) { + current_block = 3568988166330621280; + } else { + current_block = 1118134448028020070; } } } - 2 => { - current_block = 11250025114629486028; - match current_block { - 2973387206439775448 => { - if 0 == import_backup(context, param1) { - current_block = 3568988166330621280; - } else { - current_block = 1118134448028020070; - } - } - 11250025114629486028 => { - if 0 == import_self_keys(context, param1) { - current_block = 3568988166330621280; - } else { - current_block = 1118134448028020070; - } - } - 12669919903773909120 => { - if 0 == export_backup(context, param1) { - current_block = 3568988166330621280; - } else { - current_block = 1118134448028020070; - } - } - _ => { - if 0 == export_self_keys(context, param1) { - current_block = 3568988166330621280; - } else { - current_block = 1118134448028020070; - } + match current_block { + 3568988166330621280 => {} + _ => { + dc_log_info( + context, + 0i32, + b"Import/export completed.\x00" as *const u8 + as *const libc::c_char, + ); + success = 1i32 + } + } + } + 2 => { + current_block = 11250025114629486028; + match current_block { + 2973387206439775448 => { + if 0 == import_backup(context, param1) { + current_block = 3568988166330621280; + } else { + current_block = 1118134448028020070; } } - match current_block { - 3568988166330621280 => {} - _ => { - dc_log_info( - context, - 0i32, - b"Import/export completed.\x00" as *const u8 - as *const libc::c_char, - ); - success = 1i32 + 11250025114629486028 => { + if 0 == import_self_keys(context, param1) { + current_block = 3568988166330621280; + } else { + current_block = 1118134448028020070; + } + } + 12669919903773909120 => { + if 0 == export_backup(context, param1) { + current_block = 3568988166330621280; + } else { + current_block = 1118134448028020070; + } + } + _ => { + if 0 == export_self_keys(context, param1) { + current_block = 3568988166330621280; + } else { + current_block = 1118134448028020070; } } } - 11 => { - current_block = 12669919903773909120; - match current_block { - 2973387206439775448 => { - if 0 == import_backup(context, param1) { - current_block = 3568988166330621280; - } else { - current_block = 1118134448028020070; - } - } - 11250025114629486028 => { - if 0 == import_self_keys(context, param1) { - current_block = 3568988166330621280; - } else { - current_block = 1118134448028020070; - } - } - 12669919903773909120 => { - if 0 == export_backup(context, param1) { - current_block = 3568988166330621280; - } else { - current_block = 1118134448028020070; - } - } - _ => { - if 0 == export_self_keys(context, param1) { - current_block = 3568988166330621280; - } else { - current_block = 1118134448028020070; - } + match current_block { + 3568988166330621280 => {} + _ => { + dc_log_info( + context, + 0i32, + b"Import/export completed.\x00" as *const u8 + as *const libc::c_char, + ); + success = 1i32 + } + } + } + 11 => { + current_block = 12669919903773909120; + match current_block { + 2973387206439775448 => { + if 0 == import_backup(context, param1) { + current_block = 3568988166330621280; + } else { + current_block = 1118134448028020070; } } - match current_block { - 3568988166330621280 => {} - _ => { - dc_log_info( - context, - 0i32, - b"Import/export completed.\x00" as *const u8 - as *const libc::c_char, - ); - success = 1i32 + 11250025114629486028 => { + if 0 == import_self_keys(context, param1) { + current_block = 3568988166330621280; + } else { + current_block = 1118134448028020070; + } + } + 12669919903773909120 => { + if 0 == export_backup(context, param1) { + current_block = 3568988166330621280; + } else { + current_block = 1118134448028020070; + } + } + _ => { + if 0 == export_self_keys(context, param1) { + current_block = 3568988166330621280; + } else { + current_block = 1118134448028020070; } } } - 12 => { - current_block = 2973387206439775448; - match current_block { - 2973387206439775448 => { - if 0 == import_backup(context, param1) { - current_block = 3568988166330621280; - } else { - current_block = 1118134448028020070; - } - } - 11250025114629486028 => { - if 0 == import_self_keys(context, param1) { - current_block = 3568988166330621280; - } else { - current_block = 1118134448028020070; - } - } - 12669919903773909120 => { - if 0 == export_backup(context, param1) { - current_block = 3568988166330621280; - } else { - current_block = 1118134448028020070; - } - } - _ => { - if 0 == export_self_keys(context, param1) { - current_block = 3568988166330621280; - } else { - current_block = 1118134448028020070; - } + match current_block { + 3568988166330621280 => {} + _ => { + dc_log_info( + context, + 0i32, + b"Import/export completed.\x00" as *const u8 + as *const libc::c_char, + ); + success = 1i32 + } + } + } + 12 => { + current_block = 2973387206439775448; + match current_block { + 2973387206439775448 => { + if 0 == import_backup(context, param1) { + current_block = 3568988166330621280; + } else { + current_block = 1118134448028020070; } } - match current_block { - 3568988166330621280 => {} - _ => { - dc_log_info( - context, - 0i32, - b"Import/export completed.\x00" as *const u8 - as *const libc::c_char, - ); - success = 1i32 + 11250025114629486028 => { + if 0 == import_self_keys(context, param1) { + current_block = 3568988166330621280; + } else { + current_block = 1118134448028020070; + } + } + 12669919903773909120 => { + if 0 == export_backup(context, param1) { + current_block = 3568988166330621280; + } else { + current_block = 1118134448028020070; + } + } + _ => { + if 0 == export_self_keys(context, param1) { + current_block = 3568988166330621280; + } else { + current_block = 1118134448028020070; } } } - _ => {} - }, - } + match current_block { + 3568988166330621280 => {} + _ => { + dc_log_info( + context, + 0i32, + b"Import/export completed.\x00" as *const u8 + as *const libc::c_char, + ); + success = 1i32 + } + } + } + _ => {} + }, } } } } + free(param1 as *mut libc::c_void); free(param2 as *mut libc::c_void); if 0 != ongoing_allocated_here { dc_free_ongoing(context); } - ((*context).cb)( + (context.cb)( context, Event::IMEX_PROGRESS, (if 0 != success { 1000i32 } else { 0i32 }) as uintptr_t, 0i32 as uintptr_t, ); } -/* ****************************************************************************** + +/******************************************************************************* * Import backup ******************************************************************************/ + +// TODO should return bool /rtn unsafe fn import_backup( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut backup_to_import: *const libc::c_char, ) -> libc::c_int { let mut current_block: u64; let mut success: libc::c_int = 0i32; let mut processed_files_cnt: libc::c_int = 0i32; - let mut total_files_cnt: libc::c_int = 0i32; + let mut total_files_cnt: libc::c_int; let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; let mut pathNfilename: *mut libc::c_char = 0 as *mut libc::c_char; let mut repl_from: *mut libc::c_char = 0 as *mut libc::c_char; @@ -949,7 +1001,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( @@ -958,31 +1010,39 @@ unsafe fn import_backup( b"Cannot import backups to accounts in use.\x00" as *const u8 as *const libc::c_char, ); } else { - if 0 != dc_sqlite3_is_open((*context).sql) { - dc_sqlite3_close((*context).sql); + 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).sql, (*context).dbfile, 0i32)) { + if !(0 + == dc_sqlite3_open( + context, + &mut context.sql.clone().write().unwrap(), + context.get_dbfile(), + 0i32, + )) + { stmt = dc_sqlite3_prepare( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"SELECT COUNT(*) FROM backup_blobs;\x00" as *const u8 as *const libc::c_char, ); sqlite3_step(stmt); total_files_cnt = sqlite3_column_int(stmt, 0i32); sqlite3_finalize(stmt); - stmt = 0 as *mut sqlite3_stmt; stmt = dc_sqlite3_prepare( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"SELECT file_name, file_content FROM backup_blobs ORDER BY id;\x00" as *const u8 as *const libc::c_char, ); @@ -991,7 +1051,13 @@ unsafe fn import_backup( current_block = 10891380440665537214; break; } - if 0 != (*context).shall_stop_ongoing { + if context + .running_state + .clone() + .read() + .unwrap() + .shall_stop_ongoing + { current_block = 8648553629232744886; break; } @@ -1003,7 +1069,7 @@ unsafe fn import_backup( if permille > 990i32 { permille = 990i32 } - ((*context).cb)( + (context.cb)( context, Event::IMEX_PROGRESS, permille as uintptr_t, @@ -1019,7 +1085,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 @@ -1050,11 +1116,13 @@ unsafe fn import_backup( sqlite3_finalize(stmt); stmt = 0 as *mut sqlite3_stmt; dc_sqlite3_execute( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"DROP TABLE backup_blobs;\x00" as *const u8 as *const libc::c_char, ); dc_sqlite3_try_execute( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"VACUUM;\x00" as *const u8 as *const libc::c_char, ); success = 1i32 @@ -1067,37 +1135,37 @@ unsafe fn import_backup( free(repl_from as *mut libc::c_void); free(repl_to as *mut libc::c_void); sqlite3_finalize(stmt); - return success; + + success } -/* ****************************************************************************** + +/******************************************************************************* * Export backup ******************************************************************************/ /* the FILE_PROGRESS macro calls the callback with the permille of files processed. The macro avoids weird values of 0% or 100% while still working. */ -unsafe fn export_backup( - mut context: *mut dc_context_t, - mut dir: *const libc::c_char, -) -> libc::c_int { +// TODO should return bool /rtn +unsafe fn export_backup(mut context: &dc_context_t, mut dir: *const libc::c_char) -> libc::c_int { let mut current_block: u64; let mut success: libc::c_int = 0i32; let mut closed: libc::c_int = 0i32; - let mut dest_pathNfilename: *mut libc::c_char = 0 as *mut libc::c_char; - let mut dest_sql: *mut dc_sqlite3_t = 0 as *mut dc_sqlite3_t; + let mut dest_pathNfilename: *mut libc::c_char; let mut now = time(0 as *mut time_t); let mut dir_handle: *mut DIR = 0 as *mut DIR; - let mut dir_entry: *mut dirent = 0 as *mut dirent; + let mut dir_entry: *mut dirent; let mut prefix_len = strlen(b"delta-chat\x00" as *const u8 as *const libc::c_char); let mut suffix_len = strlen(b"bak\x00" as *const u8 as *const libc::c_char); let mut curr_pathNfilename: *mut libc::c_char = 0 as *mut libc::c_char; let mut buf: *mut libc::c_void = 0 as *mut libc::c_void; let mut buf_bytes: size_t = 0i32 as size_t; let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; - let mut total_files_cnt: libc::c_int = 0i32; + let mut total_files_cnt: libc::c_int; let mut processed_files_cnt: libc::c_int = 0i32; let mut delete_dest_file: libc::c_int = 0i32; + let mut dest_sql: Option = None; /* get a fine backup file name (the name includes the date so that multiple backup instances are possible) FIXME: we should write to a temporary file first and rename it on success. this would guarantee the backup is complete. however, currently it is not clear it the import exists in the long run (may be replaced by a restore-from-imap)*/ - let mut timeinfo: *mut tm = 0 as *mut tm; + let mut timeinfo: *mut tm; let mut buffer: [libc::c_char; 256] = [0; 256]; timeinfo = localtime(&mut now); strftime( @@ -1116,33 +1184,40 @@ unsafe fn export_backup( } else { dc_housekeeping(context); dc_sqlite3_try_execute( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"VACUUM;\x00" as *const u8 as *const libc::c_char, ); - dc_sqlite3_close((*context).sql); + dc_sqlite3_close(context, &mut context.sql.clone().write().unwrap()); closed = 1i32; dc_log_info( 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).sql, (*context).dbfile, 0i32); + dc_sqlite3_open( + context, + &mut context.sql.clone().write().unwrap(), + context.get_dbfile(), + 0i32, + ); closed = 0i32; /* add all files as blobs to the database copy (this does not require the source to be locked, neigher the destination as it is used only here) */ /*for logging only*/ - dest_sql = dc_sqlite3_new(context); - if !(dest_sql.is_null() || 0 == dc_sqlite3_open(dest_sql, dest_pathNfilename, 0i32)) { + let mut sql = dc_sqlite3_new(); + if 0 != dc_sqlite3_open(context, &mut sql, dest_pathNfilename, 0i32) { /* error already logged */ if 0 == dc_sqlite3_table_exists( - dest_sql, + context, + &mut sql, b"backup_blobs\x00" as *const u8 as *const libc::c_char, ) { if 0 == - dc_sqlite3_execute(dest_sql, + dc_sqlite3_execute(context, &mut sql, b"CREATE TABLE backup_blobs (id INTEGER PRIMARY KEY, file_name, file_content);\x00" as *const u8 as *const libc::c_char) { @@ -1156,7 +1231,7 @@ unsafe fn export_backup( 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, @@ -1164,7 +1239,7 @@ unsafe fn export_backup( 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 { @@ -1178,7 +1253,7 @@ unsafe fn export_backup( 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, @@ -1186,22 +1261,30 @@ unsafe fn export_backup( 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 { stmt = - dc_sqlite3_prepare(dest_sql, - b"INSERT INTO backup_blobs (file_name, file_content) VALUES (?, ?);\x00" - as *const u8 as - *const libc::c_char); + dc_sqlite3_prepare( + context, + &mut sql, + b"INSERT INTO backup_blobs (file_name, file_content) VALUES (?, ?);\x00" + as *const u8 as + *const libc::c_char); loop { dir_entry = readdir(dir_handle); if dir_entry.is_null() { current_block = 2631791190359682872; break; } - if 0 != (*context).shall_stop_ongoing { + if context + .running_state + .clone() + .read() + .unwrap() + .shall_stop_ongoing + { delete_dest_file = 1i32; current_block = 11487273724841241105; break; @@ -1215,7 +1298,7 @@ unsafe fn export_backup( if permille > 990i32 { permille = 990i32 } - ((*context).cb)( + (context.cb)( context, Event::IMEX_PROGRESS, permille as uintptr_t, @@ -1255,7 +1338,7 @@ unsafe fn export_backup( curr_pathNfilename = dc_mprintf( b"%s/%s\x00" as *const u8 as *const libc::c_char, - (*context).blobdir, + context.get_blobdir(), name, ); free(buf); @@ -1302,7 +1385,7 @@ unsafe fn export_backup( 0i32, b"Backup: No files to copy.\x00" as *const u8 as *const libc::c_char, - (*context).blobdir, + context.get_blobdir(), ); current_block = 2631791190359682872; } @@ -1310,11 +1393,12 @@ unsafe fn export_backup( 11487273724841241105 => {} _ => { dc_sqlite3_set_config_int( - dest_sql, + context, + &mut sql, b"backup_time\x00" as *const u8 as *const libc::c_char, now as int32_t, ); - ((*context).cb)( + (context.cb)( context, Event::IMEX_FILE_WRITTEN, dest_pathNfilename as uintptr_t, @@ -1327,30 +1411,40 @@ unsafe fn export_backup( } } } + dest_sql = Some(sql); } } if !dir_handle.is_null() { closedir(dir_handle); } if 0 != closed { - dc_sqlite3_open((*context).sql, (*context).dbfile, 0i32); + dc_sqlite3_open( + context, + &mut context.sql.clone().write().unwrap(), + context.get_dbfile(), + 0i32, + ); } sqlite3_finalize(stmt); - dc_sqlite3_close(dest_sql); - dc_sqlite3_unref(dest_sql); + if let Some(ref mut sql) = dest_sql { + dc_sqlite3_close(context, sql); + dc_sqlite3_unref(context, sql); + } if 0 != delete_dest_file { dc_delete_file(context, dest_pathNfilename); } free(dest_pathNfilename as *mut libc::c_void); free(curr_pathNfilename as *mut libc::c_void); free(buf); - return success; + + success } -/* ****************************************************************************** + +/******************************************************************************* * Classic key import ******************************************************************************/ unsafe fn import_self_keys( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut dir_name: *const libc::c_char, ) -> libc::c_int { /* hint: even if we switch to import Autocrypt Setup Files, we should leave the possibility to import @@ -1360,22 +1454,19 @@ unsafe fn import_self_keys( Maybe we should make the "default" key handlong also a little bit smarter (currently, the last imported key is the standard key unless it contains the string "legacy" in its name) */ let mut imported_cnt: libc::c_int = 0i32; - let mut dir_handle: *mut DIR = 0 as *mut DIR; - let mut dir_entry: *mut dirent = 0 as *mut dirent; + let mut dir_handle = 0 as *mut DIR; + let mut dir_entry: *mut dirent; let mut suffix: *mut libc::c_char = 0 as *mut libc::c_char; let mut path_plus_name: *mut libc::c_char = 0 as *mut libc::c_char; - let mut set_default: libc::c_int = 0i32; + let mut set_default: libc::c_int; let mut buf: *mut libc::c_char = 0 as *mut libc::c_char; let mut buf_bytes: size_t = 0i32 as size_t; // a pointer inside buf, MUST NOT be free()'d - let mut private_key: *const libc::c_char = 0 as *const libc::c_char; + let mut private_key: *const libc::c_char; let mut buf2: *mut libc::c_char = 0 as *mut libc::c_char; // a pointer inside buf2, MUST NOT be free()'d let mut buf2_headerline: *const libc::c_char = 0 as *const libc::c_char; - if !(context.is_null() - || (*context).magic != 0x11a11807i32 as libc::c_uint - || dir_name.is_null()) - { + if !dir_name.is_null() { dir_handle = opendir(dir_name); if dir_handle.is_null() { dc_log_error( @@ -1481,21 +1572,24 @@ unsafe fn import_self_keys( free(path_plus_name as *mut libc::c_void); free(buf as *mut libc::c_void); free(buf2 as *mut libc::c_void); - return imported_cnt; + + imported_cnt } + +// TODO should return bool /rtn unsafe fn export_self_keys( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut dir: *const libc::c_char, ) -> libc::c_int { let mut success: libc::c_int = 0i32; let mut export_errors: libc::c_int = 0i32; - let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; - let mut id: libc::c_int = 0i32; - let mut is_default: libc::c_int = 0i32; + let mut id: libc::c_int; + let mut is_default: libc::c_int; let mut public_key: *mut dc_key_t = dc_key_new(); let mut private_key: *mut dc_key_t = dc_key_new(); - stmt = dc_sqlite3_prepare( - (*context).sql, + let stmt = dc_sqlite3_prepare( + context, + &context.sql.clone().read().unwrap(), b"SELECT id, public_key, private_key, is_default FROM keypairs;\x00" as *const u8 as *const libc::c_char, ); @@ -1519,20 +1613,23 @@ unsafe fn export_self_keys( sqlite3_finalize(stmt); dc_key_unref(public_key); dc_key_unref(private_key); - return success; + + success } -/* ****************************************************************************** + +/******************************************************************************* * Classic key export ******************************************************************************/ +// TODO should return bool /rtn unsafe fn export_key_to_asc_file( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut dir: *const libc::c_char, mut id: libc::c_int, mut key: *const dc_key_t, mut is_default: libc::c_int, ) -> libc::c_int { let mut success: libc::c_int = 0i32; - let mut file_name: *mut libc::c_char = 0 as *mut libc::c_char; + let mut file_name; if 0 != is_default { file_name = dc_mprintf( b"%s/%s-key-default.asc\x00" as *const u8 as *const libc::c_char, @@ -1570,7 +1667,7 @@ unsafe fn export_key_to_asc_file( file_name, ); } else { - ((*context).cb)( + (context.cb)( context, Event::IMEX_FILE_WRITTEN, file_name as uintptr_t, @@ -1579,5 +1676,6 @@ unsafe fn export_key_to_asc_file( success = 1i32 } free(file_name as *mut libc::c_void); - return success; + + success } diff --git a/src/dc_job.rs b/src/dc_job.rs index b88ae293e..d5e3be782 100644 --- a/src/dc_job.rs +++ b/src/dc_job.rs @@ -1,4 +1,8 @@ -use libc; +use mmime::mmapstring::*; + +use std::ffi::CStr; +use std::time::{Duration, SystemTime}; + use rand::{thread_rng, Rng}; use crate::constants::Event; @@ -15,7 +19,6 @@ use crate::dc_loginparam::*; use crate::dc_mimefactory::*; use crate::dc_msg::*; use crate::dc_param::*; -use crate::dc_smtp::*; use crate::dc_sqlite3::*; use crate::dc_tools::*; use crate::types::*; @@ -45,18 +48,18 @@ pub struct dc_job_t { pub pending_error: *mut libc::c_char, } -pub unsafe fn dc_perform_imap_jobs(mut context: *mut dc_context_t) { +pub unsafe fn dc_perform_imap_jobs(context: &dc_context_t) { dc_log_info( context, 0i32, b"INBOX-jobs started...\x00" as *const u8 as *const libc::c_char, ); - pthread_mutex_lock(&mut (*context).inboxidle_condmutex); - let mut probe_imap_network: libc::c_int = (*context).probe_imap_network; - (*context).probe_imap_network = 0i32; - (*context).perform_inbox_jobs_needed = 0i32; - pthread_mutex_unlock(&mut (*context).inboxidle_condmutex); - dc_job_perform(context, 100i32, probe_imap_network); + + let probe_imap_network = *context.probe_imap_network.clone().read().unwrap(); + *context.probe_imap_network.clone().write().unwrap() = 0; + *context.perform_inbox_jobs_needed.clone().write().unwrap() = 0; + + dc_job_perform(context, 100, probe_imap_network); dc_log_info( context, 0i32, @@ -64,12 +67,12 @@ pub unsafe fn dc_perform_imap_jobs(mut context: *mut dc_context_t) { ); } unsafe fn dc_job_perform( - mut context: *mut dc_context_t, + context: &dc_context_t, mut thread: libc::c_int, mut probe_network: libc::c_int, ) { - let mut select_stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; - let mut job: dc_job_t = dc_job_t { + let mut select_stmt: *mut sqlite3_stmt; + let mut job = dc_job_t { job_id: 0, action: 0, foreign_id: 0, @@ -80,128 +83,143 @@ unsafe fn dc_job_perform( try_again: 0, pending_error: 0 as *mut libc::c_char, }; - memset( - &mut job as *mut dc_job_t as *mut libc::c_void, - 0, - ::std::mem::size_of::(), - ); job.param = dc_param_new(); - if !(context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint) { - if probe_network == 0i32 { - select_stmt = - dc_sqlite3_prepare((*context).sql, - b"SELECT id, action, foreign_id, param, added_timestamp, desired_timestamp, tries FROM jobs WHERE thread=? AND desired_timestamp<=? ORDER BY action DESC, added_timestamp;\x00" + + if probe_network == 0i32 { + select_stmt = + dc_sqlite3_prepare( + context, + &context.sql.clone().read().unwrap(), + b"SELECT id, action, foreign_id, param, added_timestamp, desired_timestamp, tries FROM jobs WHERE thread=? AND desired_timestamp<=? ORDER BY action DESC, added_timestamp;\x00" + as *const u8 as *const libc::c_char); + sqlite3_bind_int64(select_stmt, 1i32, thread as sqlite3_int64); + sqlite3_bind_int64(select_stmt, 2i32, time(0 as *mut time_t) as sqlite3_int64); + } else { + select_stmt = + dc_sqlite3_prepare( + context, + &context.sql.clone().read().unwrap(), + b"SELECT id, action, foreign_id, param, added_timestamp, desired_timestamp, tries FROM jobs WHERE thread=? AND tries>0 ORDER BY desired_timestamp, action DESC;\x00" as *const u8 as *const libc::c_char); - sqlite3_bind_int64(select_stmt, 1i32, thread as sqlite3_int64); - sqlite3_bind_int64(select_stmt, 2i32, time(0 as *mut time_t) as sqlite3_int64); - } else { - select_stmt = - dc_sqlite3_prepare((*context).sql, - b"SELECT id, action, foreign_id, param, added_timestamp, desired_timestamp, tries FROM jobs WHERE thread=? AND tries>0 ORDER BY desired_timestamp, action DESC;\x00" - as *const u8 as *const libc::c_char); - sqlite3_bind_int64(select_stmt, 1i32, thread as sqlite3_int64); - } - while sqlite3_step(select_stmt) == 100i32 { - job.job_id = sqlite3_column_int(select_stmt, 0i32) as uint32_t; - job.action = sqlite3_column_int(select_stmt, 1i32); - job.foreign_id = sqlite3_column_int(select_stmt, 2i32) as uint32_t; - dc_param_set_packed( - job.param, - sqlite3_column_text(select_stmt, 3i32) as *mut libc::c_char, + sqlite3_bind_int64(select_stmt, 1i32, thread as sqlite3_int64); + } + while sqlite3_step(select_stmt) == 100i32 { + job.job_id = sqlite3_column_int(select_stmt, 0i32) as uint32_t; + job.action = sqlite3_column_int(select_stmt, 1i32); + job.foreign_id = sqlite3_column_int(select_stmt, 2i32) as uint32_t; + dc_param_set_packed( + job.param, + sqlite3_column_text(select_stmt, 3i32) as *mut libc::c_char, + ); + job.added_timestamp = sqlite3_column_int64(select_stmt, 4i32) as time_t; + job.desired_timestamp = sqlite3_column_int64(select_stmt, 5i32) as time_t; + job.tries = sqlite3_column_int(select_stmt, 6i32); + dc_log_info( + context, + 0i32, + b"%s-job #%i, action %i started...\x00" as *const u8 as *const libc::c_char, + if thread == 100i32 { + b"INBOX\x00" as *const u8 as *const libc::c_char + } else { + b"SMTP\x00" as *const u8 as *const libc::c_char + }, + job.job_id as libc::c_int, + job.action as libc::c_int, + ); + if 900i32 == job.action || 910i32 == job.action { + dc_job_kill_action(context, job.action); + sqlite3_finalize(select_stmt); + select_stmt = 0 as *mut sqlite3_stmt; + dc_jobthread_suspend( + context, + &mut context.sentbox_thread.clone().lock().unwrap(), + 1, ); - job.added_timestamp = sqlite3_column_int64(select_stmt, 4i32) as time_t; - job.desired_timestamp = sqlite3_column_int64(select_stmt, 5i32) as time_t; - job.tries = sqlite3_column_int(select_stmt, 6i32); + dc_jobthread_suspend( + context, + &mut context.mvbox_thread.clone().lock().unwrap(), + 1, + ); + dc_suspend_smtp_thread(context, 1i32); + } + let mut tries: libc::c_int = 0i32; + while tries <= 1i32 { + job.try_again = 0i32; + match job.action { + 5901 => { + dc_job_do_DC_JOB_SEND(context, &mut job); + } + 110 => { + dc_job_do_DC_JOB_DELETE_MSG_ON_IMAP(context, &mut job); + } + 130 => { + dc_job_do_DC_JOB_MARKSEEN_MSG_ON_IMAP(context, &mut job); + } + 120 => { + dc_job_do_DC_JOB_MARKSEEN_MDN_ON_IMAP(context, &mut job); + } + 200 => { + dc_job_do_DC_JOB_MOVE_MSG(context, &mut job); + } + 5011 => { + dc_job_do_DC_JOB_SEND(context, &mut job); + } + 900 => { + dc_job_do_DC_JOB_CONFIGURE_IMAP(context, &mut job); + } + 910 => { + dc_job_do_DC_JOB_IMEX_IMAP(context, &mut job); + } + 5005 => { + dc_job_do_DC_JOB_MAYBE_SEND_LOCATIONS(context, &mut job); + } + 5007 => { + dc_job_do_DC_JOB_MAYBE_SEND_LOC_ENDED(context, &mut job); + } + 105 => { + dc_housekeeping(context); + } + _ => {} + } + if job.try_again != -1i32 { + break; + } + tries += 1 + } + if 900i32 == job.action || 910i32 == job.action { + dc_jobthread_suspend( + context, + &mut context.sentbox_thread.clone().lock().unwrap(), + 0, + ); + dc_jobthread_suspend( + context, + &mut context.mvbox_thread.clone().lock().unwrap(), + 0, + ); + dc_suspend_smtp_thread(context, 0i32); + break; + } else if job.try_again == 2i32 { dc_log_info( context, 0i32, - b"%s-job #%i, action %i started...\x00" as *const u8 as *const libc::c_char, + b"%s-job #%i not yet ready and will be delayed.\x00" as *const u8 + as *const libc::c_char, if thread == 100i32 { b"INBOX\x00" as *const u8 as *const libc::c_char } else { b"SMTP\x00" as *const u8 as *const libc::c_char }, job.job_id as libc::c_int, - job.action as libc::c_int, ); - if 900i32 == job.action || 910i32 == job.action { - dc_job_kill_action(context, job.action); - sqlite3_finalize(select_stmt); - select_stmt = 0 as *mut sqlite3_stmt; - dc_jobthread_suspend(&mut (*context).sentbox_thread, 1i32); - dc_jobthread_suspend(&mut (*context).mvbox_thread, 1i32); - dc_suspend_smtp_thread(context, 1i32); - } - let mut tries: libc::c_int = 0i32; - while tries <= 1i32 { - job.try_again = 0i32; - match job.action { - 5901 => { - dc_job_do_DC_JOB_SEND(context, &mut job); - } - 110 => { - dc_job_do_DC_JOB_DELETE_MSG_ON_IMAP(context, &mut job); - } - 130 => { - dc_job_do_DC_JOB_MARKSEEN_MSG_ON_IMAP(context, &mut job); - } - 120 => { - dc_job_do_DC_JOB_MARKSEEN_MDN_ON_IMAP(context, &mut job); - } - 200 => { - dc_job_do_DC_JOB_MOVE_MSG(context, &mut job); - } - 5011 => { - dc_job_do_DC_JOB_SEND(context, &mut job); - } - 900 => { - dc_job_do_DC_JOB_CONFIGURE_IMAP(context, &mut job); - } - 910 => { - dc_job_do_DC_JOB_IMEX_IMAP(context, &mut job); - } - 5005 => { - dc_job_do_DC_JOB_MAYBE_SEND_LOCATIONS(context, &mut job); - } - 5007 => { - dc_job_do_DC_JOB_MAYBE_SEND_LOC_ENDED(context, &mut job); - } - 105 => { - dc_housekeeping(context); - } - _ => {} - } - if job.try_again != -1i32 { - break; - } - tries += 1 - } - if 900i32 == job.action || 910i32 == job.action { - dc_jobthread_suspend(&mut (*context).sentbox_thread, 0i32); - dc_jobthread_suspend(&mut (*context).mvbox_thread, 0i32); - dc_suspend_smtp_thread(context, 0i32); - break; - } else if job.try_again == 2i32 { - dc_log_info( - context, - 0i32, - b"%s-job #%i not yet ready and will be delayed.\x00" as *const u8 - as *const libc::c_char, - if thread == 100i32 { - b"INBOX\x00" as *const u8 as *const libc::c_char - } else { - b"SMTP\x00" as *const u8 as *const libc::c_char - }, - job.job_id as libc::c_int, - ); - } else if job.try_again == -1i32 || job.try_again == 3i32 { - let mut tries_0: libc::c_int = job.tries + 1i32; - if tries_0 < 17i32 { - job.tries = tries_0; - let mut time_offset: time_t = get_backoff_time_offset(tries_0); - job.desired_timestamp = job.added_timestamp + time_offset; - dc_job_update(context, &mut job); - dc_log_info(context, 0i32, + } else if job.try_again == -1i32 || job.try_again == 3i32 { + let mut tries_0: libc::c_int = job.tries + 1i32; + if tries_0 < 17i32 { + job.tries = tries_0; + let mut time_offset: time_t = get_backoff_time_offset(tries_0); + job.desired_timestamp = job.added_timestamp + time_offset; + dc_job_update(context, &mut job); + dc_log_info(context, 0i32, b"%s-job #%i not succeeded on try #%i, retry in ADD_TIME+%i (in %i seconds).\x00" as *const u8 as *const libc::c_char, if thread == 100i32 { @@ -214,43 +232,49 @@ unsafe fn dc_job_perform( time_offset, job.added_timestamp + time_offset - time(0 as *mut time_t)); - if thread == 5000i32 && tries_0 < 17i32 - 1i32 { - pthread_mutex_lock(&mut (*context).smtpidle_condmutex); - (*context).perform_smtp_jobs_needed = 2i32; - pthread_mutex_unlock(&mut (*context).smtpidle_condmutex); - } - } else { - if job.action == 5901i32 { - dc_set_msg_failed(context, job.foreign_id, job.pending_error); - } - dc_job_delete(context, &mut job); + if thread == 5000i32 && tries_0 < 17i32 - 1i32 { + context + .smtp_state + .clone() + .0 + .lock() + .unwrap() + .perform_jobs_needed = 2i32; } - if !(0 != probe_network) { - continue; - } - // on dc_maybe_network() we stop trying here; - // these jobs are already tried once. - // otherwise, we just continue with the next job - // to give other jobs a chance being tried at least once. - break; } else { + if job.action == 5901i32 { + dc_set_msg_failed(context, job.foreign_id, job.pending_error); + } dc_job_delete(context, &mut job); } + if !(0 != probe_network) { + continue; + } + // on dc_maybe_network() we stop trying here; + // these jobs are already tried once. + // otherwise, we just continue with the next job + // to give other jobs a chance being tried at least once. + break; + } else { + dc_job_delete(context, &mut job); } } dc_param_unref(job.param); free(job.pending_error as *mut libc::c_void); sqlite3_finalize(select_stmt); } -unsafe fn dc_job_delete(mut context: *mut dc_context_t, mut job: *const dc_job_t) { + +unsafe fn dc_job_delete(context: &dc_context_t, job: &dc_job_t) { let mut delete_stmt: *mut sqlite3_stmt = dc_sqlite3_prepare( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"DELETE FROM jobs WHERE id=?;\x00" as *const u8 as *const libc::c_char, ); - sqlite3_bind_int(delete_stmt, 1i32, (*job).job_id as libc::c_int); + sqlite3_bind_int(delete_stmt, 1i32, job.job_id as libc::c_int); sqlite3_step(delete_stmt); sqlite3_finalize(delete_stmt); } + /* ****************************************************************************** * Tools ******************************************************************************/ @@ -266,52 +290,53 @@ unsafe fn get_backoff_time_offset(mut c_tries: libc::c_int) -> time_t { } return seconds; } -unsafe fn dc_job_update(mut context: *mut dc_context_t, mut job: *const dc_job_t) { +unsafe fn dc_job_update(context: &dc_context_t, job: &dc_job_t) { let mut stmt: *mut sqlite3_stmt = dc_sqlite3_prepare( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"UPDATE jobs SET desired_timestamp=?, tries=?, param=? WHERE id=?;\x00" as *const u8 as *const libc::c_char, ); - sqlite3_bind_int64(stmt, 1i32, (*job).desired_timestamp as sqlite3_int64); - sqlite3_bind_int64(stmt, 2i32, (*job).tries as sqlite3_int64); - sqlite3_bind_text(stmt, 3i32, (*(*job).param).packed, -1i32, None); - sqlite3_bind_int(stmt, 4i32, (*job).job_id as libc::c_int); + sqlite3_bind_int64(stmt, 1i32, job.desired_timestamp as sqlite3_int64); + sqlite3_bind_int64(stmt, 2i32, job.tries as sqlite3_int64); + sqlite3_bind_text(stmt, 3i32, (*job.param).packed, -1i32, None); + sqlite3_bind_int(stmt, 4i32, job.job_id as libc::c_int); sqlite3_step(stmt); sqlite3_finalize(stmt); } -unsafe fn dc_suspend_smtp_thread(mut context: *mut dc_context_t, mut suspend: libc::c_int) { - pthread_mutex_lock(&mut (*context).smtpidle_condmutex); - (*context).smtp_suspended = suspend; - pthread_mutex_unlock(&mut (*context).smtpidle_condmutex); +unsafe fn dc_suspend_smtp_thread(mut context: &dc_context_t, mut suspend: libc::c_int) { + context.smtp_state.clone().0.lock().unwrap().suspended = suspend; if 0 != suspend { loop { - pthread_mutex_lock(&mut (*context).smtpidle_condmutex); - if (*context).smtp_doing_jobs == 0i32 { - pthread_mutex_unlock(&mut (*context).smtpidle_condmutex); + if context.smtp_state.clone().0.lock().unwrap().doing_jobs == 0 { return; } - pthread_mutex_unlock(&mut (*context).smtpidle_condmutex); usleep((300i32 * 1000i32) as libc::useconds_t); } - }; + } } -unsafe extern "C" fn dc_job_do_DC_JOB_SEND(mut context: *mut dc_context_t, mut job: *mut dc_job_t) { +unsafe extern "C" fn dc_job_do_DC_JOB_SEND(context: &dc_context_t, job: &mut dc_job_t) { let mut current_block: u64; let mut filename: *mut libc::c_char = 0 as *mut libc::c_char; let mut buf: *mut libc::c_void = 0 as *mut libc::c_void; let mut buf_bytes: size_t = 0i32 as size_t; let mut recipients: *mut libc::c_char = 0 as *mut libc::c_char; - let mut recipients_list: *mut clist = 0 as *mut clist; let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; /* connect to SMTP server, if not yet done */ - if 0 == dc_smtp_is_connected((*context).smtp) { + if !context.smtp.clone().lock().unwrap().is_connected() { let mut loginparam: *mut dc_loginparam_t = dc_loginparam_new(); dc_loginparam_read( + context, loginparam, - (*context).sql, + &context.sql.clone().read().unwrap(), b"configured_\x00" as *const u8 as *const libc::c_char, ); - let mut connected: libc::c_int = dc_smtp_connect((*context).smtp, loginparam); + let mut connected = context + .smtp + .clone() + .lock() + .unwrap() + .connect(context, loginparam); dc_loginparam_unref(loginparam); if 0 == connected { dc_job_try_again_later(job, 3i32, 0 as *const libc::c_char); @@ -324,40 +349,48 @@ unsafe extern "C" fn dc_job_do_DC_JOB_SEND(mut context: *mut dc_context_t, mut j } match current_block { 13109137661213826276 => { - filename = dc_param_get((*job).param, 'f' as i32, 0 as *const libc::c_char); + filename = dc_param_get(job.param, 'f' as i32, 0 as *const libc::c_char); if filename.is_null() { dc_log_warning( context, 0i32, b"Missing file name for job %d\x00" as *const u8 as *const libc::c_char, - (*job).job_id, + job.job_id, ); } else if !(0 == dc_read_file(context, filename, &mut buf, &mut buf_bytes)) { - recipients = dc_param_get((*job).param, 'R' as i32, 0 as *const libc::c_char); + recipients = dc_param_get(job.param, 'R' as i32, 0 as *const libc::c_char); if recipients.is_null() { dc_log_warning( context, 0i32, b"Missing recipients for job %d\x00" as *const u8 as *const libc::c_char, - (*job).job_id, + job.job_id, ); } else { - recipients_list = dc_str_to_clist( - recipients, - b"\x1e\x00" as *const u8 as *const libc::c_char, - ); + let recipients_list = std::ffi::CStr::from_ptr(recipients) + .to_str() + .unwrap() + .split("\x1e") + .filter_map(|addr| match lettre::EmailAddress::new(addr.to_string()) { + Ok(addr) => Some(addr), + Err(err) => { + eprintln!("WARNING: invalid recipient: {} {:?}", addr, err); + None + } + }) + .collect::>(); /* if there is a msg-id and it does not exist in the db, cancel sending. this happends if dc_delete_msgs() was called before the generated mime was sent out */ - if 0 != (*job).foreign_id { - if 0 == dc_msg_exists(context, (*job).foreign_id) { + if 0 != job.foreign_id { + if 0 == dc_msg_exists(context, job.foreign_id) { dc_log_warning( context, 0i32, b"Message %i for job %i does not exist\x00" as *const u8 as *const libc::c_char, - (*job).foreign_id, - (*job).job_id, + job.foreign_id, + job.job_id, ); current_block = 14216916617354591294; } else { @@ -370,48 +403,40 @@ unsafe extern "C" fn dc_job_do_DC_JOB_SEND(mut context: *mut dc_context_t, mut j 14216916617354591294 => {} _ => { /* send message */ - if 0 == dc_smtp_send_msg( - (*context).smtp, + let body = + std::slice::from_raw_parts(buf as *const u8, buf_bytes).to_vec(); + if 0 == context.smtp.clone().lock().unwrap().send( + context, recipients_list, - buf as *const libc::c_char, - buf_bytes, + body, ) { - if 0 != (*job).foreign_id - && (MAILSMTP_ERROR_EXCEED_STORAGE_ALLOCATION as libc::c_int - == (*(*context).smtp).error_etpan - || MAILSMTP_ERROR_INSUFFICIENT_SYSTEM_STORAGE - as libc::c_int - == (*(*context).smtp).error_etpan) - { - dc_set_msg_failed( - context, - (*job).foreign_id, - (*(*context).smtp).error, - ); - } else { - dc_smtp_disconnect((*context).smtp); - dc_job_try_again_later(job, -1i32, (*(*context).smtp).error); - } + context.smtp.clone().lock().unwrap().disconnect(); + dc_job_try_again_later( + job, + -1i32, + (*&mut context.smtp.clone().lock().unwrap()).error, + ); } else { dc_delete_file(context, filename); - if 0 != (*job).foreign_id { - dc_update_msg_state(context, (*job).foreign_id, 26i32); + if 0 != job.foreign_id { + dc_update_msg_state(context, job.foreign_id, 26i32); stmt = dc_sqlite3_prepare( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"SELECT chat_id FROM msgs WHERE id=?\x00" as *const u8 as *const libc::c_char, ); - sqlite3_bind_int(stmt, 1i32, (*job).foreign_id as libc::c_int); + sqlite3_bind_int(stmt, 1i32, job.foreign_id as libc::c_int); let mut chat_id: libc::c_int = if sqlite3_step(stmt) == 100i32 { sqlite3_column_int(stmt, 0i32) } else { 0i32 }; - ((*context).cb)( + (context.cb)( context, Event::MSG_DELIVERED, chat_id as uintptr_t, - (*job).foreign_id as uintptr_t, + job.foreign_id as uintptr_t, ); } } @@ -423,35 +448,32 @@ unsafe extern "C" fn dc_job_do_DC_JOB_SEND(mut context: *mut dc_context_t, mut j _ => {} } sqlite3_finalize(stmt); - if !recipients_list.is_null() { - clist_free_content(recipients_list); - clist_free(recipients_list); - } free(recipients as *mut libc::c_void); free(buf); free(filename as *mut libc::c_void); } // this value does not increase the number of tries pub unsafe fn dc_job_try_again_later( - mut job: *mut dc_job_t, - mut try_again: libc::c_int, - mut pending_error: *const libc::c_char, + job: &mut dc_job_t, + try_again: libc::c_int, + pending_error: *const libc::c_char, ) { - if job.is_null() { - return; - } - (*job).try_again = try_again; - free((*job).pending_error as *mut libc::c_void); - (*job).pending_error = dc_strdup_keep_null(pending_error); + job.try_again = try_again; + free(job.pending_error as *mut libc::c_void); + job.pending_error = dc_strdup_keep_null(pending_error); } -unsafe fn dc_job_do_DC_JOB_MOVE_MSG(mut context: *mut dc_context_t, mut job: *mut dc_job_t) { + +unsafe fn dc_job_do_DC_JOB_MOVE_MSG(context: &dc_context_t, job: &mut dc_job_t) { let mut current_block: u64; 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((*context).inbox) { - connect_to_inbox(context); - if 0 == dc_imap_is_connected((*context).inbox) { + + 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 { @@ -462,25 +484,29 @@ unsafe fn dc_job_do_DC_JOB_MOVE_MSG(mut context: *mut dc_context_t, mut job: *mu } match current_block { 2473556513754201174 => { - if !(0 == dc_msg_load_from_db(msg, context, (*job).foreign_id)) { + if !(0 == dc_msg_load_from_db(msg, context, job.foreign_id)) { if dc_sqlite3_get_config_int( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"folders_configured\x00" as *const u8 as *const libc::c_char, 0i32, ) < 3i32 { - dc_configure_folders(context, (*context).inbox, 0x1i32); + inbox.configure_folders(context, 0x1i32); } dest_folder = dc_sqlite3_get_config( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"configured_mvbox_folder\x00" as *const u8 as *const libc::c_char, 0 as *const libc::c_char, ); - match dc_imap_move( - (*context).inbox, - (*msg).server_folder, + + let server_folder = CStr::from_ptr((*msg).server_folder).to_str().unwrap(); + match inbox.mv( + context, + server_folder, (*msg).server_uid, - dest_folder, + CStr::from_ptr(dest_folder).to_str().unwrap(), &mut dest_uid, ) as libc::c_uint { @@ -528,30 +554,28 @@ unsafe fn dc_job_do_DC_JOB_MOVE_MSG(mut context: *mut dc_context_t, mut job: *mu /* ****************************************************************************** * IMAP-jobs ******************************************************************************/ -unsafe fn connect_to_inbox(mut context: *mut dc_context_t) -> libc::c_int { - let mut ret_connected: libc::c_int = 0i32; - ret_connected = dc_connect_to_configured_imap(context, (*context).inbox); +unsafe fn connect_to_inbox(context: &dc_context_t, inbox: &Imap) -> libc::c_int { + let mut ret_connected: libc::c_int; + + ret_connected = dc_connect_to_configured_imap(context, inbox); if !(0 == ret_connected) { - dc_imap_set_watch_folder( - (*context).inbox, - 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: *mut 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; + 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((*context).inbox) { - connect_to_inbox(context); - if 0 == dc_imap_is_connected((*context).inbox) { + 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 { @@ -562,28 +586,28 @@ unsafe fn dc_job_do_DC_JOB_MARKSEEN_MDN_ON_IMAP( } match current_block { 11006700562992250127 => { - if dc_imap_set_seen((*context).inbox, folder, uid) as libc::c_uint - == 0i32 as libc::c_uint - { + let folder = CStr::from_ptr(folder).to_str().unwrap(); + 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) { + if 0 != dc_param_get_int(job.param, 'M' as i32, 0i32) { if dc_sqlite3_get_config_int( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"folders_configured\x00" as *const u8 as *const libc::c_char, 0i32, ) < 3i32 { - dc_configure_folders(context, (*context).inbox, 0x1i32); + inbox.configure_folders(context, 0x1i32); } dest_folder = dc_sqlite3_get_config( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"configured_mvbox_folder\x00" as *const u8 as *const libc::c_char, 0 as *const libc::c_char, ); - match dc_imap_move((*context).inbox, folder, uid, dest_folder, &mut dest_uid) - as libc::c_uint - { + let dest_folder = CStr::from_ptr(dest_folder).to_str().unwrap(); + 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); } @@ -596,15 +620,14 @@ unsafe fn dc_job_do_DC_JOB_MARKSEEN_MDN_ON_IMAP( free(folder as *mut libc::c_void); free(dest_folder as *mut libc::c_void); } -unsafe fn dc_job_do_DC_JOB_MARKSEEN_MSG_ON_IMAP( - mut context: *mut dc_context_t, - mut job: *mut dc_job_t, -) { +unsafe fn dc_job_do_DC_JOB_MARKSEEN_MSG_ON_IMAP(context: &dc_context_t, job: &mut dc_job_t) { let mut current_block: u64; let mut msg: *mut dc_msg_t = dc_msg_new_untyped(context); - if 0 == dc_imap_is_connected((*context).inbox) { - connect_to_inbox(context); - if 0 == dc_imap_is_connected((*context).inbox) { + 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 { @@ -615,10 +638,9 @@ 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).inbox, (*msg).server_folder, (*msg).server_uid) - as libc::c_uint - { + if !(0 == dc_msg_load_from_db(msg, context, job.foreign_id)) { + let server_folder = CStr::from_ptr((*msg).server_folder).to_str().unwrap(); + match inbox.set_seen(context, server_folder, (*msg).server_uid) as libc::c_uint { 0 => {} 1 => { current_block = 12392248546350854223; @@ -629,16 +651,16 @@ unsafe fn dc_job_do_DC_JOB_MARKSEEN_MSG_ON_IMAP( _ => { if 0 != dc_param_get_int((*msg).param, 'r' as i32, 0i32) && 0 != dc_sqlite3_get_config_int( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"mdns_enabled\x00" as *const u8 as *const libc::c_char, 1i32, ) { - match dc_imap_set_mdnsent( - (*context).inbox, - (*msg).server_folder, - (*msg).server_uid, - ) as libc::c_uint + let folder = + CStr::from_ptr((*msg).server_folder).to_str().unwrap(); + match inbox.set_mdnsent(context, folder, (*msg).server_uid) + as libc::c_uint { 1 => { current_block = 4016212065805849280; @@ -685,16 +707,17 @@ unsafe fn dc_job_do_DC_JOB_MARKSEEN_MSG_ON_IMAP( _ => { if 0 != dc_param_get_int((*msg).param, 'r' as i32, 0i32) && 0 != dc_sqlite3_get_config_int( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"mdns_enabled\x00" as *const u8 as *const libc::c_char, 1i32, ) { - match dc_imap_set_mdnsent( - (*context).inbox, - (*msg).server_folder, - (*msg).server_uid, - ) as libc::c_uint + let folder = + CStr::from_ptr((*msg).server_folder).to_str().unwrap(); + + match inbox.set_mdnsent(context, folder, (*msg).server_uid) + as libc::c_uint { 1 => { current_block = 4016212065805849280; @@ -739,7 +762,7 @@ unsafe fn dc_job_do_DC_JOB_MARKSEEN_MSG_ON_IMAP( } dc_msg_unref(msg); } -unsafe fn dc_send_mdn(mut context: *mut dc_context_t, mut msg_id: uint32_t) { +unsafe fn dc_send_mdn(mut context: &dc_context_t, mut msg_id: uint32_t) { let mut mimefactory: dc_mimefactory_t = dc_mimefactory_t { from_addr: 0 as *mut libc::c_char, from_displayname: 0 as *mut libc::c_char, @@ -760,12 +783,9 @@ unsafe fn dc_send_mdn(mut context: *mut dc_context_t, mut msg_id: uint32_t) { out_gossiped: 0, out_last_added_location_id: 0, error: 0 as *mut libc::c_char, - context: 0 as *mut dc_context_t, + context, }; dc_mimefactory_init(&mut mimefactory, context); - if context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint { - return; - } if !(0 == dc_mimefactory_load_mdn(&mut mimefactory, msg_id) || 0 == dc_mimefactory_render(&mut mimefactory)) { @@ -785,11 +805,11 @@ unsafe fn dc_send_mdn(mut context: *mut dc_context_t, mut msg_id: uint32_t) { * @return 1=success, 0=error */ unsafe fn dc_add_smtp_job( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut action: libc::c_int, mut mimefactory: *mut dc_mimefactory_t, ) -> libc::c_int { - let mut pathNfilename: *mut libc::c_char = 0 as *mut libc::c_char; + let mut pathNfilename: *mut libc::c_char; let mut success: libc::c_int = 0i32; let mut recipients: *mut libc::c_char = 0 as *mut libc::c_char; let mut param: *mut dc_param_t = dc_param_new(); @@ -849,15 +869,15 @@ unsafe fn dc_add_smtp_job( return success; } pub unsafe fn dc_job_add( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut action: libc::c_int, mut foreign_id: libc::c_int, mut param: *const libc::c_char, mut delay_seconds: libc::c_int, ) { let mut timestamp: time_t = time(0 as *mut time_t); - let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; - let mut thread: libc::c_int = 0i32; + let mut stmt: *mut sqlite3_stmt; + let mut thread: libc::c_int; if action >= 100i32 && action < 100i32 + 1000i32 { thread = 100i32 } else if action >= 5000i32 && action < 5000i32 + 1000i32 { @@ -866,8 +886,10 @@ pub unsafe fn dc_job_add( return; } stmt = - dc_sqlite3_prepare((*context).sql, - b"INSERT INTO jobs (added_timestamp, thread, action, foreign_id, param, desired_timestamp) VALUES (?,?,?,?,?,?);\x00" + dc_sqlite3_prepare( + context, + &context.sql.clone().read().unwrap(), + b"INSERT INTO jobs (added_timestamp, thread, action, foreign_id, param, desired_timestamp) VALUES (?,?,?,?,?,?);\x00" as *const u8 as *const libc::c_char); sqlite3_bind_int64(stmt, 1i32, timestamp as sqlite3_int64); sqlite3_bind_int(stmt, 2i32, thread); @@ -897,56 +919,39 @@ pub unsafe fn dc_job_add( dc_interrupt_smtp_idle(context); }; } -pub unsafe fn dc_interrupt_smtp_idle(mut context: *mut dc_context_t) { - if context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint { - dc_log_warning( - context, - 0i32, - b"Interrupt SMTP-idle: Bad parameters.\x00" as *const u8 as *const libc::c_char, - ); - return; - } +pub unsafe fn dc_interrupt_smtp_idle(mut context: &dc_context_t) { dc_log_info( context, 0i32, b"Interrupting SMTP-idle...\x00" as *const u8 as *const libc::c_char, ); - pthread_mutex_lock(&mut (*context).smtpidle_condmutex); - (*context).perform_smtp_jobs_needed = 1i32; - (*context).smtpidle_condflag = 1i32; - pthread_cond_signal(&mut (*context).smtpidle_cond); - pthread_mutex_unlock(&mut (*context).smtpidle_condmutex); + + let &(ref lock, ref cvar) = &*context.smtp_state.clone(); + let mut state = lock.lock().unwrap(); + + state.perform_jobs_needed = 1; + state.idle = true; + cvar.notify_one(); } -pub unsafe fn dc_interrupt_imap_idle(mut context: *mut dc_context_t) { - if context.is_null() - || (*context).magic != 0x11a11807i32 as libc::c_uint - || (*context).inbox.is_null() - { - dc_log_warning( - context, - 0i32, - b"Interrupt IMAP-IDLE: Bad parameters.\x00" as *const u8 as *const libc::c_char, - ); - return; - } + +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, ); - pthread_mutex_lock(&mut (*context).inboxidle_condmutex); - (*context).perform_inbox_jobs_needed = 1i32; - pthread_mutex_unlock(&mut (*context).inboxidle_condmutex); - dc_imap_interrupt_idle((*context).inbox); + + *context.perform_inbox_jobs_needed.write().unwrap() = 1; + context.inbox.read().unwrap().interrupt_idle(); } -unsafe fn dc_job_do_DC_JOB_DELETE_MSG_ON_IMAP( - mut context: *mut dc_context_t, - mut job: *mut dc_job_t, -) { + +unsafe fn dc_job_do_DC_JOB_DELETE_MSG_ON_IMAP(context: &dc_context_t, 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); - if !(0 == dc_msg_load_from_db(msg, context, (*job).foreign_id) + 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) { @@ -962,9 +967,9 @@ unsafe fn dc_job_do_DC_JOB_DELETE_MSG_ON_IMAP( } /* 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((*context).inbox) { - connect_to_inbox(context); - if 0 == dc_imap_is_connected((*context).inbox) { + 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 { @@ -976,12 +981,9 @@ unsafe fn dc_job_do_DC_JOB_DELETE_MSG_ON_IMAP( match current_block { 8913536887710889399 => {} _ => { - if 0 == dc_imap_delete_msg( - (*context).inbox, - (*msg).rfc724_mid, - (*msg).server_folder, - (*msg).server_uid, - ) { + let mid = CStr::from_ptr((*msg).rfc724_mid).to_str().unwrap(); + let server_folder = CStr::from_ptr((*msg).server_folder).to_str().unwrap(); + if 0 == inbox.delete_msg(context, mid, server_folder, &mut (*msg).server_uid) { dc_job_try_again_later(job, -1i32, 0 as *const libc::c_char); current_block = 8913536887710889399; } else { @@ -1001,26 +1003,29 @@ unsafe fn dc_job_do_DC_JOB_DELETE_MSG_ON_IMAP( } dc_msg_unref(msg); } + /* delete all pending jobs with the given action */ -pub unsafe fn dc_job_kill_action(mut context: *mut dc_context_t, mut action: libc::c_int) { - if context.is_null() { - return; - } - let mut stmt: *mut sqlite3_stmt = dc_sqlite3_prepare( - (*context).sql, +pub unsafe fn dc_job_kill_action(mut context: &dc_context_t, mut action: libc::c_int) { + let mut stmt = dc_sqlite3_prepare( + context, + &context.sql.clone().read().unwrap(), b"DELETE FROM jobs WHERE action=?;\x00" as *const u8 as *const libc::c_char, ); sqlite3_bind_int(stmt, 1i32, action); sqlite3_step(stmt); sqlite3_finalize(stmt); } -pub unsafe fn dc_perform_imap_fetch(mut context: *mut 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( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"inbox_watch\x00" as *const u8 as *const libc::c_char, 1i32, ) == 0i32 @@ -1037,14 +1042,14 @@ pub unsafe fn dc_perform_imap_fetch(mut context: *mut dc_context_t) { 0i32, b"INBOX-fetch started...\x00" as *const u8 as *const libc::c_char, ); - dc_imap_fetch((*context).inbox); - if 0 != (*(*context).inbox).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).inbox); + inbox.fetch(context); } dc_log_info( context, @@ -1053,220 +1058,229 @@ pub unsafe fn dc_perform_imap_fetch(mut context: *mut 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(mut context: *mut dc_context_t) { - if context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint { - return; - } - connect_to_inbox(context); - pthread_mutex_lock(&mut (*context).inboxidle_condmutex); - if 0 != (*context).perform_inbox_jobs_needed { + +pub unsafe fn dc_perform_imap_idle(context: &dc_context_t) { + let inbox = context.inbox.read().unwrap(); + + connect_to_inbox(context, &inbox); + + if 0 != *context.perform_inbox_jobs_needed.clone().read().unwrap() { dc_log_info( context, 0i32, b"INBOX-IDLE will not be started because of waiting jobs.\x00" as *const u8 as *const libc::c_char, ); - pthread_mutex_unlock(&mut (*context).inboxidle_condmutex); return; } - pthread_mutex_unlock(&mut (*context).inboxidle_condmutex); dc_log_info( context, 0i32, b"INBOX-IDLE started...\x00" as *const u8 as *const libc::c_char, ); - dc_imap_idle((*context).inbox); + inbox.idle(context); dc_log_info( context, 0i32, b"INBOX-IDLE ended.\x00" as *const u8 as *const libc::c_char, ); } -pub unsafe fn dc_perform_mvbox_fetch(mut context: *mut dc_context_t) { - if context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint { - return; - } + +pub unsafe fn dc_perform_mvbox_fetch(context: &dc_context_t) { let mut use_network: libc::c_int = dc_sqlite3_get_config_int( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"mvbox_watch\x00" as *const u8 as *const libc::c_char, 1i32, ); - dc_jobthread_fetch(&mut (*context).mvbox_thread, use_network); + dc_jobthread_fetch( + context, + &mut context.mvbox_thread.clone().lock().unwrap(), + use_network, + ); } -pub unsafe fn dc_perform_mvbox_idle(mut context: *mut dc_context_t) { - if context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint { - return; - } + +pub unsafe fn dc_perform_mvbox_idle(context: &dc_context_t) { let mut use_network: libc::c_int = dc_sqlite3_get_config_int( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"mvbox_watch\x00" as *const u8 as *const libc::c_char, 1i32, ); - dc_jobthread_idle(&mut (*context).mvbox_thread, use_network); + dc_jobthread_idle( + context, + &mut context.mvbox_thread.clone().lock().unwrap(), + use_network, + ); } -pub unsafe fn dc_interrupt_mvbox_idle(mut context: *mut dc_context_t) { - if context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint { - dc_log_warning( - context, - 0i32, - b"Interrupt MVBOX-IDLE: Bad parameters.\x00" as *const u8 as *const libc::c_char, - ); - return; - } - dc_jobthread_interrupt_idle(&mut (*context).mvbox_thread); + +pub unsafe fn dc_interrupt_mvbox_idle(context: &dc_context_t) { + dc_jobthread_interrupt_idle(context, &mut context.mvbox_thread.clone().lock().unwrap()); } -pub unsafe fn dc_perform_sentbox_fetch(mut context: *mut dc_context_t) { - if context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint { - return; - } + +pub unsafe fn dc_perform_sentbox_fetch(context: &dc_context_t) { let mut use_network: libc::c_int = dc_sqlite3_get_config_int( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"sentbox_watch\x00" as *const u8 as *const libc::c_char, 1i32, ); - dc_jobthread_fetch(&mut (*context).sentbox_thread, use_network); + dc_jobthread_fetch( + context, + &mut context.sentbox_thread.clone().lock().unwrap(), + use_network, + ); } -pub unsafe fn dc_perform_sentbox_idle(mut context: *mut dc_context_t) { - if context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint { - return; - } + +pub unsafe fn dc_perform_sentbox_idle(context: &dc_context_t) { let mut use_network: libc::c_int = dc_sqlite3_get_config_int( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"sentbox_watch\x00" as *const u8 as *const libc::c_char, 1i32, ); - dc_jobthread_idle(&mut (*context).sentbox_thread, use_network); + dc_jobthread_idle( + context, + &mut context.sentbox_thread.clone().lock().unwrap(), + use_network, + ); } -pub unsafe fn dc_interrupt_sentbox_idle(mut context: *mut dc_context_t) { - if context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint { - dc_log_warning( - context, - 0i32, - b"Interrupt SENT-IDLE: Bad parameters.\x00" as *const u8 as *const libc::c_char, - ); - return; - } - dc_jobthread_interrupt_idle(&mut (*context).sentbox_thread); + +pub unsafe fn dc_interrupt_sentbox_idle(context: &dc_context_t) { + dc_jobthread_interrupt_idle(context, &mut context.sentbox_thread.clone().lock().unwrap()); } -pub unsafe fn dc_perform_smtp_jobs(mut context: *mut dc_context_t) { - pthread_mutex_lock(&mut (*context).smtpidle_condmutex); - let mut probe_smtp_network: libc::c_int = (*context).probe_smtp_network; - (*context).probe_smtp_network = 0i32; - (*context).perform_smtp_jobs_needed = 0i32; - if 0 != (*context).smtp_suspended { - dc_log_info( - context, - 0i32, - b"SMTP-jobs suspended.\x00" as *const u8 as *const libc::c_char, - ); - pthread_mutex_unlock(&mut (*context).smtpidle_condmutex); - return; - } - (*context).smtp_doing_jobs = 1i32; - pthread_mutex_unlock(&mut (*context).smtpidle_condmutex); + +pub unsafe fn dc_perform_smtp_jobs(context: &dc_context_t) { + let probe_smtp_network = { + let &(ref lock, _) = &*context.smtp_state.clone(); + let mut state = lock.lock().unwrap(); + + let probe_smtp_network = state.probe_network; + state.probe_network = 0; + state.perform_jobs_needed = 0; + + if 0 != state.suspended { + dc_log_info( + context, + 0i32, + b"SMTP-jobs suspended.\x00" as *const u8 as *const libc::c_char, + ); + return; + } + state.doing_jobs = 1; + probe_smtp_network + }; + dc_log_info( context, - 0i32, + 0, b"SMTP-jobs started...\x00" as *const u8 as *const libc::c_char, ); - dc_job_perform(context, 5000i32, probe_smtp_network); + dc_job_perform(context, 5000, probe_smtp_network); dc_log_info( context, 0i32, b"SMTP-jobs ended.\x00" as *const u8 as *const libc::c_char, ); - pthread_mutex_lock(&mut (*context).smtpidle_condmutex); - (*context).smtp_doing_jobs = 0i32; - pthread_mutex_unlock(&mut (*context).smtpidle_condmutex); -} -pub unsafe fn dc_perform_smtp_idle(mut context: *mut dc_context_t) { - if context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint { - dc_log_warning( - context, - 0i32, - b"Cannot perform SMTP-idle: Bad parameters.\x00" as *const u8 as *const libc::c_char, - ); - return; + + { + let &(ref lock, _) = &*context.smtp_state.clone(); + let mut state = lock.lock().unwrap(); + + state.doing_jobs = 0; } +} + +pub unsafe fn dc_perform_smtp_idle(mut context: &dc_context_t) { dc_log_info( context, 0i32, b"SMTP-idle started...\x00" as *const u8 as *const libc::c_char, ); - pthread_mutex_lock(&mut (*context).smtpidle_condmutex); - if (*context).perform_smtp_jobs_needed == 1i32 { - dc_log_info( - context, - 0i32, - b"SMTP-idle will not be started because of waiting jobs.\x00" as *const u8 - as *const libc::c_char, - ); - } else { - let mut r: libc::c_int = 0i32; - let mut wakeup_at: timespec = timespec { - tv_sec: 0, - tv_nsec: 0, - }; - memset( - &mut wakeup_at as *mut timespec as *mut libc::c_void, - 0, - ::std::mem::size_of::(), - ); - wakeup_at.tv_sec = get_next_wakeup_time(context, 5000i32) + 1i32 as libc::c_long; - while (*context).smtpidle_condflag == 0i32 && r == 0i32 { - r = pthread_cond_timedwait( - &mut (*context).smtpidle_cond, - &mut (*context).smtpidle_condmutex, - &mut wakeup_at, - ) + { + let &(ref lock, ref cvar) = &*context.smtp_state.clone(); + let mut state = lock.lock().unwrap(); + + if state.perform_jobs_needed == 1 { + dc_log_info( + context, + 0, + b"SMTP-idle will not be started because of waiting jobs.\x00" as *const u8 + as *const libc::c_char, + ); + } else { + let dur = get_next_wakeup_time(context, 5000); + + loop { + let res = cvar.wait_timeout(state, dur).unwrap(); + state = res.0; + + if state.idle == true || res.1.timed_out() { + // We received the notification and the value has been updated, we can leave. + break; + } + } + state.idle = false; } - (*context).smtpidle_condflag = 0i32 } - pthread_mutex_unlock(&mut (*context).smtpidle_condmutex); + dc_log_info( context, 0i32, b"SMTP-idle ended.\x00" as *const u8 as *const libc::c_char, ); } -unsafe fn get_next_wakeup_time(mut context: *mut dc_context_t, mut thread: libc::c_int) -> time_t { - let mut wakeup_time: time_t = 0i32 as time_t; - let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; - stmt = dc_sqlite3_prepare( - (*context).sql, + +unsafe fn get_next_wakeup_time(context: &dc_context_t, thread: libc::c_int) -> Duration { + let stmt = dc_sqlite3_prepare( + context, + &context.sql.clone().read().unwrap(), b"SELECT MIN(desired_timestamp) FROM jobs WHERE thread=?;\x00" as *const u8 as *const libc::c_char, ); - sqlite3_bind_int(stmt, 1i32, thread); - if sqlite3_step(stmt) == 100i32 { - wakeup_time = sqlite3_column_int(stmt, 0i32) as time_t - } - if wakeup_time == 0i32 as libc::c_long { - wakeup_time = time(0 as *mut time_t) + (10i32 * 60i32) as libc::c_long + sqlite3_bind_int(stmt, 1, thread); + + let mut wakeup_time = Duration::new(10 * 60, 0); + + if sqlite3_step(stmt) == 100 { + let t = sqlite3_column_int(stmt, 0) as u64; + let now = SystemTime::now() + .duration_since(SystemTime::UNIX_EPOCH) + .unwrap(); + if t > 0 { + println!("{:?} {:?} {:?}", t, now, Duration::new(t, 0)); + wakeup_time = Duration::new(t, 0) - now; + } } + sqlite3_finalize(stmt); - return wakeup_time; + wakeup_time } -pub unsafe fn dc_maybe_network(mut context: *mut dc_context_t) { - pthread_mutex_lock(&mut (*context).smtpidle_condmutex); - (*context).probe_smtp_network = 1i32; - pthread_mutex_unlock(&mut (*context).smtpidle_condmutex); - pthread_mutex_lock(&mut (*context).inboxidle_condmutex); - (*context).probe_imap_network = 1i32; - pthread_mutex_unlock(&mut (*context).inboxidle_condmutex); + +pub unsafe fn dc_maybe_network(mut context: &dc_context_t) { + { + let &(ref lock, _) = &*context.smtp_state.clone(); + let mut state = lock.lock().unwrap(); + state.probe_network = 1; + + *context.probe_imap_network.clone().write().unwrap() = 1; + } + dc_interrupt_smtp_idle(context); dc_interrupt_imap_idle(context); dc_interrupt_mvbox_idle(context); dc_interrupt_sentbox_idle(context); } + pub unsafe fn dc_job_action_exists( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut action: libc::c_int, ) -> libc::c_int { - let mut job_exists: libc::c_int = 0i32; - let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; + let mut job_exists: libc::c_int; + let mut stmt; stmt = dc_sqlite3_prepare( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"SELECT id FROM jobs WHERE action=?;\x00" as *const u8 as *const libc::c_char, ); sqlite3_bind_int(stmt, 1i32, action); @@ -1275,9 +1289,9 @@ pub unsafe fn dc_job_action_exists( return job_exists; } /* special case for DC_JOB_SEND_MSG_TO_SMTP */ -pub unsafe fn dc_job_send_msg(mut context: *mut dc_context_t, mut msg_id: uint32_t) -> libc::c_int { +pub unsafe fn dc_job_send_msg(context: &dc_context_t, msg_id: uint32_t) -> libc::c_int { let mut success: libc::c_int = 0i32; - let mut mimefactory: dc_mimefactory_t = dc_mimefactory_t { + let mut mimefactory = dc_mimefactory_t { from_addr: 0 as *mut libc::c_char, from_displayname: 0 as *mut libc::c_char, selfstatus: 0 as *mut libc::c_char, @@ -1297,7 +1311,7 @@ pub unsafe fn dc_job_send_msg(mut context: *mut dc_context_t, mut msg_id: uint32 out_gossiped: 0, out_last_added_location_id: 0, error: 0 as *mut libc::c_char, - context: 0 as *mut dc_context_t, + context, }; dc_mimefactory_init(&mut mimefactory, context); /* load message data */ @@ -1317,7 +1331,7 @@ pub unsafe fn dc_job_send_msg(mut context: *mut dc_context_t, mut msg_id: uint32 || (*mimefactory.msg).type_0 == 50i32 || (*mimefactory.msg).type_0 == 60i32 { - let mut pathNfilename: *mut libc::c_char = dc_param_get( + let mut pathNfilename = dc_param_get( (*mimefactory.msg).param, 'f' as i32, 0 as *const libc::c_char, @@ -1382,7 +1396,6 @@ pub unsafe fn dc_job_send_msg(mut context: *mut dc_context_t, mut msg_id: uint32 dc_strdup(mimefactory.from_addr) as *mut libc::c_void, ); } - dc_sqlite3_begin_transaction((*context).sql); if 0 != mimefactory.out_gossiped { dc_set_gossiped_timestamp( context, @@ -1417,7 +1430,6 @@ pub unsafe fn dc_job_send_msg(mut context: *mut dc_context_t, mut msg_id: uint32 0 as *const libc::c_char, 0 as *const libc::c_char, ); - dc_sqlite3_commit((*context).sql); success = dc_add_smtp_job(context, 5901i32, &mut mimefactory) } } diff --git a/src/dc_jobthread.rs b/src/dc_jobthread.rs index 9182fc28a..6aafd4295 100644 --- a/src/dc_jobthread.rs +++ b/src/dc_jobthread.rs @@ -1,252 +1,265 @@ -use libc; +use std::sync::{Arc, Condvar, Mutex}; use crate::dc_configure::*; use crate::dc_context::dc_context_t; -use crate::dc_imap::dc_imap_t; -use crate::dc_imap::*; +use crate::dc_imap::Imap; use crate::dc_log::*; use crate::dc_sqlite3::*; use crate::dc_tools::*; use crate::types::*; use crate::x::*; -#[derive(Copy, Clone)] #[repr(C)] pub struct dc_jobthread_t { - pub context: *mut dc_context_t, pub name: *mut libc::c_char, pub folder_config_name: *mut libc::c_char, - pub imap: *mut dc_imap_t, - pub mutex: pthread_mutex_t, - pub idle_cond: pthread_cond_t, - pub idle_condflag: libc::c_int, - pub jobs_needed: libc::c_int, - pub suspended: libc::c_int, - pub using_handle: libc::c_int, + pub imap: Imap, + pub state: Arc<(Mutex, Condvar)>, } pub unsafe fn dc_jobthread_init( - mut jobthread: *mut dc_jobthread_t, - mut context: *mut dc_context_t, - mut name: *const libc::c_char, - mut folder_config_name: *const libc::c_char, + name: *const libc::c_char, + folder_config_name: *const libc::c_char, + imap: Imap, +) -> dc_jobthread_t { + dc_jobthread_t { + name: dc_strdup(name), + folder_config_name: dc_strdup(folder_config_name), + imap, + state: Arc::new((Mutex::new(Default::default()), Condvar::new())), + } +} + +#[derive(Debug, Default)] +pub struct JobState { + idle: bool, + jobs_needed: i32, + suspended: i32, + using_handle: i32, +} + +pub unsafe fn dc_jobthread_exit(jobthread: &mut dc_jobthread_t) { + free(jobthread.name as *mut libc::c_void); + jobthread.name = 0 as *mut libc::c_char; + free(jobthread.folder_config_name as *mut libc::c_void); + jobthread.folder_config_name = 0 as *mut libc::c_char; +} + +pub unsafe fn dc_jobthread_suspend( + context: &dc_context_t, + jobthread: &mut dc_jobthread_t, + suspend: libc::c_int, ) { - if jobthread.is_null() || context.is_null() || name.is_null() { - return; - } - (*jobthread).context = context; - (*jobthread).name = dc_strdup(name); - (*jobthread).folder_config_name = dc_strdup(folder_config_name); - (*jobthread).imap = 0 as *mut dc_imap_t; - pthread_mutex_init(&mut (*jobthread).mutex, 0 as *const pthread_mutexattr_t); - pthread_cond_init(&mut (*jobthread).idle_cond, 0 as *const pthread_condattr_t); - (*jobthread).idle_condflag = 0i32; - (*jobthread).jobs_needed = 0i32; - (*jobthread).suspended = 0i32; - (*jobthread).using_handle = 0i32; -} -pub unsafe fn dc_jobthread_exit(mut jobthread: *mut dc_jobthread_t) { - if jobthread.is_null() { - return; - } - pthread_cond_destroy(&mut (*jobthread).idle_cond); - pthread_mutex_destroy(&mut (*jobthread).mutex); - free((*jobthread).name as *mut libc::c_void); - (*jobthread).name = 0 as *mut libc::c_char; - free((*jobthread).folder_config_name as *mut libc::c_void); - (*jobthread).folder_config_name = 0 as *mut libc::c_char; -} -pub unsafe fn dc_jobthread_suspend(mut jobthread: *mut dc_jobthread_t, mut suspend: libc::c_int) { - if jobthread.is_null() { - return; - } if 0 != suspend { dc_log_info( - (*jobthread).context, + context, 0i32, b"Suspending %s-thread.\x00" as *const u8 as *const libc::c_char, - (*jobthread).name, + jobthread.name, ); - pthread_mutex_lock(&mut (*jobthread).mutex); - (*jobthread).suspended = 1i32; - pthread_mutex_unlock(&mut (*jobthread).mutex); - dc_jobthread_interrupt_idle(jobthread); + + { + jobthread.state.clone().0.lock().unwrap().suspended = 1; + } + dc_jobthread_interrupt_idle(context, jobthread); loop { - pthread_mutex_lock(&mut (*jobthread).mutex); - if (*jobthread).using_handle == 0i32 { - pthread_mutex_unlock(&mut (*jobthread).mutex); + let using_handle = jobthread.state.clone().0.lock().unwrap().using_handle; + if using_handle == 0 { return; } - pthread_mutex_unlock(&mut (*jobthread).mutex); usleep((300i32 * 1000i32) as useconds_t); } } else { dc_log_info( - (*jobthread).context, + context, 0i32, b"Unsuspending %s-thread.\x00" as *const u8 as *const libc::c_char, - (*jobthread).name, + jobthread.name, ); - pthread_mutex_lock(&mut (*jobthread).mutex); - (*jobthread).suspended = 0i32; - (*jobthread).idle_condflag = 1i32; - pthread_cond_signal(&mut (*jobthread).idle_cond); - pthread_mutex_unlock(&mut (*jobthread).mutex); - }; -} -pub unsafe extern "C" fn dc_jobthread_interrupt_idle(mut jobthread: *mut dc_jobthread_t) { - if jobthread.is_null() { - return; + + let &(ref lock, ref cvar) = &*jobthread.state.clone(); + let mut state = lock.lock().unwrap(); + + state.suspended = 0; + state.idle = true; + cvar.notify_one(); } - pthread_mutex_lock(&mut (*jobthread).mutex); - (*jobthread).jobs_needed = 1i32; - pthread_mutex_unlock(&mut (*jobthread).mutex); +} + +pub unsafe extern "C" fn dc_jobthread_interrupt_idle( + context: &dc_context_t, + jobthread: &mut dc_jobthread_t, +) { + { + jobthread.state.clone().0.lock().unwrap().jobs_needed = 1; + } + dc_log_info( - (*jobthread).context, - 0i32, + context, + 0, b"Interrupting %s-IDLE...\x00" as *const u8 as *const libc::c_char, - (*jobthread).name, + jobthread.name, ); - if !(*jobthread).imap.is_null() { - dc_imap_interrupt_idle((*jobthread).imap); - } - pthread_mutex_lock(&mut (*jobthread).mutex); - (*jobthread).idle_condflag = 1i32; - pthread_cond_signal(&mut (*jobthread).idle_cond); - pthread_mutex_unlock(&mut (*jobthread).mutex); + + println!("jobthread interrupt, waiting for lock"); + jobthread.imap.interrupt_idle(); + + let &(ref lock, ref cvar) = &*jobthread.state.clone(); + let mut state = lock.lock().unwrap(); + + state.idle = true; + cvar.notify_one(); } -pub unsafe fn dc_jobthread_fetch(mut jobthread: *mut dc_jobthread_t, mut use_network: libc::c_int) { - let mut start: libc::clock_t = 0; - if jobthread.is_null() { - return; + +pub unsafe fn dc_jobthread_fetch( + context: &dc_context_t, + jobthread: &mut dc_jobthread_t, + use_network: libc::c_int, +) { + let mut start; + + { + let &(ref lock, _) = &*jobthread.state.clone(); + let mut state = lock.lock().unwrap(); + + if 0 != state.suspended { + return; + } + + state.using_handle = 1; } - pthread_mutex_lock(&mut (*jobthread).mutex); - if 0 != (*jobthread).suspended { - pthread_mutex_unlock(&mut (*jobthread).mutex); - return; - } - (*jobthread).using_handle = 1i32; - pthread_mutex_unlock(&mut (*jobthread).mutex); - if !(0 == use_network || (*jobthread).imap.is_null()) { + + if !0 == use_network { start = clock(); - if !(0 == connect_to_imap(jobthread)) { + if !(0 == connect_to_imap(context, jobthread)) { dc_log_info( - (*jobthread).context, - 0i32, + context, + 0, b"%s-fetch started...\x00" as *const u8 as *const libc::c_char, - (*jobthread).name, + jobthread.name, ); - dc_imap_fetch((*jobthread).imap); - if 0 != (*(*jobthread).imap).should_reconnect { + jobthread.imap.fetch(context); + + if jobthread.imap.should_reconnect() { dc_log_info( - (*jobthread).context, + context, 0i32, b"%s-fetch aborted, starting over...\x00" as *const u8 as *const libc::c_char, - (*jobthread).name, + jobthread.name, ); - dc_imap_fetch((*jobthread).imap); + jobthread.imap.fetch(context); } dc_log_info( - (*jobthread).context, - 0i32, + context, + 0, b"%s-fetch done in %.0f ms.\x00" as *const u8 as *const libc::c_char, - (*jobthread).name, + jobthread.name, clock().wrapping_sub(start) as libc::c_double * 1000.0f64 / 1000000i32 as libc::c_double, ); } } - pthread_mutex_lock(&mut (*jobthread).mutex); - (*jobthread).using_handle = 0i32; - pthread_mutex_unlock(&mut (*jobthread).mutex); + + jobthread.state.clone().0.lock().unwrap().using_handle = 0; } + /* ****************************************************************************** * the typical fetch, idle, interrupt-idle ******************************************************************************/ -unsafe fn connect_to_imap(mut jobthread: *mut dc_jobthread_t) -> libc::c_int { - let mut ret_connected: libc::c_int = 0i32; + +unsafe fn connect_to_imap(context: &dc_context_t, jobthread: &mut dc_jobthread_t) -> libc::c_int { + let mut ret_connected: libc::c_int; let mut mvbox_name: *mut libc::c_char = 0 as *mut libc::c_char; - if 0 != dc_imap_is_connected((*jobthread).imap) { - ret_connected = 1i32 + + if jobthread.imap.is_connected() { + ret_connected = 1 } else { - ret_connected = dc_connect_to_configured_imap((*jobthread).context, (*jobthread).imap); + ret_connected = dc_connect_to_configured_imap(context, &jobthread.imap); if !(0 == ret_connected) { if dc_sqlite3_get_config_int( - (*(*jobthread).context).sql, + context, + &context.sql.clone().read().unwrap(), b"folders_configured\x00" as *const u8 as *const libc::c_char, - 0i32, - ) < 3i32 + 0, + ) < 3 { - dc_configure_folders((*jobthread).context, (*jobthread).imap, 0x1i32); + jobthread.imap.configure_folders(context, 0x1); } mvbox_name = dc_sqlite3_get_config( - (*(*jobthread).context).sql, - (*jobthread).folder_config_name, + context, + &context.sql.clone().read().unwrap(), + jobthread.folder_config_name, 0 as *const libc::c_char, ); if mvbox_name.is_null() { - dc_imap_disconnect((*jobthread).imap); - ret_connected = 0i32 + jobthread.imap.disconnect(context); + ret_connected = 0; } else { - dc_imap_set_watch_folder((*jobthread).imap, mvbox_name); + jobthread.imap.set_watch_folder(mvbox_name); } } } free(mvbox_name as *mut libc::c_void); - return ret_connected; + + ret_connected } -pub unsafe fn dc_jobthread_idle(mut jobthread: *mut dc_jobthread_t, mut use_network: libc::c_int) { - if jobthread.is_null() { - return; - } - pthread_mutex_lock(&mut (*jobthread).mutex); - if 0 != (*jobthread).jobs_needed { - dc_log_info( - (*jobthread).context, - 0i32, - b"%s-IDLE will not be started as it was interrupted while not ideling.\x00" as *const u8 - as *const libc::c_char, - (*jobthread).name, - ); - (*jobthread).jobs_needed = 0i32; - pthread_mutex_unlock(&mut (*jobthread).mutex); - return; - } - if 0 != (*jobthread).suspended { - while (*jobthread).idle_condflag == 0i32 { - pthread_cond_wait(&mut (*jobthread).idle_cond, &mut (*jobthread).mutex); + +pub unsafe fn dc_jobthread_idle( + context: &dc_context_t, + jobthread: &mut dc_jobthread_t, + use_network: libc::c_int, +) { + { + let &(ref lock, ref cvar) = &*jobthread.state.clone(); + let mut state = lock.lock().unwrap(); + + if 0 != state.jobs_needed { + dc_log_info( + context, + 0, + b"%s-IDLE will not be started as it was interrupted while not ideling.\x00" + as *const u8 as *const libc::c_char, + jobthread.name, + ); + state.jobs_needed = 0; + return; } - (*jobthread).idle_condflag = 0i32; - pthread_mutex_unlock(&mut (*jobthread).mutex); - return; - } - (*jobthread).using_handle = 1i32; - pthread_mutex_unlock(&mut (*jobthread).mutex); - if 0 == use_network || (*jobthread).imap.is_null() { - pthread_mutex_lock(&mut (*jobthread).mutex); - (*jobthread).using_handle = 0i32; - while (*jobthread).idle_condflag == 0i32 { - pthread_cond_wait(&mut (*jobthread).idle_cond, &mut (*jobthread).mutex); + + if 0 != state.suspended { + while !state.idle { + state = cvar.wait(state).unwrap(); + } + state.idle = false; + return; + } + + state.using_handle = 1; + + if 0 == use_network { + state.using_handle = 0; + + while !state.idle { + state = cvar.wait(state).unwrap(); + } + state.idle = false; + return; } - (*jobthread).idle_condflag = 0i32; - pthread_mutex_unlock(&mut (*jobthread).mutex); - return; } - connect_to_imap(jobthread); + + connect_to_imap(context, jobthread); dc_log_info( - (*jobthread).context, + context, 0i32, b"%s-IDLE started...\x00" as *const u8 as *const libc::c_char, - (*jobthread).name, + jobthread.name, ); - dc_imap_idle((*jobthread).imap); + jobthread.imap.idle(context); dc_log_info( - (*jobthread).context, + context, 0i32, b"%s-IDLE ended.\x00" as *const u8 as *const libc::c_char, - (*jobthread).name, + jobthread.name, ); - pthread_mutex_lock(&mut (*jobthread).mutex); - (*jobthread).using_handle = 0i32; - pthread_mutex_unlock(&mut (*jobthread).mutex); + + jobthread.state.clone().0.lock().unwrap().using_handle = 0; } diff --git a/src/dc_jsmn.rs b/src/dc_jsmn.rs index cd5d8267b..4db16f99c 100644 --- a/src/dc_jsmn.rs +++ b/src/dc_jsmn.rs @@ -1,5 +1,3 @@ -use libc; - use crate::types::*; /* @@ -68,6 +66,7 @@ pub struct jsmn_parser { pub toknext: libc::c_uint, pub toksuper: libc::c_int, } + /* * * Create JSON parser over an array of tokens */ @@ -76,6 +75,7 @@ pub unsafe fn jsmn_init(mut parser: *mut jsmn_parser) { (*parser).toknext = 0i32 as libc::c_uint; (*parser).toksuper = -1i32; } + /* * * Run JSON parser. It parses a JSON data string into and array of tokens, each describing * a single JSON object. @@ -87,15 +87,15 @@ pub unsafe fn jsmn_parse( mut tokens: *mut jsmntok_t, mut num_tokens: libc::c_uint, ) -> libc::c_int { - let mut r: libc::c_int = 0; - let mut i: libc::c_int = 0; - let mut token: *mut jsmntok_t = 0 as *mut jsmntok_t; + let mut r: libc::c_int; + let mut i: libc::c_int; + let mut token: *mut jsmntok_t; let mut count: libc::c_int = (*parser).toknext as libc::c_int; while (*parser).pos < len as libc::c_uint && *js.offset((*parser).pos as isize) as libc::c_int != '\u{0}' as i32 { - let mut c: libc::c_char = 0; - let mut type_0: jsmntype_t = JSMN_UNDEFINED; + let mut c: libc::c_char; + let mut type_0: jsmntype_t; c = *js.offset((*parser).pos as isize); match c as libc::c_int { 123 | 91 => { @@ -222,8 +222,10 @@ pub unsafe fn jsmn_parse( i -= 1 } } - return count; + + count } + /* * * Fills next available token with JSON primitive. */ @@ -234,8 +236,8 @@ unsafe fn jsmn_parse_primitive( mut tokens: *mut jsmntok_t, mut num_tokens: size_t, ) -> libc::c_int { - let mut token: *mut jsmntok_t = 0 as *mut jsmntok_t; - let mut start: libc::c_int = 0; + let mut token: *mut jsmntok_t; + let mut start: libc::c_int; start = (*parser).pos as libc::c_int; while (*parser).pos < len as libc::c_uint && *js.offset((*parser).pos as isize) as libc::c_int != '\u{0}' as i32 @@ -265,8 +267,10 @@ unsafe fn jsmn_parse_primitive( } jsmn_fill_token(token, JSMN_PRIMITIVE, start, (*parser).pos as libc::c_int); (*parser).pos = (*parser).pos.wrapping_sub(1); - return 0i32; + + 0 } + /* * * Fills token type and boundaries. */ @@ -281,6 +285,7 @@ unsafe fn jsmn_fill_token( (*token).end = end; (*token).size = 0i32; } + /* Copyright (c) 2010 Serge A. Zaitsev @@ -302,6 +307,7 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + /* * * Allocates a fresh unused token from the token pool. */ @@ -310,7 +316,7 @@ unsafe fn jsmn_alloc_token( mut tokens: *mut jsmntok_t, mut num_tokens: size_t, ) -> *mut jsmntok_t { - let mut tok: *mut jsmntok_t = 0 as *mut jsmntok_t; + let mut tok: *mut jsmntok_t; if (*parser).toknext as size_t >= num_tokens { return 0 as *mut jsmntok_t; } @@ -320,8 +326,10 @@ unsafe fn jsmn_alloc_token( (*tok).end = -1i32; (*tok).start = (*tok).end; (*tok).size = 0i32; - return tok; + + tok } + /* * * Fills next token with JSON string. */ @@ -332,7 +340,7 @@ unsafe fn jsmn_parse_string( mut tokens: *mut jsmntok_t, mut num_tokens: size_t, ) -> libc::c_int { - let mut token: *mut jsmntok_t = 0 as *mut jsmntok_t; + let mut token: *mut jsmntok_t; let mut start: libc::c_int = (*parser).pos as libc::c_int; (*parser).pos = (*parser).pos.wrapping_add(1); while ((*parser).pos as size_t) < len @@ -357,7 +365,7 @@ unsafe fn jsmn_parse_string( return 0i32; } if c as libc::c_int == '\\' as i32 && ((*parser).pos.wrapping_add(1) as size_t) < len { - let mut i: libc::c_int = 0; + let mut i: libc::c_int; (*parser).pos = (*parser).pos.wrapping_add(1); match *js.offset((*parser).pos as isize) as libc::c_int { 34 | 47 | 92 | 98 | 102 | 114 | 110 | 116 => {} @@ -392,5 +400,6 @@ unsafe fn jsmn_parse_string( (*parser).pos = (*parser).pos.wrapping_add(1) } (*parser).pos = start as libc::c_uint; - return JSMN_ERROR_PART as libc::c_int; + + JSMN_ERROR_PART as libc::c_int } diff --git a/src/dc_key.rs b/src/dc_key.rs index 89923a3d9..f7b0a6884 100644 --- a/src/dc_key.rs +++ b/src/dc_key.rs @@ -1,4 +1,15 @@ +use mmime::mailmime_content::*; +use mmime::mmapstring::*; +use mmime::other::*; + +use std::collections::BTreeMap; +use std::ffi::CString; +use std::io::Cursor; +use std::slice; + use libc; +use pgp::composed::{Deserializable, SignedPublicKey, SignedSecretKey}; +use pgp::ser::Serialize; use crate::dc_context::dc_context_t; use crate::dc_log::*; @@ -8,9 +19,7 @@ use crate::dc_strbuilder::*; use crate::dc_tools::*; use crate::types::*; use crate::x::*; -/* * - * Library-internal. - */ + #[derive(Copy, Clone)] #[repr(C)] pub struct dc_key_t { @@ -26,21 +35,25 @@ pub unsafe fn toupper(mut _c: libc::c_int) -> libc::c_int { } pub unsafe fn dc_key_new() -> *mut dc_key_t { - let mut key: *mut dc_key_t = 0 as *mut dc_key_t; + let mut key: *mut dc_key_t; key = calloc(1, ::std::mem::size_of::()) as *mut dc_key_t; if key.is_null() { exit(44i32); } (*key)._m_heap_refcnt = 1i32; - return key; + + key } + pub unsafe fn dc_key_ref(mut key: *mut dc_key_t) -> *mut dc_key_t { if key.is_null() { return 0 as *mut dc_key_t; } (*key)._m_heap_refcnt += 1; - return key; + + key } + pub unsafe fn dc_key_unref(mut key: *mut dc_key_t) { if key.is_null() { return; @@ -52,6 +65,7 @@ pub unsafe fn dc_key_unref(mut key: *mut dc_key_t) { dc_key_empty(key); free(key as *mut libc::c_void); } + unsafe fn dc_key_empty(mut key: *mut dc_key_t) { if key.is_null() { return; @@ -64,12 +78,15 @@ unsafe fn dc_key_empty(mut key: *mut dc_key_t) { (*key).bytes = 0i32; (*key).type_0 = 0i32; } + pub unsafe fn dc_wipe_secret_mem(mut buf: *mut libc::c_void, mut buf_bytes: size_t) { if buf.is_null() || buf_bytes <= 0 { return; } memset(buf, 0i32, buf_bytes); } + +// TODO should return bool /rtn pub unsafe fn dc_key_set_from_binary( mut key: *mut dc_key_t, mut data: *const libc::c_void, @@ -87,15 +104,20 @@ pub unsafe fn dc_key_set_from_binary( memcpy((*key).binary, data, bytes as size_t); (*key).bytes = bytes; (*key).type_0 = type_0; - return 1i32; + + 1 } + pub unsafe fn dc_key_set_from_key(mut key: *mut dc_key_t, mut o: *const dc_key_t) -> libc::c_int { dc_key_empty(key); if key.is_null() || o.is_null() { return 0i32; } - return dc_key_set_from_binary(key, (*o).binary, (*o).bytes, (*o).type_0); + + dc_key_set_from_binary(key, (*o).binary, (*o).bytes, (*o).type_0) } + +// TODO should return bool /rtn pub unsafe extern "C" fn dc_key_set_from_stmt( mut key: *mut dc_key_t, mut stmt: *mut sqlite3_stmt, @@ -106,13 +128,16 @@ pub unsafe extern "C" fn dc_key_set_from_stmt( if key.is_null() || stmt.is_null() { return 0i32; } - return dc_key_set_from_binary( + + dc_key_set_from_binary( key, sqlite3_column_blob(stmt, index) as *mut libc::c_uchar as *const libc::c_void, sqlite3_column_bytes(stmt, index), type_0, - ); + ) } + +// TODO should return bool /rtn pub unsafe fn dc_key_set_from_base64( mut key: *mut dc_key_t, mut base64: *const libc::c_char, @@ -144,90 +169,11 @@ pub unsafe fn dc_key_set_from_base64( type_0, ); mmap_string_unref(result); - return 1i32; -} -pub unsafe fn dc_key_set_from_file( - mut key: *mut dc_key_t, - mut pathNfilename: *const libc::c_char, - mut context: *mut dc_context_t, -) -> libc::c_int { - let mut current_block: u64; - let mut buf: *mut libc::c_char = 0 as *mut libc::c_char; - // just pointer inside buf, must not be freed - let mut headerline: *const libc::c_char = 0 as *const libc::c_char; - // - " - - let mut base64: *const libc::c_char = 0 as *const libc::c_char; - let mut buf_bytes: size_t = 0i32 as size_t; - let mut type_0: libc::c_int = -1i32; - let mut success: libc::c_int = 0i32; - dc_key_empty(key); - if !(key.is_null() || pathNfilename.is_null()) { - if !(0 - == dc_read_file( - context, - pathNfilename, - &mut buf as *mut *mut libc::c_char as *mut *mut libc::c_void, - &mut buf_bytes, - ) - || buf_bytes < 50) - { - /* error is already loged */ - if !(0 - == dc_split_armored_data( - buf, - &mut headerline, - 0 as *mut *const libc::c_char, - 0 as *mut *const libc::c_char, - &mut base64, - ) - || headerline.is_null() - || base64.is_null()) - { - if strcmp( - headerline, - b"-----BEGIN PGP PUBLIC KEY BLOCK-----\x00" as *const u8 as *const libc::c_char, - ) == 0i32 - { - type_0 = 0i32; - current_block = 7149356873433890176; - } else if strcmp( - headerline, - b"-----BEGIN PGP PRIVATE KEY BLOCK-----\x00" as *const u8 - as *const libc::c_char, - ) == 0i32 - { - type_0 = 1i32; - current_block = 7149356873433890176; - } else { - dc_log_warning( - context, - 0i32, - b"Header missing for key \"%s\".\x00" as *const u8 as *const libc::c_char, - pathNfilename, - ); - current_block = 7704194852291245876; - } - match current_block { - 7704194852291245876 => {} - _ => { - if 0 == dc_key_set_from_base64(key, base64, type_0) { - dc_log_warning( - context, - 0i32, - b"Bad data in key \"%s\".\x00" as *const u8 as *const libc::c_char, - pathNfilename, - ); - } else { - success = 1i32 - } - } - } - } - } - } - free(buf as *mut libc::c_void); - return success; + + 1 } + +// TODO should return bool /rtn pub unsafe fn dc_key_equals(mut key: *const dc_key_t, mut o: *const dc_key_t) -> libc::c_int { if key.is_null() || o.is_null() @@ -251,25 +197,29 @@ pub unsafe fn dc_key_equals(mut key: *const dc_key_t, mut o: *const dc_key_t) -> 0 } } + +// TODO should return bool /rtn pub unsafe fn dc_key_save_self_keypair( - mut public_key: *const dc_key_t, - mut private_key: *const dc_key_t, - mut addr: *const libc::c_char, - mut is_default: libc::c_int, - mut sql: *mut dc_sqlite3_t, + context: &dc_context_t, + public_key: *const dc_key_t, + private_key: *const dc_key_t, + addr: *const libc::c_char, + is_default: libc::c_int, + sql: &dc_sqlite3_t, ) -> libc::c_int { let mut success: libc::c_int = 0i32; let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; if !(public_key.is_null() || private_key.is_null() || addr.is_null() - || sql.is_null() || (*public_key).binary.is_null() || (*private_key).binary.is_null()) { stmt = - dc_sqlite3_prepare(sql, - b"INSERT INTO keypairs (addr, is_default, public_key, private_key, created) VALUES (?,?,?,?,?);\x00" + dc_sqlite3_prepare( + context, + sql, + b"INSERT INTO keypairs (addr, is_default, public_key, private_key, created) VALUES (?,?,?,?,?);\x00" as *const u8 as *const libc::c_char); sqlite3_bind_text(stmt, 1i32, addr, -1i32, None); sqlite3_bind_int(stmt, 2i32, is_default); @@ -287,18 +237,23 @@ pub unsafe fn dc_key_save_self_keypair( } } sqlite3_finalize(stmt); - return success; + + success } + +// TODO should return bool /rtn pub unsafe fn dc_key_load_self_public( - mut key: *mut dc_key_t, - mut self_addr: *const libc::c_char, - mut sql: *mut dc_sqlite3_t, + context: &dc_context_t, + key: *mut dc_key_t, + self_addr: *const libc::c_char, + sql: &dc_sqlite3_t, ) -> libc::c_int { let mut success: libc::c_int = 0i32; let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; - if !(key.is_null() || self_addr.is_null() || sql.is_null()) { + if !(key.is_null() || self_addr.is_null()) { dc_key_empty(key); stmt = dc_sqlite3_prepare( + context, sql, b"SELECT public_key FROM keypairs WHERE addr=? AND is_default=1;\x00" as *const u8 as *const libc::c_char, @@ -310,18 +265,23 @@ pub unsafe fn dc_key_load_self_public( } } sqlite3_finalize(stmt); - return success; + + success } + +// TODO should return bool /rtn pub unsafe fn dc_key_load_self_private( - mut key: *mut dc_key_t, - mut self_addr: *const libc::c_char, - mut sql: *mut dc_sqlite3_t, + context: &dc_context_t, + key: *mut dc_key_t, + self_addr: *const libc::c_char, + sql: &dc_sqlite3_t, ) -> libc::c_int { let mut success: libc::c_int = 0i32; let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; - if !(key.is_null() || self_addr.is_null() || sql.is_null()) { + if !(key.is_null() || self_addr.is_null()) { dc_key_empty(key); stmt = dc_sqlite3_prepare( + context, sql, b"SELECT private_key FROM keypairs WHERE addr=? AND is_default=1;\x00" as *const u8 as *const libc::c_char, @@ -329,148 +289,98 @@ pub unsafe fn dc_key_load_self_private( sqlite3_bind_text(stmt, 1i32, self_addr, -1i32, None); if !(sqlite3_step(stmt) != 100i32) { dc_key_set_from_stmt(key, stmt, 0i32, 1i32); - success = 1i32 + success = 1i32; } } sqlite3_finalize(stmt); - return success; + + success } + /* the result must be freed */ -pub unsafe fn dc_render_base64( - mut buf: *const libc::c_void, - mut buf_bytes: size_t, - mut break_every: libc::c_int, - mut break_chars: *const libc::c_char, - mut add_checksum: libc::c_int, -) -> *mut libc::c_char { - let mut ret: *mut libc::c_char = 0 as *mut libc::c_char; - if !(buf == 0 as *mut libc::c_void || buf_bytes <= 0) { - ret = encode_base64(buf as *const libc::c_char, buf_bytes as libc::c_int); - if !ret.is_null() { - if break_every > 0i32 { - let mut temp: *mut libc::c_char = ret; - ret = dc_insert_breaks(temp, break_every, break_chars); - free(temp as *mut libc::c_void); - } - if add_checksum == 2i32 { - let mut checksum: libc::c_long = crc_octets(buf as *const libc::c_uchar, buf_bytes); - let mut c: [uint8_t; 3] = [0; 3]; - c[0usize] = (checksum >> 16i32 & 0xffi32 as libc::c_long) as uint8_t; - c[1usize] = (checksum >> 8i32 & 0xffi32 as libc::c_long) as uint8_t; - c[2usize] = (checksum & 0xffi32 as libc::c_long) as uint8_t; - let mut c64: *mut libc::c_char = - encode_base64(c.as_mut_ptr() as *const libc::c_char, 3i32); - let mut temp_0: *mut libc::c_char = ret; - ret = dc_mprintf( - b"%s%s=%s\x00" as *const u8 as *const libc::c_char, - temp_0, - break_chars, - c64, - ); - free(temp_0 as *mut libc::c_void); - free(c64 as *mut libc::c_void); - } - } - } - return ret; -} -/* ****************************************************************************** - * Render keys - ******************************************************************************/ -unsafe fn crc_octets(mut octets: *const libc::c_uchar, mut len: size_t) -> libc::c_long { - let mut crc: libc::c_long = 0xb704ce; - loop { - let fresh0 = len; - len = len.wrapping_sub(1); - if !(0 != fresh0) { - break; - } - let fresh1 = octets; - octets = octets.offset(1); - crc ^= ((*fresh1 as libc::c_int) << 16i32) as libc::c_long; - let mut i: libc::c_int = 0i32; - while i < 8i32 { - crc <<= 1i32; - if 0 != crc & 0x1000000 as libc::c_long { - crc ^= 0x1864cfb - } - i += 1 - } - } - return crc & 0xffffff; -} -/* the result must be freed */ -pub unsafe fn dc_key_render_base64( - mut key: *const dc_key_t, - mut break_every: libc::c_int, - mut break_chars: *const libc::c_char, - mut add_checksum: libc::c_int, -) -> *mut libc::c_char { +pub fn dc_key_render_base64(key: *const dc_key_t, break_every: usize) -> *mut libc::c_char { if key.is_null() { - return 0 as *mut libc::c_char; + return std::ptr::null_mut(); } - return dc_render_base64( - (*key).binary, - (*key).bytes as size_t, - break_every, - break_chars, - add_checksum, - ); + + let key = unsafe { *key }; + let bytes = unsafe { slice::from_raw_parts(key.binary as *const u8, key.bytes as usize) }; + assert_eq!(bytes.len(), key.bytes as usize); + + let buf = if key.type_0 == 0 { + // public key + let skey = SignedPublicKey::from_bytes(Cursor::new(bytes)).expect("invalid pub key"); + skey.to_bytes().expect("failed to serialize key") + } else { + // secret key + let skey = SignedSecretKey::from_bytes(Cursor::new(bytes)).expect("invalid sec key"); + skey.to_bytes().expect("failed to serialize key") + }; + + let encoded = base64::encode(&buf); + let res = encoded + .as_bytes() + .chunks(break_every) + .fold(String::new(), |mut res, buf| { + // safe because we are using a base64 encoded string + res += unsafe { std::str::from_utf8_unchecked(buf) }; + res += " "; + res + }); + + let res_c = CString::new(res.trim()).unwrap(); + + // need to use strdup to allocate the result with malloc + // so it can be `free`d later. + unsafe { libc::strdup(res_c.as_ptr()) } } -/* each header line must be terminated by \r\n, the result must be freed */ -pub unsafe fn dc_key_render_asc( - mut key: *const dc_key_t, - mut add_header_lines: *const libc::c_char, -) -> *mut libc::c_char { - /* see RFC 4880, 6.2. Forming ASCII Armor, https://tools.ietf.org/html/rfc4880#section-6.2 */ - let mut base64: *mut libc::c_char = 0 as *mut libc::c_char; - let mut ret: *mut libc::c_char = 0 as *mut libc::c_char; - if !key.is_null() { - base64 = dc_key_render_base64( - key, - 76i32, - b"\r\n\x00" as *const u8 as *const libc::c_char, - 2i32, - ); - if !base64.is_null() { - /*checksum in new line*/ - /* RFC: The encoded output stream must be represented in lines of no more than 76 characters each. */ - ret = - dc_mprintf(b"-----BEGIN PGP %s KEY BLOCK-----\r\n%s\r\n%s\r\n-----END PGP %s KEY BLOCK-----\r\n\x00" - as *const u8 as *const libc::c_char, - if (*key).type_0 == 0i32 { - b"PUBLIC\x00" as *const u8 as - *const libc::c_char - } else { - b"PRIVATE\x00" as *const u8 as - *const libc::c_char - }, - if !add_header_lines.is_null() { - add_header_lines - } else { - b"\x00" as *const u8 as *const libc::c_char - }, base64, - if (*key).type_0 == 0i32 { - b"PUBLIC\x00" as *const u8 as - *const libc::c_char - } else { - b"PRIVATE\x00" as *const u8 as - *const libc::c_char - }) - } + +/// each header line must be terminated by `\r\n`, the result must be freed. +pub fn dc_key_render_asc(key: *const dc_key_t, header: Option<(&str, &str)>) -> *mut libc::c_char { + if key.is_null() { + return std::ptr::null_mut(); } - free(base64 as *mut libc::c_void); - return ret; + + let key = unsafe { *key }; + + let headers = header.map(|(key, value)| { + let mut m = BTreeMap::new(); + m.insert(key.to_string(), value.to_string()); + m + }); + + let bytes = unsafe { slice::from_raw_parts(key.binary as *const u8, key.bytes as usize) }; + + let buf = if key.type_0 == 0 { + // public key + let skey = SignedPublicKey::from_bytes(Cursor::new(bytes)).expect("invalid key"); + skey.to_armored_string(headers.as_ref()) + .expect("failed to serialize key") + } else { + // secret key + let skey = SignedSecretKey::from_bytes(Cursor::new(bytes)).expect("invalid key"); + skey.to_armored_string(headers.as_ref()) + .expect("failed to serialize key") + }; + + let buf_c = CString::new(buf).unwrap(); + + // need to use strdup to allocate the result with malloc + // so it can be `free`d later. + unsafe { libc::strdup(buf_c.as_ptr()) } } + pub unsafe fn dc_key_render_asc_to_file( mut key: *const dc_key_t, mut file: *const libc::c_char, - mut context: *mut dc_context_t, + mut context: &dc_context_t, ) -> libc::c_int { let mut success: libc::c_int = 0i32; let mut file_content: *mut libc::c_char = 0 as *mut libc::c_char; - if !(key.is_null() || file.is_null() || context.is_null()) { - file_content = dc_key_render_asc(key, 0 as *const libc::c_char); + + if !(key.is_null() || file.is_null()) { + file_content = dc_key_render_asc(key, None); + if !file_content.is_null() { if 0 == dc_write_file( context, @@ -490,8 +400,10 @@ pub unsafe fn dc_key_render_asc_to_file( } } free(file_content as *mut libc::c_void); - return success; + + success } + pub unsafe fn dc_format_fingerprint(mut fingerprint: *const libc::c_char) -> *mut libc::c_char { let mut i: libc::c_int = 0i32; let mut fingerprint_len: libc::c_int = strlen(fingerprint) as libc::c_int; @@ -517,8 +429,10 @@ pub unsafe fn dc_format_fingerprint(mut fingerprint: *const libc::c_char) -> *mu } } } - return ret.buf; + + ret.buf } + pub unsafe fn dc_normalize_fingerprint(mut in_0: *const libc::c_char) -> *mut libc::c_char { if in_0.is_null() { return 0 as *mut libc::c_char; @@ -544,14 +458,21 @@ pub unsafe fn dc_normalize_fingerprint(mut in_0: *const libc::c_char) -> *mut li } p1 = p1.offset(1isize) } - return out.buf; + + out.buf } -pub unsafe fn dc_key_get_fingerprint(mut key: *const dc_key_t) -> *mut libc::c_char { + +pub unsafe fn dc_key_get_fingerprint( + context: &dc_context_t, + key: *const dc_key_t, +) -> *mut libc::c_char { let mut fingerprint_buf: *mut uint8_t = 0 as *mut uint8_t; let mut fingerprint_bytes: size_t = 0i32 as size_t; let mut fingerprint_hex: *mut libc::c_char = 0 as *mut libc::c_char; if !key.is_null() { - if !(0 == dc_pgp_calc_fingerprint(key, &mut fingerprint_buf, &mut fingerprint_bytes)) { + if !(0 + == dc_pgp_calc_fingerprint(context, key, &mut fingerprint_buf, &mut fingerprint_bytes)) + { fingerprint_hex = dc_binary_to_uc_hex(fingerprint_buf, fingerprint_bytes) } } @@ -562,9 +483,14 @@ pub unsafe fn dc_key_get_fingerprint(mut key: *const dc_key_t) -> *mut libc::c_c dc_strdup(0 as *const libc::c_char) }; } -pub unsafe fn dc_key_get_formatted_fingerprint(mut key: *const dc_key_t) -> *mut libc::c_char { - let mut rawhex: *mut libc::c_char = dc_key_get_fingerprint(key); + +pub unsafe fn dc_key_get_formatted_fingerprint( + context: &dc_context_t, + key: *const dc_key_t, +) -> *mut libc::c_char { + let mut rawhex: *mut libc::c_char = dc_key_get_fingerprint(context, key); let mut formatted: *mut libc::c_char = dc_format_fingerprint(rawhex); free(rawhex as *mut libc::c_void); - return formatted; + + formatted } diff --git a/src/dc_keyhistory.rs b/src/dc_keyhistory.rs index 5a7adbfd6..beb077042 100644 --- a/src/dc_keyhistory.rs +++ b/src/dc_keyhistory.rs @@ -1,12 +1,10 @@ -use libc; - use crate::dc_context::dc_context_t; use crate::types::*; /* yes: uppercase */ /* library private: key-history */ -pub unsafe fn dc_add_to_keyhistory( - _context: *mut dc_context_t, +pub fn dc_add_to_keyhistory( + _context: &dc_context_t, _rfc724_mid: *const libc::c_char, _sending_time: time_t, _addr: *const libc::c_char, diff --git a/src/dc_keyring.rs b/src/dc_keyring.rs index 3abec44b9..81bc280ab 100644 --- a/src/dc_keyring.rs +++ b/src/dc_keyring.rs @@ -1,5 +1,4 @@ -use libc; - +use crate::dc_context::dc_context_t; use crate::dc_key::*; use crate::dc_sqlite3::*; use crate::types::*; @@ -14,13 +13,15 @@ pub struct dc_keyring_t { } pub unsafe fn dc_keyring_new() -> *mut dc_keyring_t { - let mut keyring: *mut dc_keyring_t = 0 as *mut dc_keyring_t; + let mut keyring: *mut dc_keyring_t; keyring = calloc(1, ::std::mem::size_of::()) as *mut dc_keyring_t; if keyring.is_null() { exit(42i32); } - return keyring; + + keyring } + pub unsafe fn dc_keyring_unref(mut keyring: *mut dc_keyring_t) { if keyring.is_null() { return; @@ -33,6 +34,7 @@ pub unsafe fn dc_keyring_unref(mut keyring: *mut dc_keyring_t) { free((*keyring).keys as *mut libc::c_void); free(keyring as *mut libc::c_void); } + /* the reference counter of the key is increased by one */ pub unsafe fn dc_keyring_add(mut keyring: *mut dc_keyring_t, mut to_add: *mut dc_key_t) { if keyring.is_null() || to_add.is_null() { @@ -53,15 +55,20 @@ pub unsafe fn dc_keyring_add(mut keyring: *mut dc_keyring_t, mut to_add: *mut dc *fresh0 = dc_key_ref(to_add); (*keyring).count += 1; } + +// TODO should return bool? /rtn pub unsafe fn dc_keyring_load_self_private_for_decrypting( - mut keyring: *mut dc_keyring_t, - mut self_addr: *const libc::c_char, - mut sql: *mut dc_sqlite3_t, + context: &dc_context_t, + keyring: *mut dc_keyring_t, + self_addr: *const libc::c_char, + sql: &dc_sqlite3_t, ) -> libc::c_int { - if keyring.is_null() || self_addr.is_null() || sql.is_null() { + // Can we prevent keyring and self_addr to be null? + if keyring.is_null() || self_addr.is_null() { return 0i32; } let mut stmt: *mut sqlite3_stmt = dc_sqlite3_prepare( + context, sql, b"SELECT private_key FROM keypairs ORDER BY addr=? DESC, is_default DESC;\x00" as *const u8 as *const libc::c_char, @@ -75,5 +82,6 @@ pub unsafe fn dc_keyring_load_self_private_for_decrypting( dc_key_unref(key); } sqlite3_finalize(stmt); - return 1i32; + + 1 } diff --git a/src/dc_location.rs b/src/dc_location.rs index b3e1a56c1..8e5d820a4 100644 --- a/src/dc_location.rs +++ b/src/dc_location.rs @@ -1,5 +1,3 @@ -use libc; - use crate::constants::Event; use crate::dc_array::*; use crate::dc_chat::*; @@ -42,7 +40,7 @@ pub struct dc_kml_t { // location streaming pub unsafe fn dc_send_locations_to_chat( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut chat_id: uint32_t, mut seconds: libc::c_int, ) { @@ -50,17 +48,15 @@ pub unsafe fn dc_send_locations_to_chat( let mut now: time_t = time(0 as *mut time_t); let mut msg: *mut dc_msg_t = 0 as *mut dc_msg_t; let mut stock_str: *mut libc::c_char = 0 as *mut libc::c_char; - let mut is_sending_locations_before: libc::c_int = 0i32; - if !(context.is_null() - || (*context).magic != 0x11a11807i32 as libc::c_uint - || seconds < 0i32 - || chat_id <= 9i32 as libc::c_uint) - { + let mut is_sending_locations_before: libc::c_int; + if !(seconds < 0i32 || chat_id <= 9i32 as libc::c_uint) { is_sending_locations_before = dc_is_sending_locations_to_chat(context, chat_id); stmt = - dc_sqlite3_prepare((*context).sql, - b"UPDATE chats SET locations_send_begin=?, locations_send_until=? WHERE id=?\x00" - as *const u8 as *const libc::c_char); + dc_sqlite3_prepare( + context, + &context.sql.clone().read().unwrap(), + b"UPDATE chats SET locations_send_begin=?, locations_send_until=? WHERE id=?\x00" + as *const u8 as *const libc::c_char); sqlite3_bind_int64( stmt, 1i32, @@ -102,7 +98,7 @@ pub unsafe fn dc_send_locations_to_chat( ); dc_add_device_msg(context, chat_id, stock_str); } - ((*context).cb)( + (context.cb)( context, Event::CHAT_MODIFIED, chat_id as uintptr_t, @@ -123,46 +119,51 @@ pub unsafe fn dc_send_locations_to_chat( dc_msg_unref(msg); sqlite3_finalize(stmt); } -/* ****************************************************************************** + +/******************************************************************************* * job to send locations out to all chats that want them ******************************************************************************/ -unsafe fn schedule_MAYBE_SEND_LOCATIONS(mut context: *mut dc_context_t, mut flags: libc::c_int) { +unsafe fn schedule_MAYBE_SEND_LOCATIONS(mut context: &dc_context_t, mut flags: libc::c_int) { if 0 != flags & 0x1i32 || 0 == dc_job_action_exists(context, 5005i32) { dc_job_add(context, 5005i32, 0i32, 0 as *const libc::c_char, 60i32); }; } + pub unsafe extern "C" fn dc_is_sending_locations_to_chat( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut chat_id: uint32_t, ) -> libc::c_int { let mut is_sending_locations: libc::c_int = 0i32; - let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; - if !(context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint) { - stmt = dc_sqlite3_prepare( - (*context).sql, - b"SELECT id FROM chats WHERE (? OR id=?) AND locations_send_until>?;\x00" - as *const u8 as *const libc::c_char, - ); - sqlite3_bind_int( - stmt, - 1i32, - if chat_id == 0i32 as libc::c_uint { - 1i32 - } else { - 0i32 - }, - ); - sqlite3_bind_int(stmt, 2i32, chat_id as libc::c_int); - sqlite3_bind_int64(stmt, 3i32, time(0 as *mut time_t) as sqlite3_int64); - if !(sqlite3_step(stmt) != 100i32) { - is_sending_locations = 1i32 - } + let mut stmt: *mut sqlite3_stmt; + + stmt = dc_sqlite3_prepare( + context, + &context.sql.clone().read().unwrap(), + b"SELECT id FROM chats WHERE (? OR id=?) AND locations_send_until>?;\x00" as *const u8 + as *const libc::c_char, + ); + sqlite3_bind_int( + stmt, + 1i32, + if chat_id == 0i32 as libc::c_uint { + 1i32 + } else { + 0i32 + }, + ); + sqlite3_bind_int(stmt, 2i32, chat_id as libc::c_int); + sqlite3_bind_int64(stmt, 3i32, time(0 as *mut time_t) as sqlite3_int64); + if !(sqlite3_step(stmt) != 100i32) { + is_sending_locations = 1i32 } + sqlite3_finalize(stmt); - return is_sending_locations; + + is_sending_locations } + pub unsafe fn dc_set_location( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut latitude: libc::c_double, mut longitude: libc::c_double, mut accuracy: libc::c_double, @@ -170,14 +171,12 @@ pub unsafe fn dc_set_location( let mut stmt_chats: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; let mut stmt_insert: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; let mut continue_streaming: libc::c_int = 0i32; - if context.is_null() - || (*context).magic != 0x11a11807i32 as libc::c_uint - || latitude == 0.0f64 && longitude == 0.0f64 - { + if latitude == 0.0f64 && longitude == 0.0f64 { continue_streaming = 1i32 } else { stmt_chats = dc_sqlite3_prepare( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"SELECT id FROM chats WHERE locations_send_until>?;\x00" as *const u8 as *const libc::c_char, ); @@ -185,9 +184,11 @@ pub unsafe fn dc_set_location( while sqlite3_step(stmt_chats) == 100i32 { let mut chat_id: uint32_t = sqlite3_column_int(stmt_chats, 0i32) as uint32_t; stmt_insert = - dc_sqlite3_prepare((*context).sql, - b"INSERT INTO locations (latitude, longitude, accuracy, timestamp, chat_id, from_id) VALUES (?,?,?,?,?,?);\x00" - as *const u8 as *const libc::c_char); + dc_sqlite3_prepare( + context, + &context.sql.clone().read().unwrap(), + b"INSERT INTO locations (latitude, longitude, accuracy, timestamp, chat_id, from_id) VALUES (?,?,?,?,?,?);\x00" + as *const u8 as *const libc::c_char); sqlite3_bind_double(stmt_insert, 1i32, latitude); sqlite3_bind_double(stmt_insert, 2i32, longitude); sqlite3_bind_double(stmt_insert, 3i32, accuracy); @@ -198,7 +199,7 @@ pub unsafe fn dc_set_location( continue_streaming = 1i32 } if 0 != continue_streaming { - ((*context).cb)( + (context.cb)( context, Event::LOCATION_CHANGED, 1i32 as uintptr_t, @@ -209,82 +210,88 @@ pub unsafe fn dc_set_location( } sqlite3_finalize(stmt_chats); sqlite3_finalize(stmt_insert); - return continue_streaming; + + continue_streaming } + pub unsafe fn dc_get_locations( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut chat_id: uint32_t, mut contact_id: uint32_t, mut timestamp_from: time_t, mut timestamp_to: time_t, ) -> *mut dc_array_t { - let mut ret: *mut dc_array_t = dc_array_new_typed(context, 1i32, 500i32 as size_t); - let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; - if !(context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint) { - if timestamp_to == 0i32 as libc::c_long { - timestamp_to = time(0 as *mut time_t) + 10i32 as libc::c_long - } - stmt = dc_sqlite3_prepare( - (*context).sql, - b"SELECT l.id, l.latitude, l.longitude, l.accuracy, l.timestamp, l.independent \ + let mut ret: *mut dc_array_t = dc_array_new_typed(1i32, 500i32 as size_t); + let mut stmt: *mut sqlite3_stmt; + + if timestamp_to == 0i32 as libc::c_long { + timestamp_to = time(0 as *mut time_t) + 10i32 as libc::c_long + } + stmt = dc_sqlite3_prepare( + context, + &context.sql.clone().read().unwrap(), + b"SELECT l.id, l.latitude, l.longitude, l.accuracy, l.timestamp, l.independent \ m.id, l.from_id, l.chat_id, m.txt \ FROM locations l LEFT JOIN msgs m ON l.id=m.location_id WHERE (? OR l.chat_id=?) \ AND (? OR l.from_id=?) \ AND (l.independent=1 OR (l.timestamp>=? AND l.timestamp<=?)) \ ORDER BY l.timestamp DESC, l.id DESC, m.id DESC;\x00" as *const u8 - as *const libc::c_char, - ); - sqlite3_bind_int( - stmt, - 1i32, - if chat_id == 0i32 as libc::c_uint { - 1i32 - } else { - 0i32 - }, - ); - sqlite3_bind_int(stmt, 2i32, chat_id as libc::c_int); - sqlite3_bind_int( - stmt, - 3i32, - if contact_id == 0i32 as libc::c_uint { - 1i32 - } else { - 0i32 - }, - ); - sqlite3_bind_int(stmt, 4i32, contact_id as libc::c_int); - sqlite3_bind_int(stmt, 5i32, timestamp_from as libc::c_int); - sqlite3_bind_int(stmt, 6i32, timestamp_to as libc::c_int); - while sqlite3_step(stmt) == 100i32 { - let mut loc: *mut _dc_location = - calloc(1, ::std::mem::size_of::<_dc_location>()) as *mut _dc_location; - if loc.is_null() { - break; - } - (*loc).location_id = sqlite3_column_double(stmt, 0i32) as uint32_t; - (*loc).latitude = sqlite3_column_double(stmt, 1i32); - (*loc).longitude = sqlite3_column_double(stmt, 2i32); - (*loc).accuracy = sqlite3_column_double(stmt, 3i32); - (*loc).timestamp = sqlite3_column_int64(stmt, 4i32) as time_t; - (*loc).independent = sqlite3_column_int(stmt, 5i32) as uint32_t; - (*loc).msg_id = sqlite3_column_int(stmt, 6i32) as uint32_t; - (*loc).contact_id = sqlite3_column_int(stmt, 7i32) as uint32_t; - (*loc).chat_id = sqlite3_column_int(stmt, 8i32) as uint32_t; - - if 0 != (*loc).msg_id { - let mut txt: *const libc::c_char = - sqlite3_column_text(stmt, 9i32) as *const libc::c_char; - if 0 != is_marker(txt) { - (*loc).marker = strdup(txt) - } - } - dc_array_add_ptr(ret, loc as *mut libc::c_void); + as *const libc::c_char, + ); + sqlite3_bind_int( + stmt, + 1i32, + if chat_id == 0i32 as libc::c_uint { + 1i32 + } else { + 0i32 + }, + ); + sqlite3_bind_int(stmt, 2i32, chat_id as libc::c_int); + sqlite3_bind_int( + stmt, + 3i32, + if contact_id == 0i32 as libc::c_uint { + 1i32 + } else { + 0i32 + }, + ); + sqlite3_bind_int(stmt, 4i32, contact_id as libc::c_int); + sqlite3_bind_int(stmt, 5i32, timestamp_from as libc::c_int); + sqlite3_bind_int(stmt, 6i32, timestamp_to as libc::c_int); + while sqlite3_step(stmt) == 100i32 { + let mut loc: *mut _dc_location = + calloc(1, ::std::mem::size_of::<_dc_location>()) as *mut _dc_location; + if loc.is_null() { + break; } + (*loc).location_id = sqlite3_column_double(stmt, 0i32) as uint32_t; + (*loc).latitude = sqlite3_column_double(stmt, 1i32); + (*loc).longitude = sqlite3_column_double(stmt, 2i32); + (*loc).accuracy = sqlite3_column_double(stmt, 3i32); + (*loc).timestamp = sqlite3_column_int64(stmt, 4i32) as time_t; + (*loc).independent = sqlite3_column_int(stmt, 5i32) as uint32_t; + (*loc).msg_id = sqlite3_column_int(stmt, 6i32) as uint32_t; + (*loc).contact_id = sqlite3_column_int(stmt, 7i32) as uint32_t; + (*loc).chat_id = sqlite3_column_int(stmt, 8i32) as uint32_t; + + if 0 != (*loc).msg_id { + let mut txt: *const libc::c_char = + sqlite3_column_text(stmt, 9i32) as *const libc::c_char; + if 0 != is_marker(txt) { + (*loc).marker = strdup(txt) + } + } + dc_array_add_ptr(ret, loc as *mut libc::c_void); } + sqlite3_finalize(stmt); - return ret; + + ret } + +// TODO should be bool /rtn unsafe fn is_marker(mut txt: *const libc::c_char) -> libc::c_int { if !txt.is_null() { let mut len: libc::c_int = dc_utf8_strlen(txt) as libc::c_int; @@ -292,37 +299,41 @@ unsafe fn is_marker(mut txt: *const libc::c_char) -> libc::c_int { return 1i32; } } - return 0i32; + + 0 } -pub unsafe fn dc_delete_all_locations(mut context: *mut dc_context_t) { - let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; - if !(context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint) { - stmt = dc_sqlite3_prepare( - (*context).sql, - b"DELETE FROM locations;\x00" as *const u8 as *const libc::c_char, - ); - sqlite3_step(stmt); - ((*context).cb)( - context, - Event::LOCATION_CHANGED, - 0i32 as uintptr_t, - 0i32 as uintptr_t, - ); - } + +pub unsafe fn dc_delete_all_locations(mut context: &dc_context_t) { + let mut stmt: *mut sqlite3_stmt; + + stmt = dc_sqlite3_prepare( + context, + &context.sql.clone().read().unwrap(), + b"DELETE FROM locations;\x00" as *const u8 as *const libc::c_char, + ); + sqlite3_step(stmt); + (context.cb)( + context, + Event::LOCATION_CHANGED, + 0i32 as uintptr_t, + 0i32 as uintptr_t, + ); + sqlite3_finalize(stmt); } + pub unsafe fn dc_get_location_kml( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut chat_id: uint32_t, mut last_added_location_id: *mut uint32_t, ) -> *mut libc::c_char { let mut success: libc::c_int = 0i32; - let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; - let mut self_addr: *mut libc::c_char = 0 as *mut libc::c_char; + let mut stmt: *mut sqlite3_stmt; + let mut self_addr: *mut libc::c_char; let mut now: time_t = time(0 as *mut time_t); - let mut locations_send_begin: time_t = 0i32 as time_t; - let mut locations_send_until: time_t = 0i32 as time_t; - let mut locations_last_sent: time_t = 0i32 as time_t; + let mut locations_send_begin: time_t; + let mut locations_send_until: time_t; + let mut locations_last_sent: time_t; let mut location_count: libc::c_int = 0i32; let mut ret: dc_strbuilder_t = dc_strbuilder_t { buf: 0 as *mut libc::c_char, @@ -331,30 +342,34 @@ pub unsafe fn dc_get_location_kml( eos: 0 as *mut libc::c_char, }; dc_strbuilder_init(&mut ret, 1000i32); - if !(context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint) { - self_addr = dc_sqlite3_get_config( - (*context).sql, - b"configured_addr\x00" as *const u8 as *const libc::c_char, - b"\x00" as *const u8 as *const libc::c_char, - ); - stmt = - dc_sqlite3_prepare((*context).sql, - b"SELECT locations_send_begin, locations_send_until, locations_last_sent FROM chats WHERE id=?;\x00" - as *const u8 as *const libc::c_char); - sqlite3_bind_int(stmt, 1i32, chat_id as libc::c_int); - if !(sqlite3_step(stmt) != 100i32) { - locations_send_begin = sqlite3_column_int64(stmt, 0i32) as time_t; - locations_send_until = sqlite3_column_int64(stmt, 1i32) as time_t; - locations_last_sent = sqlite3_column_int64(stmt, 2i32) as time_t; - sqlite3_finalize(stmt); - stmt = 0 as *mut sqlite3_stmt; - if !(locations_send_begin == 0i32 as libc::c_long || now > locations_send_until) { - dc_strbuilder_catf(&mut ret as *mut dc_strbuilder_t, + + self_addr = dc_sqlite3_get_config( + context, + &context.sql.clone().read().unwrap(), + b"configured_addr\x00" as *const u8 as *const libc::c_char, + b"\x00" as *const u8 as *const libc::c_char, + ); + stmt = + dc_sqlite3_prepare( + context, + &context.sql.clone().read().unwrap(), + b"SELECT locations_send_begin, locations_send_until, locations_last_sent FROM chats WHERE id=?;\x00" + as *const u8 as *const libc::c_char); + sqlite3_bind_int(stmt, 1i32, chat_id as libc::c_int); + if !(sqlite3_step(stmt) != 100i32) { + locations_send_begin = sqlite3_column_int64(stmt, 0i32) as time_t; + locations_send_until = sqlite3_column_int64(stmt, 1i32) as time_t; + locations_last_sent = sqlite3_column_int64(stmt, 2i32) as time_t; + sqlite3_finalize(stmt); + stmt = 0 as *mut sqlite3_stmt; + if !(locations_send_begin == 0i32 as libc::c_long || now > locations_send_until) { + dc_strbuilder_catf(&mut ret as *mut dc_strbuilder_t, b"\n\n\n\x00" as *const u8 as *const libc::c_char, self_addr); - stmt = dc_sqlite3_prepare( - (*context).sql, + stmt = dc_sqlite3_prepare( + context, + &context.sql.clone().read().unwrap(), b"SELECT id, latitude, longitude, accuracy, timestamp\ FROM locations WHERE from_id=? \ AND timestamp>=? \ @@ -365,44 +380,41 @@ pub unsafe fn dc_get_location_kml( as *const libc::c_char, ); - sqlite3_bind_int(stmt, 1i32, 1i32); - sqlite3_bind_int64(stmt, 2i32, locations_send_begin as sqlite3_int64); - sqlite3_bind_int64(stmt, 3i32, locations_last_sent as sqlite3_int64); - sqlite3_bind_int(stmt, 4i32, 1i32); - while sqlite3_step(stmt) == 100i32 { - let mut location_id: uint32_t = sqlite3_column_int(stmt, 0i32) as uint32_t; - let mut latitude: *mut libc::c_char = - dc_ftoa(sqlite3_column_double(stmt, 1i32)); - let mut longitude: *mut libc::c_char = - dc_ftoa(sqlite3_column_double(stmt, 2i32)); - let mut accuracy: *mut libc::c_char = - dc_ftoa(sqlite3_column_double(stmt, 3i32)); - let mut timestamp: *mut libc::c_char = - get_kml_timestamp(sqlite3_column_int64(stmt, 4i32) as time_t); - dc_strbuilder_catf(&mut ret as *mut dc_strbuilder_t, + sqlite3_bind_int(stmt, 1i32, 1i32); + sqlite3_bind_int64(stmt, 2i32, locations_send_begin as sqlite3_int64); + sqlite3_bind_int64(stmt, 3i32, locations_last_sent as sqlite3_int64); + sqlite3_bind_int(stmt, 4i32, 1i32); + while sqlite3_step(stmt) == 100i32 { + let mut location_id: uint32_t = sqlite3_column_int(stmt, 0i32) as uint32_t; + let mut latitude: *mut libc::c_char = dc_ftoa(sqlite3_column_double(stmt, 1i32)); + let mut longitude: *mut libc::c_char = dc_ftoa(sqlite3_column_double(stmt, 2i32)); + let mut accuracy: *mut libc::c_char = dc_ftoa(sqlite3_column_double(stmt, 3i32)); + let mut timestamp: *mut libc::c_char = + get_kml_timestamp(sqlite3_column_int64(stmt, 4i32) as time_t); + dc_strbuilder_catf(&mut ret as *mut dc_strbuilder_t, b"%s%s,%s\n\x00" as *const u8 as *const libc::c_char, timestamp, accuracy, longitude, latitude); - location_count += 1; - if !last_added_location_id.is_null() { - *last_added_location_id = location_id - } - free(latitude as *mut libc::c_void); - free(longitude as *mut libc::c_void); - free(accuracy as *mut libc::c_void); - free(timestamp as *mut libc::c_void); - } - if !(location_count == 0i32) { - dc_strbuilder_cat( - &mut ret, - b"\n\x00" as *const u8 as *const libc::c_char, - ); - success = 1i32 + location_count += 1; + if !last_added_location_id.is_null() { + *last_added_location_id = location_id } + free(latitude as *mut libc::c_void); + free(longitude as *mut libc::c_void); + free(accuracy as *mut libc::c_void); + free(timestamp as *mut libc::c_void); + } + if !(location_count == 0i32) { + dc_strbuilder_cat( + &mut ret, + b"\n\x00" as *const u8 as *const libc::c_char, + ); + success = 1i32 } } } + sqlite3_finalize(stmt); free(self_addr as *mut libc::c_void); if 0 == success { @@ -414,7 +426,8 @@ pub unsafe fn dc_get_location_kml( 0 as *mut libc::c_char }; } -/* ****************************************************************************** + +/******************************************************************************* * create kml-files ******************************************************************************/ unsafe fn get_kml_timestamp(mut utc: time_t) -> *mut libc::c_char { @@ -437,7 +450,8 @@ unsafe fn get_kml_timestamp(mut utc: time_t) -> *mut libc::c_char { gmtime(&mut utc) as *const libc::c_void, ::std::mem::size_of::(), ); - return dc_mprintf( + + dc_mprintf( b"%04i-%02i-%02iT%02i:%02i:%02iZ\x00" as *const u8 as *const libc::c_char, wanted_struct.tm_year as libc::c_int + 1900i32, wanted_struct.tm_mon as libc::c_int + 1i32, @@ -445,19 +459,14 @@ unsafe fn get_kml_timestamp(mut utc: time_t) -> *mut libc::c_char { wanted_struct.tm_hour as libc::c_int, wanted_struct.tm_min as libc::c_int, wanted_struct.tm_sec as libc::c_int, - ); + ) } pub unsafe fn dc_get_message_kml( - context: *const dc_context_t, timestamp: time_t, latitude: libc::c_double, longitude: libc::c_double, ) -> *mut libc::c_char { - if !(context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint) { - return std::ptr::null_mut(); - } - let timestamp_str = get_kml_timestamp(timestamp); let latitude_str = dc_ftoa(latitude); let longitude_str = dc_ftoa(longitude); @@ -485,13 +494,14 @@ pub unsafe fn dc_get_message_kml( } pub unsafe fn dc_set_kml_sent_timestamp( - mut context: *mut dc_context_t, - mut chat_id: uint32_t, - mut timestamp: time_t, + context: &dc_context_t, + chat_id: uint32_t, + timestamp: time_t, ) { - let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; + let mut stmt: *mut sqlite3_stmt; stmt = dc_sqlite3_prepare( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"UPDATE chats SET locations_last_sent=? WHERE id=?;\x00" as *const u8 as *const libc::c_char, ); @@ -500,14 +510,16 @@ pub unsafe fn dc_set_kml_sent_timestamp( sqlite3_step(stmt); sqlite3_finalize(stmt); } + pub unsafe fn dc_set_msg_location_id( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut msg_id: uint32_t, mut location_id: uint32_t, ) { - let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; + let mut stmt: *mut sqlite3_stmt; stmt = dc_sqlite3_prepare( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"UPDATE msgs SET location_id=? WHERE id=?;\x00" as *const u8 as *const libc::c_char, ); sqlite3_bind_int64(stmt, 1i32, location_id as sqlite3_int64); @@ -515,8 +527,9 @@ pub unsafe fn dc_set_msg_location_id( sqlite3_step(stmt); sqlite3_finalize(stmt); } + pub unsafe fn dc_save_locations( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut chat_id: uint32_t, mut contact_id: uint32_t, mut locations: *const dc_array_t, @@ -526,18 +539,16 @@ pub unsafe fn dc_save_locations( let mut stmt_insert: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; let mut newest_timestamp: time_t = 0i32 as time_t; let mut newest_location_id: uint32_t = 0i32 as uint32_t; - if !(context.is_null() - || (*context).magic != 0x11a11807i32 as libc::c_uint - || chat_id <= 9i32 as libc::c_uint - || locations.is_null()) - { + if !(chat_id <= 9i32 as libc::c_uint || locations.is_null()) { stmt_test = dc_sqlite3_prepare( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"SELECT id FROM locations WHERE timestamp=? AND from_id=?\x00" as *const u8 as *const libc::c_char, ); stmt_insert = dc_sqlite3_prepare( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"INSERT INTO locations\ (timestamp, from_id, chat_id, latitude, longitude, accuracy, independent) \ VALUES (?,?,?,?,?,?,?);\x00" as *const u8 as *const libc::c_char, @@ -563,7 +574,8 @@ pub unsafe fn dc_save_locations( if (*location).timestamp > newest_timestamp { newest_timestamp = (*location).timestamp; newest_location_id = dc_sqlite3_get_rowid2( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"locations\x00" as *const u8 as *const libc::c_char, b"timestamp\x00" as *const u8 as *const libc::c_char, (*location).timestamp as uint64_t, @@ -576,10 +588,12 @@ pub unsafe fn dc_save_locations( } sqlite3_finalize(stmt_test); sqlite3_finalize(stmt_insert); - return newest_location_id; + + newest_location_id } + pub unsafe fn dc_kml_parse( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut content: *const libc::c_char, mut content_bytes: size_t, ) -> *mut dc_kml_t { @@ -591,33 +605,35 @@ pub unsafe fn dc_kml_parse( text_cb: None, userdata: 0 as *mut libc::c_void, }; - if !(context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint) { - if content_bytes > (1 * 1024 * 1024) { - dc_log_warning( - context, - 0, - b"A kml-files with %i bytes is larger than reasonably expected.\x00" as *const u8 - as *const libc::c_char, - content_bytes, + + if content_bytes > (1 * 1024 * 1024) { + dc_log_warning( + context, + 0, + b"A kml-files with %i bytes is larger than reasonably expected.\x00" as *const u8 + as *const libc::c_char, + content_bytes, + ); + } else { + content_nullterminated = dc_null_terminate(content, content_bytes as libc::c_int); + if !content_nullterminated.is_null() { + (*kml).locations = dc_array_new_typed(1, 100 as size_t); + dc_saxparser_init(&mut saxparser, kml as *mut libc::c_void); + dc_saxparser_set_tag_handler( + &mut saxparser, + Some(kml_starttag_cb), + Some(kml_endtag_cb), ); - } else { - content_nullterminated = dc_null_terminate(content, content_bytes as libc::c_int); - if !content_nullterminated.is_null() { - (*kml).locations = dc_array_new_typed(context, 1, 100 as size_t); - dc_saxparser_init(&mut saxparser, kml as *mut libc::c_void); - dc_saxparser_set_tag_handler( - &mut saxparser, - Some(kml_starttag_cb), - Some(kml_endtag_cb), - ); - dc_saxparser_set_text_handler(&mut saxparser, Some(kml_text_cb)); - dc_saxparser_parse(&mut saxparser, content_nullterminated); - } + dc_saxparser_set_text_handler(&mut saxparser, Some(kml_text_cb)); + dc_saxparser_parse(&mut saxparser, content_nullterminated); } } + free(content_nullterminated as *mut libc::c_void); - return kml; + + kml } + unsafe fn kml_text_cb(userdata: *mut libc::c_void, text: *const libc::c_char, _len: libc::c_int) { let mut kml: *mut dc_kml_t = userdata as *mut dc_kml_t; if 0 != (*kml).tag & (0x4 | 0x10) { @@ -694,6 +710,7 @@ unsafe fn kml_text_cb(userdata: *mut libc::c_void, text: *const libc::c_char, _l free(val as *mut libc::c_void); }; } + unsafe fn kml_endtag_cb(mut userdata: *mut libc::c_void, mut tag: *const libc::c_char) { let mut kml: *mut dc_kml_t = userdata as *mut dc_kml_t; if strcmp(tag, b"placemark\x00" as *const u8 as *const libc::c_char) == 0i32 { @@ -710,7 +727,8 @@ unsafe fn kml_endtag_cb(mut userdata: *mut libc::c_void, mut tag: *const libc::c (*kml).tag = 0i32 }; } -/* ****************************************************************************** + +/******************************************************************************* * parse kml-files ******************************************************************************/ unsafe fn kml_starttag_cb( @@ -754,6 +772,7 @@ unsafe fn kml_starttag_cb( } }; } + pub unsafe fn dc_kml_unref(mut kml: *mut dc_kml_t) { if kml.is_null() { return; @@ -762,11 +781,9 @@ pub unsafe fn dc_kml_unref(mut kml: *mut dc_kml_t) { free((*kml).addr as *mut libc::c_void); free(kml as *mut libc::c_void); } -pub unsafe fn dc_job_do_DC_JOB_MAYBE_SEND_LOCATIONS( - context: *mut dc_context_t, - _job: *mut dc_job_t, -) { - let mut stmt_chats: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; + +pub unsafe fn dc_job_do_DC_JOB_MAYBE_SEND_LOCATIONS(context: &dc_context_t, _job: *mut dc_job_t) { + let mut stmt_chats: *mut sqlite3_stmt; let mut stmt_locations: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; let mut now: time_t = time(0 as *mut time_t); let mut continue_streaming: libc::c_int = 1i32; @@ -777,9 +794,10 @@ pub unsafe fn dc_job_do_DC_JOB_MAYBE_SEND_LOCATIONS( as *const libc::c_char, ); stmt_chats = dc_sqlite3_prepare( - (*context).sql, - b"SELECT id, locations_send_begin, locations_last_sent\ - FROM chats\ + context, + &context.sql.clone().read().unwrap(), + b"SELECT id, locations_send_begin, locations_last_sent \ + FROM chats \ WHERE locations_send_until>?;\x00" as *const u8 as *const libc::c_char, ); sqlite3_bind_int64(stmt_chats, 1i32, now as sqlite3_int64); @@ -794,7 +812,8 @@ pub unsafe fn dc_job_do_DC_JOB_MAYBE_SEND_LOCATIONS( } if stmt_locations.is_null() { stmt_locations = dc_sqlite3_prepare( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"SELECT id \ FROM locations \ WHERE from_id=? \ @@ -835,20 +854,22 @@ pub unsafe fn dc_job_do_DC_JOB_MAYBE_SEND_LOCATIONS( sqlite3_finalize(stmt_chats); sqlite3_finalize(stmt_locations); } + pub unsafe fn dc_job_do_DC_JOB_MAYBE_SEND_LOC_ENDED( - mut context: *mut dc_context_t, - mut job: *mut dc_job_t, + mut context: &dc_context_t, + mut job: &mut dc_job_t, ) { // this function is called when location-streaming _might_ have ended for a chat. // the function checks, if location-streaming is really ended; // if so, a device-message is added if not yet done. let mut chat_id: uint32_t = (*job).foreign_id; - let mut locations_send_begin: time_t = 0i32 as time_t; - let mut locations_send_until: time_t = 0i32 as time_t; - let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; + let mut locations_send_begin: time_t; + let mut locations_send_until: time_t; + let mut stmt; let mut stock_str: *mut libc::c_char = 0 as *mut libc::c_char; stmt = dc_sqlite3_prepare( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"SELECT locations_send_begin, locations_send_until FROM chats WHERE id=?\x00" as *const u8 as *const libc::c_char, ); @@ -869,10 +890,12 @@ pub unsafe fn dc_job_do_DC_JOB_MAYBE_SEND_LOC_ENDED( { // not streaming, device-message already sent stmt = - dc_sqlite3_prepare((*context).sql, - b"UPDATE chats SET locations_send_begin=0, locations_send_until=0 WHERE id=?\x00" - as *const u8 as - *const libc::c_char); + dc_sqlite3_prepare( + context, + &context.sql.clone().read().unwrap(), + b"UPDATE chats SET locations_send_begin=0, locations_send_until=0 WHERE id=?\x00" + as *const u8 as + *const libc::c_char); sqlite3_bind_int(stmt, 1i32, chat_id as libc::c_int); sqlite3_step(stmt); stock_str = dc_stock_system_msg( @@ -883,7 +906,7 @@ pub unsafe fn dc_job_do_DC_JOB_MAYBE_SEND_LOC_ENDED( 0i32 as uint32_t, ); dc_add_device_msg(context, chat_id, stock_str); - ((*context).cb)( + (context.cb)( context, Event::CHAT_MODIFIED, chat_id as uintptr_t, diff --git a/src/dc_log.rs b/src/dc_log.rs index 426c85272..ee6149aeb 100644 --- a/src/dc_log.rs +++ b/src/dc_log.rs @@ -1,5 +1,3 @@ -use libc; - use crate::constants::Event; use crate::dc_context::dc_context_t; use crate::dc_tools::*; @@ -7,7 +5,7 @@ use crate::types::*; use crate::x::*; pub unsafe extern "C" fn dc_log_event( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut event_code: Event, mut data1: libc::c_int, mut msg: *const libc::c_char, @@ -15,6 +13,7 @@ pub unsafe extern "C" fn dc_log_event( ) { log_vprintf(context, event_code, data1, msg, va); } + /* Asynchronous "Thread-errors" are reported by the dc_log_error() function. These errors must be shown to the user by a bubble or so. @@ -23,16 +22,13 @@ usually not reported using dc_log_error() - its up to the caller to decide, what should be reported or done. However, these "Normal" errors are usually logged by dc_log_warning(). */ unsafe fn log_vprintf( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut event: Event, mut data1: libc::c_int, mut msg_format: *const libc::c_char, mut va_0: ::std::ffi::VaList, ) { - let mut msg: *mut libc::c_char = 0 as *mut libc::c_char; - if context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint { - return; - } + let mut msg: *mut libc::c_char; if !msg_format.is_null() { let mut tempbuf: [libc::c_char; 1025] = [0; 1025]; vsnprintf( @@ -51,43 +47,95 @@ unsafe fn log_vprintf( ((*context).cb)(context, event, data1 as uintptr_t, msg as uintptr_t); free(msg as *mut libc::c_void); } + pub unsafe extern "C" fn dc_log_event_seq( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut event_code: Event, mut sequence_start: *mut libc::c_int, mut msg: *const libc::c_char, mut va_0: ... ) { - if context.is_null() - || sequence_start.is_null() - || (*context).magic != 0x11a11807i32 as libc::c_uint - { + if sequence_start.is_null() { return; } log_vprintf(context, event_code, *sequence_start, msg, va_0); *sequence_start = 0i32; } + pub unsafe extern "C" fn dc_log_error( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut data1: libc::c_int, mut msg: *const libc::c_char, mut va_1: ... ) { log_vprintf(context, Event::ERROR, data1, msg, va_1); } + pub unsafe extern "C" fn dc_log_warning( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut data1: libc::c_int, mut msg: *const libc::c_char, mut va_2: ... ) { log_vprintf(context, Event::WARNING, data1, msg, va_2); } + pub unsafe extern "C" fn dc_log_info( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut data1: libc::c_int, mut msg: *const libc::c_char, mut va_3: ... ) { log_vprintf(context, Event::INFO, data1, msg, va_3); } + +#[macro_export] +macro_rules! info { + ($ctx:expr, $data1:expr, $msg:expr) => { + info!($ctx, $data1, $msg,) + }; + ($ctx:expr, $data1:expr, $msg:expr, $($args:expr),* $(,)?) => { + unsafe { + dc_log_info( + $ctx, + $data1, + std::ffi::CString::new($msg).unwrap().as_ptr(), + $($args),* + ) + } + }; +} + +#[macro_export] +macro_rules! warn { + ($ctx:expr, $data1:expr, $msg:expr) => { + warn!($ctx, $data1, $msg,) + }; + ($ctx:expr, $data1:expr, $msg:expr, $($args:expr),* $(,)?) => { + unsafe { + dc_log_warning( + $ctx, + $data1, + std::ffi::CString::new($msg).unwrap().as_ptr(), + $($args),* + ) + } + }; +} + +#[macro_export] +macro_rules! error { + ($ctx:expr, $data1:expr, $msg:expr) => { + error!($ctx, $data1, $msg,) + }; + ($ctx:expr, $data1:expr, $msg:expr, $($args:expr),* $(,)?) => { + unsafe { + dc_log_error( + $ctx, + $data1, + std::ffi::CString::new($msg).unwrap().as_ptr(), + $($args),* + ) + } + }; +} diff --git a/src/dc_loginparam.rs b/src/dc_loginparam.rs index 34e2faa1e..b9cc29a87 100644 --- a/src/dc_loginparam.rs +++ b/src/dc_loginparam.rs @@ -1,5 +1,4 @@ -use libc; - +use crate::dc_context::dc_context_t; use crate::dc_sqlite3::*; use crate::dc_strbuilder::*; use crate::dc_tools::*; @@ -22,13 +21,15 @@ pub struct dc_loginparam_t { } pub unsafe fn dc_loginparam_new() -> *mut dc_loginparam_t { - let mut loginparam: *mut dc_loginparam_t = 0 as *mut dc_loginparam_t; + let mut loginparam: *mut dc_loginparam_t; loginparam = calloc(1, ::std::mem::size_of::()) as *mut dc_loginparam_t; if loginparam.is_null() { exit(22i32); } - return loginparam; + + loginparam } + pub unsafe fn dc_loginparam_unref(mut loginparam: *mut dc_loginparam_t) { if loginparam.is_null() { return; @@ -36,6 +37,7 @@ pub unsafe fn dc_loginparam_unref(mut loginparam: *mut dc_loginparam_t) { dc_loginparam_empty(loginparam); free(loginparam as *mut libc::c_void); } + /* clears all data and frees its memory. All pointers are NULL after this function is called. */ pub unsafe fn dc_loginparam_empty(mut loginparam: *mut dc_loginparam_t) { if loginparam.is_null() { @@ -59,10 +61,12 @@ pub unsafe fn dc_loginparam_empty(mut loginparam: *mut dc_loginparam_t) { (*loginparam).send_pw = 0 as *mut libc::c_char; (*loginparam).server_flags = 0i32; } + pub unsafe fn dc_loginparam_read( - mut loginparam: *mut dc_loginparam_t, - mut sql: *mut dc_sqlite3_t, - mut prefix: *const libc::c_char, + context: &dc_context_t, + loginparam: *mut dc_loginparam_t, + sql: &dc_sqlite3_t, + prefix: *const libc::c_char, ) { let mut key: *mut libc::c_char = 0 as *mut libc::c_char; dc_loginparam_empty(loginparam); @@ -72,76 +76,78 @@ pub unsafe fn dc_loginparam_read( prefix, b"addr\x00" as *const u8 as *const libc::c_char, ); - (*loginparam).addr = dc_sqlite3_get_config(sql, key, 0 as *const libc::c_char); + (*loginparam).addr = dc_sqlite3_get_config(context, sql, key, 0 as *const libc::c_char); sqlite3_free(key as *mut libc::c_void); key = sqlite3_mprintf( b"%s%s\x00" as *const u8 as *const libc::c_char, prefix, b"mail_server\x00" as *const u8 as *const libc::c_char, ); - (*loginparam).mail_server = dc_sqlite3_get_config(sql, key, 0 as *const libc::c_char); + (*loginparam).mail_server = dc_sqlite3_get_config(context, sql, key, 0 as *const libc::c_char); sqlite3_free(key as *mut libc::c_void); key = sqlite3_mprintf( b"%s%s\x00" as *const u8 as *const libc::c_char, prefix, b"mail_port\x00" as *const u8 as *const libc::c_char, ); - (*loginparam).mail_port = dc_sqlite3_get_config_int(sql, key, 0i32); + (*loginparam).mail_port = dc_sqlite3_get_config_int(context, sql, key, 0i32); sqlite3_free(key as *mut libc::c_void); key = sqlite3_mprintf( b"%s%s\x00" as *const u8 as *const libc::c_char, prefix, b"mail_user\x00" as *const u8 as *const libc::c_char, ); - (*loginparam).mail_user = dc_sqlite3_get_config(sql, key, 0 as *const libc::c_char); + (*loginparam).mail_user = dc_sqlite3_get_config(context, sql, key, 0 as *const libc::c_char); sqlite3_free(key as *mut libc::c_void); key = sqlite3_mprintf( b"%s%s\x00" as *const u8 as *const libc::c_char, prefix, b"mail_pw\x00" as *const u8 as *const libc::c_char, ); - (*loginparam).mail_pw = dc_sqlite3_get_config(sql, key, 0 as *const libc::c_char); + (*loginparam).mail_pw = dc_sqlite3_get_config(context, sql, key, 0 as *const libc::c_char); sqlite3_free(key as *mut libc::c_void); key = sqlite3_mprintf( b"%s%s\x00" as *const u8 as *const libc::c_char, prefix, b"send_server\x00" as *const u8 as *const libc::c_char, ); - (*loginparam).send_server = dc_sqlite3_get_config(sql, key, 0 as *const libc::c_char); + (*loginparam).send_server = dc_sqlite3_get_config(context, sql, key, 0 as *const libc::c_char); sqlite3_free(key as *mut libc::c_void); key = sqlite3_mprintf( b"%s%s\x00" as *const u8 as *const libc::c_char, prefix, b"send_port\x00" as *const u8 as *const libc::c_char, ); - (*loginparam).send_port = dc_sqlite3_get_config_int(sql, key, 0i32); + (*loginparam).send_port = dc_sqlite3_get_config_int(context, sql, key, 0i32); sqlite3_free(key as *mut libc::c_void); key = sqlite3_mprintf( b"%s%s\x00" as *const u8 as *const libc::c_char, prefix, b"send_user\x00" as *const u8 as *const libc::c_char, ); - (*loginparam).send_user = dc_sqlite3_get_config(sql, key, 0 as *const libc::c_char); + (*loginparam).send_user = dc_sqlite3_get_config(context, sql, key, 0 as *const libc::c_char); sqlite3_free(key as *mut libc::c_void); key = sqlite3_mprintf( b"%s%s\x00" as *const u8 as *const libc::c_char, prefix, b"send_pw\x00" as *const u8 as *const libc::c_char, ); - (*loginparam).send_pw = dc_sqlite3_get_config(sql, key, 0 as *const libc::c_char); + (*loginparam).send_pw = dc_sqlite3_get_config(context, sql, key, 0 as *const libc::c_char); sqlite3_free(key as *mut libc::c_void); key = sqlite3_mprintf( b"%s%s\x00" as *const u8 as *const libc::c_char, prefix, b"server_flags\x00" as *const u8 as *const libc::c_char, ); - (*loginparam).server_flags = dc_sqlite3_get_config_int(sql, key, 0i32); + (*loginparam).server_flags = dc_sqlite3_get_config_int(context, sql, key, 0i32); sqlite3_free(key as *mut libc::c_void); } + pub unsafe fn dc_loginparam_write( - mut loginparam: *const dc_loginparam_t, - mut sql: *mut dc_sqlite3_t, - mut prefix: *const libc::c_char, + context: &dc_context_t, + loginparam: *const dc_loginparam_t, + sql: &dc_sqlite3_t, + prefix: *const libc::c_char, ) { let mut key: *mut libc::c_char = 0 as *mut libc::c_char; sqlite3_free(key as *mut libc::c_void); @@ -150,72 +156,73 @@ pub unsafe fn dc_loginparam_write( prefix, b"addr\x00" as *const u8 as *const libc::c_char, ); - dc_sqlite3_set_config(sql, key, (*loginparam).addr); + dc_sqlite3_set_config(context, sql, key, (*loginparam).addr); sqlite3_free(key as *mut libc::c_void); key = sqlite3_mprintf( b"%s%s\x00" as *const u8 as *const libc::c_char, prefix, b"mail_server\x00" as *const u8 as *const libc::c_char, ); - dc_sqlite3_set_config(sql, key, (*loginparam).mail_server); + dc_sqlite3_set_config(context, sql, key, (*loginparam).mail_server); sqlite3_free(key as *mut libc::c_void); key = sqlite3_mprintf( b"%s%s\x00" as *const u8 as *const libc::c_char, prefix, b"mail_port\x00" as *const u8 as *const libc::c_char, ); - dc_sqlite3_set_config_int(sql, key, (*loginparam).mail_port); + dc_sqlite3_set_config_int(context, sql, key, (*loginparam).mail_port); sqlite3_free(key as *mut libc::c_void); key = sqlite3_mprintf( b"%s%s\x00" as *const u8 as *const libc::c_char, prefix, b"mail_user\x00" as *const u8 as *const libc::c_char, ); - dc_sqlite3_set_config(sql, key, (*loginparam).mail_user); + dc_sqlite3_set_config(context, sql, key, (*loginparam).mail_user); sqlite3_free(key as *mut libc::c_void); key = sqlite3_mprintf( b"%s%s\x00" as *const u8 as *const libc::c_char, prefix, b"mail_pw\x00" as *const u8 as *const libc::c_char, ); - dc_sqlite3_set_config(sql, key, (*loginparam).mail_pw); + dc_sqlite3_set_config(context, sql, key, (*loginparam).mail_pw); sqlite3_free(key as *mut libc::c_void); key = sqlite3_mprintf( b"%s%s\x00" as *const u8 as *const libc::c_char, prefix, b"send_server\x00" as *const u8 as *const libc::c_char, ); - dc_sqlite3_set_config(sql, key, (*loginparam).send_server); + dc_sqlite3_set_config(context, sql, key, (*loginparam).send_server); sqlite3_free(key as *mut libc::c_void); key = sqlite3_mprintf( b"%s%s\x00" as *const u8 as *const libc::c_char, prefix, b"send_port\x00" as *const u8 as *const libc::c_char, ); - dc_sqlite3_set_config_int(sql, key, (*loginparam).send_port); + dc_sqlite3_set_config_int(context, sql, key, (*loginparam).send_port); sqlite3_free(key as *mut libc::c_void); key = sqlite3_mprintf( b"%s%s\x00" as *const u8 as *const libc::c_char, prefix, b"send_user\x00" as *const u8 as *const libc::c_char, ); - dc_sqlite3_set_config(sql, key, (*loginparam).send_user); + dc_sqlite3_set_config(context, sql, key, (*loginparam).send_user); sqlite3_free(key as *mut libc::c_void); key = sqlite3_mprintf( b"%s%s\x00" as *const u8 as *const libc::c_char, prefix, b"send_pw\x00" as *const u8 as *const libc::c_char, ); - dc_sqlite3_set_config(sql, key, (*loginparam).send_pw); + dc_sqlite3_set_config(context, sql, key, (*loginparam).send_pw); sqlite3_free(key as *mut libc::c_void); key = sqlite3_mprintf( b"%s%s\x00" as *const u8 as *const libc::c_char, prefix, b"server_flags\x00" as *const u8 as *const libc::c_char, ); - dc_sqlite3_set_config_int(sql, key, (*loginparam).server_flags); + dc_sqlite3_set_config_int(context, sql, key, (*loginparam).server_flags); sqlite3_free(key as *mut libc::c_void); } + pub unsafe fn dc_loginparam_get_readable( mut loginparam: *const dc_loginparam_t, ) -> *mut libc::c_char { @@ -267,8 +274,10 @@ pub unsafe fn dc_loginparam_get_readable( flags_readable, ); free(flags_readable as *mut libc::c_void); - return ret; + + ret } + unsafe fn get_readable_flags(mut flags: libc::c_int) -> *mut libc::c_char { let mut strbuilder: dc_strbuilder_t = dc_strbuilder_t { buf: 0 as *mut libc::c_char, @@ -355,5 +364,6 @@ unsafe fn get_readable_flags(mut flags: libc::c_int) -> *mut libc::c_char { ); } dc_trim(strbuilder.buf); - return strbuilder.buf; + + strbuilder.buf } diff --git a/src/dc_lot.rs b/src/dc_lot.rs index 1cd55b0a2..e548d47b4 100644 --- a/src/dc_lot.rs +++ b/src/dc_lot.rs @@ -1,5 +1,3 @@ -use libc; - use crate::dc_chat::*; use crate::dc_contact::*; use crate::dc_context::dc_context_t; @@ -36,15 +34,17 @@ pub struct dc_lot_t { * NB: _Lot_ is used in the meaning _heap_ here. */ pub unsafe fn dc_lot_new() -> *mut dc_lot_t { - let mut lot: *mut dc_lot_t = 0 as *mut dc_lot_t; + let mut lot: *mut dc_lot_t; lot = calloc(1, ::std::mem::size_of::()) as *mut dc_lot_t; if lot.is_null() { exit(27i32); } (*lot).magic = 0x107107i32 as uint32_t; (*lot).text1_meaning = 0i32; - return lot; + + lot } + pub unsafe fn dc_lot_empty(mut lot: *mut dc_lot_t) { if lot.is_null() || (*lot).magic != 0x107107i32 as libc::c_uint { return; @@ -64,6 +64,7 @@ pub unsafe fn dc_lot_empty(mut lot: *mut dc_lot_t) { (*lot).state = 0i32; (*lot).id = 0i32 as uint32_t; } + pub unsafe fn dc_lot_unref(mut set: *mut dc_lot_t) { if set.is_null() || (*set).magic != 0x107107i32 as libc::c_uint { return; @@ -72,42 +73,55 @@ pub unsafe fn dc_lot_unref(mut set: *mut dc_lot_t) { (*set).magic = 0i32 as uint32_t; free(set as *mut libc::c_void); } + pub unsafe fn dc_lot_get_text1(mut lot: *const dc_lot_t) -> *mut libc::c_char { if lot.is_null() || (*lot).magic != 0x107107i32 as libc::c_uint { return 0 as *mut libc::c_char; } - return dc_strdup_keep_null((*lot).text1); + + dc_strdup_keep_null((*lot).text1) } + pub unsafe fn dc_lot_get_text2(mut lot: *const dc_lot_t) -> *mut libc::c_char { if lot.is_null() || (*lot).magic != 0x107107i32 as libc::c_uint { return 0 as *mut libc::c_char; } - return dc_strdup_keep_null((*lot).text2); + + dc_strdup_keep_null((*lot).text2) } + pub unsafe fn dc_lot_get_text1_meaning(mut lot: *const dc_lot_t) -> libc::c_int { if lot.is_null() || (*lot).magic != 0x107107i32 as libc::c_uint { return 0i32; } - return (*lot).text1_meaning; + + (*lot).text1_meaning } + pub unsafe fn dc_lot_get_state(mut lot: *const dc_lot_t) -> libc::c_int { if lot.is_null() || (*lot).magic != 0x107107i32 as libc::c_uint { return 0i32; } - return (*lot).state; + + (*lot).state } + pub unsafe fn dc_lot_get_id(mut lot: *const dc_lot_t) -> uint32_t { if lot.is_null() || (*lot).magic != 0x107107i32 as libc::c_uint { return 0i32 as uint32_t; } - return (*lot).id; + + (*lot).id } + pub unsafe fn dc_lot_get_timestamp(mut lot: *const dc_lot_t) -> time_t { if lot.is_null() || (*lot).magic != 0x107107i32 as libc::c_uint { return 0i32 as time_t; } - return (*lot).timestamp; + + (*lot).timestamp } + /* library-internal */ /* in practice, the user additionally cuts the string himself pixel-accurate */ pub unsafe fn dc_lot_fill( @@ -115,7 +129,7 @@ pub unsafe fn dc_lot_fill( mut msg: *const dc_msg_t, mut chat: *const dc_chat_t, mut contact: *const dc_contact_t, - mut context: *mut dc_context_t, + mut context: &dc_context_t, ) { if lot.is_null() || (*lot).magic != 0x107107i32 as libc::c_uint || msg.is_null() { return; diff --git a/src/dc_mimefactory.rs b/src/dc_mimefactory.rs index 1ee95229a..4b2355713 100644 --- a/src/dc_mimefactory.rs +++ b/src/dc_mimefactory.rs @@ -1,4 +1,11 @@ -use libc; +use mmime::mailimf_types::*; +use mmime::mailimf_types_helper::*; +use mmime::mailmime_disposition::*; +use mmime::mailmime_types::*; +use mmime::mailmime_types_helper::*; +use mmime::mailmime_write_mem::*; +use mmime::mmapstring::*; +use mmime::other::*; use crate::constants::VERSION; use crate::dc_chat::*; @@ -19,7 +26,7 @@ use crate::x::*; #[derive(Copy, Clone)] #[repr(C)] -pub struct dc_mimefactory_t { +pub struct dc_mimefactory_t<'a> { pub from_addr: *mut libc::c_char, pub from_displayname: *mut libc::c_char, pub selfstatus: *mut libc::c_char, @@ -28,8 +35,8 @@ pub struct dc_mimefactory_t { pub timestamp: time_t, pub rfc724_mid: *mut libc::c_char, pub loaded: dc_mimefactory_loaded_t, - pub msg: *mut dc_msg_t, - pub chat: *mut dc_chat_t, + pub msg: *mut dc_msg_t<'a>, + pub chat: *mut dc_chat_t<'a>, pub increation: libc::c_int, pub in_reply_to: *mut libc::c_char, pub references: *mut libc::c_char, @@ -39,7 +46,7 @@ pub struct dc_mimefactory_t { pub out_gossiped: libc::c_int, pub out_last_added_location_id: uint32_t, pub error: *mut libc::c_char, - pub context: *mut dc_context_t, + pub context: &'a dc_context_t, } pub type dc_mimefactory_loaded_t = libc::c_uint; @@ -47,11 +54,11 @@ pub const DC_MF_MDN_LOADED: dc_mimefactory_loaded_t = 2; pub const DC_MF_MSG_LOADED: dc_mimefactory_loaded_t = 1; pub const DC_MF_NOTHING_LOADED: dc_mimefactory_loaded_t = 0; -pub unsafe fn dc_mimefactory_init( - mut factory: *mut dc_mimefactory_t, - mut context: *mut dc_context_t, +pub unsafe fn dc_mimefactory_init<'a>( + factory: *mut dc_mimefactory_t<'a>, + context: &'a dc_context_t, ) { - if factory.is_null() || context.is_null() { + if factory.is_null() { return; } memset( @@ -61,6 +68,7 @@ pub unsafe fn dc_mimefactory_init( ); (*factory).context = context; } + pub unsafe fn dc_mimefactory_empty(mut factory: *mut dc_mimefactory_t) { if factory.is_null() { return; @@ -101,20 +109,16 @@ pub unsafe fn dc_mimefactory_empty(mut factory: *mut dc_mimefactory_t) { (*factory).error = 0 as *mut libc::c_char; (*factory).timestamp = 0i32 as time_t; } + pub unsafe fn dc_mimefactory_load_msg( mut factory: *mut dc_mimefactory_t, mut msg_id: uint32_t, ) -> libc::c_int { - let mut context: *mut dc_context_t = 0 as *mut dc_context_t; let mut success: libc::c_int = 0i32; let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; - if !(factory.is_null() - || msg_id <= 9i32 as libc::c_uint - || (*factory).context.is_null() - || !(*factory).msg.is_null()) - { + if !(factory.is_null() || msg_id <= 9i32 as libc::c_uint || !(*factory).msg.is_null()) { /*call empty() before */ - context = (*factory).context; + let context = (*factory).context; (*factory).recipients_names = clist_new(); (*factory).recipients_addr = clist_new(); (*factory).msg = dc_msg_new_untyped(context); @@ -137,10 +141,12 @@ pub unsafe fn dc_mimefactory_load_msg( ); } else { stmt = - dc_sqlite3_prepare((*context).sql, - b"SELECT c.authname, c.addr FROM chats_contacts cc LEFT JOIN contacts c ON cc.contact_id=c.id WHERE cc.chat_id=? AND cc.contact_id>9;\x00" - as *const u8 as - *const libc::c_char); + dc_sqlite3_prepare( + context, + &context.sql.clone().read().unwrap(), + b"SELECT c.authname, c.addr FROM chats_contacts cc LEFT JOIN contacts c ON cc.contact_id=c.id WHERE cc.chat_id=? AND cc.contact_id>9;\x00" + as *const u8 as + *const libc::c_char); sqlite3_bind_int(stmt, 1i32, (*(*factory).msg).chat_id as libc::c_int); while sqlite3_step(stmt) == 100i32 { let mut authname: *const libc::c_char = @@ -166,7 +172,6 @@ pub unsafe fn dc_mimefactory_load_msg( } } sqlite3_finalize(stmt); - stmt = 0 as *mut sqlite3_stmt; let mut command: libc::c_int = dc_param_get_int((*(*factory).msg).param, 'S' as i32, 0i32); if command == 5i32 { @@ -176,7 +181,8 @@ pub unsafe fn dc_mimefactory_load_msg( 0 as *const libc::c_char, ); let mut self_addr: *mut libc::c_char = dc_sqlite3_get_config( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"configured_addr\x00" as *const u8 as *const libc::c_char, b"\x00" as *const u8 as *const libc::c_char, ); @@ -202,7 +208,8 @@ pub unsafe fn dc_mimefactory_load_msg( if command != 6i32 && command != 7i32 && 0 != dc_sqlite3_get_config_int( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"mdns_enabled\x00" as *const u8 as *const libc::c_char, 1i32, ) @@ -211,7 +218,8 @@ pub unsafe fn dc_mimefactory_load_msg( } } stmt = dc_sqlite3_prepare( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"SELECT mime_in_reply_to, mime_references FROM msgs WHERE id=?\x00" as *const u8 as *const libc::c_char, ); @@ -236,19 +244,23 @@ pub unsafe fn dc_mimefactory_load_msg( sqlite3_finalize(stmt); return success; } + unsafe fn load_from(mut factory: *mut dc_mimefactory_t) { (*factory).from_addr = dc_sqlite3_get_config( - (*(*factory).context).sql, + (*factory).context, + &mut (*factory).context.sql.clone().read().unwrap(), b"configured_addr\x00" as *const u8 as *const libc::c_char, 0 as *const libc::c_char, ); (*factory).from_displayname = dc_sqlite3_get_config( - (*(*factory).context).sql, + (*factory).context, + &mut (*factory).context.sql.clone().read().unwrap(), b"displayname\x00" as *const u8 as *const libc::c_char, 0 as *const libc::c_char, ); (*factory).selfstatus = dc_sqlite3_get_config( - (*(*factory).context).sql, + (*factory).context, + &mut (*factory).context.sql.clone().read().unwrap(), b"selfstatus\x00" as *const u8 as *const libc::c_char, 0 as *const libc::c_char, ); @@ -256,6 +268,7 @@ unsafe fn load_from(mut factory: *mut dc_mimefactory_t) { (*factory).selfstatus = dc_stock_str((*factory).context, 13i32) }; } + pub unsafe fn dc_mimefactory_load_mdn( mut factory: *mut dc_mimefactory_t, mut msg_id: uint32_t, @@ -268,7 +281,8 @@ pub unsafe fn dc_mimefactory_load_mdn( (*factory).msg = dc_msg_new_untyped((*factory).context); if !(0 == dc_sqlite3_get_config_int( - (*(*factory).context).sql, + (*factory).context, + &mut (*factory).context.sql.clone().read().unwrap(), b"mdns_enabled\x00" as *const u8 as *const libc::c_char, 1i32, )) @@ -278,7 +292,7 @@ pub unsafe fn dc_mimefactory_load_mdn( if !(0 == dc_msg_load_from_db((*factory).msg, (*factory).context, msg_id) || 0 == dc_contact_load_from_db( contact, - (*(*factory).context).sql, + &mut (*factory).context.sql.clone().read().unwrap(), (*(*factory).msg).from_id, )) { @@ -315,12 +329,15 @@ pub unsafe fn dc_mimefactory_load_mdn( } } dc_contact_unref(contact); - return success; + + success } + +// TODO should return bool /rtn pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc::c_int { - let mut subject: *mut mailimf_subject = 0 as *mut mailimf_subject; + let mut subject: *mut mailimf_subject; let mut current_block: u64; - let mut imf_fields: *mut mailimf_fields = 0 as *mut mailimf_fields; + let mut imf_fields: *mut mailimf_fields; let mut message: *mut mailmime = 0 as *mut mailmime; let mut message_text: *mut libc::c_char = 0 as *mut libc::c_char; let mut message_text2: *mut libc::c_char = 0 as *mut libc::c_char; @@ -374,8 +391,8 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc: && !(*factory).recipients_addr.is_null() && (*(*factory).recipients_addr).count > 0i32 { - let mut iter1: *mut clistiter = 0 as *mut clistiter; - let mut iter2: *mut clistiter = 0 as *mut clistiter; + let mut iter1: *mut clistiter; + let mut iter2: *mut clistiter; to = mailimf_address_list_new_empty(); iter1 = (*(*factory).recipients_names).first; iter2 = (*(*factory).recipients_addr).first; @@ -408,12 +425,12 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc: iter1 = if !iter1.is_null() { (*iter1).next } else { - 0 as *mut clistcell_s + 0 as *mut clistcell }; iter2 = if !iter2.is_null() { (*iter2).next } else { - 0 as *mut clistcell_s + 0 as *mut clistcell } } } @@ -844,7 +861,6 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc: } else { if !meta_part.is_null() { mailmime_smart_add_part(message, meta_part); - parts += 1 } if 0 != dc_param_exists((*msg).param, DC_PARAM_SET_LATITUDE as libc::c_int) { @@ -858,12 +874,8 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc: DC_PARAM_SET_LONGITUDE as libc::c_int, 0.0, ); - let kml_file = dc_get_message_kml( - (*msg).context, - (*msg).timestamp_sort, - latitude, - longitude, - ); + let kml_file = + dc_get_message_kml((*msg).timestamp_sort, latitude, longitude); if !kml_file.is_null() { let content_type = mailmime_content_new_with_str( b"application/vnd.google-earth.kml+xml\x00" as *const u8 @@ -880,7 +892,6 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc: mailmime_set_body_text(kml_mime_part, kml_file, strlen(kml_file)); mailmime_smart_add_part(message, kml_mime_part); - parts += 1; } } @@ -909,7 +920,6 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc: mailmime_new_empty(content_type, mime_fields); mailmime_set_body_text(kml_mime_part, kml_file, strlen(kml_file)); mailmime_smart_add_part(message, kml_mime_part); - parts += 1; if 0 == dc_param_exists( (*msg).param, DC_PARAM_SET_LATITUDE as libc::c_int, @@ -939,8 +949,8 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc: ) as *mut libc::c_void, ); mailmime_add_part(message, multipart); - let mut p1: *mut libc::c_char = 0 as *mut libc::c_char; - let mut p2: *mut libc::c_char = 0 as *mut libc::c_char; + let mut p1: *mut libc::c_char; + let mut p2: *mut libc::c_char; if 0 != dc_param_get_int((*(*factory).msg).param, 'c' as i32, 0i32) { p1 = dc_stock_str((*factory).context, 24i32) } else { @@ -1050,19 +1060,17 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc: free(message_text2 as *mut libc::c_void); free(subject_str as *mut libc::c_void); free(grpimage as *mut libc::c_void); - return success; + + success } + unsafe fn get_subject( mut chat: *const dc_chat_t, mut msg: *const dc_msg_t, mut afwd_email: libc::c_int, ) -> *mut libc::c_char { - let mut context: *mut dc_context_t = if !chat.is_null() { - (*chat).context - } else { - 0 as *mut dc_context_t - }; - let mut ret: *mut libc::c_char = 0 as *mut libc::c_char; + let context = (*chat).context; + let mut ret: *mut libc::c_char; let mut raw_subject: *mut libc::c_char = dc_msg_get_summarytext_by_raw((*msg).type_0, (*msg).text, (*msg).param, 32i32, context); let mut fwd: *const libc::c_char = if 0 != afwd_email { @@ -1087,8 +1095,10 @@ unsafe fn get_subject( ) } free(raw_subject as *mut libc::c_void); - return ret; + + ret } + unsafe fn set_error(mut factory: *mut dc_mimefactory_t, mut text: *const libc::c_char) { if factory.is_null() { return; @@ -1096,10 +1106,11 @@ unsafe fn set_error(mut factory: *mut dc_mimefactory_t, mut text: *const libc::c free((*factory).error as *mut libc::c_void); (*factory).error = dc_strdup_keep_null(text); } + unsafe fn build_body_text(mut text: *mut libc::c_char) -> *mut mailmime { - let mut mime_fields: *mut mailmime_fields = 0 as *mut mailmime_fields; - let mut message_part: *mut mailmime = 0 as *mut mailmime; - let mut content: *mut mailmime_content = 0 as *mut mailmime_content; + let mut mime_fields: *mut mailmime_fields; + let mut message_part: *mut mailmime; + let mut content: *mut mailmime_content; content = mailmime_content_new_with_str(b"text/plain\x00" as *const u8 as *const libc::c_char); clist_insert_after( (*content).ct_parameters, @@ -1112,17 +1123,19 @@ unsafe fn build_body_text(mut text: *mut libc::c_char) -> *mut mailmime { mime_fields = mailmime_fields_new_encoding(MAILMIME_MECHANISM_8BIT as libc::c_int); message_part = mailmime_new_empty(content, mime_fields); mailmime_set_body_text(message_part, text, strlen(text)); - return message_part; + + message_part } + unsafe fn build_body_file( mut msg: *const dc_msg_t, mut base_name: *const libc::c_char, mut ret_file_name_as_sent: *mut *mut libc::c_char, ) -> *mut mailmime { - let mut needs_ext: libc::c_int = 0; - let mut mime_fields: *mut mailmime_fields = 0 as *mut mailmime_fields; + let mut needs_ext: libc::c_int; + let mut mime_fields: *mut mailmime_fields; let mut mime_sub: *mut mailmime = 0 as *mut mailmime; - let mut content: *mut mailmime_content = 0 as *mut mailmime_content; + let mut content: *mut mailmime_content; let mut pathNfilename: *mut libc::c_char = dc_param_get((*msg).param, 'f' as i32, 0 as *const libc::c_char); let mut mimetype: *mut libc::c_char = @@ -1268,7 +1281,7 @@ unsafe fn build_body_file( cur1 = if !cur1.is_null() { (*cur1).next } else { - 0 as *mut clistcell_s + 0 as *mut clistcell } } } @@ -1295,11 +1308,14 @@ unsafe fn build_body_file( free(filename_to_send as *mut libc::c_void); free(filename_encoded as *mut libc::c_void); free(suffix as *mut libc::c_void); - return mime_sub; + + mime_sub } -/* ****************************************************************************** + +/******************************************************************************* * Render ******************************************************************************/ + unsafe fn is_file_size_okay(mut msg: *const dc_msg_t) -> libc::c_int { let mut file_size_okay: libc::c_int = 1i32; let mut pathNfilename: *mut libc::c_char = @@ -1309,5 +1325,6 @@ unsafe fn is_file_size_okay(mut msg: *const dc_msg_t) -> libc::c_int { file_size_okay = 0i32 } free(pathNfilename as *mut libc::c_void); - return file_size_okay; + + file_size_okay } diff --git a/src/dc_mimeparser.rs b/src/dc_mimeparser.rs index 7b1ad3038..f4617fed8 100644 --- a/src/dc_mimeparser.rs +++ b/src/dc_mimeparser.rs @@ -1,4 +1,12 @@ -use libc; +use mmime::charconv::*; +use mmime::mailimf::*; +use mmime::mailimf_types::*; +use mmime::mailmime::*; +use mmime::mailmime_content::*; +use mmime::mailmime_disposition::*; +use mmime::mailmime_types::*; +use mmime::mmapstring::*; +use mmime::other::*; use crate::dc_contact::*; use crate::dc_context::dc_context_t; @@ -35,7 +43,7 @@ pub struct dc_mimepart_t { */ #[derive(Copy, Clone)] #[repr(C)] -pub struct dc_mimeparser_t { +pub struct dc_mimeparser_t<'a> { pub parts: *mut carray, pub mimeroot: *mut mailmime, pub header: dc_hash_t, @@ -47,7 +55,7 @@ pub struct dc_mimeparser_t { pub e2ee_helper: *mut dc_e2ee_helper_t, pub blobdir: *const libc::c_char, pub is_forwarded: libc::c_int, - pub context: *mut dc_context_t, + pub context: &'a dc_context_t, pub reports: *mut carray, pub is_system_message: libc::c_int, pub location_kml: *mut dc_kml_t, @@ -58,13 +66,15 @@ pub struct dc_mimeparser_t { pub unsafe fn dc_no_compound_msgs() { s_generate_compound_msgs = 0i32; } + // deprecated: flag to switch generation of compound messages on and off. static mut s_generate_compound_msgs: libc::c_int = 1i32; + pub unsafe fn dc_mimeparser_new( - mut blobdir: *const libc::c_char, - mut context: *mut dc_context_t, + blobdir: *const libc::c_char, + context: &dc_context_t, ) -> *mut dc_mimeparser_t { - let mut mimeparser: *mut dc_mimeparser_t = 0 as *mut dc_mimeparser_t; + let mut mimeparser: *mut dc_mimeparser_t; mimeparser = calloc(1, ::std::mem::size_of::()) as *mut dc_mimeparser_t; if mimeparser.is_null() { exit(30i32); @@ -76,8 +86,10 @@ pub unsafe fn dc_mimeparser_new( (*mimeparser).e2ee_helper = calloc(1, ::std::mem::size_of::()) as *mut dc_e2ee_helper_t; dc_hash_init(&mut (*mimeparser).header, 3i32, 0i32); - return mimeparser; + + mimeparser } + pub unsafe fn dc_mimeparser_unref(mut mimeparser: *mut dc_mimeparser_t) { if mimeparser.is_null() { return; @@ -98,7 +110,7 @@ pub unsafe fn dc_mimeparser_empty(mut mimeparser: *mut dc_mimeparser_t) { return; } if !(*mimeparser).parts.is_null() { - let mut i: libc::c_int = 0; + let mut i: libc::c_int; let mut cnt: libc::c_int = carray_count((*mimeparser).parts) as libc::c_int; i = 0i32; while i < cnt { @@ -150,14 +162,15 @@ unsafe fn dc_mimepart_unref(mut mimepart: *mut dc_mimepart_t) { dc_param_unref((*mimepart).param); free(mimepart as *mut libc::c_void); } + pub unsafe fn dc_mimeparser_parse( mut mimeparser: *mut dc_mimeparser_t, mut body_not_terminated: *const libc::c_char, mut body_bytes: size_t, ) { - let mut r: libc::c_int = 0i32; + let mut r: libc::c_int; let mut index: size_t = 0i32 as size_t; - let mut optional_field: *mut mailimf_optional_field = 0 as *mut mailimf_optional_field; + let mut optional_field: *mut mailimf_optional_field; dc_mimeparser_empty(mimeparser); r = mailmime_parse( body_not_terminated, @@ -194,7 +207,7 @@ pub unsafe fn dc_mimeparser_parse( ) .is_null() { - let mut i: libc::c_int = 0; + let mut i: libc::c_int; let mut has_setup_file: libc::c_int = 0i32; i = 0i32; while (i as libc::c_uint) < carray_count((*mimeparser).parts) { @@ -303,7 +316,7 @@ pub unsafe fn dc_mimeparser_parse( } dc_trim(subj); if 0 != *subj.offset(0isize) { - let mut i_0: libc::c_int = 0; + let mut i_0: libc::c_int; let mut icnt: libc::c_int = carray_count((*mimeparser).parts) as libc::c_int; i_0 = 0i32; while i_0 < icnt { @@ -328,7 +341,7 @@ pub unsafe fn dc_mimeparser_parse( } } if 0 != (*mimeparser).is_forwarded { - let mut i_1: libc::c_int = 0; + let mut i_1: libc::c_int; let mut icnt_0: libc::c_int = carray_count((*mimeparser).parts) as libc::c_int; i_1 = 0i32; while i_1 < icnt_0 { @@ -430,24 +443,26 @@ pub unsafe fn dc_mimeparser_parse( ); }; } -/* ****************************************************************************** + +/******************************************************************************* * a MIME part ******************************************************************************/ unsafe fn dc_mimepart_new() -> *mut dc_mimepart_t { - let mut mimepart: *mut dc_mimepart_t = 0 as *mut dc_mimepart_t; + let mut mimepart: *mut dc_mimepart_t; mimepart = calloc(1, ::std::mem::size_of::()) as *mut dc_mimepart_t; if mimepart.is_null() { exit(33i32); } (*mimepart).type_0 = 0i32; (*mimepart).param = dc_param_new(); - return mimepart; + mimepart } + pub unsafe fn dc_mimeparser_get_last_nonmeta( mut mimeparser: *mut dc_mimeparser_t, ) -> *mut dc_mimepart_t { if !mimeparser.is_null() && !(*mimeparser).parts.is_null() { - let mut i: libc::c_int = 0; + let mut i: libc::c_int; let mut icnt: libc::c_int = carray_count((*mimeparser).parts) as libc::c_int; i = icnt - 1i32; while i >= 0i32 { @@ -459,8 +474,10 @@ pub unsafe fn dc_mimeparser_get_last_nonmeta( i -= 1 } } - return 0 as *mut dc_mimepart_t; + + 0 as *mut dc_mimepart_t } + /*the result must be freed*/ pub unsafe fn mailimf_find_first_addr( mut mb_list: *const mailimf_mailbox_list, @@ -481,22 +498,25 @@ pub unsafe fn mailimf_find_first_addr( cur = if !cur.is_null() { (*cur).next } else { - 0 as *mut clistcell_s + 0 as *mut clistcell } } - return 0 as *mut libc::c_char; + + 0 as *mut libc::c_char } + /* the following functions can be used only after a call to dc_mimeparser_parse() */ pub unsafe fn dc_mimeparser_lookup_field( mut mimeparser: *mut dc_mimeparser_t, mut field_name: *const libc::c_char, ) -> *mut mailimf_field { - return dc_hash_find( + dc_hash_find( &mut (*mimeparser).header, field_name as *const libc::c_void, strlen(field_name) as libc::c_int, - ) as *mut mailimf_field; + ) as *mut mailimf_field } + pub unsafe fn dc_mimeparser_lookup_optional_field( mut mimeparser: *mut dc_mimeparser_t, mut field_name: *const libc::c_char, @@ -509,14 +529,16 @@ pub unsafe fn dc_mimeparser_lookup_optional_field( if !field.is_null() && (*field).fld_type == MAILIMF_FIELD_OPTIONAL_FIELD as libc::c_int { return (*field).fld_data.fld_optional_field; } - return 0 as *mut mailimf_optional_field; + + 0 as *mut mailimf_optional_field } + unsafe fn dc_mimeparser_parse_mime_recursive( mut mimeparser: *mut dc_mimeparser_t, mut mime: *mut mailmime, ) -> libc::c_int { let mut any_part_added: libc::c_int = 0i32; - let mut cur: *mut clistiter = 0 as *mut clistiter; + let mut cur: *mut clistiter; if mimeparser.is_null() || mime.is_null() { return 0i32; } @@ -577,6 +599,7 @@ unsafe fn dc_mimeparser_parse_mime_recursive( } } match (*mime).mm_type { + // TODO match on enums /rtn 1 => any_part_added = dc_mimeparser_add_single_part_if_known(mimeparser, mime), 2 => { match mailmime_get_mime_type(mime, 0 as *mut libc::c_int, 0 as *mut *mut libc::c_char) { @@ -602,7 +625,7 @@ unsafe fn dc_mimeparser_parse_mime_recursive( cur = if !cur.is_null() { (*cur).next } else { - 0 as *mut clistcell_s + 0 as *mut clistcell } } } @@ -628,7 +651,7 @@ unsafe fn dc_mimeparser_parse_mime_recursive( cur = if !cur.is_null() { (*cur).next } else { - 0 as *mut clistcell_s + 0 as *mut clistcell } } } @@ -651,7 +674,7 @@ unsafe fn dc_mimeparser_parse_mime_recursive( cur = if !cur.is_null() { (*cur).next } else { - 0 as *mut clistcell_s + 0 as *mut clistcell } } } @@ -762,7 +785,7 @@ unsafe fn dc_mimeparser_parse_mime_recursive( cur = if !cur.is_null() { (*cur).next } else { - 0 as *mut clistcell_s + 0 as *mut clistcell } } if plain_cnt == 1i32 && html_cnt == 1i32 { @@ -788,7 +811,7 @@ unsafe fn dc_mimeparser_parse_mime_recursive( cur = if !cur.is_null() { (*cur).next } else { - 0 as *mut clistcell_s + 0 as *mut clistcell } } } @@ -812,13 +835,11 @@ unsafe fn dc_mimeparser_parse_mime_recursive( } _ => {} } - return any_part_added; + + any_part_added } -unsafe fn hash_header( - out: *mut dc_hash_t, - in_0: *const mailimf_fields, - _context: *mut dc_context_t, -) { + +unsafe fn hash_header(out: *mut dc_hash_t, in_0: *const mailimf_fields, _context: &dc_context_t) { if in_0.is_null() { return; } @@ -830,6 +851,7 @@ unsafe fn hash_header( 0 as *mut libc::c_void }) as *mut mailimf_field; let mut key: *const libc::c_char = 0 as *const libc::c_char; + // TODO match on enums /rtn match (*field).fld_type { 1 => key = b"Return-Path\x00" as *const u8 as *const libc::c_char, 9 => key = b"Date\x00" as *const u8 as *const libc::c_char, @@ -879,10 +901,11 @@ unsafe fn hash_header( cur1 = if !cur1.is_null() { (*cur1).next } else { - 0 as *mut clistcell_s + 0 as *mut clistcell } } } + unsafe fn mailmime_get_mime_type( mut mime: *mut mailmime, mut msg_type: *mut libc::c_int, @@ -897,6 +920,7 @@ unsafe fn mailmime_get_mime_type( if c.is_null() || (*c).ct_type.is_null() { return 0i32; } + // TODO match on enums /rtn match (*(*c).ct_type).tp_type { 1 => match (*(*(*c).ct_type).tp_data.tp_discrete_type).dt_type { 1 => { @@ -1051,8 +1075,10 @@ unsafe fn mailmime_get_mime_type( } _ => {} } - return 0i32; + + 0 } + unsafe fn reconcat_mime( mut raw_mime: *mut *mut libc::c_char, mut type_0: *const libc::c_char, @@ -1074,6 +1100,7 @@ unsafe fn reconcat_mime( ) }; } + unsafe fn mailmime_is_attachment_disposition(mut mime: *mut mailmime) -> libc::c_int { if !(*mime).mm_mime_fields.is_null() { let mut cur: *mut clistiter = (*(*(*mime).mm_mime_fields).fld_list).first; @@ -1097,12 +1124,14 @@ unsafe fn mailmime_is_attachment_disposition(mut mime: *mut mailmime) -> libc::c cur = if !cur.is_null() { (*cur).next } else { - 0 as *mut clistcell_s + 0 as *mut clistcell } } } - return 0i32; + + 0 } + /* low-level-tools for working with mailmime structures directly */ pub unsafe fn mailmime_find_ct_parameter( mut mime: *mut mailmime, @@ -1115,7 +1144,7 @@ pub unsafe fn mailmime_find_ct_parameter( { return 0 as *mut mailmime_parameter; } - let mut cur: *mut clistiter = 0 as *mut clistiter; + let mut cur: *mut clistiter; cur = (*(*(*mime).mm_content_type).ct_parameters).first; while !cur.is_null() { let mut param: *mut mailmime_parameter = (if !cur.is_null() { @@ -1131,11 +1160,13 @@ pub unsafe fn mailmime_find_ct_parameter( cur = if !cur.is_null() { (*cur).next } else { - 0 as *mut clistcell_s + 0 as *mut clistcell } } - return 0 as *mut mailmime_parameter; + + 0 as *mut mailmime_parameter } + unsafe fn dc_mimeparser_add_single_part_if_known( mut mimeparser: *mut dc_mimeparser_t, mut mime: *mut mailmime, @@ -1143,8 +1174,8 @@ unsafe fn dc_mimeparser_add_single_part_if_known( let mut current_block: u64; let mut part: *mut dc_mimepart_t = 0 as *mut dc_mimepart_t; let mut old_part_count: libc::c_int = carray_count((*mimeparser).parts) as libc::c_int; - let mut mime_type: libc::c_int = 0; - let mut mime_data: *mut mailmime_data = 0 as *mut mailmime_data; + let mut mime_type: libc::c_int; + let mut mime_data: *mut mailmime_data; let mut file_suffix: *mut libc::c_char = 0 as *mut libc::c_char; let mut desired_filename: *mut libc::c_char = 0 as *mut libc::c_char; let mut msg_type: libc::c_int = 0i32; @@ -1187,6 +1218,7 @@ unsafe fn dc_mimeparser_add_single_part_if_known( } else { current_block = 13797916685926291137; } + // TODO match on enums /rtn match current_block { 8795901732489102124 => {} _ => { @@ -1346,7 +1378,7 @@ unsafe fn dc_mimeparser_add_single_part_if_known( cur2 = if !cur2.is_null() { (*cur2).next } else { - 0 as *mut clistcell_s + 0 as *mut clistcell } } } @@ -1355,7 +1387,7 @@ unsafe fn dc_mimeparser_add_single_part_if_known( cur1 = if !cur1.is_null() { (*cur1).next } else { - 0 as *mut clistcell_s + 0 as *mut clistcell } } } @@ -1478,6 +1510,7 @@ unsafe fn dc_mimeparser_add_single_part_if_known( 0i32 }; } + unsafe fn do_add_single_file_part( mut parser: *mut dc_mimeparser_t, mut msg_type: libc::c_int, @@ -1488,7 +1521,7 @@ unsafe fn do_add_single_file_part( mut desired_filename: *const libc::c_char, ) { let mut part: *mut dc_mimepart_t = 0 as *mut dc_mimepart_t; - let mut pathNfilename: *mut libc::c_char = 0 as *mut libc::c_char; + let mut pathNfilename: *mut libc::c_char; /* create a free file name to use */ pathNfilename = dc_get_fine_pathNfilename( (*parser).context, @@ -1530,6 +1563,7 @@ unsafe fn do_add_single_file_part( free(pathNfilename as *mut libc::c_void); dc_mimepart_unref(part); } + unsafe fn do_add_single_part(mut parser: *mut dc_mimeparser_t, mut part: *mut dc_mimepart_t) { if 0 != (*(*parser).e2ee_helper).encrypted && (*(*(*parser).e2ee_helper).signatures).count > 0i32 @@ -1544,6 +1578,8 @@ unsafe fn do_add_single_part(mut parser: *mut dc_mimeparser_t, mut part: *mut dc 0 as *mut libc::c_uint, ); } + +// TODO should return bool /rtn pub unsafe fn mailmime_transfer_decode( mut mime: *mut mailmime, mut ret_decoded_data: *mut *const libc::c_char, @@ -1551,9 +1587,9 @@ pub unsafe fn mailmime_transfer_decode( mut ret_to_mmap_string_unref: *mut *mut libc::c_char, ) -> libc::c_int { let mut mime_transfer_encoding: libc::c_int = MAILMIME_MECHANISM_BINARY as libc::c_int; - let mut mime_data: *mut mailmime_data = 0 as *mut mailmime_data; + let mut mime_data: *mut mailmime_data; /* must not be free()'d */ - let mut decoded_data: *const libc::c_char = 0 as *const libc::c_char; + let mut decoded_data: *const libc::c_char; let mut decoded_data_bytes: size_t = 0i32 as size_t; /* mmap_string_unref()'d if set */ let mut transfer_decoding_buffer: *mut libc::c_char = 0 as *mut libc::c_char; @@ -1569,7 +1605,7 @@ pub unsafe fn mailmime_transfer_decode( } mime_data = (*mime).mm_data.mm_single; if !(*mime).mm_mime_fields.is_null() { - let mut cur: *mut clistiter = 0 as *mut clistiter; + let mut cur: *mut clistiter; cur = (*(*(*mime).mm_mime_fields).fld_list).first; while !cur.is_null() { let mut field: *mut mailmime_field = (if !cur.is_null() { @@ -1587,7 +1623,7 @@ pub unsafe fn mailmime_transfer_decode( cur = if !cur.is_null() { (*cur).next } else { - 0 as *mut clistcell_s + 0 as *mut clistcell } } } @@ -1602,7 +1638,7 @@ pub unsafe fn mailmime_transfer_decode( return 0i32; } } else { - let mut r: libc::c_int = 0; + let mut r: libc::c_int; let mut current_index: size_t = 0i32 as size_t; r = mailmime_part_parse( (*mime_data).dt_data.dt_text.dt_data, @@ -1623,8 +1659,11 @@ pub unsafe fn mailmime_transfer_decode( *ret_decoded_data = decoded_data; *ret_decoded_data_bytes = decoded_data_bytes; *ret_to_mmap_string_unref = transfer_decoding_buffer; - return 1i32; + + 1 } + +// TODO should return bool /rtn pub unsafe fn dc_mimeparser_is_mailinglist_message( mut mimeparser: *mut dc_mimeparser_t, ) -> libc::c_int { @@ -1656,15 +1695,17 @@ pub unsafe fn dc_mimeparser_is_mailinglist_message( return 1i32; } } - return 0i32; + + 0 } + pub unsafe fn dc_mimeparser_sender_equals_recipient( mut mimeparser: *mut dc_mimeparser_t, ) -> libc::c_int { let mut sender_equals_recipient: libc::c_int = 0i32; - let mut fld: *const mailimf_field = 0 as *const mailimf_field; + let mut fld: *const mailimf_field; let mut fld_from: *const mailimf_from = 0 as *const mailimf_from; - let mut mb: *mut mailimf_mailbox = 0 as *mut mailimf_mailbox; + let mut mb: *mut mailimf_mailbox; let mut from_addr_norm: *mut libc::c_char = 0 as *mut libc::c_char; let mut recipients: *mut dc_hash_t = 0 as *mut dc_hash_t; if !(mimeparser.is_null() || (*mimeparser).header_root.is_null()) { @@ -1704,14 +1745,16 @@ pub unsafe fn dc_mimeparser_sender_equals_recipient( dc_hash_clear(recipients); free(recipients as *mut libc::c_void); free(from_addr_norm as *mut libc::c_void); - return sender_equals_recipient; + + sender_equals_recipient } + pub unsafe fn mailimf_get_recipients(mut imffields: *mut mailimf_fields) -> *mut dc_hash_t { /* the returned value must be dc_hash_clear()'d and free()'d. returned addresses are normalized. */ let mut recipients: *mut dc_hash_t = malloc(::std::mem::size_of::()) as *mut dc_hash_t; dc_hash_init(recipients, 3i32, 1i32); - let mut cur1: *mut clistiter = 0 as *mut clistiter; + let mut cur1: *mut clistiter; cur1 = (*(*imffields).fld_list).first; while !cur1.is_null() { let mut fld: *mut mailimf_field = (if !cur1.is_null() { @@ -1719,9 +1762,10 @@ pub unsafe fn mailimf_get_recipients(mut imffields: *mut mailimf_fields) -> *mut } else { 0 as *mut libc::c_void }) as *mut mailimf_field; - let mut fld_to: *mut mailimf_to = 0 as *mut mailimf_to; - let mut fld_cc: *mut mailimf_cc = 0 as *mut mailimf_cc; + let mut fld_to: *mut mailimf_to; + let mut fld_cc: *mut mailimf_cc; let mut addr_list: *mut mailimf_address_list = 0 as *mut mailimf_address_list; + // TODO match on enums /rtn match (*fld).fld_type { 13 => { fld_to = (*fld).fld_data.fld_to; @@ -1738,7 +1782,7 @@ pub unsafe fn mailimf_get_recipients(mut imffields: *mut mailimf_fields) -> *mut _ => {} } if !addr_list.is_null() { - let mut cur2: *mut clistiter = 0 as *mut clistiter; + let mut cur2: *mut clistiter; cur2 = (*(*addr_list).ad_list).first; while !cur2.is_null() { let mut adr: *mut mailimf_address = (if !cur2.is_null() { @@ -1752,7 +1796,7 @@ pub unsafe fn mailimf_get_recipients(mut imffields: *mut mailimf_fields) -> *mut } else if (*adr).ad_type == MAILIMF_ADDRESS_GROUP as libc::c_int { let mut group: *mut mailimf_group = (*adr).ad_data.ad_group; if !group.is_null() && !(*group).grp_mb_list.is_null() { - let mut cur3: *mut clistiter = 0 as *mut clistiter; + let mut cur3: *mut clistiter; cur3 = (*(*(*group).grp_mb_list).mb_list).first; while !cur3.is_null() { mailimf_get_recipients__add_addr( @@ -1766,7 +1810,7 @@ pub unsafe fn mailimf_get_recipients(mut imffields: *mut mailimf_fields) -> *mut cur3 = if !cur3.is_null() { (*cur3).next } else { - 0 as *mut clistcell_s + 0 as *mut clistcell } } } @@ -1775,18 +1819,20 @@ pub unsafe fn mailimf_get_recipients(mut imffields: *mut mailimf_fields) -> *mut cur2 = if !cur2.is_null() { (*cur2).next } else { - 0 as *mut clistcell_s + 0 as *mut clistcell } } } cur1 = if !cur1.is_null() { (*cur1).next } else { - 0 as *mut clistcell_s + 0 as *mut clistcell } } - return recipients; + + recipients } + /* ****************************************************************************** * debug output ******************************************************************************/ @@ -1809,6 +1855,7 @@ unsafe fn mailimf_get_recipients__add_addr( free(addr_norm as *mut libc::c_void); }; } + /*the result is a pointer to mime, must not be freed*/ pub unsafe fn mailimf_find_field( mut header: *mut mailimf_fields, @@ -1832,17 +1879,19 @@ pub unsafe fn mailimf_find_field( cur1 = if !cur1.is_null() { (*cur1).next } else { - 0 as *mut clistcell_s + 0 as *mut clistcell } } - return 0 as *mut mailimf_field; + + 0 as *mut mailimf_field } + pub unsafe fn dc_mimeparser_repl_msg_by_error( mut mimeparser: *mut dc_mimeparser_t, mut error_msg: *const libc::c_char, ) { - let mut part: *mut dc_mimepart_t = 0 as *mut dc_mimepart_t; - let mut i: libc::c_int = 0i32; + let mut part: *mut dc_mimepart_t; + let mut i: libc::c_int; if mimeparser.is_null() || (*mimeparser).parts.is_null() || carray_count((*mimeparser).parts) <= 0i32 as libc::c_uint @@ -1863,11 +1912,13 @@ pub unsafe fn dc_mimeparser_repl_msg_by_error( } carray_set_size((*mimeparser).parts, 1i32 as libc::c_uint); } + /*the result is a pointer to mime, must not be freed*/ pub unsafe fn mailmime_find_mailimf_fields(mut mime: *mut mailmime) -> *mut mailimf_fields { if mime.is_null() { return 0 as *mut mailimf_fields; } + // TODO match on enums match (*mime).mm_type { 2 => { let mut cur: *mut clistiter = (*(*mime).mm_data.mm_multipart.mm_mp_list).first; @@ -1885,15 +1936,17 @@ pub unsafe fn mailmime_find_mailimf_fields(mut mime: *mut mailmime) -> *mut mail cur = if !cur.is_null() { (*cur).next } else { - 0 as *mut clistcell_s + 0 as *mut clistcell } } } 3 => return (*mime).mm_data.mm_message.mm_fields, _ => {} } - return 0 as *mut mailimf_fields; + + 0 as *mut mailimf_fields } + pub unsafe fn mailimf_find_optional_field( mut header: *mut mailimf_fields, mut wanted_fld_name: *const libc::c_char, @@ -1922,8 +1975,9 @@ pub unsafe fn mailimf_find_optional_field( cur1 = if !cur1.is_null() { (*cur1).next } else { - 0 as *mut clistcell_s + 0 as *mut clistcell } } - return 0 as *mut mailimf_optional_field; + + 0 as *mut mailimf_optional_field } diff --git a/src/dc_move.rs b/src/dc_move.rs index bf3e29609..384af8116 100644 --- a/src/dc_move.rs +++ b/src/dc_move.rs @@ -1,5 +1,4 @@ -use libc; - +use crate::constants::*; use crate::dc_context::*; use crate::dc_job::*; use crate::dc_msg::*; @@ -7,7 +6,7 @@ use crate::dc_sqlite3::*; use crate::types::*; pub unsafe fn dc_do_heuristics_moves( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut folder: *const libc::c_char, mut msg_id: uint32_t, ) { @@ -15,7 +14,8 @@ pub unsafe fn dc_do_heuristics_moves( let mut msg: *mut dc_msg_t = 0 as *mut dc_msg_t; let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; if !(dc_sqlite3_get_config_int( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"mvbox_move\x00" as *const u8 as *const libc::c_char, 1i32, ) == 0i32) diff --git a/src/dc_msg.rs b/src/dc_msg.rs index 8df57178e..a3d0ec332 100644 --- a/src/dc_msg.rs +++ b/src/dc_msg.rs @@ -1,5 +1,3 @@ -use libc; - use crate::constants::Event; use crate::dc_chat::*; use crate::dc_contact::*; @@ -20,7 +18,7 @@ use crate::x::*; /* * the structure behind dc_msg_t */ #[derive(Copy, Clone)] #[repr(C)] -pub struct dc_msg_t { +pub struct dc_msg_t<'a> { pub magic: uint32_t, pub id: uint32_t, pub from_id: uint32_t, @@ -34,7 +32,7 @@ pub struct dc_msg_t { pub timestamp_sent: time_t, pub timestamp_rcvd: time_t, pub text: *mut libc::c_char, - pub context: *mut dc_context_t, + pub context: &'a dc_context_t, pub rfc724_mid: *mut libc::c_char, pub in_reply_to: *mut libc::c_char, pub server_folder: *mut libc::c_char, @@ -48,18 +46,18 @@ pub struct dc_msg_t { // handle messages pub unsafe fn dc_get_msg_info( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut msg_id: uint32_t, ) -> *mut libc::c_char { - let mut e2ee_errors: libc::c_int = 0; - let mut w: libc::c_int = 0; - let mut h: libc::c_int = 0; - let mut duration: libc::c_int = 0; - let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; + let mut e2ee_errors: libc::c_int; + let mut w: libc::c_int; + let mut h: libc::c_int; + let mut duration: libc::c_int; + let mut stmt: *mut sqlite3_stmt; let mut msg: *mut dc_msg_t = dc_msg_new_untyped(context); let mut contact_from: *mut dc_contact_t = dc_contact_new(context); let mut rawtxt: *mut libc::c_char = 0 as *mut libc::c_char; - let mut p: *mut libc::c_char = 0 as *mut libc::c_char; + let mut p: *mut libc::c_char; let mut ret: dc_strbuilder_t = dc_strbuilder_t { buf: 0 as *mut libc::c_char, allocated: 0, @@ -67,234 +65,233 @@ pub unsafe fn dc_get_msg_info( eos: 0 as *mut libc::c_char, }; dc_strbuilder_init(&mut ret, 0i32); - if !(context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint) { - dc_msg_load_from_db(msg, context, msg_id); - dc_contact_load_from_db(contact_from, (*context).sql, (*msg).from_id); - stmt = dc_sqlite3_prepare( - (*context).sql, - b"SELECT txt_raw FROM msgs WHERE id=?;\x00" as *const u8 as *const libc::c_char, + + dc_msg_load_from_db(msg, context, msg_id); + dc_contact_load_from_db( + contact_from, + &context.sql.clone().read().unwrap(), + (*msg).from_id, + ); + stmt = dc_sqlite3_prepare( + context, + &context.sql.clone().read().unwrap(), + b"SELECT txt_raw FROM msgs WHERE id=?;\x00" as *const u8 as *const libc::c_char, + ); + sqlite3_bind_int(stmt, 1i32, msg_id as libc::c_int); + if sqlite3_step(stmt) != 100i32 { + p = dc_mprintf( + b"Cannot load message #%i.\x00" as *const u8 as *const libc::c_char, + msg_id as libc::c_int, ); - sqlite3_bind_int(stmt, 1i32, msg_id as libc::c_int); - if sqlite3_step(stmt) != 100i32 { - p = dc_mprintf( - b"Cannot load message #%i.\x00" as *const u8 as *const libc::c_char, - msg_id as libc::c_int, + dc_strbuilder_cat(&mut ret, p); + free(p as *mut libc::c_void); + } else { + rawtxt = dc_strdup(sqlite3_column_text(stmt, 0i32) as *mut libc::c_char); + sqlite3_finalize(stmt); + stmt = 0 as *mut sqlite3_stmt; + dc_trim(rawtxt); + dc_truncate_str(rawtxt, 100000i32); + dc_strbuilder_cat(&mut ret, b"Sent: \x00" as *const u8 as *const libc::c_char); + p = dc_timestamp_to_str(dc_msg_get_timestamp(msg)); + dc_strbuilder_cat(&mut ret, p); + free(p as *mut libc::c_void); + p = dc_contact_get_name_n_addr(contact_from); + dc_strbuilder_catf( + &mut ret as *mut dc_strbuilder_t, + b" by %s\x00" as *const u8 as *const libc::c_char, + p, + ); + free(p as *mut libc::c_void); + dc_strbuilder_cat(&mut ret, b"\n\x00" as *const u8 as *const libc::c_char); + if (*msg).from_id != 1i32 as libc::c_uint { + dc_strbuilder_cat( + &mut ret, + b"Received: \x00" as *const u8 as *const libc::c_char, ); + p = dc_timestamp_to_str(if 0 != (*msg).timestamp_rcvd { + (*msg).timestamp_rcvd + } else { + (*msg).timestamp_sort + }); dc_strbuilder_cat(&mut ret, p); free(p as *mut libc::c_void); - } else { - rawtxt = dc_strdup(sqlite3_column_text(stmt, 0i32) as *mut libc::c_char); + dc_strbuilder_cat(&mut ret, b"\n\x00" as *const u8 as *const libc::c_char); + } + if !((*msg).from_id == 2i32 as libc::c_uint || (*msg).to_id == 2i32 as libc::c_uint) { + // device-internal message, no further details needed + stmt = dc_sqlite3_prepare( + context, + &context.sql.clone().read().unwrap(), + b"SELECT contact_id, timestamp_sent FROM msgs_mdns WHERE msg_id=?;\x00" as *const u8 + as *const libc::c_char, + ); + sqlite3_bind_int(stmt, 1i32, msg_id as libc::c_int); + while sqlite3_step(stmt) == 100i32 { + dc_strbuilder_cat(&mut ret, b"Read: \x00" as *const u8 as *const libc::c_char); + p = dc_timestamp_to_str(sqlite3_column_int64(stmt, 1i32) as time_t); + dc_strbuilder_cat(&mut ret, p); + free(p as *mut libc::c_void); + dc_strbuilder_cat(&mut ret, b" by \x00" as *const u8 as *const libc::c_char); + let mut contact: *mut dc_contact_t = dc_contact_new(context); + dc_contact_load_from_db( + contact, + &context.sql.clone().read().unwrap(), + sqlite3_column_int64(stmt, 0i32) as uint32_t, + ); + p = dc_contact_get_name_n_addr(contact); + dc_strbuilder_cat(&mut ret, p); + free(p as *mut libc::c_void); + dc_contact_unref(contact); + dc_strbuilder_cat(&mut ret, b"\n\x00" as *const u8 as *const libc::c_char); + } sqlite3_finalize(stmt); stmt = 0 as *mut sqlite3_stmt; - dc_trim(rawtxt); - dc_truncate_str(rawtxt, 100000i32); - dc_strbuilder_cat(&mut ret, b"Sent: \x00" as *const u8 as *const libc::c_char); - p = dc_timestamp_to_str(dc_msg_get_timestamp(msg)); - dc_strbuilder_cat(&mut ret, p); - free(p as *mut libc::c_void); - p = dc_contact_get_name_n_addr(contact_from); + match (*msg).state { + 10 => p = dc_strdup(b"Fresh\x00" as *const u8 as *const libc::c_char), + 13 => p = dc_strdup(b"Noticed\x00" as *const u8 as *const libc::c_char), + 16 => p = dc_strdup(b"Seen\x00" as *const u8 as *const libc::c_char), + 26 => p = dc_strdup(b"Delivered\x00" as *const u8 as *const libc::c_char), + 24 => p = dc_strdup(b"Failed\x00" as *const u8 as *const libc::c_char), + 28 => p = dc_strdup(b"Read\x00" as *const u8 as *const libc::c_char), + 20 => p = dc_strdup(b"Pending\x00" as *const u8 as *const libc::c_char), + 18 => p = dc_strdup(b"Preparing\x00" as *const u8 as *const libc::c_char), + _ => p = dc_mprintf(b"%i\x00" as *const u8 as *const libc::c_char, (*msg).state), + } dc_strbuilder_catf( &mut ret as *mut dc_strbuilder_t, - b" by %s\x00" as *const u8 as *const libc::c_char, + b"State: %s\x00" as *const u8 as *const libc::c_char, p, ); free(p as *mut libc::c_void); - dc_strbuilder_cat(&mut ret, b"\n\x00" as *const u8 as *const libc::c_char); - if (*msg).from_id != 1i32 as libc::c_uint { + if 0 != dc_msg_has_location(msg) { dc_strbuilder_cat( &mut ret, - b"Received: \x00" as *const u8 as *const libc::c_char, + b", Location sent\x00" as *const u8 as *const libc::c_char, ); - p = dc_timestamp_to_str(if 0 != (*msg).timestamp_rcvd { - (*msg).timestamp_rcvd - } else { - (*msg).timestamp_sort - }); - dc_strbuilder_cat(&mut ret, p); - free(p as *mut libc::c_void); - dc_strbuilder_cat(&mut ret, b"\n\x00" as *const u8 as *const libc::c_char); } - if !((*msg).from_id == 2i32 as libc::c_uint || (*msg).to_id == 2i32 as libc::c_uint) { - // device-internal message, no further details needed - stmt = dc_sqlite3_prepare( - (*context).sql, - b"SELECT contact_id, timestamp_sent FROM msgs_mdns WHERE msg_id=?;\x00" - as *const u8 as *const libc::c_char, - ); - sqlite3_bind_int(stmt, 1i32, msg_id as libc::c_int); - while sqlite3_step(stmt) == 100i32 { - dc_strbuilder_cat(&mut ret, b"Read: \x00" as *const u8 as *const libc::c_char); - p = dc_timestamp_to_str(sqlite3_column_int64(stmt, 1i32) as time_t); - dc_strbuilder_cat(&mut ret, p); - free(p as *mut libc::c_void); - dc_strbuilder_cat(&mut ret, b" by \x00" as *const u8 as *const libc::c_char); - let mut contact: *mut dc_contact_t = dc_contact_new(context); - dc_contact_load_from_db( - contact, - (*context).sql, - sqlite3_column_int64(stmt, 0i32) as uint32_t, - ); - p = dc_contact_get_name_n_addr(contact); - dc_strbuilder_cat(&mut ret, p); - free(p as *mut libc::c_void); - dc_contact_unref(contact); - dc_strbuilder_cat(&mut ret, b"\n\x00" as *const u8 as *const libc::c_char); + p = 0 as *mut libc::c_char; + e2ee_errors = dc_param_get_int((*msg).param, 'e' as i32, 0i32); + if 0 != e2ee_errors { + if 0 != e2ee_errors & 0x2i32 { + p = dc_strdup( + b"Encrypted, no valid signature\x00" as *const u8 as *const libc::c_char, + ) } - sqlite3_finalize(stmt); - stmt = 0 as *mut sqlite3_stmt; - p = 0 as *mut libc::c_char; - match (*msg).state { - 10 => p = dc_strdup(b"Fresh\x00" as *const u8 as *const libc::c_char), - 13 => p = dc_strdup(b"Noticed\x00" as *const u8 as *const libc::c_char), - 16 => p = dc_strdup(b"Seen\x00" as *const u8 as *const libc::c_char), - 26 => p = dc_strdup(b"Delivered\x00" as *const u8 as *const libc::c_char), - 24 => p = dc_strdup(b"Failed\x00" as *const u8 as *const libc::c_char), - 28 => p = dc_strdup(b"Read\x00" as *const u8 as *const libc::c_char), - 20 => p = dc_strdup(b"Pending\x00" as *const u8 as *const libc::c_char), - 18 => p = dc_strdup(b"Preparing\x00" as *const u8 as *const libc::c_char), + } else if 0 != dc_param_get_int((*msg).param, 'c' as i32, 0i32) { + p = dc_strdup(b"Encrypted\x00" as *const u8 as *const libc::c_char) + } + if !p.is_null() { + dc_strbuilder_catf( + &mut ret as *mut dc_strbuilder_t, + b", %s\x00" as *const u8 as *const libc::c_char, + p, + ); + free(p as *mut libc::c_void); + } + dc_strbuilder_cat(&mut ret, b"\n\x00" as *const u8 as *const libc::c_char); + p = dc_param_get((*msg).param, 'L' as i32, 0 as *const libc::c_char); + if !p.is_null() { + dc_strbuilder_catf( + &mut ret as *mut dc_strbuilder_t, + b"Error: %s\n\x00" as *const u8 as *const libc::c_char, + p, + ); + free(p as *mut libc::c_void); + } + p = dc_msg_get_file(msg); + if !p.is_null() && 0 != *p.offset(0isize) as libc::c_int { + dc_strbuilder_catf( + &mut ret as *mut dc_strbuilder_t, + b"\nFile: %s, %i bytes\n\x00" as *const u8 as *const libc::c_char, + p, + dc_get_filebytes(context, p) as libc::c_int, + ); + } + free(p as *mut libc::c_void); + if (*msg).type_0 != 10i32 { + match (*msg).type_0 { + 40 => p = dc_strdup(b"Audio\x00" as *const u8 as *const libc::c_char), + 60 => p = dc_strdup(b"File\x00" as *const u8 as *const libc::c_char), + 21 => p = dc_strdup(b"GIF\x00" as *const u8 as *const libc::c_char), + 20 => p = dc_strdup(b"Image\x00" as *const u8 as *const libc::c_char), + 50 => p = dc_strdup(b"Video\x00" as *const u8 as *const libc::c_char), + 41 => p = dc_strdup(b"Voice\x00" as *const u8 as *const libc::c_char), _ => { - p = dc_mprintf(b"%i\x00" as *const u8 as *const libc::c_char, (*msg).state) + p = dc_mprintf(b"%i\x00" as *const u8 as *const libc::c_char, (*msg).type_0) } } dc_strbuilder_catf( &mut ret as *mut dc_strbuilder_t, - b"State: %s\x00" as *const u8 as *const libc::c_char, + b"Type: %s\n\x00" as *const u8 as *const libc::c_char, p, ); free(p as *mut libc::c_void); - if 0 != dc_msg_has_location(msg) { - dc_strbuilder_cat( - &mut ret, - b", Location sent\x00" as *const u8 as *const libc::c_char, - ); - } - p = 0 as *mut libc::c_char; - e2ee_errors = 0; - e2ee_errors = dc_param_get_int((*msg).param, 'e' as i32, 0i32); - if 0 != e2ee_errors { - if 0 != e2ee_errors & 0x2i32 { - p = dc_strdup( - b"Encrypted, no valid signature\x00" as *const u8 - as *const libc::c_char, - ) - } - } else if 0 != dc_param_get_int((*msg).param, 'c' as i32, 0i32) { - p = dc_strdup(b"Encrypted\x00" as *const u8 as *const libc::c_char) - } - if !p.is_null() { - dc_strbuilder_catf( - &mut ret as *mut dc_strbuilder_t, - b", %s\x00" as *const u8 as *const libc::c_char, - p, - ); - free(p as *mut libc::c_void); - } - dc_strbuilder_cat(&mut ret, b"\n\x00" as *const u8 as *const libc::c_char); - p = dc_param_get((*msg).param, 'L' as i32, 0 as *const libc::c_char); - if !p.is_null() { - dc_strbuilder_catf( - &mut ret as *mut dc_strbuilder_t, - b"Error: %s\n\x00" as *const u8 as *const libc::c_char, - p, - ); - free(p as *mut libc::c_void); - } - p = dc_msg_get_file(msg); - if !p.is_null() && 0 != *p.offset(0isize) as libc::c_int { - dc_strbuilder_catf( - &mut ret as *mut dc_strbuilder_t, - b"\nFile: %s, %i bytes\n\x00" as *const u8 as *const libc::c_char, - p, - dc_get_filebytes(context, p) as libc::c_int, - ); - } + p = dc_msg_get_filemime(msg); + dc_strbuilder_catf( + &mut ret as *mut dc_strbuilder_t, + b"Mimetype: %s\n\x00" as *const u8 as *const libc::c_char, + p, + ); free(p as *mut libc::c_void); - if (*msg).type_0 != 10i32 { - p = 0 as *mut libc::c_char; - match (*msg).type_0 { - 40 => p = dc_strdup(b"Audio\x00" as *const u8 as *const libc::c_char), - 60 => p = dc_strdup(b"File\x00" as *const u8 as *const libc::c_char), - 21 => p = dc_strdup(b"GIF\x00" as *const u8 as *const libc::c_char), - 20 => p = dc_strdup(b"Image\x00" as *const u8 as *const libc::c_char), - 50 => p = dc_strdup(b"Video\x00" as *const u8 as *const libc::c_char), - 41 => p = dc_strdup(b"Voice\x00" as *const u8 as *const libc::c_char), - _ => { - p = dc_mprintf( - b"%i\x00" as *const u8 as *const libc::c_char, - (*msg).type_0, - ) - } - } - dc_strbuilder_catf( - &mut ret as *mut dc_strbuilder_t, - b"Type: %s\n\x00" as *const u8 as *const libc::c_char, - p, - ); - free(p as *mut libc::c_void); - p = dc_msg_get_filemime(msg); - dc_strbuilder_catf( - &mut ret as *mut dc_strbuilder_t, - b"Mimetype: %s\n\x00" as *const u8 as *const libc::c_char, - p, - ); - free(p as *mut libc::c_void); - } - w = dc_param_get_int((*msg).param, 'w' as i32, 0i32); - h = dc_param_get_int((*msg).param, 'h' as i32, 0i32); - if w != 0i32 || h != 0i32 { - p = dc_mprintf( - b"Dimension: %i x %i\n\x00" as *const u8 as *const libc::c_char, - w, - h, - ); - dc_strbuilder_cat(&mut ret, p); - free(p as *mut libc::c_void); - } - duration = dc_param_get_int((*msg).param, 'd' as i32, 0i32); - if duration != 0i32 { - p = dc_mprintf( - b"Duration: %i ms\n\x00" as *const u8 as *const libc::c_char, - duration, - ); - dc_strbuilder_cat(&mut ret, p); - free(p as *mut libc::c_void); - } - if !rawtxt.is_null() && 0 != *rawtxt.offset(0isize) as libc::c_int { - dc_strbuilder_cat(&mut ret, b"\n\x00" as *const u8 as *const libc::c_char); - dc_strbuilder_cat(&mut ret, rawtxt); - dc_strbuilder_cat(&mut ret, b"\n\x00" as *const u8 as *const libc::c_char); - } - if !(*msg).rfc724_mid.is_null() - && 0 != *(*msg).rfc724_mid.offset(0isize) as libc::c_int - { - dc_strbuilder_catf( - &mut ret as *mut dc_strbuilder_t, - b"\nMessage-ID: %s\x00" as *const u8 as *const libc::c_char, - (*msg).rfc724_mid, - ); - } - if !(*msg).server_folder.is_null() - && 0 != *(*msg).server_folder.offset(0isize) as libc::c_int - { - dc_strbuilder_catf( - &mut ret as *mut dc_strbuilder_t, - b"\nLast seen as: %s/%i\x00" as *const u8 as *const libc::c_char, - (*msg).server_folder, - (*msg).server_uid as libc::c_int, - ); - } + } + w = dc_param_get_int((*msg).param, 'w' as i32, 0i32); + h = dc_param_get_int((*msg).param, 'h' as i32, 0i32); + if w != 0i32 || h != 0i32 { + p = dc_mprintf( + b"Dimension: %i x %i\n\x00" as *const u8 as *const libc::c_char, + w, + h, + ); + dc_strbuilder_cat(&mut ret, p); + free(p as *mut libc::c_void); + } + duration = dc_param_get_int((*msg).param, 'd' as i32, 0i32); + if duration != 0i32 { + p = dc_mprintf( + b"Duration: %i ms\n\x00" as *const u8 as *const libc::c_char, + duration, + ); + dc_strbuilder_cat(&mut ret, p); + free(p as *mut libc::c_void); + } + if !rawtxt.is_null() && 0 != *rawtxt.offset(0isize) as libc::c_int { + dc_strbuilder_cat(&mut ret, b"\n\x00" as *const u8 as *const libc::c_char); + dc_strbuilder_cat(&mut ret, rawtxt); + dc_strbuilder_cat(&mut ret, b"\n\x00" as *const u8 as *const libc::c_char); + } + if !(*msg).rfc724_mid.is_null() && 0 != *(*msg).rfc724_mid.offset(0isize) as libc::c_int + { + dc_strbuilder_catf( + &mut ret as *mut dc_strbuilder_t, + b"\nMessage-ID: %s\x00" as *const u8 as *const libc::c_char, + (*msg).rfc724_mid, + ); + } + if !(*msg).server_folder.is_null() + && 0 != *(*msg).server_folder.offset(0isize) as libc::c_int + { + dc_strbuilder_catf( + &mut ret as *mut dc_strbuilder_t, + b"\nLast seen as: %s/%i\x00" as *const u8 as *const libc::c_char, + (*msg).server_folder, + (*msg).server_uid as libc::c_int, + ); } } } + sqlite3_finalize(stmt); dc_msg_unref(msg); dc_contact_unref(contact_from); free(rawtxt as *mut libc::c_void); - return ret.buf; + + ret.buf } -pub unsafe fn dc_msg_new_untyped(mut context: *mut dc_context_t) -> *mut dc_msg_t { - return dc_msg_new(context, 0i32); + +pub unsafe fn dc_msg_new_untyped<'a>(context: &'a dc_context_t) -> *mut dc_msg_t<'a> { + dc_msg_new(context, 0i32) } + /* * * @class dc_msg_t * @@ -305,11 +302,11 @@ pub unsafe fn dc_msg_new_untyped(mut context: *mut dc_context_t) -> *mut dc_msg_ // to check if a mail was sent, use dc_msg_is_sent() // approx. max. lenght returned by dc_msg_get_text() // approx. max. lenght returned by dc_get_msg_info() -pub unsafe fn dc_msg_new( - mut context: *mut dc_context_t, +pub unsafe fn dc_msg_new<'a>( + mut context: &'a dc_context_t, mut viewtype: libc::c_int, -) -> *mut dc_msg_t { - let mut msg: *mut dc_msg_t = 0 as *mut dc_msg_t; +) -> *mut dc_msg_t<'a> { + let mut msg: *mut dc_msg_t; msg = calloc(1, ::std::mem::size_of::()) as *mut dc_msg_t; if msg.is_null() { exit(15i32); @@ -319,8 +316,10 @@ pub unsafe fn dc_msg_new( (*msg).type_0 = viewtype; (*msg).state = 0i32; (*msg).param = dc_param_new(); - return msg; + + msg } + pub unsafe fn dc_msg_unref(mut msg: *mut dc_msg_t) { if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint { return; @@ -330,6 +329,7 @@ pub unsafe fn dc_msg_unref(mut msg: *mut dc_msg_t) { (*msg).magic = 0i32 as uint32_t; free(msg as *mut libc::c_void); } + pub unsafe fn dc_msg_empty(mut msg: *mut dc_msg_t) { if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint { return; @@ -345,6 +345,7 @@ pub unsafe fn dc_msg_empty(mut msg: *mut dc_msg_t) { dc_param_set_packed((*msg).param, 0 as *const libc::c_char); (*msg).hidden = 0i32; } + pub unsafe fn dc_msg_get_filemime(mut msg: *const dc_msg_t) -> *mut libc::c_char { let mut ret: *mut libc::c_char = 0 as *mut libc::c_char; let mut file: *mut libc::c_char = 0 as *mut libc::c_char; @@ -369,6 +370,7 @@ pub unsafe fn dc_msg_get_filemime(mut msg: *const dc_msg_t) -> *mut libc::c_char dc_strdup(0 as *const libc::c_char) }; } + pub unsafe fn dc_msg_guess_msgtype_from_suffix( mut pathNfilename: *const libc::c_char, mut ret_msgtype: *mut libc::c_int, @@ -422,6 +424,7 @@ pub unsafe fn dc_msg_guess_msgtype_from_suffix( free(suffix as *mut libc::c_void); free(dummy_buf as *mut libc::c_void); } + pub unsafe fn dc_msg_get_file(mut msg: *const dc_msg_t) -> *mut libc::c_char { let mut file_rel: *mut libc::c_char = 0 as *mut libc::c_char; let mut file_abs: *mut libc::c_char = 0 as *mut libc::c_char; @@ -448,11 +451,13 @@ pub unsafe fn dc_msg_get_file(mut msg: *const dc_msg_t) -> *mut libc::c_char { * @param msg The message object. * @return 1=Message has location bound to it, 0=No location bound to message. */ +// TODO should return bool /rtn pub unsafe fn dc_msg_has_location(mut msg: *const dc_msg_t) -> libc::c_int { if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint { return 0i32; } - return ((*msg).location_id != 0i32 as libc::c_uint) as libc::c_int; + + ((*msg).location_id != 0i32 as libc::c_uint) as libc::c_int } /** @@ -502,21 +507,21 @@ pub unsafe fn dc_msg_get_timestamp(mut msg: *const dc_msg_t) -> time_t { (*msg).timestamp_sort }; } -pub unsafe fn dc_msg_load_from_db( - mut msg: *mut dc_msg_t, - mut context: *mut dc_context_t, - mut id: uint32_t, + +// TODO should return bool /rtn +pub unsafe fn dc_msg_load_from_db<'a>( + msg: *mut dc_msg_t<'a>, + context: &'a dc_context_t, + id: uint32_t, ) -> libc::c_int { let mut success: libc::c_int = 0i32; - let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; - if !(msg.is_null() - || (*msg).magic != 0x11561156i32 as libc::c_uint - || context.is_null() - || (*context).sql.is_null()) - { + let mut stmt = 0 as *mut sqlite3_stmt; + if !msg.is_null() { stmt = - dc_sqlite3_prepare((*context).sql, - b"SELECT m.id,rfc724_mid,m.mime_in_reply_to,m.server_folder,m.server_uid,m.move_state,m.chat_id, m.from_id,m.to_id,m.timestamp,m.timestamp_sent,m.timestamp_rcvd, m.type,m.state,m.msgrmsg,m.txt, m.param,m.starred,m.hidden,m.location_id, c.blocked FROM msgs m LEFT JOIN chats c ON c.id=m.chat_id WHERE m.id=?;\x00" + dc_sqlite3_prepare( + context, + &context.sql.clone().read().unwrap(), + b"SELECT m.id,rfc724_mid,m.mime_in_reply_to,m.server_folder,m.server_uid,m.move_state,m.chat_id, m.from_id,m.to_id,m.timestamp,m.timestamp_sent,m.timestamp_rcvd, m.type,m.state,m.msgrmsg,m.txt, m.param,m.starred,m.hidden,m.location_id, c.blocked FROM msgs m LEFT JOIN chats c ON c.id=m.chat_id WHERE m.id=?;\x00" as *const u8 as *const libc::c_char); sqlite3_bind_int(stmt, 1i32, id as libc::c_int); if !(sqlite3_step(stmt) != 100i32) { @@ -528,8 +533,11 @@ pub unsafe fn dc_msg_load_from_db( } } sqlite3_finalize(stmt); - return success; + + success } + +// TODO always returns 1, should be void /rtn unsafe fn dc_msg_set_from_stmt( mut msg: *mut dc_msg_t, mut row: *mut sqlite3_stmt, @@ -600,45 +608,44 @@ unsafe fn dc_msg_set_from_stmt( row_offset = row_offset + 1; (*msg).location_id = sqlite3_column_int(row, fresh19) as uint32_t; let fresh20 = row_offset; - row_offset = row_offset + 1; (*msg).chat_blocked = sqlite3_column_int(row, fresh20); if (*msg).chat_blocked == 2i32 { dc_truncate_n_unwrap_str((*msg).text, 256i32, 0i32); } - return 1i32; + + 1 } + pub unsafe fn dc_get_mime_headers( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut msg_id: uint32_t, ) -> *mut libc::c_char { - let mut eml: *mut libc::c_char = 0 as *mut libc::c_char; - let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; - if !(context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint) { - stmt = dc_sqlite3_prepare( - (*context).sql, - b"SELECT mime_headers FROM msgs WHERE id=?;\x00" as *const u8 as *const libc::c_char, - ); - sqlite3_bind_int(stmt, 1i32, msg_id as libc::c_int); - if sqlite3_step(stmt) == 100i32 { - eml = dc_strdup_keep_null(sqlite3_column_text(stmt, 0i32) as *const libc::c_char) - } + let mut eml = 0 as *mut libc::c_char; + let mut stmt: *mut sqlite3_stmt; + + stmt = dc_sqlite3_prepare( + context, + &context.sql.clone().read().unwrap(), + b"SELECT mime_headers FROM msgs WHERE id=?;\x00" as *const u8 as *const libc::c_char, + ); + sqlite3_bind_int(stmt, 1i32, msg_id as libc::c_int); + if sqlite3_step(stmt) == 100i32 { + eml = dc_strdup_keep_null(sqlite3_column_text(stmt, 0i32) as *const libc::c_char) } + sqlite3_finalize(stmt); - return eml; + + eml } + pub unsafe fn dc_delete_msgs( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut msg_ids: *const uint32_t, mut msg_cnt: libc::c_int, ) { - if context.is_null() - || (*context).magic != 0x11a11807i32 as libc::c_uint - || msg_ids.is_null() - || msg_cnt <= 0i32 - { + if msg_ids.is_null() || msg_cnt <= 0i32 { return; } - dc_sqlite3_begin_transaction((*context).sql); let mut i: libc::c_int = 0i32; while i < msg_cnt { dc_update_msg_chat_id(context, *msg_ids.offset(i as isize), 3i32 as uint32_t); @@ -651,7 +658,7 @@ pub unsafe fn dc_delete_msgs( ); i += 1 } - dc_sqlite3_commit((*context).sql); + if 0 != msg_cnt { ((*context).cb)( context, @@ -663,13 +670,15 @@ pub unsafe fn dc_delete_msgs( dc_job_add(context, 105i32, 0i32, 0 as *const libc::c_char, 10i32); }; } + pub unsafe fn dc_update_msg_chat_id( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut msg_id: uint32_t, mut chat_id: uint32_t, ) { - let mut stmt: *mut sqlite3_stmt = dc_sqlite3_prepare( - (*context).sql, + let stmt = dc_sqlite3_prepare( + context, + &context.sql.clone().read().unwrap(), b"UPDATE msgs SET chat_id=? WHERE id=?;\x00" as *const u8 as *const libc::c_char, ); sqlite3_bind_int(stmt, 1i32, chat_id as libc::c_int); @@ -677,26 +686,20 @@ pub unsafe fn dc_update_msg_chat_id( sqlite3_step(stmt); sqlite3_finalize(stmt); } + pub unsafe fn dc_markseen_msgs( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut msg_ids: *const uint32_t, mut msg_cnt: libc::c_int, ) { - let mut transaction_pending: libc::c_int = 0i32; - let mut i: libc::c_int = 0i32; + let mut i: libc::c_int; let mut send_event: libc::c_int = 0i32; - let mut curr_state: libc::c_int = 0i32; - let mut curr_blocked: libc::c_int = 0i32; - let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; - if !(context.is_null() - || (*context).magic != 0x11a11807i32 as libc::c_uint - || msg_ids.is_null() - || msg_cnt <= 0i32) - { - dc_sqlite3_begin_transaction((*context).sql); - transaction_pending = 1i32; + let mut curr_state: libc::c_int; + let mut curr_blocked: libc::c_int; + let mut stmt = 0 as *mut sqlite3_stmt; + if !(msg_ids.is_null() || msg_cnt <= 0i32) { stmt = - dc_sqlite3_prepare((*context).sql, + dc_sqlite3_prepare(context, &context.sql.clone().read().unwrap(), b"SELECT m.state, c.blocked FROM msgs m LEFT JOIN chats c ON c.id=m.chat_id WHERE m.id=? AND m.chat_id>9\x00" as *const u8 as *const libc::c_char); i = 0i32; @@ -731,8 +734,7 @@ pub unsafe fn dc_markseen_msgs( } i += 1 } - dc_sqlite3_commit((*context).sql); - transaction_pending = 0i32; + if 0 != send_event { ((*context).cb)( context, @@ -742,18 +744,17 @@ pub unsafe fn dc_markseen_msgs( ); } } - if 0 != transaction_pending { - dc_sqlite3_rollback((*context).sql); - } sqlite3_finalize(stmt); } + pub unsafe fn dc_update_msg_state( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut msg_id: uint32_t, mut state: libc::c_int, ) { - let mut stmt: *mut sqlite3_stmt = dc_sqlite3_prepare( - (*context).sql, + let mut stmt = dc_sqlite3_prepare( + context, + &context.sql.clone().read().unwrap(), b"UPDATE msgs SET state=? WHERE id=?;\x00" as *const u8 as *const libc::c_char, ); sqlite3_bind_int(stmt, 1i32, state); @@ -761,23 +762,19 @@ pub unsafe fn dc_update_msg_state( sqlite3_step(stmt); sqlite3_finalize(stmt); } + pub unsafe fn dc_star_msgs( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut msg_ids: *const uint32_t, mut msg_cnt: libc::c_int, mut star: libc::c_int, ) { - if context.is_null() - || (*context).magic != 0x11a11807i32 as libc::c_uint - || msg_ids.is_null() - || msg_cnt <= 0i32 - || star != 0i32 && star != 1i32 - { + if msg_ids.is_null() || msg_cnt <= 0i32 || star != 0i32 && star != 1i32 { return; } - dc_sqlite3_begin_transaction((*context).sql); - let mut stmt: *mut sqlite3_stmt = dc_sqlite3_prepare( - (*context).sql, + let mut stmt = dc_sqlite3_prepare( + context, + &context.sql.clone().read().unwrap(), b"UPDATE msgs SET starred=? WHERE id=?;\x00" as *const u8 as *const libc::c_char, ); let mut i: libc::c_int = 0i32; @@ -789,35 +786,38 @@ pub unsafe fn dc_star_msgs( i += 1 } sqlite3_finalize(stmt); - dc_sqlite3_commit((*context).sql); } -pub unsafe fn dc_get_msg(mut context: *mut dc_context_t, mut msg_id: uint32_t) -> *mut dc_msg_t { + +pub unsafe fn dc_get_msg<'a>(context: &'a dc_context_t, msg_id: uint32_t) -> *mut dc_msg_t<'a> { let mut success: libc::c_int = 0i32; let mut obj: *mut dc_msg_t = dc_msg_new_untyped(context); - if !(context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint) { - if !(0 == dc_msg_load_from_db(obj, context, msg_id)) { - success = 1i32 - } + if !(0 == dc_msg_load_from_db(obj, context, msg_id)) { + success = 1i32 } if 0 != success { - return obj; + obj } else { dc_msg_unref(obj); - return 0 as *mut dc_msg_t; - }; + 0 as *mut dc_msg_t + } } + pub unsafe fn dc_msg_get_id(mut msg: *const dc_msg_t) -> uint32_t { if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint { return 0i32 as uint32_t; } - return (*msg).id; + + (*msg).id } + pub unsafe fn dc_msg_get_from_id(mut msg: *const dc_msg_t) -> uint32_t { if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint { return 0i32 as uint32_t; } - return (*msg).from_id; + + (*msg).from_id } + pub unsafe fn dc_msg_get_chat_id(mut msg: *const dc_msg_t) -> uint32_t { if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint { return 0i32 as uint32_t; @@ -828,39 +828,50 @@ pub unsafe fn dc_msg_get_chat_id(mut msg: *const dc_msg_t) -> uint32_t { (*msg).chat_id }; } + pub unsafe fn dc_msg_get_viewtype(mut msg: *const dc_msg_t) -> libc::c_int { if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint { return 0i32; } - return (*msg).type_0; + + (*msg).type_0 } + pub unsafe fn dc_msg_get_state(mut msg: *const dc_msg_t) -> libc::c_int { if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint { return 0i32; } - return (*msg).state; + + (*msg).state } + pub unsafe fn dc_msg_get_received_timestamp(mut msg: *const dc_msg_t) -> time_t { if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint { return 0i32 as time_t; } - return (*msg).timestamp_rcvd; + + (*msg).timestamp_rcvd } + pub unsafe fn dc_msg_get_sort_timestamp(mut msg: *const dc_msg_t) -> time_t { if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint { return 0i32 as time_t; } - return (*msg).timestamp_sort; + + (*msg).timestamp_sort } + pub unsafe fn dc_msg_get_text(mut msg: *const dc_msg_t) -> *mut libc::c_char { - let mut ret: *mut libc::c_char = 0 as *mut libc::c_char; + let mut ret: *mut libc::c_char; if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint { return dc_strdup(0 as *const libc::c_char); } ret = dc_strdup((*msg).text); dc_truncate_str(ret, 30000i32); - return ret; + + ret } + pub unsafe fn dc_msg_get_filename(mut msg: *const dc_msg_t) -> *mut libc::c_char { let mut ret: *mut libc::c_char = 0 as *mut libc::c_char; let mut pathNfilename: *mut libc::c_char = 0 as *mut libc::c_char; @@ -877,6 +888,7 @@ pub unsafe fn dc_msg_get_filename(mut msg: *const dc_msg_t) -> *mut libc::c_char dc_strdup(0 as *const libc::c_char) }; } + pub unsafe fn dc_msg_get_filebytes(mut msg: *const dc_msg_t) -> uint64_t { let mut ret: uint64_t = 0i32 as uint64_t; let mut file: *mut libc::c_char = 0 as *mut libc::c_char; @@ -887,38 +899,50 @@ pub unsafe fn dc_msg_get_filebytes(mut msg: *const dc_msg_t) -> uint64_t { } } free(file as *mut libc::c_void); - return ret; + + ret } + pub unsafe fn dc_msg_get_width(mut msg: *const dc_msg_t) -> libc::c_int { if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint { return 0i32; } - return dc_param_get_int((*msg).param, 'w' as i32, 0i32); + + dc_param_get_int((*msg).param, 'w' as i32, 0i32) } + pub unsafe fn dc_msg_get_height(mut msg: *const dc_msg_t) -> libc::c_int { if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint { return 0i32; } - return dc_param_get_int((*msg).param, 'h' as i32, 0i32); + + dc_param_get_int((*msg).param, 'h' as i32, 0i32) } + +// TODO should return bool /rtn pub unsafe fn dc_msg_get_duration(mut msg: *const dc_msg_t) -> libc::c_int { if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint { return 0i32; } - return dc_param_get_int((*msg).param, 'd' as i32, 0i32); + + dc_param_get_int((*msg).param, 'd' as i32, 0i32) } + +// TODO should return bool /rtn pub unsafe fn dc_msg_get_showpadlock(mut msg: *const dc_msg_t) -> libc::c_int { - if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint || (*msg).context.is_null() { + if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint { return 0i32; } if dc_param_get_int((*msg).param, 'c' as i32, 0i32) != 0i32 { return 1i32; } - return 0i32; + + 0 } -pub unsafe fn dc_msg_get_summary( - mut msg: *const dc_msg_t, - mut chat: *const dc_chat_t, + +pub unsafe fn dc_msg_get_summary<'a>( + msg: *const dc_msg_t<'a>, + mut chat: *const dc_chat_t<'a>, ) -> *mut dc_lot_t { let mut current_block: u64; let mut ret: *mut dc_lot_t = dc_lot_new(); @@ -950,8 +974,10 @@ pub unsafe fn dc_msg_get_summary( } dc_contact_unref(contact); dc_chat_unref(chat_to_delete); - return ret; + + ret } + pub unsafe fn dc_msg_get_summarytext( mut msg: *const dc_msg_t, mut approx_characters: libc::c_int, @@ -959,24 +985,26 @@ pub unsafe fn dc_msg_get_summarytext( if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint { return dc_strdup(0 as *const libc::c_char); } - return dc_msg_get_summarytext_by_raw( + + dc_msg_get_summarytext_by_raw( (*msg).type_0, (*msg).text, (*msg).param, approx_characters, (*msg).context, - ); + ) } + /* the returned value must be free()'d */ pub unsafe fn dc_msg_get_summarytext_by_raw( mut type_0: libc::c_int, mut text: *const libc::c_char, mut param: *mut dc_param_t, mut approx_characters: libc::c_int, - mut context: *mut dc_context_t, + mut context: &dc_context_t, ) -> *mut libc::c_char { /* get a summary text, result must be free()'d, never returns NULL. */ - let mut ret: *mut libc::c_char = 0 as *mut libc::c_char; + let mut ret; let mut prefix: *mut libc::c_char = 0 as *mut libc::c_char; let mut pathNfilename: *mut libc::c_char = 0 as *mut libc::c_char; let mut label: *mut libc::c_char = 0 as *mut libc::c_char; @@ -1038,27 +1066,36 @@ pub unsafe fn dc_msg_get_summarytext_by_raw( if ret.is_null() { ret = dc_strdup(0 as *const libc::c_char) } - return ret; + + ret } + pub unsafe fn dc_msg_has_deviating_timestamp(mut msg: *const dc_msg_t) -> libc::c_int { let mut cnv_to_local: libc::c_long = dc_gm2local_offset(); let mut sort_timestamp: time_t = dc_msg_get_sort_timestamp(msg) + cnv_to_local; let mut send_timestamp: time_t = dc_msg_get_timestamp(msg) + cnv_to_local; - return (sort_timestamp / 86400i32 as libc::c_long != send_timestamp / 86400i32 as libc::c_long) - as libc::c_int; + + (sort_timestamp / 86400i32 as libc::c_long != send_timestamp / 86400i32 as libc::c_long) + as libc::c_int } + +// TODO should return bool /rtn pub unsafe fn dc_msg_is_sent(mut msg: *const dc_msg_t) -> libc::c_int { if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint { return 0i32; } return if (*msg).state >= 26i32 { 1i32 } else { 0i32 }; } + +// TODO should return bool /rtn pub unsafe fn dc_msg_is_starred(mut msg: *const dc_msg_t) -> libc::c_int { if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint { return 0i32; } return if 0 != (*msg).starred { 1i32 } else { 0i32 }; } + +// TODO should return bool /rtn pub unsafe fn dc_msg_is_forwarded(mut msg: *const dc_msg_t) -> libc::c_int { if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint { return 0i32; @@ -1069,6 +1106,8 @@ pub unsafe fn dc_msg_is_forwarded(mut msg: *const dc_msg_t) -> libc::c_int { 0i32 }; } + +// TODO should return bool /rtn pub unsafe fn dc_msg_is_info(mut msg: *const dc_msg_t) -> libc::c_int { if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint { return 0i32; @@ -1080,20 +1119,26 @@ pub unsafe fn dc_msg_is_info(mut msg: *const dc_msg_t) -> libc::c_int { { return 1i32; } - return 0i32; + + 0 } + +// TODO should return bool /rtn pub unsafe fn dc_msg_is_increation(mut msg: *const dc_msg_t) -> libc::c_int { - if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint || (*msg).context.is_null() { + if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint { return 0i32; } - return (((*msg).type_0 == 20i32 + + (((*msg).type_0 == 20i32 || (*msg).type_0 == 21i32 || (*msg).type_0 == 40i32 || (*msg).type_0 == 41i32 || (*msg).type_0 == 50i32 || (*msg).type_0 == 60i32) - && (*msg).state == 18i32) as libc::c_int; + && (*msg).state == 18i32) as libc::c_int } + +// TODO should return bool /rtn pub unsafe fn dc_msg_is_setupmessage(mut msg: *const dc_msg_t) -> libc::c_int { if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint || (*msg).type_0 != 60i32 { return 0i32; @@ -1104,6 +1149,7 @@ pub unsafe fn dc_msg_is_setupmessage(mut msg: *const dc_msg_t) -> libc::c_int { 0i32 }; } + pub unsafe fn dc_msg_get_setupcodebegin(mut msg: *const dc_msg_t) -> *mut libc::c_char { let mut filename: *mut libc::c_char = 0 as *mut libc::c_char; let mut buf: *mut libc::c_char = 0 as *mut libc::c_char; @@ -1153,6 +1199,7 @@ pub unsafe fn dc_msg_get_setupcodebegin(mut msg: *const dc_msg_t) -> *mut libc:: dc_strdup(0 as *const libc::c_char) }; } + pub unsafe fn dc_msg_set_text(mut msg: *mut dc_msg_t, mut text: *const libc::c_char) { if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint { return; @@ -1160,6 +1207,8 @@ pub unsafe fn dc_msg_set_text(mut msg: *mut dc_msg_t, mut text: *const libc::c_c free((*msg).text as *mut libc::c_void); (*msg).text = dc_strdup(text); } + +// TODO should return bool /rtn pub unsafe fn dc_msg_set_file( mut msg: *mut dc_msg_t, mut file: *const libc::c_char, @@ -1171,6 +1220,7 @@ pub unsafe fn dc_msg_set_file( dc_param_set((*msg).param, 'f' as i32, file); dc_param_set((*msg).param, 'm' as i32, filemime); } + pub unsafe fn dc_msg_set_dimension( mut msg: *mut dc_msg_t, mut width: libc::c_int, @@ -1182,12 +1232,14 @@ pub unsafe fn dc_msg_set_dimension( dc_param_set_int((*msg).param, 'w' as i32, width); dc_param_set_int((*msg).param, 'h' as i32, height); } + pub unsafe fn dc_msg_set_duration(mut msg: *mut dc_msg_t, mut duration: libc::c_int) { if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint { return; } dc_param_set_int((*msg).param, 'd' as i32, duration); } + pub unsafe fn dc_msg_latefiling_mediasize( mut msg: *mut dc_msg_t, mut width: libc::c_int, @@ -1205,16 +1257,14 @@ pub unsafe fn dc_msg_latefiling_mediasize( dc_msg_save_param_to_disk(msg); }; } + pub unsafe fn dc_msg_save_param_to_disk(mut msg: *mut dc_msg_t) { - if msg.is_null() - || (*msg).magic != 0x11561156i32 as libc::c_uint - || (*msg).context.is_null() - || (*(*msg).context).sql.is_null() - { + if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint { return; } let mut stmt: *mut sqlite3_stmt = dc_sqlite3_prepare( - (*(*msg).context).sql, + (*msg).context, + &mut (*msg).context.sql.clone().read().unwrap(), b"UPDATE msgs SET param=? WHERE id=?;\x00" as *const u8 as *const libc::c_char, ); sqlite3_bind_text(stmt, 1i32, (*(*msg).param).packed, -1i32, None); @@ -1222,28 +1272,31 @@ pub unsafe fn dc_msg_save_param_to_disk(mut msg: *mut dc_msg_t) { sqlite3_step(stmt); sqlite3_finalize(stmt); } -pub unsafe fn dc_msg_new_load( - mut context: *mut dc_context_t, - mut msg_id: uint32_t, -) -> *mut dc_msg_t { - let mut msg: *mut dc_msg_t = dc_msg_new_untyped(context); + +pub unsafe fn dc_msg_new_load<'a>( + context: &'a dc_context_t, + msg_id: uint32_t, +) -> *mut dc_msg_t<'a> { + let mut msg = dc_msg_new_untyped(context); dc_msg_load_from_db(msg, context, msg_id); - return msg; + msg } -pub unsafe fn dc_delete_msg_from_db(mut context: *mut dc_context_t, mut msg_id: uint32_t) { + +pub unsafe fn dc_delete_msg_from_db(context: &dc_context_t, mut msg_id: uint32_t) { let mut msg: *mut dc_msg_t = dc_msg_new_untyped(context); let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; if !(0 == dc_msg_load_from_db(msg, context, msg_id)) { stmt = dc_sqlite3_prepare( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"DELETE FROM msgs WHERE id=?;\x00" as *const u8 as *const libc::c_char, ); sqlite3_bind_int(stmt, 1i32, (*msg).id as libc::c_int); sqlite3_step(stmt); sqlite3_finalize(stmt); - stmt = 0 as *mut sqlite3_stmt; stmt = dc_sqlite3_prepare( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"DELETE FROM msgs_mdns WHERE msg_id=?;\x00" as *const u8 as *const libc::c_char, ); sqlite3_bind_int(stmt, 1i32, (*msg).id as libc::c_int); @@ -1254,23 +1307,26 @@ pub unsafe fn dc_delete_msg_from_db(mut context: *mut dc_context_t, mut msg_id: sqlite3_finalize(stmt); dc_msg_unref(msg); } + /* as we do not cut inside words, this results in about 32-42 characters. Do not use too long subjects - we add a tag after the subject which gets truncated by the clients otherwise. It should also be very clear, the subject is _not_ the whole message. The value is also used for CC:-summaries */ + // Context functions to work with messages -pub unsafe fn dc_msg_exists(mut context: *mut dc_context_t, mut msg_id: uint32_t) -> libc::c_int { - let mut msg_exists: libc::c_int = 0i32; - let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; - if !(context.is_null() - || (*context).magic != 0x11a11807i32 as libc::c_uint - || msg_id <= 9i32 as libc::c_uint) - { + +pub unsafe fn dc_msg_exists(context: &dc_context_t, msg_id: uint32_t) -> libc::c_int { + let mut msg_exists = 0; + let mut stmt = 0 as *mut sqlite3_stmt; + + if msg_id > 9 { stmt = dc_sqlite3_prepare( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"SELECT chat_id FROM msgs WHERE id=?;\x00" as *const u8 as *const libc::c_char, ); sqlite3_bind_int(stmt, 1i32, msg_id as libc::c_int); + if sqlite3_step(stmt) == 100i32 { let mut chat_id: uint32_t = sqlite3_column_int(stmt, 0i32) as uint32_t; if chat_id != 3i32 as libc::c_uint { @@ -1279,17 +1335,20 @@ pub unsafe fn dc_msg_exists(mut context: *mut dc_context_t, mut msg_id: uint32_t } } sqlite3_finalize(stmt); - return msg_exists; + + msg_exists } + pub unsafe fn dc_update_msg_move_state( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut rfc724_mid: *const libc::c_char, mut state: dc_move_state_t, ) { // we update the move_state for all messages belonging to a given Message-ID // so that the state stay intact when parts are deleted - let mut stmt: *mut sqlite3_stmt = dc_sqlite3_prepare( - (*context).sql, + let mut stmt = dc_sqlite3_prepare( + context, + &context.sql.clone().read().unwrap(), b"UPDATE msgs SET move_state=? WHERE rfc724_mid=?;\x00" as *const u8 as *const libc::c_char, ); sqlite3_bind_int(stmt, 1i32, state as libc::c_int); @@ -1297,12 +1356,13 @@ pub unsafe fn dc_update_msg_move_state( sqlite3_step(stmt); sqlite3_finalize(stmt); } + pub unsafe fn dc_set_msg_failed( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut msg_id: uint32_t, mut error: *const libc::c_char, ) { - let mut msg: *mut dc_msg_t = dc_msg_new_untyped(context); + let mut msg = dc_msg_new_untyped(context); let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; if !(0 == dc_msg_load_from_db(msg, context, msg_id)) { if 18i32 == (*msg).state || 20i32 == (*msg).state || 26i32 == (*msg).state { @@ -1318,7 +1378,8 @@ pub unsafe fn dc_set_msg_failed( ); } stmt = dc_sqlite3_prepare( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"UPDATE msgs SET state=?, param=? WHERE id=?;\x00" as *const u8 as *const libc::c_char, ); sqlite3_bind_int(stmt, 1i32, (*msg).state); @@ -1335,25 +1396,24 @@ pub unsafe fn dc_set_msg_failed( sqlite3_finalize(stmt); dc_msg_unref(msg); } + /* returns 1 if an event should be send */ pub unsafe fn dc_mdn_from_ext( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut from_id: uint32_t, mut rfc724_mid: *const libc::c_char, mut timestamp_sent: time_t, mut ret_chat_id: *mut uint32_t, mut ret_msg_id: *mut uint32_t, ) -> libc::c_int { - let mut chat_type: libc::c_int = 0; - let mut msg_state: libc::c_int = 0; - let mut mdn_already_in_table: libc::c_int = 0; - let mut ist_cnt: libc::c_int = 0; - let mut soll_cnt: libc::c_int = 0; + let mut chat_type: libc::c_int; + let mut msg_state: libc::c_int; + let mut mdn_already_in_table: libc::c_int; + let mut ist_cnt: libc::c_int; + let mut soll_cnt: libc::c_int; let mut read_by_all: libc::c_int = 0i32; let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; - if !(context.is_null() - || (*context).magic != 0x11a11807i32 as libc::c_uint - || from_id <= 9i32 as libc::c_uint + if !(from_id <= 9i32 as libc::c_uint || rfc724_mid.is_null() || ret_chat_id.is_null() || ret_msg_id.is_null() @@ -1361,9 +1421,12 @@ pub unsafe fn dc_mdn_from_ext( || *ret_msg_id != 0i32 as libc::c_uint) { stmt = - dc_sqlite3_prepare((*context).sql, - b"SELECT m.id, c.id, c.type, m.state FROM msgs m LEFT JOIN chats c ON m.chat_id=c.id WHERE rfc724_mid=? AND from_id=1 ORDER BY m.id;\x00" - as *const u8 as *const libc::c_char); + dc_sqlite3_prepare( + context, + &context.sql.clone().read().unwrap(), + b"SELECT m.id, c.id, c.type, m.state FROM msgs m LEFT JOIN chats c ON m.chat_id=c.id WHERE rfc724_mid=? AND from_id=1 ORDER BY m.id;\x00" + as *const u8 as *const libc::c_char + ); sqlite3_bind_text(stmt, 1i32, rfc724_mid, -1i32, None); if !(sqlite3_step(stmt) != 100i32) { *ret_msg_id = sqlite3_column_int(stmt, 0i32) as uint32_t; @@ -1375,7 +1438,8 @@ pub unsafe fn dc_mdn_from_ext( if !(msg_state != 18i32 && msg_state != 20i32 && msg_state != 26i32) { /* eg. already marked as MDNS_RCVD. however, it is importent, that the message ID is set above as this will allow the caller eg. to move the message away */ stmt = dc_sqlite3_prepare( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"SELECT contact_id FROM msgs_mdns WHERE msg_id=? AND contact_id=?;\x00" as *const u8 as *const libc::c_char, ); @@ -1390,10 +1454,12 @@ pub unsafe fn dc_mdn_from_ext( stmt = 0 as *mut sqlite3_stmt; if 0 == mdn_already_in_table { stmt = - dc_sqlite3_prepare((*context).sql, - b"INSERT INTO msgs_mdns (msg_id, contact_id, timestamp_sent) VALUES (?, ?, ?);\x00" - as *const u8 as - *const libc::c_char); + dc_sqlite3_prepare( + context, + &context.sql.clone().read().unwrap(), + b"INSERT INTO msgs_mdns (msg_id, contact_id, timestamp_sent) VALUES (?, ?, ?);\x00" + as *const u8 as + *const libc::c_char); sqlite3_bind_int(stmt, 1i32, *ret_msg_id as libc::c_int); sqlite3_bind_int(stmt, 2i32, from_id as libc::c_int); sqlite3_bind_int64(stmt, 3i32, timestamp_sent as sqlite3_int64); @@ -1408,7 +1474,8 @@ pub unsafe fn dc_mdn_from_ext( } else { /* send event about new state */ stmt = dc_sqlite3_prepare( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"SELECT COUNT(*) FROM msgs_mdns WHERE msg_id=?;\x00" as *const u8 as *const libc::c_char, ); @@ -1443,20 +1510,25 @@ pub unsafe fn dc_mdn_from_ext( } } sqlite3_finalize(stmt); - return read_by_all; + + read_by_all } + /* the number of messages assigned to real chat (!=deaddrop, !=trash) */ -pub unsafe fn dc_get_real_msg_cnt(mut context: *mut dc_context_t) -> size_t { +pub unsafe fn dc_get_real_msg_cnt(mut context: &dc_context_t) -> size_t { let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; let mut ret: size_t = 0i32 as size_t; - if !(*(*context).sql).cobj.is_null() { + if !(*&context.sql.clone().read().unwrap()).cobj.is_null() { stmt = - dc_sqlite3_prepare((*context).sql, - b"SELECT COUNT(*) FROM msgs m LEFT JOIN chats c ON c.id=m.chat_id WHERE m.id>9 AND m.chat_id>9 AND c.blocked=0;\x00" + dc_sqlite3_prepare( + context, + &context.sql.clone().read().unwrap(), + b"SELECT COUNT(*) FROM msgs m LEFT JOIN chats c ON c.id=m.chat_id WHERE m.id>9 AND m.chat_id>9 AND c.blocked=0;\x00" as *const u8 as *const libc::c_char); if sqlite3_step(stmt) != 100i32 { dc_sqlite3_log_error( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"dc_get_real_msg_cnt() failed.\x00" as *const u8 as *const libc::c_char, ); } else { @@ -1464,17 +1536,16 @@ pub unsafe fn dc_get_real_msg_cnt(mut context: *mut dc_context_t) -> size_t { } } sqlite3_finalize(stmt); - return ret; + + ret } -pub unsafe fn dc_get_deaddrop_msg_cnt(mut context: *mut dc_context_t) -> size_t { + +pub unsafe fn dc_get_deaddrop_msg_cnt(mut context: &dc_context_t) -> size_t { let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; let mut ret: size_t = 0i32 as size_t; - if !(context.is_null() - || (*context).magic != 0x11a11807i32 as libc::c_uint - || (*(*context).sql).cobj.is_null()) - { + if !context.sql.clone().read().unwrap().cobj.is_null() { stmt = - dc_sqlite3_prepare((*context).sql, + dc_sqlite3_prepare(context, &context.sql.clone().read().unwrap(), b"SELECT COUNT(*) FROM msgs m LEFT JOIN chats c ON c.id=m.chat_id WHERE c.blocked=2;\x00" as *const u8 as *const libc::c_char); if !(sqlite3_step(stmt) != 100i32) { @@ -1482,21 +1553,21 @@ pub unsafe fn dc_get_deaddrop_msg_cnt(mut context: *mut dc_context_t) -> size_t } } sqlite3_finalize(stmt); - return ret; + + ret } + pub unsafe fn dc_rfc724_mid_cnt( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut rfc724_mid: *const libc::c_char, ) -> libc::c_int { /* check the number of messages with the same rfc724_mid */ let mut ret: libc::c_int = 0i32; - let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; - if !(context.is_null() - || (*context).magic != 0x11a11807i32 as libc::c_uint - || (*(*context).sql).cobj.is_null()) - { + let mut stmt = 0 as *mut sqlite3_stmt; + if !context.sql.clone().read().unwrap().cobj.is_null() { stmt = dc_sqlite3_prepare( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"SELECT COUNT(*) FROM msgs WHERE rfc724_mid=?;\x00" as *const u8 as *const libc::c_char, ); @@ -1506,22 +1577,22 @@ pub unsafe fn dc_rfc724_mid_cnt( } } sqlite3_finalize(stmt); - return ret; + + ret } + pub unsafe fn dc_rfc724_mid_exists( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut rfc724_mid: *const libc::c_char, mut ret_server_folder: *mut *mut libc::c_char, mut ret_server_uid: *mut uint32_t, ) -> uint32_t { let mut ret: uint32_t = 0i32 as uint32_t; let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; - if !(context.is_null() - || rfc724_mid.is_null() - || *rfc724_mid.offset(0isize) as libc::c_int == 0i32) - { + if !(rfc724_mid.is_null() || *rfc724_mid.offset(0isize) as libc::c_int == 0i32) { stmt = dc_sqlite3_prepare( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"SELECT server_folder, server_uid, id FROM msgs WHERE rfc724_mid=?;\x00" as *const u8 as *const libc::c_char, ); @@ -1544,16 +1615,19 @@ pub unsafe fn dc_rfc724_mid_exists( } } sqlite3_finalize(stmt); - return ret; + + ret } + pub unsafe fn dc_update_server_uid( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut rfc724_mid: *const libc::c_char, mut server_folder: *const libc::c_char, mut server_uid: uint32_t, ) { - let mut stmt: *mut sqlite3_stmt = dc_sqlite3_prepare( - (*context).sql, + let mut stmt = dc_sqlite3_prepare( + context, + &context.sql.clone().read().unwrap(), b"UPDATE msgs SET server_folder=?, server_uid=? WHERE rfc724_mid=?;\x00" as *const u8 as *const libc::c_char, ); diff --git a/src/dc_oauth2.rs b/src/dc_oauth2.rs index 5b2c97b86..9d47e3e45 100644 --- a/src/dc_oauth2.rs +++ b/src/dc_oauth2.rs @@ -1,5 +1,3 @@ -use libc; - use crate::constants::Event; use crate::dc_contact::*; use crate::dc_context::dc_context_t; @@ -22,21 +20,18 @@ pub struct oauth2_t { } pub unsafe fn dc_get_oauth2_url( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut addr: *const libc::c_char, mut redirect_uri: *const libc::c_char, ) -> *mut libc::c_char { let mut oauth2: *mut oauth2_t = 0 as *mut oauth2_t; let mut oauth2_url: *mut libc::c_char = 0 as *mut libc::c_char; - if !(context.is_null() - || (*context).magic != 0x11a11807i32 as libc::c_uint - || redirect_uri.is_null() - || *redirect_uri.offset(0isize) as libc::c_int == 0i32) - { + if !(redirect_uri.is_null() || *redirect_uri.offset(0isize) as libc::c_int == 0i32) { oauth2 = get_info(addr); if !oauth2.is_null() { dc_sqlite3_set_config( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"oauth2_pending_redirect_uri\x00" as *const u8 as *const libc::c_char, redirect_uri, ); @@ -54,8 +49,10 @@ pub unsafe fn dc_get_oauth2_url( } } free(oauth2 as *mut libc::c_void); - return oauth2_url; + + oauth2_url } + unsafe fn replace_in_uri( mut uri: *mut *mut libc::c_char, mut key: *const libc::c_char, @@ -67,10 +64,11 @@ unsafe fn replace_in_uri( free(value_urlencoded as *mut libc::c_void); }; } + unsafe fn get_info(mut addr: *const libc::c_char) -> *mut oauth2_t { let mut oauth2: *mut oauth2_t = 0 as *mut oauth2_t; - let mut addr_normalized: *mut libc::c_char = 0 as *mut libc::c_char; - let mut domain: *const libc::c_char = 0 as *const libc::c_char; + let mut addr_normalized: *mut libc::c_char; + let mut domain: *const libc::c_char; addr_normalized = dc_addr_normalize(addr); domain = strchr(addr_normalized, '@' as i32); if !(domain.is_null() || *domain.offset(0isize) as libc::c_int == 0i32) { @@ -119,12 +117,14 @@ unsafe fn get_info(mut addr: *const libc::c_char) -> *mut oauth2_t { } } free(addr_normalized as *mut libc::c_void); - return oauth2; + + oauth2 } + // the following function may block due http-requests; // must not be called from the main thread or by the ui! pub unsafe fn dc_get_oauth2_access_token( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut addr: *const libc::c_char, mut code: *const libc::c_char, mut flags: libc::c_int, @@ -153,13 +153,8 @@ pub unsafe fn dc_get_oauth2_access_token( end: 0, size: 0, }; 128]; - let mut tok_cnt: libc::c_int = 0i32; - let mut locked: libc::c_int = 0i32; - if context.is_null() - || (*context).magic != 0x11a11807i32 as libc::c_uint - || code.is_null() - || *code.offset(0isize) as libc::c_int == 0i32 - { + let mut tok_cnt: libc::c_int; + if code.is_null() || *code.offset(0isize) as libc::c_int == 0i32 { dc_log_warning( context, 0i32, @@ -174,12 +169,14 @@ pub unsafe fn dc_get_oauth2_access_token( b"Internal OAuth2 error: 2\x00" as *const u8 as *const libc::c_char, ); } else { - pthread_mutex_lock(&mut (*context).oauth2_critical); - locked = 1i32; + let lock = context.oauth2_critical.clone(); + + let l = lock.lock().unwrap(); // read generated token if 0 == flags & 0x1i32 && 0 == is_expired(context) { access_token = dc_sqlite3_get_config( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"oauth2_access_token\x00" as *const u8 as *const libc::c_char, 0 as *const libc::c_char, ); @@ -196,12 +193,14 @@ pub unsafe fn dc_get_oauth2_access_token( 16914036240511706173 => {} _ => { refresh_token = dc_sqlite3_get_config( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"oauth2_refresh_token\x00" as *const u8 as *const libc::c_char, 0 as *const libc::c_char, ); refresh_token_for = dc_sqlite3_get_config( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"oauth2_refresh_token_for\x00" as *const u8 as *const libc::c_char, b"unset\x00" as *const u8 as *const libc::c_char, ); @@ -213,7 +212,8 @@ pub unsafe fn dc_get_oauth2_access_token( as *const libc::c_char, ); redirect_uri = dc_sqlite3_get_config( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"oauth2_pending_redirect_uri\x00" as *const u8 as *const libc::c_char, b"unset\x00" as *const u8 as *const libc::c_char, ); @@ -227,7 +227,8 @@ pub unsafe fn dc_get_oauth2_access_token( as *const libc::c_char, ); redirect_uri = dc_sqlite3_get_config( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"oauth2_redirect_uri\x00" as *const u8 as *const libc::c_char, b"unset\x00" as *const u8 as *const libc::c_char, ); @@ -253,7 +254,7 @@ pub unsafe fn dc_get_oauth2_access_token( b"$REFRESH_TOKEN\x00" as *const u8 as *const libc::c_char, refresh_token, ); - json = ((*context).cb)( + json = (context.cb)( context, Event::HTTP_POST, token_url as uintptr_t, @@ -381,12 +382,14 @@ pub unsafe fn dc_get_oauth2_access_token( && 0 != *refresh_token.offset(0isize) as libc::c_int { dc_sqlite3_set_config( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"oauth2_refresh_token\x00" as *const u8 as *const libc::c_char, refresh_token, ); dc_sqlite3_set_config( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"oauth2_refresh_token_for\x00" as *const u8 as *const libc::c_char, code, @@ -405,12 +408,14 @@ pub unsafe fn dc_get_oauth2_access_token( ); } else { dc_sqlite3_set_config( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"oauth2_access_token\x00" as *const u8 as *const libc::c_char, access_token, ); dc_sqlite3_set_config_int64( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"oauth2_timestamp_expires\x00" as *const u8 as *const libc::c_char, (if 0 != expires_in { @@ -421,7 +426,8 @@ pub unsafe fn dc_get_oauth2_access_token( ); if 0 != update_redirect_uri_on_success { dc_sqlite3_set_config( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"oauth2_redirect_uri\x00" as *const u8 as *const libc::c_char, redirect_uri, @@ -432,11 +438,9 @@ pub unsafe fn dc_get_oauth2_access_token( } } } + drop(l); } } - if 0 != locked { - pthread_mutex_unlock(&mut (*context).oauth2_critical); - } free(refresh_token as *mut libc::c_void); free(refresh_token_for as *mut libc::c_void); free(redirect_uri as *mut libc::c_void); @@ -451,6 +455,7 @@ pub unsafe fn dc_get_oauth2_access_token( dc_strdup(0 as *const libc::c_char) }; } + unsafe fn jsondup(mut json: *const libc::c_char, mut tok: *mut jsmntok_t) -> *mut libc::c_char { if (*tok).type_0 as libc::c_uint == JSMN_STRING as libc::c_int as libc::c_uint || (*tok).type_0 as libc::c_uint == JSMN_PRIMITIVE as libc::c_int as libc::c_uint @@ -460,8 +465,10 @@ unsafe fn jsondup(mut json: *const libc::c_char, mut tok: *mut jsmntok_t) -> *mu ((*tok).end - (*tok).start) as libc::c_ulong, ); } - return strdup(b"\x00" as *const u8 as *const libc::c_char); + + strdup(b"\x00" as *const u8 as *const libc::c_char) } + unsafe extern "C" fn jsoneq( mut json: *const libc::c_char, mut tok: *mut jsmntok_t, @@ -477,11 +484,15 @@ unsafe extern "C" fn jsoneq( { return 0i32; } - return -1i32; + + -1 } -unsafe fn is_expired(mut context: *mut dc_context_t) -> libc::c_int { + +// TODO should return bool /rtn +unsafe fn is_expired(mut context: &dc_context_t) -> libc::c_int { let mut expire_timestamp: time_t = dc_sqlite3_get_config_int64( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"oauth2_timestamp_expires\x00" as *const u8 as *const libc::c_char, 0i32 as int64_t, ) as time_t; @@ -491,23 +502,22 @@ unsafe fn is_expired(mut context: *mut dc_context_t) -> libc::c_int { if expire_timestamp > time(0 as *mut time_t) { return 0i32; } - return 1i32; + + 1 } + pub unsafe fn dc_get_oauth2_addr( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut addr: *const libc::c_char, mut code: *const libc::c_char, ) -> *mut libc::c_char { let mut access_token: *mut libc::c_char = 0 as *mut libc::c_char; let mut addr_out: *mut libc::c_char = 0 as *mut libc::c_char; - let mut oauth2: *mut oauth2_t = 0 as *mut oauth2_t; - if !(context.is_null() - || (*context).magic != 0x11a11807i32 as libc::c_uint - || { - oauth2 = get_info(addr); - oauth2.is_null() - } - || (*oauth2).get_userinfo.is_null()) + let mut oauth2: *mut oauth2_t; + if !({ + oauth2 = get_info(addr); + oauth2.is_null() + } || (*oauth2).get_userinfo.is_null()) { access_token = dc_get_oauth2_access_token(context, addr, code, 0i32); addr_out = get_oauth2_addr(context, oauth2, access_token); @@ -519,10 +529,12 @@ pub unsafe fn dc_get_oauth2_addr( } free(access_token as *mut libc::c_void); free(oauth2 as *mut libc::c_void); - return addr_out; + + addr_out } + unsafe fn get_oauth2_addr( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut oauth2: *const oauth2_t, mut access_token: *const libc::c_char, ) -> *mut libc::c_char { @@ -541,10 +553,8 @@ unsafe fn get_oauth2_addr( end: 0, size: 0, }; 128]; - let mut tok_cnt: libc::c_int = 0i32; - if !(context.is_null() - || (*context).magic != 0x11a11807i32 as libc::c_uint - || access_token.is_null() + let mut tok_cnt: libc::c_int; + if !(access_token.is_null() || *access_token.offset(0isize) as libc::c_int == 0i32 || oauth2.is_null()) { @@ -554,7 +564,7 @@ unsafe fn get_oauth2_addr( b"$ACCESS_TOKEN\x00" as *const u8 as *const libc::c_char, access_token, ); - json = ((*context).cb)( + json = (context.cb)( context, Event::HTTP_GET, userinfo_url as uintptr_t, @@ -611,5 +621,6 @@ unsafe fn get_oauth2_addr( } free(userinfo_url as *mut libc::c_void); free(json as *mut libc::c_void); - return addr_out; + + addr_out } diff --git a/src/dc_param.rs b/src/dc_param.rs index 9f6f7a865..6ccf9f55c 100644 --- a/src/dc_param.rs +++ b/src/dc_param.rs @@ -1,5 +1,3 @@ -use libc; - use crate::dc_tools::*; use crate::types::*; use crate::x::*; @@ -94,8 +92,8 @@ unsafe extern "C" fn find_param( mut key: libc::c_int, mut ret_p2: *mut *mut libc::c_char, ) -> *mut libc::c_char { - let mut p1: *mut libc::c_char = 0 as *mut libc::c_char; - let mut p2: *mut libc::c_char = 0 as *mut libc::c_char; + let mut p1: *mut libc::c_char; + let mut p2: *mut libc::c_char; p1 = haystack; loop { if p1.is_null() || *p1 as libc::c_int == 0i32 { @@ -115,18 +113,20 @@ unsafe extern "C" fn find_param( p2 = &mut *p1.offset(strlen(p1) as isize) as *mut libc::c_char } *ret_p2 = p2; - return p1; + + p1 } + /* the value may be an empty string, "def" is returned only if the value unset. The result must be free()'d in any case. */ pub unsafe fn dc_param_get( - mut param: *const dc_param_t, - mut key: libc::c_int, - mut def: *const libc::c_char, + param: *const dc_param_t, + key: libc::c_int, + def: *const libc::c_char, ) -> *mut libc::c_char { - let mut p1: *mut libc::c_char = 0 as *mut libc::c_char; + let mut p1: *mut libc::c_char; let mut p2: *mut libc::c_char = 0 as *mut libc::c_char; - let mut bak: libc::c_char = 0i32 as libc::c_char; - let mut ret: *mut libc::c_char = 0 as *mut libc::c_char; + let mut bak: libc::c_char; + let mut ret: *mut libc::c_char; if param.is_null() || key == 0i32 { return if !def.is_null() { dc_strdup(def) @@ -148,8 +148,10 @@ pub unsafe fn dc_param_get( ret = dc_strdup(p1); dc_rtrim(ret); *p2 = bak; - return ret; + + ret } + pub unsafe fn dc_param_get_int( mut param: *const dc_param_t, mut key: libc::c_int, @@ -164,7 +166,8 @@ pub unsafe fn dc_param_get_int( } let mut ret: int32_t = atol(str) as int32_t; free(str as *mut libc::c_void); - return ret; + + ret } /** @@ -201,16 +204,16 @@ pub unsafe fn dc_param_set( mut key: libc::c_int, mut value: *const libc::c_char, ) { - let mut old1: *mut libc::c_char = 0 as *mut libc::c_char; - let mut old2: *mut libc::c_char = 0 as *mut libc::c_char; - let mut new1: *mut libc::c_char = 0 as *mut libc::c_char; + let mut old1: *mut libc::c_char; + let mut old2: *mut libc::c_char; + let mut new1: *mut libc::c_char; if param.is_null() || key == 0i32 { return; } old1 = (*param).packed; old2 = 0 as *mut libc::c_char; if !old1.is_null() { - let mut p1: *mut libc::c_char = 0 as *mut libc::c_char; + let mut p1: *mut libc::c_char; let mut p2: *mut libc::c_char = 0 as *mut libc::c_char; p1 = find_param(old1, key, &mut p2); if !p1.is_null() { @@ -277,6 +280,7 @@ pub unsafe fn dc_param_set( free((*param).packed as *mut libc::c_void); (*param).packed = new1; } + pub unsafe fn dc_param_set_int( mut param: *mut dc_param_t, mut key: libc::c_int, @@ -295,22 +299,26 @@ pub unsafe fn dc_param_set_int( dc_param_set(param, key, value_str); free(value_str as *mut libc::c_void); } + /* library-private */ pub unsafe fn dc_param_new() -> *mut dc_param_t { - let mut param: *mut dc_param_t = 0 as *mut dc_param_t; + let mut param: *mut dc_param_t; param = calloc(1, ::std::mem::size_of::()) as *mut dc_param_t; if param.is_null() { exit(28i32); } (*param).packed = calloc(1, 1) as *mut libc::c_char; - return param; + + param } + pub unsafe fn dc_param_empty(mut param: *mut dc_param_t) { if param.is_null() { return; } *(*param).packed.offset(0isize) = 0i32 as libc::c_char; } + pub unsafe fn dc_param_unref(mut param: *mut dc_param_t) { if param.is_null() { return; @@ -319,6 +327,7 @@ pub unsafe fn dc_param_unref(mut param: *mut dc_param_t) { free((*param).packed as *mut libc::c_void); free(param as *mut libc::c_void); } + pub unsafe fn dc_param_set_packed(mut param: *mut dc_param_t, mut packed: *const libc::c_char) { if param.is_null() { return; @@ -329,6 +338,7 @@ pub unsafe fn dc_param_set_packed(mut param: *mut dc_param_t, mut packed: *const (*param).packed = dc_strdup(packed) }; } + pub unsafe fn dc_param_set_urlencoded( mut param: *mut dc_param_t, mut urlencoded: *const libc::c_char, diff --git a/src/dc_pgp.rs b/src/dc_pgp.rs index 15c62234a..6796276ce 100644 --- a/src/dc_pgp.rs +++ b/src/dc_pgp.rs @@ -1,5 +1,3 @@ -use libc; - use crate::dc_context::dc_context_t; use crate::dc_hash::*; use crate::dc_key::*; @@ -10,18 +8,9 @@ use crate::pgp as rpgp; use crate::types::*; use crate::x::*; -/* ** library-private **********************************************************/ -/* validation errors */ -/* misc. */ -pub unsafe fn dc_pgp_init() {} pub unsafe fn dc_pgp_exit() {} -pub unsafe fn dc_pgp_rand_seed( - _context: *mut dc_context_t, - _buf: *const libc::c_void, - _bytes: size_t, -) { -} +// TODO should return bool /rtn pub unsafe fn dc_split_armored_data( mut buf: *mut libc::c_char, mut ret_headerline: *mut *const libc::c_char, @@ -33,7 +22,7 @@ pub unsafe fn dc_split_armored_data( let mut line_chars: size_t = 0i32 as size_t; let mut line: *mut libc::c_char = buf; let mut p1: *mut libc::c_char = buf; - let mut p2: *mut libc::c_char = 0 as *mut libc::c_char; + let mut p2: *mut libc::c_char; let mut headerline: *mut libc::c_char = 0 as *mut libc::c_char; let mut base64: *mut libc::c_char = 0 as *mut libc::c_char; if !ret_headerline.is_null() { @@ -136,21 +125,24 @@ pub unsafe fn dc_split_armored_data( } } } - return success; + + success } + /* public key encryption */ +// TODO should return bool /rtn pub unsafe fn dc_pgp_create_keypair( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut addr: *const libc::c_char, mut ret_public_key: *mut dc_key_t, mut ret_private_key: *mut dc_key_t, ) -> libc::c_int { let mut success: libc::c_int = 0i32; - let mut skey: *mut rpgp::signed_secret_key = 0 as *mut rpgp::signed_secret_key; + let mut skey: *mut rpgp::signed_secret_key; let mut pkey: *mut rpgp::signed_public_key = 0 as *mut rpgp::signed_public_key; let mut skey_bytes: *mut rpgp::cvec = 0 as *mut rpgp::cvec; let mut pkey_bytes: *mut rpgp::cvec = 0 as *mut rpgp::cvec; - let mut user_id: *mut libc::c_char = 0 as *mut libc::c_char; + let mut user_id: *mut libc::c_char; user_id = dc_mprintf(b"<%s>\x00" as *const u8 as *const libc::c_char, addr); skey = rpgp::rpgp_create_rsa_skey(2048i32 as uint32_t, user_id); if !(0 != dc_pgp_handle_rpgp_error(context)) { @@ -197,42 +189,42 @@ pub unsafe fn dc_pgp_create_keypair( if !user_id.is_null() { free(user_id as *mut libc::c_void); } - return success; + + success } + /* returns 0 if there is no error, otherwise logs the error if a context is provided and returns 1*/ -pub unsafe fn dc_pgp_handle_rpgp_error(mut context: *mut dc_context_t) -> libc::c_int { +// TODO should return bool /rtn +pub unsafe fn dc_pgp_handle_rpgp_error(mut context: &dc_context_t) -> libc::c_int { let mut success: libc::c_int = 0i32; - let mut len: libc::c_int = 0i32; + let mut len: libc::c_int; let mut msg: *mut libc::c_char = 0 as *mut libc::c_char; len = rpgp::rpgp_last_error_length(); if !(len == 0i32) { msg = rpgp::rpgp_last_error_message(); - if !context.is_null() { - dc_log_info( - context, - 0i32, - b"[rpgp][error] %s\x00" as *const u8 as *const libc::c_char, - msg, - ); - } + dc_log_info( + context, + 0i32, + b"[rpgp][error] %s\x00" as *const u8 as *const libc::c_char, + msg, + ); success = 1i32 } if !msg.is_null() { rpgp::rpgp_string_drop(msg); } - return success; + + success } + +// TODO should return bool /rtn pub unsafe fn dc_pgp_is_valid_key( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut raw_key: *const dc_key_t, ) -> libc::c_int { let mut key_is_valid: libc::c_int = 0i32; let mut key: *mut rpgp::public_or_secret_key = 0 as *mut rpgp::public_or_secret_key; - if !(context.is_null() - || raw_key.is_null() - || (*raw_key).binary.is_null() - || (*raw_key).bytes <= 0i32) - { + if !(raw_key.is_null() || (*raw_key).binary.is_null() || (*raw_key).bytes <= 0i32) { key = rpgp::rpgp_key_from_bytes( (*raw_key).binary as *const uint8_t, (*raw_key).bytes as usize, @@ -249,12 +241,16 @@ pub unsafe fn dc_pgp_is_valid_key( if !key.is_null() { rpgp::rpgp_key_drop(key); } - return key_is_valid; + + key_is_valid } + +// TODO should return bool /rtn pub unsafe fn dc_pgp_calc_fingerprint( - mut raw_key: *const dc_key_t, - mut ret_fingerprint: *mut *mut uint8_t, - mut ret_fingerprint_bytes: *mut size_t, + context: &dc_context_t, + raw_key: *const dc_key_t, + ret_fingerprint: *mut *mut uint8_t, + ret_fingerprint_bytes: *mut size_t, ) -> libc::c_int { let mut success: libc::c_int = 0i32; let mut key: *mut rpgp::public_or_secret_key = 0 as *mut rpgp::public_or_secret_key; @@ -271,9 +267,9 @@ pub unsafe fn dc_pgp_calc_fingerprint( (*raw_key).binary as *const uint8_t, (*raw_key).bytes as usize, ); - if !(0 != dc_pgp_handle_rpgp_error(0 as *mut dc_context_t)) { + if !(0 != dc_pgp_handle_rpgp_error(context)) { fingerprint = rpgp::rpgp_key_fingerprint(key); - if !(0 != dc_pgp_handle_rpgp_error(0 as *mut dc_context_t)) { + if !(0 != dc_pgp_handle_rpgp_error(context)) { *ret_fingerprint_bytes = rpgp::rpgp_cvec_len(fingerprint) as size_t; *ret_fingerprint = malloc(*ret_fingerprint_bytes) as *mut uint8_t; memcpy( @@ -291,10 +287,13 @@ pub unsafe fn dc_pgp_calc_fingerprint( if !fingerprint.is_null() { rpgp::rpgp_cvec_drop(fingerprint); } - return success; + + success } + +// TODO should return bool /rtn pub unsafe fn dc_pgp_split_key( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut private_in: *const dc_key_t, mut ret_public_key: *mut dc_key_t, ) -> libc::c_int { @@ -302,7 +301,7 @@ pub unsafe fn dc_pgp_split_key( let mut key: *mut rpgp::signed_secret_key = 0 as *mut rpgp::signed_secret_key; let mut pub_key: *mut rpgp::signed_public_key = 0 as *mut rpgp::signed_public_key; let mut buf: *mut rpgp::cvec = 0 as *mut rpgp::cvec; - if !(context.is_null() || private_in.is_null() || ret_public_key.is_null()) { + if !(private_in.is_null() || ret_public_key.is_null()) { if (*private_in).type_0 != 1i32 { dc_log_warning( context, @@ -340,10 +339,13 @@ pub unsafe fn dc_pgp_split_key( if !buf.is_null() { rpgp::rpgp_cvec_drop(buf); } - return success; + + success } + +// TODO should return bool /rtn pub unsafe fn dc_pgp_pk_encrypt( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut plain_text: *const libc::c_void, mut plain_bytes: size_t, mut raw_public_keys_for_encryption: *const dc_keyring_t, @@ -353,14 +355,13 @@ pub unsafe fn dc_pgp_pk_encrypt( mut ret_ctext_bytes: *mut size_t, ) -> libc::c_int { let mut current_block: u64; - let mut i: libc::c_int = 0i32; + let mut i: libc::c_int; let mut success: libc::c_int = 0i32; let mut public_keys_len: libc::c_int = 0i32; let mut public_keys: *mut *mut rpgp::signed_public_key = 0 as *mut *mut rpgp::signed_public_key; let mut private_key: *mut rpgp::signed_secret_key = 0 as *mut rpgp::signed_secret_key; let mut encrypted: *mut rpgp::Message = 0 as *mut rpgp::Message; - if !(context.is_null() - || plain_text == 0 as *mut libc::c_void + if !(plain_text == 0 as *mut libc::c_void || plain_bytes == 0 || ret_ctext.is_null() || ret_ctext_bytes.is_null() @@ -422,7 +423,7 @@ pub unsafe fn dc_pgp_pk_encrypt( 2132137392766895896 => {} _ => { /* sign & encrypt */ - let mut op_clocks: libc::clock_t = 0i32 as libc::clock_t; + let mut op_clocks: libc::clock_t; let mut start: libc::clock_t = clock(); if private_key.is_null() { encrypted = rpgp::rpgp_encrypt_bytes_to_keys( @@ -509,10 +510,13 @@ pub unsafe fn dc_pgp_pk_encrypt( if !encrypted.is_null() { rpgp::rpgp_msg_drop(encrypted); } - return success; + + success } + +// TODO should return bool /rtn pub unsafe fn dc_pgp_pk_decrypt( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut ctext: *const libc::c_void, mut ctext_bytes: size_t, mut raw_private_keys_for_decryption: *const dc_keyring_t, @@ -523,7 +527,7 @@ pub unsafe fn dc_pgp_pk_decrypt( mut ret_signature_fingerprints: *mut dc_hash_t, ) -> libc::c_int { let mut current_block: u64; - let mut i: libc::c_int = 0i32; + let mut i: libc::c_int; let mut success: libc::c_int = 0i32; let mut encrypted: *mut rpgp::Message = 0 as *mut rpgp::Message; let mut decrypted: *mut rpgp::message_decrypt_result = 0 as *mut rpgp::message_decrypt_result; @@ -532,8 +536,7 @@ pub unsafe fn dc_pgp_pk_decrypt( let mut private_keys: *mut *mut rpgp::signed_secret_key = 0 as *mut *mut rpgp::signed_secret_key; let mut public_keys: *mut *mut rpgp::signed_public_key = 0 as *mut *mut rpgp::signed_public_key; - if !(context.is_null() - || ctext == 0 as *mut libc::c_void + if !(ctext == 0 as *mut libc::c_void || ctext_bytes == 0 || ret_plain.is_null() || ret_plain_bytes.is_null() @@ -671,11 +674,14 @@ pub unsafe fn dc_pgp_pk_decrypt( if !decrypted.is_null() { rpgp::rpgp_message_decrypt_result_drop(decrypted); } - return success; + + success } + /* symm. encryption */ +// TODO should return bool /rtn pub unsafe fn dc_pgp_symm_encrypt( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut passphrase: *const libc::c_char, mut plain: *const libc::c_void, mut plain_bytes: size_t, @@ -683,8 +689,7 @@ pub unsafe fn dc_pgp_symm_encrypt( ) -> libc::c_int { let mut success: libc::c_int = 0i32; let mut decrypted: *mut rpgp::Message = 0 as *mut rpgp::Message; - if !(context.is_null() - || passphrase.is_null() + if !(passphrase.is_null() || plain == 0 as *mut libc::c_void || plain_bytes == 0 || ret_ctext_armored.is_null()) @@ -704,19 +709,22 @@ pub unsafe fn dc_pgp_symm_encrypt( if !decrypted.is_null() { rpgp::rpgp_msg_drop(decrypted); } - return success; + + success } + +// TODO should return bool /rtn pub unsafe fn dc_pgp_symm_decrypt( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut passphrase: *const libc::c_char, mut ctext: *const libc::c_void, mut ctext_bytes: size_t, mut ret_plain_text: *mut *mut libc::c_void, mut ret_plain_bytes: *mut size_t, ) -> libc::c_int { - let mut decrypted_bytes: *mut rpgp::cvec = 0 as *mut rpgp::cvec; + let mut decrypted_bytes: *mut rpgp::cvec; let mut success: libc::c_int = 0i32; - let mut encrypted: *mut rpgp::Message = 0 as *mut rpgp::Message; + let mut encrypted: *mut rpgp::Message; let mut decrypted: *mut rpgp::Message = 0 as *mut rpgp::Message; encrypted = rpgp::rpgp_msg_from_bytes(ctext as *const uint8_t, ctext_bytes as usize); if !(0 != dc_pgp_handle_rpgp_error(context)) { @@ -737,5 +745,6 @@ pub unsafe fn dc_pgp_symm_decrypt( if !decrypted.is_null() { rpgp::rpgp_msg_drop(decrypted); } - return success; + + success } diff --git a/src/dc_qr.rs b/src/dc_qr.rs index e8aae56bc..9bd5ec2ca 100644 --- a/src/dc_qr.rs +++ b/src/dc_qr.rs @@ -1,5 +1,3 @@ -use libc; - use crate::dc_apeerstate::*; use crate::dc_chat::*; use crate::dc_contact::*; @@ -24,7 +22,7 @@ use crate::x::*; // text1=URL // text1=error string pub unsafe fn dc_check_qr( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut qr: *const libc::c_char, ) -> *mut dc_lot_t { let mut current_block: u64; @@ -43,7 +41,7 @@ pub unsafe fn dc_check_qr( let mut grpid: *mut libc::c_char = 0 as *mut libc::c_char; let mut grpname: *mut libc::c_char = 0 as *mut libc::c_char; (*qr_parsed).state = 0i32; - if !(context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint || qr.is_null()) { + if !qr.is_null() { dc_log_info( context, 0i32, @@ -247,7 +245,7 @@ pub unsafe fn dc_check_qr( if addr.is_null() || invitenumber.is_null() || auth.is_null() { if 0 != dc_apeerstate_load_by_fingerprint( peerstate, - (*context).sql, + &context.sql.clone().read().unwrap(), fingerprint, ) { (*qr_parsed).state = 210i32; diff --git a/src/dc_receive_imf.rs b/src/dc_receive_imf.rs index 529df8ae7..3f5884e56 100644 --- a/src/dc_receive_imf.rs +++ b/src/dc_receive_imf.rs @@ -1,4 +1,10 @@ -use libc; +use mmime::mailimf::*; +use mmime::mailimf_types::*; +use mmime::mailmime::*; +use mmime::mailmime_content::*; +use mmime::mailmime_types::*; +use mmime::mmapstring::*; +use mmime::other::*; use crate::constants::*; use crate::dc_apeerstate::*; @@ -25,40 +31,39 @@ use crate::types::*; use crate::x::*; pub unsafe fn dc_receive_imf( - mut context: *mut dc_context_t, - mut imf_raw_not_terminated: *const libc::c_char, - mut imf_raw_bytes: size_t, - mut server_folder: *const libc::c_char, - mut server_uid: uint32_t, - mut flags: uint32_t, + context: &dc_context_t, + imf_raw_not_terminated: *const libc::c_char, + imf_raw_bytes: size_t, + server_folder: *const libc::c_char, + server_uid: uint32_t, + flags: uint32_t, ) { let mut current_block: u64; /* the function returns the number of created messages in the database */ let mut incoming: libc::c_int = 1i32; let mut incoming_origin: libc::c_int = 0i32; - let mut to_ids: *mut dc_array_t = 0 as *mut dc_array_t; + let mut to_ids: *mut dc_array_t; let mut to_self: libc::c_int = 0i32; let mut from_id: uint32_t = 0i32 as uint32_t; let mut from_id_blocked: libc::c_int = 0i32; let mut to_id: uint32_t = 0i32 as uint32_t; let mut chat_id: uint32_t = 0i32 as uint32_t; let mut chat_id_blocked: libc::c_int = 0i32; - let mut state: libc::c_int = 0i32; + let mut state: libc::c_int; let mut hidden: libc::c_int = 0i32; - let mut msgrmsg: libc::c_int = 0i32; + let mut msgrmsg: libc::c_int; let mut add_delete_job: libc::c_int = 0i32; let mut insert_msg_id: uint32_t = 0i32 as uint32_t; let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; - let mut i: size_t = 0i32 as size_t; - let mut icnt: size_t = 0i32 as size_t; + let mut i: size_t; + let mut icnt: size_t; /* Message-ID from the header */ let mut rfc724_mid: *mut libc::c_char = 0 as *mut libc::c_char; 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 transaction_pending: libc::c_int = 0i32; - let mut field: *const mailimf_field = 0 as *const mailimf_field; + let mut mime_parser: *mut dc_mimeparser_t = dc_mimeparser_new(context.get_blobdir(), context); + let mut field: *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; let mut created_db_entries: *mut carray = carray_new(16i32 as libc::c_uint); @@ -76,7 +81,7 @@ pub unsafe fn dc_receive_imf( }, server_uid, ); - to_ids = dc_array_new(context, 16i32 as size_t); + to_ids = dc_array_new(16i32 as size_t); if to_ids.is_null() || created_db_entries.is_null() || rr_event_to_send.is_null() @@ -107,8 +112,6 @@ pub unsafe fn dc_receive_imf( sent_timestamp = dc_timestamp_from_date((*orig_date).dt_date_time) } } - dc_sqlite3_begin_transaction((*context).sql); - transaction_pending = 1i32; field = dc_mimeparser_lookup_field( mime_parser, b"From\x00" as *const u8 as *const libc::c_char, @@ -117,7 +120,7 @@ pub unsafe fn dc_receive_imf( let mut fld_from: *mut mailimf_from = (*field).fld_data.fld_from; if !fld_from.is_null() { let mut check_self: libc::c_int = 0; - let mut from_list: *mut dc_array_t = dc_array_new(context, 16i32 as size_t); + let mut from_list: *mut dc_array_t = dc_array_new(16i32 as size_t); dc_add_or_lookup_contacts_by_mailbox_list( context, (*fld_from).frm_mb_list, @@ -226,8 +229,6 @@ pub unsafe fn dc_receive_imf( if strcmp(old_server_folder, server_folder) != 0i32 || old_server_uid != server_uid { - dc_sqlite3_rollback((*context).sql); - transaction_pending = 0i32; dc_update_server_uid( context, rfc724_mid, @@ -255,7 +256,8 @@ pub unsafe fn dc_receive_imf( let mut allow_creation: libc::c_int = 1i32; if msgrmsg == 0i32 { let mut show_emails: libc::c_int = dc_sqlite3_get_config_int( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"show_emails\x00" as *const u8 as *const libc::c_char, 0i32, ); @@ -282,7 +284,6 @@ pub unsafe fn dc_receive_imf( msgrmsg = 1i32; chat_id = 0i32 as uint32_t; allow_creation = 1i32; - dc_sqlite3_commit((*context).sql); let mut handshake: libc::c_int = dc_handle_securejoin_handshake( context, mime_parser, @@ -293,7 +294,6 @@ pub unsafe fn dc_receive_imf( add_delete_job = handshake & 0x4i32; state = 16i32 } - dc_sqlite3_begin_transaction((*context).sql); } let mut test_normal_chat_id: uint32_t = 0i32 as uint32_t; let mut test_normal_chat_id_blocked: libc::c_int = 0i32; @@ -469,13 +469,14 @@ pub unsafe fn dc_receive_imf( // if the mime-headers should be saved, find out its size // (the mime-header ends with an empty line) let mut save_mime_headers: libc::c_int = dc_sqlite3_get_config_int( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"save_mime_headers\x00" as *const u8 as *const libc::c_char, 0i32, ); let mut header_bytes: libc::c_int = imf_raw_bytes as libc::c_int; if 0 != save_mime_headers { - let mut p: *mut libc::c_char = 0 as *mut libc::c_char; + let mut p: *mut libc::c_char; p = strstr( imf_raw_not_terminated, b"\r\n\r\n\x00" as *const u8 as *const libc::c_char, @@ -533,8 +534,10 @@ pub unsafe fn dc_receive_imf( } icnt = carray_count((*mime_parser).parts) as size_t; stmt = - dc_sqlite3_prepare((*context).sql, - b"INSERT INTO msgs (rfc724_mid, server_folder, server_uid, chat_id, from_id, to_id, timestamp, timestamp_sent, timestamp_rcvd, type, state, msgrmsg, txt, txt_raw, param, bytes, hidden, mime_headers, mime_in_reply_to, mime_references) VALUES (?,?,?,?,?,?, ?,?,?,?,?,?, ?,?,?,?,?,?, ?,?);\x00" + dc_sqlite3_prepare( + context, + &context.sql.clone().read().unwrap(), + b"INSERT INTO msgs (rfc724_mid, server_folder, server_uid, chat_id, from_id, to_id, timestamp, timestamp_sent, timestamp_rcvd, type, state, msgrmsg, txt, txt_raw, param, bytes, hidden, mime_headers, mime_in_reply_to, mime_references) VALUES (?,?,?,?,?,?, ?,?,?,?,?,?, ?,?,?,?,?,?, ?,?);\x00" as *const u8 as *const libc::c_char); i = 0i32 as size_t; @@ -650,7 +653,8 @@ pub unsafe fn dc_receive_imf( free(txt_raw as *mut libc::c_void); txt_raw = 0 as *mut libc::c_char; insert_msg_id = dc_sqlite3_get_rowid( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"msgs\x00" as *const u8 as *const libc::c_char, b"rfc724_mid\x00" as *const u8 as *const libc::c_char, rfc724_mid, @@ -710,7 +714,8 @@ pub unsafe fn dc_receive_imf( _ => { if carray_count((*mime_parser).reports) > 0i32 as libc::c_uint { let mut mdns_enabled: libc::c_int = dc_sqlite3_get_config_int( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"mdns_enabled\x00" as *const u8 as *const libc::c_char, 1i32, ); @@ -751,7 +756,7 @@ pub unsafe fn dc_receive_imf( .first) .next } else { - 0 as *mut clistcell_s + 0 as *mut clistcell } .is_null() { @@ -769,7 +774,7 @@ pub unsafe fn dc_receive_imf( .first) .next } else { - 0 as *mut clistcell_s + 0 as *mut clistcell }) .data } else { @@ -901,7 +906,8 @@ pub unsafe fn dc_receive_imf( dc_param_set_int(param, 'z' as i32, server_uid as int32_t); if 0 != (*mime_parser).is_send_by_messenger && 0 != dc_sqlite3_get_config_int( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"mvbox_move\x00" as *const u8 as *const libc::c_char, 1i32, @@ -988,15 +994,10 @@ pub unsafe fn dc_receive_imf( 0i32, ); } - dc_sqlite3_commit((*context).sql); - transaction_pending = 0i32 } } } } - if 0 != transaction_pending { - dc_sqlite3_rollback((*context).sql); - } dc_mimeparser_unref(mime_parser); free(rfc724_mid as *mut libc::c_void); free(mime_in_reply_to as *mut libc::c_void); @@ -1006,7 +1007,6 @@ pub unsafe fn dc_receive_imf( if let Some(create_event_to_send) = create_event_to_send { let mut i_0: size_t = 0; let mut icnt_0: size_t = carray_count(created_db_entries) as size_t; - i_0 = 0i32 as size_t; while i_0 < icnt_0 { ((*context).cb)( context, @@ -1021,7 +1021,7 @@ pub unsafe fn dc_receive_imf( carray_free(created_db_entries); } if !rr_event_to_send.is_null() { - let mut i_1: size_t = 0; + let mut i_1: size_t; let mut icnt_1: size_t = carray_count(rr_event_to_send) as size_t; i_1 = 0i32 as size_t; while i_1 < icnt_1 { @@ -1042,7 +1042,7 @@ pub unsafe fn dc_receive_imf( * Misc. Tools ******************************************************************************/ unsafe fn calc_timestamps( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut chat_id: uint32_t, mut from_id: uint32_t, mut message_timestamp: time_t, @@ -1059,7 +1059,8 @@ unsafe fn calc_timestamps( *sort_timestamp = message_timestamp; if 0 != is_fresh_msg { let mut stmt: *mut sqlite3_stmt = dc_sqlite3_prepare( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"SELECT MAX(timestamp) FROM msgs WHERE chat_id=? and from_id!=? AND timestamp>=?\x00" as *const u8 as *const libc::c_char, ); @@ -1093,7 +1094,7 @@ which tries to create or find out the chat_id by: So when the function returns, the caller has the group id matching the current state of the group. */ unsafe fn create_or_lookup_group( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut mime_parser: *mut dc_mimeparser_t, mut allow_creation: libc::c_int, mut create_blocked: libc::c_int, @@ -1102,15 +1103,15 @@ unsafe fn create_or_lookup_group( mut ret_chat_id: *mut uint32_t, mut ret_chat_id_blocked: *mut libc::c_int, ) { - let mut group_explicitly_left: libc::c_int = 0; + let mut group_explicitly_left: libc::c_int; let mut current_block: u64; let mut chat_id: uint32_t = 0i32 as uint32_t; let mut chat_id_blocked: libc::c_int = 0i32; let mut chat_id_verified: libc::c_int = 0i32; let mut grpid: *mut libc::c_char = 0 as *mut libc::c_char; let mut grpname: *mut libc::c_char = 0 as *mut libc::c_char; - let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; - let mut i: libc::c_int = 0i32; + let mut stmt: *mut sqlite3_stmt; + let mut i: libc::c_int; let mut to_ids_cnt: libc::c_int = dc_array_get_cnt(to_ids) as libc::c_int; let mut self_addr: *mut libc::c_char = 0 as *mut libc::c_char; let mut recreate_member_list: libc::c_int = 0i32; @@ -1134,8 +1135,8 @@ unsafe fn create_or_lookup_group( } set_better_msg(mime_parser, &mut better_msg); /* search the grpid in the header */ - let mut field: *mut mailimf_field = 0 as *mut mailimf_field; - let mut optional_field: *mut mailimf_optional_field = 0 as *mut mailimf_optional_field; + let mut field: *mut mailimf_field; + let mut optional_field: *mut mailimf_optional_field; optional_field = dc_mimeparser_lookup_optional_field( mime_parser, b"Chat-Group-ID\x00" as *const u8 as *const libc::c_char, @@ -1321,7 +1322,8 @@ unsafe fn create_or_lookup_group( /* check if the group does not exist but should be created */ group_explicitly_left = dc_is_group_explicitly_left(context, grpid); self_addr = dc_sqlite3_get_config( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"configured_addr\x00" as *const u8 as *const libc::c_char, b"\x00" as *const u8 as *const libc::c_char, ); @@ -1364,7 +1366,6 @@ unsafe fn create_or_lookup_group( create_verified, ); chat_id_blocked = create_blocked; - chat_id_verified = create_verified; recreate_member_list = 1i32; current_block = 200744462051969938; } @@ -1399,7 +1400,8 @@ unsafe fn create_or_lookup_group( && strlen(grpname) < 200 { stmt = dc_sqlite3_prepare( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"UPDATE chats SET name=? WHERE id=?;\x00" as *const u8 as *const libc::c_char, ); @@ -1468,7 +1470,8 @@ unsafe fn create_or_lookup_group( 0 as *mut libc::c_char }; stmt = dc_sqlite3_prepare( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"DELETE FROM chats_contacts WHERE chat_id=?;\x00" as *const u8 as *const libc::c_char, ); @@ -1559,7 +1562,7 @@ unsafe fn create_or_lookup_group( * Handle groups for received messages ******************************************************************************/ unsafe fn create_or_lookup_adhoc_group( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut mime_parser: *mut dc_mimeparser_t, mut allow_creation: libc::c_int, mut create_blocked: libc::c_int, @@ -1574,7 +1577,7 @@ unsafe fn create_or_lookup_adhoc_group( let mut member_ids: *mut dc_array_t = 0 as *mut dc_array_t; let mut chat_id: uint32_t = 0i32 as uint32_t; let mut chat_id_blocked = 0; - let mut i = 0; + let mut i; let mut chat_ids: *mut dc_array_t = 0 as *mut dc_array_t; let mut chat_ids_str: *mut libc::c_char = 0 as *mut libc::c_char; let mut q3: *mut libc::c_char = 0 as *mut libc::c_char; @@ -1601,7 +1604,7 @@ unsafe fn create_or_lookup_adhoc_group( sqlite3_mprintf(b"SELECT c.id, c.blocked FROM chats c LEFT JOIN msgs m ON m.chat_id=c.id WHERE c.id IN(%s) ORDER BY m.timestamp DESC, m.id DESC LIMIT 1;\x00" as *const u8 as *const libc::c_char, chat_ids_str); - stmt = dc_sqlite3_prepare((*context).sql, q3); + stmt = dc_sqlite3_prepare(context, &context.sql.clone().read().unwrap(), q3); if sqlite3_step(stmt) == 100i32 { chat_id = sqlite3_column_int(stmt, 0i32) as uint32_t; chat_id_blocked = sqlite3_column_int(stmt, 1i32); @@ -1673,16 +1676,17 @@ unsafe fn create_or_lookup_adhoc_group( }; } unsafe fn create_group_record( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut grpid: *const libc::c_char, mut grpname: *const libc::c_char, mut create_blocked: libc::c_int, mut create_verified: libc::c_int, ) -> uint32_t { let mut chat_id: uint32_t = 0i32 as uint32_t; - let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; + let mut stmt: *mut sqlite3_stmt; stmt = dc_sqlite3_prepare( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"INSERT INTO chats (type, name, grpid, blocked) VALUES(?, ?, ?, ?);\x00" as *const u8 as *const libc::c_char, ); @@ -1696,7 +1700,8 @@ unsafe fn create_group_record( sqlite3_bind_int(stmt, 4i32, create_blocked); if !(sqlite3_step(stmt) != 101i32) { chat_id = dc_sqlite3_get_rowid( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"chats\x00" as *const u8 as *const libc::c_char, b"grpid\x00" as *const u8 as *const libc::c_char, grpid, @@ -1706,7 +1711,7 @@ unsafe fn create_group_record( return chat_id; } unsafe fn create_adhoc_grp_id( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut member_ids: *mut dc_array_t, ) -> *mut libc::c_char { /* algorithm: @@ -1715,14 +1720,14 @@ unsafe fn create_adhoc_grp_id( - sha-256 this string (without possibly terminating null-characters) - encode the first 64 bits of the sha-256 output as lowercase hex (results in 16 characters from the set [0-9a-f]) */ - let mut member_addrs: *mut dc_array_t = dc_array_new(context, 23i32 as size_t); + let mut member_addrs: *mut dc_array_t = dc_array_new(23i32 as size_t); let mut member_ids_str: *mut libc::c_char = dc_array_get_string(member_ids, b",\x00" as *const u8 as *const libc::c_char); - let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; - let mut q3: *mut libc::c_char = 0 as *mut libc::c_char; - let mut addr: *mut libc::c_char = 0 as *mut libc::c_char; - let mut i: libc::c_int = 0i32; - let mut iCnt: libc::c_int = 0i32; + let mut stmt: *mut sqlite3_stmt; + let mut q3: *mut libc::c_char; + let mut addr: *mut libc::c_char; + let mut i: libc::c_int; + let mut iCnt: libc::c_int; let mut ret: *mut libc::c_char = 0 as *mut libc::c_char; let mut member_cs: dc_strbuilder_t = dc_strbuilder_t { buf: 0 as *mut libc::c_char, @@ -1736,9 +1741,10 @@ unsafe fn create_adhoc_grp_id( as *const libc::c_char, member_ids_str, ); - stmt = dc_sqlite3_prepare((*context).sql, q3); + stmt = dc_sqlite3_prepare(context, &context.sql.clone().read().unwrap(), q3); addr = dc_sqlite3_get_config( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"configured_addr\x00" as *const u8 as *const libc::c_char, b"no-self\x00" as *const u8 as *const libc::c_char, ); @@ -1791,67 +1797,67 @@ unsafe fn create_adhoc_grp_id( return ret; } unsafe fn search_chat_ids_by_contact_ids( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut unsorted_contact_ids: *const dc_array_t, ) -> *mut dc_array_t { /* searches chat_id's by the given contact IDs, may return zero, one or more chat_id's */ let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; - let mut contact_ids: *mut dc_array_t = dc_array_new(context, 23i32 as size_t); + let mut contact_ids: *mut dc_array_t = dc_array_new(23i32 as size_t); let mut contact_ids_str: *mut libc::c_char = 0 as *mut libc::c_char; let mut q3: *mut libc::c_char = 0 as *mut libc::c_char; - let mut chat_ids: *mut dc_array_t = dc_array_new(context, 23i32 as size_t); - if !(context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint) { - /* copy array, remove duplicates and SELF, sort by ID */ - let mut i: libc::c_int = 0; - let mut iCnt: libc::c_int = dc_array_get_cnt(unsorted_contact_ids) as libc::c_int; - if !(iCnt <= 0i32) { - i = 0i32; - while i < iCnt { - let mut curr_id: uint32_t = dc_array_get_id(unsorted_contact_ids, i as size_t); - if curr_id != 1i32 as libc::c_uint - && 0 == dc_array_search_id(contact_ids, curr_id, 0 as *mut size_t) - { - dc_array_add_id(contact_ids, curr_id); - } - i += 1 + let mut chat_ids: *mut dc_array_t = dc_array_new(23i32 as size_t); + + /* copy array, remove duplicates and SELF, sort by ID */ + let mut i: libc::c_int; + let mut iCnt: libc::c_int = dc_array_get_cnt(unsorted_contact_ids) as libc::c_int; + if !(iCnt <= 0i32) { + i = 0i32; + while i < iCnt { + let mut curr_id: uint32_t = dc_array_get_id(unsorted_contact_ids, i as size_t); + if curr_id != 1i32 as libc::c_uint + && 0 == dc_array_search_id(contact_ids, curr_id, 0 as *mut size_t) + { + dc_array_add_id(contact_ids, curr_id); } - if !(dc_array_get_cnt(contact_ids) == 0) { - dc_array_sort_ids(contact_ids); - contact_ids_str = - dc_array_get_string(contact_ids, b",\x00" as *const u8 as *const libc::c_char); - q3 = + i += 1 + } + if !(dc_array_get_cnt(contact_ids) == 0) { + dc_array_sort_ids(contact_ids); + contact_ids_str = + dc_array_get_string(contact_ids, b",\x00" as *const u8 as *const libc::c_char); + q3 = sqlite3_mprintf(b"SELECT DISTINCT cc.chat_id, cc.contact_id FROM chats_contacts cc LEFT JOIN chats c ON c.id=cc.chat_id WHERE cc.chat_id IN(SELECT chat_id FROM chats_contacts WHERE contact_id IN(%s)) AND c.type=120 AND cc.contact_id!=1 ORDER BY cc.chat_id, cc.contact_id;\x00" as *const u8 as *const libc::c_char, contact_ids_str); - stmt = dc_sqlite3_prepare((*context).sql, q3); - let mut last_chat_id = 0; - let mut matches = 0; - let mut mismatches = 0; - while sqlite3_step(stmt) == 100 { - let mut chat_id: uint32_t = sqlite3_column_int(stmt, 0i32) as uint32_t; - let mut contact_id: uint32_t = sqlite3_column_int(stmt, 1i32) as uint32_t; - if chat_id != last_chat_id { - if matches == dc_array_get_cnt(contact_ids) - && mismatches == 0i32 as libc::c_uint - { - dc_array_add_id(chat_ids, last_chat_id); - } - last_chat_id = chat_id; - matches = 0; - mismatches = 0; - } - if contact_id == dc_array_get_id(contact_ids, matches as size_t) { - matches = matches.wrapping_add(1) - } else { - mismatches = mismatches.wrapping_add(1) + stmt = dc_sqlite3_prepare(context, &context.sql.clone().read().unwrap(), q3); + let mut last_chat_id = 0; + let mut matches = 0; + let mut mismatches = 0; + while sqlite3_step(stmt) == 100 { + let mut chat_id: uint32_t = sqlite3_column_int(stmt, 0i32) as uint32_t; + let mut contact_id: uint32_t = sqlite3_column_int(stmt, 1i32) as uint32_t; + if chat_id != last_chat_id { + if matches == dc_array_get_cnt(contact_ids) + && mismatches == 0i32 as libc::c_uint + { + dc_array_add_id(chat_ids, last_chat_id); } + last_chat_id = chat_id; + matches = 0; + mismatches = 0; } - if matches == dc_array_get_cnt(contact_ids) && mismatches == 0 { - dc_array_add_id(chat_ids, last_chat_id); + if contact_id == dc_array_get_id(contact_ids, matches as size_t) { + matches = matches.wrapping_add(1) + } else { + mismatches = mismatches.wrapping_add(1) } } + if matches == dc_array_get_cnt(contact_ids) && mismatches == 0 { + dc_array_add_id(chat_ids, last_chat_id); + } } } + sqlite3_finalize(stmt); free(contact_ids_str as *mut libc::c_void); dc_array_unref(contact_ids); @@ -1859,7 +1865,7 @@ unsafe fn search_chat_ids_by_contact_ids( return chat_ids; } unsafe fn check_verified_properties( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut mimeparser: *mut dc_mimeparser_t, mut from_id: uint32_t, mut to_ids: *const dc_array_t, @@ -1872,7 +1878,7 @@ unsafe fn check_verified_properties( let mut to_ids_str: *mut libc::c_char = 0 as *mut libc::c_char; let mut q3: *mut libc::c_char = 0 as *mut libc::c_char; let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; - if 0 == dc_contact_load_from_db(contact, (*context).sql, from_id) { + if 0 == dc_contact_load_from_db(contact, &context.sql.clone().read().unwrap(), from_id) { *failure_reason = dc_mprintf( b"%s. See \"Info\" for details.\x00" as *const u8 as *const libc::c_char, b"Internal Error; cannot load contact.\x00" as *const u8 as *const libc::c_char, @@ -1890,8 +1896,11 @@ unsafe fn check_verified_properties( // this check is skipped for SELF as there is no proper SELF-peerstate // and results in group-splits otherwise. if from_id != 1i32 as libc::c_uint { - if 0 == dc_apeerstate_load_by_addr(peerstate, (*context).sql, (*contact).addr) - || dc_contact_is_verified_ex(contact, peerstate) != 2i32 + if 0 == dc_apeerstate_load_by_addr( + peerstate, + &context.sql.clone().read().unwrap(), + (*contact).addr, + ) || dc_contact_is_verified_ex(contact, peerstate) != 2i32 { *failure_reason = dc_mprintf( b"%s. See \"Info\" for details.\x00" as *const u8 as *const libc::c_char, @@ -1928,7 +1937,7 @@ unsafe fn check_verified_properties( sqlite3_mprintf(b"SELECT c.addr, LENGTH(ps.verified_key_fingerprint) FROM contacts c LEFT JOIN acpeerstates ps ON c.addr=ps.addr WHERE c.id IN(%s) \x00" as *const u8 as *const libc::c_char, to_ids_str); - stmt = dc_sqlite3_prepare((*context).sql, q3); + stmt = dc_sqlite3_prepare(context, &context.sql.clone().read().unwrap(), q3); loop { if !(sqlite3_step(stmt) == 100i32) { current_block = 2604890879466389055; @@ -1943,7 +1952,11 @@ unsafe fn check_verified_properties( strlen(to_addr) as libc::c_int, ) .is_null() - && 0 != dc_apeerstate_load_by_addr(peerstate, (*context).sql, to_addr) + && 0 != dc_apeerstate_load_by_addr( + peerstate, + &context.sql.clone().read().unwrap(), + to_addr, + ) { if 0 == is_verified || strcmp( @@ -1968,7 +1981,11 @@ unsafe fn check_verified_properties( (*peerstate).gossip_key_fingerprint, 2i32, ); - dc_apeerstate_save_to_db(peerstate, (*context).sql, 0i32); + dc_apeerstate_save_to_db( + peerstate, + &context.sql.clone().read().unwrap(), + 0i32, + ); is_verified = 1i32 } } @@ -2018,12 +2035,12 @@ unsafe fn set_better_msg( }; } unsafe fn dc_is_reply_to_known_message( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut mime_parser: *mut dc_mimeparser_t, ) -> libc::c_int { /* check if the message is a reply to a known message; the replies are identified by the Message-ID from `In-Reply-To`/`References:` (to support non-Delta-Clients) or from `Chat-Predecessor:` (Delta clients, see comment in dc_chat.c) */ - let mut optional_field: *mut mailimf_optional_field = 0 as *mut mailimf_optional_field; + let mut optional_field: *mut mailimf_optional_field; optional_field = dc_mimeparser_lookup_optional_field( mime_parser, b"Chat-Predecessor\x00" as *const u8 as *const libc::c_char, @@ -2033,7 +2050,7 @@ unsafe fn dc_is_reply_to_known_message( return 1i32; } } - let mut field: *mut mailimf_field = 0 as *mut mailimf_field; + let mut field: *mut mailimf_field; field = dc_mimeparser_lookup_field( mime_parser, b"In-Reply-To\x00" as *const u8 as *const libc::c_char, @@ -2067,11 +2084,11 @@ unsafe fn dc_is_reply_to_known_message( return 0i32; } unsafe fn is_known_rfc724_mid_in_list( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut mid_list: *const clist, ) -> libc::c_int { if !mid_list.is_null() { - let mut cur: *mut clistiter = 0 as *mut clistiter; + let mut cur: *mut clistiter; cur = (*mid_list).first; while !cur.is_null() { if 0 != is_known_rfc724_mid( @@ -2087,7 +2104,7 @@ unsafe fn is_known_rfc724_mid_in_list( cur = if !cur.is_null() { (*cur).next } else { - 0 as *mut clistcell_s + 0 as *mut clistcell } } } @@ -2097,13 +2114,13 @@ unsafe fn is_known_rfc724_mid_in_list( * Check if a message is a reply to a known message (messenger or non-messenger) ******************************************************************************/ unsafe fn is_known_rfc724_mid( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut rfc724_mid: *const libc::c_char, ) -> libc::c_int { let mut is_known: libc::c_int = 0i32; if !rfc724_mid.is_null() { let mut stmt: *mut sqlite3_stmt = - dc_sqlite3_prepare((*context).sql, + dc_sqlite3_prepare(context, &context.sql.clone().read().unwrap(), b"SELECT m.id FROM msgs m LEFT JOIN chats c ON m.chat_id=c.id WHERE m.rfc724_mid=? AND m.chat_id>9 AND c.blocked=0;\x00" as *const u8 as *const libc::c_char); sqlite3_bind_text(stmt, 1i32, rfc724_mid, -1i32, None); @@ -2115,7 +2132,7 @@ unsafe fn is_known_rfc724_mid( return is_known; } unsafe fn dc_is_reply_to_messenger_message( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut mime_parser: *mut dc_mimeparser_t, ) -> libc::c_int { /* function checks, if the message defined by mime_parser references a message send by us from Delta Chat. @@ -2123,7 +2140,7 @@ unsafe fn dc_is_reply_to_messenger_message( - checks also if any of the referenced IDs are send by a messenger - it is okay, if the referenced messages are moved to trash here - no check for the Chat-* headers (function is only called if it is no messenger message itself) */ - let mut field: *mut mailimf_field = 0 as *mut mailimf_field; + let mut field: *mut mailimf_field; field = dc_mimeparser_lookup_field( mime_parser, b"In-Reply-To\x00" as *const u8 as *const libc::c_char, @@ -2157,7 +2174,7 @@ unsafe fn dc_is_reply_to_messenger_message( return 0i32; } unsafe fn is_msgrmsg_rfc724_mid_in_list( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut mid_list: *const clist, ) -> libc::c_int { if !mid_list.is_null() { @@ -2176,7 +2193,7 @@ unsafe fn is_msgrmsg_rfc724_mid_in_list( cur = if !cur.is_null() { (*cur).next } else { - 0 as *mut clistcell_s + 0 as *mut clistcell } } } @@ -2186,13 +2203,14 @@ unsafe fn is_msgrmsg_rfc724_mid_in_list( * Check if a message is a reply to any messenger message ******************************************************************************/ unsafe fn is_msgrmsg_rfc724_mid( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut rfc724_mid: *const libc::c_char, ) -> libc::c_int { let mut is_msgrmsg: libc::c_int = 0i32; if !rfc724_mid.is_null() { let mut stmt: *mut sqlite3_stmt = dc_sqlite3_prepare( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"SELECT id FROM msgs WHERE rfc724_mid=? AND msgrmsg!=0 AND chat_id>9;\x00" as *const u8 as *const libc::c_char, ); @@ -2205,14 +2223,13 @@ unsafe fn is_msgrmsg_rfc724_mid( return is_msgrmsg; } unsafe fn dc_add_or_lookup_contacts_by_address_list( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut adr_list: *const mailimf_address_list, mut origin: libc::c_int, mut ids: *mut dc_array_t, mut check_self: *mut libc::c_int, ) { - if context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint || adr_list.is_null() - { + if adr_list.is_null() { return; } let mut cur: *mut clistiter = (*(*adr_list).ad_list).first; @@ -2251,18 +2268,18 @@ unsafe fn dc_add_or_lookup_contacts_by_address_list( cur = if !cur.is_null() { (*cur).next } else { - 0 as *mut clistcell_s + 0 as *mut clistcell } } } unsafe fn dc_add_or_lookup_contacts_by_mailbox_list( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut mb_list: *const mailimf_mailbox_list, mut origin: libc::c_int, mut ids: *mut dc_array_t, mut check_self: *mut libc::c_int, ) { - if context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint || mb_list.is_null() { + if mb_list.is_null() { return; } let mut cur: *mut clistiter = (*(*mb_list).mb_list).first; @@ -2285,7 +2302,7 @@ unsafe fn dc_add_or_lookup_contacts_by_mailbox_list( cur = if !cur.is_null() { (*cur).next } else { - 0 as *mut clistcell_s + 0 as *mut clistcell } } } @@ -2293,7 +2310,7 @@ unsafe fn dc_add_or_lookup_contacts_by_mailbox_list( * Add contacts to database on receiving messages ******************************************************************************/ unsafe fn add_or_lookup_contact_by_addr( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut display_name_enc: *const libc::c_char, mut addr_spec: *const libc::c_char, mut origin: libc::c_int, @@ -2305,13 +2322,13 @@ unsafe fn add_or_lookup_contact_by_addr( if check_self.is_null() { check_self = &mut dummy } - if context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint || addr_spec.is_null() - { + if addr_spec.is_null() { return; } *check_self = 0i32; let mut self_addr: *mut libc::c_char = dc_sqlite3_get_config( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"configured_addr\x00" as *const u8 as *const libc::c_char, b"\x00" as *const u8 as *const libc::c_char, ); diff --git a/src/dc_saxparser.rs b/src/dc_saxparser.rs index e8aa7569b..a78994fdc 100644 --- a/src/dc_saxparser.rs +++ b/src/dc_saxparser.rs @@ -1,5 +1,3 @@ -use libc; - use crate::dc_tools::*; use crate::types::*; use crate::x::*; @@ -31,6 +29,7 @@ pub unsafe extern "C" fn dc_saxparser_init( (*saxparser).endtag_cb = Some(def_endtag_cb); (*saxparser).text_cb = Some(def_text_cb); } + unsafe fn def_text_cb(_userdata: *mut libc::c_void, _text: *const libc::c_char, _len: libc::c_int) { } @@ -65,6 +64,7 @@ pub unsafe fn dc_saxparser_set_tag_handler( Some(def_endtag_cb) }; } + pub unsafe fn dc_saxparser_set_text_handler( mut saxparser: *mut dc_saxparser_t, mut text_cb: dc_saxparser_text_cb_t, @@ -78,15 +78,16 @@ pub unsafe fn dc_saxparser_set_text_handler( Some(def_text_cb) }; } + pub unsafe fn dc_saxparser_parse( mut saxparser: *mut dc_saxparser_t, mut buf_start__: *const libc::c_char, ) { let mut current_block: u64; - let mut bak: libc::c_char = 0i32 as libc::c_char; - let mut buf_start: *mut libc::c_char = 0 as *mut libc::c_char; - let mut last_text_start: *mut libc::c_char = 0 as *mut libc::c_char; - let mut p: *mut libc::c_char = 0 as *mut libc::c_char; + let mut bak: libc::c_char; + let mut buf_start: *mut libc::c_char; + let mut last_text_start: *mut libc::c_char; + let mut p: *mut libc::c_char; /* attributes per tag - a fixed border here is a security feature, not a limit */ /* attributes as key/value pairs, +1 for terminating the list */ let mut attr: [*mut libc::c_char; 202] = [0 as *mut libc::c_char; 202]; @@ -205,7 +206,7 @@ pub unsafe fn dc_saxparser_parse( if p != beg_tag_name_0 { let mut after_tag_name: *mut libc::c_char = p; let mut attr_index: libc::c_int = 0i32; - while 0 != isspace(*p as libc::c_int) { + while 0 != libc::isspace(*p as libc::c_int) { p = p.offset(1isize) } while 0 != *p as libc::c_int @@ -214,7 +215,7 @@ pub unsafe fn dc_saxparser_parse( { let mut beg_attr_name: *mut libc::c_char = p; let mut beg_attr_value: *mut libc::c_char = 0 as *mut libc::c_char; - let mut beg_attr_value_new: *mut libc::c_char = 0 as *mut libc::c_char; + let mut beg_attr_value_new: *mut libc::c_char; if '=' as i32 == *beg_attr_name as libc::c_int { p = p.offset(1isize) } else { @@ -301,7 +302,7 @@ pub unsafe fn dc_saxparser_parse( attr_index += 2i32 } } - while 0 != isspace(*p as libc::c_int) { + while 0 != libc::isspace(*p as libc::c_int) { p = p.offset(1isize) } } @@ -356,6 +357,7 @@ pub unsafe fn dc_saxparser_parse( do_free_attr(attr.as_mut_ptr(), free_attr.as_mut_ptr()); free(buf_start as *mut libc::c_void); } + unsafe fn do_free_attr(mut attr: *mut *mut libc::c_char, mut free_attr: *mut libc::c_int) { /* "attr" are key/value pairs; the function frees the data if the corresponding bit in "free_attr" is set. (we need this as we try to use the strings from the "main" document instead of allocating small strings) */ @@ -376,6 +378,7 @@ unsafe fn do_free_attr(mut attr: *mut *mut libc::c_char, mut free_attr: *mut lib let ref mut fresh0 = *attr.offset(0isize); *fresh0 = 0 as *mut libc::c_char; } + unsafe fn call_text_cb( mut saxparser: *mut dc_saxparser_t, mut text: *mut libc::c_char, @@ -384,7 +387,7 @@ unsafe fn call_text_cb( ) { if !text.is_null() && 0 != len { let mut bak: libc::c_char = *text.offset(len as isize); - let mut text_new: *mut libc::c_char = 0 as *mut libc::c_char; + let mut text_new: *mut libc::c_char; *text.offset(len as isize) = '\u{0}' as i32 as libc::c_char; text_new = xml_decode(text, type_0); (*saxparser).text_cb.expect("non-null function pointer")( @@ -398,6 +401,7 @@ unsafe fn call_text_cb( *text.offset(len as isize) = bak }; } + /* Convert entities as ä to UTF-8 characters. - The first strings MUST NOT start with `&` and MUST end with `;`. @@ -421,10 +425,10 @@ unsafe fn xml_decode(mut s: *mut libc::c_char, mut type_0: libc::c_char) -> *mut let mut e: *mut libc::c_char = 0 as *mut libc::c_char; let mut r: *mut libc::c_char = s; let mut original_buf: *const libc::c_char = s; - let mut b = 0; - let mut c: isize = 0; - let mut d: isize = 0; - let mut l: isize = 0; + let mut b; + let mut c: isize; + let mut d: isize; + let mut l: isize; while 0 != *s { while *s as libc::c_int == '\r' as i32 { let fresh1 = s; @@ -444,7 +448,7 @@ unsafe fn xml_decode(mut s: *mut libc::c_char, mut type_0: libc::c_char) -> *mut loop { while 0 != *s as libc::c_int && *s as libc::c_int != '&' as i32 - && 0 == isspace(*s as libc::c_int) + && 0 == libc::isspace(*s as libc::c_int) { s = s.offset(1isize) } @@ -539,7 +543,7 @@ unsafe fn xml_decode(mut s: *mut libc::c_char, mut type_0: libc::c_char) -> *mut } else { s = s.offset(1isize) } - } else if type_0 as libc::c_int == ' ' as i32 && 0 != isspace(*s as libc::c_int) { + } else if type_0 as libc::c_int == ' ' as i32 && 0 != libc::isspace(*s as libc::c_int) { let fresh6 = s; s = s.offset(1); *fresh6 = ' ' as i32 as libc::c_char @@ -547,8 +551,10 @@ unsafe fn xml_decode(mut s: *mut libc::c_char, mut type_0: libc::c_char) -> *mut s = s.offset(1isize) } } - return r; + + r } + /* dc_saxparser_t parses XML and HTML files that may not be wellformed and spits out all text and tags found. @@ -1077,6 +1083,7 @@ static mut s_ent: [*const libc::c_char; 508] = [ 0 as *const libc::c_char, 0 as *const libc::c_char, ]; + pub unsafe fn dc_attr_find( mut attr: *mut *mut libc::c_char, mut key: *const libc::c_char, @@ -1090,5 +1097,6 @@ pub unsafe fn dc_attr_find( return *attr.offset((i + 1i32) as isize); } } - return 0 as *const libc::c_char; + + 0 as *const libc::c_char } diff --git a/src/dc_securejoin.rs b/src/dc_securejoin.rs index 9a8525884..b9e243cca 100644 --- a/src/dc_securejoin.rs +++ b/src/dc_securejoin.rs @@ -1,4 +1,4 @@ -use libc; +use mmime::mailimf_types::*; use crate::constants::Event; use crate::dc_apeerstate::*; @@ -25,7 +25,7 @@ use crate::types::*; use crate::x::*; pub unsafe fn dc_get_securejoin_qr( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut group_chat_id: uint32_t, ) -> *mut libc::c_char { let mut current_block: u64; @@ -34,101 +34,102 @@ pub unsafe fn dc_get_securejoin_qr( ==== Step 1 in "Setup verified contact" protocol ==== ========================================================= */ let mut qr: *mut libc::c_char = 0 as *mut libc::c_char; - let mut self_addr: *mut libc::c_char = 0 as *mut libc::c_char; + let mut self_addr: *mut libc::c_char; let mut self_addr_urlencoded: *mut libc::c_char = 0 as *mut libc::c_char; let mut self_name: *mut libc::c_char = 0 as *mut libc::c_char; let mut self_name_urlencoded: *mut libc::c_char = 0 as *mut libc::c_char; let mut fingerprint: *mut libc::c_char = 0 as *mut libc::c_char; - let mut invitenumber: *mut libc::c_char = 0 as *mut libc::c_char; - let mut auth: *mut libc::c_char = 0 as *mut libc::c_char; + let mut invitenumber: *mut libc::c_char; + let mut auth: *mut libc::c_char; let mut chat: *mut dc_chat_t = 0 as *mut dc_chat_t; let mut group_name: *mut libc::c_char = 0 as *mut libc::c_char; let mut group_name_urlencoded: *mut libc::c_char = 0 as *mut libc::c_char; - if !(context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint) { - dc_ensure_secret_key_exists(context); - invitenumber = dc_token_lookup(context, DC_TOKEN_INVITENUMBER, group_chat_id); - if invitenumber.is_null() { - invitenumber = dc_create_id(); - dc_token_save(context, DC_TOKEN_INVITENUMBER, group_chat_id, invitenumber); - } - auth = dc_token_lookup(context, DC_TOKEN_AUTH, group_chat_id); - if auth.is_null() { - auth = dc_create_id(); - dc_token_save(context, DC_TOKEN_AUTH, group_chat_id, auth); - } - self_addr = dc_sqlite3_get_config( - (*context).sql, - b"configured_addr\x00" as *const u8 as *const libc::c_char, - 0 as *const libc::c_char, + + dc_ensure_secret_key_exists(context); + invitenumber = dc_token_lookup(context, DC_TOKEN_INVITENUMBER, group_chat_id); + if invitenumber.is_null() { + invitenumber = dc_create_id(); + dc_token_save(context, DC_TOKEN_INVITENUMBER, group_chat_id, invitenumber); + } + auth = dc_token_lookup(context, DC_TOKEN_AUTH, group_chat_id); + if auth.is_null() { + auth = dc_create_id(); + dc_token_save(context, DC_TOKEN_AUTH, group_chat_id, auth); + } + self_addr = dc_sqlite3_get_config( + context, + &context.sql.clone().read().unwrap(), + b"configured_addr\x00" as *const u8 as *const libc::c_char, + 0 as *const libc::c_char, + ); + if self_addr.is_null() { + dc_log_error( + context, + 0i32, + b"Not configured, cannot generate QR code.\x00" as *const u8 as *const libc::c_char, ); - if self_addr.is_null() { - dc_log_error( - context, - 0i32, - b"Not configured, cannot generate QR code.\x00" as *const u8 as *const libc::c_char, - ); - } else { - self_name = dc_sqlite3_get_config( - (*context).sql, - b"displayname\x00" as *const u8 as *const libc::c_char, - b"\x00" as *const u8 as *const libc::c_char, - ); - fingerprint = get_self_fingerprint(context); - if !fingerprint.is_null() { - self_addr_urlencoded = dc_urlencode(self_addr); - self_name_urlencoded = dc_urlencode(self_name); - if 0 != group_chat_id { - chat = dc_get_chat(context, group_chat_id); - if chat.is_null() { - dc_log_error( - context, - 0i32, - b"Cannot get QR-code for chat-id %i\x00" as *const u8 - as *const libc::c_char, - group_chat_id, - ); - current_block = 9531737720721467826; - } else { - group_name = dc_chat_get_name(chat); - group_name_urlencoded = dc_urlencode(group_name); - qr = dc_mprintf( - b"OPENPGP4FPR:%s#a=%s&g=%s&x=%s&i=%s&s=%s\x00" as *const u8 - as *const libc::c_char, - fingerprint, - self_addr_urlencoded, - group_name_urlencoded, - (*chat).grpid, - invitenumber, - auth, - ); - current_block = 1118134448028020070; - } + } else { + self_name = dc_sqlite3_get_config( + context, + &context.sql.clone().read().unwrap(), + b"displayname\x00" as *const u8 as *const libc::c_char, + b"\x00" as *const u8 as *const libc::c_char, + ); + fingerprint = get_self_fingerprint(context); + if !fingerprint.is_null() { + self_addr_urlencoded = dc_urlencode(self_addr); + self_name_urlencoded = dc_urlencode(self_name); + if 0 != group_chat_id { + chat = dc_get_chat(context, group_chat_id); + if chat.is_null() { + dc_log_error( + context, + 0i32, + b"Cannot get QR-code for chat-id %i\x00" as *const u8 + as *const libc::c_char, + group_chat_id, + ); + current_block = 9531737720721467826; } else { + group_name = dc_chat_get_name(chat); + group_name_urlencoded = dc_urlencode(group_name); qr = dc_mprintf( - b"OPENPGP4FPR:%s#a=%s&n=%s&i=%s&s=%s\x00" as *const u8 + b"OPENPGP4FPR:%s#a=%s&g=%s&x=%s&i=%s&s=%s\x00" as *const u8 as *const libc::c_char, fingerprint, self_addr_urlencoded, - self_name_urlencoded, + group_name_urlencoded, + (*chat).grpid, invitenumber, auth, ); current_block = 1118134448028020070; } - match current_block { - 9531737720721467826 => {} - _ => { - dc_log_info( - context, - 0i32, - b"Generated QR code: %s\x00" as *const u8 as *const libc::c_char, - qr, - ); - } + } else { + qr = dc_mprintf( + b"OPENPGP4FPR:%s#a=%s&n=%s&i=%s&s=%s\x00" as *const u8 as *const libc::c_char, + fingerprint, + self_addr_urlencoded, + self_name_urlencoded, + invitenumber, + auth, + ); + current_block = 1118134448028020070; + } + match current_block { + 9531737720721467826 => {} + _ => { + dc_log_info( + context, + 0i32, + b"Generated QR code: %s\x00" as *const u8 as *const libc::c_char, + qr, + ); } } } } + free(self_addr_urlencoded as *mut libc::c_void); free(self_addr as *mut libc::c_void); free(self_name as *mut libc::c_void); @@ -145,25 +146,36 @@ pub unsafe fn dc_get_securejoin_qr( dc_strdup(0 as *const libc::c_char) }; } -unsafe fn get_self_fingerprint(mut context: *mut dc_context_t) -> *mut libc::c_char { - let mut self_addr: *mut libc::c_char = 0 as *mut libc::c_char; + +unsafe fn get_self_fingerprint(mut context: &dc_context_t) -> *mut libc::c_char { + let mut self_addr: *mut libc::c_char; let mut self_key: *mut dc_key_t = dc_key_new(); let mut fingerprint: *mut libc::c_char = 0 as *mut libc::c_char; self_addr = dc_sqlite3_get_config( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"configured_addr\x00" as *const u8 as *const libc::c_char, 0 as *const libc::c_char, ); - if !(self_addr.is_null() || 0 == dc_key_load_self_public(self_key, self_addr, (*context).sql)) { - fingerprint = dc_key_get_fingerprint(self_key); + if !(self_addr.is_null() + || 0 == dc_key_load_self_public( + context, + self_key, + self_addr, + &context.sql.clone().read().unwrap(), + )) + { + fingerprint = dc_key_get_fingerprint(context, self_key); fingerprint.is_null(); } free(self_addr as *mut libc::c_void); dc_key_unref(self_key); - return fingerprint; + + fingerprint } + pub unsafe fn dc_join_securejoin( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut qr: *const libc::c_char, ) -> uint32_t { /* ========================================================== @@ -171,11 +183,10 @@ pub unsafe fn dc_join_securejoin( ==== Step 2 in "Setup verified contact" protocol ===== ========================================================== */ let mut ret_chat_id: libc::c_int = 0i32; - let mut ongoing_allocated: libc::c_int = 0i32; + let mut ongoing_allocated: libc::c_int; let mut contact_chat_id: uint32_t = 0i32 as uint32_t; let mut join_vg: libc::c_int = 0i32; let mut qr_scan: *mut dc_lot_t = 0 as *mut dc_lot_t; - let mut qr_locked: libc::c_int = 0i32; dc_log_info( context, 0i32, @@ -199,16 +210,18 @@ pub unsafe fn dc_join_securejoin( 0i32, b"Unknown contact.\x00" as *const u8 as *const libc::c_char, ); - } else if !(0 != (*context).shall_stop_ongoing) { + } else if !(context + .running_state + .clone() + .read() + .unwrap() + .shall_stop_ongoing) + { join_vg = ((*qr_scan).state == 202i32) as libc::c_int; - (*context).bobs_status = 0i32; - pthread_mutex_lock(&mut (*context).bobs_qr_critical); - qr_locked = 1i32; - (*context).bobs_qr_scan = qr_scan; - if 0 != qr_locked { - pthread_mutex_unlock(&mut (*context).bobs_qr_critical); - qr_locked = 0i32 - } + let bob_a = context.bob.clone(); + let mut bob = bob_a.write().unwrap(); + bob.status = 0; + bob.qr_scan = qr_scan; if 0 != fingerprint_equals_sender(context, (*qr_scan).fingerprint, contact_chat_id) { dc_log_info( @@ -216,8 +229,8 @@ pub unsafe fn dc_join_securejoin( 0i32, b"Taking protocol shortcut.\x00" as *const u8 as *const libc::c_char, ); - (*context).bob_expects = 6i32; - ((*context).cb)( + bob.expects = 6; + (context.cb)( context, Event::SECUREJOIN_JOINER_PROGRESS, chat_id_2_contact_id(context, contact_chat_id) as uintptr_t, @@ -242,7 +255,7 @@ pub unsafe fn dc_join_securejoin( ); free(own_fingerprint as *mut libc::c_void); } else { - (*context).bob_expects = 2i32; + bob.expects = 2; send_handshake_msg( context, contact_chat_id, @@ -257,14 +270,23 @@ pub unsafe fn dc_join_securejoin( ); } // Bob -> Alice - while !(0 != (*context).shall_stop_ongoing) { + while !(context + .running_state + .clone() + .read() + .unwrap() + .shall_stop_ongoing) + { usleep((300i32 * 1000i32) as useconds_t); } } } } - (*context).bob_expects = 0i32; - if (*context).bobs_status == 1i32 { + let bob_a = context.bob.clone(); + let mut bob = bob_a.write().unwrap(); + + bob.expects = 0; + if bob.status == 1 { if 0 != join_vg { ret_chat_id = dc_get_chat_id_by_grpid( context, @@ -276,21 +298,17 @@ pub unsafe fn dc_join_securejoin( ret_chat_id = contact_chat_id as libc::c_int } } - pthread_mutex_lock(&mut (*context).bobs_qr_critical); - qr_locked = 1i32; - (*context).bobs_qr_scan = 0 as *mut dc_lot_t; - if 0 != qr_locked { - pthread_mutex_unlock(&mut (*context).bobs_qr_critical); - qr_locked = 0i32 - } + bob.qr_scan = std::ptr::null_mut(); + dc_lot_unref(qr_scan); if 0 != ongoing_allocated { dc_free_ongoing(context); } - return ret_chat_id as uint32_t; + ret_chat_id as uint32_t } + unsafe fn send_handshake_msg( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut contact_chat_id: uint32_t, mut step: *const libc::c_char, mut param2: *const libc::c_char, @@ -325,8 +343,9 @@ unsafe fn send_handshake_msg( dc_send_msg(context, contact_chat_id, msg); dc_msg_unref(msg); } + unsafe fn chat_id_2_contact_id( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut contact_chat_id: uint32_t, ) -> uint32_t { let mut contact_id: uint32_t = 0i32 as uint32_t; @@ -335,10 +354,12 @@ unsafe fn chat_id_2_contact_id( contact_id = dc_array_get_id(contacts, 0i32 as size_t) } dc_array_unref(contacts); - return contact_id; + + contact_id } + unsafe fn fingerprint_equals_sender( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut fingerprint: *const libc::c_char, mut contact_chat_id: uint32_t, ) -> libc::c_int { @@ -351,10 +372,14 @@ unsafe fn fingerprint_equals_sender( if !(0 == dc_contact_load_from_db( contact, - (*context).sql, + &context.sql.clone().read().unwrap(), dc_array_get_id(contacts, 0i32 as size_t), ) - || 0 == dc_apeerstate_load_by_addr(peerstate, (*context).sql, (*contact).addr)) + || 0 == dc_apeerstate_load_by_addr( + peerstate, + &context.sql.clone().read().unwrap(), + (*contact).addr, + )) { fingerprint_normalized = dc_normalize_fingerprint(fingerprint); if strcasecmp(fingerprint_normalized, (*peerstate).public_key_fingerprint) == 0i32 { @@ -365,18 +390,19 @@ unsafe fn fingerprint_equals_sender( free(fingerprint_normalized as *mut libc::c_void); dc_contact_unref(contact); dc_array_unref(contacts); - return fingerprint_equal; + + fingerprint_equal } + /* library private: secure-join */ pub unsafe fn dc_handle_securejoin_handshake( - mut context: *mut dc_context_t, - mut mimeparser: *mut dc_mimeparser_t, - mut contact_id: uint32_t, + context: &dc_context_t, + mimeparser: *mut dc_mimeparser_t, + contact_id: uint32_t, ) -> libc::c_int { let mut current_block: u64; - let mut qr_locked: libc::c_int = 0i32; - let mut step: *const libc::c_char = 0 as *const libc::c_char; - let mut join_vg: libc::c_int = 0i32; + let mut step: *const libc::c_char; + let mut join_vg: libc::c_int; let mut scanned_fingerprint_of_alice: *mut libc::c_char = 0 as *mut libc::c_char; let mut auth: *mut libc::c_char = 0 as *mut libc::c_char; let mut own_fingerprint: *mut libc::c_char = 0 as *mut libc::c_char; @@ -385,7 +411,7 @@ pub unsafe fn dc_handle_securejoin_handshake( let mut grpid: *mut libc::c_char = 0 as *mut libc::c_char; let mut ret: libc::c_int = 0i32; let mut contact: *mut dc_contact_t = 0 as *mut dc_contact_t; - if !(context.is_null() || mimeparser.is_null() || contact_id <= 9i32 as libc::c_uint) { + if !(mimeparser.is_null() || contact_id <= 9i32 as libc::c_uint) { step = lookup_field( mimeparser, b"Secure-Join\x00" as *const u8 as *const libc::c_char, @@ -422,7 +448,7 @@ pub unsafe fn dc_handle_securejoin_handshake( // it just ensures, we have Bobs key now. If we do _not_ have the key because eg. MitM has removed it, // send_message() will fail with the error "End-to-end-encryption unavailable unexpectedly.", so, there is no additional check needed here. // verify that the `Secure-Join-Invitenumber:`-header matches invitenumber written to the QR code - let mut invitenumber: *const libc::c_char = 0 as *const libc::c_char; + let mut invitenumber: *const libc::c_char; invitenumber = lookup_field( mimeparser, b"Secure-Join-Invitenumber\x00" as *const u8 as *const libc::c_char, @@ -449,7 +475,7 @@ pub unsafe fn dc_handle_securejoin_handshake( 0i32, b"Secure-join requested.\x00" as *const u8 as *const libc::c_char, ); - ((*context).cb)( + (context.cb)( context, Event::SECUREJOIN_INVITER_PROGRESS, contact_id as uintptr_t, @@ -478,11 +504,10 @@ pub unsafe fn dc_handle_securejoin_handshake( b"vc-auth-required\x00" as *const u8 as *const libc::c_char, ) == 0i32 { - pthread_mutex_lock(&mut (*context).bobs_qr_critical); - qr_locked = 1i32; - if (*context).bobs_qr_scan.is_null() - || (*context).bob_expects != 2i32 - || 0 != join_vg && (*(*context).bobs_qr_scan).state != 202i32 + let bob_a = context.bob.clone(); + let bob = bob_a.read().unwrap(); + let scan = bob.qr_scan; + if scan.is_null() || bob.expects != 2i32 || 0 != join_vg && (*scan).state != 202i32 { dc_log_warning( context, @@ -493,15 +518,10 @@ pub unsafe fn dc_handle_securejoin_handshake( // no error, just aborted somehow or a mail from another handshake current_block = 4378276786830486580; } else { - scanned_fingerprint_of_alice = - dc_strdup((*(*context).bobs_qr_scan).fingerprint); - auth = dc_strdup((*(*context).bobs_qr_scan).auth); + scanned_fingerprint_of_alice = dc_strdup((*scan).fingerprint); + auth = dc_strdup((*scan).auth); if 0 != join_vg { - grpid = dc_strdup((*(*context).bobs_qr_scan).text2) - } - if 0 != qr_locked { - pthread_mutex_unlock(&mut (*context).bobs_qr_critical); - qr_locked = 0i32 + grpid = dc_strdup((*scan).text2) } if 0 == encrypted_and_signed(mimeparser, scanned_fingerprint_of_alice) { could_not_establish_secure_connection( @@ -537,13 +557,14 @@ pub unsafe fn dc_handle_securejoin_handshake( b"Fingerprint verified.\x00" as *const u8 as *const libc::c_char, ); own_fingerprint = get_self_fingerprint(context); - ((*context).cb)( + (context.cb)( context, Event::SECUREJOIN_JOINER_PROGRESS, contact_id as uintptr_t, 400i32 as uintptr_t, ); - (*context).bob_expects = 6i32; + context.bob.clone().write().unwrap().expects = 6; + send_handshake_msg( context, contact_chat_id, @@ -574,7 +595,7 @@ pub unsafe fn dc_handle_securejoin_handshake( ==== Step 6 in "Out-of-band verified groups" protocol ==== ============================================================ */ // verify that Secure-Join-Fingerprint:-header matches the fingerprint of Bob - let mut fingerprint: *const libc::c_char = 0 as *const libc::c_char; + let mut fingerprint: *const libc::c_char; fingerprint = lookup_field( mimeparser, b"Secure-Join-Fingerprint\x00" as *const u8 as *const libc::c_char, @@ -608,7 +629,7 @@ pub unsafe fn dc_handle_securejoin_handshake( b"Fingerprint verified.\x00" as *const u8 as *const libc::c_char, ); // verify that the `Secure-Join-Auth:`-header matches the secret written to the QR code - let mut auth_0: *const libc::c_char = 0 as *const libc::c_char; + let mut auth_0: *const libc::c_char; auth_0 = lookup_field( mimeparser, b"Secure-Join-Auth\x00" as *const u8 as *const libc::c_char, @@ -643,13 +664,13 @@ pub unsafe fn dc_handle_securejoin_handshake( b"Auth verified.\x00" as *const u8 as *const libc::c_char, ); secure_connection_established(context, contact_chat_id); - ((*context).cb)( + (context.cb)( context, Event::CONTACTS_CHANGED, contact_id as uintptr_t, 0i32 as uintptr_t, ); - ((*context).cb)( + (context.cb)( context, Event::SECUREJOIN_INVITER_PROGRESS, contact_id as uintptr_t, @@ -692,7 +713,7 @@ pub unsafe fn dc_handle_securejoin_handshake( 0 as *const libc::c_char, 0 as *const libc::c_char, ); - ((*context).cb)( + (context.cb)( context, Event::SECUREJOIN_INVITER_PROGRESS, contact_id as uintptr_t, @@ -714,7 +735,7 @@ pub unsafe fn dc_handle_securejoin_handshake( if 0 != join_vg { ret = 0x1i32 } - if (*context).bob_expects != 6i32 { + if context.bob.clone().read().unwrap().expects != 6 { dc_log_info( context, 0i32, @@ -723,11 +744,8 @@ pub unsafe fn dc_handle_securejoin_handshake( ); current_block = 4378276786830486580; } else { - pthread_mutex_lock(&mut (*context).bobs_qr_critical); - qr_locked = 1i32; - if (*context).bobs_qr_scan.is_null() - || 0 != join_vg && (*(*context).bobs_qr_scan).state != 202i32 - { + let scan = context.bob.clone().read().unwrap().qr_scan; + if scan.is_null() || 0 != join_vg && (*scan).state != 202i32 { dc_log_warning( context, 0i32, @@ -736,14 +754,9 @@ pub unsafe fn dc_handle_securejoin_handshake( ); current_block = 4378276786830486580; } else { - scanned_fingerprint_of_alice = - dc_strdup((*(*context).bobs_qr_scan).fingerprint); + scanned_fingerprint_of_alice = dc_strdup((*scan).fingerprint); if 0 != join_vg { - grpid = dc_strdup((*(*context).bobs_qr_scan).text2) - } - if 0 != qr_locked { - pthread_mutex_unlock(&mut (*context).bobs_qr_critical); - qr_locked = 0i32 + grpid = dc_strdup((*scan).text2) } let mut vg_expect_encrypted: libc::c_int = 1i32; if 0 != join_vg { @@ -788,7 +801,7 @@ pub unsafe fn dc_handle_securejoin_handshake( current_block = 4378276786830486580; } else { dc_scaleup_contact_origin(context, contact_id, 0x2000000i32); - ((*context).cb)( + (context.cb)( context, Event::CONTACTS_CHANGED, 0i32 as uintptr_t, @@ -818,7 +831,7 @@ pub unsafe fn dc_handle_securejoin_handshake( 4378276786830486580 => {} _ => { secure_connection_established(context, contact_chat_id); - (*context).bob_expects = 0i32; + context.bob.clone().write().unwrap().expects = 0; if 0 != join_vg { send_handshake_msg( context, @@ -858,13 +871,13 @@ pub unsafe fn dc_handle_securejoin_handshake( ); current_block = 4378276786830486580; } else { - ((*context).cb)( + (context.cb)( context, Event::SECUREJOIN_INVITER_PROGRESS, contact_id as uintptr_t, 800i32 as uintptr_t, ); - ((*context).cb)( + (context.cb)( context, Event::SECUREJOIN_INVITER_PROGRESS, contact_id as uintptr_t, @@ -885,25 +898,21 @@ pub unsafe fn dc_handle_securejoin_handshake( } } } - if 0 != qr_locked { - pthread_mutex_unlock(&mut (*context).bobs_qr_critical); - qr_locked = 0i32 - } dc_contact_unref(contact); free(scanned_fingerprint_of_alice as *mut libc::c_void); free(auth as *mut libc::c_void); free(own_fingerprint as *mut libc::c_void); free(grpid as *mut libc::c_void); - return ret; + + ret } -unsafe fn end_bobs_joining(mut context: *mut dc_context_t, mut status: libc::c_int) { - (*context).bobs_status = status; + +unsafe fn end_bobs_joining(context: &dc_context_t, status: libc::c_int) { + context.bob.clone().write().unwrap().status = status; dc_stop_ongoing_process(context); } -unsafe fn secure_connection_established( - mut context: *mut dc_context_t, - mut contact_chat_id: uint32_t, -) { + +unsafe fn secure_connection_established(mut context: &dc_context_t, mut contact_chat_id: uint32_t) { let mut contact_id: uint32_t = chat_id_2_contact_id(context, contact_chat_id); let mut contact: *mut dc_contact_t = dc_get_contact(context, contact_id); let mut msg: *mut libc::c_char = dc_stock_str_repl_string( @@ -916,7 +925,7 @@ unsafe fn secure_connection_established( }, ); dc_add_device_msg(context, contact_chat_id, msg); - ((*context).cb)( + (context.cb)( context, Event::CHAT_MODIFIED, contact_chat_id as uintptr_t, @@ -925,6 +934,7 @@ unsafe fn secure_connection_established( free(msg as *mut libc::c_void); dc_contact_unref(contact); } + unsafe fn lookup_field( mut mimeparser: *mut dc_mimeparser_t, mut key: *const libc::c_char, @@ -941,15 +951,17 @@ unsafe fn lookup_field( { return 0 as *const libc::c_char; } - return value; + + value } + unsafe fn could_not_establish_secure_connection( - mut context: *mut dc_context_t, - mut contact_chat_id: uint32_t, - mut details: *const libc::c_char, + context: &dc_context_t, + contact_chat_id: uint32_t, + details: *const libc::c_char, ) { let mut contact_id: uint32_t = chat_id_2_contact_id(context, contact_chat_id); - let mut contact: *mut dc_contact_t = dc_get_contact(context, contact_id); + let mut contact = dc_get_contact(context, contact_id); let mut msg: *mut libc::c_char = dc_stock_str_repl_string( context, 36i32, @@ -970,26 +982,37 @@ unsafe fn could_not_establish_secure_connection( free(msg as *mut libc::c_void); dc_contact_unref(contact); } + unsafe fn mark_peer_as_verified( - mut context: *mut dc_context_t, - mut fingerprint: *const libc::c_char, + context: &dc_context_t, + fingerprint: *const libc::c_char, ) -> libc::c_int { let mut success: libc::c_int = 0i32; - let mut peerstate: *mut dc_apeerstate_t = dc_apeerstate_new(context); - if !(0 == dc_apeerstate_load_by_fingerprint(peerstate, (*context).sql, fingerprint)) { + let mut peerstate = dc_apeerstate_new(context); + if !(0 + == dc_apeerstate_load_by_fingerprint( + peerstate, + &context.sql.clone().read().unwrap(), + fingerprint, + )) + { if !(0 == dc_apeerstate_set_verified(peerstate, 1i32, fingerprint, 2i32)) { (*peerstate).prefer_encrypt = 1i32; (*peerstate).to_save |= 0x2i32; - dc_apeerstate_save_to_db(peerstate, (*context).sql, 0i32); + dc_apeerstate_save_to_db(peerstate, &context.sql.clone().read().unwrap(), 0i32); success = 1i32 } } dc_apeerstate_unref(peerstate); - return success; + + success } + /* ****************************************************************************** * Tools: Misc. ******************************************************************************/ + +// TODO should return bool unsafe fn encrypted_and_signed( mut mimeparser: *mut dc_mimeparser_t, mut expected_fingerprint: *const libc::c_char, @@ -1034,16 +1057,18 @@ unsafe fn encrypted_and_signed( ); return 0i32; } - return 1i32; + + 1 } + pub unsafe fn dc_handle_degrade_event( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut peerstate: *mut dc_apeerstate_t, ) { - let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; - let mut contact_id: uint32_t = 0i32 as uint32_t; + let mut stmt; + let mut contact_id: uint32_t; let mut contact_chat_id: uint32_t = 0i32 as uint32_t; - if !(context.is_null() || peerstate.is_null()) { + if !peerstate.is_null() { // - we do not issue an warning for DC_DE_ENCRYPTION_PAUSED as this is quite normal // - currently, we do not issue an extra warning for DC_DE_VERIFICATION_LOST - this always comes // together with DC_DE_FINGERPRINT_CHANGED which is logged, the idea is not to bother @@ -1051,7 +1076,8 @@ pub unsafe fn dc_handle_degrade_event( // (and he will know this and can fix this) if 0 != (*peerstate).degrade_event & 0x2i32 { stmt = dc_sqlite3_prepare( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"SELECT id FROM contacts WHERE addr=?;\x00" as *const u8 as *const libc::c_char, ); sqlite3_bind_text(stmt, 1i32, (*peerstate).addr, -1i32, None); @@ -1070,7 +1096,7 @@ pub unsafe fn dc_handle_degrade_event( dc_stock_str_repl_string(context, 37i32, (*peerstate).addr); dc_add_device_msg(context, contact_chat_id, msg); free(msg as *mut libc::c_void); - ((*context).cb)( + (context.cb)( context, Event::CHAT_MODIFIED, contact_chat_id as uintptr_t, diff --git a/src/dc_simplify.rs b/src/dc_simplify.rs index 69bd03e75..340b9ccd1 100644 --- a/src/dc_simplify.rs +++ b/src/dc_simplify.rs @@ -1,5 +1,3 @@ -use libc; - use crate::dc_dehtml::*; use crate::dc_strbuilder::*; use crate::dc_tools::*; @@ -15,19 +13,22 @@ pub struct dc_simplify_t { } pub unsafe fn dc_simplify_new() -> *mut dc_simplify_t { - let mut simplify: *mut dc_simplify_t = 0 as *mut dc_simplify_t; + let mut simplify: *mut dc_simplify_t; simplify = calloc(1, ::std::mem::size_of::()) as *mut dc_simplify_t; if simplify.is_null() { exit(31i32); } - return simplify; + + simplify } + pub unsafe fn dc_simplify_unref(mut simplify: *mut dc_simplify_t) { if simplify.is_null() { return; } free(simplify as *mut libc::c_void); } + /* Simplify and normalise text: Remove quotes, signatures, unnecessary lineends etc. The data returned from Simplify() must be free()'d when no longer used, private */ @@ -39,8 +40,8 @@ pub unsafe fn dc_simplify_simplify( mut is_msgrmsg: libc::c_int, ) -> *mut libc::c_char { /* create a copy of the given buffer */ - let mut out: *mut libc::c_char = 0 as *mut libc::c_char; - let mut temp: *mut libc::c_char = 0 as *mut libc::c_char; + let mut out: *mut libc::c_char; + let mut temp: *mut libc::c_char; if simplify.is_null() || in_unterminated.is_null() || in_bytes <= 0i32 { return dc_strdup(b"\x00" as *const u8 as *const libc::c_char); } @@ -68,8 +69,10 @@ pub unsafe fn dc_simplify_simplify( out = temp } dc_remove_cr_chars(out); - return out; + + out } + /* ****************************************************************************** * Simplify Plain Text ******************************************************************************/ @@ -85,12 +88,12 @@ unsafe fn dc_simplify_simplify_plain_text( ... remove a non-empty line before the removed quote (contains sth. like "On 2.9.2016, Bjoern wrote:" in different formats and lanugages) */ /* split the given buffer into lines */ let mut lines: *mut carray = dc_split_into_lines(buf_terminated); - let mut l: libc::c_int = 0i32; + let mut l: libc::c_int; let mut l_first: libc::c_int = 0i32; /* if l_last is -1, there are no lines */ let mut l_last: libc::c_int = carray_count(lines).wrapping_sub(1i32 as libc::c_uint) as libc::c_int; - let mut line: *mut libc::c_char = 0 as *mut libc::c_char; + let mut line: *mut libc::c_char; let mut footer_mark: libc::c_int = 0i32; l = l_first; while l <= l_last { @@ -246,11 +249,14 @@ unsafe fn dc_simplify_simplify_plain_text( dc_strbuilder_cat(&mut ret, b" [...]\x00" as *const u8 as *const libc::c_char); } dc_free_splitted_lines(lines); - return ret.buf; + + ret.buf } + /* ****************************************************************************** * Tools ******************************************************************************/ +// TODO should return bool /rtn unsafe fn is_empty_line(mut buf: *const libc::c_char) -> libc::c_int { /* force unsigned - otherwise the `> ' '` comparison will fail */ let mut p1: *const libc::c_uchar = buf as *const libc::c_uchar; @@ -260,8 +266,11 @@ unsafe fn is_empty_line(mut buf: *const libc::c_char) -> libc::c_int { } p1 = p1.offset(1isize) } - return 1i32; + + 1 } + +// TODO should return bool /rtn unsafe fn is_quoted_headline(mut buf: *const libc::c_char) -> libc::c_int { /* This function may be called for the line _directly_ before a quote. The function checks if the line contains sth. like "On 01.02.2016, xy@z wrote:" in various languages. @@ -274,11 +283,15 @@ unsafe fn is_quoted_headline(mut buf: *const libc::c_char) -> libc::c_int { if buf_len > 0i32 && *buf.offset((buf_len - 1i32) as isize) as libc::c_int == ':' as i32 { return 1i32; } - return 0i32; + + 0 } + +// TODO should return bool /rtn unsafe fn is_plain_quote(mut buf: *const libc::c_char) -> libc::c_int { if *buf.offset(0isize) as libc::c_int == '>' as i32 { return 1i32; } - return 0i32; + + 0 } diff --git a/src/dc_smtp.rs b/src/dc_smtp.rs index c91fdae76..06293b104 100644 --- a/src/dc_smtp.rs +++ b/src/dc_smtp.rs @@ -1,526 +1,188 @@ -use libc; +use std::ffi::{CStr, CString}; + +use lettre::smtp::client::net::*; +use lettre::*; +use native_tls::TlsConnector; 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_tools::*; -use crate::types::*; use crate::x::*; -#[derive(Copy, Clone)] -#[repr(C)] -pub struct dc_smtp_t { - pub etpan: *mut mailsmtp, - pub from: *mut libc::c_char, - pub esmtp: libc::c_int, - pub log_connect_errors: libc::c_int, - pub context: *mut dc_context_t, +pub struct Smtp { + transport: Option, + transport_connected: bool, + /// Email address we are sending from. + from: Option, pub error: *mut libc::c_char, - pub error_etpan: libc::c_int, } -pub unsafe fn dc_smtp_new(mut context: *mut dc_context_t) -> *mut dc_smtp_t { - let mut smtp: *mut dc_smtp_t = 0 as *mut dc_smtp_t; - smtp = calloc(1, ::std::mem::size_of::()) as *mut dc_smtp_t; - if smtp.is_null() { - exit(29i32); +impl Smtp { + /// Create a new Smtp instances. + pub fn new() -> Self { + Smtp { + transport: None, + transport_connected: false, + from: None, + error: std::ptr::null_mut(), + } } - (*smtp).log_connect_errors = 1i32; - (*smtp).context = context; - return smtp; -} -pub unsafe fn dc_smtp_unref(mut smtp: *mut dc_smtp_t) { - if smtp.is_null() { - return; + + /// Disconnect the SMTP transport and drop it entirely. + pub fn disconnect(&mut self) { + if self.transport.is_none() || !self.transport_connected { + return; + } + + let mut transport = self.transport.take().unwrap(); + transport.close(); + self.transport_connected = false; } - dc_smtp_disconnect(smtp); - free((*smtp).from as *mut libc::c_void); - free((*smtp).error as *mut libc::c_void); - free(smtp as *mut libc::c_void); -} -pub unsafe fn dc_smtp_disconnect(mut smtp: *mut dc_smtp_t) { - if smtp.is_null() { - return; + + /// Check if a connection already exists. + pub fn is_connected(&self) -> bool { + self.transport.is_some() } - if !(*smtp).etpan.is_null() { - mailsmtp_free((*smtp).etpan); - (*smtp).etpan = 0 as *mut mailsmtp - }; -} -pub unsafe fn dc_smtp_is_connected(mut smtp: *const dc_smtp_t) -> libc::c_int { - return if !smtp.is_null() && !(*smtp).etpan.is_null() { - 1i32 - } else { - 0i32 - }; -} -pub unsafe fn dc_smtp_connect( - mut smtp: *mut dc_smtp_t, - mut lp: *const dc_loginparam_t, -) -> libc::c_int { - let mut current_block: u64; - let mut success: libc::c_int = 0i32; - let mut r: libc::c_int = 0i32; - let mut try_esmtp: libc::c_int = 0i32; - if smtp.is_null() || lp.is_null() { - return 0i32; - } - if !(*smtp).etpan.is_null() { - dc_log_warning( - (*smtp).context, - 0i32, - b"SMTP already connected.\x00" as *const u8 as *const libc::c_char, - ); - success = 1i32 - } else if (*lp).addr.is_null() || (*lp).send_server.is_null() || (*lp).send_port == 0i32 { - dc_log_event_seq( - (*smtp).context, - Event::ERROR_NETWORK, - &mut (*smtp).log_connect_errors as *mut libc::c_int, - b"SMTP bad parameters.\x00" as *const u8 as *const libc::c_char, - ); - } else { - free((*smtp).from as *mut libc::c_void); - (*smtp).from = dc_strdup((*lp).addr); - (*smtp).etpan = mailsmtp_new(0i32 as size_t, None); - if (*smtp).etpan.is_null() { - dc_log_error( - (*smtp).context, - 0i32, - b"SMTP-object creation failed.\x00" as *const u8 as *const libc::c_char, - ); + + /// Connect using the provided login params + pub fn connect(&mut self, context: &dc_context_t, lp: *const dc_loginparam_t) -> usize { + if lp.is_null() { + return 0; + } + + if self.is_connected() { + warn!(context, 0, "SMTP already connected."); + return 1; + } + + // Safe because we checked for null pointer above. + let lp = unsafe { *lp }; + + if lp.addr.is_null() || lp.send_server.is_null() || lp.send_port == 0 { + unsafe { + dc_log_event( + context, + Event::ERROR_NETWORK, + 0, + b"SMTP bad parameters.\x00" as *const u8 as *const libc::c_char, + ); + } + } + + let raw_addr = unsafe { + CStr::from_ptr(lp.addr) + .to_str() + .expect("invalid from address") + .to_string() + }; + self.from = if let Ok(addr) = EmailAddress::new(raw_addr) { + Some(addr) } else { - mailsmtp_set_timeout((*smtp).etpan, 10i32 as time_t); - mailsmtp_set_progress_callback( - (*smtp).etpan, - Some(body_progress), - smtp as *mut libc::c_void, - ); - /* connect to SMTP server */ - if 0 != (*lp).server_flags & (0x10000i32 | 0x40000i32) { - r = mailsmtp_socket_connect( - (*smtp).etpan, - (*lp).send_server, - (*lp).send_port as uint16_t, - ); - if r != MAILSMTP_NO_ERROR as libc::c_int { - dc_log_event_seq( - (*smtp).context, - Event::ERROR_NETWORK, - &mut (*smtp).log_connect_errors as *mut libc::c_int, - b"SMTP-Socket connection to %s:%i failed (%s)\x00" as *const u8 - as *const libc::c_char, - (*lp).send_server, - (*lp).send_port as libc::c_int, - mailsmtp_strerror(r), - ); - current_block = 12512295087047028901; - } else { - current_block = 10043043949733653460; - } - } else { - r = mailsmtp_ssl_connect( - (*smtp).etpan, - (*lp).send_server, - (*lp).send_port as uint16_t, - ); - if r != MAILSMTP_NO_ERROR as libc::c_int { - dc_log_event_seq( - (*smtp).context, - Event::ERROR_NETWORK, - &mut (*smtp).log_connect_errors as *mut libc::c_int, - b"SMTP-SSL connection to %s:%i failed (%s)\x00" as *const u8 - as *const libc::c_char, - (*lp).send_server, - (*lp).send_port as libc::c_int, - mailsmtp_strerror(r), - ); - current_block = 12512295087047028901; - } else { - current_block = 10043043949733653460; - } - } - match current_block { - 12512295087047028901 => {} - _ => { - try_esmtp = 1i32; - (*smtp).esmtp = 0i32; - if 0 != try_esmtp && { - r = mailesmtp_ehlo((*smtp).etpan); - r == MAILSMTP_NO_ERROR as libc::c_int - } { - (*smtp).esmtp = 1i32 - } else if 0 == try_esmtp || r == MAILSMTP_ERROR_NOT_IMPLEMENTED as libc::c_int { - r = mailsmtp_helo((*smtp).etpan) - } - if r != MAILSMTP_NO_ERROR as libc::c_int { - dc_log_event_seq( - (*smtp).context, - Event::ERROR_NETWORK, - &mut (*smtp).log_connect_errors as *mut libc::c_int, - b"SMTP-helo failed (%s)\x00" as *const u8 as *const libc::c_char, - mailsmtp_strerror(r), - ); - } else { - if 0 != (*lp).server_flags & 0x10000i32 { - r = mailsmtp_socket_starttls((*smtp).etpan); - if r != MAILSMTP_NO_ERROR as libc::c_int { - dc_log_event_seq( - (*smtp).context, - Event::ERROR_NETWORK, - &mut (*smtp).log_connect_errors as *mut libc::c_int, - b"SMTP-STARTTLS failed (%s)\x00" as *const u8 - as *const libc::c_char, - mailsmtp_strerror(r), - ); - current_block = 12512295087047028901; - } else { - (*smtp).esmtp = 0i32; - if 0 != try_esmtp && { - r = mailesmtp_ehlo((*smtp).etpan); - r == MAILSMTP_NO_ERROR as libc::c_int - } { - (*smtp).esmtp = 1i32 - } else if 0 == try_esmtp - || r == MAILSMTP_ERROR_NOT_IMPLEMENTED as libc::c_int - { - r = mailsmtp_helo((*smtp).etpan) - } - if r != MAILSMTP_NO_ERROR as libc::c_int { - dc_log_event_seq( - (*smtp).context, - Event::ERROR_NETWORK, - &mut (*smtp).log_connect_errors as *mut libc::c_int, - b"SMTP-helo failed (%s)\x00" as *const u8 - as *const libc::c_char, - mailsmtp_strerror(r), - ); - current_block = 12512295087047028901; - } else { - dc_log_info( - (*smtp).context, - 0i32, - b"SMTP-server %s:%i STARTTLS-connected.\x00" as *const u8 - as *const libc::c_char, - (*lp).send_server, - (*lp).send_port as libc::c_int, - ); - current_block = 5892776923941496671; - } - } - } else { - if 0 != (*lp).server_flags & 0x40000i32 { - dc_log_info( - (*smtp).context, - 0i32, - b"SMTP-server %s:%i connected.\x00" as *const u8 - as *const libc::c_char, - (*lp).send_server, - (*lp).send_port as libc::c_int, - ); - } else { - dc_log_info( - (*smtp).context, - 0i32, - b"SMTP-server %s:%i SSL-connected.\x00" as *const u8 - as *const libc::c_char, - (*lp).send_server, - (*lp).send_port as libc::c_int, - ); - } - current_block = 5892776923941496671; - } - match current_block { - 12512295087047028901 => {} - _ => { - if !(*lp).send_user.is_null() { - if 0 != (*lp).server_flags & 0x2i32 { - dc_log_info( - (*smtp).context, - 0i32, - b"SMTP-OAuth2 connect...\x00" as *const u8 - as *const libc::c_char, - ); - let mut access_token: *mut libc::c_char = - dc_get_oauth2_access_token( - (*smtp).context, - (*lp).addr, - (*lp).send_pw, - 0i32, - ); - r = mailsmtp_oauth2_authenticate( - (*smtp).etpan, - (*lp).send_user, - access_token, - ); - if r != MAILSMTP_NO_ERROR as libc::c_int { - free(access_token as *mut libc::c_void); - access_token = dc_get_oauth2_access_token( - (*smtp).context, - (*lp).addr, - (*lp).send_pw, - 0x1i32, - ); - r = mailsmtp_oauth2_authenticate( - (*smtp).etpan, - (*lp).send_user, - access_token, - ) - } - free(access_token as *mut libc::c_void); - current_block = 15462640364611497761; - } else { - r = mailsmtp_auth( - (*smtp).etpan, - (*lp).send_user, - (*lp).send_pw, - ); - if r != MAILSMTP_NO_ERROR as libc::c_int { - /* - * There are some Mailservers which do not correclty implement PLAIN auth (hMail) - * So here we try a workaround. See https://github.com/deltachat/deltachat-android/issues/67 - */ - if 0 != (*(*smtp).etpan).auth - & MAILSMTP_AUTH_PLAIN as libc::c_int - { - dc_log_info( - (*smtp).context, - 0i32, - b"Trying SMTP-Login workaround \"%s\"...\x00" - as *const u8 - as *const libc::c_char, - (*lp).send_user, - ); - let mut err: libc::c_int = 0; - let mut hostname: [libc::c_char; 513] = [0; 513]; - err = gethostname( - hostname.as_mut_ptr(), - ::std::mem::size_of::<[libc::c_char; 513]>(), - ); - if err < 0i32 { - dc_log_error( - (*smtp).context, - 0i32, - b"SMTP-Login: Cannot get hostname.\x00" - as *const u8 - as *const libc::c_char, - ); - current_block = 12512295087047028901; - } else { - r = mailesmtp_auth_sasl( - (*smtp).etpan, - b"PLAIN\x00" as *const u8 - as *const libc::c_char, - hostname.as_mut_ptr(), - 0 as *const libc::c_char, - 0 as *const libc::c_char, - 0 as *const libc::c_char, - (*lp).send_user, - (*lp).send_pw, - 0 as *const libc::c_char, - ); - current_block = 15462640364611497761; - } - } else { - current_block = 15462640364611497761; - } - } else { - current_block = 15462640364611497761; - } - } - match current_block { - 12512295087047028901 => {} - _ => { - if r != MAILSMTP_NO_ERROR as libc::c_int { - dc_log_event_seq( - (*smtp).context, - Event::ERROR_NETWORK, - &mut (*smtp).log_connect_errors - as *mut libc::c_int, - b"SMTP-login failed for user %s (%s)\x00" - as *const u8 - as *const libc::c_char, - (*lp).send_user, - mailsmtp_strerror(r), - ); - current_block = 12512295087047028901; - } else { - dc_log_event( - (*smtp).context, - Event::SMTP_CONNECTED, - 0i32, - b"SMTP-login as %s ok.\x00" as *const u8 - as *const libc::c_char, - (*lp).send_user, - ); - current_block = 3736434875406665187; - } - } - } - } else { - current_block = 3736434875406665187; - } - match current_block { - 12512295087047028901 => {} - _ => success = 1i32, - } - } - } - } - } - } - } - } - if 0 == success { - if !(*smtp).etpan.is_null() { - mailsmtp_free((*smtp).etpan); - (*smtp).etpan = 0 as *mut mailsmtp - } - } - return success; -} -unsafe extern "C" fn body_progress( - _current: size_t, - _maximum: size_t, - _user_data: *mut libc::c_void, -) { -} + None + }; -pub unsafe fn dc_smtp_send_msg( - mut smtp: *mut dc_smtp_t, - mut recipients: *const clist, - mut data_not_terminated: *const libc::c_char, - mut data_bytes: size_t, -) -> libc::c_int { - let mut current_block: u64; - let mut success: libc::c_int = 0i32; - let mut r: libc::c_int = 0i32; - let mut iter: *mut clistiter = 0 as *mut clistiter; - if !smtp.is_null() { - if recipients.is_null() - || (*recipients).count == 0i32 - || data_not_terminated.is_null() - || data_bytes == 0 + if self.from.is_none() { + // TODO: print error + return 0; + } + + let domain = unsafe { + CStr::from_ptr(lp.send_server) + .to_str() + .expect("invalid send server") + }; + let port = lp.send_port as u16; + + let mut tls_builder = TlsConnector::builder(); + tls_builder.min_protocol_version(Some(DEFAULT_TLS_PROTOCOLS[0])); + + let tls_parameters = + ClientTlsParameters::new(domain.to_string(), tls_builder.build().unwrap()); + + let creds = if 0 != lp.server_flags & (DC_LP_AUTH_OAUTH2 as i32) { + // oauth2 + + let mut access_token = + unsafe { dc_get_oauth2_access_token(context, lp.addr, lp.send_pw, 0i32) }; + if access_token.is_null() { + return 0; + } + + let user = unsafe { CStr::from_ptr(lp.send_user).to_str().unwrap().to_string() }; + let token = unsafe { CStr::from_ptr(access_token).to_str().unwrap().to_string() }; + unsafe { free(access_token as *mut libc::c_void) }; + + lettre::smtp::authentication::Credentials::new(user, token) + } else { + // plain + let user = unsafe { CStr::from_ptr(lp.send_user).to_str().unwrap().to_string() }; + let pw = unsafe { CStr::from_ptr(lp.send_pw).to_str().unwrap().to_string() }; + lettre::smtp::authentication::Credentials::new(user, pw) + }; + + let security = if 0 + != lp.server_flags & (DC_LP_SMTP_SOCKET_STARTTLS | DC_LP_SMTP_SOCKET_PLAIN) as i32 { - success = 1i32 - } else if !(*smtp).etpan.is_null() { - // set source - // the `etPanSMTPTest` is the ENVID from RFC 3461 (SMTP DSNs), we should probably replace it by a random value - r = if 0 != (*smtp).esmtp { - mailesmtp_mail( - (*smtp).etpan, - (*smtp).from, - 1i32, - b"etPanSMTPTest\x00" as *const u8 as *const libc::c_char, - ) - } else { - mailsmtp_mail((*smtp).etpan, (*smtp).from) - }; - if r != MAILSMTP_NO_ERROR as libc::c_int { - log_error( - smtp, - b"SMTP failed to start message\x00" as *const u8 as *const libc::c_char, - r, - ); - } else { - // set recipients - // if the recipient is on the same server, this may fail at once. - // TODO: question is what to do if one recipient in a group fails - iter = (*recipients).first; - loop { - if iter.is_null() { - current_block = 12039483399334584727; - break; - } - let mut rcpt: *const libc::c_char = (if !iter.is_null() { - (*iter).data - } else { - 0 as *mut libc::c_void - }) - as *const libc::c_char; - r = if 0 != (*smtp).esmtp { - mailesmtp_rcpt((*smtp).etpan, rcpt, 2i32 | 4i32, 0 as *const libc::c_char) - } else { - mailsmtp_rcpt((*smtp).etpan, rcpt) - }; - if r != MAILSMTP_NO_ERROR as libc::c_int { - log_error( - smtp, - b"SMTP failed to add recipient\x00" as *const u8 as *const libc::c_char, - r, + lettre::smtp::ClientSecurity::Opportunistic(tls_parameters) + } else { + lettre::smtp::ClientSecurity::Wrapper(tls_parameters) + }; + + let client = lettre::smtp::SmtpClient::new((domain, port), security) + .expect("failed to construct stmp client") + .smtp_utf8(true) + .credentials(creds) + .connection_reuse(lettre::smtp::ConnectionReuseParameters::ReuseUnlimited); + + self.transport = Some(client.transport()); + + 1 + } + + pub fn send<'a>( + &mut self, + context: &dc_context_t, + recipients: Vec, + body: Vec, + ) -> usize { + if let Some(ref mut transport) = self.transport { + let envelope = Envelope::new(self.from.clone(), recipients).expect("invalid envelope"); + let mail = SendableEmail::new( + envelope, + "mail-id".into(), // TODO: random id + body, + ); + + match transport.send(mail) { + Ok(_) => { + unsafe { + dc_log_event( + context, + Event::SMTP_MESSAGE_SENT, + 0, + b"Message was sent to SMTP server\x00" as *const u8 + as *const libc::c_char, ); - current_block = 5498835644851925448; - break; - } else { - iter = if !iter.is_null() { - (*iter).next - } else { - 0 as *mut clistcell_s - } } + self.transport_connected = true; + 1 } - match current_block { - 5498835644851925448 => {} - _ => { - // message - r = mailsmtp_data((*smtp).etpan); - if r != MAILSMTP_NO_ERROR as libc::c_int { - log_error( - smtp, - b"SMTP failed to set data\x00" as *const u8 as *const libc::c_char, - r, - ); - } else { - r = mailsmtp_data_message( - (*smtp).etpan, - data_not_terminated, - data_bytes, - ); - if r != MAILSMTP_NO_ERROR as libc::c_int { - log_error( - smtp, - b"SMTP failed to send message\x00" as *const u8 - as *const libc::c_char, - r, - ); - } else { - dc_log_event( - (*smtp).context, - Event::SMTP_MESSAGE_SENT, - 0i32, - b"Message was sent to SMTP server\x00" as *const u8 - as *const libc::c_char, - ); - success = 1i32 - } - } - } + Err(err) => { + let error_msg = format!("SMTP failed to send message: {:?}", err); + let msg = CString::new(error_msg).unwrap(); + self.error = unsafe { libc::strdup(msg.as_ptr()) }; + + warn!(context, 0, "%s", msg,); + + 0 } } + } else { + // TODO: log error + 0 } } - return success; -} -unsafe fn log_error( - mut smtp: *mut dc_smtp_t, - mut what_failed: *const libc::c_char, - mut r: libc::c_int, -) { - let mut error_msg: *mut libc::c_char = dc_mprintf( - b"%s: %s: %s\x00" as *const u8 as *const libc::c_char, - what_failed, - mailsmtp_strerror(r), - (*(*smtp).etpan).response, - ); - dc_log_warning( - (*smtp).context, - 0i32, - b"%s\x00" as *const u8 as *const libc::c_char, - error_msg, - ); - free((*smtp).error as *mut libc::c_void); - (*smtp).error = error_msg; - (*smtp).error_etpan = r; } diff --git a/src/dc_sqlite3.rs b/src/dc_sqlite3.rs index 0c53c1d01..c13ba0a97 100644 --- a/src/dc_sqlite3.rs +++ b/src/dc_sqlite3.rs @@ -1,5 +1,4 @@ -use libc; - +use crate::constants::*; use crate::dc_apeerstate::*; use crate::dc_context::dc_context_t; use crate::dc_hash::*; @@ -9,245 +8,322 @@ use crate::dc_tools::*; use crate::types::*; use crate::x::*; -/* * - * Library-internal. - */ -#[derive(Copy, Clone)] +const DC_OPEN_READONLY: usize = 0x01; + +/// A simple wrapper around the underlying Sqlite3 object. #[repr(C)] pub struct dc_sqlite3_t { pub cobj: *mut sqlite3, - pub context: *mut dc_context_t, } -pub unsafe fn dc_sqlite3_new(mut context: *mut dc_context_t) -> *mut dc_sqlite3_t { - let mut sql: *mut dc_sqlite3_t = 0 as *mut dc_sqlite3_t; - sql = calloc(1, ::std::mem::size_of::()) as *mut dc_sqlite3_t; - if sql.is_null() { - exit(24i32); +pub fn dc_sqlite3_new() -> dc_sqlite3_t { + dc_sqlite3_t { + cobj: std::ptr::null_mut(), } - (*sql).context = context; - return sql; } -pub unsafe fn dc_sqlite3_unref(mut sql: *mut dc_sqlite3_t) { - if sql.is_null() { - return; + +pub unsafe fn dc_sqlite3_unref(context: &dc_context_t, sql: &mut dc_sqlite3_t) { + if !sql.cobj.is_null() { + dc_sqlite3_close(context, sql); } - if !(*sql).cobj.is_null() { - dc_sqlite3_close(sql); - } - free(sql as *mut libc::c_void); } -pub unsafe fn dc_sqlite3_close(mut sql: *mut dc_sqlite3_t) { - if sql.is_null() { - return; - } - if !(*sql).cobj.is_null() { - sqlite3_close((*sql).cobj); - (*sql).cobj = 0 as *mut sqlite3 + +pub unsafe fn dc_sqlite3_close(context: &dc_context_t, sql: &mut dc_sqlite3_t) { + if !sql.cobj.is_null() { + sqlite3_close(sql.cobj); + sql.cobj = 0 as *mut sqlite3 } + dc_log_info( - (*sql).context, - 0i32, + context, + 0, b"Database closed.\x00" as *const u8 as *const libc::c_char, ); } + pub unsafe fn dc_sqlite3_open( - mut sql: *mut dc_sqlite3_t, - mut dbfile: *const libc::c_char, - mut flags: libc::c_int, + context: &dc_context_t, + sql: &mut dc_sqlite3_t, + dbfile: *const libc::c_char, + flags: libc::c_int, ) -> libc::c_int { let mut current_block: u64; if 0 != dc_sqlite3_is_open(sql) { - return 0i32; + return 0; } - if !(sql.is_null() || dbfile.is_null()) { - if sqlite3_threadsafe() == 0i32 { + if !dbfile.is_null() { + if sqlite3_threadsafe() == 0 { dc_log_error( - (*sql).context, - 0i32, + context, + 0, b"Sqlite3 compiled thread-unsafe; this is not supported.\x00" as *const u8 as *const libc::c_char, ); - } else if !(*sql).cobj.is_null() { + } else if !sql.cobj.is_null() { dc_log_error( - (*sql).context, - 0i32, + context, + 0, b"Cannot open, database \"%s\" already opened.\x00" as *const u8 as *const libc::c_char, dbfile, ); } else if sqlite3_open_v2( dbfile, - &mut (*sql).cobj, - 0x10000i32 - | if 0 != flags & 0x1i32 { - 0x1i32 + &mut sql.cobj, + SQLITE_OPEN_FULLMUTEX + | (if 0 != (flags & DC_OPEN_READONLY as i32) { + SQLITE_OPEN_READONLY } else { - 0x2i32 | 0x4i32 - }, - 0 as *const libc::c_char, - ) != 0i32 + SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE + }), + std::ptr::null(), + ) != 0 { dc_sqlite3_log_error( + context, sql, b"Cannot open database \"%s\".\x00" as *const u8 as *const libc::c_char, dbfile, ); } else { dc_sqlite3_execute( + context, sql, b"PRAGMA secure_delete=on;\x00" as *const u8 as *const libc::c_char, ); - sqlite3_busy_timeout((*sql).cobj, 10i32 * 1000i32); - if 0 == flags & 0x1i32 { - let mut exists_before_update: libc::c_int = 0i32; - let mut dbversion_before_update: libc::c_int = 0i32; + sqlite3_busy_timeout(sql.cobj, 10 * 1000); + if 0 == flags & DC_OPEN_READONLY as i32 { + let mut exists_before_update = 0; + let mut dbversion_before_update = 0; /* Init tables to dbversion=0 */ if 0 == dc_sqlite3_table_exists( + context, sql, b"config\x00" as *const u8 as *const libc::c_char, ) { dc_log_info( - (*sql).context, - 0i32, + context, + 0, b"First time init: creating tables in \"%s\".\x00" as *const u8 as *const libc::c_char, dbfile, ); - dc_sqlite3_execute(sql, - b"CREATE TABLE config (id INTEGER PRIMARY KEY, keyname TEXT, value TEXT);\x00" - as *const u8 as - *const libc::c_char); dc_sqlite3_execute( + context, + sql, + b"CREATE TABLE config (id INTEGER PRIMARY KEY, keyname TEXT, value TEXT);\x00" + as *const u8 as + *const libc::c_char + ); + dc_sqlite3_execute( + context, sql, b"CREATE INDEX config_index1 ON config (keyname);\x00" as *const u8 as *const libc::c_char, ); - dc_sqlite3_execute(sql, - b"CREATE TABLE contacts (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT DEFAULT \'\', addr TEXT DEFAULT \'\' COLLATE NOCASE, origin INTEGER DEFAULT 0, blocked INTEGER DEFAULT 0, last_seen INTEGER DEFAULT 0, param TEXT DEFAULT \'\');\x00" - as *const u8 as - *const libc::c_char); dc_sqlite3_execute( + context, + sql, + b"CREATE TABLE contacts (\ + id INTEGER PRIMARY KEY AUTOINCREMENT, \ + name TEXT DEFAULT \'\', \ + addr TEXT DEFAULT \'\' COLLATE NOCASE, \ + origin INTEGER DEFAULT 0, \ + blocked INTEGER DEFAULT 0, \ + last_seen INTEGER DEFAULT 0, \ + param TEXT DEFAULT \'\');\x00" as *const u8 + as *const libc::c_char, + ); + dc_sqlite3_execute( + context, sql, b"CREATE INDEX contacts_index1 ON contacts (name COLLATE NOCASE);\x00" as *const u8 as *const libc::c_char, ); dc_sqlite3_execute( + context, sql, b"CREATE INDEX contacts_index2 ON contacts (addr COLLATE NOCASE);\x00" as *const u8 as *const libc::c_char, ); - dc_sqlite3_execute(sql, - b"INSERT INTO contacts (id,name,origin) VALUES (1,\'self\',262144), (2,\'device\',262144), (3,\'rsvd\',262144), (4,\'rsvd\',262144), (5,\'rsvd\',262144), (6,\'rsvd\',262144), (7,\'rsvd\',262144), (8,\'rsvd\',262144), (9,\'rsvd\',262144);\x00" - as *const u8 as - *const libc::c_char); - dc_sqlite3_execute(sql, - b"CREATE TABLE chats (id INTEGER PRIMARY KEY AUTOINCREMENT, type INTEGER DEFAULT 0, name TEXT DEFAULT \'\', draft_timestamp INTEGER DEFAULT 0, draft_txt TEXT DEFAULT \'\', blocked INTEGER DEFAULT 0, grpid TEXT DEFAULT \'\', param TEXT DEFAULT \'\');\x00" - as *const u8 as - *const libc::c_char); dc_sqlite3_execute( + context, + sql, + b"INSERT INTO contacts (id,name,origin) VALUES \ + (1,\'self\',262144), (2,\'device\',262144), (3,\'rsvd\',262144), \ + (4,\'rsvd\',262144), (5,\'rsvd\',262144), (6,\'rsvd\',262144), \ + (7,\'rsvd\',262144), (8,\'rsvd\',262144), (9,\'rsvd\',262144);\x00" + as *const u8 as *const libc::c_char, + ); + dc_sqlite3_execute( + context, + sql, + b"CREATE TABLE chats (\ + id INTEGER PRIMARY KEY AUTOINCREMENT, \ + type INTEGER DEFAULT 0, \ + name TEXT DEFAULT \'\', \ + draft_timestamp INTEGER DEFAULT 0, \ + draft_txt TEXT DEFAULT \'\', \ + blocked INTEGER DEFAULT 0, \ + grpid TEXT DEFAULT \'\', \ + param TEXT DEFAULT \'\');\x00" as *const u8 + as *const libc::c_char, + ); + dc_sqlite3_execute( + context, sql, b"CREATE INDEX chats_index1 ON chats (grpid);\x00" as *const u8 as *const libc::c_char, ); dc_sqlite3_execute( + context, sql, b"CREATE TABLE chats_contacts (chat_id INTEGER, contact_id INTEGER);\x00" as *const u8 as *const libc::c_char, ); dc_sqlite3_execute( + context, sql, b"CREATE INDEX chats_contacts_index1 ON chats_contacts (chat_id);\x00" as *const u8 as *const libc::c_char, ); - dc_sqlite3_execute(sql, - b"INSERT INTO chats (id,type,name) VALUES (1,120,\'deaddrop\'), (2,120,\'rsvd\'), (3,120,\'trash\'), (4,120,\'msgs_in_creation\'), (5,120,\'starred\'), (6,120,\'archivedlink\'), (7,100,\'rsvd\'), (8,100,\'rsvd\'), (9,100,\'rsvd\');\x00" - as *const u8 as - *const libc::c_char); - dc_sqlite3_execute(sql, - b"CREATE TABLE msgs (id INTEGER PRIMARY KEY AUTOINCREMENT, rfc724_mid TEXT DEFAULT \'\', server_folder TEXT DEFAULT \'\', server_uid INTEGER DEFAULT 0, chat_id INTEGER DEFAULT 0, from_id INTEGER DEFAULT 0, to_id INTEGER DEFAULT 0, timestamp INTEGER DEFAULT 0, type INTEGER DEFAULT 0, state INTEGER DEFAULT 0, msgrmsg INTEGER DEFAULT 1, bytes INTEGER DEFAULT 0, txt TEXT DEFAULT \'\', txt_raw TEXT DEFAULT \'\', param TEXT DEFAULT \'\');\x00" - as *const u8 as - *const libc::c_char); dc_sqlite3_execute( + context, + sql, + b"INSERT INTO chats (id,type,name) VALUES \ + (1,120,\'deaddrop\'), (2,120,\'rsvd\'), (3,120,\'trash\'), \ + (4,120,\'msgs_in_creation\'), (5,120,\'starred\'), (6,120,\'archivedlink\'), \ + (7,100,\'rsvd\'), (8,100,\'rsvd\'), (9,100,\'rsvd\');\x00" + as *const u8 as *const libc::c_char + ); + dc_sqlite3_execute( + context, + sql, + b"CREATE TABLE msgs (\ + id INTEGER PRIMARY KEY AUTOINCREMENT, \ + rfc724_mid TEXT DEFAULT \'\', \ + server_folder TEXT DEFAULT \'\', \ + server_uid INTEGER DEFAULT 0, \ + chat_id INTEGER DEFAULT 0, \ + from_id INTEGER DEFAULT 0, \ + to_id INTEGER DEFAULT 0, \ + timestamp INTEGER DEFAULT 0, \ + type INTEGER DEFAULT 0, \ + state INTEGER DEFAULT 0, \ + msgrmsg INTEGER DEFAULT 1, \ + bytes INTEGER DEFAULT 0, \ + txt TEXT DEFAULT \'\', \ + txt_raw TEXT DEFAULT \'\', \ + param TEXT DEFAULT \'\');\x00" as *const u8 + as *const libc::c_char, + ); + dc_sqlite3_execute( + context, sql, b"CREATE INDEX msgs_index1 ON msgs (rfc724_mid);\x00" as *const u8 as *const libc::c_char, ); dc_sqlite3_execute( + context, sql, b"CREATE INDEX msgs_index2 ON msgs (chat_id);\x00" as *const u8 as *const libc::c_char, ); dc_sqlite3_execute( + context, sql, b"CREATE INDEX msgs_index3 ON msgs (timestamp);\x00" as *const u8 as *const libc::c_char, ); dc_sqlite3_execute( + context, sql, b"CREATE INDEX msgs_index4 ON msgs (state);\x00" as *const u8 as *const libc::c_char, ); - dc_sqlite3_execute(sql, - b"INSERT INTO msgs (id,msgrmsg,txt) VALUES (1,0,\'marker1\'), (2,0,\'rsvd\'), (3,0,\'rsvd\'), (4,0,\'rsvd\'), (5,0,\'rsvd\'), (6,0,\'rsvd\'), (7,0,\'rsvd\'), (8,0,\'rsvd\'), (9,0,\'daymarker\');\x00" - as *const u8 as - *const libc::c_char); - dc_sqlite3_execute(sql, - b"CREATE TABLE jobs (id INTEGER PRIMARY KEY AUTOINCREMENT, added_timestamp INTEGER, desired_timestamp INTEGER DEFAULT 0, action INTEGER, foreign_id INTEGER, param TEXT DEFAULT \'\');\x00" - as *const u8 as - *const libc::c_char); dc_sqlite3_execute( + context, + sql, + b"INSERT INTO msgs (id,msgrmsg,txt) VALUES \ + (1,0,\'marker1\'), (2,0,\'rsvd\'), (3,0,\'rsvd\'), \ + (4,0,\'rsvd\'), (5,0,\'rsvd\'), (6,0,\'rsvd\'), (7,0,\'rsvd\'), \ + (8,0,\'rsvd\'), (9,0,\'daymarker\');\x00" + as *const u8 as *const libc::c_char, + ); + dc_sqlite3_execute( + context, + sql, + b"CREATE TABLE jobs (\ + id INTEGER PRIMARY KEY AUTOINCREMENT, \ + added_timestamp INTEGER, \ + desired_timestamp INTEGER DEFAULT 0, \ + action INTEGER, \ + foreign_id INTEGER, \ + param TEXT DEFAULT \'\');\x00" as *const u8 + as *const libc::c_char, + ); + dc_sqlite3_execute( + context, sql, b"CREATE INDEX jobs_index1 ON jobs (desired_timestamp);\x00" as *const u8 as *const libc::c_char, ); if 0 == dc_sqlite3_table_exists( + context, sql, b"config\x00" as *const u8 as *const libc::c_char, ) || 0 == dc_sqlite3_table_exists( + context, sql, b"contacts\x00" as *const u8 as *const libc::c_char, ) || 0 == dc_sqlite3_table_exists( + context, sql, b"chats\x00" as *const u8 as *const libc::c_char, ) || 0 == dc_sqlite3_table_exists( + context, sql, b"chats_contacts\x00" as *const u8 as *const libc::c_char, ) || 0 == dc_sqlite3_table_exists( + context, sql, b"msgs\x00" as *const u8 as *const libc::c_char, ) || 0 == dc_sqlite3_table_exists( + context, sql, b"jobs\x00" as *const u8 as *const libc::c_char, ) { dc_sqlite3_log_error( + context, sql, b"Cannot create tables in new database \"%s\".\x00" as *const u8 as *const libc::c_char, dbfile, ); - /* cannot create the tables - maybe we cannot write? */ + // cannot create the tables - maybe we cannot write? current_block = 13628706266672894061; } else { dc_sqlite3_set_config_int( + context, sql, b"dbversion\x00" as *const u8 as *const libc::c_char, - 0i32, + 0, ); current_block = 14072441030219150333; } } else { - exists_before_update = 1i32; + exists_before_update = 1; dbversion_before_update = dc_sqlite3_get_config_int( + context, sql, b"dbversion\x00" as *const u8 as *const libc::c_char, - 0i32, + 0, ); current_block = 14072441030219150333; } @@ -259,326 +335,397 @@ pub unsafe fn dc_sqlite3_open( // rely themselves on the low-level structure. // -------------------------------------------------------------------- let mut dbversion: libc::c_int = dbversion_before_update; - let mut recalc_fingerprints: libc::c_int = 0i32; - let mut update_file_paths: libc::c_int = 0i32; - if dbversion < 1i32 { - dc_sqlite3_execute(sql, - b"CREATE TABLE leftgrps ( id INTEGER PRIMARY KEY, grpid TEXT DEFAULT \'\');\x00" - as *const u8 as - *const libc::c_char); + let mut recalc_fingerprints: libc::c_int = 0; + let mut update_file_paths: libc::c_int = 0; + if dbversion < 1 { dc_sqlite3_execute( + context, sql, + b"CREATE TABLE leftgrps ( id INTEGER PRIMARY KEY, grpid TEXT DEFAULT \'\');\x00" + as *const u8 as *const libc::c_char + ); + dc_sqlite3_execute( + context, sql, b"CREATE INDEX leftgrps_index1 ON leftgrps (grpid);\x00" as *const u8 as *const libc::c_char, ); - dbversion = 1i32; + dbversion = 1; dc_sqlite3_set_config_int( + context, sql, b"dbversion\x00" as *const u8 as *const libc::c_char, - 1i32, + 1, ); } - if dbversion < 2i32 { + if dbversion < 2 { dc_sqlite3_execute( + context, sql, b"ALTER TABLE contacts ADD COLUMN authname TEXT DEFAULT \'\';\x00" as *const u8 as *const libc::c_char, ); - dbversion = 2i32; + dbversion = 2; dc_sqlite3_set_config_int( + context, sql, b"dbversion\x00" as *const u8 as *const libc::c_char, - 2i32, + 2, ); } - if dbversion < 7i32 { - dc_sqlite3_execute(sql, - b"CREATE TABLE keypairs ( id INTEGER PRIMARY KEY, addr TEXT DEFAULT \'\' COLLATE NOCASE, is_default INTEGER DEFAULT 0, private_key, public_key, created INTEGER DEFAULT 0);\x00" - as *const u8 as - *const libc::c_char); - dbversion = 7i32; - dc_sqlite3_set_config_int( - sql, - b"dbversion\x00" as *const u8 as *const libc::c_char, - 7i32, - ); - } - if dbversion < 10i32 { - dc_sqlite3_execute(sql, - b"CREATE TABLE acpeerstates ( id INTEGER PRIMARY KEY, addr TEXT DEFAULT \'\' COLLATE NOCASE, last_seen INTEGER DEFAULT 0, last_seen_autocrypt INTEGER DEFAULT 0, public_key, prefer_encrypted INTEGER DEFAULT 0);\x00" - as *const u8 as - *const libc::c_char); + if dbversion < 7 { dc_sqlite3_execute( + context, + sql, + b"CREATE TABLE keypairs (\ + id INTEGER PRIMARY KEY, \ + addr TEXT DEFAULT \'\' COLLATE NOCASE, \ + is_default INTEGER DEFAULT 0, \ + private_key, \ + public_key, \ + created INTEGER DEFAULT 0);\x00" + as *const u8 + as *const libc::c_char, + ); + dbversion = 7; + dc_sqlite3_set_config_int( + context, + sql, + b"dbversion\x00" as *const u8 as *const libc::c_char, + 7, + ); + } + if dbversion < 10 { + dc_sqlite3_execute( + context, + sql, + b"CREATE TABLE acpeerstates (\ + id INTEGER PRIMARY KEY, \ + addr TEXT DEFAULT \'\' COLLATE NOCASE, \ + last_seen INTEGER DEFAULT 0, \ + last_seen_autocrypt INTEGER DEFAULT 0, \ + public_key, \ + prefer_encrypted INTEGER DEFAULT 0);\x00" + as *const u8 + as *const libc::c_char, + ); + dc_sqlite3_execute( + context, sql, b"CREATE INDEX acpeerstates_index1 ON acpeerstates (addr);\x00" as *const u8 as *const libc::c_char, ); - dbversion = 10i32; + dbversion = 10; dc_sqlite3_set_config_int( + context, sql, b"dbversion\x00" as *const u8 as *const libc::c_char, - 10i32, + 10, ); } - if dbversion < 12i32 { - dc_sqlite3_execute(sql, - b"CREATE TABLE msgs_mdns ( msg_id INTEGER, contact_id INTEGER);\x00" - as *const u8 as - *const libc::c_char); + if dbversion < 12 { dc_sqlite3_execute( + context, sql, + b"CREATE TABLE msgs_mdns ( msg_id INTEGER, contact_id INTEGER);\x00" + as *const u8 as + *const libc::c_char); + dc_sqlite3_execute( + context, sql, b"CREATE INDEX msgs_mdns_index1 ON msgs_mdns (msg_id);\x00" as *const u8 as *const libc::c_char, ); - dbversion = 12i32; + dbversion = 12; dc_sqlite3_set_config_int( + context, sql, b"dbversion\x00" as *const u8 as *const libc::c_char, - 12i32, + 12, ); } - if dbversion < 17i32 { + if dbversion < 17 { dc_sqlite3_execute( + context, sql, b"ALTER TABLE chats ADD COLUMN archived INTEGER DEFAULT 0;\x00" as *const u8 as *const libc::c_char, ); dc_sqlite3_execute( + context, sql, b"CREATE INDEX chats_index2 ON chats (archived);\x00" as *const u8 as *const libc::c_char, ); dc_sqlite3_execute( + context, sql, b"ALTER TABLE msgs ADD COLUMN starred INTEGER DEFAULT 0;\x00" as *const u8 as *const libc::c_char, ); dc_sqlite3_execute( + context, sql, b"CREATE INDEX msgs_index5 ON msgs (starred);\x00" as *const u8 as *const libc::c_char, ); - dbversion = 17i32; + dbversion = 17; dc_sqlite3_set_config_int( + context, sql, b"dbversion\x00" as *const u8 as *const libc::c_char, - 17i32, + 17, ); } - if dbversion < 18i32 { - dc_sqlite3_execute(sql, - b"ALTER TABLE acpeerstates ADD COLUMN gossip_timestamp INTEGER DEFAULT 0;\x00" - as *const u8 as - *const libc::c_char); + if dbversion < 18 { dc_sqlite3_execute( + context, sql, + b"ALTER TABLE acpeerstates ADD COLUMN gossip_timestamp INTEGER DEFAULT 0;\x00" + as *const u8 as + *const libc::c_char); + dc_sqlite3_execute( + context, sql, b"ALTER TABLE acpeerstates ADD COLUMN gossip_key;\x00" as *const u8 as *const libc::c_char, ); - dbversion = 18i32; + dbversion = 18; dc_sqlite3_set_config_int( + context, sql, b"dbversion\x00" as *const u8 as *const libc::c_char, - 18i32, + 18, ); } - if dbversion < 27i32 { + if dbversion < 27 { dc_sqlite3_execute( + context, sql, b"DELETE FROM msgs WHERE chat_id=1 OR chat_id=2;\x00" as *const u8 as *const libc::c_char, ); - dc_sqlite3_execute(sql, - b"CREATE INDEX chats_contacts_index2 ON chats_contacts (contact_id);\x00" - as *const u8 as - *const libc::c_char); dc_sqlite3_execute( + context, sql, + b"CREATE INDEX chats_contacts_index2 ON chats_contacts (contact_id);\x00" + as *const u8 as + *const libc::c_char + ); + dc_sqlite3_execute( + context, sql, b"ALTER TABLE msgs ADD COLUMN timestamp_sent INTEGER DEFAULT 0;\x00" as *const u8 as *const libc::c_char, ); dc_sqlite3_execute( + context, sql, b"ALTER TABLE msgs ADD COLUMN timestamp_rcvd INTEGER DEFAULT 0;\x00" as *const u8 as *const libc::c_char, ); - dbversion = 27i32; + dbversion = 27; dc_sqlite3_set_config_int( + context, sql, b"dbversion\x00" as *const u8 as *const libc::c_char, - 27i32, + 27, ); } - if dbversion < 34i32 { + if dbversion < 34 { dc_sqlite3_execute( + context, sql, b"ALTER TABLE msgs ADD COLUMN hidden INTEGER DEFAULT 0;\x00" as *const u8 as *const libc::c_char, ); - dc_sqlite3_execute(sql, - b"ALTER TABLE msgs_mdns ADD COLUMN timestamp_sent INTEGER DEFAULT 0;\x00" - as *const u8 as - *const libc::c_char); - dc_sqlite3_execute(sql, - b"ALTER TABLE acpeerstates ADD COLUMN public_key_fingerprint TEXT DEFAULT \'\';\x00" - as *const u8 as - *const libc::c_char); - dc_sqlite3_execute(sql, - b"ALTER TABLE acpeerstates ADD COLUMN gossip_key_fingerprint TEXT DEFAULT \'\';\x00" - as *const u8 as - *const libc::c_char); - dc_sqlite3_execute(sql, - b"CREATE INDEX acpeerstates_index3 ON acpeerstates (public_key_fingerprint);\x00" - as *const u8 as - *const libc::c_char); - dc_sqlite3_execute(sql, - b"CREATE INDEX acpeerstates_index4 ON acpeerstates (gossip_key_fingerprint);\x00" - as *const u8 as - *const libc::c_char); - recalc_fingerprints = 1i32; - dbversion = 34i32; + dc_sqlite3_execute( + context, sql, + b"ALTER TABLE msgs_mdns ADD COLUMN timestamp_sent INTEGER DEFAULT 0;\x00" + as *const u8 as + *const libc::c_char + ); + dc_sqlite3_execute( + context, sql, + b"ALTER TABLE acpeerstates ADD COLUMN public_key_fingerprint TEXT DEFAULT \'\';\x00" + as *const u8 as + *const libc::c_char); + dc_sqlite3_execute( + context, sql, + b"ALTER TABLE acpeerstates ADD COLUMN gossip_key_fingerprint TEXT DEFAULT \'\';\x00" + as *const u8 as + *const libc::c_char); + dc_sqlite3_execute( + context, sql, + b"CREATE INDEX acpeerstates_index3 ON acpeerstates (public_key_fingerprint);\x00" + as *const u8 as + *const libc::c_char); + dc_sqlite3_execute( + context, sql, + b"CREATE INDEX acpeerstates_index4 ON acpeerstates (gossip_key_fingerprint);\x00" + as *const u8 as + *const libc::c_char); + recalc_fingerprints = 1; + dbversion = 34; dc_sqlite3_set_config_int( + context, sql, b"dbversion\x00" as *const u8 as *const libc::c_char, - 34i32, + 34, ); } - if dbversion < 39i32 { - dc_sqlite3_execute(sql, - b"CREATE TABLE tokens ( id INTEGER PRIMARY KEY, namespc INTEGER DEFAULT 0, foreign_id INTEGER DEFAULT 0, token TEXT DEFAULT \'\', timestamp INTEGER DEFAULT 0);\x00" - as *const u8 as - *const libc::c_char); + if dbversion < 39 { dc_sqlite3_execute( + context, sql, + b"CREATE TABLE tokens ( id INTEGER PRIMARY KEY, namespc INTEGER DEFAULT 0, foreign_id INTEGER DEFAULT 0, token TEXT DEFAULT \'\', timestamp INTEGER DEFAULT 0);\x00" + as *const u8 as + *const libc::c_char); + dc_sqlite3_execute( + context, sql, b"ALTER TABLE acpeerstates ADD COLUMN verified_key;\x00" as *const u8 as *const libc::c_char, ); - dc_sqlite3_execute(sql, - b"ALTER TABLE acpeerstates ADD COLUMN verified_key_fingerprint TEXT DEFAULT \'\';\x00" - as *const u8 as - *const libc::c_char); - dc_sqlite3_execute(sql, - b"CREATE INDEX acpeerstates_index5 ON acpeerstates (verified_key_fingerprint);\x00" - as *const u8 as - *const libc::c_char); - if dbversion_before_update == 34i32 { - dc_sqlite3_execute(sql, - b"UPDATE acpeerstates SET verified_key=gossip_key, verified_key_fingerprint=gossip_key_fingerprint WHERE gossip_key_verified=2;\x00" - as *const u8 as - *const libc::c_char); - dc_sqlite3_execute(sql, - b"UPDATE acpeerstates SET verified_key=public_key, verified_key_fingerprint=public_key_fingerprint WHERE public_key_verified=2;\x00" - as *const u8 as - *const libc::c_char); + dc_sqlite3_execute( + context, sql, + b"ALTER TABLE acpeerstates ADD COLUMN verified_key_fingerprint TEXT DEFAULT \'\';\x00" + as *const u8 as + *const libc::c_char); + dc_sqlite3_execute( + context, sql, + b"CREATE INDEX acpeerstates_index5 ON acpeerstates (verified_key_fingerprint);\x00" + as *const u8 as + *const libc::c_char); + if dbversion_before_update == 34 { + dc_sqlite3_execute( + context, sql, + b"UPDATE acpeerstates SET verified_key=gossip_key, verified_key_fingerprint=gossip_key_fingerprint WHERE gossip_key_verified=2;\x00" + as *const u8 as + *const libc::c_char); + dc_sqlite3_execute( + context, sql, + b"UPDATE acpeerstates SET verified_key=public_key, verified_key_fingerprint=public_key_fingerprint WHERE public_key_verified=2;\x00" + as *const u8 as + *const libc::c_char); } - dbversion = 39i32; + dbversion = 39; dc_sqlite3_set_config_int( + context, sql, b"dbversion\x00" as *const u8 as *const libc::c_char, - 39i32, + 39, ); } - if dbversion < 40i32 { + if dbversion < 40 { dc_sqlite3_execute( + context, sql, b"ALTER TABLE jobs ADD COLUMN thread INTEGER DEFAULT 0;\x00" as *const u8 as *const libc::c_char, ); - dbversion = 40i32; + dbversion = 40; dc_sqlite3_set_config_int( + context, sql, b"dbversion\x00" as *const u8 as *const libc::c_char, - 40i32, + 40, ); } - if dbversion < 41i32 { - update_file_paths = 1i32; - dbversion = 41i32; + if dbversion < 41 { + update_file_paths = 1; + dbversion = 41; dc_sqlite3_set_config_int( + context, sql, b"dbversion\x00" as *const u8 as *const libc::c_char, - 41i32, + 41, ); } - if dbversion < 42i32 { + if dbversion < 42 { dc_sqlite3_execute( + context, sql, b"UPDATE msgs SET txt=\'\' WHERE type!=10\x00" as *const u8 as *const libc::c_char, ); - dbversion = 42i32; + dbversion = 42; dc_sqlite3_set_config_int( + context, sql, b"dbversion\x00" as *const u8 as *const libc::c_char, - 42i32, + 42, ); } - if dbversion < 44i32 { + if dbversion < 44 { dc_sqlite3_execute( + context, sql, b"ALTER TABLE msgs ADD COLUMN mime_headers TEXT;\x00" as *const u8 as *const libc::c_char, ); - dbversion = 44i32; + dbversion = 44; dc_sqlite3_set_config_int( + context, sql, b"dbversion\x00" as *const u8 as *const libc::c_char, - 44i32, + 44, ); } - if dbversion < 46i32 { + if dbversion < 46 { dc_sqlite3_execute( + context, sql, b"ALTER TABLE msgs ADD COLUMN mime_in_reply_to TEXT;\x00" as *const u8 as *const libc::c_char, ); dc_sqlite3_execute( + context, sql, b"ALTER TABLE msgs ADD COLUMN mime_references TEXT;\x00" as *const u8 as *const libc::c_char, ); - dbversion = 46i32; + dbversion = 46; dc_sqlite3_set_config_int( + context, sql, b"dbversion\x00" as *const u8 as *const libc::c_char, - 46i32, + 46, ); } - if dbversion < 47i32 { + if dbversion < 47 { dc_sqlite3_execute( + context, sql, b"ALTER TABLE jobs ADD COLUMN tries INTEGER DEFAULT 0;\x00" as *const u8 as *const libc::c_char, ); - dbversion = 47i32; + dbversion = 47; dc_sqlite3_set_config_int( + context, sql, b"dbversion\x00" as *const u8 as *const libc::c_char, - 47i32, + 47, ); } - if dbversion < 48i32 { + if dbversion < 48 { dc_sqlite3_execute( + context, sql, b"ALTER TABLE msgs ADD COLUMN move_state INTEGER DEFAULT 1;\x00" as *const u8 as *const libc::c_char, ); - if 0 != !(DC_MOVE_STATE_UNDEFINED as libc::c_int == 0i32) as libc::c_int + if 0 != !(DC_MOVE_STATE_UNDEFINED as libc::c_int == 0) as libc::c_int as libc::c_long { __assert_rtn( @@ -587,13 +734,13 @@ pub unsafe fn dc_sqlite3_open( )) .as_ptr(), b"../src/dc_sqlite3.c\x00" as *const u8 as *const libc::c_char, - 559i32, + 559, b"DC_MOVE_STATE_UNDEFINED == 0\x00" as *const u8 as *const libc::c_char, ); } else { }; - if 0 != !(DC_MOVE_STATE_PENDING as libc::c_int == 1i32) as libc::c_int + if 0 != !(DC_MOVE_STATE_PENDING as libc::c_int == 1) as libc::c_int as libc::c_long { __assert_rtn( @@ -602,13 +749,13 @@ pub unsafe fn dc_sqlite3_open( )) .as_ptr(), b"../src/dc_sqlite3.c\x00" as *const u8 as *const libc::c_char, - 560i32, + 560, b"DC_MOVE_STATE_PENDING == 1\x00" as *const u8 as *const libc::c_char, ); } else { }; - if 0 != !(DC_MOVE_STATE_STAY as libc::c_int == 2i32) as libc::c_int + if 0 != !(DC_MOVE_STATE_STAY as libc::c_int == 2) as libc::c_int as libc::c_long { __assert_rtn( @@ -617,13 +764,13 @@ pub unsafe fn dc_sqlite3_open( )) .as_ptr(), b"../src/dc_sqlite3.c\x00" as *const u8 as *const libc::c_char, - 561i32, + 561, b"DC_MOVE_STATE_STAY == 2\x00" as *const u8 as *const libc::c_char, ); } else { }; - if 0 != !(DC_MOVE_STATE_MOVING as libc::c_int == 3i32) as libc::c_int + if 0 != !(DC_MOVE_STATE_MOVING as libc::c_int == 3) as libc::c_int as libc::c_long { __assert_rtn( @@ -632,115 +779,127 @@ pub unsafe fn dc_sqlite3_open( )) .as_ptr(), b"../src/dc_sqlite3.c\x00" as *const u8 as *const libc::c_char, - 562i32, + 562, b"DC_MOVE_STATE_MOVING == 3\x00" as *const u8 as *const libc::c_char, ); } else { }; - dbversion = 48i32; + dbversion = 48; dc_sqlite3_set_config_int( + context, sql, b"dbversion\x00" as *const u8 as *const libc::c_char, - 48i32, + 48, ); } - if dbversion < 49i32 { - dc_sqlite3_execute(sql, - b"ALTER TABLE chats ADD COLUMN gossiped_timestamp INTEGER DEFAULT 0;\x00" - as *const u8 as - *const libc::c_char); - dbversion = 49i32; + if dbversion < 49 { + dc_sqlite3_execute( + context, sql, + b"ALTER TABLE chats ADD COLUMN gossiped_timestamp INTEGER DEFAULT 0;\x00" + as *const u8 as + *const libc::c_char); + dbversion = 49; dc_sqlite3_set_config_int( + context, sql, b"dbversion\x00" as *const u8 as *const libc::c_char, - 49i32, + 49, ); } - if dbversion < 50i32 { + if dbversion < 50 { if 0 != exists_before_update { dc_sqlite3_set_config_int( + context, sql, b"show_emails\x00" as *const u8 as *const libc::c_char, - 2i32, + 2, ); } - dbversion = 50i32; + dbversion = 50; dc_sqlite3_set_config_int( + context, sql, b"dbversion\x00" as *const u8 as *const libc::c_char, - 50i32, + 50, ); } - if dbversion < 53i32 { - dc_sqlite3_execute(sql, + if dbversion < 53 { + dc_sqlite3_execute(context, sql, b"CREATE TABLE locations ( id INTEGER PRIMARY KEY AUTOINCREMENT, latitude REAL DEFAULT 0.0, longitude REAL DEFAULT 0.0, accuracy REAL DEFAULT 0.0, timestamp INTEGER DEFAULT 0, chat_id INTEGER DEFAULT 0, from_id INTEGER DEFAULT 0);\x00" - as *const u8 as - *const libc::c_char); + as *const u8 as + *const libc::c_char); dc_sqlite3_execute( + context, sql, b"CREATE INDEX locations_index1 ON locations (from_id);\x00" as *const u8 as *const libc::c_char, ); dc_sqlite3_execute( + context, sql, b"CREATE INDEX locations_index2 ON locations (timestamp);\x00" as *const u8 as *const libc::c_char, ); - dc_sqlite3_execute(sql, + dc_sqlite3_execute(context, sql, b"ALTER TABLE chats ADD COLUMN locations_send_begin INTEGER DEFAULT 0;\x00" - as *const u8 as - *const libc::c_char); - dc_sqlite3_execute(sql, + as *const u8 as + *const libc::c_char); + dc_sqlite3_execute(context, sql, b"ALTER TABLE chats ADD COLUMN locations_send_until INTEGER DEFAULT 0;\x00" - as *const u8 as - *const libc::c_char); - dc_sqlite3_execute(sql, + as *const u8 as + *const libc::c_char); + dc_sqlite3_execute(context, sql, b"ALTER TABLE chats ADD COLUMN locations_last_sent INTEGER DEFAULT 0;\x00" - as *const u8 as - *const libc::c_char); + as *const u8 as + *const libc::c_char); dc_sqlite3_execute( + context, sql, b"CREATE INDEX chats_index3 ON chats (locations_send_until);\x00" as *const u8 as *const libc::c_char, ); - dbversion = 53i32; + dbversion = 53; dc_sqlite3_set_config_int( + context, sql, b"dbversion\x00" as *const u8 as *const libc::c_char, - 53i32, + 53, ); } - if dbversion < 54i32 { + if dbversion < 54 { dc_sqlite3_execute( + context, sql, b"ALTER TABLE msgs ADD COLUMN location_id INTEGER DEFAULT 0;\x00" as *const u8 as *const libc::c_char, ); dc_sqlite3_execute( + context, sql, b"CREATE INDEX msgs_index6 ON msgs (location_id);\x00" as *const u8 as *const libc::c_char, ); - dbversion = 54i32; + dbversion = 54; dc_sqlite3_set_config_int( + context, sql, b"dbversion\x00" as *const u8 as *const libc::c_char, - 54i32, + 54, ); } if dbversion < 55 { dc_sqlite3_execute( - sql, + context, sql, b"ALTER TABLE locations ADD COLUMN independent INTEGER DEFAULT 0;\x00" as *const u8 as *const libc::c_char ); - dbversion = 55; dc_sqlite3_set_config_int( + context, sql, b"dbversion\x00" as *const u8 as *const libc::c_char, 55, @@ -749,20 +908,21 @@ pub unsafe fn dc_sqlite3_open( if 0 != recalc_fingerprints { let mut stmt: *mut sqlite3_stmt = dc_sqlite3_prepare( + context, sql, b"SELECT addr FROM acpeerstates;\x00" as *const u8 as *const libc::c_char, ); - while sqlite3_step(stmt) == 100i32 { + while sqlite3_step(stmt) == 100 { let mut peerstate: *mut dc_apeerstate_t = - dc_apeerstate_new((*sql).context); + dc_apeerstate_new(context); if 0 != dc_apeerstate_load_by_addr( peerstate, sql, - sqlite3_column_text(stmt, 0i32) as *const libc::c_char, + sqlite3_column_text(stmt, 0) as *const libc::c_char, ) && 0 != dc_apeerstate_recalc_fingerprint(peerstate) { - dc_apeerstate_save_to_db(peerstate, sql, 0i32); + dc_apeerstate_save_to_db(peerstate, sql, 0); } dc_apeerstate_unref(peerstate); } @@ -770,9 +930,10 @@ pub unsafe fn dc_sqlite3_open( } if 0 != update_file_paths { let mut repl_from: *mut libc::c_char = dc_sqlite3_get_config( + context, sql, b"backup_for\x00" as *const u8 as *const libc::c_char, - (*(*sql).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 { @@ -782,17 +943,17 @@ pub unsafe fn dc_sqlite3_open( )) .as_ptr(), b"../src/dc_sqlite3.c\x00" as *const u8 as *const libc::c_char, - 656i32, + 656, b"\'f\'==DC_PARAM_FILE\x00" as *const u8 as *const libc::c_char, ); } else { }; let mut q3: *mut libc::c_char = sqlite3_mprintf(b"UPDATE msgs SET param=replace(param, \'f=%q/\', \'f=$BLOBDIR/\');\x00" - as *const u8 as - *const libc::c_char, + as *const u8 as + *const libc::c_char, repl_from); - dc_sqlite3_execute(sql, q3); + dc_sqlite3_execute(context, sql, q3); sqlite3_free(q3 as *mut libc::c_void); if 0 != !('i' as i32 == 'i' as i32) as libc::c_int as libc::c_long { __assert_rtn( @@ -801,7 +962,7 @@ pub unsafe fn dc_sqlite3_open( )) .as_ptr(), b"../src/dc_sqlite3.c\x00" as *const u8 as *const libc::c_char, - 661i32, + 661, b"\'i\'==DC_PARAM_PROFILE_IMAGE\x00" as *const u8 as *const libc::c_char, ); @@ -809,13 +970,14 @@ pub unsafe fn dc_sqlite3_open( }; q3 = sqlite3_mprintf(b"UPDATE chats SET param=replace(param, \'i=%q/\', \'i=$BLOBDIR/\');\x00" - as *const u8 as - *const libc::c_char, + as *const u8 as + *const libc::c_char, repl_from); - dc_sqlite3_execute(sql, q3); + dc_sqlite3_execute(context, sql, q3); sqlite3_free(q3 as *mut libc::c_void); free(repl_from as *mut libc::c_void); dc_sqlite3_set_config( + context, sql, b"backup_for\x00" as *const u8 as *const libc::c_char, 0 as *const libc::c_char, @@ -831,178 +993,196 @@ pub unsafe fn dc_sqlite3_open( 13628706266672894061 => {} _ => { dc_log_info( - (*sql).context, - 0i32, + context, + 0, b"Opened \"%s\".\x00" as *const u8 as *const libc::c_char, dbfile, ); - return 1i32; + return 1; } } } } - dc_sqlite3_close(sql); - return 0i32; + + dc_sqlite3_close(context, sql); + 0 } -/* handle configurations, private */ + +// handle configurations, private pub unsafe fn dc_sqlite3_set_config( - mut sql: *mut dc_sqlite3_t, - mut key: *const libc::c_char, - mut value: *const libc::c_char, + context: &dc_context_t, + sql: &dc_sqlite3_t, + key: *const libc::c_char, + value: *const libc::c_char, ) -> libc::c_int { - let mut state: libc::c_int = 0i32; - let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; + let mut state; + let mut stmt; if key.is_null() { dc_log_error( - (*sql).context, - 0i32, + context, + 0, b"dc_sqlite3_set_config(): Bad parameter.\x00" as *const u8 as *const libc::c_char, ); - return 0i32; + return 0; } if 0 == dc_sqlite3_is_open(sql) { dc_log_error( - (*sql).context, - 0i32, + context, + 0, b"dc_sqlite3_set_config(): Database not ready.\x00" as *const u8 as *const libc::c_char, ); - return 0i32; + return 0; } if !value.is_null() { stmt = dc_sqlite3_prepare( + context, sql, b"SELECT value FROM config WHERE keyname=?;\x00" as *const u8 as *const libc::c_char, ); - sqlite3_bind_text(stmt, 1i32, key, -1i32, None); + sqlite3_bind_text(stmt, 1, key, -1, None); state = sqlite3_step(stmt); sqlite3_finalize(stmt); - if state == 101i32 { + if state == 101 { stmt = dc_sqlite3_prepare( + context, sql, b"INSERT INTO config (keyname, value) VALUES (?, ?);\x00" as *const u8 as *const libc::c_char, ); - sqlite3_bind_text(stmt, 1i32, key, -1i32, None); - sqlite3_bind_text(stmt, 2i32, value, -1i32, None); + sqlite3_bind_text(stmt, 1, key, -1, None); + sqlite3_bind_text(stmt, 2, value, -1, None); state = sqlite3_step(stmt); sqlite3_finalize(stmt); - } else if state == 100i32 { + } else if state == 100 { stmt = dc_sqlite3_prepare( + context, sql, b"UPDATE config SET value=? WHERE keyname=?;\x00" as *const u8 as *const libc::c_char, ); - sqlite3_bind_text(stmt, 1i32, value, -1i32, None); - sqlite3_bind_text(stmt, 2i32, key, -1i32, None); + sqlite3_bind_text(stmt, 1, value, -1, None); + sqlite3_bind_text(stmt, 2, key, -1, None); state = sqlite3_step(stmt); sqlite3_finalize(stmt); } else { dc_log_error( - (*sql).context, - 0i32, + context, + 0, b"dc_sqlite3_set_config(): Cannot read value.\x00" as *const u8 as *const libc::c_char, ); - return 0i32; + return 0; } } else { stmt = dc_sqlite3_prepare( + context, sql, b"DELETE FROM config WHERE keyname=?;\x00" as *const u8 as *const libc::c_char, ); - sqlite3_bind_text(stmt, 1i32, key, -1i32, None); + sqlite3_bind_text(stmt, 1, key, -1, None); state = sqlite3_step(stmt); sqlite3_finalize(stmt); } - if state != 101i32 { + if state != 101 { dc_log_error( - (*sql).context, - 0i32, + context, + 0, b"dc_sqlite3_set_config(): Cannot change value.\x00" as *const u8 as *const libc::c_char, ); - return 0i32; + return 0; } - return 1i32; + + 1 } + /* tools, these functions are compatible to the corresponding sqlite3_* functions */ /* the result mus be freed using sqlite3_finalize() */ pub unsafe fn dc_sqlite3_prepare( - mut sql: *mut dc_sqlite3_t, - mut querystr: *const libc::c_char, + context: &dc_context_t, + sql: &dc_sqlite3_t, + querystr: *const libc::c_char, ) -> *mut sqlite3_stmt { - let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; - if sql.is_null() || querystr.is_null() || (*sql).cobj.is_null() { + let mut stmt = 0 as *mut sqlite3_stmt; + if querystr.is_null() || sql.cobj.is_null() { return 0 as *mut sqlite3_stmt; } if sqlite3_prepare_v2( - (*sql).cobj, + sql.cobj, querystr, - -1i32, + -1, &mut stmt, 0 as *mut *const libc::c_char, - ) != 0i32 + ) != 0 { dc_sqlite3_log_error( + context, sql, b"Query failed: %s\x00" as *const u8 as *const libc::c_char, querystr, ); return 0 as *mut sqlite3_stmt; } - return stmt; + stmt } + pub unsafe extern "C" fn dc_sqlite3_log_error( - mut sql: *mut dc_sqlite3_t, - mut msg_format: *const libc::c_char, - mut va: ... + context: &dc_context_t, + sql: &dc_sqlite3_t, + msg_format: *const libc::c_char, + va: ... ) { - let mut msg: *mut libc::c_char = 0 as *mut libc::c_char; - if sql.is_null() || msg_format.is_null() { + let mut msg; + if msg_format.is_null() { return; } // FIXME: evil transmute msg = sqlite3_vmprintf(msg_format, std::mem::transmute(va)); dc_log_error( - (*sql).context, - 0i32, + context, + 0, b"%s SQLite says: %s\x00" as *const u8 as *const libc::c_char, if !msg.is_null() { msg } else { b"\x00" as *const u8 as *const libc::c_char }, - if !(*sql).cobj.is_null() { - sqlite3_errmsg((*sql).cobj) + if !sql.cobj.is_null() { + sqlite3_errmsg(sql.cobj) } else { b"SQLite object not set up.\x00" as *const u8 as *const libc::c_char }, ); sqlite3_free(msg as *mut libc::c_void); } -pub unsafe fn dc_sqlite3_is_open(mut sql: *const dc_sqlite3_t) -> libc::c_int { - if sql.is_null() || (*sql).cobj.is_null() { - return 0i32; + +pub unsafe fn dc_sqlite3_is_open(sql: &dc_sqlite3_t) -> libc::c_int { + if sql.cobj.is_null() { + 0 + } else { + 1 } - return 1i32; } + /* the returned string must be free()'d, returns NULL on errors */ pub unsafe fn dc_sqlite3_get_config( - mut sql: *mut dc_sqlite3_t, - mut key: *const libc::c_char, - mut def: *const libc::c_char, + context: &dc_context_t, + sql: &dc_sqlite3_t, + key: *const libc::c_char, + def: *const libc::c_char, ) -> *mut libc::c_char { - let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; + let mut stmt; if 0 == dc_sqlite3_is_open(sql) || key.is_null() { return dc_strdup_keep_null(def); } stmt = dc_sqlite3_prepare( + context, sql, b"SELECT value FROM config WHERE keyname=?;\x00" as *const u8 as *const libc::c_char, ); - sqlite3_bind_text(stmt, 1i32, key, -1i32, None); - if sqlite3_step(stmt) == 100i32 { - let mut ptr: *const libc::c_uchar = sqlite3_column_text(stmt, 0i32); + sqlite3_bind_text(stmt, 1, key, -1, None); + if sqlite3_step(stmt) == 100 { + let mut ptr: *const libc::c_uchar = sqlite3_column_text(stmt, 0); if !ptr.is_null() { let mut ret: *mut libc::c_char = dc_strdup(ptr as *const libc::c_char); sqlite3_finalize(stmt); @@ -1010,85 +1190,94 @@ pub unsafe fn dc_sqlite3_get_config( } } sqlite3_finalize(stmt); - return dc_strdup_keep_null(def); + dc_strdup_keep_null(def) } + pub unsafe fn dc_sqlite3_execute( - mut sql: *mut dc_sqlite3_t, - mut querystr: *const libc::c_char, + context: &dc_context_t, + sql: &dc_sqlite3_t, + querystr: *const libc::c_char, ) -> libc::c_int { - let mut success: libc::c_int = 0i32; - let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; - let mut sqlState: libc::c_int = 0i32; - stmt = dc_sqlite3_prepare(sql, querystr); + let mut success = 0; + let mut sqlState; + let stmt = dc_sqlite3_prepare(context, sql, querystr); if !stmt.is_null() { sqlState = sqlite3_step(stmt); - if sqlState != 101i32 && sqlState != 100i32 { + if sqlState != 101 && sqlState != 100 { dc_sqlite3_log_error( + context, sql, b"Cannot execute \"%s\".\x00" as *const u8 as *const libc::c_char, querystr, ); } else { - success = 1i32 + success = 1 } } sqlite3_finalize(stmt); - return success; + success } + pub unsafe fn dc_sqlite3_set_config_int( - mut sql: *mut dc_sqlite3_t, - mut key: *const libc::c_char, - mut value: int32_t, + context: &dc_context_t, + sql: &dc_sqlite3_t, + key: *const libc::c_char, + value: int32_t, ) -> libc::c_int { - let mut value_str: *mut libc::c_char = dc_mprintf( + let mut value_str = dc_mprintf( b"%i\x00" as *const u8 as *const libc::c_char, value as libc::c_int, ); if value_str.is_null() { - return 0i32; + return 0; } - let mut ret: libc::c_int = dc_sqlite3_set_config(sql, key, value_str); + let ret = dc_sqlite3_set_config(context, sql, key, value_str); free(value_str as *mut libc::c_void); - return ret; + + ret } + pub unsafe fn dc_sqlite3_get_config_int( - mut sql: *mut dc_sqlite3_t, - mut key: *const libc::c_char, - mut def: int32_t, + context: &dc_context_t, + sql: &dc_sqlite3_t, + key: *const libc::c_char, + def: int32_t, ) -> int32_t { - let mut str: *mut libc::c_char = dc_sqlite3_get_config(sql, key, 0 as *const libc::c_char); + let mut str = dc_sqlite3_get_config(context, sql, key, 0 as *const libc::c_char); if str.is_null() { return def; } - let mut ret: int32_t = atoi(str) as int32_t; + let mut ret = atoi(str) as int32_t; free(str as *mut libc::c_void); - return ret; + ret } + pub unsafe fn dc_sqlite3_table_exists( - mut sql: *mut dc_sqlite3_t, - mut name: *const libc::c_char, + context: &dc_context_t, + sql: &dc_sqlite3_t, + name: *const libc::c_char, ) -> libc::c_int { - let mut ret: libc::c_int = 0i32; - let mut querystr: *mut libc::c_char = 0 as *mut libc::c_char; - let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; - let mut sqlState: libc::c_int = 0i32; - querystr = sqlite3_mprintf( + let mut ret = 0; + let mut stmt = 0 as *mut sqlite3_stmt; + let mut sqlState; + + let querystr = sqlite3_mprintf( b"PRAGMA table_info(%s)\x00" as *const u8 as *const libc::c_char, name, ); if querystr.is_null() { /* this statement cannot be used with binded variables */ dc_log_error( - (*sql).context, - 0i32, + context, + 0, b"dc_sqlite3_table_exists_(): Out of memory.\x00" as *const u8 as *const libc::c_char, ); } else { - stmt = dc_sqlite3_prepare(sql, querystr); + stmt = dc_sqlite3_prepare(context, sql, querystr); if !stmt.is_null() { sqlState = sqlite3_step(stmt); - if sqlState == 100i32 { - ret = 1i32 + if sqlState == 100 { + ret = 1 } } } @@ -1099,104 +1288,113 @@ pub unsafe fn dc_sqlite3_table_exists( if !querystr.is_null() { sqlite3_free(querystr as *mut libc::c_void); } - return ret; + ret } + pub unsafe fn dc_sqlite3_set_config_int64( - mut sql: *mut dc_sqlite3_t, - mut key: *const libc::c_char, - mut value: int64_t, + context: &dc_context_t, + sql: &dc_sqlite3_t, + key: *const libc::c_char, + value: int64_t, ) -> libc::c_int { - let mut value_str: *mut libc::c_char = dc_mprintf( + let mut value_str = dc_mprintf( b"%lld\x00" as *const u8 as *const libc::c_char, value as libc::c_long, ); if value_str.is_null() { - return 0i32; + return 0; } - let mut ret: libc::c_int = dc_sqlite3_set_config(sql, key, value_str); + let ret = dc_sqlite3_set_config(context, sql, key, value_str); free(value_str as *mut libc::c_void); - return ret; + ret } + pub unsafe fn dc_sqlite3_get_config_int64( - mut sql: *mut dc_sqlite3_t, - mut key: *const libc::c_char, - mut def: int64_t, + context: &dc_context_t, + sql: &dc_sqlite3_t, + key: *const libc::c_char, + def: int64_t, ) -> int64_t { - let mut str: *mut libc::c_char = dc_sqlite3_get_config(sql, key, 0 as *const libc::c_char); + let mut str = dc_sqlite3_get_config(context, sql, key, 0 as *const libc::c_char); if str.is_null() { return def; } - let mut ret: int64_t = 0i32 as int64_t; + let mut ret = 0 as int64_t; sscanf( str, b"%lld\x00" as *const u8 as *const libc::c_char, &mut ret as *mut int64_t, ); free(str as *mut libc::c_void); - return ret; + ret } + pub unsafe fn dc_sqlite3_try_execute( - mut sql: *mut dc_sqlite3_t, - mut querystr: *const libc::c_char, + context: &dc_context_t, + sql: &dc_sqlite3_t, + querystr: *const libc::c_char, ) -> libc::c_int { // same as dc_sqlite3_execute() but does not pass error to ui - let mut success: libc::c_int = 0i32; - let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; - let mut sql_state: libc::c_int = 0i32; - stmt = dc_sqlite3_prepare(sql, querystr); + let mut success = 0; + let mut sql_state; + let stmt = dc_sqlite3_prepare(context, sql, querystr); if !stmt.is_null() { sql_state = sqlite3_step(stmt); - if sql_state != 101i32 && sql_state != 100i32 { + if sql_state != 101 && sql_state != 100 { dc_log_warning( - (*sql).context, - 0i32, + context, + 0, b"Try-execute for \"%s\" failed: %s\x00" as *const u8 as *const libc::c_char, querystr, - sqlite3_errmsg((*sql).cobj), + sqlite3_errmsg(sql.cobj), ); } else { - success = 1i32 + success = 1 } } sqlite3_finalize(stmt); - return success; + success } + pub unsafe fn dc_sqlite3_get_rowid( - mut sql: *mut dc_sqlite3_t, - mut table: *const libc::c_char, - mut field: *const libc::c_char, - mut value: *const libc::c_char, + context: &dc_context_t, + sql: &dc_sqlite3_t, + table: *const libc::c_char, + field: *const libc::c_char, + value: *const libc::c_char, ) -> uint32_t { // alternative to sqlite3_last_insert_rowid() which MUST NOT be used due to race conditions, see comment above. // the ORDER BY ensures, this function always returns the most recent id, // eg. if a Message-ID is splitted into different messages. - let mut id: uint32_t = 0i32 as uint32_t; - let mut q3: *mut libc::c_char = sqlite3_mprintf( + let mut id = 0 as uint32_t; + let mut q3 = sqlite3_mprintf( b"SELECT id FROM %s WHERE %s=%Q ORDER BY id DESC;\x00" as *const u8 as *const libc::c_char, table, field, value, ); - let mut stmt: *mut sqlite3_stmt = dc_sqlite3_prepare(sql, q3); - if 100i32 == sqlite3_step(stmt) { - id = sqlite3_column_int(stmt, 0i32) as uint32_t + let mut stmt = dc_sqlite3_prepare(context, sql, q3); + if 100 == sqlite3_step(stmt) { + id = sqlite3_column_int(stmt, 0) as uint32_t } sqlite3_finalize(stmt); sqlite3_free(q3 as *mut libc::c_void); - return id; + id } + pub unsafe fn dc_sqlite3_get_rowid2( - mut sql: *mut dc_sqlite3_t, - mut table: *const libc::c_char, - mut field: *const libc::c_char, - mut value: uint64_t, - mut field2: *const libc::c_char, - mut value2: uint32_t, + context: &dc_context_t, + sql: &dc_sqlite3_t, + table: *const libc::c_char, + field: *const libc::c_char, + value: uint64_t, + field2: *const libc::c_char, + value2: uint32_t, ) -> uint32_t { // same as dc_sqlite3_get_rowid() with a key over two columns - let mut id: uint32_t = 0i32 as uint32_t; + let mut id = 0 as uint32_t; // see https://www.sqlite.org/printf.html for sqlite-printf modifiers - let mut q3: *mut libc::c_char = sqlite3_mprintf( + let mut q3 = sqlite3_mprintf( b"SELECT id FROM %s WHERE %s=%lli AND %s=%i ORDER BY id DESC;\x00" as *const u8 as *const libc::c_char, table, @@ -1205,27 +1403,20 @@ pub unsafe fn dc_sqlite3_get_rowid2( field2, value2, ); - let mut stmt: *mut sqlite3_stmt = dc_sqlite3_prepare(sql, q3); - if 100i32 == sqlite3_step(stmt) { - id = sqlite3_column_int(stmt, 0i32) as uint32_t + let mut stmt = dc_sqlite3_prepare(context, sql, q3); + if 100 == sqlite3_step(stmt) { + id = sqlite3_column_int(stmt, 0) as uint32_t } sqlite3_finalize(stmt); sqlite3_free(q3 as *mut libc::c_void); - return id; + id } -// NOTE: This assumes no transaction usage, port code if this is desired. - -pub unsafe fn dc_sqlite3_begin_transaction(_sql: *mut dc_sqlite3_t) {} -pub unsafe fn dc_sqlite3_commit(_sql: *mut dc_sqlite3_t) {} -pub unsafe fn dc_sqlite3_rollback(_sql: *mut dc_sqlite3_t) {} - -/* housekeeping */ -pub unsafe fn dc_housekeeping(mut context: *mut dc_context_t) { - let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; - let mut dir_handle: *mut DIR = 0 as *mut DIR; - let mut dir_entry: *mut dirent = 0 as *mut dirent; - let mut files_in_use: dc_hash_t = dc_hash_t { +pub unsafe fn dc_housekeeping(context: &dc_context_t) { + let mut stmt; + let mut dir_handle; + let mut dir_entry; + let mut files_in_use = dc_hash_t { keyClass: 0, copyKey: 0, count: 0, @@ -1233,12 +1424,12 @@ pub unsafe fn dc_housekeeping(mut context: *mut dc_context_t) { htsize: 0, ht: 0 as *mut _ht, }; - let mut path: *mut libc::c_char = 0 as *mut libc::c_char; - let mut unreferenced_count: libc::c_int = 0i32; - dc_hash_init(&mut files_in_use, 3i32, 1i32); + let mut path = 0 as *mut libc::c_char; + let mut unreferenced_count = 0; + dc_hash_init(&mut files_in_use, 3, 1); dc_log_info( context, - 0i32, + 0, b"Start housekeeping...\x00" as *const u8 as *const libc::c_char, ); maybe_add_from_param( @@ -1267,29 +1458,30 @@ pub unsafe fn dc_housekeeping(mut context: *mut dc_context_t) { 'i' as i32, ); stmt = dc_sqlite3_prepare( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"SELECT value FROM config;\x00" as *const u8 as *const libc::c_char, ); - while sqlite3_step(stmt) == 100i32 { + while sqlite3_step(stmt) == 100 { maybe_add_file( &mut files_in_use, - sqlite3_column_text(stmt, 0i32) as *const libc::c_char, + sqlite3_column_text(stmt, 0) as *const libc::c_char, ); } dc_log_info( context, - 0i32, + 0, b"%i files in use.\x00" as *const u8 as *const libc::c_char, 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, - 0i32, + 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 */ @@ -1304,8 +1496,8 @@ pub unsafe fn dc_housekeeping(mut context: *mut dc_context_t) { /* name without path or `.` or `..` */ let mut name: *const libc::c_char = (*dir_entry).d_name.as_mut_ptr(); let mut name_len: libc::c_int = strlen(name) as libc::c_int; - if name_len == 1i32 && *name.offset(0isize) as libc::c_int == '.' as i32 - || name_len == 2i32 + if name_len == 1 && *name.offset(0isize) as libc::c_int == '.' as i32 + || name_len == 2 && *name.offset(0isize) as libc::c_int == '.' as i32 && *name.offset(1isize) as libc::c_int == '.' as i32 { @@ -1334,7 +1526,7 @@ pub unsafe fn dc_housekeeping(mut context: *mut 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, ); @@ -1346,7 +1538,7 @@ pub unsafe fn dc_housekeeping(mut context: *mut dc_context_t) { { dc_log_info( context, - 0i32, + 0, b"Housekeeping: Keeping new unreferenced file #%i: %s\x00" as *const u8 as *const libc::c_char, unreferenced_count, @@ -1359,7 +1551,7 @@ pub unsafe fn dc_housekeeping(mut context: *mut dc_context_t) { } dc_log_info( context, - 0i32, + 0, b"Housekeeping: Deleting unreferenced file #%i: %s\x00" as *const u8 as *const libc::c_char, unreferenced_count, @@ -1376,25 +1568,26 @@ pub unsafe fn dc_housekeeping(mut context: *mut dc_context_t) { free(path as *mut libc::c_void); dc_log_info( context, - 0i32, + 0, b"Housekeeping done.\x00" as *const u8 as *const libc::c_char, ); } + unsafe fn is_file_in_use( - mut files_in_use: *mut dc_hash_t, - mut namespc: *const libc::c_char, - mut name: *const libc::c_char, + files_in_use: *mut dc_hash_t, + namespc: *const libc::c_char, + name: *const libc::c_char, ) -> libc::c_int { - let mut name_to_check: *mut libc::c_char = dc_strdup(name); + let mut name_to_check = dc_strdup(name); if !namespc.is_null() { let mut name_len: libc::c_int = strlen(name) as libc::c_int; let mut namespc_len: libc::c_int = strlen(namespc) as libc::c_int; if name_len <= namespc_len - || strcmp(&*name.offset((name_len - namespc_len) as isize), namespc) != 0i32 + || strcmp(&*name.offset((name_len - namespc_len) as isize), namespc) != 0 { - return 0i32; + return 0; } - *name_to_check.offset((name_len - namespc_len) as isize) = 0i32 as libc::c_char + *name_to_check.offset((name_len - namespc_len) as isize) = 0 as libc::c_char } let mut ret: libc::c_int = (dc_hash_find( files_in_use, @@ -1402,42 +1595,38 @@ unsafe fn is_file_in_use( strlen(name_to_check) as libc::c_int, ) != 0 as *mut libc::c_void) as libc::c_int; free(name_to_check as *mut libc::c_void); - return ret; + ret } -/* ****************************************************************************** - * Housekeeping - ******************************************************************************/ -unsafe fn maybe_add_file(mut files_in_use: *mut dc_hash_t, mut file: *const libc::c_char) { + +unsafe fn maybe_add_file(files_in_use: *mut dc_hash_t, file: *const libc::c_char) { if strncmp( file, b"$BLOBDIR/\x00" as *const u8 as *const libc::c_char, 9, - ) != 0i32 + ) != 0 { return; } - let mut raw_name: *const libc::c_char = &*file.offset(9isize) as *const libc::c_char; + let mut raw_name = &*file.offset(9isize) as *const libc::c_char; dc_hash_insert( files_in_use, raw_name as *const libc::c_void, strlen(raw_name) as libc::c_int, - 1i32 as *mut libc::c_void, + 1 as *mut libc::c_void, ); } + unsafe fn maybe_add_from_param( - mut context: *mut dc_context_t, - mut files_in_use: *mut dc_hash_t, - mut query: *const libc::c_char, - mut param_id: libc::c_int, + context: &dc_context_t, + files_in_use: *mut dc_hash_t, + query: *const libc::c_char, + param_id: libc::c_int, ) { - let mut param: *mut dc_param_t = dc_param_new(); - let mut stmt: *mut sqlite3_stmt = dc_sqlite3_prepare((*context).sql, query); - while sqlite3_step(stmt) == 100i32 { - dc_param_set_packed( - param, - sqlite3_column_text(stmt, 0i32) as *const libc::c_char, - ); - let mut file: *mut libc::c_char = dc_param_get(param, param_id, 0 as *const libc::c_char); + let mut param = dc_param_new(); + let mut stmt = dc_sqlite3_prepare(context, &context.sql.clone().read().unwrap(), query); + while sqlite3_step(stmt) == 100 { + dc_param_set_packed(param, sqlite3_column_text(stmt, 0) as *const libc::c_char); + let mut file = dc_param_get(param, param_id, 0 as *const libc::c_char); if !file.is_null() { maybe_add_file(files_in_use, file); free(file as *mut libc::c_void); diff --git a/src/dc_stock.rs b/src/dc_stock.rs index b93ce0e2a..195dced53 100644 --- a/src/dc_stock.rs +++ b/src/dc_stock.rs @@ -1,5 +1,3 @@ -use libc; - use crate::constants::Event; use crate::dc_contact::*; use crate::dc_context::dc_context_t; @@ -9,35 +7,36 @@ use crate::x::*; /* Return the string with the given ID by calling DC_EVENT_GET_STRING. The result must be free()'d! */ -pub unsafe fn dc_stock_str( - mut context: *mut dc_context_t, - mut id: libc::c_int, -) -> *mut libc::c_char { +pub unsafe fn dc_stock_str(mut context: &dc_context_t, mut id: libc::c_int) -> *mut libc::c_char { return get_string(context, id, 0i32); } + unsafe fn get_string( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut id: libc::c_int, mut qty: libc::c_int, ) -> *mut libc::c_char { - let mut ret: *mut libc::c_char = 0 as *mut libc::c_char; - if !context.is_null() { - ret = ((*context).cb)( - context, - Event::GET_STRING, - id as uintptr_t, - qty as uintptr_t, - ) as *mut libc::c_char; - } + let mut ret: *mut libc::c_char; + + ret = ((*context).cb)( + context, + Event::GET_STRING, + id as uintptr_t, + qty as uintptr_t, + ) as *mut libc::c_char; + if ret.is_null() { ret = default_string(id) } - return ret; + + ret } + /* Add translated strings that are used by the messager backend. As the logging functions may use these strings, do not log any errors from here. */ unsafe fn default_string(mut id: libc::c_int) -> *mut libc::c_char { + // TODO match on enum values /rtn match id { 1 => { return dc_strdup(b"No messages.\x00" as *const u8 as @@ -210,12 +209,14 @@ unsafe fn default_string(mut id: libc::c_int) -> *mut libc::c_char { } _ => { } } - return dc_strdup(b"ErrStr\x00" as *const u8 as *const libc::c_char); + + dc_strdup(b"ErrStr\x00" as *const u8 as *const libc::c_char) } + /* Replaces the first `%1$s` in the given String-ID by the given value. The result must be free()'d! */ pub unsafe fn dc_stock_str_repl_string( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut id: libc::c_int, mut to_insert: *const libc::c_char, ) -> *mut libc::c_char { @@ -230,10 +231,12 @@ pub unsafe fn dc_stock_str_repl_string( b"%1$d\x00" as *const u8 as *const libc::c_char, to_insert, ); - return ret; + + ret } + pub unsafe fn dc_stock_str_repl_int( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut id: libc::c_int, mut to_insert_int: libc::c_int, ) -> *mut libc::c_char { @@ -253,12 +256,14 @@ pub unsafe fn dc_stock_str_repl_int( to_insert_str, ); free(to_insert_str as *mut libc::c_void); - return ret; + + ret } + /* Replaces the first `%1$s` and `%2$s` in the given String-ID by the two given strings. The result must be free()'d! */ pub unsafe fn dc_stock_str_repl_string2( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut id: libc::c_int, mut to_insert: *const libc::c_char, mut to_insert2: *const libc::c_char, @@ -284,17 +289,19 @@ pub unsafe fn dc_stock_str_repl_string2( b"%2$d\x00" as *const u8 as *const libc::c_char, to_insert2, ); - return ret; + + ret } + /* Misc. */ pub unsafe fn dc_stock_system_msg( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut str_id: libc::c_int, mut param1: *const libc::c_char, mut param2: *const libc::c_char, mut from_id: uint32_t, ) -> *mut libc::c_char { - let mut ret: *mut libc::c_char = 0 as *mut libc::c_char; + let mut ret: *mut libc::c_char; let mut mod_contact: *mut dc_contact_t = 0 as *mut dc_contact_t; let mut mod_displayname: *mut libc::c_char = 0 as *mut libc::c_char; let mut from_contact: *mut dc_contact_t = 0 as *mut dc_contact_t; @@ -334,5 +341,6 @@ pub unsafe fn dc_stock_system_msg( free(mod_displayname as *mut libc::c_void); dc_contact_unref(from_contact); dc_contact_unref(mod_contact); - return ret; + + ret } diff --git a/src/dc_strbuilder.rs b/src/dc_strbuilder.rs index 2b729935f..5f6974a98 100644 --- a/src/dc_strbuilder.rs +++ b/src/dc_strbuilder.rs @@ -1,5 +1,3 @@ -use libc; - use crate::x::*; #[derive(Copy, Clone)] diff --git a/src/dc_strencode.rs b/src/dc_strencode.rs index 2bee4ebc8..18280e53e 100644 --- a/src/dc_strencode.rs +++ b/src/dc_strencode.rs @@ -1,17 +1,10 @@ -use libc; +use mmime::charconv::*; +use mmime::mailmime_decode::*; +use mmime::mmapstring::*; +use mmime::other::*; use crate::dc_tools::*; use crate::types::*; -use crate::x::*; - -#[inline] -unsafe fn __isctype(mut _c: __darwin_ct_rune_t, mut _f: libc::c_ulong) -> __darwin_ct_rune_t { - return if _c < 0i32 || _c >= 1i32 << 8i32 { - 0i32 - } else { - (0 != _DefaultRuneLocale.__runetype[_c as usize] as libc::c_ulong & _f) as libc::c_int - }; -} #[inline] pub fn isalnum(mut _c: libc::c_int) -> libc::c_int { @@ -22,14 +15,6 @@ pub fn isalnum(mut _c: libc::c_int) -> libc::c_int { } } -#[cfg(test)] -#[test] -fn test_isalnum() { - assert_eq!(isalnum(0), 0); - assert_eq!(isalnum('5' as libc::c_int), 1); - assert_eq!(isalnum('Q' as libc::c_int), 1); -} - #[inline] pub fn isdigit(mut _c: libc::c_int) -> libc::c_int { if _c < std::u8::MAX as libc::c_int { @@ -78,8 +63,10 @@ pub unsafe extern "C" fn dc_urlencode(mut to_encode: *const libc::c_char) -> *mu pstr = pstr.offset(1isize) } *pbuf = '\u{0}' as i32 as libc::c_char; - return buf; + + buf } + /* ****************************************************************************** * URL encoding and decoding, RFC 3986 ******************************************************************************/ @@ -87,8 +74,10 @@ unsafe fn int_2_uppercase_hex(mut code: libc::c_char) -> libc::c_char { static mut hex: [libc::c_char; 17] = [ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 0, ]; - return hex[(code as libc::c_int & 15i32) as usize]; + + hex[(code as libc::c_int & 15i32) as usize] } + pub unsafe fn dc_urldecode(mut to_decode: *const libc::c_char) -> *mut libc::c_char { let mut pstr: *const libc::c_char = to_decode; if to_decode.is_null() { @@ -122,15 +111,18 @@ pub unsafe fn dc_urldecode(mut to_decode: *const libc::c_char) -> *mut libc::c_c pstr = pstr.offset(1isize) } *pbuf = '\u{0}' as i32 as libc::c_char; - return buf; + + buf } + unsafe fn hex_2_int(mut ch: libc::c_char) -> libc::c_char { return (if 0 != isdigit(ch as libc::c_int) { ch as libc::c_int - '0' as i32 } else { - tolower(ch as libc::c_int) - 'a' as i32 + 10i32 + libc::tolower(ch as libc::c_int) - 'a' as i32 + 10i32 }) as libc::c_char; } + pub unsafe fn dc_encode_header_words(mut to_encode: *const libc::c_char) -> *mut libc::c_char { let mut current_block: u64; let mut ret_str: *mut libc::c_char = 0 as *mut libc::c_char; @@ -151,10 +143,10 @@ pub unsafe fn dc_encode_header_words(mut to_encode: *const libc::c_char) -> *mut } _ => { if *cur as libc::c_int != '\u{0}' as i32 { - let mut begin: *const libc::c_char = 0 as *const libc::c_char; - let mut end: *const libc::c_char = 0 as *const libc::c_char; - let mut do_quote: libc::c_int = 0; - let mut quote_words: libc::c_int = 0; + let mut begin: *const libc::c_char; + let mut end: *const libc::c_char; + let mut do_quote: libc::c_int; + let mut quote_words: libc::c_int; begin = cur; end = begin; quote_words = 0i32; @@ -226,15 +218,18 @@ pub unsafe fn dc_encode_header_words(mut to_encode: *const libc::c_char) -> *mut } } } - return ret_str; + + ret_str } + +// TODO return bool /rtn unsafe fn quote_word( mut display_charset: *const libc::c_char, mut mmapstr: *mut MMAPString, mut word: *const libc::c_char, mut size: size_t, ) -> libc::c_int { - let mut cur: *const libc::c_char = 0 as *const libc::c_char; + let mut cur: *const libc::c_char; let mut i: size_t = 0i32 as size_t; let mut hex: [libc::c_char; 4] = [0; 4]; // let mut col: libc::c_int = 0i32; @@ -249,10 +244,8 @@ unsafe fn quote_word( } // col = (*mmapstr).len as libc::c_int; cur = word; - i = 0i32 as size_t; while i < size { let mut do_quote_char: libc::c_int = 0; - do_quote_char = 0i32; match *cur as libc::c_int { 44 | 58 | 33 | 34 | 35 | 36 | 64 | 91 | 92 | 93 | 94 | 96 | 123 | 124 | 125 | 126 | 61 | 63 | 95 => do_quote_char = 1i32, @@ -289,12 +282,14 @@ unsafe fn quote_word( if mmap_string_append(mmapstr, b"?=\x00" as *const u8 as *const libc::c_char).is_null() { return 0i32; } - return 1i32; + + 1 } + unsafe fn get_word( mut begin: *const libc::c_char, mut pend: *mut *const libc::c_char, - mut pto_be_quoted: *mut libc::c_int, + mut pto_be_quoted: *mut libc::c_int, // TODO should be bool /rtn ) { let mut cur: *const libc::c_char = begin; while *cur as libc::c_int != ' ' as i32 @@ -309,14 +304,16 @@ unsafe fn get_word( ); *pend = cur; } + /* ****************************************************************************** * Encode/decode header words, RFC 2047 ******************************************************************************/ + /* see comment below */ +// TODO should be bool /rtn unsafe fn to_be_quoted(mut word: *const libc::c_char, mut size: size_t) -> libc::c_int { let mut cur: *const libc::c_char = word; let mut i: size_t = 0i32 as size_t; - i = 0i32 as size_t; while i < size { match *cur as libc::c_int { 44 | 58 | 33 | 34 | 35 | 36 | 64 | 91 | 92 | 93 | 94 | 96 | 123 | 124 | 125 | 126 @@ -330,8 +327,10 @@ unsafe fn to_be_quoted(mut word: *const libc::c_char, mut size: size_t) -> libc: cur = cur.offset(1isize); i = i.wrapping_add(1) } - return 0i32; + + 0 } + pub unsafe fn dc_decode_header_words(mut in_0: *const libc::c_char) -> *mut libc::c_char { if in_0.is_null() { return 0 as *mut libc::c_char; @@ -349,22 +348,24 @@ pub unsafe fn dc_decode_header_words(mut in_0: *const libc::c_char) -> *mut libc if r != MAILIMF_NO_ERROR as libc::c_int || out.is_null() { out = dc_strdup(in_0) } - return out; + + out } + pub unsafe fn dc_encode_modified_utf7( mut to_encode: *const libc::c_char, mut change_spaces: libc::c_int, ) -> *mut libc::c_char { - let mut utf8pos: libc::c_uint = 0i32 as libc::c_uint; - let mut utf8total: libc::c_uint = 0i32 as libc::c_uint; - let mut c: libc::c_uint = 0i32 as libc::c_uint; - let mut utf7mode: libc::c_uint = 0i32 as libc::c_uint; - let mut bitstogo: libc::c_uint = 0i32 as libc::c_uint; - let mut utf16flag: libc::c_uint = 0i32 as libc::c_uint; + let mut utf8pos: libc::c_uint; + let mut utf8total: libc::c_uint; + let mut c: libc::c_uint; + let mut utf7mode: libc::c_uint; + let mut bitstogo: libc::c_uint; + let mut utf16flag: libc::c_uint; let mut ucs4: libc::c_ulong = 0; let mut bitbuf: libc::c_ulong = 0; - let mut dst: *mut libc::c_char = 0 as *mut libc::c_char; - let mut res: *mut libc::c_char = 0 as *mut libc::c_char; + let mut dst: *mut libc::c_char; + let mut res: *mut libc::c_char; if to_encode.is_null() { return dc_strdup(b"\x00" as *const u8 as *const libc::c_char); } @@ -487,31 +488,35 @@ pub unsafe fn dc_encode_modified_utf7( *fresh16 = '-' as i32 as libc::c_char } *dst = '\u{0}' as i32 as libc::c_char; - return res; + + res } + /* ****************************************************************************** * Encode/decode modified UTF-7 as needed for IMAP, see RFC 2192 ******************************************************************************/ + // UTF7 modified base64 alphabet static mut base64chars: [libc::c_char; 65] = [ 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 43, 44, 0, ]; + pub unsafe fn dc_decode_modified_utf7( mut to_decode: *const libc::c_char, mut change_spaces: libc::c_int, ) -> *mut libc::c_char { - let mut c: libc::c_uint = 0i32 as libc::c_uint; - let mut i: libc::c_uint = 0i32 as libc::c_uint; - let mut bitcount: libc::c_uint = 0i32 as libc::c_uint; - let mut ucs4: libc::c_ulong = 0; - let mut utf16: libc::c_ulong = 0; - let mut bitbuf: libc::c_ulong = 0; + let mut c: libc::c_uint; + let mut i: libc::c_uint; + let mut bitcount: libc::c_uint; + let mut ucs4: libc::c_ulong; + let mut utf16: libc::c_ulong; + let mut bitbuf: libc::c_ulong; let mut base64: [libc::c_uchar; 256] = [0; 256]; - let mut src: *const libc::c_char = 0 as *const libc::c_char; - let mut dst: *mut libc::c_char = 0 as *mut libc::c_char; - let mut res: *mut libc::c_char = 0 as *mut libc::c_char; + let mut src: *const libc::c_char; + let mut dst: *mut libc::c_char; + let mut res: *mut libc::c_char; if to_decode.is_null() { return dc_strdup(b"\x00" as *const u8 as *const libc::c_char); } @@ -607,8 +612,11 @@ pub unsafe fn dc_decode_modified_utf7( } } *dst = '\u{0}' as i32 as libc::c_char; - return res; + + res } + +// TODO should be bool /rtn pub unsafe fn dc_needs_ext_header(mut to_check: *const libc::c_char) -> libc::c_int { if !to_check.is_null() { while 0 != *to_check { @@ -623,8 +631,10 @@ pub unsafe fn dc_needs_ext_header(mut to_check: *const libc::c_char) -> libc::c_ to_check = to_check.offset(1isize) } } - return 0i32; + + 0 } + pub unsafe fn dc_encode_ext_header(mut to_encode: *const libc::c_char) -> *mut libc::c_char { let mut pstr: *const libc::c_char = to_encode; if to_encode.is_null() { @@ -665,12 +675,14 @@ pub unsafe fn dc_encode_ext_header(mut to_encode: *const libc::c_char) -> *mut l pstr = pstr.offset(1isize) } *pbuf = '\u{0}' as i32 as libc::c_char; - return buf; + + buf } + pub unsafe fn dc_decode_ext_header(mut to_decode: *const libc::c_char) -> *mut libc::c_char { let mut decoded: *mut libc::c_char = 0 as *mut libc::c_char; let mut charset: *mut libc::c_char = 0 as *mut libc::c_char; - let mut p2: *const libc::c_char = 0 as *const libc::c_char; + let mut p2: *const libc::c_char; if !to_decode.is_null() { // get char set p2 = strchr(to_decode, '\'' as i32); @@ -715,3 +727,15 @@ pub unsafe fn dc_decode_ext_header(mut to_decode: *const libc::c_char) -> *mut l dc_strdup(to_decode) }; } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_isalnum() { + assert_eq!(isalnum(0), 0); + assert_eq!(isalnum('5' as libc::c_int), 1); + assert_eq!(isalnum('Q' as libc::c_int), 1); + } +} diff --git a/src/dc_token.rs b/src/dc_token.rs index 6ecc36b9d..6818a6d79 100644 --- a/src/dc_token.rs +++ b/src/dc_token.rs @@ -1,5 +1,3 @@ -use libc; - use crate::dc_context::dc_context_t; use crate::dc_sqlite3::*; use crate::dc_tools::*; @@ -12,17 +10,17 @@ pub const DC_TOKEN_AUTH: dc_tokennamespc_t = 110; pub const DC_TOKEN_INVITENUMBER: dc_tokennamespc_t = 100; // Functions to read/write token from/to the database. A token is any string associated with a key. pub unsafe fn dc_token_save( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut namespc: dc_tokennamespc_t, mut foreign_id: uint32_t, mut token: *const libc::c_char, ) { let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; - if !(context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint || token.is_null()) - { + if !token.is_null() { // foreign_id may be 0 stmt = dc_sqlite3_prepare( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"INSERT INTO tokens (namespc, foreign_id, token, timestamp) VALUES (?, ?, ?, ?);\x00" as *const u8 as *const libc::c_char, ); @@ -35,37 +33,38 @@ pub unsafe fn dc_token_save( sqlite3_finalize(stmt); } pub unsafe fn dc_token_lookup( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut namespc: dc_tokennamespc_t, mut foreign_id: uint32_t, ) -> *mut libc::c_char { - let mut token: *mut libc::c_char = 0 as *mut libc::c_char; - let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; - if !(context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint) { - stmt = dc_sqlite3_prepare( - (*context).sql, - b"SELECT token FROM tokens WHERE namespc=? AND foreign_id=?;\x00" as *const u8 - as *const libc::c_char, - ); - sqlite3_bind_int(stmt, 1i32, namespc as libc::c_int); - sqlite3_bind_int(stmt, 2i32, foreign_id as libc::c_int); - sqlite3_step(stmt); - token = dc_strdup_keep_null(sqlite3_column_text(stmt, 0i32) as *mut libc::c_char) - } + let mut token: *mut libc::c_char; + let mut stmt: *mut sqlite3_stmt; + stmt = dc_sqlite3_prepare( + context, + &context.sql.clone().read().unwrap(), + b"SELECT token FROM tokens WHERE namespc=? AND foreign_id=?;\x00" as *const u8 + as *const libc::c_char, + ); + sqlite3_bind_int(stmt, 1i32, namespc as libc::c_int); + sqlite3_bind_int(stmt, 2i32, foreign_id as libc::c_int); + sqlite3_step(stmt); + token = dc_strdup_keep_null(sqlite3_column_text(stmt, 0i32) as *mut libc::c_char); + sqlite3_finalize(stmt); - return token; + token } + pub unsafe fn dc_token_exists( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut namespc: dc_tokennamespc_t, mut token: *const libc::c_char, ) -> libc::c_int { let mut exists: libc::c_int = 0i32; let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; - if !(context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint || token.is_null()) - { + if !token.is_null() { stmt = dc_sqlite3_prepare( - (*context).sql, + context, + &context.sql.clone().read().unwrap(), b"SELECT id FROM tokens WHERE namespc=? AND token=?;\x00" as *const u8 as *const libc::c_char, ); diff --git a/src/dc_tools.rs b/src/dc_tools.rs index a3efe57bf..39ff4f342 100644 --- a/src/dc_tools.rs +++ b/src/dc_tools.rs @@ -1,4 +1,6 @@ -use libc; +use std::fs; + +use mmime::mailimf_types::*; use rand::{thread_rng, Rng}; use crate::dc_array::*; @@ -16,10 +18,11 @@ no references to dc_context_t and other "larger" classes here. */ pub unsafe fn dc_exactly_one_bit_set(mut v: libc::c_int) -> libc::c_int { return (0 != v && 0 == v & v - 1i32) as libc::c_int; } + /* string tools */ /* dc_strdup() returns empty string if NULL is given, never returns NULL (exits on errors) */ pub unsafe fn dc_strdup(mut s: *const libc::c_char) -> *mut libc::c_char { - let mut ret: *mut libc::c_char = 0 as *mut libc::c_char; + let mut ret: *mut libc::c_char; if !s.is_null() { ret = strdup(s); if ret.is_null() { @@ -31,8 +34,10 @@ pub unsafe fn dc_strdup(mut s: *const libc::c_char) -> *mut libc::c_char { exit(17i32); } } - return ret; + + ret } + /* strdup(NULL) is undefined, safe_strdup_keep_null(NULL) returns NULL in this case */ pub unsafe fn dc_strdup_keep_null(mut s: *const libc::c_char) -> *mut libc::c_char { return if !s.is_null() { @@ -41,9 +46,11 @@ pub unsafe fn dc_strdup_keep_null(mut s: *const libc::c_char) -> *mut libc::c_ch 0 as *mut libc::c_char }; } + pub unsafe fn dc_atoi_null_is_0(mut s: *const libc::c_char) -> libc::c_int { return if !s.is_null() { atoi(s) } else { 0i32 }; } + pub unsafe fn dc_atof(mut str: *const libc::c_char) -> libc::c_double { // hack around atof() that may accept only `,` as decimal point on mac let mut test: *mut libc::c_char = @@ -58,8 +65,10 @@ pub unsafe fn dc_atof(mut str: *const libc::c_char) -> libc::c_double { let mut f: libc::c_double = atof(str_locale); free(test as *mut libc::c_void); free(str_locale as *mut libc::c_void); - return f; + + f } + pub unsafe fn dc_str_replace( mut haystack: *mut *mut libc::c_char, mut needle: *const libc::c_char, @@ -67,8 +76,8 @@ pub unsafe fn dc_str_replace( ) -> libc::c_int { let mut replacements: libc::c_int = 0i32; let mut start_search_pos: libc::c_int = 0i32; - let mut needle_len: libc::c_int = 0i32; - let mut replacement_len: libc::c_int = 0i32; + let mut needle_len: libc::c_int; + let mut replacement_len: libc::c_int; if haystack.is_null() || (*haystack).is_null() || needle.is_null() @@ -106,8 +115,10 @@ pub unsafe fn dc_str_replace( *haystack = new_string; replacements += 1 } - return replacements; + + replacements } + pub unsafe fn dc_ftoa(mut f: libc::c_double) -> *mut libc::c_char { // hack around printf(%f) that may return `,` as decimal point on mac let mut test: *mut libc::c_char = @@ -120,15 +131,17 @@ pub unsafe fn dc_ftoa(mut f: libc::c_double) -> *mut libc::c_char { b".\x00" as *const u8 as *const libc::c_char, ); free(test as *mut libc::c_void); - return str; + + str } + pub unsafe fn dc_ltrim(mut buf: *mut libc::c_char) { - let mut len: size_t = 0i32 as size_t; - let mut cur: *const libc::c_uchar = 0 as *const libc::c_uchar; + let mut len: size_t; + let mut cur: *const libc::c_uchar; if !buf.is_null() && 0 != *buf as libc::c_int { len = strlen(buf); cur = buf as *const libc::c_uchar; - while 0 != *cur as libc::c_int && 0 != isspace(*cur as libc::c_int) { + while 0 != *cur as libc::c_int && 0 != libc::isspace(*cur as libc::c_int) { cur = cur.offset(1isize); len = len.wrapping_sub(1) } @@ -141,20 +154,21 @@ pub unsafe fn dc_ltrim(mut buf: *mut libc::c_char) { } }; } + pub unsafe fn dc_rtrim(mut buf: *mut libc::c_char) { - let mut len: size_t = 0i32 as size_t; - let mut cur: *mut libc::c_uchar = 0 as *mut libc::c_uchar; + let mut len: size_t; + let mut cur: *mut libc::c_uchar; if !buf.is_null() && 0 != *buf as libc::c_int { len = strlen(buf); cur = (buf as *mut libc::c_uchar) .offset(len as isize) .offset(-1isize); - while cur != buf as *mut libc::c_uchar && 0 != isspace(*cur as libc::c_int) { + while cur != buf as *mut libc::c_uchar && 0 != libc::isspace(*cur as libc::c_int) { cur = cur.offset(-1isize); len = len.wrapping_sub(1) } *cur.offset( - (if 0 != isspace(*cur as libc::c_int) { + (if 0 != libc::isspace(*cur as libc::c_int) { 0i32 } else { 1i32 @@ -162,27 +176,32 @@ pub unsafe fn dc_rtrim(mut buf: *mut libc::c_char) { ) = '\u{0}' as i32 as libc::c_uchar }; } + pub unsafe fn dc_trim(mut buf: *mut libc::c_char) { dc_ltrim(buf); dc_rtrim(buf); } + /* the result must be free()'d */ pub unsafe fn dc_strlower(mut in_0: *const libc::c_char) -> *mut libc::c_char { let mut out: *mut libc::c_char = dc_strdup(in_0); let mut p: *mut libc::c_char = out; while 0 != *p { - *p = tolower(*p as libc::c_int) as libc::c_char; + *p = libc::tolower(*p as libc::c_int) as libc::c_char; p = p.offset(1isize) } - return out; + + out } + pub unsafe fn dc_strlower_in_place(mut in_0: *mut libc::c_char) { let mut p: *mut libc::c_char = in_0; while 0 != *p { - *p = tolower(*p as libc::c_int) as libc::c_char; + *p = libc::tolower(*p as libc::c_int) as libc::c_char; p = p.offset(1isize) } } + pub unsafe fn dc_str_contains( mut haystack: *const libc::c_char, mut needle: *const libc::c_char, @@ -202,8 +221,10 @@ pub unsafe fn dc_str_contains( }; free(haystack_lower as *mut libc::c_void); free(needle_lower as *mut libc::c_void); - return ret; + + ret } + /* the result must be free()'d */ pub unsafe fn dc_null_terminate( mut in_0: *const libc::c_char, @@ -217,11 +238,13 @@ pub unsafe fn dc_null_terminate( strncpy(out, in_0, bytes as usize); } *out.offset(bytes as isize) = 0i32 as libc::c_char; - return out; + + out } + pub unsafe fn dc_binary_to_uc_hex(mut buf: *const uint8_t, mut bytes: size_t) -> *mut libc::c_char { let mut hex: *mut libc::c_char = 0 as *mut libc::c_char; - let mut i = 0; + let mut i; if !(buf.is_null() || bytes <= 0) { hex = calloc( ::std::mem::size_of::(), @@ -240,8 +263,10 @@ pub unsafe fn dc_binary_to_uc_hex(mut buf: *const uint8_t, mut bytes: size_t) -> } } } - return hex; + + hex } + /* remove all \r characters from string */ pub unsafe extern "C" fn dc_remove_cr_chars(mut buf: *mut libc::c_char) { /* search for first `\r` */ @@ -263,9 +288,11 @@ pub unsafe extern "C" fn dc_remove_cr_chars(mut buf: *mut libc::c_char) { } *p2 = 0i32 as libc::c_char; } + pub unsafe fn dc_unify_lineends(mut buf: *mut libc::c_char) { dc_remove_cr_chars(buf); } + /* replace bad UTF-8 characters by sequences of `_` (to avoid problems in filenames, we do not use eg. `?`) the function is useful if strings are unexpectingly encoded eg. as ISO-8859-1 */ pub unsafe fn dc_replace_bad_utf8_chars(mut buf: *mut libc::c_char) { let mut current_block: u64; @@ -275,11 +302,11 @@ pub unsafe fn dc_replace_bad_utf8_chars(mut buf: *mut libc::c_char) { /* force unsigned - otherwise the `> ' '` comparison will fail */ let mut p1: *mut libc::c_uchar = buf as *mut libc::c_uchar; let mut p1len: libc::c_int = strlen(buf) as libc::c_int; - let mut c: libc::c_int = 0i32; - let mut i: libc::c_int = 0i32; - let mut ix: libc::c_int = 0i32; - let mut n: libc::c_int = 0i32; - let mut j: libc::c_int = 0i32; + let mut c: libc::c_int; + let mut i: libc::c_int; + let mut ix: libc::c_int; + let mut n: libc::c_int; + let mut j: libc::c_int; i = 0i32; ix = p1len; 's_36: loop { @@ -334,6 +361,7 @@ pub unsafe fn dc_replace_bad_utf8_chars(mut buf: *mut libc::c_char) { } }; } + pub unsafe fn dc_utf8_strlen(mut s: *const libc::c_char) -> size_t { if s.is_null() { return 0i32 as size_t; @@ -346,8 +374,10 @@ pub unsafe fn dc_utf8_strlen(mut s: *const libc::c_char) -> size_t { } i = i.wrapping_add(1) } - return j; + + j } + pub unsafe fn dc_truncate_str(mut buf: *mut libc::c_char, mut approx_chars: libc::c_int) { if approx_chars > 0 && strlen(buf) @@ -368,6 +398,7 @@ pub unsafe fn dc_truncate_str(mut buf: *mut libc::c_char, mut approx_chars: libc strcat(p, b"[...]\x00" as *const u8 as *const libc::c_char); }; } + pub unsafe fn dc_truncate_n_unwrap_str( mut buf: *mut libc::c_char, mut approx_characters: libc::c_int, @@ -411,6 +442,7 @@ pub unsafe fn dc_truncate_n_unwrap_str( dc_remove_cr_chars(buf); }; } + unsafe fn dc_utf8_strnlen(mut s: *const libc::c_char, mut n: size_t) -> size_t { if s.is_null() { return 0i32 as size_t; @@ -423,8 +455,10 @@ unsafe fn dc_utf8_strnlen(mut s: *const libc::c_char, mut n: size_t) -> size_t { } i = i.wrapping_add(1) } - return j; + + j } + /* split string into lines*/ pub unsafe fn dc_split_into_lines(mut buf_terminated: *const libc::c_char) -> *mut carray { let mut lines: *mut carray = carray_new(1024i32 as libc::c_uint); @@ -452,11 +486,13 @@ pub unsafe fn dc_split_into_lines(mut buf_terminated: *const libc::c_char) -> *m strndup(line_start, line_chars) as *mut libc::c_void, &mut l_indx, ); - return lines; + + lines } + pub unsafe fn dc_free_splitted_lines(mut lines: *mut carray) { if !lines.is_null() { - let mut i: libc::c_int = 0; + let mut i: libc::c_int; let mut cnt: libc::c_int = carray_count(lines) as libc::c_int; i = 0i32; while i < cnt { @@ -466,6 +502,7 @@ pub unsafe fn dc_free_splitted_lines(mut lines: *mut carray) { carray_free(lines); }; } + /* insert a break every n characters, the return must be free()'d */ pub unsafe fn dc_insert_breaks( mut in_0: *const libc::c_char, @@ -499,8 +536,10 @@ pub unsafe fn dc_insert_breaks( } } *o = 0i32 as libc::c_char; - return out; + + out } + pub unsafe fn dc_str_from_clist( mut list: *const clist, mut delimiter: *const libc::c_char, @@ -529,12 +568,14 @@ pub unsafe fn dc_str_from_clist( cur = if !cur.is_null() { (*cur).next } else { - 0 as *mut clistcell_s + 0 as *mut clistcell } } } - return str.buf; + + str.buf } + pub unsafe fn dc_str_to_clist( mut str: *const libc::c_char, mut delimiter: *const libc::c_char, @@ -563,8 +604,10 @@ pub unsafe fn dc_str_to_clist( } } } - return list; + + list } + pub unsafe fn dc_str_to_color(mut str: *const libc::c_char) -> libc::c_int { let mut str_lower: *mut libc::c_char = dc_strlower(str); /* the colors must fulfill some criterions as: @@ -604,8 +647,10 @@ pub unsafe fn dc_str_to_color(mut str: *const libc::c_char) -> libc::c_int { .wrapping_div(::std::mem::size_of::() as libc::c_ulong), ) as libc::c_int; free(str_lower as *mut libc::c_void); - return colors[color_index as usize] as libc::c_int; + + colors[color_index as usize] as libc::c_int } + /* clist tools */ /* calls free() for each item content */ pub unsafe fn clist_free_content(mut haystack: *const clist) { @@ -616,10 +661,11 @@ pub unsafe fn clist_free_content(mut haystack: *const clist) { iter = if !iter.is_null() { (*iter).next } else { - 0 as *mut clistcell_s + 0 as *mut clistcell } } } + pub unsafe fn clist_search_string_nocase( mut haystack: *const clist, mut needle: *const libc::c_char, @@ -632,11 +678,13 @@ pub unsafe fn clist_search_string_nocase( iter = if !iter.is_null() { (*iter).next } else { - 0 as *mut clistcell_s + 0 as *mut clistcell } } - return 0i32; + + 0 } + /* date/time tools */ /* the result is UTC or DC_INVALID_TIMESTAMP */ pub unsafe fn dc_timestamp_from_date(mut date_time: *mut mailimf_date_time) -> time_t { @@ -653,9 +701,9 @@ pub unsafe fn dc_timestamp_from_date(mut date_time: *mut mailimf_date_time) -> t tm_gmtoff: 0, tm_zone: 0 as *mut libc::c_char, }; - let mut timeval: time_t = 0i32 as time_t; - let mut zone_min: libc::c_int = 0i32; - let mut zone_hour: libc::c_int = 0i32; + let mut timeval: time_t; + let mut zone_min: libc::c_int; + let mut zone_hour: libc::c_int; memset( &mut tmval as *mut tm as *mut libc::c_void, 0, @@ -680,26 +728,16 @@ pub unsafe fn dc_timestamp_from_date(mut date_time: *mut mailimf_date_time) -> t zone_min = -(-(*date_time).dt_zone % 100i32) } timeval -= (zone_hour * 3600i32 + zone_min * 60i32) as libc::c_long; - return timeval; + + timeval } + pub unsafe fn mkgmtime(mut tmp: *mut tm) -> time_t { - let mut dir: libc::c_int = 0i32; - let mut bits: libc::c_int = 0i32; - let mut saved_seconds: libc::c_int = 0i32; - let mut t: time_t = 0i32 as time_t; - let mut yourtm: tm = tm { - tm_sec: 0, - tm_min: 0, - tm_hour: 0, - tm_mday: 0, - tm_mon: 0, - tm_year: 0, - tm_wday: 0, - tm_yday: 0, - tm_isdst: 0, - tm_gmtoff: 0, - tm_zone: 0 as *mut libc::c_char, - }; + let mut dir: libc::c_int; + let mut bits: libc::c_int; + let mut saved_seconds: libc::c_int; + let mut t: time_t; + let mut yourtm: tm; let mut mytm: tm = tm { tm_sec: 0, tm_min: 0, @@ -750,13 +788,15 @@ pub unsafe fn mkgmtime(mut tmp: *mut tm) -> time_t { } } t += saved_seconds as libc::c_long; - return t; + + t } + /* ****************************************************************************** * date/time tools ******************************************************************************/ unsafe fn tmcomp(mut atmp: *mut tm, mut btmp: *mut tm) -> libc::c_int { - let mut result: libc::c_int = 0i32; + let mut result: libc::c_int; result = (*atmp).tm_year - (*btmp).tm_year; if result == 0i32 && { @@ -778,8 +818,10 @@ unsafe fn tmcomp(mut atmp: *mut tm, mut btmp: *mut tm) -> libc::c_int { { result = (*atmp).tm_sec - (*btmp).tm_sec } - return result; + + result } + /* the return value must be free()'d */ pub unsafe fn dc_timestamp_to_str(mut wanted: time_t) -> *mut libc::c_char { let mut wanted_struct: tm = tm { @@ -810,62 +852,7 @@ pub unsafe fn dc_timestamp_to_str(mut wanted: time_t) -> *mut libc::c_char { wanted_struct.tm_sec as libc::c_int, ); } -pub unsafe fn dc_timestamp_to_mailimap_date_time(mut timeval: time_t) -> *mut mailimap_date_time { - let mut gmt: tm = tm { - tm_sec: 0, - tm_min: 0, - tm_hour: 0, - tm_mday: 0, - tm_mon: 0, - tm_year: 0, - tm_wday: 0, - tm_yday: 0, - tm_isdst: 0, - tm_gmtoff: 0, - tm_zone: 0 as *mut libc::c_char, - }; - let mut lt: tm = tm { - tm_sec: 0, - tm_min: 0, - tm_hour: 0, - tm_mday: 0, - tm_mon: 0, - tm_year: 0, - tm_wday: 0, - tm_yday: 0, - tm_isdst: 0, - tm_gmtoff: 0, - tm_zone: 0 as *mut libc::c_char, - }; - let mut off: libc::c_int = 0i32; - let mut date_time: *mut mailimap_date_time = 0 as *mut mailimap_date_time; - let mut sign: libc::c_int = 0i32; - let mut hour: libc::c_int = 0i32; - let mut min: libc::c_int = 0i32; - gmtime_r(&mut timeval, &mut gmt); - localtime_r(&mut timeval, &mut lt); - off = ((mkgmtime(&mut lt) - mkgmtime(&mut gmt)) / 60i32 as libc::c_long) as libc::c_int; - if off < 0i32 { - sign = -1i32 - } else { - sign = 1i32 - } - off = off * sign; - min = off % 60i32; - hour = off / 60i32; - off = hour * 100i32 + min; - off = off * sign; - date_time = mailimap_date_time_new( - lt.tm_mday, - lt.tm_mon + 1i32, - lt.tm_year + 1900i32, - lt.tm_hour, - lt.tm_min, - lt.tm_sec, - off, - ); - return date_time; -} + pub unsafe fn dc_gm2local_offset() -> libc::c_long { /* returns the offset that must be _added_ to an UTC/GMT-time to create the localtime. the function may return nagative values. */ @@ -884,51 +871,52 @@ pub unsafe fn dc_gm2local_offset() -> libc::c_long { tm_zone: 0 as *mut libc::c_char, }; localtime_r(&mut gmtime, &mut timeinfo); - return timeinfo.tm_gmtoff; + + timeinfo.tm_gmtoff } + /* timesmearing */ -pub unsafe fn dc_smeared_time(mut context: *mut dc_context_t) -> time_t { +pub unsafe fn dc_smeared_time(mut context: &dc_context_t) -> time_t { /* function returns a corrected time(NULL) */ let mut now: time_t = time(0 as *mut time_t); - pthread_mutex_lock(&mut (*context).smear_critical); - if (*context).last_smeared_timestamp >= now { - now = (*context).last_smeared_timestamp + 1i32 as libc::c_long + let mut ts = *context.last_smeared_timestamp.clone().read().unwrap(); + if ts >= now { + now = ts + 1; } - pthread_mutex_unlock(&mut (*context).smear_critical); - return now; + + now } -pub unsafe fn dc_create_smeared_timestamp(mut context: *mut dc_context_t) -> time_t { + +pub unsafe fn dc_create_smeared_timestamp(mut context: &dc_context_t) -> time_t { let mut now: time_t = time(0 as *mut time_t); let mut ret: time_t = now; - pthread_mutex_lock(&mut (*context).smear_critical); - if ret <= (*context).last_smeared_timestamp { - ret = (*context).last_smeared_timestamp + 1i32 as libc::c_long; - if ret - now > 5i32 as libc::c_long { - ret = now + 5i32 as libc::c_long + + let mut ts = *context.last_smeared_timestamp.clone().write().unwrap(); + if ret <= ts { + ret = ts + 1; + if ret - now > 5 { + ret = now + 5 } } - (*context).last_smeared_timestamp = ret; - pthread_mutex_unlock(&mut (*context).smear_critical); - return ret; + + ret } + pub unsafe fn dc_create_smeared_timestamps( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut count: libc::c_int, ) -> time_t { /* get a range to timestamps that can be used uniquely */ let mut now: time_t = time(0 as *mut time_t); let mut start: time_t = now + (if count < 5i32 { count } else { 5i32 }) as libc::c_long - count as libc::c_long; - pthread_mutex_lock(&mut (*context).smear_critical); - start = if (*context).last_smeared_timestamp + 1i32 as libc::c_long > start { - (*context).last_smeared_timestamp + 1i32 as libc::c_long - } else { - start - }; - (*context).last_smeared_timestamp = start + (count - 1i32) as libc::c_long; - pthread_mutex_unlock(&mut (*context).smear_critical); - return start; + + let mut ts = *context.last_smeared_timestamp.clone().write().unwrap(); + start = if ts + 1 > start { ts + 1 } else { start }; + + start } + /* Message-ID tools */ pub unsafe fn dc_create_id() -> *mut libc::c_char { /* generate an id. the generated ID should be as short and as unique as possible: @@ -944,8 +932,10 @@ pub unsafe fn dc_create_id() -> *mut libc::c_char { let mut rng = thread_rng(); let mut buf: [uint32_t; 3] = [rng.gen(), rng.gen(), rng.gen()]; - return encode_66bits_as_base64(buf[0usize], buf[1usize], buf[2usize]); + + encode_66bits_as_base64(buf[0usize], buf[1usize], buf[2usize]) } + /* ****************************************************************************** * generate Message-IDs ******************************************************************************/ @@ -982,8 +972,10 @@ unsafe fn encode_66bits_as_base64( *ret.offset(10isize) = chars[(v2 << 2i32 & 0x3ci32 as libc::c_uint | fill & 0x3i32 as libc::c_uint) as usize]; *ret.offset(11isize) = 0i32 as libc::c_char; - return ret; + + ret } + pub unsafe fn dc_create_incoming_rfc724_mid( mut message_timestamp: time_t, mut contact_id_from: uint32_t, @@ -996,7 +988,6 @@ pub unsafe fn dc_create_incoming_rfc724_mid( let mut i: size_t = 0i32 as size_t; let mut icnt: size_t = dc_array_get_cnt(contact_ids_to); let mut largest_id_to: uint32_t = 0i32 as uint32_t; - i = 0i32 as size_t; while i < icnt { let mut cur_id: uint32_t = dc_array_get_id(contact_ids_to, i); if cur_id > largest_id_to { @@ -1004,13 +995,15 @@ pub unsafe fn dc_create_incoming_rfc724_mid( } i = i.wrapping_add(1) } - return dc_mprintf( + + dc_mprintf( b"%lu-%lu-%lu@stub\x00" as *const u8 as *const libc::c_char, message_timestamp as libc::c_ulong, contact_id_from as libc::c_ulong, largest_id_to as libc::c_ulong, - ); + ) } + pub unsafe fn dc_create_outgoing_rfc724_mid( mut grpid: *const libc::c_char, mut from_addr: *const libc::c_char, @@ -1021,7 +1014,7 @@ pub unsafe fn dc_create_outgoing_rfc724_mid( - do not add a counter or any private data as as this may give unneeded information to the receiver */ let mut rand1: *mut libc::c_char = 0 as *mut libc::c_char; let mut rand2: *mut libc::c_char = dc_create_id(); - let mut ret: *mut libc::c_char = 0 as *mut libc::c_char; + let mut ret: *mut libc::c_char; let mut at_hostname: *const libc::c_char = strchr(from_addr, '@' as i32); if at_hostname.is_null() { at_hostname = b"@nohost\x00" as *const u8 as *const libc::c_char @@ -1044,14 +1037,16 @@ pub unsafe fn dc_create_outgoing_rfc724_mid( } free(rand1 as *mut libc::c_void); free(rand2 as *mut libc::c_void); - return ret; + + ret } + pub unsafe fn dc_extract_grpid_from_rfc724_mid(mut mid: *const libc::c_char) -> *mut libc::c_char { /* extract our group ID from Message-IDs as `Gr.12345678901.morerandom@domain.de`; "12345678901" is the wanted ID in this example. */ let mut success: libc::c_int = 0i32; let mut grpid: *mut libc::c_char = 0 as *mut libc::c_char; - let mut p1: *mut libc::c_char = 0 as *mut libc::c_char; - let mut grpid_len: libc::c_int = 0i32; + let mut p1: *mut libc::c_char; + let mut grpid_len: libc::c_int; if !(mid.is_null() || strlen(mid) < 8 || *mid.offset(0isize) as libc::c_int != 'G' as i32 @@ -1079,6 +1074,7 @@ pub unsafe fn dc_extract_grpid_from_rfc724_mid(mut mid: *const libc::c_char) -> 0 as *mut libc::c_char }; } + pub unsafe fn dc_extract_grpid_from_rfc724_mid_list(mut list: *const clist) -> *mut libc::c_char { if !list.is_null() { let mut cur: *mut clistiter = (*list).first; @@ -1095,12 +1091,14 @@ pub unsafe fn dc_extract_grpid_from_rfc724_mid_list(mut list: *const clist) -> * cur = if !cur.is_null() { (*cur).next } else { - 0 as *mut clistcell_s + 0 as *mut clistcell } } } - return 0 as *mut libc::c_char; + + 0 as *mut libc::c_char } + /* file tools */ pub unsafe fn dc_ensure_no_slash(mut pathNfilename: *mut libc::c_char) { let mut path_len: libc::c_int = strlen(pathNfilename) as libc::c_int; @@ -1112,6 +1110,7 @@ pub unsafe fn dc_ensure_no_slash(mut pathNfilename: *mut libc::c_char) { } }; } + pub unsafe fn dc_validate_filename(mut filename: *mut libc::c_char) { /* function modifies the given buffer and replaces all characters not valid in filenames by a "-" */ let mut p1: *mut libc::c_char = filename; @@ -1125,6 +1124,7 @@ pub unsafe fn dc_validate_filename(mut filename: *mut libc::c_char) { p1 = p1.offset(1isize) } } + pub unsafe fn dc_get_filename(mut pathNfilename: *const libc::c_char) -> *mut libc::c_char { let mut p: *const libc::c_char = strrchr(pathNfilename, '/' as i32); if p.is_null() { @@ -1137,6 +1137,7 @@ pub unsafe fn dc_get_filename(mut pathNfilename: *const libc::c_char) -> *mut li return dc_strdup(pathNfilename); }; } + // the case of the suffix is preserved pub unsafe fn dc_split_filename( mut pathNfilename: *const libc::c_char, @@ -1149,7 +1150,7 @@ pub unsafe fn dc_split_filename( - if there is no suffix, the returned suffix string is empty, eg. "/path/foobar" is split into "foobar" and "" - the case of the returned suffix is preserved; this is to allow reconstruction of (similar) names */ let mut basename: *mut libc::c_char = dc_get_filename(pathNfilename); - let mut suffix: *mut libc::c_char = 0 as *mut libc::c_char; + let mut suffix: *mut libc::c_char; let mut p1: *mut libc::c_char = strrchr(basename, '.' as i32); if !p1.is_null() { suffix = dc_strdup(p1); @@ -1168,6 +1169,7 @@ pub unsafe fn dc_split_filename( free(suffix as *mut libc::c_void); }; } + // the returned suffix is lower-case pub unsafe fn dc_get_filesuffix_lc(mut pathNfilename: *const libc::c_char) -> *mut libc::c_char { if !pathNfilename.is_null() { @@ -1177,8 +1179,10 @@ pub unsafe fn dc_get_filesuffix_lc(mut pathNfilename: *const libc::c_char) -> *m return dc_strlower(p); } } - return 0 as *mut libc::c_char; + + 0 as *mut libc::c_char } + pub unsafe fn dc_get_filemeta( mut buf_start: *const libc::c_void, mut buf_bytes: size_t, @@ -1259,16 +1263,18 @@ pub unsafe fn dc_get_filemeta( + ((*buf.offset(23isize) as libc::c_int) << 0i32)) as uint32_t; return 1i32; } - return 0i32; + + 0 } + pub unsafe fn dc_get_abs_path( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut pathNfilename: *const libc::c_char, ) -> *mut libc::c_char { let mut current_block: u64; let mut success: libc::c_int = 0i32; let mut pathNfilename_abs: *mut libc::c_char = 0 as *mut libc::c_char; - if !(context.is_null() || pathNfilename.is_null()) { + if !pathNfilename.is_null() { pathNfilename_abs = dc_strdup(pathNfilename); if strncmp( pathNfilename_abs, @@ -1276,13 +1282,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; } @@ -1298,13 +1304,19 @@ pub unsafe fn dc_get_abs_path( free(pathNfilename_abs as *mut libc::c_void); pathNfilename_abs = 0 as *mut libc::c_char } - return pathNfilename_abs; + + pathNfilename_abs } + pub unsafe fn dc_file_exist( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut pathNfilename: *const libc::c_char, ) -> libc::c_int { let pathNfilename_abs = dc_get_abs_path(context, pathNfilename); + if pathNfilename_abs.is_null() { + return 0; + } + let exist = { let p = std::path::Path::new( std::ffi::CStr::from_ptr(pathNfilename_abs) @@ -1315,21 +1327,23 @@ pub unsafe fn dc_file_exist( }; free(pathNfilename_abs as *mut libc::c_void); - exist as libc::c_int } pub unsafe fn dc_get_filebytes( - mut context: *mut dc_context_t, - mut pathNfilename: *const libc::c_char, + context: &dc_context_t, + pathNfilename: *const libc::c_char, ) -> uint64_t { let pathNfilename_abs = dc_get_abs_path(context, pathNfilename); + if pathNfilename_abs.is_null() { + return 0; + } let filebytes = { let p = std::ffi::CStr::from_ptr(pathNfilename_abs) .to_str() .unwrap(); - std::fs::metadata(p).unwrap().len() + fs::metadata(p).unwrap().len() }; free(pathNfilename_abs as *mut libc::c_void); @@ -1337,125 +1351,83 @@ pub unsafe fn dc_get_filebytes( } pub unsafe fn dc_delete_file( - mut context: *mut dc_context_t, - mut pathNfilename: *const libc::c_char, + context: &dc_context_t, + pathNfilename: *const libc::c_char, ) -> libc::c_int { let mut success: libc::c_int = 0i32; - let mut pathNfilename_abs: *mut libc::c_char = 0 as *mut libc::c_char; - pathNfilename_abs = dc_get_abs_path(context, pathNfilename); - if !pathNfilename_abs.is_null() { - if remove(pathNfilename_abs) != 0i32 { + let pathNfilename_abs = dc_get_abs_path(context, pathNfilename); + if pathNfilename_abs.is_null() { + return 0; + } + let p = std::path::Path::new( + std::ffi::CStr::from_ptr(pathNfilename_abs) + .to_str() + .unwrap(), + ); + + let res = if p.is_file() { + fs::remove_file(p) + } else { + fs::remove_dir_all(p) + }; + + match res { + Ok(_) => { + success = 1; + } + Err(_err) => { dc_log_warning( context, 0i32, b"Cannot delete \"%s\".\x00" as *const u8 as *const libc::c_char, pathNfilename, ); - } else { - success = 1i32 } } + free(pathNfilename_abs as *mut libc::c_void); - return success; + success } + pub unsafe fn dc_copy_file( - mut context: *mut dc_context_t, - mut src: *const libc::c_char, - mut dest: *const libc::c_char, + context: &dc_context_t, + src: *const libc::c_char, + dest: *const libc::c_char, ) -> libc::c_int { - let mut current_block: u64; - let mut success: libc::c_int = 0i32; - let mut src_abs: *mut libc::c_char = 0 as *mut libc::c_char; - let mut dest_abs: *mut libc::c_char = 0 as *mut libc::c_char; - let mut fd_src: libc::c_int = -1i32; - let mut fd_dest: libc::c_int = -1i32; - let mut buf: [libc::c_char; 4096] = [0; 4096]; - let mut bytes_read = 0; - let mut anything_copied: libc::c_int = 0i32; - src_abs = dc_get_abs_path(context, src); - if !(src_abs.is_null() || { - dest_abs = dc_get_abs_path(context, dest); - dest_abs.is_null() - }) { - fd_src = open(src_abs, 0i32); - if fd_src < 0i32 { + let mut success = 0; + + let src_abs = dc_get_abs_path(context, src); + let dest_abs = dc_get_abs_path(context, dest); + + if src_abs.is_null() || dest_abs.is_null() { + return 0; + } + + let src_p = std::ffi::CStr::from_ptr(src_abs).to_str().unwrap(); + let dest_p = std::ffi::CStr::from_ptr(dest_abs).to_str().unwrap(); + + match fs::copy(src_p, dest_p) { + Ok(_) => { + success = 1; + } + Err(_) => { dc_log_error( context, - 0i32, - b"Cannot open source file \"%s\".\x00" as *const u8 as *const libc::c_char, + 0, + b"Cannot copy \"%s\" to \"%s\".\x00" as *const u8 as *const libc::c_char, src, + dest, ); - } else { - fd_dest = open(dest_abs, 0x1i32 | 0x200i32 | 0x800i32, 0o666i32); - if fd_dest < 0i32 { - dc_log_error( - context, - 0i32, - b"Cannot open destination file \"%s\".\x00" as *const u8 as *const libc::c_char, - dest, - ); - } else { - loop { - bytes_read = read( - fd_src, - buf.as_mut_ptr() as *mut libc::c_void, - 4096i32 as size_t, - ) as size_t; - if !(bytes_read > 0) { - break; - } - if write(fd_dest, buf.as_mut_ptr() as *const libc::c_void, bytes_read) - != bytes_read as isize - { - dc_log_error( - context, - 0i32, - b"Cannot write %i bytes to \"%s\".\x00" as *const u8 - as *const libc::c_char, - bytes_read, - dest, - ); - } - anything_copied = 1i32 - } - if 0 == anything_copied { - close(fd_src); - fd_src = -1i32; - if dc_get_filebytes(context, src) != 0 { - dc_log_error( - context, - 0i32, - b"Different size information for \"%s\".\x00" as *const u8 - as *const libc::c_char, - bytes_read, - dest, - ); - current_block = 610040589300051390; - } else { - current_block = 5634871135123216486; - } - } else { - current_block = 5634871135123216486; - } - match current_block { - 610040589300051390 => {} - _ => success = 1i32, - } - } } } - if fd_src >= 0i32 { - close(fd_src); - } - if fd_dest >= 0i32 { - close(fd_dest); - } + free(src_abs as *mut libc::c_void); free(dest_abs as *mut libc::c_void); - return success; + success } + pub unsafe fn dc_create_folder( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut pathNfilename: *const libc::c_char, ) -> libc::c_int { let mut success = 0; @@ -1467,7 +1439,7 @@ pub unsafe fn dc_create_folder( .unwrap(), ); if !p.exists() { - if mkdir(pathNfilename_abs, 0o755i32 as mode_t) != 0i32 { + if mkdir(pathNfilename_abs, 0o755i32 as libc::mode_t) != 0i32 { dc_log_warning( context, 0i32, @@ -1487,105 +1459,96 @@ pub unsafe fn dc_create_folder( } pub unsafe fn dc_write_file( - mut context: *mut dc_context_t, - mut pathNfilename: *const libc::c_char, - mut buf: *const libc::c_void, - mut buf_bytes: size_t, + context: &dc_context_t, + pathNfilename: *const libc::c_char, + buf: *const libc::c_void, + buf_bytes: size_t, ) -> libc::c_int { - let mut f: *mut libc::FILE = 0 as *mut libc::FILE; - let mut success: libc::c_int = 0i32; - let mut pathNfilename_abs: *mut libc::c_char = 0 as *mut libc::c_char; - pathNfilename_abs = dc_get_abs_path(context, pathNfilename); - if !pathNfilename_abs.is_null() { - f = fopen( - pathNfilename_abs, - b"wb\x00" as *const u8 as *const libc::c_char, - ); - if !f.is_null() { - if fwrite(buf, 1, buf_bytes, f) == buf_bytes { - success = 1i32 - } else { - dc_log_warning( - context, - 0i32, - b"Cannot write %lu bytes to \"%s\".\x00" as *const u8 as *const libc::c_char, - buf_bytes as libc::c_ulong, - pathNfilename, - ); - } - fclose(f); - } else { + let mut success = 0; + let pathNfilename_abs = dc_get_abs_path(context, pathNfilename); + if pathNfilename_abs.is_null() { + return 0; + } + + let p = std::ffi::CStr::from_ptr(pathNfilename_abs) + .to_str() + .unwrap(); + + let bytes = std::slice::from_raw_parts(buf as *const u8, buf_bytes); + + match fs::write(p, bytes) { + Ok(_) => { + success = 1; + } + Err(_err) => { dc_log_warning( context, 0i32, - b"Cannot open \"%s\" for writing.\x00" as *const u8 as *const libc::c_char, + b"Cannot write %lu bytes to \"%s\".\x00" as *const u8 as *const libc::c_char, + buf_bytes as libc::c_ulong, pathNfilename, ); } } + free(pathNfilename_abs as *mut libc::c_void); - return success; + success } + pub unsafe fn dc_read_file( - mut context: *mut dc_context_t, - mut pathNfilename: *const libc::c_char, - mut buf: *mut *mut libc::c_void, - mut buf_bytes: *mut size_t, + context: &dc_context_t, + pathNfilename: *const libc::c_char, + buf: *mut *mut libc::c_void, + buf_bytes: *mut size_t, ) -> libc::c_int { - let mut success: libc::c_int = 0i32; - let mut pathNfilename_abs: *mut libc::c_char = 0 as *mut libc::c_char; - let mut f: *mut libc::FILE = 0 as *mut libc::FILE; + let mut success = 0; + if pathNfilename.is_null() || buf.is_null() || buf_bytes.is_null() { - return 0i32; + return 0; } + *buf = 0 as *mut libc::c_void; *buf_bytes = 0i32 as size_t; - pathNfilename_abs = dc_get_abs_path(context, pathNfilename); - if !pathNfilename_abs.is_null() { - f = fopen( - pathNfilename_abs, - b"rb\x00" as *const u8 as *const libc::c_char, - ); - if !f.is_null() { - fseek(f, 0, 2i32); - *buf_bytes = ftell(f) as size_t; - fseek(f, 0, 0i32); - if !(*buf_bytes <= 0) { - *buf = malloc((*buf_bytes).wrapping_add(1)); - if !(*buf).is_null() { - *(*buf as *mut libc::c_char).offset(*buf_bytes as isize) = 0i32 as libc::c_char; - if !(fread(*buf, 1, *buf_bytes, f) != *buf_bytes) { - success = 1i32 - } - } - } + + let pathNfilename_abs = dc_get_abs_path(context, pathNfilename); + if pathNfilename_abs.is_null() { + return 0; + } + + let p = std::ffi::CStr::from_ptr(pathNfilename_abs) + .to_str() + .unwrap(); + + match fs::read(p) { + Ok(mut bytes) => { + *buf = &mut bytes[..] as *mut _ as *mut libc::c_void; + *buf_bytes = bytes.len(); + std::mem::forget(bytes); + + success = 1; + } + Err(_err) => { + dc_log_warning( + context, + 0, + b"Cannot read \"%s\" or file is empty.\x00" as *const u8 as *const libc::c_char, + pathNfilename, + ); } } - if !f.is_null() { - fclose(f); - } - if success == 0i32 { - free(*buf); - *buf = 0 as *mut libc::c_void; - *buf_bytes = 0i32 as size_t; - dc_log_warning( - context, - 0i32, - b"Cannot read \"%s\" or file is empty.\x00" as *const u8 as *const libc::c_char, - pathNfilename, - ); - } + free(pathNfilename_abs as *mut libc::c_void); - return success; + success } + pub unsafe fn dc_get_fine_pathNfilename( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut pathNfolder: *const libc::c_char, mut desired_filenameNsuffix__: *const libc::c_char, ) -> *mut libc::c_char { let mut ret: *mut libc::c_char = 0 as *mut libc::c_char; - let mut pathNfolder_wo_slash: *mut libc::c_char = 0 as *mut libc::c_char; - let mut filenameNsuffix: *mut libc::c_char = 0 as *mut libc::c_char; + let mut pathNfolder_wo_slash: *mut libc::c_char; + let mut filenameNsuffix: *mut libc::c_char; let mut basename: *mut libc::c_char = 0 as *mut libc::c_char; let mut dotNSuffix: *mut libc::c_char = 0 as *mut libc::c_char; let mut now: time_t = time(0 as *mut time_t); @@ -1595,7 +1558,6 @@ pub unsafe fn dc_get_fine_pathNfilename( filenameNsuffix = dc_strdup(desired_filenameNsuffix__); dc_validate_filename(filenameNsuffix); dc_split_filename(filenameNsuffix, &mut basename, &mut dotNSuffix); - i = 0i32; while i < 1000i32 { /*no deadlocks, please*/ if 0 != i { @@ -1632,39 +1594,46 @@ pub unsafe fn dc_get_fine_pathNfilename( free(basename as *mut libc::c_void); free(dotNSuffix as *mut libc::c_void); free(pathNfolder_wo_slash as *mut libc::c_void); - return ret; + + ret } + +// TODO should return bool /rtn pub unsafe fn dc_is_blobdir_path( - mut context: *mut dc_context_t, + 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; } - return 0i32; + + 0 } -pub unsafe fn dc_make_rel_path(mut context: *mut dc_context_t, mut path: *mut *mut libc::c_char) { - if context.is_null() || path.is_null() || (*path).is_null() { + +pub unsafe fn dc_make_rel_path(mut context: &dc_context_t, mut path: *mut *mut libc::c_char) { + 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, ); }; } + +// TODO should return bool /rtn pub unsafe fn dc_make_rel_and_copy( - mut context: *mut dc_context_t, + mut context: &dc_context_t, mut path: *mut *mut libc::c_char, ) -> libc::c_int { let mut success: libc::c_int = 0i32; let mut filename: *mut libc::c_char = 0 as *mut libc::c_char; let mut blobdir_path: *mut libc::c_char = 0 as *mut libc::c_char; - if !(context.is_null() || path.is_null() || (*path).is_null()) { + if !(path.is_null() || (*path).is_null()) { if 0 != dc_is_blobdir_path(context, *path) { dc_make_rel_path(context, path); success = 1i32 @@ -1691,5 +1660,60 @@ pub unsafe fn dc_make_rel_and_copy( } free(blobdir_path as *mut libc::c_void); free(filename as *mut libc::c_void); - return success; + + success +} + +#[cfg(test)] +mod tests { + use super::*; + use std::ffi::CStr; + + #[test] + fn test_dc_ltrim() { + unsafe { + let mut html: *const libc::c_char = + b"\r\r\nline1
\r\n\r\n\r\rline2\n\r\x00" as *const u8 as *const libc::c_char; + let mut out: *mut libc::c_char = strndup(html, strlen(html) as libc::c_ulong); + + dc_ltrim(out); + + assert_eq!( + CStr::from_ptr(out as *const libc::c_char).to_str().unwrap(), + "line1
\r\n\r\n\r\rline2\n\r" + ); + } + } + + #[test] + fn test_dc_rtrim() { + unsafe { + let mut html: *const libc::c_char = + b"\r\r\nline1
\r\n\r\n\r\rline2\n\r\x00" as *const u8 as *const libc::c_char; + let mut out: *mut libc::c_char = strndup(html, strlen(html) as libc::c_ulong); + + dc_rtrim(out); + + assert_eq!( + CStr::from_ptr(out as *const libc::c_char).to_str().unwrap(), + "\r\r\nline1
\r\n\r\n\r\rline2" + ); + } + } + + #[test] + fn test_dc_trim() { + unsafe { + let mut html: *const libc::c_char = + b"\r\r\nline1
\r\n\r\n\r\rline2\n\r\x00" as *const u8 as *const libc::c_char; + let mut out: *mut libc::c_char = strndup(html, strlen(html) as libc::c_ulong); + + dc_trim(out); + + assert_eq!( + CStr::from_ptr(out as *const libc::c_char).to_str().unwrap(), + "line1
\r\n\r\n\r\rline2" + ); + } + } } diff --git a/src/lib.rs b/src/lib.rs index 6b2fe8638..dbae66233 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,7 +3,6 @@ non_camel_case_types, non_snake_case, non_upper_case_globals, - unused_assignments, unused_mut, unused_attributes, non_upper_case_globals, @@ -21,6 +20,11 @@ extern crate failure; #[macro_use] extern crate num_derive; +// #[macro_use] +// extern crate rental; + +#[macro_use] +pub mod dc_log; mod pgp; @@ -44,7 +48,6 @@ pub mod dc_key; pub mod dc_keyhistory; pub mod dc_keyring; pub mod dc_location; -pub mod dc_log; pub mod dc_loginparam; pub mod dc_lot; pub mod dc_mimefactory; diff --git a/src/types.rs b/src/types.rs index 272430039..e0575ee88 100644 --- a/src/types.rs +++ b/src/types.rs @@ -1,23 +1,74 @@ -use c2rust_bitfields::BitfieldStruct; -use libc; - use crate::constants::Event; use crate::dc_context::dc_context_t; -use crate::dc_imap::dc_imap_t; -use crate::x::*; -pub use libc::{ - dirent, pthread_attr_t, pthread_cond_t, pthread_condattr_t, pthread_mutex_t, - pthread_mutexattr_t, pthread_t, tm, DIR, FILE, -}; +pub use libc::{dirent, tm, DIR, FILE}; pub use libsqlite3_sys::*; +pub use mmime::carray::*; +pub use mmime::clist::*; -extern "C" { - pub type __sFILEX; - - pub type _telldir; - pub type mailstream_cancel; +pub type __builtin_va_list = [__va_list_tag; 1]; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct __va_list_tag { + pub gp_offset: libc::c_uint, + pub fp_offset: libc::c_uint, + pub overflow_arg_area: *mut libc::c_void, + pub reg_save_area: *mut libc::c_void, } +pub type va_list = __builtin_va_list; +pub type __int64_t = libc::c_longlong; +pub type __darwin_ct_rune_t = libc::c_int; +pub type __darwin_wchar_t = libc::c_int; +pub type __darwin_rune_t = __darwin_wchar_t; +pub type uint64_t = libc::c_ulonglong; +pub type uid_t = libc::uid_t; +pub type gid_t = libc::gid_t; +pub type dev_t = libc::dev_t; +pub type blkcnt_t = libc::blkcnt_t; +pub type blksize_t = libc::blksize_t; +pub type nlink_t = __uint16_t; + +/** + * Callback function that should be given to dc_context_new(). + * + * @memberof dc_context_t + * @param context The context object as returned by dc_context_new(). + * @param event one of the @ref DC_EVENT constants + * @param data1 depends on the event parameter + * @param data2 depends on the event parameter + * @return return 0 unless stated otherwise in the event parameter documentation + */ +pub type dc_callback_t = + unsafe extern "C" fn(_: &dc_context_t, _: Event, _: uintptr_t, _: uintptr_t) -> uintptr_t; + +pub type dc_move_state_t = u32; + +pub type dc_receive_imf_t = unsafe fn( + _: &dc_context_t, + _: *const libc::c_char, + _: size_t, + _: *const libc::c_char, + _: uint32_t, + _: uint32_t, +) -> (); + +/* Purpose: Reading from IMAP servers with no dependencies to the database. +dc_context_t is only used for logging and to get information about +the online state. */ + +pub type dc_precheck_imf_t = unsafe fn( + _: &dc_context_t, + _: *const libc::c_char, + _: *const libc::c_char, + _: u32, +) -> libc::c_int; +pub type dc_set_config_t = + unsafe fn(_: &dc_context_t, _: *const libc::c_char, _: *const libc::c_char) -> (); +pub type dc_get_config_t = unsafe fn( + _: &dc_context_t, + _: *const libc::c_char, + _: *const libc::c_char, +) -> *mut libc::c_char; pub type sqlite_int64 = libc::int64_t; pub type sqlite3_int64 = sqlite_int64; @@ -40,1500 +91,3 @@ pub type uint8_t = libc::c_uchar; pub type uint16_t = libc::c_ushort; pub type __uint32_t = libc::c_uint; - -#[derive(Copy, Clone)] -#[repr(C)] -pub struct carray_s { - pub array: *mut *mut libc::c_void, - pub len: libc::c_uint, - pub max: libc::c_uint, -} -pub type carray = carray_s; - -pub type mailimap_msg_att_handler = - unsafe extern "C" fn(_: *mut mailimap_msg_att, _: *mut libc::c_void) -> (); -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimap { - pub imap_response: *mut libc::c_char, - pub imap_stream: *mut mailstream, - pub imap_progr_rate: size_t, - pub imap_progr_fun: Option ()>, - pub imap_stream_buffer: *mut MMAPString, - pub imap_response_buffer: *mut MMAPString, - pub imap_state: libc::c_int, - pub imap_tag: libc::c_int, - pub imap_connection_info: *mut mailimap_connection_info, - pub imap_selection_info: *mut mailimap_selection_info, - pub imap_response_info: *mut mailimap_response_info, - pub imap_sasl: unnamed_2, - pub imap_idle_timestamp: time_t, - pub imap_idle_maxdelay: time_t, - pub imap_body_progress_fun: - Option ()>, - pub imap_items_progress_fun: - Option ()>, - pub imap_progress_context: *mut libc::c_void, - pub imap_msg_att_handler: - Option ()>, - pub imap_msg_att_handler_context: *mut libc::c_void, - pub imap_msg_body_handler: Option< - unsafe extern "C" fn( - _: libc::c_int, - _: *mut mailimap_msg_att_body_section, - _: *const libc::c_char, - _: size_t, - _: *mut libc::c_void, - ) -> bool, - >, - pub imap_msg_body_handler_context: *mut libc::c_void, - pub imap_timeout: time_t, - pub imap_logger: Option< - unsafe extern "C" fn( - _: *mut mailimap, - _: libc::c_int, - _: *const libc::c_char, - _: size_t, - _: *mut libc::c_void, - ) -> (), - >, - pub imap_logger_context: *mut libc::c_void, - pub is_163_workaround_enabled: libc::c_int, - pub is_rambler_workaround_enabled: libc::c_int, - pub is_qip_workaround_enabled: libc::c_int, -} - -#[derive(Copy, Clone)] -#[repr(C)] -pub struct _mailstream { - pub buffer_max_size: size_t, - pub write_buffer: *mut libc::c_char, - pub write_buffer_len: size_t, - pub read_buffer: *mut libc::c_char, - pub read_buffer_len: size_t, - pub low: *mut mailstream_low, - pub idle: *mut mailstream_cancel, - pub idling: libc::c_int, - pub logger: Option< - unsafe extern "C" fn( - _: *mut mailstream, - _: libc::c_int, - _: *const libc::c_char, - _: size_t, - _: *mut libc::c_void, - ) -> (), - >, - pub logger_context: *mut libc::c_void, -} -pub type mailstream = _mailstream; -pub type mailstream_low = _mailstream_low; -#[derive(Copy, Clone)] -#[repr(C)] -pub struct _mailstream_low { - pub data: *mut libc::c_void, - pub driver: *mut mailstream_low_driver, - pub privacy: libc::c_int, - pub identifier: *mut libc::c_char, - pub timeout: libc::c_ulong, - pub logger: Option< - unsafe extern "C" fn( - _: *mut mailstream_low, - _: libc::c_int, - _: *const libc::c_char, - _: size_t, - _: *mut libc::c_void, - ) -> (), - >, - pub logger_context: *mut libc::c_void, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailstream_low_driver { - pub mailstream_read: Option< - unsafe extern "C" fn(_: *mut mailstream_low, _: *mut libc::c_void, _: size_t) -> ssize_t, - >, - pub mailstream_write: Option< - unsafe extern "C" fn(_: *mut mailstream_low, _: *const libc::c_void, _: size_t) -> ssize_t, - >, - pub mailstream_close: Option libc::c_int>, - pub mailstream_get_fd: Option libc::c_int>, - pub mailstream_free: Option ()>, - pub mailstream_cancel: Option ()>, - pub mailstream_get_cancel: - Option *mut mailstream_cancel>, - pub mailstream_get_certificate_chain: - Option *mut carray>, - pub mailstream_setup_idle: Option libc::c_int>, - pub mailstream_unsetup_idle: - Option libc::c_int>, - pub mailstream_interrupt_idle: - Option libc::c_int>, -} -pub type progress_function = unsafe extern "C" fn(_: size_t, _: size_t) -> (); -pub type mailprogress_function = - unsafe extern "C" fn(_: size_t, _: size_t, _: *mut libc::c_void) -> (); -pub type unnamed = libc::c_uint; -pub const MAILSTREAM_IDLE_CANCELLED: unnamed = 4; -pub const MAILSTREAM_IDLE_TIMEOUT: unnamed = 3; -pub const MAILSTREAM_IDLE_HASDATA: unnamed = 2; -pub const MAILSTREAM_IDLE_INTERRUPTED: unnamed = 1; -pub const MAILSTREAM_IDLE_ERROR: unnamed = 0; -#[derive(Copy, Clone)] -#[repr(C)] -pub struct _MMAPString { - pub str_0: *mut libc::c_char, - pub len: size_t, - pub allocated_len: size_t, - pub fd: libc::c_int, - pub mmapped_size: size_t, -} -pub type MMAPString = _MMAPString; -#[derive(Copy, Clone)] -#[repr(C)] -pub struct clistcell_s { - pub data: *mut libc::c_void, - pub previous: *mut clistcell_s, - pub next: *mut clistcell_s, -} -pub type clistcell = clistcell_s; -#[derive(Copy, Clone)] -#[repr(C)] -pub struct clist_s { - pub first: *mut clistcell, - pub last: *mut clistcell, - pub count: libc::c_int, -} -pub type clist = clist_s; -pub type clistiter = clistcell; -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailsmtp { - pub stream: *mut mailstream, - pub progr_rate: size_t, - pub progr_fun: Option ()>, - pub response: *mut libc::c_char, - pub line_buffer: *mut MMAPString, - pub response_buffer: *mut MMAPString, - pub esmtp: libc::c_int, - pub auth: libc::c_int, - pub smtp_sasl: unnamed_0, - pub smtp_max_msg_size: size_t, - pub smtp_progress_fun: - Option ()>, - pub smtp_progress_context: *mut libc::c_void, - pub response_code: libc::c_int, - pub smtp_timeout: time_t, - pub smtp_logger: Option< - unsafe extern "C" fn( - _: *mut mailsmtp, - _: libc::c_int, - _: *const libc::c_char, - _: size_t, - _: *mut libc::c_void, - ) -> (), - >, - pub smtp_logger_context: *mut libc::c_void, -} - -#[derive(Copy, Clone)] -#[repr(C)] -pub struct unnamed_0 { - pub sasl_conn: *mut libc::c_void, - pub sasl_server_fqdn: *const libc::c_char, - pub sasl_login: *const libc::c_char, - pub sasl_auth_name: *const libc::c_char, - pub sasl_password: *const libc::c_char, - pub sasl_realm: *const libc::c_char, - pub sasl_secret: *mut libc::c_void, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimap_body { - pub bd_type: libc::c_int, - pub bd_data: unnamed_1, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub union unnamed_1 { - pub bd_body_1part: *mut mailimap_body_type_1part, - pub bd_body_mpart: *mut mailimap_body_type_mpart, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimap_body_type_mpart { - pub bd_list: *mut clist, - pub bd_media_subtype: *mut libc::c_char, - pub bd_ext_mpart: *mut mailimap_body_ext_mpart, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimap_body_ext_mpart { - pub bd_parameter: *mut mailimap_body_fld_param, - pub bd_disposition: *mut mailimap_body_fld_dsp, - pub bd_language: *mut mailimap_body_fld_lang, - pub bd_loc: *mut libc::c_char, - pub bd_extension_list: *mut clist, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimap_body_fld_lang { - pub lg_type: libc::c_int, - pub lg_data: unnamed_2, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub union unnamed_2 { - pub lg_single: *mut libc::c_char, - pub lg_list: *mut clist, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimap_body_fld_dsp { - pub dsp_type: *mut libc::c_char, - pub dsp_attributes: *mut mailimap_body_fld_param, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimap_body_fld_param { - pub pa_list: *mut clist, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimap_body_type_1part { - pub bd_type: libc::c_int, - pub bd_data: unnamed_3, - pub bd_ext_1part: *mut mailimap_body_ext_1part, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimap_body_ext_1part { - pub bd_md5: *mut libc::c_char, - pub bd_disposition: *mut mailimap_body_fld_dsp, - pub bd_language: *mut mailimap_body_fld_lang, - pub bd_loc: *mut libc::c_char, - pub bd_extension_list: *mut clist, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub union unnamed_3 { - pub bd_type_basic: *mut mailimap_body_type_basic, - pub bd_type_msg: *mut mailimap_body_type_msg, - pub bd_type_text: *mut mailimap_body_type_text, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimap_body_type_text { - pub bd_media_text: *mut libc::c_char, - pub bd_fields: *mut mailimap_body_fields, - pub bd_lines: uint32_t, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimap_body_fields { - pub bd_parameter: *mut mailimap_body_fld_param, - pub bd_id: *mut libc::c_char, - pub bd_description: *mut libc::c_char, - pub bd_encoding: *mut mailimap_body_fld_enc, - pub bd_size: uint32_t, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimap_body_fld_enc { - pub enc_type: libc::c_int, - pub enc_value: *mut libc::c_char, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimap_body_type_msg { - pub bd_fields: *mut mailimap_body_fields, - pub bd_envelope: *mut mailimap_envelope, - pub bd_body: *mut mailimap_body, - pub bd_lines: uint32_t, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimap_envelope { - pub env_date: *mut libc::c_char, - pub env_subject: *mut libc::c_char, - pub env_from: *mut mailimap_env_from, - pub env_sender: *mut mailimap_env_sender, - pub env_reply_to: *mut mailimap_env_reply_to, - pub env_to: *mut mailimap_env_to, - pub env_cc: *mut mailimap_env_cc, - pub env_bcc: *mut mailimap_env_bcc, - pub env_in_reply_to: *mut libc::c_char, - pub env_message_id: *mut libc::c_char, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimap_env_bcc { - pub bcc_list: *mut clist, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimap_env_cc { - pub cc_list: *mut clist, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimap_env_to { - pub to_list: *mut clist, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimap_env_reply_to { - pub rt_list: *mut clist, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimap_env_sender { - pub snd_list: *mut clist, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimap_env_from { - pub frm_list: *mut clist, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimap_body_type_basic { - pub bd_media_basic: *mut mailimap_media_basic, - pub bd_fields: *mut mailimap_body_fields, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimap_media_basic { - pub med_type: libc::c_int, - pub med_basic_type: *mut libc::c_char, - pub med_subtype: *mut libc::c_char, -} -pub type unnamed_4 = libc::c_uint; -pub const MAILIMAP_CAPABILITY_NAME: unnamed_4 = 1; -pub const MAILIMAP_CAPABILITY_AUTH_TYPE: unnamed_4 = 0; -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimap_capability { - pub cap_type: libc::c_int, - pub cap_data: unnamed_5, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub union unnamed_5 { - pub cap_auth_type: *mut libc::c_char, - pub cap_name: *mut libc::c_char, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimap_capability_data { - pub cap_list: *mut clist, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimap_extension_data { - pub ext_extension: *mut mailimap_extension_api, - pub ext_type: libc::c_int, - pub ext_data: *mut libc::c_void, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimap_extension_api { - pub ext_name: *mut libc::c_char, - pub ext_id: libc::c_int, - pub ext_parser: Option< - unsafe extern "C" fn( - _: libc::c_int, - _: *mut mailstream, - _: *mut MMAPString, - _: *mut mailimap_parser_context, - _: *mut size_t, - _: *mut *mut mailimap_extension_data, - _: size_t, - _: Option ()>, - ) -> libc::c_int, - >, - pub ext_free: Option ()>, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimap_parser_context { - pub is_rambler_workaround_enabled: libc::c_int, - pub is_qip_workaround_enabled: libc::c_int, - pub msg_body_handler: Option< - unsafe extern "C" fn( - _: libc::c_int, - _: *mut mailimap_msg_att_body_section, - _: *const libc::c_char, - _: size_t, - _: *mut libc::c_void, - ) -> bool, - >, - pub msg_body_handler_context: *mut libc::c_void, - pub msg_body_section: *mut mailimap_msg_att_body_section, - pub msg_body_att_type: libc::c_int, - pub msg_body_parse_in_progress: bool, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimap_msg_att_body_section { - pub sec_section: *mut mailimap_section, - pub sec_origin_octet: uint32_t, - pub sec_body_part: *mut libc::c_char, - pub sec_length: size_t, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimap_section { - pub sec_spec: *mut mailimap_section_spec, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimap_section_spec { - pub sec_type: libc::c_int, - pub sec_data: unnamed_6, - pub sec_text: *mut mailimap_section_text, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimap_section_text { - pub sec_type: libc::c_int, - pub sec_msgtext: *mut mailimap_section_msgtext, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimap_section_msgtext { - pub sec_type: libc::c_int, - pub sec_header_list: *mut mailimap_header_list, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimap_header_list { - pub hdr_list: *mut clist, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub union unnamed_6 { - pub sec_msgtext: *mut mailimap_section_msgtext, - pub sec_part: *mut mailimap_section_part, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimap_section_part { - pub sec_id: *mut clist, -} -pub type mailimap_msg_body_handler = unsafe fn( - _: libc::c_int, - _: *mut mailimap_msg_att_body_section, - _: *const libc::c_char, - _: size_t, - _: *mut libc::c_void, -) -> bool; -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimap_date_time { - pub dt_day: libc::c_int, - pub dt_month: libc::c_int, - pub dt_year: libc::c_int, - pub dt_hour: libc::c_int, - pub dt_min: libc::c_int, - pub dt_sec: libc::c_int, - pub dt_zone: libc::c_int, -} -pub type unnamed_7 = libc::c_uint; -pub const MAILIMAP_FLAG_EXTENSION: unnamed_7 = 6; -pub const MAILIMAP_FLAG_KEYWORD: unnamed_7 = 5; -pub const MAILIMAP_FLAG_DRAFT: unnamed_7 = 4; -pub const MAILIMAP_FLAG_SEEN: unnamed_7 = 3; -pub const MAILIMAP_FLAG_DELETED: unnamed_7 = 2; -pub const MAILIMAP_FLAG_FLAGGED: unnamed_7 = 1; -pub const MAILIMAP_FLAG_ANSWERED: unnamed_7 = 0; -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimap_flag { - pub fl_type: libc::c_int, - pub fl_data: unnamed_8, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub union unnamed_8 { - pub fl_keyword: *mut libc::c_char, - pub fl_extension: *mut libc::c_char, -} -pub type unnamed_9 = libc::c_uint; -pub const MAILIMAP_FLAG_FETCH_OTHER: unnamed_9 = 2; -pub const MAILIMAP_FLAG_FETCH_RECENT: unnamed_9 = 1; -pub const MAILIMAP_FLAG_FETCH_ERROR: unnamed_9 = 0; -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimap_flag_fetch { - pub fl_type: libc::c_int, - pub fl_flag: *mut mailimap_flag, -} -pub type unnamed_10 = libc::c_uint; -pub const MAILIMAP_FLAG_PERM_ALL: unnamed_10 = 2; -pub const MAILIMAP_FLAG_PERM_FLAG: unnamed_10 = 1; -pub const MAILIMAP_FLAG_PERM_ERROR: unnamed_10 = 0; -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimap_flag_perm { - pub fl_type: libc::c_int, - pub fl_flag: *mut mailimap_flag, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimap_flag_list { - pub fl_list: *mut clist, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimap_mailbox_data_status { - pub st_mailbox: *mut libc::c_char, - pub st_info_list: *mut clist, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimap_msg_att { - pub att_list: *mut clist, - pub att_number: uint32_t, -} -pub type unnamed_11 = libc::c_uint; -pub const MAILIMAP_MSG_ATT_ITEM_EXTENSION: unnamed_11 = 3; -pub const MAILIMAP_MSG_ATT_ITEM_STATIC: unnamed_11 = 2; -pub const MAILIMAP_MSG_ATT_ITEM_DYNAMIC: unnamed_11 = 1; -pub const MAILIMAP_MSG_ATT_ITEM_ERROR: unnamed_11 = 0; -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimap_msg_att_item { - pub att_type: libc::c_int, - pub att_data: unnamed_12, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub union unnamed_12 { - pub att_dyn: *mut mailimap_msg_att_dynamic, - pub att_static: *mut mailimap_msg_att_static, - pub att_extension_data: *mut mailimap_extension_data, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimap_msg_att_static { - pub att_type: libc::c_int, - pub att_data: unnamed_13, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub union unnamed_13 { - pub att_env: *mut mailimap_envelope, - pub att_internal_date: *mut mailimap_date_time, - pub att_rfc822: unnamed_16, - pub att_rfc822_header: unnamed_15, - pub att_rfc822_text: unnamed_14, - pub att_rfc822_size: uint32_t, - pub att_bodystructure: *mut mailimap_body, - pub att_body: *mut mailimap_body, - pub att_body_section: *mut mailimap_msg_att_body_section, - pub att_uid: uint32_t, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct unnamed_14 { - pub att_content: *mut libc::c_char, - pub att_length: size_t, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct unnamed_15 { - pub att_content: *mut libc::c_char, - pub att_length: size_t, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct unnamed_16 { - pub att_content: *mut libc::c_char, - pub att_length: size_t, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimap_msg_att_dynamic { - pub att_list: *mut clist, -} -pub type unnamed_17 = libc::c_uint; -pub const MAILIMAP_MSG_ATT_UID: unnamed_17 = 10; -pub const MAILIMAP_MSG_ATT_BODY_SECTION: unnamed_17 = 9; -pub const MAILIMAP_MSG_ATT_BODYSTRUCTURE: unnamed_17 = 8; -pub const MAILIMAP_MSG_ATT_BODY: unnamed_17 = 7; -pub const MAILIMAP_MSG_ATT_RFC822_SIZE: unnamed_17 = 6; -pub const MAILIMAP_MSG_ATT_RFC822_TEXT: unnamed_17 = 5; -pub const MAILIMAP_MSG_ATT_RFC822_HEADER: unnamed_17 = 4; -pub const MAILIMAP_MSG_ATT_RFC822: unnamed_17 = 3; -pub const MAILIMAP_MSG_ATT_INTERNALDATE: unnamed_17 = 2; -pub const MAILIMAP_MSG_ATT_ENVELOPE: unnamed_17 = 1; -pub const MAILIMAP_MSG_ATT_ERROR: unnamed_17 = 0; -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimap_set_item { - pub set_first: uint32_t, - pub set_last: uint32_t, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimap_set { - pub set_list: *mut clist, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimap_fetch_att { - pub att_type: libc::c_int, - pub att_section: *mut mailimap_section, - pub att_offset: uint32_t, - pub att_size: uint32_t, - pub att_extension: *mut libc::c_char, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimap_fetch_type { - pub ft_type: libc::c_int, - pub ft_data: unnamed_18, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub union unnamed_18 { - pub ft_fetch_att: *mut mailimap_fetch_att, - pub ft_fetch_att_list: *mut clist, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimap_store_att_flags { - pub fl_sign: libc::c_int, - pub fl_silent: libc::c_int, - pub fl_flag_list: *mut mailimap_flag_list, -} - -#[derive(Copy, Clone)] -#[repr(C)] -pub struct unnamed_19 { - pub sasl_conn: *mut libc::c_void, - pub sasl_server_fqdn: *const libc::c_char, - pub sasl_login: *const libc::c_char, - pub sasl_auth_name: *const libc::c_char, - pub sasl_password: *const libc::c_char, - pub sasl_realm: *const libc::c_char, - pub sasl_secret: *mut libc::c_void, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimap_response_info { - pub rsp_alert: *mut libc::c_char, - pub rsp_parse: *mut libc::c_char, - pub rsp_badcharset: *mut clist, - pub rsp_trycreate: libc::c_int, - pub rsp_mailbox_list: *mut clist, - pub rsp_mailbox_lsub: *mut clist, - pub rsp_search_result: *mut clist, - pub rsp_status: *mut mailimap_mailbox_data_status, - pub rsp_expunged: *mut clist, - pub rsp_fetch_list: *mut clist, - pub rsp_extension_list: *mut clist, - pub rsp_atom: *mut libc::c_char, - pub rsp_value: *mut libc::c_char, -} -#[derive(BitfieldStruct, Clone, Copy)] -#[repr(C)] -pub struct mailimap_selection_info { - pub sel_perm_flags: *mut clist, - pub sel_perm: libc::c_int, - pub sel_uidnext: uint32_t, - pub sel_uidvalidity: uint32_t, - pub sel_first_unseen: uint32_t, - pub sel_flags: *mut mailimap_flag_list, - pub sel_exists: uint32_t, - pub sel_recent: uint32_t, - pub sel_unseen: uint32_t, - #[bitfield(name = "sel_has_exists", ty = "uint8_t", bits = "0..=0")] - #[bitfield(name = "sel_has_recent", ty = "uint8_t", bits = "1..=1")] - pub sel_has_exists_sel_has_recent: [u8; 1], - pub _pad: [u8; 3], -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimap_connection_info { - pub imap_capability: *mut mailimap_capability_data, -} -pub type unnamed_20 = libc::c_uint; -pub const MAILIMAP_ERROR_CLIENTID: unnamed_20 = 46; -pub const MAILIMAP_ERROR_CUSTOM_COMMAND: unnamed_20 = 45; -pub const MAILIMAP_ERROR_NEEDS_MORE_DATA: unnamed_20 = 44; -pub const MAILIMAP_ERROR_SSL: unnamed_20 = 43; -pub const MAILIMAP_ERROR_SASL: unnamed_20 = 42; -pub const MAILIMAP_ERROR_EXTENSION: unnamed_20 = 41; -pub const MAILIMAP_ERROR_INVAL: unnamed_20 = 40; -pub const MAILIMAP_ERROR_STARTTLS: unnamed_20 = 39; -pub const MAILIMAP_ERROR_UNSUBSCRIBE: unnamed_20 = 38; -pub const MAILIMAP_ERROR_SUBSCRIBE: unnamed_20 = 37; -pub const MAILIMAP_ERROR_UID_STORE: unnamed_20 = 36; -pub const MAILIMAP_ERROR_STORE: unnamed_20 = 35; -pub const MAILIMAP_ERROR_STATUS: unnamed_20 = 34; -pub const MAILIMAP_ERROR_SELECT: unnamed_20 = 33; -pub const MAILIMAP_ERROR_UID_SEARCH: unnamed_20 = 32; -pub const MAILIMAP_ERROR_SEARCH: unnamed_20 = 31; -pub const MAILIMAP_ERROR_RENAME: unnamed_20 = 30; -pub const MAILIMAP_ERROR_LSUB: unnamed_20 = 29; -pub const MAILIMAP_ERROR_LOGIN: unnamed_20 = 28; -pub const MAILIMAP_ERROR_LIST: unnamed_20 = 27; -pub const MAILIMAP_ERROR_UID_FETCH: unnamed_20 = 26; -pub const MAILIMAP_ERROR_FETCH: unnamed_20 = 25; -pub const MAILIMAP_ERROR_EXAMINE: unnamed_20 = 24; -pub const MAILIMAP_ERROR_DELETE: unnamed_20 = 23; -pub const MAILIMAP_ERROR_CREATE: unnamed_20 = 22; -pub const MAILIMAP_ERROR_UID_MOVE: unnamed_20 = 21; -pub const MAILIMAP_ERROR_MOVE: unnamed_20 = 20; -pub const MAILIMAP_ERROR_UID_COPY: unnamed_20 = 19; -pub const MAILIMAP_ERROR_COPY: unnamed_20 = 18; -pub const MAILIMAP_ERROR_EXPUNGE: unnamed_20 = 17; -pub const MAILIMAP_ERROR_CLOSE: unnamed_20 = 16; -pub const MAILIMAP_ERROR_CHECK: unnamed_20 = 15; -pub const MAILIMAP_ERROR_CAPABILITY: unnamed_20 = 14; -pub const MAILIMAP_ERROR_LOGOUT: unnamed_20 = 13; -pub const MAILIMAP_ERROR_NOOP: unnamed_20 = 12; -pub const MAILIMAP_ERROR_APPEND: unnamed_20 = 11; -pub const MAILIMAP_ERROR_DONT_ACCEPT_CONNECTION: unnamed_20 = 10; -pub const MAILIMAP_ERROR_PROTOCOL: unnamed_20 = 9; -pub const MAILIMAP_ERROR_FATAL: unnamed_20 = 8; -pub const MAILIMAP_ERROR_MEMORY: unnamed_20 = 7; -pub const MAILIMAP_ERROR_CONNECTION_REFUSED: unnamed_20 = 6; -pub const MAILIMAP_ERROR_PARSE: unnamed_20 = 5; -pub const MAILIMAP_ERROR_STREAM: unnamed_20 = 4; -pub const MAILIMAP_ERROR_BAD_STATE: unnamed_20 = 3; -pub const MAILIMAP_NO_ERROR_NON_AUTHENTICATED: unnamed_20 = 2; -pub const MAILIMAP_NO_ERROR_AUTHENTICATED: unnamed_20 = 1; -pub const MAILIMAP_NO_ERROR: unnamed_20 = 0; - -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimf_fields { - pub fld_list: *mut clist, -} - -pub const MAILIMF_FIELD_OPTIONAL_FIELD: unnamed = 22; -pub const MAILIMF_FIELD_KEYWORDS: unnamed = 21; -pub const MAILIMF_FIELD_COMMENTS: unnamed = 20; -pub const MAILIMF_FIELD_SUBJECT: unnamed = 19; -pub const MAILIMF_FIELD_REFERENCES: unnamed = 18; -pub const MAILIMF_FIELD_IN_REPLY_TO: unnamed = 17; -pub const MAILIMF_FIELD_MESSAGE_ID: unnamed = 16; -pub const MAILIMF_FIELD_BCC: unnamed = 15; -pub const MAILIMF_FIELD_CC: unnamed = 14; -pub const MAILIMF_FIELD_TO: unnamed = 13; -pub const MAILIMF_FIELD_REPLY_TO: unnamed = 12; -pub const MAILIMF_FIELD_SENDER: unnamed = 11; -pub const MAILIMF_FIELD_FROM: unnamed = 10; -pub const MAILIMF_FIELD_ORIG_DATE: unnamed = 9; -pub const MAILIMF_FIELD_RESENT_MSG_ID: unnamed = 8; -pub const MAILIMF_FIELD_RESENT_BCC: unnamed = 7; -pub const MAILIMF_FIELD_RESENT_CC: unnamed = 6; -pub const MAILIMF_FIELD_RESENT_TO: unnamed = 5; -pub const MAILIMF_FIELD_RESENT_SENDER: unnamed = 4; -pub const MAILIMF_FIELD_RESENT_FROM: unnamed = 3; -pub const MAILIMF_FIELD_RESENT_DATE: unnamed = 2; -pub const MAILIMF_FIELD_RETURN_PATH: unnamed = 1; -pub const MAILIMF_FIELD_NONE: unnamed = 0; -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimf_field { - pub fld_type: libc::c_int, - pub fld_data: field_data, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub union field_data { - pub fld_return_path: *mut mailimf_return, - pub fld_resent_date: *mut mailimf_orig_date, - pub fld_resent_from: *mut mailimf_from, - pub fld_resent_sender: *mut mailimf_sender, - pub fld_resent_to: *mut mailimf_to, - pub fld_resent_cc: *mut mailimf_cc, - pub fld_resent_bcc: *mut mailimf_bcc, - pub fld_resent_msg_id: *mut mailimf_message_id, - pub fld_orig_date: *mut mailimf_orig_date, - pub fld_from: *mut mailimf_from, - pub fld_sender: *mut mailimf_sender, - pub fld_reply_to: *mut mailimf_reply_to, - pub fld_to: *mut mailimf_to, - pub fld_cc: *mut mailimf_cc, - pub fld_bcc: *mut mailimf_bcc, - pub fld_message_id: *mut mailimf_message_id, - pub fld_in_reply_to: *mut mailimf_in_reply_to, - pub fld_references: *mut mailimf_references, - pub fld_subject: *mut mailimf_subject, - pub fld_comments: *mut mailimf_comments, - pub fld_keywords: *mut mailimf_keywords, - pub fld_optional_field: *mut mailimf_optional_field, -} - -pub const MAILMIME_MESSAGE: unnamed_11 = 3; -pub const MAILMIME_MULTIPLE: unnamed_11 = 2; -pub const MAILMIME_SINGLE: unnamed_11 = 1; -pub const MAILMIME_NONE: unnamed_11 = 0; -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailmime { - pub mm_parent_type: libc::c_int, - pub mm_parent: *mut mailmime, - pub mm_multipart_pos: *mut clistiter, - pub mm_type: libc::c_int, - pub mm_mime_start: *const libc::c_char, - pub mm_length: size_t, - pub mm_mime_fields: *mut mailmime_fields, - pub mm_content_type: *mut mailmime_content, - pub mm_body: *mut mailmime_data, - pub mm_data: unnamed_12n, -} - -#[derive(Copy, Clone)] -#[repr(C)] -pub union unnamed_12n { - pub mm_single: *mut mailmime_data, - pub mm_multipart: unnamed_14n, - pub mm_message: unnamed_13n, -} - -#[derive(Copy, Clone)] -#[repr(C)] -pub struct unnamed_13n { - pub mm_fields: *mut mailimf_fields, - pub mm_msg_mime: *mut mailmime, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct unnamed_14n { - pub mm_preamble: *mut mailmime_data, - pub mm_epilogue: *mut mailmime_data, - pub mm_mp_list: *mut clist, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailmime_fields { - pub fld_list: *mut clist, -} - -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailmime_content { - pub ct_type: *mut mailmime_type, - pub ct_subtype: *mut libc::c_char, - pub ct_parameters: *mut clist, -} - -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailmime_data { - pub dt_type: libc::c_int, - pub dt_encoding: libc::c_int, - pub dt_encoded: libc::c_int, - pub dt_data: unnamed_9n, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub union unnamed_9n { - pub dt_text: unnamed_10n, - pub dt_filename: *mut libc::c_char, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct unnamed_10n { - pub dt_data: *const libc::c_char, - pub dt_length: size_t, -} - -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailmime_type { - pub tp_type: libc::c_int, - pub tp_data: unnamed_3n, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub union unnamed_3n { - pub tp_discrete_type: *mut mailmime_discrete_type, - pub tp_composite_type: *mut mailmime_composite_type, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailmime_discrete_type { - pub dt_type: libc::c_int, - pub dt_extension: *mut libc::c_char, -} - -pub const MAILMIME_COMPOSITE_TYPE_EXTENSION: libc::c_int = 3; -pub const MAILMIME_COMPOSITE_TYPE_MULTIPART: libc::c_int = 2; -pub const MAILMIME_COMPOSITE_TYPE_MESSAGE: libc::c_int = 1; -pub const MAILMIME_COMPOSITE_TYPE_ERROR: libc::c_int = 0; -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailmime_composite_type { - pub ct_type: libc::c_int, - pub ct_token: *mut libc::c_char, -} - -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimf_optional_field { - pub fld_name: *mut libc::c_char, - pub fld_value: *mut libc::c_char, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimf_keywords { - pub kw_list: *mut clist, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimf_comments { - pub cm_value: *mut libc::c_char, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimf_subject { - pub sbj_value: *mut libc::c_char, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimf_references { - pub mid_list: *mut clist, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimf_in_reply_to { - pub mid_list: *mut clist, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimf_message_id { - pub mid_value: *mut libc::c_char, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimf_bcc { - pub bcc_addr_list: *mut mailimf_address_list, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimf_cc { - pub cc_addr_list: *mut mailimf_address_list, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimf_to { - pub to_addr_list: *mut mailimf_address_list, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimf_reply_to { - pub rt_addr_list: *mut mailimf_address_list, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimf_sender { - pub snd_mb: *mut mailimf_mailbox, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimf_from { - pub frm_mb_list: *mut mailimf_mailbox_list, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimf_orig_date { - pub dt_date_time: *mut mailimf_date_time, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimf_return { - pub ret_path: *mut mailimf_path, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimf_path { - pub pt_addr_spec: *mut libc::c_char, -} - -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimf_mailbox { - pub mb_display_name: *mut libc::c_char, - pub mb_addr_spec: *mut libc::c_char, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimf_address_list { - pub ad_list: *mut clist, -} - -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimf_mailbox_list { - pub mb_list: *mut clist, -} - -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimf_date_time { - pub dt_day: libc::c_int, - pub dt_month: libc::c_int, - pub dt_year: libc::c_int, - pub dt_hour: libc::c_int, - pub dt_min: libc::c_int, - pub dt_sec: libc::c_int, - pub dt_zone: libc::c_int, -} - -pub type __builtin_va_list = [__va_list_tag; 1]; -#[derive(Copy, Clone)] -#[repr(C)] -pub struct __va_list_tag { - pub gp_offset: libc::c_uint, - pub fp_offset: libc::c_uint, - pub overflow_arg_area: *mut libc::c_void, - pub reg_save_area: *mut libc::c_void, -} -pub type va_list = __builtin_va_list; -pub type __int64_t = libc::c_longlong; -pub type __darwin_ct_rune_t = libc::c_int; -pub type __darwin_wchar_t = libc::c_int; -pub type __darwin_rune_t = __darwin_wchar_t; - -#[derive(Copy, Clone)] -#[repr(C)] -pub struct timespec { - pub tv_sec: libc::time_t, - pub tv_nsec: libc::c_long, -} - -#[derive(Copy, Clone)] -#[repr(C)] -pub struct _RuneEntry { - pub __min: __darwin_rune_t, - pub __max: __darwin_rune_t, - pub __map: __darwin_rune_t, - pub __types: *mut __uint32_t, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct _RuneRange { - pub __nranges: libc::c_int, - pub __ranges: *mut _RuneEntry, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct _RuneCharClass { - pub __name: [libc::c_char; 14], - pub __mask: __uint32_t, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct _RuneLocale { - pub __magic: [libc::c_char; 8], - pub __encoding: [libc::c_char; 32], - pub __sgetrune: Option< - unsafe extern "C" fn( - _: *const libc::c_char, - _: size_t, - _: *mut *const libc::c_char, - ) -> __darwin_rune_t, - >, - pub __sputrune: Option< - unsafe extern "C" fn( - _: __darwin_rune_t, - _: *mut libc::c_char, - _: size_t, - _: *mut *mut libc::c_char, - ) -> libc::c_int, - >, - pub __invalid_rune: __darwin_rune_t, - pub __runetype: [__uint32_t; 256], - pub __maplower: [__darwin_rune_t; 256], - pub __mapupper: [__darwin_rune_t; 256], - pub __runetype_ext: _RuneRange, - pub __maplower_ext: _RuneRange, - pub __mapupper_ext: _RuneRange, - pub __variable: *mut libc::c_void, - pub __variable_len: libc::c_int, - pub __ncharclasses: libc::c_int, - pub __charclasses: *mut _RuneCharClass, -} -pub type mode_t = libc::mode_t; -pub type off_t = libc::off_t; - -pub type uint64_t = libc::c_ulonglong; -pub type uid_t = libc::uid_t; -pub type gid_t = libc::gid_t; -pub type dev_t = libc::dev_t; -pub type blkcnt_t = libc::blkcnt_t; -pub type blksize_t = libc::blksize_t; -pub type nlink_t = __uint16_t; - -pub type dc_receive_imf_t = Option< - unsafe fn( - _: *mut dc_imap_t, - _: *const libc::c_char, - _: size_t, - _: *const libc::c_char, - _: uint32_t, - _: uint32_t, - ) -> (), ->; -/* Purpose: Reading from IMAP servers with no dependencies to the database. -dc_context_t is only used for logging and to get information about -the online state. */ - -pub type dc_precheck_imf_t = Option< - unsafe fn( - _: *mut dc_imap_t, - _: *const libc::c_char, - _: *const libc::c_char, - _: uint32_t, - ) -> libc::c_int, ->; -pub type dc_set_config_t = - Option ()>; -pub type dc_get_config_t = Option< - unsafe fn( - _: *mut dc_imap_t, - _: *const libc::c_char, - _: *const libc::c_char, - ) -> *mut libc::c_char, ->; -/* ** library-private **********************************************************/ - -/* * - * Library-internal. - */ -#[derive(Copy, Clone)] -#[repr(C)] -pub struct _dc_sqlite3 { - pub cobj: *mut sqlite3, - pub context: *mut dc_context_t, -} - -#[inline] -pub unsafe fn isascii(mut _c: libc::c_int) -> libc::c_int { - return (_c & !0x7fi32 == 0i32) as libc::c_int; -} - -#[inline] -pub unsafe fn isspace(mut _c: libc::c_int) -> libc::c_int { - if _c < std::u8::MAX as libc::c_int { - ((_c as u8 as char) == ' ') as libc::c_int - } else { - 0 - } -} - -#[inline] -pub unsafe fn tolower(mut _c: libc::c_int) -> libc::c_int { - return __tolower(_c); -} - -#[inline] -pub unsafe fn carray_count(mut array: *mut carray) -> libc::c_uint { - return (*array).len; -} - -#[inline] -pub unsafe fn carray_get(mut array: *mut carray, mut indx: libc::c_uint) -> *mut libc::c_void { - return *(*array).array.offset(indx as isize); -} - -/* * - * Callback function that should be given to dc_context_new(). - * - * @memberof dc_context_t - * @param context The context object as returned by dc_context_new(). - * @param event one of the @ref DC_EVENT constants - * @param data1 depends on the event parameter - * @param data2 depends on the event parameter - * @return return 0 unless stated otherwise in the event parameter documentation - */ -pub type dc_callback_t = - unsafe extern "C" fn(_: *mut dc_context_t, _: Event, _: uintptr_t, _: uintptr_t) -> uintptr_t; - -pub const DC_MOVE_STATE_MOVING: libc::c_uint = 3; -pub const DC_MOVE_STATE_STAY: libc::c_uint = 2; -pub const DC_MOVE_STATE_PENDING: libc::c_uint = 1; -pub const DC_MOVE_STATE_UNDEFINED: libc::c_uint = 0; - -pub const MAILIMF_ERROR_FILE: libc::c_uint = 4; -pub const MAILIMF_ERROR_INVAL: libc::c_uint = 3; -pub const MAILIMF_ERROR_MEMORY: libc::c_uint = 2; -pub const MAILIMF_ERROR_PARSE: libc::c_uint = 1; -pub const MAILIMF_NO_ERROR: libc::c_uint = 0; - -pub const MAIL_CHARCONV_ERROR_CONV: libc::c_uint = 3; -pub const MAIL_CHARCONV_ERROR_MEMORY: libc::c_uint = 2; -pub const MAIL_CHARCONV_ERROR_UNKNOWN_CHARSET: libc::c_uint = 1; -pub const MAIL_CHARCONV_NO_ERROR: libc::c_uint = 0; - -pub const MAILSMTP_ERROR_CLIENTID_NOT_SUPPORTED: libc::c_uint = 28; -pub const MAILSMTP_ERROR_SSL: libc::c_uint = 27; -pub const MAILSMTP_ERROR_AUTH_AUTHENTICATION_FAILED: libc::c_uint = 26; -pub const MAILSMTP_ERROR_CONNECTION_REFUSED: libc::c_uint = 25; -pub const MAILSMTP_ERROR_STARTTLS_NOT_SUPPORTED: libc::c_uint = 24; -pub const MAILSMTP_ERROR_STARTTLS_TEMPORARY_FAILURE: libc::c_uint = 23; -pub const MAILSMTP_ERROR_AUTH_ENCRYPTION_REQUIRED: libc::c_uint = 22; -pub const MAILSMTP_ERROR_AUTH_TEMPORARY_FAILTURE: libc::c_uint = 21; -pub const MAILSMTP_ERROR_AUTH_TRANSITION_NEEDED: libc::c_uint = 20; -pub const MAILSMTP_ERROR_AUTH_TOO_WEAK: libc::c_uint = 19; -pub const MAILSMTP_ERROR_AUTH_REQUIRED: libc::c_uint = 18; -pub const MAILSMTP_ERROR_AUTH_LOGIN: libc::c_uint = 17; -pub const MAILSMTP_ERROR_AUTH_NOT_SUPPORTED: libc::c_uint = 16; -pub const MAILSMTP_ERROR_MEMORY: libc::c_uint = 15; -pub const MAILSMTP_ERROR_TRANSACTION_FAILED: libc::c_uint = 14; -pub const MAILSMTP_ERROR_USER_NOT_LOCAL: libc::c_uint = 13; -pub const MAILSMTP_ERROR_BAD_SEQUENCE_OF_COMMAND: libc::c_uint = 12; -pub const MAILSMTP_ERROR_MAILBOX_NAME_NOT_ALLOWED: libc::c_uint = 11; -pub const MAILSMTP_ERROR_MAILBOX_UNAVAILABLE: libc::c_uint = 10; -pub const MAILSMTP_ERROR_INSUFFICIENT_SYSTEM_STORAGE: libc::c_uint = 9; -pub const MAILSMTP_ERROR_IN_PROCESSING: libc::c_uint = 8; -pub const MAILSMTP_ERROR_EXCEED_STORAGE_ALLOCATION: libc::c_uint = 7; -pub const MAILSMTP_ERROR_ACTION_NOT_TAKEN: libc::c_uint = 6; -pub const MAILSMTP_ERROR_NOT_IMPLEMENTED: libc::c_uint = 5; -pub const MAILSMTP_ERROR_HOSTNAME: libc::c_uint = 4; -pub const MAILSMTP_ERROR_STREAM: libc::c_uint = 3; -pub const MAILSMTP_ERROR_SERVICE_NOT_AVAILABLE: libc::c_uint = 2; -pub const MAILSMTP_ERROR_UNEXPECTED_CODE: libc::c_uint = 1; -pub const MAILSMTP_NO_ERROR: libc::c_uint = 0; -pub const MAILSMTP_AUTH_KERBEROS_V4: libc::c_uint = 256; -pub const MAILSMTP_AUTH_NTLM: libc::c_uint = 128; -pub const MAILSMTP_AUTH_SRP: libc::c_uint = 64; -pub const MAILSMTP_AUTH_GSSAPI: libc::c_uint = 32; -pub const MAILSMTP_AUTH_DIGEST_MD5: libc::c_uint = 16; -pub const MAILSMTP_AUTH_LOGIN: libc::c_uint = 8; -pub const MAILSMTP_AUTH_PLAIN: libc::c_uint = 4; -pub const MAILSMTP_AUTH_CRAM_MD5: libc::c_uint = 2; -pub const MAILSMTP_AUTH_CHECKED: libc::c_uint = 1; -pub const MAILSMTP_AUTH_NOT_CHECKED: libc::c_uint = 0; - -pub type dc_imap_res = libc::c_uint; -pub const DC_SUCCESS: dc_imap_res = 3; -pub const DC_ALREADY_DONE: dc_imap_res = 2; -pub const DC_RETRY_LATER: dc_imap_res = 1; -pub const DC_FAILED: dc_imap_res = 0; - -pub type dc_move_state_t = libc::c_uint; - -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailmime_disposition_parm { - pub pa_type: libc::c_int, - pub pa_data: unnamed_20n, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub union unnamed_20n { - pub pa_filename: *mut libc::c_char, - pub pa_creation_date: *mut libc::c_char, - pub pa_modification_date: *mut libc::c_char, - pub pa_read_date: *mut libc::c_char, - pub pa_size: size_t, - pub pa_parameter: *mut mailmime_parameter, -} - -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailmime_field { - pub fld_type: libc::c_int, - pub fld_data: unnamed_5n, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub union unnamed_5n { - pub fld_content: *mut mailmime_content, - pub fld_encoding: *mut mailmime_mechanism, - pub fld_id: *mut libc::c_char, - pub fld_description: *mut libc::c_char, - pub fld_version: uint32_t, - pub fld_disposition: *mut mailmime_disposition, - pub fld_language: *mut mailmime_language, - pub fld_location: *mut libc::c_char, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailmime_language { - pub lg_list: *mut clist, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailmime_disposition { - pub dsp_type: *mut mailmime_disposition_type, - pub dsp_parms: *mut clist, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailmime_disposition_type { - pub dsp_type: libc::c_int, - pub dsp_extension: *mut libc::c_char, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailmime_mechanism { - pub enc_type: libc::c_int, - pub enc_token: *mut libc::c_char, -} - -pub const MAILIMF_ADDRESS_GROUP: libc::c_uint = 2; -pub const MAILIMF_ADDRESS_MAILBOX: libc::c_uint = 1; -pub const MAILIMF_ADDRESS_ERROR: libc::c_uint = 0; -pub const MAILMIME_MECHANISM_TOKEN: libc::c_uint = 6; -pub const MAILMIME_MECHANISM_BASE64: libc::c_uint = 5; -pub const MAILMIME_MECHANISM_QUOTED_PRINTABLE: libc::c_uint = 4; -pub const MAILMIME_MECHANISM_BINARY: libc::c_uint = 3; -pub const MAILMIME_MECHANISM_8BIT: libc::c_uint = 2; -pub const MAILMIME_MECHANISM_7BIT: libc::c_uint = 1; -pub const MAILMIME_MECHANISM_ERROR: libc::c_uint = 0; - -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimf_group { - pub grp_display_name: *mut libc::c_char, - pub grp_mb_list: *mut mailimf_mailbox_list, -} - -pub const MAILMIME_DISPOSITION_TYPE_EXTENSION: libc::c_uint = 3; -pub const MAILMIME_DISPOSITION_TYPE_ATTACHMENT: libc::c_uint = 2; -pub const MAILMIME_DISPOSITION_TYPE_INLINE: libc::c_uint = 1; -pub const MAILMIME_DISPOSITION_TYPE_ERROR: libc::c_uint = 0; -pub const MAILMIME_DISPOSITION_PARM_PARAMETER: libc::c_uint = 5; -pub const MAILMIME_DISPOSITION_PARM_SIZE: libc::c_uint = 4; -pub const MAILMIME_DISPOSITION_PARM_READ_DATE: libc::c_uint = 3; -pub const MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE: libc::c_uint = 2; -pub const MAILMIME_DISPOSITION_PARM_CREATION_DATE: libc::c_uint = 1; -pub const MAILMIME_DISPOSITION_PARM_FILENAME: libc::c_uint = 0; - -pub const MAILMIME_FIELD_LOCATION: libc::c_uint = 8; -pub const MAILMIME_FIELD_LANGUAGE: libc::c_uint = 7; -pub const MAILMIME_FIELD_DISPOSITION: libc::c_uint = 6; -pub const MAILMIME_FIELD_VERSION: libc::c_uint = 5; -pub const MAILMIME_FIELD_DESCRIPTION: libc::c_uint = 4; -pub const MAILMIME_FIELD_ID: libc::c_uint = 3; -pub const MAILMIME_FIELD_TRANSFER_ENCODING: libc::c_uint = 2; -pub const MAILMIME_FIELD_TYPE: libc::c_uint = 1; -pub const MAILMIME_FIELD_NONE: libc::c_uint = 0; - -pub const MAILMIME_TYPE_COMPOSITE_TYPE: libc::c_uint = 2; -pub const MAILMIME_TYPE_DISCRETE_TYPE: libc::c_uint = 1; -pub const MAILMIME_TYPE_ERROR: libc::c_uint = 0; -pub const MAILMIME_DATA_FILE: libc::c_uint = 1; -pub const MAILMIME_DATA_TEXT: libc::c_uint = 0; - -pub const MAIL_ERROR_SSL: libc::c_uint = 58; -pub const MAIL_ERROR_FOLDER: libc::c_uint = 57; -pub const MAIL_ERROR_UNABLE: libc::c_uint = 56; -pub const MAIL_ERROR_SYSTEM: libc::c_uint = 55; -pub const MAIL_ERROR_COMMAND: libc::c_uint = 54; -pub const MAIL_ERROR_SEND: libc::c_uint = 53; -pub const MAIL_ERROR_CHAR_ENCODING_FAILED: libc::c_uint = 52; -pub const MAIL_ERROR_SUBJECT_NOT_FOUND: libc::c_uint = 51; -pub const MAIL_ERROR_PROGRAM_ERROR: libc::c_uint = 50; -pub const MAIL_ERROR_NO_PERMISSION: libc::c_uint = 49; -pub const MAIL_ERROR_COMMAND_NOT_SUPPORTED: libc::c_uint = 48; -pub const MAIL_ERROR_NO_APOP: libc::c_uint = 47; -pub const MAIL_ERROR_READONLY: libc::c_uint = 46; -pub const MAIL_ERROR_FATAL: libc::c_uint = 45; -pub const MAIL_ERROR_CLOSE: libc::c_uint = 44; -pub const MAIL_ERROR_CAPABILITY: libc::c_uint = 43; -pub const MAIL_ERROR_PROTOCOL: libc::c_uint = 42; -pub const MAIL_ERROR_MISC: libc::c_uint = 41; -pub const MAIL_ERROR_EXPUNGE: libc::c_uint = 40; -pub const MAIL_ERROR_NO_TLS: libc::c_uint = 39; -pub const MAIL_ERROR_CACHE_MISS: libc::c_uint = 38; -pub const MAIL_ERROR_STARTTLS: libc::c_uint = 37; -pub const MAIL_ERROR_MOVE: libc::c_uint = 36; -pub const MAIL_ERROR_FOLDER_NOT_FOUND: libc::c_uint = 35; -pub const MAIL_ERROR_REMOVE: libc::c_uint = 34; -pub const MAIL_ERROR_PART_NOT_FOUND: libc::c_uint = 33; -pub const MAIL_ERROR_INVAL: libc::c_uint = 32; -pub const MAIL_ERROR_PARSE: libc::c_uint = 31; -pub const MAIL_ERROR_MSG_NOT_FOUND: libc::c_uint = 30; -pub const MAIL_ERROR_DISKSPACE: libc::c_uint = 29; -pub const MAIL_ERROR_SEARCH: libc::c_uint = 28; -pub const MAIL_ERROR_STORE: libc::c_uint = 27; -pub const MAIL_ERROR_FETCH: libc::c_uint = 26; -pub const MAIL_ERROR_COPY: libc::c_uint = 25; -pub const MAIL_ERROR_APPEND: libc::c_uint = 24; -pub const MAIL_ERROR_LSUB: libc::c_uint = 23; -pub const MAIL_ERROR_LIST: libc::c_uint = 22; -pub const MAIL_ERROR_UNSUBSCRIBE: libc::c_uint = 21; -pub const MAIL_ERROR_SUBSCRIBE: libc::c_uint = 20; -pub const MAIL_ERROR_STATUS: libc::c_uint = 19; -pub const MAIL_ERROR_MEMORY: libc::c_uint = 18; -pub const MAIL_ERROR_SELECT: libc::c_uint = 17; -pub const MAIL_ERROR_EXAMINE: libc::c_uint = 16; -pub const MAIL_ERROR_CHECK: libc::c_uint = 15; -pub const MAIL_ERROR_RENAME: libc::c_uint = 14; -pub const MAIL_ERROR_NOOP: libc::c_uint = 13; -pub const MAIL_ERROR_LOGOUT: libc::c_uint = 12; -pub const MAIL_ERROR_DELETE: libc::c_uint = 11; -pub const MAIL_ERROR_CREATE: libc::c_uint = 10; -pub const MAIL_ERROR_LOGIN: libc::c_uint = 9; -pub const MAIL_ERROR_STREAM: libc::c_uint = 8; -pub const MAIL_ERROR_FILE: libc::c_uint = 7; -pub const MAIL_ERROR_BAD_STATE: libc::c_uint = 6; -pub const MAIL_ERROR_CONNECT: libc::c_uint = 5; -pub const MAIL_ERROR_UNKNOWN: libc::c_uint = 4; -pub const MAIL_ERROR_NOT_IMPLEMENTED: libc::c_uint = 3; -pub const MAIL_NO_ERROR_NON_AUTHENTICATED: libc::c_uint = 2; -pub const MAIL_NO_ERROR_AUTHENTICATED: libc::c_uint = 1; -pub const MAIL_NO_ERROR: libc::c_uint = 0; - -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimf_address { - pub ad_type: libc::c_int, - pub ad_data: unnamed_0n, -} - -#[derive(Copy, Clone)] -#[repr(C)] -pub union unnamed_0n { - pub ad_mailbox: *mut mailimf_mailbox, - pub ad_group: *mut mailimf_group, -} - -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailmime_parameter { - pub pa_name: *mut libc::c_char, - pub pa_value: *mut libc::c_char, -} - -pub const MAILMIME_DISCRETE_TYPE_EXTENSION: libc::c_uint = 6; -pub const MAILMIME_DISCRETE_TYPE_APPLICATION: libc::c_uint = 5; -pub const MAILMIME_DISCRETE_TYPE_VIDEO: libc::c_uint = 4; -pub const MAILMIME_DISCRETE_TYPE_AUDIO: libc::c_uint = 3; -pub const MAILMIME_DISCRETE_TYPE_IMAGE: libc::c_uint = 2; -pub const MAILMIME_DISCRETE_TYPE_TEXT: libc::c_uint = 1; -pub const MAILMIME_DISCRETE_TYPE_ERROR: libc::c_uint = 0; -pub const MAILIMAP_MBX_LIST_OFLAG_FLAG_EXT: libc::c_uint = 2; -pub const MAILIMAP_MBX_LIST_OFLAG_NOINFERIORS: libc::c_uint = 1; -pub const MAILIMAP_MBX_LIST_OFLAG_ERROR: libc::c_uint = 0; -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimap_mbx_list_oflag { - pub of_type: libc::c_int, - pub of_flag_ext: *mut libc::c_char, -} - -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimap_mailbox_list { - pub mb_flag: *mut mailimap_mbx_list_flags, - pub mb_delimiter: libc::c_char, - pub mb_name: *mut libc::c_char, -} - -#[derive(Copy, Clone)] -#[repr(C)] -pub struct mailimap_mbx_list_flags { - pub mbf_type: libc::c_int, - pub mbf_oflags: *mut clist, - pub mbf_sflag: libc::c_int, -} diff --git a/src/x.rs b/src/x.rs index bf4918069..9d74ddc11 100644 --- a/src/x.rs +++ b/src/x.rs @@ -1,5 +1,3 @@ -use libc; - use crate::dc_strbuilder::dc_strbuilder_t; use crate::types::*; @@ -13,7 +11,7 @@ pub use libc::{ }; extern "C" { - pub static mut _DefaultRuneLocale: _RuneLocale; + // pub static mut _DefaultRuneLocale: _RuneLocale; pub fn clock() -> libc::clock_t; pub fn qsort( @@ -55,483 +53,10 @@ extern "C" { _: *const libc::c_char, ) -> !; - // --charconv - - pub fn charconv( - tocode: *const libc::c_char, - fromcode: *const libc::c_char, - str: *const libc::c_char, - length: size_t, - result: *mut *mut libc::c_char, - ) -> libc::c_int; - pub fn charconv_buffer( - tocode: *const libc::c_char, - fromcode: *const libc::c_char, - str: *const libc::c_char, - length: size_t, - result: *mut *mut libc::c_char, - result_len: *mut size_t, - ) -> libc::c_int; - pub fn charconv_buffer_free(str: *mut libc::c_char); - - // -- libetpan Methods - - pub fn libetpan_get_version_major() -> libc::c_int; - pub fn libetpan_get_version_minor() -> libc::c_int; - pub fn gethostname(_: *mut libc::c_char, _: size_t) -> libc::c_int; - pub fn mailsmtp_socket_connect( - session: *mut mailsmtp, - server: *const libc::c_char, - port: uint16_t, - ) -> libc::c_int; - pub fn mailsmtp_socket_starttls(session: *mut mailsmtp) -> libc::c_int; - pub fn mailsmtp_ssl_connect( - session: *mut mailsmtp, - server: *const libc::c_char, - port: uint16_t, - ) -> libc::c_int; - pub fn mailsmtp_oauth2_authenticate( - session: *mut mailsmtp, - auth_user: *const libc::c_char, - access_token: *const libc::c_char, - ) -> libc::c_int; - pub fn mailsmtp_new( - progr_rate: size_t, - progr_fun: Option ()>, - ) -> *mut mailsmtp; - pub fn mailsmtp_free(session: *mut mailsmtp); - pub fn mailsmtp_set_timeout(session: *mut mailsmtp, timeout: time_t); - pub fn mailsmtp_auth( - session: *mut mailsmtp, - user: *const libc::c_char, - pass: *const libc::c_char, - ) -> libc::c_int; - pub fn mailsmtp_helo(session: *mut mailsmtp) -> libc::c_int; - pub fn mailsmtp_mail(session: *mut mailsmtp, from: *const libc::c_char) -> libc::c_int; - pub fn mailsmtp_rcpt(session: *mut mailsmtp, to: *const libc::c_char) -> libc::c_int; - pub fn mailsmtp_data(session: *mut mailsmtp) -> libc::c_int; - pub fn mailsmtp_data_message( - session: *mut mailsmtp, - message: *const libc::c_char, - size: size_t, - ) -> libc::c_int; - pub fn mailesmtp_ehlo(session: *mut mailsmtp) -> libc::c_int; - pub fn mailesmtp_mail( - session: *mut mailsmtp, - from: *const libc::c_char, - return_full: libc::c_int, - envid: *const libc::c_char, - ) -> libc::c_int; - pub fn mailesmtp_rcpt( - session: *mut mailsmtp, - to: *const libc::c_char, - notify: libc::c_int, - orcpt: *const libc::c_char, - ) -> libc::c_int; - pub fn mailsmtp_strerror(errnum: libc::c_int) -> *const libc::c_char; - pub fn mailesmtp_auth_sasl( - session: *mut mailsmtp, - auth_type: *const libc::c_char, - server_fqdn: *const libc::c_char, - local_ip_port: *const libc::c_char, - remote_ip_port: *const libc::c_char, - login: *const libc::c_char, - auth_name: *const libc::c_char, - password: *const libc::c_char, - realm: *const libc::c_char, - ) -> libc::c_int; - pub fn mailsmtp_set_progress_callback( - session: *mut mailsmtp, - progr_fun: Option ()>, - context: *mut libc::c_void, - ); - - pub fn mailmime_base64_body_parse( - message: *const libc::c_char, - length: size_t, - indx: *mut size_t, - result: *mut *mut libc::c_char, - result_len: *mut size_t, - ) -> libc::c_int; - pub fn mailimf_address_new( - ad_type: libc::c_int, - ad_mailbox: *mut mailimf_mailbox, - ad_group: *mut mailimf_group, - ) -> *mut mailimf_address; - pub fn mailimf_mailbox_new( - mb_display_name: *mut libc::c_char, - mb_addr_spec: *mut libc::c_char, - ) -> *mut mailimf_mailbox; - pub fn mailimf_field_new( - fld_type: libc::c_int, - fld_return_path: *mut mailimf_return, - fld_resent_date: *mut mailimf_orig_date, - fld_resent_from: *mut mailimf_from, - fld_resent_sender: *mut mailimf_sender, - fld_resent_to: *mut mailimf_to, - fld_resent_cc: *mut mailimf_cc, - fld_resent_bcc: *mut mailimf_bcc, - fld_resent_msg_id: *mut mailimf_message_id, - fld_orig_date: *mut mailimf_orig_date, - fld_from: *mut mailimf_from, - fld_sender: *mut mailimf_sender, - fld_reply_to: *mut mailimf_reply_to, - fld_to: *mut mailimf_to, - fld_cc: *mut mailimf_cc, - fld_bcc: *mut mailimf_bcc, - fld_message_id: *mut mailimf_message_id, - fld_in_reply_to: *mut mailimf_in_reply_to, - fld_references: *mut mailimf_references, - fld_subject: *mut mailimf_subject, - fld_comments: *mut mailimf_comments, - fld_keywords: *mut mailimf_keywords, - fld_optional_field: *mut mailimf_optional_field, - ) -> *mut mailimf_field; - pub fn mailimf_subject_new(sbj_value: *mut libc::c_char) -> *mut mailimf_subject; - pub fn mailimf_mailbox_list_new_empty() -> *mut mailimf_mailbox_list; - pub fn mailimf_mailbox_list_add( - mailbox_list: *mut mailimf_mailbox_list, - mb: *mut mailimf_mailbox, - ) -> libc::c_int; - pub fn mailimf_address_list_new_empty() -> *mut mailimf_address_list; - pub fn mailimf_address_list_add( - address_list: *mut mailimf_address_list, - addr: *mut mailimf_address, - ) -> libc::c_int; - pub fn mailimf_fields_add( - fields: *mut mailimf_fields, - field: *mut mailimf_field, - ) -> libc::c_int; - pub fn mailimf_fields_new_with_data_all( - date: *mut mailimf_date_time, - from: *mut mailimf_mailbox_list, - sender: *mut mailimf_mailbox, - reply_to: *mut mailimf_address_list, - to: *mut mailimf_address_list, - cc: *mut mailimf_address_list, - bcc: *mut mailimf_address_list, - message_id: *mut libc::c_char, - in_reply_to: *mut clist, - references: *mut clist, - subject: *mut libc::c_char, - ) -> *mut mailimf_fields; - pub fn mailimf_get_date(time_0: time_t) -> *mut mailimf_date_time; - pub fn mailimf_field_new_custom( - name: *mut libc::c_char, - value: *mut libc::c_char, - ) -> *mut mailimf_field; - pub fn mailmime_parameter_new( - pa_name: *mut libc::c_char, - pa_value: *mut libc::c_char, - ) -> *mut mailmime_parameter; - pub fn mailmime_free(mime: *mut mailmime); - pub fn mailmime_disposition_parm_new( - pa_type: libc::c_int, - pa_filename: *mut libc::c_char, - pa_creation_date: *mut libc::c_char, - pa_modification_date: *mut libc::c_char, - pa_read_date: *mut libc::c_char, - pa_size: size_t, - pa_parameter: *mut mailmime_parameter, - ) -> *mut mailmime_disposition_parm; - pub fn mailmime_new_message_data(msg_mime: *mut mailmime) -> *mut mailmime; - pub fn mailmime_new_empty( - content: *mut mailmime_content, - mime_fields: *mut mailmime_fields, - ) -> *mut mailmime; - pub fn mailmime_set_body_file( - build_info: *mut mailmime, - filename: *mut libc::c_char, - ) -> libc::c_int; - pub fn mailmime_set_body_text( - build_info: *mut mailmime, - data_str: *mut libc::c_char, - length: size_t, - ) -> libc::c_int; - pub fn mailmime_add_part(build_info: *mut mailmime, part: *mut mailmime) -> libc::c_int; - pub fn mailmime_set_imf_fields(build_info: *mut mailmime, fields: *mut mailimf_fields); - pub fn mailmime_smart_add_part(mime: *mut mailmime, mime_sub: *mut mailmime) -> libc::c_int; - pub fn mailmime_content_new_with_str(str: *const libc::c_char) -> *mut mailmime_content; - pub fn mailmime_fields_new_encoding(type_0: libc::c_int) -> *mut mailmime_fields; - pub fn mailmime_multiple_new(type_0: *const libc::c_char) -> *mut mailmime; - pub fn mailmime_fields_new_filename( - dsp_type: libc::c_int, - filename: *mut libc::c_char, - encoding_type: libc::c_int, - ) -> *mut mailmime_fields; - pub fn mailmime_param_new_with_data( - name: *mut libc::c_char, - value: *mut libc::c_char, - ) -> *mut mailmime_parameter; - pub fn mailmime_write_mem( - f: *mut MMAPString, - col: *mut libc::c_int, - build_info: *mut mailmime, - ) -> libc::c_int; - pub fn mailimf_fields_free(fields: *mut mailimf_fields); - pub fn mailimf_fields_new_empty() -> *mut mailimf_fields; - pub fn mailimf_envelope_and_optional_fields_parse( - message: *const libc::c_char, - length: size_t, - indx: *mut size_t, - result: *mut *mut mailimf_fields, - ) -> libc::c_int; - pub fn mailmime_content_free(content: *mut mailmime_content); - pub fn mailmime_mechanism_new( - enc_type: libc::c_int, - enc_token: *mut libc::c_char, - ) -> *mut mailmime_mechanism; - pub fn mailmime_mechanism_free(mechanism: *mut mailmime_mechanism); - pub fn mailmime_fields_free(fields: *mut mailmime_fields); - pub fn mailmime_new( - mm_type: libc::c_int, - mm_mime_start: *const libc::c_char, - mm_length: size_t, - mm_mime_fields: *mut mailmime_fields, - mm_content_type: *mut mailmime_content, - mm_body: *mut mailmime_data, - mm_preamble: *mut mailmime_data, - mm_epilogue: *mut mailmime_data, - mm_mp_list: *mut clist, - mm_fields: *mut mailimf_fields, - mm_msg_mime: *mut mailmime, - ) -> *mut mailmime; - pub fn mailmime_fields_new_empty() -> *mut mailmime_fields; - pub fn mailmime_fields_new_with_data( - encoding: *mut mailmime_mechanism, - id: *mut libc::c_char, - description: *mut libc::c_char, - disposition: *mut mailmime_disposition, - language: *mut mailmime_language, - ) -> *mut mailmime_fields; - pub fn mailmime_get_content_message() -> *mut mailmime_content; - pub fn mailmime_parse( - message: *const libc::c_char, - length: size_t, - indx: *mut size_t, - result: *mut *mut mailmime, - ) -> libc::c_int; - pub fn mailmime_part_parse( - message: *const libc::c_char, - length: size_t, - indx: *mut size_t, - encoding: libc::c_int, - result: *mut *mut libc::c_char, - result_len: *mut size_t, - ) -> libc::c_int; - pub fn mailmime_substitute(old_mime: *mut mailmime, new_mime: *mut mailmime) -> libc::c_int; - pub fn mailprivacy_prepare_mime(mime: *mut mailmime); - pub fn mailmime_encoded_phrase_parse( - default_fromcode: *const libc::c_char, - message: *const libc::c_char, - length: size_t, - indx: *mut size_t, - tocode: *const libc::c_char, - result: *mut *mut libc::c_char, - ) -> libc::c_int; - pub fn mailimap_date_time_new( - dt_day: libc::c_int, - dt_month: libc::c_int, - dt_year: libc::c_int, - dt_hour: libc::c_int, - dt_min: libc::c_int, - dt_sec: libc::c_int, - dt_zone: libc::c_int, - ) -> *mut mailimap_date_time; - pub fn mailimap_xlist( - session: *mut mailimap, - mb: *const libc::c_char, - list_mb: *const libc::c_char, - result: *mut *mut clist, - ) -> libc::c_int; - pub fn mailimap_create(session: *mut mailimap, mb: *const libc::c_char) -> libc::c_int; - pub fn mailimap_list( - session: *mut mailimap, - mb: *const libc::c_char, - list_mb: *const libc::c_char, - result: *mut *mut clist, - ) -> libc::c_int; - pub fn mailimap_list_result_free(list: *mut clist); - pub fn mailimap_subscribe(session: *mut mailimap, mb: *const libc::c_char) -> libc::c_int; - pub fn mailstream_close(s: *mut mailstream) -> libc::c_int; - pub fn mailstream_wait_idle(s: *mut mailstream, max_idle_delay: libc::c_int) -> libc::c_int; - pub fn mailstream_setup_idle(s: *mut mailstream) -> libc::c_int; - pub fn mailstream_unsetup_idle(s: *mut mailstream); - pub fn mailstream_interrupt_idle(s: *mut mailstream); - pub fn mailimap_section_new(sec_spec: *mut mailimap_section_spec) -> *mut mailimap_section; - pub fn mailimap_set_free(set: *mut mailimap_set); - pub fn mailimap_fetch_type_free(fetch_type: *mut mailimap_fetch_type); - pub fn mailimap_store_att_flags_free(store_att_flags: *mut mailimap_store_att_flags); - pub fn mailimap_set_new_interval(first: uint32_t, last: uint32_t) -> *mut mailimap_set; - pub fn mailimap_set_new_single(indx: uint32_t) -> *mut mailimap_set; - pub fn mailimap_fetch_att_new_envelope() -> *mut mailimap_fetch_att; - pub fn mailimap_fetch_att_new_flags() -> *mut mailimap_fetch_att; - pub fn mailimap_fetch_att_new_uid() -> *mut mailimap_fetch_att; - pub fn mailimap_fetch_att_new_body_peek_section( - section: *mut mailimap_section, - ) -> *mut mailimap_fetch_att; - pub fn mailimap_fetch_type_new_fetch_att_list_empty() -> *mut mailimap_fetch_type; - pub fn mailimap_fetch_type_new_fetch_att_list_add( - fetch_type: *mut mailimap_fetch_type, - fetch_att: *mut mailimap_fetch_att, - ) -> libc::c_int; - pub fn mailimap_store_att_flags_new_add_flags( - flags: *mut mailimap_flag_list, - ) -> *mut mailimap_store_att_flags; - pub fn mailimap_flag_list_new_empty() -> *mut mailimap_flag_list; - pub fn mailimap_flag_list_add( - flag_list: *mut mailimap_flag_list, - f: *mut mailimap_flag, - ) -> libc::c_int; - pub fn mailimap_flag_new_deleted() -> *mut mailimap_flag; - pub fn mailimap_flag_new_seen() -> *mut mailimap_flag; - pub fn mailimap_flag_new_flag_keyword(flag_keyword: *mut libc::c_char) -> *mut mailimap_flag; - pub fn mailimap_socket_connect( - f: *mut mailimap, - server: *const libc::c_char, - port: uint16_t, - ) -> libc::c_int; - pub fn mailimap_socket_starttls(f: *mut mailimap) -> libc::c_int; - pub fn mailimap_ssl_connect( - f: *mut mailimap, - server: *const libc::c_char, - port: uint16_t, - ) -> libc::c_int; - pub fn mailimap_uidplus_uid_copy( - session: *mut mailimap, - set: *mut mailimap_set, - mb: *const libc::c_char, - uidvalidity_result: *mut uint32_t, - source_result: *mut *mut mailimap_set, - dest_result: *mut *mut mailimap_set, - ) -> libc::c_int; - pub fn mailimap_uidplus_uid_move( - session: *mut mailimap, - set: *mut mailimap_set, - mb: *const libc::c_char, - uidvalidity_result: *mut uint32_t, - source_result: *mut *mut mailimap_set, - dest_result: *mut *mut mailimap_set, - ) -> 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_oauth2_authenticate( - session: *mut mailimap, - auth_user: *const libc::c_char, - access_token: *const libc::c_char, - ) -> libc::c_int; - pub fn mailimap_close(session: *mut mailimap) -> libc::c_int; - pub fn mailimap_fetch( - session: *mut mailimap, - set: *mut mailimap_set, - fetch_type: *mut mailimap_fetch_type, - result: *mut *mut clist, - ) -> libc::c_int; - pub fn mailimap_uid_fetch( - session: *mut mailimap, - set: *mut mailimap_set, - fetch_type: *mut mailimap_fetch_type, - result: *mut *mut clist, - ) -> libc::c_int; - pub fn mailimap_fetch_list_free(fetch_list: *mut clist); - pub fn mailimap_login( - session: *mut mailimap, - userid: *const libc::c_char, - password: *const libc::c_char, - ) -> libc::c_int; - pub fn mailimap_select(session: *mut mailimap, mb: *const libc::c_char) -> libc::c_int; - pub fn mailimap_uid_store( - session: *mut mailimap, - set: *mut mailimap_set, - store_att_flags: *mut mailimap_store_att_flags, - ) -> libc::c_int; - pub fn mailimap_new( - imap_progr_rate: size_t, - imap_progr_fun: Option ()>, - ) -> *mut mailimap; - pub fn mailimap_free(session: *mut mailimap); - pub fn mailimap_set_timeout(session: *mut mailimap, timeout: time_t); - pub fn mailimf_msg_id_parse( - message: *const libc::c_char, - length: size_t, - indx: *mut size_t, - result: *mut *mut libc::c_char, - ) -> libc::c_int; - pub fn mailimf_mailbox_list_free(mb_list: *mut mailimf_mailbox_list); - pub fn mailimf_mailbox_list_parse( - message: *const libc::c_char, - length: size_t, - indx: *mut size_t, - result: *mut *mut mailimf_mailbox_list, - ) -> libc::c_int; - pub fn mailmime_content_charset_get(content: *mut mailmime_content) -> *mut libc::c_char; - - pub fn carray_new(initsize: libc::c_uint) -> *mut carray; - pub fn carray_add( - array: *mut carray, - data: *mut libc::c_void, - indx: *mut libc::c_uint, - ) -> libc::c_int; - pub fn carray_set_size(array: *mut carray, new_size: libc::c_uint); - pub fn carray_free(array: *mut carray); - pub fn carray_delete_slow(array: *mut carray, indx: libc::c_uint) -> libc::c_int; - - pub fn mmap_string_unref(str: *mut libc::c_char) -> libc::c_int; - pub fn mmap_string_new(init: *const libc::c_char) -> *mut MMAPString; - pub fn mmap_string_free(string: *mut MMAPString); - pub fn mmap_string_append(string: *mut MMAPString, val: *const libc::c_char) - -> *mut MMAPString; - pub fn mmap_string_append_len( - string: *mut MMAPString, - val: *const libc::c_char, - len: size_t, - ) -> *mut MMAPString; - pub fn mmap_string_append_c(string: *mut MMAPString, c: libc::c_char) -> *mut MMAPString; - - pub fn clist_free(_: *mut clist); - pub fn clist_insert_after( - _: *mut clist, - _: *mut clistiter, - _: *mut libc::c_void, - ) -> libc::c_int; - pub fn clist_new() -> *mut clist; - pub fn clist_delete(_: *mut clist, _: *mut clistiter) -> *mut clistiter; - - pub fn encode_base64(in_0: *const libc::c_char, len: libc::c_int) -> *mut libc::c_char; - // -- DC Methods pub fn dc_strbuilder_catf(_: *mut dc_strbuilder_t, format: *const libc::c_char, _: ...); pub fn dc_mprintf(format: *const libc::c_char, _: ...) -> *mut libc::c_char; - - // -- Pthread - - pub fn pthread_create( - _: *mut pthread_t, - _: *const pthread_attr_t, - _: Option *mut libc::c_void>, - _: *mut libc::c_void, - ) -> libc::c_int; - pub fn pthread_join(_: pthread_t, _: *mut *mut libc::c_void) -> libc::c_int; - pub fn pthread_cond_signal(_: *mut pthread_cond_t) -> libc::c_int; - pub fn pthread_cond_timedwait( - _: *mut pthread_cond_t, - _: *mut pthread_mutex_t, - _: *const timespec, - ) -> libc::c_int; - pub fn pthread_mutex_lock(_: *mut pthread_mutex_t) -> libc::c_int; - pub fn pthread_mutex_unlock(_: *mut pthread_mutex_t) -> libc::c_int; - pub fn pthread_cond_destroy(_: *mut pthread_cond_t) -> libc::c_int; - pub fn pthread_cond_init(_: *mut pthread_cond_t, _: *const pthread_condattr_t) -> libc::c_int; - pub fn pthread_cond_wait(_: *mut pthread_cond_t, _: *mut pthread_mutex_t) -> libc::c_int; - pub fn pthread_mutex_destroy(_: *mut pthread_mutex_t) -> libc::c_int; - pub fn pthread_mutex_init( - _: *mut pthread_mutex_t, - _: *const pthread_mutexattr_t, - ) -> libc::c_int; - pub fn pthread_self() -> pthread_t; } #[cfg(not(target_os = "macos"))] diff --git a/examples/repl/stress.rs b/tests/stress.rs similarity index 94% rename from examples/repl/stress.rs rename to tests/stress.rs index 11140e3ab..82d7c8155 100644 --- a/examples/repl/stress.rs +++ b/tests/stress.rs @@ -1,46 +1,35 @@ //! Stress some functions for testing; if used as a lib, this file is obsolete. +use std::ffi::{CStr, CString}; + +use mmime::mailimf_types::*; +use mmime::mailmime_content::*; +use mmime::mailmime_types::*; +use mmime::other::*; +use tempfile::tempdir; + +use deltachat::constants::*; use deltachat::dc_aheader::*; -use deltachat::dc_apeerstate::*; use deltachat::dc_array::*; -use deltachat::dc_chat::*; -use deltachat::dc_chatlist::*; use deltachat::dc_configure::*; use deltachat::dc_contact::*; use deltachat::dc_context::*; -use deltachat::dc_dehtml::*; -use deltachat::dc_e2ee::*; use deltachat::dc_hash::*; -use deltachat::dc_imap::*; use deltachat::dc_imex::*; -use deltachat::dc_job::*; -use deltachat::dc_jobthread::*; -use deltachat::dc_jsmn::*; use deltachat::dc_key::*; -use deltachat::dc_keyhistory::*; use deltachat::dc_keyring::*; use deltachat::dc_location::*; -use deltachat::dc_log::*; -use deltachat::dc_loginparam::*; use deltachat::dc_lot::*; -use deltachat::dc_mimefactory::*; use deltachat::dc_mimeparser::*; -use deltachat::dc_move::*; use deltachat::dc_msg::*; -use deltachat::dc_oauth2::*; use deltachat::dc_param::*; use deltachat::dc_pgp::*; use deltachat::dc_qr::*; -use deltachat::dc_receive_imf::*; use deltachat::dc_saxparser::*; use deltachat::dc_securejoin::*; use deltachat::dc_simplify::*; -use deltachat::dc_smtp::*; -use deltachat::dc_sqlite3::*; -use deltachat::dc_stock::*; use deltachat::dc_strbuilder::*; use deltachat::dc_strencode::*; -use deltachat::dc_token::*; use deltachat::dc_tools::*; use deltachat::types::*; use deltachat::x::*; @@ -48,15 +37,15 @@ use libc; /* some data used for testing ******************************************************************************/ -/* s_em_setupfile is a AES-256 symm. encrypted setup message created by Enigmail -with an "encrypted session key", see RFC 4880. The code is in s_em_setupcode */ -static mut s_em_setupcode: *const libc::c_char = +/* S_EM_SETUPFILE is a AES-256 symm. encrypted setup message created by Enigmail +with an "encrypted session key", see RFC 4880. The code is in S_EM_SETUPCODE */ +static mut S_EM_SETUPCODE: *const libc::c_char = b"1742-0185-6197-1303-7016-8412-3581-4441-0597\x00" as *const u8 as *const libc::c_char; -static mut s_em_setupfile: *const libc::c_char = +static mut S_EM_SETUPFILE: *const libc::c_char = b"-----BEGIN PGP MESSAGE-----\nPassphrase-Format: numeric9x4\nPassphrase-Begin: 17\n\nwy4ECQMI0jNRBQfVKHVg1+a2Yihd6JAjR9H0kk3oDVeX7nc4Oi+IjEtonUJt\nPQpO0tPWASWYuYvjZSuTz9r1yZYV+y4mu9bu9NEQoRlWg2wnbjoUoKk4emFF\nFweUj84iI6VWTCSRyMu5d5JS1RfOdX4CG/muLAegyIHezqYOEC0Z3b9Ci9rd\nDiSgqqN+/LDkUR/vr7L2CSLN5suBP9Hsz75AtaV8DJ2DYDywYX89yH1CfL1O\nWohyrJPdmGJZfdvQX0LI9mzN7MH0W6vUJeCaUpujc+UkLiOM6TDB74rmYF+V\nZ7K9BXbaN4V6dyxVZfgpXUoZlaNpvqPJXuLHJ68umkuIgIyQvzmMj3mFgZ8s\nakCt6Cf3o5O9n2PJvX89vuNnDGJrO5booEqGaBJfwUk0Rwb0gWsm5U0gceUz\ndce8KZK15CzX+bNv5OC+8jjjBw7mBHVt+2q8LI+G9fEy9NIREkp5/v2ZRN0G\nR6lpZwW+8TkMvJnriQeABqDpxsJVT6ENYAhkPG3AZCr/whGBU3EbDzPexXkz\nqt8Pdu5DrazLSFtjpjkekrjCh43vHjGl8IOiWxKQx0VfBkHJ7O9CsHmb0r1o\nF++fMh0bH1/aewmlg5wd0ixwZoP1o79he8Q4kfATZAjvB1xSLyMma+jxW5uu\nU3wYUOsUmYmzo46/QzizFCUpaTJ4ZQZY1/4sflidsl/XgZ0fD1NCrdkWBNA1\n0tQF949pEAeA4hSfHfQDNKAY8A7fk8lZblqWPkyu/0x8eV537QOhs89ZvhSB\nV87KEAwxWt60+Eolf8PvvkvB/AKlfWq4MYShgyldwwCfkED3rv2mvTsdqfvW\nWvqZNo4eRkJrnv9Be3LaXoFyY6a3z+ObBIkKI+u5azGJYge97O4E2DrUEKdQ\ncScq5upzXity0E+Yhm964jzBzxnA52S4RoXzkjTxH+AHjQ5+MHQxmRfMd2ly\n7skM106weVOR0JgOdkvfiOFDTHZLIVCzVyYVlOUJYYwPhmM1426zbegHNkaM\nM2WgvjMp5G+X9qfDWKecntQJTziyDFZKfd1UrUCPHrvl1Ac9cuqgcCXLtdUS\njI+e1Y9fXvgyvHiMX0ztSz1yfvnRt34508G9j68fEQFQR/VIepULB5/SqKbq\np2flgJL48kY32hEw2GRPri64Tv3vMPIWa//zvQDhQPmcd3S4TqnTIIKUoTAO\nNUo6GS9UAX12fdSFPZINcAkNIaB69+iwGyuJE4FLHKVkqNnNmDwF3fl0Oczo\nhbboWzA3GlpR2Ri6kfe0SocfGR0CHT5ZmqI6es8hWx+RN8hpXcsRxGS0BMi2\nmcJ7fPY+bKastnEeatP+b0XN/eaJAPZPZSF8PuPeQ0Uc735fylPrrgtWK9Gp\nWq0DPaWV/+O94OB/JvWT5wq7d/EEVbTck5FPl4gdv3HHpaaQ6/8G89wVMEXA\nGUxB8WuvNeHAtQ7qXF7TkaZvUpF0rb1aV88uABOOPpsfAyWJo/PExCZacg8R\nGOQYI6inV5HcGUw06yDSqArHZmONveqjbDBApenearcskv6Uz7q+Bp60GGSA\nlvU3C3RyP/OUc1azOp72MIe0+JvP8S5DN9/Ltc/5ZyZHOjLoG+npIXnThYwV\n0kkrlsi/7loCzvhcWOac1vrSaGVCfifkYf+LUFQFrFVbxKLOQ6vTsYZWM0yM\nQsMMywW5A6CdROT5UB0UKRh/S1cwCwrN5UFTRt2UpDF3wSBAcChsHyy90RAL\nXd4+ZIyf29GIFuwwQyzGBWnXQ2ytU4kg/D5XSqJbJJTya386UuyQpnFjI19R\nuuD0mvEfFvojCKDJDWguUNtWsHSg01NXDSrY26BhlOkMpUrzPfX5r0FQpgDS\nzOdY9SIG+y9MKG+4nwmYnFM6V5NxVL+6XZ7BQTvlLIcIIu+BujVNWteDnWNZ\nT1UukCGmFd8sNZpCc3wu4o/gLDQxih/545tWMf0dmeUfYhKcjSX9uucMRZHT\n1N0FINw04fDdp2LccL+WCGatFGnkZVPw3asid4d1od9RG9DbNRBJEp/QeNhc\n/peJCPLGYlA1NjTEq+MVB+DHdGNOuy//be3KhedBr6x4VVaDzL6jyHu/a7PR\nBWRVtI1CIVDxyrEXucHdGQoEm7p+0G2zouOe/oxbPFoEYrjaI+0e/FN3u/Y3\naG0dlYWbxeHMqTh2F3lB/CFALReeGqqN6PwRyePWKaVctZYb6ydf9JVl6q1/\naV9C5rf9eFGqqA+OIx/+XuAG1w0rwlznvtajHzCoUeA4QfbmuOV/t5drWN2N\nPCk2mJlcSmd7lx53rnOIgme1hggchjezc4TisL4PvSLxjJ7DxzktD2jv2I/Q\nOlSxTUaXnGfIVedsI0WjFomz5w9tZjC0B5O5TpSRRz6gfpe/OC3kV7qs1YCS\nlJTTxj1mTs6wqt0WjKkN/Ke0Cm5r7NQ79szDNlcC0AViEOQb3U1R88nNdiVx\nymKT5Dl+yM6acv53lNX6O5BH+mpP2/pCpi3x+kYFyr4cUsNgVVGlhmkPWctZ\ntrHvO7wcLrAsrLNqRxt1G3DLjQt9VY+w5qOPJv6s9qd5JBL/qtH5zqIXiXlM\nIWI9LLwHFFXqjk/f6G4LyOeHB9AqccGQ4IztgzTKmYEmFWVIpTO4UN6+E7yQ\ngtcYSIUEJo824ht5rL+ODqmCSAWsWIomEoTPvgn9QqO0YRwAEMpsFtE17klS\nqjbYyV7Y5A0jpCvqbnGmZPqCgzjjN/p5VKSNjSdM0vdwBRgpXlyooXg/EGoJ\nZTZH8nLSuYMMu7AK8c7DKJ1AocTNYHRe9xFV8RzEiIm3zaezxa0r+Fo3nuTX\nUR9DOH0EHaDLrFQcfS5y1iRxY9CHg0N2ECaUzr/H7jck9mLZ7v9xisj3QDuv\ni0xQbC4BTxMEBGTK8fOcjHHOABOyhqotOreERqwOV2c1OOGUQE8QK18zJCUd\nBTmQZ709ttASD7VWK4TraOGczZXkZsKdZko5T6+6EkFy9H+gwENLUG9zk0x9\n2G5zicDr6PDoAGDuoB3B3VA8ertXTX7zEz30N6m+tcAtPWka0owokLy3f0o7\nZdytBPkly8foTMWKF2vsJ8K4Xdn/57jJ2qFku32xmtiPIoa6s8wINO06AVB0\n0/AuttvxcPr+ycE+9wRZHx6JBujAqOZztU3zu8WZMaqVKb7gnmkWPiL+1XFp\n2+mr0AghScIvjzTDEjigDtLydURJrW01wXjaR0ByBT4z8ZjaNmQAxIPOIRFC\nbD0mviaoX61qgQLmSc6mzVlzzNZRCKtSvvGEK5NJ6CB6g2EeFau8+w0Zd+vv\n/iv6Img3pUBgvpMaIsxRXvGZwmo2R0tztJt+CqHRvyTWjQL+CjIAWyoHEdVH\nk7ne/q9zo3iIMsQUO7tVYtgURpRYc2OM1IVQtrgbmbYGEdOrhMjaWULg9C7o\n6oDM0EFlCAId3P8ykXQNMluFKlf9il5nr19B/qf/wh6C7DFLOmnjTWDXrEiP\n6wFEWTeUWLchGlbpiJFEu05MWPIRoRd3BHQvVpzLLgeBdxMVW7D6WCK+KJxI\nW1rOKhhLVvKU3BrFgr12A4uQm+6w1j33Feh68Y0JB7GLDBBGe11QtLCD6kz5\nRzFl+GbgiwpHi3nlCc5yiNwyPq/JRxU3GRb62YJcsSQBg+CD3Mk5FGiDcuvp\nkZXOcTE2FAnUDigjEs+oH2qkhD4/5CiHkrfFJTzv+wqw+jwxPor2jkZH2akN\n6PssXQYupXJE3NmcyaYT+b5E6qbkIyQj7CknkiqmrqrmxkOQxA+Ab2Vy9zrW\nu0+Wvf+C+SebWTo3qfJZQ3KcASZHa5AGoSHetWzH2fNLIHfULXac/T++1DWE\nnbeNvhXiFmAJ+BRsZj9p6RcnSamk4bjAbX1lg2G3Sq6MiA1fIRSMlSjuDLrQ\n8xfVFrg7gfBIIQPErJWv2GdAsz76sLxuSXQLKYpFnozvMT7xRs84+iRNWWh9\nSNibbEjlh0DcJlKw49Eis/bN22sDQWy4awHuRvvQetk/QCgp54epuqWnbxoE\nXZDgGBBkMc3or+6Cxr3q9x7J/oHLvPb+Q5yVP9fyz6ZiSVWluMefA9smjJ/A\nKMD84s7uO/8/4yug+swXGrcBjHSddTcy05vm+7X6o9IEZKZb5tz7VqAfEcuk\nQNPUWCMudhzxSNr4+yVXRVpcjsjKtplJcXC5aIuJwq3C5OdysCGqXWjLuUu1\nOFSoPvTsYC2VxYdFUcczeHEFTxXoXz3I0TyLPyxUNsJiKpUGt/SXmV/IyAx+\nh6pZ2OUXspC9d78DdiHZtItPjEGiIb678ZyMxWPE59XQd/ad92mlPHU8InXD\nyTq6otZ7LwAOLGbDR9bqN7oX8PCHRwuu30hk2b4+WkZn/WLd2KCPddQswZJg\nQgi5ajUaFhZvxF5YNTqIzzYVh7Y8fFMfzH9AO+SJqy+0ECX0GwtHHeVsXYNb\nP/NO/ma4MI8301JyipPmdtzvvt9NOD/PJcnZH2KmDquARXMO/vKbn3rNUXog\npTFqqyNTr4L5FK86QPEoE4hDy9ItHGlEuiNVD+5suGVGUgYfV7AvZU46EeqO\nrfFj8wNSX1aK/pIwWmh1EkygPSxomWRUANLX1jO6zX9wk2X80Xn9q/8jot1k\nVl54OOd7cvGls2wKkEZi5h3p6KKZHJ+WIDBQupeJbuma1GK8wAiwjDH59Y0X\nwXHAk7XA+t4u0dgRpZbUUMqQmvEvfJaCr4qMlpuGdEYbbpIMUB1qCfYU9taL\nzbepMIT+XYD5mTyytZhR+zrsfpt1EzbrhuabqPioySoIS/1+bWfxvndq16r0\nAdNxR5LiVSVh8QJr3B/HJhVghgSVrrynniG3E94abNWL/GNxPS/dTHSf8ass\nvbv7+uznADzHsMiG/ZlLAEkQJ9j0ENJvHmnayeVFIXDV6jPCcQJ+rURDgl7z\n/qTLfe3o3zBMG78LcB+xDNXTQrK5Z0LX7h17hLSElpiUghFa9nviCsT0nkcr\nnz302P4IOFwJuYMMCEfW+ywTn+CHpKjLHWkZSZ4q6LzNTbbgXZn/vh7njNf0\nQHaHmaMNxnDhUw/Bl13uM52qtsfEYK07SEhLFlJbAk0G7q+OabK8dJxCRwS3\nX9k4juzLUYhX8XBovg9G3YEVckb6iM8/LF/yvNXbUsPrdhYU9lPA63xD0Pgb\nzthZCLIlnF+lS6e41WJv3n1dc4dFWD7F5tmt/7uwLC6oUGYsccSzY+bUkYhL\ndp7tlQRd5AG/Xz8XilORk8cUjvi6uZss5LyQpKvGSU+77C8ZV/oS62BdS5TE\nosBTrO2/9FGzQtHT+8DJSTPPgR6rcQUWLPemiG09ACKfRQ/g3b9Qj0upOcKL\n6dti0lq7Aorc39vV18DPMFBOwzchUEBlBFyuSa4AoD30tsoilAC3qbzBwu3z\nQLjmst76HEcWDkxgDAhlBz6/XgiVZsCivn7ygigmc2+hNEzIdDsKKfM9bkoe\n3uJzmmsv8Bh5ZEtfGoGNmu/zA7tgvTOCBeotYeHr2O6pLmYb3hK+E/qCBl14\n8pK4qYrjAlF+ZMq9BzXcaz5mRfKVfAQtghHOaNqopBczSE1bjFF6HaNhIaGa\nN8YdabNQG7mLI/fgBxJfkPl6HdIhEpctp4RURbSFhW+wn0o85VyHM6a+6Vgj\nNrYmhxPZ6N1KN0Qy76aNiw7nAToRRcOv87uZnkDIeVH8mP/0hldyiy/Y97cG\nQgOeQHOG27QW57nHhqLRqvf0zzQZekuXWFbqajpaabEcdGXyiUpJ8/ZopBPM\nAJwfkyA2LkV946IA4JV6sPnu9pYzpXQ4vdQKJ6DoDUyRTQmgmfSFGtfHAozY\nV9k0iQeetSkYYtOagTrg3t92v7M00o/NJW/rKX4jj2djD8wtBovOcv4kxg4Z\no58Iv94ROim48XfyesvSYKN1xqqbXH4sfE6b4b9pLUxQVOmWANLK9MK8D+Ci\nIvrGbz5U5bZP6vlNbe9bYzjvWTPjaMrjXknRTBcikavqOfDTSIVFtT4qvhvK\n42PpOrm0qdiLwExGKQ9FfEfYZRgEcYRGg7rH3oNz6ZNOEXppF3tCl9yVOlFb\nygdIeT3Z3HeOQbAsi8jK7o16DSXL7ZOpFq9Bv9yzusrF7Eht/fSEpAVUO3D1\nIuqjZcsQRhMtIvnF0oFujFtooJx9x3dj/RarvEGX/NzwATZkgJ+yWs2etruA\nEzMQqED4j7Lb790zEWnt+nuHdCdlPnNy8RG5u5X62p3h5KqUbg9HfmIuuESi\nhwr6dKsVQGc5XUB5KTt0dtjWlK5iaetDsZFuF5+aE0Xa6PmiQ2e7ZPFyxXmO\nT/PSHzobx0qClKCu+tSWA1HDSL08IeoGZEyyhoaxyn5D9r1Mqg101v/iu59r\nlRRs+plAhbuq5aQA3WKtF1N6Zb5+AVRpNUyrxyHoH36ddR4/n7lnIld3STGD\nRqZLrOuKHS3dCNW2Pt15lU+loYsWFZwC6T/tAbvwhax+XaBMiKQSDFmG9sBw\nTiM1JWXhq2IsjXBvCl6k2AKWLQOvc/Hin+oYs4d7M9mi0vdoEOAMadU/+Pqn\nuZzP941mOUV5UeTCCbjpyfI7qtIi3TH1cQmC2kG2HrvQYuM6Momp//JusH1+\n9eHgFo25HbitcKJ1sAqxsnYIW5/jIVyIJC7tatxmNfFQQ/LUb2cT+Jowwsf4\nbbPinA9S6aQFy9k3vk07V2ouYl+cpMMXmNAUrboFRLxw7QDapWYMKdmnbU5O\nHZuDz3iyrm0lMPsRtt/f5WUhZYY4vXT5/dj+8P6Pr5fdc4S84i5qEzf7bX/I\nSc6fpISdYBscfHdv6uXsEVtVPKEuQVYwhyc4kkwVKjZBaqsgjAA7VEhQXzO3\nrC7di4UhabWQCQTG1GYZyrj4bm6dg/32uVxMoLS5kuSpi3nMz5JmQahLqRxh\nargg13K2/MJ7w2AI23gCvO5bEmD1ZXIi1aGYdZfu7+KqrTumYxj0KgIesgU0\n6ekmPh4Zu5lIyKopa89nfQVj3uKbwr9LLHegfzeMhvI5WQWghKcNcXEvJwSA\nvEik5aXm2qSKXT+ijXBy5MuNeICoGaQ5WA0OJ30Oh5dN0XpLtFUWHZKThJvR\nmngm1QCMMw2v/j8=\n=9sJE\n-----END PGP MESSAGE-----\n\x00" as *const u8 as *const libc::c_char; -#[no_mangle] -pub unsafe extern "C" fn stress_functions(mut context: *mut dc_context_t) { + +unsafe extern "C" fn stress_functions(context: &dc_context_t) { let mut saxparser: dc_saxparser_t = dc_saxparser_t { starttag_cb: None, endtag_cb: None, @@ -73,20 +62,20 @@ pub unsafe extern "C" fn stress_functions(mut context: *mut dc_context_t) { b"\r\n\r\n\r\rline2\n\r\x00" as *const u8 as *const libc::c_char; let mut plain: *mut libc::c_char = dc_simplify_simplify(simplify, html, strlen(html) as libc::c_int, 1i32, 0i32); - // FIXME - // assert_eq!( - // strcmp(plain, b"line1\nline2\x00" as *const u8 as *const libc::c_char), - // 0, - // "{:?}", - // std::ffi::CStr::from_ptr(plain), - // ); - // free(plain as *mut libc::c_void); + assert_eq!( + CStr::from_ptr(plain as *const libc::c_char) + .to_str() + .unwrap(), + "line1\nline2", + ); + free(plain as *mut libc::c_void); + html = b"text\n\n\n2019-03-06T21:09:57Z9.423110,53.790302\n\n \n\t2018-12-13T22:11:12Z\t 19.423110 \t , \n 63.790302\n \n\n\x00" as *const u8 as *const libc::c_char; - let mut kml: *mut dc_kml_t = dc_kml_parse(context, xml, strlen(xml)); + let kml: *mut dc_kml_t = dc_kml_parse(context, xml, strlen(xml)); if 0 != !(!(*kml).addr.is_null() && strcmp( (*kml).addr, @@ -352,18 +341,18 @@ pub unsafe extern "C" fn stress_functions(mut context: *mut dc_context_t) { ); } else { }; - let mut absPath: *mut libc::c_char = dc_mprintf( + let 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, absPath)) as libc::c_int as libc::c_long { + if 0 != (0 == dc_is_blobdir_path(context, abs_path)) as libc::c_int as libc::c_long { __assert_rtn( (*::std::mem::transmute::<&[u8; 17], &[libc::c_char; 17]>(b"stress_functions\x00")) .as_ptr(), b"../cmdline/stress.c\x00" as *const u8 as *const libc::c_char, 242i32, - b"dc_is_blobdir_path(context, absPath)\x00" as *const u8 as *const libc::c_char, + b"dc_is_blobdir_path(context, abs_path)\x00" as *const u8 as *const libc::c_char, ); } else { }; @@ -399,17 +388,17 @@ pub unsafe extern "C" fn stress_functions(mut context: *mut dc_context_t) { ); } else { }; - if 0 != (0 == dc_file_exist(context, absPath)) as libc::c_int as libc::c_long { + if 0 != (0 == dc_file_exist(context, abs_path)) as libc::c_int as libc::c_long { __assert_rtn( (*::std::mem::transmute::<&[u8; 17], &[libc::c_char; 17]>(b"stress_functions\x00")) .as_ptr(), b"../cmdline/stress.c\x00" as *const u8 as *const libc::c_char, 245i32, - b"dc_file_exist(context, absPath)\x00" as *const u8 as *const libc::c_char, + b"dc_file_exist(context, abs_path)\x00" as *const u8 as *const libc::c_char, ); } else { }; - free(absPath as *mut libc::c_void); + free(abs_path as *mut libc::c_void); if 0 != (0 == dc_copy_file( context, @@ -442,50 +431,25 @@ pub unsafe extern "C" fn stress_functions(mut context: *mut dc_context_t) { ); } else { }; + let mut buf: *mut libc::c_void = 0 as *mut libc::c_void; let mut buf_bytes: size_t = 0; - if 0 != (0 - == dc_read_file( + + assert_eq!( + dc_read_file( context, b"$BLOBDIR/dada\x00" as *const u8 as *const libc::c_char, &mut buf, &mut buf_bytes, - )) as libc::c_int as libc::c_long - { - __assert_rtn( - (*::std::mem::transmute::<&[u8; 17], &[libc::c_char; 17]>(b"stress_functions\x00")) - .as_ptr(), - b"../cmdline/stress.c\x00" as *const u8 as *const libc::c_char, - 253i32, - b"dc_read_file(context, \"$BLOBDIR/dada\", &buf, &buf_bytes)\x00" as *const u8 - as *const libc::c_char, - ); - } else { - }; - if 0 != !(buf_bytes == 7) as libc::c_int as libc::c_long { - __assert_rtn( - (*::std::mem::transmute::<&[u8; 17], &[libc::c_char; 17]>(b"stress_functions\x00")) - .as_ptr(), - b"../cmdline/stress.c\x00" as *const u8 as *const libc::c_char, - 254i32, - b"buf_bytes==7\x00" as *const u8 as *const libc::c_char, - ); - } else { - }; - if 0 != !(strcmp( - buf as *const libc::c_char, - b"content\x00" as *const u8 as *const libc::c_char, - ) == 0i32) as libc::c_int as libc::c_long - { - __assert_rtn( - (*::std::mem::transmute::<&[u8; 17], &[libc::c_char; 17]>(b"stress_functions\x00")) - .as_ptr(), - b"../cmdline/stress.c\x00" as *const u8 as *const libc::c_char, - 255i32, - b"strcmp(buf, \"content\")==0\x00" as *const u8 as *const libc::c_char, - ); - } else { - }; + ), + 1 + ); + assert_eq!(buf_bytes, 7); + assert_eq!( + std::str::from_utf8(std::slice::from_raw_parts(buf as *const u8, buf_bytes)).unwrap(), + "content" + ); + free(buf); if 0 != (0 == dc_delete_file( @@ -567,7 +531,7 @@ pub unsafe extern "C" fn stress_functions(mut context: *mut dc_context_t) { ); } else { }; - let mut fn0: *mut libc::c_char = dc_get_fine_pathNfilename( + let fn0: *mut libc::c_char = dc_get_fine_pathNfilename( context, b"$BLOBDIR\x00" as *const u8 as *const libc::c_char, b"foobar.dadada\x00" as *const u8 as *const libc::c_char, @@ -603,7 +567,7 @@ pub unsafe extern "C" fn stress_functions(mut context: *mut dc_context_t) { b"content\x00" as *const u8 as *const libc::c_char as *const libc::c_void, 7i32 as size_t, ); - let mut fn1: *mut libc::c_char = dc_get_fine_pathNfilename( + let fn1: *mut libc::c_char = dc_get_fine_pathNfilename( context, b"$BLOBDIR\x00" as *const u8 as *const libc::c_char, b"foobar.dadada\x00" as *const u8 as *const libc::c_char, @@ -646,7 +610,7 @@ pub unsafe extern "C" fn stress_functions(mut context: *mut dc_context_t) { free(fn0 as *mut libc::c_void); free(fn1 as *mut libc::c_void); } - let mut txt: *const libc::c_char = + let txt: *const libc::c_char = b"FieldA: ValueA\nFieldB: ValueB\n\x00" as *const u8 as *const libc::c_char; let mut mime: *mut mailmime = 0 as *mut mailmime; let mut dummy: size_t = 0i32 as size_t; @@ -673,7 +637,7 @@ pub unsafe extern "C" fn stress_functions(mut context: *mut dc_context_t) { ); } else { }; - let mut fields: *mut mailimf_fields = mailmime_find_mailimf_fields(mime); + let fields: *mut mailimf_fields = mailmime_find_mailimf_fields(mime); if 0 != fields.is_null() as libc::c_int as libc::c_long { __assert_rtn( (*::std::mem::transmute::<&[u8; 17], &[libc::c_char; 17]>(b"stress_functions\x00")) @@ -763,7 +727,7 @@ pub unsafe extern "C" fn stress_functions(mut context: *mut dc_context_t) { ); } else { }; - let mut of_b: *mut mailimf_optional_field = + let of_b: *mut mailimf_optional_field = mailimf_find_optional_field(fields, b"FieldB\x00" as *const u8 as *const libc::c_char); if 0 != !(!of_b.is_null() && !(*of_b).fld_value.is_null()) as libc::c_int as libc::c_long { __assert_rtn( @@ -790,8 +754,8 @@ pub unsafe extern "C" fn stress_functions(mut context: *mut dc_context_t) { } else { }; mailmime_free(mime); - let mut mimeparser: *mut dc_mimeparser_t = dc_mimeparser_new((*context).blobdir, context); - let mut raw: *const libc::c_char = + let mimeparser: *mut dc_mimeparser_t = dc_mimeparser_new(context.get_blobdir(), context); + let 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; dc_mimeparser_parse(mimeparser, raw, strlen(raw)); @@ -943,7 +907,7 @@ pub unsafe extern "C" fn stress_functions(mut context: *mut dc_context_t) { ); } else { }; - let mut f: libc::c_double = dc_atof(b"1.23\x00" as *const u8 as *const libc::c_char); + let f: libc::c_double = dc_atof(b"1.23\x00" as *const u8 as *const libc::c_char); if 0 != !(f > 1.22f64 && f < 1.24f64) as libc::c_int as libc::c_long { __assert_rtn( (*::std::mem::transmute::<&[u8; 17], &[libc::c_char; 17]>(b"stress_functions\x00")) @@ -954,7 +918,7 @@ pub unsafe extern "C" fn stress_functions(mut context: *mut dc_context_t) { ); } else { }; - let mut s: *mut libc::c_char = dc_ftoa(1.23f64); + let s: *mut libc::c_char = dc_ftoa(1.23f64); if 0 != !(dc_atof(s) > 1.22f64 && dc_atof(s) < 1.24f64) as libc::c_int as libc::c_long { __assert_rtn( (*::std::mem::transmute::<&[u8; 17], &[libc::c_char; 17]>(b"stress_functions\x00")) @@ -1121,7 +1085,7 @@ pub unsafe extern "C" fn stress_functions(mut context: *mut dc_context_t) { } else { }; let mut str: *mut libc::c_char = strdup(b"aaa\x00" as *const u8 as *const libc::c_char); - let mut replacements: libc::c_int = dc_str_replace( + let replacements: libc::c_int = dc_str_replace( &mut str, b"a\x00" as *const u8 as *const libc::c_char, b"ab\x00" as *const u8 as *const libc::c_char, @@ -2445,7 +2409,7 @@ pub unsafe extern "C" fn stress_functions(mut context: *mut dc_context_t) { ); } else { }; - let mut arr: *mut dc_array_t = dc_array_new(0 as *mut dc_context_t, 7i32 as size_t); + let arr = dc_array_new(7i32 as size_t); if 0 != !(dc_array_get_cnt(arr) == 0) as libc::c_int as libc::c_long { __assert_rtn( (*::std::mem::transmute::<&[u8; 17], &[libc::c_char; 17]>(b"stress_functions\x00")) @@ -2457,7 +2421,6 @@ pub unsafe extern "C" fn stress_functions(mut context: *mut dc_context_t) { } else { }; let mut i: libc::c_int = 0; - i = 0i32; while i < 1000i32 { dc_array_add_id(arr, (i + 1i32 * 2i32) as uint32_t); i += 1 @@ -2673,7 +2636,7 @@ pub unsafe extern "C" fn stress_functions(mut context: *mut dc_context_t) { } else { }; dc_array_unref(arr); - let mut p1: *mut dc_param_t = dc_param_new(); + let p1: *mut dc_param_t = dc_param_new(); dc_param_set_packed( p1, b"\r\n\r\na=1\nb=2\n\nc = 3 \x00" as *const u8 as *const libc::c_char, @@ -2752,40 +2715,28 @@ pub unsafe extern "C" fn stress_functions(mut context: *mut dc_context_t) { ); } else { }; + dc_param_set(p1, 'b' as i32, 0 as *const libc::c_char); - // FIXME - // if 0 != !(strcmp( - // (*p1).packed, - // b"a=foo\nd=4\x00" as *const u8 as *const libc::c_char, - // ) == 0i32) as libc::c_int as libc::c_long - // { - // println!("{:?}", std::ffi::CStr::from_ptr((*p1).packed)); - // __assert_rtn( - // (*::std::mem::transmute::<&[u8; 17], &[libc::c_char; 17]>(b"stress_functions\x00")) - // .as_ptr(), - // b"../cmdline/stress.c\x00" as *const u8 as *const libc::c_char, - // 706i32, - // b"strcmp(p1->packed, \"a=foo\\nd=4\")==0\x00" as *const u8 as *const libc::c_char, - // ); - // } else { - // }; + + assert_eq!( + CStr::from_ptr((*p1).packed as *const libc::c_char) + .to_str() + .unwrap(), + "a=foo\nd=4", + ); + dc_param_set(p1, 'a' as i32, 0 as *const libc::c_char); dc_param_set(p1, 'd' as i32, 0 as *const libc::c_char); - // FIXME - // if 0 != !(strcmp((*p1).packed, b"\x00" as *const u8 as *const libc::c_char) == 0i32) - // as libc::c_int as libc::c_long - // { - // __assert_rtn( - // (*::std::mem::transmute::<&[u8; 17], &[libc::c_char; 17]>(b"stress_functions\x00")) - // .as_ptr(), - // b"../cmdline/stress.c\x00" as *const u8 as *const libc::c_char, - // 710i32, - // b"strcmp(p1->packed, \"\")==0\x00" as *const u8 as *const libc::c_char, - // ); - // } else { - // }; + assert_eq!( + CStr::from_ptr((*p1).packed as *const libc::c_char) + .to_str() + .unwrap(), + "", + ); + dc_param_unref(p1); + let mut keys: *mut libc::c_char = dc_get_config( context, b"sys.config_keys\x00" as *const u8 as *const libc::c_char, @@ -3224,14 +3175,11 @@ pub unsafe extern "C" fn stress_functions(mut context: *mut dc_context_t) { } else { }; free(keys as *mut libc::c_void); - let mut ah: *mut dc_aheader_t = dc_aheader_new(); - let mut rendered: *mut libc::c_char = 0 as *mut libc::c_char; - let mut ah_ok: libc::c_int = 0; - ah_ok = dc_aheader_set_from_string( - ah, - b"addr=a@b.example.org; prefer-encrypt=mutual; keydata=RGVsdGEgQ2hhdA==\x00" as *const u8 - as *const libc::c_char, - ); + let ah: *mut dc_aheader_t = dc_aheader_new(); + let rendered: *mut libc::c_char; + let mut ah_ok: libc::c_int; + let fixed_header = b"addr=a@b.example.org; prefer-encrypt=mutual; keydata= xsBNBFzG3j0BCAC6iNhT8zydvCXi8LI/gFnkadMbfmSE/rTJskRRra/utGbLyDta/yTrJgWL7O3y/g 4HdDW/dN2z26Y6W13IMzx9gLInn1KQZChtqWAcr/ReUucXcymwcfg1mdkBGk3TSLeLihN6CJx8Wsv8 ig+kgAzte4f5rqEEAJVQ9WZHuti7UiYs6oRzqTo06CRe9owVXxzdMf0VDQtf7ZFm9dpzKKbhH7Lu88 80iiotQ9/yRCkDGp9fNThsrLdZiK6OIAcIBAqi2rI89aS1dAmnRbktQieCx5izzyYkR1KvVL3gTTll HOzfKVEC2asmtWu2e4se/+O4WMIS1eGrn7GeWVb0Vwc5ABEBAAHNETxhQEBiLmV4YW1wbGUuZGU+ws CJBBABCAAzAhkBBQJcxt5FAhsDBAsJCAcGFQgJCgsCAxYCARYhBI4xxYKBgH3ANh5cufaKrc9mtiML AAoJEPaKrc9mtiML938H/18F+3Wf9/JaAy/8hCO1v4S2PVBhxaKCokaNFtkfaMRne2l087LscCFPiF Nyb4mv6Z3YeK8Xpxlp2sI0ecvdiqLUOGfnxS6tQrj+83EjtIrZ/hXOk1h121QFWH9Zg2VNHtODXjAg dLDC0NWUrclR0ZOqEDQHeo0ibTILdokVfXFN25wakPmGaYJP2y729cb1ve7RzvIvwn+Dddfxo3ao72 rBfLi7l4NQ4S0KsY4cw+/6l5bRCKYCP77wZtvCwUvfVVosLdT43agtSiBI49+ayqvZ8OCvSJa61i+v 81brTiEy9GBod4eAp45Ibsuemkw+gon4ZOvUXHTjwFB+h63MrozOwE0EXMbePQEIAL/vauf1zK8JgC u3V+G+SOX0iWw5xUlCPX+ERpBbWfwu3uAqn4wYXD3JDE/fVAF668xiV4eTPtlSUd5h0mn+G7uXMMOt kb+20SoEt50f8zw8TrL9t+ZsV11GKZWJpCar5AhXWsn6EEi8I2hLL5vn55ZZmHuGgN4jjmkRl3ToKC LhaXwTBjCJem7N5EH7F75wErEITa55v4Lb4Nfca7vnvtYrI1OA446xa8gHra0SINelTD09/JM/Fw4s WVPBaRZmJK/Tnu79N23No9XBUubmFPv1pNexZsQclicnTpt/BEWhiun7d6lfGB63K1aoHRTR1pcrWv BuALuuz0gqar2zlI0AEQEAAcLAdgQYAQgAIAUCXMbeRQIbDBYhBI4xxYKBgH3ANh5cufaKrc9mtiML AAoJEPaKrc9mtiMLKSEIAIyLCRO2OyZ0IYRvRPpMn4p7E+7Pfcz/0mSkOy+1hshgJnqivXurm8zwGr wdMqeV4eslKR9H1RUdWGUQJNbtwmmjrt5DHpIhYHl5t3FpCBaGbV20Omo00Q38lBl9MtrmZkZw+ktE k6X+0xCKssMF+2MADkSOIufbR5HrDVB89VZOHCO9DeXvCUUAw2hyJiL/LHmLzJ40zYoTmb+F//f0k0 j+tRdbkefyRoCmwG7YGiT+2hnCdgcezswnzah5J3ZKlrg7jOGo1LxtbvNUzxNBbC6S/aNgwm6qxo7x egRhmEl5uZ16zwyj4qz+xkjGy25Of5mWfUDoNw7OT7sjUbHOOMc="; + ah_ok = dc_aheader_set_from_string(ah, fixed_header as *const u8 as *const libc::c_char); if 0 != !(ah_ok == 1i32) as libc::c_int as libc::c_long { __assert_rtn( (*::std::mem::transmute::<&[u8; 17], &[libc::c_char; 17]>(b"stress_functions\x00")) @@ -3258,21 +3206,9 @@ pub unsafe extern "C" fn stress_functions(mut context: *mut dc_context_t) { ); } else { }; - if 0 != !((*(*ah).public_key).bytes == 10i32 - && strncmp( - (*(*ah).public_key).binary as *mut libc::c_char, - b"Delta Chat\x00" as *const u8 as *const libc::c_char, - 10, - ) == 0i32) as libc::c_int as libc::c_long - { - __assert_rtn((*::std::mem::transmute::<&[u8; 17], - &[libc::c_char; 17]>(b"stress_functions\x00")).as_ptr(), - b"../cmdline/stress.c\x00" as *const u8 as - *const libc::c_char, 771i32, - b"ah->public_key->bytes==10 && strncmp((char*)ah->public_key->binary, \"Delta Chat\", 10)==0\x00" - as *const u8 as *const libc::c_char); - } else { - }; + + assert_eq!((*(*ah).public_key).bytes, 1212); + if 0 != !((*ah).prefer_encrypt == 1i32) as libc::c_int as libc::c_long { __assert_rtn( (*::std::mem::transmute::<&[u8; 17], &[libc::c_char; 17]>(b"stress_functions\x00")) @@ -3283,22 +3219,15 @@ pub unsafe extern "C" fn stress_functions(mut context: *mut dc_context_t) { ); } else { }; + rendered = dc_aheader_render(ah); - if 0 != !(!rendered.is_null() - && strcmp( - rendered, - b"addr=a@b.example.org; prefer-encrypt=mutual; keydata= RGVsdGEgQ2hhdA==\x00" - as *const u8 as *const libc::c_char, - ) == 0i32) as libc::c_int as libc::c_long - { - __assert_rtn((*::std::mem::transmute::<&[u8; 17], - &[libc::c_char; 17]>(b"stress_functions\x00")).as_ptr(), - b"../cmdline/stress.c\x00" as *const u8 as - *const libc::c_char, 775i32, - b"rendered && strcmp(rendered, \"addr=a@b.example.org; prefer-encrypt=mutual; keydata= RGVsdGEgQ2hhdA==\")==0\x00" - as *const u8 as *const libc::c_char); - } else { - }; + + assert!(!rendered.is_null()); + assert_eq!( + std::ffi::CStr::from_ptr(rendered).to_str().unwrap(), + std::str::from_utf8(fixed_header).unwrap() + ); + ah_ok = dc_aheader_set_from_string(ah, b" _foo; __FOO=BAR ;;; addr = a@b.example.org ;\r\n prefer-encrypt = mutual ; keydata = RG VsdGEgQ\r\n2hhdA==\x00" @@ -3329,6 +3258,7 @@ pub unsafe extern "C" fn stress_functions(mut context: *mut dc_context_t) { ); } else { }; + if 0 != !((*(*ah).public_key).bytes == 10i32 && strncmp( (*(*ah).public_key).binary as *mut libc::c_char, @@ -3455,8 +3385,8 @@ pub unsafe extern "C" fn stress_functions(mut context: *mut dc_context_t) { }; dc_aheader_unref(ah); free(rendered as *mut libc::c_void); - let mut ok: libc::c_int = 0; - let mut buf_0: *mut libc::c_char = 0 as *mut libc::c_char; + let mut ok: libc::c_int; + let mut buf_0: *mut libc::c_char; let mut headerline: *const libc::c_char = 0 as *const libc::c_char; let mut setupcodebegin: *const libc::c_char = 0 as *const libc::c_char; let mut preferencrypt: *const libc::c_char = 0 as *const libc::c_char; @@ -3498,21 +3428,17 @@ pub unsafe extern "C" fn stress_functions(mut context: *mut dc_context_t) { ); } else { }; - // FIXME - // if 0 != !(!base64.is_null() - // && strcmp(base64, b"data\x00" as *const u8 as *const libc::c_char) == 0i32) - // as libc::c_int as libc::c_long - // { - // __assert_rtn( - // (*::std::mem::transmute::<&[u8; 17], &[libc::c_char; 17]>(b"stress_functions\x00")) - // .as_ptr(), - // b"../cmdline/stress.c\x00" as *const u8 as *const libc::c_char, - // 823i32, - // b"base64 && strcmp(base64, \"data\") == 0\x00" as *const u8 as *const libc::c_char, - // ); - // } else { - // }; + + assert!(!base64.is_null()); + assert_eq!( + CStr::from_ptr(base64 as *const libc::c_char) + .to_str() + .unwrap(), + "data", + ); + free(buf_0 as *mut libc::c_void); + buf_0 = strdup(b"-----BEGIN PGP MESSAGE-----\n\ndat1\n-----END PGP MESSAGE-----\n-----BEGIN PGP MESSAGE-----\n\ndat2\n-----END PGP MESSAGE-----\x00" as *const u8 as *const libc::c_char); @@ -3550,21 +3476,16 @@ pub unsafe extern "C" fn stress_functions(mut context: *mut dc_context_t) { } else { }; - // FIXME - // if 0 != !(!base64.is_null() - // && strcmp(base64, b"dat1\x00" as *const u8 as *const libc::c_char) == 0i32) - // as libc::c_int as libc::c_long - // { - // __assert_rtn( - // (*::std::mem::transmute::<&[u8; 17], &[libc::c_char; 17]>(b"stress_functions\x00")) - // .as_ptr(), - // b"../cmdline/stress.c\x00" as *const u8 as *const libc::c_char, - // 830i32, - // b"base64 && strcmp(base64, \"dat1\") == 0\x00" as *const u8 as *const libc::c_char, - // ); - // } else { - // }; + assert!(!base64.is_null()); + assert_eq!( + CStr::from_ptr(base64 as *const libc::c_char) + .to_str() + .unwrap(), + "dat1", + ); + free(buf_0 as *mut libc::c_void); + buf_0 = strdup( b"foo \n -----BEGIN PGP MESSAGE----- \n base64-123 \n -----END PGP MESSAGE-----\x00" as *const u8 as *const libc::c_char, @@ -3613,23 +3534,16 @@ pub unsafe extern "C" fn stress_functions(mut context: *mut dc_context_t) { } else { }; - // FIXME - // if 0 != !(!base64.is_null() - // && strcmp( - // base64, - // b"base64-123\x00" as *const u8 as *const libc::c_char, - // ) == 0i32) as libc::c_int as libc::c_long - // { - // __assert_rtn( - // (*::std::mem::transmute::<&[u8; 17], &[libc::c_char; 17]>(b"stress_functions\x00")) - // .as_ptr(), - // b"../cmdline/stress.c\x00" as *const u8 as *const libc::c_char, - // 838i32, - // b"base64 && strcmp(base64, \"base64-123\")==0\x00" as *const u8 as *const libc::c_char, - // ); - // } else { - // }; + assert!(!base64.is_null()); + assert_eq!( + CStr::from_ptr(base64 as *const libc::c_char) + .to_str() + .unwrap(), + "base64-123", + ); + free(buf_0 as *mut libc::c_void); + buf_0 = strdup(b"foo-----BEGIN PGP MESSAGE-----\x00" as *const u8 as *const libc::c_char); ok = dc_split_armored_data( buf_0, @@ -3702,24 +3616,16 @@ pub unsafe extern "C" fn stress_functions(mut context: *mut dc_context_t) { } else { }; - // FIXME - // if 0 != !(!base64.is_null() - // && strcmp( - // base64, - // b"base64-567 \n abc\x00" as *const u8 as *const libc::c_char, - // ) == 0i32) as libc::c_int as libc::c_long - // { - // __assert_rtn( - // (*::std::mem::transmute::<&[u8; 17], &[libc::c_char; 17]>(b"stress_functions\x00")) - // .as_ptr(), - // b"../cmdline/stress.c\x00" as *const u8 as *const libc::c_char, - // 851i32, - // b"base64 && strcmp(base64, \"base64-567 \\n abc\")==0\x00" as *const u8 - // as *const libc::c_char, - // ); - // } else { - // }; + assert!(!base64.is_null()); + assert_eq!( + CStr::from_ptr(base64 as *const libc::c_char) + .to_str() + .unwrap(), + "base64-567 \n abc", + ); + free(buf_0 as *mut libc::c_void); + buf_0 = strdup(b"-----BEGIN PGP PRIVATE KEY BLOCK-----\n Autocrypt-Prefer-Encrypt : mutual \n\nbase64\n-----END PGP PRIVATE KEY BLOCK-----\x00" as *const u8 as *const libc::c_char); @@ -3773,21 +3679,16 @@ pub unsafe extern "C" fn stress_functions(mut context: *mut dc_context_t) { } else { }; - // FIXME - // if 0 != !(!base64.is_null() - // && strcmp(base64, b"base64\x00" as *const u8 as *const libc::c_char) == 0i32) - // as libc::c_int as libc::c_long - // { - // __assert_rtn( - // (*::std::mem::transmute::<&[u8; 17], &[libc::c_char; 17]>(b"stress_functions\x00")) - // .as_ptr(), - // b"../cmdline/stress.c\x00" as *const u8 as *const libc::c_char, - // 859i32, - // b"base64 && strcmp(base64, \"base64\")==0\x00" as *const u8 as *const libc::c_char, - // ); - // } else { - // }; + assert!(!base64.is_null()); + assert_eq!( + CStr::from_ptr(base64 as *const libc::c_char) + .to_str() + .unwrap(), + "base64", + ); + free(buf_0 as *mut libc::c_void); + let mut norm: *mut libc::c_char = dc_normalize_setup_code( context, b"123422343234423452346234723482349234\x00" as *const u8 as *const libc::c_char, @@ -3849,11 +3750,11 @@ pub unsafe extern "C" fn stress_functions(mut context: *mut dc_context_t) { } else { }; free(norm as *mut libc::c_void); - let mut buf_1: *mut libc::c_char = 0 as *mut libc::c_char; + let mut buf_1: *mut libc::c_char; let mut headerline_0: *const libc::c_char = 0 as *const libc::c_char; let mut setupcodebegin_0: *const libc::c_char = 0 as *const libc::c_char; let mut preferencrypt_0: *const libc::c_char = 0 as *const libc::c_char; - buf_1 = strdup(s_em_setupfile); + buf_1 = strdup(S_EM_SETUPFILE); if 0 != (0 == dc_split_armored_data( buf_1, @@ -3890,8 +3791,8 @@ pub unsafe extern "C" fn stress_functions(mut context: *mut dc_context_t) { } else { }; if 0 != !(!setupcodebegin_0.is_null() - && strlen(setupcodebegin_0) < strlen(s_em_setupcode) - && strncmp(setupcodebegin_0, s_em_setupcode, strlen(setupcodebegin_0)) == 0i32) + && strlen(setupcodebegin_0) < strlen(S_EM_SETUPCODE) + && strncmp(setupcodebegin_0, S_EM_SETUPCODE, strlen(setupcodebegin_0)) == 0i32) as libc::c_int as libc::c_long { __assert_rtn((*::std::mem::transmute::<&[u8; 17], @@ -3913,7 +3814,7 @@ pub unsafe extern "C" fn stress_functions(mut context: *mut dc_context_t) { } else { }; free(buf_1 as *mut libc::c_void); - buf_1 = dc_decrypt_setup_file(context, s_em_setupcode, s_em_setupfile); + buf_1 = dc_decrypt_setup_file(context, S_EM_SETUPCODE, S_EM_SETUPFILE); if 0 != buf_1.is_null() as libc::c_int as libc::c_long { __assert_rtn( (*::std::mem::transmute::<&[u8; 17], &[libc::c_char; 17]>(b"stress_functions\x00")) @@ -3988,8 +3889,8 @@ pub unsafe extern "C" fn stress_functions(mut context: *mut dc_context_t) { }; free(buf_1 as *mut libc::c_void); if 0 != dc_is_configured(context) { - let mut setupcode: *mut libc::c_char = 0 as *mut libc::c_char; - let mut setupfile: *mut libc::c_char = 0 as *mut libc::c_char; + let setupcode: *mut libc::c_char; + let setupfile: *mut libc::c_char; setupcode = dc_create_setup_code(context); if 0 != setupcode.is_null() as libc::c_int as libc::c_long { __assert_rtn( @@ -4042,7 +3943,7 @@ pub unsafe extern "C" fn stress_functions(mut context: *mut dc_context_t) { ); } else { }; - let mut buf_2: *mut libc::c_char = dc_strdup(setupfile); + let buf_2: *mut libc::c_char = dc_strdup(setupfile); let mut headerline_1: *const libc::c_char = 0 as *const libc::c_char; let mut setupcodebegin_1: *const libc::c_char = 0 as *const libc::c_char; if 0 != (0 @@ -4094,7 +3995,7 @@ pub unsafe extern "C" fn stress_functions(mut context: *mut dc_context_t) { } else { }; free(buf_2 as *mut libc::c_void); - let mut payload: *mut libc::c_char = 0 as *mut libc::c_char; + let payload: *mut libc::c_char; let mut headerline_2: *const libc::c_char = 0 as *const libc::c_char; payload = dc_decrypt_setup_file(context, setupcode, setupfile); if 0 != payload.is_null() as libc::c_int as libc::c_long { @@ -4145,7 +4046,7 @@ pub unsafe extern "C" fn stress_functions(mut context: *mut dc_context_t) { free(setupfile as *mut libc::c_void); free(setupcode as *mut libc::c_void); } - let mut bad_key: *mut dc_key_t = dc_key_new(); + let bad_key: *mut dc_key_t = dc_key_new(); let mut bad_data: [libc::c_uchar; 4096] = [0; 4096]; let mut i_0: libc::c_int = 0i32; while i_0 < 4096i32 { @@ -4174,8 +4075,8 @@ pub unsafe extern "C" fn stress_functions(mut context: *mut dc_context_t) { j += 1 } dc_key_unref(bad_key); - let mut public_key: *mut dc_key_t = dc_key_new(); - let mut private_key: *mut dc_key_t = dc_key_new(); + let public_key: *mut dc_key_t = dc_key_new(); + let private_key: *mut dc_key_t = dc_key_new(); dc_pgp_create_keypair( context, b"foo@bar.de\x00" as *const u8 as *const libc::c_char, @@ -4202,7 +4103,7 @@ pub unsafe extern "C" fn stress_functions(mut context: *mut dc_context_t) { ); } else { }; - let mut test_key: *mut dc_key_t = dc_key_new(); + let test_key: *mut dc_key_t = dc_key_new(); if 0 != (0 == dc_pgp_split_key(context, private_key, test_key)) as libc::c_int as libc::c_long { __assert_rtn( (*::std::mem::transmute::<&[u8; 17], &[libc::c_char; 17]>(b"stress_functions\x00")) @@ -4215,8 +4116,8 @@ pub unsafe extern "C" fn stress_functions(mut context: *mut dc_context_t) { } else { }; dc_key_unref(test_key); - let mut public_key2: *mut dc_key_t = dc_key_new(); - let mut private_key2: *mut dc_key_t = dc_key_new(); + let public_key2: *mut dc_key_t = dc_key_new(); + let private_key2: *mut dc_key_t = dc_key_new(); dc_pgp_create_keypair( context, b"two@zwo.de\x00" as *const u8 as *const libc::c_char, @@ -4233,14 +4134,14 @@ pub unsafe extern "C" fn stress_functions(mut context: *mut dc_context_t) { ); } else { }; - let mut original_text: *const libc::c_char = + let original_text: *const libc::c_char = b"This is a test\x00" as *const u8 as *const libc::c_char; let mut ctext_signed: *mut libc::c_void = 0 as *mut libc::c_void; let mut ctext_unsigned: *mut libc::c_void = 0 as *mut libc::c_void; let mut ctext_signed_bytes: size_t = 0i32 as size_t; let mut ctext_unsigned_bytes: size_t = 0; let mut plain_bytes: size_t = 0i32 as size_t; - let mut keyring: *mut dc_keyring_t = dc_keyring_new(); + let keyring: *mut dc_keyring_t = dc_keyring_new(); dc_keyring_add(keyring, public_key); dc_keyring_add(keyring, public_key2); let mut ok_0: libc::c_int = dc_pgp_pk_encrypt( @@ -4345,11 +4246,11 @@ pub unsafe extern "C" fn stress_functions(mut context: *mut dc_context_t) { } else { }; dc_keyring_unref(keyring); - let mut keyring_0: *mut dc_keyring_t = dc_keyring_new(); + let keyring_0: *mut dc_keyring_t = dc_keyring_new(); dc_keyring_add(keyring_0, private_key); - let mut public_keyring: *mut dc_keyring_t = dc_keyring_new(); + let public_keyring: *mut dc_keyring_t = dc_keyring_new(); dc_keyring_add(public_keyring, public_key); - let mut public_keyring2: *mut dc_keyring_t = dc_keyring_new(); + let public_keyring2: *mut dc_keyring_t = dc_keyring_new(); dc_keyring_add(public_keyring2, public_key2); let mut plain_0: *mut libc::c_void = 0 as *mut libc::c_void; let mut valid_signatures: dc_hash_t = dc_hash_t { @@ -4361,7 +4262,7 @@ pub unsafe extern "C" fn stress_functions(mut context: *mut dc_context_t) { ht: 0 as *mut _ht, }; dc_hash_init(&mut valid_signatures, 3i32, 1i32); - let mut ok_1: libc::c_int = 0; + let mut ok_1: libc::c_int; ok_1 = dc_pgp_pk_decrypt( context, ctext_signed, @@ -4601,17 +4502,16 @@ pub unsafe extern "C" fn stress_functions(mut context: *mut dc_context_t) { } else { }; free(plain_0); - plain_0 = 0 as *mut libc::c_void; dc_hash_clear(&mut valid_signatures); dc_keyring_unref(keyring_0); dc_keyring_unref(public_keyring); dc_keyring_unref(public_keyring2); - let mut keyring_1: *mut dc_keyring_t = dc_keyring_new(); + let keyring_1: *mut dc_keyring_t = dc_keyring_new(); dc_keyring_add(keyring_1, private_key2); - let mut public_keyring_0: *mut dc_keyring_t = dc_keyring_new(); + let public_keyring_0: *mut dc_keyring_t = dc_keyring_new(); dc_keyring_add(public_keyring_0, public_key); let mut plain_1: *mut libc::c_void = 0 as *mut libc::c_void; - let mut ok_2: libc::c_int = dc_pgp_pk_decrypt( + let ok_2: libc::c_int = dc_pgp_pk_decrypt( context, ctext_signed, ctext_signed_bytes, @@ -4664,7 +4564,7 @@ pub unsafe extern "C" fn stress_functions(mut context: *mut dc_context_t) { dc_key_unref(private_key2); dc_key_unref(public_key); dc_key_unref(private_key); - let mut fingerprint: *mut libc::c_char = dc_normalize_fingerprint( + let fingerprint: *mut libc::c_char = dc_normalize_fingerprint( b" 1234 567890 \n AbcD abcdef ABCDEF \x00" as *const u8 as *const libc::c_char, ); if 0 != fingerprint.is_null() as libc::c_int as libc::c_long { @@ -4694,7 +4594,7 @@ pub unsafe extern "C" fn stress_functions(mut context: *mut dc_context_t) { }; free(fingerprint as *mut libc::c_void); if 0 != dc_is_configured(context) { - let mut qr: *mut libc::c_char = dc_get_securejoin_qr(context, 0i32 as uint32_t); + let qr: *mut libc::c_char = dc_get_securejoin_qr(context, 0i32 as uint32_t); if 0 != !(strlen(qr) > 55 && strncmp( qr, @@ -4776,3 +4676,31 @@ pub unsafe extern "C" fn stress_functions(mut context: *mut dc_context_t) { dc_lot_unref(res); }; } + +unsafe extern "C" fn cb( + _context: &dc_context_t, + _event: Event, + _data1: uintptr_t, + _data2: uintptr_t, +) -> uintptr_t { + 0 +} + +#[test] +fn run_stress_tests() { + unsafe { + let mut ctx = dc_context_new(cb, std::ptr::null_mut(), std::ptr::null_mut()); + let dir = tempdir().unwrap(); + let dbfile = CString::new(dir.path().join("db.sqlite").to_str().unwrap()).unwrap(); + assert_eq!( + dc_open(&mut ctx, dbfile.as_ptr(), std::ptr::null()), + 1, + "Failed to open {}", + CStr::from_ptr(dbfile.as_ptr() as *const libc::c_char) + .to_str() + .unwrap() + ); + + stress_functions(&ctx) + } +}