mirror of
https://github.com/chatmail/core.git
synced 2026-05-15 12:56:30 +03:00
Refactor qr module
This commit is contained in:
@@ -2130,7 +2130,7 @@ void dc_stop_ongoing_process (dc_context_t* context);
|
|||||||
#define DC_QR_FPR_MISMATCH 220 // id=contact
|
#define DC_QR_FPR_MISMATCH 220 // id=contact
|
||||||
#define DC_QR_FPR_WITHOUT_ADDR 230 // test1=formatted fingerprint
|
#define DC_QR_FPR_WITHOUT_ADDR 230 // test1=formatted fingerprint
|
||||||
#define DC_QR_ACCOUNT 250 // text1=domain
|
#define DC_QR_ACCOUNT 250 // text1=domain
|
||||||
#define DC_QR_WEBRTC_INSTANCE 260 // text1=domain
|
#define DC_QR_WEBRTC_INSTANCE 260 // text1=domain, text2=instance pattern
|
||||||
#define DC_QR_ADDR 320 // id=contact
|
#define DC_QR_ADDR 320 // id=contact
|
||||||
#define DC_QR_TEXT 330 // text1=text
|
#define DC_QR_TEXT 330 // text1=text
|
||||||
#define DC_QR_URL 332 // text1=URL
|
#define DC_QR_URL 332 // text1=URL
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ use deltachat::*;
|
|||||||
use deltachat::{accounts::Accounts, log::LogExt};
|
use deltachat::{accounts::Accounts, log::LogExt};
|
||||||
|
|
||||||
mod dc_array;
|
mod dc_array;
|
||||||
|
mod lot;
|
||||||
|
|
||||||
mod string;
|
mod string;
|
||||||
use self::string::*;
|
use self::string::*;
|
||||||
@@ -2043,10 +2044,11 @@ pub unsafe extern "C" fn dc_check_qr(
|
|||||||
}
|
}
|
||||||
let ctx = &*context;
|
let ctx = &*context;
|
||||||
|
|
||||||
block_on(async move {
|
let lot = match block_on(qr::check_qr(ctx, &to_string_lossy(qr))) {
|
||||||
let lot = qr::check_qr(ctx, &to_string_lossy(qr)).await;
|
Ok(qr) => qr.into(),
|
||||||
Box::into_raw(Box::new(lot))
|
Err(err) => err.into(),
|
||||||
})
|
};
|
||||||
|
Box::into_raw(Box::new(lot))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
@@ -3608,7 +3610,7 @@ pub unsafe extern "C" fn dc_lot_get_state(lot: *mut dc_lot_t) -> libc::c_int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let lot = &*lot;
|
let lot = &*lot;
|
||||||
lot.get_state().to_i64().expect("impossible") as libc::c_int
|
lot.get_state() as libc::c_int
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
|
|||||||
245
deltachat-ffi/src/lot.rs
Normal file
245
deltachat-ffi/src/lot.rs
Normal file
@@ -0,0 +1,245 @@
|
|||||||
|
//! # Legacy generic return values for C API.
|
||||||
|
|
||||||
|
use crate::message::MessageState;
|
||||||
|
use crate::qr::Qr;
|
||||||
|
use crate::summary::{Summary, SummaryPrefix};
|
||||||
|
use anyhow::Error;
|
||||||
|
use std::borrow::Cow;
|
||||||
|
|
||||||
|
/// An object containing a set of values.
|
||||||
|
/// The meaning of the values is defined by the function returning the object.
|
||||||
|
/// Lot objects are created
|
||||||
|
/// eg. by chatlist.get_summary() or dc_msg_get_summary().
|
||||||
|
///
|
||||||
|
/// *Lot* is used in the meaning *heap* here.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Lot {
|
||||||
|
Summary(Summary),
|
||||||
|
Qr(Qr),
|
||||||
|
Error(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(u8)]
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
pub enum Meaning {
|
||||||
|
None = 0,
|
||||||
|
Text1Draft = 1,
|
||||||
|
Text1Username = 2,
|
||||||
|
Text1Self = 3,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Meaning {
|
||||||
|
fn default() -> Self {
|
||||||
|
Meaning::None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Lot {
|
||||||
|
pub fn get_text1(&self) -> Option<&str> {
|
||||||
|
match self {
|
||||||
|
Self::Summary(summary) => match &summary.prefix {
|
||||||
|
None => None,
|
||||||
|
Some(SummaryPrefix::Draft(text)) => Some(text),
|
||||||
|
Some(SummaryPrefix::Username(username)) => Some(username),
|
||||||
|
Some(SummaryPrefix::Me(text)) => Some(text),
|
||||||
|
},
|
||||||
|
Self::Qr(qr) => match qr {
|
||||||
|
Qr::AskVerifyContact { .. } => None,
|
||||||
|
Qr::AskVerifyGroup { grpname, .. } => Some(grpname),
|
||||||
|
Qr::FprOk { .. } => None,
|
||||||
|
Qr::FprMismatch { .. } => None,
|
||||||
|
Qr::FprWithoutAddr { fingerprint, .. } => Some(fingerprint),
|
||||||
|
Qr::Account { domain } => Some(domain),
|
||||||
|
Qr::WebrtcInstance { domain, .. } => Some(domain),
|
||||||
|
Qr::Addr { .. } => None,
|
||||||
|
Qr::Url { url } => Some(url),
|
||||||
|
Qr::Text { text } => Some(text),
|
||||||
|
Qr::WithdrawVerifyContact { .. } => None,
|
||||||
|
Qr::WithdrawVerifyGroup { grpname, .. } => Some(grpname),
|
||||||
|
Qr::ReviveVerifyContact { .. } => None,
|
||||||
|
Qr::ReviveVerifyGroup { grpname, .. } => Some(grpname),
|
||||||
|
},
|
||||||
|
Self::Error(err) => Some(err),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_text2(&self) -> Option<Cow<str>> {
|
||||||
|
match self {
|
||||||
|
Self::Summary(summary) => Some(summary.truncated_text(160)),
|
||||||
|
Self::Qr(_) => None,
|
||||||
|
Self::Error(_) => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_text1_meaning(&self) -> Meaning {
|
||||||
|
match self {
|
||||||
|
Self::Summary(summary) => match &summary.prefix {
|
||||||
|
None => Meaning::None,
|
||||||
|
Some(SummaryPrefix::Draft(_text)) => Meaning::Text1Draft,
|
||||||
|
Some(SummaryPrefix::Username(_username)) => Meaning::Text1Username,
|
||||||
|
Some(SummaryPrefix::Me(_text)) => Meaning::Text1Self,
|
||||||
|
},
|
||||||
|
Self::Qr(_qr) => Meaning::None,
|
||||||
|
Self::Error(_err) => Meaning::None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_state(&self) -> LotState {
|
||||||
|
match self {
|
||||||
|
Self::Summary(summary) => summary.state.into(),
|
||||||
|
Self::Qr(qr) => match qr {
|
||||||
|
Qr::AskVerifyContact { .. } => LotState::QrAskVerifyContact,
|
||||||
|
Qr::AskVerifyGroup { .. } => LotState::QrAskVerifyGroup,
|
||||||
|
Qr::FprOk { .. } => LotState::QrFprOk,
|
||||||
|
Qr::FprMismatch { .. } => LotState::QrFprMismatch,
|
||||||
|
Qr::FprWithoutAddr { .. } => LotState::QrFprWithoutAddr,
|
||||||
|
Qr::Account { .. } => LotState::QrAccount,
|
||||||
|
Qr::WebrtcInstance { .. } => LotState::QrWebrtcInstance,
|
||||||
|
Qr::Addr { .. } => LotState::QrAddr,
|
||||||
|
Qr::Url { .. } => LotState::QrUrl,
|
||||||
|
Qr::Text { .. } => LotState::QrText,
|
||||||
|
Qr::WithdrawVerifyContact { .. } => LotState::QrWithdrawVerifyContact,
|
||||||
|
Qr::WithdrawVerifyGroup { .. } => LotState::QrWithdrawVerifyGroup,
|
||||||
|
Qr::ReviveVerifyContact { .. } => LotState::QrReviveVerifyContact,
|
||||||
|
Qr::ReviveVerifyGroup { .. } => LotState::QrReviveVerifyGroup,
|
||||||
|
},
|
||||||
|
Self::Error(_err) => LotState::QrError,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_id(&self) -> u32 {
|
||||||
|
match self {
|
||||||
|
Self::Summary(_) => Default::default(),
|
||||||
|
Self::Qr(qr) => match qr {
|
||||||
|
Qr::AskVerifyContact { contact_id, .. } => *contact_id,
|
||||||
|
Qr::AskVerifyGroup { .. } => Default::default(),
|
||||||
|
Qr::FprOk { contact_id } => *contact_id,
|
||||||
|
Qr::FprMismatch { contact_id } => contact_id.unwrap_or_default(),
|
||||||
|
Qr::FprWithoutAddr { .. } => Default::default(),
|
||||||
|
Qr::Account { .. } => Default::default(),
|
||||||
|
Qr::WebrtcInstance { .. } => Default::default(),
|
||||||
|
Qr::Addr { contact_id } => *contact_id,
|
||||||
|
Qr::Url { .. } => Default::default(),
|
||||||
|
Qr::Text { .. } => Default::default(),
|
||||||
|
Qr::WithdrawVerifyContact { contact_id, .. } => *contact_id,
|
||||||
|
Qr::WithdrawVerifyGroup { .. } => Default::default(),
|
||||||
|
Qr::ReviveVerifyContact { contact_id, .. } => *contact_id,
|
||||||
|
Qr::ReviveVerifyGroup { .. } => Default::default(),
|
||||||
|
},
|
||||||
|
Self::Error(_) => Default::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_timestamp(&self) -> i64 {
|
||||||
|
match self {
|
||||||
|
Self::Summary(summary) => summary.timestamp,
|
||||||
|
Self::Qr(_) => Default::default(),
|
||||||
|
Self::Error(_) => Default::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(u32)]
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
pub enum LotState {
|
||||||
|
// Default
|
||||||
|
Undefined = 0,
|
||||||
|
|
||||||
|
// Qr States
|
||||||
|
/// id=contact
|
||||||
|
QrAskVerifyContact = 200,
|
||||||
|
|
||||||
|
/// text1=groupname
|
||||||
|
QrAskVerifyGroup = 202,
|
||||||
|
|
||||||
|
/// id=contact
|
||||||
|
QrFprOk = 210,
|
||||||
|
|
||||||
|
/// id=contact
|
||||||
|
QrFprMismatch = 220,
|
||||||
|
|
||||||
|
/// text1=formatted fingerprint
|
||||||
|
QrFprWithoutAddr = 230,
|
||||||
|
|
||||||
|
/// text1=domain
|
||||||
|
QrAccount = 250,
|
||||||
|
|
||||||
|
/// text1=domain, text2=instance pattern
|
||||||
|
QrWebrtcInstance = 260,
|
||||||
|
|
||||||
|
/// id=contact
|
||||||
|
QrAddr = 320,
|
||||||
|
|
||||||
|
/// text1=text
|
||||||
|
QrText = 330,
|
||||||
|
|
||||||
|
/// text1=URL
|
||||||
|
QrUrl = 332,
|
||||||
|
|
||||||
|
/// text1=error string
|
||||||
|
QrError = 400,
|
||||||
|
|
||||||
|
QrWithdrawVerifyContact = 500,
|
||||||
|
|
||||||
|
/// text1=groupname
|
||||||
|
QrWithdrawVerifyGroup = 502,
|
||||||
|
|
||||||
|
QrReviveVerifyContact = 510,
|
||||||
|
|
||||||
|
/// text1=groupname
|
||||||
|
QrReviveVerifyGroup = 512,
|
||||||
|
|
||||||
|
// Message States
|
||||||
|
MsgInFresh = 10,
|
||||||
|
MsgInNoticed = 13,
|
||||||
|
MsgInSeen = 16,
|
||||||
|
MsgOutPreparing = 18,
|
||||||
|
MsgOutDraft = 19,
|
||||||
|
MsgOutPending = 20,
|
||||||
|
MsgOutFailed = 24,
|
||||||
|
MsgOutDelivered = 26,
|
||||||
|
MsgOutMdnRcvd = 28,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for LotState {
|
||||||
|
fn default() -> Self {
|
||||||
|
LotState::Undefined
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<MessageState> for LotState {
|
||||||
|
fn from(s: MessageState) -> Self {
|
||||||
|
use MessageState::*;
|
||||||
|
match s {
|
||||||
|
Undefined => LotState::Undefined,
|
||||||
|
InFresh => LotState::MsgInFresh,
|
||||||
|
InNoticed => LotState::MsgInNoticed,
|
||||||
|
InSeen => LotState::MsgInSeen,
|
||||||
|
OutPreparing => LotState::MsgOutPreparing,
|
||||||
|
OutDraft => LotState::MsgOutDraft,
|
||||||
|
OutPending => LotState::MsgOutPending,
|
||||||
|
OutFailed => LotState::MsgOutFailed,
|
||||||
|
OutDelivered => LotState::MsgOutDelivered,
|
||||||
|
OutMdnRcvd => LotState::MsgOutMdnRcvd,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Summary> for Lot {
|
||||||
|
fn from(summary: Summary) -> Self {
|
||||||
|
Lot::Summary(summary)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Qr> for Lot {
|
||||||
|
fn from(qr: Qr) -> Self {
|
||||||
|
Lot::Qr(qr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make it easy to convert errors into the final `Lot`.
|
||||||
|
impl From<Error> for Lot {
|
||||||
|
fn from(error: Error) -> Self {
|
||||||
|
Lot::Error(error.to_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1158,14 +1158,8 @@ pub async fn cmdline(context: Context, line: &str, chat_id: &mut ChatId) -> Resu
|
|||||||
}
|
}
|
||||||
"checkqr" => {
|
"checkqr" => {
|
||||||
ensure!(!arg1.is_empty(), "Argument <qr-content> missing.");
|
ensure!(!arg1.is_empty(), "Argument <qr-content> missing.");
|
||||||
let res = check_qr(&context, arg1).await;
|
let qr = check_qr(&context, arg1).await?;
|
||||||
println!(
|
println!("qr={:?}", qr);
|
||||||
"state={}, id={}, text1={:?}, text2={:?}",
|
|
||||||
res.get_state(),
|
|
||||||
res.get_id(),
|
|
||||||
res.get_text1(),
|
|
||||||
res.get_text2()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
"setqr" => {
|
"setqr" => {
|
||||||
ensure!(!arg1.is_empty(), "Argument <qr-content> missing.");
|
ensure!(!arg1.is_empty(), "Argument <qr-content> missing.");
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
use std::convert::{TryFrom, TryInto};
|
use std::convert::{TryFrom, TryInto};
|
||||||
|
|
||||||
use anyhow::{bail, ensure, format_err, Context as _, Result};
|
use anyhow::{bail, ensure, Context as _, Result};
|
||||||
use async_std::path::PathBuf;
|
use async_std::path::PathBuf;
|
||||||
use deltachat_derive::{FromSql, ToSql};
|
use deltachat_derive::{FromSql, ToSql};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
@@ -1339,12 +1339,11 @@ fn cat_fingerprint(
|
|||||||
impl Context {
|
impl Context {
|
||||||
/// determine whether the specified addr maps to the/a self addr
|
/// determine whether the specified addr maps to the/a self addr
|
||||||
pub async fn is_self_addr(&self, addr: &str) -> Result<bool> {
|
pub async fn is_self_addr(&self, addr: &str) -> Result<bool> {
|
||||||
let self_addr = self
|
if let Some(self_addr) = self.get_config(Config::ConfiguredAddr).await? {
|
||||||
.get_config(Config::ConfiguredAddr)
|
Ok(addr_cmp(self_addr, addr))
|
||||||
.await?
|
} else {
|
||||||
.ok_or_else(|| format_err!("Not configured"))?;
|
Ok(false)
|
||||||
|
}
|
||||||
Ok(addr_cmp(self_addr, addr))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1491,7 +1490,7 @@ mod tests {
|
|||||||
#[async_std::test]
|
#[async_std::test]
|
||||||
async fn test_is_self_addr() -> Result<()> {
|
async fn test_is_self_addr() -> Result<()> {
|
||||||
let t = TestContext::new().await;
|
let t = TestContext::new().await;
|
||||||
assert!(t.is_self_addr("me@me.org").await.is_err());
|
assert_eq!(t.is_self_addr("me@me.org").await?, false);
|
||||||
|
|
||||||
let addr = t.configure_alice().await;
|
let addr = t.configure_alice().await;
|
||||||
assert_eq!(t.is_self_addr("me@me.org").await?, false);
|
assert_eq!(t.is_self_addr("me@me.org").await?, false);
|
||||||
|
|||||||
@@ -68,7 +68,6 @@ pub mod key;
|
|||||||
mod keyring;
|
mod keyring;
|
||||||
pub mod location;
|
pub mod location;
|
||||||
mod login_param;
|
mod login_param;
|
||||||
pub mod lot;
|
|
||||||
pub mod message;
|
pub mod message;
|
||||||
mod mimefactory;
|
mod mimefactory;
|
||||||
pub mod mimeparser;
|
pub mod mimeparser;
|
||||||
|
|||||||
181
src/lot.rs
181
src/lot.rs
@@ -1,181 +0,0 @@
|
|||||||
//! # Legacy generic return values for C API.
|
|
||||||
|
|
||||||
use deltachat_derive::{FromSql, ToSql};
|
|
||||||
|
|
||||||
use crate::key::Fingerprint;
|
|
||||||
use crate::message::MessageState;
|
|
||||||
use crate::summary::{Summary, SummaryPrefix};
|
|
||||||
|
|
||||||
/// An object containing a set of values.
|
|
||||||
/// The meaning of the values is defined by the function returning the object.
|
|
||||||
/// Lot objects are created
|
|
||||||
/// eg. by chatlist.get_summary() or dc_msg_get_summary().
|
|
||||||
///
|
|
||||||
/// *Lot* is used in the meaning *heap* here.
|
|
||||||
#[derive(Default, Debug, Clone)]
|
|
||||||
pub struct Lot {
|
|
||||||
pub(crate) text1_meaning: Meaning,
|
|
||||||
pub(crate) text1: Option<String>,
|
|
||||||
pub(crate) text2: Option<String>,
|
|
||||||
pub(crate) timestamp: i64,
|
|
||||||
pub(crate) state: LotState,
|
|
||||||
pub(crate) id: u32,
|
|
||||||
pub(crate) fingerprint: Option<Fingerprint>,
|
|
||||||
pub(crate) invitenumber: Option<String>,
|
|
||||||
pub(crate) auth: Option<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[repr(u8)]
|
|
||||||
#[derive(
|
|
||||||
Debug, Display, Clone, Copy, PartialEq, Eq, FromPrimitive, ToPrimitive, ToSql, FromSql,
|
|
||||||
)]
|
|
||||||
pub enum Meaning {
|
|
||||||
None = 0,
|
|
||||||
Text1Draft = 1,
|
|
||||||
Text1Username = 2,
|
|
||||||
Text1Self = 3,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for Meaning {
|
|
||||||
fn default() -> Self {
|
|
||||||
Meaning::None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Lot {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Default::default()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_text1(&self) -> Option<&str> {
|
|
||||||
self.text1.as_deref()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_text2(&self) -> Option<&str> {
|
|
||||||
self.text2.as_deref()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_text1_meaning(&self) -> Meaning {
|
|
||||||
self.text1_meaning
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_state(&self) -> LotState {
|
|
||||||
self.state
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_id(&self) -> u32 {
|
|
||||||
self.id
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_timestamp(&self) -> i64 {
|
|
||||||
self.timestamp
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[repr(u32)]
|
|
||||||
#[derive(
|
|
||||||
Debug, Display, Clone, Copy, PartialEq, Eq, FromPrimitive, ToPrimitive, ToSql, FromSql,
|
|
||||||
)]
|
|
||||||
pub enum LotState {
|
|
||||||
// Default
|
|
||||||
Undefined = 0,
|
|
||||||
|
|
||||||
// Qr States
|
|
||||||
/// id=contact
|
|
||||||
QrAskVerifyContact = 200,
|
|
||||||
|
|
||||||
/// text1=groupname
|
|
||||||
QrAskVerifyGroup = 202,
|
|
||||||
|
|
||||||
/// id=contact
|
|
||||||
QrFprOk = 210,
|
|
||||||
|
|
||||||
/// id=contact
|
|
||||||
QrFprMismatch = 220,
|
|
||||||
|
|
||||||
/// test1=formatted fingerprint
|
|
||||||
QrFprWithoutAddr = 230,
|
|
||||||
|
|
||||||
/// text1=domain
|
|
||||||
QrAccount = 250,
|
|
||||||
|
|
||||||
/// text1=domain, text2=instance pattern
|
|
||||||
QrWebrtcInstance = 260,
|
|
||||||
|
|
||||||
/// id=contact
|
|
||||||
QrAddr = 320,
|
|
||||||
|
|
||||||
/// text1=text
|
|
||||||
QrText = 330,
|
|
||||||
|
|
||||||
/// text1=URL
|
|
||||||
QrUrl = 332,
|
|
||||||
|
|
||||||
/// text1=error string
|
|
||||||
QrError = 400,
|
|
||||||
|
|
||||||
QrWithdrawVerifyContact = 500,
|
|
||||||
|
|
||||||
/// text1=groupname
|
|
||||||
QrWithdrawVerifyGroup = 502,
|
|
||||||
|
|
||||||
QrReviveVerifyContact = 510,
|
|
||||||
|
|
||||||
/// text1=groupname
|
|
||||||
QrReviveVerifyGroup = 512,
|
|
||||||
|
|
||||||
// Message States
|
|
||||||
MsgInFresh = 10,
|
|
||||||
MsgInNoticed = 13,
|
|
||||||
MsgInSeen = 16,
|
|
||||||
MsgOutPreparing = 18,
|
|
||||||
MsgOutDraft = 19,
|
|
||||||
MsgOutPending = 20,
|
|
||||||
MsgOutFailed = 24,
|
|
||||||
MsgOutDelivered = 26,
|
|
||||||
MsgOutMdnRcvd = 28,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for LotState {
|
|
||||||
fn default() -> Self {
|
|
||||||
LotState::Undefined
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<MessageState> for LotState {
|
|
||||||
fn from(s: MessageState) -> Self {
|
|
||||||
use MessageState::*;
|
|
||||||
match s {
|
|
||||||
Undefined => LotState::Undefined,
|
|
||||||
InFresh => LotState::MsgInFresh,
|
|
||||||
InNoticed => LotState::MsgInNoticed,
|
|
||||||
InSeen => LotState::MsgInSeen,
|
|
||||||
OutPreparing => LotState::MsgOutPreparing,
|
|
||||||
OutDraft => LotState::MsgOutDraft,
|
|
||||||
OutPending => LotState::MsgOutPending,
|
|
||||||
OutFailed => LotState::MsgOutFailed,
|
|
||||||
OutDelivered => LotState::MsgOutDelivered,
|
|
||||||
OutMdnRcvd => LotState::MsgOutMdnRcvd,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Summary> for Lot {
|
|
||||||
fn from(summary: Summary) -> Self {
|
|
||||||
let text2 = Some(summary.truncated_text(160).to_string());
|
|
||||||
let (text1, text1_meaning) = match summary.prefix {
|
|
||||||
None => (None, Meaning::None),
|
|
||||||
Some(SummaryPrefix::Draft(text)) => (Some(text), Meaning::Text1Draft),
|
|
||||||
Some(SummaryPrefix::Username(username)) => (Some(username), Meaning::Text1Username),
|
|
||||||
Some(SummaryPrefix::Me(text)) => (Some(text), Meaning::Text1Self),
|
|
||||||
};
|
|
||||||
Self {
|
|
||||||
text1_meaning,
|
|
||||||
text1,
|
|
||||||
text2,
|
|
||||||
timestamp: summary.timestamp,
|
|
||||||
state: summary.state.into(),
|
|
||||||
..Default::default()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -31,7 +31,7 @@ mod bobstate;
|
|||||||
mod qrinvite;
|
mod qrinvite;
|
||||||
|
|
||||||
use bobstate::{BobHandshakeStage, BobState, BobStateHandle};
|
use bobstate::{BobHandshakeStage, BobState, BobStateHandle};
|
||||||
use qrinvite::{QrError, QrInvite};
|
use qrinvite::QrInvite;
|
||||||
|
|
||||||
pub const NON_ALPHANUMERIC_WITHOUT_DOT: &AsciiSet = &NON_ALPHANUMERIC.remove(b'.');
|
pub const NON_ALPHANUMERIC_WITHOUT_DOT: &AsciiSet = &NON_ALPHANUMERIC.remove(b'.');
|
||||||
|
|
||||||
@@ -247,9 +247,6 @@ async fn get_self_fingerprint(context: &Context) -> Option<Fingerprint> {
|
|||||||
|
|
||||||
#[derive(Debug, thiserror::Error)]
|
#[derive(Debug, thiserror::Error)]
|
||||||
pub enum JoinError {
|
pub enum JoinError {
|
||||||
#[error("Unknown QR-code: {0}")]
|
|
||||||
QrCode(#[from] QrError),
|
|
||||||
|
|
||||||
#[error("An \"ongoing\" process is already running")]
|
#[error("An \"ongoing\" process is already running")]
|
||||||
OngoingRunning,
|
OngoingRunning,
|
||||||
|
|
||||||
@@ -293,7 +290,7 @@ async fn securejoin(context: &Context, qr: &str) -> Result<ChatId, JoinError> {
|
|||||||
========================================================*/
|
========================================================*/
|
||||||
|
|
||||||
info!(context, "Requesting secure-join ...",);
|
info!(context, "Requesting secure-join ...",);
|
||||||
let qr_scan = check_qr(context, qr).await;
|
let qr_scan = check_qr(context, qr).await?;
|
||||||
|
|
||||||
let invite = QrInvite::try_from(qr_scan)?;
|
let invite = QrInvite::try_from(qr_scan)?;
|
||||||
|
|
||||||
@@ -1146,7 +1143,7 @@ mod tests {
|
|||||||
async fn test_setup_contact_bad_qr() {
|
async fn test_setup_contact_bad_qr() {
|
||||||
let bob = TestContext::new_bob().await;
|
let bob = TestContext::new_bob().await;
|
||||||
let ret = dc_join_securejoin(&bob.ctx, "not a qr code").await;
|
let ret = dc_join_securejoin(&bob.ctx, "not a qr code").await;
|
||||||
assert!(matches!(ret, Err(JoinError::QrCode(_))));
|
assert!(ret.is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_std::test]
|
#[async_std::test]
|
||||||
|
|||||||
@@ -1,16 +1,15 @@
|
|||||||
//! Supporting code for the QR-code invite.
|
//! Supporting code for the QR-code invite.
|
||||||
//!
|
//!
|
||||||
//! QR-codes are decoded into a more general-purpose [`Lot`] struct normally, this struct is
|
//! QR-codes are decoded into a more general-purpose [`Qr`] struct normally. This makes working
|
||||||
//! so general it is not even specific to QR-codes. This makes working with it rather hard,
|
//! with it rather hard, so here we have a wrapper type that specifically deals with Secure-Join
|
||||||
//! so here we have a wrapper type that specifically deals with Secure-Join QR-codes so
|
//! QR-codes so that the Secure-Join code can have more guarantees when dealing with this.
|
||||||
//! that the Secure-Join code can have many more guarantees when dealing with this.
|
|
||||||
|
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::{bail, Error, Result};
|
||||||
|
|
||||||
use crate::key::Fingerprint;
|
use crate::key::Fingerprint;
|
||||||
use crate::lot::{Lot, LotState};
|
use crate::qr::Qr;
|
||||||
|
|
||||||
/// Represents the data from a QR-code scan.
|
/// Represents the data from a QR-code scan.
|
||||||
///
|
///
|
||||||
@@ -66,53 +65,38 @@ impl QrInvite {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryFrom<Lot> for QrInvite {
|
impl TryFrom<Qr> for QrInvite {
|
||||||
type Error = QrError;
|
type Error = Error;
|
||||||
|
|
||||||
fn try_from(lot: Lot) -> Result<Self, Self::Error> {
|
fn try_from(qr: Qr) -> Result<Self> {
|
||||||
if lot.state != LotState::QrAskVerifyContact && lot.state != LotState::QrAskVerifyGroup {
|
match qr {
|
||||||
return Err(QrError::UnsupportedProtocol);
|
Qr::AskVerifyContact {
|
||||||
}
|
contact_id,
|
||||||
if lot.id == 0 {
|
fingerprint,
|
||||||
return Err(QrError::MissingContactId);
|
invitenumber,
|
||||||
}
|
authcode,
|
||||||
let fingerprint = lot.fingerprint.ok_or(QrError::MissingFingerprint)?;
|
} => Ok(QrInvite::Contact {
|
||||||
let invitenumber = lot.invitenumber.ok_or(QrError::MissingInviteNumber)?;
|
contact_id,
|
||||||
let authcode = lot.auth.ok_or(QrError::MissingAuthCode)?;
|
|
||||||
match lot.state {
|
|
||||||
LotState::QrAskVerifyContact => Ok(QrInvite::Contact {
|
|
||||||
contact_id: lot.id,
|
|
||||||
fingerprint,
|
fingerprint,
|
||||||
invitenumber,
|
invitenumber,
|
||||||
authcode,
|
authcode,
|
||||||
}),
|
}),
|
||||||
LotState::QrAskVerifyGroup => Ok(QrInvite::Group {
|
Qr::AskVerifyGroup {
|
||||||
contact_id: lot.id,
|
grpname,
|
||||||
|
grpid,
|
||||||
|
contact_id,
|
||||||
fingerprint,
|
fingerprint,
|
||||||
name: lot.text1.ok_or(QrError::MissingGroupName)?,
|
invitenumber,
|
||||||
grpid: lot.text2.ok_or(QrError::MissingGroupId)?,
|
authcode,
|
||||||
|
} => Ok(QrInvite::Group {
|
||||||
|
contact_id,
|
||||||
|
fingerprint,
|
||||||
|
name: grpname,
|
||||||
|
grpid,
|
||||||
invitenumber,
|
invitenumber,
|
||||||
authcode,
|
authcode,
|
||||||
}),
|
}),
|
||||||
_ => Err(QrError::UnsupportedProtocol),
|
_ => bail!("Unsupported QR type {:?}", qr),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, thiserror::Error)]
|
|
||||||
pub enum QrError {
|
|
||||||
#[error("Unsupported protocol in QR-code")]
|
|
||||||
UnsupportedProtocol,
|
|
||||||
#[error("Missing fingerprint")]
|
|
||||||
MissingFingerprint,
|
|
||||||
#[error("Missing invitenumber")]
|
|
||||||
MissingInviteNumber,
|
|
||||||
#[error("Missing auth code")]
|
|
||||||
MissingAuthCode,
|
|
||||||
#[error("Missing group name")]
|
|
||||||
MissingGroupName,
|
|
||||||
#[error("Missing group id")]
|
|
||||||
MissingGroupId,
|
|
||||||
#[error("Missing contact id")]
|
|
||||||
MissingContactId,
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user