Backup: Use tasks for restore
This commit is contained in:
parent
e6e16999ae
commit
dfc788cd29
6 changed files with 335 additions and 74 deletions
|
@ -58,29 +58,32 @@ import org.shadowice.flocke.andotp.Database.Entry;
|
|||
import org.shadowice.flocke.andotp.Dialogs.PasswordEntryDialog;
|
||||
import org.shadowice.flocke.andotp.R;
|
||||
import org.shadowice.flocke.andotp.Tasks.EncryptedBackupTask;
|
||||
import org.shadowice.flocke.andotp.Tasks.EncryptedRestoreTask;
|
||||
import org.shadowice.flocke.andotp.Tasks.GenericBackupTask;
|
||||
import org.shadowice.flocke.andotp.Tasks.GenericRestoreTask;
|
||||
import org.shadowice.flocke.andotp.Tasks.PGPBackupTask;
|
||||
import org.shadowice.flocke.andotp.Tasks.PGPRestoreTask;
|
||||
import org.shadowice.flocke.andotp.Tasks.PlainTextBackupTask;
|
||||
import org.shadowice.flocke.andotp.Tasks.PlainTextRestoreTask;
|
||||
import org.shadowice.flocke.andotp.Utilities.BackupHelper;
|
||||
import org.shadowice.flocke.andotp.Utilities.Constants;
|
||||
import org.shadowice.flocke.andotp.Utilities.DatabaseHelper;
|
||||
import org.shadowice.flocke.andotp.Utilities.EncryptionHelper;
|
||||
import org.shadowice.flocke.andotp.Utilities.StorageAccessHelper;
|
||||
import org.shadowice.flocke.andotp.Utilities.Tools;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
import javax.crypto.SecretKey;
|
||||
|
||||
public class BackupActivity extends BaseActivity {
|
||||
private final static String TAG = BackupActivity.class.getSimpleName();
|
||||
private static final String TAG_TASK_FRAGMENT = "BackupActivity.TaskFragmentTag";
|
||||
|
||||
private static final String TAG_BACKUP_TASK_FRAGMENT = "BackupActivity.BackupTaskFragmentTag";
|
||||
private static final String TAG_RESTORE_TASK_FRAGMENT = "BackupActivity.RestoreTaskFragmentTag";
|
||||
|
||||
private Constants.BackupType backupType = Constants.BackupType.ENCRYPTED;
|
||||
private SecretKey encryptionKey = null;
|
||||
|
@ -279,12 +282,15 @@ public class BackupActivity extends BaseActivity {
|
|||
|
||||
if (result.messageId != 0)
|
||||
notifyBackupState(result.messageId);
|
||||
else
|
||||
if (!result.success)
|
||||
notifyBackupState(R.string.backup_toast_export_failed);
|
||||
|
||||
// Clean up the task fragment
|
||||
TaskFragment taskFragment = findTaskFragment();
|
||||
if (taskFragment != null) {
|
||||
BackupTaskFragment backupTaskFragment = findBackupTaskFragment();
|
||||
if (backupTaskFragment != null) {
|
||||
getFragmentManager().beginTransaction()
|
||||
.remove(taskFragment)
|
||||
.remove(backupTaskFragment)
|
||||
.commit();
|
||||
}
|
||||
|
||||
|
@ -292,17 +298,59 @@ public class BackupActivity extends BaseActivity {
|
|||
finishWithResult();
|
||||
}
|
||||
|
||||
private void showBackupProgress(boolean running) {
|
||||
private void handleRestoreTaskResult(GenericRestoreTask.RestoreTaskResult result) {
|
||||
if (result.success) {
|
||||
if (result.isPGP) {
|
||||
InputStream is = new ByteArrayInputStream(result.payload.getBytes(StandardCharsets.UTF_8));
|
||||
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||
|
||||
OpenPgpApi api = new OpenPgpApi(this, pgpServiceConnection.getService());
|
||||
Intent resultIntent = api.executeApi(result.decryptIntent, is, os);
|
||||
|
||||
handleOpenPGPResult(resultIntent, os, result.uri, Constants.INTENT_BACKUP_DECRYPT_PGP);
|
||||
} else {
|
||||
restoreEntries(result.payload, false);
|
||||
}
|
||||
} else {
|
||||
if (result.messageId != 0)
|
||||
notifyBackupState(result.messageId);
|
||||
else
|
||||
notifyBackupState(R.string.backup_toast_import_failed);
|
||||
}
|
||||
|
||||
showRestoreProgress(false);
|
||||
|
||||
// Clean up the task fragment
|
||||
RestoreTaskFragment restoreTaskFragment = findRestoreTaskFragment();
|
||||
if (restoreTaskFragment != null) {
|
||||
getFragmentManager().beginTransaction()
|
||||
.remove(restoreTaskFragment)
|
||||
.commit();
|
||||
}
|
||||
|
||||
if (result.success && !result.isPGP)
|
||||
finishWithResult();
|
||||
}
|
||||
|
||||
private void toggleInProgressMode(boolean running) {
|
||||
allowExit = !running;
|
||||
|
||||
btnBackup.setEnabled(!running);
|
||||
btnRestore.setEnabled(!running);
|
||||
chkOldFormat.setEnabled(!running);
|
||||
swReplace.setEnabled(!running);
|
||||
}
|
||||
|
||||
private void showBackupProgress(boolean running) {
|
||||
toggleInProgressMode(running);
|
||||
progressBackup.setVisibility(running ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
|
||||
private void showRestoreProgress(boolean running) {
|
||||
toggleInProgressMode(running);
|
||||
progressRestore.setVisibility(running ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
|
||||
// Get the result from external activities
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
|
||||
|
@ -387,7 +435,7 @@ public class BackupActivity extends BaseActivity {
|
|||
}
|
||||
}
|
||||
|
||||
private void restoreEntries(String text) {
|
||||
private void restoreEntries(String text, boolean finish) {
|
||||
ArrayList<Entry> entries = DatabaseHelper.stringToEntries(text);
|
||||
|
||||
if (entries.size() > 0) {
|
||||
|
@ -401,7 +449,9 @@ public class BackupActivity extends BaseActivity {
|
|||
if (DatabaseHelper.saveDatabase(this, entries, encryptionKey)) {
|
||||
reload = true;
|
||||
Toast.makeText(this, R.string.backup_toast_import_success, Toast.LENGTH_LONG).show();
|
||||
finishWithResult();
|
||||
|
||||
if (finish)
|
||||
finishWithResult();
|
||||
} else {
|
||||
Toast.makeText(this, R.string.backup_toast_import_save_failed, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
@ -414,9 +464,10 @@ public class BackupActivity extends BaseActivity {
|
|||
|
||||
private void doRestorePlain(Uri uri) {
|
||||
if (Tools.isExternalStorageReadable()) {
|
||||
String content = StorageAccessHelper.loadFileString(this, uri);
|
||||
PlainTextRestoreTask task = new PlainTextRestoreTask(this, uri);
|
||||
task.setCallback(this::handleRestoreTaskResult);
|
||||
|
||||
restoreEntries(content);
|
||||
startRestoreTask(task);
|
||||
} else {
|
||||
Toast.makeText(this, R.string.backup_toast_storage_not_accessible, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
@ -475,39 +526,10 @@ public class BackupActivity extends BaseActivity {
|
|||
|
||||
private void doRestoreCryptWithPassword(Uri uri, String password, boolean old_format) {
|
||||
if (Tools.isExternalStorageReadable()) {
|
||||
boolean success = true;
|
||||
String decryptedString = "";
|
||||
EncryptedRestoreTask task = new EncryptedRestoreTask(this, uri, password, old_format);
|
||||
task.setCallback(this::handleRestoreTaskResult);
|
||||
|
||||
try {
|
||||
byte[] data = StorageAccessHelper.loadFile(this, uri);
|
||||
|
||||
if (old_format) {
|
||||
SecretKey key = EncryptionHelper.generateSymmetricKeyFromPassword(password);
|
||||
byte[] decrypted = EncryptionHelper.decrypt(key, data);
|
||||
|
||||
decryptedString = new String(decrypted, StandardCharsets.UTF_8);
|
||||
} else {
|
||||
byte[] iterBytes = Arrays.copyOfRange(data, 0, Constants.INT_LENGTH);
|
||||
byte[] salt = Arrays.copyOfRange(data, Constants.INT_LENGTH, Constants.INT_LENGTH + Constants.ENCRYPTION_IV_LENGTH);
|
||||
byte[] encrypted = Arrays.copyOfRange(data, Constants.INT_LENGTH + Constants.ENCRYPTION_IV_LENGTH, data.length);
|
||||
|
||||
int iter = ByteBuffer.wrap(iterBytes).getInt();
|
||||
|
||||
SecretKey key = EncryptionHelper.generateSymmetricKeyPBKDF2(password, iter, salt);
|
||||
|
||||
byte[] decrypted = EncryptionHelper.decrypt(key, encrypted);
|
||||
decryptedString = new String(decrypted, StandardCharsets.UTF_8);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
success = false;
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
if (success) {
|
||||
restoreEntries(decryptedString);
|
||||
} else {
|
||||
Toast.makeText(this,R.string.backup_toast_import_decryption_failed, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
startRestoreTask(task);
|
||||
} else {
|
||||
Toast.makeText(this, R.string.backup_toast_storage_not_accessible, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
@ -548,13 +570,10 @@ public class BackupActivity extends BaseActivity {
|
|||
if (decryptIntent == null)
|
||||
decryptIntent = new Intent(OpenPgpApi.ACTION_DECRYPT_VERIFY);
|
||||
|
||||
String input = StorageAccessHelper.loadFileString(this, uri);
|
||||
PGPRestoreTask task = new PGPRestoreTask(this, uri, decryptIntent);
|
||||
task.setCallback(this::handleRestoreTaskResult);
|
||||
|
||||
InputStream is = new ByteArrayInputStream(input.getBytes(StandardCharsets.UTF_8));
|
||||
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||
OpenPgpApi api = new OpenPgpApi(this, pgpServiceConnection.getService());
|
||||
Intent result = api.executeApi(decryptIntent, is, os);
|
||||
handleOpenPGPResult(result, os, uri, Constants.INTENT_BACKUP_DECRYPT_PGP);
|
||||
startRestoreTask(task);
|
||||
}
|
||||
|
||||
private void doBackupEncrypted(Uri uri, String data) {
|
||||
|
@ -608,12 +627,12 @@ public class BackupActivity extends BaseActivity {
|
|||
OpenPgpSignatureResult sigResult = result.getParcelableExtra(OpenPgpApi.RESULT_SIGNATURE);
|
||||
|
||||
if (sigResult.getResult() == OpenPgpSignatureResult.RESULT_VALID_KEY_CONFIRMED) {
|
||||
restoreEntries(outputStreamToString(os));
|
||||
restoreEntries(outputStreamToString(os), true);
|
||||
} else {
|
||||
Toast.makeText(this, R.string.backup_toast_openpgp_not_verified, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
} else {
|
||||
restoreEntries(outputStreamToString(os));
|
||||
restoreEntries(outputStreamToString(os), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -639,42 +658,86 @@ public class BackupActivity extends BaseActivity {
|
|||
}
|
||||
|
||||
@Nullable
|
||||
private TaskFragment findTaskFragment() {
|
||||
return (TaskFragment) getFragmentManager().findFragmentByTag(TAG_TASK_FRAGMENT);
|
||||
private BackupTaskFragment findBackupTaskFragment() {
|
||||
return (BackupTaskFragment) getFragmentManager().findFragmentByTag(TAG_BACKUP_TASK_FRAGMENT);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private RestoreTaskFragment findRestoreTaskFragment() {
|
||||
return (RestoreTaskFragment) getFragmentManager().findFragmentByTag(TAG_RESTORE_TASK_FRAGMENT);
|
||||
}
|
||||
|
||||
private void startBackupTask(GenericBackupTask task) {
|
||||
TaskFragment taskFragment = findTaskFragment();
|
||||
BackupTaskFragment backupTaskFragment = findBackupTaskFragment();
|
||||
RestoreTaskFragment restoreTaskFragment = findRestoreTaskFragment();
|
||||
|
||||
// Don't start a task if we already have an active task running.
|
||||
if (taskFragment == null || taskFragment.task.isCanceled()) {
|
||||
if (taskFragment == null) {
|
||||
taskFragment = new TaskFragment();
|
||||
// Don't start a task if we already have an active task running (backup or restore).
|
||||
if ((backupTaskFragment == null || backupTaskFragment.task.isCanceled()) && (restoreTaskFragment == null || restoreTaskFragment.task.isCanceled())) {
|
||||
if (backupTaskFragment == null) {
|
||||
backupTaskFragment = new BackupTaskFragment();
|
||||
getFragmentManager()
|
||||
.beginTransaction()
|
||||
.add(taskFragment, TAG_TASK_FRAGMENT)
|
||||
.add(backupTaskFragment, TAG_BACKUP_TASK_FRAGMENT)
|
||||
.commit();
|
||||
}
|
||||
|
||||
taskFragment.startTask(task);
|
||||
backupTaskFragment.startTask(task);
|
||||
|
||||
showBackupProgress(true);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkBackgroundTask() {
|
||||
TaskFragment taskFragment = findTaskFragment();
|
||||
if (taskFragment != null) {
|
||||
if (taskFragment.task.isCanceled()) {
|
||||
private void startRestoreTask(GenericRestoreTask task) {
|
||||
BackupTaskFragment backupTaskFragment = findBackupTaskFragment();
|
||||
RestoreTaskFragment restoreTaskFragment = findRestoreTaskFragment();
|
||||
|
||||
// Don't start a task if we already have an active task running (backup or restore).
|
||||
if ((backupTaskFragment == null || backupTaskFragment.task.isCanceled()) && (restoreTaskFragment == null || restoreTaskFragment.task.isCanceled())) {
|
||||
if (restoreTaskFragment == null) {
|
||||
restoreTaskFragment = new RestoreTaskFragment();
|
||||
getFragmentManager()
|
||||
.beginTransaction()
|
||||
.add(restoreTaskFragment, TAG_RESTORE_TASK_FRAGMENT)
|
||||
.commit();
|
||||
}
|
||||
|
||||
restoreTaskFragment.startTask(task);
|
||||
|
||||
showRestoreProgress(true);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkBackgroundBackupTask() {
|
||||
BackupTaskFragment backupTaskFragment = findBackupTaskFragment();
|
||||
|
||||
if (backupTaskFragment != null) {
|
||||
if (backupTaskFragment.task.isCanceled()) {
|
||||
// The task was canceled or has finished, so remove the task fragment.
|
||||
getFragmentManager().beginTransaction()
|
||||
.remove(taskFragment)
|
||||
.remove(backupTaskFragment)
|
||||
.commit();
|
||||
} else {
|
||||
taskFragment.task.setCallback(this::handleBackupTaskResult);
|
||||
backupTaskFragment.task.setCallback(this::handleBackupTaskResult);
|
||||
showBackupProgress(true);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void checkBackgroundRestoreTask() {
|
||||
RestoreTaskFragment restoreTaskFragment = findRestoreTaskFragment();
|
||||
|
||||
if (restoreTaskFragment != null) {
|
||||
if (restoreTaskFragment.task.isCanceled()) {
|
||||
// The task was canceled or has finished, so remove the task fragment.
|
||||
getFragmentManager().beginTransaction()
|
||||
.remove(restoreTaskFragment)
|
||||
.commit();
|
||||
} else {
|
||||
restoreTaskFragment.task.setCallback(this::handleRestoreTaskResult);
|
||||
showRestoreProgress(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -682,16 +745,22 @@ public class BackupActivity extends BaseActivity {
|
|||
super.onPause();
|
||||
|
||||
// We don't want the task to callback to a dead activity and cause a memory leak, so null it here.
|
||||
TaskFragment taskFragment = findTaskFragment();
|
||||
if (taskFragment != null) {
|
||||
taskFragment.task.setCallback(null);
|
||||
}
|
||||
BackupTaskFragment backupTaskFragment = findBackupTaskFragment();
|
||||
RestoreTaskFragment restoreTaskFragment = findRestoreTaskFragment();
|
||||
|
||||
if (backupTaskFragment != null)
|
||||
backupTaskFragment.task.setCallback(null);
|
||||
|
||||
if (restoreTaskFragment != null)
|
||||
restoreTaskFragment.task.setCallback(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
checkBackgroundTask();
|
||||
|
||||
checkBackgroundBackupTask();
|
||||
checkBackgroundRestoreTask();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -700,10 +769,10 @@ public class BackupActivity extends BaseActivity {
|
|||
}
|
||||
|
||||
/** Retained instance fragment to hold a running {@link GenericBackupTask} between configuration changes.*/
|
||||
public static class TaskFragment extends Fragment {
|
||||
public static class BackupTaskFragment extends Fragment {
|
||||
GenericBackupTask task;
|
||||
|
||||
public TaskFragment() {
|
||||
public BackupTaskFragment() {
|
||||
super();
|
||||
setRetainInstance(true);
|
||||
}
|
||||
|
@ -713,4 +782,19 @@ public class BackupActivity extends BaseActivity {
|
|||
this.task.execute();
|
||||
}
|
||||
}
|
||||
|
||||
/** Retained instance fragment to hold a running {@link GenericRestoreTask} between configuration changes.*/
|
||||
public static class RestoreTaskFragment extends Fragment {
|
||||
GenericRestoreTask task;
|
||||
|
||||
public RestoreTaskFragment() {
|
||||
super();
|
||||
setRetainInstance(true);
|
||||
}
|
||||
|
||||
public void startTask(@NonNull GenericRestoreTask task) {
|
||||
this.task = task;
|
||||
this.task.execute();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
package org.shadowice.flocke.andotp.Tasks;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import org.shadowice.flocke.andotp.R;
|
||||
import org.shadowice.flocke.andotp.Utilities.Constants;
|
||||
import org.shadowice.flocke.andotp.Utilities.EncryptionHelper;
|
||||
import org.shadowice.flocke.andotp.Utilities.StorageAccessHelper;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
|
||||
import javax.crypto.SecretKey;
|
||||
|
||||
public class EncryptedRestoreTask extends GenericRestoreTask {
|
||||
private final String password;
|
||||
private final boolean oldFormat;
|
||||
|
||||
public EncryptedRestoreTask(Context context, Uri uri, String password, boolean oldFormat) {
|
||||
super(context, uri);
|
||||
this.password = password;
|
||||
this.oldFormat = oldFormat;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
protected RestoreTaskResult doInBackground() {
|
||||
boolean success = true;
|
||||
String decryptedString = "";
|
||||
|
||||
try {
|
||||
byte[] data = StorageAccessHelper.loadFile(applicationContext, uri);
|
||||
|
||||
if (oldFormat) {
|
||||
SecretKey key = EncryptionHelper.generateSymmetricKeyFromPassword(password);
|
||||
byte[] decrypted = EncryptionHelper.decrypt(key, data);
|
||||
|
||||
decryptedString = new String(decrypted, StandardCharsets.UTF_8);
|
||||
} else {
|
||||
byte[] iterBytes = Arrays.copyOfRange(data, 0, Constants.INT_LENGTH);
|
||||
byte[] salt = Arrays.copyOfRange(data, Constants.INT_LENGTH, Constants.INT_LENGTH + Constants.ENCRYPTION_IV_LENGTH);
|
||||
byte[] encrypted = Arrays.copyOfRange(data, Constants.INT_LENGTH + Constants.ENCRYPTION_IV_LENGTH, data.length);
|
||||
|
||||
int iter = ByteBuffer.wrap(iterBytes).getInt();
|
||||
|
||||
SecretKey key = EncryptionHelper.generateSymmetricKeyPBKDF2(password, iter, salt);
|
||||
|
||||
byte[] decrypted = EncryptionHelper.decrypt(key, encrypted);
|
||||
decryptedString = new String(decrypted, StandardCharsets.UTF_8);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
success = false;
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
if (success) {
|
||||
return RestoreTaskResult.success(decryptedString);
|
||||
} else {
|
||||
return RestoreTaskResult.failure(R.string.backup_toast_import_decryption_failed);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
package org.shadowice.flocke.andotp.Tasks;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import org.shadowice.flocke.andotp.R;
|
||||
import org.shadowice.flocke.andotp.Utilities.Settings;
|
||||
|
||||
public abstract class GenericRestoreTask extends UiBasedBackgroundTask<GenericRestoreTask.RestoreTaskResult> {
|
||||
protected final Context applicationContext;
|
||||
protected final Settings settings;
|
||||
protected Uri uri;
|
||||
|
||||
public GenericRestoreTask(Context context, @Nullable Uri uri) {
|
||||
super(GenericRestoreTask.RestoreTaskResult.failure(R.string.backup_toast_import_failed));
|
||||
|
||||
this.applicationContext = context.getApplicationContext();
|
||||
this.settings = new Settings(applicationContext);
|
||||
|
||||
this.uri = uri;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
protected abstract RestoreTaskResult doInBackground();
|
||||
|
||||
public static class RestoreTaskResult {
|
||||
public final boolean success;
|
||||
public final String payload;
|
||||
public final int messageId;
|
||||
|
||||
public boolean isPGP = false;
|
||||
public Intent decryptIntent = null;
|
||||
public Uri uri = null;
|
||||
|
||||
public RestoreTaskResult(boolean success, String payload, int messageId) {
|
||||
this.success = success;
|
||||
this.payload = payload;
|
||||
this.messageId = messageId;
|
||||
}
|
||||
|
||||
public RestoreTaskResult(boolean success, String payload, int messageId, boolean isPGP, Intent decryptIntent, Uri uri) {
|
||||
this.success = success;
|
||||
this.payload = payload;
|
||||
this.messageId = messageId;
|
||||
this.isPGP = isPGP;
|
||||
this.decryptIntent = decryptIntent;
|
||||
this.uri = uri;
|
||||
}
|
||||
|
||||
public static RestoreTaskResult success(String payload) {
|
||||
return new RestoreTaskResult(true, payload, 0);
|
||||
}
|
||||
|
||||
public static RestoreTaskResult failure(int messageId) {
|
||||
return new RestoreTaskResult(false, null, messageId);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package org.shadowice.flocke.andotp.Tasks;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import org.shadowice.flocke.andotp.Utilities.StorageAccessHelper;
|
||||
|
||||
public class PGPRestoreTask extends GenericRestoreTask {
|
||||
private final Intent decryptIntent;
|
||||
|
||||
public PGPRestoreTask(Context context, Uri uri, Intent decryptIntent) {
|
||||
super(context, uri);
|
||||
this.decryptIntent = decryptIntent;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
protected RestoreTaskResult doInBackground() {
|
||||
String data = StorageAccessHelper.loadFileString(applicationContext, uri);
|
||||
|
||||
return new RestoreTaskResult(true, data, 0, true, decryptIntent, uri);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package org.shadowice.flocke.andotp.Tasks;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import org.shadowice.flocke.andotp.Utilities.StorageAccessHelper;
|
||||
|
||||
public class PlainTextRestoreTask extends GenericRestoreTask {
|
||||
public PlainTextRestoreTask(Context context, Uri uri) {
|
||||
super(context, uri);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
protected RestoreTaskResult doInBackground() {
|
||||
String data = StorageAccessHelper.loadFileString(applicationContext, uri);
|
||||
return RestoreTaskResult.success(data);
|
||||
}
|
||||
}
|
|
@ -55,6 +55,7 @@
|
|||
<string name="backup_toast_import_save_failed">Failed to save restored entries</string>
|
||||
<string name="backup_toast_import_decryption_failed">Decryption of the backup failed</string>
|
||||
<string name="backup_toast_import_no_entries">No entries found in imported data</string>
|
||||
<string name="backup_toast_import_failed">Import from external storage failed</string>
|
||||
<string name="backup_toast_storage_not_accessible">External storage currently not accessible</string>
|
||||
<string name="backup_toast_openpgp_error">OpenPGP Error: %s</string>
|
||||
<string name="backup_toast_openpgp_not_verified">No verified signature detected</string>
|
||||
|
|
Loading…
Reference in a new issue