Compare commits

..

4 Commits

28 changed files with 690 additions and 642 deletions

View File

@@ -15,7 +15,6 @@ export BRANCH=${CIRCLE_BRANCH:?specify branch for uploading purposes}
# python docs to py.delta.chat
ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null delta@py.delta.chat mkdir -p build/${BRANCH}
rsync -avz \
-e "ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null" \
"$PYDOCDIR/html/" \
@@ -38,13 +37,11 @@ pip install devpi-client
devpi use https://m.devpi.net
devpi login dc --password $DEVPI_LOGIN
N_BRANCH=${BRANCH//[\/]}
devpi use dc/$N_BRANCH || {
devpi index -c $N_BRANCH
devpi use dc/$N_BRANCH
devpi use dc/$BRANCH || {
devpi index -c $BRANCH
devpi use dc/$BRANCH
}
devpi index $N_BRANCH bases=/root/pypi
devpi index $BRANCH bases=/root/pypi
devpi upload deltachat*.whl
popd

View File

@@ -44,14 +44,11 @@ pub unsafe extern "C" fn dc_context_new(
Box::into_raw(Box::new(ctx))
}
/// Release the context structure.
///
/// This function releases the memory of the `dc_context_t` structure.
#[no_mangle]
pub unsafe extern "C" fn dc_context_unref(context: *mut dc_context_t) {
assert!(!context.is_null());
let context = &mut *context;
context::dc_close(context);
context::dc_context_unref(context);
Box::from_raw(context);
}
@@ -864,12 +861,7 @@ pub unsafe extern "C" fn dc_get_contact_encrinfo(
assert!(!context.is_null());
let context = &*context;
Contact::get_encrinfo(context, contact_id)
.map(|s| s.strdup())
.unwrap_or_else(|e| {
error!(context, 0, "{}", e);
std::ptr::null_mut()
})
Contact::get_encrinfo(context, contact_id).strdup()
}
#[no_mangle]

View File

@@ -1091,7 +1091,7 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E
let mut res = format!("Contact info for: {}:\n\n", name_n_addr);
res += &Contact::get_encrinfo(context, contact_id)?;
res += &Contact::get_encrinfo(context, contact_id);
let chatlist = Chatlist::try_load(context, 0, None, Some(contact_id))?;
let chatlist_cnt = chatlist.len();

View File

@@ -456,6 +456,12 @@ fn main_0(args: Vec<String>) -> Result<(), failure::Error> {
println!("history saved");
{
stop_threads(&ctx.read().unwrap());
unsafe {
let mut ctx = ctx.write().unwrap();
dc_close(&mut ctx);
dc_context_unref(&mut ctx);
}
}
Ok(())

View File

@@ -120,8 +120,6 @@ def acfactory(pytestconfig, tmpdir, request):
pytest.skip("specify a --liveconfig file to run tests with real accounts")
self.live_count += 1
configdict = self.configlist.pop(0)
if "e2ee_enabled" not in configdict:
configdict["e2ee_enabled"] = "1"
tmpdb = tmpdir.join("livedb%d" % self.live_count)
ac = Account(tmpdb.strpath, logid="ac{}".format(self.live_count))
ac._evlogger.init_time = self.init_time

View File

@@ -427,37 +427,6 @@ class TestOnlineAccount:
lp.step("2")
assert msg_out.is_out_mdn_received()
def test_send_and_receive_will_encrypt_decrypt(self, acfactory, lp):
lp.sec("starting accounts, waiting for configuration")
ac1 = acfactory.get_online_configuring_account()
ac2 = acfactory.get_online_configuring_account()
c2 = ac1.create_contact(email=ac2.get_config("addr"))
chat = ac1.create_chat_by_contact(c2)
assert chat.id >= const.DC_CHAT_ID_LAST_SPECIAL
wait_configuration_progress(ac1, 1000)
wait_configuration_progress(ac2, 1000)
lp.sec("sending text message from ac1 to ac2")
msg_out = chat.send_text("message1")
lp.sec("wait for ac2 to receive message")
ev = ac2._evlogger.get_matching("DC_EVENT_MSGS_CHANGED")
assert ev[2] == msg_out.id
msg_in = ac2.get_message_by_id(msg_out.id)
assert msg_in.text == "message1"
lp.sec("create new chat with contact and send back (encrypted) message")
chat2b = ac2.create_chat_by_message(msg_in)
chat2b.send_text("message-back")
lp.sec("wait for ac1 to receive message")
ev = ac1._evlogger.get_matching("DC_EVENT_INCOMING_MSG")
assert ev[1] == chat.id
assert ev[2] > msg_out.id
msg_back = ac1.get_message_by_id(ev[2])
assert msg_back.text == "message-back"
def test_saved_mime_on_received_message(self, acfactory, lp):
lp.sec("starting accounts, waiting for configuration")
ac1 = acfactory.get_online_configuring_account()

View File

@@ -6,29 +6,10 @@ use rusqlite::types::*;
pub const DC_VERSION_STR: &'static [u8; 14] = b"1.0.0-alpha.3\x00";
#[repr(u8)]
#[derive(Debug, Display, Clone, Copy, PartialEq, Eq, FromPrimitive, ToPrimitive)]
pub enum MoveState {
Undefined = 0,
Pending = 1,
Stay = 2,
Moving = 3,
}
impl ToSql for MoveState {
fn to_sql(&self) -> sql::Result<ToSqlOutput> {
let num = *self as i64;
Ok(ToSqlOutput::Owned(Value::Integer(num)))
}
}
impl FromSql for MoveState {
fn column_result(col: ValueRef) -> FromSqlResult<Self> {
let inner = FromSql::column_result(col)?;
FromPrimitive::from_i64(inner).ok_or(FromSqlError::InvalidType)
}
}
pub const DC_MOVE_STATE_MOVING: u32 = 3;
pub const DC_MOVE_STATE_STAY: u32 = 2;
pub const DC_MOVE_STATE_PENDING: u32 = 1;
pub const DC_MOVE_STATE_UNDEFINED: u32 = 0;
pub const DC_GCL_ARCHIVED_ONLY: usize = 0x01;
pub const DC_GCL_NO_SPECIALS: usize = 0x02;
@@ -87,8 +68,6 @@ 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;
pub const DC_CHAT_MAGIC: u32 = 0xc4a7c4a7;
pub const DC_MSG_ID_MARKER1: usize = 1;
pub const DC_MSG_ID_DAYMARKER: usize = 9;
pub const DC_MSG_ID_LAST_SPECIAL: usize = 9;

View File

@@ -584,12 +584,7 @@ impl<'a> Contact<'a> {
.unwrap_or_else(|_| std::ptr::null_mut())
}
/// Returns a textual summary of the encryption state for the contact.
///
/// This function returns a string explaining the encryption state
/// of the contact and if the connection is encrypted the
/// fingerprints of the keys involved.
pub fn get_encrinfo(context: &Context, contact_id: u32) -> Result<String> {
pub fn get_encrinfo(context: &Context, contact_id: u32) -> String {
let mut ret = String::new();
if let Ok(contact) = Contact::load_from_db(context, contact_id) {
@@ -608,7 +603,7 @@ impl<'a> Contact<'a> {
});
ret += &p;
if self_key.is_none() {
dc_ensure_secret_key_exists(context)?;
unsafe { dc_ensure_secret_key_exists(context) };
self_key = Key::from_self_public(context, &loginparam.addr, &context.sql);
}
let p = context.stock_str(StockMessage::FingerPrints);
@@ -651,7 +646,7 @@ impl<'a> Contact<'a> {
}
}
Ok(ret)
ret
}
/// Delete a contact. The contact is deleted from the local device. It may happen that this is not

View File

@@ -20,6 +20,7 @@ use crate::sql::Sql;
use crate::types::*;
use crate::x::*;
#[repr(C)]
pub struct Context {
pub userdata: *mut libc::c_void,
pub dbfile: Arc<RwLock<*mut libc::c_char>>,
@@ -76,14 +77,6 @@ impl Context {
}
}
impl Drop for Context {
fn drop(&mut self) {
unsafe {
dc_close(&self);
}
}
}
impl Default for RunningState {
fn default() -> Self {
RunningState {
@@ -172,6 +165,16 @@ pub fn dc_context_new(
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn no_crashes_on_context_deref() {
let mut ctx = dc_context_new(None, std::ptr::null_mut(), Some("Test OS".into()));
unsafe { dc_context_unref(&mut ctx) };
}
}
unsafe fn cb_receive_imf(
context: &Context,
imf_raw_not_terminated: *const libc::c_char,
@@ -226,7 +229,7 @@ unsafe fn cb_precheck_imf(
"[move] detected moved message {}",
as_str(rfc724_mid),
);
dc_update_msg_move_state(context, rfc724_mid, MoveState::Stay);
dc_update_msg_move_state(context, rfc724_mid, DC_MOVE_STATE_STAY);
}
if as_str(old_server_folder) != server_folder || old_server_uid != server_uid {
dc_update_server_uid(context, rfc724_mid, server_folder, server_uid);
@@ -255,6 +258,12 @@ fn cb_get_config(context: &Context, key: &str) -> Option<String> {
context.sql.get_config(context, key)
}
pub unsafe fn dc_context_unref(context: &mut Context) {
if 0 != dc_is_open(context) {
dc_close(context);
}
}
pub unsafe fn dc_close(context: &Context) {
info!(context, 0, "disconnecting INBOX-watch",);
context.inbox.read().unwrap().disconnect(context);
@@ -306,9 +315,9 @@ pub unsafe fn dc_open(context: &Context, dbfile: &str, blobdir: Option<&str>) ->
let dir = dc_ensure_no_slash_safe(blobdir.unwrap()).strdup();
*context.blobdir.write().unwrap() = dir;
} else {
let dir = dbfile.to_string() + "-blobs";
dc_create_folder(context, &dir);
*context.blobdir.write().unwrap() = dir.strdup();
let dir = (dbfile.to_string() + "-blobs").strdup();
dc_create_folder(context, dir);
*context.blobdir.write().unwrap() = dir;
}
// Create/open sqlite database, this may already use the blobdir
let dbfile_path = std::path::Path::new(dbfile);
@@ -582,24 +591,3 @@ pub fn dc_is_mvbox(context: &Context, folder_name: impl AsRef<str>) -> bool {
false
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn no_crashes_on_context_deref() {
let ctx = dc_context_new(None, std::ptr::null_mut(), Some("Test OS".into()));
std::mem::drop(ctx);
}
#[test]
fn test_context_double_close() {
let ctx = dc_context_new(None, std::ptr::null_mut(), None);
unsafe {
dc_close(&ctx);
dc_close(&ctx);
}
std::mem::drop(ctx);
}
}

View File

@@ -437,4 +437,5 @@ mod tests {
dc_array_unref(arr);
}
}
}

View File

@@ -24,7 +24,7 @@ use crate::x::*;
*/
#[derive(Clone)]
pub struct Chat<'a> {
magic: u32,
magic: uint32_t,
pub id: uint32_t,
pub type_0: libc::c_int,
pub name: *mut libc::c_char,
@@ -65,7 +65,7 @@ pub unsafe fn dc_create_chat_by_msg_id(context: &Context, msg_id: uint32_t) -> u
pub unsafe fn dc_chat_new<'a>(context: &'a Context) -> *mut Chat<'a> {
let chat = Chat {
magic: DC_CHAT_MAGIC,
magic: 0xc4a7c4a7,
id: 0,
type_0: 0,
name: std::ptr::null_mut(),
@@ -82,7 +82,7 @@ pub unsafe fn dc_chat_new<'a>(context: &'a Context) -> *mut Chat<'a> {
}
pub unsafe fn dc_chat_unref(mut chat: *mut Chat) {
if chat.is_null() || (*chat).magic != DC_CHAT_MAGIC {
if chat.is_null() || (*chat).magic != 0xc4a7c4a7u32 {
return;
}
dc_chat_empty(chat);
@@ -91,7 +91,7 @@ pub unsafe fn dc_chat_unref(mut chat: *mut Chat) {
}
pub unsafe fn dc_chat_empty(mut chat: *mut Chat) {
if chat.is_null() || (*chat).magic != DC_CHAT_MAGIC {
if chat.is_null() || (*chat).magic != 0xc4a7c4a7u32 {
return;
}
free((*chat).name as *mut libc::c_void);
@@ -120,7 +120,7 @@ pub fn dc_block_chat(context: &Context, chat_id: u32, new_blocking: libc::c_int)
}
pub fn dc_chat_load_from_db(chat: *mut Chat, chat_id: u32) -> bool {
if chat.is_null() || unsafe { (*chat).magic != DC_CHAT_MAGIC } {
if chat.is_null() || unsafe { (*chat).magic != 0xc4a7c4a7u32 } {
return false;
}
unsafe { dc_chat_empty(chat) };
@@ -810,7 +810,7 @@ unsafe fn get_parent_mime_headers(
}
pub unsafe fn dc_chat_is_self_talk(chat: *const Chat) -> libc::c_int {
if chat.is_null() || (*chat).magic != DC_CHAT_MAGIC {
if chat.is_null() || (*chat).magic != 0xc4a7c4a7u32 {
return 0;
}
(*chat).param.exists(Param::Selftalk) as libc::c_int
@@ -2020,21 +2020,21 @@ pub unsafe fn dc_forward_msgs(
}
pub unsafe fn dc_chat_get_id(chat: *const Chat) -> uint32_t {
if chat.is_null() || (*chat).magic != DC_CHAT_MAGIC {
if chat.is_null() || (*chat).magic != 0xc4a7c4a7u32 {
return 0i32 as uint32_t;
}
(*chat).id
}
pub unsafe fn dc_chat_get_type(chat: *const Chat) -> libc::c_int {
if chat.is_null() || (*chat).magic != DC_CHAT_MAGIC {
if chat.is_null() || (*chat).magic != 0xc4a7c4a7u32 {
return 0i32;
}
(*chat).type_0
}
pub unsafe fn dc_chat_get_name(chat: *const Chat) -> *mut libc::c_char {
if chat.is_null() || (*chat).magic != DC_CHAT_MAGIC {
if chat.is_null() || (*chat).magic != 0xc4a7c4a7u32 {
return dc_strdup(b"Err\x00" as *const u8 as *const libc::c_char);
}
dc_strdup((*chat).name)
@@ -2042,7 +2042,7 @@ pub unsafe fn dc_chat_get_name(chat: *const Chat) -> *mut libc::c_char {
pub unsafe fn dc_chat_get_subtitle(chat: *const Chat) -> *mut libc::c_char {
/* returns either the address or the number of chat members */
if chat.is_null() || (*chat).magic != DC_CHAT_MAGIC {
if chat.is_null() || (*chat).magic != 0xc4a7c4a7u32 {
return dc_strdup(b"Err\x00" as *const u8 as *const libc::c_char);
}
@@ -2101,7 +2101,7 @@ pub unsafe fn dc_chat_get_profile_image(chat: *const Chat) -> *mut libc::c_char
let mut image_abs: *mut libc::c_char = 0 as *mut libc::c_char;
let mut contacts: *mut dc_array_t = 0 as *mut dc_array_t;
if !(chat.is_null() || (*chat).magic != DC_CHAT_MAGIC) {
if !(chat.is_null() || (*chat).magic != 0xc4a7c4a7u32) {
image_rel = (*chat)
.param
.get(Param::ProfileImage)
@@ -2109,7 +2109,7 @@ pub unsafe fn dc_chat_get_profile_image(chat: *const Chat) -> *mut libc::c_char
.strdup();
if !image_rel.is_null() && 0 != *image_rel.offset(0isize) as libc::c_int {
image_abs = dc_get_abs_path((*chat).context, image_rel)
} else if (*chat).type_0 == DC_CHAT_TYPE_SINGLE {
} else if (*chat).type_0 == 100i32 {
contacts = dc_get_chat_contacts((*chat).context, (*chat).id);
if !(*contacts).is_empty() {
if let Ok(contact) = Contact::get_by_id((*chat).context, (*contacts).get_id(0)) {
@@ -2131,8 +2131,8 @@ pub unsafe fn dc_chat_get_color(chat: *const Chat) -> uint32_t {
let mut color: uint32_t = 0i32 as uint32_t;
let mut contacts: *mut dc_array_t = 0 as *mut dc_array_t;
if !(chat.is_null() || (*chat).magic != DC_CHAT_MAGIC) {
if (*chat).type_0 == DC_CHAT_TYPE_SINGLE {
if !(chat.is_null() || (*chat).magic != 0xc4a7c4a7u32) {
if (*chat).type_0 == 100i32 {
contacts = dc_get_chat_contacts((*chat).context, (*chat).id);
if !(*contacts).is_empty() {
if let Ok(contact) = Contact::get_by_id((*chat).context, (*contacts).get_id(0)) {
@@ -2151,7 +2151,7 @@ pub unsafe fn dc_chat_get_color(chat: *const Chat) -> uint32_t {
// TODO should return bool /rtn
pub unsafe fn dc_chat_get_archived(chat: *const Chat) -> libc::c_int {
if chat.is_null() || (*chat).magic != DC_CHAT_MAGIC {
if chat.is_null() || (*chat).magic != 0xc4a7c4a7u32 {
return 0i32;
}
(*chat).archived
@@ -2159,7 +2159,7 @@ pub unsafe fn dc_chat_get_archived(chat: *const Chat) -> libc::c_int {
// TODO should return bool /rtn
pub unsafe fn dc_chat_is_unpromoted(chat: *const Chat) -> libc::c_int {
if chat.is_null() || (*chat).magic != DC_CHAT_MAGIC {
if chat.is_null() || (*chat).magic != 0xc4a7c4a7u32 {
return 0;
}
(*chat).param.get_int(Param::Unpromoted).unwrap_or_default() as libc::c_int
@@ -2167,7 +2167,7 @@ pub unsafe fn dc_chat_is_unpromoted(chat: *const Chat) -> libc::c_int {
// TODO should return bool /rtn
pub unsafe fn dc_chat_is_verified(chat: *const Chat) -> libc::c_int {
if chat.is_null() || (*chat).magic != DC_CHAT_MAGIC {
if chat.is_null() || (*chat).magic != 0xc4a7c4a7u32 {
return 0i32;
}
((*chat).type_0 == 130i32) as libc::c_int
@@ -2175,7 +2175,7 @@ pub unsafe fn dc_chat_is_verified(chat: *const Chat) -> libc::c_int {
// TODO should return bool /rtn
pub unsafe fn dc_chat_is_sending_locations(chat: *const Chat) -> libc::c_int {
if chat.is_null() || (*chat).magic != DC_CHAT_MAGIC {
if chat.is_null() || (*chat).magic != 0xc4a7c4a7u32 {
return 0i32;
}
(*chat).is_sending_locations

View File

@@ -101,7 +101,7 @@ pub fn dc_stop_ongoing_process(context: &Context) {
}
// the other dc_job_do_DC_JOB_*() functions are declared static in the c-file
#[allow(non_snake_case, unused_must_use)]
#[allow(non_snake_case)]
pub unsafe fn dc_job_do_DC_JOB_CONFIGURE_IMAP(context: &Context, _job: *mut dc_job_t) {
let flags: libc::c_int;
let mut current_block: u64;

View File

@@ -16,12 +16,10 @@ use mmime::mmapstring::*;
use mmime::{mailmime_substitute, MAILIMF_NO_ERROR, MAIL_NO_ERROR};
use crate::aheader::*;
use crate::config::Config;
use crate::context::Context;
use crate::dc_mimeparser::*;
use crate::dc_securejoin::*;
use crate::dc_tools::*;
use crate::error::*;
use crate::key::*;
use crate::keyring::*;
use crate::peerstate::*;
@@ -117,22 +115,11 @@ pub unsafe fn dc_e2ee_encrypt(
|| 0 != e2ee_guaranteed)
{
let peerstate = peerstate.unwrap();
info!(
context,
0, "dc_e2ee_encrypt {} has peerstate", recipient_addr
);
if let Some(key) = peerstate.peek_key(min_verified as usize) {
keyring.add_owned(key.clone());
peerstates.push(peerstate);
}
} else {
info!(
context,
0,
"dc_e2ee_encrypt {} HAS NO peerstate {}",
recipient_addr,
peerstate.is_some()
);
do_encrypt = 0i32;
/* if we cannot encrypt to a single recipient, we cannot encrypt the message at all */
break;
@@ -587,7 +574,7 @@ pub unsafe fn dc_e2ee_decrypt(
}
} else if let Some(ref header) = autocryptheader {
let p = Peerstate::from_header(context, header, message_time);
assert!(p.save_to_db(&context.sql, true));
p.save_to_db(&context.sql, true);
peerstate = Some(p);
}
}
@@ -825,7 +812,7 @@ unsafe fn decrypt_recursive(
}
unsafe fn decrypt_part(
_context: &Context,
context: &Context,
mime: *mut mailmime,
private_keyring: &Keyring,
public_keyring_for_validate: &Keyring,
@@ -1047,53 +1034,33 @@ pub unsafe fn dc_e2ee_thanks(helper: &mut dc_e2ee_helper_t) {
helper.cdata_to_free = 0 as *mut libc::c_void;
}
/// Ensures a private key exists for the configured user.
///
/// Normally the private key is generated when the first message is
/// sent (allowing the use of some extra random seed from the message
/// content) but in a few locations there are no such guarantees,
/// e.g. when exporting keys, and calling this function ensures a
/// private key will be present.
///
/// If this succeeds you are also guaranteed that the
/// [Config::ConfiguredAddr] is configured, this address is returned.
pub fn dc_ensure_secret_key_exists(context: &Context) -> Result<String> {
let self_addr = context
.get_config(Config::ConfiguredAddr)
.ok_or(format_err!(concat!(
"Failed to get self address, ",
"cannot ensure secret key if not configured."
)))?;
unsafe {
load_or_generate_self_public_key(context, &self_addr, 0 as *mut mailmime)
.ok_or(format_err!("Failed to generate private key."))?;
/* makes sure, the private key exists, needed only for exporting keys and the case no message was sent before */
// TODO should return bool /rtn
pub unsafe fn dc_ensure_secret_key_exists(context: &Context) -> libc::c_int {
/* normally, the key is generated as soon as the first mail is send
(this is to gain some extra-random-seed by the message content and the timespan between program start and message sending) */
let mut success: libc::c_int = 0i32;
let self_addr = context.sql.get_config(context, "configured_addr");
if self_addr.is_none() {
warn!(
context,
0, "Cannot ensure secret key if context is not configured.",
);
} else if load_or_generate_self_public_key(context, self_addr.unwrap(), 0 as *mut mailmime)
.is_some()
{
/*no random text data for seeding available*/
success = 1;
}
Ok(self_addr)
success
}
#[cfg(test)]
mod tests {
use super::*;
use crate::test_utils::*;
mod ensure_secret_key_exists {
use super::*;
#[test]
fn test_prexisting() {
let t = dummy_context();
let test_addr = configure_alice_keypair(&t.ctx);
assert_eq!(dc_ensure_secret_key_exists(&t.ctx).unwrap(), test_addr);
}
#[test]
fn test_not_configured() {
let t = dummy_context();
assert!(dc_ensure_secret_key_exists(&t.ctx).is_err());
}
}
#[test]
fn test_mailmime_parse() {
let plain = b"Chat-Disposition-Notification-To: holger@deltachat.de

View File

@@ -194,15 +194,20 @@ pub unsafe fn dc_initiate_key_transfer(context: &Context) -> *mut libc::c_char {
setup_code.strdup()
}
/// Renders HTML body of a setup file message.
///
/// The `passphrase` must be at least 2 characters long.
pub fn dc_render_setup_file(context: &Context, passphrase: &str) -> Result<String> {
ensure!(
passphrase.len() >= 2,
"Passphrase must be at least 2 chars long."
);
let self_addr = dc_ensure_secret_key_exists(context)?;
unsafe {
ensure!(
!(dc_ensure_secret_key_exists(context) == 0),
"No secret key available."
);
}
let self_addr = context
.get_config(Config::ConfiguredAddr)
.ok_or(format_err!("Failed to get self address."))?;
let private_key = Key::from_self_private(context, self_addr, &context.sql)
.ok_or(format_err!("Failed to get private key."))?;
let ac_headers = match context
@@ -508,7 +513,7 @@ pub unsafe fn dc_normalize_setup_code(
#[allow(non_snake_case)]
pub unsafe fn dc_job_do_DC_JOB_IMEX_IMAP(context: &Context, job: *mut dc_job_t) {
let mut ok_to_continue = true;
let mut current_block: u64;
let mut success: libc::c_int = 0;
let mut ongoing_allocated_here: libc::c_int = 0;
let what: libc::c_int;
@@ -516,8 +521,7 @@ pub unsafe fn dc_job_do_DC_JOB_IMEX_IMAP(context: &Context, job: *mut dc_job_t)
if !(0 == dc_alloc_ongoing(context)) {
ongoing_allocated_here = 1;
what = (*job).param.get_int(Param::Cmd).unwrap_or_default();
let param1_s = (*job).param.get(Param::Arg).unwrap_or_default();
let param1 = CString::yolo(param1_s);
let param1 = CString::yolo((*job).param.get(Param::Arg).unwrap_or_default());
let _param2 = CString::yolo((*job).param.get(Param::Arg2).unwrap_or_default());
if strlen(param1.as_ptr()) == 0 {
@@ -530,45 +534,185 @@ pub unsafe fn dc_job_do_DC_JOB_IMEX_IMAP(context: &Context, job: *mut dc_job_t)
} else {
if what == 1 || what == 11 {
/* before we export anything, make sure the private key exists */
if dc_ensure_secret_key_exists(context).is_err() {
if 0 == dc_ensure_secret_key_exists(context) {
error!(
context,
0,
"Import/export: Cannot create private key or private key not available.",
);
ok_to_continue = false;
current_block = 3568988166330621280;
} else {
dc_create_folder(context, &param1_s);
dc_create_folder(context, param1.as_ptr());
current_block = 4495394744059808450;
}
} else {
current_block = 4495394744059808450;
}
if ok_to_continue {
match what {
match current_block {
3568988166330621280 => {}
_ => match what {
1 => {
if 0 != export_self_keys(context, param1.as_ptr()) {
info!(context, 0, "Import/export completed.",);
success = 1
current_block = 10991094515395304355;
match current_block {
2973387206439775448 => {
if 0 == import_backup(context, param1.as_ptr()) {
current_block = 3568988166330621280;
} else {
current_block = 1118134448028020070;
}
}
11250025114629486028 => {
if 0 == import_self_keys(context, param1.as_ptr()) {
current_block = 3568988166330621280;
} else {
current_block = 1118134448028020070;
}
}
12669919903773909120 => {
if 0 == export_backup(context, param1.as_ptr()) {
current_block = 3568988166330621280;
} else {
current_block = 1118134448028020070;
}
}
_ => {
if 0 == export_self_keys(context, param1.as_ptr()) {
current_block = 3568988166330621280;
} else {
current_block = 1118134448028020070;
}
}
}
match current_block {
3568988166330621280 => {}
_ => {
info!(context, 0, "Import/export completed.",);
success = 1
}
}
}
2 => {
if 0 != import_self_keys(context, param1.as_ptr()) {
info!(context, 0, "Import/export completed.",);
success = 1
current_block = 11250025114629486028;
match current_block {
2973387206439775448 => {
if 0 == import_backup(context, param1.as_ptr()) {
current_block = 3568988166330621280;
} else {
current_block = 1118134448028020070;
}
}
11250025114629486028 => {
if 0 == import_self_keys(context, param1.as_ptr()) {
current_block = 3568988166330621280;
} else {
current_block = 1118134448028020070;
}
}
12669919903773909120 => {
if 0 == export_backup(context, param1.as_ptr()) {
current_block = 3568988166330621280;
} else {
current_block = 1118134448028020070;
}
}
_ => {
if 0 == export_self_keys(context, param1.as_ptr()) {
current_block = 3568988166330621280;
} else {
current_block = 1118134448028020070;
}
}
}
match current_block {
3568988166330621280 => {}
_ => {
info!(context, 0, "Import/export completed.",);
success = 1
}
}
}
11 => {
if 0 != export_backup(context, param1.as_ptr()) {
info!(context, 0, "Import/export completed.",);
success = 1
current_block = 12669919903773909120;
match current_block {
2973387206439775448 => {
if 0 == import_backup(context, param1.as_ptr()) {
current_block = 3568988166330621280;
} else {
current_block = 1118134448028020070;
}
}
11250025114629486028 => {
if 0 == import_self_keys(context, param1.as_ptr()) {
current_block = 3568988166330621280;
} else {
current_block = 1118134448028020070;
}
}
12669919903773909120 => {
if 0 == export_backup(context, param1.as_ptr()) {
current_block = 3568988166330621280;
} else {
current_block = 1118134448028020070;
}
}
_ => {
if 0 == export_self_keys(context, param1.as_ptr()) {
current_block = 3568988166330621280;
} else {
current_block = 1118134448028020070;
}
}
}
match current_block {
3568988166330621280 => {}
_ => {
info!(context, 0, "Import/export completed.",);
success = 1
}
}
}
12 => {
if 0 != import_backup(context, param1.as_ptr()) {
info!(context, 0, "Import/export completed.",);
success = 1
current_block = 2973387206439775448;
match current_block {
2973387206439775448 => {
if 0 == import_backup(context, param1.as_ptr()) {
current_block = 3568988166330621280;
} else {
current_block = 1118134448028020070;
}
}
11250025114629486028 => {
if 0 == import_self_keys(context, param1.as_ptr()) {
current_block = 3568988166330621280;
} else {
current_block = 1118134448028020070;
}
}
12669919903773909120 => {
if 0 == export_backup(context, param1.as_ptr()) {
current_block = 3568988166330621280;
} else {
current_block = 1118134448028020070;
}
}
_ => {
if 0 == export_self_keys(context, param1.as_ptr()) {
current_block = 3568988166330621280;
} else {
current_block = 1118134448028020070;
}
}
}
match current_block {
3568988166330621280 => {}
_ => {
info!(context, 0, "Import/export completed.",);
success = 1
}
}
}
_ => {}
}
},
}
}
}
@@ -604,8 +748,8 @@ unsafe fn import_backup(context: &Context, backup_to_import: *const libc::c_char
return 0;
}
&context.sql.close(&context);
dc_delete_file(context, as_path(context.get_dbfile()));
if dc_file_exist(context, as_path(context.get_dbfile())) {
dc_delete_file(context, context.get_dbfile());
if 0 != dc_file_exist(context, context.get_dbfile()) {
error!(
context,
0, "Cannot import backups: Cannot delete the old file.",
@@ -613,11 +757,7 @@ unsafe fn import_backup(context: &Context, backup_to_import: *const libc::c_char
return 0;
}
if !dc_copy_file(
context,
as_path(backup_to_import),
as_path(context.get_dbfile()),
) {
if 0 == dc_copy_file(context, backup_to_import, context.get_dbfile()) {
return 0;
}
/* error already logged */
@@ -744,11 +884,7 @@ unsafe fn export_backup(context: &Context, dir: *const libc::c_char) -> libc::c_
as_str(context.get_dbfile()),
as_str(dest_pathNfilename),
);
if dc_copy_file(
context,
as_path(context.get_dbfile()),
as_path(dest_pathNfilename),
) {
if !(0 == dc_copy_file(context, context.get_dbfile(), dest_pathNfilename)) {
context.sql.open(&context, as_path(context.get_dbfile()), 0);
closed = false;
/* add all files as blobs to the database copy (this does not require the source to be locked, neigher the destination as it is used only here) */
@@ -908,7 +1044,7 @@ unsafe fn export_backup(context: &Context, dir: *const libc::c_char) -> libc::c_
context.sql.open(&context, as_path(context.get_dbfile()), 0);
}
if 0 != delete_dest_file {
dc_delete_file(context, as_path(dest_pathNfilename));
dc_delete_file(context, dest_pathNfilename);
}
free(dest_pathNfilename as *mut libc::c_void);
@@ -1128,7 +1264,7 @@ unsafe fn export_key_to_asc_file(
)
}
info!(context, 0, "Exporting key {}", as_str(file_name),);
dc_delete_file(context, as_path(file_name));
dc_delete_file(context, file_name);
if !key.write_asc_to_file(file_name, context) {
error!(context, 0, "Cannot write key to {}", as_str(file_name),);
} else {
@@ -1148,15 +1284,147 @@ unsafe fn export_key_to_asc_file(
mod tests {
use super::*;
use std::ffi::CStr;
use num_traits::ToPrimitive;
use crate::config::Config;
use crate::key;
use crate::test_utils::*;
unsafe extern "C" fn logging_cb(
_ctx: &Context,
evt: Event,
_d1: uintptr_t,
d2: uintptr_t,
) -> uintptr_t {
let to_str = |x| CStr::from_ptr(x as *const libc::c_char).to_str().unwrap();
match evt {
Event::INFO => println!("I: {}", to_str(d2)),
Event::WARNING => println!("W: {}", to_str(d2)),
Event::ERROR => println!("E: {}", to_str(d2)),
_ => (),
}
0
}
/// Create Alice with a pre-generated keypair.
fn create_alice_keypair(ctx: &Context) {
ctx.set_config(Config::ConfiguredAddr, Some("alice@example.org"))
.unwrap();
// The keypair was created using:
// let (public, private) = crate::pgp::dc_pgp_create_keypair("alice@example.com")
// .unwrap();
// println!("{}", public.to_base64(64));
// println!("{}", private.to_base64(64));
let public = key::Key::from_base64(
concat!(
"xsBNBF086ewBCACmJKuoxIO6T87yi4Q3MyNpMch3Y8KrtHDQyUszU36eqM3Pmd1l",
"FrbcCd8ZWo2pq6OJSwsM/jjRGn1zo2YOaQeJRRrC+KrKGqSUtRSYQBPrPjE2YjSX",
"AMbu8jBI6VVUhHeghriBkK79PY9O/oRhIJC0p14IJe6CQ6OI2fTmTUHF9i/nJ3G4",
"Wb3/K1bU3yVfyPZjTZQPYPvvh03vxHULKurtYkX5DTEMSWsF4qzLMps+l87VuLV9",
"iQnbN7YMRLHHx2KkX5Ivi7JCefhCa54M0K3bDCCxuVWAM5wjQwNZjzR+WL+dYchw",
"oFvuF8NrlzjM9dSv+2rn+J7f99ijSXarzPC7ABEBAAHNEzxhbGljZUBleGFtcGxl",
"LmNvbT7CwIkEEAEIADMCGQEFAl086fgCGwMECwkIBwYVCAkKCwIDFgIBFiEE+iai",
"x4d0doj87Q0ek6DcNkbrcegACgkQk6DcNkbrcei3ogf/cruUmQ+th52TFHTHdkw9",
"OHUl3MrXtZ7QmHyOAFvbXE/6n5Eeh+eZoF8MWWV72m14Wbs+vTcNQkFVTdOPptkK",
"A8e4cJqwDOHsyAnvQXZ7WNje9+BMzcoipIUawHP4ORFaPDsKLZQ0b4wBbKn8ziea",
"6zjGF0/qljTdoxTtsYpv5wXYuhwbYklrLOqgSa5M7LXUe7E3g9mbg+9iX1GuB8m6",
"GkquJN814Y+xny4xhZzGOfue6SeP12jJMNSjSP7416dRq7794VGnkkW9V/7oFEUK",
"u5wO9FFbgDySOSlEjByGejSGuBmho0iJSjcPjZ7EY/j3M3orq4dpza5C82OeSvxD",
"Fc7ATQRdPOnsAQgA5oLxXRLnyugzOmNCy7dxV3JrDZscA6JNlJlDWIShT0YSs+zG",
"9JzDeQql+sYXgUSxOoIayItuXtnFn7tstwGoOnYvadm/e5/7V5fKAQRtCtdN51av",
"62n18Venlm0yNKpROPcZ6M/sc4m6uU6YRZ/a1idal8VGY0wLKlghjIBuIiBoVQ/R",
"noW+/fhmwIg08dQ5m8hQe3GEOZEeLrTWL/9awPlXK7Y+DmJOoR4qbHWEcRfbzS6q",
"4zW8vk2ztB8ngwbnqYy8zrN1DCICN1gYdlU++uVw6Bb1XfY8Cdldh1VLKpF35mAm",
"jxLZfVDcoObFH3Cv2GB7BEYxv86KC2Y6T74Q/wARAQABwsB2BBgBCAAgBQJdPOn4",
"AhsMFiEE+iaix4d0doj87Q0ek6DcNkbrcegACgkQk6DcNkbrcegLxwf/dXshJnoW",
"qEnRsf6rVb9/Mc66ti+NVQLfNd275dybh/QIJdK3NmSxdnTPIEJRVspJywJoupwX",
"FNrnHG2Ff6QPvHqI+/oNu986r9d7Z1oQibbLHKt8t6kpOfg/xGxotagJuiCQvR9m",
"MjD1DqsdB37SjDxGupZOOJSXWi6KX60IE+uM+QOBfeOZziQwuFmA5wV6RDXIeYJf",
"qrcbeXeR1d0nfNpPHQR1gBiqmxNb6KBbdXD2+EXW60axC7D2b1APmzMlammDliPw",
"sK9U1rc9nuquEBvGDOJf4K+Dzn+mDCqRpP6uAuQ7RKHyim4uyN0wwKObzPqgJCGw",
"jTglkixw+aSTXw=="
),
KeyType::Public,
)
.unwrap();
let private = key::Key::from_base64(
concat!(
"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",
"zPqgJCGwjTglkixw+aSTXw=="
),
KeyType::Private,
)
.unwrap();
let saved = key::dc_key_save_self_keypair(
&ctx,
&public,
&private,
"alice@example.org",
1,
&ctx.sql,
);
assert_eq!(saved, true, "Failed to save Alice's key");
}
#[test]
fn test_render_setup_file() {
let t = test_context(Some(logging_cb));
configure_alice_keypair(&t.ctx);
create_alice_keypair(&t.ctx); // Trick things to think we're configured.
let msg = dc_render_setup_file(&t.ctx, "hello").unwrap();
println!("{}", &msg);
// Check some substrings, indicating things got substituted.
@@ -1188,7 +1456,7 @@ mod tests {
#[test]
fn test_render_setup_file_newline_replace() {
let t = test_context(Some(ac_setup_msg_cb));
configure_alice_keypair(&t.ctx);
create_alice_keypair(&t.ctx);
let msg = dc_render_setup_file(&t.ctx, "pw").unwrap();
println!("{}", &msg);
assert!(msg.contains("<p>hello<br>there</p>"));

View File

@@ -313,8 +313,7 @@ unsafe fn dc_job_do_DC_JOB_SEND(context: &Context, job: &mut dc_job_t) {
}
match current_block {
13109137661213826276 => {
let filename_s = job.param.get(Param::File).unwrap_or_default();
filename = filename_s.strdup();
filename = job.param.get(Param::File).unwrap_or_default().strdup();
if strlen(filename) == 0 {
warn!(context, 0, "Missing file name for job {}", job.job_id,);
} else if !(0 == dc_read_file(context, filename, &mut buf, &mut buf_bytes)) {
@@ -370,7 +369,7 @@ unsafe fn dc_job_do_DC_JOB_SEND(context: &Context, job: &mut dc_job_t) {
(*&mut context.smtp.clone().lock().unwrap()).error,
);
} else {
dc_delete_file(context, filename_s);
dc_delete_file(context, filename);
if 0 != job.foreign_id {
dc_update_msg_state(
context,
@@ -448,7 +447,7 @@ unsafe fn dc_job_do_DC_JOB_MOVE_MSG(context: &Context, job: &mut dc_job_t) {
let dest_folder = context.sql.get_config(context, "configured_mvbox_folder");
if let Some(dest_folder) = dest_folder {
let server_folder = (*msg).server_folder.as_ref().unwrap();
let server_folder = as_str((*msg).server_folder);
match inbox.mv(
context,
@@ -583,7 +582,7 @@ unsafe fn dc_job_do_DC_JOB_MARKSEEN_MSG_ON_IMAP(context: &Context, job: &mut dc_
match current_block {
15240798224410183470 => {
if dc_msg_load_from_db(msg, context, job.foreign_id) {
let server_folder = (*msg).server_folder.as_ref().unwrap();
let server_folder = CStr::from_ptr((*msg).server_folder).to_str().unwrap();
match inbox.set_seen(context, server_folder, (*msg).server_uid) as libc::c_uint {
0 => {}
1 => {
@@ -599,7 +598,8 @@ unsafe fn dc_job_do_DC_JOB_MARKSEEN_MSG_ON_IMAP(context: &Context, job: &mut dc_
.get_config_int(context, "mdns_enabled")
.unwrap_or_else(|| 1)
{
let folder = (*msg).server_folder.as_ref().unwrap();
let folder =
CStr::from_ptr((*msg).server_folder).to_str().unwrap();
match inbox.set_mdnsent(context, folder, (*msg).server_uid)
as libc::c_uint
{
@@ -652,7 +652,8 @@ unsafe fn dc_job_do_DC_JOB_MARKSEEN_MSG_ON_IMAP(context: &Context, job: &mut dc_
.get_config_int(context, "mdns_enabled")
.unwrap_or_else(|| 1)
{
let folder = (*msg).server_folder.as_ref().unwrap();
let folder =
CStr::from_ptr((*msg).server_folder).to_str().unwrap();
match inbox.set_mdnsent(context, folder, (*msg).server_uid)
as libc::c_uint
@@ -897,7 +898,7 @@ unsafe fn dc_job_do_DC_JOB_DELETE_MSG_ON_IMAP(context: &Context, job: &mut dc_jo
8913536887710889399 => {}
_ => {
let mid = CStr::from_ptr((*msg).rfc724_mid).to_str().unwrap();
let server_folder = (*msg).server_folder.as_ref().unwrap();
let server_folder = CStr::from_ptr((*msg).server_folder).to_str().unwrap();
if 0 == inbox.delete_msg(context, mid, server_folder, &mut (*msg).server_uid) {
dc_job_try_again_later(job, -1i32, 0 as *const libc::c_char);
current_block = 8913536887710889399;

View File

@@ -6,6 +6,8 @@ use crate::dc_tools::*;
use crate::stock::StockMessage;
use crate::types::*;
use crate::x::*;
use std::ffi::CString;
use std::ptr;
/* * Structure behind dc_lot_t */
#[derive(Copy, Clone)]
@@ -169,15 +171,14 @@ pub unsafe fn dc_lot_fill(
}
}
let message_text = (*msg).text.as_ref().unwrap();
let msgtext_c = (*msg)
.text
.as_ref()
.map(|s| CString::yolo(String::as_str(s)));
let msgtext_ptr = msgtext_c.map_or(ptr::null(), |s| s.as_ptr());
(*lot).text2 = dc_msg_get_summarytext_by_raw(
(*msg).type_0,
message_text.strdup(),
&mut (*msg).param,
160,
context,
);
(*lot).text2 =
dc_msg_get_summarytext_by_raw((*msg).type_0, msgtext_ptr, &mut (*msg).param, 160, context);
(*lot).timestamp = dc_msg_get_timestamp(msg);
(*lot).state = (*msg).state;

View File

@@ -1311,14 +1311,16 @@ unsafe fn build_body_file(
/*******************************************************************************
* Render
******************************************************************************/
#[allow(non_snake_case)]
unsafe fn is_file_size_okay(msg: *const dc_msg_t) -> bool {
let mut file_size_okay = true;
let path = (*msg).param.get(Param::File).unwrap_or_default();
let bytes = dc_get_filebytes((*msg).context, &path);
let pathNfilename = (*msg).param.get(Param::File).unwrap_or_default().strdup();
let bytes = dc_get_filebytes((*msg).context, pathNfilename);
if bytes > (49 * 1024 * 1024 / 4 * 3) {
file_size_okay = false;
}
free(pathNfilename as *mut _);
file_size_okay
}

View File

@@ -1112,7 +1112,7 @@ unsafe fn dc_mimeparser_add_single_part_if_known(
/* must not be free()'d */
let mut decoded_data: *const libc::c_char = 0 as *const libc::c_char;
let mut decoded_data_bytes = 0;
let mut simplifier: Option<Simplify> = None;
let mut simplifier: Option<dc_simplify_t> = None;
if !(mime.is_null() || (*mime).mm_data.mm_single.is_null()) {
mime_type = mailmime_get_mime_type(mime, &mut msg_type, &mut raw_mime);
mime_data = (*mime).mm_data.mm_single;
@@ -1134,7 +1134,7 @@ unsafe fn dc_mimeparser_add_single_part_if_known(
match mime_type {
60 | 70 => {
if simplifier.is_none() {
simplifier = Some(Simplify::new());
simplifier = Some(dc_simplify_t::new());
}
/* get from `Content-Type: text/...; charset=utf-8`; must not be free()'d */
let charset = mailmime_content_charset_get((*mime).mm_content_type);
@@ -1192,7 +1192,7 @@ unsafe fn dc_mimeparser_add_single_part_if_known(
let simplified_txt = simplifier.unwrap().simplify(
decoded_data,
decoded_data_bytes as libc::c_int,
mime_type == 70i32,
if mime_type == 70i32 { 1i32 } else { 0i32 },
is_msgrmsg,
);
if !simplified_txt.is_null()
@@ -1208,7 +1208,7 @@ unsafe fn dc_mimeparser_add_single_part_if_known(
} else {
free(simplified_txt as *mut libc::c_void);
}
if simplifier.unwrap().is_forwarded {
if 0 != simplifier.unwrap().is_forwarded {
mimeparser.is_forwarded = 1i32
}
current_block = 10261677128829721533;

View File

@@ -27,13 +27,13 @@ pub unsafe fn dc_do_heuristics_moves(context: &Context, folder: &str, msg_id: u3
}
if dc_is_mvbox(context, folder) {
dc_update_msg_move_state(context, (*msg).rfc724_mid, MoveState::Stay);
dc_update_msg_move_state(context, (*msg).rfc724_mid, DC_MOVE_STATE_STAY);
}
// 1 = dc message, 2 = reply to dc message
if 0 != (*msg).is_dc_message {
dc_job_add(context, 200, (*msg).id as libc::c_int, Params::new(), 0);
dc_update_msg_move_state(context, (*msg).rfc724_mid, MoveState::Moving);
dc_update_msg_move_state(context, (*msg).rfc724_mid, DC_MOVE_STATE_MOVING);
}
dc_msg_unref(msg);

View File

@@ -25,7 +25,7 @@ pub struct dc_msg_t<'a> {
pub from_id: uint32_t,
pub to_id: uint32_t,
pub chat_id: uint32_t,
pub move_state: MoveState,
pub move_state: dc_move_state_t,
pub type_0: Viewtype,
pub state: libc::c_int,
pub hidden: libc::c_int,
@@ -36,7 +36,7 @@ pub struct dc_msg_t<'a> {
pub context: &'a Context,
pub rfc724_mid: *mut libc::c_char,
pub in_reply_to: *mut libc::c_char,
pub server_folder: Option<String>,
pub server_folder: *mut libc::c_char,
pub server_uid: uint32_t,
pub is_dc_message: libc::c_int,
pub starred: libc::c_int,
@@ -168,7 +168,7 @@ pub unsafe fn dc_get_msg_info(context: &Context, msg_id: u32) -> *mut libc::c_ch
ret += &format!(
"\nFile: {}, {}, bytes\n",
as_str(p),
dc_get_filebytes(context, as_path(p)) as libc::c_int,
dc_get_filebytes(context, p) as libc::c_int,
);
}
free(p as *mut libc::c_void);
@@ -194,12 +194,14 @@ pub unsafe fn dc_get_msg_info(context: &Context, msg_id: u32) -> *mut libc::c_ch
ret += &format!("\n{}\n", rawtxt);
}
if !(*msg).rfc724_mid.is_null() && 0 != *(*msg).rfc724_mid.offset(0) as libc::c_int {
ret += &format!("\nMessage-ID: {}", as_str((*msg).rfc724_mid));
ret += &format!("\nMessage-ID: {}", (*msg).rfc724_mid as libc::c_int);
}
if let Some(ref server_folder) = (*msg).server_folder {
if server_folder != "" {
ret += &format!("\nLast seen as: {}/{}", server_folder, (*msg).server_uid);
}
if !(*msg).server_folder.is_null() && 0 != *(*msg).server_folder.offset(0) as libc::c_int {
ret += &format!(
"\nLast seen as: {}/{}",
to_string((*msg).server_folder),
(*msg).server_uid as libc::c_int,
);
}
dc_msg_unref(msg);
@@ -227,7 +229,7 @@ pub unsafe fn dc_msg_new<'a>(context: &'a Context, viewtype: Viewtype) -> *mut d
from_id: 0,
to_id: 0,
chat_id: 0,
move_state: MoveState::Undefined,
move_state: 0,
type_0: viewtype,
state: 0,
hidden: 0,
@@ -238,7 +240,7 @@ pub unsafe fn dc_msg_new<'a>(context: &'a Context, viewtype: Viewtype) -> *mut d
context,
rfc724_mid: std::ptr::null_mut(),
in_reply_to: std::ptr::null_mut(),
server_folder: None,
server_folder: std::ptr::null_mut(),
server_uid: 0,
is_dc_message: 0,
starred: 0,
@@ -267,6 +269,8 @@ pub unsafe fn dc_msg_empty(mut msg: *mut dc_msg_t) {
(*msg).rfc724_mid = 0 as *mut libc::c_char;
free((*msg).in_reply_to as *mut libc::c_void);
(*msg).in_reply_to = 0 as *mut libc::c_char;
free((*msg).server_folder as *mut libc::c_void);
(*msg).server_folder = 0 as *mut libc::c_char;
(*msg).param = Params::new();
(*msg).hidden = 0i32;
}
@@ -456,7 +460,7 @@ pub fn dc_msg_load_from_db<'a>(msg: *mut dc_msg_t<'a>, context: &'a Context, id:
Some(s) => s.strdup(),
None => std::ptr::null_mut(),
};
(*msg).server_folder = row.get::<_, Option<String>>(3)?;
(*msg).server_folder = row.get::<_, String>(3)?.strdup();
(*msg).server_uid = row.get(4)?;
(*msg).move_state = row.get(5)?;
(*msg).chat_id = row.get(6)?;
@@ -725,13 +729,16 @@ pub unsafe fn dc_msg_get_filename(msg: *const dc_msg_t) -> *mut libc::c_char {
}
pub unsafe fn dc_msg_get_filebytes(msg: *const dc_msg_t) -> uint64_t {
let mut ret = 0;
if !(msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint) {
if let Some(file) = (*msg).param.get(Param::File) {
return dc_get_filebytes((*msg).context, &file);
let file_c = CString::yolo(file);
ret = dc_get_filebytes((*msg).context, file_c.as_ptr());
}
}
0
ret
}
pub unsafe fn dc_msg_get_width(msg: *const dc_msg_t) -> libc::c_int {
@@ -779,7 +786,7 @@ pub unsafe fn dc_msg_get_summary<'a>(
msg: *mut dc_msg_t<'a>,
mut chat: *const Chat<'a>,
) -> *mut dc_lot_t {
let mut ok_to_continue = true;
let current_block: u64;
let ret: *mut dc_lot_t = dc_lot_new();
let mut chat_to_delete: *mut Chat = 0 as *mut Chat;
@@ -787,21 +794,27 @@ pub unsafe fn dc_msg_get_summary<'a>(
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;
current_block = 15204159476013091401;
} else {
chat = chat_to_delete;
current_block = 7815301370352969686;
}
} else {
current_block = 7815301370352969686;
}
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
};
match current_block {
15204159476013091401 => {}
_ => {
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);
dc_lot_fill(ret, msg, chat, contact.as_ref(), (*msg).context);
}
}
}
@@ -1174,7 +1187,7 @@ pub unsafe fn dc_msg_exists(context: &Context, msg_id: uint32_t) -> libc::c_int
pub fn dc_update_msg_move_state(
context: &Context,
rfc724_mid: *const libc::c_char,
state: MoveState,
state: dc_move_state_t,
) -> bool {
// we update the move_state for all messages belonging to a given Message-ID
// so that the state stay intact when parts are deleted

View File

@@ -42,7 +42,7 @@ pub unsafe fn dc_get_securejoin_qr(
let mut group_name_urlencoded = 0 as *mut libc::c_char;
let mut qr: Option<String> = None;
dc_ensure_secret_key_exists(context).ok();
dc_ensure_secret_key_exists(context);
invitenumber = dc_token_lookup(context, DC_TOKEN_INVITENUMBER, group_chat_id);
if invitenumber.is_null() {
invitenumber = dc_create_id().strdup();
@@ -149,7 +149,7 @@ pub unsafe fn dc_join_securejoin(context: &Context, qr: *const libc::c_char) ->
let mut join_vg: libc::c_int = 0i32;
let mut qr_scan: *mut dc_lot_t = 0 as *mut dc_lot_t;
info!(context, 0, "Requesting secure-join ...",);
dc_ensure_secret_key_exists(context).ok();
dc_ensure_secret_key_exists(context);
ongoing_allocated = dc_alloc_ongoing(context);
if !(ongoing_allocated == 0i32) {
qr_scan = dc_check_qr(context, qr);

View File

@@ -3,18 +3,19 @@ use crate::dc_tools::*;
use crate::x::*;
#[derive(Copy, Clone)]
pub struct Simplify {
pub is_forwarded: bool,
pub is_cut_at_begin: bool,
pub is_cut_at_end: bool,
#[repr(C)]
pub struct dc_simplify_t {
pub is_forwarded: libc::c_int,
pub is_cut_at_begin: libc::c_int,
pub is_cut_at_end: libc::c_int,
}
impl Simplify {
impl dc_simplify_t {
pub fn new() -> Self {
Simplify {
is_forwarded: false,
is_cut_at_begin: false,
is_cut_at_end: false,
dc_simplify_t {
is_forwarded: 0,
is_cut_at_begin: 0,
is_cut_at_end: 0,
}
}
@@ -25,7 +26,7 @@ impl Simplify {
&mut self,
in_unterminated: *const libc::c_char,
in_bytes: libc::c_int,
is_html: bool,
is_html: libc::c_int,
is_msgrmsg: libc::c_int,
) -> *mut libc::c_char {
if in_bytes <= 0 {
@@ -35,9 +36,9 @@ impl Simplify {
/* create a copy of the given buffer */
let mut out: *mut libc::c_char;
let mut temp: *mut libc::c_char;
self.is_forwarded = false;
self.is_cut_at_begin = false;
self.is_cut_at_end = false;
self.is_forwarded = 0i32;
self.is_cut_at_begin = 0i32;
self.is_cut_at_end = 0i32;
out = strndup(
in_unterminated as *mut libc::c_char,
in_bytes as libc::c_ulong,
@@ -45,7 +46,7 @@ impl Simplify {
if out.is_null() {
return dc_strdup(b"\x00" as *const u8 as *const libc::c_char);
}
if is_html {
if 0 != is_html {
temp = dc_dehtml(out);
if !temp.is_null() {
free(out as *mut libc::c_void);
@@ -95,7 +96,7 @@ impl Simplify {
|| strcmp(line, b"----\x00" as *const u8 as *const libc::c_char) == 0i32
{
footer_mark = 1i32;
self.is_cut_at_end = true
self.is_cut_at_end = 1i32
}
if 0 != footer_mark {
l_last = l;
@@ -114,7 +115,7 @@ impl Simplify {
&& strncmp(line1, b"From: \x00" as *const u8 as *const libc::c_char, 6) == 0i32
&& *line2.offset(0isize) as libc::c_int == 0i32
{
self.is_forwarded = true;
self.is_forwarded = 1i32;
l_first += 3
}
}
@@ -127,7 +128,7 @@ impl Simplify {
|| strncmp(line, b"~~~~~\x00" as *const u8 as *const libc::c_char, 5) == 0i32
{
l_last = l;
self.is_cut_at_end = true;
self.is_cut_at_end = 1i32;
/* done */
break;
}
@@ -144,7 +145,7 @@ impl Simplify {
}
if l_lastQuotedLine.is_some() {
l_last = l_lastQuotedLine.unwrap();
self.is_cut_at_end = true;
self.is_cut_at_end = 1i32;
if l_last > 1 {
if is_empty_line(lines[l_last - 1]) {
l_last -= 1
@@ -179,12 +180,12 @@ impl Simplify {
}
if l_lastQuotedLine_0.is_some() {
l_first = l_lastQuotedLine_0.unwrap() + 1;
self.is_cut_at_begin = true
self.is_cut_at_begin = 1i32
}
}
/* re-create buffer from the remaining lines */
let mut ret = String::new();
if self.is_cut_at_begin {
if 0 != self.is_cut_at_begin {
ret += "[...]";
}
/* we write empty lines only in case and non-empty line follows */
@@ -210,7 +211,7 @@ impl Simplify {
pending_linebreaks = 1i32
}
}
if self.is_cut_at_end && (!self.is_cut_at_begin || 0 != content_lines_added) {
if 0 != self.is_cut_at_end && (0 == self.is_cut_at_begin || 0 != content_lines_added) {
ret += " [...]";
}
dc_free_splitted_lines(lines);
@@ -267,11 +268,11 @@ mod tests {
#[test]
fn test_simplify_trim() {
unsafe {
let mut simplify = Simplify::new();
let mut simplify = dc_simplify_t::new();
let html: *const libc::c_char =
b"\r\r\nline1<br>\r\n\r\n\r\rline2\n\r\x00" as *const u8 as *const libc::c_char;
let plain: *mut libc::c_char =
simplify.simplify(html, strlen(html) as libc::c_int, true, 0);
simplify.simplify(html, strlen(html) as libc::c_int, 1, 0);
assert_eq!(
CStr::from_ptr(plain as *const libc::c_char)
@@ -287,11 +288,11 @@ mod tests {
#[test]
fn test_simplify_parse_href() {
unsafe {
let mut simplify = Simplify::new();
let mut simplify = dc_simplify_t::new();
let html: *const libc::c_char =
b"<a href=url>text</a\x00" as *const u8 as *const libc::c_char;
let plain: *mut libc::c_char =
simplify.simplify(html, strlen(html) as libc::c_int, true, 0);
simplify.simplify(html, strlen(html) as libc::c_int, 1, 0);
assert_eq!(
CStr::from_ptr(plain as *const libc::c_char)
@@ -307,12 +308,12 @@ mod tests {
#[test]
fn test_simplify_bold_text() {
unsafe {
let mut simplify = Simplify::new();
let mut simplify = dc_simplify_t::new();
let html: *const libc::c_char =
b"<!DOCTYPE name [<!DOCTYPE ...>]><!-- comment -->text <b><?php echo ... ?>bold</b><![CDATA[<>]]>\x00"
as *const u8 as *const libc::c_char;
let plain: *mut libc::c_char =
simplify.simplify(html, strlen(html) as libc::c_int, true, 0);
simplify.simplify(html, strlen(html) as libc::c_int, 1, 0);
assert_eq!(
CStr::from_ptr(plain as *const libc::c_char)
@@ -328,12 +329,12 @@ mod tests {
#[test]
fn test_simplify_html_encoded() {
unsafe {
let mut simplify = Simplify::new();
let mut simplify = dc_simplify_t::new();
let html: *const libc::c_char =
b"&lt;&gt;&quot;&apos;&amp; &auml;&Auml;&ouml;&Ouml;&uuml;&Uuml;&szlig; foo&AElig;&ccedil;&Ccedil; &diams;&noent;&lrm;&rlm;&zwnj;&zwj;\x00"
as *const u8 as *const libc::c_char;
let plain: *mut libc::c_char =
simplify.simplify(html, strlen(html) as libc::c_int, true, 0);
simplify.simplify(html, strlen(html) as libc::c_int, 1, 0);
assert_eq!(
strcmp(plain,

View File

@@ -23,21 +23,8 @@ pub fn dc_exactly_one_bit_set(v: libc::c_int) -> bool {
0 != v && 0 == v & v - 1i32
}
/// Duplicates a string
///
/// returns an empty string if NULL is given, never returns NULL (exits on errors)
///
/// # Examples
///
/// ```
/// use deltachat::dc_tools::{dc_strdup, to_string};
/// unsafe {
/// let str_a = b"foobar\x00" as *const u8 as *const libc::c_char;
/// let str_a_copy = dc_strdup(str_a);
/// assert_eq!(to_string(str_a_copy), "foobar");
/// assert_ne!(str_a, str_a_copy);
/// }
/// ```
/* string tools */
/* dc_strdup() returns empty string if NULL is given, never returns NULL (exits on errors) */
pub unsafe fn dc_strdup(s: *const libc::c_char) -> *mut libc::c_char {
let ret: *mut libc::c_char;
if !s.is_null() {
@@ -51,21 +38,7 @@ pub unsafe fn dc_strdup(s: *const libc::c_char) -> *mut libc::c_char {
ret
}
/// Duplicates a string, returns null if given string is null
///
/// # Examples
///
/// ```
/// use deltachat::dc_tools::{dc_strdup_keep_null, to_string};
/// use std::ffi::{CStr};
///
/// unsafe {
/// let str_a = b"foobar\x00" as *const u8 as *const libc::c_char;
/// let str_a_copy = dc_strdup_keep_null(str_a);
/// assert_eq!(to_string(str_a_copy), "foobar");
/// assert_ne!(str_a, str_a_copy);
/// }
/// ```
/* strdup(NULL) is undefined, safe_strdup_keep_null(NULL) returns NULL in this case */
pub unsafe fn dc_strdup_keep_null(s: *const libc::c_char) -> *mut libc::c_char {
return if !s.is_null() {
dc_strdup(s)
@@ -94,14 +67,50 @@ pub unsafe fn dc_str_replace(
haystack: *mut *mut libc::c_char,
needle: *const libc::c_char,
replacement: *const libc::c_char,
) {
let haystack_s = to_string(*haystack);
let needle_s = to_string(needle);
let replacement_s = to_string(replacement);
) -> libc::c_int {
let mut replacements: libc::c_int = 0i32;
let mut start_search_pos: libc::c_int = 0i32;
let needle_len: libc::c_int;
let replacement_len: libc::c_int;
if haystack.is_null()
|| (*haystack).is_null()
|| needle.is_null()
|| *needle.offset(0isize) as libc::c_int == 0i32
{
return 0i32;
}
needle_len = strlen(needle) as libc::c_int;
replacement_len = (if !replacement.is_null() {
strlen(replacement)
} else {
0
}) as libc::c_int;
loop {
let mut p2: *mut libc::c_char =
strstr((*haystack).offset(start_search_pos as isize), needle);
if p2.is_null() {
break;
}
start_search_pos =
(p2.wrapping_offset_from(*haystack) + replacement_len as isize) as libc::c_int;
*p2 = 0i32 as libc::c_char;
p2 = p2.offset(needle_len as isize);
let new_string: *mut libc::c_char = dc_mprintf(
b"%s%s%s\x00" as *const u8 as *const libc::c_char,
*haystack,
if !replacement.is_null() {
replacement
} else {
b"\x00" as *const u8 as *const libc::c_char
},
p2,
);
free(*haystack as *mut libc::c_void);
*haystack = new_string;
replacements += 1
}
free(*haystack as *mut libc::c_void);
*haystack = haystack_s.replace(&needle_s, &replacement_s).strdup();
replacements
}
pub unsafe fn dc_ftoa(f: libc::c_double) -> *mut libc::c_char {
@@ -1077,20 +1086,21 @@ pub unsafe fn dc_get_abs_path(
pathNfilename_abs
}
pub fn dc_file_exist(context: &Context, path: impl AsRef<std::path::Path>) -> bool {
dc_get_abs_path_safe(context, &path).exists()
pub fn dc_file_exist(context: &Context, path: *const libc::c_char) -> libc::c_int {
dc_get_abs_path_safe(context, as_path(path)).exists() as libc::c_int
}
pub fn dc_get_filebytes(context: &Context, path: impl AsRef<std::path::Path>) -> uint64_t {
let path_abs = dc_get_abs_path_safe(context, &path);
pub fn dc_get_filebytes(context: &Context, path: *const libc::c_char) -> uint64_t {
let path_abs = dc_get_abs_path_safe(context, as_path(path));
match fs::metadata(&path_abs) {
Ok(meta) => meta.len() as uint64_t,
Err(_err) => 0,
}
}
pub fn dc_delete_file(context: &Context, path: impl AsRef<std::path::Path>) -> bool {
let path_abs = dc_get_abs_path_safe(context, &path);
pub fn dc_delete_file(context: &Context, path: *const libc::c_char) -> libc::c_int {
let path = as_path(path);
let path_abs = dc_get_abs_path_safe(context, path);
let res = if path_abs.is_file() {
fs::remove_file(path_abs)
} else {
@@ -1098,53 +1108,56 @@ pub fn dc_delete_file(context: &Context, path: impl AsRef<std::path::Path>) -> b
};
match res {
Ok(_) => true,
Ok(_) => 1,
Err(_err) => {
warn!(context, 0, "Cannot delete \"{}\".", path.as_ref().display());
false
warn!(context, 0, "Cannot delete \"{}\".", path.display());
0
}
}
}
pub fn dc_copy_file(
context: &Context,
src: impl AsRef<std::path::Path>,
dest: impl AsRef<std::path::Path>,
) -> bool {
let src_abs = dc_get_abs_path_safe(context, &src);
let dest_abs = dc_get_abs_path_safe(context, &dest);
src: *const libc::c_char,
dest: *const libc::c_char,
) -> libc::c_int {
let src = as_path(src);
let dest = as_path(dest);
let src_abs = dc_get_abs_path_safe(context, src);
let dest_abs = dc_get_abs_path_safe(context, dest);
match fs::copy(&src_abs, &dest_abs) {
Ok(_) => true,
Ok(_) => 1,
Err(_) => {
error!(
context,
0,
"Cannot copy \"{}\" to \"{}\".",
src.as_ref().display(),
dest.as_ref().display(),
src.display(),
dest.display(),
);
false
0
}
}
}
pub fn dc_create_folder(context: &Context, path: impl AsRef<std::path::Path>) -> bool {
let path_abs = dc_get_abs_path_safe(context, &path);
pub fn dc_create_folder(context: &Context, path: *const libc::c_char) -> libc::c_int {
let path = as_path(path);
let path_abs = dc_get_abs_path_safe(context, path);
if !path_abs.exists() {
match fs::create_dir_all(path_abs) {
Ok(_) => true,
Ok(_) => 1,
Err(_err) => {
warn!(
context,
0,
"Cannot create directory \"{}\".",
path.as_ref().display(),
path.display(),
);
false
0
}
}
} else {
true
1
}
}
@@ -1253,7 +1266,7 @@ pub unsafe fn dc_get_fine_pathNfilename(
dotNSuffix,
)
}
if !dc_file_exist(context, as_path(ret)) {
if 0 == dc_file_exist(context, ret) {
/* fine filename found */
break;
} else {
@@ -1307,7 +1320,7 @@ pub unsafe fn dc_make_rel_and_copy(context: &Context, path: *mut *mut libc::c_ch
);
blobdir_path.is_null()
}
|| !dc_copy_file(context, as_path(*path), as_path(blobdir_path)))
|| 0 == dc_copy_file(context, *path, blobdir_path))
{
free(*path as *mut libc::c_void);
*path = blobdir_path;
@@ -1449,9 +1462,9 @@ pub trait StrExt {
///
/// This allocates a new raw C string which must be freed using
/// `free`. It takes care of some common pitfalls with using
/// [CString.as_ptr].
/// [CString::as_ptr].
///
/// [CString.as_ptr]: std::ffi::CString.as_ptr
/// [CString::as_ptr]: std::ffi::CString::as_ptr
///
/// # Panics
///
@@ -1560,49 +1573,6 @@ mod tests {
use super::*;
use std::ffi::CStr;
#[test]
fn test_dc_strdup() {
unsafe {
let str_a = b"foobar\x00" as *const u8 as *const libc::c_char;
let str_a_copy = dc_strdup(str_a);
// Value of str_a_copy should equal foobar
assert_eq!(
CStr::from_ptr(str_a_copy),
CString::new("foobar").unwrap().as_c_str()
);
// Address of str_a should be different from str_a_copy
assert_ne!(str_a, str_a_copy);
let str_a = std::ptr::null() as *const libc::c_char;
let str_a_copy = dc_strdup(str_a);
// Value of str_a_copy should equal ""
assert_eq!(
CStr::from_ptr(str_a_copy),
CString::new("").unwrap().as_c_str()
);
assert_ne!(str_a, str_a_copy);
}
}
#[test]
fn test_dc_strdup_keep_null() {
unsafe {
let str_a = b"foobar\x00" as *const u8 as *const libc::c_char;
let str_a_copy = dc_strdup_keep_null(str_a);
assert_eq!(
CStr::from_ptr(str_a_copy),
CString::new("foobar").unwrap().as_c_str()
);
assert_ne!(str_a, str_a_copy);
let str_a = 0 as *const u8 as *const libc::c_char;
let str_a_copy = dc_strdup_keep_null(str_a);
assert_eq!(str_a.is_null(), true);
assert_eq!(str_a_copy.is_null(), true);
}
}
#[test]
fn test_dc_ltrim() {
unsafe {
@@ -1677,7 +1647,7 @@ mod tests {
fn test_dc_str_replace() {
unsafe {
let mut str: *mut libc::c_char = strdup(b"aaa\x00" as *const u8 as *const libc::c_char);
dc_str_replace(
let replacements: libc::c_int = dc_str_replace(
&mut str,
b"a\x00" as *const u8 as *const libc::c_char,
b"ab\x00" as *const u8 as *const libc::c_char,
@@ -1686,6 +1656,7 @@ mod tests {
CStr::from_ptr(str as *const libc::c_char).to_str().unwrap(),
"ababab"
);
assert_eq!(replacements, 3);
free(str as *mut libc::c_void);
}
}
@@ -2114,4 +2085,5 @@ mod tests {
let grpid = dc_extract_grpid_from_rfc724_mid(mid);
assert_eq!(grpid, Some("1234567890123456"));
}
}

View File

@@ -166,6 +166,7 @@ impl<'a> Peerstate<'a> {
pub fn from_addr(context: &'a Context, _sql: &Sql, addr: &str) -> Option<Self> {
let query = "SELECT addr, last_seen, last_seen_autocrypt, prefer_encrypted, public_key, gossip_timestamp, gossip_key, public_key_fingerprint, gossip_key_fingerprint, verified_key, verified_key_fingerprint FROM acpeerstates WHERE addr=? COLLATE NOCASE;";
Self::from_stmt(context, query, &[addr])
}
@@ -190,11 +191,6 @@ impl<'a> Peerstate<'a> {
context
.sql
.query_row(query, params, |row| {
/* all the above queries start with this: SELECT
addr, last_seen, last_seen_autocrypt, prefer_encrypted,
public_key, gossip_timestamp, gossip_key, public_key_fingerprint,
gossip_key_fingerprint, verified_key, verified_key_fingerprint
*/
let mut res = Self::new(context);
res.addr = Some(row.get(0)?);
@@ -202,34 +198,13 @@ impl<'a> Peerstate<'a> {
res.last_seen_autocrypt = row.get(2)?;
res.prefer_encrypt = EncryptPreference::from_i32(row.get(3)?).unwrap_or_default();
res.gossip_timestamp = row.get(5)?;
let pkf: String = row.get(7)?;
res.public_key_fingerprint = if pkf.is_empty() { None } else { Some(pkf) };
let gkf: String = row.get(8)?;
res.gossip_key_fingerprint = if gkf.is_empty() { None } else { Some(gkf) };
let vkf: String = row.get(10)?;
res.verified_key_fingerprint = if vkf.is_empty() { None } else { Some(vkf) };
res.public_key_fingerprint = row.get(7)?;
if res
.public_key_fingerprint
.as_ref()
.map(|s| s.is_empty())
.unwrap_or_default()
{
res.public_key_fingerprint = None;
}
res.gossip_key_fingerprint = row.get(8)?;
if res
.gossip_key_fingerprint
.as_ref()
.map(|s| s.is_empty())
.unwrap_or_default()
{
res.gossip_key_fingerprint = None;
}
res.verified_key_fingerprint = row.get(10)?;
if res
.verified_key_fingerprint
.as_ref()
.map(|s| s.is_empty())
.unwrap_or_default()
{
res.verified_key_fingerprint = None;
}
res.public_key = row
.get(4)
.ok()
@@ -242,8 +217,7 @@ impl<'a> Peerstate<'a> {
.get(9)
.ok()
.and_then(|blob: Vec<u8>| Key::from_slice(&blob, KeyType::Public));
res.verified_key = if vk == res.gossip_key && res.gossip_key.is_some() {
res.verified_key = if vk == res.gossip_key {
VerifiedKey::Gossip
} else if vk == res.public_key {
VerifiedKey::Public
@@ -448,7 +422,6 @@ impl<'a> Peerstate<'a> {
&self.addr,
],
).is_ok();
assert_eq!(success, true);
} else if self.to_save == Some(ToSave::Timestamps) {
success = sql::execute(
self.context,
@@ -525,40 +498,6 @@ mod tests {
assert_eq!(peerstate, peerstate_new);
}
#[test]
fn test_peerstate_with_empty_gossip_key_save_to_db() {
let ctx = crate::test_utils::dummy_context();
let addr = "hello@mail.com";
let pub_key = crate::key::Key::from_base64("xsBNBFztUVkBCADYaQl/UOUpRPd32nLRzx8eU0eI+jQEnG+g5anjYA+3oct1rROGl5SygjMULDKdaUy27O3o9Srsti0YjA7uxZnavIqhSopJhFidqY1M1wA9JZa/duucZdNwUGbjGIRsS/4Cjr5+3svscK24hVYub1dvDWXpwUTnj3K6xOEnJdoM+MhCqtSD5+zcJhFc9vyZm9ZTGWUxAhKh0iJTcCD8V6CQ3XZ2z9GruwzZT/FTFovWrz7m3TUI2OdSSHh0eZLRGEoxMCT/vzflAFGAr8ijCaRsEIfqP6FW8uQWnFTqkjxEUCZG6XkeFHB84aj5jqYG/1KCLjL5vEKwfl1tz/WnPhY7ABEBAAHNEDxoZWxsb0BtYWlsLmNvbT7CwIkEEAEIADMCGQEFAlztUVoCGwMECwkIBwYVCAkKCwIDFgIBFiEEgMjHGVbvLXe6ioRROg8oKCvye7gACgkQOg8oKCvye7ijAwf+PTsuawUax9cNPn1bN90H+g9qyHZJMEwKXtUnNaXJxPW3iB7ThhpCiCzsZwP7+l7ArS8tmLeNDw2bENtcf1XCv4wovP2fdXOP3QOUUFX/GdakcTwv7DzC7CO0grB1HtaPhGw/6UX2o2cx2i9xiUf4Givq2MfCbgAW5zloH6WXGPb6yLQYJXxqDIphr4+uZDb+bMAyWHN/DUkAjHrV8nnVki7PMHqzzZpwglalxMX8RGeiGZE39ALJKL/Og87DMFah87/yoxQWGoS7Wqv0XDcCPKoTCPrpk8pOe2KEsq/lz215nefHd4aRpfUX5YCYa8HPvvfPQbGF73uvyQw5w7qjis7ATQRc7VFZAQgAt8ONdnX6KEEQ5Jw6ilJ+LBtY44SP5t0I3eK+goKepgIiKhjGDa+Mntyi4jdhH+HO6kvK5SHMh2sPp4rRO/WKHJwWFySyM1OdyiywhyH0J9R5rBY4vPHsJjf6vSKJdWLWT+ho1fNet2IIC+jVCYli91MAMbRvk6EKVj1nCc+67giOahXEkHt6xxkeCGlOvbw8hxGj1A8+AC1BLms/OR3oc4JMi9O3kq6uG0z9tlUEerac9HVwcjoO1XLe+hJhoT5H+TbnGjPuhuURP3pFiIKHpbRYgUfdSAY0dTObO7t4I5y/drPOrCTnWrBUg2wXAECUhpRKow9/ai2YemLv9KqhhwARAQABwsB2BBgBCAAgBQJc7VFaAhsMFiEEgMjHGVbvLXe6ioRROg8oKCvye7gACgkQOg8oKCvye7jmyggAhs4QzCzIbT2OsAReBxkxtm0AI+g1HZ1KFKof5NDHfgv9C/Qu1I8mKEjlZzA4qFyPmLqntgwJ0RuFy6gLbljZBNCFO7vB478AhYtnWjuKZmA40HUPwcB1hEJ31c42akzfUbioY1TLLepngdsJg7Cm8O+rhI9+1WRA66haJDgFs793SVUDyJh8f9NX50l5zR87/bsV30CFSw0q4OSSy9VI/z+2g5khn1LnuuOrCfFnYIPYtJED1BfkXkosxGlgbzy79VvGmI9d23x4atDK7oBPCzIj+lP8sytJ0u3HOguXi9OgDitKy+Pt1r8gH8frdktMJr5Ts6DW+tIn2vR23KR8aA==", KeyType::Public).unwrap();
let mut peerstate = Peerstate {
context: &ctx.ctx,
addr: Some(addr.into()),
last_seen: 10,
last_seen_autocrypt: 11,
prefer_encrypt: EncryptPreference::Mutual,
public_key: Some(pub_key.clone()),
public_key_fingerprint: Some(pub_key.fingerprint()),
gossip_key: None,
gossip_timestamp: 12,
gossip_key_fingerprint: None,
verified_key: VerifiedKey::None,
verified_key_fingerprint: None,
to_save: Some(ToSave::All),
degrade_event: None,
};
assert!(peerstate.save_to_db(&ctx.ctx.sql, true), "failed to save");
let peerstate_new = Peerstate::from_addr(&ctx.ctx, &ctx.ctx.sql, addr.into())
.expect("failed to load peerstate from db");
// clear to_save, as that is not persissted
peerstate.to_save = None;
assert_eq!(peerstate, peerstate_new);
}
// TODO: don't copy this from stress.rs
#[allow(dead_code)]
struct TestContext {

View File

@@ -4,6 +4,7 @@ use std::sync::{Arc, RwLock};
use rusqlite::{Connection, OpenFlags, Statement, NO_PARAMS};
use thread_local_object::ThreadLocal;
use crate::constants::*;
use crate::context::Context;
use crate::dc_tools::*;
use crate::error::{Error, Result};
@@ -688,6 +689,10 @@ fn open(
"ALTER TABLE msgs ADD COLUMN move_state INTEGER DEFAULT 1;",
params![],
)?;
assert_eq!(DC_MOVE_STATE_UNDEFINED as libc::c_int, 0);
assert_eq!(DC_MOVE_STATE_PENDING as libc::c_int, 1);
assert_eq!(DC_MOVE_STATE_STAY as libc::c_int, 2);
assert_eq!(DC_MOVE_STATE_MOVING as libc::c_int, 3);
dbversion = 48;
sql.set_config_int(context, "dbversion", 48)?;
@@ -1042,8 +1047,8 @@ pub fn housekeeping(context: &Context) {
unreferenced_count,
entry.file_name()
);
let path = entry.path();
dc_delete_file(context, path);
let path = entry.path().to_c_string().unwrap();
dc_delete_file(context, path.as_ptr());
}
}
Err(err) => {

View File

@@ -2,15 +2,9 @@
//!
//! This module is only compiled for test runs.
use std::ffi::CStr;
use libc::uintptr_t;
use tempfile::{tempdir, TempDir};
use crate::config::Config;
use crate::constants::{Event, KeyType};
use crate::context::{dc_context_new, dc_open, Context};
use crate::key;
use crate::types::dc_callback_t;
/// A Context and temporary directory.
@@ -50,127 +44,3 @@ pub fn test_context(cb: Option<dc_callback_t>) -> TestContext {
pub fn dummy_context() -> TestContext {
test_context(None)
}
pub unsafe extern "C" fn logging_cb(
_ctx: &Context,
evt: Event,
_d1: uintptr_t,
d2: uintptr_t,
) -> uintptr_t {
let to_str = |x| CStr::from_ptr(x as *const libc::c_char).to_str().unwrap();
match evt {
Event::INFO => println!("I: {}", to_str(d2)),
Event::WARNING => println!("W: {}", to_str(d2)),
Event::ERROR => println!("E: {}", to_str(d2)),
_ => (),
}
0
}
/// Creates Alice with a pre-generated keypair.
///
/// Returns the address of the keypair created (alice@example.org).
pub fn configure_alice_keypair(ctx: &Context) -> String {
let addr = String::from("alice@example.org");
ctx.set_config(Config::ConfiguredAddr, Some(&addr)).unwrap();
// The keypair was created using:
// let (public, private) = crate::pgp::dc_pgp_create_keypair("alice@example.com")
// .unwrap();
// println!("{}", public.to_base64(64));
// println!("{}", private.to_base64(64));
let public = key::Key::from_base64(
concat!(
"xsBNBF086ewBCACmJKuoxIO6T87yi4Q3MyNpMch3Y8KrtHDQyUszU36eqM3Pmd1l",
"FrbcCd8ZWo2pq6OJSwsM/jjRGn1zo2YOaQeJRRrC+KrKGqSUtRSYQBPrPjE2YjSX",
"AMbu8jBI6VVUhHeghriBkK79PY9O/oRhIJC0p14IJe6CQ6OI2fTmTUHF9i/nJ3G4",
"Wb3/K1bU3yVfyPZjTZQPYPvvh03vxHULKurtYkX5DTEMSWsF4qzLMps+l87VuLV9",
"iQnbN7YMRLHHx2KkX5Ivi7JCefhCa54M0K3bDCCxuVWAM5wjQwNZjzR+WL+dYchw",
"oFvuF8NrlzjM9dSv+2rn+J7f99ijSXarzPC7ABEBAAHNEzxhbGljZUBleGFtcGxl",
"LmNvbT7CwIkEEAEIADMCGQEFAl086fgCGwMECwkIBwYVCAkKCwIDFgIBFiEE+iai",
"x4d0doj87Q0ek6DcNkbrcegACgkQk6DcNkbrcei3ogf/cruUmQ+th52TFHTHdkw9",
"OHUl3MrXtZ7QmHyOAFvbXE/6n5Eeh+eZoF8MWWV72m14Wbs+vTcNQkFVTdOPptkK",
"A8e4cJqwDOHsyAnvQXZ7WNje9+BMzcoipIUawHP4ORFaPDsKLZQ0b4wBbKn8ziea",
"6zjGF0/qljTdoxTtsYpv5wXYuhwbYklrLOqgSa5M7LXUe7E3g9mbg+9iX1GuB8m6",
"GkquJN814Y+xny4xhZzGOfue6SeP12jJMNSjSP7416dRq7794VGnkkW9V/7oFEUK",
"u5wO9FFbgDySOSlEjByGejSGuBmho0iJSjcPjZ7EY/j3M3orq4dpza5C82OeSvxD",
"Fc7ATQRdPOnsAQgA5oLxXRLnyugzOmNCy7dxV3JrDZscA6JNlJlDWIShT0YSs+zG",
"9JzDeQql+sYXgUSxOoIayItuXtnFn7tstwGoOnYvadm/e5/7V5fKAQRtCtdN51av",
"62n18Venlm0yNKpROPcZ6M/sc4m6uU6YRZ/a1idal8VGY0wLKlghjIBuIiBoVQ/R",
"noW+/fhmwIg08dQ5m8hQe3GEOZEeLrTWL/9awPlXK7Y+DmJOoR4qbHWEcRfbzS6q",
"4zW8vk2ztB8ngwbnqYy8zrN1DCICN1gYdlU++uVw6Bb1XfY8Cdldh1VLKpF35mAm",
"jxLZfVDcoObFH3Cv2GB7BEYxv86KC2Y6T74Q/wARAQABwsB2BBgBCAAgBQJdPOn4",
"AhsMFiEE+iaix4d0doj87Q0ek6DcNkbrcegACgkQk6DcNkbrcegLxwf/dXshJnoW",
"qEnRsf6rVb9/Mc66ti+NVQLfNd275dybh/QIJdK3NmSxdnTPIEJRVspJywJoupwX",
"FNrnHG2Ff6QPvHqI+/oNu986r9d7Z1oQibbLHKt8t6kpOfg/xGxotagJuiCQvR9m",
"MjD1DqsdB37SjDxGupZOOJSXWi6KX60IE+uM+QOBfeOZziQwuFmA5wV6RDXIeYJf",
"qrcbeXeR1d0nfNpPHQR1gBiqmxNb6KBbdXD2+EXW60axC7D2b1APmzMlammDliPw",
"sK9U1rc9nuquEBvGDOJf4K+Dzn+mDCqRpP6uAuQ7RKHyim4uyN0wwKObzPqgJCGw",
"jTglkixw+aSTXw=="
),
KeyType::Public,
)
.unwrap();
let private = key::Key::from_base64(
concat!(
"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",
"zPqgJCGwjTglkixw+aSTXw=="
),
KeyType::Private,
)
.unwrap();
let saved = key::dc_key_save_self_keypair(&ctx, &public, &private, &addr, 1, &ctx.sql);
assert_eq!(saved, true, "Failed to save Alice's key");
addr
}

View File

@@ -16,6 +16,8 @@ pub use rusqlite::ffi::*;
pub type dc_callback_t =
unsafe extern "C" fn(_: &Context, _: Event, _: uintptr_t, _: uintptr_t) -> uintptr_t;
pub type dc_move_state_t = u32;
pub type dc_receive_imf_t = unsafe fn(
_: &Context,
_: *const libc::c_char,

View File

@@ -57,15 +57,39 @@ unsafe fn stress_functions(context: &Context) {
);
if 0 != dc_is_open(context) {
if dc_file_exist(context, "$BLOBDIR/foobar")
|| dc_file_exist(context, "$BLOBDIR/dada")
|| dc_file_exist(context, "$BLOBDIR/foobar.dadada")
|| dc_file_exist(context, "$BLOBDIR/foobar-folder")
if 0 != dc_file_exist(
context,
b"$BLOBDIR/foobar\x00" as *const u8 as *const libc::c_char,
) || 0
!= dc_file_exist(
context,
b"$BLOBDIR/dada\x00" as *const u8 as *const libc::c_char,
)
|| 0 != dc_file_exist(
context,
b"$BLOBDIR/foobar.dadada\x00" as *const u8 as *const libc::c_char,
)
|| 0 != dc_file_exist(
context,
b"$BLOBDIR/foobar-folder\x00" as *const u8 as *const libc::c_char,
)
{
dc_delete_file(context, "$BLOBDIR/foobar");
dc_delete_file(context, "$BLOBDIR/dada");
dc_delete_file(context, "$BLOBDIR/foobar.dadada");
dc_delete_file(context, "$BLOBDIR/foobar-folder");
dc_delete_file(
context,
b"$BLOBDIR/foobar\x00" as *const u8 as *const libc::c_char,
);
dc_delete_file(
context,
b"$BLOBDIR/dada\x00" as *const u8 as *const libc::c_char,
);
dc_delete_file(
context,
b"$BLOBDIR/foobar.dadada\x00" as *const u8 as *const libc::c_char,
);
dc_delete_file(
context,
b"$BLOBDIR/foobar-folder\x00" as *const u8 as *const libc::c_char,
);
}
dc_write_file(
context,
@@ -73,10 +97,25 @@ unsafe fn stress_functions(context: &Context) {
b"content\x00" as *const u8 as *const libc::c_char as *const libc::c_void,
7i32 as size_t,
);
assert!(dc_file_exist(context, "$BLOBDIR/foobar",));
assert!(!dc_file_exist(context, "$BLOBDIR/foobarx"));
assert_ne!(
0,
dc_file_exist(
context,
b"$BLOBDIR/foobar\x00" as *const u8 as *const libc::c_char,
)
);
assert_eq!(
dc_get_filebytes(context, "$BLOBDIR/foobar",),
0,
dc_file_exist(
context,
b"$BLOBDIR/foobarx\x00" as *const u8 as *const libc::c_char,
)
);
assert_eq!(
dc_get_filebytes(
context,
b"$BLOBDIR/foobar\x00" as *const u8 as *const libc::c_char,
),
7i32 as libc::c_ulonglong
);
@@ -94,10 +133,23 @@ unsafe fn stress_functions(context: &Context) {
context,
b"/BLOBDIR/fofo\x00" as *const u8 as *const libc::c_char,
));
assert!(dc_file_exist(context, as_path(abs_path)));
assert_ne!(0, dc_file_exist(context, abs_path));
free(abs_path as *mut libc::c_void);
assert!(dc_copy_file(context, "$BLOBDIR/foobar", "$BLOBDIR/dada",));
assert_eq!(dc_get_filebytes(context, "$BLOBDIR/dada",), 7);
assert_ne!(
0,
dc_copy_file(
context,
b"$BLOBDIR/foobar\x00" as *const u8 as *const libc::c_char,
b"$BLOBDIR/dada\x00" as *const u8 as *const libc::c_char,
)
);
assert_eq!(
dc_get_filebytes(
context,
b"$BLOBDIR/dada\x00" as *const u8 as *const libc::c_char,
),
7
);
let mut buf: *mut libc::c_void = 0 as *mut libc::c_void;
let mut buf_bytes: size_t = 0;
@@ -118,11 +170,41 @@ unsafe fn stress_functions(context: &Context) {
);
free(buf as *mut _);
assert!(dc_delete_file(context, "$BLOBDIR/foobar"));
assert!(dc_delete_file(context, "$BLOBDIR/dada"));
assert!(dc_create_folder(context, "$BLOBDIR/foobar-folder"));
assert!(dc_file_exist(context, "$BLOBDIR/foobar-folder",));
assert!(dc_delete_file(context, "$BLOBDIR/foobar-folder"));
assert_ne!(
0,
dc_delete_file(
context,
b"$BLOBDIR/foobar\x00" as *const u8 as *const libc::c_char,
)
);
assert_ne!(
0,
dc_delete_file(
context,
b"$BLOBDIR/dada\x00" as *const u8 as *const libc::c_char,
)
);
assert_ne!(
0,
dc_create_folder(
context,
b"$BLOBDIR/foobar-folder\x00" as *const u8 as *const libc::c_char,
)
);
assert_ne!(
0,
dc_file_exist(
context,
b"$BLOBDIR/foobar-folder\x00" as *const u8 as *const libc::c_char,
)
);
assert_ne!(
0,
dc_delete_file(
context,
b"$BLOBDIR/foobar-folder\x00" as *const u8 as *const libc::c_char,
)
);
let fn0: *mut libc::c_char = dc_get_fine_pathNfilename(
context,
b"$BLOBDIR\x00" as *const u8 as *const libc::c_char,
@@ -155,7 +237,7 @@ unsafe fn stress_functions(context: &Context) {
),
0
);
assert!(dc_delete_file(context, as_path(fn0)));
assert_ne!(0, dc_delete_file(context, fn0));
free(fn0 as *mut libc::c_void);
free(fn1 as *mut libc::c_void);
}