diff --git a/deltachat-ffi/deltachat.h b/deltachat-ffi/deltachat.h index 0e35a5506f..36555aa39d 100644 --- a/deltachat-ffi/deltachat.h +++ b/deltachat-ffi/deltachat.h @@ -2107,11 +2107,6 @@ dc_contact_t* dc_get_contact (dc_context_t* context, uint32_t co void dc_imex (dc_context_t* context, int what, const char* param1, const char* param2); -dc_backup_sender_t* dc_send_backup(dc_context_t* context, const char* folder, const char* passphrase); -char* dc_backup_sender_qr(dc_context_t* context, const dc_backup_sender_t* bs); -void dc_backup_sender_unref(dc_backup_sender_t* bs); - - /** * Check if there is a backup file. * May only be used on fresh installations (e.g. dc_is_configured() returns 0). @@ -2262,6 +2257,7 @@ void dc_stop_ongoing_process (dc_context_t* context); #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_BACKUP 251 // text1=ticket #define DC_QR_WEBRTC_INSTANCE 260 // text1=domain, text2=instance pattern #define DC_QR_ADDR 320 // id=contact #define DC_QR_TEXT 330 // text1=text @@ -2306,6 +2302,10 @@ void dc_stop_ongoing_process (dc_context_t* context); * ask the user if they want to create an account on the given domain, * if so, call dc_set_config_from_qr() and then dc_configure(). * + * - DC_QR_BACKUP with dc_lot_t::text1=ticket + * ask the user if they want to set up a new device. + * If so, get pass the ticket to dc_receive_backup(). + * * - DC_QR_WEBRTC_INSTANCE with dc_lot_t::text1=domain: * ask the user if they want to use the given service for video chats; * if so, call dc_set_config_from_qr(). @@ -2592,6 +2592,84 @@ char* dc_get_last_error (dc_context_t* context); void dc_str_unref (char* str); +/** + * @class dc_backup_sender_t + * + * Set up another device. + */ + +/** + * Create an object for sending a backup to another device. + * The backup is sent through an peer-to-peer channel which is bootstrapped by a QR-code. + * As a backup contains the whole state of the account, including credentials, + * this can be used to setup a new device. + * + * @memberof dc_backup_sender_t + * @param context The context. + * @param folder Path to create the backup in before it is sent out. + * The path must exist and being accessible at least until the other device has received all data. + * The folder is not cleaned up by the backup send; + * a temporary directory seems to be good place therefore. + * @param passphrase Used to at-rest-encrypt the backuped database in `folder` before sending, + * similar to dc_imex(). + * The same passphrase must be given to dc_receive_backup() on the other device. + * If NULL or empty string is given, the sent backup is not encrypted at rest. + * The transport of the backup is always encrypted additionally. + * @return Opaque object for sending the backup. + * On errors, NULL is returned and dc_get_last_error() returns an error that should be shown to the user. + */ +dc_backup_sender_t* dc_send_backup (dc_context_t* context, const char* folder, const char* passphrase); + + +/** + * Get QR code text that will offer the backup to other devices. + * The QR code contains a ticket that will unambiguously identify the backup. + * + * The scanning device will pass the scanned content to dc_check_qr() then; + * if dc_check_qr() returns DC_QR_BACKUP, + * the backup transfer can be started using dc_receive_backup(). + * + * @memberof dc_backup_sender_t + * @param context The context. + * @param backup_sender The backup sender object as created by dc_send_backup(). + * @return The text that should go to the QR code, + * On errors, an empty QR code is returned, NULL is never returned. + * The returned string must be released using dc_str_unref() after usage. + */ +char* dc_backup_sender_qr (dc_context_t* context, const dc_backup_sender_t* backup_sender); + + +/** + * Free a backup sender object. + * + * @memberof dc_backup_sender_t + * @param backup_sender The backup sender object as created by dc_send_backup(), + * If NULL is given, nothing is done. + */ +void dc_backup_sender_unref (dc_backup_sender_t* backup_sender); + + +/** + * Receive a backup offered by a dc_backup_sender_t object on another device. + * + * This function is typically not called on the device where the dc_backup_sender_t object exist, + * but on a device that has scanned the QR code generated by dc_backup_sender_qr(). + * + * While dc_receive_backup() returns immediately, the started job may take a while; + * you can stop it using dc_stop_ongoing_process(). + * During execution of the job #DC_EVENT_IMEX_PROGRESS is sent out several times to indicate state and progress. + * + * @memberof dc_backup_sender_t + * @param context The context. + * @param ticket The ticket of the backup from the QR code: + * If dc_check_qr() returns DC_QR_BACKUP, you can get the ticket from the QR code using dc_lot_get_text1(). + * @param passphrase Passphrase for the additional at-rest-encryption + * as defined at dc_send_backup() on the other device. + * If no passphrase is used, pass NULL or empty string. + */ +void dc_receive_backup (dc_context_t* context, const char* ticket, const char* passphrase); + + /** * @class dc_accounts_t * diff --git a/examples/repl/cmdline.rs b/examples/repl/cmdline.rs index aab5cbc708..03b8839290 100644 --- a/examples/repl/cmdline.rs +++ b/examples/repl/cmdline.rs @@ -333,8 +333,8 @@ pub async fn cmdline(context: Context, line: &str, chat_id: &mut ChatId) -> Resu continue-key-transfer \n\ has-backup\n\ export-backup\n\ - send-backup\n\ - receive-backup \n\ + send-backup []\n\ + receive-backup []\n\ import-backup \n\ export-keys\n\ import-keys\n\ @@ -479,7 +479,7 @@ pub async fn cmdline(context: Context, line: &str, chat_id: &mut ChatId) -> Resu "send-backup" => { let dir = dirs::home_dir().unwrap_or_default(); let (sender, transfer) = - send_backup(&context, dir.as_ref(), Some(arg2.to_string())).await?; + send_backup(&context, dir.as_ref(), Some(arg1.to_string())).await?; let ticket = transfer.ticket(); let ticket_bytes = ticket.as_bytes(); diff --git a/examples/repl/main.rs b/examples/repl/main.rs index 1c35fe1813..e43869f8ab 100644 --- a/examples/repl/main.rs +++ b/examples/repl/main.rs @@ -142,13 +142,15 @@ impl Completer for DcHelper { } } -const IMEX_COMMANDS: [&str; 12] = [ +const IMEX_COMMANDS: [&str; 14] = [ "initiate-key-transfer", "get-setupcodebegin", "continue-key-transfer", "has-backup", "export-backup", "import-backup", + "send-backup", + "receive-backup", "export-keys", "import-keys", "export-setup", diff --git a/src/qr.rs b/src/qr.rs index f0820d56a4..bc7bc95d98 100644 --- a/src/qr.rs +++ b/src/qr.rs @@ -496,7 +496,7 @@ async fn decode_mailto(context: &Context, qr: &str) -> Result { if subject.is_empty() { body.to_string() } else { - subject + "\n" + body + subject + "\n" + *body } } else { subject