1#![recursion_limit = "256"]
2#![warn(unused, clippy::all)]
3#![allow(
4 non_camel_case_types,
5 non_snake_case,
6 non_upper_case_globals,
7 clippy::missing_safety_doc,
8 clippy::expect_fun_call
9)]
10
11#[macro_use]
12extern crate human_panic;
13
14use std::collections::BTreeMap;
15use std::convert::TryFrom;
16use std::fmt::Write;
17use std::future::Future;
18use std::ops::Deref;
19use std::ptr;
20use std::str::FromStr;
21use std::sync::{Arc, LazyLock};
22use std::time::{Duration, SystemTime};
23
24use anyhow::Context as _;
25use deltachat::chat::{ChatId, ChatVisibility, MessageListOptions, MuteDuration};
26use deltachat::constants::DC_MSG_ID_LAST_SPECIAL;
27use deltachat::contact::{Contact, ContactId, Origin};
28use deltachat::context::{Context, ContextBuilder};
29use deltachat::ephemeral::Timer as EphemeralTimer;
30use deltachat::imex::BackupProvider;
31use deltachat::key::preconfigure_keypair;
32use deltachat::message::MsgId;
33use deltachat::qr_code_generator::{create_qr_svg, generate_backup_qr, get_securejoin_qr_svg};
34use deltachat::stock_str::StockMessage;
35use deltachat::webxdc::StatusUpdateSerial;
36use deltachat::*;
37use deltachat::{accounts::Accounts, log::LogExt};
38use deltachat_jsonrpc::api::CommandApi;
39use deltachat_jsonrpc::yerpc::{OutReceiver, RpcClient, RpcSession};
40use message::Viewtype;
41use num_traits::{FromPrimitive, ToPrimitive};
42use tokio::runtime::Runtime;
43use tokio::sync::RwLock;
44use tokio::task::JoinHandle;
45
46mod dc_array;
47mod lot;
48
49mod string;
50use deltachat::chatlist::Chatlist;
51
52use self::string::*;
53
54const DC_GCM_ADDDAYMARKER: u32 = 0x01;
63const DC_GCM_INFO_ONLY: u32 = 0x02;
64
65pub type dc_context_t = Context;
69
70static RT: LazyLock<Runtime> =
71 LazyLock::new(|| Runtime::new().expect("unable to create tokio runtime"));
72
73fn block_on<T>(fut: T) -> T::Output
74where
75 T: Future,
76{
77 RT.block_on(fut)
78}
79
80fn spawn<T>(fut: T) -> JoinHandle<T::Output>
81where
82 T: Future + Send + 'static,
83 T::Output: Send + 'static,
84{
85 RT.spawn(fut)
86}
87
88#[no_mangle]
89pub unsafe extern "C" fn dc_context_new(
90 _os_name: *const libc::c_char,
91 dbfile: *const libc::c_char,
92 blobdir: *const libc::c_char,
93) -> *mut dc_context_t {
94 setup_panic!();
95
96 if dbfile.is_null() {
97 eprintln!("ignoring careless call to dc_context_new()");
98 return ptr::null_mut();
99 }
100
101 let ctx = if blobdir.is_null() || *blobdir == 0 {
102 let id = rand::random();
104 block_on(
105 ContextBuilder::new(as_path(dbfile).to_path_buf())
106 .with_id(id)
107 .open(),
108 )
109 } else {
110 eprintln!("blobdir can not be defined explicitly anymore");
111 return ptr::null_mut();
112 };
113 match ctx {
114 Ok(ctx) => Box::into_raw(Box::new(ctx)),
115 Err(err) => {
116 eprintln!("failed to create context: {err:#}");
117 ptr::null_mut()
118 }
119 }
120}
121
122#[no_mangle]
123pub unsafe extern "C" fn dc_context_new_closed(dbfile: *const libc::c_char) -> *mut dc_context_t {
124 setup_panic!();
125
126 if dbfile.is_null() {
127 eprintln!("ignoring careless call to dc_context_new_closed()");
128 return ptr::null_mut();
129 }
130
131 let id = rand::random();
132 match block_on(
133 ContextBuilder::new(as_path(dbfile).to_path_buf())
134 .with_id(id)
135 .build(),
136 ) {
137 Ok(context) => Box::into_raw(Box::new(context)),
138 Err(err) => {
139 eprintln!("failed to create context: {err:#}");
140 ptr::null_mut()
141 }
142 }
143}
144
145#[no_mangle]
146pub unsafe extern "C" fn dc_context_open(
147 context: *mut dc_context_t,
148 passphrase: *const libc::c_char,
149) -> libc::c_int {
150 if context.is_null() {
151 eprintln!("ignoring careless call to dc_context_open()");
152 return 0;
153 }
154
155 let ctx = &*context;
156 let passphrase = to_string_lossy(passphrase);
157 block_on(ctx.open(passphrase))
158 .context("dc_context_open() failed")
159 .log_err(ctx)
160 .map(|b| b as libc::c_int)
161 .unwrap_or(0)
162}
163
164#[no_mangle]
165pub unsafe extern "C" fn dc_context_change_passphrase(
166 context: *mut dc_context_t,
167 passphrase: *const libc::c_char,
168) -> libc::c_int {
169 if context.is_null() {
170 eprintln!("ignoring careless call to dc_context_change_passphrase()");
171 return 0;
172 }
173
174 let ctx = &*context;
175 let passphrase = to_string_lossy(passphrase);
176 block_on(ctx.change_passphrase(passphrase))
177 .context("dc_context_change_passphrase() failed")
178 .log_err(ctx)
179 .is_ok() as libc::c_int
180}
181
182#[no_mangle]
183pub unsafe extern "C" fn dc_context_is_open(context: *mut dc_context_t) -> libc::c_int {
184 if context.is_null() {
185 eprintln!("ignoring careless call to dc_context_is_open()");
186 return 0;
187 }
188
189 let ctx = &*context;
190 block_on(ctx.is_open()) as libc::c_int
191}
192
193#[no_mangle]
197pub unsafe extern "C" fn dc_context_unref(context: *mut dc_context_t) {
198 if context.is_null() {
199 eprintln!("ignoring careless call to dc_context_unref()");
200 return;
201 }
202 drop(Box::from_raw(context));
203}
204
205#[no_mangle]
206pub unsafe extern "C" fn dc_get_blobdir(context: *mut dc_context_t) -> *mut libc::c_char {
207 if context.is_null() {
208 eprintln!("ignoring careless call to dc_get_blobdir()");
209 return "".strdup();
210 }
211 let ctx = &*context;
212 ctx.get_blobdir().to_string_lossy().strdup()
213}
214
215#[no_mangle]
216pub unsafe extern "C" fn dc_set_config(
217 context: *mut dc_context_t,
218 key: *const libc::c_char,
219 value: *const libc::c_char,
220) -> libc::c_int {
221 if context.is_null() || key.is_null() {
222 eprintln!("ignoring careless call to dc_set_config()");
223 return 0;
224 }
225 let ctx = &*context;
226 let key = to_string_lossy(key);
227 let value = to_opt_string_lossy(value);
228
229 block_on(async move {
230 if key.starts_with("ui.") {
231 ctx.set_ui_config(&key, value.as_deref())
232 .await
233 .with_context(|| format!("dc_set_config failed: Can't set {key} to {value:?}"))
234 .log_err(ctx)
235 .is_ok() as libc::c_int
236 } else {
237 match config::Config::from_str(&key)
238 .context("Invalid config key")
239 .log_err(ctx)
240 {
241 Ok(key) => ctx
242 .set_config(key, value.as_deref())
243 .await
244 .with_context(|| {
245 format!("dc_set_config() failed: Can't set {key} to {value:?}")
246 })
247 .log_err(ctx)
248 .is_ok() as libc::c_int,
249 Err(_) => 0,
250 }
251 }
252 })
253}
254
255#[no_mangle]
256pub unsafe extern "C" fn dc_get_config(
257 context: *mut dc_context_t,
258 key: *const libc::c_char,
259) -> *mut libc::c_char {
260 if context.is_null() || key.is_null() {
261 eprintln!("ignoring careless call to dc_get_config()");
262 return "".strdup();
263 }
264 let ctx = &*context;
265
266 let key = to_string_lossy(key);
267
268 block_on(async move {
269 if key.starts_with("ui.") {
270 ctx.get_ui_config(&key)
271 .await
272 .context("Can't get ui-config")
273 .log_err(ctx)
274 .unwrap_or_default()
275 .unwrap_or_default()
276 .strdup()
277 } else {
278 match config::Config::from_str(&key)
279 .with_context(|| format!("Invalid key {:?}", &key))
280 .log_err(ctx)
281 {
282 Ok(key) => ctx
283 .get_config(key)
284 .await
285 .context("Can't get config")
286 .log_err(ctx)
287 .unwrap_or_default()
288 .unwrap_or_default()
289 .strdup(),
290 Err(_) => "".strdup(),
291 }
292 }
293 })
294}
295
296#[no_mangle]
297pub unsafe extern "C" fn dc_set_stock_translation(
298 context: *mut dc_context_t,
299 stock_id: u32,
300 stock_msg: *mut libc::c_char,
301) -> libc::c_int {
302 if context.is_null() || stock_msg.is_null() {
303 eprintln!("ignoring careless call to dc_set_stock_string");
304 return 0;
305 }
306 let msg = to_string_lossy(stock_msg);
307 let ctx = &*context;
308
309 block_on(async move {
310 match StockMessage::from_u32(stock_id)
311 .with_context(|| format!("Invalid stock message ID {stock_id}"))
312 .log_err(ctx)
313 {
314 Ok(id) => ctx
315 .set_stock_translation(id, msg)
316 .await
317 .context("set_stock_translation failed")
318 .log_err(ctx)
319 .is_ok() as libc::c_int,
320 Err(_) => 0,
321 }
322 })
323}
324
325#[no_mangle]
326pub unsafe extern "C" fn dc_set_config_from_qr(
327 context: *mut dc_context_t,
328 qr: *mut libc::c_char,
329) -> libc::c_int {
330 if context.is_null() || qr.is_null() {
331 eprintln!("ignoring careless call to dc_set_config_from_qr");
332 return 0;
333 }
334 let qr = to_string_lossy(qr);
335 let ctx = &*context;
336
337 block_on(qr::set_config_from_qr(ctx, &qr))
338 .context("Failed to create account from QR code")
339 .log_err(ctx)
340 .is_ok() as libc::c_int
341}
342
343#[no_mangle]
344pub unsafe extern "C" fn dc_get_info(context: *const dc_context_t) -> *mut libc::c_char {
345 if context.is_null() {
346 eprintln!("ignoring careless call to dc_get_info()");
347 return "".strdup();
348 }
349 let ctx = &*context;
350 match block_on(ctx.get_info())
351 .context("Failed to get info")
352 .log_err(ctx)
353 {
354 Ok(info) => render_info(info).unwrap_or_default().strdup(),
355 Err(_) => "".strdup(),
356 }
357}
358
359fn render_info(
360 info: BTreeMap<&'static str, String>,
361) -> std::result::Result<String, std::fmt::Error> {
362 let mut res = String::new();
363 for (key, value) in &info {
364 writeln!(&mut res, "{key}={value}")?;
365 }
366
367 Ok(res)
368}
369
370#[no_mangle]
371pub unsafe extern "C" fn dc_get_connectivity(context: *const dc_context_t) -> libc::c_int {
372 if context.is_null() {
373 eprintln!("ignoring careless call to dc_get_connectivity()");
374 return 0;
375 }
376 let ctx = &*context;
377 ctx.get_connectivity() as u32 as libc::c_int
378}
379
380#[no_mangle]
381pub unsafe extern "C" fn dc_get_connectivity_html(
382 context: *const dc_context_t,
383) -> *mut libc::c_char {
384 if context.is_null() {
385 eprintln!("ignoring careless call to dc_get_connectivity_html()");
386 return "".strdup();
387 }
388 let ctx = &*context;
389 match block_on(ctx.get_connectivity_html())
390 .context("Failed to get connectivity html")
391 .log_err(ctx)
392 {
393 Ok(html) => html.strdup(),
394 Err(_) => "".strdup(),
395 }
396}
397
398#[no_mangle]
399pub unsafe extern "C" fn dc_get_push_state(context: *const dc_context_t) -> libc::c_int {
400 if context.is_null() {
401 eprintln!("ignoring careless call to dc_get_push_state()");
402 return 0;
403 }
404 let ctx = &*context;
405 block_on(ctx.push_state()) as libc::c_int
406}
407
408#[no_mangle]
409pub unsafe extern "C" fn dc_get_oauth2_url(
410 context: *mut dc_context_t,
411 addr: *const libc::c_char,
412 redirect: *const libc::c_char,
413) -> *mut libc::c_char {
414 if context.is_null() {
415 eprintln!("ignoring careless call to dc_get_oauth2_url()");
416 return ptr::null_mut(); }
418 let ctx = &*context;
419 let addr = to_string_lossy(addr);
420 let redirect = to_string_lossy(redirect);
421
422 block_on(async move {
423 match oauth2::get_oauth2_url(ctx, &addr, &redirect)
424 .await
425 .context("dc_get_oauth2_url failed")
426 .log_err(ctx)
427 {
428 Ok(Some(res)) => res.strdup(),
429 Ok(None) | Err(_) => ptr::null_mut(),
430 }
431 })
432}
433
434fn spawn_configure(ctx: Context) {
435 spawn(async move {
436 ctx.configure()
437 .await
438 .context("Configure failed")
439 .log_err(&ctx)
440 });
441}
442
443#[no_mangle]
444pub unsafe extern "C" fn dc_configure(context: *mut dc_context_t) {
445 if context.is_null() {
446 eprintln!("ignoring careless call to dc_configure()");
447 return;
448 }
449
450 let ctx = &*context;
451 spawn_configure(ctx.clone());
452}
453
454#[no_mangle]
455pub unsafe extern "C" fn dc_is_configured(context: *mut dc_context_t) -> libc::c_int {
456 if context.is_null() {
457 eprintln!("ignoring careless call to dc_is_configured()");
458 return 0;
459 }
460 let ctx = &*context;
461
462 block_on(async move {
463 ctx.is_configured()
464 .await
465 .context("failed to get configured state")
466 .log_err(ctx)
467 .unwrap_or_default() as libc::c_int
468 })
469}
470
471#[no_mangle]
472pub unsafe extern "C" fn dc_start_io(context: *mut dc_context_t) {
473 if context.is_null() {
474 return;
475 }
476 let ctx = &mut *context;
477
478 block_on(ctx.start_io())
479}
480
481#[no_mangle]
482pub unsafe extern "C" fn dc_get_id(context: *mut dc_context_t) -> libc::c_int {
483 if context.is_null() {
484 return 0;
485 }
486 let ctx = &*context;
487
488 ctx.get_id() as libc::c_int
489}
490
491pub type dc_event_t = Event;
492
493#[no_mangle]
494pub unsafe extern "C" fn dc_event_unref(a: *mut dc_event_t) {
495 if a.is_null() {
496 eprintln!("ignoring careless call to dc_event_unref()");
497 return;
498 }
499
500 drop(Box::from_raw(a));
501}
502
503#[no_mangle]
504pub unsafe extern "C" fn dc_event_get_id(event: *mut dc_event_t) -> libc::c_int {
505 if event.is_null() {
506 eprintln!("ignoring careless call to dc_event_get_id()");
507 return 0;
508 }
509
510 let event = &*event;
511 match event.typ {
512 EventType::Info(_) => 100,
513 EventType::SmtpConnected(_) => 101,
514 EventType::ImapConnected(_) => 102,
515 EventType::SmtpMessageSent(_) => 103,
516 EventType::ImapMessageDeleted(_) => 104,
517 EventType::ImapMessageMoved(_) => 105,
518 EventType::ImapInboxIdle => 106,
519 EventType::NewBlobFile(_) => 150,
520 EventType::DeletedBlobFile(_) => 151,
521 EventType::Warning(_) => 300,
522 EventType::Error(_) => 400,
523 EventType::ErrorSelfNotInGroup(_) => 410,
524 EventType::MsgsChanged { .. } => 2000,
525 EventType::ReactionsChanged { .. } => 2001,
526 EventType::IncomingReaction { .. } => 2002,
527 EventType::IncomingWebxdcNotify { .. } => 2003,
528 EventType::IncomingMsg { .. } => 2005,
529 EventType::IncomingMsgBunch => 2006,
530 EventType::MsgsNoticed { .. } => 2008,
531 EventType::MsgDelivered { .. } => 2010,
532 EventType::MsgFailed { .. } => 2012,
533 EventType::MsgRead { .. } => 2015,
534 EventType::MsgDeleted { .. } => 2016,
535 EventType::ChatModified(_) => 2020,
536 EventType::ChatEphemeralTimerModified { .. } => 2021,
537 EventType::ChatDeleted { .. } => 2023,
538 EventType::ContactsChanged(_) => 2030,
539 EventType::LocationChanged(_) => 2035,
540 EventType::ConfigureProgress { .. } => 2041,
541 EventType::ImexProgress(_) => 2051,
542 EventType::ImexFileWritten(_) => 2052,
543 EventType::SecurejoinInviterProgress { .. } => 2060,
544 EventType::SecurejoinJoinerProgress { .. } => 2061,
545 EventType::ConnectivityChanged => 2100,
546 EventType::SelfavatarChanged => 2110,
547 EventType::ConfigSynced { .. } => 2111,
548 EventType::WebxdcStatusUpdate { .. } => 2120,
549 EventType::WebxdcInstanceDeleted { .. } => 2121,
550 EventType::WebxdcRealtimeData { .. } => 2150,
551 EventType::WebxdcRealtimeAdvertisementReceived { .. } => 2151,
552 EventType::AccountsBackgroundFetchDone => 2200,
553 EventType::ChatlistChanged => 2300,
554 EventType::ChatlistItemChanged { .. } => 2301,
555 EventType::AccountsChanged => 2302,
556 EventType::AccountsItemChanged => 2303,
557 EventType::EventChannelOverflow { .. } => 2400,
558 EventType::IncomingCall { .. } => 2550,
559 EventType::IncomingCallAccepted { .. } => 2560,
560 EventType::OutgoingCallAccepted { .. } => 2570,
561 EventType::CallEnded { .. } => 2580,
562 EventType::TransportsModified => 2600,
563 #[allow(unreachable_patterns)]
564 #[cfg(test)]
565 _ => unreachable!("This is just to silence a rust_analyzer false-positive"),
566 }
567}
568
569#[no_mangle]
570pub unsafe extern "C" fn dc_event_get_data1_int(event: *mut dc_event_t) -> libc::c_int {
571 if event.is_null() {
572 eprintln!("ignoring careless call to dc_event_get_data1_int()");
573 return 0;
574 }
575
576 let event = &(*event).typ;
577 match event {
578 EventType::Info(_)
579 | EventType::SmtpConnected(_)
580 | EventType::ImapConnected(_)
581 | EventType::SmtpMessageSent(_)
582 | EventType::ImapMessageDeleted(_)
583 | EventType::ImapMessageMoved(_)
584 | EventType::ImapInboxIdle
585 | EventType::NewBlobFile(_)
586 | EventType::DeletedBlobFile(_)
587 | EventType::Warning(_)
588 | EventType::Error(_)
589 | EventType::ConnectivityChanged
590 | EventType::SelfavatarChanged
591 | EventType::ConfigSynced { .. }
592 | EventType::IncomingMsgBunch
593 | EventType::ErrorSelfNotInGroup(_)
594 | EventType::AccountsBackgroundFetchDone
595 | EventType::ChatlistChanged
596 | EventType::AccountsChanged
597 | EventType::AccountsItemChanged
598 | EventType::TransportsModified => 0,
599 EventType::IncomingReaction { contact_id, .. }
600 | EventType::IncomingWebxdcNotify { contact_id, .. } => contact_id.to_u32() as libc::c_int,
601 EventType::MsgsChanged { chat_id, .. }
602 | EventType::ReactionsChanged { chat_id, .. }
603 | EventType::IncomingMsg { chat_id, .. }
604 | EventType::MsgsNoticed(chat_id)
605 | EventType::MsgDelivered { chat_id, .. }
606 | EventType::MsgFailed { chat_id, .. }
607 | EventType::MsgRead { chat_id, .. }
608 | EventType::MsgDeleted { chat_id, .. }
609 | EventType::ChatModified(chat_id)
610 | EventType::ChatEphemeralTimerModified { chat_id, .. }
611 | EventType::ChatDeleted { chat_id } => chat_id.to_u32() as libc::c_int,
612 EventType::ContactsChanged(id) | EventType::LocationChanged(id) => {
613 let id = id.unwrap_or_default();
614 id.to_u32() as libc::c_int
615 }
616 EventType::ConfigureProgress { progress, .. } | EventType::ImexProgress(progress) => {
617 *progress as libc::c_int
618 }
619 EventType::ImexFileWritten(_) => 0,
620 EventType::SecurejoinInviterProgress { contact_id, .. }
621 | EventType::SecurejoinJoinerProgress { contact_id, .. } => {
622 contact_id.to_u32() as libc::c_int
623 }
624 EventType::WebxdcRealtimeData { msg_id, .. }
625 | EventType::WebxdcStatusUpdate { msg_id, .. }
626 | EventType::WebxdcRealtimeAdvertisementReceived { msg_id }
627 | EventType::WebxdcInstanceDeleted { msg_id, .. }
628 | EventType::IncomingCall { msg_id, .. }
629 | EventType::IncomingCallAccepted { msg_id, .. }
630 | EventType::OutgoingCallAccepted { msg_id, .. }
631 | EventType::CallEnded { msg_id, .. } => msg_id.to_u32() as libc::c_int,
632 EventType::ChatlistItemChanged { chat_id } => {
633 chat_id.unwrap_or_default().to_u32() as libc::c_int
634 }
635 EventType::EventChannelOverflow { n } => *n as libc::c_int,
636 #[allow(unreachable_patterns)]
637 #[cfg(test)]
638 _ => unreachable!("This is just to silence a rust_analyzer false-positive"),
639 }
640}
641
642#[no_mangle]
643pub unsafe extern "C" fn dc_event_get_data2_int(event: *mut dc_event_t) -> libc::c_int {
644 if event.is_null() {
645 eprintln!("ignoring careless call to dc_event_get_data2_int()");
646 return 0;
647 }
648
649 let event = &(*event).typ;
650
651 match event {
652 EventType::Info(_)
653 | EventType::SmtpConnected(_)
654 | EventType::ImapConnected(_)
655 | EventType::SmtpMessageSent(_)
656 | EventType::ImapMessageDeleted(_)
657 | EventType::ImapMessageMoved(_)
658 | EventType::ImapInboxIdle
659 | EventType::NewBlobFile(_)
660 | EventType::DeletedBlobFile(_)
661 | EventType::Warning(_)
662 | EventType::Error(_)
663 | EventType::ErrorSelfNotInGroup(_)
664 | EventType::ContactsChanged(_)
665 | EventType::LocationChanged(_)
666 | EventType::ConfigureProgress { .. }
667 | EventType::ImexProgress(_)
668 | EventType::ImexFileWritten(_)
669 | EventType::MsgsNoticed(_)
670 | EventType::ConnectivityChanged
671 | EventType::WebxdcInstanceDeleted { .. }
672 | EventType::IncomingMsgBunch
673 | EventType::SelfavatarChanged
674 | EventType::AccountsBackgroundFetchDone
675 | EventType::ChatlistChanged
676 | EventType::ChatlistItemChanged { .. }
677 | EventType::AccountsChanged
678 | EventType::AccountsItemChanged
679 | EventType::ConfigSynced { .. }
680 | EventType::ChatModified(_)
681 | EventType::ChatDeleted { .. }
682 | EventType::WebxdcRealtimeAdvertisementReceived { .. }
683 | EventType::IncomingCallAccepted { .. }
684 | EventType::OutgoingCallAccepted { .. }
685 | EventType::CallEnded { .. }
686 | EventType::EventChannelOverflow { .. }
687 | EventType::TransportsModified => 0,
688 EventType::MsgsChanged { msg_id, .. }
689 | EventType::ReactionsChanged { msg_id, .. }
690 | EventType::IncomingReaction { msg_id, .. }
691 | EventType::IncomingWebxdcNotify { msg_id, .. }
692 | EventType::IncomingMsg { msg_id, .. }
693 | EventType::MsgDelivered { msg_id, .. }
694 | EventType::MsgFailed { msg_id, .. }
695 | EventType::MsgRead { msg_id, .. }
696 | EventType::MsgDeleted { msg_id, .. } => msg_id.to_u32() as libc::c_int,
697 EventType::SecurejoinInviterProgress { progress, .. }
698 | EventType::SecurejoinJoinerProgress { progress, .. } => *progress as libc::c_int,
699 EventType::ChatEphemeralTimerModified { timer, .. } => timer.to_u32() as libc::c_int,
700 EventType::WebxdcStatusUpdate {
701 status_update_serial,
702 ..
703 } => status_update_serial.to_u32() as libc::c_int,
704 EventType::WebxdcRealtimeData { data, .. } => data.len() as libc::c_int,
705 EventType::IncomingCall { has_video, .. } => *has_video as libc::c_int,
706
707 #[allow(unreachable_patterns)]
708 #[cfg(test)]
709 _ => unreachable!("This is just to silence a rust_analyzer false-positive"),
710 }
711}
712
713#[no_mangle]
714pub unsafe extern "C" fn dc_event_get_data1_str(event: *mut dc_event_t) -> *mut libc::c_char {
715 if event.is_null() {
716 eprintln!("ignoring careless call to dc_event_get_data1_str()");
717 return ptr::null_mut();
718 }
719
720 let event = &(*event).typ;
721
722 match event {
723 EventType::IncomingWebxdcNotify { href, .. } => {
724 if let Some(href) = href {
725 href.to_c_string().unwrap_or_default().into_raw()
726 } else {
727 ptr::null_mut()
728 }
729 }
730 _ => ptr::null_mut(),
731 }
732}
733
734#[no_mangle]
735pub unsafe extern "C" fn dc_event_get_data2_str(event: *mut dc_event_t) -> *mut libc::c_char {
736 if event.is_null() {
737 eprintln!("ignoring careless call to dc_event_get_data2_str()");
738 return ptr::null_mut();
739 }
740
741 let event = &(*event).typ;
742
743 match event {
744 EventType::Info(msg)
745 | EventType::SmtpConnected(msg)
746 | EventType::ImapConnected(msg)
747 | EventType::SmtpMessageSent(msg)
748 | EventType::ImapMessageDeleted(msg)
749 | EventType::ImapMessageMoved(msg)
750 | EventType::NewBlobFile(msg)
751 | EventType::DeletedBlobFile(msg)
752 | EventType::Warning(msg)
753 | EventType::Error(msg)
754 | EventType::ErrorSelfNotInGroup(msg) => {
755 let data2 = msg.to_c_string().unwrap_or_default();
756 data2.into_raw()
757 }
758 EventType::MsgsChanged { .. }
759 | EventType::ReactionsChanged { .. }
760 | EventType::IncomingMsg { .. }
761 | EventType::ImapInboxIdle
762 | EventType::MsgsNoticed(_)
763 | EventType::MsgDelivered { .. }
764 | EventType::MsgFailed { .. }
765 | EventType::MsgRead { .. }
766 | EventType::MsgDeleted { .. }
767 | EventType::ChatModified(_)
768 | EventType::ContactsChanged(_)
769 | EventType::LocationChanged(_)
770 | EventType::ImexProgress(_)
771 | EventType::SecurejoinInviterProgress { .. }
772 | EventType::SecurejoinJoinerProgress { .. }
773 | EventType::ConnectivityChanged
774 | EventType::SelfavatarChanged
775 | EventType::WebxdcStatusUpdate { .. }
776 | EventType::WebxdcInstanceDeleted { .. }
777 | EventType::AccountsBackgroundFetchDone
778 | EventType::ChatEphemeralTimerModified { .. }
779 | EventType::ChatDeleted { .. }
780 | EventType::IncomingMsgBunch
781 | EventType::ChatlistItemChanged { .. }
782 | EventType::ChatlistChanged
783 | EventType::AccountsChanged
784 | EventType::AccountsItemChanged
785 | EventType::IncomingCallAccepted { .. }
786 | EventType::WebxdcRealtimeAdvertisementReceived { .. }
787 | EventType::TransportsModified => ptr::null_mut(),
788 EventType::IncomingCall {
789 place_call_info, ..
790 } => {
791 let data2 = place_call_info.to_c_string().unwrap_or_default();
792 data2.into_raw()
793 }
794 EventType::OutgoingCallAccepted {
795 accept_call_info, ..
796 } => {
797 let data2 = accept_call_info.to_c_string().unwrap_or_default();
798 data2.into_raw()
799 }
800 EventType::CallEnded { .. } | EventType::EventChannelOverflow { .. } => ptr::null_mut(),
801 EventType::ConfigureProgress { comment, .. } => {
802 if let Some(comment) = comment {
803 comment.to_c_string().unwrap_or_default().into_raw()
804 } else {
805 ptr::null_mut()
806 }
807 }
808 EventType::ImexFileWritten(file) => {
809 let data2 = file.to_c_string().unwrap_or_default();
810 data2.into_raw()
811 }
812 EventType::ConfigSynced { key } => {
813 let data2 = key.to_string().to_c_string().unwrap_or_default();
814 data2.into_raw()
815 }
816 EventType::WebxdcRealtimeData { data, .. } => {
817 let ptr = libc::malloc(data.len());
818 libc::memcpy(ptr, data.as_ptr() as *mut libc::c_void, data.len());
819 ptr as *mut libc::c_char
820 }
821 EventType::IncomingReaction { reaction, .. } => reaction
822 .as_str()
823 .to_c_string()
824 .unwrap_or_default()
825 .into_raw(),
826 EventType::IncomingWebxdcNotify { text, .. } => {
827 text.to_c_string().unwrap_or_default().into_raw()
828 }
829 #[allow(unreachable_patterns)]
830 #[cfg(test)]
831 _ => unreachable!("This is just to silence a rust_analyzer false-positive"),
832 }
833}
834
835#[no_mangle]
836pub unsafe extern "C" fn dc_event_get_account_id(event: *mut dc_event_t) -> u32 {
837 if event.is_null() {
838 eprintln!("ignoring careless call to dc_event_get_account_id()");
839 return 0;
840 }
841
842 (*event).id
843}
844
845pub type dc_event_emitter_t = EventEmitter;
846
847#[no_mangle]
848pub unsafe extern "C" fn dc_get_event_emitter(
849 context: *mut dc_context_t,
850) -> *mut dc_event_emitter_t {
851 if context.is_null() {
852 eprintln!("ignoring careless call to dc_get_event_emitter()");
853 return ptr::null_mut();
854 }
855 let ctx = &*context;
856 Box::into_raw(Box::new(ctx.get_event_emitter()))
857}
858
859#[no_mangle]
860pub unsafe extern "C" fn dc_event_emitter_unref(emitter: *mut dc_event_emitter_t) {
861 if emitter.is_null() {
862 eprintln!("ignoring careless call to dc_event_emitter_unref()");
863 return;
864 }
865
866 drop(Box::from_raw(emitter));
867}
868
869#[no_mangle]
870pub unsafe extern "C" fn dc_get_next_event(events: *mut dc_event_emitter_t) -> *mut dc_event_t {
871 if events.is_null() {
872 eprintln!("ignoring careless call to dc_get_next_event()");
873 return ptr::null_mut();
874 }
875 let events = &*events;
876
877 block_on(async move {
878 events
879 .recv()
880 .await
881 .map(|ev| Box::into_raw(Box::new(ev)))
882 .unwrap_or_else(ptr::null_mut)
883 })
884}
885
886#[no_mangle]
887pub unsafe extern "C" fn dc_stop_io(context: *mut dc_context_t) {
888 if context.is_null() {
889 eprintln!("ignoring careless call to dc_stop_io()");
890 return;
891 }
892 let ctx = &*context;
893
894 block_on(async move {
895 ctx.stop_io().await;
896 })
897}
898
899#[no_mangle]
900pub unsafe extern "C" fn dc_maybe_network(context: *mut dc_context_t) {
901 if context.is_null() {
902 eprintln!("ignoring careless call to dc_maybe_network()");
903 return;
904 }
905 let ctx = &*context;
906
907 block_on(async move { ctx.maybe_network().await })
908}
909
910#[no_mangle]
911pub unsafe extern "C" fn dc_preconfigure_keypair(
912 context: *mut dc_context_t,
913 secret_data: *const libc::c_char,
914) -> i32 {
915 if context.is_null() {
916 eprintln!("ignoring careless call to dc_preconfigure_keypair()");
917 return 0;
918 }
919 let ctx = &*context;
920 let secret_data = to_string_lossy(secret_data);
921 block_on(preconfigure_keypair(ctx, &secret_data))
922 .context("Failed to save keypair")
923 .log_err(ctx)
924 .is_ok() as libc::c_int
925}
926
927#[no_mangle]
928pub unsafe extern "C" fn dc_get_chatlist(
929 context: *mut dc_context_t,
930 flags: libc::c_int,
931 query_str: *const libc::c_char,
932 query_id: u32,
933) -> *mut dc_chatlist_t {
934 if context.is_null() {
935 eprintln!("ignoring careless call to dc_get_chatlist()");
936 return ptr::null_mut();
937 }
938 let ctx = &*context;
939 let qs = to_opt_string_lossy(query_str);
940
941 let qi = if query_id == 0 {
942 None
943 } else {
944 Some(ContactId::new(query_id))
945 };
946
947 block_on(async move {
948 match chatlist::Chatlist::try_load(ctx, flags as usize, qs.as_deref(), qi)
949 .await
950 .context("Failed to get chatlist")
951 .log_err(ctx)
952 {
953 Ok(list) => {
954 let ffi_list = ChatlistWrapper { context, list };
955 Box::into_raw(Box::new(ffi_list))
956 }
957 Err(_) => ptr::null_mut(),
958 }
959 })
960}
961
962#[no_mangle]
963pub unsafe extern "C" fn dc_create_chat_by_contact_id(
964 context: *mut dc_context_t,
965 contact_id: u32,
966) -> u32 {
967 if context.is_null() {
968 eprintln!("ignoring careless call to dc_create_chat_by_contact_id()");
969 return 0;
970 }
971 let ctx = &*context;
972
973 block_on(async move {
974 ChatId::create_for_contact(ctx, ContactId::new(contact_id))
975 .await
976 .context("Failed to create chat from contact_id")
977 .log_err(ctx)
978 .map(|id| id.to_u32())
979 .unwrap_or(0)
980 })
981}
982
983#[no_mangle]
984pub unsafe extern "C" fn dc_get_chat_id_by_contact_id(
985 context: *mut dc_context_t,
986 contact_id: u32,
987) -> u32 {
988 if context.is_null() {
989 eprintln!("ignoring careless call to dc_get_chat_id_by_contact_id()");
990 return 0;
991 }
992 let ctx = &*context;
993
994 block_on(async move {
995 ChatId::lookup_by_contact(ctx, ContactId::new(contact_id))
996 .await
997 .context("Failed to get chat for contact_id")
998 .log_err(ctx)
999 .unwrap_or_default() .map(|id| id.to_u32())
1001 .unwrap_or(0) })
1003}
1004
1005#[no_mangle]
1006pub unsafe extern "C" fn dc_send_msg(
1007 context: *mut dc_context_t,
1008 chat_id: u32,
1009 msg: *mut dc_msg_t,
1010) -> u32 {
1011 if context.is_null() || msg.is_null() {
1012 eprintln!("ignoring careless call to dc_send_msg()");
1013 return 0;
1014 }
1015 let ctx = &mut *context;
1016 let ffi_msg = &mut *msg;
1017
1018 block_on(async move {
1019 chat::send_msg(ctx, ChatId::new(chat_id), &mut ffi_msg.message)
1020 .await
1021 .unwrap_or_log_default(ctx, "Failed to send message")
1022 })
1023 .to_u32()
1024}
1025
1026#[no_mangle]
1027pub unsafe extern "C" fn dc_send_msg_sync(
1028 context: *mut dc_context_t,
1029 chat_id: u32,
1030 msg: *mut dc_msg_t,
1031) -> u32 {
1032 if context.is_null() || msg.is_null() {
1033 eprintln!("ignoring careless call to dc_send_msg_sync()");
1034 return 0;
1035 }
1036 let ctx = &mut *context;
1037 let ffi_msg = &mut *msg;
1038
1039 block_on(async move {
1040 chat::send_msg_sync(ctx, ChatId::new(chat_id), &mut ffi_msg.message)
1041 .await
1042 .unwrap_or_log_default(ctx, "Failed to send message")
1043 })
1044 .to_u32()
1045}
1046
1047#[no_mangle]
1048pub unsafe extern "C" fn dc_send_text_msg(
1049 context: *mut dc_context_t,
1050 chat_id: u32,
1051 text_to_send: *const libc::c_char,
1052) -> u32 {
1053 if context.is_null() || text_to_send.is_null() {
1054 eprintln!("ignoring careless call to dc_send_text_msg()");
1055 return 0;
1056 }
1057 let ctx = &*context;
1058 let text_to_send = to_string_lossy(text_to_send);
1059
1060 block_on(async move {
1061 chat::send_text_msg(ctx, ChatId::new(chat_id), text_to_send)
1062 .await
1063 .map(|msg_id| msg_id.to_u32())
1064 .unwrap_or_log_default(ctx, "Failed to send text message")
1065 })
1066}
1067
1068#[no_mangle]
1069pub unsafe extern "C" fn dc_send_edit_request(
1070 context: *mut dc_context_t,
1071 msg_id: u32,
1072 new_text: *const libc::c_char,
1073) {
1074 if context.is_null() || new_text.is_null() {
1075 eprintln!("ignoring careless call to dc_send_edit_request()");
1076 return;
1077 }
1078 let ctx = &*context;
1079 let new_text = to_string_lossy(new_text);
1080
1081 block_on(chat::send_edit_request(ctx, MsgId::new(msg_id), new_text))
1082 .unwrap_or_log_default(ctx, "Failed to send text edit")
1083}
1084
1085#[no_mangle]
1086pub unsafe extern "C" fn dc_send_delete_request(
1087 context: *mut dc_context_t,
1088 msg_ids: *const u32,
1089 msg_cnt: libc::c_int,
1090) {
1091 if context.is_null() || msg_ids.is_null() || msg_cnt <= 0 {
1092 eprintln!("ignoring careless call to dc_send_delete_request()");
1093 return;
1094 }
1095 let ctx = &*context;
1096 let msg_ids = convert_and_prune_message_ids(msg_ids, msg_cnt);
1097
1098 block_on(message::delete_msgs_ex(ctx, &msg_ids, true))
1099 .context("failed dc_send_delete_request() call")
1100 .log_err(ctx)
1101 .ok();
1102}
1103
1104#[no_mangle]
1105pub unsafe extern "C" fn dc_send_webxdc_status_update(
1106 context: *mut dc_context_t,
1107 msg_id: u32,
1108 json: *const libc::c_char,
1109 _descr: *const libc::c_char,
1110) -> libc::c_int {
1111 if context.is_null() {
1112 eprintln!("ignoring careless call to dc_send_webxdc_status_update()");
1113 return 0;
1114 }
1115 let ctx = &*context;
1116
1117 block_on(ctx.send_webxdc_status_update(MsgId::new(msg_id), &to_string_lossy(json)))
1118 .context("Failed to send webxdc update")
1119 .log_err(ctx)
1120 .is_ok() as libc::c_int
1121}
1122
1123#[no_mangle]
1124pub unsafe extern "C" fn dc_get_webxdc_status_updates(
1125 context: *mut dc_context_t,
1126 msg_id: u32,
1127 last_known_serial: u32,
1128) -> *mut libc::c_char {
1129 if context.is_null() {
1130 eprintln!("ignoring careless call to dc_get_webxdc_status_updates()");
1131 return "".strdup();
1132 }
1133 let ctx = &*context;
1134
1135 block_on(ctx.get_webxdc_status_updates(
1136 MsgId::new(msg_id),
1137 StatusUpdateSerial::new(last_known_serial),
1138 ))
1139 .unwrap_or_else(|_| "".to_string())
1140 .strdup()
1141}
1142
1143#[no_mangle]
1144pub unsafe extern "C" fn dc_set_webxdc_integration(
1145 context: *mut dc_context_t,
1146 file: *const libc::c_char,
1147) {
1148 if context.is_null() || file.is_null() {
1149 eprintln!("ignoring careless call to dc_set_webxdc_integration()");
1150 return;
1151 }
1152 let ctx = &*context;
1153 block_on(ctx.set_webxdc_integration(&to_string_lossy(file)))
1154 .log_err(ctx)
1155 .unwrap_or_default();
1156}
1157
1158#[no_mangle]
1159pub unsafe extern "C" fn dc_init_webxdc_integration(
1160 context: *mut dc_context_t,
1161 chat_id: u32,
1162) -> u32 {
1163 if context.is_null() {
1164 eprintln!("ignoring careless call to dc_init_webxdc_integration()");
1165 return 0;
1166 }
1167 let ctx = &*context;
1168 let chat_id = if chat_id == 0 {
1169 None
1170 } else {
1171 Some(ChatId::new(chat_id))
1172 };
1173
1174 block_on(ctx.init_webxdc_integration(chat_id))
1175 .log_err(ctx)
1176 .map(|msg_id| msg_id.map(|id| id.to_u32()).unwrap_or_default())
1177 .unwrap_or(0)
1178}
1179
1180#[no_mangle]
1181pub unsafe extern "C" fn dc_place_outgoing_call(
1182 context: *mut dc_context_t,
1183 chat_id: u32,
1184 place_call_info: *const libc::c_char,
1185) -> u32 {
1186 if context.is_null() || chat_id == 0 {
1187 eprintln!("ignoring careless call to dc_place_outgoing_call()");
1188 return 0;
1189 }
1190 let ctx = &*context;
1191 let chat_id = ChatId::new(chat_id);
1192 let place_call_info = to_string_lossy(place_call_info);
1193
1194 block_on(ctx.place_outgoing_call(chat_id, place_call_info))
1195 .context("Failed to place call")
1196 .log_err(ctx)
1197 .map(|msg_id| msg_id.to_u32())
1198 .unwrap_or_log_default(ctx, "Failed to place call")
1199}
1200
1201#[no_mangle]
1202pub unsafe extern "C" fn dc_accept_incoming_call(
1203 context: *mut dc_context_t,
1204 msg_id: u32,
1205 accept_call_info: *const libc::c_char,
1206) -> libc::c_int {
1207 if context.is_null() || msg_id == 0 {
1208 eprintln!("ignoring careless call to dc_accept_incoming_call()");
1209 return 0;
1210 }
1211 let ctx = &*context;
1212 let msg_id = MsgId::new(msg_id);
1213 let accept_call_info = to_string_lossy(accept_call_info);
1214
1215 block_on(ctx.accept_incoming_call(msg_id, accept_call_info))
1216 .context("Failed to accept call")
1217 .is_ok() as libc::c_int
1218}
1219
1220#[no_mangle]
1221pub unsafe extern "C" fn dc_end_call(context: *mut dc_context_t, msg_id: u32) -> libc::c_int {
1222 if context.is_null() || msg_id == 0 {
1223 eprintln!("ignoring careless call to dc_end_call()");
1224 return 0;
1225 }
1226 let ctx = &*context;
1227 let msg_id = MsgId::new(msg_id);
1228
1229 block_on(ctx.end_call(msg_id))
1230 .context("Failed to end call")
1231 .log_err(ctx)
1232 .is_ok() as libc::c_int
1233}
1234
1235#[no_mangle]
1236pub unsafe extern "C" fn dc_set_draft(
1237 context: *mut dc_context_t,
1238 chat_id: u32,
1239 msg: *mut dc_msg_t,
1240) {
1241 if context.is_null() {
1242 eprintln!("ignoring careless call to dc_set_draft()");
1243 return;
1244 }
1245 let ctx = &*context;
1246 let msg = if msg.is_null() {
1247 None
1248 } else {
1249 let ffi_msg: &mut MessageWrapper = &mut *msg;
1250 Some(&mut ffi_msg.message)
1251 };
1252
1253 block_on(async move {
1254 ChatId::new(chat_id)
1255 .set_draft(ctx, msg)
1256 .await
1257 .unwrap_or_log_default(ctx, "failed to set draft");
1258 });
1259}
1260
1261#[no_mangle]
1262pub unsafe extern "C" fn dc_add_device_msg(
1263 context: *mut dc_context_t,
1264 label: *const libc::c_char,
1265 msg: *mut dc_msg_t,
1266) -> u32 {
1267 if context.is_null() || (label.is_null() && msg.is_null()) {
1268 eprintln!("ignoring careless call to dc_add_device_msg()");
1269 return 0;
1270 }
1271 let ctx = &mut *context;
1272 let msg = if msg.is_null() {
1273 None
1274 } else {
1275 let ffi_msg: &mut MessageWrapper = &mut *msg;
1276 Some(&mut ffi_msg.message)
1277 };
1278
1279 block_on(async move {
1280 chat::add_device_msg(ctx, to_opt_string_lossy(label).as_deref(), msg)
1281 .await
1282 .unwrap_or_log_default(ctx, "Failed to add device message")
1283 })
1284 .to_u32()
1285}
1286
1287#[no_mangle]
1288pub unsafe extern "C" fn dc_was_device_msg_ever_added(
1289 context: *mut dc_context_t,
1290 label: *const libc::c_char,
1291) -> libc::c_int {
1292 if context.is_null() || label.is_null() {
1293 eprintln!("ignoring careless call to dc_was_device_msg_ever_added()");
1294 return 0;
1295 }
1296 let ctx = &mut *context;
1297
1298 block_on(async move {
1299 chat::was_device_msg_ever_added(ctx, &to_string_lossy(label))
1300 .await
1301 .unwrap_or(false) as libc::c_int
1302 })
1303}
1304
1305#[no_mangle]
1306pub unsafe extern "C" fn dc_get_draft(context: *mut dc_context_t, chat_id: u32) -> *mut dc_msg_t {
1307 if context.is_null() {
1308 eprintln!("ignoring careless call to dc_get_draft()");
1309 return ptr::null_mut(); }
1311 let ctx = &*context;
1312
1313 match block_on(ChatId::new(chat_id).get_draft(ctx))
1314 .with_context(|| format!("Failed to get draft for chat #{chat_id}"))
1315 .unwrap_or_default()
1316 {
1317 Some(draft) => {
1318 let ffi_msg = MessageWrapper {
1319 context,
1320 message: draft,
1321 };
1322 Box::into_raw(Box::new(ffi_msg))
1323 }
1324 None => ptr::null_mut(),
1325 }
1326}
1327
1328#[no_mangle]
1329pub unsafe extern "C" fn dc_get_chat_msgs(
1330 context: *mut dc_context_t,
1331 chat_id: u32,
1332 flags: u32,
1333 _marker1before: u32,
1334) -> *mut dc_array::dc_array_t {
1335 if context.is_null() {
1336 eprintln!("ignoring careless call to dc_get_chat_msgs()");
1337 return ptr::null_mut();
1338 }
1339 let ctx = &*context;
1340
1341 let info_only = (flags & DC_GCM_INFO_ONLY) != 0;
1342 let add_daymarker = (flags & DC_GCM_ADDDAYMARKER) != 0;
1343 block_on(async move {
1344 Box::into_raw(Box::new(
1345 chat::get_chat_msgs_ex(
1346 ctx,
1347 ChatId::new(chat_id),
1348 MessageListOptions {
1349 info_only,
1350 add_daymarker,
1351 },
1352 )
1353 .await
1354 .unwrap_or_log_default(ctx, "failed to get chat msgs")
1355 .into(),
1356 ))
1357 })
1358}
1359
1360#[no_mangle]
1361pub unsafe extern "C" fn dc_get_msg_cnt(context: *mut dc_context_t, chat_id: u32) -> libc::c_int {
1362 if context.is_null() {
1363 eprintln!("ignoring careless call to dc_get_msg_cnt()");
1364 return 0;
1365 }
1366 let ctx = &*context;
1367
1368 block_on(async move {
1369 ChatId::new(chat_id)
1370 .get_msg_cnt(ctx)
1371 .await
1372 .unwrap_or_log_default(ctx, "failed to get msg count") as libc::c_int
1373 })
1374}
1375
1376#[no_mangle]
1377pub unsafe extern "C" fn dc_get_fresh_msg_cnt(
1378 context: *mut dc_context_t,
1379 chat_id: u32,
1380) -> libc::c_int {
1381 if context.is_null() {
1382 eprintln!("ignoring careless call to dc_get_fresh_msg_cnt()");
1383 return 0;
1384 }
1385 let ctx = &*context;
1386
1387 block_on(async move {
1388 ChatId::new(chat_id)
1389 .get_fresh_msg_cnt(ctx)
1390 .await
1391 .unwrap_or_log_default(ctx, "failed to get fresh msg cnt") as libc::c_int
1392 })
1393}
1394
1395#[no_mangle]
1396pub unsafe extern "C" fn dc_get_similar_chatlist(
1397 context: *mut dc_context_t,
1398 chat_id: u32,
1399) -> *mut dc_chatlist_t {
1400 if context.is_null() {
1401 eprintln!("ignoring careless call to dc_get_similar_chatlist()");
1402 return ptr::null_mut();
1403 }
1404 let ctx = &*context;
1405
1406 let chat_id = ChatId::new(chat_id);
1407 match block_on(chat_id.get_similar_chatlist(ctx))
1408 .context("failed to get similar chatlist")
1409 .log_err(ctx)
1410 {
1411 Ok(list) => {
1412 let ffi_list = ChatlistWrapper { context, list };
1413 Box::into_raw(Box::new(ffi_list))
1414 }
1415 Err(_) => ptr::null_mut(),
1416 }
1417}
1418
1419#[no_mangle]
1420pub unsafe extern "C" fn dc_estimate_deletion_cnt(
1421 context: *mut dc_context_t,
1422 from_server: libc::c_int,
1423 seconds: i64,
1424) -> libc::c_int {
1425 if context.is_null() || seconds < 0 {
1426 eprintln!("ignoring careless call to dc_estimate_deletion_cnt()");
1427 return 0;
1428 }
1429 let ctx = &*context;
1430 block_on(async move {
1431 message::estimate_deletion_cnt(ctx, from_server != 0, seconds)
1432 .await
1433 .unwrap_or(0) as libc::c_int
1434 })
1435}
1436
1437#[no_mangle]
1438pub unsafe extern "C" fn dc_get_fresh_msgs(
1439 context: *mut dc_context_t,
1440) -> *mut dc_array::dc_array_t {
1441 if context.is_null() {
1442 eprintln!("ignoring careless call to dc_get_fresh_msgs()");
1443 return ptr::null_mut();
1444 }
1445 let ctx = &*context;
1446
1447 block_on(async move {
1448 let arr = dc_array_t::from(
1449 ctx.get_fresh_msgs()
1450 .await
1451 .context("Failed to get fresh messages")
1452 .log_err(ctx)
1453 .unwrap_or_default()
1454 .iter()
1455 .map(|msg_id| msg_id.to_u32())
1456 .collect::<Vec<u32>>(),
1457 );
1458 Box::into_raw(Box::new(arr))
1459 })
1460}
1461
1462#[no_mangle]
1463pub unsafe extern "C" fn dc_get_next_msgs(context: *mut dc_context_t) -> *mut dc_array::dc_array_t {
1464 if context.is_null() {
1465 eprintln!("ignoring careless call to dc_get_next_msgs()");
1466 return ptr::null_mut();
1467 }
1468 let ctx = &*context;
1469
1470 let msg_ids = block_on(ctx.get_next_msgs())
1471 .context("failed to get next messages")
1472 .log_err(ctx)
1473 .unwrap_or_default();
1474 let arr = dc_array_t::from(
1475 msg_ids
1476 .iter()
1477 .map(|msg_id| msg_id.to_u32())
1478 .collect::<Vec<u32>>(),
1479 );
1480 Box::into_raw(Box::new(arr))
1481}
1482
1483#[no_mangle]
1484pub unsafe extern "C" fn dc_wait_next_msgs(
1485 context: *mut dc_context_t,
1486) -> *mut dc_array::dc_array_t {
1487 if context.is_null() {
1488 eprintln!("ignoring careless call to dc_wait_next_msgs()");
1489 return ptr::null_mut();
1490 }
1491 let ctx = &*context;
1492
1493 let msg_ids = block_on(ctx.wait_next_msgs())
1494 .context("failed to wait for next messages")
1495 .log_err(ctx)
1496 .unwrap_or_default();
1497 let arr = dc_array_t::from(
1498 msg_ids
1499 .iter()
1500 .map(|msg_id| msg_id.to_u32())
1501 .collect::<Vec<u32>>(),
1502 );
1503 Box::into_raw(Box::new(arr))
1504}
1505
1506#[no_mangle]
1507pub unsafe extern "C" fn dc_marknoticed_chat(context: *mut dc_context_t, chat_id: u32) {
1508 if context.is_null() {
1509 eprintln!("ignoring careless call to dc_marknoticed_chat()");
1510 return;
1511 }
1512 let ctx = &*context;
1513
1514 block_on(async move {
1515 chat::marknoticed_chat(ctx, ChatId::new(chat_id))
1516 .await
1517 .context("Failed marknoticed chat")
1518 .log_err(ctx)
1519 .unwrap_or(())
1520 })
1521}
1522
1523fn from_prim<S, T>(s: S) -> Option<T>
1524where
1525 T: FromPrimitive,
1526 S: Into<i64>,
1527{
1528 FromPrimitive::from_i64(s.into())
1529}
1530
1531#[no_mangle]
1532pub unsafe extern "C" fn dc_get_chat_media(
1533 context: *mut dc_context_t,
1534 chat_id: u32,
1535 msg_type: libc::c_int,
1536 or_msg_type2: libc::c_int,
1537 or_msg_type3: libc::c_int,
1538) -> *mut dc_array::dc_array_t {
1539 if context.is_null() {
1540 eprintln!("ignoring careless call to dc_get_chat_media()");
1541 return ptr::null_mut();
1542 }
1543 let ctx = &*context;
1544 let chat_id = if chat_id == 0 {
1545 None
1546 } else {
1547 Some(ChatId::new(chat_id))
1548 };
1549 let msg_type = from_prim(msg_type).expect(&format!("invalid msg_type = {msg_type}"));
1550 let or_msg_type2 =
1551 from_prim(or_msg_type2).expect(&format!("incorrect or_msg_type2 = {or_msg_type2}"));
1552 let or_msg_type3 =
1553 from_prim(or_msg_type3).expect(&format!("incorrect or_msg_type3 = {or_msg_type3}"));
1554
1555 block_on(async move {
1556 Box::into_raw(Box::new(
1557 chat::get_chat_media(ctx, chat_id, msg_type, or_msg_type2, or_msg_type3)
1558 .await
1559 .unwrap_or_log_default(ctx, "Failed get_chat_media")
1560 .into(),
1561 ))
1562 })
1563}
1564
1565#[no_mangle]
1566pub unsafe extern "C" fn dc_set_chat_visibility(
1567 context: *mut dc_context_t,
1568 chat_id: u32,
1569 archive: libc::c_int,
1570) {
1571 if context.is_null() {
1572 eprintln!("ignoring careless call to dc_set_chat_visibility()");
1573 return;
1574 }
1575 let ctx = &*context;
1576 let visibility = match archive {
1577 0 => ChatVisibility::Normal,
1578 1 => ChatVisibility::Archived,
1579 2 => ChatVisibility::Pinned,
1580 _ => {
1581 eprintln!("ignoring careless call to dc_set_chat_visibility(): unknown archived state");
1582 return;
1583 }
1584 };
1585
1586 block_on(async move {
1587 ChatId::new(chat_id)
1588 .set_visibility(ctx, visibility)
1589 .await
1590 .context("Failed setting chat visibility")
1591 .log_err(ctx)
1592 .unwrap_or(())
1593 })
1594}
1595
1596#[no_mangle]
1597pub unsafe extern "C" fn dc_delete_chat(context: *mut dc_context_t, chat_id: u32) {
1598 if context.is_null() {
1599 eprintln!("ignoring careless call to dc_delete_chat()");
1600 return;
1601 }
1602 let ctx = &*context;
1603
1604 block_on(async move {
1605 ChatId::new(chat_id)
1606 .delete(ctx)
1607 .await
1608 .context("Failed chat delete")
1609 .log_err(ctx)
1610 .ok();
1611 })
1612}
1613
1614#[no_mangle]
1615pub unsafe extern "C" fn dc_block_chat(context: *mut dc_context_t, chat_id: u32) {
1616 if context.is_null() {
1617 eprintln!("ignoring careless call to dc_block_chat()");
1618 return;
1619 }
1620 let ctx = &*context;
1621
1622 block_on(async move {
1623 ChatId::new(chat_id)
1624 .block(ctx)
1625 .await
1626 .context("Failed chat block")
1627 .log_err(ctx)
1628 .ok();
1629 })
1630}
1631
1632#[no_mangle]
1633pub unsafe extern "C" fn dc_accept_chat(context: *mut dc_context_t, chat_id: u32) {
1634 if context.is_null() {
1635 eprintln!("ignoring careless call to dc_accept_chat()");
1636 return;
1637 }
1638 let ctx = &*context;
1639
1640 block_on(async move {
1641 ChatId::new(chat_id)
1642 .accept(ctx)
1643 .await
1644 .context("Failed chat accept")
1645 .log_err(ctx)
1646 .ok();
1647 })
1648}
1649
1650#[no_mangle]
1651pub unsafe extern "C" fn dc_get_chat_contacts(
1652 context: *mut dc_context_t,
1653 chat_id: u32,
1654) -> *mut dc_array::dc_array_t {
1655 if context.is_null() {
1656 eprintln!("ignoring careless call to dc_get_chat_contacts()");
1657 return ptr::null_mut();
1658 }
1659 let ctx = &*context;
1660
1661 block_on(async move {
1662 let arr = dc_array_t::from(
1663 chat::get_chat_contacts(ctx, ChatId::new(chat_id))
1664 .await
1665 .unwrap_or_log_default(ctx, "Failed get_chat_contacts")
1666 .iter()
1667 .map(|id| id.to_u32())
1668 .collect::<Vec<u32>>(),
1669 );
1670 Box::into_raw(Box::new(arr))
1671 })
1672}
1673
1674#[no_mangle]
1675pub unsafe extern "C" fn dc_search_msgs(
1676 context: *mut dc_context_t,
1677 chat_id: u32,
1678 query: *const libc::c_char,
1679) -> *mut dc_array::dc_array_t {
1680 if context.is_null() || query.is_null() {
1681 eprintln!("ignoring careless call to dc_search_msgs()");
1682 return ptr::null_mut();
1683 }
1684 let ctx = &*context;
1685 let chat_id = if chat_id == 0 {
1686 None
1687 } else {
1688 Some(ChatId::new(chat_id))
1689 };
1690
1691 block_on(async move {
1692 let arr = dc_array_t::from(
1693 ctx.search_msgs(chat_id, &to_string_lossy(query))
1694 .await
1695 .unwrap_or_log_default(ctx, "Failed search_msgs")
1696 .iter()
1697 .map(|msg_id| msg_id.to_u32())
1698 .collect::<Vec<u32>>(),
1699 );
1700 Box::into_raw(Box::new(arr))
1701 })
1702}
1703
1704#[no_mangle]
1705pub unsafe extern "C" fn dc_get_chat(context: *mut dc_context_t, chat_id: u32) -> *mut dc_chat_t {
1706 if context.is_null() {
1707 eprintln!("ignoring careless call to dc_get_chat()");
1708 return ptr::null_mut();
1709 }
1710 let ctx = &*context;
1711 let context: Context = ctx.clone();
1712
1713 block_on(async move {
1714 match chat::Chat::load_from_db(ctx, ChatId::new(chat_id)).await {
1715 Ok(chat) => {
1716 let ffi_chat = ChatWrapper { context, chat };
1717 Box::into_raw(Box::new(ffi_chat))
1718 }
1719 Err(_) => ptr::null_mut(),
1720 }
1721 })
1722}
1723
1724#[no_mangle]
1725pub unsafe extern "C" fn dc_create_group_chat(
1726 context: *mut dc_context_t,
1727 _protect: libc::c_int,
1728 name: *const libc::c_char,
1729) -> u32 {
1730 if context.is_null() || name.is_null() {
1731 eprintln!("ignoring careless call to dc_create_group_chat()");
1732 return 0;
1733 }
1734 let ctx = &*context;
1735
1736 block_on(chat::create_group(ctx, &to_string_lossy(name)))
1737 .context("Failed to create group chat")
1738 .log_err(ctx)
1739 .map(|id| id.to_u32())
1740 .unwrap_or(0)
1741}
1742
1743#[no_mangle]
1744pub unsafe extern "C" fn dc_create_broadcast_list(context: *mut dc_context_t) -> u32 {
1745 if context.is_null() {
1746 eprintln!("ignoring careless call to dc_create_broadcast_list()");
1747 return 0;
1748 }
1749 let ctx = &*context;
1750 block_on(chat::create_broadcast(ctx, "Channel".to_string()))
1751 .context("Failed to create broadcast channel")
1752 .log_err(ctx)
1753 .map(|id| id.to_u32())
1754 .unwrap_or(0)
1755}
1756
1757#[no_mangle]
1758pub unsafe extern "C" fn dc_is_contact_in_chat(
1759 context: *mut dc_context_t,
1760 chat_id: u32,
1761 contact_id: u32,
1762) -> libc::c_int {
1763 if context.is_null() {
1764 eprintln!("ignoring careless call to dc_is_contact_in_chat()");
1765 return 0;
1766 }
1767 let ctx = &*context;
1768
1769 block_on(chat::is_contact_in_chat(
1770 ctx,
1771 ChatId::new(chat_id),
1772 ContactId::new(contact_id),
1773 ))
1774 .context("is_contact_in_chat failed")
1775 .log_err(ctx)
1776 .unwrap_or_default() as libc::c_int
1777}
1778
1779#[no_mangle]
1780pub unsafe extern "C" fn dc_add_contact_to_chat(
1781 context: *mut dc_context_t,
1782 chat_id: u32,
1783 contact_id: u32,
1784) -> libc::c_int {
1785 if context.is_null() {
1786 eprintln!("ignoring careless call to dc_add_contact_to_chat()");
1787 return 0;
1788 }
1789 let ctx = &*context;
1790
1791 block_on(chat::add_contact_to_chat(
1792 ctx,
1793 ChatId::new(chat_id),
1794 ContactId::new(contact_id),
1795 ))
1796 .context("Failed to add contact")
1797 .log_err(ctx)
1798 .is_ok() as libc::c_int
1799}
1800
1801#[no_mangle]
1802pub unsafe extern "C" fn dc_remove_contact_from_chat(
1803 context: *mut dc_context_t,
1804 chat_id: u32,
1805 contact_id: u32,
1806) -> libc::c_int {
1807 if context.is_null() {
1808 eprintln!("ignoring careless call to dc_remove_contact_from_chat()");
1809 return 0;
1810 }
1811 let ctx = &*context;
1812
1813 block_on(chat::remove_contact_from_chat(
1814 ctx,
1815 ChatId::new(chat_id),
1816 ContactId::new(contact_id),
1817 ))
1818 .context("Failed to remove contact")
1819 .log_err(ctx)
1820 .is_ok() as libc::c_int
1821}
1822
1823#[no_mangle]
1824pub unsafe extern "C" fn dc_set_chat_name(
1825 context: *mut dc_context_t,
1826 chat_id: u32,
1827 name: *const libc::c_char,
1828) -> libc::c_int {
1829 if context.is_null() || chat_id <= constants::DC_CHAT_ID_LAST_SPECIAL.to_u32() || name.is_null()
1830 {
1831 eprintln!("ignoring careless call to dc_set_chat_name()");
1832 return 0;
1833 }
1834 let ctx = &*context;
1835
1836 block_on(async move {
1837 chat::set_chat_name(ctx, ChatId::new(chat_id), &to_string_lossy(name))
1838 .await
1839 .map(|_| 1)
1840 .unwrap_or_log_default(ctx, "Failed to set chat name")
1841 })
1842}
1843
1844#[no_mangle]
1845pub unsafe extern "C" fn dc_set_chat_profile_image(
1846 context: *mut dc_context_t,
1847 chat_id: u32,
1848 image: *const libc::c_char,
1849) -> libc::c_int {
1850 if context.is_null() || chat_id <= constants::DC_CHAT_ID_LAST_SPECIAL.to_u32() {
1851 eprintln!("ignoring careless call to dc_set_chat_profile_image()");
1852 return 0;
1853 }
1854 let ctx = &*context;
1855
1856 block_on(async move {
1857 chat::set_chat_profile_image(ctx, ChatId::new(chat_id), &to_string_lossy(image))
1858 .await
1859 .map(|_| 1)
1860 .unwrap_or_log_default(ctx, "Failed to set profile image")
1861 })
1862}
1863
1864#[no_mangle]
1865pub unsafe extern "C" fn dc_set_chat_mute_duration(
1866 context: *mut dc_context_t,
1867 chat_id: u32,
1868 duration: i64,
1869) -> libc::c_int {
1870 if context.is_null() {
1871 eprintln!("ignoring careless call to dc_set_chat_mute_duration()");
1872 return 0;
1873 }
1874 let ctx = &*context;
1875 let mute_duration = match duration {
1876 0 => MuteDuration::NotMuted,
1877 -1 => MuteDuration::Forever,
1878 n if n > 0 => SystemTime::now()
1879 .checked_add(Duration::from_secs(duration as u64))
1880 .map_or(MuteDuration::Forever, MuteDuration::Until),
1881 _ => {
1882 eprintln!("dc_chat_set_mute_duration(): Can not use negative duration other than -1");
1883 return 0;
1884 }
1885 };
1886
1887 block_on(async move {
1888 chat::set_muted(ctx, ChatId::new(chat_id), mute_duration)
1889 .await
1890 .map(|_| 1)
1891 .unwrap_or_log_default(ctx, "Failed to set mute duration")
1892 })
1893}
1894
1895#[no_mangle]
1896pub unsafe extern "C" fn dc_get_chat_encrinfo(
1897 context: *mut dc_context_t,
1898 chat_id: u32,
1899) -> *mut libc::c_char {
1900 if context.is_null() {
1901 eprintln!("ignoring careless call to dc_get_chat_encrinfo()");
1902 return "".strdup();
1903 }
1904 let ctx = &*context;
1905
1906 block_on(ChatId::new(chat_id).get_encryption_info(ctx))
1907 .map(|s| s.strdup())
1908 .log_err(ctx)
1909 .unwrap_or(ptr::null_mut())
1910}
1911
1912#[no_mangle]
1913pub unsafe extern "C" fn dc_get_chat_ephemeral_timer(
1914 context: *mut dc_context_t,
1915 chat_id: u32,
1916) -> u32 {
1917 if context.is_null() {
1918 eprintln!("ignoring careless call to dc_get_chat_ephemeral_timer()");
1919 return 0;
1920 }
1921 let ctx = &*context;
1922
1923 block_on(async move { ChatId::new(chat_id).get_ephemeral_timer(ctx).await })
1929 .context("Failed to get ephemeral timer")
1930 .log_err(ctx)
1931 .unwrap_or_default()
1932 .to_u32()
1933}
1934
1935#[no_mangle]
1936pub unsafe extern "C" fn dc_set_chat_ephemeral_timer(
1937 context: *mut dc_context_t,
1938 chat_id: u32,
1939 timer: u32,
1940) -> libc::c_int {
1941 if context.is_null() {
1942 eprintln!("ignoring careless call to dc_set_chat_ephemeral_timer()");
1943 return 0;
1944 }
1945 let ctx = &*context;
1946
1947 block_on(async move {
1948 ChatId::new(chat_id)
1949 .set_ephemeral_timer(ctx, EphemeralTimer::from_u32(timer))
1950 .await
1951 .context("Failed to set ephemeral timer")
1952 .log_err(ctx)
1953 .is_ok() as libc::c_int
1954 })
1955}
1956
1957#[no_mangle]
1958pub unsafe extern "C" fn dc_get_msg_info(
1959 context: *mut dc_context_t,
1960 msg_id: u32,
1961) -> *mut libc::c_char {
1962 if context.is_null() {
1963 eprintln!("ignoring careless call to dc_get_msg_info()");
1964 return "".strdup();
1965 }
1966 let ctx = &*context;
1967 let msg_id = MsgId::new(msg_id);
1968 block_on(msg_id.get_info(ctx))
1969 .unwrap_or_log_default(ctx, "failed to get msg id")
1970 .strdup()
1971}
1972
1973#[no_mangle]
1974pub unsafe extern "C" fn dc_get_msg_html(
1975 context: *mut dc_context_t,
1976 msg_id: u32,
1977) -> *mut libc::c_char {
1978 if context.is_null() {
1979 eprintln!("ignoring careless call to dc_get_msg_html()");
1980 return ptr::null_mut();
1981 }
1982 let ctx = &*context;
1983
1984 block_on(MsgId::new(msg_id).get_html(ctx))
1985 .unwrap_or_log_default(ctx, "Failed get_msg_html")
1986 .strdup()
1987}
1988
1989#[no_mangle]
1990pub unsafe extern "C" fn dc_delete_msgs(
1991 context: *mut dc_context_t,
1992 msg_ids: *const u32,
1993 msg_cnt: libc::c_int,
1994) {
1995 if context.is_null() || msg_ids.is_null() || msg_cnt <= 0 {
1996 eprintln!("ignoring careless call to dc_delete_msgs()");
1997 return;
1998 }
1999 let ctx = &*context;
2000 let msg_ids = convert_and_prune_message_ids(msg_ids, msg_cnt);
2001
2002 block_on(message::delete_msgs(ctx, &msg_ids))
2003 .context("failed dc_delete_msgs() call")
2004 .log_err(ctx)
2005 .ok();
2006}
2007
2008#[no_mangle]
2009pub unsafe extern "C" fn dc_forward_msgs(
2010 context: *mut dc_context_t,
2011 msg_ids: *const u32,
2012 msg_cnt: libc::c_int,
2013 chat_id: u32,
2014) {
2015 if context.is_null()
2016 || msg_ids.is_null()
2017 || msg_cnt <= 0
2018 || chat_id <= constants::DC_CHAT_ID_LAST_SPECIAL.to_u32()
2019 {
2020 eprintln!("ignoring careless call to dc_forward_msgs()");
2021 return;
2022 }
2023 let msg_ids = convert_and_prune_message_ids(msg_ids, msg_cnt);
2024 let ctx = &*context;
2025
2026 block_on(async move {
2027 chat::forward_msgs(ctx, &msg_ids[..], ChatId::new(chat_id))
2028 .await
2029 .unwrap_or_log_default(ctx, "Failed to forward message")
2030 })
2031}
2032
2033#[no_mangle]
2034pub unsafe extern "C" fn dc_save_msgs(
2035 context: *mut dc_context_t,
2036 msg_ids: *const u32,
2037 msg_cnt: libc::c_int,
2038) {
2039 if context.is_null() || msg_ids.is_null() || msg_cnt <= 0 {
2040 eprintln!("ignoring careless call to dc_save_msgs()");
2041 return;
2042 }
2043 let msg_ids = convert_and_prune_message_ids(msg_ids, msg_cnt);
2044 let ctx = &*context;
2045
2046 block_on(async move {
2047 chat::save_msgs(ctx, &msg_ids[..])
2048 .await
2049 .unwrap_or_log_default(ctx, "Failed to save message")
2050 })
2051}
2052
2053#[no_mangle]
2054pub unsafe extern "C" fn dc_resend_msgs(
2055 context: *mut dc_context_t,
2056 msg_ids: *const u32,
2057 msg_cnt: libc::c_int,
2058) -> libc::c_int {
2059 if context.is_null() || msg_ids.is_null() || msg_cnt <= 0 {
2060 eprintln!("ignoring careless call to dc_resend_msgs()");
2061 return 0;
2062 }
2063 let ctx = &*context;
2064 let msg_ids = convert_and_prune_message_ids(msg_ids, msg_cnt);
2065
2066 block_on(chat::resend_msgs(ctx, &msg_ids))
2067 .context("Resending failed")
2068 .log_err(ctx)
2069 .is_ok() as libc::c_int
2070}
2071
2072#[no_mangle]
2073pub unsafe extern "C" fn dc_markseen_msgs(
2074 context: *mut dc_context_t,
2075 msg_ids: *const u32,
2076 msg_cnt: libc::c_int,
2077) {
2078 if context.is_null() || msg_ids.is_null() || msg_cnt <= 0 {
2079 eprintln!("ignoring careless call to dc_markseen_msgs()");
2080 return;
2081 }
2082 let msg_ids = convert_and_prune_message_ids(msg_ids, msg_cnt);
2083 let ctx = &*context;
2084
2085 block_on(message::markseen_msgs(ctx, msg_ids))
2086 .context("failed dc_markseen_msgs() call")
2087 .log_err(ctx)
2088 .ok();
2089}
2090
2091#[no_mangle]
2092pub unsafe extern "C" fn dc_get_msg(context: *mut dc_context_t, msg_id: u32) -> *mut dc_msg_t {
2093 if context.is_null() {
2094 eprintln!("ignoring careless call to dc_get_msg()");
2095 return ptr::null_mut();
2096 }
2097 let ctx = &*context;
2098
2099 let message = match block_on(message::Message::load_from_db(ctx, MsgId::new(msg_id)))
2100 .with_context(|| format!("dc_get_msg could not rectieve msg_id {msg_id}"))
2101 .log_err(ctx)
2102 {
2103 Ok(msg) => msg,
2104 Err(_) => {
2105 if msg_id <= constants::DC_MSG_ID_LAST_SPECIAL {
2106 message::Message::new(Viewtype::default())
2108 } else {
2109 return ptr::null_mut();
2110 }
2111 }
2112 };
2113 let ffi_msg = MessageWrapper { context, message };
2114 Box::into_raw(Box::new(ffi_msg))
2115}
2116
2117#[no_mangle]
2118pub unsafe extern "C" fn dc_download_full_msg(context: *mut dc_context_t, msg_id: u32) {
2119 if context.is_null() {
2120 eprintln!("ignoring careless call to dc_download_full_msg()");
2121 return;
2122 }
2123 let ctx = &*context;
2124 block_on(MsgId::new(msg_id).download_full(ctx))
2125 .context("Failed to download message fully.")
2126 .log_err(ctx)
2127 .ok();
2128}
2129
2130#[no_mangle]
2131pub unsafe extern "C" fn dc_may_be_valid_addr(addr: *const libc::c_char) -> libc::c_int {
2132 if addr.is_null() {
2133 eprintln!("ignoring careless call to dc_may_be_valid_addr()");
2134 return 0;
2135 }
2136
2137 contact::may_be_valid_addr(&to_string_lossy(addr)) as libc::c_int
2138}
2139
2140#[no_mangle]
2141pub unsafe extern "C" fn dc_lookup_contact_id_by_addr(
2142 context: *mut dc_context_t,
2143 addr: *const libc::c_char,
2144) -> u32 {
2145 if context.is_null() || addr.is_null() {
2146 eprintln!("ignoring careless call to dc_lookup_contact_id_by_addr()");
2147 return 0;
2148 }
2149 let ctx = &*context;
2150
2151 block_on(async move {
2152 Contact::lookup_id_by_addr(ctx, &to_string_lossy(addr), Origin::IncomingReplyTo)
2153 .await
2154 .unwrap_or_log_default(ctx, "failed to lookup id")
2155 .map(|id| id.to_u32())
2156 .unwrap_or_default()
2157 })
2158}
2159
2160#[no_mangle]
2161pub unsafe extern "C" fn dc_create_contact(
2162 context: *mut dc_context_t,
2163 name: *const libc::c_char,
2164 addr: *const libc::c_char,
2165) -> u32 {
2166 if context.is_null() || addr.is_null() {
2167 eprintln!("ignoring careless call to dc_create_contact()");
2168 return 0;
2169 }
2170 let ctx = &*context;
2171 let name = to_string_lossy(name);
2172
2173 block_on(Contact::create(ctx, &name, &to_string_lossy(addr)))
2174 .context("Cannot create contact")
2175 .log_err(ctx)
2176 .map(|id| id.to_u32())
2177 .unwrap_or(0)
2178}
2179
2180#[no_mangle]
2181pub unsafe extern "C" fn dc_add_address_book(
2182 context: *mut dc_context_t,
2183 addr_book: *const libc::c_char,
2184) -> libc::c_int {
2185 if context.is_null() || addr_book.is_null() {
2186 eprintln!("ignoring careless call to dc_add_address_book()");
2187 return 0;
2188 }
2189 let ctx = &*context;
2190
2191 block_on(async move {
2192 match Contact::add_address_book(ctx, &to_string_lossy(addr_book)).await {
2193 Ok(cnt) => cnt as libc::c_int,
2194 Err(_) => 0,
2195 }
2196 })
2197}
2198
2199#[no_mangle]
2200pub unsafe extern "C" fn dc_make_vcard(
2201 context: *mut dc_context_t,
2202 contact_id: u32,
2203) -> *mut libc::c_char {
2204 if context.is_null() {
2205 eprintln!("ignoring careless call to dc_make_vcard()");
2206 return ptr::null_mut();
2207 }
2208 let ctx = &*context;
2209 let contact_id = ContactId::new(contact_id);
2210
2211 block_on(contact::make_vcard(ctx, &[contact_id]))
2212 .unwrap_or_log_default(ctx, "dc_make_vcard failed")
2213 .strdup()
2214}
2215
2216#[no_mangle]
2217pub unsafe extern "C" fn dc_import_vcard(
2218 context: *mut dc_context_t,
2219 vcard: *const libc::c_char,
2220) -> *mut dc_array::dc_array_t {
2221 if context.is_null() || vcard.is_null() {
2222 eprintln!("ignoring careless call to dc_import_vcard()");
2223 return ptr::null_mut();
2224 }
2225 let ctx = &*context;
2226
2227 match block_on(contact::import_vcard(ctx, &to_string_lossy(vcard)))
2228 .context("dc_import_vcard failed")
2229 .log_err(ctx)
2230 {
2231 Ok(contact_ids) => Box::into_raw(Box::new(dc_array_t::from(
2232 contact_ids
2233 .iter()
2234 .map(|id| id.to_u32())
2235 .collect::<Vec<u32>>(),
2236 ))),
2237 Err(_) => ptr::null_mut(),
2238 }
2239}
2240
2241#[no_mangle]
2242pub unsafe extern "C" fn dc_get_contacts(
2243 context: *mut dc_context_t,
2244 flags: u32,
2245 query: *const libc::c_char,
2246) -> *mut dc_array::dc_array_t {
2247 if context.is_null() {
2248 eprintln!("ignoring careless call to dc_get_contacts()");
2249 return ptr::null_mut();
2250 }
2251 let ctx = &*context;
2252 let query = to_opt_string_lossy(query);
2253
2254 block_on(async move {
2255 match Contact::get_all(ctx, flags, query.as_deref()).await {
2256 Ok(contacts) => Box::into_raw(Box::new(dc_array_t::from(
2257 contacts.iter().map(|id| id.to_u32()).collect::<Vec<u32>>(),
2258 ))),
2259 Err(_) => ptr::null_mut(),
2260 }
2261 })
2262}
2263
2264#[no_mangle]
2265pub unsafe extern "C" fn dc_get_blocked_cnt(context: *mut dc_context_t) -> libc::c_int {
2266 if context.is_null() {
2267 eprintln!("ignoring careless call to dc_get_blocked_cnt()");
2268 return 0;
2269 }
2270 let ctx = &*context;
2271
2272 block_on(async move {
2273 Contact::get_all_blocked(ctx)
2274 .await
2275 .unwrap_or_log_default(ctx, "failed to get blocked count")
2276 .len() as libc::c_int
2277 })
2278}
2279
2280#[no_mangle]
2281pub unsafe extern "C" fn dc_get_blocked_contacts(
2282 context: *mut dc_context_t,
2283) -> *mut dc_array::dc_array_t {
2284 if context.is_null() {
2285 eprintln!("ignoring careless call to dc_get_blocked_contacts()");
2286 return ptr::null_mut();
2287 }
2288 let ctx = &*context;
2289
2290 block_on(async move {
2291 Box::into_raw(Box::new(dc_array_t::from(
2292 Contact::get_all_blocked(ctx)
2293 .await
2294 .context("Can't get blocked contacts")
2295 .log_err(ctx)
2296 .unwrap_or_default()
2297 .iter()
2298 .map(|id| id.to_u32())
2299 .collect::<Vec<u32>>(),
2300 )))
2301 })
2302}
2303
2304#[no_mangle]
2305pub unsafe extern "C" fn dc_block_contact(
2306 context: *mut dc_context_t,
2307 contact_id: u32,
2308 block: libc::c_int,
2309) {
2310 let contact_id = ContactId::new(contact_id);
2311 if context.is_null() || contact_id.is_special() {
2312 eprintln!("ignoring careless call to dc_block_contact()");
2313 return;
2314 }
2315 let ctx = &*context;
2316 block_on(async move {
2317 if block == 0 {
2318 Contact::unblock(ctx, contact_id)
2319 .await
2320 .context("Can't unblock contact")
2321 .log_err(ctx)
2322 .ok();
2323 } else {
2324 Contact::block(ctx, contact_id)
2325 .await
2326 .context("Can't block contact")
2327 .log_err(ctx)
2328 .ok();
2329 }
2330 });
2331}
2332
2333#[no_mangle]
2334pub unsafe extern "C" fn dc_get_contact_encrinfo(
2335 context: *mut dc_context_t,
2336 contact_id: u32,
2337) -> *mut libc::c_char {
2338 if context.is_null() {
2339 eprintln!("ignoring careless call to dc_get_contact_encrinfo()");
2340 return "".strdup();
2341 }
2342 let ctx = &*context;
2343
2344 block_on(Contact::get_encrinfo(ctx, ContactId::new(contact_id)))
2345 .map(|s| s.strdup())
2346 .log_err(ctx)
2347 .unwrap_or(ptr::null_mut())
2348}
2349
2350#[no_mangle]
2351pub unsafe extern "C" fn dc_delete_contact(
2352 context: *mut dc_context_t,
2353 contact_id: u32,
2354) -> libc::c_int {
2355 let contact_id = ContactId::new(contact_id);
2356 if context.is_null() || contact_id.is_special() {
2357 eprintln!("ignoring careless call to dc_delete_contact()");
2358 return 0;
2359 }
2360 let ctx = &*context;
2361
2362 block_on(Contact::delete(ctx, contact_id))
2363 .context("Cannot delete contact")
2364 .log_err(ctx)
2365 .is_ok() as libc::c_int
2366}
2367
2368#[no_mangle]
2369pub unsafe extern "C" fn dc_get_contact(
2370 context: *mut dc_context_t,
2371 contact_id: u32,
2372) -> *mut dc_contact_t {
2373 if context.is_null() {
2374 eprintln!("ignoring careless call to dc_get_contact()");
2375 return ptr::null_mut();
2376 }
2377 let ctx = &*context;
2378
2379 block_on(async move {
2380 Contact::get_by_id(ctx, ContactId::new(contact_id))
2381 .await
2382 .map(|contact| Box::into_raw(Box::new(ContactWrapper { context, contact })))
2383 .unwrap_or_else(|_| ptr::null_mut())
2384 })
2385}
2386
2387fn spawn_imex(ctx: Context, what: imex::ImexMode, param1: String, passphrase: Option<String>) {
2388 spawn(async move {
2389 imex::imex(&ctx, what, param1.as_ref(), passphrase)
2390 .await
2391 .context("IMEX failed")
2392 .log_err(&ctx)
2393 });
2394}
2395
2396#[no_mangle]
2397pub unsafe extern "C" fn dc_imex(
2398 context: *mut dc_context_t,
2399 what_raw: libc::c_int,
2400 param1: *const libc::c_char,
2401 param2: *const libc::c_char,
2402) {
2403 if context.is_null() {
2404 eprintln!("ignoring careless call to dc_imex()");
2405 return;
2406 }
2407 let what = match imex::ImexMode::from_i32(what_raw) {
2408 Some(what) => what,
2409 None => {
2410 eprintln!("ignoring invalid argument {what_raw} to dc_imex");
2411 return;
2412 }
2413 };
2414 let passphrase = to_opt_string_lossy(param2);
2415
2416 let ctx = &*context;
2417
2418 if let Some(param1) = to_opt_string_lossy(param1) {
2419 spawn_imex(ctx.clone(), what, param1, passphrase);
2420 } else {
2421 eprintln!("dc_imex called without a valid directory");
2422 }
2423}
2424
2425#[no_mangle]
2426pub unsafe extern "C" fn dc_imex_has_backup(
2427 context: *mut dc_context_t,
2428 dir: *const libc::c_char,
2429) -> *mut libc::c_char {
2430 if context.is_null() || dir.is_null() {
2431 eprintln!("ignoring careless call to dc_imex_has_backup()");
2432 return ptr::null_mut(); }
2434 let ctx = &*context;
2435
2436 match block_on(imex::has_backup(ctx, to_string_lossy(dir).as_ref()))
2437 .context("dc_imex_has_backup")
2438 .log_err(ctx)
2439 {
2440 Ok(res) => res.strdup(),
2441 Err(_) => ptr::null_mut(),
2442 }
2443}
2444
2445#[no_mangle]
2446pub unsafe extern "C" fn dc_initiate_key_transfer(context: *mut dc_context_t) -> *mut libc::c_char {
2447 if context.is_null() {
2448 eprintln!("ignoring careless call to dc_initiate_key_transfer()");
2449 return ptr::null_mut(); }
2451 let ctx = &*context;
2452
2453 match block_on(imex::initiate_key_transfer(ctx))
2454 .context("dc_initiate_key_transfer()")
2455 .log_err(ctx)
2456 {
2457 Ok(res) => res.strdup(),
2458 Err(_) => ptr::null_mut(),
2459 }
2460}
2461
2462#[no_mangle]
2463pub unsafe extern "C" fn dc_continue_key_transfer(
2464 context: *mut dc_context_t,
2465 msg_id: u32,
2466 setup_code: *const libc::c_char,
2467) -> libc::c_int {
2468 if context.is_null() || msg_id <= constants::DC_MSG_ID_LAST_SPECIAL || setup_code.is_null() {
2469 eprintln!("ignoring careless call to dc_continue_key_transfer()");
2470 return 0;
2471 }
2472 let ctx = &*context;
2473
2474 block_on(imex::continue_key_transfer(
2475 ctx,
2476 MsgId::new(msg_id),
2477 &to_string_lossy(setup_code),
2478 ))
2479 .context("dc_continue_key_transfer")
2480 .log_err(ctx)
2481 .is_ok() as libc::c_int
2482}
2483
2484#[no_mangle]
2485pub unsafe extern "C" fn dc_stop_ongoing_process(context: *mut dc_context_t) {
2486 if context.is_null() {
2487 eprintln!("ignoring careless call to dc_stop_ongoing_process()");
2488 return;
2489 }
2490 let ctx = &*context;
2491 block_on(ctx.stop_ongoing());
2492}
2493
2494#[no_mangle]
2495pub unsafe extern "C" fn dc_check_qr(
2496 context: *mut dc_context_t,
2497 qr: *const libc::c_char,
2498) -> *mut dc_lot_t {
2499 if context.is_null() || qr.is_null() {
2500 eprintln!("ignoring careless call to dc_check_qr()");
2501 return ptr::null_mut();
2502 }
2503 let ctx = &*context;
2504
2505 let lot = match block_on(qr::check_qr(ctx, &to_string_lossy(qr))) {
2506 Ok(qr) => qr.into(),
2507 Err(err) => err.into(),
2508 };
2509 Box::into_raw(Box::new(lot))
2510}
2511
2512#[no_mangle]
2513pub unsafe extern "C" fn dc_get_securejoin_qr(
2514 context: *mut dc_context_t,
2515 chat_id: u32,
2516) -> *mut libc::c_char {
2517 if context.is_null() {
2518 eprintln!("ignoring careless call to dc_get_securejoin_qr()");
2519 return "".strdup();
2520 }
2521 let ctx = &*context;
2522 let chat_id = if chat_id == 0 {
2523 None
2524 } else {
2525 Some(ChatId::new(chat_id))
2526 };
2527
2528 block_on(securejoin::get_securejoin_qr(ctx, chat_id))
2529 .unwrap_or_else(|_| "".to_string())
2530 .strdup()
2531}
2532
2533#[no_mangle]
2534pub unsafe extern "C" fn dc_get_securejoin_qr_svg(
2535 context: *mut dc_context_t,
2536 chat_id: u32,
2537) -> *mut libc::c_char {
2538 if context.is_null() {
2539 eprintln!("ignoring careless call to generate_verification_qr()");
2540 return "".strdup();
2541 }
2542 let ctx = &*context;
2543 let chat_id = if chat_id == 0 {
2544 None
2545 } else {
2546 Some(ChatId::new(chat_id))
2547 };
2548
2549 block_on(get_securejoin_qr_svg(ctx, chat_id))
2550 .unwrap_or_else(|_| "".to_string())
2551 .strdup()
2552}
2553
2554#[no_mangle]
2555pub unsafe extern "C" fn dc_join_securejoin(
2556 context: *mut dc_context_t,
2557 qr: *const libc::c_char,
2558) -> u32 {
2559 if context.is_null() || qr.is_null() {
2560 eprintln!("ignoring careless call to dc_join_securejoin()");
2561 return 0;
2562 }
2563 let ctx = &*context;
2564
2565 block_on(async move {
2566 securejoin::join_securejoin(ctx, &to_string_lossy(qr))
2567 .await
2568 .map(|chatid| chatid.to_u32())
2569 .context("failed dc_join_securejoin() call")
2570 .log_err(ctx)
2571 .unwrap_or_default()
2572 })
2573}
2574
2575#[no_mangle]
2576pub unsafe extern "C" fn dc_send_locations_to_chat(
2577 context: *mut dc_context_t,
2578 chat_id: u32,
2579 seconds: libc::c_int,
2580) {
2581 if context.is_null() || chat_id <= constants::DC_CHAT_ID_LAST_SPECIAL.to_u32() || seconds < 0 {
2582 eprintln!("ignoring careless call to dc_send_locations_to_chat()");
2583 return;
2584 }
2585 let ctx = &*context;
2586
2587 block_on(location::send_locations_to_chat(
2588 ctx,
2589 ChatId::new(chat_id),
2590 seconds as i64,
2591 ))
2592 .context("Failed dc_send_locations_to_chat()")
2593 .log_err(ctx)
2594 .ok();
2595}
2596
2597#[no_mangle]
2598pub unsafe extern "C" fn dc_is_sending_locations_to_chat(
2599 context: *mut dc_context_t,
2600 chat_id: u32,
2601) -> libc::c_int {
2602 if context.is_null() {
2603 eprintln!("ignoring careless call to dc_is_sending_locations_to_chat()");
2604 return 0;
2605 }
2606 let ctx = &*context;
2607 let chat_id = if chat_id == 0 {
2608 None
2609 } else {
2610 Some(ChatId::new(chat_id))
2611 };
2612
2613 block_on(location::is_sending_locations_to_chat(ctx, chat_id))
2614 .unwrap_or_log_default(ctx, "Failed dc_is_sending_locations_to_chat()") as libc::c_int
2615}
2616
2617#[no_mangle]
2618pub unsafe extern "C" fn dc_set_location(
2619 context: *mut dc_context_t,
2620 latitude: libc::c_double,
2621 longitude: libc::c_double,
2622 accuracy: libc::c_double,
2623) -> libc::c_int {
2624 if context.is_null() {
2625 eprintln!("ignoring careless call to dc_set_location()");
2626 return 0;
2627 }
2628 let ctx = &*context;
2629
2630 block_on(async move {
2631 location::set(ctx, latitude, longitude, accuracy)
2632 .await
2633 .log_err(ctx)
2634 .unwrap_or_default()
2635 }) as libc::c_int
2636}
2637
2638#[no_mangle]
2639pub unsafe extern "C" fn dc_get_locations(
2640 context: *mut dc_context_t,
2641 chat_id: u32,
2642 contact_id: u32,
2643 timestamp_begin: i64,
2644 timestamp_end: i64,
2645) -> *mut dc_array::dc_array_t {
2646 if context.is_null() {
2647 eprintln!("ignoring careless call to dc_get_locations()");
2648 return ptr::null_mut();
2649 }
2650 let ctx = &*context;
2651 let chat_id = if chat_id == 0 {
2652 None
2653 } else {
2654 Some(ChatId::new(chat_id))
2655 };
2656 let contact_id = if contact_id == 0 {
2657 None
2658 } else {
2659 Some(contact_id)
2660 };
2661
2662 block_on(async move {
2663 let res = location::get_range(ctx, chat_id, contact_id, timestamp_begin, timestamp_end)
2664 .await
2665 .unwrap_or_log_default(ctx, "Failed get_locations");
2666 Box::into_raw(Box::new(dc_array_t::from(res)))
2667 })
2668}
2669
2670#[no_mangle]
2671pub unsafe extern "C" fn dc_delete_all_locations(context: *mut dc_context_t) {
2672 if context.is_null() {
2673 eprintln!("ignoring careless call to dc_delete_all_locations()");
2674 return;
2675 }
2676 let ctx = &*context;
2677
2678 block_on(async move {
2679 location::delete_all(ctx)
2680 .await
2681 .context("Failed to delete locations")
2682 .log_err(ctx)
2683 .ok()
2684 });
2685}
2686
2687#[no_mangle]
2688pub unsafe extern "C" fn dc_create_qr_svg(payload: *const libc::c_char) -> *mut libc::c_char {
2689 if payload.is_null() {
2690 eprintln!("ignoring careless call to dc_create_qr_svg()");
2691 return "".strdup();
2692 }
2693
2694 create_qr_svg(&to_string_lossy(payload))
2695 .unwrap_or_else(|_| "".to_string())
2696 .strdup()
2697}
2698
2699#[no_mangle]
2700pub unsafe extern "C" fn dc_get_last_error(context: *mut dc_context_t) -> *mut libc::c_char {
2701 if context.is_null() {
2702 eprintln!("ignoring careless call to dc_get_last_error()");
2703 return "".strdup();
2704 }
2705 let ctx = &*context;
2706 ctx.get_last_error().strdup()
2707}
2708
2709pub type dc_array_t = dc_array::dc_array_t;
2712
2713#[no_mangle]
2714pub unsafe extern "C" fn dc_array_unref(a: *mut dc_array::dc_array_t) {
2715 if a.is_null() {
2716 eprintln!("ignoring careless call to dc_array_unref()");
2717 return;
2718 }
2719
2720 drop(Box::from_raw(a));
2721}
2722
2723#[no_mangle]
2724pub unsafe extern "C" fn dc_array_get_cnt(array: *const dc_array_t) -> libc::size_t {
2725 if array.is_null() {
2726 eprintln!("ignoring careless call to dc_array_get_cnt()");
2727 return 0;
2728 }
2729
2730 (*array).len()
2731}
2732#[no_mangle]
2733pub unsafe extern "C" fn dc_array_get_id(array: *const dc_array_t, index: libc::size_t) -> u32 {
2734 if array.is_null() {
2735 eprintln!("ignoring careless call to dc_array_get_id()");
2736 return 0;
2737 }
2738
2739 (*array).get_id(index)
2740}
2741#[no_mangle]
2742pub unsafe extern "C" fn dc_array_get_latitude(
2743 array: *const dc_array_t,
2744 index: libc::size_t,
2745) -> libc::c_double {
2746 if array.is_null() {
2747 eprintln!("ignoring careless call to dc_array_get_latitude()");
2748 return 0.0;
2749 }
2750
2751 (*array).get_location(index).latitude
2752}
2753#[no_mangle]
2754pub unsafe extern "C" fn dc_array_get_longitude(
2755 array: *const dc_array_t,
2756 index: libc::size_t,
2757) -> libc::c_double {
2758 if array.is_null() {
2759 eprintln!("ignoring careless call to dc_array_get_longitude()");
2760 return 0.0;
2761 }
2762
2763 (*array).get_location(index).longitude
2764}
2765#[no_mangle]
2766pub unsafe extern "C" fn dc_array_get_accuracy(
2767 array: *const dc_array_t,
2768 index: libc::size_t,
2769) -> libc::c_double {
2770 if array.is_null() {
2771 eprintln!("ignoring careless call to dc_array_get_accuracy()");
2772 return 0.0;
2773 }
2774
2775 (*array).get_location(index).accuracy
2776}
2777#[no_mangle]
2778pub unsafe extern "C" fn dc_array_get_timestamp(
2779 array: *const dc_array_t,
2780 index: libc::size_t,
2781) -> i64 {
2782 if array.is_null() {
2783 eprintln!("ignoring careless call to dc_array_get_timestamp()");
2784 return 0;
2785 }
2786
2787 (*array).get_timestamp(index).unwrap_or_default()
2788}
2789#[no_mangle]
2790pub unsafe extern "C" fn dc_array_get_chat_id(
2791 array: *const dc_array_t,
2792 index: libc::size_t,
2793) -> libc::c_uint {
2794 if array.is_null() {
2795 eprintln!("ignoring careless call to dc_array_get_chat_id()");
2796 return 0;
2797 }
2798 (*array).get_location(index).chat_id.to_u32()
2799}
2800#[no_mangle]
2801pub unsafe extern "C" fn dc_array_get_contact_id(
2802 array: *const dc_array_t,
2803 index: libc::size_t,
2804) -> libc::c_uint {
2805 if array.is_null() {
2806 eprintln!("ignoring careless call to dc_array_get_contact_id()");
2807 return 0;
2808 }
2809
2810 (*array).get_location(index).contact_id.to_u32()
2811}
2812#[no_mangle]
2813pub unsafe extern "C" fn dc_array_get_msg_id(
2814 array: *const dc_array_t,
2815 index: libc::size_t,
2816) -> libc::c_uint {
2817 if array.is_null() {
2818 eprintln!("ignoring careless call to dc_array_get_msg_id()");
2819 return 0;
2820 }
2821
2822 (*array).get_location(index).msg_id
2823}
2824#[no_mangle]
2825pub unsafe extern "C" fn dc_array_get_marker(
2826 array: *const dc_array_t,
2827 index: libc::size_t,
2828) -> *mut libc::c_char {
2829 if array.is_null() {
2830 eprintln!("ignoring careless call to dc_array_get_marker()");
2831 return std::ptr::null_mut(); }
2833
2834 if let Some(s) = (*array).get_marker(index) {
2835 s.strdup()
2836 } else {
2837 std::ptr::null_mut()
2838 }
2839}
2840
2841#[no_mangle]
2842pub unsafe extern "C" fn dc_array_search_id(
2843 array: *const dc_array_t,
2844 needle: libc::c_uint,
2845 ret_index: *mut libc::size_t,
2846) -> libc::c_int {
2847 if array.is_null() {
2848 eprintln!("ignoring careless call to dc_array_search_id()");
2849 return 0;
2850 }
2851
2852 if let Some(i) = (*array).search_id(needle) {
2853 if !ret_index.is_null() {
2854 *ret_index = i
2855 }
2856 1
2857 } else {
2858 0
2859 }
2860}
2861
2862#[no_mangle]
2867pub unsafe fn dc_array_is_independent(
2868 array: *const dc_array_t,
2869 index: libc::size_t,
2870) -> libc::c_int {
2871 if array.is_null() {
2872 eprintln!("ignoring careless call to dc_array_is_independent()");
2873 return 0;
2874 }
2875
2876 (*array).get_location(index).independent as libc::c_int
2877}
2878
2879pub struct ChatlistWrapper {
2889 context: *const dc_context_t,
2890 list: chatlist::Chatlist,
2891}
2892
2893pub type dc_chatlist_t = ChatlistWrapper;
2894
2895#[no_mangle]
2896pub unsafe extern "C" fn dc_chatlist_unref(chatlist: *mut dc_chatlist_t) {
2897 if chatlist.is_null() {
2898 eprintln!("ignoring careless call to dc_chatlist_unref()");
2899 return;
2900 }
2901 drop(Box::from_raw(chatlist));
2902}
2903
2904#[no_mangle]
2905pub unsafe extern "C" fn dc_chatlist_get_cnt(chatlist: *mut dc_chatlist_t) -> libc::size_t {
2906 if chatlist.is_null() {
2907 eprintln!("ignoring careless call to dc_chatlist_get_cnt()");
2908 return 0;
2909 }
2910 let ffi_list = &*chatlist;
2911 ffi_list.list.len() as libc::size_t
2912}
2913
2914#[no_mangle]
2915pub unsafe extern "C" fn dc_chatlist_get_chat_id(
2916 chatlist: *mut dc_chatlist_t,
2917 index: libc::size_t,
2918) -> u32 {
2919 if chatlist.is_null() {
2920 eprintln!("ignoring careless call to dc_chatlist_get_chat_id()");
2921 return 0;
2922 }
2923 let ffi_list = &*chatlist;
2924 let ctx = &*ffi_list.context;
2925 match ffi_list
2926 .list
2927 .get_chat_id(index)
2928 .context("get_chat_id failed")
2929 .log_err(ctx)
2930 {
2931 Ok(chat_id) => chat_id.to_u32(),
2932 Err(_) => 0,
2933 }
2934}
2935
2936#[no_mangle]
2937pub unsafe extern "C" fn dc_chatlist_get_msg_id(
2938 chatlist: *mut dc_chatlist_t,
2939 index: libc::size_t,
2940) -> u32 {
2941 if chatlist.is_null() {
2942 eprintln!("ignoring careless call to dc_chatlist_get_msg_id()");
2943 return 0;
2944 }
2945 let ffi_list = &*chatlist;
2946 let ctx = &*ffi_list.context;
2947 match ffi_list
2948 .list
2949 .get_msg_id(index)
2950 .context("get_msg_id failed")
2951 .log_err(ctx)
2952 {
2953 Ok(msg_id) => msg_id.map_or(0, |msg_id| msg_id.to_u32()),
2954 Err(_) => 0,
2955 }
2956}
2957
2958#[no_mangle]
2959pub unsafe extern "C" fn dc_chatlist_get_summary(
2960 chatlist: *mut dc_chatlist_t,
2961 index: libc::size_t,
2962 chat: *mut dc_chat_t,
2963) -> *mut dc_lot_t {
2964 if chatlist.is_null() {
2965 eprintln!("ignoring careless call to dc_chatlist_get_summary()");
2966 return ptr::null_mut();
2967 }
2968 let maybe_chat = if chat.is_null() {
2969 None
2970 } else {
2971 let ffi_chat = &*chat;
2972 Some(&ffi_chat.chat)
2973 };
2974 let ffi_list = &*chatlist;
2975 let ctx = &*ffi_list.context;
2976
2977 block_on(async move {
2978 let summary = ffi_list
2979 .list
2980 .get_summary(ctx, index, maybe_chat)
2981 .await
2982 .context("get_summary failed")
2983 .log_err(ctx)
2984 .unwrap_or_default();
2985 Box::into_raw(Box::new(summary.into()))
2986 })
2987}
2988
2989#[no_mangle]
2990pub unsafe extern "C" fn dc_chatlist_get_summary2(
2991 context: *mut dc_context_t,
2992 chat_id: u32,
2993 msg_id: u32,
2994) -> *mut dc_lot_t {
2995 if context.is_null() {
2996 eprintln!("ignoring careless call to dc_chatlist_get_summary2()");
2997 return ptr::null_mut();
2998 }
2999 let ctx = &*context;
3000 let msg_id = if msg_id == 0 {
3001 None
3002 } else {
3003 Some(MsgId::new(msg_id))
3004 };
3005 let summary = block_on(Chatlist::get_summary2(
3006 ctx,
3007 ChatId::new(chat_id),
3008 msg_id,
3009 None,
3010 ))
3011 .context("get_summary2 failed")
3012 .log_err(ctx)
3013 .unwrap_or_default();
3014 Box::into_raw(Box::new(summary.into()))
3015}
3016
3017#[no_mangle]
3018pub unsafe extern "C" fn dc_chatlist_get_context(
3019 chatlist: *mut dc_chatlist_t,
3020) -> *const dc_context_t {
3021 if chatlist.is_null() {
3022 eprintln!("ignoring careless call to dc_chatlist_get_context()");
3023 return ptr::null_mut();
3024 }
3025 let ffi_list = &*chatlist;
3026 ffi_list.context
3027}
3028
3029pub struct ChatWrapper {
3039 context: Context,
3040 chat: chat::Chat,
3041}
3042
3043pub type dc_chat_t = ChatWrapper;
3044
3045#[no_mangle]
3046pub unsafe extern "C" fn dc_chat_unref(chat: *mut dc_chat_t) {
3047 if chat.is_null() {
3048 eprintln!("ignoring careless call to dc_chat_unref()");
3049 return;
3050 }
3051
3052 drop(Box::from_raw(chat));
3053}
3054
3055#[no_mangle]
3056pub unsafe extern "C" fn dc_chat_get_id(chat: *mut dc_chat_t) -> u32 {
3057 if chat.is_null() {
3058 eprintln!("ignoring careless call to dc_chat_get_id()");
3059 return 0;
3060 }
3061 let ffi_chat = &*chat;
3062 ffi_chat.chat.get_id().to_u32()
3063}
3064
3065#[no_mangle]
3066pub unsafe extern "C" fn dc_chat_get_type(chat: *mut dc_chat_t) -> libc::c_int {
3067 if chat.is_null() {
3068 eprintln!("ignoring careless call to dc_chat_get_type()");
3069 return 0;
3070 }
3071 let ffi_chat = &*chat;
3072 ffi_chat.chat.get_type() as libc::c_int
3073}
3074
3075#[no_mangle]
3076pub unsafe extern "C" fn dc_chat_get_name(chat: *mut dc_chat_t) -> *mut libc::c_char {
3077 if chat.is_null() {
3078 eprintln!("ignoring careless call to dc_chat_get_name()");
3079 return "".strdup();
3080 }
3081 let ffi_chat = &*chat;
3082 ffi_chat.chat.get_name().strdup()
3083}
3084
3085#[no_mangle]
3086pub unsafe extern "C" fn dc_chat_get_mailinglist_addr(chat: *mut dc_chat_t) -> *mut libc::c_char {
3087 if chat.is_null() {
3088 eprintln!("ignoring careless call to dc_chat_get_mailinglist_addr()");
3089 return "".strdup();
3090 }
3091 let ffi_chat = &*chat;
3092 ffi_chat
3093 .chat
3094 .get_mailinglist_addr()
3095 .unwrap_or_default()
3096 .strdup()
3097}
3098
3099#[no_mangle]
3100pub unsafe extern "C" fn dc_chat_get_profile_image(chat: *mut dc_chat_t) -> *mut libc::c_char {
3101 if chat.is_null() {
3102 eprintln!("ignoring careless call to dc_chat_get_profile_image()");
3103 return ptr::null_mut(); }
3105 let ffi_chat = &*chat;
3106
3107 block_on(async move {
3108 match ffi_chat
3109 .chat
3110 .get_profile_image(&ffi_chat.context)
3111 .await
3112 .context("Failed to get profile image")
3113 .log_err(&ffi_chat.context)
3114 .unwrap_or_default()
3115 {
3116 Some(p) => p.to_string_lossy().strdup(),
3117 None => ptr::null_mut(),
3118 }
3119 })
3120}
3121
3122#[no_mangle]
3123pub unsafe extern "C" fn dc_chat_get_color(chat: *mut dc_chat_t) -> u32 {
3124 if chat.is_null() {
3125 eprintln!("ignoring careless call to dc_chat_get_color()");
3126 return 0;
3127 }
3128 let ffi_chat = &*chat;
3129
3130 block_on(ffi_chat.chat.get_color(&ffi_chat.context))
3131 .unwrap_or_log_default(&ffi_chat.context, "Failed get_color")
3132}
3133
3134#[no_mangle]
3135pub unsafe extern "C" fn dc_chat_get_visibility(chat: *mut dc_chat_t) -> libc::c_int {
3136 if chat.is_null() {
3137 eprintln!("ignoring careless call to dc_chat_get_visibility()");
3138 return 0;
3139 }
3140 let ffi_chat = &*chat;
3141 match ffi_chat.chat.visibility {
3142 ChatVisibility::Normal => 0,
3143 ChatVisibility::Archived => 1,
3144 ChatVisibility::Pinned => 2,
3145 }
3146}
3147
3148#[no_mangle]
3149pub unsafe extern "C" fn dc_chat_is_contact_request(chat: *mut dc_chat_t) -> libc::c_int {
3150 if chat.is_null() {
3151 eprintln!("ignoring careless call to dc_chat_is_contact_request()");
3152 return 0;
3153 }
3154 let ffi_chat = &*chat;
3155 ffi_chat.chat.is_contact_request() as libc::c_int
3156}
3157
3158#[no_mangle]
3159pub unsafe extern "C" fn dc_chat_is_unpromoted(chat: *mut dc_chat_t) -> libc::c_int {
3160 if chat.is_null() {
3161 eprintln!("ignoring careless call to dc_chat_is_unpromoted()");
3162 return 0;
3163 }
3164 let ffi_chat = &*chat;
3165 ffi_chat.chat.is_unpromoted() as libc::c_int
3166}
3167
3168#[no_mangle]
3169pub unsafe extern "C" fn dc_chat_is_self_talk(chat: *mut dc_chat_t) -> libc::c_int {
3170 if chat.is_null() {
3171 eprintln!("ignoring careless call to dc_chat_is_self_talk()");
3172 return 0;
3173 }
3174 let ffi_chat = &*chat;
3175 ffi_chat.chat.is_self_talk() as libc::c_int
3176}
3177
3178#[no_mangle]
3179pub unsafe extern "C" fn dc_chat_is_device_talk(chat: *mut dc_chat_t) -> libc::c_int {
3180 if chat.is_null() {
3181 eprintln!("ignoring careless call to dc_chat_is_device_talk()");
3182 return 0;
3183 }
3184 let ffi_chat = &*chat;
3185 ffi_chat.chat.is_device_talk() as libc::c_int
3186}
3187
3188#[no_mangle]
3189pub unsafe extern "C" fn dc_chat_can_send(chat: *mut dc_chat_t) -> libc::c_int {
3190 if chat.is_null() {
3191 eprintln!("ignoring careless call to dc_chat_can_send()");
3192 return 0;
3193 }
3194 let ffi_chat = &*chat;
3195 block_on(ffi_chat.chat.can_send(&ffi_chat.context))
3196 .context("can_send failed")
3197 .log_err(&ffi_chat.context)
3198 .unwrap_or_default() as libc::c_int
3199}
3200
3201#[no_mangle]
3202pub extern "C" fn dc_chat_is_protected(_chat: *mut dc_chat_t) -> libc::c_int {
3203 0
3204}
3205
3206#[no_mangle]
3207pub unsafe extern "C" fn dc_chat_is_encrypted(chat: *mut dc_chat_t) -> libc::c_int {
3208 if chat.is_null() {
3209 eprintln!("ignoring careless call to dc_chat_is_encrypted()");
3210 return 0;
3211 }
3212 let ffi_chat = &*chat;
3213
3214 block_on(ffi_chat.chat.is_encrypted(&ffi_chat.context))
3215 .unwrap_or_log_default(&ffi_chat.context, "Failed dc_chat_is_encrypted") as libc::c_int
3216}
3217
3218#[no_mangle]
3219pub unsafe extern "C" fn dc_chat_is_sending_locations(chat: *mut dc_chat_t) -> libc::c_int {
3220 if chat.is_null() {
3221 eprintln!("ignoring careless call to dc_chat_is_sending_locations()");
3222 return 0;
3223 }
3224 let ffi_chat = &*chat;
3225 ffi_chat.chat.is_sending_locations() as libc::c_int
3226}
3227
3228#[no_mangle]
3229pub unsafe extern "C" fn dc_chat_is_muted(chat: *mut dc_chat_t) -> libc::c_int {
3230 if chat.is_null() {
3231 eprintln!("ignoring careless call to dc_chat_is_muted()");
3232 return 0;
3233 }
3234 let ffi_chat = &*chat;
3235 ffi_chat.chat.is_muted() as libc::c_int
3236}
3237
3238#[no_mangle]
3239pub unsafe extern "C" fn dc_chat_get_remaining_mute_duration(chat: *mut dc_chat_t) -> i64 {
3240 if chat.is_null() {
3241 eprintln!("ignoring careless call to dc_chat_get_remaining_mute_duration()");
3242 return 0;
3243 }
3244 let ffi_chat = &*chat;
3245 if !ffi_chat.chat.is_muted() {
3246 return 0;
3247 }
3248 match ffi_chat.chat.mute_duration {
3250 MuteDuration::NotMuted => 0,
3251 MuteDuration::Forever => -1,
3252 MuteDuration::Until(when) => when
3253 .duration_since(SystemTime::now())
3254 .map(|d| d.as_secs() as i64)
3255 .unwrap_or(0),
3256 }
3257}
3258
3259#[no_mangle]
3260pub unsafe extern "C" fn dc_chat_get_info_json(
3261 context: *mut dc_context_t,
3262 chat_id: u32,
3263) -> *mut libc::c_char {
3264 if context.is_null() {
3265 eprintln!("ignoring careless call to dc_chat_get_info_json()");
3266 return "".strdup();
3267 }
3268 let ctx = &*context;
3269
3270 block_on(async move {
3271 let Ok(chat) = chat::Chat::load_from_db(ctx, ChatId::new(chat_id))
3272 .await
3273 .context("dc_get_chat_info_json() failed to load chat")
3274 .log_err(ctx)
3275 else {
3276 return "".strdup();
3277 };
3278 let Ok(info) = chat
3279 .get_info(ctx)
3280 .await
3281 .context("dc_get_chat_info_json() failed to get chat info")
3282 .log_err(ctx)
3283 else {
3284 return "".strdup();
3285 };
3286 serde_json::to_string(&info)
3287 .unwrap_or_log_default(ctx, "dc_get_chat_info_json() failed to serialise to json")
3288 .strdup()
3289 })
3290}
3291
3292pub struct MessageWrapper {
3302 context: *const dc_context_t,
3303 message: message::Message,
3304}
3305
3306pub type dc_msg_t = MessageWrapper;
3307
3308#[no_mangle]
3309pub unsafe extern "C" fn dc_msg_new(
3310 context: *mut dc_context_t,
3311 viewtype: libc::c_int,
3312) -> *mut dc_msg_t {
3313 if context.is_null() {
3314 eprintln!("ignoring careless call to dc_msg_new()");
3315 return ptr::null_mut();
3316 }
3317 let context = &*context;
3318 let viewtype = from_prim(viewtype).expect(&format!("invalid viewtype = {viewtype}"));
3319 let msg = MessageWrapper {
3320 context,
3321 message: message::Message::new(viewtype),
3322 };
3323 Box::into_raw(Box::new(msg))
3324}
3325
3326#[no_mangle]
3327pub unsafe extern "C" fn dc_msg_unref(msg: *mut dc_msg_t) {
3328 if msg.is_null() {
3329 eprintln!("ignoring careless call to dc_msg_unref()");
3330 return;
3331 }
3332
3333 drop(Box::from_raw(msg));
3334}
3335
3336#[no_mangle]
3337pub unsafe extern "C" fn dc_msg_get_id(msg: *mut dc_msg_t) -> u32 {
3338 if msg.is_null() {
3339 eprintln!("ignoring careless call to dc_msg_get_id()");
3340 return 0;
3341 }
3342 let ffi_msg = &*msg;
3343 ffi_msg.message.get_id().to_u32()
3344}
3345
3346#[no_mangle]
3347pub unsafe extern "C" fn dc_msg_get_from_id(msg: *mut dc_msg_t) -> u32 {
3348 if msg.is_null() {
3349 eprintln!("ignoring careless call to dc_msg_get_from_id()");
3350 return 0;
3351 }
3352 let ffi_msg = &*msg;
3353 ffi_msg.message.get_from_id().to_u32()
3354}
3355
3356#[no_mangle]
3357pub unsafe extern "C" fn dc_msg_get_chat_id(msg: *mut dc_msg_t) -> u32 {
3358 if msg.is_null() {
3359 eprintln!("ignoring careless call to dc_msg_get_chat_id()");
3360 return 0;
3361 }
3362 let ffi_msg = &*msg;
3363 ffi_msg.message.get_chat_id().to_u32()
3364}
3365
3366#[no_mangle]
3367pub unsafe extern "C" fn dc_msg_get_viewtype(msg: *mut dc_msg_t) -> libc::c_int {
3368 if msg.is_null() {
3369 eprintln!("ignoring careless call to dc_msg_get_viewtype()");
3370 return 0;
3371 }
3372 let ffi_msg = &*msg;
3373 ffi_msg
3374 .message
3375 .get_viewtype()
3376 .to_i64()
3377 .expect("impossible: Viewtype -> i64 conversion failed") as libc::c_int
3378}
3379
3380#[no_mangle]
3381pub unsafe extern "C" fn dc_msg_get_state(msg: *mut dc_msg_t) -> libc::c_int {
3382 if msg.is_null() {
3383 eprintln!("ignoring careless call to dc_msg_get_state()");
3384 return 0;
3385 }
3386 let ffi_msg = &*msg;
3387 ffi_msg.message.get_state() as libc::c_int
3388}
3389
3390#[no_mangle]
3391pub unsafe extern "C" fn dc_msg_get_download_state(msg: *mut dc_msg_t) -> libc::c_int {
3392 if msg.is_null() {
3393 eprintln!("ignoring careless call to dc_msg_get_download_state()");
3394 return 0;
3395 }
3396 let ffi_msg = &*msg;
3397 ffi_msg.message.download_state() as libc::c_int
3398}
3399
3400#[no_mangle]
3401pub unsafe extern "C" fn dc_msg_get_timestamp(msg: *mut dc_msg_t) -> i64 {
3402 if msg.is_null() {
3403 eprintln!("ignoring careless call to dc_msg_get_received_timestamp()");
3404 return 0;
3405 }
3406 let ffi_msg = &*msg;
3407 ffi_msg.message.get_timestamp()
3408}
3409
3410#[no_mangle]
3411pub unsafe extern "C" fn dc_msg_get_received_timestamp(msg: *mut dc_msg_t) -> i64 {
3412 if msg.is_null() {
3413 eprintln!("ignoring careless call to dc_msg_get_received_timestamp()");
3414 return 0;
3415 }
3416 let ffi_msg = &*msg;
3417 ffi_msg.message.get_received_timestamp()
3418}
3419
3420#[no_mangle]
3421pub unsafe extern "C" fn dc_msg_get_sort_timestamp(msg: *mut dc_msg_t) -> i64 {
3422 if msg.is_null() {
3423 eprintln!("ignoring careless call to dc_msg_get_sort_timestamp()");
3424 return 0;
3425 }
3426 let ffi_msg = &*msg;
3427 ffi_msg.message.get_sort_timestamp()
3428}
3429
3430#[no_mangle]
3431pub unsafe extern "C" fn dc_msg_get_text(msg: *mut dc_msg_t) -> *mut libc::c_char {
3432 if msg.is_null() {
3433 eprintln!("ignoring careless call to dc_msg_get_text()");
3434 return "".strdup();
3435 }
3436 let ffi_msg = &*msg;
3437 ffi_msg.message.get_text().strdup()
3438}
3439
3440#[no_mangle]
3441pub unsafe extern "C" fn dc_msg_get_subject(msg: *mut dc_msg_t) -> *mut libc::c_char {
3442 if msg.is_null() {
3443 eprintln!("ignoring careless call to dc_msg_get_subject()");
3444 return "".strdup();
3445 }
3446 let ffi_msg = &*msg;
3447 ffi_msg.message.get_subject().strdup()
3448}
3449
3450#[no_mangle]
3451pub unsafe extern "C" fn dc_msg_get_file(msg: *mut dc_msg_t) -> *mut libc::c_char {
3452 if msg.is_null() {
3453 eprintln!("ignoring careless call to dc_msg_get_file()");
3454 return "".strdup();
3455 }
3456 let ffi_msg = &*msg;
3457 let ctx = &*ffi_msg.context;
3458 ffi_msg
3459 .message
3460 .get_file(ctx)
3461 .map(|p| p.to_string_lossy().strdup())
3462 .unwrap_or_else(|| "".strdup())
3463}
3464
3465#[no_mangle]
3466pub unsafe extern "C" fn dc_msg_save_file(
3467 msg: *mut dc_msg_t,
3468 path: *const libc::c_char,
3469) -> libc::c_int {
3470 if msg.is_null() || path.is_null() {
3471 eprintln!("ignoring careless call to dc_msg_save_file()");
3472 return 0;
3473 }
3474 let ffi_msg = &*msg;
3475 let ctx = &*ffi_msg.context;
3476 let path = to_string_lossy(path);
3477 let r = block_on(
3478 ffi_msg
3479 .message
3480 .save_file(ctx, &std::path::PathBuf::from(path)),
3481 );
3482 match r {
3483 Ok(()) => 1,
3484 Err(_) => {
3485 r.context("Failed to save file from message")
3486 .log_err(ctx)
3487 .unwrap_or_default();
3488 0
3489 }
3490 }
3491}
3492
3493#[no_mangle]
3494pub unsafe extern "C" fn dc_msg_get_filename(msg: *mut dc_msg_t) -> *mut libc::c_char {
3495 if msg.is_null() {
3496 eprintln!("ignoring careless call to dc_msg_get_filename()");
3497 return "".strdup();
3498 }
3499 let ffi_msg = &*msg;
3500 ffi_msg.message.get_filename().unwrap_or_default().strdup()
3501}
3502
3503#[no_mangle]
3504pub unsafe extern "C" fn dc_msg_get_webxdc_blob(
3505 msg: *mut dc_msg_t,
3506 filename: *const libc::c_char,
3507 ret_bytes: *mut libc::size_t,
3508) -> *mut libc::c_char {
3509 if msg.is_null() || filename.is_null() || ret_bytes.is_null() {
3510 eprintln!("ignoring careless call to dc_msg_get_webxdc_blob()");
3511 return ptr::null_mut();
3512 }
3513 let ffi_msg = &*msg;
3514 let ctx = &*ffi_msg.context;
3515 let blob = block_on(async move {
3516 ffi_msg
3517 .message
3518 .get_webxdc_blob(ctx, &to_string_lossy(filename))
3519 .await
3520 });
3521 match blob {
3522 Ok(blob) => {
3523 *ret_bytes = blob.len();
3524 let ptr = libc::malloc(*ret_bytes);
3525 libc::memcpy(ptr, blob.as_ptr() as *mut libc::c_void, *ret_bytes);
3526 ptr as *mut libc::c_char
3527 }
3528 Err(err) => {
3529 eprintln!("failed read blob from archive: {err}");
3530 ptr::null_mut()
3531 }
3532 }
3533}
3534
3535#[no_mangle]
3536pub unsafe extern "C" fn dc_msg_get_webxdc_info(msg: *mut dc_msg_t) -> *mut libc::c_char {
3537 if msg.is_null() {
3538 eprintln!("ignoring careless call to dc_msg_get_webxdc_info()");
3539 return "".strdup();
3540 }
3541 let ffi_msg = &*msg;
3542 let ctx = &*ffi_msg.context;
3543
3544 let Ok(info) = block_on(ffi_msg.message.get_webxdc_info(ctx))
3545 .context("dc_msg_get_webxdc_info() failed to get info")
3546 .log_err(ctx)
3547 else {
3548 return "".strdup();
3549 };
3550 serde_json::to_string(&info)
3551 .unwrap_or_log_default(ctx, "dc_msg_get_webxdc_info() failed to serialise to json")
3552 .strdup()
3553}
3554
3555#[no_mangle]
3556pub unsafe extern "C" fn dc_msg_get_filemime(msg: *mut dc_msg_t) -> *mut libc::c_char {
3557 if msg.is_null() {
3558 eprintln!("ignoring careless call to dc_msg_get_filemime()");
3559 return "".strdup();
3560 }
3561 let ffi_msg = &*msg;
3562 if let Some(x) = ffi_msg.message.get_filemime() {
3563 x.strdup()
3564 } else {
3565 "".strdup()
3566 }
3567}
3568
3569#[no_mangle]
3570pub unsafe extern "C" fn dc_msg_get_filebytes(msg: *mut dc_msg_t) -> u64 {
3571 if msg.is_null() {
3572 eprintln!("ignoring careless call to dc_msg_get_filebytes()");
3573 return 0;
3574 }
3575 let ffi_msg = &*msg;
3576 let ctx = &*ffi_msg.context;
3577
3578 block_on(ffi_msg.message.get_filebytes(ctx))
3579 .unwrap_or_log_default(ctx, "Cannot get file size")
3580 .unwrap_or_default()
3581}
3582
3583#[no_mangle]
3584pub unsafe extern "C" fn dc_msg_get_width(msg: *mut dc_msg_t) -> libc::c_int {
3585 if msg.is_null() {
3586 eprintln!("ignoring careless call to dc_msg_get_width()");
3587 return 0;
3588 }
3589 let ffi_msg = &*msg;
3590 ffi_msg.message.get_width()
3591}
3592
3593#[no_mangle]
3594pub unsafe extern "C" fn dc_msg_get_height(msg: *mut dc_msg_t) -> libc::c_int {
3595 if msg.is_null() {
3596 eprintln!("ignoring careless call to dc_msg_get_height()");
3597 return 0;
3598 }
3599 let ffi_msg = &*msg;
3600 ffi_msg.message.get_height()
3601}
3602
3603#[no_mangle]
3604pub unsafe extern "C" fn dc_msg_get_duration(msg: *mut dc_msg_t) -> libc::c_int {
3605 if msg.is_null() {
3606 eprintln!("ignoring careless call to dc_msg_get_duration()");
3607 return 0;
3608 }
3609 let ffi_msg = &*msg;
3610 ffi_msg.message.get_duration()
3611}
3612
3613#[no_mangle]
3614pub unsafe extern "C" fn dc_msg_get_showpadlock(msg: *mut dc_msg_t) -> libc::c_int {
3615 if msg.is_null() {
3616 eprintln!("ignoring careless call to dc_msg_get_showpadlock()");
3617 return 0;
3618 }
3619 let ffi_msg = &*msg;
3620 ffi_msg.message.get_showpadlock() as libc::c_int
3621}
3622
3623#[no_mangle]
3624pub unsafe extern "C" fn dc_msg_is_bot(msg: *mut dc_msg_t) -> libc::c_int {
3625 if msg.is_null() {
3626 eprintln!("ignoring careless call to dc_msg_is_bot()");
3627 return 0;
3628 }
3629 let ffi_msg = &*msg;
3630 ffi_msg.message.is_bot() as libc::c_int
3631}
3632
3633#[no_mangle]
3634pub unsafe extern "C" fn dc_msg_get_ephemeral_timer(msg: *mut dc_msg_t) -> u32 {
3635 if msg.is_null() {
3636 eprintln!("ignoring careless call to dc_msg_get_ephemeral_timer()");
3637 return 0;
3638 }
3639 let ffi_msg = &*msg;
3640 ffi_msg.message.get_ephemeral_timer().to_u32()
3641}
3642
3643#[no_mangle]
3644pub unsafe extern "C" fn dc_msg_get_ephemeral_timestamp(msg: *mut dc_msg_t) -> i64 {
3645 if msg.is_null() {
3646 eprintln!("ignoring careless call to dc_msg_get_ephemeral_timer()");
3647 return 0;
3648 }
3649 let ffi_msg = &*msg;
3650 ffi_msg.message.get_ephemeral_timestamp()
3651}
3652
3653#[no_mangle]
3654pub unsafe extern "C" fn dc_msg_get_summary(
3655 msg: *mut dc_msg_t,
3656 chat: *mut dc_chat_t,
3657) -> *mut dc_lot_t {
3658 if msg.is_null() {
3659 eprintln!("ignoring careless call to dc_msg_get_summary()");
3660 return ptr::null_mut();
3661 }
3662 let maybe_chat = if chat.is_null() {
3663 None
3664 } else {
3665 let ffi_chat = &*chat;
3666 Some(&ffi_chat.chat)
3667 };
3668 let ffi_msg = &mut *msg;
3669 let ctx = &*ffi_msg.context;
3670
3671 let summary = block_on(ffi_msg.message.get_summary(ctx, maybe_chat))
3672 .context("dc_msg_get_summary failed")
3673 .log_err(ctx)
3674 .unwrap_or_default();
3675 Box::into_raw(Box::new(summary.into()))
3676}
3677
3678#[no_mangle]
3679pub unsafe extern "C" fn dc_msg_get_summarytext(
3680 msg: *mut dc_msg_t,
3681 approx_characters: libc::c_int,
3682) -> *mut libc::c_char {
3683 if msg.is_null() {
3684 eprintln!("ignoring careless call to dc_msg_get_summarytext()");
3685 return "".strdup();
3686 }
3687 let ffi_msg = &mut *msg;
3688 let ctx = &*ffi_msg.context;
3689
3690 let summary = block_on(ffi_msg.message.get_summary(ctx, None))
3691 .context("dc_msg_get_summarytext failed")
3692 .log_err(ctx)
3693 .unwrap_or_default();
3694 match usize::try_from(approx_characters) {
3695 Ok(chars) => summary.truncated_text(chars).strdup(),
3696 Err(_) => summary.text.strdup(),
3697 }
3698}
3699
3700#[no_mangle]
3701pub unsafe extern "C" fn dc_msg_get_override_sender_name(msg: *mut dc_msg_t) -> *mut libc::c_char {
3702 if msg.is_null() {
3703 eprintln!("ignoring careless call to dc_msg_get_override_sender_name()");
3704 return "".strdup();
3705 }
3706 let ffi_msg = &mut *msg;
3707
3708 ffi_msg.message.get_override_sender_name().strdup()
3709}
3710
3711#[no_mangle]
3712pub unsafe extern "C" fn dc_msg_has_deviating_timestamp(msg: *mut dc_msg_t) -> libc::c_int {
3713 if msg.is_null() {
3714 eprintln!("ignoring careless call to dc_msg_has_deviating_timestamp()");
3715 return 0;
3716 }
3717 let ffi_msg = &*msg;
3718 ffi_msg.message.has_deviating_timestamp().into()
3719}
3720
3721#[no_mangle]
3722pub unsafe extern "C" fn dc_msg_has_location(msg: *mut dc_msg_t) -> libc::c_int {
3723 if msg.is_null() {
3724 eprintln!("ignoring careless call to dc_msg_has_location()");
3725 return 0;
3726 }
3727 let ffi_msg = &*msg;
3728 ffi_msg.message.has_location() as libc::c_int
3729}
3730
3731#[no_mangle]
3732pub unsafe extern "C" fn dc_msg_is_sent(msg: *mut dc_msg_t) -> libc::c_int {
3733 if msg.is_null() {
3734 eprintln!("ignoring careless call to dc_msg_is_sent()");
3735 return 0;
3736 }
3737 let ffi_msg = &*msg;
3738 ffi_msg.message.is_sent().into()
3739}
3740
3741#[no_mangle]
3742pub unsafe extern "C" fn dc_msg_is_forwarded(msg: *mut dc_msg_t) -> libc::c_int {
3743 if msg.is_null() {
3744 eprintln!("ignoring careless call to dc_msg_is_forwarded()");
3745 return 0;
3746 }
3747 let ffi_msg = &*msg;
3748 ffi_msg.message.is_forwarded().into()
3749}
3750
3751#[no_mangle]
3752pub unsafe extern "C" fn dc_msg_is_edited(msg: *mut dc_msg_t) -> libc::c_int {
3753 if msg.is_null() {
3754 eprintln!("ignoring careless call to dc_msg_is_edited()");
3755 return 0;
3756 }
3757 let ffi_msg = &*msg;
3758 ffi_msg.message.is_edited().into()
3759}
3760
3761#[no_mangle]
3762pub unsafe extern "C" fn dc_msg_is_info(msg: *mut dc_msg_t) -> libc::c_int {
3763 if msg.is_null() {
3764 eprintln!("ignoring careless call to dc_msg_is_info()");
3765 return 0;
3766 }
3767 let ffi_msg = &*msg;
3768 ffi_msg.message.is_info().into()
3769}
3770
3771#[no_mangle]
3772pub unsafe extern "C" fn dc_msg_get_info_type(msg: *mut dc_msg_t) -> libc::c_int {
3773 if msg.is_null() {
3774 eprintln!("ignoring careless call to dc_msg_get_info_type()");
3775 return 0;
3776 }
3777 let ffi_msg = &*msg;
3778 ffi_msg.message.get_info_type() as libc::c_int
3779}
3780
3781#[no_mangle]
3782pub unsafe extern "C" fn dc_msg_get_info_contact_id(msg: *mut dc_msg_t) -> u32 {
3783 if msg.is_null() {
3784 eprintln!("ignoring careless call to dc_msg_get_info_contact_id()");
3785 return 0;
3786 }
3787 let ffi_msg = &*msg;
3788 let context = &*ffi_msg.context;
3789 block_on(ffi_msg.message.get_info_contact_id(context))
3790 .unwrap_or_default()
3791 .map(|id| id.to_u32())
3792 .unwrap_or_default()
3793}
3794
3795#[no_mangle]
3796pub unsafe extern "C" fn dc_msg_get_webxdc_href(msg: *mut dc_msg_t) -> *mut libc::c_char {
3797 if msg.is_null() {
3798 eprintln!("ignoring careless call to dc_msg_get_webxdc_href()");
3799 return "".strdup();
3800 }
3801
3802 let ffi_msg = &*msg;
3803 ffi_msg.message.get_webxdc_href().strdup()
3804}
3805
3806#[no_mangle]
3807pub unsafe extern "C" fn dc_msg_is_setupmessage(msg: *mut dc_msg_t) -> libc::c_int {
3808 if msg.is_null() {
3809 eprintln!("ignoring careless call to dc_msg_is_setupmessage()");
3810 return 0;
3811 }
3812 let ffi_msg = &*msg;
3813 ffi_msg.message.is_setupmessage().into()
3814}
3815
3816#[no_mangle]
3817pub unsafe extern "C" fn dc_msg_has_html(msg: *mut dc_msg_t) -> libc::c_int {
3818 if msg.is_null() {
3819 eprintln!("ignoring careless call to dc_msg_has_html()");
3820 return 0;
3821 }
3822 let ffi_msg = &*msg;
3823 ffi_msg.message.has_html().into()
3824}
3825
3826#[no_mangle]
3827pub unsafe extern "C" fn dc_msg_get_setupcodebegin(msg: *mut dc_msg_t) -> *mut libc::c_char {
3828 if msg.is_null() {
3829 eprintln!("ignoring careless call to dc_msg_get_setupcodebegin()");
3830 return "".strdup();
3831 }
3832 let ffi_msg = &*msg;
3833 let ctx = &*ffi_msg.context;
3834
3835 block_on(ffi_msg.message.get_setupcodebegin(ctx))
3836 .unwrap_or_default()
3837 .strdup()
3838}
3839
3840#[no_mangle]
3841pub unsafe extern "C" fn dc_msg_set_text(msg: *mut dc_msg_t, text: *const libc::c_char) {
3842 if msg.is_null() {
3843 eprintln!("ignoring careless call to dc_msg_set_text()");
3844 return;
3845 }
3846 let ffi_msg = &mut *msg;
3847 ffi_msg.message.set_text(to_string_lossy(text))
3848}
3849
3850#[no_mangle]
3851pub unsafe extern "C" fn dc_msg_set_html(msg: *mut dc_msg_t, html: *const libc::c_char) {
3852 if msg.is_null() {
3853 eprintln!("ignoring careless call to dc_msg_set_html()");
3854 return;
3855 }
3856 let ffi_msg = &mut *msg;
3857 ffi_msg.message.set_html(to_opt_string_lossy(html))
3858}
3859
3860#[no_mangle]
3861pub unsafe extern "C" fn dc_msg_set_subject(msg: *mut dc_msg_t, subject: *const libc::c_char) {
3862 if msg.is_null() {
3863 eprintln!("ignoring careless call to dc_msg_get_subject()");
3864 return;
3865 }
3866 let ffi_msg = &mut *msg;
3867 ffi_msg.message.set_subject(to_string_lossy(subject));
3868}
3869
3870#[no_mangle]
3871pub unsafe extern "C" fn dc_msg_set_override_sender_name(
3872 msg: *mut dc_msg_t,
3873 name: *const libc::c_char,
3874) {
3875 if msg.is_null() {
3876 eprintln!("ignoring careless call to dc_msg_set_override_sender_name()");
3877 return;
3878 }
3879 let ffi_msg = &mut *msg;
3880 ffi_msg
3881 .message
3882 .set_override_sender_name(to_opt_string_lossy(name))
3883}
3884
3885#[no_mangle]
3886pub unsafe extern "C" fn dc_msg_set_file_and_deduplicate(
3887 msg: *mut dc_msg_t,
3888 file: *const libc::c_char,
3889 name: *const libc::c_char,
3890 filemime: *const libc::c_char,
3891) {
3892 if msg.is_null() || file.is_null() {
3893 eprintln!("ignoring careless call to dc_msg_set_file_and_deduplicate()");
3894 return;
3895 }
3896 let ffi_msg = &mut *msg;
3897 let ctx = &*ffi_msg.context;
3898
3899 ffi_msg
3900 .message
3901 .set_file_and_deduplicate(
3902 ctx,
3903 as_path(file),
3904 to_opt_string_lossy(name).as_deref(),
3905 to_opt_string_lossy(filemime).as_deref(),
3906 )
3907 .context("Failed to set file")
3908 .log_err(&*ffi_msg.context)
3909 .ok();
3910}
3911
3912#[no_mangle]
3913pub unsafe extern "C" fn dc_msg_set_dimension(
3914 msg: *mut dc_msg_t,
3915 width: libc::c_int,
3916 height: libc::c_int,
3917) {
3918 if msg.is_null() {
3919 eprintln!("ignoring careless call to dc_msg_set_dimension()");
3920 return;
3921 }
3922 let ffi_msg = &mut *msg;
3923 ffi_msg.message.set_dimension(width, height)
3924}
3925
3926#[no_mangle]
3927pub unsafe extern "C" fn dc_msg_set_duration(msg: *mut dc_msg_t, duration: libc::c_int) {
3928 if msg.is_null() {
3929 eprintln!("ignoring careless call to dc_msg_set_duration()");
3930 return;
3931 }
3932 let ffi_msg = &mut *msg;
3933 ffi_msg.message.set_duration(duration)
3934}
3935
3936#[no_mangle]
3937pub unsafe extern "C" fn dc_msg_set_location(
3938 msg: *mut dc_msg_t,
3939 latitude: libc::c_double,
3940 longitude: libc::c_double,
3941) {
3942 if msg.is_null() {
3943 eprintln!("ignoring careless call to dc_msg_set_location()");
3944 return;
3945 }
3946 let ffi_msg = &mut *msg;
3947 ffi_msg.message.set_location(latitude, longitude)
3948}
3949
3950#[no_mangle]
3951pub unsafe extern "C" fn dc_msg_latefiling_mediasize(
3952 msg: *mut dc_msg_t,
3953 width: libc::c_int,
3954 height: libc::c_int,
3955 duration: libc::c_int,
3956) {
3957 if msg.is_null() {
3958 eprintln!("ignoring careless call to dc_msg_latefiling_mediasize()");
3959 return;
3960 }
3961 let ffi_msg = &mut *msg;
3962 let ctx = &*ffi_msg.context;
3963
3964 block_on({
3965 ffi_msg
3966 .message
3967 .latefiling_mediasize(ctx, width, height, duration)
3968 })
3969 .context("Cannot set media size")
3970 .log_err(ctx)
3971 .ok();
3972}
3973
3974#[no_mangle]
3975pub unsafe extern "C" fn dc_msg_get_error(msg: *mut dc_msg_t) -> *mut libc::c_char {
3976 if msg.is_null() {
3977 eprintln!("ignoring careless call to dc_msg_get_error()");
3978 return ptr::null_mut();
3979 }
3980 let ffi_msg = &*msg;
3981 match ffi_msg.message.error() {
3982 Some(error) => error.strdup(),
3983 None => ptr::null_mut(),
3984 }
3985}
3986
3987#[no_mangle]
3988pub unsafe extern "C" fn dc_msg_set_quote(msg: *mut dc_msg_t, quote: *const dc_msg_t) {
3989 if msg.is_null() {
3990 eprintln!("ignoring careless call to dc_msg_set_quote()");
3991 return;
3992 }
3993 let ffi_msg = &mut *msg;
3994 let quote_msg = if quote.is_null() {
3995 None
3996 } else {
3997 let ffi_quote = &*quote;
3998 if ffi_msg.context != ffi_quote.context {
3999 eprintln!("ignoring attempt to quote message from a different context");
4000 return;
4001 }
4002 Some(&ffi_quote.message)
4003 };
4004
4005 block_on(async move {
4006 ffi_msg
4007 .message
4008 .set_quote(&*ffi_msg.context, quote_msg)
4009 .await
4010 .context("failed to set quote")
4011 .log_err(&*ffi_msg.context)
4012 .ok();
4013 });
4014}
4015
4016#[no_mangle]
4017pub unsafe extern "C" fn dc_msg_get_quoted_text(msg: *const dc_msg_t) -> *mut libc::c_char {
4018 if msg.is_null() {
4019 eprintln!("ignoring careless call to dc_msg_get_quoted_text()");
4020 return ptr::null_mut();
4021 }
4022 let ffi_msg: &MessageWrapper = &*msg;
4023 ffi_msg
4024 .message
4025 .quoted_text()
4026 .map_or_else(ptr::null_mut, |s| s.strdup())
4027}
4028
4029#[no_mangle]
4030pub unsafe extern "C" fn dc_msg_get_quoted_msg(msg: *const dc_msg_t) -> *mut dc_msg_t {
4031 if msg.is_null() {
4032 eprintln!("ignoring careless call to dc_get_quoted_msg()");
4033 return ptr::null_mut();
4034 }
4035 let ffi_msg: &MessageWrapper = &*msg;
4036 let context = &*ffi_msg.context;
4037 let res = block_on(async move {
4038 ffi_msg
4039 .message
4040 .quoted_message(context)
4041 .await
4042 .context("failed to get quoted message")
4043 .log_err(context)
4044 .unwrap_or(None)
4045 });
4046
4047 match res {
4048 Some(message) => Box::into_raw(Box::new(MessageWrapper { context, message })),
4049 None => ptr::null_mut(),
4050 }
4051}
4052
4053#[no_mangle]
4054pub unsafe extern "C" fn dc_msg_get_parent(msg: *const dc_msg_t) -> *mut dc_msg_t {
4055 if msg.is_null() {
4056 eprintln!("ignoring careless call to dc_msg_get_parent()");
4057 return ptr::null_mut();
4058 }
4059 let ffi_msg: &MessageWrapper = &*msg;
4060 let context = &*ffi_msg.context;
4061 let res = block_on(async move {
4062 ffi_msg
4063 .message
4064 .parent(context)
4065 .await
4066 .context("failed to get parent message")
4067 .log_err(context)
4068 .unwrap_or(None)
4069 });
4070
4071 match res {
4072 Some(message) => Box::into_raw(Box::new(MessageWrapper { context, message })),
4073 None => ptr::null_mut(),
4074 }
4075}
4076
4077#[no_mangle]
4078pub unsafe extern "C" fn dc_msg_get_original_msg_id(msg: *const dc_msg_t) -> u32 {
4079 if msg.is_null() {
4080 eprintln!("ignoring careless call to dc_msg_get_original_msg_id()");
4081 return 0;
4082 }
4083 let ffi_msg: &MessageWrapper = &*msg;
4084 let context = &*ffi_msg.context;
4085 block_on(async move {
4086 ffi_msg
4087 .message
4088 .get_original_msg_id(context)
4089 .await
4090 .context("failed to get original message")
4091 .log_err(context)
4092 .unwrap_or_default()
4093 .map(|id| id.to_u32())
4094 .unwrap_or(0)
4095 })
4096}
4097
4098#[no_mangle]
4099pub unsafe extern "C" fn dc_msg_get_saved_msg_id(msg: *const dc_msg_t) -> u32 {
4100 if msg.is_null() {
4101 eprintln!("ignoring careless call to dc_msg_get_saved_msg_id()");
4102 return 0;
4103 }
4104 let ffi_msg: &MessageWrapper = &*msg;
4105 let context = &*ffi_msg.context;
4106 block_on(async move {
4107 ffi_msg
4108 .message
4109 .get_saved_msg_id(context)
4110 .await
4111 .context("failed to get original message")
4112 .log_err(context)
4113 .unwrap_or_default()
4114 .map(|id| id.to_u32())
4115 .unwrap_or(0)
4116 })
4117}
4118
4119#[no_mangle]
4120pub unsafe extern "C" fn dc_msg_force_plaintext(msg: *mut dc_msg_t) {
4121 if msg.is_null() {
4122 eprintln!("ignoring careless call to dc_msg_force_plaintext()");
4123 return;
4124 }
4125 let ffi_msg = &mut *msg;
4126 ffi_msg.message.force_plaintext();
4127}
4128
4129pub struct ContactWrapper {
4139 context: *const dc_context_t,
4140 contact: contact::Contact,
4141}
4142
4143pub type dc_contact_t = ContactWrapper;
4144
4145#[no_mangle]
4146pub unsafe extern "C" fn dc_contact_unref(contact: *mut dc_contact_t) {
4147 if contact.is_null() {
4148 eprintln!("ignoring careless call to dc_contact_unref()");
4149 return;
4150 }
4151 drop(Box::from_raw(contact));
4152}
4153
4154#[no_mangle]
4155pub unsafe extern "C" fn dc_contact_get_id(contact: *mut dc_contact_t) -> u32 {
4156 if contact.is_null() {
4157 eprintln!("ignoring careless call to dc_contact_get_id()");
4158 return 0;
4159 }
4160 let ffi_contact = &*contact;
4161 ffi_contact.contact.get_id().to_u32()
4162}
4163
4164#[no_mangle]
4165pub unsafe extern "C" fn dc_contact_get_addr(contact: *mut dc_contact_t) -> *mut libc::c_char {
4166 if contact.is_null() {
4167 eprintln!("ignoring careless call to dc_contact_get_addr()");
4168 return "".strdup();
4169 }
4170 let ffi_contact = &*contact;
4171 ffi_contact.contact.get_addr().strdup()
4172}
4173
4174#[no_mangle]
4175pub unsafe extern "C" fn dc_contact_get_name(contact: *mut dc_contact_t) -> *mut libc::c_char {
4176 if contact.is_null() {
4177 eprintln!("ignoring careless call to dc_contact_get_name()");
4178 return "".strdup();
4179 }
4180 let ffi_contact = &*contact;
4181 ffi_contact.contact.get_name().strdup()
4182}
4183
4184#[no_mangle]
4185pub unsafe extern "C" fn dc_contact_get_auth_name(contact: *mut dc_contact_t) -> *mut libc::c_char {
4186 if contact.is_null() {
4187 eprintln!("ignoring careless call to dc_contact_get_auth_name()");
4188 return "".strdup();
4189 }
4190 let ffi_contact = &*contact;
4191 ffi_contact.contact.get_authname().strdup()
4192}
4193
4194#[no_mangle]
4195pub unsafe extern "C" fn dc_contact_get_display_name(
4196 contact: *mut dc_contact_t,
4197) -> *mut libc::c_char {
4198 if contact.is_null() {
4199 eprintln!("ignoring careless call to dc_contact_get_display_name()");
4200 return "".strdup();
4201 }
4202 let ffi_contact = &*contact;
4203 ffi_contact.contact.get_display_name().strdup()
4204}
4205
4206#[no_mangle]
4207pub unsafe extern "C" fn dc_contact_get_name_n_addr(
4208 contact: *mut dc_contact_t,
4209) -> *mut libc::c_char {
4210 if contact.is_null() {
4211 eprintln!("ignoring careless call to dc_contact_get_name_n_addr()");
4212 return "".strdup();
4213 }
4214 let ffi_contact = &*contact;
4215 ffi_contact.contact.get_name_n_addr().strdup()
4216}
4217
4218#[no_mangle]
4219pub unsafe extern "C" fn dc_contact_get_profile_image(
4220 contact: *mut dc_contact_t,
4221) -> *mut libc::c_char {
4222 if contact.is_null() {
4223 eprintln!("ignoring careless call to dc_contact_get_profile_image()");
4224 return ptr::null_mut(); }
4226 let ffi_contact = &*contact;
4227 let ctx = &*ffi_contact.context;
4228
4229 block_on(async move {
4230 ffi_contact
4231 .contact
4232 .get_profile_image(ctx)
4233 .await
4234 .unwrap_or_log_default(ctx, "failed to get profile image")
4235 .map(|p| p.to_string_lossy().strdup())
4236 .unwrap_or_else(std::ptr::null_mut)
4237 })
4238}
4239
4240#[no_mangle]
4241pub unsafe extern "C" fn dc_contact_get_color(contact: *mut dc_contact_t) -> u32 {
4242 if contact.is_null() {
4243 eprintln!("ignoring careless call to dc_contact_get_color()");
4244 return 0;
4245 }
4246 let ffi_contact = &*contact;
4247 let ctx = &*ffi_contact.context;
4248 block_on(async move {
4249 ffi_contact
4250 .contact
4251 .get_or_gen_color(ctx)
4253 .await
4254 .context("Contact::get_color()")
4255 .log_err(ctx)
4256 .unwrap_or(0)
4257 })
4258}
4259
4260#[no_mangle]
4261pub unsafe extern "C" fn dc_contact_get_status(contact: *mut dc_contact_t) -> *mut libc::c_char {
4262 if contact.is_null() {
4263 eprintln!("ignoring careless call to dc_contact_get_status()");
4264 return "".strdup();
4265 }
4266 let ffi_contact = &*contact;
4267 ffi_contact.contact.get_status().strdup()
4268}
4269
4270#[no_mangle]
4271pub unsafe extern "C" fn dc_contact_get_last_seen(contact: *mut dc_contact_t) -> i64 {
4272 if contact.is_null() {
4273 eprintln!("ignoring careless call to dc_contact_get_last_seen()");
4274 return 0;
4275 }
4276 let ffi_contact = &*contact;
4277 ffi_contact.contact.last_seen()
4278}
4279
4280#[no_mangle]
4281pub unsafe extern "C" fn dc_contact_was_seen_recently(contact: *mut dc_contact_t) -> libc::c_int {
4282 if contact.is_null() {
4283 eprintln!("ignoring careless call to dc_contact_was_seen_recently()");
4284 return 0;
4285 }
4286 let ffi_contact = &*contact;
4287 ffi_contact.contact.was_seen_recently() as libc::c_int
4288}
4289
4290#[no_mangle]
4291pub unsafe extern "C" fn dc_contact_is_blocked(contact: *mut dc_contact_t) -> libc::c_int {
4292 if contact.is_null() {
4293 eprintln!("ignoring careless call to dc_contact_is_blocked()");
4294 return 0;
4295 }
4296 let ffi_contact = &*contact;
4297 ffi_contact.contact.is_blocked() as libc::c_int
4298}
4299
4300#[no_mangle]
4301pub unsafe extern "C" fn dc_contact_is_verified(contact: *mut dc_contact_t) -> libc::c_int {
4302 if contact.is_null() {
4303 eprintln!("ignoring careless call to dc_contact_is_verified()");
4304 return 0;
4305 }
4306 let ffi_contact = &*contact;
4307 let ctx = &*ffi_contact.context;
4308
4309 if block_on(ffi_contact.contact.is_verified(ctx))
4310 .context("is_verified failed")
4311 .log_err(ctx)
4312 .unwrap_or_default()
4313 {
4314 2
4317 } else {
4318 0
4319 }
4320}
4321
4322#[no_mangle]
4323pub unsafe extern "C" fn dc_contact_is_bot(contact: *mut dc_contact_t) -> libc::c_int {
4324 if contact.is_null() {
4325 eprintln!("ignoring careless call to dc_contact_is_bot()");
4326 return 0;
4327 }
4328 (*contact).contact.is_bot() as libc::c_int
4329}
4330
4331#[no_mangle]
4332pub unsafe extern "C" fn dc_contact_is_key_contact(contact: *mut dc_contact_t) -> libc::c_int {
4333 if contact.is_null() {
4334 eprintln!("ignoring careless call to dc_contact_is_key_contact()");
4335 return 0;
4336 }
4337 (*contact).contact.is_key_contact() as libc::c_int
4338}
4339
4340#[no_mangle]
4341pub unsafe extern "C" fn dc_contact_get_verifier_id(contact: *mut dc_contact_t) -> u32 {
4342 if contact.is_null() {
4343 eprintln!("ignoring careless call to dc_contact_get_verifier_id()");
4344 return 0;
4345 }
4346 let ffi_contact = &*contact;
4347 let ctx = &*ffi_contact.context;
4348 let verifier_contact_id = block_on(ffi_contact.contact.get_verifier_id(ctx))
4349 .context("failed to get verifier")
4350 .log_err(ctx)
4351 .unwrap_or_default()
4352 .unwrap_or_default()
4353 .unwrap_or_default();
4354
4355 verifier_contact_id.to_u32()
4356}
4357pub type dc_lot_t = lot::Lot;
4360
4361#[no_mangle]
4362pub unsafe extern "C" fn dc_lot_unref(lot: *mut dc_lot_t) {
4363 if lot.is_null() {
4364 eprintln!("ignoring careless call to dc_lot_unref()");
4365 return;
4366 }
4367
4368 drop(Box::from_raw(lot));
4369}
4370
4371#[no_mangle]
4372pub unsafe extern "C" fn dc_lot_get_text1(lot: *mut dc_lot_t) -> *mut libc::c_char {
4373 if lot.is_null() {
4374 eprintln!("ignoring careless call to dc_lot_get_text1()");
4375 return ptr::null_mut(); }
4377
4378 let lot = &*lot;
4379 lot.get_text1().strdup()
4380}
4381
4382#[no_mangle]
4383pub unsafe extern "C" fn dc_lot_get_text2(lot: *mut dc_lot_t) -> *mut libc::c_char {
4384 if lot.is_null() {
4385 eprintln!("ignoring careless call to dc_lot_get_text2()");
4386 return ptr::null_mut(); }
4388
4389 let lot = &*lot;
4390 lot.get_text2().strdup()
4391}
4392
4393#[no_mangle]
4394pub unsafe extern "C" fn dc_lot_get_text1_meaning(lot: *mut dc_lot_t) -> libc::c_int {
4395 if lot.is_null() {
4396 eprintln!("ignoring careless call to dc_lot_get_text1_meaning()");
4397 return 0;
4398 }
4399
4400 let lot = &*lot;
4401 lot.get_text1_meaning() as libc::c_int
4402}
4403
4404#[no_mangle]
4405pub unsafe extern "C" fn dc_lot_get_state(lot: *mut dc_lot_t) -> libc::c_int {
4406 if lot.is_null() {
4407 eprintln!("ignoring careless call to dc_lot_get_state()");
4408 return 0;
4409 }
4410
4411 let lot = &*lot;
4412 lot.get_state() as libc::c_int
4413}
4414
4415#[no_mangle]
4416pub unsafe extern "C" fn dc_lot_get_id(lot: *mut dc_lot_t) -> u32 {
4417 if lot.is_null() {
4418 eprintln!("ignoring careless call to dc_lot_get_id()");
4419 return 0;
4420 }
4421
4422 let lot = &*lot;
4423 lot.get_id()
4424}
4425
4426#[no_mangle]
4427pub unsafe extern "C" fn dc_lot_get_timestamp(lot: *mut dc_lot_t) -> i64 {
4428 if lot.is_null() {
4429 eprintln!("ignoring careless call to dc_lot_get_timestamp()");
4430 return 0;
4431 }
4432
4433 let lot = &*lot;
4434 lot.get_timestamp()
4435}
4436
4437#[no_mangle]
4438pub unsafe extern "C" fn dc_str_unref(s: *mut libc::c_char) {
4439 libc::free(s as *mut _)
4440}
4441
4442pub struct BackupProviderWrapper {
4443 context: *const dc_context_t,
4444 provider: BackupProvider,
4445}
4446
4447pub type dc_backup_provider_t = BackupProviderWrapper;
4448
4449#[no_mangle]
4450pub unsafe extern "C" fn dc_backup_provider_new(
4451 context: *mut dc_context_t,
4452) -> *mut dc_backup_provider_t {
4453 if context.is_null() {
4454 eprintln!("ignoring careless call to dc_backup_provider_new()");
4455 return ptr::null_mut();
4456 }
4457 let ctx = &*context;
4458 block_on(BackupProvider::prepare(ctx))
4459 .map(|provider| BackupProviderWrapper {
4460 context: ctx,
4461 provider,
4462 })
4463 .map(|ffi_provider| Box::into_raw(Box::new(ffi_provider)))
4464 .context("BackupProvider failed")
4465 .log_err(ctx)
4466 .set_last_error(ctx)
4467 .unwrap_or(ptr::null_mut())
4468}
4469
4470#[no_mangle]
4471pub unsafe extern "C" fn dc_backup_provider_get_qr(
4472 provider: *const dc_backup_provider_t,
4473) -> *mut libc::c_char {
4474 if provider.is_null() {
4475 eprintln!("ignoring careless call to dc_backup_provider_qr");
4476 return "".strdup();
4477 }
4478 let ffi_provider = &*provider;
4479 let ctx = &*ffi_provider.context;
4480 deltachat::qr::format_backup(&ffi_provider.provider.qr())
4481 .context("BackupProvider get_qr failed")
4482 .log_err(ctx)
4483 .set_last_error(ctx)
4484 .unwrap_or_default()
4485 .strdup()
4486}
4487
4488#[no_mangle]
4489pub unsafe extern "C" fn dc_backup_provider_get_qr_svg(
4490 provider: *const dc_backup_provider_t,
4491) -> *mut libc::c_char {
4492 if provider.is_null() {
4493 eprintln!("ignoring careless call to dc_backup_provider_qr_svg()");
4494 return "".strdup();
4495 }
4496 let ffi_provider = &*provider;
4497 let ctx = &*ffi_provider.context;
4498 let provider = &ffi_provider.provider;
4499 block_on(generate_backup_qr(ctx, &provider.qr()))
4500 .context("BackupProvider get_qr_svg failed")
4501 .log_err(ctx)
4502 .set_last_error(ctx)
4503 .unwrap_or_default()
4504 .strdup()
4505}
4506
4507#[no_mangle]
4508pub unsafe extern "C" fn dc_backup_provider_wait(provider: *mut dc_backup_provider_t) {
4509 if provider.is_null() {
4510 eprintln!("ignoring careless call to dc_backup_provider_wait()");
4511 return;
4512 }
4513 let ffi_provider = &mut *provider;
4514 let ctx = &*ffi_provider.context;
4515 let provider = &mut ffi_provider.provider;
4516 block_on(provider)
4517 .context("Failed to await backup provider")
4518 .log_err(ctx)
4519 .set_last_error(ctx)
4520 .ok();
4521}
4522
4523#[no_mangle]
4524pub unsafe extern "C" fn dc_backup_provider_unref(provider: *mut dc_backup_provider_t) {
4525 if provider.is_null() {
4526 eprintln!("ignoring careless call to dc_backup_provider_unref()");
4527 return;
4528 }
4529 drop(Box::from_raw(provider));
4530}
4531
4532#[no_mangle]
4533pub unsafe extern "C" fn dc_receive_backup(
4534 context: *mut dc_context_t,
4535 qr: *const libc::c_char,
4536) -> libc::c_int {
4537 if context.is_null() {
4538 eprintln!("ignoring careless call to dc_receive_backup()");
4539 return 0;
4540 }
4541 let ctx = &*context;
4542 let qr_text = to_string_lossy(qr);
4543 receive_backup(ctx.clone(), qr_text)
4544}
4545
4546fn receive_backup(ctx: Context, qr_text: String) -> libc::c_int {
4549 let qr = match block_on(qr::check_qr(&ctx, &qr_text))
4550 .context("Invalid QR code")
4551 .log_err(&ctx)
4552 .set_last_error(&ctx)
4553 {
4554 Ok(qr) => qr,
4555 Err(_) => return 0,
4556 };
4557 match block_on(imex::get_backup(&ctx, qr))
4558 .context("Get backup failed")
4559 .log_err(&ctx)
4560 .set_last_error(&ctx)
4561 {
4562 Ok(_) => 1,
4563 Err(_) => 0,
4564 }
4565}
4566
4567trait ResultExt<T, E> {
4568 fn unwrap_or_log_default(self, context: &context::Context, message: &str) -> T;
4573}
4574
4575impl<T: Default, E: std::fmt::Display> ResultExt<T, E> for Result<T, E> {
4576 fn unwrap_or_log_default(self, context: &context::Context, message: &str) -> T {
4577 self.map_err(|err| anyhow::anyhow!("{err:#}"))
4578 .with_context(|| message.to_string())
4579 .log_err(context)
4580 .unwrap_or_default()
4581 }
4582}
4583
4584trait ResultLastError<T, E>
4585where
4586 E: std::fmt::Display,
4587{
4588 fn set_last_error(self, context: &context::Context) -> Result<T, E>;
4620}
4621
4622impl<T, E> ResultLastError<T, E> for Result<T, E>
4623where
4624 E: std::fmt::Display,
4625{
4626 fn set_last_error(self, context: &context::Context) -> Result<T, E> {
4627 if let Err(ref err) = self {
4628 context.set_last_error(&format!("{err:#}"));
4629 }
4630 self
4631 }
4632}
4633
4634fn convert_and_prune_message_ids(msg_ids: *const u32, msg_cnt: libc::c_int) -> Vec<MsgId> {
4635 let ids = unsafe { std::slice::from_raw_parts(msg_ids, msg_cnt as usize) };
4636 let msg_ids: Vec<MsgId> = ids
4637 .iter()
4638 .filter(|id| **id > DC_MSG_ID_LAST_SPECIAL)
4639 .map(|id| MsgId::new(*id))
4640 .collect();
4641
4642 msg_ids
4643}
4644
4645pub type dc_provider_t = provider::Provider;
4648
4649#[no_mangle]
4650pub unsafe extern "C" fn dc_provider_new_from_email(
4651 context: *const dc_context_t,
4652 addr: *const libc::c_char,
4653) -> *const dc_provider_t {
4654 if context.is_null() || addr.is_null() {
4655 eprintln!("ignoring careless call to dc_provider_new_from_email()");
4656 return ptr::null();
4657 }
4658 let addr = to_string_lossy(addr);
4659
4660 let ctx = &*context;
4661
4662 match provider::get_provider_info_by_addr(addr.as_str())
4663 .log_err(ctx)
4664 .unwrap_or_default()
4665 {
4666 Some(provider) => provider,
4667 None => ptr::null_mut(),
4668 }
4669}
4670
4671#[no_mangle]
4672pub unsafe extern "C" fn dc_provider_new_from_email_with_dns(
4673 context: *const dc_context_t,
4674 addr: *const libc::c_char,
4675) -> *const dc_provider_t {
4676 if context.is_null() || addr.is_null() {
4677 eprintln!("ignoring careless call to dc_provider_new_from_email_with_dns()");
4678 return ptr::null();
4679 }
4680 let addr = to_string_lossy(addr);
4681
4682 let ctx = &*context;
4683
4684 match provider::get_provider_info_by_addr(addr.as_str())
4685 .log_err(ctx)
4686 .unwrap_or_default()
4687 {
4688 Some(provider) => provider,
4689 None => ptr::null_mut(),
4690 }
4691}
4692
4693#[no_mangle]
4694pub unsafe extern "C" fn dc_provider_get_overview_page(
4695 provider: *const dc_provider_t,
4696) -> *mut libc::c_char {
4697 if provider.is_null() {
4698 eprintln!("ignoring careless call to dc_provider_get_overview_page()");
4699 return "".strdup();
4700 }
4701 let provider = &*provider;
4702 provider.overview_page.strdup()
4703}
4704
4705#[no_mangle]
4706pub unsafe extern "C" fn dc_provider_get_before_login_hint(
4707 provider: *const dc_provider_t,
4708) -> *mut libc::c_char {
4709 if provider.is_null() {
4710 eprintln!("ignoring careless call to dc_provider_get_before_login_hint()");
4711 return "".strdup();
4712 }
4713 let provider = &*provider;
4714 provider.before_login_hint.strdup()
4715}
4716
4717#[no_mangle]
4718pub unsafe extern "C" fn dc_provider_get_status(provider: *const dc_provider_t) -> libc::c_int {
4719 if provider.is_null() {
4720 eprintln!("ignoring careless call to dc_provider_get_status()");
4721 return 0;
4722 }
4723 let provider = &*provider;
4724 provider.status as libc::c_int
4725}
4726
4727#[no_mangle]
4728#[allow(clippy::needless_return)]
4729pub unsafe extern "C" fn dc_provider_unref(provider: *mut dc_provider_t) {
4730 if provider.is_null() {
4731 eprintln!("ignoring careless call to dc_provider_unref()");
4732 return;
4733 }
4734 }
4737
4738pub struct AccountsWrapper {
4743 inner: Arc<RwLock<Accounts>>,
4744}
4745
4746impl Deref for AccountsWrapper {
4747 type Target = Arc<RwLock<Accounts>>;
4748
4749 fn deref(&self) -> &Self::Target {
4750 &self.inner
4751 }
4752}
4753
4754impl AccountsWrapper {
4755 fn new(accounts: Accounts) -> Self {
4756 let inner = Arc::new(RwLock::new(accounts));
4757 Self { inner }
4758 }
4759}
4760
4761pub type dc_accounts_t = AccountsWrapper;
4763
4764#[no_mangle]
4765pub unsafe extern "C" fn dc_accounts_new(
4766 dir: *const libc::c_char,
4767 writable: libc::c_int,
4768) -> *mut dc_accounts_t {
4769 setup_panic!();
4770
4771 if dir.is_null() {
4772 eprintln!("ignoring careless call to dc_accounts_new()");
4773 return ptr::null_mut();
4774 }
4775
4776 let accs = block_on(Accounts::new(as_path(dir).into(), writable != 0));
4777
4778 match accs {
4779 Ok(accs) => Box::into_raw(Box::new(AccountsWrapper::new(accs))),
4780 Err(err) => {
4781 eprintln!("failed to create accounts: {err:#}");
4783 ptr::null_mut()
4784 }
4785 }
4786}
4787
4788#[no_mangle]
4792pub unsafe extern "C" fn dc_accounts_unref(accounts: *mut dc_accounts_t) {
4793 if accounts.is_null() {
4794 eprintln!("ignoring careless call to dc_accounts_unref()");
4795 return;
4796 }
4797 let _ = Box::from_raw(accounts);
4798}
4799
4800#[no_mangle]
4801pub unsafe extern "C" fn dc_accounts_get_account(
4802 accounts: *mut dc_accounts_t,
4803 id: u32,
4804) -> *mut dc_context_t {
4805 if accounts.is_null() {
4806 eprintln!("ignoring careless call to dc_accounts_get_account()");
4807 return ptr::null_mut();
4808 }
4809
4810 let accounts = &*accounts;
4811 block_on(accounts.read())
4812 .get_account(id)
4813 .map(|ctx| Box::into_raw(Box::new(ctx)))
4814 .unwrap_or_else(std::ptr::null_mut)
4815}
4816
4817#[no_mangle]
4818pub unsafe extern "C" fn dc_accounts_get_selected_account(
4819 accounts: *mut dc_accounts_t,
4820) -> *mut dc_context_t {
4821 if accounts.is_null() {
4822 eprintln!("ignoring careless call to dc_accounts_get_selected_account()");
4823 return ptr::null_mut();
4824 }
4825
4826 let accounts = &*accounts;
4827 block_on(accounts.read())
4828 .get_selected_account()
4829 .map(|ctx| Box::into_raw(Box::new(ctx)))
4830 .unwrap_or_else(std::ptr::null_mut)
4831}
4832
4833#[no_mangle]
4834pub unsafe extern "C" fn dc_accounts_select_account(
4835 accounts: *mut dc_accounts_t,
4836 id: u32,
4837) -> libc::c_int {
4838 if accounts.is_null() {
4839 eprintln!("ignoring careless call to dc_accounts_select_account()");
4840 return 0;
4841 }
4842
4843 let accounts = &*accounts;
4844 block_on(async move {
4845 let mut accounts = accounts.write().await;
4846 match accounts.select_account(id).await {
4847 Ok(()) => 1,
4848 Err(err) => {
4849 accounts.emit_event(EventType::Error(format!(
4850 "Failed to select account: {err:#}"
4851 )));
4852 0
4853 }
4854 }
4855 })
4856}
4857
4858#[no_mangle]
4859pub unsafe extern "C" fn dc_accounts_add_account(accounts: *mut dc_accounts_t) -> u32 {
4860 if accounts.is_null() {
4861 eprintln!("ignoring careless call to dc_accounts_add_account()");
4862 return 0;
4863 }
4864
4865 let accounts = &mut *accounts;
4866
4867 block_on(async move {
4868 let mut accounts = accounts.write().await;
4869 match accounts.add_account().await {
4870 Ok(id) => id,
4871 Err(err) => {
4872 accounts.emit_event(EventType::Error(format!("Failed to add account: {err:#}")));
4873 0
4874 }
4875 }
4876 })
4877}
4878
4879#[no_mangle]
4880pub unsafe extern "C" fn dc_accounts_add_closed_account(accounts: *mut dc_accounts_t) -> u32 {
4881 if accounts.is_null() {
4882 eprintln!("ignoring careless call to dc_accounts_add_closed_account()");
4883 return 0;
4884 }
4885
4886 let accounts = &mut *accounts;
4887
4888 block_on(async move {
4889 let mut accounts = accounts.write().await;
4890 match accounts.add_closed_account().await {
4891 Ok(id) => id,
4892 Err(err) => {
4893 accounts.emit_event(EventType::Error(format!("Failed to add account: {err:#}")));
4894 0
4895 }
4896 }
4897 })
4898}
4899
4900#[no_mangle]
4901pub unsafe extern "C" fn dc_accounts_remove_account(
4902 accounts: *mut dc_accounts_t,
4903 id: u32,
4904) -> libc::c_int {
4905 if accounts.is_null() {
4906 eprintln!("ignoring careless call to dc_accounts_remove_account()");
4907 return 0;
4908 }
4909
4910 let accounts = &mut *accounts;
4911
4912 block_on(async move {
4913 let mut accounts = accounts.write().await;
4914 match accounts.remove_account(id).await {
4915 Ok(()) => 1,
4916 Err(err) => {
4917 accounts.emit_event(EventType::Error(format!(
4918 "Failed to remove account: {err:#}"
4919 )));
4920 0
4921 }
4922 }
4923 })
4924}
4925
4926#[no_mangle]
4927pub unsafe extern "C" fn dc_accounts_migrate_account(
4928 accounts: *mut dc_accounts_t,
4929 dbfile: *const libc::c_char,
4930) -> u32 {
4931 if accounts.is_null() || dbfile.is_null() {
4932 eprintln!("ignoring careless call to dc_accounts_migrate_account()");
4933 return 0;
4934 }
4935
4936 let accounts = &mut *accounts;
4937 let dbfile = to_string_lossy(dbfile);
4938
4939 block_on(async move {
4940 let mut accounts = accounts.write().await;
4941 match accounts
4942 .migrate_account(std::path::PathBuf::from(dbfile))
4943 .await
4944 {
4945 Ok(id) => id,
4946 Err(err) => {
4947 accounts.emit_event(EventType::Error(format!(
4948 "Failed to migrate account: {err:#}"
4949 )));
4950 0
4951 }
4952 }
4953 })
4954}
4955
4956#[no_mangle]
4957pub unsafe extern "C" fn dc_accounts_get_all(accounts: *mut dc_accounts_t) -> *mut dc_array_t {
4958 if accounts.is_null() {
4959 eprintln!("ignoring careless call to dc_accounts_get_all()");
4960 return ptr::null_mut();
4961 }
4962
4963 let accounts = &*accounts;
4964 let list = block_on(accounts.read()).get_all();
4965 let array: dc_array_t = list.into();
4966
4967 Box::into_raw(Box::new(array))
4968}
4969
4970#[no_mangle]
4971pub unsafe extern "C" fn dc_accounts_start_io(accounts: *mut dc_accounts_t) {
4972 if accounts.is_null() {
4973 eprintln!("ignoring careless call to dc_accounts_start_io()");
4974 return;
4975 }
4976
4977 let accounts = &mut *accounts;
4978 block_on(async move { accounts.write().await.start_io().await });
4979}
4980
4981#[no_mangle]
4982pub unsafe extern "C" fn dc_accounts_stop_io(accounts: *mut dc_accounts_t) {
4983 if accounts.is_null() {
4984 eprintln!("ignoring careless call to dc_accounts_stop_io()");
4985 return;
4986 }
4987
4988 let accounts = &*accounts;
4989 block_on(async move { accounts.read().await.stop_io().await });
4990}
4991
4992#[no_mangle]
4993pub unsafe extern "C" fn dc_accounts_maybe_network(accounts: *mut dc_accounts_t) {
4994 if accounts.is_null() {
4995 eprintln!("ignoring careless call to dc_accounts_maybe_network()");
4996 return;
4997 }
4998
4999 let accounts = &*accounts;
5000 block_on(async move { accounts.read().await.maybe_network().await });
5001}
5002
5003#[no_mangle]
5004pub unsafe extern "C" fn dc_accounts_maybe_network_lost(accounts: *mut dc_accounts_t) {
5005 if accounts.is_null() {
5006 eprintln!("ignoring careless call to dc_accounts_maybe_network_lost()");
5007 return;
5008 }
5009
5010 let accounts = &*accounts;
5011 block_on(async move { accounts.read().await.maybe_network_lost().await });
5012}
5013
5014#[no_mangle]
5015pub unsafe extern "C" fn dc_accounts_background_fetch(
5016 accounts: *mut dc_accounts_t,
5017 timeout_in_seconds: u64,
5018) -> libc::c_int {
5019 if accounts.is_null() || timeout_in_seconds <= 2 {
5020 eprintln!("ignoring careless call to dc_accounts_background_fetch()");
5021 return 0;
5022 }
5023
5024 let accounts = &*accounts;
5025 let background_fetch_future = {
5026 let lock = block_on(accounts.read());
5027 lock.background_fetch(Duration::from_secs(timeout_in_seconds))
5028 };
5029 block_on(background_fetch_future);
5031 1
5032}
5033
5034#[no_mangle]
5035pub unsafe extern "C" fn dc_accounts_stop_background_fetch(accounts: *mut dc_accounts_t) {
5036 if accounts.is_null() {
5037 eprintln!("ignoring careless call to dc_accounts_stop_background_fetch()");
5038 return;
5039 }
5040
5041 let accounts = &*accounts;
5042 block_on(accounts.read()).stop_background_fetch();
5043}
5044
5045#[no_mangle]
5046pub unsafe extern "C" fn dc_accounts_set_push_device_token(
5047 accounts: *mut dc_accounts_t,
5048 token: *const libc::c_char,
5049) {
5050 if accounts.is_null() {
5051 eprintln!("ignoring careless call to dc_accounts_set_push_device_token()");
5052 return;
5053 }
5054
5055 let accounts = &*accounts;
5056 let token = to_string_lossy(token);
5057
5058 block_on(async move {
5059 let accounts = accounts.read().await;
5060 if let Err(err) = accounts.set_push_device_token(&token).await {
5061 accounts.emit_event(EventType::Error(format!(
5062 "Failed to set notify token: {err:#}."
5063 )));
5064 }
5065 })
5066}
5067
5068#[no_mangle]
5069pub unsafe extern "C" fn dc_accounts_get_event_emitter(
5070 accounts: *mut dc_accounts_t,
5071) -> *mut dc_event_emitter_t {
5072 if accounts.is_null() {
5073 eprintln!("ignoring careless call to dc_accounts_get_event_emitter()");
5074 return ptr::null_mut();
5075 }
5076
5077 let accounts = &*accounts;
5078 let emitter = block_on(accounts.read()).get_event_emitter();
5079
5080 Box::into_raw(Box::new(emitter))
5081}
5082
5083pub struct dc_jsonrpc_instance_t {
5084 receiver: OutReceiver,
5085 handle: RpcSession<CommandApi>,
5086}
5087
5088#[no_mangle]
5089pub unsafe extern "C" fn dc_jsonrpc_init(
5090 account_manager: *mut dc_accounts_t,
5091) -> *mut dc_jsonrpc_instance_t {
5092 if account_manager.is_null() {
5093 eprintln!("ignoring careless call to dc_jsonrpc_init()");
5094 return ptr::null_mut();
5095 }
5096
5097 let account_manager = &*account_manager;
5098 let cmd_api = block_on(deltachat_jsonrpc::api::CommandApi::from_arc(
5099 account_manager.inner.clone(),
5100 ));
5101
5102 let (request_handle, receiver) = RpcClient::new();
5103 let handle = RpcSession::new(request_handle, cmd_api);
5104
5105 let instance = dc_jsonrpc_instance_t { receiver, handle };
5106
5107 Box::into_raw(Box::new(instance))
5108}
5109
5110#[no_mangle]
5111pub unsafe extern "C" fn dc_jsonrpc_unref(jsonrpc_instance: *mut dc_jsonrpc_instance_t) {
5112 if jsonrpc_instance.is_null() {
5113 eprintln!("ignoring careless call to dc_jsonrpc_unref()");
5114 return;
5115 }
5116 drop(Box::from_raw(jsonrpc_instance));
5117}
5118
5119fn spawn_handle_jsonrpc_request(handle: RpcSession<CommandApi>, request: String) {
5120 spawn(async move {
5121 handle.handle_incoming(&request).await;
5122 });
5123}
5124
5125#[no_mangle]
5126pub unsafe extern "C" fn dc_jsonrpc_request(
5127 jsonrpc_instance: *mut dc_jsonrpc_instance_t,
5128 request: *const libc::c_char,
5129) {
5130 if jsonrpc_instance.is_null() || request.is_null() {
5131 eprintln!("ignoring careless call to dc_jsonrpc_request()");
5132 return;
5133 }
5134
5135 let handle = &(*jsonrpc_instance).handle;
5136 let request = to_string_lossy(request);
5137 spawn_handle_jsonrpc_request(handle.clone(), request);
5138}
5139
5140#[no_mangle]
5141pub unsafe extern "C" fn dc_jsonrpc_next_response(
5142 jsonrpc_instance: *mut dc_jsonrpc_instance_t,
5143) -> *mut libc::c_char {
5144 if jsonrpc_instance.is_null() {
5145 eprintln!("ignoring careless call to dc_jsonrpc_next_response()");
5146 return ptr::null_mut();
5147 }
5148 let api = &*jsonrpc_instance;
5149 block_on(api.receiver.recv())
5150 .map(|result| serde_json::to_string(&result).unwrap_or_default().strdup())
5151 .unwrap_or(ptr::null_mut())
5152}
5153
5154#[no_mangle]
5155pub unsafe extern "C" fn dc_jsonrpc_blocking_call(
5156 jsonrpc_instance: *mut dc_jsonrpc_instance_t,
5157 input: *const libc::c_char,
5158) -> *mut libc::c_char {
5159 if jsonrpc_instance.is_null() {
5160 eprintln!("ignoring careless call to dc_jsonrpc_blocking_call()");
5161 return ptr::null_mut();
5162 }
5163 let api = &*jsonrpc_instance;
5164 let input = to_string_lossy(input);
5165 let res = block_on(api.handle.process_incoming(&input));
5166 match res {
5167 Some(message) => {
5168 if let Ok(message) = serde_json::to_string(&message) {
5169 message.strdup()
5170 } else {
5171 ptr::null_mut()
5172 }
5173 }
5174 None => ptr::null_mut(),
5175 }
5176}