get rid of consolidate operation
This commit is contained in:
@@ -17,11 +17,14 @@
|
||||
|
||||
package org.sufficientlysecure.keychain;
|
||||
|
||||
|
||||
import java.security.Security;
|
||||
import java.util.HashMap;
|
||||
|
||||
import android.accounts.Account;
|
||||
import android.accounts.AccountManager;
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.drawable.Drawable;
|
||||
@@ -31,19 +34,15 @@ import android.support.annotation.Nullable;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||
import org.sufficientlysecure.keychain.network.TlsCertificatePinning;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainDatabase;
|
||||
import org.sufficientlysecure.keychain.provider.TemporaryFileProvider;
|
||||
import org.sufficientlysecure.keychain.service.ContactSyncAdapterService;
|
||||
import org.sufficientlysecure.keychain.service.KeyserverSyncAdapterService;
|
||||
import org.sufficientlysecure.keychain.ui.ConsolidateDialogActivity;
|
||||
import org.sufficientlysecure.keychain.ui.util.FormattingUtils;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
import org.sufficientlysecure.keychain.util.PRNGFixes;
|
||||
import org.sufficientlysecure.keychain.util.Preferences;
|
||||
import org.sufficientlysecure.keychain.network.TlsCertificatePinning;
|
||||
|
||||
import java.security.Security;
|
||||
import java.util.HashMap;
|
||||
|
||||
|
||||
public class KeychainApplication extends Application {
|
||||
@@ -119,11 +118,6 @@ public class KeychainApplication extends Application {
|
||||
TlsCertificatePinning.addPinnedCertificate("api.keybase.io", getAssets(), "api.keybase.io.CA.cer");
|
||||
|
||||
TemporaryFileProvider.cleanUp(this);
|
||||
|
||||
if (!checkConsolidateRecovery()) {
|
||||
// force DB upgrade, https://github.com/open-keychain/open-keychain/issues/1334
|
||||
new KeychainDatabase(this).getReadableDatabase().close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -164,21 +158,6 @@ public class KeychainApplication extends Application {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Restart consolidate process if it has been interrupted before
|
||||
*/
|
||||
public boolean checkConsolidateRecovery() {
|
||||
if (Preferences.getPreferences(this).getCachedConsolidate()) {
|
||||
Intent consolidateIntent = new Intent(this, ConsolidateDialogActivity.class);
|
||||
consolidateIntent.putExtra(ConsolidateDialogActivity.EXTRA_CONSOLIDATE_RECOVERY, true);
|
||||
consolidateIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
startActivity(consolidateIntent);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static void brandGlowEffect(Context context, int brandColor) {
|
||||
// no hack on Android 5
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Dominik Schürmann <dominik@dominikschuermann.de>
|
||||
* Copyright (C) 2015 Vincent Breitmoser <v.breitmoser@mugenguild.com>
|
||||
* Copyright (C) 2015 Adithya Abraham Philip <adithyaphilip@gmail.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.sufficientlysecure.keychain.operations;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import org.sufficientlysecure.keychain.operations.results.ConsolidateResult;
|
||||
import org.sufficientlysecure.keychain.pgp.Progressable;
|
||||
import org.sufficientlysecure.keychain.provider.KeyWritableRepository;
|
||||
import org.sufficientlysecure.keychain.service.ConsolidateInputParcel;
|
||||
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
|
||||
|
||||
public class ConsolidateOperation extends BaseReadWriteOperation<ConsolidateInputParcel> {
|
||||
|
||||
public ConsolidateOperation(Context context, KeyWritableRepository databaseInteractor, Progressable
|
||||
progressable) {
|
||||
super(context, databaseInteractor, progressable);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ConsolidateResult execute(ConsolidateInputParcel consolidateInputParcel,
|
||||
CryptoInputParcel cryptoInputParcel) {
|
||||
if (consolidateInputParcel.isStartFromRecovery()) {
|
||||
return mKeyWritableRepository.consolidateDatabaseStep2(mProgressable);
|
||||
} else {
|
||||
return mKeyWritableRepository.consolidateDatabaseStep1(mProgressable);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -598,32 +598,6 @@ public abstract class OperationResult implements Parcelable {
|
||||
MSG_MF_UNLOCK_ERROR (LogLevel.ERROR, R.string.msg_mf_unlock_error),
|
||||
MSG_MF_UNLOCK (LogLevel.DEBUG, R.string.msg_mf_unlock),
|
||||
|
||||
// consolidate
|
||||
MSG_CON_CRITICAL_IN (LogLevel.DEBUG, R.string.msg_con_critical_in),
|
||||
MSG_CON_CRITICAL_OUT (LogLevel.DEBUG, R.string.msg_con_critical_out),
|
||||
MSG_CON_DB_CLEAR (LogLevel.DEBUG, R.string.msg_con_db_clear),
|
||||
MSG_CON_DELETE_PUBLIC (LogLevel.DEBUG, R.string.msg_con_delete_public),
|
||||
MSG_CON_DELETE_SECRET (LogLevel.DEBUG, R.string.msg_con_delete_secret),
|
||||
MSG_CON_ERROR_BAD_STATE (LogLevel.ERROR, R.string.msg_con_error_bad_state),
|
||||
MSG_CON_ERROR_CONCURRENT(LogLevel.ERROR, R.string.msg_con_error_concurrent),
|
||||
MSG_CON_ERROR_DB (LogLevel.ERROR, R.string.msg_con_error_db),
|
||||
MSG_CON_ERROR_IO_PUBLIC (LogLevel.ERROR, R.string.msg_con_error_io_public),
|
||||
MSG_CON_ERROR_IO_SECRET (LogLevel.ERROR, R.string.msg_con_error_io_secret),
|
||||
MSG_CON_ERROR_PUBLIC (LogLevel.ERROR, R.string.msg_con_error_public),
|
||||
MSG_CON_ERROR_SECRET (LogLevel.ERROR, R.string.msg_con_error_secret),
|
||||
MSG_CON_RECOVER (LogLevel.DEBUG, R.string.msg_con_recover),
|
||||
MSG_CON_RECURSIVE (LogLevel.OK, R.string.msg_con_recursive),
|
||||
MSG_CON_REIMPORT_PUBLIC (LogLevel.DEBUG, R.plurals.msg_con_reimport_public),
|
||||
MSG_CON_REIMPORT_PUBLIC_SKIP (LogLevel.DEBUG, R.string.msg_con_reimport_public_skip),
|
||||
MSG_CON_REIMPORT_SECRET (LogLevel.DEBUG, R.plurals.msg_con_reimport_secret),
|
||||
MSG_CON_REIMPORT_SECRET_SKIP (LogLevel.DEBUG, R.string.msg_con_reimport_secret_skip),
|
||||
MSG_CON (LogLevel.START, R.string.msg_con),
|
||||
MSG_CON_SAVE_PUBLIC (LogLevel.DEBUG, R.string.msg_con_save_public),
|
||||
MSG_CON_SAVE_SECRET (LogLevel.DEBUG, R.string.msg_con_save_secret),
|
||||
MSG_CON_SUCCESS (LogLevel.OK, R.string.msg_con_success),
|
||||
MSG_CON_WARN_DELETE_PUBLIC (LogLevel.WARN, R.string.msg_con_warn_delete_public),
|
||||
MSG_CON_WARN_DELETE_SECRET (LogLevel.WARN, R.string.msg_con_warn_delete_secret),
|
||||
|
||||
// edit key (higher level operation than modify)
|
||||
MSG_ED (LogLevel.START, R.string.msg_ed),
|
||||
MSG_ED_CACHING_NEW (LogLevel.DEBUG, R.string.msg_ed_caching_new),
|
||||
|
||||
@@ -25,7 +25,6 @@ import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import android.content.ContentProviderOperation;
|
||||
@@ -41,11 +40,6 @@ import android.support.v4.util.LongSparseArray;
|
||||
|
||||
import org.openintents.openpgp.util.OpenPgpUtils;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing;
|
||||
import org.sufficientlysecure.keychain.operations.ImportOperation;
|
||||
import org.sufficientlysecure.keychain.operations.results.ConsolidateResult;
|
||||
import org.sufficientlysecure.keychain.operations.results.ImportKeyResult;
|
||||
import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType;
|
||||
import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog;
|
||||
import org.sufficientlysecure.keychain.operations.results.SaveKeyringResult;
|
||||
@@ -73,11 +67,7 @@ import org.sufficientlysecure.keychain.provider.KeychainContract.UpdatedKeys;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.UserPackets;
|
||||
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
|
||||
import org.sufficientlysecure.keychain.util.IterableIterator;
|
||||
import org.sufficientlysecure.keychain.util.IteratorWithSize;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
import org.sufficientlysecure.keychain.util.ParcelableFileCache;
|
||||
import org.sufficientlysecure.keychain.util.Preferences;
|
||||
import org.sufficientlysecure.keychain.util.ProgressFixedScaler;
|
||||
import org.sufficientlysecure.keychain.util.Utf8Util;
|
||||
|
||||
/**
|
||||
@@ -1070,335 +1060,6 @@ public class KeyWritableRepository extends KeyRepository {
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public ConsolidateResult consolidateDatabaseStep1(Progressable progress) {
|
||||
|
||||
OperationLog log = new OperationLog();
|
||||
int indent = 0;
|
||||
|
||||
// 1a. fetch all secret keyrings into a cache file
|
||||
log.add(LogType.MSG_CON, indent);
|
||||
indent += 1;
|
||||
|
||||
if (mConsolidateCritical) {
|
||||
log.add(LogType.MSG_CON_RECURSIVE, indent);
|
||||
return new ConsolidateResult(ConsolidateResult.RESULT_OK, log);
|
||||
}
|
||||
|
||||
progress.setProgress(R.string.progress_con_saving, 0, 100);
|
||||
|
||||
// The consolidate operation can never be cancelled!
|
||||
progress.setPreventCancel();
|
||||
|
||||
try {
|
||||
|
||||
log.add(LogType.MSG_CON_SAVE_SECRET, indent);
|
||||
indent += 1;
|
||||
|
||||
final Cursor cursor = mContentResolver.query(KeyRingData.buildSecretKeyRingUri(),
|
||||
new String[]{KeyRingData.KEY_RING_DATA}, null, null, null);
|
||||
|
||||
if (cursor == null) {
|
||||
log.add(LogType.MSG_CON_ERROR_DB, indent);
|
||||
return new ConsolidateResult(ConsolidateResult.RESULT_ERROR, log);
|
||||
}
|
||||
|
||||
// No keys existing might be a legitimate option, we write an empty file in that case
|
||||
cursor.moveToFirst();
|
||||
ParcelableFileCache<ParcelableKeyRing> cache =
|
||||
new ParcelableFileCache<>(mContext, "consolidate_secret.pcl");
|
||||
cache.writeCache(cursor.getCount(), new Iterator<ParcelableKeyRing>() {
|
||||
ParcelableKeyRing ring;
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
if (ring != null) {
|
||||
return true;
|
||||
}
|
||||
if (cursor.isAfterLast()) {
|
||||
return false;
|
||||
}
|
||||
ring = ParcelableKeyRing.createFromEncodedBytes(cursor.getBlob(0));
|
||||
cursor.moveToNext();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ParcelableKeyRing next() {
|
||||
try {
|
||||
return ring;
|
||||
} finally {
|
||||
ring = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
});
|
||||
cursor.close();
|
||||
|
||||
} catch (IOException e) {
|
||||
Log.e(Constants.TAG, "error saving secret", e);
|
||||
log.add(LogType.MSG_CON_ERROR_IO_SECRET, indent);
|
||||
return new ConsolidateResult(ConsolidateResult.RESULT_ERROR, log);
|
||||
} finally {
|
||||
indent -= 1;
|
||||
}
|
||||
|
||||
progress.setProgress(R.string.progress_con_saving, 3, 100);
|
||||
|
||||
// 1b. fetch all public keyrings into a cache file
|
||||
try {
|
||||
|
||||
log.add(LogType.MSG_CON_SAVE_PUBLIC, indent);
|
||||
indent += 1;
|
||||
|
||||
final Cursor cursor = mContentResolver.query(
|
||||
KeyRingData.buildPublicKeyRingUri(),
|
||||
new String[]{KeyRingData.MASTER_KEY_ID, KeyRingData.KEY_RING_DATA}, null, null, null);
|
||||
|
||||
if (cursor == null) {
|
||||
log.add(LogType.MSG_CON_ERROR_DB, indent);
|
||||
return new ConsolidateResult(ConsolidateResult.RESULT_ERROR, log);
|
||||
}
|
||||
|
||||
// No keys existing might be a legitimate option, we write an empty file in that case
|
||||
cursor.moveToFirst();
|
||||
ParcelableFileCache<ParcelableKeyRing> cache =
|
||||
new ParcelableFileCache<>(mContext, "consolidate_public.pcl");
|
||||
cache.writeCache(cursor.getCount(), new Iterator<ParcelableKeyRing>() {
|
||||
ParcelableKeyRing ring;
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
if (ring != null) {
|
||||
return true;
|
||||
}
|
||||
if (cursor.isAfterLast()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
long masterKeyId = cursor.getLong(0);
|
||||
byte[] keyBytes = cursor.getBlob(1);
|
||||
if (keyBytes == null) {
|
||||
try {
|
||||
keyBytes = mLocalPublicKeyStorage.readPublicKey(masterKeyId);
|
||||
} catch (IOException e) {
|
||||
Log.e(Constants.TAG, "Failed reading key data!", e);
|
||||
}
|
||||
}
|
||||
if (keyBytes == null) {
|
||||
throw new IllegalStateException("Lost a key! This should never happen!");
|
||||
}
|
||||
|
||||
ring = ParcelableKeyRing.createFromEncodedBytes(keyBytes);
|
||||
cursor.moveToNext();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ParcelableKeyRing next() {
|
||||
try {
|
||||
return ring;
|
||||
} finally {
|
||||
ring = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
});
|
||||
cursor.close();
|
||||
|
||||
} catch (IOException e) {
|
||||
Log.e(Constants.TAG, "error saving public", e);
|
||||
log.add(LogType.MSG_CON_ERROR_IO_PUBLIC, indent);
|
||||
return new ConsolidateResult(ConsolidateResult.RESULT_ERROR, log);
|
||||
} finally {
|
||||
indent -= 1;
|
||||
}
|
||||
|
||||
log.add(LogType.MSG_CON_CRITICAL_IN, indent);
|
||||
Preferences.getPreferences(mContext).setCachedConsolidate(true);
|
||||
|
||||
return consolidateDatabaseStep2(log, indent, progress, false);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public ConsolidateResult consolidateDatabaseStep2(Progressable progress) {
|
||||
return consolidateDatabaseStep2(new OperationLog(), 0, progress, true);
|
||||
}
|
||||
|
||||
private static boolean mConsolidateCritical = false;
|
||||
|
||||
@NonNull
|
||||
private ConsolidateResult consolidateDatabaseStep2(
|
||||
OperationLog log, int indent, Progressable progress, boolean recovery) {
|
||||
|
||||
synchronized (KeyWritableRepository.class) {
|
||||
if (mConsolidateCritical) {
|
||||
log.add(LogType.MSG_CON_ERROR_CONCURRENT, indent);
|
||||
return new ConsolidateResult(ConsolidateResult.RESULT_ERROR, log);
|
||||
}
|
||||
mConsolidateCritical = true;
|
||||
}
|
||||
|
||||
try {
|
||||
Preferences prefs = Preferences.getPreferences(mContext);
|
||||
|
||||
if (recovery) {
|
||||
log.add(LogType.MSG_CON_RECOVER, indent);
|
||||
indent += 1;
|
||||
}
|
||||
|
||||
if (!prefs.getCachedConsolidate()) {
|
||||
log.add(LogType.MSG_CON_ERROR_BAD_STATE, indent);
|
||||
return new ConsolidateResult(ConsolidateResult.RESULT_ERROR, log);
|
||||
}
|
||||
|
||||
// 2. wipe database (IT'S DANGEROUS)
|
||||
|
||||
// first, backup our list of updated key times
|
||||
ArrayList<ContentValues> updatedKeysValues = new ArrayList<>();
|
||||
final int INDEX_MASTER_KEY_ID = 0;
|
||||
final int INDEX_LAST_UPDATED = 1;
|
||||
final int INDEX_SEEN_ON_KEYSERVERS = 2;
|
||||
Cursor lastUpdatedCursor = mContentResolver.query(
|
||||
UpdatedKeys.CONTENT_URI,
|
||||
new String[]{
|
||||
UpdatedKeys.MASTER_KEY_ID,
|
||||
UpdatedKeys.LAST_UPDATED,
|
||||
UpdatedKeys.SEEN_ON_KEYSERVERS
|
||||
},
|
||||
null, null, null);
|
||||
while (lastUpdatedCursor.moveToNext()) {
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(UpdatedKeys.MASTER_KEY_ID,
|
||||
lastUpdatedCursor.getLong(INDEX_MASTER_KEY_ID));
|
||||
if (!lastUpdatedCursor.isNull(INDEX_LAST_UPDATED)) {
|
||||
values.put(UpdatedKeys.LAST_UPDATED, lastUpdatedCursor.getLong(INDEX_LAST_UPDATED));
|
||||
} else {
|
||||
values.putNull(UpdatedKeys.LAST_UPDATED);
|
||||
}
|
||||
if (!lastUpdatedCursor.isNull(INDEX_SEEN_ON_KEYSERVERS)) {
|
||||
values.put(UpdatedKeys.SEEN_ON_KEYSERVERS, lastUpdatedCursor.getInt(INDEX_SEEN_ON_KEYSERVERS));
|
||||
} else {
|
||||
values.putNull(UpdatedKeys.SEEN_ON_KEYSERVERS);
|
||||
}
|
||||
updatedKeysValues.add(values);
|
||||
}
|
||||
lastUpdatedCursor.close();
|
||||
|
||||
log.add(LogType.MSG_CON_DB_CLEAR, indent);
|
||||
mContentResolver.delete(KeyRings.buildUnifiedKeyRingsUri(), null, null);
|
||||
|
||||
ParcelableFileCache<ParcelableKeyRing> cacheSecret, cachePublic;
|
||||
|
||||
// Set flag that we have a cached consolidation here
|
||||
try {
|
||||
cacheSecret = new ParcelableFileCache<>(mContext, "consolidate_secret.pcl");
|
||||
IteratorWithSize<ParcelableKeyRing> itSecrets = cacheSecret.readCache(false);
|
||||
int numSecrets = itSecrets.getSize();
|
||||
|
||||
log.add(LogType.MSG_CON_REIMPORT_SECRET, indent, numSecrets);
|
||||
indent += 1;
|
||||
|
||||
// 3. Re-Import secret keyrings from cache
|
||||
if (numSecrets > 0) {
|
||||
|
||||
ImportKeyResult result = new ImportOperation(mContext, this,
|
||||
new ProgressFixedScaler(progress, 10, 25, 100, R.string.progress_con_reimport))
|
||||
.serialKeyRingImport(itSecrets, numSecrets, null, null, false);
|
||||
log.add(result, indent);
|
||||
} else {
|
||||
log.add(LogType.MSG_CON_REIMPORT_SECRET_SKIP, indent);
|
||||
}
|
||||
|
||||
} catch (IOException e) {
|
||||
Log.e(Constants.TAG, "error importing secret", e);
|
||||
log.add(LogType.MSG_CON_ERROR_SECRET, indent);
|
||||
return new ConsolidateResult(ConsolidateResult.RESULT_ERROR, log);
|
||||
} finally {
|
||||
indent -= 1;
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
cachePublic = new ParcelableFileCache<>(mContext, "consolidate_public.pcl");
|
||||
IteratorWithSize<ParcelableKeyRing> itPublics = cachePublic.readCache();
|
||||
int numPublics = itPublics.getSize();
|
||||
|
||||
log.add(LogType.MSG_CON_REIMPORT_PUBLIC, indent, numPublics);
|
||||
indent += 1;
|
||||
|
||||
// 4. Re-Import public keyrings from cache
|
||||
if (numPublics > 0) {
|
||||
|
||||
ImportKeyResult result = new ImportOperation(mContext, this,
|
||||
new ProgressFixedScaler(progress, 25, 99, 100, R.string.progress_con_reimport))
|
||||
.serialKeyRingImport(itPublics, numPublics, null, null, false);
|
||||
log.add(result, indent);
|
||||
// re-insert our backed up list of updated key times
|
||||
// TODO: can this cause issues in case a public key re-import failed?
|
||||
mContentResolver.bulkInsert(UpdatedKeys.CONTENT_URI,
|
||||
updatedKeysValues.toArray(new ContentValues[updatedKeysValues.size()]));
|
||||
} else {
|
||||
log.add(LogType.MSG_CON_REIMPORT_PUBLIC_SKIP, indent);
|
||||
}
|
||||
|
||||
} catch (IOException e) {
|
||||
Log.e(Constants.TAG, "error importing public", e);
|
||||
log.add(LogType.MSG_CON_ERROR_PUBLIC, indent);
|
||||
return new ConsolidateResult(ConsolidateResult.RESULT_ERROR, log);
|
||||
} finally {
|
||||
indent -= 1;
|
||||
}
|
||||
|
||||
log.add(LogType.MSG_CON_CRITICAL_OUT, indent);
|
||||
Preferences.getPreferences(mContext).setCachedConsolidate(false);
|
||||
|
||||
// 5. Delete caches
|
||||
try {
|
||||
log.add(LogType.MSG_CON_DELETE_SECRET, indent);
|
||||
indent += 1;
|
||||
cacheSecret.delete();
|
||||
} catch (IOException e) {
|
||||
// doesn't /really/ matter
|
||||
Log.e(Constants.TAG, "IOException during delete of secret cache", e);
|
||||
log.add(LogType.MSG_CON_WARN_DELETE_SECRET, indent);
|
||||
} finally {
|
||||
indent -= 1;
|
||||
}
|
||||
|
||||
try {
|
||||
log.add(LogType.MSG_CON_DELETE_PUBLIC, indent);
|
||||
indent += 1;
|
||||
cachePublic.delete();
|
||||
} catch (IOException e) {
|
||||
// doesn't /really/ matter
|
||||
Log.e(Constants.TAG, "IOException during deletion of public cache", e);
|
||||
log.add(LogType.MSG_CON_WARN_DELETE_PUBLIC, indent);
|
||||
} finally {
|
||||
indent -= 1;
|
||||
}
|
||||
|
||||
progress.setProgress(100, 100);
|
||||
log.add(LogType.MSG_CON_SUCCESS, indent);
|
||||
|
||||
return new ConsolidateResult(ConsolidateResult.RESULT_OK, log);
|
||||
|
||||
} finally {
|
||||
mConsolidateCritical = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Build ContentProviderOperation to add PGPPublicKey to database corresponding to a keyRing
|
||||
*/
|
||||
|
||||
@@ -25,7 +25,6 @@ import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteException;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
@@ -42,7 +41,6 @@ import org.sufficientlysecure.keychain.provider.KeychainContract.KeysColumns;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.OverriddenWarnings;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.UpdatedKeysColumns;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.UserPacketsColumns;
|
||||
import org.sufficientlysecure.keychain.ui.ConsolidateDialogActivity;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
|
||||
/**
|
||||
@@ -406,19 +404,7 @@ public class KeychainDatabase extends SQLiteOpenHelper {
|
||||
+ "PRIMARY KEY(master_key_id, signer_key_id), "
|
||||
+ "FOREIGN KEY(master_key_id) REFERENCES keyrings_public(master_key_id) ON DELETE CASCADE"
|
||||
+ ")");
|
||||
|
||||
if (oldVersion == 18 || oldVersion == 19 || oldVersion == 20 || oldVersion == 21 || oldVersion == 22 ||
|
||||
oldVersion == 23) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: don't depend on consolidate! make migrations inline!
|
||||
// consolidate after upgrade
|
||||
Intent consolidateIntent = new Intent(mContext.getApplicationContext(), ConsolidateDialogActivity.class);
|
||||
consolidateIntent.putExtra(ConsolidateDialogActivity.EXTRA_CONSOLIDATE_RECOVERY, false);
|
||||
consolidateIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
mContext.getApplicationContext().startActivity(consolidateIntent);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Dominik Schürmann <dominik@dominikschuermann.de>
|
||||
* Copyright (C) 2015 Vincent Breitmoser <v.breitmoser@mugenguild.com>
|
||||
* Copyright (C) 2015 Adithya Abraham Philip <adithyaphilip@gmail.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.sufficientlysecure.keychain.service;
|
||||
|
||||
|
||||
import android.os.Parcelable;
|
||||
|
||||
import com.google.auto.value.AutoValue;
|
||||
|
||||
|
||||
@AutoValue
|
||||
public abstract class ConsolidateInputParcel implements Parcelable {
|
||||
public abstract boolean isStartFromRecovery();
|
||||
|
||||
public static ConsolidateInputParcel createConsolidateInputParcel(boolean consolidateRecovery) {
|
||||
return new AutoValue_ConsolidateInputParcel(consolidateRecovery);
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,9 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.service;
|
||||
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import android.app.Service;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
@@ -28,24 +31,23 @@ import android.os.Parcelable;
|
||||
import android.os.RemoteException;
|
||||
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.operations.BackupOperation;
|
||||
import org.sufficientlysecure.keychain.operations.BaseOperation;
|
||||
import org.sufficientlysecure.keychain.operations.BenchmarkOperation;
|
||||
import org.sufficientlysecure.keychain.operations.CertifyOperation;
|
||||
import org.sufficientlysecure.keychain.operations.ConsolidateOperation;
|
||||
import org.sufficientlysecure.keychain.operations.ChangeUnlockOperation;
|
||||
import org.sufficientlysecure.keychain.operations.DeleteOperation;
|
||||
import org.sufficientlysecure.keychain.operations.EditKeyOperation;
|
||||
import org.sufficientlysecure.keychain.operations.BackupOperation;
|
||||
import org.sufficientlysecure.keychain.operations.ImportOperation;
|
||||
import org.sufficientlysecure.keychain.operations.KeybaseVerificationOperation;
|
||||
import org.sufficientlysecure.keychain.operations.InputDataOperation;
|
||||
import org.sufficientlysecure.keychain.operations.ChangeUnlockOperation;
|
||||
import org.sufficientlysecure.keychain.operations.KeybaseVerificationOperation;
|
||||
import org.sufficientlysecure.keychain.operations.PromoteKeyOperation;
|
||||
import org.sufficientlysecure.keychain.operations.RevokeOperation;
|
||||
import org.sufficientlysecure.keychain.operations.SignEncryptOperation;
|
||||
import org.sufficientlysecure.keychain.operations.UploadOperation;
|
||||
import org.sufficientlysecure.keychain.operations.results.OperationResult;
|
||||
import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyOperation;
|
||||
import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyInputParcel;
|
||||
import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyOperation;
|
||||
import org.sufficientlysecure.keychain.pgp.Progressable;
|
||||
import org.sufficientlysecure.keychain.pgp.SignEncryptParcel;
|
||||
import org.sufficientlysecure.keychain.provider.KeyWritableRepository;
|
||||
@@ -53,8 +55,6 @@ import org.sufficientlysecure.keychain.service.ServiceProgressHandler.MessageSta
|
||||
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/**
|
||||
* This Service contains all important long lasting operations for OpenKeychain. It receives Intents with
|
||||
* data from the activities or other apps, executes them, and stops itself after doing them.
|
||||
@@ -135,8 +135,6 @@ public class KeychainService extends Service implements Progressable {
|
||||
op = new BackupOperation(outerThis, databaseInteractor, outerThis, mActionCanceled);
|
||||
} else if (inputParcel instanceof UploadKeyringParcel) {
|
||||
op = new UploadOperation(outerThis, databaseInteractor, outerThis, mActionCanceled);
|
||||
} else if (inputParcel instanceof ConsolidateInputParcel) {
|
||||
op = new ConsolidateOperation(outerThis, databaseInteractor, outerThis);
|
||||
} else if (inputParcel instanceof KeybaseVerificationParcel) {
|
||||
op = new KeybaseVerificationOperation(outerThis, databaseInteractor, outerThis);
|
||||
} else if (inputParcel instanceof InputDataParcel) {
|
||||
|
||||
@@ -1,94 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.sufficientlysecure.keychain.ui;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.operations.results.ConsolidateResult;
|
||||
import org.sufficientlysecure.keychain.service.ConsolidateInputParcel;
|
||||
import org.sufficientlysecure.keychain.ui.base.CryptoOperationHelper;
|
||||
|
||||
/**
|
||||
* We can not directly create a dialog on the application context.
|
||||
* This activity encapsulates a DialogFragment to emulate a dialog.
|
||||
*/
|
||||
public class ConsolidateDialogActivity extends FragmentActivity
|
||||
implements CryptoOperationHelper.Callback<ConsolidateInputParcel, ConsolidateResult> {
|
||||
|
||||
public static final String EXTRA_CONSOLIDATE_RECOVERY = "consolidate_recovery";
|
||||
|
||||
private CryptoOperationHelper<ConsolidateInputParcel, ConsolidateResult> mConsolidateOpHelper;
|
||||
private boolean mRecovery;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
// this activity itself has no content view (see manifest)
|
||||
|
||||
boolean recovery = getIntent().getBooleanExtra(EXTRA_CONSOLIDATE_RECOVERY, false);
|
||||
|
||||
consolidateRecovery(recovery);
|
||||
}
|
||||
|
||||
private void consolidateRecovery(boolean recovery) {
|
||||
|
||||
mRecovery = recovery;
|
||||
|
||||
mConsolidateOpHelper = new CryptoOperationHelper<>(1, this, this, R.string.progress_importing);
|
||||
mConsolidateOpHelper.cryptoOperation();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
if (mConsolidateOpHelper != null) {
|
||||
mConsolidateOpHelper.handleActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConsolidateInputParcel createOperationInput() {
|
||||
return ConsolidateInputParcel.createConsolidateInputParcel(mRecovery);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCryptoOperationSuccess(ConsolidateResult result) {
|
||||
// don't care about result (for now?)
|
||||
ConsolidateDialogActivity.this.finish();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCryptoOperationCancelled() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCryptoOperationError(ConsolidateResult result) {
|
||||
// don't care about result (for now?)
|
||||
ConsolidateDialogActivity.this.finish();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCryptoSetProgress(String msg, int progress, int max) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,10 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.ui;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
@@ -47,34 +51,28 @@ import com.futuremind.recyclerviewfastscroll.FastScroller;
|
||||
import com.getbase.floatingactionbutton.FloatingActionButton;
|
||||
import com.getbase.floatingactionbutton.FloatingActionsMenu;
|
||||
import com.tonicartos.superslim.LayoutManager;
|
||||
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.keyimport.HkpKeyserverAddress;
|
||||
import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing;
|
||||
import org.sufficientlysecure.keychain.operations.results.BenchmarkResult;
|
||||
import org.sufficientlysecure.keychain.operations.results.ConsolidateResult;
|
||||
import org.sufficientlysecure.keychain.operations.results.ImportKeyResult;
|
||||
import org.sufficientlysecure.keychain.operations.results.OperationResult;
|
||||
import org.sufficientlysecure.keychain.provider.KeyRepository;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainDatabase;
|
||||
import org.sufficientlysecure.keychain.provider.KeyRepository;
|
||||
import org.sufficientlysecure.keychain.service.BenchmarkInputParcel;
|
||||
import org.sufficientlysecure.keychain.service.ConsolidateInputParcel;
|
||||
import org.sufficientlysecure.keychain.service.ImportKeyringParcel;
|
||||
import org.sufficientlysecure.keychain.ui.adapter.KeySectionedListAdapter;
|
||||
import org.sufficientlysecure.keychain.ui.base.CryptoOperationHelper;
|
||||
import org.sufficientlysecure.keychain.ui.base.RecyclerFragment;
|
||||
import org.sufficientlysecure.keychain.ui.keyview.ViewKeyActivity;
|
||||
import org.sufficientlysecure.keychain.ui.util.Notify;
|
||||
import org.sufficientlysecure.keychain.ui.base.RecyclerFragment;
|
||||
import org.sufficientlysecure.keychain.util.FabContainer;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
import org.sufficientlysecure.keychain.util.Preferences;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class KeyListFragment extends RecyclerFragment<KeySectionedListAdapter>
|
||||
implements SearchView.OnQueryTextListener,
|
||||
LoaderManager.LoaderCallbacks<Cursor>, FabContainer {
|
||||
@@ -97,9 +95,6 @@ public class KeyListFragment extends RecyclerFragment<KeySectionedListAdapter>
|
||||
private HkpKeyserverAddress mKeyserver;
|
||||
private CryptoOperationHelper<ImportKeyringParcel, ImportKeyResult> mImportOpHelper;
|
||||
|
||||
// for ConsolidateOperation
|
||||
private CryptoOperationHelper<ConsolidateInputParcel, ConsolidateResult> mConsolidateOpHelper;
|
||||
|
||||
// Callbacks related to listview and menu events
|
||||
private final ActionMode.Callback mActionCallback
|
||||
= new ActionMode.Callback() {
|
||||
@@ -334,7 +329,6 @@ public class KeyListFragment extends RecyclerFragment<KeySectionedListAdapter>
|
||||
inflater.inflate(R.menu.key_list, menu);
|
||||
|
||||
if (Constants.DEBUG) {
|
||||
menu.findItem(R.id.menu_key_list_debug_cons).setVisible(true);
|
||||
menu.findItem(R.id.menu_key_list_debug_bench).setVisible(true);
|
||||
menu.findItem(R.id.menu_key_list_debug_read).setVisible(true);
|
||||
menu.findItem(R.id.menu_key_list_debug_write).setVisible(true);
|
||||
@@ -413,10 +407,6 @@ public class KeyListFragment extends RecyclerFragment<KeySectionedListAdapter>
|
||||
getActivity().finish();
|
||||
return true;
|
||||
}
|
||||
case R.id.menu_key_list_debug_cons: {
|
||||
consolidate();
|
||||
return true;
|
||||
}
|
||||
case R.id.menu_key_list_debug_bench: {
|
||||
benchmark();
|
||||
return true;
|
||||
@@ -547,39 +537,6 @@ public class KeyListFragment extends RecyclerFragment<KeySectionedListAdapter>
|
||||
mImportOpHelper.cryptoOperation();
|
||||
}
|
||||
|
||||
private void consolidate() {
|
||||
CryptoOperationHelper.Callback<ConsolidateInputParcel, ConsolidateResult> callback
|
||||
= new CryptoOperationHelper.Callback<ConsolidateInputParcel, ConsolidateResult>() {
|
||||
|
||||
@Override
|
||||
public ConsolidateInputParcel createOperationInput() {
|
||||
return ConsolidateInputParcel.createConsolidateInputParcel(false); // we want to perform a full consolidate
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCryptoOperationSuccess(ConsolidateResult result) {
|
||||
result.createNotify(getActivity()).show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCryptoOperationCancelled() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCryptoOperationError(ConsolidateResult result) {
|
||||
result.createNotify(getActivity()).show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCryptoSetProgress(String msg, int progress, int max) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
mConsolidateOpHelper = new CryptoOperationHelper<>(2, this, callback, R.string.progress_importing);
|
||||
mConsolidateOpHelper.cryptoOperation();
|
||||
}
|
||||
|
||||
private void benchmark() {
|
||||
CryptoOperationHelper.Callback<BenchmarkInputParcel, BenchmarkResult> callback
|
||||
= new CryptoOperationHelper.Callback<BenchmarkInputParcel, BenchmarkResult>() {
|
||||
@@ -619,10 +576,6 @@ public class KeyListFragment extends RecyclerFragment<KeySectionedListAdapter>
|
||||
mImportOpHelper.handleActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
|
||||
if (mConsolidateOpHelper != null) {
|
||||
mConsolidateOpHelper.handleActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
|
||||
switch (requestCode) {
|
||||
case REQUEST_DELETE: {
|
||||
if (mActionMode != null) {
|
||||
|
||||
@@ -52,10 +52,6 @@ public class ParcelableFileCache<E extends Parcelable> {
|
||||
mFilename = filename;
|
||||
}
|
||||
|
||||
public static boolean cacheFileExists(Context context, String filename) {
|
||||
return new File(context.getCacheDir(), filename).exists();
|
||||
}
|
||||
|
||||
public void writeCache(int numEntries, Iterator<E> it) throws IOException {
|
||||
DataOutputStream oos = getOutputStream();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user