aboutsummaryrefslogtreecommitdiffstats
path: root/OpenKeychain/src/main/java
diff options
context:
space:
mode:
authorVincent Breitmoser <valodim@mugenguild.com>2015-05-11 17:28:34 +0200
committerVincent Breitmoser <valodim@mugenguild.com>2015-05-11 17:28:34 +0200
commit20a6c5ce8a0484cc0ef8f4c5ca1405f60e646e1f (patch)
tree258667acf6ea0c995b47195492d453c7459b31ca /OpenKeychain/src/main/java
parent92ac2ded10548756922a4c22ebae0a19b8862426 (diff)
parent5c44f8400970de5943fd6c5e804dfa394f3deb01 (diff)
downloadopen-keychain-20a6c5ce8a0484cc0ef8f4c5ca1405f60e646e1f.tar.gz
open-keychain-20a6c5ce8a0484cc0ef8f4c5ca1405f60e646e1f.tar.bz2
open-keychain-20a6c5ce8a0484cc0ef8f4c5ca1405f60e646e1f.zip
Merge tag 'v3.2.1' into linked-identities
Version 3.2.1 Conflicts: OpenKeychain/build.gradle OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyAdapter.java OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SelectKeyCursorAdapter.java OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionView.java OpenKeychain/src/main/res/layout/decrypt_text_fragment.xml OpenKeychain/src/main/res/values/strings.xml
Diffstat (limited to 'OpenKeychain/src/main/java')
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/linked/resources/TwitterResource.java6
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ImportExportOperation.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpCertifyOperation.java20
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java11
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java30
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/TemporaryStorageProvider.java39
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java48
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/RemoteService.java75
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/RemoteServiceActivity.java1
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/SelectAllowedKeysActivity.java115
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/CloudImportService.java19
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyActivity.java7
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java140
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyPassphraseFragment.java8
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyStartFragment.java83
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyYubiKeyImportFragment.java (renamed from OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyYubiImportFragment.java)4
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyYubiKeyWaitFragment.java (renamed from OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyYubiWaitFragment.java)2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesActivity.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesFragment.java16
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java77
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextActivity.java19
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextFragment.java33
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java126
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysProxyActivity.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java1
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/MainActivity.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvShareFragment.java53
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyFragment.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyAdapter.java22
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SelectKeyCursorAdapter.java3
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddEmailDialogFragment.java8
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/ProgressDialogFragment.java6
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/KeyFormattingUtils.java11
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionView.java4
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java22
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ContactHelper.java49
40 files changed, 692 insertions, 384 deletions
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/linked/resources/TwitterResource.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/linked/resources/TwitterResource.java
index d6b806ee6..73e3d3643 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/linked/resources/TwitterResource.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/linked/resources/TwitterResource.java
@@ -32,10 +32,10 @@ import java.util.regex.Pattern;
public class TwitterResource extends LinkedTokenResource {
- public static final String[] CERT_PINS = new String[] {
- // antec Class 3 Secure Server CA - G4
+ public static final String[] CERT_PINS = null; /*(new String[] {
+ // Symantec Class 3 Secure Server CA - G4
"513fb9743870b73440418d30930699ff"
- };
+ };*/
final String mHandle;
final String mTweetId;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ImportExportOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ImportExportOperation.java
index b48a1da91..86cfc21a3 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ImportExportOperation.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ImportExportOperation.java
@@ -376,6 +376,8 @@ public class ImportExportOperation extends BaseOperation {
log.add(LogType.MSG_IMPORT_ERROR, 1);
}
+ ContactSyncAdapterService.requestSync();
+
return new ImportKeyResult(resultType, log, newKeys, updatedKeys, badKeys, secret,
importedMasterKeyIdsArray);
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpCertifyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpCertifyOperation.java
index 90ec3053f..bf2349734 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpCertifyOperation.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpCertifyOperation.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) 2015 Dominik Schürmann <dominik@dominikschuermann.de>
+ * Copyright (C) 2015 Vincent Breitmoser <v.breitmoser@mugenguild.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.pgp;
@@ -32,7 +50,7 @@ public class PgpCertifyOperation {
OperationLog log,
int indent,
CertifyAction action,
- Map<ByteBuffer,byte[]> signedHashes,
+ Map<ByteBuffer, byte[]> signedHashes,
Date creationTimestamp) {
if (!secretKey.isMasterKey()) {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java
index 8ecb30cdd..9073e81b9 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java
@@ -178,13 +178,20 @@ public class PgpSignEncryptOperation extends BaseOperation {
case PIN:
case PATTERN:
case PASSPHRASE: {
- if (cryptoInput.getPassphrase() == null) {
+ Passphrase localPassphrase = cryptoInput.getPassphrase();
+ if (localPassphrase == null) {
+ try {
+ localPassphrase = getCachedPassphrase(signingKeyRing.getMasterKeyId(), signingKey.getKeyId());
+ } catch (PassphraseCacheInterface.NoSecretKeyException ignored) {
+ }
+ }
+ if (localPassphrase == null) {
log.add(LogType.MSG_PSE_PENDING_PASSPHRASE, indent + 1);
return new PgpSignEncryptResult(log, RequiredInputParcel.createRequiredSignPassphrase(
signingKeyRing.getMasterKeyId(), signingKey.getKeyId(),
cryptoInput.getSignatureTime()));
}
- if (!signingKey.unlock(cryptoInput.getPassphrase())) {
+ if (!signingKey.unlock(localPassphrase)) {
log.add(LogType.MSG_PSE_ERROR_BAD_PASSPHRASE, indent);
return new PgpSignEncryptResult(PgpSignEncryptResult.RESULT_ERROR, log);
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java
index deb12a146..11d6728e2 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java
@@ -73,7 +73,7 @@ public class KeychainContract {
interface ApiAppsColumns {
String PACKAGE_NAME = "package_name";
- String PACKAGE_SIGNATURE = "package_signature";
+ String PACKAGE_CERTIFICATE = "package_signature";
}
interface ApiAppsAccountsColumns {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java
index 4a162989f..ff661e494 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java
@@ -148,7 +148,7 @@ public class KeychainDatabase extends SQLiteOpenHelper {
"CREATE TABLE IF NOT EXISTS " + Tables.API_APPS + " ("
+ BaseColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
+ ApiAppsColumns.PACKAGE_NAME + " TEXT NOT NULL UNIQUE, "
- + ApiAppsColumns.PACKAGE_SIGNATURE + " BLOB"
+ + ApiAppsColumns.PACKAGE_CERTIFICATE + " BLOB"
+ ")";
private static final String CREATE_API_APPS_ACCOUNTS =
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java
index 655bf19ba..bf56417e9 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java
@@ -50,7 +50,6 @@ import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey.SecretKeyType;
import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKeyRing;
import org.sufficientlysecure.keychain.pgp.KeyRing;
import org.sufficientlysecure.keychain.pgp.PgpConstants;
-import org.sufficientlysecure.keychain.pgp.PgpHelper;
import org.sufficientlysecure.keychain.pgp.Progressable;
import org.sufficientlysecure.keychain.pgp.UncachedKeyRing;
import org.sufficientlysecure.keychain.pgp.UncachedPublicKey;
@@ -1415,7 +1414,7 @@ public class ProviderHelper {
private ContentValues contentValueForApiApps(AppSettings appSettings) {
ContentValues values = new ContentValues();
values.put(ApiApps.PACKAGE_NAME, appSettings.getPackageName());
- values.put(ApiApps.PACKAGE_SIGNATURE, appSettings.getPackageSignature());
+ values.put(ApiApps.PACKAGE_CERTIFICATE, appSettings.getPackageSignature());
return values;
}
@@ -1462,7 +1461,7 @@ public class ProviderHelper {
settings.setPackageName(cursor.getString(
cursor.getColumnIndex(KeychainContract.ApiApps.PACKAGE_NAME)));
settings.setPackageSignature(cursor.getBlob(
- cursor.getColumnIndex(KeychainContract.ApiApps.PACKAGE_SIGNATURE)));
+ cursor.getColumnIndex(KeychainContract.ApiApps.PACKAGE_CERTIFICATE)));
}
} finally {
if (cursor != null) {
@@ -1554,31 +1553,10 @@ public class ProviderHelper {
mContentResolver.insert(uri, values);
}
- public Set<String> getAllFingerprints(Uri uri) {
- Set<String> fingerprints = new HashSet<>();
- String[] projection = new String[]{KeyRings.FINGERPRINT};
- Cursor cursor = mContentResolver.query(uri, projection, null, null, null);
- try {
- if (cursor != null) {
- int fingerprintColumn = cursor.getColumnIndex(KeyRings.FINGERPRINT);
- while (cursor.moveToNext()) {
- fingerprints.add(
- KeyFormattingUtils.convertFingerprintToHex(cursor.getBlob(fingerprintColumn))
- );
- }
- }
- } finally {
- if (cursor != null) {
- cursor.close();
- }
- }
- return fingerprints;
- }
-
- public byte[] getApiAppSignature(String packageName) {
+ public byte[] getApiAppCertificate(String packageName) {
Uri queryUri = ApiApps.buildByPackageNameUri(packageName);
- String[] projection = new String[]{ApiApps.PACKAGE_SIGNATURE};
+ String[] projection = new String[]{ApiApps.PACKAGE_CERTIFICATE};
Cursor cursor = mContentResolver.query(queryUri, projection, null, null, null);
try {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/TemporaryStorageProvider.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/TemporaryStorageProvider.java
index a65d222da..45f806960 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/TemporaryStorageProvider.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/TemporaryStorageProvider.java
@@ -31,10 +31,12 @@ import android.provider.OpenableColumns;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.util.DatabaseUtil;
+import org.sufficientlysecure.keychain.util.Log;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
+import java.util.UUID;
public class TemporaryStorageProvider extends ContentProvider {
@@ -44,7 +46,9 @@ public class TemporaryStorageProvider extends ContentProvider {
private static final String COLUMN_NAME = "name";
private static final String COLUMN_TIME = "time";
private static final Uri BASE_URI = Uri.parse("content://org.sufficientlysecure.keychain.tempstorage/");
- private static final int DB_VERSION = 1;
+ private static final int DB_VERSION = 2;
+
+ private static File cacheDir;
public static Uri createFile(Context context, String targetName) {
ContentValues contentValues = new ContentValues();
@@ -66,7 +70,7 @@ public class TemporaryStorageProvider extends ContentProvider {
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE IF NOT EXISTS " + TABLE_FILES + " (" +
- COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
+ COLUMN_ID + " TEXT PRIMARY KEY, " +
COLUMN_NAME + " TEXT, " +
COLUMN_TIME + " INTEGER" +
");");
@@ -74,28 +78,39 @@ public class TemporaryStorageProvider extends ContentProvider {
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
-
+ Log.d(Constants.TAG, "Upgrading files db from " + oldVersion + " to " + newVersion);
+
+ switch (oldVersion) {
+ case 1:
+ db.execSQL("DROP TABLE IF EXISTS files");
+ db.execSQL("CREATE TABLE IF NOT EXISTS " + TABLE_FILES + " (" +
+ COLUMN_ID + " TEXT PRIMARY KEY, " +
+ COLUMN_NAME + " TEXT, " +
+ COLUMN_TIME + " INTEGER" +
+ ");");
+ }
}
}
- private TemporaryStorageDatabase db;
+ private static TemporaryStorageDatabase db;
private File getFile(Uri uri) throws FileNotFoundException {
try {
- return getFile(Integer.parseInt(uri.getLastPathSegment()));
+ return getFile(uri.getLastPathSegment());
} catch (NumberFormatException e) {
throw new FileNotFoundException();
}
}
- private File getFile(int id) {
- return new File(getContext().getCacheDir(), "temp/" + id);
+ private File getFile(String id) {
+ return new File(cacheDir, "temp/" + id);
}
@Override
public boolean onCreate() {
db = new TemporaryStorageDatabase(getContext());
- return new File(getContext().getCacheDir(), "temp").mkdirs();
+ cacheDir = getContext().getCacheDir();
+ return new File(cacheDir, "temp").mkdirs();
}
@Override
@@ -133,13 +148,15 @@ public class TemporaryStorageProvider extends ContentProvider {
if (!values.containsKey(COLUMN_TIME)) {
values.put(COLUMN_TIME, System.currentTimeMillis());
}
+ String uuid = UUID.randomUUID().toString();
+ values.put(COLUMN_ID, uuid);
int insert = (int) db.getWritableDatabase().insert(TABLE_FILES, null, values);
try {
- getFile(insert).createNewFile();
+ getFile(uuid).createNewFile();
} catch (IOException e) {
return null;
}
- return Uri.withAppendedPath(BASE_URI, Long.toString(insert));
+ return Uri.withAppendedPath(BASE_URI, uuid);
}
@Override
@@ -152,7 +169,7 @@ public class TemporaryStorageProvider extends ContentProvider {
selectionArgs, null, null, null);
if (files != null) {
while (files.moveToNext()) {
- getFile(files.getInt(0)).delete();
+ getFile(files.getString(0)).delete();
}
files.close();
return db.getWritableDatabase().delete(TABLE_FILES, selection, selectionArgs);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java
index c51edf59c..4a8bf9332 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java
@@ -34,6 +34,7 @@ import org.openintents.openpgp.util.OpenPgpApi;
import org.spongycastle.bcpg.CompressionAlgorithmTags;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.operations.results.DecryptVerifyResult;
+import org.sufficientlysecure.keychain.operations.results.OperationResult;
import org.sufficientlysecure.keychain.operations.results.OperationResult.LogEntryParcel;
import org.sufficientlysecure.keychain.operations.results.PgpSignEncryptResult;
import org.sufficientlysecure.keychain.pgp.PgpConstants;
@@ -47,6 +48,7 @@ import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.provider.KeychainDatabase.Tables;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.remote.ui.RemoteServiceActivity;
+import org.sufficientlysecure.keychain.remote.ui.SelectAllowedKeysActivity;
import org.sufficientlysecure.keychain.remote.ui.SelectSignKeyIdActivity;
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
import org.sufficientlysecure.keychain.service.input.RequiredInputParcel;
@@ -205,6 +207,18 @@ public class OpenPgpService extends RemoteService {
PendingIntent.FLAG_CANCEL_CURRENT);
}
+ private PendingIntent getSelectAllowedKeysIntent(Intent data) {
+ // If signature is unknown we return an _additional_ PendingIntent
+ // to retrieve the missing key
+ Intent intent = new Intent(getBaseContext(), SelectAllowedKeysActivity.class);
+ intent.putExtra(SelectAllowedKeysActivity.EXTRA_SERVICE_INTENT, data);
+ intent.setData(KeychainContract.ApiApps.buildByPackageNameUri(getCurrentCallingPackage()));
+
+ return PendingIntent.getActivity(getBaseContext(), 0,
+ intent,
+ PendingIntent.FLAG_CANCEL_CURRENT);
+ }
+
private PendingIntent getShowKeyPendingIntent(long masterKeyId) {
Intent intent = new Intent(getBaseContext(), ViewKeyActivity.class);
intent.setData(KeyRings.buildGenericKeyRingUri(masterKeyId));
@@ -403,6 +417,20 @@ public class OpenPgpService extends RemoteService {
.setAdditionalEncryptId(signKeyId); // add sign key for encryption
}
+ // OLD: Even if the message is not signed: Do self-encrypt to account key id
+ if (data.getIntExtra(OpenPgpApi.EXTRA_API_VERSION, -1) < 7) {
+ String accName = data.getStringExtra(OpenPgpApi.EXTRA_ACCOUNT_NAME);
+ // if no account name is given use name "default"
+ if (TextUtils.isEmpty(accName)) {
+ accName = "default";
+ }
+ final AccountSettings accSettings = getAccSettings(accName);
+ if (accSettings == null || (accSettings.getKeyId() == Constants.key.none)) {
+ return getCreateAccountIntent(data, accName);
+ }
+ pseInput.setAdditionalEncryptId(accSettings.getKeyId());
+ }
+
CryptoInputParcel inputParcel = CryptoInputParcelCacheService.getCryptoInputParcel(this, data);
if (inputParcel == null) {
inputParcel = new CryptoInputParcel();
@@ -476,13 +504,12 @@ public class OpenPgpService extends RemoteService {
}
String currentPkg = getCurrentCallingPackage();
- Set<Long> allowedKeyIds;
+ Set<Long> allowedKeyIds = mProviderHelper.getAllowedKeyIdsForApp(
+ KeychainContract.ApiAllowedKeys.buildBaseUri(currentPkg));
+
if (data.getIntExtra(OpenPgpApi.EXTRA_API_VERSION, -1) < 7) {
- allowedKeyIds = mProviderHelper.getAllKeyIdsForApp(
- ApiAccounts.buildBaseUri(currentPkg));
- } else {
- allowedKeyIds = mProviderHelper.getAllowedKeyIdsForApp(
- KeychainContract.ApiAllowedKeys.buildBaseUri(currentPkg));
+ allowedKeyIds.addAll(mProviderHelper.getAllKeyIdsForApp(
+ ApiAccounts.buildBaseUri(currentPkg)));
}
long inputLength = is.available();
@@ -575,6 +602,15 @@ public class OpenPgpService extends RemoteService {
return result;
} else {
LogEntryParcel errorMsg = pgpResult.getLog().getLast();
+
+ if (errorMsg.mType == OperationResult.LogType.MSG_DC_ERROR_NO_KEY) {
+ // allow user to select allowed keys
+ Intent result = new Intent();
+ result.putExtra(OpenPgpApi.RESULT_INTENT, getSelectAllowedKeysIntent(data));
+ result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED);
+ return result;
+ }
+
throw new Exception(getString(errorMsg.mType.getMsgId()));
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/RemoteService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/RemoteService.java
index 59dafb505..e4d4ac49a 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/RemoteService.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/RemoteService.java
@@ -37,6 +37,8 @@ import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.remote.ui.RemoteServiceActivity;
import org.sufficientlysecure.keychain.util.Log;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
@@ -45,10 +47,10 @@ import java.util.Arrays;
*/
public abstract class RemoteService extends Service {
- public static class WrongPackageSignatureException extends Exception {
+ public static class WrongPackageCertificateException extends Exception {
private static final long serialVersionUID = -8294642703122196028L;
- public WrongPackageSignatureException(String message) {
+ public WrongPackageCertificateException(String message) {
super(message);
}
}
@@ -74,9 +76,9 @@ public abstract class RemoteService extends Service {
String packageName = getCurrentCallingPackage();
Log.d(Constants.TAG, "isAllowed packageName: " + packageName);
- byte[] packageSignature;
+ byte[] packageCertificate;
try {
- packageSignature = getPackageSignature(packageName);
+ packageCertificate = getPackageCertificate(packageName);
} catch (NameNotFoundException e) {
Log.e(Constants.TAG, "Should not happen, returning!", e);
// return error
@@ -91,7 +93,7 @@ public abstract class RemoteService extends Service {
Intent intent = new Intent(getBaseContext(), RemoteServiceActivity.class);
intent.setAction(RemoteServiceActivity.ACTION_REGISTER);
intent.putExtra(RemoteServiceActivity.EXTRA_PACKAGE_NAME, packageName);
- intent.putExtra(RemoteServiceActivity.EXTRA_PACKAGE_SIGNATURE, packageSignature);
+ intent.putExtra(RemoteServiceActivity.EXTRA_PACKAGE_SIGNATURE, packageCertificate);
intent.putExtra(RemoteServiceActivity.EXTRA_DATA, data);
PendingIntent pi = PendingIntent.getActivity(getBaseContext(), 0,
@@ -105,7 +107,7 @@ public abstract class RemoteService extends Service {
return result;
}
- } catch (WrongPackageSignatureException e) {
+ } catch (WrongPackageCertificateException e) {
Log.e(Constants.TAG, "wrong signature!", e);
Intent intent = new Intent(getBaseContext(), RemoteServiceActivity.class);
@@ -127,14 +129,24 @@ public abstract class RemoteService extends Service {
}
}
- private byte[] getPackageSignature(String packageName) throws NameNotFoundException {
+ private byte[] getPackageCertificate(String packageName) throws NameNotFoundException {
PackageInfo pkgInfo = getPackageManager().getPackageInfo(packageName,
PackageManager.GET_SIGNATURES);
- Signature[] signatures = pkgInfo.signatures;
- // TODO: Only first signature?!
- byte[] packageSignature = signatures[0].toByteArray();
+ // NOTE: Silly Android API naming: Signatures are actually certificates
+ Signature[] certificates = pkgInfo.signatures;
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ for (Signature cert : certificates) {
+ try {
+ outputStream.write(cert.toByteArray());
+ } catch (IOException e) {
+ throw new RuntimeException("Should not happen! Writing ByteArrayOutputStream to concat certificates failed");
+ }
+ }
- return packageSignature;
+ // Even if an apk has several certificates, these certificates should never change
+ // Google Play does not allow the introduction of new certificates into an existing apk
+ // Also see this attack: http://stackoverflow.com/a/10567852
+ return outputStream.toByteArray();
}
/**
@@ -144,9 +156,12 @@ public abstract class RemoteService extends Service {
* @return package name
*/
protected String getCurrentCallingPackage() {
- // TODO:
- // callingPackages contains more than one entry when sharedUserId has been used...
String[] callingPackages = getPackageManager().getPackagesForUid(Binder.getCallingUid());
+
+ // NOTE: No support for sharedUserIds
+ // callingPackages contains more than one entry when sharedUserId has been used
+ // No plans to support sharedUserIds due to many bugs connected to them:
+ // http://java-hamster.blogspot.de/2010/05/androids-shareduserid.html
String currentPkg = callingPackages[0];
Log.d(Constants.TAG, "currentPkg: " + currentPkg);
@@ -155,12 +170,12 @@ public abstract class RemoteService extends Service {
/**
* DEPRECATED API
- *
+ * <p/>
* Retrieves AccountSettings from database for the application calling this remote service
*/
protected AccountSettings getAccSettings(String accountName) {
String currentPkg = getCurrentCallingPackage();
- Log.d(Constants.TAG, "getAccSettings accountName: "+ accountName);
+ Log.d(Constants.TAG, "getAccSettings accountName: " + accountName);
Uri uri = KeychainContract.ApiAccounts.buildByPackageAndAccountUri(currentPkg, accountName);
@@ -198,14 +213,14 @@ public abstract class RemoteService extends Service {
*
* @param allowOnlySelf allow only Keychain app itself
* @return true if process is allowed to use this service
- * @throws WrongPackageSignatureException
+ * @throws WrongPackageCertificateException
*/
- private boolean isCallerAllowed(boolean allowOnlySelf) throws WrongPackageSignatureException {
+ private boolean isCallerAllowed(boolean allowOnlySelf) throws WrongPackageCertificateException {
return isUidAllowed(Binder.getCallingUid(), allowOnlySelf);
}
private boolean isUidAllowed(int uid, boolean allowOnlySelf)
- throws WrongPackageSignatureException {
+ throws WrongPackageCertificateException {
if (android.os.Process.myUid() == uid) {
return true;
}
@@ -229,11 +244,9 @@ public abstract class RemoteService extends Service {
/**
* Checks if packageName is a registered app for the API. Does not return true for own package!
*
- * @param packageName
- * @return
- * @throws WrongPackageSignatureException
+ * @throws WrongPackageCertificateException
*/
- private boolean isPackageAllowed(String packageName) throws WrongPackageSignatureException {
+ private boolean isPackageAllowed(String packageName) throws WrongPackageCertificateException {
Log.d(Constants.TAG, "isPackageAllowed packageName: " + packageName);
ArrayList<String> allowedPkgs = mProviderHelper.getRegisteredApiApps();
@@ -244,22 +257,22 @@ public abstract class RemoteService extends Service {
Log.d(Constants.TAG, "Package is allowed! packageName: " + packageName);
// check package signature
- byte[] currentSig;
+ byte[] currentCert;
try {
- currentSig = getPackageSignature(packageName);
+ currentCert = getPackageCertificate(packageName);
} catch (NameNotFoundException e) {
- throw new WrongPackageSignatureException(e.getMessage());
+ throw new WrongPackageCertificateException(e.getMessage());
}
- byte[] storedSig = mProviderHelper.getApiAppSignature(packageName);
- if (Arrays.equals(currentSig, storedSig)) {
+ byte[] storedCert = mProviderHelper.getApiAppCertificate(packageName);
+ if (Arrays.equals(currentCert, storedCert)) {
Log.d(Constants.TAG,
- "Package signature is correct! (equals signature from database)");
+ "Package certificate is correct! (equals certificate from database)");
return true;
} else {
- throw new WrongPackageSignatureException(
- "PACKAGE NOT ALLOWED! Signature wrong! (Signature not " +
- "equals signature from database)");
+ throw new WrongPackageCertificateException(
+ "PACKAGE NOT ALLOWED! Certificate wrong! (Certificate not " +
+ "equals certificate from database)");
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/RemoteServiceActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/RemoteServiceActivity.java
index f312c0d44..5facde64f 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/RemoteServiceActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/RemoteServiceActivity.java
@@ -45,6 +45,7 @@ import org.sufficientlysecure.keychain.util.Log;
import java.util.ArrayList;
+// TODO: make extensible BaseRemoteServiceActivity and extend these cases from it
public class RemoteServiceActivity extends BaseActivity {
public static final String ACTION_REGISTER = Constants.INTENT_PREFIX + "API_ACTIVITY_REGISTER";
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/SelectAllowedKeysActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/SelectAllowedKeysActivity.java
new file mode 100644
index 000000000..767106ff0
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/SelectAllowedKeysActivity.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2015 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.remote.ui;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+import android.view.View;
+
+import org.sufficientlysecure.keychain.Constants;
+import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.provider.KeychainContract;
+import org.sufficientlysecure.keychain.ui.base.BaseActivity;
+import org.sufficientlysecure.keychain.util.Log;
+
+public class SelectAllowedKeysActivity extends BaseActivity {
+
+ public static final String EXTRA_SERVICE_INTENT = "data";
+
+ private Uri mAppUri;
+
+ private AppSettingsAllowedKeysListFragment mAllowedKeysFragment;
+
+ Intent mServiceData;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Inflate a "Done" custom action bar
+ setFullScreenDialogDoneClose(R.string.api_settings_save,
+ new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ save();
+ }
+ },
+ new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ cancel();
+ }
+ });
+
+ Intent intent = getIntent();
+ mServiceData = intent.getParcelableExtra(EXTRA_SERVICE_INTENT);
+ mAppUri = intent.getData();
+ if (mAppUri == null) {
+ Log.e(Constants.TAG, "Intent data missing. Should be Uri of app!");
+ finish();
+ return;
+ } else {
+ Log.d(Constants.TAG, "uri: " + mAppUri);
+ loadData(savedInstanceState, mAppUri);
+ }
+ }
+
+ @Override
+ protected void initLayout() {
+ setContentView(R.layout.api_remote_select_allowed_keys);
+ }
+
+ private void save() {
+ mAllowedKeysFragment.saveAllowedKeys();
+ setResult(Activity.RESULT_OK, mServiceData);
+ finish();
+ }
+
+ private void cancel() {
+ setResult(Activity.RESULT_CANCELED);
+ finish();
+ }
+
+ private void loadData(Bundle savedInstanceState, Uri appUri) {
+ Uri allowedKeysUri = appUri.buildUpon().appendPath(KeychainContract.PATH_ALLOWED_KEYS).build();
+ Log.d(Constants.TAG, "allowedKeysUri: " + allowedKeysUri);
+ startListFragments(savedInstanceState, allowedKeysUri);
+ }
+
+ private void startListFragments(Bundle savedInstanceState, Uri allowedKeysUri) {
+ // However, if we're being restored from a previous state,
+ // then we don't need to do anything and should return or else
+ // we could end up with overlapping fragments.
+ if (savedInstanceState != null) {
+ return;
+ }
+
+ // Create an instance of the fragments
+ mAllowedKeysFragment = AppSettingsAllowedKeysListFragment.newInstance(allowedKeysUri);
+ // Add the fragment to the 'fragment_container' FrameLayout
+ // NOTE: We use commitAllowingStateLoss() to prevent weird crashes!
+ getSupportFragmentManager().beginTransaction()
+ .replace(R.id.api_allowed_keys_list_fragment, mAllowedKeysFragment)
+ .commitAllowingStateLoss();
+ // do it immediately!
+ getSupportFragmentManager().executePendingTransactions();
+ }
+
+}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/CloudImportService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/CloudImportService.java
index 180109297..249586f6d 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/CloudImportService.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/CloudImportService.java
@@ -50,18 +50,18 @@ import java.util.concurrent.atomic.AtomicBoolean;
*/
public class CloudImportService extends Service implements Progressable {
- //required as extras from intent
+ // required as extras from intent
public static final String EXTRA_MESSENGER = "messenger";
public static final String EXTRA_DATA = "data";
- //required by data bundle
+ // required by data bundle
public static final String IMPORT_KEY_LIST = "import_key_list";
public static final String IMPORT_KEY_SERVER = "import_key_server";
// indicates a request to cancel the import
public static final String ACTION_CANCEL = Constants.INTENT_PREFIX + "CANCEL";
- //tells the spawned threads whether the user has requested a cancel
+ // tells the spawned threads whether the user has requested a cancel
private static AtomicBoolean mActionCancelled = new AtomicBoolean(false);
@Override
@@ -86,7 +86,7 @@ public class CloudImportService extends Service implements Progressable {
public KeyImportAccumulator(int totalKeys) {
mTotalKeys = totalKeys;
- //ignore updates from ImportExportOperation for now
+ // ignore updates from ImportExportOperation for now
mImportProgressable = new Progressable() {
@Override
public void setProgress(String message, int current, int total) {
@@ -131,20 +131,17 @@ public class CloudImportService extends Service implements Progressable {
mSecret += result.mSecret;
long[] masterKeyIds = result.getImportedMasterKeyIds();
- for (int i = 0; i < masterKeyIds.length; i++) {
- mImportedMasterKeyIds.add(masterKeyIds[i]);
+ for (long masterKeyId : masterKeyIds) {
+ mImportedMasterKeyIds.add(masterKeyId);
}
// if any key import has been cancelled, set result type to cancelled
// resultType is added to in getConsolidatedKayImport to account for remaining factors
mResultType |= result.getResult() & ImportKeyResult.RESULT_CANCELLED;
-
}
/**
* returns accumulated result of all imports so far
- *
- * @return
*/
public ImportKeyResult getConsolidatedImportKeyResult() {
@@ -205,7 +202,7 @@ public class CloudImportService extends Service implements Progressable {
Bundle data = extras.getBundle(EXTRA_DATA);
final String keyServer = data.getString(IMPORT_KEY_SERVER);
- //keyList being null (in case key list to be reaad from cache) is checked by importKeys
+ // keyList being null (in case key list to be reaad from cache) is checked by importKeys
final ArrayList<ParcelableKeyRing> keyList = data.getParcelableArrayList(IMPORT_KEY_LIST);
// Adding keys to the ThreadPoolExecutor takes time, we don't want to block the main thread
@@ -225,7 +222,7 @@ public class CloudImportService extends Service implements Progressable {
new ParcelableFileCache<>(this, "key_import.pcl");
int totKeys = 0;
Iterator<ParcelableKeyRing> keyListIterator = null;
- //either keyList or cache must be null, no guarantees otherwise
+ // either keyList or cache must be null, no guarantees otherwise
if (keyList == null) {//export from cache, copied from ImportExportOperation.importKeyRings
try {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyActivity.java
index 0b203614b..e0b728bd4 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyActivity.java
@@ -20,7 +20,6 @@ package org.sufficientlysecure.keychain.ui;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
-import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import org.sufficientlysecure.keychain.R;
@@ -84,7 +83,7 @@ public class CreateKeyActivity extends BaseNfcActivity {
String nfcUserId = intent.getStringExtra(EXTRA_NFC_USER_ID);
byte[] nfcAid = intent.getByteArrayExtra(EXTRA_NFC_AID);
- Fragment frag2 = CreateKeyYubiImportFragment.createInstance(
+ Fragment frag2 = CreateKeyYubiKeyImportFragment.createInstance(
nfcFingerprints, nfcAid, nfcUserId);
loadFragment(frag2, FragAction.START);
@@ -99,7 +98,7 @@ public class CreateKeyActivity extends BaseNfcActivity {
if (mFirstTime) {
setTitle(R.string.app_name);
- setActionBarIcon(R.drawable.ic_launcher);
+ mToolbar.setNavigationIcon(null);
mToolbar.setNavigationOnClickListener(null);
} else {
setTitle(R.string.title_manage_my_keys);
@@ -131,7 +130,7 @@ public class CreateKeyActivity extends BaseNfcActivity {
finish();
} catch (PgpKeyNotFoundException e) {
- Fragment frag = CreateKeyYubiImportFragment.createInstance(
+ Fragment frag = CreateKeyYubiKeyImportFragment.createInstance(
scannedFingerprints, nfcAid, userId);
loadFragment(frag, FragAction.TO_RIGHT);
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java
index 85e2f8e9d..597f04d6b 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java
@@ -18,7 +18,6 @@
package org.sufficientlysecure.keychain.ui;
import android.app.Activity;
-import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
@@ -44,18 +43,17 @@ import org.sufficientlysecure.keychain.ui.widget.EmailEditText;
import java.util.ArrayList;
import java.util.List;
+import java.util.regex.Pattern;
public class CreateKeyEmailFragment extends Fragment {
+ private CreateKeyActivity mCreateKeyActivity;
+ private EmailEditText mEmailEdit;
+ private ArrayList<EmailAdapter.ViewModel> mAdditionalEmailModels = new ArrayList<>();
+ private EmailAdapter mEmailAdapter;
- CreateKeyActivity mCreateKeyActivity;
- EmailEditText mEmailEdit;
- RecyclerView mEmailsRecyclerView;
- View mBackButton;
- View mNextButton;
-
- ArrayList<EmailAdapter.ViewModel> mAdditionalEmailModels;
-
- EmailAdapter mEmailAdapter;
+ // NOTE: Do not use more complicated pattern like defined in android.util.Patterns.EMAIL_ADDRESS
+ // EMAIL_ADDRESS fails for mails with umlauts for example
+ private static final Pattern EMAIL_PATTERN = Pattern.compile("^[\\S]+@[\\S]+\\.[a-z]+$");
/**
* Creates new instance of this fragment
@@ -73,14 +71,13 @@ public class CreateKeyEmailFragment extends Fragment {
* Checks if text of given EditText is not empty. If it is empty an error is
* set and the EditText gets the focus.
*
- * @param context
* @param editText
* @return true if EditText is not empty
*/
- private static boolean isEditTextNotEmpty(Context context, EditText editText) {
+ private boolean isMainEmailValid(EditText editText) {
boolean output = true;
- if (editText.getText().length() == 0) {
- editText.setError(context.getString(R.string.create_key_empty));
+ if (!checkEmail(editText.getText().toString(), false)) {
+ editText.setError(getString(R.string.create_key_empty));
editText.requestFocus();
output = false;
} else {
@@ -95,9 +92,9 @@ public class CreateKeyEmailFragment extends Fragment {
View view = inflater.inflate(R.layout.create_key_email_fragment, container, false);
mEmailEdit = (EmailEditText) view.findViewById(R.id.create_key_email);
- mBackButton = view.findViewById(R.id.create_key_back_button);
- mNextButton = view.findViewById(R.id.create_key_next_button);
- mEmailsRecyclerView = (RecyclerView) view.findViewById(R.id.create_key_emails);
+ View backButton = view.findViewById(R.id.create_key_back_button);
+ View nextButton = view.findViewById(R.id.create_key_next_button);
+ RecyclerView emailsRecyclerView = (RecyclerView) view.findViewById(R.id.create_key_emails);
// initial values
mEmailEdit.setText(mCreateKeyActivity.mEmail);
@@ -106,29 +103,21 @@ public class CreateKeyEmailFragment extends Fragment {
if (mCreateKeyActivity.mEmail == null) {
mEmailEdit.requestFocus();
}
- mBackButton.setOnClickListener(new View.OnClickListener() {
+ backButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mCreateKeyActivity.loadFragment(null, FragAction.TO_LEFT);
}
});
- mNextButton.setOnClickListener(new View.OnClickListener() {
+ nextButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
nextClicked();
}
});
- mEmailsRecyclerView.setHasFixedSize(true);
- mEmailsRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
- mEmailsRecyclerView.setItemAnimator(new DefaultItemAnimator());
-
- // initial values
- if (mAdditionalEmailModels == null) {
- mAdditionalEmailModels = new ArrayList<>();
- if (mCreateKeyActivity.mAdditionalEmails != null) {
- mEmailAdapter.addAll(mCreateKeyActivity.mAdditionalEmails);
- }
- }
+ emailsRecyclerView.setHasFixedSize(true);
+ emailsRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
+ emailsRecyclerView.setItemAnimator(new DefaultItemAnimator());
if (mEmailAdapter == null) {
mEmailAdapter = new EmailAdapter(mAdditionalEmailModels, new View.OnClickListener() {
@@ -137,13 +126,77 @@ public class CreateKeyEmailFragment extends Fragment {
addEmail();
}
});
+
+ if (mCreateKeyActivity.mAdditionalEmails != null) {
+ mEmailAdapter.addAll(mCreateKeyActivity.mAdditionalEmails);
+ }
}
- mEmailsRecyclerView.setAdapter(mEmailAdapter);
+ emailsRecyclerView.setAdapter(mEmailAdapter);
return view;
}
+ /**
+ * Checks if a given email is valid
+ *
+ * @param email
+ * @param additionalEmail
+ * @return
+ */
+ private boolean checkEmail(String email, boolean additionalEmail) {
+ // check for email format or if the user did any input
+ if (!isEmailFormatValid(email)) {
+ Notify.create(getActivity(),
+ getString(R.string.create_key_email_invalid_email),
+ Notify.LENGTH_LONG, Notify.Style.ERROR).show(CreateKeyEmailFragment.this);
+ return false;
+ }
+
+ // check for duplicated emails
+ if (!additionalEmail && isEmailDuplicatedInsideAdapter(email) || additionalEmail &&
+ mEmailEdit.getText().length() > 0 && email.equals(mEmailEdit.getText().toString())) {
+ Notify.create(getActivity(),
+ getString(R.string.create_key_email_already_exists_text),
+ Notify.LENGTH_LONG, Notify.Style.ERROR).show(CreateKeyEmailFragment.this);
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Checks the email format
+ * Uses the default Android Email Pattern
+ *
+ * @param email
+ * @return
+ */
+ private boolean isEmailFormatValid(String email) {
+ // check for email format or if the user did any input
+ return !(email.length() == 0 || !EMAIL_PATTERN.matcher(email).matches());
+ }
+
+ /**
+ * Checks for duplicated emails inside the additional email adapter.
+ *
+ * @param email
+ * @return
+ */
+ private boolean isEmailDuplicatedInsideAdapter(String email) {
+ //check for duplicated emails inside the adapter
+ for (EmailAdapter.ViewModel model : mAdditionalEmailModels) {
+ if (email.equals(model.email)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Displays a dialog fragment for the user to input a valid email.
+ */
private void addEmail() {
Handler returnHandler = new Handler() {
@Override
@@ -153,34 +206,17 @@ public class CreateKeyEmailFragment extends Fragment {
String email = data.getString(AddEmailDialogFragment.MESSAGE_DATA_EMAIL);
- if (email.length() > 0 && mEmailEdit.getText().length() > 0 &&
- email.equals(mEmailEdit.getText().toString())) {
- Notify.create(getActivity(),
- getString(R.string.create_key_email_already_exists_text),
- Notify.LENGTH_LONG, Notify.Style.ERROR).show();
- return;
- }
- //check for duplicated emails inside the adapter
- for (EmailAdapter.ViewModel model : mAdditionalEmailModels) {
- if (email.equals(model.email)) {
- Notify.create(getActivity(),
- getString(R.string.create_key_email_already_exists_text),
- Notify.LENGTH_LONG, Notify.Style.ERROR).show();
- return;
- }
+ if (checkEmail(email, true)) {
+ // add new user id
+ mEmailAdapter.add(email);
}
-
- // add new user id
- mEmailAdapter.add(email);
}
}
};
-
// Create a new Messenger for the communication back
Messenger messenger = new Messenger(returnHandler);
AddEmailDialogFragment addEmailDialog = AddEmailDialogFragment.newInstance(messenger);
-
addEmailDialog.show(getActivity().getSupportFragmentManager(), "addEmailDialog");
}
@@ -191,7 +227,7 @@ public class CreateKeyEmailFragment extends Fragment {
}
private void nextClicked() {
- if (isEditTextNotEmpty(getActivity(), mEmailEdit)) {
+ if (isMainEmailValid(mEmailEdit)) {
// save state
mCreateKeyActivity.mEmail = mEmailEdit.getText().toString();
mCreateKeyActivity.mAdditionalEmails = getAdditionalEmails();
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyPassphraseFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyPassphraseFragment.java
index 32173edf7..3379e0a6d 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyPassphraseFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyPassphraseFragment.java
@@ -21,7 +21,6 @@ import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;
-import android.text.Editable;
import android.text.method.HideReturnsTransformationMethod;
import android.text.method.PasswordTransformationMethod;
import android.view.LayoutInflater;
@@ -37,9 +36,6 @@ import org.sufficientlysecure.keychain.ui.CreateKeyActivity.FragAction;
import org.sufficientlysecure.keychain.ui.widget.PassphraseEditText;
import org.sufficientlysecure.keychain.util.Passphrase;
-import java.util.ArrayList;
-import java.util.Arrays;
-
public class CreateKeyPassphraseFragment extends Fragment {
// view
@@ -111,8 +107,8 @@ public class CreateKeyPassphraseFragment extends Fragment {
// initial values
// TODO: using String here is unsafe...
if (mCreateKeyActivity.mPassphrase != null) {
- mPassphraseEdit.setText(Arrays.toString(mCreateKeyActivity.mPassphrase.getCharArray()));
- mPassphraseEditAgain.setText(Arrays.toString(mCreateKeyActivity.mPassphrase.getCharArray()));
+ mPassphraseEdit.setText(new String(mCreateKeyActivity.mPassphrase.getCharArray()));
+ mPassphraseEditAgain.setText(new String(mCreateKeyActivity.mPassphrase.getCharArray()));
}
mPassphraseEdit.requestFocus();
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyStartFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyStartFragment.java
index 3f56949f5..1a844e6e4 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyStartFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyStartFragment.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
+ * Copyright (C) 2014-2015 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
@@ -18,37 +18,20 @@
package org.sufficientlysecure.keychain.ui;
import android.app.Activity;
-import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
-import android.os.Handler;
-import android.os.Message;
-import android.os.Messenger;
import android.support.v4.app.Fragment;
-import android.support.v7.widget.DefaultItemAnimator;
-import android.support.v7.widget.LinearLayoutManager;
-import android.support.v7.widget.RecyclerView;
-import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.Button;
-import android.widget.EditText;
-import android.widget.ImageButton;
import android.widget.TextView;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.ui.CreateKeyActivity.FragAction;
-import org.sufficientlysecure.keychain.ui.dialog.AddEmailDialogFragment;
-import org.sufficientlysecure.keychain.ui.dialog.SetPassphraseDialogFragment;
-import org.sufficientlysecure.keychain.ui.widget.EmailEditText;
import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.Preferences;
-import java.util.ArrayList;
-import java.util.List;
-
public class CreateKeyStartFragment extends Fragment {
CreateKeyActivity mCreateKeyActivity;
@@ -56,8 +39,8 @@ public class CreateKeyStartFragment extends Fragment {
View mCreateKey;
View mImportKey;
View mYubiKey;
- TextView mCancel;
- public static final int REQUEST_CODE_CREATE_OR_IMPORT_KEY = 0x00007012;
+ TextView mSkipOrCancel;
+ public static final int REQUEST_CODE_IMPORT_KEY = 0x00007012;
/**
* Creates new instance of this fragment
@@ -79,12 +62,12 @@ public class CreateKeyStartFragment extends Fragment {
mCreateKey = view.findViewById(R.id.create_key_create_key_button);
mImportKey = view.findViewById(R.id.create_key_import_button);
mYubiKey = view.findViewById(R.id.create_key_yubikey_button);
- mCancel = (TextView) view.findViewById(R.id.create_key_cancel);
+ mSkipOrCancel = (TextView) view.findViewById(R.id.create_key_cancel);
if (mCreateKeyActivity.mFirstTime) {
- mCancel.setText(R.string.first_time_skip);
+ mSkipOrCancel.setText(R.string.first_time_skip);
} else {
- mCancel.setText(R.string.btn_do_not_save);
+ mSkipOrCancel.setText(R.string.btn_do_not_save);
}
mCreateKey.setOnClickListener(new View.OnClickListener() {
@@ -98,7 +81,7 @@ public class CreateKeyStartFragment extends Fragment {
mYubiKey.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- CreateKeyYubiWaitFragment frag = new CreateKeyYubiWaitFragment();
+ CreateKeyYubiKeyWaitFragment frag = new CreateKeyYubiKeyWaitFragment();
mCreateKeyActivity.loadFragment(frag, FragAction.TO_RIGHT);
}
});
@@ -108,48 +91,48 @@ public class CreateKeyStartFragment extends Fragment {
public void onClick(View v) {
Intent intent = new Intent(mCreateKeyActivity, ImportKeysActivity.class);
intent.setAction(ImportKeysActivity.ACTION_IMPORT_KEY_FROM_FILE_AND_RETURN);
- startActivityForResult(intent, REQUEST_CODE_CREATE_OR_IMPORT_KEY);
+ startActivityForResult(intent, REQUEST_CODE_IMPORT_KEY);
}
});
- mCancel.setOnClickListener(new View.OnClickListener() {
+ mSkipOrCancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- finishSetup(null);
+ if (mCreateKeyActivity.mFirstTime) {
+ Preferences prefs = Preferences.getPreferences(mCreateKeyActivity);
+ prefs.setFirstTime(false);
+ Intent intent = new Intent(mCreateKeyActivity, MainActivity.class);
+ startActivity(intent);
+ mCreateKeyActivity.finish();
+ } else {
+ // just finish activity and return data
+ mCreateKeyActivity.setResult(Activity.RESULT_CANCELED);
+ mCreateKeyActivity.finish();
+ }
}
});
return view;
}
-
- private void finishSetup(Intent srcData) {
- if (mCreateKeyActivity.mFirstTime) {
- Preferences prefs = Preferences.getPreferences(mCreateKeyActivity);
- prefs.setFirstTime(false);
- }
- Intent intent = new Intent(mCreateKeyActivity, MainActivity.class);
- // give intent through to display notify
- if (srcData != null) {
- intent.putExtras(srcData);
- }
- startActivity(intent);
- mCreateKeyActivity.finish();
- }
-
- // workaround for https://code.google.com/p/android/issues/detail?id=61394
-// @Override
-// public boolean onKeyDown(int keyCode, KeyEvent event) {
-// return keyCode == KeyEvent.KEYCODE_MENU || super.onKeyDown(keyCode, event);
-// }
-
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
- if (requestCode == REQUEST_CODE_CREATE_OR_IMPORT_KEY) {
+ if (requestCode == REQUEST_CODE_IMPORT_KEY) {
if (resultCode == Activity.RESULT_OK) {
- finishSetup(data);
+ if (mCreateKeyActivity.mFirstTime) {
+ Preferences prefs = Preferences.getPreferences(mCreateKeyActivity);
+ prefs.setFirstTime(false);
+ Intent intent = new Intent(mCreateKeyActivity, MainActivity.class);
+ intent.putExtras(data);
+ startActivity(intent);
+ mCreateKeyActivity.finish();
+ } else {
+ // just finish activity and return data
+ mCreateKeyActivity.setResult(Activity.RESULT_OK, data);
+ mCreateKeyActivity.finish();
+ }
}
} else {
Log.e(Constants.TAG, "No valid request code!");
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyYubiImportFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyYubiKeyImportFragment.java
index db62d53c5..4c7d1dfbd 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyYubiImportFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyYubiKeyImportFragment.java
@@ -48,7 +48,7 @@ import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.util.Preferences;
-public class CreateKeyYubiImportFragment extends Fragment implements NfcListenerFragment {
+public class CreateKeyYubiKeyImportFragment extends Fragment implements NfcListenerFragment {
private static final String ARG_FINGERPRINT = "fingerprint";
public static final String ARG_AID = "aid";
@@ -67,7 +67,7 @@ public class CreateKeyYubiImportFragment extends Fragment implements NfcListener
public static Fragment createInstance(byte[] scannedFingerprints, byte[] nfcAid, String userId) {
- CreateKeyYubiImportFragment frag = new CreateKeyYubiImportFragment();
+ CreateKeyYubiKeyImportFragment frag = new CreateKeyYubiKeyImportFragment();
Bundle args = new Bundle();
args.putByteArray(ARG_FINGERPRINT, scannedFingerprints);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyYubiWaitFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyYubiKeyWaitFragment.java
index 579dddf79..0b8586c0a 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyYubiWaitFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyYubiKeyWaitFragment.java
@@ -28,7 +28,7 @@ import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.ui.CreateKeyActivity.FragAction;
-public class CreateKeyYubiWaitFragment extends Fragment {
+public class CreateKeyYubiKeyWaitFragment extends Fragment {
CreateKeyActivity mCreateKeyActivity;
View mBackButton;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesActivity.java
index dce2386b5..c9a590c5b 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesActivity.java
@@ -25,7 +25,7 @@ import android.view.View;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.api.OpenKeychainIntents;
+import org.sufficientlysecure.keychain.intents.OpenKeychainIntents;
import org.sufficientlysecure.keychain.ui.base.BaseActivity;
import org.sufficientlysecure.keychain.util.Log;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesFragment.java
index 6c1902af1..234362edc 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesFragment.java
@@ -86,12 +86,12 @@ public class DecryptFilesFragment extends DecryptFragment {
*/
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- View view = inflater.inflate(R.layout.decrypt_file_fragment, container, false);
+ View view = inflater.inflate(R.layout.decrypt_files_fragment, container, false);
- mFilename = (TextView) view.findViewById(R.id.decrypt_file_filename);
- mDeleteAfter = (CheckBox) view.findViewById(R.id.decrypt_file_delete_after_decryption);
- mDecryptButton = view.findViewById(R.id.decrypt_file_action_decrypt);
- view.findViewById(R.id.decrypt_file_browse).setOnClickListener(new View.OnClickListener() {
+ mFilename = (TextView) view.findViewById(R.id.decrypt_files_filename);
+ mDeleteAfter = (CheckBox) view.findViewById(R.id.decrypt_files_delete_after_decryption);
+ mDecryptButton = view.findViewById(R.id.decrypt_files_action_decrypt);
+ view.findViewById(R.id.decrypt_files_browse).setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
FileHelper.openDocument(DecryptFilesFragment.this, "*/*", REQUEST_CODE_INPUT);
@@ -232,7 +232,6 @@ public class DecryptFilesFragment extends DecryptFragment {
returnData.getParcelable(DecryptVerifyResult.EXTRA_RESULT);
if (pgpResult.success()) {
-
switch (mCurrentCryptoOperation) {
case KeychainIntentService.ACTION_DECRYPT_METADATA: {
askForOutputFilename(pgpResult.getDecryptMetadata().getFilename());
@@ -264,9 +263,8 @@ public class DecryptFilesFragment extends DecryptFragment {
break;
}
}
- } else {
- pgpResult.createNotify(getActivity()).show();
}
+ pgpResult.createNotify(getActivity()).show(DecryptFilesFragment.this);
}
}
@@ -309,7 +307,7 @@ public class DecryptFilesFragment extends DecryptFragment {
}
@Override
- protected void onVerifyLoaded(boolean verified) {
+ protected void onVerifyLoaded(boolean hideErrorOverlay) {
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java
index 9c51893ce..e9bc42a4d 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java
@@ -30,6 +30,7 @@ import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.util.Log;
import android.view.View;
+import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
@@ -55,24 +56,24 @@ import org.sufficientlysecure.keychain.ui.util.Notify;
import org.sufficientlysecure.keychain.ui.util.Notify.Style;
import org.sufficientlysecure.keychain.util.Preferences;
-
public abstract class DecryptFragment extends CryptoOperationFragment implements
LoaderManager.LoaderCallbacks<Cursor> {
public static final int LOADER_ID_UNIFIED = 0;
protected LinearLayout mResultLayout;
-
protected ImageView mEncryptionIcon;
protected TextView mEncryptionText;
protected ImageView mSignatureIcon;
protected TextView mSignatureText;
-
protected View mSignatureLayout;
protected TextView mSignatureName;
protected TextView mSignatureEmail;
protected TextView mSignatureAction;
+ private LinearLayout mContentLayout;
+ private LinearLayout mErrorOverlayLayout;
+
private OpenPgpSignatureResult mSignatureResult;
@Override
@@ -82,7 +83,6 @@ public abstract class DecryptFragment extends CryptoOperationFragment implements
// NOTE: These views are inside the activity!
mResultLayout = (LinearLayout) getActivity().findViewById(R.id.result_main_layout);
mResultLayout.setVisibility(View.GONE);
-
mEncryptionIcon = (ImageView) getActivity().findViewById(R.id.result_encryption_icon);
mEncryptionText = (TextView) getActivity().findViewById(R.id.result_encryption_text);
mSignatureIcon = (ImageView) getActivity().findViewById(R.id.result_signature_icon);
@@ -92,6 +92,17 @@ public abstract class DecryptFragment extends CryptoOperationFragment implements
mSignatureEmail = (TextView) getActivity().findViewById(R.id.result_signature_email);
mSignatureAction = (TextView) getActivity().findViewById(R.id.result_signature_action);
+ // Overlay
+ mContentLayout = (LinearLayout) view.findViewById(R.id.decrypt_content);
+ mErrorOverlayLayout = (LinearLayout) view.findViewById(R.id.decrypt_error_overlay);
+ Button vErrorOverlayButton = (Button) view.findViewById(R.id.decrypt_error_overlay_button);
+ vErrorOverlayButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mErrorOverlayLayout.setVisibility(View.GONE);
+ mContentLayout.setVisibility(View.VISIBLE);
+ }
+ });
}
private void lookupUnknownKey(long unknownKeyId) {
@@ -113,12 +124,9 @@ public abstract class DecryptFragment extends CryptoOperationFragment implements
final ImportKeyResult result =
returnData.getParcelable(OperationResult.EXTRA_RESULT);
- // if (!result.success()) {
- result.createNotify(getActivity()).show();
- // }
+ result.createNotify(getActivity()).show();
getLoaderManager().restartLoader(LOADER_ID_UNIFIED, null, DecryptFragment.this);
-
}
}
};
@@ -153,7 +161,6 @@ public abstract class DecryptFragment extends CryptoOperationFragment implements
intent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger);
getActivity().startService(intent);
-
}
private void showKey(long keyId) {
@@ -191,6 +198,9 @@ public abstract class DecryptFragment extends CryptoOperationFragment implements
getLoaderManager().destroyLoader(LOADER_ID_UNIFIED);
+ mErrorOverlayLayout.setVisibility(View.GONE);
+ mContentLayout.setVisibility(View.VISIBLE);
+
onVerifyLoaded(true);
return;
@@ -205,7 +215,6 @@ public abstract class DecryptFragment extends CryptoOperationFragment implements
}
getLoaderManager().restartLoader(LOADER_ID_UNIFIED, null, this);
-
}
private void setSignatureLayoutVisibility(int visibility) {
@@ -228,8 +237,6 @@ public abstract class DecryptFragment extends CryptoOperationFragment implements
KeychainContract.KeyRings._ID,
KeychainContract.KeyRings.MASTER_KEY_ID,
KeychainContract.KeyRings.USER_ID,
- KeychainContract.KeyRings.IS_REVOKED,
- KeychainContract.KeyRings.IS_EXPIRED,
KeychainContract.KeyRings.VERIFIED,
KeychainContract.KeyRings.HAS_ANY_SECRET,
};
@@ -237,10 +244,8 @@ public abstract class DecryptFragment extends CryptoOperationFragment implements
@SuppressWarnings("unused")
static final int INDEX_MASTER_KEY_ID = 1;
static final int INDEX_USER_ID = 2;
- static final int INDEX_IS_REVOKED = 3;
- static final int INDEX_IS_EXPIRED = 4;
- static final int INDEX_VERIFIED = 5;
- static final int INDEX_HAS_ANY_SECRET = 6;
+ static final int INDEX_VERIFIED = 3;
+ static final int INDEX_HAS_ANY_SECRET = 4;
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
@@ -282,8 +287,10 @@ public abstract class DecryptFragment extends CryptoOperationFragment implements
getActivity(), mSignatureResult.getKeyId()));
}
- boolean isRevoked = data.getInt(INDEX_IS_REVOKED) != 0;
- boolean isExpired = data.getInt(INDEX_IS_EXPIRED) != 0;
+ // NOTE: Don't use revoked and expired fields from database, they don't show
+ // revoked/expired subkeys
+ boolean isRevoked = mSignatureResult.getStatus() == OpenPgpSignatureResult.SIGNATURE_KEY_REVOKED;
+ boolean isExpired = mSignatureResult.getStatus() == OpenPgpSignatureResult.SIGNATURE_KEY_EXPIRED;
boolean isVerified = data.getInt(INDEX_VERIFIED) > 0;
boolean isYours = data.getInt(INDEX_HAS_ANY_SECRET) != 0;
@@ -294,6 +301,9 @@ public abstract class DecryptFragment extends CryptoOperationFragment implements
setSignatureLayoutVisibility(View.VISIBLE);
setShowAction(signatureKeyId);
+ mErrorOverlayLayout.setVisibility(View.VISIBLE);
+ mContentLayout.setVisibility(View.GONE);
+
onVerifyLoaded(false);
} else if (isExpired) {
@@ -303,6 +313,22 @@ public abstract class DecryptFragment extends CryptoOperationFragment implements
setSignatureLayoutVisibility(View.VISIBLE);
setShowAction(signatureKeyId);
+ mErrorOverlayLayout.setVisibility(View.GONE);
+ mContentLayout.setVisibility(View.VISIBLE);
+
+ onVerifyLoaded(true);
+
+ } else if (isYours) {
+
+ mSignatureText.setText(R.string.decrypt_result_signature_secret);
+ KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, State.VERIFIED);
+
+ setSignatureLayoutVisibility(View.VISIBLE);
+ setShowAction(signatureKeyId);
+
+ mErrorOverlayLayout.setVisibility(View.GONE);
+ mContentLayout.setVisibility(View.VISIBLE);
+
onVerifyLoaded(true);
} else if (isYours) {
@@ -322,6 +348,9 @@ public abstract class DecryptFragment extends CryptoOperationFragment implements
setSignatureLayoutVisibility(View.VISIBLE);
setShowAction(signatureKeyId);
+ mErrorOverlayLayout.setVisibility(View.GONE);
+ mContentLayout.setVisibility(View.VISIBLE);
+
onVerifyLoaded(true);
} else {
@@ -331,6 +360,9 @@ public abstract class DecryptFragment extends CryptoOperationFragment implements
setSignatureLayoutVisibility(View.VISIBLE);
setShowAction(signatureKeyId);
+ mErrorOverlayLayout.setVisibility(View.GONE);
+ mContentLayout.setVisibility(View.VISIBLE);
+
onVerifyLoaded(true);
}
@@ -344,7 +376,6 @@ public abstract class DecryptFragment extends CryptoOperationFragment implements
}
setSignatureLayoutVisibility(View.GONE);
-
}
private void showUnknownKeyStatus() {
@@ -388,6 +419,9 @@ public abstract class DecryptFragment extends CryptoOperationFragment implements
}
});
+ mErrorOverlayLayout.setVisibility(View.GONE);
+ mContentLayout.setVisibility(View.VISIBLE);
+
onVerifyLoaded(true);
break;
@@ -399,6 +433,9 @@ public abstract class DecryptFragment extends CryptoOperationFragment implements
setSignatureLayoutVisibility(View.GONE);
+ mErrorOverlayLayout.setVisibility(View.VISIBLE);
+ mContentLayout.setVisibility(View.GONE);
+
onVerifyLoaded(false);
break;
}
@@ -407,6 +444,6 @@ public abstract class DecryptFragment extends CryptoOperationFragment implements
}
- protected abstract void onVerifyLoaded(boolean verified);
+ protected abstract void onVerifyLoaded(boolean hideErrorOverlay);
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextActivity.java
index 728e3ba41..e2eba3947 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextActivity.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2014 Dominik Schürmann <dominik@dominikschuermann.de>
+ * Copyright (C) 2012-2015 Dominik Schürmann <dominik@dominikschuermann.de>
* Copyright (C) 2010-2014 Thialfihar <thi@thialfihar.org>
*
* This program is free software: you can redistribute it and/or modify
@@ -23,16 +23,16 @@ import android.content.Intent;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
+import android.widget.Toast;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.api.OpenKeychainIntents;
import org.sufficientlysecure.keychain.compatibility.ClipboardReflection;
+import org.sufficientlysecure.keychain.intents.OpenKeychainIntents;
import org.sufficientlysecure.keychain.operations.results.OperationResult;
import org.sufficientlysecure.keychain.operations.results.SingletonResult;
import org.sufficientlysecure.keychain.pgp.PgpHelper;
import org.sufficientlysecure.keychain.ui.base.BaseActivity;
-import org.sufficientlysecure.keychain.ui.util.Notify;
import org.sufficientlysecure.keychain.util.Log;
import java.util.regex.Matcher;
@@ -138,8 +138,6 @@ public class DecryptTextActivity extends BaseActivity {
/**
* Handles all actions with this intent
- *
- * @param intent
*/
private void handleActions(Bundle savedInstanceState, Intent intent) {
String action = intent.getAction();
@@ -162,10 +160,14 @@ public class DecryptTextActivity extends BaseActivity {
if (sharedText != null) {
loadFragment(savedInstanceState, sharedText);
} else {
- Notify.create(this, R.string.error_invalid_data, Notify.Style.ERROR).show();
+ Log.e(Constants.TAG, "EXTRA_TEXT does not contain PGP content!");
+ Toast.makeText(this, R.string.error_invalid_data, Toast.LENGTH_LONG).show();
+ finish();
}
} else {
Log.e(Constants.TAG, "ACTION_SEND received non-plaintext, this should not happen in this activity!");
+ Toast.makeText(this, R.string.error_invalid_data, Toast.LENGTH_LONG).show();
+ finish();
}
} else if (ACTION_DECRYPT_TEXT.equals(action)) {
Log.d(Constants.TAG, "ACTION_DECRYPT_TEXT");
@@ -176,7 +178,9 @@ public class DecryptTextActivity extends BaseActivity {
if (extraText != null) {
loadFragment(savedInstanceState, extraText);
} else {
- Notify.create(this, R.string.error_invalid_data, Notify.Style.ERROR).show();
+ Log.e(Constants.TAG, "EXTRA_TEXT does not contain PGP content!");
+ Toast.makeText(this, R.string.error_invalid_data, Toast.LENGTH_LONG).show();
+ finish();
}
} else if (ACTION_DECRYPT_FROM_CLIPBOARD.equals(action)) {
Log.d(Constants.TAG, "ACTION_DECRYPT_FROM_CLIPBOARD");
@@ -191,6 +195,7 @@ public class DecryptTextActivity extends BaseActivity {
}
} else if (ACTION_DECRYPT_TEXT.equals(action)) {
Log.e(Constants.TAG, "Include the extra 'text' in your Intent!");
+ Toast.makeText(this, R.string.error_invalid_data, Toast.LENGTH_LONG).show();
finish();
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextFragment.java
index 6f576a112..381da6f0d 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextFragment.java
@@ -50,8 +50,6 @@ public class DecryptTextFragment extends DecryptFragment {
public static final String ARG_CIPHERTEXT = "ciphertext";
// view
- private LinearLayout mValidLayout;
- private LinearLayout mInvalidLayout;
private TextView mText;
// model
@@ -78,19 +76,8 @@ public class DecryptTextFragment extends DecryptFragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.decrypt_text_fragment, container, false);
- mValidLayout = (LinearLayout) view.findViewById(R.id.decrypt_text_valid);
- mInvalidLayout = (LinearLayout) view.findViewById(R.id.decrypt_text_invalid);
mText = (TextView) view.findViewById(R.id.decrypt_text_plaintext);
- Button vInvalidButton = (Button) view.findViewById(R.id.decrypt_text_invalid_button);
- vInvalidButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- mInvalidLayout.setVisibility(View.GONE);
- mValidLayout.setVisibility(View.VISIBLE);
- }
- });
-
return view;
}
@@ -203,7 +190,6 @@ public class DecryptTextFragment extends DecryptFragment {
returnData.getParcelable(DecryptVerifyResult.EXTRA_RESULT);
if (pgpResult.success()) {
-
byte[] decryptedMessage = returnData
.getByteArray(KeychainIntentService.RESULT_DECRYPTED_BYTES);
String displayMessage;
@@ -219,15 +205,12 @@ public class DecryptTextFragment extends DecryptFragment {
}
mText.setText(displayMessage);
- pgpResult.createNotify(getActivity()).show();
-
// display signature result in activity
loadVerifyResult(pgpResult);
-
} else {
- pgpResult.createNotify(getActivity()).show();
// TODO: show also invalid layout with different text?
}
+ pgpResult.createNotify(getActivity()).show(DecryptTextFragment.this);
}
}
};
@@ -244,18 +227,8 @@ public class DecryptTextFragment extends DecryptFragment {
}
@Override
- protected void onVerifyLoaded(boolean verified) {
-
- mShowMenuOptions = verified;
+ protected void onVerifyLoaded(boolean hideErrorOverlay) {
+ mShowMenuOptions = hideErrorOverlay;
getActivity().supportInvalidateOptionsMenu();
-
- if (verified) {
- mInvalidLayout.setVisibility(View.GONE);
- mValidLayout.setVisibility(View.VISIBLE);
- } else {
- mInvalidLayout.setVisibility(View.VISIBLE);
- mValidLayout.setVisibility(View.GONE);
- }
-
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java
index 64e908b1a..b3ec60890 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java
@@ -28,7 +28,7 @@ import android.view.View;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.api.OpenKeychainIntents;
+import org.sufficientlysecure.keychain.intents.OpenKeychainIntents;
import org.sufficientlysecure.keychain.ui.base.BaseActivity;
import org.sufficientlysecure.keychain.util.Passphrase;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java
index dd6dd6594..52d098adc 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java
@@ -26,7 +26,7 @@ import android.view.View;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.api.OpenKeychainIntents;
+import org.sufficientlysecure.keychain.intents.OpenKeychainIntents;
import org.sufficientlysecure.keychain.ui.base.BaseActivity;
import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.Passphrase;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java
index 5d9950db6..4cba62d5b 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java
@@ -30,16 +30,16 @@ import android.view.ViewGroup;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.api.OpenKeychainIntents;
+import org.sufficientlysecure.keychain.intents.OpenKeychainIntents;
import org.sufficientlysecure.keychain.keyimport.ImportKeysListEntry;
import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing;
import org.sufficientlysecure.keychain.operations.results.ImportKeyResult;
import org.sufficientlysecure.keychain.operations.results.OperationResult;
+import org.sufficientlysecure.keychain.service.KeychainIntentService;
import org.sufficientlysecure.keychain.ui.base.BaseNfcActivity;
import org.sufficientlysecure.keychain.service.CloudImportService;
import org.sufficientlysecure.keychain.service.ServiceProgressHandler;
import org.sufficientlysecure.keychain.ui.dialog.ProgressDialogFragment;
-import org.sufficientlysecure.keychain.ui.util.FormattingUtils;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.ui.util.Notify;
import org.sufficientlysecure.keychain.util.Log;
@@ -346,60 +346,66 @@ public class ImportKeysActivity extends BaseNfcActivity {
mListFragment.loadNew(loaderState);
}
+ private void handleMessage(Message message) {
+ if (message.arg1 == ServiceProgressHandler.MessageStatus.OKAY.ordinal()) {
+ // get returned data bundle
+ Bundle returnData = message.getData();
+ if (returnData == null) {
+ return;
+ }
+ final ImportKeyResult result =
+ returnData.getParcelable(OperationResult.EXTRA_RESULT);
+ if (result == null) {
+ Log.e(Constants.TAG, "result == null");
+ return;
+ }
+
+ if (ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN_RESULT.equals(getIntent().getAction())
+ || ACTION_IMPORT_KEY_FROM_FILE_AND_RETURN.equals(getIntent().getAction())) {
+ Intent intent = new Intent();
+ intent.putExtra(ImportKeyResult.EXTRA_RESULT, result);
+ ImportKeysActivity.this.setResult(RESULT_OK, intent);
+ ImportKeysActivity.this.finish();
+ return;
+ }
+ if (ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN_TO_SERVICE.equals(getIntent().getAction())) {
+ ImportKeysActivity.this.setResult(RESULT_OK, mPendingIntentData);
+ ImportKeysActivity.this.finish();
+ return;
+ }
+
+ result.createNotify(ImportKeysActivity.this)
+ .show((ViewGroup) findViewById(R.id.import_snackbar));
+ }
+ }
+
/**
* Import keys with mImportData
*/
public void importKeys() {
- // Message is received after importing is done in CloudImportService
- ServiceProgressHandler saveHandler = new ServiceProgressHandler(
- this,
- getString(R.string.progress_importing),
- ProgressDialog.STYLE_HORIZONTAL,
- true,
- ProgressDialogFragment.ServiceType.CLOUD_IMPORT) {
- public void handleMessage(Message message) {
- // handle messages by standard KeychainIntentServiceHandler first
- super.handleMessage(message);
-
- if (message.arg1 == MessageStatus.OKAY.ordinal()) {
- // get returned data bundle
- Bundle returnData = message.getData();
- if (returnData == null) {
- return;
- }
- final ImportKeyResult result =
- returnData.getParcelable(OperationResult.EXTRA_RESULT);
- if (result == null) {
- Log.e(Constants.TAG, "result == null");
- return;
- }
-
- if (ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN_RESULT.equals(getIntent().getAction())
- || ACTION_IMPORT_KEY_FROM_FILE_AND_RETURN.equals(getIntent().getAction())) {
- Intent intent = new Intent();
- intent.putExtra(ImportKeyResult.EXTRA_RESULT, result);
- ImportKeysActivity.this.setResult(RESULT_OK, intent);
- ImportKeysActivity.this.finish();
- return;
- }
- if (ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN_TO_SERVICE.equals(getIntent().getAction())) {
- ImportKeysActivity.this.setResult(RESULT_OK, mPendingIntentData);
- ImportKeysActivity.this.finish();
- return;
- }
-
- result.createNotify(ImportKeysActivity.this)
- .show((ViewGroup) findViewById(R.id.import_snackbar));
- }
- }
- };
-
ImportKeysListFragment.LoaderState ls = mListFragment.getLoaderState();
if (ls instanceof ImportKeysListFragment.BytesLoaderState) {
Log.d(Constants.TAG, "importKeys started");
+ ServiceProgressHandler serviceHandler = new ServiceProgressHandler(
+ this,
+ getString(R.string.progress_importing),
+ ProgressDialog.STYLE_HORIZONTAL,
+ true,
+ ProgressDialogFragment.ServiceType.KEYCHAIN_INTENT) {
+ public void handleMessage(Message message) {
+ // handle messages by standard KeychainIntentServiceHandler first
+ super.handleMessage(message);
+
+ ImportKeysActivity.this.handleMessage(message);
+ }
+ };
+
+ // TODO: Currently not using CloudImport here due to https://github.com/open-keychain/open-keychain/issues/1221
// Send all information needed to service to import key in other thread
- Intent intent = new Intent(this, CloudImportService.class);
+ Intent intent = new Intent(this, KeychainIntentService.class);
+
+ intent.setAction(KeychainIntentService.ACTION_IMPORT_KEYRING);
// fill values for this action
Bundle data = new Bundle();
@@ -417,14 +423,14 @@ public class ImportKeysActivity extends BaseNfcActivity {
new ParcelableFileCache<>(this, "key_import.pcl");
cache.writeCache(selectedEntries);
- intent.putExtra(CloudImportService.EXTRA_DATA, data);
+ intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
// Create a new Messenger for the communication back
- Messenger messenger = new Messenger(saveHandler);
- intent.putExtra(CloudImportService.EXTRA_MESSENGER, messenger);
+ Messenger messenger = new Messenger(serviceHandler);
+ intent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger);
// show progress dialog
- saveHandler.showProgressDialog(this);
+ serviceHandler.showProgressDialog(this);
// start service with intent
startService(intent);
@@ -436,6 +442,20 @@ public class ImportKeysActivity extends BaseNfcActivity {
} else if (ls instanceof ImportKeysListFragment.CloudLoaderState) {
ImportKeysListFragment.CloudLoaderState sls = (ImportKeysListFragment.CloudLoaderState) ls;
+ ServiceProgressHandler serviceHandler = new ServiceProgressHandler(
+ this,
+ getString(R.string.progress_importing),
+ ProgressDialog.STYLE_HORIZONTAL,
+ true,
+ ProgressDialogFragment.ServiceType.CLOUD_IMPORT) {
+ public void handleMessage(Message message) {
+ // handle messages by standard KeychainIntentServiceHandler first
+ super.handleMessage(message);
+
+ ImportKeysActivity.this.handleMessage(message);
+ }
+ };
+
// Send all information needed to service to query keys in other thread
Intent intent = new Intent(this, CloudImportService.class);
@@ -460,11 +480,11 @@ public class ImportKeysActivity extends BaseNfcActivity {
intent.putExtra(CloudImportService.EXTRA_DATA, data);
// Create a new Messenger for the communication back
- Messenger messenger = new Messenger(saveHandler);
+ Messenger messenger = new Messenger(serviceHandler);
intent.putExtra(CloudImportService.EXTRA_MESSENGER, messenger);
// show progress dialog
- saveHandler.showProgressDialog(this);
+ serviceHandler.showProgressDialog(this);
// start service with intent
startService(intent);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysProxyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysProxyActivity.java
index 29f2511a0..dc8752d1a 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysProxyActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysProxyActivity.java
@@ -37,7 +37,7 @@ import com.google.zxing.integration.android.IntentResult;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.api.OpenKeychainIntents;
+import org.sufficientlysecure.keychain.intents.OpenKeychainIntents;
import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing;
import org.sufficientlysecure.keychain.operations.results.ImportKeyResult;
import org.sufficientlysecure.keychain.operations.results.OperationResult;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java
index 8c4ea1884..d8c3e0350 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java
@@ -70,7 +70,6 @@ import org.sufficientlysecure.keychain.ui.adapter.KeyAdapter;
import org.sufficientlysecure.keychain.ui.dialog.DeleteKeyDialogFragment;
import org.sufficientlysecure.keychain.service.ServiceProgressHandler;
import org.sufficientlysecure.keychain.service.PassphraseCacheService;
-import org.sufficientlysecure.keychain.ui.dialog.DeleteKeyDialogFragment;
import org.sufficientlysecure.keychain.ui.dialog.ProgressDialogFragment;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.ui.util.Notify;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/MainActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/MainActivity.java
index 05cf64092..f571ba1e6 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/MainActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/MainActivity.java
@@ -64,7 +64,7 @@ public class MainActivity extends AppCompatActivity implements FabContainer {
transaction.replace(R.id.main_fragment_container, mainFragment);
transaction.commit();
- mToolbar = (Toolbar) findViewById(R.id.activity_main_toolbar);
+ mToolbar = (Toolbar) findViewById(R.id.toolbar);
mToolbar.setTitle(R.string.app_name);
setSupportActionBar(mToolbar);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvShareFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvShareFragment.java
index 6bd3a9303..fde0f62fd 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvShareFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvShareFragment.java
@@ -26,6 +26,7 @@ import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
+import android.os.ParcelFileDescriptor;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
@@ -42,19 +43,24 @@ import android.widget.TextView;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.compatibility.ClipboardReflection;
+import org.sufficientlysecure.keychain.pgp.UncachedKeyRing;
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.provider.KeychainContract.Keys;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
+import org.sufficientlysecure.keychain.provider.TemporaryStorageProvider;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.ui.util.Notify;
import org.sufficientlysecure.keychain.ui.util.QrCodeUtils;
import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.NfcHelper;
+import java.io.BufferedWriter;
+import java.io.OutputStreamWriter;
import java.io.IOException;
+import java.io.FileNotFoundException;
public class ViewKeyAdvShareFragment extends LoaderFragment implements
@@ -175,11 +181,11 @@ public class ViewKeyAdvShareFragment extends LoaderFragment implements
boolean toClipboard) {
try {
String content;
+ byte[] fingerprintData = (byte[]) providerHelper.getGenericData(
+ KeyRings.buildUnifiedKeyRingUri(dataUri),
+ Keys.FINGERPRINT, ProviderHelper.FIELD_TYPE_BLOB);
if (fingerprintOnly) {
- byte[] data = (byte[]) providerHelper.getGenericData(
- KeyRings.buildUnifiedKeyRingUri(dataUri),
- Keys.FINGERPRINT, ProviderHelper.FIELD_TYPE_BLOB);
- String fingerprint = KeyFormattingUtils.convertFingerprintToHex(data);
+ String fingerprint = KeyFormattingUtils.convertFingerprintToHex(fingerprintData);
if (!toClipboard) {
content = Constants.FINGERPRINT_SCHEME + ":" + fingerprint;
} else {
@@ -213,13 +219,48 @@ public class ViewKeyAdvShareFragment extends LoaderFragment implements
Intent sendIntent = new Intent(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, content);
sendIntent.setType("text/plain");
+
String title;
if (fingerprintOnly) {
title = getResources().getString(R.string.title_share_fingerprint_with);
} else {
title = getResources().getString(R.string.title_share_key);
}
- startActivity(Intent.createChooser(sendIntent, title));
+ Intent shareChooser = Intent.createChooser(sendIntent, title);
+
+ // Bluetooth Share will convert text/plain sent via EXTRA_TEXT to HTML
+ // Add replacement extra to send a text/plain file instead.
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+ try {
+ String primaryUserId = UncachedKeyRing.decodeFromData(content.getBytes()).
+ getPublicKey().getPrimaryUserIdWithFallback();
+
+ TemporaryStorageProvider shareFileProv = new TemporaryStorageProvider();
+ Uri contentUri = TemporaryStorageProvider.createFile(getActivity(),
+ primaryUserId + Constants.FILE_EXTENSION_ASC);
+
+ BufferedWriter contentWriter = new BufferedWriter(new OutputStreamWriter(
+ new ParcelFileDescriptor.AutoCloseOutputStream(
+ shareFileProv.openFile(contentUri, "w"))));
+ contentWriter.write(content);
+ contentWriter.close();
+
+ // create replacement extras inside try{}:
+ // if file creation fails, just don't add the replacements
+ Bundle replacements = new Bundle();
+ shareChooser.putExtra(Intent.EXTRA_REPLACEMENT_EXTRAS, replacements);
+
+ Bundle bluetoothExtra = new Bundle(sendIntent.getExtras());
+ replacements.putBundle("com.android.bluetooth", bluetoothExtra);
+
+ bluetoothExtra.putParcelable(Intent.EXTRA_STREAM, contentUri);
+ } catch (FileNotFoundException e) {
+ Log.e(Constants.TAG, "error creating temporary Bluetooth key share file!", e);
+ Notify.create(getActivity(), R.string.error_bluetooth_file, Notify.Style.ERROR).show();
+ }
+ }
+
+ startActivity(shareChooser);
}
} catch (PgpGeneralException | IOException e) {
Log.e(Constants.TAG, "error processing key!", e);
@@ -379,4 +420,4 @@ public class ViewKeyAdvShareFragment extends LoaderFragment implements
}
-} \ No newline at end of file
+}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyFragment.java
index d9b1fa279..c01a94286 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyFragment.java
@@ -202,6 +202,8 @@ public class ViewKeyFragment extends LoaderFragment implements
* In the case of a secret key, "me" (own profile) contact details are loaded.
*/
private void loadLinkedSystemContact(final long contactId) {
+ // contact doesn't exist, stop
+ if(contactId == -1) return;
final Context context = mSystemContactName.getContext();
final ContentResolver resolver = context.getContentResolver();
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyAdapter.java
index f09dc1a4f..3dbae09b6 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyAdapter.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyAdapter.java
@@ -18,15 +18,12 @@
package org.sufficientlysecure.keychain.ui.adapter;
-import java.util.Calendar;
import java.util.Date;
-import java.util.TimeZone;
import android.content.Context;
import android.database.Cursor;
import android.graphics.PorterDuff;
import android.support.v4.widget.CursorAdapter;
-import android.text.format.DateFormat;
import android.text.format.DateUtils;
import android.view.LayoutInflater;
import android.view.View;
@@ -176,9 +173,8 @@ public class KeyAdapter extends CursorAdapter {
| DateUtils.FORMAT_SHOW_TIME
| DateUtils.FORMAT_SHOW_YEAR
| DateUtils.FORMAT_ABBREV_MONTH);
-
- mCreationDate.setText(context.getString(R.string.label_creation,
- dateTime));
+ mCreationDate.setText(context.getString(R.string.label_key_created,
+ dateTime));
mCreationDate.setVisibility(View.VISIBLE);
} else {
mCreationDate.setVisibility(View.GONE);
@@ -281,20 +277,6 @@ public class KeyAdapter extends CursorAdapter {
}
}
- public boolean hasDuplicate() {
- return mHasDuplicate;
- }
-
- public String getCreationDate(Context context) {
- Calendar creationCal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
- creationCal.setTime(mCreation);
- // convert from UTC to time zone of device
- creationCal.setTimeZone(TimeZone.getDefault());
-
- return context.getString(R.string.label_creation) + ": "
- + DateFormat.getDateFormat(context).format(creationCal.getTime());
- }
-
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SelectKeyCursorAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SelectKeyCursorAdapter.java
index 1ccb910d0..6bbf41a88 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SelectKeyCursorAdapter.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SelectKeyCursorAdapter.java
@@ -140,8 +140,7 @@ abstract public class SelectKeyCursorAdapter extends CursorAdapter {
| DateUtils.FORMAT_SHOW_TIME
| DateUtils.FORMAT_SHOW_YEAR
| DateUtils.FORMAT_ABBREV_MONTH);
-
- h.creation.setText(context.getString(R.string.label_creation, dateTime));
+ h.creation.setText(context.getString(R.string.label_key_created, dateTime));
h.creation.setVisibility(View.VISIBLE);
} else {
h.creation.setVisibility(View.GONE);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddEmailDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddEmailDialogFragment.java
index 5d5ca533e..5b91b9d37 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddEmailDialogFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddEmailDialogFragment.java
@@ -112,9 +112,11 @@ public class AddEmailDialogFragment extends DialogFragment implements OnEditorAc
mEmail.post(new Runnable() {
@Override
public void run() {
- InputMethodManager imm = (InputMethodManager) getActivity()
- .getSystemService(Context.INPUT_METHOD_SERVICE);
- imm.showSoftInput(mEmail, InputMethodManager.SHOW_IMPLICIT);
+ if(getActivity() != null) {
+ InputMethodManager imm = (InputMethodManager) getActivity()
+ .getSystemService(Context.INPUT_METHOD_SERVICE);
+ imm.showSoftInput(mEmail, InputMethodManager.SHOW_IMPLICIT);
+ }
}
});
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/ProgressDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/ProgressDialogFragment.java
index b58f584c8..af9d175ff 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/ProgressDialogFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/ProgressDialogFragment.java
@@ -94,12 +94,12 @@ public class ProgressDialogFragment extends DialogFragment {
/** Updates progress of dialog */
public void setProgress(String message, int progress, int max) {
- if (mIsCancelled) {
+ ProgressDialog dialog = (ProgressDialog) getDialog();
+
+ if (mIsCancelled || dialog == null) {
return;
}
- ProgressDialog dialog = (ProgressDialog) getDialog();
-
dialog.setMessage(message);
dialog.setProgress(progress);
dialog.setMax(max);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/KeyFormattingUtils.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/KeyFormattingUtils.java
index ac7e7a487..3d98034d2 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/KeyFormattingUtils.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/KeyFormattingUtils.java
@@ -216,7 +216,16 @@ public class KeyFormattingUtils {
* @return
*/
public static String convertFingerprintToHex(byte[] fingerprint) {
- return Hex.toHexString(fingerprint, 0, 20).toLowerCase(Locale.ENGLISH);
+ // NOTE: Even though v3 keys are not imported we need to support both fingerprints for
+ // display/comparison before import
+ // Also better cut of unneeded parts, e.g., for fingerprints returned from YubiKeys
+ if (fingerprint.length < 20) {
+ // v3 key fingerprint with 128 bit (MD5)
+ return Hex.toHexString(fingerprint, 0, 16).toLowerCase(Locale.ENGLISH);
+ } else {
+ // v4 key fingerprint with 160 bit (SHA1)
+ return Hex.toHexString(fingerprint, 0, 20).toLowerCase(Locale.ENGLISH);
+ }
}
public static long getKeyIdFromFingerprint(byte[] fingerprint) {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionView.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionView.java
index 525bc26ca..63a1aade9 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionView.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionView.java
@@ -136,7 +136,7 @@ public class EncryptKeyCompletionView extends TokenCompleteTextView
where += " AND " + KeyRings.USER_ID + " LIKE ?";
return new CursorLoader(getContext(), baseUri, KeyAdapter.PROJECTION, where,
- new String[] { "%" + query + "%" }, null);
+ new String[]{"%" + query + "%"}, null);
}
mAdapter.setSearchQuery(null);
@@ -156,7 +156,7 @@ public class EncryptKeyCompletionView extends TokenCompleteTextView
@Override
public void showDropDown() {
- if (mAdapter.getCursor().isClosed()) {
+ if (mAdapter == null || mAdapter.getCursor() == null || mAdapter.getCursor().isClosed()) {
return;
}
super.showDropDown();
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java
index 8cf15a75a..61b7c718b 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java
@@ -26,7 +26,7 @@ import android.support.v4.app.LoaderManager;
import android.support.v4.content.Loader;
import android.support.v4.widget.CursorAdapter;
import android.support.v7.widget.AppCompatSpinner;
-import android.text.format.DateFormat;
+import android.text.format.DateUtils;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
@@ -42,10 +42,6 @@ import org.sufficientlysecure.keychain.pgp.KeyRing;
import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.util.Log;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.TimeZone;
-
/**
* Use AppCompatSpinner from AppCompat lib instead of Spinner. Fixes white dropdown icon.
* Related: http://stackoverflow.com/a/27713090
@@ -164,14 +160,14 @@ public abstract class KeySpinner extends AppCompatSpinner implements LoaderManag
boolean duplicate = cursor.getLong(mIndexDuplicate) > 0;
if (duplicate) {
- Date creationDate = new Date(cursor.getLong(mIndexCreationDate) * 1000);
- Calendar creationCal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
- creationCal.setTime(creationDate);
- // convert from UTC to time zone of device
- creationCal.setTimeZone(TimeZone.getDefault());
-
- vDuplicate.setText(context.getString(R.string.label_creation) + ": "
- + DateFormat.getDateFormat(context).format(creationCal.getTime()));
+ String dateTime = DateUtils.formatDateTime(context,
+ cursor.getLong(mIndexCreationDate) * 1000,
+ DateUtils.FORMAT_SHOW_DATE
+ | DateUtils.FORMAT_SHOW_TIME
+ | DateUtils.FORMAT_SHOW_YEAR
+ | DateUtils.FORMAT_ABBREV_MONTH);
+
+ vDuplicate.setText(context.getString(R.string.label_key_created, dateTime));
vDuplicate.setVisibility(View.VISIBLE);
} else {
vDuplicate.setVisibility(View.GONE);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ContactHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ContactHelper.java
index 609288bf1..e1efd5abc 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ContactHelper.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ContactHelper.java
@@ -446,6 +446,13 @@ public class ContactHelper {
writeKeysToMainProfileContact(context, resolver);
+ writeKeysToNormalContacts(context, resolver);
+ }
+
+ private static void writeKeysToNormalContacts(Context context, ContentResolver resolver) {
+ // delete raw contacts flagged for deletion by user so they can be reinserted
+ deleteFlaggedNormalRawContacts(resolver);
+
Set<Long> deletedKeys = getRawContactMasterKeyIds(resolver);
// Load all public Keys from OK
@@ -519,6 +526,9 @@ public class ContactHelper {
* @param context
*/
public static void writeKeysToMainProfileContact(Context context, ContentResolver resolver) {
+ // deletes contacts hidden by the user so they can be reinserted if necessary
+ deleteFlaggedMainProfileRawContacts(resolver);
+
Set<Long> keysToDelete = getMainProfileMasterKeyIds(resolver);
// get all keys which have associated secret keys
@@ -585,7 +595,7 @@ public class ContactHelper {
*
* @param resolver
* @param masterKeyId
- * @return
+ * @return number of rows deleted
*/
private static int deleteMainProfileRawContactByMasterKeyId(ContentResolver resolver,
long masterKeyId) {
@@ -603,6 +613,28 @@ public class ContactHelper {
}
/**
+ * deletes all raw contact entries in the "me" contact flagged for deletion ('hidden'),
+ * presumably by the user
+ *
+ * @param resolver
+ * @return number of raw contacts deleted
+ */
+ private static int deleteFlaggedMainProfileRawContacts(ContentResolver resolver) {
+ // CALLER_IS_SYNCADAPTER allows us to actually wipe the RawContact from the device, otherwise
+ // would be just flagged for deletion
+ Uri deleteUri = ContactsContract.Profile.CONTENT_RAW_CONTACTS_URI.buildUpon().
+ appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "true").build();
+
+ return resolver.delete(deleteUri,
+ ContactsContract.RawContacts.ACCOUNT_TYPE + "=? AND " +
+ ContactsContract.RawContacts.DELETED + "=?",
+ new String[]{
+ Constants.ACCOUNT_TYPE,
+ "1"
+ });
+ }
+
+ /**
* Delete all raw contacts associated to OpenKeychain, including those from "me" contact
* defined by ContactsContract.Profile
*
@@ -677,6 +709,21 @@ public class ContactHelper {
});
}
+ private static int deleteFlaggedNormalRawContacts(ContentResolver resolver) {
+ // CALLER_IS_SYNCADAPTER allows us to actually wipe the RawContact from the device, otherwise
+ // would be just flagged for deletion
+ Uri deleteUri = ContactsContract.RawContacts.CONTENT_URI.buildUpon().
+ appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "true").build();
+
+ return resolver.delete(deleteUri,
+ ContactsContract.RawContacts.ACCOUNT_TYPE + "=? AND " +
+ ContactsContract.RawContacts.DELETED + "=?",
+ new String[]{
+ Constants.ACCOUNT_TYPE,
+ "1"
+ });
+ }
+
/**
* @return a set of all key master key ids currently present in the contact db
*/