diff --git a/deltachat-ffi/deltachat.h b/deltachat-ffi/deltachat.h index 8ca28e7cf..f4d1aeb77 100644 --- a/deltachat-ffi/deltachat.h +++ b/deltachat-ffi/deltachat.h @@ -2456,7 +2456,6 @@ void dc_stop_ongoing_process (dc_context_t* context); #define DC_QR_ASK_VERIFYBROADCAST 204 // text1=broadcast name #define DC_QR_FPR_OK 210 // id=contact #define DC_QR_FPR_MISMATCH 220 // id=contact -#define DC_QR_FPR_WITHOUT_ADDR 230 // test1=formatted fingerprint #define DC_QR_ACCOUNT 250 // text1=domain #define DC_QR_BACKUP2 252 #define DC_QR_BACKUP_TOO_NEW 255 @@ -2498,11 +2497,8 @@ void dc_stop_ongoing_process (dc_context_t* context); * if so, call dc_create_chat_by_contact_id(). * * - DC_QR_FPR_MISMATCH with dc_lot_t::id=Contact ID: - * scanned fingerprint does not match last seen fingerprint. - * - * - DC_QR_FPR_WITHOUT_ADDR with dc_lot_t::text1=Formatted fingerprint - * the scanned QR code contains a fingerprint but no e-mail address; - * suggest the user to establish an encrypted connection first. + * scanned fingerprint does not match any contact + * or the key for this contact is not available. * * - DC_QR_ACCOUNT dc_lot_t::text1=domain: * ask the user if they want to create an account on the given domain, diff --git a/deltachat-ffi/src/lot.rs b/deltachat-ffi/src/lot.rs index 1c8c0af5b..1d10ce801 100644 --- a/deltachat-ffi/src/lot.rs +++ b/deltachat-ffi/src/lot.rs @@ -48,7 +48,6 @@ impl Lot { Qr::AskJoinBroadcast { name, .. } => Some(Cow::Borrowed(name)), Qr::FprOk { .. } => None, Qr::FprMismatch { .. } => None, - Qr::FprWithoutAddr { fingerprint, .. } => Some(Cow::Borrowed(fingerprint)), Qr::Account { domain } => Some(Cow::Borrowed(domain)), Qr::Backup2 { .. } => None, Qr::BackupTooNew { .. } => None, @@ -104,7 +103,6 @@ impl Lot { Qr::AskJoinBroadcast { .. } => LotState::QrAskJoinBroadcast, Qr::FprOk { .. } => LotState::QrFprOk, Qr::FprMismatch { .. } => LotState::QrFprMismatch, - Qr::FprWithoutAddr { .. } => LotState::QrFprWithoutAddr, Qr::Account { .. } => LotState::QrAccount, Qr::Backup2 { .. } => LotState::QrBackup2, Qr::BackupTooNew { .. } => LotState::QrBackupTooNew, @@ -133,7 +131,6 @@ impl Lot { Qr::AskJoinBroadcast { .. } => Default::default(), Qr::FprOk { contact_id } => contact_id.to_u32(), Qr::FprMismatch { contact_id } => contact_id.unwrap_or_default().to_u32(), - Qr::FprWithoutAddr { .. } => Default::default(), Qr::Account { .. } => Default::default(), Qr::Backup2 { .. } => Default::default(), Qr::BackupTooNew { .. } => Default::default(), @@ -184,9 +181,6 @@ pub enum LotState { /// id=contact QrFprMismatch = 220, - /// text1=formatted fingerprint - QrFprWithoutAddr = 230, - /// text1=domain QrAccount = 250, diff --git a/deltachat-jsonrpc/src/api/types/qr.rs b/deltachat-jsonrpc/src/api/types/qr.rs index 446b37fa3..2bd605081 100644 --- a/deltachat-jsonrpc/src/api/types/qr.rs +++ b/deltachat-jsonrpc/src/api/types/qr.rs @@ -73,11 +73,6 @@ pub enum QrObject { /// Contact ID. contact_id: Option, }, - /// The scanned QR code contains a fingerprint but no e-mail address. - FprWithoutAddr { - /// Key fingerprint. - fingerprint: String, - }, /// Ask the user if they want to create an account on the given domain. Account { /// Server domain name. @@ -300,7 +295,6 @@ impl From for QrObject { let contact_id = contact_id.map(|contact_id| contact_id.to_u32()); QrObject::FprMismatch { contact_id } } - Qr::FprWithoutAddr { fingerprint } => QrObject::FprWithoutAddr { fingerprint }, Qr::Account { domain } => QrObject::Account { domain }, Qr::Backup2 { ref node_addr, diff --git a/src/qr.rs b/src/qr.rs index 7297c6325..434232b3c 100644 --- a/src/qr.rs +++ b/src/qr.rs @@ -133,18 +133,15 @@ pub enum Qr { contact_id: ContactId, }, - /// Scanned fingerprint does not match the last seen fingerprint. + /// Scanned fingerprint does not match any contact + /// or the key for this contact is not available. FprMismatch { - /// Contact ID. + /// Contact ID if key-contact exists, but we have no key. + /// + /// `None` if there is no contact corresponding to the scanned fingerprint. contact_id: Option, }, - /// The scanned QR code contains a fingerprint but no e-mail address. - FprWithoutAddr { - /// Key fingerprint. - fingerprint: String, - }, - /// Ask the user if they want to create an account on the given domain. Account { /// Server domain name. @@ -651,24 +648,28 @@ async fn decode_openpgp(context: &Context, qr: &str) -> Result { is_v3, }) } - } else if let Some(addr) = addrs.first() { - let fingerprint = fingerprint.hex(); - let (contact_id, _) = - Contact::add_or_lookup_ext(context, "", addr, &fingerprint, Origin::UnhandledQrScan) - .await?; - let contact = Contact::get_by_id(context, contact_id).await?; - - if contact.public_key(context).await?.is_some() { - Ok(Qr::FprOk { contact_id }) - } else { - Ok(Qr::FprMismatch { - contact_id: Some(contact_id), - }) - } } else { - Ok(Qr::FprWithoutAddr { - fingerprint: fingerprint.human_readable(), - }) + let fingerprint = fingerprint.hex(); + let contact_id: Option = context + .sql + .query_get_value( + "SELECT id FROM contacts WHERE fingerprint=?", + (fingerprint,), + ) + .await?; + + if let Some(contact_id) = contact_id { + let contact = Contact::get_by_id(context, contact_id).await?; + if contact.public_key(context).await?.is_some() { + Ok(Qr::FprOk { contact_id }) + } else { + Ok(Qr::FprMismatch { + contact_id: Some(contact_id), + }) + } + } else { + Ok(Qr::FprMismatch { contact_id: None }) + } } } diff --git a/src/qr/qr_tests.rs b/src/qr/qr_tests.rs index 3db74ca1c..6ba73f200 100644 --- a/src/qr/qr_tests.rs +++ b/src/qr/qr_tests.rs @@ -373,16 +373,15 @@ async fn test_decode_openpgp_fingerprint() -> Result<()> { let alice_contact = bob.add_or_lookup_contact(alice).await; let alice_contact_id = alice_contact.id; + // OPENPGP4FPR may have an address, + // but it is not used anymore since key contacts are introduced. + // We lookup the contact only by fingerprint and ignore the address. let qr = check_qr( bob, "OPENPGP4FPR:1234567890123456789012345678901234567890#a=alice@example.org", ) .await?; - if let Qr::FprMismatch { contact_id, .. } = qr { - assert_ne!(contact_id.unwrap(), alice_contact_id); - } else { - bail!("Wrong QR code type"); - } + assert_eq!(qr, Qr::FprMismatch { contact_id: None }); let qr = check_qr( bob, @@ -410,6 +409,10 @@ async fn test_decode_openpgp_fingerprint() -> Result<()> { Ok(()) } +/// Tests OPENPGP4FPR QR codes without an email address. +/// +/// Email address in OPENPGP4FPR QR codes was an extension +/// used before switch to identifying contacts by fingerprint. #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn test_decode_openpgp_without_addr() -> Result<()> { let ctx = TestContext::new().await; @@ -419,12 +422,7 @@ async fn test_decode_openpgp_without_addr() -> Result<()> { "OPENPGP4FPR:1234567890123456789012345678901234567890", ) .await?; - assert_eq!( - qr, - Qr::FprWithoutAddr { - fingerprint: "1234 5678 9012 3456 7890\n1234 5678 9012 3456 7890".to_string() - } - ); + assert_eq!(qr, Qr::FprMismatch { contact_id: None }); // Test it again with lowercased "openpgp4fpr:" uri scheme @@ -433,12 +431,7 @@ async fn test_decode_openpgp_without_addr() -> Result<()> { "openpgp4fpr:1234567890123456789012345678901234567890", ) .await?; - assert_eq!( - qr, - Qr::FprWithoutAddr { - fingerprint: "1234 5678 9012 3456 7890\n1234 5678 9012 3456 7890".to_string() - } - ); + assert_eq!(qr, Qr::FprMismatch { contact_id: None }); let res = check_qr(&ctx.ctx, "OPENPGP4FPR:12345678901234567890").await; assert!(res.is_err());