feat: update latest deltachat-core 0.43.0

This commit is contained in:
dignifiedquire
2019-04-27 17:35:49 +03:00
parent 294bd05f1f
commit 4cf5903d60
12 changed files with 496 additions and 73 deletions

View File

@@ -1,3 +1,3 @@
# Delta Chat Rust # Delta Chat Rust
Current commit on deltachat/deltachate-core: `b9fcace18ebb6db2937fee1e7f5bd5b583829a33`. Current commit on deltachat/deltachate-core: `12ef73c8e76185f9b78e844ea673025f56a959ab`.

View File

@@ -1,6 +1,6 @@
//! Constants //! Constants
pub const VERSION: &'static [u8; 7] = b"0.42.0\x00"; pub const VERSION: &'static [u8; 7] = b"0.43.0\x00";
pub const DC_GCL_ARCHIVED_ONLY: usize = 0x01; pub const DC_GCL_ARCHIVED_ONLY: usize = 0x01;
pub const DC_GCL_NO_SPECIALS: usize = 0x02; pub const DC_GCL_NO_SPECIALS: usize = 0x02;

View File

@@ -1,7 +1,7 @@
use c2rust_bitfields::BitfieldStruct; use c2rust_bitfields::BitfieldStruct;
use libc; use libc;
use crate::dc_context::dc_context_t; use crate::dc_context::*;
use crate::dc_lot::dc_lot_t; use crate::dc_lot::dc_lot_t;
use crate::dc_sqlite3::*; use crate::dc_sqlite3::*;
use crate::dc_tools::*; use crate::dc_tools::*;
@@ -20,21 +20,6 @@ pub struct dc_array_t {
pub array: *mut uintptr_t, pub array: *mut uintptr_t,
} }
// location handling
#[derive(Copy, Clone)]
#[repr(C)]
pub struct _dc_location {
pub location_id: uint32_t,
pub latitude: libc::c_double,
pub longitude: libc::c_double,
pub accuracy: libc::c_double,
pub timestamp: time_t,
pub contact_id: uint32_t,
pub msg_id: uint32_t,
pub chat_id: uint32_t,
pub marker: *mut libc::c_char,
}
/* * /* *
* @class dc_array_t * @class dc_array_t
* *
@@ -232,6 +217,30 @@ pub unsafe fn dc_array_get_marker(
(*(*(*array).array.offset(index as isize) as *mut _dc_location)).marker, (*(*(*array).array.offset(index as isize) as *mut _dc_location)).marker,
); );
} }
/**
* Return the independent-state of the location at the given index.
* Independent locations do not belong to the track of the user.
*
* @memberof dc_array_t
* @param array The array object.
* @param index Index of the item. Must be between 0 and dc_array_get_cnt()-1.
* @return 0=Location belongs to the track of the user,
* 1=Location was reported independently.
*/
pub unsafe fn dc_array_is_independent(array: *const dc_array_t, index: size_t) -> libc::c_int {
if array.is_null()
|| (*array).magic != 0xa11aai32 as libc::c_uint
|| index >= (*array).count
|| (*array).type_0 != 1i32
|| *(*array).array.offset(index as isize) == 0i32 as libc::c_ulong
{
return 0;
}
(*(*(*array).array.offset(index as isize) as *mut _dc_location)).independent as libc::c_int
}
pub unsafe fn dc_array_search_id( pub unsafe fn dc_array_search_id(
mut array: *const dc_array_t, mut array: *const dc_array_t,
mut needle: uint32_t, mut needle: uint32_t,

View File

@@ -1,7 +1,7 @@
use c2rust_bitfields::BitfieldStruct; use c2rust_bitfields::BitfieldStruct;
use libc; use libc;
use crate::constants::Event; use crate::constants::*;
use crate::dc_array::*; use crate::dc_array::*;
use crate::dc_chatlist::*; use crate::dc_chatlist::*;
use crate::dc_contact::*; use crate::dc_contact::*;
@@ -572,6 +572,8 @@ unsafe fn prepare_msg_raw(
let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt;
let mut msg_id: uint32_t = 0i32 as uint32_t; let mut msg_id: uint32_t = 0i32 as uint32_t;
let mut to_id: uint32_t = 0i32 as uint32_t; let mut to_id: uint32_t = 0i32 as uint32_t;
let mut location_id: uint32_t = 0i32 as uint32_t;
if !((*chat).type_0 == 100i32 || (*chat).type_0 == 120i32 || (*chat).type_0 == 130i32) { if !((*chat).type_0 == 100i32 || (*chat).type_0 == 120i32 || (*chat).type_0 == 130i32) {
dc_log_error( dc_log_error(
context, context,
@@ -759,9 +761,57 @@ unsafe fn prepare_msg_raw(
new_references = dc_strdup(parent_in_reply_to) new_references = dc_strdup(parent_in_reply_to)
} }
} }
// add independent location to database
if 0 != dc_param_exists((*msg).param, DC_PARAM_SET_LATITUDE as libc::c_int) {
stmt = dc_sqlite3_prepare(
(*context).sql,
b"INSERT INTO locations \
(timestamp,from_id,chat_id, latitude,longitude,independent)\
VALUES (?,?,?, ?,?,1);\x00" as *const u8
as *const libc::c_char,
);
sqlite3_bind_int64(stmt, 1, timestamp);
sqlite3_bind_int(stmt, 2, DC_CONTACT_ID_SELF as libc::c_int);
sqlite3_bind_int(stmt, 3, (*chat).id as libc::c_int);
sqlite3_bind_double(
stmt,
4,
dc_param_get_float(
(*msg).param,
DC_PARAM_SET_LATITUDE as libc::c_int,
0.0,
),
);
sqlite3_bind_double(
stmt,
5,
dc_param_get_float(
(*msg).param,
DC_PARAM_SET_LONGITUDE as libc::c_int,
0.0,
),
);
sqlite3_step(stmt);
sqlite3_finalize(stmt);
stmt = 0 as *mut sqlite3_stmt;
location_id = dc_sqlite3_get_rowid2(
(*context).sql,
b"locations\x00" as *const u8 as *const libc::c_char,
b"timestamp\x00" as *const u8 as *const libc::c_char,
timestamp as u64,
b"from_id\x00" as *const u8 as *const libc::c_char,
DC_CONTACT_ID_SELF as u32,
);
}
// add message to the database
stmt = stmt =
dc_sqlite3_prepare((*context).sql, dc_sqlite3_prepare((*context).sql,
b"INSERT INTO msgs (rfc724_mid, chat_id, from_id, to_id, timestamp, type, state, txt, param, hidden, mime_in_reply_to, mime_references) VALUES (?,?,?,?,?, ?,?,?,?,?, ?,?);\x00" b"INSERT INTO msgs (rfc724_mid, chat_id, from_id, to_id, timestamp, type, state, txt, param, hidden, mime_in_reply_to, mime_references, location_id) VALUES (?,?,?,?,?, ?,?,?,?,?, ?,?,?);\x00"
as *const u8 as as *const u8 as
*const libc::c_char); *const libc::c_char);
sqlite3_bind_text(stmt, 1i32, new_rfc724_mid, -1i32, None); sqlite3_bind_text(stmt, 1i32, new_rfc724_mid, -1i32, None);
@@ -786,6 +836,7 @@ unsafe fn prepare_msg_raw(
sqlite3_bind_int(stmt, 10i32, (*msg).hidden); sqlite3_bind_int(stmt, 10i32, (*msg).hidden);
sqlite3_bind_text(stmt, 11i32, new_in_reply_to, -1i32, None); sqlite3_bind_text(stmt, 11i32, new_in_reply_to, -1i32, None);
sqlite3_bind_text(stmt, 12i32, new_references, -1i32, None); sqlite3_bind_text(stmt, 12i32, new_references, -1i32, None);
sqlite3_bind_int(stmt, 13i32, location_id as libc::c_int);
if sqlite3_step(stmt) != 101i32 { if sqlite3_step(stmt) != 101i32 {
dc_log_error( dc_log_error(
context, context,
@@ -974,6 +1025,16 @@ pub unsafe fn dc_send_msg(
(*msg).chat_id as uintptr_t, (*msg).chat_id as uintptr_t,
(*msg).id as uintptr_t, (*msg).id as uintptr_t,
); );
if 0 != dc_param_exists((*msg).param, DC_PARAM_SET_LATITUDE as libc::c_int) {
(*context).cb.expect("non-null function pointer")(
context,
Event::LOCATION_CHANGED,
DC_CONTACT_ID_SELF as u64,
0,
);
}
if 0 == chat_id { if 0 == chat_id {
let mut forwards: *mut libc::c_char = let mut forwards: *mut libc::c_char =
dc_param_get((*msg).param, 'P' as i32, 0 as *const libc::c_char); dc_param_get((*msg).param, 'P' as i32, 0 as *const libc::c_char);

View File

@@ -63,6 +63,22 @@ pub struct dc_context_t {
unsafe impl Send for dc_context_t {} unsafe impl Send for dc_context_t {}
unsafe impl Sync for dc_context_t {} unsafe impl Sync for dc_context_t {}
// location handling
#[derive(Copy, Clone)]
#[repr(C)]
pub struct _dc_location {
pub location_id: uint32_t,
pub latitude: libc::c_double,
pub longitude: libc::c_double,
pub accuracy: libc::c_double,
pub timestamp: time_t,
pub contact_id: uint32_t,
pub msg_id: uint32_t,
pub chat_id: uint32_t,
pub marker: *mut libc::c_char,
pub independent: uint32_t,
}
// create/open/config/information // create/open/config/information
pub unsafe fn dc_context_new( pub unsafe fn dc_context_new(
mut cb: dc_callback_t, mut cb: dc_callback_t,

View File

@@ -4,7 +4,7 @@ use libc;
use crate::constants::Event; use crate::constants::Event;
use crate::dc_array::*; use crate::dc_array::*;
use crate::dc_chat::*; use crate::dc_chat::*;
use crate::dc_context::dc_context_t; use crate::dc_context::*;
use crate::dc_job::*; use crate::dc_job::*;
use crate::dc_log::*; use crate::dc_log::*;
use crate::dc_lot::dc_lot_t; use crate::dc_lot::dc_lot_t;
@@ -226,10 +226,16 @@ pub unsafe fn dc_get_locations(
if timestamp_to == 0i32 as libc::c_long { if timestamp_to == 0i32 as libc::c_long {
timestamp_to = time(0 as *mut time_t) + 10i32 as libc::c_long timestamp_to = time(0 as *mut time_t) + 10i32 as libc::c_long
} }
stmt = stmt = dc_sqlite3_prepare(
dc_sqlite3_prepare((*context).sql, (*context).sql,
b"SELECT l.id, l.latitude, l.longitude, l.accuracy, l.timestamp, m.id, l.from_id, l.chat_id, m.txt FROM locations l LEFT JOIN msgs m ON l.id=m.location_id WHERE (? OR l.chat_id=?) AND (? OR l.from_id=?) AND l.timestamp>=? AND l.timestamp<=? ORDER BY l.timestamp DESC, l.id DESC, m.id DESC;\x00" b"SELECT l.id, l.latitude, l.longitude, l.accuracy, l.timestamp, l.independent \
as *const u8 as *const libc::c_char); m.id, l.from_id, l.chat_id, m.txt \
FROM locations l LEFT JOIN msgs m ON l.id=m.location_id WHERE (? OR l.chat_id=?) \
AND (? OR l.from_id=?) \
AND (l.independent=1 OR (l.timestamp>=? AND l.timestamp<=?)) \
ORDER BY l.timestamp DESC, l.id DESC, m.id DESC;\x00" as *const u8
as *const libc::c_char,
);
sqlite3_bind_int( sqlite3_bind_int(
stmt, stmt,
1i32, 1i32,
@@ -265,12 +271,14 @@ pub unsafe fn dc_get_locations(
(*loc).longitude = sqlite3_column_double(stmt, 2i32); (*loc).longitude = sqlite3_column_double(stmt, 2i32);
(*loc).accuracy = sqlite3_column_double(stmt, 3i32); (*loc).accuracy = sqlite3_column_double(stmt, 3i32);
(*loc).timestamp = sqlite3_column_int64(stmt, 4i32) as time_t; (*loc).timestamp = sqlite3_column_int64(stmt, 4i32) as time_t;
(*loc).msg_id = sqlite3_column_int(stmt, 5i32) as uint32_t; (*loc).independent = sqlite3_column_int(stmt, 5i32) as uint32_t;
(*loc).contact_id = sqlite3_column_int(stmt, 6i32) as uint32_t; (*loc).msg_id = sqlite3_column_int(stmt, 6i32) as uint32_t;
(*loc).chat_id = sqlite3_column_int(stmt, 7i32) as uint32_t; (*loc).contact_id = sqlite3_column_int(stmt, 7i32) as uint32_t;
(*loc).chat_id = sqlite3_column_int(stmt, 8i32) as uint32_t;
if 0 != (*loc).msg_id { if 0 != (*loc).msg_id {
let mut txt: *const libc::c_char = let mut txt: *const libc::c_char =
sqlite3_column_text(stmt, 8i32) as *const libc::c_char; sqlite3_column_text(stmt, 9i32) as *const libc::c_char;
if 0 != is_marker(txt) { if 0 != is_marker(txt) {
(*loc).marker = strdup(txt) (*loc).marker = strdup(txt)
} }
@@ -349,11 +357,18 @@ pub unsafe fn dc_get_location_kml(
b"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<kml xmlns=\"http://www.opengis.net/kml/2.2\">\n<Document addr=\"%s\">\n\x00" b"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<kml xmlns=\"http://www.opengis.net/kml/2.2\">\n<Document addr=\"%s\">\n\x00"
as *const u8 as *const libc::c_char, as *const u8 as *const libc::c_char,
self_addr); self_addr);
stmt = stmt = dc_sqlite3_prepare(
dc_sqlite3_prepare((*context).sql, (*context).sql,
b"SELECT id, latitude, longitude, accuracy, timestamp FROM locations WHERE from_id=? AND timestamp>=? AND (timestamp>=? OR timestamp=(SELECT MAX(timestamp) FROM locations WHERE from_id=?)) GROUP BY timestamp ORDER BY timestamp;\x00" b"SELECT id, latitude, longitude, accuracy, timestamp\
as *const u8 as FROM locations WHERE from_id=? \
*const libc::c_char); AND timestamp>=? \
AND (timestamp>=? OR timestamp=(SELECT MAX(timestamp) FROM locations WHERE from_id=?)) \
AND independent=0 \
GROUP BY timestamp \
ORDER BY timestamp;\x00" as *const u8
as *const libc::c_char,
);
sqlite3_bind_int(stmt, 1i32, 1i32); sqlite3_bind_int(stmt, 1i32, 1i32);
sqlite3_bind_int64(stmt, 2i32, locations_send_begin as sqlite3_int64); sqlite3_bind_int64(stmt, 2i32, locations_send_begin as sqlite3_int64);
sqlite3_bind_int64(stmt, 3i32, locations_last_sent as sqlite3_int64); sqlite3_bind_int64(stmt, 3i32, locations_last_sent as sqlite3_int64);
@@ -436,6 +451,43 @@ unsafe fn get_kml_timestamp(mut utc: time_t) -> *mut libc::c_char {
wanted_struct.tm_sec as libc::c_int, wanted_struct.tm_sec as libc::c_int,
); );
} }
pub unsafe fn dc_get_message_kml(
context: *const dc_context_t,
timestamp: time_t,
latitude: libc::c_double,
longitude: libc::c_double,
) -> *mut libc::c_char {
if !(context.is_null() || (*context).magic != 0x11a11807i32 as libc::c_uint) {
return std::ptr::null_mut();
}
let timestamp_str = get_kml_timestamp(timestamp);
let latitude_str = dc_ftoa(latitude);
let longitude_str = dc_ftoa(longitude);
let ret = dc_mprintf(
b"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
<kml xmlns=\"http://www.opengis.net/kml/2.2\">\n\
<Document>\n\
<Placemark>\
<Timestamp><when>%s</when></Timestamp>\
<Point><coordinates>%s,%s</coordinates></Point>\
</Placemark>\n\
</Document>\n\
</kml>\x00" as *const u8 as *const libc::c_char,
timestamp_str,
longitude_str, // reverse order!
latitude_str,
);
free(latitude_str as *mut libc::c_void);
free(longitude_str as *mut libc::c_void);
free(timestamp_str as *mut libc::c_void);
ret
}
pub unsafe fn dc_set_kml_sent_timestamp( pub unsafe fn dc_set_kml_sent_timestamp(
mut context: *mut dc_context_t, mut context: *mut dc_context_t,
mut chat_id: uint32_t, mut chat_id: uint32_t,
@@ -472,6 +524,7 @@ pub unsafe fn dc_save_locations(
mut chat_id: uint32_t, mut chat_id: uint32_t,
mut contact_id: uint32_t, mut contact_id: uint32_t,
mut locations: *const dc_array_t, mut locations: *const dc_array_t,
independent: libc::c_int,
) -> uint32_t { ) -> uint32_t {
let mut stmt_test: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; let mut stmt_test: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt;
let mut stmt_insert: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; let mut stmt_insert: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt;
@@ -487,10 +540,12 @@ pub unsafe fn dc_save_locations(
b"SELECT id FROM locations WHERE timestamp=? AND from_id=?\x00" as *const u8 b"SELECT id FROM locations WHERE timestamp=? AND from_id=?\x00" as *const u8
as *const libc::c_char, as *const libc::c_char,
); );
stmt_insert = stmt_insert = dc_sqlite3_prepare(
dc_sqlite3_prepare((*context).sql, (*context).sql,
b"INSERT INTO locations (timestamp, from_id, chat_id, latitude, longitude, accuracy) VALUES (?,?,?,?,?,?);\x00" b"INSERT INTO locations\
as *const u8 as *const libc::c_char); (timestamp, from_id, chat_id, latitude, longitude, accuracy, independent) \
VALUES (?,?,?,?,?,?,?);\x00" as *const u8 as *const libc::c_char,
);
let mut i: libc::c_int = 0i32; let mut i: libc::c_int = 0i32;
while (i as libc::c_ulong) < dc_array_get_cnt(locations) { while (i as libc::c_ulong) < dc_array_get_cnt(locations) {
let mut location: *mut dc_location_t = let mut location: *mut dc_location_t =
@@ -498,7 +553,7 @@ pub unsafe fn dc_save_locations(
sqlite3_reset(stmt_test); sqlite3_reset(stmt_test);
sqlite3_bind_int64(stmt_test, 1i32, (*location).timestamp as sqlite3_int64); sqlite3_bind_int64(stmt_test, 1i32, (*location).timestamp as sqlite3_int64);
sqlite3_bind_int(stmt_test, 2i32, contact_id as libc::c_int); sqlite3_bind_int(stmt_test, 2i32, contact_id as libc::c_int);
if sqlite3_step(stmt_test) != 100i32 { if independent | sqlite3_step(stmt_test) != 100i32 {
sqlite3_reset(stmt_insert); sqlite3_reset(stmt_insert);
sqlite3_bind_int64(stmt_insert, 1i32, (*location).timestamp as sqlite3_int64); sqlite3_bind_int64(stmt_insert, 1i32, (*location).timestamp as sqlite3_int64);
sqlite3_bind_int(stmt_insert, 2i32, contact_id as libc::c_int); sqlite3_bind_int(stmt_insert, 2i32, contact_id as libc::c_int);
@@ -506,6 +561,7 @@ pub unsafe fn dc_save_locations(
sqlite3_bind_double(stmt_insert, 4i32, (*location).latitude); sqlite3_bind_double(stmt_insert, 4i32, (*location).latitude);
sqlite3_bind_double(stmt_insert, 5i32, (*location).longitude); sqlite3_bind_double(stmt_insert, 5i32, (*location).longitude);
sqlite3_bind_double(stmt_insert, 6i32, (*location).accuracy); sqlite3_bind_double(stmt_insert, 6i32, (*location).accuracy);
sqlite3_bind_double(stmt_insert, 7i32, independent as libc::c_double);
sqlite3_step(stmt_insert); sqlite3_step(stmt_insert);
} }
if (*location).timestamp > newest_timestamp { if (*location).timestamp > newest_timestamp {
@@ -733,10 +789,12 @@ pub unsafe fn dc_job_do_DC_JOB_MAYBE_SEND_LOCATIONS(
b" ----------------- MAYBE_SEND_LOCATIONS -------------- \x00" as *const u8 b" ----------------- MAYBE_SEND_LOCATIONS -------------- \x00" as *const u8
as *const libc::c_char, as *const libc::c_char,
); );
stmt_chats = stmt_chats = dc_sqlite3_prepare(
dc_sqlite3_prepare((*context).sql, (*context).sql,
b"SELECT id, locations_send_begin, locations_last_sent FROM chats WHERE locations_send_until>?;\x00" b"SELECT id, locations_send_begin, locations_last_sent\
as *const u8 as *const libc::c_char); FROM chats\
WHERE locations_send_until>?;\x00" as *const u8 as *const libc::c_char,
);
sqlite3_bind_int64(stmt_chats, 1i32, now as sqlite3_int64); sqlite3_bind_int64(stmt_chats, 1i32, now as sqlite3_int64);
while sqlite3_step(stmt_chats) == 100i32 { while sqlite3_step(stmt_chats) == 100i32 {
let mut chat_id: uint32_t = sqlite3_column_int(stmt_chats, 0i32) as uint32_t; let mut chat_id: uint32_t = sqlite3_column_int(stmt_chats, 0i32) as uint32_t;
@@ -748,10 +806,16 @@ pub unsafe fn dc_job_do_DC_JOB_MAYBE_SEND_LOCATIONS(
continue; continue;
} }
if stmt_locations.is_null() { if stmt_locations.is_null() {
stmt_locations = stmt_locations = dc_sqlite3_prepare(
dc_sqlite3_prepare((*context).sql, (*context).sql,
b"SELECT id FROM locations WHERE from_id=? AND timestamp>=? AND timestamp>? ORDER BY timestamp;\x00" b"SELECT id \
as *const u8 as *const libc::c_char) FROM locations \
WHERE from_id=? \
AND timestamp>=? \
AND timestamp>? \
AND independent=0 \
ORDER BY timestamp;\x00" as *const u8 as *const libc::c_char,
);
} else { } else {
sqlite3_reset(stmt_locations); sqlite3_reset(stmt_locations);
} }

View File

@@ -850,6 +850,44 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc:
mailmime_smart_add_part(message, meta_part); mailmime_smart_add_part(message, meta_part);
parts += 1 parts += 1
} }
if 0 != dc_param_exists((*msg).param, DC_PARAM_SET_LATITUDE as libc::c_int)
{
let latitude = dc_param_get_float(
(*msg).param,
DC_PARAM_SET_LATITUDE as libc::c_int,
0.0,
);
let longitude = dc_param_get_float(
(*msg).param,
DC_PARAM_SET_LONGITUDE as libc::c_int,
0.0,
);
let kml_file = dc_get_message_kml(
(*msg).context,
(*msg).timestamp_sort,
latitude,
longitude,
);
if !kml_file.is_null() {
let content_type = mailmime_content_new_with_str(
b"application/vnd.google-earth.kml+xml\x00" as *const u8
as *const libc::c_char,
);
let mime_fields = mailmime_fields_new_filename(
MAILMIME_DISPOSITION_TYPE_ATTACHMENT as libc::c_int,
dc_strdup(
b"message.kml\x00" as *const u8 as *const libc::c_char,
),
MAILMIME_MECHANISM_8BIT as libc::c_int,
);
let kml_mime_part = mailmime_new_empty(content_type, mime_fields);
mailmime_set_body_text(kml_mime_part, kml_file, strlen(kml_file));
mailmime_smart_add_part(message, kml_mime_part);
parts += 1;
}
}
if 0 != dc_is_sending_locations_to_chat((*msg).context, (*msg).chat_id) { if 0 != dc_is_sending_locations_to_chat((*msg).context, (*msg).chat_id) {
let mut last_added_location_id: uint32_t = 0i32 as uint32_t; let mut last_added_location_id: uint32_t = 0i32 as uint32_t;
let mut kml_file: *mut libc::c_char = dc_get_location_kml( let mut kml_file: *mut libc::c_char = dc_get_location_kml(
@@ -876,7 +914,13 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc:
mailmime_set_body_text(kml_mime_part, kml_file, strlen(kml_file)); mailmime_set_body_text(kml_mime_part, kml_file, strlen(kml_file));
mailmime_smart_add_part(message, kml_mime_part); mailmime_smart_add_part(message, kml_mime_part);
parts += 1; parts += 1;
(*factory).out_last_added_location_id = last_added_location_id if 0 == dc_param_exists(
(*msg).param,
DC_PARAM_SET_LATITUDE as libc::c_int,
) {
// otherwise, the independent location is already filed
(*factory).out_last_added_location_id = last_added_location_id;
}
} }
} }
current_block = 9952640327414195044; current_block = 9952640327414195044;

View File

@@ -53,7 +53,8 @@ pub struct dc_mimeparser_t {
pub context: *mut dc_context_t, pub context: *mut dc_context_t,
pub reports: *mut carray, pub reports: *mut carray,
pub is_system_message: libc::c_int, pub is_system_message: libc::c_int,
pub kml: *mut dc_kml_t, pub location_kml: *mut dc_kml_t,
pub message_kml: *mut dc_kml_t,
} }
// deprecated // deprecated
@@ -99,6 +100,7 @@ pub unsafe fn dc_mimeparser_unref(mut mimeparser: *mut dc_mimeparser_t) {
free((*mimeparser).e2ee_helper as *mut libc::c_void); free((*mimeparser).e2ee_helper as *mut libc::c_void);
free(mimeparser as *mut libc::c_void); free(mimeparser as *mut libc::c_void);
} }
pub unsafe fn dc_mimeparser_empty(mut mimeparser: *mut dc_mimeparser_t) { pub unsafe fn dc_mimeparser_empty(mut mimeparser: *mut dc_mimeparser_t) {
if mimeparser.is_null() { if mimeparser.is_null() {
return; return;
@@ -137,9 +139,14 @@ pub unsafe fn dc_mimeparser_empty(mut mimeparser: *mut dc_mimeparser_t) {
} }
(*mimeparser).decrypting_failed = 0i32; (*mimeparser).decrypting_failed = 0i32;
dc_e2ee_thanks((*mimeparser).e2ee_helper); dc_e2ee_thanks((*mimeparser).e2ee_helper);
dc_kml_unref((*mimeparser).kml);
(*mimeparser).kml = 0 as *mut dc_kml_t; dc_kml_unref((*mimeparser).location_kml);
(*mimeparser).location_kml = 0 as *mut dc_kml_t;
dc_kml_unref((*mimeparser).message_kml);
(*mimeparser).message_kml = 0 as *mut dc_kml_t;
} }
unsafe fn dc_mimepart_unref(mut mimepart: *mut dc_mimepart_t) { unsafe fn dc_mimepart_unref(mut mimepart: *mut dc_mimepart_t) {
if mimepart.is_null() { if mimepart.is_null() {
return; return;
@@ -1415,7 +1422,26 @@ unsafe fn dc_mimeparser_add_single_part_if_known(
4i32 as libc::c_ulong, 4i32 as libc::c_ulong,
) == 0i32 ) == 0i32
{ {
(*mimeparser).kml = dc_kml_parse( (*mimeparser).location_kml = dc_kml_parse(
(*mimeparser).context,
decoded_data,
decoded_data_bytes,
);
current_block = 8795901732489102124;
} else if strncmp(
desired_filename,
b"message\x00" as *const u8 as *const libc::c_char,
7i32 as libc::c_ulong,
) == 0i32
&& strncmp(
desired_filename
.offset(strlen(desired_filename) as isize)
.offset(-4isize),
b".kml\x00" as *const u8 as *const libc::c_char,
4i32 as libc::c_ulong,
) == 0i32
{
(*mimeparser).message_kml = dc_kml_parse(
(*mimeparser).context, (*mimeparser).context,
decoded_data, decoded_data,
decoded_data_bytes, decoded_data_bytes,

View File

@@ -442,12 +442,60 @@ pub unsafe fn dc_msg_get_file(mut msg: *const dc_msg_t) -> *mut libc::c_char {
dc_strdup(0 as *const libc::c_char) dc_strdup(0 as *const libc::c_char)
}; };
} }
/**
* Check if a message has a location bound to it.
* These messages are also returned by dc_get_locations()
* and the UI may decide to display a special icon beside such messages,
*
* @memberof dc_msg_t
* @param msg The message object.
* @return 1=Message has location bound to it, 0=No location bound to message.
*/
pub unsafe fn dc_msg_has_location(mut msg: *const dc_msg_t) -> libc::c_int { pub unsafe fn dc_msg_has_location(mut msg: *const dc_msg_t) -> libc::c_int {
if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint { if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint {
return 0i32; return 0i32;
} }
return ((*msg).location_id != 0i32 as libc::c_uint) as libc::c_int; return ((*msg).location_id != 0i32 as libc::c_uint) as libc::c_int;
} }
/**
* Set any location that should be bound to the message object.
* The function is useful to add a marker to the map
* at a position different from the self-location.
* You should not call this function
* if you want to bind the current self-location to a message;
* this is done by dc_set_location() and dc_send_locations_to_chat().
*
* Typically results in the event #DC_EVENT_LOCATION_CHANGED with
* contact_id set to DC_CONTACT_ID_SELF.
*
* @memberof dc_msg_t
* @param msg The message object.
* @param latitude North-south position of the location.
* @param longitude East-west position of the location.
* @return None.
*/
pub unsafe fn dc_msg_set_location(
mut msg: *const dc_msg_t,
latitude: libc::c_double,
longitude: libc::c_double,
) {
if msg.is_null()
|| (*msg).magic != 0x11561156i32 as libc::c_uint
|| (latitude == 0.0 && longitude == 0.0)
{
return;
}
dc_param_set_float((*msg).param, DC_PARAM_SET_LATITUDE as libc::c_int, latitude);
dc_param_set_float(
(*msg).param,
DC_PARAM_SET_LONGITUDE as libc::c_int,
longitude,
);
}
pub unsafe fn dc_msg_get_timestamp(mut msg: *const dc_msg_t) -> time_t { pub unsafe fn dc_msg_get_timestamp(mut msg: *const dc_msg_t) -> time_t {
if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint { if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint {
return 0i32 as time_t; return 0i32 as time_t;

View File

@@ -4,17 +4,71 @@ use crate::dc_tools::*;
use crate::types::*; use crate::types::*;
use crate::x::*; use crate::x::*;
/* * /// for msgs and jobs
* @class dc_param_t pub const DC_PARAM_FILE: char = 'f';
* /// for msgs
* An object for handling key=value parameter lists; for the key, curently only pub const DC_PARAM_WIDTH: char = 'w';
* a single character is allowed. /// for msgs
* pub const DC_PARAM_HEIGHT: char = 'h';
* The object is used eg. by dc_chat_t or dc_msg_t, for readable paramter names, /// for msgs
* these classes define some DC_PARAM_* constantats. pub const DC_PARAM_DURATION: char = 'd';
* /// for msgs
* Only for library-internal use. pub const DC_PARAM_MIMETYPE: char = 'm';
*/ /// for msgs: incoming: message is encryoted, outgoing: guarantee E2EE or the message is not send
pub const DC_PARAM_GUARANTEE_E2EE: char = 'c';
/// for msgs: decrypted with validation errors or without mutual set, if neither 'c' nor 'e' are preset, the messages is only transport encrypted
pub const DC_PARAM_ERRONEOUS_E2EE: char = 'e';
/// for msgs: force unencrypted message, either DC_FP_ADD_AUTOCRYPT_HEADER (1), DC_FP_NO_AUTOCRYPT_HEADER (2) or 0
pub const DC_PARAM_FORCE_PLAINTEXT: char = 'u';
/// for msgs: an incoming message which requestes a MDN (aka read receipt)
pub const DC_PARAM_WANTS_MDN: char = 'r';
/// for msgs
pub const DC_PARAM_FORWARDED: char = 'a';
/// for msgs
pub const DC_PARAM_CMD: char = 'S';
/// for msgs
pub const DC_PARAM_CMD_ARG: char = 'E';
/// for msgs
pub const DC_PARAM_CMD_ARG2: char = 'F';
/// for msgs
pub const DC_PARAM_CMD_ARG3: char = 'G';
/// for msgs
pub const DC_PARAM_CMD_ARG4: char = 'H';
/// for msgs
pub const DC_PARAM_ERROR: char = 'L';
/// for msgs in PREPARING: space-separated list of message IDs of forwarded copies
pub const DC_PARAM_PREP_FORWARDS: char = 'P';
/// for msgs
pub const DC_PARAM_SET_LATITUDE: char = 'l';
/// for msgs
pub const DC_PARAM_SET_LONGITUDE: char = 'n';
/// for jobs
pub const DC_PARAM_SERVER_FOLDER: char = 'Z';
/// for jobs
pub const DC_PARAM_SERVER_UID: char = 'z';
/// for jobs
pub const DC_PARAM_ALSO_MOVE: char = 'M';
/// for jobs: space-separated list of message recipients
pub const DC_PARAM_RECIPIENTS: char = 'R';
/// for groups
pub const DC_PARAM_UNPROMOTED: char = 'U';
/// for groups and contacts
pub const DC_PARAM_PROFILE_IMAGE: char = 'i';
/// for chats
pub const DC_PARAM_SELFTALK: char = 'K';
// values for DC_PARAM_FORCE_PLAINTEXT
pub const DC_FP_ADD_AUTOCRYPT_HEADER: u8 = 1;
pub const DC_FP_NO_AUTOCRYPT_HEADER: u8 = 2;
/// An object for handling key=value parameter lists; for the key, curently only
/// a single character is allowed.
///
/// The object is used eg. by dc_chat_t or dc_msg_t, for readable paramter names,
/// these classes define some DC_PARAM_* constantats.
///
/// Only for library-internal use.
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
#[repr(C)] #[repr(C)]
pub struct dc_param_t { pub struct dc_param_t {
@@ -34,6 +88,7 @@ pub unsafe fn dc_param_exists(mut param: *mut dc_param_t, mut key: libc::c_int)
0i32 0i32
}; };
} }
unsafe extern "C" fn find_param( unsafe extern "C" fn find_param(
mut haystack: *mut libc::c_char, mut haystack: *mut libc::c_char,
mut key: libc::c_int, mut key: libc::c_int,
@@ -111,6 +166,36 @@ pub unsafe fn dc_param_get_int(
free(str as *mut libc::c_void); free(str as *mut libc::c_void);
return ret; return ret;
} }
/**
* Get value of a parameter.
*
* @memberof dc_param_t
* @param param Parameter object to query.
* @param key Key of the parameter to get, one of the DC_PARAM_* constants.
* @param def Value to return if the parameter is not set.
* @return The stored value or the default value.
*/
pub unsafe fn dc_param_get_float(
param: *const dc_param_t,
key: libc::c_int,
def: libc::c_double,
) -> libc::c_double {
if param.is_null() || key == 0 {
return def;
}
let mut str = dc_param_get(param, key, std::ptr::null());
if str.is_null() {
return def;
}
let ret = dc_atof(str) as libc::c_double;
free(str as *mut libc::c_void);
ret
}
pub unsafe fn dc_param_set( pub unsafe fn dc_param_set(
mut param: *mut dc_param_t, mut param: *mut dc_param_t,
mut key: libc::c_int, mut key: libc::c_int,
@@ -265,3 +350,25 @@ pub unsafe fn dc_param_set_urlencoded(
); );
}; };
} }
/**
* Set parameter to a float.
*
* @memberof dc_param_t
* @param param Parameter object to modify.
* @param key Key of the parameter to modify, one of the DC_PARAM_* constants.
* @param value Value to store for key.
* @return None.
*/
pub unsafe fn dc_param_set_float(param: *mut dc_param_t, key: libc::c_int, value: libc::c_double) {
if param.is_null() || key == 0 {
return;
}
let value_str = dc_ftoa(value);
if value_str.is_null() {
return;
}
dc_param_set(param, key, value_str);
free(value_str as *mut libc::c_void);
}

View File

@@ -1,7 +1,7 @@
use c2rust_bitfields::BitfieldStruct; use c2rust_bitfields::BitfieldStruct;
use libc; use libc;
use crate::constants::Event; use crate::constants::*;
use crate::dc_apeerstate::*; use crate::dc_apeerstate::*;
use crate::dc_array::*; use crate::dc_array::*;
use crate::dc_chat::*; use crate::dc_chat::*;
@@ -552,7 +552,7 @@ pub unsafe fn dc_receive_imf(
carray_get((*mime_parser).parts, i as libc::c_uint) carray_get((*mime_parser).parts, i as libc::c_uint)
as *mut dc_mimepart_t; as *mut dc_mimepart_t;
if !(0 != (*part).is_meta) { if !(0 != (*part).is_meta) {
if !(*mime_parser).kml.is_null() if !(*mime_parser).location_kml.is_null()
&& icnt == 1i32 as libc::c_ulong && icnt == 1i32 as libc::c_ulong
&& !(*part).msg.is_null() && !(*part).msg.is_null()
&& (strcmp( && (strcmp(
@@ -922,22 +922,56 @@ pub unsafe fn dc_receive_imf(
i = i.wrapping_add(1) i = i.wrapping_add(1)
} }
} }
if !(*mime_parser).kml.is_null() && chat_id > 9i32 as libc::c_uint { if !(*mime_parser).message_kml.is_null() && chat_id > 9i32 as libc::c_uint {
let mut contact: *mut dc_contact_t = dc_get_contact(context, from_id); let mut location_id_written = false;
if !(*(*mime_parser).kml).addr.is_null() let mut send_event = false;
&& !contact.is_null()
&& !(*contact).addr.is_null() if !(*mime_parser).message_kml.is_null()
&& strcasecmp((*contact).addr, (*(*mime_parser).kml).addr) == 0i32 && chat_id > DC_CHAT_ID_LAST_SPECIAL as libc::c_uint
{ {
let mut newest_location_id: uint32_t = dc_save_locations( let mut newest_location_id: uint32_t = dc_save_locations(
context, context,
chat_id, chat_id,
from_id, from_id,
(*(*mime_parser).kml).locations, (*(*mime_parser).message_kml).locations,
1,
); );
if 0 != newest_location_id && 0 == hidden { if 0 != newest_location_id && 0 == hidden {
dc_set_msg_location_id(context, insert_msg_id, newest_location_id); dc_set_msg_location_id(context, insert_msg_id, newest_location_id);
location_id_written = true;
send_event = true;
} }
}
if !(*mime_parser).location_kml.is_null()
&& chat_id > DC_CHAT_ID_LAST_SPECIAL as libc::c_uint
{
let contact = dc_get_contact(context, from_id);
if !(*(*mime_parser).location_kml).addr.is_null()
&& !contact.is_null()
&& !(*contact).addr.is_null()
&& strcasecmp((*contact).addr, (*(*mime_parser).location_kml).addr)
== 0i32
{
let newest_location_id = dc_save_locations(
context,
chat_id,
from_id,
(*(*mime_parser).location_kml).locations,
0,
);
if newest_location_id != 0 && hidden == 0 && !location_id_written {
dc_set_msg_location_id(
context,
insert_msg_id,
newest_location_id,
);
}
send_event = true;
}
dc_contact_unref(contact);
}
if send_event {
(*context).cb.expect("non-null function pointer")( (*context).cb.expect("non-null function pointer")(
context, context,
Event::LOCATION_CHANGED, Event::LOCATION_CHANGED,
@@ -945,8 +979,8 @@ pub unsafe fn dc_receive_imf(
0i32 as uintptr_t, 0i32 as uintptr_t,
); );
} }
dc_contact_unref(contact);
} }
if 0 != add_delete_job if 0 != add_delete_job
&& carray_count(created_db_entries) >= 2i32 as libc::c_uint && carray_count(created_db_entries) >= 2i32 as libc::c_uint
{ {

View File

@@ -740,6 +740,20 @@ pub unsafe fn dc_sqlite3_open(
54i32, 54i32,
); );
} }
if dbversion < 55 {
dc_sqlite3_execute(
sql,
b"ALTER TABLE locations ADD COLUMN independent INTEGER DEFAULT 0;\x00" as *const u8 as *const libc::c_char
);
dbversion = 55;
dc_sqlite3_set_config_int(
sql,
b"dbversion\x00" as *const u8 as *const libc::c_char,
55,
);
}
if 0 != recalc_fingerprints { if 0 != recalc_fingerprints {
let mut stmt: *mut sqlite3_stmt = dc_sqlite3_prepare( let mut stmt: *mut sqlite3_stmt = dc_sqlite3_prepare(
sql, sql,