From 776392be3a66d30c5c91b56dee7a9eabcdcbf038 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Sat, 1 Feb 2014 21:55:34 +0100 Subject: [PATCH] Reworking import, testing needed... --- OpenPGP-Keychain/src/main/AndroidManifest.xml | 4 - .../keychain/pgp/PgpImportExport.java | 94 ++-- .../service/KeychainIntentService.java | 420 +++++++++--------- .../keychain/ui/DecryptActivity.java | 10 +- .../keychain/ui/EncryptActivity.java | 2 +- .../keychain/ui/ImportKeysActivity.java | 170 +++---- .../keychain/ui/ImportKeysListFragment.java | 9 + .../keychain/ui/KeyServerQueryActivity.java | 391 ---------------- .../keychain/ui/ViewKeyActivity.java | 6 +- .../ui/adapter/ImportKeysAdapter.java | 10 + .../ui/adapter/ImportKeysListEntry.java | 94 +++- .../LookupUnknownKeyDialogFragment.java | 8 +- .../keychain/util/KeyServer.java | 43 -- .../layout/import_keys_server_fragment.xml | 9 - .../src/main/res/layout/key_server_query.xml | 40 -- .../layout/key_server_query_result_item.xml | 77 ---- .../key_server_query_result_user_id.xml | 10 - 17 files changed, 448 insertions(+), 949 deletions(-) delete mode 100644 OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyServerQueryActivity.java delete mode 100644 OpenPGP-Keychain/src/main/res/layout/key_server_query.xml delete mode 100644 OpenPGP-Keychain/src/main/res/layout/key_server_query_result_item.xml delete mode 100644 OpenPGP-Keychain/src/main/res/layout/key_server_query_result_user_id.xml diff --git a/OpenPGP-Keychain/src/main/AndroidManifest.xml b/OpenPGP-Keychain/src/main/AndroidManifest.xml index d40580a79..58219356b 100644 --- a/OpenPGP-Keychain/src/main/AndroidManifest.xml +++ b/OpenPGP-Keychain/src/main/AndroidManifest.xml @@ -238,10 +238,6 @@ - keyIds) - throws PgpGeneralException, FileNotFoundException, PGPException, IOException { + public Bundle importKeyRings(List entries) throws PgpGeneralException, PGPException, IOException { Bundle returnData = new Bundle(); - updateProgress(R.string.progress_importing_secret_keys, 0, 100); + updateProgress(R.string.progress_importing_secret_keys, 0, entries.size()); - PositionAwareInputStream progressIn = new PositionAwareInputStream(data.getInputStream()); - - // need to have access to the bufferedInput, so we can reuse it for the possible - // PGPObject chunks after the first one, e.g. files with several consecutive ASCII - // armour blocks - BufferedInputStream bufferedInput = new BufferedInputStream(progressIn); int newKeys = 0; int oldKeys = 0; int badKeys = 0; + + int position = 0; try { + for (ImportKeysListEntry entry : entries) { + Object obj = PgpConversionHelper.BytesToPGPKeyRing(entry.getBytes()); - // read all available blocks... (asc files can contain many blocks with BEGIN END) - while (bufferedInput.available() > 0) { - InputStream in = PGPUtil.getDecoderStream(bufferedInput); - PGPObjectFactory objectFactory = new PGPObjectFactory(in); + if (obj instanceof PGPKeyRing) { + PGPKeyRing keyring = (PGPKeyRing) obj; - // go through all objects in this block - Object obj; - while ((obj = objectFactory.nextObject()) != null) { - Log.d(Constants.TAG, "Found class: " + obj.getClass()); + int status = storeKeyRingInCache(keyring); - if (obj instanceof PGPKeyRing) { - PGPKeyRing keyring = (PGPKeyRing) obj; - - int status = Integer.MIN_VALUE; // out of bounds value - - if (keyIds != null) { - if (keyIds.contains(keyring.getPublicKey().getKeyID())) { - status = storeKeyRingInCache(keyring); - } else { - Log.d(Constants.TAG, "not selected! key id: " - + keyring.getPublicKey().getKeyID()); - } - } else { - status = storeKeyRingInCache(keyring); - } - - if (status == Id.return_value.error) { - throw new PgpGeneralException( - mContext.getString(R.string.error_saving_keys)); - } - - // update the counts to display to the user at the end - if (status == Id.return_value.updated) { - ++oldKeys; - } else if (status == Id.return_value.ok) { - ++newKeys; - } else if (status == Id.return_value.bad) { - ++badKeys; - } - - updateProgress((int) (100 * progressIn.position() / data.getSize()), 100); - } else { - Log.e(Constants.TAG, "Object not recognized as PGPKeyRing!"); + if (status == Id.return_value.error) { + throw new PgpGeneralException( + mContext.getString(R.string.error_saving_keys)); } + + // update the counts to display to the user at the end + if (status == Id.return_value.updated) { + ++oldKeys; + } else if (status == Id.return_value.ok) { + ++newKeys; + } else if (status == Id.return_value.bad) { + ++badKeys; + } + + position++; + updateProgress(position, entries.size()); + } else { + Log.e(Constants.TAG, "Object not recognized as PGPKeyRing!"); } } } catch (Exception e) { @@ -187,13 +157,11 @@ public class PgpImportExport { returnData.putInt(KeychainIntentService.RESULT_IMPORT_UPDATED, oldKeys); returnData.putInt(KeychainIntentService.RESULT_IMPORT_BAD, badKeys); - updateProgress(R.string.progress_done, 100, 100); - return returnData; } public Bundle exportKeyRings(ArrayList keyRingMasterKeyIds, int keyType, - OutputStream outStream) throws PgpGeneralException, FileNotFoundException, + OutputStream outStream) throws PgpGeneralException, FileNotFoundException, PGPException, IOException { Bundle returnData = new Bundle(); @@ -253,10 +221,6 @@ public class PgpImportExport { /** * TODO: implement Id.return_value.updated as status when key already existed - * - * @param context - * @param keyring - * @return */ @SuppressWarnings("unchecked") public int storeKeyRingInCache(PGPKeyRing keyring) { diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java index 7a90c5609..657d40a5a 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java @@ -17,6 +17,7 @@ package org.sufficientlysecure.keychain.service; +import java.io.BufferedInputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; @@ -28,9 +29,13 @@ import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.GregorianCalendar; +import java.util.List; +import org.spongycastle.openpgp.PGPKeyRing; +import org.spongycastle.openpgp.PGPObjectFactory; import org.spongycastle.openpgp.PGPPublicKeyRing; import org.spongycastle.openpgp.PGPSecretKey; +import org.spongycastle.openpgp.PGPUtil; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.Id; import org.sufficientlysecure.keychain.R; @@ -45,9 +50,11 @@ import org.sufficientlysecure.keychain.pgp.PgpOperation; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.provider.KeychainContract.DataStream; import org.sufficientlysecure.keychain.provider.ProviderHelper; +import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListEntry; import org.sufficientlysecure.keychain.util.HkpKeyServer; import org.sufficientlysecure.keychain.util.InputData; import org.sufficientlysecure.keychain.util.Log; +import org.sufficientlysecure.keychain.util.PositionAwareInputStream; import org.sufficientlysecure.keychain.util.ProgressDialogUpdater; import android.app.IntentService; @@ -87,7 +94,7 @@ public class KeychainIntentService extends IntentService implements ProgressDial public static final String ACTION_EXPORT_KEYRING = Constants.INTENT_PREFIX + "EXPORT_KEYRING"; public static final String ACTION_UPLOAD_KEYRING = Constants.INTENT_PREFIX + "UPLOAD_KEYRING"; - public static final String ACTION_QUERY_KEYRING = Constants.INTENT_PREFIX + "QUERY_KEYRING"; + public static final String ACTION_DOWNLOAD_AND_IMPORT_KEYS = Constants.INTENT_PREFIX + "QUERY_KEYRING"; public static final String ACTION_SIGN_KEYRING = Constants.INTENT_PREFIX + "SIGN_KEYRING"; @@ -97,7 +104,7 @@ public class KeychainIntentService extends IntentService implements ProgressDial public static final String TARGET = "target"; // possible targets: public static final int TARGET_BYTES = 1; - public static final int TARGET_FILE = 2; + public static final int TARGET_URI = 2; public static final int TARGET_STREAM = 3; // encrypt @@ -139,7 +146,6 @@ public class KeychainIntentService extends IntentService implements ProgressDial public static final String DELETE_FILE = "deleteFile"; // import key - public static final String IMPORT_BYTES = "import_bytes"; public static final String IMPORT_KEY_LIST = "import_key_list"; // export key @@ -153,8 +159,8 @@ public class KeychainIntentService extends IntentService implements ProgressDial public static final String UPLOAD_KEY_SERVER = "upload_key_server"; // query key - public static final String QUERY_KEY_SERVER = "query_key_server"; - public static final String QUERY_KEY_ID = "query_key_id"; + public static final String DOWNLOAD_KEY_SERVER = "query_key_server"; + public static final String DOWNLOAD_KEY_LIST = "query_key_id"; // sign key public static final String SIGN_KEY_MASTER_KEY_ID = "sign_key_master_key_id"; @@ -253,62 +259,62 @@ public class KeychainIntentService extends IntentService implements ProgressDial OutputStream outStream = null; String streamFilename = null; switch (target) { - case TARGET_BYTES: /* encrypting bytes directly */ - byte[] bytes = data.getByteArray(ENCRYPT_MESSAGE_BYTES); + case TARGET_BYTES: /* encrypting bytes directly */ + byte[] bytes = data.getByteArray(ENCRYPT_MESSAGE_BYTES); - inStream = new ByteArrayInputStream(bytes); - inLength = bytes.length; + inStream = new ByteArrayInputStream(bytes); + inLength = bytes.length; - inputData = new InputData(inStream, inLength); - outStream = new ByteArrayOutputStream(); + inputData = new InputData(inStream, inLength); + outStream = new ByteArrayOutputStream(); - break; - case TARGET_FILE: /* encrypting file */ - String inputFile = data.getString(ENCRYPT_INPUT_FILE); - String outputFile = data.getString(ENCRYPT_OUTPUT_FILE); + break; + case TARGET_URI: /* encrypting file */ + String inputFile = data.getString(ENCRYPT_INPUT_FILE); + String outputFile = data.getString(ENCRYPT_OUTPUT_FILE); - // check if storage is ready - if (!FileHelper.isStorageMounted(inputFile) - || !FileHelper.isStorageMounted(outputFile)) { - throw new PgpGeneralException( - getString(R.string.error_external_storage_not_ready)); - } - - inStream = new FileInputStream(inputFile); - File file = new File(inputFile); - inLength = file.length(); - inputData = new InputData(inStream, inLength); - - outStream = new FileOutputStream(outputFile); - - break; - - case TARGET_STREAM: /* Encrypting stream from content uri */ - Uri providerUri = (Uri) data.getParcelable(ENCRYPT_PROVIDER_URI); - - // InputStream - InputStream in = getContentResolver().openInputStream(providerUri); - inLength = PgpHelper.getLengthOfStream(in); - inputData = new InputData(in, inLength); - - // OutputStream - try { - while (true) { - streamFilename = PgpHelper.generateRandomFilename(32); - if (streamFilename == null) { - throw new PgpGeneralException("couldn't generate random file name"); - } - openFileInput(streamFilename).close(); + // check if storage is ready + if (!FileHelper.isStorageMounted(inputFile) + || !FileHelper.isStorageMounted(outputFile)) { + throw new PgpGeneralException( + getString(R.string.error_external_storage_not_ready)); } - } catch (FileNotFoundException e) { - // found a name that isn't used yet - } - outStream = openFileOutput(streamFilename, Context.MODE_PRIVATE); - break; + inStream = new FileInputStream(inputFile); + File file = new File(inputFile); + inLength = file.length(); + inputData = new InputData(inStream, inLength); - default: - throw new PgpGeneralException("No target choosen!"); + outStream = new FileOutputStream(outputFile); + + break; + + case TARGET_STREAM: /* Encrypting stream from content uri */ + Uri providerUri = (Uri) data.getParcelable(ENCRYPT_PROVIDER_URI); + + // InputStream + InputStream in = getContentResolver().openInputStream(providerUri); + inLength = PgpHelper.getLengthOfStream(in); + inputData = new InputData(in, inLength); + + // OutputStream + try { + while (true) { + streamFilename = PgpHelper.generateRandomFilename(32); + if (streamFilename == null) { + throw new PgpGeneralException("couldn't generate random file name"); + } + openFileInput(streamFilename).close(); + } + } catch (FileNotFoundException e) { + // found a name that isn't used yet + } + outStream = openFileOutput(streamFilename, Context.MODE_PRIVATE); + + break; + + default: + throw new PgpGeneralException("No target choosen!"); } @@ -319,7 +325,7 @@ public class KeychainIntentService extends IntentService implements ProgressDial operation.generateSignature(useAsciiArmor, false, secretKeyId, PassphraseCacheService.getCachedPassphrase(this, secretKeyId), Preferences.getPreferences(this).getDefaultHashAlgorithm(), Preferences - .getPreferences(this).getForceV3Signatures()); + .getPreferences(this).getForceV3Signatures()); } else if (signOnly) { Log.d(Constants.TAG, "sign only..."); operation.signText(secretKeyId, PassphraseCacheService.getCachedPassphrase( @@ -330,9 +336,9 @@ public class KeychainIntentService extends IntentService implements ProgressDial Log.d(Constants.TAG, "encrypt..."); operation.signAndEncrypt(useAsciiArmor, compressionId, encryptionKeyIds, encryptionPassphrase, Preferences.getPreferences(this) - .getDefaultEncryptionAlgorithm(), secretKeyId, Preferences - .getPreferences(this).getDefaultHashAlgorithm(), Preferences - .getPreferences(this).getForceV3Signatures(), + .getDefaultEncryptionAlgorithm(), secretKeyId, Preferences + .getPreferences(this).getDefaultHashAlgorithm(), Preferences + .getPreferences(this).getForceV3Signatures(), PassphraseCacheService.getCachedPassphrase(this, secretKeyId)); } @@ -343,34 +349,34 @@ public class KeychainIntentService extends IntentService implements ProgressDial Bundle resultData = new Bundle(); switch (target) { - case TARGET_BYTES: - if (useAsciiArmor) { - String output = new String( - ((ByteArrayOutputStream) outStream).toByteArray()); - if (generateSignature) { - resultData.putString(RESULT_SIGNATURE_STRING, output); + case TARGET_BYTES: + if (useAsciiArmor) { + String output = new String( + ((ByteArrayOutputStream) outStream).toByteArray()); + if (generateSignature) { + resultData.putString(RESULT_SIGNATURE_STRING, output); + } else { + resultData.putString(RESULT_ENCRYPTED_STRING, output); + } } else { - resultData.putString(RESULT_ENCRYPTED_STRING, output); + byte output[] = ((ByteArrayOutputStream) outStream).toByteArray(); + if (generateSignature) { + resultData.putByteArray(RESULT_SIGNATURE_BYTES, output); + } else { + resultData.putByteArray(RESULT_ENCRYPTED_BYTES, output); + } } - } else { - byte output[] = ((ByteArrayOutputStream) outStream).toByteArray(); - if (generateSignature) { - resultData.putByteArray(RESULT_SIGNATURE_BYTES, output); - } else { - resultData.putByteArray(RESULT_ENCRYPTED_BYTES, output); - } - } - break; - case TARGET_FILE: - // nothing, file was written, just send okay + break; + case TARGET_URI: + // nothing, file was written, just send okay - break; - case TARGET_STREAM: - String uri = DataStream.buildDataStreamUri(streamFilename).toString(); - resultData.putString(RESULT_URI, uri); + break; + case TARGET_STREAM: + String uri = DataStream.buildDataStreamUri(streamFilename).toString(); + resultData.putString(RESULT_URI, uri); - break; + break; } OtherHelper.logDebugBundle(resultData, "resultData"); @@ -398,64 +404,64 @@ public class KeychainIntentService extends IntentService implements ProgressDial OutputStream outStream = null; String streamFilename = null; switch (target) { - case TARGET_BYTES: /* decrypting bytes directly */ - inStream = new ByteArrayInputStream(bytes); - inLength = bytes.length; + case TARGET_BYTES: /* decrypting bytes directly */ + inStream = new ByteArrayInputStream(bytes); + inLength = bytes.length; - inputData = new InputData(inStream, inLength); - outStream = new ByteArrayOutputStream(); + inputData = new InputData(inStream, inLength); + outStream = new ByteArrayOutputStream(); - break; + break; - case TARGET_FILE: /* decrypting file */ - String inputFile = data.getString(ENCRYPT_INPUT_FILE); - String outputFile = data.getString(ENCRYPT_OUTPUT_FILE); + case TARGET_URI: /* decrypting file */ + String inputFile = data.getString(ENCRYPT_INPUT_FILE); + String outputFile = data.getString(ENCRYPT_OUTPUT_FILE); - // check if storage is ready - if (!FileHelper.isStorageMounted(inputFile) - || !FileHelper.isStorageMounted(outputFile)) { - throw new PgpGeneralException( - getString(R.string.error_external_storage_not_ready)); - } - - // InputStream - inLength = -1; - inStream = new FileInputStream(inputFile); - File file = new File(inputFile); - inLength = file.length(); - inputData = new InputData(inStream, inLength); - - // OutputStream - outStream = new FileOutputStream(outputFile); - - break; - - case TARGET_STREAM: /* decrypting stream from content uri */ - Uri providerUri = (Uri) data.getParcelable(ENCRYPT_PROVIDER_URI); - - // InputStream - InputStream in = getContentResolver().openInputStream(providerUri); - inLength = PgpHelper.getLengthOfStream(in); - inputData = new InputData(in, inLength); - - // OutputStream - try { - while (true) { - streamFilename = PgpHelper.generateRandomFilename(32); - if (streamFilename == null) { - throw new PgpGeneralException("couldn't generate random file name"); - } - openFileInput(streamFilename).close(); + // check if storage is ready + if (!FileHelper.isStorageMounted(inputFile) + || !FileHelper.isStorageMounted(outputFile)) { + throw new PgpGeneralException( + getString(R.string.error_external_storage_not_ready)); } - } catch (FileNotFoundException e) { - // found a name that isn't used yet - } - outStream = openFileOutput(streamFilename, Context.MODE_PRIVATE); - break; + // InputStream + inLength = -1; + inStream = new FileInputStream(inputFile); + File file = new File(inputFile); + inLength = file.length(); + inputData = new InputData(inStream, inLength); - default: - throw new PgpGeneralException("No target choosen!"); + // OutputStream + outStream = new FileOutputStream(outputFile); + + break; + + case TARGET_STREAM: /* decrypting stream from content uri */ + Uri providerUri = (Uri) data.getParcelable(ENCRYPT_PROVIDER_URI); + + // InputStream + InputStream in = getContentResolver().openInputStream(providerUri); + inLength = PgpHelper.getLengthOfStream(in); + inputData = new InputData(in, inLength); + + // OutputStream + try { + while (true) { + streamFilename = PgpHelper.generateRandomFilename(32); + if (streamFilename == null) { + throw new PgpGeneralException("couldn't generate random file name"); + } + openFileInput(streamFilename).close(); + } + } catch (FileNotFoundException e) { + // found a name that isn't used yet + } + outStream = openFileOutput(streamFilename, Context.MODE_PRIVATE); + + break; + + default: + throw new PgpGeneralException("No target choosen!"); } @@ -479,26 +485,26 @@ public class KeychainIntentService extends IntentService implements ProgressDial /* Output */ switch (target) { - case TARGET_BYTES: - if (returnBytes) { - byte output[] = ((ByteArrayOutputStream) outStream).toByteArray(); - resultData.putByteArray(RESULT_DECRYPTED_BYTES, output); - } else { - String output = new String( - ((ByteArrayOutputStream) outStream).toByteArray()); - resultData.putString(RESULT_DECRYPTED_STRING, output); - } + case TARGET_BYTES: + if (returnBytes) { + byte output[] = ((ByteArrayOutputStream) outStream).toByteArray(); + resultData.putByteArray(RESULT_DECRYPTED_BYTES, output); + } else { + String output = new String( + ((ByteArrayOutputStream) outStream).toByteArray()); + resultData.putString(RESULT_DECRYPTED_STRING, output); + } - break; - case TARGET_FILE: - // nothing, file was written, just send okay and verification bundle + break; + case TARGET_URI: + // nothing, file was written, just send okay and verification bundle - break; - case TARGET_STREAM: - String uri = DataStream.buildDataStreamUri(streamFilename).toString(); - resultData.putString(RESULT_URI, uri); + break; + case TARGET_STREAM: + String uri = DataStream.buildDataStreamUri(streamFilename).toString(); + resultData.putString(RESULT_URI, uri); - break; + break; } OtherHelper.logDebugBundle(resultData, "resultData"); @@ -624,51 +630,12 @@ public class KeychainIntentService extends IntentService implements ProgressDial } } else if (ACTION_IMPORT_KEYRING.equals(action)) { try { - - /* Input */ - int target = data.getInt(TARGET); - - /* Operation */ - InputStream inStream = null; - long inLength = -1; - InputData inputData = null; - switch (target) { - case TARGET_BYTES: /* import key from bytes directly */ - byte[] bytes = data.getByteArray(IMPORT_BYTES); - - inStream = new ByteArrayInputStream(bytes); - inLength = bytes.length; - - inputData = new InputData(inStream, inLength); - - break; - case TARGET_FILE: /* import key from file */ - // dataUri! - - try { - inStream = getContentResolver().openInputStream(dataUri); - inLength = inStream.available(); - - inputData = new InputData(inStream, inLength); - } catch (FileNotFoundException e) { - Log.e(Constants.TAG, "FileNotFoundException!", e); - } catch (IOException e) { - Log.e(Constants.TAG, "IOException!", e); - } - - break; - - case TARGET_STREAM: - // TODO: not implemented - break; - } + List entries = data.getParcelableArrayList(IMPORT_KEY_LIST); Bundle resultData = new Bundle(); - ArrayList keyIds = (ArrayList) data.getSerializable(IMPORT_KEY_LIST); - PgpImportExport pgpImportExport = new PgpImportExport(this, this); - resultData = pgpImportExport.importKeyRings(inputData, keyIds); + resultData = pgpImportExport.importKeyRings(entries); sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, resultData); } catch (Exception e) { @@ -749,31 +716,64 @@ public class KeychainIntentService extends IntentService implements ProgressDial } catch (Exception e) { sendErrorToHandler(e); } - } else if (ACTION_QUERY_KEYRING.equals(action)) { + } else if (ACTION_DOWNLOAD_AND_IMPORT_KEYS.equals(action)) { try { + ArrayList entries = data.getParcelableArrayList(DOWNLOAD_KEY_LIST); + String keyServer = data.getString(DOWNLOAD_KEY_SERVER); - /* Input */ -// int queryType = data.getInt(QUERY_KEY_TYPE); - String keyServer = data.getString(QUERY_KEY_SERVER); - -// String queryString = data.getString(QUERY_KEY_STRING); - long keyId = data.getLong(QUERY_KEY_ID); - - /* Operation */ - Bundle resultData = new Bundle(); - + // this downloads the keys and places them into the ImportKeysListEntry entries HkpKeyServer server = new HkpKeyServer(keyServer); -// if (queryType == Id.keyserver.search) { -// ArrayList searchResult = server.search(queryString); -// -// resultData.putParcelableArrayList(RESULT_QUERY_KEY_SEARCH_RESULT, searchResult); -// } else if (queryType == Id.keyserver.get) { - String keyData = server.get(keyId); - resultData.putString(RESULT_QUERY_KEY_DATA, keyData); -// } + for (ImportKeysListEntry entry : entries) { + byte[] downloadedKey = server.get(entry.getKeyId()).getBytes(); - sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, resultData); + /** + * TODO: copied from ImportKeysListLoader + * + * + * this parses the downloaded key + */ + // need to have access to the bufferedInput, so we can reuse it for the possible + // PGPObject chunks after the first one, e.g. files with several consecutive ASCII + // armour blocks + BufferedInputStream bufferedInput = new BufferedInputStream(new ByteArrayInputStream(downloadedKey)); + try { + + // read all available blocks... (asc files can contain many blocks with BEGIN END) + while (bufferedInput.available() > 0) { + InputStream in = PGPUtil.getDecoderStream(bufferedInput); + PGPObjectFactory objectFactory = new PGPObjectFactory(in); + + // go through all objects in this block + Object obj; + while ((obj = objectFactory.nextObject()) != null) { + Log.d(Constants.TAG, "Found class: " + obj.getClass()); + + if (obj instanceof PGPKeyRing) { + PGPKeyRing newKeyring = (PGPKeyRing) obj; + + entry.setBytes(newKeyring.getEncoded()); + } else { + Log.e(Constants.TAG, "Object not recognized as PGPKeyRing!"); + } + } + } + } catch (Exception e) { + Log.e(Constants.TAG, "Exception on parsing key file!", e); + } + } + + Intent importIntent = new Intent(this, KeychainIntentService.class); + importIntent.setAction(ACTION_IMPORT_KEYRING); + Bundle importData = new Bundle(); + importData.putParcelableArrayList(IMPORT_KEY_LIST, entries); + importIntent.putExtra(EXTRA_DATA, importData); + importIntent.putExtra(EXTRA_MESSENGER, mMessenger); + + // now import it with this service + onHandleIntent(importIntent); + + // result is handled in ACTION_IMPORT_KEYRING } catch (Exception e) { sendErrorToHandler(e); } diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptActivity.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptActivity.java index c7b37dd9d..a803e4680 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptActivity.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptActivity.java @@ -271,9 +271,9 @@ public class DecryptActivity extends DrawerActivity { PGPPublicKeyRing key = ProviderHelper.getPGPPublicKeyRingByKeyId( DecryptActivity.this, mSignatureKeyId); if (key != null) { - Intent intent = new Intent(DecryptActivity.this, KeyServerQueryActivity.class); - intent.setAction(KeyServerQueryActivity.ACTION_LOOK_UP_KEY_ID); - intent.putExtra(KeyServerQueryActivity.EXTRA_KEY_ID, mSignatureKeyId); + Intent intent = new Intent(DecryptActivity.this, ImportKeysActivity.class); + intent.setAction(ImportKeysActivity.ACTION_IMPORT_KEY_FROM_KEYSERVER); + intent.putExtra(ImportKeysActivity.EXTRA_KEY_ID, mSignatureKeyId); startActivity(intent); } } @@ -676,7 +676,7 @@ public class DecryptActivity extends DrawerActivity { data.putParcelable(KeychainIntentService.ENCRYPT_PROVIDER_URI, mContentUri); } else if (mDecryptTarget == Id.target.file) { - data.putInt(KeychainIntentService.TARGET, KeychainIntentService.TARGET_FILE); + data.putInt(KeychainIntentService.TARGET, KeychainIntentService.TARGET_URI); Log.d(Constants.TAG, "mInputFilename=" + mInputFilename + ", mOutputFilename=" + mOutputFilename); @@ -826,7 +826,7 @@ public class DecryptActivity extends DrawerActivity { } // this request is returned after LookupUnknownKeyDialogFragment started - // KeyServerQueryActivity and user looked uo key + // ImportKeysActivity and user looked uo key case Id.request.look_up_key_id: { Log.d(Constants.TAG, "Returning from Lookup Key..."); // decrypt again without lookup diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java index c067dadc5..2ba726bfe 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java @@ -628,7 +628,7 @@ public class EncryptActivity extends DrawerActivity { useAsciiArmor = mAsciiArmor.isChecked(); compressionId = ((Choice) mFileCompression.getSelectedItem()).getId(); - data.putInt(KeychainIntentService.TARGET, KeychainIntentService.TARGET_FILE); + data.putInt(KeychainIntentService.TARGET, KeychainIntentService.TARGET_URI); Log.d(Constants.TAG, "mInputFilename=" + mInputFilename + ", mOutputFilename=" + mOutputFilename); diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java index 1d26c071a..bf534012f 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java @@ -18,10 +18,10 @@ package org.sufficientlysecure.keychain.ui; import java.util.ArrayList; -import java.util.List; import java.util.Locale; import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.Id; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; import org.sufficientlysecure.keychain.service.KeychainIntentService; @@ -270,9 +270,9 @@ public class ImportKeysActivity extends DrawerActivity implements OnNavigationLi return; } - Intent queryIntent = new Intent(this, KeyServerQueryActivity.class); - queryIntent.setAction(KeyServerQueryActivity.ACTION_LOOK_UP_KEY_ID); - queryIntent.putExtra(KeyServerQueryActivity.EXTRA_FINGERPRINT, fingerprint); + Intent queryIntent = new Intent(this, ImportKeysActivity.class); + queryIntent.setAction(ImportKeysActivity.ACTION_IMPORT_KEY_FROM_KEYSERVER); + queryIntent.putExtra(ImportKeysActivity.EXTRA_FINGERPRINT, fingerprint); startActivity(queryIntent); } @@ -338,6 +338,63 @@ public class ImportKeysActivity extends DrawerActivity implements OnNavigationLi // } // } + + // Message is received after importing is done in ApgService + KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler(this, + R.string.progress_importing, ProgressDialog.STYLE_HORIZONTAL) { + public void handleMessage(Message message) { + // handle messages by standard ApgHandler first + super.handleMessage(message); + + if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) { + // get returned data bundle + Bundle returnData = message.getData(); + + int added = returnData.getInt(KeychainIntentService.RESULT_IMPORT_ADDED); + int updated = returnData + .getInt(KeychainIntentService.RESULT_IMPORT_UPDATED); + int bad = returnData.getInt(KeychainIntentService.RESULT_IMPORT_BAD); + String toastMessage; + if (added > 0 && updated > 0) { + String addedStr = getResources().getQuantityString( + R.plurals.keys_added_and_updated_1, added, added); + String updatedStr = getResources().getQuantityString( + R.plurals.keys_added_and_updated_2, updated, updated); + toastMessage = addedStr + updatedStr; + } else if (added > 0) { + toastMessage = getResources().getQuantityString(R.plurals.keys_added, + added, added); + } else if (updated > 0) { + toastMessage = getResources().getQuantityString(R.plurals.keys_updated, + updated, updated); + } else { + toastMessage = getString(R.string.no_keys_added_or_updated); + } + Toast.makeText(ImportKeysActivity.this, toastMessage, Toast.LENGTH_SHORT) + .show(); + if (bad > 0) { + AlertDialog.Builder alert = new AlertDialog.Builder( + ImportKeysActivity.this); + + alert.setIcon(android.R.drawable.ic_dialog_alert); + alert.setTitle(R.string.warning); + + alert.setMessage(ImportKeysActivity.this.getResources() + .getQuantityString(R.plurals.bad_keys_encountered, bad, bad)); + + alert.setPositiveButton(android.R.string.ok, + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + dialog.cancel(); + } + }); + alert.setCancelable(true); + alert.create().show(); + } + } + } + }; + /** * Import keys with mImportData */ @@ -353,85 +410,12 @@ public class ImportKeysActivity extends DrawerActivity implements OnNavigationLi // fill values for this action Bundle data = new Bundle(); - // get selected key ids - List listEntries = mListFragment.getData(); - ArrayList selectedKeyIds = new ArrayList(); - for (ImportKeysListEntry entry : listEntries) { - if (entry.isSelected()) { - selectedKeyIds.add(entry.keyId); - } - } - - data.putSerializable(KeychainIntentService.IMPORT_KEY_LIST, selectedKeyIds); - - if (mListFragment.getKeyBytes() != null) { - data.putInt(KeychainIntentService.TARGET, KeychainIntentService.TARGET_BYTES); - data.putByteArray(KeychainIntentService.IMPORT_BYTES, mListFragment.getKeyBytes()); - } else { - data.putInt(KeychainIntentService.TARGET, KeychainIntentService.TARGET_FILE); - intent.setData(mListFragment.getDataUri()); - } + // get selected key entries + ArrayList selectedEntries = mListFragment.getSelectedData(); + data.putParcelableArrayList(KeychainIntentService.IMPORT_KEY_LIST, selectedEntries); intent.putExtra(KeychainIntentService.EXTRA_DATA, data); - // Message is received after importing is done in ApgService - KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler(this, - R.string.progress_importing, ProgressDialog.STYLE_HORIZONTAL) { - public void handleMessage(Message message) { - // handle messages by standard ApgHandler first - super.handleMessage(message); - - if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) { - // get returned data bundle - Bundle returnData = message.getData(); - - int added = returnData.getInt(KeychainIntentService.RESULT_IMPORT_ADDED); - int updated = returnData - .getInt(KeychainIntentService.RESULT_IMPORT_UPDATED); - int bad = returnData.getInt(KeychainIntentService.RESULT_IMPORT_BAD); - String toastMessage; - if (added > 0 && updated > 0) { - String addedStr = getResources().getQuantityString( - R.plurals.keys_added_and_updated_1, added, added); - String updatedStr = getResources().getQuantityString( - R.plurals.keys_added_and_updated_2, updated, updated); - toastMessage = addedStr + updatedStr; - } else if (added > 0) { - toastMessage = getResources().getQuantityString(R.plurals.keys_added, - added, added); - } else if (updated > 0) { - toastMessage = getResources().getQuantityString(R.plurals.keys_updated, - updated, updated); - } else { - toastMessage = getString(R.string.no_keys_added_or_updated); - } - Toast.makeText(ImportKeysActivity.this, toastMessage, Toast.LENGTH_SHORT) - .show(); - if (bad > 0) { - AlertDialog.Builder alert = new AlertDialog.Builder( - ImportKeysActivity.this); - - alert.setIcon(android.R.drawable.ic_dialog_alert); - alert.setTitle(R.string.warning); - - alert.setMessage(ImportKeysActivity.this.getResources() - .getQuantityString(R.plurals.bad_keys_encountered, bad, bad)); - - alert.setPositiveButton(android.R.string.ok, - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - dialog.cancel(); - } - }); - alert.setCancelable(true); - alert.create().show(); - } - } - } - - ; - }; - // Create a new Messenger for the communication back Messenger messenger = new Messenger(saveHandler); intent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger); @@ -442,7 +426,31 @@ public class ImportKeysActivity extends DrawerActivity implements OnNavigationLi // start service with intent startService(intent); } else if (mListFragment.getServerQuery() != null) { - // TODO! + // Send all information needed to service to query keys in other thread + Intent intent = new Intent(this, KeychainIntentService.class); + + intent.setAction(KeychainIntentService.ACTION_DOWNLOAD_AND_IMPORT_KEYS); + + // fill values for this action + Bundle data = new Bundle(); + + data.putString(KeychainIntentService.DOWNLOAD_KEY_SERVER, mListFragment.getKeyServer()); + + // get selected key entries + ArrayList selectedEntries = mListFragment.getSelectedData(); + data.putParcelableArrayList(KeychainIntentService.DOWNLOAD_KEY_LIST, selectedEntries); + + intent.putExtra(KeychainIntentService.EXTRA_DATA, data); + + // Create a new Messenger for the communication back + Messenger messenger = new Messenger(saveHandler); + intent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger); + + // show progress dialog + saveHandler.showProgressDialog(this); + + // start service with intent + startService(intent); } else { Toast.makeText(this, R.string.error_nothing_import, Toast.LENGTH_LONG).show(); } diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java index 9c9dda0b4..ea9f507db 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java @@ -21,6 +21,7 @@ import java.io.ByteArrayInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; +import java.util.ArrayList; import java.util.List; import org.sufficientlysecure.keychain.Constants; @@ -72,10 +73,18 @@ public class ImportKeysListFragment extends SherlockListFragment implements return mServerQuery; } + public String getKeyServer() { + return mKeyServer; + } + public List getData() { return mAdapter.getData(); } + public ArrayList getSelectedData() { + return mAdapter.getSelectedData(); + } + /** * Creates new instance of this fragment */ diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyServerQueryActivity.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyServerQueryActivity.java deleted file mode 100644 index 4be096a7d..000000000 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyServerQueryActivity.java +++ /dev/null @@ -1,391 +0,0 @@ -/* - * Copyright (C) 2012-2014 Dominik Schürmann - * Copyright (C) 2010 Thialfihar - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.sufficientlysecure.keychain.ui; - -import android.app.Activity; -import android.app.ProgressDialog; -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; -import android.os.Message; -import android.os.Messenger; -import android.view.KeyEvent; -import android.view.LayoutInflater; -import android.view.View; -import android.view.View.OnClickListener; -import android.view.ViewGroup; -import android.view.inputmethod.EditorInfo; -import android.widget.AdapterView; -import android.widget.AdapterView.OnItemClickListener; -import android.widget.ArrayAdapter; -import android.widget.BaseAdapter; -import android.widget.Button; -import android.widget.EditText; -import android.widget.LinearLayout; -import android.widget.LinearLayout.LayoutParams; -import android.widget.ListView; -import android.widget.Spinner; -import android.widget.TextView; -import android.widget.TextView.OnEditorActionListener; -import android.widget.Toast; -import com.actionbarsherlock.app.SherlockFragmentActivity; -import com.actionbarsherlock.view.MenuItem; -import java.util.ArrayList; -import java.util.List; -import org.sufficientlysecure.keychain.Constants; -import org.sufficientlysecure.keychain.Id; -import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.helper.Preferences; -import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; -import org.sufficientlysecure.keychain.service.KeychainIntentService; -import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; -import org.sufficientlysecure.keychain.util.KeyServer.KeyInfo; -import org.sufficientlysecure.keychain.util.Log; - -public class KeyServerQueryActivity extends SherlockFragmentActivity { - - // possible intent actions for this activity - public static final String ACTION_LOOK_UP_KEY_ID = Constants.INTENT_PREFIX + "LOOK_UP_KEY_ID"; - - public static final String ACTION_LOOK_UP_KEY_ID_AND_RETURN = Constants.INTENT_PREFIX - + "LOOK_UP_KEY_ID_AND_RETURN"; - - public static final String EXTRA_KEY_ID = "key_id"; - public static final String EXTRA_FINGERPRINT = "fingerprint"; - - public static final String RESULT_EXTRA_TEXT = "text"; - - private ListView mList; - private EditText mQuery; - private Button mSearch; - private Spinner mKeyServer; - - private KeyInfoListAdapter mAdapter; - - private int mQueryType; - private String mQueryString; - private long mQueryId; - - private volatile List mSearchResult; - - private volatile String mKeyData; - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - - case android.R.id.home: - // app icon in Action Bar clicked; go home - Intent intent = new Intent(this, KeyListPublicActivity.class); - intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); - startActivity(intent); - return true; - - default: - break; - - } - return false; - } - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - setContentView(R.layout.key_server_query); - - mQuery = (EditText) findViewById(R.id.query); - mSearch = (Button) findViewById(R.id.btn_search); - mList = (ListView) findViewById(R.id.list); - mAdapter = new KeyInfoListAdapter(this); - mList.setAdapter(mAdapter); - - mKeyServer = (Spinner) findViewById(R.id.sign_key_keyserver); - ArrayAdapter adapter = new ArrayAdapter(this, - android.R.layout.simple_spinner_item, Preferences.getPreferences(this) - .getKeyServers()); - adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); - mKeyServer.setAdapter(adapter); - if (adapter.getCount() > 0) { - mKeyServer.setSelection(0); - } else { - mSearch.setEnabled(false); - } - - mList.setOnItemClickListener(new OnItemClickListener() { - @Override - public void onItemClick(AdapterView adapter, View view, int position, long keyId) { - get(keyId); - } - }); - - mSearch.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - String query = mQuery.getText().toString(); - search(query); - } - }); - mQuery.setOnEditorActionListener(new OnEditorActionListener() { - @Override - public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { - if (actionId == EditorInfo.IME_ACTION_SEARCH) { - String query = mQuery.getText().toString(); - search(query); - return false; // FIXME This is a hack to hide a keyboard - // after search http://tinyurl.com/pwdc3q9 - - } - return false; - } - }); - - Intent intent = getIntent(); - String action = intent.getAction(); - if (ACTION_LOOK_UP_KEY_ID.equals(action) || ACTION_LOOK_UP_KEY_ID_AND_RETURN.equals(action)) { - long keyId = intent.getLongExtra(EXTRA_KEY_ID, 0); - if (keyId != 0) { - String query = "0x" + PgpKeyHelper.convertKeyToHex(keyId); - mQuery.setText(query); - search(query); - } - String fingerprint = intent.getStringExtra(EXTRA_FINGERPRINT); - if (fingerprint != null) { - fingerprint = "0x" + fingerprint; - mQuery.setText(fingerprint); - search(fingerprint); - } - } - } - - private void search(String query) { - mQueryType = Id.keyserver.search; - mQueryString = query; - mAdapter.setKeys(new ArrayList()); - - start(); - } - - private void get(long keyId) { - mQueryType = Id.keyserver.get; - mQueryId = keyId; - - start(); - } - - private void start() { - Log.d(Constants.TAG, "start search with service"); - - // Send all information needed to service to query keys in other thread - Intent intent = new Intent(this, KeychainIntentService.class); - - intent.setAction(KeychainIntentService.ACTION_QUERY_KEYRING); - - // fill values for this action - Bundle data = new Bundle(); - - String server = (String) mKeyServer.getSelectedItem(); - data.putString(KeychainIntentService.QUERY_KEY_SERVER, server); - -// data.putInt(KeychainIntentService.QUERY_KEY_TYPE, mQueryType); - -// if (mQueryType == Id.keyserver.search) { -// data.putString(KeychainIntentService.QUERY_KEY_STRING, mQueryString); -// } else if (mQueryType == Id.keyserver.get) { -// data.putLong(KeychainIntentService.QUERY_KEY_ID, mQueryId); -// } - - intent.putExtra(KeychainIntentService.EXTRA_DATA, data); - - // Message is received after querying is done in ApgService - KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler(this, - R.string.progress_querying, ProgressDialog.STYLE_SPINNER) { - @Override - public void handleMessage(Message message) { - // handle messages by standard ApgHandler first - super.handleMessage(message); - - if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) { - // get returned data bundle - Bundle returnData = message.getData(); - - if (mQueryType == Id.keyserver.search) { - mSearchResult = returnData - .getParcelableArrayList(KeychainIntentService.RESULT_QUERY_KEY_SEARCH_RESULT); - } else if (mQueryType == Id.keyserver.get) { - mKeyData = returnData - .getString(KeychainIntentService.RESULT_QUERY_KEY_DATA); - } - - // TODO: IMPROVE CODE!!! some global variables can be - // avoided!!! - if (mQueryType == Id.keyserver.search) { - if (mSearchResult != null) { - Toast.makeText( - KeyServerQueryActivity.this, - getResources().getQuantityString(R.plurals.keys_found, - mSearchResult.size(), mSearchResult.size()), - Toast.LENGTH_SHORT).show(); - mAdapter.setKeys(mSearchResult); - } - } else if (mQueryType == Id.keyserver.get) { - Intent orgIntent = getIntent(); - if (ACTION_LOOK_UP_KEY_ID_AND_RETURN.equals(orgIntent.getAction())) { - if (mKeyData != null) { - Intent intent = new Intent(); - intent.putExtra(RESULT_EXTRA_TEXT, mKeyData); - setResult(RESULT_OK, intent); - } else { - setResult(RESULT_CANCELED); - } - finish(); - } else { - if (mKeyData != null) { - Intent intent = new Intent(KeyServerQueryActivity.this, - ImportKeysActivity.class); - intent.setAction(ImportKeysActivity.ACTION_IMPORT_KEY); - intent.putExtra(ImportKeysActivity.EXTRA_KEY_BYTES, - mKeyData.getBytes()); - startActivity(intent); - } - } - } - - } - }; - }; - - // Create a new Messenger for the communication back - Messenger messenger = new Messenger(saveHandler); - intent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger); - - // show progress dialog - saveHandler.showProgressDialog(this); - - // start service with intent - startService(intent); - } - - public class KeyInfoListAdapter extends BaseAdapter { - protected LayoutInflater mInflater; - - protected Activity mActivity; - - protected List mKeys; - - public KeyInfoListAdapter(Activity activity) { - mActivity = activity; - mInflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE); - mKeys = new ArrayList(); - } - - public void setKeys(List keys) { - mKeys = keys; - notifyDataSetChanged(); - } - - @Override - public boolean hasStableIds() { - return true; - } - - @Override - public int getCount() { - return mKeys.size(); - } - - @Override - public Object getItem(int position) { - return mKeys.get(position); - } - - @Override - public long getItemId(int position) { - return mKeys.get(position).keyId; - } - - @Override - public View getView(int position, View convertView, ViewGroup parent) { - KeyInfo keyInfo = mKeys.get(position); - - View view = mInflater.inflate(R.layout.key_server_query_result_item, null); - - TextView mainUserId = (TextView) view.findViewById(R.id.mainUserId); - mainUserId.setText(R.string.user_id_no_name); - TextView mainUserIdRest = (TextView) view.findViewById(R.id.mainUserIdRest); - mainUserIdRest.setText(""); - TextView keyId = (TextView) view.findViewById(R.id.keyId); - keyId.setText(R.string.no_key); - TextView algorithm = (TextView) view.findViewById(R.id.algorithm); - algorithm.setText(""); - TextView status = (TextView) view.findViewById(R.id.status); - status.setText(""); - - String userId = keyInfo.userIds.get(0); - if (userId != null) { - String chunks[] = userId.split(" <", 2); - userId = chunks[0]; - if (chunks.length > 1) { - mainUserIdRest.setText("<" + chunks[1]); - } - mainUserId.setText(userId); - } - - keyId.setText(PgpKeyHelper.convertKeyIdToHex(keyInfo.keyId)); - - if (mainUserIdRest.getText().length() == 0) { - mainUserIdRest.setVisibility(View.GONE); - } - - algorithm.setText("" + keyInfo.size + "/" + keyInfo.algorithm); - - if (keyInfo.revoked != null) { - status.setText("revoked"); - } else { - status.setVisibility(View.GONE); - } - - LinearLayout ll = (LinearLayout) view.findViewById(R.id.list); - if (keyInfo.userIds.size() == 1) { - ll.setVisibility(View.GONE); - } else { - boolean first = true; - boolean second = true; - for (String uid : keyInfo.userIds) { - if (first) { - first = false; - continue; - } - if (!second) { - View sep = new View(mActivity); - sep.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, 1)); - sep.setBackgroundResource(android.R.drawable.divider_horizontal_dark); - ll.addView(sep); - } - TextView uidView = (TextView) mInflater.inflate( - R.layout.key_server_query_result_user_id, null); - uidView.setText(uid); - ll.addView(uidView); - second = false; - } - } - - return view; - } - } -} diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java index 74aac1d3c..b837a09d0 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java @@ -397,9 +397,9 @@ public class ViewKeyActivity extends SherlockFragmentActivity implements return; } - Intent queryIntent = new Intent(this, KeyServerQueryActivity.class); - queryIntent.setAction(KeyServerQueryActivity.ACTION_LOOK_UP_KEY_ID_AND_RETURN); - queryIntent.putExtra(KeyServerQueryActivity.EXTRA_KEY_ID, updateKeyId); + Intent queryIntent = new Intent(this, ImportKeysActivity.class); + queryIntent.setAction(ImportKeysActivity.ACTION_IMPORT_KEY_FROM_KEYSERVER); + queryIntent.putExtra(ImportKeysActivity.EXTRA_KEY_ID, updateKeyId); // TODO: lookup?? startActivityForResult(queryIntent, Id.request.look_up_key_id); diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysAdapter.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysAdapter.java index 8170defe4..a850fc020 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysAdapter.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysAdapter.java @@ -17,6 +17,7 @@ package org.sufficientlysecure.keychain.ui.adapter; +import java.util.ArrayList; import java.util.List; import org.sufficientlysecure.keychain.R; @@ -69,6 +70,15 @@ public class ImportKeysAdapter extends ArrayAdapter { return data; } + public ArrayList getSelectedData() { + ArrayList selectedData = new ArrayList(); + for (ImportKeysListEntry entry : data) { + if (entry.isSelected()) + selectedData.add(entry); + } + return selectedData; + } + @Override public boolean hasStableIds() { return true; diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListEntry.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListEntry.java index 2ad9cc593..5094e8abd 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListEntry.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListEntry.java @@ -17,6 +17,10 @@ package org.sufficientlysecure.keychain.ui.adapter; +import android.os.Parcel; +import android.os.Parcelable; + +import java.io.IOException; import java.io.Serializable; import java.util.ArrayList; import java.util.Date; @@ -24,15 +28,16 @@ import java.util.Date; import org.spongycastle.openpgp.PGPKeyRing; import org.spongycastle.openpgp.PGPPublicKey; import org.spongycastle.openpgp.PGPSecretKeyRing; +import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; -import org.sufficientlysecure.keychain.util.AlgorithmNames; import org.sufficientlysecure.keychain.util.IterableIterator; +import org.sufficientlysecure.keychain.util.Log; -public class ImportKeysListEntry implements Serializable { +public class ImportKeysListEntry implements Serializable, Parcelable { private static final long serialVersionUID = -7797972103284992662L; public ArrayList userIds; - public long keyId; + public long keyId; public boolean revoked; public Date date; // TODO: not displayed public String fingerPrint; @@ -40,10 +45,82 @@ public class ImportKeysListEntry implements Serializable { public int bitStrength; public String algorithm; public boolean secretKey; - AlgorithmNames algorithmNames; private boolean selected; + private byte[] bytes = new byte[] {}; + + public ImportKeysListEntry(ImportKeysListEntry b) { + this.userIds = b.userIds; + this.keyId = b.keyId; + this.revoked = b.revoked; + this.date = b.date; + this.fingerPrint = b.fingerPrint; + this.hexKeyId = b.hexKeyId; + this.bitStrength = b.bitStrength; + this.algorithm = b.algorithm; + this.secretKey = b.secretKey; + this.selected = b.selected; + this.bytes = b.bytes; + } + + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeStringList(userIds); + dest.writeLong(keyId); + dest.writeByte((byte) (revoked ? 1 : 0)); + dest.writeSerializable(date); + dest.writeString(fingerPrint); + dest.writeString(hexKeyId); + dest.writeInt(bitStrength); + dest.writeString(algorithm); + dest.writeByte((byte) (secretKey ? 1 : 0)); + dest.writeByte((byte) (selected ? 1 : 0)); + dest.writeInt(bytes.length); + dest.writeByteArray(bytes); + } + + public static final Creator CREATOR = new Creator() { + public ImportKeysListEntry createFromParcel(final Parcel source) { + ImportKeysListEntry vr = new ImportKeysListEntry(); + vr.userIds = new ArrayList(); + source.readStringList(vr.userIds); + vr.keyId = source.readLong(); + vr.revoked = source.readByte() == 1; + vr.date = (Date) source.readSerializable(); + vr.fingerPrint = source.readString(); + vr.hexKeyId = source.readString(); + vr.bitStrength = source.readInt(); + vr.algorithm = source.readString(); + vr.secretKey = source.readByte() == 1; + vr.selected = source.readByte() == 1; + vr.bytes = new byte[source.readInt()]; + source.readByteArray(vr.bytes); + + return vr; + } + + public ImportKeysListEntry[] newArray(final int size) { + return new ImportKeysListEntry[size]; + } + }; + + public long getKeyId() { + return keyId; + } + + public byte[] getBytes() { + return bytes; + } + + public void setBytes(byte[] bytes) { + this.bytes = bytes; + } + /** * Constructor for later querying from keyserver */ @@ -62,11 +139,16 @@ public class ImportKeysListEntry implements Serializable { /** * Constructor based on key object, used for import from NFC, QR Codes, files - * - * @param pgpKey */ @SuppressWarnings("unchecked") public ImportKeysListEntry(PGPKeyRing pgpKeyRing) { + // save actual key object into entry, used to import it later + try { + this.bytes = pgpKeyRing.getEncoded(); + } catch (IOException e) { + Log.e(Constants.TAG, "IOException on pgpKeyRing.getEncoded()", e); + } + // selected is default this.selected = true; diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/LookupUnknownKeyDialogFragment.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/LookupUnknownKeyDialogFragment.java index d018f4b8e..dbbc87a1a 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/LookupUnknownKeyDialogFragment.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/LookupUnknownKeyDialogFragment.java @@ -21,7 +21,7 @@ import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.Id; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; -import org.sufficientlysecure.keychain.ui.KeyServerQueryActivity; +import org.sufficientlysecure.keychain.ui.ImportKeysActivity; import org.sufficientlysecure.keychain.util.Log; import android.app.Activity; @@ -90,9 +90,9 @@ public class LookupUnknownKeyDialogFragment extends SherlockDialogFragment { sendMessageToHandler(MESSAGE_OKAY); - Intent intent = new Intent(activity, KeyServerQueryActivity.class); - intent.setAction(KeyServerQueryActivity.ACTION_LOOK_UP_KEY_ID); - intent.putExtra(KeyServerQueryActivity.EXTRA_KEY_ID, unknownKeyId); + Intent intent = new Intent(activity, ImportKeysActivity.class); + intent.setAction(ImportKeysActivity.ACTION_IMPORT_KEY_FROM_KEYSERVER); + intent.putExtra(ImportKeysActivity.EXTRA_KEY_ID, unknownKeyId); startActivityForResult(intent, Id.request.look_up_key_id); } }); diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/util/KeyServer.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/util/KeyServer.java index 832f4f62c..072affb1f 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/util/KeyServer.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/util/KeyServer.java @@ -47,49 +47,6 @@ public abstract class KeyServer { private static final long serialVersionUID = -507574859137295530L; } - static public class KeyInfo implements Serializable, Parcelable { - private static final long serialVersionUID = -7797972113284992662L; - public ArrayList userIds; - public String revoked; - public Date date; - public String fingerPrint; - public long keyId; - public int size; - public String algorithm; - - public KeyInfo() { - userIds = new ArrayList(); - } - - public KeyInfo(Parcel in) { - this(); - - in.readStringList(this.userIds); - this.revoked = in.readString(); - this.date = (Date) in.readSerializable(); - this.fingerPrint = in.readString(); - this.keyId = in.readLong(); - this.size = in.readInt(); - this.algorithm = in.readString(); - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeStringList(userIds); - dest.writeString(revoked); - dest.writeSerializable(date); - dest.writeString(fingerPrint); - dest.writeLong(keyId); - dest.writeInt(size); - dest.writeString(algorithm); - } - } - abstract List search(String query) throws QueryException, TooManyResponses, InsufficientQuery; diff --git a/OpenPGP-Keychain/src/main/res/layout/import_keys_server_fragment.xml b/OpenPGP-Keychain/src/main/res/layout/import_keys_server_fragment.xml index d5fa3e290..2438dd785 100644 --- a/OpenPGP-Keychain/src/main/res/layout/import_keys_server_fragment.xml +++ b/OpenPGP-Keychain/src/main/res/layout/import_keys_server_fragment.xml @@ -42,13 +42,4 @@ bootstrapbutton:bb_type="default" /> - - \ No newline at end of file diff --git a/OpenPGP-Keychain/src/main/res/layout/key_server_query.xml b/OpenPGP-Keychain/src/main/res/layout/key_server_query.xml deleted file mode 100644 index 5ba90de47..000000000 --- a/OpenPGP-Keychain/src/main/res/layout/key_server_query.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - -