-
-
Notifications
You must be signed in to change notification settings - Fork 86
/
deltachat.h
7434 lines (6547 loc) · 269 KB
/
deltachat.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#ifndef __DELTACHAT_H__
#define __DELTACHAT_H__
#ifdef __cplusplus
extern "C" {
#endif
#ifndef PY_CFFI
#include <stdint.h>
#include <time.h>
#endif
typedef struct _dc_context dc_context_t;
typedef struct _dc_accounts dc_accounts_t;
typedef struct _dc_array dc_array_t;
typedef struct _dc_chatlist dc_chatlist_t;
typedef struct _dc_chat dc_chat_t;
typedef struct _dc_msg dc_msg_t;
typedef struct _dc_contact dc_contact_t;
typedef struct _dc_lot dc_lot_t;
typedef struct _dc_provider dc_provider_t;
typedef struct _dc_event dc_event_t;
typedef struct _dc_event_emitter dc_event_emitter_t;
typedef struct _dc_jsonrpc_instance dc_jsonrpc_instance_t;
typedef struct _dc_backup_provider dc_backup_provider_t;
// Alias for backwards compatibility, use dc_event_emitter_t instead.
typedef struct _dc_event_emitter dc_accounts_event_emitter_t;
/**
* @mainpage Getting started
*
* This document describes how to handle the Delta Chat core library.
* For general information about Delta Chat itself,
* see <https://delta.chat> and <https://github.com/deltachat>.
*
* Let's start.
*
* First of all, you have to **create a context object**
* bound to a database.
* The database is a normal SQLite file with a "blob directory" beside it.
* This will create "example.db" database and "example.db-blobs"
* directory if they don't exist already:
*
* ~~~
* dc_context_t* context = dc_context_new(NULL, "example.db", NULL);
* ~~~
*
* After that, make sure you can **receive events from the context**.
* For that purpose, create an event emitter you can ask for events.
* If there is no event, the emitter will wait until there is one,
* so, in many situations, you will do this in a thread:
*
* ~~~
* void* event_handler(void* context)
* {
* dc_event_emitter_t* emitter = dc_get_event_emitter(context);
* dc_event_t* event;
* while ((event = dc_get_next_event(emitter)) != NULL) {
* // use the event as needed, e.g. dc_event_get_id() returns the type.
* // once you're done, unref the event to avoid memory leakage:
* dc_event_unref(event);
* }
* dc_event_emitter_unref(emitter);
* }
*
* static pthread_t event_thread;
* pthread_create(&event_thread, NULL, event_handler, context);
* ~~~
*
* The example above uses "pthreads",
* however, you can also use anything else for thread handling.
*
* Now you can **configure the context:**
*
* ~~~
* // use some real test credentials here
* dc_set_config(context, "addr", "[email protected]");
* dc_set_config(context, "mail_pw", "***");
* dc_configure(context);
* ~~~
*
* dc_configure() returns immediately.
* The configuration itself runs in the background and may take a while.
* Once done, the #DC_EVENT_CONFIGURE_PROGRESS reports success
* to the event_handler() you've defined above.
*
* The configuration result is saved in the database.
* On subsequent starts it is not needed to call dc_configure()
* (you can check this using dc_is_configured()).
*
* On a successfully configured context,
* you can finally **connect to the servers:**
*
* ~~~
* dc_start_io(context);
* ~~~
*
* Now you can **send the first message:**
*
* ~~~
* // use a real testing address here
* uint32_t contact_id = dc_create_contact(context, NULL, "[email protected]");
* uint32_t chat_id = dc_create_chat_by_contact_id(context, contact_id);
*
* dc_send_text_msg(context, chat_id, "Hi, here is my first message!");
* ~~~
*
* dc_send_text_msg() returns immediately;
* the sending itself is done in the background.
* If you check the testing address (bob),
* you should receive a normal e-mail.
* Answer this e-mail in any e-mail program with "Got it!",
* and the IO you started above will **receive the message**.
*
* You can then **list all messages** of a chat as follows:
*
* ~~~
* dc_array_t* msglist = dc_get_chat_msgs(context, chat_id, 0, 0);
* for (int i = 0; i < dc_array_get_cnt(msglist); i++)
* {
* uint32_t msg_id = dc_array_get_id(msglist, i);
* dc_msg_t* msg = dc_get_msg(context, msg_id);
* char* text = dc_msg_get_text(msg);
*
* printf("Message %i: %s\n", i+1, text);
*
* dc_str_unref(text);
* dc_msg_unref(msg);
* }
* dc_array_unref(msglist);
* ~~~
*
* This will output the following two lines:
*
* ~~~
* Message 1: Hi, here is my first message!
* Message 2: Got it!
* ~~~
*
*
* ## Thread safety
*
* All deltachat-core functions, unless stated otherwise, are thread-safe.
* In particular, it is safe to pass the same dc_context_t pointer
* to multiple functions running concurrently in different threads.
*
* All the functions are guaranteed not to use the reference passed to them
* after returning. If the function spawns a long-running process,
* such as dc_configure() or dc_imex(), it will ensure that the objects
* passed to them are not deallocated as long as they are needed.
* For example, it is safe to call dc_imex(context, ...) and
* call dc_context_unref(context) immediately after return from dc_imex().
* It is however **not safe** to call dc_context_unref(context) concurrently
* until dc_imex() returns, because dc_imex() may have not increased
* the reference count of dc_context_t yet.
*
* This means that the context may be still in use after
* dc_context_unref() call.
* For example, it is possible to start the import/export process,
* call dc_context_unref(context) immediately after
* and observe #DC_EVENT_IMEX_PROGRESS events via the event emitter.
* Once dc_get_next_event() returns NULL,
* it is safe to terminate the application.
*
* It is recommended to create dc_context_t in the main thread
* and only call dc_context_unref() once other threads that may use it,
* such as the event loop thread, are terminated.
* Common mistake is to use dc_context_unref() as a way
* to cause dc_get_next_event() return NULL and terminate event loop this way.
* If event loop thread is inside a function taking dc_context_t
* as an argument at the moment dc_context_unref() is called on the main thread,
* the behavior is undefined.
*
* Recommended way to safely terminate event loop
* and shutdown the application is
* to use a boolean variable
* indicating that the event loop should stop
* and check it in the event loop thread
* every time before calling dc_get_next_event().
* To terminate the event loop, main thread should:
* 1. Notify background threads,
* such as event loop (blocking in dc_get_next_event())
* and message processing loop (blocking in dc_wait_next_msgs()),
* that they should terminate by atomically setting the
* boolean flag in the memory
* shared between the main thread and background loop threads.
* 2. Call dc_stop_io() or dc_accounts_stop_io(), depending
* on whether a single account or account manager is used.
* Stopping I/O is guaranteed to emit at least one event
* and interrupt the event loop even if it was blocked on dc_get_next_event().
* Stopping I/O is guaranteed to interrupt a single dc_wait_next_msgs().
* 3. Wait until the event loop thread notices the flag,
* exits the event loop and terminates.
* 4. Call dc_context_unref() or dc_accounts_unref().
* 5. Keep calling dc_get_next_event() in a loop until it returns NULL,
* indicating that the contexts are deallocated.
* 6. Terminate the application.
*
* When using C API via FFI in runtimes that use automatic memory management,
* such as CPython, JVM or Node.js, take care to ensure the correct
* shutdown order and avoid calling dc_context_unref() or dc_accounts_unref()
* on the objects still in use in other threads,
* e.g. by keeping a reference to the wrapper object.
* The details depend on the runtime being used.
*
*
* ## Class reference
*
* For a class reference, see the "Classes" link atop.
*
*
* ## Further hints
*
* Here are some additional, unsorted hints that may be useful.
*
* - For `get`-functions, you have to unref the return value in some way.
*
* - Strings in function arguments or return values are usually UTF-8 encoded.
*
* - The issue-tracker for the core library is here:
* <https://github.com/deltachat/deltachat-core-rust/issues>
*
* If you need further assistance,
* please do not hesitate to contact us
* through the channels shown at https://delta.chat/en/contribute
*
* Please keep in mind, that your derived work
* must respect the Mozilla Public License 2.0 of libdeltachat
* and the respective licenses of the libraries libdeltachat links with.
*
* See you.
*/
/**
* @class dc_context_t
*
* An object representing a single account.
*
* Each account is linked to an IMAP/SMTP account and uses a separate
* SQLite database for offline functionality and for account related
* settings.
*/
// create/open/config/information
/**
* Create a new context object and try to open it without passphrase. If
* database is encrypted, the result is the same as using
* dc_context_new_closed() and the database should be opened with
* dc_context_open() before using.
*
* @memberof dc_context_t
* @param os_name Deprecated, pass NULL or empty string here.
* @param dbfile The file to use to store the database,
* something like `~/file` won't work, use absolute paths.
* @param blobdir Deprecated, pass NULL or an empty string here.
* @return A context object with some public members.
* The object must be passed to the other context functions
* and must be freed using dc_context_unref() after usage.
*/
dc_context_t* dc_context_new (const char* os_name, const char* dbfile, const char* blobdir);
/**
* Create a new context object. After creation it is usually opened with
* dc_context_open() and started with dc_start_io() so it is connected and
* mails are fetched.
*
* @memberof dc_context_t
* @param dbfile The file to use to store the database,
* something like `~/file` won't work, use absolute paths.
* @return A context object with some public members.
* The object must be passed to the other context functions
* and must be freed using dc_context_unref() after usage.
*
* If you want to use multiple context objects at the same time,
* this can be managed using dc_accounts_t.
*/
dc_context_t* dc_context_new_closed (const char* dbfile);
/**
* Opens the database with the given passphrase. This can only be used on
* closed context, such as created by dc_context_new_closed(). If the database
* is new, this operation sets the database passphrase. For existing databases
* the passphrase should be the one used to encrypt the database the first
* time.
*
* @memberof dc_context_t
* @param context The context object.
* @param passphrase The passphrase to use with the database. Pass NULL or
* empty string to use no passphrase and no encryption.
* @return 1 if the database is opened with this passphrase, 0 if the
* passphrase is incorrect and on error.
*/
int dc_context_open (dc_context_t *context, const char* passphrase);
/**
* Changes the passphrase on the open database.
* Existing database must already be encrypted and the passphrase cannot be NULL or empty.
* It is impossible to encrypt unencrypted database with this method and vice versa.
*
* @memberof dc_context_t
* @param context The context object.
* @param passphrase The new passphrase.
* @return 1 on success, 0 on error.
*/
int dc_context_change_passphrase (dc_context_t* context, const char* passphrase);
/**
* Returns 1 if database is open.
*
* @memberof dc_context_t
* @param context The context object.
* @return 1 if database is open, 0 if database is closed.
*/
int dc_context_is_open (dc_context_t *context);
/**
* Free a context object.
*
* You have to call this function
* also for accounts returned by dc_accounts_get_account() or dc_accounts_get_selected_account().
*
* @memberof dc_context_t
* @param context The context object as created by dc_context_new(),
* dc_accounts_get_account() or dc_accounts_get_selected_account().
* If NULL is given, nothing is done.
*/
void dc_context_unref (dc_context_t* context);
/**
* Get the ID of a context object.
* Each context has an ID assigned.
* If the context was created through the dc_accounts_t account manager,
* the ID is unique, no other context handled by the account manager will have the same ID.
* If the context was created by dc_context_new(), a random ID is assigned.
*
* @memberof dc_context_t
* @param context The context object as created e.g. by dc_accounts_get_account() or dc_context_new().
* @return The context-id.
*/
uint32_t dc_get_id (dc_context_t* context);
/**
* Create the event emitter that is used to receive events.
* The library will emit various @ref DC_EVENT events, such as "new message", "message read" etc.
* To get these events, you have to create an event emitter using this function
* and call dc_get_next_event() on the emitter.
*
* @memberof dc_context_t
* @param context The context object as created by dc_context_new().
* @return Returns the event emitter, NULL on errors.
* Must be freed using dc_event_emitter_unref() after usage.
*
* Note: Use only one event emitter per context.
* The result of having multiple event emitters is unspecified.
* Currently events are broadcasted to all existing event emitters,
* but previous versions delivered events to only one event emitter
* and this behavior may change again in the future.
* Events emitted before creation of event emitter
* may or may not be available to event emitter.
*/
dc_event_emitter_t* dc_get_event_emitter(dc_context_t* context);
/**
* Get the blob directory.
*
* @memberof dc_context_t
* @param context The context object.
* @return The blob directory associated with the context object, empty string if unset or on errors. NULL is never returned.
* The returned string must be released using dc_str_unref().
*/
char* dc_get_blobdir (const dc_context_t* context);
/**
* Configure the context. The configuration is handled by key=value pairs as:
*
* - `addr` = Email address to use for configuration.
* If dc_configure() fails this is not the email address actually in use.
* Use `configured_addr` to find out the email address actually in use.
* - `configured_addr` = Email address actually in use.
* Unless for testing, do not set this value using dc_set_config().
* Instead, set `addr` and call dc_configure().
* - `mail_server` = IMAP-server, guessed if left out
* - `mail_user` = IMAP-username, guessed if left out
* - `mail_pw` = IMAP-password (always needed)
* - `mail_port` = IMAP-port, guessed if left out
* - `mail_security`= IMAP-socket, one of @ref DC_SOCKET, defaults to #DC_SOCKET_AUTO
* - `send_server` = SMTP-server, guessed if left out
* - `send_user` = SMTP-user, guessed if left out
* - `send_pw` = SMTP-password, guessed if left out
* - `send_port` = SMTP-port, guessed if left out
* - `send_security`= SMTP-socket, one of @ref DC_SOCKET, defaults to #DC_SOCKET_AUTO
* - `server_flags` = IMAP-/SMTP-flags as a combination of @ref DC_LP flags, guessed if left out
* - `proxy_enabled` = Proxy enabled. Disabled by default.
* - `proxy_url` = Proxy URL. May contain multiple URLs separated by newline, but only the first one is used.
* - `imap_certificate_checks` = how to check IMAP certificates, one of the @ref DC_CERTCK flags, defaults to #DC_CERTCK_AUTO (0)
* - `smtp_certificate_checks` = deprecated option, should be set to the same value as `imap_certificate_checks` but ignored by the new core
* - `displayname` = Own name to use when sending messages. MUAs are allowed to spread this way e.g. using CC, defaults to empty
* - `selfstatus` = Own status to display, e.g. in e-mail footers, defaults to empty
* - `selfavatar` = File containing avatar. Will immediately be copied to the
* `blobdir`; the original image will not be needed anymore.
* NULL to remove the avatar.
* As for `displayname` and `selfstatus`, also the avatar is sent to the recipients.
* To save traffic, however, the avatar is attached only as needed
* and also recoded to a reasonable size.
* - `e2ee_enabled` = 0=no end-to-end-encryption, 1=prefer end-to-end-encryption (default)
* - `mdns_enabled` = 0=do not send or request read receipts,
* 1=send and request read receipts
* default=send and request read receipts, only send but not reuqest if `bot` is set
* - `bcc_self` = 0=do not send a copy of outgoing messages to self,
* 1=send a copy of outgoing messages to self (default).
* Sending messages to self is needed for a proper multi-account setup,
* however, on the other hand, may lead to unwanted notifications in non-delta clients.
* - `sentbox_watch`= 1=watch `Sent`-folder for changes,
* 0=do not watch the `Sent`-folder (default).
* - `mvbox_move` = 1=detect chat messages,
* move them to the `DeltaChat` folder,
* and watch the `DeltaChat` folder for updates (default),
* 0=do not move chat-messages
* - `only_fetch_mvbox` = 1=Do not fetch messages from folders other than the
* `DeltaChat` folder. Messages will still be fetched from the
* spam folder and `sendbox_watch` will also still be respected
* if enabled.
* 0=watch all folders normally (default)
* - `show_emails` = DC_SHOW_EMAILS_OFF (0)=
* show direct replies to chats only,
* DC_SHOW_EMAILS_ACCEPTED_CONTACTS (1)=
* also show all mails of confirmed contacts,
* DC_SHOW_EMAILS_ALL (2)=
* also show mails of unconfirmed contacts (default).
* - `key_gen_type` = DC_KEY_GEN_DEFAULT (0)=
* generate recommended key type (default),
* DC_KEY_GEN_RSA2048 (1)=
* generate RSA 2048 keypair
* DC_KEY_GEN_ED25519 (2)=
* generate Curve25519 keypair
* DC_KEY_GEN_RSA4096 (3)=
* generate RSA 4096 keypair
* - `save_mime_headers` = 1=save mime headers
* and make dc_get_mime_headers() work for subsequent calls,
* 0=do not save mime headers (default)
* - `delete_device_after` = 0=do not delete messages from device automatically (default),
* >=1=seconds, after which messages are deleted automatically from the device.
* Messages in the "saved messages" chat (see dc_chat_is_self_talk()) are skipped.
* Messages are deleted whether they were seen or not, the UI should clearly point that out.
* See also dc_estimate_deletion_cnt().
* - `delete_server_after` = 0=do not delete messages from server automatically (default),
* 1=delete messages directly after receiving from server, mvbox is skipped.
* >1=seconds, after which messages are deleted automatically from the server, mvbox is used as defined.
* "Saved messages" are deleted from the server as well as
* e-mails matching the `show_emails` settings above, the UI should clearly point that out.
* See also dc_estimate_deletion_cnt().
* - `media_quality` = DC_MEDIA_QUALITY_BALANCED (0) =
* good outgoing images/videos/voice quality at reasonable sizes (default)
* DC_MEDIA_QUALITY_WORSE (1)
* allow worse images/videos/voice quality to gain smaller sizes,
* suitable for providers or areas known to have a bad connection.
* The library uses the `media_quality` setting to use different defaults
* for recoding images sent with type #DC_MSG_IMAGE.
* If needed, recoding other file types is up to the UI.
* - `webrtc_instance` = webrtc instance to use for videochats in the form
* `[basicwebrtc:|jitsi:]https://example.com/subdir#roomname=$ROOM`
* if the URL is prefixed by `basicwebrtc`, the server is assumed to be of the type
* https://github.com/cracker0dks/basicwebrtc which some UIs have native support for.
* The type `jitsi:` may be handled by external apps.
* If no type is prefixed, the videochat is handled completely in a browser.
* - `bot` = Set to "1" if this is a bot.
* Prevents adding the "Device messages" and "Saved messages" chats,
* adds Auto-Submitted header to outgoing messages,
* accepts contact requests automatically (calling dc_accept_chat() is not needed),
* does not cut large incoming text messages,
* handles existing messages the same way as new ones if `fetch_existing_msgs=1`.
* - `last_msg_id` = database ID of the last message processed by the bot.
* This ID and IDs below it are guaranteed not to be returned
* by dc_get_next_msgs() and dc_wait_next_msgs().
* The value is updated automatically
* when dc_markseen_msgs() is called,
* but the bot can also set it manually if it processed
* the message but does not want to mark it as seen.
* For most bots calling `dc_markseen_msgs()` is the
* recommended way to update this value
* even for self-sent messages.
* - `fetch_existing_msgs` = 0=do not fetch existing messages on configure (default),
* 1=fetch most recent existing messages on configure.
* In both cases, existing recipients are added to the contact database.
* - `disable_idle` = 1=disable IMAP IDLE even if the server supports it,
* 0=use IMAP IDLE if the server supports it.
* This is a developer option used for testing polling used as an IDLE fallback.
* - `download_limit` = Messages up to this number of bytes are downloaded automatically.
* For larger messages, only the header is downloaded and a placeholder is shown.
* These messages can be downloaded fully using dc_download_full_msg() later.
* The limit is compared against raw message sizes, including headers.
* The actually used limit may be corrected
* to not mess up with non-delivery-reports or read-receipts.
* 0=no limit (default).
* Changes affect future messages only.
* - `protect_autocrypt` = Enable Header Protection for Autocrypt header.
* This is an experimental option not compatible to other MUAs
* and older Delta Chat versions.
* 1 = enable.
* 0 = disable (default).
* - `gossip_period` = How often to gossip Autocrypt keys in chats with multiple recipients, in
* seconds. 2 days by default.
* This is not supposed to be changed by UIs and only used for testing.
* - `verified_one_on_one_chats` = Feature flag for verified 1:1 chats; the UI should set it
* to 1 if it supports verified 1:1 chats.
* Regardless of this setting, `dc_chat_is_protected()` returns true while the key is verified,
* and when the key changes, an info message is posted into the chat.
* 0=Nothing else happens when the key changes.
* 1=After the key changed, `dc_chat_can_send()` returns false and `dc_chat_is_protection_broken()` returns true
* until `dc_accept_chat()` is called.
* - `is_chatmail` = 1 if the the server is a chatmail server, 0 otherwise.
* - `is_muted` = Whether a context is muted by the user.
* Muted contexts should not sound, vibrate or show notifications.
* In contrast to `dc_set_chat_mute_duration()`,
* fresh message and badge counters are not changed by this setting,
* but should be tuned down where appropriate.
* - `private_tag` = Optional tag as "Work", "Family".
* Meant to help profile owner to differ between profiles with similar names.
* - `ui.*` = All keys prefixed by `ui.` can be used by the user-interfaces for system-specific purposes.
* The prefix should be followed by the system and maybe subsystem,
* e.g. `ui.desktop.foo`, `ui.desktop.linux.bar`, `ui.android.foo`, `ui.dc40.bar`, `ui.bot.simplebot.baz`.
* These keys go to backups and allow easy per-account settings when using @ref dc_accounts_t,
* however, are not handled by the core otherwise.
* - `webxdc_realtime_enabled` = Whether the realtime APIs should be enabled.
* 0 = WebXDC realtime API is disabled and behaves as noop.
* 1 = WebXDC realtime API is enabled (default).
*
* If you want to retrieve a value, use dc_get_config().
*
* @memberof dc_context_t
* @param context The context object.
* @param key The option to change, see above.
* @param value The value to save for "key"
* @return 0=failure, 1=success
*/
int dc_set_config (dc_context_t* context, const char* key, const char* value);
/**
* Get a configuration option.
* The configuration option is set by dc_set_config() or by the library itself.
*
* Beside the options shown at dc_set_config(),
* this function can be used to query some global system values:
*
* - `sys.version` = get the version string e.g. as `1.2.3` or as `1.2.3special4`.
* - `sys.msgsize_max_recommended` = maximal recommended attachment size in bytes.
* All possible overheads are already subtracted and this value can be used e.g. for direct comparison
* with the size of a file the user wants to attach. If an attachment is larger than this value,
* an error (no warning as it should be shown to the user) is logged but the attachment is sent anyway.
* - `sys.config_keys` = get a space-separated list of all config-keys available.
* The config-keys are the keys that can be passed to the parameter `key` of this function.
* - `quota_exceeding` = 0: quota is unknown or in normal range;
* >=80: quota is about to exceed, the value is the concrete percentage,
* a device message is added when that happens, however, that value may still be interesting for bots.
*
* @memberof dc_context_t
* @param context The context object. For querying system values, this can be NULL.
* @param key The key to query.
* @return Returns current value of "key", if "key" is unset, the default
* value is returned. The returned value must be released using dc_str_unref(), NULL is never
* returned. If there is an error an empty string will be returned.
*/
char* dc_get_config (dc_context_t* context, const char* key);
/**
* Set stock string translation.
*
* The function will emit warnings if it returns an error state.
*
* @memberof dc_context_t
* @param context The context object.
* @param stock_id The integer ID of the stock message, one of the @ref DC_STR constants.
* @param stock_msg The message to be used.
* @return int (==0 on error, 1 on success)
*/
int dc_set_stock_translation(dc_context_t* context, uint32_t stock_id, const char* stock_msg);
/**
* Set configuration values from a QR code.
* Before this function is called, dc_check_qr() should confirm the type of the
* QR code is DC_QR_ACCOUNT, DC_QR_LOGIN or DC_QR_WEBRTC_INSTANCE.
*
* Internally, the function will call dc_set_config() with the appropriate keys,
* e.g. `addr` and `mail_pw` for DC_QR_ACCOUNT and DC_QR_LOGIN
* or `webrtc_instance` for DC_QR_WEBRTC_INSTANCE.
*
* @memberof dc_context_t
* @param context The context object.
* @param qr The scanned QR code.
* @return int (==0 on error, 1 on success)
*/
int dc_set_config_from_qr (dc_context_t* context, const char* qr);
/**
* Get information about the context.
*
* The information is returned by a multi-line string
* and contains information about the current configuration.
*
* If the context is not open or configured only a subset of the information
* will be available. There is no guarantee about which information will be
* included when however.
*
* @memberof dc_context_t
* @param context The context object.
* @return The string which must be released using dc_str_unref() after usage. Never returns NULL.
*/
char* dc_get_info (const dc_context_t* context);
/**
* Get URL that can be used to initiate an OAuth2 authorization.
*
* If an OAuth2 authorization is possible for a given e-mail address,
* this function returns the URL that should be opened in a browser.
*
* If the user authorizes access,
* the given redirect_uri is called by the provider.
* It's up to the UI to handle this call.
*
* The provider will attach some parameters to the URL,
* most important the parameter `code` that should be set as the `mail_pw`.
* With `server_flags` set to #DC_LP_AUTH_OAUTH2,
* dc_configure() can be called as usual afterwards.
*
* @memberof dc_context_t
* @param context The context object.
* @param addr E-mail address the user has entered.
* In case the user selects a different e-mail address during
* authorization, this is corrected in dc_configure()
* @param redirect_uri URL that will get `code` that is used as `mail_pw` then.
* Not all URLs are allowed here, however, the following should work:
* `chat.delta:/PATH`, `http://localhost:PORT/PATH`,
* `https://localhost:PORT/PATH`, `urn:ietf:wg:oauth:2.0:oob`
* (the latter just displays the code the user can copy+paste then)
* @return URL that can be opened in the browser to start OAuth2.
* Returned strings must be released using dc_str_unref().
* If OAuth2 is not possible for the given e-mail address, NULL is returned.
*/
char* dc_get_oauth2_url (dc_context_t* context, const char* addr, const char* redirect_uri);
#define DC_CONNECTIVITY_NOT_CONNECTED 1000
#define DC_CONNECTIVITY_CONNECTING 2000
#define DC_CONNECTIVITY_WORKING 3000
#define DC_CONNECTIVITY_CONNECTED 4000
/**
* Get the current connectivity, i.e. whether the device is connected to the IMAP server.
* One of:
* - DC_CONNECTIVITY_NOT_CONNECTED (1000-1999): Show e.g. the string "Not connected" or a red dot
* - DC_CONNECTIVITY_CONNECTING (2000-2999): Show e.g. the string "Connecting…" or a yellow dot
* - DC_CONNECTIVITY_WORKING (3000-3999): Show e.g. the string "Getting new messages" or a spinning wheel
* - DC_CONNECTIVITY_CONNECTED (>=4000): Show e.g. the string "Connected" or a green dot
*
* We don't use exact values but ranges here so that we can split up
* states into multiple states in the future.
*
* Meant as a rough overview that can be shown
* e.g. in the title of the main screen.
*
* If the connectivity changes, a #DC_EVENT_CONNECTIVITY_CHANGED will be emitted.
*
* @memberof dc_context_t
* @param context The context object.
* @return The current connectivity.
*/
int dc_get_connectivity (dc_context_t* context);
/**
* Get an overview of the current connectivity, and possibly more statistics.
* Meant to give the user more insight about the current status than
* the basic connectivity info returned by dc_get_connectivity(); show this
* e.g., if the user taps on said basic connectivity info.
*
* If this page changes, a #DC_EVENT_CONNECTIVITY_CHANGED will be emitted.
*
* This comes as an HTML from the core so that we can easily improve it
* and the improvement instantly reaches all UIs.
*
* @memberof dc_context_t
* @param context The context object.
* @return An HTML page with some info about the current connectivity and status.
*/
char* dc_get_connectivity_html (dc_context_t* context);
#define DC_PUSH_NOT_CONNECTED 0
#define DC_PUSH_HEARTBEAT 1
#define DC_PUSH_CONNECTED 2
/**
* Get the current push notification state.
* One of:
* - DC_PUSH_NOT_CONNECTED
* - DC_PUSH_HEARTBEAT
* - DC_PUSH_CONNECTED
*
* @memberof dc_context_t
* @param context The context object.
* @return Push notification state.
*/
int dc_get_push_state (dc_context_t* context);
/**
* Only used by the python tests.
*/
int dc_all_work_done (dc_context_t* context);
// connect
/**
* Configure a context.
* During configuration IO must not be started,
* if needed stop IO using dc_accounts_stop_io() or dc_stop_io() first.
* If the context is already configured,
* this function will try to change the configuration.
*
* - Before you call this function,
* you must set at least `addr` and `mail_pw` using dc_set_config().
*
* - Use `mail_user` to use a different user name than `addr`
* and `send_pw` to use a different password for the SMTP server.
*
* - If _no_ more options are specified,
* the function **uses autoconfigure/autodiscover**
* to get the full configuration from well-known URLs.
*
* - If _more_ options as `mail_server`, `mail_port`, `send_server`,
* `send_port`, `send_user` or `server_flags` are specified,
* **autoconfigure/autodiscover is skipped**.
*
* While dc_configure() returns immediately,
* the started configuration-job may take a while.
*
* During configuration, #DC_EVENT_CONFIGURE_PROGRESS events are emitted;
* they indicate a successful configuration as well as errors
* and may be used to create a progress bar.
*
* Additional calls to dc_configure() while a config-job is running are ignored.
* To interrupt a configuration prematurely, use dc_stop_ongoing_process();
* this is not needed if #DC_EVENT_CONFIGURE_PROGRESS reports success.
*
* If #DC_EVENT_CONFIGURE_PROGRESS reports failure,
* the core continues to use the last working configuration
* and parameters as `addr`, `mail_pw` etc. are set to that.
*
* @memberof dc_context_t
* @param context The context object.
*
* There is no need to call dc_configure() on every program start,
* the configuration result is saved in the database
* and you can use the connection directly:
*
* ~~~
* if (!dc_is_configured(context)) {
* dc_configure(context);
* // wait for progress events
* }
* ~~~
*/
void dc_configure (dc_context_t* context);
/**
* Check if the context is already configured.
*
* Typically, for unconfigured accounts, the user is prompted
* to enter some settings and dc_configure() is called in a thread then.
*
* A once successfully configured context cannot become unconfigured again;
* if a subsequent call to dc_configure() fails,
* the prior configuration is used.
*
* However, of course, also a configuration may stop working,
* as e.g. the password was changed on the server.
* To check that use e.g. dc_get_connectivity().
*
* @memberof dc_context_t
* @param context The context object.
* @return 1=context is configured and can be used;
* 0=context is not configured and a configuration by dc_configure() is required.
*/
int dc_is_configured (const dc_context_t* context);
/**
* Start job and IMAP/SMTP tasks.
* If IO is already running, nothing happens.
*
* If the context was created by the dc_accounts_t account manager,
* use dc_accounts_start_io() instead of this function.
*
* @memberof dc_context_t
* @param context The context object as created by dc_context_new().
*/
void dc_start_io (dc_context_t* context);
/**
* Stop job, IMAP, SMTP and other tasks and return when they
* are finished.
*
* Even if IO is not running, there may be pending tasks,
* so this function should always be called before releasing
* context to ensure clean termination of event loop.
*
* If the context was created by the dc_accounts_t account manager,
* use dc_accounts_stop_io() instead of this function.
*
* @memberof dc_context_t
* @param context The context object as created by dc_context_new().
*/
void dc_stop_io(dc_context_t* context);
/**
* This function should be called when there is a hint
* that the network is available again,
* e.g. as a response to system event reporting network availability.
* The library will try to send pending messages out immediately.
*
* Moreover, to have a reliable state
* when the app comes to foreground with network available,
* it may be reasonable to call the function also at that moment.
*
* It is okay to call the function unconditionally when there is
* network available, however, calling the function
* _without_ having network may interfere with the backoff algorithm
* and will led to let the jobs fail faster, with fewer retries
* and may avoid messages being sent out.
*
* Finally, if the context was created by the dc_accounts_t account manager,
* use dc_accounts_maybe_network() instead of this function.
*
* @memberof dc_context_t
* @param context The context as created by dc_context_new().
*/
void dc_maybe_network (dc_context_t* context);
/**
* Save a keypair as the default keys for the user.
*
* This API is only for testing purposes and should not be used as part of a
* normal application, use the import-export APIs instead.
*
* This saves a public/private keypair as the default keypair in the context.
* It allows avoiding having to generate a secret key for unittests which need
* one.
*
* @memberof dc_context_t
* @param context The context as created by dc_context_new().
* @param secret_data ASCII armored secret key.
* @return 1 on success, 0 on failure.
*/
int dc_preconfigure_keypair (dc_context_t* context, const char *secret_data);
// handle chatlists
#define DC_GCL_ARCHIVED_ONLY 0x01
#define DC_GCL_NO_SPECIALS 0x02
#define DC_GCL_ADD_ALLDONE_HINT 0x04
#define DC_GCL_FOR_FORWARDING 0x08
/**
* Get a list of chats.
* The list can be filtered by query parameters.
*
* The list is already sorted and starts with the most recent chat in use.
* The sorting takes care of invalid sending dates, drafts and chats without messages.
* Clients should not try to re-sort the list as this would be an expensive action
* and would result in inconsistencies between clients.
*
* To get information about each entry, use e.g. dc_chatlist_get_summary().
*
* By default, the function adds some special entries to the list.
* These special entries can be identified by the ID returned by dc_chatlist_get_chat_id():
* - DC_CHAT_ID_ARCHIVED_LINK (6) - this special chat is present if the user has
* archived _any_ chat using dc_set_chat_visibility(). The UI should show a link as
* "Show archived chats", if the user clicks this item, the UI should show a
* list of all archived chats that can be created by this function hen using
* the DC_GCL_ARCHIVED_ONLY flag.
* - DC_CHAT_ID_ALLDONE_HINT (7) - this special chat is present
* if DC_GCL_ADD_ALLDONE_HINT is added to listflags
* and if there are only archived chats.
*
* @memberof dc_context_t
* @param context The context object as returned by dc_context_new().
* @param flags A combination of flags:
* - if the flag DC_GCL_ARCHIVED_ONLY is set, only archived chats are returned.
* if DC_GCL_ARCHIVED_ONLY is not set, only unarchived chats are returned and
* the pseudo-chat DC_CHAT_ID_ARCHIVED_LINK is added if there are _any_ archived
* chats
* - the flag DC_GCL_FOR_FORWARDING sorts "Saved messages" to the top of the chatlist
* and hides the "Device chat" and contact requests.
* typically used on forwarding, may be combined with DC_GCL_NO_SPECIALS
* to also hide the archive link.
* - if the flag DC_GCL_NO_SPECIALS is set, archive link is not added
* to the list (may be used e.g. for selecting chats on forwarding, the flag is
* not needed when DC_GCL_ARCHIVED_ONLY is already set)
* - if the flag DC_GCL_ADD_ALLDONE_HINT is set, DC_CHAT_ID_ALLDONE_HINT
* is added as needed.
* @param query_str An optional query for filtering the list. Only chats matching this query
* are returned. Give NULL for no filtering. When `is:unread` is contained in the query,
* the chatlist is filtered such that only chats with unread messages show up.
* @param query_id An optional contact ID for filtering the list. Only chats including this contact ID
* are returned. Give 0 for no filtering.
* @return A chatlist as an dc_chatlist_t object.
* On errors, NULL is returned.
* Must be freed using dc_chatlist_unref() when no longer used.
*
* See also: dc_get_chat_msgs() to get the messages of a single chat.
*/
dc_chatlist_t* dc_get_chatlist (dc_context_t* context, int flags, const char* query_str, uint32_t query_id);
// handle chats
/**
* Create a normal chat with a single user. To create group chats,
* see dc_create_group_chat().
*
* If a chat already exists, this ID is returned, otherwise a new chat is created;
* to get the chat messages, use dc_get_chat_msgs().
*
* @memberof dc_context_t
* @param context The context object as returned from dc_context_new().
* @param contact_id The contact ID to create the chat for. If there is already
* a chat with this contact, the already existing ID is returned.
* @return The created or reused chat ID on success. 0 on errors.
*/
uint32_t dc_create_chat_by_contact_id (dc_context_t* context, uint32_t contact_id);
/**
* Check, if there is a normal chat with a given contact.
* To get the chat messages, use dc_get_chat_msgs().
*
* @memberof dc_context_t
* @param context The context object as returned from dc_context_new().
* @param contact_id The contact ID to check.
* @return If there is a normal chat with the given contact_id, this chat_id is
* returned. If there is no normal chat with the contact_id, the function
* returns 0.
*/
uint32_t dc_get_chat_id_by_contact_id (dc_context_t* context, uint32_t contact_id);
/**
* Prepare a message for sending.
*
* Call this function if the file to be sent is still in creation.
* Once you're done with creating the file, call dc_send_msg() as usual
* and the message will really be sent.
*
* This is useful as the user can already send the next messages while
* e.g. the recoding of a video is not yet finished. Or the user can even forward
* the message with the file being still in creation to other groups.
*
* Files being sent with the increation-method must be placed in the
* blob directory, see dc_get_blobdir().
* If the increation-method is not used - which is probably the normal case -
* dc_send_msg() copies the file to the blob directory if it is not yet there.
* To distinguish the two cases, msg->state must be set properly. The easiest
* way to ensure this is to re-use the same object for both calls.
*
* Example:
* ~~~
* char* blobdir = dc_get_blobdir(context);
* char* file_to_send = mprintf("%s/%s", blobdir, "send.mp4")
*
* dc_msg_t* msg = dc_msg_new(context, DC_MSG_VIDEO);
* dc_msg_set_file(msg, file_to_send, NULL);
* dc_prepare_msg(context, chat_id, msg);
*
* // ... create the file ...
*