diff --git a/deltachat-jsonrpc/src/api/types/mod.rs b/deltachat-jsonrpc/src/api/types/mod.rs index 5f8b541bd..a0f973271 100644 --- a/deltachat-jsonrpc/src/api/types/mod.rs +++ b/deltachat-jsonrpc/src/api/types/mod.rs @@ -20,3 +20,215 @@ fn maybe_empty_string_to_option(string: String) -> Option { Some(string) } } +#[derive(Serialize, TypeDef)] +#[serde(rename = "Qr", rename_all = "camelCase")] +#[serde(tag = "type")] +pub enum QrObject { + AskVerifyContact { + contact_id: u32, + fingerprint: String, + invitenumber: String, + authcode: String, + }, + AskVerifyGroup { + grpname: String, + grpid: String, + contact_id: u32, + fingerprint: String, + invitenumber: String, + authcode: String, + }, + FprOk { + contact_id: u32, + }, + FprMismatch { + contact_id: Option, + }, + FprWithoutAddr { + fingerprint: String, + }, + Account { + domain: String, + }, + WebrtcInstance { + domain: String, + instance_pattern: String, + }, + Addr { + contact_id: u32, + draft: Option, + }, + Url { + url: String, + }, + Text { + text: String, + }, + WithdrawVerifyContact { + contact_id: u32, + fingerprint: String, + invitenumber: String, + authcode: String, + }, + WithdrawVerifyGroup { + grpname: String, + grpid: String, + contact_id: u32, + fingerprint: String, + invitenumber: String, + authcode: String, + }, + ReviveVerifyContact { + contact_id: u32, + fingerprint: String, + invitenumber: String, + authcode: String, + }, + ReviveVerifyGroup { + grpname: String, + grpid: String, + contact_id: u32, + fingerprint: String, + invitenumber: String, + authcode: String, + }, + Login { + address: String, + }, +} + +impl From for QrObject { + fn from(qr: Qr) -> Self { + match qr { + Qr::AskVerifyContact { + contact_id, + fingerprint, + invitenumber, + authcode, + } => { + let contact_id = contact_id.to_u32(); + let fingerprint = fingerprint.to_string(); + QrObject::AskVerifyContact { + contact_id, + fingerprint, + invitenumber, + authcode, + } + } + Qr::AskVerifyGroup { + grpname, + grpid, + contact_id, + fingerprint, + invitenumber, + authcode, + } => { + let contact_id = contact_id.to_u32(); + let fingerprint = fingerprint.to_string(); + QrObject::AskVerifyGroup { + grpname, + grpid, + contact_id, + fingerprint, + invitenumber, + authcode, + } + } + Qr::FprOk { contact_id } => { + let contact_id = contact_id.to_u32(); + QrObject::FprOk { contact_id } + } + Qr::FprMismatch { contact_id } => { + 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::WebrtcInstance { + domain, + instance_pattern, + } => QrObject::WebrtcInstance { + domain, + instance_pattern, + }, + Qr::Addr { contact_id, draft } => { + let contact_id = contact_id.to_u32(); + QrObject::Addr { contact_id, draft } + } + Qr::Url { url } => QrObject::Url { url }, + Qr::Text { text } => QrObject::Text { text }, + Qr::WithdrawVerifyContact { + contact_id, + fingerprint, + invitenumber, + authcode, + } => { + let contact_id = contact_id.to_u32(); + let fingerprint = fingerprint.to_string(); + QrObject::WithdrawVerifyContact { + contact_id, + fingerprint, + invitenumber, + authcode, + } + } + Qr::WithdrawVerifyGroup { + grpname, + grpid, + contact_id, + fingerprint, + invitenumber, + authcode, + } => { + let contact_id = contact_id.to_u32(); + let fingerprint = fingerprint.to_string(); + QrObject::WithdrawVerifyGroup { + grpname, + grpid, + contact_id, + fingerprint, + invitenumber, + authcode, + } + } + Qr::ReviveVerifyContact { + contact_id, + fingerprint, + invitenumber, + authcode, + } => { + let contact_id = contact_id.to_u32(); + let fingerprint = fingerprint.to_string(); + QrObject::ReviveVerifyContact { + contact_id, + fingerprint, + invitenumber, + authcode, + } + } + Qr::ReviveVerifyGroup { + grpname, + grpid, + contact_id, + fingerprint, + invitenumber, + authcode, + } => { + let contact_id = contact_id.to_u32(); + let fingerprint = fingerprint.to_string(); + QrObject::ReviveVerifyGroup { + grpname, + grpid, + contact_id, + fingerprint, + invitenumber, + authcode, + } + } + Qr::Login { address, .. } => QrObject::Login { address }, + Qr::Backup { ticket } => QrObject::Backup { + ticket: ticket.as_bytes(), + }, + } + } +} diff --git a/examples/repl/cmdline.rs b/examples/repl/cmdline.rs index d8dee3b1c..83a7e9bb9 100644 --- a/examples/repl/cmdline.rs +++ b/examples/repl/cmdline.rs @@ -489,7 +489,7 @@ pub async fn cmdline(context: Context, line: &str, chat_id: &mut ChatId) -> Resu "Ticket: {}", multibase::encode(multibase::Base::Base64, &ticket_bytes) ); - let qr_code = deltachat::qr_code_generator::generate_backup_qr_code(&ticket)?; + let qr_code = deltachat::qr_code_generator::generate_backup_qr_code(ticket)?; let file = dir.join("qr.svg"); tokio::fs::write(file, qr_code.as_bytes()).await?; @@ -497,7 +497,7 @@ pub async fn cmdline(context: Context, line: &str, chat_id: &mut ChatId) -> Resu } "receive-backup" => { ensure!(!arg1.is_empty(), "Argument is missing."); - let (_, ticket) = multibase::decode(&arg1.to_string())?; + let (_, ticket) = multibase::decode(&arg1)?; receive_backup(&context, ticket, Some(arg2.to_string())).await?; } "import-backup" => { diff --git a/src/imex.rs b/src/imex.rs index 2ffd253c7..1164288ea 100644 --- a/src/imex.rs +++ b/src/imex.rs @@ -151,11 +151,11 @@ pub async fn receive_backup_inner( ); let ticket = Ticket::from_bytes(&ticket_bytes)?; - let sender_dir = tempfile::tempdir().unwrap(); - let sender_db = sender_dir.path().join("db"); - + let recv_dir = tempfile::tempdir().unwrap(); + let recv_db = recv_dir.path().join("db"); let port = 9991; - let receiver = Receiver::new(port, &sender_db) + + let receiver = Receiver::new(port, &recv_db) .await .context("failed to create sender")?; let mut receiver_transfer = receiver @@ -190,16 +190,20 @@ pub async fn receive_backup_inner( let out = context.get_blobdir(); - for link in data.read_dir().unwrap() { + let mut read_dir_stream = data + .read_dir()? + .ok_or_else(|| anyhow::anyhow!("unexpected data structure"))?; + + while let Some(link) = read_dir_stream.next().await { let link = link?; let file_content = data.read_file(&link).await?; let name = link.name.unwrap_or_default(); let path = out.join(&name); - println!("Writing {}", path.display()); + let mut file = tokio::fs::File::create(&path) .await .with_context(|| format!("create file: {}", path.display()))?; - let mut content = file_content.pretty(); + let mut content = file_content.pretty()?; tokio::io::copy(&mut content, &mut file) .await .context("copy")?; @@ -223,7 +227,7 @@ pub async fn receive_backup_inner( progress_task.await?; receiver_transfer.finish().await?; - println!("Received all data, written to: {}", out.display()); + info!(context, "Received all data, written to: {}", out.display()); Ok(()) } @@ -246,10 +250,10 @@ pub async fn send_backup( if let Err(err) = res.as_ref() { // We are using Anyhow's .context() and to show the inner error, too, we need the {:#}: - error!(context, "IMEX failed to complete: {:#}", err); + error!(context, "Send backup failed to complete: {:#}", err); context.emit_event(EventType::ImexProgress(0)); } else { - info!(context, "IMEX successfully completed"); + info!(context, "Send backup successfully completed"); context.emit_event(EventType::ImexProgress(1000)); } @@ -261,7 +265,7 @@ async fn send_backup_inner( path: &Path, passphrase: Option, ) -> Result { - info!(context, "Import/export dir: {}", path.display()); + info!(context, "Send backup dir: {}", path.display()); ensure!(context.sql.is_open().await, "Database not opened."); context.emit_event(EventType::ImexProgress(10)); diff --git a/src/qr.rs b/src/qr.rs index c025eca34..191e79a3c 100644 --- a/src/qr.rs +++ b/src/qr.rs @@ -34,7 +34,7 @@ const HTTP_SCHEME: &str = "http://"; const HTTPS_SCHEME: &str = "https://"; pub const DCBACKUP_SCHEME: &str = "DCBACKUP:"; -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq)] pub enum Qr { AskVerifyContact { contact_id: ContactId,