From 05accb49066a2693cfc1c92e29ad10112f957495 Mon Sep 17 00:00:00 2001 From: "tdjogi010@gmail.com" Date: Wed, 2 Mar 2016 02:51:25 +0530 Subject: Alert for Stripping Subkeys. --- .../keychain/ui/dialog/EditSubkeyDialogFragment.java | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditSubkeyDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditSubkeyDialogFragment.java index b51648740..c34312e79 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditSubkeyDialogFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditSubkeyDialogFragment.java @@ -75,7 +75,22 @@ public class EditSubkeyDialogFragment extends DialogFragment { sendMessageToHandler(MESSAGE_REVOKE, null); break; case 2: - sendMessageToHandler(MESSAGE_STRIP, null); + CustomAlertDialogBuilder stripAlertDialog = new CustomAlertDialogBuilder(getActivity()); + stripAlertDialog.setTitle(getResources().getString(R.string.title_alert_strip)). + setMessage(R.string.alert_strip).setCancelable(true); + stripAlertDialog.setPositiveButton(R.string.strip, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + sendMessageToHandler(MESSAGE_STRIP, null); + } + }); + stripAlertDialog.setNegativeButton(R.string.btn_do_not_save, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + dismiss(); + } + }); + stripAlertDialog.show(); break; case 3: sendMessageToHandler(MESSAGE_MOVE_KEY_TO_CARD, null); -- cgit v1.2.3 From 6087b0a6e048dbc4cfeae6d71e825ece6253994e Mon Sep 17 00:00:00 2001 From: fjodor Date: Thu, 10 Mar 2016 21:09:28 +0200 Subject: Updated HAS_DUPLICATE_USER_ID in KeychainProvider to use name and email address instead of user id #1745 --- .../org/sufficientlysecure/keychain/provider/KeychainProvider.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java index 9fbee0a67..e6789bc7b 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java @@ -316,8 +316,8 @@ public class KeychainProvider extends ContentProvider { + " WHERE dups." + UserPackets.MASTER_KEY_ID + " != " + Tables.KEYS + "." + Keys.MASTER_KEY_ID + " AND dups." + UserPackets.RANK + " = 0" - + " AND dups." + UserPackets.USER_ID - + " = "+ Tables.USER_PACKETS + "." + UserPackets.USER_ID + + " AND dups." + UserPackets.NAME + " = "+ Tables.USER_PACKETS + "." + UserPackets.NAME + + " AND dups." + UserPackets.EMAIL + " = "+ Tables.USER_PACKETS + "." + UserPackets.EMAIL + ")) AS " + KeyRings.HAS_DUPLICATE_USER_ID); projectionMap.put(KeyRings.VERIFIED, Tables.CERTS + "." + Certs.VERIFIED); projectionMap.put(KeyRings.PUBKEY_DATA, -- cgit v1.2.3 From b5211b33de683f5e903a2ad2d5028e2176c88eb8 Mon Sep 17 00:00:00 2001 From: Alex Fong Date: Sat, 12 Mar 2016 10:32:38 +0800 Subject: Provisional backup-code text selection fix For issue #1779, a provisional fix where selection is still possible, but more difficult. Preventing selection altogether is not possible due to the implementation in the Masked-Edittext dependency. To be updated when Masked-Edittext fixes this bug. --- .../keychain/ui/BackupCodeFragment.java | 25 ++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BackupCodeFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BackupCodeFragment.java index f1d9b270d..e7ff6ce46 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BackupCodeFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BackupCodeFragment.java @@ -43,6 +43,7 @@ import android.support.v4.app.FragmentManager.OnBackStackChangedListener; import android.text.Editable; import android.text.InputType; import android.text.TextWatcher; +import android.view.ActionMode; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; @@ -237,6 +238,30 @@ public class BackupCodeFragment extends CryptoOperationFragment Date: Mon, 14 Mar 2016 23:06:49 +0100 Subject: Set MIME application/pgp-keys when sending a key --- .../org/sufficientlysecure/keychain/ui/ViewKeyAdvShareFragment.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') 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 ce2f2def8..0aa8330ea 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvShareFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvShareFragment.java @@ -238,7 +238,7 @@ public class ViewKeyAdvShareFragment extends LoaderFragment implements // let user choose application Intent sendIntent = new Intent(Intent.ACTION_SEND); - sendIntent.setType("text/plain"); + sendIntent.setType(Constants.MIME_TYPE_KEYS); // NOTE: Don't use Intent.EXTRA_TEXT to send the key // better send it via a Uri! -- cgit v1.2.3 From eb5eb95a9ffb0f340c85c0710b451a5895988e21 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Tue, 15 Mar 2016 23:30:50 +0100 Subject: fix ridiculous database migration bug introduced by d6e4936fa54dc3577296dbadaeb556178dcad2c3 --- .../keychain/provider/KeychainDatabase.java | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') 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 2a4d898bc..c3697997f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java @@ -279,37 +279,35 @@ public class KeychainDatabase extends SQLiteOpenHelper { db.execSQL("ALTER TABLE user_ids ADD COLUMN type INTEGER"); db.execSQL("ALTER TABLE user_ids ADD COLUMN attribute_data BLOB"); case 7: - // consolidate - case 8: // new table for allowed key ids in API try { db.execSQL(CREATE_API_APPS_ALLOWED_KEYS); } catch (Exception e) { // never mind, the column probably already existed } - case 9: + case 8: // tbale name for user_ids changed to user_packets db.execSQL("DROP TABLE IF EXISTS certs"); db.execSQL("DROP TABLE IF EXISTS user_ids"); db.execSQL(CREATE_USER_PACKETS); db.execSQL(CREATE_CERTS); - case 10: + case 9: // do nothing here, just consolidate - case 11: + case 10: // fix problems in database, see #1402 for details // https://github.com/open-keychain/open-keychain/issues/1402 db.execSQL("DELETE FROM api_accounts WHERE key_id BETWEEN 0 AND 3"); - case 12: + case 11: db.execSQL(CREATE_UPDATE_KEYS); - case 13: + case 12: // do nothing here, just consolidate - case 14: + case 13: db.execSQL("CREATE INDEX keys_by_rank ON keys (" + KeysColumns.RANK + ");"); db.execSQL("CREATE INDEX uids_by_rank ON user_packets (" + UserPacketsColumns.RANK + ", " + UserPacketsColumns.USER_ID + ", " + UserPacketsColumns.MASTER_KEY_ID + ");"); db.execSQL("CREATE INDEX verified_certs ON certs (" + CertsColumns.VERIFIED + ", " + CertsColumns.MASTER_KEY_ID + ");"); - case 15: + case 14: db.execSQL("ALTER TABLE user_packets ADD COLUMN name TEXT"); db.execSQL("ALTER TABLE user_packets ADD COLUMN email TEXT"); db.execSQL("ALTER TABLE user_packets ADD COLUMN comment TEXT"); -- cgit v1.2.3 From 6029564d68afeba980bbdd5509622653efef1673 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Tue, 15 Mar 2016 23:51:21 +0100 Subject: small update to duplicate detection --- .../org/sufficientlysecure/keychain/provider/KeychainProvider.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java index e6789bc7b..75a5e89b8 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java @@ -316,8 +316,11 @@ public class KeychainProvider extends ContentProvider { + " WHERE dups." + UserPackets.MASTER_KEY_ID + " != " + Tables.KEYS + "." + Keys.MASTER_KEY_ID + " AND dups." + UserPackets.RANK + " = 0" - + " AND dups." + UserPackets.NAME + " = "+ Tables.USER_PACKETS + "." + UserPackets.NAME - + " AND dups." + UserPackets.EMAIL + " = "+ Tables.USER_PACKETS + "." + UserPackets.EMAIL + + " AND (dups." + UserPackets.USER_ID + " = " + Tables.USER_PACKETS + "." + UserPackets.USER_ID + " COLLATE NOCASE" + + " OR (dups." + UserPackets.NAME + " = " + Tables.USER_PACKETS + "." + UserPackets.NAME + " COLLATE NOCASE" + + " AND dups." + UserPackets.EMAIL + " = " + Tables.USER_PACKETS + "." + UserPackets.EMAIL + " COLLATE NOCASE" + + ")" + + ")" + ")) AS " + KeyRings.HAS_DUPLICATE_USER_ID); projectionMap.put(KeyRings.VERIFIED, Tables.CERTS + "." + Certs.VERIFIED); projectionMap.put(KeyRings.PUBKEY_DATA, -- cgit v1.2.3 From ce5e5f36c56fe14cb4a90a912eece07e4cb92285 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Wed, 16 Mar 2016 00:33:09 +0100 Subject: update null-check for duplicates, and add matching indexes to name and email columns --- .../keychain/provider/KeychainDatabase.java | 9 ++++++++- .../keychain/provider/KeychainProvider.java | 11 +++++------ 2 files changed, 13 insertions(+), 7 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') 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 c3697997f..04c14491b 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java @@ -54,7 +54,7 @@ import java.io.IOException; */ public class KeychainDatabase extends SQLiteOpenHelper { private static final String DATABASE_NAME = "openkeychain.db"; - private static final int DATABASE_VERSION = 15; + private static final int DATABASE_VERSION = 16; static Boolean apgHack = false; private Context mContext; @@ -311,6 +311,13 @@ public class KeychainDatabase extends SQLiteOpenHelper { db.execSQL("ALTER TABLE user_packets ADD COLUMN name TEXT"); db.execSQL("ALTER TABLE user_packets ADD COLUMN email TEXT"); db.execSQL("ALTER TABLE user_packets ADD COLUMN comment TEXT"); + case 15: + db.execSQL("CREATE INDEX uids_by_name ON user_packets (name COLLATE NOCASE)"); + db.execSQL("CREATE INDEX uids_by_email ON user_packets (email COLLATE NOCASE)"); + if (oldVersion == 14) { + // no consolidate necessary + return; + } } // always do consolidate after upgrade diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java index 75a5e89b8..9c5d0c054 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java @@ -312,15 +312,14 @@ public class KeychainProvider extends ContentProvider { projectionMap.put(KeyRings.EMAIL, Tables.USER_PACKETS + "." + UserPackets.EMAIL); projectionMap.put(KeyRings.COMMENT, Tables.USER_PACKETS + "." + UserPackets.COMMENT); projectionMap.put(KeyRings.HAS_DUPLICATE_USER_ID, - "(EXISTS (SELECT * FROM " + Tables.USER_PACKETS + " AS dups" + "(EXISTS (SELECT * FROM " + Tables.USER_PACKETS + " AS dups" + " WHERE dups." + UserPackets.MASTER_KEY_ID + " != " + Tables.KEYS + "." + Keys.MASTER_KEY_ID + " AND dups." + UserPackets.RANK + " = 0" - + " AND (dups." + UserPackets.USER_ID + " = " + Tables.USER_PACKETS + "." + UserPackets.USER_ID + " COLLATE NOCASE" - + " OR (dups." + UserPackets.NAME + " = " + Tables.USER_PACKETS + "." + UserPackets.NAME + " COLLATE NOCASE" - + " AND dups." + UserPackets.EMAIL + " = " + Tables.USER_PACKETS + "." + UserPackets.EMAIL + " COLLATE NOCASE" - + ")" - + ")" + + " AND dups." + UserPackets.NAME + + " = " + Tables.USER_PACKETS + "." + UserPackets.NAME + " COLLATE NOCASE" + + " AND dups." + UserPackets.EMAIL + + " = " + Tables.USER_PACKETS + "." + UserPackets.EMAIL + " COLLATE NOCASE" + ")) AS " + KeyRings.HAS_DUPLICATE_USER_ID); projectionMap.put(KeyRings.VERIFIED, Tables.CERTS + "." + Certs.VERIFIED); projectionMap.put(KeyRings.PUBKEY_DATA, -- cgit v1.2.3 From a8603d69749f0609e07f8894c695ba500b8404cb Mon Sep 17 00:00:00 2001 From: Durgesh <007durgesh219@gmail.com> Date: Mon, 7 Mar 2016 21:51:03 +0530 Subject: Fix CertifyKeyActivity back button on action bar not working #1758 Signed-off-by: Durgesh <007durgesh219@gmail.com> --- .../org/sufficientlysecure/keychain/ui/base/BaseActivity.java | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseActivity.java index beaf68372..063181dfe 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseActivity.java @@ -26,6 +26,7 @@ import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; import android.view.Gravity; import android.view.LayoutInflater; +import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; @@ -65,6 +66,16 @@ public abstract class BaseActivity extends AppCompatActivity { } } + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home : + onBackPressed(); + return true; + } + return super.onOptionsItemSelected(item); + } + public static void onResumeChecks(Context context) { KeyserverSyncAdapterService.cancelUpdates(context); // in case user has disabled sync from Android account settings -- cgit v1.2.3 From cab3fa7874f90f9aa8f5d3b9244e78ac4dd96638 Mon Sep 17 00:00:00 2001 From: Advaita Date: Tue, 15 Mar 2016 23:07:27 +0530 Subject: Final commit All changes included Improvements -Reformatted code wherever required -Only active wifi connections trigger events -Improve sync reliability -Removed extra permission Minor Changes -Refactored 2 variables for easier readbility -Wifi-Only-Sync is now enabled by default --- .../org/sufficientlysecure/keychain/Constants.java | 1 + .../keychain/receiver/NetworkReceiver.java | 52 ++++++++++++++++++++++ .../service/ContactSyncAdapterService.java | 9 ++-- .../service/KeyserverSyncAdapterService.java | 24 +++++++++- .../keychain/ui/SettingsActivity.java | 6 +-- .../keychain/util/Preferences.java | 32 +++++++------ 6 files changed, 102 insertions(+), 22 deletions(-) create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/receiver/NetworkReceiver.java (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java index 53fb5afc6..fd6e903fa 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java @@ -118,6 +118,7 @@ public final class Constants { // keyserver sync settings public static final String SYNC_CONTACTS = "syncContacts"; public static final String SYNC_KEYSERVER = "syncKeyserver"; + public static final String ENABLE_WIFI_SYNC_ONLY = "enableWifiSyncOnly"; // other settings public static final String EXPERIMENTAL_ENABLE_WORD_CONFIRM = "experimentalEnableWordConfirm"; public static final String EXPERIMENTAL_ENABLE_LINKED_IDENTITIES = "experimentalEnableLinkedIdentities"; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/receiver/NetworkReceiver.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/receiver/NetworkReceiver.java new file mode 100644 index 000000000..7c103a9a3 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/receiver/NetworkReceiver.java @@ -0,0 +1,52 @@ +package org.sufficientlysecure.keychain.receiver; + +import android.content.BroadcastReceiver; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.net.ConnectivityManager; +import android.net.NetworkInfo; + +import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.service.KeyserverSyncAdapterService; +import org.sufficientlysecure.keychain.util.Log; + +public class NetworkReceiver extends BroadcastReceiver { + + @Override + public void onReceive(Context context, Intent intent) { + + ConnectivityManager conn = (ConnectivityManager) + context.getSystemService(Context.CONNECTIVITY_SERVICE); + NetworkInfo networkInfo = conn.getActiveNetworkInfo(); + boolean isTypeWifi = (networkInfo.getType() == ConnectivityManager.TYPE_WIFI); + boolean isConnected = networkInfo.isConnected(); + + if (isTypeWifi && isConnected) { + + // broadcaster receiver disabled + setWifiReceiverComponent(false, context); + Intent serviceIntent = new Intent(context, KeyserverSyncAdapterService.class); + serviceIntent.setAction(KeyserverSyncAdapterService.ACTION_SYNC_NOW); + context.startService(serviceIntent); + } + } + + public void setWifiReceiverComponent(Boolean isEnabled, Context context) { + + PackageManager pm = context.getPackageManager(); + ComponentName compName = new ComponentName(context, + NetworkReceiver.class); + + if (isEnabled) { + pm.setComponentEnabledSetting(compName, + PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP); + Log.d(Constants.TAG, "Wifi Receiver is enabled!"); + } else { + pm.setComponentEnabledSetting(compName, + PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP); + Log.d(Constants.TAG, "Wifi Receiver is disabled!"); + } + } +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ContactSyncAdapterService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ContactSyncAdapterService.java index 15f8a47db..965d15138 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ContactSyncAdapterService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ContactSyncAdapterService.java @@ -144,12 +144,13 @@ public class ContactSyncAdapterService extends Service { public static void requestContactsSync() { // if user has disabled automatic sync, do nothing - if (!ContentResolver.getSyncAutomatically( - new Account(Constants.ACCOUNT_NAME, Constants.ACCOUNT_TYPE), - ContactsContract.AUTHORITY)) { + boolean isSyncEnabled = ContentResolver.getSyncAutomatically(new Account + (Constants.ACCOUNT_NAME, Constants.ACCOUNT_TYPE), ContactsContract.AUTHORITY); + + if (!isSyncEnabled) { return; } - + Bundle extras = new Bundle(); // no need to wait, do it immediately extras.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeyserverSyncAdapterService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeyserverSyncAdapterService.java index 1c59782fc..f92c0d229 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeyserverSyncAdapterService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeyserverSyncAdapterService.java @@ -16,6 +16,8 @@ import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.drawable.Drawable; +import android.net.ConnectivityManager; +import android.net.NetworkInfo; import android.os.Build; import android.os.Bundle; import android.os.Handler; @@ -35,6 +37,7 @@ import org.sufficientlysecure.keychain.operations.results.ImportKeyResult; import org.sufficientlysecure.keychain.operations.results.OperationResult; import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.provider.ProviderHelper; +import org.sufficientlysecure.keychain.receiver.NetworkReceiver; import org.sufficientlysecure.keychain.service.input.CryptoInputParcel; import org.sufficientlysecure.keychain.ui.OrbotRequiredDialogActivity; import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; @@ -68,7 +71,7 @@ public class KeyserverSyncAdapterService extends Service { private static final String ACTION_IGNORE_TOR = "ignore_tor"; private static final String ACTION_UPDATE_ALL = "update_all"; - private static final String ACTION_SYNC_NOW = "sync_now"; + public static final String ACTION_SYNC_NOW = "sync_now"; private static final String ACTION_DISMISS_NOTIFICATION = "cancel_sync"; private static final String ACTION_START_ORBOT = "start_orbot"; private static final String ACTION_CANCEL = "cancel"; @@ -176,8 +179,25 @@ public class KeyserverSyncAdapterService extends Service { @Override public void onPerformSync(Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult syncResult) { - Log.d(Constants.TAG, "Performing a keyserver sync!"); + Preferences prefs = Preferences.getPreferences(getContext()); + + // for a wifi-ONLY sync + if (prefs.getWifiOnlySync()) { + + ConnectivityManager connMgr = (ConnectivityManager) + getSystemService(Context.CONNECTIVITY_SERVICE); + NetworkInfo networkInfo = connMgr.getNetworkInfo(ConnectivityManager.TYPE_WIFI); + boolean isNotOnWifi = !(networkInfo.getType() == ConnectivityManager.TYPE_WIFI); + boolean isNotConnected = !(networkInfo.isConnected()); + + // if Wi-Fi connection doesn't exist then receiver is enabled + if (isNotOnWifi && isNotConnected) { + new NetworkReceiver().setWifiReceiverComponent(true, getContext()); + return; + } + } + Log.d(Constants.TAG, "Performing a keyserver sync!"); PowerManager pm = (PowerManager) KeyserverSyncAdapterService.this .getSystemService(Context.POWER_SERVICE); @SuppressWarnings("deprecation") // our min is API 15, deprecated only in 20 diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsActivity.java index ea70cde2a..a01637d84 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsActivity.java @@ -19,8 +19,6 @@ package org.sufficientlysecure.keychain.ui; -import java.util.List; - import android.Manifest; import android.accounts.Account; import android.accounts.AccountManager; @@ -59,6 +57,8 @@ import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.Preferences; import org.sufficientlysecure.keychain.util.orbot.OrbotHelper; +import java.util.List; + public class SettingsActivity extends AppCompatPreferenceActivity { public static final int REQUEST_CODE_KEYSERVER_PREF = 0x00007005; @@ -405,7 +405,7 @@ public class SettingsActivity extends AppCompatPreferenceActivity { } /** - * This fragment shows the keyserver/contacts sync preferences + * This fragment shows the keyserver/wifi-only-sync/contacts sync preferences */ public static class SyncPrefsFragment extends PresetPreferenceFragment { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Preferences.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Preferences.java index b3d679a0e..e0e50abf7 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Preferences.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Preferences.java @@ -19,19 +19,6 @@ package org.sufficientlysecure.keychain.util; -import java.io.Serializable; -import java.net.Proxy; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.ListIterator; -import java.util.Map; -import java.util.Set; -import java.util.Vector; - import android.annotation.SuppressLint; import android.content.Context; import android.content.SharedPreferences; @@ -45,6 +32,19 @@ import org.sufficientlysecure.keychain.Constants.Pref; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.service.KeyserverSyncAdapterService; +import java.io.Serializable; +import java.net.Proxy; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.ListIterator; +import java.util.Map; +import java.util.Set; +import java.util.Vector; + /** * Singleton Implementation of a Preference Helper */ @@ -424,6 +424,12 @@ public class Preferences { }; } + // sync preferences + + public boolean getWifiOnlySync() { + return mSharedPreferences.getBoolean(Pref.ENABLE_WIFI_SYNC_ONLY, true); + } + // experimental prefs public boolean getExperimentalEnableWordConfirm() { -- cgit v1.2.3 From c917262957e3fd182f77fa32b9de5bd24abbd6e1 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Wed, 23 Mar 2016 17:49:26 +0100 Subject: get rid of code path for pin and notation data handling --- .../operations/results/OperationResult.java | 2 - .../keychain/pgp/PgpKeyOperation.java | 113 ++++----------------- .../keychain/pgp/UncachedKeyRing.java | 42 ++++++++ .../keychain/service/SaveKeyringParcel.java | 16 +-- .../keychain/ui/CreateKeyFinalFragment.java | 4 +- .../keychain/ui/EditKeyFragment.java | 3 +- .../keychain/ui/ViewKeyActivity.java | 3 +- 7 files changed, 70 insertions(+), 113 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java index ec2fddbd0..a3979904c 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java @@ -566,8 +566,6 @@ public abstract class OperationResult implements Parcelable { MSG_MF_ERROR_BAD_SECURITY_TOKEN_SIZE(LogLevel.ERROR, R.string.edit_key_error_bad_security_token_size), MSG_MF_ERROR_BAD_SECURITY_TOKEN_STRIPPED(LogLevel.ERROR, R.string.edit_key_error_bad_security_token_stripped), MSG_MF_MASTER (LogLevel.DEBUG, R.string.msg_mf_master), - MSG_MF_NOTATION_PIN (LogLevel.DEBUG, R.string.msg_mf_notation_pin), - MSG_MF_NOTATION_EMPTY (LogLevel.DEBUG, R.string.msg_mf_notation_empty), MSG_MF_PASSPHRASE (LogLevel.INFO, R.string.msg_mf_passphrase), MSG_MF_PIN (LogLevel.INFO, R.string.msg_mf_pin), MSG_MF_ADMIN_PIN (LogLevel.INFO, R.string.msg_mf_admin_pin), diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java index e43548165..102e11674 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java @@ -18,6 +18,23 @@ package org.sufficientlysecure.keychain.pgp; + +import java.io.IOException; +import java.math.BigInteger; +import java.nio.ByteBuffer; +import java.security.InvalidAlgorithmParameterException; +import java.security.KeyPairGenerator; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.SecureRandom; +import java.security.SignatureException; +import java.security.spec.ECGenParameterSpec; +import java.util.Arrays; +import java.util.Date; +import java.util.Iterator; +import java.util.Stack; +import java.util.concurrent.atomic.AtomicBoolean; + import org.bouncycastle.bcpg.PublicKeyAlgorithmTags; import org.bouncycastle.bcpg.S2K; import org.bouncycastle.bcpg.sig.Features; @@ -57,13 +74,12 @@ import org.sufficientlysecure.keychain.operations.results.OperationResult.Operat import org.sufficientlysecure.keychain.operations.results.PgpEditKeyResult; import org.sufficientlysecure.keychain.service.SaveKeyringParcel; import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Algorithm; -import org.sufficientlysecure.keychain.service.SaveKeyringParcel.ChangeUnlockParcel; import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Curve; import org.sufficientlysecure.keychain.service.SaveKeyringParcel.SubkeyAdd; import org.sufficientlysecure.keychain.service.input.CryptoInputParcel; import org.sufficientlysecure.keychain.service.input.RequiredInputParcel; -import org.sufficientlysecure.keychain.service.input.RequiredInputParcel.NfcSignOperationsBuilder; import org.sufficientlysecure.keychain.service.input.RequiredInputParcel.NfcKeyToCardOperationsBuilder; +import org.sufficientlysecure.keychain.service.input.RequiredInputParcel.NfcSignOperationsBuilder; import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; import org.sufficientlysecure.keychain.util.IterableIterator; import org.sufficientlysecure.keychain.util.Log; @@ -71,22 +87,6 @@ import org.sufficientlysecure.keychain.util.Passphrase; import org.sufficientlysecure.keychain.util.Primes; import org.sufficientlysecure.keychain.util.ProgressScaler; -import java.io.IOException; -import java.math.BigInteger; -import java.nio.ByteBuffer; -import java.security.InvalidAlgorithmParameterException; -import java.security.KeyPairGenerator; -import java.security.NoSuchAlgorithmException; -import java.security.NoSuchProviderException; -import java.security.SecureRandom; -import java.security.SignatureException; -import java.security.spec.ECGenParameterSpec; -import java.util.Arrays; -import java.util.Date; -import java.util.Iterator; -import java.util.Stack; -import java.util.concurrent.atomic.AtomicBoolean; - /** * This class is the single place where ALL operations that actually modify a PGP public or secret * key take place. @@ -1058,8 +1058,8 @@ public class PgpKeyOperation { log.add(LogType.MSG_MF_PASSPHRASE, indent); indent += 1; - sKR = applyNewUnlock(sKR, masterPublicKey, masterPrivateKey, - cryptoInput.getPassphrase(), saveParcel.mNewUnlock, log, indent); + sKR = applyNewPassphrase(sKR, masterPublicKey, cryptoInput.getPassphrase(), + saveParcel.mNewUnlock.mNewPassphrase, log, indent); if (sKR == null) { // The error has been logged above, just return a bad state return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null); @@ -1191,76 +1191,6 @@ public class PgpKeyOperation { } - - private static PGPSecretKeyRing applyNewUnlock( - PGPSecretKeyRing sKR, - PGPPublicKey masterPublicKey, - PGPPrivateKey masterPrivateKey, - Passphrase passphrase, - ChangeUnlockParcel newUnlock, - OperationLog log, int indent) throws PGPException { - - if (newUnlock.mNewPassphrase != null) { - sKR = applyNewPassphrase(sKR, masterPublicKey, passphrase, newUnlock.mNewPassphrase, log, indent); - - // if there is any old packet with notation data - if (hasNotationData(sKR)) { - - log.add(LogType.MSG_MF_NOTATION_EMPTY, indent); - - // add packet with EMPTY notation data (updates old one, but will be stripped later) - PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder( - masterPrivateKey.getPublicKeyPacket().getAlgorithm(), - PgpSecurityConstants.SECRET_KEY_BINDING_SIGNATURE_HASH_ALGO) - .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); - PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder); - { // set subpackets - PGPSignatureSubpacketGenerator hashedPacketsGen = new PGPSignatureSubpacketGenerator(); - hashedPacketsGen.setExportable(false, false); - sGen.setHashedSubpackets(hashedPacketsGen.generate()); - } - sGen.init(PGPSignature.DIRECT_KEY, masterPrivateKey); - PGPSignature emptySig = sGen.generateCertification(masterPublicKey); - - masterPublicKey = PGPPublicKey.addCertification(masterPublicKey, emptySig); - sKR = PGPSecretKeyRing.insertSecretKey(sKR, - PGPSecretKey.replacePublicKey(sKR.getSecretKey(), masterPublicKey)); - } - - return sKR; - } - - if (newUnlock.mNewPin != null) { - sKR = applyNewPassphrase(sKR, masterPublicKey, passphrase, newUnlock.mNewPin, log, indent); - - log.add(LogType.MSG_MF_NOTATION_PIN, indent); - - // add packet with "pin" notation data - PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder( - masterPrivateKey.getPublicKeyPacket().getAlgorithm(), - PgpSecurityConstants.SECRET_KEY_BINDING_SIGNATURE_HASH_ALGO) - .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); - PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder); - { // set subpackets - PGPSignatureSubpacketGenerator hashedPacketsGen = new PGPSignatureSubpacketGenerator(); - hashedPacketsGen.setExportable(false, false); - hashedPacketsGen.setNotationData(false, true, "unlock.pin@sufficientlysecure.org", "1"); - sGen.setHashedSubpackets(hashedPacketsGen.generate()); - } - sGen.init(PGPSignature.DIRECT_KEY, masterPrivateKey); - PGPSignature emptySig = sGen.generateCertification(masterPublicKey); - - masterPublicKey = PGPPublicKey.addCertification(masterPublicKey, emptySig); - sKR = PGPSecretKeyRing.insertSecretKey(sKR, - PGPSecretKey.replacePublicKey(sKR.getSecretKey(), masterPublicKey)); - - return sKR; - } - - throw new UnsupportedOperationException("PIN passphrases not yet implemented!"); - - } - /** This method returns true iff the provided keyring has a local direct key signature * with notation data. */ @@ -1294,8 +1224,7 @@ public class PgpKeyOperation { PgpSecurityConstants.SECRET_KEY_ENCRYPTOR_S2K_COUNT) .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(newPassphrase.getCharArray()); - // noinspection unchecked - for (PGPSecretKey sKey : new IterableIterator(sKR.getSecretKeys())) { + for (PGPSecretKey sKey : new IterableIterator<>(sKR.getSecretKeys())) { log.add(LogType.MSG_MF_PASSPHRASE_KEY, indent, KeyFormattingUtils.convertKeyIdToHex(sKey.getKeyID())); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java index d696b9d70..b0db36b06 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java @@ -35,6 +35,8 @@ import java.util.Set; import java.util.TimeZone; import java.util.TreeSet; +import android.support.annotation.VisibleForTesting; + import org.bouncycastle.bcpg.ArmoredOutputStream; import org.bouncycastle.bcpg.PublicKeyAlgorithmTags; import org.bouncycastle.bcpg.SignatureSubpacketTags; @@ -42,15 +44,22 @@ import org.bouncycastle.bcpg.UserAttributeSubpacketTags; import org.bouncycastle.bcpg.sig.KeyFlags; import org.bouncycastle.openpgp.PGPKeyRing; import org.bouncycastle.openpgp.PGPObjectFactory; +import org.bouncycastle.openpgp.PGPPrivateKey; import org.bouncycastle.openpgp.PGPPublicKey; import org.bouncycastle.openpgp.PGPPublicKeyRing; import org.bouncycastle.openpgp.PGPSecretKey; import org.bouncycastle.openpgp.PGPSecretKeyRing; import org.bouncycastle.openpgp.PGPSignature; +import org.bouncycastle.openpgp.PGPSignatureGenerator; import org.bouncycastle.openpgp.PGPSignatureList; +import org.bouncycastle.openpgp.PGPSignatureSubpacketGenerator; import org.bouncycastle.openpgp.PGPUserAttributeSubpacketVector; import org.bouncycastle.openpgp.PGPUtil; +import org.bouncycastle.openpgp.operator.PBESecretKeyDecryptor; +import org.bouncycastle.openpgp.operator.PGPContentSignerBuilder; import org.bouncycastle.openpgp.operator.jcajce.JcaKeyFingerprintCalculator; +import org.bouncycastle.openpgp.operator.jcajce.JcaPGPContentSignerBuilder; +import org.bouncycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType; import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog; @@ -1310,4 +1319,37 @@ public class UncachedKeyRing { || algorithm == PGPPublicKey.ECDH; } + // ONLY TO BE USED FOR TESTING!! + @VisibleForTesting + public static UncachedKeyRing forTestingOnlyAddDummyLocalSignature( + UncachedKeyRing uncachedKeyRing, String passphrase) throws Exception { + PGPSecretKeyRing sKR = (PGPSecretKeyRing) uncachedKeyRing.mRing; + + PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider( + Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase.toCharArray()); + PGPPrivateKey masterPrivateKey = sKR.getSecretKey().extractPrivateKey(keyDecryptor); + PGPPublicKey masterPublicKey = uncachedKeyRing.mRing.getPublicKey(); + + // add packet with "pin" notation data + PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder( + masterPrivateKey.getPublicKeyPacket().getAlgorithm(), + PgpSecurityConstants.SECRET_KEY_BINDING_SIGNATURE_HASH_ALGO) + .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); + PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder); + { // set subpackets + PGPSignatureSubpacketGenerator hashedPacketsGen = new PGPSignatureSubpacketGenerator(); + hashedPacketsGen.setExportable(false, false); + hashedPacketsGen.setNotationData(false, true, "dummynotationdata", "some data"); + sGen.setHashedSubpackets(hashedPacketsGen.generate()); + } + sGen.init(PGPSignature.DIRECT_KEY, masterPrivateKey); + PGPSignature emptySig = sGen.generateCertification(masterPublicKey); + + masterPublicKey = PGPPublicKey.addCertification(masterPublicKey, emptySig); + sKR = PGPSecretKeyRing.insertSecretKey(sKR, + PGPSecretKey.replacePublicKey(sKR.getSecretKey(), masterPublicKey)); + + return new UncachedKeyRing(sKR); + } + } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java index 472eb3b18..dc892ecc8 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java @@ -356,29 +356,21 @@ public class SaveKeyringParcel implements Parcelable { // The new passphrase to use public final Passphrase mNewPassphrase; - // A new pin to use. Must only contain [0-9]+ - public final Passphrase mNewPin; public ChangeUnlockParcel(Passphrase newPassphrase) { - this(newPassphrase, null); - } - public ChangeUnlockParcel(Passphrase newPassphrase, Passphrase newPin) { - if (newPassphrase == null && newPin == null) { - throw new RuntimeException("Cannot set both passphrase and pin. THIS IS A BUG!"); + if (newPassphrase == null) { + throw new AssertionError("newPassphrase must be non-null. THIS IS A BUG!"); } mNewPassphrase = newPassphrase; - mNewPin = newPin; } public ChangeUnlockParcel(Parcel source) { mNewPassphrase = source.readParcelable(Passphrase.class.getClassLoader()); - mNewPin = source.readParcelable(Passphrase.class.getClassLoader()); } @Override public void writeToParcel(Parcel destination, int flags) { destination.writeParcelable(mNewPassphrase, flags); - destination.writeParcelable(mNewPin, flags); } @Override @@ -397,9 +389,7 @@ public class SaveKeyringParcel implements Parcelable { }; public String toString() { - return mNewPassphrase != null - ? ("passphrase (" + mNewPassphrase + ")") - : ("pin (" + mNewPin + ")"); + return "passphrase (" + mNewPassphrase + ")"; } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java index b53bfc1d0..58a28da51 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java @@ -278,7 +278,7 @@ public class CreateKeyFinalFragment extends Fragment { 2048, null, KeyFlags.AUTHENTICATION, 0L)); // use empty passphrase - saveKeyringParcel.mNewUnlock = new ChangeUnlockParcel(new Passphrase(), null); + saveKeyringParcel.mNewUnlock = new ChangeUnlockParcel(new Passphrase()); } else { saveKeyringParcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(Algorithm.RSA, 4096, null, KeyFlags.CERTIFY_OTHER, 0L)); @@ -288,7 +288,7 @@ public class CreateKeyFinalFragment extends Fragment { 4096, null, KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE, 0L)); saveKeyringParcel.mNewUnlock = createKeyActivity.mPassphrase != null - ? new ChangeUnlockParcel(createKeyActivity.mPassphrase, null) + ? new ChangeUnlockParcel(createKeyActivity.mPassphrase) : null; } String userId = KeyRing.createUserId( diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java index 2d94d0d93..2184f91f1 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java @@ -339,8 +339,7 @@ public class EditKeyFragment extends QueueingCryptoOperationFragment Date: Wed, 23 Mar 2016 22:46:25 +0100 Subject: use new TokenAutoComplete 2.0.7, fixes #1636 --- .../keychain/ui/EncryptModeAsymmetricFragment.java | 3 --- .../org/sufficientlysecure/keychain/ui/adapter/KeyAdapter.java | 8 -------- 2 files changed, 11 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptModeAsymmetricFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptModeAsymmetricFragment.java index ca5d20fb9..b2b85ec14 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptModeAsymmetricFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptModeAsymmetricFragment.java @@ -79,9 +79,6 @@ public class EncryptModeAsymmetricFragment extends EncryptModeFragment { mSignKeySpinner = (KeySpinner) view.findViewById(R.id.sign); mEncryptKeyView = (EncryptKeyCompletionView) view.findViewById(R.id.recipient_list); mEncryptKeyView.setThreshold(1); // Start working from first character - // TODO: workaround for bug in TokenAutoComplete, - // see https://github.com/open-keychain/open-keychain/issues/1636 - mEncryptKeyView.setDeletionStyle(TokenCompleteTextView.TokenDeleteStyle.ToString); final ViewAnimator vSignatureIcon = (ViewAnimator) view.findViewById(R.id.result_signature_icon); mSignKeySpinner.setOnKeyChangedListener(new OnKeyChangedListener() { 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 fb72a263e..4a68c55fe 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 @@ -333,14 +333,6 @@ public class KeyAdapter extends CursorAdapter { return mUserId.email; } } - - // TODO: workaround for bug in TokenAutoComplete, - // see https://github.com/open-keychain/open-keychain/issues/1636 - @Override - public String toString() { - return " "; - } - } public static String[] getProjectionWith(String[] projection) { -- cgit v1.2.3 From 4b6df7d17c6eae43b1db5f858d925103258f207e Mon Sep 17 00:00:00 2001 From: Adithya Abraham Philip Date: Thu, 24 Mar 2016 19:40:18 +0530 Subject: change sync interval on change in code --- .../keychain/KeychainApplication.java | 5 ++++ .../service/KeyserverSyncAdapterService.java | 31 +++++++++++++++++----- .../keychain/ui/SettingsActivity.java | 16 ++++++++--- .../keychain/util/Preferences.java | 23 ++++++++++++++-- 4 files changed, 63 insertions(+), 12 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java index e1f61a5ef..2f0ebe904 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java @@ -100,6 +100,11 @@ public class KeychainApplication extends Application { // Add OpenKeychain account to Android to link contacts with keys and keyserver sync createAccountIfNecessary(this); + if (Preferences.getKeyserverSyncEnabled(this)) { + // will update a keyserver sync if the interval has changed + KeyserverSyncAdapterService.enableKeyserverSync(this); + } + // if first time, enable keyserver and contact sync if (Preferences.getPreferences(this).isFirstTime()) { KeyserverSyncAdapterService.enableKeyserverSync(this); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeyserverSyncAdapterService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeyserverSyncAdapterService.java index f92c0d229..b71fbada8 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeyserverSyncAdapterService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeyserverSyncAdapterService.java @@ -11,6 +11,7 @@ import android.content.ContentProviderClient; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; +import android.content.PeriodicSync; import android.content.SyncResult; import android.database.Cursor; import android.graphics.Bitmap; @@ -529,6 +530,10 @@ public class KeyserverSyncAdapterService extends Service { return builder.build(); } + /** + * creates a new sync if one does not exist, or updates an existing sync if the sync interval + * has changed. + */ public static void enableKeyserverSync(Context context) { Account account = KeychainApplication.createAccountIfNecessary(context); @@ -539,12 +544,26 @@ public class KeyserverSyncAdapterService extends Service { ContentResolver.setIsSyncable(account, Constants.PROVIDER_AUTHORITY, 1); ContentResolver.setSyncAutomatically(account, Constants.PROVIDER_AUTHORITY, true); - ContentResolver.addPeriodicSync( - account, - Constants.PROVIDER_AUTHORITY, - new Bundle(), - SYNC_INTERVAL - ); + + boolean intervalChanged = false; + boolean syncExists = Preferences.getKeyserverSyncEnabled(context); + + if (syncExists) { + long oldInterval = ContentResolver.getPeriodicSyncs( + account, Constants.PROVIDER_AUTHORITY).get(0).period; + if (oldInterval != SYNC_INTERVAL) { + intervalChanged = true; + } + } + + if (!syncExists || intervalChanged) { + ContentResolver.addPeriodicSync( + account, + Constants.PROVIDER_AUTHORITY, + new Bundle(), + SYNC_INTERVAL + ); + } } private boolean isSyncEnabled() { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsActivity.java index a01637d84..4fd327c8f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsActivity.java @@ -47,6 +47,7 @@ import android.view.ViewGroup; import android.widget.LinearLayout; import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.KeychainApplication; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.compatibility.AppCompatPreferenceActivity; import org.sufficientlysecure.keychain.service.ContactSyncAdapterService; @@ -422,8 +423,7 @@ public class SettingsActivity extends AppCompatPreferenceActivity { super.onResume(); // this needs to be done in onResume since the user can change sync values from Android // settings and we need to reflect that change when the user navigates back - AccountManager manager = AccountManager.get(getActivity()); - final Account account = manager.getAccountsByType(Constants.ACCOUNT_TYPE)[0]; + final Account account = KeychainApplication.createAccountIfNecessary(getActivity()); // for keyserver sync initializeSyncCheckBox( (SwitchPreference) findPreference(Constants.Pref.SYNC_KEYSERVER), @@ -441,8 +441,11 @@ public class SettingsActivity extends AppCompatPreferenceActivity { private void initializeSyncCheckBox(final SwitchPreference syncCheckBox, final Account account, final String authority) { - boolean syncEnabled = ContentResolver.getSyncAutomatically(account, authority) - && checkContactsPermission(authority); + // account is null if it could not be created for some reason + boolean syncEnabled = + account != null + && ContentResolver.getSyncAutomatically(account, authority) + && checkContactsPermission(authority); syncCheckBox.setChecked(syncEnabled); setSummary(syncCheckBox, authority, syncEnabled); @@ -464,6 +467,11 @@ public class SettingsActivity extends AppCompatPreferenceActivity { return false; } } else { + if (account == null) { + // if account could not be created for some reason, + // we can't have our sync + return false; + } // disable syncs ContentResolver.setSyncAutomatically(account, authority, false); // immediately delete any linked contacts diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Preferences.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Preferences.java index e0e50abf7..5f53845d8 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Preferences.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Preferences.java @@ -19,7 +19,9 @@ package org.sufficientlysecure.keychain.util; +import android.accounts.Account; import android.annotation.SuppressLint; +import android.content.ContentResolver; import android.content.Context; import android.content.SharedPreferences; import android.os.Parcel; @@ -29,6 +31,7 @@ import android.support.annotation.NonNull; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.Constants.Pref; +import org.sufficientlysecure.keychain.KeychainApplication; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.service.KeyserverSyncAdapterService; @@ -76,9 +79,8 @@ public class Preferences { /** * Makes android's preference framework write to our file instead of default. - * This allows us to use the "persistent" attribute to simplify code, which automatically + * This allows us to use the xml "persistent" attribute to simplify code, which automatically * writes and reads preference values. - * @param manager */ public static void setPreferenceManagerFileAndMode(PreferenceManager manager) { manager.setSharedPreferencesName(PREF_FILE_NAME); @@ -302,6 +304,23 @@ public class Preferences { } + /** + * @return true if a periodic sync exists and is set to run automatically, false otherwise + */ + public static boolean getKeyserverSyncEnabled(Context context) { + Account account = KeychainApplication.createAccountIfNecessary(context); + + if (account == null) { + // if the account could not be created for some reason, we can't have a sync + return false; + } + + String authority = Constants.PROVIDER_AUTHORITY; + + return ContentResolver.getSyncAutomatically(account, authority) && + !ContentResolver.getPeriodicSyncs(account, authority).isEmpty(); + } + public CacheTTLPrefs getPassphraseCacheTtl() { Set pref = mSharedPreferences.getStringSet(Constants.Pref.PASSPHRASE_CACHE_TTLS, null); if (pref == null) { -- cgit v1.2.3 From 0f716f7b9f3a3a820723415a2351b883f320874a Mon Sep 17 00:00:00 2001 From: Durgesh <007durgesh219@gmail.com> Date: Mon, 7 Mar 2016 16:03:52 +0530 Subject: Display Key moved to Fragment Signed-off-by: Durgesh <007durgesh219@gmail.com> --- .../keychain/ui/CertifyKeyActivity.java | 2 +- .../keychain/ui/CertifyKeyFragment.java | 176 +---------------- .../keychain/ui/MultiUserIdsFragment.java | 217 +++++++++++++++++++++ 3 files changed, 224 insertions(+), 171 deletions(-) create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/MultiUserIdsFragment.java (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java index 3845e07cb..32da02efe 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java @@ -28,7 +28,7 @@ import org.sufficientlysecure.keychain.ui.base.BaseActivity; public class CertifyKeyActivity extends BaseActivity { public static final String EXTRA_RESULT = "operation_result"; - public static final String EXTRA_KEY_IDS = "extra_key_ids"; + public static final String EXTRA_KEY_IDS = MultiUserIdsFragment.EXTRA_KEY_IDS ; public static final String EXTRA_CERTIFY_KEY_ID = "certify_key_id"; @Override diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyFragment.java index 357b445f0..22cfabcc9 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyFragment.java @@ -62,52 +62,19 @@ import java.util.ArrayList; import java.util.Date; public class CertifyKeyFragment - extends CachingCryptoOperationFragment - implements LoaderManager.LoaderCallbacks { - - public static final String ARG_CHECK_STATES = "check_states"; + extends CachingCryptoOperationFragment { private CheckBox mUploadKeyCheckbox; - ListView mUserIds; private CertifyKeySpinner mCertifyKeySpinner; - private long[] mPubMasterKeyIds; - - public static final String[] USER_IDS_PROJECTION = new String[]{ - UserPackets._ID, - UserPackets.MASTER_KEY_ID, - UserPackets.USER_ID, - UserPackets.IS_PRIMARY, - UserPackets.IS_REVOKED - }; - private static final int INDEX_MASTER_KEY_ID = 1; - private static final int INDEX_USER_ID = 2; - @SuppressWarnings("unused") - private static final int INDEX_IS_PRIMARY = 3; - @SuppressWarnings("unused") - private static final int INDEX_IS_REVOKED = 4; - - private MultiUserIdsAdapter mUserIdsAdapter; + private MultiUserIdsFragment mMultiUserIdsFragment; @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); - mPubMasterKeyIds = getActivity().getIntent().getLongArrayExtra(CertifyKeyActivity.EXTRA_KEY_IDS); - if (mPubMasterKeyIds == null) { - Log.e(Constants.TAG, "List of key ids to certify missing!"); - getActivity().finish(); - return; - } - - ArrayList checkedStates; - if (savedInstanceState != null) { - checkedStates = (ArrayList) savedInstanceState.getSerializable(ARG_CHECK_STATES); - // key spinner and the checkbox keep their own state - } else { - checkedStates = null; - + if (savedInstanceState == null){ // preselect certify key id if given long certifyKeyId = getActivity().getIntent() .getLongExtra(CertifyKeyActivity.EXTRA_CERTIFY_KEY_ID, Constants.key.none); @@ -124,12 +91,6 @@ public class CertifyKeyFragment } - mUserIdsAdapter = new MultiUserIdsAdapter(getActivity(), null, 0, checkedStates); - mUserIds.setAdapter(mUserIdsAdapter); - mUserIds.setDividerHeight(0); - - getLoaderManager().initLoader(0, null, this); - OperationResult result = getActivity().getIntent().getParcelableExtra(CertifyKeyActivity.EXTRA_RESULT); if (result != null) { // display result from import @@ -137,22 +98,14 @@ public class CertifyKeyFragment } } - @Override - public void onSaveInstanceState(Bundle outState) { - super.onSaveInstanceState(outState); - - ArrayList states = mUserIdsAdapter.getCheckStates(); - // no proper parceling method available :( - outState.putSerializable(ARG_CHECK_STATES, states); - } - @Override public View onCreateView(LayoutInflater inflater, ViewGroup superContainer, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.certify_key_fragment, null); mCertifyKeySpinner = (CertifyKeySpinner) view.findViewById(R.id.certify_key_spinner); mUploadKeyCheckbox = (CheckBox) view.findViewById(R.id.sign_key_upload_checkbox); - mUserIds = (ListView) view.findViewById(R.id.view_key_user_ids); + mMultiUserIdsFragment = (MultiUserIdsFragment) + getChildFragmentManager().findFragmentById(R.id.multi_user_ids_fragment); // make certify image gray, like action icons ImageView vActionCertifyImage = @@ -183,128 +136,11 @@ public class CertifyKeyFragment return view; } - @Override - public Loader onCreateLoader(int id, Bundle args) { - Uri uri = UserPackets.buildUserIdsUri(); - - String selection, ids[]; - { - // generate placeholders and string selection args - ids = new String[mPubMasterKeyIds.length]; - StringBuilder placeholders = new StringBuilder("?"); - for (int i = 0; i < mPubMasterKeyIds.length; i++) { - ids[i] = Long.toString(mPubMasterKeyIds[i]); - if (i != 0) { - placeholders.append(",?"); - } - } - // put together selection string - selection = UserPackets.IS_REVOKED + " = 0" + " AND " - + Tables.USER_PACKETS + "." + UserPackets.MASTER_KEY_ID - + " IN (" + placeholders + ")"; - } - - return new CursorLoader(getActivity(), uri, - USER_IDS_PROJECTION, selection, ids, - Tables.USER_PACKETS + "." + UserPackets.MASTER_KEY_ID + " ASC" - + ", " + Tables.USER_PACKETS + "." + UserPackets.USER_ID + " ASC" - ); - } - - @Override - public void onLoadFinished(Loader loader, Cursor data) { - - MatrixCursor matrix = new MatrixCursor(new String[]{ - "_id", "user_data", "grouped" - }) { - @Override - public byte[] getBlob(int column) { - return super.getBlob(column); - } - }; - data.moveToFirst(); - - long lastMasterKeyId = 0; - String lastName = ""; - ArrayList uids = new ArrayList<>(); - - boolean header = true; - - // Iterate over all rows - while (!data.isAfterLast()) { - long masterKeyId = data.getLong(INDEX_MASTER_KEY_ID); - String userId = data.getString(INDEX_USER_ID); - KeyRing.UserId pieces = KeyRing.splitUserId(userId); - - // Two cases: - - boolean grouped = masterKeyId == lastMasterKeyId; - boolean subGrouped = data.isFirst() || grouped && lastName.equals(pieces.name); - // Remember for next loop - lastName = pieces.name; - - Log.d(Constants.TAG, Long.toString(masterKeyId, 16) + (grouped ? "grouped" : "not grouped")); - - if (!subGrouped) { - // 1. This name should NOT be grouped with the previous, so we flush the buffer - - Parcel p = Parcel.obtain(); - p.writeStringList(uids); - byte[] d = p.marshall(); - p.recycle(); - - matrix.addRow(new Object[]{ - lastMasterKeyId, d, header ? 1 : 0 - }); - // indicate that we have a header for this masterKeyId - header = false; - - // Now clear the buffer, and add the new user id, for the next round - uids.clear(); - - } - - // 2. This name should be grouped with the previous, just add to buffer - uids.add(userId); - lastMasterKeyId = masterKeyId; - - // If this one wasn't grouped, the next one's gotta be a header - if (!grouped) { - header = true; - } - - // Regardless of the outcome, move to next entry - data.moveToNext(); - - } - - // If there is anything left in the buffer, flush it one last time - if (!uids.isEmpty()) { - - Parcel p = Parcel.obtain(); - p.writeStringList(uids); - byte[] d = p.marshall(); - p.recycle(); - - matrix.addRow(new Object[]{ - lastMasterKeyId, d, header ? 1 : 0 - }); - - } - - mUserIdsAdapter.swapCursor(matrix); - } - - @Override - public void onLoaderReset(Loader loader) { - mUserIdsAdapter.swapCursor(null); - } - @Override public CertifyActionsParcel createOperationInput() { // Bail out if there is not at least one user id selected - ArrayList certifyActions = mUserIdsAdapter.getSelectedCertifyActions(); + ArrayList certifyActions = mMultiUserIdsFragment.getSelectedCertifyActions(); if (certifyActions.isEmpty()) { Notify.create(getActivity(), "No identities selected!", Notify.Style.ERROR).show(); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/MultiUserIdsFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/MultiUserIdsFragment.java new file mode 100644 index 000000000..b61ec79ee --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/MultiUserIdsFragment.java @@ -0,0 +1,217 @@ +package org.sufficientlysecure.keychain.ui; + +import android.database.Cursor; +import android.database.MatrixCursor; +import android.net.Uri; +import android.os.Bundle; +import android.os.Parcel; +import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; +import android.support.v4.app.LoaderManager; +import android.support.v4.content.CursorLoader; +import android.support.v4.content.Loader; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ListView; + +import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.pgp.KeyRing; +import org.sufficientlysecure.keychain.provider.KeychainContract; +import org.sufficientlysecure.keychain.provider.KeychainDatabase; +import org.sufficientlysecure.keychain.service.CertifyActionsParcel; +import org.sufficientlysecure.keychain.ui.adapter.MultiUserIdsAdapter; +import org.sufficientlysecure.keychain.util.Log; + +import java.util.ArrayList; + +/** + * Created by durgeshchoudhary on 07/03/16. + */ +public class MultiUserIdsFragment extends Fragment implements LoaderManager.LoaderCallbacks{ + public static final String ARG_CHECK_STATES = "check_states"; + public static final String EXTRA_KEY_IDS = "extra_key_ids"; + + ListView mUserIds; + private MultiUserIdsAdapter mUserIdsAdapter; + + private long[] mPubMasterKeyIds; + + public static final String[] USER_IDS_PROJECTION = new String[]{ + KeychainContract.UserPackets._ID, + KeychainContract.UserPackets.MASTER_KEY_ID, + KeychainContract.UserPackets.USER_ID, + KeychainContract.UserPackets.IS_PRIMARY, + KeychainContract.UserPackets.IS_REVOKED + }; + private static final int INDEX_MASTER_KEY_ID = 1; + private static final int INDEX_USER_ID = 2; + @SuppressWarnings("unused") + private static final int INDEX_IS_PRIMARY = 3; + @SuppressWarnings("unused") + private static final int INDEX_IS_REVOKED = 4; + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.multi_user_ids_fragment, null); + + mUserIds = (ListView) view.findViewById(R.id.view_key_user_ids); + + return view; + } + + @Override + public void onActivityCreated(@Nullable Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + + mPubMasterKeyIds = getActivity().getIntent().getLongArrayExtra(EXTRA_KEY_IDS); + if (mPubMasterKeyIds == null) { + Log.e(Constants.TAG, "List of key ids to certify missing!"); + getActivity().finish(); + return; + } + + ArrayList checkedStates = null; + if (savedInstanceState != null) { + checkedStates = (ArrayList) savedInstanceState.getSerializable(ARG_CHECK_STATES); + } + + mUserIdsAdapter = new MultiUserIdsAdapter(getActivity(), null, 0, checkedStates); + mUserIds.setAdapter(mUserIdsAdapter); + mUserIds.setDividerHeight(0); + + getLoaderManager().initLoader(0, null, this); + } + + @Override + public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + + ArrayList states = mUserIdsAdapter.getCheckStates(); + // no proper parceling method available :( + outState.putSerializable(ARG_CHECK_STATES, states); + } + + public ArrayList getSelectedCertifyActions() { + return mUserIdsAdapter.getSelectedCertifyActions(); + } + + @Override + public Loader onCreateLoader(int id, Bundle args) { + Uri uri = KeychainContract.UserPackets.buildUserIdsUri(); + + String selection, ids[]; + { + // generate placeholders and string selection args + ids = new String[mPubMasterKeyIds.length]; + StringBuilder placeholders = new StringBuilder("?"); + for (int i = 0; i < mPubMasterKeyIds.length; i++) { + ids[i] = Long.toString(mPubMasterKeyIds[i]); + if (i != 0) { + placeholders.append(",?"); + } + } + // put together selection string + selection = KeychainContract.UserPackets.IS_REVOKED + " = 0" + " AND " + + KeychainDatabase.Tables.USER_PACKETS + "." + KeychainContract.UserPackets.MASTER_KEY_ID + + " IN (" + placeholders + ")"; + } + + return new CursorLoader(getActivity(), uri, + USER_IDS_PROJECTION, selection, ids, + KeychainDatabase.Tables.USER_PACKETS + "." + KeychainContract.UserPackets.MASTER_KEY_ID + " ASC" + + ", " + KeychainDatabase.Tables.USER_PACKETS + "." + KeychainContract.UserPackets.USER_ID + " ASC" + ); + } + + @Override + public void onLoadFinished(Loader loader, Cursor data) { + + MatrixCursor matrix = new MatrixCursor(new String[]{ + "_id", "user_data", "grouped" + }) { + @Override + public byte[] getBlob(int column) { + return super.getBlob(column); + } + }; + data.moveToFirst(); + + long lastMasterKeyId = 0; + String lastName = ""; + ArrayList uids = new ArrayList<>(); + + boolean header = true; + + // Iterate over all rows + while (!data.isAfterLast()) { + long masterKeyId = data.getLong(INDEX_MASTER_KEY_ID); + String userId = data.getString(INDEX_USER_ID); + KeyRing.UserId pieces = KeyRing.splitUserId(userId); + + // Two cases: + + boolean grouped = masterKeyId == lastMasterKeyId; + boolean subGrouped = data.isFirst() || grouped && lastName.equals(pieces.name); + // Remember for next loop + lastName = pieces.name; + + Log.d(Constants.TAG, Long.toString(masterKeyId, 16) + (grouped ? "grouped" : "not grouped")); + + if (!subGrouped) { + // 1. This name should NOT be grouped with the previous, so we flush the buffer + + Parcel p = Parcel.obtain(); + p.writeStringList(uids); + byte[] d = p.marshall(); + p.recycle(); + + matrix.addRow(new Object[]{ + lastMasterKeyId, d, header ? 1 : 0 + }); + // indicate that we have a header for this masterKeyId + header = false; + + // Now clear the buffer, and add the new user id, for the next round + uids.clear(); + + } + + // 2. This name should be grouped with the previous, just add to buffer + uids.add(userId); + lastMasterKeyId = masterKeyId; + + // If this one wasn't grouped, the next one's gotta be a header + if (!grouped) { + header = true; + } + + // Regardless of the outcome, move to next entry + data.moveToNext(); + + } + + // If there is anything left in the buffer, flush it one last time + if (!uids.isEmpty()) { + + Parcel p = Parcel.obtain(); + p.writeStringList(uids); + byte[] d = p.marshall(); + p.recycle(); + + matrix.addRow(new Object[]{ + lastMasterKeyId, d, header ? 1 : 0 + }); + + } + + mUserIdsAdapter.swapCursor(matrix); + } + + @Override + public void onLoaderReset(Loader loader) { + mUserIdsAdapter.swapCursor(null); + } +} -- cgit v1.2.3 From 8f4238df28bea3473fb1414f64ad959368575e28 Mon Sep 17 00:00:00 2001 From: Victor Hazali Date: Wed, 30 Mar 2016 04:21:33 +0800 Subject: Fixes #1298 --- .../main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java | 2 ++ 1 file changed, 2 insertions(+) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java index 35c1615c7..6c96a40ba 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java @@ -32,6 +32,7 @@ import android.app.ActivityOptions; import android.content.Intent; import android.database.Cursor; import android.graphics.Bitmap; +import android.graphics.Color; import android.net.Uri; import android.nfc.NfcAdapter; import android.os.AsyncTask; @@ -923,6 +924,7 @@ public class ViewKeyActivity extends BaseSecurityTokenNfcActivity implements } mPhoto.setImageBitmap(photo); + mPhoto.setColorFilter(Color.argb(30, 120, 166, 69)); mPhotoLayout.setVisibility(View.VISIBLE); } }; -- cgit v1.2.3 From ce70568ff3f87e194ef1dd9ff04501610b7661db Mon Sep 17 00:00:00 2001 From: Victor Hazali Date: Wed, 30 Mar 2016 05:37:31 +0800 Subject: Extracted method --- .../ui/dialog/EditSubkeyDialogFragment.java | 36 ++++++++++++---------- 1 file changed, 20 insertions(+), 16 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditSubkeyDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditSubkeyDialogFragment.java index c34312e79..ba8920d4f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditSubkeyDialogFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditSubkeyDialogFragment.java @@ -75,22 +75,7 @@ public class EditSubkeyDialogFragment extends DialogFragment { sendMessageToHandler(MESSAGE_REVOKE, null); break; case 2: - CustomAlertDialogBuilder stripAlertDialog = new CustomAlertDialogBuilder(getActivity()); - stripAlertDialog.setTitle(getResources().getString(R.string.title_alert_strip)). - setMessage(R.string.alert_strip).setCancelable(true); - stripAlertDialog.setPositiveButton(R.string.strip, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialogInterface, int i) { - sendMessageToHandler(MESSAGE_STRIP, null); - } - }); - stripAlertDialog.setNegativeButton(R.string.btn_do_not_save, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialogInterface, int i) { - dismiss(); - } - }); - stripAlertDialog.show(); + showAlertDialog(); break; case 3: sendMessageToHandler(MESSAGE_MOVE_KEY_TO_CARD, null); @@ -110,6 +95,25 @@ public class EditSubkeyDialogFragment extends DialogFragment { return builder.show(); } + private void showAlertDialog() { + CustomAlertDialogBuilder stripAlertDialog = new CustomAlertDialogBuilder(getActivity()); + stripAlertDialog.setTitle(getResources().getString(R.string.title_alert_strip)). + setMessage(R.string.alert_strip).setCancelable(true); + stripAlertDialog.setPositiveButton(R.string.strip, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + sendMessageToHandler(MESSAGE_STRIP, null); + } + }); + stripAlertDialog.setNegativeButton(R.string.btn_do_not_save, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + dismiss(); + } + }); + stripAlertDialog.show(); + } + /** * Send message back to handler which is initialized in a activity * -- cgit v1.2.3 From 5411963aff0ed017f949de5cdbcf9a83d0e2087a Mon Sep 17 00:00:00 2001 From: Victor Hazali Date: Wed, 30 Mar 2016 06:07:59 +0800 Subject: Refactored switch statements to use constants --- .../keychain/ui/dialog/EditSubkeyDialogFragment.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditSubkeyDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditSubkeyDialogFragment.java index ba8920d4f..01decf2ef 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditSubkeyDialogFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditSubkeyDialogFragment.java @@ -36,6 +36,10 @@ public class EditSubkeyDialogFragment extends DialogFragment { public static final int MESSAGE_REVOKE = 2; public static final int MESSAGE_STRIP = 3; public static final int MESSAGE_MOVE_KEY_TO_CARD = 4; + public static final int SUBKEY_MENU_CHANGE_EXPIRY = 0; + public static final int SUBKEY_MENU_REVOKE_SUBKEY = 1; + public static final int SUBKEY_MENU_STRIP_SUBKEY = 2; + public static final int SUBKEY_MENU_MOVE_TO_SECURITY_TOKEN = 3; private Messenger mMessenger; @@ -68,16 +72,16 @@ public class EditSubkeyDialogFragment extends DialogFragment { @Override public void onClick(DialogInterface dialog, int which) { switch (which) { - case 0: + case SUBKEY_MENU_CHANGE_EXPIRY: sendMessageToHandler(MESSAGE_CHANGE_EXPIRY, null); break; - case 1: + case SUBKEY_MENU_REVOKE_SUBKEY: sendMessageToHandler(MESSAGE_REVOKE, null); break; - case 2: + case SUBKEY_MENU_STRIP_SUBKEY: showAlertDialog(); break; - case 3: + case SUBKEY_MENU_MOVE_TO_SECURITY_TOKEN: sendMessageToHandler(MESSAGE_MOVE_KEY_TO_CARD, null); break; default: @@ -98,7 +102,7 @@ public class EditSubkeyDialogFragment extends DialogFragment { private void showAlertDialog() { CustomAlertDialogBuilder stripAlertDialog = new CustomAlertDialogBuilder(getActivity()); stripAlertDialog.setTitle(getResources().getString(R.string.title_alert_strip)). - setMessage(R.string.alert_strip).setCancelable(true); + setMessage(R.string.alert_strip).setCancelable(true); stripAlertDialog.setPositiveButton(R.string.strip, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { -- cgit v1.2.3 From 990948e3fbb52b879b517c18c06328e7d005d236 Mon Sep 17 00:00:00 2001 From: Durgesh <007durgesh219@gmail.com> Date: Mon, 7 Mar 2016 17:29:06 +0530 Subject: Fix Display Key in UploadKeyActivity, Issue #506 --- .../keychain/ui/CertifyKeyActivity.java | 1 + .../keychain/ui/CertifyKeyFragment.java | 6 +++--- .../keychain/ui/MultiUserIdsFragment.java | 14 ++++++++++---- .../keychain/ui/UploadKeyActivity.java | 21 +++++++-------------- .../keychain/ui/ViewKeyAdvShareFragment.java | 11 +++++++++++ .../keychain/ui/adapter/MultiUserIdsAdapter.java | 7 +++++++ 6 files changed, 39 insertions(+), 21 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java index 32da02efe..09149716c 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java @@ -28,6 +28,7 @@ import org.sufficientlysecure.keychain.ui.base.BaseActivity; public class CertifyKeyActivity extends BaseActivity { public static final String EXTRA_RESULT = "operation_result"; + // For sending masterKeyIds to MultiUserIdsFragment to display list of keys public static final String EXTRA_KEY_IDS = MultiUserIdsFragment.EXTRA_KEY_IDS ; public static final String EXTRA_CERTIFY_KEY_ID = "certify_key_id"; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyFragment.java index 22cfabcc9..ad39ff43d 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyFragment.java @@ -74,13 +74,14 @@ public class CertifyKeyFragment public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); - if (savedInstanceState == null){ + if (savedInstanceState == null) { // preselect certify key id if given long certifyKeyId = getActivity().getIntent() .getLongExtra(CertifyKeyActivity.EXTRA_CERTIFY_KEY_ID, Constants.key.none); if (certifyKeyId != Constants.key.none) { try { - CachedPublicKeyRing key = (new ProviderHelper(getActivity())).getCachedPublicKeyRing(certifyKeyId); + CachedPublicKeyRing key = (new ProviderHelper(getActivity())) + .getCachedPublicKeyRing(certifyKeyId); if (key.canCertify()) { mCertifyKeySpinner.setPreSelectedKeyId(certifyKeyId); } @@ -88,7 +89,6 @@ public class CertifyKeyFragment Log.e(Constants.TAG, "certify certify check failed", e); } } - } OperationResult result = getActivity().getIntent().getParcelableExtra(CertifyKeyActivity.EXTRA_RESULT); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/MultiUserIdsFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/MultiUserIdsFragment.java index b61ec79ee..8ba695cf7 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/MultiUserIdsFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/MultiUserIdsFragment.java @@ -26,12 +26,10 @@ import org.sufficientlysecure.keychain.util.Log; import java.util.ArrayList; -/** - * Created by durgeshchoudhary on 07/03/16. - */ public class MultiUserIdsFragment extends Fragment implements LoaderManager.LoaderCallbacks{ public static final String ARG_CHECK_STATES = "check_states"; public static final String EXTRA_KEY_IDS = "extra_key_ids"; + private boolean checkboxVisibility = true; ListView mUserIds; private MultiUserIdsAdapter mUserIdsAdapter; @@ -78,7 +76,7 @@ public class MultiUserIdsFragment extends Fragment implements LoaderManager.Load checkedStates = (ArrayList) savedInstanceState.getSerializable(ARG_CHECK_STATES); } - mUserIdsAdapter = new MultiUserIdsAdapter(getActivity(), null, 0, checkedStates); + mUserIdsAdapter = new MultiUserIdsAdapter(getActivity(), null, 0, checkedStates, checkboxVisibility); mUserIds.setAdapter(mUserIdsAdapter); mUserIds.setDividerHeight(0); @@ -95,6 +93,10 @@ public class MultiUserIdsFragment extends Fragment implements LoaderManager.Load } public ArrayList getSelectedCertifyActions() { + if (!checkboxVisibility) { + throw new AssertionError("Item selection not allowed"); + } + return mUserIdsAdapter.getSelectedCertifyActions(); } @@ -214,4 +216,8 @@ public class MultiUserIdsFragment extends Fragment implements LoaderManager.Load public void onLoaderReset(Loader loader) { mUserIdsAdapter.swapCursor(null); } + + public void setCheckboxVisibility(boolean checkboxVisibility) { + this.checkboxVisibility = checkboxVisibility; + } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/UploadKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/UploadKeyActivity.java index f38e4928d..306b022c1 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/UploadKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/UploadKeyActivity.java @@ -31,10 +31,7 @@ import android.widget.Spinner; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.operations.results.UploadResult; -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.ProviderHelper; import org.sufficientlysecure.keychain.service.UploadKeyringParcel; import org.sufficientlysecure.keychain.ui.base.BaseActivity; import org.sufficientlysecure.keychain.ui.base.CryptoOperationHelper; @@ -53,7 +50,6 @@ public class UploadKeyActivity extends BaseActivity // CryptoOperationHelper.Callback vars private String mKeyserver; - private long mMasterKeyId; private CryptoOperationHelper mUploadOpHelper; @Override @@ -63,6 +59,10 @@ public class UploadKeyActivity extends BaseActivity mUploadButton = findViewById(R.id.upload_key_action_upload); mKeyServerSpinner = (Spinner) findViewById(R.id.upload_key_keyserver); + MultiUserIdsFragment mMultiUserIdsFragment = (MultiUserIdsFragment) + getSupportFragmentManager().findFragmentById(R.id.multi_user_ids_fragment); + mMultiUserIdsFragment.setCheckboxVisibility(false); + ArrayAdapter adapter = new ArrayAdapter<>(this, android.R.layout.simple_spinner_item, Preferences.getPreferences(this) .getKeyServers() @@ -89,15 +89,6 @@ public class UploadKeyActivity extends BaseActivity return; } - try { - mMasterKeyId = new ProviderHelper(this).getCachedPublicKeyRing( - KeyRings.buildUnifiedKeyRingUri(mDataUri)).getMasterKeyId(); - } catch (PgpKeyNotFoundException e) { - Log.e(Constants.TAG, "Intent data pointed to bad key!"); - finish(); - return; - } - } @Override @@ -136,7 +127,9 @@ public class UploadKeyActivity extends BaseActivity @Override public UploadKeyringParcel createOperationInput() { - return new UploadKeyringParcel(mKeyserver, mMasterKeyId); + long[] masterKeyIds = getIntent().getLongArrayExtra(MultiUserIdsFragment.EXTRA_KEY_IDS); + + return new UploadKeyringParcel(mKeyserver, masterKeyIds[0]); } @Override 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 0aa8330ea..02eae1b2b 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvShareFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvShareFragment.java @@ -455,8 +455,19 @@ public class ViewKeyAdvShareFragment extends LoaderFragment implements } private void uploadToKeyserver() { + long keyId; + try { + keyId = new ProviderHelper(getActivity()) + .getCachedPublicKeyRing(mDataUri) + .extractOrGetMasterKeyId(); + } catch (PgpKeyNotFoundException e) { + Log.e(Constants.TAG, "key not found!", e); + Notify.create(getActivity(), "key not found", Style.ERROR).show(); + return; + } Intent uploadIntent = new Intent(getActivity(), UploadKeyActivity.class); uploadIntent.setData(mDataUri); + uploadIntent.putExtra(MultiUserIdsFragment.EXTRA_KEY_IDS, new long[]{keyId}); startActivityForResult(uploadIntent, 0); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/MultiUserIdsAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/MultiUserIdsAdapter.java index b91abf076..d247faddc 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/MultiUserIdsAdapter.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/MultiUserIdsAdapter.java @@ -39,6 +39,7 @@ import java.util.ArrayList; public class MultiUserIdsAdapter extends CursorAdapter { private LayoutInflater mInflater; private final ArrayList mCheckStates; + private boolean checkboxVisibility = true; public MultiUserIdsAdapter(Context context, Cursor c, int flags, ArrayList preselectStates) { super(context, c, flags); @@ -46,6 +47,11 @@ public class MultiUserIdsAdapter extends CursorAdapter { mCheckStates = preselectStates == null ? new ArrayList() : preselectStates; } + public MultiUserIdsAdapter(Context context, Cursor c, int flags, ArrayList preselectStates, boolean checkboxVisibility) { + this(context,c,flags,preselectStates); + this.checkboxVisibility = checkboxVisibility; + } + @Override public Cursor swapCursor(Cursor newCursor) { if (newCursor != null) { @@ -138,6 +144,7 @@ public class MultiUserIdsAdapter extends CursorAdapter { } }); vCheckBox.setClickable(false); + vCheckBox.setVisibility(checkboxVisibility?View.VISIBLE:View.GONE); View vUidBody = view.findViewById(R.id.user_id_body); vUidBody.setClickable(true); -- cgit v1.2.3 From e627006fcfecdc84b28298bdf4815aaa7d67cdfa Mon Sep 17 00:00:00 2001 From: Victor Hazali Date: Fri, 1 Apr 2016 10:34:52 +0800 Subject: setTitle now uses resource id directly --- .../sufficientlysecure/keychain/ui/dialog/EditSubkeyDialogFragment.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditSubkeyDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditSubkeyDialogFragment.java index 01decf2ef..9f5ffc358 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditSubkeyDialogFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditSubkeyDialogFragment.java @@ -101,7 +101,7 @@ public class EditSubkeyDialogFragment extends DialogFragment { private void showAlertDialog() { CustomAlertDialogBuilder stripAlertDialog = new CustomAlertDialogBuilder(getActivity()); - stripAlertDialog.setTitle(getResources().getString(R.string.title_alert_strip)). + stripAlertDialog.setTitle(R.string.title_alert_strip). setMessage(R.string.alert_strip).setCancelable(true); stripAlertDialog.setPositiveButton(R.string.strip, new DialogInterface.OnClickListener() { @Override -- cgit v1.2.3 From cb9bdb3cf72ec387e6f34d29a31e701f5f5e7d92 Mon Sep 17 00:00:00 2001 From: Alex Fong Date: Mon, 21 Mar 2016 21:37:19 +0800 Subject: Redesigned subkey creation dialog and changed default key type created to RSA, 3072 bit. Added code to prevent removal of master subkey when modifying a new key. --- .../keychain/ui/CreateKeyFinalFragment.java | 6 +- .../keychain/ui/EditKeyFragment.java | 10 +- .../keychain/ui/adapter/SubkeysAddedAdapter.java | 48 ++- .../ui/dialog/AddSubkeyDialogFragment.java | 473 +++++++-------------- .../ui/util/spinner/FocusFirstItemSpinner.java | 77 ++++ .../sufficientlysecure/keychain/util/Choice.java | 9 +- 6 files changed, 271 insertions(+), 352 deletions(-) create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/spinner/FocusFirstItemSpinner.java (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java index b53bfc1d0..e1d20f2e1 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java @@ -281,11 +281,11 @@ public class CreateKeyFinalFragment extends Fragment { saveKeyringParcel.mNewUnlock = new ChangeUnlockParcel(new Passphrase(), null); } else { saveKeyringParcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(Algorithm.RSA, - 4096, null, KeyFlags.CERTIFY_OTHER, 0L)); + 3072, null, KeyFlags.CERTIFY_OTHER, 0L)); saveKeyringParcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(Algorithm.RSA, - 4096, null, KeyFlags.SIGN_DATA, 0L)); + 3072, null, KeyFlags.SIGN_DATA, 0L)); saveKeyringParcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(Algorithm.RSA, - 4096, null, KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE, 0L)); + 3072, null, KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE, 0L)); saveKeyringParcel.mNewUnlock = createKeyActivity.mPassphrase != null ? new ChangeUnlockParcel(createKeyActivity.mPassphrase, null) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java index 2d94d0d93..1571a7104 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java @@ -562,15 +562,9 @@ public class EditKeyFragment extends QueueingCryptoOperationFragment> choices = new ArrayList<>(); - choices.add(new Choice<>(Algorithm.DSA, getResources().getString( - R.string.dsa))); - if (!mWillBeMasterKey) { - choices.add(new Choice<>(Algorithm.ELGAMAL, getResources().getString( - R.string.elgamal))); - } - choices.add(new Choice<>(Algorithm.RSA, getResources().getString( - R.string.rsa))); - choices.add(new Choice<>(Algorithm.ECDSA, getResources().getString( - R.string.ecdsa))); - choices.add(new Choice<>(Algorithm.ECDH, getResources().getString( - R.string.ecdh))); - ArrayAdapter> adapter = new ArrayAdapter<>(context, + ArrayList> choices = new ArrayList<>(); + choices.add(new Choice<>(SupportedKeyType.RSA_2048, getResources().getString( + R.string.rsa_2048), getResources().getString(R.string.rsa_2048_description_html))); + choices.add(new Choice<>(SupportedKeyType.RSA_3072, getResources().getString( + R.string.rsa_3072), getResources().getString(R.string.rsa_3072_description_html))); + choices.add(new Choice<>(SupportedKeyType.RSA_4096, getResources().getString( + R.string.rsa_4096), getResources().getString(R.string.rsa_4096_description_html))); + choices.add(new Choice<>(SupportedKeyType.ECC_P256, getResources().getString( + R.string.ecc_p256), getResources().getString(R.string.ecc_p256_description_html))); + choices.add(new Choice<>(SupportedKeyType.ECC_P521, getResources().getString( + R.string.ecc_p521), getResources().getString(R.string.ecc_p521_description_html))); + TwoLineArrayAdapter adapter = new TwoLineArrayAdapter(context, android.R.layout.simple_spinner_item, choices); - adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); - mAlgorithmSpinner.setAdapter(adapter); - // make RSA the default + mKeyTypeSpinner.setAdapter(adapter); + // make RSA 3072 the default for (int i = 0; i < choices.size(); ++i) { - if (choices.get(i).getId() == Algorithm.RSA) { - mAlgorithmSpinner.setSelection(i); - break; - } - } - } - - // dynamic ArrayAdapter must be created (instead of ArrayAdapter.getFromResource), because it's content may change - ArrayAdapter keySizeAdapter = new ArrayAdapter<>(context, android.R.layout.simple_spinner_item, - new ArrayList(Arrays.asList(getResources().getStringArray(R.array.rsa_key_size_spinner_values)))); - keySizeAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); - mKeySizeSpinner.setAdapter(keySizeAdapter); - mKeySizeSpinner.setSelection(1); // Default to 4096 for the key length - - { - ArrayList> choices = new ArrayList<>(); - - choices.add(new Choice<>(Curve.NIST_P256, getResources().getString( - R.string.key_curve_nist_p256))); - choices.add(new Choice<>(Curve.NIST_P384, getResources().getString( - R.string.key_curve_nist_p384))); - choices.add(new Choice<>(Curve.NIST_P521, getResources().getString( - R.string.key_curve_nist_p521))); - - /* @see SaveKeyringParcel - choices.add(new Choice(Curve.BRAINPOOL_P256, getResources().getString( - R.string.key_curve_bp_p256))); - choices.add(new Choice(Curve.BRAINPOOL_P384, getResources().getString( - R.string.key_curve_bp_p384))); - choices.add(new Choice(Curve.BRAINPOOL_P512, getResources().getString( - R.string.key_curve_bp_p512))); - */ - - ArrayAdapter> adapter = new ArrayAdapter<>(context, - android.R.layout.simple_spinner_item, choices); - mCurveSpinner.setAdapter(adapter); - // make NIST P-256 the default - for (int i = 0; i < choices.size(); ++i) { - if (choices.get(i).getId() == Curve.NIST_P256) { - mCurveSpinner.setSelection(i); + if (choices.get(i).getId() == SupportedKeyType.RSA_3072) { + mKeyTypeSpinner.setSelection(i); break; } } @@ -215,45 +177,35 @@ public class AddSubkeyDialogFragment extends DialogFragment { final AlertDialog alertDialog = dialog.show(); - mCustomKeyEditText.addTextChangedListener(new TextWatcher() { - @Override - public void beforeTextChanged(CharSequence s, int start, int count, int after) { - } - - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) { - } + mKeyTypeSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { - @Override - public void afterTextChanged(Editable s) { - setOkButtonAvailability(alertDialog); - } - }); - - mKeySizeSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView parent, View view, int position, long id) { - setCustomKeyVisibility(); - setOkButtonAvailability(alertDialog); - } + // noinspection unchecked + SupportedKeyType keyType = ((Choice) parent.getSelectedItem()).getId(); - @Override - public void onNothingSelected(AdapterView parent) { - } - }); + // RadioGroup.getCheckedRadioButtonId() gives the wrong RadioButton checked + // when programmatically unchecking children radio buttons. Clearing all is the only option. + mUsageRadioGroup.clearCheck(); - mAlgorithmSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { - @Override - public void onItemSelected(AdapterView parent, View view, int position, long id) { - updateUiForAlgorithm(((Choice) parent.getSelectedItem()).getId()); + if(mWillBeMasterKey) { + mUsageNone.setChecked(true); + } - setCustomKeyVisibility(); - setOkButtonAvailability(alertDialog); + if (keyType == SupportedKeyType.ECC_P521 || keyType == SupportedKeyType.ECC_P256) { + mUsageSignAndEncrypt.setEnabled(false); + if (mWillBeMasterKey) { + mUsageEncrypt.setEnabled(false); + } + } else { + // need to enable if previously disabled for ECC masterkey + mUsageEncrypt.setEnabled(true); + mUsageSignAndEncrypt.setEnabled(true); + } } @Override - public void onNothingSelected(AdapterView parent) { - } + public void onNothingSelected(AdapterView parent) {} }); return alertDialog; @@ -269,36 +221,74 @@ public class AddSubkeyDialogFragment extends DialogFragment { positiveButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - if (!mFlagCertify.isChecked() && !mFlagSign.isChecked() - && !mFlagEncrypt.isChecked() && !mFlagAuthenticate.isChecked()) { - Toast.makeText(getActivity(), R.string.edit_key_select_flag, Toast.LENGTH_LONG).show(); + if (mUsageRadioGroup.getCheckedRadioButtonId() == -1) { + Toast.makeText(getActivity(), R.string.edit_key_select_usage, Toast.LENGTH_LONG).show(); return; } - Algorithm algorithm = ((Choice) mAlgorithmSpinner.getSelectedItem()).getId(); + // noinspection unchecked + SupportedKeyType keyType = ((Choice) mKeyTypeSpinner.getSelectedItem()).getId(); Curve curve = null; Integer keySize = null; - // For EC keys, add a curve - if (algorithm == Algorithm.ECDH || algorithm == Algorithm.ECDSA) { - curve = ((Choice) mCurveSpinner.getSelectedItem()).getId(); - // Otherwise, get a keysize - } else { - keySize = getProperKeyLength(algorithm, getSelectedKeyLength()); + Algorithm algorithm = null; + + // set keysize & curve, for RSA & ECC respectively + switch (keyType) { + case RSA_2048: { + keySize = 2048; + break; + } + case RSA_3072: { + keySize = 3072; + break; + } + case RSA_4096: { + keySize = 4096; + break; + } + case ECC_P256: { + curve = Curve.NIST_P256; + break; + } + case ECC_P521: { + curve = Curve.NIST_P521; + break; + } } + // set algorithm + switch (keyType) { + case RSA_2048: + case RSA_3072: + case RSA_4096: { + algorithm = Algorithm.RSA; + break; + } + + case ECC_P256: + case ECC_P521: { + if(mUsageEncrypt.isChecked()) { + algorithm = Algorithm.ECDH; + } else { + algorithm = Algorithm.ECDSA; + } + break; + } + } + + // set flags int flags = 0; - if (mFlagCertify.isChecked()) { + if (mWillBeMasterKey) { flags |= KeyFlags.CERTIFY_OTHER; } - if (mFlagSign.isChecked()) { + if (mUsageSign.isChecked()) { flags |= KeyFlags.SIGN_DATA; - } - if (mFlagEncrypt.isChecked()) { + } else if (mUsageEncrypt.isChecked()) { flags |= KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE; + } else if (mUsageSignAndEncrypt.isChecked()) { + flags |= KeyFlags.SIGN_DATA | KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE; } - if (mFlagAuthenticate.isChecked()) { - flags |= KeyFlags.AUTHENTICATION; - } + long expiry; if (mNoExpiryCheckBox.isChecked()) { @@ -332,206 +322,29 @@ public class AddSubkeyDialogFragment extends DialogFragment { } } - private int getSelectedKeyLength() { - final String selectedItemString = (String) mKeySizeSpinner.getSelectedItem(); - final String customLengthString = getResources().getString(R.string.key_size_custom); - final boolean customSelected = customLengthString.equals(selectedItemString); - String keyLengthString = customSelected ? mCustomKeyEditText.getText().toString() : selectedItemString; - int keySize; - try { - keySize = Integer.parseInt(keyLengthString); - } catch (NumberFormatException e) { - keySize = 0; - } - return keySize; - } - - /** - *

