mirror of
https://github.com/chatmail/core.git
synced 2026-10-02 11:10:25 +03:00
api!: remove verification methods from the FFI and JSON-RPC APIs
Core no longer tracks verification, so the API has nothing left to report and UIs should drop their checkmark and "Introduced by" code. BREAKING CHANGE: dc_contact_is_verified() and dc_contact_get_verifier_id() are removed. BREAKING CHANGE: the JSON-RPC Contact object loses the `isVerified` and `verifierId` fields. A bot reading `snapshot.is_verified` now gets an `AttributeError` at runtime. BREAKING CHANGE: the Python bindings lose `Contact.is_verified()` and `Contact.get_verifier()`. BREAKING CHANGE: DC_STR_CONTACT_VERIFIED (35) is removed, so UIs should stop registering a translation for it. A stock id core does not know is logged and otherwise ignored, so an un-updated client keeps working.
This commit is contained in:
+13
-69
@@ -1778,8 +1778,6 @@ int dc_is_contact_in_chat (dc_context_t* context, uint32_t ch
|
|||||||
* If the group is already _promoted_ (any message was sent to the group),
|
* If the group is already _promoted_ (any message was sent to the group),
|
||||||
* all group members are informed by a special status message that is sent automatically by this function.
|
* all group members are informed by a special status message that is sent automatically by this function.
|
||||||
*
|
*
|
||||||
* If the group has group protection enabled, only verified contacts can be added to the group.
|
|
||||||
*
|
|
||||||
* Sends out #DC_EVENT_CHAT_MODIFIED and #DC_EVENT_MSGS_CHANGED if a status message was sent.
|
* Sends out #DC_EVENT_CHAT_MODIFIED and #DC_EVENT_MSGS_CHANGED if a status message was sent.
|
||||||
*
|
*
|
||||||
* @memberof dc_context_t
|
* @memberof dc_context_t
|
||||||
@@ -2278,7 +2276,7 @@ void dc_block_contact (dc_context_t* context, uint32_t co
|
|||||||
/**
|
/**
|
||||||
* Get encryption info for a contact.
|
* Get encryption info for a contact.
|
||||||
* Get a multi-line encryption info, containing your fingerprint and the
|
* Get a multi-line encryption info, containing your fingerprint and the
|
||||||
* fingerprint of the contact, used e.g. to compare the fingerprints for a simple out-of-band verification.
|
* fingerprint of the contact, used e.g. to compare the fingerprints out-of-band.
|
||||||
*
|
*
|
||||||
* @memberof dc_context_t
|
* @memberof dc_context_t
|
||||||
* @param context The context object.
|
* @param context The context object.
|
||||||
@@ -2445,7 +2443,7 @@ char* dc_imex_has_backup (dc_context_t* context, const char*
|
|||||||
void dc_stop_ongoing_process (dc_context_t* context);
|
void dc_stop_ongoing_process (dc_context_t* context);
|
||||||
|
|
||||||
|
|
||||||
// out-of-band verification
|
// securejoin
|
||||||
|
|
||||||
#define DC_QR_ASK_VERIFYCONTACT 200 // id=contact
|
#define DC_QR_ASK_VERIFYCONTACT 200 // id=contact
|
||||||
#define DC_QR_ASK_VERIFYGROUP 202 // text1=groupname
|
#define DC_QR_ASK_VERIFYGROUP 202 // text1=groupname
|
||||||
@@ -2480,7 +2478,7 @@ void dc_stop_ongoing_process (dc_context_t* context);
|
|||||||
* The QR code state is returned in dc_lot_t::state as:
|
* The QR code state is returned in dc_lot_t::state as:
|
||||||
*
|
*
|
||||||
* - DC_QR_ASK_VERIFYCONTACT with dc_lot_t::id=Contact ID:
|
* - DC_QR_ASK_VERIFYCONTACT with dc_lot_t::id=Contact ID:
|
||||||
* ask whether to verify the contact;
|
* ask whether to start chatting with the contact;
|
||||||
* if so, start the protocol with dc_join_securejoin().
|
* if so, start the protocol with dc_join_securejoin().
|
||||||
*
|
*
|
||||||
* - DC_QR_ASK_VERIFYGROUP or DC_QR_ASK_VERIFYBROADCAST
|
* - DC_QR_ASK_VERIFYGROUP or DC_QR_ASK_VERIFYBROADCAST
|
||||||
@@ -2489,7 +2487,7 @@ void dc_stop_ongoing_process (dc_context_t* context);
|
|||||||
* if so, start the protocol with dc_join_securejoin().
|
* if so, start the protocol with dc_join_securejoin().
|
||||||
*
|
*
|
||||||
* - DC_QR_FPR_OK with dc_lot_t::id=Contact ID:
|
* - DC_QR_FPR_OK with dc_lot_t::id=Contact ID:
|
||||||
* contact fingerprint verified,
|
* contact fingerprint matches,
|
||||||
* ask the user if they want to start chatting;
|
* ask the user if they want to start chatting;
|
||||||
* if so, call dc_create_chat_by_contact_id().
|
* if so, call dc_create_chat_by_contact_id().
|
||||||
*
|
*
|
||||||
@@ -2565,12 +2563,12 @@ dc_lot_t* dc_check_qr (dc_context_t* context, const char*
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get QR code text that will offer an Setup-Contact or Verified-Group invitation.
|
* Get QR code text that will offer a SecureJoin invitation.
|
||||||
*
|
*
|
||||||
* The scanning device will pass the scanned content to dc_check_qr() then;
|
* The scanning device will pass the scanned content to dc_check_qr() then;
|
||||||
* if dc_check_qr() returns
|
* if dc_check_qr() returns
|
||||||
* DC_QR_ASK_VERIFYCONTACT, DC_QR_ASK_VERIFYGROUP or DC_QR_ASK_VERIFYBROADCAST
|
* DC_QR_ASK_VERIFYCONTACT, DC_QR_ASK_VERIFYGROUP or DC_QR_ASK_VERIFYBROADCAST
|
||||||
* an out-of-band-verification can be joined using dc_join_securejoin()
|
* the SecureJoin protocol can be started using dc_join_securejoin()
|
||||||
*
|
*
|
||||||
* The returned text will also work as a normal https:-link,
|
* The returned text will also work as a normal https:-link,
|
||||||
* so that the QR code is useful also without Delta Chat being installed
|
* so that the QR code is useful also without Delta Chat being installed
|
||||||
@@ -2581,9 +2579,8 @@ dc_lot_t* dc_check_qr (dc_context_t* context, const char*
|
|||||||
* @memberof dc_context_t
|
* @memberof dc_context_t
|
||||||
* @param context The context object.
|
* @param context The context object.
|
||||||
* @param chat_id If set to a group-chat-id,
|
* @param chat_id If set to a group-chat-id,
|
||||||
* the Verified-Group-Invite protocol is offered in the QR code;
|
* the SecureJoin QR code for the group is returned.
|
||||||
* works for protected groups as well as for normal groups.
|
* If set to 0, the setup contact QR code is returned.
|
||||||
* If set to 0, the Setup-Contact protocol is offered in the QR code.
|
|
||||||
* See https://securejoin.delta.chat/
|
* See https://securejoin.delta.chat/
|
||||||
* for details about both protocols.
|
* for details about both protocols.
|
||||||
* @return The text that should go to the QR code,
|
* @return The text that should go to the QR code,
|
||||||
@@ -2609,7 +2606,7 @@ char* dc_get_securejoin_qr (dc_context_t* context, uint32_t ch
|
|||||||
char* dc_get_securejoin_qr_svg (dc_context_t* context, uint32_t chat_id);
|
char* dc_get_securejoin_qr_svg (dc_context_t* context, uint32_t chat_id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Continue a Setup-Contact or Verified-Group-Invite protocol
|
* Continue the SecureJoin protocol
|
||||||
* started on another device with dc_get_securejoin_qr().
|
* started on another device with dc_get_securejoin_qr().
|
||||||
* This function is typically called when dc_check_qr() returns
|
* This function is typically called when dc_check_qr() returns
|
||||||
* lot.state=DC_QR_ASK_VERIFYCONTACT, lot.state=DC_QR_ASK_VERIFYGROUP or lot.state=DC_QR_ASK_VERIFYBROADCAST
|
* lot.state=DC_QR_ASK_VERIFYCONTACT, lot.state=DC_QR_ASK_VERIFYGROUP or lot.state=DC_QR_ASK_VERIFYBROADCAST
|
||||||
@@ -3575,7 +3572,6 @@ dc_lot_t* dc_chatlist_get_summary2 (dc_context_t* context, uint32_t ch
|
|||||||
* last-message-state: @ref DC_STATE constant
|
* last-message-state: @ref DC_STATE constant
|
||||||
* last-message-date:
|
* last-message-date:
|
||||||
* avatar-path: path-to-blobfile
|
* avatar-path: path-to-blobfile
|
||||||
* is_verified: yes/no
|
|
||||||
* @return a UTF8-encoded JSON string containing all requested info. Must be freed using dc_str_unref(). NULL is never returned.
|
* @return a UTF8-encoded JSON string containing all requested info. Must be freed using dc_str_unref(). NULL is never returned.
|
||||||
*/
|
*/
|
||||||
char* dc_chat_get_info_json (dc_context_t* context, size_t chat_id);
|
char* dc_chat_get_info_json (dc_context_t* context, size_t chat_id);
|
||||||
@@ -5115,19 +5111,6 @@ int dc_contact_was_seen_recently (const dc_contact_t* contact);
|
|||||||
int dc_contact_is_blocked (const dc_contact_t* contact);
|
int dc_contact_is_blocked (const dc_contact_t* contact);
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the contact
|
|
||||||
* can be added to protected chats.
|
|
||||||
*
|
|
||||||
* See dc_contact_get_verifier_id() for a guidance how to display these information.
|
|
||||||
*
|
|
||||||
* @memberof dc_contact_t
|
|
||||||
* @param contact The contact object.
|
|
||||||
* @return 0: contact is not verified.
|
|
||||||
* 2: SELF and contact have verified their fingerprints in both directions.
|
|
||||||
*/
|
|
||||||
int dc_contact_is_verified (dc_contact_t* contact);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether contact is a bot.
|
* Returns whether contact is a bot.
|
||||||
*
|
*
|
||||||
@@ -5152,36 +5135,6 @@ int dc_contact_is_bot (dc_contact_t* contact);
|
|||||||
int dc_contact_is_key_contact (dc_contact_t* contact);
|
int dc_contact_is_key_contact (dc_contact_t* contact);
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the contact ID that verified a contact.
|
|
||||||
*
|
|
||||||
* As verifier may be unknown,
|
|
||||||
* use dc_contact_is_verified() to check if a contact can be added to a protected chat.
|
|
||||||
*
|
|
||||||
* UI should display the information in the contact's profile as follows:
|
|
||||||
*
|
|
||||||
* - If dc_contact_get_verifier_id() != 0,
|
|
||||||
* display text "Introduced by ..."
|
|
||||||
* with the name of the contact
|
|
||||||
* formatted by dc_contact_get_name().
|
|
||||||
* Prefix the text by a green checkmark.
|
|
||||||
*
|
|
||||||
* - If dc_contact_get_verifier_id() == 0 and dc_contact_is_verified() != 0,
|
|
||||||
* display "Introduced" prefixed by a green checkmark.
|
|
||||||
*
|
|
||||||
* - if dc_contact_get_verifier_id() == 0 and dc_contact_is_verified() == 0,
|
|
||||||
* display nothing
|
|
||||||
*
|
|
||||||
* @memberof dc_contact_t
|
|
||||||
* @param contact The contact object.
|
|
||||||
* @return
|
|
||||||
* The contact ID of the verifier. If it is DC_CONTACT_ID_SELF,
|
|
||||||
* we verified the contact ourself. If it is 0, we don't have verifier information or
|
|
||||||
* the contact is not verified.
|
|
||||||
*/
|
|
||||||
uint32_t dc_contact_get_verifier_id (dc_contact_t* contact);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @class dc_lot_t
|
* @class dc_lot_t
|
||||||
*
|
*
|
||||||
@@ -6212,7 +6165,7 @@ void dc_event_unref(dc_event_t* event);
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contact(s) created, renamed, verified, blocked or deleted.
|
* Contact(s) created, renamed, blocked or deleted.
|
||||||
*
|
*
|
||||||
* @param data1 (int) contact_id of the changed contact or 0 on batch-changes or deletion.
|
* @param data1 (int) contact_id of the changed contact or 0 on batch-changes or deletion.
|
||||||
* @param data2 0
|
* @param data2 0
|
||||||
@@ -6284,8 +6237,7 @@ void dc_event_unref(dc_event_t* event);
|
|||||||
*
|
*
|
||||||
* @param data1 (int) The ID of the inviting contact.
|
* @param data1 (int) The ID of the inviting contact.
|
||||||
* @param data2 (int) The progress as:
|
* @param data2 (int) The progress as:
|
||||||
* 400=vg-/vc-request-with-auth sent, typically shown as "alice@addr verified, introducing myself."
|
* 400=vg-/vc-request-with-auth sent, typically shown as "introducing myself."
|
||||||
* (Bob has verified alice and waits until Alice does the same for him)
|
|
||||||
* 1000=vg-member-added/vc-contact-confirm received
|
* 1000=vg-member-added/vc-contact-confirm received
|
||||||
*/
|
*/
|
||||||
#define DC_EVENT_SECUREJOIN_JOINER_PROGRESS 2061
|
#define DC_EVENT_SECUREJOIN_JOINER_PROGRESS 2061
|
||||||
@@ -6671,12 +6623,6 @@ void dc_event_unref(dc_event_t* event);
|
|||||||
/// Used to build the string returned by dc_get_contact_encrinfo().
|
/// Used to build the string returned by dc_get_contact_encrinfo().
|
||||||
#define DC_STR_FINGERPRINTS 30
|
#define DC_STR_FINGERPRINTS 30
|
||||||
|
|
||||||
/// "%1$s verified"
|
|
||||||
///
|
|
||||||
/// Used in status messages.
|
|
||||||
/// - %1$s will be replaced by the name of the verified contact
|
|
||||||
#define DC_STR_CONTACT_VERIFIED 35
|
|
||||||
|
|
||||||
/// "Archived chats"
|
/// "Archived chats"
|
||||||
///
|
///
|
||||||
/// Used as the name for the corresponding chatlist entry.
|
/// Used as the name for the corresponding chatlist entry.
|
||||||
@@ -6855,7 +6801,7 @@ void dc_event_unref(dc_event_t* event);
|
|||||||
///
|
///
|
||||||
/// Added as an info-message directly after scanning a QR code for joining a group.
|
/// Added as an info-message directly after scanning a QR code for joining a group.
|
||||||
/// May be followed by the info-messages
|
/// May be followed by the info-messages
|
||||||
/// #DC_STR_SECURE_JOIN_REPLIES, #DC_STR_CONTACT_VERIFIED and #DC_STR_MSGADDMEMBER.
|
/// #DC_STR_SECURE_JOIN_REPLIES and #DC_STR_MSGADDMEMBER.
|
||||||
///
|
///
|
||||||
/// `%1$s` and `%2$s` will be replaced by name of the inviter.
|
/// `%1$s` and `%2$s` will be replaced by name of the inviter.
|
||||||
#define DC_STR_SECURE_JOIN_STARTED 117
|
#define DC_STR_SECURE_JOIN_STARTED 117
|
||||||
@@ -6864,15 +6810,13 @@ void dc_event_unref(dc_event_t* event);
|
|||||||
///
|
///
|
||||||
/// Info-message on scanning a QR code for joining a group.
|
/// Info-message on scanning a QR code for joining a group.
|
||||||
/// Added after #DC_STR_SECURE_JOIN_STARTED.
|
/// Added after #DC_STR_SECURE_JOIN_STARTED.
|
||||||
/// If the handshake allows to skip a step and go for #DC_STR_CONTACT_VERIFIED directly,
|
|
||||||
/// this info-message is skipped.
|
|
||||||
///
|
///
|
||||||
/// `%1$s` will be replaced by the name of the inviter.
|
/// `%1$s` will be replaced by the name of the inviter.
|
||||||
#define DC_STR_SECURE_JOIN_REPLIES 118
|
#define DC_STR_SECURE_JOIN_REPLIES 118
|
||||||
|
|
||||||
/// "Scan to chat with %1$s"
|
/// "Scan to chat with %1$s"
|
||||||
///
|
///
|
||||||
/// Subtitle for verification qrcode svg image generated by the core.
|
/// Subtitle for the invite qrcode svg image generated by the core.
|
||||||
///
|
///
|
||||||
/// `%1$s` will be replaced by name of the inviter.
|
/// `%1$s` will be replaced by name of the inviter.
|
||||||
#define DC_STR_SETUP_CONTACT_QR_DESC 119
|
#define DC_STR_SETUP_CONTACT_QR_DESC 119
|
||||||
|
|||||||
@@ -2397,7 +2397,7 @@ pub unsafe extern "C" fn dc_get_securejoin_qr_svg(
|
|||||||
chat_id: u32,
|
chat_id: u32,
|
||||||
) -> *mut libc::c_char {
|
) -> *mut libc::c_char {
|
||||||
if context.is_null() {
|
if context.is_null() {
|
||||||
eprintln!("ignoring careless call to generate_verification_qr()");
|
eprintln!("ignoring careless call to dc_get_securejoin_qr_svg()");
|
||||||
return "".strdup();
|
return "".strdup();
|
||||||
}
|
}
|
||||||
let ctx = unsafe { &*context };
|
let ctx = unsafe { &*context };
|
||||||
@@ -4049,27 +4049,6 @@ pub unsafe extern "C" fn dc_contact_is_blocked(contact: *mut dc_contact_t) -> li
|
|||||||
ffi_contact.contact.is_blocked() as libc::c_int
|
ffi_contact.contact.is_blocked() as libc::c_int
|
||||||
}
|
}
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
|
||||||
pub unsafe extern "C" fn dc_contact_is_verified(contact: *mut dc_contact_t) -> libc::c_int {
|
|
||||||
if contact.is_null() {
|
|
||||||
eprintln!("ignoring careless call to dc_contact_is_verified()");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
let ffi_contact = unsafe { &*contact };
|
|
||||||
|
|
||||||
if block_on(ffi_contact.contact.is_verified(&ffi_contact.context))
|
|
||||||
.context("is_verified failed")
|
|
||||||
.log_err(&ffi_contact.context)
|
|
||||||
.unwrap_or_default()
|
|
||||||
{
|
|
||||||
// Return value is essentially a boolean,
|
|
||||||
// but we return 2 for true for backwards compatibility.
|
|
||||||
2
|
|
||||||
} else {
|
|
||||||
0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
#[unsafe(no_mangle)]
|
||||||
pub unsafe extern "C" fn dc_contact_is_bot(contact: *mut dc_contact_t) -> libc::c_int {
|
pub unsafe extern "C" fn dc_contact_is_bot(contact: *mut dc_contact_t) -> libc::c_int {
|
||||||
if contact.is_null() {
|
if contact.is_null() {
|
||||||
@@ -4088,22 +4067,6 @@ pub unsafe extern "C" fn dc_contact_is_key_contact(contact: *mut dc_contact_t) -
|
|||||||
unsafe { (*contact).contact.is_key_contact() as libc::c_int }
|
unsafe { (*contact).contact.is_key_contact() as libc::c_int }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
|
||||||
pub unsafe extern "C" fn dc_contact_get_verifier_id(contact: *mut dc_contact_t) -> u32 {
|
|
||||||
if contact.is_null() {
|
|
||||||
eprintln!("ignoring careless call to dc_contact_get_verifier_id()");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
let ffi_contact = unsafe { &*contact };
|
|
||||||
let verifier_contact_id = block_on(ffi_contact.contact.get_verifier_id(&ffi_contact.context))
|
|
||||||
.context("failed to get verifier")
|
|
||||||
.log_err(&ffi_contact.context)
|
|
||||||
.unwrap_or_default()
|
|
||||||
.unwrap_or_default()
|
|
||||||
.unwrap_or_default();
|
|
||||||
|
|
||||||
verifier_contact_id.to_u32()
|
|
||||||
}
|
|
||||||
// dc_lot_t
|
// dc_lot_t
|
||||||
|
|
||||||
pub type dc_lot_t = lot::Lot;
|
pub type dc_lot_t = lot::Lot;
|
||||||
|
|||||||
@@ -841,20 +841,19 @@ impl CommandApi {
|
|||||||
Ok(qr)
|
Ok(qr)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get QR code (text and SVG) that will offer a Setup-Contact or Verified-Group invitation.
|
/// Get QR code (text and SVG) that will offer a SecureJoin invitation.
|
||||||
/// The QR code is compatible to the OPENPGP4FPR format
|
/// The QR code is compatible to the OPENPGP4FPR format
|
||||||
/// so that a basic fingerprint comparison also works e.g. with OpenKeychain.
|
/// so that a basic fingerprint comparison also works e.g. with OpenKeychain.
|
||||||
///
|
///
|
||||||
/// The scanning device will pass the scanned content to `checkQr()` then;
|
/// The scanning device will pass the scanned content to `checkQr()` then;
|
||||||
/// if `checkQr()` returns `askVerifyContact` or `askVerifyGroup`
|
/// if `checkQr()` returns `askVerifyContact` or `askVerifyGroup`
|
||||||
/// an out-of-band-verification can be joined using `secure_join()`
|
/// the securejoin protocol can be started using `secure_join()`
|
||||||
///
|
///
|
||||||
/// @deprecated as of 2026-03; use create_qr_svg(get_chat_securejoin_qr_code()) instead.
|
/// @deprecated as of 2026-03; use create_qr_svg(get_chat_securejoin_qr_code()) instead.
|
||||||
///
|
///
|
||||||
/// chat_id: If set to a group-chat-id,
|
/// chat_id: If set to a group-chat-id,
|
||||||
/// the Verified-Group-Invite protocol is offered in the QR code;
|
/// the SecureJoin QR code for the group is returned.
|
||||||
/// works for protected groups as well as for normal groups.
|
/// If not set, the setup contact QR code is returned.
|
||||||
/// If not set, the Setup-Contact protocol is offered in the QR code.
|
|
||||||
/// See https://securejoin.delta.chat/ for details about both protocols.
|
/// See https://securejoin.delta.chat/ for details about both protocols.
|
||||||
///
|
///
|
||||||
/// return format: `[code, svg]`
|
/// return format: `[code, svg]`
|
||||||
@@ -870,7 +869,7 @@ impl CommandApi {
|
|||||||
Ok((qr, svg))
|
Ok((qr, svg))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Continue a Setup-Contact or Verified-Group-Invite protocol
|
/// Continue the SecureJoin protocol
|
||||||
/// started on another device with `get_chat_securejoin_qr_code_svg()`.
|
/// started on another device with `get_chat_securejoin_qr_code_svg()`.
|
||||||
/// This function is typically called when `check_qr()` returns
|
/// This function is typically called when `check_qr()` returns
|
||||||
/// type=AskVerifyContact or type=AskVerifyGroup.
|
/// type=AskVerifyContact or type=AskVerifyGroup.
|
||||||
@@ -953,8 +952,6 @@ impl CommandApi {
|
|||||||
/// If the group is already _promoted_ (any message was sent to the group),
|
/// If the group is already _promoted_ (any message was sent to the group),
|
||||||
/// all group members are informed by a special status message that is sent automatically by this function.
|
/// all group members are informed by a special status message that is sent automatically by this function.
|
||||||
///
|
///
|
||||||
/// If the group has group protection enabled, only verified contacts can be added to the group.
|
|
||||||
///
|
|
||||||
/// Sends out #DC_EVENT_CHAT_MODIFIED and #DC_EVENT_MSGS_CHANGED if a status message was sent.
|
/// Sends out #DC_EVENT_CHAT_MODIFIED and #DC_EVENT_MSGS_CHANGED if a status message was sent.
|
||||||
async fn add_contact_to_chat(
|
async fn add_contact_to_chat(
|
||||||
&self,
|
&self,
|
||||||
@@ -1776,7 +1773,7 @@ impl CommandApi {
|
|||||||
|
|
||||||
/// Get encryption info for a contact.
|
/// Get encryption info for a contact.
|
||||||
/// Get a multi-line encryption info, containing your fingerprint and the
|
/// Get a multi-line encryption info, containing your fingerprint and the
|
||||||
/// fingerprint of the contact, used e.g. to compare the fingerprints for a simple out-of-band verification.
|
/// fingerprint of the contact, used e.g. to compare the fingerprints out-of-band.
|
||||||
async fn get_contact_encryption_info(
|
async fn get_contact_encryption_info(
|
||||||
&self,
|
&self,
|
||||||
account_id: u32,
|
account_id: u32,
|
||||||
|
|||||||
@@ -31,37 +31,6 @@ pub struct ContactObject {
|
|||||||
/// e.g. if we just scanned the fingerprint from a QR code.
|
/// e.g. if we just scanned the fingerprint from a QR code.
|
||||||
e2ee_avail: bool,
|
e2ee_avail: bool,
|
||||||
|
|
||||||
/// True if the contact
|
|
||||||
/// can be added to protected chats
|
|
||||||
/// because SELF and contact have verified their fingerprints in both directions.
|
|
||||||
///
|
|
||||||
/// See [`Self::verifier_id`]/`Contact.verifierId` for a guidance how to display these information.
|
|
||||||
is_verified: bool,
|
|
||||||
|
|
||||||
/// The contact ID that verified a contact.
|
|
||||||
///
|
|
||||||
/// As verifier may be unknown,
|
|
||||||
/// use [`Self::is_verified`]/`Contact.isVerified` to check if a contact can be added to a protected chat.
|
|
||||||
///
|
|
||||||
/// UI should display the information in the contact's profile as follows:
|
|
||||||
///
|
|
||||||
/// - If `verifierId` != 0,
|
|
||||||
/// display text "Introduced by ..."
|
|
||||||
/// with the name of the contact.
|
|
||||||
/// Prefix the text by a green checkmark.
|
|
||||||
///
|
|
||||||
/// - If `verifierId` == 0 and `isVerified` != 0,
|
|
||||||
/// display "Introduced" prefixed by a green checkmark.
|
|
||||||
///
|
|
||||||
/// - if `verifierId` == 0 and `isVerified` == 0,
|
|
||||||
/// display nothing
|
|
||||||
///
|
|
||||||
/// This contains the contact ID of the verifier.
|
|
||||||
/// If it is `DC_CONTACT_ID_SELF`, we verified the contact ourself.
|
|
||||||
/// If it is None/Null, we don't have verifier information or
|
|
||||||
/// the contact is not verified.
|
|
||||||
verifier_id: Option<u32>,
|
|
||||||
|
|
||||||
/// the contact's last seen timestamp
|
/// the contact's last seen timestamp
|
||||||
last_seen: i64,
|
last_seen: i64,
|
||||||
was_seen_recently: bool,
|
was_seen_recently: bool,
|
||||||
@@ -79,14 +48,6 @@ impl ContactObject {
|
|||||||
Some(path_buf) => path_buf.to_str().map(|s| s.to_owned()),
|
Some(path_buf) => path_buf.to_str().map(|s| s.to_owned()),
|
||||||
None => None,
|
None => None,
|
||||||
};
|
};
|
||||||
let is_verified = contact.is_verified(context).await?;
|
|
||||||
|
|
||||||
let verifier_id = contact
|
|
||||||
.get_verifier_id(context)
|
|
||||||
.await?
|
|
||||||
.flatten()
|
|
||||||
.map(|contact_id| contact_id.to_u32());
|
|
||||||
|
|
||||||
Ok(ContactObject {
|
Ok(ContactObject {
|
||||||
address: contact.get_addr().to_owned(),
|
address: contact.get_addr().to_owned(),
|
||||||
color: color_int_to_hex_string(contact.get_color()),
|
color: color_int_to_hex_string(contact.get_color()),
|
||||||
@@ -100,8 +61,6 @@ impl ContactObject {
|
|||||||
is_blocked: contact.is_blocked(),
|
is_blocked: contact.is_blocked(),
|
||||||
is_key_contact: contact.is_key_contact(),
|
is_key_contact: contact.is_key_contact(),
|
||||||
e2ee_avail: contact.e2ee_avail(context).await?,
|
e2ee_avail: contact.e2ee_avail(context).await?,
|
||||||
is_verified,
|
|
||||||
verifier_id,
|
|
||||||
last_seen: contact.last_seen(),
|
last_seen: contact.last_seen(),
|
||||||
was_seen_recently: contact.was_seen_recently(),
|
was_seen_recently: contact.was_seen_recently(),
|
||||||
is_bot: contact.is_bot(),
|
is_bot: contact.is_bot(),
|
||||||
|
|||||||
@@ -337,8 +337,7 @@ pub enum EventType {
|
|||||||
contact_id: u32,
|
contact_id: u32,
|
||||||
|
|
||||||
/// Progress as:
|
/// Progress as:
|
||||||
/// 400=vg-/vc-request-with-auth sent, typically shown as "alice@addr verified, introducing myself."
|
/// 400=vg-/vc-request-with-auth sent, typically shown as "introducing myself."
|
||||||
/// (Bob has verified alice and waits until Alice does the same for him)
|
|
||||||
/// 1000=vg-member-added/vc-contact-confirm received
|
/// 1000=vg-member-added/vc-contact-confirm received
|
||||||
progress: u16,
|
progress: u16,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ use typescript_type_def::TypeDef;
|
|||||||
#[serde(rename = "Qr", rename_all = "camelCase")]
|
#[serde(rename = "Qr", rename_all = "camelCase")]
|
||||||
#[serde(tag = "kind")]
|
#[serde(tag = "kind")]
|
||||||
pub enum QrObject {
|
pub enum QrObject {
|
||||||
/// Ask the user whether to verify the contact.
|
/// Ask the user whether to start chatting with the contact.
|
||||||
///
|
///
|
||||||
/// If the user agrees, pass this QR code to [`crate::securejoin::join_securejoin`].
|
/// If the user agrees, pass this QR code to [`crate::securejoin::join_securejoin`].
|
||||||
AskVerifyContact {
|
AskVerifyContact {
|
||||||
@@ -61,7 +61,7 @@ pub enum QrObject {
|
|||||||
/// Whether the inviter supports the new Securejoin v3 protocol
|
/// Whether the inviter supports the new Securejoin v3 protocol
|
||||||
is_v3: bool,
|
is_v3: bool,
|
||||||
},
|
},
|
||||||
/// Contact fingerprint is verified.
|
/// Contact fingerprint matches.
|
||||||
///
|
///
|
||||||
/// Ask the user if they want to start chatting.
|
/// Ask the user if they want to start chatting.
|
||||||
FprOk {
|
FprOk {
|
||||||
|
|||||||
@@ -259,19 +259,13 @@ async fn log_contactlist(context: &Context, contacts: &[ContactId]) -> Result<()
|
|||||||
let contact = Contact::get_by_id(context, *contact_id).await?;
|
let contact = Contact::get_by_id(context, *contact_id).await?;
|
||||||
let name = contact.get_display_name();
|
let name = contact.get_display_name();
|
||||||
let addr = contact.get_addr();
|
let addr = contact.get_addr();
|
||||||
let verified_str = if contact.is_verified(context).await? {
|
|
||||||
" √"
|
|
||||||
} else {
|
|
||||||
""
|
|
||||||
};
|
|
||||||
let line = format!(
|
let line = format!(
|
||||||
"{}{} <{}>",
|
"{} <{}>",
|
||||||
if !name.is_empty() {
|
if !name.is_empty() {
|
||||||
name
|
name
|
||||||
} else {
|
} else {
|
||||||
"<name unset>"
|
"<name unset>"
|
||||||
},
|
},
|
||||||
verified_str,
|
|
||||||
if !addr.is_empty() { addr } else { "addr unset" }
|
if !addr.is_empty() { addr } else { "addr unset" }
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -360,7 +360,7 @@ class Account:
|
|||||||
return Chat(self, chat_id)
|
return Chat(self, chat_id)
|
||||||
|
|
||||||
def secure_join(self, qrdata: str) -> Chat:
|
def secure_join(self, qrdata: str) -> Chat:
|
||||||
"""Continue a Setup-Contact or Verified-Group-Invite protocol started on another device.
|
"""Continue the SecureJoin protocol started on another device.
|
||||||
|
|
||||||
The function returns immediately and the handshake runs in background, sending
|
The function returns immediately and the handshake runs in background, sending
|
||||||
and receiving several messages.
|
and receiving several messages.
|
||||||
|
|||||||
@@ -71,17 +71,6 @@ class Contact:
|
|||||||
"""Unblock this contact. Messages from this contact will be retrieved (again)."""
|
"""Unblock this contact. Messages from this contact will be retrieved (again)."""
|
||||||
return lib.dc_block_contact(self.account._dc_context, self.id, False)
|
return lib.dc_block_contact(self.account._dc_context, self.id, False)
|
||||||
|
|
||||||
def is_verified(self) -> bool:
|
|
||||||
"""Return True if the contact is verified."""
|
|
||||||
return lib.dc_contact_is_verified(self._dc_contact) == 2
|
|
||||||
|
|
||||||
def get_verifier(self, contact) -> Optional["Contact"]:
|
|
||||||
"""Return the address of the contact that verified the contact."""
|
|
||||||
verifier_id = lib.dc_contact_get_verifier_id(contact._dc_contact)
|
|
||||||
if verifier_id == 0:
|
|
||||||
return None
|
|
||||||
return Contact(self.account, verifier_id)
|
|
||||||
|
|
||||||
def get_profile_image(self) -> Optional[str]:
|
def get_profile_image(self) -> Optional[str]:
|
||||||
"""Get contact profile image.
|
"""Get contact profile image.
|
||||||
|
|
||||||
|
|||||||
@@ -115,7 +115,6 @@ class TestOfflineContact:
|
|||||||
assert contact1.addr == "some1@example.org"
|
assert contact1.addr == "some1@example.org"
|
||||||
assert contact1.display_name == "some1"
|
assert contact1.display_name == "some1"
|
||||||
assert not contact1.is_blocked()
|
assert not contact1.is_blocked()
|
||||||
assert not contact1.is_verified()
|
|
||||||
|
|
||||||
def test_get_blocked(self, acfactory):
|
def test_get_blocked(self, acfactory):
|
||||||
ac1 = acfactory.get_pseudo_configured_account()
|
ac1 = acfactory.get_pseudo_configured_account()
|
||||||
|
|||||||
+4
-48
@@ -560,10 +560,10 @@ pub enum Origin {
|
|||||||
/// To: of incoming messages of unknown sender
|
/// To: of incoming messages of unknown sender
|
||||||
IncomingUnknownTo = 0x40,
|
IncomingUnknownTo = 0x40,
|
||||||
|
|
||||||
/// Address scanned but not verified.
|
/// Address scanned from a QR code.
|
||||||
UnhandledQrScan = 0x80,
|
UnhandledQrScan = 0x80,
|
||||||
|
|
||||||
/// Address scanned from a SecureJoin QR code, but not verified yet.
|
/// Address scanned from a SecureJoin QR code.
|
||||||
UnhandledSecurejoinQrScan = 0x81,
|
UnhandledSecurejoinQrScan = 0x81,
|
||||||
|
|
||||||
/// Reply-To: of incoming message of known sender
|
/// Reply-To: of incoming message of known sender
|
||||||
@@ -594,14 +594,14 @@ pub enum Origin {
|
|||||||
/// address is in our address book
|
/// address is in our address book
|
||||||
AddressBook = 0x80000,
|
AddressBook = 0x80000,
|
||||||
|
|
||||||
/// set on Alice's side for contacts like Bob that have scanned the QR code offered by her. Only means the contact has once been established using the "securejoin" procedure in the past, getting the current key verification status requires calling contact_is_verified() !
|
/// Set on Alice's side for contacts like Bob that have scanned the QR code offered by her.
|
||||||
|
/// Only means the contact has once been established using the "securejoin" procedure.
|
||||||
SecurejoinInvited = 0x0100_0000,
|
SecurejoinInvited = 0x0100_0000,
|
||||||
|
|
||||||
/// Set on Bob's side for contacts scanned from a QR code.
|
/// Set on Bob's side for contacts scanned from a QR code.
|
||||||
/// Only means the contact has been scanned from the QR code,
|
/// Only means the contact has been scanned from the QR code,
|
||||||
/// but does not mean that securejoin succeeded
|
/// but does not mean that securejoin succeeded
|
||||||
/// or the key has not changed since the last scan.
|
/// or the key has not changed since the last scan.
|
||||||
/// Getting the current key verification status requires calling contact_is_verified() !
|
|
||||||
SecurejoinJoined = 0x0200_0000,
|
SecurejoinJoined = 0x0200_0000,
|
||||||
|
|
||||||
/// contact added manually by create_contact(), this should be the largest origin as otherwise the user cannot modify the names
|
/// contact added manually by create_contact(), this should be the largest origin as otherwise the user cannot modify the names
|
||||||
@@ -1688,50 +1688,6 @@ WHERE addr=?
|
|||||||
Ok(self.public_key(context).await?.is_some())
|
Ok(self.public_key(context).await?.is_some())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if the contact
|
|
||||||
/// can be added to verified chats.
|
|
||||||
///
|
|
||||||
/// If contact is verified
|
|
||||||
/// UI should display green checkmark after the contact name
|
|
||||||
/// in contact list items and
|
|
||||||
/// in chat member list items.
|
|
||||||
///
|
|
||||||
/// Use [Self::get_verifier_id] to display the verifier contact
|
|
||||||
/// in the info section of the contact profile.
|
|
||||||
pub async fn is_verified(&self, context: &Context) -> Result<bool> {
|
|
||||||
// We're always sort of secured-verified as we could verify the key on this device any time with the key
|
|
||||||
// on this device
|
|
||||||
if self.id == ContactId::SELF {
|
|
||||||
return Ok(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(self.get_verifier_id(context).await?.is_some())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the `ContactId` that verified the contact.
|
|
||||||
///
|
|
||||||
/// If this returns Some(_),
|
|
||||||
/// display green checkmark in the profile and "Introduced by ..." line
|
|
||||||
/// with the name of the contact.
|
|
||||||
///
|
|
||||||
/// If this returns `Some(None)`, then the contact is verified,
|
|
||||||
/// but it's unclear by whom.
|
|
||||||
pub async fn get_verifier_id(&self, context: &Context) -> Result<Option<Option<ContactId>>> {
|
|
||||||
let verifier_id: u32 = context
|
|
||||||
.sql
|
|
||||||
.query_get_value("SELECT verifier FROM contacts WHERE id=?", (self.id,))
|
|
||||||
.await?
|
|
||||||
.with_context(|| format!("Contact {} does not exist", self.id))?;
|
|
||||||
|
|
||||||
if verifier_id == 0 {
|
|
||||||
Ok(None)
|
|
||||||
} else if verifier_id == self.id.to_u32() {
|
|
||||||
Ok(Some(None))
|
|
||||||
} else {
|
|
||||||
Ok(Some(Some(ContactId::new(verifier_id))))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the number of real (i.e. non-special) contacts in the database.
|
/// Returns the number of real (i.e. non-special) contacts in the database.
|
||||||
pub async fn get_real_cnt(context: &Context) -> Result<usize> {
|
pub async fn get_real_cnt(context: &Context) -> Result<usize> {
|
||||||
if !context.sql.is_open().await {
|
if !context.sql.is_open().await {
|
||||||
|
|||||||
@@ -69,10 +69,6 @@ pub enum StockMessage {
|
|||||||
#[strum(props(fallback = "Fingerprints"))]
|
#[strum(props(fallback = "Fingerprints"))]
|
||||||
FingerPrints = 30,
|
FingerPrints = 30,
|
||||||
|
|
||||||
/// Unused. Was used in status messages.
|
|
||||||
#[strum(props(fallback = "%1$s verified."))]
|
|
||||||
ContactVerified = 35,
|
|
||||||
|
|
||||||
#[strum(props(fallback = "Archived chats"))]
|
#[strum(props(fallback = "Archived chats"))]
|
||||||
ArchivedChats = 40,
|
ArchivedChats = 40,
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user