commit ff99e19972fc18e91647ef9d3d5d9e9b3b403f56 Author: dignifiedquire Date: Fri Apr 26 11:57:23 2019 +0300 inital commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..93b96d216 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +/target +**/*.rs.bk +Cargo.lock +*.db \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 000000000..60109286b --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "deltachat-core-rust" +version = "0.1.0" +authors = ["dignifiedquire "] +edition = "2018" + +[build-dependencies] +cc = "1.0.35" +pkg-config = "0.3" +bindgen = "0.49.0" + +[dependencies] +c2rust-bitfields = "0.1.0" +libc = "0.2.51" diff --git a/README.md b/README.md new file mode 100644 index 000000000..8e3e7a008 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +# Delta Chat Rust diff --git a/build.rs b/build.rs new file mode 100644 index 000000000..941eda770 --- /dev/null +++ b/build.rs @@ -0,0 +1,28 @@ +extern crate bindgen; +extern crate cc; + +fn main() { + let mut config = cc::Build::new(); + config.file("misc.h"); + config.file("misc.c"); + config.compile("libtools.a"); + + println!("cargo:rustc-link-search=native=/usr/local/opt/openssl/lib"); + + println!("cargo:rustc-link-lib=dylib=sasl2"); + println!("cargo:rustc-link-lib=dylib=ssl"); + println!("cargo:rustc-link-lib=dylib=sqlite3"); + println!("cargo:rustc-link-lib=dylib=pthread"); + println!("cargo:rustc-link-lib=dylib=rpgp"); + println!("cargo:rustc-link-lib=dylib=etpan"); + println!("cargo:rustc-link-lib=dylib=iconv"); + println!("cargo:rustc-link-lib=dylib=crypto"); + println!("cargo:rustc-link-lib=dylib=z"); + println!("cargo:rustc-link-lib=dylib=tools"); + + if std::env::var("TARGET").unwrap().contains("-apple") { + println!("cargo:rustc-link-lib=framework=CoreFoundation"); + println!("cargo:rustc-link-lib=framework=CoreServices"); + println!("cargo:rustc-link-lib=framework=Security"); + } +} diff --git a/misc.c b/misc.c new file mode 100644 index 000000000..7b4978126 --- /dev/null +++ b/misc.c @@ -0,0 +1,163 @@ +#include +#include +#include +#include +#include +#include "misc.h" + + +char* dc_strdup(const char* s) /* strdup(NULL) is undefined, save_strdup(NULL) returns an empty string in this case */ +{ + char* ret = NULL; + if (s) { + if ((ret=strdup(s))==NULL) { + exit(16); /* cannot allocate (little) memory, unrecoverable error */ + } + } + else { + if ((ret=(char*)calloc(1, 1))==NULL) { + exit(17); /* cannot allocate little memory, unrecoverable error */ + } + } + return ret; +} + +char* dc_mprintf(const char* format, ...) +{ + char testbuf[1]; + char* buf = NULL; + int char_cnt_without_zero = 0; + + va_list argp; + va_list argp_copy; + va_start(argp, format); + va_copy(argp_copy, argp); + + char_cnt_without_zero = vsnprintf(testbuf, 0, format, argp); + va_end(argp); + if (char_cnt_without_zero < 0) { + va_end(argp_copy); + return dc_strdup("ErrFmt"); + } + + buf = malloc(char_cnt_without_zero+2 /* +1 would be enough, however, protect against off-by-one-errors */); + if (buf==NULL) { + va_end(argp_copy); + return dc_strdup("ErrMem"); + } + + vsnprintf(buf, char_cnt_without_zero+1, format, argp_copy); + va_end(argp_copy); + return buf; + + #if 0 /* old implementation based upon sqlite3 */ + char *sqlite_str, *c_string; + + va_list argp; + va_start(argp, format); /* expects the last non-variable argument as the second parameter */ + sqlite_str = sqlite3_vmprintf(format, argp); + va_end(argp); + + if (sqlite_str==NULL) { + return dc_strdup("ErrFmt"); /* error - the result must be free()'d */ + } + + /* as sqlite-strings must be freed using sqlite3_free() instead of a simple free(), convert it to a normal c-string */ + c_string = dc_strdup(sqlite_str); /* exists on errors */ + sqlite3_free(sqlite_str); + return c_string; /* success - the result must be free()'d */ + #endif /* /old implementation based upon sqlite3 */ +} + + +/** + * Add a string to the end of the current string in a string-builder-object. + * The internal buffer is reallocated as needed. + * If reallocation fails, the program halts. + * + * @param strbuilder The object to initialze. Must be initialized with + * dc_strbuilder_init(). + * @param text Null-terminated string to add to the end of the string-builder-string. + * @return Returns a pointer to the copy of the given text. + * The returned pointer is a pointer inside dc_strbuilder_t::buf and MUST NOT + * be freed. If the string-builder was empty before, the returned + * pointer is equal to dc_strbuilder_t::buf. + * If the given text is NULL, NULL is returned and the string-builder-object is not modified. + */ +char* dc_strbuilder_cat(dc_strbuilder_t* strbuilder, const char* text) +{ + // this function MUST NOT call logging functions as it is used to output the log + if (strbuilder==NULL || text==NULL) { + return NULL; + } + + int len = strlen(text); + + if (len > strbuilder->free) { + int add_bytes = DC_MAX(len, strbuilder->allocated); + int old_offset = (int)(strbuilder->eos - strbuilder->buf); + + strbuilder->allocated = strbuilder->allocated + add_bytes; + strbuilder->buf = realloc(strbuilder->buf, strbuilder->allocated+add_bytes); + + if (strbuilder->buf==NULL) { + exit(39); + } + + strbuilder->free = strbuilder->free + add_bytes; + strbuilder->eos = strbuilder->buf + old_offset; + } + + char* ret = strbuilder->eos; + + strcpy(strbuilder->eos, text); + strbuilder->eos += len; + strbuilder->free -= len; + + return ret; +} + +/** + * Add a formatted string to a string-builder-object. + * This function is similar to dc_strbuilder_cat() but allows the same + * formatting options as eg. printf() + * + * @param strbuilder The object to initialze. Must be initialized with + * dc_strbuilder_init(). + * @param format The formatting string to add to the string-builder-object. + * This parameter may be followed by data to be inserted into the + * formatting string, see eg. printf() + * @return None. + */ +void dc_strbuilder_catf(dc_strbuilder_t* strbuilder, const char* format, ...) +{ + char testbuf[1]; + char* buf = NULL; + int char_cnt_without_zero = 0; + + va_list argp; + va_list argp_copy; + va_start(argp, format); + va_copy(argp_copy, argp); + + char_cnt_without_zero = vsnprintf(testbuf, 0, format, argp); + va_end(argp); + if (char_cnt_without_zero < 0) { + va_end(argp_copy); + dc_strbuilder_cat(strbuilder, "ErrFmt"); + return; + } + + buf = malloc(char_cnt_without_zero+2 /* +1 would be enough, however, protect against off-by-one-errors */); + if (buf==NULL) { + va_end(argp_copy); + dc_strbuilder_cat(strbuilder, "ErrMem"); + return; + } + + vsnprintf(buf, char_cnt_without_zero+1, format, argp_copy); + va_end(argp_copy); + + dc_strbuilder_cat(strbuilder, buf); + free(buf); +} diff --git a/misc.h b/misc.h new file mode 100644 index 000000000..5ef9d1c77 --- /dev/null +++ b/misc.h @@ -0,0 +1,23 @@ +#define DC_MAX(X, Y) (((X) > (Y))? (X) : (Y)) + +typedef struct _dc_strbuilder dc_strbuilder_t; + + +char* dc_mprintf (const char* format, ...); /* The result must be free()'d. */ +char* dc_strdup(const char* s); + + + +struct _dc_strbuilder +{ + char* buf; + int allocated; + int free; + char* eos; +}; + + +//void dc_strbuilder_init (dc_strbuilder_t*, int init_bytes); +char* dc_strbuilder_cat (dc_strbuilder_t*, const char* text); +void dc_strbuilder_catf (dc_strbuilder_t*, const char* format, ...); +//void dc_strbuilder_empty (dc_strbuilder_t*); diff --git a/src/dc_aheader.rs b/src/dc_aheader.rs new file mode 100644 index 000000000..6097bf7a5 --- /dev/null +++ b/src/dc_aheader.rs @@ -0,0 +1,524 @@ +use libc; +extern "C" { + #[no_mangle] + fn calloc(_: libc::c_ulong, _: libc::c_ulong) -> *mut libc::c_void; + #[no_mangle] + fn free(_: *mut libc::c_void); + #[no_mangle] + fn exit(_: libc::c_int) -> !; + #[no_mangle] + fn strcspn(_: *const libc::c_char, _: *const libc::c_char) -> libc::c_ulong; + #[no_mangle] + fn strspn(_: *const libc::c_char, _: *const libc::c_char) -> libc::c_ulong; + #[no_mangle] + fn strcasecmp(_: *const libc::c_char, _: *const libc::c_char) -> libc::c_int; + // handle contacts + #[no_mangle] + fn dc_may_be_valid_addr(addr: *const libc::c_char) -> libc::c_int; + /* string tools */ + #[no_mangle] + fn dc_strdup(_: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn dc_trim(_: *mut libc::c_char); + #[no_mangle] + fn dc_strbuilder_init(_: *mut dc_strbuilder_t, init_bytes: libc::c_int); + #[no_mangle] + fn dc_strbuilder_cat(_: *mut dc_strbuilder_t, text: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn dc_key_new() -> *mut dc_key_t; + #[no_mangle] + fn dc_key_unref(_: *mut dc_key_t); + #[no_mangle] + fn dc_key_set_from_base64( + _: *mut dc_key_t, + base64: *const libc::c_char, + type_0: libc::c_int, + ) -> libc::c_int; + #[no_mangle] + fn dc_key_render_base64( + _: *const dc_key_t, + break_every: libc::c_int, + break_chars: *const libc::c_char, + add_checksum: libc::c_int, + ) -> *mut libc::c_char; + // Working with e-mail-addresses + #[no_mangle] + fn dc_addr_cmp(addr1: *const libc::c_char, addr2: *const libc::c_char) -> libc::c_int; + #[no_mangle] + fn dc_addr_normalize(addr: *const libc::c_char) -> *mut libc::c_char; +} +#[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 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, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct mailimf_mailbox_list { + pub mb_list: *mut clist, +} +#[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_fields { + pub fld_list: *mut clist, +} +pub type unnamed = libc::c_uint; +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: unnamed_0, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed_0 { + 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, +} +#[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 _dc_strbuilder { + pub buf: *mut libc::c_char, + pub allocated: libc::c_int, + pub free: libc::c_int, + pub eos: *mut libc::c_char, +} +pub type dc_strbuilder_t = _dc_strbuilder; +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_key { + pub binary: *mut libc::c_void, + pub bytes: libc::c_int, + pub type_0: libc::c_int, + pub _m_heap_refcnt: libc::c_int, +} +pub type dc_key_t = _dc_key; +/* * + * @class dc_aheader_t + * Library-internal. Parse and create [Autocrypt-headers](https://autocrypt.org/en/latest/level1.html#the-autocrypt-header). + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_aheader { + pub addr: *mut libc::c_char, + pub public_key: *mut dc_key_t, + pub prefer_encrypt: libc::c_int, +} +pub type dc_aheader_t = _dc_aheader; +/* the returned pointer is ref'd and must be unref'd after usage */ +#[no_mangle] +pub unsafe extern "C" fn dc_aheader_new() -> *mut dc_aheader_t { + let mut aheader: *mut dc_aheader_t = 0 as *mut dc_aheader_t; + aheader = calloc( + 1i32 as libc::c_ulong, + ::std::mem::size_of::() as libc::c_ulong, + ) as *mut dc_aheader_t; + if aheader.is_null() { + exit(37i32); + } + (*aheader).public_key = dc_key_new(); + return aheader; +} +#[no_mangle] +pub unsafe extern "C" 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: *mut clistiter = 0 as *mut clistiter; + let mut fine_header: *mut dc_aheader_t = 0 as *mut dc_aheader_t; + if wanted_from.is_null() || header.is_null() { + return 0 as *mut dc_aheader_t; + } + cur = (*(*header).fld_list).first; + while !cur.is_null() { + let mut field: *mut mailimf_field = (if !cur.is_null() { + (*cur).data + } else { + 0 as *mut libc::c_void + }) as *mut mailimf_field; + if !field.is_null() && (*field).fld_type == MAILIMF_FIELD_OPTIONAL_FIELD as libc::c_int { + let mut optional_field: *mut mailimf_optional_field = + (*field).fld_data.fld_optional_field; + if !optional_field.is_null() + && !(*optional_field).fld_name.is_null() + && strcasecmp( + (*optional_field).fld_name, + b"Autocrypt\x00" as *const u8 as *const libc::c_char, + ) == 0i32 + { + let mut test: *mut dc_aheader_t = dc_aheader_new(); + if 0 == dc_aheader_set_from_string(test, (*optional_field).fld_value) + || dc_addr_cmp((*test).addr, wanted_from) != 0i32 + { + dc_aheader_unref(test); + test = 0 as *mut dc_aheader_t + } + if fine_header.is_null() { + fine_header = test + } else if !test.is_null() { + dc_aheader_unref(fine_header); + dc_aheader_unref(test); + return 0 as *mut dc_aheader_t; + } + } + } + cur = if !cur.is_null() { + (*cur).next + } else { + 0 as *mut clistcell_s + } + } + return fine_header; +} +#[no_mangle] +pub unsafe extern "C" fn dc_aheader_unref(mut aheader: *mut dc_aheader_t) { + if aheader.is_null() { + return; + } + free((*aheader).addr as *mut libc::c_void); + dc_key_unref((*aheader).public_key); + free(aheader as *mut libc::c_void); +} +#[no_mangle] +pub unsafe extern "C" fn dc_aheader_set_from_string( + mut aheader: *mut dc_aheader_t, + mut header_str__: *const libc::c_char, +) -> libc::c_int { + let mut current_block: u64; + /* according to RFC 5322 (Internet Message Format), the given string may contain `\r\n` before any whitespace. + we can ignore this issue as + (a) no key or value is expected to contain spaces, + (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: *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 beg_attr_name: *mut libc::c_char = 0 as *mut libc::c_char; + let mut after_attr_name: *mut libc::c_char = 0 as *mut libc::c_char; + let mut beg_attr_value: *mut libc::c_char = 0 as *mut libc::c_char; + let mut success: libc::c_int = 0i32; + dc_aheader_empty(aheader); + if !(aheader.is_null() || header_str__.is_null()) { + (*aheader).prefer_encrypt = 0i32; + header_str = dc_strdup(header_str__); + p = header_str; + loop { + if !(0 != *p) { + current_block = 5689316957504528238; + break; + } + p = p.offset(strspn(p, b"\t\r\n =;\x00" as *const u8 as *const libc::c_char) as isize); + beg_attr_name = p; + beg_attr_value = 0 as *mut libc::c_char; + p = p.offset(strcspn(p, b"\t\r\n =;\x00" as *const u8 as *const libc::c_char) as isize); + if !(p != beg_attr_name) { + continue; + } + after_attr_name = p; + p = p.offset(strspn(p, b"\t\r\n \x00" as *const u8 as *const libc::c_char) as isize); + if *p as libc::c_int == '=' as i32 { + p = p.offset( + strspn(p, b"\t\r\n =\x00" as *const u8 as *const libc::c_char) as isize, + ); + beg_attr_value = p; + p = p.offset(strcspn(p, b";\x00" as *const u8 as *const libc::c_char) as isize); + if *p as libc::c_int != '\u{0}' as i32 { + *p = '\u{0}' as i32 as libc::c_char; + p = p.offset(1isize) + } + dc_trim(beg_attr_value); + } else { + p = p + .offset(strspn(p, b"\t\r\n ;\x00" as *const u8 as *const libc::c_char) as isize) + } + *after_attr_name = '\u{0}' as i32 as libc::c_char; + if !(0 == add_attribute(aheader, beg_attr_name, beg_attr_value)) { + continue; + } + /* a bad attribute makes the whole header invalid */ + current_block = 9271062167157603455; + break; + } + match current_block { + 9271062167157603455 => {} + _ => { + if !(*aheader).addr.is_null() && !(*(*aheader).public_key).binary.is_null() { + success = 1i32 + } + } + } + } + free(header_str as *mut libc::c_void); + if 0 == success { + dc_aheader_empty(aheader); + } + return success; +} +#[no_mangle] +pub unsafe extern "C" fn dc_aheader_empty(mut aheader: *mut dc_aheader_t) { + if aheader.is_null() { + return; + } + (*aheader).prefer_encrypt = 0i32; + free((*aheader).addr as *mut libc::c_void); + (*aheader).addr = 0 as *mut libc::c_char; + if !(*(*aheader).public_key).binary.is_null() { + dc_key_unref((*aheader).public_key); + (*aheader).public_key = dc_key_new() + }; +} +/* ****************************************************************************** + * Parse Autocrypt Header + ******************************************************************************/ +unsafe extern "C" fn add_attribute( + mut aheader: *mut dc_aheader_t, + mut name: *const libc::c_char, + mut value: *const libc::c_char, +) -> libc::c_int { + if strcasecmp(name, b"addr\x00" as *const u8 as *const libc::c_char) == 0i32 { + if value.is_null() || 0 == dc_may_be_valid_addr(value) || !(*aheader).addr.is_null() { + return 0i32; + } + (*aheader).addr = dc_addr_normalize(value); + return 1i32; + } else { + if strcasecmp( + name, + b"prefer-encrypt\x00" as *const u8 as *const libc::c_char, + ) == 0i32 + { + if !value.is_null() + && strcasecmp(value, b"mutual\x00" as *const u8 as *const libc::c_char) == 0i32 + { + (*aheader).prefer_encrypt = 1i32; + return 1i32; + } + return 1i32; + } else { + if strcasecmp(name, b"keydata\x00" as *const u8 as *const libc::c_char) == 0i32 { + if value.is_null() + || !(*(*aheader).public_key).binary.is_null() + || 0 != (*(*aheader).public_key).bytes + { + return 0i32; + } + return dc_key_set_from_base64((*aheader).public_key, value, 0i32); + } else { + if *name.offset(0isize) as libc::c_int == '_' as i32 { + return 1i32; + } + } + } + } + return 0i32; +} +#[no_mangle] +pub unsafe extern "C" fn dc_aheader_render(mut aheader: *const dc_aheader_t) -> *mut libc::c_char { + let mut success: libc::c_int = 0i32; + let mut keybase64_wrapped: *mut libc::c_char = 0 as *mut libc::c_char; + let mut ret: dc_strbuilder_t = _dc_strbuilder { + 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 !(aheader.is_null() + || (*aheader).addr.is_null() + || (*(*aheader).public_key).binary.is_null() + || (*(*aheader).public_key).type_0 != 0i32) + { + dc_strbuilder_cat(&mut ret, b"addr=\x00" as *const u8 as *const libc::c_char); + dc_strbuilder_cat(&mut ret, (*aheader).addr); + dc_strbuilder_cat(&mut ret, b"; \x00" as *const u8 as *const libc::c_char); + if (*aheader).prefer_encrypt == 1i32 { + dc_strbuilder_cat( + &mut ret, + b"prefer-encrypt=mutual; \x00" as *const u8 as *const libc::c_char, + ); + } + dc_strbuilder_cat( + &mut ret, + b"keydata= \x00" as *const u8 as *const libc::c_char, + ); + /* 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, + 78i32, + b" \x00" as *const u8 as *const libc::c_char, + 0i32, + ); + if !keybase64_wrapped.is_null() { + /*no checksum*/ + dc_strbuilder_cat(&mut ret, keybase64_wrapped); + success = 1i32 + } + } + if 0 == success { + free(ret.buf as *mut libc::c_void); + ret.buf = 0 as *mut libc::c_char + } + free(keybase64_wrapped as *mut libc::c_void); + return ret.buf; +} diff --git a/src/dc_apeerstate.rs b/src/dc_apeerstate.rs new file mode 100644 index 000000000..a43ef0421 --- /dev/null +++ b/src/dc_apeerstate.rs @@ -0,0 +1,1428 @@ +use c2rust_bitfields::BitfieldStruct; +use libc; +extern "C" { + pub type mailstream_cancel; + pub type sqlite3; + pub type sqlite3_stmt; + #[no_mangle] + fn calloc(_: libc::c_ulong, _: libc::c_ulong) -> *mut libc::c_void; + #[no_mangle] + fn free(_: *mut libc::c_void); + #[no_mangle] + fn exit(_: libc::c_int) -> !; + #[no_mangle] + fn strlen(_: *const libc::c_char) -> libc::c_ulong; + #[no_mangle] + fn strcasecmp(_: *const libc::c_char, _: *const libc::c_char) -> libc::c_int; + #[no_mangle] + fn sqlite3_bind_blob( + _: *mut sqlite3_stmt, + _: libc::c_int, + _: *const libc::c_void, + n: libc::c_int, + _: Option ()>, + ) -> libc::c_int; + #[no_mangle] + fn sqlite3_bind_int64(_: *mut sqlite3_stmt, _: libc::c_int, _: sqlite3_int64) -> libc::c_int; + #[no_mangle] + fn sqlite3_bind_text( + _: *mut sqlite3_stmt, + _: libc::c_int, + _: *const libc::c_char, + _: libc::c_int, + _: Option ()>, + ) -> libc::c_int; + #[no_mangle] + fn sqlite3_step(_: *mut sqlite3_stmt) -> libc::c_int; + #[no_mangle] + fn sqlite3_column_int(_: *mut sqlite3_stmt, iCol: libc::c_int) -> libc::c_int; + #[no_mangle] + fn sqlite3_column_int64(_: *mut sqlite3_stmt, iCol: libc::c_int) -> sqlite3_int64; + #[no_mangle] + fn sqlite3_column_text(_: *mut sqlite3_stmt, iCol: libc::c_int) -> *const libc::c_uchar; + #[no_mangle] + fn sqlite3_column_type(_: *mut sqlite3_stmt, iCol: libc::c_int) -> libc::c_int; + #[no_mangle] + fn sqlite3_finalize(pStmt: *mut sqlite3_stmt) -> libc::c_int; + /* tools, these functions are compatible to the corresponding sqlite3_* functions */ + #[no_mangle] + fn dc_sqlite3_prepare(_: *mut dc_sqlite3_t, sql: *const libc::c_char) -> *mut sqlite3_stmt; + /* string tools */ + #[no_mangle] + fn dc_strdup(_: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn dc_reset_gossiped_timestamp(_: *mut dc_context_t, chat_id: uint32_t); + #[no_mangle] + fn dc_key_new() -> *mut dc_key_t; + #[no_mangle] + fn dc_key_ref(_: *mut dc_key_t) -> *mut dc_key_t; + #[no_mangle] + fn dc_key_unref(_: *mut dc_key_t); + #[no_mangle] + fn dc_key_set_from_key(_: *mut dc_key_t, _: *const dc_key_t) -> libc::c_int; + #[no_mangle] + fn dc_key_set_from_stmt( + _: *mut dc_key_t, + _: *mut sqlite3_stmt, + index: libc::c_int, + type_0: libc::c_int, + ) -> libc::c_int; + #[no_mangle] + fn dc_key_equals(_: *const dc_key_t, _: *const dc_key_t) -> libc::c_int; + #[no_mangle] + fn dc_key_get_fingerprint(_: *const dc_key_t) -> *mut libc::c_char; + /* the returned pointer is ref'd and must be unref'd after usage */ + #[no_mangle] + fn dc_aheader_new() -> *mut dc_aheader_t; + #[no_mangle] + fn dc_aheader_unref(_: *mut dc_aheader_t); + #[no_mangle] + fn dc_aheader_render(_: *const dc_aheader_t) -> *mut libc::c_char; + #[no_mangle] + fn dc_hash_find( + _: *const dc_hash_t, + pKey: *const libc::c_void, + nKey: libc::c_int, + ) -> *mut libc::c_void; +} +pub type __darwin_size_t = libc::c_ulong; +pub type __darwin_ssize_t = libc::c_long; +pub type __darwin_time_t = libc::c_long; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_cond_t { + pub __sig: libc::c_long, + pub __opaque: [libc::c_char; 40], +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_mutex_t { + pub __sig: libc::c_long, + pub __opaque: [libc::c_char; 56], +} +pub type __darwin_pthread_cond_t = _opaque_pthread_cond_t; +pub type __darwin_pthread_mutex_t = _opaque_pthread_mutex_t; +pub type uintptr_t = libc::c_ulong; +pub type size_t = __darwin_size_t; +pub type uint8_t = libc::c_uchar; +pub type uint32_t = libc::c_uint; +pub type ssize_t = __darwin_ssize_t; +pub type time_t = __darwin_time_t; +pub type pthread_cond_t = __darwin_pthread_cond_t; +pub type pthread_mutex_t = __darwin_pthread_mutex_t; +#[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; +#[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) -> (); +#[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; +#[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, + 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 { + 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_capability_data { + pub cap_list: *mut clist, +} +#[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_0, + 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_0 { + 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 extern "C" 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_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, +} +#[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_1, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed_1 { + pub ft_fetch_att: *mut mailimap_fetch_att, + pub ft_fetch_att_list: *mut clist, +} +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 unnamed_2 { + 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, +} +/* define DC_USE_RPGP to enable use of rPGP instead of netpgp where available; +preferrably, this should be done in the project configuration currently */ +//#define DC_USE_RPGP 1 +/* Includes that are used frequently. This file may also be used to create predefined headers. */ +/* * Structure behind dc_context_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_context { + pub magic: uint32_t, + pub userdata: *mut libc::c_void, + pub dbfile: *mut libc::c_char, + pub blobdir: *mut libc::c_char, + pub sql: *mut dc_sqlite3_t, + pub inbox: *mut dc_imap_t, + pub inboxidle_condmutex: pthread_mutex_t, + pub perform_inbox_jobs_needed: libc::c_int, + pub probe_imap_network: libc::c_int, + pub sentbox_thread: dc_jobthread_t, + pub mvbox_thread: dc_jobthread_t, + pub smtp: *mut dc_smtp_t, + pub smtpidle_cond: pthread_cond_t, + pub smtpidle_condmutex: pthread_mutex_t, + pub smtpidle_condflag: libc::c_int, + pub smtp_suspended: libc::c_int, + pub smtp_doing_jobs: libc::c_int, + pub perform_smtp_jobs_needed: libc::c_int, + pub probe_smtp_network: libc::c_int, + pub oauth2_critical: pthread_mutex_t, + 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 type dc_lot_t = _dc_lot; +/* * Structure behind dc_lot_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_lot { + pub magic: uint32_t, + pub text1_meaning: libc::c_int, + pub text1: *mut libc::c_char, + pub text2: *mut libc::c_char, + pub timestamp: time_t, + pub state: libc::c_int, + pub id: uint32_t, + pub fingerprint: *mut libc::c_char, + pub invitenumber: *mut libc::c_char, + pub auth: *mut libc::c_char, +} +/* * + * 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 = Option< + unsafe extern "C" fn( + _: *mut dc_context_t, + _: libc::c_int, + _: uintptr_t, + _: uintptr_t, + ) -> uintptr_t, +>; +/* * + * @mainpage Getting started + * + * This document describes how to handle the Delta Chat core library. + * For general information about Delta Chat itself, + * see and . + * + * Let's start. + * + * First of all, you have to **define an event-handler-function** + * that is called by the library on specific events + * (eg. when the configuration is done or when fresh messages arrive). + * With this function you can create a Delta Chat context then: + * + * ~~~ + * #include + * + * uintptr_t event_handler_func(dc_context_t* context, int event, + * uintptr_t data1, uintptr_t data2) + * { + * return 0; // for unhandled events, it is always safe to return 0 + * } + * + * dc_context_t* context = dc_context_new(event_handler_func, NULL, NULL); + * ~~~ + * + * After that, you should make sure, + * sending and receiving jobs are processed as needed. + * For this purpose, you have to **create two threads:** + * + * ~~~ + * #include + * + * void* imap_thread_func(void* context) + * { + * while (true) { + * dc_perform_imap_jobs(context); + * dc_perform_imap_fetch(context); + * dc_perform_imap_idle(context); + * } + * } + * + * void* smtp_thread_func(void* context) + * { + * while (true) { + * dc_perform_smtp_jobs(context); + * dc_perform_smtp_idle(context); + * } + * } + * + * static pthread_t imap_thread, smtp_thread; + * pthread_create(&imap_thread, NULL, imap_thread_func, context); + * pthread_create(&smtp_thread, NULL, smtp_thread_func, context); + * ~~~ + * + * The example above uses "pthreads", + * however, you can also use anything else for thread handling. + * NB: The deltachat-core library itself does not create any threads on its own, + * however, functions, unless stated otherwise, are thread-safe. + * + * After that you can **define and open a database.** + * The database is a normal sqlite-file and is created as needed: + * + * ~~~ + * dc_open(context, "example.db", NULL); + * ~~~ + * + * Now you can **configure the context:** + * + * ~~~ + * // use some real test credentials here + * dc_set_config(context, "addr", "alice@example.org"); + * dc_set_config(context, "mail_pw", "***"); + * dc_configure(context); + * ~~~ + * + * dc_configure() returns immediately, the configuration itself may take a while + * and is done by a job in the imap-thread you've defined above. + * Once done, the #DC_EVENT_CONFIGURE_PROGRESS reports success + * to the event_handler_func() that is also defined above. + * + * The configuration result is saved in the database, + * on subsequent starts it is not needed to call dc_configure() + * (you can check this using dc_is_configured()). + * + * Now you can **send the first message:** + * + * ~~~ + * // use a real testing address here + * uint32_t contact_id = dc_create_contact(context, NULL, "bob@example.org"); + * uint32_t chat_id = dc_create_chat_by_contact_id(context, contact_id); + * + * dc_send_text_msg(context, chat_id, "Hi, here is my first message!"); + * ~~~ + * + * dc_send_text_msg() returns immediately; + * the sending itself is done by a job in the smtp-thread you've defined above. + * If you check the testing address (bob) + * and you should have received a normal email. + * Answer this email in any email program with "Got it!" + * and the imap-thread you've create above will **receive the message**. + * + * You can then **list all messages** of a chat as follow: + * + * ~~~ + * dc_array_t* msglist = dc_get_chat_msgs(context, chat_id, 0, 0); + * for (int i = 0; i < dc_array_get_cnt(msglist); i++) + * { + * uint32_t msg_id = dc_array_get_id(msglist, i); + * dc_msg_t* msg = dc_get_msg(context, msg_id); + * char* text = dc_msg_get_text(msg); + * + * printf("Message %i: %s\n", i+1, text); + * + * free(text); + * dc_msg_unref(msg); + * } + * dc_array_unref(msglist); + * ~~~ + * + * This will output the following two lines: + * + * ~~~ + * Message 1: Hi, here is my first message! + * Message 2: Got it! + * ~~~ + * + * + * ## Class reference + * + * For a class reference, see the "Classes" link atop. + * + * + * ## Further hints + * + * Here are some additional, unsorted hints that may be useful. + * + * - For `get`-functions, you have to unref the return value in some way. + * + * - Strings in function arguments or return values are usually UTF-8 encoded. + * + * - The issue-tracker for the core library is here: + * + * + * The following points are important mainly + * for the authors of the library itself: + * + * - For indentation, use tabs. + * Alignments that are not placed at the beginning of a line + * should be done with spaces. + * + * - For padding between functions, + * classes etc. use 2 empty lines + * + * - Source files are encoded as UTF-8 with Unix line endings + * (a simple `LF`, `0x0A` or `\n`) + * + * If you need further assistance, + * please do not hesitate to contact us + * through the channels shown at https://delta.chat/en/contribute + * + * Please keep in mind, that your derived work + * must respect the Mozilla Public License 2.0 of libdeltachat + * and the respective licenses of the libraries libdeltachat links with. + * + * See you. + */ +/* * + * @class dc_context_t + * + * An object representing a single account. + * + * Each account is linked to an IMAP/SMTP account and uses a separate + * SQLite database for offline functionality and for account-related + * settings. + */ +pub type dc_context_t = _dc_context; +/* ** library-private **********************************************************/ +pub type dc_smtp_t = _dc_smtp; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_smtp { + 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 error: *mut libc::c_char, + pub error_etpan: libc::c_int, +} +pub type dc_jobthread_t = _dc_jobthread; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_jobthread { + 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, + 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, +} +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_imap { + 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 type dc_receive_imf_t = Option< + unsafe extern "C" 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_imap_t = _dc_imap; +pub type dc_precheck_imf_t = Option< + unsafe extern "C" 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< + unsafe extern "C" fn(_: *mut dc_imap_t, _: *const libc::c_char, _: *const libc::c_char) -> (), +>; +pub type dc_get_config_t = Option< + unsafe extern "C" fn( + _: *mut dc_imap_t, + _: *const libc::c_char, + _: *const libc::c_char, + ) -> *mut libc::c_char, +>; +/* ** library-private **********************************************************/ +pub type dc_sqlite3_t = _dc_sqlite3; +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_sqlite3 { + pub cobj: *mut sqlite3, + pub context: *mut dc_context_t, +} +pub type sqlite_int64 = libc::c_longlong; +pub type sqlite3_int64 = sqlite_int64; +pub type sqlite3_destructor_type = Option ()>; +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_key { + pub binary: *mut libc::c_void, + pub bytes: libc::c_int, + pub type_0: libc::c_int, + pub _m_heap_refcnt: libc::c_int, +} +pub type dc_key_t = _dc_key; +/* * + * @class dc_aheader_t + * Library-internal. Parse and create [Autocrypt-headers](https://autocrypt.org/en/latest/level1.html#the-autocrypt-header). + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_aheader { + pub addr: *mut libc::c_char, + pub public_key: *mut dc_key_t, + pub prefer_encrypt: libc::c_int, +} +pub type dc_aheader_t = _dc_aheader; +/* A complete hash table is an instance of the following structure. + * The internals of this structure are intended to be opaque -- client + * code should not attempt to access or modify the fields of this structure + * directly. Change this structure only by using the routines below. + * However, many of the "procedures" and "functions" for modifying and + * accessing this structure are really macros, so we can't really make + * this structure opaque. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_hash { + pub keyClass: libc::c_char, + pub copyKey: libc::c_char, + pub count: libc::c_int, + pub first: *mut dc_hashelem_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. + * + * Again, this structure is intended to be opaque, but it can't really + * be opaque because it is used by macros. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_hashelem { + pub next: *mut dc_hashelem_t, + pub prev: *mut dc_hashelem_t, + pub data: *mut libc::c_void, + pub pKey: *mut libc::c_void, + pub nKey: libc::c_int, +} +/* Forward declarations of structures. + */ +pub type dc_hash_t = _dc_hash; +/* prefer-encrypt states */ +/* * + * @class dc_apeerstate_t + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_apeerstate { + pub context: *mut dc_context_t, + pub addr: *mut libc::c_char, + pub last_seen: time_t, + pub last_seen_autocrypt: time_t, + pub prefer_encrypt: libc::c_int, + pub public_key: *mut dc_key_t, + pub public_key_fingerprint: *mut libc::c_char, + pub gossip_key: *mut dc_key_t, + pub gossip_timestamp: time_t, + pub gossip_key_fingerprint: *mut libc::c_char, + pub verified_key: *mut dc_key_t, + pub verified_key_fingerprint: *mut libc::c_char, + pub to_save: libc::c_int, + pub degrade_event: libc::c_int, +} +pub type dc_apeerstate_t = _dc_apeerstate; +/* the returned pointer is ref'd and must be unref'd after usage */ +#[no_mangle] +pub unsafe extern "C" 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; + peerstate = calloc( + 1i32 as libc::c_ulong, + ::std::mem::size_of::() as libc::c_ulong, + ) as *mut dc_apeerstate_t; + if peerstate.is_null() { + exit(43i32); + } + (*peerstate).context = context; + return peerstate; +} +#[no_mangle] +pub unsafe extern "C" 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 extern "C" fn dc_apeerstate_empty(mut peerstate: *mut dc_apeerstate_t) { + if peerstate.is_null() { + return; + } + (*peerstate).last_seen = 0i32 as time_t; + (*peerstate).last_seen_autocrypt = 0i32 as time_t; + (*peerstate).prefer_encrypt = 0i32; + (*peerstate).to_save = 0i32; + free((*peerstate).addr as *mut libc::c_void); + (*peerstate).addr = 0 as *mut libc::c_char; + free((*peerstate).public_key_fingerprint as *mut libc::c_void); + (*peerstate).public_key_fingerprint = 0 as *mut libc::c_char; + free((*peerstate).gossip_key_fingerprint as *mut libc::c_void); + (*peerstate).gossip_key_fingerprint = 0 as *mut libc::c_char; + free((*peerstate).verified_key_fingerprint as *mut libc::c_void); + (*peerstate).verified_key_fingerprint = 0 as *mut libc::c_char; + dc_key_unref((*peerstate).public_key); + (*peerstate).public_key = 0 as *mut dc_key_t; + (*peerstate).gossip_timestamp = 0i32 as time_t; + dc_key_unref((*peerstate).gossip_key); + (*peerstate).gossip_key = 0 as *mut dc_key_t; + dc_key_unref((*peerstate).verified_key); + (*peerstate).verified_key = 0 as *mut dc_key_t; + (*peerstate).degrade_event = 0i32; +} +#[no_mangle] +pub unsafe extern "C" fn dc_apeerstate_init_from_header( + mut peerstate: *mut dc_apeerstate_t, + mut header: *const dc_aheader_t, + mut message_time: time_t, +) -> libc::c_int { + if peerstate.is_null() || header.is_null() { + return 0i32; + } + dc_apeerstate_empty(peerstate); + (*peerstate).addr = dc_strdup((*header).addr); + (*peerstate).last_seen = message_time; + (*peerstate).last_seen_autocrypt = message_time; + (*peerstate).to_save |= 0x2i32; + (*peerstate).prefer_encrypt = (*header).prefer_encrypt; + (*peerstate).public_key = dc_key_new(); + dc_key_set_from_key((*peerstate).public_key, (*header).public_key); + dc_apeerstate_recalc_fingerprint(peerstate); + return 1i32; +} +#[no_mangle] +pub unsafe extern "C" 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; + let mut old_gossip_fingerprint: *mut libc::c_char = 0 as *mut libc::c_char; + 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); + if old_public_fingerprint.is_null() + || *old_public_fingerprint.offset(0isize) as libc::c_int == 0i32 + || (*peerstate).public_key_fingerprint.is_null() + || *(*peerstate).public_key_fingerprint.offset(0isize) as libc::c_int == 0i32 + || strcasecmp(old_public_fingerprint, (*peerstate).public_key_fingerprint) != 0i32 + { + (*peerstate).to_save |= 0x2i32; + if !old_public_fingerprint.is_null() + && 0 != *old_public_fingerprint.offset(0isize) as libc::c_int + { + (*peerstate).degrade_event |= 0x2i32 + } + } + } + if !(*peerstate).gossip_key.is_null() { + old_gossip_fingerprint = (*peerstate).gossip_key_fingerprint; + (*peerstate).gossip_key_fingerprint = dc_key_get_fingerprint((*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() + || *(*peerstate).gossip_key_fingerprint.offset(0isize) as libc::c_int == 0i32 + || strcasecmp(old_gossip_fingerprint, (*peerstate).gossip_key_fingerprint) != 0i32 + { + (*peerstate).to_save |= 0x2i32; + if !old_gossip_fingerprint.is_null() + && 0 != *old_gossip_fingerprint.offset(0isize) as libc::c_int + { + (*peerstate).degrade_event |= 0x2i32 + } + } + } + success = 1i32 + } + free(old_public_fingerprint as *mut libc::c_void); + free(old_gossip_fingerprint as *mut libc::c_void); + return success; +} +#[no_mangle] +pub unsafe extern "C" fn dc_apeerstate_init_from_gossip( + mut peerstate: *mut dc_apeerstate_t, + mut gossip_header: *const dc_aheader_t, + mut message_time: time_t, +) -> libc::c_int { + if peerstate.is_null() || gossip_header.is_null() { + return 0i32; + } + dc_apeerstate_empty(peerstate); + (*peerstate).addr = dc_strdup((*gossip_header).addr); + (*peerstate).gossip_timestamp = message_time; + (*peerstate).to_save |= 0x2i32; + (*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; +} +#[no_mangle] +pub unsafe extern "C" fn dc_apeerstate_degrade_encryption( + mut peerstate: *mut dc_apeerstate_t, + mut message_time: time_t, +) -> libc::c_int { + if peerstate.is_null() { + return 0i32; + } + if (*peerstate).prefer_encrypt == 1i32 { + (*peerstate).degrade_event |= 0x1i32 + } + (*peerstate).prefer_encrypt = 20i32; + (*peerstate).last_seen = message_time; + (*peerstate).to_save |= 0x2i32; + return 1i32; +} +#[no_mangle] +pub unsafe extern "C" fn dc_apeerstate_apply_header( + mut peerstate: *mut dc_apeerstate_t, + mut header: *const dc_aheader_t, + mut message_time: time_t, +) { + if peerstate.is_null() + || header.is_null() + || (*peerstate).addr.is_null() + || (*header).addr.is_null() + || (*(*header).public_key).binary.is_null() + || strcasecmp((*peerstate).addr, (*header).addr) != 0i32 + { + return; + } + if message_time > (*peerstate).last_seen_autocrypt { + (*peerstate).last_seen = message_time; + (*peerstate).last_seen_autocrypt = message_time; + (*peerstate).to_save |= 0x1i32; + if ((*header).prefer_encrypt == 1i32 || (*header).prefer_encrypt == 0i32) + && (*header).prefer_encrypt != (*peerstate).prefer_encrypt + { + if (*peerstate).prefer_encrypt == 1i32 && (*header).prefer_encrypt != 1i32 { + (*peerstate).degrade_event |= 0x1i32 + } + (*peerstate).prefer_encrypt = (*header).prefer_encrypt; + (*peerstate).to_save |= 0x2i32 + } + if (*peerstate).public_key.is_null() { + (*peerstate).public_key = dc_key_new() + } + if 0 == dc_key_equals((*peerstate).public_key, (*header).public_key) { + dc_key_set_from_key((*peerstate).public_key, (*header).public_key); + dc_apeerstate_recalc_fingerprint(peerstate); + (*peerstate).to_save |= 0x2i32 + } + }; +} +#[no_mangle] +pub unsafe extern "C" fn dc_apeerstate_apply_gossip( + mut peerstate: *mut dc_apeerstate_t, + mut gossip_header: *const dc_aheader_t, + mut message_time: time_t, +) { + if peerstate.is_null() + || gossip_header.is_null() + || (*peerstate).addr.is_null() + || (*gossip_header).addr.is_null() + || (*(*gossip_header).public_key).binary.is_null() + || strcasecmp((*peerstate).addr, (*gossip_header).addr) != 0i32 + { + return; + } + if message_time > (*peerstate).gossip_timestamp { + (*peerstate).gossip_timestamp = message_time; + (*peerstate).to_save |= 0x1i32; + if (*peerstate).gossip_key.is_null() { + (*peerstate).gossip_key = dc_key_new() + } + if 0 == dc_key_equals((*peerstate).gossip_key, (*gossip_header).public_key) { + dc_key_set_from_key((*peerstate).gossip_key, (*gossip_header).public_key); + dc_apeerstate_recalc_fingerprint(peerstate); + (*peerstate).to_save |= 0x2i32 + } + }; +} +#[no_mangle] +pub unsafe extern "C" fn dc_apeerstate_render_gossip_header( + mut peerstate: *const dc_apeerstate_t, + mut min_verified: libc::c_int, +) -> *mut libc::c_char { + let mut ret: *mut libc::c_char = 0 as *mut libc::c_char; + let mut autocryptheader: *mut dc_aheader_t = dc_aheader_new(); + if !(peerstate.is_null() || (*peerstate).addr.is_null()) { + (*autocryptheader).prefer_encrypt = 0i32; + (*autocryptheader).addr = dc_strdup((*peerstate).addr); + (*autocryptheader).public_key = dc_key_ref(dc_apeerstate_peek_key(peerstate, min_verified)); + ret = dc_aheader_render(autocryptheader) + } + dc_aheader_unref(autocryptheader); + return ret; +} +#[no_mangle] +pub unsafe extern "C" fn dc_apeerstate_peek_key( + mut peerstate: *const dc_apeerstate_t, + mut min_verified: libc::c_int, +) -> *mut dc_key_t { + if peerstate.is_null() + || !(*peerstate).public_key.is_null() + && ((*(*peerstate).public_key).binary.is_null() + || (*(*peerstate).public_key).bytes <= 0i32) + || !(*peerstate).gossip_key.is_null() + && ((*(*peerstate).gossip_key).binary.is_null() + || (*(*peerstate).gossip_key).bytes <= 0i32) + || !(*peerstate).verified_key.is_null() + && ((*(*peerstate).verified_key).binary.is_null() + || (*(*peerstate).verified_key).bytes <= 0i32) + { + return 0 as *mut dc_key_t; + } + if 0 != min_verified { + return (*peerstate).verified_key; + } + if !(*peerstate).public_key.is_null() { + return (*peerstate).public_key; + } + return (*peerstate).gossip_key; +} +#[no_mangle] +pub unsafe extern "C" fn dc_apeerstate_set_verified( + mut peerstate: *mut dc_apeerstate_t, + mut which_key: libc::c_int, + mut fingerprint: *const libc::c_char, + mut verified: libc::c_int, +) -> libc::c_int { + let mut success: libc::c_int = 0i32; + if !(peerstate.is_null() || which_key != 0i32 && which_key != 1i32 || verified != 2i32) { + if which_key == 1i32 + && !(*peerstate).public_key_fingerprint.is_null() + && *(*peerstate).public_key_fingerprint.offset(0isize) as libc::c_int != 0i32 + && *fingerprint.offset(0isize) as libc::c_int != 0i32 + && strcasecmp((*peerstate).public_key_fingerprint, fingerprint) == 0i32 + { + (*peerstate).to_save |= 0x2i32; + (*peerstate).verified_key = dc_key_ref((*peerstate).public_key); + (*peerstate).verified_key_fingerprint = dc_strdup((*peerstate).public_key_fingerprint); + success = 1i32 + } + if which_key == 0i32 + && !(*peerstate).gossip_key_fingerprint.is_null() + && *(*peerstate).gossip_key_fingerprint.offset(0isize) as libc::c_int != 0i32 + && *fingerprint.offset(0isize) as libc::c_int != 0i32 + && strcasecmp((*peerstate).gossip_key_fingerprint, fingerprint) == 0i32 + { + (*peerstate).to_save |= 0x2i32; + (*peerstate).verified_key = dc_key_ref((*peerstate).gossip_key); + (*peerstate).verified_key_fingerprint = dc_strdup((*peerstate).gossip_key_fingerprint); + success = 1i32 + } + } + return success; +} +#[no_mangle] +pub unsafe extern "C" fn dc_apeerstate_load_by_addr( + mut peerstate: *mut dc_apeerstate_t, + mut sql: *mut 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()) { + 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 addr=? COLLATE NOCASE;\x00" + as *const u8 as *const libc::c_char); + sqlite3_bind_text(stmt, 1i32, addr, -1i32, None); + if !(sqlite3_step(stmt) != 100i32) { + dc_apeerstate_set_from_stmt(peerstate, stmt); + success = 1i32 + } + } + sqlite3_finalize(stmt); + return success; +} +unsafe extern "C" fn dc_apeerstate_set_from_stmt( + mut peerstate: *mut dc_apeerstate_t, + mut stmt: *mut sqlite3_stmt, +) { + (*peerstate).addr = dc_strdup(sqlite3_column_text(stmt, 0i32) as *mut libc::c_char); + (*peerstate).last_seen = sqlite3_column_int64(stmt, 1i32) as time_t; + (*peerstate).last_seen_autocrypt = sqlite3_column_int64(stmt, 2i32) as time_t; + (*peerstate).prefer_encrypt = sqlite3_column_int(stmt, 3i32); + (*peerstate).gossip_timestamp = sqlite3_column_int(stmt, 5i32) as time_t; + (*peerstate).public_key_fingerprint = + dc_strdup(sqlite3_column_text(stmt, 7i32) as *mut libc::c_char); + (*peerstate).gossip_key_fingerprint = + dc_strdup(sqlite3_column_text(stmt, 8i32) as *mut libc::c_char); + (*peerstate).verified_key_fingerprint = + dc_strdup(sqlite3_column_text(stmt, 10i32) as *mut libc::c_char); + if sqlite3_column_type(stmt, 4i32) != 5i32 { + (*peerstate).public_key = dc_key_new(); + dc_key_set_from_stmt((*peerstate).public_key, stmt, 4i32, 0i32); + } + if sqlite3_column_type(stmt, 6i32) != 5i32 { + (*peerstate).gossip_key = dc_key_new(); + dc_key_set_from_stmt((*peerstate).gossip_key, stmt, 6i32, 0i32); + } + if sqlite3_column_type(stmt, 9i32) != 5i32 { + (*peerstate).verified_key = dc_key_new(); + dc_key_set_from_stmt((*peerstate).verified_key, stmt, 9i32, 0i32); + }; +} +#[no_mangle] +pub unsafe extern "C" fn dc_apeerstate_load_by_fingerprint( + mut peerstate: *mut dc_apeerstate_t, + mut sql: *mut 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()) { + 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" + as *const u8 as *const libc::c_char); + sqlite3_bind_text(stmt, 1i32, fingerprint, -1i32, None); + sqlite3_bind_text(stmt, 2i32, fingerprint, -1i32, None); + sqlite3_bind_text(stmt, 3i32, fingerprint, -1i32, None); + if !(sqlite3_step(stmt) != 100i32) { + dc_apeerstate_set_from_stmt(peerstate, stmt); + success = 1i32 + } + } + sqlite3_finalize(stmt); + return success; +} +#[no_mangle] +pub unsafe extern "C" fn dc_apeerstate_save_to_db( + mut peerstate: *const dc_apeerstate_t, + mut sql: *mut 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() { + return 0i32; + } + if 0 != create { + stmt = dc_sqlite3_prepare( + sql, + b"INSERT INTO acpeerstates (addr) VALUES(?);\x00" as *const u8 as *const libc::c_char, + ); + sqlite3_bind_text(stmt, 1i32, (*peerstate).addr, -1i32, None); + sqlite3_step(stmt); + sqlite3_finalize(stmt); + stmt = 0 as *mut sqlite3_stmt + } + if 0 != (*peerstate).to_save & 0x2i32 || 0 != create { + stmt = + dc_sqlite3_prepare(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); + sqlite3_bind_int64( + stmt, + 2i32, + (*peerstate).last_seen_autocrypt as sqlite3_int64, + ); + sqlite3_bind_int64(stmt, 3i32, (*peerstate).prefer_encrypt as sqlite3_int64); + sqlite3_bind_blob( + stmt, + 4i32, + if !(*peerstate).public_key.is_null() { + (*(*peerstate).public_key).binary + } else { + 0 as *mut libc::c_void + }, + if !(*peerstate).public_key.is_null() { + (*(*peerstate).public_key).bytes + } else { + 0i32 + }, + None, + ); + sqlite3_bind_int64(stmt, 5i32, (*peerstate).gossip_timestamp as sqlite3_int64); + sqlite3_bind_blob( + stmt, + 6i32, + if !(*peerstate).gossip_key.is_null() { + (*(*peerstate).gossip_key).binary + } else { + 0 as *mut libc::c_void + }, + if !(*peerstate).gossip_key.is_null() { + (*(*peerstate).gossip_key).bytes + } else { + 0i32 + }, + None, + ); + sqlite3_bind_text(stmt, 7i32, (*peerstate).public_key_fingerprint, -1i32, None); + sqlite3_bind_text(stmt, 8i32, (*peerstate).gossip_key_fingerprint, -1i32, None); + sqlite3_bind_blob( + stmt, + 9i32, + if !(*peerstate).verified_key.is_null() { + (*(*peerstate).verified_key).binary + } else { + 0 as *mut libc::c_void + }, + if !(*peerstate).verified_key.is_null() { + (*(*peerstate).verified_key).bytes + } else { + 0i32 + }, + None, + ); + sqlite3_bind_text( + stmt, + 10i32, + (*peerstate).verified_key_fingerprint, + -1i32, + None, + ); + sqlite3_bind_text(stmt, 11i32, (*peerstate).addr, -1i32, None); + if sqlite3_step(stmt) != 101i32 { + current_block = 7258450500457619456; + } else { + sqlite3_finalize(stmt); + stmt = 0 as *mut sqlite3_stmt; + current_block = 11913429853522160501; + } + } else if 0 != (*peerstate).to_save & 0x1i32 { + stmt = + dc_sqlite3_prepare(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); + sqlite3_bind_int64( + stmt, + 2i32, + (*peerstate).last_seen_autocrypt as sqlite3_int64, + ); + sqlite3_bind_int64(stmt, 3i32, (*peerstate).gossip_timestamp as sqlite3_int64); + sqlite3_bind_text(stmt, 4i32, (*peerstate).addr, -1i32, None); + if sqlite3_step(stmt) != 101i32 { + current_block = 7258450500457619456; + } else { + sqlite3_finalize(stmt); + stmt = 0 as *mut sqlite3_stmt; + current_block = 11913429853522160501; + } + } else { + current_block = 11913429853522160501; + } + match current_block { + 11913429853522160501 => { + if 0 != (*peerstate).to_save & 0x2i32 || 0 != create { + dc_reset_gossiped_timestamp((*peerstate).context, 0i32 as uint32_t); + } + success = 1i32 + } + _ => {} + } + sqlite3_finalize(stmt); + return success; +} +#[no_mangle] +pub unsafe extern "C" fn dc_apeerstate_has_verified_key( + mut peerstate: *const dc_apeerstate_t, + mut fingerprints: *const dc_hash_t, +) -> libc::c_int { + if peerstate.is_null() || fingerprints.is_null() { + return 0i32; + } + if !(*peerstate).verified_key.is_null() + && !(*peerstate).verified_key_fingerprint.is_null() + && !dc_hash_find( + fingerprints, + (*peerstate).verified_key_fingerprint as *const libc::c_void, + strlen((*peerstate).verified_key_fingerprint) as libc::c_int, + ) + .is_null() + { + return 1i32; + } + return 0i32; +} diff --git a/src/dc_array.rs b/src/dc_array.rs new file mode 100644 index 000000000..a028bba96 --- /dev/null +++ b/src/dc_array.rs @@ -0,0 +1,1241 @@ +use c2rust_bitfields::BitfieldStruct; +use libc; +extern "C" { + pub type mailstream_cancel; + pub type sqlite3; + #[no_mangle] + fn malloc(_: libc::c_ulong) -> *mut libc::c_void; + #[no_mangle] + fn calloc(_: libc::c_ulong, _: libc::c_ulong) -> *mut libc::c_void; + #[no_mangle] + fn free(_: *mut libc::c_void); + #[no_mangle] + fn realloc(_: *mut libc::c_void, _: libc::c_ulong) -> *mut libc::c_void; + #[no_mangle] + fn exit(_: libc::c_int) -> !; + #[no_mangle] + fn qsort( + __base: *mut libc::c_void, + __nel: size_t, + __width: size_t, + __compar: Option< + unsafe extern "C" fn(_: *const libc::c_void, _: *const libc::c_void) -> libc::c_int, + >, + ); + #[no_mangle] + fn memcpy(_: *mut libc::c_void, _: *const libc::c_void, _: libc::c_ulong) -> *mut libc::c_void; + #[no_mangle] + fn strcat(_: *mut libc::c_char, _: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn strcmp(_: *const libc::c_char, _: *const libc::c_char) -> libc::c_int; + #[no_mangle] + fn strlen(_: *const libc::c_char) -> libc::c_ulong; + #[no_mangle] + fn sprintf(_: *mut libc::c_char, _: *const libc::c_char, _: ...) -> libc::c_int; + #[no_mangle] + fn dc_strdup_keep_null(_: *const libc::c_char) -> *mut libc::c_char; + /* string tools */ + #[no_mangle] + fn dc_strdup(_: *const libc::c_char) -> *mut libc::c_char; +} +pub type __darwin_size_t = libc::c_ulong; +pub type __darwin_ssize_t = libc::c_long; +pub type __darwin_time_t = libc::c_long; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_cond_t { + pub __sig: libc::c_long, + pub __opaque: [libc::c_char; 40], +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_mutex_t { + pub __sig: libc::c_long, + pub __opaque: [libc::c_char; 56], +} +pub type __darwin_pthread_cond_t = _opaque_pthread_cond_t; +pub type __darwin_pthread_mutex_t = _opaque_pthread_mutex_t; +pub type uintptr_t = libc::c_ulong; +pub type size_t = __darwin_size_t; +pub type uint8_t = libc::c_uchar; +pub type uint32_t = libc::c_uint; +pub type ssize_t = __darwin_ssize_t; +pub type time_t = __darwin_time_t; +pub type pthread_cond_t = __darwin_pthread_cond_t; +pub type pthread_mutex_t = __darwin_pthread_mutex_t; +#[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; +#[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) -> (); +#[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; +#[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, + 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 { + 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_capability_data { + pub cap_list: *mut clist, +} +#[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_0, + 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_0 { + 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 extern "C" 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_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, +} +#[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_1, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed_1 { + pub ft_fetch_att: *mut mailimap_fetch_att, + pub ft_fetch_att_list: *mut clist, +} +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 unnamed_2 { + 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, +} +/* define DC_USE_RPGP to enable use of rPGP instead of netpgp where available; +preferrably, this should be done in the project configuration currently */ +//#define DC_USE_RPGP 1 +/* Includes that are used frequently. This file may also be used to create predefined headers. */ +/* * Structure behind dc_context_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_context { + pub magic: uint32_t, + pub userdata: *mut libc::c_void, + pub dbfile: *mut libc::c_char, + pub blobdir: *mut libc::c_char, + pub sql: *mut dc_sqlite3_t, + pub inbox: *mut dc_imap_t, + pub inboxidle_condmutex: pthread_mutex_t, + pub perform_inbox_jobs_needed: libc::c_int, + pub probe_imap_network: libc::c_int, + pub sentbox_thread: dc_jobthread_t, + pub mvbox_thread: dc_jobthread_t, + pub smtp: *mut dc_smtp_t, + pub smtpidle_cond: pthread_cond_t, + pub smtpidle_condmutex: pthread_mutex_t, + pub smtpidle_condflag: libc::c_int, + pub smtp_suspended: libc::c_int, + pub smtp_doing_jobs: libc::c_int, + pub perform_smtp_jobs_needed: libc::c_int, + pub probe_smtp_network: libc::c_int, + pub oauth2_critical: pthread_mutex_t, + 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 type dc_lot_t = _dc_lot; +/* * Structure behind dc_lot_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_lot { + pub magic: uint32_t, + pub text1_meaning: libc::c_int, + pub text1: *mut libc::c_char, + pub text2: *mut libc::c_char, + pub timestamp: time_t, + pub state: libc::c_int, + pub id: uint32_t, + pub fingerprint: *mut libc::c_char, + pub invitenumber: *mut libc::c_char, + pub auth: *mut libc::c_char, +} +/* * + * 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 = Option< + unsafe extern "C" fn( + _: *mut dc_context_t, + _: libc::c_int, + _: uintptr_t, + _: uintptr_t, + ) -> uintptr_t, +>; +/* * + * @mainpage Getting started + * + * This document describes how to handle the Delta Chat core library. + * For general information about Delta Chat itself, + * see and . + * + * Let's start. + * + * First of all, you have to **define an event-handler-function** + * that is called by the library on specific events + * (eg. when the configuration is done or when fresh messages arrive). + * With this function you can create a Delta Chat context then: + * + * ~~~ + * #include + * + * uintptr_t event_handler_func(dc_context_t* context, int event, + * uintptr_t data1, uintptr_t data2) + * { + * return 0; // for unhandled events, it is always safe to return 0 + * } + * + * dc_context_t* context = dc_context_new(event_handler_func, NULL, NULL); + * ~~~ + * + * After that, you should make sure, + * sending and receiving jobs are processed as needed. + * For this purpose, you have to **create two threads:** + * + * ~~~ + * #include + * + * void* imap_thread_func(void* context) + * { + * while (true) { + * dc_perform_imap_jobs(context); + * dc_perform_imap_fetch(context); + * dc_perform_imap_idle(context); + * } + * } + * + * void* smtp_thread_func(void* context) + * { + * while (true) { + * dc_perform_smtp_jobs(context); + * dc_perform_smtp_idle(context); + * } + * } + * + * static pthread_t imap_thread, smtp_thread; + * pthread_create(&imap_thread, NULL, imap_thread_func, context); + * pthread_create(&smtp_thread, NULL, smtp_thread_func, context); + * ~~~ + * + * The example above uses "pthreads", + * however, you can also use anything else for thread handling. + * NB: The deltachat-core library itself does not create any threads on its own, + * however, functions, unless stated otherwise, are thread-safe. + * + * After that you can **define and open a database.** + * The database is a normal sqlite-file and is created as needed: + * + * ~~~ + * dc_open(context, "example.db", NULL); + * ~~~ + * + * Now you can **configure the context:** + * + * ~~~ + * // use some real test credentials here + * dc_set_config(context, "addr", "alice@example.org"); + * dc_set_config(context, "mail_pw", "***"); + * dc_configure(context); + * ~~~ + * + * dc_configure() returns immediately, the configuration itself may take a while + * and is done by a job in the imap-thread you've defined above. + * Once done, the #DC_EVENT_CONFIGURE_PROGRESS reports success + * to the event_handler_func() that is also defined above. + * + * The configuration result is saved in the database, + * on subsequent starts it is not needed to call dc_configure() + * (you can check this using dc_is_configured()). + * + * Now you can **send the first message:** + * + * ~~~ + * // use a real testing address here + * uint32_t contact_id = dc_create_contact(context, NULL, "bob@example.org"); + * uint32_t chat_id = dc_create_chat_by_contact_id(context, contact_id); + * + * dc_send_text_msg(context, chat_id, "Hi, here is my first message!"); + * ~~~ + * + * dc_send_text_msg() returns immediately; + * the sending itself is done by a job in the smtp-thread you've defined above. + * If you check the testing address (bob) + * and you should have received a normal email. + * Answer this email in any email program with "Got it!" + * and the imap-thread you've create above will **receive the message**. + * + * You can then **list all messages** of a chat as follow: + * + * ~~~ + * dc_array_t* msglist = dc_get_chat_msgs(context, chat_id, 0, 0); + * for (int i = 0; i < dc_array_get_cnt(msglist); i++) + * { + * uint32_t msg_id = dc_array_get_id(msglist, i); + * dc_msg_t* msg = dc_get_msg(context, msg_id); + * char* text = dc_msg_get_text(msg); + * + * printf("Message %i: %s\n", i+1, text); + * + * free(text); + * dc_msg_unref(msg); + * } + * dc_array_unref(msglist); + * ~~~ + * + * This will output the following two lines: + * + * ~~~ + * Message 1: Hi, here is my first message! + * Message 2: Got it! + * ~~~ + * + * + * ## Class reference + * + * For a class reference, see the "Classes" link atop. + * + * + * ## Further hints + * + * Here are some additional, unsorted hints that may be useful. + * + * - For `get`-functions, you have to unref the return value in some way. + * + * - Strings in function arguments or return values are usually UTF-8 encoded. + * + * - The issue-tracker for the core library is here: + * + * + * The following points are important mainly + * for the authors of the library itself: + * + * - For indentation, use tabs. + * Alignments that are not placed at the beginning of a line + * should be done with spaces. + * + * - For padding between functions, + * classes etc. use 2 empty lines + * + * - Source files are encoded as UTF-8 with Unix line endings + * (a simple `LF`, `0x0A` or `\n`) + * + * If you need further assistance, + * please do not hesitate to contact us + * through the channels shown at https://delta.chat/en/contribute + * + * Please keep in mind, that your derived work + * must respect the Mozilla Public License 2.0 of libdeltachat + * and the respective licenses of the libraries libdeltachat links with. + * + * See you. + */ +/* * + * @class dc_context_t + * + * An object representing a single account. + * + * Each account is linked to an IMAP/SMTP account and uses a separate + * SQLite database for offline functionality and for account-related + * settings. + */ +pub type dc_context_t = _dc_context; +/* ** library-private **********************************************************/ +pub type dc_smtp_t = _dc_smtp; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_smtp { + 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 error: *mut libc::c_char, + pub error_etpan: libc::c_int, +} +pub type dc_jobthread_t = _dc_jobthread; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_jobthread { + 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, + 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, +} +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_imap { + 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 type dc_receive_imf_t = Option< + unsafe extern "C" 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_imap_t = _dc_imap; +pub type dc_precheck_imf_t = Option< + unsafe extern "C" 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< + unsafe extern "C" fn(_: *mut dc_imap_t, _: *const libc::c_char, _: *const libc::c_char) -> (), +>; +pub type dc_get_config_t = Option< + unsafe extern "C" fn( + _: *mut dc_imap_t, + _: *const libc::c_char, + _: *const libc::c_char, + ) -> *mut libc::c_char, +>; +/* ** library-private **********************************************************/ +pub type dc_sqlite3_t = _dc_sqlite3; +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_sqlite3 { + pub cobj: *mut sqlite3, + pub context: *mut dc_context_t, +} +/* * the structure behind dc_array_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_array { + 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, +} +pub type dc_array_t = _dc_array; +// location handling +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_location { + pub location_id: uint32_t, + pub latitude: libc::c_double, + pub longitude: libc::c_double, + pub accuracy: libc::c_double, + pub timestamp: time_t, + pub contact_id: uint32_t, + pub msg_id: uint32_t, + pub chat_id: uint32_t, + pub marker: *mut libc::c_char, +} +/* * + * @class dc_array_t + * + * An object containing a simple array. + * This object is used in several places where functions need to return an array. + * The items of the array are typically IDs. + * To free an array object, use dc_array_unref(). + */ +#[no_mangle] +pub unsafe extern "C" fn dc_array_unref(mut array: *mut dc_array_t) { + if array.is_null() || (*array).magic != 0xa11aai32 as libc::c_uint { + return; + } + if (*array).type_0 == 1i32 { + dc_array_free_ptr(array); + } + free((*array).array as *mut libc::c_void); + (*array).magic = 0i32 as uint32_t; + free(array as *mut libc::c_void); +} +#[no_mangle] +pub unsafe extern "C" fn dc_array_free_ptr(mut array: *mut dc_array_t) { + if array.is_null() || (*array).magic != 0xa11aai32 as libc::c_uint { + return; + } + let mut i: size_t = 0i32 as size_t; + while i < (*array).count { + if (*array).type_0 == 1i32 { + free( + (*(*(*array).array.offset(i as isize) as *mut _dc_location)).marker + as *mut libc::c_void, + ); + } + free(*(*array).array.offset(i as isize) as *mut libc::c_void); + *(*array).array.offset(i as isize) = 0i32 as uintptr_t; + i = i.wrapping_add(1) + } +} +#[no_mangle] +pub unsafe extern "C" 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; + } + if (*array).count == (*array).allocated { + let mut newsize: libc::c_int = (*array) + .allocated + .wrapping_mul(2i32 as libc::c_ulong) + .wrapping_add(10i32 as libc::c_ulong) + as libc::c_int; + (*array).array = realloc( + (*array).array as *mut libc::c_void, + (newsize as libc::c_ulong) + .wrapping_mul(::std::mem::size_of::() as libc::c_ulong), + ) as *mut uintptr_t; + if (*array).array.is_null() { + exit(49i32); + } + (*array).allocated = newsize as size_t + } + *(*array).array.offset((*array).count as isize) = item; + (*array).count = (*array).count.wrapping_add(1); +} +#[no_mangle] +pub unsafe extern "C" fn dc_array_add_id(mut array: *mut dc_array_t, mut item: uint32_t) { + dc_array_add_uint(array, item as uintptr_t); +} +#[no_mangle] +pub unsafe extern "C" 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); +} +#[no_mangle] +pub unsafe extern "C" 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; +} +#[no_mangle] +pub unsafe extern "C" 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); +} +#[no_mangle] +pub unsafe extern "C" 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; + } + 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; +} +#[no_mangle] +pub unsafe extern "C" fn dc_array_get_ptr( + mut array: *const dc_array_t, + mut index: size_t, +) -> *mut libc::c_void { + 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; +} +#[no_mangle] +pub unsafe extern "C" fn dc_array_get_latitude( + mut array: *const dc_array_t, + mut index: size_t, +) -> libc::c_double { + if array.is_null() + || (*array).magic != 0xa11aai32 as libc::c_uint + || index >= (*array).count + || (*array).type_0 != 1i32 + || *(*array).array.offset(index as isize) == 0i32 as libc::c_ulong + { + return 0i32 as libc::c_double; + } + return (*(*(*array).array.offset(index as isize) as *mut _dc_location)).latitude; +} +#[no_mangle] +pub unsafe extern "C" fn dc_array_get_longitude( + mut array: *const dc_array_t, + mut index: size_t, +) -> libc::c_double { + if array.is_null() + || (*array).magic != 0xa11aai32 as libc::c_uint + || index >= (*array).count + || (*array).type_0 != 1i32 + || *(*array).array.offset(index as isize) == 0i32 as libc::c_ulong + { + return 0i32 as libc::c_double; + } + return (*(*(*array).array.offset(index as isize) as *mut _dc_location)).longitude; +} +#[no_mangle] +pub unsafe extern "C" fn dc_array_get_accuracy( + mut array: *const dc_array_t, + mut index: size_t, +) -> libc::c_double { + if array.is_null() + || (*array).magic != 0xa11aai32 as libc::c_uint + || index >= (*array).count + || (*array).type_0 != 1i32 + || *(*array).array.offset(index as isize) == 0i32 as libc::c_ulong + { + return 0i32 as libc::c_double; + } + return (*(*(*array).array.offset(index as isize) as *mut _dc_location)).accuracy; +} +#[no_mangle] +pub unsafe extern "C" 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 + || index >= (*array).count + || (*array).type_0 != 1i32 + || *(*array).array.offset(index as isize) == 0i32 as libc::c_ulong + { + return 0i32 as time_t; + } + return (*(*(*array).array.offset(index as isize) as *mut _dc_location)).timestamp; +} +#[no_mangle] +pub unsafe extern "C" 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 + || index >= (*array).count + || (*array).type_0 != 1i32 + || *(*array).array.offset(index as isize) == 0i32 as libc::c_ulong + { + return 0i32 as uint32_t; + } + return (*(*(*array).array.offset(index as isize) as *mut _dc_location)).chat_id; +} +#[no_mangle] +pub unsafe extern "C" 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 + || index >= (*array).count + || (*array).type_0 != 1i32 + || *(*array).array.offset(index as isize) == 0i32 as libc::c_ulong + { + return 0i32 as uint32_t; + } + return (*(*(*array).array.offset(index as isize) as *mut _dc_location)).contact_id; +} +#[no_mangle] +pub unsafe extern "C" 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 + || index >= (*array).count + || (*array).type_0 != 1i32 + || *(*array).array.offset(index as isize) == 0i32 as libc::c_ulong + { + return 0i32 as uint32_t; + } + return (*(*(*array).array.offset(index as isize) as *mut _dc_location)).msg_id; +} +#[no_mangle] +pub unsafe extern "C" fn dc_array_get_marker( + mut array: *const dc_array_t, + mut index: size_t, +) -> *mut libc::c_char { + if array.is_null() + || (*array).magic != 0xa11aai32 as libc::c_uint + || index >= (*array).count + || (*array).type_0 != 1i32 + || *(*array).array.offset(index as isize) == 0i32 as libc::c_ulong + { + return 0 as *mut libc::c_char; + } + return dc_strdup_keep_null( + (*(*(*array).array.offset(index as isize) as *mut _dc_location)).marker, + ); +} +#[no_mangle] +pub unsafe extern "C" fn dc_array_search_id( + mut array: *const dc_array_t, + mut needle: uint32_t, + mut ret_index: *mut size_t, +) -> libc::c_int { + if array.is_null() || (*array).magic != 0xa11aai32 as libc::c_uint { + return 0i32; + } + 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 libc::c_ulong { + if !ret_index.is_null() { + *ret_index = i + } + return 1i32; + } + i = i.wrapping_add(1) + } + return 0i32; +} +#[no_mangle] +pub unsafe extern "C" 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; +} +#[no_mangle] +pub unsafe extern "C" 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); +} +#[no_mangle] +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; + array = calloc( + 1i32 as libc::c_ulong, + ::std::mem::size_of::() as libc::c_ulong, + ) 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 < 1i32 as libc::c_ulong { + 1i32 as libc::c_ulong + } else { + initsize + }; + (*array).type_0 = type_0; + (*array).array = malloc( + (*array) + .allocated + .wrapping_mul(::std::mem::size_of::() as libc::c_ulong), + ) as *mut uintptr_t; + if (*array).array.is_null() { + exit(48i32); + } + return array; +} +#[no_mangle] +pub unsafe extern "C" 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; +} +#[no_mangle] +pub unsafe extern "C" 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; + 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).count = (*array).count; + memcpy( + (*ret).array as *mut libc::c_void, + (*array).array as *const libc::c_void, + (*array) + .count + .wrapping_mul(::std::mem::size_of::() as libc::c_ulong), + ); + return ret; +} +#[no_mangle] +pub unsafe extern "C" fn dc_array_sort_ids(mut array: *mut dc_array_t) { + if array.is_null() + || (*array).magic != 0xa11aai32 as libc::c_uint + || (*array).count <= 1i32 as libc::c_ulong + { + return; + } + qsort( + (*array).array as *mut libc::c_void, + (*array).count, + ::std::mem::size_of::() as libc::c_ulong, + Some(cmp_intptr_t), + ); +} +unsafe extern "C" fn cmp_intptr_t( + mut p1: *const libc::c_void, + mut p2: *const libc::c_void, +) -> libc::c_int { + let mut v1: uintptr_t = *(p1 as *mut uintptr_t); + let mut v2: uintptr_t = *(p2 as *mut uintptr_t); + return if v1 < v2 { + -1i32 + } else if v1 > v2 { + 1i32 + } else { + 0i32 + }; +} +#[no_mangle] +pub unsafe extern "C" fn dc_array_sort_strings(mut array: *mut dc_array_t) { + if array.is_null() + || (*array).magic != 0xa11aai32 as libc::c_uint + || (*array).count <= 1i32 as libc::c_ulong + { + return; + } + qsort( + (*array).array as *mut libc::c_void, + (*array).count, + ::std::mem::size_of::<*mut libc::c_char>() as libc::c_ulong, + 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); +} +#[no_mangle] +pub unsafe extern "C" 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; + 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); + } + let mut i: libc::c_int = 0; + ret = malloc( + (*array) + .count + .wrapping_mul((11i32 as libc::c_ulong).wrapping_add(strlen(sep))) + .wrapping_add(1i32 as libc::c_ulong), + ) as *mut libc::c_char; + if ret.is_null() { + exit(35i32); + } + *ret.offset(0isize) = 0i32 as libc::c_char; + i = 0i32; + while (i as libc::c_ulong) < (*array).count { + if 0 != i { + strcat(ret, sep); + } + sprintf( + &mut *ret.offset(strlen(ret) as isize) as *mut libc::c_char, + b"%lu\x00" as *const u8 as *const libc::c_char, + *(*array).array.offset(i as isize) as libc::c_ulong, + ); + i += 1 + } + return ret; +} +#[no_mangle] +pub unsafe extern "C" 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 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; + ret = malloc( + (cnt as libc::c_ulong) + .wrapping_mul((11i32 as libc::c_ulong).wrapping_add(strlen(sep))) + .wrapping_add(1i32 as libc::c_ulong), + ) as *mut libc::c_char; + if ret.is_null() { + exit(35i32); + } + *ret.offset(0isize) = 0i32 as libc::c_char; + i = 0i32; + while i < cnt { + if 0 != i { + strcat(ret, sep); + } + sprintf( + &mut *ret.offset(strlen(ret) as isize) as *mut libc::c_char, + b"%lu\x00" as *const u8 as *const libc::c_char, + *arr.offset(i as isize) as libc::c_ulong, + ); + i += 1 + } + return ret; +} diff --git a/src/dc_chat.rs b/src/dc_chat.rs new file mode 100644 index 000000000..6a3189802 --- /dev/null +++ b/src/dc_chat.rs @@ -0,0 +1,3697 @@ +use c2rust_bitfields::BitfieldStruct; +use libc; +extern "C" { + pub type mailstream_cancel; + pub type sqlite3; + pub type sqlite3_stmt; + #[no_mangle] + fn __assert_rtn( + _: *const libc::c_char, + _: *const libc::c_char, + _: libc::c_int, + _: *const libc::c_char, + ) -> !; + #[no_mangle] + fn calloc(_: libc::c_ulong, _: libc::c_ulong) -> *mut libc::c_void; + #[no_mangle] + fn free(_: *mut libc::c_void); + #[no_mangle] + fn exit(_: libc::c_int) -> !; + #[no_mangle] + fn strtol(_: *const libc::c_char, _: *mut *mut libc::c_char, _: libc::c_int) -> libc::c_long; + #[no_mangle] + fn strchr(_: *const libc::c_char, _: libc::c_int) -> *mut libc::c_char; + #[no_mangle] + fn strcmp(_: *const libc::c_char, _: *const libc::c_char) -> libc::c_int; + #[no_mangle] + fn strcasecmp(_: *const libc::c_char, _: *const libc::c_char) -> libc::c_int; + #[no_mangle] + fn time(_: *mut time_t) -> time_t; + #[no_mangle] + fn carray_new(initsize: libc::c_uint) -> *mut carray; + #[no_mangle] + fn carray_add( + array: *mut carray, + data: *mut libc::c_void, + indx: *mut libc::c_uint, + ) -> libc::c_int; + #[no_mangle] + fn carray_free(array: *mut carray); + /* library-private */ + #[no_mangle] + fn dc_param_new() -> *mut dc_param_t; + #[no_mangle] + fn dc_param_unref(_: *mut dc_param_t); + #[no_mangle] + fn dc_param_set_packed(_: *mut dc_param_t, _: *const libc::c_char); + #[no_mangle] + fn dc_msg_new_untyped(_: *mut dc_context_t) -> *mut dc_msg_t; + #[no_mangle] + fn dc_msg_unref(_: *mut dc_msg_t); + #[no_mangle] + fn dc_scaleup_contact_origin(_: *mut dc_context_t, contact_id: uint32_t, origin: libc::c_int); + #[no_mangle] + fn sqlite3_finalize(pStmt: *mut sqlite3_stmt) -> libc::c_int; + #[no_mangle] + fn sqlite3_step(_: *mut sqlite3_stmt) -> libc::c_int; + #[no_mangle] + fn sqlite3_bind_int(_: *mut sqlite3_stmt, _: libc::c_int, _: libc::c_int) -> libc::c_int; + /* tools, these functions are compatible to the corresponding sqlite3_* functions */ + #[no_mangle] + fn dc_sqlite3_prepare(_: *mut dc_sqlite3_t, sql: *const libc::c_char) -> *mut sqlite3_stmt; + /* Return the string with the given ID by calling DC_EVENT_GET_STRING. + The result must be free()'d! */ + #[no_mangle] + fn dc_stock_str(_: *mut dc_context_t, id: libc::c_int) -> *mut libc::c_char; + /* for msgs and jobs */ + /* for msgs */ + /* for msgs */ + /* for msgs */ + /* for msgs */ + /* for msgs: incoming: message is encryoted, outgoing: guarantee E2EE or the message is not send */ + /* for msgs: decrypted with validation errors or without mutual set, if neither 'c' nor 'e' are preset, the messages is only transport encrypted */ + /* for msgs: force unencrypted message, either DC_FP_ADD_AUTOCRYPT_HEADER (1), DC_FP_NO_AUTOCRYPT_HEADER (2) or 0 */ + /* for msgs: an incoming message which requestes a MDN (aka read receipt) */ + /* for msgs */ + /* for msgs */ + /* for msgs */ + /* for msgs */ + /* for msgs */ + /* for msgs */ + /* for msgs */ + /* for msgs in PREPARING: space-separated list of message IDs of forwarded copies */ + /* for jobs */ + /* for jobs */ + /* for jobs */ + /* for jobs: space-separated list of message recipients */ + /* for groups */ + /* for groups and contacts */ + /* for chats */ + // values for DC_PARAM_FORCE_PLAINTEXT + /* user functions */ + #[no_mangle] + fn dc_param_exists(_: *mut dc_param_t, key: libc::c_int) -> libc::c_int; + // Context functions to work with chatlist + #[no_mangle] + fn dc_get_archived_cnt(_: *mut dc_context_t) -> libc::c_int; + #[no_mangle] + fn dc_mprintf(format: *const libc::c_char, _: ...) -> *mut libc::c_char; + #[no_mangle] + fn sqlite3_column_int64(_: *mut sqlite3_stmt, iCol: libc::c_int) -> sqlite3_int64; + #[no_mangle] + fn sqlite3_column_int(_: *mut sqlite3_stmt, iCol: libc::c_int) -> libc::c_int; + #[no_mangle] + fn sqlite3_column_text(_: *mut sqlite3_stmt, iCol: libc::c_int) -> *const libc::c_uchar; + /* string tools */ + #[no_mangle] + fn dc_strdup(_: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn dc_msg_load_from_db(_: *mut dc_msg_t, _: *mut dc_context_t, id: uint32_t) -> libc::c_int; + #[no_mangle] + fn dc_contact_unref(_: *mut dc_contact_t); + #[no_mangle] + fn sqlite3_free(_: *mut libc::c_void); + #[no_mangle] + fn sqlite3_mprintf(_: *const libc::c_char, _: ...) -> *mut libc::c_char; + #[no_mangle] + fn dc_sqlite3_get_rowid( + _: *mut dc_sqlite3_t, + table: *const libc::c_char, + field: *const libc::c_char, + value: *const libc::c_char, + ) -> uint32_t; + /* From: of incoming messages of unknown sender */ + /* Cc: of incoming messages of unknown sender */ + /* To: of incoming messages of unknown sender */ + /* address scanned but not verified */ + /* Reply-To: of incoming message of known sender */ + /* Cc: of incoming message of known sender */ + /* additional To:'s of incoming message of known sender */ + /* a chat was manually created for this user, but no message yet sent */ + /* message sent by us */ + /* message sent by us */ + /* message sent by us */ + /* internal use */ + /* address is in our address book */ + /* set on Alice's side for contacts like Bob that have scanned the QR code offered by her. Only means the contact has once been established using the "securejoin" procedure in the past, getting the current key verification status requires calling dc_contact_is_verified() ! */ + /* set on Bob's side for contacts scanned and verified from a QR code. Only means the contact has once been established using the "securejoin" procedure in the past, getting the current key verification status requires calling dc_contact_is_verified() ! */ + /* contact added mannually by dc_create_contact(), this should be the largets origin as otherwise the user cannot modify the names */ + /* 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 */ + #[no_mangle] + fn dc_contact_load_from_db( + _: *mut dc_contact_t, + _: *mut dc_sqlite3_t, + contact_id: uint32_t, + ) -> libc::c_int; + /* * + * @class dc_contact_t + * + * An object representing a single contact in memory. + * The contact object is not updated. + * If you want an update, you have to recreate the object. + * + * The library makes sure + * only to use names _authorized_ by the contact in `To:` or `Cc:`. + * _Given-names _as "Daddy" or "Honey" are not used there. + * For this purpose, internally, two names are tracked - + * authorized-name and given-name. + * By default, these names are equal, + * but functions working with contact names + * (eg. dc_contact_get_name(), dc_contact_get_display_name(), + * dc_contact_get_name_n_addr(), dc_contact_get_first_name(), + * dc_create_contact() or dc_add_address_book()) + * only affect the given-name. + */ + #[no_mangle] + fn dc_contact_new(_: *mut dc_context_t) -> *mut dc_contact_t; + #[no_mangle] + fn dc_log_warning(_: *mut dc_context_t, data1: libc::c_int, msg: *const libc::c_char, _: ...); + #[no_mangle] + fn dc_real_contact_exists(_: *mut dc_context_t, contact_id: uint32_t) -> libc::c_int; + #[no_mangle] + fn dc_create_smeared_timestamp(_: *mut dc_context_t) -> time_t; + #[no_mangle] + fn dc_log_error(_: *mut dc_context_t, data1: libc::c_int, msg: *const libc::c_char, _: ...); + #[no_mangle] + fn sqlite3_bind_text( + _: *mut sqlite3_stmt, + _: libc::c_int, + _: *const libc::c_char, + _: libc::c_int, + _: Option ()>, + ) -> libc::c_int; + #[no_mangle] + fn sqlite3_bind_int64(_: *mut sqlite3_stmt, _: libc::c_int, _: sqlite3_int64) -> libc::c_int; + #[no_mangle] + fn dc_param_set(_: *mut dc_param_t, key: libc::c_int, value: *const libc::c_char); + #[no_mangle] + fn dc_param_set_int(_: *mut dc_param_t, key: libc::c_int, value: int32_t); + #[no_mangle] + fn dc_log_info(_: *mut dc_context_t, data1: libc::c_int, msg: *const libc::c_char, _: ...); + #[no_mangle] + fn sqlite3_column_type(_: *mut sqlite3_stmt, iCol: libc::c_int) -> libc::c_int; + #[no_mangle] + fn dc_param_get_int(_: *const dc_param_t, key: libc::c_int, def: int32_t) -> int32_t; + #[no_mangle] + fn dc_sqlite3_get_config_int( + _: *mut dc_sqlite3_t, + key: *const libc::c_char, + def: int32_t, + ) -> int32_t; + #[no_mangle] + fn dc_sqlite3_get_config( + _: *mut dc_sqlite3_t, + key: *const libc::c_char, + def: *const libc::c_char, + ) -> *mut libc::c_char; + #[no_mangle] + fn dc_create_outgoing_rfc724_mid( + grpid: *const libc::c_char, + addr: *const libc::c_char, + ) -> *mut libc::c_char; + #[no_mangle] + fn dc_log_event( + _: *mut dc_context_t, + event_code: libc::c_int, + data1: libc::c_int, + msg: *const libc::c_char, + _: ... + ); + #[no_mangle] + fn dc_msg_guess_msgtype_from_suffix( + pathNfilename: *const libc::c_char, + ret_msgtype: *mut libc::c_int, + ret_mime: *mut *mut libc::c_char, + ); + #[no_mangle] + fn dc_make_rel_and_copy( + _: *mut dc_context_t, + pathNfilename: *mut *mut libc::c_char, + ) -> libc::c_int; + #[no_mangle] + fn dc_is_blobdir_path(_: *mut dc_context_t, path: *const libc::c_char) -> libc::c_int; + #[no_mangle] + fn dc_param_get( + _: *const dc_param_t, + key: libc::c_int, + def: *const libc::c_char, + ) -> *mut libc::c_char; + #[no_mangle] + fn dc_msg_save_param_to_disk(_: *mut dc_msg_t); + #[no_mangle] + fn dc_get_msg(_: *mut dc_context_t, msg_id: uint32_t) -> *mut dc_msg_t; + #[no_mangle] + fn dc_job_send_msg(_: *mut dc_context_t, msg_id: uint32_t) -> libc::c_int; + #[no_mangle] + fn dc_update_msg_state(_: *mut dc_context_t, msg_id: uint32_t, state: libc::c_int); + /* * + * @class dc_msg_t + * + * An object representing a single message in memory. + * The message object is not updated. + * If you want an update, you have to recreate the object. + */ + // 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() + #[no_mangle] + fn dc_msg_new(_: *mut dc_context_t, viewtype: libc::c_int) -> *mut dc_msg_t; + #[no_mangle] + fn dc_msg_is_increation(_: *const dc_msg_t) -> libc::c_int; + #[no_mangle] + fn dc_delete_msg_from_db(_: *mut dc_context_t, _: uint32_t); + #[no_mangle] + fn dc_array_new(_: *mut dc_context_t, initsize: size_t) -> *mut dc_array_t; + /* * + * @class dc_array_t + * + * An object containing a simple array. + * This object is used in several places where functions need to return an array. + * The items of the array are typically IDs. + * To free an array object, use dc_array_unref(). + */ + #[no_mangle] + fn dc_array_unref(_: *mut dc_array_t); + #[no_mangle] + fn dc_array_add_id(_: *mut dc_array_t, _: uint32_t); + #[no_mangle] + fn dc_gm2local_offset() -> libc::c_long; + #[no_mangle] + fn dc_array_get_id(_: *const dc_array_t, index: size_t) -> uint32_t; + #[no_mangle] + fn dc_array_get_cnt(_: *const dc_array_t) -> size_t; + #[no_mangle] + fn dc_sqlite3_rollback(_: *mut dc_sqlite3_t); + #[no_mangle] + fn dc_job_add( + _: *mut dc_context_t, + action: libc::c_int, + foreign_id: libc::c_int, + param: *const libc::c_char, + delay: libc::c_int, + ); + #[no_mangle] + fn dc_job_kill_action(_: *mut dc_context_t, action: libc::c_int); + #[no_mangle] + fn dc_sqlite3_commit(_: *mut dc_sqlite3_t); + #[no_mangle] + fn dc_sqlite3_execute(_: *mut dc_sqlite3_t, sql: *const libc::c_char) -> libc::c_int; + #[no_mangle] + fn dc_sqlite3_begin_transaction(_: *mut dc_sqlite3_t); + #[no_mangle] + fn dc_msg_set_text(_: *mut dc_msg_t, text: *const libc::c_char); + /* Message-ID tools */ + #[no_mangle] + fn dc_create_id() -> *mut libc::c_char; + /* Replaces the first `%1$s` in the given String-ID by the given value. + The result must be free()'d! */ + #[no_mangle] + fn dc_stock_str_repl_string( + _: *mut dc_context_t, + id: libc::c_int, + value: *const libc::c_char, + ) -> *mut libc::c_char; + #[no_mangle] + fn dc_get_contact(_: *mut dc_context_t, contact_id: uint32_t) -> *mut dc_contact_t; + /* Misc. */ + #[no_mangle] + fn dc_stock_system_msg( + context: *mut dc_context_t, + str_id: libc::c_int, + param1: *const libc::c_char, + param2: *const libc::c_char, + from_id: uint32_t, + ) -> *mut libc::c_char; + #[no_mangle] + fn dc_contact_is_verified(_: *mut dc_contact_t) -> libc::c_int; + #[no_mangle] + fn dc_arr_to_string(arr: *const uint32_t, cnt: libc::c_int) -> *mut libc::c_char; + #[no_mangle] + fn dc_create_smeared_timestamps(_: *mut dc_context_t, count: libc::c_int) -> time_t; + #[no_mangle] + fn dc_stock_str_repl_int( + _: *mut dc_context_t, + id: libc::c_int, + value: libc::c_int, + ) -> *mut libc::c_char; + #[no_mangle] + fn dc_contact_get_profile_image(_: *const dc_contact_t) -> *mut libc::c_char; + #[no_mangle] + fn dc_get_abs_path( + _: *mut dc_context_t, + pathNfilename: *const libc::c_char, + ) -> *mut libc::c_char; + #[no_mangle] + fn dc_str_to_color(_: *const libc::c_char) -> libc::c_int; +} +pub type __darwin_size_t = libc::c_ulong; +pub type __darwin_ssize_t = libc::c_long; +pub type __darwin_time_t = libc::c_long; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_cond_t { + pub __sig: libc::c_long, + pub __opaque: [libc::c_char; 40], +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_mutex_t { + pub __sig: libc::c_long, + pub __opaque: [libc::c_char; 56], +} +pub type __darwin_pthread_cond_t = _opaque_pthread_cond_t; +pub type __darwin_pthread_mutex_t = _opaque_pthread_mutex_t; +pub type int32_t = libc::c_int; +pub type uintptr_t = libc::c_ulong; +pub type size_t = __darwin_size_t; +pub type uint8_t = libc::c_uchar; +pub type uint32_t = libc::c_uint; +pub type ssize_t = __darwin_ssize_t; +pub type time_t = __darwin_time_t; +pub type pthread_cond_t = __darwin_pthread_cond_t; +pub type pthread_mutex_t = __darwin_pthread_mutex_t; +#[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; +#[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) -> (); +#[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; +#[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, + 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 { + 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_capability_data { + pub cap_list: *mut clist, +} +#[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_0, + 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_0 { + 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 extern "C" 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_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, +} +#[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_1, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed_1 { + pub ft_fetch_att: *mut mailimap_fetch_att, + pub ft_fetch_att_list: *mut clist, +} +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 unnamed_2 { + 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, +} +/* define DC_USE_RPGP to enable use of rPGP instead of netpgp where available; +preferrably, this should be done in the project configuration currently */ +//#define DC_USE_RPGP 1 +/* Includes that are used frequently. This file may also be used to create predefined headers. */ +/* * Structure behind dc_context_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_context { + pub magic: uint32_t, + pub userdata: *mut libc::c_void, + pub dbfile: *mut libc::c_char, + pub blobdir: *mut libc::c_char, + pub sql: *mut dc_sqlite3_t, + pub inbox: *mut dc_imap_t, + pub inboxidle_condmutex: pthread_mutex_t, + pub perform_inbox_jobs_needed: libc::c_int, + pub probe_imap_network: libc::c_int, + pub sentbox_thread: dc_jobthread_t, + pub mvbox_thread: dc_jobthread_t, + pub smtp: *mut dc_smtp_t, + pub smtpidle_cond: pthread_cond_t, + pub smtpidle_condmutex: pthread_mutex_t, + pub smtpidle_condflag: libc::c_int, + pub smtp_suspended: libc::c_int, + pub smtp_doing_jobs: libc::c_int, + pub perform_smtp_jobs_needed: libc::c_int, + pub probe_smtp_network: libc::c_int, + pub oauth2_critical: pthread_mutex_t, + 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 type dc_lot_t = _dc_lot; +/* * Structure behind dc_lot_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_lot { + pub magic: uint32_t, + pub text1_meaning: libc::c_int, + pub text1: *mut libc::c_char, + pub text2: *mut libc::c_char, + pub timestamp: time_t, + pub state: libc::c_int, + pub id: uint32_t, + pub fingerprint: *mut libc::c_char, + pub invitenumber: *mut libc::c_char, + pub auth: *mut libc::c_char, +} +/* * + * 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 = Option< + unsafe extern "C" fn( + _: *mut dc_context_t, + _: libc::c_int, + _: uintptr_t, + _: uintptr_t, + ) -> uintptr_t, +>; +/* * + * @mainpage Getting started + * + * This document describes how to handle the Delta Chat core library. + * For general information about Delta Chat itself, + * see and . + * + * Let's start. + * + * First of all, you have to **define an event-handler-function** + * that is called by the library on specific events + * (eg. when the configuration is done or when fresh messages arrive). + * With this function you can create a Delta Chat context then: + * + * ~~~ + * #include + * + * uintptr_t event_handler_func(dc_context_t* context, int event, + * uintptr_t data1, uintptr_t data2) + * { + * return 0; // for unhandled events, it is always safe to return 0 + * } + * + * dc_context_t* context = dc_context_new(event_handler_func, NULL, NULL); + * ~~~ + * + * After that, you should make sure, + * sending and receiving jobs are processed as needed. + * For this purpose, you have to **create two threads:** + * + * ~~~ + * #include + * + * void* imap_thread_func(void* context) + * { + * while (true) { + * dc_perform_imap_jobs(context); + * dc_perform_imap_fetch(context); + * dc_perform_imap_idle(context); + * } + * } + * + * void* smtp_thread_func(void* context) + * { + * while (true) { + * dc_perform_smtp_jobs(context); + * dc_perform_smtp_idle(context); + * } + * } + * + * static pthread_t imap_thread, smtp_thread; + * pthread_create(&imap_thread, NULL, imap_thread_func, context); + * pthread_create(&smtp_thread, NULL, smtp_thread_func, context); + * ~~~ + * + * The example above uses "pthreads", + * however, you can also use anything else for thread handling. + * NB: The deltachat-core library itself does not create any threads on its own, + * however, functions, unless stated otherwise, are thread-safe. + * + * After that you can **define and open a database.** + * The database is a normal sqlite-file and is created as needed: + * + * ~~~ + * dc_open(context, "example.db", NULL); + * ~~~ + * + * Now you can **configure the context:** + * + * ~~~ + * // use some real test credentials here + * dc_set_config(context, "addr", "alice@example.org"); + * dc_set_config(context, "mail_pw", "***"); + * dc_configure(context); + * ~~~ + * + * dc_configure() returns immediately, the configuration itself may take a while + * and is done by a job in the imap-thread you've defined above. + * Once done, the #DC_EVENT_CONFIGURE_PROGRESS reports success + * to the event_handler_func() that is also defined above. + * + * The configuration result is saved in the database, + * on subsequent starts it is not needed to call dc_configure() + * (you can check this using dc_is_configured()). + * + * Now you can **send the first message:** + * + * ~~~ + * // use a real testing address here + * uint32_t contact_id = dc_create_contact(context, NULL, "bob@example.org"); + * uint32_t chat_id = dc_create_chat_by_contact_id(context, contact_id); + * + * dc_send_text_msg(context, chat_id, "Hi, here is my first message!"); + * ~~~ + * + * dc_send_text_msg() returns immediately; + * the sending itself is done by a job in the smtp-thread you've defined above. + * If you check the testing address (bob) + * and you should have received a normal email. + * Answer this email in any email program with "Got it!" + * and the imap-thread you've create above will **receive the message**. + * + * You can then **list all messages** of a chat as follow: + * + * ~~~ + * dc_array_t* msglist = dc_get_chat_msgs(context, chat_id, 0, 0); + * for (int i = 0; i < dc_array_get_cnt(msglist); i++) + * { + * uint32_t msg_id = dc_array_get_id(msglist, i); + * dc_msg_t* msg = dc_get_msg(context, msg_id); + * char* text = dc_msg_get_text(msg); + * + * printf("Message %i: %s\n", i+1, text); + * + * free(text); + * dc_msg_unref(msg); + * } + * dc_array_unref(msglist); + * ~~~ + * + * This will output the following two lines: + * + * ~~~ + * Message 1: Hi, here is my first message! + * Message 2: Got it! + * ~~~ + * + * + * ## Class reference + * + * For a class reference, see the "Classes" link atop. + * + * + * ## Further hints + * + * Here are some additional, unsorted hints that may be useful. + * + * - For `get`-functions, you have to unref the return value in some way. + * + * - Strings in function arguments or return values are usually UTF-8 encoded. + * + * - The issue-tracker for the core library is here: + * + * + * The following points are important mainly + * for the authors of the library itself: + * + * - For indentation, use tabs. + * Alignments that are not placed at the beginning of a line + * should be done with spaces. + * + * - For padding between functions, + * classes etc. use 2 empty lines + * + * - Source files are encoded as UTF-8 with Unix line endings + * (a simple `LF`, `0x0A` or `\n`) + * + * If you need further assistance, + * please do not hesitate to contact us + * through the channels shown at https://delta.chat/en/contribute + * + * Please keep in mind, that your derived work + * must respect the Mozilla Public License 2.0 of libdeltachat + * and the respective licenses of the libraries libdeltachat links with. + * + * See you. + */ +/* * + * @class dc_context_t + * + * An object representing a single account. + * + * Each account is linked to an IMAP/SMTP account and uses a separate + * SQLite database for offline functionality and for account-related + * settings. + */ +pub type dc_context_t = _dc_context; +/* ** library-private **********************************************************/ +pub type dc_smtp_t = _dc_smtp; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_smtp { + 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 error: *mut libc::c_char, + pub error_etpan: libc::c_int, +} +pub type dc_jobthread_t = _dc_jobthread; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_jobthread { + 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, + 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, +} +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_imap { + 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 type dc_receive_imf_t = Option< + unsafe extern "C" 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_imap_t = _dc_imap; +pub type dc_precheck_imf_t = Option< + unsafe extern "C" 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< + unsafe extern "C" fn(_: *mut dc_imap_t, _: *const libc::c_char, _: *const libc::c_char) -> (), +>; +pub type dc_get_config_t = Option< + unsafe extern "C" fn( + _: *mut dc_imap_t, + _: *const libc::c_char, + _: *const libc::c_char, + ) -> *mut libc::c_char, +>; +/* ** library-private **********************************************************/ +pub type dc_sqlite3_t = _dc_sqlite3; +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_sqlite3 { + pub cobj: *mut sqlite3, + pub context: *mut dc_context_t, +} +/* * the structure behind dc_array_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_array { + 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, +} +pub type dc_array_t = _dc_array; +/* values for the chats.blocked database field */ +/* * the structure behind dc_chat_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_chat { + 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 grpid: *mut libc::c_char, + pub blocked: libc::c_int, + pub param: *mut dc_param_t, + pub gossiped_timestamp: time_t, + pub is_sending_locations: libc::c_int, +} +pub type dc_param_t = _dc_param; +/* * + * @class dc_param_t + * + * An object for handling key=value parameter lists; for the key, curently only + * a single character is allowed. + * + * The object is used eg. by dc_chat_t or dc_msg_t, for readable paramter names, + * these classes define some DC_PARAM_* constantats. + * + * Only for library-internal use. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_param { + pub packed: *mut libc::c_char, +} +pub type dc_chat_t = _dc_chat; +/* * the structure behind dc_msg_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_msg { + pub magic: uint32_t, + pub id: uint32_t, + pub from_id: uint32_t, + pub to_id: uint32_t, + pub chat_id: uint32_t, + pub move_state: dc_move_state_t, + pub type_0: libc::c_int, + pub state: libc::c_int, + pub hidden: libc::c_int, + pub timestamp_sort: time_t, + pub timestamp_sent: time_t, + pub timestamp_rcvd: time_t, + pub text: *mut libc::c_char, + pub context: *mut 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, + pub server_uid: uint32_t, + pub is_dc_message: libc::c_int, + pub starred: libc::c_int, + pub chat_blocked: libc::c_int, + pub location_id: uint32_t, + pub param: *mut dc_param_t, +} +pub type dc_move_state_t = libc::c_uint; +pub const DC_MOVE_STATE_MOVING: dc_move_state_t = 3; +pub const DC_MOVE_STATE_STAY: dc_move_state_t = 2; +pub const DC_MOVE_STATE_PENDING: dc_move_state_t = 1; +pub const DC_MOVE_STATE_UNDEFINED: dc_move_state_t = 0; +pub type dc_msg_t = _dc_msg; +/* * the structure behind dc_contact_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_contact { + pub magic: uint32_t, + pub context: *mut dc_context_t, + pub id: uint32_t, + pub name: *mut libc::c_char, + pub authname: *mut libc::c_char, + pub addr: *mut libc::c_char, + pub blocked: libc::c_int, + pub origin: libc::c_int, +} +pub type dc_contact_t = _dc_contact; +pub type sqlite3_int64 = sqlite_int64; +pub type sqlite_int64 = libc::c_longlong; +pub type sqlite3_destructor_type = Option ()>; +#[inline] +unsafe extern "C" fn carray_count(mut array: *mut carray) -> libc::c_uint { + return (*array).len; +} +#[inline] +unsafe extern "C" fn carray_get( + mut array: *mut carray, + mut indx: libc::c_uint, +) -> *mut libc::c_void { + return *(*array).array.offset(indx as isize); +} +// handle chats +#[no_mangle] +pub unsafe extern "C" fn dc_create_chat_by_msg_id( + mut context: *mut 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); + } + } + dc_msg_unref(msg); + dc_chat_unref(chat); + if 0 != send_event { + (*context).cb.expect("non-null function pointer")( + context, + 2000i32, + 0i32 as uintptr_t, + 0i32 as uintptr_t, + ); + } + return chat_id; +} +/* * + * @class dc_chat_t + * + * An object representing a single chat in memory. + * Chat objects are created using eg. dc_get_chat() + * and are not updated on database changes; + * if you want an update, you have to recreate the object. + */ +// virtual chat showing all messages belonging to chats flagged with chats.blocked=2 +// messages that should be deleted get this chat_id; the messages are deleted from the working thread later then. This is also needed as rfc724_mid should be preset as long as the message is not deleted on the server (otherwise it is downloaded again) +// a message is just in creation but not yet assigned to a chat (eg. we may need the message ID to set up blobs; this avoids unready message to be sent and shown) +// virtual chat showing all messages flagged with msgs.starred=2 +// only an indicator in a chatlist +// only an indicator in a chatlist +// larger chat IDs are "real" chats, their messages are "real" messages. +#[no_mangle] +pub unsafe extern "C" 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( + 1i32 as libc::c_ulong, + ::std::mem::size_of::() as libc::c_ulong, + ) as *mut dc_chat_t; + chat.is_null() + } { + exit(14i32); + } + (*chat).magic = 0xc4a7c4a7u32; + (*chat).context = context; + (*chat).type_0 = 0i32; + (*chat).param = dc_param_new(); + return chat; +} +#[no_mangle] +pub unsafe extern "C" fn dc_chat_unref(mut chat: *mut dc_chat_t) { + if chat.is_null() || (*chat).magic != 0xc4a7c4a7u32 { + return; + } + dc_chat_empty(chat); + dc_param_unref((*chat).param); + (*chat).magic = 0i32 as uint32_t; + free(chat as *mut libc::c_void); +} +#[no_mangle] +pub unsafe extern "C" fn dc_chat_empty(mut chat: *mut dc_chat_t) { + if chat.is_null() || (*chat).magic != 0xc4a7c4a7u32 { + return; + } + free((*chat).name as *mut libc::c_void); + (*chat).name = 0 as *mut libc::c_char; + (*chat).type_0 = 0i32; + (*chat).id = 0i32 as uint32_t; + free((*chat).grpid as *mut libc::c_void); + (*chat).grpid = 0 as *mut libc::c_char; + (*chat).blocked = 0i32; + (*chat).gossiped_timestamp = 0i32 as time_t; + dc_param_set_packed((*chat).param, 0 as *const libc::c_char); +} +#[no_mangle] +pub unsafe extern "C" fn dc_unblock_chat(mut context: *mut dc_context_t, mut chat_id: uint32_t) { + dc_block_chat(context, chat_id, 0i32); +} +#[no_mangle] +pub unsafe extern "C" fn dc_block_chat( + mut context: *mut 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; + } + stmt = dc_sqlite3_prepare( + (*context).sql, + b"UPDATE chats SET blocked=? WHERE id=?;\x00" as *const u8 as *const libc::c_char, + ); + sqlite3_bind_int(stmt, 1i32, new_blocking); + sqlite3_bind_int(stmt, 2i32, chat_id as libc::c_int); + sqlite3_step(stmt); + sqlite3_finalize(stmt); +} +#[no_mangle] +pub unsafe extern "C" 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); + if !(sqlite3_step(stmt) != 100i32) { + if !(0 == set_from_stmt(chat, stmt)) { + success = 1i32 + } + } + } + sqlite3_finalize(stmt); + return success; +} +unsafe extern "C" 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() { + return 0i32; + } + dc_chat_empty(chat); + let fresh0 = row_offset; + row_offset = row_offset + 1; + (*chat).id = sqlite3_column_int(row, fresh0) as uint32_t; + let fresh1 = row_offset; + row_offset = row_offset + 1; + (*chat).type_0 = sqlite3_column_int(row, fresh1); + let fresh2 = row_offset; + row_offset = row_offset + 1; + (*chat).name = dc_strdup(sqlite3_column_text(row, fresh2) as *mut libc::c_char); + let fresh3 = row_offset; + row_offset = row_offset + 1; + (*chat).grpid = dc_strdup(sqlite3_column_text(row, fresh3) as *mut libc::c_char); + let fresh4 = row_offset; + row_offset = row_offset + 1; + dc_param_set_packed( + (*chat).param, + sqlite3_column_text(row, fresh4) as *mut libc::c_char, + ); + let fresh5 = row_offset; + row_offset = row_offset + 1; + (*chat).archived = sqlite3_column_int(row, fresh5); + let fresh6 = row_offset; + row_offset = row_offset + 1; + (*chat).blocked = sqlite3_column_int(row, fresh6); + let fresh7 = row_offset; + row_offset = row_offset + 1; + (*chat).gossiped_timestamp = sqlite3_column_int64(row, fresh7) as time_t; + let fresh8 = row_offset; + row_offset = row_offset + 1; + (*chat).is_sending_locations = (sqlite3_column_int64(row, fresh8) + > time(0 as *mut time_t) as libc::c_longlong) + as libc::c_int; + if (*chat).id == 1i32 as libc::c_uint { + free((*chat).name as *mut libc::c_void); + (*chat).name = dc_stock_str((*chat).context, 8i32) + } else if (*chat).id == 6i32 as libc::c_uint { + free((*chat).name as *mut libc::c_void); + let mut tempname: *mut libc::c_char = dc_stock_str((*chat).context, 40i32); + (*chat).name = dc_mprintf( + b"%s (%i)\x00" as *const u8 as *const libc::c_char, + tempname, + dc_get_archived_cnt((*chat).context), + ); + free(tempname as *mut libc::c_void); + } else if (*chat).id == 5i32 as libc::c_uint { + free((*chat).name as *mut libc::c_void); + (*chat).name = dc_stock_str((*chat).context, 41i32) + } else if 0 != dc_param_exists((*chat).param, 'K' as i32) { + free((*chat).name as *mut libc::c_void); + (*chat).name = dc_stock_str((*chat).context, 2i32) + } + return row_offset; +} +#[no_mangle] +pub unsafe extern "C" fn dc_create_chat_by_contact_id( + mut context: *mut 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 { + dc_unblock_chat(context, chat_id); + send_event = 1i32 + } + } else if 0i32 == dc_real_contact_exists(context, contact_id) + && contact_id != 1i32 as libc::c_uint + { + dc_log_warning( + context, + 0i32, + b"Cannot create chat, contact %i does not exist.\x00" as *const u8 + as *const libc::c_char, + contact_id as libc::c_int, + ); + } else { + dc_create_or_lookup_nchat_by_contact_id( + context, + contact_id, + 0i32, + &mut chat_id, + 0 as *mut libc::c_int, + ); + if 0 != chat_id { + send_event = 1i32 + } + dc_scaleup_contact_origin(context, contact_id, 0x800i32); + } + if 0 != send_event { + (*context).cb.expect("non-null function pointer")( + context, + 2000i32, + 0i32 as uintptr_t, + 0i32 as uintptr_t, + ); + } + return chat_id; +} +#[no_mangle] +pub unsafe extern "C" fn dc_create_or_lookup_nchat_by_contact_id( + mut context: *mut dc_context_t, + mut contact_id: uint32_t, + mut create_blocked: libc::c_int, + mut ret_chat_id: *mut uint32_t, + mut ret_chat_blocked: *mut libc::c_int, +) { + 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 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() { + *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() + { + return; + } + if contact_id == 0i32 as libc::c_uint { + return; + } + dc_lookup_real_nchat_by_contact_id(context, contact_id, &mut chat_id, &mut chat_blocked); + if chat_id != 0i32 as libc::c_uint { + if !ret_chat_id.is_null() { + *ret_chat_id = chat_id + } + if !ret_chat_blocked.is_null() { + *ret_chat_blocked = chat_blocked + } + return; + } + contact = dc_contact_new(context); + if !(0 == dc_contact_load_from_db(contact, (*context).sql, contact_id)) { + chat_name = + if !(*contact).name.is_null() && 0 != *(*contact).name.offset(0isize) as libc::c_int { + (*contact).name + } else { + (*contact).addr + }; + q = sqlite3_mprintf( + b"INSERT INTO chats (type, name, param, blocked, grpid) VALUES(%i, %Q, %Q, %i, %Q)\x00" + as *const u8 as *const libc::c_char, + 100i32, + chat_name, + if contact_id == 1i32 as libc::c_uint { + b"K=1\x00" as *const u8 as *const libc::c_char + } else { + b"\x00" as *const u8 as *const libc::c_char + }, + create_blocked, + (*contact).addr, + ); + if 0 != !('K' as i32 == 'K' as i32) as libc::c_int as libc::c_long { + __assert_rtn( + (*::std::mem::transmute::<&[u8; 40], &[libc::c_char; 40]>( + b"dc_create_or_lookup_nchat_by_contact_id\x00", + )) + .as_ptr(), + b"../src/dc_chat.c\x00" as *const u8 as *const libc::c_char, + 1386i32, + b"DC_PARAM_SELFTALK==\'K\'\x00" as *const u8 as *const libc::c_char, + ); + } else { + }; + stmt = dc_sqlite3_prepare((*context).sql, q); + if !stmt.is_null() { + if !(sqlite3_step(stmt) != 101i32) { + chat_id = dc_sqlite3_get_rowid( + (*context).sql, + 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); + if !(sqlite3_step(stmt) != 101i32) { + sqlite3_free(q as *mut libc::c_void); + q = 0 as *mut libc::c_char; + sqlite3_finalize(stmt); + stmt = 0 as *mut sqlite3_stmt + } + } + } + } + sqlite3_free(q as *mut libc::c_void); + sqlite3_finalize(stmt); + dc_contact_unref(contact); + if !ret_chat_id.is_null() { + *ret_chat_id = chat_id + } + if !ret_chat_blocked.is_null() { + *ret_chat_blocked = create_blocked + }; +} +#[no_mangle] +pub unsafe extern "C" fn dc_lookup_real_nchat_by_contact_id( + mut context: *mut 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; + 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() + { + 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" + as *const u8 as *const libc::c_char); + sqlite3_bind_int(stmt, 1i32, contact_id as libc::c_int); + if sqlite3_step(stmt) == 100i32 { + if !ret_chat_id.is_null() { + *ret_chat_id = sqlite3_column_int(stmt, 0i32) as uint32_t + } + if !ret_chat_blocked.is_null() { + *ret_chat_blocked = sqlite3_column_int(stmt, 1i32) + } + } + sqlite3_finalize(stmt); +} +#[no_mangle] +pub unsafe extern "C" fn dc_get_chat_id_by_contact_id( + mut context: *mut 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 + } else { + chat_id + }; +} +#[no_mangle] +pub unsafe extern "C" fn dc_prepare_msg( + mut context: *mut dc_context_t, + mut chat_id: uint32_t, + mut msg: *mut dc_msg_t, +) -> uint32_t { + if context.is_null() + || (*context).magic != 0x11a11807i32 as libc::c_uint + || 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.expect("non-null function pointer")( + context, + 2000i32, + (*msg).chat_id as uintptr_t, + (*msg).id as uintptr_t, + ); + return msg_id; +} +unsafe extern "C" fn prepare_msg_common( + mut context: *mut dc_context_t, + mut chat_id: uint32_t, + mut msg: *mut dc_msg_t, +) -> uint32_t { + let mut current_block: u64; + let mut pathNfilename: *mut libc::c_char = 0 as *mut libc::c_char; + let mut chat: *mut dc_chat_t = 0 as *mut dc_chat_t; + (*msg).id = 0i32 as uint32_t; + (*msg).context = context; + if (*msg).type_0 == 10i32 { + current_block = 17281240262373992796; + } else if (*msg).type_0 == 20i32 + || (*msg).type_0 == 21i32 + || (*msg).type_0 == 40i32 + || (*msg).type_0 == 41i32 + || (*msg).type_0 == 50i32 + || (*msg).type_0 == 60i32 + { + pathNfilename = dc_param_get((*msg).param, 'f' as i32, 0 as *const libc::c_char); + if pathNfilename.is_null() { + dc_log_error( + context, + 0i32, + b"Attachment missing for message of type #%i.\x00" as *const u8 + as *const libc::c_char, + (*msg).type_0 as libc::c_int, + ); + current_block = 2171833246886114521; + } else if (*msg).state == 18i32 && 0 == dc_is_blobdir_path(context, pathNfilename) { + dc_log_error( + context, + 0i32, + b"Files must be created in the blob-directory.\x00" as *const u8 + as *const libc::c_char, + ); + current_block = 2171833246886114521; + } else if 0 == dc_make_rel_and_copy(context, &mut pathNfilename) { + current_block = 2171833246886114521; + } else { + dc_param_set((*msg).param, 'f' as i32, pathNfilename); + if (*msg).type_0 == 60i32 || (*msg).type_0 == 20i32 { + let mut better_type: libc::c_int = 0i32; + let mut better_mime: *mut libc::c_char = 0 as *mut libc::c_char; + dc_msg_guess_msgtype_from_suffix(pathNfilename, &mut better_type, &mut better_mime); + if 0 != better_type { + (*msg).type_0 = better_type; + dc_param_set((*msg).param, 'm' as i32, better_mime); + } + free(better_mime as *mut libc::c_void); + } else if 0 == dc_param_exists((*msg).param, 'm' as i32) { + let mut better_mime_0: *mut libc::c_char = 0 as *mut libc::c_char; + dc_msg_guess_msgtype_from_suffix( + pathNfilename, + 0 as *mut libc::c_int, + &mut better_mime_0, + ); + dc_param_set((*msg).param, 'm' as i32, better_mime_0); + free(better_mime_0 as *mut libc::c_void); + } + dc_log_info( + context, + 0i32, + b"Attaching \"%s\" for message type #%i.\x00" as *const u8 as *const libc::c_char, + pathNfilename, + (*msg).type_0 as libc::c_int, + ); + current_block = 17281240262373992796; + } + } else { + dc_log_error( + context, + 0i32, + b"Cannot send messages of type #%i.\x00" as *const u8 as *const libc::c_char, + (*msg).type_0 as libc::c_int, + ); + current_block = 2171833246886114521; + } + 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 { + (*msg).state = 20i32 + } + (*msg).id = + prepare_msg_raw(context, chat, msg, dc_create_smeared_timestamp(context)); + (*msg).chat_id = chat_id + } + } + _ => {} + } + /* potential error already logged */ + dc_chat_unref(chat); + free(pathNfilename as *mut libc::c_void); + return (*msg).id; +} +unsafe extern "C" fn prepare_msg_raw( + mut context: *mut 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 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; + let mut parent_in_reply_to: *mut libc::c_char = 0 as *mut libc::c_char; + let mut new_rfc724_mid: *mut libc::c_char = 0 as *mut libc::c_char; + let mut new_references: *mut libc::c_char = 0 as *mut libc::c_char; + let mut new_in_reply_to: *mut libc::c_char = 0 as *mut libc::c_char; + let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; + let mut msg_id: uint32_t = 0i32 as uint32_t; + let mut to_id: uint32_t = 0i32 as uint32_t; + if !((*chat).type_0 == 100i32 || (*chat).type_0 == 120i32 || (*chat).type_0 == 130i32) { + dc_log_error( + context, + 0i32, + b"Cannot send to chat type #%i.\x00" as *const u8 as *const libc::c_char, + (*chat).type_0, + ); + } else if ((*chat).type_0 == 120i32 || (*chat).type_0 == 130i32) + && 0 == dc_is_contact_in_chat(context, (*chat).id, 1i32 as uint32_t) + { + dc_log_event( + context, + 410i32, + 0i32, + b"Cannot send message; self not in group.\x00" as *const u8 as *const libc::c_char, + ); + } else { + let mut from: *mut libc::c_char = dc_sqlite3_get_config( + (*context).sql, + b"configured_addr\x00" as *const u8 as *const libc::c_char, + 0 as *const libc::c_char, + ); + if from.is_null() { + dc_log_error( + context, + 0i32, + b"Cannot send message, not configured.\x00" as *const u8 as *const libc::c_char, + ); + } else { + new_rfc724_mid = dc_create_outgoing_rfc724_mid( + if (*chat).type_0 == 120i32 || (*chat).type_0 == 130i32 { + (*chat).grpid + } else { + 0 as *mut libc::c_char + }, + from, + ); + free(from as *mut libc::c_void); + if (*chat).type_0 == 100i32 { + stmt = dc_sqlite3_prepare( + (*context).sql, + b"SELECT contact_id FROM chats_contacts 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 { + dc_log_error( + context, + 0i32, + b"Cannot send message, contact for chat #%i not found.\x00" as *const u8 + as *const libc::c_char, + (*chat).id, + ); + current_block = 10477488590406205504; + } else { + to_id = sqlite3_column_int(stmt, 0i32) as uint32_t; + sqlite3_finalize(stmt); + stmt = 0 as *mut sqlite3_stmt; + current_block = 5689316957504528238; + } + } else { + if (*chat).type_0 == 120i32 || (*chat).type_0 == 130i32 { + if dc_param_get_int((*chat).param, 'U' as i32, 0i32) == 1i32 { + dc_param_set((*chat).param, 'U' as i32, 0 as *const libc::c_char); + dc_chat_update_param(chat); + } + } + current_block = 5689316957504528238; + } + match current_block { + 10477488590406205504 => {} + _ => { + /* check if we can guarantee E2EE for this message. + if we guarantee E2EE, and circumstances change + so that E2EE is no longer available at a later point (reset, changed settings), + we do not send the message out at all */ + do_guarantee_e2ee = 0i32; + e2ee_enabled = dc_sqlite3_get_config_int( + (*context).sql, + b"e2ee_enabled\x00" as *const u8 as *const libc::c_char, + 1i32, + ); + if 0 != e2ee_enabled && dc_param_get_int((*msg).param, 'u' as i32, 0i32) == 0i32 + { + let mut can_encrypt: libc::c_int = 1i32; + let mut all_mutual: libc::c_int = 1i32; + stmt = + dc_sqlite3_prepare((*context).sql, + 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); + sqlite3_bind_int(stmt, 1i32, (*chat).id as libc::c_int); + while sqlite3_step(stmt) == 100i32 { + if sqlite3_column_type(stmt, 0i32) == 5i32 { + dc_log_info( + context, + 0i32, + b"[autocrypt] no peerstate for %s\x00" as *const u8 + as *const libc::c_char, + sqlite3_column_text(stmt, 1i32), + ); + can_encrypt = 0i32; + all_mutual = 0i32 + } else { + let mut prefer_encrypted: libc::c_int = + sqlite3_column_int(stmt, 0i32); + if prefer_encrypted != 1i32 { + dc_log_info( + context, + 0i32, + b"[autocrypt] peerstate for %s is %s\x00" as *const u8 + as *const libc::c_char, + sqlite3_column_text(stmt, 1i32), + if prefer_encrypted == 0i32 { + b"NOPREFERENCE\x00" as *const u8 as *const libc::c_char + } else { + b"RESET\x00" as *const u8 as *const libc::c_char + }, + ); + all_mutual = 0i32 + } + } + } + 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) { + do_guarantee_e2ee = 1i32 + } + } + } + if 0 != do_guarantee_e2ee { + dc_param_set_int((*msg).param, 'c' as i32, 1i32); + } + dc_param_set((*msg).param, 'e' as i32, 0 as *const libc::c_char); + if 0 == dc_chat_is_self_talk(chat) + && 0 != get_parent_mime_headers( + chat, + &mut parent_rfc724_mid, + &mut parent_in_reply_to, + &mut parent_references, + ) + { + if !parent_rfc724_mid.is_null() + && 0 != *parent_rfc724_mid.offset(0isize) as libc::c_int + { + 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; + space = strchr(parent_references, ' ' as i32); + if !space.is_null() { + *space = 0i32 as libc::c_char + } + } + if !parent_references.is_null() + && 0 != *parent_references.offset(0isize) as libc::c_int + && !parent_rfc724_mid.is_null() + && 0 != *parent_rfc724_mid.offset(0isize) as libc::c_int + { + new_references = dc_mprintf( + b"%s %s\x00" as *const u8 as *const libc::c_char, + parent_references, + parent_rfc724_mid, + ) + } else if !parent_references.is_null() + && 0 != *parent_references.offset(0isize) as libc::c_int + { + new_references = dc_strdup(parent_references) + } else if !parent_in_reply_to.is_null() + && 0 != *parent_in_reply_to.offset(0isize) as libc::c_int + && !parent_rfc724_mid.is_null() + && 0 != *parent_rfc724_mid.offset(0isize) as libc::c_int + { + new_references = dc_mprintf( + b"%s %s\x00" as *const u8 as *const libc::c_char, + parent_in_reply_to, + parent_rfc724_mid, + ) + } else if !parent_in_reply_to.is_null() + && 0 != *parent_in_reply_to.offset(0isize) as libc::c_int + { + new_references = dc_strdup(parent_in_reply_to) + } + } + stmt = + dc_sqlite3_prepare((*context).sql, + b"INSERT INTO msgs (rfc724_mid, chat_id, from_id, to_id, timestamp, type, state, txt, param, hidden, mime_in_reply_to, mime_references) VALUES (?,?,?,?,?, ?,?,?,?,?, ?,?);\x00" + as *const u8 as + *const libc::c_char); + sqlite3_bind_text(stmt, 1i32, new_rfc724_mid, -1i32, None); + sqlite3_bind_int(stmt, 2i32, (*chat).id as libc::c_int); + sqlite3_bind_int(stmt, 3i32, 1i32); + sqlite3_bind_int(stmt, 4i32, to_id as libc::c_int); + sqlite3_bind_int64(stmt, 5i32, timestamp as sqlite3_int64); + sqlite3_bind_int(stmt, 6i32, (*msg).type_0); + sqlite3_bind_int(stmt, 7i32, (*msg).state); + sqlite3_bind_text( + stmt, + 8i32, + if !(*msg).text.is_null() { + (*msg).text + } else { + b"\x00" as *const u8 as *const libc::c_char + }, + -1i32, + None, + ); + sqlite3_bind_text(stmt, 9i32, (*(*msg).param).packed, -1i32, None); + sqlite3_bind_int(stmt, 10i32, (*msg).hidden); + sqlite3_bind_text(stmt, 11i32, new_in_reply_to, -1i32, None); + sqlite3_bind_text(stmt, 12i32, new_references, -1i32, None); + if sqlite3_step(stmt) != 101i32 { + dc_log_error( + context, + 0i32, + b"Cannot send message, cannot insert to database.\x00" as *const u8 + as *const libc::c_char, + (*chat).id, + ); + } else { + msg_id = dc_sqlite3_get_rowid( + (*context).sql, + 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, + ) + } + } + } + } + } + free(parent_rfc724_mid as *mut libc::c_void); + free(parent_in_reply_to as *mut libc::c_void); + free(parent_references as *mut libc::c_void); + free(new_rfc724_mid as *mut libc::c_void); + free(new_in_reply_to as *mut libc::c_void); + free(new_references as *mut libc::c_void); + sqlite3_finalize(stmt); + return msg_id; +} +unsafe extern "C" fn get_parent_mime_headers( + mut chat: *const dc_chat_t, + mut parent_rfc724_mid: *mut *mut libc::c_char, + mut parent_in_reply_to: *mut *mut libc::c_char, + mut parent_references: *mut *mut 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 !(chat.is_null() + || parent_rfc724_mid.is_null() + || parent_in_reply_to.is_null() + || parent_references.is_null()) + { + stmt = + dc_sqlite3_prepare((*(*chat).context).sql, + 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); + sqlite3_bind_int(stmt, 2i32, 1i32); + if sqlite3_step(stmt) == 100i32 { + *parent_rfc724_mid = dc_strdup(sqlite3_column_text(stmt, 0i32) as *const libc::c_char); + *parent_in_reply_to = dc_strdup(sqlite3_column_text(stmt, 1i32) as *const libc::c_char); + *parent_references = dc_strdup(sqlite3_column_text(stmt, 2i32) as *const libc::c_char); + success = 1i32 + } + sqlite3_finalize(stmt); + stmt = 0 as *mut sqlite3_stmt; + if 0 == success { + stmt = + dc_sqlite3_prepare((*(*chat).context).sql, + 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); + sqlite3_bind_int(stmt, 2i32, 1i32); + if sqlite3_step(stmt) == 100i32 { + *parent_rfc724_mid = + dc_strdup(sqlite3_column_text(stmt, 0i32) as *const libc::c_char); + *parent_in_reply_to = + dc_strdup(sqlite3_column_text(stmt, 1i32) as *const libc::c_char); + *parent_references = + dc_strdup(sqlite3_column_text(stmt, 2i32) as *const libc::c_char); + success = 1i32 + } + } + } + sqlite3_finalize(stmt); + return success; +} +#[no_mangle] +pub unsafe extern "C" 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); +} +/* ****************************************************************************** + * Sending messages + ******************************************************************************/ +unsafe extern "C" fn last_msg_in_chat_encrypted( + mut sql: *mut dc_sqlite3_t, + mut 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, + 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); + if sqlite3_step(stmt) == 100i32 { + let mut msg_param: *mut dc_param_t = dc_param_new(); + dc_param_set_packed( + msg_param, + sqlite3_column_text(stmt, 0i32) as *mut libc::c_char, + ); + if 0 != dc_param_exists(msg_param, 'c' as i32) { + last_is_encrypted = 1i32 + } + dc_param_unref(msg_param); + } + sqlite3_finalize(stmt); + return last_is_encrypted; +} +#[no_mangle] +pub unsafe extern "C" fn dc_chat_update_param(mut chat: *mut dc_chat_t) -> libc::c_int { + let mut success: libc::c_int = 0i32; + let mut stmt: *mut sqlite3_stmt = dc_sqlite3_prepare( + (*(*chat).context).sql, + 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); + sqlite3_bind_int(stmt, 2i32, (*chat).id as libc::c_int); + success = if sqlite3_step(stmt) == 101i32 { + 1i32 + } else { + 0i32 + }; + sqlite3_finalize(stmt); + return success; +} +#[no_mangle] +pub unsafe extern "C" fn dc_is_contact_in_chat( + mut context: *mut 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 + } + } + sqlite3_finalize(stmt); + return ret; +} +#[no_mangle] +pub unsafe extern "C" fn dc_unarchive_chat(mut context: *mut dc_context_t, mut chat_id: uint32_t) { + let mut stmt: *mut sqlite3_stmt = dc_sqlite3_prepare( + (*context).sql, + 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); +} +#[no_mangle] +pub unsafe extern "C" fn dc_send_msg( + mut context: *mut dc_context_t, + mut chat_id: uint32_t, + mut msg: *mut dc_msg_t, +) -> uint32_t { + if context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint || msg.is_null() { + return 0i32 as uint32_t; + } + if (*msg).state != 18i32 { + if 0 == prepare_msg_common(context, chat_id, msg) { + return 0i32 as uint32_t; + } + } else { + if chat_id != 0i32 as libc::c_uint && chat_id != (*msg).chat_id { + return 0i32 as uint32_t; + } + dc_update_msg_state(context, (*msg).id, 20i32); + } + if 0 == dc_job_send_msg(context, (*msg).id) { + return 0i32 as uint32_t; + } + (*context).cb.expect("non-null function pointer")( + context, + 2000i32, + (*msg).chat_id as uintptr_t, + (*msg).id as uintptr_t, + ); + if 0 == chat_id { + let mut forwards: *mut libc::c_char = + dc_param_get((*msg).param, 'P' as i32, 0 as *const libc::c_char); + if !forwards.is_null() { + let mut p: *mut libc::c_char = forwards; + while 0 != *p { + let mut id: int32_t = strtol(p, &mut p, 10i32) as int32_t; + if 0 == id { + // avoid hanging if user tampers with db + break; + } else { + let mut copy: *mut dc_msg_t = dc_get_msg(context, id as uint32_t); + if !copy.is_null() { + dc_send_msg(context, 0i32 as uint32_t, copy); + } + dc_msg_unref(copy); + } + } + dc_param_set((*msg).param, 'P' as i32, 0 as *const libc::c_char); + dc_msg_save_param_to_disk(msg); + } + free(forwards as *mut libc::c_void); + } + return (*msg).id; +} +#[no_mangle] +pub unsafe extern "C" fn dc_send_text_msg( + mut context: *mut 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()) + { + (*msg).text = dc_strdup(text_to_send); + ret = dc_send_msg(context, chat_id, msg) + } + dc_msg_unref(msg); + return ret; +} +#[no_mangle] +pub unsafe extern "C" fn dc_set_draft( + mut context: *mut 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 + { + return; + } + if 0 != set_draft_raw(context, chat_id, msg) { + (*context).cb.expect("non-null function pointer")( + context, + 2000i32, + chat_id as uintptr_t, + 0i32 as uintptr_t, + ); + }; +} +unsafe extern "C" fn set_draft_raw( + mut context: *mut dc_context_t, + mut chat_id: uint32_t, + mut msg: *mut dc_msg_t, +) -> libc::c_int { + let mut current_block: u64; + // 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 sth_changed: libc::c_int = 0i32; + prev_draft_msg_id = get_draft_msg_id(context, chat_id); + if 0 != prev_draft_msg_id { + dc_delete_msg_from_db(context, prev_draft_msg_id); + sth_changed = 1i32 + } + // save new draft + if !msg.is_null() { + if (*msg).type_0 == 10i32 { + if (*msg).text.is_null() || *(*msg).text.offset(0isize) as libc::c_int == 0i32 { + current_block = 14513523936503887211; + } else { + current_block = 4495394744059808450; + } + } else if (*msg).type_0 == 20i32 + || (*msg).type_0 == 21i32 + || (*msg).type_0 == 40i32 + || (*msg).type_0 == 41i32 + || (*msg).type_0 == 50i32 + || (*msg).type_0 == 60i32 + { + pathNfilename = dc_param_get((*msg).param, 'f' as i32, 0 as *const libc::c_char); + if pathNfilename.is_null() { + current_block = 14513523936503887211; + } else if 0 != dc_msg_is_increation(msg) + && 0 == dc_is_blobdir_path(context, pathNfilename) + { + current_block = 14513523936503887211; + } else if 0 == dc_make_rel_and_copy(context, &mut pathNfilename) { + current_block = 14513523936503887211; + } else { + dc_param_set((*msg).param, 'f' as i32, pathNfilename); + current_block = 4495394744059808450; + } + } else { + current_block = 14513523936503887211; + } + match current_block { + 14513523936503887211 => {} + _ => { + stmt = + dc_sqlite3_prepare((*context).sql, + b"INSERT INTO msgs (chat_id, from_id, timestamp, type, state, txt, param, hidden) VALUES (?,?,?, ?,?,?,?,?);\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, 1i32); + sqlite3_bind_int64(stmt, 3i32, time(0 as *mut time_t) as sqlite3_int64); + sqlite3_bind_int(stmt, 4i32, (*msg).type_0); + sqlite3_bind_int(stmt, 5i32, 19i32); + sqlite3_bind_text( + stmt, + 6i32, + if !(*msg).text.is_null() { + (*msg).text + } else { + b"\x00" as *const u8 as *const libc::c_char + }, + -1i32, + None, + ); + sqlite3_bind_text(stmt, 7i32, (*(*msg).param).packed, -1i32, None); + sqlite3_bind_int(stmt, 8i32, 1i32); + if !(sqlite3_step(stmt) != 101i32) { + sth_changed = 1i32 + } + } + } + } + sqlite3_finalize(stmt); + free(pathNfilename as *mut libc::c_void); + return sth_changed; +} +unsafe extern "C" fn get_draft_msg_id( + mut context: *mut 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, + 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); + sqlite3_bind_int(stmt, 2i32, 19i32); + if sqlite3_step(stmt) == 100i32 { + draft_msg_id = sqlite3_column_int(stmt, 0i32) as uint32_t + } + sqlite3_finalize(stmt); + return draft_msg_id; +} +#[no_mangle] +pub unsafe extern "C" 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 + { + return 0 as *mut dc_msg_t; + } + draft_msg_id = get_draft_msg_id(context, chat_id); + if draft_msg_id == 0i32 as libc::c_uint { + return 0 as *mut dc_msg_t; + } + draft_msg = dc_msg_new_untyped(context); + if 0 == dc_msg_load_from_db(draft_msg, context, draft_msg_id) { + dc_msg_unref(draft_msg); + return 0 as *mut dc_msg_t; + } + return draft_msg; +} +#[no_mangle] +pub unsafe extern "C" fn dc_get_chat_msgs( + mut context: *mut 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 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 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 chat_id == 1i32 as libc::c_uint { + let mut show_emails: libc::c_int = dc_sqlite3_get_config_int( + (*context).sql, + b"show_emails\x00" as *const u8 as *const libc::c_char, + 0i32, + ); + stmt = + dc_sqlite3_prepare((*context).sql, + 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, + 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, + 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); + } + while sqlite3_step(stmt) == 100i32 { + curr_id = sqlite3_column_int(stmt, 0i32) as uint32_t; + if curr_id == marker1before { + dc_array_add_id(ret, 1i32 as uint32_t); + } + if 0 != flags & 0x1i32 as libc::c_uint { + curr_local_timestamp = sqlite3_column_int64(stmt, 1i32) as time_t + cnv_to_local; + curr_day = (curr_local_timestamp / 86400i32 as libc::c_long) as libc::c_int; + if curr_day != last_day { + dc_array_add_id(ret, 9i32 as uint32_t); + last_day = curr_day + } + } + dc_array_add_id(ret, curr_id); + } + success = 1i32 + } + sqlite3_finalize(stmt); + if 0 != success { + return ret; + } else { + if !ret.is_null() { + dc_array_unref(ret); + } + return 0 as *mut dc_array_t; + }; +} +#[no_mangle] +pub unsafe extern "C" fn dc_get_msg_cnt( + mut context: *mut 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) + } + } + sqlite3_finalize(stmt); + return ret; +} +#[no_mangle] +pub unsafe extern "C" fn dc_get_fresh_msg_cnt( + mut context: *mut 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) + } + } + sqlite3_finalize(stmt); + return ret; +} +#[no_mangle] +pub unsafe extern "C" 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; + 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 + 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.expect("non-null function pointer")( + context, + 2000i32, + 0i32 as uintptr_t, + 0i32 as uintptr_t, + ); + } + } + sqlite3_finalize(check); + sqlite3_finalize(update); +} +#[no_mangle] +pub unsafe extern "C" 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, + ); + 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.expect("non-null function pointer")( + context, + 2000i32, + 0i32 as uintptr_t, + 0i32 as uintptr_t, + ); + } + } + sqlite3_finalize(check); + sqlite3_finalize(update); +} +#[no_mangle] +pub unsafe extern "C" fn dc_get_chat_media( + mut context: *mut 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 stmt: *mut sqlite3_stmt = + dc_sqlite3_prepare((*context).sql, + 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); + sqlite3_bind_int(stmt, 2i32, msg_type); + sqlite3_bind_int( + stmt, + 3i32, + if msg_type2 > 0i32 { + msg_type2 + } else { + msg_type + }, + ); + sqlite3_bind_int( + stmt, + 4i32, + if msg_type3 > 0i32 { + msg_type3 + } else { + msg_type + }, + ); + while sqlite3_step(stmt) == 100i32 { + dc_array_add_id(ret, sqlite3_column_int(stmt, 0i32) as uint32_t); + } + sqlite3_finalize(stmt); + return ret; +} +#[no_mangle] +pub unsafe extern "C" fn dc_get_next_media( + mut context: *mut dc_context_t, + mut curr_msg_id: uint32_t, + mut dir: libc::c_int, + mut msg_type: libc::c_int, + mut msg_type2: libc::c_int, + mut msg_type3: libc::c_int, +) -> uint32_t { + 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) + } + } + break; + } else { + i += 1 + } + } + } + } + } + dc_array_unref(list); + dc_msg_unref(msg); + return ret_msg_id; +} +#[no_mangle] +pub unsafe extern "C" fn dc_archive_chat( + mut context: *mut 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 + { + return; + } + if 0 != archive { + let mut stmt: *mut sqlite3_stmt = 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(stmt, 1i32, chat_id as libc::c_int); + sqlite3_step(stmt); + sqlite3_finalize(stmt); + } + let mut stmt_0: *mut sqlite3_stmt = dc_sqlite3_prepare( + (*context).sql, + 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.expect("non-null function pointer")( + context, + 2000i32, + 0i32 as uintptr_t, + 0i32 as uintptr_t, + ); +} +#[no_mangle] +pub unsafe extern "C" fn dc_delete_chat(mut context: *mut 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 !(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)) { + 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)) { + 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)) { + 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)) { + 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.expect("non-null function pointer")( + context, + 2000i32, + 0i32 as uintptr_t, + 0i32 as uintptr_t, + ); + dc_job_kill_action(context, 105i32); + dc_job_add(context, 105i32, 0i32, 0 as *const libc::c_char, 10i32); + } + } + } + } + } + } + if 0 != pending_transaction { + dc_sqlite3_rollback((*context).sql); + } + dc_chat_unref(obj); + sqlite3_free(q3 as *mut libc::c_void); +} +#[no_mangle] +pub unsafe extern "C" fn dc_get_chat_contacts( + mut context: *mut 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 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); + } + } + } + sqlite3_finalize(stmt); + return ret; +} +#[no_mangle] +pub unsafe extern "C" fn dc_get_chat( + mut context: *mut 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 != success { + return obj; + } else { + dc_chat_unref(obj); + return 0 as *mut dc_chat_t; + }; +} +// handle group chats +#[no_mangle] +pub unsafe extern "C" fn dc_create_group_chat( + mut context: *mut 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_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 + { + 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, + b"INSERT INTO chats (type, name, grpid, param) VALUES(?, ?, ?, \'U=1\');\x00" as *const u8 + as *const libc::c_char, + ); + sqlite3_bind_int(stmt, 1i32, if 0 != verified { 130i32 } else { 120i32 }); + sqlite3_bind_text(stmt, 2i32, chat_name, -1i32, None); + sqlite3_bind_text(stmt, 3i32, grpid, -1i32, None); + if !(sqlite3_step(stmt) != 101i32) { + chat_id = dc_sqlite3_get_rowid( + (*context).sql, + b"chats\x00" as *const u8 as *const libc::c_char, + b"grpid\x00" as *const u8 as *const libc::c_char, + grpid, + ); + if !(chat_id == 0i32 as libc::c_uint) { + if !(0 == dc_add_to_chat_contacts_table(context, chat_id, 1i32 as uint32_t)) { + draft_msg = dc_msg_new(context, 10i32); + dc_msg_set_text(draft_msg, draft_txt); + set_draft_raw(context, chat_id, draft_msg); + } + } + } + sqlite3_finalize(stmt); + free(draft_txt as *mut libc::c_void); + dc_msg_unref(draft_msg); + free(grpid as *mut libc::c_void); + if 0 != chat_id { + (*context).cb.expect("non-null function pointer")( + context, + 2000i32, + 0i32 as uintptr_t, + 0i32 as uintptr_t, + ); + } + return chat_id; +} +/* you MUST NOT modify this or the following strings */ +// Context functions to work with chats +#[no_mangle] +pub unsafe extern "C" fn dc_add_to_chat_contacts_table( + mut context: *mut 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 stmt: *mut sqlite3_stmt = dc_sqlite3_prepare( + (*context).sql, + b"INSERT INTO chats_contacts (chat_id, contact_id) VALUES(?, ?)\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) == 101i32 { + 1i32 + } else { + 0i32 + }; + sqlite3_finalize(stmt); + return ret; +} +#[no_mangle] +pub unsafe extern "C" fn dc_add_contact_to_chat( + mut context: *mut 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); +} +#[no_mangle] +pub unsafe extern "C" fn dc_add_contact_to_chat_ex( + mut context: *mut dc_context_t, + mut chat_id: uint32_t, + mut contact_id: uint32_t, + mut flags: libc::c_int, +) -> libc::c_int { + let mut current_block: u64; + let mut success: libc::c_int = 0i32; + let mut contact: *mut dc_contact_t = dc_get_contact(context, contact_id); + 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) + { + 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) + || 0i32 == dc_real_contact_exists(context, contact_id) + && contact_id != 1i32 as libc::c_uint + || 0i32 == dc_chat_load_from_db(chat, chat_id)) + { + if !(dc_is_contact_in_chat(context, chat_id, 1i32 as uint32_t) == 1i32) { + dc_log_event( + context, + 410i32, + 0i32, + b"Cannot add contact to group; self not in group.\x00" as *const u8 + as *const libc::c_char, + ); + } else { + /* we shoud respect this - whatever we send to the group, it gets discarded anyway! */ + if 0 != flags & 0x1i32 && dc_param_get_int((*chat).param, 'U' as i32, 0i32) == 1i32 + { + dc_param_set((*chat).param, 'U' as i32, 0 as *const libc::c_char); + dc_chat_update_param(chat); + } + 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 !(strcasecmp((*contact).addr, self_addr) == 0i32) { + /* ourself is added using DC_CONTACT_ID_SELF, do not add it explicitly. if SELF is not in the group, members cannot be added at all. */ + if 0 != dc_is_contact_in_chat(context, chat_id, contact_id) { + if 0 == flags & 0x1i32 { + success = 1i32; + current_block = 12326129973959287090; + } else { + current_block = 15125582407903384992; + } + } else { + // else continue and send status mail + if (*chat).type_0 == 130i32 { + if dc_contact_is_verified(contact) != 2i32 { + dc_log_error(context, 0i32, + b"Only bidirectional verified contacts can be added to verified groups.\x00" + as *const u8 as + *const libc::c_char); + current_block = 12326129973959287090; + } else { + current_block = 13472856163611868459; + } + } else { + current_block = 13472856163611868459; + } + match current_block { + 12326129973959287090 => {} + _ => { + if 0i32 + == dc_add_to_chat_contacts_table(context, chat_id, contact_id) + { + current_block = 12326129973959287090; + } else { + current_block = 15125582407903384992; + } + } + } + } + match current_block { + 12326129973959287090 => {} + _ => { + if dc_param_get_int((*chat).param, 'U' as i32, 0i32) == 0i32 { + (*msg).type_0 = 10i32; + (*msg).text = dc_stock_system_msg( + context, + 17i32, + (*contact).addr, + 0 as *const libc::c_char, + 1i32 as uint32_t, + ); + dc_param_set_int((*msg).param, 'S' as i32, 4i32); + 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.expect("non-null function pointer")( + context, + 2000i32, + chat_id as uintptr_t, + (*msg).id as uintptr_t, + ); + } + (*context).cb.expect("non-null function pointer")( + context, + 2020i32, + chat_id as uintptr_t, + 0i32 as uintptr_t, + ); + success = 1i32 + } + } + } + } + } + } + dc_chat_unref(chat); + dc_contact_unref(contact); + dc_msg_unref(msg); + free(self_addr as *mut libc::c_void); + return success; +} +unsafe extern "C" fn real_group_exists( + mut context: *mut 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 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 + { + return 0i32; + } + stmt = dc_sqlite3_prepare( + (*context).sql, + b"SELECT id FROM chats WHERE id=? AND (type=120 OR type=130);\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 = 1i32 + } + sqlite3_finalize(stmt); + return ret; +} +#[no_mangle] +pub unsafe extern "C" fn dc_reset_gossiped_timestamp( + mut context: *mut dc_context_t, + mut chat_id: uint32_t, +) { + dc_set_gossiped_timestamp(context, chat_id, 0i32 as time_t); +} +#[no_mangle] +pub unsafe extern "C" fn dc_set_gossiped_timestamp( + mut context: *mut dc_context_t, + mut chat_id: uint32_t, + mut timestamp: time_t, +) { + let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; + if 0 != chat_id { + dc_log_info( + context, + 0i32, + b"set gossiped_timestamp for chat #%i to %i.\x00" as *const u8 as *const libc::c_char, + chat_id as libc::c_int, + timestamp as libc::c_int, + ); + stmt = dc_sqlite3_prepare( + (*context).sql, + b"UPDATE chats SET gossiped_timestamp=? WHERE id=?;\x00" as *const u8 + as *const libc::c_char, + ); + sqlite3_bind_int64(stmt, 1i32, timestamp as sqlite3_int64); + sqlite3_bind_int(stmt, 2i32, chat_id as libc::c_int); + } else { + dc_log_info( + context, + 0i32, + b"set gossiped_timestamp for all chats to %i.\x00" as *const u8 as *const libc::c_char, + timestamp as libc::c_int, + ); + stmt = dc_sqlite3_prepare( + (*context).sql, + b"UPDATE chats SET gossiped_timestamp=?;\x00" as *const u8 as *const libc::c_char, + ); + sqlite3_bind_int64(stmt, 1i32, timestamp as sqlite3_int64); + } + sqlite3_step(stmt); + sqlite3_finalize(stmt); +} +#[no_mangle] +pub unsafe extern "C" fn dc_remove_contact_from_chat( + mut context: *mut dc_context_t, + mut chat_id: uint32_t, + mut contact_id: uint32_t, +) -> libc::c_int { + let mut success: libc::c_int = 0i32; + let mut contact: *mut dc_contact_t = dc_get_contact(context, contact_id); + 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 + || 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 */ + /* this allows to delete pending references to deleted contacts. Of course, this should _not_ happen. */ + if !(0i32 == real_group_exists(context, chat_id) + || 0i32 == dc_chat_load_from_db(chat, chat_id)) + { + if !(dc_is_contact_in_chat(context, chat_id, 1i32 as uint32_t) == 1i32) { + dc_log_event( + context, + 410i32, + 0i32, + b"Cannot remove contact from chat; self not in group.\x00" as *const u8 + as *const libc::c_char, + ); + } else { + /* we shoud respect this - whatever we send to the group, it gets discarded anyway! */ + if !contact.is_null() { + if dc_param_get_int((*chat).param, 'U' as i32, 0i32) == 0i32 { + (*msg).type_0 = 10i32; + if (*contact).id == 1i32 as libc::c_uint { + dc_set_group_explicitly_left(context, (*chat).grpid); + (*msg).text = dc_stock_system_msg( + context, + 19i32, + 0 as *const libc::c_char, + 0 as *const libc::c_char, + 1i32 as uint32_t, + ) + } else { + (*msg).text = dc_stock_system_msg( + context, + 18i32, + (*contact).addr, + 0 as *const libc::c_char, + 1i32 as uint32_t, + ) + } + 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.expect("non-null function pointer")( + context, + 2000i32, + chat_id as uintptr_t, + (*msg).id as uintptr_t, + ); + } + } + q3 = sqlite3_mprintf( + b"DELETE FROM chats_contacts WHERE chat_id=%i AND contact_id=%i;\x00" + as *const u8 as *const libc::c_char, + chat_id, + contact_id, + ); + if !(0 == dc_sqlite3_execute((*context).sql, q3)) { + (*context).cb.expect("non-null function pointer")( + context, + 2020i32, + chat_id as uintptr_t, + 0i32 as uintptr_t, + ); + success = 1i32 + } + } + } + } + sqlite3_free(q3 as *mut libc::c_void); + dc_chat_unref(chat); + dc_contact_unref(contact); + dc_msg_unref(msg); + return success; +} +#[no_mangle] +pub unsafe extern "C" fn dc_set_group_explicitly_left( + mut context: *mut 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, + b"INSERT INTO leftgrps (grpid) VALUES(?);\x00" as *const u8 as *const libc::c_char, + ); + sqlite3_bind_text(stmt, 1i32, grpid, -1i32, None); + sqlite3_step(stmt); + sqlite3_finalize(stmt); + }; +} +#[no_mangle] +pub unsafe extern "C" fn dc_is_group_explicitly_left( + mut context: *mut dc_context_t, + mut grpid: *const libc::c_char, +) -> libc::c_int { + let mut stmt: *mut sqlite3_stmt = dc_sqlite3_prepare( + (*context).sql, + 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; +} +#[no_mangle] +pub unsafe extern "C" fn dc_set_chat_name( + mut context: *mut dc_context_t, + mut chat_id: uint32_t, + mut new_name: *const libc::c_char, +) -> libc::c_int { + /* the function only sets the names of group chats; normal chats get their names from the contacts */ + let mut success: libc::c_int = 0i32; + 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() + || *new_name.offset(0isize) as libc::c_int == 0i32 + || chat_id <= 9i32 as libc::c_uint) + { + if !(0i32 == real_group_exists(context, chat_id) + || 0i32 == dc_chat_load_from_db(chat, chat_id)) + { + if strcmp((*chat).name, new_name) == 0i32 { + success = 1i32 + } else if !(dc_is_contact_in_chat(context, chat_id, 1i32 as uint32_t) == 1i32) { + dc_log_event( + context, + 410i32, + 0i32, + b"Cannot set chat name; self not in group\x00" as *const u8 + as *const libc::c_char, + ); + } else { + /* we shoud respect this - whatever we send to the group, it gets discarded anyway! */ + q3 = sqlite3_mprintf( + b"UPDATE chats SET name=%Q WHERE id=%i;\x00" as *const u8 + as *const libc::c_char, + new_name, + chat_id, + ); + if !(0 == dc_sqlite3_execute((*context).sql, q3)) { + if dc_param_get_int((*chat).param, 'U' as i32, 0i32) == 0i32 { + (*msg).type_0 = 10i32; + (*msg).text = dc_stock_system_msg( + context, + 15i32, + (*chat).name, + new_name, + 1i32 as uint32_t, + ); + 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.expect("non-null function pointer")( + context, + 2000i32, + chat_id as uintptr_t, + (*msg).id as uintptr_t, + ); + } + (*context).cb.expect("non-null function pointer")( + context, + 2020i32, + chat_id as uintptr_t, + 0i32 as uintptr_t, + ); + success = 1i32 + } + } + } + } + sqlite3_free(q3 as *mut libc::c_void); + dc_chat_unref(chat); + dc_msg_unref(msg); + return success; +} +#[no_mangle] +pub unsafe extern "C" fn dc_set_chat_profile_image( + mut context: *mut dc_context_t, + mut chat_id: uint32_t, + mut new_image: *const libc::c_char, +) -> libc::c_int { + let mut current_block: u64; + let mut success: libc::c_int = 0i32; + 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 !(0i32 == real_group_exists(context, chat_id) + || 0i32 == dc_chat_load_from_db(chat, chat_id)) + { + if !(dc_is_contact_in_chat(context, chat_id, 1i32 as uint32_t) == 1i32) { + dc_log_event( + context, + 410i32, + 0i32, + b"Cannot set chat profile image; self not in group.\x00" as *const u8 + as *const libc::c_char, + ); + } else { + /* we shoud respect this - whatever we send to the group, it gets discarded anyway! */ + if !new_image.is_null() { + new_image_rel = dc_strdup(new_image); + if 0 == dc_make_rel_and_copy(context, &mut new_image_rel) { + current_block = 14766584022300871387; + } else { + current_block = 1856101646708284338; + } + } else { + current_block = 1856101646708284338; + } + match current_block { + 14766584022300871387 => {} + _ => { + dc_param_set((*chat).param, 'i' as i32, new_image_rel); + if !(0 == dc_chat_update_param(chat)) { + if dc_param_get_int((*chat).param, 'U' as i32, 0i32) == 0i32 { + dc_param_set_int((*msg).param, 'S' as i32, 3i32); + dc_param_set((*msg).param, 'E' as i32, new_image_rel); + (*msg).type_0 = 10i32; + (*msg).text = dc_stock_system_msg( + context, + if !new_image_rel.is_null() { + 16i32 + } else { + 33i32 + }, + 0 as *const libc::c_char, + 0 as *const libc::c_char, + 1i32 as uint32_t, + ); + (*msg).id = dc_send_msg(context, chat_id, msg); + (*context).cb.expect("non-null function pointer")( + context, + 2000i32, + chat_id as uintptr_t, + (*msg).id as uintptr_t, + ); + } + (*context).cb.expect("non-null function pointer")( + context, + 2020i32, + chat_id as uintptr_t, + 0i32 as uintptr_t, + ); + success = 1i32 + } + } + } + } + } + } + dc_chat_unref(chat); + dc_msg_unref(msg); + free(new_image_rel as *mut libc::c_void); + return success; +} +#[no_mangle] +pub unsafe extern "C" fn dc_forward_msgs( + mut context: *mut 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 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; + 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); + q3 = sqlite3_mprintf( + b"SELECT id FROM msgs WHERE id IN(%s) ORDER BY timestamp,id\x00" as *const u8 + as *const libc::c_char, + idsstr, + ); + stmt = dc_sqlite3_prepare((*context).sql, 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); + if (*msg).from_id != 1i32 as libc::c_uint { + dc_param_set_int((*msg).param, 'a' as i32, 1i32); + } + 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; + if (*msg).state == 18i32 { + let fresh9 = curr_timestamp; + curr_timestamp = curr_timestamp + 1; + new_msg_id = prepare_msg_raw(context, chat, msg, fresh9); + let mut save_param: *mut dc_param_t = (*msg).param; + (*msg).param = original_param; + (*msg).id = src_msg_id as uint32_t; + let mut old_fwd: *mut libc::c_char = dc_param_get( + (*msg).param, + 'P' as i32, + b"\x00" as *const u8 as *const libc::c_char, + ); + let mut new_fwd: *mut libc::c_char = dc_mprintf( + b"%s %d\x00" as *const u8 as *const libc::c_char, + old_fwd, + new_msg_id, + ); + dc_param_set((*msg).param, 'P' as i32, new_fwd); + dc_msg_save_param_to_disk(msg); + free(new_fwd as *mut libc::c_void); + free(old_fwd as *mut libc::c_void); + (*msg).param = save_param + } else { + (*msg).state = 20i32; + let fresh10 = curr_timestamp; + curr_timestamp = curr_timestamp + 1; + new_msg_id = prepare_msg_raw(context, chat, msg, fresh10); + dc_job_send_msg(context, new_msg_id); + } + carray_add( + created_db_entries, + chat_id as uintptr_t as *mut libc::c_void, + 0 as *mut libc::c_uint, + ); + carray_add( + created_db_entries, + new_msg_id as uintptr_t as *mut libc::c_void, + 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: size_t = 0; + let mut icnt: size_t = carray_count(created_db_entries) as size_t; + i = 0i32 as size_t; + while i < icnt { + (*context).cb.expect("non-null function pointer")( + context, + 2000i32, + carray_get(created_db_entries, i as libc::c_uint) as uintptr_t, + carray_get( + created_db_entries, + i.wrapping_add(1i32 as libc::c_ulong) as libc::c_uint, + ) as uintptr_t, + ); + i = (i as libc::c_ulong).wrapping_add(2i32 as libc::c_ulong) as size_t as size_t + } + carray_free(created_db_entries); + } + dc_contact_unref(contact); + dc_msg_unref(msg); + dc_chat_unref(chat); + sqlite3_finalize(stmt); + free(idsstr as *mut libc::c_void); + sqlite3_free(q3 as *mut libc::c_void); + dc_param_unref(original_param); +} +#[no_mangle] +pub unsafe extern "C" 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; +} +#[no_mangle] +pub unsafe extern "C" 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; +} +#[no_mangle] +pub unsafe extern "C" 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); +} +#[no_mangle] +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; + if chat.is_null() || (*chat).magic != 0xc4a7c4a7u32 { + return dc_strdup(b"Err\x00" as *const u8 as *const libc::c_char); + } + 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 stmt: *mut sqlite3_stmt = + dc_sqlite3_prepare((*(*chat).context).sql, + 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); + r = sqlite3_step(stmt); + if r == 100i32 { + ret = dc_strdup(sqlite3_column_text(stmt, 0i32) as *const libc::c_char) + } + sqlite3_finalize(stmt); + } else if (*chat).type_0 == 120i32 || (*chat).type_0 == 130i32 { + let mut cnt: libc::c_int = 0i32; + if (*chat).id == 1i32 as libc::c_uint { + ret = dc_stock_str((*chat).context, 8i32) + } else { + cnt = dc_get_chat_contact_cnt((*chat).context, (*chat).id); + ret = dc_stock_str_repl_int((*chat).context, 4i32, cnt) + } + } + return if !ret.is_null() { + ret + } else { + dc_strdup(b"Err\x00" as *const u8 as *const libc::c_char) + }; +} +#[no_mangle] +pub unsafe extern "C" fn dc_get_chat_contact_cnt( + mut context: *mut 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, + b"SELECT COUNT(*) FROM chats_contacts 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; +} +#[no_mangle] +pub unsafe extern "C" 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; + let mut contacts: *mut dc_array_t = 0 as *mut dc_array_t; + let mut contact: *mut dc_contact_t = 0 as *mut dc_contact_t; + if !(chat.is_null() || (*chat).magic != 0xc4a7c4a7u32) { + image_rel = dc_param_get((*chat).param, 'i' as i32, 0 as *const libc::c_char); + if !image_rel.is_null() && 0 != *image_rel.offset(0isize) as libc::c_int { + image_abs = dc_get_abs_path((*chat).context, image_rel) + } else if (*chat).type_0 == 100i32 { + contacts = dc_get_chat_contacts((*chat).context, (*chat).id); + if (*contacts).count >= 1i32 as libc::c_ulong { + contact = dc_get_contact( + (*chat).context, + *(*contacts).array.offset(0isize) as uint32_t, + ); + image_abs = dc_contact_get_profile_image(contact) + } + } + } + free(image_rel as *mut libc::c_void); + dc_array_unref(contacts); + dc_contact_unref(contact); + return image_abs; +} +#[no_mangle] +pub unsafe extern "C" 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; + let mut contact: *mut dc_contact_t = 0 as *mut dc_contact_t; + if !(chat.is_null() || (*chat).magic != 0xc4a7c4a7u32) { + if (*chat).type_0 == 100i32 { + contacts = dc_get_chat_contacts((*chat).context, (*chat).id); + if (*contacts).count >= 1i32 as libc::c_ulong { + contact = dc_get_contact( + (*chat).context, + *(*contacts).array.offset(0isize) as uint32_t, + ); + color = dc_str_to_color((*contact).addr) as uint32_t + } + } else { + color = dc_str_to_color((*chat).name) as uint32_t + } + } + dc_array_unref(contacts); + dc_contact_unref(contact); + return color; +} +#[no_mangle] +pub unsafe extern "C" 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; +} +#[no_mangle] +pub unsafe extern "C" 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); +} +#[no_mangle] +pub unsafe extern "C" 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; +} +#[no_mangle] +pub unsafe extern "C" 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; +} +#[no_mangle] +pub unsafe extern "C" fn dc_get_chat_cnt(mut context: *mut 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()) + { + /* no database, no chats - this is no error (needed eg. for information) */ + stmt = dc_sqlite3_prepare( + (*context).sql, + b"SELECT COUNT(*) FROM chats WHERE id>9 AND blocked=0;\x00" as *const u8 + as *const libc::c_char, + ); + if !(sqlite3_step(stmt) != 100i32) { + ret = sqlite3_column_int(stmt, 0i32) as size_t + } + } + sqlite3_finalize(stmt); + return ret; +} +#[no_mangle] +pub unsafe extern "C" fn dc_get_chat_id_by_grpid( + mut context: *mut 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; + 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 + } + } + } + sqlite3_finalize(stmt); + return chat_id; +} +#[no_mangle] +pub unsafe extern "C" fn dc_add_device_msg( + mut context: *mut 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 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()) { + stmt = + dc_sqlite3_prepare((*context).sql, + 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); + sqlite3_bind_int(stmt, 2i32, 2i32); + sqlite3_bind_int(stmt, 3i32, 2i32); + sqlite3_bind_int64( + stmt, + 4i32, + dc_create_smeared_timestamp(context) as sqlite3_int64, + ); + sqlite3_bind_int(stmt, 5i32, 10i32); + sqlite3_bind_int(stmt, 6i32, 13i32); + sqlite3_bind_text(stmt, 7i32, text, -1i32, None); + sqlite3_bind_text(stmt, 8i32, rfc724_mid, -1i32, None); + if !(sqlite3_step(stmt) != 101i32) { + msg_id = dc_sqlite3_get_rowid( + (*context).sql, + 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.expect("non-null function pointer")( + context, + 2000i32, + chat_id as uintptr_t, + msg_id as uintptr_t, + ); + } + } + free(rfc724_mid as *mut libc::c_void); + sqlite3_finalize(stmt); +} diff --git a/src/dc_chatlist.rs b/src/dc_chatlist.rs new file mode 100644 index 000000000..254182833 --- /dev/null +++ b/src/dc_chatlist.rs @@ -0,0 +1,1358 @@ +use c2rust_bitfields::BitfieldStruct; +use libc; +extern "C" { + pub type mailstream_cancel; + pub type sqlite3; + pub type sqlite3_stmt; + #[no_mangle] + fn calloc(_: libc::c_ulong, _: libc::c_ulong) -> *mut libc::c_void; + #[no_mangle] + fn free(_: *mut libc::c_void); + #[no_mangle] + fn exit(_: libc::c_int) -> !; + #[no_mangle] + fn dc_array_new(_: *mut dc_context_t, initsize: size_t) -> *mut dc_array_t; + /* * + * @class dc_array_t + * + * An object containing a simple array. + * This object is used in several places where functions need to return an array. + * The items of the array are typically IDs. + * To free an array object, use dc_array_unref(). + */ + #[no_mangle] + fn dc_array_unref(_: *mut dc_array_t); + #[no_mangle] + fn dc_array_empty(_: *mut dc_array_t); + #[no_mangle] + fn sqlite3_finalize(pStmt: *mut sqlite3_stmt) -> libc::c_int; + #[no_mangle] + fn dc_array_get_cnt(_: *const dc_array_t) -> size_t; + #[no_mangle] + fn dc_array_add_id(_: *mut dc_array_t, _: uint32_t); + /* tools, these functions are compatible to the corresponding sqlite3_* functions */ + #[no_mangle] + fn dc_sqlite3_prepare(_: *mut dc_sqlite3_t, sql: *const libc::c_char) -> *mut sqlite3_stmt; + #[no_mangle] + fn sqlite3_column_int(_: *mut sqlite3_stmt, iCol: libc::c_int) -> libc::c_int; + #[no_mangle] + fn sqlite3_step(_: *mut sqlite3_stmt) -> libc::c_int; + #[no_mangle] + fn sqlite3_bind_text( + _: *mut sqlite3_stmt, + _: libc::c_int, + _: *const libc::c_char, + _: libc::c_int, + _: Option ()>, + ) -> libc::c_int; + #[no_mangle] + fn dc_mprintf(format: *const libc::c_char, _: ...) -> *mut libc::c_char; + #[no_mangle] + fn dc_trim(_: *mut libc::c_char); + /* string tools */ + #[no_mangle] + fn dc_strdup(_: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn sqlite3_bind_int(_: *mut sqlite3_stmt, _: libc::c_int, _: libc::c_int) -> libc::c_int; + #[no_mangle] + fn dc_array_get_id(_: *const dc_array_t, index: size_t) -> uint32_t; + /* * + * @class dc_lot_t + * + * An object containing a set of values. + * The meaning of the values is defined by the function returning the object. + * Lot objects are created + * eg. by dc_chatlist_get_summary() or dc_msg_get_summary(). + * + * NB: _Lot_ is used in the meaning _heap_ here. + */ + #[no_mangle] + fn dc_lot_new() -> *mut dc_lot_t; + #[no_mangle] + fn dc_chat_unref(_: *mut dc_chat_t); + #[no_mangle] + fn dc_contact_unref(_: *mut dc_contact_t); + #[no_mangle] + fn dc_msg_unref(_: *mut dc_msg_t); + /* library-internal */ + /* in practice, the user additionally cuts the string himself pixel-accurate */ + #[no_mangle] + fn dc_lot_fill( + _: *mut dc_lot_t, + _: *const dc_msg_t, + _: *const dc_chat_t, + _: *const dc_contact_t, + _: *mut dc_context_t, + ); + /* Return the string with the given ID by calling DC_EVENT_GET_STRING. + The result must be free()'d! */ + #[no_mangle] + fn dc_stock_str(_: *mut dc_context_t, id: libc::c_int) -> *mut libc::c_char; + /* From: of incoming messages of unknown sender */ + /* Cc: of incoming messages of unknown sender */ + /* To: of incoming messages of unknown sender */ + /* address scanned but not verified */ + /* Reply-To: of incoming message of known sender */ + /* Cc: of incoming message of known sender */ + /* additional To:'s of incoming message of known sender */ + /* a chat was manually created for this user, but no message yet sent */ + /* message sent by us */ + /* message sent by us */ + /* message sent by us */ + /* internal use */ + /* address is in our address book */ + /* set on Alice's side for contacts like Bob that have scanned the QR code offered by her. Only means the contact has once been established using the "securejoin" procedure in the past, getting the current key verification status requires calling dc_contact_is_verified() ! */ + /* set on Bob's side for contacts scanned and verified from a QR code. Only means the contact has once been established using the "securejoin" procedure in the past, getting the current key verification status requires calling dc_contact_is_verified() ! */ + /* contact added mannually by dc_create_contact(), this should be the largets origin as otherwise the user cannot modify the names */ + /* 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 */ + #[no_mangle] + fn dc_contact_load_from_db( + _: *mut dc_contact_t, + _: *mut dc_sqlite3_t, + contact_id: uint32_t, + ) -> libc::c_int; + /* * + * @class dc_contact_t + * + * An object representing a single contact in memory. + * The contact object is not updated. + * If you want an update, you have to recreate the object. + * + * The library makes sure + * only to use names _authorized_ by the contact in `To:` or `Cc:`. + * _Given-names _as "Daddy" or "Honey" are not used there. + * For this purpose, internally, two names are tracked - + * authorized-name and given-name. + * By default, these names are equal, + * but functions working with contact names + * (eg. dc_contact_get_name(), dc_contact_get_display_name(), + * dc_contact_get_name_n_addr(), dc_contact_get_first_name(), + * dc_create_contact() or dc_add_address_book()) + * only affect the given-name. + */ + #[no_mangle] + fn dc_contact_new(_: *mut dc_context_t) -> *mut dc_contact_t; + #[no_mangle] + fn dc_msg_load_from_db(_: *mut dc_msg_t, _: *mut dc_context_t, id: uint32_t) -> libc::c_int; + #[no_mangle] + fn dc_msg_new_untyped(_: *mut dc_context_t) -> *mut dc_msg_t; + #[no_mangle] + fn dc_chat_load_from_db(_: *mut dc_chat_t, id: uint32_t) -> libc::c_int; + /* * + * @class dc_chat_t + * + * An object representing a single chat in memory. + * Chat objects are created using eg. dc_get_chat() + * and are not updated on database changes; + * if you want an update, you have to recreate the object. + */ + // virtual chat showing all messages belonging to chats flagged with chats.blocked=2 + // messages that should be deleted get this chat_id; the messages are deleted from the working thread later then. This is also needed as rfc724_mid should be preset as long as the message is not deleted on the server (otherwise it is downloaded again) + // a message is just in creation but not yet assigned to a chat (eg. we may need the message ID to set up blobs; this avoids unready message to be sent and shown) + // virtual chat showing all messages flagged with msgs.starred=2 + // only an indicator in a chatlist + // only an indicator in a chatlist + // larger chat IDs are "real" chats, their messages are "real" messages. + #[no_mangle] + fn dc_chat_new(_: *mut dc_context_t) -> *mut dc_chat_t; +} +pub type __darwin_size_t = libc::c_ulong; +pub type __darwin_ssize_t = libc::c_long; +pub type __darwin_time_t = libc::c_long; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_cond_t { + pub __sig: libc::c_long, + pub __opaque: [libc::c_char; 40], +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_mutex_t { + pub __sig: libc::c_long, + pub __opaque: [libc::c_char; 56], +} +pub type __darwin_pthread_cond_t = _opaque_pthread_cond_t; +pub type __darwin_pthread_mutex_t = _opaque_pthread_mutex_t; +pub type uintptr_t = libc::c_ulong; +pub type size_t = __darwin_size_t; +pub type uint8_t = libc::c_uchar; +pub type uint32_t = libc::c_uint; +pub type ssize_t = __darwin_ssize_t; +pub type time_t = __darwin_time_t; +pub type pthread_cond_t = __darwin_pthread_cond_t; +pub type pthread_mutex_t = __darwin_pthread_mutex_t; +#[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; +#[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) -> (); +#[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; +#[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, + 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 { + 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_capability_data { + pub cap_list: *mut clist, +} +#[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_0, + 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_0 { + 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 extern "C" 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_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, +} +#[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_1, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed_1 { + pub ft_fetch_att: *mut mailimap_fetch_att, + pub ft_fetch_att_list: *mut clist, +} +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 unnamed_2 { + 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, +} +/* define DC_USE_RPGP to enable use of rPGP instead of netpgp where available; +preferrably, this should be done in the project configuration currently */ +//#define DC_USE_RPGP 1 +/* Includes that are used frequently. This file may also be used to create predefined headers. */ +/* * Structure behind dc_context_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_context { + pub magic: uint32_t, + pub userdata: *mut libc::c_void, + pub dbfile: *mut libc::c_char, + pub blobdir: *mut libc::c_char, + pub sql: *mut dc_sqlite3_t, + pub inbox: *mut dc_imap_t, + pub inboxidle_condmutex: pthread_mutex_t, + pub perform_inbox_jobs_needed: libc::c_int, + pub probe_imap_network: libc::c_int, + pub sentbox_thread: dc_jobthread_t, + pub mvbox_thread: dc_jobthread_t, + pub smtp: *mut dc_smtp_t, + pub smtpidle_cond: pthread_cond_t, + pub smtpidle_condmutex: pthread_mutex_t, + pub smtpidle_condflag: libc::c_int, + pub smtp_suspended: libc::c_int, + pub smtp_doing_jobs: libc::c_int, + pub perform_smtp_jobs_needed: libc::c_int, + pub probe_smtp_network: libc::c_int, + pub oauth2_critical: pthread_mutex_t, + 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 type dc_lot_t = _dc_lot; +/* * Structure behind dc_lot_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_lot { + pub magic: uint32_t, + pub text1_meaning: libc::c_int, + pub text1: *mut libc::c_char, + pub text2: *mut libc::c_char, + pub timestamp: time_t, + pub state: libc::c_int, + pub id: uint32_t, + pub fingerprint: *mut libc::c_char, + pub invitenumber: *mut libc::c_char, + pub auth: *mut libc::c_char, +} +/* * + * 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 = Option< + unsafe extern "C" fn( + _: *mut dc_context_t, + _: libc::c_int, + _: uintptr_t, + _: uintptr_t, + ) -> uintptr_t, +>; +/* * + * @mainpage Getting started + * + * This document describes how to handle the Delta Chat core library. + * For general information about Delta Chat itself, + * see and . + * + * Let's start. + * + * First of all, you have to **define an event-handler-function** + * that is called by the library on specific events + * (eg. when the configuration is done or when fresh messages arrive). + * With this function you can create a Delta Chat context then: + * + * ~~~ + * #include + * + * uintptr_t event_handler_func(dc_context_t* context, int event, + * uintptr_t data1, uintptr_t data2) + * { + * return 0; // for unhandled events, it is always safe to return 0 + * } + * + * dc_context_t* context = dc_context_new(event_handler_func, NULL, NULL); + * ~~~ + * + * After that, you should make sure, + * sending and receiving jobs are processed as needed. + * For this purpose, you have to **create two threads:** + * + * ~~~ + * #include + * + * void* imap_thread_func(void* context) + * { + * while (true) { + * dc_perform_imap_jobs(context); + * dc_perform_imap_fetch(context); + * dc_perform_imap_idle(context); + * } + * } + * + * void* smtp_thread_func(void* context) + * { + * while (true) { + * dc_perform_smtp_jobs(context); + * dc_perform_smtp_idle(context); + * } + * } + * + * static pthread_t imap_thread, smtp_thread; + * pthread_create(&imap_thread, NULL, imap_thread_func, context); + * pthread_create(&smtp_thread, NULL, smtp_thread_func, context); + * ~~~ + * + * The example above uses "pthreads", + * however, you can also use anything else for thread handling. + * NB: The deltachat-core library itself does not create any threads on its own, + * however, functions, unless stated otherwise, are thread-safe. + * + * After that you can **define and open a database.** + * The database is a normal sqlite-file and is created as needed: + * + * ~~~ + * dc_open(context, "example.db", NULL); + * ~~~ + * + * Now you can **configure the context:** + * + * ~~~ + * // use some real test credentials here + * dc_set_config(context, "addr", "alice@example.org"); + * dc_set_config(context, "mail_pw", "***"); + * dc_configure(context); + * ~~~ + * + * dc_configure() returns immediately, the configuration itself may take a while + * and is done by a job in the imap-thread you've defined above. + * Once done, the #DC_EVENT_CONFIGURE_PROGRESS reports success + * to the event_handler_func() that is also defined above. + * + * The configuration result is saved in the database, + * on subsequent starts it is not needed to call dc_configure() + * (you can check this using dc_is_configured()). + * + * Now you can **send the first message:** + * + * ~~~ + * // use a real testing address here + * uint32_t contact_id = dc_create_contact(context, NULL, "bob@example.org"); + * uint32_t chat_id = dc_create_chat_by_contact_id(context, contact_id); + * + * dc_send_text_msg(context, chat_id, "Hi, here is my first message!"); + * ~~~ + * + * dc_send_text_msg() returns immediately; + * the sending itself is done by a job in the smtp-thread you've defined above. + * If you check the testing address (bob) + * and you should have received a normal email. + * Answer this email in any email program with "Got it!" + * and the imap-thread you've create above will **receive the message**. + * + * You can then **list all messages** of a chat as follow: + * + * ~~~ + * dc_array_t* msglist = dc_get_chat_msgs(context, chat_id, 0, 0); + * for (int i = 0; i < dc_array_get_cnt(msglist); i++) + * { + * uint32_t msg_id = dc_array_get_id(msglist, i); + * dc_msg_t* msg = dc_get_msg(context, msg_id); + * char* text = dc_msg_get_text(msg); + * + * printf("Message %i: %s\n", i+1, text); + * + * free(text); + * dc_msg_unref(msg); + * } + * dc_array_unref(msglist); + * ~~~ + * + * This will output the following two lines: + * + * ~~~ + * Message 1: Hi, here is my first message! + * Message 2: Got it! + * ~~~ + * + * + * ## Class reference + * + * For a class reference, see the "Classes" link atop. + * + * + * ## Further hints + * + * Here are some additional, unsorted hints that may be useful. + * + * - For `get`-functions, you have to unref the return value in some way. + * + * - Strings in function arguments or return values are usually UTF-8 encoded. + * + * - The issue-tracker for the core library is here: + * + * + * The following points are important mainly + * for the authors of the library itself: + * + * - For indentation, use tabs. + * Alignments that are not placed at the beginning of a line + * should be done with spaces. + * + * - For padding between functions, + * classes etc. use 2 empty lines + * + * - Source files are encoded as UTF-8 with Unix line endings + * (a simple `LF`, `0x0A` or `\n`) + * + * If you need further assistance, + * please do not hesitate to contact us + * through the channels shown at https://delta.chat/en/contribute + * + * Please keep in mind, that your derived work + * must respect the Mozilla Public License 2.0 of libdeltachat + * and the respective licenses of the libraries libdeltachat links with. + * + * See you. + */ +/* * + * @class dc_context_t + * + * An object representing a single account. + * + * Each account is linked to an IMAP/SMTP account and uses a separate + * SQLite database for offline functionality and for account-related + * settings. + */ +pub type dc_context_t = _dc_context; +/* ** library-private **********************************************************/ +pub type dc_smtp_t = _dc_smtp; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_smtp { + 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 error: *mut libc::c_char, + pub error_etpan: libc::c_int, +} +pub type dc_jobthread_t = _dc_jobthread; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_jobthread { + 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, + 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, +} +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_imap { + 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 type dc_receive_imf_t = Option< + unsafe extern "C" 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_imap_t = _dc_imap; +pub type dc_precheck_imf_t = Option< + unsafe extern "C" 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< + unsafe extern "C" fn(_: *mut dc_imap_t, _: *const libc::c_char, _: *const libc::c_char) -> (), +>; +pub type dc_get_config_t = Option< + unsafe extern "C" fn( + _: *mut dc_imap_t, + _: *const libc::c_char, + _: *const libc::c_char, + ) -> *mut libc::c_char, +>; +/* ** library-private **********************************************************/ +pub type dc_sqlite3_t = _dc_sqlite3; +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_sqlite3 { + pub cobj: *mut sqlite3, + pub context: *mut dc_context_t, +} +/* * the structure behind dc_array_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_array { + 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, +} +pub type dc_array_t = _dc_array; +/* * the structure behind dc_chatlist_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_chatlist { + pub magic: uint32_t, + pub context: *mut dc_context_t, + pub cnt: size_t, + pub chatNlastmsg_ids: *mut dc_array_t, +} +pub type dc_chatlist_t = _dc_chatlist; +/* values for the chats.blocked database field */ +/* * the structure behind dc_chat_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_chat { + 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 grpid: *mut libc::c_char, + pub blocked: libc::c_int, + pub param: *mut dc_param_t, + pub gossiped_timestamp: time_t, + pub is_sending_locations: libc::c_int, +} +pub type dc_param_t = _dc_param; +/* * + * @class dc_param_t + * + * An object for handling key=value parameter lists; for the key, curently only + * a single character is allowed. + * + * The object is used eg. by dc_chat_t or dc_msg_t, for readable paramter names, + * these classes define some DC_PARAM_* constantats. + * + * Only for library-internal use. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_param { + pub packed: *mut libc::c_char, +} +pub type dc_chat_t = _dc_chat; +/* * the structure behind dc_msg_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_msg { + pub magic: uint32_t, + pub id: uint32_t, + pub from_id: uint32_t, + pub to_id: uint32_t, + pub chat_id: uint32_t, + pub move_state: dc_move_state_t, + pub type_0: libc::c_int, + pub state: libc::c_int, + pub hidden: libc::c_int, + pub timestamp_sort: time_t, + pub timestamp_sent: time_t, + pub timestamp_rcvd: time_t, + pub text: *mut libc::c_char, + pub context: *mut 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, + pub server_uid: uint32_t, + pub is_dc_message: libc::c_int, + pub starred: libc::c_int, + pub chat_blocked: libc::c_int, + pub location_id: uint32_t, + pub param: *mut dc_param_t, +} +pub type dc_move_state_t = libc::c_uint; +pub const DC_MOVE_STATE_MOVING: dc_move_state_t = 3; +pub const DC_MOVE_STATE_STAY: dc_move_state_t = 2; +pub const DC_MOVE_STATE_PENDING: dc_move_state_t = 1; +pub const DC_MOVE_STATE_UNDEFINED: dc_move_state_t = 0; +pub type dc_msg_t = _dc_msg; +/* * the structure behind dc_contact_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_contact { + pub magic: uint32_t, + pub context: *mut dc_context_t, + pub id: uint32_t, + pub name: *mut libc::c_char, + pub authname: *mut libc::c_char, + pub addr: *mut libc::c_char, + pub blocked: libc::c_int, + pub origin: libc::c_int, +} +pub type dc_contact_t = _dc_contact; +pub type sqlite3_destructor_type = Option ()>; +// handle chatlists +#[no_mangle] +pub unsafe extern "C" fn dc_get_chatlist( + mut context: *mut dc_context_t, + mut listflags: libc::c_int, + mut query_str: *const libc::c_char, + mut query_id: uint32_t, +) -> *mut dc_chatlist_t { + 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 != success { + return obj; + } else { + dc_chatlist_unref(obj); + return 0 as *mut dc_chatlist_t; + }; +} +/* * + * @class dc_chatlist_t + * + * An object representing a single chatlist in memory. + * Chatlist objects contain chat IDs + * and, if possible, message IDs belonging to them. + * The chatlist object is not updated; + * if you want an update, you have to recreate the object. + * + * For a **typical chat overview**, + * the idea is to get the list of all chats via dc_get_chatlist() + * without any listflags (see below) + * and to implement a "virtual list" or so + * (the count of chats is known by dc_chatlist_get_cnt()). + * + * Only for the items that are in view + * (the list may have several hundreds chats), + * the UI should call dc_chatlist_get_summary() then. + * dc_chatlist_get_summary() provides all elements needed for painting the item. + * + * On a click of such an item, + * the UI should change to the chat view + * and get all messages from this view via dc_get_chat_msgs(). + * Again, a "virtual list" is created + * (the count of messages is known) + * and for each messages that is scrolled into view, dc_get_msg() is called then. + * + * Why no listflags? + * Without listflags, dc_get_chatlist() adds the deaddrop + * and the archive "link" automatically as needed. + * The UI can just render these items differently then. + * Although the deaddrop link is currently always the first entry + * and only present on new messages, + * there is the rough idea that it can be optionally always present + * and sorted into the list by date. + * Rendering the deaddrop in the described way + * would not add extra work in the UI then. + */ +#[no_mangle] +pub unsafe extern "C" 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; + chatlist = calloc( + 1i32 as libc::c_ulong, + ::std::mem::size_of::() as libc::c_ulong, + ) 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); + if (*chatlist).chatNlastmsg_ids.is_null() { + exit(32i32); + } + return chatlist; +} +#[no_mangle] +pub unsafe extern "C" fn dc_chatlist_unref(mut chatlist: *mut dc_chatlist_t) { + if chatlist.is_null() || (*chatlist).magic != 0xc4a71157u32 { + return; + } + dc_chatlist_empty(chatlist); + dc_array_unref((*chatlist).chatNlastmsg_ids); + (*chatlist).magic = 0i32 as uint32_t; + free(chatlist as *mut libc::c_void); +} +#[no_mangle] +pub unsafe extern "C" fn dc_chatlist_empty(mut chatlist: *mut dc_chatlist_t) { + if chatlist.is_null() || (*chatlist).magic != 0xc4a71157u32 { + return; + } + (*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 + */ +unsafe extern "C" fn dc_chatlist_load_from_db( + mut chatlist: *mut dc_chatlist_t, + mut listflags: libc::c_int, + mut query__: *const libc::c_char, + mut query_contact_id: uint32_t, +) -> libc::c_int { + let mut current_block: u64; + //clock_t start = clock(); + let mut success: libc::c_int = 0i32; + let mut add_archived_link_item: libc::c_int = 0i32; + 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()) + { + dc_chatlist_empty(chatlist); + // select with left join and minimum: + // - the inner select must use `hidden` and _not_ `m.hidden` + // which would refer the outer select and take a lot of time + // - `GROUP BY` is needed several messages may have the same timestamp + // - the list starts with the newest chats + // nb: the query currently shows messages from blocked contacts in groups. + // however, for normal-groups, this is okay as the message is also returned by dc_get_chat_msgs() + // (otherwise it would be hard to follow conversations, wa and tg do the same) + // for the deaddrop, however, they should really be hidden, however, _currently_ the deaddrop is not + // 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); + 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" + as *const u8 as *const libc::c_char); + current_block = 3437258052017859086; + } else if query__.is_null() { + if 0 == listflags & 0x2i32 { + let mut last_deaddrop_fresh_msg_id: uint32_t = + get_last_deaddrop_fresh_msg((*chatlist).context); + if last_deaddrop_fresh_msg_id > 0i32 as libc::c_uint { + dc_array_add_id((*chatlist).chatNlastmsg_ids, 1i32 as uint32_t); + dc_array_add_id((*chatlist).chatNlastmsg_ids, last_deaddrop_fresh_msg_id); + } + add_archived_link_item = 1i32 + } + 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=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; + } else { + query = dc_strdup(query__); + dc_trim(query); + if *query.offset(0isize) as libc::c_int == 0i32 { + success = 1i32; + current_block = 15179736777190528364; + } 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" + as *const u8 as + *const libc::c_char); + sqlite3_bind_text(stmt, 1i32, strLikeCmd, -1i32, None); + current_block = 3437258052017859086; + } + } + match current_block { + 15179736777190528364 => {} + _ => { + while sqlite3_step(stmt) == 100i32 { + dc_array_add_id( + (*chatlist).chatNlastmsg_ids, + sqlite3_column_int(stmt, 0i32) as uint32_t, + ); + dc_array_add_id( + (*chatlist).chatNlastmsg_ids, + sqlite3_column_int(stmt, 1i32) as uint32_t, + ); + } + if 0 != add_archived_link_item && dc_get_archived_cnt((*chatlist).context) > 0i32 { + if dc_array_get_cnt((*chatlist).chatNlastmsg_ids) == 0i32 as libc::c_ulong + && 0 != listflags & 0x4i32 + { + dc_array_add_id((*chatlist).chatNlastmsg_ids, 7i32 as uint32_t); + dc_array_add_id((*chatlist).chatNlastmsg_ids, 0i32 as uint32_t); + } + dc_array_add_id((*chatlist).chatNlastmsg_ids, 6i32 as uint32_t); + dc_array_add_id((*chatlist).chatNlastmsg_ids, 0i32 as uint32_t); + } + (*chatlist).cnt = dc_array_get_cnt((*chatlist).chatNlastmsg_ids) + .wrapping_div(2i32 as libc::c_ulong); + success = 1i32 + } + } + } + sqlite3_finalize(stmt); + free(query as *mut libc::c_void); + free(strLikeCmd as *mut libc::c_void); + return success; +} +// Context functions to work with chatlist +#[no_mangle] +pub unsafe extern "C" fn dc_get_archived_cnt(mut context: *mut dc_context_t) -> libc::c_int { + let mut ret: libc::c_int = 0i32; + let mut stmt: *mut sqlite3_stmt = dc_sqlite3_prepare( + (*context).sql, + b"SELECT COUNT(*) FROM chats WHERE blocked=0 AND archived=1;\x00" as *const u8 + as *const libc::c_char, + ); + if sqlite3_step(stmt) == 100i32 { + ret = sqlite3_column_int(stmt, 0i32) + } + sqlite3_finalize(stmt); + return ret; +} +unsafe extern "C" fn get_last_deaddrop_fresh_msg(mut context: *mut 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; + 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" + 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; +} +#[no_mangle] +pub unsafe extern "C" 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; +} +#[no_mangle] +pub unsafe extern "C" fn dc_chatlist_get_chat_id( + mut chatlist: *const dc_chatlist_t, + mut index: size_t, +) -> uint32_t { + if chatlist.is_null() + || (*chatlist).magic != 0xc4a71157u32 + || (*chatlist).chatNlastmsg_ids.is_null() + || index >= (*chatlist).cnt + { + return 0i32 as uint32_t; + } + return dc_array_get_id( + (*chatlist).chatNlastmsg_ids, + index.wrapping_mul(2i32 as libc::c_ulong), + ); +} +#[no_mangle] +pub unsafe extern "C" fn dc_chatlist_get_msg_id( + mut chatlist: *const dc_chatlist_t, + mut index: size_t, +) -> uint32_t { + if chatlist.is_null() + || (*chatlist).magic != 0xc4a71157u32 + || (*chatlist).chatNlastmsg_ids.is_null() + || index >= (*chatlist).cnt + { + return 0i32 as uint32_t; + } + return dc_array_get_id( + (*chatlist).chatNlastmsg_ids, + index + .wrapping_mul(2i32 as libc::c_ulong) + .wrapping_add(1i32 as libc::c_ulong), + ); +} +#[no_mangle] +pub unsafe extern "C" fn dc_chatlist_get_summary( + mut chatlist: *const dc_chatlist_t, + mut index: size_t, + mut chat: *mut dc_chat_t, +) -> *mut dc_lot_t { + let mut current_block: u64; + /* The summary is created by the chat, not by the last message. + This is because we may want to display drafts here or stuff as + "is typing". + Also, sth. as "No messages" would not work if the summary comes from a + 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: *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; + if chatlist.is_null() || (*chatlist).magic != 0xc4a71157u32 || index >= (*chatlist).cnt { + (*ret).text2 = dc_strdup(b"ErrBadChatlistIndex\x00" as *const u8 as *const libc::c_char) + } else { + lastmsg_id = dc_array_get_id( + (*chatlist).chatNlastmsg_ids, + index + .wrapping_mul(2i32 as libc::c_ulong) + .wrapping_add(1i32 as libc::c_ulong), + ); + if chat.is_null() { + chat = dc_chat_new((*chatlist).context); + chat_to_delete = chat; + if 0 == dc_chat_load_from_db( + chat, + dc_array_get_id( + (*chatlist).chatNlastmsg_ids, + index.wrapping_mul(2i32 as libc::c_ulong), + ), + ) { + (*ret).text2 = + dc_strdup(b"ErrCannotReadChat\x00" as *const u8 as *const libc::c_char); + current_block = 3777403817673069519; + } else { + current_block = 7651349459974463963; + } + } else { + current_block = 7651349459974463963; + } + match current_block { + 3777403817673069519 => {} + _ => { + if 0 != lastmsg_id { + lastmsg = dc_msg_new_untyped((*chatlist).context); + dc_msg_load_from_db(lastmsg, (*chatlist).context, lastmsg_id); + if (*lastmsg).from_id != 1i32 as libc::c_uint + && ((*chat).type_0 == 120i32 || (*chat).type_0 == 130i32) + { + lastcontact = dc_contact_new((*chatlist).context); + dc_contact_load_from_db( + lastcontact, + (*(*chatlist).context).sql, + (*lastmsg).from_id, + ); + } + } + if (*chat).id == 6i32 as libc::c_uint { + (*ret).text2 = dc_strdup(0 as *const libc::c_char) + } else if lastmsg.is_null() || (*lastmsg).from_id == 0i32 as libc::c_uint { + (*ret).text2 = dc_stock_str((*chatlist).context, 1i32) + } else { + dc_lot_fill(ret, lastmsg, chat, lastcontact, (*chatlist).context); + } + } + } + } + dc_msg_unref(lastmsg); + dc_contact_unref(lastcontact); + dc_chat_unref(chat_to_delete); + return ret; +} +#[no_mangle] +pub unsafe extern "C" 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; +} diff --git a/src/dc_configure.rs b/src/dc_configure.rs new file mode 100644 index 000000000..f7b2b0704 --- /dev/null +++ b/src/dc_configure.rs @@ -0,0 +1,3154 @@ +use c2rust_bitfields::BitfieldStruct; +use libc; +extern "C" { + pub type mailstream_cancel; + pub type sqlite3; + #[no_mangle] + fn calloc(_: libc::c_ulong, _: libc::c_ulong) -> *mut libc::c_void; + #[no_mangle] + fn free(_: *mut libc::c_void); + #[no_mangle] + fn atoi(_: *const libc::c_char) -> libc::c_int; + #[no_mangle] + fn memcpy(_: *mut libc::c_void, _: *const libc::c_void, _: libc::c_ulong) -> *mut libc::c_void; + #[no_mangle] + fn memset(_: *mut libc::c_void, _: libc::c_int, _: libc::c_ulong) -> *mut libc::c_void; + #[no_mangle] + fn strchr(_: *const libc::c_char, _: libc::c_int) -> *mut libc::c_char; + #[no_mangle] + fn strcmp(_: *const libc::c_char, _: *const libc::c_char) -> libc::c_int; + #[no_mangle] + fn strncmp(_: *const libc::c_char, _: *const libc::c_char, _: libc::c_ulong) -> libc::c_int; + #[no_mangle] + fn strstr(_: *const libc::c_char, _: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn strcasecmp(_: *const libc::c_char, _: *const libc::c_char) -> libc::c_int; + #[no_mangle] + fn clist_new() -> *mut clist; + #[no_mangle] + fn clist_free(_: *mut clist); + #[no_mangle] + fn clist_insert_after(_: *mut clist, _: *mut clistiter, _: *mut libc::c_void) -> libc::c_int; + #[no_mangle] + fn mailimap_xlist( + session: *mut mailimap, + mb: *const libc::c_char, + list_mb: *const libc::c_char, + result: *mut *mut clist, + ) -> libc::c_int; + #[no_mangle] + fn mailimap_create(session: *mut mailimap, mb: *const libc::c_char) -> libc::c_int; + #[no_mangle] + fn mailimap_list( + session: *mut mailimap, + mb: *const libc::c_char, + list_mb: *const libc::c_char, + result: *mut *mut clist, + ) -> libc::c_int; + #[no_mangle] + fn mailimap_list_result_free(list: *mut clist); + #[no_mangle] + fn mailimap_subscribe(session: *mut mailimap, mb: *const libc::c_char) -> libc::c_int; + #[no_mangle] + fn dc_job_add( + _: *mut dc_context_t, + action: libc::c_int, + foreign_id: libc::c_int, + param: *const libc::c_char, + delay: libc::c_int, + ); + #[no_mangle] + fn dc_job_kill_action(_: *mut dc_context_t, action: libc::c_int); + #[no_mangle] + fn dc_log_warning(_: *mut dc_context_t, data1: libc::c_int, msg: *const libc::c_char, _: ...); + #[no_mangle] + fn dc_sqlite3_get_config_int( + _: *mut dc_sqlite3_t, + key: *const libc::c_char, + def: int32_t, + ) -> int32_t; + #[no_mangle] + fn dc_log_info(_: *mut dc_context_t, data1: libc::c_int, msg: *const libc::c_char, _: ...); + #[no_mangle] + fn dc_sqlite3_is_open(_: *const dc_sqlite3_t) -> libc::c_int; + /* handle configurations, private */ + #[no_mangle] + fn dc_sqlite3_set_config( + _: *mut dc_sqlite3_t, + key: *const libc::c_char, + value: *const libc::c_char, + ) -> libc::c_int; + #[no_mangle] + fn dc_sqlite3_set_config_int( + _: *mut dc_sqlite3_t, + key: *const libc::c_char, + value: int32_t, + ) -> libc::c_int; + /* Some tools and enhancements to the used libraries, there should be + no references to dc_context_t and other "larger" classes here. */ + // for carray etc. + /* ** library-private **********************************************************/ + /* math tools */ + #[no_mangle] + fn dc_exactly_one_bit_set(v: libc::c_int) -> libc::c_int; + /* string tools */ + #[no_mangle] + fn dc_strdup(_: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn dc_strdup_keep_null(_: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn dc_atoi_null_is_0(_: *const libc::c_char) -> libc::c_int; + #[no_mangle] + fn dc_trim(_: *mut libc::c_char); + #[no_mangle] + fn dc_strlower_in_place(_: *mut libc::c_char); + #[no_mangle] + fn dc_str_replace( + haystack: *mut *mut libc::c_char, + needle: *const libc::c_char, + replacement: *const libc::c_char, + ) -> libc::c_int; + #[no_mangle] + fn dc_mprintf(format: *const libc::c_char, _: ...) -> *mut libc::c_char; + #[no_mangle] + fn dc_urlencode(_: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn dc_decode_modified_utf7( + _: *const libc::c_char, + change_spaces: libc::c_int, + ) -> *mut libc::c_char; + #[no_mangle] + fn dc_loginparam_new() -> *mut dc_loginparam_t; + #[no_mangle] + fn dc_loginparam_unref(_: *mut dc_loginparam_t); + #[no_mangle] + fn dc_loginparam_read( + _: *mut dc_loginparam_t, + _: *mut dc_sqlite3_t, + prefix: *const libc::c_char, + ); + #[no_mangle] + fn dc_loginparam_write( + _: *const dc_loginparam_t, + _: *mut dc_sqlite3_t, + prefix: *const libc::c_char, + ); + #[no_mangle] + fn dc_loginparam_get_readable(_: *const dc_loginparam_t) -> *mut libc::c_char; + #[no_mangle] + fn dc_imap_connect(_: *mut dc_imap_t, _: *const dc_loginparam_t) -> libc::c_int; + #[no_mangle] + fn dc_imap_disconnect(_: *mut dc_imap_t); + #[no_mangle] + fn dc_imap_is_connected(_: *const dc_imap_t) -> libc::c_int; + #[no_mangle] + fn dc_imap_is_error(imap: *mut dc_imap_t, code: libc::c_int) -> libc::c_int; + #[no_mangle] + fn dc_smtp_connect(_: *mut dc_smtp_t, _: *const dc_loginparam_t) -> libc::c_int; + #[no_mangle] + fn dc_smtp_disconnect(_: *mut dc_smtp_t); + #[no_mangle] + fn dc_ensure_secret_key_exists(_: *mut dc_context_t) -> libc::c_int; + #[no_mangle] + fn dc_log_error(_: *mut dc_context_t, data1: libc::c_int, msg: *const libc::c_char, _: ...); + #[no_mangle] + fn dc_saxparser_parse(_: *mut dc_saxparser_t, text: *const libc::c_char); + #[no_mangle] + fn dc_saxparser_set_text_handler(_: *mut dc_saxparser_t, _: dc_saxparser_text_cb_t); + #[no_mangle] + fn dc_attr_find(attr: *mut *mut libc::c_char, key: *const libc::c_char) -> *const libc::c_char; + #[no_mangle] + fn dc_saxparser_set_tag_handler( + _: *mut dc_saxparser_t, + _: dc_saxparser_starttag_cb_t, + _: dc_saxparser_endtag_cb_t, + ); + #[no_mangle] + fn dc_saxparser_init(_: *mut dc_saxparser_t, userData: *mut libc::c_void); + #[no_mangle] + fn dc_get_oauth2_addr( + _: *mut dc_context_t, + addr: *const libc::c_char, + code: *const libc::c_char, + ) -> *mut libc::c_char; +} +pub type __darwin_size_t = libc::c_ulong; +pub type __darwin_ssize_t = libc::c_long; +pub type __darwin_time_t = libc::c_long; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_cond_t { + pub __sig: libc::c_long, + pub __opaque: [libc::c_char; 40], +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_mutex_t { + pub __sig: libc::c_long, + pub __opaque: [libc::c_char; 56], +} +pub type __darwin_pthread_cond_t = _opaque_pthread_cond_t; +pub type __darwin_pthread_mutex_t = _opaque_pthread_mutex_t; +pub type size_t = __darwin_size_t; +pub type uint32_t = libc::c_uint; +pub type int32_t = libc::c_int; +pub type uintptr_t = libc::c_ulong; +pub type ssize_t = __darwin_ssize_t; +pub type time_t = __darwin_time_t; +pub type uint8_t = libc::c_uchar; +pub type uint16_t = libc::c_ushort; +pub type pthread_cond_t = __darwin_pthread_cond_t; +pub type pthread_mutex_t = __darwin_pthread_mutex_t; +#[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; +#[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) -> (); +#[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, + 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 { + 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_capability_data { + pub cap_list: *mut clist, +} +#[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_0, + 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_0 { + 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 extern "C" 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_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_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, +} +pub type unnamed_1 = libc::c_uint; +pub const MAILIMAP_MBX_LIST_OFLAG_FLAG_EXT: unnamed_1 = 2; +pub const MAILIMAP_MBX_LIST_OFLAG_NOINFERIORS: unnamed_1 = 1; +pub const MAILIMAP_MBX_LIST_OFLAG_ERROR: unnamed_1 = 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_msg_att { + pub att_list: *mut clist, + pub att_number: uint32_t, +} +#[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_2, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed_2 { + pub ft_fetch_att: *mut mailimap_fetch_att, + pub ft_fetch_att_list: *mut clist, +} +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_3, +// 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 unnamed_3 { + 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, +} +/* define DC_USE_RPGP to enable use of rPGP instead of netpgp where available; +preferrably, this should be done in the project configuration currently */ +//#define DC_USE_RPGP 1 +/* Includes that are used frequently. This file may also be used to create predefined headers. */ +/* * Structure behind dc_context_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_context { + pub magic: uint32_t, + pub userdata: *mut libc::c_void, + pub dbfile: *mut libc::c_char, + pub blobdir: *mut libc::c_char, + pub sql: *mut dc_sqlite3_t, + pub inbox: *mut dc_imap_t, + pub inboxidle_condmutex: pthread_mutex_t, + pub perform_inbox_jobs_needed: libc::c_int, + pub probe_imap_network: libc::c_int, + pub sentbox_thread: dc_jobthread_t, + pub mvbox_thread: dc_jobthread_t, + pub smtp: *mut dc_smtp_t, + pub smtpidle_cond: pthread_cond_t, + pub smtpidle_condmutex: pthread_mutex_t, + pub smtpidle_condflag: libc::c_int, + pub smtp_suspended: libc::c_int, + pub smtp_doing_jobs: libc::c_int, + pub perform_smtp_jobs_needed: libc::c_int, + pub probe_smtp_network: libc::c_int, + pub oauth2_critical: pthread_mutex_t, + 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 type dc_lot_t = _dc_lot; +/* * Structure behind dc_lot_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_lot { + pub magic: uint32_t, + pub text1_meaning: libc::c_int, + pub text1: *mut libc::c_char, + pub text2: *mut libc::c_char, + pub timestamp: time_t, + pub state: libc::c_int, + pub id: uint32_t, + pub fingerprint: *mut libc::c_char, + pub invitenumber: *mut libc::c_char, + pub auth: *mut libc::c_char, +} +/* * + * 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 = Option< + unsafe extern "C" fn( + _: *mut dc_context_t, + _: libc::c_int, + _: uintptr_t, + _: uintptr_t, + ) -> uintptr_t, +>; +/* * + * @mainpage Getting started + * + * This document describes how to handle the Delta Chat core library. + * For general information about Delta Chat itself, + * see and . + * + * Let's start. + * + * First of all, you have to **define an event-handler-function** + * that is called by the library on specific events + * (eg. when the configuration is done or when fresh messages arrive). + * With this function you can create a Delta Chat context then: + * + * ~~~ + * #include + * + * uintptr_t event_handler_func(dc_context_t* context, int event, + * uintptr_t data1, uintptr_t data2) + * { + * return 0; // for unhandled events, it is always safe to return 0 + * } + * + * dc_context_t* context = dc_context_new(event_handler_func, NULL, NULL); + * ~~~ + * + * After that, you should make sure, + * sending and receiving jobs are processed as needed. + * For this purpose, you have to **create two threads:** + * + * ~~~ + * #include + * + * void* imap_thread_func(void* context) + * { + * while (true) { + * dc_perform_imap_jobs(context); + * dc_perform_imap_fetch(context); + * dc_perform_imap_idle(context); + * } + * } + * + * void* smtp_thread_func(void* context) + * { + * while (true) { + * dc_perform_smtp_jobs(context); + * dc_perform_smtp_idle(context); + * } + * } + * + * static pthread_t imap_thread, smtp_thread; + * pthread_create(&imap_thread, NULL, imap_thread_func, context); + * pthread_create(&smtp_thread, NULL, smtp_thread_func, context); + * ~~~ + * + * The example above uses "pthreads", + * however, you can also use anything else for thread handling. + * NB: The deltachat-core library itself does not create any threads on its own, + * however, functions, unless stated otherwise, are thread-safe. + * + * After that you can **define and open a database.** + * The database is a normal sqlite-file and is created as needed: + * + * ~~~ + * dc_open(context, "example.db", NULL); + * ~~~ + * + * Now you can **configure the context:** + * + * ~~~ + * // use some real test credentials here + * dc_set_config(context, "addr", "alice@example.org"); + * dc_set_config(context, "mail_pw", "***"); + * dc_configure(context); + * ~~~ + * + * dc_configure() returns immediately, the configuration itself may take a while + * and is done by a job in the imap-thread you've defined above. + * Once done, the #DC_EVENT_CONFIGURE_PROGRESS reports success + * to the event_handler_func() that is also defined above. + * + * The configuration result is saved in the database, + * on subsequent starts it is not needed to call dc_configure() + * (you can check this using dc_is_configured()). + * + * Now you can **send the first message:** + * + * ~~~ + * // use a real testing address here + * uint32_t contact_id = dc_create_contact(context, NULL, "bob@example.org"); + * uint32_t chat_id = dc_create_chat_by_contact_id(context, contact_id); + * + * dc_send_text_msg(context, chat_id, "Hi, here is my first message!"); + * ~~~ + * + * dc_send_text_msg() returns immediately; + * the sending itself is done by a job in the smtp-thread you've defined above. + * If you check the testing address (bob) + * and you should have received a normal email. + * Answer this email in any email program with "Got it!" + * and the imap-thread you've create above will **receive the message**. + * + * You can then **list all messages** of a chat as follow: + * + * ~~~ + * dc_array_t* msglist = dc_get_chat_msgs(context, chat_id, 0, 0); + * for (int i = 0; i < dc_array_get_cnt(msglist); i++) + * { + * uint32_t msg_id = dc_array_get_id(msglist, i); + * dc_msg_t* msg = dc_get_msg(context, msg_id); + * char* text = dc_msg_get_text(msg); + * + * printf("Message %i: %s\n", i+1, text); + * + * free(text); + * dc_msg_unref(msg); + * } + * dc_array_unref(msglist); + * ~~~ + * + * This will output the following two lines: + * + * ~~~ + * Message 1: Hi, here is my first message! + * Message 2: Got it! + * ~~~ + * + * + * ## Class reference + * + * For a class reference, see the "Classes" link atop. + * + * + * ## Further hints + * + * Here are some additional, unsorted hints that may be useful. + * + * - For `get`-functions, you have to unref the return value in some way. + * + * - Strings in function arguments or return values are usually UTF-8 encoded. + * + * - The issue-tracker for the core library is here: + * + * + * The following points are important mainly + * for the authors of the library itself: + * + * - For indentation, use tabs. + * Alignments that are not placed at the beginning of a line + * should be done with spaces. + * + * - For padding between functions, + * classes etc. use 2 empty lines + * + * - Source files are encoded as UTF-8 with Unix line endings + * (a simple `LF`, `0x0A` or `\n`) + * + * If you need further assistance, + * please do not hesitate to contact us + * through the channels shown at https://delta.chat/en/contribute + * + * Please keep in mind, that your derived work + * must respect the Mozilla Public License 2.0 of libdeltachat + * and the respective licenses of the libraries libdeltachat links with. + * + * See you. + */ +/* * + * @class dc_context_t + * + * An object representing a single account. + * + * Each account is linked to an IMAP/SMTP account and uses a separate + * SQLite database for offline functionality and for account-related + * settings. + */ +//pub type dc_context_t = _dc_context; +use crate::dc_context::*; +/* ** library-private **********************************************************/ +// pub type dc_smtp_t = _dc_smtp; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_smtp { + 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 error: *mut libc::c_char, + pub error_etpan: libc::c_int, +} +// pub type dc_jobthread_t = _dc_jobthread; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_jobthread { + 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, + 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, +} +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_imap { + 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 type dc_receive_imf_t = Option< + unsafe extern "C" 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_imap_t = _dc_imap; +pub type dc_precheck_imf_t = Option< + unsafe extern "C" 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< + unsafe extern "C" fn(_: *mut dc_imap_t, _: *const libc::c_char, _: *const libc::c_char) -> (), +>; +pub type dc_get_config_t = Option< + unsafe extern "C" fn( + _: *mut dc_imap_t, + _: *const libc::c_char, + _: *const libc::c_char, + ) -> *mut libc::c_char, +>; +/* ** library-private **********************************************************/ +// pub type dc_sqlite3_t = _dc_sqlite3; +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_sqlite3 { + pub cobj: *mut sqlite3, + pub context: *mut dc_context_t, +} +pub type dc_param_t = _dc_param; +/* * + * @class dc_param_t + * + * An object for handling key=value parameter lists; for the key, curently only + * a single character is allowed. + * + * The object is used eg. by dc_chat_t or dc_msg_t, for readable paramter names, + * these classes define some DC_PARAM_* constantats. + * + * Only for library-internal use. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_param { + pub packed: *mut libc::c_char, +} +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_loginparam { + pub addr: *mut libc::c_char, + pub mail_server: *mut libc::c_char, + pub mail_user: *mut libc::c_char, + pub mail_pw: *mut libc::c_char, + pub mail_port: uint16_t, + pub send_server: *mut libc::c_char, + pub send_user: *mut libc::c_char, + pub send_pw: *mut libc::c_char, + pub send_port: libc::c_int, + pub server_flags: libc::c_int, +} +pub type dc_loginparam_t = _dc_loginparam; +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_job { + pub job_id: uint32_t, + pub action: libc::c_int, + pub foreign_id: uint32_t, + pub desired_timestamp: time_t, + pub added_timestamp: time_t, + pub tries: libc::c_int, + pub param: *mut dc_param_t, + pub try_again: libc::c_int, + pub pending_error: *mut libc::c_char, +} +// thread IDs +// jobs in the INBOX-thread, range from DC_IMAP_THREAD..DC_IMAP_THREAD+999 +// low priority ... +// ... high priority +// jobs in the SMTP-thread, range from DC_SMTP_THREAD..DC_SMTP_THREAD+999 +// low priority ... +// ... high priority +// timeouts until actions are aborted. +// this may also affects IDLE to return, so a re-connect may take this time. +// mailcore2 uses 30 seconds, k-9 uses 10 seconds +pub type dc_job_t = _dc_job; +/* ****************************************************************************** + * Configure folders + ******************************************************************************/ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct dc_imapfolder_t { + pub name_to_select: *mut libc::c_char, + pub name_utf8: *mut libc::c_char, + pub meaning: libc::c_int, +} +/* ****************************************************************************** + * Thunderbird's Autoconfigure + ******************************************************************************/ +/* documentation: https://developer.mozilla.org/en-US/docs/Mozilla/Thunderbird/Autoconfiguration */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct moz_autoconfigure_t { + pub in_0: *const dc_loginparam_t, + pub in_emaildomain: *mut libc::c_char, + pub in_emaillocalpart: *mut libc::c_char, + pub out: *mut dc_loginparam_t, + pub out_imap_set: libc::c_int, + pub out_smtp_set: libc::c_int, + pub tag_server: libc::c_int, + pub tag_config: libc::c_int, +} +pub type dc_saxparser_t = _dc_saxparser; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_saxparser { + pub starttag_cb: dc_saxparser_starttag_cb_t, + pub endtag_cb: dc_saxparser_endtag_cb_t, + pub text_cb: dc_saxparser_text_cb_t, + pub userdata: *mut libc::c_void, +} +/* len is only informational, text is already null-terminated */ +pub type dc_saxparser_text_cb_t = Option< + unsafe extern "C" fn(_: *mut libc::c_void, _: *const libc::c_char, _: libc::c_int) -> (), +>; +pub type dc_saxparser_endtag_cb_t = + Option ()>; +pub type dc_saxparser_starttag_cb_t = Option< + unsafe extern "C" fn( + _: *mut libc::c_void, + _: *const libc::c_char, + _: *mut *mut libc::c_char, + ) -> (), +>; +/* ****************************************************************************** + * Outlook's Autodiscover + ******************************************************************************/ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct outlk_autodiscover_t { + pub in_0: *const dc_loginparam_t, + pub out: *mut dc_loginparam_t, + pub out_imap_set: libc::c_int, + pub out_smtp_set: libc::c_int, + pub tag_config: libc::c_int, + pub config: [*mut libc::c_char; 6], + pub redirect: *mut libc::c_char, +} +// connect +#[no_mangle] +pub unsafe extern "C" fn dc_configure(mut context: *mut dc_context_t) { + if 0 != dc_has_ongoing(context) { + dc_log_warning( + context, + 0i32, + b"There is already another ongoing process running.\x00" as *const u8 + as *const libc::c_char, + ); + return; + } + dc_job_kill_action(context, 900i32); + dc_job_add(context, 900i32, 0i32, 0 as *const libc::c_char, 0i32); +} +#[no_mangle] +pub unsafe extern "C" 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 + } else { + 0i32 + }; +} +#[no_mangle] +pub unsafe extern "C" 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; + } + return if 0 + != dc_sqlite3_get_config_int( + (*context).sql, + b"configured\x00" as *const u8 as *const libc::c_char, + 0i32, + ) { + 1i32 + } else { + 0i32 + }; +} +#[no_mangle] +pub unsafe extern "C" 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 { + 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 + } else { + dc_log_info( + context, + 0i32, + b"No ongoing process to stop.\x00" as *const u8 as *const libc::c_char, + ); + }; +} +// the other dc_job_do_DC_JOB_*() functions are declared static in the c-file +#[no_mangle] +pub unsafe extern "C" fn dc_job_do_DC_JOB_CONFIGURE_IMAP( + mut context: *mut dc_context_t, + mut job: *mut dc_job_t, +) { + let mut flags: libc::c_int = 0; + let mut current_block: u64; + let mut success: libc::c_int = 0i32; + let mut imap_connected_here: libc::c_int = 0i32; + let mut smtp_connected_here: libc::c_int = 0i32; + let mut ongoing_allocated_here: libc::c_int = 0i32; + 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_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( + 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.expect("non-null function pointer")( + context, + 2041i32, + (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, + ); + } 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 { + current_block = 2927484062889439186; + } else { + (*context).cb.expect("non-null function pointer")( + context, + 2041i32, + (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).sql, + b"addr\x00" as *const u8 as *const libc::c_char, + (*param).addr, + ); + } + if 0 != (*context).shall_stop_ongoing { + current_block = 2927484062889439186; + } else { + (*context).cb.expect("non-null function pointer")( + context, + 2041i32, + (if 20i32 < 1i32 { + 1i32 + } else if 20i32 > 999i32 { + 999i32 + } else { + 20i32 + }) 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.expect("non-null function pointer")( + context, + 2041i32, + (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 as libc::c_int == 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 + .expect("non-null function pointer")( + context, + 2041i32, + (if 300i32 < 1i32 { + 1i32 + } else if 300i32 > 999i32 { + 999i32 + } else { + 300i32 + }) + as uintptr_t, + 0i32 as uintptr_t, + ); + current_block = 13325891313334703151; + } + } else { + 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.expect( + "non-null function pointer", + )( + context, + 2041i32, + (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.expect( + "non-null function pointer", + )( + context, + 2041i32, + (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.expect("non-null function pointer")(context, + 2041i32, + (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.expect("non-null function pointer")(context, + 2041i32, + (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.expect("non-null function pointer")(context, + 2041i32, + (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; + } + 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 as libc::c_int == 0i32 { + (*param).mail_port = (if 0 + != (*param).server_flags + & (0x100i32 | 0x400i32) + { + 143i32 + } else { + 993i32 + }) + as uint16_t + } + 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, + 5i32 as libc::c_ulong, + ) == 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, + 4i32 as libc::c_ulong, + ); + } + } + 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 as libc::c_int == 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 + .expect("non-null function pointer")( + context, + 2041i32, + (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 + .expect("non-null function pointer")( + context, + 2041i32, + (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 != 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 + .expect("non-null function pointer")( + context, + 2041i32, + (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 as uint16_t; + 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 + .expect("non-null function pointer")( + context, + 2041i32, + (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 as uint16_t; + 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 !(0 != (*context).shall_stop_ongoing) + { + (*context).cb.expect( + "non-null function pointer", + )( + context, + 2041i32, + (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 == dc_smtp_connect( + (*context).smtp, + param, + ) { + if !param_autoconfig.is_null() { + current_block = + 2927484062889439186; + } else if 0 + != (*context) + .shall_stop_ongoing + { + current_block = + 2927484062889439186; + } else { + (*context).cb.expect("non-null function pointer")(context, + 2041i32, + (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 + { + current_block + = + 2927484062889439186; + } else { + (*context).cb.expect("non-null function pointer")(context, + 2041i32, + (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; + } + } + } else { + current_block = + 5083741289379115417; + } + } + } else { + current_block = + 5083741289379115417; + } + match current_block { + 2927484062889439186 => {} + _ => { + smtp_connected_here = 1i32; + if !(0 + != (*context) + .shall_stop_ongoing) + { + (*context).cb.expect("non-null function pointer")(context, + 2041i32, + (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) + { + 0x1i32 + } else { + 0i32 + }; + dc_configure_folders( + context, + (*context).inbox, + flags, + ); + if !(0 != (*context) + .shall_stop_ongoing) + { + (*context).cb.expect("non-null function pointer")(context, + 2041i32, + (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.expect("non-null function pointer")(context, + 2041i32, + (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 !(0 + != + (*context).shall_stop_ongoing) + { + (*context).cb.expect("non-null function pointer")(context, + 2041i32, + (if 940i32 + < + 1i32 + { + 1i32 + } else if 940i32 + > + 999i32 + { + 999i32 + } else { + 940i32 + }) + as + uintptr_t, + 0i32 + as + uintptr_t); + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + if 0 != imap_connected_here { + dc_imap_disconnect((*context).inbox); + } + if 0 != smtp_connected_here { + dc_smtp_disconnect((*context).smtp); + } + dc_loginparam_unref(param); + dc_loginparam_unref(param_autoconfig); + free(param_addr_urlencoded as *mut libc::c_void); + if 0 != ongoing_allocated_here { + dc_free_ongoing(context); + } + free(mvbox_folder as *mut libc::c_void); + (*context).cb.expect("non-null function pointer")( + context, + 2041i32, + (if 0 != success { 1000i32 } else { 0i32 }) as uintptr_t, + 0i32 as uintptr_t, + ); +} +#[no_mangle] +pub unsafe extern "C" 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; +} +#[no_mangle] +pub unsafe extern "C" 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 extern "C" 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 extern "C" 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( + 1i32 as libc::c_ulong, + ::std::mem::size_of::() as libc::c_ulong, + ) + 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 extern "C" 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 extern "C" fn get_folder_meaning(mut flags: *mut mailimap_mbx_list_flags) -> libc::c_int { + let mut ret_meaning: libc::c_int = 0i32; + if !flags.is_null() { + let mut iter2: *mut clistiter = 0 as *mut clistiter; + iter2 = (*(*flags).mbf_oflags).first; + while !iter2.is_null() { + let mut oflag: *mut mailimap_mbx_list_oflag = (if !iter2.is_null() { + (*iter2).data + } else { + 0 as *mut libc::c_void + }) + as *mut mailimap_mbx_list_oflag; + match (*oflag).of_type { + 2 => { + if strcasecmp( + (*oflag).of_flag_ext, + b"spam\x00" as *const u8 as *const libc::c_char, + ) == 0i32 + || strcasecmp( + (*oflag).of_flag_ext, + b"trash\x00" as *const u8 as *const libc::c_char, + ) == 0i32 + || strcasecmp( + (*oflag).of_flag_ext, + b"drafts\x00" as *const u8 as *const libc::c_char, + ) == 0i32 + || strcasecmp( + (*oflag).of_flag_ext, + b"junk\x00" as *const u8 as *const libc::c_char, + ) == 0i32 + { + ret_meaning = 2i32 + } else if strcasecmp( + (*oflag).of_flag_ext, + b"sent\x00" as *const u8 as *const libc::c_char, + ) == 0i32 + { + ret_meaning = 1i32 + } + } + _ => {} + } + iter2 = if !iter2.is_null() { + (*iter2).next + } else { + 0 as *mut clistcell_s + } + } + } + return ret_meaning; +} +unsafe extern "C" fn moz_autoconfigure( + mut context: *mut 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 { + 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 moz_ac: moz_autoconfigure_t = moz_autoconfigure_t { + in_0: 0 as *const dc_loginparam_t, + in_emaildomain: 0 as *mut libc::c_char, + in_emaillocalpart: 0 as *mut libc::c_char, + out: 0 as *mut dc_loginparam_t, + out_imap_set: 0, + out_smtp_set: 0, + tag_server: 0, + tag_config: 0, + }; + memset( + &mut moz_ac as *mut moz_autoconfigure_t as *mut libc::c_void, + 0i32, + ::std::mem::size_of::() as libc::c_ulong, + ); + xml_raw = read_autoconf_file(context, url); + if !xml_raw.is_null() { + moz_ac.in_0 = param_in; + moz_ac.in_emaillocalpart = dc_strdup((*param_in).addr); + p = strchr(moz_ac.in_emaillocalpart, '@' as i32); + if !p.is_null() { + *p = 0i32 as libc::c_char; + moz_ac.in_emaildomain = dc_strdup(p.offset(1isize)); + moz_ac.out = dc_loginparam_new(); + saxparser = _dc_saxparser { + starttag_cb: None, + endtag_cb: None, + text_cb: None, + userdata: 0 as *mut libc::c_void, + }; + dc_saxparser_init( + &mut saxparser, + &mut moz_ac as *mut moz_autoconfigure_t as *mut libc::c_void, + ); + dc_saxparser_set_tag_handler( + &mut saxparser, + Some(moz_autoconfigure_starttag_cb), + Some(moz_autoconfigure_endtag_cb), + ); + dc_saxparser_set_text_handler(&mut saxparser, Some(moz_autoconfigure_text_cb)); + dc_saxparser_parse(&mut saxparser, xml_raw); + if (*moz_ac.out).mail_server.is_null() + || (*moz_ac.out).mail_port as libc::c_int == 0i32 + || (*moz_ac.out).send_server.is_null() + || (*moz_ac.out).send_port == 0i32 + { + let mut r: *mut libc::c_char = dc_loginparam_get_readable(moz_ac.out); + dc_log_warning( + context, + 0i32, + b"Bad or incomplete autoconfig: %s\x00" as *const u8 as *const libc::c_char, + r, + ); + free(r as *mut libc::c_void); + dc_loginparam_unref(moz_ac.out); + moz_ac.out = 0 as *mut dc_loginparam_t + } + } + } + free(xml_raw as *mut libc::c_void); + free(moz_ac.in_emaildomain as *mut libc::c_void); + free(moz_ac.in_emaillocalpart as *mut libc::c_void); + return moz_ac.out; +} +unsafe extern "C" fn moz_autoconfigure_text_cb( + mut userdata: *mut libc::c_void, + mut text: *const libc::c_char, + mut len: libc::c_int, +) { + let mut moz_ac: *mut moz_autoconfigure_t = userdata as *mut moz_autoconfigure_t; + let mut val: *mut libc::c_char = dc_strdup(text); + dc_trim(val); + dc_str_replace( + &mut val, + b"%EMAILADDRESS%\x00" as *const u8 as *const libc::c_char, + (*(*moz_ac).in_0).addr, + ); + dc_str_replace( + &mut val, + b"%EMAILLOCALPART%\x00" as *const u8 as *const libc::c_char, + (*moz_ac).in_emaillocalpart, + ); + dc_str_replace( + &mut val, + b"%EMAILDOMAIN%\x00" as *const u8 as *const libc::c_char, + (*moz_ac).in_emaildomain, + ); + if (*moz_ac).tag_server == 1i32 { + match (*moz_ac).tag_config { + 10 => { + free((*(*moz_ac).out).mail_server as *mut libc::c_void); + (*(*moz_ac).out).mail_server = val; + val = 0 as *mut libc::c_char + } + 11 => (*(*moz_ac).out).mail_port = atoi(val) as uint16_t, + 12 => { + free((*(*moz_ac).out).mail_user as *mut libc::c_void); + (*(*moz_ac).out).mail_user = val; + val = 0 as *mut libc::c_char + } + 13 => { + if strcasecmp(val, b"ssl\x00" as *const u8 as *const libc::c_char) == 0i32 { + (*(*moz_ac).out).server_flags |= 0x200i32 + } + if strcasecmp(val, b"starttls\x00" as *const u8 as *const libc::c_char) == 0i32 { + (*(*moz_ac).out).server_flags |= 0x100i32 + } + if strcasecmp(val, b"plain\x00" as *const u8 as *const libc::c_char) == 0i32 { + (*(*moz_ac).out).server_flags |= 0x400i32 + } + } + _ => {} + } + } else if (*moz_ac).tag_server == 2i32 { + match (*moz_ac).tag_config { + 10 => { + free((*(*moz_ac).out).send_server as *mut libc::c_void); + (*(*moz_ac).out).send_server = val; + val = 0 as *mut libc::c_char + } + 11 => (*(*moz_ac).out).send_port = atoi(val), + 12 => { + free((*(*moz_ac).out).send_user as *mut libc::c_void); + (*(*moz_ac).out).send_user = val; + val = 0 as *mut libc::c_char + } + 13 => { + if strcasecmp(val, b"ssl\x00" as *const u8 as *const libc::c_char) == 0i32 { + (*(*moz_ac).out).server_flags |= 0x20000i32 + } + if strcasecmp(val, b"starttls\x00" as *const u8 as *const libc::c_char) == 0i32 { + (*(*moz_ac).out).server_flags |= 0x10000i32 + } + if strcasecmp(val, b"plain\x00" as *const u8 as *const libc::c_char) == 0i32 { + (*(*moz_ac).out).server_flags |= 0x40000i32 + } + } + _ => {} + } + } + free(val as *mut libc::c_void); +} +unsafe extern "C" fn moz_autoconfigure_endtag_cb( + mut userdata: *mut libc::c_void, + mut tag: *const libc::c_char, +) { + let mut moz_ac: *mut moz_autoconfigure_t = userdata as *mut moz_autoconfigure_t; + if strcmp( + tag, + b"incomingserver\x00" as *const u8 as *const libc::c_char, + ) == 0i32 + { + (*moz_ac).tag_server = 0i32; + (*moz_ac).tag_config = 0i32; + (*moz_ac).out_imap_set = 1i32 + } else if strcmp( + tag, + b"outgoingserver\x00" as *const u8 as *const libc::c_char, + ) == 0i32 + { + (*moz_ac).tag_server = 0i32; + (*moz_ac).tag_config = 0i32; + (*moz_ac).out_smtp_set = 1i32 + } else { + (*moz_ac).tag_config = 0i32 + }; +} +unsafe extern "C" fn moz_autoconfigure_starttag_cb( + mut userdata: *mut libc::c_void, + mut tag: *const libc::c_char, + mut attr: *mut *mut libc::c_char, +) { + let mut moz_ac: *mut moz_autoconfigure_t = userdata as *mut moz_autoconfigure_t; + let mut p1: *const libc::c_char = 0 as *const libc::c_char; + if strcmp( + tag, + b"incomingserver\x00" as *const u8 as *const libc::c_char, + ) == 0i32 + { + (*moz_ac).tag_server = if (*moz_ac).out_imap_set == 0i32 + && { + p1 = dc_attr_find(attr, b"type\x00" as *const u8 as *const libc::c_char); + !p1.is_null() + } + && strcasecmp(p1, b"imap\x00" as *const u8 as *const libc::c_char) == 0i32 + { + 1i32 + } else { + 0i32 + }; + (*moz_ac).tag_config = 0i32 + } else if strcmp( + tag, + b"outgoingserver\x00" as *const u8 as *const libc::c_char, + ) == 0i32 + { + (*moz_ac).tag_server = if (*moz_ac).out_smtp_set == 0i32 { + 2i32 + } else { + 0i32 + }; + (*moz_ac).tag_config = 0i32 + } else if strcmp(tag, b"hostname\x00" as *const u8 as *const libc::c_char) == 0i32 { + (*moz_ac).tag_config = 10i32 + } else if strcmp(tag, b"port\x00" as *const u8 as *const libc::c_char) == 0i32 { + (*moz_ac).tag_config = 11i32 + } else if strcmp(tag, b"sockettype\x00" as *const u8 as *const libc::c_char) == 0i32 { + (*moz_ac).tag_config = 13i32 + } else if strcmp(tag, b"username\x00" as *const u8 as *const libc::c_char) == 0i32 { + (*moz_ac).tag_config = 12i32 + }; +} +unsafe extern "C" fn read_autoconf_file( + mut context: *mut 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; + dc_log_info( + context, + 0i32, + b"Testing %s ...\x00" as *const u8 as *const libc::c_char, + url, + ); + filecontent = (*context).cb.expect("non-null function pointer")( + context, + 2100i32, + url as uintptr_t, + 0i32 as uintptr_t, + ) as *mut libc::c_char; + if filecontent.is_null() || *filecontent.offset(0isize) as libc::c_int == 0i32 { + free(filecontent as *mut libc::c_void); + dc_log_info( + context, + 0i32, + b"Can\'t read file.\x00" as *const u8 as *const libc::c_char, + ); + return 0 as *mut libc::c_char; + } + return filecontent; +} +unsafe extern "C" fn outlk_autodiscover( + mut context: *mut dc_context_t, + mut url__: *const libc::c_char, + mut 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; + let mut url: *mut libc::c_char = dc_strdup(url__); + let mut outlk_ad: outlk_autodiscover_t = outlk_autodiscover_t { + in_0: 0 as *const dc_loginparam_t, + out: 0 as *mut dc_loginparam_t, + out_imap_set: 0, + out_smtp_set: 0, + tag_config: 0, + config: [0 as *mut libc::c_char; 6], + redirect: 0 as *mut libc::c_char, + }; + let mut i: libc::c_int = 0; + i = 0i32; + loop { + if !(i < 10i32) { + current_block = 11584701595673473500; + break; + } + memset( + &mut outlk_ad as *mut outlk_autodiscover_t as *mut libc::c_void, + 0i32, + ::std::mem::size_of::() as libc::c_ulong, + ); + xml_raw = read_autoconf_file(context, url); + if xml_raw.is_null() { + current_block = 3070887585260837332; + break; + } + outlk_ad.in_0 = param_in; + outlk_ad.out = dc_loginparam_new(); + let mut saxparser: dc_saxparser_t = _dc_saxparser { + starttag_cb: None, + endtag_cb: None, + text_cb: None, + userdata: 0 as *mut libc::c_void, + }; + dc_saxparser_init( + &mut saxparser, + &mut outlk_ad as *mut outlk_autodiscover_t as *mut libc::c_void, + ); + dc_saxparser_set_tag_handler( + &mut saxparser, + Some(outlk_autodiscover_starttag_cb), + Some(outlk_autodiscover_endtag_cb), + ); + dc_saxparser_set_text_handler(&mut saxparser, Some(outlk_autodiscover_text_cb)); + dc_saxparser_parse(&mut saxparser, xml_raw); + if !(!outlk_ad.config[5usize].is_null() + && 0 != *outlk_ad.config[5usize].offset(0isize) as libc::c_int) + { + current_block = 11584701595673473500; + break; + } + free(url as *mut libc::c_void); + url = dc_strdup(outlk_ad.config[5usize]); + dc_loginparam_unref(outlk_ad.out); + outlk_clean_config(&mut outlk_ad); + free(xml_raw as *mut libc::c_void); + xml_raw = 0 as *mut libc::c_char; + i += 1 + } + match current_block { + 11584701595673473500 => { + if (*outlk_ad.out).mail_server.is_null() + || (*outlk_ad.out).mail_port as libc::c_int == 0i32 + || (*outlk_ad.out).send_server.is_null() + || (*outlk_ad.out).send_port == 0i32 + { + let mut r: *mut libc::c_char = dc_loginparam_get_readable(outlk_ad.out); + dc_log_warning( + context, + 0i32, + b"Bad or incomplete autoconfig: %s\x00" as *const u8 as *const libc::c_char, + r, + ); + free(r as *mut libc::c_void); + dc_loginparam_unref(outlk_ad.out); + outlk_ad.out = 0 as *mut dc_loginparam_t + } + } + _ => {} + } + free(url as *mut libc::c_void); + free(xml_raw as *mut libc::c_void); + outlk_clean_config(&mut outlk_ad); + return outlk_ad.out; +} +unsafe extern "C" 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; + i += 1 + } +} +unsafe extern "C" fn outlk_autodiscover_text_cb( + mut userdata: *mut libc::c_void, + mut text: *const libc::c_char, + mut len: libc::c_int, +) { + let mut outlk_ad: *mut outlk_autodiscover_t = userdata as *mut outlk_autodiscover_t; + let mut val: *mut libc::c_char = dc_strdup(text); + dc_trim(val); + free((*outlk_ad).config[(*outlk_ad).tag_config as usize] as *mut libc::c_void); + (*outlk_ad).config[(*outlk_ad).tag_config as usize] = val; +} +unsafe extern "C" fn outlk_autodiscover_endtag_cb( + mut userdata: *mut libc::c_void, + mut tag: *const libc::c_char, +) { + let mut outlk_ad: *mut outlk_autodiscover_t = userdata as *mut outlk_autodiscover_t; + if strcmp(tag, b"protocol\x00" as *const u8 as *const libc::c_char) == 0i32 { + if !(*outlk_ad).config[1usize].is_null() { + let mut port: libc::c_int = dc_atoi_null_is_0((*outlk_ad).config[3usize]); + let mut ssl_on: libc::c_int = (!(*outlk_ad).config[4usize].is_null() + && strcasecmp( + (*outlk_ad).config[4usize], + b"on\x00" as *const u8 as *const libc::c_char, + ) == 0i32) as libc::c_int; + let mut ssl_off: libc::c_int = (!(*outlk_ad).config[4usize].is_null() + && strcasecmp( + (*outlk_ad).config[4usize], + b"off\x00" as *const u8 as *const libc::c_char, + ) == 0i32) as libc::c_int; + if strcasecmp( + (*outlk_ad).config[1usize], + b"imap\x00" as *const u8 as *const libc::c_char, + ) == 0i32 + && (*outlk_ad).out_imap_set == 0i32 + { + (*(*outlk_ad).out).mail_server = dc_strdup_keep_null((*outlk_ad).config[2usize]); + (*(*outlk_ad).out).mail_port = port as uint16_t; + if 0 != ssl_on { + (*(*outlk_ad).out).server_flags |= 0x200i32 + } else if 0 != ssl_off { + (*(*outlk_ad).out).server_flags |= 0x400i32 + } + (*outlk_ad).out_imap_set = 1i32 + } else if strcasecmp( + (*outlk_ad).config[1usize], + b"smtp\x00" as *const u8 as *const libc::c_char, + ) == 0i32 + && (*outlk_ad).out_smtp_set == 0i32 + { + (*(*outlk_ad).out).send_server = dc_strdup_keep_null((*outlk_ad).config[2usize]); + (*(*outlk_ad).out).send_port = port; + if 0 != ssl_on { + (*(*outlk_ad).out).server_flags |= 0x20000i32 + } else if 0 != ssl_off { + (*(*outlk_ad).out).server_flags |= 0x40000i32 + } + (*outlk_ad).out_smtp_set = 1i32 + } + } + outlk_clean_config(outlk_ad); + } + (*outlk_ad).tag_config = 0i32; +} +unsafe extern "C" fn outlk_autodiscover_starttag_cb( + mut userdata: *mut libc::c_void, + mut tag: *const libc::c_char, + mut attr: *mut *mut libc::c_char, +) { + let mut outlk_ad: *mut outlk_autodiscover_t = userdata as *mut outlk_autodiscover_t; + if strcmp(tag, b"protocol\x00" as *const u8 as *const libc::c_char) == 0i32 { + outlk_clean_config(outlk_ad); + } else if strcmp(tag, b"type\x00" as *const u8 as *const libc::c_char) == 0i32 { + (*outlk_ad).tag_config = 1i32 + } else if strcmp(tag, b"server\x00" as *const u8 as *const libc::c_char) == 0i32 { + (*outlk_ad).tag_config = 2i32 + } else if strcmp(tag, b"port\x00" as *const u8 as *const libc::c_char) == 0i32 { + (*outlk_ad).tag_config = 3i32 + } else if strcmp(tag, b"ssl\x00" as *const u8 as *const libc::c_char) == 0i32 { + (*outlk_ad).tag_config = 4i32 + } else if strcmp(tag, b"redirecturl\x00" as *const u8 as *const libc::c_char) == 0i32 { + (*outlk_ad).tag_config = 5i32 + }; +} +#[no_mangle] +pub unsafe extern "C" 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; + } + if 0 != dc_has_ongoing(context) { + dc_log_warning( + context, + 0i32, + b"There is already another ongoing process running.\x00" as *const u8 + as *const libc::c_char, + ); + return 0i32; + } + (*context).ongoing_running = 1i32; + (*context).shall_stop_ongoing = 0i32; + return 1i32; +} +#[no_mangle] +pub unsafe extern "C" fn dc_connect_to_configured_imap( + mut context: *mut dc_context_t, + mut imap: *mut dc_imap_t, +) -> 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) { + ret_connected = 1i32 + } else if dc_sqlite3_get_config_int( + (*(*imap).context).sql, + b"configured\x00" as *const u8 as *const libc::c_char, + 0i32, + ) == 0i32 + { + dc_log_warning( + (*imap).context, + 0i32, + b"Not configured, cannot connect.\x00" as *const u8 as *const libc::c_char, + ); + } else { + dc_loginparam_read( + param, + (*(*imap).context).sql, + b"configured_\x00" as *const u8 as *const libc::c_char, + ); + /*the trailing underscore is correct*/ + if !(0 == dc_imap_connect(imap, param)) { + ret_connected = 2i32 + } + } + dc_loginparam_unref(param); + return ret_connected; +} diff --git a/src/dc_contact.rs b/src/dc_contact.rs new file mode 100644 index 000000000..b7095f8b0 --- /dev/null +++ b/src/dc_contact.rs @@ -0,0 +1,2241 @@ +use c2rust_bitfields::BitfieldStruct; +use libc; +extern "C" { + pub type mailstream_cancel; + pub type sqlite3; + pub type sqlite3_stmt; + #[no_mangle] + fn calloc(_: libc::c_ulong, _: libc::c_ulong) -> *mut libc::c_void; + #[no_mangle] + fn free(_: *mut libc::c_void); + #[no_mangle] + fn exit(_: libc::c_int) -> !; + #[no_mangle] + fn strcat(_: *mut libc::c_char, _: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn strchr(_: *const libc::c_char, _: libc::c_int) -> *mut libc::c_char; + #[no_mangle] + fn strcmp(_: *const libc::c_char, _: *const libc::c_char) -> libc::c_int; + #[no_mangle] + fn strcpy(_: *mut libc::c_char, _: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn strlen(_: *const libc::c_char) -> libc::c_ulong; + #[no_mangle] + fn strncmp(_: *const libc::c_char, _: *const libc::c_char, _: libc::c_ulong) -> libc::c_int; + #[no_mangle] + fn strcasecmp(_: *const libc::c_char, _: *const libc::c_char) -> libc::c_int; + #[no_mangle] + fn dc_get_config(_: *mut dc_context_t, key: *const libc::c_char) -> *mut libc::c_char; + /* tools, these functions are compatible to the corresponding sqlite3_* functions */ + #[no_mangle] + fn dc_sqlite3_prepare(_: *mut dc_sqlite3_t, sql: *const libc::c_char) -> *mut sqlite3_stmt; + #[no_mangle] + fn sqlite3_finalize(pStmt: *mut sqlite3_stmt) -> libc::c_int; + #[no_mangle] + fn sqlite3_step(_: *mut sqlite3_stmt) -> libc::c_int; + #[no_mangle] + fn sqlite3_bind_int(_: *mut sqlite3_stmt, _: libc::c_int, _: libc::c_int) -> libc::c_int; + #[no_mangle] + fn sqlite3_column_int(_: *mut sqlite3_stmt, iCol: libc::c_int) -> libc::c_int; + #[no_mangle] + fn sqlite3_bind_text( + _: *mut sqlite3_stmt, + _: libc::c_int, + _: *const libc::c_char, + _: libc::c_int, + _: Option ()>, + ) -> libc::c_int; + #[no_mangle] + fn dc_sqlite3_get_config( + _: *mut dc_sqlite3_t, + key: *const libc::c_char, + def: *const libc::c_char, + ) -> *mut libc::c_char; + /* string tools */ + #[no_mangle] + fn dc_strdup(_: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn dc_trim(_: *mut libc::c_char); + #[no_mangle] + fn sqlite3_column_text(_: *mut sqlite3_stmt, iCol: libc::c_int) -> *const libc::c_uchar; + /* Return the string with the given ID by calling DC_EVENT_GET_STRING. + The result must be free()'d! */ + #[no_mangle] + fn dc_stock_str(_: *mut dc_context_t, id: libc::c_int) -> *mut libc::c_char; + #[no_mangle] + fn dc_log_error(_: *mut dc_context_t, data1: libc::c_int, msg: *const libc::c_char, _: ...); + #[no_mangle] + fn dc_sqlite3_get_rowid( + _: *mut dc_sqlite3_t, + table: *const libc::c_char, + field: *const libc::c_char, + value: *const libc::c_char, + ) -> uint32_t; + #[no_mangle] + fn dc_log_warning(_: *mut dc_context_t, data1: libc::c_int, msg: *const libc::c_char, _: ...); + #[no_mangle] + fn dc_free_splitted_lines(lines: *mut carray); + #[no_mangle] + fn dc_sqlite3_commit(_: *mut dc_sqlite3_t); + #[no_mangle] + fn dc_sqlite3_begin_transaction(_: *mut dc_sqlite3_t); + #[no_mangle] + fn dc_split_into_lines(buf_terminated: *const libc::c_char) -> *mut carray; + #[no_mangle] + fn dc_array_new(_: *mut dc_context_t, initsize: size_t) -> *mut dc_array_t; + #[no_mangle] + fn sqlite3_free(_: *mut libc::c_void); + #[no_mangle] + fn dc_array_add_id(_: *mut dc_array_t, _: uint32_t); + #[no_mangle] + fn dc_str_contains(haystack: *const libc::c_char, needle: *const libc::c_char) -> libc::c_int; + #[no_mangle] + fn sqlite3_mprintf(_: *const libc::c_char, _: ...) -> *mut libc::c_char; + #[no_mangle] + fn dc_key_new() -> *mut dc_key_t; + #[no_mangle] + fn dc_key_unref(_: *mut dc_key_t); + #[no_mangle] + fn dc_loginparam_new() -> *mut dc_loginparam_t; + #[no_mangle] + fn dc_loginparam_unref(_: *mut dc_loginparam_t); + #[no_mangle] + fn dc_apeerstate_new(_: *mut dc_context_t) -> *mut dc_apeerstate_t; + #[no_mangle] + fn dc_apeerstate_unref(_: *mut dc_apeerstate_t); + #[no_mangle] + fn dc_strbuilder_cat(_: *mut dc_strbuilder_t, text: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn dc_apeerstate_peek_key( + _: *const dc_apeerstate_t, + min_verified: libc::c_int, + ) -> *mut dc_key_t; + #[no_mangle] + fn dc_key_get_formatted_fingerprint(_: *const dc_key_t) -> *mut libc::c_char; + #[no_mangle] + fn dc_key_load_self_public( + _: *mut dc_key_t, + self_addr: *const libc::c_char, + sql: *mut dc_sqlite3_t, + ) -> libc::c_int; + #[no_mangle] + fn dc_ensure_secret_key_exists(_: *mut dc_context_t) -> libc::c_int; + #[no_mangle] + fn dc_pgp_rand_seed(_: *mut dc_context_t, buf: *const libc::c_void, bytes: size_t); + #[no_mangle] + fn dc_loginparam_read( + _: *mut dc_loginparam_t, + _: *mut dc_sqlite3_t, + prefix: *const libc::c_char, + ); + #[no_mangle] + fn dc_apeerstate_load_by_addr( + _: *mut dc_apeerstate_t, + _: *mut dc_sqlite3_t, + addr: *const libc::c_char, + ) -> libc::c_int; + #[no_mangle] + fn dc_strbuilder_init(_: *mut dc_strbuilder_t, init_bytes: libc::c_int); + #[no_mangle] + fn dc_mprintf(format: *const libc::c_char, _: ...) -> *mut libc::c_char; + #[no_mangle] + fn dc_rtrim(_: *mut libc::c_char); + #[no_mangle] + fn dc_str_to_color(_: *const libc::c_char) -> libc::c_int; +} +pub type __darwin_size_t = libc::c_ulong; +pub type __darwin_ssize_t = libc::c_long; +pub type __darwin_time_t = libc::c_long; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_cond_t { + pub __sig: libc::c_long, + pub __opaque: [libc::c_char; 40], +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_mutex_t { + pub __sig: libc::c_long, + pub __opaque: [libc::c_char; 56], +} +pub type __darwin_pthread_cond_t = _opaque_pthread_cond_t; +pub type __darwin_pthread_mutex_t = _opaque_pthread_mutex_t; +pub type uintptr_t = libc::c_ulong; +pub type size_t = __darwin_size_t; +pub type uint8_t = libc::c_uchar; +pub type uint16_t = libc::c_ushort; +pub type uint32_t = libc::c_uint; +pub type ssize_t = __darwin_ssize_t; +pub type time_t = __darwin_time_t; +pub type pthread_cond_t = __darwin_pthread_cond_t; +pub type pthread_mutex_t = __darwin_pthread_mutex_t; +#[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; +#[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) -> (); +#[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; +#[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, + 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 { + 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_capability_data { + pub cap_list: *mut clist, +} +#[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_0, + 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_0 { + 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 extern "C" 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_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, +} +#[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_1, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed_1 { + pub ft_fetch_att: *mut mailimap_fetch_att, + pub ft_fetch_att_list: *mut clist, +} +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 unnamed_2 { + 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, +} +/* define DC_USE_RPGP to enable use of rPGP instead of netpgp where available; +preferrably, this should be done in the project configuration currently */ +//#define DC_USE_RPGP 1 +/* Includes that are used frequently. This file may also be used to create predefined headers. */ +/* * Structure behind dc_context_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_context { + pub magic: uint32_t, + pub userdata: *mut libc::c_void, + pub dbfile: *mut libc::c_char, + pub blobdir: *mut libc::c_char, + pub sql: *mut dc_sqlite3_t, + pub inbox: *mut dc_imap_t, + pub inboxidle_condmutex: pthread_mutex_t, + pub perform_inbox_jobs_needed: libc::c_int, + pub probe_imap_network: libc::c_int, + pub sentbox_thread: dc_jobthread_t, + pub mvbox_thread: dc_jobthread_t, + pub smtp: *mut dc_smtp_t, + pub smtpidle_cond: pthread_cond_t, + pub smtpidle_condmutex: pthread_mutex_t, + pub smtpidle_condflag: libc::c_int, + pub smtp_suspended: libc::c_int, + pub smtp_doing_jobs: libc::c_int, + pub perform_smtp_jobs_needed: libc::c_int, + pub probe_smtp_network: libc::c_int, + pub oauth2_critical: pthread_mutex_t, + 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 type dc_lot_t = _dc_lot; +/* * Structure behind dc_lot_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_lot { + pub magic: uint32_t, + pub text1_meaning: libc::c_int, + pub text1: *mut libc::c_char, + pub text2: *mut libc::c_char, + pub timestamp: time_t, + pub state: libc::c_int, + pub id: uint32_t, + pub fingerprint: *mut libc::c_char, + pub invitenumber: *mut libc::c_char, + pub auth: *mut libc::c_char, +} +/* * + * 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 = Option< + unsafe extern "C" fn( + _: *mut dc_context_t, + _: libc::c_int, + _: uintptr_t, + _: uintptr_t, + ) -> uintptr_t, +>; +/* * + * @mainpage Getting started + * + * This document describes how to handle the Delta Chat core library. + * For general information about Delta Chat itself, + * see and . + * + * Let's start. + * + * First of all, you have to **define an event-handler-function** + * that is called by the library on specific events + * (eg. when the configuration is done or when fresh messages arrive). + * With this function you can create a Delta Chat context then: + * + * ~~~ + * #include + * + * uintptr_t event_handler_func(dc_context_t* context, int event, + * uintptr_t data1, uintptr_t data2) + * { + * return 0; // for unhandled events, it is always safe to return 0 + * } + * + * dc_context_t* context = dc_context_new(event_handler_func, NULL, NULL); + * ~~~ + * + * After that, you should make sure, + * sending and receiving jobs are processed as needed. + * For this purpose, you have to **create two threads:** + * + * ~~~ + * #include + * + * void* imap_thread_func(void* context) + * { + * while (true) { + * dc_perform_imap_jobs(context); + * dc_perform_imap_fetch(context); + * dc_perform_imap_idle(context); + * } + * } + * + * void* smtp_thread_func(void* context) + * { + * while (true) { + * dc_perform_smtp_jobs(context); + * dc_perform_smtp_idle(context); + * } + * } + * + * static pthread_t imap_thread, smtp_thread; + * pthread_create(&imap_thread, NULL, imap_thread_func, context); + * pthread_create(&smtp_thread, NULL, smtp_thread_func, context); + * ~~~ + * + * The example above uses "pthreads", + * however, you can also use anything else for thread handling. + * NB: The deltachat-core library itself does not create any threads on its own, + * however, functions, unless stated otherwise, are thread-safe. + * + * After that you can **define and open a database.** + * The database is a normal sqlite-file and is created as needed: + * + * ~~~ + * dc_open(context, "example.db", NULL); + * ~~~ + * + * Now you can **configure the context:** + * + * ~~~ + * // use some real test credentials here + * dc_set_config(context, "addr", "alice@example.org"); + * dc_set_config(context, "mail_pw", "***"); + * dc_configure(context); + * ~~~ + * + * dc_configure() returns immediately, the configuration itself may take a while + * and is done by a job in the imap-thread you've defined above. + * Once done, the #DC_EVENT_CONFIGURE_PROGRESS reports success + * to the event_handler_func() that is also defined above. + * + * The configuration result is saved in the database, + * on subsequent starts it is not needed to call dc_configure() + * (you can check this using dc_is_configured()). + * + * Now you can **send the first message:** + * + * ~~~ + * // use a real testing address here + * uint32_t contact_id = dc_create_contact(context, NULL, "bob@example.org"); + * uint32_t chat_id = dc_create_chat_by_contact_id(context, contact_id); + * + * dc_send_text_msg(context, chat_id, "Hi, here is my first message!"); + * ~~~ + * + * dc_send_text_msg() returns immediately; + * the sending itself is done by a job in the smtp-thread you've defined above. + * If you check the testing address (bob) + * and you should have received a normal email. + * Answer this email in any email program with "Got it!" + * and the imap-thread you've create above will **receive the message**. + * + * You can then **list all messages** of a chat as follow: + * + * ~~~ + * dc_array_t* msglist = dc_get_chat_msgs(context, chat_id, 0, 0); + * for (int i = 0; i < dc_array_get_cnt(msglist); i++) + * { + * uint32_t msg_id = dc_array_get_id(msglist, i); + * dc_msg_t* msg = dc_get_msg(context, msg_id); + * char* text = dc_msg_get_text(msg); + * + * printf("Message %i: %s\n", i+1, text); + * + * free(text); + * dc_msg_unref(msg); + * } + * dc_array_unref(msglist); + * ~~~ + * + * This will output the following two lines: + * + * ~~~ + * Message 1: Hi, here is my first message! + * Message 2: Got it! + * ~~~ + * + * + * ## Class reference + * + * For a class reference, see the "Classes" link atop. + * + * + * ## Further hints + * + * Here are some additional, unsorted hints that may be useful. + * + * - For `get`-functions, you have to unref the return value in some way. + * + * - Strings in function arguments or return values are usually UTF-8 encoded. + * + * - The issue-tracker for the core library is here: + * + * + * The following points are important mainly + * for the authors of the library itself: + * + * - For indentation, use tabs. + * Alignments that are not placed at the beginning of a line + * should be done with spaces. + * + * - For padding between functions, + * classes etc. use 2 empty lines + * + * - Source files are encoded as UTF-8 with Unix line endings + * (a simple `LF`, `0x0A` or `\n`) + * + * If you need further assistance, + * please do not hesitate to contact us + * through the channels shown at https://delta.chat/en/contribute + * + * Please keep in mind, that your derived work + * must respect the Mozilla Public License 2.0 of libdeltachat + * and the respective licenses of the libraries libdeltachat links with. + * + * See you. + */ +/* * + * @class dc_context_t + * + * An object representing a single account. + * + * Each account is linked to an IMAP/SMTP account and uses a separate + * SQLite database for offline functionality and for account-related + * settings. + */ +pub type dc_context_t = _dc_context; +/* ** library-private **********************************************************/ +pub type dc_smtp_t = _dc_smtp; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_smtp { + 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 error: *mut libc::c_char, + pub error_etpan: libc::c_int, +} +pub type dc_jobthread_t = _dc_jobthread; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_jobthread { + 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, + 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, +} +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_imap { + 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 type dc_receive_imf_t = Option< + unsafe extern "C" 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_imap_t = _dc_imap; +pub type dc_precheck_imf_t = Option< + unsafe extern "C" 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< + unsafe extern "C" fn(_: *mut dc_imap_t, _: *const libc::c_char, _: *const libc::c_char) -> (), +>; +pub type dc_get_config_t = Option< + unsafe extern "C" fn( + _: *mut dc_imap_t, + _: *const libc::c_char, + _: *const libc::c_char, + ) -> *mut libc::c_char, +>; +/* ** library-private **********************************************************/ +pub type dc_sqlite3_t = _dc_sqlite3; +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_sqlite3 { + pub cobj: *mut sqlite3, + pub context: *mut dc_context_t, +} +/* * the structure behind dc_array_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_array { + 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, +} +pub type dc_array_t = _dc_array; +/* * the structure behind dc_contact_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_contact { + pub magic: uint32_t, + pub context: *mut dc_context_t, + pub id: uint32_t, + pub name: *mut libc::c_char, + pub authname: *mut libc::c_char, + pub addr: *mut libc::c_char, + pub blocked: libc::c_int, + pub origin: libc::c_int, +} +pub type dc_contact_t = _dc_contact; +pub type sqlite3_destructor_type = Option ()>; +pub type dc_strbuilder_t = _dc_strbuilder; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_strbuilder { + pub buf: *mut libc::c_char, + pub allocated: libc::c_int, + pub free: libc::c_int, + pub eos: *mut libc::c_char, +} +pub type dc_key_t = _dc_key; +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_key { + pub binary: *mut libc::c_void, + pub bytes: libc::c_int, + pub type_0: libc::c_int, + pub _m_heap_refcnt: libc::c_int, +} +pub type dc_loginparam_t = _dc_loginparam; +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_loginparam { + pub addr: *mut libc::c_char, + pub mail_server: *mut libc::c_char, + pub mail_user: *mut libc::c_char, + pub mail_pw: *mut libc::c_char, + pub mail_port: uint16_t, + pub send_server: *mut libc::c_char, + pub send_user: *mut libc::c_char, + pub send_pw: *mut libc::c_char, + pub send_port: libc::c_int, + pub server_flags: libc::c_int, +} +pub type dc_apeerstate_t = _dc_apeerstate; +/* prefer-encrypt states */ +/* * + * @class dc_apeerstate_t + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_apeerstate { + pub context: *mut dc_context_t, + pub addr: *mut libc::c_char, + pub last_seen: time_t, + pub last_seen_autocrypt: time_t, + pub prefer_encrypt: libc::c_int, + pub public_key: *mut dc_key_t, + pub public_key_fingerprint: *mut libc::c_char, + pub gossip_key: *mut dc_key_t, + pub gossip_timestamp: time_t, + pub gossip_key_fingerprint: *mut libc::c_char, + pub verified_key: *mut dc_key_t, + pub verified_key_fingerprint: *mut libc::c_char, + pub to_save: libc::c_int, + pub degrade_event: libc::c_int, +} +#[inline] +unsafe extern "C" fn carray_count(mut array: *mut carray) -> libc::c_uint { + return (*array).len; +} +#[inline] +unsafe extern "C" fn carray_get( + mut array: *mut carray, + mut indx: libc::c_uint, +) -> *mut libc::c_void { + return *(*array).array.offset(indx as isize); +} +#[no_mangle] +pub unsafe extern "C" 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; + } + let mut stmt: *mut sqlite3_stmt = dc_sqlite3_prepare( + (*context).sql, + b"UPDATE msgs SET state=13 WHERE from_id=? AND state=10;\x00" as *const u8 + as *const libc::c_char, + ); + sqlite3_bind_int(stmt, 1i32, contact_id as libc::c_int); + sqlite3_step(stmt); + sqlite3_finalize(stmt); + (*context).cb.expect("non-null function pointer")( + context, + 2000i32, + 0i32 as uintptr_t, + 0i32 as uintptr_t, + ); +} +// handle contacts +#[no_mangle] +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; + } + let mut at: *const libc::c_char = strchr(addr, '@' as i32); + if at.is_null() || (at.wrapping_offset_from(addr) as libc::c_long) < 1i32 as libc::c_long { + return 0i32; + } + let mut dot: *const libc::c_char = strchr(at, '.' as i32); + if dot.is_null() + || (dot.wrapping_offset_from(at) as libc::c_long) < 2i32 as libc::c_long + || *dot.offset(1isize) as libc::c_int == 0i32 + || *dot.offset(2isize) as libc::c_int == 0i32 + { + return 0i32; + } + return 1i32; +} +#[no_mangle] +pub unsafe extern "C" fn dc_lookup_contact_id_by_addr( + mut context: *mut 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) + { + addr_normalized = dc_addr_normalize(addr); + addr_self = 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 strcasecmp(addr_normalized, addr_self) == 0i32 { + contact_id = 1i32 + } else { + stmt = + dc_sqlite3_prepare((*context).sql, + 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( + stmt, + 1i32, + addr_normalized as *const libc::c_char, + -1i32, + None, + ); + sqlite3_bind_int(stmt, 2i32, 9i32); + sqlite3_bind_int(stmt, 3i32, 0x100i32); + if sqlite3_step(stmt) == 100i32 { + contact_id = sqlite3_column_int(stmt, 0i32) + } + } + } + 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; +} +#[no_mangle] +pub unsafe extern "C" 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); + if strncmp( + addr_normalized, + b"mailto:\x00" as *const u8 as *const libc::c_char, + 7i32 as libc::c_ulong, + ) == 0i32 + { + let mut old: *mut libc::c_char = addr_normalized; + addr_normalized = dc_strdup(&mut *old.offset(7isize)); + free(old as *mut libc::c_void); + dc_trim(addr_normalized); + } + return addr_normalized; +} +#[no_mangle] +pub unsafe extern "C" fn dc_create_contact( + mut context: *mut 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) + { + contact_id = dc_add_or_lookup_contact(context, name, addr, 0x4000000i32, &mut sth_modified); + blocked = dc_is_contact_blocked(context, contact_id); + (*context).cb.expect("non-null function pointer")( + context, + 2030i32, + (if sth_modified == 2i32 { + contact_id + } else { + 0i32 as libc::c_uint + }) as uintptr_t, + 0i32 as uintptr_t, + ); + if 0 != blocked { + dc_block_contact(context, contact_id, 0i32); + } + } + return contact_id; +} +#[no_mangle] +pub unsafe extern "C" fn dc_block_contact( + mut context: *mut dc_context_t, + mut contact_id: uint32_t, + mut new_blocking: libc::c_int, +) { + let mut current_block: u64; + 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) + && (*contact).blocked != new_blocking + { + stmt = dc_sqlite3_prepare( + (*context).sql, + b"UPDATE contacts SET blocked=? WHERE id=?;\x00" as *const u8 + as *const libc::c_char, + ); + sqlite3_bind_int(stmt, 1i32, new_blocking); + sqlite3_bind_int(stmt, 2i32, contact_id as libc::c_int); + if sqlite3_step(stmt) != 101i32 { + current_block = 5249903830285462583; + } else { + sqlite3_finalize(stmt); + stmt = 0 as *mut sqlite3_stmt; + stmt = + dc_sqlite3_prepare((*context).sql, + 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); + sqlite3_bind_int(stmt, 1i32, new_blocking); + sqlite3_bind_int(stmt, 2i32, 100i32); + sqlite3_bind_int(stmt, 3i32, contact_id as libc::c_int); + if sqlite3_step(stmt) != 101i32 { + current_block = 5249903830285462583; + } else { + dc_marknoticed_contact(context, contact_id); + send_event = 1i32; + current_block = 15652330335145281839; + } + } + } else { + current_block = 15652330335145281839; + } + match current_block { + 5249903830285462583 => {} + _ => { + if 0 != send_event { + (*context).cb.expect("non-null function pointer")( + context, + 2030i32, + 0i32 as uintptr_t, + 0i32 as uintptr_t, + ); + } + } + } + } + sqlite3_finalize(stmt); + dc_contact_unref(contact); +} +/* * + * @class dc_contact_t + * + * An object representing a single contact in memory. + * The contact object is not updated. + * If you want an update, you have to recreate the object. + * + * The library makes sure + * only to use names _authorized_ by the contact in `To:` or `Cc:`. + * _Given-names _as "Daddy" or "Honey" are not used there. + * For this purpose, internally, two names are tracked - + * authorized-name and given-name. + * By default, these names are equal, + * but functions working with contact names + * (eg. dc_contact_get_name(), dc_contact_get_display_name(), + * dc_contact_get_name_n_addr(), dc_contact_get_first_name(), + * dc_create_contact() or dc_add_address_book()) + * only affect the given-name. + */ +#[no_mangle] +pub unsafe extern "C" 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; + contact = calloc( + 1i32 as libc::c_ulong, + ::std::mem::size_of::() as libc::c_ulong, + ) as *mut dc_contact_t; + if contact.is_null() { + exit(19i32); + } + (*contact).magic = 0xc047ac7i32 as uint32_t; + (*contact).context = context; + return contact; +} +#[no_mangle] +pub unsafe extern "C" fn dc_contact_unref(mut contact: *mut dc_contact_t) { + if contact.is_null() || (*contact).magic != 0xc047ac7i32 as libc::c_uint { + return; + } + dc_contact_empty(contact); + (*contact).magic = 0i32 as uint32_t; + free(contact as *mut libc::c_void); +} +#[no_mangle] +pub unsafe extern "C" fn dc_contact_empty(mut contact: *mut dc_contact_t) { + if contact.is_null() || (*contact).magic != 0xc047ac7i32 as libc::c_uint { + return; + } + (*contact).id = 0i32 as uint32_t; + free((*contact).name as *mut libc::c_void); + (*contact).name = 0 as *mut libc::c_char; + free((*contact).authname as *mut libc::c_void); + (*contact).authname = 0 as *mut libc::c_char; + free((*contact).addr as *mut libc::c_void); + (*contact).addr = 0 as *mut libc::c_char; + (*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 */ +/* address scanned but not verified */ +/* Reply-To: of incoming message of known sender */ +/* Cc: of incoming message of known sender */ +/* additional To:'s of incoming message of known sender */ +/* a chat was manually created for this user, but no message yet sent */ +/* message sent by us */ +/* message sent by us */ +/* message sent by us */ +/* internal use */ +/* address is in our address book */ +/* set on Alice's side for contacts like Bob that have scanned the QR code offered by her. Only means the contact has once been established using the "securejoin" procedure in the past, getting the current key verification status requires calling dc_contact_is_verified() ! */ +/* set on Bob's side for contacts scanned and verified from a QR code. Only means the contact has once been established using the "securejoin" procedure in the past, getting the current key verification status requires calling dc_contact_is_verified() ! */ +/* contact added mannually by dc_create_contact(), this should be the largets origin as otherwise the user cannot modify the names */ +/* 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 */ +#[no_mangle] +pub unsafe extern "C" fn dc_contact_load_from_db( + mut contact: *mut dc_contact_t, + mut sql: *mut dc_sqlite3_t, + mut 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()) { + 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( + sql, + b"configured_addr\x00" as *const u8 as *const libc::c_char, + b"\x00" as *const u8 as *const libc::c_char, + ); + current_block = 5143058163439228106; + } else { + stmt = + dc_sqlite3_prepare(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); + if sqlite3_step(stmt) != 100i32 { + current_block = 12908855840294526070; + } else { + (*contact).id = contact_id; + (*contact).name = dc_strdup(sqlite3_column_text(stmt, 0i32) as *mut libc::c_char); + (*contact).addr = dc_strdup(sqlite3_column_text(stmt, 1i32) as *mut libc::c_char); + (*contact).origin = sqlite3_column_int(stmt, 2i32); + (*contact).blocked = sqlite3_column_int(stmt, 3i32); + (*contact).authname = + dc_strdup(sqlite3_column_text(stmt, 4i32) as *mut libc::c_char); + current_block = 5143058163439228106; + } + } + match current_block { + 12908855840294526070 => {} + _ => success = 1i32, + } + } + sqlite3_finalize(stmt); + return success; +} +#[no_mangle] +pub unsafe extern "C" fn dc_is_contact_blocked( + mut context: *mut 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 != (*contact).blocked { + is_blocked = 1i32 + } + } + dc_contact_unref(contact); + return is_blocked; +} +/*can be NULL*/ +#[no_mangle] +pub unsafe extern "C" fn dc_add_or_lookup_contact( + mut context: *mut dc_context_t, + mut name: *const libc::c_char, + mut addr__: *const libc::c_char, + mut origin: libc::c_int, + mut sth_modified: *mut libc::c_int, +) -> uint32_t { + let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; + let mut row_id: uint32_t = 0i32 as uint32_t; + let mut dummy: libc::c_int = 0i32; + let mut addr: *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 row_name: *mut libc::c_char = 0 as *mut libc::c_char; + let mut row_addr: *mut libc::c_char = 0 as *mut libc::c_char; + let mut row_authname: *mut libc::c_char = 0 as *mut libc::c_char; + if sth_modified.is_null() { + sth_modified = &mut dummy + } + *sth_modified = 0i32; + if !(context.is_null() + || (*context).magic != 0x11a11807i32 as libc::c_uint + || addr__.is_null() + || origin <= 0i32) + { + addr = dc_addr_normalize(addr__); + addr_self = 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 strcasecmp(addr, addr_self) == 0i32 { + row_id = 1i32 as uint32_t + } else if 0 == dc_may_be_valid_addr(addr) { + dc_log_warning( + context, + 0i32, + b"Bad address \"%s\" for contact \"%s\".\x00" as *const u8 as *const libc::c_char, + addr, + if !name.is_null() { + name + } else { + b"\x00" as *const u8 as *const libc::c_char + }, + ); + } else { + stmt = + dc_sqlite3_prepare((*context).sql, + 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 update_addr: libc::c_int = 0i32; + let mut update_name: libc::c_int = 0i32; + let mut update_authname: libc::c_int = 0i32; + row_id = sqlite3_column_int(stmt, 0i32) as uint32_t; + row_name = dc_strdup(sqlite3_column_text(stmt, 1i32) as *mut libc::c_char); + row_addr = dc_strdup(sqlite3_column_text(stmt, 2i32) as *mut libc::c_char); + row_origin = sqlite3_column_int(stmt, 3i32); + row_authname = dc_strdup(sqlite3_column_text(stmt, 4i32) as *mut libc::c_char); + sqlite3_finalize(stmt); + stmt = 0 as *mut sqlite3_stmt; + if !name.is_null() && 0 != *name.offset(0isize) as libc::c_int { + if 0 != *row_name.offset(0isize) { + if origin >= row_origin && strcmp(name, row_name) != 0i32 { + update_name = 1i32 + } + } else { + update_name = 1i32 + } + if origin == 0x10i32 && strcmp(name, row_authname) != 0i32 { + update_authname = 1i32 + } + } + if origin >= row_origin && strcmp(addr, row_addr) != 0i32 { + update_addr = 1i32 + } + if 0 != update_name + || 0 != update_authname + || 0 != update_addr + || origin > row_origin + { + stmt = dc_sqlite3_prepare( + (*context).sql, + b"UPDATE contacts SET name=?, addr=?, origin=?, authname=? WHERE id=?;\x00" + as *const u8 as *const libc::c_char, + ); + sqlite3_bind_text( + stmt, + 1i32, + if 0 != update_name { name } else { row_name }, + -1i32, + None, + ); + sqlite3_bind_text( + stmt, + 2i32, + if 0 != update_addr { addr } else { row_addr }, + -1i32, + None, + ); + sqlite3_bind_int( + stmt, + 3i32, + if origin > row_origin { + origin + } else { + row_origin + }, + ); + sqlite3_bind_text( + stmt, + 4i32, + if 0 != update_authname { + name + } else { + row_authname + }, + -1i32, + None, + ); + sqlite3_bind_int(stmt, 5i32, row_id as libc::c_int); + sqlite3_step(stmt); + sqlite3_finalize(stmt); + stmt = 0 as *mut sqlite3_stmt; + if 0 != update_name { + stmt = + dc_sqlite3_prepare((*context).sql, + 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); + sqlite3_bind_text(stmt, 1i32, name, -1i32, None); + sqlite3_bind_int(stmt, 2i32, 100i32); + sqlite3_bind_int(stmt, 3i32, row_id as libc::c_int); + sqlite3_step(stmt); + } + *sth_modified = 1i32 + } + } else { + sqlite3_finalize(stmt); + stmt = 0 as *mut sqlite3_stmt; + stmt = dc_sqlite3_prepare( + (*context).sql, + b"INSERT INTO contacts (name, addr, origin) VALUES(?, ?, ?);\x00" as *const u8 + as *const libc::c_char, + ); + sqlite3_bind_text( + stmt, + 1i32, + if !name.is_null() { + name + } else { + b"\x00" as *const u8 as *const libc::c_char + }, + -1i32, + None, + ); + sqlite3_bind_text(stmt, 2i32, addr, -1i32, None); + sqlite3_bind_int(stmt, 3i32, origin); + if sqlite3_step(stmt) == 101i32 { + row_id = dc_sqlite3_get_rowid( + (*context).sql, + b"contacts\x00" as *const u8 as *const libc::c_char, + b"addr\x00" as *const u8 as *const libc::c_char, + addr, + ); + *sth_modified = 2i32 + } else { + dc_log_error( + context, + 0i32, + b"Cannot add contact.\x00" as *const u8 as *const libc::c_char, + ); + } + } + } + } + free(addr as *mut libc::c_void); + free(addr_self as *mut libc::c_void); + free(row_addr as *mut libc::c_void); + free(row_name as *mut libc::c_void); + free(row_authname as *mut libc::c_void); + sqlite3_finalize(stmt); + return row_id; +} +#[no_mangle] +pub unsafe extern "C" fn dc_add_address_book( + mut context: *mut 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 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()) + { + 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(1i32 as libc::c_ulong) < iCnt { + let mut name: *mut libc::c_char = + carray_get(lines, i as libc::c_uint) as *mut libc::c_char; + let mut addr: *mut libc::c_char = + carray_get(lines, i.wrapping_add(1i32 as libc::c_ulong) as libc::c_uint) + as *mut libc::c_char; + dc_normalize_name(name); + dc_add_or_lookup_contact(context, name, addr, 0x80000i32, &mut sth_modified); + if 0 != sth_modified { + modify_cnt += 1 + } + 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.expect("non-null function pointer")( + context, + 2030i32, + 0i32 as uintptr_t, + 0i32 as uintptr_t, + ); + } + } + } + dc_free_splitted_lines(lines); + return modify_cnt; +} +// Working with names +#[no_mangle] +pub unsafe extern "C" fn dc_normalize_name(mut full_name: *mut libc::c_char) { + if full_name.is_null() { + return; + } + dc_trim(full_name); + let mut len: libc::c_int = strlen(full_name) as libc::c_int; + if len > 0i32 { + let mut firstchar: libc::c_char = *full_name.offset(0isize); + let mut lastchar: libc::c_char = *full_name.offset((len - 1i32) as isize); + if firstchar as libc::c_int == '\'' as i32 && lastchar as libc::c_int == '\'' as i32 + || firstchar as libc::c_int == '\"' as i32 && lastchar as libc::c_int == '\"' as i32 + || firstchar as libc::c_int == '<' as i32 && lastchar as libc::c_int == '>' as i32 + { + *full_name.offset(0isize) = ' ' as i32 as libc::c_char; + *full_name.offset((len - 1i32) as isize) = ' ' as i32 as libc::c_char + } + } + let mut p1: *mut libc::c_char = strchr(full_name, ',' as i32); + if !p1.is_null() { + *p1 = 0i32 as libc::c_char; + let mut last_name: *mut libc::c_char = dc_strdup(full_name); + let mut first_name: *mut libc::c_char = dc_strdup(p1.offset(1isize)); + dc_trim(last_name); + dc_trim(first_name); + strcpy(full_name, first_name); + strcat(full_name, b" \x00" as *const u8 as *const libc::c_char); + strcat(full_name, last_name); + free(last_name as *mut libc::c_void); + free(first_name as *mut libc::c_void); + } else { + dc_trim(full_name); + }; +} +#[no_mangle] +pub unsafe extern "C" fn dc_get_contacts( + mut context: *mut 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_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 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; + } else { + stmt = + dc_sqlite3_prepare((*context).sql, + 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; + 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; +} +#[no_mangle] +pub unsafe extern "C" fn dc_get_blocked_cnt(mut context: *mut 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) + } + } + sqlite3_finalize(stmt); + return ret; +} +#[no_mangle] +pub unsafe extern "C" 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); + } + } + sqlite3_finalize(stmt); + return ret; +} +#[no_mangle] +pub unsafe extern "C" fn dc_get_contact_encrinfo( + mut context: *mut dc_context_t, + mut contact_id: uint32_t, +) -> *mut libc::c_char { + let mut ret: dc_strbuilder_t = _dc_strbuilder { + buf: 0 as *mut libc::c_char, + allocated: 0, + free: 0, + eos: 0 as *mut libc::c_char, + }; + 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); + let mut self_key: *mut dc_key_t = dc_key_new(); + 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 { + 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, + ); + } 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); + dc_key_unref(self_key); + 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; +} +unsafe extern "C" fn cat_fingerprint( + mut ret: *mut dc_strbuilder_t, + mut addr: *const libc::c_char, + mut fingerprint_verified: *const libc::c_char, + mut fingerprint_unverified: *const libc::c_char, +) { + dc_strbuilder_cat(ret, b"\n\n\x00" as *const u8 as *const libc::c_char); + dc_strbuilder_cat(ret, addr); + dc_strbuilder_cat(ret, b":\n\x00" as *const u8 as *const libc::c_char); + dc_strbuilder_cat( + ret, + if !fingerprint_verified.is_null() + && 0 != *fingerprint_verified.offset(0isize) as libc::c_int + { + fingerprint_verified + } else { + fingerprint_unverified + }, + ); + if !fingerprint_verified.is_null() + && 0 != *fingerprint_verified.offset(0isize) as libc::c_int + && !fingerprint_unverified.is_null() + && 0 != *fingerprint_unverified.offset(0isize) as libc::c_int + && strcmp(fingerprint_verified, fingerprint_unverified) != 0i32 + { + dc_strbuilder_cat(ret, b"\n\n\x00" as *const u8 as *const libc::c_char); + dc_strbuilder_cat(ret, addr); + dc_strbuilder_cat( + ret, + b" (alternative):\n\x00" as *const u8 as *const libc::c_char, + ); + dc_strbuilder_cat(ret, fingerprint_unverified); + }; +} +#[no_mangle] +pub unsafe extern "C" fn dc_delete_contact( + mut context: *mut 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) + { + stmt = dc_sqlite3_prepare( + (*context).sql, + 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, + b"SELECT COUNT(*) FROM msgs WHERE from_id=? OR to_id=?;\x00" as *const u8 + as *const libc::c_char, + ); + sqlite3_bind_int(stmt, 1i32, contact_id as libc::c_int); + 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, + 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); + if !(sqlite3_step(stmt) != 101i32) { + (*context).cb.expect("non-null function pointer")( + context, + 2030i32, + 0i32 as uintptr_t, + 0i32 as uintptr_t, + ); + success = 1i32 + } + } + } + } + sqlite3_finalize(stmt); + return success; +} +#[no_mangle] +pub unsafe extern "C" fn dc_get_contact( + mut context: *mut 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) { + dc_contact_unref(ret); + ret = 0 as *mut dc_contact_t + } + return ret; +} +#[no_mangle] +pub unsafe extern "C" 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; +} +#[no_mangle] +pub unsafe extern "C" 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); +} +#[no_mangle] +pub unsafe extern "C" 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); +} +#[no_mangle] +pub unsafe extern "C" 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); + } + if !(*contact).name.is_null() && 0 != *(*contact).name.offset(0isize) as libc::c_int { + return dc_strdup((*contact).name); + } + return dc_strdup((*contact).addr); +} +#[no_mangle] +pub unsafe extern "C" 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); + } + if !(*contact).name.is_null() && 0 != *(*contact).name.offset(0isize) as libc::c_int { + return dc_mprintf( + b"%s (%s)\x00" as *const u8 as *const libc::c_char, + (*contact).name, + (*contact).addr, + ); + } + return dc_strdup((*contact).addr); +} +#[no_mangle] +pub unsafe extern "C" 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); + } + 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); +} +#[no_mangle] +pub unsafe extern "C" 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); + if !p1.is_null() { + *p1 = 0i32 as libc::c_char; + dc_rtrim(first_name); + if *first_name.offset(0isize) as libc::c_int == 0i32 { + free(first_name as *mut libc::c_void); + first_name = dc_strdup(full_name) + } + } + return first_name; +} +#[no_mangle] +pub unsafe extern "C" 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; + if !(contact.is_null() || (*contact).magic != 0xc047ac7i32 as libc::c_uint) { + if (*contact).id == 1i32 as libc::c_uint { + selfavatar = dc_get_config( + (*contact).context, + b"selfavatar\x00" as *const u8 as *const libc::c_char, + ); + if !selfavatar.is_null() && 0 != *selfavatar.offset(0isize) as libc::c_int { + image_abs = dc_strdup(selfavatar) + } + } + } + // TODO: else get image_abs from contact param + free(selfavatar as *mut libc::c_void); + return image_abs; +} +#[no_mangle] +pub unsafe extern "C" 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; +} +#[no_mangle] +pub unsafe extern "C" 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; +} +#[no_mangle] +pub unsafe extern "C" 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); +} +#[no_mangle] +pub unsafe extern "C" fn dc_contact_is_verified_ex( + mut contact: *mut dc_contact_t, + mut peerstate: *const dc_apeerstate_t, +) -> libc::c_int { + let mut current_block: u64; + let mut contact_verified: libc::c_int = 0i32; + let mut peerstate_to_delete: *mut dc_apeerstate_t = 0 as *mut dc_apeerstate_t; + if !(contact.is_null() || (*contact).magic != 0xc047ac7i32 as libc::c_uint) { + if (*contact).id == 1i32 as libc::c_uint { + contact_verified = 2i32 + } else { + // we're always sort of secured-verified as we could verify the key on this device any time with the key on this device + if peerstate.is_null() { + peerstate_to_delete = dc_apeerstate_new((*contact).context); + if 0 == dc_apeerstate_load_by_addr( + peerstate_to_delete, + (*(*contact).context).sql, + (*contact).addr, + ) { + current_block = 8667923638376902112; + } else { + peerstate = peerstate_to_delete; + current_block = 13109137661213826276; + } + } else { + current_block = 13109137661213826276; + } + match current_block { + 8667923638376902112 => {} + _ => { + contact_verified = if !(*peerstate).verified_key.is_null() { + 2i32 + } else { + 0i32 + } + } + } + } + } + dc_apeerstate_unref(peerstate_to_delete); + return contact_verified; +} +// Working with e-mail-addresses +#[no_mangle] +pub unsafe extern "C" fn dc_addr_cmp( + mut addr1: *const libc::c_char, + mut addr2: *const libc::c_char, +) -> libc::c_int { + let mut norm1: *mut libc::c_char = dc_addr_normalize(addr1); + let mut norm2: *mut libc::c_char = dc_addr_normalize(addr2); + 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; +} +#[no_mangle] +pub unsafe extern "C" fn dc_addr_equals_self( + mut context: *mut 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()) { + normalized_addr = dc_addr_normalize(addr); + 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, + ); + if !self_addr.is_null() { + ret = if strcasecmp(normalized_addr, self_addr) == 0i32 { + 1i32 + } else { + 0i32 + } + } + } + free(self_addr as *mut libc::c_void); + free(normalized_addr as *mut libc::c_void); + return ret; +} +#[no_mangle] +pub unsafe extern "C" fn dc_addr_equals_contact( + mut context: *mut 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 !(*contact).addr.is_null() { + let mut normalized_addr: *mut libc::c_char = dc_addr_normalize(addr); + if strcasecmp((*contact).addr, normalized_addr) == 0i32 { + addr_are_equal = 1i32 + } + free(normalized_addr as *mut libc::c_void); + } + } + dc_contact_unref(contact); + } + return addr_are_equal; +} +// Context functions to work with contacts +#[no_mangle] +pub unsafe extern "C" fn dc_get_real_contact_cnt(mut context: *mut 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()) + { + stmt = dc_sqlite3_prepare( + (*context).sql, + b"SELECT COUNT(*) FROM contacts WHERE id>?;\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) as size_t + } + } + sqlite3_finalize(stmt); + return ret; +} +#[no_mangle] +pub unsafe extern "C" fn dc_get_contact_origin( + mut context: *mut dc_context_t, + mut contact_id: uint32_t, + mut ret_blocked: *mut libc::c_int, +) -> libc::c_int { + let mut ret: libc::c_int = 0i32; + let mut dummy: libc::c_int = 0i32; + if ret_blocked.is_null() { + ret_blocked = &mut dummy + } + 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)) { + /* we could optimize this by loading only the needed fields */ + if 0 != (*contact).blocked { + *ret_blocked = 1i32 + } else { + ret = (*contact).origin + } + } + dc_contact_unref(contact); + return ret; +} +#[no_mangle] +pub unsafe extern "C" fn dc_real_contact_exists( + mut context: *mut 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) + { + stmt = dc_sqlite3_prepare( + (*context).sql, + 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); + if sqlite3_step(stmt) == 100i32 { + ret = 1i32 + } + } + sqlite3_finalize(stmt); + return ret; +} +#[no_mangle] +pub unsafe extern "C" fn dc_scaleup_contact_origin( + mut context: *mut 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, + b"UPDATE contacts SET origin=? WHERE id=? AND origin pid_t; + #[no_mangle] + fn calloc(_: libc::c_ulong, _: libc::c_ulong) -> *mut libc::c_void; + #[no_mangle] + fn free(_: *mut libc::c_void); + #[no_mangle] + fn exit(_: libc::c_int) -> !; + #[no_mangle] + fn strcmp(_: *const libc::c_char, _: *const libc::c_char) -> libc::c_int; + #[no_mangle] + fn strlen(_: *const libc::c_char) -> libc::c_ulong; + #[no_mangle] + fn strcasecmp(_: *const libc::c_char, _: *const libc::c_char) -> libc::c_int; + #[no_mangle] + fn time(_: *mut time_t) -> time_t; + #[no_mangle] + fn pthread_cond_destroy(_: *mut pthread_cond_t) -> libc::c_int; + #[no_mangle] + fn pthread_cond_init(_: *mut pthread_cond_t, _: *const pthread_condattr_t) -> libc::c_int; + #[no_mangle] + fn pthread_mutex_destroy(_: *mut pthread_mutex_t) -> libc::c_int; + #[no_mangle] + fn pthread_mutex_init(_: *mut pthread_mutex_t, _: *const pthread_mutexattr_t) -> libc::c_int; + #[no_mangle] + fn pthread_self() -> pthread_t; + #[no_mangle] + fn libetpan_get_version_major() -> libc::c_int; + #[no_mangle] + fn libetpan_get_version_minor() -> libc::c_int; + #[no_mangle] + fn dc_pgp_rand_seed(_: *mut dc_context_t, buf: *const libc::c_void, bytes: size_t); + #[no_mangle] + fn dc_smtp_new(_: *mut dc_context_t) -> *mut dc_smtp_t; + #[no_mangle] + fn dc_receive_imf( + _: *mut 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, + ); + #[no_mangle] + fn dc_job_add( + _: *mut dc_context_t, + action: libc::c_int, + foreign_id: libc::c_int, + param: *const libc::c_char, + delay: libc::c_int, + ); + #[no_mangle] + fn dc_do_heuristics_moves(_: *mut dc_context_t, folder: *const libc::c_char, msg_id: uint32_t); + #[no_mangle] + fn dc_update_server_uid( + _: *mut dc_context_t, + rfc724_mid: *const libc::c_char, + server_folder: *const libc::c_char, + server_uid: uint32_t, + ); + #[no_mangle] + fn dc_update_msg_move_state( + _: *mut dc_context_t, + rfc724_mid: *const libc::c_char, + _: dc_move_state_t, + ); + #[no_mangle] + fn dc_log_info(_: *mut dc_context_t, data1: libc::c_int, msg: *const libc::c_char, _: ...); + #[no_mangle] + fn dc_rfc724_mid_exists( + _: *mut dc_context_t, + rfc724_mid: *const libc::c_char, + ret_server_folder: *mut *mut libc::c_char, + ret_server_uid: *mut uint32_t, + ) -> uint32_t; + /* handle configurations, private */ + #[no_mangle] + fn dc_sqlite3_set_config( + _: *mut dc_sqlite3_t, + key: *const libc::c_char, + value: *const libc::c_char, + ) -> libc::c_int; + #[no_mangle] + fn dc_sqlite3_get_config( + _: *mut dc_sqlite3_t, + key: *const libc::c_char, + def: *const libc::c_char, + ) -> *mut libc::c_char; + #[no_mangle] + fn dc_imap_new( + _: dc_get_config_t, + _: dc_set_config_t, + _: dc_precheck_imf_t, + _: dc_receive_imf_t, + userData: *mut libc::c_void, + _: *mut dc_context_t, + ) -> *mut dc_imap_t; + #[no_mangle] + fn dc_sqlite3_new(_: *mut dc_context_t) -> *mut dc_sqlite3_t; + /* ** library-private **********************************************************/ + /* validation errors */ + /* misc. */ + #[no_mangle] + fn dc_pgp_init(); + /* ** library-private **********************************************************/ + #[no_mangle] + fn dc_openssl_init(); + #[no_mangle] + fn dc_strdup_keep_null(_: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn dc_jobthread_init( + _: *mut dc_jobthread_t, + context: *mut dc_context_t, + name: *const libc::c_char, + folder_config_name: *const libc::c_char, + ); + #[no_mangle] + fn dc_jobthread_exit(_: *mut dc_jobthread_t); + #[no_mangle] + fn dc_openssl_exit(); + #[no_mangle] + fn dc_sqlite3_unref(_: *mut dc_sqlite3_t); + #[no_mangle] + fn dc_smtp_unref(_: *mut dc_smtp_t); + #[no_mangle] + fn dc_imap_unref(_: *mut dc_imap_t); + #[no_mangle] + fn dc_sqlite3_close(_: *mut dc_sqlite3_t); + #[no_mangle] + fn dc_sqlite3_is_open(_: *const dc_sqlite3_t) -> libc::c_int; + #[no_mangle] + fn dc_smtp_disconnect(_: *mut dc_smtp_t); + #[no_mangle] + fn dc_imap_disconnect(_: *mut dc_imap_t); + #[no_mangle] + fn dc_pgp_exit(); + #[no_mangle] + fn dc_sqlite3_open( + _: *mut dc_sqlite3_t, + dbfile: *const libc::c_char, + flags: libc::c_int, + ) -> libc::c_int; + #[no_mangle] + fn dc_create_folder(_: *mut dc_context_t, pathNfilename: *const libc::c_char) -> libc::c_int; + #[no_mangle] + fn dc_mprintf(format: *const libc::c_char, _: ...) -> *mut libc::c_char; + /* file tools */ + #[no_mangle] + fn dc_ensure_no_slash(pathNfilename: *mut libc::c_char); + /* string tools */ + #[no_mangle] + fn dc_strdup(_: *const libc::c_char) -> *mut libc::c_char; + /* Return the string with the given ID by calling DC_EVENT_GET_STRING. + The result must be free()'d! */ + #[no_mangle] + fn dc_stock_str(_: *mut dc_context_t, id: libc::c_int) -> *mut libc::c_char; + #[no_mangle] + fn dc_interrupt_mvbox_idle(_: *mut dc_context_t); + #[no_mangle] + fn dc_interrupt_sentbox_idle(_: *mut dc_context_t); + #[no_mangle] + fn dc_interrupt_imap_idle(_: *mut dc_context_t); + #[no_mangle] + fn dc_make_rel_and_copy( + _: *mut dc_context_t, + pathNfilename: *mut *mut libc::c_char, + ) -> libc::c_int; + #[no_mangle] + fn dc_get_abs_path( + _: *mut dc_context_t, + pathNfilename: *const libc::c_char, + ) -> *mut libc::c_char; + #[no_mangle] + fn dc_strbuilder_cat(_: *mut dc_strbuilder_t, text: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn dc_strbuilder_init(_: *mut dc_strbuilder_t, init_bytes: libc::c_int); + #[no_mangle] + fn dc_key_new() -> *mut dc_key_t; + #[no_mangle] + fn dc_key_unref(_: *mut dc_key_t); + #[no_mangle] + fn dc_loginparam_unref(_: *mut dc_loginparam_t); + #[no_mangle] + fn sqlite3_threadsafe() -> libc::c_int; + #[no_mangle] + fn dc_sqlite3_get_config_int( + _: *mut dc_sqlite3_t, + key: *const libc::c_char, + def: int32_t, + ) -> int32_t; + #[no_mangle] + fn dc_loginparam_get_readable(_: *const dc_loginparam_t) -> *mut libc::c_char; + #[no_mangle] + fn dc_key_get_fingerprint(_: *const dc_key_t) -> *mut libc::c_char; + #[no_mangle] + fn dc_key_load_self_public( + _: *mut dc_key_t, + self_addr: *const libc::c_char, + sql: *mut dc_sqlite3_t, + ) -> libc::c_int; + /* tools, these functions are compatible to the corresponding sqlite3_* functions */ + #[no_mangle] + fn dc_sqlite3_prepare(_: *mut dc_sqlite3_t, sql: *const libc::c_char) -> *mut sqlite3_stmt; + #[no_mangle] + fn sqlite3_finalize(pStmt: *mut sqlite3_stmt) -> libc::c_int; + #[no_mangle] + fn sqlite3_column_int(_: *mut sqlite3_stmt, iCol: libc::c_int) -> libc::c_int; + #[no_mangle] + fn sqlite3_step(_: *mut sqlite3_stmt) -> libc::c_int; + // Context functions to work with contacts + #[no_mangle] + fn dc_get_real_contact_cnt(_: *mut dc_context_t) -> size_t; + #[no_mangle] + fn dc_get_deaddrop_msg_cnt(_: *mut dc_context_t) -> size_t; + #[no_mangle] + fn dc_get_real_msg_cnt(_: *mut dc_context_t) -> size_t; + #[no_mangle] + fn dc_get_chat_cnt(_: *mut dc_context_t) -> size_t; + #[no_mangle] + fn dc_loginparam_read( + _: *mut dc_loginparam_t, + _: *mut dc_sqlite3_t, + prefix: *const libc::c_char, + ); + #[no_mangle] + fn dc_loginparam_new() -> *mut dc_loginparam_t; + #[no_mangle] + fn dc_array_new(_: *mut dc_context_t, initsize: size_t) -> *mut dc_array_t; + #[no_mangle] + fn dc_array_add_id(_: *mut dc_array_t, _: uint32_t); + #[no_mangle] + fn sqlite3_bind_int(_: *mut sqlite3_stmt, _: libc::c_int, _: libc::c_int) -> libc::c_int; + /* * + * @class dc_array_t + * + * An object containing a simple array. + * This object is used in several places where functions need to return an array. + * The items of the array are typically IDs. + * To free an array object, use dc_array_unref(). + */ + #[no_mangle] + fn dc_array_unref(_: *mut dc_array_t); + #[no_mangle] + fn sqlite3_bind_text( + _: *mut sqlite3_stmt, + _: libc::c_int, + _: *const libc::c_char, + _: libc::c_int, + _: Option ()>, + ) -> libc::c_int; + #[no_mangle] + fn dc_trim(_: *mut libc::c_char); +} +pub type __int32_t = libc::c_int; +pub type __darwin_size_t = libc::c_ulong; +pub type __darwin_ssize_t = libc::c_long; +pub type __darwin_time_t = libc::c_long; +pub type __darwin_pid_t = __int32_t; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct __darwin_pthread_handler_rec { + pub __routine: Option ()>, + pub __arg: *mut libc::c_void, + pub __next: *mut __darwin_pthread_handler_rec, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_cond_t { + pub __sig: libc::c_long, + pub __opaque: [libc::c_char; 40], +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_condattr_t { + pub __sig: libc::c_long, + pub __opaque: [libc::c_char; 8], +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_mutex_t { + pub __sig: libc::c_long, + pub __opaque: [libc::c_char; 56], +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_mutexattr_t { + pub __sig: libc::c_long, + pub __opaque: [libc::c_char; 8], +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_t { + pub __sig: libc::c_long, + pub __cleanup_stack: *mut __darwin_pthread_handler_rec, + pub __opaque: [libc::c_char; 8176], +} +pub type __darwin_pthread_cond_t = _opaque_pthread_cond_t; +pub type __darwin_pthread_condattr_t = _opaque_pthread_condattr_t; +pub type __darwin_pthread_mutex_t = _opaque_pthread_mutex_t; +pub type __darwin_pthread_mutexattr_t = _opaque_pthread_mutexattr_t; +pub type __darwin_pthread_t = *mut _opaque_pthread_t; +pub type int32_t = libc::c_int; +pub type uintptr_t = libc::c_ulong; +pub type time_t = __darwin_time_t; +pub type pid_t = __darwin_pid_t; +pub type size_t = __darwin_size_t; +pub type ssize_t = __darwin_ssize_t; +pub type pthread_cond_t = __darwin_pthread_cond_t; +pub type pthread_condattr_t = __darwin_pthread_condattr_t; +pub type pthread_mutex_t = __darwin_pthread_mutex_t; +pub type pthread_mutexattr_t = __darwin_pthread_mutexattr_t; +pub type pthread_t = __darwin_pthread_t; +pub type uint32_t = libc::c_uint; +pub type uint8_t = libc::c_uchar; +pub type uint16_t = libc::c_ushort; +#[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; +#[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) -> (); +#[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; +#[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, + 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 { + 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_capability_data { + pub cap_list: *mut clist, +} +#[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_0, + 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_0 { + 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 extern "C" 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_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, +} +#[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_1, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed_1 { + pub ft_fetch_att: *mut mailimap_fetch_att, + pub ft_fetch_att_list: *mut clist, +} +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 unnamed_2 { + 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, +} +/* define DC_USE_RPGP to enable use of rPGP instead of netpgp where available; +preferrably, this should be done in the project configuration currently */ +//#define DC_USE_RPGP 1 +/* Includes that are used frequently. This file may also be used to create predefined headers. */ +/* * Structure behind dc_context_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_context { + pub magic: uint32_t, + pub userdata: *mut libc::c_void, + pub dbfile: *mut libc::c_char, + pub blobdir: *mut libc::c_char, + pub sql: *mut dc_sqlite3_t, + pub inbox: *mut dc_imap_t, + pub inboxidle_condmutex: pthread_mutex_t, + pub perform_inbox_jobs_needed: libc::c_int, + pub probe_imap_network: libc::c_int, + pub sentbox_thread: dc_jobthread_t, + pub mvbox_thread: dc_jobthread_t, + pub smtp: *mut dc_smtp_t, + pub smtpidle_cond: pthread_cond_t, + pub smtpidle_condmutex: pthread_mutex_t, + pub smtpidle_condflag: libc::c_int, + pub smtp_suspended: libc::c_int, + pub smtp_doing_jobs: libc::c_int, + pub perform_smtp_jobs_needed: libc::c_int, + pub probe_smtp_network: libc::c_int, + pub oauth2_critical: pthread_mutex_t, + 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, +} + +unsafe impl Send for _dc_context {} +unsafe impl Sync for _dc_context {} + +pub type dc_lot_t = _dc_lot; +/* * Structure behind dc_lot_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_lot { + pub magic: uint32_t, + pub text1_meaning: libc::c_int, + pub text1: *mut libc::c_char, + pub text2: *mut libc::c_char, + pub timestamp: time_t, + pub state: libc::c_int, + pub id: uint32_t, + pub fingerprint: *mut libc::c_char, + pub invitenumber: *mut libc::c_char, + pub auth: *mut libc::c_char, +} +/* * + * 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 = Option< + unsafe extern "C" fn( + _: *mut dc_context_t, + _: libc::c_int, + _: uintptr_t, + _: uintptr_t, + ) -> uintptr_t, +>; +/* * + * @mainpage Getting started + * + * This document describes how to handle the Delta Chat core library. + * For general information about Delta Chat itself, + * see and . + * + * Let's start. + * + * First of all, you have to **define an event-handler-function** + * that is called by the library on specific events + * (eg. when the configuration is done or when fresh messages arrive). + * With this function you can create a Delta Chat context then: + * + * ~~~ + * #include + * + * uintptr_t event_handler_func(dc_context_t* context, int event, + * uintptr_t data1, uintptr_t data2) + * { + * return 0; // for unhandled events, it is always safe to return 0 + * } + * + * dc_context_t* context = dc_context_new(event_handler_func, NULL, NULL); + * ~~~ + * + * After that, you should make sure, + * sending and receiving jobs are processed as needed. + * For this purpose, you have to **create two threads:** + * + * ~~~ + * #include + * + * void* imap_thread_func(void* context) + * { + * while (true) { + * dc_perform_imap_jobs(context); + * dc_perform_imap_fetch(context); + * dc_perform_imap_idle(context); + * } + * } + * + * void* smtp_thread_func(void* context) + * { + * while (true) { + * dc_perform_smtp_jobs(context); + * dc_perform_smtp_idle(context); + * } + * } + * + * static pthread_t imap_thread, smtp_thread; + * pthread_create(&imap_thread, NULL, imap_thread_func, context); + * pthread_create(&smtp_thread, NULL, smtp_thread_func, context); + * ~~~ + * + * The example above uses "pthreads", + * however, you can also use anything else for thread handling. + * NB: The deltachat-core library itself does not create any threads on its own, + * however, functions, unless stated otherwise, are thread-safe. + * + * After that you can **define and open a database.** + * The database is a normal sqlite-file and is created as needed: + * + * ~~~ + * dc_open(context, "example.db", NULL); + * ~~~ + * + * Now you can **configure the context:** + * + * ~~~ + * // use some real test credentials here + * dc_set_config(context, "addr", "alice@example.org"); + * dc_set_config(context, "mail_pw", "***"); + * dc_configure(context); + * ~~~ + * + * dc_configure() returns immediately, the configuration itself may take a while + * and is done by a job in the imap-thread you've defined above. + * Once done, the #DC_EVENT_CONFIGURE_PROGRESS reports success + * to the event_handler_func() that is also defined above. + * + * The configuration result is saved in the database, + * on subsequent starts it is not needed to call dc_configure() + * (you can check this using dc_is_configured()). + * + * Now you can **send the first message:** + * + * ~~~ + * // use a real testing address here + * uint32_t contact_id = dc_create_contact(context, NULL, "bob@example.org"); + * uint32_t chat_id = dc_create_chat_by_contact_id(context, contact_id); + * + * dc_send_text_msg(context, chat_id, "Hi, here is my first message!"); + * ~~~ + * + * dc_send_text_msg() returns immediately; + * the sending itself is done by a job in the smtp-thread you've defined above. + * If you check the testing address (bob) + * and you should have received a normal email. + * Answer this email in any email program with "Got it!" + * and the imap-thread you've create above will **receive the message**. + * + * You can then **list all messages** of a chat as follow: + * + * ~~~ + * dc_array_t* msglist = dc_get_chat_msgs(context, chat_id, 0, 0); + * for (int i = 0; i < dc_array_get_cnt(msglist); i++) + * { + * uint32_t msg_id = dc_array_get_id(msglist, i); + * dc_msg_t* msg = dc_get_msg(context, msg_id); + * char* text = dc_msg_get_text(msg); + * + * printf("Message %i: %s\n", i+1, text); + * + * free(text); + * dc_msg_unref(msg); + * } + * dc_array_unref(msglist); + * ~~~ + * + * This will output the following two lines: + * + * ~~~ + * Message 1: Hi, here is my first message! + * Message 2: Got it! + * ~~~ + * + * + * ## Class reference + * + * For a class reference, see the "Classes" link atop. + * + * + * ## Further hints + * + * Here are some additional, unsorted hints that may be useful. + * + * - For `get`-functions, you have to unref the return value in some way. + * + * - Strings in function arguments or return values are usually UTF-8 encoded. + * + * - The issue-tracker for the core library is here: + * + * + * The following points are important mainly + * for the authors of the library itself: + * + * - For indentation, use tabs. + * Alignments that are not placed at the beginning of a line + * should be done with spaces. + * + * - For padding between functions, + * classes etc. use 2 empty lines + * + * - Source files are encoded as UTF-8 with Unix line endings + * (a simple `LF`, `0x0A` or `\n`) + * + * If you need further assistance, + * please do not hesitate to contact us + * through the channels shown at https://delta.chat/en/contribute + * + * Please keep in mind, that your derived work + * must respect the Mozilla Public License 2.0 of libdeltachat + * and the respective licenses of the libraries libdeltachat links with. + * + * See you. + */ +/* * + * @class dc_context_t + * + * An object representing a single account. + * + * Each account is linked to an IMAP/SMTP account and uses a separate + * SQLite database for offline functionality and for account-related + * settings. + */ +pub type dc_context_t = _dc_context; +/* ** library-private **********************************************************/ +pub type dc_smtp_t = _dc_smtp; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_smtp { + 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 error: *mut libc::c_char, + pub error_etpan: libc::c_int, +} +pub type dc_jobthread_t = _dc_jobthread; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_jobthread { + 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, + 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, +} +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_imap { + 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 type dc_receive_imf_t = Option< + unsafe extern "C" 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_imap_t = _dc_imap; +pub type dc_precheck_imf_t = Option< + unsafe extern "C" 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< + unsafe extern "C" fn(_: *mut dc_imap_t, _: *const libc::c_char, _: *const libc::c_char) -> (), +>; +pub type dc_get_config_t = Option< + unsafe extern "C" fn( + _: *mut dc_imap_t, + _: *const libc::c_char, + _: *const libc::c_char, + ) -> *mut libc::c_char, +>; +/* ** library-private **********************************************************/ +pub type dc_sqlite3_t = _dc_sqlite3; +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_sqlite3 { + pub cobj: *mut sqlite3, + pub context: *mut dc_context_t, +} +/* * the structure behind dc_array_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_array { + 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, +} +pub type dc_array_t = _dc_array; +pub type dc_move_state_t = libc::c_uint; +pub const DC_MOVE_STATE_MOVING: dc_move_state_t = 3; +pub const DC_MOVE_STATE_STAY: dc_move_state_t = 2; +pub const DC_MOVE_STATE_PENDING: dc_move_state_t = 1; +pub const DC_MOVE_STATE_UNDEFINED: dc_move_state_t = 0; +pub type dc_strbuilder_t = _dc_strbuilder; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_strbuilder { + pub buf: *mut libc::c_char, + pub allocated: libc::c_int, + pub free: libc::c_int, + pub eos: *mut libc::c_char, +} +pub type dc_key_t = _dc_key; +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_key { + pub binary: *mut libc::c_void, + pub bytes: libc::c_int, + pub type_0: libc::c_int, + pub _m_heap_refcnt: libc::c_int, +} +pub type dc_loginparam_t = _dc_loginparam; +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_loginparam { + pub addr: *mut libc::c_char, + pub mail_server: *mut libc::c_char, + pub mail_user: *mut libc::c_char, + pub mail_pw: *mut libc::c_char, + pub mail_port: uint16_t, + pub send_server: *mut libc::c_char, + pub send_user: *mut libc::c_char, + pub send_pw: *mut libc::c_char, + pub send_port: libc::c_int, + pub server_flags: libc::c_int, +} +pub type sqlite3_destructor_type = Option ()>; +// create/open/config/information +#[no_mangle] +pub unsafe extern "C" 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( + 1i32 as libc::c_ulong, + ::std::mem::size_of::() as libc::c_ulong, + ) as *mut dc_context_t; + if context.is_null() { + exit(23i32); + } + 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 = if cb.is_some() { cb } else { Some(cb_dummy) }; + (*context).os_name = dc_strdup_keep_null(os_name); + (*context).shall_stop_ongoing = 1i32; + dc_openssl_init(); + 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] = 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]>() as libc::c_ulong, + ); + return context; +} +unsafe extern "C" 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, +) { + let mut context: *mut dc_context_t = (*imap).userData as *mut dc_context_t; + dc_receive_imf( + context, + imf_raw_not_terminated, + imf_raw_bytes, + server_folder, + server_uid, + flags, + ); +} +unsafe extern "C" 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, +) -> libc::c_int { + let mut rfc724_mid_exists: libc::c_int = 0i32; + let mut msg_id: uint32_t = 0i32 as 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, + rfc724_mid, + &mut old_server_folder, + &mut old_server_uid, + ); + if msg_id != 0i32 as libc::c_uint { + rfc724_mid_exists = 1i32; + if *old_server_folder.offset(0isize) as libc::c_int == 0i32 + && old_server_uid == 0i32 as libc::c_uint + { + dc_log_info( + (*imap).context, + 0i32, + b"[move] detected bbc-self %s\x00" as *const u8 as *const libc::c_char, + rfc724_mid, + ); + mark_seen = 1i32 + } else if strcmp(old_server_folder, server_folder) != 0i32 { + dc_log_info( + (*imap).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); + } + 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_do_heuristics_moves((*imap).context, server_folder, msg_id); + if 0 != mark_seen { + dc_job_add( + (*imap).context, + 130i32, + msg_id as libc::c_int, + 0 as *const libc::c_char, + 0i32, + ); + } + } + free(old_server_folder as *mut libc::c_void); + return rfc724_mid_exists; +} +unsafe extern "C" fn cb_set_config( + mut imap: *mut dc_imap_t, + mut key: *const libc::c_char, + mut 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); +} +/* * + * 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 + * a separate user-thread, also these functions may be called from a different thread. + * + * @private @memberof dc_context_t + */ +unsafe extern "C" fn cb_get_config( + mut imap: *mut dc_imap_t, + mut key: *const libc::c_char, + mut 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); +} +/* * + * A callback function that is used if no user-defined callback is given to dc_context_new(). + * The callback function simply returns 0 which is safe for every event. + * + * @private @memberof dc_context_t + */ +unsafe extern "C" fn cb_dummy( + mut context: *mut dc_context_t, + mut event: libc::c_int, + mut data1: uintptr_t, + mut data2: uintptr_t, +) -> uintptr_t { + return 0i32 as uintptr_t; +} +#[no_mangle] +pub unsafe extern "C" 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(); + 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_openssl_exit(); + 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); +} +#[no_mangle] +pub unsafe extern "C" fn dc_close(mut context: *mut dc_context_t) { + if context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint { + return; + } + 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; +} +#[no_mangle] +pub unsafe extern "C" 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); +} +#[no_mangle] +pub unsafe extern "C" 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; +} +#[no_mangle] +pub unsafe extern "C" fn dc_open( + mut context: *mut dc_context_t, + mut dbfile: *const libc::c_char, + mut blobdir: *const libc::c_char, +) -> libc::c_int { + let mut success: libc::c_int = 0i32; + if 0 != dc_is_open(context) { + return 0i32; + } + if !(context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint || dbfile.is_null()) + { + (*context).dbfile = 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); + } else { + (*context).blobdir = + dc_mprintf(b"%s-blobs\x00" as *const u8 as *const libc::c_char, dbfile); + dc_create_folder(context, (*context).blobdir); + } + /* Create/open sqlite database, this may already use the blobdir */ + if !(0 == dc_sqlite3_open((*context).sql, dbfile, 0i32)) { + success = 1i32 + } + } + if 0 == success { + dc_close(context); + } + return success; +} +#[no_mangle] +pub unsafe extern "C" 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); +} +#[no_mangle] +pub unsafe extern "C" fn dc_set_config( + mut context: *mut dc_context_t, + mut key: *const libc::c_char, + mut 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; + } + if strcmp(key, b"selfavatar\x00" as *const u8 as *const libc::c_char) == 0i32 + && !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) + } + } 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); + dc_interrupt_imap_idle(context); + } else if strcmp( + key, + b"sentbox_watch\x00" as *const u8 as *const libc::c_char, + ) == 0i32 + { + ret = dc_sqlite3_set_config((*context).sql, 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); + 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); + ret = dc_sqlite3_set_config( + (*context).sql, + key, + if value.is_null() || strcmp(value, def) == 0i32 { + 0 as *const libc::c_char + } else { + value + }, + ); + free(def as *mut libc::c_void); + } else { + ret = dc_sqlite3_set_config((*context).sql, key, value) + } + free(rel_path as *mut libc::c_void); + return ret; +} +/* ****************************************************************************** + * INI-handling, Information + ******************************************************************************/ +unsafe extern "C" fn is_settable_config_key(mut key: *const libc::c_char) -> libc::c_int { + let mut i: libc::c_int = 0i32; + while (i as libc::c_ulong) + < (::std::mem::size_of::<[*const libc::c_char; 33]>() as libc::c_ulong) + .wrapping_div(::std::mem::size_of::<*mut libc::c_char>() as libc::c_ulong) + { + if strcmp(key, config_keys[i as usize]) == 0i32 { + return 1i32; + } + i += 1 + } + return 0i32; +} +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, + b"mail_user\x00" as *const u8 as *const libc::c_char, + b"mail_pw\x00" as *const u8 as *const libc::c_char, + b"mail_port\x00" as *const u8 as *const libc::c_char, + b"send_server\x00" as *const u8 as *const libc::c_char, + b"send_user\x00" as *const u8 as *const libc::c_char, + b"send_pw\x00" as *const u8 as *const libc::c_char, + b"send_port\x00" as *const u8 as *const libc::c_char, + b"server_flags\x00" as *const u8 as *const libc::c_char, + b"imap_folder\x00" as *const u8 as *const libc::c_char, + b"displayname\x00" as *const u8 as *const libc::c_char, + b"selfstatus\x00" as *const u8 as *const libc::c_char, + b"selfavatar\x00" as *const u8 as *const libc::c_char, + b"e2ee_enabled\x00" as *const u8 as *const libc::c_char, + b"mdns_enabled\x00" as *const u8 as *const libc::c_char, + b"inbox_watch\x00" as *const u8 as *const libc::c_char, + b"sentbox_watch\x00" as *const u8 as *const libc::c_char, + b"mvbox_watch\x00" as *const u8 as *const libc::c_char, + b"mvbox_move\x00" as *const u8 as *const libc::c_char, + b"show_emails\x00" as *const u8 as *const libc::c_char, + b"save_mime_headers\x00" as *const u8 as *const libc::c_char, + b"configured_addr\x00" as *const u8 as *const libc::c_char, + b"configured_mail_server\x00" as *const u8 as *const libc::c_char, + b"configured_mail_user\x00" as *const u8 as *const libc::c_char, + b"configured_mail_pw\x00" as *const u8 as *const libc::c_char, + b"configured_mail_port\x00" as *const u8 as *const libc::c_char, + b"configured_send_server\x00" as *const u8 as *const libc::c_char, + b"configured_send_user\x00" as *const u8 as *const libc::c_char, + b"configured_send_pw\x00" as *const u8 as *const libc::c_char, + b"configured_send_port\x00" as *const u8 as *const libc::c_char, + b"configured_server_flags\x00" as *const u8 as *const libc::c_char, + b"configured\x00" as *const u8 as *const libc::c_char, +]; +#[no_mangle] +pub unsafe extern "C" 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; + if !key.is_null() + && *key.offset(0isize) as libc::c_int == 's' as i32 + && *key.offset(1isize) as libc::c_int == 'y' as i32 + && *key.offset(2isize) as libc::c_int == 's' as i32 + && *key.offset(3isize) as libc::c_int == '.' as i32 + { + 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) + { + 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 !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) + } + 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 { + 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"sentbox_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_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) + } else { + value = dc_mprintf(b"\x00" as *const u8 as *const libc::c_char) + } + } + return value; +} +unsafe extern "C" fn is_gettable_config_key(mut key: *const libc::c_char) -> libc::c_int { + let mut i: libc::c_int = 0i32; + while (i as libc::c_ulong) + < (::std::mem::size_of::<[*const libc::c_char; 3]>() as libc::c_ulong) + .wrapping_div(::std::mem::size_of::<*mut libc::c_char>() as libc::c_ulong) + { + if strcmp(key, sys_config_keys[i as usize]) == 0i32 { + return 1i32; + } + i += 1 + } + return 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 extern "C" 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 { + return dc_strdup(b"0.42.0\x00" 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 + { + return dc_mprintf( + b"%i\x00" as *const u8 as *const libc::c_char, + 24i32 * 1024i32 * 1024i32 / 4i32 * 3i32, + ); + } else if strcmp( + key, + b"sys.config_keys\x00" as *const u8 as *const libc::c_char, + ) == 0i32 + { + return get_config_keys_str(); + } else { + return dc_strdup(0 as *const libc::c_char); + }; +} +unsafe extern "C" fn get_config_keys_str() -> *mut libc::c_char { + let mut ret: dc_strbuilder_t = _dc_strbuilder { + buf: 0 as *mut libc::c_char, + allocated: 0, + free: 0, + eos: 0 as *mut libc::c_char, + }; + dc_strbuilder_init(&mut ret, 0i32); + let mut i: libc::c_int = 0i32; + while (i as libc::c_ulong) + < (::std::mem::size_of::<[*const libc::c_char; 33]>() as libc::c_ulong) + .wrapping_div(::std::mem::size_of::<*mut libc::c_char>() as libc::c_ulong) + { + if strlen(ret.buf) > 0i32 as libc::c_ulong { + dc_strbuilder_cat(&mut ret, b" \x00" as *const u8 as *const libc::c_char); + } + dc_strbuilder_cat(&mut ret, config_keys[i as usize]); + i += 1 + } + let mut i_0: libc::c_int = 0i32; + while (i_0 as libc::c_ulong) + < (::std::mem::size_of::<[*const libc::c_char; 3]>() as libc::c_ulong) + .wrapping_div(::std::mem::size_of::<*mut libc::c_char>() as libc::c_ulong) + { + if strlen(ret.buf) > 0i32 as libc::c_ulong { + 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 + } + return ret.buf; +} +#[no_mangle] +pub unsafe extern "C" 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 { + 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); + } + l = dc_loginparam_new(); + l2 = dc_loginparam_new(); + dc_loginparam_read( + l, + (*context).sql, + b"\x00" as *const u8 as *const libc::c_char, + ); + dc_loginparam_read( + l2, + (*context).sql, + b"configured_\x00" as *const u8 as *const libc::c_char, + ); + displayname = dc_sqlite3_get_config( + (*context).sql, + b"displayname\x00" as *const u8 as *const libc::c_char, + 0 as *const libc::c_char, + ); + chats = dc_get_chat_cnt(context) as libc::c_int; + real_msgs = dc_get_real_msg_cnt(context) as libc::c_int; + 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, + b"configured\x00" as *const u8 as *const libc::c_char, + 0i32, + ); + dbversion = dc_sqlite3_get_config_int( + (*context).sql, + b"dbversion\x00" as *const u8 as *const libc::c_char, + 0i32, + ); + e2ee_enabled = dc_sqlite3_get_config_int( + (*context).sql, + b"e2ee_enabled\x00" as *const u8 as *const libc::c_char, + 1i32, + ); + mdns_enabled = dc_sqlite3_get_config_int( + (*context).sql, + b"mdns_enabled\x00" as *const u8 as *const libc::c_char, + 1i32, + ); + let mut stmt: *mut sqlite3_stmt = dc_sqlite3_prepare( + (*context).sql, + 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); + sqlite3_finalize(stmt); + stmt = dc_sqlite3_prepare( + (*context).sql, + 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); + sqlite3_finalize(stmt); + if 0 != dc_key_load_self_public(self_public, (*l2).addr, (*context).sql) { + fingerprint_str = dc_key_get_fingerprint(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, + b"inbox_watch\x00" as *const u8 as *const libc::c_char, + 1i32, + ); + sentbox_watch = dc_sqlite3_get_config_int( + (*context).sql, + b"sentbox_watch\x00" as *const u8 as *const libc::c_char, + 1i32, + ); + mvbox_watch = dc_sqlite3_get_config_int( + (*context).sql, + b"mvbox_watch\x00" as *const u8 as *const libc::c_char, + 1i32, + ); + mvbox_move = dc_sqlite3_get_config_int( + (*context).sql, + b"mvbox_move\x00" as *const u8 as *const libc::c_char, + 1i32, + ); + folders_configured = dc_sqlite3_get_config_int( + (*context).sql, + b"folders_configured\x00" as *const u8 as *const libc::c_char, + 0i32, + ); + configured_sentbox_folder = dc_sqlite3_get_config( + (*context).sql, + 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, + b"configured_mvbox_folder\x00" as *const u8 as *const libc::c_char, + b"\x00" as *const u8 as *const libc::c_char, + ); + temp = + dc_mprintf(b"deltachat_core_version=v%s\nsqlite_version=%s\nsqlite_thread_safe=%i\nlibetpan_version=%i.%i\nopenssl_version=%i.%i.%i%c\nrpgp_enabled=%i\ncompile_date=Apr 26 2019, 00:51:50\narch=%i\nnumber_of_chats=%i\nnumber_of_chat_messages=%i\nmessages_in_contact_requests=%i\nnumber_of_contacts=%i\ndatabase_dir=%s\ndatabase_version=%i\nblobdir=%s\ndisplay_name=%s\nis_configured=%i\nentered_account_settings=%s\nused_account_settings=%s\ninbox_watch=%i\nsentbox_watch=%i\nmvbox_watch=%i\nmvbox_move=%i\nfolders_configured=%i\nconfigured_sentbox_folder=%s\nconfigured_mvbox_folder=%s\nmdns_enabled=%i\ne2ee_enabled=%i\nprivate_key_count=%i\npublic_key_count=%i\nfingerprint=%s\n\x00" + as *const u8 as *const libc::c_char, + b"0.42.0\x00" as *const u8 as *const libc::c_char, + b"3.24.0\x00" as *const u8 as *const libc::c_char, + sqlite3_threadsafe(), libetpan_get_version_major(), + libetpan_get_version_minor(), + (0x1000212fi64 >> 28i32) as libc::c_int, + (0x1000212fi64 >> 20i32) as libc::c_int & 0xffi32, + (0x1000212fi64 >> 12i32) as libc::c_int & 0xffi32, + (('a' as i32 - 1i32) as libc::c_long + + (0x1000212fi64 >> 4i32 & 0xffi32 as libc::c_long)) as + libc::c_char as libc::c_int, rpgp_enabled, + (::std::mem::size_of::<*mut libc::c_void>() as + libc::c_ulong).wrapping_mul(8i32 as libc::c_ulong), + chats, real_msgs, deaddrop_msgs, contacts, + if !(*context).dbfile.is_null() { + (*context).dbfile + } else { unset }, dbversion, + if !(*context).blobdir.is_null() { + (*context).blobdir + } else { unset }, + if !displayname.is_null() { displayname } else { unset }, + is_configured, l_readable_str, l2_readable_str, + inbox_watch, sentbox_watch, mvbox_watch, mvbox_move, + folders_configured, configured_sentbox_folder, + configured_mvbox_folder, mdns_enabled, e2ee_enabled, + prv_key_cnt, pub_key_cnt, fingerprint_str); + dc_strbuilder_cat(&mut ret, temp); + free(temp as *mut libc::c_void); + dc_loginparam_unref(l); + dc_loginparam_unref(l2); + free(displayname as *mut libc::c_void); + free(l_readable_str as *mut libc::c_void); + free(l2_readable_str as *mut libc::c_void); + free(configured_sentbox_folder as *mut libc::c_void); + 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; +} +#[no_mangle] +pub unsafe extern "C" fn dc_get_version_str() -> *mut libc::c_char { + return dc_strdup(b"0.42.0\x00" as *const u8 as *const libc::c_char); +} +#[no_mangle] +pub unsafe extern "C" 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); + } + } + sqlite3_finalize(stmt); + return ret; +} +#[no_mangle] +pub unsafe extern "C" fn dc_search_msgs( + mut context: *mut dc_context_t, + mut chat_id: uint32_t, + mut 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()) + { + real_query = dc_strdup(query); + dc_trim(real_query); + if *real_query.offset(0isize) as libc::c_int == 0i32 { + success = 1i32 + } else { + strLikeInText = dc_mprintf( + b"%%%s%%\x00" as *const u8 as *const libc::c_char, + real_query, + ); + 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); + } 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); + } + while sqlite3_step(stmt) == 100i32 { + dc_array_add_id(ret, sqlite3_column_int(stmt, 0i32) as uint32_t); + } + success = 1i32 + } + } + 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; + } else { + if !ret.is_null() { + dc_array_unref(ret); + } + return 0 as *mut dc_array_t; + }; +} +#[no_mangle] +pub unsafe extern "C" fn dc_is_inbox( + mut context: *mut dc_context_t, + mut folder_name: *const libc::c_char, +) -> libc::c_int { + let mut is_inbox: libc::c_int = 0i32; + if !folder_name.is_null() { + is_inbox = if strcasecmp( + b"INBOX\x00" as *const u8 as *const libc::c_char, + folder_name, + ) == 0i32 + { + 1i32 + } else { + 0i32 + } + } + return is_inbox; +} +#[no_mangle] +pub unsafe extern "C" fn dc_is_sentbox( + mut context: *mut dc_context_t, + mut folder_name: *const libc::c_char, +) -> libc::c_int { + let mut sentbox_name: *mut libc::c_char = dc_sqlite3_get_config( + (*context).sql, + 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; + if !sentbox_name.is_null() && !folder_name.is_null() { + is_sentbox = if strcasecmp(sentbox_name, folder_name) == 0i32 { + 1i32 + } else { + 0i32 + } + } + free(sentbox_name as *mut libc::c_void); + return is_sentbox; +} +#[no_mangle] +pub unsafe extern "C" 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, + 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; + if !mvbox_name.is_null() && !folder_name.is_null() { + is_mvbox = if strcasecmp(mvbox_name, folder_name) == 0i32 { + 1i32 + } else { + 0i32 + } + } + free(mvbox_name as *mut libc::c_void); + return is_mvbox; +} diff --git a/src/dc_dehtml.rs b/src/dc_dehtml.rs new file mode 100644 index 000000000..3a753134a --- /dev/null +++ b/src/dc_dehtml.rs @@ -0,0 +1,269 @@ +use libc; +extern "C" { + #[no_mangle] + fn free(_: *mut libc::c_void); + #[no_mangle] + fn memset(_: *mut libc::c_void, _: libc::c_int, _: libc::c_ulong) -> *mut libc::c_void; + #[no_mangle] + fn strcmp(_: *const libc::c_char, _: *const libc::c_char) -> libc::c_int; + #[no_mangle] + fn strlen(_: *const libc::c_char) -> libc::c_ulong; + /* string tools */ + #[no_mangle] + fn dc_strdup(_: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn dc_strdup_keep_null(_: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn dc_trim(_: *mut libc::c_char); + #[no_mangle] + fn dc_strbuilder_init(_: *mut dc_strbuilder_t, init_bytes: libc::c_int); + #[no_mangle] + fn dc_strbuilder_cat(_: *mut dc_strbuilder_t, text: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn dc_saxparser_parse(_: *mut dc_saxparser_t, text: *const libc::c_char); + #[no_mangle] + fn dc_saxparser_set_text_handler(_: *mut dc_saxparser_t, _: dc_saxparser_text_cb_t); + #[no_mangle] + fn dc_attr_find(attr: *mut *mut libc::c_char, key: *const libc::c_char) -> *const libc::c_char; + #[no_mangle] + fn dc_saxparser_set_tag_handler( + _: *mut dc_saxparser_t, + _: dc_saxparser_starttag_cb_t, + _: dc_saxparser_endtag_cb_t, + ); + #[no_mangle] + fn dc_saxparser_init(_: *mut dc_saxparser_t, userData: *mut libc::c_void); +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_strbuilder { + pub buf: *mut libc::c_char, + pub allocated: libc::c_int, + pub free: libc::c_int, + pub eos: *mut libc::c_char, +} +pub type dc_strbuilder_t = _dc_strbuilder; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct dehtml_t { + pub strbuilder: dc_strbuilder_t, + pub add_text: libc::c_int, + pub last_href: *mut libc::c_char, +} +pub type dc_saxparser_t = _dc_saxparser; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_saxparser { + pub starttag_cb: dc_saxparser_starttag_cb_t, + pub endtag_cb: dc_saxparser_endtag_cb_t, + pub text_cb: dc_saxparser_text_cb_t, + pub userdata: *mut libc::c_void, +} +/* len is only informational, text is already null-terminated */ +pub type dc_saxparser_text_cb_t = Option< + unsafe extern "C" fn(_: *mut libc::c_void, _: *const libc::c_char, _: libc::c_int) -> (), +>; +pub type dc_saxparser_endtag_cb_t = + Option ()>; +pub type dc_saxparser_starttag_cb_t = Option< + unsafe extern "C" fn( + _: *mut libc::c_void, + _: *const libc::c_char, + _: *mut *mut libc::c_char, + ) -> (), +>; +/* ** library-internal *********************************************************/ +/* dc_dehtml() returns way too many lineends; however, an optimisation on this issue is not needed as the lineends are typically remove in further processing by the caller */ +#[no_mangle] +pub unsafe extern "C" fn dc_dehtml(mut buf_terminated: *mut libc::c_char) -> *mut libc::c_char { + dc_trim(buf_terminated); + if *buf_terminated.offset(0isize) as libc::c_int == 0i32 { + return dc_strdup(b"\x00" as *const u8 as *const libc::c_char); + } else { + let mut dehtml: dehtml_t = dehtml_t { + strbuilder: _dc_strbuilder { + buf: 0 as *mut libc::c_char, + allocated: 0, + free: 0, + eos: 0 as *mut libc::c_char, + }, + add_text: 0, + last_href: 0 as *mut libc::c_char, + }; + let mut saxparser: dc_saxparser_t = _dc_saxparser { + starttag_cb: None, + endtag_cb: None, + text_cb: None, + userdata: 0 as *mut libc::c_void, + }; + memset( + &mut dehtml as *mut dehtml_t as *mut libc::c_void, + 0i32, + ::std::mem::size_of::() as libc::c_ulong, + ); + dehtml.add_text = 1i32; + dc_strbuilder_init( + &mut dehtml.strbuilder, + strlen(buf_terminated) as libc::c_int, + ); + dc_saxparser_init( + &mut saxparser, + &mut dehtml as *mut dehtml_t as *mut libc::c_void, + ); + dc_saxparser_set_tag_handler( + &mut saxparser, + Some(dehtml_starttag_cb), + Some(dehtml_endtag_cb), + ); + dc_saxparser_set_text_handler(&mut saxparser, Some(dehtml_text_cb)); + dc_saxparser_parse(&mut saxparser, buf_terminated); + free(dehtml.last_href as *mut libc::c_void); + return dehtml.strbuilder.buf; + }; +} +unsafe extern "C" fn dehtml_text_cb( + mut userdata: *mut libc::c_void, + mut text: *const libc::c_char, + mut len: libc::c_int, +) { + let mut dehtml: *mut dehtml_t = userdata as *mut dehtml_t; + if (*dehtml).add_text != 0i32 { + let mut last_added: *mut libc::c_char = dc_strbuilder_cat(&mut (*dehtml).strbuilder, text); + if (*dehtml).add_text == 1i32 { + let mut p: *mut libc::c_uchar = last_added as *mut libc::c_uchar; + while 0 != *p { + if *p as libc::c_int == '\n' as i32 { + let mut last_is_lineend: libc::c_int = 1i32; + let mut p2: *const libc::c_uchar = p.offset(-1isize); + while p2 >= (*dehtml).strbuilder.buf as *const libc::c_uchar { + if *p2 as libc::c_int == '\r' as i32 { + p2 = p2.offset(-1isize) + } else { + if *p2 as libc::c_int == '\n' as i32 { + break; + } + last_is_lineend = 0i32; + break; + } + } + *p = (if 0 != last_is_lineend { + '\r' as i32 + } else { + ' ' as i32 + }) as libc::c_uchar + } + p = p.offset(1isize) + } + } + }; +} +unsafe extern "C" fn dehtml_endtag_cb( + mut userdata: *mut libc::c_void, + mut tag: *const libc::c_char, +) { + let mut dehtml: *mut dehtml_t = userdata as *mut dehtml_t; + if strcmp(tag, b"p\x00" as *const u8 as *const libc::c_char) == 0i32 + || strcmp(tag, b"div\x00" as *const u8 as *const libc::c_char) == 0i32 + || strcmp(tag, b"table\x00" as *const u8 as *const libc::c_char) == 0i32 + || strcmp(tag, b"td\x00" as *const u8 as *const libc::c_char) == 0i32 + || strcmp(tag, b"style\x00" as *const u8 as *const libc::c_char) == 0i32 + || strcmp(tag, b"script\x00" as *const u8 as *const libc::c_char) == 0i32 + || strcmp(tag, b"title\x00" as *const u8 as *const libc::c_char) == 0i32 + || strcmp(tag, b"pre\x00" as *const u8 as *const libc::c_char) == 0i32 + { + dc_strbuilder_cat( + &mut (*dehtml).strbuilder, + b"\n\n\x00" as *const u8 as *const libc::c_char, + ); + (*dehtml).add_text = 1i32 + } else if strcmp(tag, b"a\x00" as *const u8 as *const libc::c_char) == 0i32 { + if !(*dehtml).last_href.is_null() { + dc_strbuilder_cat( + &mut (*dehtml).strbuilder, + b"](\x00" as *const u8 as *const libc::c_char, + ); + dc_strbuilder_cat(&mut (*dehtml).strbuilder, (*dehtml).last_href); + dc_strbuilder_cat( + &mut (*dehtml).strbuilder, + b")\x00" as *const u8 as *const libc::c_char, + ); + free((*dehtml).last_href as *mut libc::c_void); + (*dehtml).last_href = 0 as *mut libc::c_char + } + } else if strcmp(tag, b"b\x00" as *const u8 as *const libc::c_char) == 0i32 + || strcmp(tag, b"strong\x00" as *const u8 as *const libc::c_char) == 0i32 + { + dc_strbuilder_cat( + &mut (*dehtml).strbuilder, + b"*\x00" as *const u8 as *const libc::c_char, + ); + } else if strcmp(tag, b"i\x00" as *const u8 as *const libc::c_char) == 0i32 + || strcmp(tag, b"em\x00" as *const u8 as *const libc::c_char) == 0i32 + { + dc_strbuilder_cat( + &mut (*dehtml).strbuilder, + b"_\x00" as *const u8 as *const libc::c_char, + ); + }; +} +unsafe extern "C" fn dehtml_starttag_cb( + mut userdata: *mut libc::c_void, + mut tag: *const libc::c_char, + mut attr: *mut *mut libc::c_char, +) { + let mut dehtml: *mut dehtml_t = userdata as *mut dehtml_t; + if strcmp(tag, b"p\x00" as *const u8 as *const libc::c_char) == 0i32 + || strcmp(tag, b"div\x00" as *const u8 as *const libc::c_char) == 0i32 + || strcmp(tag, b"table\x00" as *const u8 as *const libc::c_char) == 0i32 + || strcmp(tag, b"td\x00" as *const u8 as *const libc::c_char) == 0i32 + { + dc_strbuilder_cat( + &mut (*dehtml).strbuilder, + b"\n\n\x00" as *const u8 as *const libc::c_char, + ); + (*dehtml).add_text = 1i32 + } else if strcmp(tag, b"br\x00" as *const u8 as *const libc::c_char) == 0i32 { + dc_strbuilder_cat( + &mut (*dehtml).strbuilder, + b"\n\x00" as *const u8 as *const libc::c_char, + ); + (*dehtml).add_text = 1i32 + } else if strcmp(tag, b"style\x00" as *const u8 as *const libc::c_char) == 0i32 + || strcmp(tag, b"script\x00" as *const u8 as *const libc::c_char) == 0i32 + || strcmp(tag, b"title\x00" as *const u8 as *const libc::c_char) == 0i32 + { + (*dehtml).add_text = 0i32 + } else if strcmp(tag, b"pre\x00" as *const u8 as *const libc::c_char) == 0i32 { + dc_strbuilder_cat( + &mut (*dehtml).strbuilder, + b"\n\n\x00" as *const u8 as *const libc::c_char, + ); + (*dehtml).add_text = 2i32 + } else if strcmp(tag, b"a\x00" as *const u8 as *const libc::c_char) == 0i32 { + free((*dehtml).last_href as *mut libc::c_void); + (*dehtml).last_href = dc_strdup_keep_null(dc_attr_find( + attr, + b"href\x00" as *const u8 as *const libc::c_char, + )); + if !(*dehtml).last_href.is_null() { + dc_strbuilder_cat( + &mut (*dehtml).strbuilder, + b"[\x00" as *const u8 as *const libc::c_char, + ); + } + } else if strcmp(tag, b"b\x00" as *const u8 as *const libc::c_char) == 0i32 + || strcmp(tag, b"strong\x00" as *const u8 as *const libc::c_char) == 0i32 + { + dc_strbuilder_cat( + &mut (*dehtml).strbuilder, + b"*\x00" as *const u8 as *const libc::c_char, + ); + } else if strcmp(tag, b"i\x00" as *const u8 as *const libc::c_char) == 0i32 + || strcmp(tag, b"em\x00" as *const u8 as *const libc::c_char) == 0i32 + { + dc_strbuilder_cat( + &mut (*dehtml).strbuilder, + b"_\x00" as *const u8 as *const libc::c_char, + ); + }; +} diff --git a/src/dc_e2ee.rs b/src/dc_e2ee.rs new file mode 100644 index 000000000..329e651a2 --- /dev/null +++ b/src/dc_e2ee.rs @@ -0,0 +1,2908 @@ +use c2rust_bitfields::BitfieldStruct; +use libc; +extern "C" { + pub type mailstream_cancel; + pub type sqlite3; + #[no_mangle] + fn malloc(_: libc::c_ulong) -> *mut libc::c_void; + #[no_mangle] + fn free(_: *mut libc::c_void); + #[no_mangle] + fn memset(_: *mut libc::c_void, _: libc::c_int, _: libc::c_ulong) -> *mut libc::c_void; + #[no_mangle] + fn strcmp(_: *const libc::c_char, _: *const libc::c_char) -> libc::c_int; + #[no_mangle] + fn strlen(_: *const libc::c_char) -> libc::c_ulong; + #[no_mangle] + fn strncmp(_: *const libc::c_char, _: *const libc::c_char, _: libc::c_ulong) -> libc::c_int; + #[no_mangle] + fn strdup(_: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn strcasecmp(_: *const libc::c_char, _: *const libc::c_char) -> libc::c_int; + #[no_mangle] + fn clock() -> clock_t; + #[no_mangle] + fn time(_: *mut time_t) -> time_t; + #[no_mangle] + fn pthread_self() -> pthread_t; + #[no_mangle] + fn mmap_string_new(init: *const libc::c_char) -> *mut MMAPString; + #[no_mangle] + fn mmap_string_free(string: *mut MMAPString); + #[no_mangle] + fn mmap_string_unref(str: *mut libc::c_char) -> libc::c_int; + #[no_mangle] + fn clist_insert_after(_: *mut clist, _: *mut clistiter, _: *mut libc::c_void) -> libc::c_int; + #[no_mangle] + fn clist_delete(_: *mut clist, _: *mut clistiter) -> *mut clistiter; + #[no_mangle] + fn mailimf_fields_free(fields: *mut mailimf_fields); + #[no_mangle] + 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; + #[no_mangle] + fn mailimf_subject_new(sbj_value: *mut libc::c_char) -> *mut mailimf_subject; + #[no_mangle] + fn mailimf_fields_new_empty() -> *mut mailimf_fields; + #[no_mangle] + fn mailimf_fields_add(fields: *mut mailimf_fields, field: *mut mailimf_field) -> libc::c_int; + #[no_mangle] + fn mailimf_field_new_custom( + name: *mut libc::c_char, + value: *mut libc::c_char, + ) -> *mut mailimf_field; + #[no_mangle] + 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; + #[no_mangle] + fn mailmime_content_free(content: *mut mailmime_content); + #[no_mangle] + fn mailmime_mechanism_new( + enc_type: libc::c_int, + enc_token: *mut libc::c_char, + ) -> *mut mailmime_mechanism; + #[no_mangle] + fn mailmime_mechanism_free(mechanism: *mut mailmime_mechanism); + #[no_mangle] + fn mailmime_fields_free(fields: *mut mailmime_fields); + #[no_mangle] + 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; + #[no_mangle] + fn mailmime_free(mime: *mut mailmime); + #[no_mangle] + fn mailmime_fields_new_empty() -> *mut mailmime_fields; + #[no_mangle] + 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; + #[no_mangle] + fn mailmime_get_content_message() -> *mut mailmime_content; + #[no_mangle] + fn mailmime_new_empty( + content: *mut mailmime_content, + mime_fields: *mut mailmime_fields, + ) -> *mut mailmime; + #[no_mangle] + fn mailmime_set_body_text( + build_info: *mut mailmime, + data_str: *mut libc::c_char, + length: size_t, + ) -> libc::c_int; + #[no_mangle] + fn mailmime_smart_add_part(mime: *mut mailmime, mime_sub: *mut mailmime) -> libc::c_int; + #[no_mangle] + fn mailmime_content_new_with_str(str: *const libc::c_char) -> *mut mailmime_content; + #[no_mangle] + fn mailmime_param_new_with_data( + name: *mut libc::c_char, + value: *mut libc::c_char, + ) -> *mut mailmime_parameter; + #[no_mangle] + fn mailmime_parse( + message: *const libc::c_char, + length: size_t, + indx: *mut size_t, + result: *mut *mut mailmime, + ) -> libc::c_int; + #[no_mangle] + 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; + #[no_mangle] + fn mailmime_write_mem( + f: *mut MMAPString, + col: *mut libc::c_int, + build_info: *mut mailmime, + ) -> libc::c_int; + #[no_mangle] + fn mailmime_substitute(old_mime: *mut mailmime, new_mime: *mut mailmime) -> libc::c_int; + #[no_mangle] + fn mailprivacy_prepare_mime(mime: *mut mailmime); + /* * + * @class dc_array_t + * + * An object containing a simple array. + * This object is used in several places where functions need to return an array. + * The items of the array are typically IDs. + * To free an array object, use dc_array_unref(). + */ + #[no_mangle] + fn dc_array_unref(_: *mut dc_array_t); + #[no_mangle] + fn dc_array_add_ptr(_: *mut dc_array_t, _: *mut libc::c_void); + #[no_mangle] + fn dc_array_get_cnt(_: *const dc_array_t) -> size_t; + #[no_mangle] + fn dc_array_get_ptr(_: *const dc_array_t, index: size_t) -> *mut libc::c_void; + #[no_mangle] + fn dc_sqlite3_get_config( + _: *mut dc_sqlite3_t, + key: *const libc::c_char, + def: *const libc::c_char, + ) -> *mut libc::c_char; + #[no_mangle] + fn dc_sqlite3_get_config_int( + _: *mut dc_sqlite3_t, + key: *const libc::c_char, + def: int32_t, + ) -> int32_t; + /* string tools */ + #[no_mangle] + fn dc_strdup(_: *const libc::c_char) -> *mut libc::c_char; + /* date/time tools */ + #[no_mangle] + fn dc_timestamp_from_date(date_time: *mut mailimf_date_time) -> time_t; + #[no_mangle] + fn dc_array_new(_: *mut dc_context_t, initsize: size_t) -> *mut dc_array_t; + #[no_mangle] + fn dc_key_new() -> *mut dc_key_t; + #[no_mangle] + fn dc_key_unref(_: *mut dc_key_t); + #[no_mangle] + fn dc_key_save_self_keypair( + public_key: *const dc_key_t, + private_key: *const dc_key_t, + addr: *const libc::c_char, + is_default: libc::c_int, + sql: *mut dc_sqlite3_t, + ) -> libc::c_int; + #[no_mangle] + fn dc_key_load_self_public( + _: *mut dc_key_t, + self_addr: *const libc::c_char, + sql: *mut dc_sqlite3_t, + ) -> libc::c_int; + #[no_mangle] + fn dc_key_load_self_private( + _: *mut dc_key_t, + self_addr: *const libc::c_char, + sql: *mut dc_sqlite3_t, + ) -> libc::c_int; + /* the returned pointer is ref'd and must be unref'd after usage */ + #[no_mangle] + fn dc_aheader_new() -> *mut dc_aheader_t; + #[no_mangle] + fn dc_aheader_new_from_imffields( + wanted_from: *const libc::c_char, + mime: *const mailimf_fields, + ) -> *mut dc_aheader_t; + #[no_mangle] + fn dc_aheader_unref(_: *mut dc_aheader_t); + #[no_mangle] + fn dc_aheader_set_from_string( + _: *mut dc_aheader_t, + header_str: *const libc::c_char, + ) -> libc::c_int; + #[no_mangle] + fn dc_aheader_render(_: *const dc_aheader_t) -> *mut libc::c_char; + /* + * There are 4 different modes of operation for a hash table: + * + * DC_HASH_INT nKey is used as the key and pKey is ignored. + * + * DC_HASH_POINTER pKey is used as the key and nKey is ignored. + * + * DC_HASH_STRING pKey points to a string that is nKey bytes long + * (including the null-terminator, if any). Case + * is ignored in comparisons. + * + * DC_HASH_BINARY pKey points to binary data nKey bytes long. + * memcmp() is used to compare keys. + * + * A copy of the key is made for DC_HASH_STRING and DC_HASH_BINARY + * if the copyKey parameter to dc_hash_init() is 1. + */ + /* + * Just to make the last parameter of dc_hash_init() more readable. + */ + /* + * Access routines. To delete an element, insert a NULL pointer. + */ + #[no_mangle] + fn dc_hash_init(_: *mut dc_hash_t, keytype: libc::c_int, copyKey: libc::c_int); + #[no_mangle] + fn dc_hash_insert( + _: *mut dc_hash_t, + pKey: *const libc::c_void, + nKey: libc::c_int, + pData: *mut libc::c_void, + ) -> *mut libc::c_void; + #[no_mangle] + fn dc_hash_find( + _: *const dc_hash_t, + pKey: *const libc::c_void, + nKey: libc::c_int, + ) -> *mut libc::c_void; + #[no_mangle] + fn dc_hash_clear(_: *mut dc_hash_t); + #[no_mangle] + fn dc_apeerstate_new(_: *mut dc_context_t) -> *mut dc_apeerstate_t; + #[no_mangle] + fn dc_apeerstate_unref(_: *mut dc_apeerstate_t); + #[no_mangle] + fn dc_apeerstate_init_from_header( + _: *mut dc_apeerstate_t, + _: *const dc_aheader_t, + message_time: time_t, + ) -> libc::c_int; + #[no_mangle] + fn dc_apeerstate_init_from_gossip( + _: *mut dc_apeerstate_t, + _: *const dc_aheader_t, + message_time: time_t, + ) -> libc::c_int; + #[no_mangle] + fn dc_apeerstate_degrade_encryption( + _: *mut dc_apeerstate_t, + message_time: time_t, + ) -> libc::c_int; + #[no_mangle] + fn dc_apeerstate_apply_header( + _: *mut dc_apeerstate_t, + _: *const dc_aheader_t, + message_time: time_t, + ); + #[no_mangle] + fn dc_apeerstate_apply_gossip( + _: *mut dc_apeerstate_t, + _: *const dc_aheader_t, + message_time: time_t, + ); + #[no_mangle] + fn dc_apeerstate_render_gossip_header( + _: *const dc_apeerstate_t, + min_verified: libc::c_int, + ) -> *mut libc::c_char; + #[no_mangle] + fn dc_apeerstate_peek_key( + _: *const dc_apeerstate_t, + min_verified: libc::c_int, + ) -> *mut dc_key_t; + #[no_mangle] + fn dc_apeerstate_load_by_addr( + _: *mut dc_apeerstate_t, + _: *mut dc_sqlite3_t, + addr: *const libc::c_char, + ) -> libc::c_int; + #[no_mangle] + fn dc_apeerstate_save_to_db( + _: *const dc_apeerstate_t, + _: *mut dc_sqlite3_t, + create: libc::c_int, + ) -> libc::c_int; + #[no_mangle] + fn mailmime_find_mailimf_fields(_: *mut mailmime) -> *mut mailimf_fields; + #[no_mangle] + fn mailimf_find_first_addr(_: *const mailimf_mailbox_list) -> *mut libc::c_char; + #[no_mangle] + fn mailimf_find_field( + _: *mut mailimf_fields, + wanted_fld_type: libc::c_int, + ) -> *mut mailimf_field; + #[no_mangle] + fn mailimf_get_recipients(_: *mut mailimf_fields) -> *mut dc_hash_t; + #[no_mangle] + fn dc_log_warning(_: *mut dc_context_t, data1: libc::c_int, msg: *const libc::c_char, _: ...); + #[no_mangle] + fn dc_log_info(_: *mut dc_context_t, data1: libc::c_int, msg: *const libc::c_char, _: ...); + #[no_mangle] + fn dc_keyring_new() -> *mut dc_keyring_t; + #[no_mangle] + fn dc_keyring_unref(_: *mut dc_keyring_t); + #[no_mangle] + fn dc_pgp_pk_encrypt( + _: *mut dc_context_t, + plain: *const libc::c_void, + plain_bytes: size_t, + _: *const dc_keyring_t, + sign_key: *const dc_key_t, + use_armor: libc::c_int, + ret_ctext: *mut *mut libc::c_void, + ret_ctext_bytes: *mut size_t, + ) -> libc::c_int; + #[no_mangle] + fn dc_keyring_add(_: *mut dc_keyring_t, _: *mut dc_key_t); + #[no_mangle] + fn dc_pgp_is_valid_key(_: *mut dc_context_t, _: *const dc_key_t) -> libc::c_int; + /* public key encryption */ + #[no_mangle] + fn dc_pgp_create_keypair( + _: *mut dc_context_t, + addr: *const libc::c_char, + public_key: *mut dc_key_t, + private_key: *mut dc_key_t, + ) -> libc::c_int; + #[no_mangle] + fn dc_pgp_rand_seed(_: *mut dc_context_t, buf: *const libc::c_void, bytes: size_t); + #[no_mangle] + fn dc_handle_degrade_event(_: *mut dc_context_t, _: *mut dc_apeerstate_t); + #[no_mangle] + fn dc_pgp_pk_decrypt( + _: *mut dc_context_t, + ctext: *const libc::c_void, + ctext_bytes: size_t, + _: *const dc_keyring_t, + validate_keys: *const dc_keyring_t, + use_armor: libc::c_int, + plain: *mut *mut libc::c_void, + plain_bytes: *mut size_t, + ret_signature_fingerprints: *mut dc_hash_t, + ) -> libc::c_int; + #[no_mangle] + fn dc_keyring_load_self_private_for_decrypting( + _: *mut dc_keyring_t, + self_addr: *const libc::c_char, + sql: *mut dc_sqlite3_t, + ) -> libc::c_int; +} +pub type __darwin_size_t = libc::c_ulong; +pub type __darwin_clock_t = libc::c_ulong; +pub type __darwin_ssize_t = libc::c_long; +pub type __darwin_time_t = libc::c_long; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct __darwin_pthread_handler_rec { + pub __routine: Option ()>, + pub __arg: *mut libc::c_void, + pub __next: *mut __darwin_pthread_handler_rec, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_cond_t { + pub __sig: libc::c_long, + pub __opaque: [libc::c_char; 40], +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_mutex_t { + pub __sig: libc::c_long, + pub __opaque: [libc::c_char; 56], +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_t { + pub __sig: libc::c_long, + pub __cleanup_stack: *mut __darwin_pthread_handler_rec, + pub __opaque: [libc::c_char; 8176], +} +pub type __darwin_pthread_cond_t = _opaque_pthread_cond_t; +pub type __darwin_pthread_mutex_t = _opaque_pthread_mutex_t; +pub type __darwin_pthread_t = *mut _opaque_pthread_t; +pub type int32_t = libc::c_int; +pub type uintptr_t = libc::c_ulong; +pub type size_t = __darwin_size_t; +pub type uint8_t = libc::c_uchar; +pub type uint32_t = libc::c_uint; +pub type ssize_t = __darwin_ssize_t; +pub type clock_t = __darwin_clock_t; +pub type time_t = __darwin_time_t; +pub type pthread_cond_t = __darwin_pthread_cond_t; +pub type pthread_mutex_t = __darwin_pthread_mutex_t; +pub type pthread_t = __darwin_pthread_t; +#[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; +#[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) -> (); +#[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 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, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct mailimf_mailbox_list { + pub mb_list: *mut clist, +} +#[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_fields { + pub fld_list: *mut clist, +} +pub type unnamed = libc::c_uint; +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: unnamed_0, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed_0 { + 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, +} +#[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, +} +pub type unnamed_1 = libc::c_uint; +pub const MAILIMF_ERROR_FILE: unnamed_1 = 4; +pub const MAILIMF_ERROR_INVAL: unnamed_1 = 3; +pub const MAILIMF_ERROR_MEMORY: unnamed_1 = 2; +pub const MAILIMF_ERROR_PARSE: unnamed_1 = 1; +pub const MAILIMF_NO_ERROR: unnamed_1 = 0; +pub type unnamed_2 = libc::c_uint; +pub const MAILMIME_COMPOSITE_TYPE_EXTENSION: unnamed_2 = 3; +pub const MAILMIME_COMPOSITE_TYPE_MULTIPART: unnamed_2 = 2; +pub const MAILMIME_COMPOSITE_TYPE_MESSAGE: unnamed_2 = 1; +pub const MAILMIME_COMPOSITE_TYPE_ERROR: unnamed_2 = 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 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_type { + pub tp_type: libc::c_int, + pub tp_data: unnamed_3, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed_3 { + 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 type unnamed_4 = libc::c_uint; +pub const MAILMIME_FIELD_LOCATION: unnamed_4 = 8; +pub const MAILMIME_FIELD_LANGUAGE: unnamed_4 = 7; +pub const MAILMIME_FIELD_DISPOSITION: unnamed_4 = 6; +pub const MAILMIME_FIELD_VERSION: unnamed_4 = 5; +pub const MAILMIME_FIELD_DESCRIPTION: unnamed_4 = 4; +pub const MAILMIME_FIELD_ID: unnamed_4 = 3; +pub const MAILMIME_FIELD_TRANSFER_ENCODING: unnamed_4 = 2; +pub const MAILMIME_FIELD_TYPE: unnamed_4 = 1; +pub const MAILMIME_FIELD_NONE: unnamed_4 = 0; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct mailmime_field { + pub fld_type: libc::c_int, + pub fld_data: unnamed_5, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed_5 { + 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 type unnamed_6 = libc::c_uint; +pub const MAILMIME_MECHANISM_TOKEN: unnamed_6 = 6; +pub const MAILMIME_MECHANISM_BASE64: unnamed_6 = 5; +pub const MAILMIME_MECHANISM_QUOTED_PRINTABLE: unnamed_6 = 4; +pub const MAILMIME_MECHANISM_BINARY: unnamed_6 = 3; +pub const MAILMIME_MECHANISM_8BIT: unnamed_6 = 2; +pub const MAILMIME_MECHANISM_7BIT: unnamed_6 = 1; +pub const MAILMIME_MECHANISM_ERROR: unnamed_6 = 0; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct mailmime_fields { + pub fld_list: *mut clist, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct mailmime_parameter { + pub pa_name: *mut libc::c_char, + pub pa_value: *mut libc::c_char, +} +pub type unnamed_7 = libc::c_uint; +pub const MAILMIME_TYPE_COMPOSITE_TYPE: unnamed_7 = 2; +pub const MAILMIME_TYPE_DISCRETE_TYPE: unnamed_7 = 1; +pub const MAILMIME_TYPE_ERROR: unnamed_7 = 0; +pub type unnamed_8 = libc::c_uint; +pub const MAILMIME_DATA_FILE: unnamed_8 = 1; +pub const MAILMIME_DATA_TEXT: unnamed_8 = 0; +#[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_9, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed_9 { + pub dt_text: unnamed_10, + pub dt_filename: *mut libc::c_char, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct unnamed_10 { + pub dt_data: *const libc::c_char, + pub dt_length: size_t, +} +pub type unnamed_11 = libc::c_uint; +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_12, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed_12 { + pub mm_single: *mut mailmime_data, + pub mm_multipart: unnamed_14, + pub mm_message: unnamed_13, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct unnamed_13 { + pub mm_fields: *mut mailimf_fields, + pub mm_msg_mime: *mut mailmime, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct unnamed_14 { + pub mm_preamble: *mut mailmime_data, + pub mm_epilogue: *mut mailmime_data, + pub mm_mp_list: *mut clist, +} +pub type unnamed_15 = libc::c_uint; +pub const MAIL_ERROR_SSL: unnamed_15 = 58; +pub const MAIL_ERROR_FOLDER: unnamed_15 = 57; +pub const MAIL_ERROR_UNABLE: unnamed_15 = 56; +pub const MAIL_ERROR_SYSTEM: unnamed_15 = 55; +pub const MAIL_ERROR_COMMAND: unnamed_15 = 54; +pub const MAIL_ERROR_SEND: unnamed_15 = 53; +pub const MAIL_ERROR_CHAR_ENCODING_FAILED: unnamed_15 = 52; +pub const MAIL_ERROR_SUBJECT_NOT_FOUND: unnamed_15 = 51; +pub const MAIL_ERROR_PROGRAM_ERROR: unnamed_15 = 50; +pub const MAIL_ERROR_NO_PERMISSION: unnamed_15 = 49; +pub const MAIL_ERROR_COMMAND_NOT_SUPPORTED: unnamed_15 = 48; +pub const MAIL_ERROR_NO_APOP: unnamed_15 = 47; +pub const MAIL_ERROR_READONLY: unnamed_15 = 46; +pub const MAIL_ERROR_FATAL: unnamed_15 = 45; +pub const MAIL_ERROR_CLOSE: unnamed_15 = 44; +pub const MAIL_ERROR_CAPABILITY: unnamed_15 = 43; +pub const MAIL_ERROR_PROTOCOL: unnamed_15 = 42; +pub const MAIL_ERROR_MISC: unnamed_15 = 41; +pub const MAIL_ERROR_EXPUNGE: unnamed_15 = 40; +pub const MAIL_ERROR_NO_TLS: unnamed_15 = 39; +pub const MAIL_ERROR_CACHE_MISS: unnamed_15 = 38; +pub const MAIL_ERROR_STARTTLS: unnamed_15 = 37; +pub const MAIL_ERROR_MOVE: unnamed_15 = 36; +pub const MAIL_ERROR_FOLDER_NOT_FOUND: unnamed_15 = 35; +pub const MAIL_ERROR_REMOVE: unnamed_15 = 34; +pub const MAIL_ERROR_PART_NOT_FOUND: unnamed_15 = 33; +pub const MAIL_ERROR_INVAL: unnamed_15 = 32; +pub const MAIL_ERROR_PARSE: unnamed_15 = 31; +pub const MAIL_ERROR_MSG_NOT_FOUND: unnamed_15 = 30; +pub const MAIL_ERROR_DISKSPACE: unnamed_15 = 29; +pub const MAIL_ERROR_SEARCH: unnamed_15 = 28; +pub const MAIL_ERROR_STORE: unnamed_15 = 27; +pub const MAIL_ERROR_FETCH: unnamed_15 = 26; +pub const MAIL_ERROR_COPY: unnamed_15 = 25; +pub const MAIL_ERROR_APPEND: unnamed_15 = 24; +pub const MAIL_ERROR_LSUB: unnamed_15 = 23; +pub const MAIL_ERROR_LIST: unnamed_15 = 22; +pub const MAIL_ERROR_UNSUBSCRIBE: unnamed_15 = 21; +pub const MAIL_ERROR_SUBSCRIBE: unnamed_15 = 20; +pub const MAIL_ERROR_STATUS: unnamed_15 = 19; +pub const MAIL_ERROR_MEMORY: unnamed_15 = 18; +pub const MAIL_ERROR_SELECT: unnamed_15 = 17; +pub const MAIL_ERROR_EXAMINE: unnamed_15 = 16; +pub const MAIL_ERROR_CHECK: unnamed_15 = 15; +pub const MAIL_ERROR_RENAME: unnamed_15 = 14; +pub const MAIL_ERROR_NOOP: unnamed_15 = 13; +pub const MAIL_ERROR_LOGOUT: unnamed_15 = 12; +pub const MAIL_ERROR_DELETE: unnamed_15 = 11; +pub const MAIL_ERROR_CREATE: unnamed_15 = 10; +pub const MAIL_ERROR_LOGIN: unnamed_15 = 9; +pub const MAIL_ERROR_STREAM: unnamed_15 = 8; +pub const MAIL_ERROR_FILE: unnamed_15 = 7; +pub const MAIL_ERROR_BAD_STATE: unnamed_15 = 6; +pub const MAIL_ERROR_CONNECT: unnamed_15 = 5; +pub const MAIL_ERROR_UNKNOWN: unnamed_15 = 4; +pub const MAIL_ERROR_NOT_IMPLEMENTED: unnamed_15 = 3; +pub const MAIL_NO_ERROR_NON_AUTHENTICATED: unnamed_15 = 2; +pub const MAIL_NO_ERROR_AUTHENTICATED: unnamed_15 = 1; +pub const MAIL_NO_ERROR: unnamed_15 = 0; +#[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_16, + 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_16 { + 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_capability_data { + pub cap_list: *mut clist, +} +#[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_17, + 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_17 { + 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 extern "C" 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_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, +} +#[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, +} +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_19, + 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 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, +} +/* define DC_USE_RPGP to enable use of rPGP instead of netpgp where available; +preferrably, this should be done in the project configuration currently */ +//#define DC_USE_RPGP 1 +/* Includes that are used frequently. This file may also be used to create predefined headers. */ +/* * Structure behind dc_context_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_context { + pub magic: uint32_t, + pub userdata: *mut libc::c_void, + pub dbfile: *mut libc::c_char, + pub blobdir: *mut libc::c_char, + pub sql: *mut dc_sqlite3_t, + pub inbox: *mut dc_imap_t, + pub inboxidle_condmutex: pthread_mutex_t, + pub perform_inbox_jobs_needed: libc::c_int, + pub probe_imap_network: libc::c_int, + pub sentbox_thread: dc_jobthread_t, + pub mvbox_thread: dc_jobthread_t, + pub smtp: *mut dc_smtp_t, + pub smtpidle_cond: pthread_cond_t, + pub smtpidle_condmutex: pthread_mutex_t, + pub smtpidle_condflag: libc::c_int, + pub smtp_suspended: libc::c_int, + pub smtp_doing_jobs: libc::c_int, + pub perform_smtp_jobs_needed: libc::c_int, + pub probe_smtp_network: libc::c_int, + pub oauth2_critical: pthread_mutex_t, + 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 type dc_lot_t = _dc_lot; +/* * Structure behind dc_lot_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_lot { + pub magic: uint32_t, + pub text1_meaning: libc::c_int, + pub text1: *mut libc::c_char, + pub text2: *mut libc::c_char, + pub timestamp: time_t, + pub state: libc::c_int, + pub id: uint32_t, + pub fingerprint: *mut libc::c_char, + pub invitenumber: *mut libc::c_char, + pub auth: *mut libc::c_char, +} +/* * + * 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 = Option< + unsafe extern "C" fn( + _: *mut dc_context_t, + _: libc::c_int, + _: uintptr_t, + _: uintptr_t, + ) -> uintptr_t, +>; +/* * + * @mainpage Getting started + * + * This document describes how to handle the Delta Chat core library. + * For general information about Delta Chat itself, + * see and . + * + * Let's start. + * + * First of all, you have to **define an event-handler-function** + * that is called by the library on specific events + * (eg. when the configuration is done or when fresh messages arrive). + * With this function you can create a Delta Chat context then: + * + * ~~~ + * #include + * + * uintptr_t event_handler_func(dc_context_t* context, int event, + * uintptr_t data1, uintptr_t data2) + * { + * return 0; // for unhandled events, it is always safe to return 0 + * } + * + * dc_context_t* context = dc_context_new(event_handler_func, NULL, NULL); + * ~~~ + * + * After that, you should make sure, + * sending and receiving jobs are processed as needed. + * For this purpose, you have to **create two threads:** + * + * ~~~ + * #include + * + * void* imap_thread_func(void* context) + * { + * while (true) { + * dc_perform_imap_jobs(context); + * dc_perform_imap_fetch(context); + * dc_perform_imap_idle(context); + * } + * } + * + * void* smtp_thread_func(void* context) + * { + * while (true) { + * dc_perform_smtp_jobs(context); + * dc_perform_smtp_idle(context); + * } + * } + * + * static pthread_t imap_thread, smtp_thread; + * pthread_create(&imap_thread, NULL, imap_thread_func, context); + * pthread_create(&smtp_thread, NULL, smtp_thread_func, context); + * ~~~ + * + * The example above uses "pthreads", + * however, you can also use anything else for thread handling. + * NB: The deltachat-core library itself does not create any threads on its own, + * however, functions, unless stated otherwise, are thread-safe. + * + * After that you can **define and open a database.** + * The database is a normal sqlite-file and is created as needed: + * + * ~~~ + * dc_open(context, "example.db", NULL); + * ~~~ + * + * Now you can **configure the context:** + * + * ~~~ + * // use some real test credentials here + * dc_set_config(context, "addr", "alice@example.org"); + * dc_set_config(context, "mail_pw", "***"); + * dc_configure(context); + * ~~~ + * + * dc_configure() returns immediately, the configuration itself may take a while + * and is done by a job in the imap-thread you've defined above. + * Once done, the #DC_EVENT_CONFIGURE_PROGRESS reports success + * to the event_handler_func() that is also defined above. + * + * The configuration result is saved in the database, + * on subsequent starts it is not needed to call dc_configure() + * (you can check this using dc_is_configured()). + * + * Now you can **send the first message:** + * + * ~~~ + * // use a real testing address here + * uint32_t contact_id = dc_create_contact(context, NULL, "bob@example.org"); + * uint32_t chat_id = dc_create_chat_by_contact_id(context, contact_id); + * + * dc_send_text_msg(context, chat_id, "Hi, here is my first message!"); + * ~~~ + * + * dc_send_text_msg() returns immediately; + * the sending itself is done by a job in the smtp-thread you've defined above. + * If you check the testing address (bob) + * and you should have received a normal email. + * Answer this email in any email program with "Got it!" + * and the imap-thread you've create above will **receive the message**. + * + * You can then **list all messages** of a chat as follow: + * + * ~~~ + * dc_array_t* msglist = dc_get_chat_msgs(context, chat_id, 0, 0); + * for (int i = 0; i < dc_array_get_cnt(msglist); i++) + * { + * uint32_t msg_id = dc_array_get_id(msglist, i); + * dc_msg_t* msg = dc_get_msg(context, msg_id); + * char* text = dc_msg_get_text(msg); + * + * printf("Message %i: %s\n", i+1, text); + * + * free(text); + * dc_msg_unref(msg); + * } + * dc_array_unref(msglist); + * ~~~ + * + * This will output the following two lines: + * + * ~~~ + * Message 1: Hi, here is my first message! + * Message 2: Got it! + * ~~~ + * + * + * ## Class reference + * + * For a class reference, see the "Classes" link atop. + * + * + * ## Further hints + * + * Here are some additional, unsorted hints that may be useful. + * + * - For `get`-functions, you have to unref the return value in some way. + * + * - Strings in function arguments or return values are usually UTF-8 encoded. + * + * - The issue-tracker for the core library is here: + * + * + * The following points are important mainly + * for the authors of the library itself: + * + * - For indentation, use tabs. + * Alignments that are not placed at the beginning of a line + * should be done with spaces. + * + * - For padding between functions, + * classes etc. use 2 empty lines + * + * - Source files are encoded as UTF-8 with Unix line endings + * (a simple `LF`, `0x0A` or `\n`) + * + * If you need further assistance, + * please do not hesitate to contact us + * through the channels shown at https://delta.chat/en/contribute + * + * Please keep in mind, that your derived work + * must respect the Mozilla Public License 2.0 of libdeltachat + * and the respective licenses of the libraries libdeltachat links with. + * + * See you. + */ +/* * + * @class dc_context_t + * + * An object representing a single account. + * + * Each account is linked to an IMAP/SMTP account and uses a separate + * SQLite database for offline functionality and for account-related + * settings. + */ +pub type dc_context_t = _dc_context; +/* ** library-private **********************************************************/ +pub type dc_smtp_t = _dc_smtp; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_smtp { + 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 error: *mut libc::c_char, + pub error_etpan: libc::c_int, +} +pub type dc_jobthread_t = _dc_jobthread; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_jobthread { + 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, + 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, +} +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_imap { + 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 type dc_receive_imf_t = Option< + unsafe extern "C" 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_imap_t = _dc_imap; +pub type dc_precheck_imf_t = Option< + unsafe extern "C" 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< + unsafe extern "C" fn(_: *mut dc_imap_t, _: *const libc::c_char, _: *const libc::c_char) -> (), +>; +pub type dc_get_config_t = Option< + unsafe extern "C" fn( + _: *mut dc_imap_t, + _: *const libc::c_char, + _: *const libc::c_char, + ) -> *mut libc::c_char, +>; +/* ** library-private **********************************************************/ +pub type dc_sqlite3_t = _dc_sqlite3; +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_sqlite3 { + pub cobj: *mut sqlite3, + pub context: *mut dc_context_t, +} +/* * the structure behind dc_array_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_array { + 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, +} +pub type dc_array_t = _dc_array; +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_key { + pub binary: *mut libc::c_void, + pub bytes: libc::c_int, + pub type_0: libc::c_int, + pub _m_heap_refcnt: libc::c_int, +} +pub type dc_key_t = _dc_key; +/* * + * @class dc_aheader_t + * Library-internal. Parse and create [Autocrypt-headers](https://autocrypt.org/en/latest/level1.html#the-autocrypt-header). + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_aheader { + pub addr: *mut libc::c_char, + pub public_key: *mut dc_key_t, + pub prefer_encrypt: libc::c_int, +} +pub type dc_aheader_t = _dc_aheader; +/* A complete hash table is an instance of the following structure. + * The internals of this structure are intended to be opaque -- client + * code should not attempt to access or modify the fields of this structure + * directly. Change this structure only by using the routines below. + * However, many of the "procedures" and "functions" for modifying and + * accessing this structure are really macros, so we can't really make + * this structure opaque. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_hash { + pub keyClass: libc::c_char, + pub copyKey: libc::c_char, + pub count: libc::c_int, + pub first: *mut dc_hashelem_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. + * + * Again, this structure is intended to be opaque, but it can't really + * be opaque because it is used by macros. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_hashelem { + pub next: *mut dc_hashelem_t, + pub prev: *mut dc_hashelem_t, + pub data: *mut libc::c_void, + pub pKey: *mut libc::c_void, + pub nKey: libc::c_int, +} +/* Forward declarations of structures. + */ +pub type dc_hash_t = _dc_hash; +/* prefer-encrypt states */ +/* * + * @class dc_apeerstate_t + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_apeerstate { + pub context: *mut dc_context_t, + pub addr: *mut libc::c_char, + pub last_seen: time_t, + pub last_seen_autocrypt: time_t, + pub prefer_encrypt: libc::c_int, + pub public_key: *mut dc_key_t, + pub public_key_fingerprint: *mut libc::c_char, + pub gossip_key: *mut dc_key_t, + pub gossip_timestamp: time_t, + pub gossip_key_fingerprint: *mut libc::c_char, + pub verified_key: *mut dc_key_t, + pub verified_key_fingerprint: *mut libc::c_char, + pub to_save: libc::c_int, + pub degrade_event: libc::c_int, +} +pub type dc_apeerstate_t = _dc_apeerstate; +/* library private: end-to-end-encryption */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_e2ee_helper { + pub encryption_successfull: libc::c_int, + pub cdata_to_free: *mut libc::c_void, + pub encrypted: libc::c_int, + pub signatures: *mut dc_hash_t, + pub gossipped_addr: *mut dc_hash_t, +} +// backups +// attachments of 25 mb brutto should work on the majority of providers +// (brutto examples: web.de=50, 1&1=40, t-online.de=32, gmail=25, posteo=50, yahoo=25, all-inkl=100). +// as an upper limit, we double the size; the core won't send messages larger than this +// to get the netto sizes, we substract 1 mb header-overhead and the base64-overhead. +// some defaults +pub type dc_e2ee_helper_t = _dc_e2ee_helper; +pub type dc_keyring_t = _dc_keyring; +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_keyring { + pub keys: *mut *mut dc_key_t, + pub count: libc::c_int, + pub allocated: libc::c_int, +} +#[no_mangle] +pub unsafe extern "C" fn dc_e2ee_encrypt( + mut context: *mut dc_context_t, + mut recipients_addr: *const clist, + mut force_unencrypted: libc::c_int, + mut e2ee_guaranteed: libc::c_int, + mut min_verified: libc::c_int, + mut do_gossip: libc::c_int, + 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 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 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); + if !helper.is_null() { + memset( + helper as *mut libc::c_void, + 0i32, + ::std::mem::size_of::() as libc::c_ulong, + ); + } + if !(context.is_null() + || (*context).magic != 0x11a11807i32 as libc::c_uint + || recipients_addr.is_null() + || in_out_message.is_null() + || !(*in_out_message).mm_parent.is_null() + || autocryptheader.is_null() + || keyring.is_null() + || sign_key.is_null() + || plain.is_null() + || helper.is_null()) + { + /* 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, + 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, + b"configured_addr\x00" as *const u8 as *const libc::c_char, + 0 as *const libc::c_char, + ); + if !(*autocryptheader).addr.is_null() { + if !(0 + == load_or_generate_self_public_key( + context, + (*autocryptheader).public_key, + (*autocryptheader).addr, + in_out_message, + )) + { + /*only for random-seed*/ + if (*autocryptheader).prefer_encrypt == 1i32 || 0 != e2ee_guaranteed { + do_encrypt = 1i32; + let mut iter1: *mut clistiter = 0 as *mut clistiter; + iter1 = (*recipients_addr).first; + while !iter1.is_null() { + let mut recipient_addr: *const libc::c_char = (if !iter1.is_null() { + (*iter1).data + } else { + 0 as *mut libc::c_void + }) + as *const libc::c_char; + let mut peerstate: *mut dc_apeerstate_t = dc_apeerstate_new(context); + let mut key_to_use: *mut dc_key_t = 0 as *mut dc_key_t; + if !(strcasecmp(recipient_addr, (*autocryptheader).addr) == 0i32) { + if 0 != dc_apeerstate_load_by_addr( + peerstate, + (*context).sql, + recipient_addr, + ) && { + key_to_use = dc_apeerstate_peek_key(peerstate, min_verified); + !key_to_use.is_null() + } && ((*peerstate).prefer_encrypt == 1i32 || 0 != e2ee_guaranteed) + { + dc_keyring_add(keyring, key_to_use); + dc_array_add_ptr(peerstates, peerstate as *mut libc::c_void); + } else { + dc_apeerstate_unref(peerstate); + do_encrypt = 0i32; + /* if we cannot encrypt to a single recipient, we cannot encrypt the message at all */ + break; + } + } + iter1 = if !iter1.is_null() { + (*iter1).next + } else { + 0 as *mut clistcell_s + } + } + } + if 0 != do_encrypt { + dc_keyring_add(keyring, (*autocryptheader).public_key); + if 0 == dc_key_load_self_private( + sign_key, + (*autocryptheader).addr, + (*context).sql, + ) { + do_encrypt = 0i32 + } + } + if 0 != force_unencrypted { + do_encrypt = 0i32 + } + imffields_unprotected = mailmime_find_mailimf_fields(in_out_message); + if !imffields_unprotected.is_null() { + /* encrypt message, if possible */ + if 0 != do_encrypt { + mailprivacy_prepare_mime(in_out_message); + let mut part_to_encrypt: *mut mailmime = + (*in_out_message).mm_data.mm_message.mm_msg_mime; + (*part_to_encrypt).mm_parent = 0 as *mut mailmime; + let mut imffields_encrypted: *mut mailimf_fields = + mailimf_fields_new_empty(); + /* mailmime_new_message_data() calls mailmime_fields_new_with_version() which would add the unwanted MIME-Version:-header */ + let mut message_to_encrypt: *mut mailmime = mailmime_new( + MAILMIME_MESSAGE as libc::c_int, + 0 as *const libc::c_char, + 0i32 as size_t, + mailmime_fields_new_empty(), + mailmime_get_content_message(), + 0 as *mut mailmime_data, + 0 as *mut mailmime_data, + 0 as *mut mailmime_data, + 0 as *mut clist, + imffields_encrypted, + part_to_encrypt, + ); + if 0 != do_gossip { + let mut iCnt: libc::c_int = dc_array_get_cnt(peerstates) as libc::c_int; + if iCnt > 1i32 { + let mut i: libc::c_int = 0i32; + while i < iCnt { + let mut p: *mut libc::c_char = + dc_apeerstate_render_gossip_header( + dc_array_get_ptr(peerstates, i as size_t) + as *mut dc_apeerstate_t, + min_verified, + ); + if !p.is_null() { + mailimf_fields_add( + imffields_encrypted, + mailimf_field_new_custom( + strdup( + b"Autocrypt-Gossip\x00" as *const u8 + as *const libc::c_char, + ), + p, + ), + ); + } + i += 1 + } + } + } + /* memoryhole headers */ + let mut cur: *mut clistiter = (*(*imffields_unprotected).fld_list).first; + while !cur.is_null() { + let mut move_to_encrypted: libc::c_int = 0i32; + let mut field: *mut mailimf_field = (if !cur.is_null() { + (*cur).data + } else { + 0 as *mut libc::c_void + }) + as *mut mailimf_field; + if !field.is_null() { + if (*field).fld_type == MAILIMF_FIELD_SUBJECT as libc::c_int { + move_to_encrypted = 1i32 + } else if (*field).fld_type + == MAILIMF_FIELD_OPTIONAL_FIELD as libc::c_int + { + let mut opt_field: *mut mailimf_optional_field = + (*field).fld_data.fld_optional_field; + if !opt_field.is_null() && !(*opt_field).fld_name.is_null() { + if strncmp( + (*opt_field).fld_name, + b"Secure-Join\x00" as *const u8 as *const libc::c_char, + 11i32 as libc::c_ulong, + ) == 0i32 + || strncmp( + (*opt_field).fld_name, + b"Chat-\x00" as *const u8 as *const libc::c_char, + 5i32 as libc::c_ulong, + ) == 0i32 + && strcmp( + (*opt_field).fld_name, + b"Chat-Version\x00" as *const u8 + as *const libc::c_char, + ) != 0i32 + { + move_to_encrypted = 1i32 + } + } + } + } + if 0 != move_to_encrypted { + mailimf_fields_add(imffields_encrypted, field); + cur = clist_delete((*imffields_unprotected).fld_list, cur) + } else { + cur = if !cur.is_null() { + (*cur).next + } else { + 0 as *mut clistcell_s + } + } + } + let mut subject: *mut mailimf_subject = mailimf_subject_new(dc_strdup( + b"...\x00" as *const u8 as *const libc::c_char, + )); + mailimf_fields_add( + imffields_unprotected, + mailimf_field_new( + MAILIMF_FIELD_SUBJECT as libc::c_int, + 0 as *mut mailimf_return, + 0 as *mut mailimf_orig_date, + 0 as *mut mailimf_from, + 0 as *mut mailimf_sender, + 0 as *mut mailimf_to, + 0 as *mut mailimf_cc, + 0 as *mut mailimf_bcc, + 0 as *mut mailimf_message_id, + 0 as *mut mailimf_orig_date, + 0 as *mut mailimf_from, + 0 as *mut mailimf_sender, + 0 as *mut mailimf_reply_to, + 0 as *mut mailimf_to, + 0 as *mut mailimf_cc, + 0 as *mut mailimf_bcc, + 0 as *mut mailimf_message_id, + 0 as *mut mailimf_in_reply_to, + 0 as *mut mailimf_references, + subject, + 0 as *mut mailimf_comments, + 0 as *mut mailimf_keywords, + 0 as *mut mailimf_optional_field, + ), + ); + clist_insert_after( + (*(*part_to_encrypt).mm_content_type).ct_parameters, + (*(*(*part_to_encrypt).mm_content_type).ct_parameters).last, + mailmime_param_new_with_data( + b"protected-headers\x00" as *const u8 as *const libc::c_char + as *mut libc::c_char, + b"v1\x00" as *const u8 as *const libc::c_char as *mut libc::c_char, + ) as *mut libc::c_void, + ); + mailmime_write_mem(plain, &mut col, message_to_encrypt); + if (*plain).str_0.is_null() || (*plain).len <= 0i32 as libc::c_ulong { + current_block = 14181132614457621749; + } else if 0 + == dc_pgp_pk_encrypt( + context, + (*plain).str_0 as *const libc::c_void, + (*plain).len, + keyring, + sign_key, + 1i32, + &mut ctext as *mut *mut libc::c_char as *mut *mut libc::c_void, + &mut ctext_bytes, + ) + { + /*use_armor*/ + current_block = 14181132614457621749; + } else { + (*helper).cdata_to_free = ctext as *mut libc::c_void; + //char* t2=dc_null_terminate(ctext,ctext_bytes);printf("ENCRYPTED:\n%s\n",t2);free(t2); // DEBUG OUTPUT + /* create MIME-structure that will contain the encrypted text */ + let mut encrypted_part: *mut mailmime = new_data_part( + 0 as *mut libc::c_void, + 0i32 as size_t, + b"multipart/encrypted\x00" as *const u8 as *const libc::c_char + as *mut libc::c_char, + -1i32, + ); + let mut content: *mut mailmime_content = + (*encrypted_part).mm_content_type; + clist_insert_after( + (*content).ct_parameters, + (*(*content).ct_parameters).last, + mailmime_param_new_with_data( + b"protocol\x00" as *const u8 as *const libc::c_char + as *mut libc::c_char, + b"application/pgp-encrypted\x00" as *const u8 + as *const libc::c_char + as *mut libc::c_char, + ) as *mut libc::c_void, + ); + static mut version_content: [libc::c_char; 13] = + [86, 101, 114, 115, 105, 111, 110, 58, 32, 49, 13, 10, 0]; + let mut version_mime: *mut mailmime = new_data_part( + version_content.as_mut_ptr() as *mut libc::c_void, + strlen(version_content.as_mut_ptr()), + b"application/pgp-encrypted\x00" as *const u8 as *const libc::c_char + as *mut libc::c_char, + MAILMIME_MECHANISM_7BIT as libc::c_int, + ); + mailmime_smart_add_part(encrypted_part, version_mime); + let mut ctext_part: *mut mailmime = new_data_part( + ctext as *mut libc::c_void, + ctext_bytes, + b"application/octet-stream\x00" as *const u8 as *const libc::c_char + as *mut libc::c_char, + MAILMIME_MECHANISM_7BIT as libc::c_int, + ); + mailmime_smart_add_part(encrypted_part, ctext_part); + (*in_out_message).mm_data.mm_message.mm_msg_mime = encrypted_part; + (*encrypted_part).mm_parent = in_out_message; + mailmime_free(message_to_encrypt); + (*helper).encryption_successfull = 1i32; + current_block = 13824533195664196414; + } + } else { + current_block = 13824533195664196414; + } + match current_block { + 14181132614457621749 => {} + _ => { + p_0 = dc_aheader_render(autocryptheader); + if !p_0.is_null() { + mailimf_fields_add( + imffields_unprotected, + mailimf_field_new_custom( + strdup( + b"Autocrypt\x00" as *const u8 as *const libc::c_char, + ), + p_0, + ), + ); + } + } + } + } + } + } + } + dc_aheader_unref(autocryptheader); + dc_keyring_unref(keyring); + dc_key_unref(sign_key); + if !plain.is_null() { + mmap_string_free(plain); + } + let mut i_0: libc::c_int = + dc_array_get_cnt(peerstates).wrapping_sub(1i32 as libc::c_ulong) as libc::c_int; + while i_0 >= 0i32 { + dc_apeerstate_unref(dc_array_get_ptr(peerstates, i_0 as size_t) as *mut dc_apeerstate_t); + i_0 -= 1 + } + dc_array_unref(peerstates); +} +/* ****************************************************************************** + * Tools + ******************************************************************************/ +unsafe extern "C" fn new_data_part( + mut data: *mut libc::c_void, + mut data_bytes: size_t, + mut default_content_type: *mut libc::c_char, + mut default_encoding: libc::c_int, +) -> *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; + //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; + encoding = 0 as *mut mailmime_mechanism; + if default_content_type.is_null() { + content_type_str = + b"application/octet-stream\x00" as *const u8 as *const libc::c_char as *mut libc::c_char + } else { + content_type_str = default_content_type + } + content = mailmime_content_new_with_str(content_type_str); + if content.is_null() { + current_block = 16266721588079097885; + } 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; + composite = (*(*content).ct_type).tp_data.tp_composite_type; + match (*composite).ct_type { + 1 => { + if strcasecmp( + (*content).ct_subtype, + b"rfc822\x00" as *const u8 as *const libc::c_char, + ) == 0i32 + { + do_encoding = 0i32 + } + } + 2 => do_encoding = 0i32, + _ => {} + } + } + if 0 != do_encoding { + if default_encoding == -1i32 { + encoding_type = MAILMIME_MECHANISM_BASE64 as libc::c_int + } else { + encoding_type = default_encoding + } + encoding = mailmime_mechanism_new(encoding_type, 0 as *mut libc::c_char); + if encoding.is_null() { + current_block = 16266721588079097885; + } else { + current_block = 11057878835866523405; + } + } else { + current_block = 11057878835866523405; + } + match current_block { + 16266721588079097885 => {} + _ => { + mime_fields = mailmime_fields_new_with_data( + encoding, + 0 as *mut libc::c_char, + 0 as *mut libc::c_char, + 0 as *mut mailmime_disposition, + 0 as *mut mailmime_language, + ); + if mime_fields.is_null() { + current_block = 16266721588079097885; + } else { + mime = mailmime_new_empty(content, mime_fields); + if mime.is_null() { + mailmime_fields_free(mime_fields); + mailmime_content_free(content); + } else { + if !data.is_null() + && data_bytes > 0i32 as libc::c_ulong + && (*mime).mm_type == MAILMIME_SINGLE as libc::c_int + { + mailmime_set_body_text(mime, data as *mut libc::c_char, data_bytes); + } + return mime; + } + current_block = 13668317689588454213; + } + } + } + } + match current_block { + 16266721588079097885 => { + if !encoding.is_null() { + mailmime_mechanism_free(encoding); + } + if !content.is_null() { + mailmime_content_free(content); + } + } + _ => {} + } + return 0 as *mut mailmime; +} +/* ****************************************************************************** + * Generate Keypairs + ******************************************************************************/ +unsafe extern "C" fn load_or_generate_self_public_key( + mut context: *mut dc_context_t, + mut public_key: *mut dc_key_t, + mut self_addr: *const libc::c_char, + mut random_data_mime: *mut mailmime, +) -> libc::c_int { + 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 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) { + /* 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]>() as libc::c_ulong, + ); + if !random_data_mime.is_null() { + let mut random_data_mmap: *mut MMAPString = 0 as *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; + } + } else { + current_block = 26972500619410423; + } + match current_block { + 10496152961502316708 => {} + _ => { + let mut private_key: *mut dc_key_t = dc_key_new(); + let mut start: clock_t = clock(); + dc_log_info( + context, + 0i32, + b"Generating keypair with %i bits, e=%i ...\x00" as *const u8 + as *const libc::c_char, + 2048i32, + 65537i32, + ); + key_created = + dc_pgp_create_keypair(context, self_addr, public_key, private_key); + if 0 == key_created { + dc_log_warning( + context, + 0i32, + b"Cannot create keypair.\x00" as *const u8 as *const libc::c_char, + ); + current_block = 10496152961502316708; + } else if 0 == dc_pgp_is_valid_key(context, public_key) + || 0 == dc_pgp_is_valid_key(context, private_key) + { + dc_log_warning( + context, + 0i32, + b"Generated keys are not valid.\x00" as *const u8 + as *const libc::c_char, + ); + current_block = 10496152961502316708; + } else if 0 + == dc_key_save_self_keypair( + public_key, + private_key, + self_addr, + 1i32, + (*context).sql, + ) + { + /*set default*/ + dc_log_warning( + context, + 0i32, + b"Cannot save keypair.\x00" as *const u8 as *const libc::c_char, + ); + current_block = 10496152961502316708; + } else { + dc_log_info( + context, + 0i32, + b"Keypair generated in %.3f s.\x00" as *const u8 + as *const libc::c_char, + clock().wrapping_sub(start) as libc::c_double + / 1000000i32 as libc::c_double, + ); + dc_key_unref(private_key); + current_block = 1118134448028020070; + } + } + } + } + } else { + current_block = 1118134448028020070; + } + match current_block { + 10496152961502316708 => {} + _ => success = 1i32, + } + } + if 0 != key_creation_here { + s_in_key_creation = 0i32 + } + return success; +} +/* returns 1 if sth. was decrypted, 0 in other cases */ +#[no_mangle] +pub unsafe extern "C" fn dc_e2ee_decrypt( + mut context: *mut dc_context_t, + mut in_out_message: *mut mailmime, + mut helper: *mut dc_e2ee_helper_t, +) { + let mut iterations: libc::c_int = 0; + /* 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*/ + let mut imffields: *mut mailimf_fields = mailmime_find_mailimf_fields(in_out_message); + let mut autocryptheader: *mut dc_aheader_t = 0 as *mut dc_aheader_t; + let mut message_time: time_t = 0i32 as time_t; + let mut peerstate: *mut dc_apeerstate_t = dc_apeerstate_new(context); + let mut from: *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 private_keyring: *mut dc_keyring_t = dc_keyring_new(); + let mut public_keyring_for_validate: *mut dc_keyring_t = dc_keyring_new(); + let mut gossip_headers: *mut mailimf_fields = 0 as *mut mailimf_fields; + if !helper.is_null() { + memset( + helper as *mut libc::c_void, + 0i32, + ::std::mem::size_of::() as libc::c_ulong, + ); + } + if !(context.is_null() + || (*context).magic != 0x11a11807i32 as libc::c_uint + || 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); + if !field.is_null() && !(*field).fld_data.fld_from.is_null() { + from = mailimf_find_first_addr((*(*field).fld_data.fld_from).frm_mb_list) + } + field = mailimf_find_field(imffields, MAILIMF_FIELD_ORIG_DATE as libc::c_int); + if !field.is_null() && !(*field).fld_data.fld_orig_date.is_null() { + let mut orig_date: *mut mailimf_orig_date = (*field).fld_data.fld_orig_date; + if !orig_date.is_null() { + message_time = dc_timestamp_from_date((*orig_date).dt_date_time); + if message_time != -1i32 as libc::c_long + && message_time > time(0 as *mut time_t) + { + message_time = time(0 as *mut time_t) + } + } + } + } + autocryptheader = dc_aheader_new_from_imffields(from, imffields); + if !autocryptheader.is_null() { + if 0 == dc_pgp_is_valid_key(context, (*autocryptheader).public_key) { + dc_aheader_unref(autocryptheader); + autocryptheader = 0 as *mut dc_aheader_t + } + } + if message_time > 0i32 as libc::c_long && !from.is_null() { + if 0 != dc_apeerstate_load_by_addr(peerstate, (*context).sql, from) { + if !autocryptheader.is_null() { + dc_apeerstate_apply_header(peerstate, autocryptheader, message_time); + dc_apeerstate_save_to_db(peerstate, (*context).sql, 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); + } + } else if !autocryptheader.is_null() { + dc_apeerstate_init_from_header(peerstate, autocryptheader, message_time); + dc_apeerstate_save_to_db(peerstate, (*context).sql, 1i32); + } + } + /* load private key for decryption */ + 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, + ); + if !self_addr.is_null() { + if !(0 + == dc_keyring_load_self_private_for_decrypting( + private_keyring, + self_addr, + (*context).sql, + )) + { + if (*peerstate).last_seen == 0i32 as libc::c_long { + dc_apeerstate_load_by_addr(peerstate, (*context).sql, from); + } + if 0 != (*peerstate).degrade_event { + dc_handle_degrade_event(context, peerstate); + } + dc_keyring_add(public_keyring_for_validate, (*peerstate).gossip_key); + dc_keyring_add(public_keyring_for_validate, (*peerstate).public_key); + (*helper).signatures = + malloc(::std::mem::size_of::() as libc::c_ulong) as *mut dc_hash_t; + dc_hash_init((*helper).signatures, 3i32, 1i32); + iterations = 0i32; + while iterations < 10i32 { + let mut has_unencrypted_parts: libc::c_int = 0i32; + if 0 == decrypt_recursive( + context, + in_out_message, + private_keyring, + public_keyring_for_validate, + (*helper).signatures, + &mut gossip_headers, + &mut has_unencrypted_parts, + ) { + break; + } + if iterations == 0i32 && 0 == has_unencrypted_parts { + (*helper).encrypted = 1i32 + } + iterations += 1 + } + if !gossip_headers.is_null() { + (*helper).gossipped_addr = + update_gossip_peerstates(context, message_time, imffields, gossip_headers) + } + } + } + } + //mailmime_print(in_out_message); + if !gossip_headers.is_null() { + mailimf_fields_free(gossip_headers); + } + dc_aheader_unref(autocryptheader); + dc_apeerstate_unref(peerstate); + dc_keyring_unref(private_keyring); + dc_keyring_unref(public_keyring_for_validate); + free(from as *mut libc::c_void); + free(self_addr as *mut libc::c_void); +} +unsafe extern "C" fn update_gossip_peerstates( + mut context: *mut 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 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; + while !cur1.is_null() { + let mut field: *mut mailimf_field = (if !cur1.is_null() { + (*cur1).data + } else { + 0 as *mut libc::c_void + }) as *mut mailimf_field; + if (*field).fld_type == MAILIMF_FIELD_OPTIONAL_FIELD as libc::c_int { + let mut optional_field: *const mailimf_optional_field = + (*field).fld_data.fld_optional_field; + if !optional_field.is_null() + && !(*optional_field).fld_name.is_null() + && strcasecmp( + (*optional_field).fld_name, + b"Autocrypt-Gossip\x00" as *const u8 as *const libc::c_char, + ) == 0i32 + { + let mut gossip_header: *mut dc_aheader_t = dc_aheader_new(); + if 0 != dc_aheader_set_from_string(gossip_header, (*optional_field).fld_value) + && 0 != dc_pgp_is_valid_key(context, (*gossip_header).public_key) + { + if recipients.is_null() { + recipients = mailimf_get_recipients(imffields) + } + if !dc_hash_find( + recipients, + (*gossip_header).addr as *const libc::c_void, + strlen((*gossip_header).addr) as libc::c_int, + ) + .is_null() + { + let mut peerstate: *mut dc_apeerstate_t = dc_apeerstate_new(context); + if 0 == dc_apeerstate_load_by_addr( + peerstate, + (*context).sql, + (*gossip_header).addr, + ) { + dc_apeerstate_init_from_gossip(peerstate, gossip_header, message_time); + dc_apeerstate_save_to_db(peerstate, (*context).sql, 1i32); + } else { + dc_apeerstate_apply_gossip(peerstate, gossip_header, message_time); + dc_apeerstate_save_to_db(peerstate, (*context).sql, 0i32); + } + if 0 != (*peerstate).degrade_event { + dc_handle_degrade_event(context, peerstate); + } + dc_apeerstate_unref(peerstate); + if gossipped_addr.is_null() { + gossipped_addr = + malloc(::std::mem::size_of::() as libc::c_ulong) + as *mut dc_hash_t; + dc_hash_init(gossipped_addr, 3i32, 1i32); + } + dc_hash_insert( + gossipped_addr, + (*gossip_header).addr as *const libc::c_void, + strlen((*gossip_header).addr) as libc::c_int, + 1i32 as *mut libc::c_void, + ); + } else { + dc_log_info( + context, + 0i32, + b"Ignoring gossipped \"%s\" as the address is not in To/Cc list.\x00" + as *const u8 as *const libc::c_char, + (*gossip_header).addr, + ); + } + } + dc_aheader_unref(gossip_header); + } + } + cur1 = if !cur1.is_null() { + (*cur1).next + } else { + 0 as *mut clistcell_s + } + } + if !recipients.is_null() { + dc_hash_clear(recipients); + free(recipients as *mut libc::c_void); + } + return gossipped_addr; +} +unsafe extern "C" fn decrypt_recursive( + mut context: *mut 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_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() { + return 0i32; + } + if (*mime).mm_type == MAILMIME_MULTIPLE as libc::c_int { + ct = (*mime).mm_content_type; + if !ct.is_null() + && !(*ct).ct_subtype.is_null() + && strcmp( + (*ct).ct_subtype, + b"encrypted\x00" as *const u8 as *const libc::c_char, + ) == 0i32 + { + cur = (*(*mime).mm_data.mm_multipart.mm_mp_list).first; + while !cur.is_null() { + let mut decrypted_mime: *mut mailmime = 0 as *mut mailmime; + if 0 != decrypt_part( + context, + (if !cur.is_null() { + (*cur).data + } else { + 0 as *mut libc::c_void + }) as *mut mailmime, + private_keyring, + public_keyring_for_validate, + ret_valid_signatures, + &mut decrypted_mime, + ) { + if (*ret_gossip_headers).is_null() && (*ret_valid_signatures).count > 0i32 { + let mut dummy: size_t = 0i32 as size_t; + let mut test: *mut mailimf_fields = 0 as *mut mailimf_fields; + if mailimf_envelope_and_optional_fields_parse( + (*decrypted_mime).mm_mime_start, + (*decrypted_mime).mm_length, + &mut dummy, + &mut test, + ) == MAILIMF_NO_ERROR as libc::c_int + && !test.is_null() + { + *ret_gossip_headers = test + } + } + mailmime_substitute(mime, decrypted_mime); + mailmime_free(mime); + return 1i32; + } + cur = if !cur.is_null() { + (*cur).next + } else { + 0 as *mut clistcell_s + } + } + *ret_has_unencrypted_parts = 1i32 + } else { + cur = (*(*mime).mm_data.mm_multipart.mm_mp_list).first; + while !cur.is_null() { + if 0 != decrypt_recursive( + context, + (if !cur.is_null() { + (*cur).data + } else { + 0 as *mut libc::c_void + }) as *mut mailmime, + private_keyring, + public_keyring_for_validate, + ret_valid_signatures, + ret_gossip_headers, + ret_has_unencrypted_parts, + ) { + return 1i32; + } + cur = if !cur.is_null() { + (*cur).next + } else { + 0 as *mut clistcell_s + } + } + } + } else if (*mime).mm_type == MAILMIME_MESSAGE as libc::c_int { + if 0 != decrypt_recursive( + context, + (*mime).mm_data.mm_message.mm_msg_mime, + private_keyring, + public_keyring_for_validate, + ret_valid_signatures, + ret_gossip_headers, + ret_has_unencrypted_parts, + ) { + return 1i32; + } + } else { + *ret_has_unencrypted_parts = 1i32 + } + return 0i32; +} +unsafe extern "C" fn decrypt_part( + mut context: *mut 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 current_block: u64; + let mut mime_data: *mut mailmime_data = 0 as *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; + /* must not be free()'d */ + let mut decoded_data: *const libc::c_char = 0 as *const libc::c_char; + let mut decoded_data_bytes: size_t = 0i32 as size_t; + let mut plain_buf: *mut libc::c_void = 0 as *mut libc::c_void; + let mut plain_bytes: size_t = 0i32 as size_t; + let mut sth_decrypted: libc::c_int = 0i32; + *ret_decrypted_mime = 0 as *mut mailmime; + mime_data = (*mime).mm_data.mm_single; + /* MAILMIME_DATA_FILE indicates, the data is in a file; AFAIK this is not used on parsing */ + if !((*mime_data).dt_type != MAILMIME_DATA_TEXT as libc::c_int + || (*mime_data).dt_data.dt_text.dt_data.is_null() + || (*mime_data).dt_data.dt_text.dt_length <= 0i32 as libc::c_ulong) + { + if !(*mime).mm_mime_fields.is_null() { + let mut cur: *mut clistiter = 0 as *mut clistiter; + cur = (*(*(*mime).mm_mime_fields).fld_list).first; + while !cur.is_null() { + let mut field: *mut mailmime_field = (if !cur.is_null() { + (*cur).data + } else { + 0 as *mut libc::c_void + }) as *mut mailmime_field; + if !field.is_null() { + if (*field).fld_type == MAILMIME_FIELD_TRANSFER_ENCODING as libc::c_int + && !(*field).fld_data.fld_encoding.is_null() + { + mime_transfer_encoding = (*(*field).fld_data.fld_encoding).enc_type + } + } + cur = if !cur.is_null() { + (*cur).next + } else { + 0 as *mut clistcell_s + } + } + } + /* regard `Content-Transfer-Encoding:` */ + if mime_transfer_encoding == MAILMIME_MECHANISM_7BIT as libc::c_int + || mime_transfer_encoding == MAILMIME_MECHANISM_8BIT as libc::c_int + || mime_transfer_encoding == MAILMIME_MECHANISM_BINARY as libc::c_int + { + decoded_data = (*mime_data).dt_data.dt_text.dt_data; + decoded_data_bytes = (*mime_data).dt_data.dt_text.dt_length; + if decoded_data.is_null() || decoded_data_bytes <= 0i32 as libc::c_ulong { + /* no error - but no data */ + current_block = 2554982661806928548; + } else { + current_block = 4488286894823169796; + } + } else { + let mut r: libc::c_int = 0; + let mut current_index: size_t = 0i32 as size_t; + r = mailmime_part_parse( + (*mime_data).dt_data.dt_text.dt_data, + (*mime_data).dt_data.dt_text.dt_length, + &mut current_index, + mime_transfer_encoding, + &mut transfer_decoding_buffer, + &mut decoded_data_bytes, + ); + if r != MAILIMF_NO_ERROR as libc::c_int + || transfer_decoding_buffer.is_null() + || decoded_data_bytes <= 0i32 as libc::c_ulong + { + current_block = 2554982661806928548; + } else { + decoded_data = transfer_decoding_buffer; + current_block = 4488286894823169796; + } + } + match current_block { + 2554982661806928548 => {} + _ => { + /* encrypted, decoded data in decoded_data now ... */ + if !(0 == has_decrypted_pgp_armor(decoded_data, decoded_data_bytes as libc::c_int)) + { + add_signatures = if (*ret_valid_signatures).count <= 0i32 { + ret_valid_signatures + } else { + 0 as *mut dc_hash_t + }; + /*if we already have fingerprints, do not add more; this ensures, only the fingerprints from the outer-most part are collected */ + if !(0 + == dc_pgp_pk_decrypt( + context, + decoded_data as *const libc::c_void, + decoded_data_bytes, + private_keyring, + public_keyring_for_validate, + 1i32, + &mut plain_buf, + &mut plain_bytes, + add_signatures, + ) + || plain_buf.is_null() + || plain_bytes <= 0i32 as libc::c_ulong) + { + //{char* t1=dc_null_terminate(plain_buf,plain_bytes);printf("\n**********\n%s\n**********\n",t1);free(t1);} + let mut index: size_t = 0i32 as size_t; + let mut decrypted_mime: *mut mailmime = 0 as *mut mailmime; + if mailmime_parse( + plain_buf as *const libc::c_char, + plain_bytes, + &mut index, + &mut decrypted_mime, + ) != MAIL_NO_ERROR as libc::c_int + || decrypted_mime.is_null() + { + if !decrypted_mime.is_null() { + mailmime_free(decrypted_mime); + } + } else { + *ret_decrypted_mime = decrypted_mime; + sth_decrypted = 1i32 + } + } + } + } + } + } + //mailmime_substitute(mime, new_mime); + //s. mailprivacy_gnupg.c::pgp_decrypt() + if !transfer_decoding_buffer.is_null() { + mmap_string_unref(transfer_decoding_buffer); + } + return sth_decrypted; +} +/* ****************************************************************************** + * Decrypt + ******************************************************************************/ +unsafe extern "C" fn has_decrypted_pgp_armor( + mut str__: *const libc::c_char, + mut str_bytes: libc::c_int, +) -> libc::c_int { + let mut str_end: *const libc::c_uchar = + (str__ as *const libc::c_uchar).offset(str_bytes as isize); + let mut p: *const libc::c_uchar = str__ as *const libc::c_uchar; + while p < str_end { + if *p as libc::c_int > ' ' as i32 { + break; + } + p = p.offset(1isize); + str_bytes -= 1 + } + if str_bytes > 27i32 + && strncmp( + p as *const libc::c_char, + b"-----BEGIN PGP MESSAGE-----\x00" as *const u8 as *const libc::c_char, + 27i32 as libc::c_ulong, + ) == 0i32 + { + return 1i32; + } + return 0i32; +} +/* * + * Check if a MIME structure contains a multipart/report part. + * + * As reports are often unencrypted, we do not reset the Autocrypt header in + * this case. + * + * However, Delta Chat itself has no problem with encrypted multipart/report + * parts and MUAs should be encouraged to encrpyt multipart/reports as well so + * that we could use the normal Autocrypt processing. + * + * @private + * @param mime The mime struture to check + * @return 1=multipart/report found in MIME, 0=no multipart/report found + */ +unsafe extern "C" 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 + == MAILMIME_TYPE_COMPOSITE_TYPE as libc::c_int + && (*(*(*(*mime).mm_content_type).ct_type) + .tp_data + .tp_composite_type) + .ct_type + == MAILMIME_COMPOSITE_TYPE_MULTIPART as libc::c_int + && strcmp( + (*(*mime).mm_content_type).ct_subtype, + b"report\x00" as *const u8 as *const libc::c_char, + ) == 0i32 + { + return 1i32; + } + let mut cur: *mut clistiter = 0 as *mut clistiter; + cur = (*(*mime).mm_data.mm_multipart.mm_mp_list).first; + while !cur.is_null() { + if 0 != contains_report( + (if !cur.is_null() { + (*cur).data + } else { + 0 as *mut libc::c_void + }) as *mut mailmime, + ) { + return 1i32; + } + cur = if !cur.is_null() { + (*cur).next + } else { + 0 as *mut clistcell_s + } + } + } else if (*mime).mm_type == MAILMIME_MESSAGE as libc::c_int { + if 0 != contains_report((*mime).mm_data.mm_message.mm_msg_mime) { + return 1i32; + } + } + return 0i32; +} +/* frees data referenced by "mailmime" but not freed by mailmime_free(). After calling this function, in_out_message cannot be used any longer! */ +#[no_mangle] +pub unsafe extern "C" fn dc_e2ee_thanks(mut helper: *mut dc_e2ee_helper_t) { + if helper.is_null() { + return; + } + free((*helper).cdata_to_free); + (*helper).cdata_to_free = 0 as *mut libc::c_void; + if !(*helper).gossipped_addr.is_null() { + dc_hash_clear((*helper).gossipped_addr); + free((*helper).gossipped_addr as *mut libc::c_void); + (*helper).gossipped_addr = 0 as *mut dc_hash_t + } + if !(*helper).signatures.is_null() { + dc_hash_clear((*helper).signatures); + free((*helper).signatures as *mut libc::c_void); + (*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 */ +#[no_mangle] +pub unsafe extern "C" fn dc_ensure_secret_key_exists( + mut context: *mut 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()) + { + 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, + ); + if self_addr.is_null() { + dc_log_warning( + context, + 0i32, + b"Cannot ensure secret key if context is not configured.\x00" as *const u8 + as *const libc::c_char, + ); + } else if !(0 + == load_or_generate_self_public_key(context, public_key, self_addr, 0 as *mut mailmime)) + { + /*no random text data for seeding available*/ + success = 1i32 + } + } + dc_key_unref(public_key); + free(self_addr as *mut libc::c_void); + return success; +} diff --git a/src/dc_hash.rs b/src/dc_hash.rs new file mode 100644 index 000000000..18a6310b9 --- /dev/null +++ b/src/dc_hash.rs @@ -0,0 +1,916 @@ +use libc; +extern "C" { + #[no_mangle] + fn __assert_rtn( + _: *const libc::c_char, + _: *const libc::c_char, + _: libc::c_int, + _: *const libc::c_char, + ) -> !; + #[no_mangle] + fn malloc(_: libc::c_ulong) -> *mut libc::c_void; + #[no_mangle] + fn free(_: *mut libc::c_void); + #[no_mangle] + fn memcmp(_: *const libc::c_void, _: *const libc::c_void, _: libc::c_ulong) -> libc::c_int; + #[no_mangle] + fn memcpy(_: *mut libc::c_void, _: *const libc::c_void, _: libc::c_ulong) -> *mut libc::c_void; + #[no_mangle] + fn memset(_: *mut libc::c_void, _: libc::c_int, _: libc::c_ulong) -> *mut libc::c_void; + #[no_mangle] + fn strlen(_: *const libc::c_char) -> libc::c_ulong; +} +pub type uintptr_t = libc::c_ulong; +/* A complete hash table is an instance of the following structure. + * The internals of this structure are intended to be opaque -- client + * code should not attempt to access or modify the fields of this structure + * directly. Change this structure only by using the routines below. + * However, many of the "procedures" and "functions" for modifying and + * accessing this structure are really macros, so we can't really make + * this structure opaque. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_hash { + pub keyClass: libc::c_char, + pub copyKey: libc::c_char, + pub count: libc::c_int, + pub first: *mut dc_hashelem_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. + * + * Again, this structure is intended to be opaque, but it can't really + * be opaque because it is used by macros. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_hashelem { + pub next: *mut dc_hashelem_t, + pub prev: *mut dc_hashelem_t, + pub data: *mut libc::c_void, + pub pKey: *mut libc::c_void, + pub nKey: libc::c_int, +} +/* Forward declarations of structures. + */ +pub type dc_hash_t = _dc_hash; +/* + * There are 4 different modes of operation for a hash table: + * + * DC_HASH_INT nKey is used as the key and pKey is ignored. + * + * DC_HASH_POINTER pKey is used as the key and nKey is ignored. + * + * DC_HASH_STRING pKey points to a string that is nKey bytes long + * (including the null-terminator, if any). Case + * is ignored in comparisons. + * + * DC_HASH_BINARY pKey points to binary data nKey bytes long. + * memcmp() is used to compare keys. + * + * A copy of the key is made for DC_HASH_STRING and DC_HASH_BINARY + * if the copyKey parameter to dc_hash_init() is 1. + */ +/* + * Just to make the last parameter of dc_hash_init() more readable. + */ +/* + * Access routines. To delete an element, insert a NULL pointer. + */ +#[no_mangle] +pub unsafe extern "C" fn dc_hash_init( + mut pNew: *mut dc_hash_t, + mut keyClass: libc::c_int, + mut copyKey: libc::c_int, +) { + if 0 != pNew.is_null() as libc::c_int as libc::c_long { + __assert_rtn( + (*::std::mem::transmute::<&[u8; 13], &[libc::c_char; 13]>(b"dc_hash_init\x00")) + .as_ptr(), + b"../src/dc_hash.c\x00" as *const u8 as *const libc::c_char, + 93i32, + b"pNew!=0\x00" as *const u8 as *const libc::c_char, + ); + } else { + }; + if 0 != !(keyClass >= 1i32 && keyClass <= 4i32) as libc::c_int as libc::c_long { + __assert_rtn( + (*::std::mem::transmute::<&[u8; 13], &[libc::c_char; 13]>(b"dc_hash_init\x00")) + .as_ptr(), + b"../src/dc_hash.c\x00" as *const u8 as *const libc::c_char, + 94i32, + b"keyClass>=DC_HASH_INT && keyClass<=DC_HASH_BINARY\x00" as *const u8 + as *const libc::c_char, + ); + } else { + }; + (*pNew).keyClass = keyClass as libc::c_char; + if keyClass == 2i32 || keyClass == 1i32 { + copyKey = 0i32 + } + (*pNew).copyKey = copyKey as libc::c_char; + (*pNew).first = 0 as *mut dc_hashelem_t; + (*pNew).count = 0i32; + (*pNew).htsize = 0i32; + (*pNew).ht = 0 as *mut _ht; +} +#[no_mangle] +pub unsafe extern "C" fn dc_hash_insert( + mut pH: *mut dc_hash_t, + mut pKey: *const libc::c_void, + mut nKey: libc::c_int, + mut data: *mut libc::c_void, +) -> *mut libc::c_void { + /* Raw hash value of the key */ + let mut hraw: libc::c_int = 0; + /* the hash of the key modulo hash table size */ + let mut h: libc::c_int = 0; + /* Used to loop thru the element list */ + let mut elem: *mut dc_hashelem_t = 0 as *mut dc_hashelem_t; + /* New element added to the pH */ + let mut new_elem: *mut dc_hashelem_t = 0 as *mut dc_hashelem_t; + /* The hash function */ + let mut xHash: Option< + unsafe extern "C" fn(_: *const libc::c_void, _: libc::c_int) -> libc::c_int, + > = None; + 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")) + .as_ptr(), + b"../src/dc_hash.c\x00" as *const u8 as *const libc::c_char, + 429i32, + b"pH!=0\x00" as *const u8 as *const libc::c_char, + ); + } else { + }; + xHash = hashFunction((*pH).keyClass as libc::c_int); + if 0 != xHash.is_none() as libc::c_int as libc::c_long { + __assert_rtn( + (*::std::mem::transmute::<&[u8; 15], &[libc::c_char; 15]>(b"dc_hash_insert\x00")) + .as_ptr(), + b"../src/dc_hash.c\x00" as *const u8 as *const libc::c_char, + 431i32, + b"xHash!=0\x00" as *const u8 as *const libc::c_char, + ); + } else { + }; + hraw = xHash.expect("non-null function pointer")(pKey, nKey); + if 0 != !((*pH).htsize & (*pH).htsize - 1i32 == 0i32) as libc::c_int as libc::c_long { + __assert_rtn( + (*::std::mem::transmute::<&[u8; 15], &[libc::c_char; 15]>(b"dc_hash_insert\x00")) + .as_ptr(), + b"../src/dc_hash.c\x00" as *const u8 as *const libc::c_char, + 433i32, + b"(pH->htsize & (pH->htsize-1))==0\x00" as *const u8 as *const libc::c_char, + ); + } else { + }; + h = hraw & (*pH).htsize - 1i32; + elem = findElementGivenHash(pH, pKey, nKey, h); + if !elem.is_null() { + let mut old_data: *mut libc::c_void = (*elem).data; + if data.is_null() { + removeElementGivenHash(pH, elem, h); + } else { + (*elem).data = data + } + return old_data; + } + if data.is_null() { + return 0 as *mut libc::c_void; + } + new_elem = sjhashMalloc(::std::mem::size_of::() as libc::c_ulong as libc::c_long) + as *mut dc_hashelem_t; + if new_elem.is_null() { + return data; + } + if 0 != (*pH).copyKey as libc::c_int && !pKey.is_null() { + (*new_elem).pKey = malloc(nKey as libc::c_ulong); + if (*new_elem).pKey.is_null() { + free(new_elem as *mut libc::c_void); + return data; + } + memcpy( + (*new_elem).pKey as *mut libc::c_void, + pKey, + nKey as libc::c_ulong, + ); + } else { + (*new_elem).pKey = pKey as *mut libc::c_void + } + (*new_elem).nKey = nKey; + (*pH).count += 1; + if (*pH).htsize == 0i32 { + rehash(pH, 8i32); + if (*pH).htsize == 0i32 { + (*pH).count = 0i32; + free(new_elem as *mut libc::c_void); + return data; + } + } + if (*pH).count > (*pH).htsize { + rehash(pH, (*pH).htsize * 2i32); + } + if 0 != !((*pH).htsize > 0i32) as libc::c_int as libc::c_long { + __assert_rtn( + (*::std::mem::transmute::<&[u8; 15], &[libc::c_char; 15]>(b"dc_hash_insert\x00")) + .as_ptr(), + b"../src/dc_hash.c\x00" as *const u8 as *const libc::c_char, + 491i32, + b"pH->htsize>0\x00" as *const u8 as *const libc::c_char, + ); + } else { + }; + if 0 != !((*pH).htsize & (*pH).htsize - 1i32 == 0i32) as libc::c_int as libc::c_long { + __assert_rtn( + (*::std::mem::transmute::<&[u8; 15], &[libc::c_char; 15]>(b"dc_hash_insert\x00")) + .as_ptr(), + b"../src/dc_hash.c\x00" as *const u8 as *const libc::c_char, + 492i32, + b"(pH->htsize & (pH->htsize-1))==0\x00" as *const u8 as *const libc::c_char, + ); + } else { + }; + 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; +} +/* Link an element into the hash table + */ +unsafe extern "C" fn insertElement( + mut pH: *mut dc_hash_t, + mut pEntry: *mut _ht, + mut pNew: *mut dc_hashelem_t, +) { + /* First element already in pEntry */ + let mut pHead: *mut dc_hashelem_t = 0 as *mut dc_hashelem_t; + pHead = (*pEntry).chain; + if !pHead.is_null() { + (*pNew).next = pHead; + (*pNew).prev = (*pHead).prev; + if !(*pHead).prev.is_null() { + (*(*pHead).prev).next = pNew + } else { + (*pH).first = pNew + } + (*pHead).prev = pNew + } else { + (*pNew).next = (*pH).first; + if !(*pH).first.is_null() { + (*(*pH).first).prev = pNew + } + (*pNew).prev = 0 as *mut dc_hashelem_t; + (*pH).first = pNew + } + (*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 extern "C" 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; + /* 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; + /* The hash function */ + let mut xHash: Option< + unsafe extern "C" fn(_: *const libc::c_void, _: libc::c_int) -> libc::c_int, + > = None; + 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(), + b"../src/dc_hash.c\x00" as *const u8 as *const libc::c_char, + 287i32, + b"(new_size & (new_size-1))==0\x00" as *const u8 as *const libc::c_char, + ); + } else { + }; + new_ht = sjhashMalloc( + (new_size as libc::c_ulong).wrapping_mul(::std::mem::size_of::<_ht>() as libc::c_ulong) + as libc::c_long, + ) as *mut _ht; + if new_ht.is_null() { + return; + } + if !(*pH).ht.is_null() { + free((*pH).ht as *mut libc::c_void); + } + (*pH).ht = new_ht; + (*pH).htsize = new_size; + xHash = hashFunction((*pH).keyClass as libc::c_int); + elem = (*pH).first; + (*pH).first = 0 as *mut dc_hashelem_t; + while !elem.is_null() { + let mut h: libc::c_int = + xHash.expect("non-null function pointer")((*elem).pKey, (*elem).nKey) & new_size - 1i32; + next_elem = (*elem).next; + insertElement(pH, &mut *new_ht.offset(h as isize), elem); + elem = next_elem + } +} +/* Return a pointer to the appropriate hash function given the key class. + * + * About the syntax: + * The name of the function is "hashFunction". The function takes a + * single parameter "keyClass". The return value of hashFunction() + * is a pointer to another function. Specifically, the return value + * of hashFunction() is a pointer to a function that takes two parameters + * with types "const void*" and "int" and returns an "int". + */ +unsafe extern "C" fn hashFunction( + mut keyClass: libc::c_int, +) -> Option libc::c_int> { + match keyClass { + 1 => return Some(intHash), + 2 => return Some(ptrHash), + 3 => return Some(strHash), + 4 => return Some(binHash), + _ => {} + } + return None; +} +/* Hash and comparison functions when the mode is SJHASH_BINARY + */ +unsafe extern "C" fn binHash(mut pKey: *const libc::c_void, mut nKey: libc::c_int) -> libc::c_int { + let mut h: libc::c_int = 0i32; + let mut z: *const libc::c_char = pKey as *const libc::c_char; + loop { + let fresh0 = nKey; + nKey = nKey - 1; + if !(fresh0 > 0i32) { + break; + } + let fresh1 = z; + z = z.offset(1); + h = h << 3i32 ^ h ^ *fresh1 as libc::c_int + } + return h & 0x7fffffffi32; +} +/* Hash and comparison functions when the mode is SJHASH_STRING + */ +unsafe extern "C" 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); +} +/* This function computes a hash on the name of a keyword. + * Case is not significant. + */ +unsafe extern "C" fn sjhashNoCase(mut z: *const libc::c_char, mut n: libc::c_int) -> libc::c_int { + let mut h: libc::c_int = 0i32; + if n <= 0i32 { + n = strlen(z) as libc::c_int + } + while n > 0i32 { + let fresh2 = z; + z = z.offset(1); + h = h << 3i32 ^ h ^ sjhashUpperToLower[*fresh2 as libc::c_uchar as usize] as libc::c_int; + n -= 1 + } + return h & 0x7fffffffi32; +} +/* An array to map all upper-case characters into their corresponding + * lower-case character. + */ +static mut sjhashUpperToLower: [libc::c_uchar; 256] = [ + 0i32 as libc::c_uchar, + 1i32 as libc::c_uchar, + 2i32 as libc::c_uchar, + 3i32 as libc::c_uchar, + 4i32 as libc::c_uchar, + 5i32 as libc::c_uchar, + 6i32 as libc::c_uchar, + 7i32 as libc::c_uchar, + 8i32 as libc::c_uchar, + 9i32 as libc::c_uchar, + 10i32 as libc::c_uchar, + 11i32 as libc::c_uchar, + 12i32 as libc::c_uchar, + 13i32 as libc::c_uchar, + 14i32 as libc::c_uchar, + 15i32 as libc::c_uchar, + 16i32 as libc::c_uchar, + 17i32 as libc::c_uchar, + 18i32 as libc::c_uchar, + 19i32 as libc::c_uchar, + 20i32 as libc::c_uchar, + 21i32 as libc::c_uchar, + 22i32 as libc::c_uchar, + 23i32 as libc::c_uchar, + 24i32 as libc::c_uchar, + 25i32 as libc::c_uchar, + 26i32 as libc::c_uchar, + 27i32 as libc::c_uchar, + 28i32 as libc::c_uchar, + 29i32 as libc::c_uchar, + 30i32 as libc::c_uchar, + 31i32 as libc::c_uchar, + 32i32 as libc::c_uchar, + 33i32 as libc::c_uchar, + 34i32 as libc::c_uchar, + 35i32 as libc::c_uchar, + 36i32 as libc::c_uchar, + 37i32 as libc::c_uchar, + 38i32 as libc::c_uchar, + 39i32 as libc::c_uchar, + 40i32 as libc::c_uchar, + 41i32 as libc::c_uchar, + 42i32 as libc::c_uchar, + 43i32 as libc::c_uchar, + 44i32 as libc::c_uchar, + 45i32 as libc::c_uchar, + 46i32 as libc::c_uchar, + 47i32 as libc::c_uchar, + 48i32 as libc::c_uchar, + 49i32 as libc::c_uchar, + 50i32 as libc::c_uchar, + 51i32 as libc::c_uchar, + 52i32 as libc::c_uchar, + 53i32 as libc::c_uchar, + 54i32 as libc::c_uchar, + 55i32 as libc::c_uchar, + 56i32 as libc::c_uchar, + 57i32 as libc::c_uchar, + 58i32 as libc::c_uchar, + 59i32 as libc::c_uchar, + 60i32 as libc::c_uchar, + 61i32 as libc::c_uchar, + 62i32 as libc::c_uchar, + 63i32 as libc::c_uchar, + 64i32 as libc::c_uchar, + 97i32 as libc::c_uchar, + 98i32 as libc::c_uchar, + 99i32 as libc::c_uchar, + 100i32 as libc::c_uchar, + 101i32 as libc::c_uchar, + 102i32 as libc::c_uchar, + 103i32 as libc::c_uchar, + 104i32 as libc::c_uchar, + 105i32 as libc::c_uchar, + 106i32 as libc::c_uchar, + 107i32 as libc::c_uchar, + 108i32 as libc::c_uchar, + 109i32 as libc::c_uchar, + 110i32 as libc::c_uchar, + 111i32 as libc::c_uchar, + 112i32 as libc::c_uchar, + 113i32 as libc::c_uchar, + 114i32 as libc::c_uchar, + 115i32 as libc::c_uchar, + 116i32 as libc::c_uchar, + 117i32 as libc::c_uchar, + 118i32 as libc::c_uchar, + 119i32 as libc::c_uchar, + 120i32 as libc::c_uchar, + 121i32 as libc::c_uchar, + 122i32 as libc::c_uchar, + 91i32 as libc::c_uchar, + 92i32 as libc::c_uchar, + 93i32 as libc::c_uchar, + 94i32 as libc::c_uchar, + 95i32 as libc::c_uchar, + 96i32 as libc::c_uchar, + 97i32 as libc::c_uchar, + 98i32 as libc::c_uchar, + 99i32 as libc::c_uchar, + 100i32 as libc::c_uchar, + 101i32 as libc::c_uchar, + 102i32 as libc::c_uchar, + 103i32 as libc::c_uchar, + 104i32 as libc::c_uchar, + 105i32 as libc::c_uchar, + 106i32 as libc::c_uchar, + 107i32 as libc::c_uchar, + 108i32 as libc::c_uchar, + 109i32 as libc::c_uchar, + 110i32 as libc::c_uchar, + 111i32 as libc::c_uchar, + 112i32 as libc::c_uchar, + 113i32 as libc::c_uchar, + 114i32 as libc::c_uchar, + 115i32 as libc::c_uchar, + 116i32 as libc::c_uchar, + 117i32 as libc::c_uchar, + 118i32 as libc::c_uchar, + 119i32 as libc::c_uchar, + 120i32 as libc::c_uchar, + 121i32 as libc::c_uchar, + 122i32 as libc::c_uchar, + 123i32 as libc::c_uchar, + 124i32 as libc::c_uchar, + 125i32 as libc::c_uchar, + 126i32 as libc::c_uchar, + 127i32 as libc::c_uchar, + 128i32 as libc::c_uchar, + 129i32 as libc::c_uchar, + 130i32 as libc::c_uchar, + 131i32 as libc::c_uchar, + 132i32 as libc::c_uchar, + 133i32 as libc::c_uchar, + 134i32 as libc::c_uchar, + 135i32 as libc::c_uchar, + 136i32 as libc::c_uchar, + 137i32 as libc::c_uchar, + 138i32 as libc::c_uchar, + 139i32 as libc::c_uchar, + 140i32 as libc::c_uchar, + 141i32 as libc::c_uchar, + 142i32 as libc::c_uchar, + 143i32 as libc::c_uchar, + 144i32 as libc::c_uchar, + 145i32 as libc::c_uchar, + 146i32 as libc::c_uchar, + 147i32 as libc::c_uchar, + 148i32 as libc::c_uchar, + 149i32 as libc::c_uchar, + 150i32 as libc::c_uchar, + 151i32 as libc::c_uchar, + 152i32 as libc::c_uchar, + 153i32 as libc::c_uchar, + 154i32 as libc::c_uchar, + 155i32 as libc::c_uchar, + 156i32 as libc::c_uchar, + 157i32 as libc::c_uchar, + 158i32 as libc::c_uchar, + 159i32 as libc::c_uchar, + 160i32 as libc::c_uchar, + 161i32 as libc::c_uchar, + 162i32 as libc::c_uchar, + 163i32 as libc::c_uchar, + 164i32 as libc::c_uchar, + 165i32 as libc::c_uchar, + 166i32 as libc::c_uchar, + 167i32 as libc::c_uchar, + 168i32 as libc::c_uchar, + 169i32 as libc::c_uchar, + 170i32 as libc::c_uchar, + 171i32 as libc::c_uchar, + 172i32 as libc::c_uchar, + 173i32 as libc::c_uchar, + 174i32 as libc::c_uchar, + 175i32 as libc::c_uchar, + 176i32 as libc::c_uchar, + 177i32 as libc::c_uchar, + 178i32 as libc::c_uchar, + 179i32 as libc::c_uchar, + 180i32 as libc::c_uchar, + 181i32 as libc::c_uchar, + 182i32 as libc::c_uchar, + 183i32 as libc::c_uchar, + 184i32 as libc::c_uchar, + 185i32 as libc::c_uchar, + 186i32 as libc::c_uchar, + 187i32 as libc::c_uchar, + 188i32 as libc::c_uchar, + 189i32 as libc::c_uchar, + 190i32 as libc::c_uchar, + 191i32 as libc::c_uchar, + 192i32 as libc::c_uchar, + 193i32 as libc::c_uchar, + 194i32 as libc::c_uchar, + 195i32 as libc::c_uchar, + 196i32 as libc::c_uchar, + 197i32 as libc::c_uchar, + 198i32 as libc::c_uchar, + 199i32 as libc::c_uchar, + 200i32 as libc::c_uchar, + 201i32 as libc::c_uchar, + 202i32 as libc::c_uchar, + 203i32 as libc::c_uchar, + 204i32 as libc::c_uchar, + 205i32 as libc::c_uchar, + 206i32 as libc::c_uchar, + 207i32 as libc::c_uchar, + 208i32 as libc::c_uchar, + 209i32 as libc::c_uchar, + 210i32 as libc::c_uchar, + 211i32 as libc::c_uchar, + 212i32 as libc::c_uchar, + 213i32 as libc::c_uchar, + 214i32 as libc::c_uchar, + 215i32 as libc::c_uchar, + 216i32 as libc::c_uchar, + 217i32 as libc::c_uchar, + 218i32 as libc::c_uchar, + 219i32 as libc::c_uchar, + 220i32 as libc::c_uchar, + 221i32 as libc::c_uchar, + 222i32 as libc::c_uchar, + 223i32 as libc::c_uchar, + 224i32 as libc::c_uchar, + 225i32 as libc::c_uchar, + 226i32 as libc::c_uchar, + 227i32 as libc::c_uchar, + 228i32 as libc::c_uchar, + 229i32 as libc::c_uchar, + 230i32 as libc::c_uchar, + 231i32 as libc::c_uchar, + 232i32 as libc::c_uchar, + 233i32 as libc::c_uchar, + 234i32 as libc::c_uchar, + 235i32 as libc::c_uchar, + 236i32 as libc::c_uchar, + 237i32 as libc::c_uchar, + 238i32 as libc::c_uchar, + 239i32 as libc::c_uchar, + 240i32 as libc::c_uchar, + 241i32 as libc::c_uchar, + 242i32 as libc::c_uchar, + 243i32 as libc::c_uchar, + 244i32 as libc::c_uchar, + 245i32 as libc::c_uchar, + 246i32 as libc::c_uchar, + 247i32 as libc::c_uchar, + 248i32 as libc::c_uchar, + 249i32 as libc::c_uchar, + 250i32 as libc::c_uchar, + 251i32 as libc::c_uchar, + 252i32 as libc::c_uchar, + 253i32 as libc::c_uchar, + 254i32 as libc::c_uchar, + 255i32 as libc::c_uchar, +]; +/* Hash and comparison functions when the mode is SJHASH_POINTER + */ +unsafe extern "C" fn ptrHash(mut pKey: *const libc::c_void, mut 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; +} +/* Hash and comparison functions when the mode is SJHASH_INT + */ +unsafe extern "C" fn intHash(mut pKey: *const libc::c_void, mut nKey: libc::c_int) -> libc::c_int { + return 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: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +*/ +unsafe extern "C" fn sjhashMalloc(mut bytes: libc::c_long) -> *mut libc::c_void { + let mut p: *mut libc::c_void = malloc(bytes as libc::c_ulong); + if !p.is_null() { + memset(p, 0i32, bytes as libc::c_ulong); + } + return p; +} +/* Remove a single entry from the hash table given a pointer to that + * element and a hash on the element's key. + */ +unsafe extern "C" fn removeElementGivenHash( + mut pH: *mut dc_hash_t, + mut elem: *mut dc_hashelem_t, + mut h: libc::c_int, +) { + let mut pEntry: *mut _ht = 0 as *mut _ht; + if !(*elem).prev.is_null() { + (*(*elem).prev).next = (*elem).next + } else { + (*pH).first = (*elem).next + } + if !(*elem).next.is_null() { + (*(*elem).next).prev = (*elem).prev + } + pEntry = &mut *(*pH).ht.offset(h as isize) as *mut _ht; + if (*pEntry).chain == elem { + (*pEntry).chain = (*elem).next + } + (*pEntry).count -= 1; + if (*pEntry).count <= 0i32 { + (*pEntry).chain = 0 as *mut dc_hashelem_t + } + if 0 != (*pH).copyKey as libc::c_int && !(*elem).pKey.is_null() { + free((*elem).pKey); + } + 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. + */ +unsafe extern "C" fn findElementGivenHash( + mut pH: *const dc_hash_t, + mut pKey: *const libc::c_void, + mut nKey: libc::c_int, + 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; + /* Number of elements left to test */ + let mut count: libc::c_int = 0; + /* comparison function */ + let mut xCompare: Option< + unsafe extern "C" fn( + _: *const libc::c_void, + _: libc::c_int, + _: *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; + count = (*pEntry).count; + xCompare = compareFunction((*pH).keyClass as libc::c_int); + loop { + let fresh3 = count; + count = count - 1; + if !(0 != fresh3 && !elem.is_null()) { + break; + } + if xCompare.expect("non-null function pointer")((*elem).pKey, (*elem).nKey, pKey, nKey) + == 0i32 + { + return elem; + } + elem = (*elem).next + } + } + return 0 as *mut dc_hashelem_t; +} +/* Return a pointer to the appropriate hash function given the key class. + */ +unsafe extern "C" fn compareFunction( + mut keyClass: libc::c_int, +) -> Option< + unsafe extern "C" fn( + _: *const libc::c_void, + _: libc::c_int, + _: *const libc::c_void, + _: libc::c_int, + ) -> libc::c_int, +> { + match keyClass { + 1 => return Some(intCompare), + 2 => return Some(ptrCompare), + 3 => return Some(strCompare), + 4 => return Some(binCompare), + _ => {} + } + return None; +} +unsafe extern "C" fn binCompare( + mut pKey1: *const libc::c_void, + mut n1: libc::c_int, + mut pKey2: *const libc::c_void, + mut n2: libc::c_int, +) -> libc::c_int { + if n1 != n2 { + return 1i32; + } + return memcmp(pKey1, pKey2, n1 as libc::c_ulong); +} +unsafe extern "C" fn strCompare( + mut pKey1: *const libc::c_void, + mut n1: libc::c_int, + mut pKey2: *const libc::c_void, + mut n2: libc::c_int, +) -> libc::c_int { + if n1 != n2 { + return 1i32; + } + return 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. + */ +unsafe extern "C" fn sjhashStrNICmp( + mut zLeft: *const libc::c_char, + 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; + a = zLeft as *mut libc::c_uchar; + b = zRight as *mut libc::c_uchar; + loop { + let fresh4 = N; + N = N - 1; + if !(fresh4 > 0i32 + && *a as libc::c_int != 0i32 + && sjhashUpperToLower[*a as usize] as libc::c_int + == sjhashUpperToLower[*b as usize] as libc::c_int) + { + break; + } + a = a.offset(1isize); + b = b.offset(1isize) + } + return if N < 0i32 { + 0i32 + } else { + sjhashUpperToLower[*a as usize] as libc::c_int + - sjhashUpperToLower[*b as usize] as libc::c_int + }; +} +unsafe extern "C" fn ptrCompare( + mut pKey1: *const libc::c_void, + mut n1: libc::c_int, + mut pKey2: *const libc::c_void, + mut n2: libc::c_int, +) -> libc::c_int { + if pKey1 == pKey2 { + return 0i32; + } + if pKey1 < pKey2 { + return -1i32; + } + return 1i32; +} +unsafe extern "C" fn intCompare( + mut pKey1: *const libc::c_void, + mut n1: libc::c_int, + mut pKey2: *const libc::c_void, + mut n2: libc::c_int, +) -> libc::c_int { + return n2 - n1; +} +#[no_mangle] +pub unsafe extern "C" fn dc_hash_find( + mut pH: *const dc_hash_t, + mut pKey: *const libc::c_void, + mut nKey: libc::c_int, +) -> *mut libc::c_void { + /* A hash on key */ + let mut h: libc::c_int = 0; + /* The element that matches key */ + let mut elem: *mut dc_hashelem_t = 0 as *mut dc_hashelem_t; + /* The hash function */ + let mut xHash: Option< + unsafe extern "C" fn(_: *const libc::c_void, _: libc::c_int) -> libc::c_int, + > = None; + if pH.is_null() || (*pH).ht.is_null() { + return 0 as *mut libc::c_void; + } + xHash = hashFunction((*pH).keyClass as libc::c_int); + if 0 != xHash.is_none() as libc::c_int as libc::c_long { + __assert_rtn( + (*::std::mem::transmute::<&[u8; 13], &[libc::c_char; 13]>(b"dc_hash_find\x00")) + .as_ptr(), + b"../src/dc_hash.c\x00" as *const u8 as *const libc::c_char, + 397i32, + b"xHash!=0\x00" as *const u8 as *const libc::c_char, + ); + } else { + }; + h = xHash.expect("non-null function pointer")(pKey, nKey); + if 0 != !((*pH).htsize & (*pH).htsize - 1i32 == 0i32) as libc::c_int as libc::c_long { + __assert_rtn( + (*::std::mem::transmute::<&[u8; 13], &[libc::c_char; 13]>(b"dc_hash_find\x00")) + .as_ptr(), + b"../src/dc_hash.c\x00" as *const u8 as *const libc::c_char, + 399i32, + b"(pH->htsize & (pH->htsize-1))==0\x00" as *const u8 as *const libc::c_char, + ); + } else { + }; + elem = findElementGivenHash(pH, pKey, nKey, h & (*pH).htsize - 1i32); + return if !elem.is_null() { + (*elem).data + } else { + 0 as *mut libc::c_void + }; +} +#[no_mangle] +pub unsafe extern "C" 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; + if pH.is_null() { + return; + } + elem = (*pH).first; + (*pH).first = 0 as *mut dc_hashelem_t; + if !(*pH).ht.is_null() { + free((*pH).ht as *mut libc::c_void); + } + (*pH).ht = 0 as *mut _ht; + (*pH).htsize = 0i32; + while !elem.is_null() { + let mut next_elem: *mut dc_hashelem_t = (*elem).next; + if 0 != (*pH).copyKey as libc::c_int && !(*elem).pKey.is_null() { + free((*elem).pKey); + } + free(elem as *mut libc::c_void); + elem = next_elem + } + (*pH).count = 0i32; +} diff --git a/src/dc_imap.rs b/src/dc_imap.rs new file mode 100644 index 000000000..a378bba69 --- /dev/null +++ b/src/dc_imap.rs @@ -0,0 +1,3290 @@ +use c2rust_bitfields::BitfieldStruct; +use libc; +extern "C" { + pub type mailstream_cancel; + pub type sqlite3; + #[no_mangle] + fn calloc(_: libc::c_ulong, _: libc::c_ulong) -> *mut libc::c_void; + #[no_mangle] + fn free(_: *mut libc::c_void); + #[no_mangle] + fn atol(_: *const libc::c_char) -> libc::c_long; + #[no_mangle] + fn exit(_: libc::c_int) -> !; + #[no_mangle] + fn time(_: *mut time_t) -> time_t; + #[no_mangle] + fn mailstream_close(s: *mut mailstream) -> libc::c_int; + #[no_mangle] + fn mailstream_wait_idle(s: *mut mailstream, max_idle_delay: libc::c_int) -> libc::c_int; + #[no_mangle] + fn mailstream_setup_idle(s: *mut mailstream) -> libc::c_int; + #[no_mangle] + fn mailstream_unsetup_idle(s: *mut mailstream); + #[no_mangle] + fn mailstream_interrupt_idle(s: *mut mailstream); + #[no_mangle] + fn mailimap_section_new(sec_spec: *mut mailimap_section_spec) -> *mut mailimap_section; + #[no_mangle] + fn mailimap_set_free(set: *mut mailimap_set); + #[no_mangle] + fn mailimap_fetch_type_free(fetch_type: *mut mailimap_fetch_type); + #[no_mangle] + fn mailimap_store_att_flags_free(store_att_flags: *mut mailimap_store_att_flags); + #[no_mangle] + fn mailimap_set_new_interval(first: uint32_t, last: uint32_t) -> *mut mailimap_set; + #[no_mangle] + fn mailimap_set_new_single(indx: uint32_t) -> *mut mailimap_set; + #[no_mangle] + fn mailimap_fetch_att_new_envelope() -> *mut mailimap_fetch_att; + #[no_mangle] + fn mailimap_fetch_att_new_flags() -> *mut mailimap_fetch_att; + #[no_mangle] + fn mailimap_fetch_att_new_uid() -> *mut mailimap_fetch_att; + #[no_mangle] + fn mailimap_fetch_att_new_body_peek_section( + section: *mut mailimap_section, + ) -> *mut mailimap_fetch_att; + #[no_mangle] + fn mailimap_fetch_type_new_fetch_att_list_empty() -> *mut mailimap_fetch_type; + #[no_mangle] + fn mailimap_fetch_type_new_fetch_att_list_add( + fetch_type: *mut mailimap_fetch_type, + fetch_att: *mut mailimap_fetch_att, + ) -> libc::c_int; + #[no_mangle] + fn mailimap_store_att_flags_new_add_flags( + flags: *mut mailimap_flag_list, + ) -> *mut mailimap_store_att_flags; + #[no_mangle] + fn mailimap_flag_list_new_empty() -> *mut mailimap_flag_list; + #[no_mangle] + fn mailimap_flag_list_add( + flag_list: *mut mailimap_flag_list, + f: *mut mailimap_flag, + ) -> libc::c_int; + #[no_mangle] + fn mailimap_flag_new_deleted() -> *mut mailimap_flag; + #[no_mangle] + fn mailimap_flag_new_seen() -> *mut mailimap_flag; + #[no_mangle] + fn mailimap_flag_new_flag_keyword(flag_keyword: *mut libc::c_char) -> *mut mailimap_flag; + #[no_mangle] + fn mailimap_socket_connect( + f: *mut mailimap, + server: *const libc::c_char, + port: uint16_t, + ) -> libc::c_int; + #[no_mangle] + fn mailimap_socket_starttls(f: *mut mailimap) -> libc::c_int; + #[no_mangle] + fn mailimap_ssl_connect( + f: *mut mailimap, + server: *const libc::c_char, + port: uint16_t, + ) -> libc::c_int; + #[no_mangle] + 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; + #[no_mangle] + 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; + #[no_mangle] + fn mailimap_idle(session: *mut mailimap) -> libc::c_int; + #[no_mangle] + fn mailimap_idle_done(session: *mut mailimap) -> libc::c_int; + #[no_mangle] + fn mailimap_has_idle(session: *mut mailimap) -> libc::c_int; + #[no_mangle] + fn mailimap_has_xlist(session: *mut mailimap) -> libc::c_int; + #[no_mangle] + fn mailimap_oauth2_authenticate( + session: *mut mailimap, + auth_user: *const libc::c_char, + access_token: *const libc::c_char, + ) -> libc::c_int; + #[no_mangle] + fn mailimap_close(session: *mut mailimap) -> libc::c_int; + #[no_mangle] + fn mailimap_fetch( + session: *mut mailimap, + set: *mut mailimap_set, + fetch_type: *mut mailimap_fetch_type, + result: *mut *mut clist, + ) -> libc::c_int; + #[no_mangle] + fn mailimap_uid_fetch( + session: *mut mailimap, + set: *mut mailimap_set, + fetch_type: *mut mailimap_fetch_type, + result: *mut *mut clist, + ) -> libc::c_int; + #[no_mangle] + fn mailimap_fetch_list_free(fetch_list: *mut clist); + #[no_mangle] + fn mailimap_login( + session: *mut mailimap, + userid: *const libc::c_char, + password: *const libc::c_char, + ) -> libc::c_int; + #[no_mangle] + fn mailimap_select(session: *mut mailimap, mb: *const libc::c_char) -> libc::c_int; + #[no_mangle] + fn mailimap_uid_store( + session: *mut mailimap, + set: *mut mailimap_set, + store_att_flags: *mut mailimap_store_att_flags, + ) -> libc::c_int; + #[no_mangle] + fn mailimap_new( + imap_progr_rate: size_t, + imap_progr_fun: Option ()>, + ) -> *mut mailimap; + #[no_mangle] + fn mailimap_free(session: *mut mailimap); + #[no_mangle] + fn mailimap_set_timeout(session: *mut mailimap, timeout: time_t); + #[no_mangle] + fn memset(_: *mut libc::c_void, _: libc::c_int, _: libc::c_ulong) -> *mut libc::c_void; + #[no_mangle] + fn strchr(_: *const libc::c_char, _: libc::c_int) -> *mut libc::c_char; + #[no_mangle] + fn strcmp(_: *const libc::c_char, _: *const libc::c_char) -> libc::c_int; + #[no_mangle] + fn strlen(_: *const libc::c_char) -> libc::c_ulong; + #[no_mangle] + fn strcasecmp(_: *const libc::c_char, _: *const libc::c_char) -> libc::c_int; + #[no_mangle] + fn pthread_cond_destroy(_: *mut pthread_cond_t) -> libc::c_int; + #[no_mangle] + fn pthread_cond_init(_: *mut pthread_cond_t, _: *const pthread_condattr_t) -> libc::c_int; + #[no_mangle] + fn pthread_cond_signal(_: *mut pthread_cond_t) -> libc::c_int; + #[no_mangle] + fn pthread_cond_timedwait( + _: *mut pthread_cond_t, + _: *mut pthread_mutex_t, + _: *const timespec, + ) -> libc::c_int; + #[no_mangle] + fn pthread_mutex_destroy(_: *mut pthread_mutex_t) -> libc::c_int; + #[no_mangle] + fn pthread_mutex_init(_: *mut pthread_mutex_t, _: *const pthread_mutexattr_t) -> libc::c_int; + #[no_mangle] + fn pthread_mutex_lock(_: *mut pthread_mutex_t) -> libc::c_int; + #[no_mangle] + fn pthread_mutex_unlock(_: *mut pthread_mutex_t) -> libc::c_int; + /* string tools */ + #[no_mangle] + fn dc_strdup(_: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn dc_trim(_: *mut libc::c_char); + #[no_mangle] + fn dc_mprintf(format: *const libc::c_char, _: ...) -> *mut libc::c_char; + #[no_mangle] + fn dc_strbuilder_init(_: *mut dc_strbuilder_t, init_bytes: libc::c_int); + #[no_mangle] + fn dc_strbuilder_cat(_: *mut dc_strbuilder_t, text: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn dc_strbuilder_catf(_: *mut dc_strbuilder_t, format: *const libc::c_char, _: ...); + /* Replaces the first `%1$s` in the given String-ID by the given value. + The result must be free()'d! */ + #[no_mangle] + fn dc_stock_str_repl_string( + _: *mut dc_context_t, + id: libc::c_int, + value: *const libc::c_char, + ) -> *mut libc::c_char; + /* Replaces the first `%1$s` and `%2$s` in the given String-ID by the two given strings. + The result must be free()'d! */ + #[no_mangle] + fn dc_stock_str_repl_string2( + _: *mut dc_context_t, + id: libc::c_int, + _: *const libc::c_char, + _: *const libc::c_char, + ) -> *mut libc::c_char; + #[no_mangle] + fn dc_log_info(_: *mut dc_context_t, data1: libc::c_int, msg: *const libc::c_char, _: ...); + #[no_mangle] + fn dc_log_event( + _: *mut dc_context_t, + event_code: libc::c_int, + data1: libc::c_int, + msg: *const libc::c_char, + _: ... + ); + #[no_mangle] + fn dc_log_event_seq( + _: *mut dc_context_t, + event_code: libc::c_int, + sequence_start: *mut libc::c_int, + msg: *const libc::c_char, + _: ... + ); + // the following function may block due http-requests; + // must not be called from the main thread or by the ui! + #[no_mangle] + fn dc_get_oauth2_access_token( + _: *mut dc_context_t, + addr: *const libc::c_char, + code: *const libc::c_char, + flags: libc::c_int, + ) -> *mut libc::c_char; + #[no_mangle] + fn dc_log_warning(_: *mut dc_context_t, data1: libc::c_int, msg: *const libc::c_char, _: ...); + #[no_mangle] + fn dc_log_error(_: *mut dc_context_t, data1: libc::c_int, msg: *const libc::c_char, _: ...); +} +pub type __darwin_size_t = libc::c_ulong; +pub type __darwin_ssize_t = libc::c_long; +pub type __darwin_time_t = libc::c_long; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_cond_t { + pub __sig: libc::c_long, + pub __opaque: [libc::c_char; 40], +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_condattr_t { + pub __sig: libc::c_long, + pub __opaque: [libc::c_char; 8], +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_mutex_t { + pub __sig: libc::c_long, + pub __opaque: [libc::c_char; 56], +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_mutexattr_t { + pub __sig: libc::c_long, + pub __opaque: [libc::c_char; 8], +} +pub type __darwin_pthread_cond_t = _opaque_pthread_cond_t; +pub type __darwin_pthread_condattr_t = _opaque_pthread_condattr_t; +pub type __darwin_pthread_mutex_t = _opaque_pthread_mutex_t; +pub type __darwin_pthread_mutexattr_t = _opaque_pthread_mutexattr_t; +pub type uintptr_t = libc::c_ulong; +pub type size_t = __darwin_size_t; +pub type uint8_t = libc::c_uchar; +pub type uint16_t = libc::c_ushort; +pub type uint32_t = libc::c_uint; +pub type ssize_t = __darwin_ssize_t; +pub type time_t = __darwin_time_t; +pub type pthread_cond_t = __darwin_pthread_cond_t; +pub type pthread_condattr_t = __darwin_pthread_condattr_t; +pub type pthread_mutex_t = __darwin_pthread_mutex_t; +pub type pthread_mutexattr_t = __darwin_pthread_mutexattr_t; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct timespec { + pub tv_sec: __darwin_time_t, + pub tv_nsec: libc::c_long, +} +#[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; +#[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 extern "C" 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, +} +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_19, + 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 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; +/* define DC_USE_RPGP to enable use of rPGP instead of netpgp where available; +preferrably, this should be done in the project configuration currently */ +//#define DC_USE_RPGP 1 +/* Includes that are used frequently. This file may also be used to create predefined headers. */ +/* * Structure behind dc_context_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_context { + pub magic: uint32_t, + pub userdata: *mut libc::c_void, + pub dbfile: *mut libc::c_char, + pub blobdir: *mut libc::c_char, + pub sql: *mut dc_sqlite3_t, + pub inbox: *mut dc_imap_t, + pub inboxidle_condmutex: pthread_mutex_t, + pub perform_inbox_jobs_needed: libc::c_int, + pub probe_imap_network: libc::c_int, + pub sentbox_thread: dc_jobthread_t, + pub mvbox_thread: dc_jobthread_t, + pub smtp: *mut dc_smtp_t, + pub smtpidle_cond: pthread_cond_t, + pub smtpidle_condmutex: pthread_mutex_t, + pub smtpidle_condflag: libc::c_int, + pub smtp_suspended: libc::c_int, + pub smtp_doing_jobs: libc::c_int, + pub perform_smtp_jobs_needed: libc::c_int, + pub probe_smtp_network: libc::c_int, + pub oauth2_critical: pthread_mutex_t, + 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 type dc_lot_t = _dc_lot; +/* * Structure behind dc_lot_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_lot { + pub magic: uint32_t, + pub text1_meaning: libc::c_int, + pub text1: *mut libc::c_char, + pub text2: *mut libc::c_char, + pub timestamp: time_t, + pub state: libc::c_int, + pub id: uint32_t, + pub fingerprint: *mut libc::c_char, + pub invitenumber: *mut libc::c_char, + pub auth: *mut libc::c_char, +} +/* * + * 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 = Option< + unsafe extern "C" fn( + _: *mut dc_context_t, + _: libc::c_int, + _: uintptr_t, + _: uintptr_t, + ) -> uintptr_t, +>; +/* * + * @mainpage Getting started + * + * This document describes how to handle the Delta Chat core library. + * For general information about Delta Chat itself, + * see and . + * + * Let's start. + * + * First of all, you have to **define an event-handler-function** + * that is called by the library on specific events + * (eg. when the configuration is done or when fresh messages arrive). + * With this function you can create a Delta Chat context then: + * + * ~~~ + * #include + * + * uintptr_t event_handler_func(dc_context_t* context, int event, + * uintptr_t data1, uintptr_t data2) + * { + * return 0; // for unhandled events, it is always safe to return 0 + * } + * + * dc_context_t* context = dc_context_new(event_handler_func, NULL, NULL); + * ~~~ + * + * After that, you should make sure, + * sending and receiving jobs are processed as needed. + * For this purpose, you have to **create two threads:** + * + * ~~~ + * #include + * + * void* imap_thread_func(void* context) + * { + * while (true) { + * dc_perform_imap_jobs(context); + * dc_perform_imap_fetch(context); + * dc_perform_imap_idle(context); + * } + * } + * + * void* smtp_thread_func(void* context) + * { + * while (true) { + * dc_perform_smtp_jobs(context); + * dc_perform_smtp_idle(context); + * } + * } + * + * static pthread_t imap_thread, smtp_thread; + * pthread_create(&imap_thread, NULL, imap_thread_func, context); + * pthread_create(&smtp_thread, NULL, smtp_thread_func, context); + * ~~~ + * + * The example above uses "pthreads", + * however, you can also use anything else for thread handling. + * NB: The deltachat-core library itself does not create any threads on its own, + * however, functions, unless stated otherwise, are thread-safe. + * + * After that you can **define and open a database.** + * The database is a normal sqlite-file and is created as needed: + * + * ~~~ + * dc_open(context, "example.db", NULL); + * ~~~ + * + * Now you can **configure the context:** + * + * ~~~ + * // use some real test credentials here + * dc_set_config(context, "addr", "alice@example.org"); + * dc_set_config(context, "mail_pw", "***"); + * dc_configure(context); + * ~~~ + * + * dc_configure() returns immediately, the configuration itself may take a while + * and is done by a job in the imap-thread you've defined above. + * Once done, the #DC_EVENT_CONFIGURE_PROGRESS reports success + * to the event_handler_func() that is also defined above. + * + * The configuration result is saved in the database, + * on subsequent starts it is not needed to call dc_configure() + * (you can check this using dc_is_configured()). + * + * Now you can **send the first message:** + * + * ~~~ + * // use a real testing address here + * uint32_t contact_id = dc_create_contact(context, NULL, "bob@example.org"); + * uint32_t chat_id = dc_create_chat_by_contact_id(context, contact_id); + * + * dc_send_text_msg(context, chat_id, "Hi, here is my first message!"); + * ~~~ + * + * dc_send_text_msg() returns immediately; + * the sending itself is done by a job in the smtp-thread you've defined above. + * If you check the testing address (bob) + * and you should have received a normal email. + * Answer this email in any email program with "Got it!" + * and the imap-thread you've create above will **receive the message**. + * + * You can then **list all messages** of a chat as follow: + * + * ~~~ + * dc_array_t* msglist = dc_get_chat_msgs(context, chat_id, 0, 0); + * for (int i = 0; i < dc_array_get_cnt(msglist); i++) + * { + * uint32_t msg_id = dc_array_get_id(msglist, i); + * dc_msg_t* msg = dc_get_msg(context, msg_id); + * char* text = dc_msg_get_text(msg); + * + * printf("Message %i: %s\n", i+1, text); + * + * free(text); + * dc_msg_unref(msg); + * } + * dc_array_unref(msglist); + * ~~~ + * + * This will output the following two lines: + * + * ~~~ + * Message 1: Hi, here is my first message! + * Message 2: Got it! + * ~~~ + * + * + * ## Class reference + * + * For a class reference, see the "Classes" link atop. + * + * + * ## Further hints + * + * Here are some additional, unsorted hints that may be useful. + * + * - For `get`-functions, you have to unref the return value in some way. + * + * - Strings in function arguments or return values are usually UTF-8 encoded. + * + * - The issue-tracker for the core library is here: + * + * + * The following points are important mainly + * for the authors of the library itself: + * + * - For indentation, use tabs. + * Alignments that are not placed at the beginning of a line + * should be done with spaces. + * + * - For padding between functions, + * classes etc. use 2 empty lines + * + * - Source files are encoded as UTF-8 with Unix line endings + * (a simple `LF`, `0x0A` or `\n`) + * + * If you need further assistance, + * please do not hesitate to contact us + * through the channels shown at https://delta.chat/en/contribute + * + * Please keep in mind, that your derived work + * must respect the Mozilla Public License 2.0 of libdeltachat + * and the respective licenses of the libraries libdeltachat links with. + * + * See you. + */ +/* * + * @class dc_context_t + * + * An object representing a single account. + * + * Each account is linked to an IMAP/SMTP account and uses a separate + * SQLite database for offline functionality and for account-related + * settings. + */ +pub type dc_context_t = _dc_context; +/* ** library-private **********************************************************/ +pub type dc_smtp_t = _dc_smtp; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_smtp { + 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 error: *mut libc::c_char, + pub error_etpan: libc::c_int, +} +pub type dc_jobthread_t = _dc_jobthread; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_jobthread { + 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, + 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, +} +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_imap { + 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 type dc_receive_imf_t = Option< + unsafe extern "C" 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_imap_t = _dc_imap; +pub type dc_precheck_imf_t = Option< + unsafe extern "C" 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< + unsafe extern "C" fn(_: *mut dc_imap_t, _: *const libc::c_char, _: *const libc::c_char) -> (), +>; +pub type dc_get_config_t = Option< + unsafe extern "C" fn( + _: *mut dc_imap_t, + _: *const libc::c_char, + _: *const libc::c_char, + ) -> *mut libc::c_char, +>; +/* ** library-private **********************************************************/ +pub type dc_sqlite3_t = _dc_sqlite3; +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_sqlite3 { + pub cobj: *mut sqlite3, + pub context: *mut dc_context_t, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_strbuilder { + pub buf: *mut libc::c_char, + pub allocated: libc::c_int, + pub free: libc::c_int, + pub eos: *mut libc::c_char, +} +pub type dc_strbuilder_t = _dc_strbuilder; +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_loginparam { + pub addr: *mut libc::c_char, + pub mail_server: *mut libc::c_char, + pub mail_user: *mut libc::c_char, + pub mail_pw: *mut libc::c_char, + pub mail_port: uint16_t, + pub send_server: *mut libc::c_char, + pub send_user: *mut libc::c_char, + pub send_pw: *mut libc::c_char, + pub send_port: libc::c_int, + pub server_flags: libc::c_int, +} +pub type dc_loginparam_t = _dc_loginparam; +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; +#[no_mangle] +pub unsafe extern "C" fn dc_imap_new( + mut get_config: dc_get_config_t, + mut set_config: dc_set_config_t, + mut precheck_imf: dc_precheck_imf_t, + mut receive_imf: dc_receive_imf_t, + mut userData: *mut libc::c_void, + mut context: *mut dc_context_t, +) -> *mut dc_imap_t { + let mut imap: *mut dc_imap_t = 0 as *mut dc_imap_t; + imap = calloc( + 1i32 as libc::c_ulong, + ::std::mem::size_of::() as libc::c_ulong, + ) as *mut dc_imap_t; + if imap.is_null() { + exit(25i32); + } + (*imap).log_connect_errors = 1i32; + (*imap).context = context; + (*imap).get_config = get_config; + (*imap).set_config = set_config; + (*imap).precheck_imf = precheck_imf; + (*imap).receive_imf = receive_imf; + (*imap).userData = userData; + pthread_mutex_init( + &mut (*imap).watch_condmutex, + 0 as *const pthread_mutexattr_t, + ); + pthread_cond_init(&mut (*imap).watch_cond, 0 as *const pthread_condattr_t); + (*imap).watch_folder = + calloc(1i32 as libc::c_ulong, 1i32 as libc::c_ulong) as *mut libc::c_char; + (*imap).selected_folder = + calloc(1i32 as libc::c_ulong, 1i32 as libc::c_ulong) as *mut libc::c_char; + (*imap).fetch_type_prefetch = mailimap_fetch_type_new_fetch_att_list_empty(); + mailimap_fetch_type_new_fetch_att_list_add( + (*imap).fetch_type_prefetch, + mailimap_fetch_att_new_uid(), + ); + mailimap_fetch_type_new_fetch_att_list_add( + (*imap).fetch_type_prefetch, + mailimap_fetch_att_new_envelope(), + ); + (*imap).fetch_type_body = mailimap_fetch_type_new_fetch_att_list_empty(); + mailimap_fetch_type_new_fetch_att_list_add( + (*imap).fetch_type_body, + mailimap_fetch_att_new_flags(), + ); + mailimap_fetch_type_new_fetch_att_list_add( + (*imap).fetch_type_body, + mailimap_fetch_att_new_body_peek_section(mailimap_section_new( + 0 as *mut mailimap_section_spec, + )), + ); + (*imap).fetch_type_flags = mailimap_fetch_type_new_fetch_att_list_empty(); + mailimap_fetch_type_new_fetch_att_list_add( + (*imap).fetch_type_flags, + mailimap_fetch_att_new_flags(), + ); + return imap; +} +#[no_mangle] +pub unsafe extern "C" 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); +} +#[no_mangle] +pub unsafe extern "C" fn dc_imap_disconnect(mut imap: *mut dc_imap_t) { + if imap.is_null() { + return; + } + if 0 != (*imap).connected { + unsetup_handle(imap); + free_connect_param(imap); + (*imap).connected = 0i32 + }; +} +/* we leave sent_folder set; normally this does not change in a normal reconnect; we'll update this folder if we get errors */ +/* ****************************************************************************** + * Connect/Disconnect + ******************************************************************************/ +unsafe extern "C" fn free_connect_param(mut imap: *mut dc_imap_t) { + free((*imap).addr as *mut libc::c_void); + (*imap).addr = 0 as *mut libc::c_char; + free((*imap).imap_server as *mut libc::c_void); + (*imap).imap_server = 0 as *mut libc::c_char; + free((*imap).imap_user as *mut libc::c_void); + (*imap).imap_user = 0 as *mut libc::c_char; + free((*imap).imap_pw as *mut libc::c_void); + (*imap).imap_pw = 0 as *mut libc::c_char; + *(*imap).watch_folder.offset(0isize) = 0i32 as libc::c_char; + *(*imap).selected_folder.offset(0isize) = 0i32 as libc::c_char; + (*imap).imap_port = 0i32; + (*imap).can_idle = 0i32; + (*imap).has_xlist = 0i32; +} +unsafe extern "C" fn unsetup_handle(mut imap: *mut dc_imap_t) { + if imap.is_null() { + return; + } + if !(*imap).etpan.is_null() { + if 0 != (*imap).idle_set_up { + mailstream_unsetup_idle((*(*imap).etpan).imap_stream); + (*imap).idle_set_up = 0i32 + } + if !(*(*imap).etpan).imap_stream.is_null() { + mailstream_close((*(*imap).etpan).imap_stream); + (*(*imap).etpan).imap_stream = 0 as *mut mailstream + } + mailimap_free((*imap).etpan); + (*imap).etpan = 0 as *mut mailimap; + dc_log_info( + (*imap).context, + 0i32, + b"IMAP disconnected.\x00" as *const u8 as *const libc::c_char, + ); + } + *(*imap).selected_folder.offset(0isize) = 0i32 as libc::c_char; +} +#[no_mangle] +pub unsafe extern "C" fn dc_imap_connect( + mut imap: *mut dc_imap_t, + mut lp: *const dc_loginparam_t, +) -> libc::c_int { + let mut success: libc::c_int = 0i32; + if imap.is_null() + || lp.is_null() + || (*lp).mail_server.is_null() + || (*lp).mail_user.is_null() + || (*lp).mail_pw.is_null() + { + return 0i32; + } + if 0 != (*imap).connected { + success = 1i32 + } else { + (*imap).addr = dc_strdup((*lp).addr); + (*imap).imap_server = dc_strdup((*lp).mail_server); + (*imap).imap_port = (*lp).mail_port as libc::c_int; + (*imap).imap_user = dc_strdup((*lp).mail_user); + (*imap).imap_pw = dc_strdup((*lp).mail_pw); + (*imap).server_flags = (*lp).server_flags; + if !(0 == setup_handle_if_needed(imap)) { + (*imap).can_idle = mailimap_has_idle((*imap).etpan); + (*imap).has_xlist = mailimap_has_xlist((*imap).etpan); + (*imap).can_idle = 0i32; + if 0 == (*imap).skip_log_capabilities + && !(*(*imap).etpan).imap_connection_info.is_null() + && !(*(*(*imap).etpan).imap_connection_info) + .imap_capability + .is_null() + { + (*imap).skip_log_capabilities = 1i32; + let mut capinfostr: dc_strbuilder_t = _dc_strbuilder { + buf: 0 as *mut libc::c_char, + allocated: 0, + free: 0, + eos: 0 as *mut libc::c_char, + }; + dc_strbuilder_init(&mut capinfostr, 0i32); + let mut list: *mut clist = + (*(*(*(*imap).etpan).imap_connection_info).imap_capability).cap_list; + if !list.is_null() { + let mut cur: *mut clistiter = 0 as *mut clistiter; + cur = (*list).first; + while !cur.is_null() { + let mut cap: *mut mailimap_capability = (if !cur.is_null() { + (*cur).data + } else { + 0 as *mut libc::c_void + }) + as *mut mailimap_capability; + if !cap.is_null() + && (*cap).cap_type == MAILIMAP_CAPABILITY_NAME as libc::c_int + { + dc_strbuilder_cat( + &mut capinfostr, + b" \x00" as *const u8 as *const libc::c_char, + ); + dc_strbuilder_cat(&mut capinfostr, (*cap).cap_data.cap_name); + } + cur = if !cur.is_null() { + (*cur).next + } else { + 0 as *mut clistcell_s + } + } + } + dc_log_info( + (*imap).context, + 0i32, + b"IMAP-capabilities:%s\x00" as *const u8 as *const libc::c_char, + capinfostr.buf, + ); + free(capinfostr.buf as *mut libc::c_void); + } + (*imap).connected = 1i32; + success = 1i32 + } + } + if success == 0i32 { + unsetup_handle(imap); + free_connect_param(imap); + } + return success; +} +unsafe extern "C" fn setup_handle_if_needed(mut imap: *mut dc_imap_t) -> libc::c_int { + let mut current_block: u64; + let mut r: libc::c_int = 0i32; + let mut success: libc::c_int = 0i32; + if !(imap.is_null() || (*imap).imap_server.is_null()) { + if 0 != (*imap).should_reconnect { + unsetup_handle(imap); + } + if !(*imap).etpan.is_null() { + success = 1i32 + } else { + (*imap).etpan = mailimap_new(0i32 as size_t, None); + mailimap_set_timeout((*imap).etpan, 10i32 as time_t); + if 0 != (*imap).server_flags & (0x100i32 | 0x400i32) { + r = mailimap_socket_connect( + (*imap).etpan, + (*imap).imap_server, + (*imap).imap_port as uint16_t, + ); + if 0 != dc_imap_is_error(imap, r) { + dc_log_event_seq( + (*imap).context, + 401i32, + &mut (*imap).log_connect_errors as *mut libc::c_int, + b"Could not connect to IMAP-server %s:%i. (Error #%i)\x00" as *const u8 + as *const libc::c_char, + (*imap).imap_server, + (*imap).imap_port as libc::c_int, + r as libc::c_int, + ); + current_block = 15811161807000851472; + } else if 0 != (*imap).server_flags & 0x100i32 { + r = mailimap_socket_starttls((*imap).etpan); + if 0 != dc_imap_is_error(imap, r) { + dc_log_event_seq((*imap).context, 401i32, + &mut (*imap).log_connect_errors as + *mut libc::c_int, + b"Could not connect to IMAP-server %s:%i using STARTTLS. (Error #%i)\x00" + as *const u8 as + *const libc::c_char, + (*imap).imap_server, + (*imap).imap_port as libc::c_int, + r as libc::c_int); + current_block = 15811161807000851472; + } else { + dc_log_info( + (*imap).context, + 0i32, + b"IMAP-server %s:%i STARTTLS-connected.\x00" as *const u8 + as *const libc::c_char, + (*imap).imap_server, + (*imap).imap_port as libc::c_int, + ); + current_block = 14763689060501151050; + } + } else { + dc_log_info( + (*imap).context, + 0i32, + b"IMAP-server %s:%i connected.\x00" as *const u8 as *const libc::c_char, + (*imap).imap_server, + (*imap).imap_port as libc::c_int, + ); + current_block = 14763689060501151050; + } + } else { + r = mailimap_ssl_connect( + (*imap).etpan, + (*imap).imap_server, + (*imap).imap_port as uint16_t, + ); + if 0 != dc_imap_is_error(imap, r) { + dc_log_event_seq( + (*imap).context, + 401i32, + &mut (*imap).log_connect_errors as *mut libc::c_int, + b"Could not connect to IMAP-server %s:%i using SSL. (Error #%i)\x00" + as *const u8 as *const libc::c_char, + (*imap).imap_server, + (*imap).imap_port as libc::c_int, + r as libc::c_int, + ); + current_block = 15811161807000851472; + } else { + dc_log_info( + (*imap).context, + 0i32, + b"IMAP-server %s:%i SSL-connected.\x00" as *const u8 as *const libc::c_char, + (*imap).imap_server, + (*imap).imap_port as libc::c_int, + ); + current_block = 14763689060501151050; + } + } + match current_block { + 15811161807000851472 => {} + _ => { + if 0 != (*imap).server_flags & 0x2i32 { + dc_log_info( + (*imap).context, + 0i32, + b"IMAP-OAuth2 connect...\x00" as *const u8 as *const libc::c_char, + ); + let mut access_token: *mut libc::c_char = dc_get_oauth2_access_token( + (*imap).context, + (*imap).addr, + (*imap).imap_pw, + 0i32, + ); + r = mailimap_oauth2_authenticate( + (*imap).etpan, + (*imap).imap_user, + access_token, + ); + if 0 != dc_imap_is_error(imap, r) { + free(access_token as *mut libc::c_void); + access_token = dc_get_oauth2_access_token( + (*imap).context, + (*imap).addr, + (*imap).imap_pw, + 0x1i32, + ); + r = mailimap_oauth2_authenticate( + (*imap).etpan, + (*imap).imap_user, + access_token, + ) + } + free(access_token as *mut libc::c_void); + } else { + r = mailimap_login((*imap).etpan, (*imap).imap_user, (*imap).imap_pw) + } + if 0 != dc_imap_is_error(imap, r) { + let mut msg: *mut libc::c_char = get_error_msg( + imap, + b"Cannot login\x00" as *const u8 as *const libc::c_char, + r, + ); + dc_log_event_seq( + (*imap).context, + 401i32, + &mut (*imap).log_connect_errors as *mut libc::c_int, + b"%s\x00" as *const u8 as *const libc::c_char, + msg, + ); + free(msg as *mut libc::c_void); + } else { + dc_log_event( + (*imap).context, + 102i32, + 0i32, + b"IMAP-login as %s ok.\x00" as *const u8 as *const libc::c_char, + (*imap).imap_user, + ); + success = 1i32 + } + } + } + } + } + if success == 0i32 { + unsetup_handle(imap); + } + (*imap).should_reconnect = 0i32; + return success; +} +unsafe extern "C" 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 { + 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; +} +#[no_mangle] +pub unsafe extern "C" fn dc_imap_is_error( + mut imap: *mut dc_imap_t, + mut code: libc::c_int, +) -> libc::c_int { + if code == MAILIMAP_NO_ERROR as libc::c_int + || code == MAILIMAP_NO_ERROR_AUTHENTICATED as libc::c_int + || code == MAILIMAP_NO_ERROR_NON_AUTHENTICATED as libc::c_int + { + return 0i32; + } + if code == MAILIMAP_ERROR_STREAM as libc::c_int || code == MAILIMAP_ERROR_PARSE as libc::c_int { + dc_log_info( + (*imap).context, + 0i32, + b"IMAP stream lost; we\'ll reconnect soon.\x00" as *const u8 as *const libc::c_char, + ); + (*imap).should_reconnect = 1i32 + } + return 1i32; +} +#[no_mangle] +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); +} +#[no_mangle] +pub unsafe extern "C" 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; +} +#[no_mangle] +pub unsafe extern "C" 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 extern "C" fn fetch_from_single_folder( + mut imap: *mut dc_imap_t, + mut folder: *const libc::c_char, +) -> libc::c_int { + let mut current_block: u64; + let mut r: libc::c_int = 0; + let mut uidvalidity: uint32_t = 0i32 as uint32_t; + let mut lastseenuid: uint32_t = 0i32 as uint32_t; + let mut new_lastseenuid: uint32_t = 0i32 as uint32_t; + let mut fetch_result: *mut clist = 0 as *mut clist; + let mut read_cnt: size_t = 0i32 as size_t; + let mut read_errors: size_t = 0i32 as size_t; + let mut cur: *mut clistiter = 0 as *mut clistiter; + let mut set: *mut mailimap_set = 0 as *mut mailimap_set; + if !imap.is_null() { + if (*imap).etpan.is_null() { + dc_log_info( + (*imap).context, + 0i32, + b"Cannot fetch from \"%s\" - not connected.\x00" as *const u8 + as *const libc::c_char, + folder, + ); + } else if select_folder(imap, folder) == 0i32 { + dc_log_warning( + (*imap).context, + 0i32, + b"Cannot select folder %s for fetching.\x00" as *const u8 as *const libc::c_char, + folder, + ); + } else { + get_config_lastseenuid(imap, folder, &mut uidvalidity, &mut lastseenuid); + if uidvalidity != (*(*(*imap).etpan).imap_selection_info).sel_uidvalidity { + /* first time this folder is selected or UIDVALIDITY has changed, init lastseenuid and save it to config */ + if (*(*(*imap).etpan).imap_selection_info).sel_uidvalidity <= 0i32 as libc::c_uint { + dc_log_error( + (*imap).context, + 0i32, + b"Cannot get UIDVALIDITY for folder \"%s\".\x00" as *const u8 + as *const libc::c_char, + folder, + ); + current_block = 17288151659885296046; + } else { + if 0 != (*(*(*imap).etpan).imap_selection_info).sel_has_exists() { + if (*(*(*imap).etpan).imap_selection_info).sel_exists + <= 0i32 as libc::c_uint + { + dc_log_info( + (*imap).context, + 0i32, + b"Folder \"%s\" is empty.\x00" as *const u8 as *const libc::c_char, + folder, + ); + if (*(*(*imap).etpan).imap_selection_info).sel_exists + == 0i32 as libc::c_uint + { + set_config_lastseenuid( + imap, + folder, + (*(*(*imap).etpan).imap_selection_info).sel_uidvalidity, + 0i32 as uint32_t, + ); + } + current_block = 17288151659885296046; + } else { + set = mailimap_set_new_single( + (*(*(*imap).etpan).imap_selection_info).sel_exists, + ); + current_block = 11057878835866523405; + } + } else { + dc_log_info( + (*imap).context, + 0i32, + b"EXISTS is missing for folder \"%s\", using fallback.\x00" as *const u8 + as *const libc::c_char, + folder, + ); + set = mailimap_set_new_single(0i32 as uint32_t); + current_block = 11057878835866523405; + } + match current_block { + 17288151659885296046 => {} + _ => { + r = mailimap_fetch( + (*imap).etpan, + set, + (*imap).fetch_type_prefetch, + &mut fetch_result, + ); + if !set.is_null() { + mailimap_set_free(set); + set = 0 as *mut mailimap_set + } + if 0 != dc_imap_is_error(imap, r) || fetch_result.is_null() { + fetch_result = 0 as *mut clist; + dc_log_info( + (*imap).context, + 0i32, + b"No result returned for folder \"%s\".\x00" as *const u8 + as *const libc::c_char, + folder, + ); + /* this might happen if the mailbox is empty an EXISTS does not work */ + current_block = 17288151659885296046; + } else { + cur = (*fetch_result).first; + if cur.is_null() { + dc_log_info( + (*imap).context, + 0i32, + b"Empty result returned for folder \"%s\".\x00" as *const u8 + as *const libc::c_char, + folder, + ); + /* this might happen if the mailbox is empty an EXISTS does not work */ + current_block = 17288151659885296046; + } else { + let mut msg_att: *mut mailimap_msg_att = (if !cur.is_null() { + (*cur).data + } else { + 0 as *mut libc::c_void + }) + as *mut mailimap_msg_att; + lastseenuid = peek_uid(msg_att); + if !fetch_result.is_null() { + mailimap_fetch_list_free(fetch_result); + fetch_result = 0 as *mut clist + } + if lastseenuid <= 0i32 as libc::c_uint { + dc_log_error( + (*imap).context, + 0i32, + b"Cannot get largest UID for folder \"%s\"\x00" + as *const u8 + as *const libc::c_char, + folder, + ); + current_block = 17288151659885296046; + } else { + if uidvalidity > 0i32 as libc::c_uint + && lastseenuid > 1i32 as libc::c_uint + { + lastseenuid = (lastseenuid as libc::c_uint) + .wrapping_sub(1i32 as libc::c_uint) + as uint32_t + as uint32_t + } + uidvalidity = + (*(*(*imap).etpan).imap_selection_info).sel_uidvalidity; + set_config_lastseenuid( + imap, + folder, + uidvalidity, + lastseenuid, + ); + dc_log_info( + (*imap).context, + 0i32, + b"lastseenuid initialized to %i for %s@%i\x00" + as *const u8 + as *const libc::c_char, + lastseenuid as libc::c_int, + folder, + uidvalidity as libc::c_int, + ); + current_block = 2516253395664191498; + } + } + } + } + } + } + } else { + current_block = 2516253395664191498; + } + match current_block { + 17288151659885296046 => {} + _ => { + set = mailimap_set_new_interval( + lastseenuid.wrapping_add(1i32 as libc::c_uint), + 0i32 as uint32_t, + ); + r = mailimap_uid_fetch( + (*imap).etpan, + set, + (*imap).fetch_type_prefetch, + &mut fetch_result, + ); + if !set.is_null() { + mailimap_set_free(set); + set = 0 as *mut mailimap_set + } + if 0 != dc_imap_is_error(imap, r) || fetch_result.is_null() { + fetch_result = 0 as *mut clist; + if r == MAILIMAP_ERROR_PROTOCOL as libc::c_int { + dc_log_info( + (*imap).context, + 0i32, + b"Folder \"%s\" is empty\x00" as *const u8 as *const libc::c_char, + folder, + ); + } else { + /* the folder is simply empty, this is no error */ + dc_log_warning( + (*imap).context, + 0i32, + b"Cannot fetch message list from folder \"%s\".\x00" as *const u8 + as *const libc::c_char, + folder, + ); + } + } else { + cur = (*fetch_result).first; + while !cur.is_null() { + let mut msg_att_0: *mut mailimap_msg_att = (if !cur.is_null() { + (*cur).data + } else { + 0 as *mut libc::c_void + }) + as *mut mailimap_msg_att; + let mut cur_uid: uint32_t = peek_uid(msg_att_0); + if cur_uid > lastseenuid { + let mut rfc724_mid: *mut libc::c_char = + unquote_rfc724_mid(peek_rfc724_mid(msg_att_0)); + read_cnt = read_cnt.wrapping_add(1); + if 0 == (*imap).precheck_imf.expect("non-null function pointer")( + imap, rfc724_mid, folder, cur_uid, + ) { + if fetch_single_msg(imap, folder, cur_uid) == 0i32 { + dc_log_info((*imap).context, 0i32, + b"Read error for message %s from \"%s\", trying over later.\x00" + as *const u8 as + *const libc::c_char, + rfc724_mid, folder); + read_errors = read_errors.wrapping_add(1) + } + } else { + dc_log_info( + (*imap).context, + 0i32, + b"Skipping message %s from \"%s\" by precheck.\x00" + as *const u8 + as *const libc::c_char, + rfc724_mid, + folder, + ); + } + if cur_uid > new_lastseenuid { + new_lastseenuid = cur_uid + } + free(rfc724_mid as *mut libc::c_void); + } + cur = if !cur.is_null() { + (*cur).next + } else { + 0 as *mut clistcell_s + } + } + if 0 == read_errors && new_lastseenuid > 0i32 as libc::c_uint { + set_config_lastseenuid(imap, folder, uidvalidity, new_lastseenuid); + } + } + } + } + } + } + /* done */ + if 0 != read_errors { + dc_log_warning( + (*imap).context, + 0i32, + b"%i mails read from \"%s\" with %i errors.\x00" as *const u8 as *const libc::c_char, + read_cnt as libc::c_int, + folder, + read_errors as libc::c_int, + ); + } else { + dc_log_info( + (*imap).context, + 0i32, + b"%i mails read from \"%s\".\x00" as *const u8 as *const libc::c_char, + read_cnt as libc::c_int, + folder, + ); + } + if !fetch_result.is_null() { + mailimap_fetch_list_free(fetch_result); + fetch_result = 0 as *mut clist + } + return read_cnt as libc::c_int; +} +unsafe extern "C" 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 extern "C" fn peek_rfc724_mid(mut msg_att: *mut mailimap_msg_att) -> *const libc::c_char { + if msg_att.is_null() { + return 0 as *const libc::c_char; + } + /* search the UID in a list of attributes returned by a FETCH command */ + let mut iter1: *mut clistiter = 0 as *mut clistiter; + iter1 = (*(*msg_att).att_list).first; + while !iter1.is_null() { + let mut item: *mut mailimap_msg_att_item = (if !iter1.is_null() { + (*iter1).data + } else { + 0 as *mut libc::c_void + }) as *mut mailimap_msg_att_item; + if !item.is_null() { + if (*item).att_type == MAILIMAP_MSG_ATT_ITEM_STATIC as libc::c_int { + if (*(*item).att_data.att_static).att_type + == MAILIMAP_MSG_ATT_ENVELOPE as libc::c_int + { + let mut env: *mut mailimap_envelope = + (*(*item).att_data.att_static).att_data.att_env; + if !env.is_null() && !(*env).env_message_id.is_null() { + return (*env).env_message_id; + } + } + } + } + iter1 = if !iter1.is_null() { + (*iter1).next + } else { + 0 as *mut clistcell_s + } + } + return 0 as *const libc::c_char; +} +unsafe extern "C" 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 extern "C" 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 extern "C" fn fetch_single_msg( + mut imap: *mut dc_imap_t, + mut folder: *const libc::c_char, + mut server_uid: uint32_t, +) -> libc::c_int { + let mut msg_att: *mut mailimap_msg_att = 0 as *mut mailimap_msg_att; + /* the function returns: + 0 the caller should try over again later + or 1 if the messages should be treated as received, the caller should not try to read the message again (even if no database entries are returned) */ + let mut msg_content: *mut libc::c_char = 0 as *mut libc::c_char; + let mut msg_bytes: size_t = 0i32 as size_t; + let mut r: libc::c_int = 0i32; + let mut retry_later: libc::c_int = 0i32; + let mut deleted: libc::c_int = 0i32; + let mut flags: uint32_t = 0i32 as uint32_t; + let mut fetch_result: *mut clist = 0 as *mut clist; + let mut cur: *mut clistiter = 0 as *mut clistiter; + if !imap.is_null() { + if !(*imap).etpan.is_null() { + let mut set: *mut mailimap_set = mailimap_set_new_single(server_uid); + r = mailimap_uid_fetch( + (*imap).etpan, + set, + (*imap).fetch_type_body, + &mut fetch_result, + ); + if !set.is_null() { + mailimap_set_free(set); + set = 0 as *mut mailimap_set + } + if 0 != dc_imap_is_error(imap, r) || fetch_result.is_null() { + fetch_result = 0 as *mut clist; + dc_log_warning( + (*imap).context, + 0i32, + b"Error #%i on fetching message #%i from folder \"%s\"; retry=%i.\x00" + as *const u8 as *const libc::c_char, + r as libc::c_int, + server_uid as libc::c_int, + folder, + (*imap).should_reconnect as libc::c_int, + ); + if 0 != (*imap).should_reconnect { + retry_later = 1i32 + } + } else { + /* this is an error that should be recovered; the caller should try over later to fetch the message again (if there is no such message, we simply get an empty result) */ + cur = (*fetch_result).first; + if cur.is_null() { + dc_log_warning( + (*imap).context, + 0i32, + b"Message #%i does not exist in folder \"%s\".\x00" as *const u8 + as *const libc::c_char, + server_uid as libc::c_int, + folder, + ); + } else { + /* server response is fine, however, there is no such message, do not try to fetch the message again */ + msg_att = (if !cur.is_null() { + (*cur).data + } else { + 0 as *mut libc::c_void + }) as *mut mailimap_msg_att; + peek_body( + msg_att, + &mut msg_content, + &mut msg_bytes, + &mut flags, + &mut deleted, + ); + if !(msg_content.is_null() + || msg_bytes <= 0i32 as libc::c_ulong + || 0 != deleted) + { + /* dc_log_warning(imap->context, 0, "Message #%i in folder \"%s\" is empty or deleted.", (int)server_uid, folder); -- this is a quite usual situation, do not print a warning */ + (*imap).receive_imf.expect("non-null function pointer")( + imap, + msg_content, + msg_bytes, + folder, + server_uid, + flags, + ); + } + } + } + } + } + if !fetch_result.is_null() { + mailimap_fetch_list_free(fetch_result); + fetch_result = 0 as *mut clist + } + return if 0 != retry_later { 0i32 } else { 1i32 }; +} +unsafe extern "C" fn peek_body( + mut msg_att: *mut mailimap_msg_att, + mut p_msg: *mut *mut libc::c_char, + mut p_msg_bytes: *mut size_t, + mut flags: *mut uint32_t, + mut deleted: *mut libc::c_int, +) { + if msg_att.is_null() { + return; + } + /* search body & Co. in a list of attributes returned by a FETCH command */ + let mut iter1: *mut clistiter = 0 as *mut clistiter; + let mut iter2: *mut clistiter = 0 as *mut clistiter; + iter1 = (*(*msg_att).att_list).first; + while !iter1.is_null() { + let mut item: *mut mailimap_msg_att_item = (if !iter1.is_null() { + (*iter1).data + } else { + 0 as *mut libc::c_void + }) as *mut mailimap_msg_att_item; + if !item.is_null() { + if (*item).att_type == MAILIMAP_MSG_ATT_ITEM_DYNAMIC as libc::c_int { + if !(*(*item).att_data.att_dyn).att_list.is_null() { + iter2 = (*(*(*item).att_data.att_dyn).att_list).first; + while !iter2.is_null() { + let mut flag_fetch: *mut mailimap_flag_fetch = (if !iter2.is_null() { + (*iter2).data + } else { + 0 as *mut libc::c_void + }) + as *mut mailimap_flag_fetch; + if !flag_fetch.is_null() + && (*flag_fetch).fl_type == MAILIMAP_FLAG_FETCH_OTHER as libc::c_int + { + let mut flag: *mut mailimap_flag = (*flag_fetch).fl_flag; + if !flag.is_null() { + if (*flag).fl_type == MAILIMAP_FLAG_SEEN as libc::c_int { + *flags = (*flags as libc::c_long | 0x1i64) as uint32_t + } else if (*flag).fl_type == MAILIMAP_FLAG_DELETED as libc::c_int { + *deleted = 1i32 + } + } + } + iter2 = if !iter2.is_null() { + (*iter2).next + } else { + 0 as *mut clistcell_s + } + } + } + } else if (*item).att_type == MAILIMAP_MSG_ATT_ITEM_STATIC as libc::c_int { + if (*(*item).att_data.att_static).att_type + == MAILIMAP_MSG_ATT_BODY_SECTION as libc::c_int + { + *p_msg = + (*(*(*item).att_data.att_static).att_data.att_body_section).sec_body_part; + *p_msg_bytes = + (*(*(*item).att_data.att_static).att_data.att_body_section).sec_length + } + } + } + iter1 = if !iter1.is_null() { + (*iter1).next + } else { + 0 as *mut clistcell_s + } + } +} +unsafe extern "C" 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 extern "C" fn select_folder( + mut imap: *mut dc_imap_t, + mut folder: *const libc::c_char, +) -> libc::c_int { + if imap.is_null() { + return 0i32; + } + if (*imap).etpan.is_null() { + *(*imap).selected_folder.offset(0isize) = 0i32 as libc::c_char; + (*imap).selected_folder_needs_expunge = 0i32; + return 0i32; + } + if !folder.is_null() + && 0 != *folder.offset(0isize) as libc::c_int + && strcmp((*imap).selected_folder, folder) == 0i32 + { + return 1i32; + } + if 0 != (*imap).selected_folder_needs_expunge { + if 0 != *(*imap).selected_folder.offset(0isize) { + dc_log_info( + (*imap).context, + 0i32, + b"Expunge messages in \"%s\".\x00" as *const u8 as *const libc::c_char, + (*imap).selected_folder, + ); + mailimap_close((*imap).etpan); + } + (*imap).selected_folder_needs_expunge = 0i32 + } + if !folder.is_null() { + let mut r: libc::c_int = mailimap_select((*imap).etpan, folder); + if 0 != dc_imap_is_error(imap, r) || (*(*imap).etpan).imap_selection_info.is_null() { + dc_log_info( + (*imap).context, + 0i32, + b"Cannot select folder; code=%i, imap_response=%s\x00" as *const u8 + as *const libc::c_char, + r, + if !(*(*imap).etpan).imap_response.is_null() { + (*(*imap).etpan).imap_response + } else { + b"\x00" as *const u8 as *const libc::c_char + }, + ); + *(*imap).selected_folder.offset(0isize) = 0i32 as libc::c_char; + return 0i32; + } + } + free((*imap).selected_folder as *mut libc::c_void); + (*imap).selected_folder = dc_strdup(folder); + return 1i32; +} +#[no_mangle] +pub unsafe extern "C" fn dc_imap_idle(mut imap: *mut dc_imap_t) { + let mut current_block: u64; + let mut r: libc::c_int = 0i32; + let mut r2: libc::c_int = 0i32; + if !imap.is_null() { + if 0 != (*imap).can_idle { + setup_handle_if_needed(imap); + if (*imap).idle_set_up == 0i32 + && !(*imap).etpan.is_null() + && !(*(*imap).etpan).imap_stream.is_null() + { + r = mailstream_setup_idle((*(*imap).etpan).imap_stream); + if 0 != dc_imap_is_error(imap, r) { + dc_log_warning( + (*imap).context, + 0i32, + b"IMAP-IDLE: Cannot setup.\x00" as *const u8 as *const libc::c_char, + ); + fake_idle(imap); + current_block = 14832935472441733737; + } else { + (*imap).idle_set_up = 1i32; + current_block = 17965632435239708295; + } + } else { + current_block = 17965632435239708295; + } + match current_block { + 14832935472441733737 => {} + _ => { + if 0 == (*imap).idle_set_up || 0 == select_folder(imap, (*imap).watch_folder) { + dc_log_warning( + (*imap).context, + 0i32, + b"IMAP-IDLE not setup.\x00" as *const u8 as *const libc::c_char, + ); + fake_idle(imap); + } else { + r = mailimap_idle((*imap).etpan); + if 0 != dc_imap_is_error(imap, r) { + dc_log_warning( + (*imap).context, + 0i32, + b"IMAP-IDLE: Cannot start.\x00" as *const u8 as *const libc::c_char, + ); + fake_idle(imap); + } else { + r = mailstream_wait_idle((*(*imap).etpan).imap_stream, 23i32 * 60i32); + r2 = mailimap_idle_done((*imap).etpan); + if r == MAILSTREAM_IDLE_ERROR as libc::c_int + || r == MAILSTREAM_IDLE_CANCELLED as libc::c_int + { + dc_log_info((*imap).context, 0i32, + b"IMAP-IDLE wait cancelled, r=%i, r2=%i; we\'ll reconnect soon.\x00" + as *const u8 as + *const libc::c_char, r, r2); + (*imap).should_reconnect = 1i32 + } else if r == MAILSTREAM_IDLE_INTERRUPTED as libc::c_int { + dc_log_info( + (*imap).context, + 0i32, + b"IMAP-IDLE interrupted.\x00" as *const u8 + as *const libc::c_char, + ); + } else if r == MAILSTREAM_IDLE_HASDATA as libc::c_int { + dc_log_info( + (*imap).context, + 0i32, + b"IMAP-IDLE has data.\x00" as *const u8 as *const libc::c_char, + ); + } else if r == MAILSTREAM_IDLE_TIMEOUT as libc::c_int { + dc_log_info( + (*imap).context, + 0i32, + b"IMAP-IDLE timeout.\x00" as *const u8 as *const libc::c_char, + ); + } else { + dc_log_warning( + (*imap).context, + 0i32, + b"IMAP-IDLE returns unknown value r=%i, r2=%i.\x00" as *const u8 + as *const libc::c_char, + r, + r2, + ); + } + } + } + } + } + } else { + fake_idle(imap); + } + }; +} +unsafe extern "C" fn fake_idle(mut imap: *mut dc_imap_t) { + /* Idle using timeouts. This is also needed if we're not yet configured - + in this case, we're waiting for a configure job */ + let mut fake_idle_start_time: time_t = time(0 as *mut time_t); + let mut seconds_to_wait: time_t = 0i32 as time_t; + dc_log_info( + (*imap).context, + 0i32, + b"IMAP-fake-IDLEing...\x00" as *const u8 as *const libc::c_char, + ); + let mut do_fake_idle: libc::c_int = 1i32; + while 0 != do_fake_idle { + seconds_to_wait = + (if time(0 as *mut time_t) - fake_idle_start_time < (3i32 * 60i32) as libc::c_long { + 5i32 + } else { + 60i32 + }) as time_t; + pthread_mutex_lock(&mut (*imap).watch_condmutex); + let mut r: libc::c_int = 0i32; + let mut wakeup_at: timespec = timespec { + tv_sec: 0, + tv_nsec: 0, + }; + memset( + &mut wakeup_at as *mut timespec as *mut libc::c_void, + 0i32, + ::std::mem::size_of::() as libc::c_ulong, + ); + wakeup_at.tv_sec = time(0 as *mut time_t) + seconds_to_wait; + while (*imap).watch_condflag == 0i32 && r == 0i32 { + r = pthread_cond_timedwait( + &mut (*imap).watch_cond, + &mut (*imap).watch_condmutex, + &mut wakeup_at, + ); + if 0 != (*imap).watch_condflag { + do_fake_idle = 0i32 + } + } + (*imap).watch_condflag = 0i32; + pthread_mutex_unlock(&mut (*imap).watch_condmutex); + if do_fake_idle == 0i32 { + return; + } + if 0 != setup_handle_if_needed(imap) { + if 0 != fetch_from_single_folder(imap, (*imap).watch_folder) { + do_fake_idle = 0i32 + } + } else { + fake_idle_start_time = 0i32 as time_t + } + } +} +#[no_mangle] +pub unsafe extern "C" 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); +} +#[no_mangle] +pub unsafe extern "C" fn dc_imap_move( + mut imap: *mut dc_imap_t, + mut folder: *const libc::c_char, + mut uid: uint32_t, + mut dest_folder: *const libc::c_char, + mut dest_uid: *mut uint32_t, +) -> dc_imap_res { + let mut current_block: u64; + let mut res: dc_imap_res = DC_RETRY_LATER; + let mut r: libc::c_int = 0i32; + let mut set: *mut mailimap_set = mailimap_set_new_single(uid); + let mut res_uid: uint32_t = 0i32 as uint32_t; + let mut res_setsrc: *mut mailimap_set = 0 as *mut mailimap_set; + let mut res_setdest: *mut mailimap_set = 0 as *mut mailimap_set; + if imap.is_null() + || folder.is_null() + || uid == 0i32 as libc::c_uint + || dest_folder.is_null() + || dest_uid.is_null() + || set.is_null() + { + res = DC_FAILED + } else if strcasecmp(folder, dest_folder) == 0i32 { + dc_log_info( + (*imap).context, + 0i32, + b"Skip moving message; message %s/%i is already in %s...\x00" as *const u8 + as *const libc::c_char, + folder, + uid as libc::c_int, + dest_folder, + ); + res = DC_ALREADY_DONE + } else { + dc_log_info( + (*imap).context, + 0i32, + b"Moving message %s/%i to %s...\x00" as *const u8 as *const libc::c_char, + folder, + uid as libc::c_int, + dest_folder, + ); + if select_folder(imap, folder) == 0i32 { + dc_log_warning( + (*imap).context, + 0i32, + b"Cannot select folder %s for moving message.\x00" as *const u8 + as *const libc::c_char, + folder, + ); + } else { + r = mailimap_uidplus_uid_move( + (*imap).etpan, + set, + dest_folder, + &mut res_uid, + &mut res_setsrc, + &mut res_setdest, + ); + if 0 != dc_imap_is_error(imap, r) { + if !res_setsrc.is_null() { + mailimap_set_free(res_setsrc); + res_setsrc = 0 as *mut mailimap_set + } + if !res_setdest.is_null() { + mailimap_set_free(res_setdest); + res_setdest = 0 as *mut mailimap_set + } + dc_log_info( + (*imap).context, + 0i32, + b"Cannot move message, fallback to COPY/DELETE %s/%i to %s...\x00" as *const u8 + as *const libc::c_char, + folder, + uid as libc::c_int, + dest_folder, + ); + r = mailimap_uidplus_uid_copy( + (*imap).etpan, + set, + dest_folder, + &mut res_uid, + &mut res_setsrc, + &mut res_setdest, + ); + if 0 != dc_imap_is_error(imap, r) { + dc_log_info( + (*imap).context, + 0i32, + b"Cannot copy message.\x00" as *const u8 as *const libc::c_char, + ); + current_block = 14415637129417834392; + } else { + if add_flag(imap, uid, mailimap_flag_new_deleted()) == 0i32 { + dc_log_warning( + (*imap).context, + 0i32, + b"Cannot mark message as \"Deleted\".\x00" as *const u8 + as *const libc::c_char, + ); + } + (*imap).selected_folder_needs_expunge = 1i32; + current_block = 1538046216550696469; + } + } else { + current_block = 1538046216550696469; + } + match current_block { + 14415637129417834392 => {} + _ => { + if !res_setdest.is_null() { + let mut cur: *mut clistiter = (*(*res_setdest).set_list).first; + if !cur.is_null() { + let mut item: *mut mailimap_set_item = 0 as *mut mailimap_set_item; + item = (if !cur.is_null() { + (*cur).data + } else { + 0 as *mut libc::c_void + }) as *mut mailimap_set_item; + *dest_uid = (*item).set_first + } + } + res = DC_SUCCESS + } + } + } + } + if !set.is_null() { + mailimap_set_free(set); + set = 0 as *mut mailimap_set + } + if !res_setsrc.is_null() { + mailimap_set_free(res_setsrc); + res_setsrc = 0 as *mut mailimap_set + } + if !res_setdest.is_null() { + mailimap_set_free(res_setdest); + res_setdest = 0 as *mut mailimap_set + } + return (if res as libc::c_uint == DC_RETRY_LATER as libc::c_int as libc::c_uint { + (if 0 != (*imap).should_reconnect { + DC_RETRY_LATER as libc::c_int + } else { + DC_FAILED as libc::c_int + }) as libc::c_uint + } else { + res as libc::c_uint + }) as dc_imap_res; +} +unsafe extern "C" fn add_flag( + mut imap: *mut dc_imap_t, + mut server_uid: uint32_t, + mut flag: *mut mailimap_flag, +) -> libc::c_int { + let mut r: libc::c_int = 0i32; + let mut flag_list: *mut mailimap_flag_list = 0 as *mut mailimap_flag_list; + let mut store_att_flags: *mut mailimap_store_att_flags = 0 as *mut mailimap_store_att_flags; + let mut set: *mut mailimap_set = mailimap_set_new_single(server_uid); + if !(imap.is_null() || (*imap).etpan.is_null()) { + flag_list = mailimap_flag_list_new_empty(); + mailimap_flag_list_add(flag_list, flag); + store_att_flags = mailimap_store_att_flags_new_add_flags(flag_list); + r = mailimap_uid_store((*imap).etpan, set, store_att_flags); + 0 != dc_imap_is_error(imap, r); + } + if !store_att_flags.is_null() { + mailimap_store_att_flags_free(store_att_flags); + } + if !set.is_null() { + mailimap_set_free(set); + set = 0 as *mut mailimap_set + } + return if 0 != (*imap).should_reconnect { + 0i32 + } else { + 1i32 + }; +} +#[no_mangle] +pub unsafe extern "C" 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; +} +#[no_mangle] +pub unsafe extern "C" fn dc_imap_set_mdnsent( + mut imap: *mut dc_imap_t, + mut folder: *const libc::c_char, + mut uid: uint32_t, +) -> dc_imap_res { + let mut can_create_flag: libc::c_int = 0; + let mut current_block: u64; + // returns 0=job should be retried later, 1=job done, 2=job done and flag just set + let mut res: dc_imap_res = DC_RETRY_LATER; + let mut set: *mut mailimap_set = mailimap_set_new_single(uid); + let mut fetch_result: *mut clist = 0 as *mut clist; + if imap.is_null() || folder.is_null() || uid == 0i32 as libc::c_uint || set.is_null() { + res = DC_FAILED + } else if !(*imap).etpan.is_null() { + dc_log_info( + (*imap).context, + 0i32, + b"Marking message %s/%i as $MDNSent...\x00" as *const u8 as *const libc::c_char, + folder, + uid as libc::c_int, + ); + if select_folder(imap, folder) == 0i32 { + dc_log_warning( + (*imap).context, + 0i32, + b"Cannot select folder %s for setting $MDNSent flag.\x00" as *const u8 + as *const libc::c_char, + folder, + ); + } else { + /* Check if the folder can handle the `$MDNSent` flag (see RFC 3503). If so, and not set: set the flags and return this information. + If the folder cannot handle the `$MDNSent` flag, we risk duplicated MDNs; it's up to the receiving MUA to handle this then (eg. Delta Chat has no problem with this). */ + can_create_flag = 0i32; + if !(*(*imap).etpan).imap_selection_info.is_null() + && !(*(*(*imap).etpan).imap_selection_info) + .sel_perm_flags + .is_null() + { + let mut iter: *mut clistiter = 0 as *mut clistiter; + iter = (*(*(*(*imap).etpan).imap_selection_info).sel_perm_flags).first; + while !iter.is_null() { + let mut fp: *mut mailimap_flag_perm = (if !iter.is_null() { + (*iter).data + } else { + 0 as *mut libc::c_void + }) + as *mut mailimap_flag_perm; + if !fp.is_null() { + if (*fp).fl_type == MAILIMAP_FLAG_PERM_ALL as libc::c_int { + can_create_flag = 1i32; + break; + } else if (*fp).fl_type == MAILIMAP_FLAG_PERM_FLAG as libc::c_int + && !(*fp).fl_flag.is_null() + { + let mut fl: *mut mailimap_flag = (*fp).fl_flag as *mut mailimap_flag; + if (*fl).fl_type == MAILIMAP_FLAG_KEYWORD as libc::c_int + && !(*fl).fl_data.fl_keyword.is_null() + && strcmp( + (*fl).fl_data.fl_keyword, + b"$MDNSent\x00" as *const u8 as *const libc::c_char, + ) == 0i32 + { + can_create_flag = 1i32; + break; + } + } + } + iter = if !iter.is_null() { + (*iter).next + } else { + 0 as *mut clistcell_s + } + } + } + if 0 != can_create_flag { + let mut r: libc::c_int = mailimap_uid_fetch( + (*imap).etpan, + set, + (*imap).fetch_type_flags, + &mut fetch_result, + ); + if 0 != dc_imap_is_error(imap, r) || fetch_result.is_null() { + fetch_result = 0 as *mut clist + } else { + let mut cur: *mut clistiter = (*fetch_result).first; + if !cur.is_null() { + if 0 != peek_flag_keyword( + (if !cur.is_null() { + (*cur).data + } else { + 0 as *mut libc::c_void + }) as *mut mailimap_msg_att, + b"$MDNSent\x00" as *const u8 as *const libc::c_char, + ) { + res = DC_ALREADY_DONE; + current_block = 14832935472441733737; + } else if add_flag( + imap, + uid, + mailimap_flag_new_flag_keyword(dc_strdup( + b"$MDNSent\x00" as *const u8 as *const libc::c_char, + )), + ) == 0i32 + { + current_block = 17044610252497760460; + } else { + res = DC_SUCCESS; + current_block = 14832935472441733737; + } + match current_block { + 17044610252497760460 => {} + _ => { + dc_log_info( + (*imap).context, + 0i32, + if res as libc::c_uint + == DC_SUCCESS as libc::c_int as libc::c_uint + { + b"$MDNSent just set and MDN will be sent.\x00" as *const u8 + as *const libc::c_char + } else { + b"$MDNSent already set and MDN already sent.\x00" + as *const u8 + as *const libc::c_char + }, + ); + } + } + } + } + } else { + res = DC_SUCCESS; + dc_log_info( + (*imap).context, + 0i32, + b"Cannot store $MDNSent flags, risk sending duplicate MDN.\x00" as *const u8 + as *const libc::c_char, + ); + } + } + } + if !set.is_null() { + mailimap_set_free(set); + set = 0 as *mut mailimap_set + } + if !fetch_result.is_null() { + mailimap_fetch_list_free(fetch_result); + fetch_result = 0 as *mut clist + } + return (if res as libc::c_uint == DC_RETRY_LATER as libc::c_int as libc::c_uint { + (if 0 != (*imap).should_reconnect { + DC_RETRY_LATER as libc::c_int + } else { + DC_FAILED as libc::c_int + }) as libc::c_uint + } else { + res as libc::c_uint + }) as dc_imap_res; +} +unsafe extern "C" fn peek_flag_keyword( + mut msg_att: *mut mailimap_msg_att, + mut flag_keyword: *const libc::c_char, +) -> libc::c_int { + if msg_att.is_null() || (*msg_att).att_list.is_null() || flag_keyword.is_null() { + return 0i32; + } + let mut iter1: *mut clistiter = 0 as *mut clistiter; + let mut iter2: *mut clistiter = 0 as *mut clistiter; + iter1 = (*(*msg_att).att_list).first; + while !iter1.is_null() { + let mut item: *mut mailimap_msg_att_item = (if !iter1.is_null() { + (*iter1).data + } else { + 0 as *mut libc::c_void + }) as *mut mailimap_msg_att_item; + if !item.is_null() { + if (*item).att_type == MAILIMAP_MSG_ATT_ITEM_DYNAMIC as libc::c_int { + if !(*(*item).att_data.att_dyn).att_list.is_null() { + iter2 = (*(*(*item).att_data.att_dyn).att_list).first; + while !iter2.is_null() { + let mut flag_fetch: *mut mailimap_flag_fetch = (if !iter2.is_null() { + (*iter2).data + } else { + 0 as *mut libc::c_void + }) + as *mut mailimap_flag_fetch; + if !flag_fetch.is_null() + && (*flag_fetch).fl_type == MAILIMAP_FLAG_FETCH_OTHER as libc::c_int + { + let mut flag: *mut mailimap_flag = (*flag_fetch).fl_flag; + if !flag.is_null() { + if (*flag).fl_type == MAILIMAP_FLAG_KEYWORD as libc::c_int + && !(*flag).fl_data.fl_keyword.is_null() + && strcmp((*flag).fl_data.fl_keyword, flag_keyword) == 0i32 + { + return 1i32; + } + } + } + iter2 = if !iter2.is_null() { + (*iter2).next + } else { + 0 as *mut clistcell_s + } + } + } + } + } + iter1 = if !iter1.is_null() { + (*iter1).next + } else { + 0 as *mut clistcell_s + } + } + return 0i32; +} +/* only returns 0 on connection problems; we should try later again in this case */ +#[no_mangle] +pub unsafe extern "C" fn dc_imap_delete_msg( + mut imap: *mut dc_imap_t, + mut rfc724_mid: *const libc::c_char, + mut folder: *const libc::c_char, + mut server_uid: uint32_t, +) -> libc::c_int { + let mut success: libc::c_int = 0i32; + let mut r: libc::c_int = 0i32; + let mut fetch_result: *mut clist = 0 as *mut clist; + let mut is_rfc724_mid: *mut libc::c_char = 0 as *mut libc::c_char; + let mut new_folder: *mut libc::c_char = 0 as *mut libc::c_char; + if imap.is_null() + || rfc724_mid.is_null() + || folder.is_null() + || *folder.offset(0isize) as libc::c_int == 0i32 + || server_uid == 0i32 as libc::c_uint + { + success = 1i32 + } else { + dc_log_info( + (*imap).context, + 0i32, + b"Marking message \"%s\", %s/%i for deletion...\x00" as *const u8 + as *const libc::c_char, + rfc724_mid, + folder, + server_uid as libc::c_int, + ); + if select_folder(imap, folder) == 0i32 { + dc_log_warning( + (*imap).context, + 0i32, + b"Cannot select folder %s for deleting message.\x00" as *const u8 + as *const libc::c_char, + folder, + ); + } else { + let mut cur: *mut clistiter = 0 as *mut clistiter; + let mut is_quoted_rfc724_mid: *const libc::c_char = 0 as *const libc::c_char; + let mut set: *mut mailimap_set = mailimap_set_new_single(server_uid); + r = mailimap_uid_fetch( + (*imap).etpan, + set, + (*imap).fetch_type_prefetch, + &mut fetch_result, + ); + if !set.is_null() { + mailimap_set_free(set); + set = 0 as *mut mailimap_set + } + if 0 != dc_imap_is_error(imap, r) || fetch_result.is_null() { + fetch_result = 0 as *mut clist; + dc_log_warning( + (*imap).context, + 0i32, + b"Cannot delete on IMAP, %s/%i not found.\x00" as *const u8 + as *const libc::c_char, + folder, + server_uid as libc::c_int, + ); + server_uid = 0i32 as uint32_t + } + cur = (*fetch_result).first; + if cur.is_null() + || { + is_quoted_rfc724_mid = peek_rfc724_mid( + (if !cur.is_null() { + (*cur).data + } else { + 0 as *mut libc::c_void + }) as *mut mailimap_msg_att, + ); + is_quoted_rfc724_mid.is_null() + } + || { + is_rfc724_mid = unquote_rfc724_mid(is_quoted_rfc724_mid); + is_rfc724_mid.is_null() + } + || strcmp(is_rfc724_mid, rfc724_mid) != 0i32 + { + dc_log_warning( + (*imap).context, + 0i32, + b"Cannot delete on IMAP, %s/%i does not match %s.\x00" as *const u8 + as *const libc::c_char, + folder, + server_uid as libc::c_int, + rfc724_mid, + ); + server_uid = 0i32 as uint32_t + } + /* mark the message for deletion */ + if add_flag(imap, server_uid, mailimap_flag_new_deleted()) == 0i32 { + dc_log_warning( + (*imap).context, + 0i32, + b"Cannot mark message as \"Deleted\".\x00" as *const u8 as *const libc::c_char, + ); + } else { + (*imap).selected_folder_needs_expunge = 1i32; + success = 1i32 + } + } + } + if !fetch_result.is_null() { + mailimap_fetch_list_free(fetch_result); + fetch_result = 0 as *mut clist + } + free(is_rfc724_mid as *mut libc::c_void); + free(new_folder as *mut libc::c_void); + return if 0 != success { + 1i32 + } else { + dc_imap_is_connected(imap) + }; +} diff --git a/src/dc_imex.rs b/src/dc_imex.rs new file mode 100644 index 000000000..045c67da5 --- /dev/null +++ b/src/dc_imex.rs @@ -0,0 +1,2816 @@ +use c2rust_bitfields::BitfieldStruct; +use libc; +extern "C" { + pub type _telldir; + pub type mailstream_cancel; + pub type sqlite3; + pub type sqlite3_stmt; + #[no_mangle] + fn closedir(_: *mut DIR) -> libc::c_int; + #[no_mangle] + fn opendir(_: *const libc::c_char) -> *mut DIR; + #[no_mangle] + fn readdir(_: *mut DIR) -> *mut dirent; + #[no_mangle] + fn sleep(_: libc::c_uint) -> libc::c_uint; + #[no_mangle] + fn free(_: *mut libc::c_void); + #[no_mangle] + fn RAND_bytes(buf: *mut libc::c_uchar, num: libc::c_int) -> libc::c_int; + #[no_mangle] + fn RAND_pseudo_bytes(buf: *mut libc::c_uchar, num: libc::c_int) -> libc::c_int; + #[no_mangle] + fn mmap_string_unref(str: *mut libc::c_char) -> libc::c_int; + #[no_mangle] + fn strcmp(_: *const libc::c_char, _: *const libc::c_char) -> libc::c_int; + #[no_mangle] + fn strlen(_: *const libc::c_char) -> libc::c_ulong; + #[no_mangle] + fn strncmp(_: *const libc::c_char, _: *const libc::c_char, _: libc::c_ulong) -> libc::c_int; + #[no_mangle] + fn strncpy(_: *mut libc::c_char, _: *const libc::c_char, _: libc::c_ulong) + -> *mut libc::c_char; + #[no_mangle] + fn strstr(_: *const libc::c_char, _: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn strndup(_: *const libc::c_char, _: libc::c_ulong) -> *mut libc::c_char; + #[no_mangle] + fn localtime(_: *const time_t) -> *mut tm; + #[no_mangle] + fn strftime(_: *mut libc::c_char, _: size_t, _: *const libc::c_char, _: *const tm) -> size_t; + #[no_mangle] + fn time(_: *mut time_t) -> time_t; + #[no_mangle] + 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; + #[no_mangle] + fn dc_is_configured(_: *const dc_context_t) -> libc::c_int; + #[no_mangle] + fn dc_create_chat_by_contact_id(_: *mut dc_context_t, contact_id: uint32_t) -> uint32_t; + #[no_mangle] + fn dc_send_msg(_: *mut dc_context_t, chat_id: uint32_t, _: *mut dc_msg_t) -> uint32_t; + #[no_mangle] + fn dc_get_msg(_: *mut dc_context_t, msg_id: uint32_t) -> *mut dc_msg_t; + /* library-private */ + #[no_mangle] + fn dc_param_new() -> *mut dc_param_t; + #[no_mangle] + fn dc_param_unref(_: *mut dc_param_t); + #[no_mangle] + fn dc_job_add( + _: *mut dc_context_t, + action: libc::c_int, + foreign_id: libc::c_int, + param: *const libc::c_char, + delay: libc::c_int, + ); + #[no_mangle] + fn dc_job_kill_action(_: *mut dc_context_t, action: libc::c_int); + #[no_mangle] + fn dc_param_set(_: *mut dc_param_t, key: libc::c_int, value: *const libc::c_char); + #[no_mangle] + fn dc_param_set_int(_: *mut dc_param_t, key: libc::c_int, value: int32_t); + #[no_mangle] + fn dc_sqlite3_unref(_: *mut dc_sqlite3_t); + #[no_mangle] + fn dc_sqlite3_get_config_int( + _: *mut dc_sqlite3_t, + key: *const libc::c_char, + def: int32_t, + ) -> int32_t; + #[no_mangle] + fn dc_sqlite3_open( + _: *mut dc_sqlite3_t, + dbfile: *const libc::c_char, + flags: libc::c_int, + ) -> libc::c_int; + #[no_mangle] + fn dc_sqlite3_new(_: *mut dc_context_t) -> *mut dc_sqlite3_t; + #[no_mangle] + fn dc_mprintf(format: *const libc::c_char, _: ...) -> *mut libc::c_char; + #[no_mangle] + fn dc_log_info(_: *mut dc_context_t, data1: libc::c_int, msg: *const libc::c_char, _: ...); + #[no_mangle] + fn dc_loginparam_new() -> *mut dc_loginparam_t; + #[no_mangle] + fn dc_loginparam_unref(_: *mut dc_loginparam_t); + #[no_mangle] + fn dc_loginparam_read( + _: *mut dc_loginparam_t, + _: *mut dc_sqlite3_t, + prefix: *const libc::c_char, + ); + #[no_mangle] + fn dc_free_ongoing(_: *mut dc_context_t); + #[no_mangle] + fn dc_msg_unref(_: *mut dc_msg_t); + #[no_mangle] + fn dc_msg_is_sent(_: *const dc_msg_t) -> libc::c_int; + #[no_mangle] + fn dc_msg_new_untyped(_: *mut dc_context_t) -> *mut dc_msg_t; + #[no_mangle] + fn dc_write_file( + _: *mut dc_context_t, + pathNfilename: *const libc::c_char, + buf: *const libc::c_void, + buf_bytes: size_t, + ) -> libc::c_int; + #[no_mangle] + fn dc_get_fine_pathNfilename( + _: *mut dc_context_t, + pathNfolder: *const libc::c_char, + desired_name: *const libc::c_char, + ) -> *mut libc::c_char; + #[no_mangle] + fn dc_key_new() -> *mut dc_key_t; + #[no_mangle] + fn dc_key_unref(_: *mut dc_key_t); + #[no_mangle] + fn sqlite3_finalize(pStmt: *mut sqlite3_stmt) -> libc::c_int; + /* Return the string with the given ID by calling DC_EVENT_GET_STRING. + The result must be free()'d! */ + #[no_mangle] + fn dc_stock_str(_: *mut dc_context_t, id: libc::c_int) -> *mut libc::c_char; + #[no_mangle] + fn dc_str_replace( + haystack: *mut *mut libc::c_char, + needle: *const libc::c_char, + replacement: *const libc::c_char, + ) -> libc::c_int; + #[no_mangle] + fn dc_key_render_asc( + _: *const dc_key_t, + add_header_lines: *const libc::c_char, + ) -> *mut libc::c_char; + /* symm. encryption */ + #[no_mangle] + fn dc_pgp_symm_encrypt( + context: *mut dc_context_t, + passphrase: *const libc::c_char, + plain: *const libc::c_void, + plain_bytes: size_t, + ret_ctext_armored: *mut *mut libc::c_char, + ) -> libc::c_int; + #[no_mangle] + fn dc_key_load_self_private( + _: *mut dc_key_t, + self_addr: *const libc::c_char, + sql: *mut dc_sqlite3_t, + ) -> libc::c_int; + #[no_mangle] + fn dc_sqlite3_get_config( + _: *mut dc_sqlite3_t, + key: *const libc::c_char, + def: *const libc::c_char, + ) -> *mut libc::c_char; + #[no_mangle] + fn dc_ensure_secret_key_exists(_: *mut dc_context_t) -> libc::c_int; + #[no_mangle] + fn dc_strbuilder_catf(_: *mut dc_strbuilder_t, format: *const libc::c_char, _: ...); + #[no_mangle] + fn dc_log_warning(_: *mut dc_context_t, data1: libc::c_int, msg: *const libc::c_char, _: ...); + #[no_mangle] + fn dc_strbuilder_init(_: *mut dc_strbuilder_t, init_bytes: libc::c_int); + #[no_mangle] + fn dc_alloc_ongoing(_: *mut dc_context_t) -> libc::c_int; + #[no_mangle] + fn dc_sqlite3_set_config_int( + _: *mut dc_sqlite3_t, + key: *const libc::c_char, + value: int32_t, + ) -> libc::c_int; + #[no_mangle] + fn dc_log_error(_: *mut dc_context_t, data1: libc::c_int, msg: *const libc::c_char, _: ...); + #[no_mangle] + fn dc_key_save_self_keypair( + public_key: *const dc_key_t, + private_key: *const dc_key_t, + addr: *const libc::c_char, + is_default: libc::c_int, + sql: *mut dc_sqlite3_t, + ) -> libc::c_int; + #[no_mangle] + fn dc_sqlite3_execute(_: *mut dc_sqlite3_t, sql: *const libc::c_char) -> libc::c_int; + #[no_mangle] + fn sqlite3_step(_: *mut sqlite3_stmt) -> libc::c_int; + #[no_mangle] + fn sqlite3_bind_blob( + _: *mut sqlite3_stmt, + _: libc::c_int, + _: *const libc::c_void, + n: libc::c_int, + _: Option ()>, + ) -> libc::c_int; + /* tools, these functions are compatible to the corresponding sqlite3_* functions */ + #[no_mangle] + fn dc_sqlite3_prepare(_: *mut dc_sqlite3_t, sql: *const libc::c_char) -> *mut sqlite3_stmt; + #[no_mangle] + fn dc_pgp_split_key( + _: *mut dc_context_t, + private_in: *const dc_key_t, + public_out: *mut dc_key_t, + ) -> libc::c_int; + #[no_mangle] + fn dc_pgp_is_valid_key(_: *mut dc_context_t, _: *const dc_key_t) -> libc::c_int; + #[no_mangle] + fn dc_key_set_from_base64( + _: *mut dc_key_t, + base64: *const libc::c_char, + type_0: libc::c_int, + ) -> libc::c_int; + #[no_mangle] + fn dc_split_armored_data( + buf: *mut libc::c_char, + ret_headerline: *mut *const libc::c_char, + ret_setupcodebegin: *mut *const libc::c_char, + ret_preferencrypt: *mut *const libc::c_char, + ret_base64: *mut *const libc::c_char, + ) -> libc::c_int; + /* string tools */ + #[no_mangle] + fn dc_strdup(_: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn dc_pgp_symm_decrypt( + context: *mut dc_context_t, + passphrase: *const libc::c_char, + ctext: *const libc::c_void, + ctext_bytes: size_t, + ret_plain_text: *mut *mut libc::c_void, + ret_plain_bytes: *mut size_t, + ) -> libc::c_int; + #[no_mangle] + fn dc_strbuilder_cat(_: *mut dc_strbuilder_t, text: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn dc_read_file( + _: *mut dc_context_t, + pathNfilename: *const libc::c_char, + buf: *mut *mut libc::c_void, + buf_bytes: *mut size_t, + ) -> libc::c_int; + #[no_mangle] + fn dc_msg_get_file(_: *const dc_msg_t) -> *mut libc::c_char; + #[no_mangle] + fn dc_msg_is_setupmessage(_: *const dc_msg_t) -> libc::c_int; + #[no_mangle] + fn sqlite3_bind_text( + _: *mut sqlite3_stmt, + _: libc::c_int, + _: *const libc::c_char, + _: libc::c_int, + _: Option ()>, + ) -> libc::c_int; + #[no_mangle] + fn sqlite3_column_blob(_: *mut sqlite3_stmt, iCol: libc::c_int) -> *const libc::c_void; + #[no_mangle] + fn sqlite3_column_int(_: *mut sqlite3_stmt, iCol: libc::c_int) -> libc::c_int; + #[no_mangle] + fn sqlite3_column_text(_: *mut sqlite3_stmt, iCol: libc::c_int) -> *const libc::c_uchar; + #[no_mangle] + fn sqlite3_column_bytes(_: *mut sqlite3_stmt, iCol: libc::c_int) -> libc::c_int; + #[no_mangle] + fn sqlite3_reset(pStmt: *mut sqlite3_stmt) -> libc::c_int; + #[no_mangle] + fn dc_sqlite3_close(_: *mut dc_sqlite3_t); + #[no_mangle] + fn dc_sqlite3_is_open(_: *const dc_sqlite3_t) -> libc::c_int; + #[no_mangle] + fn dc_sqlite3_try_execute(_: *mut dc_sqlite3_t, sql: *const libc::c_char) -> libc::c_int; + #[no_mangle] + fn dc_sqlite3_table_exists(_: *mut dc_sqlite3_t, name: *const libc::c_char) -> libc::c_int; + /* housekeeping */ + #[no_mangle] + fn dc_housekeeping(_: *mut dc_context_t); + #[no_mangle] + fn dc_get_filesuffix_lc(pathNfilename: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn dc_file_exist(_: *mut dc_context_t, pathNfilename: *const libc::c_char) -> libc::c_int; + #[no_mangle] + fn dc_delete_file(_: *mut dc_context_t, pathNFilename: *const libc::c_char) -> libc::c_int; + #[no_mangle] + fn dc_copy_file( + _: *mut dc_context_t, + pathNFilename: *const libc::c_char, + dest_pathNFilename: *const libc::c_char, + ) -> libc::c_int; + #[no_mangle] + fn dc_create_folder(_: *mut dc_context_t, pathNfilename: *const libc::c_char) -> libc::c_int; + #[no_mangle] + fn dc_param_get( + _: *const dc_param_t, + key: libc::c_int, + def: *const libc::c_char, + ) -> *mut libc::c_char; + #[no_mangle] + fn dc_param_get_int(_: *const dc_param_t, key: libc::c_int, def: int32_t) -> int32_t; + #[no_mangle] + fn dc_key_set_from_stmt( + _: *mut dc_key_t, + _: *mut sqlite3_stmt, + index: libc::c_int, + type_0: libc::c_int, + ) -> libc::c_int; + #[no_mangle] + fn dc_key_render_asc_to_file( + _: *const dc_key_t, + file: *const libc::c_char, + _: *mut dc_context_t, + ) -> libc::c_int; +} +pub type __uint8_t = libc::c_uchar; +pub type __uint16_t = libc::c_ushort; +pub type __uint64_t = libc::c_ulonglong; +pub type __darwin_size_t = libc::c_ulong; +pub type __darwin_ssize_t = libc::c_long; +pub type __darwin_time_t = libc::c_long; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_cond_t { + pub __sig: libc::c_long, + pub __opaque: [libc::c_char; 40], +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_mutex_t { + pub __sig: libc::c_long, + pub __opaque: [libc::c_char; 56], +} +pub type __darwin_pthread_cond_t = _opaque_pthread_cond_t; +pub type __darwin_pthread_mutex_t = _opaque_pthread_mutex_t; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct dirent { + pub d_ino: __uint64_t, + pub d_seekoff: __uint64_t, + pub d_reclen: __uint16_t, + pub d_namlen: __uint16_t, + pub d_type: __uint8_t, + pub d_name: [libc::c_char; 1024], +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct DIR { + pub __dd_fd: libc::c_int, + pub __dd_loc: libc::c_long, + pub __dd_size: libc::c_long, + pub __dd_buf: *mut libc::c_char, + pub __dd_len: libc::c_int, + pub __dd_seek: libc::c_long, + pub __padding: libc::c_long, + pub __dd_flags: libc::c_int, + pub __dd_lock: __darwin_pthread_mutex_t, + pub __dd_td: *mut _telldir, +} +pub type size_t = __darwin_size_t; +pub type uint32_t = libc::c_uint; +pub type int32_t = libc::c_int; +pub type uintptr_t = libc::c_ulong; +pub type ssize_t = __darwin_ssize_t; +pub type time_t = __darwin_time_t; +pub type uint8_t = libc::c_uchar; +pub type uint16_t = libc::c_ushort; +pub type pthread_cond_t = __darwin_pthread_cond_t; +pub type pthread_mutex_t = __darwin_pthread_mutex_t; +#[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 tm { + pub tm_sec: libc::c_int, + pub tm_min: libc::c_int, + pub tm_hour: libc::c_int, + pub tm_mday: libc::c_int, + pub tm_mon: libc::c_int, + pub tm_year: libc::c_int, + pub tm_wday: libc::c_int, + pub tm_yday: libc::c_int, + pub tm_isdst: libc::c_int, + pub tm_gmtoff: libc::c_long, + pub tm_zone: *mut libc::c_char, +} +#[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; +#[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) -> (); +#[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 unnamed = libc::c_uint; +pub const MAILIMF_ERROR_FILE: unnamed = 4; +pub const MAILIMF_ERROR_INVAL: unnamed = 3; +pub const MAILIMF_ERROR_MEMORY: unnamed = 2; +pub const MAILIMF_ERROR_PARSE: unnamed = 1; +pub const MAILIMF_NO_ERROR: unnamed = 0; +#[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_capability_data { + pub cap_list: *mut clist, +} +#[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_1, + 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_1 { + 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 extern "C" 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_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, +} +#[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_2, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed_2 { + pub ft_fetch_att: *mut mailimap_fetch_att, + pub ft_fetch_att_list: *mut clist, +} +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_3, + 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 unnamed_3 { + 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, +} +/* define DC_USE_RPGP to enable use of rPGP instead of netpgp where available; +preferrably, this should be done in the project configuration currently */ +//#define DC_USE_RPGP 1 +/* Includes that are used frequently. This file may also be used to create predefined headers. */ +/* * Structure behind dc_context_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_context { + pub magic: uint32_t, + pub userdata: *mut libc::c_void, + pub dbfile: *mut libc::c_char, + pub blobdir: *mut libc::c_char, + pub sql: *mut dc_sqlite3_t, + pub inbox: *mut dc_imap_t, + pub inboxidle_condmutex: pthread_mutex_t, + pub perform_inbox_jobs_needed: libc::c_int, + pub probe_imap_network: libc::c_int, + pub sentbox_thread: dc_jobthread_t, + pub mvbox_thread: dc_jobthread_t, + pub smtp: *mut dc_smtp_t, + pub smtpidle_cond: pthread_cond_t, + pub smtpidle_condmutex: pthread_mutex_t, + pub smtpidle_condflag: libc::c_int, + pub smtp_suspended: libc::c_int, + pub smtp_doing_jobs: libc::c_int, + pub perform_smtp_jobs_needed: libc::c_int, + pub probe_smtp_network: libc::c_int, + pub oauth2_critical: pthread_mutex_t, + 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 type dc_lot_t = _dc_lot; +/* * Structure behind dc_lot_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_lot { + pub magic: uint32_t, + pub text1_meaning: libc::c_int, + pub text1: *mut libc::c_char, + pub text2: *mut libc::c_char, + pub timestamp: time_t, + pub state: libc::c_int, + pub id: uint32_t, + pub fingerprint: *mut libc::c_char, + pub invitenumber: *mut libc::c_char, + pub auth: *mut libc::c_char, +} +/* * + * 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 = Option< + unsafe extern "C" fn( + _: *mut dc_context_t, + _: libc::c_int, + _: uintptr_t, + _: uintptr_t, + ) -> uintptr_t, +>; +/* * + * @mainpage Getting started + * + * This document describes how to handle the Delta Chat core library. + * For general information about Delta Chat itself, + * see and . + * + * Let's start. + * + * First of all, you have to **define an event-handler-function** + * that is called by the library on specific events + * (eg. when the configuration is done or when fresh messages arrive). + * With this function you can create a Delta Chat context then: + * + * ~~~ + * #include + * + * uintptr_t event_handler_func(dc_context_t* context, int event, + * uintptr_t data1, uintptr_t data2) + * { + * return 0; // for unhandled events, it is always safe to return 0 + * } + * + * dc_context_t* context = dc_context_new(event_handler_func, NULL, NULL); + * ~~~ + * + * After that, you should make sure, + * sending and receiving jobs are processed as needed. + * For this purpose, you have to **create two threads:** + * + * ~~~ + * #include + * + * void* imap_thread_func(void* context) + * { + * while (true) { + * dc_perform_imap_jobs(context); + * dc_perform_imap_fetch(context); + * dc_perform_imap_idle(context); + * } + * } + * + * void* smtp_thread_func(void* context) + * { + * while (true) { + * dc_perform_smtp_jobs(context); + * dc_perform_smtp_idle(context); + * } + * } + * + * static pthread_t imap_thread, smtp_thread; + * pthread_create(&imap_thread, NULL, imap_thread_func, context); + * pthread_create(&smtp_thread, NULL, smtp_thread_func, context); + * ~~~ + * + * The example above uses "pthreads", + * however, you can also use anything else for thread handling. + * NB: The deltachat-core library itself does not create any threads on its own, + * however, functions, unless stated otherwise, are thread-safe. + * + * After that you can **define and open a database.** + * The database is a normal sqlite-file and is created as needed: + * + * ~~~ + * dc_open(context, "example.db", NULL); + * ~~~ + * + * Now you can **configure the context:** + * + * ~~~ + * // use some real test credentials here + * dc_set_config(context, "addr", "alice@example.org"); + * dc_set_config(context, "mail_pw", "***"); + * dc_configure(context); + * ~~~ + * + * dc_configure() returns immediately, the configuration itself may take a while + * and is done by a job in the imap-thread you've defined above. + * Once done, the #DC_EVENT_CONFIGURE_PROGRESS reports success + * to the event_handler_func() that is also defined above. + * + * The configuration result is saved in the database, + * on subsequent starts it is not needed to call dc_configure() + * (you can check this using dc_is_configured()). + * + * Now you can **send the first message:** + * + * ~~~ + * // use a real testing address here + * uint32_t contact_id = dc_create_contact(context, NULL, "bob@example.org"); + * uint32_t chat_id = dc_create_chat_by_contact_id(context, contact_id); + * + * dc_send_text_msg(context, chat_id, "Hi, here is my first message!"); + * ~~~ + * + * dc_send_text_msg() returns immediately; + * the sending itself is done by a job in the smtp-thread you've defined above. + * If you check the testing address (bob) + * and you should have received a normal email. + * Answer this email in any email program with "Got it!" + * and the imap-thread you've create above will **receive the message**. + * + * You can then **list all messages** of a chat as follow: + * + * ~~~ + * dc_array_t* msglist = dc_get_chat_msgs(context, chat_id, 0, 0); + * for (int i = 0; i < dc_array_get_cnt(msglist); i++) + * { + * uint32_t msg_id = dc_array_get_id(msglist, i); + * dc_msg_t* msg = dc_get_msg(context, msg_id); + * char* text = dc_msg_get_text(msg); + * + * printf("Message %i: %s\n", i+1, text); + * + * free(text); + * dc_msg_unref(msg); + * } + * dc_array_unref(msglist); + * ~~~ + * + * This will output the following two lines: + * + * ~~~ + * Message 1: Hi, here is my first message! + * Message 2: Got it! + * ~~~ + * + * + * ## Class reference + * + * For a class reference, see the "Classes" link atop. + * + * + * ## Further hints + * + * Here are some additional, unsorted hints that may be useful. + * + * - For `get`-functions, you have to unref the return value in some way. + * + * - Strings in function arguments or return values are usually UTF-8 encoded. + * + * - The issue-tracker for the core library is here: + * + * + * The following points are important mainly + * for the authors of the library itself: + * + * - For indentation, use tabs. + * Alignments that are not placed at the beginning of a line + * should be done with spaces. + * + * - For padding between functions, + * classes etc. use 2 empty lines + * + * - Source files are encoded as UTF-8 with Unix line endings + * (a simple `LF`, `0x0A` or `\n`) + * + * If you need further assistance, + * please do not hesitate to contact us + * through the channels shown at https://delta.chat/en/contribute + * + * Please keep in mind, that your derived work + * must respect the Mozilla Public License 2.0 of libdeltachat + * and the respective licenses of the libraries libdeltachat links with. + * + * See you. + */ +/* * + * @class dc_context_t + * + * An object representing a single account. + * + * Each account is linked to an IMAP/SMTP account and uses a separate + * SQLite database for offline functionality and for account-related + * settings. + */ +pub type dc_context_t = _dc_context; +/* ** library-private **********************************************************/ +pub type dc_smtp_t = _dc_smtp; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_smtp { + 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 error: *mut libc::c_char, + pub error_etpan: libc::c_int, +} +pub type dc_jobthread_t = _dc_jobthread; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_jobthread { + 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, + 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, +} +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_imap { + 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 type dc_receive_imf_t = Option< + unsafe extern "C" 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_imap_t = _dc_imap; +pub type dc_precheck_imf_t = Option< + unsafe extern "C" 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< + unsafe extern "C" fn(_: *mut dc_imap_t, _: *const libc::c_char, _: *const libc::c_char) -> (), +>; +pub type dc_get_config_t = Option< + unsafe extern "C" fn( + _: *mut dc_imap_t, + _: *const libc::c_char, + _: *const libc::c_char, + ) -> *mut libc::c_char, +>; +/* ** library-private **********************************************************/ +pub type dc_sqlite3_t = _dc_sqlite3; +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_sqlite3 { + pub cobj: *mut sqlite3, + pub context: *mut dc_context_t, +} +pub type dc_param_t = _dc_param; +/* * + * @class dc_param_t + * + * An object for handling key=value parameter lists; for the key, curently only + * a single character is allowed. + * + * The object is used eg. by dc_chat_t or dc_msg_t, for readable paramter names, + * these classes define some DC_PARAM_* constantats. + * + * Only for library-internal use. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_param { + pub packed: *mut libc::c_char, +} +/* * the structure behind dc_msg_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_msg { + pub magic: uint32_t, + pub id: uint32_t, + pub from_id: uint32_t, + pub to_id: uint32_t, + pub chat_id: uint32_t, + pub move_state: dc_move_state_t, + pub type_0: libc::c_int, + pub state: libc::c_int, + pub hidden: libc::c_int, + pub timestamp_sort: time_t, + pub timestamp_sent: time_t, + pub timestamp_rcvd: time_t, + pub text: *mut libc::c_char, + pub context: *mut 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, + pub server_uid: uint32_t, + pub is_dc_message: libc::c_int, + pub starred: libc::c_int, + pub chat_blocked: libc::c_int, + pub location_id: uint32_t, + pub param: *mut dc_param_t, +} +pub type dc_move_state_t = libc::c_uint; +pub const DC_MOVE_STATE_MOVING: dc_move_state_t = 3; +pub const DC_MOVE_STATE_STAY: dc_move_state_t = 2; +pub const DC_MOVE_STATE_PENDING: dc_move_state_t = 1; +pub const DC_MOVE_STATE_UNDEFINED: dc_move_state_t = 0; +pub type dc_msg_t = _dc_msg; +pub type dc_loginparam_t = _dc_loginparam; +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_loginparam { + pub addr: *mut libc::c_char, + pub mail_server: *mut libc::c_char, + pub mail_user: *mut libc::c_char, + pub mail_pw: *mut libc::c_char, + pub mail_port: uint16_t, + pub send_server: *mut libc::c_char, + pub send_user: *mut libc::c_char, + pub send_pw: *mut libc::c_char, + pub send_port: libc::c_int, + pub server_flags: libc::c_int, +} +pub type dc_key_t = _dc_key; +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_key { + pub binary: *mut libc::c_void, + pub bytes: libc::c_int, + pub type_0: libc::c_int, + pub _m_heap_refcnt: libc::c_int, +} +pub type dc_strbuilder_t = _dc_strbuilder; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_strbuilder { + pub buf: *mut libc::c_char, + pub allocated: libc::c_int, + pub free: libc::c_int, + pub eos: *mut libc::c_char, +} +pub type sqlite3_destructor_type = Option ()>; +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_job { + pub job_id: uint32_t, + pub action: libc::c_int, + pub foreign_id: uint32_t, + pub desired_timestamp: time_t, + pub added_timestamp: time_t, + pub tries: libc::c_int, + pub param: *mut dc_param_t, + pub try_again: libc::c_int, + pub pending_error: *mut libc::c_char, +} +// thread IDs +// jobs in the INBOX-thread, range from DC_IMAP_THREAD..DC_IMAP_THREAD+999 +// low priority ... +// ... high priority +// jobs in the SMTP-thread, range from DC_SMTP_THREAD..DC_SMTP_THREAD+999 +// low priority ... +// ... high priority +// timeouts until actions are aborted. +// this may also affects IDLE to return, so a re-connect may take this time. +// mailcore2 uses 30 seconds, k-9 uses 10 seconds +pub type dc_job_t = _dc_job; +// import/export and tools +// param1 is a directory where the keys are written to +// param1 is a directory where the keys are searched in and read from +// param1 is a directory where the backup is written to +// param1 is the file with the backup to import +#[no_mangle] +pub unsafe extern "C" fn dc_imex( + mut context: *mut dc_context_t, + mut what: libc::c_int, + mut param1: *const libc::c_char, + mut param2: *const libc::c_char, +) { + let mut param: *mut dc_param_t = dc_param_new(); + dc_param_set_int(param, 'S' as i32, what); + dc_param_set(param, 'E' as i32, param1); + dc_param_set(param, 'F' as i32, param2); + dc_job_kill_action(context, 910i32); + dc_job_add(context, 910i32, 0i32, (*param).packed, 0i32); + dc_param_unref(param); +} +#[no_mangle] +pub unsafe extern "C" fn dc_imex_has_backup( + mut context: *mut 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 prefix_len: libc::c_int = + strlen(b"delta-chat\x00" as *const u8 as *const libc::c_char) as libc::c_int; + let mut suffix_len: libc::c_int = + strlen(b"bak\x00" as *const u8 as *const libc::c_char) as libc::c_int; + 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; + } + dir_handle = opendir(dir_name); + if dir_handle.is_null() { + dc_log_info( + context, + 0i32, + b"Backup check: Cannot open directory \"%s\".\x00" as *const u8 as *const libc::c_char, + dir_name, + ); + } else { + loop { + dir_entry = readdir(dir_handle); + if dir_entry.is_null() { + break; + } + 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 > prefix_len + && strncmp( + name, + b"delta-chat\x00" as *const u8 as *const libc::c_char, + prefix_len as libc::c_ulong, + ) == 0i32 + && name_len > suffix_len + && strncmp( + &*name.offset((name_len - suffix_len - 1i32) as isize), + b".bak\x00" as *const u8 as *const libc::c_char, + suffix_len as libc::c_ulong, + ) == 0i32 + { + free(curr_pathNfilename as *mut libc::c_void); + curr_pathNfilename = dc_mprintf( + b"%s/%s\x00" as *const u8 as *const libc::c_char, + 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) + { + let mut curr_backup_time: time_t = dc_sqlite3_get_config_int( + test_sql, + b"backup_time\x00" as *const u8 as *const libc::c_char, + 0i32, + ) as time_t; + if curr_backup_time > 0i32 as libc::c_long && curr_backup_time > ret_backup_time + { + free(ret as *mut libc::c_void); + ret = curr_pathNfilename; + ret_backup_time = curr_backup_time; + curr_pathNfilename = 0 as *mut libc::c_char + } + } + } + } + } + if !dir_handle.is_null() { + closedir(dir_handle); + } + free(curr_pathNfilename as *mut libc::c_void); + dc_sqlite3_unref(test_sql); + return ret; +} +#[no_mangle] +pub unsafe extern "C" fn dc_check_password( + mut context: *mut dc_context_t, + mut test_pw: *const libc::c_char, +) -> libc::c_int { + /* Check if the given password matches the configured mail_pw. + This is to prompt the user before starting eg. an export; this is mainly to avoid doing people bad thinkgs if they have short access to the device. + 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_unref(loginparam); + return success; +} +#[no_mangle] +pub unsafe extern "C" fn dc_initiate_key_transfer( + mut context: *mut 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_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 msg: *mut dc_msg_t = 0 as *mut dc_msg_t; + let mut msg_id: uint32_t = 0i32 as 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) { + 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) { + setup_file_name = dc_get_fine_pathNfilename( + context, + b"$BLOBDIR\x00" as *const u8 as *const libc::c_char, + b"autocrypt-setup-message.html\x00" as *const u8 as *const libc::c_char, + ); + if !(setup_file_name.is_null() + || 0 == dc_write_file( + context, + setup_file_name, + setup_file_content as *const libc::c_void, + strlen(setup_file_content), + )) + { + chat_id = dc_create_chat_by_contact_id(context, 1i32 as uint32_t); + if !(chat_id == 0i32 as libc::c_uint) { + msg = dc_msg_new_untyped(context); + (*msg).type_0 = 60i32; + dc_param_set((*msg).param, 'f' as i32, setup_file_name); + dc_param_set( + (*msg).param, + 'm' as i32, + b"application/autocrypt-setup\x00" as *const u8 + as *const libc::c_char, + ); + 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) { + msg_id = dc_send_msg(context, chat_id, msg); + if !(msg_id == 0i32 as libc::c_uint) { + dc_msg_unref(msg); + msg = 0 as *mut dc_msg_t; + dc_log_info( + context, + 0i32, + b"Wait for setup message being sent ...\x00" as *const u8 + as *const libc::c_char, + ); + loop { + if 0 != (*context).shall_stop_ongoing { + current_block = 6116957410927263949; + break; + } + sleep(1i32 as libc::c_uint); + msg = dc_get_msg(context, msg_id); + if 0 != dc_msg_is_sent(msg) { + current_block = 6450636197030046351; + break; + } + dc_msg_unref(msg); + msg = 0 as *mut dc_msg_t + } + match current_block { + 6116957410927263949 => {} + _ => { + dc_log_info( + context, + 0i32, + b"... setup message sent.\x00" as *const u8 + as *const libc::c_char, + ); + success = 1i32 + } + } + } + } + } + } + } + } + } + } + if 0 == success { + free(setup_code as *mut libc::c_void); + setup_code = 0 as *mut libc::c_char + } + free(setup_file_name as *mut libc::c_void); + free(setup_file_content as *mut libc::c_void); + dc_msg_unref(msg); + dc_free_ongoing(context); + return setup_code; +} +#[no_mangle] +pub unsafe extern "C" fn dc_render_setup_file( + mut context: *mut dc_context_t, + mut passphrase: *const libc::c_char, +) -> *mut libc::c_char { + 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 curr_private_key: *mut dc_key_t = dc_key_new(); + 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) < 2i32 as libc::c_ulong + || curr_private_key.is_null()) + { + strncpy( + passphrase_begin.as_mut_ptr(), + passphrase, + 2i32 as libc::c_ulong, + ); + 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, + 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); + let mut e2ee_enabled: libc::c_int = dc_sqlite3_get_config_int( + (*context).sql, + 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 + } else { + 0 as *const libc::c_char + }, + ); + if !payload_key_asc.is_null() { + if !(0 + == dc_pgp_symm_encrypt( + context, + passphrase, + payload_key_asc as *const libc::c_void, + strlen(payload_key_asc), + &mut encr_string, + )) + { + free(payload_key_asc as *mut libc::c_void); + let mut replacement: *mut libc::c_char = + dc_mprintf(b"-----BEGIN PGP MESSAGE-----\r\nPassphrase-Format: numeric9x4\r\nPassphrase-Begin: %s\x00" + as *const u8 as *const libc::c_char, + passphrase_begin.as_mut_ptr()); + dc_str_replace( + &mut encr_string, + b"-----BEGIN PGP MESSAGE-----\x00" as *const u8 as *const libc::c_char, + replacement, + ); + free(replacement as *mut libc::c_void); + let mut setup_message_title: *mut libc::c_char = dc_stock_str(context, 42i32); + let mut setup_message_body: *mut libc::c_char = dc_stock_str(context, 43i32); + dc_str_replace( + &mut setup_message_body, + b"\r\x00" as *const u8 as *const libc::c_char, + 0 as *const libc::c_char, + ); + dc_str_replace( + &mut setup_message_body, + b"\n\x00" as *const u8 as *const libc::c_char, + b"
\x00" as *const u8 as *const libc::c_char, + ); + ret_setupfilecontent = + dc_mprintf(b"\r\n\r\n\r\n%s\r\n\r\n\r\n

%s

\r\n

%s

\r\n
\r\n%s\r\n
\r\n\r\n\r\n\x00" + as *const u8 as *const libc::c_char, + setup_message_title, setup_message_title, + setup_message_body, encr_string); + free(setup_message_title as *mut libc::c_void); + free(setup_message_body as *mut libc::c_void); + } + } + } + } + sqlite3_finalize(stmt); + 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; +} +#[no_mangle] +pub unsafe extern "C" fn dc_create_setup_code(mut 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; + let mut ret: dc_strbuilder_t = _dc_strbuilder { + buf: 0 as *mut libc::c_char, + allocated: 0, + free: 0, + eos: 0 as *mut libc::c_char, + }; + dc_strbuilder_init(&mut ret, 0i32); + i = 0i32; + while i < 9i32 { + loop { + if 0 == RAND_bytes( + &mut random_val as *mut uint16_t as *mut libc::c_uchar, + ::std::mem::size_of::() as libc::c_ulong as libc::c_int, + ) { + dc_log_warning( + context, + 0i32, + b"Falling back to pseudo-number generation for the setup code.\x00" as *const u8 + as *const libc::c_char, + ); + RAND_pseudo_bytes( + &mut random_val as *mut uint16_t as *mut libc::c_uchar, + ::std::mem::size_of::() as libc::c_ulong as libc::c_int, + ); + } + if !(random_val as libc::c_int > 60000i32) { + break; + } + } + random_val = (random_val as libc::c_int % 10000i32) as uint16_t; + dc_strbuilder_catf( + &mut ret as *mut dc_strbuilder_t, + b"%s%04i\x00" as *const u8 as *const libc::c_char, + if 0 != i { + b"-\x00" as *const u8 as *const libc::c_char + } else { + b"\x00" as *const u8 as *const libc::c_char + }, + random_val as libc::c_int, + ); + i += 1 + } + return ret.buf; +} +#[no_mangle] +pub unsafe extern "C" fn dc_continue_key_transfer( + mut context: *mut dc_context_t, + mut msg_id: uint32_t, + mut setup_code: *const libc::c_char, +) -> libc::c_int { + let mut success: libc::c_int = 0i32; + let mut msg: *mut dc_msg_t = 0 as *mut dc_msg_t; + let mut filename: *mut libc::c_char = 0 as *mut libc::c_char; + let mut filecontent: *mut libc::c_char = 0 as *mut libc::c_char; + 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()) + { + msg = dc_get_msg(context, msg_id); + if msg.is_null() + || 0 == dc_msg_is_setupmessage(msg) + || { + filename = dc_msg_get_file(msg); + filename.is_null() + } + || *filename.offset(0isize) as libc::c_int == 0i32 + { + dc_log_error( + context, + 0i32, + b"Message is no Autocrypt Setup Message.\x00" as *const u8 as *const libc::c_char, + ); + } else if 0 + == dc_read_file( + context, + filename, + &mut filecontent as *mut *mut libc::c_char as *mut *mut libc::c_void, + &mut filebytes, + ) + || filecontent.is_null() + || filebytes <= 0i32 as libc::c_ulong + { + dc_log_error( + context, + 0i32, + b"Cannot read Autocrypt Setup Message file.\x00" as *const u8 + as *const libc::c_char, + ); + } else { + norm_sc = dc_normalize_setup_code(context, setup_code); + if norm_sc.is_null() { + dc_log_warning( + context, + 0i32, + b"Cannot normalize Setup Code.\x00" as *const u8 as *const libc::c_char, + ); + } else { + armored_key = dc_decrypt_setup_file(context, norm_sc, filecontent); + if armored_key.is_null() { + dc_log_warning( + context, + 0i32, + b"Cannot decrypt Autocrypt Setup Message.\x00" as *const u8 + as *const libc::c_char, + ); + } else if !(0 == set_self_key(context, armored_key, 1i32)) { + /*set default*/ + /* error already logged */ + success = 1i32 + } + } + } + } + free(armored_key as *mut libc::c_void); + free(filecontent as *mut libc::c_void); + free(filename as *mut libc::c_void); + dc_msg_unref(msg); + free(norm_sc as *mut libc::c_void); + return success; +} +unsafe extern "C" fn set_self_key( + mut context: *mut 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; + // pointer inside buf, MUST NOT be free()'d + let mut buf_headerline: *const libc::c_char = 0 as *const libc::c_char; + // - " - + let mut buf_preferencrypt: *const libc::c_char = 0 as *const libc::c_char; + // - " - + let mut buf_base64: *const libc::c_char = 0 as *const libc::c_char; + let mut private_key: *mut dc_key_t = dc_key_new(); + let mut public_key: *mut dc_key_t = dc_key_new(); + 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; + buf = dc_strdup(armored); + if 0 == dc_split_armored_data( + buf, + &mut buf_headerline, + 0 as *mut *const libc::c_char, + &mut buf_preferencrypt, + &mut buf_base64, + ) || strcmp( + buf_headerline, + b"-----BEGIN PGP PRIVATE KEY BLOCK-----\x00" as *const u8 as *const libc::c_char, + ) != 0i32 + || buf_base64.is_null() + { + dc_log_warning( + context, + 0i32, + b"File does not contain a private key.\x00" as *const u8 as *const libc::c_char, + ); + } else if 0 == dc_key_set_from_base64(private_key, buf_base64, 1i32) + || 0 == dc_pgp_is_valid_key(context, private_key) + || 0 == dc_pgp_split_key(context, private_key, public_key) + { + dc_log_error( + context, + 0i32, + b"File does not contain a valid private key.\x00" as *const u8 as *const libc::c_char, + ); + } else { + stmt = dc_sqlite3_prepare( + (*context).sql, + b"DELETE FROM keypairs WHERE public_key=? OR private_key=?;\x00" as *const u8 + as *const libc::c_char, + ); + sqlite3_bind_blob(stmt, 1i32, (*public_key).binary, (*public_key).bytes, None); + sqlite3_bind_blob( + stmt, + 2i32, + (*private_key).binary, + (*private_key).bytes, + None, + ); + sqlite3_step(stmt); + sqlite3_finalize(stmt); + stmt = 0 as *mut sqlite3_stmt; + if 0 != set_default { + dc_sqlite3_execute( + (*context).sql, + b"UPDATE keypairs SET is_default=0;\x00" as *const u8 as *const libc::c_char, + ); + } + 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, + ); + if 0 == dc_key_save_self_keypair( + public_key, + private_key, + self_addr, + set_default, + (*context).sql, + ) { + dc_log_error( + context, + 0i32, + b"Cannot save keypair.\x00" as *const u8 as *const libc::c_char, + ); + } else { + if !buf_preferencrypt.is_null() { + if strcmp( + buf_preferencrypt, + b"nopreference\x00" as *const u8 as *const libc::c_char, + ) == 0i32 + { + dc_sqlite3_set_config_int( + (*context).sql, + b"e2ee_enabled\x00" as *const u8 as *const libc::c_char, + 0i32, + ); + } else if strcmp( + buf_preferencrypt, + b"mutual\x00" as *const u8 as *const libc::c_char, + ) == 0i32 + { + dc_sqlite3_set_config_int( + (*context).sql, + b"e2ee_enabled\x00" as *const u8 as *const libc::c_char, + 1i32, + ); + } + } + success = 1i32 + } + } + sqlite3_finalize(stmt); + free(buf as *mut libc::c_void); + free(self_addr as *mut libc::c_void); + dc_key_unref(private_key); + dc_key_unref(public_key); + return success; +} +#[no_mangle] +pub unsafe extern "C" fn dc_decrypt_setup_file( + mut context: *mut 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_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; + let mut binary_bytes: size_t = 0i32 as size_t; + let mut indx: size_t = 0i32 as size_t; + let mut plain: *mut libc::c_void = 0 as *mut libc::c_void; + let mut plain_bytes: size_t = 0i32 as size_t; + let mut payload: *mut libc::c_char = 0 as *mut libc::c_char; + fc_buf = dc_strdup(filecontent); + if !(0 + == dc_split_armored_data( + fc_buf, + &mut fc_headerline, + 0 as *mut *const libc::c_char, + 0 as *mut *const libc::c_char, + &mut fc_base64, + ) + || fc_headerline.is_null() + || strcmp( + fc_headerline, + b"-----BEGIN PGP MESSAGE-----\x00" as *const u8 as *const libc::c_char, + ) != 0i32 + || fc_base64.is_null()) + { + /* convert base64 to binary */ + /*must be freed using mmap_string_unref()*/ + if !(mailmime_base64_body_parse( + fc_base64, + strlen(fc_base64), + &mut indx, + &mut binary, + &mut binary_bytes, + ) != MAILIMF_NO_ERROR as libc::c_int + || binary.is_null() + || binary_bytes == 0i32 as libc::c_ulong) + { + /* decrypt symmetrically */ + if !(0 + == dc_pgp_symm_decrypt( + context, + passphrase, + binary as *const libc::c_void, + binary_bytes, + &mut plain, + &mut plain_bytes, + )) + { + payload = strndup(plain as *const libc::c_char, plain_bytes) + } + } + } + free(plain); + free(fc_buf as *mut libc::c_void); + if !binary.is_null() { + mmap_string_unref(binary); + } + return payload; +} +#[no_mangle] +pub unsafe extern "C" fn dc_normalize_setup_code( + mut context: *mut dc_context_t, + mut in_0: *const libc::c_char, +) -> *mut libc::c_char { + if in_0.is_null() { + return 0 as *mut libc::c_char; + } + let mut out: dc_strbuilder_t = _dc_strbuilder { + buf: 0 as *mut libc::c_char, + allocated: 0, + free: 0, + eos: 0 as *mut libc::c_char, + }; + dc_strbuilder_init(&mut out, 0i32); + let mut outlen: libc::c_int = 0i32; + 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 { + dc_strbuilder_catf( + &mut out as *mut dc_strbuilder_t, + b"%c\x00" as *const u8 as *const libc::c_char, + *p1 as libc::c_int, + ); + outlen = strlen(out.buf) as libc::c_int; + if outlen == 4i32 + || outlen == 9i32 + || outlen == 14i32 + || outlen == 19i32 + || outlen == 24i32 + || outlen == 29i32 + || outlen == 34i32 + || outlen == 39i32 + { + dc_strbuilder_cat(&mut out, b"-\x00" as *const u8 as *const libc::c_char); + } + } + p1 = p1.offset(1isize) + } + return out.buf; +} +#[no_mangle] +pub unsafe extern "C" fn dc_job_do_DC_JOB_IMEX_IMAP( + mut context: *mut 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 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() { + 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.expect("non-null function pointer")( + context, + 2051i32, + 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, + 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; + } + } 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; + } + } + 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; + } + } + 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; + } + } + 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; + } + } + 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.expect("non-null function pointer")( + context, + 2051i32, + (if 0 != success { 1000i32 } else { 0i32 }) as uintptr_t, + 0i32 as uintptr_t, + ); +} +/* ****************************************************************************** + * Import backup + ******************************************************************************/ +unsafe extern "C" fn import_backup( + mut context: *mut 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 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; + let mut repl_to: *mut libc::c_char = 0 as *mut libc::c_char; + dc_log_info( + context, + 0i32, + b"Import \"%s\" to \"%s\".\x00" as *const u8 as *const libc::c_char, + backup_to_import, + (*context).dbfile, + ); + if 0 != dc_is_configured(context) { + dc_log_error( + context, + 0i32, + 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); + } + dc_delete_file(context, (*context).dbfile); + if 0 != dc_file_exist(context, (*context).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)) { + /* error already logged */ + /* re-open copied database file */ + if !(0 == dc_sqlite3_open((*context).sql, (*context).dbfile, 0i32)) { + stmt = dc_sqlite3_prepare( + (*context).sql, + 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, + b"SELECT file_name, file_content FROM backup_blobs ORDER BY id;\x00" + as *const u8 as *const libc::c_char, + ); + loop { + if !(sqlite3_step(stmt) == 100i32) { + current_block = 10891380440665537214; + break; + } + if 0 != (*context).shall_stop_ongoing { + current_block = 8648553629232744886; + break; + } + processed_files_cnt += 1; + let mut permille: libc::c_int = processed_files_cnt * 1000i32 / total_files_cnt; + if permille < 10i32 { + permille = 10i32 + } + if permille > 990i32 { + permille = 990i32 + } + (*context).cb.expect("non-null function pointer")( + context, + 2051i32, + permille as uintptr_t, + 0i32 as uintptr_t, + ); + let mut file_name: *const libc::c_char = + sqlite3_column_text(stmt, 0i32) as *const libc::c_char; + let mut file_bytes: libc::c_int = sqlite3_column_bytes(stmt, 1i32); + let mut file_content: *const libc::c_void = sqlite3_column_blob(stmt, 1i32); + if !(file_bytes > 0i32 && !file_content.is_null()) { + continue; + } + free(pathNfilename as *mut libc::c_void); + pathNfilename = dc_mprintf( + b"%s/%s\x00" as *const u8 as *const libc::c_char, + (*context).blobdir, + file_name, + ); + if !(0 + == dc_write_file( + context, + pathNfilename, + file_content, + file_bytes as size_t, + )) + { + continue; + } + dc_log_error( + context, + 0i32, + b"Storage full? Cannot write file %s with %i bytes.\x00" as *const u8 + as *const libc::c_char, + pathNfilename, + file_bytes, + ); + /* otherwise the user may believe the stuff is imported correctly, but there are files missing ... */ + current_block = 8648553629232744886; + break; + } + match current_block { + 8648553629232744886 => {} + _ => { + sqlite3_finalize(stmt); + stmt = 0 as *mut sqlite3_stmt; + dc_sqlite3_execute( + (*context).sql, + b"DROP TABLE backup_blobs;\x00" as *const u8 as *const libc::c_char, + ); + dc_sqlite3_try_execute( + (*context).sql, + b"VACUUM;\x00" as *const u8 as *const libc::c_char, + ); + success = 1i32 + } + } + } + } + } + free(pathNfilename as *mut libc::c_void); + free(repl_from as *mut libc::c_void); + free(repl_to as *mut libc::c_void); + sqlite3_finalize(stmt); + return 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 extern "C" fn export_backup( + mut context: *mut 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 now: time_t = 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 prefix_len: libc::c_int = + strlen(b"delta-chat\x00" as *const u8 as *const libc::c_char) as libc::c_int; + let mut suffix_len: libc::c_int = + strlen(b"bak\x00" as *const u8 as *const libc::c_char) as libc::c_int; + 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 processed_files_cnt: libc::c_int = 0i32; + let mut delete_dest_file: libc::c_int = 0i32; + /* 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 buffer: [libc::c_char; 256] = [0; 256]; + timeinfo = localtime(&mut now); + strftime( + buffer.as_mut_ptr(), + 256i32 as size_t, + b"delta-chat-%Y-%m-%d.bak\x00" as *const u8 as *const libc::c_char, + timeinfo, + ); + dest_pathNfilename = dc_get_fine_pathNfilename(context, dir, buffer.as_mut_ptr()); + if dest_pathNfilename.is_null() { + dc_log_error( + context, + 0i32, + b"Cannot get backup file name.\x00" as *const u8 as *const libc::c_char, + ); + } else { + dc_housekeeping(context); + dc_sqlite3_try_execute( + (*context).sql, + b"VACUUM;\x00" as *const u8 as *const libc::c_char, + ); + dc_sqlite3_close((*context).sql); + closed = 1i32; + dc_log_info( + context, + 0i32, + b"Backup \"%s\" to \"%s\".\x00" as *const u8 as *const libc::c_char, + (*context).dbfile, + dest_pathNfilename, + ); + if !(0 == dc_copy_file(context, (*context).dbfile, dest_pathNfilename)) { + /* error already logged */ + dc_sqlite3_open((*context).sql, (*context).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)) { + /* error already logged */ + if 0 == dc_sqlite3_table_exists( + dest_sql, + b"backup_blobs\x00" as *const u8 as *const libc::c_char, + ) { + if 0 == + dc_sqlite3_execute(dest_sql, + b"CREATE TABLE backup_blobs (id INTEGER PRIMARY KEY, file_name, file_content);\x00" + as *const u8 as + *const libc::c_char) { + /* error already logged */ + current_block = 11487273724841241105; + } else { current_block = 14648156034262866959; } + } else { + current_block = 14648156034262866959; + } + match current_block { + 11487273724841241105 => {} + _ => { + total_files_cnt = 0i32; + dir_handle = opendir((*context).blobdir); + if dir_handle.is_null() { + dc_log_error( + context, + 0i32, + b"Backup: Cannot get info for blob-directory \"%s\".\x00" + as *const u8 + as *const libc::c_char, + (*context).blobdir, + ); + } else { + loop { + dir_entry = readdir(dir_handle); + if dir_entry.is_null() { + break; + } + total_files_cnt += 1 + } + closedir(dir_handle); + dir_handle = 0 as *mut DIR; + if total_files_cnt > 0i32 { + /* scan directory, pass 2: copy files */ + dir_handle = opendir((*context).blobdir); + if dir_handle.is_null() { + dc_log_error( + context, + 0i32, + b"Backup: Cannot copy from blob-directory \"%s\".\x00" + as *const u8 + as *const libc::c_char, + (*context).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); + loop { + dir_entry = readdir(dir_handle); + if dir_entry.is_null() { + current_block = 2631791190359682872; + break; + } + if 0 != (*context).shall_stop_ongoing { + delete_dest_file = 1i32; + current_block = 11487273724841241105; + break; + } else { + processed_files_cnt += 1; + let mut permille: libc::c_int = + processed_files_cnt * 1000i32 / total_files_cnt; + if permille < 10i32 { + permille = 10i32 + } + if permille > 990i32 { + permille = 990i32 + } + (*context).cb.expect("non-null function pointer")( + context, + 2051i32, + permille as uintptr_t, + 0i32 as uintptr_t, + ); + /* name without path; may also be `.` or `..` */ + let mut name: *mut 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 + && *name.offset(0isize) as libc::c_int + == '.' as i32 + && *name.offset(1isize) as libc::c_int + == '.' as i32 + || name_len > prefix_len + && strncmp( + name, + b"delta-chat\x00" as *const u8 + as *const libc::c_char, + prefix_len as libc::c_ulong, + ) == 0i32 + && name_len > suffix_len + && strncmp( + &mut *name.offset( + (name_len - suffix_len - 1i32) as isize, + ), + b".bak\x00" as *const u8 + as *const libc::c_char, + suffix_len as libc::c_ulong, + ) == 0i32) + { + //dc_log_info(context, 0, "Backup: Skipping \"%s\".", name); + free(curr_pathNfilename as *mut libc::c_void); + curr_pathNfilename = dc_mprintf( + b"%s/%s\x00" as *const u8 + as *const libc::c_char, + (*context).blobdir, + name, + ); + free(buf); + if 0 == dc_read_file( + context, + curr_pathNfilename, + &mut buf, + &mut buf_bytes, + ) || buf.is_null() + || buf_bytes <= 0i32 as libc::c_ulong + { + continue; + } + sqlite3_bind_text(stmt, 1i32, name, -1i32, None); + sqlite3_bind_blob( + stmt, + 2i32, + buf, + buf_bytes as libc::c_int, + None, + ); + if sqlite3_step(stmt) != 101i32 { + dc_log_error(context, + 0i32, + b"Disk full? Cannot add file \"%s\" to backup.\x00" + as + *const u8 + as + *const libc::c_char, + curr_pathNfilename); + /* this is not recoverable! writing to the sqlite database should work! */ + current_block = 11487273724841241105; + break; + } else { + sqlite3_reset(stmt); + } + } + } + } + } + } else { + dc_log_info( + context, + 0i32, + b"Backup: No files to copy.\x00" as *const u8 + as *const libc::c_char, + (*context).blobdir, + ); + current_block = 2631791190359682872; + } + match current_block { + 11487273724841241105 => {} + _ => { + dc_sqlite3_set_config_int( + dest_sql, + b"backup_time\x00" as *const u8 as *const libc::c_char, + now as int32_t, + ); + (*context).cb.expect("non-null function pointer")( + context, + 2052i32, + dest_pathNfilename as uintptr_t, + 0i32 as uintptr_t, + ); + success = 1i32 + } + } + } + } + } + } + } + } + if !dir_handle.is_null() { + closedir(dir_handle); + } + if 0 != closed { + dc_sqlite3_open((*context).sql, (*context).dbfile, 0i32); + } + sqlite3_finalize(stmt); + dc_sqlite3_close(dest_sql); + dc_sqlite3_unref(dest_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; +} +/* ****************************************************************************** + * Classic key import + ******************************************************************************/ +unsafe extern "C" fn import_self_keys( + mut context: *mut 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 + plain ASC keys, at least keys without a password, if we do not want to implement a password entry function. + Importing ASC keys is useful to use keys in Delta Chat used by any other non-Autocrypt-PGP implementation. + + 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 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 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 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()) + { + dir_handle = opendir(dir_name); + if dir_handle.is_null() { + dc_log_error( + context, + 0i32, + b"Import: Cannot open directory \"%s\".\x00" as *const u8 as *const libc::c_char, + dir_name, + ); + } else { + loop { + dir_entry = readdir(dir_handle); + if dir_entry.is_null() { + break; + } + free(suffix as *mut libc::c_void); + suffix = dc_get_filesuffix_lc((*dir_entry).d_name.as_mut_ptr()); + if suffix.is_null() + || strcmp(suffix, b"asc\x00" as *const u8 as *const libc::c_char) != 0i32 + { + continue; + } + free(path_plus_name as *mut libc::c_void); + path_plus_name = dc_mprintf( + b"%s/%s\x00" as *const u8 as *const libc::c_char, + dir_name, + (*dir_entry).d_name.as_mut_ptr(), + ); + dc_log_info( + context, + 0i32, + b"Checking: %s\x00" as *const u8 as *const libc::c_char, + path_plus_name, + ); + free(buf as *mut libc::c_void); + buf = 0 as *mut libc::c_char; + if 0 == dc_read_file( + context, + path_plus_name, + &mut buf as *mut *mut libc::c_char as *mut *mut libc::c_void, + &mut buf_bytes, + ) || buf_bytes < 50i32 as libc::c_ulong + { + continue; + } + private_key = buf; + free(buf2 as *mut libc::c_void); + buf2 = dc_strdup(buf); + if 0 != dc_split_armored_data( + buf2, + &mut buf2_headerline, + 0 as *mut *const libc::c_char, + 0 as *mut *const libc::c_char, + 0 as *mut *const libc::c_char, + ) && strcmp( + buf2_headerline, + b"-----BEGIN PGP PUBLIC KEY BLOCK-----\x00" as *const u8 as *const libc::c_char, + ) == 0i32 + { + private_key = strstr( + buf, + b"-----BEGIN PGP PRIVATE KEY BLOCK\x00" as *const u8 as *const libc::c_char, + ); + if private_key.is_null() { + /* this is no error but quite normal as we always export the public keys together with the private ones */ + continue; + } + } + set_default = 1i32; + if !strstr( + (*dir_entry).d_name.as_mut_ptr(), + b"legacy\x00" as *const u8 as *const libc::c_char, + ) + .is_null() + { + dc_log_info( + context, + 0i32, + b"Treating \"%s\" as a legacy private key.\x00" as *const u8 + as *const libc::c_char, + path_plus_name, + ); + set_default = 0i32 + } + if 0 == set_self_key(context, private_key, set_default) { + continue; + } + imported_cnt += 1 + } + if imported_cnt == 0i32 { + dc_log_error( + context, + 0i32, + b"No private keys found in \"%s\".\x00" as *const u8 as *const libc::c_char, + dir_name, + ); + } + } + } + if !dir_handle.is_null() { + closedir(dir_handle); + } + free(suffix as *mut libc::c_void); + 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; +} +unsafe extern "C" fn export_self_keys( + mut context: *mut 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 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, + b"SELECT id, public_key, private_key, is_default FROM keypairs;\x00" as *const u8 + as *const libc::c_char, + ); + if !stmt.is_null() { + while sqlite3_step(stmt) == 100i32 { + id = sqlite3_column_int(stmt, 0i32); + dc_key_set_from_stmt(public_key, stmt, 1i32, 0i32); + dc_key_set_from_stmt(private_key, stmt, 2i32, 1i32); + is_default = sqlite3_column_int(stmt, 3i32); + if 0 == export_key_to_asc_file(context, dir, id, public_key, is_default) { + export_errors += 1 + } + if 0 == export_key_to_asc_file(context, dir, id, private_key, is_default) { + export_errors += 1 + } + } + if export_errors == 0i32 { + success = 1i32 + } + } + sqlite3_finalize(stmt); + dc_key_unref(public_key); + dc_key_unref(private_key); + return success; +} +/* ****************************************************************************** + * Classic key export + ******************************************************************************/ +unsafe extern "C" fn export_key_to_asc_file( + mut context: *mut 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; + if 0 != is_default { + file_name = dc_mprintf( + b"%s/%s-key-default.asc\x00" as *const u8 as *const libc::c_char, + dir, + 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 + }, + ) + } else { + file_name = dc_mprintf( + b"%s/%s-key-%i.asc\x00" as *const u8 as *const libc::c_char, + dir, + 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 + }, + id, + ) + } + dc_log_info( + context, + 0i32, + b"Exporting key %s\x00" as *const u8 as *const libc::c_char, + file_name, + ); + dc_delete_file(context, file_name); + if 0 == dc_key_render_asc_to_file(key, file_name, context) { + dc_log_error( + context, + 0i32, + b"Cannot write key to %s\x00" as *const u8 as *const libc::c_char, + file_name, + ); + } else { + (*context).cb.expect("non-null function pointer")( + context, + 2052i32, + file_name as uintptr_t, + 0i32 as uintptr_t, + ); + success = 1i32 + } + free(file_name as *mut libc::c_void); + return success; +} diff --git a/src/dc_job.rs b/src/dc_job.rs new file mode 100644 index 000000000..5abffeb1b --- /dev/null +++ b/src/dc_job.rs @@ -0,0 +1,2652 @@ +use c2rust_bitfields::BitfieldStruct; +use libc; +extern "C" { + pub type mailstream_cancel; + pub type sqlite3; + pub type sqlite3_stmt; + #[no_mangle] + fn usleep(_: useconds_t) -> libc::c_int; + #[no_mangle] + fn pow(_: libc::c_double, _: libc::c_double) -> libc::c_double; + #[no_mangle] + fn free(_: *mut libc::c_void); + #[no_mangle] + fn rand() -> libc::c_int; + #[no_mangle] + fn memset(_: *mut libc::c_void, _: libc::c_int, _: libc::c_ulong) -> *mut libc::c_void; + #[no_mangle] + fn clock() -> clock_t; + #[no_mangle] + fn time(_: *mut time_t) -> time_t; + #[no_mangle] + fn pthread_cond_signal(_: *mut pthread_cond_t) -> libc::c_int; + #[no_mangle] + fn pthread_cond_timedwait( + _: *mut pthread_cond_t, + _: *mut pthread_mutex_t, + _: *const timespec, + ) -> libc::c_int; + #[no_mangle] + fn pthread_mutex_lock(_: *mut pthread_mutex_t) -> libc::c_int; + #[no_mangle] + fn pthread_mutex_unlock(_: *mut pthread_mutex_t) -> libc::c_int; + #[no_mangle] + fn clist_free(_: *mut clist); + #[no_mangle] + fn clist_insert_after(_: *mut clist, _: *mut clistiter, _: *mut libc::c_void) -> libc::c_int; + #[no_mangle] + fn dc_log_info(_: *mut dc_context_t, data1: libc::c_int, msg: *const libc::c_char, _: ...); + #[no_mangle] + fn sqlite3_finalize(pStmt: *mut sqlite3_stmt) -> libc::c_int; + #[no_mangle] + fn dc_param_unref(_: *mut dc_param_t); + /* tools, these functions are compatible to the corresponding sqlite3_* functions */ + #[no_mangle] + fn dc_sqlite3_prepare(_: *mut dc_sqlite3_t, sql: *const libc::c_char) -> *mut sqlite3_stmt; + #[no_mangle] + fn sqlite3_step(_: *mut sqlite3_stmt) -> libc::c_int; + #[no_mangle] + fn sqlite3_bind_int(_: *mut sqlite3_stmt, _: libc::c_int, _: libc::c_int) -> libc::c_int; + #[no_mangle] + fn dc_set_msg_failed(_: *mut dc_context_t, msg_id: uint32_t, error: *const libc::c_char); + #[no_mangle] + fn sqlite3_bind_text( + _: *mut sqlite3_stmt, + _: libc::c_int, + _: *const libc::c_char, + _: libc::c_int, + _: Option ()>, + ) -> libc::c_int; + #[no_mangle] + fn sqlite3_bind_int64(_: *mut sqlite3_stmt, _: libc::c_int, _: sqlite3_int64) -> libc::c_int; + #[no_mangle] + fn dc_jobthread_suspend(_: *mut dc_jobthread_t, suspend: libc::c_int); + /* housekeeping */ + #[no_mangle] + fn dc_housekeeping(_: *mut dc_context_t); + #[no_mangle] + fn dc_job_do_DC_JOB_MAYBE_SEND_LOC_ENDED(_: *mut dc_context_t, _: *mut dc_job_t); + #[no_mangle] + fn dc_job_do_DC_JOB_MAYBE_SEND_LOCATIONS(_: *mut dc_context_t, _: *mut dc_job_t); + #[no_mangle] + fn dc_job_do_DC_JOB_IMEX_IMAP(_: *mut dc_context_t, _: *mut dc_job_t); + // the other dc_job_do_DC_JOB_*() functions are declared static in the c-file + #[no_mangle] + fn dc_job_do_DC_JOB_CONFIGURE_IMAP(_: *mut dc_context_t, _: *mut dc_job_t); + /* clist tools */ + #[no_mangle] + fn clist_free_content(_: *const clist); + #[no_mangle] + fn sqlite3_column_int(_: *mut sqlite3_stmt, iCol: libc::c_int) -> libc::c_int; + #[no_mangle] + fn dc_update_msg_state(_: *mut dc_context_t, msg_id: uint32_t, state: libc::c_int); + #[no_mangle] + fn dc_delete_file(_: *mut dc_context_t, pathNFilename: *const libc::c_char) -> libc::c_int; + #[no_mangle] + fn dc_strdup_keep_null(_: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn dc_smtp_disconnect(_: *mut dc_smtp_t); + #[no_mangle] + fn dc_smtp_send_msg( + _: *mut dc_smtp_t, + recipients: *const clist, + data: *const libc::c_char, + data_bytes: size_t, + ) -> libc::c_int; + #[no_mangle] + fn dc_log_warning(_: *mut dc_context_t, data1: libc::c_int, msg: *const libc::c_char, _: ...); + /* 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 + #[no_mangle] + fn dc_msg_exists(_: *mut dc_context_t, msg_id: uint32_t) -> libc::c_int; + #[no_mangle] + fn dc_str_to_clist(_: *const libc::c_char, delimiter: *const libc::c_char) -> *mut clist; + #[no_mangle] + fn dc_param_get( + _: *const dc_param_t, + key: libc::c_int, + def: *const libc::c_char, + ) -> *mut libc::c_char; + #[no_mangle] + fn dc_read_file( + _: *mut dc_context_t, + pathNfilename: *const libc::c_char, + buf: *mut *mut libc::c_void, + buf_bytes: *mut size_t, + ) -> libc::c_int; + #[no_mangle] + fn dc_loginparam_new() -> *mut dc_loginparam_t; + #[no_mangle] + fn dc_smtp_connect(_: *mut dc_smtp_t, _: *const dc_loginparam_t) -> libc::c_int; + #[no_mangle] + fn dc_loginparam_unref(_: *mut dc_loginparam_t); + #[no_mangle] + fn dc_loginparam_read( + _: *mut dc_loginparam_t, + _: *mut dc_sqlite3_t, + prefix: *const libc::c_char, + ); + #[no_mangle] + fn dc_smtp_is_connected(_: *const dc_smtp_t) -> libc::c_int; + #[no_mangle] + fn dc_msg_new_untyped(_: *mut dc_context_t) -> *mut dc_msg_t; + #[no_mangle] + fn dc_msg_unref(_: *mut dc_msg_t); + #[no_mangle] + fn dc_update_server_uid( + _: *mut dc_context_t, + rfc724_mid: *const libc::c_char, + server_folder: *const libc::c_char, + server_uid: uint32_t, + ); + #[no_mangle] + fn dc_imap_move( + _: *mut dc_imap_t, + folder: *const libc::c_char, + uid: uint32_t, + dest_folder: *const libc::c_char, + dest_uid: *mut uint32_t, + ) -> dc_imap_res; + #[no_mangle] + fn dc_sqlite3_get_config( + _: *mut dc_sqlite3_t, + key: *const libc::c_char, + def: *const libc::c_char, + ) -> *mut libc::c_char; + #[no_mangle] + fn dc_configure_folders(_: *mut dc_context_t, _: *mut dc_imap_t, flags: libc::c_int); + #[no_mangle] + fn dc_sqlite3_get_config_int( + _: *mut dc_sqlite3_t, + key: *const libc::c_char, + def: int32_t, + ) -> int32_t; + #[no_mangle] + fn dc_msg_load_from_db(_: *mut dc_msg_t, _: *mut dc_context_t, id: uint32_t) -> libc::c_int; + #[no_mangle] + fn dc_imap_is_connected(_: *const dc_imap_t) -> libc::c_int; + #[no_mangle] + fn dc_imap_set_watch_folder(_: *mut dc_imap_t, watch_folder: *const libc::c_char); + #[no_mangle] + fn dc_connect_to_configured_imap(_: *mut dc_context_t, _: *mut dc_imap_t) -> libc::c_int; + #[no_mangle] + fn dc_param_get_int(_: *const dc_param_t, key: libc::c_int, def: int32_t) -> int32_t; + #[no_mangle] + fn dc_imap_set_seen( + _: *mut dc_imap_t, + folder: *const libc::c_char, + uid: uint32_t, + ) -> dc_imap_res; + #[no_mangle] + fn dc_mimefactory_empty(_: *mut dc_mimefactory_t); + /* library-private */ + #[no_mangle] + fn dc_param_new() -> *mut dc_param_t; + #[no_mangle] + fn dc_imap_interrupt_idle(_: *mut dc_imap_t); + #[no_mangle] + fn dc_param_set(_: *mut dc_param_t, key: libc::c_int, value: *const libc::c_char); + #[no_mangle] + fn dc_str_from_clist(_: *const clist, delimiter: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn dc_log_error(_: *mut dc_context_t, data1: libc::c_int, msg: *const libc::c_char, _: ...); + #[no_mangle] + fn dc_write_file( + _: *mut dc_context_t, + pathNfilename: *const libc::c_char, + buf: *const libc::c_void, + buf_bytes: size_t, + ) -> libc::c_int; + #[no_mangle] + fn dc_get_fine_pathNfilename( + _: *mut dc_context_t, + pathNfolder: *const libc::c_char, + desired_name: *const libc::c_char, + ) -> *mut libc::c_char; + #[no_mangle] + fn dc_mimefactory_render(_: *mut dc_mimefactory_t) -> libc::c_int; + #[no_mangle] + fn dc_mimefactory_load_mdn(_: *mut dc_mimefactory_t, msg_id: uint32_t) -> libc::c_int; + #[no_mangle] + fn dc_mimefactory_init(_: *mut dc_mimefactory_t, _: *mut dc_context_t); + #[no_mangle] + fn dc_imap_set_mdnsent( + _: *mut dc_imap_t, + folder: *const libc::c_char, + uid: uint32_t, + ) -> dc_imap_res; + #[no_mangle] + fn dc_delete_msg_from_db(_: *mut dc_context_t, _: uint32_t); + #[no_mangle] + fn dc_imap_delete_msg( + _: *mut dc_imap_t, + rfc724_mid: *const libc::c_char, + folder: *const libc::c_char, + server_uid: uint32_t, + ) -> libc::c_int; + #[no_mangle] + fn dc_rfc724_mid_cnt(_: *mut dc_context_t, rfc724_mid: *const libc::c_char) -> libc::c_int; + #[no_mangle] + fn sqlite3_column_int64(_: *mut sqlite3_stmt, iCol: libc::c_int) -> sqlite3_int64; + #[no_mangle] + fn sqlite3_column_text(_: *mut sqlite3_stmt, iCol: libc::c_int) -> *const libc::c_uchar; + #[no_mangle] + fn dc_param_set_packed(_: *mut dc_param_t, _: *const libc::c_char); + #[no_mangle] + fn dc_imap_fetch(_: *mut dc_imap_t) -> libc::c_int; + #[no_mangle] + fn dc_imap_idle(_: *mut dc_imap_t); + #[no_mangle] + fn dc_jobthread_fetch(_: *mut dc_jobthread_t, use_network: libc::c_int); + #[no_mangle] + fn dc_jobthread_idle(_: *mut dc_jobthread_t, use_network: libc::c_int); + #[no_mangle] + fn dc_jobthread_interrupt_idle(_: *mut dc_jobthread_t); + #[no_mangle] + fn dc_sqlite3_begin_transaction(_: *mut dc_sqlite3_t); + #[no_mangle] + fn dc_sqlite3_commit(_: *mut dc_sqlite3_t); + /* string tools */ + #[no_mangle] + fn dc_strdup(_: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn clist_search_string_nocase(_: *const clist, str: *const libc::c_char) -> libc::c_int; + #[no_mangle] + fn dc_get_filemeta( + buf: *const libc::c_void, + buf_bytes: size_t, + ret_width: *mut uint32_t, + ret_height: *mut uint32_t, + ) -> libc::c_int; + /* for msgs and jobs */ + /* for msgs */ + /* for msgs */ + /* for msgs */ + /* for msgs */ + /* for msgs: incoming: message is encryoted, outgoing: guarantee E2EE or the message is not send */ + /* for msgs: decrypted with validation errors or without mutual set, if neither 'c' nor 'e' are preset, the messages is only transport encrypted */ + /* for msgs: force unencrypted message, either DC_FP_ADD_AUTOCRYPT_HEADER (1), DC_FP_NO_AUTOCRYPT_HEADER (2) or 0 */ + /* for msgs: an incoming message which requestes a MDN (aka read receipt) */ + /* for msgs */ + /* for msgs */ + /* for msgs */ + /* for msgs */ + /* for msgs */ + /* for msgs */ + /* for msgs */ + /* for msgs in PREPARING: space-separated list of message IDs of forwarded copies */ + /* for jobs */ + /* for jobs */ + /* for jobs */ + /* for jobs: space-separated list of message recipients */ + /* for groups */ + /* for groups and contacts */ + /* for chats */ + // values for DC_PARAM_FORCE_PLAINTEXT + /* user functions */ + #[no_mangle] + fn dc_param_exists(_: *mut dc_param_t, key: libc::c_int) -> libc::c_int; + #[no_mangle] + fn dc_param_set_int(_: *mut dc_param_t, key: libc::c_int, value: int32_t); + #[no_mangle] + fn dc_set_gossiped_timestamp(_: *mut dc_context_t, chat_id: uint32_t, _: time_t); + #[no_mangle] + fn dc_msg_save_param_to_disk(_: *mut dc_msg_t); + /* yes: uppercase */ + /* library private: key-history */ + #[no_mangle] + fn dc_add_to_keyhistory( + _: *mut dc_context_t, + rfc724_mid: *const libc::c_char, + _: time_t, + addr: *const libc::c_char, + fingerprint: *const libc::c_char, + ); + #[no_mangle] + fn dc_set_msg_location_id(_: *mut dc_context_t, msg_id: uint32_t, location_id: uint32_t); + #[no_mangle] + fn dc_set_kml_sent_timestamp(_: *mut dc_context_t, chat_id: uint32_t, _: time_t); + #[no_mangle] + fn dc_mimefactory_load_msg(_: *mut dc_mimefactory_t, msg_id: uint32_t) -> libc::c_int; +} +pub type __uint32_t = libc::c_uint; +pub type __darwin_size_t = libc::c_ulong; +pub type __darwin_clock_t = libc::c_ulong; +pub type __darwin_ssize_t = libc::c_long; +pub type __darwin_time_t = libc::c_long; +pub type __darwin_useconds_t = __uint32_t; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_cond_t { + pub __sig: libc::c_long, + pub __opaque: [libc::c_char; 40], +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_mutex_t { + pub __sig: libc::c_long, + pub __opaque: [libc::c_char; 56], +} +pub type __darwin_pthread_cond_t = _opaque_pthread_cond_t; +pub type __darwin_pthread_mutex_t = _opaque_pthread_mutex_t; +pub type size_t = __darwin_size_t; +pub type uint32_t = libc::c_uint; +pub type int32_t = libc::c_int; +pub type uintptr_t = libc::c_ulong; +pub type ssize_t = __darwin_ssize_t; +pub type useconds_t = __darwin_useconds_t; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct timespec { + pub tv_sec: __darwin_time_t, + pub tv_nsec: libc::c_long, +} +pub type time_t = __darwin_time_t; +pub type uint8_t = libc::c_uchar; +pub type uint16_t = libc::c_ushort; +pub type clock_t = __darwin_clock_t; + +// pub type pthread_cond_t = __darwin_pthread_cond_t; +// pub type pthread_mutex_t = __darwin_pthread_mutex_t; +#[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; +#[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) -> (); +#[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; +pub type unnamed = libc::c_uint; +pub const MAILSMTP_ERROR_CLIENTID_NOT_SUPPORTED: unnamed = 28; +pub const MAILSMTP_ERROR_SSL: unnamed = 27; +pub const MAILSMTP_ERROR_AUTH_AUTHENTICATION_FAILED: unnamed = 26; +pub const MAILSMTP_ERROR_CONNECTION_REFUSED: unnamed = 25; +pub const MAILSMTP_ERROR_STARTTLS_NOT_SUPPORTED: unnamed = 24; +pub const MAILSMTP_ERROR_STARTTLS_TEMPORARY_FAILURE: unnamed = 23; +pub const MAILSMTP_ERROR_AUTH_ENCRYPTION_REQUIRED: unnamed = 22; +pub const MAILSMTP_ERROR_AUTH_TEMPORARY_FAILTURE: unnamed = 21; +pub const MAILSMTP_ERROR_AUTH_TRANSITION_NEEDED: unnamed = 20; +pub const MAILSMTP_ERROR_AUTH_TOO_WEAK: unnamed = 19; +pub const MAILSMTP_ERROR_AUTH_REQUIRED: unnamed = 18; +pub const MAILSMTP_ERROR_AUTH_LOGIN: unnamed = 17; +pub const MAILSMTP_ERROR_AUTH_NOT_SUPPORTED: unnamed = 16; +pub const MAILSMTP_ERROR_MEMORY: unnamed = 15; +pub const MAILSMTP_ERROR_TRANSACTION_FAILED: unnamed = 14; +pub const MAILSMTP_ERROR_USER_NOT_LOCAL: unnamed = 13; +pub const MAILSMTP_ERROR_BAD_SEQUENCE_OF_COMMAND: unnamed = 12; +pub const MAILSMTP_ERROR_MAILBOX_NAME_NOT_ALLOWED: unnamed = 11; +pub const MAILSMTP_ERROR_MAILBOX_UNAVAILABLE: unnamed = 10; +pub const MAILSMTP_ERROR_INSUFFICIENT_SYSTEM_STORAGE: unnamed = 9; +pub const MAILSMTP_ERROR_IN_PROCESSING: unnamed = 8; +pub const MAILSMTP_ERROR_EXCEED_STORAGE_ALLOCATION: unnamed = 7; +pub const MAILSMTP_ERROR_ACTION_NOT_TAKEN: unnamed = 6; +pub const MAILSMTP_ERROR_NOT_IMPLEMENTED: unnamed = 5; +pub const MAILSMTP_ERROR_HOSTNAME: unnamed = 4; +pub const MAILSMTP_ERROR_STREAM: unnamed = 3; +pub const MAILSMTP_ERROR_SERVICE_NOT_AVAILABLE: unnamed = 2; +pub const MAILSMTP_ERROR_UNEXPECTED_CODE: unnamed = 1; +pub const MAILSMTP_NO_ERROR: unnamed = 0; +#[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_capability_data { + pub cap_list: *mut clist, +} +#[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_1, + 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_1 { + 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 extern "C" 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_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, +} +#[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_2, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed_2 { + pub ft_fetch_att: *mut mailimap_fetch_att, + pub ft_fetch_att_list: *mut clist, +} +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_3, + 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 unnamed_3 { + 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, +} +/* define DC_USE_RPGP to enable use of rPGP instead of netpgp where available; +preferrably, this should be done in the project configuration currently */ +//#define DC_USE_RPGP 1 +/* Includes that are used frequently. This file may also be used to create predefined headers. */ +/* * Structure behind dc_context_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_context { + pub magic: uint32_t, + pub userdata: *mut libc::c_void, + pub dbfile: *mut libc::c_char, + pub blobdir: *mut libc::c_char, + pub sql: *mut dc_sqlite3_t, + pub inbox: *mut dc_imap_t, + pub inboxidle_condmutex: pthread_mutex_t, + pub perform_inbox_jobs_needed: libc::c_int, + pub probe_imap_network: libc::c_int, + pub sentbox_thread: dc_jobthread_t, + pub mvbox_thread: dc_jobthread_t, + pub smtp: *mut dc_smtp_t, + pub smtpidle_cond: pthread_cond_t, + pub smtpidle_condmutex: pthread_mutex_t, + pub smtpidle_condflag: libc::c_int, + pub smtp_suspended: libc::c_int, + pub smtp_doing_jobs: libc::c_int, + pub perform_smtp_jobs_needed: libc::c_int, + pub probe_smtp_network: libc::c_int, + pub oauth2_critical: pthread_mutex_t, + 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 type dc_lot_t = _dc_lot; +/* * Structure behind dc_lot_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_lot { + pub magic: uint32_t, + pub text1_meaning: libc::c_int, + pub text1: *mut libc::c_char, + pub text2: *mut libc::c_char, + pub timestamp: time_t, + pub state: libc::c_int, + pub id: uint32_t, + pub fingerprint: *mut libc::c_char, + pub invitenumber: *mut libc::c_char, + pub auth: *mut libc::c_char, +} +/* * + * 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 = Option< + unsafe extern "C" fn( + _: *mut dc_context_t, + _: libc::c_int, + _: uintptr_t, + _: uintptr_t, + ) -> uintptr_t, +>; +/* * + * @mainpage Getting started + * + * This document describes how to handle the Delta Chat core library. + * For general information about Delta Chat itself, + * see and . + * + * Let's start. + * + * First of all, you have to **define an event-handler-function** + * that is called by the library on specific events + * (eg. when the configuration is done or when fresh messages arrive). + * With this function you can create a Delta Chat context then: + * + * ~~~ + * #include + * + * uintptr_t event_handler_func(dc_context_t* context, int event, + * uintptr_t data1, uintptr_t data2) + * { + * return 0; // for unhandled events, it is always safe to return 0 + * } + * + * dc_context_t* context = dc_context_new(event_handler_func, NULL, NULL); + * ~~~ + * + * After that, you should make sure, + * sending and receiving jobs are processed as needed. + * For this purpose, you have to **create two threads:** + * + * ~~~ + * #include + * + * void* imap_thread_func(void* context) + * { + * while (true) { + * dc_perform_imap_jobs(context); + * dc_perform_imap_fetch(context); + * dc_perform_imap_idle(context); + * } + * } + * + * void* smtp_thread_func(void* context) + * { + * while (true) { + * dc_perform_smtp_jobs(context); + * dc_perform_smtp_idle(context); + * } + * } + * + * static pthread_t imap_thread, smtp_thread; + * pthread_create(&imap_thread, NULL, imap_thread_func, context); + * pthread_create(&smtp_thread, NULL, smtp_thread_func, context); + * ~~~ + * + * The example above uses "pthreads", + * however, you can also use anything else for thread handling. + * NB: The deltachat-core library itself does not create any threads on its own, + * however, functions, unless stated otherwise, are thread-safe. + * + * After that you can **define and open a database.** + * The database is a normal sqlite-file and is created as needed: + * + * ~~~ + * dc_open(context, "example.db", NULL); + * ~~~ + * + * Now you can **configure the context:** + * + * ~~~ + * // use some real test credentials here + * dc_set_config(context, "addr", "alice@example.org"); + * dc_set_config(context, "mail_pw", "***"); + * dc_configure(context); + * ~~~ + * + * dc_configure() returns immediately, the configuration itself may take a while + * and is done by a job in the imap-thread you've defined above. + * Once done, the #DC_EVENT_CONFIGURE_PROGRESS reports success + * to the event_handler_func() that is also defined above. + * + * The configuration result is saved in the database, + * on subsequent starts it is not needed to call dc_configure() + * (you can check this using dc_is_configured()). + * + * Now you can **send the first message:** + * + * ~~~ + * // use a real testing address here + * uint32_t contact_id = dc_create_contact(context, NULL, "bob@example.org"); + * uint32_t chat_id = dc_create_chat_by_contact_id(context, contact_id); + * + * dc_send_text_msg(context, chat_id, "Hi, here is my first message!"); + * ~~~ + * + * dc_send_text_msg() returns immediately; + * the sending itself is done by a job in the smtp-thread you've defined above. + * If you check the testing address (bob) + * and you should have received a normal email. + * Answer this email in any email program with "Got it!" + * and the imap-thread you've create above will **receive the message**. + * + * You can then **list all messages** of a chat as follow: + * + * ~~~ + * dc_array_t* msglist = dc_get_chat_msgs(context, chat_id, 0, 0); + * for (int i = 0; i < dc_array_get_cnt(msglist); i++) + * { + * uint32_t msg_id = dc_array_get_id(msglist, i); + * dc_msg_t* msg = dc_get_msg(context, msg_id); + * char* text = dc_msg_get_text(msg); + * + * printf("Message %i: %s\n", i+1, text); + * + * free(text); + * dc_msg_unref(msg); + * } + * dc_array_unref(msglist); + * ~~~ + * + * This will output the following two lines: + * + * ~~~ + * Message 1: Hi, here is my first message! + * Message 2: Got it! + * ~~~ + * + * + * ## Class reference + * + * For a class reference, see the "Classes" link atop. + * + * + * ## Further hints + * + * Here are some additional, unsorted hints that may be useful. + * + * - For `get`-functions, you have to unref the return value in some way. + * + * - Strings in function arguments or return values are usually UTF-8 encoded. + * + * - The issue-tracker for the core library is here: + * + * + * The following points are important mainly + * for the authors of the library itself: + * + * - For indentation, use tabs. + * Alignments that are not placed at the beginning of a line + * should be done with spaces. + * + * - For padding between functions, + * classes etc. use 2 empty lines + * + * - Source files are encoded as UTF-8 with Unix line endings + * (a simple `LF`, `0x0A` or `\n`) + * + * If you need further assistance, + * please do not hesitate to contact us + * through the channels shown at https://delta.chat/en/contribute + * + * Please keep in mind, that your derived work + * must respect the Mozilla Public License 2.0 of libdeltachat + * and the respective licenses of the libraries libdeltachat links with. + * + * See you. + */ +/* * + * @class dc_context_t + * + * An object representing a single account. + * + * Each account is linked to an IMAP/SMTP account and uses a separate + * SQLite database for offline functionality and for account-related + * settings. + */ +// pub type dc_context_t = _dc_context; +use crate::dc_context::*; +/* ** library-private **********************************************************/ +//pub type dc_smtp_t = _dc_smtp; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_smtp { + 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 error: *mut libc::c_char, + pub error_etpan: libc::c_int, +} +//pub type dc_jobthread_t = _dc_jobthread; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_jobthread { + 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, + 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, +} +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_imap { + 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 type dc_receive_imf_t = Option< + unsafe extern "C" 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_imap_t = _dc_imap; +pub type dc_precheck_imf_t = Option< + unsafe extern "C" 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< + unsafe extern "C" fn(_: *mut dc_imap_t, _: *const libc::c_char, _: *const libc::c_char) -> (), +>; +pub type dc_get_config_t = Option< + unsafe extern "C" fn( + _: *mut dc_imap_t, + _: *const libc::c_char, + _: *const libc::c_char, + ) -> *mut libc::c_char, +>; +/* ** library-private **********************************************************/ +//pub type dc_sqlite3_t = _dc_sqlite3; +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_sqlite3 { + pub cobj: *mut sqlite3, + pub context: *mut dc_context_t, +} +/* values for the chats.blocked database field */ +/* * the structure behind dc_chat_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_chat { + 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 grpid: *mut libc::c_char, + pub blocked: libc::c_int, + pub param: *mut dc_param_t, + pub gossiped_timestamp: time_t, + pub is_sending_locations: libc::c_int, +} +pub type dc_param_t = _dc_param; +/* * + * @class dc_param_t + * + * An object for handling key=value parameter lists; for the key, curently only + * a single character is allowed. + * + * The object is used eg. by dc_chat_t or dc_msg_t, for readable paramter names, + * these classes define some DC_PARAM_* constantats. + * + * Only for library-internal use. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_param { + pub packed: *mut libc::c_char, +} +pub type dc_chat_t = _dc_chat; +/* * the structure behind dc_msg_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_msg { + pub magic: uint32_t, + pub id: uint32_t, + pub from_id: uint32_t, + pub to_id: uint32_t, + pub chat_id: uint32_t, + pub move_state: dc_move_state_t, + pub type_0: libc::c_int, + pub state: libc::c_int, + pub hidden: libc::c_int, + pub timestamp_sort: time_t, + pub timestamp_sent: time_t, + pub timestamp_rcvd: time_t, + pub text: *mut libc::c_char, + pub context: *mut 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, + pub server_uid: uint32_t, + pub is_dc_message: libc::c_int, + pub starred: libc::c_int, + pub chat_blocked: libc::c_int, + pub location_id: uint32_t, + pub param: *mut dc_param_t, +} +pub type dc_move_state_t = libc::c_uint; +pub const DC_MOVE_STATE_MOVING: dc_move_state_t = 3; +pub const DC_MOVE_STATE_STAY: dc_move_state_t = 2; +pub const DC_MOVE_STATE_PENDING: dc_move_state_t = 1; +pub const DC_MOVE_STATE_UNDEFINED: dc_move_state_t = 0; +pub type dc_msg_t = _dc_msg; +// thread IDs +// jobs in the INBOX-thread, range from DC_IMAP_THREAD..DC_IMAP_THREAD+999 +// low priority ... +// ... high priority +// jobs in the SMTP-thread, range from DC_SMTP_THREAD..DC_SMTP_THREAD+999 +// low priority ... +// ... high priority +// timeouts until actions are aborted. +// this may also affects IDLE to return, so a re-connect may take this time. +// mailcore2 uses 30 seconds, k-9 uses 10 seconds +pub type dc_job_t = _dc_job; +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_job { + pub job_id: uint32_t, + pub action: libc::c_int, + pub foreign_id: uint32_t, + pub desired_timestamp: time_t, + pub added_timestamp: time_t, + pub tries: libc::c_int, + pub param: *mut dc_param_t, + pub try_again: libc::c_int, + pub pending_error: *mut libc::c_char, +} +pub type sqlite3_destructor_type = Option ()>; +pub type sqlite3_int64 = sqlite_int64; +pub type sqlite_int64 = libc::c_longlong; +pub type dc_loginparam_t = _dc_loginparam; +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_loginparam { + pub addr: *mut libc::c_char, + pub mail_server: *mut libc::c_char, + pub mail_user: *mut libc::c_char, + pub mail_pw: *mut libc::c_char, + pub mail_port: uint16_t, + pub send_server: *mut libc::c_char, + pub send_user: *mut libc::c_char, + pub send_pw: *mut libc::c_char, + pub send_port: libc::c_int, + pub server_flags: libc::c_int, +} +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_imap_res = libc::c_uint; +pub type dc_mimefactory_t = _dc_mimefactory; +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_mimefactory { + pub from_addr: *mut libc::c_char, + pub from_displayname: *mut libc::c_char, + pub selfstatus: *mut libc::c_char, + pub recipients_names: *mut clist, + pub recipients_addr: *mut clist, + 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 increation: libc::c_int, + pub in_reply_to: *mut libc::c_char, + pub references: *mut libc::c_char, + pub req_mdn: libc::c_int, + pub out: *mut MMAPString, + pub out_encrypted: libc::c_int, + 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 type dc_mimefactory_loaded_t = libc::c_uint; +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; +#[no_mangle] +pub unsafe extern "C" fn dc_perform_imap_jobs(mut context: *mut 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); + dc_log_info( + context, + 0i32, + b"INBOX-jobs ended.\x00" as *const u8 as *const libc::c_char, + ); +} +unsafe extern "C" fn dc_job_perform( + mut context: *mut 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 { + job_id: 0, + action: 0, + foreign_id: 0, + desired_timestamp: 0, + added_timestamp: 0, + tries: 0, + param: 0 as *mut dc_param_t, + try_again: 0, + pending_error: 0 as *mut libc::c_char, + }; + memset( + &mut job as *mut dc_job_t as *mut libc::c_void, + 0i32, + ::std::mem::size_of::() as libc::c_ulong, + ); + 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" + 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, + ); + 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(&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, + 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 { + 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, tries_0, + 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 !(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 extern "C" fn dc_job_delete(mut context: *mut dc_context_t, mut job: *const dc_job_t) { + let mut delete_stmt: *mut sqlite3_stmt = dc_sqlite3_prepare( + (*context).sql, + 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_step(delete_stmt); + sqlite3_finalize(delete_stmt); +} +/* ****************************************************************************** + * Tools + ******************************************************************************/ +unsafe extern "C" fn get_backoff_time_offset(mut c_tries: libc::c_int) -> time_t { + // results in ~3 weeks for the last backoff timespan + let mut N: time_t = pow(2i32 as libc::c_double, (c_tries - 1i32) as libc::c_double) as time_t; + N = N * 60i32 as libc::c_long; + let mut seconds: time_t = rand() as libc::c_long % (N + 1i32 as libc::c_long); + if seconds < 1i32 as libc::c_long { + seconds = 1i32 as time_t + } + return seconds; +} +unsafe extern "C" fn dc_job_update(mut context: *mut dc_context_t, mut job: *const dc_job_t) { + let mut stmt: *mut sqlite3_stmt = dc_sqlite3_prepare( + (*context).sql, + 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_step(stmt); + sqlite3_finalize(stmt); +} +unsafe extern "C" 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); + if 0 != suspend { + loop { + pthread_mutex_lock(&mut (*context).smtpidle_condmutex); + if (*context).smtp_doing_jobs == 0i32 { + pthread_mutex_unlock(&mut (*context).smtpidle_condmutex); + return; + } + pthread_mutex_unlock(&mut (*context).smtpidle_condmutex); + usleep((300i32 * 1000i32) as useconds_t); + } + }; +} +unsafe extern "C" fn dc_job_do_DC_JOB_SEND(mut context: *mut dc_context_t, mut 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) { + let mut loginparam: *mut dc_loginparam_t = dc_loginparam_new(); + dc_loginparam_read( + loginparam, + (*context).sql, + b"configured_\x00" as *const u8 as *const libc::c_char, + ); + let mut connected: libc::c_int = dc_smtp_connect((*context).smtp, loginparam); + dc_loginparam_unref(loginparam); + if 0 == connected { + dc_job_try_again_later(job, 3i32, 0 as *const libc::c_char); + current_block = 14216916617354591294; + } else { + current_block = 13109137661213826276; + } + } else { + current_block = 13109137661213826276; + } + match current_block { + 13109137661213826276 => { + 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, + ); + } 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); + 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, + ); + } else { + recipients_list = dc_str_to_clist( + recipients, + b"\x1e\x00" as *const u8 as *const libc::c_char, + ); + /* 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) { + 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, + ); + current_block = 14216916617354591294; + } else { + current_block = 11194104282611034094; + } + } else { + current_block = 11194104282611034094; + } + match current_block { + 14216916617354591294 => {} + _ => { + /* send message */ + if 0 == dc_smtp_send_msg( + (*context).smtp, + recipients_list, + buf as *const libc::c_char, + buf_bytes, + ) { + 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); + } + } else { + dc_delete_file(context, filename); + if 0 != (*job).foreign_id { + dc_update_msg_state(context, (*job).foreign_id, 26i32); + stmt = dc_sqlite3_prepare( + (*context).sql, + 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); + let mut chat_id: libc::c_int = if sqlite3_step(stmt) == 100i32 { + sqlite3_column_int(stmt, 0i32) + } else { + 0i32 + }; + (*context).cb.expect("non-null function pointer")( + context, + 2010i32, + chat_id as uintptr_t, + (*job).foreign_id as uintptr_t, + ); + } + } + } + } + } + } + } + _ => {} + } + 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 +#[no_mangle] +pub unsafe extern "C" 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, +) { + 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); +} +unsafe extern "C" fn dc_job_do_DC_JOB_MOVE_MSG( + mut context: *mut dc_context_t, + mut 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) { + dc_job_try_again_later(job, 3i32, 0 as *const libc::c_char); + current_block = 2238328302157162973; + } else { + current_block = 2473556513754201174; + } + } else { + current_block = 2473556513754201174; + } + match current_block { + 2473556513754201174 => { + if !(0 == dc_msg_load_from_db(msg, context, (*job).foreign_id)) { + if dc_sqlite3_get_config_int( + (*context).sql, + b"folders_configured\x00" as *const u8 as *const libc::c_char, + 0i32, + ) < 3i32 + { + dc_configure_folders(context, (*context).inbox, 0x1i32); + } + dest_folder = dc_sqlite3_get_config( + (*context).sql, + 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, + (*msg).server_uid, + dest_folder, + &mut dest_uid, + ) as libc::c_uint + { + 1 => { + current_block = 6379107252614456477; + match current_block { + 12072121998757195963 => { + dc_update_server_uid( + context, + (*msg).rfc724_mid, + dest_folder, + dest_uid, + ); + } + _ => { + dc_job_try_again_later(job, 3i32, 0 as *const libc::c_char); + } + } + } + 3 => { + current_block = 12072121998757195963; + match current_block { + 12072121998757195963 => { + dc_update_server_uid( + context, + (*msg).rfc724_mid, + dest_folder, + dest_uid, + ); + } + _ => { + dc_job_try_again_later(job, 3i32, 0 as *const libc::c_char); + } + } + } + 0 | 2 | _ => {} + } + } + } + _ => {} + } + free(dest_folder as *mut libc::c_void); + dc_msg_unref(msg); +} +/* ****************************************************************************** + * IMAP-jobs + ******************************************************************************/ +unsafe extern "C" 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); + if !(0 == ret_connected) { + dc_imap_set_watch_folder( + (*context).inbox, + b"INBOX\x00" as *const u8 as *const libc::c_char, + ); + } + return ret_connected; +} +unsafe extern "C" fn dc_job_do_DC_JOB_MARKSEEN_MDN_ON_IMAP( + mut context: *mut dc_context_t, + mut job: *mut dc_job_t, +) { + let mut current_block: u64; + let mut folder: *mut libc::c_char = + dc_param_get((*job).param, 'Z' as i32, 0 as *const libc::c_char); + let mut uid: uint32_t = dc_param_get_int((*job).param, 'z' as i32, 0i32) as uint32_t; + let mut dest_folder: *mut libc::c_char = 0 as *mut libc::c_char; + let mut dest_uid: uint32_t = 0i32 as uint32_t; + if 0 == dc_imap_is_connected((*context).inbox) { + connect_to_inbox(context); + if 0 == dc_imap_is_connected((*context).inbox) { + dc_job_try_again_later(job, 3i32, 0 as *const libc::c_char); + current_block = 2670689566614003383; + } else { + current_block = 11006700562992250127; + } + } else { + current_block = 11006700562992250127; + } + match current_block { + 11006700562992250127 => { + if dc_imap_set_seen((*context).inbox, 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 dc_sqlite3_get_config_int( + (*context).sql, + b"folders_configured\x00" as *const u8 as *const libc::c_char, + 0i32, + ) < 3i32 + { + dc_configure_folders(context, (*context).inbox, 0x1i32); + } + dest_folder = dc_sqlite3_get_config( + (*context).sql, + 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 + { + 1 => { + dc_job_try_again_later(job, 3i32, 0 as *const libc::c_char); + } + 0 | _ => {} + } + } + } + _ => {} + } + free(folder as *mut libc::c_void); + free(dest_folder as *mut libc::c_void); +} +unsafe extern "C" fn dc_job_do_DC_JOB_MARKSEEN_MSG_ON_IMAP( + mut context: *mut dc_context_t, + mut 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) { + dc_job_try_again_later(job, 3i32, 0 as *const libc::c_char); + current_block = 17792648348530113339; + } else { + current_block = 15240798224410183470; + } + } else { + current_block = 15240798224410183470; + } + 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 + { + 0 => {} + 1 => { + current_block = 12392248546350854223; + match current_block { + 12392248546350854223 => { + dc_job_try_again_later(job, 3i32, 0 as *const libc::c_char); + } + _ => { + if 0 != dc_param_get_int((*msg).param, 'r' as i32, 0i32) + && 0 != dc_sqlite3_get_config_int( + (*context).sql, + 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 + { + 1 => { + current_block = 4016212065805849280; + match current_block { + 6186957421461061791 => { + dc_send_mdn(context, (*msg).id); + } + _ => { + dc_job_try_again_later( + job, + 3i32, + 0 as *const libc::c_char, + ); + } + } + } + 3 => { + current_block = 6186957421461061791; + match current_block { + 6186957421461061791 => { + dc_send_mdn(context, (*msg).id); + } + _ => { + dc_job_try_again_later( + job, + 3i32, + 0 as *const libc::c_char, + ); + } + } + } + 0 | 2 | _ => {} + } + } + } + } + } + _ => { + current_block = 7746791466490516765; + match current_block { + 12392248546350854223 => { + dc_job_try_again_later(job, 3i32, 0 as *const libc::c_char); + } + _ => { + if 0 != dc_param_get_int((*msg).param, 'r' as i32, 0i32) + && 0 != dc_sqlite3_get_config_int( + (*context).sql, + 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 + { + 1 => { + current_block = 4016212065805849280; + match current_block { + 6186957421461061791 => { + dc_send_mdn(context, (*msg).id); + } + _ => { + dc_job_try_again_later( + job, + 3i32, + 0 as *const libc::c_char, + ); + } + } + } + 3 => { + current_block = 6186957421461061791; + match current_block { + 6186957421461061791 => { + dc_send_mdn(context, (*msg).id); + } + _ => { + dc_job_try_again_later( + job, + 3i32, + 0 as *const libc::c_char, + ); + } + } + } + 0 | 2 | _ => {} + } + } + } + } + } + } + } + } + _ => {} + } + dc_msg_unref(msg); +} +unsafe extern "C" fn dc_send_mdn(mut context: *mut dc_context_t, mut msg_id: uint32_t) { + let mut mimefactory: dc_mimefactory_t = _dc_mimefactory { + from_addr: 0 as *mut libc::c_char, + from_displayname: 0 as *mut libc::c_char, + selfstatus: 0 as *mut libc::c_char, + recipients_names: 0 as *mut clist, + recipients_addr: 0 as *mut clist, + timestamp: 0, + rfc724_mid: 0 as *mut libc::c_char, + loaded: DC_MF_NOTHING_LOADED, + msg: 0 as *mut dc_msg_t, + chat: 0 as *mut dc_chat_t, + increation: 0, + in_reply_to: 0 as *mut libc::c_char, + references: 0 as *mut libc::c_char, + req_mdn: 0, + out: 0 as *mut MMAPString, + out_encrypted: 0, + out_gossiped: 0, + out_last_added_location_id: 0, + error: 0 as *mut libc::c_char, + context: 0 as *mut dc_context_t, + }; + 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)) + { + dc_add_smtp_job(context, 5011i32, &mut mimefactory); + } + dc_mimefactory_empty(&mut mimefactory); +} +/* ****************************************************************************** + * SMTP-jobs + ******************************************************************************/ +/* * + * Store the MIME message in a file and send it later with a new SMTP job. + * + * @param context The context object as created by dc_context_new() + * @param action One of the DC_JOB_SEND_ constants + * @param mimefactory An instance of dc_mimefactory_t with a loaded and rendered message or MDN + * @return 1=success, 0=error + */ +unsafe extern "C" fn dc_add_smtp_job( + mut context: *mut 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 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(); + pathNfilename = dc_get_fine_pathNfilename( + context, + b"$BLOBDIR\x00" as *const u8 as *const libc::c_char, + (*mimefactory).rfc724_mid, + ); + if pathNfilename.is_null() { + dc_log_error( + context, + 0i32, + b"Could not find free file name for message with ID <%s>.\x00" as *const u8 + as *const libc::c_char, + (*mimefactory).rfc724_mid, + ); + } else if 0 + == dc_write_file( + context, + pathNfilename, + (*(*mimefactory).out).str_0 as *const libc::c_void, + (*(*mimefactory).out).len, + ) + { + dc_log_error( + context, + 0i32, + b"Could not write message <%s> to \"%s\".\x00" as *const u8 as *const libc::c_char, + (*mimefactory).rfc724_mid, + pathNfilename, + ); + } else { + recipients = dc_str_from_clist( + (*mimefactory).recipients_addr, + b"\x1e\x00" as *const u8 as *const libc::c_char, + ); + dc_param_set(param, 'f' as i32, pathNfilename); + dc_param_set(param, 'R' as i32, recipients); + dc_job_add( + context, + action, + (if (*mimefactory).loaded as libc::c_uint + == DC_MF_MSG_LOADED as libc::c_int as libc::c_uint + { + (*(*mimefactory).msg).id + } else { + 0i32 as libc::c_uint + }) as libc::c_int, + (*param).packed, + 0i32, + ); + success = 1i32 + } + dc_param_unref(param); + free(recipients as *mut libc::c_void); + free(pathNfilename as *mut libc::c_void); + return success; +} +#[no_mangle] +pub unsafe extern "C" fn dc_job_add( + mut context: *mut 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; + if action >= 100i32 && action < 100i32 + 1000i32 { + thread = 100i32 + } else if action >= 5000i32 && action < 5000i32 + 1000i32 { + thread = 5000i32 + } else { + return; + } + stmt = + dc_sqlite3_prepare((*context).sql, + 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); + sqlite3_bind_int(stmt, 3i32, action); + sqlite3_bind_int(stmt, 4i32, foreign_id); + sqlite3_bind_text( + stmt, + 5i32, + if !param.is_null() { + param + } else { + b"\x00" as *const u8 as *const libc::c_char + }, + -1i32, + None, + ); + sqlite3_bind_int64( + stmt, + 6i32, + (timestamp + delay_seconds as libc::c_long) as sqlite3_int64, + ); + sqlite3_step(stmt); + sqlite3_finalize(stmt); + if thread == 100i32 { + dc_interrupt_imap_idle(context); + } else { + dc_interrupt_smtp_idle(context); + }; +} +#[no_mangle] +pub unsafe extern "C" 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; + } + 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); +} +#[no_mangle] +pub unsafe extern "C" 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; + } + 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); +} +unsafe extern "C" fn dc_job_do_DC_JOB_DELETE_MSG_ON_IMAP( + mut context: *mut dc_context_t, + mut job: *mut dc_job_t, +) { + let mut current_block: u64; + let mut delete_from_server: libc::c_int = 1i32; + let mut msg: *mut dc_msg_t = dc_msg_new_untyped(context); + 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) + { + /* eg. device messages have no Message-ID */ + if dc_rfc724_mid_cnt(context, (*msg).rfc724_mid) != 1i32 { + dc_log_info( + context, + 0i32, + b"The message is deleted from the server when all parts are deleted.\x00" + as *const u8 as *const libc::c_char, + ); + delete_from_server = 0i32 + } + /* if this is the last existing part of the message, we delete the message from the server */ + if 0 != delete_from_server { + if 0 == dc_imap_is_connected((*context).inbox) { + connect_to_inbox(context); + if 0 == dc_imap_is_connected((*context).inbox) { + dc_job_try_again_later(job, 3i32, 0 as *const libc::c_char); + current_block = 8913536887710889399; + } else { + current_block = 5399440093318478209; + } + } else { + current_block = 5399440093318478209; + } + match current_block { + 8913536887710889399 => {} + _ => { + if 0 == dc_imap_delete_msg( + (*context).inbox, + (*msg).rfc724_mid, + (*msg).server_folder, + (*msg).server_uid, + ) { + dc_job_try_again_later(job, -1i32, 0 as *const libc::c_char); + current_block = 8913536887710889399; + } else { + current_block = 17407779659766490442; + } + } + } + } else { + current_block = 17407779659766490442; + } + match current_block { + 8913536887710889399 => {} + _ => { + dc_delete_msg_from_db(context, (*msg).id); + } + } + } + dc_msg_unref(msg); +} +/* delete all pending jobs with the given action */ +#[no_mangle] +pub unsafe extern "C" 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, + 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); +} +#[no_mangle] +pub unsafe extern "C" fn dc_perform_imap_fetch(mut context: *mut dc_context_t) { + let mut start: clock_t = clock(); + if 0 == connect_to_inbox(context) { + return; + } + if dc_sqlite3_get_config_int( + (*context).sql, + b"inbox_watch\x00" as *const u8 as *const libc::c_char, + 1i32, + ) == 0i32 + { + dc_log_info( + context, + 0i32, + b"INBOX-watch disabled.\x00" as *const u8 as *const libc::c_char, + ); + return; + } + dc_log_info( + context, + 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 { + 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); + } + dc_log_info( + context, + 0i32, + b"INBOX-fetch done in %.0f ms.\x00" as *const u8 as *const libc::c_char, + clock().wrapping_sub(start) as libc::c_double * 1000.0f64 / 1000000i32 as libc::c_double, + ); +} +#[no_mangle] +pub unsafe extern "C" 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 { + 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); + dc_log_info( + context, + 0i32, + b"INBOX-IDLE ended.\x00" as *const u8 as *const libc::c_char, + ); +} +#[no_mangle] +pub unsafe extern "C" fn dc_perform_mvbox_fetch(mut context: *mut dc_context_t) { + if context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint { + return; + } + let mut use_network: libc::c_int = dc_sqlite3_get_config_int( + (*context).sql, + b"mvbox_watch\x00" as *const u8 as *const libc::c_char, + 1i32, + ); + dc_jobthread_fetch(&mut (*context).mvbox_thread, use_network); +} +#[no_mangle] +pub unsafe extern "C" fn dc_perform_mvbox_idle(mut context: *mut dc_context_t) { + if context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint { + return; + } + let mut use_network: libc::c_int = dc_sqlite3_get_config_int( + (*context).sql, + b"mvbox_watch\x00" as *const u8 as *const libc::c_char, + 1i32, + ); + dc_jobthread_idle(&mut (*context).mvbox_thread, use_network); +} +#[no_mangle] +pub unsafe extern "C" 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); +} +#[no_mangle] +pub unsafe extern "C" fn dc_perform_sentbox_fetch(mut context: *mut dc_context_t) { + if context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint { + return; + } + let mut use_network: libc::c_int = dc_sqlite3_get_config_int( + (*context).sql, + b"sentbox_watch\x00" as *const u8 as *const libc::c_char, + 1i32, + ); + dc_jobthread_fetch(&mut (*context).sentbox_thread, use_network); +} +#[no_mangle] +pub unsafe extern "C" fn dc_perform_sentbox_idle(mut context: *mut dc_context_t) { + if context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint { + return; + } + let mut use_network: libc::c_int = dc_sqlite3_get_config_int( + (*context).sql, + b"sentbox_watch\x00" as *const u8 as *const libc::c_char, + 1i32, + ); + dc_jobthread_idle(&mut (*context).sentbox_thread, use_network); +} +#[no_mangle] +pub unsafe extern "C" 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); +} +#[no_mangle] +pub unsafe extern "C" 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); + dc_log_info( + context, + 0i32, + b"SMTP-jobs started...\x00" as *const u8 as *const libc::c_char, + ); + dc_job_perform(context, 5000i32, 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); +} +#[no_mangle] +pub unsafe extern "C" 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; + } + 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, + 0i32, + ::std::mem::size_of::() as libc::c_ulong, + ); + 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, + ) + } + (*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 extern "C" 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, + 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_finalize(stmt); + return wakeup_time; +} +#[no_mangle] +pub unsafe extern "C" 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); + dc_interrupt_smtp_idle(context); + dc_interrupt_imap_idle(context); + dc_interrupt_mvbox_idle(context); + dc_interrupt_sentbox_idle(context); +} +#[no_mangle] +pub unsafe extern "C" fn dc_job_action_exists( + mut context: *mut 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; + stmt = dc_sqlite3_prepare( + (*context).sql, + b"SELECT id FROM jobs WHERE action=?;\x00" as *const u8 as *const libc::c_char, + ); + sqlite3_bind_int(stmt, 1i32, action); + job_exists = (sqlite3_step(stmt) == 100i32) as libc::c_int; + sqlite3_finalize(stmt); + return job_exists; +} +/* special case for DC_JOB_SEND_MSG_TO_SMTP */ +#[no_mangle] +pub unsafe extern "C" fn dc_job_send_msg( + mut context: *mut dc_context_t, + mut msg_id: uint32_t, +) -> libc::c_int { + let mut success: libc::c_int = 0i32; + let mut mimefactory: dc_mimefactory_t = _dc_mimefactory { + from_addr: 0 as *mut libc::c_char, + from_displayname: 0 as *mut libc::c_char, + selfstatus: 0 as *mut libc::c_char, + recipients_names: 0 as *mut clist, + recipients_addr: 0 as *mut clist, + timestamp: 0, + rfc724_mid: 0 as *mut libc::c_char, + loaded: DC_MF_NOTHING_LOADED, + msg: 0 as *mut dc_msg_t, + chat: 0 as *mut dc_chat_t, + increation: 0, + in_reply_to: 0 as *mut libc::c_char, + references: 0 as *mut libc::c_char, + req_mdn: 0, + out: 0 as *mut MMAPString, + out_encrypted: 0, + out_gossiped: 0, + out_last_added_location_id: 0, + error: 0 as *mut libc::c_char, + context: 0 as *mut dc_context_t, + }; + dc_mimefactory_init(&mut mimefactory, context); + /* load message data */ + if 0 == dc_mimefactory_load_msg(&mut mimefactory, msg_id) || mimefactory.from_addr.is_null() { + dc_log_warning( + context, + 0i32, + b"Cannot load data to send, maybe the message is deleted in between.\x00" as *const u8 + as *const libc::c_char, + ); + } else { + // no redo, no IMAP. moreover, as the data does not exist, there is no need in calling dc_set_msg_failed() + if (*mimefactory.msg).type_0 == 20i32 + || (*mimefactory.msg).type_0 == 21i32 + || (*mimefactory.msg).type_0 == 40i32 + || (*mimefactory.msg).type_0 == 41i32 + || (*mimefactory.msg).type_0 == 50i32 + || (*mimefactory.msg).type_0 == 60i32 + { + let mut pathNfilename: *mut libc::c_char = dc_param_get( + (*mimefactory.msg).param, + 'f' as i32, + 0 as *const libc::c_char, + ); + if !pathNfilename.is_null() { + if ((*mimefactory.msg).type_0 == 20i32 || (*mimefactory.msg).type_0 == 21i32) + && 0 == dc_param_exists((*mimefactory.msg).param, 'w' as i32) + { + 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; + dc_param_set_int((*mimefactory.msg).param, 'w' as i32, 0i32); + dc_param_set_int((*mimefactory.msg).param, 'h' as i32, 0i32); + if 0 != dc_read_file( + context, + pathNfilename, + &mut buf as *mut *mut libc::c_uchar as *mut *mut libc::c_void, + &mut buf_bytes, + ) { + if 0 != dc_get_filemeta( + buf as *const libc::c_void, + buf_bytes, + &mut w, + &mut h, + ) { + dc_param_set_int((*mimefactory.msg).param, 'w' as i32, w as int32_t); + dc_param_set_int((*mimefactory.msg).param, 'h' as i32, h as int32_t); + } + } + free(buf as *mut libc::c_void); + dc_msg_save_param_to_disk(mimefactory.msg); + } + } + free(pathNfilename as *mut libc::c_void); + } + /* create message */ + if 0 == dc_mimefactory_render(&mut mimefactory) { + dc_set_msg_failed(context, msg_id, mimefactory.error); + } else if 0 != dc_param_get_int((*mimefactory.msg).param, 'c' as i32, 0i32) + && 0 == mimefactory.out_encrypted + { + dc_set_msg_failed( + context, + msg_id, + b"End-to-end-encryption unavailable unexpectedly.\x00" as *const u8 + as *const libc::c_char, + ); + } else { + /* unrecoverable */ + if clist_search_string_nocase(mimefactory.recipients_addr, mimefactory.from_addr) + == 0i32 + { + clist_insert_after( + mimefactory.recipients_names, + (*mimefactory.recipients_names).last, + 0 as *mut libc::c_void, + ); + clist_insert_after( + mimefactory.recipients_addr, + (*mimefactory.recipients_addr).last, + 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, + (*mimefactory.msg).chat_id, + time(0 as *mut time_t), + ); + } + if 0 != mimefactory.out_last_added_location_id { + dc_set_kml_sent_timestamp( + context, + (*mimefactory.msg).chat_id, + time(0 as *mut time_t), + ); + if 0 == (*mimefactory.msg).hidden { + dc_set_msg_location_id( + context, + (*mimefactory.msg).id, + mimefactory.out_last_added_location_id, + ); + } + } + if 0 != mimefactory.out_encrypted + && dc_param_get_int((*mimefactory.msg).param, 'c' as i32, 0i32) == 0i32 + { + dc_param_set_int((*mimefactory.msg).param, 'c' as i32, 1i32); + dc_msg_save_param_to_disk(mimefactory.msg); + } + dc_add_to_keyhistory( + context, + 0 as *const libc::c_char, + 0i32 as time_t, + 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) + } + } + dc_mimefactory_empty(&mut mimefactory); + return success; +} diff --git a/src/dc_jobthread.rs b/src/dc_jobthread.rs new file mode 100644 index 000000000..cc20779ac --- /dev/null +++ b/src/dc_jobthread.rs @@ -0,0 +1,1050 @@ +use c2rust_bitfields::BitfieldStruct; +use libc; +extern "C" { + pub type mailstream_cancel; + pub type sqlite3; + #[no_mangle] + fn usleep(_: useconds_t) -> libc::c_int; + #[no_mangle] + fn free(_: *mut libc::c_void); + #[no_mangle] + fn clock() -> clock_t; + #[no_mangle] + fn pthread_cond_destroy(_: *mut pthread_cond_t) -> libc::c_int; + #[no_mangle] + fn pthread_cond_init(_: *mut pthread_cond_t, _: *const pthread_condattr_t) -> libc::c_int; + #[no_mangle] + fn pthread_cond_signal(_: *mut pthread_cond_t) -> libc::c_int; + #[no_mangle] + fn pthread_cond_wait(_: *mut pthread_cond_t, _: *mut pthread_mutex_t) -> libc::c_int; + #[no_mangle] + fn pthread_mutex_destroy(_: *mut pthread_mutex_t) -> libc::c_int; + #[no_mangle] + fn pthread_mutex_init(_: *mut pthread_mutex_t, _: *const pthread_mutexattr_t) -> libc::c_int; + #[no_mangle] + fn pthread_mutex_lock(_: *mut pthread_mutex_t) -> libc::c_int; + #[no_mangle] + fn pthread_mutex_unlock(_: *mut pthread_mutex_t) -> libc::c_int; + #[no_mangle] + fn dc_sqlite3_get_config( + _: *mut dc_sqlite3_t, + key: *const libc::c_char, + def: *const libc::c_char, + ) -> *mut libc::c_char; + #[no_mangle] + fn dc_sqlite3_get_config_int( + _: *mut dc_sqlite3_t, + key: *const libc::c_char, + def: int32_t, + ) -> int32_t; + /* string tools */ + #[no_mangle] + fn dc_strdup(_: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn dc_log_info(_: *mut dc_context_t, data1: libc::c_int, msg: *const libc::c_char, _: ...); + #[no_mangle] + fn dc_imap_interrupt_idle(_: *mut dc_imap_t); + #[no_mangle] + fn dc_imap_fetch(_: *mut dc_imap_t) -> libc::c_int; + #[no_mangle] + fn dc_imap_set_watch_folder(_: *mut dc_imap_t, watch_folder: *const libc::c_char); + #[no_mangle] + fn dc_imap_disconnect(_: *mut dc_imap_t); + #[no_mangle] + fn dc_configure_folders(_: *mut dc_context_t, _: *mut dc_imap_t, flags: libc::c_int); + #[no_mangle] + fn dc_connect_to_configured_imap(_: *mut dc_context_t, _: *mut dc_imap_t) -> libc::c_int; + #[no_mangle] + fn dc_imap_is_connected(_: *const dc_imap_t) -> libc::c_int; + #[no_mangle] + fn dc_imap_idle(_: *mut dc_imap_t); +} +pub type __uint32_t = libc::c_uint; +pub type __darwin_size_t = libc::c_ulong; +pub type __darwin_clock_t = libc::c_ulong; +pub type __darwin_ssize_t = libc::c_long; +pub type __darwin_time_t = libc::c_long; +pub type __darwin_useconds_t = __uint32_t; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_cond_t { + pub __sig: libc::c_long, + pub __opaque: [libc::c_char; 40], +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_condattr_t { + pub __sig: libc::c_long, + pub __opaque: [libc::c_char; 8], +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_mutex_t { + pub __sig: libc::c_long, + pub __opaque: [libc::c_char; 56], +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_mutexattr_t { + pub __sig: libc::c_long, + pub __opaque: [libc::c_char; 8], +} +pub type __darwin_pthread_cond_t = _opaque_pthread_cond_t; +pub type __darwin_pthread_condattr_t = _opaque_pthread_condattr_t; +pub type __darwin_pthread_mutex_t = _opaque_pthread_mutex_t; +pub type __darwin_pthread_mutexattr_t = _opaque_pthread_mutexattr_t; +pub type size_t = __darwin_size_t; +pub type uint32_t = libc::c_uint; +pub type int32_t = libc::c_int; +pub type uintptr_t = libc::c_ulong; +pub type ssize_t = __darwin_ssize_t; +pub type useconds_t = __darwin_useconds_t; +pub type time_t = __darwin_time_t; +pub type uint8_t = libc::c_uchar; +pub type clock_t = __darwin_clock_t; +pub type pthread_cond_t = __darwin_pthread_cond_t; +pub type pthread_condattr_t = __darwin_pthread_condattr_t; +pub type pthread_mutex_t = __darwin_pthread_mutex_t; +pub type pthread_mutexattr_t = __darwin_pthread_mutexattr_t; +#[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; +#[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) -> (); +#[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; +#[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, + 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 { + 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_capability_data { + pub cap_list: *mut clist, +} +#[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_0, + 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_0 { + 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 extern "C" 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_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, +} +#[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_1, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed_1 { + pub ft_fetch_att: *mut mailimap_fetch_att, + pub ft_fetch_att_list: *mut clist, +} +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 unnamed_2 { + 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, +} +/* define DC_USE_RPGP to enable use of rPGP instead of netpgp where available; +preferrably, this should be done in the project configuration currently */ +//#define DC_USE_RPGP 1 +/* Includes that are used frequently. This file may also be used to create predefined headers. */ +/* * Structure behind dc_context_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_context { + pub magic: uint32_t, + pub userdata: *mut libc::c_void, + pub dbfile: *mut libc::c_char, + pub blobdir: *mut libc::c_char, + pub sql: *mut dc_sqlite3_t, + pub inbox: *mut dc_imap_t, + pub inboxidle_condmutex: pthread_mutex_t, + pub perform_inbox_jobs_needed: libc::c_int, + pub probe_imap_network: libc::c_int, + pub sentbox_thread: dc_jobthread_t, + pub mvbox_thread: dc_jobthread_t, + pub smtp: *mut dc_smtp_t, + pub smtpidle_cond: pthread_cond_t, + pub smtpidle_condmutex: pthread_mutex_t, + pub smtpidle_condflag: libc::c_int, + pub smtp_suspended: libc::c_int, + pub smtp_doing_jobs: libc::c_int, + pub perform_smtp_jobs_needed: libc::c_int, + pub probe_smtp_network: libc::c_int, + pub oauth2_critical: pthread_mutex_t, + 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 type dc_lot_t = _dc_lot; +/* * Structure behind dc_lot_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_lot { + pub magic: uint32_t, + pub text1_meaning: libc::c_int, + pub text1: *mut libc::c_char, + pub text2: *mut libc::c_char, + pub timestamp: time_t, + pub state: libc::c_int, + pub id: uint32_t, + pub fingerprint: *mut libc::c_char, + pub invitenumber: *mut libc::c_char, + pub auth: *mut libc::c_char, +} +/* * + * 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 = Option< + unsafe extern "C" fn( + _: *mut dc_context_t, + _: libc::c_int, + _: uintptr_t, + _: uintptr_t, + ) -> uintptr_t, +>; +/* * + * @mainpage Getting started + * + * This document describes how to handle the Delta Chat core library. + * For general information about Delta Chat itself, + * see and . + * + * Let's start. + * + * First of all, you have to **define an event-handler-function** + * that is called by the library on specific events + * (eg. when the configuration is done or when fresh messages arrive). + * With this function you can create a Delta Chat context then: + * + * ~~~ + * #include + * + * uintptr_t event_handler_func(dc_context_t* context, int event, + * uintptr_t data1, uintptr_t data2) + * { + * return 0; // for unhandled events, it is always safe to return 0 + * } + * + * dc_context_t* context = dc_context_new(event_handler_func, NULL, NULL); + * ~~~ + * + * After that, you should make sure, + * sending and receiving jobs are processed as needed. + * For this purpose, you have to **create two threads:** + * + * ~~~ + * #include + * + * void* imap_thread_func(void* context) + * { + * while (true) { + * dc_perform_imap_jobs(context); + * dc_perform_imap_fetch(context); + * dc_perform_imap_idle(context); + * } + * } + * + * void* smtp_thread_func(void* context) + * { + * while (true) { + * dc_perform_smtp_jobs(context); + * dc_perform_smtp_idle(context); + * } + * } + * + * static pthread_t imap_thread, smtp_thread; + * pthread_create(&imap_thread, NULL, imap_thread_func, context); + * pthread_create(&smtp_thread, NULL, smtp_thread_func, context); + * ~~~ + * + * The example above uses "pthreads", + * however, you can also use anything else for thread handling. + * NB: The deltachat-core library itself does not create any threads on its own, + * however, functions, unless stated otherwise, are thread-safe. + * + * After that you can **define and open a database.** + * The database is a normal sqlite-file and is created as needed: + * + * ~~~ + * dc_open(context, "example.db", NULL); + * ~~~ + * + * Now you can **configure the context:** + * + * ~~~ + * // use some real test credentials here + * dc_set_config(context, "addr", "alice@example.org"); + * dc_set_config(context, "mail_pw", "***"); + * dc_configure(context); + * ~~~ + * + * dc_configure() returns immediately, the configuration itself may take a while + * and is done by a job in the imap-thread you've defined above. + * Once done, the #DC_EVENT_CONFIGURE_PROGRESS reports success + * to the event_handler_func() that is also defined above. + * + * The configuration result is saved in the database, + * on subsequent starts it is not needed to call dc_configure() + * (you can check this using dc_is_configured()). + * + * Now you can **send the first message:** + * + * ~~~ + * // use a real testing address here + * uint32_t contact_id = dc_create_contact(context, NULL, "bob@example.org"); + * uint32_t chat_id = dc_create_chat_by_contact_id(context, contact_id); + * + * dc_send_text_msg(context, chat_id, "Hi, here is my first message!"); + * ~~~ + * + * dc_send_text_msg() returns immediately; + * the sending itself is done by a job in the smtp-thread you've defined above. + * If you check the testing address (bob) + * and you should have received a normal email. + * Answer this email in any email program with "Got it!" + * and the imap-thread you've create above will **receive the message**. + * + * You can then **list all messages** of a chat as follow: + * + * ~~~ + * dc_array_t* msglist = dc_get_chat_msgs(context, chat_id, 0, 0); + * for (int i = 0; i < dc_array_get_cnt(msglist); i++) + * { + * uint32_t msg_id = dc_array_get_id(msglist, i); + * dc_msg_t* msg = dc_get_msg(context, msg_id); + * char* text = dc_msg_get_text(msg); + * + * printf("Message %i: %s\n", i+1, text); + * + * free(text); + * dc_msg_unref(msg); + * } + * dc_array_unref(msglist); + * ~~~ + * + * This will output the following two lines: + * + * ~~~ + * Message 1: Hi, here is my first message! + * Message 2: Got it! + * ~~~ + * + * + * ## Class reference + * + * For a class reference, see the "Classes" link atop. + * + * + * ## Further hints + * + * Here are some additional, unsorted hints that may be useful. + * + * - For `get`-functions, you have to unref the return value in some way. + * + * - Strings in function arguments or return values are usually UTF-8 encoded. + * + * - The issue-tracker for the core library is here: + * + * + * The following points are important mainly + * for the authors of the library itself: + * + * - For indentation, use tabs. + * Alignments that are not placed at the beginning of a line + * should be done with spaces. + * + * - For padding between functions, + * classes etc. use 2 empty lines + * + * - Source files are encoded as UTF-8 with Unix line endings + * (a simple `LF`, `0x0A` or `\n`) + * + * If you need further assistance, + * please do not hesitate to contact us + * through the channels shown at https://delta.chat/en/contribute + * + * Please keep in mind, that your derived work + * must respect the Mozilla Public License 2.0 of libdeltachat + * and the respective licenses of the libraries libdeltachat links with. + * + * See you. + */ +/* * + * @class dc_context_t + * + * An object representing a single account. + * + * Each account is linked to an IMAP/SMTP account and uses a separate + * SQLite database for offline functionality and for account-related + * settings. + */ +pub type dc_context_t = _dc_context; +/* ** library-private **********************************************************/ +pub type dc_smtp_t = _dc_smtp; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_smtp { + 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 error: *mut libc::c_char, + pub error_etpan: libc::c_int, +} +pub type dc_jobthread_t = _dc_jobthread; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_jobthread { + 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, + 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, +} +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_imap { + 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 type dc_receive_imf_t = Option< + unsafe extern "C" 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_imap_t = _dc_imap; +pub type dc_precheck_imf_t = Option< + unsafe extern "C" 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< + unsafe extern "C" fn(_: *mut dc_imap_t, _: *const libc::c_char, _: *const libc::c_char) -> (), +>; +pub type dc_get_config_t = Option< + unsafe extern "C" fn( + _: *mut dc_imap_t, + _: *const libc::c_char, + _: *const libc::c_char, + ) -> *mut libc::c_char, +>; +/* ** library-private **********************************************************/ +pub type dc_sqlite3_t = _dc_sqlite3; +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_sqlite3 { + pub cobj: *mut sqlite3, + pub context: *mut dc_context_t, +} +#[no_mangle] +pub unsafe extern "C" 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, +) { + 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; + 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; +} +#[no_mangle] +pub unsafe extern "C" 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; +} +#[no_mangle] +pub unsafe extern "C" 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, + 0i32, + b"Suspending %s-thread.\x00" as *const u8 as *const libc::c_char, + (*jobthread).name, + ); + pthread_mutex_lock(&mut (*jobthread).mutex); + (*jobthread).suspended = 1i32; + pthread_mutex_unlock(&mut (*jobthread).mutex); + dc_jobthread_interrupt_idle(jobthread); + loop { + pthread_mutex_lock(&mut (*jobthread).mutex); + if (*jobthread).using_handle == 0i32 { + pthread_mutex_unlock(&mut (*jobthread).mutex); + return; + } + pthread_mutex_unlock(&mut (*jobthread).mutex); + usleep((300i32 * 1000i32) as useconds_t); + } + } else { + dc_log_info( + (*jobthread).context, + 0i32, + b"Unsuspending %s-thread.\x00" as *const u8 as *const libc::c_char, + (*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); + }; +} +#[no_mangle] +pub unsafe extern "C" fn dc_jobthread_interrupt_idle(mut jobthread: *mut dc_jobthread_t) { + if jobthread.is_null() { + return; + } + pthread_mutex_lock(&mut (*jobthread).mutex); + (*jobthread).jobs_needed = 1i32; + pthread_mutex_unlock(&mut (*jobthread).mutex); + dc_log_info( + (*jobthread).context, + 0i32, + b"Interrupting %s-IDLE...\x00" as *const u8 as *const libc::c_char, + (*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); +} +#[no_mangle] +pub unsafe extern "C" fn dc_jobthread_fetch( + mut jobthread: *mut dc_jobthread_t, + mut use_network: libc::c_int, +) { + let mut start: clock_t = 0; + if jobthread.is_null() { + return; + } + 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()) { + start = clock(); + if !(0 == connect_to_imap(jobthread)) { + dc_log_info( + (*jobthread).context, + 0i32, + b"%s-fetch started...\x00" as *const u8 as *const libc::c_char, + (*jobthread).name, + ); + dc_imap_fetch((*jobthread).imap); + if 0 != (*(*jobthread).imap).should_reconnect { + dc_log_info( + (*jobthread).context, + 0i32, + b"%s-fetch aborted, starting over...\x00" as *const u8 as *const libc::c_char, + (*jobthread).name, + ); + dc_imap_fetch((*jobthread).imap); + } + dc_log_info( + (*jobthread).context, + 0i32, + b"%s-fetch done in %.0f ms.\x00" as *const u8 as *const libc::c_char, + (*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); +} +/* ****************************************************************************** + * the typical fetch, idle, interrupt-idle + ******************************************************************************/ +unsafe extern "C" fn connect_to_imap(mut jobthread: *mut dc_jobthread_t) -> libc::c_int { + let mut ret_connected: libc::c_int = 0i32; + let mut mvbox_name: *mut libc::c_char = 0 as *mut libc::c_char; + if 0 != dc_imap_is_connected((*jobthread).imap) { + ret_connected = 1i32 + } else { + ret_connected = dc_connect_to_configured_imap((*jobthread).context, (*jobthread).imap); + if !(0 == ret_connected) { + if dc_sqlite3_get_config_int( + (*(*jobthread).context).sql, + b"folders_configured\x00" as *const u8 as *const libc::c_char, + 0i32, + ) < 3i32 + { + dc_configure_folders((*jobthread).context, (*jobthread).imap, 0x1i32); + } + mvbox_name = dc_sqlite3_get_config( + (*(*jobthread).context).sql, + (*jobthread).folder_config_name, + 0 as *const libc::c_char, + ); + if mvbox_name.is_null() { + dc_imap_disconnect((*jobthread).imap); + ret_connected = 0i32 + } else { + dc_imap_set_watch_folder((*jobthread).imap, mvbox_name); + } + } + } + free(mvbox_name as *mut libc::c_void); + return ret_connected; +} +#[no_mangle] +pub unsafe extern "C" 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); + } + (*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); + } + (*jobthread).idle_condflag = 0i32; + pthread_mutex_unlock(&mut (*jobthread).mutex); + return; + } + connect_to_imap(jobthread); + dc_log_info( + (*jobthread).context, + 0i32, + b"%s-IDLE started...\x00" as *const u8 as *const libc::c_char, + (*jobthread).name, + ); + dc_imap_idle((*jobthread).imap); + dc_log_info( + (*jobthread).context, + 0i32, + b"%s-IDLE ended.\x00" as *const u8 as *const libc::c_char, + (*jobthread).name, + ); + pthread_mutex_lock(&mut (*jobthread).mutex); + (*jobthread).using_handle = 0i32; + pthread_mutex_unlock(&mut (*jobthread).mutex); +} diff --git a/src/dc_jsmn.rs b/src/dc_jsmn.rs new file mode 100644 index 000000000..965a0ca3e --- /dev/null +++ b/src/dc_jsmn.rs @@ -0,0 +1,398 @@ +use libc; +pub type size_t = libc::c_ulong; +/* +Copyright (c) 2010 Serge A. Zaitsev + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +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. +*/ +/* * + * JSON type identifier. Basic types are: + * o Object + * o Array + * o String + * o Other primitive: number, boolean (true/false) or null + */ +pub type jsmntype_t = libc::c_uint; +pub const JSMN_PRIMITIVE: jsmntype_t = 4; +pub const JSMN_STRING: jsmntype_t = 3; +pub const JSMN_ARRAY: jsmntype_t = 2; +pub const JSMN_OBJECT: jsmntype_t = 1; +pub const JSMN_UNDEFINED: jsmntype_t = 0; +pub type jsmnerr = libc::c_int; +/* The string is not a full JSON packet, more bytes expected */ +pub const JSMN_ERROR_PART: jsmnerr = -3; +/* Invalid character inside JSON string */ +pub const JSMN_ERROR_INVAL: jsmnerr = -2; +/* Not enough tokens were provided */ +pub const JSMN_ERROR_NOMEM: jsmnerr = -1; +/* * + * JSON token description. + * type type (object, array, string etc.) + * start start position in JSON data string + * end end position in JSON data string + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct jsmntok_t { + pub type_0: jsmntype_t, + pub start: libc::c_int, + pub end: libc::c_int, + pub size: libc::c_int, +} +/* * + * JSON parser. Contains an array of token blocks available. Also stores + * the string being parsed now and current position in that string + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct jsmn_parser { + pub pos: libc::c_uint, + pub toknext: libc::c_uint, + pub toksuper: libc::c_int, +} +/* * + * Create JSON parser over an array of tokens + */ +#[no_mangle] +pub unsafe extern "C" fn jsmn_init(mut parser: *mut jsmn_parser) { + (*parser).pos = 0i32 as libc::c_uint; + (*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. + */ +#[no_mangle] +pub unsafe extern "C" fn jsmn_parse( + mut parser: *mut jsmn_parser, + mut js: *const libc::c_char, + mut len: size_t, + 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 count: libc::c_int = (*parser).toknext as libc::c_int; + while ((*parser).pos as libc::c_ulong) < len + && *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; + c = *js.offset((*parser).pos as isize); + match c as libc::c_int { + 123 | 91 => { + count += 1; + if !tokens.is_null() { + token = jsmn_alloc_token(parser, tokens, num_tokens as size_t); + if token.is_null() { + return JSMN_ERROR_NOMEM as libc::c_int; + } + if (*parser).toksuper != -1i32 { + let ref mut fresh0 = (*tokens.offset((*parser).toksuper as isize)).size; + *fresh0 += 1 + } + (*token).type_0 = (if c as libc::c_int == '{' as i32 { + JSMN_OBJECT as libc::c_int + } else { + JSMN_ARRAY as libc::c_int + }) as jsmntype_t; + (*token).start = (*parser).pos as libc::c_int; + (*parser).toksuper = + (*parser).toknext.wrapping_sub(1i32 as libc::c_uint) as libc::c_int + } + } + 125 | 93 => { + if !tokens.is_null() { + type_0 = (if c as libc::c_int == '}' as i32 { + JSMN_OBJECT as libc::c_int + } else { + JSMN_ARRAY as libc::c_int + }) as jsmntype_t; + i = (*parser).toknext.wrapping_sub(1i32 as libc::c_uint) as libc::c_int; + while i >= 0i32 { + token = &mut *tokens.offset(i as isize) as *mut jsmntok_t; + if (*token).start != -1i32 && (*token).end == -1i32 { + if (*token).type_0 as libc::c_uint != type_0 as libc::c_uint { + return JSMN_ERROR_INVAL as libc::c_int; + } + (*parser).toksuper = -1i32; + (*token).end = + (*parser).pos.wrapping_add(1i32 as libc::c_uint) as libc::c_int; + break; + } else { + i -= 1 + } + } + if i == -1i32 { + return JSMN_ERROR_INVAL as libc::c_int; + } + while i >= 0i32 { + token = &mut *tokens.offset(i as isize) as *mut jsmntok_t; + if (*token).start != -1i32 && (*token).end == -1i32 { + (*parser).toksuper = i; + break; + } else { + i -= 1 + } + } + } + } + 34 => { + r = jsmn_parse_string(parser, js, len, tokens, num_tokens as size_t); + if r < 0i32 { + return r; + } + count += 1; + if (*parser).toksuper != -1i32 && !tokens.is_null() { + let ref mut fresh1 = (*tokens.offset((*parser).toksuper as isize)).size; + *fresh1 += 1 + } + } + 9 | 13 | 10 | 32 => {} + 58 => { + (*parser).toksuper = + (*parser).toknext.wrapping_sub(1i32 as libc::c_uint) as libc::c_int + } + 44 => { + if !tokens.is_null() + && (*parser).toksuper != -1i32 + && (*tokens.offset((*parser).toksuper as isize)).type_0 as libc::c_uint + != JSMN_ARRAY as libc::c_int as libc::c_uint + && (*tokens.offset((*parser).toksuper as isize)).type_0 as libc::c_uint + != JSMN_OBJECT as libc::c_int as libc::c_uint + { + i = (*parser).toknext.wrapping_sub(1i32 as libc::c_uint) as libc::c_int; + while i >= 0i32 { + if (*tokens.offset(i as isize)).type_0 as libc::c_uint + == JSMN_ARRAY as libc::c_int as libc::c_uint + || (*tokens.offset(i as isize)).type_0 as libc::c_uint + == JSMN_OBJECT as libc::c_int as libc::c_uint + { + if (*tokens.offset(i as isize)).start != -1i32 + && (*tokens.offset(i as isize)).end == -1i32 + { + (*parser).toksuper = i; + break; + } + } + i -= 1 + } + } + } + _ => { + r = jsmn_parse_primitive(parser, js, len, tokens, num_tokens as size_t); + if r < 0i32 { + return r; + } + count += 1; + if (*parser).toksuper != -1i32 && !tokens.is_null() { + let ref mut fresh2 = (*tokens.offset((*parser).toksuper as isize)).size; + *fresh2 += 1 + } + } + } + (*parser).pos = (*parser).pos.wrapping_add(1) + } + if !tokens.is_null() { + i = (*parser).toknext.wrapping_sub(1i32 as libc::c_uint) as libc::c_int; + while i >= 0i32 { + if (*tokens.offset(i as isize)).start != -1i32 + && (*tokens.offset(i as isize)).end == -1i32 + { + return JSMN_ERROR_PART as libc::c_int; + } + i -= 1 + } + } + return count; +} +/* * + * Fills next available token with JSON primitive. + */ +unsafe extern "C" fn jsmn_parse_primitive( + mut parser: *mut jsmn_parser, + mut js: *const libc::c_char, + mut len: size_t, + 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; + start = (*parser).pos as libc::c_int; + while ((*parser).pos as libc::c_ulong) < len + && *js.offset((*parser).pos as isize) as libc::c_int != '\u{0}' as i32 + { + match *js.offset((*parser).pos as isize) as libc::c_int { + 58 | 9 | 13 | 10 | 32 | 44 | 93 | 125 => { + break; + } + _ => {} + } + if (*js.offset((*parser).pos as isize) as libc::c_int) < 32i32 + || *js.offset((*parser).pos as isize) as libc::c_int >= 127i32 + { + (*parser).pos = start as libc::c_uint; + return JSMN_ERROR_INVAL as libc::c_int; + } + (*parser).pos = (*parser).pos.wrapping_add(1) + } + if tokens.is_null() { + (*parser).pos = (*parser).pos.wrapping_sub(1); + return 0i32; + } + token = jsmn_alloc_token(parser, tokens, num_tokens); + if token.is_null() { + (*parser).pos = start as libc::c_uint; + return JSMN_ERROR_NOMEM as libc::c_int; + } + jsmn_fill_token(token, JSMN_PRIMITIVE, start, (*parser).pos as libc::c_int); + (*parser).pos = (*parser).pos.wrapping_sub(1); + return 0i32; +} +/* * + * Fills token type and boundaries. + */ +unsafe extern "C" fn jsmn_fill_token( + mut token: *mut jsmntok_t, + mut type_0: jsmntype_t, + mut start: libc::c_int, + mut end: libc::c_int, +) { + (*token).type_0 = type_0; + (*token).start = start; + (*token).end = end; + (*token).size = 0i32; +} +/* +Copyright (c) 2010 Serge A. Zaitsev + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +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. + */ +unsafe extern "C" fn jsmn_alloc_token( + mut parser: *mut jsmn_parser, + mut tokens: *mut jsmntok_t, + mut num_tokens: size_t, +) -> *mut jsmntok_t { + let mut tok: *mut jsmntok_t = 0 as *mut jsmntok_t; + if (*parser).toknext as libc::c_ulong >= num_tokens { + return 0 as *mut jsmntok_t; + } + let fresh3 = (*parser).toknext; + (*parser).toknext = (*parser).toknext.wrapping_add(1); + tok = &mut *tokens.offset(fresh3 as isize) as *mut jsmntok_t; + (*tok).end = -1i32; + (*tok).start = (*tok).end; + (*tok).size = 0i32; + return tok; +} +/* * + * Fills next token with JSON string. + */ +unsafe extern "C" fn jsmn_parse_string( + mut parser: *mut jsmn_parser, + mut js: *const libc::c_char, + mut len: size_t, + 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 = (*parser).pos as libc::c_int; + (*parser).pos = (*parser).pos.wrapping_add(1); + while ((*parser).pos as libc::c_ulong) < len + && *js.offset((*parser).pos as isize) as libc::c_int != '\u{0}' as i32 + { + let mut c: libc::c_char = *js.offset((*parser).pos as isize); + if c as libc::c_int == '\"' as i32 { + if tokens.is_null() { + return 0i32; + } + token = jsmn_alloc_token(parser, tokens, num_tokens); + if token.is_null() { + (*parser).pos = start as libc::c_uint; + return JSMN_ERROR_NOMEM as libc::c_int; + } + jsmn_fill_token( + token, + JSMN_STRING, + start + 1i32, + (*parser).pos as libc::c_int, + ); + return 0i32; + } + if c as libc::c_int == '\\' as i32 + && ((*parser).pos.wrapping_add(1i32 as libc::c_uint) as libc::c_ulong) < len + { + let mut i: libc::c_int = 0; + (*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 => {} + 117 => { + (*parser).pos = (*parser).pos.wrapping_add(1); + i = 0i32; + while i < 4i32 + && ((*parser).pos as libc::c_ulong) < len + && *js.offset((*parser).pos as isize) as libc::c_int != '\u{0}' as i32 + { + if !(*js.offset((*parser).pos as isize) as libc::c_int >= 48i32 + && *js.offset((*parser).pos as isize) as libc::c_int <= 57i32 + || *js.offset((*parser).pos as isize) as libc::c_int >= 65i32 + && *js.offset((*parser).pos as isize) as libc::c_int <= 70i32 + || *js.offset((*parser).pos as isize) as libc::c_int >= 97i32 + && *js.offset((*parser).pos as isize) as libc::c_int <= 102i32) + { + (*parser).pos = start as libc::c_uint; + return JSMN_ERROR_INVAL as libc::c_int; + } + (*parser).pos = (*parser).pos.wrapping_add(1); + i += 1 + } + (*parser).pos = (*parser).pos.wrapping_sub(1) + } + _ => { + (*parser).pos = start as libc::c_uint; + return JSMN_ERROR_INVAL as libc::c_int; + } + } + } + (*parser).pos = (*parser).pos.wrapping_add(1) + } + (*parser).pos = start as libc::c_uint; + return JSMN_ERROR_PART as libc::c_int; +} diff --git a/src/dc_key.rs b/src/dc_key.rs new file mode 100644 index 000000000..8d451694c --- /dev/null +++ b/src/dc_key.rs @@ -0,0 +1,1465 @@ +use c2rust_bitfields::BitfieldStruct; +use libc; +extern "C" { + pub type mailstream_cancel; + pub type sqlite3; + pub type sqlite3_stmt; + #[no_mangle] + fn __toupper(_: __darwin_ct_rune_t) -> __darwin_ct_rune_t; + #[no_mangle] + fn memcmp(_: *const libc::c_void, _: *const libc::c_void, _: libc::c_ulong) -> libc::c_int; + #[no_mangle] + fn memcpy(_: *mut libc::c_void, _: *const libc::c_void, _: libc::c_ulong) -> *mut libc::c_void; + #[no_mangle] + fn memset(_: *mut libc::c_void, _: libc::c_int, _: libc::c_ulong) -> *mut libc::c_void; + #[no_mangle] + fn strcmp(_: *const libc::c_char, _: *const libc::c_char) -> libc::c_int; + #[no_mangle] + fn strlen(_: *const libc::c_char) -> libc::c_ulong; + #[no_mangle] + fn malloc(_: libc::c_ulong) -> *mut libc::c_void; + #[no_mangle] + fn calloc(_: libc::c_ulong, _: libc::c_ulong) -> *mut libc::c_void; + #[no_mangle] + fn free(_: *mut libc::c_void); + #[no_mangle] + fn exit(_: libc::c_int) -> !; + #[no_mangle] + fn time(_: *mut time_t) -> time_t; + #[no_mangle] + fn mmap_string_unref(str: *mut libc::c_char) -> libc::c_int; + #[no_mangle] + 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; + #[no_mangle] + fn sqlite3_bind_blob( + _: *mut sqlite3_stmt, + _: libc::c_int, + _: *const libc::c_void, + n: libc::c_int, + _: Option ()>, + ) -> libc::c_int; + #[no_mangle] + fn sqlite3_bind_int(_: *mut sqlite3_stmt, _: libc::c_int, _: libc::c_int) -> libc::c_int; + #[no_mangle] + fn sqlite3_bind_int64(_: *mut sqlite3_stmt, _: libc::c_int, _: sqlite3_int64) -> libc::c_int; + #[no_mangle] + fn sqlite3_bind_text( + _: *mut sqlite3_stmt, + _: libc::c_int, + _: *const libc::c_char, + _: libc::c_int, + _: Option ()>, + ) -> libc::c_int; + #[no_mangle] + fn sqlite3_step(_: *mut sqlite3_stmt) -> libc::c_int; + #[no_mangle] + fn sqlite3_column_blob(_: *mut sqlite3_stmt, iCol: libc::c_int) -> *const libc::c_void; + #[no_mangle] + fn sqlite3_column_bytes(_: *mut sqlite3_stmt, iCol: libc::c_int) -> libc::c_int; + #[no_mangle] + fn sqlite3_finalize(pStmt: *mut sqlite3_stmt) -> libc::c_int; + /* tools, these functions are compatible to the corresponding sqlite3_* functions */ + #[no_mangle] + fn dc_sqlite3_prepare(_: *mut dc_sqlite3_t, sql: *const libc::c_char) -> *mut sqlite3_stmt; + /* string tools */ + #[no_mangle] + fn dc_strdup(_: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn dc_mprintf(format: *const libc::c_char, _: ...) -> *mut libc::c_char; + #[no_mangle] + fn dc_binary_to_uc_hex(buf: *const uint8_t, bytes: size_t) -> *mut libc::c_char; + #[no_mangle] + fn dc_insert_breaks( + _: *const libc::c_char, + break_every: libc::c_int, + break_chars: *const libc::c_char, + ) -> *mut libc::c_char; + // from libetpan/src/data-types/base64.h (which cannot be included without adding libetpan/src/... to the include-search-paths, which would result in double-file-name-errors, so, for now, we use this hack) + #[no_mangle] + fn encode_base64(in_0: *const libc::c_char, len: libc::c_int) -> *mut libc::c_char; + #[no_mangle] + fn dc_write_file( + _: *mut dc_context_t, + pathNfilename: *const libc::c_char, + buf: *const libc::c_void, + buf_bytes: size_t, + ) -> libc::c_int; + #[no_mangle] + fn dc_read_file( + _: *mut dc_context_t, + pathNfilename: *const libc::c_char, + buf: *mut *mut libc::c_void, + buf_bytes: *mut size_t, + ) -> libc::c_int; + #[no_mangle] + fn dc_strbuilder_init(_: *mut dc_strbuilder_t, init_bytes: libc::c_int); + #[no_mangle] + fn dc_strbuilder_cat(_: *mut dc_strbuilder_t, text: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn dc_strbuilder_catf(_: *mut dc_strbuilder_t, format: *const libc::c_char, _: ...); + #[no_mangle] + fn dc_log_warning(_: *mut dc_context_t, data1: libc::c_int, msg: *const libc::c_char, _: ...); + #[no_mangle] + fn dc_split_armored_data( + buf: *mut libc::c_char, + ret_headerline: *mut *const libc::c_char, + ret_setupcodebegin: *mut *const libc::c_char, + ret_preferencrypt: *mut *const libc::c_char, + ret_base64: *mut *const libc::c_char, + ) -> libc::c_int; + #[no_mangle] + fn dc_log_error(_: *mut dc_context_t, data1: libc::c_int, msg: *const libc::c_char, _: ...); + #[no_mangle] + fn dc_pgp_calc_fingerprint( + _: *const dc_key_t, + fingerprint: *mut *mut uint8_t, + fingerprint_bytes: *mut size_t, + ) -> libc::c_int; +} +pub type __darwin_ct_rune_t = libc::c_int; +pub type __darwin_size_t = libc::c_ulong; +pub type __darwin_ssize_t = libc::c_long; +pub type __darwin_time_t = libc::c_long; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_cond_t { + pub __sig: libc::c_long, + pub __opaque: [libc::c_char; 40], +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_mutex_t { + pub __sig: libc::c_long, + pub __opaque: [libc::c_char; 56], +} +pub type __darwin_pthread_cond_t = _opaque_pthread_cond_t; +pub type __darwin_pthread_mutex_t = _opaque_pthread_mutex_t; +pub type size_t = __darwin_size_t; +pub type uintptr_t = libc::c_ulong; +pub type ssize_t = __darwin_ssize_t; +pub type uint8_t = libc::c_uchar; +pub type uint32_t = libc::c_uint; +pub type time_t = __darwin_time_t; +pub type pthread_cond_t = __darwin_pthread_cond_t; +pub type pthread_mutex_t = __darwin_pthread_mutex_t; +#[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; +#[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) -> (); +#[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 unnamed = libc::c_uint; +pub const MAILIMF_ERROR_FILE: unnamed = 4; +pub const MAILIMF_ERROR_INVAL: unnamed = 3; +pub const MAILIMF_ERROR_MEMORY: unnamed = 2; +pub const MAILIMF_ERROR_PARSE: unnamed = 1; +pub const MAILIMF_NO_ERROR: unnamed = 0; +#[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_capability_data { + pub cap_list: *mut clist, +} +#[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_1, + 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_1 { + 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 extern "C" 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_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, +} +#[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_2, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed_2 { + pub ft_fetch_att: *mut mailimap_fetch_att, + pub ft_fetch_att_list: *mut clist, +} +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_3, + 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 unnamed_3 { + 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, +} +/* define DC_USE_RPGP to enable use of rPGP instead of netpgp where available; +preferrably, this should be done in the project configuration currently */ +//#define DC_USE_RPGP 1 +/* Includes that are used frequently. This file may also be used to create predefined headers. */ +/* * Structure behind dc_context_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_context { + pub magic: uint32_t, + pub userdata: *mut libc::c_void, + pub dbfile: *mut libc::c_char, + pub blobdir: *mut libc::c_char, + pub sql: *mut dc_sqlite3_t, + pub inbox: *mut dc_imap_t, + pub inboxidle_condmutex: pthread_mutex_t, + pub perform_inbox_jobs_needed: libc::c_int, + pub probe_imap_network: libc::c_int, + pub sentbox_thread: dc_jobthread_t, + pub mvbox_thread: dc_jobthread_t, + pub smtp: *mut dc_smtp_t, + pub smtpidle_cond: pthread_cond_t, + pub smtpidle_condmutex: pthread_mutex_t, + pub smtpidle_condflag: libc::c_int, + pub smtp_suspended: libc::c_int, + pub smtp_doing_jobs: libc::c_int, + pub perform_smtp_jobs_needed: libc::c_int, + pub probe_smtp_network: libc::c_int, + pub oauth2_critical: pthread_mutex_t, + 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 type dc_lot_t = _dc_lot; +/* * Structure behind dc_lot_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_lot { + pub magic: uint32_t, + pub text1_meaning: libc::c_int, + pub text1: *mut libc::c_char, + pub text2: *mut libc::c_char, + pub timestamp: time_t, + pub state: libc::c_int, + pub id: uint32_t, + pub fingerprint: *mut libc::c_char, + pub invitenumber: *mut libc::c_char, + pub auth: *mut libc::c_char, +} +/* * + * 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 = Option< + unsafe extern "C" fn( + _: *mut dc_context_t, + _: libc::c_int, + _: uintptr_t, + _: uintptr_t, + ) -> uintptr_t, +>; +/* * + * @mainpage Getting started + * + * This document describes how to handle the Delta Chat core library. + * For general information about Delta Chat itself, + * see and . + * + * Let's start. + * + * First of all, you have to **define an event-handler-function** + * that is called by the library on specific events + * (eg. when the configuration is done or when fresh messages arrive). + * With this function you can create a Delta Chat context then: + * + * ~~~ + * #include + * + * uintptr_t event_handler_func(dc_context_t* context, int event, + * uintptr_t data1, uintptr_t data2) + * { + * return 0; // for unhandled events, it is always safe to return 0 + * } + * + * dc_context_t* context = dc_context_new(event_handler_func, NULL, NULL); + * ~~~ + * + * After that, you should make sure, + * sending and receiving jobs are processed as needed. + * For this purpose, you have to **create two threads:** + * + * ~~~ + * #include + * + * void* imap_thread_func(void* context) + * { + * while (true) { + * dc_perform_imap_jobs(context); + * dc_perform_imap_fetch(context); + * dc_perform_imap_idle(context); + * } + * } + * + * void* smtp_thread_func(void* context) + * { + * while (true) { + * dc_perform_smtp_jobs(context); + * dc_perform_smtp_idle(context); + * } + * } + * + * static pthread_t imap_thread, smtp_thread; + * pthread_create(&imap_thread, NULL, imap_thread_func, context); + * pthread_create(&smtp_thread, NULL, smtp_thread_func, context); + * ~~~ + * + * The example above uses "pthreads", + * however, you can also use anything else for thread handling. + * NB: The deltachat-core library itself does not create any threads on its own, + * however, functions, unless stated otherwise, are thread-safe. + * + * After that you can **define and open a database.** + * The database is a normal sqlite-file and is created as needed: + * + * ~~~ + * dc_open(context, "example.db", NULL); + * ~~~ + * + * Now you can **configure the context:** + * + * ~~~ + * // use some real test credentials here + * dc_set_config(context, "addr", "alice@example.org"); + * dc_set_config(context, "mail_pw", "***"); + * dc_configure(context); + * ~~~ + * + * dc_configure() returns immediately, the configuration itself may take a while + * and is done by a job in the imap-thread you've defined above. + * Once done, the #DC_EVENT_CONFIGURE_PROGRESS reports success + * to the event_handler_func() that is also defined above. + * + * The configuration result is saved in the database, + * on subsequent starts it is not needed to call dc_configure() + * (you can check this using dc_is_configured()). + * + * Now you can **send the first message:** + * + * ~~~ + * // use a real testing address here + * uint32_t contact_id = dc_create_contact(context, NULL, "bob@example.org"); + * uint32_t chat_id = dc_create_chat_by_contact_id(context, contact_id); + * + * dc_send_text_msg(context, chat_id, "Hi, here is my first message!"); + * ~~~ + * + * dc_send_text_msg() returns immediately; + * the sending itself is done by a job in the smtp-thread you've defined above. + * If you check the testing address (bob) + * and you should have received a normal email. + * Answer this email in any email program with "Got it!" + * and the imap-thread you've create above will **receive the message**. + * + * You can then **list all messages** of a chat as follow: + * + * ~~~ + * dc_array_t* msglist = dc_get_chat_msgs(context, chat_id, 0, 0); + * for (int i = 0; i < dc_array_get_cnt(msglist); i++) + * { + * uint32_t msg_id = dc_array_get_id(msglist, i); + * dc_msg_t* msg = dc_get_msg(context, msg_id); + * char* text = dc_msg_get_text(msg); + * + * printf("Message %i: %s\n", i+1, text); + * + * free(text); + * dc_msg_unref(msg); + * } + * dc_array_unref(msglist); + * ~~~ + * + * This will output the following two lines: + * + * ~~~ + * Message 1: Hi, here is my first message! + * Message 2: Got it! + * ~~~ + * + * + * ## Class reference + * + * For a class reference, see the "Classes" link atop. + * + * + * ## Further hints + * + * Here are some additional, unsorted hints that may be useful. + * + * - For `get`-functions, you have to unref the return value in some way. + * + * - Strings in function arguments or return values are usually UTF-8 encoded. + * + * - The issue-tracker for the core library is here: + * + * + * The following points are important mainly + * for the authors of the library itself: + * + * - For indentation, use tabs. + * Alignments that are not placed at the beginning of a line + * should be done with spaces. + * + * - For padding between functions, + * classes etc. use 2 empty lines + * + * - Source files are encoded as UTF-8 with Unix line endings + * (a simple `LF`, `0x0A` or `\n`) + * + * If you need further assistance, + * please do not hesitate to contact us + * through the channels shown at https://delta.chat/en/contribute + * + * Please keep in mind, that your derived work + * must respect the Mozilla Public License 2.0 of libdeltachat + * and the respective licenses of the libraries libdeltachat links with. + * + * See you. + */ +/* * + * @class dc_context_t + * + * An object representing a single account. + * + * Each account is linked to an IMAP/SMTP account and uses a separate + * SQLite database for offline functionality and for account-related + * settings. + */ +pub type dc_context_t = _dc_context; +/* ** library-private **********************************************************/ +pub type dc_smtp_t = _dc_smtp; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_smtp { + 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 error: *mut libc::c_char, + pub error_etpan: libc::c_int, +} +pub type dc_jobthread_t = _dc_jobthread; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_jobthread { + 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, + 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, +} +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_imap { + 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 type dc_receive_imf_t = Option< + unsafe extern "C" 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_imap_t = _dc_imap; +pub type dc_precheck_imf_t = Option< + unsafe extern "C" 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< + unsafe extern "C" fn(_: *mut dc_imap_t, _: *const libc::c_char, _: *const libc::c_char) -> (), +>; +pub type dc_get_config_t = Option< + unsafe extern "C" fn( + _: *mut dc_imap_t, + _: *const libc::c_char, + _: *const libc::c_char, + ) -> *mut libc::c_char, +>; +/* ** library-private **********************************************************/ +pub type dc_sqlite3_t = _dc_sqlite3; +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_sqlite3 { + pub cobj: *mut sqlite3, + pub context: *mut dc_context_t, +} +pub type sqlite_int64 = libc::c_longlong; +pub type sqlite3_int64 = sqlite_int64; +pub type sqlite3_destructor_type = Option ()>; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_strbuilder { + pub buf: *mut libc::c_char, + pub allocated: libc::c_int, + pub free: libc::c_int, + pub eos: *mut libc::c_char, +} +pub type dc_strbuilder_t = _dc_strbuilder; +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_key { + pub binary: *mut libc::c_void, + pub bytes: libc::c_int, + pub type_0: libc::c_int, + pub _m_heap_refcnt: libc::c_int, +} +pub type dc_key_t = _dc_key; +#[no_mangle] +#[inline] +pub unsafe extern "C" fn toupper(mut _c: libc::c_int) -> libc::c_int { + return __toupper(_c); +} +#[no_mangle] +pub unsafe extern "C" fn dc_key_new() -> *mut dc_key_t { + let mut key: *mut dc_key_t = 0 as *mut dc_key_t; + key = calloc( + 1i32 as libc::c_ulong, + ::std::mem::size_of::() as libc::c_ulong, + ) as *mut dc_key_t; + if key.is_null() { + exit(44i32); + } + (*key)._m_heap_refcnt = 1i32; + return key; +} +#[no_mangle] +pub unsafe extern "C" 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; +} +#[no_mangle] +pub unsafe extern "C" fn dc_key_unref(mut key: *mut dc_key_t) { + if key.is_null() { + return; + } + (*key)._m_heap_refcnt -= 1; + if (*key)._m_heap_refcnt != 0i32 { + return; + } + dc_key_empty(key); + free(key as *mut libc::c_void); +} +unsafe extern "C" fn dc_key_empty(mut key: *mut dc_key_t) { + if key.is_null() { + return; + } + if (*key).type_0 == 1i32 { + dc_wipe_secret_mem((*key).binary, (*key).bytes as size_t); + } + free((*key).binary); + (*key).binary = 0 as *mut libc::c_void; + (*key).bytes = 0i32; + (*key).type_0 = 0i32; +} +#[no_mangle] +pub unsafe extern "C" fn dc_wipe_secret_mem(mut buf: *mut libc::c_void, mut buf_bytes: size_t) { + if buf.is_null() || buf_bytes <= 0i32 as libc::c_ulong { + return; + } + memset(buf, 0i32, buf_bytes); +} +#[no_mangle] +pub unsafe extern "C" fn dc_key_set_from_binary( + mut key: *mut dc_key_t, + mut data: *const libc::c_void, + mut bytes: libc::c_int, + mut type_0: libc::c_int, +) -> libc::c_int { + dc_key_empty(key); + if key.is_null() || data == 0 as *mut libc::c_void || bytes <= 0i32 { + return 0i32; + } + (*key).binary = malloc(bytes as libc::c_ulong); + if (*key).binary.is_null() { + exit(40i32); + } + memcpy((*key).binary, data, bytes as libc::c_ulong); + (*key).bytes = bytes; + (*key).type_0 = type_0; + return 1i32; +} +#[no_mangle] +pub unsafe extern "C" 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); +} +#[no_mangle] +pub unsafe extern "C" fn dc_key_set_from_stmt( + mut key: *mut dc_key_t, + mut stmt: *mut sqlite3_stmt, + mut index: libc::c_int, + mut type_0: libc::c_int, +) -> libc::c_int { + dc_key_empty(key); + if key.is_null() || stmt.is_null() { + return 0i32; + } + return 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, + ); +} +#[no_mangle] +pub unsafe extern "C" fn dc_key_set_from_base64( + mut key: *mut dc_key_t, + mut base64: *const libc::c_char, + mut type_0: libc::c_int, +) -> libc::c_int { + let mut indx: size_t = 0i32 as size_t; + let mut result_len: size_t = 0i32 as size_t; + let mut result: *mut libc::c_char = 0 as *mut libc::c_char; + dc_key_empty(key); + if key.is_null() || base64.is_null() { + return 0i32; + } + if mailmime_base64_body_parse( + base64, + strlen(base64), + &mut indx, + &mut result, + &mut result_len, + ) != MAILIMF_NO_ERROR as libc::c_int + || result.is_null() + || result_len == 0i32 as libc::c_ulong + { + return 0i32; + } + dc_key_set_from_binary( + key, + result as *const libc::c_void, + result_len as libc::c_int, + type_0, + ); + mmap_string_unref(result); + return 1i32; +} +#[no_mangle] +pub unsafe extern "C" 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 < 50i32 as libc::c_ulong) + { + /* 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; +} +#[no_mangle] +pub unsafe extern "C" 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() + || (*key).binary.is_null() + || (*key).bytes <= 0i32 + || (*o).binary.is_null() + || (*o).bytes <= 0i32 + { + return 0i32; + } + if (*key).bytes != (*o).bytes { + return 0i32; + } + if (*key).type_0 != (*o).type_0 { + return 0i32; + } + return if memcmp((*key).binary, (*o).binary, (*o).bytes as libc::c_ulong) == 0i32 { + 1i32 + } else { + 0i32 + }; +} +#[no_mangle] +pub unsafe extern "C" 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, +) -> 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" + as *const u8 as *const libc::c_char); + sqlite3_bind_text(stmt, 1i32, addr, -1i32, None); + sqlite3_bind_int(stmt, 2i32, is_default); + sqlite3_bind_blob(stmt, 3i32, (*public_key).binary, (*public_key).bytes, None); + sqlite3_bind_blob( + stmt, + 4i32, + (*private_key).binary, + (*private_key).bytes, + None, + ); + sqlite3_bind_int64(stmt, 5i32, time(0 as *mut time_t) as sqlite3_int64); + if !(sqlite3_step(stmt) != 101i32) { + success = 1i32 + } + } + sqlite3_finalize(stmt); + return success; +} +#[no_mangle] +pub unsafe extern "C" 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, +) -> 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()) { + dc_key_empty(key); + stmt = dc_sqlite3_prepare( + sql, + b"SELECT public_key FROM keypairs WHERE addr=? AND is_default=1;\x00" as *const u8 + as *const libc::c_char, + ); + sqlite3_bind_text(stmt, 1i32, self_addr, -1i32, None); + if !(sqlite3_step(stmt) != 100i32) { + dc_key_set_from_stmt(key, stmt, 0i32, 0i32); + success = 1i32 + } + } + sqlite3_finalize(stmt); + return success; +} +#[no_mangle] +pub unsafe extern "C" 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, +) -> 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()) { + dc_key_empty(key); + stmt = dc_sqlite3_prepare( + sql, + b"SELECT private_key FROM keypairs WHERE addr=? AND is_default=1;\x00" as *const u8 + as *const libc::c_char, + ); + 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 + } + } + sqlite3_finalize(stmt); + return success; +} +/* the result must be freed */ +#[no_mangle] +pub unsafe extern "C" 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 <= 0i32 as libc::c_ulong) { + 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 extern "C" fn crc_octets(mut octets: *const libc::c_uchar, mut len: size_t) -> libc::c_long { + let mut crc: libc::c_long = 0xb704cei64; + 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 & 0x1000000i32 as libc::c_long { + crc ^= 0x1864cfbi64 + } + i += 1 + } + } + return crc & 0xffffffi64; +} +/* the result must be freed */ +#[no_mangle] +pub unsafe extern "C" 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 { + if key.is_null() { + return 0 as *mut libc::c_char; + } + return dc_render_base64( + (*key).binary, + (*key).bytes as size_t, + break_every, + break_chars, + add_checksum, + ); +} +/* each header line must be terminated by \r\n, the result must be freed */ +#[no_mangle] +pub unsafe extern "C" 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 + }) + } + } + free(base64 as *mut libc::c_void); + return ret; +} +#[no_mangle] +pub unsafe extern "C" 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, +) -> 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 !file_content.is_null() { + if 0 == dc_write_file( + context, + file, + file_content as *const libc::c_void, + strlen(file_content), + ) { + dc_log_error( + context, + 0i32, + b"Cannot write key to %s\x00" as *const u8 as *const libc::c_char, + file, + ); + } else { + success = 1i32 + } + } + } + free(file_content as *mut libc::c_void); + return success; +} +#[no_mangle] +pub unsafe extern "C" 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; + let mut ret: dc_strbuilder_t = _dc_strbuilder { + buf: 0 as *mut libc::c_char, + allocated: 0, + free: 0, + eos: 0 as *mut libc::c_char, + }; + dc_strbuilder_init(&mut ret, 0i32); + while 0 != *fingerprint.offset(i as isize) { + dc_strbuilder_catf( + &mut ret as *mut dc_strbuilder_t, + b"%c\x00" as *const u8 as *const libc::c_char, + *fingerprint.offset(i as isize) as libc::c_int, + ); + i += 1; + if i != fingerprint_len { + if i % 20i32 == 0i32 { + dc_strbuilder_cat(&mut ret, b"\n\x00" as *const u8 as *const libc::c_char); + } else if i % 4i32 == 0i32 { + dc_strbuilder_cat(&mut ret, b" \x00" as *const u8 as *const libc::c_char); + } + } + } + return ret.buf; +} +#[no_mangle] +pub unsafe extern "C" 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; + } + let mut out: dc_strbuilder_t = _dc_strbuilder { + buf: 0 as *mut libc::c_char, + allocated: 0, + free: 0, + eos: 0 as *mut libc::c_char, + }; + dc_strbuilder_init(&mut out, 0i32); + 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 + || *p1 as libc::c_int >= 'A' as i32 && *p1 as libc::c_int <= 'F' as i32 + || *p1 as libc::c_int >= 'a' as i32 && *p1 as libc::c_int <= 'f' as i32 + { + dc_strbuilder_catf( + &mut out as *mut dc_strbuilder_t, + b"%c\x00" as *const u8 as *const libc::c_char, + toupper(*p1 as libc::c_int), + ); + } + p1 = p1.offset(1isize) + } + return out.buf; +} +#[no_mangle] +pub unsafe extern "C" fn dc_key_get_fingerprint(mut 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)) { + fingerprint_hex = dc_binary_to_uc_hex(fingerprint_buf, fingerprint_bytes) + } + } + free(fingerprint_buf as *mut libc::c_void); + return if !fingerprint_hex.is_null() { + fingerprint_hex + } else { + dc_strdup(0 as *const libc::c_char) + }; +} +#[no_mangle] +pub unsafe extern "C" 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); + let mut formatted: *mut libc::c_char = dc_format_fingerprint(rawhex); + free(rawhex as *mut libc::c_void); + return formatted; +} diff --git a/src/dc_keyhistory.rs b/src/dc_keyhistory.rs new file mode 100644 index 000000000..31b730991 --- /dev/null +++ b/src/dc_keyhistory.rs @@ -0,0 +1,744 @@ +use c2rust_bitfields::BitfieldStruct; +use libc; +extern "C" { + pub type mailstream_cancel; + pub type sqlite3; +} +pub type __darwin_size_t = libc::c_ulong; +pub type __darwin_ssize_t = libc::c_long; +pub type __darwin_time_t = libc::c_long; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_cond_t { + pub __sig: libc::c_long, + pub __opaque: [libc::c_char; 40], +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_mutex_t { + pub __sig: libc::c_long, + pub __opaque: [libc::c_char; 56], +} +pub type __darwin_pthread_cond_t = _opaque_pthread_cond_t; +pub type __darwin_pthread_mutex_t = _opaque_pthread_mutex_t; +pub type uintptr_t = libc::c_ulong; +pub type size_t = __darwin_size_t; +pub type uint8_t = libc::c_uchar; +pub type uint32_t = libc::c_uint; +pub type ssize_t = __darwin_ssize_t; +pub type time_t = __darwin_time_t; +pub type pthread_cond_t = __darwin_pthread_cond_t; +pub type pthread_mutex_t = __darwin_pthread_mutex_t; +#[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; +#[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) -> (); +#[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; +#[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, + 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 { + 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_capability_data { + pub cap_list: *mut clist, +} +#[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_0, + 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_0 { + 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 extern "C" 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_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, +} +#[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_1, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed_1 { + pub ft_fetch_att: *mut mailimap_fetch_att, + pub ft_fetch_att_list: *mut clist, +} +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 unnamed_2 { + 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, +} +/* define DC_USE_RPGP to enable use of rPGP instead of netpgp where available; +preferrably, this should be done in the project configuration currently */ +//#define DC_USE_RPGP 1 +/* Includes that are used frequently. This file may also be used to create predefined headers. */ +/* * Structure behind dc_context_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_context { + pub magic: uint32_t, + pub userdata: *mut libc::c_void, + pub dbfile: *mut libc::c_char, + pub blobdir: *mut libc::c_char, + pub sql: *mut dc_sqlite3_t, + pub inbox: *mut dc_imap_t, + pub inboxidle_condmutex: pthread_mutex_t, + pub perform_inbox_jobs_needed: libc::c_int, + pub probe_imap_network: libc::c_int, + pub sentbox_thread: dc_jobthread_t, + pub mvbox_thread: dc_jobthread_t, + pub smtp: *mut dc_smtp_t, + pub smtpidle_cond: pthread_cond_t, + pub smtpidle_condmutex: pthread_mutex_t, + pub smtpidle_condflag: libc::c_int, + pub smtp_suspended: libc::c_int, + pub smtp_doing_jobs: libc::c_int, + pub perform_smtp_jobs_needed: libc::c_int, + pub probe_smtp_network: libc::c_int, + pub oauth2_critical: pthread_mutex_t, + 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 type dc_lot_t = _dc_lot; +/* * Structure behind dc_lot_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_lot { + pub magic: uint32_t, + pub text1_meaning: libc::c_int, + pub text1: *mut libc::c_char, + pub text2: *mut libc::c_char, + pub timestamp: time_t, + pub state: libc::c_int, + pub id: uint32_t, + pub fingerprint: *mut libc::c_char, + pub invitenumber: *mut libc::c_char, + pub auth: *mut libc::c_char, +} +/* * + * 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 = Option< + unsafe extern "C" fn( + _: *mut dc_context_t, + _: libc::c_int, + _: uintptr_t, + _: uintptr_t, + ) -> uintptr_t, +>; +/* * + * @mainpage Getting started + * + * This document describes how to handle the Delta Chat core library. + * For general information about Delta Chat itself, + * see and . + * + * Let's start. + * + * First of all, you have to **define an event-handler-function** + * that is called by the library on specific events + * (eg. when the configuration is done or when fresh messages arrive). + * With this function you can create a Delta Chat context then: + * + * ~~~ + * #include + * + * uintptr_t event_handler_func(dc_context_t* context, int event, + * uintptr_t data1, uintptr_t data2) + * { + * return 0; // for unhandled events, it is always safe to return 0 + * } + * + * dc_context_t* context = dc_context_new(event_handler_func, NULL, NULL); + * ~~~ + * + * After that, you should make sure, + * sending and receiving jobs are processed as needed. + * For this purpose, you have to **create two threads:** + * + * ~~~ + * #include + * + * void* imap_thread_func(void* context) + * { + * while (true) { + * dc_perform_imap_jobs(context); + * dc_perform_imap_fetch(context); + * dc_perform_imap_idle(context); + * } + * } + * + * void* smtp_thread_func(void* context) + * { + * while (true) { + * dc_perform_smtp_jobs(context); + * dc_perform_smtp_idle(context); + * } + * } + * + * static pthread_t imap_thread, smtp_thread; + * pthread_create(&imap_thread, NULL, imap_thread_func, context); + * pthread_create(&smtp_thread, NULL, smtp_thread_func, context); + * ~~~ + * + * The example above uses "pthreads", + * however, you can also use anything else for thread handling. + * NB: The deltachat-core library itself does not create any threads on its own, + * however, functions, unless stated otherwise, are thread-safe. + * + * After that you can **define and open a database.** + * The database is a normal sqlite-file and is created as needed: + * + * ~~~ + * dc_open(context, "example.db", NULL); + * ~~~ + * + * Now you can **configure the context:** + * + * ~~~ + * // use some real test credentials here + * dc_set_config(context, "addr", "alice@example.org"); + * dc_set_config(context, "mail_pw", "***"); + * dc_configure(context); + * ~~~ + * + * dc_configure() returns immediately, the configuration itself may take a while + * and is done by a job in the imap-thread you've defined above. + * Once done, the #DC_EVENT_CONFIGURE_PROGRESS reports success + * to the event_handler_func() that is also defined above. + * + * The configuration result is saved in the database, + * on subsequent starts it is not needed to call dc_configure() + * (you can check this using dc_is_configured()). + * + * Now you can **send the first message:** + * + * ~~~ + * // use a real testing address here + * uint32_t contact_id = dc_create_contact(context, NULL, "bob@example.org"); + * uint32_t chat_id = dc_create_chat_by_contact_id(context, contact_id); + * + * dc_send_text_msg(context, chat_id, "Hi, here is my first message!"); + * ~~~ + * + * dc_send_text_msg() returns immediately; + * the sending itself is done by a job in the smtp-thread you've defined above. + * If you check the testing address (bob) + * and you should have received a normal email. + * Answer this email in any email program with "Got it!" + * and the imap-thread you've create above will **receive the message**. + * + * You can then **list all messages** of a chat as follow: + * + * ~~~ + * dc_array_t* msglist = dc_get_chat_msgs(context, chat_id, 0, 0); + * for (int i = 0; i < dc_array_get_cnt(msglist); i++) + * { + * uint32_t msg_id = dc_array_get_id(msglist, i); + * dc_msg_t* msg = dc_get_msg(context, msg_id); + * char* text = dc_msg_get_text(msg); + * + * printf("Message %i: %s\n", i+1, text); + * + * free(text); + * dc_msg_unref(msg); + * } + * dc_array_unref(msglist); + * ~~~ + * + * This will output the following two lines: + * + * ~~~ + * Message 1: Hi, here is my first message! + * Message 2: Got it! + * ~~~ + * + * + * ## Class reference + * + * For a class reference, see the "Classes" link atop. + * + * + * ## Further hints + * + * Here are some additional, unsorted hints that may be useful. + * + * - For `get`-functions, you have to unref the return value in some way. + * + * - Strings in function arguments or return values are usually UTF-8 encoded. + * + * - The issue-tracker for the core library is here: + * + * + * The following points are important mainly + * for the authors of the library itself: + * + * - For indentation, use tabs. + * Alignments that are not placed at the beginning of a line + * should be done with spaces. + * + * - For padding between functions, + * classes etc. use 2 empty lines + * + * - Source files are encoded as UTF-8 with Unix line endings + * (a simple `LF`, `0x0A` or `\n`) + * + * If you need further assistance, + * please do not hesitate to contact us + * through the channels shown at https://delta.chat/en/contribute + * + * Please keep in mind, that your derived work + * must respect the Mozilla Public License 2.0 of libdeltachat + * and the respective licenses of the libraries libdeltachat links with. + * + * See you. + */ +/* * + * @class dc_context_t + * + * An object representing a single account. + * + * Each account is linked to an IMAP/SMTP account and uses a separate + * SQLite database for offline functionality and for account-related + * settings. + */ +pub type dc_context_t = _dc_context; +/* ** library-private **********************************************************/ +pub type dc_smtp_t = _dc_smtp; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_smtp { + 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 error: *mut libc::c_char, + pub error_etpan: libc::c_int, +} +pub type dc_jobthread_t = _dc_jobthread; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_jobthread { + 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, + 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, +} +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_imap { + 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 type dc_receive_imf_t = Option< + unsafe extern "C" 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_imap_t = _dc_imap; +pub type dc_precheck_imf_t = Option< + unsafe extern "C" 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< + unsafe extern "C" fn(_: *mut dc_imap_t, _: *const libc::c_char, _: *const libc::c_char) -> (), +>; +pub type dc_get_config_t = Option< + unsafe extern "C" fn( + _: *mut dc_imap_t, + _: *const libc::c_char, + _: *const libc::c_char, + ) -> *mut libc::c_char, +>; +/* ** library-private **********************************************************/ +pub type dc_sqlite3_t = _dc_sqlite3; +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_sqlite3 { + pub cobj: *mut sqlite3, + pub context: *mut dc_context_t, +} +/* yes: uppercase */ +/* library private: key-history */ +#[no_mangle] +pub unsafe extern "C" fn dc_add_to_keyhistory( + mut context: *mut dc_context_t, + mut rfc724_mid: *const libc::c_char, + mut sending_time: time_t, + mut addr: *const libc::c_char, + mut fingerprint: *const libc::c_char, +) { +} diff --git a/src/dc_keyring.rs b/src/dc_keyring.rs new file mode 100644 index 000000000..51e97114a --- /dev/null +++ b/src/dc_keyring.rs @@ -0,0 +1,866 @@ +use c2rust_bitfields::BitfieldStruct; +use libc; +extern "C" { + pub type mailstream_cancel; + pub type sqlite3; + pub type sqlite3_stmt; + #[no_mangle] + fn calloc(_: libc::c_ulong, _: libc::c_ulong) -> *mut libc::c_void; + #[no_mangle] + fn free(_: *mut libc::c_void); + #[no_mangle] + fn realloc(_: *mut libc::c_void, _: libc::c_ulong) -> *mut libc::c_void; + #[no_mangle] + fn exit(_: libc::c_int) -> !; + #[no_mangle] + fn sqlite3_bind_text( + _: *mut sqlite3_stmt, + _: libc::c_int, + _: *const libc::c_char, + _: libc::c_int, + _: Option ()>, + ) -> libc::c_int; + #[no_mangle] + fn sqlite3_step(_: *mut sqlite3_stmt) -> libc::c_int; + #[no_mangle] + fn sqlite3_finalize(pStmt: *mut sqlite3_stmt) -> libc::c_int; + /* tools, these functions are compatible to the corresponding sqlite3_* functions */ + #[no_mangle] + fn dc_sqlite3_prepare(_: *mut dc_sqlite3_t, sql: *const libc::c_char) -> *mut sqlite3_stmt; + #[no_mangle] + fn dc_key_new() -> *mut dc_key_t; + #[no_mangle] + fn dc_key_ref(_: *mut dc_key_t) -> *mut dc_key_t; + #[no_mangle] + fn dc_key_unref(_: *mut dc_key_t); + #[no_mangle] + fn dc_key_set_from_stmt( + _: *mut dc_key_t, + _: *mut sqlite3_stmt, + index: libc::c_int, + type_0: libc::c_int, + ) -> libc::c_int; +} +pub type __darwin_size_t = libc::c_ulong; +pub type __darwin_ssize_t = libc::c_long; +pub type __darwin_time_t = libc::c_long; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_cond_t { + pub __sig: libc::c_long, + pub __opaque: [libc::c_char; 40], +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_mutex_t { + pub __sig: libc::c_long, + pub __opaque: [libc::c_char; 56], +} +pub type __darwin_pthread_cond_t = _opaque_pthread_cond_t; +pub type __darwin_pthread_mutex_t = _opaque_pthread_mutex_t; +pub type size_t = __darwin_size_t; +pub type uintptr_t = libc::c_ulong; +pub type ssize_t = __darwin_ssize_t; +pub type uint8_t = libc::c_uchar; +pub type uint32_t = libc::c_uint; +pub type time_t = __darwin_time_t; +pub type pthread_cond_t = __darwin_pthread_cond_t; +pub type pthread_mutex_t = __darwin_pthread_mutex_t; +#[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; +#[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) -> (); +#[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; +#[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, + 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 { + 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_capability_data { + pub cap_list: *mut clist, +} +#[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_0, + 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_0 { + 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 extern "C" 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_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, +} +#[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_1, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed_1 { + pub ft_fetch_att: *mut mailimap_fetch_att, + pub ft_fetch_att_list: *mut clist, +} +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 unnamed_2 { + 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, +} +/* define DC_USE_RPGP to enable use of rPGP instead of netpgp where available; +preferrably, this should be done in the project configuration currently */ +//#define DC_USE_RPGP 1 +/* Includes that are used frequently. This file may also be used to create predefined headers. */ +/* * Structure behind dc_context_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_context { + pub magic: uint32_t, + pub userdata: *mut libc::c_void, + pub dbfile: *mut libc::c_char, + pub blobdir: *mut libc::c_char, + pub sql: *mut dc_sqlite3_t, + pub inbox: *mut dc_imap_t, + pub inboxidle_condmutex: pthread_mutex_t, + pub perform_inbox_jobs_needed: libc::c_int, + pub probe_imap_network: libc::c_int, + pub sentbox_thread: dc_jobthread_t, + pub mvbox_thread: dc_jobthread_t, + pub smtp: *mut dc_smtp_t, + pub smtpidle_cond: pthread_cond_t, + pub smtpidle_condmutex: pthread_mutex_t, + pub smtpidle_condflag: libc::c_int, + pub smtp_suspended: libc::c_int, + pub smtp_doing_jobs: libc::c_int, + pub perform_smtp_jobs_needed: libc::c_int, + pub probe_smtp_network: libc::c_int, + pub oauth2_critical: pthread_mutex_t, + 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 type dc_lot_t = _dc_lot; +/* * Structure behind dc_lot_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_lot { + pub magic: uint32_t, + pub text1_meaning: libc::c_int, + pub text1: *mut libc::c_char, + pub text2: *mut libc::c_char, + pub timestamp: time_t, + pub state: libc::c_int, + pub id: uint32_t, + pub fingerprint: *mut libc::c_char, + pub invitenumber: *mut libc::c_char, + pub auth: *mut libc::c_char, +} +/* * + * 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 = Option< + unsafe extern "C" fn( + _: *mut dc_context_t, + _: libc::c_int, + _: uintptr_t, + _: uintptr_t, + ) -> uintptr_t, +>; +/* * + * @mainpage Getting started + * + * This document describes how to handle the Delta Chat core library. + * For general information about Delta Chat itself, + * see and . + * + * Let's start. + * + * First of all, you have to **define an event-handler-function** + * that is called by the library on specific events + * (eg. when the configuration is done or when fresh messages arrive). + * With this function you can create a Delta Chat context then: + * + * ~~~ + * #include + * + * uintptr_t event_handler_func(dc_context_t* context, int event, + * uintptr_t data1, uintptr_t data2) + * { + * return 0; // for unhandled events, it is always safe to return 0 + * } + * + * dc_context_t* context = dc_context_new(event_handler_func, NULL, NULL); + * ~~~ + * + * After that, you should make sure, + * sending and receiving jobs are processed as needed. + * For this purpose, you have to **create two threads:** + * + * ~~~ + * #include + * + * void* imap_thread_func(void* context) + * { + * while (true) { + * dc_perform_imap_jobs(context); + * dc_perform_imap_fetch(context); + * dc_perform_imap_idle(context); + * } + * } + * + * void* smtp_thread_func(void* context) + * { + * while (true) { + * dc_perform_smtp_jobs(context); + * dc_perform_smtp_idle(context); + * } + * } + * + * static pthread_t imap_thread, smtp_thread; + * pthread_create(&imap_thread, NULL, imap_thread_func, context); + * pthread_create(&smtp_thread, NULL, smtp_thread_func, context); + * ~~~ + * + * The example above uses "pthreads", + * however, you can also use anything else for thread handling. + * NB: The deltachat-core library itself does not create any threads on its own, + * however, functions, unless stated otherwise, are thread-safe. + * + * After that you can **define and open a database.** + * The database is a normal sqlite-file and is created as needed: + * + * ~~~ + * dc_open(context, "example.db", NULL); + * ~~~ + * + * Now you can **configure the context:** + * + * ~~~ + * // use some real test credentials here + * dc_set_config(context, "addr", "alice@example.org"); + * dc_set_config(context, "mail_pw", "***"); + * dc_configure(context); + * ~~~ + * + * dc_configure() returns immediately, the configuration itself may take a while + * and is done by a job in the imap-thread you've defined above. + * Once done, the #DC_EVENT_CONFIGURE_PROGRESS reports success + * to the event_handler_func() that is also defined above. + * + * The configuration result is saved in the database, + * on subsequent starts it is not needed to call dc_configure() + * (you can check this using dc_is_configured()). + * + * Now you can **send the first message:** + * + * ~~~ + * // use a real testing address here + * uint32_t contact_id = dc_create_contact(context, NULL, "bob@example.org"); + * uint32_t chat_id = dc_create_chat_by_contact_id(context, contact_id); + * + * dc_send_text_msg(context, chat_id, "Hi, here is my first message!"); + * ~~~ + * + * dc_send_text_msg() returns immediately; + * the sending itself is done by a job in the smtp-thread you've defined above. + * If you check the testing address (bob) + * and you should have received a normal email. + * Answer this email in any email program with "Got it!" + * and the imap-thread you've create above will **receive the message**. + * + * You can then **list all messages** of a chat as follow: + * + * ~~~ + * dc_array_t* msglist = dc_get_chat_msgs(context, chat_id, 0, 0); + * for (int i = 0; i < dc_array_get_cnt(msglist); i++) + * { + * uint32_t msg_id = dc_array_get_id(msglist, i); + * dc_msg_t* msg = dc_get_msg(context, msg_id); + * char* text = dc_msg_get_text(msg); + * + * printf("Message %i: %s\n", i+1, text); + * + * free(text); + * dc_msg_unref(msg); + * } + * dc_array_unref(msglist); + * ~~~ + * + * This will output the following two lines: + * + * ~~~ + * Message 1: Hi, here is my first message! + * Message 2: Got it! + * ~~~ + * + * + * ## Class reference + * + * For a class reference, see the "Classes" link atop. + * + * + * ## Further hints + * + * Here are some additional, unsorted hints that may be useful. + * + * - For `get`-functions, you have to unref the return value in some way. + * + * - Strings in function arguments or return values are usually UTF-8 encoded. + * + * - The issue-tracker for the core library is here: + * + * + * The following points are important mainly + * for the authors of the library itself: + * + * - For indentation, use tabs. + * Alignments that are not placed at the beginning of a line + * should be done with spaces. + * + * - For padding between functions, + * classes etc. use 2 empty lines + * + * - Source files are encoded as UTF-8 with Unix line endings + * (a simple `LF`, `0x0A` or `\n`) + * + * If you need further assistance, + * please do not hesitate to contact us + * through the channels shown at https://delta.chat/en/contribute + * + * Please keep in mind, that your derived work + * must respect the Mozilla Public License 2.0 of libdeltachat + * and the respective licenses of the libraries libdeltachat links with. + * + * See you. + */ +/* * + * @class dc_context_t + * + * An object representing a single account. + * + * Each account is linked to an IMAP/SMTP account and uses a separate + * SQLite database for offline functionality and for account-related + * settings. + */ +pub type dc_context_t = _dc_context; +/* ** library-private **********************************************************/ +pub type dc_smtp_t = _dc_smtp; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_smtp { + 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 error: *mut libc::c_char, + pub error_etpan: libc::c_int, +} +pub type dc_jobthread_t = _dc_jobthread; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_jobthread { + 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, + 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, +} +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_imap { + 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 type dc_receive_imf_t = Option< + unsafe extern "C" 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_imap_t = _dc_imap; +pub type dc_precheck_imf_t = Option< + unsafe extern "C" 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< + unsafe extern "C" fn(_: *mut dc_imap_t, _: *const libc::c_char, _: *const libc::c_char) -> (), +>; +pub type dc_get_config_t = Option< + unsafe extern "C" fn( + _: *mut dc_imap_t, + _: *const libc::c_char, + _: *const libc::c_char, + ) -> *mut libc::c_char, +>; +/* ** library-private **********************************************************/ +pub type dc_sqlite3_t = _dc_sqlite3; +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_sqlite3 { + pub cobj: *mut sqlite3, + pub context: *mut dc_context_t, +} +pub type sqlite3_destructor_type = Option ()>; +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_key { + pub binary: *mut libc::c_void, + pub bytes: libc::c_int, + pub type_0: libc::c_int, + pub _m_heap_refcnt: libc::c_int, +} +pub type dc_key_t = _dc_key; +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_keyring { + pub keys: *mut *mut dc_key_t, + pub count: libc::c_int, + pub allocated: libc::c_int, +} +pub type dc_keyring_t = _dc_keyring; +#[no_mangle] +pub unsafe extern "C" fn dc_keyring_new() -> *mut dc_keyring_t { + let mut keyring: *mut dc_keyring_t = 0 as *mut dc_keyring_t; + keyring = calloc( + 1i32 as libc::c_ulong, + ::std::mem::size_of::() as libc::c_ulong, + ) as *mut dc_keyring_t; + if keyring.is_null() { + exit(42i32); + } + return keyring; +} +#[no_mangle] +pub unsafe extern "C" fn dc_keyring_unref(mut keyring: *mut dc_keyring_t) { + if keyring.is_null() { + return; + } + let mut i: libc::c_int = 0i32; + while i < (*keyring).count { + dc_key_unref(*(*keyring).keys.offset(i as isize)); + i += 1 + } + 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 */ +#[no_mangle] +pub unsafe extern "C" 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() { + return; + } + if (*keyring).count == (*keyring).allocated { + let mut newsize: libc::c_int = (*keyring).allocated * 2i32 + 10i32; + (*keyring).keys = realloc( + (*keyring).keys as *mut libc::c_void, + (newsize as libc::c_ulong) + .wrapping_mul(::std::mem::size_of::<*mut dc_key_t>() as libc::c_ulong), + ) as *mut *mut dc_key_t; + if (*keyring).keys.is_null() { + exit(41i32); + } + (*keyring).allocated = newsize + } + let ref mut fresh0 = *(*keyring).keys.offset((*keyring).count as isize); + *fresh0 = dc_key_ref(to_add); + (*keyring).count += 1; +} +#[no_mangle] +pub unsafe extern "C" 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, +) -> libc::c_int { + if keyring.is_null() || self_addr.is_null() || sql.is_null() { + return 0i32; + } + let mut stmt: *mut sqlite3_stmt = dc_sqlite3_prepare( + sql, + b"SELECT private_key FROM keypairs ORDER BY addr=? DESC, is_default DESC;\x00" as *const u8 + as *const libc::c_char, + ); + sqlite3_bind_text(stmt, 1i32, self_addr, -1i32, None); + while sqlite3_step(stmt) == 100i32 { + let mut key: *mut dc_key_t = dc_key_new(); + if 0 != dc_key_set_from_stmt(key, stmt, 0i32, 1i32) { + dc_keyring_add(keyring, key); + } + dc_key_unref(key); + } + sqlite3_finalize(stmt); + return 1i32; +} diff --git a/src/dc_location.rs b/src/dc_location.rs new file mode 100644 index 000000000..9d86b0bb6 --- /dev/null +++ b/src/dc_location.rs @@ -0,0 +1,1884 @@ +use c2rust_bitfields::BitfieldStruct; +use libc; +extern "C" { + pub type mailstream_cancel; + pub type sqlite3; + pub type sqlite3_stmt; + + #[no_mangle] + pub fn dc_mprintf(format: *const libc::c_char, _: ...) -> *mut libc::c_char; + + #[no_mangle] + fn calloc(_: libc::c_ulong, _: libc::c_ulong) -> *mut libc::c_void; + #[no_mangle] + fn free(_: *mut libc::c_void); + #[no_mangle] + fn atoi(_: *const libc::c_char) -> libc::c_int; + #[no_mangle] + fn memcpy(_: *mut libc::c_void, _: *const libc::c_void, _: libc::c_ulong) -> *mut libc::c_void; + #[no_mangle] + fn memset(_: *mut libc::c_void, _: libc::c_int, _: libc::c_ulong) -> *mut libc::c_void; + #[no_mangle] + fn strchr(_: *const libc::c_char, _: libc::c_int) -> *mut libc::c_char; + #[no_mangle] + fn strcmp(_: *const libc::c_char, _: *const libc::c_char) -> libc::c_int; + #[no_mangle] + fn strlen(_: *const libc::c_char) -> libc::c_ulong; + #[no_mangle] + fn strdup(_: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn gmtime(_: *const time_t) -> *mut tm; + #[no_mangle] + fn time(_: *mut time_t) -> time_t; + #[no_mangle] + fn dc_send_msg(_: *mut dc_context_t, chat_id: uint32_t, _: *mut dc_msg_t) -> uint32_t; + #[no_mangle] + fn sqlite3_finalize(pStmt: *mut sqlite3_stmt) -> libc::c_int; + #[no_mangle] + fn dc_msg_unref(_: *mut dc_msg_t); + #[no_mangle] + fn dc_job_add( + _: *mut dc_context_t, + action: libc::c_int, + foreign_id: libc::c_int, + param: *const libc::c_char, + delay: libc::c_int, + ); + #[no_mangle] + fn dc_job_action_exists(_: *mut dc_context_t, action: libc::c_int) -> libc::c_int; + #[no_mangle] + fn dc_add_device_msg(_: *mut dc_context_t, chat_id: uint32_t, text: *const libc::c_char); + /* Misc. */ + #[no_mangle] + fn dc_stock_system_msg( + context: *mut dc_context_t, + str_id: libc::c_int, + param1: *const libc::c_char, + param2: *const libc::c_char, + from_id: uint32_t, + ) -> *mut libc::c_char; + #[no_mangle] + fn dc_param_set_int(_: *mut dc_param_t, key: libc::c_int, value: int32_t); + /* * + * @class dc_msg_t + * + * An object representing a single message in memory. + * The message object is not updated. + * If you want an update, you have to recreate the object. + */ + // 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() + #[no_mangle] + fn dc_msg_new(_: *mut dc_context_t, viewtype: libc::c_int) -> *mut dc_msg_t; + #[no_mangle] + fn sqlite3_step(_: *mut sqlite3_stmt) -> libc::c_int; + #[no_mangle] + fn sqlite3_bind_int(_: *mut sqlite3_stmt, _: libc::c_int, _: libc::c_int) -> libc::c_int; + #[no_mangle] + fn sqlite3_bind_int64(_: *mut sqlite3_stmt, _: libc::c_int, _: sqlite3_int64) -> libc::c_int; + /* tools, these functions are compatible to the corresponding sqlite3_* functions */ + #[no_mangle] + fn dc_sqlite3_prepare(_: *mut dc_sqlite3_t, sql: *const libc::c_char) -> *mut sqlite3_stmt; + #[no_mangle] + fn sqlite3_column_int(_: *mut sqlite3_stmt, iCol: libc::c_int) -> libc::c_int; + #[no_mangle] + fn sqlite3_bind_double(_: *mut sqlite3_stmt, _: libc::c_int, _: libc::c_double) -> libc::c_int; + #[no_mangle] + fn dc_array_new_typed( + _: *mut dc_context_t, + type_0: libc::c_int, + initsize: size_t, + ) -> *mut dc_array_t; + #[no_mangle] + fn dc_array_add_ptr(_: *mut dc_array_t, _: *mut libc::c_void); + #[no_mangle] + fn sqlite3_column_text(_: *mut sqlite3_stmt, iCol: libc::c_int) -> *const libc::c_uchar; + #[no_mangle] + fn dc_utf8_strlen(_: *const libc::c_char) -> size_t; + #[no_mangle] + fn sqlite3_column_int64(_: *mut sqlite3_stmt, iCol: libc::c_int) -> sqlite3_int64; + #[no_mangle] + fn sqlite3_column_double(_: *mut sqlite3_stmt, iCol: libc::c_int) -> libc::c_double; + /* * + * @class dc_array_t + * + * An object containing a simple array. + * This object is used in several places where functions need to return an array. + * The items of the array are typically IDs. + * To free an array object, use dc_array_unref(). + */ + #[no_mangle] + fn dc_array_unref(_: *mut dc_array_t); + #[no_mangle] + fn dc_array_get_cnt(_: *const dc_array_t) -> size_t; + #[no_mangle] + fn dc_array_get_ptr(_: *const dc_array_t, index: size_t) -> *mut libc::c_void; + #[no_mangle] + fn sqlite3_reset(pStmt: *mut sqlite3_stmt) -> libc::c_int; + #[no_mangle] + fn dc_sqlite3_get_config( + _: *mut dc_sqlite3_t, + key: *const libc::c_char, + def: *const libc::c_char, + ) -> *mut libc::c_char; + #[no_mangle] + fn dc_sqlite3_get_rowid2( + _: *mut 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; + /* string tools */ + #[no_mangle] + fn dc_strdup(_: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn dc_atof(_: *const libc::c_char) -> libc::c_double; + #[no_mangle] + fn dc_ftoa(_: libc::c_double) -> *mut libc::c_char; + #[no_mangle] + fn dc_str_replace( + haystack: *mut *mut libc::c_char, + needle: *const libc::c_char, + replacement: *const libc::c_char, + ) -> libc::c_int; + #[no_mangle] + fn dc_null_terminate(_: *const libc::c_char, bytes: libc::c_int) -> *mut libc::c_char; + #[no_mangle] + fn mkgmtime(_: *mut tm) -> time_t; + #[no_mangle] + fn dc_strbuilder_init(_: *mut dc_strbuilder_t, init_bytes: libc::c_int); + #[no_mangle] + fn dc_strbuilder_cat(_: *mut dc_strbuilder_t, text: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn dc_strbuilder_catf(_: *mut dc_strbuilder_t, format: *const libc::c_char, _: ...); + #[no_mangle] + fn dc_log_warning(_: *mut dc_context_t, data1: libc::c_int, msg: *const libc::c_char, _: ...); + #[no_mangle] + fn dc_log_info(_: *mut dc_context_t, data1: libc::c_int, msg: *const libc::c_char, _: ...); + #[no_mangle] + fn dc_saxparser_parse(_: *mut dc_saxparser_t, text: *const libc::c_char); + #[no_mangle] + fn dc_saxparser_set_text_handler(_: *mut dc_saxparser_t, _: dc_saxparser_text_cb_t); + #[no_mangle] + fn dc_attr_find(attr: *mut *mut libc::c_char, key: *const libc::c_char) -> *const libc::c_char; + #[no_mangle] + fn dc_saxparser_set_tag_handler( + _: *mut dc_saxparser_t, + _: dc_saxparser_starttag_cb_t, + _: dc_saxparser_endtag_cb_t, + ); + #[no_mangle] + fn dc_saxparser_init(_: *mut dc_saxparser_t, userData: *mut libc::c_void); +} +pub type __darwin_size_t = libc::c_ulong; +pub type __darwin_ssize_t = libc::c_long; +pub type __darwin_time_t = libc::c_long; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_cond_t { + pub __sig: libc::c_long, + pub __opaque: [libc::c_char; 40], +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_mutex_t { + pub __sig: libc::c_long, + pub __opaque: [libc::c_char; 56], +} +pub type __darwin_pthread_cond_t = _opaque_pthread_cond_t; +pub type __darwin_pthread_mutex_t = _opaque_pthread_mutex_t; +pub type int32_t = libc::c_int; +pub type uintptr_t = libc::c_ulong; +pub type size_t = __darwin_size_t; +pub type uint8_t = libc::c_uchar; +pub type uint32_t = libc::c_uint; +pub type uint64_t = libc::c_ulonglong; +pub type ssize_t = __darwin_ssize_t; +pub type time_t = __darwin_time_t; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct tm { + pub tm_sec: libc::c_int, + pub tm_min: libc::c_int, + pub tm_hour: libc::c_int, + pub tm_mday: libc::c_int, + pub tm_mon: libc::c_int, + pub tm_year: libc::c_int, + pub tm_wday: libc::c_int, + pub tm_yday: libc::c_int, + pub tm_isdst: libc::c_int, + pub tm_gmtoff: libc::c_long, + pub tm_zone: *mut libc::c_char, +} +pub type pthread_cond_t = __darwin_pthread_cond_t; +pub type pthread_mutex_t = __darwin_pthread_mutex_t; +#[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; +#[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) -> (); +#[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; +#[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, + 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 { + 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_capability_data { + pub cap_list: *mut clist, +} +#[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_0, + 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_0 { + 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 extern "C" 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_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, +} +#[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_1, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed_1 { + pub ft_fetch_att: *mut mailimap_fetch_att, + pub ft_fetch_att_list: *mut clist, +} +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 unnamed_2 { + 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, +} +/* define DC_USE_RPGP to enable use of rPGP instead of netpgp where available; +preferrably, this should be done in the project configuration currently */ +//#define DC_USE_RPGP 1 +/* Includes that are used frequently. This file may also be used to create predefined headers. */ +/* * Structure behind dc_context_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_context { + pub magic: uint32_t, + pub userdata: *mut libc::c_void, + pub dbfile: *mut libc::c_char, + pub blobdir: *mut libc::c_char, + pub sql: *mut dc_sqlite3_t, + pub inbox: *mut dc_imap_t, + pub inboxidle_condmutex: pthread_mutex_t, + pub perform_inbox_jobs_needed: libc::c_int, + pub probe_imap_network: libc::c_int, + pub sentbox_thread: dc_jobthread_t, + pub mvbox_thread: dc_jobthread_t, + pub smtp: *mut dc_smtp_t, + pub smtpidle_cond: pthread_cond_t, + pub smtpidle_condmutex: pthread_mutex_t, + pub smtpidle_condflag: libc::c_int, + pub smtp_suspended: libc::c_int, + pub smtp_doing_jobs: libc::c_int, + pub perform_smtp_jobs_needed: libc::c_int, + pub probe_smtp_network: libc::c_int, + pub oauth2_critical: pthread_mutex_t, + 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 type dc_lot_t = _dc_lot; +/* * Structure behind dc_lot_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_lot { + pub magic: uint32_t, + pub text1_meaning: libc::c_int, + pub text1: *mut libc::c_char, + pub text2: *mut libc::c_char, + pub timestamp: time_t, + pub state: libc::c_int, + pub id: uint32_t, + pub fingerprint: *mut libc::c_char, + pub invitenumber: *mut libc::c_char, + pub auth: *mut libc::c_char, +} +/* * + * 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 = Option< + unsafe extern "C" fn( + _: *mut dc_context_t, + _: libc::c_int, + _: uintptr_t, + _: uintptr_t, + ) -> uintptr_t, +>; +/* * + * @mainpage Getting started + * + * This document describes how to handle the Delta Chat core library. + * For general information about Delta Chat itself, + * see and . + * + * Let's start. + * + * First of all, you have to **define an event-handler-function** + * that is called by the library on specific events + * (eg. when the configuration is done or when fresh messages arrive). + * With this function you can create a Delta Chat context then: + * + * ~~~ + * #include + * + * uintptr_t event_handler_func(dc_context_t* context, int event, + * uintptr_t data1, uintptr_t data2) + * { + * return 0; // for unhandled events, it is always safe to return 0 + * } + * + * dc_context_t* context = dc_context_new(event_handler_func, NULL, NULL); + * ~~~ + * + * After that, you should make sure, + * sending and receiving jobs are processed as needed. + * For this purpose, you have to **create two threads:** + * + * ~~~ + * #include + * + * void* imap_thread_func(void* context) + * { + * while (true) { + * dc_perform_imap_jobs(context); + * dc_perform_imap_fetch(context); + * dc_perform_imap_idle(context); + * } + * } + * + * void* smtp_thread_func(void* context) + * { + * while (true) { + * dc_perform_smtp_jobs(context); + * dc_perform_smtp_idle(context); + * } + * } + * + * static pthread_t imap_thread, smtp_thread; + * pthread_create(&imap_thread, NULL, imap_thread_func, context); + * pthread_create(&smtp_thread, NULL, smtp_thread_func, context); + * ~~~ + * + * The example above uses "pthreads", + * however, you can also use anything else for thread handling. + * NB: The deltachat-core library itself does not create any threads on its own, + * however, functions, unless stated otherwise, are thread-safe. + * + * After that you can **define and open a database.** + * The database is a normal sqlite-file and is created as needed: + * + * ~~~ + * dc_open(context, "example.db", NULL); + * ~~~ + * + * Now you can **configure the context:** + * + * ~~~ + * // use some real test credentials here + * dc_set_config(context, "addr", "alice@example.org"); + * dc_set_config(context, "mail_pw", "***"); + * dc_configure(context); + * ~~~ + * + * dc_configure() returns immediately, the configuration itself may take a while + * and is done by a job in the imap-thread you've defined above. + * Once done, the #DC_EVENT_CONFIGURE_PROGRESS reports success + * to the event_handler_func() that is also defined above. + * + * The configuration result is saved in the database, + * on subsequent starts it is not needed to call dc_configure() + * (you can check this using dc_is_configured()). + * + * Now you can **send the first message:** + * + * ~~~ + * // use a real testing address here + * uint32_t contact_id = dc_create_contact(context, NULL, "bob@example.org"); + * uint32_t chat_id = dc_create_chat_by_contact_id(context, contact_id); + * + * dc_send_text_msg(context, chat_id, "Hi, here is my first message!"); + * ~~~ + * + * dc_send_text_msg() returns immediately; + * the sending itself is done by a job in the smtp-thread you've defined above. + * If you check the testing address (bob) + * and you should have received a normal email. + * Answer this email in any email program with "Got it!" + * and the imap-thread you've create above will **receive the message**. + * + * You can then **list all messages** of a chat as follow: + * + * ~~~ + * dc_array_t* msglist = dc_get_chat_msgs(context, chat_id, 0, 0); + * for (int i = 0; i < dc_array_get_cnt(msglist); i++) + * { + * uint32_t msg_id = dc_array_get_id(msglist, i); + * dc_msg_t* msg = dc_get_msg(context, msg_id); + * char* text = dc_msg_get_text(msg); + * + * printf("Message %i: %s\n", i+1, text); + * + * free(text); + * dc_msg_unref(msg); + * } + * dc_array_unref(msglist); + * ~~~ + * + * This will output the following two lines: + * + * ~~~ + * Message 1: Hi, here is my first message! + * Message 2: Got it! + * ~~~ + * + * + * ## Class reference + * + * For a class reference, see the "Classes" link atop. + * + * + * ## Further hints + * + * Here are some additional, unsorted hints that may be useful. + * + * - For `get`-functions, you have to unref the return value in some way. + * + * - Strings in function arguments or return values are usually UTF-8 encoded. + * + * - The issue-tracker for the core library is here: + * + * + * The following points are important mainly + * for the authors of the library itself: + * + * - For indentation, use tabs. + * Alignments that are not placed at the beginning of a line + * should be done with spaces. + * + * - For padding between functions, + * classes etc. use 2 empty lines + * + * - Source files are encoded as UTF-8 with Unix line endings + * (a simple `LF`, `0x0A` or `\n`) + * + * If you need further assistance, + * please do not hesitate to contact us + * through the channels shown at https://delta.chat/en/contribute + * + * Please keep in mind, that your derived work + * must respect the Mozilla Public License 2.0 of libdeltachat + * and the respective licenses of the libraries libdeltachat links with. + * + * See you. + */ +/* * + * @class dc_context_t + * + * An object representing a single account. + * + * Each account is linked to an IMAP/SMTP account and uses a separate + * SQLite database for offline functionality and for account-related + * settings. + */ +pub type dc_context_t = _dc_context; +/* ** library-private **********************************************************/ +pub type dc_smtp_t = _dc_smtp; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_smtp { + 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 error: *mut libc::c_char, + pub error_etpan: libc::c_int, +} +pub type dc_jobthread_t = _dc_jobthread; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_jobthread { + 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, + 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, +} +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_imap { + 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 type dc_receive_imf_t = Option< + unsafe extern "C" 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_imap_t = _dc_imap; +pub type dc_precheck_imf_t = Option< + unsafe extern "C" 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< + unsafe extern "C" fn(_: *mut dc_imap_t, _: *const libc::c_char, _: *const libc::c_char) -> (), +>; +pub type dc_get_config_t = Option< + unsafe extern "C" fn( + _: *mut dc_imap_t, + _: *const libc::c_char, + _: *const libc::c_char, + ) -> *mut libc::c_char, +>; +/* ** library-private **********************************************************/ +pub type dc_sqlite3_t = _dc_sqlite3; +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_sqlite3 { + pub cobj: *mut sqlite3, + pub context: *mut dc_context_t, +} +/* * the structure behind dc_array_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_array { + 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, +} +pub type dc_array_t = _dc_array; +pub type dc_param_t = _dc_param; +/* * + * @class dc_param_t + * + * An object for handling key=value parameter lists; for the key, curently only + * a single character is allowed. + * + * The object is used eg. by dc_chat_t or dc_msg_t, for readable paramter names, + * these classes define some DC_PARAM_* constantats. + * + * Only for library-internal use. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_param { + pub packed: *mut libc::c_char, +} +/* * the structure behind dc_msg_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_msg { + pub magic: uint32_t, + pub id: uint32_t, + pub from_id: uint32_t, + pub to_id: uint32_t, + pub chat_id: uint32_t, + pub move_state: dc_move_state_t, + pub type_0: libc::c_int, + pub state: libc::c_int, + pub hidden: libc::c_int, + pub timestamp_sort: time_t, + pub timestamp_sent: time_t, + pub timestamp_rcvd: time_t, + pub text: *mut libc::c_char, + pub context: *mut 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, + pub server_uid: uint32_t, + pub is_dc_message: libc::c_int, + pub starred: libc::c_int, + pub chat_blocked: libc::c_int, + pub location_id: uint32_t, + pub param: *mut dc_param_t, +} +pub type dc_move_state_t = libc::c_uint; +pub const DC_MOVE_STATE_MOVING: dc_move_state_t = 3; +pub const DC_MOVE_STATE_STAY: dc_move_state_t = 2; +pub const DC_MOVE_STATE_PENDING: dc_move_state_t = 1; +pub const DC_MOVE_STATE_UNDEFINED: dc_move_state_t = 0; +pub type dc_msg_t = _dc_msg; +pub type sqlite3_int64 = sqlite_int64; +pub type sqlite_int64 = libc::c_longlong; +// location handling +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_location { + pub location_id: uint32_t, + pub latitude: libc::c_double, + pub longitude: libc::c_double, + pub accuracy: libc::c_double, + pub timestamp: time_t, + pub contact_id: uint32_t, + pub msg_id: uint32_t, + pub chat_id: uint32_t, + pub marker: *mut libc::c_char, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_strbuilder { + pub buf: *mut libc::c_char, + pub allocated: libc::c_int, + pub free: libc::c_int, + pub eos: *mut libc::c_char, +} +pub type dc_strbuilder_t = _dc_strbuilder; +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_job { + pub job_id: uint32_t, + pub action: libc::c_int, + pub foreign_id: uint32_t, + pub desired_timestamp: time_t, + pub added_timestamp: time_t, + pub tries: libc::c_int, + pub param: *mut dc_param_t, + pub try_again: libc::c_int, + pub pending_error: *mut libc::c_char, +} +// thread IDs +// jobs in the INBOX-thread, range from DC_IMAP_THREAD..DC_IMAP_THREAD+999 +// low priority ... +// ... high priority +// jobs in the SMTP-thread, range from DC_SMTP_THREAD..DC_SMTP_THREAD+999 +// low priority ... +// ... high priority +// timeouts until actions are aborted. +// this may also affects IDLE to return, so a re-connect may take this time. +// mailcore2 uses 30 seconds, k-9 uses 10 seconds +pub type dc_job_t = _dc_job; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_kml { + pub addr: *mut libc::c_char, + pub locations: *mut dc_array_t, + pub tag: libc::c_int, + pub curr: dc_location_t, +} +pub type dc_location_t = _dc_location; +pub type dc_kml_t = _dc_kml; +pub type dc_saxparser_t = _dc_saxparser; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_saxparser { + pub starttag_cb: dc_saxparser_starttag_cb_t, + pub endtag_cb: dc_saxparser_endtag_cb_t, + pub text_cb: dc_saxparser_text_cb_t, + pub userdata: *mut libc::c_void, +} +/* len is only informational, text is already null-terminated */ +pub type dc_saxparser_text_cb_t = Option< + unsafe extern "C" fn(_: *mut libc::c_void, _: *const libc::c_char, _: libc::c_int) -> (), +>; +pub type dc_saxparser_endtag_cb_t = + Option ()>; +pub type dc_saxparser_starttag_cb_t = Option< + unsafe extern "C" fn( + _: *mut libc::c_void, + _: *const libc::c_char, + _: *mut *mut libc::c_char, + ) -> (), +>; +// location streaming +#[no_mangle] +pub unsafe extern "C" fn dc_send_locations_to_chat( + mut context: *mut dc_context_t, + mut chat_id: uint32_t, + mut seconds: libc::c_int, +) { + let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; + 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) + { + 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); + sqlite3_bind_int64( + stmt, + 1i32, + (if 0 != seconds { + now + } else { + 0i32 as libc::c_long + }) as sqlite3_int64, + ); + sqlite3_bind_int64( + stmt, + 2i32, + (if 0 != seconds { + now + seconds as libc::c_long + } else { + 0i32 as libc::c_long + }) as sqlite3_int64, + ); + sqlite3_bind_int(stmt, 3i32, chat_id as libc::c_int); + sqlite3_step(stmt); + if 0 != seconds && 0 == is_sending_locations_before { + msg = dc_msg_new(context, 10i32); + (*msg).text = dc_stock_system_msg( + context, + 64i32, + 0 as *const libc::c_char, + 0 as *const libc::c_char, + 0i32 as uint32_t, + ); + dc_param_set_int((*msg).param, 'S' as i32, 8i32); + dc_send_msg(context, chat_id, msg); + } else if 0 == seconds && 0 != is_sending_locations_before { + stock_str = dc_stock_system_msg( + context, + 65i32, + 0 as *const libc::c_char, + 0 as *const libc::c_char, + 0i32 as uint32_t, + ); + dc_add_device_msg(context, chat_id, stock_str); + } + (*context).cb.expect("non-null function pointer")( + context, + 2020i32, + chat_id as uintptr_t, + 0i32 as uintptr_t, + ); + if 0 != seconds { + schedule_MAYBE_SEND_LOCATIONS(context, 0i32); + dc_job_add( + context, + 5007i32, + chat_id as libc::c_int, + 0 as *const libc::c_char, + seconds + 1i32, + ); + } + } + free(stock_str as *mut libc::c_void); + dc_msg_unref(msg); + sqlite3_finalize(stmt); +} +/* ****************************************************************************** + * job to send locations out to all chats that want them + ******************************************************************************/ +unsafe extern "C" fn schedule_MAYBE_SEND_LOCATIONS( + mut context: *mut 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); + }; +} +#[no_mangle] +pub unsafe extern "C" fn dc_is_sending_locations_to_chat( + mut context: *mut 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 + } + } + sqlite3_finalize(stmt); + return is_sending_locations; +} +#[no_mangle] +pub unsafe extern "C" fn dc_set_location( + mut context: *mut dc_context_t, + mut latitude: libc::c_double, + mut longitude: libc::c_double, + mut accuracy: libc::c_double, +) -> libc::c_int { + 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 + { + continue_streaming = 1i32 + } else { + stmt_chats = dc_sqlite3_prepare( + (*context).sql, + b"SELECT id FROM chats WHERE locations_send_until>?;\x00" as *const u8 + as *const libc::c_char, + ); + sqlite3_bind_int64(stmt_chats, 1i32, time(0 as *mut time_t) as sqlite3_int64); + 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); + sqlite3_bind_double(stmt_insert, 1i32, latitude); + sqlite3_bind_double(stmt_insert, 2i32, longitude); + sqlite3_bind_double(stmt_insert, 3i32, accuracy); + sqlite3_bind_int64(stmt_insert, 4i32, time(0 as *mut time_t) as sqlite3_int64); + sqlite3_bind_int(stmt_insert, 5i32, chat_id as libc::c_int); + sqlite3_bind_int(stmt_insert, 6i32, 1i32); + sqlite3_step(stmt_insert); + continue_streaming = 1i32 + } + if 0 != continue_streaming { + (*context).cb.expect("non-null function pointer")( + context, + 2035i32, + 1i32 as uintptr_t, + 0i32 as uintptr_t, + ); + schedule_MAYBE_SEND_LOCATIONS(context, 0i32); + } + } + sqlite3_finalize(stmt_chats); + sqlite3_finalize(stmt_insert); + return continue_streaming; +} +#[no_mangle] +pub unsafe extern "C" fn dc_get_locations( + mut context: *mut 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, 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.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( + 1i32 as libc::c_ulong, + ::std::mem::size_of::<_dc_location>() as libc::c_ulong, + ) 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).msg_id = sqlite3_column_int(stmt, 5i32) as uint32_t; + (*loc).contact_id = sqlite3_column_int(stmt, 6i32) as uint32_t; + (*loc).chat_id = sqlite3_column_int(stmt, 7i32) as uint32_t; + if 0 != (*loc).msg_id { + let mut txt: *const libc::c_char = + sqlite3_column_text(stmt, 8i32) 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; +} +unsafe extern "C" 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; + if len == 1i32 && *txt.offset(0isize) as libc::c_int != ' ' as i32 { + return 1i32; + } + } + return 0i32; +} +#[no_mangle] +pub unsafe extern "C" 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.expect("non-null function pointer")( + context, + 2035i32, + 0i32 as uintptr_t, + 0i32 as uintptr_t, + ); + } + sqlite3_finalize(stmt); +} +#[no_mangle] +pub unsafe extern "C" fn dc_get_location_kml( + mut context: *mut 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 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 location_count: libc::c_int = 0i32; + let mut ret: dc_strbuilder_t = _dc_strbuilder { + buf: 0 as *mut libc::c_char, + allocated: 0, + free: 0, + 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, + b"\n\n\n\x00" + as *const u8 as *const libc::c_char, + self_addr); + stmt = + dc_sqlite3_prepare((*context).sql, + b"SELECT id, latitude, longitude, accuracy, timestamp FROM locations WHERE from_id=? AND timestamp>=? AND (timestamp>=? OR timestamp=(SELECT MAX(timestamp) FROM locations WHERE from_id=?)) GROUP BY timestamp ORDER BY timestamp;\x00" + as *const u8 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, + 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 + } + } + } + } + sqlite3_finalize(stmt); + free(self_addr as *mut libc::c_void); + if 0 == success { + free(ret.buf as *mut libc::c_void); + } + return if 0 != success { + ret.buf + } else { + 0 as *mut libc::c_char + }; +} +/* ****************************************************************************** + * create kml-files + ******************************************************************************/ +unsafe extern "C" fn get_kml_timestamp(mut utc: time_t) -> *mut libc::c_char { + // Returns a string formatted as YYYY-MM-DDTHH:MM:SSZ. The trailing `Z` indicates UTC. + let mut wanted_struct: 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, + }; + memcpy( + &mut wanted_struct as *mut tm as *mut libc::c_void, + gmtime(&mut utc) as *const libc::c_void, + ::std::mem::size_of::() as libc::c_ulong, + ); + return 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, + wanted_struct.tm_mday as libc::c_int, + wanted_struct.tm_hour as libc::c_int, + wanted_struct.tm_min as libc::c_int, + wanted_struct.tm_sec as libc::c_int, + ); +} +#[no_mangle] +pub unsafe extern "C" fn dc_set_kml_sent_timestamp( + mut context: *mut dc_context_t, + mut chat_id: uint32_t, + mut timestamp: time_t, +) { + let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; + stmt = dc_sqlite3_prepare( + (*context).sql, + b"UPDATE chats SET locations_last_sent=? WHERE id=?;\x00" as *const u8 + as *const libc::c_char, + ); + sqlite3_bind_int64(stmt, 1i32, timestamp as sqlite3_int64); + sqlite3_bind_int(stmt, 2i32, chat_id as libc::c_int); + sqlite3_step(stmt); + sqlite3_finalize(stmt); +} +#[no_mangle] +pub unsafe extern "C" fn dc_set_msg_location_id( + mut context: *mut dc_context_t, + mut msg_id: uint32_t, + mut location_id: uint32_t, +) { + let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; + stmt = dc_sqlite3_prepare( + (*context).sql, + 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); + sqlite3_bind_int(stmt, 2i32, msg_id as libc::c_int); + sqlite3_step(stmt); + sqlite3_finalize(stmt); +} +#[no_mangle] +pub unsafe extern "C" fn dc_save_locations( + mut context: *mut dc_context_t, + mut chat_id: uint32_t, + mut contact_id: uint32_t, + mut locations: *const dc_array_t, +) -> uint32_t { + let mut stmt_test: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; + 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()) + { + stmt_test = dc_sqlite3_prepare( + (*context).sql, + 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, + b"INSERT INTO locations (timestamp, from_id, chat_id, latitude, longitude, accuracy) VALUES (?,?,?,?,?,?);\x00" + as *const u8 as *const libc::c_char); + let mut i: libc::c_int = 0i32; + while (i as libc::c_ulong) < dc_array_get_cnt(locations) { + let mut location: *mut dc_location_t = + dc_array_get_ptr(locations, i as size_t) as *mut dc_location_t; + sqlite3_reset(stmt_test); + sqlite3_bind_int64(stmt_test, 1i32, (*location).timestamp as sqlite3_int64); + sqlite3_bind_int(stmt_test, 2i32, contact_id as libc::c_int); + if sqlite3_step(stmt_test) != 100i32 { + sqlite3_reset(stmt_insert); + sqlite3_bind_int64(stmt_insert, 1i32, (*location).timestamp as sqlite3_int64); + sqlite3_bind_int(stmt_insert, 2i32, contact_id as libc::c_int); + sqlite3_bind_int(stmt_insert, 3i32, chat_id as libc::c_int); + sqlite3_bind_double(stmt_insert, 4i32, (*location).latitude); + sqlite3_bind_double(stmt_insert, 5i32, (*location).longitude); + sqlite3_bind_double(stmt_insert, 6i32, (*location).accuracy); + sqlite3_step(stmt_insert); + } + if (*location).timestamp > newest_timestamp { + newest_timestamp = (*location).timestamp; + newest_location_id = dc_sqlite3_get_rowid2( + (*context).sql, + 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, + b"from_id\x00" as *const u8 as *const libc::c_char, + contact_id, + ) + } + i += 1 + } + } + sqlite3_finalize(stmt_test); + sqlite3_finalize(stmt_insert); + return newest_location_id; +} +#[no_mangle] +pub unsafe extern "C" fn dc_kml_parse( + mut context: *mut dc_context_t, + mut content: *const libc::c_char, + mut content_bytes: size_t, +) -> *mut dc_kml_t { + let mut kml: *mut dc_kml_t = calloc( + 1i32 as libc::c_ulong, + ::std::mem::size_of::() as libc::c_ulong, + ) as *mut dc_kml_t; + let mut content_nullterminated: *mut libc::c_char = 0 as *mut libc::c_char; + let mut saxparser: dc_saxparser_t = _dc_saxparser { + starttag_cb: None, + endtag_cb: None, + text_cb: None, + userdata: 0 as *mut libc::c_void, + }; + if !(context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint) { + if content_bytes > (1i32 * 1024i32 * 1024i32) as libc::c_ulong { + dc_log_warning( + context, + 0i32, + 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(context, 1i32, 100i32 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); + } + } + } + free(content_nullterminated as *mut libc::c_void); + return kml; +} +unsafe extern "C" fn kml_text_cb( + mut userdata: *mut libc::c_void, + mut text: *const libc::c_char, + mut len: libc::c_int, +) { + let mut kml: *mut dc_kml_t = userdata as *mut dc_kml_t; + if 0 != (*kml).tag & (0x4i32 | 0x10i32) { + let mut val: *mut libc::c_char = dc_strdup(text); + dc_str_replace( + &mut val, + b"\n\x00" as *const u8 as *const libc::c_char, + b"\x00" as *const u8 as *const libc::c_char, + ); + dc_str_replace( + &mut val, + b"\r\x00" as *const u8 as *const libc::c_char, + b"\x00" as *const u8 as *const libc::c_char, + ); + dc_str_replace( + &mut val, + b"\t\x00" as *const u8 as *const libc::c_char, + b"\x00" as *const u8 as *const libc::c_char, + ); + dc_str_replace( + &mut val, + b" \x00" as *const u8 as *const libc::c_char, + b"\x00" as *const u8 as *const libc::c_char, + ); + if 0 != (*kml).tag & 0x4i32 && strlen(val) >= 19i32 as libc::c_ulong { + let mut tmval: 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, + }; + memset( + &mut tmval as *mut tm as *mut libc::c_void, + 0i32, + ::std::mem::size_of::() as libc::c_ulong, + ); + *val.offset(4isize) = 0i32 as libc::c_char; + tmval.tm_year = atoi(val) - 1900i32; + *val.offset(7isize) = 0i32 as libc::c_char; + tmval.tm_mon = atoi(val.offset(5isize)) - 1i32; + *val.offset(10isize) = 0i32 as libc::c_char; + tmval.tm_mday = atoi(val.offset(8isize)); + *val.offset(13isize) = 0i32 as libc::c_char; + tmval.tm_hour = atoi(val.offset(11isize)); + *val.offset(16isize) = 0i32 as libc::c_char; + tmval.tm_min = atoi(val.offset(14isize)); + *val.offset(19isize) = 0i32 as libc::c_char; + tmval.tm_sec = atoi(val.offset(17isize)); + (*kml).curr.timestamp = mkgmtime(&mut tmval); + if (*kml).curr.timestamp > time(0 as *mut time_t) { + (*kml).curr.timestamp = time(0 as *mut time_t) + } + } else if 0 != (*kml).tag & 0x10i32 { + let mut comma: *mut libc::c_char = strchr(val, ',' as i32); + if !comma.is_null() { + let mut longitude: *mut libc::c_char = val; + let mut latitude: *mut libc::c_char = comma.offset(1isize); + *comma = 0i32 as libc::c_char; + comma = strchr(latitude, ',' as i32); + if !comma.is_null() { + *comma = 0i32 as libc::c_char + } + (*kml).curr.latitude = dc_atof(latitude); + (*kml).curr.longitude = dc_atof(longitude) + } + } + free(val as *mut libc::c_void); + }; +} +unsafe extern "C" 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 { + if 0 != (*kml).tag & 0x1i32 + && 0 != (*kml).curr.timestamp + && 0. != (*kml).curr.latitude + && 0. != (*kml).curr.longitude + { + let mut location: *mut dc_location_t = calloc( + 1i32 as libc::c_ulong, + ::std::mem::size_of::() as libc::c_ulong, + ) as *mut dc_location_t; + *location = (*kml).curr; + dc_array_add_ptr((*kml).locations, location as *mut libc::c_void); + } + (*kml).tag = 0i32 + }; +} +/* ****************************************************************************** + * parse kml-files + ******************************************************************************/ +unsafe extern "C" fn kml_starttag_cb( + mut userdata: *mut libc::c_void, + mut tag: *const libc::c_char, + mut attr: *mut *mut libc::c_char, +) { + let mut kml: *mut dc_kml_t = userdata as *mut dc_kml_t; + if strcmp(tag, b"document\x00" as *const u8 as *const libc::c_char) == 0i32 { + let mut addr: *const libc::c_char = + dc_attr_find(attr, b"addr\x00" as *const u8 as *const libc::c_char); + if !addr.is_null() { + (*kml).addr = dc_strdup(addr) + } + } else if strcmp(tag, b"placemark\x00" as *const u8 as *const libc::c_char) == 0i32 { + (*kml).tag = 0x1i32; + (*kml).curr.timestamp = 0i32 as time_t; + (*kml).curr.latitude = 0i32 as libc::c_double; + (*kml).curr.longitude = 0.0f64; + (*kml).curr.accuracy = 0.0f64 + } else if strcmp(tag, b"timestamp\x00" as *const u8 as *const libc::c_char) == 0i32 + && 0 != (*kml).tag & 0x1i32 + { + (*kml).tag = 0x1i32 | 0x2i32 + } else if strcmp(tag, b"when\x00" as *const u8 as *const libc::c_char) == 0i32 + && 0 != (*kml).tag & 0x2i32 + { + (*kml).tag = 0x1i32 | 0x2i32 | 0x4i32 + } else if strcmp(tag, b"point\x00" as *const u8 as *const libc::c_char) == 0i32 + && 0 != (*kml).tag & 0x1i32 + { + (*kml).tag = 0x1i32 | 0x8i32 + } else if strcmp(tag, b"coordinates\x00" as *const u8 as *const libc::c_char) == 0i32 + && 0 != (*kml).tag & 0x8i32 + { + (*kml).tag = 0x1i32 | 0x8i32 | 0x10i32; + let mut accuracy: *const libc::c_char = + dc_attr_find(attr, b"accuracy\x00" as *const u8 as *const libc::c_char); + if !accuracy.is_null() { + (*kml).curr.accuracy = dc_atof(accuracy) + } + }; +} +#[no_mangle] +pub unsafe extern "C" fn dc_kml_unref(mut kml: *mut dc_kml_t) { + if kml.is_null() { + return; + } + dc_array_unref((*kml).locations); + free((*kml).addr as *mut libc::c_void); + free(kml as *mut libc::c_void); +} +#[no_mangle] +pub unsafe extern "C" fn dc_job_do_DC_JOB_MAYBE_SEND_LOCATIONS( + mut context: *mut dc_context_t, + mut job: *mut dc_job_t, +) { + let mut stmt_chats: *mut sqlite3_stmt = 0 as *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; + dc_log_info( + context, + 0i32, + b" ----------------- MAYBE_SEND_LOCATIONS -------------- \x00" as *const u8 + as *const libc::c_char, + ); + stmt_chats = + dc_sqlite3_prepare((*context).sql, + 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); + while sqlite3_step(stmt_chats) == 100i32 { + let mut chat_id: uint32_t = sqlite3_column_int(stmt_chats, 0i32) as uint32_t; + let mut locations_send_begin: time_t = sqlite3_column_int64(stmt_chats, 1i32) as time_t; + let mut locations_last_sent: time_t = sqlite3_column_int64(stmt_chats, 2i32) as time_t; + continue_streaming = 1i32; + // be a bit tolerant as the timer may not align exactly with time(NULL) + if now - locations_last_sent < (60i32 - 3i32) as libc::c_long { + continue; + } + if stmt_locations.is_null() { + stmt_locations = + dc_sqlite3_prepare((*context).sql, + b"SELECT id FROM locations WHERE from_id=? AND timestamp>=? AND timestamp>? ORDER BY timestamp;\x00" + as *const u8 as *const libc::c_char) + } else { + sqlite3_reset(stmt_locations); + } + sqlite3_bind_int(stmt_locations, 1i32, 1i32); + sqlite3_bind_int64(stmt_locations, 2i32, locations_send_begin as sqlite3_int64); + sqlite3_bind_int64(stmt_locations, 3i32, locations_last_sent as sqlite3_int64); + // if there is no new location, there's nothing to send. + // however, maybe we want to bypass this test eg. 15 minutes + if sqlite3_step(stmt_locations) != 100i32 { + continue; + } + // pending locations are attached automatically to every message, + // so also to this empty text message. + // DC_CMD_LOCATION is only needed to create a nicer subject. + // + // for optimisation and to avoid flooding the sending queue, + // we could sending these messages only if we're really online. + // the easiest way to determine this, is to check for an empty message queue. + // (might not be 100%, however, as positions are sent combined later + // and dc_set_location() is typically called periodically, this is ok) + let mut msg: *mut dc_msg_t = dc_msg_new(context, 10i32); + (*msg).hidden = 1i32; + dc_param_set_int((*msg).param, 'S' as i32, 9i32); + dc_send_msg(context, chat_id, msg); + dc_msg_unref(msg); + } + if 0 != continue_streaming { + schedule_MAYBE_SEND_LOCATIONS(context, 0x1i32); + } + sqlite3_finalize(stmt_chats); + sqlite3_finalize(stmt_locations); +} +#[no_mangle] +pub unsafe extern "C" fn dc_job_do_DC_JOB_MAYBE_SEND_LOC_ENDED( + mut context: *mut 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 stock_str: *mut libc::c_char = 0 as *mut libc::c_char; + stmt = dc_sqlite3_prepare( + (*context).sql, + b"SELECT locations_send_begin, locations_send_until 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; + sqlite3_finalize(stmt); + stmt = 0 as *mut sqlite3_stmt; + if !(locations_send_begin != 0i32 as libc::c_long + && time(0 as *mut time_t) <= locations_send_until) + { + // still streaming - + // may happen as several calls to dc_send_locations_to_chat() + // do not un-schedule pending DC_MAYBE_SEND_LOC_ENDED jobs + if !(locations_send_begin == 0i32 as libc::c_long + && locations_send_until == 0i32 as libc::c_long) + { + // 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); + sqlite3_bind_int(stmt, 1i32, chat_id as libc::c_int); + sqlite3_step(stmt); + stock_str = dc_stock_system_msg( + context, + 65i32, + 0 as *const libc::c_char, + 0 as *const libc::c_char, + 0i32 as uint32_t, + ); + dc_add_device_msg(context, chat_id, stock_str); + (*context).cb.expect("non-null function pointer")( + context, + 2020i32, + chat_id as uintptr_t, + 0i32 as uintptr_t, + ); + } + } + } + sqlite3_finalize(stmt); + free(stock_str as *mut libc::c_void); +} diff --git a/src/dc_log.rs b/src/dc_log.rs new file mode 100644 index 000000000..8fd040481 --- /dev/null +++ b/src/dc_log.rs @@ -0,0 +1,852 @@ +use c2rust_bitfields::BitfieldStruct; +use libc; +extern "C" { + pub type mailstream_cancel; + pub type sqlite3; + #[no_mangle] + fn free(_: *mut libc::c_void); + #[no_mangle] + fn vsnprintf( + _: *mut libc::c_char, + _: libc::c_ulong, + _: *const libc::c_char, + _: ::std::ffi::VaList, + ) -> libc::c_int; + /* string tools */ + #[no_mangle] + fn dc_strdup(_: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn dc_mprintf(format: *const libc::c_char, _: ...) -> *mut libc::c_char; +} +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 __darwin_size_t = libc::c_ulong; +pub type __darwin_ssize_t = libc::c_long; +pub type __darwin_time_t = libc::c_long; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_cond_t { + pub __sig: libc::c_long, + pub __opaque: [libc::c_char; 40], +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_mutex_t { + pub __sig: libc::c_long, + pub __opaque: [libc::c_char; 56], +} +pub type __darwin_pthread_cond_t = _opaque_pthread_cond_t; +pub type __darwin_pthread_mutex_t = _opaque_pthread_mutex_t; +pub type size_t = __darwin_size_t; +pub type uintptr_t = libc::c_ulong; +pub type ssize_t = __darwin_ssize_t; +pub type uint8_t = libc::c_uchar; +pub type uint32_t = libc::c_uint; +pub type time_t = __darwin_time_t; +pub type pthread_cond_t = __darwin_pthread_cond_t; +pub type pthread_mutex_t = __darwin_pthread_mutex_t; +#[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; +#[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) -> (); +#[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; +#[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, + 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 { + 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_capability_data { + pub cap_list: *mut clist, +} +#[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_0, + 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_0 { + 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 extern "C" 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_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, +} +#[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_1, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed_1 { + pub ft_fetch_att: *mut mailimap_fetch_att, + pub ft_fetch_att_list: *mut clist, +} +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 unnamed_2 { + 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, +} +/* define DC_USE_RPGP to enable use of rPGP instead of netpgp where available; +preferrably, this should be done in the project configuration currently */ +//#define DC_USE_RPGP 1 +/* Includes that are used frequently. This file may also be used to create predefined headers. */ +/* * Structure behind dc_context_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_context { + pub magic: uint32_t, + pub userdata: *mut libc::c_void, + pub dbfile: *mut libc::c_char, + pub blobdir: *mut libc::c_char, + pub sql: *mut dc_sqlite3_t, + pub inbox: *mut dc_imap_t, + pub inboxidle_condmutex: pthread_mutex_t, + pub perform_inbox_jobs_needed: libc::c_int, + pub probe_imap_network: libc::c_int, + pub sentbox_thread: dc_jobthread_t, + pub mvbox_thread: dc_jobthread_t, + pub smtp: *mut dc_smtp_t, + pub smtpidle_cond: pthread_cond_t, + pub smtpidle_condmutex: pthread_mutex_t, + pub smtpidle_condflag: libc::c_int, + pub smtp_suspended: libc::c_int, + pub smtp_doing_jobs: libc::c_int, + pub perform_smtp_jobs_needed: libc::c_int, + pub probe_smtp_network: libc::c_int, + pub oauth2_critical: pthread_mutex_t, + 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 type dc_lot_t = _dc_lot; +/* * Structure behind dc_lot_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_lot { + pub magic: uint32_t, + pub text1_meaning: libc::c_int, + pub text1: *mut libc::c_char, + pub text2: *mut libc::c_char, + pub timestamp: time_t, + pub state: libc::c_int, + pub id: uint32_t, + pub fingerprint: *mut libc::c_char, + pub invitenumber: *mut libc::c_char, + pub auth: *mut libc::c_char, +} +/* * + * 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 = Option< + unsafe extern "C" fn( + _: *mut dc_context_t, + _: libc::c_int, + _: uintptr_t, + _: uintptr_t, + ) -> uintptr_t, +>; +/* * + * @mainpage Getting started + * + * This document describes how to handle the Delta Chat core library. + * For general information about Delta Chat itself, + * see and . + * + * Let's start. + * + * First of all, you have to **define an event-handler-function** + * that is called by the library on specific events + * (eg. when the configuration is done or when fresh messages arrive). + * With this function you can create a Delta Chat context then: + * + * ~~~ + * #include + * + * uintptr_t event_handler_func(dc_context_t* context, int event, + * uintptr_t data1, uintptr_t data2) + * { + * return 0; // for unhandled events, it is always safe to return 0 + * } + * + * dc_context_t* context = dc_context_new(event_handler_func, NULL, NULL); + * ~~~ + * + * After that, you should make sure, + * sending and receiving jobs are processed as needed. + * For this purpose, you have to **create two threads:** + * + * ~~~ + * #include + * + * void* imap_thread_func(void* context) + * { + * while (true) { + * dc_perform_imap_jobs(context); + * dc_perform_imap_fetch(context); + * dc_perform_imap_idle(context); + * } + * } + * + * void* smtp_thread_func(void* context) + * { + * while (true) { + * dc_perform_smtp_jobs(context); + * dc_perform_smtp_idle(context); + * } + * } + * + * static pthread_t imap_thread, smtp_thread; + * pthread_create(&imap_thread, NULL, imap_thread_func, context); + * pthread_create(&smtp_thread, NULL, smtp_thread_func, context); + * ~~~ + * + * The example above uses "pthreads", + * however, you can also use anything else for thread handling. + * NB: The deltachat-core library itself does not create any threads on its own, + * however, functions, unless stated otherwise, are thread-safe. + * + * After that you can **define and open a database.** + * The database is a normal sqlite-file and is created as needed: + * + * ~~~ + * dc_open(context, "example.db", NULL); + * ~~~ + * + * Now you can **configure the context:** + * + * ~~~ + * // use some real test credentials here + * dc_set_config(context, "addr", "alice@example.org"); + * dc_set_config(context, "mail_pw", "***"); + * dc_configure(context); + * ~~~ + * + * dc_configure() returns immediately, the configuration itself may take a while + * and is done by a job in the imap-thread you've defined above. + * Once done, the #DC_EVENT_CONFIGURE_PROGRESS reports success + * to the event_handler_func() that is also defined above. + * + * The configuration result is saved in the database, + * on subsequent starts it is not needed to call dc_configure() + * (you can check this using dc_is_configured()). + * + * Now you can **send the first message:** + * + * ~~~ + * // use a real testing address here + * uint32_t contact_id = dc_create_contact(context, NULL, "bob@example.org"); + * uint32_t chat_id = dc_create_chat_by_contact_id(context, contact_id); + * + * dc_send_text_msg(context, chat_id, "Hi, here is my first message!"); + * ~~~ + * + * dc_send_text_msg() returns immediately; + * the sending itself is done by a job in the smtp-thread you've defined above. + * If you check the testing address (bob) + * and you should have received a normal email. + * Answer this email in any email program with "Got it!" + * and the imap-thread you've create above will **receive the message**. + * + * You can then **list all messages** of a chat as follow: + * + * ~~~ + * dc_array_t* msglist = dc_get_chat_msgs(context, chat_id, 0, 0); + * for (int i = 0; i < dc_array_get_cnt(msglist); i++) + * { + * uint32_t msg_id = dc_array_get_id(msglist, i); + * dc_msg_t* msg = dc_get_msg(context, msg_id); + * char* text = dc_msg_get_text(msg); + * + * printf("Message %i: %s\n", i+1, text); + * + * free(text); + * dc_msg_unref(msg); + * } + * dc_array_unref(msglist); + * ~~~ + * + * This will output the following two lines: + * + * ~~~ + * Message 1: Hi, here is my first message! + * Message 2: Got it! + * ~~~ + * + * + * ## Class reference + * + * For a class reference, see the "Classes" link atop. + * + * + * ## Further hints + * + * Here are some additional, unsorted hints that may be useful. + * + * - For `get`-functions, you have to unref the return value in some way. + * + * - Strings in function arguments or return values are usually UTF-8 encoded. + * + * - The issue-tracker for the core library is here: + * + * + * The following points are important mainly + * for the authors of the library itself: + * + * - For indentation, use tabs. + * Alignments that are not placed at the beginning of a line + * should be done with spaces. + * + * - For padding between functions, + * classes etc. use 2 empty lines + * + * - Source files are encoded as UTF-8 with Unix line endings + * (a simple `LF`, `0x0A` or `\n`) + * + * If you need further assistance, + * please do not hesitate to contact us + * through the channels shown at https://delta.chat/en/contribute + * + * Please keep in mind, that your derived work + * must respect the Mozilla Public License 2.0 of libdeltachat + * and the respective licenses of the libraries libdeltachat links with. + * + * See you. + */ +/* * + * @class dc_context_t + * + * An object representing a single account. + * + * Each account is linked to an IMAP/SMTP account and uses a separate + * SQLite database for offline functionality and for account-related + * settings. + */ +pub type dc_context_t = _dc_context; +/* ** library-private **********************************************************/ +pub type dc_smtp_t = _dc_smtp; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_smtp { + 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 error: *mut libc::c_char, + pub error_etpan: libc::c_int, +} +pub type dc_jobthread_t = _dc_jobthread; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_jobthread { + 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, + 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, +} +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_imap { + 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 type dc_receive_imf_t = Option< + unsafe extern "C" 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_imap_t = _dc_imap; +pub type dc_precheck_imf_t = Option< + unsafe extern "C" 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< + unsafe extern "C" fn(_: *mut dc_imap_t, _: *const libc::c_char, _: *const libc::c_char) -> (), +>; +pub type dc_get_config_t = Option< + unsafe extern "C" fn( + _: *mut dc_imap_t, + _: *const libc::c_char, + _: *const libc::c_char, + ) -> *mut libc::c_char, +>; +/* ** library-private **********************************************************/ +pub type dc_sqlite3_t = _dc_sqlite3; +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_sqlite3 { + pub cobj: *mut sqlite3, + pub context: *mut dc_context_t, +} +#[no_mangle] +pub unsafe extern "C" fn dc_log_event( + mut context: *mut dc_context_t, + mut event_code: libc::c_int, + mut data1: libc::c_int, + mut msg: *const libc::c_char, + mut va: ... +) { + 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. + +"Normal" errors are usually returned by a special value (null or so) and are +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 extern "C" fn log_vprintf( + mut context: *mut dc_context_t, + mut event: libc::c_int, + 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; + } + if !msg_format.is_null() { + let mut tempbuf: [libc::c_char; 1025] = [0; 1025]; + vsnprintf( + tempbuf.as_mut_ptr(), + 1024i32 as libc::c_ulong, + msg_format, + va_0, + ); + msg = dc_strdup(tempbuf.as_mut_ptr()) + } else { + msg = dc_mprintf( + b"event #%i\x00" as *const u8 as *const libc::c_char, + event as libc::c_int, + ) + } + (*context).cb.expect("non-null function pointer")( + context, + event, + data1 as uintptr_t, + msg as uintptr_t, + ); + free(msg as *mut libc::c_void); +} +#[no_mangle] +pub unsafe extern "C" fn dc_log_event_seq( + mut context: *mut dc_context_t, + mut event_code: libc::c_int, + 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 + { + return; + } + log_vprintf(context, event_code, *sequence_start, msg, va_0); + *sequence_start = 0i32; +} +#[no_mangle] +pub unsafe extern "C" fn dc_log_error( + mut context: *mut dc_context_t, + mut data1: libc::c_int, + mut msg: *const libc::c_char, + mut va_1: ... +) { + log_vprintf(context, 400i32, data1, msg, va_1); +} +#[no_mangle] +pub unsafe extern "C" fn dc_log_warning( + mut context: *mut dc_context_t, + mut data1: libc::c_int, + mut msg: *const libc::c_char, + mut va_2: ... +) { + log_vprintf(context, 300i32, data1, msg, va_2); +} +#[no_mangle] +pub unsafe extern "C" fn dc_log_info( + mut context: *mut dc_context_t, + mut data1: libc::c_int, + mut msg: *const libc::c_char, + mut va_3: ... +) { + log_vprintf(context, 100i32, data1, msg, va_3); +} diff --git a/src/dc_loginparam.rs b/src/dc_loginparam.rs new file mode 100644 index 000000000..d39b9192d --- /dev/null +++ b/src/dc_loginparam.rs @@ -0,0 +1,1153 @@ +use c2rust_bitfields::BitfieldStruct; +use libc; +extern "C" { + pub type mailstream_cancel; + pub type sqlite3; + #[no_mangle] + fn calloc(_: libc::c_ulong, _: libc::c_ulong) -> *mut libc::c_void; + #[no_mangle] + fn free(_: *mut libc::c_void); + #[no_mangle] + fn exit(_: libc::c_int) -> !; + #[no_mangle] + fn sqlite3_mprintf(_: *const libc::c_char, _: ...) -> *mut libc::c_char; + #[no_mangle] + fn sqlite3_free(_: *mut libc::c_void); + /* handle configurations, private */ + #[no_mangle] + fn dc_sqlite3_set_config( + _: *mut dc_sqlite3_t, + key: *const libc::c_char, + value: *const libc::c_char, + ) -> libc::c_int; + #[no_mangle] + fn dc_sqlite3_set_config_int( + _: *mut dc_sqlite3_t, + key: *const libc::c_char, + value: int32_t, + ) -> libc::c_int; + #[no_mangle] + fn dc_sqlite3_get_config( + _: *mut dc_sqlite3_t, + key: *const libc::c_char, + def: *const libc::c_char, + ) -> *mut libc::c_char; + #[no_mangle] + fn dc_sqlite3_get_config_int( + _: *mut dc_sqlite3_t, + key: *const libc::c_char, + def: int32_t, + ) -> int32_t; + /* string tools */ + #[no_mangle] + fn dc_strdup(_: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn dc_trim(_: *mut libc::c_char); + #[no_mangle] + fn dc_mprintf(format: *const libc::c_char, _: ...) -> *mut libc::c_char; + #[no_mangle] + fn dc_strbuilder_init(_: *mut dc_strbuilder_t, init_bytes: libc::c_int); + #[no_mangle] + fn dc_strbuilder_cat(_: *mut dc_strbuilder_t, text: *const libc::c_char) -> *mut libc::c_char; +} +pub type __darwin_size_t = libc::c_ulong; +pub type __darwin_ssize_t = libc::c_long; +pub type __darwin_time_t = libc::c_long; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_cond_t { + pub __sig: libc::c_long, + pub __opaque: [libc::c_char; 40], +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_mutex_t { + pub __sig: libc::c_long, + pub __opaque: [libc::c_char; 56], +} +pub type __darwin_pthread_cond_t = _opaque_pthread_cond_t; +pub type __darwin_pthread_mutex_t = _opaque_pthread_mutex_t; +pub type int32_t = libc::c_int; +pub type uintptr_t = libc::c_ulong; +pub type size_t = __darwin_size_t; +pub type uint8_t = libc::c_uchar; +pub type uint16_t = libc::c_ushort; +pub type uint32_t = libc::c_uint; +pub type ssize_t = __darwin_ssize_t; +pub type time_t = __darwin_time_t; +pub type pthread_cond_t = __darwin_pthread_cond_t; +pub type pthread_mutex_t = __darwin_pthread_mutex_t; +#[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; +#[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) -> (); +#[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; +#[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, + 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 { + 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_capability_data { + pub cap_list: *mut clist, +} +#[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_0, + 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_0 { + 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 extern "C" 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_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, +} +#[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_1, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed_1 { + pub ft_fetch_att: *mut mailimap_fetch_att, + pub ft_fetch_att_list: *mut clist, +} +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 unnamed_2 { + 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, +} +/* define DC_USE_RPGP to enable use of rPGP instead of netpgp where available; +preferrably, this should be done in the project configuration currently */ +//#define DC_USE_RPGP 1 +/* Includes that are used frequently. This file may also be used to create predefined headers. */ +/* * Structure behind dc_context_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_context { + pub magic: uint32_t, + pub userdata: *mut libc::c_void, + pub dbfile: *mut libc::c_char, + pub blobdir: *mut libc::c_char, + pub sql: *mut dc_sqlite3_t, + pub inbox: *mut dc_imap_t, + pub inboxidle_condmutex: pthread_mutex_t, + pub perform_inbox_jobs_needed: libc::c_int, + pub probe_imap_network: libc::c_int, + pub sentbox_thread: dc_jobthread_t, + pub mvbox_thread: dc_jobthread_t, + pub smtp: *mut dc_smtp_t, + pub smtpidle_cond: pthread_cond_t, + pub smtpidle_condmutex: pthread_mutex_t, + pub smtpidle_condflag: libc::c_int, + pub smtp_suspended: libc::c_int, + pub smtp_doing_jobs: libc::c_int, + pub perform_smtp_jobs_needed: libc::c_int, + pub probe_smtp_network: libc::c_int, + pub oauth2_critical: pthread_mutex_t, + 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 type dc_lot_t = _dc_lot; +/* * Structure behind dc_lot_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_lot { + pub magic: uint32_t, + pub text1_meaning: libc::c_int, + pub text1: *mut libc::c_char, + pub text2: *mut libc::c_char, + pub timestamp: time_t, + pub state: libc::c_int, + pub id: uint32_t, + pub fingerprint: *mut libc::c_char, + pub invitenumber: *mut libc::c_char, + pub auth: *mut libc::c_char, +} +/* * + * 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 = Option< + unsafe extern "C" fn( + _: *mut dc_context_t, + _: libc::c_int, + _: uintptr_t, + _: uintptr_t, + ) -> uintptr_t, +>; +/* * + * @mainpage Getting started + * + * This document describes how to handle the Delta Chat core library. + * For general information about Delta Chat itself, + * see and . + * + * Let's start. + * + * First of all, you have to **define an event-handler-function** + * that is called by the library on specific events + * (eg. when the configuration is done or when fresh messages arrive). + * With this function you can create a Delta Chat context then: + * + * ~~~ + * #include + * + * uintptr_t event_handler_func(dc_context_t* context, int event, + * uintptr_t data1, uintptr_t data2) + * { + * return 0; // for unhandled events, it is always safe to return 0 + * } + * + * dc_context_t* context = dc_context_new(event_handler_func, NULL, NULL); + * ~~~ + * + * After that, you should make sure, + * sending and receiving jobs are processed as needed. + * For this purpose, you have to **create two threads:** + * + * ~~~ + * #include + * + * void* imap_thread_func(void* context) + * { + * while (true) { + * dc_perform_imap_jobs(context); + * dc_perform_imap_fetch(context); + * dc_perform_imap_idle(context); + * } + * } + * + * void* smtp_thread_func(void* context) + * { + * while (true) { + * dc_perform_smtp_jobs(context); + * dc_perform_smtp_idle(context); + * } + * } + * + * static pthread_t imap_thread, smtp_thread; + * pthread_create(&imap_thread, NULL, imap_thread_func, context); + * pthread_create(&smtp_thread, NULL, smtp_thread_func, context); + * ~~~ + * + * The example above uses "pthreads", + * however, you can also use anything else for thread handling. + * NB: The deltachat-core library itself does not create any threads on its own, + * however, functions, unless stated otherwise, are thread-safe. + * + * After that you can **define and open a database.** + * The database is a normal sqlite-file and is created as needed: + * + * ~~~ + * dc_open(context, "example.db", NULL); + * ~~~ + * + * Now you can **configure the context:** + * + * ~~~ + * // use some real test credentials here + * dc_set_config(context, "addr", "alice@example.org"); + * dc_set_config(context, "mail_pw", "***"); + * dc_configure(context); + * ~~~ + * + * dc_configure() returns immediately, the configuration itself may take a while + * and is done by a job in the imap-thread you've defined above. + * Once done, the #DC_EVENT_CONFIGURE_PROGRESS reports success + * to the event_handler_func() that is also defined above. + * + * The configuration result is saved in the database, + * on subsequent starts it is not needed to call dc_configure() + * (you can check this using dc_is_configured()). + * + * Now you can **send the first message:** + * + * ~~~ + * // use a real testing address here + * uint32_t contact_id = dc_create_contact(context, NULL, "bob@example.org"); + * uint32_t chat_id = dc_create_chat_by_contact_id(context, contact_id); + * + * dc_send_text_msg(context, chat_id, "Hi, here is my first message!"); + * ~~~ + * + * dc_send_text_msg() returns immediately; + * the sending itself is done by a job in the smtp-thread you've defined above. + * If you check the testing address (bob) + * and you should have received a normal email. + * Answer this email in any email program with "Got it!" + * and the imap-thread you've create above will **receive the message**. + * + * You can then **list all messages** of a chat as follow: + * + * ~~~ + * dc_array_t* msglist = dc_get_chat_msgs(context, chat_id, 0, 0); + * for (int i = 0; i < dc_array_get_cnt(msglist); i++) + * { + * uint32_t msg_id = dc_array_get_id(msglist, i); + * dc_msg_t* msg = dc_get_msg(context, msg_id); + * char* text = dc_msg_get_text(msg); + * + * printf("Message %i: %s\n", i+1, text); + * + * free(text); + * dc_msg_unref(msg); + * } + * dc_array_unref(msglist); + * ~~~ + * + * This will output the following two lines: + * + * ~~~ + * Message 1: Hi, here is my first message! + * Message 2: Got it! + * ~~~ + * + * + * ## Class reference + * + * For a class reference, see the "Classes" link atop. + * + * + * ## Further hints + * + * Here are some additional, unsorted hints that may be useful. + * + * - For `get`-functions, you have to unref the return value in some way. + * + * - Strings in function arguments or return values are usually UTF-8 encoded. + * + * - The issue-tracker for the core library is here: + * + * + * The following points are important mainly + * for the authors of the library itself: + * + * - For indentation, use tabs. + * Alignments that are not placed at the beginning of a line + * should be done with spaces. + * + * - For padding between functions, + * classes etc. use 2 empty lines + * + * - Source files are encoded as UTF-8 with Unix line endings + * (a simple `LF`, `0x0A` or `\n`) + * + * If you need further assistance, + * please do not hesitate to contact us + * through the channels shown at https://delta.chat/en/contribute + * + * Please keep in mind, that your derived work + * must respect the Mozilla Public License 2.0 of libdeltachat + * and the respective licenses of the libraries libdeltachat links with. + * + * See you. + */ +/* * + * @class dc_context_t + * + * An object representing a single account. + * + * Each account is linked to an IMAP/SMTP account and uses a separate + * SQLite database for offline functionality and for account-related + * settings. + */ +pub type dc_context_t = _dc_context; +/* ** library-private **********************************************************/ +pub type dc_smtp_t = _dc_smtp; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_smtp { + 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 error: *mut libc::c_char, + pub error_etpan: libc::c_int, +} +pub type dc_jobthread_t = _dc_jobthread; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_jobthread { + 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, + 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, +} +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_imap { + 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 type dc_receive_imf_t = Option< + unsafe extern "C" 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_imap_t = _dc_imap; +pub type dc_precheck_imf_t = Option< + unsafe extern "C" 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< + unsafe extern "C" fn(_: *mut dc_imap_t, _: *const libc::c_char, _: *const libc::c_char) -> (), +>; +pub type dc_get_config_t = Option< + unsafe extern "C" fn( + _: *mut dc_imap_t, + _: *const libc::c_char, + _: *const libc::c_char, + ) -> *mut libc::c_char, +>; +/* ** library-private **********************************************************/ +pub type dc_sqlite3_t = _dc_sqlite3; +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_sqlite3 { + pub cobj: *mut sqlite3, + pub context: *mut dc_context_t, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_strbuilder { + pub buf: *mut libc::c_char, + pub allocated: libc::c_int, + pub free: libc::c_int, + pub eos: *mut libc::c_char, +} +pub type dc_strbuilder_t = _dc_strbuilder; +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_loginparam { + pub addr: *mut libc::c_char, + pub mail_server: *mut libc::c_char, + pub mail_user: *mut libc::c_char, + pub mail_pw: *mut libc::c_char, + pub mail_port: uint16_t, + pub send_server: *mut libc::c_char, + pub send_user: *mut libc::c_char, + pub send_pw: *mut libc::c_char, + pub send_port: libc::c_int, + pub server_flags: libc::c_int, +} +pub type dc_loginparam_t = _dc_loginparam; +#[no_mangle] +pub unsafe extern "C" fn dc_loginparam_new() -> *mut dc_loginparam_t { + let mut loginparam: *mut dc_loginparam_t = 0 as *mut dc_loginparam_t; + loginparam = calloc( + 1i32 as libc::c_ulong, + ::std::mem::size_of::() as libc::c_ulong, + ) as *mut dc_loginparam_t; + if loginparam.is_null() { + exit(22i32); + } + return loginparam; +} +#[no_mangle] +pub unsafe extern "C" fn dc_loginparam_unref(mut loginparam: *mut dc_loginparam_t) { + if loginparam.is_null() { + return; + } + 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. */ +#[no_mangle] +pub unsafe extern "C" fn dc_loginparam_empty(mut loginparam: *mut dc_loginparam_t) { + if loginparam.is_null() { + return; + } + free((*loginparam).addr as *mut libc::c_void); + (*loginparam).addr = 0 as *mut libc::c_char; + free((*loginparam).mail_server as *mut libc::c_void); + (*loginparam).mail_server = 0 as *mut libc::c_char; + (*loginparam).mail_port = 0i32 as uint16_t; + free((*loginparam).mail_user as *mut libc::c_void); + (*loginparam).mail_user = 0 as *mut libc::c_char; + free((*loginparam).mail_pw as *mut libc::c_void); + (*loginparam).mail_pw = 0 as *mut libc::c_char; + free((*loginparam).send_server as *mut libc::c_void); + (*loginparam).send_server = 0 as *mut libc::c_char; + (*loginparam).send_port = 0i32; + free((*loginparam).send_user as *mut libc::c_void); + (*loginparam).send_user = 0 as *mut libc::c_char; + free((*loginparam).send_pw as *mut libc::c_void); + (*loginparam).send_pw = 0 as *mut libc::c_char; + (*loginparam).server_flags = 0i32; +} +#[no_mangle] +pub unsafe extern "C" fn dc_loginparam_read( + mut loginparam: *mut dc_loginparam_t, + mut sql: *mut dc_sqlite3_t, + mut prefix: *const libc::c_char, +) { + let mut key: *mut libc::c_char = 0 as *mut libc::c_char; + dc_loginparam_empty(loginparam); + 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"addr\x00" as *const u8 as *const libc::c_char, + ); + (*loginparam).addr = dc_sqlite3_get_config(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); + 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) as uint16_t; + 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); + 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); + 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); + 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); + 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); + 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); + 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); + sqlite3_free(key as *mut libc::c_void); +} +#[no_mangle] +pub unsafe extern "C" fn dc_loginparam_write( + mut loginparam: *const dc_loginparam_t, + mut sql: *mut dc_sqlite3_t, + mut 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); + key = sqlite3_mprintf( + b"%s%s\x00" as *const u8 as *const libc::c_char, + prefix, + b"addr\x00" as *const u8 as *const libc::c_char, + ); + dc_sqlite3_set_config(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); + 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 as int32_t); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + sqlite3_free(key as *mut libc::c_void); +} +#[no_mangle] +pub unsafe extern "C" fn dc_loginparam_get_readable( + mut loginparam: *const dc_loginparam_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 pw: *const libc::c_char = b"***\x00" as *const u8 as *const libc::c_char; + if loginparam.is_null() { + return dc_strdup(0 as *const libc::c_char); + } + let mut flags_readable: *mut libc::c_char = get_readable_flags((*loginparam).server_flags); + let mut ret: *mut libc::c_char = dc_mprintf( + b"%s %s:%s:%s:%i %s:%s:%s:%i %s\x00" as *const u8 as *const libc::c_char, + if !(*loginparam).addr.is_null() { + (*loginparam).addr + } else { + unset + }, + if !(*loginparam).mail_user.is_null() { + (*loginparam).mail_user + } else { + unset + }, + if !(*loginparam).mail_pw.is_null() { + pw + } else { + unset + }, + if !(*loginparam).mail_server.is_null() { + (*loginparam).mail_server + } else { + unset + }, + (*loginparam).mail_port as libc::c_int, + if !(*loginparam).send_user.is_null() { + (*loginparam).send_user + } else { + unset + }, + if !(*loginparam).send_pw.is_null() { + pw + } else { + unset + }, + if !(*loginparam).send_server.is_null() { + (*loginparam).send_server + } else { + unset + }, + (*loginparam).send_port, + flags_readable, + ); + free(flags_readable as *mut libc::c_void); + return ret; +} +unsafe extern "C" fn get_readable_flags(mut flags: libc::c_int) -> *mut libc::c_char { + let mut strbuilder: dc_strbuilder_t = _dc_strbuilder { + 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 bit: libc::c_int = 0i32; + while bit <= 30i32 { + if 0 != flags & 1i32 << bit { + let mut flag_added: libc::c_int = 0i32; + if 1i32 << bit == 0x2i32 { + dc_strbuilder_cat( + &mut strbuilder, + b"OAUTH2 \x00" as *const u8 as *const libc::c_char, + ); + flag_added = 1i32 + } + if 1i32 << bit == 0x4i32 { + dc_strbuilder_cat( + &mut strbuilder, + b"AUTH_NORMAL \x00" as *const u8 as *const libc::c_char, + ); + flag_added = 1i32 + } + if 1i32 << bit == 0x100i32 { + dc_strbuilder_cat( + &mut strbuilder, + b"IMAP_STARTTLS \x00" as *const u8 as *const libc::c_char, + ); + flag_added = 1i32 + } + if 1i32 << bit == 0x200i32 { + dc_strbuilder_cat( + &mut strbuilder, + b"IMAP_SSL \x00" as *const u8 as *const libc::c_char, + ); + flag_added = 1i32 + } + if 1i32 << bit == 0x400i32 { + dc_strbuilder_cat( + &mut strbuilder, + b"IMAP_PLAIN \x00" as *const u8 as *const libc::c_char, + ); + flag_added = 1i32 + } + if 1i32 << bit == 0x10000i32 { + dc_strbuilder_cat( + &mut strbuilder, + b"SMTP_STARTTLS \x00" as *const u8 as *const libc::c_char, + ); + flag_added = 1i32 + } + if 1i32 << bit == 0x20000i32 { + dc_strbuilder_cat( + &mut strbuilder, + b"SMTP_SSL \x00" as *const u8 as *const libc::c_char, + ); + flag_added = 1i32 + } + if 1i32 << bit == 0x40000i32 { + dc_strbuilder_cat( + &mut strbuilder, + b"SMTP_PLAIN \x00" as *const u8 as *const libc::c_char, + ); + flag_added = 1i32 + } + if 0 == flag_added { + let mut temp: *mut libc::c_char = dc_mprintf( + b"0x%x \x00" as *const u8 as *const libc::c_char, + 1i32 << bit, + ); + dc_strbuilder_cat(&mut strbuilder, temp); + free(temp as *mut libc::c_void); + } + } + bit += 1 + } + if *strbuilder.buf.offset(0isize) as libc::c_int == 0i32 { + dc_strbuilder_cat( + &mut strbuilder, + b"0\x00" as *const u8 as *const libc::c_char, + ); + } + dc_trim(strbuilder.buf); + return strbuilder.buf; +} diff --git a/src/dc_lot.rs b/src/dc_lot.rs new file mode 100644 index 000000000..5a7af339c --- /dev/null +++ b/src/dc_lot.rs @@ -0,0 +1,986 @@ +use c2rust_bitfields::BitfieldStruct; +use libc; +extern "C" { + pub type mailstream_cancel; + pub type sqlite3; + #[no_mangle] + fn calloc(_: libc::c_ulong, _: libc::c_ulong) -> *mut libc::c_void; + #[no_mangle] + fn free(_: *mut libc::c_void); + #[no_mangle] + fn exit(_: libc::c_int) -> !; + #[no_mangle] + fn dc_chat_is_self_talk(_: *const dc_chat_t) -> libc::c_int; + #[no_mangle] + fn dc_msg_get_timestamp(_: *const dc_msg_t) -> time_t; + #[no_mangle] + fn dc_msg_is_info(_: *const dc_msg_t) -> libc::c_int; + #[no_mangle] + fn dc_contact_get_display_name(_: *const dc_contact_t) -> *mut libc::c_char; + #[no_mangle] + fn dc_contact_get_first_name(_: *const dc_contact_t) -> *mut libc::c_char; + #[no_mangle] + fn dc_strdup_keep_null(_: *const libc::c_char) -> *mut libc::c_char; + /* Return the string with the given ID by calling DC_EVENT_GET_STRING. + The result must be free()'d! */ + #[no_mangle] + fn dc_stock_str(_: *mut dc_context_t, id: libc::c_int) -> *mut libc::c_char; + #[no_mangle] + fn dc_msg_get_summarytext_by_raw( + type_0: libc::c_int, + text: *const libc::c_char, + _: *mut dc_param_t, + approx_bytes: libc::c_int, + _: *mut dc_context_t, + ) -> *mut libc::c_char; +} +pub type __darwin_size_t = libc::c_ulong; +pub type __darwin_ssize_t = libc::c_long; +pub type __darwin_time_t = libc::c_long; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_cond_t { + pub __sig: libc::c_long, + pub __opaque: [libc::c_char; 40], +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_mutex_t { + pub __sig: libc::c_long, + pub __opaque: [libc::c_char; 56], +} +pub type __darwin_pthread_cond_t = _opaque_pthread_cond_t; +pub type __darwin_pthread_mutex_t = _opaque_pthread_mutex_t; +pub type uintptr_t = libc::c_ulong; +pub type size_t = __darwin_size_t; +pub type uint8_t = libc::c_uchar; +pub type uint32_t = libc::c_uint; +pub type ssize_t = __darwin_ssize_t; +pub type time_t = __darwin_time_t; +pub type pthread_cond_t = __darwin_pthread_cond_t; +pub type pthread_mutex_t = __darwin_pthread_mutex_t; +#[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; +#[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) -> (); +#[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; +#[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, + 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 { + 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_capability_data { + pub cap_list: *mut clist, +} +#[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_0, + 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_0 { + 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 extern "C" 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_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, +} +#[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_1, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed_1 { + pub ft_fetch_att: *mut mailimap_fetch_att, + pub ft_fetch_att_list: *mut clist, +} +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 unnamed_2 { + 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, +} +/* define DC_USE_RPGP to enable use of rPGP instead of netpgp where available; +preferrably, this should be done in the project configuration currently */ +//#define DC_USE_RPGP 1 +/* Includes that are used frequently. This file may also be used to create predefined headers. */ +/* * Structure behind dc_context_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_context { + pub magic: uint32_t, + pub userdata: *mut libc::c_void, + pub dbfile: *mut libc::c_char, + pub blobdir: *mut libc::c_char, + pub sql: *mut dc_sqlite3_t, + pub inbox: *mut dc_imap_t, + pub inboxidle_condmutex: pthread_mutex_t, + pub perform_inbox_jobs_needed: libc::c_int, + pub probe_imap_network: libc::c_int, + pub sentbox_thread: dc_jobthread_t, + pub mvbox_thread: dc_jobthread_t, + pub smtp: *mut dc_smtp_t, + pub smtpidle_cond: pthread_cond_t, + pub smtpidle_condmutex: pthread_mutex_t, + pub smtpidle_condflag: libc::c_int, + pub smtp_suspended: libc::c_int, + pub smtp_doing_jobs: libc::c_int, + pub perform_smtp_jobs_needed: libc::c_int, + pub probe_smtp_network: libc::c_int, + pub oauth2_critical: pthread_mutex_t, + 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 type dc_lot_t = _dc_lot; +/* * Structure behind dc_lot_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_lot { + pub magic: uint32_t, + pub text1_meaning: libc::c_int, + pub text1: *mut libc::c_char, + pub text2: *mut libc::c_char, + pub timestamp: time_t, + pub state: libc::c_int, + pub id: uint32_t, + pub fingerprint: *mut libc::c_char, + pub invitenumber: *mut libc::c_char, + pub auth: *mut libc::c_char, +} +/* * + * 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 = Option< + unsafe extern "C" fn( + _: *mut dc_context_t, + _: libc::c_int, + _: uintptr_t, + _: uintptr_t, + ) -> uintptr_t, +>; +/* * + * @mainpage Getting started + * + * This document describes how to handle the Delta Chat core library. + * For general information about Delta Chat itself, + * see and . + * + * Let's start. + * + * First of all, you have to **define an event-handler-function** + * that is called by the library on specific events + * (eg. when the configuration is done or when fresh messages arrive). + * With this function you can create a Delta Chat context then: + * + * ~~~ + * #include + * + * uintptr_t event_handler_func(dc_context_t* context, int event, + * uintptr_t data1, uintptr_t data2) + * { + * return 0; // for unhandled events, it is always safe to return 0 + * } + * + * dc_context_t* context = dc_context_new(event_handler_func, NULL, NULL); + * ~~~ + * + * After that, you should make sure, + * sending and receiving jobs are processed as needed. + * For this purpose, you have to **create two threads:** + * + * ~~~ + * #include + * + * void* imap_thread_func(void* context) + * { + * while (true) { + * dc_perform_imap_jobs(context); + * dc_perform_imap_fetch(context); + * dc_perform_imap_idle(context); + * } + * } + * + * void* smtp_thread_func(void* context) + * { + * while (true) { + * dc_perform_smtp_jobs(context); + * dc_perform_smtp_idle(context); + * } + * } + * + * static pthread_t imap_thread, smtp_thread; + * pthread_create(&imap_thread, NULL, imap_thread_func, context); + * pthread_create(&smtp_thread, NULL, smtp_thread_func, context); + * ~~~ + * + * The example above uses "pthreads", + * however, you can also use anything else for thread handling. + * NB: The deltachat-core library itself does not create any threads on its own, + * however, functions, unless stated otherwise, are thread-safe. + * + * After that you can **define and open a database.** + * The database is a normal sqlite-file and is created as needed: + * + * ~~~ + * dc_open(context, "example.db", NULL); + * ~~~ + * + * Now you can **configure the context:** + * + * ~~~ + * // use some real test credentials here + * dc_set_config(context, "addr", "alice@example.org"); + * dc_set_config(context, "mail_pw", "***"); + * dc_configure(context); + * ~~~ + * + * dc_configure() returns immediately, the configuration itself may take a while + * and is done by a job in the imap-thread you've defined above. + * Once done, the #DC_EVENT_CONFIGURE_PROGRESS reports success + * to the event_handler_func() that is also defined above. + * + * The configuration result is saved in the database, + * on subsequent starts it is not needed to call dc_configure() + * (you can check this using dc_is_configured()). + * + * Now you can **send the first message:** + * + * ~~~ + * // use a real testing address here + * uint32_t contact_id = dc_create_contact(context, NULL, "bob@example.org"); + * uint32_t chat_id = dc_create_chat_by_contact_id(context, contact_id); + * + * dc_send_text_msg(context, chat_id, "Hi, here is my first message!"); + * ~~~ + * + * dc_send_text_msg() returns immediately; + * the sending itself is done by a job in the smtp-thread you've defined above. + * If you check the testing address (bob) + * and you should have received a normal email. + * Answer this email in any email program with "Got it!" + * and the imap-thread you've create above will **receive the message**. + * + * You can then **list all messages** of a chat as follow: + * + * ~~~ + * dc_array_t* msglist = dc_get_chat_msgs(context, chat_id, 0, 0); + * for (int i = 0; i < dc_array_get_cnt(msglist); i++) + * { + * uint32_t msg_id = dc_array_get_id(msglist, i); + * dc_msg_t* msg = dc_get_msg(context, msg_id); + * char* text = dc_msg_get_text(msg); + * + * printf("Message %i: %s\n", i+1, text); + * + * free(text); + * dc_msg_unref(msg); + * } + * dc_array_unref(msglist); + * ~~~ + * + * This will output the following two lines: + * + * ~~~ + * Message 1: Hi, here is my first message! + * Message 2: Got it! + * ~~~ + * + * + * ## Class reference + * + * For a class reference, see the "Classes" link atop. + * + * + * ## Further hints + * + * Here are some additional, unsorted hints that may be useful. + * + * - For `get`-functions, you have to unref the return value in some way. + * + * - Strings in function arguments or return values are usually UTF-8 encoded. + * + * - The issue-tracker for the core library is here: + * + * + * The following points are important mainly + * for the authors of the library itself: + * + * - For indentation, use tabs. + * Alignments that are not placed at the beginning of a line + * should be done with spaces. + * + * - For padding between functions, + * classes etc. use 2 empty lines + * + * - Source files are encoded as UTF-8 with Unix line endings + * (a simple `LF`, `0x0A` or `\n`) + * + * If you need further assistance, + * please do not hesitate to contact us + * through the channels shown at https://delta.chat/en/contribute + * + * Please keep in mind, that your derived work + * must respect the Mozilla Public License 2.0 of libdeltachat + * and the respective licenses of the libraries libdeltachat links with. + * + * See you. + */ +/* * + * @class dc_context_t + * + * An object representing a single account. + * + * Each account is linked to an IMAP/SMTP account and uses a separate + * SQLite database for offline functionality and for account-related + * settings. + */ +pub type dc_context_t = _dc_context; +/* ** library-private **********************************************************/ +pub type dc_smtp_t = _dc_smtp; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_smtp { + 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 error: *mut libc::c_char, + pub error_etpan: libc::c_int, +} +pub type dc_jobthread_t = _dc_jobthread; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_jobthread { + 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, + 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, +} +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_imap { + 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 type dc_receive_imf_t = Option< + unsafe extern "C" 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_imap_t = _dc_imap; +pub type dc_precheck_imf_t = Option< + unsafe extern "C" 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< + unsafe extern "C" fn(_: *mut dc_imap_t, _: *const libc::c_char, _: *const libc::c_char) -> (), +>; +pub type dc_get_config_t = Option< + unsafe extern "C" fn( + _: *mut dc_imap_t, + _: *const libc::c_char, + _: *const libc::c_char, + ) -> *mut libc::c_char, +>; +/* ** library-private **********************************************************/ +pub type dc_sqlite3_t = _dc_sqlite3; +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_sqlite3 { + pub cobj: *mut sqlite3, + pub context: *mut dc_context_t, +} +/* values for the chats.blocked database field */ +/* * the structure behind dc_chat_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_chat { + 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 grpid: *mut libc::c_char, + pub blocked: libc::c_int, + pub param: *mut dc_param_t, + pub gossiped_timestamp: time_t, + pub is_sending_locations: libc::c_int, +} +pub type dc_param_t = _dc_param; +/* * + * @class dc_param_t + * + * An object for handling key=value parameter lists; for the key, curently only + * a single character is allowed. + * + * The object is used eg. by dc_chat_t or dc_msg_t, for readable paramter names, + * these classes define some DC_PARAM_* constantats. + * + * Only for library-internal use. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_param { + pub packed: *mut libc::c_char, +} +pub type dc_chat_t = _dc_chat; +/* * the structure behind dc_msg_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_msg { + pub magic: uint32_t, + pub id: uint32_t, + pub from_id: uint32_t, + pub to_id: uint32_t, + pub chat_id: uint32_t, + pub move_state: dc_move_state_t, + pub type_0: libc::c_int, + pub state: libc::c_int, + pub hidden: libc::c_int, + pub timestamp_sort: time_t, + pub timestamp_sent: time_t, + pub timestamp_rcvd: time_t, + pub text: *mut libc::c_char, + pub context: *mut 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, + pub server_uid: uint32_t, + pub is_dc_message: libc::c_int, + pub starred: libc::c_int, + pub chat_blocked: libc::c_int, + pub location_id: uint32_t, + pub param: *mut dc_param_t, +} +pub type dc_move_state_t = libc::c_uint; +pub const DC_MOVE_STATE_MOVING: dc_move_state_t = 3; +pub const DC_MOVE_STATE_STAY: dc_move_state_t = 2; +pub const DC_MOVE_STATE_PENDING: dc_move_state_t = 1; +pub const DC_MOVE_STATE_UNDEFINED: dc_move_state_t = 0; +pub type dc_msg_t = _dc_msg; +/* * the structure behind dc_contact_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_contact { + pub magic: uint32_t, + pub context: *mut dc_context_t, + pub id: uint32_t, + pub name: *mut libc::c_char, + pub authname: *mut libc::c_char, + pub addr: *mut libc::c_char, + pub blocked: libc::c_int, + pub origin: libc::c_int, +} +pub type dc_contact_t = _dc_contact; +/* * + * @class dc_lot_t + * + * An object containing a set of values. + * The meaning of the values is defined by the function returning the object. + * Lot objects are created + * eg. by dc_chatlist_get_summary() or dc_msg_get_summary(). + * + * NB: _Lot_ is used in the meaning _heap_ here. + */ +#[no_mangle] +pub unsafe extern "C" fn dc_lot_new() -> *mut dc_lot_t { + let mut lot: *mut dc_lot_t = 0 as *mut dc_lot_t; + lot = calloc( + 1i32 as libc::c_ulong, + ::std::mem::size_of::() as libc::c_ulong, + ) as *mut dc_lot_t; + if lot.is_null() { + exit(27i32); + } + (*lot).magic = 0x107107i32 as uint32_t; + (*lot).text1_meaning = 0i32; + return lot; +} +#[no_mangle] +pub unsafe extern "C" fn dc_lot_empty(mut lot: *mut dc_lot_t) { + if lot.is_null() || (*lot).magic != 0x107107i32 as libc::c_uint { + return; + } + free((*lot).text1 as *mut libc::c_void); + (*lot).text1 = 0 as *mut libc::c_char; + (*lot).text1_meaning = 0i32; + free((*lot).text2 as *mut libc::c_void); + (*lot).text2 = 0 as *mut libc::c_char; + free((*lot).fingerprint as *mut libc::c_void); + (*lot).fingerprint = 0 as *mut libc::c_char; + free((*lot).invitenumber as *mut libc::c_void); + (*lot).invitenumber = 0 as *mut libc::c_char; + free((*lot).auth as *mut libc::c_void); + (*lot).auth = 0 as *mut libc::c_char; + (*lot).timestamp = 0i32 as time_t; + (*lot).state = 0i32; + (*lot).id = 0i32 as uint32_t; +} +#[no_mangle] +pub unsafe extern "C" fn dc_lot_unref(mut set: *mut dc_lot_t) { + if set.is_null() || (*set).magic != 0x107107i32 as libc::c_uint { + return; + } + dc_lot_empty(set); + (*set).magic = 0i32 as uint32_t; + free(set as *mut libc::c_void); +} +#[no_mangle] +pub unsafe extern "C" 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); +} +#[no_mangle] +pub unsafe extern "C" 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); +} +#[no_mangle] +pub unsafe extern "C" 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; +} +#[no_mangle] +pub unsafe extern "C" 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; +} +#[no_mangle] +pub unsafe extern "C" 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; +} +#[no_mangle] +pub unsafe extern "C" 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; +} +/* library-internal */ +/* in practice, the user additionally cuts the string himself pixel-accurate */ +#[no_mangle] +pub unsafe extern "C" fn dc_lot_fill( + mut lot: *mut dc_lot_t, + mut msg: *const dc_msg_t, + mut chat: *const dc_chat_t, + mut contact: *const dc_contact_t, + mut context: *mut dc_context_t, +) { + if lot.is_null() || (*lot).magic != 0x107107i32 as libc::c_uint || msg.is_null() { + return; + } + if (*msg).state == 19i32 { + (*lot).text1 = dc_stock_str(context, 3i32); + (*lot).text1_meaning = 1i32 + } else if (*msg).from_id == 1i32 as libc::c_uint { + if 0 != dc_msg_is_info(msg) || 0 != dc_chat_is_self_talk(chat) { + (*lot).text1 = 0 as *mut libc::c_char; + (*lot).text1_meaning = 0i32 + } else { + (*lot).text1 = dc_stock_str(context, 2i32); + (*lot).text1_meaning = 3i32 + } + } else if chat.is_null() { + (*lot).text1 = 0 as *mut libc::c_char; + (*lot).text1_meaning = 0i32 + } else if (*chat).type_0 == 120i32 || (*chat).type_0 == 130i32 { + if 0 != dc_msg_is_info(msg) || contact.is_null() { + (*lot).text1 = 0 as *mut libc::c_char; + (*lot).text1_meaning = 0i32 + } else { + if !chat.is_null() && (*chat).id == 1i32 as libc::c_uint { + (*lot).text1 = dc_contact_get_display_name(contact) + } else { + (*lot).text1 = dc_contact_get_first_name(contact) + } + (*lot).text1_meaning = 2i32 + } + } + (*lot).text2 = + dc_msg_get_summarytext_by_raw((*msg).type_0, (*msg).text, (*msg).param, 160i32, context); + (*lot).timestamp = dc_msg_get_timestamp(msg); + (*lot).state = (*msg).state; +} diff --git a/src/dc_mimefactory.rs b/src/dc_mimefactory.rs new file mode 100644 index 000000000..862c39a86 --- /dev/null +++ b/src/dc_mimefactory.rs @@ -0,0 +1,2920 @@ +use c2rust_bitfields::BitfieldStruct; +use libc; +extern "C" { + pub type mailstream_cancel; + pub type sqlite3; + pub type sqlite3_stmt; + #[no_mangle] + fn free(_: *mut libc::c_void); + #[no_mangle] + fn memcpy(_: *mut libc::c_void, _: *const libc::c_void, _: libc::c_ulong) -> *mut libc::c_void; + #[no_mangle] + fn memset(_: *mut libc::c_void, _: libc::c_int, _: libc::c_ulong) -> *mut libc::c_void; + #[no_mangle] + fn strcmp(_: *const libc::c_char, _: *const libc::c_char) -> libc::c_int; + #[no_mangle] + fn strlen(_: *const libc::c_char) -> libc::c_ulong; + #[no_mangle] + fn strdup(_: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn strcasecmp(_: *const libc::c_char, _: *const libc::c_char) -> libc::c_int; + #[no_mangle] + fn localtime(_: *const time_t) -> *mut tm; + #[no_mangle] + fn time(_: *mut time_t) -> time_t; + #[no_mangle] + fn mmap_string_new(init: *const libc::c_char) -> *mut MMAPString; + #[no_mangle] + fn mmap_string_free(string: *mut MMAPString); + #[no_mangle] + fn clist_new() -> *mut clist; + #[no_mangle] + fn clist_free(_: *mut clist); + #[no_mangle] + fn clist_insert_after(_: *mut clist, _: *mut clistiter, _: *mut libc::c_void) -> libc::c_int; + #[no_mangle] + fn mailimf_address_new( + ad_type: libc::c_int, + ad_mailbox: *mut mailimf_mailbox, + ad_group: *mut mailimf_group, + ) -> *mut mailimf_address; + #[no_mangle] + fn mailimf_mailbox_new( + mb_display_name: *mut libc::c_char, + mb_addr_spec: *mut libc::c_char, + ) -> *mut mailimf_mailbox; + #[no_mangle] + 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; + #[no_mangle] + fn mailimf_subject_new(sbj_value: *mut libc::c_char) -> *mut mailimf_subject; + #[no_mangle] + fn mailimf_mailbox_list_new_empty() -> *mut mailimf_mailbox_list; + #[no_mangle] + fn mailimf_mailbox_list_add( + mailbox_list: *mut mailimf_mailbox_list, + mb: *mut mailimf_mailbox, + ) -> libc::c_int; + #[no_mangle] + fn mailimf_address_list_new_empty() -> *mut mailimf_address_list; + #[no_mangle] + fn mailimf_address_list_add( + address_list: *mut mailimf_address_list, + addr: *mut mailimf_address, + ) -> libc::c_int; + #[no_mangle] + fn mailimf_fields_add(fields: *mut mailimf_fields, field: *mut mailimf_field) -> libc::c_int; + #[no_mangle] + 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; + #[no_mangle] + fn mailimf_get_date(time_0: time_t) -> *mut mailimf_date_time; + #[no_mangle] + fn mailimf_field_new_custom( + name: *mut libc::c_char, + value: *mut libc::c_char, + ) -> *mut mailimf_field; + #[no_mangle] + fn mailmime_parameter_new( + pa_name: *mut libc::c_char, + pa_value: *mut libc::c_char, + ) -> *mut mailmime_parameter; + #[no_mangle] + fn mailmime_free(mime: *mut mailmime); + #[no_mangle] + 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; + #[no_mangle] + fn mailmime_new_message_data(msg_mime: *mut mailmime) -> *mut mailmime; + #[no_mangle] + fn mailmime_new_empty( + content: *mut mailmime_content, + mime_fields: *mut mailmime_fields, + ) -> *mut mailmime; + #[no_mangle] + fn mailmime_set_body_file( + build_info: *mut mailmime, + filename: *mut libc::c_char, + ) -> libc::c_int; + #[no_mangle] + fn mailmime_set_body_text( + build_info: *mut mailmime, + data_str: *mut libc::c_char, + length: size_t, + ) -> libc::c_int; + #[no_mangle] + fn mailmime_add_part(build_info: *mut mailmime, part: *mut mailmime) -> libc::c_int; + #[no_mangle] + fn mailmime_set_imf_fields(build_info: *mut mailmime, fields: *mut mailimf_fields); + #[no_mangle] + fn mailmime_smart_add_part(mime: *mut mailmime, mime_sub: *mut mailmime) -> libc::c_int; + #[no_mangle] + fn mailmime_content_new_with_str(str: *const libc::c_char) -> *mut mailmime_content; + #[no_mangle] + fn mailmime_fields_new_encoding(type_0: libc::c_int) -> *mut mailmime_fields; + #[no_mangle] + fn mailmime_multiple_new(type_0: *const libc::c_char) -> *mut mailmime; + #[no_mangle] + fn mailmime_fields_new_filename( + dsp_type: libc::c_int, + filename: *mut libc::c_char, + encoding_type: libc::c_int, + ) -> *mut mailmime_fields; + #[no_mangle] + fn mailmime_param_new_with_data( + name: *mut libc::c_char, + value: *mut libc::c_char, + ) -> *mut mailmime_parameter; + #[no_mangle] + fn mailmime_write_mem( + f: *mut MMAPString, + col: *mut libc::c_int, + build_info: *mut mailmime, + ) -> libc::c_int; + #[no_mangle] + fn dc_is_sending_locations_to_chat(_: *mut dc_context_t, chat_id: uint32_t) -> libc::c_int; + /* * + * @class dc_chat_t + * + * An object representing a single chat in memory. + * Chat objects are created using eg. dc_get_chat() + * and are not updated on database changes; + * if you want an update, you have to recreate the object. + */ + // virtual chat showing all messages belonging to chats flagged with chats.blocked=2 + // messages that should be deleted get this chat_id; the messages are deleted from the working thread later then. This is also needed as rfc724_mid should be preset as long as the message is not deleted on the server (otherwise it is downloaded again) + // a message is just in creation but not yet assigned to a chat (eg. we may need the message ID to set up blobs; this avoids unready message to be sent and shown) + // virtual chat showing all messages flagged with msgs.starred=2 + // only an indicator in a chatlist + // only an indicator in a chatlist + // larger chat IDs are "real" chats, their messages are "real" messages. + #[no_mangle] + fn dc_chat_new(_: *mut dc_context_t) -> *mut dc_chat_t; + #[no_mangle] + fn dc_chat_unref(_: *mut dc_chat_t); + #[no_mangle] + fn dc_chat_is_self_talk(_: *const dc_chat_t) -> libc::c_int; + #[no_mangle] + fn dc_msg_unref(_: *mut dc_msg_t); + #[no_mangle] + fn dc_msg_get_summarytext( + _: *const dc_msg_t, + approx_characters: libc::c_int, + ) -> *mut libc::c_char; + #[no_mangle] + fn dc_msg_is_increation(_: *const dc_msg_t) -> libc::c_int; + /* * + * @class dc_contact_t + * + * An object representing a single contact in memory. + * The contact object is not updated. + * If you want an update, you have to recreate the object. + * + * The library makes sure + * only to use names _authorized_ by the contact in `To:` or `Cc:`. + * _Given-names _as "Daddy" or "Honey" are not used there. + * For this purpose, internally, two names are tracked - + * authorized-name and given-name. + * By default, these names are equal, + * but functions working with contact names + * (eg. dc_contact_get_name(), dc_contact_get_display_name(), + * dc_contact_get_name_n_addr(), dc_contact_get_first_name(), + * dc_create_contact() or dc_add_address_book()) + * only affect the given-name. + */ + #[no_mangle] + fn dc_contact_new(_: *mut dc_context_t) -> *mut dc_contact_t; + #[no_mangle] + fn dc_contact_unref(_: *mut dc_contact_t); + #[no_mangle] + fn sqlite3_bind_int(_: *mut sqlite3_stmt, _: libc::c_int, _: libc::c_int) -> libc::c_int; + #[no_mangle] + fn sqlite3_step(_: *mut sqlite3_stmt) -> libc::c_int; + #[no_mangle] + fn sqlite3_column_text(_: *mut sqlite3_stmt, iCol: libc::c_int) -> *const libc::c_uchar; + #[no_mangle] + fn sqlite3_finalize(pStmt: *mut sqlite3_stmt) -> libc::c_int; + #[no_mangle] + fn dc_sqlite3_get_config( + _: *mut dc_sqlite3_t, + key: *const libc::c_char, + def: *const libc::c_char, + ) -> *mut libc::c_char; + #[no_mangle] + fn dc_sqlite3_get_config_int( + _: *mut dc_sqlite3_t, + key: *const libc::c_char, + def: int32_t, + ) -> int32_t; + /* tools, these functions are compatible to the corresponding sqlite3_* functions */ + #[no_mangle] + fn dc_sqlite3_prepare(_: *mut dc_sqlite3_t, sql: *const libc::c_char) -> *mut sqlite3_stmt; + /* string tools */ + #[no_mangle] + fn dc_strdup(_: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn dc_strdup_keep_null(_: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn dc_mprintf(format: *const libc::c_char, _: ...) -> *mut libc::c_char; + #[no_mangle] + fn dc_str_to_clist(_: *const libc::c_char, delimiter: *const libc::c_char) -> *mut clist; + /* clist tools */ + #[no_mangle] + fn clist_free_content(_: *const clist); + #[no_mangle] + fn clist_search_string_nocase(_: *const clist, str: *const libc::c_char) -> libc::c_int; + #[no_mangle] + fn dc_create_smeared_timestamp(_: *mut dc_context_t) -> time_t; + #[no_mangle] + fn dc_create_outgoing_rfc724_mid( + grpid: *const libc::c_char, + addr: *const libc::c_char, + ) -> *mut libc::c_char; + #[no_mangle] + fn dc_get_filename(pathNfilename: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn dc_get_filesuffix_lc(pathNfilename: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn dc_get_abs_path( + _: *mut dc_context_t, + pathNfilename: *const libc::c_char, + ) -> *mut libc::c_char; + #[no_mangle] + fn dc_get_filebytes(_: *mut dc_context_t, pathNfilename: *const libc::c_char) -> uint64_t; + #[no_mangle] + fn dc_encode_header_words(_: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn dc_needs_ext_header(_: *const libc::c_char) -> libc::c_int; + #[no_mangle] + fn dc_encode_ext_header(_: *const libc::c_char) -> *mut libc::c_char; + /* for msgs and jobs */ + /* for msgs */ + /* for msgs */ + /* for msgs */ + /* for msgs */ + /* for msgs: incoming: message is encryoted, outgoing: guarantee E2EE or the message is not send */ + /* for msgs: decrypted with validation errors or without mutual set, if neither 'c' nor 'e' are preset, the messages is only transport encrypted */ + /* for msgs: force unencrypted message, either DC_FP_ADD_AUTOCRYPT_HEADER (1), DC_FP_NO_AUTOCRYPT_HEADER (2) or 0 */ + /* for msgs: an incoming message which requestes a MDN (aka read receipt) */ + /* for msgs */ + /* for msgs */ + /* for msgs */ + /* for msgs */ + /* for msgs */ + /* for msgs */ + /* for msgs */ + /* for msgs in PREPARING: space-separated list of message IDs of forwarded copies */ + /* for jobs */ + /* for jobs */ + /* for jobs */ + /* for jobs: space-separated list of message recipients */ + /* for groups */ + /* for groups and contacts */ + /* for chats */ + // values for DC_PARAM_FORCE_PLAINTEXT + /* user functions */ + #[no_mangle] + fn dc_param_exists(_: *mut dc_param_t, key: libc::c_int) -> libc::c_int; + #[no_mangle] + fn dc_param_get( + _: *const dc_param_t, + key: libc::c_int, + def: *const libc::c_char, + ) -> *mut libc::c_char; + #[no_mangle] + fn dc_param_get_int(_: *const dc_param_t, key: libc::c_int, def: int32_t) -> int32_t; + #[no_mangle] + fn dc_param_set(_: *mut dc_param_t, key: libc::c_int, value: *const libc::c_char); + /* Return the string with the given ID by calling DC_EVENT_GET_STRING. + The result must be free()'d! */ + #[no_mangle] + fn dc_stock_str(_: *mut dc_context_t, id: libc::c_int) -> *mut libc::c_char; + /* Replaces the first `%1$s` in the given String-ID by the given value. + The result must be free()'d! */ + #[no_mangle] + fn dc_stock_str_repl_string( + _: *mut dc_context_t, + id: libc::c_int, + value: *const libc::c_char, + ) -> *mut libc::c_char; + #[no_mangle] + fn dc_chat_load_from_db(_: *mut dc_chat_t, id: uint32_t) -> libc::c_int; + #[no_mangle] + fn dc_msg_new_untyped(_: *mut dc_context_t) -> *mut dc_msg_t; + #[no_mangle] + fn dc_msg_load_from_db(_: *mut dc_msg_t, _: *mut dc_context_t, id: uint32_t) -> libc::c_int; + #[no_mangle] + fn dc_msg_get_summarytext_by_raw( + type_0: libc::c_int, + text: *const libc::c_char, + _: *mut dc_param_t, + approx_bytes: libc::c_int, + _: *mut dc_context_t, + ) -> *mut libc::c_char; + /* From: of incoming messages of unknown sender */ + /* Cc: of incoming messages of unknown sender */ + /* To: of incoming messages of unknown sender */ + /* address scanned but not verified */ + /* Reply-To: of incoming message of known sender */ + /* Cc: of incoming message of known sender */ + /* additional To:'s of incoming message of known sender */ + /* a chat was manually created for this user, but no message yet sent */ + /* message sent by us */ + /* message sent by us */ + /* message sent by us */ + /* internal use */ + /* address is in our address book */ + /* set on Alice's side for contacts like Bob that have scanned the QR code offered by her. Only means the contact has once been established using the "securejoin" procedure in the past, getting the current key verification status requires calling dc_contact_is_verified() ! */ + /* set on Bob's side for contacts scanned and verified from a QR code. Only means the contact has once been established using the "securejoin" procedure in the past, getting the current key verification status requires calling dc_contact_is_verified() ! */ + /* contact added mannually by dc_create_contact(), this should be the largets origin as otherwise the user cannot modify the names */ + /* 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 */ + #[no_mangle] + fn dc_contact_load_from_db( + _: *mut dc_contact_t, + _: *mut dc_sqlite3_t, + contact_id: uint32_t, + ) -> libc::c_int; + #[no_mangle] + fn dc_log_info(_: *mut dc_context_t, data1: libc::c_int, msg: *const libc::c_char, _: ...); + #[no_mangle] + fn dc_get_location_kml( + _: *mut dc_context_t, + chat_id: uint32_t, + last_added_location_id: *mut uint32_t, + ) -> *mut libc::c_char; + #[no_mangle] + fn dc_e2ee_encrypt( + _: *mut dc_context_t, + recipients_addr: *const clist, + force_plaintext: libc::c_int, + e2ee_guaranteed: libc::c_int, + min_verified: libc::c_int, + do_gossip: libc::c_int, + in_out_message: *mut mailmime, + _: *mut dc_e2ee_helper_t, + ); + #[no_mangle] + fn dc_e2ee_thanks(_: *mut dc_e2ee_helper_t); +} +pub type __darwin_size_t = libc::c_ulong; +pub type __darwin_ssize_t = libc::c_long; +pub type __darwin_time_t = libc::c_long; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_cond_t { + pub __sig: libc::c_long, + pub __opaque: [libc::c_char; 40], +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_mutex_t { + pub __sig: libc::c_long, + pub __opaque: [libc::c_char; 56], +} +pub type __darwin_pthread_cond_t = _opaque_pthread_cond_t; +pub type __darwin_pthread_mutex_t = _opaque_pthread_mutex_t; +pub type int32_t = libc::c_int; +pub type uintptr_t = libc::c_ulong; +pub type size_t = __darwin_size_t; +pub type uint8_t = libc::c_uchar; +pub type uint32_t = libc::c_uint; +pub type uint64_t = libc::c_ulonglong; +pub type ssize_t = __darwin_ssize_t; +pub type time_t = __darwin_time_t; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct tm { + pub tm_sec: libc::c_int, + pub tm_min: libc::c_int, + pub tm_hour: libc::c_int, + pub tm_mday: libc::c_int, + pub tm_mon: libc::c_int, + pub tm_year: libc::c_int, + pub tm_wday: libc::c_int, + pub tm_yday: libc::c_int, + pub tm_isdst: libc::c_int, + pub tm_gmtoff: libc::c_long, + pub tm_zone: *mut libc::c_char, +} +pub type pthread_cond_t = __darwin_pthread_cond_t; +pub type pthread_mutex_t = __darwin_pthread_mutex_t; +#[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; +#[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) -> (); +#[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 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 unnamed = libc::c_uint; +pub const MAILIMF_ADDRESS_GROUP: unnamed = 2; +pub const MAILIMF_ADDRESS_MAILBOX: unnamed = 1; +pub const MAILIMF_ADDRESS_ERROR: unnamed = 0; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct mailimf_address { + pub ad_type: libc::c_int, + pub ad_data: unnamed_0, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed_0 { + pub ad_mailbox: *mut mailimf_mailbox, + pub ad_group: *mut mailimf_group, +} +#[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, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct mailimf_mailbox_list { + pub mb_list: *mut clist, +} +#[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_fields { + pub fld_list: *mut clist, +} +pub type unnamed_1 = libc::c_uint; +pub const MAILIMF_FIELD_OPTIONAL_FIELD: unnamed_1 = 22; +pub const MAILIMF_FIELD_KEYWORDS: unnamed_1 = 21; +pub const MAILIMF_FIELD_COMMENTS: unnamed_1 = 20; +pub const MAILIMF_FIELD_SUBJECT: unnamed_1 = 19; +pub const MAILIMF_FIELD_REFERENCES: unnamed_1 = 18; +pub const MAILIMF_FIELD_IN_REPLY_TO: unnamed_1 = 17; +pub const MAILIMF_FIELD_MESSAGE_ID: unnamed_1 = 16; +pub const MAILIMF_FIELD_BCC: unnamed_1 = 15; +pub const MAILIMF_FIELD_CC: unnamed_1 = 14; +pub const MAILIMF_FIELD_TO: unnamed_1 = 13; +pub const MAILIMF_FIELD_REPLY_TO: unnamed_1 = 12; +pub const MAILIMF_FIELD_SENDER: unnamed_1 = 11; +pub const MAILIMF_FIELD_FROM: unnamed_1 = 10; +pub const MAILIMF_FIELD_ORIG_DATE: unnamed_1 = 9; +pub const MAILIMF_FIELD_RESENT_MSG_ID: unnamed_1 = 8; +pub const MAILIMF_FIELD_RESENT_BCC: unnamed_1 = 7; +pub const MAILIMF_FIELD_RESENT_CC: unnamed_1 = 6; +pub const MAILIMF_FIELD_RESENT_TO: unnamed_1 = 5; +pub const MAILIMF_FIELD_RESENT_SENDER: unnamed_1 = 4; +pub const MAILIMF_FIELD_RESENT_FROM: unnamed_1 = 3; +pub const MAILIMF_FIELD_RESENT_DATE: unnamed_1 = 2; +pub const MAILIMF_FIELD_RETURN_PATH: unnamed_1 = 1; +pub const MAILIMF_FIELD_NONE: unnamed_1 = 0; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct mailimf_field { + pub fld_type: libc::c_int, + pub fld_data: unnamed_2, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed_2 { + 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, +} +#[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 mailmime_composite_type { + pub ct_type: libc::c_int, + pub ct_token: *mut libc::c_char, +} +#[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_type { + pub tp_type: libc::c_int, + pub tp_data: unnamed_3, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed_3 { + 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 type unnamed_4 = libc::c_uint; +pub const MAILMIME_FIELD_LOCATION: unnamed_4 = 8; +pub const MAILMIME_FIELD_LANGUAGE: unnamed_4 = 7; +pub const MAILMIME_FIELD_DISPOSITION: unnamed_4 = 6; +pub const MAILMIME_FIELD_VERSION: unnamed_4 = 5; +pub const MAILMIME_FIELD_DESCRIPTION: unnamed_4 = 4; +pub const MAILMIME_FIELD_ID: unnamed_4 = 3; +pub const MAILMIME_FIELD_TRANSFER_ENCODING: unnamed_4 = 2; +pub const MAILMIME_FIELD_TYPE: unnamed_4 = 1; +pub const MAILMIME_FIELD_NONE: unnamed_4 = 0; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct mailmime_field { + pub fld_type: libc::c_int, + pub fld_data: unnamed_5, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed_5 { + 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 type unnamed_6 = libc::c_uint; +pub const MAILMIME_MECHANISM_TOKEN: unnamed_6 = 6; +pub const MAILMIME_MECHANISM_BASE64: unnamed_6 = 5; +pub const MAILMIME_MECHANISM_QUOTED_PRINTABLE: unnamed_6 = 4; +pub const MAILMIME_MECHANISM_BINARY: unnamed_6 = 3; +pub const MAILMIME_MECHANISM_8BIT: unnamed_6 = 2; +pub const MAILMIME_MECHANISM_7BIT: unnamed_6 = 1; +pub const MAILMIME_MECHANISM_ERROR: unnamed_6 = 0; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct mailmime_fields { + pub fld_list: *mut clist, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct mailmime_parameter { + pub pa_name: *mut libc::c_char, + pub pa_value: *mut libc::c_char, +} +#[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_7, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed_7 { + pub dt_text: unnamed_8, + pub dt_filename: *mut libc::c_char, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct unnamed_8 { + pub dt_data: *const libc::c_char, + pub dt_length: size_t, +} +#[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_9, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed_9 { + pub mm_single: *mut mailmime_data, + pub mm_multipart: unnamed_11, + pub mm_message: unnamed_10, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct unnamed_10 { + pub mm_fields: *mut mailimf_fields, + pub mm_msg_mime: *mut mailmime, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct unnamed_11 { + pub mm_preamble: *mut mailmime_data, + pub mm_epilogue: *mut mailmime_data, + pub mm_mp_list: *mut clist, +} +pub type unnamed_12 = libc::c_uint; +pub const MAILMIME_DISPOSITION_TYPE_EXTENSION: unnamed_12 = 3; +pub const MAILMIME_DISPOSITION_TYPE_ATTACHMENT: unnamed_12 = 2; +pub const MAILMIME_DISPOSITION_TYPE_INLINE: unnamed_12 = 1; +pub const MAILMIME_DISPOSITION_TYPE_ERROR: unnamed_12 = 0; +pub type unnamed_13 = libc::c_uint; +pub const MAILMIME_DISPOSITION_PARM_PARAMETER: unnamed_13 = 5; +pub const MAILMIME_DISPOSITION_PARM_SIZE: unnamed_13 = 4; +pub const MAILMIME_DISPOSITION_PARM_READ_DATE: unnamed_13 = 3; +pub const MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE: unnamed_13 = 2; +pub const MAILMIME_DISPOSITION_PARM_CREATION_DATE: unnamed_13 = 1; +pub const MAILMIME_DISPOSITION_PARM_FILENAME: unnamed_13 = 0; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct mailmime_disposition_parm { + pub pa_type: libc::c_int, + pub pa_data: unnamed_14, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed_14 { + 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 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_15, + 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_15 { + 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_capability_data { + pub cap_list: *mut clist, +} +#[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_16, + 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_16 { + 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 extern "C" 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_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, +} +#[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_17, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed_17 { + pub ft_fetch_att: *mut mailimap_fetch_att, + pub ft_fetch_att_list: *mut clist, +} +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_18, + 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 unnamed_18 { + 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, +} +/* define DC_USE_RPGP to enable use of rPGP instead of netpgp where available; +preferrably, this should be done in the project configuration currently */ +//#define DC_USE_RPGP 1 +/* Includes that are used frequently. This file may also be used to create predefined headers. */ +/* * Structure behind dc_context_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_context { + pub magic: uint32_t, + pub userdata: *mut libc::c_void, + pub dbfile: *mut libc::c_char, + pub blobdir: *mut libc::c_char, + pub sql: *mut dc_sqlite3_t, + pub inbox: *mut dc_imap_t, + pub inboxidle_condmutex: pthread_mutex_t, + pub perform_inbox_jobs_needed: libc::c_int, + pub probe_imap_network: libc::c_int, + pub sentbox_thread: dc_jobthread_t, + pub mvbox_thread: dc_jobthread_t, + pub smtp: *mut dc_smtp_t, + pub smtpidle_cond: pthread_cond_t, + pub smtpidle_condmutex: pthread_mutex_t, + pub smtpidle_condflag: libc::c_int, + pub smtp_suspended: libc::c_int, + pub smtp_doing_jobs: libc::c_int, + pub perform_smtp_jobs_needed: libc::c_int, + pub probe_smtp_network: libc::c_int, + pub oauth2_critical: pthread_mutex_t, + 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 type dc_lot_t = _dc_lot; +/* * Structure behind dc_lot_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_lot { + pub magic: uint32_t, + pub text1_meaning: libc::c_int, + pub text1: *mut libc::c_char, + pub text2: *mut libc::c_char, + pub timestamp: time_t, + pub state: libc::c_int, + pub id: uint32_t, + pub fingerprint: *mut libc::c_char, + pub invitenumber: *mut libc::c_char, + pub auth: *mut libc::c_char, +} +/* * + * 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 = Option< + unsafe extern "C" fn( + _: *mut dc_context_t, + _: libc::c_int, + _: uintptr_t, + _: uintptr_t, + ) -> uintptr_t, +>; +/* * + * @mainpage Getting started + * + * This document describes how to handle the Delta Chat core library. + * For general information about Delta Chat itself, + * see and . + * + * Let's start. + * + * First of all, you have to **define an event-handler-function** + * that is called by the library on specific events + * (eg. when the configuration is done or when fresh messages arrive). + * With this function you can create a Delta Chat context then: + * + * ~~~ + * #include + * + * uintptr_t event_handler_func(dc_context_t* context, int event, + * uintptr_t data1, uintptr_t data2) + * { + * return 0; // for unhandled events, it is always safe to return 0 + * } + * + * dc_context_t* context = dc_context_new(event_handler_func, NULL, NULL); + * ~~~ + * + * After that, you should make sure, + * sending and receiving jobs are processed as needed. + * For this purpose, you have to **create two threads:** + * + * ~~~ + * #include + * + * void* imap_thread_func(void* context) + * { + * while (true) { + * dc_perform_imap_jobs(context); + * dc_perform_imap_fetch(context); + * dc_perform_imap_idle(context); + * } + * } + * + * void* smtp_thread_func(void* context) + * { + * while (true) { + * dc_perform_smtp_jobs(context); + * dc_perform_smtp_idle(context); + * } + * } + * + * static pthread_t imap_thread, smtp_thread; + * pthread_create(&imap_thread, NULL, imap_thread_func, context); + * pthread_create(&smtp_thread, NULL, smtp_thread_func, context); + * ~~~ + * + * The example above uses "pthreads", + * however, you can also use anything else for thread handling. + * NB: The deltachat-core library itself does not create any threads on its own, + * however, functions, unless stated otherwise, are thread-safe. + * + * After that you can **define and open a database.** + * The database is a normal sqlite-file and is created as needed: + * + * ~~~ + * dc_open(context, "example.db", NULL); + * ~~~ + * + * Now you can **configure the context:** + * + * ~~~ + * // use some real test credentials here + * dc_set_config(context, "addr", "alice@example.org"); + * dc_set_config(context, "mail_pw", "***"); + * dc_configure(context); + * ~~~ + * + * dc_configure() returns immediately, the configuration itself may take a while + * and is done by a job in the imap-thread you've defined above. + * Once done, the #DC_EVENT_CONFIGURE_PROGRESS reports success + * to the event_handler_func() that is also defined above. + * + * The configuration result is saved in the database, + * on subsequent starts it is not needed to call dc_configure() + * (you can check this using dc_is_configured()). + * + * Now you can **send the first message:** + * + * ~~~ + * // use a real testing address here + * uint32_t contact_id = dc_create_contact(context, NULL, "bob@example.org"); + * uint32_t chat_id = dc_create_chat_by_contact_id(context, contact_id); + * + * dc_send_text_msg(context, chat_id, "Hi, here is my first message!"); + * ~~~ + * + * dc_send_text_msg() returns immediately; + * the sending itself is done by a job in the smtp-thread you've defined above. + * If you check the testing address (bob) + * and you should have received a normal email. + * Answer this email in any email program with "Got it!" + * and the imap-thread you've create above will **receive the message**. + * + * You can then **list all messages** of a chat as follow: + * + * ~~~ + * dc_array_t* msglist = dc_get_chat_msgs(context, chat_id, 0, 0); + * for (int i = 0; i < dc_array_get_cnt(msglist); i++) + * { + * uint32_t msg_id = dc_array_get_id(msglist, i); + * dc_msg_t* msg = dc_get_msg(context, msg_id); + * char* text = dc_msg_get_text(msg); + * + * printf("Message %i: %s\n", i+1, text); + * + * free(text); + * dc_msg_unref(msg); + * } + * dc_array_unref(msglist); + * ~~~ + * + * This will output the following two lines: + * + * ~~~ + * Message 1: Hi, here is my first message! + * Message 2: Got it! + * ~~~ + * + * + * ## Class reference + * + * For a class reference, see the "Classes" link atop. + * + * + * ## Further hints + * + * Here are some additional, unsorted hints that may be useful. + * + * - For `get`-functions, you have to unref the return value in some way. + * + * - Strings in function arguments or return values are usually UTF-8 encoded. + * + * - The issue-tracker for the core library is here: + * + * + * The following points are important mainly + * for the authors of the library itself: + * + * - For indentation, use tabs. + * Alignments that are not placed at the beginning of a line + * should be done with spaces. + * + * - For padding between functions, + * classes etc. use 2 empty lines + * + * - Source files are encoded as UTF-8 with Unix line endings + * (a simple `LF`, `0x0A` or `\n`) + * + * If you need further assistance, + * please do not hesitate to contact us + * through the channels shown at https://delta.chat/en/contribute + * + * Please keep in mind, that your derived work + * must respect the Mozilla Public License 2.0 of libdeltachat + * and the respective licenses of the libraries libdeltachat links with. + * + * See you. + */ +/* * + * @class dc_context_t + * + * An object representing a single account. + * + * Each account is linked to an IMAP/SMTP account and uses a separate + * SQLite database for offline functionality and for account-related + * settings. + */ +pub type dc_context_t = _dc_context; +/* ** library-private **********************************************************/ +pub type dc_smtp_t = _dc_smtp; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_smtp { + 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 error: *mut libc::c_char, + pub error_etpan: libc::c_int, +} +pub type dc_jobthread_t = _dc_jobthread; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_jobthread { + 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, + 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, +} +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_imap { + 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 type dc_receive_imf_t = Option< + unsafe extern "C" 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_imap_t = _dc_imap; +pub type dc_precheck_imf_t = Option< + unsafe extern "C" 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< + unsafe extern "C" fn(_: *mut dc_imap_t, _: *const libc::c_char, _: *const libc::c_char) -> (), +>; +pub type dc_get_config_t = Option< + unsafe extern "C" fn( + _: *mut dc_imap_t, + _: *const libc::c_char, + _: *const libc::c_char, + ) -> *mut libc::c_char, +>; +/* ** library-private **********************************************************/ +pub type dc_sqlite3_t = _dc_sqlite3; +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_sqlite3 { + pub cobj: *mut sqlite3, + pub context: *mut dc_context_t, +} +/* values for the chats.blocked database field */ +/* * the structure behind dc_chat_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_chat { + 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 grpid: *mut libc::c_char, + pub blocked: libc::c_int, + pub param: *mut dc_param_t, + pub gossiped_timestamp: time_t, + pub is_sending_locations: libc::c_int, +} +pub type dc_param_t = _dc_param; +/* * + * @class dc_param_t + * + * An object for handling key=value parameter lists; for the key, curently only + * a single character is allowed. + * + * The object is used eg. by dc_chat_t or dc_msg_t, for readable paramter names, + * these classes define some DC_PARAM_* constantats. + * + * Only for library-internal use. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_param { + pub packed: *mut libc::c_char, +} +pub type dc_chat_t = _dc_chat; +/* * the structure behind dc_msg_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_msg { + pub magic: uint32_t, + pub id: uint32_t, + pub from_id: uint32_t, + pub to_id: uint32_t, + pub chat_id: uint32_t, + pub move_state: dc_move_state_t, + pub type_0: libc::c_int, + pub state: libc::c_int, + pub hidden: libc::c_int, + pub timestamp_sort: time_t, + pub timestamp_sent: time_t, + pub timestamp_rcvd: time_t, + pub text: *mut libc::c_char, + pub context: *mut 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, + pub server_uid: uint32_t, + pub is_dc_message: libc::c_int, + pub starred: libc::c_int, + pub chat_blocked: libc::c_int, + pub location_id: uint32_t, + pub param: *mut dc_param_t, +} +pub type dc_move_state_t = libc::c_uint; +pub const DC_MOVE_STATE_MOVING: dc_move_state_t = 3; +pub const DC_MOVE_STATE_STAY: dc_move_state_t = 2; +pub const DC_MOVE_STATE_PENDING: dc_move_state_t = 1; +pub const DC_MOVE_STATE_UNDEFINED: dc_move_state_t = 0; +pub type dc_msg_t = _dc_msg; +/* * the structure behind dc_contact_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_contact { + pub magic: uint32_t, + pub context: *mut dc_context_t, + pub id: uint32_t, + pub name: *mut libc::c_char, + pub authname: *mut libc::c_char, + pub addr: *mut libc::c_char, + pub blocked: libc::c_int, + pub origin: libc::c_int, +} +pub type dc_contact_t = _dc_contact; +/* A complete hash table is an instance of the following structure. + * The internals of this structure are intended to be opaque -- client + * code should not attempt to access or modify the fields of this structure + * directly. Change this structure only by using the routines below. + * However, many of the "procedures" and "functions" for modifying and + * accessing this structure are really macros, so we can't really make + * this structure opaque. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_hash { + pub keyClass: libc::c_char, + pub copyKey: libc::c_char, + pub count: libc::c_int, + pub first: *mut dc_hashelem_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. + * + * Again, this structure is intended to be opaque, but it can't really + * be opaque because it is used by macros. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_hashelem { + pub next: *mut dc_hashelem_t, + pub prev: *mut dc_hashelem_t, + pub data: *mut libc::c_void, + pub pKey: *mut libc::c_void, + pub nKey: libc::c_int, +} +/* Forward declarations of structures. + */ +pub type dc_hash_t = _dc_hash; +/* library private: end-to-end-encryption */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_e2ee_helper { + pub encryption_successfull: libc::c_int, + pub cdata_to_free: *mut libc::c_void, + pub encrypted: libc::c_int, + pub signatures: *mut dc_hash_t, + pub gossipped_addr: *mut dc_hash_t, +} +// backups +// attachments of 25 mb brutto should work on the majority of providers +// (brutto examples: web.de=50, 1&1=40, t-online.de=32, gmail=25, posteo=50, yahoo=25, all-inkl=100). +// as an upper limit, we double the size; the core won't send messages larger than this +// to get the netto sizes, we substract 1 mb header-overhead and the base64-overhead. +// some defaults +pub type dc_e2ee_helper_t = _dc_e2ee_helper; +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_mimefactory { + pub from_addr: *mut libc::c_char, + pub from_displayname: *mut libc::c_char, + pub selfstatus: *mut libc::c_char, + pub recipients_names: *mut clist, + pub recipients_addr: *mut clist, + 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 increation: libc::c_int, + pub in_reply_to: *mut libc::c_char, + pub references: *mut libc::c_char, + pub req_mdn: libc::c_int, + pub out: *mut MMAPString, + pub out_encrypted: libc::c_int, + 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 type dc_mimefactory_loaded_t = libc::c_uint; +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 type dc_mimefactory_t = _dc_mimefactory; +#[no_mangle] +pub unsafe extern "C" fn dc_mimefactory_init( + mut factory: *mut dc_mimefactory_t, + mut context: *mut dc_context_t, +) { + if factory.is_null() || context.is_null() { + return; + } + memset( + factory as *mut libc::c_void, + 0i32, + ::std::mem::size_of::() as libc::c_ulong, + ); + (*factory).context = context; +} +#[no_mangle] +pub unsafe extern "C" fn dc_mimefactory_empty(mut factory: *mut dc_mimefactory_t) { + if factory.is_null() { + return; + } + free((*factory).from_addr as *mut libc::c_void); + (*factory).from_addr = 0 as *mut libc::c_char; + free((*factory).from_displayname as *mut libc::c_void); + (*factory).from_displayname = 0 as *mut libc::c_char; + free((*factory).selfstatus as *mut libc::c_void); + (*factory).selfstatus = 0 as *mut libc::c_char; + free((*factory).rfc724_mid as *mut libc::c_void); + (*factory).rfc724_mid = 0 as *mut libc::c_char; + if !(*factory).recipients_names.is_null() { + clist_free_content((*factory).recipients_names); + clist_free((*factory).recipients_names); + (*factory).recipients_names = 0 as *mut clist + } + if !(*factory).recipients_addr.is_null() { + clist_free_content((*factory).recipients_addr); + clist_free((*factory).recipients_addr); + (*factory).recipients_addr = 0 as *mut clist + } + dc_msg_unref((*factory).msg); + (*factory).msg = 0 as *mut dc_msg_t; + dc_chat_unref((*factory).chat); + (*factory).chat = 0 as *mut dc_chat_t; + free((*factory).in_reply_to as *mut libc::c_void); + (*factory).in_reply_to = 0 as *mut libc::c_char; + free((*factory).references as *mut libc::c_void); + (*factory).references = 0 as *mut libc::c_char; + if !(*factory).out.is_null() { + mmap_string_free((*factory).out); + (*factory).out = 0 as *mut MMAPString + } + (*factory).out_encrypted = 0i32; + (*factory).loaded = DC_MF_NOTHING_LOADED; + free((*factory).error as *mut libc::c_void); + (*factory).error = 0 as *mut libc::c_char; + (*factory).timestamp = 0i32 as time_t; +} +#[no_mangle] +pub unsafe extern "C" 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()) + { + /*call empty() before */ + context = (*factory).context; + (*factory).recipients_names = clist_new(); + (*factory).recipients_addr = clist_new(); + (*factory).msg = dc_msg_new_untyped(context); + (*factory).chat = dc_chat_new(context); + if 0 != dc_msg_load_from_db((*factory).msg, context, msg_id) + && 0 != dc_chat_load_from_db((*factory).chat, (*(*factory).msg).chat_id) + { + load_from(factory); + (*factory).req_mdn = 0i32; + if 0 != dc_chat_is_self_talk((*factory).chat) { + clist_insert_after( + (*factory).recipients_names, + (*(*factory).recipients_names).last, + dc_strdup_keep_null((*factory).from_displayname) as *mut libc::c_void, + ); + clist_insert_after( + (*factory).recipients_addr, + (*(*factory).recipients_addr).last, + dc_strdup((*factory).from_addr) as *mut libc::c_void, + ); + } 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); + 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 = + sqlite3_column_text(stmt, 0i32) as *const libc::c_char; + let mut addr: *const libc::c_char = + sqlite3_column_text(stmt, 1i32) as *const libc::c_char; + if clist_search_string_nocase((*factory).recipients_addr, addr) == 0i32 { + clist_insert_after( + (*factory).recipients_names, + (*(*factory).recipients_names).last, + (if !authname.is_null() && 0 != *authname.offset(0isize) as libc::c_int + { + dc_strdup(authname) + } else { + 0 as *mut libc::c_char + }) as *mut libc::c_void, + ); + clist_insert_after( + (*factory).recipients_addr, + (*(*factory).recipients_addr).last, + dc_strdup(addr) as *mut libc::c_void, + ); + } + } + 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 { + let mut email_to_remove: *mut libc::c_char = dc_param_get( + (*(*factory).msg).param, + 'E' as i32, + 0 as *const libc::c_char, + ); + let mut self_addr: *mut libc::c_char = 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 !email_to_remove.is_null() && strcasecmp(email_to_remove, self_addr) != 0i32 + { + if clist_search_string_nocase((*factory).recipients_addr, email_to_remove) + == 0i32 + { + clist_insert_after( + (*factory).recipients_names, + (*(*factory).recipients_names).last, + 0 as *mut libc::c_void, + ); + clist_insert_after( + (*factory).recipients_addr, + (*(*factory).recipients_addr).last, + email_to_remove as *mut libc::c_void, + ); + } + } + free(self_addr as *mut libc::c_void); + } + if command != 6i32 + && command != 7i32 + && 0 != dc_sqlite3_get_config_int( + (*context).sql, + b"mdns_enabled\x00" as *const u8 as *const libc::c_char, + 1i32, + ) + { + (*factory).req_mdn = 1i32 + } + } + stmt = dc_sqlite3_prepare( + (*context).sql, + b"SELECT mime_in_reply_to, mime_references FROM msgs WHERE id=?\x00" as *const u8 + as *const libc::c_char, + ); + sqlite3_bind_int(stmt, 1i32, (*(*factory).msg).id as libc::c_int); + if sqlite3_step(stmt) == 100i32 { + (*factory).in_reply_to = + dc_strdup(sqlite3_column_text(stmt, 0i32) as *const libc::c_char); + (*factory).references = + dc_strdup(sqlite3_column_text(stmt, 1i32) as *const libc::c_char) + } + sqlite3_finalize(stmt); + stmt = 0 as *mut sqlite3_stmt; + success = 1i32; + (*factory).loaded = DC_MF_MSG_LOADED; + (*factory).timestamp = (*(*factory).msg).timestamp_sort; + (*factory).rfc724_mid = dc_strdup((*(*factory).msg).rfc724_mid) + } + if 0 != success { + (*factory).increation = dc_msg_is_increation((*factory).msg) + } + } + sqlite3_finalize(stmt); + return success; +} +unsafe extern "C" fn load_from(mut factory: *mut dc_mimefactory_t) { + (*factory).from_addr = dc_sqlite3_get_config( + (*(*factory).context).sql, + 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, + 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, + b"selfstatus\x00" as *const u8 as *const libc::c_char, + 0 as *const libc::c_char, + ); + if (*factory).selfstatus.is_null() { + (*factory).selfstatus = dc_stock_str((*factory).context, 13i32) + }; +} +#[no_mangle] +pub unsafe extern "C" fn dc_mimefactory_load_mdn( + mut factory: *mut dc_mimefactory_t, + mut msg_id: uint32_t, +) -> libc::c_int { + let mut success: libc::c_int = 0i32; + let mut contact: *mut dc_contact_t = 0 as *mut dc_contact_t; + if !factory.is_null() { + (*factory).recipients_names = clist_new(); + (*factory).recipients_addr = clist_new(); + (*factory).msg = dc_msg_new_untyped((*factory).context); + if !(0 + == dc_sqlite3_get_config_int( + (*(*factory).context).sql, + b"mdns_enabled\x00" as *const u8 as *const libc::c_char, + 1i32, + )) + { + /* MDNs not enabled - check this is late, in the job. the use may have changed its choice while offline ... */ + contact = dc_contact_new((*factory).context); + if !(0 == dc_msg_load_from_db((*factory).msg, (*factory).context, msg_id) + || 0 == dc_contact_load_from_db( + contact, + (*(*factory).context).sql, + (*(*factory).msg).from_id, + )) + { + if !(0 != (*contact).blocked || (*(*factory).msg).chat_id <= 9i32 as libc::c_uint) { + /* Do not send MDNs trash etc.; chats.blocked is already checked by the caller in dc_markseen_msgs() */ + if !((*(*factory).msg).from_id <= 9i32 as libc::c_uint) { + clist_insert_after( + (*factory).recipients_names, + (*(*factory).recipients_names).last, + (if !(*contact).authname.is_null() + && 0 != *(*contact).authname.offset(0isize) as libc::c_int + { + dc_strdup((*contact).authname) + } else { + 0 as *mut libc::c_char + }) as *mut libc::c_void, + ); + clist_insert_after( + (*factory).recipients_addr, + (*(*factory).recipients_addr).last, + dc_strdup((*contact).addr) as *mut libc::c_void, + ); + load_from(factory); + (*factory).timestamp = dc_create_smeared_timestamp((*factory).context); + (*factory).rfc724_mid = dc_create_outgoing_rfc724_mid( + 0 as *const libc::c_char, + (*factory).from_addr, + ); + success = 1i32; + (*factory).loaded = DC_MF_MDN_LOADED + } + } + } + } + } + dc_contact_unref(contact); + return success; +} +#[no_mangle] +pub unsafe extern "C" 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 current_block: u64; + let mut imf_fields: *mut mailimf_fields = 0 as *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; + let mut subject_str: *mut libc::c_char = 0 as *mut libc::c_char; + let mut afwd_email: libc::c_int = 0i32; + let mut col: libc::c_int = 0i32; + let mut success: libc::c_int = 0i32; + let mut parts: libc::c_int = 0i32; + let mut e2ee_guaranteed: libc::c_int = 0i32; + let mut min_verified: libc::c_int = 0i32; + // 1=add Autocrypt-header (needed eg. for handshaking), 2=no Autocrypte-header (used for MDN) + let mut force_plaintext: libc::c_int = 0i32; + let mut do_gossip: libc::c_int = 0i32; + let mut grpimage: *mut libc::c_char = 0 as *mut libc::c_char; + let mut e2ee_helper: dc_e2ee_helper_t = _dc_e2ee_helper { + encryption_successfull: 0, + cdata_to_free: 0 as *mut libc::c_void, + encrypted: 0, + signatures: 0 as *mut dc_hash_t, + gossipped_addr: 0 as *mut dc_hash_t, + }; + memset( + &mut e2ee_helper as *mut dc_e2ee_helper_t as *mut libc::c_void, + 0i32, + ::std::mem::size_of::() as libc::c_ulong, + ); + if factory.is_null() + || (*factory).loaded as libc::c_uint == DC_MF_NOTHING_LOADED as libc::c_int as libc::c_uint + || !(*factory).out.is_null() + { + /*call empty() before*/ + set_error( + factory, + b"Invalid use of mimefactory-object.\x00" as *const u8 as *const libc::c_char, + ); + } else { + let mut from: *mut mailimf_mailbox_list = mailimf_mailbox_list_new_empty(); + mailimf_mailbox_list_add( + from, + mailimf_mailbox_new( + if !(*factory).from_displayname.is_null() { + dc_encode_header_words((*factory).from_displayname) + } else { + 0 as *mut libc::c_char + }, + dc_strdup((*factory).from_addr), + ), + ); + let mut to: *mut mailimf_address_list = 0 as *mut mailimf_address_list; + if !(*factory).recipients_names.is_null() + && !(*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; + to = mailimf_address_list_new_empty(); + iter1 = (*(*factory).recipients_names).first; + iter2 = (*(*factory).recipients_addr).first; + while !iter1.is_null() && !iter2.is_null() { + let mut name: *const libc::c_char = (if !iter1.is_null() { + (*iter1).data + } else { + 0 as *mut libc::c_void + }) as *const libc::c_char; + let mut addr: *const libc::c_char = (if !iter2.is_null() { + (*iter2).data + } else { + 0 as *mut libc::c_void + }) as *const libc::c_char; + mailimf_address_list_add( + to, + mailimf_address_new( + MAILIMF_ADDRESS_MAILBOX as libc::c_int, + mailimf_mailbox_new( + if !name.is_null() { + dc_encode_header_words(name) + } else { + 0 as *mut libc::c_char + }, + dc_strdup(addr), + ), + 0 as *mut mailimf_group, + ), + ); + iter1 = if !iter1.is_null() { + (*iter1).next + } else { + 0 as *mut clistcell_s + }; + iter2 = if !iter2.is_null() { + (*iter2).next + } else { + 0 as *mut clistcell_s + } + } + } + let mut references_list: *mut clist = 0 as *mut clist; + if !(*factory).references.is_null() + && 0 != *(*factory).references.offset(0isize) as libc::c_int + { + references_list = dc_str_to_clist( + (*factory).references, + b" \x00" as *const u8 as *const libc::c_char, + ) + } + let mut in_reply_to_list: *mut clist = 0 as *mut clist; + if !(*factory).in_reply_to.is_null() + && 0 != *(*factory).in_reply_to.offset(0isize) as libc::c_int + { + in_reply_to_list = dc_str_to_clist( + (*factory).in_reply_to, + b" \x00" as *const u8 as *const libc::c_char, + ) + } + imf_fields = mailimf_fields_new_with_data_all( + mailimf_get_date((*factory).timestamp), + from, + 0 as *mut mailimf_mailbox, + 0 as *mut mailimf_address_list, + to, + 0 as *mut mailimf_address_list, + 0 as *mut mailimf_address_list, + dc_strdup((*factory).rfc724_mid), + in_reply_to_list, + references_list, + 0 as *mut libc::c_char, + ); + mailimf_fields_add( + imf_fields, + mailimf_field_new_custom( + strdup(b"X-Mailer\x00" as *const u8 as *const libc::c_char), + dc_mprintf( + b"Delta Chat Core %s%s%s\x00" as *const u8 as *const libc::c_char, + b"0.42.0\x00" as *const u8 as *const libc::c_char, + if !(*(*factory).context).os_name.is_null() { + b"/\x00" as *const u8 as *const libc::c_char + } else { + b"\x00" as *const u8 as *const libc::c_char + }, + if !(*(*factory).context).os_name.is_null() { + (*(*factory).context).os_name + } else { + b"\x00" as *const u8 as *const libc::c_char + }, + ), + ), + ); + mailimf_fields_add( + imf_fields, + mailimf_field_new_custom( + strdup(b"Chat-Version\x00" as *const u8 as *const libc::c_char), + strdup(b"1.0\x00" as *const u8 as *const libc::c_char), + ), + ); + if 0 != (*factory).req_mdn { + mailimf_fields_add( + imf_fields, + mailimf_field_new_custom( + strdup( + b"Chat-Disposition-Notification-To\x00" as *const u8 as *const libc::c_char, + ), + strdup((*factory).from_addr), + ), + ); + } + message = mailmime_new_message_data(0 as *mut mailmime); + mailmime_set_imf_fields(message, imf_fields); + if (*factory).loaded as libc::c_uint == DC_MF_MSG_LOADED as libc::c_int as libc::c_uint { + /* Render a normal message + *********************************************************************/ + let mut chat: *mut dc_chat_t = (*factory).chat; + let mut msg: *mut dc_msg_t = (*factory).msg; + let mut meta_part: *mut mailmime = 0 as *mut mailmime; + let mut placeholdertext: *mut libc::c_char = 0 as *mut libc::c_char; + if (*chat).type_0 == 130i32 { + mailimf_fields_add( + imf_fields, + mailimf_field_new_custom( + strdup(b"Chat-Verified\x00" as *const u8 as *const libc::c_char), + strdup(b"1\x00" as *const u8 as *const libc::c_char), + ), + ); + force_plaintext = 0i32; + e2ee_guaranteed = 1i32; + min_verified = 2i32 + } else { + force_plaintext = dc_param_get_int((*(*factory).msg).param, 'u' as i32, 0i32); + if force_plaintext == 0i32 { + e2ee_guaranteed = dc_param_get_int((*(*factory).msg).param, 'c' as i32, 0i32) + } + } + if (*chat).gossiped_timestamp == 0i32 as libc::c_long + || ((*chat).gossiped_timestamp + (2i32 * 24i32 * 60i32 * 60i32) as libc::c_long) + < time(0 as *mut time_t) + { + do_gossip = 1i32 + } + /* build header etc. */ + let mut command: libc::c_int = dc_param_get_int((*msg).param, 'S' as i32, 0i32); + if (*chat).type_0 == 120i32 || (*chat).type_0 == 130i32 { + mailimf_fields_add( + imf_fields, + mailimf_field_new_custom( + strdup(b"Chat-Group-ID\x00" as *const u8 as *const libc::c_char), + dc_strdup((*chat).grpid), + ), + ); + mailimf_fields_add( + imf_fields, + mailimf_field_new_custom( + strdup(b"Chat-Group-Name\x00" as *const u8 as *const libc::c_char), + dc_encode_header_words((*chat).name), + ), + ); + if command == 5i32 { + let mut email_to_remove: *mut libc::c_char = + dc_param_get((*msg).param, 'E' as i32, 0 as *const libc::c_char); + if !email_to_remove.is_null() { + mailimf_fields_add( + imf_fields, + mailimf_field_new_custom( + strdup( + b"Chat-Group-Member-Removed\x00" as *const u8 + as *const libc::c_char, + ), + email_to_remove, + ), + ); + } + } else if command == 4i32 { + do_gossip = 1i32; + let mut email_to_add: *mut libc::c_char = + dc_param_get((*msg).param, 'E' as i32, 0 as *const libc::c_char); + if !email_to_add.is_null() { + mailimf_fields_add( + imf_fields, + mailimf_field_new_custom( + strdup( + b"Chat-Group-Member-Added\x00" as *const u8 + as *const libc::c_char, + ), + email_to_add, + ), + ); + grpimage = dc_param_get((*chat).param, 'i' as i32, 0 as *const libc::c_char) + } + if 0 != dc_param_get_int((*msg).param, 'F' as i32, 0i32) & 0x1i32 { + dc_log_info( + (*msg).context, + 0i32, + b"sending secure-join message \'%s\' >>>>>>>>>>>>>>>>>>>>>>>>>\x00" + as *const u8 as *const libc::c_char, + b"vg-member-added\x00" as *const u8 as *const libc::c_char, + ); + mailimf_fields_add( + imf_fields, + mailimf_field_new_custom( + strdup(b"Secure-Join\x00" as *const u8 as *const libc::c_char), + strdup(b"vg-member-added\x00" as *const u8 as *const libc::c_char), + ), + ); + } + } else if command == 2i32 { + mailimf_fields_add( + imf_fields, + mailimf_field_new_custom( + strdup( + b"Chat-Group-Name-Changed\x00" as *const u8 as *const libc::c_char, + ), + dc_param_get( + (*msg).param, + 'E' as i32, + b"\x00" as *const u8 as *const libc::c_char, + ), + ), + ); + } else if command == 3i32 { + grpimage = dc_param_get((*msg).param, 'E' as i32, 0 as *const libc::c_char); + if grpimage.is_null() { + mailimf_fields_add( + imf_fields, + mailimf_field_new_custom( + strdup(b"Chat-Group-Image\x00" as *const u8 as *const libc::c_char), + dc_strdup(b"0\x00" as *const u8 as *const libc::c_char), + ), + ); + } + } + } + if command == 8i32 { + mailimf_fields_add( + imf_fields, + mailimf_field_new_custom( + strdup(b"Chat-Content\x00" as *const u8 as *const libc::c_char), + strdup( + b"location-streaming-enabled\x00" as *const u8 as *const libc::c_char, + ), + ), + ); + } + if command == 6i32 { + mailimf_fields_add( + imf_fields, + mailimf_field_new_custom( + strdup(b"Autocrypt-Setup-Message\x00" as *const u8 as *const libc::c_char), + strdup(b"v1\x00" as *const u8 as *const libc::c_char), + ), + ); + placeholdertext = dc_stock_str((*factory).context, 43i32) + } + if command == 7i32 { + let mut step: *mut libc::c_char = + dc_param_get((*msg).param, 'E' as i32, 0 as *const libc::c_char); + if !step.is_null() { + dc_log_info( + (*msg).context, + 0i32, + b"sending secure-join message \'%s\' >>>>>>>>>>>>>>>>>>>>>>>>>\x00" + as *const u8 as *const libc::c_char, + step, + ); + mailimf_fields_add( + imf_fields, + mailimf_field_new_custom( + strdup(b"Secure-Join\x00" as *const u8 as *const libc::c_char), + step, + ), + ); + let mut param2: *mut libc::c_char = + dc_param_get((*msg).param, 'F' as i32, 0 as *const libc::c_char); + if !param2.is_null() { + mailimf_fields_add( + imf_fields, + mailimf_field_new_custom( + if strcmp( + step, + b"vg-request-with-auth\x00" as *const u8 as *const libc::c_char, + ) == 0i32 + || strcmp( + step, + b"vc-request-with-auth\x00" as *const u8 + as *const libc::c_char, + ) == 0i32 + { + strdup( + b"Secure-Join-Auth\x00" as *const u8 as *const libc::c_char, + ) + } else { + strdup( + b"Secure-Join-Invitenumber\x00" as *const u8 + as *const libc::c_char, + ) + }, + param2, + ), + ); + } + let mut fingerprint: *mut libc::c_char = + dc_param_get((*msg).param, 'G' as i32, 0 as *const libc::c_char); + if !fingerprint.is_null() { + mailimf_fields_add( + imf_fields, + mailimf_field_new_custom( + strdup( + b"Secure-Join-Fingerprint\x00" as *const u8 + as *const libc::c_char, + ), + fingerprint, + ), + ); + } + let mut grpid: *mut libc::c_char = + dc_param_get((*msg).param, 'H' as i32, 0 as *const libc::c_char); + if !grpid.is_null() { + mailimf_fields_add( + imf_fields, + mailimf_field_new_custom( + strdup( + b"Secure-Join-Group\x00" as *const u8 as *const libc::c_char, + ), + grpid, + ), + ); + } + } + } + if !grpimage.is_null() { + let mut meta: *mut dc_msg_t = dc_msg_new_untyped((*factory).context); + (*meta).type_0 = 20i32; + dc_param_set((*meta).param, 'f' as i32, grpimage); + let mut filename_as_sent: *mut libc::c_char = 0 as *mut libc::c_char; + meta_part = build_body_file( + meta, + b"group-image\x00" as *const u8 as *const libc::c_char, + &mut filename_as_sent, + ); + if !meta_part.is_null() { + mailimf_fields_add( + imf_fields, + mailimf_field_new_custom( + strdup(b"Chat-Group-Image\x00" as *const u8 as *const libc::c_char), + filename_as_sent, + ), + ); + } + dc_msg_unref(meta); + } + if (*msg).type_0 == 41i32 || (*msg).type_0 == 40i32 || (*msg).type_0 == 50i32 { + if (*msg).type_0 == 41i32 { + mailimf_fields_add( + imf_fields, + mailimf_field_new_custom( + strdup(b"Chat-Voice-Message\x00" as *const u8 as *const libc::c_char), + strdup(b"1\x00" as *const u8 as *const libc::c_char), + ), + ); + } + let mut duration_ms: libc::c_int = dc_param_get_int((*msg).param, 'd' as i32, 0i32); + if duration_ms > 0i32 { + mailimf_fields_add( + imf_fields, + mailimf_field_new_custom( + strdup(b"Chat-Duration\x00" as *const u8 as *const libc::c_char), + dc_mprintf( + b"%i\x00" as *const u8 as *const libc::c_char, + duration_ms as libc::c_int, + ), + ), + ); + } + } + afwd_email = dc_param_exists((*msg).param, 'a' as i32); + let mut fwdhint: *mut libc::c_char = 0 as *mut libc::c_char; + if 0 != afwd_email { + fwdhint = dc_strdup( + b"---------- Forwarded message ----------\r\nFrom: Delta Chat\r\n\r\n\x00" + as *const u8 as *const libc::c_char, + ) + } + let mut final_text: *const libc::c_char = 0 as *const libc::c_char; + if !placeholdertext.is_null() { + final_text = placeholdertext + } else if !(*msg).text.is_null() && 0 != *(*msg).text.offset(0isize) as libc::c_int { + final_text = (*msg).text + } + let mut footer: *mut libc::c_char = (*factory).selfstatus; + message_text = dc_mprintf( + b"%s%s%s%s%s\x00" as *const u8 as *const libc::c_char, + if !fwdhint.is_null() { + fwdhint + } else { + b"\x00" as *const u8 as *const libc::c_char + }, + if !final_text.is_null() { + final_text + } else { + b"\x00" as *const u8 as *const libc::c_char + }, + if !final_text.is_null() + && !footer.is_null() + && 0 != *footer.offset(0isize) as libc::c_int + { + b"\r\n\r\n\x00" as *const u8 as *const libc::c_char + } else { + b"\x00" as *const u8 as *const libc::c_char + }, + if !footer.is_null() && 0 != *footer.offset(0isize) as libc::c_int { + b"-- \r\n\x00" as *const u8 as *const libc::c_char + } else { + b"\x00" as *const u8 as *const libc::c_char + }, + if !footer.is_null() && 0 != *footer.offset(0isize) as libc::c_int { + footer + } else { + b"\x00" as *const u8 as *const libc::c_char + }, + ); + let mut text_part: *mut mailmime = build_body_text(message_text); + mailmime_smart_add_part(message, text_part); + parts += 1; + free(fwdhint as *mut libc::c_void); + free(placeholdertext as *mut libc::c_void); + /* add attachment part */ + if (*msg).type_0 == 20i32 + || (*msg).type_0 == 21i32 + || (*msg).type_0 == 40i32 + || (*msg).type_0 == 41i32 + || (*msg).type_0 == 50i32 + || (*msg).type_0 == 60i32 + { + if 0 == is_file_size_okay(msg) { + let mut error: *mut libc::c_char = dc_mprintf( + b"Message exceeds the recommended %i MB.\x00" as *const u8 + as *const libc::c_char, + 24i32 * 1024i32 * 1024i32 / 4i32 * 3i32 / 1000i32 / 1000i32, + ); + set_error(factory, error); + free(error as *mut libc::c_void); + current_block = 11328123142868406523; + } else { + let mut file_part: *mut mailmime = + build_body_file(msg, 0 as *const libc::c_char, 0 as *mut *mut libc::c_char); + if !file_part.is_null() { + mailmime_smart_add_part(message, file_part); + parts += 1 + } + current_block = 13000670339742628194; + } + } else { + current_block = 13000670339742628194; + } + match current_block { + 11328123142868406523 => {} + _ => { + if parts == 0i32 { + set_error( + factory, + b"Empty message.\x00" as *const u8 as *const libc::c_char, + ); + current_block = 11328123142868406523; + } else { + if !meta_part.is_null() { + mailmime_smart_add_part(message, meta_part); + parts += 1 + } + if 0 != dc_is_sending_locations_to_chat((*msg).context, (*msg).chat_id) { + let mut last_added_location_id: uint32_t = 0i32 as uint32_t; + let mut kml_file: *mut libc::c_char = dc_get_location_kml( + (*msg).context, + (*msg).chat_id, + &mut last_added_location_id, + ); + if !kml_file.is_null() { + let mut content_type: *mut mailmime_content = + mailmime_content_new_with_str( + b"application/vnd.google-earth.kml+xml\x00" as *const u8 + as *const libc::c_char, + ); + let mut mime_fields: *mut mailmime_fields = + mailmime_fields_new_filename( + MAILMIME_DISPOSITION_TYPE_ATTACHMENT as libc::c_int, + dc_strdup( + b"location.kml\x00" as *const u8 as *const libc::c_char, + ), + MAILMIME_MECHANISM_8BIT as libc::c_int, + ); + let mut kml_mime_part: *mut mailmime = + 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; + (*factory).out_last_added_location_id = last_added_location_id + } + } + current_block = 9952640327414195044; + } + } + } + } else if (*factory).loaded as libc::c_uint + == DC_MF_MDN_LOADED as libc::c_int as libc::c_uint + { + let mut multipart: *mut mailmime = + mailmime_multiple_new(b"multipart/report\x00" as *const u8 as *const libc::c_char); + let mut content: *mut mailmime_content = (*multipart).mm_content_type; + clist_insert_after( + (*content).ct_parameters, + (*(*content).ct_parameters).last, + mailmime_param_new_with_data( + b"report-type\x00" as *const u8 as *const libc::c_char as *mut libc::c_char, + b"disposition-notification\x00" as *const u8 as *const libc::c_char + as *mut libc::c_char, + ) 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; + if 0 != dc_param_get_int((*(*factory).msg).param, 'c' as i32, 0i32) { + p1 = dc_stock_str((*factory).context, 24i32) + } else { + p1 = dc_msg_get_summarytext((*factory).msg, 32i32) + } + p2 = dc_stock_str_repl_string((*factory).context, 32i32, p1); + message_text = dc_mprintf(b"%s\r\n\x00" as *const u8 as *const libc::c_char, p2); + free(p2 as *mut libc::c_void); + free(p1 as *mut libc::c_void); + let mut human_mime_part: *mut mailmime = build_body_text(message_text); + mailmime_add_part(multipart, human_mime_part); + message_text2 = + dc_mprintf(b"Reporting-UA: Delta Chat %s\r\nOriginal-Recipient: rfc822;%s\r\nFinal-Recipient: rfc822;%s\r\nOriginal-Message-ID: <%s>\r\nDisposition: manual-action/MDN-sent-automatically; displayed\r\n\x00" + as *const u8 as *const libc::c_char, + b"0.42.0\x00" as *const u8 as *const libc::c_char, + (*factory).from_addr, (*factory).from_addr, + (*(*factory).msg).rfc724_mid); + let mut content_type_0: *mut mailmime_content = mailmime_content_new_with_str( + b"message/disposition-notification\x00" as *const u8 as *const libc::c_char, + ); + let mut mime_fields_0: *mut mailmime_fields = + mailmime_fields_new_encoding(MAILMIME_MECHANISM_8BIT as libc::c_int); + let mut mach_mime_part: *mut mailmime = + mailmime_new_empty(content_type_0, mime_fields_0); + mailmime_set_body_text(mach_mime_part, message_text2, strlen(message_text2)); + mailmime_add_part(multipart, mach_mime_part); + force_plaintext = 2i32; + current_block = 9952640327414195044; + } else { + set_error( + factory, + b"No message loaded.\x00" as *const u8 as *const libc::c_char, + ); + current_block = 11328123142868406523; + } + match current_block { + 11328123142868406523 => {} + _ => { + if (*factory).loaded as libc::c_uint + == DC_MF_MDN_LOADED as libc::c_int as libc::c_uint + { + let mut e: *mut libc::c_char = dc_stock_str((*factory).context, 31i32); + subject_str = + dc_mprintf(b"Chat: %s\x00" as *const u8 as *const libc::c_char, e); + free(e as *mut libc::c_void); + } else { + subject_str = get_subject((*factory).chat, (*factory).msg, afwd_email) + } + subject = mailimf_subject_new(dc_encode_header_words(subject_str)); + mailimf_fields_add( + imf_fields, + mailimf_field_new( + MAILIMF_FIELD_SUBJECT as libc::c_int, + 0 as *mut mailimf_return, + 0 as *mut mailimf_orig_date, + 0 as *mut mailimf_from, + 0 as *mut mailimf_sender, + 0 as *mut mailimf_to, + 0 as *mut mailimf_cc, + 0 as *mut mailimf_bcc, + 0 as *mut mailimf_message_id, + 0 as *mut mailimf_orig_date, + 0 as *mut mailimf_from, + 0 as *mut mailimf_sender, + 0 as *mut mailimf_reply_to, + 0 as *mut mailimf_to, + 0 as *mut mailimf_cc, + 0 as *mut mailimf_bcc, + 0 as *mut mailimf_message_id, + 0 as *mut mailimf_in_reply_to, + 0 as *mut mailimf_references, + subject, + 0 as *mut mailimf_comments, + 0 as *mut mailimf_keywords, + 0 as *mut mailimf_optional_field, + ), + ); + if force_plaintext != 2i32 { + dc_e2ee_encrypt( + (*factory).context, + (*factory).recipients_addr, + force_plaintext, + e2ee_guaranteed, + min_verified, + do_gossip, + message, + &mut e2ee_helper, + ); + } + if 0 != e2ee_helper.encryption_successfull { + (*factory).out_encrypted = 1i32; + if 0 != do_gossip { + (*factory).out_gossiped = 1i32 + } + } + (*factory).out = mmap_string_new(b"\x00" as *const u8 as *const libc::c_char); + mailmime_write_mem((*factory).out, &mut col, message); + success = 1i32 + } + } + } + if !message.is_null() { + mailmime_free(message); + } + dc_e2ee_thanks(&mut e2ee_helper); + free(message_text as *mut libc::c_void); + 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; +} +unsafe extern "C" 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 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 { + b"Fwd: \x00" as *const u8 as *const libc::c_char + } else { + b"\x00" as *const u8 as *const libc::c_char + }; + if dc_param_get_int((*msg).param, 'S' as i32, 0i32) == 6i32 { + ret = dc_stock_str(context, 42i32) + } else if (*chat).type_0 == 120i32 || (*chat).type_0 == 130i32 { + ret = dc_mprintf( + b"Chat: %s: %s%s\x00" as *const u8 as *const libc::c_char, + (*chat).name, + fwd, + raw_subject, + ) + } else { + ret = dc_mprintf( + b"Chat: %s%s\x00" as *const u8 as *const libc::c_char, + fwd, + raw_subject, + ) + } + free(raw_subject as *mut libc::c_void); + return ret; +} +unsafe extern "C" fn set_error(mut factory: *mut dc_mimefactory_t, mut text: *const libc::c_char) { + if factory.is_null() { + return; + } + free((*factory).error as *mut libc::c_void); + (*factory).error = dc_strdup_keep_null(text); +} +unsafe extern "C" 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; + content = mailmime_content_new_with_str(b"text/plain\x00" as *const u8 as *const libc::c_char); + clist_insert_after( + (*content).ct_parameters, + (*(*content).ct_parameters).last, + mailmime_param_new_with_data( + b"charset\x00" as *const u8 as *const libc::c_char as *mut libc::c_char, + b"utf-8\x00" as *const u8 as *const libc::c_char as *mut libc::c_char, + ) as *mut libc::c_void, + ); + 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; +} +unsafe extern "C" 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 mime_sub: *mut mailmime = 0 as *mut mailmime; + let mut content: *mut mailmime_content = 0 as *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 = + dc_param_get((*msg).param, 'm' as i32, 0 as *const libc::c_char); + let mut suffix: *mut libc::c_char = dc_get_filesuffix_lc(pathNfilename); + let mut filename_to_send: *mut libc::c_char = 0 as *mut libc::c_char; + let mut filename_encoded: *mut libc::c_char = 0 as *mut libc::c_char; + if !pathNfilename.is_null() { + if (*msg).type_0 == 41i32 { + let mut wanted_struct: 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, + }; + memcpy( + &mut wanted_struct as *mut tm as *mut libc::c_void, + localtime(&(*msg).timestamp_sort) as *const libc::c_void, + ::std::mem::size_of::() as libc::c_ulong, + ); + filename_to_send = dc_mprintf( + b"voice-message_%04i-%02i-%02i_%02i-%02i-%02i.%s\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, + wanted_struct.tm_mday as libc::c_int, + wanted_struct.tm_hour as libc::c_int, + wanted_struct.tm_min as libc::c_int, + wanted_struct.tm_sec as libc::c_int, + if !suffix.is_null() { + suffix + } else { + b"dat\x00" as *const u8 as *const libc::c_char + }, + ) + } else if (*msg).type_0 == 40i32 { + filename_to_send = dc_get_filename(pathNfilename) + } else if (*msg).type_0 == 20i32 || (*msg).type_0 == 21i32 { + if base_name.is_null() { + base_name = b"image\x00" as *const u8 as *const libc::c_char + } + filename_to_send = dc_mprintf( + b"%s.%s\x00" as *const u8 as *const libc::c_char, + base_name, + if !suffix.is_null() { + suffix + } else { + b"dat\x00" as *const u8 as *const libc::c_char + }, + ) + } else if (*msg).type_0 == 50i32 { + filename_to_send = dc_mprintf( + b"video.%s\x00" as *const u8 as *const libc::c_char, + if !suffix.is_null() { + suffix + } else { + b"dat\x00" as *const u8 as *const libc::c_char + }, + ) + } else { + filename_to_send = dc_get_filename(pathNfilename) + } + if mimetype.is_null() { + if suffix.is_null() { + mimetype = + dc_strdup(b"application/octet-stream\x00" as *const u8 as *const libc::c_char) + } else if strcmp(suffix, b"png\x00" as *const u8 as *const libc::c_char) == 0i32 { + mimetype = dc_strdup(b"image/png\x00" as *const u8 as *const libc::c_char) + } else if strcmp(suffix, b"jpg\x00" as *const u8 as *const libc::c_char) == 0i32 + || strcmp(suffix, b"jpeg\x00" as *const u8 as *const libc::c_char) == 0i32 + || strcmp(suffix, b"jpe\x00" as *const u8 as *const libc::c_char) == 0i32 + { + mimetype = dc_strdup(b"image/jpeg\x00" as *const u8 as *const libc::c_char) + } else if strcmp(suffix, b"gif\x00" as *const u8 as *const libc::c_char) == 0i32 { + mimetype = dc_strdup(b"image/gif\x00" as *const u8 as *const libc::c_char) + } else { + mimetype = + dc_strdup(b"application/octet-stream\x00" as *const u8 as *const libc::c_char) + } + } + if !mimetype.is_null() { + /* create mime part, for Content-Disposition, see RFC 2183. + `Content-Disposition: attachment` seems not to make a difference to `Content-Disposition: inline` at least on tested Thunderbird and Gma'l in 2017. + But I've heard about problems with inline and outl'k, so we just use the attachment-type until we run into other problems ... */ + needs_ext = dc_needs_ext_header(filename_to_send); + mime_fields = mailmime_fields_new_filename( + MAILMIME_DISPOSITION_TYPE_ATTACHMENT as libc::c_int, + if 0 != needs_ext { + 0 as *mut libc::c_char + } else { + dc_strdup(filename_to_send) + }, + MAILMIME_MECHANISM_BASE64 as libc::c_int, + ); + if 0 != needs_ext { + let mut cur1: *mut clistiter = (*(*mime_fields).fld_list).first; + while !cur1.is_null() { + let mut field: *mut mailmime_field = (if !cur1.is_null() { + (*cur1).data + } else { + 0 as *mut libc::c_void + }) + as *mut mailmime_field; + if !field.is_null() + && (*field).fld_type == MAILMIME_FIELD_DISPOSITION as libc::c_int + && !(*field).fld_data.fld_disposition.is_null() + { + let mut file_disposition: *mut mailmime_disposition = + (*field).fld_data.fld_disposition; + if !file_disposition.is_null() { + let mut parm: *mut mailmime_disposition_parm = + mailmime_disposition_parm_new( + MAILMIME_DISPOSITION_PARM_PARAMETER as libc::c_int, + 0 as *mut libc::c_char, + 0 as *mut libc::c_char, + 0 as *mut libc::c_char, + 0 as *mut libc::c_char, + 0i32 as size_t, + mailmime_parameter_new( + strdup( + b"filename*\x00" as *const u8 as *const libc::c_char, + ), + dc_encode_ext_header(filename_to_send), + ), + ); + if !parm.is_null() { + clist_insert_after( + (*file_disposition).dsp_parms, + (*(*file_disposition).dsp_parms).last, + parm as *mut libc::c_void, + ); + } + } + break; + } else { + cur1 = if !cur1.is_null() { + (*cur1).next + } else { + 0 as *mut clistcell_s + } + } + } + } + content = mailmime_content_new_with_str(mimetype); + filename_encoded = dc_encode_header_words(filename_to_send); + clist_insert_after( + (*content).ct_parameters, + (*(*content).ct_parameters).last, + mailmime_param_new_with_data( + b"name\x00" as *const u8 as *const libc::c_char as *mut libc::c_char, + filename_encoded, + ) as *mut libc::c_void, + ); + mime_sub = mailmime_new_empty(content, mime_fields); + mailmime_set_body_file(mime_sub, dc_get_abs_path((*msg).context, pathNfilename)); + if !ret_file_name_as_sent.is_null() { + *ret_file_name_as_sent = dc_strdup(filename_to_send) + } + } + } + free(pathNfilename as *mut libc::c_void); + free(mimetype as *mut libc::c_void); + 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; +} +/* ****************************************************************************** + * Render + ******************************************************************************/ +unsafe extern "C" 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 = + dc_param_get((*msg).param, 'f' as i32, 0 as *const libc::c_char); + let mut bytes: uint64_t = dc_get_filebytes((*msg).context, pathNfilename); + if bytes > (49i32 * 1024i32 * 1024i32 / 4i32 * 3i32) as libc::c_ulonglong { + file_size_okay = 0i32 + } + free(pathNfilename as *mut libc::c_void); + return file_size_okay; +} diff --git a/src/dc_mimeparser.rs b/src/dc_mimeparser.rs new file mode 100644 index 000000000..70cd1c683 --- /dev/null +++ b/src/dc_mimeparser.rs @@ -0,0 +1,3428 @@ +use c2rust_bitfields::BitfieldStruct; +use libc; +extern "C" { + pub type mailstream_cancel; + pub type sqlite3; + #[no_mangle] + fn malloc(_: libc::c_ulong) -> *mut libc::c_void; + #[no_mangle] + fn calloc(_: libc::c_ulong, _: libc::c_ulong) -> *mut libc::c_void; + #[no_mangle] + fn free(_: *mut libc::c_void); + #[no_mangle] + fn atoi(_: *const libc::c_char) -> libc::c_int; + #[no_mangle] + fn exit(_: libc::c_int) -> !; + #[no_mangle] + fn strchr(_: *const libc::c_char, _: libc::c_int) -> *mut libc::c_char; + #[no_mangle] + fn strcmp(_: *const libc::c_char, _: *const libc::c_char) -> libc::c_int; + #[no_mangle] + fn strlen(_: *const libc::c_char) -> libc::c_ulong; + #[no_mangle] + fn strncmp(_: *const libc::c_char, _: *const libc::c_char, _: libc::c_ulong) -> libc::c_int; + #[no_mangle] + fn strstr(_: *const libc::c_char, _: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn strndup(_: *const libc::c_char, _: libc::c_ulong) -> *mut libc::c_char; + #[no_mangle] + fn strcasecmp(_: *const libc::c_char, _: *const libc::c_char) -> libc::c_int; + #[no_mangle] + fn strncasecmp(_: *const libc::c_char, _: *const libc::c_char, _: libc::c_ulong) + -> libc::c_int; + #[no_mangle] + fn carray_new(initsize: libc::c_uint) -> *mut carray; + #[no_mangle] + fn carray_add( + array: *mut carray, + data: *mut libc::c_void, + indx: *mut libc::c_uint, + ) -> libc::c_int; + #[no_mangle] + fn carray_set_size(array: *mut carray, new_size: libc::c_uint) -> libc::c_int; + #[no_mangle] + fn carray_delete_slow(array: *mut carray, indx: libc::c_uint) -> libc::c_int; + #[no_mangle] + fn carray_free(array: *mut carray); + #[no_mangle] + fn mmap_string_unref(str: *mut libc::c_char) -> libc::c_int; + #[no_mangle] + fn mailimf_mailbox_list_free(mb_list: *mut mailimf_mailbox_list); + #[no_mangle] + fn mailimf_fields_free(fields: *mut mailimf_fields); + #[no_mangle] + 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; + #[no_mangle] + 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; + #[no_mangle] + fn mailmime_free(mime: *mut mailmime); + #[no_mangle] + fn mailmime_content_charset_get(content: *mut mailmime_content) -> *mut libc::c_char; + #[no_mangle] + fn mailmime_parse( + message: *const libc::c_char, + length: size_t, + indx: *mut size_t, + result: *mut *mut mailmime, + ) -> libc::c_int; + #[no_mangle] + 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; + #[no_mangle] + 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; + #[no_mangle] + fn charconv_buffer_free(str: *mut libc::c_char); + /* string tools */ + #[no_mangle] + fn dc_strdup(_: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn dc_trim(_: *mut libc::c_char); + #[no_mangle] + fn dc_mprintf(format: *const libc::c_char, _: ...) -> *mut libc::c_char; + #[no_mangle] + fn dc_replace_bad_utf8_chars(_: *mut libc::c_char); + #[no_mangle] + fn dc_get_filemeta( + buf: *const libc::c_void, + buf_bytes: size_t, + ret_width: *mut uint32_t, + ret_height: *mut uint32_t, + ) -> libc::c_int; + #[no_mangle] + fn dc_write_file( + _: *mut dc_context_t, + pathNfilename: *const libc::c_char, + buf: *const libc::c_void, + buf_bytes: size_t, + ) -> libc::c_int; + #[no_mangle] + fn dc_get_fine_pathNfilename( + _: *mut dc_context_t, + pathNfolder: *const libc::c_char, + desired_name: *const libc::c_char, + ) -> *mut libc::c_char; + #[no_mangle] + fn dc_strbuilder_init(_: *mut dc_strbuilder_t, init_bytes: libc::c_int); + #[no_mangle] + fn dc_strbuilder_cat(_: *mut dc_strbuilder_t, text: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn dc_decode_header_words(_: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn dc_decode_ext_header(_: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn dc_param_set(_: *mut dc_param_t, key: libc::c_int, value: *const libc::c_char); + #[no_mangle] + fn dc_param_set_int(_: *mut dc_param_t, key: libc::c_int, value: int32_t); + /* library-private */ + #[no_mangle] + fn dc_param_new() -> *mut dc_param_t; + #[no_mangle] + fn dc_param_unref(_: *mut dc_param_t); + /* Return the string with the given ID by calling DC_EVENT_GET_STRING. + The result must be free()'d! */ + #[no_mangle] + fn dc_stock_str(_: *mut dc_context_t, id: libc::c_int) -> *mut libc::c_char; + /* + * There are 4 different modes of operation for a hash table: + * + * DC_HASH_INT nKey is used as the key and pKey is ignored. + * + * DC_HASH_POINTER pKey is used as the key and nKey is ignored. + * + * DC_HASH_STRING pKey points to a string that is nKey bytes long + * (including the null-terminator, if any). Case + * is ignored in comparisons. + * + * DC_HASH_BINARY pKey points to binary data nKey bytes long. + * memcmp() is used to compare keys. + * + * A copy of the key is made for DC_HASH_STRING and DC_HASH_BINARY + * if the copyKey parameter to dc_hash_init() is 1. + */ + /* + * Just to make the last parameter of dc_hash_init() more readable. + */ + /* + * Access routines. To delete an element, insert a NULL pointer. + */ + #[no_mangle] + fn dc_hash_init(_: *mut dc_hash_t, keytype: libc::c_int, copyKey: libc::c_int); + #[no_mangle] + fn dc_hash_insert( + _: *mut dc_hash_t, + pKey: *const libc::c_void, + nKey: libc::c_int, + pData: *mut libc::c_void, + ) -> *mut libc::c_void; + #[no_mangle] + fn dc_hash_find( + _: *const dc_hash_t, + pKey: *const libc::c_void, + nKey: libc::c_int, + ) -> *mut libc::c_void; + #[no_mangle] + fn dc_hash_clear(_: *mut dc_hash_t); + #[no_mangle] + fn dc_addr_normalize(addr: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn dc_kml_unref(_: *mut dc_kml_t); + #[no_mangle] + fn dc_e2ee_thanks(_: *mut dc_e2ee_helper_t); + #[no_mangle] + fn dc_log_warning(_: *mut dc_context_t, data1: libc::c_int, msg: *const libc::c_char, _: ...); + #[no_mangle] + fn dc_simplify_unref(_: *mut dc_simplify_t); + #[no_mangle] + fn dc_kml_parse( + _: *mut dc_context_t, + content: *const libc::c_char, + content_bytes: size_t, + ) -> *mut dc_kml_t; + /* Simplify and normalise text: Remove quotes, signatures, unnecessary + lineends etc. + The data returned from Simplify() must be free()'d when no longer used, private */ + #[no_mangle] + fn dc_simplify_simplify( + _: *mut dc_simplify_t, + txt_unterminated: *const libc::c_char, + txt_bytes: libc::c_int, + is_html: libc::c_int, + is_msgrmsg: libc::c_int, + ) -> *mut libc::c_char; + #[no_mangle] + fn dc_simplify_new() -> *mut dc_simplify_t; + #[no_mangle] + fn dc_log_info(_: *mut dc_context_t, data1: libc::c_int, msg: *const libc::c_char, _: ...); + #[no_mangle] + fn dc_e2ee_decrypt( + _: *mut dc_context_t, + in_out_message: *mut mailmime, + _: *mut dc_e2ee_helper_t, + ); +} +pub type __darwin_size_t = libc::c_ulong; +pub type __darwin_ssize_t = libc::c_long; +pub type __darwin_time_t = libc::c_long; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_cond_t { + pub __sig: libc::c_long, + pub __opaque: [libc::c_char; 40], +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_mutex_t { + pub __sig: libc::c_long, + pub __opaque: [libc::c_char; 56], +} +pub type __darwin_pthread_cond_t = _opaque_pthread_cond_t; +pub type __darwin_pthread_mutex_t = _opaque_pthread_mutex_t; +pub type int32_t = libc::c_int; +pub type uintptr_t = libc::c_ulong; +pub type size_t = __darwin_size_t; +pub type uint8_t = libc::c_uchar; +pub type uint32_t = libc::c_uint; +pub type ssize_t = __darwin_ssize_t; +pub type time_t = __darwin_time_t; +pub type pthread_cond_t = __darwin_pthread_cond_t; +pub type pthread_mutex_t = __darwin_pthread_mutex_t; +#[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; +#[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) -> (); +#[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 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 unnamed = libc::c_uint; +pub const MAILIMF_ADDRESS_GROUP: unnamed = 2; +pub const MAILIMF_ADDRESS_MAILBOX: unnamed = 1; +pub const MAILIMF_ADDRESS_ERROR: unnamed = 0; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct mailimf_address { + pub ad_type: libc::c_int, + pub ad_data: unnamed_0, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed_0 { + pub ad_mailbox: *mut mailimf_mailbox, + pub ad_group: *mut mailimf_group, +} +#[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, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct mailimf_mailbox_list { + pub mb_list: *mut clist, +} +#[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_fields { + pub fld_list: *mut clist, +} +pub type unnamed_1 = libc::c_uint; +pub const MAILIMF_FIELD_OPTIONAL_FIELD: unnamed_1 = 22; +pub const MAILIMF_FIELD_KEYWORDS: unnamed_1 = 21; +pub const MAILIMF_FIELD_COMMENTS: unnamed_1 = 20; +pub const MAILIMF_FIELD_SUBJECT: unnamed_1 = 19; +pub const MAILIMF_FIELD_REFERENCES: unnamed_1 = 18; +pub const MAILIMF_FIELD_IN_REPLY_TO: unnamed_1 = 17; +pub const MAILIMF_FIELD_MESSAGE_ID: unnamed_1 = 16; +pub const MAILIMF_FIELD_BCC: unnamed_1 = 15; +pub const MAILIMF_FIELD_CC: unnamed_1 = 14; +pub const MAILIMF_FIELD_TO: unnamed_1 = 13; +pub const MAILIMF_FIELD_REPLY_TO: unnamed_1 = 12; +pub const MAILIMF_FIELD_SENDER: unnamed_1 = 11; +pub const MAILIMF_FIELD_FROM: unnamed_1 = 10; +pub const MAILIMF_FIELD_ORIG_DATE: unnamed_1 = 9; +pub const MAILIMF_FIELD_RESENT_MSG_ID: unnamed_1 = 8; +pub const MAILIMF_FIELD_RESENT_BCC: unnamed_1 = 7; +pub const MAILIMF_FIELD_RESENT_CC: unnamed_1 = 6; +pub const MAILIMF_FIELD_RESENT_TO: unnamed_1 = 5; +pub const MAILIMF_FIELD_RESENT_SENDER: unnamed_1 = 4; +pub const MAILIMF_FIELD_RESENT_FROM: unnamed_1 = 3; +pub const MAILIMF_FIELD_RESENT_DATE: unnamed_1 = 2; +pub const MAILIMF_FIELD_RETURN_PATH: unnamed_1 = 1; +pub const MAILIMF_FIELD_NONE: unnamed_1 = 0; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct mailimf_field { + pub fld_type: libc::c_int, + pub fld_data: unnamed_2, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed_2 { + 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, +} +#[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, +} +pub type unnamed_3 = libc::c_uint; +pub const MAILIMF_ERROR_FILE: unnamed_3 = 4; +pub const MAILIMF_ERROR_INVAL: unnamed_3 = 3; +pub const MAILIMF_ERROR_MEMORY: unnamed_3 = 2; +pub const MAILIMF_ERROR_PARSE: unnamed_3 = 1; +pub const MAILIMF_NO_ERROR: unnamed_3 = 0; +pub type unnamed_4 = libc::c_uint; +pub const MAILMIME_COMPOSITE_TYPE_EXTENSION: unnamed_4 = 3; +pub const MAILMIME_COMPOSITE_TYPE_MULTIPART: unnamed_4 = 2; +pub const MAILMIME_COMPOSITE_TYPE_MESSAGE: unnamed_4 = 1; +pub const MAILMIME_COMPOSITE_TYPE_ERROR: unnamed_4 = 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 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_type { + pub tp_type: libc::c_int, + pub tp_data: unnamed_5, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed_5 { + 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 type unnamed_6 = libc::c_uint; +pub const MAILMIME_DISCRETE_TYPE_EXTENSION: unnamed_6 = 6; +pub const MAILMIME_DISCRETE_TYPE_APPLICATION: unnamed_6 = 5; +pub const MAILMIME_DISCRETE_TYPE_VIDEO: unnamed_6 = 4; +pub const MAILMIME_DISCRETE_TYPE_AUDIO: unnamed_6 = 3; +pub const MAILMIME_DISCRETE_TYPE_IMAGE: unnamed_6 = 2; +pub const MAILMIME_DISCRETE_TYPE_TEXT: unnamed_6 = 1; +pub const MAILMIME_DISCRETE_TYPE_ERROR: unnamed_6 = 0; +pub type unnamed_7 = libc::c_uint; +pub const MAILMIME_FIELD_LOCATION: unnamed_7 = 8; +pub const MAILMIME_FIELD_LANGUAGE: unnamed_7 = 7; +pub const MAILMIME_FIELD_DISPOSITION: unnamed_7 = 6; +pub const MAILMIME_FIELD_VERSION: unnamed_7 = 5; +pub const MAILMIME_FIELD_DESCRIPTION: unnamed_7 = 4; +pub const MAILMIME_FIELD_ID: unnamed_7 = 3; +pub const MAILMIME_FIELD_TRANSFER_ENCODING: unnamed_7 = 2; +pub const MAILMIME_FIELD_TYPE: unnamed_7 = 1; +pub const MAILMIME_FIELD_NONE: unnamed_7 = 0; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct mailmime_field { + pub fld_type: libc::c_int, + pub fld_data: unnamed_8, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed_8 { + 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 type unnamed_9 = libc::c_uint; +pub const MAILMIME_MECHANISM_TOKEN: unnamed_9 = 6; +pub const MAILMIME_MECHANISM_BASE64: unnamed_9 = 5; +pub const MAILMIME_MECHANISM_QUOTED_PRINTABLE: unnamed_9 = 4; +pub const MAILMIME_MECHANISM_BINARY: unnamed_9 = 3; +pub const MAILMIME_MECHANISM_8BIT: unnamed_9 = 2; +pub const MAILMIME_MECHANISM_7BIT: unnamed_9 = 1; +pub const MAILMIME_MECHANISM_ERROR: unnamed_9 = 0; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct mailmime_fields { + pub fld_list: *mut clist, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct mailmime_parameter { + pub pa_name: *mut libc::c_char, + pub pa_value: *mut libc::c_char, +} +pub type unnamed_10 = libc::c_uint; +pub const MAILMIME_TYPE_COMPOSITE_TYPE: unnamed_10 = 2; +pub const MAILMIME_TYPE_DISCRETE_TYPE: unnamed_10 = 1; +pub const MAILMIME_TYPE_ERROR: unnamed_10 = 0; +pub type unnamed_11 = libc::c_uint; +pub const MAILMIME_DATA_FILE: unnamed_11 = 1; +pub const MAILMIME_DATA_TEXT: unnamed_11 = 0; +#[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_12, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed_12 { + pub dt_text: unnamed_13, + pub dt_filename: *mut libc::c_char, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct unnamed_13 { + pub dt_data: *const libc::c_char, + pub dt_length: size_t, +} +pub type unnamed_14 = libc::c_uint; +pub const MAILMIME_MESSAGE: unnamed_14 = 3; +pub const MAILMIME_MULTIPLE: unnamed_14 = 2; +pub const MAILMIME_SINGLE: unnamed_14 = 1; +pub const MAILMIME_NONE: unnamed_14 = 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_15, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed_15 { + pub mm_single: *mut mailmime_data, + pub mm_multipart: unnamed_17, + pub mm_message: unnamed_16, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct unnamed_16 { + pub mm_fields: *mut mailimf_fields, + pub mm_msg_mime: *mut mailmime, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct unnamed_17 { + pub mm_preamble: *mut mailmime_data, + pub mm_epilogue: *mut mailmime_data, + pub mm_mp_list: *mut clist, +} +pub type unnamed_18 = libc::c_uint; +pub const MAILMIME_DISPOSITION_TYPE_EXTENSION: unnamed_18 = 3; +pub const MAILMIME_DISPOSITION_TYPE_ATTACHMENT: unnamed_18 = 2; +pub const MAILMIME_DISPOSITION_TYPE_INLINE: unnamed_18 = 1; +pub const MAILMIME_DISPOSITION_TYPE_ERROR: unnamed_18 = 0; +pub type unnamed_19 = libc::c_uint; +pub const MAILMIME_DISPOSITION_PARM_PARAMETER: unnamed_19 = 5; +pub const MAILMIME_DISPOSITION_PARM_SIZE: unnamed_19 = 4; +pub const MAILMIME_DISPOSITION_PARM_READ_DATE: unnamed_19 = 3; +pub const MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE: unnamed_19 = 2; +pub const MAILMIME_DISPOSITION_PARM_CREATION_DATE: unnamed_19 = 1; +pub const MAILMIME_DISPOSITION_PARM_FILENAME: unnamed_19 = 0; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct mailmime_disposition_parm { + pub pa_type: libc::c_int, + pub pa_data: unnamed_20, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed_20 { + 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 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_21, + 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_21 { + 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, +} +pub type unnamed_22 = libc::c_uint; +pub const MAIL_CHARCONV_ERROR_CONV: unnamed_22 = 3; +pub const MAIL_CHARCONV_ERROR_MEMORY: unnamed_22 = 2; +pub const MAIL_CHARCONV_ERROR_UNKNOWN_CHARSET: unnamed_22 = 1; +pub const MAIL_CHARCONV_NO_ERROR: unnamed_22 = 0; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct mailimap_capability_data { + pub cap_list: *mut clist, +} +#[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_23, + 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_23 { + 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 extern "C" 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_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, +} +#[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_24, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed_24 { + pub ft_fetch_att: *mut mailimap_fetch_att, + pub ft_fetch_att_list: *mut clist, +} +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_25, + 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 unnamed_25 { + 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, +} +/* define DC_USE_RPGP to enable use of rPGP instead of netpgp where available; +preferrably, this should be done in the project configuration currently */ +//#define DC_USE_RPGP 1 +/* Includes that are used frequently. This file may also be used to create predefined headers. */ +/* * Structure behind dc_context_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_context { + pub magic: uint32_t, + pub userdata: *mut libc::c_void, + pub dbfile: *mut libc::c_char, + pub blobdir: *mut libc::c_char, + pub sql: *mut dc_sqlite3_t, + pub inbox: *mut dc_imap_t, + pub inboxidle_condmutex: pthread_mutex_t, + pub perform_inbox_jobs_needed: libc::c_int, + pub probe_imap_network: libc::c_int, + pub sentbox_thread: dc_jobthread_t, + pub mvbox_thread: dc_jobthread_t, + pub smtp: *mut dc_smtp_t, + pub smtpidle_cond: pthread_cond_t, + pub smtpidle_condmutex: pthread_mutex_t, + pub smtpidle_condflag: libc::c_int, + pub smtp_suspended: libc::c_int, + pub smtp_doing_jobs: libc::c_int, + pub perform_smtp_jobs_needed: libc::c_int, + pub probe_smtp_network: libc::c_int, + pub oauth2_critical: pthread_mutex_t, + 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 type dc_lot_t = _dc_lot; +/* * Structure behind dc_lot_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_lot { + pub magic: uint32_t, + pub text1_meaning: libc::c_int, + pub text1: *mut libc::c_char, + pub text2: *mut libc::c_char, + pub timestamp: time_t, + pub state: libc::c_int, + pub id: uint32_t, + pub fingerprint: *mut libc::c_char, + pub invitenumber: *mut libc::c_char, + pub auth: *mut libc::c_char, +} +/* * + * 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 = Option< + unsafe extern "C" fn( + _: *mut dc_context_t, + _: libc::c_int, + _: uintptr_t, + _: uintptr_t, + ) -> uintptr_t, +>; +/* * + * @mainpage Getting started + * + * This document describes how to handle the Delta Chat core library. + * For general information about Delta Chat itself, + * see and . + * + * Let's start. + * + * First of all, you have to **define an event-handler-function** + * that is called by the library on specific events + * (eg. when the configuration is done or when fresh messages arrive). + * With this function you can create a Delta Chat context then: + * + * ~~~ + * #include + * + * uintptr_t event_handler_func(dc_context_t* context, int event, + * uintptr_t data1, uintptr_t data2) + * { + * return 0; // for unhandled events, it is always safe to return 0 + * } + * + * dc_context_t* context = dc_context_new(event_handler_func, NULL, NULL); + * ~~~ + * + * After that, you should make sure, + * sending and receiving jobs are processed as needed. + * For this purpose, you have to **create two threads:** + * + * ~~~ + * #include + * + * void* imap_thread_func(void* context) + * { + * while (true) { + * dc_perform_imap_jobs(context); + * dc_perform_imap_fetch(context); + * dc_perform_imap_idle(context); + * } + * } + * + * void* smtp_thread_func(void* context) + * { + * while (true) { + * dc_perform_smtp_jobs(context); + * dc_perform_smtp_idle(context); + * } + * } + * + * static pthread_t imap_thread, smtp_thread; + * pthread_create(&imap_thread, NULL, imap_thread_func, context); + * pthread_create(&smtp_thread, NULL, smtp_thread_func, context); + * ~~~ + * + * The example above uses "pthreads", + * however, you can also use anything else for thread handling. + * NB: The deltachat-core library itself does not create any threads on its own, + * however, functions, unless stated otherwise, are thread-safe. + * + * After that you can **define and open a database.** + * The database is a normal sqlite-file and is created as needed: + * + * ~~~ + * dc_open(context, "example.db", NULL); + * ~~~ + * + * Now you can **configure the context:** + * + * ~~~ + * // use some real test credentials here + * dc_set_config(context, "addr", "alice@example.org"); + * dc_set_config(context, "mail_pw", "***"); + * dc_configure(context); + * ~~~ + * + * dc_configure() returns immediately, the configuration itself may take a while + * and is done by a job in the imap-thread you've defined above. + * Once done, the #DC_EVENT_CONFIGURE_PROGRESS reports success + * to the event_handler_func() that is also defined above. + * + * The configuration result is saved in the database, + * on subsequent starts it is not needed to call dc_configure() + * (you can check this using dc_is_configured()). + * + * Now you can **send the first message:** + * + * ~~~ + * // use a real testing address here + * uint32_t contact_id = dc_create_contact(context, NULL, "bob@example.org"); + * uint32_t chat_id = dc_create_chat_by_contact_id(context, contact_id); + * + * dc_send_text_msg(context, chat_id, "Hi, here is my first message!"); + * ~~~ + * + * dc_send_text_msg() returns immediately; + * the sending itself is done by a job in the smtp-thread you've defined above. + * If you check the testing address (bob) + * and you should have received a normal email. + * Answer this email in any email program with "Got it!" + * and the imap-thread you've create above will **receive the message**. + * + * You can then **list all messages** of a chat as follow: + * + * ~~~ + * dc_array_t* msglist = dc_get_chat_msgs(context, chat_id, 0, 0); + * for (int i = 0; i < dc_array_get_cnt(msglist); i++) + * { + * uint32_t msg_id = dc_array_get_id(msglist, i); + * dc_msg_t* msg = dc_get_msg(context, msg_id); + * char* text = dc_msg_get_text(msg); + * + * printf("Message %i: %s\n", i+1, text); + * + * free(text); + * dc_msg_unref(msg); + * } + * dc_array_unref(msglist); + * ~~~ + * + * This will output the following two lines: + * + * ~~~ + * Message 1: Hi, here is my first message! + * Message 2: Got it! + * ~~~ + * + * + * ## Class reference + * + * For a class reference, see the "Classes" link atop. + * + * + * ## Further hints + * + * Here are some additional, unsorted hints that may be useful. + * + * - For `get`-functions, you have to unref the return value in some way. + * + * - Strings in function arguments or return values are usually UTF-8 encoded. + * + * - The issue-tracker for the core library is here: + * + * + * The following points are important mainly + * for the authors of the library itself: + * + * - For indentation, use tabs. + * Alignments that are not placed at the beginning of a line + * should be done with spaces. + * + * - For padding between functions, + * classes etc. use 2 empty lines + * + * - Source files are encoded as UTF-8 with Unix line endings + * (a simple `LF`, `0x0A` or `\n`) + * + * If you need further assistance, + * please do not hesitate to contact us + * through the channels shown at https://delta.chat/en/contribute + * + * Please keep in mind, that your derived work + * must respect the Mozilla Public License 2.0 of libdeltachat + * and the respective licenses of the libraries libdeltachat links with. + * + * See you. + */ +/* * + * @class dc_context_t + * + * An object representing a single account. + * + * Each account is linked to an IMAP/SMTP account and uses a separate + * SQLite database for offline functionality and for account-related + * settings. + */ +pub type dc_context_t = _dc_context; +/* ** library-private **********************************************************/ +pub type dc_smtp_t = _dc_smtp; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_smtp { + 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 error: *mut libc::c_char, + pub error_etpan: libc::c_int, +} +pub type dc_jobthread_t = _dc_jobthread; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_jobthread { + 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, + 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, +} +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_imap { + 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 type dc_receive_imf_t = Option< + unsafe extern "C" 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_imap_t = _dc_imap; +pub type dc_precheck_imf_t = Option< + unsafe extern "C" 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< + unsafe extern "C" fn(_: *mut dc_imap_t, _: *const libc::c_char, _: *const libc::c_char) -> (), +>; +pub type dc_get_config_t = Option< + unsafe extern "C" fn( + _: *mut dc_imap_t, + _: *const libc::c_char, + _: *const libc::c_char, + ) -> *mut libc::c_char, +>; +/* ** library-private **********************************************************/ +pub type dc_sqlite3_t = _dc_sqlite3; +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_sqlite3 { + pub cobj: *mut sqlite3, + pub context: *mut dc_context_t, +} +/* * the structure behind dc_array_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_array { + 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, +} +pub type dc_array_t = _dc_array; +pub type dc_param_t = _dc_param; +/* * + * @class dc_param_t + * + * An object for handling key=value parameter lists; for the key, curently only + * a single character is allowed. + * + * The object is used eg. by dc_chat_t or dc_msg_t, for readable paramter names, + * these classes define some DC_PARAM_* constantats. + * + * Only for library-internal use. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_param { + pub packed: *mut libc::c_char, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_strbuilder { + pub buf: *mut libc::c_char, + pub allocated: libc::c_int, + pub free: libc::c_int, + pub eos: *mut libc::c_char, +} +pub type dc_strbuilder_t = _dc_strbuilder; +/* A complete hash table is an instance of the following structure. + * The internals of this structure are intended to be opaque -- client + * code should not attempt to access or modify the fields of this structure + * directly. Change this structure only by using the routines below. + * However, many of the "procedures" and "functions" for modifying and + * accessing this structure are really macros, so we can't really make + * this structure opaque. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_hash { + pub keyClass: libc::c_char, + pub copyKey: libc::c_char, + pub count: libc::c_int, + pub first: *mut dc_hashelem_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. + * + * Again, this structure is intended to be opaque, but it can't really + * be opaque because it is used by macros. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_hashelem { + pub next: *mut dc_hashelem_t, + pub prev: *mut dc_hashelem_t, + pub data: *mut libc::c_void, + pub pKey: *mut libc::c_void, + pub nKey: libc::c_int, +} +/* Forward declarations of structures. + */ +pub type dc_hash_t = _dc_hash; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_mimepart { + pub type_0: libc::c_int, + pub is_meta: libc::c_int, + pub int_mimetype: libc::c_int, + pub msg: *mut libc::c_char, + pub msg_raw: *mut libc::c_char, + pub bytes: libc::c_int, + pub param: *mut dc_param_t, +} +/* Parse MIME body; this is the text part of an IMF, see https://tools.ietf.org/html/rfc5322 +dc_mimeparser_t has no deep dependencies to dc_context_t or to the database +(dc_context_t is used for logging only). */ +pub type dc_mimepart_t = _dc_mimepart; +/* * + * @class dc_mimeparser_t + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_mimeparser { + pub parts: *mut carray, + pub mimeroot: *mut mailmime, + pub header: dc_hash_t, + pub header_root: *mut mailimf_fields, + pub header_protected: *mut mailimf_fields, + pub subject: *mut libc::c_char, + pub is_send_by_messenger: libc::c_int, + pub decrypting_failed: libc::c_int, + pub e2ee_helper: *mut _dc_e2ee_helper, + pub blobdir: *const libc::c_char, + pub is_forwarded: libc::c_int, + pub context: *mut dc_context_t, + pub reports: *mut carray, + pub is_system_message: libc::c_int, + pub kml: *mut _dc_kml, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_kml { + pub addr: *mut libc::c_char, + pub locations: *mut dc_array_t, + pub tag: libc::c_int, + pub curr: dc_location_t, +} +pub type dc_location_t = _dc_location; +// location handling +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_location { + pub location_id: uint32_t, + pub latitude: libc::c_double, + pub longitude: libc::c_double, + pub accuracy: libc::c_double, + pub timestamp: time_t, + pub contact_id: uint32_t, + pub msg_id: uint32_t, + pub chat_id: uint32_t, + pub marker: *mut libc::c_char, +} +/* library private: end-to-end-encryption */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_e2ee_helper { + pub encryption_successfull: libc::c_int, + pub cdata_to_free: *mut libc::c_void, + pub encrypted: libc::c_int, + pub signatures: *mut dc_hash_t, + pub gossipped_addr: *mut dc_hash_t, +} +pub type dc_mimeparser_t = _dc_mimeparser; +// backups +// attachments of 25 mb brutto should work on the majority of providers +// (brutto examples: web.de=50, 1&1=40, t-online.de=32, gmail=25, posteo=50, yahoo=25, all-inkl=100). +// as an upper limit, we double the size; the core won't send messages larger than this +// to get the netto sizes, we substract 1 mb header-overhead and the base64-overhead. +// some defaults +pub type dc_e2ee_helper_t = _dc_e2ee_helper; +pub type dc_kml_t = _dc_kml; +/* ** library-private **********************************************************/ +pub type dc_simplify_t = _dc_simplify; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_simplify { + pub is_forwarded: libc::c_int, + pub is_cut_at_begin: libc::c_int, + pub is_cut_at_end: libc::c_int, +} +#[inline] +unsafe extern "C" fn carray_count(mut array: *mut carray) -> libc::c_uint { + return (*array).len; +} +#[inline] +unsafe extern "C" fn carray_get( + mut array: *mut carray, + mut indx: libc::c_uint, +) -> *mut libc::c_void { + return *(*array).array.offset(indx as isize); +} +// deprecated +#[no_mangle] +pub unsafe extern "C" 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; +#[no_mangle] +pub unsafe extern "C" fn dc_mimeparser_new( + mut blobdir: *const libc::c_char, + mut context: *mut dc_context_t, +) -> *mut dc_mimeparser_t { + let mut mimeparser: *mut dc_mimeparser_t = 0 as *mut dc_mimeparser_t; + mimeparser = calloc( + 1i32 as libc::c_ulong, + ::std::mem::size_of::() as libc::c_ulong, + ) as *mut dc_mimeparser_t; + if mimeparser.is_null() { + exit(30i32); + } + (*mimeparser).context = context; + (*mimeparser).parts = carray_new(16i32 as libc::c_uint); + (*mimeparser).blobdir = blobdir; + (*mimeparser).reports = carray_new(16i32 as libc::c_uint); + (*mimeparser).e2ee_helper = calloc( + 1i32 as libc::c_ulong, + ::std::mem::size_of::() as libc::c_ulong, + ) as *mut _dc_e2ee_helper; + dc_hash_init(&mut (*mimeparser).header, 3i32, 0i32); + return mimeparser; +} +#[no_mangle] +pub unsafe extern "C" fn dc_mimeparser_unref(mut mimeparser: *mut dc_mimeparser_t) { + if mimeparser.is_null() { + return; + } + dc_mimeparser_empty(mimeparser); + if !(*mimeparser).parts.is_null() { + carray_free((*mimeparser).parts); + } + if !(*mimeparser).reports.is_null() { + carray_free((*mimeparser).reports); + } + free((*mimeparser).e2ee_helper as *mut libc::c_void); + free(mimeparser as *mut libc::c_void); +} +#[no_mangle] +pub unsafe extern "C" fn dc_mimeparser_empty(mut mimeparser: *mut dc_mimeparser_t) { + if mimeparser.is_null() { + return; + } + if !(*mimeparser).parts.is_null() { + let mut i: libc::c_int = 0; + let mut cnt: libc::c_int = carray_count((*mimeparser).parts) as libc::c_int; + i = 0i32; + while i < cnt { + let mut part: *mut dc_mimepart_t = + carray_get((*mimeparser).parts, i as libc::c_uint) as *mut dc_mimepart_t; + if !part.is_null() { + dc_mimepart_unref(part); + } + i += 1 + } + carray_set_size((*mimeparser).parts, 0i32 as libc::c_uint); + } + (*mimeparser).header_root = 0 as *mut mailimf_fields; + dc_hash_clear(&mut (*mimeparser).header); + if !(*mimeparser).header_protected.is_null() { + mailimf_fields_free((*mimeparser).header_protected); + (*mimeparser).header_protected = 0 as *mut mailimf_fields + } + (*mimeparser).is_send_by_messenger = 0i32; + (*mimeparser).is_system_message = 0i32; + free((*mimeparser).subject as *mut libc::c_void); + (*mimeparser).subject = 0 as *mut libc::c_char; + if !(*mimeparser).mimeroot.is_null() { + mailmime_free((*mimeparser).mimeroot); + (*mimeparser).mimeroot = 0 as *mut mailmime + } + (*mimeparser).is_forwarded = 0i32; + if !(*mimeparser).reports.is_null() { + carray_set_size((*mimeparser).reports, 0i32 as libc::c_uint); + } + (*mimeparser).decrypting_failed = 0i32; + dc_e2ee_thanks((*mimeparser).e2ee_helper); + dc_kml_unref((*mimeparser).kml); + (*mimeparser).kml = 0 as *mut _dc_kml; +} +unsafe extern "C" fn dc_mimepart_unref(mut mimepart: *mut dc_mimepart_t) { + if mimepart.is_null() { + return; + } + free((*mimepart).msg as *mut libc::c_void); + (*mimepart).msg = 0 as *mut libc::c_char; + free((*mimepart).msg_raw as *mut libc::c_void); + (*mimepart).msg_raw = 0 as *mut libc::c_char; + dc_param_unref((*mimepart).param); + free(mimepart as *mut libc::c_void); +} +#[no_mangle] +pub unsafe extern "C" 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 index: size_t = 0i32 as size_t; + let mut optional_field: *mut mailimf_optional_field = 0 as *mut mailimf_optional_field; + dc_mimeparser_empty(mimeparser); + r = mailmime_parse( + body_not_terminated, + body_bytes, + &mut index, + &mut (*mimeparser).mimeroot, + ); + if !(r != MAILIMF_NO_ERROR as libc::c_int || (*mimeparser).mimeroot.is_null()) { + dc_e2ee_decrypt( + (*mimeparser).context, + (*mimeparser).mimeroot, + (*mimeparser).e2ee_helper, + ); + dc_mimeparser_parse_mime_recursive(mimeparser, (*mimeparser).mimeroot); + let mut field: *mut mailimf_field = dc_mimeparser_lookup_field( + mimeparser, + b"Subject\x00" as *const u8 as *const libc::c_char, + ); + if !field.is_null() && (*field).fld_type == MAILIMF_FIELD_SUBJECT as libc::c_int { + (*mimeparser).subject = + dc_decode_header_words((*(*field).fld_data.fld_subject).sbj_value) + } + if !dc_mimeparser_lookup_optional_field( + mimeparser, + b"Chat-Version\x00" as *const u8 as *const libc::c_char, + ) + .is_null() + { + (*mimeparser).is_send_by_messenger = 1i32 + } + if !dc_mimeparser_lookup_field( + mimeparser, + b"Autocrypt-Setup-Message\x00" as *const u8 as *const libc::c_char, + ) + .is_null() + { + let mut i: libc::c_int = 0; + let mut has_setup_file: libc::c_int = 0i32; + i = 0i32; + while (i as libc::c_uint) < carray_count((*mimeparser).parts) { + let mut part: *mut dc_mimepart_t = + carray_get((*mimeparser).parts, i as libc::c_uint) as *mut dc_mimepart_t; + if (*part).int_mimetype == 111i32 { + has_setup_file = 1i32 + } + i += 1 + } + if 0 != has_setup_file { + (*mimeparser).is_system_message = 6i32; + i = 0i32; + while (i as libc::c_uint) < carray_count((*mimeparser).parts) { + let mut part_0: *mut dc_mimepart_t = + carray_get((*mimeparser).parts, i as libc::c_uint) as *mut dc_mimepart_t; + if (*part_0).int_mimetype != 111i32 { + dc_mimepart_unref(part_0); + carray_delete_slow((*mimeparser).parts, i as libc::c_uint); + i -= 1 + } + i += 1 + } + } + } else { + optional_field = dc_mimeparser_lookup_optional_field( + mimeparser, + b"Chat-Content\x00" as *const u8 as *const libc::c_char, + ); + if !optional_field.is_null() && !(*optional_field).fld_value.is_null() { + if strcmp( + (*optional_field).fld_value, + b"location-streaming-enabled\x00" as *const u8 as *const libc::c_char, + ) == 0i32 + { + (*mimeparser).is_system_message = 8i32 + } + } + } + if !dc_mimeparser_lookup_field( + mimeparser, + b"Chat-Group-Image\x00" as *const u8 as *const libc::c_char, + ) + .is_null() + && carray_count((*mimeparser).parts) >= 1i32 as libc::c_uint + { + let mut textpart: *mut dc_mimepart_t = + carray_get((*mimeparser).parts, 0i32 as libc::c_uint) as *mut dc_mimepart_t; + if (*textpart).type_0 == 10i32 { + if carray_count((*mimeparser).parts) >= 2i32 as libc::c_uint { + let mut imgpart: *mut dc_mimepart_t = + carray_get((*mimeparser).parts, 1i32 as libc::c_uint) as *mut dc_mimepart_t; + if (*imgpart).type_0 == 20i32 { + (*imgpart).is_meta = 1i32 + } + } + } + } + if 0 != (*mimeparser).is_send_by_messenger + && 0 != s_generate_compound_msgs + && carray_count((*mimeparser).parts) == 2i32 as libc::c_uint + { + let mut textpart_0: *mut dc_mimepart_t = + carray_get((*mimeparser).parts, 0i32 as libc::c_uint) as *mut dc_mimepart_t; + let mut filepart: *mut dc_mimepart_t = + carray_get((*mimeparser).parts, 1i32 as libc::c_uint) as *mut dc_mimepart_t; + if (*textpart_0).type_0 == 10i32 + && ((*filepart).type_0 == 20i32 + || (*filepart).type_0 == 21i32 + || (*filepart).type_0 == 40i32 + || (*filepart).type_0 == 41i32 + || (*filepart).type_0 == 50i32 + || (*filepart).type_0 == 60i32) + && 0 == (*filepart).is_meta + { + free((*filepart).msg as *mut libc::c_void); + (*filepart).msg = (*textpart_0).msg; + (*textpart_0).msg = 0 as *mut libc::c_char; + dc_mimepart_unref(textpart_0); + carray_delete_slow((*mimeparser).parts, 0i32 as libc::c_uint); + } + } + if !(*mimeparser).subject.is_null() { + let mut prepend_subject: libc::c_int = 1i32; + if 0 == (*mimeparser).decrypting_failed { + let mut p: *mut libc::c_char = strchr((*mimeparser).subject, ':' as i32); + if p.wrapping_offset_from((*mimeparser).subject) as libc::c_long + == 2i32 as libc::c_long + || p.wrapping_offset_from((*mimeparser).subject) as libc::c_long + == 3i32 as libc::c_long + || 0 != (*mimeparser).is_send_by_messenger + || !strstr( + (*mimeparser).subject, + b"Chat:\x00" as *const u8 as *const libc::c_char, + ) + .is_null() + { + prepend_subject = 0i32 + } + } + if 0 != prepend_subject { + let mut subj: *mut libc::c_char = dc_strdup((*mimeparser).subject); + let mut p_0: *mut libc::c_char = strchr(subj, '[' as i32); + if !p_0.is_null() { + *p_0 = 0i32 as libc::c_char + } + dc_trim(subj); + if 0 != *subj.offset(0isize) { + let mut i_0: libc::c_int = 0; + let mut icnt: libc::c_int = carray_count((*mimeparser).parts) as libc::c_int; + i_0 = 0i32; + while i_0 < icnt { + let mut part_1: *mut dc_mimepart_t = + carray_get((*mimeparser).parts, i_0 as libc::c_uint) + as *mut dc_mimepart_t; + if (*part_1).type_0 == 10i32 { + let mut new_txt: *mut libc::c_char = dc_mprintf( + b"%s \xe2\x80\x93 %s\x00" as *const u8 as *const libc::c_char, + subj, + (*part_1).msg, + ); + free((*part_1).msg as *mut libc::c_void); + (*part_1).msg = new_txt; + break; + } else { + i_0 += 1 + } + } + } + free(subj as *mut libc::c_void); + } + } + if 0 != (*mimeparser).is_forwarded { + let mut i_1: libc::c_int = 0; + let mut icnt_0: libc::c_int = carray_count((*mimeparser).parts) as libc::c_int; + i_1 = 0i32; + while i_1 < icnt_0 { + let mut part_2: *mut dc_mimepart_t = + carray_get((*mimeparser).parts, i_1 as libc::c_uint) as *mut dc_mimepart_t; + dc_param_set_int((*part_2).param, 'a' as i32, 1i32); + i_1 += 1 + } + } + if carray_count((*mimeparser).parts) == 1i32 as libc::c_uint { + let mut part_3: *mut dc_mimepart_t = + carray_get((*mimeparser).parts, 0i32 as libc::c_uint) as *mut dc_mimepart_t; + if (*part_3).type_0 == 40i32 { + if !dc_mimeparser_lookup_optional_field( + mimeparser, + b"Chat-Voice-Message\x00" as *const u8 as *const libc::c_char, + ) + .is_null() + { + (*part_3).type_0 = 41i32 + } + } + if (*part_3).type_0 == 40i32 || (*part_3).type_0 == 41i32 || (*part_3).type_0 == 50i32 { + let mut field_0: *const mailimf_optional_field = + dc_mimeparser_lookup_optional_field( + mimeparser, + b"Chat-Duration\x00" as *const u8 as *const libc::c_char, + ); + if !field_0.is_null() { + let mut duration_ms: libc::c_int = atoi((*field_0).fld_value); + if duration_ms > 0i32 && duration_ms < 24i32 * 60i32 * 60i32 * 1000i32 { + dc_param_set_int((*part_3).param, 'd' as i32, duration_ms); + } + } + } + } + if 0 == (*mimeparser).decrypting_failed { + let mut dn_field: *const mailimf_optional_field = dc_mimeparser_lookup_optional_field( + mimeparser, + b"Chat-Disposition-Notification-To\x00" as *const u8 as *const libc::c_char, + ); + if !dn_field.is_null() && !dc_mimeparser_get_last_nonmeta(mimeparser).is_null() { + let mut mb_list: *mut mailimf_mailbox_list = 0 as *mut mailimf_mailbox_list; + let mut index_0: size_t = 0i32 as size_t; + if mailimf_mailbox_list_parse( + (*dn_field).fld_value, + strlen((*dn_field).fld_value), + &mut index_0, + &mut mb_list, + ) == MAILIMF_NO_ERROR as libc::c_int + && !mb_list.is_null() + { + let mut dn_to_addr: *mut libc::c_char = mailimf_find_first_addr(mb_list); + if !dn_to_addr.is_null() { + let mut from_field: *mut mailimf_field = dc_mimeparser_lookup_field( + mimeparser, + b"From\x00" as *const u8 as *const libc::c_char, + ); + if !from_field.is_null() + && (*from_field).fld_type == MAILIMF_FIELD_FROM as libc::c_int + && !(*from_field).fld_data.fld_from.is_null() + { + let mut from_addr: *mut libc::c_char = mailimf_find_first_addr( + (*(*from_field).fld_data.fld_from).frm_mb_list, + ); + if !from_addr.is_null() { + if strcmp(from_addr, dn_to_addr) == 0i32 { + let mut part_4: *mut dc_mimepart_t = + dc_mimeparser_get_last_nonmeta(mimeparser); + if !part_4.is_null() { + dc_param_set_int((*part_4).param, 'r' as i32, 1i32); + } + } + free(from_addr as *mut libc::c_void); + } + } + free(dn_to_addr as *mut libc::c_void); + } + mailimf_mailbox_list_free(mb_list); + } + } + } + } + /* Cleanup - and try to create at least an empty part if there are no parts yet */ + if dc_mimeparser_get_last_nonmeta(mimeparser).is_null() + && carray_count((*mimeparser).reports) == 0i32 as libc::c_uint + { + let mut part_5: *mut dc_mimepart_t = dc_mimepart_new(); + (*part_5).type_0 = 10i32; + if !(*mimeparser).subject.is_null() && 0 == (*mimeparser).is_send_by_messenger { + (*part_5).msg = dc_strdup((*mimeparser).subject) + } else { + (*part_5).msg = dc_strdup(b"\x00" as *const u8 as *const libc::c_char) + } + carray_add( + (*mimeparser).parts, + part_5 as *mut libc::c_void, + 0 as *mut libc::c_uint, + ); + }; +} +/* ****************************************************************************** + * a MIME part + ******************************************************************************/ +unsafe extern "C" fn dc_mimepart_new() -> *mut dc_mimepart_t { + let mut mimepart: *mut dc_mimepart_t = 0 as *mut dc_mimepart_t; + mimepart = calloc( + 1i32 as libc::c_ulong, + ::std::mem::size_of::() as libc::c_ulong, + ) as *mut dc_mimepart_t; + if mimepart.is_null() { + exit(33i32); + } + (*mimepart).type_0 = 0i32; + (*mimepart).param = dc_param_new(); + return mimepart; +} +#[no_mangle] +pub unsafe extern "C" 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 icnt: libc::c_int = carray_count((*mimeparser).parts) as libc::c_int; + i = icnt - 1i32; + while i >= 0i32 { + let mut part: *mut dc_mimepart_t = + carray_get((*mimeparser).parts, i as libc::c_uint) as *mut dc_mimepart_t; + if !part.is_null() && 0 == (*part).is_meta { + return part; + } + i -= 1 + } + } + return 0 as *mut dc_mimepart_t; +} +/*the result must be freed*/ +#[no_mangle] +pub unsafe extern "C" fn mailimf_find_first_addr( + mut mb_list: *const mailimf_mailbox_list, +) -> *mut libc::c_char { + if mb_list.is_null() { + return 0 as *mut libc::c_char; + } + let mut cur: *mut clistiter = (*(*mb_list).mb_list).first; + while !cur.is_null() { + let mut mb: *mut mailimf_mailbox = (if !cur.is_null() { + (*cur).data + } else { + 0 as *mut libc::c_void + }) as *mut mailimf_mailbox; + if !mb.is_null() && !(*mb).mb_addr_spec.is_null() { + return dc_addr_normalize((*mb).mb_addr_spec); + } + cur = if !cur.is_null() { + (*cur).next + } else { + 0 as *mut clistcell_s + } + } + return 0 as *mut libc::c_char; +} +/* the following functions can be used only after a call to dc_mimeparser_parse() */ +#[no_mangle] +pub unsafe extern "C" 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( + &mut (*mimeparser).header, + field_name as *const libc::c_void, + strlen(field_name) as libc::c_int, + ) as *mut mailimf_field; +} +#[no_mangle] +pub unsafe extern "C" fn dc_mimeparser_lookup_optional_field( + mut mimeparser: *mut dc_mimeparser_t, + mut field_name: *const libc::c_char, +) -> *mut mailimf_optional_field { + let mut field: *mut mailimf_field = dc_hash_find( + &mut (*mimeparser).header, + field_name as *const libc::c_void, + strlen(field_name) as libc::c_int, + ) as *mut mailimf_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; +} +unsafe extern "C" 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; + if mimeparser.is_null() || mime.is_null() { + return 0i32; + } + if !mailmime_find_ct_parameter( + mime, + b"protected-headers\x00" as *const u8 as *const libc::c_char, + ) + .is_null() + { + if (*mime).mm_type == MAILMIME_SINGLE as libc::c_int + && (*(*(*mime).mm_content_type).ct_type).tp_type + == MAILMIME_TYPE_DISCRETE_TYPE as libc::c_int + && (*(*(*(*mime).mm_content_type).ct_type) + .tp_data + .tp_discrete_type) + .dt_type + == MAILMIME_DISCRETE_TYPE_TEXT as libc::c_int + && !(*(*mime).mm_content_type).ct_subtype.is_null() + && strcmp( + (*(*mime).mm_content_type).ct_subtype, + b"rfc822-headers\x00" as *const u8 as *const libc::c_char, + ) == 0i32 + { + dc_log_info( + (*mimeparser).context, + 0i32, + b"Protected headers found in text/rfc822-headers attachment: Will be ignored.\x00" + as *const u8 as *const libc::c_char, + ); + return 0i32; + } + if (*mimeparser).header_protected.is_null() { + let mut dummy: size_t = 0i32 as size_t; + if mailimf_envelope_and_optional_fields_parse( + (*mime).mm_mime_start, + (*mime).mm_length, + &mut dummy, + &mut (*mimeparser).header_protected, + ) != MAILIMF_NO_ERROR as libc::c_int + || (*mimeparser).header_protected.is_null() + { + dc_log_warning( + (*mimeparser).context, + 0i32, + b"Protected headers parsing error.\x00" as *const u8 as *const libc::c_char, + ); + } else { + hash_header( + &mut (*mimeparser).header, + (*mimeparser).header_protected, + (*mimeparser).context, + ); + } + } else { + dc_log_info((*mimeparser).context, 0i32, + b"Protected headers found in MIME header: Will be ignored as we already found an outer one.\x00" + as *const u8 as *const libc::c_char); + } + } + match (*mime).mm_type { + 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) { + 10 => { + cur = (*(*mime).mm_data.mm_multipart.mm_mp_list).first; + while !cur.is_null() { + let mut childmime: *mut mailmime = (if !cur.is_null() { + (*cur).data + } else { + 0 as *mut libc::c_void + }) + as *mut mailmime; + if mailmime_get_mime_type( + childmime, + 0 as *mut libc::c_int, + 0 as *mut *mut libc::c_char, + ) == 30i32 + { + any_part_added = + dc_mimeparser_parse_mime_recursive(mimeparser, childmime); + break; + } else { + cur = if !cur.is_null() { + (*cur).next + } else { + 0 as *mut clistcell_s + } + } + } + if 0 == any_part_added { + cur = (*(*mime).mm_data.mm_multipart.mm_mp_list).first; + while !cur.is_null() { + let mut childmime_0: *mut mailmime = (if !cur.is_null() { + (*cur).data + } else { + 0 as *mut libc::c_void + }) + as *mut mailmime; + if mailmime_get_mime_type( + childmime_0, + 0 as *mut libc::c_int, + 0 as *mut *mut libc::c_char, + ) == 60i32 + { + any_part_added = + dc_mimeparser_parse_mime_recursive(mimeparser, childmime_0); + break; + } else { + cur = if !cur.is_null() { + (*cur).next + } else { + 0 as *mut clistcell_s + } + } + } + } + if 0 == any_part_added { + cur = (*(*mime).mm_data.mm_multipart.mm_mp_list).first; + while !cur.is_null() { + if 0 != dc_mimeparser_parse_mime_recursive( + mimeparser, + (if !cur.is_null() { + (*cur).data + } else { + 0 as *mut libc::c_void + }) as *mut mailmime, + ) { + any_part_added = 1i32; + /* out of for() */ + break; + } else { + cur = if !cur.is_null() { + (*cur).next + } else { + 0 as *mut clistcell_s + } + } + } + } + } + 20 => { + cur = (*(*mime).mm_data.mm_multipart.mm_mp_list).first; + if !cur.is_null() { + any_part_added = dc_mimeparser_parse_mime_recursive( + mimeparser, + (if !cur.is_null() { + (*cur).data + } else { + 0 as *mut libc::c_void + }) as *mut mailmime, + ) + } + } + 40 => { + let mut part: *mut dc_mimepart_t = dc_mimepart_new(); + (*part).type_0 = 10i32; + let mut msg_body: *mut libc::c_char = + dc_stock_str((*mimeparser).context, 29i32); + (*part).msg = + dc_mprintf(b"[%s]\x00" as *const u8 as *const libc::c_char, msg_body); + (*part).msg_raw = dc_strdup((*part).msg); + free(msg_body as *mut libc::c_void); + carray_add( + (*mimeparser).parts, + part as *mut libc::c_void, + 0 as *mut libc::c_uint, + ); + any_part_added = 1i32; + (*mimeparser).decrypting_failed = 1i32 + } + 46 => { + cur = (*(*mime).mm_data.mm_multipart.mm_mp_list).first; + if !cur.is_null() { + any_part_added = dc_mimeparser_parse_mime_recursive( + mimeparser, + (if !cur.is_null() { + (*cur).data + } else { + 0 as *mut libc::c_void + }) as *mut mailmime, + ) + } + } + 45 => { + if (*(*mime).mm_data.mm_multipart.mm_mp_list).count >= 2i32 { + let mut report_type: *mut mailmime_parameter = mailmime_find_ct_parameter( + mime, + b"report-type\x00" as *const u8 as *const libc::c_char, + ); + if !report_type.is_null() + && !(*report_type).pa_value.is_null() + && strcmp( + (*report_type).pa_value, + b"disposition-notification\x00" as *const u8 as *const libc::c_char, + ) == 0i32 + { + carray_add( + (*mimeparser).reports, + mime as *mut libc::c_void, + 0 as *mut libc::c_uint, + ); + } else { + any_part_added = dc_mimeparser_parse_mime_recursive( + mimeparser, + (if !(*(*mime).mm_data.mm_multipart.mm_mp_list).first.is_null() { + (*(*(*mime).mm_data.mm_multipart.mm_mp_list).first).data + } else { + 0 as *mut libc::c_void + }) as *mut mailmime, + ) + } + } + } + _ => { + let mut skip_part: *mut mailmime = 0 as *mut mailmime; + let mut html_part: *mut mailmime = 0 as *mut mailmime; + let mut plain_cnt: libc::c_int = 0i32; + let mut html_cnt: libc::c_int = 0i32; + cur = (*(*mime).mm_data.mm_multipart.mm_mp_list).first; + while !cur.is_null() { + let mut childmime_1: *mut mailmime = (if !cur.is_null() { + (*cur).data + } else { + 0 as *mut libc::c_void + }) + as *mut mailmime; + if mailmime_get_mime_type( + childmime_1, + 0 as *mut libc::c_int, + 0 as *mut *mut libc::c_char, + ) == 60i32 + { + plain_cnt += 1 + } else if mailmime_get_mime_type( + childmime_1, + 0 as *mut libc::c_int, + 0 as *mut *mut libc::c_char, + ) == 70i32 + { + html_part = childmime_1; + html_cnt += 1 + } + cur = if !cur.is_null() { + (*cur).next + } else { + 0 as *mut clistcell_s + } + } + if plain_cnt == 1i32 && html_cnt == 1i32 { + dc_log_warning((*mimeparser).context, 0i32, + b"HACK: multipart/mixed message found with PLAIN and HTML, we\'ll skip the HTML part as this seems to be unwanted.\x00" + as *const u8 as + *const libc::c_char); + skip_part = html_part + } + cur = (*(*mime).mm_data.mm_multipart.mm_mp_list).first; + while !cur.is_null() { + let mut childmime_2: *mut mailmime = (if !cur.is_null() { + (*cur).data + } else { + 0 as *mut libc::c_void + }) + as *mut mailmime; + if childmime_2 != skip_part { + if 0 != dc_mimeparser_parse_mime_recursive(mimeparser, childmime_2) { + any_part_added = 1i32 + } + } + cur = if !cur.is_null() { + (*cur).next + } else { + 0 as *mut clistcell_s + } + } + } + } + } + 3 => { + if (*mimeparser).header_root.is_null() { + (*mimeparser).header_root = (*mime).mm_data.mm_message.mm_fields; + hash_header( + &mut (*mimeparser).header, + (*mimeparser).header_root, + (*mimeparser).context, + ); + } + if !(*mime).mm_data.mm_message.mm_msg_mime.is_null() { + any_part_added = dc_mimeparser_parse_mime_recursive( + mimeparser, + (*mime).mm_data.mm_message.mm_msg_mime, + ) + } + } + _ => {} + } + return any_part_added; +} +unsafe extern "C" fn hash_header( + mut out: *mut dc_hash_t, + mut in_0: *const mailimf_fields, + mut context: *mut dc_context_t, +) { + if in_0.is_null() { + return; + } + let mut cur1: *mut clistiter = (*(*in_0).fld_list).first; + while !cur1.is_null() { + let mut field: *mut mailimf_field = (if !cur1.is_null() { + (*cur1).data + } else { + 0 as *mut libc::c_void + }) as *mut mailimf_field; + let mut key: *const libc::c_char = 0 as *const libc::c_char; + 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, + 10 => key = b"From\x00" as *const u8 as *const libc::c_char, + 11 => key = b"Sender\x00" as *const u8 as *const libc::c_char, + 12 => key = b"Reply-To\x00" as *const u8 as *const libc::c_char, + 13 => key = b"To\x00" as *const u8 as *const libc::c_char, + 14 => key = b"Cc\x00" as *const u8 as *const libc::c_char, + 15 => key = b"Bcc\x00" as *const u8 as *const libc::c_char, + 16 => key = b"Message-ID\x00" as *const u8 as *const libc::c_char, + 17 => key = b"In-Reply-To\x00" as *const u8 as *const libc::c_char, + 18 => key = b"References\x00" as *const u8 as *const libc::c_char, + 19 => key = b"Subject\x00" as *const u8 as *const libc::c_char, + 22 => { + let mut optional_field: *const mailimf_optional_field = + (*field).fld_data.fld_optional_field; + if !optional_field.is_null() { + key = (*optional_field).fld_name + } + } + _ => {} + } + if !key.is_null() { + let mut key_len: libc::c_int = strlen(key) as libc::c_int; + if !dc_hash_find(out, key as *const libc::c_void, key_len).is_null() { + if (*field).fld_type != MAILIMF_FIELD_OPTIONAL_FIELD as libc::c_int + || key_len > 5i32 + && strncasecmp( + key, + b"Chat-\x00" as *const u8 as *const libc::c_char, + 5i32 as libc::c_ulong, + ) == 0i32 + { + dc_hash_insert( + out, + key as *const libc::c_void, + key_len, + field as *mut libc::c_void, + ); + } + } else { + dc_hash_insert( + out, + key as *const libc::c_void, + key_len, + field as *mut libc::c_void, + ); + } + } + cur1 = if !cur1.is_null() { + (*cur1).next + } else { + 0 as *mut clistcell_s + } + } +} +unsafe extern "C" fn mailmime_get_mime_type( + mut mime: *mut mailmime, + mut msg_type: *mut libc::c_int, + mut raw_mime: *mut *mut libc::c_char, +) -> libc::c_int { + let mut c: *mut mailmime_content = (*mime).mm_content_type; + let mut dummy: libc::c_int = 0i32; + if msg_type.is_null() { + msg_type = &mut dummy + } + *msg_type = 0i32; + if c.is_null() || (*c).ct_type.is_null() { + return 0i32; + } + match (*(*c).ct_type).tp_type { + 1 => match (*(*(*c).ct_type).tp_data.tp_discrete_type).dt_type { + 1 => { + if !(0 != mailmime_is_attachment_disposition(mime)) { + if strcmp( + (*c).ct_subtype, + b"plain\x00" as *const u8 as *const libc::c_char, + ) == 0i32 + { + *msg_type = 10i32; + return 60i32; + } else { + if strcmp( + (*c).ct_subtype, + b"html\x00" as *const u8 as *const libc::c_char, + ) == 0i32 + { + *msg_type = 10i32; + return 70i32; + } + } + } + *msg_type = 60i32; + reconcat_mime( + raw_mime, + b"text\x00" as *const u8 as *const libc::c_char, + (*c).ct_subtype, + ); + return 110i32; + } + 2 => { + if strcmp( + (*c).ct_subtype, + b"gif\x00" as *const u8 as *const libc::c_char, + ) == 0i32 + { + *msg_type = 21i32 + } else if strcmp( + (*c).ct_subtype, + b"svg+xml\x00" as *const u8 as *const libc::c_char, + ) == 0i32 + { + *msg_type = 60i32; + reconcat_mime( + raw_mime, + b"image\x00" as *const u8 as *const libc::c_char, + (*c).ct_subtype, + ); + return 110i32; + } else { + *msg_type = 20i32 + } + reconcat_mime( + raw_mime, + b"image\x00" as *const u8 as *const libc::c_char, + (*c).ct_subtype, + ); + return 80i32; + } + 3 => { + *msg_type = 40i32; + reconcat_mime( + raw_mime, + b"audio\x00" as *const u8 as *const libc::c_char, + (*c).ct_subtype, + ); + return 90i32; + } + 4 => { + *msg_type = 50i32; + reconcat_mime( + raw_mime, + b"video\x00" as *const u8 as *const libc::c_char, + (*c).ct_subtype, + ); + return 100i32; + } + _ => { + *msg_type = 60i32; + if (*(*(*c).ct_type).tp_data.tp_discrete_type).dt_type + == MAILMIME_DISCRETE_TYPE_APPLICATION as libc::c_int + && strcmp( + (*c).ct_subtype, + b"autocrypt-setup\x00" as *const u8 as *const libc::c_char, + ) == 0i32 + { + reconcat_mime( + raw_mime, + b"application\x00" as *const u8 as *const libc::c_char, + (*c).ct_subtype, + ); + return 111i32; + } + reconcat_mime( + raw_mime, + (*(*(*c).ct_type).tp_data.tp_discrete_type).dt_extension, + (*c).ct_subtype, + ); + return 110i32; + } + }, + 2 => { + if (*(*(*c).ct_type).tp_data.tp_composite_type).ct_type + == MAILMIME_COMPOSITE_TYPE_MULTIPART as libc::c_int + { + if strcmp( + (*c).ct_subtype, + b"alternative\x00" as *const u8 as *const libc::c_char, + ) == 0i32 + { + return 10i32; + } else if strcmp( + (*c).ct_subtype, + b"related\x00" as *const u8 as *const libc::c_char, + ) == 0i32 + { + return 20i32; + } else if strcmp( + (*c).ct_subtype, + b"encrypted\x00" as *const u8 as *const libc::c_char, + ) == 0i32 + { + return 40i32; + } else if strcmp( + (*c).ct_subtype, + b"signed\x00" as *const u8 as *const libc::c_char, + ) == 0i32 + { + return 46i32; + } else if strcmp( + (*c).ct_subtype, + b"mixed\x00" as *const u8 as *const libc::c_char, + ) == 0i32 + { + return 30i32; + } else if strcmp( + (*c).ct_subtype, + b"report\x00" as *const u8 as *const libc::c_char, + ) == 0i32 + { + return 45i32; + } else { + return 50i32; + } + } else { + if (*(*(*c).ct_type).tp_data.tp_composite_type).ct_type + == MAILMIME_COMPOSITE_TYPE_MESSAGE as libc::c_int + { + return 0i32; + } + } + } + _ => {} + } + return 0i32; +} +unsafe extern "C" fn reconcat_mime( + mut raw_mime: *mut *mut libc::c_char, + mut type_0: *const libc::c_char, + mut subtype: *const libc::c_char, +) { + if !raw_mime.is_null() { + *raw_mime = dc_mprintf( + b"%s/%s\x00" as *const u8 as *const libc::c_char, + if !type_0.is_null() { + type_0 + } else { + b"application\x00" as *const u8 as *const libc::c_char + }, + if !subtype.is_null() { + subtype + } else { + b"octet-stream\x00" as *const u8 as *const libc::c_char + }, + ) + }; +} +unsafe extern "C" 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; + while !cur.is_null() { + let mut field: *mut mailmime_field = (if !cur.is_null() { + (*cur).data + } else { + 0 as *mut libc::c_void + }) as *mut mailmime_field; + if !field.is_null() + && (*field).fld_type == MAILMIME_FIELD_DISPOSITION as libc::c_int + && !(*field).fld_data.fld_disposition.is_null() + { + if !(*(*field).fld_data.fld_disposition).dsp_type.is_null() + && (*(*(*field).fld_data.fld_disposition).dsp_type).dsp_type + == MAILMIME_DISPOSITION_TYPE_ATTACHMENT as libc::c_int + { + return 1i32; + } + } + cur = if !cur.is_null() { + (*cur).next + } else { + 0 as *mut clistcell_s + } + } + } + return 0i32; +} +/* low-level-tools for working with mailmime structures directly */ +#[no_mangle] +pub unsafe extern "C" fn mailmime_find_ct_parameter( + mut mime: *mut mailmime, + mut name: *const libc::c_char, +) -> *mut mailmime_parameter { + if mime.is_null() + || name.is_null() + || (*mime).mm_content_type.is_null() + || (*(*mime).mm_content_type).ct_parameters.is_null() + { + return 0 as *mut mailmime_parameter; + } + let mut cur: *mut clistiter = 0 as *mut clistiter; + cur = (*(*(*mime).mm_content_type).ct_parameters).first; + while !cur.is_null() { + let mut param: *mut mailmime_parameter = (if !cur.is_null() { + (*cur).data + } else { + 0 as *mut libc::c_void + }) as *mut mailmime_parameter; + if !param.is_null() && !(*param).pa_name.is_null() { + if strcmp((*param).pa_name, name) == 0i32 { + return param; + } + } + cur = if !cur.is_null() { + (*cur).next + } else { + 0 as *mut clistcell_s + } + } + return 0 as *mut mailmime_parameter; +} +unsafe extern "C" fn dc_mimeparser_add_single_part_if_known( + mut mimeparser: *mut dc_mimeparser_t, + mut mime: *mut mailmime, +) -> libc::c_int { + 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 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; + let mut raw_mime: *mut libc::c_char = 0 as *mut libc::c_char; + /* mmap_string_unref()'d if set */ + let mut transfer_decoding_buffer: *mut libc::c_char = 0 as *mut libc::c_char; + /* charconv_buffer_free()'d if set (just calls mmap_string_unref()) */ + let mut charset_buffer: *mut libc::c_char = 0 as *mut libc::c_char; + /* must not be free()'d */ + let mut decoded_data: *const libc::c_char = 0 as *const libc::c_char; + let mut decoded_data_bytes: size_t = 0i32 as size_t; + let mut simplifier: *mut dc_simplify_t = 0 as *mut dc_simplify_t; + if !(mime.is_null() || (*mime).mm_data.mm_single.is_null()) { + mime_type = mailmime_get_mime_type(mime, &mut msg_type, &mut raw_mime); + mime_data = (*mime).mm_data.mm_single; + /* MAILMIME_DATA_FILE indicates, the data is in a file; AFAIK this is not used on parsing */ + if !((*mime_data).dt_type != MAILMIME_DATA_TEXT as libc::c_int + || (*mime_data).dt_data.dt_text.dt_data.is_null() + || (*mime_data).dt_data.dt_text.dt_length <= 0i32 as libc::c_ulong) + { + /* regard `Content-Transfer-Encoding:` */ + if !(0 + == mailmime_transfer_decode( + mime, + &mut decoded_data, + &mut decoded_data_bytes, + &mut transfer_decoding_buffer, + )) + { + /* no always error - but no data */ + match mime_type { + 60 | 70 => { + if simplifier.is_null() { + simplifier = dc_simplify_new(); + if simplifier.is_null() { + current_block = 8795901732489102124; + } else { + current_block = 13797916685926291137; + } + } else { + current_block = 13797916685926291137; + } + match current_block { + 8795901732489102124 => {} + _ => { + /* get from `Content-Type: text/...; charset=utf-8`; must not be free()'d */ + let mut charset: *const libc::c_char = + mailmime_content_charset_get((*mime).mm_content_type); + if !charset.is_null() + && strcmp( + charset, + b"utf-8\x00" as *const u8 as *const libc::c_char, + ) != 0i32 + && strcmp( + charset, + b"UTF-8\x00" as *const u8 as *const libc::c_char, + ) != 0i32 + { + let mut ret_bytes: size_t = 0i32 as size_t; + let mut r: libc::c_int = charconv_buffer( + b"utf-8\x00" as *const u8 as *const libc::c_char, + charset, + decoded_data, + decoded_data_bytes, + &mut charset_buffer, + &mut ret_bytes, + ); + if r != MAIL_CHARCONV_NO_ERROR as libc::c_int { + dc_log_warning((*mimeparser).context, + 0i32, + b"Cannot convert %i bytes from \"%s\" to \"utf-8\"; errorcode is %i.\x00" + as *const u8 as + *const libc::c_char, + decoded_data_bytes as + libc::c_int, + charset, + r as libc::c_int); + current_block = 17788412896529399552; + } else if charset_buffer.is_null() + || ret_bytes <= 0i32 as libc::c_ulong + { + /* no error - but nothing to add */ + current_block = 8795901732489102124; + } else { + decoded_data = charset_buffer; + decoded_data_bytes = ret_bytes; + current_block = 17788412896529399552; + } + } else { + current_block = 17788412896529399552; + } + match current_block { + 8795901732489102124 => {} + _ => { + /* check header directly as is_send_by_messenger is not yet set up */ + let mut is_msgrmsg: libc::c_int = + (dc_mimeparser_lookup_optional_field( + mimeparser, + b"Chat-Version\x00" as *const u8 + as *const libc::c_char, + ) != 0 as *mut libc::c_void + as *mut mailimf_optional_field) + as libc::c_int; + let mut simplified_txt: *mut libc::c_char = + dc_simplify_simplify( + simplifier, + decoded_data, + decoded_data_bytes as libc::c_int, + if mime_type == 70i32 { 1i32 } else { 0i32 }, + is_msgrmsg, + ); + if !simplified_txt.is_null() + && 0 != *simplified_txt.offset(0isize) as libc::c_int + { + part = dc_mimepart_new(); + (*part).type_0 = 10i32; + (*part).int_mimetype = mime_type; + (*part).msg = simplified_txt; + (*part).msg_raw = + strndup(decoded_data, decoded_data_bytes); + do_add_single_part(mimeparser, part); + part = 0 as *mut dc_mimepart_t + } else { + free(simplified_txt as *mut libc::c_void); + } + if 0 != (*simplifier).is_forwarded { + (*mimeparser).is_forwarded = 1i32 + } + current_block = 10261677128829721533; + } + } + } + } + } + 80 | 90 | 100 | 110 | 111 => { + /* try to get file name from + `Content-Disposition: ... filename*=...` + or `Content-Disposition: ... filename*0*=... filename*1*=... filename*2*=...` + or `Content-Disposition: ... filename=...` */ + let mut filename_parts: dc_strbuilder_t = _dc_strbuilder { + buf: 0 as *mut libc::c_char, + allocated: 0, + free: 0, + eos: 0 as *mut libc::c_char, + }; + dc_strbuilder_init(&mut filename_parts, 0i32); + let mut cur1: *mut clistiter = (*(*(*mime).mm_mime_fields).fld_list).first; + while !cur1.is_null() { + let mut field: *mut mailmime_field = (if !cur1.is_null() { + (*cur1).data + } else { + 0 as *mut libc::c_void + }) + as *mut mailmime_field; + if !field.is_null() + && (*field).fld_type == MAILMIME_FIELD_DISPOSITION as libc::c_int + && !(*field).fld_data.fld_disposition.is_null() + { + let mut file_disposition: *mut mailmime_disposition = + (*field).fld_data.fld_disposition; + if !file_disposition.is_null() { + let mut cur2: *mut clistiter = + (*(*file_disposition).dsp_parms).first; + while !cur2.is_null() { + let mut dsp_param: *mut mailmime_disposition_parm = + (if !cur2.is_null() { + (*cur2).data + } else { + 0 as *mut libc::c_void + }) + as *mut mailmime_disposition_parm; + if !dsp_param.is_null() { + if (*dsp_param).pa_type + == MAILMIME_DISPOSITION_PARM_PARAMETER + as libc::c_int + && !(*dsp_param).pa_data.pa_parameter.is_null() + && !(*(*dsp_param).pa_data.pa_parameter) + .pa_name + .is_null() + && strncmp( + (*(*dsp_param).pa_data.pa_parameter).pa_name, + b"filename*\x00" as *const u8 + as *const libc::c_char, + 9i32 as libc::c_ulong, + ) == 0i32 + { + dc_strbuilder_cat( + &mut filename_parts, + (*(*dsp_param).pa_data.pa_parameter).pa_value, + ); + } else if (*dsp_param).pa_type + == MAILMIME_DISPOSITION_PARM_FILENAME as libc::c_int + { + desired_filename = dc_decode_header_words( + (*dsp_param).pa_data.pa_filename, + ) + } + } + cur2 = if !cur2.is_null() { + (*cur2).next + } else { + 0 as *mut clistcell_s + } + } + } + break; + } else { + cur1 = if !cur1.is_null() { + (*cur1).next + } else { + 0 as *mut clistcell_s + } + } + } + if 0 != strlen(filename_parts.buf) { + free(desired_filename as *mut libc::c_void); + desired_filename = dc_decode_ext_header(filename_parts.buf) + } + free(filename_parts.buf as *mut libc::c_void); + if desired_filename.is_null() { + let mut param: *mut mailmime_parameter = mailmime_find_ct_parameter( + mime, + b"name\x00" as *const u8 as *const libc::c_char, + ); + if !param.is_null() + && !(*param).pa_value.is_null() + && 0 != *(*param).pa_value.offset(0isize) as libc::c_int + { + desired_filename = dc_strdup((*param).pa_value) + } + } + /* if there is still no filename, guess one */ + if desired_filename.is_null() { + if !(*mime).mm_content_type.is_null() + && !(*(*mime).mm_content_type).ct_subtype.is_null() + { + desired_filename = dc_mprintf( + b"file.%s\x00" as *const u8 as *const libc::c_char, + (*(*mime).mm_content_type).ct_subtype, + ); + current_block = 17019156190352891614; + } else { + current_block = 8795901732489102124; + } + } else { + current_block = 17019156190352891614; + } + match current_block { + 8795901732489102124 => {} + _ => { + if strncmp( + desired_filename, + b"location\x00" as *const u8 as *const libc::c_char, + 8i32 as libc::c_ulong, + ) == 0i32 + && strncmp( + desired_filename + .offset(strlen(desired_filename) as isize) + .offset(-4isize), + b".kml\x00" as *const u8 as *const libc::c_char, + 4i32 as libc::c_ulong, + ) == 0i32 + { + (*mimeparser).kml = dc_kml_parse( + (*mimeparser).context, + decoded_data, + decoded_data_bytes, + ); + current_block = 8795901732489102124; + } else { + dc_replace_bad_utf8_chars(desired_filename); + do_add_single_file_part( + mimeparser, + msg_type, + mime_type, + raw_mime, + decoded_data, + decoded_data_bytes, + desired_filename, + ); + current_block = 10261677128829721533; + } + } + } + } + _ => { + current_block = 10261677128829721533; + } + } + match current_block { + 8795901732489102124 => {} + _ => {} + } + } + } + } + /* add object? (we do not add all objetcs, eg. signatures etc. are ignored) */ + dc_simplify_unref(simplifier); + if !charset_buffer.is_null() { + charconv_buffer_free(charset_buffer); + } + if !transfer_decoding_buffer.is_null() { + mmap_string_unref(transfer_decoding_buffer); + } + free(file_suffix as *mut libc::c_void); + free(desired_filename as *mut libc::c_void); + dc_mimepart_unref(part); + free(raw_mime as *mut libc::c_void); + return if carray_count((*mimeparser).parts) > old_part_count as libc::c_uint { + 1i32 + } else { + 0i32 + }; +} +unsafe extern "C" fn do_add_single_file_part( + mut parser: *mut dc_mimeparser_t, + mut msg_type: libc::c_int, + mut mime_type: libc::c_int, + mut raw_mime: *const libc::c_char, + mut decoded_data: *const libc::c_char, + mut decoded_data_bytes: size_t, + 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; + /* create a free file name to use */ + pathNfilename = dc_get_fine_pathNfilename( + (*parser).context, + b"$BLOBDIR\x00" as *const u8 as *const libc::c_char, + desired_filename, + ); + if !pathNfilename.is_null() { + /* copy data to file */ + if !(dc_write_file( + (*parser).context, + pathNfilename, + decoded_data as *const libc::c_void, + decoded_data_bytes, + ) == 0i32) + { + part = dc_mimepart_new(); + (*part).type_0 = msg_type; + (*part).int_mimetype = mime_type; + (*part).bytes = decoded_data_bytes as libc::c_int; + dc_param_set((*part).param, 'f' as i32, pathNfilename); + dc_param_set((*part).param, 'm' as i32, raw_mime); + if mime_type == 80i32 { + let mut w: uint32_t = 0i32 as uint32_t; + let mut h: uint32_t = 0i32 as uint32_t; + if 0 != dc_get_filemeta( + decoded_data as *const libc::c_void, + decoded_data_bytes, + &mut w, + &mut h, + ) { + dc_param_set_int((*part).param, 'w' as i32, w as int32_t); + dc_param_set_int((*part).param, 'h' as i32, h as int32_t); + } + } + do_add_single_part(parser, part); + part = 0 as *mut dc_mimepart_t + } + } + free(pathNfilename as *mut libc::c_void); + dc_mimepart_unref(part); +} +unsafe extern "C" 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 + { + dc_param_set_int((*part).param, 'c' as i32, 1i32); + } else if 0 != (*(*parser).e2ee_helper).encrypted { + dc_param_set_int((*part).param, 'e' as i32, 0x2i32); + } + carray_add( + (*parser).parts, + part as *mut libc::c_void, + 0 as *mut libc::c_uint, + ); +} +#[no_mangle] +pub unsafe extern "C" fn mailmime_transfer_decode( + mut mime: *mut mailmime, + mut ret_decoded_data: *mut *const libc::c_char, + mut ret_decoded_data_bytes: *mut size_t, + 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; + /* must not be free()'d */ + let mut decoded_data: *const libc::c_char = 0 as *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; + if mime.is_null() + || ret_decoded_data.is_null() + || ret_decoded_data_bytes.is_null() + || ret_to_mmap_string_unref.is_null() + || !(*ret_decoded_data).is_null() + || *ret_decoded_data_bytes != 0i32 as libc::c_ulong + || !(*ret_to_mmap_string_unref).is_null() + { + return 0i32; + } + mime_data = (*mime).mm_data.mm_single; + if !(*mime).mm_mime_fields.is_null() { + let mut cur: *mut clistiter = 0 as *mut clistiter; + cur = (*(*(*mime).mm_mime_fields).fld_list).first; + while !cur.is_null() { + let mut field: *mut mailmime_field = (if !cur.is_null() { + (*cur).data + } else { + 0 as *mut libc::c_void + }) as *mut mailmime_field; + if !field.is_null() + && (*field).fld_type == MAILMIME_FIELD_TRANSFER_ENCODING as libc::c_int + && !(*field).fld_data.fld_encoding.is_null() + { + mime_transfer_encoding = (*(*field).fld_data.fld_encoding).enc_type; + break; + } else { + cur = if !cur.is_null() { + (*cur).next + } else { + 0 as *mut clistcell_s + } + } + } + } + if mime_transfer_encoding == MAILMIME_MECHANISM_7BIT as libc::c_int + || mime_transfer_encoding == MAILMIME_MECHANISM_8BIT as libc::c_int + || mime_transfer_encoding == MAILMIME_MECHANISM_BINARY as libc::c_int + { + decoded_data = (*mime_data).dt_data.dt_text.dt_data; + decoded_data_bytes = (*mime_data).dt_data.dt_text.dt_length; + if decoded_data.is_null() || decoded_data_bytes <= 0i32 as libc::c_ulong { + return 0i32; + } + } else { + let mut r: libc::c_int = 0; + let mut current_index: size_t = 0i32 as size_t; + r = mailmime_part_parse( + (*mime_data).dt_data.dt_text.dt_data, + (*mime_data).dt_data.dt_text.dt_length, + &mut current_index, + mime_transfer_encoding, + &mut transfer_decoding_buffer, + &mut decoded_data_bytes, + ); + if r != MAILIMF_NO_ERROR as libc::c_int + || transfer_decoding_buffer.is_null() + || decoded_data_bytes <= 0i32 as libc::c_ulong + { + return 0i32; + } + decoded_data = transfer_decoding_buffer + } + *ret_decoded_data = decoded_data; + *ret_decoded_data_bytes = decoded_data_bytes; + *ret_to_mmap_string_unref = transfer_decoding_buffer; + return 1i32; +} +#[no_mangle] +pub unsafe extern "C" fn dc_mimeparser_is_mailinglist_message( + mut mimeparser: *mut dc_mimeparser_t, +) -> libc::c_int { + if mimeparser.is_null() { + return 0i32; + } + if !dc_mimeparser_lookup_field( + mimeparser, + b"List-Id\x00" as *const u8 as *const libc::c_char, + ) + .is_null() + { + return 1i32; + } + let mut precedence: *mut mailimf_optional_field = dc_mimeparser_lookup_optional_field( + mimeparser, + b"Precedence\x00" as *const u8 as *const libc::c_char, + ); + if !precedence.is_null() { + if strcasecmp( + (*precedence).fld_value, + b"list\x00" as *const u8 as *const libc::c_char, + ) == 0i32 + || strcasecmp( + (*precedence).fld_value, + b"bulk\x00" as *const u8 as *const libc::c_char, + ) == 0i32 + { + return 1i32; + } + } + return 0i32; +} +#[no_mangle] +pub unsafe extern "C" 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_from: *const mailimf_from = 0 as *const mailimf_from; + let mut mb: *mut mailimf_mailbox = 0 as *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()) { + /* get From: and check there is exactly one sender */ + fld = mailimf_find_field((*mimeparser).header_root, MAILIMF_FIELD_FROM as libc::c_int); + if !(fld.is_null() + || { + fld_from = (*fld).fld_data.fld_from; + fld_from.is_null() + } + || (*fld_from).frm_mb_list.is_null() + || (*(*fld_from).frm_mb_list).mb_list.is_null() + || (*(*(*fld_from).frm_mb_list).mb_list).count != 1i32) + { + mb = (if !(*(*(*fld_from).frm_mb_list).mb_list).first.is_null() { + (*(*(*(*fld_from).frm_mb_list).mb_list).first).data + } else { + 0 as *mut libc::c_void + }) as *mut mailimf_mailbox; + if !mb.is_null() { + from_addr_norm = dc_addr_normalize((*mb).mb_addr_spec); + recipients = mailimf_get_recipients((*mimeparser).header_root); + if !((*recipients).count != 1i32) { + if !dc_hash_find( + recipients, + from_addr_norm as *const libc::c_void, + strlen(from_addr_norm) as libc::c_int, + ) + .is_null() + { + sender_equals_recipient = 1i32 + } + } + } + } + } + dc_hash_clear(recipients); + free(recipients as *mut libc::c_void); + free(from_addr_norm as *mut libc::c_void); + return sender_equals_recipient; +} +#[no_mangle] +pub unsafe extern "C" 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 libc::c_ulong) as *mut dc_hash_t; + dc_hash_init(recipients, 3i32, 1i32); + let mut cur1: *mut clistiter = 0 as *mut clistiter; + cur1 = (*(*imffields).fld_list).first; + while !cur1.is_null() { + let mut fld: *mut mailimf_field = (if !cur1.is_null() { + (*cur1).data + } 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 addr_list: *mut mailimf_address_list = 0 as *mut mailimf_address_list; + match (*fld).fld_type { + 13 => { + fld_to = (*fld).fld_data.fld_to; + if !fld_to.is_null() { + addr_list = (*fld_to).to_addr_list + } + } + 14 => { + fld_cc = (*fld).fld_data.fld_cc; + if !fld_cc.is_null() { + addr_list = (*fld_cc).cc_addr_list + } + } + _ => {} + } + if !addr_list.is_null() { + let mut cur2: *mut clistiter = 0 as *mut clistiter; + cur2 = (*(*addr_list).ad_list).first; + while !cur2.is_null() { + let mut adr: *mut mailimf_address = (if !cur2.is_null() { + (*cur2).data + } else { + 0 as *mut libc::c_void + }) as *mut mailimf_address; + if !adr.is_null() { + if (*adr).ad_type == MAILIMF_ADDRESS_MAILBOX as libc::c_int { + mailimf_get_recipients__add_addr(recipients, (*adr).ad_data.ad_mailbox); + } 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; + cur3 = (*(*(*group).grp_mb_list).mb_list).first; + while !cur3.is_null() { + mailimf_get_recipients__add_addr( + recipients, + (if !cur3.is_null() { + (*cur3).data + } else { + 0 as *mut libc::c_void + }) as *mut mailimf_mailbox, + ); + cur3 = if !cur3.is_null() { + (*cur3).next + } else { + 0 as *mut clistcell_s + } + } + } + } + } + cur2 = if !cur2.is_null() { + (*cur2).next + } else { + 0 as *mut clistcell_s + } + } + } + cur1 = if !cur1.is_null() { + (*cur1).next + } else { + 0 as *mut clistcell_s + } + } + return recipients; +} +/* ****************************************************************************** + * debug output + ******************************************************************************/ +/* DEBUG_MIME_OUTPUT */ +/* ****************************************************************************** + * low-level-tools for getting a list of all recipients + ******************************************************************************/ +unsafe extern "C" fn mailimf_get_recipients__add_addr( + mut recipients: *mut dc_hash_t, + mut mb: *mut mailimf_mailbox, +) { + if !mb.is_null() { + let mut addr_norm: *mut libc::c_char = dc_addr_normalize((*mb).mb_addr_spec); + dc_hash_insert( + recipients, + addr_norm as *const libc::c_void, + strlen(addr_norm) as libc::c_int, + 1i32 as *mut libc::c_void, + ); + free(addr_norm as *mut libc::c_void); + }; +} +/*the result is a pointer to mime, must not be freed*/ +#[no_mangle] +pub unsafe extern "C" fn mailimf_find_field( + mut header: *mut mailimf_fields, + mut wanted_fld_type: libc::c_int, +) -> *mut mailimf_field { + if header.is_null() || (*header).fld_list.is_null() { + return 0 as *mut mailimf_field; + } + let mut cur1: *mut clistiter = (*(*header).fld_list).first; + while !cur1.is_null() { + let mut field: *mut mailimf_field = (if !cur1.is_null() { + (*cur1).data + } else { + 0 as *mut libc::c_void + }) as *mut mailimf_field; + if !field.is_null() { + if (*field).fld_type == wanted_fld_type { + return field; + } + } + cur1 = if !cur1.is_null() { + (*cur1).next + } else { + 0 as *mut clistcell_s + } + } + return 0 as *mut mailimf_field; +} +#[no_mangle] +pub unsafe extern "C" 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; + if mimeparser.is_null() + || (*mimeparser).parts.is_null() + || carray_count((*mimeparser).parts) <= 0i32 as libc::c_uint + { + return; + } + part = carray_get((*mimeparser).parts, 0i32 as libc::c_uint) as *mut dc_mimepart_t; + (*part).type_0 = 10i32; + free((*part).msg as *mut libc::c_void); + (*part).msg = dc_mprintf(b"[%s]\x00" as *const u8 as *const libc::c_char, error_msg); + i = 1i32; + while (i as libc::c_uint) < carray_count((*mimeparser).parts) { + part = carray_get((*mimeparser).parts, i as libc::c_uint) as *mut dc_mimepart_t; + if !part.is_null() { + dc_mimepart_unref(part); + } + i += 1 + } + carray_set_size((*mimeparser).parts, 1i32 as libc::c_uint); +} +/*the result is a pointer to mime, must not be freed*/ +#[no_mangle] +pub unsafe extern "C" fn mailmime_find_mailimf_fields( + mut mime: *mut mailmime, +) -> *mut mailimf_fields { + if mime.is_null() { + return 0 as *mut mailimf_fields; + } + match (*mime).mm_type { + 2 => { + let mut cur: *mut clistiter = (*(*mime).mm_data.mm_multipart.mm_mp_list).first; + while !cur.is_null() { + let mut header: *mut mailimf_fields = mailmime_find_mailimf_fields( + (if !cur.is_null() { + (*cur).data + } else { + 0 as *mut libc::c_void + }) as *mut mailmime, + ); + if !header.is_null() { + return header; + } + cur = if !cur.is_null() { + (*cur).next + } else { + 0 as *mut clistcell_s + } + } + } + 3 => return (*mime).mm_data.mm_message.mm_fields, + _ => {} + } + return 0 as *mut mailimf_fields; +} +#[no_mangle] +pub unsafe extern "C" fn mailimf_find_optional_field( + mut header: *mut mailimf_fields, + mut wanted_fld_name: *const libc::c_char, +) -> *mut mailimf_optional_field { + if header.is_null() || (*header).fld_list.is_null() { + return 0 as *mut mailimf_optional_field; + } + let mut cur1: *mut clistiter = (*(*header).fld_list).first; + while !cur1.is_null() { + let mut field: *mut mailimf_field = (if !cur1.is_null() { + (*cur1).data + } else { + 0 as *mut libc::c_void + }) as *mut mailimf_field; + if !field.is_null() && (*field).fld_type == MAILIMF_FIELD_OPTIONAL_FIELD as libc::c_int { + let mut optional_field: *mut mailimf_optional_field = + (*field).fld_data.fld_optional_field; + if !optional_field.is_null() + && !(*optional_field).fld_name.is_null() + && !(*optional_field).fld_value.is_null() + && strcasecmp((*optional_field).fld_name, wanted_fld_name) == 0i32 + { + return optional_field; + } + } + cur1 = if !cur1.is_null() { + (*cur1).next + } else { + 0 as *mut clistcell_s + } + } + return 0 as *mut mailimf_optional_field; +} diff --git a/src/dc_move.rs b/src/dc_move.rs new file mode 100644 index 000000000..741e20776 --- /dev/null +++ b/src/dc_move.rs @@ -0,0 +1,858 @@ +use c2rust_bitfields::BitfieldStruct; +use libc; +extern "C" { + pub type mailstream_cancel; + pub type sqlite3; + pub type sqlite3_stmt; + #[no_mangle] + fn dc_msg_unref(_: *mut dc_msg_t); + #[no_mangle] + fn dc_msg_is_setupmessage(_: *const dc_msg_t) -> libc::c_int; + #[no_mangle] + fn sqlite3_finalize(pStmt: *mut sqlite3_stmt) -> libc::c_int; + #[no_mangle] + fn dc_sqlite3_get_config_int( + _: *mut dc_sqlite3_t, + key: *const libc::c_char, + def: int32_t, + ) -> int32_t; + #[no_mangle] + fn dc_msg_new_load(_: *mut dc_context_t, id: uint32_t) -> *mut dc_msg_t; + #[no_mangle] + fn dc_update_msg_move_state( + _: *mut dc_context_t, + rfc724_mid: *const libc::c_char, + _: dc_move_state_t, + ); + #[no_mangle] + fn dc_job_add( + _: *mut dc_context_t, + action: libc::c_int, + foreign_id: libc::c_int, + param: *const libc::c_char, + delay: libc::c_int, + ); + #[no_mangle] + fn dc_is_mvbox(_: *mut dc_context_t, folder: *const libc::c_char) -> libc::c_int; + #[no_mangle] + fn dc_is_sentbox(_: *mut dc_context_t, folder: *const libc::c_char) -> libc::c_int; + #[no_mangle] + fn dc_is_inbox(_: *mut dc_context_t, folder: *const libc::c_char) -> libc::c_int; +} +pub type __darwin_size_t = libc::c_ulong; +pub type __darwin_ssize_t = libc::c_long; +pub type __darwin_time_t = libc::c_long; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_cond_t { + pub __sig: libc::c_long, + pub __opaque: [libc::c_char; 40], +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_mutex_t { + pub __sig: libc::c_long, + pub __opaque: [libc::c_char; 56], +} +pub type __darwin_pthread_cond_t = _opaque_pthread_cond_t; +pub type __darwin_pthread_mutex_t = _opaque_pthread_mutex_t; +pub type int32_t = libc::c_int; +pub type uintptr_t = libc::c_ulong; +pub type size_t = __darwin_size_t; +pub type uint8_t = libc::c_uchar; +pub type uint32_t = libc::c_uint; +pub type ssize_t = __darwin_ssize_t; +pub type time_t = __darwin_time_t; +pub type pthread_cond_t = __darwin_pthread_cond_t; +pub type pthread_mutex_t = __darwin_pthread_mutex_t; +#[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; +#[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) -> (); +#[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; +#[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, + 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 { + 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_capability_data { + pub cap_list: *mut clist, +} +#[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_0, + 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_0 { + 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 extern "C" 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_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, +} +#[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_1, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed_1 { + pub ft_fetch_att: *mut mailimap_fetch_att, + pub ft_fetch_att_list: *mut clist, +} +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 unnamed_2 { + 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, +} +/* define DC_USE_RPGP to enable use of rPGP instead of netpgp where available; +preferrably, this should be done in the project configuration currently */ +//#define DC_USE_RPGP 1 +/* Includes that are used frequently. This file may also be used to create predefined headers. */ +/* * Structure behind dc_context_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_context { + pub magic: uint32_t, + pub userdata: *mut libc::c_void, + pub dbfile: *mut libc::c_char, + pub blobdir: *mut libc::c_char, + pub sql: *mut dc_sqlite3_t, + pub inbox: *mut dc_imap_t, + pub inboxidle_condmutex: pthread_mutex_t, + pub perform_inbox_jobs_needed: libc::c_int, + pub probe_imap_network: libc::c_int, + pub sentbox_thread: dc_jobthread_t, + pub mvbox_thread: dc_jobthread_t, + pub smtp: *mut dc_smtp_t, + pub smtpidle_cond: pthread_cond_t, + pub smtpidle_condmutex: pthread_mutex_t, + pub smtpidle_condflag: libc::c_int, + pub smtp_suspended: libc::c_int, + pub smtp_doing_jobs: libc::c_int, + pub perform_smtp_jobs_needed: libc::c_int, + pub probe_smtp_network: libc::c_int, + pub oauth2_critical: pthread_mutex_t, + 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 type dc_lot_t = _dc_lot; +/* * Structure behind dc_lot_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_lot { + pub magic: uint32_t, + pub text1_meaning: libc::c_int, + pub text1: *mut libc::c_char, + pub text2: *mut libc::c_char, + pub timestamp: time_t, + pub state: libc::c_int, + pub id: uint32_t, + pub fingerprint: *mut libc::c_char, + pub invitenumber: *mut libc::c_char, + pub auth: *mut libc::c_char, +} +/* * + * 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 = Option< + unsafe extern "C" fn( + _: *mut dc_context_t, + _: libc::c_int, + _: uintptr_t, + _: uintptr_t, + ) -> uintptr_t, +>; +/* * + * @mainpage Getting started + * + * This document describes how to handle the Delta Chat core library. + * For general information about Delta Chat itself, + * see and . + * + * Let's start. + * + * First of all, you have to **define an event-handler-function** + * that is called by the library on specific events + * (eg. when the configuration is done or when fresh messages arrive). + * With this function you can create a Delta Chat context then: + * + * ~~~ + * #include + * + * uintptr_t event_handler_func(dc_context_t* context, int event, + * uintptr_t data1, uintptr_t data2) + * { + * return 0; // for unhandled events, it is always safe to return 0 + * } + * + * dc_context_t* context = dc_context_new(event_handler_func, NULL, NULL); + * ~~~ + * + * After that, you should make sure, + * sending and receiving jobs are processed as needed. + * For this purpose, you have to **create two threads:** + * + * ~~~ + * #include + * + * void* imap_thread_func(void* context) + * { + * while (true) { + * dc_perform_imap_jobs(context); + * dc_perform_imap_fetch(context); + * dc_perform_imap_idle(context); + * } + * } + * + * void* smtp_thread_func(void* context) + * { + * while (true) { + * dc_perform_smtp_jobs(context); + * dc_perform_smtp_idle(context); + * } + * } + * + * static pthread_t imap_thread, smtp_thread; + * pthread_create(&imap_thread, NULL, imap_thread_func, context); + * pthread_create(&smtp_thread, NULL, smtp_thread_func, context); + * ~~~ + * + * The example above uses "pthreads", + * however, you can also use anything else for thread handling. + * NB: The deltachat-core library itself does not create any threads on its own, + * however, functions, unless stated otherwise, are thread-safe. + * + * After that you can **define and open a database.** + * The database is a normal sqlite-file and is created as needed: + * + * ~~~ + * dc_open(context, "example.db", NULL); + * ~~~ + * + * Now you can **configure the context:** + * + * ~~~ + * // use some real test credentials here + * dc_set_config(context, "addr", "alice@example.org"); + * dc_set_config(context, "mail_pw", "***"); + * dc_configure(context); + * ~~~ + * + * dc_configure() returns immediately, the configuration itself may take a while + * and is done by a job in the imap-thread you've defined above. + * Once done, the #DC_EVENT_CONFIGURE_PROGRESS reports success + * to the event_handler_func() that is also defined above. + * + * The configuration result is saved in the database, + * on subsequent starts it is not needed to call dc_configure() + * (you can check this using dc_is_configured()). + * + * Now you can **send the first message:** + * + * ~~~ + * // use a real testing address here + * uint32_t contact_id = dc_create_contact(context, NULL, "bob@example.org"); + * uint32_t chat_id = dc_create_chat_by_contact_id(context, contact_id); + * + * dc_send_text_msg(context, chat_id, "Hi, here is my first message!"); + * ~~~ + * + * dc_send_text_msg() returns immediately; + * the sending itself is done by a job in the smtp-thread you've defined above. + * If you check the testing address (bob) + * and you should have received a normal email. + * Answer this email in any email program with "Got it!" + * and the imap-thread you've create above will **receive the message**. + * + * You can then **list all messages** of a chat as follow: + * + * ~~~ + * dc_array_t* msglist = dc_get_chat_msgs(context, chat_id, 0, 0); + * for (int i = 0; i < dc_array_get_cnt(msglist); i++) + * { + * uint32_t msg_id = dc_array_get_id(msglist, i); + * dc_msg_t* msg = dc_get_msg(context, msg_id); + * char* text = dc_msg_get_text(msg); + * + * printf("Message %i: %s\n", i+1, text); + * + * free(text); + * dc_msg_unref(msg); + * } + * dc_array_unref(msglist); + * ~~~ + * + * This will output the following two lines: + * + * ~~~ + * Message 1: Hi, here is my first message! + * Message 2: Got it! + * ~~~ + * + * + * ## Class reference + * + * For a class reference, see the "Classes" link atop. + * + * + * ## Further hints + * + * Here are some additional, unsorted hints that may be useful. + * + * - For `get`-functions, you have to unref the return value in some way. + * + * - Strings in function arguments or return values are usually UTF-8 encoded. + * + * - The issue-tracker for the core library is here: + * + * + * The following points are important mainly + * for the authors of the library itself: + * + * - For indentation, use tabs. + * Alignments that are not placed at the beginning of a line + * should be done with spaces. + * + * - For padding between functions, + * classes etc. use 2 empty lines + * + * - Source files are encoded as UTF-8 with Unix line endings + * (a simple `LF`, `0x0A` or `\n`) + * + * If you need further assistance, + * please do not hesitate to contact us + * through the channels shown at https://delta.chat/en/contribute + * + * Please keep in mind, that your derived work + * must respect the Mozilla Public License 2.0 of libdeltachat + * and the respective licenses of the libraries libdeltachat links with. + * + * See you. + */ +/* * + * @class dc_context_t + * + * An object representing a single account. + * + * Each account is linked to an IMAP/SMTP account and uses a separate + * SQLite database for offline functionality and for account-related + * settings. + */ +pub type dc_context_t = _dc_context; +/* ** library-private **********************************************************/ +pub type dc_smtp_t = _dc_smtp; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_smtp { + 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 error: *mut libc::c_char, + pub error_etpan: libc::c_int, +} +pub type dc_jobthread_t = _dc_jobthread; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_jobthread { + 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, + 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, +} +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_imap { + 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 type dc_receive_imf_t = Option< + unsafe extern "C" 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_imap_t = _dc_imap; +pub type dc_precheck_imf_t = Option< + unsafe extern "C" 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< + unsafe extern "C" fn(_: *mut dc_imap_t, _: *const libc::c_char, _: *const libc::c_char) -> (), +>; +pub type dc_get_config_t = Option< + unsafe extern "C" fn( + _: *mut dc_imap_t, + _: *const libc::c_char, + _: *const libc::c_char, + ) -> *mut libc::c_char, +>; +/* ** library-private **********************************************************/ +pub type dc_sqlite3_t = _dc_sqlite3; +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_sqlite3 { + pub cobj: *mut sqlite3, + pub context: *mut dc_context_t, +} +pub type dc_param_t = _dc_param; +/* * + * @class dc_param_t + * + * An object for handling key=value parameter lists; for the key, curently only + * a single character is allowed. + * + * The object is used eg. by dc_chat_t or dc_msg_t, for readable paramter names, + * these classes define some DC_PARAM_* constantats. + * + * Only for library-internal use. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_param { + pub packed: *mut libc::c_char, +} +/* * the structure behind dc_msg_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_msg { + pub magic: uint32_t, + pub id: uint32_t, + pub from_id: uint32_t, + pub to_id: uint32_t, + pub chat_id: uint32_t, + pub move_state: dc_move_state_t, + pub type_0: libc::c_int, + pub state: libc::c_int, + pub hidden: libc::c_int, + pub timestamp_sort: time_t, + pub timestamp_sent: time_t, + pub timestamp_rcvd: time_t, + pub text: *mut libc::c_char, + pub context: *mut 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, + pub server_uid: uint32_t, + pub is_dc_message: libc::c_int, + pub starred: libc::c_int, + pub chat_blocked: libc::c_int, + pub location_id: uint32_t, + pub param: *mut dc_param_t, +} +pub type dc_move_state_t = libc::c_uint; +pub const DC_MOVE_STATE_MOVING: dc_move_state_t = 3; +pub const DC_MOVE_STATE_STAY: dc_move_state_t = 2; +pub const DC_MOVE_STATE_PENDING: dc_move_state_t = 1; +pub const DC_MOVE_STATE_UNDEFINED: dc_move_state_t = 0; +pub type dc_msg_t = _dc_msg; +#[no_mangle] +pub unsafe extern "C" fn dc_do_heuristics_moves( + mut context: *mut dc_context_t, + mut folder: *const libc::c_char, + mut msg_id: uint32_t, +) { + // for already seen messages, folder may be different from msg->folder + 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, + b"mvbox_move\x00" as *const u8 as *const libc::c_char, + 1i32, + ) == 0i32) + { + if !(0 == dc_is_inbox(context, folder) && 0 == dc_is_sentbox(context, folder)) { + msg = dc_msg_new_load(context, msg_id); + if !(0 != dc_msg_is_setupmessage(msg)) { + // do not move setup messages; + // there may be a non-delta device that wants to handle it + if 0 != dc_is_mvbox(context, folder) { + dc_update_msg_move_state(context, (*msg).rfc724_mid, DC_MOVE_STATE_STAY); + } else if 0 != (*msg).is_dc_message { + dc_job_add( + context, + 200i32, + (*msg).id as libc::c_int, + 0 as *const libc::c_char, + 0i32, + ); + dc_update_msg_move_state(context, (*msg).rfc724_mid, DC_MOVE_STATE_MOVING); + } + } + } + } + sqlite3_finalize(stmt); + dc_msg_unref(msg); +} diff --git a/src/dc_msg.rs b/src/dc_msg.rs new file mode 100644 index 000000000..6873d595b --- /dev/null +++ b/src/dc_msg.rs @@ -0,0 +1,2585 @@ +use c2rust_bitfields::BitfieldStruct; +use libc; +extern "C" { + pub type mailstream_cancel; + pub type sqlite3; + pub type sqlite3_stmt; + #[no_mangle] + fn calloc(_: libc::c_ulong, _: libc::c_ulong) -> *mut libc::c_void; + #[no_mangle] + fn free(_: *mut libc::c_void); + #[no_mangle] + fn exit(_: libc::c_int) -> !; + #[no_mangle] + fn strcmp(_: *const libc::c_char, _: *const libc::c_char) -> libc::c_int; + #[no_mangle] + fn dc_get_chat(_: *mut dc_context_t, chat_id: uint32_t) -> *mut dc_chat_t; + /* * + * @class dc_contact_t + * + * An object representing a single contact in memory. + * The contact object is not updated. + * If you want an update, you have to recreate the object. + * + * The library makes sure + * only to use names _authorized_ by the contact in `To:` or `Cc:`. + * _Given-names _as "Daddy" or "Honey" are not used there. + * For this purpose, internally, two names are tracked - + * authorized-name and given-name. + * By default, these names are equal, + * but functions working with contact names + * (eg. dc_contact_get_name(), dc_contact_get_display_name(), + * dc_contact_get_name_n_addr(), dc_contact_get_first_name(), + * dc_create_contact() or dc_add_address_book()) + * only affect the given-name. + */ + #[no_mangle] + fn dc_contact_new(_: *mut dc_context_t) -> *mut dc_contact_t; + #[no_mangle] + fn dc_contact_unref(_: *mut dc_contact_t); + /* library-private */ + #[no_mangle] + fn dc_param_new() -> *mut dc_param_t; + #[no_mangle] + fn dc_param_unref(_: *mut dc_param_t); + #[no_mangle] + fn dc_param_set_packed(_: *mut dc_param_t, _: *const libc::c_char); + #[no_mangle] + fn sqlite3_finalize(pStmt: *mut sqlite3_stmt) -> libc::c_int; + #[no_mangle] + fn dc_strbuilder_catf(_: *mut dc_strbuilder_t, format: *const libc::c_char, _: ...); + #[no_mangle] + fn dc_strbuilder_cat(_: *mut dc_strbuilder_t, text: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn dc_param_get_int(_: *const dc_param_t, key: libc::c_int, def: int32_t) -> int32_t; + #[no_mangle] + fn dc_mprintf(format: *const libc::c_char, _: ...) -> *mut libc::c_char; + /* string tools */ + #[no_mangle] + fn dc_strdup(_: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn dc_get_filesuffix_lc(pathNfilename: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn dc_param_get( + _: *const dc_param_t, + key: libc::c_int, + def: *const libc::c_char, + ) -> *mut libc::c_char; + #[no_mangle] + fn dc_get_filebytes(_: *mut dc_context_t, pathNfilename: *const libc::c_char) -> uint64_t; + #[no_mangle] + fn dc_get_abs_path( + _: *mut dc_context_t, + pathNfilename: *const libc::c_char, + ) -> *mut libc::c_char; + #[no_mangle] + fn dc_contact_get_name_n_addr(_: *const dc_contact_t) -> *mut libc::c_char; + #[no_mangle] + fn sqlite3_column_int64(_: *mut sqlite3_stmt, iCol: libc::c_int) -> sqlite3_int64; + /* From: of incoming messages of unknown sender */ + /* Cc: of incoming messages of unknown sender */ + /* To: of incoming messages of unknown sender */ + /* address scanned but not verified */ + /* Reply-To: of incoming message of known sender */ + /* Cc: of incoming message of known sender */ + /* additional To:'s of incoming message of known sender */ + /* a chat was manually created for this user, but no message yet sent */ + /* message sent by us */ + /* message sent by us */ + /* message sent by us */ + /* internal use */ + /* address is in our address book */ + /* set on Alice's side for contacts like Bob that have scanned the QR code offered by her. Only means the contact has once been established using the "securejoin" procedure in the past, getting the current key verification status requires calling dc_contact_is_verified() ! */ + /* set on Bob's side for contacts scanned and verified from a QR code. Only means the contact has once been established using the "securejoin" procedure in the past, getting the current key verification status requires calling dc_contact_is_verified() ! */ + /* contact added mannually by dc_create_contact(), this should be the largets origin as otherwise the user cannot modify the names */ + /* 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 */ + #[no_mangle] + fn dc_contact_load_from_db( + _: *mut dc_contact_t, + _: *mut dc_sqlite3_t, + contact_id: uint32_t, + ) -> libc::c_int; + #[no_mangle] + fn dc_timestamp_to_str(_: time_t) -> *mut libc::c_char; + #[no_mangle] + fn sqlite3_step(_: *mut sqlite3_stmt) -> libc::c_int; + #[no_mangle] + fn sqlite3_bind_int(_: *mut sqlite3_stmt, _: libc::c_int, _: libc::c_int) -> libc::c_int; + /* tools, these functions are compatible to the corresponding sqlite3_* functions */ + #[no_mangle] + fn dc_sqlite3_prepare(_: *mut dc_sqlite3_t, sql: *const libc::c_char) -> *mut sqlite3_stmt; + #[no_mangle] + fn dc_truncate_str(_: *mut libc::c_char, approx_characters: libc::c_int); + #[no_mangle] + fn dc_trim(_: *mut libc::c_char); + #[no_mangle] + fn sqlite3_column_text(_: *mut sqlite3_stmt, iCol: libc::c_int) -> *const libc::c_uchar; + #[no_mangle] + fn dc_truncate_n_unwrap_str( + _: *mut libc::c_char, + approx_characters: libc::c_int, + do_unwrap: libc::c_int, + ); + #[no_mangle] + fn sqlite3_column_int(_: *mut sqlite3_stmt, iCol: libc::c_int) -> libc::c_int; + #[no_mangle] + fn dc_strbuilder_init(_: *mut dc_strbuilder_t, init_bytes: libc::c_int); + #[no_mangle] + fn dc_strdup_keep_null(_: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn dc_job_add( + _: *mut dc_context_t, + action: libc::c_int, + foreign_id: libc::c_int, + param: *const libc::c_char, + delay: libc::c_int, + ); + #[no_mangle] + fn dc_job_kill_action(_: *mut dc_context_t, action: libc::c_int); + #[no_mangle] + fn dc_sqlite3_commit(_: *mut dc_sqlite3_t); + #[no_mangle] + fn dc_sqlite3_begin_transaction(_: *mut dc_sqlite3_t); + #[no_mangle] + fn dc_sqlite3_rollback(_: *mut dc_sqlite3_t); + #[no_mangle] + fn dc_log_info(_: *mut dc_context_t, data1: libc::c_int, msg: *const libc::c_char, _: ...); + #[no_mangle] + fn sqlite3_reset(pStmt: *mut sqlite3_stmt) -> libc::c_int; + #[no_mangle] + fn dc_get_contact(_: *mut dc_context_t, contact_id: uint32_t) -> *mut dc_contact_t; + #[no_mangle] + fn dc_chat_unref(_: *mut dc_chat_t); + #[no_mangle] + fn dc_get_filename(pathNfilename: *const libc::c_char) -> *mut libc::c_char; + /* * + * @class dc_lot_t + * + * An object containing a set of values. + * The meaning of the values is defined by the function returning the object. + * Lot objects are created + * eg. by dc_chatlist_get_summary() or dc_msg_get_summary(). + * + * NB: _Lot_ is used in the meaning _heap_ here. + */ + #[no_mangle] + fn dc_lot_new() -> *mut dc_lot_t; + /* library-internal */ + /* in practice, the user additionally cuts the string himself pixel-accurate */ + #[no_mangle] + fn dc_lot_fill( + _: *mut dc_lot_t, + _: *const dc_msg_t, + _: *const dc_chat_t, + _: *const dc_contact_t, + _: *mut dc_context_t, + ); + /* Return the string with the given ID by calling DC_EVENT_GET_STRING. + The result must be free()'d! */ + #[no_mangle] + fn dc_stock_str(_: *mut dc_context_t, id: libc::c_int) -> *mut libc::c_char; + #[no_mangle] + fn dc_gm2local_offset() -> libc::c_long; + #[no_mangle] + fn dc_split_armored_data( + buf: *mut libc::c_char, + ret_headerline: *mut *const libc::c_char, + ret_setupcodebegin: *mut *const libc::c_char, + ret_preferencrypt: *mut *const libc::c_char, + ret_base64: *mut *const libc::c_char, + ) -> libc::c_int; + #[no_mangle] + fn dc_read_file( + _: *mut dc_context_t, + pathNfilename: *const libc::c_char, + buf: *mut *mut libc::c_void, + buf_bytes: *mut size_t, + ) -> libc::c_int; + #[no_mangle] + fn dc_param_set(_: *mut dc_param_t, key: libc::c_int, value: *const libc::c_char); + #[no_mangle] + fn dc_param_set_int(_: *mut dc_param_t, key: libc::c_int, value: int32_t); + #[no_mangle] + fn sqlite3_bind_text( + _: *mut sqlite3_stmt, + _: libc::c_int, + _: *const libc::c_char, + _: libc::c_int, + _: Option ()>, + ) -> libc::c_int; + #[no_mangle] + fn sqlite3_bind_int64(_: *mut sqlite3_stmt, _: libc::c_int, _: sqlite3_int64) -> libc::c_int; + #[no_mangle] + fn dc_sqlite3_log_error(_: *mut dc_sqlite3_t, msg: *const libc::c_char, _: ...); + #[no_mangle] + fn dc_get_chat_contact_cnt(_: *mut dc_context_t, chat_id: uint32_t) -> libc::c_int; + #[no_mangle] + fn dc_log_error(_: *mut dc_context_t, data1: libc::c_int, msg: *const libc::c_char, _: ...); +} +pub type __darwin_size_t = libc::c_ulong; +pub type __darwin_ssize_t = libc::c_long; +pub type __darwin_time_t = libc::c_long; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_cond_t { + pub __sig: libc::c_long, + pub __opaque: [libc::c_char; 40], +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_mutex_t { + pub __sig: libc::c_long, + pub __opaque: [libc::c_char; 56], +} +pub type __darwin_pthread_cond_t = _opaque_pthread_cond_t; +pub type __darwin_pthread_mutex_t = _opaque_pthread_mutex_t; +pub type int32_t = libc::c_int; +pub type uintptr_t = libc::c_ulong; +pub type size_t = __darwin_size_t; +pub type uint8_t = libc::c_uchar; +pub type uint32_t = libc::c_uint; +pub type uint64_t = libc::c_ulonglong; +pub type ssize_t = __darwin_ssize_t; +pub type time_t = __darwin_time_t; +pub type pthread_cond_t = __darwin_pthread_cond_t; +pub type pthread_mutex_t = __darwin_pthread_mutex_t; +#[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; +#[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) -> (); +#[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; +#[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, + 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 { + 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_capability_data { + pub cap_list: *mut clist, +} +#[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_0, + 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_0 { + 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 extern "C" 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_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, +} +#[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_1, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed_1 { + pub ft_fetch_att: *mut mailimap_fetch_att, + pub ft_fetch_att_list: *mut clist, +} +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 unnamed_2 { + 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, +} +/* define DC_USE_RPGP to enable use of rPGP instead of netpgp where available; +preferrably, this should be done in the project configuration currently */ +//#define DC_USE_RPGP 1 +/* Includes that are used frequently. This file may also be used to create predefined headers. */ +/* * Structure behind dc_context_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_context { + pub magic: uint32_t, + pub userdata: *mut libc::c_void, + pub dbfile: *mut libc::c_char, + pub blobdir: *mut libc::c_char, + pub sql: *mut dc_sqlite3_t, + pub inbox: *mut dc_imap_t, + pub inboxidle_condmutex: pthread_mutex_t, + pub perform_inbox_jobs_needed: libc::c_int, + pub probe_imap_network: libc::c_int, + pub sentbox_thread: dc_jobthread_t, + pub mvbox_thread: dc_jobthread_t, + pub smtp: *mut dc_smtp_t, + pub smtpidle_cond: pthread_cond_t, + pub smtpidle_condmutex: pthread_mutex_t, + pub smtpidle_condflag: libc::c_int, + pub smtp_suspended: libc::c_int, + pub smtp_doing_jobs: libc::c_int, + pub perform_smtp_jobs_needed: libc::c_int, + pub probe_smtp_network: libc::c_int, + pub oauth2_critical: pthread_mutex_t, + 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 type dc_lot_t = _dc_lot; +/* * Structure behind dc_lot_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_lot { + pub magic: uint32_t, + pub text1_meaning: libc::c_int, + pub text1: *mut libc::c_char, + pub text2: *mut libc::c_char, + pub timestamp: time_t, + pub state: libc::c_int, + pub id: uint32_t, + pub fingerprint: *mut libc::c_char, + pub invitenumber: *mut libc::c_char, + pub auth: *mut libc::c_char, +} +/* * + * 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 = Option< + unsafe extern "C" fn( + _: *mut dc_context_t, + _: libc::c_int, + _: uintptr_t, + _: uintptr_t, + ) -> uintptr_t, +>; +/* * + * @mainpage Getting started + * + * This document describes how to handle the Delta Chat core library. + * For general information about Delta Chat itself, + * see and . + * + * Let's start. + * + * First of all, you have to **define an event-handler-function** + * that is called by the library on specific events + * (eg. when the configuration is done or when fresh messages arrive). + * With this function you can create a Delta Chat context then: + * + * ~~~ + * #include + * + * uintptr_t event_handler_func(dc_context_t* context, int event, + * uintptr_t data1, uintptr_t data2) + * { + * return 0; // for unhandled events, it is always safe to return 0 + * } + * + * dc_context_t* context = dc_context_new(event_handler_func, NULL, NULL); + * ~~~ + * + * After that, you should make sure, + * sending and receiving jobs are processed as needed. + * For this purpose, you have to **create two threads:** + * + * ~~~ + * #include + * + * void* imap_thread_func(void* context) + * { + * while (true) { + * dc_perform_imap_jobs(context); + * dc_perform_imap_fetch(context); + * dc_perform_imap_idle(context); + * } + * } + * + * void* smtp_thread_func(void* context) + * { + * while (true) { + * dc_perform_smtp_jobs(context); + * dc_perform_smtp_idle(context); + * } + * } + * + * static pthread_t imap_thread, smtp_thread; + * pthread_create(&imap_thread, NULL, imap_thread_func, context); + * pthread_create(&smtp_thread, NULL, smtp_thread_func, context); + * ~~~ + * + * The example above uses "pthreads", + * however, you can also use anything else for thread handling. + * NB: The deltachat-core library itself does not create any threads on its own, + * however, functions, unless stated otherwise, are thread-safe. + * + * After that you can **define and open a database.** + * The database is a normal sqlite-file and is created as needed: + * + * ~~~ + * dc_open(context, "example.db", NULL); + * ~~~ + * + * Now you can **configure the context:** + * + * ~~~ + * // use some real test credentials here + * dc_set_config(context, "addr", "alice@example.org"); + * dc_set_config(context, "mail_pw", "***"); + * dc_configure(context); + * ~~~ + * + * dc_configure() returns immediately, the configuration itself may take a while + * and is done by a job in the imap-thread you've defined above. + * Once done, the #DC_EVENT_CONFIGURE_PROGRESS reports success + * to the event_handler_func() that is also defined above. + * + * The configuration result is saved in the database, + * on subsequent starts it is not needed to call dc_configure() + * (you can check this using dc_is_configured()). + * + * Now you can **send the first message:** + * + * ~~~ + * // use a real testing address here + * uint32_t contact_id = dc_create_contact(context, NULL, "bob@example.org"); + * uint32_t chat_id = dc_create_chat_by_contact_id(context, contact_id); + * + * dc_send_text_msg(context, chat_id, "Hi, here is my first message!"); + * ~~~ + * + * dc_send_text_msg() returns immediately; + * the sending itself is done by a job in the smtp-thread you've defined above. + * If you check the testing address (bob) + * and you should have received a normal email. + * Answer this email in any email program with "Got it!" + * and the imap-thread you've create above will **receive the message**. + * + * You can then **list all messages** of a chat as follow: + * + * ~~~ + * dc_array_t* msglist = dc_get_chat_msgs(context, chat_id, 0, 0); + * for (int i = 0; i < dc_array_get_cnt(msglist); i++) + * { + * uint32_t msg_id = dc_array_get_id(msglist, i); + * dc_msg_t* msg = dc_get_msg(context, msg_id); + * char* text = dc_msg_get_text(msg); + * + * printf("Message %i: %s\n", i+1, text); + * + * free(text); + * dc_msg_unref(msg); + * } + * dc_array_unref(msglist); + * ~~~ + * + * This will output the following two lines: + * + * ~~~ + * Message 1: Hi, here is my first message! + * Message 2: Got it! + * ~~~ + * + * + * ## Class reference + * + * For a class reference, see the "Classes" link atop. + * + * + * ## Further hints + * + * Here are some additional, unsorted hints that may be useful. + * + * - For `get`-functions, you have to unref the return value in some way. + * + * - Strings in function arguments or return values are usually UTF-8 encoded. + * + * - The issue-tracker for the core library is here: + * + * + * The following points are important mainly + * for the authors of the library itself: + * + * - For indentation, use tabs. + * Alignments that are not placed at the beginning of a line + * should be done with spaces. + * + * - For padding between functions, + * classes etc. use 2 empty lines + * + * - Source files are encoded as UTF-8 with Unix line endings + * (a simple `LF`, `0x0A` or `\n`) + * + * If you need further assistance, + * please do not hesitate to contact us + * through the channels shown at https://delta.chat/en/contribute + * + * Please keep in mind, that your derived work + * must respect the Mozilla Public License 2.0 of libdeltachat + * and the respective licenses of the libraries libdeltachat links with. + * + * See you. + */ +/* * + * @class dc_context_t + * + * An object representing a single account. + * + * Each account is linked to an IMAP/SMTP account and uses a separate + * SQLite database for offline functionality and for account-related + * settings. + */ +pub type dc_context_t = _dc_context; +/* ** library-private **********************************************************/ +pub type dc_smtp_t = _dc_smtp; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_smtp { + 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 error: *mut libc::c_char, + pub error_etpan: libc::c_int, +} +pub type dc_jobthread_t = _dc_jobthread; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_jobthread { + 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, + 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, +} +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_imap { + 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 type dc_receive_imf_t = Option< + unsafe extern "C" 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_imap_t = _dc_imap; +pub type dc_precheck_imf_t = Option< + unsafe extern "C" 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< + unsafe extern "C" fn(_: *mut dc_imap_t, _: *const libc::c_char, _: *const libc::c_char) -> (), +>; +pub type dc_get_config_t = Option< + unsafe extern "C" fn( + _: *mut dc_imap_t, + _: *const libc::c_char, + _: *const libc::c_char, + ) -> *mut libc::c_char, +>; +/* ** library-private **********************************************************/ +pub type dc_sqlite3_t = _dc_sqlite3; +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_sqlite3 { + pub cobj: *mut sqlite3, + pub context: *mut dc_context_t, +} +/* values for the chats.blocked database field */ +/* * the structure behind dc_chat_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_chat { + 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 grpid: *mut libc::c_char, + pub blocked: libc::c_int, + pub param: *mut dc_param_t, + pub gossiped_timestamp: time_t, + pub is_sending_locations: libc::c_int, +} +pub type dc_param_t = _dc_param; +/* * + * @class dc_param_t + * + * An object for handling key=value parameter lists; for the key, curently only + * a single character is allowed. + * + * The object is used eg. by dc_chat_t or dc_msg_t, for readable paramter names, + * these classes define some DC_PARAM_* constantats. + * + * Only for library-internal use. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_param { + pub packed: *mut libc::c_char, +} +pub type dc_chat_t = _dc_chat; +/* * the structure behind dc_msg_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_msg { + pub magic: uint32_t, + pub id: uint32_t, + pub from_id: uint32_t, + pub to_id: uint32_t, + pub chat_id: uint32_t, + pub move_state: dc_move_state_t, + pub type_0: libc::c_int, + pub state: libc::c_int, + pub hidden: libc::c_int, + pub timestamp_sort: time_t, + pub timestamp_sent: time_t, + pub timestamp_rcvd: time_t, + pub text: *mut libc::c_char, + pub context: *mut 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, + pub server_uid: uint32_t, + pub is_dc_message: libc::c_int, + pub starred: libc::c_int, + pub chat_blocked: libc::c_int, + pub location_id: uint32_t, + pub param: *mut dc_param_t, +} +pub type dc_move_state_t = libc::c_uint; +pub const DC_MOVE_STATE_MOVING: dc_move_state_t = 3; +pub const DC_MOVE_STATE_STAY: dc_move_state_t = 2; +pub const DC_MOVE_STATE_PENDING: dc_move_state_t = 1; +pub const DC_MOVE_STATE_UNDEFINED: dc_move_state_t = 0; +pub type dc_msg_t = _dc_msg; +/* * the structure behind dc_contact_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_contact { + pub magic: uint32_t, + pub context: *mut dc_context_t, + pub id: uint32_t, + pub name: *mut libc::c_char, + pub authname: *mut libc::c_char, + pub addr: *mut libc::c_char, + pub blocked: libc::c_int, + pub origin: libc::c_int, +} +pub type dc_contact_t = _dc_contact; +pub type dc_strbuilder_t = _dc_strbuilder; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_strbuilder { + pub buf: *mut libc::c_char, + pub allocated: libc::c_int, + pub free: libc::c_int, + pub eos: *mut libc::c_char, +} +pub type sqlite3_int64 = sqlite_int64; +pub type sqlite_int64 = libc::c_longlong; +pub type sqlite3_destructor_type = Option ()>; +// handle messages +#[no_mangle] +pub unsafe extern "C" fn dc_get_msg_info( + mut context: *mut 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 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 ret: dc_strbuilder_t = _dc_strbuilder { + 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) { + 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, + ); + 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); + 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); + } + 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), + _ => { + 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"State: %s\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, + ); + } + 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, + ); + } + } + } + } + sqlite3_finalize(stmt); + dc_msg_unref(msg); + dc_contact_unref(contact_from); + free(rawtxt as *mut libc::c_void); + return ret.buf; +} +#[no_mangle] +pub unsafe extern "C" fn dc_msg_new_untyped(mut context: *mut dc_context_t) -> *mut dc_msg_t { + return dc_msg_new(context, 0i32); +} +/* * + * @class dc_msg_t + * + * An object representing a single message in memory. + * The message object is not updated. + * If you want an update, you have to recreate the object. + */ +// 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() +#[no_mangle] +pub unsafe extern "C" fn dc_msg_new( + mut context: *mut 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; + msg = calloc( + 1i32 as libc::c_ulong, + ::std::mem::size_of::() as libc::c_ulong, + ) as *mut dc_msg_t; + if msg.is_null() { + exit(15i32); + } + (*msg).context = context; + (*msg).magic = 0x11561156i32 as uint32_t; + (*msg).type_0 = viewtype; + (*msg).state = 0i32; + (*msg).param = dc_param_new(); + return msg; +} +#[no_mangle] +pub unsafe extern "C" fn dc_msg_unref(mut msg: *mut dc_msg_t) { + if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint { + return; + } + dc_msg_empty(msg); + dc_param_unref((*msg).param); + (*msg).magic = 0i32 as uint32_t; + free(msg as *mut libc::c_void); +} +#[no_mangle] +pub unsafe extern "C" fn dc_msg_empty(mut msg: *mut dc_msg_t) { + if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint { + return; + } + free((*msg).text as *mut libc::c_void); + (*msg).text = 0 as *mut libc::c_char; + free((*msg).rfc724_mid as *mut libc::c_void); + (*msg).rfc724_mid = 0 as *mut libc::c_char; + free((*msg).in_reply_to as *mut libc::c_void); + (*msg).in_reply_to = 0 as *mut libc::c_char; + free((*msg).server_folder as *mut libc::c_void); + (*msg).server_folder = 0 as *mut libc::c_char; + dc_param_set_packed((*msg).param, 0 as *const libc::c_char); + (*msg).hidden = 0i32; +} +#[no_mangle] +pub unsafe extern "C" 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; + if !(msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint) { + ret = dc_param_get((*msg).param, 'm' as i32, 0 as *const libc::c_char); + if ret.is_null() { + file = dc_param_get((*msg).param, 'f' as i32, 0 as *const libc::c_char); + if !file.is_null() { + dc_msg_guess_msgtype_from_suffix(file, 0 as *mut libc::c_int, &mut ret); + if ret.is_null() { + ret = dc_strdup( + b"application/octet-stream\x00" as *const u8 as *const libc::c_char, + ) + } + } + } + } + free(file as *mut libc::c_void); + return if !ret.is_null() { + ret + } else { + dc_strdup(0 as *const libc::c_char) + }; +} +#[no_mangle] +pub unsafe extern "C" fn dc_msg_guess_msgtype_from_suffix( + mut pathNfilename: *const libc::c_char, + mut ret_msgtype: *mut libc::c_int, + mut ret_mime: *mut *mut libc::c_char, +) { + let mut suffix: *mut libc::c_char = 0 as *mut libc::c_char; + let mut dummy_msgtype: libc::c_int = 0i32; + let mut dummy_buf: *mut libc::c_char = 0 as *mut libc::c_char; + if !pathNfilename.is_null() { + if ret_msgtype.is_null() { + ret_msgtype = &mut dummy_msgtype + } + if ret_mime.is_null() { + ret_mime = &mut dummy_buf + } + *ret_msgtype = 0i32; + *ret_mime = 0 as *mut libc::c_char; + suffix = dc_get_filesuffix_lc(pathNfilename); + if !suffix.is_null() { + if strcmp(suffix, b"mp3\x00" as *const u8 as *const libc::c_char) == 0i32 { + *ret_msgtype = 40i32; + *ret_mime = dc_strdup(b"audio/mpeg\x00" as *const u8 as *const libc::c_char) + } else if strcmp(suffix, b"aac\x00" as *const u8 as *const libc::c_char) == 0i32 { + *ret_msgtype = 40i32; + *ret_mime = dc_strdup(b"audio/aac\x00" as *const u8 as *const libc::c_char) + } else if strcmp(suffix, b"mp4\x00" as *const u8 as *const libc::c_char) == 0i32 { + *ret_msgtype = 50i32; + *ret_mime = dc_strdup(b"video/mp4\x00" as *const u8 as *const libc::c_char) + } else if strcmp(suffix, b"jpg\x00" as *const u8 as *const libc::c_char) == 0i32 + || strcmp(suffix, b"jpeg\x00" as *const u8 as *const libc::c_char) == 0i32 + { + *ret_msgtype = 20i32; + *ret_mime = dc_strdup(b"image/jpeg\x00" as *const u8 as *const libc::c_char) + } else if strcmp(suffix, b"png\x00" as *const u8 as *const libc::c_char) == 0i32 { + *ret_msgtype = 20i32; + *ret_mime = dc_strdup(b"image/png\x00" as *const u8 as *const libc::c_char) + } else if strcmp(suffix, b"webp\x00" as *const u8 as *const libc::c_char) == 0i32 { + *ret_msgtype = 20i32; + *ret_mime = dc_strdup(b"image/webp\x00" as *const u8 as *const libc::c_char) + } else if strcmp(suffix, b"gif\x00" as *const u8 as *const libc::c_char) == 0i32 { + *ret_msgtype = 21i32; + *ret_mime = dc_strdup(b"image/gif\x00" as *const u8 as *const libc::c_char) + } else if strcmp(suffix, b"vcf\x00" as *const u8 as *const libc::c_char) == 0i32 + || strcmp(suffix, b"vcard\x00" as *const u8 as *const libc::c_char) == 0i32 + { + *ret_msgtype = 60i32; + *ret_mime = dc_strdup(b"text/vcard\x00" as *const u8 as *const libc::c_char) + } + } + } + free(suffix as *mut libc::c_void); + free(dummy_buf as *mut libc::c_void); +} +#[no_mangle] +pub unsafe extern "C" 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; + if !(msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint) { + file_rel = dc_param_get((*msg).param, 'f' as i32, 0 as *const libc::c_char); + if !file_rel.is_null() { + file_abs = dc_get_abs_path((*msg).context, file_rel) + } + } + free(file_rel as *mut libc::c_void); + return if !file_abs.is_null() { + file_abs + } else { + dc_strdup(0 as *const libc::c_char) + }; +} +#[no_mangle] +pub unsafe extern "C" 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; +} +#[no_mangle] +pub unsafe extern "C" fn dc_msg_get_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 if 0 != (*msg).timestamp_sent { + (*msg).timestamp_sent + } else { + (*msg).timestamp_sort + }; +} +#[no_mangle] +pub unsafe extern "C" fn dc_msg_load_from_db( + mut msg: *mut dc_msg_t, + mut context: *mut dc_context_t, + mut 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()) + { + 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" + as *const u8 as *const libc::c_char); + sqlite3_bind_int(stmt, 1i32, id as libc::c_int); + if !(sqlite3_step(stmt) != 100i32) { + if !(0 == dc_msg_set_from_stmt(msg, stmt, 0i32)) { + /* also calls dc_msg_empty() */ + (*msg).context = context; + success = 1i32 + } + } + } + sqlite3_finalize(stmt); + return success; +} +unsafe extern "C" fn dc_msg_set_from_stmt( + mut msg: *mut dc_msg_t, + mut row: *mut sqlite3_stmt, + mut row_offset: libc::c_int, +) -> libc::c_int { + dc_msg_empty(msg); + let fresh0 = row_offset; + row_offset = row_offset + 1; + (*msg).id = sqlite3_column_int(row, fresh0) as uint32_t; + let fresh1 = row_offset; + row_offset = row_offset + 1; + (*msg).rfc724_mid = dc_strdup(sqlite3_column_text(row, fresh1) as *mut libc::c_char); + let fresh2 = row_offset; + row_offset = row_offset + 1; + (*msg).in_reply_to = dc_strdup(sqlite3_column_text(row, fresh2) as *mut libc::c_char); + let fresh3 = row_offset; + row_offset = row_offset + 1; + (*msg).server_folder = dc_strdup(sqlite3_column_text(row, fresh3) as *mut libc::c_char); + let fresh4 = row_offset; + row_offset = row_offset + 1; + (*msg).server_uid = sqlite3_column_int(row, fresh4) as uint32_t; + let fresh5 = row_offset; + row_offset = row_offset + 1; + (*msg).move_state = sqlite3_column_int(row, fresh5) as dc_move_state_t; + let fresh6 = row_offset; + row_offset = row_offset + 1; + (*msg).chat_id = sqlite3_column_int(row, fresh6) as uint32_t; + let fresh7 = row_offset; + row_offset = row_offset + 1; + (*msg).from_id = sqlite3_column_int(row, fresh7) as uint32_t; + let fresh8 = row_offset; + row_offset = row_offset + 1; + (*msg).to_id = sqlite3_column_int(row, fresh8) as uint32_t; + let fresh9 = row_offset; + row_offset = row_offset + 1; + (*msg).timestamp_sort = sqlite3_column_int64(row, fresh9) as time_t; + let fresh10 = row_offset; + row_offset = row_offset + 1; + (*msg).timestamp_sent = sqlite3_column_int64(row, fresh10) as time_t; + let fresh11 = row_offset; + row_offset = row_offset + 1; + (*msg).timestamp_rcvd = sqlite3_column_int64(row, fresh11) as time_t; + let fresh12 = row_offset; + row_offset = row_offset + 1; + (*msg).type_0 = sqlite3_column_int(row, fresh12); + let fresh13 = row_offset; + row_offset = row_offset + 1; + (*msg).state = sqlite3_column_int(row, fresh13); + let fresh14 = row_offset; + row_offset = row_offset + 1; + (*msg).is_dc_message = sqlite3_column_int(row, fresh14); + let fresh15 = row_offset; + row_offset = row_offset + 1; + (*msg).text = dc_strdup(sqlite3_column_text(row, fresh15) as *mut libc::c_char); + let fresh16 = row_offset; + row_offset = row_offset + 1; + dc_param_set_packed( + (*msg).param, + sqlite3_column_text(row, fresh16) as *mut libc::c_char, + ); + let fresh17 = row_offset; + row_offset = row_offset + 1; + (*msg).starred = sqlite3_column_int(row, fresh17); + let fresh18 = row_offset; + row_offset = row_offset + 1; + (*msg).hidden = sqlite3_column_int(row, fresh18); + let fresh19 = row_offset; + 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; +} +#[no_mangle] +pub unsafe extern "C" fn dc_get_mime_headers( + mut context: *mut 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) + } + } + sqlite3_finalize(stmt); + return eml; +} +#[no_mangle] +pub unsafe extern "C" fn dc_delete_msgs( + mut context: *mut 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 + { + 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); + dc_job_add( + context, + 110i32, + *msg_ids.offset(i as isize) as libc::c_int, + 0 as *const libc::c_char, + 0i32, + ); + i += 1 + } + dc_sqlite3_commit((*context).sql); + if 0 != msg_cnt { + (*context).cb.expect("non-null function pointer")( + context, + 2000i32, + 0i32 as uintptr_t, + 0i32 as uintptr_t, + ); + dc_job_kill_action(context, 105i32); + dc_job_add(context, 105i32, 0i32, 0 as *const libc::c_char, 10i32); + }; +} +#[no_mangle] +pub unsafe extern "C" fn dc_update_msg_chat_id( + mut context: *mut dc_context_t, + mut msg_id: uint32_t, + mut chat_id: uint32_t, +) { + let mut stmt: *mut sqlite3_stmt = dc_sqlite3_prepare( + (*context).sql, + 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); + sqlite3_bind_int(stmt, 2i32, msg_id as libc::c_int); + sqlite3_step(stmt); + sqlite3_finalize(stmt); +} +#[no_mangle] +pub unsafe extern "C" fn dc_markseen_msgs( + mut context: *mut 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 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; + stmt = + dc_sqlite3_prepare((*context).sql, + 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; + while i < msg_cnt { + sqlite3_reset(stmt); + sqlite3_bind_int(stmt, 1i32, *msg_ids.offset(i as isize) as libc::c_int); + if !(sqlite3_step(stmt) != 100i32) { + curr_state = sqlite3_column_int(stmt, 0i32); + curr_blocked = sqlite3_column_int(stmt, 1i32); + if curr_blocked == 0i32 { + if curr_state == 10i32 || curr_state == 13i32 { + dc_update_msg_state(context, *msg_ids.offset(i as isize), 16i32); + dc_log_info( + context, + 0i32, + b"Seen message #%i.\x00" as *const u8 as *const libc::c_char, + *msg_ids.offset(i as isize), + ); + dc_job_add( + context, + 130i32, + *msg_ids.offset(i as isize) as libc::c_int, + 0 as *const libc::c_char, + 0i32, + ); + send_event = 1i32 + } + } else if curr_state == 10i32 { + dc_update_msg_state(context, *msg_ids.offset(i as isize), 13i32); + send_event = 1i32 + } + } + i += 1 + } + dc_sqlite3_commit((*context).sql); + transaction_pending = 0i32; + if 0 != send_event { + (*context).cb.expect("non-null function pointer")( + context, + 2000i32, + 0i32 as uintptr_t, + 0i32 as uintptr_t, + ); + } + } + if 0 != transaction_pending { + dc_sqlite3_rollback((*context).sql); + } + sqlite3_finalize(stmt); +} +#[no_mangle] +pub unsafe extern "C" fn dc_update_msg_state( + mut context: *mut dc_context_t, + mut msg_id: uint32_t, + mut state: libc::c_int, +) { + let mut stmt: *mut sqlite3_stmt = dc_sqlite3_prepare( + (*context).sql, + b"UPDATE msgs SET state=? WHERE id=?;\x00" as *const u8 as *const libc::c_char, + ); + sqlite3_bind_int(stmt, 1i32, state); + sqlite3_bind_int(stmt, 2i32, msg_id as libc::c_int); + sqlite3_step(stmt); + sqlite3_finalize(stmt); +} +#[no_mangle] +pub unsafe extern "C" fn dc_star_msgs( + mut context: *mut 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 + { + return; + } + dc_sqlite3_begin_transaction((*context).sql); + let mut stmt: *mut sqlite3_stmt = dc_sqlite3_prepare( + (*context).sql, + b"UPDATE msgs SET starred=? WHERE id=?;\x00" as *const u8 as *const libc::c_char, + ); + let mut i: libc::c_int = 0i32; + while i < msg_cnt { + sqlite3_reset(stmt); + sqlite3_bind_int(stmt, 1i32, star); + sqlite3_bind_int(stmt, 2i32, *msg_ids.offset(i as isize) as libc::c_int); + sqlite3_step(stmt); + i += 1 + } + sqlite3_finalize(stmt); + dc_sqlite3_commit((*context).sql); +} +#[no_mangle] +pub unsafe extern "C" fn dc_get_msg( + mut context: *mut dc_context_t, + mut msg_id: uint32_t, +) -> *mut dc_msg_t { + 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 != success { + return obj; + } else { + dc_msg_unref(obj); + return 0 as *mut dc_msg_t; + }; +} +#[no_mangle] +pub unsafe extern "C" 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; +} +#[no_mangle] +pub unsafe extern "C" 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; +} +#[no_mangle] +pub unsafe extern "C" 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; + } + return if 0 != (*msg).chat_blocked { + 1i32 as libc::c_uint + } else { + (*msg).chat_id + }; +} +#[no_mangle] +pub unsafe extern "C" 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; +} +#[no_mangle] +pub unsafe extern "C" 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; +} +#[no_mangle] +pub unsafe extern "C" 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; +} +#[no_mangle] +pub unsafe extern "C" 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; +} +#[no_mangle] +pub unsafe extern "C" 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; + 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; +} +#[no_mangle] +pub unsafe extern "C" 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; + if !(msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint) { + pathNfilename = dc_param_get((*msg).param, 'f' as i32, 0 as *const libc::c_char); + if !pathNfilename.is_null() { + ret = dc_get_filename(pathNfilename) + } + } + free(pathNfilename as *mut libc::c_void); + return if !ret.is_null() { + ret + } else { + dc_strdup(0 as *const libc::c_char) + }; +} +#[no_mangle] +pub unsafe extern "C" 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; + if !(msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint) { + file = dc_param_get((*msg).param, 'f' as i32, 0 as *const libc::c_char); + if !file.is_null() { + ret = dc_get_filebytes((*msg).context, file) + } + } + free(file as *mut libc::c_void); + return ret; +} +#[no_mangle] +pub unsafe extern "C" 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); +} +#[no_mangle] +pub unsafe extern "C" 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); +} +#[no_mangle] +pub unsafe extern "C" 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); +} +#[no_mangle] +pub unsafe extern "C" 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() { + return 0i32; + } + if dc_param_get_int((*msg).param, 'c' as i32, 0i32) != 0i32 { + return 1i32; + } + return 0i32; +} +#[no_mangle] +pub unsafe extern "C" fn dc_msg_get_summary( + mut msg: *const dc_msg_t, + mut chat: *const dc_chat_t, +) -> *mut dc_lot_t { + let mut current_block: u64; + let mut ret: *mut dc_lot_t = dc_lot_new(); + let mut contact: *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; + if !(msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint) { + if chat.is_null() { + chat_to_delete = dc_get_chat((*msg).context, (*msg).chat_id); + if chat_to_delete.is_null() { + current_block = 15204159476013091401; + } else { + chat = chat_to_delete; + current_block = 7815301370352969686; + } + } else { + current_block = 7815301370352969686; + } + match current_block { + 15204159476013091401 => {} + _ => { + if (*msg).from_id != 1i32 as libc::c_uint + && ((*chat).type_0 == 120i32 || (*chat).type_0 == 130i32) + { + contact = dc_get_contact((*chat).context, (*msg).from_id) + } + dc_lot_fill(ret, msg, chat, contact, (*msg).context); + } + } + } + dc_contact_unref(contact); + dc_chat_unref(chat_to_delete); + return ret; +} +#[no_mangle] +pub unsafe extern "C" fn dc_msg_get_summarytext( + mut msg: *const dc_msg_t, + mut approx_characters: libc::c_int, +) -> *mut libc::c_char { + 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( + (*msg).type_0, + (*msg).text, + (*msg).param, + approx_characters, + (*msg).context, + ); +} +/* the returned value must be free()'d */ +#[no_mangle] +pub unsafe extern "C" 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 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 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; + let mut value: *mut libc::c_char = 0 as *mut libc::c_char; + let mut append_text: libc::c_int = 1i32; + match type_0 { + 20 => prefix = dc_stock_str(context, 9i32), + 21 => prefix = dc_stock_str(context, 23i32), + 50 => prefix = dc_stock_str(context, 10i32), + 41 => prefix = dc_stock_str(context, 7i32), + 40 | 60 => { + if dc_param_get_int(param, 'S' as i32, 0i32) == 6i32 { + prefix = dc_stock_str(context, 42i32); + append_text = 0i32 + } else { + pathNfilename = dc_param_get( + param, + 'f' as i32, + b"ErrFilename\x00" as *const u8 as *const libc::c_char, + ); + value = dc_get_filename(pathNfilename); + label = dc_stock_str(context, if type_0 == 40i32 { 11i32 } else { 12i32 }); + prefix = dc_mprintf( + b"%s \xe2\x80\x93 %s\x00" as *const u8 as *const libc::c_char, + label, + value, + ) + } + } + _ => { + if dc_param_get_int(param, 'S' as i32, 0i32) == 9i32 { + prefix = dc_stock_str(context, 66i32); + append_text = 0i32 + } + } + } + if 0 != append_text + && !prefix.is_null() + && !text.is_null() + && 0 != *text.offset(0isize) as libc::c_int + { + ret = dc_mprintf( + b"%s \xe2\x80\x93 %s\x00" as *const u8 as *const libc::c_char, + prefix, + text, + ); + dc_truncate_n_unwrap_str(ret, approx_characters, 1i32); + } else if 0 != append_text && !text.is_null() && 0 != *text.offset(0isize) as libc::c_int { + ret = dc_strdup(text); + dc_truncate_n_unwrap_str(ret, approx_characters, 1i32); + } else { + ret = prefix; + prefix = 0 as *mut libc::c_char + } + free(prefix as *mut libc::c_void); + free(pathNfilename as *mut libc::c_void); + free(label as *mut libc::c_void); + free(value as *mut libc::c_void); + if ret.is_null() { + ret = dc_strdup(0 as *const libc::c_char) + } + return ret; +} +#[no_mangle] +pub unsafe extern "C" 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; +} +#[no_mangle] +pub unsafe extern "C" 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 }; +} +#[no_mangle] +pub unsafe extern "C" 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 }; +} +#[no_mangle] +pub unsafe extern "C" 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; + } + return if 0 != dc_param_get_int((*msg).param, 'a' as i32, 0i32) { + 1i32 + } else { + 0i32 + }; +} +#[no_mangle] +pub unsafe extern "C" 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; + } + let mut cmd: libc::c_int = dc_param_get_int((*msg).param, 'S' as i32, 0i32); + if (*msg).from_id == 2i32 as libc::c_uint + || (*msg).to_id == 2i32 as libc::c_uint + || 0 != cmd && cmd != 6i32 + { + return 1i32; + } + return 0i32; +} +#[no_mangle] +pub unsafe extern "C" 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() { + return 0i32; + } + return (((*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; +} +#[no_mangle] +pub unsafe extern "C" 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; + } + return if dc_param_get_int((*msg).param, 'S' as i32, 0i32) == 6i32 { + 1i32 + } else { + 0i32 + }; +} +#[no_mangle] +pub unsafe extern "C" 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; + let mut buf_bytes: size_t = 0i32 as size_t; + // just a pointer inside buf, MUST NOT be free()'d + let mut buf_headerline: *const libc::c_char = 0 as *const libc::c_char; + // just a pointer inside buf, MUST NOT be free()'d + let mut buf_setupcodebegin: *const libc::c_char = 0 as *const libc::c_char; + let mut ret: *mut libc::c_char = 0 as *mut libc::c_char; + if !(0 == dc_msg_is_setupmessage(msg)) { + filename = dc_msg_get_file(msg); + if !(filename.is_null() || *filename.offset(0isize) as libc::c_int == 0i32) { + if !(0 + == dc_read_file( + (*msg).context, + filename, + &mut buf as *mut *mut libc::c_char as *mut *mut libc::c_void, + &mut buf_bytes, + ) + || buf.is_null() + || buf_bytes <= 0i32 as libc::c_ulong) + { + if !(0 + == dc_split_armored_data( + buf, + &mut buf_headerline, + &mut buf_setupcodebegin, + 0 as *mut *const libc::c_char, + 0 as *mut *const libc::c_char, + ) + || strcmp( + buf_headerline, + b"-----BEGIN PGP MESSAGE-----\x00" as *const u8 as *const libc::c_char, + ) != 0i32 + || buf_setupcodebegin.is_null()) + { + ret = dc_strdup(buf_setupcodebegin) + } + } + } + } + free(filename as *mut libc::c_void); + free(buf as *mut libc::c_void); + return if !ret.is_null() { + ret + } else { + dc_strdup(0 as *const libc::c_char) + }; +} +#[no_mangle] +pub unsafe extern "C" 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; + } + free((*msg).text as *mut libc::c_void); + (*msg).text = dc_strdup(text); +} +#[no_mangle] +pub unsafe extern "C" fn dc_msg_set_file( + mut msg: *mut dc_msg_t, + mut file: *const libc::c_char, + mut filemime: *const libc::c_char, +) { + if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint { + return; + } + dc_param_set((*msg).param, 'f' as i32, file); + dc_param_set((*msg).param, 'm' as i32, filemime); +} +#[no_mangle] +pub unsafe extern "C" fn dc_msg_set_dimension( + mut msg: *mut dc_msg_t, + mut width: libc::c_int, + mut height: libc::c_int, +) { + if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint { + return; + } + dc_param_set_int((*msg).param, 'w' as i32, width); + dc_param_set_int((*msg).param, 'h' as i32, height); +} +#[no_mangle] +pub unsafe extern "C" 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); +} +#[no_mangle] +pub unsafe extern "C" fn dc_msg_latefiling_mediasize( + mut msg: *mut dc_msg_t, + mut width: libc::c_int, + mut height: libc::c_int, + mut duration: libc::c_int, +) { + if !(msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint) { + if width > 0i32 && height > 0i32 { + dc_param_set_int((*msg).param, 'w' as i32, width); + dc_param_set_int((*msg).param, 'h' as i32, height); + } + if duration > 0i32 { + dc_param_set_int((*msg).param, 'd' as i32, duration); + } + dc_msg_save_param_to_disk(msg); + }; +} +#[no_mangle] +pub unsafe extern "C" 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() + { + return; + } + let mut stmt: *mut sqlite3_stmt = dc_sqlite3_prepare( + (*(*msg).context).sql, + 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); + sqlite3_bind_int(stmt, 2i32, (*msg).id as libc::c_int); + sqlite3_step(stmt); + sqlite3_finalize(stmt); +} +#[no_mangle] +pub unsafe extern "C" 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); + dc_msg_load_from_db(msg, context, msg_id); + return msg; +} +#[no_mangle] +pub unsafe extern "C" fn dc_delete_msg_from_db( + mut context: *mut 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, + 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, + 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); + sqlite3_step(stmt); + sqlite3_finalize(stmt); + stmt = 0 as *mut sqlite3_stmt + } + 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 +#[no_mangle] +pub unsafe extern "C" 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) + { + stmt = dc_sqlite3_prepare( + (*context).sql, + 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 { + msg_exists = 1i32 + } + } + } + sqlite3_finalize(stmt); + return msg_exists; +} +#[no_mangle] +pub unsafe extern "C" fn dc_update_msg_move_state( + mut context: *mut 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, + 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); + sqlite3_bind_text(stmt, 2i32, rfc724_mid, -1i32, None); + sqlite3_step(stmt); + sqlite3_finalize(stmt); +} +#[no_mangle] +pub unsafe extern "C" fn dc_set_msg_failed( + mut context: *mut 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 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 { + (*msg).state = 24i32 + } + if !error.is_null() { + dc_param_set((*msg).param, 'L' as i32, error); + dc_log_error( + context, + 0i32, + b"%s\x00" as *const u8 as *const libc::c_char, + error, + ); + } + stmt = dc_sqlite3_prepare( + (*context).sql, + b"UPDATE msgs SET state=?, param=? WHERE id=?;\x00" as *const u8 as *const libc::c_char, + ); + sqlite3_bind_int(stmt, 1i32, (*msg).state); + sqlite3_bind_text(stmt, 2i32, (*(*msg).param).packed, -1i32, None); + sqlite3_bind_int(stmt, 3i32, msg_id as libc::c_int); + sqlite3_step(stmt); + (*context).cb.expect("non-null function pointer")( + context, + 2012i32, + (*msg).chat_id as uintptr_t, + msg_id as uintptr_t, + ); + } + sqlite3_finalize(stmt); + dc_msg_unref(msg); +} +/* returns 1 if an event should be send */ +#[no_mangle] +pub unsafe extern "C" fn dc_mdn_from_ext( + mut context: *mut 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 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 + || rfc724_mid.is_null() + || ret_chat_id.is_null() + || ret_msg_id.is_null() + || *ret_chat_id != 0i32 as libc::c_uint + || *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); + 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; + *ret_chat_id = sqlite3_column_int(stmt, 1i32) as uint32_t; + chat_type = sqlite3_column_int(stmt, 2i32); + msg_state = sqlite3_column_int(stmt, 3i32); + sqlite3_finalize(stmt); + stmt = 0 as *mut sqlite3_stmt; + 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, + b"SELECT contact_id FROM msgs_mdns WHERE msg_id=? AND contact_id=?;\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); + mdn_already_in_table = if sqlite3_step(stmt) == 100i32 { + 1i32 + } else { + 0i32 + }; + sqlite3_finalize(stmt); + 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); + 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); + sqlite3_step(stmt); + sqlite3_finalize(stmt); + stmt = 0 as *mut sqlite3_stmt + } + // Normal chat? that's quite easy. + if chat_type == 100i32 { + dc_update_msg_state(context, *ret_msg_id, 28i32); + read_by_all = 1i32 + } else { + /* send event about new state */ + stmt = dc_sqlite3_prepare( + (*context).sql, + b"SELECT COUNT(*) FROM msgs_mdns WHERE msg_id=?;\x00" as *const u8 + as *const libc::c_char, + ); + sqlite3_bind_int(stmt, 1i32, *ret_msg_id as libc::c_int); + if !(sqlite3_step(stmt) != 100i32) { + /* error */ + ist_cnt = sqlite3_column_int(stmt, 0i32); + sqlite3_finalize(stmt); + stmt = 0 as *mut sqlite3_stmt; + /* + Groupsize: Min. MDNs + + 1 S n/a + 2 SR 1 + 3 SRR 2 + 4 SRRR 2 + 5 SRRRR 3 + 6 SRRRRR 3 + + (S=Sender, R=Recipient) + */ + /*for rounding, SELF is already included!*/ + soll_cnt = (dc_get_chat_contact_cnt(context, *ret_chat_id) + 1i32) / 2i32; + if !(ist_cnt < soll_cnt) { + /* wait for more receipts */ + dc_update_msg_state(context, *ret_msg_id, 28i32); + read_by_all = 1i32 + } + } + } + } + } + } + sqlite3_finalize(stmt); + return read_by_all; +} +/* the number of messages assigned to real chat (!=deaddrop, !=trash) */ +#[no_mangle] +pub unsafe extern "C" fn dc_get_real_msg_cnt(mut context: *mut 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() { + 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" + as *const u8 as *const libc::c_char); + if sqlite3_step(stmt) != 100i32 { + dc_sqlite3_log_error( + (*context).sql, + b"dc_get_real_msg_cnt() failed.\x00" as *const u8 as *const libc::c_char, + ); + } else { + ret = sqlite3_column_int(stmt, 0i32) as size_t + } + } + sqlite3_finalize(stmt); + return ret; +} +#[no_mangle] +pub unsafe extern "C" fn dc_get_deaddrop_msg_cnt(mut context: *mut 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()) + { + stmt = + dc_sqlite3_prepare((*context).sql, + 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) { + ret = sqlite3_column_int(stmt, 0i32) as size_t + } + } + sqlite3_finalize(stmt); + return ret; +} +#[no_mangle] +pub unsafe extern "C" fn dc_rfc724_mid_cnt( + mut context: *mut 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()) + { + stmt = dc_sqlite3_prepare( + (*context).sql, + b"SELECT COUNT(*) FROM msgs WHERE rfc724_mid=?;\x00" as *const u8 + as *const libc::c_char, + ); + sqlite3_bind_text(stmt, 1i32, rfc724_mid, -1i32, None); + if !(sqlite3_step(stmt) != 100i32) { + ret = sqlite3_column_int(stmt, 0i32) + } + } + sqlite3_finalize(stmt); + return ret; +} +#[no_mangle] +pub unsafe extern "C" fn dc_rfc724_mid_exists( + mut context: *mut 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) + { + stmt = dc_sqlite3_prepare( + (*context).sql, + b"SELECT server_folder, server_uid, id FROM msgs WHERE rfc724_mid=?;\x00" as *const u8 + as *const libc::c_char, + ); + sqlite3_bind_text(stmt, 1i32, rfc724_mid, -1i32, None); + if sqlite3_step(stmt) != 100i32 { + if !ret_server_folder.is_null() { + *ret_server_folder = 0 as *mut libc::c_char + } + if !ret_server_uid.is_null() { + *ret_server_uid = 0i32 as uint32_t + } + } else { + if !ret_server_folder.is_null() { + *ret_server_folder = dc_strdup(sqlite3_column_text(stmt, 0i32) as *mut libc::c_char) + } + if !ret_server_uid.is_null() { + *ret_server_uid = sqlite3_column_int(stmt, 1i32) as uint32_t + } + ret = sqlite3_column_int(stmt, 2i32) as uint32_t + } + } + sqlite3_finalize(stmt); + return ret; +} +#[no_mangle] +pub unsafe extern "C" fn dc_update_server_uid( + mut context: *mut 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, + b"UPDATE msgs SET server_folder=?, server_uid=? WHERE rfc724_mid=?;\x00" as *const u8 + as *const libc::c_char, + ); + sqlite3_bind_text(stmt, 1i32, server_folder, -1i32, None); + sqlite3_bind_int(stmt, 2i32, server_uid as libc::c_int); + sqlite3_bind_text(stmt, 3i32, rfc724_mid, -1i32, None); + sqlite3_step(stmt); + sqlite3_finalize(stmt); +} diff --git a/src/dc_oauth2.rs b/src/dc_oauth2.rs new file mode 100644 index 000000000..935f286c7 --- /dev/null +++ b/src/dc_oauth2.rs @@ -0,0 +1,1491 @@ +use c2rust_bitfields::BitfieldStruct; +use libc; +extern "C" { + pub type mailstream_cancel; + pub type sqlite3; + #[no_mangle] + fn calloc(_: libc::c_ulong, _: libc::c_ulong) -> *mut libc::c_void; + #[no_mangle] + fn free(_: *mut libc::c_void); + #[no_mangle] + fn atol(_: *const libc::c_char) -> libc::c_long; + #[no_mangle] + fn strchr(_: *const libc::c_char, _: libc::c_int) -> *mut libc::c_char; + #[no_mangle] + fn strcmp(_: *const libc::c_char, _: *const libc::c_char) -> libc::c_int; + #[no_mangle] + fn strlen(_: *const libc::c_char) -> libc::c_ulong; + #[no_mangle] + fn strncmp(_: *const libc::c_char, _: *const libc::c_char, _: libc::c_ulong) -> libc::c_int; + #[no_mangle] + fn strdup(_: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn strndup(_: *const libc::c_char, _: libc::c_ulong) -> *mut libc::c_char; + #[no_mangle] + fn strcasecmp(_: *const libc::c_char, _: *const libc::c_char) -> libc::c_int; + #[no_mangle] + fn time(_: *mut time_t) -> time_t; + #[no_mangle] + fn pthread_mutex_lock(_: *mut pthread_mutex_t) -> libc::c_int; + #[no_mangle] + fn pthread_mutex_unlock(_: *mut pthread_mutex_t) -> libc::c_int; + #[no_mangle] + fn dc_urlencode(_: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn dc_str_replace( + haystack: *mut *mut libc::c_char, + needle: *const libc::c_char, + replacement: *const libc::c_char, + ) -> libc::c_int; + /* string tools */ + #[no_mangle] + fn dc_strdup(_: *const libc::c_char) -> *mut libc::c_char; + /* handle configurations, private */ + #[no_mangle] + fn dc_sqlite3_set_config( + _: *mut dc_sqlite3_t, + key: *const libc::c_char, + value: *const libc::c_char, + ) -> libc::c_int; + #[no_mangle] + fn dc_addr_normalize(addr: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn dc_sqlite3_set_config_int64( + _: *mut dc_sqlite3_t, + key: *const libc::c_char, + value: int64_t, + ) -> libc::c_int; + #[no_mangle] + fn dc_sqlite3_get_config( + _: *mut dc_sqlite3_t, + key: *const libc::c_char, + def: *const libc::c_char, + ) -> *mut libc::c_char; + #[no_mangle] + fn dc_sqlite3_get_config_int64( + _: *mut dc_sqlite3_t, + key: *const libc::c_char, + def: int64_t, + ) -> int64_t; + #[no_mangle] + fn dc_log_warning(_: *mut dc_context_t, data1: libc::c_int, msg: *const libc::c_char, _: ...); + #[no_mangle] + fn dc_log_info(_: *mut dc_context_t, data1: libc::c_int, msg: *const libc::c_char, _: ...); + /* * + * Run JSON parser. It parses a JSON data string into and array of tokens, each describing + * a single JSON object. + */ + #[no_mangle] + fn jsmn_parse( + parser: *mut jsmn_parser, + js: *const libc::c_char, + len: size_t, + tokens: *mut jsmntok_t, + num_tokens: libc::c_uint, + ) -> libc::c_int; + /* * + * Create JSON parser over an array of tokens + */ + #[no_mangle] + fn jsmn_init(parser: *mut jsmn_parser); +} +pub type __darwin_size_t = libc::c_ulong; +pub type __darwin_ssize_t = libc::c_long; +pub type __darwin_time_t = libc::c_long; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_cond_t { + pub __sig: libc::c_long, + pub __opaque: [libc::c_char; 40], +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_mutex_t { + pub __sig: libc::c_long, + pub __opaque: [libc::c_char; 56], +} +pub type __darwin_pthread_cond_t = _opaque_pthread_cond_t; +pub type __darwin_pthread_mutex_t = _opaque_pthread_mutex_t; +pub type int64_t = libc::c_longlong; +pub type uintptr_t = libc::c_ulong; +pub type size_t = __darwin_size_t; +pub type uint8_t = libc::c_uchar; +pub type uint32_t = libc::c_uint; +pub type ssize_t = __darwin_ssize_t; +pub type time_t = __darwin_time_t; +pub type pthread_cond_t = __darwin_pthread_cond_t; +pub type pthread_mutex_t = __darwin_pthread_mutex_t; +#[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; +#[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) -> (); +#[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; +#[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, + 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 { + 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_capability_data { + pub cap_list: *mut clist, +} +#[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_0, + 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_0 { + 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 extern "C" 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_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, +} +#[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_1, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed_1 { + pub ft_fetch_att: *mut mailimap_fetch_att, + pub ft_fetch_att_list: *mut clist, +} +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 unnamed_2 { + 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, +} +/* define DC_USE_RPGP to enable use of rPGP instead of netpgp where available; +preferrably, this should be done in the project configuration currently */ +//#define DC_USE_RPGP 1 +/* Includes that are used frequently. This file may also be used to create predefined headers. */ +/* * Structure behind dc_context_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_context { + pub magic: uint32_t, + pub userdata: *mut libc::c_void, + pub dbfile: *mut libc::c_char, + pub blobdir: *mut libc::c_char, + pub sql: *mut dc_sqlite3_t, + pub inbox: *mut dc_imap_t, + pub inboxidle_condmutex: pthread_mutex_t, + pub perform_inbox_jobs_needed: libc::c_int, + pub probe_imap_network: libc::c_int, + pub sentbox_thread: dc_jobthread_t, + pub mvbox_thread: dc_jobthread_t, + pub smtp: *mut dc_smtp_t, + pub smtpidle_cond: pthread_cond_t, + pub smtpidle_condmutex: pthread_mutex_t, + pub smtpidle_condflag: libc::c_int, + pub smtp_suspended: libc::c_int, + pub smtp_doing_jobs: libc::c_int, + pub perform_smtp_jobs_needed: libc::c_int, + pub probe_smtp_network: libc::c_int, + pub oauth2_critical: pthread_mutex_t, + 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 type dc_lot_t = _dc_lot; +/* * Structure behind dc_lot_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_lot { + pub magic: uint32_t, + pub text1_meaning: libc::c_int, + pub text1: *mut libc::c_char, + pub text2: *mut libc::c_char, + pub timestamp: time_t, + pub state: libc::c_int, + pub id: uint32_t, + pub fingerprint: *mut libc::c_char, + pub invitenumber: *mut libc::c_char, + pub auth: *mut libc::c_char, +} +/* * + * 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 = Option< + unsafe extern "C" fn( + _: *mut dc_context_t, + _: libc::c_int, + _: uintptr_t, + _: uintptr_t, + ) -> uintptr_t, +>; +/* * + * @mainpage Getting started + * + * This document describes how to handle the Delta Chat core library. + * For general information about Delta Chat itself, + * see and . + * + * Let's start. + * + * First of all, you have to **define an event-handler-function** + * that is called by the library on specific events + * (eg. when the configuration is done or when fresh messages arrive). + * With this function you can create a Delta Chat context then: + * + * ~~~ + * #include + * + * uintptr_t event_handler_func(dc_context_t* context, int event, + * uintptr_t data1, uintptr_t data2) + * { + * return 0; // for unhandled events, it is always safe to return 0 + * } + * + * dc_context_t* context = dc_context_new(event_handler_func, NULL, NULL); + * ~~~ + * + * After that, you should make sure, + * sending and receiving jobs are processed as needed. + * For this purpose, you have to **create two threads:** + * + * ~~~ + * #include + * + * void* imap_thread_func(void* context) + * { + * while (true) { + * dc_perform_imap_jobs(context); + * dc_perform_imap_fetch(context); + * dc_perform_imap_idle(context); + * } + * } + * + * void* smtp_thread_func(void* context) + * { + * while (true) { + * dc_perform_smtp_jobs(context); + * dc_perform_smtp_idle(context); + * } + * } + * + * static pthread_t imap_thread, smtp_thread; + * pthread_create(&imap_thread, NULL, imap_thread_func, context); + * pthread_create(&smtp_thread, NULL, smtp_thread_func, context); + * ~~~ + * + * The example above uses "pthreads", + * however, you can also use anything else for thread handling. + * NB: The deltachat-core library itself does not create any threads on its own, + * however, functions, unless stated otherwise, are thread-safe. + * + * After that you can **define and open a database.** + * The database is a normal sqlite-file and is created as needed: + * + * ~~~ + * dc_open(context, "example.db", NULL); + * ~~~ + * + * Now you can **configure the context:** + * + * ~~~ + * // use some real test credentials here + * dc_set_config(context, "addr", "alice@example.org"); + * dc_set_config(context, "mail_pw", "***"); + * dc_configure(context); + * ~~~ + * + * dc_configure() returns immediately, the configuration itself may take a while + * and is done by a job in the imap-thread you've defined above. + * Once done, the #DC_EVENT_CONFIGURE_PROGRESS reports success + * to the event_handler_func() that is also defined above. + * + * The configuration result is saved in the database, + * on subsequent starts it is not needed to call dc_configure() + * (you can check this using dc_is_configured()). + * + * Now you can **send the first message:** + * + * ~~~ + * // use a real testing address here + * uint32_t contact_id = dc_create_contact(context, NULL, "bob@example.org"); + * uint32_t chat_id = dc_create_chat_by_contact_id(context, contact_id); + * + * dc_send_text_msg(context, chat_id, "Hi, here is my first message!"); + * ~~~ + * + * dc_send_text_msg() returns immediately; + * the sending itself is done by a job in the smtp-thread you've defined above. + * If you check the testing address (bob) + * and you should have received a normal email. + * Answer this email in any email program with "Got it!" + * and the imap-thread you've create above will **receive the message**. + * + * You can then **list all messages** of a chat as follow: + * + * ~~~ + * dc_array_t* msglist = dc_get_chat_msgs(context, chat_id, 0, 0); + * for (int i = 0; i < dc_array_get_cnt(msglist); i++) + * { + * uint32_t msg_id = dc_array_get_id(msglist, i); + * dc_msg_t* msg = dc_get_msg(context, msg_id); + * char* text = dc_msg_get_text(msg); + * + * printf("Message %i: %s\n", i+1, text); + * + * free(text); + * dc_msg_unref(msg); + * } + * dc_array_unref(msglist); + * ~~~ + * + * This will output the following two lines: + * + * ~~~ + * Message 1: Hi, here is my first message! + * Message 2: Got it! + * ~~~ + * + * + * ## Class reference + * + * For a class reference, see the "Classes" link atop. + * + * + * ## Further hints + * + * Here are some additional, unsorted hints that may be useful. + * + * - For `get`-functions, you have to unref the return value in some way. + * + * - Strings in function arguments or return values are usually UTF-8 encoded. + * + * - The issue-tracker for the core library is here: + * + * + * The following points are important mainly + * for the authors of the library itself: + * + * - For indentation, use tabs. + * Alignments that are not placed at the beginning of a line + * should be done with spaces. + * + * - For padding between functions, + * classes etc. use 2 empty lines + * + * - Source files are encoded as UTF-8 with Unix line endings + * (a simple `LF`, `0x0A` or `\n`) + * + * If you need further assistance, + * please do not hesitate to contact us + * through the channels shown at https://delta.chat/en/contribute + * + * Please keep in mind, that your derived work + * must respect the Mozilla Public License 2.0 of libdeltachat + * and the respective licenses of the libraries libdeltachat links with. + * + * See you. + */ +/* * + * @class dc_context_t + * + * An object representing a single account. + * + * Each account is linked to an IMAP/SMTP account and uses a separate + * SQLite database for offline functionality and for account-related + * settings. + */ +pub type dc_context_t = _dc_context; +/* ** library-private **********************************************************/ +pub type dc_smtp_t = _dc_smtp; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_smtp { + 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 error: *mut libc::c_char, + pub error_etpan: libc::c_int, +} +pub type dc_jobthread_t = _dc_jobthread; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_jobthread { + 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, + 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, +} +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_imap { + 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 type dc_receive_imf_t = Option< + unsafe extern "C" 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_imap_t = _dc_imap; +pub type dc_precheck_imf_t = Option< + unsafe extern "C" 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< + unsafe extern "C" fn(_: *mut dc_imap_t, _: *const libc::c_char, _: *const libc::c_char) -> (), +>; +pub type dc_get_config_t = Option< + unsafe extern "C" fn( + _: *mut dc_imap_t, + _: *const libc::c_char, + _: *const libc::c_char, + ) -> *mut libc::c_char, +>; +/* ** library-private **********************************************************/ +pub type dc_sqlite3_t = _dc_sqlite3; +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_sqlite3 { + pub cobj: *mut sqlite3, + pub context: *mut dc_context_t, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct oauth2_t { + pub client_id: *mut libc::c_char, + pub get_code: *mut libc::c_char, + pub init_token: *mut libc::c_char, + pub refresh_token: *mut libc::c_char, + pub get_userinfo: *mut libc::c_char, +} +/* * + * JSON token description. + * type type (object, array, string etc.) + * start start position in JSON data string + * end end position in JSON data string + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct jsmntok_t { + pub type_0: jsmntype_t, + pub start: libc::c_int, + pub end: libc::c_int, + pub size: libc::c_int, +} +/* +Copyright (c) 2010 Serge A. Zaitsev + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +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. +*/ +/* * + * JSON type identifier. Basic types are: + * o Object + * o Array + * o String + * o Other primitive: number, boolean (true/false) or null + */ +pub type jsmntype_t = libc::c_uint; +pub const JSMN_PRIMITIVE: jsmntype_t = 4; +pub const JSMN_STRING: jsmntype_t = 3; +pub const JSMN_ARRAY: jsmntype_t = 2; +pub const JSMN_OBJECT: jsmntype_t = 1; +pub const JSMN_UNDEFINED: jsmntype_t = 0; +/* * + * JSON parser. Contains an array of token blocks available. Also stores + * the string being parsed now and current position in that string + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct jsmn_parser { + pub pos: libc::c_uint, + pub toknext: libc::c_uint, + pub toksuper: libc::c_int, +} +#[no_mangle] +pub unsafe extern "C" fn dc_get_oauth2_url( + mut context: *mut 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) + { + oauth2 = get_info(addr); + if !oauth2.is_null() { + dc_sqlite3_set_config( + (*context).sql, + b"oauth2_pending_redirect_uri\x00" as *const u8 as *const libc::c_char, + redirect_uri, + ); + oauth2_url = dc_strdup((*oauth2).get_code); + replace_in_uri( + &mut oauth2_url, + b"$CLIENT_ID\x00" as *const u8 as *const libc::c_char, + (*oauth2).client_id, + ); + replace_in_uri( + &mut oauth2_url, + b"$REDIRECT_URI\x00" as *const u8 as *const libc::c_char, + redirect_uri, + ); + } + } + free(oauth2 as *mut libc::c_void); + return oauth2_url; +} +unsafe extern "C" fn replace_in_uri( + mut uri: *mut *mut libc::c_char, + mut key: *const libc::c_char, + mut value: *const libc::c_char, +) { + if !uri.is_null() && !key.is_null() && !value.is_null() { + let mut value_urlencoded: *mut libc::c_char = dc_urlencode(value); + dc_str_replace(uri, key, value_urlencoded); + free(value_urlencoded as *mut libc::c_void); + }; +} +unsafe extern "C" 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; + addr_normalized = dc_addr_normalize(addr); + domain = strchr(addr_normalized, '@' as i32); + if !(domain.is_null() || *domain.offset(0isize) as libc::c_int == 0i32) { + domain = domain.offset(1isize); + if strcasecmp(domain, b"gmail.com\x00" as *const u8 as *const libc::c_char) == 0i32 + || strcasecmp( + domain, + b"googlemail.com\x00" as *const u8 as *const libc::c_char, + ) == 0i32 + { + oauth2 = calloc( + 1i32 as libc::c_ulong, + ::std::mem::size_of::() as libc::c_ulong, + ) as *mut oauth2_t; + (*oauth2).client_id = + b"959970109878-4mvtgf6feshskf7695nfln6002mom908.apps.googleusercontent.com\x00" + as *const u8 as *const libc::c_char as *mut libc::c_char; + (*oauth2).get_code = + b"https://accounts.google.com/o/oauth2/auth?client_id=$CLIENT_ID&redirect_uri=$REDIRECT_URI&response_type=code&scope=https%3A%2F%2Fmail.google.com%2F%20email&access_type=offline\x00" + as *const u8 as *const libc::c_char as *mut libc::c_char; + (*oauth2).init_token = + b"https://accounts.google.com/o/oauth2/token?client_id=$CLIENT_ID&redirect_uri=$REDIRECT_URI&code=$CODE&grant_type=authorization_code\x00" + as *const u8 as *const libc::c_char as *mut libc::c_char; + (*oauth2).refresh_token = + b"https://accounts.google.com/o/oauth2/token?client_id=$CLIENT_ID&redirect_uri=$REDIRECT_URI&refresh_token=$REFRESH_TOKEN&grant_type=refresh_token\x00" + as *const u8 as *const libc::c_char as *mut libc::c_char; + (*oauth2).get_userinfo = + b"https://www.googleapis.com/oauth2/v1/userinfo?alt=json&access_token=$ACCESS_TOKEN\x00" + as *const u8 as *const libc::c_char as *mut libc::c_char + } else if strcasecmp( + domain, + b"yandex.com\x00" as *const u8 as *const libc::c_char, + ) == 0i32 + || strcasecmp(domain, b"yandex.ru\x00" as *const u8 as *const libc::c_char) == 0i32 + || strcasecmp(domain, b"yandex.ua\x00" as *const u8 as *const libc::c_char) == 0i32 + { + oauth2 = calloc( + 1i32 as libc::c_ulong, + ::std::mem::size_of::() as libc::c_ulong, + ) as *mut oauth2_t; + (*oauth2).client_id = b"c4d0b6735fc8420a816d7e1303469341\x00" as *const u8 + as *const libc::c_char as *mut libc::c_char; + (*oauth2).get_code = + b"https://oauth.yandex.com/authorize?client_id=$CLIENT_ID&response_type=code&scope=mail%3Aimap_full%20mail%3Asmtp&force_confirm=true\x00" + as *const u8 as *const libc::c_char as *mut libc::c_char; + (*oauth2).init_token = + b"https://oauth.yandex.com/token?grant_type=authorization_code&code=$CODE&client_id=$CLIENT_ID&client_secret=58b8c6e94cf44fbe952da8511955dacf\x00" + as *const u8 as *const libc::c_char as *mut libc::c_char; + (*oauth2).refresh_token = + b"https://oauth.yandex.com/token?grant_type=refresh_token&refresh_token=$REFRESH_TOKEN&client_id=$CLIENT_ID&client_secret=58b8c6e94cf44fbe952da8511955dacf\x00" + as *const u8 as *const libc::c_char as *mut libc::c_char + } + } + free(addr_normalized as *mut libc::c_void); + return oauth2; +} +// the following function may block due http-requests; +// must not be called from the main thread or by the ui! +#[no_mangle] +pub unsafe extern "C" fn dc_get_oauth2_access_token( + mut context: *mut dc_context_t, + mut addr: *const libc::c_char, + mut code: *const libc::c_char, + mut flags: libc::c_int, +) -> *mut libc::c_char { + let mut current_block: u64; + let mut oauth2: *mut oauth2_t = 0 as *mut oauth2_t; + let mut access_token: *mut libc::c_char = 0 as *mut libc::c_char; + let mut refresh_token: *mut libc::c_char = 0 as *mut libc::c_char; + let mut refresh_token_for: *mut libc::c_char = 0 as *mut libc::c_char; + let mut redirect_uri: *mut libc::c_char = 0 as *mut libc::c_char; + let mut update_redirect_uri_on_success: libc::c_int = 0i32; + let mut token_url: *mut libc::c_char = 0 as *mut libc::c_char; + let mut expires_in: time_t = 0i32 as time_t; + let mut error: *mut libc::c_char = 0 as *mut libc::c_char; + let mut error_description: *mut libc::c_char = 0 as *mut libc::c_char; + let mut json: *mut libc::c_char = 0 as *mut libc::c_char; + let mut parser: jsmn_parser = jsmn_parser { + pos: 0, + toknext: 0, + toksuper: 0, + }; + // we do not expect nor read more tokens + let mut tok: [jsmntok_t; 128] = [jsmntok_t { + type_0: JSMN_UNDEFINED, + start: 0, + 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 + { + dc_log_warning( + context, + 0i32, + b"Internal OAuth2 error\x00" as *const u8 as *const libc::c_char, + ); + } else { + oauth2 = get_info(addr); + if oauth2.is_null() { + dc_log_warning( + context, + 0i32, + b"Internal OAuth2 error: 2\x00" as *const u8 as *const libc::c_char, + ); + } else { + pthread_mutex_lock(&mut (*context).oauth2_critical); + locked = 1i32; + // read generated token + if 0 == flags & 0x1i32 && 0 == is_expired(context) { + access_token = dc_sqlite3_get_config( + (*context).sql, + b"oauth2_access_token\x00" as *const u8 as *const libc::c_char, + 0 as *const libc::c_char, + ); + if !access_token.is_null() { + // success + current_block = 16914036240511706173; + } else { + current_block = 2838571290723028321; + } + } else { + current_block = 2838571290723028321; + } + match current_block { + 16914036240511706173 => {} + _ => { + refresh_token = dc_sqlite3_get_config( + (*context).sql, + 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, + 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, + ); + if refresh_token.is_null() || strcmp(refresh_token_for, code) != 0i32 { + dc_log_info( + context, + 0i32, + b"Generate OAuth2 refresh_token and access_token...\x00" as *const u8 + as *const libc::c_char, + ); + redirect_uri = dc_sqlite3_get_config( + (*context).sql, + 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, + ); + update_redirect_uri_on_success = 1i32; + token_url = dc_strdup((*oauth2).init_token) + } else { + dc_log_info( + context, + 0i32, + b"Regenerate OAuth2 access_token by refresh_token...\x00" as *const u8 + as *const libc::c_char, + ); + redirect_uri = dc_sqlite3_get_config( + (*context).sql, + b"oauth2_redirect_uri\x00" as *const u8 as *const libc::c_char, + b"unset\x00" as *const u8 as *const libc::c_char, + ); + token_url = dc_strdup((*oauth2).refresh_token) + } + replace_in_uri( + &mut token_url, + b"$CLIENT_ID\x00" as *const u8 as *const libc::c_char, + (*oauth2).client_id, + ); + replace_in_uri( + &mut token_url, + b"$REDIRECT_URI\x00" as *const u8 as *const libc::c_char, + redirect_uri, + ); + replace_in_uri( + &mut token_url, + b"$CODE\x00" as *const u8 as *const libc::c_char, + code, + ); + replace_in_uri( + &mut token_url, + b"$REFRESH_TOKEN\x00" as *const u8 as *const libc::c_char, + refresh_token, + ); + json = (*context).cb.expect("non-null function pointer")( + context, + 2110i32, + token_url as uintptr_t, + 0i32 as uintptr_t, + ) as *mut libc::c_char; + if json.is_null() { + dc_log_warning( + context, + 0i32, + b"Error calling OAuth2 at %s\x00" as *const u8 as *const libc::c_char, + token_url, + ); + } else { + jsmn_init(&mut parser); + tok_cnt = jsmn_parse( + &mut parser, + json, + strlen(json), + tok.as_mut_ptr(), + (::std::mem::size_of::<[jsmntok_t; 128]>() as libc::c_ulong) + .wrapping_div(::std::mem::size_of::() as libc::c_ulong) + as libc::c_uint, + ); + if tok_cnt < 2i32 + || tok[0usize].type_0 as libc::c_uint + != JSMN_OBJECT as libc::c_int as libc::c_uint + { + dc_log_warning( + context, + 0i32, + b"Failed to parse OAuth2 json from %s\x00" as *const u8 + as *const libc::c_char, + token_url, + ); + } else { + let mut i: libc::c_int = 1i32; + while i < tok_cnt { + if access_token.is_null() + && jsoneq( + json, + &mut *tok.as_mut_ptr().offset(i as isize), + b"access_token\x00" as *const u8 as *const libc::c_char, + ) == 0i32 + { + access_token = jsondup( + json, + &mut *tok.as_mut_ptr().offset((i + 1i32) as isize), + ) + } else if refresh_token.is_null() + && jsoneq( + json, + &mut *tok.as_mut_ptr().offset(i as isize), + b"refresh_token\x00" as *const u8 as *const libc::c_char, + ) == 0i32 + { + refresh_token = jsondup( + json, + &mut *tok.as_mut_ptr().offset((i + 1i32) as isize), + ) + } else if jsoneq( + json, + &mut *tok.as_mut_ptr().offset(i as isize), + b"expires_in\x00" as *const u8 as *const libc::c_char, + ) == 0i32 + { + let mut expires_in_str: *mut libc::c_char = jsondup( + json, + &mut *tok.as_mut_ptr().offset((i + 1i32) as isize), + ); + if !expires_in_str.is_null() { + let mut val: time_t = atol(expires_in_str); + if val > 20i32 as libc::c_long + && val + < (60i32 * 60i32 * 24i32 * 365i32 * 5i32) + as libc::c_long + { + expires_in = val + } + free(expires_in_str as *mut libc::c_void); + } + } else if error.is_null() + && jsoneq( + json, + &mut *tok.as_mut_ptr().offset(i as isize), + b"error\x00" as *const u8 as *const libc::c_char, + ) == 0i32 + { + error = jsondup( + json, + &mut *tok.as_mut_ptr().offset((i + 1i32) as isize), + ) + } else if error_description.is_null() + && jsoneq( + json, + &mut *tok.as_mut_ptr().offset(i as isize), + b"error_description\x00" as *const u8 + as *const libc::c_char, + ) == 0i32 + { + error_description = jsondup( + json, + &mut *tok.as_mut_ptr().offset((i + 1i32) as isize), + ) + } + i += 1 + } + if !error.is_null() || !error_description.is_null() { + dc_log_warning( + context, + 0i32, + b"OAuth error: %s: %s\x00" as *const u8 as *const libc::c_char, + if !error.is_null() { + error + } else { + b"unknown\x00" as *const u8 as *const libc::c_char + }, + if !error_description.is_null() { + error_description + } else { + b"no details\x00" as *const u8 as *const libc::c_char + }, + ); + } + if !refresh_token.is_null() + && 0 != *refresh_token.offset(0isize) as libc::c_int + { + dc_sqlite3_set_config( + (*context).sql, + b"oauth2_refresh_token\x00" as *const u8 as *const libc::c_char, + refresh_token, + ); + dc_sqlite3_set_config( + (*context).sql, + b"oauth2_refresh_token_for\x00" as *const u8 + as *const libc::c_char, + code, + ); + } + // after that, save the access token. + // if it's unset, we may get it in the next round as we have the refresh_token now. + if access_token.is_null() + || *access_token.offset(0isize) as libc::c_int == 0i32 + { + dc_log_warning( + context, + 0i32, + b"Failed to find OAuth2 access token\x00" as *const u8 + as *const libc::c_char, + ); + } else { + dc_sqlite3_set_config( + (*context).sql, + b"oauth2_access_token\x00" as *const u8 as *const libc::c_char, + access_token, + ); + dc_sqlite3_set_config_int64( + (*context).sql, + b"oauth2_timestamp_expires\x00" as *const u8 + as *const libc::c_char, + (if 0 != expires_in { + time(0 as *mut time_t) + expires_in - 5i32 as libc::c_long + } else { + 0i32 as libc::c_long + }) as int64_t, + ); + if 0 != update_redirect_uri_on_success { + dc_sqlite3_set_config( + (*context).sql, + b"oauth2_redirect_uri\x00" as *const u8 + as *const libc::c_char, + redirect_uri, + ); + } + } + } + } + } + } + } + } + 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); + free(token_url as *mut libc::c_void); + free(json as *mut libc::c_void); + free(error as *mut libc::c_void); + free(error_description as *mut libc::c_void); + free(oauth2 as *mut libc::c_void); + return if !access_token.is_null() { + access_token + } else { + dc_strdup(0 as *const libc::c_char) + }; +} +unsafe extern "C" 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 + { + return strndup( + json.offset((*tok).start as isize), + ((*tok).end - (*tok).start) as libc::c_ulong, + ); + } + return 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, + mut s: *const libc::c_char, +) -> libc::c_int { + if (*tok).type_0 as libc::c_uint == JSMN_STRING as libc::c_int as libc::c_uint + && strlen(s) as libc::c_int == (*tok).end - (*tok).start + && strncmp( + json.offset((*tok).start as isize), + s, + ((*tok).end - (*tok).start) as libc::c_ulong, + ) == 0i32 + { + return 0i32; + } + return -1i32; +} +unsafe extern "C" fn is_expired(mut context: *mut dc_context_t) -> libc::c_int { + let mut expire_timestamp: time_t = dc_sqlite3_get_config_int64( + (*context).sql, + b"oauth2_timestamp_expires\x00" as *const u8 as *const libc::c_char, + 0i32 as int64_t, + ) as time_t; + if expire_timestamp <= 0i32 as libc::c_long { + return 0i32; + } + if expire_timestamp > time(0 as *mut time_t) { + return 0i32; + } + return 1i32; +} +#[no_mangle] +pub unsafe extern "C" fn dc_get_oauth2_addr( + mut context: *mut 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()) + { + access_token = dc_get_oauth2_access_token(context, addr, code, 0i32); + addr_out = get_oauth2_addr(context, oauth2, access_token); + if addr_out.is_null() { + free(access_token as *mut libc::c_void); + access_token = dc_get_oauth2_access_token(context, addr, code, 0x1i32); + addr_out = get_oauth2_addr(context, oauth2, access_token) + } + } + free(access_token as *mut libc::c_void); + free(oauth2 as *mut libc::c_void); + return addr_out; +} +unsafe extern "C" fn get_oauth2_addr( + mut context: *mut dc_context_t, + mut oauth2: *const oauth2_t, + mut access_token: *const libc::c_char, +) -> *mut libc::c_char { + let mut addr_out: *mut libc::c_char = 0 as *mut libc::c_char; + let mut userinfo_url: *mut libc::c_char = 0 as *mut libc::c_char; + let mut json: *mut libc::c_char = 0 as *mut libc::c_char; + let mut parser: jsmn_parser = jsmn_parser { + pos: 0, + toknext: 0, + toksuper: 0, + }; + // we do not expect nor read more tokens + let mut tok: [jsmntok_t; 128] = [jsmntok_t { + type_0: JSMN_UNDEFINED, + start: 0, + 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() + || *access_token.offset(0isize) as libc::c_int == 0i32 + || oauth2.is_null()) + { + userinfo_url = dc_strdup((*oauth2).get_userinfo); + replace_in_uri( + &mut userinfo_url, + b"$ACCESS_TOKEN\x00" as *const u8 as *const libc::c_char, + access_token, + ); + json = (*context).cb.expect("non-null function pointer")( + context, + 2100i32, + userinfo_url as uintptr_t, + 0i32 as uintptr_t, + ) as *mut libc::c_char; + if json.is_null() { + dc_log_warning( + context, + 0i32, + b"Error getting userinfo.\x00" as *const u8 as *const libc::c_char, + ); + } else { + jsmn_init(&mut parser); + tok_cnt = jsmn_parse( + &mut parser, + json, + strlen(json), + tok.as_mut_ptr(), + (::std::mem::size_of::<[jsmntok_t; 128]>() as libc::c_ulong) + .wrapping_div(::std::mem::size_of::() as libc::c_ulong) + as libc::c_uint, + ); + if tok_cnt < 2i32 + || tok[0usize].type_0 as libc::c_uint != JSMN_OBJECT as libc::c_int as libc::c_uint + { + dc_log_warning( + context, + 0i32, + b"Failed to parse userinfo.\x00" as *const u8 as *const libc::c_char, + ); + } else { + let mut i: libc::c_int = 1i32; + while i < tok_cnt { + if addr_out.is_null() + && jsoneq( + json, + &mut *tok.as_mut_ptr().offset(i as isize), + b"email\x00" as *const u8 as *const libc::c_char, + ) == 0i32 + { + addr_out = jsondup(json, &mut *tok.as_mut_ptr().offset((i + 1i32) as isize)) + } + i += 1 + } + if addr_out.is_null() { + dc_log_warning( + context, + 0i32, + b"E-mail missing in userinfo.\x00" as *const u8 as *const libc::c_char, + ); + } + } + } + } + free(userinfo_url as *mut libc::c_void); + free(json as *mut libc::c_void); + return addr_out; +} diff --git a/src/dc_openssl.rs b/src/dc_openssl.rs new file mode 100644 index 000000000..c0db42f51 --- /dev/null +++ b/src/dc_openssl.rs @@ -0,0 +1,281 @@ +use libc; +extern "C" { + #[no_mangle] + fn malloc(_: libc::c_ulong) -> *mut libc::c_void; + #[no_mangle] + fn free(_: *mut libc::c_void); + #[no_mangle] + fn exit(_: libc::c_int) -> !; + /* return CRYPTO_NUM_LOCKS (shared libs!) */ + #[no_mangle] + fn CRYPTO_num_locks() -> libc::c_int; + #[no_mangle] + fn CRYPTO_set_locking_callback( + func: Option< + unsafe extern "C" fn( + _: libc::c_int, + _: libc::c_int, + _: *const libc::c_char, + _: libc::c_int, + ) -> (), + >, + ); + #[no_mangle] + fn CRYPTO_set_id_callback(func: Option libc::c_ulong>); + #[no_mangle] + fn CRYPTO_set_dynlock_create_callback( + dyn_create_function_0: Option< + unsafe extern "C" fn( + _: *const libc::c_char, + _: libc::c_int, + ) -> *mut CRYPTO_dynlock_value, + >, + ); + #[no_mangle] + fn CRYPTO_set_dynlock_lock_callback( + dyn_lock_function_0: Option< + unsafe extern "C" fn( + _: libc::c_int, + _: *mut CRYPTO_dynlock_value, + _: *const libc::c_char, + _: libc::c_int, + ) -> (), + >, + ); + #[no_mangle] + fn CRYPTO_set_dynlock_destroy_callback( + dyn_destroy_function_0: Option< + unsafe extern "C" fn( + _: *mut CRYPTO_dynlock_value, + _: *const libc::c_char, + _: libc::c_int, + ) -> (), + >, + ); + #[no_mangle] + fn OPENSSL_init(); + #[no_mangle] + fn OPENSSL_add_all_algorithms_noconf(); + #[no_mangle] + fn pthread_mutex_destroy(_: *mut pthread_mutex_t) -> libc::c_int; + #[no_mangle] + fn pthread_mutex_init(_: *mut pthread_mutex_t, _: *const pthread_mutexattr_t) -> libc::c_int; + #[no_mangle] + fn pthread_mutex_lock(_: *mut pthread_mutex_t) -> libc::c_int; + #[no_mangle] + fn pthread_mutex_unlock(_: *mut pthread_mutex_t) -> libc::c_int; + #[no_mangle] + fn pthread_self() -> pthread_t; + #[no_mangle] + fn mailstream_openssl_init_not_required(); +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct __darwin_pthread_handler_rec { + pub __routine: Option ()>, + pub __arg: *mut libc::c_void, + pub __next: *mut __darwin_pthread_handler_rec, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_mutex_t { + pub __sig: libc::c_long, + pub __opaque: [libc::c_char; 56], +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_mutexattr_t { + pub __sig: libc::c_long, + pub __opaque: [libc::c_char; 8], +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_t { + pub __sig: libc::c_long, + pub __cleanup_stack: *mut __darwin_pthread_handler_rec, + pub __opaque: [libc::c_char; 8176], +} +pub type __darwin_pthread_mutex_t = _opaque_pthread_mutex_t; +pub type __darwin_pthread_mutexattr_t = _opaque_pthread_mutexattr_t; +pub type __darwin_pthread_t = *mut _opaque_pthread_t; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct CRYPTO_dynlock_value { + pub mutex: pthread_mutex_t, +} +pub type pthread_mutex_t = __darwin_pthread_mutex_t; +pub type pthread_mutexattr_t = __darwin_pthread_mutexattr_t; +pub type pthread_t = __darwin_pthread_t; +#[no_mangle] +pub unsafe extern "C" fn dc_openssl_init_not_required() { + pthread_mutex_lock(&mut s_init_lock); + s_init_not_required = 1i32; + pthread_mutex_unlock(&mut s_init_lock); +} +static mut s_init_lock: pthread_mutex_t = _opaque_pthread_mutex_t { + __sig: 0x32aaaba7i32 as libc::c_long, + __opaque: [ + 0i32 as libc::c_char, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + ], +}; +static mut s_init_not_required: libc::c_int = 0i32; +static mut s_init_counter: libc::c_int = 0i32; +static mut s_mutex_buf: *mut pthread_mutex_t = 0 as *const pthread_mutex_t as *mut pthread_mutex_t; +unsafe extern "C" fn id_function() -> libc::c_ulong { + return pthread_self() as libc::c_ulong; +} +unsafe extern "C" fn locking_function( + mut mode: libc::c_int, + mut n: libc::c_int, + mut file: *const libc::c_char, + mut line: libc::c_int, +) { + if 0 != mode & 1i32 { + pthread_mutex_lock(&mut *s_mutex_buf.offset(n as isize)); + } else { + pthread_mutex_unlock(&mut *s_mutex_buf.offset(n as isize)); + }; +} +unsafe extern "C" fn dyn_create_function( + mut file: *const libc::c_char, + mut line: libc::c_int, +) -> *mut CRYPTO_dynlock_value { + let mut value: *mut CRYPTO_dynlock_value = + malloc(::std::mem::size_of::() as libc::c_ulong) + as *mut CRYPTO_dynlock_value; + if value.is_null() { + return 0 as *mut CRYPTO_dynlock_value; + } + pthread_mutex_init(&mut (*value).mutex, 0 as *const pthread_mutexattr_t); + return value; +} +unsafe extern "C" fn dyn_lock_function( + mut mode: libc::c_int, + mut l: *mut CRYPTO_dynlock_value, + mut file: *const libc::c_char, + mut line: libc::c_int, +) { + if 0 != mode & 1i32 { + pthread_mutex_lock(&mut (*l).mutex); + } else { + pthread_mutex_unlock(&mut (*l).mutex); + }; +} +unsafe extern "C" fn dyn_destroy_function( + mut l: *mut CRYPTO_dynlock_value, + mut file: *const libc::c_char, + mut line: libc::c_int, +) { + pthread_mutex_destroy(&mut (*l).mutex); + free(l as *mut libc::c_void); +} +#[no_mangle] +pub unsafe extern "C" fn dc_openssl_init() { + pthread_mutex_lock(&mut s_init_lock); + s_init_counter += 1; + if s_init_counter == 1i32 { + if 0 == s_init_not_required { + s_mutex_buf = malloc( + (CRYPTO_num_locks() as libc::c_ulong) + .wrapping_mul(::std::mem::size_of::() as libc::c_ulong), + ) as *mut pthread_mutex_t; + if s_mutex_buf.is_null() { + exit(53i32); + } + let mut i: libc::c_int = 0i32; + while i < CRYPTO_num_locks() { + pthread_mutex_init( + &mut *s_mutex_buf.offset(i as isize), + 0 as *const pthread_mutexattr_t, + ); + i += 1 + } + CRYPTO_set_id_callback(Some(id_function)); + CRYPTO_set_locking_callback(Some(locking_function)); + CRYPTO_set_dynlock_create_callback(Some(dyn_create_function)); + CRYPTO_set_dynlock_lock_callback(Some(dyn_lock_function)); + CRYPTO_set_dynlock_destroy_callback(Some(dyn_destroy_function)); + OPENSSL_init(); + OPENSSL_add_all_algorithms_noconf(); + } + mailstream_openssl_init_not_required(); + } + pthread_mutex_unlock(&mut s_init_lock); +} +#[no_mangle] +pub unsafe extern "C" fn dc_openssl_exit() { + pthread_mutex_lock(&mut s_init_lock); + if s_init_counter > 0i32 { + s_init_counter -= 1; + if s_init_counter == 0i32 && 0 == s_init_not_required { + CRYPTO_set_id_callback(None); + CRYPTO_set_locking_callback(None); + CRYPTO_set_dynlock_create_callback(None); + CRYPTO_set_dynlock_lock_callback(None); + CRYPTO_set_dynlock_destroy_callback(None); + let mut i: libc::c_int = 0i32; + while i < CRYPTO_num_locks() { + pthread_mutex_destroy(&mut *s_mutex_buf.offset(i as isize)); + i += 1 + } + free(s_mutex_buf as *mut libc::c_void); + s_mutex_buf = 0 as *mut pthread_mutex_t + } + } + pthread_mutex_unlock(&mut s_init_lock); +} diff --git a/src/dc_param.rs b/src/dc_param.rs new file mode 100644 index 000000000..de4bbe055 --- /dev/null +++ b/src/dc_param.rs @@ -0,0 +1,332 @@ +use libc; +extern "C" { + #[no_mangle] + fn calloc(_: libc::c_ulong, _: libc::c_ulong) -> *mut libc::c_void; + #[no_mangle] + fn free(_: *mut libc::c_void); + #[no_mangle] + fn atol(_: *const libc::c_char) -> libc::c_long; + #[no_mangle] + fn exit(_: libc::c_int) -> !; + #[no_mangle] + fn strchr(_: *const libc::c_char, _: libc::c_int) -> *mut libc::c_char; + #[no_mangle] + fn strlen(_: *const libc::c_char) -> libc::c_ulong; + /* string tools */ + #[no_mangle] + fn dc_strdup(_: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn dc_ltrim(_: *mut libc::c_char); + #[no_mangle] + fn dc_rtrim(_: *mut libc::c_char); + #[no_mangle] + fn dc_str_replace( + haystack: *mut *mut libc::c_char, + needle: *const libc::c_char, + replacement: *const libc::c_char, + ) -> libc::c_int; + #[no_mangle] + fn dc_mprintf(format: *const libc::c_char, _: ...) -> *mut libc::c_char; +} +pub type int32_t = libc::c_int; +pub type dc_param_t = _dc_param; +/* * + * @class dc_param_t + * + * An object for handling key=value parameter lists; for the key, curently only + * a single character is allowed. + * + * The object is used eg. by dc_chat_t or dc_msg_t, for readable paramter names, + * these classes define some DC_PARAM_* constantats. + * + * Only for library-internal use. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_param { + pub packed: *mut libc::c_char, +} +/* for msgs and jobs */ +/* for msgs */ +/* for msgs */ +/* for msgs */ +/* for msgs */ +/* for msgs: incoming: message is encryoted, outgoing: guarantee E2EE or the message is not send */ +/* for msgs: decrypted with validation errors or without mutual set, if neither 'c' nor 'e' are preset, the messages is only transport encrypted */ +/* for msgs: force unencrypted message, either DC_FP_ADD_AUTOCRYPT_HEADER (1), DC_FP_NO_AUTOCRYPT_HEADER (2) or 0 */ +/* for msgs: an incoming message which requestes a MDN (aka read receipt) */ +/* for msgs */ +/* for msgs */ +/* for msgs */ +/* for msgs */ +/* for msgs */ +/* for msgs */ +/* for msgs */ +/* for msgs in PREPARING: space-separated list of message IDs of forwarded copies */ +/* for jobs */ +/* for jobs */ +/* for jobs */ +/* for jobs: space-separated list of message recipients */ +/* for groups */ +/* for groups and contacts */ +/* for chats */ +// values for DC_PARAM_FORCE_PLAINTEXT +/* user functions */ +#[no_mangle] +pub unsafe extern "C" fn dc_param_exists( + mut param: *mut dc_param_t, + mut key: libc::c_int, +) -> libc::c_int { + let mut p2: *mut libc::c_char = 0 as *mut libc::c_char; + if param.is_null() || key == 0i32 { + return 0i32; + } + return if !find_param((*param).packed, key, &mut p2).is_null() { + 1i32 + } else { + 0i32 + }; +} +unsafe extern "C" fn find_param( + mut haystack: *mut libc::c_char, + 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; + p1 = haystack; + loop { + if p1.is_null() || *p1 as libc::c_int == 0i32 { + return 0 as *mut libc::c_char; + } else { + if *p1 as libc::c_int == key && *p1.offset(1isize) as libc::c_int == '=' as i32 { + break; + } + p1 = strchr(p1, '\n' as i32); + if !p1.is_null() { + p1 = p1.offset(1isize) + } + } + } + p2 = strchr(p1, '\n' as i32); + if p2.is_null() { + p2 = &mut *p1.offset(strlen(p1) as isize) as *mut libc::c_char + } + *ret_p2 = p2; + return 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. */ +#[no_mangle] +pub unsafe extern "C" fn dc_param_get( + mut param: *const dc_param_t, + mut key: libc::c_int, + mut def: *const 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 bak: libc::c_char = 0i32 as libc::c_char; + let mut ret: *mut libc::c_char = 0 as *mut libc::c_char; + if param.is_null() || key == 0i32 { + return if !def.is_null() { + dc_strdup(def) + } else { + 0 as *mut libc::c_char + }; + } + p1 = find_param((*param).packed, key, &mut p2); + if p1.is_null() { + return if !def.is_null() { + dc_strdup(def) + } else { + 0 as *mut libc::c_char + }; + } + p1 = p1.offset(2isize); + bak = *p2; + *p2 = 0i32 as libc::c_char; + ret = dc_strdup(p1); + dc_rtrim(ret); + *p2 = bak; + return ret; +} +#[no_mangle] +pub unsafe extern "C" fn dc_param_get_int( + mut param: *const dc_param_t, + mut key: libc::c_int, + mut def: int32_t, +) -> int32_t { + if param.is_null() || key == 0i32 { + return def; + } + let mut str: *mut libc::c_char = dc_param_get(param, key, 0 as *const libc::c_char); + if str.is_null() { + return def; + } + let mut ret: int32_t = atol(str) as int32_t; + free(str as *mut libc::c_void); + return ret; +} +#[no_mangle] +pub unsafe extern "C" fn dc_param_set( + mut param: *mut dc_param_t, + 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; + 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 p2: *mut libc::c_char = 0 as *mut libc::c_char; + p1 = find_param(old1, key, &mut p2); + if !p1.is_null() { + *p1 = 0i32 as libc::c_char; + old2 = p2 + } else if value.is_null() { + return; + } + } + dc_rtrim(old1); + dc_ltrim(old2); + if !old1.is_null() && *old1.offset(0isize) as libc::c_int == 0i32 { + old1 = 0 as *mut libc::c_char + } + if !old2.is_null() && *old2.offset(0isize) as libc::c_int == 0i32 { + old2 = 0 as *mut libc::c_char + } + if !value.is_null() { + new1 = dc_mprintf( + b"%s%s%c=%s%s%s\x00" as *const u8 as *const libc::c_char, + if !old1.is_null() { + old1 + } else { + b"\x00" as *const u8 as *const libc::c_char + }, + if !old1.is_null() { + b"\n\x00" as *const u8 as *const libc::c_char + } else { + b"\x00" as *const u8 as *const libc::c_char + }, + key, + value, + if !old2.is_null() { + b"\n\x00" as *const u8 as *const libc::c_char + } else { + b"\x00" as *const u8 as *const libc::c_char + }, + if !old2.is_null() { + old2 + } else { + b"\x00" as *const u8 as *const libc::c_char + }, + ) + } else { + new1 = dc_mprintf( + b"%s%s%s\x00" as *const u8 as *const libc::c_char, + if !old1.is_null() { + old1 + } else { + b"\x00" as *const u8 as *const libc::c_char + }, + if !old1.is_null() && !old2.is_null() { + b"\n\x00" as *const u8 as *const libc::c_char + } else { + b"\x00" as *const u8 as *const libc::c_char + }, + if !old2.is_null() { + old2 + } else { + b"\x00" as *const u8 as *const libc::c_char + }, + ) + } + free((*param).packed as *mut libc::c_void); + (*param).packed = new1; +} +#[no_mangle] +pub unsafe extern "C" fn dc_param_set_int( + mut param: *mut dc_param_t, + mut key: libc::c_int, + mut value: int32_t, +) { + if param.is_null() || key == 0i32 { + return; + } + let mut value_str: *mut libc::c_char = dc_mprintf( + b"%i\x00" as *const u8 as *const libc::c_char, + value as libc::c_int, + ); + if value_str.is_null() { + return; + } + dc_param_set(param, key, value_str); + free(value_str as *mut libc::c_void); +} +/* library-private */ +#[no_mangle] +pub unsafe extern "C" fn dc_param_new() -> *mut dc_param_t { + let mut param: *mut dc_param_t = 0 as *mut dc_param_t; + param = calloc( + 1i32 as libc::c_ulong, + ::std::mem::size_of::() as libc::c_ulong, + ) as *mut dc_param_t; + if param.is_null() { + exit(28i32); + } + (*param).packed = calloc(1i32 as libc::c_ulong, 1i32 as libc::c_ulong) as *mut libc::c_char; + return param; +} +#[no_mangle] +pub unsafe extern "C" fn dc_param_empty(mut param: *mut dc_param_t) { + if param.is_null() { + return; + } + *(*param).packed.offset(0isize) = 0i32 as libc::c_char; +} +#[no_mangle] +pub unsafe extern "C" fn dc_param_unref(mut param: *mut dc_param_t) { + if param.is_null() { + return; + } + dc_param_empty(param); + free((*param).packed as *mut libc::c_void); + free(param as *mut libc::c_void); +} +#[no_mangle] +pub unsafe extern "C" fn dc_param_set_packed( + mut param: *mut dc_param_t, + mut packed: *const libc::c_char, +) { + if param.is_null() { + return; + } + dc_param_empty(param); + if !packed.is_null() { + free((*param).packed as *mut libc::c_void); + (*param).packed = dc_strdup(packed) + }; +} +#[no_mangle] +pub unsafe extern "C" fn dc_param_set_urlencoded( + mut param: *mut dc_param_t, + mut urlencoded: *const libc::c_char, +) { + if param.is_null() { + return; + } + dc_param_empty(param); + if !urlencoded.is_null() { + free((*param).packed as *mut libc::c_void); + (*param).packed = dc_strdup(urlencoded); + dc_str_replace( + &mut (*param).packed, + b"&\x00" as *const u8 as *const libc::c_char, + b"\n\x00" as *const u8 as *const libc::c_char, + ); + }; +} diff --git a/src/dc_pgp.rs b/src/dc_pgp.rs new file mode 100644 index 000000000..8de534d9a --- /dev/null +++ b/src/dc_pgp.rs @@ -0,0 +1,1687 @@ +use c2rust_bitfields::BitfieldStruct; +use libc; +extern "C" { + pub type mailstream_cancel; + pub type sqlite3; + pub type rpgp_Message; + pub type rpgp_PublicOrSecret; + pub type rpgp_SignedPublicKey; + pub type rpgp_SignedSecretKey; + #[no_mangle] + fn malloc(_: libc::c_ulong) -> *mut libc::c_void; + #[no_mangle] + fn free(_: *mut libc::c_void); + #[no_mangle] + fn memcpy(_: *mut libc::c_void, _: *const libc::c_void, _: libc::c_ulong) -> *mut libc::c_void; + #[no_mangle] + fn strchr(_: *const libc::c_char, _: libc::c_int) -> *mut libc::c_char; + #[no_mangle] + fn strlen(_: *const libc::c_char) -> libc::c_ulong; + #[no_mangle] + fn strncmp(_: *const libc::c_char, _: *const libc::c_char, _: libc::c_ulong) -> libc::c_int; + #[no_mangle] + fn strspn(_: *const libc::c_char, _: *const libc::c_char) -> libc::c_ulong; + #[no_mangle] + fn strstr(_: *const libc::c_char, _: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn strcasecmp(_: *const libc::c_char, _: *const libc::c_char) -> libc::c_int; + #[no_mangle] + fn clock() -> clock_t; + #[no_mangle] + fn dc_trim(_: *mut libc::c_char); + #[no_mangle] + fn dc_mprintf(format: *const libc::c_char, _: ...) -> *mut libc::c_char; + #[no_mangle] + fn dc_remove_cr_chars(_: *mut libc::c_char); + #[no_mangle] + fn dc_key_set_from_binary( + _: *mut dc_key_t, + data: *const libc::c_void, + bytes: libc::c_int, + type_0: libc::c_int, + ) -> libc::c_int; + #[no_mangle] + fn dc_hash_insert( + _: *mut dc_hash_t, + pKey: *const libc::c_void, + nKey: libc::c_int, + pData: *mut libc::c_void, + ) -> *mut libc::c_void; + #[no_mangle] + fn dc_log_warning(_: *mut dc_context_t, data1: libc::c_int, msg: *const libc::c_char, _: ...); + #[no_mangle] + fn dc_log_info(_: *mut dc_context_t, data1: libc::c_int, msg: *const libc::c_char, _: ...); + #[no_mangle] + fn rpgp_create_rsa_skey( + bits: uint32_t, + user_id: *const libc::c_char, + ) -> *mut rpgp_signed_secret_key; + #[no_mangle] + fn rpgp_cvec_data(cvec_ptr: *mut rpgp_cvec) -> *const uint8_t; + #[no_mangle] + fn rpgp_cvec_drop(cvec_ptr: *mut rpgp_cvec); + #[no_mangle] + fn rpgp_cvec_len(cvec_ptr: *mut rpgp_cvec) -> size_t; + #[no_mangle] + fn rpgp_encrypt_bytes_to_keys( + bytes_ptr: *const uint8_t, + bytes_len: size_t, + pkeys_ptr: *const *const rpgp_signed_public_key, + pkeys_len: size_t, + ) -> *mut rpgp_message; + #[no_mangle] + fn rpgp_encrypt_bytes_with_password( + bytes_ptr: *const uint8_t, + bytes_len: size_t, + password_ptr: *const libc::c_char, + ) -> *mut rpgp_message; + #[no_mangle] + fn rpgp_key_drop(key_ptr: *mut rpgp_public_or_secret_key); + #[no_mangle] + fn rpgp_key_fingerprint(key_ptr: *mut rpgp_public_or_secret_key) -> *mut rpgp_cvec; + #[no_mangle] + fn rpgp_key_from_bytes(raw: *const uint8_t, len: size_t) -> *mut rpgp_public_or_secret_key; + #[no_mangle] + fn rpgp_key_is_public(key_ptr: *mut rpgp_public_or_secret_key) -> bool; + #[no_mangle] + fn rpgp_key_is_secret(key_ptr: *mut rpgp_public_or_secret_key) -> bool; + #[no_mangle] + fn rpgp_last_error_length() -> libc::c_int; + #[no_mangle] + fn rpgp_last_error_message() -> *mut libc::c_char; + #[no_mangle] + fn rpgp_message_decrypt_result_drop(res_ptr: *mut rpgp_message_decrypt_result); + #[no_mangle] + fn rpgp_msg_decrypt_no_pw( + msg_ptr: *const rpgp_message, + skeys_ptr: *const *const rpgp_signed_secret_key, + skeys_len: size_t, + pkeys_ptr: *const *const rpgp_signed_public_key, + pkeys_len: size_t, + ) -> *mut rpgp_message_decrypt_result; + #[no_mangle] + fn rpgp_msg_decrypt_with_password( + msg_ptr: *const rpgp_message, + password_ptr: *const libc::c_char, + ) -> *mut rpgp_message; + #[no_mangle] + fn rpgp_msg_drop(msg_ptr: *mut rpgp_message); + #[no_mangle] + fn rpgp_msg_from_armor(msg_ptr: *const uint8_t, msg_len: size_t) -> *mut rpgp_message; + #[no_mangle] + fn rpgp_msg_from_bytes(msg_ptr: *const uint8_t, msg_len: size_t) -> *mut rpgp_message; + #[no_mangle] + fn rpgp_msg_to_armored(msg_ptr: *const rpgp_message) -> *mut rpgp_cvec; + #[no_mangle] + fn rpgp_msg_to_armored_str(msg_ptr: *const rpgp_message) -> *mut libc::c_char; + #[no_mangle] + fn rpgp_msg_to_bytes(msg_ptr: *const rpgp_message) -> *mut rpgp_cvec; + #[no_mangle] + fn rpgp_pkey_drop(pkey_ptr: *mut rpgp_signed_public_key); + #[no_mangle] + fn rpgp_pkey_from_bytes(raw: *const uint8_t, len: size_t) -> *mut rpgp_signed_public_key; + #[no_mangle] + fn rpgp_pkey_to_bytes(pkey_ptr: *mut rpgp_signed_public_key) -> *mut rpgp_cvec; + #[no_mangle] + fn rpgp_sign_encrypt_bytes_to_keys( + bytes_ptr: *const uint8_t, + bytes_len: size_t, + pkeys_ptr: *const *const rpgp_signed_public_key, + pkeys_len: size_t, + skey_ptr: *const rpgp_signed_secret_key, + ) -> *mut rpgp_message; + #[no_mangle] + fn rpgp_skey_drop(skey_ptr: *mut rpgp_signed_secret_key); + #[no_mangle] + fn rpgp_skey_from_bytes(raw: *const uint8_t, len: size_t) -> *mut rpgp_signed_secret_key; + #[no_mangle] + fn rpgp_skey_public_key(skey_ptr: *mut rpgp_signed_secret_key) -> *mut rpgp_signed_public_key; + #[no_mangle] + fn rpgp_skey_to_bytes(skey_ptr: *mut rpgp_signed_secret_key) -> *mut rpgp_cvec; + #[no_mangle] + fn rpgp_string_drop(p: *mut libc::c_char); +} +pub type __darwin_size_t = libc::c_ulong; +pub type __darwin_clock_t = libc::c_ulong; +pub type __darwin_ssize_t = libc::c_long; +pub type __darwin_time_t = libc::c_long; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_cond_t { + pub __sig: libc::c_long, + pub __opaque: [libc::c_char; 40], +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_mutex_t { + pub __sig: libc::c_long, + pub __opaque: [libc::c_char; 56], +} +pub type __darwin_pthread_cond_t = _opaque_pthread_cond_t; +pub type __darwin_pthread_mutex_t = _opaque_pthread_mutex_t; +pub type uintptr_t = libc::c_ulong; +pub type size_t = __darwin_size_t; +pub type uint8_t = libc::c_uchar; +pub type uint32_t = libc::c_uint; +pub type ssize_t = __darwin_ssize_t; +pub type clock_t = __darwin_clock_t; +pub type time_t = __darwin_time_t; +pub type pthread_cond_t = __darwin_pthread_cond_t; +pub type pthread_mutex_t = __darwin_pthread_mutex_t; +#[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; +#[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) -> (); +#[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; +#[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, + 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 { + 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_capability_data { + pub cap_list: *mut clist, +} +#[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_0, + 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_0 { + 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 extern "C" 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_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, +} +#[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_1, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed_1 { + pub ft_fetch_att: *mut mailimap_fetch_att, + pub ft_fetch_att_list: *mut clist, +} +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 unnamed_2 { + 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, +} +/* define DC_USE_RPGP to enable use of rPGP instead of netpgp where available; +preferrably, this should be done in the project configuration currently */ +//#define DC_USE_RPGP 1 +/* Includes that are used frequently. This file may also be used to create predefined headers. */ +/* * Structure behind dc_context_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_context { + pub magic: uint32_t, + pub userdata: *mut libc::c_void, + pub dbfile: *mut libc::c_char, + pub blobdir: *mut libc::c_char, + pub sql: *mut dc_sqlite3_t, + pub inbox: *mut dc_imap_t, + pub inboxidle_condmutex: pthread_mutex_t, + pub perform_inbox_jobs_needed: libc::c_int, + pub probe_imap_network: libc::c_int, + pub sentbox_thread: dc_jobthread_t, + pub mvbox_thread: dc_jobthread_t, + pub smtp: *mut dc_smtp_t, + pub smtpidle_cond: pthread_cond_t, + pub smtpidle_condmutex: pthread_mutex_t, + pub smtpidle_condflag: libc::c_int, + pub smtp_suspended: libc::c_int, + pub smtp_doing_jobs: libc::c_int, + pub perform_smtp_jobs_needed: libc::c_int, + pub probe_smtp_network: libc::c_int, + pub oauth2_critical: pthread_mutex_t, + 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 type dc_lot_t = _dc_lot; +/* * Structure behind dc_lot_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_lot { + pub magic: uint32_t, + pub text1_meaning: libc::c_int, + pub text1: *mut libc::c_char, + pub text2: *mut libc::c_char, + pub timestamp: time_t, + pub state: libc::c_int, + pub id: uint32_t, + pub fingerprint: *mut libc::c_char, + pub invitenumber: *mut libc::c_char, + pub auth: *mut libc::c_char, +} +/* * + * 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 = Option< + unsafe extern "C" fn( + _: *mut dc_context_t, + _: libc::c_int, + _: uintptr_t, + _: uintptr_t, + ) -> uintptr_t, +>; +/* * + * @mainpage Getting started + * + * This document describes how to handle the Delta Chat core library. + * For general information about Delta Chat itself, + * see and . + * + * Let's start. + * + * First of all, you have to **define an event-handler-function** + * that is called by the library on specific events + * (eg. when the configuration is done or when fresh messages arrive). + * With this function you can create a Delta Chat context then: + * + * ~~~ + * #include + * + * uintptr_t event_handler_func(dc_context_t* context, int event, + * uintptr_t data1, uintptr_t data2) + * { + * return 0; // for unhandled events, it is always safe to return 0 + * } + * + * dc_context_t* context = dc_context_new(event_handler_func, NULL, NULL); + * ~~~ + * + * After that, you should make sure, + * sending and receiving jobs are processed as needed. + * For this purpose, you have to **create two threads:** + * + * ~~~ + * #include + * + * void* imap_thread_func(void* context) + * { + * while (true) { + * dc_perform_imap_jobs(context); + * dc_perform_imap_fetch(context); + * dc_perform_imap_idle(context); + * } + * } + * + * void* smtp_thread_func(void* context) + * { + * while (true) { + * dc_perform_smtp_jobs(context); + * dc_perform_smtp_idle(context); + * } + * } + * + * static pthread_t imap_thread, smtp_thread; + * pthread_create(&imap_thread, NULL, imap_thread_func, context); + * pthread_create(&smtp_thread, NULL, smtp_thread_func, context); + * ~~~ + * + * The example above uses "pthreads", + * however, you can also use anything else for thread handling. + * NB: The deltachat-core library itself does not create any threads on its own, + * however, functions, unless stated otherwise, are thread-safe. + * + * After that you can **define and open a database.** + * The database is a normal sqlite-file and is created as needed: + * + * ~~~ + * dc_open(context, "example.db", NULL); + * ~~~ + * + * Now you can **configure the context:** + * + * ~~~ + * // use some real test credentials here + * dc_set_config(context, "addr", "alice@example.org"); + * dc_set_config(context, "mail_pw", "***"); + * dc_configure(context); + * ~~~ + * + * dc_configure() returns immediately, the configuration itself may take a while + * and is done by a job in the imap-thread you've defined above. + * Once done, the #DC_EVENT_CONFIGURE_PROGRESS reports success + * to the event_handler_func() that is also defined above. + * + * The configuration result is saved in the database, + * on subsequent starts it is not needed to call dc_configure() + * (you can check this using dc_is_configured()). + * + * Now you can **send the first message:** + * + * ~~~ + * // use a real testing address here + * uint32_t contact_id = dc_create_contact(context, NULL, "bob@example.org"); + * uint32_t chat_id = dc_create_chat_by_contact_id(context, contact_id); + * + * dc_send_text_msg(context, chat_id, "Hi, here is my first message!"); + * ~~~ + * + * dc_send_text_msg() returns immediately; + * the sending itself is done by a job in the smtp-thread you've defined above. + * If you check the testing address (bob) + * and you should have received a normal email. + * Answer this email in any email program with "Got it!" + * and the imap-thread you've create above will **receive the message**. + * + * You can then **list all messages** of a chat as follow: + * + * ~~~ + * dc_array_t* msglist = dc_get_chat_msgs(context, chat_id, 0, 0); + * for (int i = 0; i < dc_array_get_cnt(msglist); i++) + * { + * uint32_t msg_id = dc_array_get_id(msglist, i); + * dc_msg_t* msg = dc_get_msg(context, msg_id); + * char* text = dc_msg_get_text(msg); + * + * printf("Message %i: %s\n", i+1, text); + * + * free(text); + * dc_msg_unref(msg); + * } + * dc_array_unref(msglist); + * ~~~ + * + * This will output the following two lines: + * + * ~~~ + * Message 1: Hi, here is my first message! + * Message 2: Got it! + * ~~~ + * + * + * ## Class reference + * + * For a class reference, see the "Classes" link atop. + * + * + * ## Further hints + * + * Here are some additional, unsorted hints that may be useful. + * + * - For `get`-functions, you have to unref the return value in some way. + * + * - Strings in function arguments or return values are usually UTF-8 encoded. + * + * - The issue-tracker for the core library is here: + * + * + * The following points are important mainly + * for the authors of the library itself: + * + * - For indentation, use tabs. + * Alignments that are not placed at the beginning of a line + * should be done with spaces. + * + * - For padding between functions, + * classes etc. use 2 empty lines + * + * - Source files are encoded as UTF-8 with Unix line endings + * (a simple `LF`, `0x0A` or `\n`) + * + * If you need further assistance, + * please do not hesitate to contact us + * through the channels shown at https://delta.chat/en/contribute + * + * Please keep in mind, that your derived work + * must respect the Mozilla Public License 2.0 of libdeltachat + * and the respective licenses of the libraries libdeltachat links with. + * + * See you. + */ +/* * + * @class dc_context_t + * + * An object representing a single account. + * + * Each account is linked to an IMAP/SMTP account and uses a separate + * SQLite database for offline functionality and for account-related + * settings. + */ +pub type dc_context_t = _dc_context; +/* ** library-private **********************************************************/ +pub type dc_smtp_t = _dc_smtp; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_smtp { + 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 error: *mut libc::c_char, + pub error_etpan: libc::c_int, +} +pub type dc_jobthread_t = _dc_jobthread; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_jobthread { + 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, + 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, +} +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_imap { + 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 type dc_receive_imf_t = Option< + unsafe extern "C" 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_imap_t = _dc_imap; +pub type dc_precheck_imf_t = Option< + unsafe extern "C" 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< + unsafe extern "C" fn(_: *mut dc_imap_t, _: *const libc::c_char, _: *const libc::c_char) -> (), +>; +pub type dc_get_config_t = Option< + unsafe extern "C" fn( + _: *mut dc_imap_t, + _: *const libc::c_char, + _: *const libc::c_char, + ) -> *mut libc::c_char, +>; +/* ** library-private **********************************************************/ +pub type dc_sqlite3_t = _dc_sqlite3; +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_sqlite3 { + pub cobj: *mut sqlite3, + pub context: *mut dc_context_t, +} +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_key { + pub binary: *mut libc::c_void, + pub bytes: libc::c_int, + pub type_0: libc::c_int, + pub _m_heap_refcnt: libc::c_int, +} +pub type dc_key_t = _dc_key; +/* A complete hash table is an instance of the following structure. + * The internals of this structure are intended to be opaque -- client + * code should not attempt to access or modify the fields of this structure + * directly. Change this structure only by using the routines below. + * However, many of the "procedures" and "functions" for modifying and + * accessing this structure are really macros, so we can't really make + * this structure opaque. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_hash { + pub keyClass: libc::c_char, + pub copyKey: libc::c_char, + pub count: libc::c_int, + pub first: *mut dc_hashelem_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. + * + * Again, this structure is intended to be opaque, but it can't really + * be opaque because it is used by macros. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_hashelem { + pub next: *mut dc_hashelem_t, + pub prev: *mut dc_hashelem_t, + pub data: *mut libc::c_void, + pub pKey: *mut libc::c_void, + pub nKey: libc::c_int, +} +/* Forward declarations of structures. + */ +pub type dc_hash_t = _dc_hash; +pub type rpgp_signed_secret_key = rpgp_SignedSecretKey; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct rpgp_cvec { + pub data: *mut uint8_t, + pub len: size_t, +} +pub type rpgp_message = rpgp_Message; +pub type rpgp_signed_public_key = rpgp_SignedPublicKey; +pub type rpgp_public_or_secret_key = rpgp_PublicOrSecret; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct rpgp_message_decrypt_result { + pub message_ptr: *mut rpgp_message, + pub valid_ids_ptr: *mut *mut libc::c_char, + pub valid_ids_len: size_t, +} +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_keyring { + pub keys: *mut *mut dc_key_t, + pub count: libc::c_int, + pub allocated: libc::c_int, +} +pub type dc_keyring_t = _dc_keyring; +/* ** library-private **********************************************************/ +/* validation errors */ +/* misc. */ +#[no_mangle] +pub unsafe extern "C" fn dc_pgp_init() {} +#[no_mangle] +pub unsafe extern "C" fn dc_pgp_exit() {} +#[no_mangle] +pub unsafe extern "C" fn dc_pgp_rand_seed( + mut context: *mut dc_context_t, + mut buf: *const libc::c_void, + mut bytes: size_t, +) { +} +#[no_mangle] +pub unsafe extern "C" fn dc_split_armored_data( + mut buf: *mut libc::c_char, + mut ret_headerline: *mut *const libc::c_char, + mut ret_setupcodebegin: *mut *const libc::c_char, + mut ret_preferencrypt: *mut *const libc::c_char, + mut ret_base64: *mut *const libc::c_char, +) -> libc::c_int { + let mut success: libc::c_int = 0i32; + 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 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() { + *ret_headerline = 0 as *const libc::c_char + } + if !ret_setupcodebegin.is_null() { + *ret_setupcodebegin = 0 as *const libc::c_char + } + if !ret_preferencrypt.is_null() { + *ret_preferencrypt = 0 as *const libc::c_char + } + if !ret_base64.is_null() { + *ret_base64 = 0 as *const libc::c_char + } + if !(buf.is_null() || ret_headerline.is_null()) { + dc_remove_cr_chars(buf); + while 0 != *p1 { + if *p1 as libc::c_int == '\n' as i32 { + *line.offset(line_chars as isize) = 0i32 as libc::c_char; + if headerline.is_null() { + dc_trim(line); + if strncmp( + line, + b"-----BEGIN \x00" as *const u8 as *const libc::c_char, + 11i32 as libc::c_ulong, + ) == 0i32 + && strncmp( + &mut *line + .offset(strlen(line).wrapping_sub(5i32 as libc::c_ulong) as isize), + b"-----\x00" as *const u8 as *const libc::c_char, + 5i32 as libc::c_ulong, + ) == 0i32 + { + headerline = line; + if !ret_headerline.is_null() { + *ret_headerline = headerline + } + } + } else if strspn(line, b"\t\r\n \x00" as *const u8 as *const libc::c_char) + == strlen(line) + { + base64 = p1.offset(1isize); + break; + } else { + p2 = strchr(line, ':' as i32); + if p2.is_null() { + *line.offset(line_chars as isize) = '\n' as i32 as libc::c_char; + base64 = line; + break; + } else { + *p2 = 0i32 as libc::c_char; + dc_trim(line); + if strcasecmp( + line, + b"Passphrase-Begin\x00" as *const u8 as *const libc::c_char, + ) == 0i32 + { + p2 = p2.offset(1isize); + dc_trim(p2); + if !ret_setupcodebegin.is_null() { + *ret_setupcodebegin = p2 + } + } else if strcasecmp( + line, + b"Autocrypt-Prefer-Encrypt\x00" as *const u8 as *const libc::c_char, + ) == 0i32 + { + p2 = p2.offset(1isize); + dc_trim(p2); + if !ret_preferencrypt.is_null() { + *ret_preferencrypt = p2 + } + } + } + } + p1 = p1.offset(1isize); + line = p1; + line_chars = 0i32 as size_t + } else { + p1 = p1.offset(1isize); + line_chars = line_chars.wrapping_add(1) + } + } + if !(headerline.is_null() || base64.is_null()) { + /* now, line points to beginning of base64 data, search end */ + /*the trailing space makes sure, this is not a normal base64 sequence*/ + p1 = strstr(base64, b"-----END \x00" as *const u8 as *const libc::c_char); + if !(p1.is_null() + || strncmp( + p1.offset(9isize), + headerline.offset(11isize), + strlen(headerline.offset(11isize)), + ) != 0i32) + { + *p1 = 0i32 as libc::c_char; + dc_trim(base64); + if !ret_base64.is_null() { + *ret_base64 = base64 + } + success = 1i32 + } + } + } + return success; +} +/* public key encryption */ +#[no_mangle] +pub unsafe extern "C" fn dc_pgp_create_keypair( + mut context: *mut 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 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; + user_id = dc_mprintf(b"<%s>\x00" as *const u8 as *const libc::c_char, addr); + skey = rpgp_create_rsa_skey(2048i32 as uint32_t, user_id); + if !(0 != dc_pgp_handle_rpgp_error(context)) { + skey_bytes = rpgp_skey_to_bytes(skey); + if !(0 != dc_pgp_handle_rpgp_error(context)) { + pkey = rpgp_skey_public_key(skey); + if !(0 != dc_pgp_handle_rpgp_error(context)) { + pkey_bytes = rpgp_pkey_to_bytes(pkey); + if !(0 != dc_pgp_handle_rpgp_error(context)) { + dc_key_set_from_binary( + ret_private_key, + rpgp_cvec_data(skey_bytes) as *const libc::c_void, + rpgp_cvec_len(skey_bytes) as libc::c_int, + 1i32, + ); + if !(0 != dc_pgp_handle_rpgp_error(context)) { + dc_key_set_from_binary( + ret_public_key, + rpgp_cvec_data(pkey_bytes) as *const libc::c_void, + rpgp_cvec_len(pkey_bytes) as libc::c_int, + 0i32, + ); + if !(0 != dc_pgp_handle_rpgp_error(context)) { + success = 1i32 + } + } + } + } + } + } + /* cleanup */ + if !skey.is_null() { + rpgp_skey_drop(skey); + } + if !skey_bytes.is_null() { + rpgp_cvec_drop(skey_bytes); + } + if !pkey.is_null() { + rpgp_pkey_drop(pkey); + } + if !pkey_bytes.is_null() { + rpgp_cvec_drop(pkey_bytes); + } + if !user_id.is_null() { + free(user_id as *mut libc::c_void); + } + return success; +} +/* returns 0 if there is no error, otherwise logs the error if a context is provided and returns 1*/ +#[no_mangle] +pub unsafe extern "C" fn dc_pgp_handle_rpgp_error(mut context: *mut dc_context_t) -> libc::c_int { + let mut success: libc::c_int = 0i32; + let mut len: libc::c_int = 0i32; + let mut msg: *mut libc::c_char = 0 as *mut libc::c_char; + len = rpgp_last_error_length(); + if !(len == 0i32) { + msg = 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, + ); + } + success = 1i32 + } + if !msg.is_null() { + rpgp_string_drop(msg); + } + return success; +} +#[no_mangle] +pub unsafe extern "C" fn dc_pgp_is_valid_key( + mut context: *mut 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) + { + key = rpgp_key_from_bytes( + (*raw_key).binary as *const uint8_t, + (*raw_key).bytes as size_t, + ); + if !(0 != dc_pgp_handle_rpgp_error(context)) { + if (*raw_key).type_0 == 0i32 && 0 != rpgp_key_is_public(key) as libc::c_int { + key_is_valid = 1i32 + } else if (*raw_key).type_0 == 1i32 && 0 != rpgp_key_is_secret(key) as libc::c_int { + key_is_valid = 1i32 + } + } + } + if !key.is_null() { + rpgp_key_drop(key); + } + return key_is_valid; +} +#[no_mangle] +pub unsafe extern "C" 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, +) -> 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; + let mut fingerprint: *mut rpgp_cvec = 0 as *mut rpgp_cvec; + if !(raw_key.is_null() + || ret_fingerprint.is_null() + || !(*ret_fingerprint).is_null() + || ret_fingerprint_bytes.is_null() + || *ret_fingerprint_bytes != 0i32 as libc::c_ulong + || (*raw_key).binary.is_null() + || (*raw_key).bytes <= 0i32) + { + key = rpgp_key_from_bytes( + (*raw_key).binary as *const uint8_t, + (*raw_key).bytes as size_t, + ); + if !(0 != dc_pgp_handle_rpgp_error(0 as *mut dc_context_t)) { + fingerprint = rpgp_key_fingerprint(key); + if !(0 != dc_pgp_handle_rpgp_error(0 as *mut dc_context_t)) { + *ret_fingerprint_bytes = rpgp_cvec_len(fingerprint); + *ret_fingerprint = malloc(*ret_fingerprint_bytes) as *mut uint8_t; + memcpy( + *ret_fingerprint as *mut libc::c_void, + rpgp_cvec_data(fingerprint) as *const libc::c_void, + *ret_fingerprint_bytes, + ); + success = 1i32 + } + } + } + if !key.is_null() { + rpgp_key_drop(key); + } + if !fingerprint.is_null() { + rpgp_cvec_drop(fingerprint); + } + return success; +} +#[no_mangle] +pub unsafe extern "C" fn dc_pgp_split_key( + mut context: *mut dc_context_t, + mut private_in: *const dc_key_t, + mut ret_public_key: *mut dc_key_t, +) -> libc::c_int { + let mut success: libc::c_int = 0i32; + 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).type_0 != 1i32 { + dc_log_warning( + context, + 0i32, + b"Split key: Given key is no private key.\x00" as *const u8 as *const libc::c_char, + ); + } else { + key = rpgp_skey_from_bytes( + (*private_in).binary as *const uint8_t, + (*private_in).bytes as size_t, + ); + if !(0 != dc_pgp_handle_rpgp_error(context)) { + pub_key = rpgp_skey_public_key(key); + if !(0 != dc_pgp_handle_rpgp_error(context)) { + buf = rpgp_pkey_to_bytes(pub_key); + if !(0 != dc_pgp_handle_rpgp_error(context)) { + dc_key_set_from_binary( + ret_public_key, + rpgp_cvec_data(buf) as *const libc::c_void, + rpgp_cvec_len(buf) as libc::c_int, + 0i32, + ); + success = 1i32 + } + } + } + } + } + if !key.is_null() { + rpgp_skey_drop(key); + } + if !pub_key.is_null() { + rpgp_pkey_drop(pub_key); + } + if !buf.is_null() { + rpgp_cvec_drop(buf); + } + return success; +} +#[no_mangle] +pub unsafe extern "C" fn dc_pgp_pk_encrypt( + mut context: *mut 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, + mut raw_private_key_for_signing: *const dc_key_t, + mut use_armor: libc::c_int, + mut ret_ctext: *mut *mut libc::c_void, + mut ret_ctext_bytes: *mut size_t, +) -> libc::c_int { + let mut current_block: u64; + let mut i: libc::c_int = 0i32; + 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 + || plain_bytes == 0i32 as libc::c_ulong + || ret_ctext.is_null() + || ret_ctext_bytes.is_null() + || raw_public_keys_for_encryption.is_null() + || (*raw_public_keys_for_encryption).count <= 0i32 + || use_armor == 0i32) + { + /* only support use_armor=1 */ + *ret_ctext = 0 as *mut libc::c_void; + *ret_ctext_bytes = 0i32 as size_t; + public_keys_len = (*raw_public_keys_for_encryption).count; + public_keys = malloc( + (::std::mem::size_of::<*mut rpgp_signed_public_key>() as libc::c_ulong) + .wrapping_mul(public_keys_len as libc::c_ulong), + ) as *mut *mut rpgp_signed_public_key; + /* setup secret key for signing */ + if !raw_private_key_for_signing.is_null() { + private_key = rpgp_skey_from_bytes( + (*raw_private_key_for_signing).binary as *const uint8_t, + (*raw_private_key_for_signing).bytes as size_t, + ); + if private_key.is_null() || 0 != dc_pgp_handle_rpgp_error(context) { + dc_log_warning( + context, + 0i32, + b"No key for signing found.\x00" as *const u8 as *const libc::c_char, + ); + current_block = 2132137392766895896; + } else { + current_block = 12800627514080957624; + } + } else { + current_block = 12800627514080957624; + } + match current_block { + 2132137392766895896 => {} + _ => { + /* setup public keys for encryption */ + i = 0i32; + loop { + if !(i < public_keys_len) { + current_block = 6057473163062296781; + break; + } + let ref mut fresh0 = *public_keys.offset(i as isize); + *fresh0 = rpgp_pkey_from_bytes( + (**(*raw_public_keys_for_encryption).keys.offset(i as isize)).binary + as *const uint8_t, + (**(*raw_public_keys_for_encryption).keys.offset(i as isize)).bytes + as size_t, + ); + if 0 != dc_pgp_handle_rpgp_error(context) { + current_block = 2132137392766895896; + break; + } + i += 1 + } + match current_block { + 2132137392766895896 => {} + _ => { + /* sign & encrypt */ + let mut op_clocks: clock_t = 0i32 as clock_t; + let mut start: clock_t = clock(); + if private_key.is_null() { + encrypted = rpgp_encrypt_bytes_to_keys( + plain_text as *const uint8_t, + plain_bytes, + public_keys as *const *const rpgp_signed_public_key, + public_keys_len as size_t, + ); + if 0 != dc_pgp_handle_rpgp_error(context) { + dc_log_warning( + context, + 0i32, + b"Encryption failed.\x00" as *const u8 as *const libc::c_char, + ); + current_block = 2132137392766895896; + } else { + op_clocks = clock().wrapping_sub(start); + dc_log_info( + context, + 0i32, + b"Message encrypted in %.3f ms.\x00" as *const u8 + as *const libc::c_char, + op_clocks as libc::c_double * 1000.0f64 + / 1000000i32 as libc::c_double, + ); + current_block = 1538046216550696469; + } + } else { + encrypted = rpgp_sign_encrypt_bytes_to_keys( + plain_text as *const uint8_t, + plain_bytes, + public_keys as *const *const rpgp_signed_public_key, + public_keys_len as size_t, + private_key, + ); + if 0 != dc_pgp_handle_rpgp_error(context) { + dc_log_warning( + context, + 0i32, + b"Signing and encrypting failed.\x00" as *const u8 + as *const libc::c_char, + ); + current_block = 2132137392766895896; + } else { + op_clocks = clock().wrapping_sub(start); + dc_log_info( + context, + 0i32, + b"Message signed and encrypted in %.3f ms.\x00" as *const u8 + as *const libc::c_char, + op_clocks as libc::c_double * 1000.0f64 + / 1000000i32 as libc::c_double, + ); + current_block = 1538046216550696469; + } + } + match current_block { + 2132137392766895896 => {} + _ => { + /* convert message to armored bytes and return values */ + let mut armored: *mut rpgp_cvec = rpgp_msg_to_armored(encrypted); + if !(0 != dc_pgp_handle_rpgp_error(context)) { + *ret_ctext = rpgp_cvec_data(armored) as *mut libc::c_void; + *ret_ctext_bytes = rpgp_cvec_len(armored); + free(armored as *mut libc::c_void); + success = 1i32 + } + } + } + } + } + } + } + } + if !private_key.is_null() { + rpgp_skey_drop(private_key); + } + i = 0i32; + while i < public_keys_len { + rpgp_pkey_drop(*public_keys.offset(i as isize)); + i += 1 + } + if !encrypted.is_null() { + rpgp_msg_drop(encrypted); + } + return success; +} +#[no_mangle] +pub unsafe extern "C" fn dc_pgp_pk_decrypt( + mut context: *mut dc_context_t, + mut ctext: *const libc::c_void, + mut ctext_bytes: size_t, + mut raw_private_keys_for_decryption: *const dc_keyring_t, + mut raw_public_keys_for_validation: *const dc_keyring_t, + mut use_armor: libc::c_int, + mut ret_plain: *mut *mut libc::c_void, + mut ret_plain_bytes: *mut size_t, + 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 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; + let mut private_keys_len: libc::c_int = 0i32; + let mut public_keys_len: libc::c_int = 0i32; + 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 + || ctext_bytes == 0i32 as libc::c_ulong + || ret_plain.is_null() + || ret_plain_bytes.is_null() + || raw_private_keys_for_decryption.is_null() + || (*raw_private_keys_for_decryption).count <= 0i32 + || use_armor == 0i32) + { + /* only support use_armor=1 */ + *ret_plain = 0 as *mut libc::c_void; + *ret_plain_bytes = 0i32 as size_t; + private_keys_len = (*raw_private_keys_for_decryption).count; + private_keys = malloc( + (::std::mem::size_of::<*mut rpgp_signed_secret_key>() as libc::c_ulong) + .wrapping_mul(private_keys_len as libc::c_ulong), + ) as *mut *mut rpgp_signed_secret_key; + if !raw_public_keys_for_validation.is_null() { + public_keys_len = (*raw_public_keys_for_validation).count; + public_keys = malloc( + (::std::mem::size_of::<*mut rpgp_signed_public_key>() as libc::c_ulong) + .wrapping_mul(public_keys_len as libc::c_ulong), + ) as *mut *mut rpgp_signed_public_key + } + /* setup secret keys for decryption */ + i = 0i32; + loop { + if !(i < (*raw_private_keys_for_decryption).count) { + current_block = 15904375183555213903; + break; + } + let ref mut fresh1 = *private_keys.offset(i as isize); + *fresh1 = rpgp_skey_from_bytes( + (**(*raw_private_keys_for_decryption).keys.offset(i as isize)).binary + as *const uint8_t, + (**(*raw_private_keys_for_decryption).keys.offset(i as isize)).bytes as size_t, + ); + if 0 != dc_pgp_handle_rpgp_error(context) { + current_block = 11904635156640512504; + break; + } + i += 1 + } + match current_block { + 11904635156640512504 => {} + _ => { + /* setup public keys for validation */ + if !raw_public_keys_for_validation.is_null() { + i = 0i32; + loop { + if !(i < (*raw_public_keys_for_validation).count) { + current_block = 7172762164747879670; + break; + } + let ref mut fresh2 = *public_keys.offset(i as isize); + *fresh2 = rpgp_pkey_from_bytes( + (**(*raw_public_keys_for_validation).keys.offset(i as isize)).binary + as *const uint8_t, + (**(*raw_public_keys_for_validation).keys.offset(i as isize)).bytes + as size_t, + ); + if 0 != dc_pgp_handle_rpgp_error(context) { + current_block = 11904635156640512504; + break; + } + i += 1 + } + } else { + current_block = 7172762164747879670; + } + match current_block { + 11904635156640512504 => {} + _ => { + /* decrypt */ + encrypted = rpgp_msg_from_armor(ctext as *const uint8_t, ctext_bytes); + if !(0 != dc_pgp_handle_rpgp_error(context)) { + decrypted = rpgp_msg_decrypt_no_pw( + encrypted, + private_keys as *const *const rpgp_signed_secret_key, + private_keys_len as size_t, + public_keys as *const *const rpgp_signed_public_key, + public_keys_len as size_t, + ); + if !(0 != dc_pgp_handle_rpgp_error(context)) { + let mut decrypted_bytes: *mut rpgp_cvec = + rpgp_msg_to_bytes((*decrypted).message_ptr); + if !(0 != dc_pgp_handle_rpgp_error(context)) { + *ret_plain_bytes = rpgp_cvec_len(decrypted_bytes); + *ret_plain = + rpgp_cvec_data(decrypted_bytes) as *mut libc::c_void; + free(decrypted_bytes as *mut libc::c_void); + if !ret_signature_fingerprints.is_null() { + let mut j: uint32_t = 0i32 as uint32_t; + let mut len: uint32_t = + (*decrypted).valid_ids_len as uint32_t; + while j < len { + let mut fingerprint_hex: *mut libc::c_char = + *(*decrypted).valid_ids_ptr.offset(j as isize); + if !fingerprint_hex.is_null() { + dc_hash_insert( + ret_signature_fingerprints, + fingerprint_hex as *const libc::c_void, + strlen(fingerprint_hex) as libc::c_int, + 1i32 as *mut libc::c_void, + ); + free(fingerprint_hex as *mut libc::c_void); + } + j = j.wrapping_add(1) + } + } + success = 1i32 + } + } + } + } + } + } + } + } + i = 0i32; + while i < private_keys_len { + rpgp_skey_drop(*private_keys.offset(i as isize)); + i += 1 + } + i = 0i32; + while i < public_keys_len { + rpgp_pkey_drop(*public_keys.offset(i as isize)); + i += 1 + } + if !encrypted.is_null() { + rpgp_msg_drop(encrypted); + } + if !decrypted.is_null() { + rpgp_message_decrypt_result_drop(decrypted); + } + return success; +} +/* symm. encryption */ +#[no_mangle] +pub unsafe extern "C" fn dc_pgp_symm_encrypt( + mut context: *mut dc_context_t, + mut passphrase: *const libc::c_char, + mut plain: *const libc::c_void, + mut plain_bytes: size_t, + mut ret_ctext_armored: *mut *mut libc::c_char, +) -> 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() + || plain == 0 as *mut libc::c_void + || plain_bytes == 0i32 as libc::c_ulong + || ret_ctext_armored.is_null()) + { + decrypted = + rpgp_encrypt_bytes_with_password(plain as *const uint8_t, plain_bytes, passphrase); + if !(0 != dc_pgp_handle_rpgp_error(context)) { + *ret_ctext_armored = rpgp_msg_to_armored_str(decrypted); + if !(0 != dc_pgp_handle_rpgp_error(context)) { + success = 1i32 + } + } + } + if !decrypted.is_null() { + rpgp_msg_drop(decrypted); + } + return success; +} +#[no_mangle] +pub unsafe extern "C" fn dc_pgp_symm_decrypt( + mut context: *mut 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 success: libc::c_int = 0i32; + let mut encrypted: *mut rpgp_message = 0 as *mut rpgp_message; + let mut decrypted: *mut rpgp_message = 0 as *mut rpgp_message; + encrypted = rpgp_msg_from_bytes(ctext as *const uint8_t, ctext_bytes); + if !(0 != dc_pgp_handle_rpgp_error(context)) { + decrypted = rpgp_msg_decrypt_with_password(encrypted, passphrase); + if !(0 != dc_pgp_handle_rpgp_error(context)) { + decrypted_bytes = rpgp_msg_to_bytes(decrypted); + if !(0 != dc_pgp_handle_rpgp_error(context)) { + *ret_plain_text = rpgp_cvec_data(decrypted_bytes) as *mut libc::c_void; + *ret_plain_bytes = rpgp_cvec_len(decrypted_bytes); + free(decrypted_bytes as *mut libc::c_void); + success = 1i32 + } + } + } + if !encrypted.is_null() { + rpgp_msg_drop(encrypted); + } + if !decrypted.is_null() { + rpgp_msg_drop(decrypted); + } + return success; +} diff --git a/src/dc_qr.rs b/src/dc_qr.rs new file mode 100644 index 000000000..468d8f1c1 --- /dev/null +++ b/src/dc_qr.rs @@ -0,0 +1,1223 @@ +use c2rust_bitfields::BitfieldStruct; +use libc; +extern "C" { + pub type mailstream_cancel; + pub type sqlite3; + #[no_mangle] + fn free(_: *mut libc::c_void); + #[no_mangle] + fn strchr(_: *const libc::c_char, _: libc::c_int) -> *mut libc::c_char; + #[no_mangle] + fn strlen(_: *const libc::c_char) -> libc::c_ulong; + #[no_mangle] + fn strstr(_: *const libc::c_char, _: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn strcasecmp(_: *const libc::c_char, _: *const libc::c_char) -> libc::c_int; + #[no_mangle] + fn strncasecmp(_: *const libc::c_char, _: *const libc::c_char, _: libc::c_ulong) + -> libc::c_int; + // handle contacts + #[no_mangle] + fn dc_may_be_valid_addr(addr: *const libc::c_char) -> libc::c_int; + /* * + * @class dc_lot_t + * + * An object containing a set of values. + * The meaning of the values is defined by the function returning the object. + * Lot objects are created + * eg. by dc_chatlist_get_summary() or dc_msg_get_summary(). + * + * NB: _Lot_ is used in the meaning _heap_ here. + */ + #[no_mangle] + fn dc_lot_new() -> *mut dc_lot_t; + #[no_mangle] + fn dc_apeerstate_new(_: *mut dc_context_t) -> *mut dc_apeerstate_t; + #[no_mangle] + fn dc_apeerstate_unref(_: *mut dc_apeerstate_t); + #[no_mangle] + fn dc_add_device_msg(_: *mut dc_context_t, chat_id: uint32_t, text: *const libc::c_char); + /* string tools */ + #[no_mangle] + fn dc_strdup(_: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn dc_add_or_lookup_contact( + _: *mut dc_context_t, + display_name: *const libc::c_char, + addr_spec: *const libc::c_char, + origin: libc::c_int, + sth_modified: *mut libc::c_int, + ) -> uint32_t; + #[no_mangle] + fn dc_format_fingerprint(_: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn dc_mprintf(format: *const libc::c_char, _: ...) -> *mut libc::c_char; + #[no_mangle] + fn dc_create_or_lookup_nchat_by_contact_id( + _: *mut dc_context_t, + contact_id: uint32_t, + create_blocked: libc::c_int, + ret_chat_id: *mut uint32_t, + ret_chat_blocked: *mut libc::c_int, + ); + #[no_mangle] + fn dc_apeerstate_load_by_fingerprint( + _: *mut dc_apeerstate_t, + _: *mut dc_sqlite3_t, + fingerprint: *const libc::c_char, + ) -> libc::c_int; + #[no_mangle] + fn dc_urldecode(_: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn dc_addr_normalize(addr: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn dc_split_into_lines(buf_terminated: *const libc::c_char) -> *mut carray; + #[no_mangle] + fn dc_free_splitted_lines(lines: *mut carray); + // Working with names + #[no_mangle] + fn dc_normalize_name(full_name: *mut libc::c_char); + #[no_mangle] + fn dc_str_replace( + haystack: *mut *mut libc::c_char, + needle: *const libc::c_char, + replacement: *const libc::c_char, + ) -> libc::c_int; + #[no_mangle] + fn dc_trim(_: *mut libc::c_char); + #[no_mangle] + fn dc_normalize_fingerprint(_: *const libc::c_char) -> *mut libc::c_char; + /* library-private */ + #[no_mangle] + fn dc_param_new() -> *mut dc_param_t; + #[no_mangle] + fn dc_param_unref(_: *mut dc_param_t); + #[no_mangle] + fn dc_param_get( + _: *const dc_param_t, + key: libc::c_int, + def: *const libc::c_char, + ) -> *mut libc::c_char; + #[no_mangle] + fn dc_param_set_urlencoded(_: *mut dc_param_t, _: *const libc::c_char); + #[no_mangle] + fn dc_log_info(_: *mut dc_context_t, data1: libc::c_int, msg: *const libc::c_char, _: ...); +} +pub type __darwin_size_t = libc::c_ulong; +pub type __darwin_ssize_t = libc::c_long; +pub type __darwin_time_t = libc::c_long; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_cond_t { + pub __sig: libc::c_long, + pub __opaque: [libc::c_char; 40], +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_mutex_t { + pub __sig: libc::c_long, + pub __opaque: [libc::c_char; 56], +} +pub type __darwin_pthread_cond_t = _opaque_pthread_cond_t; +pub type __darwin_pthread_mutex_t = _opaque_pthread_mutex_t; +pub type size_t = __darwin_size_t; +pub type uint32_t = libc::c_uint; +pub type uintptr_t = libc::c_ulong; +pub type ssize_t = __darwin_ssize_t; +pub type time_t = __darwin_time_t; +pub type uint8_t = libc::c_uchar; +pub type pthread_cond_t = __darwin_pthread_cond_t; +pub type pthread_mutex_t = __darwin_pthread_mutex_t; +#[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; +#[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) -> (); +#[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; +#[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, + 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 { + 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_capability_data { + pub cap_list: *mut clist, +} +#[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_0, + 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_0 { + 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 extern "C" 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_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, +} +#[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_1, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed_1 { + pub ft_fetch_att: *mut mailimap_fetch_att, + pub ft_fetch_att_list: *mut clist, +} +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 unnamed_2 { + 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, +} +/* define DC_USE_RPGP to enable use of rPGP instead of netpgp where available; +preferrably, this should be done in the project configuration currently */ +//#define DC_USE_RPGP 1 +/* Includes that are used frequently. This file may also be used to create predefined headers. */ +/* * Structure behind dc_context_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_context { + pub magic: uint32_t, + pub userdata: *mut libc::c_void, + pub dbfile: *mut libc::c_char, + pub blobdir: *mut libc::c_char, + pub sql: *mut dc_sqlite3_t, + pub inbox: *mut dc_imap_t, + pub inboxidle_condmutex: pthread_mutex_t, + pub perform_inbox_jobs_needed: libc::c_int, + pub probe_imap_network: libc::c_int, + pub sentbox_thread: dc_jobthread_t, + pub mvbox_thread: dc_jobthread_t, + pub smtp: *mut dc_smtp_t, + pub smtpidle_cond: pthread_cond_t, + pub smtpidle_condmutex: pthread_mutex_t, + pub smtpidle_condflag: libc::c_int, + pub smtp_suspended: libc::c_int, + pub smtp_doing_jobs: libc::c_int, + pub perform_smtp_jobs_needed: libc::c_int, + pub probe_smtp_network: libc::c_int, + pub oauth2_critical: pthread_mutex_t, + 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 type dc_lot_t = _dc_lot; +/* * Structure behind dc_lot_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_lot { + pub magic: uint32_t, + pub text1_meaning: libc::c_int, + pub text1: *mut libc::c_char, + pub text2: *mut libc::c_char, + pub timestamp: time_t, + pub state: libc::c_int, + pub id: uint32_t, + pub fingerprint: *mut libc::c_char, + pub invitenumber: *mut libc::c_char, + pub auth: *mut libc::c_char, +} +/* * + * 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 = Option< + unsafe extern "C" fn( + _: *mut dc_context_t, + _: libc::c_int, + _: uintptr_t, + _: uintptr_t, + ) -> uintptr_t, +>; +/* * + * @mainpage Getting started + * + * This document describes how to handle the Delta Chat core library. + * For general information about Delta Chat itself, + * see and . + * + * Let's start. + * + * First of all, you have to **define an event-handler-function** + * that is called by the library on specific events + * (eg. when the configuration is done or when fresh messages arrive). + * With this function you can create a Delta Chat context then: + * + * ~~~ + * #include + * + * uintptr_t event_handler_func(dc_context_t* context, int event, + * uintptr_t data1, uintptr_t data2) + * { + * return 0; // for unhandled events, it is always safe to return 0 + * } + * + * dc_context_t* context = dc_context_new(event_handler_func, NULL, NULL); + * ~~~ + * + * After that, you should make sure, + * sending and receiving jobs are processed as needed. + * For this purpose, you have to **create two threads:** + * + * ~~~ + * #include + * + * void* imap_thread_func(void* context) + * { + * while (true) { + * dc_perform_imap_jobs(context); + * dc_perform_imap_fetch(context); + * dc_perform_imap_idle(context); + * } + * } + * + * void* smtp_thread_func(void* context) + * { + * while (true) { + * dc_perform_smtp_jobs(context); + * dc_perform_smtp_idle(context); + * } + * } + * + * static pthread_t imap_thread, smtp_thread; + * pthread_create(&imap_thread, NULL, imap_thread_func, context); + * pthread_create(&smtp_thread, NULL, smtp_thread_func, context); + * ~~~ + * + * The example above uses "pthreads", + * however, you can also use anything else for thread handling. + * NB: The deltachat-core library itself does not create any threads on its own, + * however, functions, unless stated otherwise, are thread-safe. + * + * After that you can **define and open a database.** + * The database is a normal sqlite-file and is created as needed: + * + * ~~~ + * dc_open(context, "example.db", NULL); + * ~~~ + * + * Now you can **configure the context:** + * + * ~~~ + * // use some real test credentials here + * dc_set_config(context, "addr", "alice@example.org"); + * dc_set_config(context, "mail_pw", "***"); + * dc_configure(context); + * ~~~ + * + * dc_configure() returns immediately, the configuration itself may take a while + * and is done by a job in the imap-thread you've defined above. + * Once done, the #DC_EVENT_CONFIGURE_PROGRESS reports success + * to the event_handler_func() that is also defined above. + * + * The configuration result is saved in the database, + * on subsequent starts it is not needed to call dc_configure() + * (you can check this using dc_is_configured()). + * + * Now you can **send the first message:** + * + * ~~~ + * // use a real testing address here + * uint32_t contact_id = dc_create_contact(context, NULL, "bob@example.org"); + * uint32_t chat_id = dc_create_chat_by_contact_id(context, contact_id); + * + * dc_send_text_msg(context, chat_id, "Hi, here is my first message!"); + * ~~~ + * + * dc_send_text_msg() returns immediately; + * the sending itself is done by a job in the smtp-thread you've defined above. + * If you check the testing address (bob) + * and you should have received a normal email. + * Answer this email in any email program with "Got it!" + * and the imap-thread you've create above will **receive the message**. + * + * You can then **list all messages** of a chat as follow: + * + * ~~~ + * dc_array_t* msglist = dc_get_chat_msgs(context, chat_id, 0, 0); + * for (int i = 0; i < dc_array_get_cnt(msglist); i++) + * { + * uint32_t msg_id = dc_array_get_id(msglist, i); + * dc_msg_t* msg = dc_get_msg(context, msg_id); + * char* text = dc_msg_get_text(msg); + * + * printf("Message %i: %s\n", i+1, text); + * + * free(text); + * dc_msg_unref(msg); + * } + * dc_array_unref(msglist); + * ~~~ + * + * This will output the following two lines: + * + * ~~~ + * Message 1: Hi, here is my first message! + * Message 2: Got it! + * ~~~ + * + * + * ## Class reference + * + * For a class reference, see the "Classes" link atop. + * + * + * ## Further hints + * + * Here are some additional, unsorted hints that may be useful. + * + * - For `get`-functions, you have to unref the return value in some way. + * + * - Strings in function arguments or return values are usually UTF-8 encoded. + * + * - The issue-tracker for the core library is here: + * + * + * The following points are important mainly + * for the authors of the library itself: + * + * - For indentation, use tabs. + * Alignments that are not placed at the beginning of a line + * should be done with spaces. + * + * - For padding between functions, + * classes etc. use 2 empty lines + * + * - Source files are encoded as UTF-8 with Unix line endings + * (a simple `LF`, `0x0A` or `\n`) + * + * If you need further assistance, + * please do not hesitate to contact us + * through the channels shown at https://delta.chat/en/contribute + * + * Please keep in mind, that your derived work + * must respect the Mozilla Public License 2.0 of libdeltachat + * and the respective licenses of the libraries libdeltachat links with. + * + * See you. + */ +/* * + * @class dc_context_t + * + * An object representing a single account. + * + * Each account is linked to an IMAP/SMTP account and uses a separate + * SQLite database for offline functionality and for account-related + * settings. + */ +pub type dc_context_t = _dc_context; +/* ** library-private **********************************************************/ +pub type dc_smtp_t = _dc_smtp; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_smtp { + 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 error: *mut libc::c_char, + pub error_etpan: libc::c_int, +} +pub type dc_jobthread_t = _dc_jobthread; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_jobthread { + 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, + 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, +} +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_imap { + 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 type dc_receive_imf_t = Option< + unsafe extern "C" 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_imap_t = _dc_imap; +pub type dc_precheck_imf_t = Option< + unsafe extern "C" 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< + unsafe extern "C" fn(_: *mut dc_imap_t, _: *const libc::c_char, _: *const libc::c_char) -> (), +>; +pub type dc_get_config_t = Option< + unsafe extern "C" fn( + _: *mut dc_imap_t, + _: *const libc::c_char, + _: *const libc::c_char, + ) -> *mut libc::c_char, +>; +/* ** library-private **********************************************************/ +pub type dc_sqlite3_t = _dc_sqlite3; +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_sqlite3 { + pub cobj: *mut sqlite3, + pub context: *mut dc_context_t, +} +pub type dc_param_t = _dc_param; +/* * + * @class dc_param_t + * + * An object for handling key=value parameter lists; for the key, curently only + * a single character is allowed. + * + * The object is used eg. by dc_chat_t or dc_msg_t, for readable paramter names, + * these classes define some DC_PARAM_* constantats. + * + * Only for library-internal use. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_param { + pub packed: *mut libc::c_char, +} +pub type dc_apeerstate_t = _dc_apeerstate; +/* prefer-encrypt states */ +/* * + * @class dc_apeerstate_t + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_apeerstate { + pub context: *mut dc_context_t, + pub addr: *mut libc::c_char, + pub last_seen: time_t, + pub last_seen_autocrypt: time_t, + pub prefer_encrypt: libc::c_int, + pub public_key: *mut dc_key_t, + pub public_key_fingerprint: *mut libc::c_char, + pub gossip_key: *mut dc_key_t, + pub gossip_timestamp: time_t, + pub gossip_key_fingerprint: *mut libc::c_char, + pub verified_key: *mut dc_key_t, + pub verified_key_fingerprint: *mut libc::c_char, + pub to_save: libc::c_int, + pub degrade_event: libc::c_int, +} +pub type dc_key_t = _dc_key; +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_key { + pub binary: *mut libc::c_void, + pub bytes: libc::c_int, + pub type_0: libc::c_int, + pub _m_heap_refcnt: libc::c_int, +} +#[inline] +unsafe extern "C" fn carray_count(mut array: *mut carray) -> libc::c_uint { + return (*array).len; +} +#[inline] +unsafe extern "C" fn carray_get( + mut array: *mut carray, + mut indx: libc::c_uint, +) -> *mut libc::c_void { + return *(*array).array.offset(indx as isize); +} +// out-of-band verification +// id=contact +// text1=groupname +// id=contact +// id=contact +// test1=formatted fingerprint +// id=contact +// text1=text +// text1=URL +// text1=error string +#[no_mangle] +pub unsafe extern "C" fn dc_check_qr( + mut context: *mut dc_context_t, + mut qr: *const libc::c_char, +) -> *mut dc_lot_t { + let mut current_block: u64; + let mut payload: *mut libc::c_char = 0 as *mut libc::c_char; + // must be normalized, if set + let mut addr: *mut libc::c_char = 0 as *mut libc::c_char; + // must be normalized, if set + let mut fingerprint: *mut libc::c_char = 0 as *mut libc::c_char; + let mut name: *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 peerstate: *mut dc_apeerstate_t = dc_apeerstate_new(context); + let mut qr_parsed: *mut dc_lot_t = dc_lot_new(); + let mut chat_id: uint32_t = 0i32 as uint32_t; + let mut device_msg: *mut libc::c_char = 0 as *mut libc::c_char; + 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()) { + dc_log_info( + context, + 0i32, + b"Scanned QR code: %s\x00" as *const u8 as *const libc::c_char, + qr, + ); + /* split parameters from the qr code + ------------------------------------ */ + if strncasecmp( + qr, + b"OPENPGP4FPR:\x00" as *const u8 as *const libc::c_char, + strlen(b"OPENPGP4FPR:\x00" as *const u8 as *const libc::c_char), + ) == 0i32 + { + payload = + dc_strdup(&*qr.offset(strlen( + b"OPENPGP4FPR:\x00" as *const u8 as *const libc::c_char, + ) as isize)); + let mut fragment: *mut libc::c_char = strchr(payload, '#' as i32); + if !fragment.is_null() { + *fragment = 0i32 as libc::c_char; + fragment = fragment.offset(1isize); + let mut param: *mut dc_param_t = dc_param_new(); + dc_param_set_urlencoded(param, fragment); + addr = dc_param_get(param, 'a' as i32, 0 as *const libc::c_char); + if !addr.is_null() { + let mut urlencoded: *mut libc::c_char = + dc_param_get(param, 'n' as i32, 0 as *const libc::c_char); + if !urlencoded.is_null() { + name = dc_urldecode(urlencoded); + dc_normalize_name(name); + free(urlencoded as *mut libc::c_void); + } + invitenumber = dc_param_get(param, 'i' as i32, 0 as *const libc::c_char); + auth = dc_param_get(param, 's' as i32, 0 as *const libc::c_char); + grpid = dc_param_get(param, 'x' as i32, 0 as *const libc::c_char); + if !grpid.is_null() { + urlencoded = dc_param_get(param, 'g' as i32, 0 as *const libc::c_char); + if !urlencoded.is_null() { + grpname = dc_urldecode(urlencoded); + free(urlencoded as *mut libc::c_void); + } + } + } + dc_param_unref(param); + } + fingerprint = dc_normalize_fingerprint(payload); + current_block = 5023038348526654800; + } else if strncasecmp( + qr, + b"mailto:\x00" as *const u8 as *const libc::c_char, + strlen(b"mailto:\x00" as *const u8 as *const libc::c_char), + ) == 0i32 + { + payload = dc_strdup( + &*qr.offset(strlen(b"mailto:\x00" as *const u8 as *const libc::c_char) as isize), + ); + let mut query: *mut libc::c_char = strchr(payload, '?' as i32); + if !query.is_null() { + *query = 0i32 as libc::c_char + } + addr = dc_strdup(payload); + current_block = 5023038348526654800; + } else if strncasecmp( + qr, + b"SMTP:\x00" as *const u8 as *const libc::c_char, + strlen(b"SMTP:\x00" as *const u8 as *const libc::c_char), + ) == 0i32 + { + payload = dc_strdup( + &*qr.offset(strlen(b"SMTP:\x00" as *const u8 as *const libc::c_char) as isize), + ); + let mut colon: *mut libc::c_char = strchr(payload, ':' as i32); + if !colon.is_null() { + *colon = 0i32 as libc::c_char + } + addr = dc_strdup(payload); + current_block = 5023038348526654800; + } else if strncasecmp( + qr, + b"MATMSG:\x00" as *const u8 as *const libc::c_char, + strlen(b"MATMSG:\x00" as *const u8 as *const libc::c_char), + ) == 0i32 + { + /* scheme: `MATMSG:TO:addr...;SUB:subject...;BODY:body...;` - there may or may not be linebreaks after the fields */ + /* does not work when the text `TO:` is used in subject/body _and_ TO: is not the first field. we ignore this case. */ + let mut to: *mut libc::c_char = + strstr(qr, b"TO:\x00" as *const u8 as *const libc::c_char); + if !to.is_null() { + addr = dc_strdup(&mut *to.offset(3isize)); + let mut semicolon: *mut libc::c_char = strchr(addr, ';' as i32); + if !semicolon.is_null() { + *semicolon = 0i32 as libc::c_char + } + current_block = 5023038348526654800; + } else { + (*qr_parsed).state = 400i32; + (*qr_parsed).text1 = + dc_strdup(b"Bad e-mail address.\x00" as *const u8 as *const libc::c_char); + current_block = 16562876845594826114; + } + } else { + if strncasecmp( + qr, + b"BEGIN:VCARD\x00" as *const u8 as *const libc::c_char, + strlen(b"BEGIN:VCARD\x00" as *const u8 as *const libc::c_char), + ) == 0i32 + { + let mut lines: *mut carray = dc_split_into_lines(qr); + let mut i: libc::c_int = 0i32; + while (i as libc::c_uint) < carray_count(lines) { + let mut key: *mut libc::c_char = + carray_get(lines, i as libc::c_uint) as *mut libc::c_char; + dc_trim(key); + let mut value: *mut libc::c_char = strchr(key, ':' as i32); + if !value.is_null() { + *value = 0i32 as libc::c_char; + value = value.offset(1isize); + let mut semicolon_0: *mut libc::c_char = strchr(key, ';' as i32); + if !semicolon_0.is_null() { + *semicolon_0 = 0i32 as libc::c_char + } + if strcasecmp(key, b"EMAIL\x00" as *const u8 as *const libc::c_char) == 0i32 + { + semicolon_0 = strchr(value, ';' as i32); + if !semicolon_0.is_null() { + *semicolon_0 = 0i32 as libc::c_char + } + addr = dc_strdup(value) + } else if strcasecmp(key, b"N\x00" as *const u8 as *const libc::c_char) + == 0i32 + { + semicolon_0 = strchr(value, ';' as i32); + if !semicolon_0.is_null() { + semicolon_0 = strchr(semicolon_0.offset(1isize), ';' as i32); + if !semicolon_0.is_null() { + *semicolon_0 = 0i32 as libc::c_char + } + } + name = dc_strdup(value); + dc_str_replace( + &mut name, + b";\x00" as *const u8 as *const libc::c_char, + b",\x00" as *const u8 as *const libc::c_char, + ); + dc_normalize_name(name); + } + } + i += 1 + } + dc_free_splitted_lines(lines); + } + current_block = 5023038348526654800; + } + match current_block { + 16562876845594826114 => {} + _ => { + /* check the paramters + ---------------------- */ + if !addr.is_null() { + /* urldecoding is needed at least for OPENPGP4FPR but should not hurt in the other cases */ + let mut temp: *mut libc::c_char = dc_urldecode(addr); + free(addr as *mut libc::c_void); + addr = temp; + temp = dc_addr_normalize(addr); + free(addr as *mut libc::c_void); + addr = temp; + if 0 == dc_may_be_valid_addr(addr) { + (*qr_parsed).state = 400i32; + (*qr_parsed).text1 = dc_strdup( + b"Bad e-mail address.\x00" as *const u8 as *const libc::c_char, + ); + current_block = 16562876845594826114; + } else { + current_block = 14116432890150942211; + } + } else { + current_block = 14116432890150942211; + } + match current_block { + 16562876845594826114 => {} + _ => { + if !fingerprint.is_null() { + if strlen(fingerprint) != 40i32 as libc::c_ulong { + (*qr_parsed).state = 400i32; + (*qr_parsed).text1 = dc_strdup( + b"Bad fingerprint length in QR code.\x00" as *const u8 + as *const libc::c_char, + ); + current_block = 16562876845594826114; + } else { + current_block = 5409161009579131794; + } + } else { + current_block = 5409161009579131794; + } + match current_block { + 16562876845594826114 => {} + _ => { + if !fingerprint.is_null() { + if addr.is_null() || invitenumber.is_null() || auth.is_null() { + if 0 != dc_apeerstate_load_by_fingerprint( + peerstate, + (*context).sql, + fingerprint, + ) { + (*qr_parsed).state = 210i32; + (*qr_parsed).id = dc_add_or_lookup_contact( + context, + 0 as *const libc::c_char, + (*peerstate).addr, + 0x80i32, + 0 as *mut libc::c_int, + ); + dc_create_or_lookup_nchat_by_contact_id( + context, + (*qr_parsed).id, + 2i32, + &mut chat_id, + 0 as *mut libc::c_int, + ); + device_msg = dc_mprintf( + b"%s verified.\x00" as *const u8 + as *const libc::c_char, + (*peerstate).addr, + ) + } else { + (*qr_parsed).text1 = dc_format_fingerprint(fingerprint); + (*qr_parsed).state = 230i32 + } + } else { + if !grpid.is_null() && !grpname.is_null() { + (*qr_parsed).state = 202i32; + (*qr_parsed).text1 = dc_strdup(grpname); + (*qr_parsed).text2 = dc_strdup(grpid) + } else { + (*qr_parsed).state = 200i32 + } + (*qr_parsed).id = dc_add_or_lookup_contact( + context, + name, + addr, + 0x80i32, + 0 as *mut libc::c_int, + ); + (*qr_parsed).fingerprint = dc_strdup(fingerprint); + (*qr_parsed).invitenumber = dc_strdup(invitenumber); + (*qr_parsed).auth = dc_strdup(auth) + } + } else if !addr.is_null() { + (*qr_parsed).state = 320i32; + (*qr_parsed).id = dc_add_or_lookup_contact( + context, + name, + addr, + 0x80i32, + 0 as *mut libc::c_int, + ) + } else if strstr( + qr, + b"http://\x00" as *const u8 as *const libc::c_char, + ) == qr as *mut libc::c_char + || strstr( + qr, + b"https://\x00" as *const u8 as *const libc::c_char, + ) == qr as *mut libc::c_char + { + (*qr_parsed).state = 332i32; + (*qr_parsed).text1 = dc_strdup(qr) + } else { + (*qr_parsed).state = 330i32; + (*qr_parsed).text1 = dc_strdup(qr) + } + if !device_msg.is_null() { + dc_add_device_msg(context, chat_id, device_msg); + } + } + } + } + } + } + } + } + free(addr as *mut libc::c_void); + free(fingerprint as *mut libc::c_void); + dc_apeerstate_unref(peerstate); + free(payload as *mut libc::c_void); + free(name as *mut libc::c_void); + free(invitenumber as *mut libc::c_void); + free(auth as *mut libc::c_void); + free(device_msg as *mut libc::c_void); + free(grpname as *mut libc::c_void); + free(grpid as *mut libc::c_void); + return qr_parsed; +} diff --git a/src/dc_receive_imf.rs b/src/dc_receive_imf.rs new file mode 100644 index 000000000..b7f702d0c --- /dev/null +++ b/src/dc_receive_imf.rs @@ -0,0 +1,4124 @@ +use c2rust_bitfields::BitfieldStruct; +use libc; +extern "C" { + pub type mailstream_cancel; + pub type sqlite3; + pub type sqlite3_stmt; + #[no_mangle] + fn calloc(_: libc::c_ulong, _: libc::c_ulong) -> *mut libc::c_void; + #[no_mangle] + fn free(_: *mut libc::c_void); + #[no_mangle] + fn strcmp(_: *const libc::c_char, _: *const libc::c_char) -> libc::c_int; + #[no_mangle] + fn strlen(_: *const libc::c_char) -> libc::c_ulong; + #[no_mangle] + fn strstr(_: *const libc::c_char, _: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn strcasecmp(_: *const libc::c_char, _: *const libc::c_char) -> libc::c_int; + #[no_mangle] + fn time(_: *mut time_t) -> time_t; + #[no_mangle] + fn carray_new(initsize: libc::c_uint) -> *mut carray; + #[no_mangle] + fn carray_add( + array: *mut carray, + data: *mut libc::c_void, + indx: *mut libc::c_uint, + ) -> libc::c_int; + #[no_mangle] + fn carray_free(array: *mut carray); + #[no_mangle] + fn mmap_string_unref(str: *mut libc::c_char) -> libc::c_int; + #[no_mangle] + fn sprintf(_: *mut libc::c_char, _: *const libc::c_char, _: ...) -> libc::c_int; + #[no_mangle] + 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; + #[no_mangle] + fn mailmime_free(mime: *mut mailmime); + #[no_mangle] + fn mailmime_parse( + message: *const libc::c_char, + length: size_t, + indx: *mut size_t, + result: *mut *mut mailmime, + ) -> libc::c_int; + #[no_mangle] + fn dc_is_contact_in_chat( + _: *mut dc_context_t, + chat_id: uint32_t, + contact_id: uint32_t, + ) -> libc::c_int; + #[no_mangle] + fn dc_lookup_contact_id_by_addr(_: *mut dc_context_t, addr: *const libc::c_char) -> uint32_t; + #[no_mangle] + fn dc_get_contact(_: *mut dc_context_t, contact_id: uint32_t) -> *mut dc_contact_t; + /* * + * @class dc_array_t + * + * An object containing a simple array. + * This object is used in several places where functions need to return an array. + * The items of the array are typically IDs. + * To free an array object, use dc_array_unref(). + */ + #[no_mangle] + fn dc_array_unref(_: *mut dc_array_t); + #[no_mangle] + fn dc_array_add_id(_: *mut dc_array_t, _: uint32_t); + #[no_mangle] + fn dc_array_add_ptr(_: *mut dc_array_t, _: *mut libc::c_void); + #[no_mangle] + fn dc_array_get_cnt(_: *const dc_array_t) -> size_t; + #[no_mangle] + fn dc_array_get_id(_: *const dc_array_t, index: size_t) -> uint32_t; + #[no_mangle] + fn dc_array_get_ptr(_: *const dc_array_t, index: size_t) -> *mut libc::c_void; + #[no_mangle] + fn dc_array_search_id(_: *const dc_array_t, needle: uint32_t, indx: *mut size_t) + -> libc::c_int; + /* * + * @class dc_chat_t + * + * An object representing a single chat in memory. + * Chat objects are created using eg. dc_get_chat() + * and are not updated on database changes; + * if you want an update, you have to recreate the object. + */ + // virtual chat showing all messages belonging to chats flagged with chats.blocked=2 + // messages that should be deleted get this chat_id; the messages are deleted from the working thread later then. This is also needed as rfc724_mid should be preset as long as the message is not deleted on the server (otherwise it is downloaded again) + // a message is just in creation but not yet assigned to a chat (eg. we may need the message ID to set up blobs; this avoids unready message to be sent and shown) + // virtual chat showing all messages flagged with msgs.starred=2 + // only an indicator in a chatlist + // only an indicator in a chatlist + // larger chat IDs are "real" chats, their messages are "real" messages. + #[no_mangle] + fn dc_chat_new(_: *mut dc_context_t) -> *mut dc_chat_t; + #[no_mangle] + fn dc_chat_unref(_: *mut dc_chat_t); + /* * + * @class dc_contact_t + * + * An object representing a single contact in memory. + * The contact object is not updated. + * If you want an update, you have to recreate the object. + * + * The library makes sure + * only to use names _authorized_ by the contact in `To:` or `Cc:`. + * _Given-names _as "Daddy" or "Honey" are not used there. + * For this purpose, internally, two names are tracked - + * authorized-name and given-name. + * By default, these names are equal, + * but functions working with contact names + * (eg. dc_contact_get_name(), dc_contact_get_display_name(), + * dc_contact_get_name_n_addr(), dc_contact_get_first_name(), + * dc_create_contact() or dc_add_address_book()) + * only affect the given-name. + */ + #[no_mangle] + fn dc_contact_new(_: *mut dc_context_t) -> *mut dc_contact_t; + #[no_mangle] + fn dc_contact_unref(_: *mut dc_contact_t); + #[no_mangle] + fn sqlite3_mprintf(_: *const libc::c_char, _: ...) -> *mut libc::c_char; + #[no_mangle] + fn sqlite3_free(_: *mut libc::c_void); + #[no_mangle] + fn sqlite3_bind_int(_: *mut sqlite3_stmt, _: libc::c_int, _: libc::c_int) -> libc::c_int; + #[no_mangle] + fn sqlite3_bind_int64(_: *mut sqlite3_stmt, _: libc::c_int, _: sqlite3_int64) -> libc::c_int; + #[no_mangle] + fn sqlite3_bind_text( + _: *mut sqlite3_stmt, + _: libc::c_int, + _: *const libc::c_char, + _: libc::c_int, + _: Option ()>, + ) -> libc::c_int; + #[no_mangle] + fn sqlite3_step(_: *mut sqlite3_stmt) -> libc::c_int; + #[no_mangle] + fn sqlite3_column_int(_: *mut sqlite3_stmt, iCol: libc::c_int) -> libc::c_int; + #[no_mangle] + fn sqlite3_column_int64(_: *mut sqlite3_stmt, iCol: libc::c_int) -> sqlite3_int64; + #[no_mangle] + fn sqlite3_column_text(_: *mut sqlite3_stmt, iCol: libc::c_int) -> *const libc::c_uchar; + #[no_mangle] + fn sqlite3_finalize(pStmt: *mut sqlite3_stmt) -> libc::c_int; + #[no_mangle] + fn sqlite3_reset(pStmt: *mut sqlite3_stmt) -> libc::c_int; + #[no_mangle] + fn dc_sqlite3_get_config( + _: *mut dc_sqlite3_t, + key: *const libc::c_char, + def: *const libc::c_char, + ) -> *mut libc::c_char; + #[no_mangle] + fn dc_sqlite3_get_config_int( + _: *mut dc_sqlite3_t, + key: *const libc::c_char, + def: int32_t, + ) -> int32_t; + /* tools, these functions are compatible to the corresponding sqlite3_* functions */ + #[no_mangle] + fn dc_sqlite3_prepare(_: *mut dc_sqlite3_t, sql: *const libc::c_char) -> *mut sqlite3_stmt; + #[no_mangle] + fn dc_sqlite3_get_rowid( + _: *mut dc_sqlite3_t, + table: *const libc::c_char, + field: *const libc::c_char, + value: *const libc::c_char, + ) -> uint32_t; + #[no_mangle] + fn dc_sqlite3_begin_transaction(_: *mut dc_sqlite3_t); + #[no_mangle] + fn dc_sqlite3_commit(_: *mut dc_sqlite3_t); + #[no_mangle] + fn dc_sqlite3_rollback(_: *mut dc_sqlite3_t); + /* string tools */ + #[no_mangle] + fn dc_strdup(_: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn dc_strlower_in_place(_: *mut libc::c_char); + #[no_mangle] + fn dc_mprintf(format: *const libc::c_char, _: ...) -> *mut libc::c_char; + #[no_mangle] + fn dc_str_from_clist(_: *const clist, delimiter: *const libc::c_char) -> *mut libc::c_char; + /* date/time tools */ + #[no_mangle] + fn dc_timestamp_from_date(date_time: *mut mailimf_date_time) -> time_t; + /* timesmearing */ + #[no_mangle] + fn dc_smeared_time(_: *mut dc_context_t) -> time_t; + #[no_mangle] + fn dc_create_smeared_timestamp(_: *mut dc_context_t) -> time_t; + #[no_mangle] + fn dc_create_incoming_rfc724_mid( + message_timestamp: time_t, + contact_id_from: uint32_t, + contact_ids_to: *mut dc_array_t, + ) -> *mut libc::c_char; + #[no_mangle] + fn dc_extract_grpid_from_rfc724_mid(rfc724_mid: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn dc_extract_grpid_from_rfc724_mid_list(rfc724_mid_list: *const clist) -> *mut libc::c_char; + #[no_mangle] + fn dc_strbuilder_init(_: *mut dc_strbuilder_t, init_bytes: libc::c_int); + #[no_mangle] + fn dc_strbuilder_cat(_: *mut dc_strbuilder_t, text: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn dc_decode_header_words(_: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn dc_param_get( + _: *const dc_param_t, + key: libc::c_int, + def: *const libc::c_char, + ) -> *mut libc::c_char; + #[no_mangle] + fn dc_param_set(_: *mut dc_param_t, key: libc::c_int, value: *const libc::c_char); + #[no_mangle] + fn dc_param_set_int(_: *mut dc_param_t, key: libc::c_int, value: int32_t); + /* library-private */ + #[no_mangle] + fn dc_param_new() -> *mut dc_param_t; + #[no_mangle] + fn dc_param_unref(_: *mut dc_param_t); + #[no_mangle] + fn dc_stock_str_repl_int( + _: *mut dc_context_t, + id: libc::c_int, + value: libc::c_int, + ) -> *mut libc::c_char; + /* Misc. */ + #[no_mangle] + fn dc_stock_system_msg( + context: *mut dc_context_t, + str_id: libc::c_int, + param1: *const libc::c_char, + param2: *const libc::c_char, + from_id: uint32_t, + ) -> *mut libc::c_char; + #[no_mangle] + fn dc_array_new(_: *mut dc_context_t, initsize: size_t) -> *mut dc_array_t; + #[no_mangle] + fn dc_array_free_ptr(_: *mut dc_array_t); + #[no_mangle] + fn dc_array_duplicate(_: *const dc_array_t) -> *mut dc_array_t; + #[no_mangle] + fn dc_array_sort_ids(_: *mut dc_array_t); + #[no_mangle] + fn dc_array_sort_strings(_: *mut dc_array_t); + #[no_mangle] + fn dc_array_get_string(_: *const dc_array_t, sep: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn dc_chat_load_from_db(_: *mut dc_chat_t, id: uint32_t) -> libc::c_int; + #[no_mangle] + fn dc_chat_update_param(_: *mut dc_chat_t) -> libc::c_int; + /* you MUST NOT modify this or the following strings */ + // Context functions to work with chats + #[no_mangle] + fn dc_add_to_chat_contacts_table( + _: *mut dc_context_t, + chat_id: uint32_t, + contact_id: uint32_t, + ) -> libc::c_int; + #[no_mangle] + fn dc_get_chat_id_by_grpid( + _: *mut dc_context_t, + grpid: *const libc::c_char, + ret_blocked: *mut libc::c_int, + ret_verified: *mut libc::c_int, + ) -> uint32_t; + #[no_mangle] + fn dc_create_or_lookup_nchat_by_contact_id( + _: *mut dc_context_t, + contact_id: uint32_t, + create_blocked: libc::c_int, + ret_chat_id: *mut uint32_t, + ret_chat_blocked: *mut libc::c_int, + ); + #[no_mangle] + fn dc_lookup_real_nchat_by_contact_id( + _: *mut dc_context_t, + contact_id: uint32_t, + ret_chat_id: *mut uint32_t, + ret_chat_blocked: *mut libc::c_int, + ); + #[no_mangle] + fn dc_unarchive_chat(_: *mut dc_context_t, chat_id: uint32_t); + #[no_mangle] + fn dc_unblock_chat(_: *mut dc_context_t, chat_id: uint32_t); + #[no_mangle] + fn dc_get_chat_contact_cnt(_: *mut dc_context_t, chat_id: uint32_t) -> libc::c_int; + #[no_mangle] + fn dc_is_group_explicitly_left(_: *mut dc_context_t, grpid: *const libc::c_char) + -> libc::c_int; + #[no_mangle] + fn dc_reset_gossiped_timestamp(_: *mut dc_context_t, chat_id: uint32_t); + #[no_mangle] + fn dc_mdn_from_ext( + _: *mut dc_context_t, + from_id: uint32_t, + rfc724_mid: *const libc::c_char, + _: time_t, + ret_chat_id: *mut uint32_t, + ret_msg_id: *mut uint32_t, + ) -> libc::c_int; + #[no_mangle] + fn dc_rfc724_mid_exists( + _: *mut dc_context_t, + rfc724_mid: *const libc::c_char, + ret_server_folder: *mut *mut libc::c_char, + ret_server_uid: *mut uint32_t, + ) -> uint32_t; + #[no_mangle] + fn dc_update_server_uid( + _: *mut dc_context_t, + rfc724_mid: *const libc::c_char, + server_folder: *const libc::c_char, + server_uid: uint32_t, + ); + #[no_mangle] + fn dc_hash_find( + _: *const dc_hash_t, + pKey: *const libc::c_void, + nKey: libc::c_int, + ) -> *mut libc::c_void; + #[no_mangle] + fn dc_apeerstate_new(_: *mut dc_context_t) -> *mut dc_apeerstate_t; + #[no_mangle] + fn dc_apeerstate_unref(_: *mut dc_apeerstate_t); + #[no_mangle] + fn dc_apeerstate_set_verified( + _: *mut dc_apeerstate_t, + which_key: libc::c_int, + fingerprint: *const libc::c_char, + verified: libc::c_int, + ) -> libc::c_int; + #[no_mangle] + fn dc_apeerstate_load_by_addr( + _: *mut dc_apeerstate_t, + _: *mut dc_sqlite3_t, + addr: *const libc::c_char, + ) -> libc::c_int; + #[no_mangle] + fn dc_apeerstate_save_to_db( + _: *const dc_apeerstate_t, + _: *mut dc_sqlite3_t, + create: libc::c_int, + ) -> libc::c_int; + #[no_mangle] + fn dc_apeerstate_has_verified_key( + _: *const dc_apeerstate_t, + fingerprints: *const dc_hash_t, + ) -> libc::c_int; + /* From: of incoming messages of unknown sender */ + /* Cc: of incoming messages of unknown sender */ + /* To: of incoming messages of unknown sender */ + /* address scanned but not verified */ + /* Reply-To: of incoming message of known sender */ + /* Cc: of incoming message of known sender */ + /* additional To:'s of incoming message of known sender */ + /* a chat was manually created for this user, but no message yet sent */ + /* message sent by us */ + /* message sent by us */ + /* message sent by us */ + /* internal use */ + /* address is in our address book */ + /* set on Alice's side for contacts like Bob that have scanned the QR code offered by her. Only means the contact has once been established using the "securejoin" procedure in the past, getting the current key verification status requires calling dc_contact_is_verified() ! */ + /* set on Bob's side for contacts scanned and verified from a QR code. Only means the contact has once been established using the "securejoin" procedure in the past, getting the current key verification status requires calling dc_contact_is_verified() ! */ + /* contact added mannually by dc_create_contact(), this should be the largets origin as otherwise the user cannot modify the names */ + /* 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 */ + #[no_mangle] + fn dc_contact_load_from_db( + _: *mut dc_contact_t, + _: *mut dc_sqlite3_t, + contact_id: uint32_t, + ) -> libc::c_int; + #[no_mangle] + fn dc_contact_is_verified_ex(_: *mut dc_contact_t, _: *const dc_apeerstate_t) -> libc::c_int; + // Working with names + #[no_mangle] + fn dc_normalize_name(full_name: *mut libc::c_char); + // Working with e-mail-addresses + #[no_mangle] + fn dc_addr_cmp(addr1: *const libc::c_char, addr2: *const libc::c_char) -> libc::c_int; + #[no_mangle] + fn dc_addr_equals_contact( + _: *mut dc_context_t, + addr: *const libc::c_char, + contact_id: uint32_t, + ) -> libc::c_int; + #[no_mangle] + fn dc_add_or_lookup_contact( + _: *mut dc_context_t, + display_name: *const libc::c_char, + addr_spec: *const libc::c_char, + origin: libc::c_int, + sth_modified: *mut libc::c_int, + ) -> uint32_t; + #[no_mangle] + fn dc_get_contact_origin( + _: *mut dc_context_t, + contact_id: uint32_t, + ret_blocked: *mut libc::c_int, + ) -> libc::c_int; + #[no_mangle] + fn dc_is_contact_blocked(_: *mut dc_context_t, contact_id: uint32_t) -> libc::c_int; + #[no_mangle] + fn dc_scaleup_contact_origin(_: *mut dc_context_t, contact_id: uint32_t, origin: libc::c_int); + #[no_mangle] + fn dc_job_add( + _: *mut dc_context_t, + action: libc::c_int, + foreign_id: libc::c_int, + param: *const libc::c_char, + delay: libc::c_int, + ); + #[no_mangle] + fn dc_mimeparser_new( + blobdir: *const libc::c_char, + _: *mut dc_context_t, + ) -> *mut dc_mimeparser_t; + #[no_mangle] + fn dc_mimeparser_unref(_: *mut dc_mimeparser_t); + #[no_mangle] + fn dc_mimeparser_parse( + _: *mut dc_mimeparser_t, + body_not_terminated: *const libc::c_char, + body_bytes: size_t, + ); + /* the following functions can be used only after a call to dc_mimeparser_parse() */ + #[no_mangle] + fn dc_mimeparser_lookup_field( + _: *mut dc_mimeparser_t, + field_name: *const libc::c_char, + ) -> *mut mailimf_field; + #[no_mangle] + fn dc_mimeparser_lookup_optional_field( + _: *mut dc_mimeparser_t, + field_name: *const libc::c_char, + ) -> *mut mailimf_optional_field; + #[no_mangle] + fn dc_mimeparser_get_last_nonmeta(_: *mut dc_mimeparser_t) -> *mut dc_mimepart_t; + #[no_mangle] + fn dc_mimeparser_is_mailinglist_message(_: *mut dc_mimeparser_t) -> libc::c_int; + #[no_mangle] + fn dc_mimeparser_sender_equals_recipient(_: *mut dc_mimeparser_t) -> libc::c_int; + #[no_mangle] + fn dc_mimeparser_repl_msg_by_error(_: *mut dc_mimeparser_t, error_msg: *const libc::c_char); + /* low-level-tools for working with mailmime structures directly */ + #[no_mangle] + fn mailmime_find_ct_parameter( + _: *mut mailmime, + name: *const libc::c_char, + ) -> *mut mailmime_parameter; + #[no_mangle] + fn mailmime_transfer_decode( + _: *mut mailmime, + ret_decoded_data: *mut *const libc::c_char, + ret_decoded_data_bytes: *mut size_t, + ret_to_mmap_string_unref: *mut *mut libc::c_char, + ) -> libc::c_int; + #[no_mangle] + fn mailmime_find_mailimf_fields(_: *mut mailmime) -> *mut mailimf_fields; + #[no_mangle] + fn mailimf_find_optional_field( + _: *mut mailimf_fields, + wanted_fld_name: *const libc::c_char, + ) -> *mut mailimf_optional_field; + #[no_mangle] + fn dc_log_warning(_: *mut dc_context_t, data1: libc::c_int, msg: *const libc::c_char, _: ...); + #[no_mangle] + fn dc_log_info(_: *mut dc_context_t, data1: libc::c_int, msg: *const libc::c_char, _: ...); + #[no_mangle] + fn dc_save_locations( + _: *mut dc_context_t, + chat_id: uint32_t, + contact_id: uint32_t, + _: *const dc_array_t, + ) -> uint32_t; + #[no_mangle] + fn dc_set_msg_location_id(_: *mut dc_context_t, msg_id: uint32_t, location_id: uint32_t); + #[no_mangle] + fn dc_do_heuristics_moves(_: *mut dc_context_t, folder: *const libc::c_char, msg_id: uint32_t); + #[no_mangle] + fn rpgp_hash_sha256(bytes_ptr: *const uint8_t, bytes_len: size_t) -> *mut rpgp_cvec; + #[no_mangle] + fn rpgp_cvec_drop(cvec_ptr: *mut rpgp_cvec); + #[no_mangle] + fn rpgp_cvec_data(cvec_ptr: *mut rpgp_cvec) -> *const uint8_t; + /* library private: secure-join */ + #[no_mangle] + fn dc_handle_securejoin_handshake( + _: *mut dc_context_t, + _: *mut dc_mimeparser_t, + contact_id: uint32_t, + ) -> libc::c_int; +} +pub type __darwin_size_t = libc::c_ulong; +pub type __darwin_ssize_t = libc::c_long; +pub type __darwin_time_t = libc::c_long; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_cond_t { + pub __sig: libc::c_long, + pub __opaque: [libc::c_char; 40], +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_mutex_t { + pub __sig: libc::c_long, + pub __opaque: [libc::c_char; 56], +} +pub type __darwin_pthread_cond_t = _opaque_pthread_cond_t; +pub type __darwin_pthread_mutex_t = _opaque_pthread_mutex_t; +pub type int32_t = libc::c_int; +pub type uintptr_t = libc::c_ulong; +pub type size_t = __darwin_size_t; +pub type uint8_t = libc::c_uchar; +pub type uint32_t = libc::c_uint; +pub type ssize_t = __darwin_ssize_t; +pub type time_t = __darwin_time_t; +pub type pthread_cond_t = __darwin_pthread_cond_t; +pub type pthread_mutex_t = __darwin_pthread_mutex_t; +#[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; +#[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) -> (); +#[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 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 unnamed = libc::c_uint; +pub const MAILIMF_ADDRESS_GROUP: unnamed = 2; +pub const MAILIMF_ADDRESS_MAILBOX: unnamed = 1; +pub const MAILIMF_ADDRESS_ERROR: unnamed = 0; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct mailimf_address { + pub ad_type: libc::c_int, + pub ad_data: unnamed_0, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed_0 { + pub ad_mailbox: *mut mailimf_mailbox, + pub ad_group: *mut mailimf_group, +} +#[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, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct mailimf_mailbox_list { + pub mb_list: *mut clist, +} +#[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_fields { + pub fld_list: *mut clist, +} +pub type unnamed_1 = libc::c_uint; +pub const MAILIMF_FIELD_OPTIONAL_FIELD: unnamed_1 = 22; +pub const MAILIMF_FIELD_KEYWORDS: unnamed_1 = 21; +pub const MAILIMF_FIELD_COMMENTS: unnamed_1 = 20; +pub const MAILIMF_FIELD_SUBJECT: unnamed_1 = 19; +pub const MAILIMF_FIELD_REFERENCES: unnamed_1 = 18; +pub const MAILIMF_FIELD_IN_REPLY_TO: unnamed_1 = 17; +pub const MAILIMF_FIELD_MESSAGE_ID: unnamed_1 = 16; +pub const MAILIMF_FIELD_BCC: unnamed_1 = 15; +pub const MAILIMF_FIELD_CC: unnamed_1 = 14; +pub const MAILIMF_FIELD_TO: unnamed_1 = 13; +pub const MAILIMF_FIELD_REPLY_TO: unnamed_1 = 12; +pub const MAILIMF_FIELD_SENDER: unnamed_1 = 11; +pub const MAILIMF_FIELD_FROM: unnamed_1 = 10; +pub const MAILIMF_FIELD_ORIG_DATE: unnamed_1 = 9; +pub const MAILIMF_FIELD_RESENT_MSG_ID: unnamed_1 = 8; +pub const MAILIMF_FIELD_RESENT_BCC: unnamed_1 = 7; +pub const MAILIMF_FIELD_RESENT_CC: unnamed_1 = 6; +pub const MAILIMF_FIELD_RESENT_TO: unnamed_1 = 5; +pub const MAILIMF_FIELD_RESENT_SENDER: unnamed_1 = 4; +pub const MAILIMF_FIELD_RESENT_FROM: unnamed_1 = 3; +pub const MAILIMF_FIELD_RESENT_DATE: unnamed_1 = 2; +pub const MAILIMF_FIELD_RETURN_PATH: unnamed_1 = 1; +pub const MAILIMF_FIELD_NONE: unnamed_1 = 0; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct mailimf_field { + pub fld_type: libc::c_int, + pub fld_data: unnamed_2, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed_2 { + 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, +} +#[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, +} +pub type unnamed_3 = libc::c_uint; +pub const MAILMIME_COMPOSITE_TYPE_EXTENSION: unnamed_3 = 3; +pub const MAILMIME_COMPOSITE_TYPE_MULTIPART: unnamed_3 = 2; +pub const MAILMIME_COMPOSITE_TYPE_MESSAGE: unnamed_3 = 1; +pub const MAILMIME_COMPOSITE_TYPE_ERROR: unnamed_3 = 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 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_type { + pub tp_type: libc::c_int, + pub tp_data: unnamed_4, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed_4 { + 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, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct mailmime_fields { + pub fld_list: *mut clist, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct mailmime_parameter { + pub pa_name: *mut libc::c_char, + pub pa_value: *mut libc::c_char, +} +pub type unnamed_5 = libc::c_uint; +pub const MAILMIME_TYPE_COMPOSITE_TYPE: unnamed_5 = 2; +pub const MAILMIME_TYPE_DISCRETE_TYPE: unnamed_5 = 1; +pub const MAILMIME_TYPE_ERROR: unnamed_5 = 0; +#[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_6, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed_6 { + pub dt_text: unnamed_7, + pub dt_filename: *mut libc::c_char, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct unnamed_7 { + pub dt_data: *const libc::c_char, + pub dt_length: size_t, +} +#[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_8, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed_8 { + pub mm_single: *mut mailmime_data, + pub mm_multipart: unnamed_10, + pub mm_message: unnamed_9, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct unnamed_9 { + pub mm_fields: *mut mailimf_fields, + pub mm_msg_mime: *mut mailmime, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct unnamed_10 { + pub mm_preamble: *mut mailmime_data, + pub mm_epilogue: *mut mailmime_data, + pub mm_mp_list: *mut clist, +} +pub type unnamed_11 = libc::c_uint; +pub const MAIL_ERROR_SSL: unnamed_11 = 58; +pub const MAIL_ERROR_FOLDER: unnamed_11 = 57; +pub const MAIL_ERROR_UNABLE: unnamed_11 = 56; +pub const MAIL_ERROR_SYSTEM: unnamed_11 = 55; +pub const MAIL_ERROR_COMMAND: unnamed_11 = 54; +pub const MAIL_ERROR_SEND: unnamed_11 = 53; +pub const MAIL_ERROR_CHAR_ENCODING_FAILED: unnamed_11 = 52; +pub const MAIL_ERROR_SUBJECT_NOT_FOUND: unnamed_11 = 51; +pub const MAIL_ERROR_PROGRAM_ERROR: unnamed_11 = 50; +pub const MAIL_ERROR_NO_PERMISSION: unnamed_11 = 49; +pub const MAIL_ERROR_COMMAND_NOT_SUPPORTED: unnamed_11 = 48; +pub const MAIL_ERROR_NO_APOP: unnamed_11 = 47; +pub const MAIL_ERROR_READONLY: unnamed_11 = 46; +pub const MAIL_ERROR_FATAL: unnamed_11 = 45; +pub const MAIL_ERROR_CLOSE: unnamed_11 = 44; +pub const MAIL_ERROR_CAPABILITY: unnamed_11 = 43; +pub const MAIL_ERROR_PROTOCOL: unnamed_11 = 42; +pub const MAIL_ERROR_MISC: unnamed_11 = 41; +pub const MAIL_ERROR_EXPUNGE: unnamed_11 = 40; +pub const MAIL_ERROR_NO_TLS: unnamed_11 = 39; +pub const MAIL_ERROR_CACHE_MISS: unnamed_11 = 38; +pub const MAIL_ERROR_STARTTLS: unnamed_11 = 37; +pub const MAIL_ERROR_MOVE: unnamed_11 = 36; +pub const MAIL_ERROR_FOLDER_NOT_FOUND: unnamed_11 = 35; +pub const MAIL_ERROR_REMOVE: unnamed_11 = 34; +pub const MAIL_ERROR_PART_NOT_FOUND: unnamed_11 = 33; +pub const MAIL_ERROR_INVAL: unnamed_11 = 32; +pub const MAIL_ERROR_PARSE: unnamed_11 = 31; +pub const MAIL_ERROR_MSG_NOT_FOUND: unnamed_11 = 30; +pub const MAIL_ERROR_DISKSPACE: unnamed_11 = 29; +pub const MAIL_ERROR_SEARCH: unnamed_11 = 28; +pub const MAIL_ERROR_STORE: unnamed_11 = 27; +pub const MAIL_ERROR_FETCH: unnamed_11 = 26; +pub const MAIL_ERROR_COPY: unnamed_11 = 25; +pub const MAIL_ERROR_APPEND: unnamed_11 = 24; +pub const MAIL_ERROR_LSUB: unnamed_11 = 23; +pub const MAIL_ERROR_LIST: unnamed_11 = 22; +pub const MAIL_ERROR_UNSUBSCRIBE: unnamed_11 = 21; +pub const MAIL_ERROR_SUBSCRIBE: unnamed_11 = 20; +pub const MAIL_ERROR_STATUS: unnamed_11 = 19; +pub const MAIL_ERROR_MEMORY: unnamed_11 = 18; +pub const MAIL_ERROR_SELECT: unnamed_11 = 17; +pub const MAIL_ERROR_EXAMINE: unnamed_11 = 16; +pub const MAIL_ERROR_CHECK: unnamed_11 = 15; +pub const MAIL_ERROR_RENAME: unnamed_11 = 14; +pub const MAIL_ERROR_NOOP: unnamed_11 = 13; +pub const MAIL_ERROR_LOGOUT: unnamed_11 = 12; +pub const MAIL_ERROR_DELETE: unnamed_11 = 11; +pub const MAIL_ERROR_CREATE: unnamed_11 = 10; +pub const MAIL_ERROR_LOGIN: unnamed_11 = 9; +pub const MAIL_ERROR_STREAM: unnamed_11 = 8; +pub const MAIL_ERROR_FILE: unnamed_11 = 7; +pub const MAIL_ERROR_BAD_STATE: unnamed_11 = 6; +pub const MAIL_ERROR_CONNECT: unnamed_11 = 5; +pub const MAIL_ERROR_UNKNOWN: unnamed_11 = 4; +pub const MAIL_ERROR_NOT_IMPLEMENTED: unnamed_11 = 3; +pub const MAIL_NO_ERROR_NON_AUTHENTICATED: unnamed_11 = 2; +pub const MAIL_NO_ERROR_AUTHENTICATED: unnamed_11 = 1; +pub const MAIL_NO_ERROR: unnamed_11 = 0; +#[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_12, + 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_12 { + 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_capability_data { + pub cap_list: *mut clist, +} +#[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_13, + 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_13 { + 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 extern "C" 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_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, +} +#[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_14, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed_14 { + pub ft_fetch_att: *mut mailimap_fetch_att, + pub ft_fetch_att_list: *mut clist, +} +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_15, + 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 unnamed_15 { + 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, +} +/* define DC_USE_RPGP to enable use of rPGP instead of netpgp where available; +preferrably, this should be done in the project configuration currently */ +//#define DC_USE_RPGP 1 +/* Includes that are used frequently. This file may also be used to create predefined headers. */ +/* * Structure behind dc_context_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_context { + pub magic: uint32_t, + pub userdata: *mut libc::c_void, + pub dbfile: *mut libc::c_char, + pub blobdir: *mut libc::c_char, + pub sql: *mut dc_sqlite3_t, + pub inbox: *mut dc_imap_t, + pub inboxidle_condmutex: pthread_mutex_t, + pub perform_inbox_jobs_needed: libc::c_int, + pub probe_imap_network: libc::c_int, + pub sentbox_thread: dc_jobthread_t, + pub mvbox_thread: dc_jobthread_t, + pub smtp: *mut dc_smtp_t, + pub smtpidle_cond: pthread_cond_t, + pub smtpidle_condmutex: pthread_mutex_t, + pub smtpidle_condflag: libc::c_int, + pub smtp_suspended: libc::c_int, + pub smtp_doing_jobs: libc::c_int, + pub perform_smtp_jobs_needed: libc::c_int, + pub probe_smtp_network: libc::c_int, + pub oauth2_critical: pthread_mutex_t, + 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 type dc_lot_t = _dc_lot; +/* * Structure behind dc_lot_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_lot { + pub magic: uint32_t, + pub text1_meaning: libc::c_int, + pub text1: *mut libc::c_char, + pub text2: *mut libc::c_char, + pub timestamp: time_t, + pub state: libc::c_int, + pub id: uint32_t, + pub fingerprint: *mut libc::c_char, + pub invitenumber: *mut libc::c_char, + pub auth: *mut libc::c_char, +} +/* * + * 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 = Option< + unsafe extern "C" fn( + _: *mut dc_context_t, + _: libc::c_int, + _: uintptr_t, + _: uintptr_t, + ) -> uintptr_t, +>; +/* * + * @mainpage Getting started + * + * This document describes how to handle the Delta Chat core library. + * For general information about Delta Chat itself, + * see and . + * + * Let's start. + * + * First of all, you have to **define an event-handler-function** + * that is called by the library on specific events + * (eg. when the configuration is done or when fresh messages arrive). + * With this function you can create a Delta Chat context then: + * + * ~~~ + * #include + * + * uintptr_t event_handler_func(dc_context_t* context, int event, + * uintptr_t data1, uintptr_t data2) + * { + * return 0; // for unhandled events, it is always safe to return 0 + * } + * + * dc_context_t* context = dc_context_new(event_handler_func, NULL, NULL); + * ~~~ + * + * After that, you should make sure, + * sending and receiving jobs are processed as needed. + * For this purpose, you have to **create two threads:** + * + * ~~~ + * #include + * + * void* imap_thread_func(void* context) + * { + * while (true) { + * dc_perform_imap_jobs(context); + * dc_perform_imap_fetch(context); + * dc_perform_imap_idle(context); + * } + * } + * + * void* smtp_thread_func(void* context) + * { + * while (true) { + * dc_perform_smtp_jobs(context); + * dc_perform_smtp_idle(context); + * } + * } + * + * static pthread_t imap_thread, smtp_thread; + * pthread_create(&imap_thread, NULL, imap_thread_func, context); + * pthread_create(&smtp_thread, NULL, smtp_thread_func, context); + * ~~~ + * + * The example above uses "pthreads", + * however, you can also use anything else for thread handling. + * NB: The deltachat-core library itself does not create any threads on its own, + * however, functions, unless stated otherwise, are thread-safe. + * + * After that you can **define and open a database.** + * The database is a normal sqlite-file and is created as needed: + * + * ~~~ + * dc_open(context, "example.db", NULL); + * ~~~ + * + * Now you can **configure the context:** + * + * ~~~ + * // use some real test credentials here + * dc_set_config(context, "addr", "alice@example.org"); + * dc_set_config(context, "mail_pw", "***"); + * dc_configure(context); + * ~~~ + * + * dc_configure() returns immediately, the configuration itself may take a while + * and is done by a job in the imap-thread you've defined above. + * Once done, the #DC_EVENT_CONFIGURE_PROGRESS reports success + * to the event_handler_func() that is also defined above. + * + * The configuration result is saved in the database, + * on subsequent starts it is not needed to call dc_configure() + * (you can check this using dc_is_configured()). + * + * Now you can **send the first message:** + * + * ~~~ + * // use a real testing address here + * uint32_t contact_id = dc_create_contact(context, NULL, "bob@example.org"); + * uint32_t chat_id = dc_create_chat_by_contact_id(context, contact_id); + * + * dc_send_text_msg(context, chat_id, "Hi, here is my first message!"); + * ~~~ + * + * dc_send_text_msg() returns immediately; + * the sending itself is done by a job in the smtp-thread you've defined above. + * If you check the testing address (bob) + * and you should have received a normal email. + * Answer this email in any email program with "Got it!" + * and the imap-thread you've create above will **receive the message**. + * + * You can then **list all messages** of a chat as follow: + * + * ~~~ + * dc_array_t* msglist = dc_get_chat_msgs(context, chat_id, 0, 0); + * for (int i = 0; i < dc_array_get_cnt(msglist); i++) + * { + * uint32_t msg_id = dc_array_get_id(msglist, i); + * dc_msg_t* msg = dc_get_msg(context, msg_id); + * char* text = dc_msg_get_text(msg); + * + * printf("Message %i: %s\n", i+1, text); + * + * free(text); + * dc_msg_unref(msg); + * } + * dc_array_unref(msglist); + * ~~~ + * + * This will output the following two lines: + * + * ~~~ + * Message 1: Hi, here is my first message! + * Message 2: Got it! + * ~~~ + * + * + * ## Class reference + * + * For a class reference, see the "Classes" link atop. + * + * + * ## Further hints + * + * Here are some additional, unsorted hints that may be useful. + * + * - For `get`-functions, you have to unref the return value in some way. + * + * - Strings in function arguments or return values are usually UTF-8 encoded. + * + * - The issue-tracker for the core library is here: + * + * + * The following points are important mainly + * for the authors of the library itself: + * + * - For indentation, use tabs. + * Alignments that are not placed at the beginning of a line + * should be done with spaces. + * + * - For padding between functions, + * classes etc. use 2 empty lines + * + * - Source files are encoded as UTF-8 with Unix line endings + * (a simple `LF`, `0x0A` or `\n`) + * + * If you need further assistance, + * please do not hesitate to contact us + * through the channels shown at https://delta.chat/en/contribute + * + * Please keep in mind, that your derived work + * must respect the Mozilla Public License 2.0 of libdeltachat + * and the respective licenses of the libraries libdeltachat links with. + * + * See you. + */ +/* * + * @class dc_context_t + * + * An object representing a single account. + * + * Each account is linked to an IMAP/SMTP account and uses a separate + * SQLite database for offline functionality and for account-related + * settings. + */ +pub type dc_context_t = _dc_context; +/* ** library-private **********************************************************/ +pub type dc_smtp_t = _dc_smtp; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_smtp { + 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 error: *mut libc::c_char, + pub error_etpan: libc::c_int, +} +pub type dc_jobthread_t = _dc_jobthread; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_jobthread { + 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, + 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, +} +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_imap { + 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 type dc_receive_imf_t = Option< + unsafe extern "C" 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_imap_t = _dc_imap; +pub type dc_precheck_imf_t = Option< + unsafe extern "C" 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< + unsafe extern "C" fn(_: *mut dc_imap_t, _: *const libc::c_char, _: *const libc::c_char) -> (), +>; +pub type dc_get_config_t = Option< + unsafe extern "C" fn( + _: *mut dc_imap_t, + _: *const libc::c_char, + _: *const libc::c_char, + ) -> *mut libc::c_char, +>; +/* ** library-private **********************************************************/ +pub type dc_sqlite3_t = _dc_sqlite3; +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_sqlite3 { + pub cobj: *mut sqlite3, + pub context: *mut dc_context_t, +} +/* * the structure behind dc_array_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_array { + 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, +} +pub type dc_array_t = _dc_array; +/* values for the chats.blocked database field */ +/* * the structure behind dc_chat_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_chat { + 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 grpid: *mut libc::c_char, + pub blocked: libc::c_int, + pub param: *mut dc_param_t, + pub gossiped_timestamp: time_t, + pub is_sending_locations: libc::c_int, +} +pub type dc_param_t = _dc_param; +/* * + * @class dc_param_t + * + * An object for handling key=value parameter lists; for the key, curently only + * a single character is allowed. + * + * The object is used eg. by dc_chat_t or dc_msg_t, for readable paramter names, + * these classes define some DC_PARAM_* constantats. + * + * Only for library-internal use. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_param { + pub packed: *mut libc::c_char, +} +pub type dc_chat_t = _dc_chat; +/* * the structure behind dc_contact_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_contact { + pub magic: uint32_t, + pub context: *mut dc_context_t, + pub id: uint32_t, + pub name: *mut libc::c_char, + pub authname: *mut libc::c_char, + pub addr: *mut libc::c_char, + pub blocked: libc::c_int, + pub origin: libc::c_int, +} +pub type dc_contact_t = _dc_contact; +pub type sqlite_int64 = libc::c_longlong; +pub type sqlite3_int64 = sqlite_int64; +pub type sqlite3_destructor_type = Option ()>; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_strbuilder { + pub buf: *mut libc::c_char, + pub allocated: libc::c_int, + pub free: libc::c_int, + pub eos: *mut libc::c_char, +} +pub type dc_strbuilder_t = _dc_strbuilder; +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_key { + pub binary: *mut libc::c_void, + pub bytes: libc::c_int, + pub type_0: libc::c_int, + pub _m_heap_refcnt: libc::c_int, +} +pub type dc_key_t = _dc_key; +/* A complete hash table is an instance of the following structure. + * The internals of this structure are intended to be opaque -- client + * code should not attempt to access or modify the fields of this structure + * directly. Change this structure only by using the routines below. + * However, many of the "procedures" and "functions" for modifying and + * accessing this structure are really macros, so we can't really make + * this structure opaque. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_hash { + pub keyClass: libc::c_char, + pub copyKey: libc::c_char, + pub count: libc::c_int, + pub first: *mut dc_hashelem_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. + * + * Again, this structure is intended to be opaque, but it can't really + * be opaque because it is used by macros. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_hashelem { + pub next: *mut dc_hashelem_t, + pub prev: *mut dc_hashelem_t, + pub data: *mut libc::c_void, + pub pKey: *mut libc::c_void, + pub nKey: libc::c_int, +} +/* Forward declarations of structures. + */ +pub type dc_hash_t = _dc_hash; +/* prefer-encrypt states */ +/* * + * @class dc_apeerstate_t + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_apeerstate { + pub context: *mut dc_context_t, + pub addr: *mut libc::c_char, + pub last_seen: time_t, + pub last_seen_autocrypt: time_t, + pub prefer_encrypt: libc::c_int, + pub public_key: *mut dc_key_t, + pub public_key_fingerprint: *mut libc::c_char, + pub gossip_key: *mut dc_key_t, + pub gossip_timestamp: time_t, + pub gossip_key_fingerprint: *mut libc::c_char, + pub verified_key: *mut dc_key_t, + pub verified_key_fingerprint: *mut libc::c_char, + pub to_save: libc::c_int, + pub degrade_event: libc::c_int, +} +pub type dc_apeerstate_t = _dc_apeerstate; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_mimepart { + pub type_0: libc::c_int, + pub is_meta: libc::c_int, + pub int_mimetype: libc::c_int, + pub msg: *mut libc::c_char, + pub msg_raw: *mut libc::c_char, + pub bytes: libc::c_int, + pub param: *mut dc_param_t, +} +/* Parse MIME body; this is the text part of an IMF, see https://tools.ietf.org/html/rfc5322 +dc_mimeparser_t has no deep dependencies to dc_context_t or to the database +(dc_context_t is used for logging only). */ +pub type dc_mimepart_t = _dc_mimepart; +/* * + * @class dc_mimeparser_t + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_mimeparser { + pub parts: *mut carray, + pub mimeroot: *mut mailmime, + pub header: dc_hash_t, + pub header_root: *mut mailimf_fields, + pub header_protected: *mut mailimf_fields, + pub subject: *mut libc::c_char, + pub is_send_by_messenger: libc::c_int, + pub decrypting_failed: libc::c_int, + pub e2ee_helper: *mut _dc_e2ee_helper, + pub blobdir: *const libc::c_char, + pub is_forwarded: libc::c_int, + pub context: *mut dc_context_t, + pub reports: *mut carray, + pub is_system_message: libc::c_int, + pub kml: *mut _dc_kml, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_kml { + pub addr: *mut libc::c_char, + pub locations: *mut dc_array_t, + pub tag: libc::c_int, + pub curr: dc_location_t, +} +pub type dc_location_t = _dc_location; +// location handling +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_location { + pub location_id: uint32_t, + pub latitude: libc::c_double, + pub longitude: libc::c_double, + pub accuracy: libc::c_double, + pub timestamp: time_t, + pub contact_id: uint32_t, + pub msg_id: uint32_t, + pub chat_id: uint32_t, + pub marker: *mut libc::c_char, +} +/* library private: end-to-end-encryption */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_e2ee_helper { + pub encryption_successfull: libc::c_int, + pub cdata_to_free: *mut libc::c_void, + pub encrypted: libc::c_int, + pub signatures: *mut dc_hash_t, + pub gossipped_addr: *mut dc_hash_t, +} +pub type dc_mimeparser_t = _dc_mimeparser; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct rpgp_cvec { + pub data: *mut uint8_t, + pub len: size_t, +} +#[inline] +unsafe extern "C" fn carray_count(mut array: *mut carray) -> libc::c_uint { + return (*array).len; +} +#[inline] +unsafe extern "C" fn carray_get( + mut array: *mut carray, + mut indx: libc::c_uint, +) -> *mut libc::c_void { + return *(*array).array.offset(indx as isize); +} +#[no_mangle] +pub unsafe extern "C" 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, +) { + 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_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 hidden: libc::c_int = 0i32; + let mut msgrmsg: libc::c_int = 0i32; + 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; + /* 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_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); + let mut create_event_to_send: libc::c_int = 2000i32; + let mut rr_event_to_send: *mut carray = carray_new(16i32 as libc::c_uint); + let mut txt_raw: *mut libc::c_char = 0 as *mut libc::c_char; + dc_log_info( + context, + 0i32, + b"Receiving message %s/%lu...\x00" as *const u8 as *const libc::c_char, + if !server_folder.is_null() { + server_folder + } else { + b"?\x00" as *const u8 as *const libc::c_char + }, + server_uid, + ); + to_ids = dc_array_new(context, 16i32 as size_t); + if to_ids.is_null() + || created_db_entries.is_null() + || rr_event_to_send.is_null() + || mime_parser.is_null() + { + dc_log_info( + context, + 0i32, + b"Bad param.\x00" as *const u8 as *const libc::c_char, + ); + } else { + dc_mimeparser_parse(mime_parser, imf_raw_not_terminated, imf_raw_bytes); + if (*mime_parser).header.count == 0i32 { + dc_log_info( + context, + 0i32, + b"No header.\x00" as *const u8 as *const libc::c_char, + ); + } else { + /* Error - even adding an empty record won't help as we do not know the message ID */ + field = dc_mimeparser_lookup_field( + mime_parser, + b"Date\x00" as *const u8 as *const libc::c_char, + ); + if !field.is_null() && (*field).fld_type == MAILIMF_FIELD_ORIG_DATE as libc::c_int { + let mut orig_date: *mut mailimf_orig_date = (*field).fld_data.fld_orig_date; + if !orig_date.is_null() { + 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, + ); + if !field.is_null() && (*field).fld_type == MAILIMF_FIELD_FROM as libc::c_int { + 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); + dc_add_or_lookup_contacts_by_mailbox_list( + context, + (*fld_from).frm_mb_list, + 0x10i32, + from_list, + &mut check_self, + ); + if 0 != check_self { + incoming = 0i32; + if 0 != dc_mimeparser_sender_equals_recipient(mime_parser) { + from_id = 1i32 as uint32_t + } + } else if dc_array_get_cnt(from_list) >= 1i32 as libc::c_ulong { + from_id = dc_array_get_id(from_list, 0i32 as size_t); + incoming_origin = + dc_get_contact_origin(context, from_id, &mut from_id_blocked) + } + dc_array_unref(from_list); + } + } + field = dc_mimeparser_lookup_field( + mime_parser, + b"To\x00" as *const u8 as *const libc::c_char, + ); + if !field.is_null() && (*field).fld_type == MAILIMF_FIELD_TO as libc::c_int { + let mut fld_to: *mut mailimf_to = (*field).fld_data.fld_to; + if !fld_to.is_null() { + dc_add_or_lookup_contacts_by_address_list( + context, + (*fld_to).to_addr_list, + if 0 == incoming { + 0x4000i32 + } else if incoming_origin >= 0x100i32 { + 0x400i32 + } else { + 0x40i32 + }, + to_ids, + &mut to_self, + ); + } + } + if !dc_mimeparser_get_last_nonmeta(mime_parser).is_null() { + field = dc_mimeparser_lookup_field( + mime_parser, + b"Cc\x00" as *const u8 as *const libc::c_char, + ); + if !field.is_null() && (*field).fld_type == MAILIMF_FIELD_CC as libc::c_int { + let mut fld_cc: *mut mailimf_cc = (*field).fld_data.fld_cc; + if !fld_cc.is_null() { + dc_add_or_lookup_contacts_by_address_list( + context, + (*fld_cc).cc_addr_list, + if 0 == incoming { + 0x2000i32 + } else if incoming_origin >= 0x100i32 { + 0x200i32 + } else { + 0x20i32 + }, + to_ids, + 0 as *mut libc::c_int, + ); + } + } + field = dc_mimeparser_lookup_field( + mime_parser, + b"Message-ID\x00" as *const u8 as *const libc::c_char, + ); + if !field.is_null() && (*field).fld_type == MAILIMF_FIELD_MESSAGE_ID as libc::c_int + { + let mut fld_message_id: *mut mailimf_message_id = + (*field).fld_data.fld_message_id; + if !fld_message_id.is_null() { + rfc724_mid = dc_strdup((*fld_message_id).mid_value) + } + } + if rfc724_mid.is_null() { + rfc724_mid = dc_create_incoming_rfc724_mid(sent_timestamp, from_id, to_ids); + if rfc724_mid.is_null() { + dc_log_info( + context, + 0i32, + b"Cannot create Message-ID.\x00" as *const u8 as *const libc::c_char, + ); + current_block = 16282941964262048061; + } else { + current_block = 777662472977924419; + } + } else { + current_block = 777662472977924419; + } + match current_block { + 16282941964262048061 => {} + _ => { + /* check, if the mail is already in our database - if so, just update the folder/uid (if the mail was moved around) and finish. + (we may get a mail twice eg. if it is moved between folders. make sure, this check is done eg. before securejoin-processing) */ + 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; + if 0 != dc_rfc724_mid_exists( + context, + rfc724_mid, + &mut old_server_folder, + &mut old_server_uid, + ) { + 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, + server_folder, + server_uid, + ); + } + free(old_server_folder as *mut libc::c_void); + dc_log_info( + context, + 0i32, + b"Message already in DB.\x00" as *const u8 as *const libc::c_char, + ); + current_block = 16282941964262048061; + } else { + msgrmsg = (*mime_parser).is_send_by_messenger; + if msgrmsg == 0i32 + && 0 != dc_is_reply_to_messenger_message(context, mime_parser) + { + msgrmsg = 2i32 + } + /* incoming non-chat messages may be discarded; + maybe this can be optimized later, + by checking the state before the message body is downloaded */ + 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, + b"show_emails\x00" as *const u8 as *const libc::c_char, + 0i32, + ); + if show_emails == 0i32 { + chat_id = 3i32 as uint32_t; + allow_creation = 0i32 + } else if show_emails == 1i32 { + allow_creation = 0i32 + } + } + if 0 != incoming { + state = if 0 != flags as libc::c_long & 0x1i64 { + 16i32 + } else { + 10i32 + }; + to_id = 1i32 as uint32_t; + if !dc_mimeparser_lookup_field( + mime_parser, + b"Secure-Join\x00" as *const u8 as *const libc::c_char, + ) + .is_null() + { + 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, + from_id, + ); + if 0 != handshake & 0x2i32 { + hidden = 1i32; + 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; + dc_lookup_real_nchat_by_contact_id( + context, + from_id, + &mut test_normal_chat_id, + &mut test_normal_chat_id_blocked, + ); + if chat_id == 0i32 as libc::c_uint { + let mut create_blocked: libc::c_int = if 0 + != test_normal_chat_id + && test_normal_chat_id_blocked == 0i32 + || incoming_origin >= 0x7fffffffi32 + { + 0i32 + } else { + 2i32 + }; + create_or_lookup_group( + context, + mime_parser, + allow_creation, + create_blocked, + from_id as int32_t, + to_ids, + &mut chat_id, + &mut chat_id_blocked, + ); + if 0 != chat_id && 0 != chat_id_blocked && 0 == create_blocked { + dc_unblock_chat(context, chat_id); + chat_id_blocked = 0i32 + } + } + if chat_id == 0i32 as libc::c_uint { + if 0 != dc_mimeparser_is_mailinglist_message(mime_parser) { + chat_id = 3i32 as uint32_t; + dc_log_info( + context, + 0i32, + b"Message belongs to a mailing list and is ignored.\x00" + as *const u8 + as *const libc::c_char, + ); + } + } + if chat_id == 0i32 as libc::c_uint { + let mut create_blocked_0: libc::c_int = + if incoming_origin >= 0x7fffffffi32 || from_id == to_id { + 0i32 + } else { + 2i32 + }; + if 0 != test_normal_chat_id { + chat_id = test_normal_chat_id; + chat_id_blocked = test_normal_chat_id_blocked + } else if 0 != allow_creation { + dc_create_or_lookup_nchat_by_contact_id( + context, + from_id, + create_blocked_0, + &mut chat_id, + &mut chat_id_blocked, + ); + } + if 0 != chat_id && 0 != chat_id_blocked { + if 0 == create_blocked_0 { + dc_unblock_chat(context, chat_id); + chat_id_blocked = 0i32 + } else if 0 + != dc_is_reply_to_known_message(context, mime_parser) + { + dc_scaleup_contact_origin(context, from_id, 0x100i32); + dc_log_info(context, 0i32, + b"Message is a reply to a known message, mark sender as known.\x00" + as *const u8 as + *const libc::c_char); + incoming_origin = if incoming_origin > 0x100i32 { + incoming_origin + } else { + 0x100i32 + } + } + } + } + if chat_id == 0i32 as libc::c_uint { + chat_id = 3i32 as uint32_t + } + if 0 != chat_id_blocked && state == 10i32 { + if incoming_origin < 0x100i32 && msgrmsg == 0i32 { + state = 13i32 + } + } + } else { + state = 26i32; + from_id = 1i32 as uint32_t; + if dc_array_get_cnt(to_ids) >= 1i32 as libc::c_ulong { + to_id = dc_array_get_id(to_ids, 0i32 as size_t); + if chat_id == 0i32 as libc::c_uint { + create_or_lookup_group( + context, + mime_parser, + allow_creation, + 0i32, + from_id as int32_t, + to_ids, + &mut chat_id, + &mut chat_id_blocked, + ); + if 0 != chat_id && 0 != chat_id_blocked { + dc_unblock_chat(context, chat_id); + chat_id_blocked = 0i32 + } + } + if chat_id == 0i32 as libc::c_uint && 0 != allow_creation { + let mut create_blocked_1: libc::c_int = if 0 != msgrmsg + && 0 == dc_is_contact_blocked(context, to_id) + { + 0i32 + } else { + 2i32 + }; + dc_create_or_lookup_nchat_by_contact_id( + context, + to_id, + create_blocked_1, + &mut chat_id, + &mut chat_id_blocked, + ); + if 0 != chat_id + && 0 != chat_id_blocked + && 0 == create_blocked_1 + { + dc_unblock_chat(context, chat_id); + chat_id_blocked = 0i32 + } + } + } + if chat_id == 0i32 as libc::c_uint { + if dc_array_get_cnt(to_ids) == 0i32 as libc::c_ulong + && 0 != to_self + { + dc_create_or_lookup_nchat_by_contact_id( + context, + 1i32 as uint32_t, + 0i32, + &mut chat_id, + &mut chat_id_blocked, + ); + if 0 != chat_id && 0 != chat_id_blocked { + dc_unblock_chat(context, chat_id); + chat_id_blocked = 0i32 + } + } + } + if chat_id == 0i32 as libc::c_uint { + chat_id = 3i32 as uint32_t + } + } + calc_timestamps( + context, + chat_id, + from_id, + sent_timestamp, + if 0 != flags as libc::c_long & 0x1i64 { + 0i32 + } else { + 1i32 + }, + &mut sort_timestamp, + &mut sent_timestamp, + &mut rcvd_timestamp, + ); + dc_unarchive_chat(context, chat_id); + // 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, + 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; + p = strstr( + imf_raw_not_terminated, + b"\r\n\r\n\x00" as *const u8 as *const libc::c_char, + ); + if !p.is_null() { + header_bytes = (p.wrapping_offset_from(imf_raw_not_terminated) + as libc::c_long + + 4i32 as libc::c_long) + as libc::c_int + } else { + p = strstr( + imf_raw_not_terminated, + b"\n\n\x00" as *const u8 as *const libc::c_char, + ); + if !p.is_null() { + header_bytes = (p + .wrapping_offset_from(imf_raw_not_terminated) + as libc::c_long + + 2i32 as libc::c_long) + as libc::c_int + } + } + } + field = dc_mimeparser_lookup_field( + mime_parser, + b"In-Reply-To\x00" as *const u8 as *const libc::c_char, + ); + if !field.is_null() + && (*field).fld_type == MAILIMF_FIELD_IN_REPLY_TO as libc::c_int + { + let mut fld_in_reply_to: *mut mailimf_in_reply_to = + (*field).fld_data.fld_in_reply_to; + if !fld_in_reply_to.is_null() { + mime_in_reply_to = dc_str_from_clist( + (*(*field).fld_data.fld_in_reply_to).mid_list, + b" \x00" as *const u8 as *const libc::c_char, + ) + } + } + field = dc_mimeparser_lookup_field( + mime_parser, + b"References\x00" as *const u8 as *const libc::c_char, + ); + if !field.is_null() + && (*field).fld_type == MAILIMF_FIELD_REFERENCES as libc::c_int + { + let mut fld_references: *mut mailimf_references = + (*field).fld_data.fld_references; + if !fld_references.is_null() { + mime_references = dc_str_from_clist( + (*(*field).fld_data.fld_references).mid_list, + b" \x00" as *const u8 as *const libc::c_char, + ) + } + } + 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" + as *const u8 as + *const libc::c_char); + i = 0i32 as size_t; + loop { + if !(i < icnt) { + current_block = 2756754640271984560; + break; + } + let mut part: *mut dc_mimepart_t = + carray_get((*mime_parser).parts, i as libc::c_uint) + as *mut dc_mimepart_t; + if !(0 != (*part).is_meta) { + if !(*mime_parser).kml.is_null() + && icnt == 1i32 as libc::c_ulong + && !(*part).msg.is_null() + && (strcmp( + (*part).msg, + b"-location-\x00" as *const u8 as *const libc::c_char, + ) == 0i32 + || *(*part).msg.offset(0isize) as libc::c_int == 0i32) + { + hidden = 1i32; + if state == 10i32 { + state = 13i32 + } + } + if (*part).type_0 == 10i32 { + txt_raw = dc_mprintf( + b"%s\n\n%s\x00" as *const u8 as *const libc::c_char, + if !(*mime_parser).subject.is_null() { + (*mime_parser).subject + } else { + b"\x00" as *const u8 as *const libc::c_char + }, + (*part).msg_raw, + ) + } + if 0 != (*mime_parser).is_system_message { + dc_param_set_int( + (*part).param, + 'S' as i32, + (*mime_parser).is_system_message, + ); + } + sqlite3_reset(stmt); + sqlite3_bind_text(stmt, 1i32, rfc724_mid, -1i32, None); + sqlite3_bind_text(stmt, 2i32, server_folder, -1i32, None); + sqlite3_bind_int(stmt, 3i32, server_uid as libc::c_int); + sqlite3_bind_int(stmt, 4i32, chat_id as libc::c_int); + sqlite3_bind_int(stmt, 5i32, from_id as libc::c_int); + sqlite3_bind_int(stmt, 6i32, to_id as libc::c_int); + sqlite3_bind_int64(stmt, 7i32, sort_timestamp as sqlite3_int64); + sqlite3_bind_int64(stmt, 8i32, sent_timestamp as sqlite3_int64); + sqlite3_bind_int64(stmt, 9i32, rcvd_timestamp as sqlite3_int64); + sqlite3_bind_int(stmt, 10i32, (*part).type_0); + sqlite3_bind_int(stmt, 11i32, state); + sqlite3_bind_int(stmt, 12i32, msgrmsg); + sqlite3_bind_text( + stmt, + 13i32, + if !(*part).msg.is_null() { + (*part).msg + } else { + b"\x00" as *const u8 as *const libc::c_char + }, + -1i32, + None, + ); + sqlite3_bind_text( + stmt, + 14i32, + if !txt_raw.is_null() { + txt_raw + } else { + b"\x00" as *const u8 as *const libc::c_char + }, + -1i32, + None, + ); + sqlite3_bind_text( + stmt, + 15i32, + (*(*part).param).packed, + -1i32, + None, + ); + sqlite3_bind_int(stmt, 16i32, (*part).bytes); + sqlite3_bind_int(stmt, 17i32, hidden); + sqlite3_bind_text( + stmt, + 18i32, + if 0 != save_mime_headers { + imf_raw_not_terminated + } else { + 0 as *const libc::c_char + }, + header_bytes, + None, + ); + sqlite3_bind_text(stmt, 19i32, mime_in_reply_to, -1i32, None); + sqlite3_bind_text(stmt, 20i32, mime_references, -1i32, None); + if sqlite3_step(stmt) != 101i32 { + dc_log_info( + context, + 0i32, + b"Cannot write DB.\x00" as *const u8 + as *const libc::c_char, + ); + /* i/o error - there is nothing more we can do - in other cases, we try to write at least an empty record */ + current_block = 16282941964262048061; + break; + } else { + 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, + 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, + ); + carray_add( + created_db_entries, + chat_id as uintptr_t as *mut libc::c_void, + 0 as *mut libc::c_uint, + ); + carray_add( + created_db_entries, + insert_msg_id as uintptr_t as *mut libc::c_void, + 0 as *mut libc::c_uint, + ); + } + } + i = i.wrapping_add(1) + } + match current_block { + 16282941964262048061 => {} + _ => { + dc_log_info( + context, + 0i32, + b"Message has %i parts and is assigned to chat #%i.\x00" + as *const u8 + as *const libc::c_char, + icnt, + chat_id, + ); + if chat_id == 3i32 as libc::c_uint { + create_event_to_send = 0i32 + } else if 0 != incoming && state == 10i32 { + if 0 != from_id_blocked { + create_event_to_send = 0i32 + } else if 0 != chat_id_blocked { + create_event_to_send = 2000i32 + } else { + create_event_to_send = 2005i32 + } + } + dc_do_heuristics_moves(context, server_folder, insert_msg_id); + current_block = 18330534242458572360; + } + } + } + } + } + } else { + if sent_timestamp > time(0 as *mut time_t) { + sent_timestamp = time(0 as *mut time_t) + } + current_block = 18330534242458572360; + } + match current_block { + 16282941964262048061 => {} + _ => { + 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, + b"mdns_enabled\x00" as *const u8 as *const libc::c_char, + 1i32, + ); + icnt = carray_count((*mime_parser).reports) as size_t; + i = 0i32 as size_t; + while i < icnt { + let mut mdn_consumed: libc::c_int = 0i32; + let mut report_root: *mut mailmime = + carray_get((*mime_parser).reports, i as libc::c_uint) + as *mut mailmime; + let mut report_type: *mut mailmime_parameter = + mailmime_find_ct_parameter( + report_root, + b"report-type\x00" as *const u8 as *const libc::c_char, + ); + if !(report_root.is_null() + || report_type.is_null() + || (*report_type).pa_value.is_null()) + { + if strcmp( + (*report_type).pa_value, + b"disposition-notification\x00" as *const u8 + as *const libc::c_char, + ) == 0i32 + && (*(*report_root).mm_data.mm_multipart.mm_mp_list).count + >= 2i32 + { + if 0 != mdns_enabled { + let mut report_data: *mut mailmime = + (if !if !(*(*report_root) + .mm_data + .mm_multipart + .mm_mp_list) + .first + .is_null() + { + (*(*(*report_root).mm_data.mm_multipart.mm_mp_list) + .first) + .next + } else { + 0 as *mut clistcell_s + } + .is_null() + { + (*if !(*(*report_root) + .mm_data + .mm_multipart + .mm_mp_list) + .first + .is_null() + { + (*(*(*report_root) + .mm_data + .mm_multipart + .mm_mp_list) + .first) + .next + } else { + 0 as *mut clistcell_s + }) + .data + } else { + 0 as *mut libc::c_void + }) + as *mut mailmime; + if !report_data.is_null() + && (*(*(*report_data).mm_content_type).ct_type).tp_type + == MAILMIME_TYPE_COMPOSITE_TYPE as libc::c_int + && (*(*(*(*report_data).mm_content_type).ct_type) + .tp_data + .tp_composite_type) + .ct_type + == MAILMIME_COMPOSITE_TYPE_MESSAGE as libc::c_int + && strcmp( + (*(*report_data).mm_content_type).ct_subtype, + b"disposition-notification\x00" as *const u8 + as *const libc::c_char, + ) == 0i32 + { + let mut report_body: *const libc::c_char = + 0 as *const libc::c_char; + let mut report_body_bytes: size_t = 0i32 as size_t; + let mut to_mmap_string_unref: *mut libc::c_char = + 0 as *mut libc::c_char; + if 0 != mailmime_transfer_decode( + report_data, + &mut report_body, + &mut report_body_bytes, + &mut to_mmap_string_unref, + ) { + let mut report_parsed: *mut mailmime = + 0 as *mut mailmime; + let mut dummy: size_t = 0i32 as size_t; + if mailmime_parse( + report_body, + report_body_bytes, + &mut dummy, + &mut report_parsed, + ) == MAIL_NO_ERROR as libc::c_int + && !report_parsed.is_null() + { + let mut report_fields: *mut mailimf_fields = + mailmime_find_mailimf_fields(report_parsed); + if !report_fields.is_null() { + let mut of_disposition: + *mut mailimf_optional_field = + mailimf_find_optional_field(report_fields, + b"Disposition\x00" + as + *const u8 + as + *const libc::c_char); + let mut of_org_msgid: + *mut mailimf_optional_field = + mailimf_find_optional_field(report_fields, + b"Original-Message-ID\x00" + as + *const u8 + as + *const libc::c_char); + if !of_disposition.is_null() + && !(*of_disposition) + .fld_value + .is_null() + && !of_org_msgid.is_null() + && !(*of_org_msgid).fld_value.is_null() + { + let mut rfc724_mid_0: + *mut libc::c_char = + 0 as + *mut libc::c_char; + dummy = 0i32 as size_t; + if mailimf_msg_id_parse( + (*of_org_msgid).fld_value, + strlen((*of_org_msgid).fld_value), + &mut dummy, + &mut rfc724_mid_0, + ) == MAIL_NO_ERROR as libc::c_int + && !rfc724_mid_0.is_null() + { + let mut chat_id_0: uint32_t = + 0i32 as uint32_t; + let mut msg_id: uint32_t = + 0i32 as uint32_t; + if 0 != dc_mdn_from_ext( + context, + from_id, + rfc724_mid_0, + sent_timestamp, + &mut chat_id_0, + &mut msg_id, + ) { + carray_add( + rr_event_to_send, + chat_id_0 as uintptr_t + as *mut libc::c_void, + 0 as *mut libc::c_uint, + ); + carray_add( + rr_event_to_send, + msg_id as uintptr_t + as *mut libc::c_void, + 0 as *mut libc::c_uint, + ); + } + mdn_consumed = (msg_id + != 0i32 as libc::c_uint) + as libc::c_int; + free( + rfc724_mid_0 + as *mut libc::c_void, + ); + } + } + } + mailmime_free(report_parsed); + } + if !to_mmap_string_unref.is_null() { + mmap_string_unref(to_mmap_string_unref); + } + } + } + } + if 0 != (*mime_parser).is_send_by_messenger || 0 != mdn_consumed + { + let mut param: *mut dc_param_t = dc_param_new(); + dc_param_set(param, 'Z' as i32, server_folder); + 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, + b"mvbox_move\x00" as *const u8 + as *const libc::c_char, + 1i32, + ) + { + dc_param_set_int(param, 'M' as i32, 1i32); + } + dc_job_add(context, 120i32, 0i32, (*param).packed, 0i32); + dc_param_unref(param); + } + } + } + i = i.wrapping_add(1) + } + } + if !(*mime_parser).kml.is_null() && chat_id > 9i32 as libc::c_uint { + let mut contact: *mut dc_contact_t = dc_get_contact(context, from_id); + if !(*(*mime_parser).kml).addr.is_null() + && !contact.is_null() + && !(*contact).addr.is_null() + && strcasecmp((*contact).addr, (*(*mime_parser).kml).addr) == 0i32 + { + let mut newest_location_id: uint32_t = dc_save_locations( + context, + chat_id, + from_id, + (*(*mime_parser).kml).locations, + ); + if 0 != newest_location_id && 0 == hidden { + dc_set_msg_location_id(context, insert_msg_id, newest_location_id); + } + (*context).cb.expect("non-null function pointer")( + context, + 2035i32, + from_id as uintptr_t, + 0i32 as uintptr_t, + ); + } + dc_contact_unref(contact); + } + if 0 != add_delete_job + && carray_count(created_db_entries) >= 2i32 as libc::c_uint + { + dc_job_add( + context, + 110i32, + carray_get(created_db_entries, 1i32 as libc::c_uint) as uintptr_t + as libc::c_int, + 0 as *const libc::c_char, + 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); + free(mime_references as *mut libc::c_void); + dc_array_unref(to_ids); + if !created_db_entries.is_null() { + if 0 != 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.expect("non-null function pointer")( + context, + create_event_to_send, + carray_get(created_db_entries, i_0 as libc::c_uint) as uintptr_t, + carray_get( + created_db_entries, + i_0.wrapping_add(1i32 as libc::c_ulong) as libc::c_uint, + ) as uintptr_t, + ); + i_0 = (i_0 as libc::c_ulong).wrapping_add(2i32 as libc::c_ulong) as size_t as size_t + } + } + carray_free(created_db_entries); + } + if !rr_event_to_send.is_null() { + let mut i_1: size_t = 0; + 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 { + (*context).cb.expect("non-null function pointer")( + context, + 2015i32, + carray_get(rr_event_to_send, i_1 as libc::c_uint) as uintptr_t, + carray_get( + rr_event_to_send, + i_1.wrapping_add(1i32 as libc::c_ulong) as libc::c_uint, + ) as uintptr_t, + ); + i_1 = (i_1 as libc::c_ulong).wrapping_add(2i32 as libc::c_ulong) as size_t as size_t + } + carray_free(rr_event_to_send); + } + free(txt_raw as *mut libc::c_void); + sqlite3_finalize(stmt); +} +/* ****************************************************************************** + * Misc. Tools + ******************************************************************************/ +unsafe extern "C" fn calc_timestamps( + mut context: *mut dc_context_t, + mut chat_id: uint32_t, + mut from_id: uint32_t, + mut message_timestamp: time_t, + mut is_fresh_msg: libc::c_int, + mut sort_timestamp: *mut time_t, + mut sent_timestamp: *mut time_t, + mut rcvd_timestamp: *mut time_t, +) { + *rcvd_timestamp = time(0 as *mut time_t); + *sent_timestamp = message_timestamp; + if *sent_timestamp > *rcvd_timestamp { + *sent_timestamp = *rcvd_timestamp + } + *sort_timestamp = message_timestamp; + if 0 != is_fresh_msg { + let mut stmt: *mut sqlite3_stmt = dc_sqlite3_prepare( + (*context).sql, + b"SELECT MAX(timestamp) FROM msgs WHERE chat_id=? and from_id!=? AND timestamp>=?\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, from_id as libc::c_int); + sqlite3_bind_int64(stmt, 3i32, *sort_timestamp as sqlite3_int64); + if sqlite3_step(stmt) == 100i32 { + let mut last_msg_time: time_t = sqlite3_column_int64(stmt, 0i32) as time_t; + if last_msg_time > 0i32 as libc::c_long { + if *sort_timestamp <= last_msg_time { + *sort_timestamp = last_msg_time + 1i32 as libc::c_long + } + } + } + sqlite3_finalize(stmt); + } + if *sort_timestamp >= dc_smeared_time(context) { + *sort_timestamp = dc_create_smeared_timestamp(context) + }; +} +/* the function tries extracts the group-id from the message and returns the +corresponding chat_id. If the chat_id is not existant, it is created. +If the message contains groups commands (name, profile image, changed members), +they are executed as well. + +if no group-id could be extracted from the message, create_or_lookup_adhoc_group() is called +which tries to create or find out the chat_id by: +- is there a group with the same recipients? if so, use this (if there are multiple, use the most recent one) +- create an ad-hoc group based on the recipient list + +So when the function returns, the caller has the group id matching the current +state of the group. */ +unsafe extern "C" fn create_or_lookup_group( + mut context: *mut dc_context_t, + mut mime_parser: *mut dc_mimeparser_t, + mut allow_creation: libc::c_int, + mut create_blocked: libc::c_int, + mut from_id: int32_t, + mut to_ids: *const dc_array_t, + 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 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 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; + let mut send_EVENT_CHAT_MODIFIED: libc::c_int = 0i32; + /* pointer somewhere into mime_parser, must not be freed */ + let mut X_MrRemoveFromGrp: *mut libc::c_char = 0 as *mut libc::c_char; + /* pointer somewhere into mime_parser, must not be freed */ + let mut X_MrAddToGrp: *mut libc::c_char = 0 as *mut libc::c_char; + let mut X_MrGrpNameChanged: libc::c_int = 0i32; + let mut X_MrGrpImageChanged: *const libc::c_char = 0 as *const libc::c_char; + let mut better_msg: *mut libc::c_char = 0 as *mut libc::c_char; + let mut failure_reason: *mut libc::c_char = 0 as *mut libc::c_char; + if (*mime_parser).is_system_message == 8i32 { + better_msg = dc_stock_system_msg( + context, + 64i32, + 0 as *const libc::c_char, + 0 as *const libc::c_char, + from_id as uint32_t, + ) + } + 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; + optional_field = dc_mimeparser_lookup_optional_field( + mime_parser, + b"Chat-Group-ID\x00" as *const u8 as *const libc::c_char, + ); + if !optional_field.is_null() { + grpid = dc_strdup((*optional_field).fld_value) + } + if grpid.is_null() { + field = dc_mimeparser_lookup_field( + mime_parser, + b"Message-ID\x00" as *const u8 as *const libc::c_char, + ); + if !field.is_null() && (*field).fld_type == MAILIMF_FIELD_MESSAGE_ID as libc::c_int { + let mut fld_message_id: *mut mailimf_message_id = (*field).fld_data.fld_message_id; + if !fld_message_id.is_null() { + grpid = dc_extract_grpid_from_rfc724_mid((*fld_message_id).mid_value) + } + } + if grpid.is_null() { + field = dc_mimeparser_lookup_field( + mime_parser, + b"In-Reply-To\x00" as *const u8 as *const libc::c_char, + ); + if !field.is_null() && (*field).fld_type == MAILIMF_FIELD_IN_REPLY_TO as libc::c_int { + let mut fld_in_reply_to: *mut mailimf_in_reply_to = + (*field).fld_data.fld_in_reply_to; + if !fld_in_reply_to.is_null() { + grpid = dc_extract_grpid_from_rfc724_mid_list((*fld_in_reply_to).mid_list) + } + } + if grpid.is_null() { + field = dc_mimeparser_lookup_field( + mime_parser, + b"References\x00" as *const u8 as *const libc::c_char, + ); + if !field.is_null() && (*field).fld_type == MAILIMF_FIELD_REFERENCES as libc::c_int + { + let mut fld_references: *mut mailimf_references = + (*field).fld_data.fld_references; + if !fld_references.is_null() { + grpid = dc_extract_grpid_from_rfc724_mid_list((*fld_references).mid_list) + } + } + if grpid.is_null() { + create_or_lookup_adhoc_group( + context, + mime_parser, + allow_creation, + create_blocked, + from_id, + to_ids, + &mut chat_id, + &mut chat_id_blocked, + ); + current_block = 281803052766328415; + } else { + current_block = 18435049525520518667; + } + } else { + current_block = 18435049525520518667; + } + } else { + current_block = 18435049525520518667; + } + } else { + current_block = 18435049525520518667; + } + match current_block { + 18435049525520518667 => { + optional_field = dc_mimeparser_lookup_optional_field( + mime_parser, + b"Chat-Group-Name\x00" as *const u8 as *const libc::c_char, + ); + if !optional_field.is_null() { + grpname = dc_decode_header_words((*optional_field).fld_value) + } + optional_field = dc_mimeparser_lookup_optional_field( + mime_parser, + b"Chat-Group-Member-Removed\x00" as *const u8 as *const libc::c_char, + ); + if !optional_field.is_null() { + X_MrRemoveFromGrp = (*optional_field).fld_value; + (*mime_parser).is_system_message = 5i32; + let mut left_group: libc::c_int = + (dc_lookup_contact_id_by_addr(context, X_MrRemoveFromGrp) + == from_id as libc::c_uint) as libc::c_int; + better_msg = dc_stock_system_msg( + context, + if 0 != left_group { 19i32 } else { 18i32 }, + X_MrRemoveFromGrp, + 0 as *const libc::c_char, + from_id as uint32_t, + ) + } else { + optional_field = dc_mimeparser_lookup_optional_field( + mime_parser, + b"Chat-Group-Member-Added\x00" as *const u8 as *const libc::c_char, + ); + if !optional_field.is_null() { + X_MrAddToGrp = (*optional_field).fld_value; + (*mime_parser).is_system_message = 4i32; + optional_field = dc_mimeparser_lookup_optional_field( + mime_parser, + b"Chat-Group-Image\x00" as *const u8 as *const libc::c_char, + ); + if !optional_field.is_null() { + X_MrGrpImageChanged = (*optional_field).fld_value + } + better_msg = dc_stock_system_msg( + context, + 17i32, + X_MrAddToGrp, + 0 as *const libc::c_char, + from_id as uint32_t, + ) + } else { + optional_field = dc_mimeparser_lookup_optional_field( + mime_parser, + b"Chat-Group-Name-Changed\x00" as *const u8 as *const libc::c_char, + ); + if !optional_field.is_null() { + X_MrGrpNameChanged = 1i32; + (*mime_parser).is_system_message = 2i32; + better_msg = dc_stock_system_msg( + context, + 15i32, + (*optional_field).fld_value, + grpname, + from_id as uint32_t, + ) + } else { + optional_field = dc_mimeparser_lookup_optional_field( + mime_parser, + b"Chat-Group-Image\x00" as *const u8 as *const libc::c_char, + ); + if !optional_field.is_null() { + X_MrGrpImageChanged = (*optional_field).fld_value; + (*mime_parser).is_system_message = 3i32; + better_msg = dc_stock_system_msg( + context, + if strcmp( + X_MrGrpImageChanged, + b"0\x00" as *const u8 as *const libc::c_char, + ) == 0i32 + { + 33i32 + } else { + 16i32 + }, + 0 as *const libc::c_char, + 0 as *const libc::c_char, + from_id as uint32_t, + ) + } + } + } + } + set_better_msg(mime_parser, &mut better_msg); + chat_id = dc_get_chat_id_by_grpid( + context, + grpid, + &mut chat_id_blocked, + &mut chat_id_verified, + ); + if chat_id != 0i32 as libc::c_uint { + if 0 != chat_id_verified + && 0 == check_verified_properties( + context, + mime_parser, + from_id as uint32_t, + to_ids, + &mut failure_reason, + ) + { + dc_mimeparser_repl_msg_by_error(mime_parser, failure_reason); + } + } + if chat_id != 0i32 as libc::c_uint + && 0 == dc_is_contact_in_chat(context, chat_id, from_id as uint32_t) + { + recreate_member_list = 1i32 + } + /* 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, + b"configured_addr\x00" as *const u8 as *const libc::c_char, + b"\x00" as *const u8 as *const libc::c_char, + ); + if chat_id == 0i32 as libc::c_uint + && 0 == dc_mimeparser_is_mailinglist_message(mime_parser) + && !grpid.is_null() + && !grpname.is_null() + && X_MrRemoveFromGrp.is_null() + && (0 == group_explicitly_left + || !X_MrAddToGrp.is_null() && dc_addr_cmp(self_addr, X_MrAddToGrp) == 0i32) + { + /*otherwise, a pending "quit" message may pop up*/ + /*re-create explicitly left groups only if ourself is re-added*/ + let mut create_verified: libc::c_int = 0i32; + if !dc_mimeparser_lookup_field( + mime_parser, + b"Chat-Verified\x00" as *const u8 as *const libc::c_char, + ) + .is_null() + { + create_verified = 1i32; + if 0 == check_verified_properties( + context, + mime_parser, + from_id as uint32_t, + to_ids, + &mut failure_reason, + ) { + dc_mimeparser_repl_msg_by_error(mime_parser, failure_reason); + } + } + if 0 == allow_creation { + current_block = 281803052766328415; + } else { + chat_id = create_group_record( + context, + grpid, + grpname, + create_blocked, + create_verified, + ); + chat_id_blocked = create_blocked; + chat_id_verified = create_verified; + recreate_member_list = 1i32; + current_block = 200744462051969938; + } + } else { + current_block = 200744462051969938; + } + match current_block { + 281803052766328415 => {} + _ => { + /* again, check chat_id */ + if chat_id <= 9i32 as libc::c_uint { + chat_id = 0i32 as uint32_t; + if 0 != group_explicitly_left { + chat_id = 3i32 as uint32_t + } else { + create_or_lookup_adhoc_group( + context, + mime_parser, + allow_creation, + create_blocked, + from_id, + to_ids, + &mut chat_id, + &mut chat_id_blocked, + ); + } + } else { + if !X_MrAddToGrp.is_null() || !X_MrRemoveFromGrp.is_null() { + recreate_member_list = 1i32 + } else if 0 != X_MrGrpNameChanged + && !grpname.is_null() + && strlen(grpname) < 200i32 as libc::c_ulong + { + stmt = dc_sqlite3_prepare( + (*context).sql, + b"UPDATE chats SET name=? WHERE id=?;\x00" as *const u8 + as *const libc::c_char, + ); + sqlite3_bind_text(stmt, 1i32, grpname, -1i32, None); + sqlite3_bind_int(stmt, 2i32, chat_id as libc::c_int); + sqlite3_step(stmt); + sqlite3_finalize(stmt); + (*context).cb.expect("non-null function pointer")( + context, + 2020i32, + chat_id as uintptr_t, + 0i32 as uintptr_t, + ); + } + if !X_MrGrpImageChanged.is_null() { + let mut ok: libc::c_int = 0i32; + let mut grpimage: *mut libc::c_char = 0 as *mut libc::c_char; + if strcmp( + X_MrGrpImageChanged, + b"0\x00" as *const u8 as *const libc::c_char, + ) == 0i32 + { + ok = 1i32 + } else { + let mut i_0: libc::c_int = 0i32; + while (i_0 as libc::c_uint) < carray_count((*mime_parser).parts) { + let mut part: *mut dc_mimepart_t = + carray_get((*mime_parser).parts, i_0 as libc::c_uint) + as *mut dc_mimepart_t; + if (*part).type_0 == 20i32 { + grpimage = dc_param_get( + (*part).param, + 'f' as i32, + 0 as *const libc::c_char, + ); + ok = 1i32 + } + i_0 += 1 + } + } + if 0 != ok { + let mut chat: *mut dc_chat_t = dc_chat_new(context); + dc_log_info( + context, + 0i32, + b"New group image set to %s.\x00" as *const u8 + as *const libc::c_char, + if !grpimage.is_null() { + b"DELETED\x00" as *const u8 as *const libc::c_char + } else { + grpimage + }, + ); + dc_chat_load_from_db(chat, chat_id); + dc_param_set((*chat).param, 'i' as i32, grpimage); + dc_chat_update_param(chat); + dc_chat_unref(chat); + free(grpimage as *mut libc::c_void); + send_EVENT_CHAT_MODIFIED = 1i32 + } + } + if 0 != recreate_member_list { + let mut skip: *const libc::c_char = if !X_MrRemoveFromGrp.is_null() { + X_MrRemoveFromGrp + } else { + 0 as *mut libc::c_char + }; + stmt = dc_sqlite3_prepare( + (*context).sql, + b"DELETE FROM chats_contacts WHERE chat_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); + if skip.is_null() || dc_addr_cmp(self_addr, skip) != 0i32 { + dc_add_to_chat_contacts_table(context, chat_id, 1i32 as uint32_t); + } + if from_id > 9i32 { + if dc_addr_equals_contact(context, self_addr, from_id as uint32_t) + == 0i32 + && (skip.is_null() + || dc_addr_equals_contact( + context, + skip, + from_id as uint32_t, + ) == 0i32) + { + dc_add_to_chat_contacts_table( + context, + chat_id, + from_id as uint32_t, + ); + } + } + i = 0i32; + while i < to_ids_cnt { + let mut to_id: uint32_t = dc_array_get_id(to_ids, i as size_t); + if dc_addr_equals_contact(context, self_addr, to_id) == 0i32 + && (skip.is_null() + || dc_addr_equals_contact(context, skip, to_id) == 0i32) + { + dc_add_to_chat_contacts_table(context, chat_id, to_id); + } + i += 1 + } + send_EVENT_CHAT_MODIFIED = 1i32; + dc_reset_gossiped_timestamp(context, chat_id); + } + if 0 != send_EVENT_CHAT_MODIFIED { + (*context).cb.expect("non-null function pointer")( + context, + 2020i32, + chat_id as uintptr_t, + 0i32 as uintptr_t, + ); + } + /* check the number of receivers - + the only critical situation is if the user hits "Reply" instead of "Reply all" in a non-messenger-client */ + if to_ids_cnt == 1i32 && (*mime_parser).is_send_by_messenger == 0i32 { + let mut is_contact_cnt: libc::c_int = + dc_get_chat_contact_cnt(context, chat_id); + if is_contact_cnt > 3i32 { + /* to_ids_cnt==1 may be "From: A, To: B, SELF" as SELF is not counted in to_ids_cnt. So everything up to 3 is no error. */ + chat_id = 0i32 as uint32_t; + create_or_lookup_adhoc_group( + context, + mime_parser, + allow_creation, + create_blocked, + from_id, + to_ids, + &mut chat_id, + &mut chat_id_blocked, + ); + } + } + } + } + } + } + _ => {} + } + free(grpid as *mut libc::c_void); + free(grpname as *mut libc::c_void); + free(self_addr as *mut libc::c_void); + free(better_msg as *mut libc::c_void); + free(failure_reason as *mut libc::c_void); + if !ret_chat_id.is_null() { + *ret_chat_id = chat_id + } + if !ret_chat_id_blocked.is_null() { + *ret_chat_id_blocked = if 0 != chat_id { chat_id_blocked } else { 0i32 } + }; +} +/* ****************************************************************************** + * Handle groups for received messages + ******************************************************************************/ +unsafe extern "C" fn create_or_lookup_adhoc_group( + mut context: *mut dc_context_t, + mut mime_parser: *mut dc_mimeparser_t, + mut allow_creation: libc::c_int, + mut create_blocked: libc::c_int, + mut from_id: int32_t, + mut to_ids: *const dc_array_t, + mut ret_chat_id: *mut uint32_t, + mut ret_chat_id_blocked: *mut libc::c_int, +) { + let mut current_block: u64; + /* if we're here, no grpid was found, check there is an existing ad-hoc + group matching the to-list or if we can create one */ + 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: libc::c_int = 0i32; + let mut i: libc::c_int = 0i32; + 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; + let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; + 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; + /* build member list from the given ids */ + if !(dc_array_get_cnt(to_ids) == 0i32 as libc::c_ulong + || 0 != dc_mimeparser_is_mailinglist_message(mime_parser)) + { + /* too few contacts or a mailinglist */ + member_ids = dc_array_duplicate(to_ids); + if 0 == dc_array_search_id(member_ids, from_id as uint32_t, 0 as *mut size_t) { + dc_array_add_id(member_ids, from_id as uint32_t); + } + if 0 == dc_array_search_id(member_ids, 1i32 as uint32_t, 0 as *mut size_t) { + dc_array_add_id(member_ids, 1i32 as uint32_t); + } + if !(dc_array_get_cnt(member_ids) < 3i32 as libc::c_ulong) { + /* too few contacts given */ + chat_ids = search_chat_ids_by_contact_ids(context, member_ids); + if dc_array_get_cnt(chat_ids) > 0i32 as libc::c_ulong { + chat_ids_str = + dc_array_get_string(chat_ids, b",\x00" as *const u8 as *const libc::c_char); + q3 = + 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); + if sqlite3_step(stmt) == 100i32 { + chat_id = sqlite3_column_int(stmt, 0i32) as uint32_t; + chat_id_blocked = sqlite3_column_int(stmt, 1i32); + /* success, chat found */ + current_block = 11334989263469503965; + } else { + current_block = 11194104282611034094; + } + } else { + current_block = 11194104282611034094; + } + match current_block { + 11334989263469503965 => {} + _ => { + if !(0 == allow_creation) { + /* we do not check if the message is a reply to another group, this may result in + chats with unclear member list. instead we create a new group in the following lines ... */ + /* create a new ad-hoc group + - there is no need to check if this group exists; otherwise we would have catched it above */ + grpid = create_adhoc_grp_id(context, member_ids); + if !grpid.is_null() { + if !(*mime_parser).subject.is_null() + && 0 != *(*mime_parser).subject.offset(0isize) as libc::c_int + { + grpname = dc_strdup((*mime_parser).subject) + } else { + grpname = dc_stock_str_repl_int( + context, + 4i32, + dc_array_get_cnt(member_ids) as libc::c_int, + ) + } + chat_id = + create_group_record(context, grpid, grpname, create_blocked, 0i32); + chat_id_blocked = create_blocked; + i = 0i32; + while (i as libc::c_ulong) < dc_array_get_cnt(member_ids) { + dc_add_to_chat_contacts_table( + context, + chat_id, + dc_array_get_id(member_ids, i as size_t), + ); + i += 1 + } + (*context).cb.expect("non-null function pointer")( + context, + 2020i32, + chat_id as uintptr_t, + 0i32 as uintptr_t, + ); + } + } + } + } + } + } + dc_array_unref(member_ids); + dc_array_unref(chat_ids); + free(chat_ids_str as *mut libc::c_void); + free(grpid as *mut libc::c_void); + free(grpname as *mut libc::c_void); + sqlite3_finalize(stmt); + sqlite3_free(q3 as *mut libc::c_void); + if !ret_chat_id.is_null() { + *ret_chat_id = chat_id + } + if !ret_chat_id_blocked.is_null() { + *ret_chat_id_blocked = chat_id_blocked + }; +} +unsafe extern "C" fn create_group_record( + mut context: *mut 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; + stmt = dc_sqlite3_prepare( + (*context).sql, + b"INSERT INTO chats (type, name, grpid, blocked) VALUES(?, ?, ?, ?);\x00" as *const u8 + as *const libc::c_char, + ); + sqlite3_bind_int( + stmt, + 1i32, + if 0 != create_verified { 130i32 } else { 120i32 }, + ); + sqlite3_bind_text(stmt, 2i32, grpname, -1i32, None); + sqlite3_bind_text(stmt, 3i32, grpid, -1i32, None); + sqlite3_bind_int(stmt, 4i32, create_blocked); + if !(sqlite3_step(stmt) != 101i32) { + chat_id = dc_sqlite3_get_rowid( + (*context).sql, + b"chats\x00" as *const u8 as *const libc::c_char, + b"grpid\x00" as *const u8 as *const libc::c_char, + grpid, + ) + } + sqlite3_finalize(stmt); + return chat_id; +} +unsafe extern "C" fn create_adhoc_grp_id( + mut context: *mut dc_context_t, + mut member_ids: *mut dc_array_t, +) -> *mut libc::c_char { + /* algorithm: + - sort normalized, lowercased, e-mail addresses alphabetically + - put all e-mail addresses into a single string, separate the addresss by a single comma + - 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_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 ret: *mut libc::c_char = 0 as *mut libc::c_char; + let mut member_cs: dc_strbuilder_t = _dc_strbuilder { + buf: 0 as *mut libc::c_char, + allocated: 0, + free: 0, + eos: 0 as *mut libc::c_char, + }; + dc_strbuilder_init(&mut member_cs, 0i32); + q3 = sqlite3_mprintf( + b"SELECT addr FROM contacts WHERE id IN(%s) AND id!=1\x00" as *const u8 + as *const libc::c_char, + member_ids_str, + ); + stmt = dc_sqlite3_prepare((*context).sql, q3); + addr = dc_sqlite3_get_config( + (*context).sql, + b"configured_addr\x00" as *const u8 as *const libc::c_char, + b"no-self\x00" as *const u8 as *const libc::c_char, + ); + dc_strlower_in_place(addr); + dc_array_add_ptr(member_addrs, addr as *mut libc::c_void); + while sqlite3_step(stmt) == 100i32 { + addr = dc_strdup(sqlite3_column_text(stmt, 0i32) as *const libc::c_char); + dc_strlower_in_place(addr); + dc_array_add_ptr(member_addrs, addr as *mut libc::c_void); + } + dc_array_sort_strings(member_addrs); + iCnt = dc_array_get_cnt(member_addrs) as libc::c_int; + i = 0i32; + while i < iCnt { + if 0 != i { + dc_strbuilder_cat(&mut member_cs, b",\x00" as *const u8 as *const libc::c_char); + } + dc_strbuilder_cat( + &mut member_cs, + dc_array_get_ptr(member_addrs, i as size_t) as *const libc::c_char, + ); + i += 1 + } + /* make sha-256 from the string */ + let mut binary_hash: *mut rpgp_cvec = + rpgp_hash_sha256(member_cs.buf as *const uint8_t, strlen(member_cs.buf)); + if !binary_hash.is_null() { + ret = calloc(1i32 as libc::c_ulong, 256i32 as libc::c_ulong) as *mut libc::c_char; + if !ret.is_null() { + i = 0i32; + while i < 8i32 { + sprintf( + &mut *ret.offset((i * 2i32) as isize) as *mut libc::c_char, + b"%02x\x00" as *const u8 as *const libc::c_char, + *rpgp_cvec_data(binary_hash).offset(i as isize) as libc::c_int, + ); + i += 1 + } + rpgp_cvec_drop(binary_hash); + } + } + dc_array_free_ptr(member_addrs); + dc_array_unref(member_addrs); + free(member_ids_str as *mut libc::c_void); + sqlite3_finalize(stmt); + sqlite3_free(q3 as *mut libc::c_void); + free(member_cs.buf as *mut libc::c_void); + return ret; +} +unsafe extern "C" fn search_chat_ids_by_contact_ids( + mut context: *mut 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_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 + } + if !(dc_array_get_cnt(contact_ids) == 0i32 as libc::c_ulong) { + 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: uint32_t = 0i32 as uint32_t; + let mut matches: uint32_t = 0i32 as uint32_t; + let mut mismatches: uint32_t = 0i32 as uint32_t; + while sqlite3_step(stmt) == 100i32 { + 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 as libc::c_ulong == 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 = 0i32 as uint32_t; + mismatches = 0i32 as uint32_t + } + 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 as libc::c_ulong == dc_array_get_cnt(contact_ids) + && mismatches == 0i32 as libc::c_uint + { + 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); + sqlite3_free(q3 as *mut libc::c_void); + return chat_ids; +} +unsafe extern "C" fn check_verified_properties( + mut context: *mut dc_context_t, + mut mimeparser: *mut dc_mimeparser_t, + mut from_id: uint32_t, + mut to_ids: *const dc_array_t, + mut failure_reason: *mut *mut libc::c_char, +) -> libc::c_int { + let mut current_block: u64; + let mut everythings_okay: libc::c_int = 0i32; + let mut contact: *mut dc_contact_t = dc_contact_new(context); + let mut peerstate: *mut dc_apeerstate_t = dc_apeerstate_new(context); + 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) { + *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, + ); + dc_log_warning(context, 0i32, *failure_reason); + } else if 0 == (*(*mimeparser).e2ee_helper).encrypted { + *failure_reason = dc_mprintf( + b"%s. See \"Info\" for details.\x00" as *const u8 as *const libc::c_char, + b"This message is not encrypted.\x00" as *const u8 as *const libc::c_char, + ); + dc_log_warning(context, 0i32, *failure_reason); + } else { + // ensure, the contact is verified + // and the message is signed with a verified key of the sender. + // 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 + { + *failure_reason = dc_mprintf( + b"%s. See \"Info\" for details.\x00" as *const u8 as *const libc::c_char, + b"The sender of this message is not verified.\x00" as *const u8 + as *const libc::c_char, + ); + dc_log_warning(context, 0i32, *failure_reason); + current_block = 14837890932895028253; + } else if 0 + == dc_apeerstate_has_verified_key( + peerstate, + (*(*mimeparser).e2ee_helper).signatures, + ) + { + *failure_reason = dc_mprintf( + b"%s. See \"Info\" for details.\x00" as *const u8 as *const libc::c_char, + b"The message was sent with non-verified encryption.\x00" as *const u8 + as *const libc::c_char, + ); + dc_log_warning(context, 0i32, *failure_reason); + current_block = 14837890932895028253; + } else { + current_block = 15904375183555213903; + } + } else { + current_block = 15904375183555213903; + } + match current_block { + 14837890932895028253 => {} + _ => { + to_ids_str = + dc_array_get_string(to_ids, b",\x00" as *const u8 as *const libc::c_char); + q3 = + 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); + loop { + if !(sqlite3_step(stmt) == 100i32) { + current_block = 2604890879466389055; + break; + } + let mut to_addr: *const libc::c_char = + sqlite3_column_text(stmt, 0i32) as *const libc::c_char; + let mut is_verified: libc::c_int = sqlite3_column_int(stmt, 1i32); + if !dc_hash_find( + (*(*mimeparser).e2ee_helper).gossipped_addr, + to_addr as *const libc::c_void, + strlen(to_addr) as libc::c_int, + ) + .is_null() + && 0 != dc_apeerstate_load_by_addr(peerstate, (*context).sql, to_addr) + { + if 0 == is_verified + || strcmp( + (*peerstate).verified_key_fingerprint, + (*peerstate).public_key_fingerprint, + ) != 0i32 + && strcmp( + (*peerstate).verified_key_fingerprint, + (*peerstate).gossip_key_fingerprint, + ) != 0i32 + { + dc_log_info( + context, + 0i32, + b"%s has verfied %s.\x00" as *const u8 as *const libc::c_char, + (*contact).addr, + to_addr, + ); + dc_apeerstate_set_verified( + peerstate, + 0i32, + (*peerstate).gossip_key_fingerprint, + 2i32, + ); + dc_apeerstate_save_to_db(peerstate, (*context).sql, 0i32); + is_verified = 1i32 + } + } + if !(0 == is_verified) { + continue; + } + let mut err: *mut libc::c_char = dc_mprintf( + b"%s is not a member of this verified group.\x00" as *const u8 + as *const libc::c_char, + to_addr, + ); + *failure_reason = dc_mprintf( + b"%s. See \"Info\" for details.\x00" as *const u8 as *const libc::c_char, + err, + ); + dc_log_warning(context, 0i32, *failure_reason); + free(err as *mut libc::c_void); + current_block = 14837890932895028253; + break; + } + match current_block { + 14837890932895028253 => {} + _ => everythings_okay = 1i32, + } + } + } + } + sqlite3_finalize(stmt); + dc_contact_unref(contact); + dc_apeerstate_unref(peerstate); + free(to_ids_str as *mut libc::c_void); + sqlite3_free(q3 as *mut libc::c_void); + return everythings_okay; +} +unsafe extern "C" fn set_better_msg( + mut mime_parser: *mut dc_mimeparser_t, + mut better_msg: *mut *mut libc::c_char, +) { + if !(*better_msg).is_null() && carray_count((*mime_parser).parts) > 0i32 as libc::c_uint { + let mut part: *mut dc_mimepart_t = + carray_get((*mime_parser).parts, 0i32 as libc::c_uint) as *mut dc_mimepart_t; + if (*part).type_0 == 10i32 { + free((*part).msg as *mut libc::c_void); + (*part).msg = *better_msg; + *better_msg = 0 as *mut libc::c_char + } + }; +} +unsafe extern "C" fn dc_is_reply_to_known_message( + mut context: *mut 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; + optional_field = dc_mimeparser_lookup_optional_field( + mime_parser, + b"Chat-Predecessor\x00" as *const u8 as *const libc::c_char, + ); + if !optional_field.is_null() { + if 0 != is_known_rfc724_mid(context, (*optional_field).fld_value) { + return 1i32; + } + } + let mut field: *mut mailimf_field = 0 as *mut mailimf_field; + field = dc_mimeparser_lookup_field( + mime_parser, + b"In-Reply-To\x00" as *const u8 as *const libc::c_char, + ); + if !field.is_null() && (*field).fld_type == MAILIMF_FIELD_IN_REPLY_TO as libc::c_int { + let mut fld_in_reply_to: *mut mailimf_in_reply_to = (*field).fld_data.fld_in_reply_to; + if !fld_in_reply_to.is_null() { + if 0 != is_known_rfc724_mid_in_list( + context, + (*(*field).fld_data.fld_in_reply_to).mid_list, + ) { + return 1i32; + } + } + } + field = dc_mimeparser_lookup_field( + mime_parser, + b"References\x00" as *const u8 as *const libc::c_char, + ); + if !field.is_null() && (*field).fld_type == MAILIMF_FIELD_REFERENCES as libc::c_int { + let mut fld_references: *mut mailimf_references = (*field).fld_data.fld_references; + if !fld_references.is_null() { + if 0 != is_known_rfc724_mid_in_list( + context, + (*(*field).fld_data.fld_references).mid_list, + ) { + return 1i32; + } + } + } + return 0i32; +} +unsafe extern "C" fn is_known_rfc724_mid_in_list( + mut context: *mut 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; + cur = (*mid_list).first; + while !cur.is_null() { + if 0 != is_known_rfc724_mid( + context, + (if !cur.is_null() { + (*cur).data + } else { + 0 as *mut libc::c_void + }) as *const libc::c_char, + ) { + return 1i32; + } + cur = if !cur.is_null() { + (*cur).next + } else { + 0 as *mut clistcell_s + } + } + } + return 0i32; +} +/* ****************************************************************************** + * Check if a message is a reply to a known message (messenger or non-messenger) + ******************************************************************************/ +unsafe extern "C" fn is_known_rfc724_mid( + mut context: *mut 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, + 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); + if sqlite3_step(stmt) == 100i32 { + is_known = 1i32 + } + sqlite3_finalize(stmt); + } + return is_known; +} +unsafe extern "C" fn dc_is_reply_to_messenger_message( + mut context: *mut 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. + This is similar to is_reply_to_known_message() but + - 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; + field = dc_mimeparser_lookup_field( + mime_parser, + b"In-Reply-To\x00" as *const u8 as *const libc::c_char, + ); + if !field.is_null() && (*field).fld_type == MAILIMF_FIELD_IN_REPLY_TO as libc::c_int { + let mut fld_in_reply_to: *mut mailimf_in_reply_to = (*field).fld_data.fld_in_reply_to; + if !fld_in_reply_to.is_null() { + if 0 != is_msgrmsg_rfc724_mid_in_list( + context, + (*(*field).fld_data.fld_in_reply_to).mid_list, + ) { + return 1i32; + } + } + } + field = dc_mimeparser_lookup_field( + mime_parser, + b"References\x00" as *const u8 as *const libc::c_char, + ); + if !field.is_null() && (*field).fld_type == MAILIMF_FIELD_REFERENCES as libc::c_int { + let mut fld_references: *mut mailimf_references = (*field).fld_data.fld_references; + if !fld_references.is_null() { + if 0 != is_msgrmsg_rfc724_mid_in_list( + context, + (*(*field).fld_data.fld_references).mid_list, + ) { + return 1i32; + } + } + } + return 0i32; +} +unsafe extern "C" fn is_msgrmsg_rfc724_mid_in_list( + mut context: *mut dc_context_t, + mut mid_list: *const clist, +) -> libc::c_int { + if !mid_list.is_null() { + let mut cur: *mut clistiter = (*mid_list).first; + while !cur.is_null() { + if 0 != is_msgrmsg_rfc724_mid( + context, + (if !cur.is_null() { + (*cur).data + } else { + 0 as *mut libc::c_void + }) as *const libc::c_char, + ) { + return 1i32; + } + cur = if !cur.is_null() { + (*cur).next + } else { + 0 as *mut clistcell_s + } + } + } + return 0i32; +} +/* ****************************************************************************** + * Check if a message is a reply to any messenger message + ******************************************************************************/ +unsafe extern "C" fn is_msgrmsg_rfc724_mid( + mut context: *mut 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, + b"SELECT id FROM msgs WHERE rfc724_mid=? AND msgrmsg!=0 AND chat_id>9;\x00" + as *const u8 as *const libc::c_char, + ); + sqlite3_bind_text(stmt, 1i32, rfc724_mid, -1i32, None); + if sqlite3_step(stmt) == 100i32 { + is_msgrmsg = 1i32 + } + sqlite3_finalize(stmt); + } + return is_msgrmsg; +} +unsafe extern "C" fn dc_add_or_lookup_contacts_by_address_list( + mut context: *mut 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() + { + return; + } + let mut cur: *mut clistiter = (*(*adr_list).ad_list).first; + while !cur.is_null() { + let mut adr: *mut mailimf_address = (if !cur.is_null() { + (*cur).data + } else { + 0 as *mut libc::c_void + }) as *mut mailimf_address; + if !adr.is_null() { + if (*adr).ad_type == MAILIMF_ADDRESS_MAILBOX as libc::c_int { + let mut mb: *mut mailimf_mailbox = (*adr).ad_data.ad_mailbox; + if !mb.is_null() { + add_or_lookup_contact_by_addr( + context, + (*mb).mb_display_name, + (*mb).mb_addr_spec, + origin, + ids, + check_self, + ); + } + } 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() { + dc_add_or_lookup_contacts_by_mailbox_list( + context, + (*group).grp_mb_list, + origin, + ids, + check_self, + ); + } + } + } + cur = if !cur.is_null() { + (*cur).next + } else { + 0 as *mut clistcell_s + } + } +} +unsafe extern "C" fn dc_add_or_lookup_contacts_by_mailbox_list( + mut context: *mut 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() { + return; + } + let mut cur: *mut clistiter = (*(*mb_list).mb_list).first; + while !cur.is_null() { + let mut mb: *mut mailimf_mailbox = (if !cur.is_null() { + (*cur).data + } else { + 0 as *mut libc::c_void + }) as *mut mailimf_mailbox; + if !mb.is_null() { + add_or_lookup_contact_by_addr( + context, + (*mb).mb_display_name, + (*mb).mb_addr_spec, + origin, + ids, + check_self, + ); + } + cur = if !cur.is_null() { + (*cur).next + } else { + 0 as *mut clistcell_s + } + } +} +/* ****************************************************************************** + * Add contacts to database on receiving messages + ******************************************************************************/ +unsafe extern "C" fn add_or_lookup_contact_by_addr( + mut context: *mut dc_context_t, + mut display_name_enc: *const libc::c_char, + mut addr_spec: *const libc::c_char, + mut origin: libc::c_int, + mut ids: *mut dc_array_t, + mut check_self: *mut libc::c_int, +) { + /* is addr_spec equal to SELF? */ + let mut dummy: libc::c_int = 0i32; + if check_self.is_null() { + check_self = &mut dummy + } + if context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint || addr_spec.is_null() + { + return; + } + *check_self = 0i32; + let mut self_addr: *mut libc::c_char = 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 dc_addr_cmp(self_addr, addr_spec) == 0i32 { + *check_self = 1i32 + } + free(self_addr as *mut libc::c_void); + if 0 != *check_self { + return; + } + /* add addr_spec if missing, update otherwise */ + let mut display_name_dec: *mut libc::c_char = 0 as *mut libc::c_char; + if !display_name_enc.is_null() { + display_name_dec = dc_decode_header_words(display_name_enc); + dc_normalize_name(display_name_dec); + } + /*can be NULL*/ + let mut row_id: uint32_t = dc_add_or_lookup_contact( + context, + display_name_dec, + addr_spec, + origin, + 0 as *mut libc::c_int, + ); + free(display_name_dec as *mut libc::c_void); + if 0 != row_id { + if 0 == dc_array_search_id(ids, row_id, 0 as *mut size_t) { + dc_array_add_id(ids, row_id); + } + }; +} diff --git a/src/dc_saxparser.rs b/src/dc_saxparser.rs new file mode 100644 index 000000000..0b567ac94 --- /dev/null +++ b/src/dc_saxparser.rs @@ -0,0 +1,1245 @@ +use libc; + +use crate::dc_tools::*; + +extern "C" { + #[no_mangle] + fn malloc(_: libc::c_ulong) -> *mut libc::c_void; + #[no_mangle] + fn free(_: *mut libc::c_void); + #[no_mangle] + fn realloc(_: *mut libc::c_void, _: libc::c_ulong) -> *mut libc::c_void; + #[no_mangle] + fn strtol(_: *const libc::c_char, _: *mut *mut libc::c_char, _: libc::c_int) -> libc::c_long; + #[no_mangle] + fn memmove(_: *mut libc::c_void, _: *const libc::c_void, _: libc::c_ulong) + -> *mut libc::c_void; + #[no_mangle] + fn strchr(_: *const libc::c_char, _: libc::c_int) -> *mut libc::c_char; + #[no_mangle] + fn strcmp(_: *const libc::c_char, _: *const libc::c_char) -> libc::c_int; + #[no_mangle] + fn strcpy(_: *mut libc::c_char, _: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn strcspn(_: *const libc::c_char, _: *const libc::c_char) -> libc::c_ulong; + #[no_mangle] + fn strlen(_: *const libc::c_char) -> libc::c_ulong; + #[no_mangle] + fn strncmp(_: *const libc::c_char, _: *const libc::c_char, _: libc::c_ulong) -> libc::c_int; + #[no_mangle] + fn strncpy(_: *mut libc::c_char, _: *const libc::c_char, _: libc::c_ulong) + -> *mut libc::c_char; + #[no_mangle] + fn strspn(_: *const libc::c_char, _: *const libc::c_char) -> libc::c_ulong; + #[no_mangle] + fn strstr(_: *const libc::c_char, _: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + static mut _DefaultRuneLocale: _RuneLocale; + #[no_mangle] + fn __maskrune(_: __darwin_ct_rune_t, _: libc::c_ulong) -> libc::c_int; + /* string tools */ + #[no_mangle] + fn dc_strdup(_: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn dc_strlower_in_place(_: *mut libc::c_char); +} +pub type __uint32_t = libc::c_uint; +pub type __darwin_ct_rune_t = libc::c_int; +pub type __darwin_size_t = libc::c_ulong; +pub type __darwin_wchar_t = libc::c_int; +pub type __darwin_rune_t = __darwin_wchar_t; +pub type size_t = __darwin_size_t; +#[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, + _: __darwin_size_t, + _: *mut *const libc::c_char, + ) -> __darwin_rune_t, + >, + pub __sputrune: Option< + unsafe extern "C" fn( + _: __darwin_rune_t, + _: *mut libc::c_char, + _: __darwin_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, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_saxparser { + pub starttag_cb: dc_saxparser_starttag_cb_t, + pub endtag_cb: dc_saxparser_endtag_cb_t, + pub text_cb: dc_saxparser_text_cb_t, + pub userdata: *mut libc::c_void, +} +/* len is only informational, text is already null-terminated */ +pub type dc_saxparser_text_cb_t = Option< + unsafe extern "C" fn(_: *mut libc::c_void, _: *const libc::c_char, _: libc::c_int) -> (), +>; +pub type dc_saxparser_endtag_cb_t = + Option ()>; +pub type dc_saxparser_starttag_cb_t = Option< + unsafe extern "C" fn( + _: *mut libc::c_void, + _: *const libc::c_char, + _: *mut *mut libc::c_char, + ) -> (), +>; +pub type dc_saxparser_t = _dc_saxparser; +#[inline] +unsafe extern "C" fn isascii(mut _c: libc::c_int) -> libc::c_int { + return (_c & !0x7fi32 == 0i32) as libc::c_int; +} +#[inline] +unsafe extern "C" fn __istype(mut _c: __darwin_ct_rune_t, mut _f: libc::c_ulong) -> libc::c_int { + return if 0 != isascii(_c) { + (0 != _DefaultRuneLocale.__runetype[_c as usize] as libc::c_ulong & _f) as libc::c_int + } else { + (0 != __maskrune(_c, _f)) as libc::c_int + }; +} + +#[no_mangle] +pub unsafe extern "C" fn dc_saxparser_init( + mut saxparser: *mut dc_saxparser_t, + mut userdata: *mut libc::c_void, +) { + (*saxparser).userdata = userdata; + (*saxparser).starttag_cb = Some(def_starttag_cb); + (*saxparser).endtag_cb = Some(def_endtag_cb); + (*saxparser).text_cb = Some(def_text_cb); +} +unsafe extern "C" fn def_text_cb( + mut userdata: *mut libc::c_void, + mut text: *const libc::c_char, + mut len: libc::c_int, +) { +} +unsafe extern "C" fn def_endtag_cb(mut userdata: *mut libc::c_void, mut tag: *const libc::c_char) {} +/* ****************************************************************************** + * Tools + ******************************************************************************/ +unsafe extern "C" fn def_starttag_cb( + mut userdata: *mut libc::c_void, + mut tag: *const libc::c_char, + mut attr: *mut *mut libc::c_char, +) { +} +#[no_mangle] +pub unsafe extern "C" fn dc_saxparser_set_tag_handler( + mut saxparser: *mut dc_saxparser_t, + mut starttag_cb: dc_saxparser_starttag_cb_t, + mut endtag_cb: dc_saxparser_endtag_cb_t, +) { + if saxparser.is_null() { + return; + } + (*saxparser).starttag_cb = if starttag_cb.is_some() { + starttag_cb + } else { + Some(def_starttag_cb) + }; + (*saxparser).endtag_cb = if endtag_cb.is_some() { + endtag_cb + } else { + Some(def_endtag_cb) + }; +} +#[no_mangle] +pub unsafe extern "C" fn dc_saxparser_set_text_handler( + mut saxparser: *mut dc_saxparser_t, + mut text_cb: dc_saxparser_text_cb_t, +) { + if saxparser.is_null() { + return; + } + (*saxparser).text_cb = if text_cb.is_some() { + text_cb + } else { + Some(def_text_cb) + }; +} +#[no_mangle] +pub unsafe extern "C" 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; + /* 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]; + /* free the value at attr[i*2+1]? */ + let mut free_attr: [libc::c_int; 100] = [0; 100]; + attr[0usize] = 0 as *mut libc::c_char; + if saxparser.is_null() { + return; + } + buf_start = dc_strdup(buf_start__); + last_text_start = buf_start; + p = buf_start; + loop { + if !(0 != *p) { + current_block = 13425230902034816933; + break; + } + if *p as libc::c_int == '<' as i32 { + call_text_cb( + saxparser, + last_text_start, + p.wrapping_offset_from(last_text_start) as libc::c_long as size_t, + '&' as i32 as libc::c_char, + ); + p = p.offset(1isize); + if strncmp( + p, + b"!--\x00" as *const u8 as *const libc::c_char, + 3i32 as libc::c_ulong, + ) == 0i32 + { + p = strstr(p, b"-->\x00" as *const u8 as *const libc::c_char); + if p.is_null() { + current_block = 7627180618761592946; + break; + } + p = p.offset(3isize) + } else if strncmp( + p, + b"![CDATA[\x00" as *const u8 as *const libc::c_char, + 8i32 as libc::c_ulong, + ) == 0i32 + { + /* process text + **************************************************************/ + let mut text_beg: *mut libc::c_char = p.offset(8isize); + p = strstr(p, b"]]>\x00" as *const u8 as *const libc::c_char); + if !p.is_null() { + call_text_cb( + saxparser, + text_beg, + p.wrapping_offset_from(text_beg) as libc::c_long as size_t, + 'c' as i32 as libc::c_char, + ); + p = p.offset(3isize) + } else { + call_text_cb( + saxparser, + text_beg, + strlen(text_beg), + 'c' as i32 as libc::c_char, + ); + current_block = 7627180618761592946; + break; + } + } else if strncmp( + p, + b"!DOCTYPE\x00" as *const u8 as *const libc::c_char, + 8i32 as libc::c_ulong, + ) == 0i32 + { + while 0 != *p as libc::c_int + && *p as libc::c_int != '[' as i32 + && *p as libc::c_int != '>' as i32 + { + p = p.offset(1isize) + } + if *p as libc::c_int == 0i32 { + /* unclosed doctype */ + current_block = 7627180618761592946; + break; + } else if *p as libc::c_int == '[' as i32 { + p = strstr(p, b"]>\x00" as *const u8 as *const libc::c_char); + if p.is_null() { + /* unclosed inline doctype */ + current_block = 7627180618761592946; + break; + } else { + p = p.offset(2isize) + } + } else { + p = p.offset(1isize) + } + } else if *p as libc::c_int == '?' as i32 { + p = strstr(p, b"?>\x00" as *const u8 as *const libc::c_char); + if p.is_null() { + /* unclosed processing instruction */ + current_block = 7627180618761592946; + break; + } else { + p = p.offset(2isize) + } + } else { + p = p + .offset(strspn(p, b"\t\r\n \x00" as *const u8 as *const libc::c_char) as isize); + if *p as libc::c_int == '/' as i32 { + p = p.offset(1isize); + p = p.offset( + strspn(p, b"\t\r\n \x00" as *const u8 as *const libc::c_char) as isize, + ); + let mut beg_tag_name: *mut libc::c_char = p; + p = p.offset( + strcspn(p, b"\t\r\n />\x00" as *const u8 as *const libc::c_char) as isize, + ); + if p != beg_tag_name { + bak = *p; + *p = '\u{0}' as i32 as libc::c_char; + dc_strlower_in_place(beg_tag_name); + (*saxparser).endtag_cb.expect("non-null function pointer")( + (*saxparser).userdata, + beg_tag_name, + ); + *p = bak + } + } else { + do_free_attr(attr.as_mut_ptr(), free_attr.as_mut_ptr()); + let mut beg_tag_name_0: *mut libc::c_char = p; + p = p.offset( + strcspn(p, b"\t\r\n />\x00" as *const u8 as *const libc::c_char) as isize, + ); + 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) { + p = p.offset(1isize) + } + while 0 != *p as libc::c_int + && *p as libc::c_int != '/' as i32 + && *p as libc::c_int != '>' as i32 + { + 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; + if '=' as i32 == *beg_attr_name as libc::c_int { + p = p.offset(1isize) + } else { + p = p.offset(strcspn( + p, + b"\t\r\n =/>\x00" as *const u8 as *const libc::c_char, + ) as isize); + if p != beg_attr_name { + let mut after_attr_name: *mut libc::c_char = p; + p = p.offset(strspn( + p, + b"\t\r\n \x00" as *const u8 as *const libc::c_char, + ) as isize); + if *p as libc::c_int == '=' as i32 { + p = p.offset(strspn( + p, + b"\t\r\n =\x00" as *const u8 as *const libc::c_char, + ) + as isize); + let mut quote: libc::c_char = *p; + if quote as libc::c_int == '\"' as i32 + || quote as libc::c_int == '\'' as i32 + { + p = p.offset(1isize); + beg_attr_value = p; + while 0 != *p as libc::c_int + && *p as libc::c_int != quote as libc::c_int + { + p = p.offset(1isize) + } + if 0 != *p { + *p = '\u{0}' as i32 as libc::c_char; + p = p.offset(1isize) + } + beg_attr_value_new = xml_decode( + beg_attr_value, + ' ' as i32 as libc::c_char, + ) + } else { + beg_attr_value = p; + p = p.offset(strcspn( + p, + b"\t\r\n />\x00" as *const u8 + as *const libc::c_char, + ) + as isize); + bak = *p; + *p = '\u{0}' as i32 as libc::c_char; + let mut temp: *mut libc::c_char = + dc_strdup(beg_attr_value); + beg_attr_value_new = + xml_decode(temp, ' ' as i32 as libc::c_char); + if beg_attr_value_new != temp { + free(temp as *mut libc::c_void); + } + *p = bak + } + } else { + beg_attr_value_new = dc_strdup(0 as *const libc::c_char) + } + if attr_index < 100i32 { + let mut beg_attr_name_new: *mut libc::c_char = + beg_attr_name; + let mut free_bits: libc::c_int = + if beg_attr_value_new != beg_attr_value { + 0x2i32 + } else { + 0i32 + }; + if after_attr_name == p { + bak = *after_attr_name; + *after_attr_name = '\u{0}' as i32 as libc::c_char; + beg_attr_name_new = dc_strdup(beg_attr_name); + *after_attr_name = bak; + free_bits |= 0x1i32 + } else { + *after_attr_name = '\u{0}' as i32 as libc::c_char + } + dc_strlower_in_place(beg_attr_name_new); + attr[attr_index as usize] = beg_attr_name_new; + attr[(attr_index + 1i32) as usize] = beg_attr_value_new; + attr[(attr_index + 2i32) as usize] = 0 as *mut libc::c_char; + free_attr[(attr_index >> 1i32) as usize] = free_bits; + attr_index += 2i32 + } + } + while 0 != isspace(*p as libc::c_int) { + p = p.offset(1isize) + } + } + } + let mut bak_0: libc::c_char = *after_tag_name; + *after_tag_name = 0i32 as libc::c_char; + dc_strlower_in_place(beg_tag_name_0); + (*saxparser).starttag_cb.expect("non-null function pointer")( + (*saxparser).userdata, + beg_tag_name_0, + attr.as_mut_ptr(), + ); + *after_tag_name = bak_0; + p = p.offset( + strspn(p, b"\t\r\n \x00" as *const u8 as *const libc::c_char) as isize, + ); + if *p as libc::c_int == '/' as i32 { + p = p.offset(1isize); + *after_tag_name = 0i32 as libc::c_char; + (*saxparser).endtag_cb.expect("non-null function pointer")( + (*saxparser).userdata, + beg_tag_name_0, + ); + } + } + } + p = strchr(p, '>' as i32); + if p.is_null() { + /* unclosed start-tag or end-tag */ + current_block = 7627180618761592946; + break; + } else { + p = p.offset(1isize) + } + } + last_text_start = p + } else { + p = p.offset(1isize) + } + } + match current_block { + 13425230902034816933 => { + call_text_cb( + saxparser, + last_text_start, + p.wrapping_offset_from(last_text_start) as libc::c_long as size_t, + '&' as i32 as libc::c_char, + ); + } + _ => {} + } + do_free_attr(attr.as_mut_ptr(), free_attr.as_mut_ptr()); + free(buf_start as *mut libc::c_void); +} +unsafe extern "C" 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) */ + let mut i: libc::c_int = 0i32; + while !(*attr.offset(i as isize)).is_null() { + if 0 != *free_attr.offset((i >> 1i32) as isize) & 0x1i32 + && !(*attr.offset(i as isize)).is_null() + { + free(*attr.offset(i as isize) as *mut libc::c_void); + } + if 0 != *free_attr.offset((i >> 1i32) as isize) & 0x2i32 + && !(*attr.offset((i + 1i32) as isize)).is_null() + { + free(*attr.offset((i + 1i32) as isize) as *mut libc::c_void); + } + i += 2i32 + } + let ref mut fresh0 = *attr.offset(0isize); + *fresh0 = 0 as *mut libc::c_char; +} +unsafe extern "C" fn call_text_cb( + mut saxparser: *mut dc_saxparser_t, + mut text: *mut libc::c_char, + mut len: size_t, + mut type_0: libc::c_char, +) { + 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; + *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")( + (*saxparser).userdata, + text_new, + len as libc::c_int, + ); + if text != text_new { + free(text_new as *mut libc::c_void); + } + *text.offset(len as isize) = bak + }; +} +/* Convert entities as ä to UTF-8 characters. + +- The first strings MUST NOT start with `&` and MUST end with `;`. +- take care not to miss a comma between the strings. +- It's also possible to specify the destination as a character reference as `"` (they are converted in a second pass without a table). */ +/* basic XML/HTML */ +/* advanced HTML */ +/* MUST be last */ +/* Recursively decodes entity and character references and normalizes new lines. +set "type" to ... +'&' for general entity decoding, +'%' for parameter entity decoding (currently not needed), +'c' for cdata sections, +' ' for attribute normalization, or +'*' for non-cdata attribute normalization (currently not needed). +Returns s, or if the decoded string is longer than s, returns a malloced string +that must be freed. +Function based upon ezxml_decode() from the "ezxml" parser which is +Copyright 2004-2006 Aaron Voisine */ +unsafe extern "C" fn xml_decode( + mut s: *mut libc::c_char, + mut type_0: libc::c_char, +) -> *mut libc::c_char { + 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: libc::c_long = 0i32 as libc::c_long; + let mut c: libc::c_long = 0i32 as libc::c_long; + let mut d: libc::c_long = 0i32 as libc::c_long; + let mut l: libc::c_long = 0i32 as libc::c_long; + while 0 != *s { + while *s as libc::c_int == '\r' as i32 { + let fresh1 = s; + s = s.offset(1); + *fresh1 = '\n' as i32 as libc::c_char; + if *s as libc::c_int == '\n' as i32 { + memmove( + s as *mut libc::c_void, + s.offset(1isize) as *const libc::c_void, + strlen(s), + ); + } + } + s = s.offset(1isize) + } + s = r; + loop { + while 0 != *s as libc::c_int + && *s as libc::c_int != '&' as i32 + && 0 == isspace(*s as libc::c_int) + { + s = s.offset(1isize) + } + if 0 == *s { + break; + } + if type_0 as libc::c_int != 'c' as i32 + && 0 == strncmp( + s, + b"&#\x00" as *const u8 as *const libc::c_char, + 2i32 as libc::c_ulong, + ) + { + if *s.offset(2isize) as libc::c_int == 'x' as i32 { + c = strtol(s.offset(3isize), &mut e, 16i32) + } else { + c = strtol(s.offset(2isize), &mut e, 10i32) + } + if 0 == c || *e as libc::c_int != ';' as i32 { + s = s.offset(1isize) + } else { + /* not a character ref */ + if c < 0x80i32 as libc::c_long { + let fresh2 = s; + s = s.offset(1); + *fresh2 = c as libc::c_char + } else { + b = 0i32 as libc::c_long; + d = c; + while 0 != d { + b += 1; + d /= 2i32 as libc::c_long + } + b = (b - 2i32 as libc::c_long) / 5i32 as libc::c_long; + let fresh3 = s; + s = s.offset(1); + *fresh3 = ((0xffi32 << 7i32 as libc::c_long - b) as libc::c_long + | c >> 6i32 as libc::c_long * b) + as libc::c_char; + while 0 != b { + let fresh4 = s; + s = s.offset(1); + b -= 1; + *fresh4 = (0x80i32 as libc::c_long + | c >> 6i32 as libc::c_long * b & 0x3fi32 as libc::c_long) + as libc::c_char + } + } + memmove( + s as *mut libc::c_void, + strchr(s, ';' as i32).offset(1isize) as *const libc::c_void, + strlen(strchr(s, ';' as i32)), + ); + } + } else if *s as libc::c_int == '&' as i32 + && (type_0 as libc::c_int == '&' as i32 || type_0 as libc::c_int == ' ' as i32) + { + b = 0i32 as libc::c_long; + while !s_ent[b as usize].is_null() + && 0 != strncmp( + s.offset(1isize), + s_ent[b as usize], + strlen(s_ent[b as usize]), + ) + { + b += 2i32 as libc::c_long + } + let fresh5 = b; + b = b + 1; + if !s_ent[fresh5 as usize].is_null() { + c = strlen(s_ent[b as usize]) as libc::c_long; + e = strchr(s, ';' as i32); + if c - 1i32 as libc::c_long > e.wrapping_offset_from(s) as libc::c_long { + d = s.wrapping_offset_from(r) as libc::c_long; + l = ((d + c) as libc::c_ulong).wrapping_add(strlen(e)) as libc::c_long; + if r == original_buf as *mut libc::c_char { + let mut new_ret: *mut libc::c_char = + malloc(l as libc::c_ulong) as *mut libc::c_char; + if new_ret.is_null() { + return r; + } + strcpy(new_ret, r); + r = new_ret + } else { + let mut new_ret_0: *mut libc::c_char = + realloc(r as *mut libc::c_void, l as libc::c_ulong) + as *mut libc::c_char; + if new_ret_0.is_null() { + return r; + } + r = new_ret_0 + } + s = r.offset(d as isize); + e = strchr(s, ';' as i32) + } + memmove( + s.offset(c as isize) as *mut libc::c_void, + e.offset(1isize) as *const libc::c_void, + strlen(e), + ); + strncpy(s, s_ent[b as usize], c as libc::c_ulong); + } else { + s = s.offset(1isize) + } + } else if type_0 as libc::c_int == ' ' as i32 && 0 != isspace(*s as libc::c_int) { + let fresh6 = s; + s = s.offset(1); + *fresh6 = ' ' as i32 as libc::c_char + } else { + s = s.offset(1isize) + } + } + return r; +} +/* dc_saxparser_t parses XML and HTML files that may not be wellformed +and spits out all text and tags found. + +- Attributes are recognized with single, double or no quotes +- Whitespace ignored inside tags +- Self-closing tags are issued as open-tag plus close-tag +- CDATA is supoorted; DTA, comments, processing instruction are + skipped properly +- The parser does not care about hierarchy, if needed this can be + done by the user. +- Input and output strings must be UTF-8 encoded. +- Tag and attribute names are converted to lower case. +- Parsing does not stop on errors; instead errors are recovered. + +NB: SAX = Simple API for XML */ +/* ****************************************************************************** + * Decoding text + ******************************************************************************/ +static mut s_ent: [*const libc::c_char; 508] = [ + b"lt;\x00" as *const u8 as *const libc::c_char, + b"<\x00" as *const u8 as *const libc::c_char, + b"gt;\x00" as *const u8 as *const libc::c_char, + b">\x00" as *const u8 as *const libc::c_char, + b"quot;\x00" as *const u8 as *const libc::c_char, + b"\"\x00" as *const u8 as *const libc::c_char, + b"apos;\x00" as *const u8 as *const libc::c_char, + b"\'\x00" as *const u8 as *const libc::c_char, + b"amp;\x00" as *const u8 as *const libc::c_char, + b"&\x00" as *const u8 as *const libc::c_char, + b"nbsp;\x00" as *const u8 as *const libc::c_char, + b" \x00" as *const u8 as *const libc::c_char, + b"iexcl;\x00" as *const u8 as *const libc::c_char, + b"\xc2\xa1\x00" as *const u8 as *const libc::c_char, + b"cent;\x00" as *const u8 as *const libc::c_char, + b"\xc2\xa2\x00" as *const u8 as *const libc::c_char, + b"pound;\x00" as *const u8 as *const libc::c_char, + b"\xc2\xa3\x00" as *const u8 as *const libc::c_char, + b"curren;\x00" as *const u8 as *const libc::c_char, + b"\xc2\xa4\x00" as *const u8 as *const libc::c_char, + b"yen;\x00" as *const u8 as *const libc::c_char, + b"\xc2\xa5\x00" as *const u8 as *const libc::c_char, + b"brvbar;\x00" as *const u8 as *const libc::c_char, + b"\xc2\xa6\x00" as *const u8 as *const libc::c_char, + b"sect;\x00" as *const u8 as *const libc::c_char, + b"\xc2\xa7\x00" as *const u8 as *const libc::c_char, + b"uml;\x00" as *const u8 as *const libc::c_char, + b"\xc2\xa8\x00" as *const u8 as *const libc::c_char, + b"copy;\x00" as *const u8 as *const libc::c_char, + b"\xc2\xa9\x00" as *const u8 as *const libc::c_char, + b"ordf;\x00" as *const u8 as *const libc::c_char, + b"\xc2\xaa\x00" as *const u8 as *const libc::c_char, + b"laquo;\x00" as *const u8 as *const libc::c_char, + b"\xc2\xab\x00" as *const u8 as *const libc::c_char, + b"not;\x00" as *const u8 as *const libc::c_char, + b"\xc2\xac\x00" as *const u8 as *const libc::c_char, + b"shy;\x00" as *const u8 as *const libc::c_char, + b"-\x00" as *const u8 as *const libc::c_char, + b"reg;\x00" as *const u8 as *const libc::c_char, + b"\xc2\xae\x00" as *const u8 as *const libc::c_char, + b"macr;\x00" as *const u8 as *const libc::c_char, + b"\xc2\xaf\x00" as *const u8 as *const libc::c_char, + b"deg;\x00" as *const u8 as *const libc::c_char, + b"\xc2\xb0\x00" as *const u8 as *const libc::c_char, + b"plusmn;\x00" as *const u8 as *const libc::c_char, + b"\xc2\xb1\x00" as *const u8 as *const libc::c_char, + b"sup2;\x00" as *const u8 as *const libc::c_char, + b"\xc2\xb2\x00" as *const u8 as *const libc::c_char, + b"sup3;\x00" as *const u8 as *const libc::c_char, + b"\xc2\xb3\x00" as *const u8 as *const libc::c_char, + b"acute;\x00" as *const u8 as *const libc::c_char, + b"\xc2\xb4\x00" as *const u8 as *const libc::c_char, + b"micro;\x00" as *const u8 as *const libc::c_char, + b"\xc2\xb5\x00" as *const u8 as *const libc::c_char, + b"para;\x00" as *const u8 as *const libc::c_char, + b"\xc2\xb6\x00" as *const u8 as *const libc::c_char, + b"middot;\x00" as *const u8 as *const libc::c_char, + b"\xc2\xb7\x00" as *const u8 as *const libc::c_char, + b"cedil;\x00" as *const u8 as *const libc::c_char, + b"\xc2\xb8\x00" as *const u8 as *const libc::c_char, + b"sup1;\x00" as *const u8 as *const libc::c_char, + b"\xc2\xb9\x00" as *const u8 as *const libc::c_char, + b"ordm;\x00" as *const u8 as *const libc::c_char, + b"\xc2\xba\x00" as *const u8 as *const libc::c_char, + b"raquo;\x00" as *const u8 as *const libc::c_char, + b"\xc2\xbb\x00" as *const u8 as *const libc::c_char, + b"frac14;\x00" as *const u8 as *const libc::c_char, + b"\xc2\xbc\x00" as *const u8 as *const libc::c_char, + b"frac12;\x00" as *const u8 as *const libc::c_char, + b"\xc2\xbd\x00" as *const u8 as *const libc::c_char, + b"frac34;\x00" as *const u8 as *const libc::c_char, + b"\xc2\xbe\x00" as *const u8 as *const libc::c_char, + b"iquest;\x00" as *const u8 as *const libc::c_char, + b"\xc2\xbf\x00" as *const u8 as *const libc::c_char, + b"Agrave;\x00" as *const u8 as *const libc::c_char, + b"\xc3\x80\x00" as *const u8 as *const libc::c_char, + b"Aacute;\x00" as *const u8 as *const libc::c_char, + b"\xc3\x81\x00" as *const u8 as *const libc::c_char, + b"Acirc;\x00" as *const u8 as *const libc::c_char, + b"\xc3\x82\x00" as *const u8 as *const libc::c_char, + b"Atilde;\x00" as *const u8 as *const libc::c_char, + b"\xc3\x83\x00" as *const u8 as *const libc::c_char, + b"Auml;\x00" as *const u8 as *const libc::c_char, + b"\xc3\x84\x00" as *const u8 as *const libc::c_char, + b"Aring;\x00" as *const u8 as *const libc::c_char, + b"\xc3\x85\x00" as *const u8 as *const libc::c_char, + b"AElig;\x00" as *const u8 as *const libc::c_char, + b"\xc3\x86\x00" as *const u8 as *const libc::c_char, + b"Ccedil;\x00" as *const u8 as *const libc::c_char, + b"\xc3\x87\x00" as *const u8 as *const libc::c_char, + b"Egrave;\x00" as *const u8 as *const libc::c_char, + b"\xc3\x88\x00" as *const u8 as *const libc::c_char, + b"Eacute;\x00" as *const u8 as *const libc::c_char, + b"\xc3\x89\x00" as *const u8 as *const libc::c_char, + b"Ecirc;\x00" as *const u8 as *const libc::c_char, + b"\xc3\x8a\x00" as *const u8 as *const libc::c_char, + b"Euml;\x00" as *const u8 as *const libc::c_char, + b"\xc3\x8b\x00" as *const u8 as *const libc::c_char, + b"Igrave;\x00" as *const u8 as *const libc::c_char, + b"\xc3\x8c\x00" as *const u8 as *const libc::c_char, + b"Iacute;\x00" as *const u8 as *const libc::c_char, + b"\xc3\x8d\x00" as *const u8 as *const libc::c_char, + b"Icirc;\x00" as *const u8 as *const libc::c_char, + b"\xc3\x8e\x00" as *const u8 as *const libc::c_char, + b"Iuml;\x00" as *const u8 as *const libc::c_char, + b"\xc3\x8f\x00" as *const u8 as *const libc::c_char, + b"ETH;\x00" as *const u8 as *const libc::c_char, + b"\xc3\x90\x00" as *const u8 as *const libc::c_char, + b"Ntilde;\x00" as *const u8 as *const libc::c_char, + b"\xc3\x91\x00" as *const u8 as *const libc::c_char, + b"Ograve;\x00" as *const u8 as *const libc::c_char, + b"\xc3\x92\x00" as *const u8 as *const libc::c_char, + b"Oacute;\x00" as *const u8 as *const libc::c_char, + b"\xc3\x93\x00" as *const u8 as *const libc::c_char, + b"Ocirc;\x00" as *const u8 as *const libc::c_char, + b"\xc3\x94\x00" as *const u8 as *const libc::c_char, + b"Otilde;\x00" as *const u8 as *const libc::c_char, + b"\xc3\x95\x00" as *const u8 as *const libc::c_char, + b"Ouml;\x00" as *const u8 as *const libc::c_char, + b"\xc3\x96\x00" as *const u8 as *const libc::c_char, + b"times;\x00" as *const u8 as *const libc::c_char, + b"\xc3\x97\x00" as *const u8 as *const libc::c_char, + b"Oslash;\x00" as *const u8 as *const libc::c_char, + b"\xc3\x98\x00" as *const u8 as *const libc::c_char, + b"Ugrave;\x00" as *const u8 as *const libc::c_char, + b"\xc3\x99\x00" as *const u8 as *const libc::c_char, + b"Uacute;\x00" as *const u8 as *const libc::c_char, + b"\xc3\x9a\x00" as *const u8 as *const libc::c_char, + b"Ucirc;\x00" as *const u8 as *const libc::c_char, + b"\xc3\x9b\x00" as *const u8 as *const libc::c_char, + b"Uuml;\x00" as *const u8 as *const libc::c_char, + b"\xc3\x9c\x00" as *const u8 as *const libc::c_char, + b"Yacute;\x00" as *const u8 as *const libc::c_char, + b"\xc3\x9d\x00" as *const u8 as *const libc::c_char, + b"THORN;\x00" as *const u8 as *const libc::c_char, + b"\xc3\x9e\x00" as *const u8 as *const libc::c_char, + b"szlig;\x00" as *const u8 as *const libc::c_char, + b"\xc3\x9f\x00" as *const u8 as *const libc::c_char, + b"agrave;\x00" as *const u8 as *const libc::c_char, + b"\xc3\xa0\x00" as *const u8 as *const libc::c_char, + b"aacute;\x00" as *const u8 as *const libc::c_char, + b"\xc3\xa1\x00" as *const u8 as *const libc::c_char, + b"acirc;\x00" as *const u8 as *const libc::c_char, + b"\xc3\xa2\x00" as *const u8 as *const libc::c_char, + b"atilde;\x00" as *const u8 as *const libc::c_char, + b"\xc3\xa3\x00" as *const u8 as *const libc::c_char, + b"auml;\x00" as *const u8 as *const libc::c_char, + b"\xc3\xa4\x00" as *const u8 as *const libc::c_char, + b"aring;\x00" as *const u8 as *const libc::c_char, + b"\xc3\xa5\x00" as *const u8 as *const libc::c_char, + b"aelig;\x00" as *const u8 as *const libc::c_char, + b"\xc3\xa6\x00" as *const u8 as *const libc::c_char, + b"ccedil;\x00" as *const u8 as *const libc::c_char, + b"\xc3\xa7\x00" as *const u8 as *const libc::c_char, + b"egrave;\x00" as *const u8 as *const libc::c_char, + b"\xc3\xa8\x00" as *const u8 as *const libc::c_char, + b"eacute;\x00" as *const u8 as *const libc::c_char, + b"\xc3\xa9\x00" as *const u8 as *const libc::c_char, + b"ecirc;\x00" as *const u8 as *const libc::c_char, + b"\xc3\xaa\x00" as *const u8 as *const libc::c_char, + b"euml;\x00" as *const u8 as *const libc::c_char, + b"\xc3\xab\x00" as *const u8 as *const libc::c_char, + b"igrave;\x00" as *const u8 as *const libc::c_char, + b"\xc3\xac\x00" as *const u8 as *const libc::c_char, + b"iacute;\x00" as *const u8 as *const libc::c_char, + b"\xc3\xad\x00" as *const u8 as *const libc::c_char, + b"icirc;\x00" as *const u8 as *const libc::c_char, + b"\xc3\xae\x00" as *const u8 as *const libc::c_char, + b"iuml;\x00" as *const u8 as *const libc::c_char, + b"\xc3\xaf\x00" as *const u8 as *const libc::c_char, + b"eth;\x00" as *const u8 as *const libc::c_char, + b"\xc3\xb0\x00" as *const u8 as *const libc::c_char, + b"ntilde;\x00" as *const u8 as *const libc::c_char, + b"\xc3\xb1\x00" as *const u8 as *const libc::c_char, + b"ograve;\x00" as *const u8 as *const libc::c_char, + b"\xc3\xb2\x00" as *const u8 as *const libc::c_char, + b"oacute;\x00" as *const u8 as *const libc::c_char, + b"\xc3\xb3\x00" as *const u8 as *const libc::c_char, + b"ocirc;\x00" as *const u8 as *const libc::c_char, + b"\xc3\xb4\x00" as *const u8 as *const libc::c_char, + b"otilde;\x00" as *const u8 as *const libc::c_char, + b"\xc3\xb5\x00" as *const u8 as *const libc::c_char, + b"ouml;\x00" as *const u8 as *const libc::c_char, + b"\xc3\xb6\x00" as *const u8 as *const libc::c_char, + b"divide;\x00" as *const u8 as *const libc::c_char, + b"\xc3\xb7\x00" as *const u8 as *const libc::c_char, + b"oslash;\x00" as *const u8 as *const libc::c_char, + b"\xc3\xb8\x00" as *const u8 as *const libc::c_char, + b"ugrave;\x00" as *const u8 as *const libc::c_char, + b"\xc3\xb9\x00" as *const u8 as *const libc::c_char, + b"uacute;\x00" as *const u8 as *const libc::c_char, + b"\xc3\xba\x00" as *const u8 as *const libc::c_char, + b"ucirc;\x00" as *const u8 as *const libc::c_char, + b"\xc3\xbb\x00" as *const u8 as *const libc::c_char, + b"uuml;\x00" as *const u8 as *const libc::c_char, + b"\xc3\xbc\x00" as *const u8 as *const libc::c_char, + b"yacute;\x00" as *const u8 as *const libc::c_char, + b"\xc3\xbd\x00" as *const u8 as *const libc::c_char, + b"thorn;\x00" as *const u8 as *const libc::c_char, + b"\xc3\xbe\x00" as *const u8 as *const libc::c_char, + b"yuml;\x00" as *const u8 as *const libc::c_char, + b"\xc3\xbf\x00" as *const u8 as *const libc::c_char, + b"OElig;\x00" as *const u8 as *const libc::c_char, + b"\xc5\x92\x00" as *const u8 as *const libc::c_char, + b"oelig;\x00" as *const u8 as *const libc::c_char, + b"\xc5\x93\x00" as *const u8 as *const libc::c_char, + b"Scaron;\x00" as *const u8 as *const libc::c_char, + b"\xc5\xa0\x00" as *const u8 as *const libc::c_char, + b"scaron;\x00" as *const u8 as *const libc::c_char, + b"\xc5\xa1\x00" as *const u8 as *const libc::c_char, + b"Yuml;\x00" as *const u8 as *const libc::c_char, + b"\xc5\xb8\x00" as *const u8 as *const libc::c_char, + b"fnof;\x00" as *const u8 as *const libc::c_char, + b"\xc6\x92\x00" as *const u8 as *const libc::c_char, + b"circ;\x00" as *const u8 as *const libc::c_char, + b"\xcb\x86\x00" as *const u8 as *const libc::c_char, + b"tilde;\x00" as *const u8 as *const libc::c_char, + b"\xcb\x9c\x00" as *const u8 as *const libc::c_char, + b"Alpha;\x00" as *const u8 as *const libc::c_char, + b"\xce\x91\x00" as *const u8 as *const libc::c_char, + b"Beta;\x00" as *const u8 as *const libc::c_char, + b"\xce\x92\x00" as *const u8 as *const libc::c_char, + b"Gamma;\x00" as *const u8 as *const libc::c_char, + b"\xce\x93\x00" as *const u8 as *const libc::c_char, + b"Delta;\x00" as *const u8 as *const libc::c_char, + b"\xce\x94\x00" as *const u8 as *const libc::c_char, + b"Epsilon;\x00" as *const u8 as *const libc::c_char, + b"\xce\x95\x00" as *const u8 as *const libc::c_char, + b"Zeta;\x00" as *const u8 as *const libc::c_char, + b"\xce\x96\x00" as *const u8 as *const libc::c_char, + b"Eta;\x00" as *const u8 as *const libc::c_char, + b"\xce\x97\x00" as *const u8 as *const libc::c_char, + b"Theta;\x00" as *const u8 as *const libc::c_char, + b"\xce\x98\x00" as *const u8 as *const libc::c_char, + b"Iota;\x00" as *const u8 as *const libc::c_char, + b"\xce\x99\x00" as *const u8 as *const libc::c_char, + b"Kappa;\x00" as *const u8 as *const libc::c_char, + b"\xce\x9a\x00" as *const u8 as *const libc::c_char, + b"Lambda;\x00" as *const u8 as *const libc::c_char, + b"\xce\x9b\x00" as *const u8 as *const libc::c_char, + b"Mu;\x00" as *const u8 as *const libc::c_char, + b"\xce\x9c\x00" as *const u8 as *const libc::c_char, + b"Nu;\x00" as *const u8 as *const libc::c_char, + b"\xce\x9d\x00" as *const u8 as *const libc::c_char, + b"Xi;\x00" as *const u8 as *const libc::c_char, + b"\xce\x9e\x00" as *const u8 as *const libc::c_char, + b"Omicron;\x00" as *const u8 as *const libc::c_char, + b"\xce\x9f\x00" as *const u8 as *const libc::c_char, + b"Pi;\x00" as *const u8 as *const libc::c_char, + b"\xce\xa0\x00" as *const u8 as *const libc::c_char, + b"Rho;\x00" as *const u8 as *const libc::c_char, + b"\xce\xa1\x00" as *const u8 as *const libc::c_char, + b"Sigma;\x00" as *const u8 as *const libc::c_char, + b"\xce\xa3\x00" as *const u8 as *const libc::c_char, + b"Tau;\x00" as *const u8 as *const libc::c_char, + b"\xce\xa4\x00" as *const u8 as *const libc::c_char, + b"Upsilon;\x00" as *const u8 as *const libc::c_char, + b"\xce\xa5\x00" as *const u8 as *const libc::c_char, + b"Phi;\x00" as *const u8 as *const libc::c_char, + b"\xce\xa6\x00" as *const u8 as *const libc::c_char, + b"Chi;\x00" as *const u8 as *const libc::c_char, + b"\xce\xa7\x00" as *const u8 as *const libc::c_char, + b"Psi;\x00" as *const u8 as *const libc::c_char, + b"\xce\xa8\x00" as *const u8 as *const libc::c_char, + b"Omega;\x00" as *const u8 as *const libc::c_char, + b"\xce\xa9\x00" as *const u8 as *const libc::c_char, + b"alpha;\x00" as *const u8 as *const libc::c_char, + b"\xce\xb1\x00" as *const u8 as *const libc::c_char, + b"beta;\x00" as *const u8 as *const libc::c_char, + b"\xce\xb2\x00" as *const u8 as *const libc::c_char, + b"gamma;\x00" as *const u8 as *const libc::c_char, + b"\xce\xb3\x00" as *const u8 as *const libc::c_char, + b"delta;\x00" as *const u8 as *const libc::c_char, + b"\xce\xb4\x00" as *const u8 as *const libc::c_char, + b"epsilon;\x00" as *const u8 as *const libc::c_char, + b"\xce\xb5\x00" as *const u8 as *const libc::c_char, + b"zeta;\x00" as *const u8 as *const libc::c_char, + b"\xce\xb6\x00" as *const u8 as *const libc::c_char, + b"eta;\x00" as *const u8 as *const libc::c_char, + b"\xce\xb7\x00" as *const u8 as *const libc::c_char, + b"theta;\x00" as *const u8 as *const libc::c_char, + b"\xce\xb8\x00" as *const u8 as *const libc::c_char, + b"iota;\x00" as *const u8 as *const libc::c_char, + b"\xce\xb9\x00" as *const u8 as *const libc::c_char, + b"kappa;\x00" as *const u8 as *const libc::c_char, + b"\xce\xba\x00" as *const u8 as *const libc::c_char, + b"lambda;\x00" as *const u8 as *const libc::c_char, + b"\xce\xbb\x00" as *const u8 as *const libc::c_char, + b"mu;\x00" as *const u8 as *const libc::c_char, + b"\xce\xbc\x00" as *const u8 as *const libc::c_char, + b"nu;\x00" as *const u8 as *const libc::c_char, + b"\xce\xbd\x00" as *const u8 as *const libc::c_char, + b"xi;\x00" as *const u8 as *const libc::c_char, + b"\xce\xbe\x00" as *const u8 as *const libc::c_char, + b"omicron;\x00" as *const u8 as *const libc::c_char, + b"\xce\xbf\x00" as *const u8 as *const libc::c_char, + b"pi;\x00" as *const u8 as *const libc::c_char, + b"\xcf\x80\x00" as *const u8 as *const libc::c_char, + b"rho;\x00" as *const u8 as *const libc::c_char, + b"\xcf\x81\x00" as *const u8 as *const libc::c_char, + b"sigmaf;\x00" as *const u8 as *const libc::c_char, + b"\xcf\x82\x00" as *const u8 as *const libc::c_char, + b"sigma;\x00" as *const u8 as *const libc::c_char, + b"\xcf\x83\x00" as *const u8 as *const libc::c_char, + b"tau;\x00" as *const u8 as *const libc::c_char, + b"\xcf\x84\x00" as *const u8 as *const libc::c_char, + b"upsilon;\x00" as *const u8 as *const libc::c_char, + b"\xcf\x85\x00" as *const u8 as *const libc::c_char, + b"phi;\x00" as *const u8 as *const libc::c_char, + b"\xcf\x86\x00" as *const u8 as *const libc::c_char, + b"chi;\x00" as *const u8 as *const libc::c_char, + b"\xcf\x87\x00" as *const u8 as *const libc::c_char, + b"psi;\x00" as *const u8 as *const libc::c_char, + b"\xcf\x88\x00" as *const u8 as *const libc::c_char, + b"omega;\x00" as *const u8 as *const libc::c_char, + b"\xcf\x89\x00" as *const u8 as *const libc::c_char, + b"thetasym;\x00" as *const u8 as *const libc::c_char, + b"\xcf\x91\x00" as *const u8 as *const libc::c_char, + b"upsih;\x00" as *const u8 as *const libc::c_char, + b"\xcf\x92\x00" as *const u8 as *const libc::c_char, + b"piv;\x00" as *const u8 as *const libc::c_char, + b"\xcf\x96\x00" as *const u8 as *const libc::c_char, + b"ensp;\x00" as *const u8 as *const libc::c_char, + b" \x00" as *const u8 as *const libc::c_char, + b"emsp;\x00" as *const u8 as *const libc::c_char, + b" \x00" as *const u8 as *const libc::c_char, + b"thinsp;\x00" as *const u8 as *const libc::c_char, + b" \x00" as *const u8 as *const libc::c_char, + b"zwnj;\x00" as *const u8 as *const libc::c_char, + b"\x00" as *const u8 as *const libc::c_char, + b"zwj;\x00" as *const u8 as *const libc::c_char, + b"\x00" as *const u8 as *const libc::c_char, + b"lrm;\x00" as *const u8 as *const libc::c_char, + b"\x00" as *const u8 as *const libc::c_char, + b"rlm;\x00" as *const u8 as *const libc::c_char, + b"\x00" as *const u8 as *const libc::c_char, + b"ndash;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x80\x93\x00" as *const u8 as *const libc::c_char, + b"mdash;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x80\x94\x00" as *const u8 as *const libc::c_char, + b"lsquo;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x80\x98\x00" as *const u8 as *const libc::c_char, + b"rsquo;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x80\x99\x00" as *const u8 as *const libc::c_char, + b"sbquo;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x80\x9a\x00" as *const u8 as *const libc::c_char, + b"ldquo;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x80\x9c\x00" as *const u8 as *const libc::c_char, + b"rdquo;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x80\x9d\x00" as *const u8 as *const libc::c_char, + b"bdquo;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x80\x9e\x00" as *const u8 as *const libc::c_char, + b"dagger;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x80\xa0\x00" as *const u8 as *const libc::c_char, + b"Dagger;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x80\xa1\x00" as *const u8 as *const libc::c_char, + b"bull;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x80\xa2\x00" as *const u8 as *const libc::c_char, + b"hellip;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x80\xa6\x00" as *const u8 as *const libc::c_char, + b"permil;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x80\xb0\x00" as *const u8 as *const libc::c_char, + b"prime;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x80\xb2\x00" as *const u8 as *const libc::c_char, + b"Prime;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x80\xb3\x00" as *const u8 as *const libc::c_char, + b"lsaquo;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x80\xb9\x00" as *const u8 as *const libc::c_char, + b"rsaquo;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x80\xba\x00" as *const u8 as *const libc::c_char, + b"oline;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x80\xbe\x00" as *const u8 as *const libc::c_char, + b"frasl;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x81\x84\x00" as *const u8 as *const libc::c_char, + b"euro;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x82\xac\x00" as *const u8 as *const libc::c_char, + b"image;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x84\x91\x00" as *const u8 as *const libc::c_char, + b"weierp;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x84\x98\x00" as *const u8 as *const libc::c_char, + b"real;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x84\x9c\x00" as *const u8 as *const libc::c_char, + b"trade;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x84\xa2\x00" as *const u8 as *const libc::c_char, + b"alefsym;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x84\xb5\x00" as *const u8 as *const libc::c_char, + b"larr;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x86\x90\x00" as *const u8 as *const libc::c_char, + b"uarr;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x86\x91\x00" as *const u8 as *const libc::c_char, + b"rarr;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x86\x92\x00" as *const u8 as *const libc::c_char, + b"darr;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x86\x93\x00" as *const u8 as *const libc::c_char, + b"harr;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x86\x94\x00" as *const u8 as *const libc::c_char, + b"crarr;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x86\xb5\x00" as *const u8 as *const libc::c_char, + b"lArr;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x87\x90\x00" as *const u8 as *const libc::c_char, + b"uArr;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x87\x91\x00" as *const u8 as *const libc::c_char, + b"rArr;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x87\x92\x00" as *const u8 as *const libc::c_char, + b"dArr;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x87\x93\x00" as *const u8 as *const libc::c_char, + b"hArr;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x87\x94\x00" as *const u8 as *const libc::c_char, + b"forall;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x88\x80\x00" as *const u8 as *const libc::c_char, + b"part;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x88\x82\x00" as *const u8 as *const libc::c_char, + b"exist;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x88\x83\x00" as *const u8 as *const libc::c_char, + b"empty;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x88\x85\x00" as *const u8 as *const libc::c_char, + b"nabla;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x88\x87\x00" as *const u8 as *const libc::c_char, + b"isin;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x88\x88\x00" as *const u8 as *const libc::c_char, + b"notin;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x88\x89\x00" as *const u8 as *const libc::c_char, + b"ni;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x88\x8b\x00" as *const u8 as *const libc::c_char, + b"prod;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x88\x8f\x00" as *const u8 as *const libc::c_char, + b"sum;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x88\x91\x00" as *const u8 as *const libc::c_char, + b"minus;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x88\x92\x00" as *const u8 as *const libc::c_char, + b"lowast;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x88\x97\x00" as *const u8 as *const libc::c_char, + b"radic;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x88\x9a\x00" as *const u8 as *const libc::c_char, + b"prop;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x88\x9d\x00" as *const u8 as *const libc::c_char, + b"infin;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x88\x9e\x00" as *const u8 as *const libc::c_char, + b"ang;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x88\xa0\x00" as *const u8 as *const libc::c_char, + b"and;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x88\xa7\x00" as *const u8 as *const libc::c_char, + b"or;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x88\xa8\x00" as *const u8 as *const libc::c_char, + b"cap;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x88\xa9\x00" as *const u8 as *const libc::c_char, + b"cup;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x88\xaa\x00" as *const u8 as *const libc::c_char, + b"int;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x88\xab\x00" as *const u8 as *const libc::c_char, + b"there4;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x88\xb4\x00" as *const u8 as *const libc::c_char, + b"sim;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x88\xbc\x00" as *const u8 as *const libc::c_char, + b"cong;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x89\x85\x00" as *const u8 as *const libc::c_char, + b"asymp;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x89\x88\x00" as *const u8 as *const libc::c_char, + b"ne;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x89\xa0\x00" as *const u8 as *const libc::c_char, + b"equiv;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x89\xa1\x00" as *const u8 as *const libc::c_char, + b"le;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x89\xa4\x00" as *const u8 as *const libc::c_char, + b"ge;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x89\xa5\x00" as *const u8 as *const libc::c_char, + b"sub;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x8a\x82\x00" as *const u8 as *const libc::c_char, + b"sup;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x8a\x83\x00" as *const u8 as *const libc::c_char, + b"nsub;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x8a\x84\x00" as *const u8 as *const libc::c_char, + b"sube;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x8a\x86\x00" as *const u8 as *const libc::c_char, + b"supe;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x8a\x87\x00" as *const u8 as *const libc::c_char, + b"oplus;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x8a\x95\x00" as *const u8 as *const libc::c_char, + b"otimes;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x8a\x97\x00" as *const u8 as *const libc::c_char, + b"perp;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x8a\xa5\x00" as *const u8 as *const libc::c_char, + b"sdot;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x8b\x85\x00" as *const u8 as *const libc::c_char, + b"lceil;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x8c\x88\x00" as *const u8 as *const libc::c_char, + b"rceil;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x8c\x89\x00" as *const u8 as *const libc::c_char, + b"lfloor;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x8c\x8a\x00" as *const u8 as *const libc::c_char, + b"rfloor;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x8c\x8b\x00" as *const u8 as *const libc::c_char, + b"lang;\x00" as *const u8 as *const libc::c_char, + b"<\x00" as *const u8 as *const libc::c_char, + b"rang;\x00" as *const u8 as *const libc::c_char, + b">\x00" as *const u8 as *const libc::c_char, + b"loz;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x97\x8a\x00" as *const u8 as *const libc::c_char, + b"spades;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x99\xa0\x00" as *const u8 as *const libc::c_char, + b"clubs;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x99\xa3\x00" as *const u8 as *const libc::c_char, + b"hearts;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x99\xa5\x00" as *const u8 as *const libc::c_char, + b"diams;\x00" as *const u8 as *const libc::c_char, + b"\xe2\x99\xa6\x00" as *const u8 as *const libc::c_char, + 0 as *const libc::c_char, + 0 as *const libc::c_char, +]; +#[no_mangle] +pub unsafe extern "C" fn dc_attr_find( + mut attr: *mut *mut libc::c_char, + mut key: *const libc::c_char, +) -> *const libc::c_char { + if !attr.is_null() && !key.is_null() { + let mut i: libc::c_int = 0i32; + while !(*attr.offset(i as isize)).is_null() && 0 != strcmp(key, *attr.offset(i as isize)) { + i += 2i32 + } + if !(*attr.offset(i as isize)).is_null() { + return *attr.offset((i + 1i32) as isize); + } + } + return 0 as *const libc::c_char; +} diff --git a/src/dc_securejoin.rs b/src/dc_securejoin.rs new file mode 100644 index 000000000..16f8f248d --- /dev/null +++ b/src/dc_securejoin.rs @@ -0,0 +1,2572 @@ +use c2rust_bitfields::BitfieldStruct; +use libc; +extern "C" { + pub type mailstream_cancel; + pub type sqlite3; + pub type sqlite3_stmt; + #[no_mangle] + fn usleep(_: useconds_t) -> libc::c_int; + #[no_mangle] + fn free(_: *mut libc::c_void); + #[no_mangle] + fn strcmp(_: *const libc::c_char, _: *const libc::c_char) -> libc::c_int; + #[no_mangle] + fn strlen(_: *const libc::c_char) -> libc::c_ulong; + #[no_mangle] + fn strncmp(_: *const libc::c_char, _: *const libc::c_char, _: libc::c_ulong) -> libc::c_int; + #[no_mangle] + fn strcasecmp(_: *const libc::c_char, _: *const libc::c_char) -> libc::c_int; + #[no_mangle] + fn pthread_mutex_lock(_: *mut pthread_mutex_t) -> libc::c_int; + #[no_mangle] + fn pthread_mutex_unlock(_: *mut pthread_mutex_t) -> libc::c_int; + #[no_mangle] + fn dc_create_chat_by_contact_id(_: *mut dc_context_t, contact_id: uint32_t) -> uint32_t; + #[no_mangle] + fn dc_send_msg(_: *mut dc_context_t, chat_id: uint32_t, _: *mut dc_msg_t) -> uint32_t; + #[no_mangle] + fn dc_get_chat_contacts(_: *mut dc_context_t, chat_id: uint32_t) -> *mut dc_array_t; + #[no_mangle] + fn dc_get_chat(_: *mut dc_context_t, chat_id: uint32_t) -> *mut dc_chat_t; + #[no_mangle] + fn dc_get_contact(_: *mut dc_context_t, contact_id: uint32_t) -> *mut dc_contact_t; + #[no_mangle] + fn dc_stop_ongoing_process(_: *mut dc_context_t); + // out-of-band verification + // id=contact + // text1=groupname + // id=contact + // id=contact + // test1=formatted fingerprint + // id=contact + // text1=text + // text1=URL + // text1=error string + #[no_mangle] + fn dc_check_qr(_: *mut dc_context_t, qr: *const libc::c_char) -> *mut dc_lot_t; + /* string tools */ + #[no_mangle] + fn dc_strdup(_: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn dc_chat_unref(_: *mut dc_chat_t); + #[no_mangle] + fn dc_log_info(_: *mut dc_context_t, data1: libc::c_int, msg: *const libc::c_char, _: ...); + #[no_mangle] + fn dc_mprintf(format: *const libc::c_char, _: ...) -> *mut libc::c_char; + #[no_mangle] + fn dc_urlencode(_: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn dc_chat_get_name(_: *const dc_chat_t) -> *mut libc::c_char; + #[no_mangle] + fn dc_log_error(_: *mut dc_context_t, data1: libc::c_int, msg: *const libc::c_char, _: ...); + #[no_mangle] + fn dc_key_new() -> *mut dc_key_t; + #[no_mangle] + fn dc_key_unref(_: *mut dc_key_t); + #[no_mangle] + fn dc_key_get_fingerprint(_: *const dc_key_t) -> *mut libc::c_char; + #[no_mangle] + fn dc_key_load_self_public( + _: *mut dc_key_t, + self_addr: *const libc::c_char, + sql: *mut dc_sqlite3_t, + ) -> libc::c_int; + #[no_mangle] + fn dc_sqlite3_get_config( + _: *mut dc_sqlite3_t, + key: *const libc::c_char, + def: *const libc::c_char, + ) -> *mut libc::c_char; + // Functions to read/write token from/to the database. A token is any string associated with a key. + #[no_mangle] + fn dc_token_save( + _: *mut dc_context_t, + _: dc_tokennamespc_t, + foreign_id: uint32_t, + token: *const libc::c_char, + ); + /* Message-ID tools */ + #[no_mangle] + fn dc_create_id() -> *mut libc::c_char; + #[no_mangle] + fn dc_token_lookup( + _: *mut dc_context_t, + _: dc_tokennamespc_t, + foreign_id: uint32_t, + ) -> *mut libc::c_char; + #[no_mangle] + fn dc_ensure_secret_key_exists(_: *mut dc_context_t) -> libc::c_int; + #[no_mangle] + fn dc_free_ongoing(_: *mut dc_context_t); + #[no_mangle] + fn dc_lot_unref(_: *mut dc_lot_t); + #[no_mangle] + fn dc_get_chat_id_by_grpid( + _: *mut dc_context_t, + grpid: *const libc::c_char, + ret_blocked: *mut libc::c_int, + ret_verified: *mut libc::c_int, + ) -> uint32_t; + #[no_mangle] + fn dc_msg_new_untyped(_: *mut dc_context_t) -> *mut dc_msg_t; + #[no_mangle] + fn dc_msg_unref(_: *mut dc_msg_t); + #[no_mangle] + fn dc_param_set_int(_: *mut dc_param_t, key: libc::c_int, value: int32_t); + #[no_mangle] + fn dc_param_set(_: *mut dc_param_t, key: libc::c_int, value: *const libc::c_char); + /* * + * @class dc_array_t + * + * An object containing a simple array. + * This object is used in several places where functions need to return an array. + * The items of the array are typically IDs. + * To free an array object, use dc_array_unref(). + */ + #[no_mangle] + fn dc_array_unref(_: *mut dc_array_t); + #[no_mangle] + fn dc_array_get_id(_: *const dc_array_t, index: size_t) -> uint32_t; + #[no_mangle] + fn dc_array_get_cnt(_: *const dc_array_t) -> size_t; + /* * + * @class dc_contact_t + * + * An object representing a single contact in memory. + * The contact object is not updated. + * If you want an update, you have to recreate the object. + * + * The library makes sure + * only to use names _authorized_ by the contact in `To:` or `Cc:`. + * _Given-names _as "Daddy" or "Honey" are not used there. + * For this purpose, internally, two names are tracked - + * authorized-name and given-name. + * By default, these names are equal, + * but functions working with contact names + * (eg. dc_contact_get_name(), dc_contact_get_display_name(), + * dc_contact_get_name_n_addr(), dc_contact_get_first_name(), + * dc_create_contact() or dc_add_address_book()) + * only affect the given-name. + */ + #[no_mangle] + fn dc_contact_new(_: *mut dc_context_t) -> *mut dc_contact_t; + #[no_mangle] + fn dc_contact_unref(_: *mut dc_contact_t); + #[no_mangle] + fn dc_apeerstate_new(_: *mut dc_context_t) -> *mut dc_apeerstate_t; + #[no_mangle] + fn dc_normalize_fingerprint(_: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn dc_apeerstate_load_by_addr( + _: *mut dc_apeerstate_t, + _: *mut dc_sqlite3_t, + addr: *const libc::c_char, + ) -> libc::c_int; + /* From: of incoming messages of unknown sender */ + /* Cc: of incoming messages of unknown sender */ + /* To: of incoming messages of unknown sender */ + /* address scanned but not verified */ + /* Reply-To: of incoming message of known sender */ + /* Cc: of incoming message of known sender */ + /* additional To:'s of incoming message of known sender */ + /* a chat was manually created for this user, but no message yet sent */ + /* message sent by us */ + /* message sent by us */ + /* message sent by us */ + /* internal use */ + /* address is in our address book */ + /* set on Alice's side for contacts like Bob that have scanned the QR code offered by her. Only means the contact has once been established using the "securejoin" procedure in the past, getting the current key verification status requires calling dc_contact_is_verified() ! */ + /* set on Bob's side for contacts scanned and verified from a QR code. Only means the contact has once been established using the "securejoin" procedure in the past, getting the current key verification status requires calling dc_contact_is_verified() ! */ + /* contact added mannually by dc_create_contact(), this should be the largets origin as otherwise the user cannot modify the names */ + /* 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 */ + #[no_mangle] + fn dc_contact_load_from_db( + _: *mut dc_contact_t, + _: *mut dc_sqlite3_t, + contact_id: uint32_t, + ) -> libc::c_int; + #[no_mangle] + fn dc_alloc_ongoing(_: *mut dc_context_t) -> libc::c_int; + #[no_mangle] + fn dc_contact_is_verified(_: *mut dc_contact_t) -> libc::c_int; + #[no_mangle] + fn sqlite3_bind_text( + _: *mut sqlite3_stmt, + _: libc::c_int, + _: *const libc::c_char, + _: libc::c_int, + _: Option ()>, + ) -> libc::c_int; + #[no_mangle] + fn sqlite3_step(_: *mut sqlite3_stmt) -> libc::c_int; + #[no_mangle] + fn sqlite3_column_int(_: *mut sqlite3_stmt, iCol: libc::c_int) -> libc::c_int; + #[no_mangle] + fn sqlite3_finalize(pStmt: *mut sqlite3_stmt) -> libc::c_int; + /* tools, these functions are compatible to the corresponding sqlite3_* functions */ + #[no_mangle] + fn dc_sqlite3_prepare(_: *mut dc_sqlite3_t, sql: *const libc::c_char) -> *mut sqlite3_stmt; + /* Replaces the first `%1$s` in the given String-ID by the given value. + The result must be free()'d! */ + #[no_mangle] + fn dc_stock_str_repl_string( + _: *mut dc_context_t, + id: libc::c_int, + value: *const libc::c_char, + ) -> *mut libc::c_char; + #[no_mangle] + fn dc_create_or_lookup_nchat_by_contact_id( + _: *mut dc_context_t, + contact_id: uint32_t, + create_blocked: libc::c_int, + ret_chat_id: *mut uint32_t, + ret_chat_blocked: *mut libc::c_int, + ); + #[no_mangle] + fn dc_unblock_chat(_: *mut dc_context_t, chat_id: uint32_t); + #[no_mangle] + fn dc_add_device_msg(_: *mut dc_context_t, chat_id: uint32_t, text: *const libc::c_char); + #[no_mangle] + fn dc_add_contact_to_chat_ex( + _: *mut dc_context_t, + chat_id: uint32_t, + contact_id: uint32_t, + flags: libc::c_int, + ) -> libc::c_int; + #[no_mangle] + fn dc_hash_find( + _: *const dc_hash_t, + pKey: *const libc::c_void, + nKey: libc::c_int, + ) -> *mut libc::c_void; + #[no_mangle] + fn dc_apeerstate_unref(_: *mut dc_apeerstate_t); + #[no_mangle] + fn dc_apeerstate_set_verified( + _: *mut dc_apeerstate_t, + which_key: libc::c_int, + fingerprint: *const libc::c_char, + verified: libc::c_int, + ) -> libc::c_int; + #[no_mangle] + fn dc_apeerstate_load_by_fingerprint( + _: *mut dc_apeerstate_t, + _: *mut dc_sqlite3_t, + fingerprint: *const libc::c_char, + ) -> libc::c_int; + #[no_mangle] + fn dc_apeerstate_save_to_db( + _: *const dc_apeerstate_t, + _: *mut dc_sqlite3_t, + create: libc::c_int, + ) -> libc::c_int; + #[no_mangle] + fn dc_addr_equals_self(_: *mut dc_context_t, addr: *const libc::c_char) -> libc::c_int; + #[no_mangle] + fn dc_scaleup_contact_origin(_: *mut dc_context_t, contact_id: uint32_t, origin: libc::c_int); + /* the following functions can be used only after a call to dc_mimeparser_parse() */ + #[no_mangle] + fn dc_mimeparser_lookup_field( + _: *mut dc_mimeparser_t, + field_name: *const libc::c_char, + ) -> *mut mailimf_field; + #[no_mangle] + fn dc_log_warning(_: *mut dc_context_t, data1: libc::c_int, msg: *const libc::c_char, _: ...); + #[no_mangle] + fn dc_token_exists( + _: *mut dc_context_t, + _: dc_tokennamespc_t, + token: *const libc::c_char, + ) -> libc::c_int; +} +pub type __uint32_t = libc::c_uint; +pub type __darwin_size_t = libc::c_ulong; +pub type __darwin_ssize_t = libc::c_long; +pub type __darwin_time_t = libc::c_long; +pub type __darwin_useconds_t = __uint32_t; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_cond_t { + pub __sig: libc::c_long, + pub __opaque: [libc::c_char; 40], +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_mutex_t { + pub __sig: libc::c_long, + pub __opaque: [libc::c_char; 56], +} +pub type __darwin_pthread_cond_t = _opaque_pthread_cond_t; +pub type __darwin_pthread_mutex_t = _opaque_pthread_mutex_t; +pub type size_t = __darwin_size_t; +pub type uint32_t = libc::c_uint; +pub type int32_t = libc::c_int; +pub type uintptr_t = libc::c_ulong; +pub type ssize_t = __darwin_ssize_t; +pub type useconds_t = __darwin_useconds_t; +pub type time_t = __darwin_time_t; +pub type uint8_t = libc::c_uchar; +pub type pthread_cond_t = __darwin_pthread_cond_t; +pub type pthread_mutex_t = __darwin_pthread_mutex_t; +#[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; +#[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) -> (); +#[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 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, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct mailimf_mailbox_list { + pub mb_list: *mut clist, +} +#[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_fields { + pub fld_list: *mut clist, +} +pub type unnamed = libc::c_uint; +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: unnamed_0, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed_0 { + 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, +} +#[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 mailmime_composite_type { + pub ct_type: libc::c_int, + pub ct_token: *mut libc::c_char, +} +#[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_type { + pub tp_type: libc::c_int, + pub tp_data: unnamed_1, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed_1 { + 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, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct mailmime_fields { + pub fld_list: *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_2, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed_2 { + pub dt_text: unnamed_3, + pub dt_filename: *mut libc::c_char, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct unnamed_3 { + pub dt_data: *const libc::c_char, + pub dt_length: size_t, +} +#[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_4, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed_4 { + pub mm_single: *mut mailmime_data, + pub mm_multipart: unnamed_6, + pub mm_message: unnamed_5, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct unnamed_5 { + pub mm_fields: *mut mailimf_fields, + pub mm_msg_mime: *mut mailmime, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct unnamed_6 { + 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 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_7, + 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_7 { + 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_capability_data { + pub cap_list: *mut clist, +} +#[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_8, + 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_8 { + 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 extern "C" 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_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, +} +#[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_9, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed_9 { + pub ft_fetch_att: *mut mailimap_fetch_att, + pub ft_fetch_att_list: *mut clist, +} +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_10, + 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 unnamed_10 { + 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, +} +/* define DC_USE_RPGP to enable use of rPGP instead of netpgp where available; +preferrably, this should be done in the project configuration currently */ +//#define DC_USE_RPGP 1 +/* Includes that are used frequently. This file may also be used to create predefined headers. */ +/* * Structure behind dc_context_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_context { + pub magic: uint32_t, + pub userdata: *mut libc::c_void, + pub dbfile: *mut libc::c_char, + pub blobdir: *mut libc::c_char, + pub sql: *mut dc_sqlite3_t, + pub inbox: *mut dc_imap_t, + pub inboxidle_condmutex: pthread_mutex_t, + pub perform_inbox_jobs_needed: libc::c_int, + pub probe_imap_network: libc::c_int, + pub sentbox_thread: dc_jobthread_t, + pub mvbox_thread: dc_jobthread_t, + pub smtp: *mut dc_smtp_t, + pub smtpidle_cond: pthread_cond_t, + pub smtpidle_condmutex: pthread_mutex_t, + pub smtpidle_condflag: libc::c_int, + pub smtp_suspended: libc::c_int, + pub smtp_doing_jobs: libc::c_int, + pub perform_smtp_jobs_needed: libc::c_int, + pub probe_smtp_network: libc::c_int, + pub oauth2_critical: pthread_mutex_t, + 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 type dc_lot_t = _dc_lot; +/* * Structure behind dc_lot_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_lot { + pub magic: uint32_t, + pub text1_meaning: libc::c_int, + pub text1: *mut libc::c_char, + pub text2: *mut libc::c_char, + pub timestamp: time_t, + pub state: libc::c_int, + pub id: uint32_t, + pub fingerprint: *mut libc::c_char, + pub invitenumber: *mut libc::c_char, + pub auth: *mut libc::c_char, +} +/* * + * 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 = Option< + unsafe extern "C" fn( + _: *mut dc_context_t, + _: libc::c_int, + _: uintptr_t, + _: uintptr_t, + ) -> uintptr_t, +>; +/* * + * @mainpage Getting started + * + * This document describes how to handle the Delta Chat core library. + * For general information about Delta Chat itself, + * see and . + * + * Let's start. + * + * First of all, you have to **define an event-handler-function** + * that is called by the library on specific events + * (eg. when the configuration is done or when fresh messages arrive). + * With this function you can create a Delta Chat context then: + * + * ~~~ + * #include + * + * uintptr_t event_handler_func(dc_context_t* context, int event, + * uintptr_t data1, uintptr_t data2) + * { + * return 0; // for unhandled events, it is always safe to return 0 + * } + * + * dc_context_t* context = dc_context_new(event_handler_func, NULL, NULL); + * ~~~ + * + * After that, you should make sure, + * sending and receiving jobs are processed as needed. + * For this purpose, you have to **create two threads:** + * + * ~~~ + * #include + * + * void* imap_thread_func(void* context) + * { + * while (true) { + * dc_perform_imap_jobs(context); + * dc_perform_imap_fetch(context); + * dc_perform_imap_idle(context); + * } + * } + * + * void* smtp_thread_func(void* context) + * { + * while (true) { + * dc_perform_smtp_jobs(context); + * dc_perform_smtp_idle(context); + * } + * } + * + * static pthread_t imap_thread, smtp_thread; + * pthread_create(&imap_thread, NULL, imap_thread_func, context); + * pthread_create(&smtp_thread, NULL, smtp_thread_func, context); + * ~~~ + * + * The example above uses "pthreads", + * however, you can also use anything else for thread handling. + * NB: The deltachat-core library itself does not create any threads on its own, + * however, functions, unless stated otherwise, are thread-safe. + * + * After that you can **define and open a database.** + * The database is a normal sqlite-file and is created as needed: + * + * ~~~ + * dc_open(context, "example.db", NULL); + * ~~~ + * + * Now you can **configure the context:** + * + * ~~~ + * // use some real test credentials here + * dc_set_config(context, "addr", "alice@example.org"); + * dc_set_config(context, "mail_pw", "***"); + * dc_configure(context); + * ~~~ + * + * dc_configure() returns immediately, the configuration itself may take a while + * and is done by a job in the imap-thread you've defined above. + * Once done, the #DC_EVENT_CONFIGURE_PROGRESS reports success + * to the event_handler_func() that is also defined above. + * + * The configuration result is saved in the database, + * on subsequent starts it is not needed to call dc_configure() + * (you can check this using dc_is_configured()). + * + * Now you can **send the first message:** + * + * ~~~ + * // use a real testing address here + * uint32_t contact_id = dc_create_contact(context, NULL, "bob@example.org"); + * uint32_t chat_id = dc_create_chat_by_contact_id(context, contact_id); + * + * dc_send_text_msg(context, chat_id, "Hi, here is my first message!"); + * ~~~ + * + * dc_send_text_msg() returns immediately; + * the sending itself is done by a job in the smtp-thread you've defined above. + * If you check the testing address (bob) + * and you should have received a normal email. + * Answer this email in any email program with "Got it!" + * and the imap-thread you've create above will **receive the message**. + * + * You can then **list all messages** of a chat as follow: + * + * ~~~ + * dc_array_t* msglist = dc_get_chat_msgs(context, chat_id, 0, 0); + * for (int i = 0; i < dc_array_get_cnt(msglist); i++) + * { + * uint32_t msg_id = dc_array_get_id(msglist, i); + * dc_msg_t* msg = dc_get_msg(context, msg_id); + * char* text = dc_msg_get_text(msg); + * + * printf("Message %i: %s\n", i+1, text); + * + * free(text); + * dc_msg_unref(msg); + * } + * dc_array_unref(msglist); + * ~~~ + * + * This will output the following two lines: + * + * ~~~ + * Message 1: Hi, here is my first message! + * Message 2: Got it! + * ~~~ + * + * + * ## Class reference + * + * For a class reference, see the "Classes" link atop. + * + * + * ## Further hints + * + * Here are some additional, unsorted hints that may be useful. + * + * - For `get`-functions, you have to unref the return value in some way. + * + * - Strings in function arguments or return values are usually UTF-8 encoded. + * + * - The issue-tracker for the core library is here: + * + * + * The following points are important mainly + * for the authors of the library itself: + * + * - For indentation, use tabs. + * Alignments that are not placed at the beginning of a line + * should be done with spaces. + * + * - For padding between functions, + * classes etc. use 2 empty lines + * + * - Source files are encoded as UTF-8 with Unix line endings + * (a simple `LF`, `0x0A` or `\n`) + * + * If you need further assistance, + * please do not hesitate to contact us + * through the channels shown at https://delta.chat/en/contribute + * + * Please keep in mind, that your derived work + * must respect the Mozilla Public License 2.0 of libdeltachat + * and the respective licenses of the libraries libdeltachat links with. + * + * See you. + */ +/* * + * @class dc_context_t + * + * An object representing a single account. + * + * Each account is linked to an IMAP/SMTP account and uses a separate + * SQLite database for offline functionality and for account-related + * settings. + */ +pub type dc_context_t = _dc_context; +/* ** library-private **********************************************************/ +pub type dc_smtp_t = _dc_smtp; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_smtp { + 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 error: *mut libc::c_char, + pub error_etpan: libc::c_int, +} +pub type dc_jobthread_t = _dc_jobthread; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_jobthread { + 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, + 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, +} +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_imap { + 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 type dc_receive_imf_t = Option< + unsafe extern "C" 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_imap_t = _dc_imap; +pub type dc_precheck_imf_t = Option< + unsafe extern "C" 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< + unsafe extern "C" fn(_: *mut dc_imap_t, _: *const libc::c_char, _: *const libc::c_char) -> (), +>; +pub type dc_get_config_t = Option< + unsafe extern "C" fn( + _: *mut dc_imap_t, + _: *const libc::c_char, + _: *const libc::c_char, + ) -> *mut libc::c_char, +>; +/* ** library-private **********************************************************/ +pub type dc_sqlite3_t = _dc_sqlite3; +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_sqlite3 { + pub cobj: *mut sqlite3, + pub context: *mut dc_context_t, +} +/* * the structure behind dc_array_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_array { + 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, +} +pub type dc_array_t = _dc_array; +/* values for the chats.blocked database field */ +/* * the structure behind dc_chat_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_chat { + 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 grpid: *mut libc::c_char, + pub blocked: libc::c_int, + pub param: *mut dc_param_t, + pub gossiped_timestamp: time_t, + pub is_sending_locations: libc::c_int, +} +pub type dc_param_t = _dc_param; +/* * + * @class dc_param_t + * + * An object for handling key=value parameter lists; for the key, curently only + * a single character is allowed. + * + * The object is used eg. by dc_chat_t or dc_msg_t, for readable paramter names, + * these classes define some DC_PARAM_* constantats. + * + * Only for library-internal use. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_param { + pub packed: *mut libc::c_char, +} +pub type dc_chat_t = _dc_chat; +/* * the structure behind dc_msg_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_msg { + pub magic: uint32_t, + pub id: uint32_t, + pub from_id: uint32_t, + pub to_id: uint32_t, + pub chat_id: uint32_t, + pub move_state: dc_move_state_t, + pub type_0: libc::c_int, + pub state: libc::c_int, + pub hidden: libc::c_int, + pub timestamp_sort: time_t, + pub timestamp_sent: time_t, + pub timestamp_rcvd: time_t, + pub text: *mut libc::c_char, + pub context: *mut 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, + pub server_uid: uint32_t, + pub is_dc_message: libc::c_int, + pub starred: libc::c_int, + pub chat_blocked: libc::c_int, + pub location_id: uint32_t, + pub param: *mut dc_param_t, +} +pub type dc_move_state_t = libc::c_uint; +pub const DC_MOVE_STATE_MOVING: dc_move_state_t = 3; +pub const DC_MOVE_STATE_STAY: dc_move_state_t = 2; +pub const DC_MOVE_STATE_PENDING: dc_move_state_t = 1; +pub const DC_MOVE_STATE_UNDEFINED: dc_move_state_t = 0; +pub type dc_msg_t = _dc_msg; +/* * the structure behind dc_contact_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_contact { + pub magic: uint32_t, + pub context: *mut dc_context_t, + pub id: uint32_t, + pub name: *mut libc::c_char, + pub authname: *mut libc::c_char, + pub addr: *mut libc::c_char, + pub blocked: libc::c_int, + pub origin: libc::c_int, +} +pub type dc_contact_t = _dc_contact; +pub type dc_key_t = _dc_key; +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_key { + pub binary: *mut libc::c_void, + pub bytes: libc::c_int, + pub type_0: libc::c_int, + pub _m_heap_refcnt: libc::c_int, +} +// Token namespaces +pub type dc_tokennamespc_t = libc::c_uint; +pub const DC_TOKEN_AUTH: dc_tokennamespc_t = 110; +pub const DC_TOKEN_INVITENUMBER: dc_tokennamespc_t = 100; +pub type dc_apeerstate_t = _dc_apeerstate; +/* prefer-encrypt states */ +/* * + * @class dc_apeerstate_t + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_apeerstate { + pub context: *mut dc_context_t, + pub addr: *mut libc::c_char, + pub last_seen: time_t, + pub last_seen_autocrypt: time_t, + pub prefer_encrypt: libc::c_int, + pub public_key: *mut dc_key_t, + pub public_key_fingerprint: *mut libc::c_char, + pub gossip_key: *mut dc_key_t, + pub gossip_timestamp: time_t, + pub gossip_key_fingerprint: *mut libc::c_char, + pub verified_key: *mut dc_key_t, + pub verified_key_fingerprint: *mut libc::c_char, + pub to_save: libc::c_int, + pub degrade_event: libc::c_int, +} +pub type sqlite3_destructor_type = Option ()>; +/* A complete hash table is an instance of the following structure. + * The internals of this structure are intended to be opaque -- client + * code should not attempt to access or modify the fields of this structure + * directly. Change this structure only by using the routines below. + * However, many of the "procedures" and "functions" for modifying and + * accessing this structure are really macros, so we can't really make + * this structure opaque. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_hash { + pub keyClass: libc::c_char, + pub copyKey: libc::c_char, + pub count: libc::c_int, + pub first: *mut dc_hashelem_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. + * + * Again, this structure is intended to be opaque, but it can't really + * be opaque because it is used by macros. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_hashelem { + pub next: *mut dc_hashelem_t, + pub prev: *mut dc_hashelem_t, + pub data: *mut libc::c_void, + pub pKey: *mut libc::c_void, + pub nKey: libc::c_int, +} +/* Forward declarations of structures. + */ +pub type dc_hash_t = _dc_hash; +/* * + * @class dc_mimeparser_t + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_mimeparser { + pub parts: *mut carray, + pub mimeroot: *mut mailmime, + pub header: dc_hash_t, + pub header_root: *mut mailimf_fields, + pub header_protected: *mut mailimf_fields, + pub subject: *mut libc::c_char, + pub is_send_by_messenger: libc::c_int, + pub decrypting_failed: libc::c_int, + pub e2ee_helper: *mut _dc_e2ee_helper, + pub blobdir: *const libc::c_char, + pub is_forwarded: libc::c_int, + pub context: *mut dc_context_t, + pub reports: *mut carray, + pub is_system_message: libc::c_int, + pub kml: *mut _dc_kml, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_kml { + pub addr: *mut libc::c_char, + pub locations: *mut dc_array_t, + pub tag: libc::c_int, + pub curr: dc_location_t, +} +pub type dc_location_t = _dc_location; +// location handling +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_location { + pub location_id: uint32_t, + pub latitude: libc::c_double, + pub longitude: libc::c_double, + pub accuracy: libc::c_double, + pub timestamp: time_t, + pub contact_id: uint32_t, + pub msg_id: uint32_t, + pub chat_id: uint32_t, + pub marker: *mut libc::c_char, +} +/* library private: end-to-end-encryption */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_e2ee_helper { + pub encryption_successfull: libc::c_int, + pub cdata_to_free: *mut libc::c_void, + pub encrypted: libc::c_int, + pub signatures: *mut dc_hash_t, + pub gossipped_addr: *mut dc_hash_t, +} +pub type dc_mimeparser_t = _dc_mimeparser; +#[no_mangle] +pub unsafe extern "C" fn dc_get_securejoin_qr( + mut context: *mut dc_context_t, + mut group_chat_id: uint32_t, +) -> *mut libc::c_char { + let mut current_block: u64; + /* ========================================================= + ==== Alice - the inviter side ==== + ==== 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_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 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, + ); + 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 { + 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); + free(self_name_urlencoded as *mut libc::c_void); + free(fingerprint as *mut libc::c_void); + free(invitenumber as *mut libc::c_void); + free(auth as *mut libc::c_void); + dc_chat_unref(chat); + free(group_name as *mut libc::c_void); + free(group_name_urlencoded as *mut libc::c_void); + return if !qr.is_null() { + qr + } else { + dc_strdup(0 as *const libc::c_char) + }; +} +unsafe extern "C" 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; + 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, + 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); + fingerprint.is_null(); + } + free(self_addr as *mut libc::c_void); + dc_key_unref(self_key); + return fingerprint; +} +#[no_mangle] +pub unsafe extern "C" fn dc_join_securejoin( + mut context: *mut dc_context_t, + mut qr: *const libc::c_char, +) -> uint32_t { + /* ========================================================== + ==== Bob - the joiner's side ===== + ==== 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 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, + b"Requesting secure-join ...\x00" as *const u8 as *const libc::c_char, + ); + dc_ensure_secret_key_exists(context); + ongoing_allocated = dc_alloc_ongoing(context); + if !(ongoing_allocated == 0i32) { + qr_scan = dc_check_qr(context, qr); + if qr_scan.is_null() || (*qr_scan).state != 200i32 && (*qr_scan).state != 202i32 { + dc_log_error( + context, + 0i32, + b"Unknown QR code.\x00" as *const u8 as *const libc::c_char, + ); + } else { + contact_chat_id = dc_create_chat_by_contact_id(context, (*qr_scan).id); + if contact_chat_id == 0i32 as libc::c_uint { + dc_log_error( + context, + 0i32, + b"Unknown contact.\x00" as *const u8 as *const libc::c_char, + ); + } else if !(0 != (*context).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 + } + if 0 != fingerprint_equals_sender(context, (*qr_scan).fingerprint, contact_chat_id) + { + dc_log_info( + context, + 0i32, + b"Taking protocol shortcut.\x00" as *const u8 as *const libc::c_char, + ); + (*context).bob_expects = 6i32; + (*context).cb.expect("non-null function pointer")( + context, + 2061i32, + chat_id_2_contact_id(context, contact_chat_id) as uintptr_t, + 400i32 as uintptr_t, + ); + let mut own_fingerprint: *mut libc::c_char = get_self_fingerprint(context); + send_handshake_msg( + context, + contact_chat_id, + if 0 != join_vg { + b"vg-request-with-auth\x00" as *const u8 as *const libc::c_char + } else { + b"vc-request-with-auth\x00" as *const u8 as *const libc::c_char + }, + (*qr_scan).auth, + own_fingerprint, + if 0 != join_vg { + (*qr_scan).text2 + } else { + 0 as *mut libc::c_char + }, + ); + free(own_fingerprint as *mut libc::c_void); + } else { + (*context).bob_expects = 2i32; + send_handshake_msg( + context, + contact_chat_id, + if 0 != join_vg { + b"vg-request\x00" as *const u8 as *const libc::c_char + } else { + b"vc-request\x00" as *const u8 as *const libc::c_char + }, + (*qr_scan).invitenumber, + 0 as *const libc::c_char, + 0 as *const libc::c_char, + ); + } + // Bob -> Alice + while !(0 != (*context).shall_stop_ongoing) { + usleep((300i32 * 1000i32) as useconds_t); + } + } + } + } + (*context).bob_expects = 0i32; + if (*context).bobs_status == 1i32 { + if 0 != join_vg { + ret_chat_id = dc_get_chat_id_by_grpid( + context, + (*qr_scan).text2, + 0 as *mut libc::c_int, + 0 as *mut libc::c_int, + ) as libc::c_int + } else { + 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 + } + dc_lot_unref(qr_scan); + if 0 != ongoing_allocated { + dc_free_ongoing(context); + } + return ret_chat_id as uint32_t; +} +unsafe extern "C" fn send_handshake_msg( + mut context: *mut dc_context_t, + mut contact_chat_id: uint32_t, + mut step: *const libc::c_char, + mut param2: *const libc::c_char, + mut fingerprint: *const libc::c_char, + mut grpid: *const libc::c_char, +) { + let mut msg: *mut dc_msg_t = dc_msg_new_untyped(context); + (*msg).type_0 = 10i32; + (*msg).text = dc_mprintf( + b"Secure-Join: %s\x00" as *const u8 as *const libc::c_char, + step, + ); + (*msg).hidden = 1i32; + dc_param_set_int((*msg).param, 'S' as i32, 7i32); + dc_param_set((*msg).param, 'E' as i32, step); + if !param2.is_null() { + dc_param_set((*msg).param, 'F' as i32, param2); + } + if !fingerprint.is_null() { + dc_param_set((*msg).param, 'G' as i32, fingerprint); + } + if !grpid.is_null() { + dc_param_set((*msg).param, 'H' as i32, grpid); + } + if strcmp(step, b"vg-request\x00" as *const u8 as *const libc::c_char) == 0i32 + || strcmp(step, b"vc-request\x00" as *const u8 as *const libc::c_char) == 0i32 + { + dc_param_set_int((*msg).param, 'u' as i32, 1i32); + } else { + dc_param_set_int((*msg).param, 'c' as i32, 1i32); + } + dc_send_msg(context, contact_chat_id, msg); + dc_msg_unref(msg); +} +unsafe extern "C" fn chat_id_2_contact_id( + mut context: *mut dc_context_t, + mut contact_chat_id: uint32_t, +) -> uint32_t { + let mut contact_id: uint32_t = 0i32 as uint32_t; + let mut contacts: *mut dc_array_t = dc_get_chat_contacts(context, contact_chat_id); + if !(dc_array_get_cnt(contacts) != 1i32 as libc::c_ulong) { + contact_id = dc_array_get_id(contacts, 0i32 as size_t) + } + dc_array_unref(contacts); + return contact_id; +} +unsafe extern "C" fn fingerprint_equals_sender( + mut context: *mut dc_context_t, + mut fingerprint: *const libc::c_char, + mut contact_chat_id: uint32_t, +) -> libc::c_int { + let mut fingerprint_equal: libc::c_int = 0i32; + let mut contacts: *mut dc_array_t = dc_get_chat_contacts(context, contact_chat_id); + let mut contact: *mut dc_contact_t = dc_contact_new(context); + let mut peerstate: *mut dc_apeerstate_t = dc_apeerstate_new(context); + let mut fingerprint_normalized: *mut libc::c_char = 0 as *mut libc::c_char; + if !(dc_array_get_cnt(contacts) != 1i32 as libc::c_ulong) { + if !(0 + == dc_contact_load_from_db( + contact, + (*context).sql, + dc_array_get_id(contacts, 0i32 as size_t), + ) + || 0 == dc_apeerstate_load_by_addr(peerstate, (*context).sql, (*contact).addr)) + { + fingerprint_normalized = dc_normalize_fingerprint(fingerprint); + if strcasecmp(fingerprint_normalized, (*peerstate).public_key_fingerprint) == 0i32 { + fingerprint_equal = 1i32 + } + } + } + free(fingerprint_normalized as *mut libc::c_void); + dc_contact_unref(contact); + dc_array_unref(contacts); + return fingerprint_equal; +} +/* library private: secure-join */ +#[no_mangle] +pub unsafe extern "C" fn dc_handle_securejoin_handshake( + mut context: *mut dc_context_t, + mut mimeparser: *mut dc_mimeparser_t, + mut 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 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; + let mut contact_chat_id: uint32_t = 0i32 as uint32_t; + let mut contact_chat_id_blocked: libc::c_int = 0i32; + 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) { + step = lookup_field( + mimeparser, + b"Secure-Join\x00" as *const u8 as *const libc::c_char, + ); + if !step.is_null() { + dc_log_info( + context, + 0i32, + b">>>>>>>>>>>>>>>>>>>>>>>>> secure-join message \'%s\' received\x00" as *const u8 + as *const libc::c_char, + step, + ); + join_vg = (strncmp( + step, + b"vg-\x00" as *const u8 as *const libc::c_char, + 3i32 as libc::c_ulong, + ) == 0i32) as libc::c_int; + dc_create_or_lookup_nchat_by_contact_id( + context, + contact_id, + 0i32, + &mut contact_chat_id, + &mut contact_chat_id_blocked, + ); + if 0 != contact_chat_id_blocked { + dc_unblock_chat(context, contact_chat_id); + } + ret = 0x2i32; + if strcmp(step, b"vg-request\x00" as *const u8 as *const libc::c_char) == 0i32 + || strcmp(step, b"vc-request\x00" as *const u8 as *const libc::c_char) == 0i32 + { + /* ========================================================= + ==== Alice - the inviter side ==== + ==== Step 3 in "Setup verified contact" protocol ==== + ========================================================= */ + // this message may be unencrypted (Bob, the joinder and the sender, might not have Alice's key yet) + // 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; + invitenumber = lookup_field( + mimeparser, + b"Secure-Join-Invitenumber\x00" as *const u8 as *const libc::c_char, + ); + if invitenumber.is_null() { + dc_log_warning( + context, + 0i32, + b"Secure-join denied (invitenumber missing).\x00" as *const u8 + as *const libc::c_char, + ); + current_block = 4378276786830486580; + } else if dc_token_exists(context, DC_TOKEN_INVITENUMBER, invitenumber) == 0i32 { + dc_log_warning( + context, + 0i32, + b"Secure-join denied (bad invitenumber).\x00" as *const u8 + as *const libc::c_char, + ); + current_block = 4378276786830486580; + } else { + dc_log_info( + context, + 0i32, + b"Secure-join requested.\x00" as *const u8 as *const libc::c_char, + ); + (*context).cb.expect("non-null function pointer")( + context, + 2060i32, + contact_id as uintptr_t, + 300i32 as uintptr_t, + ); + send_handshake_msg( + context, + contact_chat_id, + if 0 != join_vg { + b"vg-auth-required\x00" as *const u8 as *const libc::c_char + } else { + b"vc-auth-required\x00" as *const u8 as *const libc::c_char + }, + 0 as *const libc::c_char, + 0 as *const libc::c_char, + 0 as *const libc::c_char, + ); + current_block = 10256747982273457880; + } + } else if strcmp( + step, + b"vg-auth-required\x00" as *const u8 as *const libc::c_char, + ) == 0i32 + || strcmp( + step, + 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 + { + dc_log_warning( + context, + 0i32, + b"auth-required message out of sync.\x00" as *const u8 + as *const libc::c_char, + ); + // 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); + 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 + } + if 0 == encrypted_and_signed(mimeparser, scanned_fingerprint_of_alice) { + could_not_establish_secure_connection( + context, + contact_chat_id, + if 0 != (*(*mimeparser).e2ee_helper).encrypted { + b"No valid signature.\x00" as *const u8 as *const libc::c_char + } else { + b"Not encrypted.\x00" as *const u8 as *const libc::c_char + }, + ); + end_bobs_joining(context, 0i32); + current_block = 4378276786830486580; + } else if 0 + == fingerprint_equals_sender( + context, + scanned_fingerprint_of_alice, + contact_chat_id, + ) + { + could_not_establish_secure_connection( + context, + contact_chat_id, + b"Fingerprint mismatch on joiner-side.\x00" as *const u8 + as *const libc::c_char, + ); + end_bobs_joining(context, 0i32); + current_block = 4378276786830486580; + } else { + dc_log_info( + context, + 0i32, + b"Fingerprint verified.\x00" as *const u8 as *const libc::c_char, + ); + own_fingerprint = get_self_fingerprint(context); + (*context).cb.expect("non-null function pointer")( + context, + 2061i32, + contact_id as uintptr_t, + 400i32 as uintptr_t, + ); + (*context).bob_expects = 6i32; + send_handshake_msg( + context, + contact_chat_id, + if 0 != join_vg { + b"vg-request-with-auth\x00" as *const u8 as *const libc::c_char + } else { + b"vc-request-with-auth\x00" as *const u8 as *const libc::c_char + }, + auth, + own_fingerprint, + grpid, + ); + current_block = 10256747982273457880; + } + } + } else if strcmp( + step, + b"vg-request-with-auth\x00" as *const u8 as *const libc::c_char, + ) == 0i32 + || strcmp( + step, + b"vc-request-with-auth\x00" as *const u8 as *const libc::c_char, + ) == 0i32 + { + /* ============================================================ + ==== Alice - the inviter side ==== + ==== Steps 5+6 in "Setup verified contact" protocol ==== + ==== 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; + fingerprint = lookup_field( + mimeparser, + b"Secure-Join-Fingerprint\x00" as *const u8 as *const libc::c_char, + ); + if fingerprint.is_null() { + could_not_establish_secure_connection( + context, + contact_chat_id, + b"Fingerprint not provided.\x00" as *const u8 as *const libc::c_char, + ); + current_block = 4378276786830486580; + } else if 0 == encrypted_and_signed(mimeparser, fingerprint) { + could_not_establish_secure_connection( + context, + contact_chat_id, + b"Auth not encrypted.\x00" as *const u8 as *const libc::c_char, + ); + current_block = 4378276786830486580; + } else if 0 == fingerprint_equals_sender(context, fingerprint, contact_chat_id) { + could_not_establish_secure_connection( + context, + contact_chat_id, + b"Fingerprint mismatch on inviter-side.\x00" as *const u8 + as *const libc::c_char, + ); + current_block = 4378276786830486580; + } else { + dc_log_info( + context, + 0i32, + 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; + auth_0 = lookup_field( + mimeparser, + b"Secure-Join-Auth\x00" as *const u8 as *const libc::c_char, + ); + if auth_0.is_null() { + could_not_establish_secure_connection( + context, + contact_chat_id, + b"Auth not provided.\x00" as *const u8 as *const libc::c_char, + ); + current_block = 4378276786830486580; + } else if dc_token_exists(context, DC_TOKEN_AUTH, auth_0) == 0i32 { + could_not_establish_secure_connection( + context, + contact_chat_id, + b"Auth invalid.\x00" as *const u8 as *const libc::c_char, + ); + current_block = 4378276786830486580; + } else if 0 == mark_peer_as_verified(context, fingerprint) { + could_not_establish_secure_connection( + context, + contact_chat_id, + b"Fingerprint mismatch on inviter-side.\x00" as *const u8 + as *const libc::c_char, + ); + current_block = 4378276786830486580; + } else { + dc_scaleup_contact_origin(context, contact_id, 0x1000000i32); + dc_log_info( + context, + 0i32, + b"Auth verified.\x00" as *const u8 as *const libc::c_char, + ); + secure_connection_established(context, contact_chat_id); + (*context).cb.expect("non-null function pointer")( + context, + 2030i32, + contact_id as uintptr_t, + 0i32 as uintptr_t, + ); + (*context).cb.expect("non-null function pointer")( + context, + 2060i32, + contact_id as uintptr_t, + 600i32 as uintptr_t, + ); + if 0 != join_vg { + grpid = dc_strdup(lookup_field( + mimeparser, + b"Secure-Join-Group\x00" as *const u8 as *const libc::c_char, + )); + let mut group_chat_id: uint32_t = dc_get_chat_id_by_grpid( + context, + grpid, + 0 as *mut libc::c_int, + 0 as *mut libc::c_int, + ); + if group_chat_id == 0i32 as libc::c_uint { + dc_log_error( + context, + 0i32, + b"Chat %s not found.\x00" as *const u8 as *const libc::c_char, + grpid, + ); + current_block = 4378276786830486580; + } else { + dc_add_contact_to_chat_ex( + context, + group_chat_id, + contact_id, + 0x1i32, + ); + current_block = 10256747982273457880; + } + } else { + send_handshake_msg( + context, + contact_chat_id, + b"vc-contact-confirm\x00" as *const u8 as *const libc::c_char, + 0 as *const libc::c_char, + 0 as *const libc::c_char, + 0 as *const libc::c_char, + ); + (*context).cb.expect("non-null function pointer")( + context, + 2060i32, + contact_id as uintptr_t, + 1000i32 as uintptr_t, + ); + current_block = 10256747982273457880; + } + } + } + } else if strcmp( + step, + b"vg-member-added\x00" as *const u8 as *const libc::c_char, + ) == 0i32 + || strcmp( + step, + b"vc-contact-confirm\x00" as *const u8 as *const libc::c_char, + ) == 0i32 + { + if 0 != join_vg { + ret = 0x1i32 + } + if (*context).bob_expects != 6i32 { + dc_log_info( + context, + 0i32, + b"Message belongs to a different handshake.\x00" as *const u8 + as *const libc::c_char, + ); + 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 + { + dc_log_warning( + context, + 0i32, + b"Message out of sync or belongs to a different handshake.\x00" + as *const u8 as *const libc::c_char, + ); + current_block = 4378276786830486580; + } else { + scanned_fingerprint_of_alice = + dc_strdup((*(*context).bobs_qr_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 + } + let mut vg_expect_encrypted: libc::c_int = 1i32; + if 0 != join_vg { + let mut is_verified_group: libc::c_int = 0i32; + dc_get_chat_id_by_grpid( + context, + grpid, + 0 as *mut libc::c_int, + &mut is_verified_group, + ); + if 0 == is_verified_group { + vg_expect_encrypted = 0i32 + } + } + if 0 != vg_expect_encrypted { + if 0 == encrypted_and_signed(mimeparser, scanned_fingerprint_of_alice) { + could_not_establish_secure_connection( + context, + contact_chat_id, + b"Contact confirm message not encrypted.\x00" as *const u8 + as *const libc::c_char, + ); + end_bobs_joining(context, 0i32); + current_block = 4378276786830486580; + } else { + current_block = 5195798230510548452; + } + } else { + current_block = 5195798230510548452; + } + match current_block { + 4378276786830486580 => {} + _ => { + if 0 == mark_peer_as_verified(context, scanned_fingerprint_of_alice) + { + could_not_establish_secure_connection( + context, + contact_chat_id, + b"Fingerprint mismatch on joiner-side.\x00" as *const u8 + as *const libc::c_char, + ); + current_block = 4378276786830486580; + } else { + dc_scaleup_contact_origin(context, contact_id, 0x2000000i32); + (*context).cb.expect("non-null function pointer")( + context, + 2030i32, + 0i32 as uintptr_t, + 0i32 as uintptr_t, + ); + if 0 != join_vg { + if 0 == dc_addr_equals_self( + context, + lookup_field( + mimeparser, + b"Chat-Group-Member-Added\x00" as *const u8 + as *const libc::c_char, + ), + ) { + dc_log_info(context, 0i32, + b"Message belongs to a different handshake (scaled up contact anyway to allow creation of group).\x00" + as *const u8 as + *const libc::c_char); + current_block = 4378276786830486580; + } else { + current_block = 9180031981464905198; + } + } else { + current_block = 9180031981464905198; + } + match current_block { + 4378276786830486580 => {} + _ => { + secure_connection_established(context, contact_chat_id); + (*context).bob_expects = 0i32; + if 0 != join_vg { + send_handshake_msg( + context, + contact_chat_id, + b"vg-member-added-received\x00" as *const u8 + as *const libc::c_char, + 0 as *const libc::c_char, + 0 as *const libc::c_char, + 0 as *const libc::c_char, + ); + } + end_bobs_joining(context, 1i32); + current_block = 10256747982273457880; + } + } + } + } + } + } + } + } else if strcmp( + step, + b"vg-member-added-received\x00" as *const u8 as *const libc::c_char, + ) == 0i32 + { + /* ============================================================ + ==== Alice - the inviter side ==== + ==== Step 8 in "Out-of-band verified groups" protocol ==== + ============================================================ */ + contact = dc_get_contact(context, contact_id); + if contact.is_null() || 0 == dc_contact_is_verified(contact) { + dc_log_warning( + context, + 0i32, + b"vg-member-added-received invalid.\x00" as *const u8 + as *const libc::c_char, + ); + current_block = 4378276786830486580; + } else { + (*context).cb.expect("non-null function pointer")( + context, + 2060i32, + contact_id as uintptr_t, + 800i32 as uintptr_t, + ); + (*context).cb.expect("non-null function pointer")( + context, + 2060i32, + contact_id as uintptr_t, + 1000i32 as uintptr_t, + ); + current_block = 10256747982273457880; + } + } else { + current_block = 10256747982273457880; + } + match current_block { + 4378276786830486580 => {} + _ => { + if 0 != ret & 0x2i32 { + ret |= 0x4i32 + } + } + } + } + } + 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; +} +unsafe extern "C" fn end_bobs_joining(mut context: *mut dc_context_t, mut status: libc::c_int) { + (*context).bobs_status = status; + dc_stop_ongoing_process(context); +} +unsafe extern "C" fn secure_connection_established( + mut context: *mut 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( + context, + 35i32, + if !contact.is_null() { + (*contact).addr + } else { + b"?\x00" as *const u8 as *const libc::c_char + }, + ); + dc_add_device_msg(context, contact_chat_id, msg); + (*context).cb.expect("non-null function pointer")( + context, + 2020i32, + contact_chat_id as uintptr_t, + 0i32 as uintptr_t, + ); + free(msg as *mut libc::c_void); + dc_contact_unref(contact); +} +unsafe extern "C" fn lookup_field( + mut mimeparser: *mut dc_mimeparser_t, + mut key: *const libc::c_char, +) -> *const libc::c_char { + let mut value: *const libc::c_char = 0 as *const libc::c_char; + let mut field: *mut mailimf_field = dc_mimeparser_lookup_field(mimeparser, key); + if field.is_null() + || (*field).fld_type != MAILIMF_FIELD_OPTIONAL_FIELD as libc::c_int + || (*field).fld_data.fld_optional_field.is_null() + || { + value = (*(*field).fld_data.fld_optional_field).fld_value; + value.is_null() + } + { + return 0 as *const libc::c_char; + } + return value; +} +unsafe extern "C" fn could_not_establish_secure_connection( + mut context: *mut dc_context_t, + mut contact_chat_id: uint32_t, + mut 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 msg: *mut libc::c_char = dc_stock_str_repl_string( + context, + 36i32, + if !contact.is_null() { + (*contact).addr + } else { + b"?\x00" as *const u8 as *const libc::c_char + }, + ); + dc_add_device_msg(context, contact_chat_id, msg); + dc_log_error( + context, + 0i32, + b"%s (%s)\x00" as *const u8 as *const libc::c_char, + msg, + details, + ); + free(msg as *mut libc::c_void); + dc_contact_unref(contact); +} +unsafe extern "C" fn mark_peer_as_verified( + mut context: *mut dc_context_t, + mut 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)) { + 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); + success = 1i32 + } + } + dc_apeerstate_unref(peerstate); + return success; +} +/* ****************************************************************************** + * Tools: Misc. + ******************************************************************************/ +unsafe extern "C" fn encrypted_and_signed( + mut mimeparser: *mut dc_mimeparser_t, + mut expected_fingerprint: *const libc::c_char, +) -> libc::c_int { + if 0 == (*(*mimeparser).e2ee_helper).encrypted { + dc_log_warning( + (*mimeparser).context, + 0i32, + b"Message not encrypted.\x00" as *const u8 as *const libc::c_char, + ); + return 0i32; + } + if (*(*(*mimeparser).e2ee_helper).signatures).count <= 0i32 { + dc_log_warning( + (*mimeparser).context, + 0i32, + b"Message not signed.\x00" as *const u8 as *const libc::c_char, + ); + return 0i32; + } + if expected_fingerprint.is_null() { + dc_log_warning( + (*mimeparser).context, + 0i32, + b"Fingerprint for comparison missing.\x00" as *const u8 as *const libc::c_char, + ); + return 0i32; + } + if dc_hash_find( + (*(*mimeparser).e2ee_helper).signatures, + expected_fingerprint as *const libc::c_void, + strlen(expected_fingerprint) as libc::c_int, + ) + .is_null() + { + dc_log_warning( + (*mimeparser).context, + 0i32, + b"Message does not match expected fingerprint %s.\x00" as *const u8 + as *const libc::c_char, + expected_fingerprint, + ); + return 0i32; + } + return 1i32; +} +#[no_mangle] +pub unsafe extern "C" fn dc_handle_degrade_event( + mut context: *mut 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 contact_chat_id: uint32_t = 0i32 as uint32_t; + if !(context.is_null() || 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 + // with things they cannot fix, so the user is just kicked from the verified group + // (and he will know this and can fix this) + if 0 != (*peerstate).degrade_event & 0x2i32 { + stmt = dc_sqlite3_prepare( + (*context).sql, + 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); + sqlite3_step(stmt); + contact_id = sqlite3_column_int(stmt, 0i32) as uint32_t; + sqlite3_finalize(stmt); + if !(contact_id == 0i32 as libc::c_uint) { + dc_create_or_lookup_nchat_by_contact_id( + context, + contact_id, + 2i32, + &mut contact_chat_id, + 0 as *mut libc::c_int, + ); + let mut msg: *mut libc::c_char = + 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.expect("non-null function pointer")( + context, + 2020i32, + contact_chat_id as uintptr_t, + 0i32 as uintptr_t, + ); + } + } + }; +} diff --git a/src/dc_simplify.rs b/src/dc_simplify.rs new file mode 100644 index 000000000..7463fb49e --- /dev/null +++ b/src/dc_simplify.rs @@ -0,0 +1,368 @@ +use libc; +extern "C" { + #[no_mangle] + fn calloc(_: libc::c_ulong, _: libc::c_ulong) -> *mut libc::c_void; + #[no_mangle] + fn free(_: *mut libc::c_void); + #[no_mangle] + fn exit(_: libc::c_int) -> !; + #[no_mangle] + fn strcmp(_: *const libc::c_char, _: *const libc::c_char) -> libc::c_int; + #[no_mangle] + fn strlen(_: *const libc::c_char) -> libc::c_ulong; + #[no_mangle] + fn strncmp(_: *const libc::c_char, _: *const libc::c_char, _: libc::c_ulong) -> libc::c_int; + #[no_mangle] + fn strndup(_: *const libc::c_char, _: libc::c_ulong) -> *mut libc::c_char; + /* string tools */ + #[no_mangle] + fn dc_strdup(_: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn dc_remove_cr_chars(_: *mut libc::c_char); + #[no_mangle] + fn dc_split_into_lines(buf_terminated: *const libc::c_char) -> *mut carray; + #[no_mangle] + fn dc_free_splitted_lines(lines: *mut carray); + #[no_mangle] + fn dc_strbuilder_init(_: *mut dc_strbuilder_t, init_bytes: libc::c_int); + #[no_mangle] + fn dc_strbuilder_cat(_: *mut dc_strbuilder_t, text: *const libc::c_char) -> *mut libc::c_char; + /* ** library-internal *********************************************************/ + #[no_mangle] + fn dc_dehtml(buf_terminated: *mut libc::c_char) -> *mut libc::c_char; +} +#[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; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_strbuilder { + pub buf: *mut libc::c_char, + pub allocated: libc::c_int, + pub free: libc::c_int, + pub eos: *mut libc::c_char, +} +pub type dc_strbuilder_t = _dc_strbuilder; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_simplify { + pub is_forwarded: libc::c_int, + pub is_cut_at_begin: libc::c_int, + pub is_cut_at_end: libc::c_int, +} +/* ** library-private **********************************************************/ +pub type dc_simplify_t = _dc_simplify; +#[inline] +unsafe extern "C" fn carray_count(mut array: *mut carray) -> libc::c_uint { + return (*array).len; +} +#[inline] +unsafe extern "C" fn carray_get( + mut array: *mut carray, + mut indx: libc::c_uint, +) -> *mut libc::c_void { + return *(*array).array.offset(indx as isize); +} +#[no_mangle] +pub unsafe extern "C" fn dc_simplify_new() -> *mut dc_simplify_t { + let mut simplify: *mut dc_simplify_t = 0 as *mut dc_simplify_t; + simplify = calloc( + 1i32 as libc::c_ulong, + ::std::mem::size_of::() as libc::c_ulong, + ) as *mut dc_simplify_t; + if simplify.is_null() { + exit(31i32); + } + return simplify; +} +#[no_mangle] +pub unsafe extern "C" 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 */ +#[no_mangle] +pub unsafe extern "C" fn dc_simplify_simplify( + mut simplify: *mut dc_simplify_t, + mut in_unterminated: *const libc::c_char, + mut in_bytes: libc::c_int, + mut is_html: libc::c_int, + 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; + if simplify.is_null() || in_unterminated.is_null() || in_bytes <= 0i32 { + return dc_strdup(b"\x00" as *const u8 as *const libc::c_char); + } + (*simplify).is_forwarded = 0i32; + (*simplify).is_cut_at_begin = 0i32; + (*simplify).is_cut_at_end = 0i32; + out = strndup( + in_unterminated as *mut libc::c_char, + in_bytes as libc::c_ulong, + ); + if out.is_null() { + return dc_strdup(b"\x00" as *const u8 as *const libc::c_char); + } + if 0 != is_html { + temp = dc_dehtml(out); + if !temp.is_null() { + free(out as *mut libc::c_void); + out = temp + } + } + dc_remove_cr_chars(out); + temp = dc_simplify_simplify_plain_text(simplify, out, is_msgrmsg); + if !temp.is_null() { + free(out as *mut libc::c_void); + out = temp + } + dc_remove_cr_chars(out); + return out; +} +/* ****************************************************************************** + * Simplify Plain Text + ******************************************************************************/ +unsafe extern "C" fn dc_simplify_simplify_plain_text( + mut simplify: *mut dc_simplify_t, + mut buf_terminated: *const libc::c_char, + mut is_msgrmsg: libc::c_int, +) -> *mut libc::c_char { + /* This function ... + ... removes all text after the line `-- ` (footer mark) + ... removes full quotes at the beginning and at the end of the text - + these are all lines starting with the character `>` + ... 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_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 footer_mark: libc::c_int = 0i32; + l = l_first; + while l <= l_last { + line = carray_get(lines, l as libc::c_uint) as *mut libc::c_char; + if strcmp(line, b"-- \x00" as *const u8 as *const libc::c_char) == 0i32 + || strcmp(line, b"-- \x00" as *const u8 as *const libc::c_char) == 0i32 + { + footer_mark = 1i32 + } + if strcmp(line, b"--\x00" as *const u8 as *const libc::c_char) == 0i32 + || strcmp(line, b"---\x00" as *const u8 as *const libc::c_char) == 0i32 + || strcmp(line, b"----\x00" as *const u8 as *const libc::c_char) == 0i32 + { + footer_mark = 1i32; + (*simplify).is_cut_at_end = 1i32 + } + if 0 != footer_mark { + l_last = l - 1i32; + /* done */ + break; + } else { + l += 1 + } + } + if l_last - l_first + 1i32 >= 3i32 { + let mut line0: *mut libc::c_char = + carray_get(lines, l_first as libc::c_uint) as *mut libc::c_char; + let mut line1: *mut libc::c_char = + carray_get(lines, (l_first + 1i32) as libc::c_uint) as *mut libc::c_char; + let mut line2: *mut libc::c_char = + carray_get(lines, (l_first + 2i32) as libc::c_uint) as *mut libc::c_char; + if strcmp( + line0, + b"---------- Forwarded message ----------\x00" as *const u8 as *const libc::c_char, + ) == 0i32 + && strncmp( + line1, + b"From: \x00" as *const u8 as *const libc::c_char, + 6i32 as libc::c_ulong, + ) == 0i32 + && *line2.offset(0isize) as libc::c_int == 0i32 + { + (*simplify).is_forwarded = 1i32; + l_first += 3i32 + } + } + l = l_first; + while l <= l_last { + line = carray_get(lines, l as libc::c_uint) as *mut libc::c_char; + if strncmp( + line, + b"-----\x00" as *const u8 as *const libc::c_char, + 5i32 as libc::c_ulong, + ) == 0i32 + || strncmp( + line, + b"_____\x00" as *const u8 as *const libc::c_char, + 5i32 as libc::c_ulong, + ) == 0i32 + || strncmp( + line, + b"=====\x00" as *const u8 as *const libc::c_char, + 5i32 as libc::c_ulong, + ) == 0i32 + || strncmp( + line, + b"*****\x00" as *const u8 as *const libc::c_char, + 5i32 as libc::c_ulong, + ) == 0i32 + || strncmp( + line, + b"~~~~~\x00" as *const u8 as *const libc::c_char, + 5i32 as libc::c_ulong, + ) == 0i32 + { + l_last = l - 1i32; + (*simplify).is_cut_at_end = 1i32; + /* done */ + break; + } else { + l += 1 + } + } + if 0 == is_msgrmsg { + let mut l_lastQuotedLine: libc::c_int = -1i32; + l = l_last; + while l >= l_first { + line = carray_get(lines, l as libc::c_uint) as *mut libc::c_char; + if 0 != is_plain_quote(line) { + l_lastQuotedLine = l + } else if 0 == is_empty_line(line) { + break; + } + l -= 1 + } + if l_lastQuotedLine != -1i32 { + l_last = l_lastQuotedLine - 1i32; + (*simplify).is_cut_at_end = 1i32; + if l_last > 0i32 { + if 0 != is_empty_line(carray_get(lines, l_last as libc::c_uint) as *mut libc::c_char) + { + l_last -= 1 + } + } + if l_last > 0i32 { + line = carray_get(lines, l_last as libc::c_uint) as *mut libc::c_char; + if 0 != is_quoted_headline(line) { + l_last -= 1 + } + } + } + } + if 0 == is_msgrmsg { + let mut l_lastQuotedLine_0: libc::c_int = -1i32; + let mut hasQuotedHeadline: libc::c_int = 0i32; + l = l_first; + while l <= l_last { + line = carray_get(lines, l as libc::c_uint) as *mut libc::c_char; + if 0 != is_plain_quote(line) { + l_lastQuotedLine_0 = l + } else if 0 == is_empty_line(line) { + if 0 != is_quoted_headline(line) + && 0 == hasQuotedHeadline + && l_lastQuotedLine_0 == -1i32 + { + hasQuotedHeadline = 1i32 + } else { + /* non-quoting line found */ + break; + } + } + l += 1 + } + if l_lastQuotedLine_0 != -1i32 { + l_first = l_lastQuotedLine_0 + 1i32; + (*simplify).is_cut_at_begin = 1i32 + } + } + /* re-create buffer from the remaining lines */ + let mut ret: dc_strbuilder_t = _dc_strbuilder { + buf: 0 as *mut libc::c_char, + allocated: 0, + free: 0, + eos: 0 as *mut libc::c_char, + }; + dc_strbuilder_init(&mut ret, strlen(buf_terminated) as libc::c_int); + if 0 != (*simplify).is_cut_at_begin { + dc_strbuilder_cat(&mut ret, b"[...] \x00" as *const u8 as *const libc::c_char); + } + /* we write empty lines only in case and non-empty line follows */ + let mut pending_linebreaks: libc::c_int = 0i32; + let mut content_lines_added: libc::c_int = 0i32; + l = l_first; + while l <= l_last { + line = carray_get(lines, l as libc::c_uint) as *mut libc::c_char; + if 0 != is_empty_line(line) { + pending_linebreaks += 1 + } else { + if 0 != content_lines_added { + if pending_linebreaks > 2i32 { + pending_linebreaks = 2i32 + } + while 0 != pending_linebreaks { + dc_strbuilder_cat(&mut ret, b"\n\x00" as *const u8 as *const libc::c_char); + pending_linebreaks -= 1 + } + } + dc_strbuilder_cat(&mut ret, line); + content_lines_added += 1; + pending_linebreaks = 1i32 + } + l += 1 + } + if 0 != (*simplify).is_cut_at_end + && (0 == (*simplify).is_cut_at_begin || 0 != content_lines_added) + { + dc_strbuilder_cat(&mut ret, b" [...]\x00" as *const u8 as *const libc::c_char); + } + dc_free_splitted_lines(lines); + return ret.buf; +} +/* ****************************************************************************** + * Tools + ******************************************************************************/ +unsafe extern "C" 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; + while 0 != *p1 { + if *p1 as libc::c_int > ' ' as i32 { + return 0i32; + } + p1 = p1.offset(1isize) + } + return 1i32; +} +unsafe extern "C" 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. + - Currently, we simply check if the last character is a ':'. + - Checking for the existance of an email address may fail (headlines may show the user's name instead of the address) */ + let mut buf_len: libc::c_int = strlen(buf) as libc::c_int; + if buf_len > 80i32 { + return 0i32; + } + if buf_len > 0i32 && *buf.offset((buf_len - 1i32) as isize) as libc::c_int == ':' as i32 { + return 1i32; + } + return 0i32; +} +unsafe extern "C" 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; +} diff --git a/src/dc_smtp.rs b/src/dc_smtp.rs new file mode 100644 index 000000000..43ea2201b --- /dev/null +++ b/src/dc_smtp.rs @@ -0,0 +1,1435 @@ +use c2rust_bitfields::BitfieldStruct; +use libc; +extern "C" { + pub type mailstream_cancel; + pub type sqlite3; + #[no_mangle] + fn gethostname(_: *mut libc::c_char, _: size_t) -> libc::c_int; + #[no_mangle] + fn mailsmtp_socket_connect( + session: *mut mailsmtp, + server: *const libc::c_char, + port: uint16_t, + ) -> libc::c_int; + #[no_mangle] + fn mailsmtp_socket_starttls(session: *mut mailsmtp) -> libc::c_int; + #[no_mangle] + fn mailsmtp_ssl_connect( + session: *mut mailsmtp, + server: *const libc::c_char, + port: uint16_t, + ) -> libc::c_int; + #[no_mangle] + fn mailsmtp_oauth2_authenticate( + session: *mut mailsmtp, + auth_user: *const libc::c_char, + access_token: *const libc::c_char, + ) -> libc::c_int; + #[no_mangle] + fn mailsmtp_new( + progr_rate: size_t, + progr_fun: Option ()>, + ) -> *mut mailsmtp; + #[no_mangle] + fn mailsmtp_free(session: *mut mailsmtp); + #[no_mangle] + fn mailsmtp_set_timeout(session: *mut mailsmtp, timeout: time_t); + #[no_mangle] + fn mailsmtp_auth( + session: *mut mailsmtp, + user: *const libc::c_char, + pass: *const libc::c_char, + ) -> libc::c_int; + #[no_mangle] + fn mailsmtp_helo(session: *mut mailsmtp) -> libc::c_int; + #[no_mangle] + fn mailsmtp_mail(session: *mut mailsmtp, from: *const libc::c_char) -> libc::c_int; + #[no_mangle] + fn mailsmtp_rcpt(session: *mut mailsmtp, to: *const libc::c_char) -> libc::c_int; + #[no_mangle] + fn mailsmtp_data(session: *mut mailsmtp) -> libc::c_int; + #[no_mangle] + fn mailsmtp_data_message( + session: *mut mailsmtp, + message: *const libc::c_char, + size: size_t, + ) -> libc::c_int; + #[no_mangle] + fn mailesmtp_ehlo(session: *mut mailsmtp) -> libc::c_int; + #[no_mangle] + fn mailesmtp_mail( + session: *mut mailsmtp, + from: *const libc::c_char, + return_full: libc::c_int, + envid: *const libc::c_char, + ) -> libc::c_int; + #[no_mangle] + fn mailesmtp_rcpt( + session: *mut mailsmtp, + to: *const libc::c_char, + notify: libc::c_int, + orcpt: *const libc::c_char, + ) -> libc::c_int; + #[no_mangle] + fn mailsmtp_strerror(errnum: libc::c_int) -> *const libc::c_char; + #[no_mangle] + 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; + #[no_mangle] + fn mailsmtp_set_progress_callback( + session: *mut mailsmtp, + progr_fun: Option ()>, + context: *mut libc::c_void, + ); + #[no_mangle] + fn calloc(_: libc::c_ulong, _: libc::c_ulong) -> *mut libc::c_void; + #[no_mangle] + fn free(_: *mut libc::c_void); + #[no_mangle] + fn exit(_: libc::c_int) -> !; + /* string tools */ + #[no_mangle] + fn dc_strdup(_: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn dc_mprintf(format: *const libc::c_char, _: ...) -> *mut libc::c_char; + #[no_mangle] + fn dc_log_event( + _: *mut dc_context_t, + event_code: libc::c_int, + data1: libc::c_int, + msg: *const libc::c_char, + _: ... + ); + #[no_mangle] + fn dc_log_event_seq( + _: *mut dc_context_t, + event_code: libc::c_int, + sequence_start: *mut libc::c_int, + msg: *const libc::c_char, + _: ... + ); + #[no_mangle] + fn dc_log_error(_: *mut dc_context_t, data1: libc::c_int, msg: *const libc::c_char, _: ...); + #[no_mangle] + fn dc_log_info(_: *mut dc_context_t, data1: libc::c_int, msg: *const libc::c_char, _: ...); + // the following function may block due http-requests; + // must not be called from the main thread or by the ui! + #[no_mangle] + fn dc_get_oauth2_access_token( + _: *mut dc_context_t, + addr: *const libc::c_char, + code: *const libc::c_char, + flags: libc::c_int, + ) -> *mut libc::c_char; + #[no_mangle] + fn dc_log_warning(_: *mut dc_context_t, data1: libc::c_int, msg: *const libc::c_char, _: ...); +} +pub type __darwin_size_t = libc::c_ulong; +pub type __darwin_ssize_t = libc::c_long; +pub type __darwin_time_t = libc::c_long; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_cond_t { + pub __sig: libc::c_long, + pub __opaque: [libc::c_char; 40], +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_mutex_t { + pub __sig: libc::c_long, + pub __opaque: [libc::c_char; 56], +} +pub type __darwin_pthread_cond_t = _opaque_pthread_cond_t; +pub type __darwin_pthread_mutex_t = _opaque_pthread_mutex_t; +pub type size_t = __darwin_size_t; +pub type uint32_t = libc::c_uint; +pub type uintptr_t = libc::c_ulong; +pub type ssize_t = __darwin_ssize_t; +pub type time_t = __darwin_time_t; +pub type pthread_cond_t = __darwin_pthread_cond_t; +pub type pthread_mutex_t = __darwin_pthread_mutex_t; +pub type uint8_t = libc::c_uchar; +pub type uint16_t = libc::c_ushort; +#[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; +#[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) -> (); +#[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; +pub type unnamed = libc::c_uint; +pub const MAILSMTP_ERROR_CLIENTID_NOT_SUPPORTED: unnamed = 28; +pub const MAILSMTP_ERROR_SSL: unnamed = 27; +pub const MAILSMTP_ERROR_AUTH_AUTHENTICATION_FAILED: unnamed = 26; +pub const MAILSMTP_ERROR_CONNECTION_REFUSED: unnamed = 25; +pub const MAILSMTP_ERROR_STARTTLS_NOT_SUPPORTED: unnamed = 24; +pub const MAILSMTP_ERROR_STARTTLS_TEMPORARY_FAILURE: unnamed = 23; +pub const MAILSMTP_ERROR_AUTH_ENCRYPTION_REQUIRED: unnamed = 22; +pub const MAILSMTP_ERROR_AUTH_TEMPORARY_FAILTURE: unnamed = 21; +pub const MAILSMTP_ERROR_AUTH_TRANSITION_NEEDED: unnamed = 20; +pub const MAILSMTP_ERROR_AUTH_TOO_WEAK: unnamed = 19; +pub const MAILSMTP_ERROR_AUTH_REQUIRED: unnamed = 18; +pub const MAILSMTP_ERROR_AUTH_LOGIN: unnamed = 17; +pub const MAILSMTP_ERROR_AUTH_NOT_SUPPORTED: unnamed = 16; +pub const MAILSMTP_ERROR_MEMORY: unnamed = 15; +pub const MAILSMTP_ERROR_TRANSACTION_FAILED: unnamed = 14; +pub const MAILSMTP_ERROR_USER_NOT_LOCAL: unnamed = 13; +pub const MAILSMTP_ERROR_BAD_SEQUENCE_OF_COMMAND: unnamed = 12; +pub const MAILSMTP_ERROR_MAILBOX_NAME_NOT_ALLOWED: unnamed = 11; +pub const MAILSMTP_ERROR_MAILBOX_UNAVAILABLE: unnamed = 10; +pub const MAILSMTP_ERROR_INSUFFICIENT_SYSTEM_STORAGE: unnamed = 9; +pub const MAILSMTP_ERROR_IN_PROCESSING: unnamed = 8; +pub const MAILSMTP_ERROR_EXCEED_STORAGE_ALLOCATION: unnamed = 7; +pub const MAILSMTP_ERROR_ACTION_NOT_TAKEN: unnamed = 6; +pub const MAILSMTP_ERROR_NOT_IMPLEMENTED: unnamed = 5; +pub const MAILSMTP_ERROR_HOSTNAME: unnamed = 4; +pub const MAILSMTP_ERROR_STREAM: unnamed = 3; +pub const MAILSMTP_ERROR_SERVICE_NOT_AVAILABLE: unnamed = 2; +pub const MAILSMTP_ERROR_UNEXPECTED_CODE: unnamed = 1; +pub const MAILSMTP_NO_ERROR: unnamed = 0; +pub type unnamed_0 = libc::c_uint; +pub const MAILSMTP_AUTH_KERBEROS_V4: unnamed_0 = 256; +pub const MAILSMTP_AUTH_NTLM: unnamed_0 = 128; +pub const MAILSMTP_AUTH_SRP: unnamed_0 = 64; +pub const MAILSMTP_AUTH_GSSAPI: unnamed_0 = 32; +pub const MAILSMTP_AUTH_DIGEST_MD5: unnamed_0 = 16; +pub const MAILSMTP_AUTH_LOGIN: unnamed_0 = 8; +pub const MAILSMTP_AUTH_PLAIN: unnamed_0 = 4; +pub const MAILSMTP_AUTH_CRAM_MD5: unnamed_0 = 2; +pub const MAILSMTP_AUTH_CHECKED: unnamed_0 = 1; +pub const MAILSMTP_AUTH_NOT_CHECKED: unnamed_0 = 0; +#[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_1, + 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_1 { + 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_capability_data { + pub cap_list: *mut clist, +} +#[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_2, + 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_2 { + 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 extern "C" 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_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, +} +#[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_3, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed_3 { + pub ft_fetch_att: *mut mailimap_fetch_att, + pub ft_fetch_att_list: *mut clist, +} +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_4, + 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 unnamed_4 { + 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, +} +/* define DC_USE_RPGP to enable use of rPGP instead of netpgp where available; +preferrably, this should be done in the project configuration currently */ +//#define DC_USE_RPGP 1 +/* Includes that are used frequently. This file may also be used to create predefined headers. */ +/* * Structure behind dc_context_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_context { + pub magic: uint32_t, + pub userdata: *mut libc::c_void, + pub dbfile: *mut libc::c_char, + pub blobdir: *mut libc::c_char, + pub sql: *mut dc_sqlite3_t, + pub inbox: *mut dc_imap_t, + pub inboxidle_condmutex: pthread_mutex_t, + pub perform_inbox_jobs_needed: libc::c_int, + pub probe_imap_network: libc::c_int, + pub sentbox_thread: dc_jobthread_t, + pub mvbox_thread: dc_jobthread_t, + pub smtp: *mut dc_smtp_t, + pub smtpidle_cond: pthread_cond_t, + pub smtpidle_condmutex: pthread_mutex_t, + pub smtpidle_condflag: libc::c_int, + pub smtp_suspended: libc::c_int, + pub smtp_doing_jobs: libc::c_int, + pub perform_smtp_jobs_needed: libc::c_int, + pub probe_smtp_network: libc::c_int, + pub oauth2_critical: pthread_mutex_t, + 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 type dc_lot_t = _dc_lot; +/* * Structure behind dc_lot_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_lot { + pub magic: uint32_t, + pub text1_meaning: libc::c_int, + pub text1: *mut libc::c_char, + pub text2: *mut libc::c_char, + pub timestamp: time_t, + pub state: libc::c_int, + pub id: uint32_t, + pub fingerprint: *mut libc::c_char, + pub invitenumber: *mut libc::c_char, + pub auth: *mut libc::c_char, +} +/* * + * 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 = Option< + unsafe extern "C" fn( + _: *mut dc_context_t, + _: libc::c_int, + _: uintptr_t, + _: uintptr_t, + ) -> uintptr_t, +>; +/* * + * @mainpage Getting started + * + * This document describes how to handle the Delta Chat core library. + * For general information about Delta Chat itself, + * see and . + * + * Let's start. + * + * First of all, you have to **define an event-handler-function** + * that is called by the library on specific events + * (eg. when the configuration is done or when fresh messages arrive). + * With this function you can create a Delta Chat context then: + * + * ~~~ + * #include + * + * uintptr_t event_handler_func(dc_context_t* context, int event, + * uintptr_t data1, uintptr_t data2) + * { + * return 0; // for unhandled events, it is always safe to return 0 + * } + * + * dc_context_t* context = dc_context_new(event_handler_func, NULL, NULL); + * ~~~ + * + * After that, you should make sure, + * sending and receiving jobs are processed as needed. + * For this purpose, you have to **create two threads:** + * + * ~~~ + * #include + * + * void* imap_thread_func(void* context) + * { + * while (true) { + * dc_perform_imap_jobs(context); + * dc_perform_imap_fetch(context); + * dc_perform_imap_idle(context); + * } + * } + * + * void* smtp_thread_func(void* context) + * { + * while (true) { + * dc_perform_smtp_jobs(context); + * dc_perform_smtp_idle(context); + * } + * } + * + * static pthread_t imap_thread, smtp_thread; + * pthread_create(&imap_thread, NULL, imap_thread_func, context); + * pthread_create(&smtp_thread, NULL, smtp_thread_func, context); + * ~~~ + * + * The example above uses "pthreads", + * however, you can also use anything else for thread handling. + * NB: The deltachat-core library itself does not create any threads on its own, + * however, functions, unless stated otherwise, are thread-safe. + * + * After that you can **define and open a database.** + * The database is a normal sqlite-file and is created as needed: + * + * ~~~ + * dc_open(context, "example.db", NULL); + * ~~~ + * + * Now you can **configure the context:** + * + * ~~~ + * // use some real test credentials here + * dc_set_config(context, "addr", "alice@example.org"); + * dc_set_config(context, "mail_pw", "***"); + * dc_configure(context); + * ~~~ + * + * dc_configure() returns immediately, the configuration itself may take a while + * and is done by a job in the imap-thread you've defined above. + * Once done, the #DC_EVENT_CONFIGURE_PROGRESS reports success + * to the event_handler_func() that is also defined above. + * + * The configuration result is saved in the database, + * on subsequent starts it is not needed to call dc_configure() + * (you can check this using dc_is_configured()). + * + * Now you can **send the first message:** + * + * ~~~ + * // use a real testing address here + * uint32_t contact_id = dc_create_contact(context, NULL, "bob@example.org"); + * uint32_t chat_id = dc_create_chat_by_contact_id(context, contact_id); + * + * dc_send_text_msg(context, chat_id, "Hi, here is my first message!"); + * ~~~ + * + * dc_send_text_msg() returns immediately; + * the sending itself is done by a job in the smtp-thread you've defined above. + * If you check the testing address (bob) + * and you should have received a normal email. + * Answer this email in any email program with "Got it!" + * and the imap-thread you've create above will **receive the message**. + * + * You can then **list all messages** of a chat as follow: + * + * ~~~ + * dc_array_t* msglist = dc_get_chat_msgs(context, chat_id, 0, 0); + * for (int i = 0; i < dc_array_get_cnt(msglist); i++) + * { + * uint32_t msg_id = dc_array_get_id(msglist, i); + * dc_msg_t* msg = dc_get_msg(context, msg_id); + * char* text = dc_msg_get_text(msg); + * + * printf("Message %i: %s\n", i+1, text); + * + * free(text); + * dc_msg_unref(msg); + * } + * dc_array_unref(msglist); + * ~~~ + * + * This will output the following two lines: + * + * ~~~ + * Message 1: Hi, here is my first message! + * Message 2: Got it! + * ~~~ + * + * + * ## Class reference + * + * For a class reference, see the "Classes" link atop. + * + * + * ## Further hints + * + * Here are some additional, unsorted hints that may be useful. + * + * - For `get`-functions, you have to unref the return value in some way. + * + * - Strings in function arguments or return values are usually UTF-8 encoded. + * + * - The issue-tracker for the core library is here: + * + * + * The following points are important mainly + * for the authors of the library itself: + * + * - For indentation, use tabs. + * Alignments that are not placed at the beginning of a line + * should be done with spaces. + * + * - For padding between functions, + * classes etc. use 2 empty lines + * + * - Source files are encoded as UTF-8 with Unix line endings + * (a simple `LF`, `0x0A` or `\n`) + * + * If you need further assistance, + * please do not hesitate to contact us + * through the channels shown at https://delta.chat/en/contribute + * + * Please keep in mind, that your derived work + * must respect the Mozilla Public License 2.0 of libdeltachat + * and the respective licenses of the libraries libdeltachat links with. + * + * See you. + */ +/* * + * @class dc_context_t + * + * An object representing a single account. + * + * Each account is linked to an IMAP/SMTP account and uses a separate + * SQLite database for offline functionality and for account-related + * settings. + */ +pub type dc_context_t = _dc_context; +/* ** library-private **********************************************************/ +pub type dc_smtp_t = _dc_smtp; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_smtp { + 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 error: *mut libc::c_char, + pub error_etpan: libc::c_int, +} +pub type dc_jobthread_t = _dc_jobthread; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_jobthread { + 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, + 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, +} +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_imap { + 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 type dc_receive_imf_t = Option< + unsafe extern "C" 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_imap_t = _dc_imap; +pub type dc_precheck_imf_t = Option< + unsafe extern "C" 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< + unsafe extern "C" fn(_: *mut dc_imap_t, _: *const libc::c_char, _: *const libc::c_char) -> (), +>; +pub type dc_get_config_t = Option< + unsafe extern "C" fn( + _: *mut dc_imap_t, + _: *const libc::c_char, + _: *const libc::c_char, + ) -> *mut libc::c_char, +>; +/* ** library-private **********************************************************/ +pub type dc_sqlite3_t = _dc_sqlite3; +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_sqlite3 { + pub cobj: *mut sqlite3, + pub context: *mut dc_context_t, +} +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_loginparam { + pub addr: *mut libc::c_char, + pub mail_server: *mut libc::c_char, + pub mail_user: *mut libc::c_char, + pub mail_pw: *mut libc::c_char, + pub mail_port: uint16_t, + pub send_server: *mut libc::c_char, + pub send_user: *mut libc::c_char, + pub send_pw: *mut libc::c_char, + pub send_port: libc::c_int, + pub server_flags: libc::c_int, +} +pub type dc_loginparam_t = _dc_loginparam; +#[no_mangle] +pub unsafe extern "C" 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( + 1i32 as libc::c_ulong, + ::std::mem::size_of::() as libc::c_ulong, + ) as *mut dc_smtp_t; + if smtp.is_null() { + exit(29i32); + } + (*smtp).log_connect_errors = 1i32; + (*smtp).context = context; + return smtp; +} +#[no_mangle] +pub unsafe extern "C" fn dc_smtp_unref(mut smtp: *mut dc_smtp_t) { + if smtp.is_null() { + return; + } + 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); +} +#[no_mangle] +pub unsafe extern "C" fn dc_smtp_disconnect(mut smtp: *mut dc_smtp_t) { + if smtp.is_null() { + return; + } + if !(*smtp).etpan.is_null() { + mailsmtp_free((*smtp).etpan); + (*smtp).etpan = 0 as *mut mailsmtp + }; +} +#[no_mangle] +pub unsafe extern "C" 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 + }; +} +#[no_mangle] +pub unsafe extern "C" 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, + 401i32, + &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, + ); + } 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, + 401i32, + &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, + 401i32, + &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, + 401i32, + &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, + 401i32, + &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, + 401i32, + &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]>() + as libc::c_ulong, + ); + 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, + 401i32, + &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, + 101i32, + 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( + mut current: size_t, + mut maximum: size_t, + mut user_data: *mut libc::c_void, +) { +} +#[no_mangle] +pub unsafe extern "C" 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 == 0i32 as libc::c_ulong + { + 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, + ); + current_block = 5498835644851925448; + break; + } else { + iter = if !iter.is_null() { + (*iter).next + } else { + 0 as *mut clistcell_s + } + } + } + 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, + 103i32, + 0i32, + b"Message was sent to SMTP server\x00" as *const u8 + as *const libc::c_char, + ); + success = 1i32 + } + } + } + } + } + } + } + return success; +} +unsafe extern "C" 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 new file mode 100644 index 000000000..297a89b7e --- /dev/null +++ b/src/dc_sqlite3.rs @@ -0,0 +1,2555 @@ +use c2rust_bitfields::BitfieldStruct; +use libc; +extern "C" { + pub type _telldir; + pub type mailstream_cancel; + pub type sqlite3; + pub type sqlite3_stmt; + #[no_mangle] + fn __assert_rtn( + _: *const libc::c_char, + _: *const libc::c_char, + _: libc::c_int, + _: *const libc::c_char, + ) -> !; + #[no_mangle] + fn closedir(_: *mut DIR) -> libc::c_int; + #[no_mangle] + fn opendir(_: *const libc::c_char) -> *mut DIR; + #[no_mangle] + fn readdir(_: *mut DIR) -> *mut dirent; + #[no_mangle] + fn stat(_: *const libc::c_char, _: *mut stat) -> libc::c_int; + #[no_mangle] + fn calloc(_: libc::c_ulong, _: libc::c_ulong) -> *mut libc::c_void; + #[no_mangle] + fn free(_: *mut libc::c_void); + #[no_mangle] + fn atol(_: *const libc::c_char) -> libc::c_long; + #[no_mangle] + fn exit(_: libc::c_int) -> !; + #[no_mangle] + fn strcmp(_: *const libc::c_char, _: *const libc::c_char) -> libc::c_int; + #[no_mangle] + fn strlen(_: *const libc::c_char) -> libc::c_ulong; + #[no_mangle] + fn strncmp(_: *const libc::c_char, _: *const libc::c_char, _: libc::c_ulong) -> libc::c_int; + #[no_mangle] + fn time(_: *mut time_t) -> time_t; + #[no_mangle] + fn sscanf(_: *const libc::c_char, _: *const libc::c_char, _: ...) -> libc::c_int; + #[no_mangle] + fn sqlite3_threadsafe() -> libc::c_int; + #[no_mangle] + fn sqlite3_close(_: *mut sqlite3) -> libc::c_int; + #[no_mangle] + fn sqlite3_busy_timeout(_: *mut sqlite3, ms: libc::c_int) -> libc::c_int; + #[no_mangle] + fn sqlite3_mprintf(_: *const libc::c_char, _: ...) -> *mut libc::c_char; + #[no_mangle] + fn sqlite3_vmprintf(_: *const libc::c_char, _: ::std::ffi::VaList) -> *mut libc::c_char; + #[no_mangle] + fn sqlite3_free(_: *mut libc::c_void); + #[no_mangle] + fn sqlite3_open_v2( + filename: *const libc::c_char, + ppDb: *mut *mut sqlite3, + flags: libc::c_int, + zVfs: *const libc::c_char, + ) -> libc::c_int; + #[no_mangle] + fn sqlite3_errmsg(_: *mut sqlite3) -> *const libc::c_char; + #[no_mangle] + fn sqlite3_prepare_v2( + db: *mut sqlite3, + zSql: *const libc::c_char, + nByte: libc::c_int, + ppStmt: *mut *mut sqlite3_stmt, + pzTail: *mut *const libc::c_char, + ) -> libc::c_int; + #[no_mangle] + fn sqlite3_bind_text( + _: *mut sqlite3_stmt, + _: libc::c_int, + _: *const libc::c_char, + _: libc::c_int, + _: Option ()>, + ) -> libc::c_int; + #[no_mangle] + fn sqlite3_step(_: *mut sqlite3_stmt) -> libc::c_int; + #[no_mangle] + fn sqlite3_column_int(_: *mut sqlite3_stmt, iCol: libc::c_int) -> libc::c_int; + #[no_mangle] + fn sqlite3_column_text(_: *mut sqlite3_stmt, iCol: libc::c_int) -> *const libc::c_uchar; + #[no_mangle] + fn sqlite3_finalize(pStmt: *mut sqlite3_stmt) -> libc::c_int; + #[no_mangle] + fn dc_log_info(_: *mut dc_context_t, data1: libc::c_int, msg: *const libc::c_char, _: ...); + #[no_mangle] + fn dc_log_error(_: *mut dc_context_t, data1: libc::c_int, msg: *const libc::c_char, _: ...); + #[no_mangle] + fn dc_strdup_keep_null(_: *const libc::c_char) -> *mut libc::c_char; + /* string tools */ + #[no_mangle] + fn dc_strdup(_: *const libc::c_char) -> *mut libc::c_char; + /* file tools */ + #[no_mangle] + fn dc_ensure_no_slash(pathNfilename: *mut libc::c_char); + #[no_mangle] + fn dc_apeerstate_new(_: *mut dc_context_t) -> *mut dc_apeerstate_t; + #[no_mangle] + fn dc_apeerstate_unref(_: *mut dc_apeerstate_t); + #[no_mangle] + fn dc_apeerstate_save_to_db( + _: *const dc_apeerstate_t, + _: *mut dc_sqlite3_t, + create: libc::c_int, + ) -> libc::c_int; + #[no_mangle] + fn dc_apeerstate_recalc_fingerprint(_: *mut dc_apeerstate_t) -> libc::c_int; + #[no_mangle] + fn dc_apeerstate_load_by_addr( + _: *mut dc_apeerstate_t, + _: *mut dc_sqlite3_t, + addr: *const libc::c_char, + ) -> libc::c_int; + #[no_mangle] + fn dc_mprintf(format: *const libc::c_char, _: ...) -> *mut libc::c_char; + #[no_mangle] + fn dc_log_warning(_: *mut dc_context_t, data1: libc::c_int, msg: *const libc::c_char, _: ...); + #[no_mangle] + fn dc_hash_clear(_: *mut dc_hash_t); + #[no_mangle] + fn dc_delete_file(_: *mut dc_context_t, pathNFilename: *const libc::c_char) -> libc::c_int; + #[no_mangle] + fn dc_hash_find( + _: *const dc_hash_t, + pKey: *const libc::c_void, + nKey: libc::c_int, + ) -> *mut libc::c_void; + #[no_mangle] + fn dc_hash_insert( + _: *mut dc_hash_t, + pKey: *const libc::c_void, + nKey: libc::c_int, + pData: *mut libc::c_void, + ) -> *mut libc::c_void; + /* library-private */ + #[no_mangle] + fn dc_param_new() -> *mut dc_param_t; + #[no_mangle] + fn dc_param_unref(_: *mut dc_param_t); + #[no_mangle] + fn dc_param_get( + _: *const dc_param_t, + key: libc::c_int, + def: *const libc::c_char, + ) -> *mut libc::c_char; + #[no_mangle] + fn dc_param_set_packed(_: *mut dc_param_t, _: *const libc::c_char); + /* + * There are 4 different modes of operation for a hash table: + * + * DC_HASH_INT nKey is used as the key and pKey is ignored. + * + * DC_HASH_POINTER pKey is used as the key and nKey is ignored. + * + * DC_HASH_STRING pKey points to a string that is nKey bytes long + * (including the null-terminator, if any). Case + * is ignored in comparisons. + * + * DC_HASH_BINARY pKey points to binary data nKey bytes long. + * memcmp() is used to compare keys. + * + * A copy of the key is made for DC_HASH_STRING and DC_HASH_BINARY + * if the copyKey parameter to dc_hash_init() is 1. + */ + /* + * Just to make the last parameter of dc_hash_init() more readable. + */ + /* + * Access routines. To delete an element, insert a NULL pointer. + */ + #[no_mangle] + fn dc_hash_init(_: *mut dc_hash_t, keytype: libc::c_int, copyKey: 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 __uint8_t = libc::c_uchar; +pub type __uint16_t = libc::c_ushort; +pub type __int32_t = libc::c_int; +pub type __uint32_t = libc::c_uint; +pub type __int64_t = libc::c_longlong; +pub type __uint64_t = libc::c_ulonglong; +pub type __darwin_size_t = libc::c_ulong; +pub type __darwin_va_list = __builtin_va_list; +pub type __darwin_ssize_t = libc::c_long; +pub type __darwin_time_t = libc::c_long; +pub type __darwin_blkcnt_t = __int64_t; +pub type __darwin_blksize_t = __int32_t; +pub type __darwin_dev_t = __int32_t; +pub type __darwin_gid_t = __uint32_t; +pub type __darwin_ino64_t = __uint64_t; +pub type __darwin_mode_t = __uint16_t; +pub type __darwin_off_t = __int64_t; +pub type __darwin_uid_t = __uint32_t; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_cond_t { + pub __sig: libc::c_long, + pub __opaque: [libc::c_char; 40], +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_mutex_t { + pub __sig: libc::c_long, + pub __opaque: [libc::c_char; 56], +} +pub type __darwin_pthread_cond_t = _opaque_pthread_cond_t; +pub type __darwin_pthread_mutex_t = _opaque_pthread_mutex_t; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct dirent { + pub d_ino: __uint64_t, + pub d_seekoff: __uint64_t, + pub d_reclen: __uint16_t, + pub d_namlen: __uint16_t, + pub d_type: __uint8_t, + pub d_name: [libc::c_char; 1024], +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct DIR { + pub __dd_fd: libc::c_int, + pub __dd_loc: libc::c_long, + pub __dd_size: libc::c_long, + pub __dd_buf: *mut libc::c_char, + pub __dd_len: libc::c_int, + pub __dd_seek: libc::c_long, + pub __padding: libc::c_long, + pub __dd_flags: libc::c_int, + pub __dd_lock: __darwin_pthread_mutex_t, + pub __dd_td: *mut _telldir, +} +pub type int32_t = libc::c_int; +pub type int64_t = libc::c_longlong; +pub type uintptr_t = libc::c_ulong; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct timespec { + pub tv_sec: __darwin_time_t, + pub tv_nsec: libc::c_long, +} +pub type blkcnt_t = __darwin_blkcnt_t; +pub type blksize_t = __darwin_blksize_t; +pub type dev_t = __darwin_dev_t; +pub type mode_t = __darwin_mode_t; +pub type nlink_t = __uint16_t; +pub type uid_t = __darwin_uid_t; +pub type gid_t = __darwin_gid_t; +pub type off_t = __darwin_off_t; +pub type time_t = __darwin_time_t; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct stat { + pub st_dev: dev_t, + pub st_mode: mode_t, + pub st_nlink: nlink_t, + pub st_ino: __darwin_ino64_t, + pub st_uid: uid_t, + pub st_gid: gid_t, + pub st_rdev: dev_t, + pub st_atimespec: timespec, + pub st_mtimespec: timespec, + pub st_ctimespec: timespec, + pub st_birthtimespec: timespec, + pub st_size: off_t, + pub st_blocks: blkcnt_t, + pub st_blksize: blksize_t, + pub st_flags: __uint32_t, + pub st_gen: __uint32_t, + pub st_lspare: __int32_t, + pub st_qspare: [__int64_t; 2], +} +pub type size_t = __darwin_size_t; +pub type uint8_t = libc::c_uchar; +pub type uint32_t = libc::c_uint; +pub type uint64_t = libc::c_ulonglong; +pub type ssize_t = __darwin_ssize_t; +pub type pthread_cond_t = __darwin_pthread_cond_t; +pub type pthread_mutex_t = __darwin_pthread_mutex_t; +#[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; +#[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) -> (); +#[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 va_list = __darwin_va_list; +#[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, + 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 { + 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_capability_data { + pub cap_list: *mut clist, +} +#[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_0, + 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_0 { + 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 extern "C" 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_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, +} +#[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_1, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed_1 { + pub ft_fetch_att: *mut mailimap_fetch_att, + pub ft_fetch_att_list: *mut clist, +} +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 unnamed_2 { + 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, +} +/* define DC_USE_RPGP to enable use of rPGP instead of netpgp where available; +preferrably, this should be done in the project configuration currently */ +//#define DC_USE_RPGP 1 +/* Includes that are used frequently. This file may also be used to create predefined headers. */ +/* * Structure behind dc_context_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_context { + pub magic: uint32_t, + pub userdata: *mut libc::c_void, + pub dbfile: *mut libc::c_char, + pub blobdir: *mut libc::c_char, + pub sql: *mut dc_sqlite3_t, + pub inbox: *mut dc_imap_t, + pub inboxidle_condmutex: pthread_mutex_t, + pub perform_inbox_jobs_needed: libc::c_int, + pub probe_imap_network: libc::c_int, + pub sentbox_thread: dc_jobthread_t, + pub mvbox_thread: dc_jobthread_t, + pub smtp: *mut dc_smtp_t, + pub smtpidle_cond: pthread_cond_t, + pub smtpidle_condmutex: pthread_mutex_t, + pub smtpidle_condflag: libc::c_int, + pub smtp_suspended: libc::c_int, + pub smtp_doing_jobs: libc::c_int, + pub perform_smtp_jobs_needed: libc::c_int, + pub probe_smtp_network: libc::c_int, + pub oauth2_critical: pthread_mutex_t, + 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 type dc_lot_t = _dc_lot; +/* * Structure behind dc_lot_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_lot { + pub magic: uint32_t, + pub text1_meaning: libc::c_int, + pub text1: *mut libc::c_char, + pub text2: *mut libc::c_char, + pub timestamp: time_t, + pub state: libc::c_int, + pub id: uint32_t, + pub fingerprint: *mut libc::c_char, + pub invitenumber: *mut libc::c_char, + pub auth: *mut libc::c_char, +} +/* * + * 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 = Option< + unsafe extern "C" fn( + _: *mut dc_context_t, + _: libc::c_int, + _: uintptr_t, + _: uintptr_t, + ) -> uintptr_t, +>; +/* * + * @mainpage Getting started + * + * This document describes how to handle the Delta Chat core library. + * For general information about Delta Chat itself, + * see and . + * + * Let's start. + * + * First of all, you have to **define an event-handler-function** + * that is called by the library on specific events + * (eg. when the configuration is done or when fresh messages arrive). + * With this function you can create a Delta Chat context then: + * + * ~~~ + * #include + * + * uintptr_t event_handler_func(dc_context_t* context, int event, + * uintptr_t data1, uintptr_t data2) + * { + * return 0; // for unhandled events, it is always safe to return 0 + * } + * + * dc_context_t* context = dc_context_new(event_handler_func, NULL, NULL); + * ~~~ + * + * After that, you should make sure, + * sending and receiving jobs are processed as needed. + * For this purpose, you have to **create two threads:** + * + * ~~~ + * #include + * + * void* imap_thread_func(void* context) + * { + * while (true) { + * dc_perform_imap_jobs(context); + * dc_perform_imap_fetch(context); + * dc_perform_imap_idle(context); + * } + * } + * + * void* smtp_thread_func(void* context) + * { + * while (true) { + * dc_perform_smtp_jobs(context); + * dc_perform_smtp_idle(context); + * } + * } + * + * static pthread_t imap_thread, smtp_thread; + * pthread_create(&imap_thread, NULL, imap_thread_func, context); + * pthread_create(&smtp_thread, NULL, smtp_thread_func, context); + * ~~~ + * + * The example above uses "pthreads", + * however, you can also use anything else for thread handling. + * NB: The deltachat-core library itself does not create any threads on its own, + * however, functions, unless stated otherwise, are thread-safe. + * + * After that you can **define and open a database.** + * The database is a normal sqlite-file and is created as needed: + * + * ~~~ + * dc_open(context, "example.db", NULL); + * ~~~ + * + * Now you can **configure the context:** + * + * ~~~ + * // use some real test credentials here + * dc_set_config(context, "addr", "alice@example.org"); + * dc_set_config(context, "mail_pw", "***"); + * dc_configure(context); + * ~~~ + * + * dc_configure() returns immediately, the configuration itself may take a while + * and is done by a job in the imap-thread you've defined above. + * Once done, the #DC_EVENT_CONFIGURE_PROGRESS reports success + * to the event_handler_func() that is also defined above. + * + * The configuration result is saved in the database, + * on subsequent starts it is not needed to call dc_configure() + * (you can check this using dc_is_configured()). + * + * Now you can **send the first message:** + * + * ~~~ + * // use a real testing address here + * uint32_t contact_id = dc_create_contact(context, NULL, "bob@example.org"); + * uint32_t chat_id = dc_create_chat_by_contact_id(context, contact_id); + * + * dc_send_text_msg(context, chat_id, "Hi, here is my first message!"); + * ~~~ + * + * dc_send_text_msg() returns immediately; + * the sending itself is done by a job in the smtp-thread you've defined above. + * If you check the testing address (bob) + * and you should have received a normal email. + * Answer this email in any email program with "Got it!" + * and the imap-thread you've create above will **receive the message**. + * + * You can then **list all messages** of a chat as follow: + * + * ~~~ + * dc_array_t* msglist = dc_get_chat_msgs(context, chat_id, 0, 0); + * for (int i = 0; i < dc_array_get_cnt(msglist); i++) + * { + * uint32_t msg_id = dc_array_get_id(msglist, i); + * dc_msg_t* msg = dc_get_msg(context, msg_id); + * char* text = dc_msg_get_text(msg); + * + * printf("Message %i: %s\n", i+1, text); + * + * free(text); + * dc_msg_unref(msg); + * } + * dc_array_unref(msglist); + * ~~~ + * + * This will output the following two lines: + * + * ~~~ + * Message 1: Hi, here is my first message! + * Message 2: Got it! + * ~~~ + * + * + * ## Class reference + * + * For a class reference, see the "Classes" link atop. + * + * + * ## Further hints + * + * Here are some additional, unsorted hints that may be useful. + * + * - For `get`-functions, you have to unref the return value in some way. + * + * - Strings in function arguments or return values are usually UTF-8 encoded. + * + * - The issue-tracker for the core library is here: + * + * + * The following points are important mainly + * for the authors of the library itself: + * + * - For indentation, use tabs. + * Alignments that are not placed at the beginning of a line + * should be done with spaces. + * + * - For padding between functions, + * classes etc. use 2 empty lines + * + * - Source files are encoded as UTF-8 with Unix line endings + * (a simple `LF`, `0x0A` or `\n`) + * + * If you need further assistance, + * please do not hesitate to contact us + * through the channels shown at https://delta.chat/en/contribute + * + * Please keep in mind, that your derived work + * must respect the Mozilla Public License 2.0 of libdeltachat + * and the respective licenses of the libraries libdeltachat links with. + * + * See you. + */ +/* * + * @class dc_context_t + * + * An object representing a single account. + * + * Each account is linked to an IMAP/SMTP account and uses a separate + * SQLite database for offline functionality and for account-related + * settings. + */ +pub type dc_context_t = _dc_context; +/* ** library-private **********************************************************/ +pub type dc_smtp_t = _dc_smtp; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_smtp { + 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 error: *mut libc::c_char, + pub error_etpan: libc::c_int, +} +pub type dc_jobthread_t = _dc_jobthread; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_jobthread { + 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, + 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, +} +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_imap { + 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 type dc_receive_imf_t = Option< + unsafe extern "C" 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_imap_t = _dc_imap; +pub type dc_precheck_imf_t = Option< + unsafe extern "C" 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< + unsafe extern "C" fn(_: *mut dc_imap_t, _: *const libc::c_char, _: *const libc::c_char) -> (), +>; +pub type dc_get_config_t = Option< + unsafe extern "C" fn( + _: *mut dc_imap_t, + _: *const libc::c_char, + _: *const libc::c_char, + ) -> *mut libc::c_char, +>; +/* ** library-private **********************************************************/ +pub type dc_sqlite3_t = _dc_sqlite3; +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_sqlite3 { + pub cobj: *mut sqlite3, + pub context: *mut dc_context_t, +} +pub type dc_param_t = _dc_param; +/* * + * @class dc_param_t + * + * An object for handling key=value parameter lists; for the key, curently only + * a single character is allowed. + * + * The object is used eg. by dc_chat_t or dc_msg_t, for readable paramter names, + * these classes define some DC_PARAM_* constantats. + * + * Only for library-internal use. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_param { + pub packed: *mut libc::c_char, +} +pub type unnamed_3 = libc::c_uint; +pub const DC_MOVE_STATE_MOVING: unnamed_3 = 3; +pub const DC_MOVE_STATE_STAY: unnamed_3 = 2; +pub const DC_MOVE_STATE_PENDING: unnamed_3 = 1; +pub const DC_MOVE_STATE_UNDEFINED: unnamed_3 = 0; +pub type sqlite3_destructor_type = Option ()>; +pub type dc_apeerstate_t = _dc_apeerstate; +/* prefer-encrypt states */ +/* * + * @class dc_apeerstate_t + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_apeerstate { + pub context: *mut dc_context_t, + pub addr: *mut libc::c_char, + pub last_seen: time_t, + pub last_seen_autocrypt: time_t, + pub prefer_encrypt: libc::c_int, + pub public_key: *mut dc_key_t, + pub public_key_fingerprint: *mut libc::c_char, + pub gossip_key: *mut dc_key_t, + pub gossip_timestamp: time_t, + pub gossip_key_fingerprint: *mut libc::c_char, + pub verified_key: *mut dc_key_t, + pub verified_key_fingerprint: *mut libc::c_char, + pub to_save: libc::c_int, + pub degrade_event: libc::c_int, +} +pub type dc_key_t = _dc_key; +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_key { + pub binary: *mut libc::c_void, + pub bytes: libc::c_int, + pub type_0: libc::c_int, + pub _m_heap_refcnt: libc::c_int, +} +/* Forward declarations of structures. + */ +pub type dc_hash_t = _dc_hash; +/* A complete hash table is an instance of the following structure. + * The internals of this structure are intended to be opaque -- client + * code should not attempt to access or modify the fields of this structure + * directly. Change this structure only by using the routines below. + * However, many of the "procedures" and "functions" for modifying and + * accessing this structure are really macros, so we can't really make + * this structure opaque. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_hash { + pub keyClass: libc::c_char, + pub copyKey: libc::c_char, + pub count: libc::c_int, + pub first: *mut dc_hashelem_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. + * + * Again, this structure is intended to be opaque, but it can't really + * be opaque because it is used by macros. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_hashelem { + pub next: *mut dc_hashelem_t, + pub prev: *mut dc_hashelem_t, + pub data: *mut libc::c_void, + pub pKey: *mut libc::c_void, + pub nKey: libc::c_int, +} +#[no_mangle] +pub unsafe extern "C" 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( + 1i32 as libc::c_ulong, + ::std::mem::size_of::() as libc::c_ulong, + ) as *mut dc_sqlite3_t; + if sql.is_null() { + exit(24i32); + } + (*sql).context = context; + return sql; +} +#[no_mangle] +pub unsafe extern "C" fn dc_sqlite3_unref(mut sql: *mut dc_sqlite3_t) { + if sql.is_null() { + return; + } + if !(*sql).cobj.is_null() { + dc_sqlite3_close(sql); + } + free(sql as *mut libc::c_void); +} +#[no_mangle] +pub unsafe extern "C" 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 + } + dc_log_info( + (*sql).context, + 0i32, + b"Database closed.\x00" as *const u8 as *const libc::c_char, + ); +} +#[no_mangle] +pub unsafe extern "C" fn dc_sqlite3_open( + mut sql: *mut dc_sqlite3_t, + mut dbfile: *const libc::c_char, + mut flags: libc::c_int, +) -> libc::c_int { + let mut current_block: u64; + if 0 != dc_sqlite3_is_open(sql) { + return 0i32; + } + if !(sql.is_null() || dbfile.is_null()) { + if sqlite3_threadsafe() == 0i32 { + dc_log_error( + (*sql).context, + 0i32, + b"Sqlite3 compiled thread-unsafe; this is not supported.\x00" as *const u8 + as *const libc::c_char, + ); + } else if !(*sql).cobj.is_null() { + dc_log_error( + (*sql).context, + 0i32, + 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 + } else { + 0x2i32 | 0x4i32 + }, + 0 as *const libc::c_char, + ) != 0i32 + { + dc_sqlite3_log_error( + sql, + b"Cannot open database \"%s\".\x00" as *const u8 as *const libc::c_char, + dbfile, + ); + } else { + dc_sqlite3_execute( + 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; + /* Init tables to dbversion=0 */ + if 0 == dc_sqlite3_table_exists( + sql, + b"config\x00" as *const u8 as *const libc::c_char, + ) { + dc_log_info( + (*sql).context, + 0i32, + 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( + 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( + sql, + b"CREATE INDEX contacts_index1 ON contacts (name COLLATE NOCASE);\x00" + as *const u8 as *const libc::c_char, + ); + dc_sqlite3_execute( + 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( + sql, + b"CREATE INDEX chats_index1 ON chats (grpid);\x00" as *const u8 + as *const libc::c_char, + ); + dc_sqlite3_execute( + sql, + b"CREATE TABLE chats_contacts (chat_id INTEGER, contact_id INTEGER);\x00" + as *const u8 as *const libc::c_char, + ); + dc_sqlite3_execute( + 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( + sql, + b"CREATE INDEX msgs_index1 ON msgs (rfc724_mid);\x00" as *const u8 + as *const libc::c_char, + ); + dc_sqlite3_execute( + sql, + b"CREATE INDEX msgs_index2 ON msgs (chat_id);\x00" as *const u8 + as *const libc::c_char, + ); + dc_sqlite3_execute( + sql, + b"CREATE INDEX msgs_index3 ON msgs (timestamp);\x00" as *const u8 + as *const libc::c_char, + ); + dc_sqlite3_execute( + 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( + 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( + sql, + b"config\x00" as *const u8 as *const libc::c_char, + ) || 0 + == dc_sqlite3_table_exists( + sql, + b"contacts\x00" as *const u8 as *const libc::c_char, + ) + || 0 == dc_sqlite3_table_exists( + sql, + b"chats\x00" as *const u8 as *const libc::c_char, + ) + || 0 == dc_sqlite3_table_exists( + sql, + b"chats_contacts\x00" as *const u8 as *const libc::c_char, + ) + || 0 == dc_sqlite3_table_exists( + sql, + b"msgs\x00" as *const u8 as *const libc::c_char, + ) + || 0 == dc_sqlite3_table_exists( + sql, + b"jobs\x00" as *const u8 as *const libc::c_char, + ) + { + dc_sqlite3_log_error( + 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? */ + current_block = 13628706266672894061; + } else { + dc_sqlite3_set_config_int( + sql, + b"dbversion\x00" as *const u8 as *const libc::c_char, + 0i32, + ); + current_block = 14072441030219150333; + } + } else { + exists_before_update = 1i32; + dbversion_before_update = dc_sqlite3_get_config_int( + sql, + b"dbversion\x00" as *const u8 as *const libc::c_char, + 0i32, + ); + current_block = 14072441030219150333; + } + match current_block { + 13628706266672894061 => {} + _ => { + // (1) update low-level database structure. + // this should be done before updates that use high-level objects that + // 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); + dc_sqlite3_execute( + sql, + b"CREATE INDEX leftgrps_index1 ON leftgrps (grpid);\x00" + as *const u8 + as *const libc::c_char, + ); + dbversion = 1i32; + dc_sqlite3_set_config_int( + sql, + b"dbversion\x00" as *const u8 as *const libc::c_char, + 1i32, + ); + } + if dbversion < 2i32 { + dc_sqlite3_execute( + sql, + b"ALTER TABLE contacts ADD COLUMN authname TEXT DEFAULT \'\';\x00" + as *const u8 + as *const libc::c_char, + ); + dbversion = 2i32; + dc_sqlite3_set_config_int( + sql, + b"dbversion\x00" as *const u8 as *const libc::c_char, + 2i32, + ); + } + 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); + dc_sqlite3_execute( + sql, + b"CREATE INDEX acpeerstates_index1 ON acpeerstates (addr);\x00" + as *const u8 + as *const libc::c_char, + ); + dbversion = 10i32; + dc_sqlite3_set_config_int( + sql, + b"dbversion\x00" as *const u8 as *const libc::c_char, + 10i32, + ); + } + 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); + dc_sqlite3_execute( + sql, + b"CREATE INDEX msgs_mdns_index1 ON msgs_mdns (msg_id);\x00" + as *const u8 + as *const libc::c_char, + ); + dbversion = 12i32; + dc_sqlite3_set_config_int( + sql, + b"dbversion\x00" as *const u8 as *const libc::c_char, + 12i32, + ); + } + if dbversion < 17i32 { + dc_sqlite3_execute( + sql, + b"ALTER TABLE chats ADD COLUMN archived INTEGER DEFAULT 0;\x00" + as *const u8 + as *const libc::c_char, + ); + dc_sqlite3_execute( + sql, + b"CREATE INDEX chats_index2 ON chats (archived);\x00" as *const u8 + as *const libc::c_char, + ); + dc_sqlite3_execute( + sql, + b"ALTER TABLE msgs ADD COLUMN starred INTEGER DEFAULT 0;\x00" + as *const u8 + as *const libc::c_char, + ); + dc_sqlite3_execute( + sql, + b"CREATE INDEX msgs_index5 ON msgs (starred);\x00" as *const u8 + as *const libc::c_char, + ); + dbversion = 17i32; + dc_sqlite3_set_config_int( + sql, + b"dbversion\x00" as *const u8 as *const libc::c_char, + 17i32, + ); + } + 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); + dc_sqlite3_execute( + sql, + b"ALTER TABLE acpeerstates ADD COLUMN gossip_key;\x00" as *const u8 + as *const libc::c_char, + ); + dbversion = 18i32; + dc_sqlite3_set_config_int( + sql, + b"dbversion\x00" as *const u8 as *const libc::c_char, + 18i32, + ); + } + if dbversion < 27i32 { + dc_sqlite3_execute( + 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( + sql, + b"ALTER TABLE msgs ADD COLUMN timestamp_sent INTEGER DEFAULT 0;\x00" + as *const u8 + as *const libc::c_char, + ); + dc_sqlite3_execute( + sql, + b"ALTER TABLE msgs ADD COLUMN timestamp_rcvd INTEGER DEFAULT 0;\x00" + as *const u8 + as *const libc::c_char, + ); + dbversion = 27i32; + dc_sqlite3_set_config_int( + sql, + b"dbversion\x00" as *const u8 as *const libc::c_char, + 27i32, + ); + } + if dbversion < 34i32 { + dc_sqlite3_execute( + 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_set_config_int( + sql, + b"dbversion\x00" as *const u8 as *const libc::c_char, + 34i32, + ); + } + 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); + dc_sqlite3_execute( + 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); + } + dbversion = 39i32; + dc_sqlite3_set_config_int( + sql, + b"dbversion\x00" as *const u8 as *const libc::c_char, + 39i32, + ); + } + if dbversion < 40i32 { + dc_sqlite3_execute( + sql, + b"ALTER TABLE jobs ADD COLUMN thread INTEGER DEFAULT 0;\x00" + as *const u8 + as *const libc::c_char, + ); + dbversion = 40i32; + dc_sqlite3_set_config_int( + sql, + b"dbversion\x00" as *const u8 as *const libc::c_char, + 40i32, + ); + } + if dbversion < 41i32 { + update_file_paths = 1i32; + dbversion = 41i32; + dc_sqlite3_set_config_int( + sql, + b"dbversion\x00" as *const u8 as *const libc::c_char, + 41i32, + ); + } + if dbversion < 42i32 { + dc_sqlite3_execute( + sql, + b"UPDATE msgs SET txt=\'\' WHERE type!=10\x00" as *const u8 + as *const libc::c_char, + ); + dbversion = 42i32; + dc_sqlite3_set_config_int( + sql, + b"dbversion\x00" as *const u8 as *const libc::c_char, + 42i32, + ); + } + if dbversion < 44i32 { + dc_sqlite3_execute( + sql, + b"ALTER TABLE msgs ADD COLUMN mime_headers TEXT;\x00" as *const u8 + as *const libc::c_char, + ); + dbversion = 44i32; + dc_sqlite3_set_config_int( + sql, + b"dbversion\x00" as *const u8 as *const libc::c_char, + 44i32, + ); + } + if dbversion < 46i32 { + dc_sqlite3_execute( + sql, + b"ALTER TABLE msgs ADD COLUMN mime_in_reply_to TEXT;\x00" + as *const u8 + as *const libc::c_char, + ); + dc_sqlite3_execute( + sql, + b"ALTER TABLE msgs ADD COLUMN mime_references TEXT;\x00" + as *const u8 + as *const libc::c_char, + ); + dbversion = 46i32; + dc_sqlite3_set_config_int( + sql, + b"dbversion\x00" as *const u8 as *const libc::c_char, + 46i32, + ); + } + if dbversion < 47i32 { + dc_sqlite3_execute( + sql, + b"ALTER TABLE jobs ADD COLUMN tries INTEGER DEFAULT 0;\x00" + as *const u8 + as *const libc::c_char, + ); + dbversion = 47i32; + dc_sqlite3_set_config_int( + sql, + b"dbversion\x00" as *const u8 as *const libc::c_char, + 47i32, + ); + } + if dbversion < 48i32 { + dc_sqlite3_execute( + 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 + as libc::c_long + { + __assert_rtn( + (*::std::mem::transmute::<&[u8; 16], &[libc::c_char; 16]>( + b"dc_sqlite3_open\x00", + )) + .as_ptr(), + b"../src/dc_sqlite3.c\x00" as *const u8 as *const libc::c_char, + 559i32, + 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 + as libc::c_long + { + __assert_rtn( + (*::std::mem::transmute::<&[u8; 16], &[libc::c_char; 16]>( + b"dc_sqlite3_open\x00", + )) + .as_ptr(), + b"../src/dc_sqlite3.c\x00" as *const u8 as *const libc::c_char, + 560i32, + 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 + as libc::c_long + { + __assert_rtn( + (*::std::mem::transmute::<&[u8; 16], &[libc::c_char; 16]>( + b"dc_sqlite3_open\x00", + )) + .as_ptr(), + b"../src/dc_sqlite3.c\x00" as *const u8 as *const libc::c_char, + 561i32, + 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 + as libc::c_long + { + __assert_rtn( + (*::std::mem::transmute::<&[u8; 16], &[libc::c_char; 16]>( + b"dc_sqlite3_open\x00", + )) + .as_ptr(), + b"../src/dc_sqlite3.c\x00" as *const u8 as *const libc::c_char, + 562i32, + b"DC_MOVE_STATE_MOVING == 3\x00" as *const u8 + as *const libc::c_char, + ); + } else { + }; + dbversion = 48i32; + dc_sqlite3_set_config_int( + sql, + b"dbversion\x00" as *const u8 as *const libc::c_char, + 48i32, + ); + } + 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; + dc_sqlite3_set_config_int( + sql, + b"dbversion\x00" as *const u8 as *const libc::c_char, + 49i32, + ); + } + if dbversion < 50i32 { + if 0 != exists_before_update { + dc_sqlite3_set_config_int( + sql, + b"show_emails\x00" as *const u8 as *const libc::c_char, + 2i32, + ); + } + dbversion = 50i32; + dc_sqlite3_set_config_int( + sql, + b"dbversion\x00" as *const u8 as *const libc::c_char, + 50i32, + ); + } + if dbversion < 53i32 { + dc_sqlite3_execute(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); + dc_sqlite3_execute( + sql, + b"CREATE INDEX locations_index1 ON locations (from_id);\x00" + as *const u8 + as *const libc::c_char, + ); + dc_sqlite3_execute( + sql, + b"CREATE INDEX locations_index2 ON locations (timestamp);\x00" + as *const u8 + as *const libc::c_char, + ); + dc_sqlite3_execute(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, + 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, + b"ALTER TABLE chats ADD COLUMN locations_last_sent INTEGER DEFAULT 0;\x00" + as *const u8 as + *const libc::c_char); + dc_sqlite3_execute( + sql, + b"CREATE INDEX chats_index3 ON chats (locations_send_until);\x00" + as *const u8 + as *const libc::c_char, + ); + dbversion = 53i32; + dc_sqlite3_set_config_int( + sql, + b"dbversion\x00" as *const u8 as *const libc::c_char, + 53i32, + ); + } + if dbversion < 54i32 { + dc_sqlite3_execute( + sql, + b"ALTER TABLE msgs ADD COLUMN location_id INTEGER DEFAULT 0;\x00" + as *const u8 + as *const libc::c_char, + ); + dc_sqlite3_execute( + sql, + b"CREATE INDEX msgs_index6 ON msgs (location_id);\x00" as *const u8 + as *const libc::c_char, + ); + dbversion = 54i32; + dc_sqlite3_set_config_int( + sql, + b"dbversion\x00" as *const u8 as *const libc::c_char, + 54i32, + ); + } + if 0 != recalc_fingerprints { + let mut stmt: *mut sqlite3_stmt = dc_sqlite3_prepare( + sql, + b"SELECT addr FROM acpeerstates;\x00" as *const u8 + as *const libc::c_char, + ); + while sqlite3_step(stmt) == 100i32 { + let mut peerstate: *mut dc_apeerstate_t = + dc_apeerstate_new((*sql).context); + if 0 != dc_apeerstate_load_by_addr( + peerstate, + sql, + sqlite3_column_text(stmt, 0i32) as *const libc::c_char, + ) && 0 != dc_apeerstate_recalc_fingerprint(peerstate) + { + dc_apeerstate_save_to_db(peerstate, sql, 0i32); + } + dc_apeerstate_unref(peerstate); + } + sqlite3_finalize(stmt); + } + if 0 != update_file_paths { + let mut repl_from: *mut libc::c_char = dc_sqlite3_get_config( + sql, + b"backup_for\x00" as *const u8 as *const libc::c_char, + (*(*sql).context).blobdir, + ); + dc_ensure_no_slash(repl_from); + if 0 != !('f' as i32 == 'f' as i32) as libc::c_int as libc::c_long { + __assert_rtn( + (*::std::mem::transmute::<&[u8; 16], &[libc::c_char; 16]>( + b"dc_sqlite3_open\x00", + )) + .as_ptr(), + b"../src/dc_sqlite3.c\x00" as *const u8 as *const libc::c_char, + 656i32, + 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, + repl_from); + dc_sqlite3_execute(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( + (*::std::mem::transmute::<&[u8; 16], &[libc::c_char; 16]>( + b"dc_sqlite3_open\x00", + )) + .as_ptr(), + b"../src/dc_sqlite3.c\x00" as *const u8 as *const libc::c_char, + 661i32, + b"\'i\'==DC_PARAM_PROFILE_IMAGE\x00" as *const u8 + as *const libc::c_char, + ); + } else { + }; + q3 = + sqlite3_mprintf(b"UPDATE chats SET param=replace(param, \'i=%q/\', \'i=$BLOBDIR/\');\x00" + as *const u8 as + *const libc::c_char, + repl_from); + dc_sqlite3_execute(sql, q3); + sqlite3_free(q3 as *mut libc::c_void); + free(repl_from as *mut libc::c_void); + dc_sqlite3_set_config( + sql, + b"backup_for\x00" as *const u8 as *const libc::c_char, + 0 as *const libc::c_char, + ); + } + current_block = 12024807525273687499; + } + } + } else { + current_block = 12024807525273687499; + } + match current_block { + 13628706266672894061 => {} + _ => { + dc_log_info( + (*sql).context, + 0i32, + b"Opened \"%s\".\x00" as *const u8 as *const libc::c_char, + dbfile, + ); + return 1i32; + } + } + } + } + dc_sqlite3_close(sql); + return 0i32; +} +/* handle configurations, private */ +#[no_mangle] +pub unsafe extern "C" fn dc_sqlite3_set_config( + mut sql: *mut dc_sqlite3_t, + mut key: *const libc::c_char, + mut 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; + if key.is_null() { + dc_log_error( + (*sql).context, + 0i32, + b"dc_sqlite3_set_config(): Bad parameter.\x00" as *const u8 as *const libc::c_char, + ); + return 0i32; + } + if 0 == dc_sqlite3_is_open(sql) { + dc_log_error( + (*sql).context, + 0i32, + b"dc_sqlite3_set_config(): Database not ready.\x00" as *const u8 as *const libc::c_char, + ); + return 0i32; + } + if !value.is_null() { + stmt = dc_sqlite3_prepare( + 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); + state = sqlite3_step(stmt); + sqlite3_finalize(stmt); + if state == 101i32 { + stmt = dc_sqlite3_prepare( + 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); + state = sqlite3_step(stmt); + sqlite3_finalize(stmt); + } else if state == 100i32 { + stmt = dc_sqlite3_prepare( + 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); + state = sqlite3_step(stmt); + sqlite3_finalize(stmt); + } else { + dc_log_error( + (*sql).context, + 0i32, + b"dc_sqlite3_set_config(): Cannot read value.\x00" as *const u8 + as *const libc::c_char, + ); + return 0i32; + } + } else { + stmt = dc_sqlite3_prepare( + sql, + b"DELETE FROM config WHERE keyname=?;\x00" as *const u8 as *const libc::c_char, + ); + sqlite3_bind_text(stmt, 1i32, key, -1i32, None); + state = sqlite3_step(stmt); + sqlite3_finalize(stmt); + } + if state != 101i32 { + dc_log_error( + (*sql).context, + 0i32, + b"dc_sqlite3_set_config(): Cannot change value.\x00" as *const u8 + as *const libc::c_char, + ); + return 0i32; + } + return 1i32; +} +/* tools, these functions are compatible to the corresponding sqlite3_* functions */ +/* the result mus be freed using sqlite3_finalize() */ +#[no_mangle] +pub unsafe extern "C" fn dc_sqlite3_prepare( + mut sql: *mut dc_sqlite3_t, + mut 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() { + return 0 as *mut sqlite3_stmt; + } + if sqlite3_prepare_v2( + (*sql).cobj, + querystr, + -1i32, + &mut stmt, + 0 as *mut *const libc::c_char, + ) != 0i32 + { + dc_sqlite3_log_error( + sql, + b"Query failed: %s\x00" as *const u8 as *const libc::c_char, + querystr, + ); + return 0 as *mut sqlite3_stmt; + } + return stmt; +} +#[no_mangle] +pub unsafe extern "C" fn dc_sqlite3_log_error( + mut sql: *mut dc_sqlite3_t, + mut msg_format: *const libc::c_char, + mut va: ... +) { + let mut msg: *mut libc::c_char = 0 as *mut libc::c_char; + if sql.is_null() || msg_format.is_null() { + return; + } + msg = sqlite3_vmprintf(msg_format, va); + dc_log_error( + (*sql).context, + 0i32, + 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) + } else { + b"SQLite object not set up.\x00" as *const u8 as *const libc::c_char + }, + ); + sqlite3_free(msg as *mut libc::c_void); +} +#[no_mangle] +pub unsafe extern "C" fn dc_sqlite3_is_open(mut sql: *const dc_sqlite3_t) -> libc::c_int { + if sql.is_null() || (*sql).cobj.is_null() { + return 0i32; + } + return 1i32; +} +/* the returned string must be free()'d, returns NULL on errors */ +#[no_mangle] +pub unsafe extern "C" fn dc_sqlite3_get_config( + mut sql: *mut dc_sqlite3_t, + mut key: *const libc::c_char, + mut def: *const libc::c_char, +) -> *mut libc::c_char { + let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; + if 0 == dc_sqlite3_is_open(sql) || key.is_null() { + return dc_strdup_keep_null(def); + } + stmt = dc_sqlite3_prepare( + 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); + if !ptr.is_null() { + let mut ret: *mut libc::c_char = dc_strdup(ptr as *const libc::c_char); + sqlite3_finalize(stmt); + return ret; + } + } + sqlite3_finalize(stmt); + return dc_strdup_keep_null(def); +} +#[no_mangle] +pub unsafe extern "C" fn dc_sqlite3_execute( + mut sql: *mut dc_sqlite3_t, + mut 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); + if !stmt.is_null() { + sqlState = sqlite3_step(stmt); + if sqlState != 101i32 && sqlState != 100i32 { + dc_sqlite3_log_error( + sql, + b"Cannot execute \"%s\".\x00" as *const u8 as *const libc::c_char, + querystr, + ); + } else { + success = 1i32 + } + } + sqlite3_finalize(stmt); + return success; +} +#[no_mangle] +pub unsafe extern "C" fn dc_sqlite3_set_config_int( + mut sql: *mut dc_sqlite3_t, + mut key: *const libc::c_char, + mut value: int32_t, +) -> libc::c_int { + let mut value_str: *mut libc::c_char = 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; + } + let mut ret: libc::c_int = dc_sqlite3_set_config(sql, key, value_str); + free(value_str as *mut libc::c_void); + return ret; +} +#[no_mangle] +pub unsafe extern "C" fn dc_sqlite3_get_config_int( + mut sql: *mut dc_sqlite3_t, + mut key: *const libc::c_char, + mut def: int32_t, +) -> int32_t { + let mut str: *mut libc::c_char = dc_sqlite3_get_config(sql, key, 0 as *const libc::c_char); + if str.is_null() { + return def; + } + let mut ret: int32_t = atol(str) as int32_t; + free(str as *mut libc::c_void); + return ret; +} +#[no_mangle] +pub unsafe extern "C" fn dc_sqlite3_table_exists( + mut sql: *mut dc_sqlite3_t, + mut 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( + 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, + b"dc_sqlite3_table_exists_(): Out of memory.\x00" as *const u8 as *const libc::c_char, + ); + } else { + stmt = dc_sqlite3_prepare(sql, querystr); + if !stmt.is_null() { + sqlState = sqlite3_step(stmt); + if sqlState == 100i32 { + ret = 1i32 + } + } + } + /* error/cleanup */ + if !stmt.is_null() { + sqlite3_finalize(stmt); + } + if !querystr.is_null() { + sqlite3_free(querystr as *mut libc::c_void); + } + return ret; +} +#[no_mangle] +pub unsafe extern "C" fn dc_sqlite3_set_config_int64( + mut sql: *mut dc_sqlite3_t, + mut key: *const libc::c_char, + mut value: int64_t, +) -> libc::c_int { + let mut value_str: *mut libc::c_char = 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; + } + let mut ret: libc::c_int = dc_sqlite3_set_config(sql, key, value_str); + free(value_str as *mut libc::c_void); + return ret; +} +#[no_mangle] +pub unsafe extern "C" fn dc_sqlite3_get_config_int64( + mut sql: *mut dc_sqlite3_t, + mut key: *const libc::c_char, + mut def: int64_t, +) -> int64_t { + let mut str: *mut libc::c_char = dc_sqlite3_get_config(sql, key, 0 as *const libc::c_char); + if str.is_null() { + return def; + } + let mut ret: int64_t = 0i32 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; +} +#[no_mangle] +pub unsafe extern "C" fn dc_sqlite3_try_execute( + mut sql: *mut dc_sqlite3_t, + mut 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); + if !stmt.is_null() { + sql_state = sqlite3_step(stmt); + if sql_state != 101i32 && sql_state != 100i32 { + dc_log_warning( + (*sql).context, + 0i32, + b"Try-execute for \"%s\" failed: %s\x00" as *const u8 as *const libc::c_char, + querystr, + sqlite3_errmsg((*sql).cobj), + ); + } else { + success = 1i32 + } + } + sqlite3_finalize(stmt); + return success; +} +#[no_mangle] +pub unsafe extern "C" 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, +) -> 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( + 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 + } + sqlite3_finalize(stmt); + sqlite3_free(q3 as *mut libc::c_void); + return id; +} +#[no_mangle] +pub unsafe extern "C" 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, +) -> uint32_t { + // same as dc_sqlite3_get_rowid() with a key over two columns + let mut id: uint32_t = 0i32 as uint32_t; + // see https://www.sqlite.org/printf.html for sqlite-printf modifiers + let mut q3: *mut libc::c_char = 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, + field, + value, + 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 + } + sqlite3_finalize(stmt); + sqlite3_free(q3 as *mut libc::c_void); + return id; +} +#[no_mangle] +pub unsafe extern "C" fn dc_sqlite3_begin_transaction(mut sql: *mut dc_sqlite3_t) {} +#[no_mangle] +pub unsafe extern "C" fn dc_sqlite3_commit(mut sql: *mut dc_sqlite3_t) {} +#[no_mangle] +pub unsafe extern "C" fn dc_sqlite3_rollback(mut sql: *mut dc_sqlite3_t) {} +/* housekeeping */ +#[no_mangle] +pub unsafe extern "C" fn dc_housekeeping(mut context: *mut dc_context_t) { + let mut keep_files_newer_than: time_t = 0; + 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 { + keyClass: 0, + copyKey: 0, + count: 0, + first: 0 as *mut dc_hashelem_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); + dc_log_info( + context, + 0i32, + b"Start housekeeping...\x00" as *const u8 as *const libc::c_char, + ); + maybe_add_from_param( + context, + &mut files_in_use, + b"SELECT param FROM msgs WHERE chat_id!=3 AND type!=10;\x00" as *const u8 + as *const libc::c_char, + 'f' as i32, + ); + maybe_add_from_param( + context, + &mut files_in_use, + b"SELECT param FROM jobs;\x00" as *const u8 as *const libc::c_char, + 'f' as i32, + ); + maybe_add_from_param( + context, + &mut files_in_use, + b"SELECT param FROM chats;\x00" as *const u8 as *const libc::c_char, + 'i' as i32, + ); + maybe_add_from_param( + context, + &mut files_in_use, + b"SELECT param FROM contacts;\x00" as *const u8 as *const libc::c_char, + 'i' as i32, + ); + stmt = dc_sqlite3_prepare( + (*context).sql, + b"SELECT value FROM config;\x00" as *const u8 as *const libc::c_char, + ); + while sqlite3_step(stmt) == 100i32 { + maybe_add_file( + &mut files_in_use, + sqlite3_column_text(stmt, 0i32) as *const libc::c_char, + ); + } + dc_log_info( + context, + 0i32, + 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); + if dir_handle.is_null() { + dc_log_warning( + context, + 0i32, + b"Housekeeping: Cannot open %s.\x00" as *const u8 as *const libc::c_char, + (*context).blobdir, + ); + } else { + /* avoid deletion of files that are just created to build a message object */ + keep_files_newer_than = time(0 as *mut time_t) - (60i32 * 60i32) as libc::c_long; + loop { + dir_entry = readdir(dir_handle); + if dir_entry.is_null() { + break; + } + /* 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 + && *name.offset(0isize) as libc::c_int == '.' as i32 + && *name.offset(1isize) as libc::c_int == '.' as i32 + { + continue; + } + if 0 != is_file_in_use(&mut files_in_use, 0 as *const libc::c_char, name) + || 0 != is_file_in_use( + &mut files_in_use, + b".increation\x00" as *const u8 as *const libc::c_char, + name, + ) + || 0 != is_file_in_use( + &mut files_in_use, + b".waveform\x00" as *const u8 as *const libc::c_char, + name, + ) + || 0 != is_file_in_use( + &mut files_in_use, + b"-preview.jpg\x00" as *const u8 as *const libc::c_char, + name, + ) + { + continue; + } + unreferenced_count += 1; + free(path as *mut libc::c_void); + path = dc_mprintf( + b"%s/%s\x00" as *const u8 as *const libc::c_char, + (*context).blobdir, + name, + ); + let mut st: stat = stat { + st_dev: 0, + st_mode: 0, + st_nlink: 0, + st_ino: 0, + st_uid: 0, + st_gid: 0, + st_rdev: 0, + st_atimespec: timespec { + tv_sec: 0, + tv_nsec: 0, + }, + st_mtimespec: timespec { + tv_sec: 0, + tv_nsec: 0, + }, + st_ctimespec: timespec { + tv_sec: 0, + tv_nsec: 0, + }, + st_birthtimespec: timespec { + tv_sec: 0, + tv_nsec: 0, + }, + st_size: 0, + st_blocks: 0, + st_blksize: 0, + st_flags: 0, + st_gen: 0, + st_lspare: 0, + st_qspare: [0; 2], + }; + if stat(path, &mut st) == 0i32 { + if st.st_mtimespec.tv_sec > keep_files_newer_than + || st.st_atimespec.tv_sec > keep_files_newer_than + || st.st_ctimespec.tv_sec > keep_files_newer_than + { + dc_log_info( + context, + 0i32, + b"Housekeeping: Keeping new unreferenced file #%i: %s\x00" as *const u8 + as *const libc::c_char, + unreferenced_count, + name, + ); + continue; + } + } + dc_log_info( + context, + 0i32, + b"Housekeeping: Deleting unreferenced file #%i: %s\x00" as *const u8 + as *const libc::c_char, + unreferenced_count, + name, + ); + dc_delete_file(context, path); + } + } + if !dir_handle.is_null() { + closedir(dir_handle); + } + sqlite3_finalize(stmt); + dc_hash_clear(&mut files_in_use); + free(path as *mut libc::c_void); + dc_log_info( + context, + 0i32, + b"Housekeeping done.\x00" as *const u8 as *const libc::c_char, + ); +} +unsafe extern "C" 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, +) -> libc::c_int { + let mut name_to_check: *mut libc::c_char = 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 + { + return 0i32; + } + *name_to_check.offset((name_len - namespc_len) as isize) = 0i32 as libc::c_char + } + let mut ret: libc::c_int = (dc_hash_find( + files_in_use, + name_to_check as *const libc::c_void, + 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; +} +/* ****************************************************************************** + * Housekeeping + ******************************************************************************/ +unsafe extern "C" fn maybe_add_file( + mut files_in_use: *mut dc_hash_t, + mut file: *const libc::c_char, +) { + if strncmp( + file, + b"$BLOBDIR/\x00" as *const u8 as *const libc::c_char, + 9i32 as libc::c_ulong, + ) != 0i32 + { + return; + } + let mut raw_name: *const libc::c_char = &*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, + ); +} +unsafe extern "C" 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, +) { + 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); + if !file.is_null() { + maybe_add_file(files_in_use, file); + free(file as *mut libc::c_void); + } + } + sqlite3_finalize(stmt); + dc_param_unref(param); +} diff --git a/src/dc_stock.rs b/src/dc_stock.rs new file mode 100644 index 000000000..e2f2d60a4 --- /dev/null +++ b/src/dc_stock.rs @@ -0,0 +1,1109 @@ +use c2rust_bitfields::BitfieldStruct; +use libc; +extern "C" { + pub type mailstream_cancel; + pub type sqlite3; + #[no_mangle] + fn free(_: *mut libc::c_void); + #[no_mangle] + fn strlen(_: *const libc::c_char) -> libc::c_ulong; + #[no_mangle] + fn dc_lookup_contact_id_by_addr(_: *mut dc_context_t, addr: *const libc::c_char) -> uint32_t; + #[no_mangle] + fn dc_get_contact(_: *mut dc_context_t, contact_id: uint32_t) -> *mut dc_contact_t; + #[no_mangle] + fn dc_contact_unref(_: *mut dc_contact_t); + #[no_mangle] + fn dc_contact_get_display_name(_: *const dc_contact_t) -> *mut libc::c_char; + #[no_mangle] + fn dc_contact_get_name_n_addr(_: *const dc_contact_t) -> *mut libc::c_char; + /* string tools */ + #[no_mangle] + fn dc_strdup(_: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn dc_str_replace( + haystack: *mut *mut libc::c_char, + needle: *const libc::c_char, + replacement: *const libc::c_char, + ) -> libc::c_int; + #[no_mangle] + fn dc_mprintf(format: *const libc::c_char, _: ...) -> *mut libc::c_char; +} +pub type __darwin_size_t = libc::c_ulong; +pub type __darwin_ssize_t = libc::c_long; +pub type __darwin_time_t = libc::c_long; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_cond_t { + pub __sig: libc::c_long, + pub __opaque: [libc::c_char; 40], +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_mutex_t { + pub __sig: libc::c_long, + pub __opaque: [libc::c_char; 56], +} +pub type __darwin_pthread_cond_t = _opaque_pthread_cond_t; +pub type __darwin_pthread_mutex_t = _opaque_pthread_mutex_t; +pub type uintptr_t = libc::c_ulong; +pub type size_t = __darwin_size_t; +pub type uint8_t = libc::c_uchar; +pub type uint32_t = libc::c_uint; +pub type ssize_t = __darwin_ssize_t; +pub type time_t = __darwin_time_t; +pub type pthread_cond_t = __darwin_pthread_cond_t; +pub type pthread_mutex_t = __darwin_pthread_mutex_t; +#[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; +#[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) -> (); +#[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; +#[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, + 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 { + 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_capability_data { + pub cap_list: *mut clist, +} +#[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_0, + 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_0 { + 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 extern "C" 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_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, +} +#[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_1, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed_1 { + pub ft_fetch_att: *mut mailimap_fetch_att, + pub ft_fetch_att_list: *mut clist, +} +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 unnamed_2 { + 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, +} +/* define DC_USE_RPGP to enable use of rPGP instead of netpgp where available; +preferrably, this should be done in the project configuration currently */ +//#define DC_USE_RPGP 1 +/* Includes that are used frequently. This file may also be used to create predefined headers. */ +/* * Structure behind dc_context_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_context { + pub magic: uint32_t, + pub userdata: *mut libc::c_void, + pub dbfile: *mut libc::c_char, + pub blobdir: *mut libc::c_char, + pub sql: *mut dc_sqlite3_t, + pub inbox: *mut dc_imap_t, + pub inboxidle_condmutex: pthread_mutex_t, + pub perform_inbox_jobs_needed: libc::c_int, + pub probe_imap_network: libc::c_int, + pub sentbox_thread: dc_jobthread_t, + pub mvbox_thread: dc_jobthread_t, + pub smtp: *mut dc_smtp_t, + pub smtpidle_cond: pthread_cond_t, + pub smtpidle_condmutex: pthread_mutex_t, + pub smtpidle_condflag: libc::c_int, + pub smtp_suspended: libc::c_int, + pub smtp_doing_jobs: libc::c_int, + pub perform_smtp_jobs_needed: libc::c_int, + pub probe_smtp_network: libc::c_int, + pub oauth2_critical: pthread_mutex_t, + 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 type dc_lot_t = _dc_lot; +/* * Structure behind dc_lot_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_lot { + pub magic: uint32_t, + pub text1_meaning: libc::c_int, + pub text1: *mut libc::c_char, + pub text2: *mut libc::c_char, + pub timestamp: time_t, + pub state: libc::c_int, + pub id: uint32_t, + pub fingerprint: *mut libc::c_char, + pub invitenumber: *mut libc::c_char, + pub auth: *mut libc::c_char, +} +/* * + * 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 = Option< + unsafe extern "C" fn( + _: *mut dc_context_t, + _: libc::c_int, + _: uintptr_t, + _: uintptr_t, + ) -> uintptr_t, +>; +/* * + * @mainpage Getting started + * + * This document describes how to handle the Delta Chat core library. + * For general information about Delta Chat itself, + * see and . + * + * Let's start. + * + * First of all, you have to **define an event-handler-function** + * that is called by the library on specific events + * (eg. when the configuration is done or when fresh messages arrive). + * With this function you can create a Delta Chat context then: + * + * ~~~ + * #include + * + * uintptr_t event_handler_func(dc_context_t* context, int event, + * uintptr_t data1, uintptr_t data2) + * { + * return 0; // for unhandled events, it is always safe to return 0 + * } + * + * dc_context_t* context = dc_context_new(event_handler_func, NULL, NULL); + * ~~~ + * + * After that, you should make sure, + * sending and receiving jobs are processed as needed. + * For this purpose, you have to **create two threads:** + * + * ~~~ + * #include + * + * void* imap_thread_func(void* context) + * { + * while (true) { + * dc_perform_imap_jobs(context); + * dc_perform_imap_fetch(context); + * dc_perform_imap_idle(context); + * } + * } + * + * void* smtp_thread_func(void* context) + * { + * while (true) { + * dc_perform_smtp_jobs(context); + * dc_perform_smtp_idle(context); + * } + * } + * + * static pthread_t imap_thread, smtp_thread; + * pthread_create(&imap_thread, NULL, imap_thread_func, context); + * pthread_create(&smtp_thread, NULL, smtp_thread_func, context); + * ~~~ + * + * The example above uses "pthreads", + * however, you can also use anything else for thread handling. + * NB: The deltachat-core library itself does not create any threads on its own, + * however, functions, unless stated otherwise, are thread-safe. + * + * After that you can **define and open a database.** + * The database is a normal sqlite-file and is created as needed: + * + * ~~~ + * dc_open(context, "example.db", NULL); + * ~~~ + * + * Now you can **configure the context:** + * + * ~~~ + * // use some real test credentials here + * dc_set_config(context, "addr", "alice@example.org"); + * dc_set_config(context, "mail_pw", "***"); + * dc_configure(context); + * ~~~ + * + * dc_configure() returns immediately, the configuration itself may take a while + * and is done by a job in the imap-thread you've defined above. + * Once done, the #DC_EVENT_CONFIGURE_PROGRESS reports success + * to the event_handler_func() that is also defined above. + * + * The configuration result is saved in the database, + * on subsequent starts it is not needed to call dc_configure() + * (you can check this using dc_is_configured()). + * + * Now you can **send the first message:** + * + * ~~~ + * // use a real testing address here + * uint32_t contact_id = dc_create_contact(context, NULL, "bob@example.org"); + * uint32_t chat_id = dc_create_chat_by_contact_id(context, contact_id); + * + * dc_send_text_msg(context, chat_id, "Hi, here is my first message!"); + * ~~~ + * + * dc_send_text_msg() returns immediately; + * the sending itself is done by a job in the smtp-thread you've defined above. + * If you check the testing address (bob) + * and you should have received a normal email. + * Answer this email in any email program with "Got it!" + * and the imap-thread you've create above will **receive the message**. + * + * You can then **list all messages** of a chat as follow: + * + * ~~~ + * dc_array_t* msglist = dc_get_chat_msgs(context, chat_id, 0, 0); + * for (int i = 0; i < dc_array_get_cnt(msglist); i++) + * { + * uint32_t msg_id = dc_array_get_id(msglist, i); + * dc_msg_t* msg = dc_get_msg(context, msg_id); + * char* text = dc_msg_get_text(msg); + * + * printf("Message %i: %s\n", i+1, text); + * + * free(text); + * dc_msg_unref(msg); + * } + * dc_array_unref(msglist); + * ~~~ + * + * This will output the following two lines: + * + * ~~~ + * Message 1: Hi, here is my first message! + * Message 2: Got it! + * ~~~ + * + * + * ## Class reference + * + * For a class reference, see the "Classes" link atop. + * + * + * ## Further hints + * + * Here are some additional, unsorted hints that may be useful. + * + * - For `get`-functions, you have to unref the return value in some way. + * + * - Strings in function arguments or return values are usually UTF-8 encoded. + * + * - The issue-tracker for the core library is here: + * + * + * The following points are important mainly + * for the authors of the library itself: + * + * - For indentation, use tabs. + * Alignments that are not placed at the beginning of a line + * should be done with spaces. + * + * - For padding between functions, + * classes etc. use 2 empty lines + * + * - Source files are encoded as UTF-8 with Unix line endings + * (a simple `LF`, `0x0A` or `\n`) + * + * If you need further assistance, + * please do not hesitate to contact us + * through the channels shown at https://delta.chat/en/contribute + * + * Please keep in mind, that your derived work + * must respect the Mozilla Public License 2.0 of libdeltachat + * and the respective licenses of the libraries libdeltachat links with. + * + * See you. + */ +/* * + * @class dc_context_t + * + * An object representing a single account. + * + * Each account is linked to an IMAP/SMTP account and uses a separate + * SQLite database for offline functionality and for account-related + * settings. + */ +pub type dc_context_t = _dc_context; +/* ** library-private **********************************************************/ +pub type dc_smtp_t = _dc_smtp; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_smtp { + 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 error: *mut libc::c_char, + pub error_etpan: libc::c_int, +} +pub type dc_jobthread_t = _dc_jobthread; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_jobthread { + 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, + 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, +} +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_imap { + 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 type dc_receive_imf_t = Option< + unsafe extern "C" 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_imap_t = _dc_imap; +pub type dc_precheck_imf_t = Option< + unsafe extern "C" 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< + unsafe extern "C" fn(_: *mut dc_imap_t, _: *const libc::c_char, _: *const libc::c_char) -> (), +>; +pub type dc_get_config_t = Option< + unsafe extern "C" fn( + _: *mut dc_imap_t, + _: *const libc::c_char, + _: *const libc::c_char, + ) -> *mut libc::c_char, +>; +/* ** library-private **********************************************************/ +pub type dc_sqlite3_t = _dc_sqlite3; +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_sqlite3 { + pub cobj: *mut sqlite3, + pub context: *mut dc_context_t, +} +/* * the structure behind dc_contact_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_contact { + pub magic: uint32_t, + pub context: *mut dc_context_t, + pub id: uint32_t, + pub name: *mut libc::c_char, + pub authname: *mut libc::c_char, + pub addr: *mut libc::c_char, + pub blocked: libc::c_int, + pub origin: libc::c_int, +} +pub type dc_contact_t = _dc_contact; +/* Return the string with the given ID by calling DC_EVENT_GET_STRING. +The result must be free()'d! */ +#[no_mangle] +pub unsafe extern "C" fn dc_stock_str( + mut context: *mut dc_context_t, + mut id: libc::c_int, +) -> *mut libc::c_char { + return get_string(context, id, 0i32); +} +unsafe extern "C" fn get_string( + mut context: *mut 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.expect("non-null function pointer")( + context, + 2091i32, + id as uintptr_t, + qty as uintptr_t, + ) as *mut libc::c_char + } + if ret.is_null() { + ret = default_string(id) + } + return 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 extern "C" fn default_string(mut id: libc::c_int) -> *mut libc::c_char { + match id { + 1 => { + return dc_strdup(b"No messages.\x00" as *const u8 as + *const libc::c_char) + } + 2 => { + return dc_strdup(b"Me\x00" as *const u8 as *const libc::c_char) + } + 3 => { + return dc_strdup(b"Draft\x00" as *const u8 as *const libc::c_char) + } + 4 => { + return dc_strdup(b"%1$s member(s)\x00" as *const u8 as + *const libc::c_char) + } + 6 => { + return dc_strdup(b"%1$s contact(s)\x00" as *const u8 as + *const libc::c_char) + } + 7 => { + return dc_strdup(b"Voice message\x00" as *const u8 as + *const libc::c_char) + } + 8 => { + return dc_strdup(b"Contact requests\x00" as *const u8 as + *const libc::c_char) + } + 9 => { + return dc_strdup(b"Image\x00" as *const u8 as *const libc::c_char) + } + 23 => { + return dc_strdup(b"GIF\x00" as *const u8 as *const libc::c_char) + } + 10 => { + return dc_strdup(b"Video\x00" as *const u8 as *const libc::c_char) + } + 11 => { + return dc_strdup(b"Audio\x00" as *const u8 as *const libc::c_char) + } + 12 => { + return dc_strdup(b"File\x00" as *const u8 as *const libc::c_char) + } + 66 => { + return dc_strdup(b"Location\x00" as *const u8 as + *const libc::c_char) + } + 24 => { + return dc_strdup(b"Encrypted message\x00" as *const u8 as + *const libc::c_char) + } + 13 => { + return dc_strdup(b"Sent with my Delta Chat Messenger: https://delta.chat\x00" + as *const u8 as *const libc::c_char) + } + 14 => { + return dc_strdup(b"Hello, I\'ve just created the group \"%1$s\" for us.\x00" + as *const u8 as *const libc::c_char) + } + 15 => { + return dc_strdup(b"Group name changed from \"%1$s\" to \"%2$s\".\x00" + as *const u8 as *const libc::c_char) + } + 16 => { + return dc_strdup(b"Group image changed.\x00" as *const u8 as + *const libc::c_char) + } + 17 => { + return dc_strdup(b"Member %1$s added.\x00" as *const u8 as + *const libc::c_char) + } + 18 => { + return dc_strdup(b"Member %1$s removed.\x00" as *const u8 as + *const libc::c_char) + } + 19 => { + return dc_strdup(b"Group left.\x00" as *const u8 as + *const libc::c_char) + } + 64 => { + return dc_strdup(b"Location streaming enabled.\x00" as *const u8 + as *const libc::c_char) + } + 65 => { + return dc_strdup(b"Location streaming disabled.\x00" as *const u8 + as *const libc::c_char) + } + 62 => { + return dc_strdup(b"%1$s by %2$s.\x00" as *const u8 as + *const libc::c_char) + } + 63 => { + return dc_strdup(b"%1$s by me.\x00" as *const u8 as + *const libc::c_char) + } + 25 => { + return dc_strdup(b"End-to-end encryption available.\x00" as + *const u8 as *const libc::c_char) + } + 27 => { + return dc_strdup(b"Transport-encryption.\x00" as *const u8 as + *const libc::c_char) + } + 28 => { + return dc_strdup(b"No encryption.\x00" as *const u8 as + *const libc::c_char) + } + 30 => { + return dc_strdup(b"Fingerprints\x00" as *const u8 as + *const libc::c_char) + } + 31 => { + return dc_strdup(b"Return receipt\x00" as *const u8 as + *const libc::c_char) + } + 32 => { + return dc_strdup(b"This is a return receipt for the message \"%1$s\".\x00" + as *const u8 as *const libc::c_char) + } + 33 => { + return dc_strdup(b"Group image deleted.\x00" as *const u8 as + *const libc::c_char) + } + 34 => { + return dc_strdup(b"End-to-end encryption preferred.\x00" as + *const u8 as *const libc::c_char) + } + 35 => { + return dc_strdup(b"%1$s verified.\x00" as *const u8 as + *const libc::c_char) + } + 36 => { + return dc_strdup(b"Cannot verifiy %1$s\x00" as *const u8 as + *const libc::c_char) + } + 37 => { + return dc_strdup(b"Changed setup for %1$s\x00" as *const u8 as + *const libc::c_char) + } + 40 => { + return dc_strdup(b"Archived chats\x00" as *const u8 as + *const libc::c_char) + } + 41 => { + return dc_strdup(b"Starred messages\x00" as *const u8 as + *const libc::c_char) + } + 42 => { + return dc_strdup(b"Autocrypt Setup Message\x00" as *const u8 as + *const libc::c_char) + } + 43 => { + return dc_strdup(b"This is the Autocrypt Setup Message used to transfer your key between clients.\n\nTo decrypt and use your key, open the message in an Autocrypt-compliant client and enter the setup code presented on the generating device.\x00" + as *const u8 as *const libc::c_char) + } + 50 => { + return dc_strdup(b"Messages I sent to myself\x00" as *const u8 as + *const libc::c_char) + } + 29 => { + return dc_strdup(b"This message was encrypted for another setup.\x00" + as *const u8 as *const libc::c_char) + } + 60 => { + return dc_strdup(b"Cannot login as %1$s.\x00" as *const u8 as + *const libc::c_char) + } + 61 => { + return dc_strdup(b"Response from %1$s: %2$s\x00" as *const u8 as + *const libc::c_char) + } + _ => { } + } + return 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! */ +#[no_mangle] +pub unsafe extern "C" fn dc_stock_str_repl_string( + mut context: *mut dc_context_t, + mut id: libc::c_int, + mut to_insert: *const libc::c_char, +) -> *mut libc::c_char { + let mut ret: *mut libc::c_char = get_string(context, id, 0i32); + dc_str_replace( + &mut ret, + b"%1$s\x00" as *const u8 as *const libc::c_char, + to_insert, + ); + dc_str_replace( + &mut ret, + b"%1$d\x00" as *const u8 as *const libc::c_char, + to_insert, + ); + return ret; +} +#[no_mangle] +pub unsafe extern "C" fn dc_stock_str_repl_int( + mut context: *mut dc_context_t, + mut id: libc::c_int, + mut to_insert_int: libc::c_int, +) -> *mut libc::c_char { + let mut ret: *mut libc::c_char = get_string(context, id, to_insert_int); + let mut to_insert_str: *mut libc::c_char = dc_mprintf( + b"%i\x00" as *const u8 as *const libc::c_char, + to_insert_int as libc::c_int, + ); + dc_str_replace( + &mut ret, + b"%1$s\x00" as *const u8 as *const libc::c_char, + to_insert_str, + ); + dc_str_replace( + &mut ret, + b"%1$d\x00" as *const u8 as *const libc::c_char, + to_insert_str, + ); + free(to_insert_str as *mut libc::c_void); + return 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! */ +#[no_mangle] +pub unsafe extern "C" fn dc_stock_str_repl_string2( + mut context: *mut dc_context_t, + mut id: libc::c_int, + mut to_insert: *const libc::c_char, + mut to_insert2: *const libc::c_char, +) -> *mut libc::c_char { + let mut ret: *mut libc::c_char = get_string(context, id, 0i32); + dc_str_replace( + &mut ret, + b"%1$s\x00" as *const u8 as *const libc::c_char, + to_insert, + ); + dc_str_replace( + &mut ret, + b"%1$d\x00" as *const u8 as *const libc::c_char, + to_insert, + ); + dc_str_replace( + &mut ret, + b"%2$s\x00" as *const u8 as *const libc::c_char, + to_insert2, + ); + dc_str_replace( + &mut ret, + b"%2$d\x00" as *const u8 as *const libc::c_char, + to_insert2, + ); + return ret; +} +/* Misc. */ +#[no_mangle] +pub unsafe extern "C" fn dc_stock_system_msg( + mut context: *mut 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 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; + let mut from_displayname: *mut libc::c_char = 0 as *mut libc::c_char; + if str_id == 17i32 || str_id == 18i32 { + let mut mod_contact_id: uint32_t = dc_lookup_contact_id_by_addr(context, param1); + if mod_contact_id != 0i32 as libc::c_uint { + mod_contact = dc_get_contact(context, mod_contact_id); + mod_displayname = dc_contact_get_name_n_addr(mod_contact); + param1 = mod_displayname + } + } + let mut action: *mut libc::c_char = dc_stock_str_repl_string2(context, str_id, param1, param2); + if 0 != from_id { + if 0 != strlen(action) + && *action.offset(strlen(action).wrapping_sub(1i32 as libc::c_ulong) as isize) + as libc::c_int + == '.' as i32 + { + *action.offset(strlen(action).wrapping_sub(1i32 as libc::c_ulong) as isize) = + 0i32 as libc::c_char + } + from_contact = dc_get_contact(context, from_id); + from_displayname = dc_contact_get_display_name(from_contact); + ret = dc_stock_str_repl_string2( + context, + if from_id == 1i32 as libc::c_uint { + 63i32 + } else { + 62i32 + }, + action, + from_displayname, + ) + } else { + ret = dc_strdup(action) + } + free(action as *mut libc::c_void); + free(from_displayname as *mut libc::c_void); + free(mod_displayname as *mut libc::c_void); + dc_contact_unref(from_contact); + dc_contact_unref(mod_contact); + return ret; +} diff --git a/src/dc_strbuilder.rs b/src/dc_strbuilder.rs new file mode 100644 index 000000000..7eda07004 --- /dev/null +++ b/src/dc_strbuilder.rs @@ -0,0 +1,103 @@ +use libc; +extern "C" { + #[no_mangle] + fn malloc(_: libc::c_ulong) -> *mut libc::c_void; + #[no_mangle] + fn free(_: *mut libc::c_void); + #[no_mangle] + fn realloc(_: *mut libc::c_void, _: libc::c_ulong) -> *mut libc::c_void; + #[no_mangle] + fn exit(_: libc::c_int) -> !; + #[no_mangle] + fn strcpy(_: *mut libc::c_char, _: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn strlen(_: *const libc::c_char) -> libc::c_ulong; + #[no_mangle] + fn vsnprintf( + _: *mut libc::c_char, + _: libc::c_ulong, + _: *const libc::c_char, + _: ::std::ffi::VaList, + ) -> 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 __darwin_va_list = __builtin_va_list; +pub type va_list = __darwin_va_list; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_strbuilder { + pub buf: *mut libc::c_char, + pub allocated: libc::c_int, + pub free: libc::c_int, + pub eos: *mut libc::c_char, +} +pub type dc_strbuilder_t = _dc_strbuilder; +#[no_mangle] +pub unsafe extern "C" fn dc_strbuilder_init( + mut strbuilder: *mut dc_strbuilder_t, + mut init_bytes: libc::c_int, +) { + if strbuilder.is_null() { + return; + } + (*strbuilder).allocated = if init_bytes > 128i32 { + init_bytes + } else { + 128i32 + }; + (*strbuilder).buf = malloc((*strbuilder).allocated as libc::c_ulong) as *mut libc::c_char; + if (*strbuilder).buf.is_null() { + exit(38i32); + } + *(*strbuilder).buf.offset(0isize) = 0i32 as libc::c_char; + (*strbuilder).free = (*strbuilder).allocated - 1i32; + (*strbuilder).eos = (*strbuilder).buf; +} +#[no_mangle] +pub unsafe extern "C" fn dc_strbuilder_cat( + mut strbuilder: *mut dc_strbuilder_t, + mut text: *const libc::c_char, +) -> *mut libc::c_char { + if strbuilder.is_null() || text.is_null() { + return 0 as *mut libc::c_char; + } + let mut len: libc::c_int = strlen(text) as libc::c_int; + if len > (*strbuilder).free { + let mut add_bytes: libc::c_int = if len > (*strbuilder).allocated { + len + } else { + (*strbuilder).allocated + }; + let mut old_offset: libc::c_int = (*strbuilder).eos.wrapping_offset_from((*strbuilder).buf) + as libc::c_long as libc::c_int; + (*strbuilder).allocated = (*strbuilder).allocated + add_bytes; + (*strbuilder).buf = realloc( + (*strbuilder).buf as *mut libc::c_void, + ((*strbuilder).allocated + add_bytes) as libc::c_ulong, + ) as *mut libc::c_char; + if (*strbuilder).buf.is_null() { + exit(39i32); + } + (*strbuilder).free = (*strbuilder).free + add_bytes; + (*strbuilder).eos = (*strbuilder).buf.offset(old_offset as isize) + } + let mut ret: *mut libc::c_char = (*strbuilder).eos; + strcpy((*strbuilder).eos, text); + (*strbuilder).eos = (*strbuilder).eos.offset(len as isize); + (*strbuilder).free -= len; + return ret; +} +#[no_mangle] +pub unsafe extern "C" fn dc_strbuilder_empty(mut strbuilder: *mut dc_strbuilder_t) { + *(*strbuilder).buf.offset(0isize) = 0i32 as libc::c_char; + (*strbuilder).free = (*strbuilder).allocated - 1i32; + (*strbuilder).eos = (*strbuilder).buf; +} diff --git a/src/dc_strencode.rs b/src/dc_strencode.rs new file mode 100644 index 000000000..1c22f0604 --- /dev/null +++ b/src/dc_strencode.rs @@ -0,0 +1,908 @@ +use libc; + +use crate::dc_tools::*; + +extern "C" { + #[no_mangle] + static mut _DefaultRuneLocale: _RuneLocale; + #[no_mangle] + fn __maskrune(_: __darwin_ct_rune_t, _: libc::c_ulong) -> libc::c_int; + #[no_mangle] + fn __tolower(_: __darwin_ct_rune_t) -> __darwin_ct_rune_t; + #[no_mangle] + fn mmap_string_new(init: *const libc::c_char) -> *mut MMAPString; + #[no_mangle] + fn mmap_string_free(string: *mut MMAPString); + #[no_mangle] + fn mmap_string_append(string: *mut MMAPString, val: *const libc::c_char) -> *mut MMAPString; + #[no_mangle] + fn mmap_string_append_len( + string: *mut MMAPString, + val: *const libc::c_char, + len: size_t, + ) -> *mut MMAPString; + #[no_mangle] + fn mmap_string_append_c(string: *mut MMAPString, c: libc::c_char) -> *mut MMAPString; + #[no_mangle] + fn snprintf( + _: *mut libc::c_char, + _: libc::c_ulong, + _: *const libc::c_char, + _: ... + ) -> libc::c_int; + #[no_mangle] + 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; + #[no_mangle] + 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; + #[no_mangle] + fn malloc(_: libc::c_ulong) -> *mut libc::c_void; + #[no_mangle] + fn free(_: *mut libc::c_void); + #[no_mangle] + fn exit(_: libc::c_int) -> !; + #[no_mangle] + fn memset(_: *mut libc::c_void, _: libc::c_int, _: libc::c_ulong) -> *mut libc::c_void; + #[no_mangle] + fn strchr(_: *const libc::c_char, _: libc::c_int) -> *mut libc::c_char; + #[no_mangle] + fn strcmp(_: *const libc::c_char, _: *const libc::c_char) -> libc::c_int; + #[no_mangle] + fn strcpy(_: *mut libc::c_char, _: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn strlen(_: *const libc::c_char) -> libc::c_ulong; + #[no_mangle] + fn strdup(_: *const libc::c_char) -> *mut libc::c_char; + /* string tools */ + #[no_mangle] + fn dc_strdup(_: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn dc_null_terminate(_: *const libc::c_char, bytes: libc::c_int) -> *mut libc::c_char; +} +pub type __uint32_t = libc::c_uint; +pub type __darwin_ct_rune_t = libc::c_int; +pub type __darwin_size_t = libc::c_ulong; +pub type __darwin_wchar_t = libc::c_int; +pub type __darwin_rune_t = __darwin_wchar_t; +pub type size_t = __darwin_size_t; +#[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, + _: __darwin_size_t, + _: *mut *const libc::c_char, + ) -> __darwin_rune_t, + >, + pub __sputrune: Option< + unsafe extern "C" fn( + _: __darwin_rune_t, + _: *mut libc::c_char, + _: __darwin_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, +} +#[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; +pub type unnamed = libc::c_uint; +pub const MAILIMF_ERROR_FILE: unnamed = 4; +pub const MAILIMF_ERROR_INVAL: unnamed = 3; +pub const MAILIMF_ERROR_MEMORY: unnamed = 2; +pub const MAILIMF_ERROR_PARSE: unnamed = 1; +pub const MAILIMF_NO_ERROR: unnamed = 0; +pub type unnamed_0 = libc::c_uint; +pub const MAIL_CHARCONV_ERROR_CONV: unnamed_0 = 3; +pub const MAIL_CHARCONV_ERROR_MEMORY: unnamed_0 = 2; +pub const MAIL_CHARCONV_ERROR_UNKNOWN_CHARSET: unnamed_0 = 1; +pub const MAIL_CHARCONV_NO_ERROR: unnamed_0 = 0; +#[inline] +unsafe extern "C" fn isascii(mut _c: libc::c_int) -> libc::c_int { + return (_c & !0x7fi32 == 0i32) as libc::c_int; +} +#[inline] +unsafe extern "C" fn __istype(mut _c: __darwin_ct_rune_t, mut _f: libc::c_ulong) -> libc::c_int { + return if 0 != isascii(_c) { + (0 != _DefaultRuneLocale.__runetype[_c as usize] as libc::c_ulong & _f) as libc::c_int + } else { + (0 != __maskrune(_c, _f)) as libc::c_int + }; +} +#[inline] +unsafe extern "C" 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 + }; +} +#[no_mangle] +#[inline] +pub unsafe extern "C" fn isalnum(mut _c: libc::c_int) -> libc::c_int { + return __istype(_c, (0x100i64 | 0x400i64) as libc::c_ulong); +} +#[no_mangle] +#[inline] +pub unsafe extern "C" fn isdigit(mut _c: libc::c_int) -> libc::c_int { + return __isctype(_c, 0x400i64 as libc::c_ulong); +} + +#[no_mangle] +pub unsafe extern "C" fn dc_urlencode(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() { + return dc_strdup(b"\x00" as *const u8 as *const libc::c_char); + } + let mut buf: *mut libc::c_char = malloc( + strlen(to_encode) + .wrapping_mul(3i32 as libc::c_ulong) + .wrapping_add(1i32 as libc::c_ulong), + ) as *mut libc::c_char; + let mut pbuf: *mut libc::c_char = buf; + if buf.is_null() { + exit(46i32); + } + while 0 != *pstr { + if 0 != isalnum(*pstr as libc::c_int) + || *pstr as libc::c_int == '-' as i32 + || *pstr as libc::c_int == '_' as i32 + || *pstr as libc::c_int == '.' as i32 + || *pstr as libc::c_int == '~' as i32 + { + let fresh0 = pbuf; + pbuf = pbuf.offset(1); + *fresh0 = *pstr + } else if *pstr as libc::c_int == ' ' as i32 { + let fresh1 = pbuf; + pbuf = pbuf.offset(1); + *fresh1 = '+' as i32 as libc::c_char + } else { + let fresh2 = pbuf; + pbuf = pbuf.offset(1); + *fresh2 = '%' as i32 as libc::c_char; + let fresh3 = pbuf; + pbuf = pbuf.offset(1); + *fresh3 = int_2_uppercase_hex((*pstr as libc::c_int >> 4i32) as libc::c_char); + let fresh4 = pbuf; + pbuf = pbuf.offset(1); + *fresh4 = int_2_uppercase_hex((*pstr as libc::c_int & 15i32) as libc::c_char) + } + pstr = pstr.offset(1isize) + } + *pbuf = '\u{0}' as i32 as libc::c_char; + return buf; +} +/* ****************************************************************************** + * URL encoding and decoding, RFC 3986 + ******************************************************************************/ +unsafe extern "C" 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]; +} +#[no_mangle] +pub unsafe extern "C" 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() { + return dc_strdup(b"\x00" as *const u8 as *const libc::c_char); + } + let mut buf: *mut libc::c_char = + malloc(strlen(to_decode).wrapping_add(1i32 as libc::c_ulong)) as *mut libc::c_char; + let mut pbuf: *mut libc::c_char = buf; + if buf.is_null() { + exit(50i32); + } + while 0 != *pstr { + if *pstr as libc::c_int == '%' as i32 { + if 0 != *pstr.offset(1isize) as libc::c_int && 0 != *pstr.offset(2isize) as libc::c_int + { + let fresh5 = pbuf; + pbuf = pbuf.offset(1); + *fresh5 = ((hex_2_int(*pstr.offset(1isize)) as libc::c_int) << 4i32 + | hex_2_int(*pstr.offset(2isize)) as libc::c_int) + as libc::c_char; + pstr = pstr.offset(2isize) + } + } else if *pstr as libc::c_int == '+' as i32 { + let fresh6 = pbuf; + pbuf = pbuf.offset(1); + *fresh6 = ' ' as i32 as libc::c_char + } else { + let fresh7 = pbuf; + pbuf = pbuf.offset(1); + *fresh7 = *pstr + } + pstr = pstr.offset(1isize) + } + *pbuf = '\u{0}' as i32 as libc::c_char; + return buf; +} +unsafe extern "C" 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 + }) as libc::c_char; +} +#[no_mangle] +pub unsafe extern "C" 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; + let mut cur: *const libc::c_char = to_encode; + let mut mmapstr: *mut MMAPString = mmap_string_new(b"\x00" as *const u8 as *const libc::c_char); + if to_encode.is_null() || mmapstr.is_null() { + current_block = 8550051112593613029; + } else { + current_block = 4644295000439058019; + } + loop { + match current_block { + 8550051112593613029 => { + if !mmapstr.is_null() { + mmap_string_free(mmapstr); + } + break; + } + _ => { + 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; + begin = cur; + end = begin; + quote_words = 0i32; + do_quote = 1i32; + while *cur as libc::c_int != '\u{0}' as i32 { + get_word(cur, &mut cur, &mut do_quote); + if !(0 != do_quote) { + break; + } + quote_words = 1i32; + end = cur; + if *cur as libc::c_int != '\u{0}' as i32 { + cur = cur.offset(1isize) + } + } + if 0 != quote_words { + if 0 == quote_word( + b"utf-8\x00" as *const u8 as *const libc::c_char, + mmapstr, + begin, + end.wrapping_offset_from(begin) as libc::c_long as size_t, + ) { + current_block = 8550051112593613029; + continue; + } + if *end as libc::c_int == ' ' as i32 || *end as libc::c_int == '\t' as i32 { + if mmap_string_append_c(mmapstr, *end).is_null() { + current_block = 8550051112593613029; + continue; + } + end = end.offset(1isize) + } + if *end as libc::c_int != '\u{0}' as i32 { + if mmap_string_append_len( + mmapstr, + end, + cur.wrapping_offset_from(end) as libc::c_long as size_t, + ) + .is_null() + { + current_block = 8550051112593613029; + continue; + } + } + } else if mmap_string_append_len( + mmapstr, + begin, + cur.wrapping_offset_from(begin) as libc::c_long as size_t, + ) + .is_null() + { + current_block = 8550051112593613029; + continue; + } + if !(*cur as libc::c_int == ' ' as i32 || *cur as libc::c_int == '\t' as i32) { + current_block = 4644295000439058019; + continue; + } + if mmap_string_append_c(mmapstr, *cur).is_null() { + current_block = 8550051112593613029; + continue; + } + cur = cur.offset(1isize); + current_block = 4644295000439058019; + } else { + ret_str = strdup((*mmapstr).str_0); + current_block = 8550051112593613029; + } + } + } + } + return ret_str; +} +unsafe extern "C" 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 i: size_t = 0i32 as size_t; + let mut hex: [libc::c_char; 4] = [0; 4]; + let mut col: libc::c_int = 0i32; + if mmap_string_append(mmapstr, b"=?\x00" as *const u8 as *const libc::c_char).is_null() { + return 0i32; + } + if mmap_string_append(mmapstr, display_charset).is_null() { + return 0i32; + } + if mmap_string_append(mmapstr, b"?Q?\x00" as *const u8 as *const libc::c_char).is_null() { + return 0i32; + } + 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, + _ => { + if *cur as libc::c_uchar as libc::c_int >= 128i32 { + do_quote_char = 1i32 + } + } + } + if 0 != do_quote_char { + snprintf( + hex.as_mut_ptr(), + 4i32 as libc::c_ulong, + b"=%2.2X\x00" as *const u8 as *const libc::c_char, + *cur as libc::c_uchar as libc::c_int, + ); + if mmap_string_append(mmapstr, hex.as_mut_ptr()).is_null() { + return 0i32; + } + col += 3i32 + } else { + if *cur as libc::c_int == ' ' as i32 { + if mmap_string_append_c(mmapstr, '_' as i32 as libc::c_char).is_null() { + return 0i32; + } + } else if mmap_string_append_c(mmapstr, *cur).is_null() { + return 0i32; + } + col += 3i32 + } + cur = cur.offset(1isize); + i = i.wrapping_add(1) + } + if mmap_string_append(mmapstr, b"?=\x00" as *const u8 as *const libc::c_char).is_null() { + return 0i32; + } + return 1i32; +} +unsafe extern "C" fn get_word( + mut begin: *const libc::c_char, + mut pend: *mut *const libc::c_char, + mut pto_be_quoted: *mut libc::c_int, +) { + let mut cur: *const libc::c_char = begin; + while *cur as libc::c_int != ' ' as i32 + && *cur as libc::c_int != '\t' as i32 + && *cur as libc::c_int != '\u{0}' as i32 + { + cur = cur.offset(1isize) + } + *pto_be_quoted = to_be_quoted( + begin, + cur.wrapping_offset_from(begin) as libc::c_long as size_t, + ); + *pend = cur; +} +/* ****************************************************************************** + * Encode/decode header words, RFC 2047 + ******************************************************************************/ +/* see comment below */ +unsafe extern "C" 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 + | 61 | 63 | 95 => return 1i32, + _ => { + if *cur as libc::c_uchar as libc::c_int >= 128i32 { + return 1i32; + } + } + } + cur = cur.offset(1isize); + i = i.wrapping_add(1) + } + return 0i32; +} +#[no_mangle] +pub unsafe extern "C" 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; + } + let mut out: *mut libc::c_char = 0 as *mut libc::c_char; + let mut cur_token: size_t = 0i32 as size_t; + let mut r: libc::c_int = mailmime_encoded_phrase_parse( + b"iso-8859-1\x00" as *const u8 as *const libc::c_char, + in_0, + strlen(in_0), + &mut cur_token, + b"utf-8\x00" as *const u8 as *const libc::c_char, + &mut out, + ); + if r != MAILIMF_NO_ERROR as libc::c_int || out.is_null() { + out = dc_strdup(in_0) + } + return out; +} +#[no_mangle] +pub unsafe extern "C" 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 ucs4: libc::c_ulong = 0i32 as libc::c_ulong; + let mut bitbuf: libc::c_ulong = 0i32 as libc::c_ulong; + 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; + if to_encode.is_null() { + return dc_strdup(b"\x00" as *const u8 as *const libc::c_char); + } + res = malloc( + (2i32 as libc::c_ulong) + .wrapping_mul(strlen(to_encode)) + .wrapping_add(1i32 as libc::c_ulong), + ) as *mut libc::c_char; + dst = res; + if dst.is_null() { + exit(51i32); + } + utf7mode = 0i32 as libc::c_uint; + utf8total = 0i32 as libc::c_uint; + bitstogo = 0i32 as libc::c_uint; + utf8pos = 0i32 as libc::c_uint; + loop { + c = *to_encode as libc::c_uchar as libc::c_uint; + if !(c != '\u{0}' as i32 as libc::c_uint) { + break; + } + to_encode = to_encode.offset(1isize); + // normal character? + if c >= ' ' as i32 as libc::c_uint + && c <= '~' as i32 as libc::c_uint + && (c != '_' as i32 as libc::c_uint || 0 == change_spaces) + { + if 0 != utf7mode { + if 0 != bitstogo { + let fresh8 = dst; + dst = dst.offset(1); + *fresh8 = base64chars[(bitbuf << (6i32 as libc::c_uint).wrapping_sub(bitstogo) + & 0x3fi32 as libc::c_ulong) + as usize] + } + let fresh9 = dst; + dst = dst.offset(1); + *fresh9 = '-' as i32 as libc::c_char; + utf7mode = 0i32 as libc::c_uint; + utf8pos = 0i32 as libc::c_uint; + bitstogo = 0i32 as libc::c_uint; + utf8total = 0i32 as libc::c_uint + } + if 0 != change_spaces && c == ' ' as i32 as libc::c_uint { + let fresh10 = dst; + dst = dst.offset(1); + *fresh10 = '_' as i32 as libc::c_char + } else { + let fresh11 = dst; + dst = dst.offset(1); + *fresh11 = c as libc::c_char + } + if c == '&' as i32 as libc::c_uint { + let fresh12 = dst; + dst = dst.offset(1); + *fresh12 = '-' as i32 as libc::c_char + } + } else { + if 0 == utf7mode { + let fresh13 = dst; + dst = dst.offset(1); + *fresh13 = '&' as i32 as libc::c_char; + utf7mode = 1i32 as libc::c_uint + } + // encode ascii characters as themselves + if c < 0x80i32 as libc::c_uint { + ucs4 = c as libc::c_ulong + } else if 0 != utf8total { + ucs4 = ucs4 << 6i32 | c as libc::c_ulong & 0x3fu64; + utf8pos = utf8pos.wrapping_add(1); + if utf8pos < utf8total { + continue; + } + } else { + utf8pos = 1i32 as libc::c_uint; + if c < 0xe0i32 as libc::c_uint { + utf8total = 2i32 as libc::c_uint; + ucs4 = (c & 0x1fi32 as libc::c_uint) as libc::c_ulong + } else if c < 0xf0i32 as libc::c_uint { + utf8total = 3i32 as libc::c_uint; + ucs4 = (c & 0xfi32 as libc::c_uint) as libc::c_ulong + } else { + utf8total = 4i32 as libc::c_uint; + ucs4 = (c & 0x3i32 as libc::c_uint) as libc::c_ulong + } + continue; + } + utf8total = 0i32 as libc::c_uint; + loop { + if ucs4 >= 0x10000u64 { + ucs4 = ucs4.wrapping_sub(0x10000u64); + bitbuf = bitbuf << 16i32 | (ucs4 >> 10i32).wrapping_add(0xd800u64); + ucs4 = (ucs4 & 0x3ffu64).wrapping_add(0xdc00u64); + utf16flag = 1i32 as libc::c_uint + } else { + bitbuf = bitbuf << 16i32 | ucs4; + utf16flag = 0i32 as libc::c_uint + } + bitstogo = bitstogo.wrapping_add(16i32 as libc::c_uint); + while bitstogo >= 6i32 as libc::c_uint { + bitstogo = bitstogo.wrapping_sub(6i32 as libc::c_uint); + let fresh14 = dst; + dst = dst.offset(1); + *fresh14 = base64chars[(if 0 != bitstogo { + bitbuf >> bitstogo + } else { + bitbuf + } & 0x3fi32 as libc::c_ulong) + as usize] + } + if !(0 != utf16flag) { + break; + } + } + } + } + if 0 != utf7mode { + if 0 != bitstogo { + let fresh15 = dst; + dst = dst.offset(1); + *fresh15 = base64chars[(bitbuf << (6i32 as libc::c_uint).wrapping_sub(bitstogo) + & 0x3fi32 as libc::c_ulong) as usize] + } + let fresh16 = dst; + dst = dst.offset(1); + *fresh16 = '-' as i32 as libc::c_char + } + *dst = '\u{0}' as i32 as libc::c_char; + return 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, +]; +#[no_mangle] +pub unsafe extern "C" 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 = 0i32 as libc::c_ulong; + let mut utf16: libc::c_ulong = 0i32 as libc::c_ulong; + let mut bitbuf: libc::c_ulong = 0i32 as 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; + if to_decode.is_null() { + return dc_strdup(b"\x00" as *const u8 as *const libc::c_char); + } + res = malloc( + (4i32 as libc::c_ulong) + .wrapping_mul(strlen(to_decode)) + .wrapping_add(1i32 as libc::c_ulong), + ) as *mut libc::c_char; + dst = res; + src = to_decode; + if dst.is_null() { + exit(52i32); + } + memset( + base64.as_mut_ptr() as *mut libc::c_void, + 64i32, + ::std::mem::size_of::<[libc::c_uchar; 256]>() as libc::c_ulong, + ); + i = 0i32 as libc::c_uint; + while (i as libc::c_ulong) < ::std::mem::size_of::<[libc::c_char; 65]>() as libc::c_ulong { + base64[base64chars[i as usize] as libc::c_uint as usize] = i as libc::c_uchar; + i = i.wrapping_add(1) + } + while *src as libc::c_int != '\u{0}' as i32 { + let fresh17 = src; + src = src.offset(1); + c = *fresh17 as libc::c_uint; + if c != '&' as i32 as libc::c_uint || *src as libc::c_int == '-' as i32 { + if 0 != change_spaces && c == '_' as i32 as libc::c_uint { + let fresh18 = dst; + dst = dst.offset(1); + *fresh18 = ' ' as i32 as libc::c_char + } else { + let fresh19 = dst; + dst = dst.offset(1); + *fresh19 = c as libc::c_char + } + if c == '&' as i32 as libc::c_uint { + src = src.offset(1isize) + } + } else { + bitbuf = 0i32 as libc::c_ulong; + bitcount = 0i32 as libc::c_uint; + ucs4 = 0i32 as libc::c_ulong; + loop { + c = base64[*src as libc::c_uchar as usize] as libc::c_uint; + if !(c != 64i32 as libc::c_uint) { + break; + } + src = src.offset(1isize); + bitbuf = bitbuf << 6i32 | c as libc::c_ulong; + bitcount = bitcount.wrapping_add(6i32 as libc::c_uint); + // enough bits for a UTF-16 character? + if !(bitcount >= 16i32 as libc::c_uint) { + continue; + } + bitcount = bitcount.wrapping_sub(16i32 as libc::c_uint); + utf16 = if 0 != bitcount { + bitbuf >> bitcount + } else { + bitbuf + } & 0xffffi32 as libc::c_ulong; + // convert UTF16 to UCS4 + if utf16 >= 0xd800u64 && utf16 <= 0xdbffu64 { + ucs4 = utf16.wrapping_sub(0xd800u64) << 10i32 + } else { + if utf16 >= 0xdc00u64 && utf16 <= 0xdfffu64 { + ucs4 = ucs4 + .wrapping_add(utf16.wrapping_sub(0xdc00u64).wrapping_add(0x10000u64)) + } else { + ucs4 = utf16 + } + if ucs4 <= 0x7fu64 { + *dst.offset(0isize) = ucs4 as libc::c_char; + dst = dst.offset(1isize) + } else if ucs4 <= 0x7ffu64 { + *dst.offset(0isize) = + (0xc0i32 as libc::c_ulong | ucs4 >> 6i32) as libc::c_char; + *dst.offset(1isize) = (0x80i32 as libc::c_ulong + | ucs4 & 0x3fi32 as libc::c_ulong) + as libc::c_char; + dst = dst.offset(2isize) + } else if ucs4 <= 0xffffu64 { + *dst.offset(0isize) = + (0xe0i32 as libc::c_ulong | ucs4 >> 12i32) as libc::c_char; + *dst.offset(1isize) = (0x80i32 as libc::c_ulong + | ucs4 >> 6i32 & 0x3fi32 as libc::c_ulong) + as libc::c_char; + *dst.offset(2isize) = (0x80i32 as libc::c_ulong + | ucs4 & 0x3fi32 as libc::c_ulong) + as libc::c_char; + dst = dst.offset(3isize) + } else { + *dst.offset(0isize) = + (0xf0i32 as libc::c_ulong | ucs4 >> 18i32) as libc::c_char; + *dst.offset(1isize) = (0x80i32 as libc::c_ulong + | ucs4 >> 12i32 & 0x3fi32 as libc::c_ulong) + as libc::c_char; + *dst.offset(2isize) = (0x80i32 as libc::c_ulong + | ucs4 >> 6i32 & 0x3fi32 as libc::c_ulong) + as libc::c_char; + *dst.offset(3isize) = (0x80i32 as libc::c_ulong + | ucs4 & 0x3fi32 as libc::c_ulong) + as libc::c_char; + dst = dst.offset(4isize) + } + } + } + if *src as libc::c_int == '-' as i32 { + src = src.offset(1isize) + } + } + } + *dst = '\u{0}' as i32 as libc::c_char; + return res; +} +#[no_mangle] +pub unsafe extern "C" fn dc_needs_ext_header(mut to_check: *const libc::c_char) -> libc::c_int { + if !to_check.is_null() { + while 0 != *to_check { + if 0 == isalnum(*to_check as libc::c_int) + && *to_check as libc::c_int != '-' as i32 + && *to_check as libc::c_int != '_' as i32 + && *to_check as libc::c_int != '.' as i32 + && *to_check as libc::c_int != '~' as i32 + { + return 1i32; + } + to_check = to_check.offset(1isize) + } + } + return 0i32; +} +#[no_mangle] +pub unsafe extern "C" 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() { + return dc_strdup(b"utf-8\'\'\x00" as *const u8 as *const libc::c_char); + } + let mut buf: *mut libc::c_char = malloc( + strlen(b"utf-8\'\'\x00" as *const u8 as *const libc::c_char) + .wrapping_add(strlen(to_encode).wrapping_mul(3i32 as libc::c_ulong)) + .wrapping_add(1i32 as libc::c_ulong), + ) as *mut libc::c_char; + if buf.is_null() { + exit(46i32); + } + let mut pbuf: *mut libc::c_char = buf; + strcpy(pbuf, b"utf-8\'\'\x00" as *const u8 as *const libc::c_char); + pbuf = pbuf.offset(strlen(pbuf) as isize); + while 0 != *pstr { + if 0 != isalnum(*pstr as libc::c_int) + || *pstr as libc::c_int == '-' as i32 + || *pstr as libc::c_int == '_' as i32 + || *pstr as libc::c_int == '.' as i32 + || *pstr as libc::c_int == '~' as i32 + { + let fresh20 = pbuf; + pbuf = pbuf.offset(1); + *fresh20 = *pstr + } else { + let fresh21 = pbuf; + pbuf = pbuf.offset(1); + *fresh21 = '%' as i32 as libc::c_char; + let fresh22 = pbuf; + pbuf = pbuf.offset(1); + *fresh22 = int_2_uppercase_hex((*pstr as libc::c_int >> 4i32) as libc::c_char); + let fresh23 = pbuf; + pbuf = pbuf.offset(1); + *fresh23 = int_2_uppercase_hex((*pstr as libc::c_int & 15i32) as libc::c_char) + } + pstr = pstr.offset(1isize) + } + *pbuf = '\u{0}' as i32 as libc::c_char; + return buf; +} +#[no_mangle] +pub unsafe extern "C" 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; + if !to_decode.is_null() { + // get char set + p2 = strchr(to_decode, '\'' as i32); + if !(p2.is_null() || p2 == to_decode) { + /*no empty charset allowed*/ + charset = dc_null_terminate( + to_decode, + p2.wrapping_offset_from(to_decode) as libc::c_long as libc::c_int, + ); + p2 = p2.offset(1isize); + // skip language + p2 = strchr(p2, '\'' as i32); + if !p2.is_null() { + p2 = p2.offset(1isize); + decoded = dc_urldecode(p2); + if !charset.is_null() + && strcmp(charset, b"utf-8\x00" as *const u8 as *const libc::c_char) != 0i32 + && strcmp(charset, b"UTF-8\x00" as *const u8 as *const libc::c_char) != 0i32 + { + let mut converted: *mut libc::c_char = 0 as *mut libc::c_char; + let mut r: libc::c_int = charconv( + b"utf-8\x00" as *const u8 as *const libc::c_char, + charset, + decoded, + strlen(decoded), + &mut converted, + ); + if r == MAIL_CHARCONV_NO_ERROR as libc::c_int && !converted.is_null() { + free(decoded as *mut libc::c_void); + decoded = converted + } else { + free(converted as *mut libc::c_void); + } + } + } + } + } + free(charset as *mut libc::c_void); + return if !decoded.is_null() { + decoded + } else { + dc_strdup(to_decode) + }; +} diff --git a/src/dc_token.rs b/src/dc_token.rs new file mode 100644 index 000000000..82c6f031d --- /dev/null +++ b/src/dc_token.rs @@ -0,0 +1,835 @@ +use c2rust_bitfields::BitfieldStruct; +use libc; +extern "C" { + pub type mailstream_cancel; + pub type sqlite3; + pub type sqlite3_stmt; + #[no_mangle] + fn time(_: *mut time_t) -> time_t; + #[no_mangle] + fn sqlite3_bind_int(_: *mut sqlite3_stmt, _: libc::c_int, _: libc::c_int) -> libc::c_int; + #[no_mangle] + fn sqlite3_bind_int64(_: *mut sqlite3_stmt, _: libc::c_int, _: sqlite3_int64) -> libc::c_int; + #[no_mangle] + fn sqlite3_bind_text( + _: *mut sqlite3_stmt, + _: libc::c_int, + _: *const libc::c_char, + _: libc::c_int, + _: Option ()>, + ) -> libc::c_int; + #[no_mangle] + fn sqlite3_step(_: *mut sqlite3_stmt) -> libc::c_int; + #[no_mangle] + fn sqlite3_column_text(_: *mut sqlite3_stmt, iCol: libc::c_int) -> *const libc::c_uchar; + #[no_mangle] + fn sqlite3_finalize(pStmt: *mut sqlite3_stmt) -> libc::c_int; + /* tools, these functions are compatible to the corresponding sqlite3_* functions */ + #[no_mangle] + fn dc_sqlite3_prepare(_: *mut dc_sqlite3_t, sql: *const libc::c_char) -> *mut sqlite3_stmt; + #[no_mangle] + fn dc_strdup_keep_null(_: *const libc::c_char) -> *mut libc::c_char; +} +pub type __darwin_size_t = libc::c_ulong; +pub type __darwin_ssize_t = libc::c_long; +pub type __darwin_time_t = libc::c_long; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_cond_t { + pub __sig: libc::c_long, + pub __opaque: [libc::c_char; 40], +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_mutex_t { + pub __sig: libc::c_long, + pub __opaque: [libc::c_char; 56], +} +pub type __darwin_pthread_cond_t = _opaque_pthread_cond_t; +pub type __darwin_pthread_mutex_t = _opaque_pthread_mutex_t; +pub type uintptr_t = libc::c_ulong; +pub type size_t = __darwin_size_t; +pub type uint8_t = libc::c_uchar; +pub type uint32_t = libc::c_uint; +pub type ssize_t = __darwin_ssize_t; +pub type time_t = __darwin_time_t; +pub type pthread_cond_t = __darwin_pthread_cond_t; +pub type pthread_mutex_t = __darwin_pthread_mutex_t; +#[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; +#[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) -> (); +#[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; +#[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, + 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 { + 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_capability_data { + pub cap_list: *mut clist, +} +#[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_0, + 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_0 { + 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 extern "C" 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_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, +} +#[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_1, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed_1 { + pub ft_fetch_att: *mut mailimap_fetch_att, + pub ft_fetch_att_list: *mut clist, +} +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 unnamed_2 { + 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, +} +/* define DC_USE_RPGP to enable use of rPGP instead of netpgp where available; +preferrably, this should be done in the project configuration currently */ +//#define DC_USE_RPGP 1 +/* Includes that are used frequently. This file may also be used to create predefined headers. */ +/* * Structure behind dc_context_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_context { + pub magic: uint32_t, + pub userdata: *mut libc::c_void, + pub dbfile: *mut libc::c_char, + pub blobdir: *mut libc::c_char, + pub sql: *mut dc_sqlite3_t, + pub inbox: *mut dc_imap_t, + pub inboxidle_condmutex: pthread_mutex_t, + pub perform_inbox_jobs_needed: libc::c_int, + pub probe_imap_network: libc::c_int, + pub sentbox_thread: dc_jobthread_t, + pub mvbox_thread: dc_jobthread_t, + pub smtp: *mut dc_smtp_t, + pub smtpidle_cond: pthread_cond_t, + pub smtpidle_condmutex: pthread_mutex_t, + pub smtpidle_condflag: libc::c_int, + pub smtp_suspended: libc::c_int, + pub smtp_doing_jobs: libc::c_int, + pub perform_smtp_jobs_needed: libc::c_int, + pub probe_smtp_network: libc::c_int, + pub oauth2_critical: pthread_mutex_t, + 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 type dc_lot_t = _dc_lot; +/* * Structure behind dc_lot_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_lot { + pub magic: uint32_t, + pub text1_meaning: libc::c_int, + pub text1: *mut libc::c_char, + pub text2: *mut libc::c_char, + pub timestamp: time_t, + pub state: libc::c_int, + pub id: uint32_t, + pub fingerprint: *mut libc::c_char, + pub invitenumber: *mut libc::c_char, + pub auth: *mut libc::c_char, +} +/* * + * 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 = Option< + unsafe extern "C" fn( + _: *mut dc_context_t, + _: libc::c_int, + _: uintptr_t, + _: uintptr_t, + ) -> uintptr_t, +>; +/* * + * @mainpage Getting started + * + * This document describes how to handle the Delta Chat core library. + * For general information about Delta Chat itself, + * see and . + * + * Let's start. + * + * First of all, you have to **define an event-handler-function** + * that is called by the library on specific events + * (eg. when the configuration is done or when fresh messages arrive). + * With this function you can create a Delta Chat context then: + * + * ~~~ + * #include + * + * uintptr_t event_handler_func(dc_context_t* context, int event, + * uintptr_t data1, uintptr_t data2) + * { + * return 0; // for unhandled events, it is always safe to return 0 + * } + * + * dc_context_t* context = dc_context_new(event_handler_func, NULL, NULL); + * ~~~ + * + * After that, you should make sure, + * sending and receiving jobs are processed as needed. + * For this purpose, you have to **create two threads:** + * + * ~~~ + * #include + * + * void* imap_thread_func(void* context) + * { + * while (true) { + * dc_perform_imap_jobs(context); + * dc_perform_imap_fetch(context); + * dc_perform_imap_idle(context); + * } + * } + * + * void* smtp_thread_func(void* context) + * { + * while (true) { + * dc_perform_smtp_jobs(context); + * dc_perform_smtp_idle(context); + * } + * } + * + * static pthread_t imap_thread, smtp_thread; + * pthread_create(&imap_thread, NULL, imap_thread_func, context); + * pthread_create(&smtp_thread, NULL, smtp_thread_func, context); + * ~~~ + * + * The example above uses "pthreads", + * however, you can also use anything else for thread handling. + * NB: The deltachat-core library itself does not create any threads on its own, + * however, functions, unless stated otherwise, are thread-safe. + * + * After that you can **define and open a database.** + * The database is a normal sqlite-file and is created as needed: + * + * ~~~ + * dc_open(context, "example.db", NULL); + * ~~~ + * + * Now you can **configure the context:** + * + * ~~~ + * // use some real test credentials here + * dc_set_config(context, "addr", "alice@example.org"); + * dc_set_config(context, "mail_pw", "***"); + * dc_configure(context); + * ~~~ + * + * dc_configure() returns immediately, the configuration itself may take a while + * and is done by a job in the imap-thread you've defined above. + * Once done, the #DC_EVENT_CONFIGURE_PROGRESS reports success + * to the event_handler_func() that is also defined above. + * + * The configuration result is saved in the database, + * on subsequent starts it is not needed to call dc_configure() + * (you can check this using dc_is_configured()). + * + * Now you can **send the first message:** + * + * ~~~ + * // use a real testing address here + * uint32_t contact_id = dc_create_contact(context, NULL, "bob@example.org"); + * uint32_t chat_id = dc_create_chat_by_contact_id(context, contact_id); + * + * dc_send_text_msg(context, chat_id, "Hi, here is my first message!"); + * ~~~ + * + * dc_send_text_msg() returns immediately; + * the sending itself is done by a job in the smtp-thread you've defined above. + * If you check the testing address (bob) + * and you should have received a normal email. + * Answer this email in any email program with "Got it!" + * and the imap-thread you've create above will **receive the message**. + * + * You can then **list all messages** of a chat as follow: + * + * ~~~ + * dc_array_t* msglist = dc_get_chat_msgs(context, chat_id, 0, 0); + * for (int i = 0; i < dc_array_get_cnt(msglist); i++) + * { + * uint32_t msg_id = dc_array_get_id(msglist, i); + * dc_msg_t* msg = dc_get_msg(context, msg_id); + * char* text = dc_msg_get_text(msg); + * + * printf("Message %i: %s\n", i+1, text); + * + * free(text); + * dc_msg_unref(msg); + * } + * dc_array_unref(msglist); + * ~~~ + * + * This will output the following two lines: + * + * ~~~ + * Message 1: Hi, here is my first message! + * Message 2: Got it! + * ~~~ + * + * + * ## Class reference + * + * For a class reference, see the "Classes" link atop. + * + * + * ## Further hints + * + * Here are some additional, unsorted hints that may be useful. + * + * - For `get`-functions, you have to unref the return value in some way. + * + * - Strings in function arguments or return values are usually UTF-8 encoded. + * + * - The issue-tracker for the core library is here: + * + * + * The following points are important mainly + * for the authors of the library itself: + * + * - For indentation, use tabs. + * Alignments that are not placed at the beginning of a line + * should be done with spaces. + * + * - For padding between functions, + * classes etc. use 2 empty lines + * + * - Source files are encoded as UTF-8 with Unix line endings + * (a simple `LF`, `0x0A` or `\n`) + * + * If you need further assistance, + * please do not hesitate to contact us + * through the channels shown at https://delta.chat/en/contribute + * + * Please keep in mind, that your derived work + * must respect the Mozilla Public License 2.0 of libdeltachat + * and the respective licenses of the libraries libdeltachat links with. + * + * See you. + */ +/* * + * @class dc_context_t + * + * An object representing a single account. + * + * Each account is linked to an IMAP/SMTP account and uses a separate + * SQLite database for offline functionality and for account-related + * settings. + */ +pub type dc_context_t = _dc_context; +/* ** library-private **********************************************************/ +pub type dc_smtp_t = _dc_smtp; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_smtp { + 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 error: *mut libc::c_char, + pub error_etpan: libc::c_int, +} +pub type dc_jobthread_t = _dc_jobthread; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_jobthread { + 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, + 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, +} +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_imap { + 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 type dc_receive_imf_t = Option< + unsafe extern "C" 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_imap_t = _dc_imap; +pub type dc_precheck_imf_t = Option< + unsafe extern "C" 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< + unsafe extern "C" fn(_: *mut dc_imap_t, _: *const libc::c_char, _: *const libc::c_char) -> (), +>; +pub type dc_get_config_t = Option< + unsafe extern "C" fn( + _: *mut dc_imap_t, + _: *const libc::c_char, + _: *const libc::c_char, + ) -> *mut libc::c_char, +>; +/* ** library-private **********************************************************/ +pub type dc_sqlite3_t = _dc_sqlite3; +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_sqlite3 { + pub cobj: *mut sqlite3, + pub context: *mut dc_context_t, +} +pub type sqlite_int64 = libc::c_longlong; +pub type sqlite3_int64 = sqlite_int64; +pub type sqlite3_destructor_type = Option ()>; +// Token namespaces +pub type dc_tokennamespc_t = libc::c_uint; +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. +#[no_mangle] +pub unsafe extern "C" fn dc_token_save( + mut context: *mut 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()) + { + // foreign_id may be 0 + stmt = dc_sqlite3_prepare( + (*context).sql, + b"INSERT INTO tokens (namespc, foreign_id, token, timestamp) VALUES (?, ?, ?, ?);\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_bind_text(stmt, 3i32, token, -1i32, None); + sqlite3_bind_int64(stmt, 4i32, time(0 as *mut time_t) as sqlite3_int64); + sqlite3_step(stmt); + } + sqlite3_finalize(stmt); +} +#[no_mangle] +pub unsafe extern "C" fn dc_token_lookup( + mut context: *mut 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) + } + sqlite3_finalize(stmt); + return token; +} +#[no_mangle] +pub unsafe extern "C" fn dc_token_exists( + mut context: *mut 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()) + { + stmt = dc_sqlite3_prepare( + (*context).sql, + b"SELECT id FROM tokens WHERE namespc=? AND token=?;\x00" as *const u8 + as *const libc::c_char, + ); + sqlite3_bind_int(stmt, 1i32, namespc as libc::c_int); + sqlite3_bind_text(stmt, 2i32, token, -1i32, None); + exists = (sqlite3_step(stmt) != 0i32) as libc::c_int + } + sqlite3_finalize(stmt); + return exists; +} diff --git a/src/dc_tools.rs b/src/dc_tools.rs new file mode 100644 index 000000000..e124a92a1 --- /dev/null +++ b/src/dc_tools.rs @@ -0,0 +1,3109 @@ +use c2rust_bitfields::BitfieldStruct; +use libc; + +extern "C" { + pub type mailstream_cancel; + pub type __sFILEX; + pub type sqlite3; + #[no_mangle] + static mut _DefaultRuneLocale: _RuneLocale; + #[no_mangle] + pub fn dc_mprintf(format: *const libc::c_char, _: ...) -> *mut libc::c_char; + + #[no_mangle] + fn __maskrune(_: __darwin_ct_rune_t, _: libc::c_ulong) -> libc::c_int; + #[no_mangle] + fn __tolower(_: __darwin_ct_rune_t) -> __darwin_ct_rune_t; + #[no_mangle] + fn open(_: *const libc::c_char, _: libc::c_int, _: ...) -> libc::c_int; + #[no_mangle] + fn close(_: libc::c_int) -> libc::c_int; + #[no_mangle] + fn read(_: libc::c_int, _: *mut libc::c_void, _: size_t) -> ssize_t; + #[no_mangle] + fn write(__fd: libc::c_int, __buf: *const libc::c_void, __nbyte: size_t) -> ssize_t; + #[no_mangle] + fn mkdir(_: *const libc::c_char, _: mode_t) -> libc::c_int; + #[no_mangle] + fn stat(_: *const libc::c_char, _: *mut stat) -> libc::c_int; + #[no_mangle] + fn malloc(_: libc::c_ulong) -> *mut libc::c_void; + #[no_mangle] + fn calloc(_: libc::c_ulong, _: libc::c_ulong) -> *mut libc::c_void; + #[no_mangle] + fn free(_: *mut libc::c_void); + #[no_mangle] + fn atof(_: *const libc::c_char) -> libc::c_double; + #[no_mangle] + fn atoi(_: *const libc::c_char) -> libc::c_int; + #[no_mangle] + fn exit(_: libc::c_int) -> !; + #[no_mangle] + fn RAND_bytes(buf: *mut libc::c_uchar, num: libc::c_int) -> libc::c_int; + #[no_mangle] + fn RAND_pseudo_bytes(buf: *mut libc::c_uchar, num: libc::c_int) -> libc::c_int; + #[no_mangle] + fn localtime(_: *const time_t) -> *mut tm; + #[no_mangle] + fn time(_: *mut time_t) -> time_t; + #[no_mangle] + fn gmtime_r(_: *const time_t, _: *mut tm) -> *mut tm; + #[no_mangle] + fn localtime_r(_: *const time_t, _: *mut tm) -> *mut tm; + #[no_mangle] + fn carray_new(initsize: libc::c_uint) -> *mut carray; + #[no_mangle] + fn carray_add( + array: *mut carray, + data: *mut libc::c_void, + indx: *mut libc::c_uint, + ) -> libc::c_int; + #[no_mangle] + fn carray_free(array: *mut carray); + #[no_mangle] + fn clist_new() -> *mut clist; + #[no_mangle] + fn clist_insert_after(_: *mut clist, _: *mut clistiter, _: *mut libc::c_void) -> libc::c_int; + #[no_mangle] + fn fclose(_: *mut FILE) -> libc::c_int; + #[no_mangle] + fn fopen(_: *const libc::c_char, _: *const libc::c_char) -> *mut FILE; + #[no_mangle] + fn fread( + _: *mut libc::c_void, + _: libc::c_ulong, + _: libc::c_ulong, + _: *mut FILE, + ) -> libc::c_ulong; + #[no_mangle] + fn fseek(_: *mut FILE, _: libc::c_long, _: libc::c_int) -> libc::c_int; + #[no_mangle] + fn ftell(_: *mut FILE) -> libc::c_long; + #[no_mangle] + fn fwrite( + _: *const libc::c_void, + _: libc::c_ulong, + _: libc::c_ulong, + _: *mut FILE, + ) -> libc::c_ulong; + #[no_mangle] + fn remove(_: *const libc::c_char) -> libc::c_int; + #[no_mangle] + fn snprintf( + _: *mut libc::c_char, + _: libc::c_ulong, + _: *const libc::c_char, + _: ... + ) -> libc::c_int; + #[no_mangle] + fn vsnprintf( + _: *mut libc::c_char, + _: libc::c_ulong, + _: *const libc::c_char, + _: ::std::ffi::VaList, + ) -> libc::c_int; + #[no_mangle] + 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; + #[no_mangle] + fn memcpy(_: *mut libc::c_void, _: *const libc::c_void, _: libc::c_ulong) -> *mut libc::c_void; + #[no_mangle] + fn memmove(_: *mut libc::c_void, _: *const libc::c_void, _: libc::c_ulong) + -> *mut libc::c_void; + #[no_mangle] + fn memset(_: *mut libc::c_void, _: libc::c_int, _: libc::c_ulong) -> *mut libc::c_void; + #[no_mangle] + fn strcat(_: *mut libc::c_char, _: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn strchr(_: *const libc::c_char, _: libc::c_int) -> *mut libc::c_char; + #[no_mangle] + fn strcpy(_: *mut libc::c_char, _: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn strlen(_: *const libc::c_char) -> libc::c_ulong; + #[no_mangle] + fn strncmp(_: *const libc::c_char, _: *const libc::c_char, _: libc::c_ulong) -> libc::c_int; + #[no_mangle] + fn strncpy(_: *mut libc::c_char, _: *const libc::c_char, _: libc::c_ulong) + -> *mut libc::c_char; + #[no_mangle] + fn strrchr(_: *const libc::c_char, _: libc::c_int) -> *mut libc::c_char; + #[no_mangle] + fn strstr(_: *const libc::c_char, _: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn strdup(_: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn strndup(_: *const libc::c_char, _: libc::c_ulong) -> *mut libc::c_char; + #[no_mangle] + fn strcasecmp(_: *const libc::c_char, _: *const libc::c_char) -> libc::c_int; + #[no_mangle] + fn pthread_mutex_lock(_: *mut pthread_mutex_t) -> libc::c_int; + #[no_mangle] + fn pthread_mutex_unlock(_: *mut pthread_mutex_t) -> libc::c_int; + #[no_mangle] + fn dc_array_get_cnt(_: *const dc_array_t) -> size_t; + #[no_mangle] + fn dc_array_get_id(_: *const dc_array_t, index: size_t) -> uint32_t; + #[no_mangle] + fn dc_strbuilder_cat(_: *mut dc_strbuilder_t, text: *const libc::c_char) -> *mut libc::c_char; + #[no_mangle] + fn dc_strbuilder_init(_: *mut dc_strbuilder_t, init_bytes: libc::c_int); + #[no_mangle] + fn dc_log_warning(_: *mut dc_context_t, data1: libc::c_int, msg: *const libc::c_char, _: ...); + #[no_mangle] + fn dc_log_error(_: *mut dc_context_t, data1: libc::c_int, msg: *const libc::c_char, _: ...); +} +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 __uint16_t = libc::c_ushort; +pub type __int32_t = libc::c_int; +pub type __uint32_t = libc::c_uint; +pub type __int64_t = libc::c_longlong; +pub type __uint64_t = libc::c_ulonglong; +pub type __darwin_ct_rune_t = libc::c_int; +pub type __darwin_size_t = libc::c_ulong; +pub type __darwin_wchar_t = libc::c_int; +pub type __darwin_rune_t = __darwin_wchar_t; +pub type __darwin_ssize_t = libc::c_long; +pub type __darwin_time_t = libc::c_long; +pub type __darwin_blkcnt_t = __int64_t; +pub type __darwin_blksize_t = __int32_t; +pub type __darwin_dev_t = __int32_t; +pub type __darwin_gid_t = __uint32_t; +pub type __darwin_ino64_t = __uint64_t; +pub type __darwin_mode_t = __uint16_t; +pub type __darwin_off_t = __int64_t; +pub type __darwin_uid_t = __uint32_t; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_cond_t { + pub __sig: libc::c_long, + pub __opaque: [libc::c_char; 40], +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_mutex_t { + pub __sig: libc::c_long, + pub __opaque: [libc::c_char; 56], +} +pub type __darwin_pthread_cond_t = _opaque_pthread_cond_t; +pub type __darwin_pthread_mutex_t = _opaque_pthread_mutex_t; +pub type size_t = __darwin_size_t; +#[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, + _: __darwin_size_t, + _: *mut *const libc::c_char, + ) -> __darwin_rune_t, + >, + pub __sputrune: Option< + unsafe extern "C" fn( + _: __darwin_rune_t, + _: *mut libc::c_char, + _: __darwin_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 = __darwin_mode_t; +pub type off_t = __darwin_off_t; +pub type uintptr_t = libc::c_ulong; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct timespec { + pub tv_sec: __darwin_time_t, + pub tv_nsec: libc::c_long, +} +pub type uint64_t = libc::c_ulonglong; +pub type uint32_t = libc::c_uint; +pub type ssize_t = __darwin_ssize_t; +pub type uid_t = __darwin_uid_t; +pub type gid_t = __darwin_gid_t; +pub type time_t = __darwin_time_t; +pub type dev_t = __darwin_dev_t; +pub type blkcnt_t = __darwin_blkcnt_t; +pub type blksize_t = __darwin_blksize_t; +pub type nlink_t = __uint16_t; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct stat { + pub st_dev: dev_t, + pub st_mode: mode_t, + pub st_nlink: nlink_t, + pub st_ino: __darwin_ino64_t, + pub st_uid: uid_t, + pub st_gid: gid_t, + pub st_rdev: dev_t, + pub st_atimespec: timespec, + pub st_mtimespec: timespec, + pub st_ctimespec: timespec, + pub st_birthtimespec: timespec, + pub st_size: off_t, + pub st_blocks: blkcnt_t, + pub st_blksize: blksize_t, + pub st_flags: __uint32_t, + pub st_gen: __uint32_t, + pub st_lspare: __int32_t, + pub st_qspare: [__int64_t; 2], +} +pub type pthread_cond_t = __darwin_pthread_cond_t; +pub type pthread_mutex_t = __darwin_pthread_mutex_t; +pub type uint8_t = libc::c_uchar; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct tm { + pub tm_sec: libc::c_int, + pub tm_min: libc::c_int, + pub tm_hour: libc::c_int, + pub tm_mday: libc::c_int, + pub tm_mon: libc::c_int, + pub tm_year: libc::c_int, + pub tm_wday: libc::c_int, + pub tm_yday: libc::c_int, + pub tm_isdst: libc::c_int, + pub tm_gmtoff: libc::c_long, + pub tm_zone: *mut libc::c_char, +} +#[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; +#[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) -> (); +#[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 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 fpos_t = __darwin_off_t; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct __sbuf { + pub _base: *mut libc::c_uchar, + pub _size: libc::c_int, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct __sFILE { + pub _p: *mut libc::c_uchar, + pub _r: libc::c_int, + pub _w: libc::c_int, + pub _flags: libc::c_short, + pub _file: libc::c_short, + pub _bf: __sbuf, + pub _lbfsize: libc::c_int, + pub _cookie: *mut libc::c_void, + pub _close: Option libc::c_int>, + pub _read: Option< + unsafe extern "C" fn( + _: *mut libc::c_void, + _: *mut libc::c_char, + _: libc::c_int, + ) -> libc::c_int, + >, + pub _seek: + Option fpos_t>, + pub _write: Option< + unsafe extern "C" fn( + _: *mut libc::c_void, + _: *const libc::c_char, + _: libc::c_int, + ) -> libc::c_int, + >, + pub _ub: __sbuf, + pub _extra: *mut __sFILEX, + pub _ur: libc::c_int, + pub _ubuf: [libc::c_uchar; 3], + pub _nbuf: [libc::c_uchar; 1], + pub _lb: __sbuf, + pub _blksize: libc::c_int, + pub _offset: fpos_t, +} +pub type FILE = __sFILE; +#[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, + 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 { + 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_capability_data { + pub cap_list: *mut clist, +} +#[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_0, + 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_0 { + 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 extern "C" 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, +} +#[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, +} +#[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_1, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed_1 { + pub ft_fetch_att: *mut mailimap_fetch_att, + pub ft_fetch_att_list: *mut clist, +} +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 unnamed_2 { + 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, +} +/* define DC_USE_RPGP to enable use of rPGP instead of netpgp where available; +preferrably, this should be done in the project configuration currently */ +//#define DC_USE_RPGP 1 +/* Includes that are used frequently. This file may also be used to create predefined headers. */ +/* * Structure behind dc_context_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_context { + pub magic: uint32_t, + pub userdata: *mut libc::c_void, + pub dbfile: *mut libc::c_char, + pub blobdir: *mut libc::c_char, + pub sql: *mut dc_sqlite3_t, + pub inbox: *mut dc_imap_t, + pub inboxidle_condmutex: pthread_mutex_t, + pub perform_inbox_jobs_needed: libc::c_int, + pub probe_imap_network: libc::c_int, + pub sentbox_thread: dc_jobthread_t, + pub mvbox_thread: dc_jobthread_t, + pub smtp: *mut dc_smtp_t, + pub smtpidle_cond: pthread_cond_t, + pub smtpidle_condmutex: pthread_mutex_t, + pub smtpidle_condflag: libc::c_int, + pub smtp_suspended: libc::c_int, + pub smtp_doing_jobs: libc::c_int, + pub perform_smtp_jobs_needed: libc::c_int, + pub probe_smtp_network: libc::c_int, + pub oauth2_critical: pthread_mutex_t, + 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 type dc_lot_t = _dc_lot; +/* * Structure behind dc_lot_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_lot { + pub magic: uint32_t, + pub text1_meaning: libc::c_int, + pub text1: *mut libc::c_char, + pub text2: *mut libc::c_char, + pub timestamp: time_t, + pub state: libc::c_int, + pub id: uint32_t, + pub fingerprint: *mut libc::c_char, + pub invitenumber: *mut libc::c_char, + pub auth: *mut libc::c_char, +} +/* * + * 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 = Option< + unsafe extern "C" fn( + _: *mut dc_context_t, + _: libc::c_int, + _: uintptr_t, + _: uintptr_t, + ) -> uintptr_t, +>; +/* * + * @mainpage Getting started + * + * This document describes how to handle the Delta Chat core library. + * For general information about Delta Chat itself, + * see and . + * + * Let's start. + * + * First of all, you have to **define an event-handler-function** + * that is called by the library on specific events + * (eg. when the configuration is done or when fresh messages arrive). + * With this function you can create a Delta Chat context then: + * + * ~~~ + * #include + * + * uintptr_t event_handler_func(dc_context_t* context, int event, + * uintptr_t data1, uintptr_t data2) + * { + * return 0; // for unhandled events, it is always safe to return 0 + * } + * + * dc_context_t* context = dc_context_new(event_handler_func, NULL, NULL); + * ~~~ + * + * After that, you should make sure, + * sending and receiving jobs are processed as needed. + * For this purpose, you have to **create two threads:** + * + * ~~~ + * #include + * + * void* imap_thread_func(void* context) + * { + * while (true) { + * dc_perform_imap_jobs(context); + * dc_perform_imap_fetch(context); + * dc_perform_imap_idle(context); + * } + * } + * + * void* smtp_thread_func(void* context) + * { + * while (true) { + * dc_perform_smtp_jobs(context); + * dc_perform_smtp_idle(context); + * } + * } + * + * static pthread_t imap_thread, smtp_thread; + * pthread_create(&imap_thread, NULL, imap_thread_func, context); + * pthread_create(&smtp_thread, NULL, smtp_thread_func, context); + * ~~~ + * + * The example above uses "pthreads", + * however, you can also use anything else for thread handling. + * NB: The deltachat-core library itself does not create any threads on its own, + * however, functions, unless stated otherwise, are thread-safe. + * + * After that you can **define and open a database.** + * The database is a normal sqlite-file and is created as needed: + * + * ~~~ + * dc_open(context, "example.db", NULL); + * ~~~ + * + * Now you can **configure the context:** + * + * ~~~ + * // use some real test credentials here + * dc_set_config(context, "addr", "alice@example.org"); + * dc_set_config(context, "mail_pw", "***"); + * dc_configure(context); + * ~~~ + * + * dc_configure() returns immediately, the configuration itself may take a while + * and is done by a job in the imap-thread you've defined above. + * Once done, the #DC_EVENT_CONFIGURE_PROGRESS reports success + * to the event_handler_func() that is also defined above. + * + * The configuration result is saved in the database, + * on subsequent starts it is not needed to call dc_configure() + * (you can check this using dc_is_configured()). + * + * Now you can **send the first message:** + * + * ~~~ + * // use a real testing address here + * uint32_t contact_id = dc_create_contact(context, NULL, "bob@example.org"); + * uint32_t chat_id = dc_create_chat_by_contact_id(context, contact_id); + * + * dc_send_text_msg(context, chat_id, "Hi, here is my first message!"); + * ~~~ + * + * dc_send_text_msg() returns immediately; + * the sending itself is done by a job in the smtp-thread you've defined above. + * If you check the testing address (bob) + * and you should have received a normal email. + * Answer this email in any email program with "Got it!" + * and the imap-thread you've create above will **receive the message**. + * + * You can then **list all messages** of a chat as follow: + * + * ~~~ + * dc_array_t* msglist = dc_get_chat_msgs(context, chat_id, 0, 0); + * for (int i = 0; i < dc_array_get_cnt(msglist); i++) + * { + * uint32_t msg_id = dc_array_get_id(msglist, i); + * dc_msg_t* msg = dc_get_msg(context, msg_id); + * char* text = dc_msg_get_text(msg); + * + * printf("Message %i: %s\n", i+1, text); + * + * free(text); + * dc_msg_unref(msg); + * } + * dc_array_unref(msglist); + * ~~~ + * + * This will output the following two lines: + * + * ~~~ + * Message 1: Hi, here is my first message! + * Message 2: Got it! + * ~~~ + * + * + * ## Class reference + * + * For a class reference, see the "Classes" link atop. + * + * + * ## Further hints + * + * Here are some additional, unsorted hints that may be useful. + * + * - For `get`-functions, you have to unref the return value in some way. + * + * - Strings in function arguments or return values are usually UTF-8 encoded. + * + * - The issue-tracker for the core library is here: + * + * + * The following points are important mainly + * for the authors of the library itself: + * + * - For indentation, use tabs. + * Alignments that are not placed at the beginning of a line + * should be done with spaces. + * + * - For padding between functions, + * classes etc. use 2 empty lines + * + * - Source files are encoded as UTF-8 with Unix line endings + * (a simple `LF`, `0x0A` or `\n`) + * + * If you need further assistance, + * please do not hesitate to contact us + * through the channels shown at https://delta.chat/en/contribute + * + * Please keep in mind, that your derived work + * must respect the Mozilla Public License 2.0 of libdeltachat + * and the respective licenses of the libraries libdeltachat links with. + * + * See you. + */ +/* * + * @class dc_context_t + * + * An object representing a single account. + * + * Each account is linked to an IMAP/SMTP account and uses a separate + * SQLite database for offline functionality and for account-related + * settings. + */ +pub type dc_context_t = _dc_context; +/* ** library-private **********************************************************/ +pub type dc_smtp_t = _dc_smtp; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_smtp { + 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 error: *mut libc::c_char, + pub error_etpan: libc::c_int, +} +pub type dc_jobthread_t = _dc_jobthread; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_jobthread { + 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, + 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, +} +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_imap { + 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 type dc_receive_imf_t = Option< + unsafe extern "C" 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_imap_t = _dc_imap; +pub type dc_precheck_imf_t = Option< + unsafe extern "C" 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< + unsafe extern "C" fn(_: *mut dc_imap_t, _: *const libc::c_char, _: *const libc::c_char) -> (), +>; +pub type dc_get_config_t = Option< + unsafe extern "C" fn( + _: *mut dc_imap_t, + _: *const libc::c_char, + _: *const libc::c_char, + ) -> *mut libc::c_char, +>; +/* ** library-private **********************************************************/ +pub type dc_sqlite3_t = _dc_sqlite3; +/* * + * Library-internal. + */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_sqlite3 { + pub cobj: *mut sqlite3, + pub context: *mut dc_context_t, +} +/* * the structure behind dc_array_t */ +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_array { + 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, +} +pub type dc_array_t = _dc_array; +pub type dc_strbuilder_t = _dc_strbuilder; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _dc_strbuilder { + pub buf: *mut libc::c_char, + pub allocated: libc::c_int, + pub free: libc::c_int, + pub eos: *mut libc::c_char, +} +#[inline] +unsafe extern "C" fn isascii(mut _c: libc::c_int) -> libc::c_int { + return (_c & !0x7fi32 == 0i32) as libc::c_int; +} +#[inline] +unsafe extern "C" fn __istype(mut _c: __darwin_ct_rune_t, mut _f: libc::c_ulong) -> libc::c_int { + return if 0 != isascii(_c) { + (0 != _DefaultRuneLocale.__runetype[_c as usize] as libc::c_ulong & _f) as libc::c_int + } else { + (0 != __maskrune(_c, _f)) as libc::c_int + }; +} +#[no_mangle] +#[inline] +pub unsafe extern "C" fn isspace(mut _c: libc::c_int) -> libc::c_int { + return __istype(_c, 0x4000i64 as libc::c_ulong); +} +#[no_mangle] +#[inline] +pub unsafe extern "C" fn tolower(mut _c: libc::c_int) -> libc::c_int { + return __tolower(_c); +} +#[inline] +unsafe extern "C" fn carray_count(mut array: *mut carray) -> libc::c_uint { + return (*array).len; +} +#[inline] +unsafe extern "C" fn carray_get( + mut array: *mut carray, + mut indx: libc::c_uint, +) -> *mut libc::c_void { + return *(*array).array.offset(indx as isize); +} +/* Some tools and enhancements to the used libraries, there should be +no references to dc_context_t and other "larger" classes here. */ +// for carray etc. +/* ** library-private **********************************************************/ +/* math tools */ +#[no_mangle] +pub unsafe extern "C" 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) */ +#[no_mangle] +pub unsafe extern "C" 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; + if !s.is_null() { + ret = strdup(s); + if ret.is_null() { + exit(16i32); + } + } else { + ret = calloc(1i32 as libc::c_ulong, 1i32 as libc::c_ulong) as *mut libc::c_char; + if ret.is_null() { + exit(17i32); + } + } + return ret; +} +/* strdup(NULL) is undefined, safe_strdup_keep_null(NULL) returns NULL in this case */ +#[no_mangle] +pub unsafe extern "C" fn dc_strdup_keep_null(mut s: *const libc::c_char) -> *mut libc::c_char { + return if !s.is_null() { + dc_strdup(s) + } else { + 0 as *mut libc::c_char + }; +} +#[no_mangle] +pub unsafe extern "C" fn dc_atoi_null_is_0(mut s: *const libc::c_char) -> libc::c_int { + return if !s.is_null() { atoi(s) } else { 0i32 }; +} +#[no_mangle] +pub unsafe extern "C" 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 = + dc_mprintf(b"%f\x00" as *const u8 as *const libc::c_char, 1.2f64); + *test.offset(2isize) = 0i32 as libc::c_char; + let mut str_locale: *mut libc::c_char = dc_strdup(str); + dc_str_replace( + &mut str_locale, + b".\x00" as *const u8 as *const libc::c_char, + test.offset(1isize), + ); + 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; +} +#[no_mangle] +pub unsafe extern "C" fn dc_str_replace( + mut haystack: *mut *mut libc::c_char, + mut needle: *const libc::c_char, + mut replacement: *const libc::c_char, +) -> 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; + if haystack.is_null() + || (*haystack).is_null() + || needle.is_null() + || *needle.offset(0isize) as libc::c_int == 0i32 + { + return 0i32; + } + needle_len = strlen(needle) as libc::c_int; + replacement_len = (if !replacement.is_null() { + strlen(replacement) + } else { + 0i32 as libc::c_ulong + }) as libc::c_int; + loop { + let mut p2: *mut libc::c_char = + strstr((*haystack).offset(start_search_pos as isize), needle); + if p2.is_null() { + break; + } + start_search_pos = (p2.wrapping_offset_from(*haystack) as libc::c_long + + replacement_len as libc::c_long) as libc::c_int; + *p2 = 0i32 as libc::c_char; + p2 = p2.offset(needle_len as isize); + let mut new_string: *mut libc::c_char = dc_mprintf( + b"%s%s%s\x00" as *const u8 as *const libc::c_char, + *haystack, + if !replacement.is_null() { + replacement + } else { + b"\x00" as *const u8 as *const libc::c_char + }, + p2, + ); + free(*haystack as *mut libc::c_void); + *haystack = new_string; + replacements += 1 + } + return replacements; +} +#[no_mangle] +pub unsafe extern "C" 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 = + dc_mprintf(b"%f\x00" as *const u8 as *const libc::c_char, 1.2f64); + *test.offset(2isize) = 0i32 as libc::c_char; + let mut str: *mut libc::c_char = dc_mprintf(b"%f\x00" as *const u8 as *const libc::c_char, f); + dc_str_replace( + &mut str, + test.offset(1isize), + b".\x00" as *const u8 as *const libc::c_char, + ); + free(test as *mut libc::c_void); + return str; +} +#[no_mangle] +pub unsafe extern "C" 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; + 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) { + cur = cur.offset(1isize); + len = len.wrapping_sub(1) + } + if buf as *const libc::c_uchar != cur { + memmove( + buf as *mut libc::c_void, + cur as *const libc::c_void, + len.wrapping_add(1i32 as libc::c_ulong), + ); + } + }; +} +#[no_mangle] +pub unsafe extern "C" 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; + 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) { + cur = cur.offset(-1isize); + len = len.wrapping_sub(1) + } + *cur.offset( + (if 0 != isspace(*cur as libc::c_int) { + 0i32 + } else { + 1i32 + }) as isize, + ) = '\u{0}' as i32 as libc::c_uchar + }; +} +#[no_mangle] +pub unsafe extern "C" fn dc_trim(mut buf: *mut libc::c_char) { + dc_ltrim(buf); + dc_rtrim(buf); +} +/* the result must be free()'d */ +#[no_mangle] +pub unsafe extern "C" 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 = p.offset(1isize) + } + return out; +} +#[no_mangle] +pub unsafe extern "C" 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 = p.offset(1isize) + } +} +#[no_mangle] +pub unsafe extern "C" fn dc_str_contains( + mut haystack: *const libc::c_char, + mut needle: *const libc::c_char, +) -> libc::c_int { + if haystack.is_null() || needle.is_null() { + return 0i32; + } + if !strstr(haystack, needle).is_null() { + return 1i32; + } + let mut haystack_lower: *mut libc::c_char = dc_strlower(haystack); + let mut needle_lower: *mut libc::c_char = dc_strlower(needle); + let mut ret: libc::c_int = if !strstr(haystack_lower, needle_lower).is_null() { + 1i32 + } else { + 0i32 + }; + free(haystack_lower as *mut libc::c_void); + free(needle_lower as *mut libc::c_void); + return ret; +} +/* the result must be free()'d */ +#[no_mangle] +pub unsafe extern "C" fn dc_null_terminate( + mut in_0: *const libc::c_char, + mut bytes: libc::c_int, +) -> *mut libc::c_char { + let mut out: *mut libc::c_char = malloc((bytes + 1i32) as libc::c_ulong) as *mut libc::c_char; + if out.is_null() { + exit(45i32); + } + if !in_0.is_null() && bytes > 0i32 { + strncpy(out, in_0, bytes as libc::c_ulong); + } + *out.offset(bytes as isize) = 0i32 as libc::c_char; + return out; +} +#[no_mangle] +pub unsafe extern "C" 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: libc::c_int = 0i32; + if !(buf.is_null() || bytes <= 0i32 as libc::c_ulong) { + hex = calloc( + ::std::mem::size_of::() as libc::c_ulong, + bytes + .wrapping_mul(2i32 as libc::c_ulong) + .wrapping_add(1i32 as libc::c_ulong), + ) as *mut libc::c_char; + if !hex.is_null() { + i = 0i32; + while (i as libc::c_ulong) < bytes { + snprintf( + &mut *hex.offset((i * 2i32) as isize) as *mut libc::c_char, + 3i32 as libc::c_ulong, + b"%02X\x00" as *const u8 as *const libc::c_char, + *buf.offset(i as isize) as libc::c_int, + ); + i += 1 + } + } + } + return hex; +} +/* remove all \r characters from string */ +#[no_mangle] +pub unsafe extern "C" fn dc_remove_cr_chars(mut buf: *mut libc::c_char) { + /* search for first `\r` */ + let mut p1: *const libc::c_char = buf; + while 0 != *p1 { + if *p1 as libc::c_int == '\r' as i32 { + break; + } + p1 = p1.offset(1isize) + } + /* p1 is `\r` or null-byte; start removing `\r` */ + let mut p2: *mut libc::c_char = p1 as *mut libc::c_char; + while 0 != *p1 { + if *p1 as libc::c_int != '\r' as i32 { + *p2 = *p1; + p2 = p2.offset(1isize) + } + p1 = p1.offset(1isize) + } + *p2 = 0i32 as libc::c_char; +} +#[no_mangle] +pub unsafe extern "C" 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 */ +#[no_mangle] +pub unsafe extern "C" fn dc_replace_bad_utf8_chars(mut buf: *mut libc::c_char) { + let mut current_block: u64; + if buf.is_null() { + return; + } + /* 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; + i = 0i32; + ix = p1len; + 's_36: loop { + if !(i < ix) { + current_block = 13550086250199790493; + break; + } + c = *p1.offset(i as isize) as libc::c_int; + if c > 0i32 && c <= 0x7fi32 { + n = 0i32 + } else if c & 0xe0i32 == 0xc0i32 { + n = 1i32 + } else if c == 0xedi32 + && i < ix - 1i32 + && *p1.offset((i + 1i32) as isize) as libc::c_int & 0xa0i32 == 0xa0i32 + { + /* U+d800 to U+dfff */ + current_block = 2775201239069267972; + break; + } else if c & 0xf0i32 == 0xe0i32 { + n = 2i32 + } else if c & 0xf8i32 == 0xf0i32 { + n = 3i32 + } else { + //else if ((c & 0xFC) == 0xF8) { n=4; } /* 111110bb - not valid in https://tools.ietf.org/html/rfc3629 */ + //else if ((c & 0xFE) == 0xFC) { n=5; } /* 1111110b - not valid in https://tools.ietf.org/html/rfc3629 */ + current_block = 2775201239069267972; + break; + } + j = 0i32; + while j < n && i < ix { + /* n bytes matching 10bbbbbb follow ? */ + i += 1; + if i == ix || *p1.offset(i as isize) as libc::c_int & 0xc0i32 != 0x80i32 { + current_block = 2775201239069267972; + break 's_36; + } + j += 1 + } + i += 1 + } + match current_block { + 13550086250199790493 => return, + _ => { + while 0 != *p1 { + if *p1 as libc::c_int > 0x7fi32 { + *p1 = '_' as i32 as libc::c_uchar + } + p1 = p1.offset(1isize) + } + return; + } + }; +} +#[no_mangle] +pub unsafe extern "C" fn dc_utf8_strlen(mut s: *const libc::c_char) -> size_t { + if s.is_null() { + return 0i32 as size_t; + } + let mut i: size_t = 0i32 as size_t; + let mut j: size_t = 0i32 as size_t; + while 0 != *s.offset(i as isize) { + if *s.offset(i as isize) as libc::c_int & 0xc0i32 != 0x80i32 { + j = j.wrapping_add(1) + } + i = i.wrapping_add(1) + } + return j; +} +#[no_mangle] +pub unsafe extern "C" fn dc_truncate_str( + mut buf: *mut libc::c_char, + mut approx_chars: libc::c_int, +) { + if approx_chars > 0i32 + && strlen(buf) + > (approx_chars as libc::c_ulong) + .wrapping_add(strlen(b"[...]\x00" as *const u8 as *const libc::c_char)) + { + let mut p: *mut libc::c_char = &mut *buf.offset(approx_chars as isize) as *mut libc::c_char; + *p = 0i32 as libc::c_char; + if !strchr(buf, ' ' as i32).is_null() { + while *p.offset(-1i32 as isize) as libc::c_int != ' ' as i32 + && *p.offset(-1i32 as isize) as libc::c_int != '\n' as i32 + { + p = p.offset(-1isize); + *p = 0i32 as libc::c_char + } + } + strcat(p, b"[...]\x00" as *const u8 as *const libc::c_char); + }; +} +#[no_mangle] +pub unsafe extern "C" fn dc_truncate_n_unwrap_str( + mut buf: *mut libc::c_char, + mut approx_characters: libc::c_int, + mut do_unwrap: libc::c_int, +) { + /* Function unwraps the given string and removes unnecessary whitespace. + Function stops processing after approx_characters are processed. + (as we're using UTF-8, for simplicity, we cut the string only at whitespaces). */ + /* a single line is truncated `...` instead of `[...]` (the former is typically also used by the UI to fit strings in a rectangle) */ + let mut ellipse_utf8: *const libc::c_char = if 0 != do_unwrap { + b" ...\x00" as *const u8 as *const libc::c_char + } else { + b" [...]\x00" as *const u8 as *const libc::c_char + }; + let mut lastIsCharacter: libc::c_int = 0i32; + /* force unsigned - otherwise the `> ' '` comparison will fail */ + let mut p1: *mut libc::c_uchar = buf as *mut libc::c_uchar; + while 0 != *p1 { + if *p1 as libc::c_int > ' ' as i32 { + lastIsCharacter = 1i32 + } else if 0 != lastIsCharacter { + let mut used_bytes: size_t = (p1 as uintptr_t).wrapping_sub(buf as uintptr_t) as size_t; + if dc_utf8_strnlen(buf, used_bytes) >= approx_characters as libc::c_ulong { + let mut buf_bytes: size_t = strlen(buf); + if buf_bytes.wrapping_sub(used_bytes) >= strlen(ellipse_utf8) { + strcpy(p1 as *mut libc::c_char, ellipse_utf8); + } + break; + } else { + lastIsCharacter = 0i32; + if 0 != do_unwrap { + *p1 = ' ' as i32 as libc::c_uchar + } + } + } else if 0 != do_unwrap { + *p1 = '\r' as i32 as libc::c_uchar + } + p1 = p1.offset(1isize) + } + if 0 != do_unwrap { + dc_remove_cr_chars(buf); + }; +} +unsafe extern "C" 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; + } + let mut i: size_t = 0i32 as size_t; + let mut j: size_t = 0i32 as size_t; + while i < n { + if *s.offset(i as isize) as libc::c_int & 0xc0i32 != 0x80i32 { + j = j.wrapping_add(1) + } + i = i.wrapping_add(1) + } + return j; +} +/* split string into lines*/ +#[no_mangle] +pub unsafe extern "C" 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); + let mut line_chars: size_t = 0i32 as size_t; + let mut p1: *const libc::c_char = buf_terminated; + let mut line_start: *const libc::c_char = p1; + let mut l_indx: libc::c_uint = 0i32 as libc::c_uint; + while 0 != *p1 { + if *p1 as libc::c_int == '\n' as i32 { + carray_add( + lines, + strndup(line_start, line_chars) as *mut libc::c_void, + &mut l_indx, + ); + p1 = p1.offset(1isize); + line_start = p1; + line_chars = 0i32 as size_t + } else { + p1 = p1.offset(1isize); + line_chars = line_chars.wrapping_add(1) + } + } + carray_add( + lines, + strndup(line_start, line_chars) as *mut libc::c_void, + &mut l_indx, + ); + return lines; +} +#[no_mangle] +pub unsafe extern "C" fn dc_free_splitted_lines(mut lines: *mut carray) { + if !lines.is_null() { + let mut i: libc::c_int = 0; + let mut cnt: libc::c_int = carray_count(lines) as libc::c_int; + i = 0i32; + while i < cnt { + free(carray_get(lines, i as libc::c_uint)); + i += 1 + } + carray_free(lines); + }; +} +/* insert a break every n characters, the return must be free()'d */ +#[no_mangle] +pub unsafe extern "C" fn dc_insert_breaks( + mut in_0: *const libc::c_char, + mut break_every: libc::c_int, + mut break_chars: *const libc::c_char, +) -> *mut libc::c_char { + if in_0.is_null() || break_every <= 0i32 || break_chars.is_null() { + return dc_strdup(in_0); + } + let mut out_len: libc::c_int = strlen(in_0) as libc::c_int; + let mut chars_added: libc::c_int = 0i32; + let mut break_chars_len: libc::c_int = strlen(break_chars) as libc::c_int; + out_len += (out_len / break_every + 1i32) * break_chars_len + 1i32; + let mut out: *mut libc::c_char = malloc(out_len as libc::c_ulong) as *mut libc::c_char; + if out.is_null() { + return 0 as *mut libc::c_char; + } + let mut i: *const libc::c_char = in_0; + let mut o: *mut libc::c_char = out; + while 0 != *i { + let fresh1 = o; + o = o.offset(1); + let fresh0 = i; + i = i.offset(1); + *fresh1 = *fresh0; + chars_added += 1; + if chars_added == break_every && 0 != *i as libc::c_int { + strcpy(o, break_chars); + o = o.offset(break_chars_len as isize); + chars_added = 0i32 + } + } + *o = 0i32 as libc::c_char; + return out; +} +#[no_mangle] +pub unsafe extern "C" fn dc_str_from_clist( + mut list: *const clist, + mut delimiter: *const libc::c_char, +) -> *mut libc::c_char { + let mut str: dc_strbuilder_t = _dc_strbuilder { + buf: 0 as *mut libc::c_char, + allocated: 0, + free: 0, + eos: 0 as *mut libc::c_char, + }; + dc_strbuilder_init(&mut str, 256i32); + if !list.is_null() { + let mut cur: *mut clistiter = (*list).first; + while !cur.is_null() { + let mut rfc724_mid: *const libc::c_char = (if !cur.is_null() { + (*cur).data + } else { + 0 as *mut libc::c_void + }) as *const libc::c_char; + if !rfc724_mid.is_null() { + if 0 != *str.buf.offset(0isize) as libc::c_int && !delimiter.is_null() { + dc_strbuilder_cat(&mut str, delimiter); + } + dc_strbuilder_cat(&mut str, rfc724_mid); + } + cur = if !cur.is_null() { + (*cur).next + } else { + 0 as *mut clistcell_s + } + } + } + return str.buf; +} +#[no_mangle] +pub unsafe extern "C" fn dc_str_to_clist( + mut str: *const libc::c_char, + mut delimiter: *const libc::c_char, +) -> *mut clist { + let mut list: *mut clist = clist_new(); + if list.is_null() { + exit(54i32); + } + if !str.is_null() && !delimiter.is_null() && strlen(delimiter) >= 1i32 as libc::c_ulong { + let mut p1: *const libc::c_char = str; + loop { + let mut p2: *const libc::c_char = strstr(p1, delimiter); + if p2.is_null() { + clist_insert_after(list, (*list).last, strdup(p1) as *mut libc::c_void); + break; + } else { + clist_insert_after( + list, + (*list).last, + strndup( + p1, + p2.wrapping_offset_from(p1) as libc::c_long as libc::c_ulong, + ) as *mut libc::c_void, + ); + p1 = p2.offset(strlen(delimiter) as isize) + } + } + } + return list; +} +#[no_mangle] +pub unsafe extern "C" 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: + - contrast to black and to white + - work as a text-color + - being noticable on a typical map + - harmonize together while being different enough + (therefore, we cannot just use random rgb colors :) */ + static mut colors: [uint32_t; 16] = [ + 0xe56555i32 as uint32_t, + 0xf28c48i32 as uint32_t, + 0x8e85eei32 as uint32_t, + 0x76c84di32 as uint32_t, + 0x5bb6cci32 as uint32_t, + 0x549cddi32 as uint32_t, + 0xd25c99i32 as uint32_t, + 0xb37800i32 as uint32_t, + 0xf23030i32 as uint32_t, + 0x39b249i32 as uint32_t, + 0xbb243bi32 as uint32_t, + 0x964078i32 as uint32_t, + 0x66874fi32 as uint32_t, + 0x308ab9i32 as uint32_t, + 0x127ed0i32 as uint32_t, + 0xbe450ci32 as uint32_t, + ]; + let mut checksum: libc::c_int = 0i32; + let mut str_len: libc::c_int = strlen(str_lower) as libc::c_int; + let mut i: libc::c_int = 0i32; + while i < str_len { + checksum += (i + 1i32) * *str_lower.offset(i as isize) as libc::c_int; + checksum %= 0xffffffi32; + i += 1 + } + let mut color_index: libc::c_int = (checksum as libc::c_ulong).wrapping_rem( + (::std::mem::size_of::<[uint32_t; 16]>() as libc::c_ulong) + .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; +} +/* clist tools */ +/* calls free() for each item content */ +#[no_mangle] +pub unsafe extern "C" fn clist_free_content(mut haystack: *const clist) { + let mut iter: *mut clistiter = (*haystack).first; + while !iter.is_null() { + free((*iter).data); + (*iter).data = 0 as *mut libc::c_void; + iter = if !iter.is_null() { + (*iter).next + } else { + 0 as *mut clistcell_s + } + } +} +#[no_mangle] +pub unsafe extern "C" fn clist_search_string_nocase( + mut haystack: *const clist, + mut needle: *const libc::c_char, +) -> libc::c_int { + let mut iter: *mut clistiter = (*haystack).first; + while !iter.is_null() { + if strcasecmp((*iter).data as *const libc::c_char, needle) == 0i32 { + return 1i32; + } + iter = if !iter.is_null() { + (*iter).next + } else { + 0 as *mut clistcell_s + } + } + return 0i32; +} +/* date/time tools */ +/* the result is UTC or DC_INVALID_TIMESTAMP */ +#[no_mangle] +pub unsafe extern "C" fn dc_timestamp_from_date(mut date_time: *mut mailimf_date_time) -> time_t { + let mut tmval: 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 timeval: time_t = 0i32 as time_t; + let mut zone_min: libc::c_int = 0i32; + let mut zone_hour: libc::c_int = 0i32; + memset( + &mut tmval as *mut tm as *mut libc::c_void, + 0i32, + ::std::mem::size_of::() as libc::c_ulong, + ); + tmval.tm_sec = (*date_time).dt_sec; + tmval.tm_min = (*date_time).dt_min; + tmval.tm_hour = (*date_time).dt_hour; + tmval.tm_mday = (*date_time).dt_day; + tmval.tm_mon = (*date_time).dt_month - 1i32; + if (*date_time).dt_year < 1000i32 { + tmval.tm_year = (*date_time).dt_year + 2000i32 - 1900i32 + } else { + tmval.tm_year = (*date_time).dt_year - 1900i32 + } + timeval = mkgmtime(&mut tmval); + if (*date_time).dt_zone >= 0i32 { + zone_hour = (*date_time).dt_zone / 100i32; + zone_min = (*date_time).dt_zone % 100i32 + } else { + zone_hour = -(-(*date_time).dt_zone / 100i32); + zone_min = -(-(*date_time).dt_zone % 100i32) + } + timeval -= (zone_hour * 3600i32 + zone_min * 60i32) as libc::c_long; + return timeval; +} +#[no_mangle] +pub unsafe extern "C" 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 mytm: 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, + }; + yourtm = *tmp; + saved_seconds = yourtm.tm_sec; + yourtm.tm_sec = 0i32; + bits = 0i32; + t = 1i32 as time_t; + while t > 0i32 as libc::c_long { + bits += 1; + t <<= 1i32 + } + if bits > 40i32 { + bits = 40i32 + } + t = if t < 0i32 as libc::c_long { + 0i32 as libc::c_long + } else { + (1i32 as time_t) << bits + }; + loop { + gmtime_r(&mut t, &mut mytm); + dir = tmcomp(&mut mytm, &mut yourtm); + if !(dir != 0i32) { + break; + } + let fresh2 = bits; + bits = bits - 1; + if fresh2 < 0i32 { + return -1i32 as time_t; + } + if bits < 0i32 { + t -= 1 + } else if dir > 0i32 { + t -= (1i32 as time_t) << bits + } else { + t += (1i32 as time_t) << bits + } + } + t += saved_seconds as libc::c_long; + return t; +} +/* ****************************************************************************** + * date/time tools + ******************************************************************************/ +unsafe extern "C" fn tmcomp(mut atmp: *mut tm, mut btmp: *mut tm) -> libc::c_int { + let mut result: libc::c_int = 0i32; + result = (*atmp).tm_year - (*btmp).tm_year; + if result == 0i32 + && { + result = (*atmp).tm_mon - (*btmp).tm_mon; + result == 0i32 + } + && { + result = (*atmp).tm_mday - (*btmp).tm_mday; + result == 0i32 + } + && { + result = (*atmp).tm_hour - (*btmp).tm_hour; + result == 0i32 + } + && { + result = (*atmp).tm_min - (*btmp).tm_min; + result == 0i32 + } + { + result = (*atmp).tm_sec - (*btmp).tm_sec + } + return result; +} +/* the return value must be free()'d */ +#[no_mangle] +pub unsafe extern "C" fn dc_timestamp_to_str(mut wanted: time_t) -> *mut libc::c_char { + let mut wanted_struct: 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, + }; + memcpy( + &mut wanted_struct as *mut tm as *mut libc::c_void, + localtime(&mut wanted) as *const libc::c_void, + ::std::mem::size_of::() as libc::c_ulong, + ); + return dc_mprintf( + b"%02i.%02i.%04i %02i:%02i:%02i\x00" as *const u8 as *const libc::c_char, + wanted_struct.tm_mday as libc::c_int, + wanted_struct.tm_mon as libc::c_int + 1i32, + wanted_struct.tm_year as libc::c_int + 1900i32, + wanted_struct.tm_hour as libc::c_int, + wanted_struct.tm_min as libc::c_int, + wanted_struct.tm_sec as libc::c_int, + ); +} +#[no_mangle] +pub unsafe extern "C" 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; +} +#[no_mangle] +pub unsafe extern "C" 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. */ + let mut gmtime: time_t = time(0 as *mut time_t); + let mut timeinfo: tm = tm { + tm_sec: 0i32, + 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, + }; + localtime_r(&mut gmtime, &mut timeinfo); + return timeinfo.tm_gmtoff; +} +/* timesmearing */ +#[no_mangle] +pub unsafe extern "C" fn dc_smeared_time(mut context: *mut 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 + } + pthread_mutex_unlock(&mut (*context).smear_critical); + return now; +} +#[no_mangle] +pub unsafe extern "C" fn dc_create_smeared_timestamp(mut context: *mut 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 + } + } + (*context).last_smeared_timestamp = ret; + pthread_mutex_unlock(&mut (*context).smear_critical); + return ret; +} +#[no_mangle] +pub unsafe extern "C" fn dc_create_smeared_timestamps( + mut context: *mut 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; +} +/* Message-ID tools */ +#[no_mangle] +pub unsafe extern "C" fn dc_create_id() -> *mut libc::c_char { + /* generate an id. the generated ID should be as short and as unique as possible: + - short, because it may also used as part of Message-ID headers or in QR codes + - unique as two IDs generated on two devices should not be the same. However, collisions are not world-wide but only by the few contacts. + IDs generated by this function are 66 bit wide and are returned as 11 base64 characters. + If possible, RNG of OpenSSL is used. + + Additional information when used as a message-id or group-id: + - for OUTGOING messages this ID is written to the header as `Chat-Group-ID:` and is added to the message ID as Gr..@ + - for INCOMING messages, the ID is taken from the Chat-Group-ID-header or from the Message-ID in the In-Reply-To: or References:-Header + - the group-id should be a string with the characters [a-zA-Z0-9\-_] */ + let mut buf: [uint32_t; 3] = [0; 3]; + if 0 == RAND_bytes( + &mut buf as *mut [uint32_t; 3] as *mut libc::c_uchar, + (::std::mem::size_of::() as libc::c_ulong).wrapping_mul(3i32 as libc::c_ulong) + as libc::c_int, + ) { + RAND_pseudo_bytes( + &mut buf as *mut [uint32_t; 3] as *mut libc::c_uchar, + (::std::mem::size_of::() as libc::c_ulong).wrapping_mul(3i32 as libc::c_ulong) + as libc::c_int, + ); + } + return encode_66bits_as_base64(buf[0usize], buf[1usize], buf[2usize]); +} +/* ****************************************************************************** + * generate Message-IDs + ******************************************************************************/ +unsafe extern "C" fn encode_66bits_as_base64( + mut v1: uint32_t, + mut v2: uint32_t, + mut fill: uint32_t, +) -> *mut libc::c_char { + /* encode 66 bits as a base64 string. This is useful for ID generating with short strings as + we save 5 character in each id compared to 64 bit hex encoding, for a typical group ID, these are 10 characters (grpid+msgid): + hex: 64 bit, 4 bits/character, length = 64/4 = 16 characters + base64: 64 bit, 6 bits/character, length = 64/6 = 11 characters (plus 2 additional bits) */ + let mut ret: *mut libc::c_char = malloc(12i32 as libc::c_ulong) as *mut libc::c_char; + if ret.is_null() { + exit(34i32); + } + static mut chars: [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, + 45, 95, 0, + ]; + *ret.offset(0isize) = chars[(v1 >> 26i32 & 0x3fi32 as libc::c_uint) as usize]; + *ret.offset(1isize) = chars[(v1 >> 20i32 & 0x3fi32 as libc::c_uint) as usize]; + *ret.offset(2isize) = chars[(v1 >> 14i32 & 0x3fi32 as libc::c_uint) as usize]; + *ret.offset(3isize) = chars[(v1 >> 8i32 & 0x3fi32 as libc::c_uint) as usize]; + *ret.offset(4isize) = chars[(v1 >> 2i32 & 0x3fi32 as libc::c_uint) as usize]; + *ret.offset(5isize) = chars + [(v1 << 4i32 & 0x30i32 as libc::c_uint | v2 >> 28i32 & 0xfi32 as libc::c_uint) as usize]; + *ret.offset(6isize) = chars[(v2 >> 22i32 & 0x3fi32 as libc::c_uint) as usize]; + *ret.offset(7isize) = chars[(v2 >> 16i32 & 0x3fi32 as libc::c_uint) as usize]; + *ret.offset(8isize) = chars[(v2 >> 10i32 & 0x3fi32 as libc::c_uint) as usize]; + *ret.offset(9isize) = chars[(v2 >> 4i32 & 0x3fi32 as libc::c_uint) as usize]; + *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; +} +#[no_mangle] +pub unsafe extern "C" fn dc_create_incoming_rfc724_mid( + mut message_timestamp: time_t, + mut contact_id_from: uint32_t, + mut contact_ids_to: *mut dc_array_t, +) -> *mut libc::c_char { + if contact_ids_to.is_null() || dc_array_get_cnt(contact_ids_to) == 0i32 as libc::c_ulong { + return 0 as *mut libc::c_char; + } + /* find out the largest receiver ID (we could also take the smallest, but it should be unique) */ + 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 { + largest_id_to = cur_id + } + i = i.wrapping_add(1) + } + return 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, + ); +} +#[no_mangle] +pub unsafe extern "C" fn dc_create_outgoing_rfc724_mid( + mut grpid: *const libc::c_char, + mut from_addr: *const libc::c_char, +) -> *mut libc::c_char { + /* Function generates a Message-ID that can be used for a new outgoing message. + - this function is called for all outgoing messages. + - the message ID should be globally unique + - do not add a counter or any private data as as this may give unneeded information to the receiver */ + 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 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 + } + if !grpid.is_null() { + ret = dc_mprintf( + b"Gr.%s.%s%s\x00" as *const u8 as *const libc::c_char, + grpid, + rand2, + at_hostname, + ) + } else { + rand1 = dc_create_id(); + ret = dc_mprintf( + b"Mr.%s.%s%s\x00" as *const u8 as *const libc::c_char, + rand1, + rand2, + at_hostname, + ) + } + free(rand1 as *mut libc::c_void); + free(rand2 as *mut libc::c_void); + return ret; +} +#[no_mangle] +pub unsafe extern "C" 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; + if !(mid.is_null() + || strlen(mid) < 8i32 as libc::c_ulong + || *mid.offset(0isize) as libc::c_int != 'G' as i32 + || *mid.offset(1isize) as libc::c_int != 'r' as i32 + || *mid.offset(2isize) as libc::c_int != '.' as i32) + { + grpid = dc_strdup(&*mid.offset(3isize)); + p1 = strchr(grpid, '.' as i32); + if !p1.is_null() { + *p1 = 0i32 as libc::c_char; + grpid_len = strlen(grpid) as libc::c_int; + if !(grpid_len != 11i32 && grpid_len != 16i32) { + /* strict length comparison, the 'Gr.' magic is weak enough */ + success = 1i32 + } + } + } + if success == 0i32 { + free(grpid as *mut libc::c_void); + grpid = 0 as *mut libc::c_char + } + return if 0 != success { + grpid + } else { + 0 as *mut libc::c_char + }; +} +#[no_mangle] +pub unsafe extern "C" 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; + while !cur.is_null() { + let mut mid: *const libc::c_char = (if !cur.is_null() { + (*cur).data + } else { + 0 as *mut libc::c_void + }) as *const libc::c_char; + let mut grpid: *mut libc::c_char = dc_extract_grpid_from_rfc724_mid(mid); + if !grpid.is_null() { + return grpid; + } + cur = if !cur.is_null() { + (*cur).next + } else { + 0 as *mut clistcell_s + } + } + } + return 0 as *mut libc::c_char; +} +/* file tools */ +#[no_mangle] +pub unsafe extern "C" fn dc_ensure_no_slash(mut pathNfilename: *mut libc::c_char) { + let mut path_len: libc::c_int = strlen(pathNfilename) as libc::c_int; + if path_len > 0i32 { + if *pathNfilename.offset((path_len - 1i32) as isize) as libc::c_int == '/' as i32 + || *pathNfilename.offset((path_len - 1i32) as isize) as libc::c_int == '\\' as i32 + { + *pathNfilename.offset((path_len - 1i32) as isize) = 0i32 as libc::c_char + } + }; +} +#[no_mangle] +pub unsafe extern "C" 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; + while 0 != *p1 { + if *p1 as libc::c_int == '/' as i32 + || *p1 as libc::c_int == '\\' as i32 + || *p1 as libc::c_int == ':' as i32 + { + *p1 = '-' as i32 as libc::c_char + } + p1 = p1.offset(1isize) + } +} +#[no_mangle] +pub unsafe extern "C" 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() { + p = strrchr(pathNfilename, '\\' as i32) + } + if !p.is_null() { + p = p.offset(1isize); + return dc_strdup(p); + } else { + return dc_strdup(pathNfilename); + }; +} +// the case of the suffix is preserved +#[no_mangle] +pub unsafe extern "C" fn dc_split_filename( + mut pathNfilename: *const libc::c_char, + mut ret_basename: *mut *mut libc::c_char, + mut ret_all_suffixes_incl_dot: *mut *mut libc::c_char, +) { + /* splits a filename into basename and all suffixes, eg. "/path/foo.tar.gz" is split into "foo.tar" and ".gz", + (we use the _last_ dot which allows the usage inside the filename which are very usual; + maybe the detection could be more intelligent, however, for the moment, it is just file) + - 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 p1: *mut libc::c_char = strrchr(basename, '.' as i32); + if !p1.is_null() { + suffix = dc_strdup(p1); + *p1 = 0i32 as libc::c_char + } else { + suffix = dc_strdup(0 as *const libc::c_char) + } + if !ret_basename.is_null() { + *ret_basename = basename + } else { + free(basename as *mut libc::c_void); + } + if !ret_all_suffixes_incl_dot.is_null() { + *ret_all_suffixes_incl_dot = suffix + } else { + free(suffix as *mut libc::c_void); + }; +} +// the returned suffix is lower-case +#[no_mangle] +pub unsafe extern "C" fn dc_get_filesuffix_lc( + mut pathNfilename: *const libc::c_char, +) -> *mut libc::c_char { + if !pathNfilename.is_null() { + let mut p: *const libc::c_char = strrchr(pathNfilename, '.' as i32); + if !p.is_null() { + p = p.offset(1isize); + return dc_strlower(p); + } + } + return 0 as *mut libc::c_char; +} +#[no_mangle] +pub unsafe extern "C" fn dc_get_filemeta( + mut buf_start: *const libc::c_void, + mut buf_bytes: size_t, + mut ret_width: *mut uint32_t, + mut ret_height: *mut uint32_t, +) -> libc::c_int { + /* Strategy: + reading GIF dimensions requires the first 10 bytes of the file + reading PNG dimensions requires the first 24 bytes of the file + reading JPEG dimensions requires scanning through jpeg chunks + In all formats, the file is at least 24 bytes big, so we'll read that always + inspired by http://www.cplusplus.com/forum/beginner/45217/ */ + let mut buf: *const libc::c_uchar = buf_start as *const libc::c_uchar; + if buf_bytes < 24i32 as libc::c_ulong { + return 0i32; + } + if *buf.offset(0isize) as libc::c_int == 0xffi32 + && *buf.offset(1isize) as libc::c_int == 0xd8i32 + && *buf.offset(2isize) as libc::c_int == 0xffi32 + { + let mut pos: libc::c_long = 2i32 as libc::c_long; + while *buf.offset(pos as isize) as libc::c_int == 0xffi32 { + if *buf.offset((pos + 1i32 as libc::c_long) as isize) as libc::c_int == 0xc0i32 + || *buf.offset((pos + 1i32 as libc::c_long) as isize) as libc::c_int == 0xc1i32 + || *buf.offset((pos + 1i32 as libc::c_long) as isize) as libc::c_int == 0xc2i32 + || *buf.offset((pos + 1i32 as libc::c_long) as isize) as libc::c_int == 0xc3i32 + || *buf.offset((pos + 1i32 as libc::c_long) as isize) as libc::c_int == 0xc9i32 + || *buf.offset((pos + 1i32 as libc::c_long) as isize) as libc::c_int == 0xcai32 + || *buf.offset((pos + 1i32 as libc::c_long) as isize) as libc::c_int == 0xcbi32 + { + *ret_height = + (((*buf.offset((pos + 5i32 as libc::c_long) as isize) as libc::c_int) << 8i32) + + *buf.offset((pos + 6i32 as libc::c_long) as isize) as libc::c_int) + as uint32_t; + *ret_width = (((*buf.offset((pos + 7i32 as libc::c_long) as isize) as libc::c_int) + << 8i32) + + *buf.offset((pos + 8i32 as libc::c_long) as isize) as libc::c_int) + as uint32_t; + return 1i32; + } + pos += (2i32 + + ((*buf.offset((pos + 2i32 as libc::c_long) as isize) as libc::c_int) << 8i32) + + *buf.offset((pos + 3i32 as libc::c_long) as isize) as libc::c_int) + as libc::c_long; + if (pos + 12i32 as libc::c_long) as libc::c_ulong > buf_bytes { + break; + } + } + } + if *buf.offset(0isize) as libc::c_int == 'G' as i32 + && *buf.offset(1isize) as libc::c_int == 'I' as i32 + && *buf.offset(2isize) as libc::c_int == 'F' as i32 + { + *ret_width = (*buf.offset(6isize) as libc::c_int + + ((*buf.offset(7isize) as libc::c_int) << 8i32)) as uint32_t; + *ret_height = (*buf.offset(8isize) as libc::c_int + + ((*buf.offset(9isize) as libc::c_int) << 8i32)) as uint32_t; + return 1i32; + } + if *buf.offset(0isize) as libc::c_int == 0x89i32 + && *buf.offset(1isize) as libc::c_int == 'P' as i32 + && *buf.offset(2isize) as libc::c_int == 'N' as i32 + && *buf.offset(3isize) as libc::c_int == 'G' as i32 + && *buf.offset(4isize) as libc::c_int == 0xdi32 + && *buf.offset(5isize) as libc::c_int == 0xai32 + && *buf.offset(6isize) as libc::c_int == 0x1ai32 + && *buf.offset(7isize) as libc::c_int == 0xai32 + && *buf.offset(12isize) as libc::c_int == 'I' as i32 + && *buf.offset(13isize) as libc::c_int == 'H' as i32 + && *buf.offset(14isize) as libc::c_int == 'D' as i32 + && *buf.offset(15isize) as libc::c_int == 'R' as i32 + { + *ret_width = (((*buf.offset(16isize) as libc::c_int) << 24i32) + + ((*buf.offset(17isize) as libc::c_int) << 16i32) + + ((*buf.offset(18isize) as libc::c_int) << 8i32) + + ((*buf.offset(19isize) as libc::c_int) << 0i32)) as uint32_t; + *ret_height = (((*buf.offset(20isize) as libc::c_int) << 24i32) + + ((*buf.offset(21isize) as libc::c_int) << 16i32) + + ((*buf.offset(22isize) as libc::c_int) << 8i32) + + ((*buf.offset(23isize) as libc::c_int) << 0i32)) as uint32_t; + return 1i32; + } + return 0i32; +} +#[no_mangle] +pub unsafe extern "C" fn dc_get_abs_path( + mut context: *mut 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()) { + pathNfilename_abs = dc_strdup(pathNfilename); + if strncmp( + pathNfilename_abs, + b"$BLOBDIR\x00" as *const u8 as *const libc::c_char, + 8i32 as libc::c_ulong, + ) == 0i32 + { + if (*context).blobdir.is_null() { + current_block = 3805228753452640762; + } else { + dc_str_replace( + &mut pathNfilename_abs, + b"$BLOBDIR\x00" as *const u8 as *const libc::c_char, + (*context).blobdir, + ); + current_block = 6937071982253665452; + } + } else { + current_block = 6937071982253665452; + } + match current_block { + 3805228753452640762 => {} + _ => success = 1i32, + } + } + if 0 == success { + free(pathNfilename_abs as *mut libc::c_void); + pathNfilename_abs = 0 as *mut libc::c_char + } + return pathNfilename_abs; +} +#[no_mangle] +pub unsafe extern "C" fn dc_file_exist( + mut context: *mut dc_context_t, + mut pathNfilename: *const libc::c_char, +) -> libc::c_int { + let mut st: stat = stat { + st_dev: 0, + st_mode: 0, + st_nlink: 0, + st_ino: 0, + st_uid: 0, + st_gid: 0, + st_rdev: 0, + st_atimespec: timespec { + tv_sec: 0, + tv_nsec: 0, + }, + st_mtimespec: timespec { + tv_sec: 0, + tv_nsec: 0, + }, + st_ctimespec: timespec { + tv_sec: 0, + tv_nsec: 0, + }, + st_birthtimespec: timespec { + tv_sec: 0, + tv_nsec: 0, + }, + st_size: 0, + st_blocks: 0, + st_blksize: 0, + st_flags: 0, + st_gen: 0, + st_lspare: 0, + st_qspare: [0; 2], + }; + let mut exist: 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() { + st = stat { + st_dev: 0, + st_mode: 0, + st_nlink: 0, + st_ino: 0, + st_uid: 0, + st_gid: 0, + st_rdev: 0, + st_atimespec: timespec { + tv_sec: 0, + tv_nsec: 0, + }, + st_mtimespec: timespec { + tv_sec: 0, + tv_nsec: 0, + }, + st_ctimespec: timespec { + tv_sec: 0, + tv_nsec: 0, + }, + st_birthtimespec: timespec { + tv_sec: 0, + tv_nsec: 0, + }, + st_size: 0, + st_blocks: 0, + st_blksize: 0, + st_flags: 0, + st_gen: 0, + st_lspare: 0, + st_qspare: [0; 2], + }; + if stat(pathNfilename_abs, &mut st) == 0i32 { + exist = 1i32 + } + } + free(pathNfilename_abs as *mut libc::c_void); + return exist; +} +#[no_mangle] +pub unsafe extern "C" fn dc_get_filebytes( + mut context: *mut dc_context_t, + mut pathNfilename: *const libc::c_char, +) -> uint64_t { + let mut st: stat = stat { + st_dev: 0, + st_mode: 0, + st_nlink: 0, + st_ino: 0, + st_uid: 0, + st_gid: 0, + st_rdev: 0, + st_atimespec: timespec { + tv_sec: 0, + tv_nsec: 0, + }, + st_mtimespec: timespec { + tv_sec: 0, + tv_nsec: 0, + }, + st_ctimespec: timespec { + tv_sec: 0, + tv_nsec: 0, + }, + st_birthtimespec: timespec { + tv_sec: 0, + tv_nsec: 0, + }, + st_size: 0, + st_blocks: 0, + st_blksize: 0, + st_flags: 0, + st_gen: 0, + st_lspare: 0, + st_qspare: [0; 2], + }; + let mut filebytes: uint64_t = 0i32 as uint64_t; + 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() { + st = stat { + st_dev: 0, + st_mode: 0, + st_nlink: 0, + st_ino: 0, + st_uid: 0, + st_gid: 0, + st_rdev: 0, + st_atimespec: timespec { + tv_sec: 0, + tv_nsec: 0, + }, + st_mtimespec: timespec { + tv_sec: 0, + tv_nsec: 0, + }, + st_ctimespec: timespec { + tv_sec: 0, + tv_nsec: 0, + }, + st_birthtimespec: timespec { + tv_sec: 0, + tv_nsec: 0, + }, + st_size: 0, + st_blocks: 0, + st_blksize: 0, + st_flags: 0, + st_gen: 0, + st_lspare: 0, + st_qspare: [0; 2], + }; + if stat(pathNfilename_abs, &mut st) == 0i32 { + filebytes = st.st_size as uint64_t + } + } + free(pathNfilename_abs as *mut libc::c_void); + return filebytes; +} +#[no_mangle] +pub unsafe extern "C" fn dc_delete_file( + mut context: *mut dc_context_t, + mut 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 { + 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; +} +#[no_mangle] +pub unsafe extern "C" fn dc_copy_file( + mut context: *mut dc_context_t, + mut src: *const libc::c_char, + mut 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: size_t = 0i32 as size_t; + 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 { + dc_log_error( + context, + 0i32, + b"Cannot open source file \"%s\".\x00" as *const u8 as *const libc::c_char, + src, + ); + } 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 > 0i32 as libc::c_ulong) { + break; + } + if write(fd_dest, buf.as_mut_ptr() as *const libc::c_void, bytes_read) + as libc::c_ulong + != bytes_read + { + 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) != 0i32 as libc::c_ulonglong { + 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; +} +#[no_mangle] +pub unsafe extern "C" fn dc_create_folder( + mut context: *mut dc_context_t, + mut pathNfilename: *const libc::c_char, +) -> libc::c_int { + let mut st: stat = stat { + st_dev: 0, + st_mode: 0, + st_nlink: 0, + st_ino: 0, + st_uid: 0, + st_gid: 0, + st_rdev: 0, + st_atimespec: timespec { + tv_sec: 0, + tv_nsec: 0, + }, + st_mtimespec: timespec { + tv_sec: 0, + tv_nsec: 0, + }, + st_ctimespec: timespec { + tv_sec: 0, + tv_nsec: 0, + }, + st_birthtimespec: timespec { + tv_sec: 0, + tv_nsec: 0, + }, + st_size: 0, + st_blocks: 0, + st_blksize: 0, + st_flags: 0, + st_gen: 0, + st_lspare: 0, + st_qspare: [0; 2], + }; + 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; + pathNfilename_abs = dc_get_abs_path(context, pathNfilename); + if !pathNfilename_abs.is_null() { + st = stat { + st_dev: 0, + st_mode: 0, + st_nlink: 0, + st_ino: 0, + st_uid: 0, + st_gid: 0, + st_rdev: 0, + st_atimespec: timespec { + tv_sec: 0, + tv_nsec: 0, + }, + st_mtimespec: timespec { + tv_sec: 0, + tv_nsec: 0, + }, + st_ctimespec: timespec { + tv_sec: 0, + tv_nsec: 0, + }, + st_birthtimespec: timespec { + tv_sec: 0, + tv_nsec: 0, + }, + st_size: 0, + st_blocks: 0, + st_blksize: 0, + st_flags: 0, + st_gen: 0, + st_lspare: 0, + st_qspare: [0; 2], + }; + if stat(pathNfilename_abs, &mut st) == -1i32 { + if mkdir(pathNfilename_abs, 0o755i32 as mode_t) != 0i32 { + dc_log_warning( + context, + 0i32, + b"Cannot create directory \"%s\".\x00" as *const u8 as *const libc::c_char, + pathNfilename, + ); + current_block = 7696101774396965466; + } else { + current_block = 7815301370352969686; + } + } else { + current_block = 7815301370352969686; + } + match current_block { + 7696101774396965466 => {} + _ => success = 1i32, + } + } + free(pathNfilename_abs as *mut libc::c_void); + return success; +} +#[no_mangle] +pub unsafe extern "C" 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, +) -> libc::c_int { + let mut f: *mut FILE = 0 as *mut 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, 1i32 as libc::c_ulong, 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 { + dc_log_warning( + context, + 0i32, + b"Cannot open \"%s\" for writing.\x00" as *const u8 as *const libc::c_char, + pathNfilename, + ); + } + } + free(pathNfilename_abs as *mut libc::c_void); + return success; +} +#[no_mangle] +pub unsafe extern "C" 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, +) -> 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 FILE = 0 as *mut FILE; + if pathNfilename.is_null() || buf.is_null() || buf_bytes.is_null() { + return 0i32; + } + *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, 0i32 as libc::c_long, 2i32); + *buf_bytes = ftell(f) as size_t; + fseek(f, 0i32 as libc::c_long, 0i32); + if !(*buf_bytes <= 0i32 as libc::c_ulong) { + *buf = malloc((*buf_bytes).wrapping_add(1i32 as libc::c_ulong)); + if !(*buf).is_null() { + *(*buf as *mut libc::c_char).offset(*buf_bytes as isize) = 0i32 as libc::c_char; + if !(fread(*buf, 1i32 as libc::c_ulong, *buf_bytes, f) != *buf_bytes) { + success = 1i32 + } + } + } + } + } + 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; +} +#[no_mangle] +pub unsafe extern "C" fn dc_get_fine_pathNfilename( + mut context: *mut 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 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); + let mut i: libc::c_int = 0i32; + pathNfolder_wo_slash = dc_strdup(pathNfolder); + dc_ensure_no_slash(pathNfolder_wo_slash); + 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 { + let mut idx: time_t = if i < 100i32 { + i as libc::c_long + } else { + now + i as libc::c_long + }; + ret = dc_mprintf( + b"%s/%s-%lu%s\x00" as *const u8 as *const libc::c_char, + pathNfolder_wo_slash, + basename, + idx as libc::c_ulong, + dotNSuffix, + ) + } else { + ret = dc_mprintf( + b"%s/%s%s\x00" as *const u8 as *const libc::c_char, + pathNfolder_wo_slash, + basename, + dotNSuffix, + ) + } + if 0 == dc_file_exist(context, ret) { + /* fine filename found */ + break; + } else { + free(ret as *mut libc::c_void); + ret = 0 as *mut libc::c_char; + i += 1 + } + } + free(filenameNsuffix as *mut libc::c_void); + 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; +} +#[no_mangle] +pub unsafe extern "C" fn dc_is_blobdir_path( + mut context: *mut dc_context_t, + mut path: *const libc::c_char, +) -> libc::c_int { + if strncmp(path, (*context).blobdir, strlen((*context).blobdir)) == 0i32 + || strncmp( + path, + b"$BLOBDIR\x00" as *const u8 as *const libc::c_char, + 8i32 as libc::c_ulong, + ) == 0i32 + { + return 1i32; + } + return 0i32; +} +#[no_mangle] +pub unsafe extern "C" 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() { + return; + } + if strncmp(*path, (*context).blobdir, strlen((*context).blobdir)) == 0i32 { + dc_str_replace( + path, + (*context).blobdir, + b"$BLOBDIR\x00" as *const u8 as *const libc::c_char, + ); + }; +} +#[no_mangle] +pub unsafe extern "C" fn dc_make_rel_and_copy( + mut context: *mut 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 0 != dc_is_blobdir_path(context, *path) { + dc_make_rel_path(context, path); + success = 1i32 + } else { + filename = dc_get_filename(*path); + if !(filename.is_null() + || { + blobdir_path = dc_get_fine_pathNfilename( + context, + b"$BLOBDIR\x00" as *const u8 as *const libc::c_char, + filename, + ); + blobdir_path.is_null() + } + || 0 == dc_copy_file(context, *path, blobdir_path)) + { + free(*path as *mut libc::c_void); + *path = blobdir_path; + blobdir_path = 0 as *mut libc::c_char; + dc_make_rel_path(context, path); + success = 1i32 + } + } + } + free(blobdir_path as *mut libc::c_void); + free(filename as *mut libc::c_void); + return success; +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 000000000..8b4b0bfda --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,128 @@ +#![allow( + dead_code, + mutable_transmutes, + non_camel_case_types, + non_snake_case, + non_upper_case_globals, + unused_assignments, + unused_mut +)] +#![feature( + c_variadic, + const_raw_ptr_to_usize_cast, + extern_types, + ptr_wrapping_offset_from +)] +#![allow(unused_attributes)] +#![allow(non_upper_case_globals)] +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] + +pub mod dc_aheader; +pub mod dc_apeerstate; +pub mod dc_array; +pub mod dc_chat; +pub mod dc_chatlist; +pub mod dc_configure; +pub mod dc_contact; +pub mod dc_context; +pub mod dc_dehtml; +pub mod dc_e2ee; +pub mod dc_hash; +pub mod dc_imap; +pub mod dc_imex; +pub mod dc_job; +pub mod dc_jobthread; +pub mod dc_jsmn; +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; +pub mod dc_mimeparser; +pub mod dc_move; +pub mod dc_msg; +pub mod dc_oauth2; +pub mod dc_openssl; +pub mod dc_param; +pub mod dc_pgp; +pub mod dc_qr; +pub mod dc_receive_imf; +pub mod dc_saxparser; +pub mod dc_securejoin; +pub mod dc_simplify; +pub mod dc_smtp; +pub mod dc_sqlite3; +pub mod dc_stock; +pub mod dc_strbuilder; +pub mod dc_strencode; +pub mod dc_token; +pub mod dc_tools; + +#[cfg(test)] +mod tests { + use super::*; + + use std::ffi::{CStr, CString}; + use std::os::raw::c_int; + use std::ptr::NonNull; + + use crate::dc_configure::dc_configure; + use crate::dc_context::*; + use crate::dc_job::{dc_perform_imap_fetch, dc_perform_imap_idle, dc_perform_imap_jobs}; + + extern "C" fn cb(ctx: *mut dc_context_t, event: c_int, data1: u64, data2: u64) -> u64 { + let info = if data2 > 0 { + Some(unsafe { CStr::from_ptr(data2 as *const _) }) + } else { + None + }; + + println!("event: {} - {} - {:?}", event, data1, info); + + 0 + } + + struct Wrapper(NonNull); + + unsafe impl std::marker::Send for Wrapper {} + unsafe impl std::marker::Sync for Wrapper {} + + #[test] + fn test_basics() { + unsafe { + let mut ctx = dc_context_new(Some(cb), std::ptr::null_mut(), std::ptr::null_mut()); + let info = dc_get_info(ctx); + let info_s = CStr::from_ptr(info); + println!("info: {:?}", info_s); + + let dbfile = CString::new("hello.db").unwrap(); + let blobdir = CString::new("hello").unwrap(); + dc_open(ctx, dbfile.as_ptr(), blobdir.as_ptr()); + + let sendable_ctx = Wrapper(NonNull::new(ctx).unwrap()); + + dc_set_config( + ctx, + CString::new("addr").unwrap().as_ptr(), + CString::new("d@testrun.org").unwrap().as_ptr(), + ); + dc_set_config( + ctx, + CString::new("mail_pw").unwrap().as_ptr(), + CString::new("__").unwrap().as_ptr(), + ); + dc_configure(ctx); + + 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()); + }) + .join(); + } + } +}