RSA

- *

for RSA algorithm, key length must be greater than 2048. Possibility to generate keys bigger - * than 8192 bits is currently disabled, because it's almost impossible to generate them on a mobile device (check - * RSA key length plot and - * Cryptographic Key Length Recommendation). Also, key length must be a - * multiplicity of 8.

- *

ElGamal

- *

For ElGamal algorithm, supported key lengths are 2048, 3072, 4096 or 8192 bits.

- *

DSA

- *

For DSA algorithm key length must be between 2048 and 3072. Also, it must me dividable by 64.

- * - * @return correct key length, according to BouncyCastle specification. Returns -1, if key length is - * inappropriate. - */ - private int getProperKeyLength(Algorithm algorithm, int currentKeyLength) { - final int[] elGamalSupportedLengths = {2048, 3072, 4096, 8192}; - int properKeyLength = -1; - switch (algorithm) { - case RSA: { - if (currentKeyLength >= 2048 && currentKeyLength <= 16384) { - properKeyLength = currentKeyLength + ((8 - (currentKeyLength % 8)) % 8); - } - break; - } - case ELGAMAL: { - int[] elGammalKeyDiff = new int[elGamalSupportedLengths.length]; - for (int i = 0; i < elGamalSupportedLengths.length; i++) { - elGammalKeyDiff[i] = Math.abs(elGamalSupportedLengths[i] - currentKeyLength); - } - int minimalValue = Integer.MAX_VALUE; - int minimalIndex = -1; - for (int i = 0; i < elGammalKeyDiff.length; i++) { - if (elGammalKeyDiff[i] <= minimalValue) { - minimalValue = elGammalKeyDiff[i]; - minimalIndex = i; - } - } - properKeyLength = elGamalSupportedLengths[minimalIndex]; - break; - } - case DSA: { - // Bouncy Castle supports 4096 maximum - if (currentKeyLength >= 2048 && currentKeyLength <= 4096) { - properKeyLength = currentKeyLength + ((64 - (currentKeyLength % 64)) % 64); - } - break; - } + private class TwoLineArrayAdapter extends ArrayAdapter> { + public TwoLineArrayAdapter(Context context, int resource, List> objects) { + super(context, resource, objects); } - return properKeyLength; - } - private void setOkButtonAvailability(AlertDialog alertDialog) { - Algorithm algorithm = ((Choice) mAlgorithmSpinner.getSelectedItem()).getId(); - boolean enabled = algorithm == Algorithm.ECDSA || algorithm == Algorithm.ECDH - || getProperKeyLength(algorithm, getSelectedKeyLength()) > 0; - alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(enabled); - } - private void setCustomKeyVisibility() { - final String selectedItemString = (String) mKeySizeSpinner.getSelectedItem(); - final String customLengthString = getResources().getString(R.string.key_size_custom); - final boolean customSelected = customLengthString.equals(selectedItemString); - final int visibility = customSelected ? View.VISIBLE : View.GONE; - - mCustomKeyEditText.setVisibility(visibility); - mCustomKeyTextView.setVisibility(visibility); - mCustomKeyInfoTextView.setVisibility(visibility); - - // hide keyboard after setting visibility to gone - if (visibility == View.GONE) { - InputMethodManager imm = (InputMethodManager) - getActivity().getSystemService(FragmentActivity.INPUT_METHOD_SERVICE); - imm.hideSoftInputFromWindow(mCustomKeyEditText.getWindowToken(), 0); - } - } + @Override + public View getDropDownView(int position, View convertView, ViewGroup parent) { + // inflate view if not given one + if (convertView == null) { + convertView = getActivity().getLayoutInflater() + .inflate(R.layout.two_line_spinner_dropdown_item, parent, false); + } - private void updateUiForAlgorithm(Algorithm algorithm) { - final ArrayAdapter keySizeAdapter = (ArrayAdapter) mKeySizeSpinner.getAdapter(); - keySizeAdapter.clear(); - switch (algorithm) { - case RSA: { - replaceArrayAdapterContent(keySizeAdapter, R.array.rsa_key_size_spinner_values); - mKeySizeSpinner.setSelection(1); - mKeySizeRow.setVisibility(View.VISIBLE); - mCurveRow.setVisibility(View.GONE); - mCustomKeyInfoTextView.setText(getResources().getString(R.string.key_size_custom_info_rsa)); - // allowed flags: - mFlagSign.setEnabled(true); - mFlagEncrypt.setEnabled(true); - mFlagAuthenticate.setEnabled(true); - - if (mWillBeMasterKey) { - mFlagCertify.setEnabled(true); - - mFlagCertify.setChecked(true); - mFlagSign.setChecked(false); - mFlagEncrypt.setChecked(false); - } else { - mFlagCertify.setEnabled(false); + Choice c = this.getItem(position); - mFlagCertify.setChecked(false); - mFlagSign.setChecked(true); - mFlagEncrypt.setChecked(true); - } - mFlagAuthenticate.setChecked(false); - break; - } - case ELGAMAL: { - replaceArrayAdapterContent(keySizeAdapter, R.array.elgamal_key_size_spinner_values); - mKeySizeSpinner.setSelection(3); - mKeySizeRow.setVisibility(View.VISIBLE); - mCurveRow.setVisibility(View.GONE); - mCustomKeyInfoTextView.setText(""); // ElGamal does not support custom key length - // allowed flags: - mFlagCertify.setChecked(false); - mFlagCertify.setEnabled(false); - mFlagSign.setChecked(false); - mFlagSign.setEnabled(false); - mFlagEncrypt.setChecked(true); - mFlagEncrypt.setEnabled(true); - mFlagAuthenticate.setChecked(false); - mFlagAuthenticate.setEnabled(false); - break; - } - case DSA: { - replaceArrayAdapterContent(keySizeAdapter, R.array.dsa_key_size_spinner_values); - mKeySizeSpinner.setSelection(2); - mKeySizeRow.setVisibility(View.VISIBLE); - mCurveRow.setVisibility(View.GONE); - mCustomKeyInfoTextView.setText(getResources().getString(R.string.key_size_custom_info_dsa)); - // allowed flags: - mFlagCertify.setChecked(false); - mFlagCertify.setEnabled(false); - mFlagSign.setChecked(true); - mFlagSign.setEnabled(true); - mFlagEncrypt.setChecked(false); - mFlagEncrypt.setEnabled(false); - mFlagAuthenticate.setChecked(false); - mFlagAuthenticate.setEnabled(false); - break; - } - case ECDSA: { - mKeySizeRow.setVisibility(View.GONE); - mCurveRow.setVisibility(View.VISIBLE); - mCustomKeyInfoTextView.setText(""); - // allowed flags: - mFlagCertify.setEnabled(mWillBeMasterKey); - mFlagCertify.setChecked(mWillBeMasterKey); - mFlagSign.setEnabled(true); - mFlagSign.setChecked(!mWillBeMasterKey); - mFlagEncrypt.setEnabled(false); - mFlagEncrypt.setChecked(false); - mFlagAuthenticate.setEnabled(true); - mFlagAuthenticate.setChecked(false); - break; - } - case ECDH: { - mKeySizeRow.setVisibility(View.GONE); - mCurveRow.setVisibility(View.VISIBLE); - mCustomKeyInfoTextView.setText(""); - // allowed flags: - mFlagCertify.setChecked(false); - mFlagCertify.setEnabled(false); - mFlagSign.setChecked(false); - mFlagSign.setEnabled(false); - mFlagEncrypt.setChecked(true); - mFlagEncrypt.setEnabled(true); - mFlagAuthenticate.setChecked(false); - mFlagAuthenticate.setEnabled(false); - break; - } - } - keySizeAdapter.notifyDataSetChanged(); + TextView text1 = (TextView) convertView.findViewById(android.R.id.text1); + TextView text2 = (TextView) convertView.findViewById(android.R.id.text2); - } + text1.setText(c.getName()); + text2.setText(Html.fromHtml(c.getDescription())); - @TargetApi(Build.VERSION_CODES.HONEYCOMB) - private void replaceArrayAdapterContent(ArrayAdapter arrayAdapter, int stringArrayResourceId) { - final String[] spinnerValuesStringArray = getResources().getStringArray(stringArrayResourceId); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { - arrayAdapter.addAll(spinnerValuesStringArray); - } else { - for (final String value : spinnerValuesStringArray) { - arrayAdapter.add(value); - } + return convertView; } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/spinner/FocusFirstItemSpinner.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/spinner/FocusFirstItemSpinner.java new file mode 100644 index 000000000..7919a0918 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/spinner/FocusFirstItemSpinner.java @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2016 Alex Fong Jie Wen + * + * 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 . + */ + +package org.sufficientlysecure.keychain.ui.util.spinner; + +import android.content.Context; +import android.util.AttributeSet; +import android.widget.Spinner; + +/** + * Custom spinner which uses a hack to + * always set focus on first item in list + * + */ +public class FocusFirstItemSpinner extends Spinner { + /** + * Spinner is originally designed to set focus on the currently selected item. + * When Spinner is selected to show dropdown, 'performClick()' is called internally. + * 'getSelectedItemPosition()' is then called to obtain the item to focus on. + * We use a toggle to have 'getSelectedItemPosition()' return the 0th index + * for this particular case. + */ + + private boolean mToggleFlag = true; + + public FocusFirstItemSpinner(Context context, AttributeSet attrs, + int defStyle, int mode) { + super(context, attrs, defStyle, mode); + } + + public FocusFirstItemSpinner(Context context, AttributeSet attrs, + int defStyle) { + super(context, attrs, defStyle); + } + + public FocusFirstItemSpinner(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public FocusFirstItemSpinner(Context context, int mode) { + super(context, mode); + } + + public FocusFirstItemSpinner(Context context) { + super(context); + } + + @Override + public int getSelectedItemPosition() { + if (!mToggleFlag) { + return 0; + } + return super.getSelectedItemPosition(); + } + + @Override + public boolean performClick() { + mToggleFlag = false; + boolean result = super.performClick(); + mToggleFlag = true; + return result; + } +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Choice.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Choice.java index 48f10d4b9..5ffce9f24 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Choice.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Choice.java @@ -18,12 +18,15 @@ package org.sufficientlysecure.keychain.util; public class Choice { + private String mName; private E mId; + private String mDescription; - public Choice(E id, String name) { + public Choice(E id, String name, String description) { mId = id; mName = name; + mDescription = description; } public E getId() { @@ -34,6 +37,10 @@ public class Choice { return mName; } + public String getDescription() { + return mDescription; + } + @Override public String toString() { return mName; -- cgit v1.2.3 From db3e90821cfff9ac8fe369fdcbbf8ce7e708ba15 Mon Sep 17 00:00:00 2001 From: Victor Hazali Date: Mon, 4 Apr 2016 18:52:22 +0800 Subject: Used a constant instead of magic number for colour Explicitly stated the blending mode --- .../main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java index 6c96a40ba..d81797454 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java @@ -33,6 +33,7 @@ import android.content.Intent; import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.Color; +import android.graphics.PorterDuff; import android.net.Uri; import android.nfc.NfcAdapter; import android.os.AsyncTask; @@ -924,7 +925,7 @@ public class ViewKeyActivity extends BaseSecurityTokenNfcActivity implements } mPhoto.setImageBitmap(photo); - mPhoto.setColorFilter(Color.argb(30, 120, 166, 69)); + mPhoto.setColorFilter(getResources().getColor(R.color.toolbar_photo_tint), PorterDuff.Mode.SRC_ATOP); mPhotoLayout.setVisibility(View.VISIBLE); } }; -- cgit v1.2.3 From aec4744b31b74e697a147b30a3eda2f5b381c9e2 Mon Sep 17 00:00:00 2001 From: Durgesh <007durgesh219@gmail.com> Date: Tue, 5 Apr 2016 02:07:29 +0530 Subject: Fix Unusable signing key not properly disabled, Issue #1468 Signed-off-by: Durgesh <007durgesh219@gmail.com> --- .../org/sufficientlysecure/keychain/ui/widget/CertifyKeySpinner.java | 5 ----- .../org/sufficientlysecure/keychain/ui/widget/SignKeySpinner.java | 5 ----- 2 files changed, 10 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/CertifyKeySpinner.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/CertifyKeySpinner.java index 6a51085f3..63afb1e8b 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/CertifyKeySpinner.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/CertifyKeySpinner.java @@ -113,11 +113,6 @@ public class CertifyKeySpinner extends KeySpinner { @Override boolean isItemEnabled(Cursor cursor) { - // "none" entry is always enabled! - if (cursor.getPosition() == 0) { - return true; - } - if (cursor.getInt(KeyAdapter.INDEX_IS_REVOKED) != 0) { return false; } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SignKeySpinner.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SignKeySpinner.java index 8fb9e38aa..0c2d93ad9 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SignKeySpinner.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SignKeySpinner.java @@ -72,11 +72,6 @@ public class SignKeySpinner extends KeySpinner { @Override boolean isItemEnabled(Cursor cursor) { - // "none" entry is always enabled! - if (cursor.getPosition() == 0) { - return true; - } - if (cursor.getInt(KeyAdapter.INDEX_IS_REVOKED) != 0) { return false; } -- cgit v1.2.3