wrapped-key-ring: move key data around in ParcelableKeyRing instead of ImportKeysListEntry

This commit is contained in:
Vincent Breitmoser
2014-05-30 17:11:54 +02:00
parent ed8b62c32b
commit e27048fe73
9 changed files with 117 additions and 181 deletions

View File

@@ -21,13 +21,10 @@ import android.content.Context;
import android.os.Parcel; import android.os.Parcel;
import android.os.Parcelable; import android.os.Parcelable;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
import org.sufficientlysecure.keychain.pgp.UncachedKeyRing; import org.sufficientlysecure.keychain.pgp.UncachedKeyRing;
import org.sufficientlysecure.keychain.pgp.UncachedPublicKey; import org.sufficientlysecure.keychain.pgp.UncachedPublicKey;
import org.sufficientlysecure.keychain.util.Log;
import java.io.IOException;
import java.io.Serializable; import java.io.Serializable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date; import java.util.Date;
@@ -50,8 +47,6 @@ public class ImportKeysListEntry implements Serializable, Parcelable {
private boolean mSelected; private boolean mSelected;
private byte[] mBytes = new byte[]{};
public int describeContents() { public int describeContents() {
return 0; return 0;
} }
@@ -69,8 +64,6 @@ public class ImportKeysListEntry implements Serializable, Parcelable {
dest.writeString(algorithm); dest.writeString(algorithm);
dest.writeByte((byte) (secretKey ? 1 : 0)); dest.writeByte((byte) (secretKey ? 1 : 0));
dest.writeByte((byte) (mSelected ? 1 : 0)); dest.writeByte((byte) (mSelected ? 1 : 0));
dest.writeInt(mBytes.length);
dest.writeByteArray(mBytes);
dest.writeString(mExtraData); dest.writeString(mExtraData);
} }
@@ -89,8 +82,6 @@ public class ImportKeysListEntry implements Serializable, Parcelable {
vr.algorithm = source.readString(); vr.algorithm = source.readString();
vr.secretKey = source.readByte() == 1; vr.secretKey = source.readByte() == 1;
vr.mSelected = source.readByte() == 1; vr.mSelected = source.readByte() == 1;
vr.mBytes = new byte[source.readInt()];
source.readByteArray(vr.mBytes);
vr.mExtraData = source.readString(); vr.mExtraData = source.readString();
return vr; return vr;
@@ -105,14 +96,6 @@ public class ImportKeysListEntry implements Serializable, Parcelable {
return keyIdHex; return keyIdHex;
} }
public byte[] getBytes() {
return mBytes;
}
public void setBytes(byte[] bytes) {
this.mBytes = bytes;
}
public boolean isSelected() { public boolean isSelected() {
return mSelected; return mSelected;
} }
@@ -229,13 +212,6 @@ public class ImportKeysListEntry implements Serializable, Parcelable {
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public ImportKeysListEntry(Context context, UncachedKeyRing ring) { public ImportKeysListEntry(Context context, UncachedKeyRing ring) {
// save actual key object into entry, used to import it later
try {
this.mBytes = ring.getEncoded();
} catch (IOException e) {
Log.e(Constants.TAG, "IOException on pgpKeyRing.getEncoded()", e);
}
// selected is default // selected is default
this.mSelected = true; this.mSelected = true;

View File

@@ -0,0 +1,51 @@
package org.sufficientlysecure.keychain.keyimport;
import android.os.Parcel;
import android.os.Parcelable;
import org.sufficientlysecure.keychain.pgp.UncachedKeyRing;
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
import java.io.IOException;
/** This is a trivial wrapper around UncachedKeyRing which implements Parcelable. It exists
* for the sole purpose of keeping spongycastle and android imports in separate packages.
*/
public class ParcelableKeyRing implements Parcelable {
final byte[] mBytes;
final String mExpectedFingerprint;
public ParcelableKeyRing(byte[] bytes) {
mBytes = bytes;
mExpectedFingerprint = null;
}
public ParcelableKeyRing(byte[] bytes, String expectedFingerprint) {
mBytes = bytes;
mExpectedFingerprint = expectedFingerprint;
}
public void writeToParcel(Parcel dest, int flags) {
dest.writeByteArray(mBytes);
dest.writeString(mExpectedFingerprint);
}
public static final Creator<ParcelableKeyRing> CREATOR = new Creator<ParcelableKeyRing>() {
public ParcelableKeyRing createFromParcel(final Parcel source) {
return new ParcelableKeyRing(source.createByteArray());
}
public ParcelableKeyRing[] newArray(final int size) {
return new ParcelableKeyRing[size];
}
};
public int describeContents() {
return 0;
}
public UncachedKeyRing getUncachedKeyRing() throws PgpGeneralException, IOException {
return UncachedKeyRing.decodeFromData(mBytes);
}
}

View File

@@ -30,26 +30,6 @@ import java.util.Iterator;
public class PgpConversionHelper { public class PgpConversionHelper {
/**
* Convert from byte[] to PGPKeyRing
*
* @param keysBytes
* @return
*/
public static PGPKeyRing BytesToPGPKeyRing(byte[] keysBytes) {
PGPObjectFactory factory = new PGPObjectFactory(keysBytes);
PGPKeyRing keyRing = null;
try {
if ((keyRing = (PGPKeyRing) factory.nextObject()) == null) {
Log.e(Constants.TAG, "No keys given!");
}
} catch (IOException e) {
Log.e(Constants.TAG, "Error while converting to PGPKeyRing!", e);
}
return keyRing;
}
/** /**
* Convert from byte[] to ArrayList<PGPSecretKey> * Convert from byte[] to ArrayList<PGPSecretKey>
* *

View File

@@ -24,20 +24,14 @@ import android.os.Environment;
import org.spongycastle.bcpg.ArmoredOutputStream; import org.spongycastle.bcpg.ArmoredOutputStream;
import org.spongycastle.openpgp.PGPException; import org.spongycastle.openpgp.PGPException;
import org.spongycastle.openpgp.PGPKeyRing;
import org.spongycastle.openpgp.PGPPublicKey;
import org.spongycastle.openpgp.PGPPublicKeyRing;
import org.spongycastle.openpgp.PGPSecretKeyRing;
import org.spongycastle.openpgp.operator.jcajce.JcaKeyFingerprintCalculator;
import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing;
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.service.KeychainIntentService; import org.sufficientlysecure.keychain.service.KeychainIntentService;
import org.sufficientlysecure.keychain.keyimport.ImportKeysListEntry;
import org.sufficientlysecure.keychain.keyimport.HkpKeyserver; import org.sufficientlysecure.keychain.keyimport.HkpKeyserver;
import org.sufficientlysecure.keychain.util.IterableIterator;
import org.sufficientlysecure.keychain.keyimport.Keyserver.AddKeyException; import org.sufficientlysecure.keychain.keyimport.Keyserver.AddKeyException;
import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.Log;
@@ -62,7 +56,6 @@ public class PgpImportExport {
private ProviderHelper mProviderHelper; private ProviderHelper mProviderHelper;
public static final int RETURN_OK = 0; public static final int RETURN_OK = 0;
public static final int RETURN_ERROR = -1;
public static final int RETURN_BAD = -2; public static final int RETURN_BAD = -2;
public static final int RETURN_UPDATED = 1; public static final int RETURN_UPDATED = 1;
@@ -133,7 +126,7 @@ public class PgpImportExport {
/** /**
* Imports keys from given data. If keyIds is given only those are imported * Imports keys from given data. If keyIds is given only those are imported
*/ */
public Bundle importKeyRings(List<ImportKeysListEntry> entries) public Bundle importKeyRings(List<ParcelableKeyRing> entries)
throws PgpGeneralException, PGPException, IOException { throws PgpGeneralException, PGPException, IOException {
Bundle returnData = new Bundle(); Bundle returnData = new Bundle();
@@ -144,55 +137,26 @@ public class PgpImportExport {
int badKeys = 0; int badKeys = 0;
int position = 0; int position = 0;
try { for (ParcelableKeyRing entry : entries) {
for (ImportKeysListEntry entry : entries) { try {
Object obj = PgpConversionHelper.BytesToPGPKeyRing(entry.getBytes()); UncachedKeyRing key = entry.getUncachedKeyRing();
if (obj instanceof PGPKeyRing) { mProviderHelper.savePublicKeyRing(key);
PGPKeyRing keyring = (PGPKeyRing) obj; /*switch(status) {
int status; case RETURN_UPDATED: oldKeys++; break;
// TODO Better try to get this one from the db first! case RETURN_OK: newKeys++; break;
if(keyring instanceof PGPSecretKeyRing) { case RETURN_BAD: badKeys++; break;
PGPSecretKeyRing secretKeyRing = (PGPSecretKeyRing) keyring; }*/
// TODO: preserve certifications // TODO proper import feedback
// (http://osdir.com/ml/encryption.bouncy-castle.devel/2007-01/msg00054.html ?) newKeys += 1;
PGPPublicKeyRing newPubRing = null;
for (PGPPublicKey key : new IterableIterator<PGPPublicKey>(
secretKeyRing.getPublicKeys())) {
if (newPubRing == null) {
newPubRing = new PGPPublicKeyRing(key.getEncoded(),
new JcaKeyFingerprintCalculator());
}
newPubRing = PGPPublicKeyRing.insertPublicKey(newPubRing, key);
}
status = storeKeyRingInCache(new UncachedKeyRing(newPubRing),
new UncachedKeyRing(secretKeyRing));
} else {
status = storeKeyRingInCache(new UncachedKeyRing(keyring));
}
if (status == RETURN_ERROR) { } catch (PgpGeneralException e) {
throw new PgpGeneralException( Log.e(Constants.TAG, "Encountered bad key on import!", e);
mContext.getString(R.string.error_saving_keys)); ++badKeys;
}
// update the counts to display to the user at the end
if (status == RETURN_UPDATED) {
++oldKeys;
} else if (status == RETURN_OK) {
++newKeys;
} else if (status == RETURN_BAD) {
++badKeys;
}
} else {
Log.e(Constants.TAG, "Object not recognized as PGPKeyRing!");
}
position++;
updateProgress(position / entries.size() * 100, 100);
} }
} catch (Exception e) { // update progress
Log.e(Constants.TAG, "Exception on parsing key file!", e); position++;
updateProgress(position / entries.size() * 100, 100);
} }
returnData.putInt(KeychainIntentService.RESULT_IMPORT_ADDED, newKeys); returnData.putInt(KeychainIntentService.RESULT_IMPORT_ADDED, newKeys);
@@ -280,28 +244,4 @@ public class PgpImportExport {
return returnData; return returnData;
} }
public int storeKeyRingInCache(UncachedKeyRing ring) {
return storeKeyRingInCache(ring, null);
}
@SuppressWarnings("unchecked")
public int storeKeyRingInCache(UncachedKeyRing ring, UncachedKeyRing secretRing) {
int status;
try {
UncachedKeyRing secretKeyRing = null;
// see what type we have. we can either have a secret + public keyring, or just public
if (secretKeyRing != null) {
mProviderHelper.saveKeyRing(ring, secretRing);
status = RETURN_OK;
} else {
mProviderHelper.savePublicKeyRing(ring);
status = RETURN_OK;
}
} catch (IOException e) {
status = RETURN_ERROR;
}
return status;
}
} }

View File

@@ -32,6 +32,7 @@ import org.sufficientlysecure.keychain.helper.FileHelper;
import org.sufficientlysecure.keychain.helper.OtherHelper; import org.sufficientlysecure.keychain.helper.OtherHelper;
import org.sufficientlysecure.keychain.helper.Preferences; import org.sufficientlysecure.keychain.helper.Preferences;
import org.sufficientlysecure.keychain.keyimport.HkpKeyserver; import org.sufficientlysecure.keychain.keyimport.HkpKeyserver;
import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing;
import org.sufficientlysecure.keychain.pgp.UncachedSecretKey; import org.sufficientlysecure.keychain.pgp.UncachedSecretKey;
import org.sufficientlysecure.keychain.pgp.WrappedPublicKeyRing; import org.sufficientlysecure.keychain.pgp.WrappedPublicKeyRing;
import org.sufficientlysecure.keychain.pgp.WrappedSecretKey; import org.sufficientlysecure.keychain.pgp.WrappedSecretKey;
@@ -40,7 +41,6 @@ import org.sufficientlysecure.keychain.pgp.PgpDecryptVerify;
import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyResult; import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyResult;
import org.sufficientlysecure.keychain.pgp.PgpHelper; import org.sufficientlysecure.keychain.pgp.PgpHelper;
import org.sufficientlysecure.keychain.pgp.PgpImportExport; import org.sufficientlysecure.keychain.pgp.PgpImportExport;
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
import org.sufficientlysecure.keychain.pgp.PgpKeyOperation; import org.sufficientlysecure.keychain.pgp.PgpKeyOperation;
import org.sufficientlysecure.keychain.pgp.PgpSignEncrypt; import org.sufficientlysecure.keychain.pgp.PgpSignEncrypt;
import org.sufficientlysecure.keychain.pgp.Progressable; import org.sufficientlysecure.keychain.pgp.Progressable;
@@ -56,7 +56,6 @@ import org.sufficientlysecure.keychain.keyimport.KeybaseKeyserver;
import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.ProgressScaler; import org.sufficientlysecure.keychain.util.ProgressScaler;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.File; import java.io.File;
@@ -645,7 +644,7 @@ public class KeychainIntentService extends IntentService
} }
} else if (ACTION_IMPORT_KEYRING.equals(action)) { } else if (ACTION_IMPORT_KEYRING.equals(action)) {
try { try {
List<ImportKeysListEntry> entries = data.getParcelableArrayList(IMPORT_KEY_LIST); List<ParcelableKeyRing> entries = data.getParcelableArrayList(IMPORT_KEY_LIST);
PgpImportExport pgpImportExport = new PgpImportExport(this, this); PgpImportExport pgpImportExport = new PgpImportExport(this, this);
Bundle resultData = pgpImportExport.importKeyRings(entries); Bundle resultData = pgpImportExport.importKeyRings(entries);
@@ -739,32 +738,21 @@ public class KeychainIntentService extends IntentService
try { try {
KeybaseKeyserver server = new KeybaseKeyserver(); KeybaseKeyserver server = new KeybaseKeyserver();
ArrayList<ParcelableKeyRing> keyRings = new ArrayList<ParcelableKeyRing>(entries.size());
for (ImportKeysListEntry entry : entries) { for (ImportKeysListEntry entry : entries) {
// the keybase handle is in userId(1) // the keybase handle is in userId(1)
String keybaseId = entry.getExtraData(); String keybaseId = entry.getExtraData();
byte[] downloadedKeyBytes = server.get(keybaseId).getBytes(); byte[] downloadedKeyBytes = server.get(keybaseId).getBytes();
// create PGPKeyRing object based on downloaded armored key
UncachedKeyRing downloadedKey = null;
BufferedInputStream bufferedInput =
new BufferedInputStream(new ByteArrayInputStream(downloadedKeyBytes));
if (bufferedInput.available() > 0) {
List<UncachedKeyRing> rings = UncachedKeyRing.fromStream(bufferedInput);
if(rings.isEmpty()) {
throw new PgpGeneralException("No keys in result!");
}
downloadedKey = rings.get(0);
}
// save key bytes in entry object for doing the // save key bytes in entry object for doing the
// actual import afterwards // actual import afterwards
entry.setBytes(downloadedKey.getEncoded()); keyRings.add(new ParcelableKeyRing(downloadedKeyBytes));
} }
Intent importIntent = new Intent(this, KeychainIntentService.class); Intent importIntent = new Intent(this, KeychainIntentService.class);
importIntent.setAction(ACTION_IMPORT_KEYRING); importIntent.setAction(ACTION_IMPORT_KEYRING);
Bundle importData = new Bundle(); Bundle importData = new Bundle();
importData.putParcelableArrayList(IMPORT_KEY_LIST, entries); importData.putParcelableArrayList(IMPORT_KEY_LIST, keyRings);
importIntent.putExtra(EXTRA_DATA, importData); importIntent.putExtra(EXTRA_DATA, importData);
importIntent.putExtra(EXTRA_MESSENGER, mMessenger); importIntent.putExtra(EXTRA_MESSENGER, mMessenger);
@@ -778,11 +766,12 @@ public class KeychainIntentService extends IntentService
} else if (ACTION_DOWNLOAD_AND_IMPORT_KEYS.equals(action)) { } else if (ACTION_DOWNLOAD_AND_IMPORT_KEYS.equals(action)) {
try { try {
ArrayList<ImportKeysListEntry> entries = data.getParcelableArrayList(DOWNLOAD_KEY_LIST); ArrayList<ImportKeysListEntry> entries = data.getParcelableArrayList(DOWNLOAD_KEY_LIST);
String keyServer = data.getString(DOWNLOAD_KEY_SERVER);
// this downloads the keys and places them into the ImportKeysListEntry entries // this downloads the keys and places them into the ImportKeysListEntry entries
String keyServer = data.getString(DOWNLOAD_KEY_SERVER);
HkpKeyserver server = new HkpKeyserver(keyServer); HkpKeyserver server = new HkpKeyserver(keyServer);
ArrayList<ParcelableKeyRing> keyRings = new ArrayList<ParcelableKeyRing>(entries.size());
for (ImportKeysListEntry entry : entries) { for (ImportKeysListEntry entry : entries) {
// if available use complete fingerprint for get request // if available use complete fingerprint for get request
byte[] downloadedKeyBytes; byte[] downloadedKeyBytes;
@@ -792,32 +781,15 @@ public class KeychainIntentService extends IntentService
downloadedKeyBytes = server.get(entry.getKeyIdHex()).getBytes(); downloadedKeyBytes = server.get(entry.getKeyIdHex()).getBytes();
} }
// create PGPKeyRing object based on downloaded armored key
UncachedKeyRing downloadedKey =
UncachedKeyRing.decodePublicFromData(downloadedKeyBytes);
// verify downloaded key by comparing fingerprints
if (entry.getFingerprintHex() != null) {
String downloadedKeyFp = PgpKeyHelper.convertFingerprintToHex(
downloadedKey.getFingerprint());
if (downloadedKeyFp.equals(entry.getFingerprintHex())) {
Log.d(Constants.TAG, "fingerprint of downloaded key is the same as " +
"the requested fingerprint!");
} else {
throw new PgpGeneralException("fingerprint of downloaded key is " +
"NOT the same as the requested fingerprint!");
}
}
// save key bytes in entry object for doing the // save key bytes in entry object for doing the
// actual import afterwards // actual import afterwards
entry.setBytes(downloadedKeyBytes); keyRings.add(new ParcelableKeyRing(downloadedKeyBytes, entry.getFingerprintHex()));
} }
Intent importIntent = new Intent(this, KeychainIntentService.class); Intent importIntent = new Intent(this, KeychainIntentService.class);
importIntent.setAction(ACTION_IMPORT_KEYRING); importIntent.setAction(ACTION_IMPORT_KEYRING);
Bundle importData = new Bundle(); Bundle importData = new Bundle();
importData.putParcelableArrayList(IMPORT_KEY_LIST, entries); importData.putParcelableArrayList(IMPORT_KEY_LIST, keyRings);
importIntent.putExtra(EXTRA_DATA, importData); importIntent.putExtra(EXTRA_DATA, importData);
importIntent.putExtra(EXTRA_MESSENGER, mMessenger); importIntent.putExtra(EXTRA_MESSENGER, mMessenger);
@@ -853,13 +825,9 @@ public class KeychainIntentService extends IntentService
UncachedKeyRing newRing = certificationKey.certifyUserIds(publicRing, userIds); UncachedKeyRing newRing = certificationKey.certifyUserIds(publicRing, userIds);
// store the signed key in our local cache // store the signed key in our local cache
PgpImportExport pgpImportExport = new PgpImportExport(this, null); providerHelper.savePublicKeyRing(newRing);
int retval = pgpImportExport.storeKeyRingInCache(newRing);
if (retval != PgpImportExport.RETURN_OK && retval != PgpImportExport.RETURN_UPDATED) {
throw new PgpGeneralException("Failed to store signed key in local cache");
}
sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY); sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY);
} catch (Exception e) { } catch (Exception e) {
sendErrorToHandler(e); sendErrorToHandler(e);
} }

View File

@@ -42,6 +42,7 @@ import com.devspark.appmsg.AppMsg;
import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing;
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
import org.sufficientlysecure.keychain.service.KeychainIntentService; import org.sufficientlysecure.keychain.service.KeychainIntentService;
import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
@@ -415,8 +416,8 @@ public class ImportKeysActivity extends ActionBarActivity implements ActionBar.O
// fill values for this action // fill values for this action
Bundle data = new Bundle(); Bundle data = new Bundle();
// get selected key entries // get DATA from selected key entries
ArrayList<ImportKeysListEntry> selectedEntries = mListFragment.getSelectedData(); ArrayList<ParcelableKeyRing> selectedEntries = mListFragment.getSelectedData();
data.putParcelableArrayList(KeychainIntentService.IMPORT_KEY_LIST, selectedEntries); data.putParcelableArrayList(KeychainIntentService.IMPORT_KEY_LIST, selectedEntries);
intent.putExtra(KeychainIntentService.EXTRA_DATA, data); intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
@@ -442,7 +443,7 @@ public class ImportKeysActivity extends ActionBarActivity implements ActionBar.O
data.putString(KeychainIntentService.DOWNLOAD_KEY_SERVER, mListFragment.getKeyServer()); data.putString(KeychainIntentService.DOWNLOAD_KEY_SERVER, mListFragment.getKeyServer());
// get selected key entries // get selected key entries
ArrayList<ImportKeysListEntry> selectedEntries = mListFragment.getSelectedData(); ArrayList<ImportKeysListEntry> selectedEntries = mListFragment.getSelectedEntries();
data.putParcelableArrayList(KeychainIntentService.DOWNLOAD_KEY_LIST, selectedEntries); data.putParcelableArrayList(KeychainIntentService.DOWNLOAD_KEY_LIST, selectedEntries);
intent.putExtra(KeychainIntentService.EXTRA_DATA, data); intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
@@ -466,7 +467,7 @@ public class ImportKeysActivity extends ActionBarActivity implements ActionBar.O
Bundle data = new Bundle(); Bundle data = new Bundle();
// get selected key entries // get selected key entries
ArrayList<ImportKeysListEntry> selectedEntries = mListFragment.getSelectedData(); ArrayList<ImportKeysListEntry> selectedEntries = mListFragment.getSelectedEntries();
data.putParcelableArrayList(KeychainIntentService.DOWNLOAD_KEY_LIST, selectedEntries); data.putParcelableArrayList(KeychainIntentService.DOWNLOAD_KEY_LIST, selectedEntries);
intent.putExtra(KeychainIntentService.EXTRA_DATA, data); intent.putExtra(KeychainIntentService.EXTRA_DATA, data);

View File

@@ -23,6 +23,7 @@ import android.os.Bundle;
import android.support.v4.app.ListFragment; import android.support.v4.app.ListFragment;
import android.support.v4.app.LoaderManager; import android.support.v4.app.LoaderManager;
import android.support.v4.content.Loader; import android.support.v4.content.Loader;
import android.support.v4.util.LongSparseArray;
import android.view.View; import android.view.View;
import android.widget.ListView; import android.widget.ListView;
@@ -31,6 +32,7 @@ import com.devspark.appmsg.AppMsg;
import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.helper.Preferences; import org.sufficientlysecure.keychain.helper.Preferences;
import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing;
import org.sufficientlysecure.keychain.ui.adapter.AsyncTaskResultWrapper; import org.sufficientlysecure.keychain.ui.adapter.AsyncTaskResultWrapper;
import org.sufficientlysecure.keychain.ui.adapter.ImportKeysAdapter; import org.sufficientlysecure.keychain.ui.adapter.ImportKeysAdapter;
import org.sufficientlysecure.keychain.keyimport.ImportKeysListEntry; import org.sufficientlysecure.keychain.keyimport.ImportKeysListEntry;
@@ -67,6 +69,8 @@ public class ImportKeysListFragment extends ListFragment implements
private static final int LOADER_ID_SERVER_QUERY = 1; private static final int LOADER_ID_SERVER_QUERY = 1;
private static final int LOADER_ID_KEYBASE = 2; private static final int LOADER_ID_KEYBASE = 2;
private LongSparseArray<ParcelableKeyRing> mCachedKeyData;
public byte[] getKeyBytes() { public byte[] getKeyBytes() {
return mKeyBytes; return mKeyBytes;
} }
@@ -91,8 +95,16 @@ public class ImportKeysListFragment extends ListFragment implements
return mAdapter.getData(); return mAdapter.getData();
} }
public ArrayList<ImportKeysListEntry> getSelectedData() { public ArrayList<ParcelableKeyRing> getSelectedData() {
return mAdapter.getSelectedData(); ArrayList<ParcelableKeyRing> result = new ArrayList<ParcelableKeyRing>();
for(ImportKeysListEntry entry : getSelectedEntries()) {
result.add(mCachedKeyData.get(entry.getKeyId()));
}
return result;
}
public ArrayList<ImportKeysListEntry> getSelectedEntries() {
return mAdapter.getSelectedEntries();
} }
/** /**
@@ -120,8 +132,7 @@ public class ImportKeysListFragment extends ListFragment implements
mActivity = getActivity(); mActivity = getActivity();
// Give some text to display if there is no data. In a real // Give some text to display if there is no data.
// application this would come from a resource.
setEmptyText(mActivity.getString(R.string.error_nothing_import)); setEmptyText(mActivity.getString(R.string.error_nothing_import));
// Create an empty adapter we will use to display the loaded data. // Create an empty adapter we will use to display the loaded data.
@@ -252,11 +263,15 @@ public class ImportKeysListFragment extends ListFragment implements
Exception error = data.getError(); Exception error = data.getError();
// free old cached key data
mCachedKeyData = null;
switch (loader.getId()) { switch (loader.getId()) {
case LOADER_ID_BYTES: case LOADER_ID_BYTES:
if (error == null) { if (error == null) {
// No error // No error
mCachedKeyData = ((ImportKeysListLoader) loader).getParcelableRings();
} else if (error instanceof ImportKeysListLoader.FileHasNoContent) { } else if (error instanceof ImportKeysListLoader.FileHasNoContent) {
AppMsg.makeText(getActivity(), R.string.error_import_file_no_content, AppMsg.makeText(getActivity(), R.string.error_import_file_no_content,
AppMsg.STYLE_ALERT).show(); AppMsg.STYLE_ALERT).show();

View File

@@ -32,6 +32,7 @@ import android.widget.TextView;
import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.keyimport.ImportKeysListEntry; import org.sufficientlysecure.keychain.keyimport.ImportKeysListEntry;
import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing;
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
import org.sufficientlysecure.keychain.util.Highlighter; import org.sufficientlysecure.keychain.util.Highlighter;
@@ -83,7 +84,7 @@ public class ImportKeysAdapter extends ArrayAdapter<ImportKeysListEntry> {
return mData; return mData;
} }
public ArrayList<ImportKeysListEntry> getSelectedData() { public ArrayList<ImportKeysListEntry> getSelectedEntries() {
ArrayList<ImportKeysListEntry> selectedData = new ArrayList<ImportKeysListEntry>(); ArrayList<ImportKeysListEntry> selectedData = new ArrayList<ImportKeysListEntry>();
for (ImportKeysListEntry entry : mData) { for (ImportKeysListEntry entry : mData) {
if (entry.isSelected()) { if (entry.isSelected()) {

View File

@@ -19,9 +19,11 @@ package org.sufficientlysecure.keychain.ui.adapter;
import android.content.Context; import android.content.Context;
import android.support.v4.content.AsyncTaskLoader; import android.support.v4.content.AsyncTaskLoader;
import android.support.v4.util.LongSparseArray;
import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.keyimport.ImportKeysListEntry; import org.sufficientlysecure.keychain.keyimport.ImportKeysListEntry;
import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing;
import org.sufficientlysecure.keychain.pgp.UncachedKeyRing; import org.sufficientlysecure.keychain.pgp.UncachedKeyRing;
import org.sufficientlysecure.keychain.util.InputData; import org.sufficientlysecure.keychain.util.InputData;
import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.Log;
@@ -54,6 +56,7 @@ public class ImportKeysListLoader
final InputData mInputData; final InputData mInputData;
ArrayList<ImportKeysListEntry> mData = new ArrayList<ImportKeysListEntry>(); ArrayList<ImportKeysListEntry> mData = new ArrayList<ImportKeysListEntry>();
LongSparseArray<ParcelableKeyRing> mParcelableRings = new LongSparseArray<ParcelableKeyRing>();
AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>> mEntryListWrapper; AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>> mEntryListWrapper;
public ImportKeysListLoader(Context context, InputData inputData) { public ImportKeysListLoader(Context context, InputData inputData) {
@@ -105,6 +108,10 @@ public class ImportKeysListLoader
super.deliverResult(data); super.deliverResult(data);
} }
public LongSparseArray<ParcelableKeyRing> getParcelableRings() {
return mParcelableRings;
}
/** /**
* Reads all PGPKeyRing objects from input * Reads all PGPKeyRing objects from input
* *
@@ -129,7 +136,9 @@ public class ImportKeysListLoader
// todo deal with non-keyring objects? // todo deal with non-keyring objects?
List<UncachedKeyRing> rings = UncachedKeyRing.fromStream(bufferedInput); List<UncachedKeyRing> rings = UncachedKeyRing.fromStream(bufferedInput);
for(UncachedKeyRing key : rings) { for(UncachedKeyRing key : rings) {
addToData(key); ImportKeysListEntry item = new ImportKeysListEntry(getContext(), key);
mData.add(item);
mParcelableRings.put(key.getMasterKeyId(), new ParcelableKeyRing(key.getEncoded()));
isEmpty = false; isEmpty = false;
} }
} }
@@ -145,9 +154,4 @@ public class ImportKeysListLoader
} }
} }
private void addToData(UncachedKeyRing keyring) {
ImportKeysListEntry item = new ImportKeysListEntry(getContext(), keyring);
mData.add(item);
}
} }