mirror of
https://github.com/chatmail/core.git
synced 2026-04-17 21:46:35 +03:00
Merge pull request #374 from deltachat/refactor-chat
refactor(chat): make it rusty and safe
This commit is contained in:
@@ -13,6 +13,7 @@ extern crate num_traits;
|
||||
|
||||
use num_traits::{FromPrimitive, ToPrimitive};
|
||||
use std::convert::TryInto;
|
||||
use std::ptr;
|
||||
use std::str::FromStr;
|
||||
|
||||
use deltachat::contact::Contact;
|
||||
@@ -322,7 +323,7 @@ pub unsafe extern "C" fn dc_create_chat_by_msg_id(context: *mut dc_context_t, ms
|
||||
assert!(!context.is_null());
|
||||
let context = &*context;
|
||||
|
||||
dc_chat::dc_create_chat_by_msg_id(context, msg_id)
|
||||
chat::create_by_msg_id(context, msg_id).unwrap_or_log_default(context, "Failed to create chat")
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@@ -333,7 +334,8 @@ pub unsafe extern "C" fn dc_create_chat_by_contact_id(
|
||||
assert!(!context.is_null());
|
||||
let context = &*context;
|
||||
|
||||
dc_chat::dc_create_chat_by_contact_id(context, contact_id)
|
||||
chat::create_by_contact_id(context, contact_id)
|
||||
.unwrap_or_log_default(context, "Failed to create chat")
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@@ -344,7 +346,8 @@ pub unsafe extern "C" fn dc_get_chat_id_by_contact_id(
|
||||
assert!(!context.is_null());
|
||||
let context = &*context;
|
||||
|
||||
dc_chat::dc_get_chat_id_by_contact_id(context, contact_id)
|
||||
chat::get_by_contact_id(context, contact_id)
|
||||
.unwrap_or_log_default(context, "Failed to get chat")
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@@ -357,7 +360,8 @@ pub unsafe extern "C" fn dc_prepare_msg(
|
||||
assert!(!msg.is_null());
|
||||
let context = &*context;
|
||||
|
||||
dc_chat::dc_prepare_msg(context, chat_id, msg)
|
||||
chat::prepare_msg(context, chat_id, msg)
|
||||
.unwrap_or_log_default(context, "Failed to prepare message")
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@@ -370,7 +374,7 @@ pub unsafe extern "C" fn dc_send_msg(
|
||||
assert!(!msg.is_null());
|
||||
let context = &*context;
|
||||
|
||||
dc_chat::dc_send_msg(context, chat_id, msg)
|
||||
chat::send_msg(context, chat_id, msg).unwrap_or_log_default(context, "Failed to send message")
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@@ -384,7 +388,8 @@ pub unsafe extern "C" fn dc_send_text_msg(
|
||||
let context = &*context;
|
||||
let text_to_send = dc_tools::to_string_lossy(text_to_send);
|
||||
|
||||
dc_chat::dc_send_text_msg(context, chat_id, text_to_send)
|
||||
chat::send_text_msg(context, chat_id, text_to_send)
|
||||
.unwrap_or_log_default(context, "Failed to send text message")
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@@ -396,7 +401,7 @@ pub unsafe extern "C" fn dc_set_draft(
|
||||
assert!(!context.is_null());
|
||||
let context = &*context;
|
||||
|
||||
dc_chat::dc_set_draft(context, chat_id, msg)
|
||||
chat::set_draft(context, chat_id, msg)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@@ -407,7 +412,7 @@ pub unsafe extern "C" fn dc_get_draft<'a>(
|
||||
assert!(!context.is_null());
|
||||
let context = &*context;
|
||||
|
||||
dc_chat::dc_get_draft(context, chat_id)
|
||||
chat::get_draft(context, chat_id)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@@ -420,7 +425,7 @@ pub unsafe extern "C" fn dc_get_chat_msgs(
|
||||
assert!(!context.is_null());
|
||||
let context = &*context;
|
||||
|
||||
dc_chat::dc_get_chat_msgs(context, chat_id, flags, marker1before)
|
||||
chat::get_chat_msgs(context, chat_id, flags, marker1before)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@@ -428,7 +433,7 @@ pub unsafe extern "C" fn dc_get_msg_cnt(context: *mut dc_context_t, chat_id: u32
|
||||
assert!(!context.is_null());
|
||||
let context = &*context;
|
||||
|
||||
dc_chat::dc_get_msg_cnt(context, chat_id)
|
||||
chat::get_msg_cnt(context, chat_id) as libc::c_int
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@@ -439,7 +444,7 @@ pub unsafe extern "C" fn dc_get_fresh_msg_cnt(
|
||||
assert!(!context.is_null());
|
||||
let context = &*context;
|
||||
|
||||
dc_chat::dc_get_fresh_msg_cnt(context, chat_id)
|
||||
chat::get_fresh_msg_cnt(context, chat_id) as libc::c_int
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@@ -457,7 +462,7 @@ pub unsafe extern "C" fn dc_marknoticed_chat(context: *mut dc_context_t, chat_id
|
||||
assert!(!context.is_null());
|
||||
let context = &*context;
|
||||
|
||||
dc_chat::dc_marknoticed_chat(context, chat_id);
|
||||
chat::marknoticed_chat(context, chat_id).log_err(context, "Failed marknoticed chat");
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@@ -465,7 +470,7 @@ pub unsafe extern "C" fn dc_marknoticed_all_chats(context: *mut dc_context_t) {
|
||||
assert!(!context.is_null());
|
||||
let context = &*context;
|
||||
|
||||
dc_chat::dc_marknoticed_all_chats(context);
|
||||
chat::marknoticed_all_chats(context).log_err(context, "Failed marknoticed all chats");
|
||||
}
|
||||
|
||||
fn from_prim<S, T>(s: S) -> Option<T>
|
||||
@@ -493,7 +498,7 @@ pub unsafe extern "C" fn dc_get_chat_media(
|
||||
let or_msg_type3 =
|
||||
from_prim(or_msg_type3).expect(&format!("incorrect or_msg_type3 = {}", or_msg_type3));
|
||||
|
||||
dc_chat::dc_get_chat_media(context, chat_id, msg_type, or_msg_type2, or_msg_type3)
|
||||
chat::get_chat_media(context, chat_id, msg_type, or_msg_type2, or_msg_type3)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@@ -514,7 +519,7 @@ pub unsafe extern "C" fn dc_get_next_media(
|
||||
let or_msg_type3 =
|
||||
from_prim(or_msg_type3).expect(&format!("incorrect or_msg_type3 = {}", or_msg_type3));
|
||||
|
||||
dc_chat::dc_get_next_media(context, msg_id, dir, msg_type, or_msg_type2, or_msg_type3)
|
||||
chat::get_next_media(context, msg_id, dir, msg_type, or_msg_type2, or_msg_type3)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@@ -526,7 +531,15 @@ pub unsafe extern "C" fn dc_archive_chat(
|
||||
assert!(!context.is_null());
|
||||
let context = &*context;
|
||||
|
||||
dc_chat::dc_archive_chat(context, chat_id, archive);
|
||||
let archive = if archive == 0 {
|
||||
false
|
||||
} else if archive == 1 {
|
||||
true
|
||||
} else {
|
||||
return;
|
||||
};
|
||||
|
||||
chat::archive(context, chat_id, archive).log_err(context, "Failed archive chat");
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@@ -534,8 +547,7 @@ pub unsafe extern "C" fn dc_delete_chat(context: *mut dc_context_t, chat_id: u32
|
||||
assert!(!context.is_null());
|
||||
let context = &*context;
|
||||
|
||||
// TODO: update to indicate public api success/failure of deletion
|
||||
dc_chat::dc_delete_chat(context, chat_id);
|
||||
chat::delete(context, chat_id).log_err(context, "Failed chat delete");
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@@ -546,7 +558,7 @@ pub unsafe extern "C" fn dc_get_chat_contacts(
|
||||
assert!(!context.is_null());
|
||||
let context = &*context;
|
||||
|
||||
dc_array_t::from(dc_chat::dc_get_chat_contacts(context, chat_id)).into_raw()
|
||||
dc_array_t::from(chat::get_chat_contacts(context, chat_id)).into_raw()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@@ -570,7 +582,10 @@ pub unsafe extern "C" fn dc_get_chat<'a>(
|
||||
assert!(!context.is_null());
|
||||
let context = &*context;
|
||||
|
||||
dc_chat::dc_get_chat(context, chat_id)
|
||||
match chat::Chat::load_from_db(context, chat_id) {
|
||||
Ok(chat) => Box::into_raw(Box::new(chat)),
|
||||
Err(_) => std::ptr::null_mut(),
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@@ -583,7 +598,14 @@ pub unsafe extern "C" fn dc_create_group_chat(
|
||||
assert!(!name.is_null());
|
||||
let context = &*context;
|
||||
|
||||
dc_chat::dc_create_group_chat(context, verified, name)
|
||||
let verified = if let Some(s) = contact::VerifiedStatus::from_i32(verified) {
|
||||
s
|
||||
} else {
|
||||
return 0;
|
||||
};
|
||||
|
||||
chat::create_group_chat(context, verified, as_str(name))
|
||||
.unwrap_or_log_default(context, "Failed to create group chat")
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@@ -595,7 +617,7 @@ pub unsafe extern "C" fn dc_is_contact_in_chat(
|
||||
assert!(!context.is_null());
|
||||
let context = &*context;
|
||||
|
||||
dc_chat::dc_is_contact_in_chat(context, chat_id, contact_id)
|
||||
chat::is_contact_in_chat(context, chat_id, contact_id)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@@ -607,7 +629,7 @@ pub unsafe extern "C" fn dc_add_contact_to_chat(
|
||||
assert!(!context.is_null());
|
||||
let context = &*context;
|
||||
|
||||
dc_chat::dc_add_contact_to_chat(context, chat_id, contact_id)
|
||||
chat::add_contact_to_chat(context, chat_id, contact_id)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@@ -619,7 +641,9 @@ pub unsafe extern "C" fn dc_remove_contact_from_chat(
|
||||
assert!(!context.is_null());
|
||||
let context = &*context;
|
||||
|
||||
dc_chat::dc_remove_contact_from_chat(context, chat_id, contact_id)
|
||||
chat::remove_contact_from_chat(context, chat_id, contact_id)
|
||||
.map(|_| 1)
|
||||
.unwrap_or_log_default(context, "Failed to remove contact")
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@@ -633,7 +657,9 @@ pub unsafe extern "C" fn dc_set_chat_name(
|
||||
assert!(chat_id > constants::DC_CHAT_ID_LAST_SPECIAL as u32);
|
||||
let context = &*context;
|
||||
|
||||
dc_chat::dc_set_chat_name(context, chat_id, name)
|
||||
chat::set_chat_name(context, chat_id, as_str(name))
|
||||
.map(|_| 1)
|
||||
.unwrap_or_log_default(context, "Failed to set chat name")
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@@ -646,7 +672,9 @@ pub unsafe extern "C" fn dc_set_chat_profile_image(
|
||||
assert!(chat_id > constants::DC_CHAT_ID_LAST_SPECIAL as u32);
|
||||
let context = &*context;
|
||||
|
||||
dc_chat::dc_set_chat_profile_image(context, chat_id, image)
|
||||
chat::set_chat_profile_image(context, chat_id, as_str(image))
|
||||
.map(|_| 1)
|
||||
.unwrap_or_log_default(context, "Failed to set profile image")
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@@ -698,7 +726,7 @@ pub unsafe extern "C" fn dc_forward_msgs(
|
||||
assert!(chat_id > constants::DC_CHAT_ID_LAST_SPECIAL as u32);
|
||||
let context = &*context;
|
||||
|
||||
dc_chat::dc_forward_msgs(context, msg_ids, msg_cnt, chat_id)
|
||||
chat::forward_msgs(context, msg_ids, msg_cnt, chat_id)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@@ -1239,7 +1267,9 @@ pub unsafe extern "C" fn dc_chatlist_get_summary<'a>(
|
||||
) -> *mut dc_lot::dc_lot_t {
|
||||
assert!(!chatlist.is_null());
|
||||
|
||||
let chat = if chat.is_null() { None } else { Some(&*chat) };
|
||||
let list = &*chatlist;
|
||||
|
||||
list.get_summary(index as usize, chat)
|
||||
}
|
||||
|
||||
@@ -1256,90 +1286,104 @@ pub unsafe extern "C" fn dc_chatlist_get_context(
|
||||
// dc_chat_t
|
||||
|
||||
#[no_mangle]
|
||||
pub type dc_chat_t<'a> = dc_chat::Chat<'a>;
|
||||
pub type dc_chat_t<'a> = chat::Chat<'a>;
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_chat_unref(chat: *mut dc_chat_t) {
|
||||
assert!(!chat.is_null());
|
||||
|
||||
dc_chat::dc_chat_unref(chat)
|
||||
Box::from_raw(chat);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_chat_get_id(chat: *mut dc_chat_t) -> u32 {
|
||||
assert!(!chat.is_null());
|
||||
let chat = &*chat;
|
||||
|
||||
dc_chat::dc_chat_get_id(chat)
|
||||
chat.get_id()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_chat_get_type(chat: *mut dc_chat_t) -> libc::c_int {
|
||||
assert!(!chat.is_null());
|
||||
let chat = &*chat;
|
||||
|
||||
dc_chat::dc_chat_get_type(chat)
|
||||
chat.get_type() as libc::c_int
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_chat_get_name(chat: *mut dc_chat_t) -> *mut libc::c_char {
|
||||
assert!(!chat.is_null());
|
||||
let chat = &*chat;
|
||||
|
||||
dc_chat::dc_chat_get_name(chat)
|
||||
chat.get_name().strdup()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_chat_get_subtitle(chat: *mut dc_chat_t) -> *mut libc::c_char {
|
||||
assert!(!chat.is_null());
|
||||
let chat = &*chat;
|
||||
|
||||
dc_chat::dc_chat_get_subtitle(chat)
|
||||
chat.get_subtitle().strdup()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_chat_get_profile_image(chat: *mut dc_chat_t) -> *mut libc::c_char {
|
||||
assert!(!chat.is_null());
|
||||
let chat = &*chat;
|
||||
|
||||
dc_chat::dc_chat_get_profile_image(chat)
|
||||
match chat.get_profile_image() {
|
||||
Some(i) => i.strdup(),
|
||||
None => ptr::null_mut(),
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_chat_get_color(chat: *mut dc_chat_t) -> u32 {
|
||||
assert!(!chat.is_null());
|
||||
let chat = &*chat;
|
||||
|
||||
dc_chat::dc_chat_get_color(chat)
|
||||
chat.get_color()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_chat_get_archived(chat: *mut dc_chat_t) -> libc::c_int {
|
||||
assert!(!chat.is_null());
|
||||
let chat = &*chat;
|
||||
|
||||
dc_chat::dc_chat_get_archived(chat)
|
||||
chat.is_archived() as libc::c_int
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_chat_is_unpromoted(chat: *mut dc_chat_t) -> libc::c_int {
|
||||
assert!(!chat.is_null());
|
||||
let chat = &*chat;
|
||||
|
||||
dc_chat::dc_chat_is_unpromoted(chat)
|
||||
chat.is_unpromoted() as libc::c_int
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_chat_is_self_talk(chat: *mut dc_chat_t) -> libc::c_int {
|
||||
assert!(!chat.is_null());
|
||||
let chat = &*chat;
|
||||
|
||||
dc_chat::dc_chat_is_self_talk(chat)
|
||||
chat.is_self_talk() as libc::c_int
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_chat_is_verified(chat: *mut dc_chat_t) -> libc::c_int {
|
||||
assert!(!chat.is_null());
|
||||
let chat = &*chat;
|
||||
|
||||
dc_chat::dc_chat_is_verified(chat)
|
||||
chat.is_verified() as libc::c_int
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_chat_is_sending_locations(chat: *mut dc_chat_t) -> libc::c_int {
|
||||
assert!(!chat.is_null());
|
||||
let chat = &*chat;
|
||||
|
||||
dc_chat::dc_chat_is_sending_locations(chat)
|
||||
chat.is_sending_locations() as libc::c_int
|
||||
}
|
||||
|
||||
// dc_msg_t
|
||||
@@ -1500,6 +1544,7 @@ pub unsafe extern "C" fn dc_msg_get_summary<'a>(
|
||||
chat: *mut dc_chat_t<'a>,
|
||||
) -> *mut dc_lot::dc_lot_t {
|
||||
assert!(!msg.is_null());
|
||||
let chat = if chat.is_null() { None } else { Some(&*chat) };
|
||||
|
||||
dc_msg::dc_msg_get_summary(msg, chat)
|
||||
}
|
||||
@@ -1819,3 +1864,26 @@ fn as_opt_str<'a>(s: *const libc::c_char) -> Option<&'a str> {
|
||||
|
||||
Some(dc_tools::as_str(s))
|
||||
}
|
||||
|
||||
pub trait ResultExt<T: Default> {
|
||||
fn unwrap_or_log_default(self, context: &context::Context, message: &str) -> T;
|
||||
fn log_err(&self, context: &context::Context, message: &str);
|
||||
}
|
||||
|
||||
impl<T: Default, E: std::fmt::Display> ResultExt<T> for Result<T, E> {
|
||||
fn unwrap_or_log_default(self, context: &context::Context, message: &str) -> T {
|
||||
match self {
|
||||
Ok(t) => t,
|
||||
Err(err) => {
|
||||
error!(context, 0, "{}: {}", message, err);
|
||||
Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn log_err(&self, context: &context::Context, message: &str) {
|
||||
if let Err(err) = self {
|
||||
error!(context, 0, "{}: {}", message, err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@ pub fn to_sql_derive(input: TokenStream) -> TokenStream {
|
||||
let num = *self as i64;
|
||||
let value = rusqlite::types::Value::Integer(num);
|
||||
let output = rusqlite::types::ToSqlOutput::Owned(value);
|
||||
|
||||
std::result::Result::Ok(output)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
use std::ffi::CString;
|
||||
use std::str::FromStr;
|
||||
|
||||
use deltachat::chat::{self, Chat};
|
||||
use deltachat::chatlist::*;
|
||||
use deltachat::config;
|
||||
use deltachat::constants::*;
|
||||
use deltachat::contact::*;
|
||||
use deltachat::context::*;
|
||||
use deltachat::dc_array::*;
|
||||
use deltachat::dc_chat::*;
|
||||
use deltachat::dc_configure::*;
|
||||
use deltachat::dc_imex::*;
|
||||
use deltachat::dc_job::*;
|
||||
@@ -151,7 +151,7 @@ unsafe fn poke_spec(context: &Context, spec: *const libc::c_char) -> libc::c_int
|
||||
}
|
||||
if ok_to_continue {
|
||||
let ok_to_continue2;
|
||||
suffix = dc_get_filesuffix_lc(real_spec);
|
||||
suffix = dc_get_filesuffix_lc(as_str(real_spec));
|
||||
if !suffix.is_null() && strcmp(suffix, b"eml\x00" as *const u8 as *const libc::c_char) == 0
|
||||
{
|
||||
if 0 != dc_poke_eml_file(context, real_spec) {
|
||||
@@ -349,22 +349,16 @@ pub unsafe fn dc_cmdline_skip_auth() {
|
||||
S_IS_AUTH = 1;
|
||||
}
|
||||
|
||||
unsafe fn chat_prefix(chat: *const Chat) -> &'static str {
|
||||
if (*chat).type_0 == 120 {
|
||||
"Group"
|
||||
} else if (*chat).type_0 == 130 {
|
||||
"VerifiedGroup"
|
||||
} else {
|
||||
"Single"
|
||||
}
|
||||
fn chat_prefix(chat: &Chat) -> &'static str {
|
||||
chat.typ.into()
|
||||
}
|
||||
|
||||
pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::Error> {
|
||||
let chat_id = *context.cmdline_sel_chat_id.read().unwrap();
|
||||
let mut sel_chat = if chat_id > 0 {
|
||||
dc_get_chat(context, chat_id)
|
||||
Chat::load_from_db(context, chat_id).ok()
|
||||
} else {
|
||||
std::ptr::null_mut()
|
||||
None
|
||||
};
|
||||
|
||||
let mut args = line.splitn(3, ' ');
|
||||
@@ -612,23 +606,21 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E
|
||||
);
|
||||
|
||||
for i in (0..cnt).rev() {
|
||||
let chat = dc_get_chat(context, chatlist.get_chat_id(i));
|
||||
let temp_subtitle = dc_chat_get_subtitle(chat);
|
||||
let temp_name = dc_chat_get_name(chat);
|
||||
let chat = Chat::load_from_db(context, chatlist.get_chat_id(i))?;
|
||||
let temp_subtitle = chat.get_subtitle();
|
||||
let temp_name = chat.get_name();
|
||||
info!(
|
||||
context,
|
||||
0,
|
||||
"{}#{}: {} [{}] [{} fresh]",
|
||||
chat_prefix(chat),
|
||||
dc_chat_get_id(chat) as libc::c_int,
|
||||
as_str(temp_name),
|
||||
as_str(temp_subtitle),
|
||||
dc_get_fresh_msg_cnt(context, dc_chat_get_id(chat)) as libc::c_int,
|
||||
chat_prefix(&chat),
|
||||
chat.get_id(),
|
||||
temp_name,
|
||||
temp_subtitle,
|
||||
chat::get_fresh_msg_cnt(context, chat.get_id()),
|
||||
);
|
||||
free(temp_subtitle as *mut libc::c_void);
|
||||
free(temp_name as *mut libc::c_void);
|
||||
let lot = chatlist.get_summary(i, chat);
|
||||
let statestr = if 0 != dc_chat_get_archived(chat) {
|
||||
let lot = chatlist.get_summary(i, Some(&chat));
|
||||
let statestr = if chat.is_archived() {
|
||||
" [Archived]"
|
||||
} else {
|
||||
match dc_lot_get_state(lot) {
|
||||
@@ -651,7 +643,7 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E
|
||||
to_string(text2),
|
||||
statestr,
|
||||
×tr,
|
||||
if 0 != dc_chat_is_sending_locations(chat) {
|
||||
if chat.is_sending_locations() {
|
||||
"📍"
|
||||
} else {
|
||||
""
|
||||
@@ -660,7 +652,6 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E
|
||||
free(text1 as *mut libc::c_void);
|
||||
free(text2 as *mut libc::c_void);
|
||||
dc_lot_unref(lot);
|
||||
dc_chat_unref(chat);
|
||||
info!(
|
||||
context, 0,
|
||||
"================================================================================"
|
||||
@@ -673,109 +664,86 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E
|
||||
println!("{} chats", cnt);
|
||||
}
|
||||
"chat" => {
|
||||
if sel_chat.is_null() && arg1.is_empty() {
|
||||
if sel_chat.is_none() && arg1.is_empty() {
|
||||
bail!("Argument [chat-id] is missing.");
|
||||
}
|
||||
if !sel_chat.is_null() && !arg1.is_empty() {
|
||||
dc_chat_unref(sel_chat);
|
||||
}
|
||||
if !arg1.is_empty() {
|
||||
let chat_id = arg1.parse()?;
|
||||
println!("Selecting chat #{}", chat_id);
|
||||
sel_chat = dc_get_chat(context, chat_id);
|
||||
sel_chat = Some(Chat::load_from_db(context, chat_id)?);
|
||||
*context.cmdline_sel_chat_id.write().unwrap() = chat_id;
|
||||
}
|
||||
|
||||
ensure!(!sel_chat.is_null(), "Failed to select chat");
|
||||
ensure!(sel_chat.is_some(), "Failed to select chat");
|
||||
let sel_chat = sel_chat.as_ref().unwrap();
|
||||
|
||||
let msglist = dc_get_chat_msgs(context, dc_chat_get_id(sel_chat), 0x1, 0);
|
||||
let temp2 = dc_chat_get_subtitle(sel_chat);
|
||||
let temp_name = dc_chat_get_name(sel_chat);
|
||||
let msglist = chat::get_chat_msgs(context, sel_chat.get_id(), 0x1, 0);
|
||||
let temp2 = sel_chat.get_subtitle();
|
||||
let temp_name = sel_chat.get_name();
|
||||
info!(
|
||||
context,
|
||||
0,
|
||||
"{}#{}: {} [{}]{}",
|
||||
chat_prefix(sel_chat),
|
||||
dc_chat_get_id(sel_chat),
|
||||
as_str(temp_name),
|
||||
as_str(temp2),
|
||||
if 0 != dc_chat_is_sending_locations(sel_chat) {
|
||||
sel_chat.get_id(),
|
||||
temp_name,
|
||||
temp2,
|
||||
if sel_chat.is_sending_locations() {
|
||||
"📍"
|
||||
} else {
|
||||
""
|
||||
},
|
||||
);
|
||||
free(temp_name as *mut libc::c_void);
|
||||
free(temp2 as *mut libc::c_void);
|
||||
if !msglist.is_null() {
|
||||
log_msglist(context, msglist);
|
||||
dc_array_unref(msglist);
|
||||
}
|
||||
let draft = dc_get_draft(context, dc_chat_get_id(sel_chat));
|
||||
let draft = chat::get_draft(context, sel_chat.get_id());
|
||||
if !draft.is_null() {
|
||||
log_msg(context, "Draft", draft);
|
||||
dc_msg_unref(draft);
|
||||
}
|
||||
println!(
|
||||
"{} messages.",
|
||||
dc_get_msg_cnt(context, dc_chat_get_id(sel_chat))
|
||||
chat::get_msg_cnt(context, sel_chat.get_id())
|
||||
);
|
||||
dc_marknoticed_chat(context, dc_chat_get_id(sel_chat));
|
||||
chat::marknoticed_chat(context, sel_chat.get_id())?;
|
||||
}
|
||||
"createchat" => {
|
||||
ensure!(!arg1.is_empty(), "Argument <contact-id> missing.");
|
||||
let contact_id: libc::c_int = arg1.parse()?;
|
||||
let chat_id: libc::c_int =
|
||||
dc_create_chat_by_contact_id(context, contact_id as uint32_t) as libc::c_int;
|
||||
if chat_id != 0 {
|
||||
println!("Single#{} created successfully.", chat_id,);
|
||||
} else {
|
||||
bail!("Failed to create chat");
|
||||
}
|
||||
let chat_id = chat::create_by_contact_id(context, contact_id as uint32_t)?;
|
||||
|
||||
println!("Single#{} created successfully.", chat_id,);
|
||||
}
|
||||
"createchatbymsg" => {
|
||||
ensure!(!arg1.is_empty(), "Argument <msg-id> missing");
|
||||
let msg_id_0: libc::c_int = arg1.parse()?;
|
||||
let chat_id_0: libc::c_int =
|
||||
dc_create_chat_by_msg_id(context, msg_id_0 as uint32_t) as libc::c_int;
|
||||
if chat_id_0 != 0 {
|
||||
let chat_0: *mut Chat = dc_get_chat(context, chat_id_0 as uint32_t);
|
||||
println!(
|
||||
"{}#{} created successfully.",
|
||||
chat_prefix(chat_0),
|
||||
chat_id_0,
|
||||
);
|
||||
dc_chat_unref(chat_0);
|
||||
} else {
|
||||
bail!("");
|
||||
}
|
||||
let msg_id: u32 = arg1.parse()?;
|
||||
let chat_id = chat::create_by_msg_id(context, msg_id)?;
|
||||
let chat = Chat::load_from_db(context, chat_id)?;
|
||||
|
||||
println!("{}#{} created successfully.", chat_prefix(&chat), chat_id,);
|
||||
}
|
||||
"creategroup" => {
|
||||
ensure!(!arg1.is_empty(), "Argument <name> missing.");
|
||||
let chat_id_1: libc::c_int = dc_create_group_chat(context, 0, arg1_c) as libc::c_int;
|
||||
if chat_id_1 != 0 {
|
||||
println!("Group#{} created successfully.", chat_id_1,);
|
||||
} else {
|
||||
bail!("Failed to create group");
|
||||
}
|
||||
let chat_id = chat::create_group_chat(context, VerifiedStatus::Unverified, arg1)?;
|
||||
|
||||
println!("Group#{} created successfully.", chat_id);
|
||||
}
|
||||
"createverified" => {
|
||||
ensure!(!arg1.is_empty(), "Argument <name> missing.");
|
||||
let chat_id_2: libc::c_int = dc_create_group_chat(context, 1, arg1_c) as libc::c_int;
|
||||
if chat_id_2 != 0 {
|
||||
println!("VerifiedGroup#{} created successfully.", chat_id_2,);
|
||||
} else {
|
||||
bail!("Failed to create verified group");
|
||||
}
|
||||
let chat_id = chat::create_group_chat(context, VerifiedStatus::Verified, arg1)?;
|
||||
|
||||
println!("VerifiedGroup#{} created successfully.", chat_id);
|
||||
}
|
||||
"addmember" => {
|
||||
ensure!(!sel_chat.is_null(), "No chat selected");
|
||||
ensure!(sel_chat.is_some(), "No chat selected");
|
||||
ensure!(!arg1.is_empty(), "Argument <contact-id> missing.");
|
||||
|
||||
let contact_id_0: libc::c_int = arg1.parse()?;
|
||||
if 0 != dc_add_contact_to_chat(
|
||||
if 0 != chat::add_contact_to_chat(
|
||||
context,
|
||||
dc_chat_get_id(sel_chat),
|
||||
sel_chat.as_ref().unwrap().get_id(),
|
||||
contact_id_0 as uint32_t,
|
||||
) {
|
||||
println!("Contact added to chat.");
|
||||
@@ -784,62 +752,56 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E
|
||||
}
|
||||
}
|
||||
"removemember" => {
|
||||
ensure!(!sel_chat.is_null(), "No chat selected.");
|
||||
ensure!(sel_chat.is_some(), "No chat selected.");
|
||||
ensure!(!arg1.is_empty(), "Argument <contact-id> missing.");
|
||||
let contact_id_1: libc::c_int = arg1.parse()?;
|
||||
if 0 != dc_remove_contact_from_chat(
|
||||
chat::remove_contact_from_chat(
|
||||
context,
|
||||
dc_chat_get_id(sel_chat),
|
||||
sel_chat.as_ref().unwrap().get_id(),
|
||||
contact_id_1 as uint32_t,
|
||||
) {
|
||||
println!("Contact added to chat.");
|
||||
} else {
|
||||
bail!("Cannot remove member from chat.");
|
||||
}
|
||||
)?;
|
||||
|
||||
println!("Contact added to chat.");
|
||||
}
|
||||
"groupname" => {
|
||||
ensure!(!sel_chat.is_null(), "No chat selected.");
|
||||
ensure!(sel_chat.is_some(), "No chat selected.");
|
||||
ensure!(!arg1.is_empty(), "Argument <name> missing.");
|
||||
if 0 != dc_set_chat_name(context, dc_chat_get_id(sel_chat), arg1_c) {
|
||||
println!("Chat name set");
|
||||
} else {
|
||||
bail!("Failed to set chat name");
|
||||
}
|
||||
chat::set_chat_name(context, sel_chat.as_ref().unwrap().get_id(), arg1)?;
|
||||
|
||||
println!("Chat name set");
|
||||
}
|
||||
"groupimage" => {
|
||||
ensure!(!sel_chat.is_null(), "No chat selected.");
|
||||
ensure!(sel_chat.is_some(), "No chat selected.");
|
||||
ensure!(!arg1.is_empty(), "Argument <image> missing.");
|
||||
|
||||
if 0 != dc_set_chat_profile_image(
|
||||
context,
|
||||
dc_chat_get_id(sel_chat),
|
||||
if !arg1.is_empty() {
|
||||
arg1_c
|
||||
} else {
|
||||
std::ptr::null_mut()
|
||||
},
|
||||
) {
|
||||
println!("Chat image set");
|
||||
} else {
|
||||
bail!("Failed to set chat image");
|
||||
}
|
||||
chat::set_chat_profile_image(context, sel_chat.as_ref().unwrap().get_id(), arg1)?;
|
||||
|
||||
println!("Chat image set");
|
||||
}
|
||||
"chatinfo" => {
|
||||
ensure!(!sel_chat.is_null(), "No chat selected.");
|
||||
ensure!(sel_chat.is_some(), "No chat selected.");
|
||||
|
||||
let contacts = dc_get_chat_contacts(context, dc_chat_get_id(sel_chat));
|
||||
let contacts = chat::get_chat_contacts(context, sel_chat.as_ref().unwrap().get_id());
|
||||
info!(context, 0, "Memberlist:");
|
||||
|
||||
log_contactlist(context, &contacts);
|
||||
println!(
|
||||
"{} contacts\nLocation streaming: {}",
|
||||
contacts.len(),
|
||||
dc_is_sending_locations_to_chat(context, dc_chat_get_id(sel_chat)),
|
||||
dc_is_sending_locations_to_chat(context, sel_chat.as_ref().unwrap().get_id()),
|
||||
);
|
||||
}
|
||||
"getlocations" => {
|
||||
ensure!(sel_chat.is_some(), "No chat selected.");
|
||||
|
||||
let contact_id = arg1.parse().unwrap_or_default();
|
||||
let locations = dc_get_locations(context, dc_chat_get_id(sel_chat), contact_id, 0, 0);
|
||||
let locations = dc_get_locations(
|
||||
context,
|
||||
sel_chat.as_ref().unwrap().get_id(),
|
||||
contact_id,
|
||||
0,
|
||||
0,
|
||||
);
|
||||
let default_marker = "-".to_string();
|
||||
for location in &locations {
|
||||
let marker = location.marker.as_ref().unwrap_or(&default_marker);
|
||||
@@ -863,12 +825,16 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E
|
||||
}
|
||||
}
|
||||
"sendlocations" => {
|
||||
ensure!(!sel_chat.is_null(), "No chat selected.");
|
||||
ensure!(sel_chat.is_some(), "No chat selected.");
|
||||
ensure!(!arg1.is_empty(), "No timeout given.");
|
||||
|
||||
let seconds = arg1.parse()?;
|
||||
dc_send_locations_to_chat(context, dc_chat_get_id(sel_chat), seconds);
|
||||
println!("Locations will be sent to Chat#{} for {} seconds. Use 'setlocation <lat> <lng>' to play around.", dc_chat_get_id(sel_chat), seconds);
|
||||
dc_send_locations_to_chat(context, sel_chat.as_ref().unwrap().get_id(), seconds);
|
||||
println!(
|
||||
"Locations will be sent to Chat#{} for {} seconds. Use 'setlocation <lat> <lng>' to play around.",
|
||||
sel_chat.as_ref().unwrap().get_id(),
|
||||
seconds
|
||||
);
|
||||
}
|
||||
"setlocation" => {
|
||||
ensure!(
|
||||
@@ -889,27 +855,19 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E
|
||||
dc_delete_all_locations(context);
|
||||
}
|
||||
"send" => {
|
||||
ensure!(!sel_chat.is_null(), "No chat selected.");
|
||||
ensure!(sel_chat.is_some(), "No chat selected.");
|
||||
ensure!(!arg1.is_empty(), "No message text given.");
|
||||
|
||||
let msg = format!("{} {}", arg1, arg2);
|
||||
|
||||
if 0 != dc_send_text_msg(context, dc_chat_get_id(sel_chat), msg) {
|
||||
println!("Message sent.");
|
||||
} else {
|
||||
bail!("Sending failed.");
|
||||
}
|
||||
chat::send_text_msg(context, sel_chat.as_ref().unwrap().get_id(), msg)?;
|
||||
}
|
||||
"sendempty" => {
|
||||
ensure!(!sel_chat.is_null(), "No chat selected.");
|
||||
if 0 != dc_send_text_msg(context, dc_chat_get_id(sel_chat), "".into()) {
|
||||
println!("Message sent.");
|
||||
} else {
|
||||
bail!("Sending failed.");
|
||||
}
|
||||
ensure!(sel_chat.is_some(), "No chat selected.");
|
||||
chat::send_text_msg(context, sel_chat.as_ref().unwrap().get_id(), "".into())?;
|
||||
}
|
||||
"sendimage" | "sendfile" => {
|
||||
ensure!(!sel_chat.is_null(), "No chat selected.");
|
||||
ensure!(sel_chat.is_some(), "No chat selected.");
|
||||
ensure!(!arg1.is_empty() && !arg2.is_empty(), "No file given.");
|
||||
|
||||
let msg_0 = dc_msg_new(
|
||||
@@ -922,14 +880,14 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E
|
||||
);
|
||||
dc_msg_set_file(msg_0, arg1_c, 0 as *const libc::c_char);
|
||||
dc_msg_set_text(msg_0, arg2_c);
|
||||
dc_send_msg(context, dc_chat_get_id(sel_chat), msg_0);
|
||||
chat::send_msg(context, sel_chat.as_ref().unwrap().get_id(), msg_0)?;
|
||||
dc_msg_unref(msg_0);
|
||||
}
|
||||
"listmsgs" => {
|
||||
ensure!(!arg1.is_empty(), "Argument <query> missing.");
|
||||
|
||||
let chat = if !sel_chat.is_null() {
|
||||
dc_chat_get_id(sel_chat)
|
||||
let chat = if let Some(ref sel_chat) = sel_chat {
|
||||
sel_chat.get_id()
|
||||
} else {
|
||||
0 as libc::c_uint
|
||||
};
|
||||
@@ -943,25 +901,29 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E
|
||||
}
|
||||
}
|
||||
"draft" => {
|
||||
ensure!(!sel_chat.is_null(), "No chat selected.");
|
||||
ensure!(sel_chat.is_some(), "No chat selected.");
|
||||
|
||||
if !arg1.is_empty() {
|
||||
let draft_0 = dc_msg_new(context, Viewtype::Text);
|
||||
dc_msg_set_text(draft_0, arg1_c);
|
||||
dc_set_draft(context, dc_chat_get_id(sel_chat), draft_0);
|
||||
chat::set_draft(context, sel_chat.as_ref().unwrap().get_id(), draft_0);
|
||||
dc_msg_unref(draft_0);
|
||||
println!("Draft saved.");
|
||||
} else {
|
||||
dc_set_draft(context, dc_chat_get_id(sel_chat), 0 as *mut dc_msg_t);
|
||||
chat::set_draft(
|
||||
context,
|
||||
sel_chat.as_ref().unwrap().get_id(),
|
||||
0 as *mut dc_msg_t,
|
||||
);
|
||||
println!("Draft deleted.");
|
||||
}
|
||||
}
|
||||
"listmedia" => {
|
||||
ensure!(!sel_chat.is_null(), "No chat selected.");
|
||||
ensure!(sel_chat.is_some(), "No chat selected.");
|
||||
|
||||
let images = dc_get_chat_media(
|
||||
let images = chat::get_chat_media(
|
||||
context,
|
||||
dc_chat_get_id(sel_chat),
|
||||
sel_chat.as_ref().unwrap().get_id(),
|
||||
Viewtype::Image,
|
||||
Viewtype::Gif,
|
||||
Viewtype::Video,
|
||||
@@ -982,12 +944,16 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E
|
||||
"archive" | "unarchive" => {
|
||||
ensure!(!arg1.is_empty(), "Argument <chat-id> missing.");
|
||||
let chat_id = arg1.parse()?;
|
||||
dc_archive_chat(context, chat_id, if arg0 == "archive" { 1 } else { 0 });
|
||||
chat::archive(
|
||||
context,
|
||||
chat_id,
|
||||
if arg0 == "archive" { true } else { false },
|
||||
)?;
|
||||
}
|
||||
"delchat" => {
|
||||
ensure!(!arg1.is_empty(), "Argument <chat-id> missing.");
|
||||
let chat_id = arg1.parse()?;
|
||||
dc_delete_chat(context, chat_id);
|
||||
chat::delete(context, chat_id)?;
|
||||
}
|
||||
"msginfo" => {
|
||||
ensure!(!arg1.is_empty(), "Argument <msg-id> missing.");
|
||||
@@ -1012,7 +978,7 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E
|
||||
let mut msg_ids = [0; 1];
|
||||
let chat_id = arg2.parse()?;
|
||||
msg_ids[0] = arg1.parse()?;
|
||||
dc_forward_msgs(context, msg_ids.as_mut_ptr(), 1, chat_id);
|
||||
chat::forward_msgs(context, msg_ids.as_mut_ptr(), 1, chat_id);
|
||||
}
|
||||
"markseen" => {
|
||||
ensure!(!arg1.is_empty(), "Argument <msg-id> missing.");
|
||||
@@ -1082,9 +1048,8 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E
|
||||
if 0 != i {
|
||||
res += ", ";
|
||||
}
|
||||
let chat = dc_get_chat(context, chatlist.get_chat_id(i));
|
||||
res += &format!("{}#{}", chat_prefix(chat), dc_chat_get_id(chat));
|
||||
dc_chat_unref(chat);
|
||||
let chat = Chat::load_from_db(context, chatlist.get_chat_id(i))?;
|
||||
res += &format!("{}#{}", chat_prefix(&chat), chat.get_id());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1130,10 +1095,6 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E
|
||||
_ => bail!("Unknown command: \"{}\" type ? for help.", arg0),
|
||||
}
|
||||
|
||||
if !sel_chat.is_null() {
|
||||
dc_chat_unref(sel_chat);
|
||||
}
|
||||
|
||||
free(arg1_c as *mut _);
|
||||
free(arg2_c as *mut _);
|
||||
|
||||
|
||||
@@ -5,12 +5,12 @@ use std::sync::{Arc, RwLock};
|
||||
use std::{thread, time};
|
||||
use tempfile::tempdir;
|
||||
|
||||
use deltachat::chat;
|
||||
use deltachat::chatlist::*;
|
||||
use deltachat::config;
|
||||
use deltachat::constants::Event;
|
||||
use deltachat::contact::*;
|
||||
use deltachat::context::*;
|
||||
use deltachat::dc_chat::*;
|
||||
use deltachat::dc_configure::*;
|
||||
use deltachat::dc_job::{
|
||||
dc_perform_imap_fetch, dc_perform_imap_idle, dc_perform_imap_jobs, dc_perform_smtp_idle,
|
||||
@@ -96,14 +96,14 @@ fn main() {
|
||||
println!("sending a message");
|
||||
let contact_id =
|
||||
Contact::create(&ctx, "dignifiedquire", "dignifiedquire@gmail.com").unwrap();
|
||||
let chat_id = dc_create_chat_by_contact_id(&ctx, contact_id);
|
||||
dc_send_text_msg(&ctx, chat_id, "Hi, here is my first message!".into());
|
||||
let chat_id = chat::create_by_contact_id(&ctx, contact_id).unwrap();
|
||||
chat::send_text_msg(&ctx, chat_id, "Hi, here is my first message!".into()).unwrap();
|
||||
|
||||
println!("fetching chats..");
|
||||
let chats = Chatlist::try_load(&ctx, 0, None, None).unwrap();
|
||||
|
||||
for i in 0..chats.len() {
|
||||
let summary = chats.get_summary(0, std::ptr::null_mut());
|
||||
let summary = chats.get_summary(0, None);
|
||||
let text1 = dc_lot_get_text1(summary);
|
||||
let text2 = dc_lot_get_text2(summary);
|
||||
|
||||
|
||||
2060
src/chat.rs
Normal file
2060
src/chat.rs
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
||||
use crate::chat::*;
|
||||
use crate::constants::*;
|
||||
use crate::contact::*;
|
||||
use crate::context::*;
|
||||
use crate::dc_chat::*;
|
||||
use crate::dc_lot::*;
|
||||
use crate::dc_msg::*;
|
||||
use crate::dc_tools::*;
|
||||
@@ -249,7 +249,7 @@ impl<'a> Chatlist<'a> {
|
||||
/// - dc_lot_t::timestamp: the timestamp of the message. 0 if not applicable.
|
||||
/// - dc_lot_t::state: The state of the message as one of the DC_STATE_* constants (see #dc_msg_get_state()).
|
||||
// 0 if not applicable.
|
||||
pub unsafe fn get_summary(&self, index: usize, mut chat: *mut Chat<'a>) -> *mut dc_lot_t {
|
||||
pub unsafe fn get_summary(&self, index: usize, chat: Option<&Chat<'a>>) -> *mut dc_lot_t {
|
||||
// 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".
|
||||
@@ -261,27 +261,27 @@ impl<'a> Chatlist<'a> {
|
||||
return ret;
|
||||
}
|
||||
|
||||
let lastmsg_id = self.ids[index].1;
|
||||
let mut lastcontact = None;
|
||||
|
||||
if chat.is_null() {
|
||||
chat = dc_chat_new(self.context);
|
||||
let chat_to_delete = chat;
|
||||
if !dc_chat_load_from_db(chat, self.ids[index].0) {
|
||||
(*ret).text2 = "ErrCannotReadChat".strdup();
|
||||
dc_chat_unref(chat_to_delete);
|
||||
|
||||
let chat_loaded: Chat;
|
||||
let chat = if let Some(chat) = chat {
|
||||
chat
|
||||
} else {
|
||||
if let Ok(chat) = Chat::load_from_db(self.context, self.ids[index].0) {
|
||||
chat_loaded = chat;
|
||||
&chat_loaded
|
||||
} else {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let lastmsg_id = self.ids[index].1;
|
||||
let mut lastcontact = None;
|
||||
|
||||
let lastmsg = if 0 != lastmsg_id {
|
||||
let lastmsg = dc_msg_new_untyped(self.context);
|
||||
dc_msg_load_from_db(lastmsg, self.context, lastmsg_id);
|
||||
|
||||
if (*lastmsg).from_id != 1 as libc::c_uint
|
||||
&& ((*chat).type_0 == DC_CHAT_TYPE_GROUP
|
||||
|| (*chat).type_0 == DC_CHAT_TYPE_VERIFIED_GROUP)
|
||||
&& (chat.typ == Chattype::Group || chat.typ == Chattype::VerifiedGroup)
|
||||
{
|
||||
lastcontact = Contact::load_from_db(self.context, (*lastmsg).from_id).ok();
|
||||
}
|
||||
@@ -290,7 +290,7 @@ impl<'a> Chatlist<'a> {
|
||||
std::ptr::null_mut()
|
||||
};
|
||||
|
||||
if (*chat).id == DC_CHAT_ID_ARCHIVED_LINK as u32 {
|
||||
if chat.id == DC_CHAT_ID_ARCHIVED_LINK as u32 {
|
||||
(*ret).text2 = dc_strdup(ptr::null())
|
||||
} else if lastmsg.is_null() || (*lastmsg).from_id == DC_CONTACT_ID_UNDEFINED as u32 {
|
||||
(*ret).text2 = self.context.stock_str(StockMessage::NoMessages).strdup();
|
||||
|
||||
@@ -26,9 +26,19 @@ const DC_SENTBOX_WATCH_DEFAULT: i32 = 1;
|
||||
const DC_MVBOX_WATCH_DEFAULT: i32 = 1;
|
||||
const DC_MVBOX_MOVE_DEFAULT: i32 = 1;
|
||||
|
||||
pub const DC_CHAT_NOT_BLOCKED: i32 = 0;
|
||||
const DC_CHAT_MANUALLY_BLOCKED: i32 = 1;
|
||||
pub const DC_CHAT_DEADDROP_BLOCKED: i32 = 2;
|
||||
#[derive(Debug, Display, Clone, Copy, PartialEq, Eq, FromPrimitive, ToPrimitive, FromSql, ToSql)]
|
||||
#[repr(u8)]
|
||||
pub enum Blocked {
|
||||
Not = 0,
|
||||
Manually = 1,
|
||||
Deaddrop = 2,
|
||||
}
|
||||
|
||||
impl Default for Blocked {
|
||||
fn default() -> Self {
|
||||
Blocked::Not
|
||||
}
|
||||
}
|
||||
|
||||
pub const DC_IMAP_SEEN: u32 = 0x1;
|
||||
|
||||
@@ -88,10 +98,32 @@ pub const DC_CHAT_ID_ALLDONE_HINT: usize = 7;
|
||||
/// larger chat IDs are "real" chats, their messages are "real" messages.
|
||||
pub const DC_CHAT_ID_LAST_SPECIAL: usize = 9;
|
||||
|
||||
const DC_CHAT_TYPE_UNDEFINED: i32 = 0;
|
||||
pub const DC_CHAT_TYPE_SINGLE: i32 = 100;
|
||||
pub const DC_CHAT_TYPE_GROUP: i32 = 120;
|
||||
pub const DC_CHAT_TYPE_VERIFIED_GROUP: i32 = 130;
|
||||
#[derive(
|
||||
Debug,
|
||||
Display,
|
||||
Clone,
|
||||
Copy,
|
||||
PartialEq,
|
||||
Eq,
|
||||
FromPrimitive,
|
||||
ToPrimitive,
|
||||
FromSql,
|
||||
ToSql,
|
||||
IntoStaticStr,
|
||||
)]
|
||||
#[repr(u32)]
|
||||
pub enum Chattype {
|
||||
Undefined = 0,
|
||||
Single = 100,
|
||||
Group = 120,
|
||||
VerifiedGroup = 130,
|
||||
}
|
||||
|
||||
impl Default for Chattype {
|
||||
fn default() -> Self {
|
||||
Chattype::Undefined
|
||||
}
|
||||
}
|
||||
|
||||
pub const DC_MSG_ID_MARKER1: usize = 1;
|
||||
const DC_MSG_ID_DAYMARKER: usize = 9;
|
||||
|
||||
@@ -138,7 +138,7 @@ pub enum Modifier {
|
||||
Created,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy, FromPrimitive)]
|
||||
#[repr(u8)]
|
||||
pub enum VerifiedStatus {
|
||||
/// Contact is not verified.
|
||||
@@ -791,7 +791,7 @@ impl<'a> Contact<'a> {
|
||||
/// and can be used for an fallback avatar with white initials
|
||||
/// as well as for headlines in bubbles of group chats.
|
||||
pub fn get_color(&self) -> u32 {
|
||||
dc_str_to_color_safe(&self.addr)
|
||||
dc_str_to_color(&self.addr)
|
||||
}
|
||||
|
||||
/// Check if a contact was verified. E.g. by a secure-join QR code scan
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
use std::sync::{Arc, Condvar, Mutex, RwLock};
|
||||
|
||||
use crate::chat::*;
|
||||
use crate::constants::*;
|
||||
use crate::contact::*;
|
||||
use crate::dc_array::*;
|
||||
use crate::dc_chat::*;
|
||||
use crate::dc_job::*;
|
||||
use crate::dc_jobthread::*;
|
||||
use crate::dc_loginparam::*;
|
||||
@@ -338,7 +338,7 @@ pub unsafe fn dc_get_info(context: &Context) -> *mut libc::c_char {
|
||||
let l = dc_loginparam_read(context, &context.sql, "");
|
||||
let l2 = dc_loginparam_read(context, &context.sql, "configured_");
|
||||
let displayname = context.sql.get_config(context, "displayname");
|
||||
let chats = dc_get_chat_cnt(context) as usize;
|
||||
let chats = get_chat_cnt(context) as usize;
|
||||
let real_msgs = dc_get_real_msg_cnt(context) as usize;
|
||||
let deaddrop_msgs = dc_get_deaddrop_msg_cnt(context) as usize;
|
||||
let contacts = Contact::get_real_cnt(context) as usize;
|
||||
|
||||
2269
src/dc_chat.rs
2269
src/dc_chat.rs
File diff suppressed because it is too large
Load Diff
@@ -6,10 +6,10 @@ use mmime::mmapstring::*;
|
||||
use mmime::other::*;
|
||||
use rand::{thread_rng, Rng};
|
||||
|
||||
use crate::chat;
|
||||
use crate::config::Config;
|
||||
use crate::constants::*;
|
||||
use crate::context::Context;
|
||||
use crate::dc_chat::*;
|
||||
use crate::dc_configure::*;
|
||||
use crate::dc_e2ee::*;
|
||||
use crate::dc_job::*;
|
||||
@@ -138,8 +138,7 @@ pub unsafe fn dc_initiate_key_transfer(context: &Context) -> *mut libc::c_char {
|
||||
setup_file_content_c.as_bytes().len(),
|
||||
))
|
||||
{
|
||||
let chat_id = dc_create_chat_by_contact_id(context, 1i32 as uint32_t);
|
||||
if !(chat_id == 0i32 as libc::c_uint) {
|
||||
if let Ok(chat_id) = chat::create_by_contact_id(context, 1) {
|
||||
msg = dc_msg_new_untyped(context);
|
||||
(*msg).type_0 = Viewtype::File;
|
||||
(*msg).param.set(Param::File, as_str(setup_file_name));
|
||||
@@ -157,8 +156,7 @@ pub unsafe fn dc_initiate_key_transfer(context: &Context) -> *mut libc::c_char {
|
||||
.unwrap()
|
||||
.shall_stop_ongoing
|
||||
{
|
||||
let msg_id = dc_send_msg(context, chat_id, msg);
|
||||
if msg_id != 0 {
|
||||
if let Ok(msg_id) = chat::send_msg(context, chat_id, msg) {
|
||||
dc_msg_unref(msg);
|
||||
msg = ptr::null_mut();
|
||||
info!(context, 0, "Wait for setup message being sent ...",);
|
||||
@@ -970,7 +968,7 @@ unsafe fn import_self_keys(context: &Context, dir_name: *const libc::c_char) ->
|
||||
free(suffix as *mut libc::c_void);
|
||||
let name_f = entry.file_name();
|
||||
let name_c = name_f.to_c_string().unwrap();
|
||||
suffix = dc_get_filesuffix_lc(name_c.as_ptr());
|
||||
suffix = dc_get_filesuffix_lc(name_f.to_string_lossy());
|
||||
if suffix.is_null()
|
||||
|| strcmp(suffix, b"asc\x00" as *const u8 as *const libc::c_char) != 0
|
||||
{
|
||||
|
||||
@@ -6,9 +6,9 @@ use std::time::Duration;
|
||||
|
||||
use rand::{thread_rng, Rng};
|
||||
|
||||
use crate::chat;
|
||||
use crate::constants::*;
|
||||
use crate::context::Context;
|
||||
use crate::dc_chat::*;
|
||||
use crate::dc_configure::*;
|
||||
use crate::dc_imex::*;
|
||||
use crate::dc_jobthread::*;
|
||||
@@ -565,7 +565,7 @@ unsafe fn dc_job_do_DC_JOB_MARKSEEN_MSG_ON_IMAP(context: &Context, job: &mut dc_
|
||||
dc_msg_unref(msg);
|
||||
}
|
||||
unsafe fn dc_send_mdn(context: &Context, msg_id: uint32_t) {
|
||||
let mut mimefactory: dc_mimefactory_t = dc_mimefactory_t {
|
||||
let mut mimefactory = dc_mimefactory_t {
|
||||
from_addr: ptr::null_mut(),
|
||||
from_displayname: ptr::null_mut(),
|
||||
selfstatus: ptr::null_mut(),
|
||||
@@ -575,7 +575,7 @@ unsafe fn dc_send_mdn(context: &Context, msg_id: uint32_t) {
|
||||
rfc724_mid: ptr::null_mut(),
|
||||
loaded: DC_MF_NOTHING_LOADED,
|
||||
msg: ptr::null_mut(),
|
||||
chat: ptr::null_mut(),
|
||||
chat: None,
|
||||
increation: 0,
|
||||
in_reply_to: ptr::null_mut(),
|
||||
references: ptr::null_mut(),
|
||||
@@ -587,7 +587,7 @@ unsafe fn dc_send_mdn(context: &Context, msg_id: uint32_t) {
|
||||
error: ptr::null_mut(),
|
||||
context,
|
||||
};
|
||||
dc_mimefactory_init(&mut mimefactory, context);
|
||||
|
||||
if !(0 == dc_mimefactory_load_mdn(&mut mimefactory, msg_id)
|
||||
|| 0 == dc_mimefactory_render(&mut mimefactory))
|
||||
{
|
||||
@@ -1014,7 +1014,7 @@ pub unsafe fn dc_job_send_msg(context: &Context, msg_id: uint32_t) -> libc::c_in
|
||||
rfc724_mid: 0 as *mut libc::c_char,
|
||||
loaded: DC_MF_NOTHING_LOADED,
|
||||
msg: 0 as *mut dc_msg_t,
|
||||
chat: 0 as *mut Chat,
|
||||
chat: None,
|
||||
increation: 0,
|
||||
in_reply_to: 0 as *mut libc::c_char,
|
||||
references: 0 as *mut libc::c_char,
|
||||
@@ -1026,7 +1026,7 @@ pub unsafe fn dc_job_send_msg(context: &Context, msg_id: uint32_t) -> libc::c_in
|
||||
error: 0 as *mut libc::c_char,
|
||||
context,
|
||||
};
|
||||
dc_mimefactory_init(&mut mimefactory, context);
|
||||
|
||||
/* load message data */
|
||||
if 0 == dc_mimefactory_load_msg(&mut mimefactory, msg_id) || mimefactory.from_addr.is_null() {
|
||||
warn!(
|
||||
@@ -1035,7 +1035,7 @@ pub unsafe fn dc_job_send_msg(context: &Context, msg_id: uint32_t) -> libc::c_in
|
||||
);
|
||||
} else {
|
||||
// no redo, no IMAP. moreover, as the data does not exist, there is no need in calling dc_set_msg_failed()
|
||||
if msgtype_has_file((*mimefactory.msg).type_0) {
|
||||
if chat::msgtype_has_file((*mimefactory.msg).type_0) {
|
||||
if let Some(pathNfilename) = (*mimefactory.msg).param.get(Param::File) {
|
||||
if ((*mimefactory.msg).type_0 == Viewtype::Image
|
||||
|| (*mimefactory.msg).type_0 == Viewtype::Gif)
|
||||
@@ -1096,7 +1096,7 @@ pub unsafe fn dc_job_send_msg(context: &Context, msg_id: uint32_t) -> libc::c_in
|
||||
);
|
||||
}
|
||||
if 0 != mimefactory.out_gossiped {
|
||||
dc_set_gossiped_timestamp(context, (*mimefactory.msg).chat_id, time());
|
||||
chat::set_gossiped_timestamp(context, (*mimefactory.msg).chat_id, time());
|
||||
}
|
||||
if 0 != mimefactory.out_last_added_location_id {
|
||||
dc_set_kml_sent_timestamp(context, (*mimefactory.msg).chat_id, time());
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
use std::ffi::CString;
|
||||
|
||||
use quick_xml;
|
||||
use quick_xml::events::{BytesEnd, BytesStart, BytesText};
|
||||
|
||||
use crate::chat;
|
||||
use crate::constants::Event;
|
||||
use crate::constants::*;
|
||||
use crate::context::*;
|
||||
use crate::dc_chat::*;
|
||||
use crate::dc_job::*;
|
||||
use crate::dc_msg::*;
|
||||
use crate::dc_tools::*;
|
||||
@@ -104,16 +102,11 @@ pub unsafe fn dc_send_locations_to_chat(
|
||||
(*msg).text =
|
||||
Some(context.stock_system_msg(StockMessage::MsgLocationEnabled, "", "", 0));
|
||||
(*msg).param.set_int(Param::Cmd, 8);
|
||||
dc_send_msg(context, chat_id, msg);
|
||||
chat::send_msg(context, chat_id, msg).unwrap();
|
||||
} else if 0 == seconds && is_sending_locations_before {
|
||||
let stock_str = CString::new(context.stock_system_msg(
|
||||
StockMessage::MsgLocationDisabled,
|
||||
"",
|
||||
"",
|
||||
0,
|
||||
))
|
||||
.unwrap();
|
||||
dc_add_device_msg(context, chat_id, stock_str.as_ptr());
|
||||
let stock_str =
|
||||
context.stock_system_msg(StockMessage::MsgLocationDisabled, "", "", 0);
|
||||
chat::add_device_msg(context, chat_id, stock_str);
|
||||
}
|
||||
context.call_cb(
|
||||
Event::CHAT_MODIFIED,
|
||||
@@ -697,7 +690,8 @@ pub unsafe fn dc_job_do_DC_JOB_MAYBE_SEND_LOCATIONS(context: &Context, _job: *mu
|
||||
let mut msg = dc_msg_new(context, Viewtype::Text);
|
||||
(*msg).hidden = 1;
|
||||
(*msg).param.set_int(Param::Cmd, 9);
|
||||
dc_send_msg(context, chat_id as u32, msg);
|
||||
// TODO: handle cleanup on error
|
||||
chat::send_msg(context, chat_id as u32, msg).unwrap();
|
||||
dc_msg_unref(msg);
|
||||
}
|
||||
Ok(())
|
||||
@@ -735,8 +729,8 @@ pub unsafe fn dc_job_do_DC_JOB_MAYBE_SEND_LOC_ENDED(context: &Context, job: &mut
|
||||
"UPDATE chats SET locations_send_begin=0, locations_send_until=0 WHERE id=?",
|
||||
params![chat_id as i32],
|
||||
).is_ok() {
|
||||
let stock_str = CString::new(context.stock_system_msg(StockMessage::MsgLocationDisabled, "", "", 0)).unwrap();
|
||||
dc_add_device_msg(context, chat_id, stock_str.as_ptr());
|
||||
let stock_str = context.stock_system_msg(StockMessage::MsgLocationDisabled, "", "", 0);
|
||||
chat::add_device_msg(context, chat_id, stock_str);
|
||||
context.call_cb(
|
||||
Event::CHAT_MODIFIED,
|
||||
chat_id as usize,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use crate::chat::*;
|
||||
use crate::constants::Chattype;
|
||||
use crate::contact::*;
|
||||
use crate::context::Context;
|
||||
use crate::dc_chat::*;
|
||||
use crate::dc_msg::*;
|
||||
use crate::dc_tools::*;
|
||||
use crate::stock::StockMessage;
|
||||
@@ -123,7 +124,7 @@ pub unsafe fn dc_lot_get_timestamp(lot: *const dc_lot_t) -> i64 {
|
||||
pub unsafe fn dc_lot_fill(
|
||||
mut lot: *mut dc_lot_t,
|
||||
msg: *mut dc_msg_t,
|
||||
chat: *const Chat,
|
||||
chat: &Chat,
|
||||
contact: Option<&Contact>,
|
||||
context: &Context,
|
||||
) {
|
||||
@@ -134,22 +135,19 @@ pub unsafe fn dc_lot_fill(
|
||||
(*lot).text1 = context.stock_str(StockMessage::Draft).strdup();
|
||||
(*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) {
|
||||
if 0 != dc_msg_is_info(msg) || chat.is_self_talk() {
|
||||
(*lot).text1 = 0 as *mut libc::c_char;
|
||||
(*lot).text1_meaning = 0i32
|
||||
} else {
|
||||
(*lot).text1 = context.stock_str(StockMessage::SelfMsg).strdup();
|
||||
(*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 {
|
||||
} else if chat.typ == Chattype::Group || chat.typ == Chattype::VerifiedGroup {
|
||||
if 0 != dc_msg_is_info(msg) || contact.is_none() {
|
||||
(*lot).text1 = 0 as *mut libc::c_char;
|
||||
(*lot).text1_meaning = 0i32
|
||||
} else {
|
||||
if !chat.is_null() && (*chat).id == 1i32 as libc::c_uint {
|
||||
if chat.id == 1 {
|
||||
if let Some(contact) = contact {
|
||||
(*lot).text1 = contact.get_display_name().strdup();
|
||||
} else {
|
||||
|
||||
@@ -10,10 +10,10 @@ use mmime::mailmime_write_mem::*;
|
||||
use mmime::mmapstring::*;
|
||||
use mmime::other::*;
|
||||
|
||||
use crate::chat::{self, Chat};
|
||||
use crate::constants::*;
|
||||
use crate::contact::*;
|
||||
use crate::context::{dc_get_version_str, Context};
|
||||
use crate::dc_chat::*;
|
||||
use crate::dc_e2ee::*;
|
||||
use crate::dc_location::*;
|
||||
use crate::dc_msg::*;
|
||||
@@ -24,8 +24,7 @@ use crate::stock::StockMessage;
|
||||
use crate::types::*;
|
||||
use crate::x::*;
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
#[repr(C)]
|
||||
#[derive(Clone)]
|
||||
#[allow(non_camel_case_types)]
|
||||
pub struct dc_mimefactory_t<'a> {
|
||||
pub from_addr: *mut libc::c_char,
|
||||
@@ -37,7 +36,7 @@ pub struct dc_mimefactory_t<'a> {
|
||||
pub rfc724_mid: *mut libc::c_char,
|
||||
pub loaded: dc_mimefactory_loaded_t,
|
||||
pub msg: *mut dc_msg_t<'a>,
|
||||
pub chat: *mut Chat<'a>,
|
||||
pub chat: Option<Chat<'a>>,
|
||||
pub increation: libc::c_int,
|
||||
pub in_reply_to: *mut libc::c_char,
|
||||
pub references: *mut libc::c_char,
|
||||
@@ -56,18 +55,6 @@ const DC_MF_MDN_LOADED: dc_mimefactory_loaded_t = 2;
|
||||
pub const DC_MF_MSG_LOADED: dc_mimefactory_loaded_t = 1;
|
||||
pub const DC_MF_NOTHING_LOADED: dc_mimefactory_loaded_t = 0;
|
||||
|
||||
pub unsafe fn dc_mimefactory_init<'a>(factory: *mut dc_mimefactory_t<'a>, context: &'a Context) {
|
||||
if factory.is_null() {
|
||||
return;
|
||||
}
|
||||
memset(
|
||||
factory as *mut libc::c_void,
|
||||
0,
|
||||
::std::mem::size_of::<dc_mimefactory_t>(),
|
||||
);
|
||||
(*factory).context = context;
|
||||
}
|
||||
|
||||
pub unsafe fn dc_mimefactory_empty(mut factory: *mut dc_mimefactory_t) {
|
||||
if factory.is_null() {
|
||||
return;
|
||||
@@ -92,8 +79,7 @@ pub unsafe fn dc_mimefactory_empty(mut factory: *mut dc_mimefactory_t) {
|
||||
}
|
||||
dc_msg_unref((*factory).msg);
|
||||
(*factory).msg = 0 as *mut dc_msg_t;
|
||||
dc_chat_unref((*factory).chat);
|
||||
(*factory).chat = 0 as *mut Chat;
|
||||
(*factory).chat = None;
|
||||
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);
|
||||
@@ -124,131 +110,139 @@ pub unsafe fn dc_mimefactory_load_msg(
|
||||
(*factory).recipients_names = clist_new();
|
||||
(*factory).recipients_addr = clist_new();
|
||||
(*factory).msg = dc_msg_new_untyped(context);
|
||||
(*factory).chat = dc_chat_new(context);
|
||||
if dc_msg_load_from_db((*factory).msg, context, msg_id)
|
||||
&& dc_chat_load_from_db((*factory).chat, (*(*factory).msg).chat_id)
|
||||
{
|
||||
load_from(factory);
|
||||
(*factory).req_mdn = 0;
|
||||
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 {
|
||||
context
|
||||
.sql
|
||||
.query_map(
|
||||
"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;",
|
||||
params![(*(*factory).msg).chat_id as i32],
|
||||
|row| {
|
||||
let authname: String = row.get(0)?;
|
||||
let addr: String = row.get(1)?;
|
||||
Ok((authname, addr))
|
||||
},
|
||||
|rows| {
|
||||
for row in rows {
|
||||
let (authname, addr) = row?;
|
||||
let addr_c = addr.strdup();
|
||||
if clist_search_string_nocase((*factory).recipients_addr, addr_c) == 0 {
|
||||
clist_insert_after(
|
||||
(*factory).recipients_names,
|
||||
(*(*factory).recipients_names).last,
|
||||
if !authname.is_empty() {
|
||||
authname.strdup()
|
||||
} else {
|
||||
std::ptr::null_mut()
|
||||
} as *mut libc::c_void,
|
||||
);
|
||||
clist_insert_after(
|
||||
(*factory).recipients_addr,
|
||||
(*(*factory).recipients_addr).last,
|
||||
addr_c as *mut libc::c_void,
|
||||
);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let command = (*(*factory).msg)
|
||||
.param
|
||||
.get_int(Param::Cmd)
|
||||
.unwrap_or_default();
|
||||
if dc_msg_load_from_db((*factory).msg, context, msg_id) {
|
||||
if let Ok(chat) = Chat::load_from_db(context, (*(*factory).msg).chat_id) {
|
||||
(*factory).chat = Some(chat);
|
||||
|
||||
if command == 5 {
|
||||
let email_to_remove = (*(*factory).msg).param.get(Param::Arg).unwrap_or_default();
|
||||
let email_to_remove_c = email_to_remove.strdup();
|
||||
let chat = (*factory).chat.as_ref().unwrap();
|
||||
|
||||
let self_addr = context
|
||||
load_from(factory);
|
||||
(*factory).req_mdn = 0;
|
||||
if chat.is_self_talk() {
|
||||
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 {
|
||||
context
|
||||
.sql
|
||||
.get_config(context, "configured_addr")
|
||||
.query_map(
|
||||
"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;",
|
||||
params![(*(*factory).msg).chat_id as i32],
|
||||
|row| {
|
||||
let authname: String = row.get(0)?;
|
||||
let addr: String = row.get(1)?;
|
||||
Ok((authname, addr))
|
||||
},
|
||||
|rows| {
|
||||
for row in rows {
|
||||
let (authname, addr) = row?;
|
||||
let addr_c = addr.strdup();
|
||||
if clist_search_string_nocase((*factory).recipients_addr, addr_c)
|
||||
== 0
|
||||
{
|
||||
clist_insert_after(
|
||||
(*factory).recipients_names,
|
||||
(*(*factory).recipients_names).last,
|
||||
if !authname.is_empty() {
|
||||
authname.strdup()
|
||||
} else {
|
||||
std::ptr::null_mut()
|
||||
}
|
||||
as *mut libc::c_void,
|
||||
);
|
||||
clist_insert_after(
|
||||
(*factory).recipients_addr,
|
||||
(*(*factory).recipients_addr).last,
|
||||
addr_c as *mut libc::c_void,
|
||||
);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let command = (*(*factory).msg)
|
||||
.param
|
||||
.get_int(Param::Cmd)
|
||||
.unwrap_or_default();
|
||||
|
||||
if !email_to_remove.is_empty() && email_to_remove != self_addr {
|
||||
if clist_search_string_nocase((*factory).recipients_addr, email_to_remove_c)
|
||||
== 0
|
||||
{
|
||||
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_c as *mut libc::c_void,
|
||||
);
|
||||
if command == 5 {
|
||||
let email_to_remove =
|
||||
(*(*factory).msg).param.get(Param::Arg).unwrap_or_default();
|
||||
let email_to_remove_c = email_to_remove.strdup();
|
||||
|
||||
let self_addr = context
|
||||
.sql
|
||||
.get_config(context, "configured_addr")
|
||||
.unwrap_or_default();
|
||||
|
||||
if !email_to_remove.is_empty() && email_to_remove != self_addr {
|
||||
if clist_search_string_nocase((*factory).recipients_addr, email_to_remove_c)
|
||||
== 0
|
||||
{
|
||||
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_c as *mut libc::c_void,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
if command != 6
|
||||
&& command != 7
|
||||
&& 0 != context
|
||||
.sql
|
||||
.get_config_int(context, "mdns_enabled")
|
||||
.unwrap_or_else(|| 1)
|
||||
{
|
||||
(*factory).req_mdn = 1
|
||||
}
|
||||
}
|
||||
if command != 6
|
||||
&& command != 7
|
||||
&& 0 != context
|
||||
.sql
|
||||
.get_config_int(context, "mdns_enabled")
|
||||
.unwrap_or_else(|| 1)
|
||||
{
|
||||
(*factory).req_mdn = 1
|
||||
}
|
||||
}
|
||||
let row = context.sql.query_row(
|
||||
"SELECT mime_in_reply_to, mime_references FROM msgs WHERE id=?",
|
||||
params![(*(*factory).msg).id as i32],
|
||||
|row| {
|
||||
let in_reply_to: String = row.get(0)?;
|
||||
let references: String = row.get(1)?;
|
||||
let row = context.sql.query_row(
|
||||
"SELECT mime_in_reply_to, mime_references FROM msgs WHERE id=?",
|
||||
params![(*(*factory).msg).id as i32],
|
||||
|row| {
|
||||
let in_reply_to: String = row.get(0)?;
|
||||
let references: String = row.get(1)?;
|
||||
|
||||
Ok((in_reply_to, references))
|
||||
},
|
||||
);
|
||||
match row {
|
||||
Ok((in_reply_to, references)) => {
|
||||
(*factory).in_reply_to = in_reply_to.strdup();
|
||||
(*factory).references = references.strdup();
|
||||
Ok((in_reply_to, references))
|
||||
},
|
||||
);
|
||||
match row {
|
||||
Ok((in_reply_to, references)) => {
|
||||
(*factory).in_reply_to = in_reply_to.strdup();
|
||||
(*factory).references = references.strdup();
|
||||
}
|
||||
Err(err) => {
|
||||
error!(
|
||||
context,
|
||||
0, "mimefactory: failed to load mime_in_reply_to: {:?}", err
|
||||
);
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
error!(
|
||||
context,
|
||||
0, "mimefactory: failed to load mime_in_reply_to: {:?}", err
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
success = 1;
|
||||
(*factory).loaded = DC_MF_MSG_LOADED;
|
||||
(*factory).timestamp = (*(*factory).msg).timestamp_sort;
|
||||
(*factory).rfc724_mid = dc_strdup((*(*factory).msg).rfc724_mid)
|
||||
success = 1;
|
||||
(*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)
|
||||
@@ -514,11 +508,11 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc:
|
||||
if (*factory).loaded as libc::c_uint == DC_MF_MSG_LOADED as libc::c_int as libc::c_uint {
|
||||
/* Render a normal message
|
||||
*********************************************************************/
|
||||
let chat: *mut Chat = (*factory).chat;
|
||||
let msg: *mut dc_msg_t = (*factory).msg;
|
||||
let chat = (*factory).chat.as_ref().unwrap();
|
||||
let msg = (*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 == DC_CHAT_TYPE_VERIFIED_GROUP as libc::c_int {
|
||||
if chat.typ == Chattype::VerifiedGroup {
|
||||
mailimf_fields_add(
|
||||
imf_fields,
|
||||
mailimf_field_new_custom(
|
||||
@@ -541,29 +535,28 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc:
|
||||
.unwrap_or_default()
|
||||
}
|
||||
}
|
||||
if (*chat).gossiped_timestamp == 0
|
||||
|| ((*chat).gossiped_timestamp + (2 * 24 * 60 * 60)) < time()
|
||||
if chat.gossiped_timestamp == 0
|
||||
|| (chat.gossiped_timestamp + (2 * 24 * 60 * 60)) < time()
|
||||
{
|
||||
do_gossip = 1
|
||||
}
|
||||
|
||||
/* build header etc. */
|
||||
let command = (*msg).param.get_int(Param::Cmd).unwrap_or_default();
|
||||
if (*chat).type_0 == DC_CHAT_TYPE_GROUP as libc::c_int
|
||||
|| (*chat).type_0 == DC_CHAT_TYPE_VERIFIED_GROUP as libc::c_int
|
||||
{
|
||||
if chat.typ == Chattype::Group || chat.typ == Chattype::VerifiedGroup {
|
||||
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),
|
||||
chat.grpid.strdup(),
|
||||
),
|
||||
);
|
||||
let name = CString::yolo(chat.name.as_bytes());
|
||||
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),
|
||||
dc_encode_header_words(name.as_ptr()),
|
||||
),
|
||||
);
|
||||
if command == 5 {
|
||||
@@ -594,7 +587,7 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc:
|
||||
email_to_add,
|
||||
),
|
||||
);
|
||||
grpimage = (*chat).param.get(Param::ProfileImage);
|
||||
grpimage = chat.param.get(Param::ProfileImage);
|
||||
}
|
||||
if 0 != (*msg).param.get_int(Param::Arg2).unwrap_or_default() & 0x1 {
|
||||
info!(
|
||||
@@ -838,7 +831,7 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc:
|
||||
free(placeholdertext as *mut libc::c_void);
|
||||
|
||||
/* add attachment part */
|
||||
if msgtype_has_file((*msg).type_0) {
|
||||
if chat::msgtype_has_file((*msg).type_0) {
|
||||
if !is_file_size_okay(msg) {
|
||||
let error: *mut libc::c_char = dc_mprintf(
|
||||
b"Message exceeds the recommended %i MB.\x00" as *const u8
|
||||
@@ -1000,7 +993,7 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc:
|
||||
e.as_ptr(),
|
||||
);
|
||||
} else {
|
||||
subject_str = get_subject((*factory).chat, (*factory).msg, afwd_email)
|
||||
subject_str = get_subject((*factory).chat.as_ref(), (*factory).msg, afwd_email)
|
||||
}
|
||||
subject = mailimf_subject_new(dc_encode_header_words(subject_str));
|
||||
mailimf_fields_add(
|
||||
@@ -1054,6 +1047,7 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc:
|
||||
success = 1
|
||||
}
|
||||
}
|
||||
|
||||
if !message.is_null() {
|
||||
mailmime_free(message);
|
||||
}
|
||||
@@ -1066,11 +1060,16 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc:
|
||||
}
|
||||
|
||||
unsafe fn get_subject(
|
||||
chat: *const Chat,
|
||||
chat: Option<&Chat>,
|
||||
msg: *mut dc_msg_t,
|
||||
afwd_email: libc::c_int,
|
||||
) -> *mut libc::c_char {
|
||||
let context = (*chat).context;
|
||||
if chat.is_none() {
|
||||
return std::ptr::null_mut();
|
||||
}
|
||||
|
||||
let chat = chat.unwrap();
|
||||
let context = chat.context;
|
||||
let ret: *mut libc::c_char;
|
||||
|
||||
let raw_subject = {
|
||||
@@ -1091,15 +1090,14 @@ unsafe fn get_subject(
|
||||
};
|
||||
if (*msg).param.get_int(Param::Cmd).unwrap_or_default() == 6 {
|
||||
ret = context.stock_str(StockMessage::AcSetupMsgSubject).strdup()
|
||||
} else if (*chat).type_0 == DC_CHAT_TYPE_GROUP as libc::c_int
|
||||
|| (*chat).type_0 == DC_CHAT_TYPE_VERIFIED_GROUP as libc::c_int
|
||||
{
|
||||
ret = dc_mprintf(
|
||||
b"Chat: %s: %s%s\x00" as *const u8 as *const libc::c_char,
|
||||
(*chat).name,
|
||||
fwd,
|
||||
raw_subject,
|
||||
} else if chat.typ == Chattype::Group || chat.typ == Chattype::VerifiedGroup {
|
||||
ret = format!(
|
||||
"Chat: {}: {}{}",
|
||||
chat.name,
|
||||
to_string(fwd),
|
||||
to_string(raw_subject),
|
||||
)
|
||||
.strdup()
|
||||
} else {
|
||||
ret = dc_mprintf(
|
||||
b"Chat: %s%s\x00" as *const u8 as *const libc::c_char,
|
||||
@@ -1150,22 +1148,20 @@ unsafe fn build_body_file(
|
||||
let mime_fields: *mut mailmime_fields;
|
||||
let mut mime_sub: *mut mailmime = 0 as *mut mailmime;
|
||||
let content: *mut mailmime_content;
|
||||
let pathNfilename = (*msg)
|
||||
.param
|
||||
.get(Param::File)
|
||||
.map(|s| s.strdup())
|
||||
.unwrap_or_else(|| std::ptr::null_mut());
|
||||
let path_filename = (*msg).param.get(Param::File);
|
||||
|
||||
let mut mimetype = (*msg)
|
||||
.param
|
||||
.get(Param::MimeType)
|
||||
.map(|s| s.strdup())
|
||||
.unwrap_or_else(|| std::ptr::null_mut());
|
||||
|
||||
let suffix = dc_get_filesuffix_lc(pathNfilename);
|
||||
let mut filename_to_send = 0 as *mut libc::c_char;
|
||||
let mut filename_encoded = 0 as *mut libc::c_char;
|
||||
|
||||
if !pathNfilename.is_null() {
|
||||
if let Some(ref path_filename) = path_filename {
|
||||
let suffix = dc_get_filesuffix_lc(path_filename);
|
||||
|
||||
if (*msg).type_0 == Viewtype::Voice {
|
||||
let ts = chrono::Utc.timestamp((*msg).timestamp_sort as i64, 0);
|
||||
|
||||
@@ -1179,7 +1175,7 @@ unsafe fn build_body_file(
|
||||
.to_string();
|
||||
filename_to_send = res.strdup();
|
||||
} else if (*msg).type_0 == Viewtype::Audio {
|
||||
filename_to_send = dc_get_filename(pathNfilename)
|
||||
filename_to_send = dc_get_filename(path_filename)
|
||||
} else if (*msg).type_0 == Viewtype::Image || (*msg).type_0 == Viewtype::Gif {
|
||||
if base_name.is_null() {
|
||||
base_name = b"image\x00" as *const u8 as *const libc::c_char
|
||||
@@ -1203,7 +1199,7 @@ unsafe fn build_body_file(
|
||||
},
|
||||
)
|
||||
} else {
|
||||
filename_to_send = dc_get_filename(pathNfilename)
|
||||
filename_to_send = dc_get_filename(path_filename)
|
||||
}
|
||||
if mimetype.is_null() {
|
||||
if suffix.is_null() {
|
||||
@@ -1296,17 +1292,16 @@ unsafe fn build_body_file(
|
||||
) 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));
|
||||
mailmime_set_body_file(mime_sub, dc_get_abs_path((*msg).context, path_filename));
|
||||
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);
|
||||
|
||||
mime_sub
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
use std::ffi::CString;
|
||||
use std::path::Path;
|
||||
|
||||
use crate::chat::{self, Chat};
|
||||
use crate::constants::*;
|
||||
use crate::contact::*;
|
||||
use crate::context::*;
|
||||
use crate::dc_chat::*;
|
||||
use crate::dc_job::*;
|
||||
use crate::dc_lot::dc_lot_t;
|
||||
use crate::dc_lot::*;
|
||||
@@ -309,8 +309,7 @@ pub unsafe fn dc_msg_get_file(msg: *const dc_msg_t) -> *mut libc::c_char {
|
||||
|
||||
if !msg.is_null() {
|
||||
if let Some(file_rel) = (*msg).param.get(Param::File) {
|
||||
let file_rel_c = CString::yolo(file_rel);
|
||||
file_abs = dc_get_abs_path((*msg).context, file_rel_c.as_ptr());
|
||||
file_abs = dc_get_abs_path((*msg).context, file_rel);
|
||||
}
|
||||
}
|
||||
if !file_abs.is_null() {
|
||||
@@ -681,8 +680,7 @@ pub unsafe fn dc_msg_get_filename(msg: *const dc_msg_t) -> *mut libc::c_char {
|
||||
|
||||
if !msg.is_null() {
|
||||
if let Some(file) = (*msg).param.get(Param::File) {
|
||||
let file_c = CString::yolo(file);
|
||||
ret = dc_get_filename(file_c.as_ptr());
|
||||
ret = dc_get_filename(file);
|
||||
}
|
||||
}
|
||||
if !ret.is_null() {
|
||||
@@ -745,35 +743,35 @@ pub unsafe fn dc_msg_get_showpadlock(msg: *const dc_msg_t) -> libc::c_int {
|
||||
|
||||
pub unsafe fn dc_msg_get_summary<'a>(
|
||||
msg: *mut dc_msg_t<'a>,
|
||||
mut chat: *const Chat<'a>,
|
||||
chat: Option<&Chat<'a>>,
|
||||
) -> *mut dc_lot_t {
|
||||
let mut ok_to_continue = true;
|
||||
let ret: *mut dc_lot_t = dc_lot_new();
|
||||
let mut chat_to_delete: *mut Chat = 0 as *mut Chat;
|
||||
let ret = dc_lot_new();
|
||||
|
||||
if !msg.is_null() {
|
||||
if chat.is_null() {
|
||||
chat_to_delete = dc_get_chat((*msg).context, (*msg).chat_id);
|
||||
if chat_to_delete.is_null() {
|
||||
ok_to_continue = false;
|
||||
} else {
|
||||
chat = chat_to_delete;
|
||||
}
|
||||
}
|
||||
if ok_to_continue {
|
||||
let contact = if (*msg).from_id != DC_CONTACT_ID_SELF as libc::c_uint
|
||||
&& ((*chat).type_0 == 120 || (*chat).type_0 == 130)
|
||||
{
|
||||
Contact::get_by_id((*chat).context, (*msg).from_id).ok()
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
dc_lot_fill(ret, msg, chat, contact.as_ref(), (*msg).context);
|
||||
}
|
||||
if msg.is_null() {
|
||||
return ret;
|
||||
}
|
||||
|
||||
dc_chat_unref(chat_to_delete);
|
||||
let chat_loaded: Chat;
|
||||
let chat = if let Some(chat) = chat {
|
||||
chat
|
||||
} else {
|
||||
if let Ok(chat) = Chat::load_from_db((*msg).context, (*msg).chat_id) {
|
||||
chat_loaded = chat;
|
||||
&chat_loaded
|
||||
} else {
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
let contact = if (*msg).from_id != DC_CONTACT_ID_SELF as libc::c_uint
|
||||
&& ((*chat).typ == Chattype::Group || (*chat).typ == Chattype::VerifiedGroup)
|
||||
{
|
||||
Contact::get_by_id((*chat).context, (*msg).from_id).ok()
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
dc_lot_fill(ret, msg, chat, contact.as_ref(), (*msg).context);
|
||||
|
||||
ret
|
||||
}
|
||||
@@ -921,7 +919,7 @@ pub unsafe fn dc_msg_is_increation(msg: *const dc_msg_t) -> libc::c_int {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if msgtype_has_file((*msg).type_0) && (*msg).state == DC_STATE_OUT_PREPARING {
|
||||
if chat::msgtype_has_file((*msg).type_0) && (*msg).state == DC_STATE_OUT_PREPARING {
|
||||
1
|
||||
} else {
|
||||
0
|
||||
@@ -1252,7 +1250,7 @@ pub unsafe fn dc_mdn_from_ext(
|
||||
(S=Sender, R=Recipient)
|
||||
*/
|
||||
// for rounding, SELF is already included!
|
||||
let soll_cnt = (dc_get_chat_contact_cnt(context, *ret_chat_id) + 1) / 2;
|
||||
let soll_cnt = (chat::get_chat_contact_cnt(context, *ret_chat_id) + 1) / 2;
|
||||
if ist_cnt >= soll_cnt {
|
||||
dc_update_msg_state(context, *ret_msg_id, DC_STATE_OUT_MDN_RCVD);
|
||||
read_by_all = 1;
|
||||
@@ -1392,14 +1390,12 @@ mod tests {
|
||||
let res = ctx.set_config(Config::ConfiguredAddr, Some("self@example.com"));
|
||||
assert!(res.is_ok());
|
||||
|
||||
let chat = dc_create_chat_by_contact_id(ctx, contact);
|
||||
assert!(chat != 0);
|
||||
let chat = chat::create_by_contact_id(ctx, contact).unwrap();
|
||||
|
||||
let msg = dc_msg_new(ctx, Viewtype::Text);
|
||||
assert!(!msg.is_null());
|
||||
|
||||
let msg_id = dc_prepare_msg(ctx, chat, msg);
|
||||
assert!(msg_id != 0);
|
||||
let msg_id = chat::prepare_msg(ctx, chat, msg).unwrap();
|
||||
|
||||
let msg2 = dc_get_msg(ctx, msg_id);
|
||||
assert!(!msg2.is_null());
|
||||
|
||||
25
src/dc_qr.rs
25
src/dc_qr.rs
@@ -1,8 +1,9 @@
|
||||
use percent_encoding::percent_decode_str;
|
||||
|
||||
use crate::chat;
|
||||
use crate::constants::Blocked;
|
||||
use crate::contact::*;
|
||||
use crate::context::Context;
|
||||
use crate::dc_chat::*;
|
||||
use crate::dc_lot::*;
|
||||
use crate::dc_strencode::*;
|
||||
use crate::dc_tools::*;
|
||||
@@ -34,7 +35,7 @@ pub unsafe fn dc_check_qr(context: &Context, qr: *const libc::c_char) -> *mut dc
|
||||
let mut auth: *mut libc::c_char = 0 as *mut libc::c_char;
|
||||
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 device_msg = "".to_string();
|
||||
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;
|
||||
@@ -230,20 +231,17 @@ pub unsafe fn dc_check_qr(context: &Context, qr: *const libc::c_char) -> *mut dc
|
||||
Contact::add_or_lookup(context, "", addr, Origin::UnhandledQrScan)
|
||||
.map(|(id, _)| id)
|
||||
.unwrap_or_default();
|
||||
dc_create_or_lookup_nchat_by_contact_id(
|
||||
let (id, _) = chat::create_or_lookup_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,
|
||||
Blocked::Deaddrop,
|
||||
)
|
||||
.unwrap_or_default();
|
||||
chat_id = id;
|
||||
device_msg = format!("{} verified.", peerstate.addr.unwrap_or_default());
|
||||
} else {
|
||||
(*qr_parsed).text1 = dc_format_fingerprint_c(fingerprint);
|
||||
(*qr_parsed).state = 230i32
|
||||
(*qr_parsed).state = 230i32;
|
||||
}
|
||||
} else {
|
||||
if !grpid.is_null() && !grpname.is_null() {
|
||||
@@ -286,8 +284,8 @@ pub unsafe fn dc_check_qr(context: &Context, qr: *const libc::c_char) -> *mut dc
|
||||
(*qr_parsed).state = 330i32;
|
||||
(*qr_parsed).text1 = dc_strdup(qr)
|
||||
}
|
||||
if !device_msg.is_null() {
|
||||
dc_add_device_msg(context, chat_id, device_msg);
|
||||
if !device_msg.is_empty() {
|
||||
chat::add_device_msg(context, chat_id, device_msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -297,7 +295,6 @@ pub unsafe fn dc_check_qr(context: &Context, qr: *const libc::c_char) -> *mut dc
|
||||
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);
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use itertools::join;
|
||||
use std::ptr;
|
||||
|
||||
use itertools::join;
|
||||
use mmime::mailimf::*;
|
||||
use mmime::mailimf_types::*;
|
||||
use mmime::mailmime::*;
|
||||
@@ -8,12 +9,11 @@ use mmime::mailmime_types::*;
|
||||
use mmime::mmapstring::*;
|
||||
use mmime::other::*;
|
||||
use sha2::{Digest, Sha256};
|
||||
use std::ptr;
|
||||
|
||||
use crate::chat::{self, Chat};
|
||||
use crate::constants::*;
|
||||
use crate::contact::*;
|
||||
use crate::context::Context;
|
||||
use crate::dc_chat::*;
|
||||
use crate::dc_job::*;
|
||||
use crate::dc_location::*;
|
||||
use crate::dc_mimeparser::*;
|
||||
@@ -284,7 +284,7 @@ unsafe fn add_parts(
|
||||
) -> Result<()> {
|
||||
let mut state: libc::c_int;
|
||||
let mut msgrmsg: libc::c_int;
|
||||
let mut chat_id_blocked = 0;
|
||||
let mut chat_id_blocked = Blocked::Not;
|
||||
let mut sort_timestamp = 0;
|
||||
let mut rcvd_timestamp = 0;
|
||||
let mut mime_in_reply_to = std::ptr::null_mut();
|
||||
@@ -408,15 +408,9 @@ unsafe fn add_parts(
|
||||
state = DC_STATE_IN_SEEN;
|
||||
}
|
||||
}
|
||||
let mut test_normal_chat_id = 0;
|
||||
let mut test_normal_chat_id_blocked = 0;
|
||||
|
||||
dc_lookup_real_nchat_by_contact_id(
|
||||
context,
|
||||
*from_id,
|
||||
&mut test_normal_chat_id,
|
||||
&mut test_normal_chat_id_blocked,
|
||||
);
|
||||
let (test_normal_chat_id, test_normal_chat_id_blocked) =
|
||||
chat::lookup_by_contact_id(context, *from_id).unwrap_or_default();
|
||||
|
||||
// get the chat_id - a chat_id here is no indicator that the chat is displayed in the normal list,
|
||||
// it might also be blocked and displayed in the deaddrop as a result
|
||||
@@ -425,12 +419,12 @@ unsafe fn add_parts(
|
||||
// (groups appear automatically only if the _sender_ is known, see core issue #54)
|
||||
|
||||
let create_blocked = if 0 != test_normal_chat_id
|
||||
&& test_normal_chat_id_blocked == DC_CHAT_NOT_BLOCKED
|
||||
&& test_normal_chat_id_blocked == Blocked::Not
|
||||
|| incoming_origin.is_start_new_chat()
|
||||
{
|
||||
DC_CHAT_NOT_BLOCKED
|
||||
Blocked::Not
|
||||
} else {
|
||||
DC_CHAT_DEADDROP_BLOCKED
|
||||
Blocked::Deaddrop
|
||||
};
|
||||
|
||||
create_or_lookup_group(
|
||||
@@ -443,9 +437,9 @@ unsafe fn add_parts(
|
||||
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 = 0;
|
||||
if 0 != *chat_id && Blocked::Not != chat_id_blocked && create_blocked == Blocked::Not {
|
||||
chat::unblock(context, *chat_id);
|
||||
chat_id_blocked = Blocked::Not;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -463,27 +457,25 @@ unsafe fn add_parts(
|
||||
if *chat_id == 0 {
|
||||
// try to create a normal chat
|
||||
let create_blocked = if incoming_origin.is_start_new_chat() || *from_id == *to_id {
|
||||
DC_CHAT_NOT_BLOCKED
|
||||
Blocked::Not
|
||||
} else {
|
||||
DC_CHAT_DEADDROP_BLOCKED
|
||||
Blocked::Deaddrop
|
||||
};
|
||||
|
||||
if 0 != test_normal_chat_id {
|
||||
*chat_id = test_normal_chat_id;
|
||||
chat_id_blocked = test_normal_chat_id_blocked
|
||||
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,
|
||||
chat_id,
|
||||
&mut chat_id_blocked,
|
||||
);
|
||||
let (id, bl) =
|
||||
chat::create_or_lookup_by_contact_id(context, *from_id, create_blocked)
|
||||
.unwrap_or_default();
|
||||
*chat_id = id;
|
||||
chat_id_blocked = bl;
|
||||
}
|
||||
if 0 != *chat_id && 0 != chat_id_blocked {
|
||||
if 0 == create_blocked {
|
||||
dc_unblock_chat(context, *chat_id);
|
||||
chat_id_blocked = 0;
|
||||
if 0 != *chat_id && Blocked::Not != chat_id_blocked {
|
||||
if Blocked::Not == create_blocked {
|
||||
chat::unblock(context, *chat_id);
|
||||
chat_id_blocked = Blocked::Not;
|
||||
} else if 0 != dc_is_reply_to_known_message(context, mime_parser) {
|
||||
// we do not want any chat to be created implicitly. Because of the origin-scale-up,
|
||||
// the contact requests will pop up and this should be just fine.
|
||||
@@ -506,7 +498,7 @@ unsafe fn add_parts(
|
||||
// if the chat_id is blocked,
|
||||
// for unknown senders and non-delta messages set the state to NOTICED
|
||||
// to not result in a contact request (this would require the state FRESH)
|
||||
if 0 != chat_id_blocked && state == DC_STATE_IN_FRESH {
|
||||
if Blocked::Not != chat_id_blocked && state == DC_STATE_IN_FRESH {
|
||||
if !incoming_origin.is_verified() && msgrmsg == 0 {
|
||||
state = DC_STATE_IN_NOTICED;
|
||||
}
|
||||
@@ -525,33 +517,35 @@ unsafe fn add_parts(
|
||||
context,
|
||||
&mut mime_parser,
|
||||
allow_creation,
|
||||
0,
|
||||
Blocked::Not,
|
||||
*from_id,
|
||||
to_ids,
|
||||
chat_id,
|
||||
&mut chat_id_blocked,
|
||||
);
|
||||
if 0 != *chat_id && 0 != chat_id_blocked {
|
||||
dc_unblock_chat(context, *chat_id);
|
||||
chat_id_blocked = 0
|
||||
if 0 != *chat_id && Blocked::Not != chat_id_blocked {
|
||||
chat::unblock(context, *chat_id);
|
||||
chat_id_blocked = Blocked::Not;
|
||||
}
|
||||
}
|
||||
if *chat_id == 0 && 0 != allow_creation {
|
||||
let create_blocked = if 0 != msgrmsg && !Contact::is_blocked_load(context, *to_id) {
|
||||
DC_CHAT_NOT_BLOCKED
|
||||
Blocked::Not
|
||||
} else {
|
||||
DC_CHAT_DEADDROP_BLOCKED
|
||||
Blocked::Deaddrop
|
||||
};
|
||||
dc_create_or_lookup_nchat_by_contact_id(
|
||||
context,
|
||||
*to_id,
|
||||
create_blocked,
|
||||
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 = 0
|
||||
let (id, bl) =
|
||||
chat::create_or_lookup_by_contact_id(context, *to_id, create_blocked)
|
||||
.unwrap_or_default();
|
||||
*chat_id = id;
|
||||
chat_id_blocked = bl;
|
||||
|
||||
if 0 != *chat_id
|
||||
&& Blocked::Not != chat_id_blocked
|
||||
&& Blocked::Not == create_blocked
|
||||
{
|
||||
chat::unblock(context, *chat_id);
|
||||
chat_id_blocked = Blocked::Not;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -559,16 +553,14 @@ unsafe fn add_parts(
|
||||
if to_ids.is_empty() && 0 != to_self {
|
||||
// from_id==to_id==DC_CONTACT_ID_SELF - this is a self-sent messages,
|
||||
// maybe an Autocrypt Setup Messag
|
||||
dc_create_or_lookup_nchat_by_contact_id(
|
||||
context,
|
||||
1,
|
||||
0,
|
||||
chat_id,
|
||||
&mut chat_id_blocked,
|
||||
);
|
||||
if 0 != *chat_id && 0 != chat_id_blocked {
|
||||
dc_unblock_chat(context, *chat_id);
|
||||
chat_id_blocked = 0;
|
||||
let (id, bl) = chat::create_or_lookup_by_contact_id(context, 1, Blocked::Not)
|
||||
.unwrap_or_default();
|
||||
*chat_id = id;
|
||||
chat_id_blocked = bl;
|
||||
|
||||
if 0 != *chat_id && Blocked::Not != chat_id_blocked {
|
||||
chat::unblock(context, *chat_id);
|
||||
chat_id_blocked = Blocked::Not;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -590,7 +582,7 @@ unsafe fn add_parts(
|
||||
);
|
||||
|
||||
// unarchive chat
|
||||
dc_unarchive_chat(context, *chat_id);
|
||||
chat::unarchive(context, *chat_id).unwrap();
|
||||
|
||||
// if the mime-headers should be saved, find out its size
|
||||
// (the mime-header ends with an empty line)
|
||||
@@ -743,7 +735,7 @@ unsafe fn add_parts(
|
||||
} else if 0 != incoming && state == DC_STATE_IN_FRESH {
|
||||
if 0 != from_id_blocked {
|
||||
*create_event_to_send = None;
|
||||
} else if 0 != chat_id_blocked {
|
||||
} else if Blocked::Not != chat_id_blocked {
|
||||
*create_event_to_send = Some(Event::MSGS_CHANGED);
|
||||
} else {
|
||||
*create_event_to_send = Some(Event::INCOMING_MSG);
|
||||
@@ -1043,17 +1035,17 @@ unsafe fn create_or_lookup_group(
|
||||
context: &Context,
|
||||
mime_parser: &mut dc_mimeparser_t,
|
||||
allow_creation: libc::c_int,
|
||||
create_blocked: libc::c_int,
|
||||
create_blocked: Blocked,
|
||||
from_id: u32,
|
||||
to_ids: &mut Vec<u32>,
|
||||
ret_chat_id: *mut uint32_t,
|
||||
ret_chat_id_blocked: *mut libc::c_int,
|
||||
ret_chat_id_blocked: &mut Blocked,
|
||||
) {
|
||||
let group_explicitly_left: libc::c_int;
|
||||
let group_explicitly_left: bool;
|
||||
let mut chat_id = 0;
|
||||
let mut chat_id_blocked = 0;
|
||||
let mut chat_id_blocked = Blocked::Not;
|
||||
let mut chat_id_verified = 0;
|
||||
let mut grpid = std::ptr::null_mut();
|
||||
let mut grpid = "".to_string();
|
||||
let mut grpname = std::ptr::null_mut();
|
||||
let to_ids_cnt = to_ids.len();
|
||||
let mut recreate_member_list = 0;
|
||||
@@ -1067,23 +1059,23 @@ unsafe fn create_or_lookup_group(
|
||||
let mut better_msg: String = From::from("");
|
||||
let mut failure_reason = std::ptr::null_mut();
|
||||
|
||||
let cleanup = |grpid: *mut libc::c_char,
|
||||
grpname: *mut libc::c_char,
|
||||
let cleanup = |grpname: *mut libc::c_char,
|
||||
failure_reason: *mut libc::c_char,
|
||||
ret_chat_id: *mut uint32_t,
|
||||
ret_chat_id_blocked: *mut libc::c_int,
|
||||
ret_chat_id_blocked: &mut Blocked,
|
||||
chat_id: u32,
|
||||
chat_id_blocked: i32| {
|
||||
free(grpid.cast());
|
||||
chat_id_blocked: Blocked| {
|
||||
free(grpname.cast());
|
||||
free(failure_reason.cast());
|
||||
|
||||
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 { 0 };
|
||||
}
|
||||
*ret_chat_id_blocked = if 0 != chat_id {
|
||||
chat_id_blocked
|
||||
} else {
|
||||
Blocked::Not
|
||||
};
|
||||
};
|
||||
|
||||
if mime_parser.is_system_message == DC_CMD_LOCATION_STREAMING_ENABLED {
|
||||
@@ -1095,40 +1087,44 @@ unsafe fn create_or_lookup_group(
|
||||
// search the grpid in the header
|
||||
let optional_field = dc_mimeparser_lookup_optional_field(mime_parser, "Chat-Group-ID");
|
||||
if !optional_field.is_null() {
|
||||
grpid = dc_strdup((*optional_field).fld_value)
|
||||
grpid = to_string((*optional_field).fld_value)
|
||||
}
|
||||
if grpid.is_null() {
|
||||
if grpid.is_empty() {
|
||||
if let Some(field) = lookup_field(mime_parser, "Message-ID", MAILIMF_FIELD_MESSAGE_ID) {
|
||||
let fld_message_id = (*field).fld_data.fld_message_id;
|
||||
if !fld_message_id.is_null() {
|
||||
if let Some(extracted_grpid) =
|
||||
dc_extract_grpid_from_rfc724_mid(as_str((*fld_message_id).mid_value))
|
||||
{
|
||||
grpid = extracted_grpid.strdup();
|
||||
grpid = extracted_grpid.to_string();
|
||||
} else {
|
||||
grpid = std::ptr::null_mut();
|
||||
grpid = "".to_string();
|
||||
}
|
||||
}
|
||||
}
|
||||
if grpid.is_null() {
|
||||
if grpid.is_empty() {
|
||||
if let Some(field) = lookup_field(mime_parser, "In-Reply-To", MAILIMF_FIELD_IN_REPLY_TO)
|
||||
{
|
||||
let fld_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)
|
||||
grpid = to_string(dc_extract_grpid_from_rfc724_mid_list(
|
||||
(*fld_in_reply_to).mid_list,
|
||||
));
|
||||
}
|
||||
}
|
||||
if grpid.is_null() {
|
||||
if grpid.is_empty() {
|
||||
if let Some(field) =
|
||||
lookup_field(mime_parser, "References", MAILIMF_FIELD_REFERENCES)
|
||||
{
|
||||
let fld_references = (*field).fld_data.fld_references;
|
||||
if !fld_references.is_null() {
|
||||
grpid = dc_extract_grpid_from_rfc724_mid_list((*fld_references).mid_list)
|
||||
grpid = to_string(dc_extract_grpid_from_rfc724_mid_list(
|
||||
(*fld_references).mid_list,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
if grpid.is_null() {
|
||||
if grpid.is_empty() {
|
||||
create_or_lookup_adhoc_group(
|
||||
context,
|
||||
mime_parser,
|
||||
@@ -1140,7 +1136,6 @@ unsafe fn create_or_lookup_group(
|
||||
&mut chat_id_blocked,
|
||||
);
|
||||
cleanup(
|
||||
grpid,
|
||||
grpname,
|
||||
failure_reason,
|
||||
ret_chat_id,
|
||||
@@ -1231,7 +1226,12 @@ unsafe fn create_or_lookup_group(
|
||||
set_better_msg(mime_parser, &better_msg);
|
||||
|
||||
// check, if we have a chat with this group ID
|
||||
chat_id = dc_get_chat_id_by_grpid(context, grpid, &mut chat_id_blocked, &mut chat_id_verified);
|
||||
chat_id = chat::get_chat_id_by_grpid(
|
||||
context,
|
||||
&grpid,
|
||||
Some(&mut chat_id_blocked),
|
||||
&mut chat_id_verified,
|
||||
);
|
||||
if chat_id != 0 {
|
||||
if 0 != chat_id_verified
|
||||
&& 0 == check_verified_properties(
|
||||
@@ -1248,12 +1248,12 @@ unsafe fn create_or_lookup_group(
|
||||
|
||||
// check if the sender is a member of the existing group -
|
||||
// if not, we'll recreate the group list
|
||||
if chat_id != 0 && 0 == dc_is_contact_in_chat(context, chat_id, from_id as u32) {
|
||||
if chat_id != 0 && 0 == chat::is_contact_in_chat(context, chat_id, from_id as u32) {
|
||||
recreate_member_list = 1;
|
||||
}
|
||||
|
||||
// check if the group does not exist but should be created
|
||||
group_explicitly_left = dc_is_group_explicitly_left(context, grpid);
|
||||
group_explicitly_left = chat::is_group_explicitly_left(context, &grpid).unwrap_or_default();
|
||||
|
||||
let self_addr = context
|
||||
.sql
|
||||
@@ -1261,17 +1261,17 @@ unsafe fn create_or_lookup_group(
|
||||
.unwrap_or_default();
|
||||
if chat_id == 0
|
||||
&& 0 == dc_mimeparser_is_mailinglist_message(mime_parser)
|
||||
&& !grpid.is_null()
|
||||
&& !grpid.is_empty()
|
||||
&& !grpname.is_null()
|
||||
// otherwise, a pending "quit" message may pop up
|
||||
&& X_MrRemoveFromGrp.is_null()
|
||||
// re-create explicitly left groups only if ourself is re-added
|
||||
&& (0 == group_explicitly_left
|
||||
&& (!group_explicitly_left
|
||||
|| !X_MrAddToGrp.is_null() && addr_cmp(&self_addr, as_str(X_MrAddToGrp)))
|
||||
{
|
||||
let mut create_verified: libc::c_int = 0;
|
||||
let mut create_verified = VerifiedStatus::Unverified;
|
||||
if !dc_mimeparser_lookup_field(mime_parser, "Chat-Verified").is_null() {
|
||||
create_verified = 1;
|
||||
create_verified = VerifiedStatus::Verified;
|
||||
if 0 == check_verified_properties(
|
||||
context,
|
||||
mime_parser,
|
||||
@@ -1284,7 +1284,6 @@ unsafe fn create_or_lookup_group(
|
||||
}
|
||||
if 0 == allow_creation {
|
||||
cleanup(
|
||||
grpid,
|
||||
grpname,
|
||||
failure_reason,
|
||||
ret_chat_id,
|
||||
@@ -1294,7 +1293,7 @@ unsafe fn create_or_lookup_group(
|
||||
);
|
||||
return;
|
||||
}
|
||||
chat_id = create_group_record(context, grpid, grpname, create_blocked, create_verified);
|
||||
chat_id = create_group_record(context, &grpid, grpname, create_blocked, create_verified);
|
||||
chat_id_blocked = create_blocked;
|
||||
recreate_member_list = 1;
|
||||
}
|
||||
@@ -1302,7 +1301,7 @@ unsafe fn create_or_lookup_group(
|
||||
// again, check chat_id
|
||||
if chat_id <= DC_CHAT_ID_LAST_SPECIAL as u32 {
|
||||
chat_id = 0;
|
||||
if 0 != group_explicitly_left {
|
||||
if group_explicitly_left {
|
||||
chat_id = DC_CHAT_ID_TRASH as u32;
|
||||
} else {
|
||||
create_or_lookup_adhoc_group(
|
||||
@@ -1317,7 +1316,6 @@ unsafe fn create_or_lookup_group(
|
||||
);
|
||||
}
|
||||
cleanup(
|
||||
grpid,
|
||||
grpname,
|
||||
failure_reason,
|
||||
ret_chat_id,
|
||||
@@ -1365,7 +1363,6 @@ unsafe fn create_or_lookup_group(
|
||||
}
|
||||
}
|
||||
if 0 != ok {
|
||||
let chat = dc_chat_new(context);
|
||||
info!(
|
||||
context,
|
||||
0,
|
||||
@@ -1376,16 +1373,17 @@ unsafe fn create_or_lookup_group(
|
||||
to_string(grpimage)
|
||||
},
|
||||
);
|
||||
dc_chat_load_from_db(chat, chat_id);
|
||||
if grpimage.is_null() {
|
||||
(*chat).param.remove(Param::ProfileImage);
|
||||
} else {
|
||||
(*chat).param.set(Param::ProfileImage, as_str(grpimage));
|
||||
if let Ok(mut chat) = Chat::load_from_db(context, chat_id) {
|
||||
if grpimage.is_null() {
|
||||
chat.param.remove(Param::ProfileImage);
|
||||
} else {
|
||||
chat.param.set(Param::ProfileImage, as_str(grpimage));
|
||||
}
|
||||
chat.update_param().unwrap();
|
||||
send_EVENT_CHAT_MODIFIED = 1;
|
||||
}
|
||||
dc_chat_update_param(chat);
|
||||
dc_chat_unref(chat);
|
||||
|
||||
free(grpimage as *mut libc::c_void);
|
||||
send_EVENT_CHAT_MODIFIED = 1
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1409,14 +1407,14 @@ unsafe fn create_or_lookup_group(
|
||||
)
|
||||
.ok();
|
||||
if skip.is_null() || !addr_cmp(&self_addr, as_str(skip)) {
|
||||
dc_add_to_chat_contacts_table(context, chat_id, DC_CONTACT_ID_SELF as u32);
|
||||
chat::add_to_chat_contacts_table(context, chat_id, DC_CONTACT_ID_SELF as u32);
|
||||
}
|
||||
if from_id > DC_CHAT_ID_LAST_SPECIAL as u32 {
|
||||
if !Contact::addr_equals_contact(context, &self_addr, from_id as u32)
|
||||
&& (skip.is_null()
|
||||
|| !Contact::addr_equals_contact(context, to_string(skip), from_id as u32))
|
||||
{
|
||||
dc_add_to_chat_contacts_table(context, chat_id, from_id as u32);
|
||||
chat::add_to_chat_contacts_table(context, chat_id, from_id as u32);
|
||||
}
|
||||
}
|
||||
for &to_id in to_ids.iter() {
|
||||
@@ -1424,11 +1422,11 @@ unsafe fn create_or_lookup_group(
|
||||
&& (skip.is_null()
|
||||
|| !Contact::addr_equals_contact(context, to_string(skip), to_id))
|
||||
{
|
||||
dc_add_to_chat_contacts_table(context, chat_id, to_id);
|
||||
chat::add_to_chat_contacts_table(context, chat_id, to_id);
|
||||
}
|
||||
}
|
||||
send_EVENT_CHAT_MODIFIED = 1;
|
||||
dc_reset_gossiped_timestamp(context, chat_id);
|
||||
chat::reset_gossiped_timestamp(context, chat_id);
|
||||
}
|
||||
|
||||
if 0 != send_EVENT_CHAT_MODIFIED {
|
||||
@@ -1438,7 +1436,7 @@ unsafe fn create_or_lookup_group(
|
||||
// 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 == 1 && mime_parser.is_send_by_messenger == 0 {
|
||||
let is_contact_cnt = dc_get_chat_contact_cnt(context, chat_id);
|
||||
let is_contact_cnt = chat::get_chat_contact_cnt(context, chat_id);
|
||||
if is_contact_cnt > 3 {
|
||||
// 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.
|
||||
@@ -1457,7 +1455,6 @@ unsafe fn create_or_lookup_group(
|
||||
}
|
||||
|
||||
cleanup(
|
||||
grpid,
|
||||
grpname,
|
||||
failure_reason,
|
||||
ret_chat_id,
|
||||
@@ -1472,41 +1469,35 @@ unsafe fn create_or_lookup_adhoc_group(
|
||||
context: &Context,
|
||||
mime_parser: &dc_mimeparser_t,
|
||||
allow_creation: libc::c_int,
|
||||
create_blocked: libc::c_int,
|
||||
create_blocked: Blocked,
|
||||
from_id: u32,
|
||||
to_ids: &mut Vec<u32>,
|
||||
ret_chat_id: *mut uint32_t,
|
||||
ret_chat_id_blocked: *mut libc::c_int,
|
||||
ret_chat_id_blocked: &mut Blocked,
|
||||
) {
|
||||
// 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 chat_id = 0;
|
||||
let mut chat_id_blocked = 0;
|
||||
let mut grpid = 0 as *mut libc::c_char;
|
||||
let mut chat_id_blocked = Blocked::Not;
|
||||
let mut grpname = 0 as *mut libc::c_char;
|
||||
|
||||
let cleanup = |grpid: *mut libc::c_char,
|
||||
grpname: *mut libc::c_char,
|
||||
let cleanup = |grpname: *mut libc::c_char,
|
||||
ret_chat_id: *mut uint32_t,
|
||||
ret_chat_id_blocked: *mut libc::c_int,
|
||||
ret_chat_id_blocked: &mut Blocked,
|
||||
chat_id: u32,
|
||||
chat_id_blocked: i32| {
|
||||
free(grpid as *mut libc::c_void);
|
||||
chat_id_blocked: Blocked| {
|
||||
free(grpname as *mut libc::c_void);
|
||||
|
||||
if !ret_chat_id.is_null() {
|
||||
*ret_chat_id = chat_id
|
||||
*ret_chat_id = chat_id;
|
||||
}
|
||||
if !ret_chat_id_blocked.is_null() {
|
||||
*ret_chat_id_blocked = chat_id_blocked
|
||||
};
|
||||
*ret_chat_id_blocked = chat_id_blocked;
|
||||
};
|
||||
|
||||
// build member list from the given ids
|
||||
if to_ids.is_empty() || 0 != dc_mimeparser_is_mailinglist_message(mime_parser) {
|
||||
// too few contacts or a mailinglist
|
||||
cleanup(
|
||||
grpid,
|
||||
grpname,
|
||||
ret_chat_id,
|
||||
ret_chat_id_blocked,
|
||||
@@ -1526,7 +1517,6 @@ unsafe fn create_or_lookup_adhoc_group(
|
||||
if member_ids.len() < 3 {
|
||||
// too few contacts given
|
||||
cleanup(
|
||||
grpid,
|
||||
grpname,
|
||||
ret_chat_id,
|
||||
ret_chat_id_blocked,
|
||||
@@ -1547,7 +1537,7 @@ unsafe fn create_or_lookup_adhoc_group(
|
||||
),
|
||||
params![],
|
||||
|row| {
|
||||
Ok((row.get::<_, i32>(0)?, row.get::<_, Option<i32>>(1)?.unwrap_or_default()))
|
||||
Ok((row.get::<_, i32>(0)?, row.get::<_, Option<Blocked>>(1)?.unwrap_or_default()))
|
||||
}
|
||||
);
|
||||
|
||||
@@ -1556,7 +1546,6 @@ unsafe fn create_or_lookup_adhoc_group(
|
||||
chat_id_blocked = id_blocked;
|
||||
/* success, chat found */
|
||||
cleanup(
|
||||
grpid,
|
||||
grpname,
|
||||
ret_chat_id,
|
||||
ret_chat_id_blocked,
|
||||
@@ -1569,7 +1558,6 @@ unsafe fn create_or_lookup_adhoc_group(
|
||||
|
||||
if 0 == allow_creation {
|
||||
cleanup(
|
||||
grpid,
|
||||
grpname,
|
||||
ret_chat_id,
|
||||
ret_chat_id_blocked,
|
||||
@@ -1583,10 +1571,9 @@ unsafe fn create_or_lookup_adhoc_group(
|
||||
|
||||
// create a new ad-hoc group
|
||||
// - there is no need to check if this group exists; otherwise we would have caught it above
|
||||
grpid = create_adhoc_grp_id(context, &member_ids);
|
||||
if grpid.is_null() {
|
||||
let grpid = create_adhoc_grp_id(context, &member_ids);
|
||||
if grpid.is_empty() {
|
||||
cleanup(
|
||||
grpid,
|
||||
grpname,
|
||||
ret_chat_id,
|
||||
ret_chat_id_blocked,
|
||||
@@ -1606,16 +1593,21 @@ unsafe fn create_or_lookup_adhoc_group(
|
||||
}
|
||||
|
||||
// create group record
|
||||
chat_id = create_group_record(context, grpid, grpname, create_blocked, 0);
|
||||
chat_id = create_group_record(
|
||||
context,
|
||||
&grpid,
|
||||
grpname,
|
||||
create_blocked,
|
||||
VerifiedStatus::Unverified,
|
||||
);
|
||||
chat_id_blocked = create_blocked;
|
||||
for &member_id in &member_ids {
|
||||
dc_add_to_chat_contacts_table(context, chat_id, member_id);
|
||||
chat::add_to_chat_contacts_table(context, chat_id, member_id);
|
||||
}
|
||||
|
||||
context.call_cb(Event::CHAT_MODIFIED, chat_id as uintptr_t, 0 as uintptr_t);
|
||||
|
||||
cleanup(
|
||||
grpid,
|
||||
grpname,
|
||||
ret_chat_id,
|
||||
ret_chat_id_blocked,
|
||||
@@ -1626,19 +1618,23 @@ unsafe fn create_or_lookup_adhoc_group(
|
||||
|
||||
fn create_group_record(
|
||||
context: &Context,
|
||||
grpid: *const libc::c_char,
|
||||
grpid: impl AsRef<str>,
|
||||
grpname: *const libc::c_char,
|
||||
create_blocked: libc::c_int,
|
||||
create_verified: libc::c_int,
|
||||
create_blocked: Blocked,
|
||||
create_verified: VerifiedStatus,
|
||||
) -> u32 {
|
||||
if sql::execute(
|
||||
context,
|
||||
&context.sql,
|
||||
"INSERT INTO chats (type, name, grpid, blocked) VALUES(?, ?, ?, ?);",
|
||||
params![
|
||||
if 0 != create_verified { 130 } else { 120 },
|
||||
if VerifiedStatus::Unverified != create_verified {
|
||||
Chattype::VerifiedGroup
|
||||
} else {
|
||||
Chattype::Group
|
||||
},
|
||||
as_str(grpname),
|
||||
as_str(grpid),
|
||||
grpid.as_ref(),
|
||||
create_blocked,
|
||||
],
|
||||
)
|
||||
@@ -1647,10 +1643,10 @@ fn create_group_record(
|
||||
return 0;
|
||||
}
|
||||
|
||||
sql::get_rowid(context, &context.sql, "chats", "grpid", as_str(grpid))
|
||||
sql::get_rowid(context, &context.sql, "chats", "grpid", grpid.as_ref())
|
||||
}
|
||||
|
||||
unsafe fn create_adhoc_grp_id(context: &Context, member_ids: &Vec<u32>) -> *mut libc::c_char {
|
||||
fn create_adhoc_grp_id(context: &Context, member_ids: &Vec<u32>) -> String {
|
||||
/* algorithm:
|
||||
- sort normalized, lowercased, e-mail addresses alphabetically
|
||||
- put all e-mail addresses into a single string, separate the address by a single comma
|
||||
@@ -1686,14 +1682,13 @@ unsafe fn create_adhoc_grp_id(context: &Context, member_ids: &Vec<u32>) -> *mut
|
||||
)
|
||||
.unwrap_or_else(|_| member_cs);
|
||||
|
||||
hex_hash(&members) as *mut _
|
||||
hex_hash(&members)
|
||||
}
|
||||
|
||||
fn hex_hash(s: impl AsRef<str>) -> *const libc::c_char {
|
||||
fn hex_hash(s: impl AsRef<str>) -> String {
|
||||
let bytes = s.as_ref().as_bytes();
|
||||
let result = Sha256::digest(bytes);
|
||||
let result_hex = hex::encode(&result[..8]);
|
||||
unsafe { result_hex.strdup() as *const _ }
|
||||
hex::encode(&result[..8])
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
@@ -2170,8 +2165,7 @@ mod tests {
|
||||
fn test_hex_hash() {
|
||||
let data = "hello world";
|
||||
|
||||
let res_c = hex_hash(data);
|
||||
let res = to_string(res_c);
|
||||
let res = hex_hash(data);
|
||||
assert_eq!(res, "b94d27b9934d3e08");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,20 +1,17 @@
|
||||
use std::ffi::CString;
|
||||
|
||||
use mmime::mailimf_types::*;
|
||||
use percent_encoding::{utf8_percent_encode, NON_ALPHANUMERIC};
|
||||
|
||||
use crate::aheader::EncryptPreference;
|
||||
use crate::chat::{self, Chat};
|
||||
use crate::constants::*;
|
||||
use crate::contact::*;
|
||||
use crate::context::Context;
|
||||
use crate::dc_chat::*;
|
||||
use crate::dc_configure::*;
|
||||
use crate::dc_e2ee::*;
|
||||
use crate::dc_lot::*;
|
||||
use crate::dc_mimeparser::*;
|
||||
use crate::dc_msg::*;
|
||||
use crate::dc_qr::*;
|
||||
use crate::dc_strencode::*;
|
||||
use crate::dc_token::*;
|
||||
use crate::dc_tools::*;
|
||||
use crate::key::*;
|
||||
@@ -36,9 +33,6 @@ pub unsafe fn dc_get_securejoin_qr(
|
||||
let mut fingerprint = 0 as *mut libc::c_char;
|
||||
let mut invitenumber: *mut libc::c_char;
|
||||
let mut auth: *mut libc::c_char;
|
||||
let mut chat = 0 as *mut Chat;
|
||||
let mut group_name = 0 as *mut libc::c_char;
|
||||
let mut group_name_urlencoded = 0 as *mut libc::c_char;
|
||||
let mut qr: Option<String> = None;
|
||||
|
||||
dc_ensure_secret_key_exists(context).ok();
|
||||
@@ -54,13 +48,10 @@ pub unsafe fn dc_get_securejoin_qr(
|
||||
}
|
||||
let self_addr = context.sql.get_config(context, "configured_addr");
|
||||
|
||||
let cleanup = |fingerprint, chat, group_name, group_name_urlencoded| {
|
||||
let cleanup = |fingerprint| {
|
||||
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);
|
||||
|
||||
if let Some(qr) = qr {
|
||||
qr.strdup()
|
||||
@@ -71,7 +62,7 @@ pub unsafe fn dc_get_securejoin_qr(
|
||||
|
||||
if self_addr.is_none() {
|
||||
error!(context, 0, "Not configured, cannot generate QR code.",);
|
||||
return cleanup(fingerprint, chat, group_name, group_name_urlencoded);
|
||||
return cleanup(fingerprint);
|
||||
}
|
||||
|
||||
let self_addr = self_addr.unwrap();
|
||||
@@ -83,34 +74,34 @@ pub unsafe fn dc_get_securejoin_qr(
|
||||
fingerprint = get_self_fingerprint(context);
|
||||
|
||||
if fingerprint.is_null() {
|
||||
return cleanup(fingerprint, chat, group_name, group_name_urlencoded);
|
||||
return cleanup(fingerprint);
|
||||
}
|
||||
|
||||
let self_addr_urlencoded = utf8_percent_encode(&self_addr, NON_ALPHANUMERIC).to_string();
|
||||
let self_name_urlencoded = utf8_percent_encode(&self_name, NON_ALPHANUMERIC).to_string();
|
||||
|
||||
qr = if 0 != group_chat_id {
|
||||
chat = dc_get_chat(context, group_chat_id);
|
||||
if chat.is_null() {
|
||||
if let Ok(chat) = Chat::load_from_db(context, group_chat_id) {
|
||||
let group_name = chat.get_name();
|
||||
let group_name_urlencoded =
|
||||
utf8_percent_encode(&group_name, NON_ALPHANUMERIC).to_string();
|
||||
|
||||
Some(format!(
|
||||
"OPENPGP4FPR:{}#a={}&g={}&x={}&i={}&s={}",
|
||||
as_str(fingerprint),
|
||||
self_addr_urlencoded,
|
||||
&group_name_urlencoded,
|
||||
&chat.grpid,
|
||||
as_str(invitenumber),
|
||||
as_str(auth),
|
||||
))
|
||||
} else {
|
||||
error!(
|
||||
context,
|
||||
0, "Cannot get QR-code for chat-id {}", group_chat_id,
|
||||
);
|
||||
return cleanup(fingerprint, chat, group_name, group_name_urlencoded);
|
||||
return cleanup(fingerprint);
|
||||
}
|
||||
|
||||
group_name = dc_chat_get_name(chat);
|
||||
group_name_urlencoded = dc_urlencode(group_name);
|
||||
|
||||
Some(format!(
|
||||
"OPENPGP4FPR:{}#a={}&g={}&x={}&i={}&s={}",
|
||||
as_str(fingerprint),
|
||||
self_addr_urlencoded,
|
||||
as_str(group_name_urlencoded),
|
||||
as_str((*chat).grpid),
|
||||
as_str(invitenumber),
|
||||
as_str(auth),
|
||||
))
|
||||
} else {
|
||||
Some(format!(
|
||||
"OPENPGP4FPR:{}#a={}&n={}&i={}&s={}",
|
||||
@@ -124,7 +115,7 @@ pub unsafe fn dc_get_securejoin_qr(
|
||||
|
||||
info!(context, 0, "Generated QR code: {}", qr.as_ref().unwrap());
|
||||
|
||||
cleanup(fingerprint, chat, group_name, group_name_urlencoded)
|
||||
cleanup(fingerprint)
|
||||
}
|
||||
|
||||
fn get_self_fingerprint(context: &Context) -> *mut libc::c_char {
|
||||
@@ -155,7 +146,8 @@ pub unsafe fn dc_join_securejoin(context: &Context, qr: *const libc::c_char) ->
|
||||
if qr_scan.is_null() || (*qr_scan).state != 200i32 && (*qr_scan).state != 202i32 {
|
||||
error!(context, 0, "Unknown QR code.",);
|
||||
} else {
|
||||
contact_chat_id = dc_create_chat_by_contact_id(context, (*qr_scan).id);
|
||||
contact_chat_id =
|
||||
chat::create_by_contact_id(context, (*qr_scan).id).unwrap_or_default();
|
||||
if contact_chat_id == 0i32 as libc::c_uint {
|
||||
error!(context, 0, "Unknown contact.",);
|
||||
} else if !(context
|
||||
@@ -193,9 +185,9 @@ pub unsafe fn dc_join_securejoin(context: &Context, qr: *const libc::c_char) ->
|
||||
(*qr_scan).auth,
|
||||
own_fingerprint,
|
||||
if 0 != join_vg {
|
||||
(*qr_scan).text2
|
||||
as_str((*qr_scan).text2)
|
||||
} else {
|
||||
0 as *mut libc::c_char
|
||||
""
|
||||
},
|
||||
);
|
||||
free(own_fingerprint as *mut libc::c_void);
|
||||
@@ -211,7 +203,7 @@ pub unsafe fn dc_join_securejoin(context: &Context, qr: *const libc::c_char) ->
|
||||
},
|
||||
(*qr_scan).invitenumber,
|
||||
0 as *const libc::c_char,
|
||||
0 as *const libc::c_char,
|
||||
"",
|
||||
);
|
||||
}
|
||||
|
||||
@@ -234,10 +226,10 @@ pub unsafe fn dc_join_securejoin(context: &Context, qr: *const libc::c_char) ->
|
||||
bob.expects = 0;
|
||||
if bob.status == 1 {
|
||||
if 0 != join_vg {
|
||||
ret_chat_id = dc_get_chat_id_by_grpid(
|
||||
ret_chat_id = chat::get_chat_id_by_grpid(
|
||||
context,
|
||||
(*qr_scan).text2,
|
||||
0 as *mut libc::c_int,
|
||||
to_string((*qr_scan).text2),
|
||||
None,
|
||||
0 as *mut libc::c_int,
|
||||
) as libc::c_int
|
||||
} else {
|
||||
@@ -259,7 +251,7 @@ unsafe fn send_handshake_msg(
|
||||
step: *const libc::c_char,
|
||||
param2: *const libc::c_char,
|
||||
fingerprint: *const libc::c_char,
|
||||
grpid: *const libc::c_char,
|
||||
grpid: impl AsRef<str>,
|
||||
) {
|
||||
let mut msg: *mut dc_msg_t = dc_msg_new_untyped(context);
|
||||
(*msg).type_0 = Viewtype::Text;
|
||||
@@ -277,8 +269,8 @@ unsafe fn send_handshake_msg(
|
||||
if !fingerprint.is_null() {
|
||||
(*msg).param.set(Param::Arg3, as_str(fingerprint));
|
||||
}
|
||||
if !grpid.is_null() {
|
||||
(*msg).param.set(Param::Arg4, as_str(grpid));
|
||||
if !grpid.as_ref().is_empty() {
|
||||
(*msg).param.set(Param::Arg4, grpid.as_ref());
|
||||
}
|
||||
if strcmp(step, b"vg-request\x00" as *const u8 as *const libc::c_char) == 0i32
|
||||
|| strcmp(step, b"vc-request\x00" as *const u8 as *const libc::c_char) == 0i32
|
||||
@@ -290,12 +282,13 @@ unsafe fn send_handshake_msg(
|
||||
} else {
|
||||
(*msg).param.set_int(Param::GuranteeE2ee, 1);
|
||||
}
|
||||
dc_send_msg(context, contact_chat_id, msg);
|
||||
// TODO. handle cleanup on error
|
||||
chat::send_msg(context, contact_chat_id, msg).unwrap();
|
||||
dc_msg_unref(msg);
|
||||
}
|
||||
|
||||
unsafe fn chat_id_2_contact_id(context: &Context, contact_chat_id: uint32_t) -> uint32_t {
|
||||
let contacts = dc_get_chat_contacts(context, contact_chat_id);
|
||||
let contacts = chat::get_chat_contacts(context, contact_chat_id);
|
||||
if contacts.len() == 1 {
|
||||
contacts[0]
|
||||
} else {
|
||||
@@ -312,7 +305,7 @@ unsafe fn fingerprint_equals_sender(
|
||||
return 0;
|
||||
}
|
||||
let mut fingerprint_equal: libc::c_int = 0i32;
|
||||
let contacts = dc_get_chat_contacts(context, contact_chat_id);
|
||||
let contacts = chat::get_chat_contacts(context, contact_chat_id);
|
||||
|
||||
if contacts.len() == 1 {
|
||||
if let Ok(contact) = Contact::load_from_db(context, contacts[0]) {
|
||||
@@ -345,9 +338,9 @@ pub unsafe fn dc_handle_securejoin_handshake(
|
||||
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 contact_chat_id: u32;
|
||||
let contact_chat_id_blocked: Blocked;
|
||||
let mut grpid = "".to_string();
|
||||
let mut ret: libc::c_int = 0i32;
|
||||
|
||||
if !(contact_id <= 9i32 as libc::c_uint) {
|
||||
@@ -361,15 +354,13 @@ pub unsafe fn dc_handle_securejoin_handshake(
|
||||
);
|
||||
join_vg = (strncmp(step, b"vg-\x00" as *const u8 as *const libc::c_char, 3) == 0)
|
||||
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);
|
||||
let (id, bl) = chat::create_or_lookup_by_contact_id(context, contact_id, Blocked::Not)
|
||||
.unwrap_or_default();
|
||||
contact_chat_id = id;
|
||||
contact_chat_id_blocked = bl;
|
||||
|
||||
if Blocked::Not != contact_chat_id_blocked {
|
||||
chat::unblock(context, contact_chat_id);
|
||||
}
|
||||
ret = 0x2i32;
|
||||
if strcmp(step, b"vg-request\x00" as *const u8 as *const libc::c_char) == 0i32
|
||||
@@ -409,7 +400,7 @@ pub unsafe fn dc_handle_securejoin_handshake(
|
||||
},
|
||||
0 as *const libc::c_char,
|
||||
0 as *const libc::c_char,
|
||||
0 as *const libc::c_char,
|
||||
"",
|
||||
);
|
||||
current_block = 10256747982273457880;
|
||||
}
|
||||
@@ -439,7 +430,7 @@ pub unsafe fn dc_handle_securejoin_handshake(
|
||||
scanned_fingerprint_of_alice = dc_strdup((*scan).fingerprint);
|
||||
auth = dc_strdup((*scan).auth);
|
||||
if 0 != join_vg {
|
||||
grpid = dc_strdup((*scan).text2)
|
||||
grpid = to_string((*scan).text2);
|
||||
}
|
||||
}
|
||||
if !encrypted_and_signed(mimeparser, scanned_fingerprint_of_alice) {
|
||||
@@ -579,18 +570,18 @@ pub unsafe fn dc_handle_securejoin_handshake(
|
||||
600i32 as uintptr_t,
|
||||
);
|
||||
if 0 != join_vg {
|
||||
grpid = dc_strdup(lookup_field(mimeparser, "Secure-Join-Group"));
|
||||
let group_chat_id: uint32_t = dc_get_chat_id_by_grpid(
|
||||
grpid = to_string(lookup_field(mimeparser, "Secure-Join-Group"));
|
||||
let group_chat_id: uint32_t = chat::get_chat_id_by_grpid(
|
||||
context,
|
||||
grpid,
|
||||
0 as *mut libc::c_int,
|
||||
&grpid,
|
||||
None,
|
||||
0 as *mut libc::c_int,
|
||||
);
|
||||
if group_chat_id == 0i32 as libc::c_uint {
|
||||
error!(context, 0, "Chat {} not found.", as_str(grpid),);
|
||||
error!(context, 0, "Chat {} not found.", &grpid);
|
||||
current_block = 4378276786830486580;
|
||||
} else {
|
||||
dc_add_contact_to_chat_ex(
|
||||
chat::add_contact_to_chat_ex(
|
||||
context,
|
||||
group_chat_id,
|
||||
contact_id,
|
||||
@@ -605,7 +596,7 @@ pub unsafe fn dc_handle_securejoin_handshake(
|
||||
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.call_cb(
|
||||
Event::SECUREJOIN_INVITER_PROGRESS,
|
||||
@@ -647,16 +638,16 @@ pub unsafe fn dc_handle_securejoin_handshake(
|
||||
let scan = context.bob.clone().read().unwrap().qr_scan;
|
||||
scanned_fingerprint_of_alice = dc_strdup((*scan).fingerprint);
|
||||
if 0 != join_vg {
|
||||
grpid = dc_strdup((*scan).text2)
|
||||
grpid = to_string((*scan).text2);
|
||||
}
|
||||
}
|
||||
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(
|
||||
chat::get_chat_id_by_grpid(
|
||||
context,
|
||||
grpid,
|
||||
0 as *mut libc::c_int,
|
||||
None,
|
||||
&mut is_verified_group,
|
||||
);
|
||||
if 0 == is_verified_group {
|
||||
@@ -735,7 +726,7 @@ pub unsafe fn dc_handle_securejoin_handshake(
|
||||
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);
|
||||
@@ -794,7 +785,6 @@ pub unsafe fn dc_handle_securejoin_handshake(
|
||||
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);
|
||||
|
||||
ret
|
||||
}
|
||||
@@ -812,9 +802,8 @@ unsafe fn secure_connection_established(context: &Context, contact_chat_id: uint
|
||||
} else {
|
||||
"?"
|
||||
};
|
||||
let msg =
|
||||
CString::new(context.stock_string_repl_str(StockMessage::ContactVerified, addr)).unwrap();
|
||||
dc_add_device_msg(context, contact_chat_id, msg.as_ptr());
|
||||
let msg = context.stock_string_repl_str(StockMessage::ContactVerified, addr);
|
||||
chat::add_device_msg(context, contact_chat_id, msg);
|
||||
context.call_cb(
|
||||
Event::CHAT_MODIFIED,
|
||||
contact_chat_id as uintptr_t,
|
||||
@@ -854,9 +843,9 @@ unsafe fn could_not_establish_secure_connection(
|
||||
"?"
|
||||
},
|
||||
);
|
||||
let msg_c = CString::new(msg.as_str()).unwrap();
|
||||
dc_add_device_msg(context, contact_chat_id, msg_c.as_ptr());
|
||||
error!(context, 0, "{} ({})", msg, as_str(details));
|
||||
|
||||
chat::add_device_msg(context, contact_chat_id, &msg);
|
||||
error!(context, 0, "{} ({})", &msg, as_str(details));
|
||||
}
|
||||
|
||||
unsafe fn mark_peer_as_verified(
|
||||
@@ -917,8 +906,6 @@ unsafe fn encrypted_and_signed(
|
||||
}
|
||||
|
||||
pub unsafe fn dc_handle_degrade_event(context: &Context, peerstate: &Peerstate) {
|
||||
let mut contact_chat_id = 0;
|
||||
|
||||
// - 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
|
||||
@@ -935,22 +922,17 @@ pub unsafe fn dc_handle_degrade_event(context: &Context, peerstate: &Peerstate)
|
||||
)
|
||||
.unwrap_or_default();
|
||||
if contact_id > 0 {
|
||||
dc_create_or_lookup_nchat_by_contact_id(
|
||||
context,
|
||||
contact_id as u32,
|
||||
2,
|
||||
&mut contact_chat_id,
|
||||
0 as *mut libc::c_int,
|
||||
);
|
||||
let (contact_chat_id, _) =
|
||||
chat::create_or_lookup_by_contact_id(context, contact_id as u32, Blocked::Deaddrop)
|
||||
.unwrap_or_default();
|
||||
|
||||
let peeraddr: &str = match peerstate.addr {
|
||||
Some(ref addr) => &addr,
|
||||
None => "",
|
||||
};
|
||||
let msg = CString::new(
|
||||
context.stock_string_repl_str(StockMessage::ContactSetupChanged, peeraddr),
|
||||
)
|
||||
.unwrap();
|
||||
dc_add_device_msg(context, contact_chat_id, msg.as_ptr());
|
||||
let msg = context.stock_string_repl_str(StockMessage::ContactSetupChanged, peeraddr);
|
||||
|
||||
chat::add_device_msg(context, contact_chat_id, msg);
|
||||
context.call_cb(
|
||||
Event::CHAT_MODIFIED,
|
||||
contact_chat_id as uintptr_t,
|
||||
|
||||
@@ -18,48 +18,6 @@ fn isalnum(c: libc::c_int) -> libc::c_int {
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn dc_urlencode(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 buf: *mut libc::c_char =
|
||||
malloc(strlen(to_encode).wrapping_mul(3).wrapping_add(1)) as *mut libc::c_char;
|
||||
let mut pbuf: *mut libc::c_char = buf;
|
||||
assert!(!buf.is_null());
|
||||
|
||||
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;
|
||||
|
||||
buf
|
||||
}
|
||||
|
||||
/* ******************************************************************************
|
||||
* URL encoding and decoding, RFC 3986
|
||||
******************************************************************************/
|
||||
@@ -713,6 +671,7 @@ unsafe fn print_hex(target: *mut libc::c_char, cur: *const libc::c_char) {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use percent_encoding::{percent_encode, NON_ALPHANUMERIC};
|
||||
use std::ffi::CStr;
|
||||
|
||||
#[test]
|
||||
@@ -892,14 +851,15 @@ mod tests {
|
||||
#[test]
|
||||
fn test_dc_urlencode_urldecode() {
|
||||
unsafe {
|
||||
let buf1 =
|
||||
dc_urlencode(b"Bj\xc3\xb6rn Petersen\x00" as *const u8 as *const libc::c_char);
|
||||
let buf1 = percent_encode(b"Bj\xc3\xb6rn Petersen", NON_ALPHANUMERIC)
|
||||
.to_string()
|
||||
.strdup();
|
||||
|
||||
assert_eq!(
|
||||
CStr::from_ptr(buf1 as *const libc::c_char)
|
||||
.to_str()
|
||||
.unwrap(),
|
||||
"Bj%C3%B6rn+Petersen"
|
||||
"Bj%C3%B6rn%20Petersen"
|
||||
);
|
||||
|
||||
let buf2 = dc_urldecode(buf1);
|
||||
|
||||
137
src/dc_tools.rs
137
src/dc_tools.rs
@@ -1,5 +1,6 @@
|
||||
use std::borrow::Cow;
|
||||
use std::ffi::{CStr, CString};
|
||||
use std::path::Path;
|
||||
use std::str::FromStr;
|
||||
use std::time::SystemTime;
|
||||
use std::{fmt, fs, ptr};
|
||||
@@ -166,11 +167,6 @@ pub unsafe fn dc_trim(buf: *mut libc::c_char) {
|
||||
dc_rtrim(buf);
|
||||
}
|
||||
|
||||
/* the result must be free()'d */
|
||||
unsafe fn dc_strlower(in_0: *const libc::c_char) -> *mut libc::c_char {
|
||||
to_string(in_0).to_lowercase().strdup()
|
||||
}
|
||||
|
||||
pub unsafe fn dc_strlower_in_place(in_0: *mut libc::c_char) {
|
||||
let raw = CString::yolo(to_string(in_0).to_lowercase());
|
||||
assert_eq!(strlen(in_0), strlen(raw.as_ptr()));
|
||||
@@ -531,7 +527,7 @@ const COLORS: [u32; 16] = [
|
||||
0x39b249, 0xbb243b, 0x964078, 0x66874f, 0x308ab9, 0x127ed0, 0xbe450c,
|
||||
];
|
||||
|
||||
pub fn dc_str_to_color_safe(s: impl AsRef<str>) -> u32 {
|
||||
pub fn dc_str_to_color(s: impl AsRef<str>) -> u32 {
|
||||
let str_lower = s.as_ref().to_lowercase();
|
||||
let mut checksum = 0;
|
||||
let bytes = str_lower.as_bytes();
|
||||
@@ -544,10 +540,6 @@ pub fn dc_str_to_color_safe(s: impl AsRef<str>) -> u32 {
|
||||
COLORS[color_index]
|
||||
}
|
||||
|
||||
pub unsafe fn dc_str_to_color(str: *const libc::c_char) -> libc::c_int {
|
||||
dc_str_to_color_safe(as_str(str)) as libc::c_int
|
||||
}
|
||||
|
||||
/* clist tools */
|
||||
/* calls free() for each item content */
|
||||
pub unsafe fn clist_free_content(haystack: *const clist) {
|
||||
@@ -637,7 +629,7 @@ pub unsafe fn dc_smeared_time(context: &Context) -> i64 {
|
||||
now
|
||||
}
|
||||
|
||||
pub unsafe fn dc_create_smeared_timestamp(context: &Context) -> i64 {
|
||||
pub fn dc_create_smeared_timestamp(context: &Context) -> i64 {
|
||||
let now = time();
|
||||
let mut ret = now;
|
||||
|
||||
@@ -652,7 +644,7 @@ pub unsafe fn dc_create_smeared_timestamp(context: &Context) -> i64 {
|
||||
ret
|
||||
}
|
||||
|
||||
pub unsafe fn dc_create_smeared_timestamps(context: &Context, count: libc::c_int) -> i64 {
|
||||
pub fn dc_create_smeared_timestamps(context: &Context, count: libc::c_int) -> i64 {
|
||||
/* get a range to timestamps that can be used uniquely */
|
||||
let now = time();
|
||||
let start = now + (if count < 5 { count } else { 5 }) as i64 - count as i64;
|
||||
@@ -848,17 +840,11 @@ unsafe fn dc_validate_filename(filename: *mut libc::c_char) {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
pub unsafe fn dc_get_filename(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);
|
||||
dc_strdup(p)
|
||||
pub unsafe fn dc_get_filename(path_filename: impl AsRef<str>) -> *mut libc::c_char {
|
||||
if let Some(p) = Path::new(path_filename.as_ref()).file_name() {
|
||||
p.to_string_lossy().strdup()
|
||||
} else {
|
||||
dc_strdup(pathNfilename)
|
||||
ptr::null_mut()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -869,12 +855,15 @@ unsafe fn dc_split_filename(
|
||||
ret_basename: *mut *mut libc::c_char,
|
||||
ret_all_suffixes_incl_dot: *mut *mut libc::c_char,
|
||||
) {
|
||||
if pathNfilename.is_null() {
|
||||
return;
|
||||
}
|
||||
/* 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 basename: *mut libc::c_char = dc_get_filename(pathNfilename);
|
||||
let basename: *mut libc::c_char = dc_get_filename(as_str(pathNfilename));
|
||||
let suffix: *mut libc::c_char;
|
||||
let p1: *mut libc::c_char = strrchr(basename, '.' as i32);
|
||||
if !p1.is_null() {
|
||||
@@ -897,16 +886,12 @@ unsafe fn dc_split_filename(
|
||||
|
||||
// the returned suffix is lower-case
|
||||
#[allow(non_snake_case)]
|
||||
pub unsafe fn dc_get_filesuffix_lc(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);
|
||||
}
|
||||
pub unsafe fn dc_get_filesuffix_lc(path_filename: impl AsRef<str>) -> *mut libc::c_char {
|
||||
if let Some(p) = Path::new(path_filename.as_ref()).extension() {
|
||||
p.to_string_lossy().to_lowercase().strdup()
|
||||
} else {
|
||||
ptr::null_mut()
|
||||
}
|
||||
|
||||
ptr::null_mut()
|
||||
}
|
||||
|
||||
/// Returns the `(width, height)` of the given image buffer.
|
||||
@@ -936,34 +921,25 @@ pub fn dc_get_abs_path_safe<P: AsRef<std::path::Path>>(
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
pub unsafe fn dc_get_abs_path(
|
||||
context: &Context,
|
||||
pathNfilename: *const libc::c_char,
|
||||
path_filename: impl AsRef<str>,
|
||||
) -> *mut libc::c_char {
|
||||
if pathNfilename.is_null() {
|
||||
return ptr::null_mut();
|
||||
}
|
||||
|
||||
let starts = strncmp(
|
||||
pathNfilename,
|
||||
b"$BLOBDIR\x00" as *const u8 as *const libc::c_char,
|
||||
8,
|
||||
) == 0;
|
||||
let starts = path_filename.as_ref().starts_with("$BLOBDIR");
|
||||
|
||||
if starts && !context.has_blobdir() {
|
||||
return ptr::null_mut();
|
||||
}
|
||||
|
||||
let mut pathNfilename_abs: *mut libc::c_char = dc_strdup(pathNfilename);
|
||||
let mut path_filename_abs = path_filename.as_ref().strdup();
|
||||
if starts && context.has_blobdir() {
|
||||
dc_str_replace(
|
||||
&mut pathNfilename_abs,
|
||||
&mut path_filename_abs,
|
||||
b"$BLOBDIR\x00" as *const u8 as *const libc::c_char,
|
||||
context.get_blobdir(),
|
||||
);
|
||||
}
|
||||
pathNfilename_abs
|
||||
path_filename_abs
|
||||
}
|
||||
|
||||
pub fn dc_file_exist(context: &Context, path: impl AsRef<std::path::Path>) -> bool {
|
||||
@@ -1159,56 +1135,49 @@ pub unsafe fn dc_get_fine_pathNfilename(
|
||||
ret
|
||||
}
|
||||
|
||||
pub unsafe fn dc_is_blobdir_path(context: &Context, path: *const libc::c_char) -> bool {
|
||||
strncmp(path, context.get_blobdir(), strlen(context.get_blobdir())) == 0
|
||||
|| strncmp(path, b"$BLOBDIR\x00" as *const u8 as *const libc::c_char, 8) == 0
|
||||
pub fn dc_is_blobdir_path(context: &Context, path: impl AsRef<str>) -> bool {
|
||||
path.as_ref().starts_with(as_str(context.get_blobdir()))
|
||||
|| path.as_ref().starts_with("$BLOBDIR")
|
||||
}
|
||||
|
||||
unsafe fn dc_make_rel_path(context: &Context, path: *mut *mut libc::c_char) {
|
||||
if path.is_null() || (*path).is_null() {
|
||||
return;
|
||||
fn dc_make_rel_path(context: &Context, path: &mut String) {
|
||||
if path.starts_with(as_str(context.get_blobdir())) {
|
||||
*path = path.replace("$BLOBDIR", as_str(context.get_blobdir()));
|
||||
}
|
||||
if strncmp(*path, context.get_blobdir(), strlen(context.get_blobdir())) == 0 {
|
||||
dc_str_replace(
|
||||
path,
|
||||
context.get_blobdir(),
|
||||
b"$BLOBDIR\x00" as *const u8 as *const libc::c_char,
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
pub unsafe fn dc_make_rel_and_copy(context: &Context, path: *mut *mut libc::c_char) -> bool {
|
||||
pub fn dc_make_rel_and_copy(context: &Context, path: &mut String) -> bool {
|
||||
let mut success = false;
|
||||
let mut filename: *mut libc::c_char = ptr::null_mut();
|
||||
let mut blobdir_path: *mut libc::c_char = ptr::null_mut();
|
||||
if !(path.is_null() || (*path).is_null()) {
|
||||
if dc_is_blobdir_path(context, *path) {
|
||||
dc_make_rel_path(context, path);
|
||||
success = true;
|
||||
} else {
|
||||
filename = dc_get_filename(*path);
|
||||
if !(filename.is_null()
|
||||
|| {
|
||||
blobdir_path = dc_get_fine_pathNfilename(
|
||||
let mut filename = ptr::null_mut();
|
||||
let mut blobdir_path = ptr::null_mut();
|
||||
if dc_is_blobdir_path(context, &path) {
|
||||
dc_make_rel_path(context, path);
|
||||
success = true;
|
||||
} else {
|
||||
filename = unsafe { dc_get_filename(&path) };
|
||||
if !(filename.is_null()
|
||||
|| {
|
||||
blobdir_path = unsafe {
|
||||
dc_get_fine_pathNfilename(
|
||||
context,
|
||||
b"$BLOBDIR\x00" as *const u8 as *const libc::c_char,
|
||||
filename,
|
||||
);
|
||||
blobdir_path.is_null()
|
||||
}
|
||||
|| !dc_copy_file(context, as_path(*path), as_path(blobdir_path)))
|
||||
{
|
||||
free(*path as *mut libc::c_void);
|
||||
*path = blobdir_path;
|
||||
blobdir_path = ptr::null_mut();
|
||||
dc_make_rel_path(context, path);
|
||||
success = true;
|
||||
)
|
||||
};
|
||||
blobdir_path.is_null()
|
||||
}
|
||||
|| !dc_copy_file(context, &path, as_path(blobdir_path)))
|
||||
{
|
||||
*path = to_string(blobdir_path);
|
||||
blobdir_path = ptr::null_mut();
|
||||
dc_make_rel_path(context, path);
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
free(blobdir_path as *mut libc::c_void);
|
||||
free(filename as *mut libc::c_void);
|
||||
|
||||
unsafe {
|
||||
free(blobdir_path.cast());
|
||||
free(filename.cast());
|
||||
}
|
||||
success
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ mod log;
|
||||
mod error;
|
||||
|
||||
mod aheader;
|
||||
pub mod chat;
|
||||
pub mod chatlist;
|
||||
pub mod config;
|
||||
pub mod constants;
|
||||
@@ -42,7 +43,6 @@ pub mod types;
|
||||
pub mod x;
|
||||
|
||||
pub mod dc_array;
|
||||
pub mod dc_chat;
|
||||
pub mod dc_configure;
|
||||
mod dc_dehtml;
|
||||
mod dc_e2ee;
|
||||
|
||||
@@ -4,9 +4,9 @@ use std::fmt;
|
||||
use num_traits::FromPrimitive;
|
||||
|
||||
use crate::aheader::*;
|
||||
use crate::chat::*;
|
||||
use crate::constants::*;
|
||||
use crate::context::Context;
|
||||
use crate::dc_chat::*;
|
||||
use crate::key::*;
|
||||
use crate::sql::{self, Sql};
|
||||
|
||||
@@ -466,7 +466,7 @@ impl<'a> Peerstate<'a> {
|
||||
}
|
||||
|
||||
if self.to_save == Some(ToSave::All) || create {
|
||||
dc_reset_gossiped_timestamp(self.context, 0);
|
||||
reset_gossiped_timestamp(self.context, 0);
|
||||
}
|
||||
|
||||
success
|
||||
|
||||
@@ -6,11 +6,11 @@ use std::ffi::CString;
|
||||
use mmime::mailimf_types::*;
|
||||
use tempfile::{tempdir, TempDir};
|
||||
|
||||
use deltachat::chat::{self, Chat};
|
||||
use deltachat::config;
|
||||
use deltachat::constants::*;
|
||||
use deltachat::contact::*;
|
||||
use deltachat::context::*;
|
||||
use deltachat::dc_chat::*;
|
||||
use deltachat::dc_configure::*;
|
||||
use deltachat::dc_imex::*;
|
||||
use deltachat::dc_lot::*;
|
||||
@@ -66,15 +66,9 @@ unsafe fn stress_functions(context: &Context) {
|
||||
context.get_blobdir(),
|
||||
b"foobar\x00" as *const u8 as *const libc::c_char,
|
||||
);
|
||||
assert!(dc_is_blobdir_path(context, abs_path));
|
||||
assert!(dc_is_blobdir_path(
|
||||
context,
|
||||
b"$BLOBDIR/fofo\x00" as *const u8 as *const libc::c_char,
|
||||
));
|
||||
assert!(!dc_is_blobdir_path(
|
||||
context,
|
||||
b"/BLOBDIR/fofo\x00" as *const u8 as *const libc::c_char,
|
||||
));
|
||||
assert!(dc_is_blobdir_path(context, as_str(abs_path)));
|
||||
assert!(dc_is_blobdir_path(context, "$BLOBDIR/fofo",));
|
||||
assert!(!dc_is_blobdir_path(context, "/BLOBDIR/fofo",));
|
||||
assert!(dc_file_exist(context, as_path(abs_path)));
|
||||
free(abs_path as *mut libc::c_void);
|
||||
assert!(dc_copy_file(context, "$BLOBDIR/foobar", "$BLOBDIR/dada",));
|
||||
@@ -765,17 +759,15 @@ fn test_chat() {
|
||||
let contact1 = Contact::create(&context.ctx, "bob", "bob@mail.de").unwrap();
|
||||
assert_ne!(contact1, 0);
|
||||
|
||||
let chat_id = dc_create_chat_by_contact_id(&context.ctx, contact1);
|
||||
let chat_id = chat::create_by_contact_id(&context.ctx, contact1).unwrap();
|
||||
assert!(chat_id > 9, "chat_id too small {}", chat_id);
|
||||
let chat = dc_chat_new(&context.ctx);
|
||||
assert!(dc_chat_load_from_db(chat, chat_id));
|
||||
let chat = Chat::load_from_db(&context.ctx, chat_id).unwrap();
|
||||
|
||||
let chat2_id = dc_create_chat_by_contact_id(&context.ctx, contact1);
|
||||
let chat2_id = chat::create_by_contact_id(&context.ctx, contact1).unwrap();
|
||||
assert_eq!(chat2_id, chat_id);
|
||||
let chat2 = dc_chat_new(&context.ctx);
|
||||
assert!(dc_chat_load_from_db(chat2, chat2_id));
|
||||
let chat2 = Chat::load_from_db(&context.ctx, chat2_id).unwrap();
|
||||
|
||||
assert_eq!(as_str((*chat2).name), as_str((*chat).name));
|
||||
assert_eq!(chat2.name, chat.name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user