mirror of
https://github.com/chatmail/core.git
synced 2026-05-04 05:46:29 +03:00
Make ContactId::LAST_SPECIAL private
Also remove the Ord implementations, this makes ContactId more opaque by no longer letting people deal with the fact this is ordered.
This commit is contained in:
@@ -1949,18 +1949,19 @@ pub unsafe extern "C" fn dc_block_contact(
|
|||||||
contact_id: u32,
|
contact_id: u32,
|
||||||
block: libc::c_int,
|
block: libc::c_int,
|
||||||
) {
|
) {
|
||||||
if context.is_null() || contact_id <= ContactId::LAST_SPECIAL.to_u32() {
|
let contact_id = ContactId::new(contact_id);
|
||||||
|
if context.is_null() || contact_id.is_special() {
|
||||||
eprintln!("ignoring careless call to dc_block_contact()");
|
eprintln!("ignoring careless call to dc_block_contact()");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let ctx = &*context;
|
let ctx = &*context;
|
||||||
block_on(async move {
|
block_on(async move {
|
||||||
if block == 0 {
|
if block == 0 {
|
||||||
Contact::unblock(ctx, ContactId::new(contact_id))
|
Contact::unblock(ctx, contact_id)
|
||||||
.await
|
.await
|
||||||
.ok_or_log_msg(ctx, "Can't unblock contact");
|
.ok_or_log_msg(ctx, "Can't unblock contact");
|
||||||
} else {
|
} else {
|
||||||
Contact::block(ctx, ContactId::new(contact_id))
|
Contact::block(ctx, contact_id)
|
||||||
.await
|
.await
|
||||||
.ok_or_log_msg(ctx, "Can't block contact");
|
.ok_or_log_msg(ctx, "Can't block contact");
|
||||||
}
|
}
|
||||||
@@ -1994,14 +1995,15 @@ pub unsafe extern "C" fn dc_delete_contact(
|
|||||||
context: *mut dc_context_t,
|
context: *mut dc_context_t,
|
||||||
contact_id: u32,
|
contact_id: u32,
|
||||||
) -> libc::c_int {
|
) -> libc::c_int {
|
||||||
if context.is_null() || contact_id <= ContactId::LAST_SPECIAL.to_u32() {
|
let contact_id = ContactId::new(contact_id);
|
||||||
|
if context.is_null() || contact_id.is_special() {
|
||||||
eprintln!("ignoring careless call to dc_delete_contact()");
|
eprintln!("ignoring careless call to dc_delete_contact()");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
let ctx = &*context;
|
let ctx = &*context;
|
||||||
|
|
||||||
block_on(async move {
|
block_on(async move {
|
||||||
match Contact::delete(ctx, ContactId::new(contact_id)).await {
|
match Contact::delete(ctx, contact_id).await {
|
||||||
Ok(_) => 1,
|
Ok(_) => 1,
|
||||||
Err(_) => 0,
|
Err(_) => 0,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -860,7 +860,7 @@ impl ChatId {
|
|||||||
for contact_id in get_chat_contacts(context, self)
|
for contact_id in get_chat_contacts(context, self)
|
||||||
.await?
|
.await?
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|&contact_id| *contact_id > ContactId::LAST_SPECIAL)
|
.filter(|&contact_id| !contact_id.is_special())
|
||||||
{
|
{
|
||||||
let contact = Contact::load_from_db(context, *contact_id).await?;
|
let contact = Contact::load_from_db(context, *contact_id).await?;
|
||||||
let addr = contact.get_addr();
|
let addr = contact.get_addr();
|
||||||
@@ -1686,7 +1686,7 @@ impl ChatIdBlocked {
|
|||||||
) -> Result<Option<Self>> {
|
) -> Result<Option<Self>> {
|
||||||
ensure!(context.sql.is_open().await, "Database not available");
|
ensure!(context.sql.is_open().await, "Database not available");
|
||||||
ensure!(
|
ensure!(
|
||||||
contact_id > ContactId::new(0),
|
contact_id != ContactId::UNDEFINED,
|
||||||
"Invalid contact id requested"
|
"Invalid contact id requested"
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -1722,7 +1722,7 @@ impl ChatIdBlocked {
|
|||||||
) -> Result<Self> {
|
) -> Result<Self> {
|
||||||
ensure!(context.sql.is_open().await, "Database not available");
|
ensure!(context.sql.is_open().await, "Database not available");
|
||||||
ensure!(
|
ensure!(
|
||||||
contact_id > ContactId::new(0),
|
contact_id != ContactId::UNDEFINED,
|
||||||
"Invalid contact id requested"
|
"Invalid contact id requested"
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -2888,7 +2888,7 @@ pub async fn remove_contact_from_chat(
|
|||||||
chat_id
|
chat_id
|
||||||
);
|
);
|
||||||
ensure!(
|
ensure!(
|
||||||
contact_id > ContactId::LAST_SPECIAL || contact_id == ContactId::SELF,
|
!contact_id.is_special() || contact_id == ContactId::SELF,
|
||||||
"Cannot remove special contact"
|
"Cannot remove special contact"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -30,9 +30,7 @@ use crate::{chat, stock_str};
|
|||||||
///
|
///
|
||||||
/// Some contact IDs are reserved to identify special contacts. This
|
/// Some contact IDs are reserved to identify special contacts. This
|
||||||
/// type can represent both the special as well as normal contacts.
|
/// type can represent both the special as well as normal contacts.
|
||||||
#[derive(
|
#[derive(Debug, Copy, Clone, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||||
Debug, Copy, Clone, Default, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize,
|
|
||||||
)]
|
|
||||||
pub struct ContactId(u32);
|
pub struct ContactId(u32);
|
||||||
|
|
||||||
impl ContactId {
|
impl ContactId {
|
||||||
@@ -43,9 +41,9 @@ impl ContactId {
|
|||||||
pub const SELF: ContactId = ContactId::new(1);
|
pub const SELF: ContactId = ContactId::new(1);
|
||||||
pub const INFO: ContactId = ContactId::new(2);
|
pub const INFO: ContactId = ContactId::new(2);
|
||||||
pub const DEVICE: ContactId = ContactId::new(5);
|
pub const DEVICE: ContactId = ContactId::new(5);
|
||||||
pub const LAST_SPECIAL: ContactId = ContactId::new(9);
|
const LAST_SPECIAL: ContactId = ContactId::new(9);
|
||||||
|
|
||||||
/// Address to go with [`ContactId::Device`].
|
/// Address to go with [`ContactId::DEVICE`].
|
||||||
///
|
///
|
||||||
/// This is used by APIs which need to return an email address for this contact.
|
/// This is used by APIs which need to return an email address for this contact.
|
||||||
pub const DEVICE_ADDR: &'static str = "device@localhost";
|
pub const DEVICE_ADDR: &'static str = "device@localhost";
|
||||||
@@ -55,6 +53,16 @@ impl ContactId {
|
|||||||
ContactId(id)
|
ContactId(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Whether this is a special [`ContactId`].
|
||||||
|
///
|
||||||
|
/// Some [`ContactId`]s are reserved for special contacts like [`ContactId::SELF`],
|
||||||
|
/// [`ContactId::INFO`] and [`ContactId::DEVICE`]. This function indicates whether this
|
||||||
|
/// [`ContactId`] is any of the reserved special [`ContactId`]s (`true`) or whether it
|
||||||
|
/// is the [`ContactId`] of a real contact (`false`).
|
||||||
|
pub fn is_special(&self) -> bool {
|
||||||
|
self.0 <= Self::LAST_SPECIAL.0
|
||||||
|
}
|
||||||
|
|
||||||
/// Numerical representation of the [`ContactId`].
|
/// Numerical representation of the [`ContactId`].
|
||||||
///
|
///
|
||||||
/// Each contact ID has a unique numerical representation which is used in the database
|
/// Each contact ID has a unique numerical representation which is used in the database
|
||||||
@@ -75,7 +83,7 @@ impl fmt::Display for ContactId {
|
|||||||
write!(f, "Contact#Info")
|
write!(f, "Contact#Info")
|
||||||
} else if *self == ContactId::DEVICE {
|
} else if *self == ContactId::DEVICE {
|
||||||
write!(f, "Contact#Device")
|
write!(f, "Contact#Device")
|
||||||
} else if *self <= ContactId::LAST_SPECIAL {
|
} else if self.is_special() {
|
||||||
write!(f, "Contact#Special{}", self.0)
|
write!(f, "Contact#Special{}", self.0)
|
||||||
} else {
|
} else {
|
||||||
write!(f, "Contact#{}", self.0)
|
write!(f, "Contact#{}", self.0)
|
||||||
@@ -856,7 +864,7 @@ impl Contact {
|
|||||||
/// fingerprints of the keys involved.
|
/// fingerprints of the keys involved.
|
||||||
pub async fn get_encrinfo(context: &Context, contact_id: ContactId) -> Result<String> {
|
pub async fn get_encrinfo(context: &Context, contact_id: ContactId) -> Result<String> {
|
||||||
ensure!(
|
ensure!(
|
||||||
contact_id > ContactId::LAST_SPECIAL,
|
!contact_id.is_special(),
|
||||||
"Can not provide encryption info for special contact"
|
"Can not provide encryption info for special contact"
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -924,10 +932,7 @@ impl Contact {
|
|||||||
///
|
///
|
||||||
/// May result in a `#DC_EVENT_CONTACTS_CHANGED` event.
|
/// May result in a `#DC_EVENT_CONTACTS_CHANGED` event.
|
||||||
pub async fn delete(context: &Context, contact_id: ContactId) -> Result<()> {
|
pub async fn delete(context: &Context, contact_id: ContactId) -> Result<()> {
|
||||||
ensure!(
|
ensure!(!contact_id.is_special(), "Can not delete special contact");
|
||||||
contact_id > ContactId::LAST_SPECIAL,
|
|
||||||
"Can not delete special contact"
|
|
||||||
);
|
|
||||||
|
|
||||||
let count_chats = context
|
let count_chats = context
|
||||||
.sql
|
.sql
|
||||||
@@ -1157,7 +1162,7 @@ impl Contact {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn real_exists_by_id(context: &Context, contact_id: ContactId) -> Result<bool> {
|
pub async fn real_exists_by_id(context: &Context, contact_id: ContactId) -> Result<bool> {
|
||||||
if contact_id <= ContactId::LAST_SPECIAL {
|
if contact_id.is_special() {
|
||||||
return Ok(false);
|
return Ok(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1230,7 +1235,7 @@ async fn set_block_contact(
|
|||||||
new_blocking: bool,
|
new_blocking: bool,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
ensure!(
|
ensure!(
|
||||||
contact_id > ContactId::LAST_SPECIAL,
|
!contact_id.is_special(),
|
||||||
"Can't block special contact {}",
|
"Can't block special contact {}",
|
||||||
contact_id
|
contact_id
|
||||||
);
|
);
|
||||||
@@ -1370,7 +1375,7 @@ pub(crate) async fn update_last_seen(
|
|||||||
timestamp: i64,
|
timestamp: i64,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
ensure!(
|
ensure!(
|
||||||
contact_id > ContactId::LAST_SPECIAL,
|
!contact_id.is_special(),
|
||||||
"Can not update special contact last seen timestamp"
|
"Can not update special contact last seen timestamp"
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -1615,7 +1620,7 @@ mod tests {
|
|||||||
Contact::add_or_lookup(&t, "bla foo", "one@eins.org", Origin::IncomingUnknownTo)
|
Contact::add_or_lookup(&t, "bla foo", "one@eins.org", Origin::IncomingUnknownTo)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert!(contact_id > ContactId::LAST_SPECIAL);
|
assert!(!contact_id.is_special());
|
||||||
assert_eq!(sth_modified, Modifier::Modified);
|
assert_eq!(sth_modified, Modifier::Modified);
|
||||||
let contact = Contact::load_from_db(&t, contact_id).await.unwrap();
|
let contact = Contact::load_from_db(&t, contact_id).await.unwrap();
|
||||||
assert_eq!(contact.get_id(), contact_id);
|
assert_eq!(contact.get_id(), contact_id);
|
||||||
@@ -1642,7 +1647,7 @@ mod tests {
|
|||||||
Contact::add_or_lookup(&t, "", "three@drei.sam", Origin::IncomingUnknownTo)
|
Contact::add_or_lookup(&t, "", "three@drei.sam", Origin::IncomingUnknownTo)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert!(contact_id > ContactId::LAST_SPECIAL);
|
assert!(!contact_id.is_special());
|
||||||
assert_eq!(sth_modified, Modifier::None);
|
assert_eq!(sth_modified, Modifier::None);
|
||||||
let contact = Contact::load_from_db(&t, contact_id).await.unwrap();
|
let contact = Contact::load_from_db(&t, contact_id).await.unwrap();
|
||||||
assert_eq!(contact.get_name(), "");
|
assert_eq!(contact.get_name(), "");
|
||||||
@@ -1682,7 +1687,7 @@ mod tests {
|
|||||||
Contact::add_or_lookup(&t, "", "alice@w.de", Origin::IncomingUnknownTo)
|
Contact::add_or_lookup(&t, "", "alice@w.de", Origin::IncomingUnknownTo)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert!(contact_id > ContactId::LAST_SPECIAL);
|
assert!(!contact_id.is_special());
|
||||||
assert_eq!(sth_modified, Modifier::None);
|
assert_eq!(sth_modified, Modifier::None);
|
||||||
let contact = Contact::load_from_db(&t, contact_id).await.unwrap();
|
let contact = Contact::load_from_db(&t, contact_id).await.unwrap();
|
||||||
assert_eq!(contact.get_name(), "Wonderland, Alice");
|
assert_eq!(contact.get_name(), "Wonderland, Alice");
|
||||||
@@ -1735,7 +1740,7 @@ mod tests {
|
|||||||
Contact::add_or_lookup(&t, "bob1", "bob@example.org", Origin::IncomingUnknownFrom)
|
Contact::add_or_lookup(&t, "bob1", "bob@example.org", Origin::IncomingUnknownFrom)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert!(contact_id > ContactId::LAST_SPECIAL);
|
assert!(!contact_id.is_special());
|
||||||
assert_eq!(sth_modified, Modifier::Created);
|
assert_eq!(sth_modified, Modifier::Created);
|
||||||
let contact = Contact::load_from_db(&t, contact_id).await.unwrap();
|
let contact = Contact::load_from_db(&t, contact_id).await.unwrap();
|
||||||
assert_eq!(contact.get_authname(), "bob1");
|
assert_eq!(contact.get_authname(), "bob1");
|
||||||
@@ -1747,7 +1752,7 @@ mod tests {
|
|||||||
Contact::add_or_lookup(&t, "bob2", "bob@example.org", Origin::IncomingUnknownFrom)
|
Contact::add_or_lookup(&t, "bob2", "bob@example.org", Origin::IncomingUnknownFrom)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert!(contact_id > ContactId::LAST_SPECIAL);
|
assert!(!contact_id.is_special());
|
||||||
assert_eq!(sth_modified, Modifier::Modified);
|
assert_eq!(sth_modified, Modifier::Modified);
|
||||||
let contact = Contact::load_from_db(&t, contact_id).await.unwrap();
|
let contact = Contact::load_from_db(&t, contact_id).await.unwrap();
|
||||||
assert_eq!(contact.get_authname(), "bob2");
|
assert_eq!(contact.get_authname(), "bob2");
|
||||||
@@ -1758,7 +1763,7 @@ mod tests {
|
|||||||
let contact_id = Contact::create(&t, "bob3", "bob@example.org")
|
let contact_id = Contact::create(&t, "bob3", "bob@example.org")
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert!(contact_id > ContactId::LAST_SPECIAL);
|
assert!(!contact_id.is_special());
|
||||||
let contact = Contact::load_from_db(&t, contact_id).await.unwrap();
|
let contact = Contact::load_from_db(&t, contact_id).await.unwrap();
|
||||||
assert_eq!(contact.get_authname(), "bob2");
|
assert_eq!(contact.get_authname(), "bob2");
|
||||||
assert_eq!(contact.get_name(), "bob3");
|
assert_eq!(contact.get_name(), "bob3");
|
||||||
@@ -1769,7 +1774,7 @@ mod tests {
|
|||||||
Contact::add_or_lookup(&t, "bob4", "bob@example.org", Origin::IncomingUnknownFrom)
|
Contact::add_or_lookup(&t, "bob4", "bob@example.org", Origin::IncomingUnknownFrom)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert!(contact_id > ContactId::LAST_SPECIAL);
|
assert!(!contact_id.is_special());
|
||||||
assert_eq!(sth_modified, Modifier::Modified);
|
assert_eq!(sth_modified, Modifier::Modified);
|
||||||
let contact = Contact::load_from_db(&t, contact_id).await.unwrap();
|
let contact = Contact::load_from_db(&t, contact_id).await.unwrap();
|
||||||
assert_eq!(contact.get_authname(), "bob4");
|
assert_eq!(contact.get_authname(), "bob4");
|
||||||
@@ -1783,7 +1788,7 @@ mod tests {
|
|||||||
|
|
||||||
// manually create "claire@example.org" without a given name
|
// manually create "claire@example.org" without a given name
|
||||||
let contact_id = Contact::create(&t, "", "claire@example.org").await.unwrap();
|
let contact_id = Contact::create(&t, "", "claire@example.org").await.unwrap();
|
||||||
assert!(contact_id > ContactId::LAST_SPECIAL);
|
assert!(!contact_id.is_special());
|
||||||
let contact = Contact::load_from_db(&t, contact_id).await.unwrap();
|
let contact = Contact::load_from_db(&t, contact_id).await.unwrap();
|
||||||
assert_eq!(contact.get_authname(), "");
|
assert_eq!(contact.get_authname(), "");
|
||||||
assert_eq!(contact.get_name(), "");
|
assert_eq!(contact.get_name(), "");
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
//! Internet Message Format reception pipeline.
|
//! Internet Message Format reception pipeline.
|
||||||
|
|
||||||
use std::cmp::min;
|
use std::cmp::min;
|
||||||
use std::collections::BTreeSet;
|
use std::collections::HashSet;
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
use anyhow::{bail, ensure, Context as _, Result};
|
use anyhow::{bail, ensure, Context as _, Result};
|
||||||
@@ -220,7 +220,7 @@ pub(crate) async fn dc_receive_imf_inner(
|
|||||||
.await
|
.await
|
||||||
.context("add_parts error")?;
|
.context("add_parts error")?;
|
||||||
|
|
||||||
if from_id > ContactId::LAST_SPECIAL {
|
if !from_id.is_special() {
|
||||||
contact::update_last_seen(context, from_id, sent_timestamp).await?;
|
contact::update_last_seen(context, from_id, sent_timestamp).await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1489,8 +1489,7 @@ async fn create_or_lookup_group(
|
|||||||
|
|
||||||
// Create initial member list.
|
// Create initial member list.
|
||||||
chat::add_to_chat_contacts_table(context, new_chat_id, ContactId::SELF).await?;
|
chat::add_to_chat_contacts_table(context, new_chat_id, ContactId::SELF).await?;
|
||||||
if from_id > ContactId::LAST_SPECIAL
|
if !from_id.is_special() && !chat::is_contact_in_chat(context, new_chat_id, from_id).await?
|
||||||
&& !chat::is_contact_in_chat(context, new_chat_id, from_id).await?
|
|
||||||
{
|
{
|
||||||
chat::add_to_chat_contacts_table(context, new_chat_id, from_id).await?;
|
chat::add_to_chat_contacts_table(context, new_chat_id, from_id).await?;
|
||||||
}
|
}
|
||||||
@@ -1674,7 +1673,7 @@ async fn apply_group_changes(
|
|||||||
chat::add_to_chat_contacts_table(context, chat_id, ContactId::SELF).await?;
|
chat::add_to_chat_contacts_table(context, chat_id, ContactId::SELF).await?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if from_id > ContactId::LAST_SPECIAL
|
if !from_id.is_special()
|
||||||
&& !Contact::addr_equals_contact(context, &self_addr, from_id).await?
|
&& !Contact::addr_equals_contact(context, &self_addr, from_id).await?
|
||||||
&& !chat::is_contact_in_chat(context, chat_id, from_id).await?
|
&& !chat::is_contact_in_chat(context, chat_id, from_id).await?
|
||||||
&& removed_id != Some(from_id)
|
&& removed_id != Some(from_id)
|
||||||
@@ -2261,7 +2260,7 @@ async fn dc_add_or_lookup_contacts_by_address_list(
|
|||||||
origin: Origin,
|
origin: Origin,
|
||||||
prevent_rename: bool,
|
prevent_rename: bool,
|
||||||
) -> Result<Vec<ContactId>> {
|
) -> Result<Vec<ContactId>> {
|
||||||
let mut contact_ids = BTreeSet::new();
|
let mut contact_ids = HashSet::new();
|
||||||
for info in address_list.iter() {
|
for info in address_list.iter() {
|
||||||
let addr = &info.addr;
|
let addr = &info.addr;
|
||||||
if !may_be_valid_addr(addr) {
|
if !may_be_valid_addr(addr) {
|
||||||
|
|||||||
@@ -310,7 +310,7 @@ pub(crate) async fn handle_securejoin_handshake(
|
|||||||
mime_message: &MimeMessage,
|
mime_message: &MimeMessage,
|
||||||
contact_id: ContactId,
|
contact_id: ContactId,
|
||||||
) -> Result<HandshakeMessage> {
|
) -> Result<HandshakeMessage> {
|
||||||
if contact_id <= ContactId::LAST_SPECIAL {
|
if contact_id.is_special() {
|
||||||
return Err(Error::msg("Can not be called with special contact ID"));
|
return Err(Error::msg("Can not be called with special contact ID"));
|
||||||
}
|
}
|
||||||
let step = mime_message
|
let step = mime_message
|
||||||
@@ -573,7 +573,7 @@ pub(crate) async fn observe_securejoin_on_other_device(
|
|||||||
mime_message: &MimeMessage,
|
mime_message: &MimeMessage,
|
||||||
contact_id: ContactId,
|
contact_id: ContactId,
|
||||||
) -> Result<HandshakeMessage> {
|
) -> Result<HandshakeMessage> {
|
||||||
if contact_id <= ContactId::LAST_SPECIAL {
|
if contact_id.is_special() {
|
||||||
return Err(Error::msg("Can not be called with special contact ID"));
|
return Err(Error::msg("Can not be called with special contact ID"));
|
||||||
}
|
}
|
||||||
let step = mime_message
|
let step = mime_message
|
||||||
|
|||||||
Reference in New Issue
Block a user