Introduce new enum: Viewtype

With this change, kind of message is represented by value of enum
`Viewtype' instead of raw libc::c_int, providing more type safety. This
enum replaces DC_MSG_* constants. The only way to create `Viewtype' from
libc::c_int is smart constructor.

With this change, functions `dc_get_chat_media' and `dc_get_next_media' became
less forgiving about invalid message type arguments. Previously, invalid
message types were implicitly interpreted as 0 (Viewtype::Unknown). Now,
function calls with invalid message type arguments are rejected (error code
returned) on FFI boundary.

Additionally, when `Viewtype' is read from database, it is checked to have
sensible value.

No tests assumed forgiving behaviour.
This commit is contained in:
Dmitry Bogatov
2019-07-29 01:58:42 +00:00
parent e7456248a0
commit c04c8ff103
12 changed files with 219 additions and 135 deletions

1
Cargo.lock generated
View File

@@ -507,6 +507,7 @@ dependencies = [
"deltachat 1.0.0-alpha.3",
"human-panic 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]

View File

@@ -18,6 +18,7 @@ crate-type = ["cdylib", "staticlib"]
deltachat = { path = "../", default-features = false }
libc = "0.2"
human-panic = "1.0.1"
num-traits = "0.2.6"
[features]
default = ["vendored", "nightly", "ringbuf"]

View File

@@ -9,7 +9,10 @@
#[macro_use]
extern crate human_panic;
extern crate num_traits;
use num_traits::{FromPrimitive, ToPrimitive};
use std::ptr;
use std::str::FromStr;
use deltachat::*;
@@ -458,6 +461,14 @@ pub unsafe extern "C" fn dc_marknoticed_all_chats(context: *mut dc_context_t) {
dc_chat::dc_marknoticed_all_chats(context);
}
fn from_prim<S, T>(s: S) -> Option<T>
where
T: FromPrimitive,
S: Into<i64>,
{
FromPrimitive::from_i64(s.into())
}
#[no_mangle]
pub unsafe extern "C" fn dc_get_chat_media(
context: *mut dc_context_t,
@@ -469,7 +480,15 @@ pub unsafe extern "C" fn dc_get_chat_media(
assert!(!context.is_null());
let context = &*context;
dc_chat::dc_get_chat_media(context, chat_id, msg_type, or_msg_type2, or_msg_type3)
if let (Some(msg_type), Some(or_msg_type2), Some(or_msg_type3)) = (
from_prim(msg_type),
from_prim(or_msg_type2),
from_prim(or_msg_type3),
) {
dc_chat::dc_get_chat_media(context, chat_id, msg_type, or_msg_type2, or_msg_type3)
} else {
ptr::null_mut()
}
}
#[no_mangle]
@@ -484,7 +503,15 @@ pub unsafe extern "C" fn dc_get_next_media(
assert!(!context.is_null());
let context = &*context;
dc_chat::dc_get_next_media(context, msg_id, dir, msg_type, or_msg_type2, or_msg_type3)
if let (Some(msg_type), Some(or_msg_type2), Some(or_msg_type3)) = (
from_prim(msg_type),
from_prim(or_msg_type2),
from_prim(or_msg_type3),
) {
dc_chat::dc_get_next_media(context, msg_id, dir, msg_type, or_msg_type2, or_msg_type3)
} else {
0
}
}
#[no_mangle]
@@ -1236,8 +1263,11 @@ pub unsafe extern "C" fn dc_msg_new<'a>(
) -> *mut dc_msg::dc_msg_t<'a> {
assert!(!context.is_null());
let context = &*context;
dc_msg::dc_msg_new(context, viewtype)
if let Some(viewtype) = from_prim(viewtype) {
dc_msg::dc_msg_new(context, viewtype)
} else {
ptr::null_mut()
}
}
#[no_mangle]
@@ -1268,6 +1298,8 @@ pub unsafe extern "C" fn dc_msg_get_chat_id(msg: *mut dc_msg::dc_msg_t) -> u32 {
#[no_mangle]
pub unsafe extern "C" fn dc_msg_get_viewtype(msg: *mut dc_msg::dc_msg_t) -> libc::c_int {
dc_msg::dc_msg_get_viewtype(msg)
.to_i64()
.expect("impossible: Viewtype -> i64 conversion failed") as libc::c_int
}
#[no_mangle]

View File

@@ -963,7 +963,14 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E
ensure!(!sel_chat.is_null(), "No chat selected.");
ensure!(!arg1.is_empty() && !arg2.is_empty(), "No file given.");
let msg_0 = dc_msg_new(context, if arg0 == "sendimage" { 20 } else { 60 });
let msg_0 = dc_msg_new(
context,
if arg0 == "sendimage" {
Viewtype::Image
} else {
Viewtype::File
},
);
dc_msg_set_file(msg_0, arg1_c, 0 as *const libc::c_char);
dc_msg_set_text(msg_0, arg2_c);
dc_send_msg(context, dc_chat_get_id(sel_chat), msg_0);
@@ -990,7 +997,7 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E
ensure!(!sel_chat.is_null(), "No chat selected.");
if !arg1.is_empty() {
let draft_0 = dc_msg_new(context, 10);
let draft_0 = dc_msg_new(context, Viewtype::Text);
dc_msg_set_text(draft_0, arg1_c);
dc_set_draft(context, dc_chat_get_id(sel_chat), draft_0);
dc_msg_unref(draft_0);
@@ -1003,7 +1010,13 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E
"listmedia" => {
ensure!(!sel_chat.is_null(), "No chat selected.");
let images = dc_get_chat_media(context, dc_chat_get_id(sel_chat), 20, 21, 50);
let images = dc_get_chat_media(
context,
dc_chat_get_id(sel_chat),
Viewtype::Image,
Viewtype::Gif,
Viewtype::Video,
);
let icnt: libc::c_int = dc_array_get_cnt(images) as libc::c_int;
println!("{} images or videos: ", icnt);
for i in 0..icnt {

View File

@@ -1,5 +1,9 @@
#![allow(non_camel_case_types)]
//! Constants
#![allow(non_camel_case_types)]
use num_traits::{FromPrimitive, ToPrimitive};
use rusqlite as sql;
use rusqlite::types::*;
use std::fmt;
pub const DC_VERSION_STR: &'static [u8; 14] = b"1.0.0-alpha.3\x00";
@@ -96,46 +100,6 @@ pub const DC_TEXT1_SELF: usize = 3;
pub const DC_CREATE_MVBOX: usize = 1;
/// Text message.
/// The text of the message is set using dc_msg_set_text()
/// and retrieved with dc_msg_get_text().
pub const DC_MSG_TEXT: i32 = 10;
/// Image message.
/// If the image is an animated GIF, the type DC_MSG_GIF should be used.
/// File, width and height are set via dc_msg_set_file(), dc_msg_set_dimension
/// and retrieved via dc_msg_set_file(), dc_msg_set_dimension().
pub const DC_MSG_IMAGE: i32 = 20;
/// Animated GIF message.
/// File, width and height are set via dc_msg_set_file(), dc_msg_set_dimension()
/// and retrieved via dc_msg_get_file(), dc_msg_get_width(), dc_msg_get_height().
pub const DC_MSG_GIF: i32 = 21;
/// Message containing an Audio file.
/// File and duration are set via dc_msg_set_file(), dc_msg_set_duration()
/// and retrieved via dc_msg_get_file(), dc_msg_get_duration().
pub const DC_MSG_AUDIO: i32 = 40;
/// A voice message that was directly recorded by the user.
/// For all other audio messages, the type #DC_MSG_AUDIO should be used.
/// File and duration are set via dc_msg_set_file(), dc_msg_set_duration()
/// and retrieved via dc_msg_get_file(), dc_msg_get_duration()
pub const DC_MSG_VOICE: i32 = 41;
/// Video messages.
/// File, width, height and durarion
/// are set via dc_msg_set_file(), dc_msg_set_dimension(), dc_msg_set_duration()
/// and retrieved via
/// dc_msg_get_file(), dc_msg_get_width(),
/// dc_msg_get_height(), dc_msg_get_duration().
pub const DC_MSG_VIDEO: i32 = 50;
/// Message containing any file, eg. a PDF.
/// The file is set via dc_msg_set_file()
/// and retrieved via dc_msg_get_file().
pub const DC_MSG_FILE: i32 = 60;
// Flags for configuring IMAP and SMTP servers.
// These flags are optional
// and may be set together with the username, password etc.
@@ -183,6 +147,79 @@ pub const DC_LP_IMAP_SOCKET_FLAGS: usize =
pub const DC_LP_SMTP_SOCKET_FLAGS: usize =
(DC_LP_SMTP_SOCKET_STARTTLS | DC_LP_SMTP_SOCKET_SSL | DC_LP_SMTP_SOCKET_PLAIN);
#[derive(Debug, Clone, Copy, PartialEq, Eq, FromPrimitive, ToPrimitive)]
#[repr(i32)]
pub enum Viewtype {
Unknown = 0,
/// Text message.
/// The text of the message is set using dc_msg_set_text()
/// and retrieved with dc_msg_get_text().
Text = 10,
/// Image message.
/// If the image is an animated GIF, the type DC_MSG_GIF should be used.
/// File, width and height are set via dc_msg_set_file(), dc_msg_set_dimension
/// and retrieved via dc_msg_set_file(), dc_msg_set_dimension().
Image = 20,
/// Animated GIF message.
/// File, width and height are set via dc_msg_set_file(), dc_msg_set_dimension()
/// and retrieved via dc_msg_get_file(), dc_msg_get_width(), dc_msg_get_height().
Gif = 21,
/// Message containing an Audio file.
/// File and duration are set via dc_msg_set_file(), dc_msg_set_duration()
/// and retrieved via dc_msg_get_file(), dc_msg_get_duration().
Audio = 40,
/// A voice message that was directly recorded by the user.
/// For all other audio messages, the type #DC_MSG_AUDIO should be used.
/// File and duration are set via dc_msg_set_file(), dc_msg_set_duration()
/// and retrieved via dc_msg_get_file(), dc_msg_get_duration()
Voice = 41,
/// Video messages.
/// File, width, height and durarion
/// are set via dc_msg_set_file(), dc_msg_set_dimension(), dc_msg_set_duration()
/// and retrieved via
/// dc_msg_get_file(), dc_msg_get_width(),
/// dc_msg_get_height(), dc_msg_get_duration().
Video = 50,
/// Message containing any file, eg. a PDF.
/// The file is set via dc_msg_set_file()
/// and retrieved via dc_msg_get_file().
File = 60,
}
impl ToSql for Viewtype {
fn to_sql(&self) -> sql::Result<ToSqlOutput> {
let num: i64 = self
.to_i64()
.expect("impossible: Viewtype -> i64 conversion failed");
Ok(ToSqlOutput::Owned(Value::Integer(num)))
}
}
impl FromSql for Viewtype {
fn column_result(col: ValueRef) -> FromSqlResult<Self> {
let inner = FromSql::column_result(col)?;
FromPrimitive::from_i64(inner).ok_or(FromSqlError::InvalidType)
}
}
impl fmt::Display for Viewtype {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"{}",
self.to_i64()
.expect("impossible: Viewtype -> i64 conversion failed")
)
}
}
// These constants are used as events
// reported to the callback given to dc_context_new().
// If you do not want to handle an event, it is always safe to return 0,

View File

@@ -371,14 +371,14 @@ pub unsafe fn dc_prepare_msg<'a>(
return msg_id;
}
pub fn msgtype_has_file(msgtype: i32) -> bool {
pub fn msgtype_has_file(msgtype: Viewtype) -> bool {
match msgtype {
DC_MSG_IMAGE => true,
DC_MSG_GIF => true,
DC_MSG_AUDIO => true,
DC_MSG_VOICE => true,
DC_MSG_VIDEO => true,
DC_MSG_FILE => true,
Viewtype::Image => true,
Viewtype::Gif => true,
Viewtype::Audio => true,
Viewtype::Voice => true,
Viewtype::Video => true,
Viewtype::File => true,
_ => false,
}
}
@@ -392,7 +392,7 @@ unsafe fn prepare_msg_common<'a>(
let mut OK_TO_CONTINUE = true;
(*msg).id = 0i32 as uint32_t;
(*msg).context = context;
if (*msg).type_0 == DC_MSG_TEXT {
if (*msg).type_0 == Viewtype::Text {
/* the caller should check if the message text is empty */
} else if msgtype_has_file((*msg).type_0) {
let mut pathNfilename = (*msg)
@@ -417,16 +417,16 @@ unsafe fn prepare_msg_common<'a>(
OK_TO_CONTINUE = false;
} else {
(*msg).param.set(Param::File, as_str(pathNfilename));
if (*msg).type_0 == DC_MSG_FILE || (*msg).type_0 == DC_MSG_IMAGE {
if (*msg).type_0 == Viewtype::File || (*msg).type_0 == Viewtype::Image {
/* Correct the type, take care not to correct already very special formats as GIF or VOICE.
Typical conversions:
- from FILE to AUDIO/VIDEO/IMAGE
- from FILE/IMAGE to GIF */
let mut better_type = 0;
let mut better_type = Viewtype::Unknown;
let mut better_mime = std::ptr::null_mut();
dc_msg_guess_msgtype_from_suffix(pathNfilename, &mut better_type, &mut better_mime);
if 0 != better_type && !better_mime.is_null() {
if Viewtype::Unknown != better_type && !better_mime.is_null() {
(*msg).type_0 = better_type;
(*msg).param.set(Param::MimeType, as_str(better_mime));
}
@@ -436,7 +436,7 @@ unsafe fn prepare_msg_common<'a>(
dc_msg_guess_msgtype_from_suffix(
pathNfilename,
0 as *mut libc::c_int,
0 as *mut Viewtype,
&mut better_mime,
);
@@ -974,7 +974,7 @@ pub unsafe fn dc_send_text_msg(
return 0;
}
let mut msg = dc_msg_new(context, 10);
let mut msg = dc_msg_new(context, Viewtype::Text);
(*msg).text = dc_strdup(text_to_send);
let ret = dc_send_msg(context, chat_id, msg);
dc_msg_unref(msg);
@@ -1004,7 +1004,7 @@ unsafe fn set_draft_raw(context: &Context, chat_id: uint32_t, msg: *mut dc_msg_t
}
// save new draft
if !msg.is_null() {
if (*msg).type_0 == DC_MSG_TEXT {
if (*msg).type_0 == Viewtype::Text {
if (*msg).text.is_null() || *(*msg).text.offset(0isize) as libc::c_int == 0i32 {
OK_TO_CONTINUE = false;
}
@@ -1258,20 +1258,20 @@ pub fn dc_marknoticed_all_chats(context: &Context) -> bool {
pub fn dc_get_chat_media(
context: &Context,
chat_id: uint32_t,
msg_type: libc::c_int,
msg_type2: libc::c_int,
msg_type3: libc::c_int,
msg_type: Viewtype,
msg_type2: Viewtype,
msg_type3: Viewtype,
) -> *mut dc_array_t {
context.sql.query_map(
"SELECT id FROM msgs WHERE chat_id=? AND (type=? OR type=? OR type=?) ORDER BY timestamp, id;",
params![
chat_id as i32,
msg_type,
if msg_type2 > 0 {
if msg_type2 != Viewtype::Unknown {
msg_type2
} else {
msg_type
}, if msg_type3 > 0 {
}, if msg_type3 != Viewtype::Unknown {
msg_type3
} else {
msg_type
@@ -1292,9 +1292,9 @@ pub unsafe fn dc_get_next_media(
context: &Context,
curr_msg_id: uint32_t,
dir: libc::c_int,
msg_type: libc::c_int,
msg_type2: libc::c_int,
msg_type3: libc::c_int,
msg_type: Viewtype,
msg_type2: Viewtype,
msg_type3: Viewtype,
) -> uint32_t {
let mut ret_msg_id: uint32_t = 0i32 as uint32_t;
let msg: *mut dc_msg_t = dc_msg_new_untyped(context);
@@ -1306,7 +1306,7 @@ pub unsafe fn dc_get_next_media(
list = dc_get_chat_media(
context,
(*msg).chat_id,
if msg_type > 0i32 {
if msg_type != Viewtype::Unknown {
msg_type
} else {
(*msg).type_0
@@ -1510,7 +1510,7 @@ pub unsafe fn dc_create_group_chat(
chat_id = sql::get_rowid(context, &context.sql, "chats", "grpid", grpid);
if chat_id != 0 {
if 0 != dc_add_to_chat_contacts_table(context, chat_id, 1) {
let draft_msg = dc_msg_new(context, 10);
let draft_msg = dc_msg_new(context, Viewtype::Text);
dc_msg_set_text(draft_msg, draft_txt.as_ptr());
set_draft_raw(context, chat_id, draft_msg);
dc_msg_unref(draft_msg);
@@ -1619,7 +1619,7 @@ pub unsafe fn dc_add_contact_to_chat_ex(
}
if OK_TO_CONTINUE {
if (*chat).param.get_int(Param::Unpromoted).unwrap_or_default() == 0 {
(*msg).type_0 = DC_MSG_TEXT;
(*msg).type_0 = Viewtype::Text;
(*msg).text = to_cstring(context.stock_system_msg(
StockMessage::MsgAddMember,
as_str((*contact).addr),
@@ -1730,7 +1730,7 @@ pub unsafe fn dc_remove_contact_from_chat(
/* we should respect this - whatever we send to the group, it gets discarded anyway! */
if !contact.is_null() {
if (*chat).param.get_int(Param::Unpromoted).unwrap_or_default() == 0 {
(*msg).type_0 = DC_MSG_TEXT;
(*msg).type_0 = Viewtype::Text;
if (*contact).id == 1 as libc::c_uint {
dc_set_group_explicitly_left(context, (*chat).grpid);
(*msg).text = to_cstring(context.stock_system_msg(
@@ -1845,7 +1845,7 @@ pub unsafe fn dc_set_chat_name(
.is_ok()
{
if (*chat).param.get_int(Param::Unpromoted).unwrap_or_default() == 0 {
(*msg).type_0 = DC_MSG_TEXT;
(*msg).type_0 = Viewtype::Text;
(*msg).text = to_cstring(context.stock_system_msg(
StockMessage::MsgGrpName,
as_str((*chat).name),
@@ -1917,7 +1917,7 @@ pub unsafe fn dc_set_chat_profile_image(
if (*chat).param.get_int(Param::Unpromoted).unwrap_or_default() == 0 {
(*msg).param.set_int(Param::Cmd, 3);
(*msg).param.set(Param::Arg, as_str(new_image_rel));
(*msg).type_0 = DC_MSG_TEXT;
(*msg).type_0 = Viewtype::Text;
(*msg).text = to_cstring(context.stock_system_msg(
if !new_image_rel.is_null() {
StockMessage::MsgGrpImgChanged
@@ -2287,7 +2287,7 @@ pub fn dc_add_device_msg(context: &Context, chat_id: uint32_t, text: *const libc
2,
2,
unsafe {dc_create_smeared_timestamp(context)},
DC_MSG_TEXT,
Viewtype::Text,
DC_STATE_IN_NOTICED,
as_str(text),
as_str(rfc724_mid),

View File

@@ -139,7 +139,7 @@ pub unsafe fn dc_initiate_key_transfer(context: &Context) -> *mut libc::c_char {
let chat_id = dc_create_chat_by_contact_id(context, 1i32 as uint32_t);
if !(chat_id == 0i32 as libc::c_uint) {
msg = dc_msg_new_untyped(context);
(*msg).type_0 = DC_MSG_FILE;
(*msg).type_0 = Viewtype::File;
(*msg).param.set(Param::File, as_str(setup_file_name));
(*msg)

View File

@@ -1184,8 +1184,8 @@ pub unsafe fn dc_job_send_msg(context: &Context, msg_id: uint32_t) -> libc::c_in
.unwrap_or_default(),
);
if strlen(pathNfilename) > 0 {
if ((*mimefactory.msg).type_0 == DC_MSG_IMAGE
|| (*mimefactory.msg).type_0 == DC_MSG_GIF)
if ((*mimefactory.msg).type_0 == Viewtype::Image
|| (*mimefactory.msg).type_0 == Viewtype::Gif)
&& !(*mimefactory.msg).param.exists(Param::Width)
{
let mut buf = 0 as *mut libc::c_uchar;

View File

@@ -1,6 +1,7 @@
use std::ffi::CString;
use crate::constants::Event;
use crate::constants::*;
use crate::context::*;
use crate::dc_array::*;
use crate::dc_chat::*;
@@ -98,7 +99,7 @@ pub unsafe fn dc_send_locations_to_chat(
.is_ok()
{
if 0 != seconds && !is_sending_locations_before {
msg = dc_msg_new(context, 10i32);
msg = dc_msg_new(context, Viewtype::Text);
(*msg).text = to_cstring(context.stock_system_msg(
StockMessage::MsgLocationEnabled,
"",
@@ -702,7 +703,7 @@ pub unsafe fn dc_job_do_DC_JOB_MAYBE_SEND_LOCATIONS(context: &Context, _job: *mu
// the easiest way to determine this, is to check for an empty message queue.
// (might not be 100%, however, as positions are sent combined later
// and dc_set_location() is typically called periodically, this is ok)
let mut msg = dc_msg_new(context, 10);
let mut msg = dc_msg_new(context, Viewtype::Text);
(*msg).hidden = 1;
(*msg).param.set_int(Param::Cmd, 9);
dc_send_msg(context, chat_id as u32, msg);

View File

@@ -738,10 +738,9 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc:
}
}
}
if let Some(grpimage) = grpimage {
let mut meta = dc_msg_new_untyped((*factory).context);
(*meta).type_0 = DC_MSG_IMAGE as libc::c_int;
(*meta).type_0 = Viewtype::Image;
(*meta).param.set(Param::File, grpimage);
let mut filename_as_sent = 0 as *mut libc::c_char;
@@ -762,11 +761,11 @@ pub unsafe fn dc_mimefactory_render(mut factory: *mut dc_mimefactory_t) -> libc:
dc_msg_unref(meta);
}
if (*msg).type_0 == DC_MSG_VOICE
|| (*msg).type_0 == DC_MSG_AUDIO
|| (*msg).type_0 == DC_MSG_VIDEO
if (*msg).type_0 == Viewtype::Voice
|| (*msg).type_0 == Viewtype::Audio
|| (*msg).type_0 == Viewtype::Video
{
if (*msg).type_0 == DC_MSG_VOICE {
if (*msg).type_0 == Viewtype::Voice {
mailimf_fields_add(
imf_fields,
mailimf_field_new_custom(
@@ -1179,7 +1178,7 @@ unsafe fn build_body_file(
let mut filename_encoded = 0 as *mut libc::c_char;
if !pathNfilename.is_null() {
if (*msg).type_0 == DC_MSG_VOICE {
if (*msg).type_0 == Viewtype::Voice {
let ts = chrono::Utc.timestamp((*msg).timestamp_sort as i64, 0);
let suffix = if !suffix.is_null() {
@@ -1191,9 +1190,9 @@ unsafe fn build_body_file(
.format(&format!("voice-message_%Y-%m-%d_%H-%M-%S.{}", suffix))
.to_string();
filename_to_send = to_cstring(res);
} else if (*msg).type_0 == DC_MSG_AUDIO {
} else if (*msg).type_0 == Viewtype::Audio {
filename_to_send = dc_get_filename(pathNfilename)
} else if (*msg).type_0 == DC_MSG_IMAGE || (*msg).type_0 == DC_MSG_GIF {
} else if (*msg).type_0 == Viewtype::Image || (*msg).type_0 == Viewtype::Gif {
if base_name.is_null() {
base_name = b"image\x00" as *const u8 as *const libc::c_char
}
@@ -1206,7 +1205,7 @@ unsafe fn build_body_file(
b"dat\x00" as *const u8 as *const libc::c_char
},
)
} else if (*msg).type_0 == DC_MSG_VIDEO {
} else if (*msg).type_0 == Viewtype::Video {
filename_to_send = dc_mprintf(
b"video.%s\x00" as *const u8 as *const libc::c_char,
if !suffix.is_null() {

View File

@@ -25,7 +25,7 @@ pub struct dc_msg_t<'a> {
pub to_id: uint32_t,
pub chat_id: uint32_t,
pub move_state: dc_move_state_t,
pub type_0: libc::c_int,
pub type_0: Viewtype,
pub state: libc::c_int,
pub hidden: libc::c_int,
pub timestamp_sort: i64,
@@ -177,15 +177,15 @@ pub unsafe fn dc_get_msg_info(context: &Context, msg_id: u32) -> *mut libc::c_ch
}
free(p as *mut libc::c_void);
if (*msg).type_0 != DC_MSG_TEXT {
if (*msg).type_0 != Viewtype::Text {
ret += "Type: ";
match (*msg).type_0 {
DC_MSG_AUDIO => ret += "Audio",
DC_MSG_FILE => ret += "File",
DC_MSG_GIF => ret += "GIF",
DC_MSG_IMAGE => ret += "Image",
DC_MSG_VIDEO => ret += "Video",
DC_MSG_VOICE => ret += "Voice",
Viewtype::Audio => ret += "Audio",
Viewtype::File => ret += "File",
Viewtype::Gif => ret += "GIF",
Viewtype::Image => ret += "Image",
Viewtype::Video => ret += "Video",
Viewtype::Voice => ret += "Voice",
_ => ret += &format!("{}", (*msg).type_0),
}
ret += "\n";
@@ -222,7 +222,7 @@ pub unsafe fn dc_get_msg_info(context: &Context, msg_id: u32) -> *mut libc::c_ch
}
pub unsafe fn dc_msg_new_untyped<'a>(context: &'a Context) -> *mut dc_msg_t<'a> {
dc_msg_new(context, 0i32)
dc_msg_new(context, Viewtype::Unknown)
}
/* *
@@ -235,7 +235,7 @@ pub unsafe fn dc_msg_new_untyped<'a>(context: &'a Context) -> *mut dc_msg_t<'a>
// to check if a mail was sent, use dc_msg_is_sent()
// approx. max. length returned by dc_msg_get_text()
// approx. max. length returned by dc_get_msg_info()
pub unsafe fn dc_msg_new<'a>(context: &'a Context, viewtype: libc::c_int) -> *mut dc_msg_t<'a> {
pub unsafe fn dc_msg_new<'a>(context: &'a Context, viewtype: Viewtype) -> *mut dc_msg_t<'a> {
let msg = dc_msg_t {
magic: 0x11561156,
id: 0,
@@ -301,7 +301,7 @@ pub unsafe fn dc_msg_get_filemime(msg: *const dc_msg_t) -> *mut libc::c_char {
None => {
if let Some(file) = (*msg).param.get(Param::File) {
let file_c = to_cstring(file);
dc_msg_guess_msgtype_from_suffix(file_c, 0 as *mut libc::c_int, &mut ret);
dc_msg_guess_msgtype_from_suffix(file_c, 0 as *mut Viewtype, &mut ret);
if ret.is_null() {
ret = dc_strdup(
b"application/octet-stream\x00" as *const u8 as *const libc::c_char,
@@ -323,11 +323,11 @@ pub unsafe fn dc_msg_get_filemime(msg: *const dc_msg_t) -> *mut libc::c_char {
#[allow(non_snake_case)]
pub unsafe fn dc_msg_guess_msgtype_from_suffix(
pathNfilename: *const libc::c_char,
mut ret_msgtype: *mut libc::c_int,
mut ret_msgtype: *mut Viewtype,
mut ret_mime: *mut *mut libc::c_char,
) {
let mut suffix: *mut libc::c_char = 0 as *mut libc::c_char;
let mut dummy_msgtype: libc::c_int = 0;
let mut dummy_msgtype = Viewtype::Unknown;
let mut dummy_buf: *mut libc::c_char = 0 as *mut libc::c_char;
if !pathNfilename.is_null() {
if ret_msgtype.is_null() {
@@ -336,37 +336,37 @@ pub unsafe fn dc_msg_guess_msgtype_from_suffix(
if ret_mime.is_null() {
ret_mime = &mut dummy_buf
}
*ret_msgtype = 0;
*ret_msgtype = Viewtype::Unknown;
*ret_mime = 0 as *mut libc::c_char;
suffix = dc_get_filesuffix_lc(pathNfilename);
if !suffix.is_null() {
if strcmp(suffix, b"mp3\x00" as *const u8 as *const libc::c_char) == 0i32 {
*ret_msgtype = DC_MSG_AUDIO;
*ret_msgtype = Viewtype::Audio;
*ret_mime = dc_strdup(b"audio/mpeg\x00" as *const u8 as *const libc::c_char)
} else if strcmp(suffix, b"aac\x00" as *const u8 as *const libc::c_char) == 0i32 {
*ret_msgtype = DC_MSG_AUDIO;
*ret_msgtype = Viewtype::Audio;
*ret_mime = dc_strdup(b"audio/aac\x00" as *const u8 as *const libc::c_char)
} else if strcmp(suffix, b"mp4\x00" as *const u8 as *const libc::c_char) == 0i32 {
*ret_msgtype = DC_MSG_VIDEO;
*ret_msgtype = Viewtype::Video;
*ret_mime = dc_strdup(b"video/mp4\x00" as *const u8 as *const libc::c_char)
} else if strcmp(suffix, b"jpg\x00" as *const u8 as *const libc::c_char) == 0i32
|| strcmp(suffix, b"jpeg\x00" as *const u8 as *const libc::c_char) == 0i32
{
*ret_msgtype = DC_MSG_IMAGE;
*ret_msgtype = Viewtype::Image;
*ret_mime = dc_strdup(b"image/jpeg\x00" as *const u8 as *const libc::c_char)
} else if strcmp(suffix, b"png\x00" as *const u8 as *const libc::c_char) == 0i32 {
*ret_msgtype = DC_MSG_IMAGE;
*ret_msgtype = Viewtype::Image;
*ret_mime = dc_strdup(b"image/png\x00" as *const u8 as *const libc::c_char)
} else if strcmp(suffix, b"webp\x00" as *const u8 as *const libc::c_char) == 0i32 {
*ret_msgtype = DC_MSG_IMAGE;
*ret_msgtype = Viewtype::Image;
*ret_mime = dc_strdup(b"image/webp\x00" as *const u8 as *const libc::c_char)
} else if strcmp(suffix, b"gif\x00" as *const u8 as *const libc::c_char) == 0i32 {
*ret_msgtype = DC_MSG_GIF;
*ret_msgtype = Viewtype::Gif;
*ret_mime = dc_strdup(b"image/gif\x00" as *const u8 as *const libc::c_char)
} else if strcmp(suffix, b"vcf\x00" as *const u8 as *const libc::c_char) == 0i32
|| strcmp(suffix, b"vcard\x00" as *const u8 as *const libc::c_char) == 0i32
{
*ret_msgtype = DC_MSG_FILE;
*ret_msgtype = Viewtype::File;
*ret_mime = dc_strdup(b"text/vcard\x00" as *const u8 as *const libc::c_char)
}
}
@@ -681,9 +681,9 @@ pub unsafe fn dc_msg_get_chat_id(msg: *const dc_msg_t) -> uint32_t {
};
}
pub unsafe fn dc_msg_get_viewtype(msg: *const dc_msg_t) -> libc::c_int {
pub unsafe fn dc_msg_get_viewtype(msg: *const dc_msg_t) -> Viewtype {
if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint {
return 0i32;
return Viewtype::Unknown;
}
(*msg).type_0
@@ -853,7 +853,7 @@ pub unsafe fn dc_msg_get_summarytext(
/* the returned value must be free()'d */
#[allow(non_snake_case)]
pub unsafe fn dc_msg_get_summarytext_by_raw(
type_0: libc::c_int,
type_0: Viewtype,
text: *const libc::c_char,
param: &mut Params,
approx_characters: libc::c_int,
@@ -866,11 +866,11 @@ pub unsafe fn dc_msg_get_summarytext_by_raw(
let mut value: *mut libc::c_char = 0 as *mut libc::c_char;
let mut append_text: libc::c_int = 1i32;
match type_0 {
20 => prefix = to_cstring(context.stock_str(StockMessage::Image)),
21 => prefix = to_cstring(context.stock_str(StockMessage::Gif)),
50 => prefix = to_cstring(context.stock_str(StockMessage::Video)),
41 => prefix = to_cstring(context.stock_str(StockMessage::VoiceMessage)),
40 | 60 => {
Viewtype::Image => prefix = to_cstring(context.stock_str(StockMessage::Image)),
Viewtype::Gif => prefix = to_cstring(context.stock_str(StockMessage::Gif)),
Viewtype::Video => prefix = to_cstring(context.stock_str(StockMessage::Video)),
Viewtype::Voice => prefix = to_cstring(context.stock_str(StockMessage::VoiceMessage)),
Viewtype::Audio | Viewtype::File => {
if param.get_int(Param::Cmd) == Some(6) {
prefix = to_cstring(context.stock_str(StockMessage::AcSetupMsgSubject));
append_text = 0i32
@@ -879,7 +879,7 @@ pub unsafe fn dc_msg_get_summarytext_by_raw(
value = dc_get_filename(pathNfilename);
let label = CString::new(
context
.stock_str(if type_0 == DC_MSG_AUDIO {
.stock_str(if type_0 == Viewtype::Audio {
StockMessage::Audio
} else {
StockMessage::File
@@ -1000,7 +1000,7 @@ pub unsafe fn dc_msg_is_increation(msg: *const dc_msg_t) -> libc::c_int {
pub unsafe fn dc_msg_is_setupmessage(msg: *const dc_msg_t) -> bool {
if msg.is_null()
|| (*msg).magic != 0x11561156i32 as libc::c_uint
|| (*msg).type_0 != DC_MSG_FILE as libc::c_int
|| (*msg).type_0 != Viewtype::File
{
return false;
}
@@ -1442,7 +1442,7 @@ mod tests {
#[test]
fn test_dc_msg_guess_msgtype_from_suffix() {
unsafe {
let mut type_0: libc::c_int = 0;
let mut type_0 = Viewtype::Unknown;
let mut mime_0: *mut libc::c_char = 0 as *mut libc::c_char;
dc_msg_guess_msgtype_from_suffix(
@@ -1450,7 +1450,7 @@ mod tests {
&mut type_0,
&mut mime_0,
);
assert_eq!(type_0, DC_MSG_AUDIO as libc::c_int);
assert_eq!(type_0, Viewtype::Audio);
assert_eq!(as_str(mime_0 as *const libc::c_char), "audio/mpeg");
free(mime_0 as *mut libc::c_void);
@@ -1459,7 +1459,7 @@ mod tests {
&mut type_0,
&mut mime_0,
);
assert_eq!(type_0, DC_MSG_AUDIO as libc::c_int);
assert_eq!(type_0, Viewtype::Audio);
assert_eq!(as_str(mime_0 as *const libc::c_char), "audio/aac");
free(mime_0 as *mut libc::c_void);
@@ -1468,7 +1468,7 @@ mod tests {
&mut type_0,
&mut mime_0,
);
assert_eq!(type_0, DC_MSG_VIDEO as libc::c_int);
assert_eq!(type_0, Viewtype::Video);
assert_eq!(as_str(mime_0 as *const libc::c_char), "video/mp4");
free(mime_0 as *mut libc::c_void);
@@ -1477,7 +1477,7 @@ mod tests {
&mut type_0,
&mut mime_0,
);
assert_eq!(type_0, DC_MSG_IMAGE as libc::c_int);
assert_eq!(type_0, Viewtype::Image);
assert_eq!(
CStr::from_ptr(mime_0 as *const libc::c_char)
.to_str()
@@ -1491,7 +1491,7 @@ mod tests {
&mut type_0,
&mut mime_0,
);
assert_eq!(type_0, DC_MSG_IMAGE as libc::c_int);
assert_eq!(type_0, Viewtype::Image);
assert_eq!(
CStr::from_ptr(mime_0 as *const libc::c_char)
.to_str()
@@ -1505,7 +1505,7 @@ mod tests {
&mut type_0,
&mut mime_0,
);
assert_eq!(type_0, DC_MSG_IMAGE as libc::c_int);
assert_eq!(type_0, Viewtype::Image);
assert_eq!(
CStr::from_ptr(mime_0 as *const libc::c_char)
.to_str()
@@ -1519,7 +1519,7 @@ mod tests {
&mut type_0,
&mut mime_0,
);
assert_eq!(type_0, DC_MSG_IMAGE as libc::c_int);
assert_eq!(type_0, Viewtype::Image);
assert_eq!(
CStr::from_ptr(mime_0 as *const libc::c_char)
.to_str()
@@ -1533,7 +1533,7 @@ mod tests {
&mut type_0,
&mut mime_0,
);
assert_eq!(type_0, DC_MSG_GIF as libc::c_int);
assert_eq!(type_0, Viewtype::Gif);
assert_eq!(
CStr::from_ptr(mime_0 as *const libc::c_char)
.to_str()
@@ -1547,7 +1547,7 @@ mod tests {
&mut type_0,
&mut mime_0,
);
assert_eq!(type_0, DC_MSG_FILE as libc::c_int);
assert_eq!(type_0, Viewtype::File);
assert_eq!(
CStr::from_ptr(mime_0 as *const libc::c_char)
.to_str()

View File

@@ -263,7 +263,7 @@ unsafe fn send_handshake_msg(
grpid: *const libc::c_char,
) {
let mut msg: *mut dc_msg_t = dc_msg_new_untyped(context);
(*msg).type_0 = DC_MSG_TEXT;
(*msg).type_0 = Viewtype::Text;
(*msg).text = dc_mprintf(
b"Secure-Join: %s\x00" as *const u8 as *const libc::c_char,
step,