aboutsummaryrefslogtreecommitdiffstats
path: root/OpenKeychain/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'OpenKeychain/src/main')
-rw-r--r--OpenKeychain/src/main/AndroidManifest.xml7
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/CloudSearch.java4
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/HkpKeyserver.java4
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/ImportKeysListEntry.java12
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/KeybaseKeyserver.java4
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/BaseOperation.java6
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/CertifyOperation.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/EditKeyOperation.java3
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ImportExportOperation.java50
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/PromoteKeyOperation.java103
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/DecryptVerifyResult.java11
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/ImportKeyResult.java4
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java17
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/PromoteKeyResult.java53
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/SignEncryptResult.java16
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedKeyRing.java1
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedPublicKey.java8
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedPublicKeyRing.java13
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKey.java8
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKeyRing.java14
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/OpenPgpSignatureResultBuilder.java3
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java313
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java128
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java138
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java14
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedPublicKey.java55
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedSignature.java5
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java12
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java36
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java86
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/RemoteService.java5
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountSettingsActivity.java17
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AppSettingsActivity.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AppsListActivity.java24
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/RemoteServiceActivity.java399
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/CertifyActionsParcel.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java448
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java3
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java67
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BaseActivity.java80
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java3
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyFragment.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyActivity.java1
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java1
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyInputFragment.java4
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptActivity.java4
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesActivity.java1
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextActivity.java1
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextFragment.java17
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java1
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java36
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java5
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java12
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java4
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java11
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/FirstTimeActivity.java1
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java175
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysCloudFragment.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListActivity.java20
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java172
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LogDisplayActivity.java5
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NavDrawerActivity.java56
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcActivity.java62
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcIntentActivity.java1
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseWizardActivity.java8
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/QrCodeScanActivity.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/QrCodeViewActivity.java5
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SafeSlingerActivity.java9
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectPublicKeyActivity.java12
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectPublicKeyFragment.java5
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsKeyServerActivity.java16
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/UploadKeyActivity.java3
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewCertActivity.java4
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvancedActivity.java6
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyShareFragment.java5
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysAdapter.java4
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListCloudLoader.java8
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListLoader.java21
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyValueSpinnerAdapter.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/MultiUserIdsAdapter.java6
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/PagerTabStripAdapter.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java8
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/TabsAdapter.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAdapter.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddSubkeyDialogFragment.java26
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddUserIdDialogFragment.java4
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteFileDialogFragment.java1
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/ActionBarHelper.java99
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/QrCodeUtils.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/CertifyKeySpinner.java1
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionView.java4
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/FoldableLinearLayout.java39
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/ListAwareSwipeRefreshLayout.java5
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SignKeySpinner.java1
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/AlgorithmNames.java7
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ContactHelper.java40
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/EmailKeyHelper.java10
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ExportHelper.java8
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Iso7816TLV.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/KeyUpdateHelper.java15
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Log.java3
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ParcelableFileCache.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Preferences.java4
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ShareHelper.java10
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/TlsHelper.java10
-rw-r--r--OpenKeychain/src/main/res/drawable-hdpi/ic_action_collapse.pngbin467 -> 0 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-hdpi/ic_action_expand.pngbin415 -> 0 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-hdpi/ic_apps_black_24dp.pngbin0 -> 182 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-hdpi/ic_check_white_24dp.pngbin0 -> 309 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-hdpi/ic_close_white_24dp.pngbin0 -> 324 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-hdpi/ic_cloud_search_24px.pngbin0 -> 1025 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-hdpi/ic_expand_less_black_24dp.pngbin0 -> 234 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-hdpi/ic_expand_more_black_24dp.pngbin0 -> 244 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-hdpi/ic_lock_open_black_24dp.pngbin0 -> 393 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-hdpi/ic_lock_outline_black_24dp.pngbin0 -> 398 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-hdpi/ic_refresh_white_24dp.pngbin0 -> 531 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-hdpi/ic_settings_black_24dp.pngbin0 -> 561 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-hdpi/ic_vpn_key_black_24dp.pngbin0 -> 381 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-mdpi/ic_action_collapse.pngbin404 -> 0 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-mdpi/ic_action_expand.pngbin345 -> 0 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-mdpi/ic_apps_black_24dp.pngbin0 -> 173 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-mdpi/ic_check_white_24dp.pngbin0 -> 243 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-mdpi/ic_close_white_24dp.pngbin0 -> 279 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-mdpi/ic_cloud_search_24px.pngbin0 -> 712 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-mdpi/ic_expand_less_black_24dp.pngbin0 -> 206 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-mdpi/ic_expand_more_black_24dp.pngbin0 -> 206 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-mdpi/ic_lock_open_black_24dp.pngbin0 -> 295 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-mdpi/ic_lock_outline_black_24dp.pngbin0 -> 294 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-mdpi/ic_refresh_white_24dp.pngbin0 -> 346 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-mdpi/ic_settings_black_24dp.pngbin0 -> 416 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-mdpi/ic_vpn_key_black_24dp.pngbin0 -> 293 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xhdpi/ic_action_collapse.pngbin631 -> 0 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xhdpi/ic_action_expand.pngbin582 -> 0 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xhdpi/ic_apps_black_24dp.pngbin0 -> 193 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xhdpi/ic_check_white_24dp.pngbin0 -> 363 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xhdpi/ic_close_white_24dp.pngbin0 -> 402 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xhdpi/ic_cloud_search_24px.pngbin0 -> 1428 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xhdpi/ic_expand_less_black_24dp.pngbin0 -> 259 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xhdpi/ic_expand_more_black_24dp.pngbin0 -> 272 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xhdpi/ic_lock_open_black_24dp.pngbin0 -> 450 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xhdpi/ic_lock_outline_black_24dp.pngbin0 -> 484 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xhdpi/ic_refresh_white_24dp.pngbin0 -> 637 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xhdpi/ic_settings_black_24dp.pngbin0 -> 691 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xhdpi/ic_vpn_key_black_24dp.pngbin0 -> 446 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xxhdpi/ic_action_collapse.pngbin901 -> 0 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xxhdpi/ic_action_expand.pngbin974 -> 0 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xxhdpi/ic_apps_black_24dp.pngbin0 -> 213 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xxhdpi/ic_check_white_24dp.pngbin0 -> 460 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xxhdpi/ic_close_white_24dp.pngbin0 -> 492 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xxhdpi/ic_cloud_search_24px.pngbin0 -> 2128 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xxhdpi/ic_expand_less_black_24dp.pngbin0 -> 304 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xxhdpi/ic_expand_more_black_24dp.pngbin0 -> 316 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xxhdpi/ic_lock_open_black_24dp.pngbin0 -> 615 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xxhdpi/ic_lock_outline_black_24dp.pngbin0 -> 675 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xxhdpi/ic_refresh_white_24dp.pngbin0 -> 875 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xxhdpi/ic_settings_black_24dp.pngbin0 -> 969 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xxhdpi/ic_vpn_key_black_24dp.pngbin0 -> 622 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xxxhdpi/ic_apps_black_24dp.pngbin0 -> 236 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xxxhdpi/ic_check_white_24dp.pngbin0 -> 587 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xxxhdpi/ic_close_white_24dp.pngbin0 -> 662 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xxxhdpi/ic_expand_less_black_24dp.pngbin0 -> 360 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xxxhdpi/ic_expand_more_black_24dp.pngbin0 -> 379 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xxxhdpi/ic_lock_open_black_24dp.pngbin0 -> 881 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xxxhdpi/ic_lock_outline_black_24dp.pngbin0 -> 883 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xxxhdpi/ic_refresh_white_24dp.pngbin0 -> 1148 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xxxhdpi/ic_settings_black_24dp.pngbin0 -> 1257 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xxxhdpi/ic_vpn_key_black_24dp.pngbin0 -> 789 bytes
-rw-r--r--OpenKeychain/src/main/res/layout/actionbar_custom_view_done.xml26
-rw-r--r--OpenKeychain/src/main/res/layout/actionbar_custom_view_done_cancel.xml28
-rw-r--r--OpenKeychain/src/main/res/layout/custom_drawer.xml16
-rw-r--r--OpenKeychain/src/main/res/layout/foldable_linearlayout.xml2
-rw-r--r--OpenKeychain/src/main/res/layout/full_screen_dialog.xml10
-rw-r--r--OpenKeychain/src/main/res/layout/full_screen_dialog_2.xml12
-rw-r--r--OpenKeychain/src/main/res/layout/full_screen_dialog_2_cancel_button.xml (renamed from OpenKeychain/src/main/res/layout/actionbar_include_cancel_button.xml)20
-rw-r--r--OpenKeychain/src/main/res/layout/full_screen_dialog_2_done_button.xml (renamed from OpenKeychain/src/main/res/layout/actionbar_include_done_button.xml)20
-rw-r--r--OpenKeychain/src/main/res/layout/full_screen_dialog_done_button.xml25
-rw-r--r--OpenKeychain/src/main/res/layout/full_screen_dialog_old.xml10
-rw-r--r--OpenKeychain/src/main/res/menu/key_list.xml3
-rw-r--r--OpenKeychain/src/main/res/values/strings.xml14
-rw-r--r--OpenKeychain/src/main/res/values/themes.xml15
182 files changed, 2090 insertions, 1312 deletions
diff --git a/OpenKeychain/src/main/AndroidManifest.xml b/OpenKeychain/src/main/AndroidManifest.xml
index 536b66319..865e0272d 100644
--- a/OpenKeychain/src/main/AndroidManifest.xml
+++ b/OpenKeychain/src/main/AndroidManifest.xml
@@ -75,7 +75,7 @@
android:theme="@style/KeychainTheme"
android:label="@string/app_name">
<activity
- android:name=".ui.KeyListActivity"
+ android:name=".ui.MainActivity"
android:configChanges="orientation|screenSize|keyboardHidden|keyboard"
android:label="@string/app_name"
android:launchMode="singleTop">
@@ -86,6 +86,11 @@
</intent-filter>
</activity>
<activity
+ android:name=".ui.KeyListActivity"
+ android:configChanges="orientation|screenSize|keyboardHidden|keyboard"
+ android:label="@string/app_name"
+ android:windowSoftInputMode="stateAlwaysHidden" />
+ <activity
android:name=".ui.FirstTimeActivity"
android:configChanges="orientation|screenSize|keyboardHidden|keyboard"
android:label="@string/app_name"
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/CloudSearch.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/CloudSearch.java
index 255ca1cde..3b281876f 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/CloudSearch.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/CloudSearch.java
@@ -32,10 +32,10 @@ public class CloudSearch {
public static ArrayList<ImportKeysListEntry> search(final String query, Preferences.CloudSearchPrefs cloudPrefs)
throws Keyserver.CloudSearchFailureException {
- final ArrayList<Keyserver> servers = new ArrayList<Keyserver>();
+ final ArrayList<Keyserver> servers = new ArrayList<>();
// it's a Vector for sync, multiple threads might report problems
- final Vector<Keyserver.CloudSearchFailureException> problems = new Vector<Keyserver.CloudSearchFailureException>();
+ final Vector<Keyserver.CloudSearchFailureException> problems = new Vector<>();
if (cloudPrefs.searchKeyserver) {
servers.add(new HkpKeyserver(cloudPrefs.keyserver));
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/HkpKeyserver.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/HkpKeyserver.java
index 7f07b8162..f39c552a3 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/HkpKeyserver.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/HkpKeyserver.java
@@ -234,7 +234,7 @@ public class HkpKeyserver extends Keyserver {
@Override
public ArrayList<ImportKeysListEntry> search(String query) throws QueryFailedException,
QueryNeedsRepairException {
- ArrayList<ImportKeysListEntry> results = new ArrayList<ImportKeysListEntry>();
+ ArrayList<ImportKeysListEntry> results = new ArrayList<>();
if (query.length() < 3) {
throw new QueryTooShortException();
@@ -305,7 +305,7 @@ public class HkpKeyserver extends Keyserver {
entry.setRevoked(matcher.group(6).contains("r"));
entry.setExpired(matcher.group(6).contains("e"));
- ArrayList<String> userIds = new ArrayList<String>();
+ ArrayList<String> userIds = new ArrayList<>();
final String uidLines = matcher.group(7);
final Matcher uidMatcher = UID_LINE.matcher(uidLines);
while (uidMatcher.find()) {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/ImportKeysListEntry.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/ImportKeysListEntry.java
index d60d7757b..1d5ee76a4 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/ImportKeysListEntry.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/ImportKeysListEntry.java
@@ -89,7 +89,7 @@ public class ImportKeysListEntry implements Serializable, Parcelable {
public ImportKeysListEntry createFromParcel(final Parcel source) {
ImportKeysListEntry vr = new ImportKeysListEntry();
vr.mPrimaryUserId = source.readString();
- vr.mUserIds = new ArrayList<String>();
+ vr.mUserIds = new ArrayList<>();
source.readStringList(vr.mUserIds);
vr.mMergedUserIds = (HashMap<String, HashSet<String>>) source.readSerializable();
vr.mKeyId = source.readLong();
@@ -103,7 +103,7 @@ public class ImportKeysListEntry implements Serializable, Parcelable {
vr.mSecretKey = source.readByte() == 1;
vr.mSelected = source.readByte() == 1;
vr.mExtraData = source.readString();
- vr.mOrigins = new ArrayList<String>();
+ vr.mOrigins = new ArrayList<>();
source.readStringList(vr.mOrigins);
return vr;
@@ -265,8 +265,8 @@ public class ImportKeysListEntry implements Serializable, Parcelable {
mSecretKey = false;
// do not select by default
mSelected = false;
- mUserIds = new ArrayList<String>();
- mOrigins = new ArrayList<String>();
+ mUserIds = new ArrayList<>();
+ mOrigins = new ArrayList<>();
}
/**
@@ -304,7 +304,7 @@ public class ImportKeysListEntry implements Serializable, Parcelable {
}
public void updateMergedUserIds() {
- mMergedUserIds = new HashMap<String, HashSet<String>>();
+ mMergedUserIds = new HashMap<>();
for (String userId : mUserIds) {
String[] userIdSplit = KeyRing.splitUserId(userId);
@@ -315,7 +315,7 @@ public class ImportKeysListEntry implements Serializable, Parcelable {
// email
if (userIdSplit[1] != null) {
if (!mMergedUserIds.containsKey(userIdSplit[0])) {
- HashSet<String> emails = new HashSet<String>();
+ HashSet<String> emails = new HashSet<>();
emails.add(userIdSplit[1]);
mMergedUserIds.put(userIdSplit[0], emails);
} else {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/KeybaseKeyserver.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/KeybaseKeyserver.java
index 2363a40b3..e310e9a3f 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/KeybaseKeyserver.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/KeybaseKeyserver.java
@@ -36,7 +36,7 @@ public class KeybaseKeyserver extends Keyserver {
@Override
public ArrayList<ImportKeysListEntry> search(String query) throws QueryFailedException,
QueryNeedsRepairException {
- ArrayList<ImportKeysListEntry> results = new ArrayList<ImportKeysListEntry>();
+ ArrayList<ImportKeysListEntry> results = new ArrayList<>();
if (query.startsWith("0x")) {
// cut off "0x" if a user is searching for a key id
@@ -81,7 +81,7 @@ public class KeybaseKeyserver extends Keyserver {
final int algorithmId = match.getAlgorithmId();
entry.setAlgorithm(KeyFormattingUtils.getAlgorithmInfo(algorithmId, bitStrength, null));
- ArrayList<String> userIds = new ArrayList<String>();
+ ArrayList<String> userIds = new ArrayList<>();
String name = "<keybase.io/" + username + ">";
if (fullName != null) {
name = fullName + " " + name;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/BaseOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/BaseOperation.java
index c400eb813..e796bdc91 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/BaseOperation.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/BaseOperation.java
@@ -77,6 +77,12 @@ public abstract class BaseOperation implements PassphraseCacheInterface {
return mCancelled != null && mCancelled.get();
}
+ protected void setPreventCancel () {
+ if (mProgressable != null) {
+ mProgressable.setPreventCancel();
+ }
+ }
+
@Override
public String getCachedPassphrase(long subKeyId) throws NoSecretKeyException {
try {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/CertifyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/CertifyOperation.java
index a5eb95b07..3b391814e 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/CertifyOperation.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/CertifyOperation.java
@@ -78,7 +78,7 @@ public class CertifyOperation extends BaseOperation {
return new CertifyResult(CertifyResult.RESULT_ERROR, log);
}
- ArrayList<UncachedKeyRing> certifiedKeys = new ArrayList<UncachedKeyRing>();
+ ArrayList<UncachedKeyRing> certifiedKeys = new ArrayList<>();
log.add(LogType.MSG_CRT_CERTIFYING, 1);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/EditKeyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/EditKeyOperation.java
index 4d466593b..106c62688 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/EditKeyOperation.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/EditKeyOperation.java
@@ -11,7 +11,6 @@ import org.sufficientlysecure.keychain.pgp.Progressable;
import org.sufficientlysecure.keychain.pgp.UncachedKeyRing;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.provider.ProviderHelper.NotFoundException;
-import org.sufficientlysecure.keychain.service.CertifyActionsParcel;
import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType;
import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog;
import org.sufficientlysecure.keychain.operations.results.SaveKeyringResult;
@@ -29,7 +28,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
* create key operations in PgpKeyOperation. It takes care of fetching
* and saving the key before and after the operation.
*
- * @see CertifyActionsParcel
+ * @see SaveKeyringParcel
*
*/
public class EditKeyOperation extends BaseOperation {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ImportExportOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ImportExportOperation.java
index 6ca28142f..3f3e0a432 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ImportExportOperation.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ImportExportOperation.java
@@ -30,6 +30,7 @@ import org.sufficientlysecure.keychain.keyimport.KeybaseKeyserver;
import org.sufficientlysecure.keychain.keyimport.Keyserver;
import org.sufficientlysecure.keychain.keyimport.Keyserver.AddKeyException;
import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing;
+import org.sufficientlysecure.keychain.operations.results.ConsolidateResult;
import org.sufficientlysecure.keychain.operations.results.ExportResult;
import org.sufficientlysecure.keychain.pgp.CanonicalizedKeyRing;
import org.sufficientlysecure.keychain.pgp.CanonicalizedPublicKeyRing;
@@ -44,9 +45,12 @@ import org.sufficientlysecure.keychain.operations.results.OperationResult.LogTyp
import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog;
import org.sufficientlysecure.keychain.operations.results.ImportKeyResult;
import org.sufficientlysecure.keychain.operations.results.SaveKeyringResult;
+import org.sufficientlysecure.keychain.service.ContactSyncAdapterService;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.util.FileHelper;
import org.sufficientlysecure.keychain.util.Log;
+import org.sufficientlysecure.keychain.util.ParcelableFileCache;
+import org.sufficientlysecure.keychain.util.ParcelableFileCache.IteratorWithSize;
import org.sufficientlysecure.keychain.util.ProgressScaler;
import java.io.BufferedOutputStream;
@@ -58,6 +62,7 @@ import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Iterator;
+import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
/** An operation class which implements high level import and export
@@ -123,6 +128,35 @@ public class ImportExportOperation extends BaseOperation {
}
}
+ public ImportKeyResult importKeyRings(List<ParcelableKeyRing> entries, String keyServerUri) {
+
+ Iterator<ParcelableKeyRing> it = entries.iterator();
+ int numEntries = entries.size();
+
+ return importKeyRings(it, numEntries, keyServerUri);
+
+ }
+
+ public ImportKeyResult importKeyRings(ParcelableFileCache<ParcelableKeyRing> cache, String keyServerUri) {
+
+ // get entries from cached file
+ try {
+ IteratorWithSize<ParcelableKeyRing> it = cache.readCache();
+ int numEntries = it.getSize();
+
+ return importKeyRings(it, numEntries, keyServerUri);
+ } catch (IOException e) {
+
+ // Special treatment here, we need a lot
+ OperationLog log = new OperationLog();
+ log.add(LogType.MSG_IMPORT, 0, 0);
+ log.add(LogType.MSG_IMPORT_ERROR_IO, 0, 0);
+
+ return new ImportKeyResult(ImportKeyResult.RESULT_ERROR, log);
+ }
+
+ }
+
public ImportKeyResult importKeyRings(Iterator<ParcelableKeyRing> entries, int num, String keyServerUri) {
updateProgress(R.string.progress_importing, 0, 100);
@@ -131,13 +165,11 @@ public class ImportExportOperation extends BaseOperation {
// If there aren't even any keys, do nothing here.
if (entries == null || !entries.hasNext()) {
- return new ImportKeyResult(
- ImportKeyResult.RESULT_FAIL_NOTHING, log, 0, 0, 0, 0,
- new long[]{});
+ return new ImportKeyResult(ImportKeyResult.RESULT_FAIL_NOTHING, log);
}
int newKeys = 0, oldKeys = 0, badKeys = 0, secret = 0;
- ArrayList<Long> importedMasterKeyIds = new ArrayList<Long>();
+ ArrayList<Long> importedMasterKeyIds = new ArrayList<>();
boolean cancelled = false;
int position = 0;
@@ -293,6 +325,16 @@ public class ImportExportOperation extends BaseOperation {
position++;
}
+ // Special: consolidate on secret key import (cannot be cancelled!)
+ if (secret > 0) {
+ setPreventCancel();
+ ConsolidateResult result = mProviderHelper.consolidateDatabaseStep1(mProgressable);
+ log.add(result, 1);
+ }
+
+ // Special: make sure new data is synced into contacts
+ ContactSyncAdapterService.requestSync();
+
// convert to long array
long[] importedMasterKeyIdsArray = new long[importedMasterKeyIds.size()];
for (int i = 0; i < importedMasterKeyIds.size(); ++i) {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/PromoteKeyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/PromoteKeyOperation.java
new file mode 100644
index 000000000..f10d11684
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/PromoteKeyOperation.java
@@ -0,0 +1,103 @@
+package org.sufficientlysecure.keychain.operations;
+
+import android.content.Context;
+
+import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.operations.results.PromoteKeyResult;
+import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType;
+import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog;
+import org.sufficientlysecure.keychain.operations.results.PgpEditKeyResult;
+import org.sufficientlysecure.keychain.operations.results.SaveKeyringResult;
+import org.sufficientlysecure.keychain.pgp.CanonicalizedPublicKeyRing;
+import org.sufficientlysecure.keychain.pgp.Progressable;
+import org.sufficientlysecure.keychain.pgp.UncachedKeyRing;
+import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
+import org.sufficientlysecure.keychain.provider.ProviderHelper;
+import org.sufficientlysecure.keychain.provider.ProviderHelper.NotFoundException;
+import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
+import org.sufficientlysecure.keychain.util.ProgressScaler;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/** An operation which promotes a public key ring to a secret one.
+ *
+ * This operation can only be applied to public key rings where no secret key
+ * is available. Doing this "promotes" the public key ring to a secret one
+ * without secret key material, using a GNU_DUMMY s2k type.
+ *
+ */
+public class PromoteKeyOperation extends BaseOperation {
+
+ public PromoteKeyOperation(Context context, ProviderHelper providerHelper,
+ Progressable progressable, AtomicBoolean cancelled) {
+ super(context, providerHelper, progressable, cancelled);
+ }
+
+ public PromoteKeyResult execute(long masterKeyId) {
+
+ OperationLog log = new OperationLog();
+ log.add(LogType.MSG_PR, 0);
+
+ // Perform actual type change
+ UncachedKeyRing promotedRing;
+ {
+
+ try {
+
+ // This operation is only allowed for pure public keys
+ // TODO delete secret keys if they are stripped, or have been moved to the card?
+ if (mProviderHelper.getCachedPublicKeyRing(masterKeyId).hasAnySecret()) {
+ log.add(LogType.MSG_PR_ERROR_ALREADY_SECRET, 2);
+ return new PromoteKeyResult(PromoteKeyResult.RESULT_ERROR, log, null);
+ }
+
+ log.add(LogType.MSG_PR_FETCHING, 1,
+ KeyFormattingUtils.convertKeyIdToHex(masterKeyId));
+ CanonicalizedPublicKeyRing pubRing =
+ mProviderHelper.getCanonicalizedPublicKeyRing(masterKeyId);
+
+ // create divert-to-card secret key from public key
+ promotedRing = pubRing.createDummySecretRing();
+
+ } catch (PgpKeyNotFoundException e) {
+ log.add(LogType.MSG_PR_ERROR_KEY_NOT_FOUND, 2);
+ return new PromoteKeyResult(PromoteKeyResult.RESULT_ERROR, log, null);
+ } catch (NotFoundException e) {
+ log.add(LogType.MSG_PR_ERROR_KEY_NOT_FOUND, 2);
+ return new PromoteKeyResult(PromoteKeyResult.RESULT_ERROR, log, null);
+ }
+ }
+
+ // If the edit operation didn't succeed, exit here
+ if (promotedRing == null) {
+ // error is already logged by modification
+ return new PromoteKeyResult(PromoteKeyResult.RESULT_ERROR, log, null);
+ }
+
+ // Check if the action was cancelled
+ if (checkCancelled()) {
+ log.add(LogType.MSG_OPERATION_CANCELLED, 0);
+ return new PromoteKeyResult(PgpEditKeyResult.RESULT_CANCELLED, log, null);
+ }
+
+ // Cannot cancel from here on out!
+ setPreventCancel();
+
+ // Save the new keyring.
+ SaveKeyringResult saveResult = mProviderHelper
+ .saveSecretKeyRing(promotedRing, new ProgressScaler(mProgressable, 60, 95, 100));
+ log.add(saveResult, 1);
+
+ // If the save operation didn't succeed, exit here
+ if (!saveResult.success()) {
+ return new PromoteKeyResult(PromoteKeyResult.RESULT_ERROR, log, null);
+ }
+
+ updateProgress(R.string.progress_done, 100, 100);
+
+ log.add(LogType.MSG_PR_SUCCESS, 0);
+ return new PromoteKeyResult(PromoteKeyResult.RESULT_OK, log, promotedRing.getMasterKeyId());
+
+ }
+
+}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/DecryptVerifyResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/DecryptVerifyResult.java
index d81577102..86b37fea6 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/DecryptVerifyResult.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/DecryptVerifyResult.java
@@ -41,6 +41,9 @@ public class DecryptVerifyResult extends OperationResult {
OpenPgpSignatureResult mSignatureResult;
OpenPgpMetadata mDecryptMetadata;
+ // This holds the charset which was specified in the ascii armor, if specified
+ // https://tools.ietf.org/html/rfc4880#page56
+ String mCharset;
public long getKeyIdPassphraseNeeded() {
return mKeyIdPassphraseNeeded;
@@ -84,6 +87,14 @@ public class DecryptVerifyResult extends OperationResult {
mDecryptMetadata = decryptMetadata;
}
+ public String getCharset () {
+ return mCharset;
+ }
+
+ public void setCharset(String charset) {
+ mCharset = charset;
+ }
+
public boolean isPending() {
return (mResult & RESULT_PENDING) == RESULT_PENDING;
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/ImportKeyResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/ImportKeyResult.java
index ecde90ea6..2d533ed16 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/ImportKeyResult.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/ImportKeyResult.java
@@ -79,6 +79,10 @@ public class ImportKeyResult extends OperationResult {
mImportedMasterKeyIds = source.createLongArray();
}
+ public ImportKeyResult(int result, OperationLog log) {
+ this(result, log, 0, 0, 0, 0, new long[] { });
+ }
+
public ImportKeyResult(int result, OperationLog log,
int newKeys, int updatedKeys, int badKeys, int secret,
long[] importedMasterKeyIds) {
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 6552948fa..055028064 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
@@ -464,6 +464,7 @@ public abstract class OperationResult implements Parcelable {
// secret key modify
MSG_MF (LogLevel.START, R.string.msg_mr),
+ MSG_MF_ERROR_DIVERT_SERIAL (LogLevel.ERROR, R.string.msg_mf_error_divert_serial),
MSG_MF_ERROR_ENCODE (LogLevel.ERROR, R.string.msg_mf_error_encode),
MSG_MF_ERROR_FINGERPRINT (LogLevel.ERROR, R.string.msg_mf_error_fingerprint),
MSG_MF_ERROR_KEYID (LogLevel.ERROR, R.string.msg_mf_error_keyid),
@@ -476,6 +477,7 @@ public abstract class OperationResult implements Parcelable {
MSG_MF_ERROR_PASSPHRASE_MASTER(LogLevel.ERROR, R.string.msg_mf_error_passphrase_master),
MSG_MF_ERROR_PAST_EXPIRY(LogLevel.ERROR, R.string.msg_mf_error_past_expiry),
MSG_MF_ERROR_PGP (LogLevel.ERROR, R.string.msg_mf_error_pgp),
+ MSG_MF_ERROR_RESTRICTED(LogLevel.ERROR, R.string.msg_mf_error_restricted),
MSG_MF_ERROR_REVOKED_PRIMARY (LogLevel.ERROR, R.string.msg_mf_error_revoked_primary),
MSG_MF_ERROR_SIG (LogLevel.ERROR, R.string.msg_mf_error_sig),
MSG_MF_ERROR_SUBKEY_MISSING(LogLevel.ERROR, R.string.msg_mf_error_subkey_missing),
@@ -537,6 +539,13 @@ public abstract class OperationResult implements Parcelable {
MSG_ED_FETCHING (LogLevel.DEBUG, R.string.msg_ed_fetching),
MSG_ED_SUCCESS (LogLevel.OK, R.string.msg_ed_success),
+ // promote key
+ MSG_PR (LogLevel.START, R.string.msg_pr),
+ MSG_PR_ERROR_ALREADY_SECRET (LogLevel.ERROR, R.string.msg_pr_error_already_secret),
+ MSG_PR_ERROR_KEY_NOT_FOUND (LogLevel.ERROR, R.string.msg_pr_error_key_not_found),
+ MSG_PR_FETCHING (LogLevel.DEBUG, R.string.msg_pr_fetching),
+ MSG_PR_SUCCESS (LogLevel.OK, R.string.msg_pr_success),
+
// messages used in UI code
MSG_EK_ERROR_DIVERT (LogLevel.ERROR, R.string.msg_ek_error_divert),
MSG_EK_ERROR_DUMMY (LogLevel.ERROR, R.string.msg_ek_error_dummy),
@@ -546,6 +555,7 @@ public abstract class OperationResult implements Parcelable {
MSG_DC_ASKIP_NO_KEY (LogLevel.DEBUG, R.string.msg_dc_askip_no_key),
MSG_DC_ASKIP_NOT_ALLOWED (LogLevel.DEBUG, R.string.msg_dc_askip_not_allowed),
MSG_DC_ASYM (LogLevel.DEBUG, R.string.msg_dc_asym),
+ MSG_DC_CHARSET (LogLevel.DEBUG, R.string.msg_dc_charset),
MSG_DC_CLEAR_DATA (LogLevel.DEBUG, R.string.msg_dc_clear_data),
MSG_DC_CLEAR_DECOMPRESS (LogLevel.DEBUG, R.string.msg_dc_clear_decompress),
MSG_DC_CLEAR_META_FILE (LogLevel.DEBUG, R.string.msg_dc_clear_meta_file),
@@ -636,6 +646,7 @@ public abstract class OperationResult implements Parcelable {
MSG_IMPORT_FINGERPRINT_ERROR (LogLevel.ERROR, R.string.msg_import_fingerprint_error),
MSG_IMPORT_FINGERPRINT_OK (LogLevel.DEBUG, R.string.msg_import_fingerprint_ok),
MSG_IMPORT_ERROR (LogLevel.ERROR, R.string.msg_import_error),
+ MSG_IMPORT_ERROR_IO (LogLevel.ERROR, R.string.msg_import_error_io),
MSG_IMPORT_PARTIAL (LogLevel.ERROR, R.string.msg_import_partial),
MSG_IMPORT_SUCCESS (LogLevel.OK, R.string.msg_import_success),
@@ -717,7 +728,7 @@ public abstract class OperationResult implements Parcelable {
public static class OperationLog implements Iterable<LogEntryParcel> {
- private final List<LogEntryParcel> mParcels = new ArrayList<LogEntryParcel>();
+ private final List<LogEntryParcel> mParcels = new ArrayList<>();
/// Simple convenience method
public void add(LogType type, int indent, Object... parameters) {
@@ -742,7 +753,7 @@ public abstract class OperationResult implements Parcelable {
}
public boolean containsType(LogType type) {
- for(LogEntryParcel entry : new IterableIterator<LogEntryParcel>(mParcels.iterator())) {
+ for(LogEntryParcel entry : new IterableIterator<>(mParcels.iterator())) {
if (entry.mType == type) {
return true;
}
@@ -751,7 +762,7 @@ public abstract class OperationResult implements Parcelable {
}
public boolean containsWarnings() {
- for(LogEntryParcel entry : new IterableIterator<LogEntryParcel>(mParcels.iterator())) {
+ for(LogEntryParcel entry : new IterableIterator<>(mParcels.iterator())) {
if (entry.mType.mLevel == LogLevel.WARN || entry.mType.mLevel == LogLevel.ERROR) {
return true;
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/PromoteKeyResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/PromoteKeyResult.java
new file mode 100644
index 000000000..af9aff84a
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/PromoteKeyResult.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
+ * Copyright (C) 2014 Vincent Breitmoser <v.breitmoser@mugenguild.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.sufficientlysecure.keychain.operations.results;
+
+import android.os.Parcel;
+
+public class PromoteKeyResult extends OperationResult {
+
+ public final Long mMasterKeyId;
+
+ public PromoteKeyResult(int result, OperationLog log, Long masterKeyId) {
+ super(result, log);
+ mMasterKeyId = masterKeyId;
+ }
+
+ public PromoteKeyResult(Parcel source) {
+ super(source);
+ mMasterKeyId = source.readLong();
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ super.writeToParcel(dest, flags);
+ dest.writeLong(mMasterKeyId);
+ }
+
+ public static Creator<PromoteKeyResult> CREATOR = new Creator<PromoteKeyResult>() {
+ public PromoteKeyResult createFromParcel(final Parcel source) {
+ return new PromoteKeyResult(source);
+ }
+
+ public PromoteKeyResult[] newArray(final int size) {
+ return new PromoteKeyResult[size];
+ }
+ };
+
+}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/SignEncryptResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/SignEncryptResult.java
index 57daf3430..c336f8502 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/SignEncryptResult.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/SignEncryptResult.java
@@ -37,6 +37,7 @@ public class SignEncryptResult extends OperationResult {
int mNfcAlgo;
Date mNfcTimestamp;
String mNfcPassphrase;
+ byte[] mDetachedSignature;
public long getKeyIdPassphraseNeeded() {
return mKeyIdPassphraseNeeded;
@@ -54,6 +55,10 @@ public class SignEncryptResult extends OperationResult {
mNfcPassphrase = passphrase;
}
+ public void setDetachedSignature(byte[] detachedSignature) {
+ mDetachedSignature = detachedSignature;
+ }
+
public long getNfcKeyId() {
return mNfcKeyId;
}
@@ -74,6 +79,10 @@ public class SignEncryptResult extends OperationResult {
return mNfcPassphrase;
}
+ public byte[] getDetachedSignature() {
+ return mDetachedSignature;
+ }
+
public boolean isPending() {
return (mResult & RESULT_PENDING) == RESULT_PENDING;
}
@@ -87,6 +96,7 @@ public class SignEncryptResult extends OperationResult {
mNfcHash = source.readInt() != 0 ? source.createByteArray() : null;
mNfcAlgo = source.readInt();
mNfcTimestamp = source.readInt() != 0 ? new Date(source.readLong()) : null;
+ mDetachedSignature = source.readInt() != 0 ? source.createByteArray() : null;
}
public int describeContents() {
@@ -108,6 +118,12 @@ public class SignEncryptResult extends OperationResult {
} else {
dest.writeInt(0);
}
+ if (mDetachedSignature != null) {
+ dest.writeInt(1);
+ dest.writeByteArray(mDetachedSignature);
+ } else {
+ dest.writeInt(0);
+ }
}
public static final Creator<SignEncryptResult> CREATOR = new Creator<SignEncryptResult>() {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedKeyRing.java
index db0a9b137..bbf136dac 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedKeyRing.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedKeyRing.java
@@ -19,7 +19,6 @@
package org.sufficientlysecure.keychain.pgp;
import org.spongycastle.openpgp.PGPKeyRing;
-import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
import org.sufficientlysecure.keychain.util.IterableIterator;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedPublicKey.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedPublicKey.java
index 3539a4ceb..b026d9257 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedPublicKey.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedPublicKey.java
@@ -53,7 +53,7 @@ public class CanonicalizedPublicKey extends UncachedPublicKey {
public boolean canSign() {
// if key flags subpacket is available, honor it!
- if (getKeyUsage() != null) {
+ if (getKeyUsage() != 0) {
return (getKeyUsage() & KeyFlags.SIGN_DATA) != 0;
}
@@ -66,7 +66,7 @@ public class CanonicalizedPublicKey extends UncachedPublicKey {
public boolean canCertify() {
// if key flags subpacket is available, honor it!
- if (getKeyUsage() != null) {
+ if (getKeyUsage() != 0) {
return (getKeyUsage() & KeyFlags.CERTIFY_OTHER) != 0;
}
@@ -79,7 +79,7 @@ public class CanonicalizedPublicKey extends UncachedPublicKey {
public boolean canEncrypt() {
// if key flags subpacket is available, honor it!
- if (getKeyUsage() != null) {
+ if (getKeyUsage() != 0) {
return (getKeyUsage() & (KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE)) != 0;
}
@@ -93,7 +93,7 @@ public class CanonicalizedPublicKey extends UncachedPublicKey {
public boolean canAuthenticate() {
// if key flags subpacket is available, honor it!
- if (getKeyUsage() != null) {
+ if (getKeyUsage() != 0) {
return (getKeyUsage() & KeyFlags.AUTHENTICATION) != 0;
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedPublicKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedPublicKeyRing.java
index 85ef3eaa4..c2506685d 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedPublicKeyRing.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedPublicKeyRing.java
@@ -18,9 +18,11 @@
package org.sufficientlysecure.keychain.pgp;
+import org.spongycastle.bcpg.S2K;
import org.spongycastle.openpgp.PGPObjectFactory;
import org.spongycastle.openpgp.PGPPublicKey;
import org.spongycastle.openpgp.PGPPublicKeyRing;
+import org.spongycastle.openpgp.PGPSecretKeyRing;
import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
import org.sufficientlysecure.keychain.util.IterableIterator;
@@ -76,7 +78,7 @@ public class CanonicalizedPublicKeyRing extends CanonicalizedKeyRing {
public IterableIterator<CanonicalizedPublicKey> publicKeyIterator() {
@SuppressWarnings("unchecked")
final Iterator<PGPPublicKey> it = getRing().getPublicKeys();
- return new IterableIterator<CanonicalizedPublicKey>(new Iterator<CanonicalizedPublicKey>() {
+ return new IterableIterator<>(new Iterator<CanonicalizedPublicKey>() {
@Override
public boolean hasNext() {
return it.hasNext();
@@ -94,4 +96,13 @@ public class CanonicalizedPublicKeyRing extends CanonicalizedKeyRing {
});
}
+ /** Create a dummy secret ring from this key */
+ public UncachedKeyRing createDummySecretRing () {
+
+ PGPSecretKeyRing secRing = PGPSecretKeyRing.constructDummyFromPublic(getRing(),
+ S2K.GNU_PROTECTION_MODE_NO_PRIVATE_KEY);
+ return new UncachedKeyRing(secRing);
+
+ }
+
} \ No newline at end of file
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKey.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKey.java
index 6ccadac2e..40f2f48ad 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKey.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKey.java
@@ -182,7 +182,7 @@ public class CanonicalizedSecretKey extends CanonicalizedPublicKey {
* @return
*/
public LinkedList<Integer> getSupportedHashAlgorithms() {
- LinkedList<Integer> supported = new LinkedList<Integer>();
+ LinkedList<Integer> supported = new LinkedList<>();
if (mPrivateKeyState == PRIVATE_KEY_STATE_DIVERT_TO_CARD) {
// No support for MD5
@@ -247,7 +247,7 @@ public class CanonicalizedSecretKey extends CanonicalizedPublicKey {
int signatureType;
if (cleartext) {
- // for sign-only ascii text
+ // for sign-only ascii text (cleartext signature)
signatureType = PGPSignature.CANONICAL_TEXT_DOCUMENT;
} else {
signatureType = PGPSignature.BINARY_DOCUMENT;
@@ -262,11 +262,9 @@ public class CanonicalizedSecretKey extends CanonicalizedPublicKey {
spGen.setSignatureCreationTime(false, nfcCreationTimestamp);
signatureGenerator.setHashedSubpackets(spGen.generate());
return signatureGenerator;
- } catch (PgpKeyNotFoundException e) {
+ } catch (PgpKeyNotFoundException | PGPException e) {
// TODO: simply throw PGPException!
throw new PgpGeneralException("Error initializing signature!", e);
- } catch (PGPException e) {
- throw new PgpGeneralException("Error initializing signature!", e);
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKeyRing.java
index eb589c3f9..b5f6a5b09 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKeyRing.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKeyRing.java
@@ -18,27 +18,19 @@
package org.sufficientlysecure.keychain.pgp;
-import org.spongycastle.bcpg.S2K;
-import org.spongycastle.openpgp.PGPException;
import org.spongycastle.openpgp.PGPKeyRing;
import org.spongycastle.openpgp.PGPObjectFactory;
-import org.spongycastle.openpgp.PGPPrivateKey;
import org.spongycastle.openpgp.PGPPublicKey;
import org.spongycastle.openpgp.PGPSecretKey;
import org.spongycastle.openpgp.PGPSecretKeyRing;
import org.spongycastle.openpgp.PGPSignature;
-import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor;
-import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
-import org.sufficientlysecure.keychain.provider.KeychainContract;
-import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.util.IterableIterator;
import org.sufficientlysecure.keychain.util.Log;
import java.io.IOException;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.Iterator;
public class CanonicalizedSecretKeyRing extends CanonicalizedKeyRing {
@@ -94,7 +86,7 @@ public class CanonicalizedSecretKeyRing extends CanonicalizedKeyRing {
public IterableIterator<CanonicalizedSecretKey> secretKeyIterator() {
final Iterator<PGPSecretKey> it = mRing.getSecretKeys();
- return new IterableIterator<CanonicalizedSecretKey>(new Iterator<CanonicalizedSecretKey>() {
+ return new IterableIterator<>(new Iterator<CanonicalizedSecretKey>() {
@Override
public boolean hasNext() {
return it.hasNext();
@@ -114,7 +106,7 @@ public class CanonicalizedSecretKeyRing extends CanonicalizedKeyRing {
public IterableIterator<CanonicalizedPublicKey> publicKeyIterator() {
final Iterator<PGPPublicKey> it = getRing().getPublicKeys();
- return new IterableIterator<CanonicalizedPublicKey>(new Iterator<CanonicalizedPublicKey>() {
+ return new IterableIterator<>(new Iterator<CanonicalizedPublicKey>() {
@Override
public boolean hasNext() {
return it.hasNext();
@@ -133,7 +125,7 @@ public class CanonicalizedSecretKeyRing extends CanonicalizedKeyRing {
}
public HashMap<String,String> getLocalNotationData() {
- HashMap<String,String> result = new HashMap<String,String>();
+ HashMap<String,String> result = new HashMap<>();
Iterator<PGPSignature> it = getRing().getPublicKey().getKeySignatures();
while (it.hasNext()) {
WrappedSignature sig = new WrappedSignature(it.next());
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/OpenPgpSignatureResultBuilder.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/OpenPgpSignatureResultBuilder.java
index aa324c7ed..ed4715681 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/OpenPgpSignatureResultBuilder.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/OpenPgpSignatureResultBuilder.java
@@ -19,7 +19,6 @@ package org.sufficientlysecure.keychain.pgp;
import org.openintents.openpgp.OpenPgpSignatureResult;
import org.sufficientlysecure.keychain.Constants;
-import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
import org.sufficientlysecure.keychain.util.Log;
@@ -33,7 +32,7 @@ public class OpenPgpSignatureResultBuilder {
// OpenPgpSignatureResult
private boolean mSignatureOnly = false;
private String mPrimaryUserId;
- private ArrayList<String> mUserIds = new ArrayList<String>();
+ private ArrayList<String> mUserIds = new ArrayList<>();
private long mKeyId;
// builder
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java
index b58df085f..a69c5fe36 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java
@@ -28,7 +28,6 @@ import org.spongycastle.openpgp.PGPEncryptedData;
import org.spongycastle.openpgp.PGPEncryptedDataList;
import org.spongycastle.openpgp.PGPException;
import org.spongycastle.openpgp.PGPLiteralData;
-import org.spongycastle.openpgp.PGPObjectFactory;
import org.spongycastle.openpgp.PGPOnePassSignature;
import org.spongycastle.openpgp.PGPOnePassSignatureList;
import org.spongycastle.openpgp.PGPPBEEncryptedData;
@@ -36,6 +35,7 @@ import org.spongycastle.openpgp.PGPPublicKeyEncryptedData;
import org.spongycastle.openpgp.PGPSignature;
import org.spongycastle.openpgp.PGPSignatureList;
import org.spongycastle.openpgp.PGPUtil;
+import org.spongycastle.openpgp.jcajce.JcaPGPObjectFactory;
import org.spongycastle.openpgp.operator.PBEDataDecryptorFactory;
import org.spongycastle.openpgp.operator.PGPDigestCalculatorProvider;
import org.spongycastle.openpgp.operator.PublicKeyDataDecryptorFactory;
@@ -83,6 +83,7 @@ public class PgpDecryptVerify extends BaseOperation {
private Set<Long> mAllowedKeyIds;
private boolean mDecryptMetadataOnly;
private byte[] mDecryptedSessionKey;
+ private byte[] mDetachedSignature;
protected PgpDecryptVerify(Builder builder) {
super(builder.mContext, builder.mProviderHelper, builder.mProgressable);
@@ -96,6 +97,7 @@ public class PgpDecryptVerify extends BaseOperation {
this.mAllowedKeyIds = builder.mAllowedKeyIds;
this.mDecryptMetadataOnly = builder.mDecryptMetadataOnly;
this.mDecryptedSessionKey = builder.mDecryptedSessionKey;
+ this.mDetachedSignature = builder.mDetachedSignature;
}
public static class Builder {
@@ -103,15 +105,16 @@ public class PgpDecryptVerify extends BaseOperation {
private Context mContext;
private ProviderHelper mProviderHelper;
private InputData mData;
- private OutputStream mOutStream;
// optional
+ private OutputStream mOutStream = null;
private Progressable mProgressable = null;
private boolean mAllowSymmetricDecryption = true;
private String mPassphrase = null;
private Set<Long> mAllowedKeyIds = null;
private boolean mDecryptMetadataOnly = false;
private byte[] mDecryptedSessionKey = null;
+ private byte[] mDetachedSignature = null;
public Builder(Context context, ProviderHelper providerHelper,
Progressable progressable,
@@ -156,6 +159,17 @@ public class PgpDecryptVerify extends BaseOperation {
return this;
}
+ /**
+ * If detachedSignature != null, it will be used exclusively to verify the signature
+ *
+ * @param detachedSignature
+ * @return
+ */
+ public Builder setDetachedSignature(byte[] detachedSignature) {
+ mDetachedSignature = detachedSignature;
+ return this;
+ }
+
public PgpDecryptVerify build() {
return new PgpDecryptVerify(this);
}
@@ -166,22 +180,30 @@ public class PgpDecryptVerify extends BaseOperation {
*/
public DecryptVerifyResult execute() {
try {
- // automatically works with ascii armor input and binary
- InputStream in = PGPUtil.getDecoderStream(mData.getInputStream());
+ if (mDetachedSignature != null) {
+ Log.d(Constants.TAG, "Detached signature present, verifying with this signature only");
- if (in instanceof ArmoredInputStream) {
- ArmoredInputStream aIn = (ArmoredInputStream) in;
- // it is ascii armored
- Log.d(Constants.TAG, "ASCII Armor Header Line: " + aIn.getArmorHeaderLine());
-
- if (aIn.isClearText()) {
- // a cleartext signature, verify it with the other method
- return verifyCleartextSignature(aIn, 0);
+ return verifyDetachedSignature(mData.getInputStream(), 0);
+ } else {
+ // automatically works with PGP ascii armor and PGP binary
+ InputStream in = PGPUtil.getDecoderStream(mData.getInputStream());
+
+ if (in instanceof ArmoredInputStream) {
+ ArmoredInputStream aIn = (ArmoredInputStream) in;
+ // it is ascii armored
+ Log.d(Constants.TAG, "ASCII Armor Header Line: " + aIn.getArmorHeaderLine());
+
+ if (aIn.isClearText()) {
+ // a cleartext signature, verify it with the other method
+ return verifyCleartextSignature(aIn, 0);
+ } else {
+ // else: ascii armored encryption! go on...
+ return decryptVerify(in, 0);
+ }
+ } else {
+ return decryptVerify(in, 0);
}
- // else: ascii armored encryption! go on...
}
-
- return decryptVerify(in, 0);
} catch (PGPException e) {
Log.d(Constants.TAG, "PGPException", e);
OperationLog log = new OperationLog();
@@ -205,7 +227,7 @@ public class PgpDecryptVerify extends BaseOperation {
log.add(LogType.MSG_DC, indent);
indent += 1;
- PGPObjectFactory pgpF = new PGPObjectFactory(in, new JcaKeyFingerprintCalculator());
+ JcaPGPObjectFactory pgpF = new JcaPGPObjectFactory(in);
PGPEncryptedDataList enc;
Object o = pgpF.nextObject();
@@ -234,6 +256,25 @@ public class PgpDecryptVerify extends BaseOperation {
boolean symmetricPacketFound = false;
boolean anyPacketFound = false;
+ // If the input stream is armored, and there is a charset specified, take a note for later
+ // https://tools.ietf.org/html/rfc4880#page56
+ String charset = null;
+ if (in instanceof ArmoredInputStream) {
+ ArmoredInputStream aIn = (ArmoredInputStream) in;
+ if (aIn.getArmorHeaders() != null) {
+ for (String header : aIn.getArmorHeaders()) {
+ String[] pieces = header.split(":", 2);
+ if (pieces.length == 2 && "charset".equalsIgnoreCase(pieces[0])) {
+ charset = pieces[1].trim();
+ break;
+ }
+ }
+ if (charset != null) {
+ log.add(LogType.MSG_DC_CHARSET, indent, charset);
+ }
+ }
+ }
+
// go through all objects and find one we can decrypt
while (it.hasNext()) {
Object obj = it.next();
@@ -257,19 +298,19 @@ public class PgpDecryptVerify extends BaseOperation {
);
} catch (ProviderHelper.NotFoundException e) {
// continue with the next packet in the while loop
- log.add(LogType.MSG_DC_ASKIP_NO_KEY, indent +1);
+ log.add(LogType.MSG_DC_ASKIP_NO_KEY, indent + 1);
continue;
}
if (secretKeyRing == null) {
// continue with the next packet in the while loop
- log.add(LogType.MSG_DC_ASKIP_NO_KEY, indent +1);
+ log.add(LogType.MSG_DC_ASKIP_NO_KEY, indent + 1);
continue;
}
// get subkey which has been used for this encryption packet
secretEncryptionKey = secretKeyRing.getSecretKey(subKeyId);
if (secretEncryptionKey == null) {
// should actually never happen, so no need to be more specific.
- log.add(LogType.MSG_DC_ASKIP_NO_KEY, indent +1);
+ log.add(LogType.MSG_DC_ASKIP_NO_KEY, indent + 1);
continue;
}
@@ -283,7 +324,7 @@ public class PgpDecryptVerify extends BaseOperation {
if (!mAllowedKeyIds.contains(masterKeyId)) {
// this key is in our db, but NOT allowed!
// continue with the next packet in the while loop
- log.add(LogType.MSG_DC_ASKIP_NOT_ALLOWED, indent +1);
+ log.add(LogType.MSG_DC_ASKIP_NOT_ALLOWED, indent + 1);
continue;
}
}
@@ -298,15 +339,15 @@ public class PgpDecryptVerify extends BaseOperation {
try {
// returns "" if key has no passphrase
mPassphrase = getCachedPassphrase(subKeyId);
- log.add(LogType.MSG_DC_PASS_CACHED, indent +1);
+ log.add(LogType.MSG_DC_PASS_CACHED, indent + 1);
} catch (PassphraseCacheInterface.NoSecretKeyException e) {
- log.add(LogType.MSG_DC_ERROR_NO_KEY, indent +1);
+ log.add(LogType.MSG_DC_ERROR_NO_KEY, indent + 1);
return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log);
}
// if passphrase was not cached, return here indicating that a passphrase is missing!
if (mPassphrase == null) {
- log.add(LogType.MSG_DC_PENDING_PASSPHRASE, indent +1);
+ log.add(LogType.MSG_DC_PENDING_PASSPHRASE, indent + 1);
DecryptVerifyResult result =
new DecryptVerifyResult(DecryptVerifyResult.RESULT_PENDING_ASYM_PASSPHRASE, log);
result.setKeyIdPassphraseNeeded(subKeyId);
@@ -322,8 +363,8 @@ public class PgpDecryptVerify extends BaseOperation {
log.add(LogType.MSG_DC_SYM, indent);
- if (! mAllowSymmetricDecryption) {
- log.add(LogType.MSG_DC_SYM_SKIP, indent +1);
+ if (!mAllowSymmetricDecryption) {
+ log.add(LogType.MSG_DC_SYM_SKIP, indent + 1);
continue;
}
@@ -338,7 +379,7 @@ public class PgpDecryptVerify extends BaseOperation {
// if no passphrase is given, return here
// indicating that a passphrase is missing!
if (mPassphrase == null) {
- log.add(LogType.MSG_DC_PENDING_PASSPHRASE, indent +1);
+ log.add(LogType.MSG_DC_PENDING_PASSPHRASE, indent + 1);
return new DecryptVerifyResult(DecryptVerifyResult.RESULT_PENDING_SYM_PASSPHRASE, log);
}
@@ -383,13 +424,13 @@ public class PgpDecryptVerify extends BaseOperation {
updateProgress(R.string.progress_extracting_key, currentProgress, 100);
try {
- log.add(LogType.MSG_DC_UNLOCKING, indent +1);
+ log.add(LogType.MSG_DC_UNLOCKING, indent + 1);
if (!secretEncryptionKey.unlock(mPassphrase)) {
- log.add(LogType.MSG_DC_ERROR_BAD_PASSPHRASE, indent +1);
+ log.add(LogType.MSG_DC_ERROR_BAD_PASSPHRASE, indent + 1);
return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log);
}
} catch (PgpGeneralException e) {
- log.add(LogType.MSG_DC_ERROR_EXTRACT_KEY, indent +1);
+ log.add(LogType.MSG_DC_ERROR_EXTRACT_KEY, indent + 1);
return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log);
}
@@ -401,7 +442,7 @@ public class PgpDecryptVerify extends BaseOperation {
= secretEncryptionKey.getDecryptorFactory(mDecryptedSessionKey);
clear = encryptedDataAsymmetric.getDataStream(decryptorFactory);
} catch (NfcSyncPublicKeyDataDecryptorFactoryBuilder.NfcInteractionNeeded e) {
- log.add(LogType.MSG_DC_PENDING_NFC, indent +1);
+ log.add(LogType.MSG_DC_PENDING_NFC, indent + 1);
DecryptVerifyResult result =
new DecryptVerifyResult(DecryptVerifyResult.RESULT_PENDING_NFC, log);
result.setNfcState(secretEncryptionKey.getKeyId(), e.encryptedSessionKey, mPassphrase);
@@ -412,11 +453,11 @@ public class PgpDecryptVerify extends BaseOperation {
// If we didn't find any useful data, error out
// no packet has been found where we have the corresponding secret key in our db
log.add(
- anyPacketFound ? LogType.MSG_DC_ERROR_NO_KEY : LogType.MSG_DC_ERROR_NO_DATA, indent +1);
+ anyPacketFound ? LogType.MSG_DC_ERROR_NO_KEY : LogType.MSG_DC_ERROR_NO_DATA, indent + 1);
return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log);
}
- PGPObjectFactory plainFact = new PGPObjectFactory(clear, new JcaKeyFingerprintCalculator());
+ JcaPGPObjectFactory plainFact = new JcaPGPObjectFactory(clear);
Object dataChunk = plainFact.nextObject();
OpenPgpSignatureResultBuilder signatureResultBuilder = new OpenPgpSignatureResultBuilder();
int signatureIndex = -1;
@@ -427,25 +468,27 @@ public class PgpDecryptVerify extends BaseOperation {
indent += 1;
if (dataChunk instanceof PGPCompressedData) {
- log.add(LogType.MSG_DC_CLEAR_DECOMPRESS, indent +1);
+ log.add(LogType.MSG_DC_CLEAR_DECOMPRESS, indent + 1);
currentProgress += 2;
updateProgress(R.string.progress_decompressing_data, currentProgress, 100);
PGPCompressedData compressedData = (PGPCompressedData) dataChunk;
- PGPObjectFactory fact = new PGPObjectFactory(compressedData.getDataStream(), new JcaKeyFingerprintCalculator());
+ JcaPGPObjectFactory fact = new JcaPGPObjectFactory(compressedData.getDataStream());
dataChunk = fact.nextObject();
plainFact = fact;
}
PGPOnePassSignature signature = null;
if (dataChunk instanceof PGPOnePassSignatureList) {
- log.add(LogType.MSG_DC_CLEAR_SIGNATURE, indent +1);
+ log.add(LogType.MSG_DC_CLEAR_SIGNATURE, indent + 1);
currentProgress += 2;
updateProgress(R.string.progress_processing_signature, currentProgress, 100);
PGPOnePassSignatureList sigList = (PGPOnePassSignatureList) dataChunk;
+ // NOTE: following code is similar to processSignature, but for PGPOnePassSignature
+
// go through all signatures
// and find out for which signature we have a key in our database
for (int i = 0; i < sigList.size(); ++i) {
@@ -491,7 +534,7 @@ public class PgpDecryptVerify extends BaseOperation {
OpenPgpMetadata metadata;
if (dataChunk instanceof PGPLiteralData) {
- log.add(LogType.MSG_DC_CLEAR_DATA, indent +1);
+ log.add(LogType.MSG_DC_CLEAR_DATA, indent + 1);
indent += 2;
currentProgress += 4;
updateProgress(R.string.progress_decrypting, currentProgress, 100);
@@ -533,12 +576,12 @@ public class PgpDecryptVerify extends BaseOperation {
literalData.getModificationTime().getTime(),
originalSize);
- if ( ! originalFilename.equals("")) {
+ if (!originalFilename.equals("")) {
log.add(LogType.MSG_DC_CLEAR_META_FILE, indent + 1, originalFilename);
}
- log.add(LogType.MSG_DC_CLEAR_META_MIME, indent +1,
+ log.add(LogType.MSG_DC_CLEAR_META_MIME, indent + 1,
mimeType);
- log.add(LogType.MSG_DC_CLEAR_META_TIME, indent +1,
+ log.add(LogType.MSG_DC_CLEAR_META_TIME, indent + 1,
new Date(literalData.getModificationTime().getTime()).toString());
if (originalSize != 0) {
log.add(LogType.MSG_DC_CLEAR_META_SIZE, indent + 1,
@@ -550,6 +593,7 @@ public class PgpDecryptVerify extends BaseOperation {
log.add(LogType.MSG_DC_OK_META_ONLY, indent);
DecryptVerifyResult result =
new DecryptVerifyResult(DecryptVerifyResult.RESULT_OK, log);
+ result.setCharset(charset);
result.setDecryptMetadata(metadata);
return result;
}
@@ -572,7 +616,9 @@ public class PgpDecryptVerify extends BaseOperation {
int length;
byte[] buffer = new byte[1 << 16];
while ((length = dataIn.read(buffer)) > 0) {
- mOutStream.write(buffer, 0, length);
+ if (mOutStream != null) {
+ mOutStream.write(buffer, 0, length);
+ }
// update signature buffer if signature is also present
if (signature != null) {
@@ -606,9 +652,9 @@ public class PgpDecryptVerify extends BaseOperation {
// Verify signature and check binding signatures
boolean validSignature = signature.verify(messageSignature);
if (validSignature) {
- log.add(LogType.MSG_DC_CLEAR_SIGNATURE_OK, indent +1);
+ log.add(LogType.MSG_DC_CLEAR_SIGNATURE_OK, indent + 1);
} else {
- log.add(LogType.MSG_DC_CLEAR_SIGNATURE_BAD, indent +1);
+ log.add(LogType.MSG_DC_CLEAR_SIGNATURE_BAD, indent + 1);
}
signatureResultBuilder.setValidSignature(validSignature);
}
@@ -647,6 +693,7 @@ public class PgpDecryptVerify extends BaseOperation {
new DecryptVerifyResult(DecryptVerifyResult.RESULT_OK, log);
result.setDecryptMetadata(metadata);
result.setSignatureResult(signatureResultBuilder.build());
+ result.setCharset(charset);
return result;
}
@@ -669,7 +716,7 @@ public class PgpDecryptVerify extends BaseOperation {
ByteArrayOutputStream out = new ByteArrayOutputStream();
- updateProgress(R.string.progress_done, 0, 100);
+ updateProgress(R.string.progress_reading_data, 0, 100);
ByteArrayOutputStream lineOut = new ByteArrayOutputStream();
int lookAhead = readInputLine(lineOut, aIn);
@@ -689,10 +736,12 @@ public class PgpDecryptVerify extends BaseOperation {
out.close();
byte[] clearText = out.toByteArray();
- mOutStream.write(clearText);
+ if (mOutStream != null) {
+ mOutStream.write(clearText);
+ }
updateProgress(R.string.progress_processing_signature, 60, 100);
- PGPObjectFactory pgpFact = new PGPObjectFactory(aIn, new JcaKeyFingerprintCalculator());
+ JcaPGPObjectFactory pgpFact = new JcaPGPObjectFactory(aIn);
PGPSignatureList sigList = (PGPSignatureList) pgpFact.nextObject();
if (sigList == null) {
@@ -700,45 +749,7 @@ public class PgpDecryptVerify extends BaseOperation {
return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log);
}
- CanonicalizedPublicKeyRing signingRing = null;
- CanonicalizedPublicKey signingKey = null;
- int signatureIndex = -1;
-
- // go through all signatures
- // and find out for which signature we have a key in our database
- for (int i = 0; i < sigList.size(); ++i) {
- try {
- long sigKeyId = sigList.get(i).getKeyID();
- signingRing = mProviderHelper.getCanonicalizedPublicKeyRing(
- KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(sigKeyId)
- );
- signingKey = signingRing.getPublicKey(sigKeyId);
- signatureIndex = i;
- } catch (ProviderHelper.NotFoundException e) {
- Log.d(Constants.TAG, "key not found, trying next signature...");
- }
- }
-
- PGPSignature signature = null;
-
- if (signingKey != null) {
- // key found in our database!
- signature = sigList.get(signatureIndex);
-
- signatureResultBuilder.initValid(signingRing, signingKey);
-
- JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider =
- new JcaPGPContentVerifierBuilderProvider()
- .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
- signature.init(contentVerifierBuilderProvider, signingKey.getPublicKey());
- } else {
- // no key in our database -> return "unknown pub key" status including the first key id
- if (!sigList.isEmpty()) {
- signatureResultBuilder.setSignatureAvailable(true);
- signatureResultBuilder.setKnownKey(false);
- signatureResultBuilder.setKeyId(sigList.get(0).getKeyID());
- }
- }
+ PGPSignature signature = processPGPSignatureList(sigList, signatureResultBuilder);
if (signature != null) {
try {
@@ -786,6 +797,134 @@ public class PgpDecryptVerify extends BaseOperation {
return result;
}
+ private DecryptVerifyResult verifyDetachedSignature(InputStream in, int indent)
+ throws IOException, PGPException {
+
+ OperationLog log = new OperationLog();
+
+ OpenPgpSignatureResultBuilder signatureResultBuilder = new OpenPgpSignatureResultBuilder();
+ // detached signatures are never encrypted
+ signatureResultBuilder.setSignatureOnly(true);
+
+ updateProgress(R.string.progress_processing_signature, 0, 100);
+ InputStream detachedSigIn = new ByteArrayInputStream(mDetachedSignature);
+ detachedSigIn = PGPUtil.getDecoderStream(detachedSigIn);
+
+ JcaPGPObjectFactory pgpFact = new JcaPGPObjectFactory(detachedSigIn);
+
+ PGPSignatureList sigList;
+ Object o = pgpFact.nextObject();
+ if (o instanceof PGPCompressedData) {
+ PGPCompressedData c1 = (PGPCompressedData) o;
+ pgpFact = new JcaPGPObjectFactory(c1.getDataStream());
+ sigList = (PGPSignatureList) pgpFact.nextObject();
+ } else if (o instanceof PGPSignatureList) {
+ sigList = (PGPSignatureList) o;
+ } else {
+ log.add(LogType.MSG_DC_ERROR_INVALID_SIGLIST, 0);
+ return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log);
+ }
+
+ PGPSignature signature = processPGPSignatureList(sigList, signatureResultBuilder);
+
+ if (signature != null) {
+ updateProgress(R.string.progress_reading_data, 60, 100);
+
+ ProgressScaler progressScaler = new ProgressScaler(mProgressable, 60, 90, 100);
+ long alreadyWritten = 0;
+ long wholeSize = mData.getSize() - mData.getStreamPosition();
+ int length;
+ byte[] buffer = new byte[1 << 16];
+ while ((length = in.read(buffer)) > 0) {
+ if (mOutStream != null) {
+ mOutStream.write(buffer, 0, length);
+ }
+
+ // update signature buffer if signature is also present
+ signature.update(buffer, 0, length);
+
+ alreadyWritten += length;
+ if (wholeSize > 0) {
+ long progress = 100 * alreadyWritten / wholeSize;
+ // stop at 100% for wrong file sizes...
+ if (progress > 100) {
+ progress = 100;
+ }
+ progressScaler.setProgress((int) progress, 100);
+ } else {
+ // TODO: slow annealing to fake a progress?
+ }
+ }
+
+ updateProgress(R.string.progress_verifying_signature, 90, 100);
+ log.add(LogType.MSG_DC_CLEAR_SIGNATURE_CHECK, indent);
+
+ // these are not cleartext signatures!
+ signatureResultBuilder.setSignatureOnly(false);
+
+ // Verify signature and check binding signatures
+ boolean validSignature = signature.verify();
+ if (validSignature) {
+ log.add(LogType.MSG_DC_CLEAR_SIGNATURE_OK, indent + 1);
+ } else {
+ log.add(LogType.MSG_DC_CLEAR_SIGNATURE_BAD, indent + 1);
+ }
+ signatureResultBuilder.setValidSignature(validSignature);
+ }
+
+ updateProgress(R.string.progress_done, 100, 100);
+
+ log.add(LogType.MSG_DC_OK, indent);
+
+ DecryptVerifyResult result = new DecryptVerifyResult(DecryptVerifyResult.RESULT_OK, log);
+ result.setSignatureResult(signatureResultBuilder.build());
+ return result;
+ }
+
+ private PGPSignature processPGPSignatureList(PGPSignatureList sigList, OpenPgpSignatureResultBuilder signatureResultBuilder) throws PGPException {
+ CanonicalizedPublicKeyRing signingRing = null;
+ CanonicalizedPublicKey signingKey = null;
+ int signatureIndex = -1;
+
+ // go through all signatures
+ // and find out for which signature we have a key in our database
+ for (int i = 0; i < sigList.size(); ++i) {
+ try {
+ long sigKeyId = sigList.get(i).getKeyID();
+ signingRing = mProviderHelper.getCanonicalizedPublicKeyRing(
+ KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(sigKeyId)
+ );
+ signingKey = signingRing.getPublicKey(sigKeyId);
+ signatureIndex = i;
+ } catch (ProviderHelper.NotFoundException e) {
+ Log.d(Constants.TAG, "key not found, trying next signature...");
+ }
+ }
+
+ PGPSignature signature = null;
+
+ if (signingKey != null) {
+ // key found in our database!
+ signature = sigList.get(signatureIndex);
+
+ signatureResultBuilder.initValid(signingRing, signingKey);
+
+ JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider =
+ new JcaPGPContentVerifierBuilderProvider()
+ .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
+ signature.init(contentVerifierBuilderProvider, signingKey.getPublicKey());
+ } else {
+ // no key in our database -> return "unknown pub key" status including the first key id
+ if (!sigList.isEmpty()) {
+ signatureResultBuilder.setSignatureAvailable(true);
+ signatureResultBuilder.setKnownKey(false);
+ signatureResultBuilder.setKeyId(sigList.get(0).getKeyID());
+ }
+ }
+
+ return signature;
+ }
+
/**
* Mostly taken from ClearSignedFileProcessor in Bouncy Castle
*/
@@ -807,7 +946,7 @@ public class PgpDecryptVerify extends BaseOperation {
while ((ch = fIn.read()) >= 0) {
bOut.write(ch);
if (ch == '\r' || ch == '\n') {
- lookAhead = readPassedEOL(bOut, ch, fIn);
+ lookAhead = readPastEOL(bOut, ch, fIn);
break;
}
}
@@ -824,7 +963,7 @@ public class PgpDecryptVerify extends BaseOperation {
do {
bOut.write(ch);
if (ch == '\r' || ch == '\n') {
- lookAhead = readPassedEOL(bOut, ch, fIn);
+ lookAhead = readPastEOL(bOut, ch, fIn);
break;
}
} while ((ch = fIn.read()) >= 0);
@@ -836,7 +975,7 @@ public class PgpDecryptVerify extends BaseOperation {
return lookAhead;
}
- private static int readPassedEOL(ByteArrayOutputStream bOut, int lastCh, InputStream fIn)
+ private static int readPastEOL(ByteArrayOutputStream bOut, int lastCh, InputStream fIn)
throws IOException {
int lookAhead = fIn.read();
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 4bab7f2b9..aebb52a03 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java
@@ -135,7 +135,7 @@ public class PgpKeyOperation {
public PgpKeyOperation(Progressable progress) {
super();
if (progress != null) {
- mProgress = new Stack<Progressable>();
+ mProgress = new Stack<>();
mProgress.push(progress);
}
}
@@ -288,13 +288,11 @@ public class PgpKeyOperation {
// build new key pair
return new JcaPGPKeyPair(algorithm, keyGen.generateKeyPair(), new Date());
- } catch(NoSuchProviderException e) {
+ } catch(NoSuchProviderException | InvalidAlgorithmParameterException e) {
throw new RuntimeException(e);
} catch(NoSuchAlgorithmException e) {
log.add(LogType.MSG_CR_ERROR_UNKNOWN_ALGO, indent);
return null;
- } catch(InvalidAlgorithmParameterException e) {
- throw new RuntimeException(e);
} catch(PGPException e) {
Log.e(Constants.TAG, "internal pgp error", e);
log.add(LogType.MSG_CR_ERROR_INTERNAL_PGP, indent);
@@ -389,6 +387,9 @@ public class PgpKeyOperation {
* with a passphrase fails, the operation will fail with an unlocking error. More specific
* handling of errors should be done in UI code!
*
+ * If the passphrase is null, only a restricted subset of operations will be available,
+ * namely stripping of subkeys and changing the protection mode of dummy keys.
+ *
*/
public PgpEditKeyResult modifySecretKeyRing(CanonicalizedSecretKeyRing wsKR, SaveKeyringParcel saveParcel,
String passphrase) {
@@ -429,6 +430,11 @@ public class PgpKeyOperation {
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
}
+ // If we have no passphrase, only allow restricted operation
+ if (passphrase == null) {
+ return internalRestricted(sKR, saveParcel, log);
+ }
+
// read masterKeyFlags, and use the same as before.
// since this is the master key, this contains at least CERTIFY_OTHER
PGPPublicKey masterPublicKey = masterSecretKey.getPublicKey();
@@ -496,7 +502,7 @@ public class PgpKeyOperation {
@SuppressWarnings("unchecked")
Iterator<PGPSignature> it = modifiedPublicKey.getSignaturesForID(userId);
if (it != null) {
- for (PGPSignature cert : new IterableIterator<PGPSignature>(it)) {
+ for (PGPSignature cert : new IterableIterator<>(it)) {
if (cert.getKeyID() != masterPublicKey.getKeyID()) {
// foreign certificate?! error error error
log.add(LogType.MSG_MF_ERROR_INTEGRITY, indent);
@@ -715,6 +721,27 @@ public class PgpKeyOperation {
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
}
+ if (change.mDummyStrip || change.mDummyDivert != null) {
+ // IT'S DANGEROUS~
+ // no really, it is. this operation irrevocably removes the private key data from the key
+ if (change.mDummyStrip) {
+ sKey = PGPSecretKey.constructGnuDummyKey(sKey.getPublicKey());
+ } else {
+ // the serial number must be 16 bytes in length
+ if (change.mDummyDivert.length != 16) {
+ log.add(LogType.MSG_MF_ERROR_DIVERT_SERIAL,
+ indent + 1, KeyFormattingUtils.convertKeyIdToHex(change.mKeyId));
+ return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
+ }
+ }
+ sKR = PGPSecretKeyRing.insertSecretKey(sKR, sKey);
+ }
+
+ // This doesn't concern us any further
+ if (!change.mRecertify && (change.mExpiry == null && change.mFlags == null)) {
+ continue;
+ }
+
// expiry must not be in the past
if (change.mExpiry != null && change.mExpiry != 0 &&
new Date(change.mExpiry*1000).before(new Date())) {
@@ -805,30 +832,6 @@ public class PgpKeyOperation {
}
subProgressPop();
- // 4c. For each subkey to be stripped... do so
- subProgressPush(65, 70);
- for (int i = 0; i < saveParcel.mStripSubKeys.size(); i++) {
-
- progress(R.string.progress_modify_subkeystrip, (i-1) * (100 / saveParcel.mStripSubKeys.size()));
- long strip = saveParcel.mStripSubKeys.get(i);
- log.add(LogType.MSG_MF_SUBKEY_STRIP,
- indent, KeyFormattingUtils.convertKeyIdToHex(strip));
-
- PGPSecretKey sKey = sKR.getSecretKey(strip);
- if (sKey == null) {
- log.add(LogType.MSG_MF_ERROR_SUBKEY_MISSING,
- indent+1, KeyFormattingUtils.convertKeyIdToHex(strip));
- return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
- }
-
- // IT'S DANGEROUS~
- // no really, it is. this operation irrevocably removes the private key data from the key
- sKey = PGPSecretKey.constructGnuDummyKey(sKey.getPublicKey());
- sKR = PGPSecretKeyRing.insertSecretKey(sKR, sKey);
-
- }
- subProgressPop();
-
// 5. Generate and add new subkeys
subProgressPush(70, 90);
for (int i = 0; i < saveParcel.mAddSubKeys.size(); i++) {
@@ -937,6 +940,73 @@ public class PgpKeyOperation {
}
+ /** This method does the actual modifications in a keyring just like internal, except it
+ * supports only the subset of operations which require no passphrase, and will error
+ * otherwise.
+ */
+ private PgpEditKeyResult internalRestricted(PGPSecretKeyRing sKR, SaveKeyringParcel saveParcel,
+ OperationLog log) {
+
+ int indent = 1;
+
+ progress(R.string.progress_modify, 0);
+
+ // Make sure the saveParcel includes only operations available without passphrae!
+ if (!saveParcel.isRestrictedOnly()) {
+ log.add(LogType.MSG_MF_ERROR_RESTRICTED, indent);
+ return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
+ }
+
+ // Check if we were cancelled
+ if (checkCancelled()) {
+ log.add(LogType.MSG_OPERATION_CANCELLED, indent);
+ return new PgpEditKeyResult(PgpEditKeyResult.RESULT_CANCELLED, log, null);
+ }
+
+ // The only operation we can do here:
+ // 4a. Strip secret keys, or change their protection mode (stripped/divert-to-card)
+ subProgressPush(50, 60);
+ for (int i = 0; i < saveParcel.mChangeSubKeys.size(); i++) {
+
+ progress(R.string.progress_modify_subkeychange, (i - 1) * (100 / saveParcel.mChangeSubKeys.size()));
+ SaveKeyringParcel.SubkeyChange change = saveParcel.mChangeSubKeys.get(i);
+ log.add(LogType.MSG_MF_SUBKEY_CHANGE,
+ indent, KeyFormattingUtils.convertKeyIdToHex(change.mKeyId));
+
+ PGPSecretKey sKey = sKR.getSecretKey(change.mKeyId);
+ if (sKey == null) {
+ log.add(LogType.MSG_MF_ERROR_SUBKEY_MISSING,
+ indent + 1, KeyFormattingUtils.convertKeyIdToHex(change.mKeyId));
+ return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
+ }
+
+ if (change.mDummyStrip || change.mDummyDivert != null) {
+ // IT'S DANGEROUS~
+ // no really, it is. this operation irrevocably removes the private key data from the key
+ if (change.mDummyStrip) {
+ sKey = PGPSecretKey.constructGnuDummyKey(sKey.getPublicKey());
+ } else {
+ // the serial number must be 16 bytes in length
+ if (change.mDummyDivert.length != 16) {
+ log.add(LogType.MSG_MF_ERROR_DIVERT_SERIAL,
+ indent + 1, KeyFormattingUtils.convertKeyIdToHex(change.mKeyId));
+ return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
+ }
+ sKey = PGPSecretKey.constructGnuDummyKey(sKey.getPublicKey(), change.mDummyDivert);
+ }
+ sKR = PGPSecretKeyRing.insertSecretKey(sKR, sKey);
+ }
+
+ }
+
+ // And we're done!
+ progress(R.string.progress_done, 100);
+ log.add(LogType.MSG_MF_SUCCESS, indent);
+ return new PgpEditKeyResult(OperationResult.RESULT_OK, log, new UncachedKeyRing(sKR));
+
+ }
+
+
private static PGPSecretKeyRing applyNewUnlock(
PGPSecretKeyRing sKR,
PGPPublicKey masterPublicKey,
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java
index 3c3bcc890..060db96b4 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java
@@ -50,6 +50,7 @@ import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.ProgressScaler;
import java.io.BufferedReader;
+import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
@@ -78,9 +79,11 @@ public class PgpSignEncrypt extends BaseOperation {
private int mSignatureHashAlgorithm;
private String mSignaturePassphrase;
private long mAdditionalEncryptId;
- private boolean mCleartextInput;
+ private boolean mCleartextSignature;
+ private boolean mDetachedSignature;
private String mOriginalFilename;
private boolean mFailOnMissingEncryptionKeyIds;
+ private String mCharset;
private byte[] mNfcSignedHash = null;
private Date mNfcCreationTimestamp = null;
@@ -113,11 +116,13 @@ public class PgpSignEncrypt extends BaseOperation {
this.mSignatureHashAlgorithm = builder.mSignatureHashAlgorithm;
this.mSignaturePassphrase = builder.mSignaturePassphrase;
this.mAdditionalEncryptId = builder.mAdditionalEncryptId;
- this.mCleartextInput = builder.mCleartextInput;
+ this.mCleartextSignature = builder.mCleartextSignature;
+ this.mDetachedSignature = builder.mDetachedSignature;
this.mNfcSignedHash = builder.mNfcSignedHash;
this.mNfcCreationTimestamp = builder.mNfcCreationTimestamp;
this.mOriginalFilename = builder.mOriginalFilename;
this.mFailOnMissingEncryptionKeyIds = builder.mFailOnMissingEncryptionKeyIds;
+ this.mCharset = builder.mCharset;
}
public static class Builder {
@@ -140,11 +145,13 @@ public class PgpSignEncrypt extends BaseOperation {
private int mSignatureHashAlgorithm = 0;
private String mSignaturePassphrase = null;
private long mAdditionalEncryptId = Constants.key.none;
- private boolean mCleartextInput = false;
+ private boolean mCleartextSignature = false;
+ private boolean mDetachedSignature = false;
private String mOriginalFilename = "";
private byte[] mNfcSignedHash = null;
private Date mNfcCreationTimestamp = null;
private boolean mFailOnMissingEncryptionKeyIds = false;
+ private String mCharset = null;
public Builder(Context context, ProviderHelper providerHelper, Progressable progressable,
InputData data, OutputStream outStream) {
@@ -211,6 +218,11 @@ public class PgpSignEncrypt extends BaseOperation {
return this;
}
+ public Builder setCharset(String charset) {
+ mCharset = charset;
+ return this;
+ }
+
/**
* Also encrypt with the signing keyring
*
@@ -222,14 +234,13 @@ public class PgpSignEncrypt extends BaseOperation {
return this;
}
- /**
- * TODO: test this option!
- *
- * @param cleartextInput
- * @return
- */
- public Builder setCleartextInput(boolean cleartextInput) {
- mCleartextInput = cleartextInput;
+ public Builder setCleartextSignature(boolean cleartextSignature) {
+ mCleartextSignature = cleartextSignature;
+ return this;
+ }
+
+ public Builder setDetachedSignature(boolean detachedSignature) {
+ mDetachedSignature = detachedSignature;
return this;
}
@@ -283,6 +294,10 @@ public class PgpSignEncrypt extends BaseOperation {
if (mVersionHeader != null) {
armorOut.setHeader("Version", mVersionHeader);
}
+ // if we have a charset, put it in the header
+ if (mCharset != null) {
+ armorOut.setHeader("Charset", mCharset);
+ }
out = armorOut;
} else {
out = mOutStream;
@@ -408,7 +423,7 @@ public class PgpSignEncrypt extends BaseOperation {
updateProgress(R.string.progress_preparing_signature, 4, 100);
try {
- boolean cleartext = mCleartextInput && mEnableAsciiArmorOutput && !enableEncryption;
+ boolean cleartext = mCleartextSignature && mEnableAsciiArmorOutput && !enableEncryption;
signatureGenerator = signingKey.getSignatureGenerator(
mSignatureHashAlgorithm, cleartext, mNfcSignedHash, mNfcCreationTimestamp);
} catch (PgpGeneralException e) {
@@ -424,6 +439,10 @@ public class PgpSignEncrypt extends BaseOperation {
OutputStream encryptionOut = null;
BCPGOutputStream bcpgOut;
+ ByteArrayOutputStream detachedByteOut = null;
+ ArmoredOutputStream detachedArmorOut = null;
+ BCPGOutputStream detachedBcpgOut = null;
+
try {
if (enableEncryption) {
@@ -452,7 +471,7 @@ public class PgpSignEncrypt extends BaseOperation {
PGPLiteralDataGenerator literalGen = new PGPLiteralDataGenerator();
char literalDataFormatTag;
- if (mCleartextInput) {
+ if (mCleartextSignature) {
literalDataFormatTag = PGPLiteralData.UTF8;
} else {
literalDataFormatTag = PGPLiteralData.BINARY;
@@ -482,7 +501,7 @@ public class PgpSignEncrypt extends BaseOperation {
literalGen.close();
indent -= 1;
- } else if (enableSignature && mCleartextInput && mEnableAsciiArmorOutput) {
+ } else if (enableSignature && mCleartextSignature && mEnableAsciiArmorOutput) {
/* cleartext signature: sign-only of ascii text */
updateProgress(R.string.progress_signing, 8, 100);
@@ -517,11 +536,48 @@ public class PgpSignEncrypt extends BaseOperation {
armorOut.endClearText();
pOut = new BCPGOutputStream(armorOut);
- } else if (enableSignature && !mCleartextInput) {
+ } else if (enableSignature && mDetachedSignature) {
+ /* detached signature */
+
+ updateProgress(R.string.progress_signing, 8, 100);
+ log.add(LogType.MSG_SE_SIGNING, indent);
+
+ InputStream in = mData.getInputStream();
+
+ // handle output stream separately for detached signatures
+ detachedByteOut = new ByteArrayOutputStream();
+ OutputStream detachedOut = detachedByteOut;
+ if (mEnableAsciiArmorOutput) {
+ detachedArmorOut = new ArmoredOutputStream(detachedOut);
+ if (mVersionHeader != null) {
+ detachedArmorOut.setHeader("Version", mVersionHeader);
+ }
+
+ detachedOut = detachedArmorOut;
+ }
+ detachedBcpgOut = new BCPGOutputStream(detachedOut);
+
+ long alreadyWritten = 0;
+ int length;
+ byte[] buffer = new byte[1 << 16];
+ while ((length = in.read(buffer)) > 0) {
+ // no output stream is written, no changed to original data!
+
+ signatureGenerator.update(buffer, 0, length);
+
+ alreadyWritten += length;
+ if (mData.getSize() > 0) {
+ long progress = 100 * alreadyWritten / mData.getSize();
+ progressScaler.setProgress((int) progress, 100);
+ }
+ }
+
+ pOut = null;
+ } else if (enableSignature && !mCleartextSignature && !mDetachedSignature) {
/* sign-only binary (files/data stream) */
updateProgress(R.string.progress_signing, 8, 100);
- log.add(LogType.MSG_SE_ENCRYPTING, indent);
+ log.add(LogType.MSG_SE_SIGNING, indent);
InputStream in = mData.getInputStream();
@@ -556,13 +612,18 @@ public class PgpSignEncrypt extends BaseOperation {
literalGen.close();
} else {
pOut = null;
+ // TODO: Is this log right?
log.add(LogType.MSG_SE_CLEARSIGN_ONLY, indent);
}
if (enableSignature) {
updateProgress(R.string.progress_generating_signature, 95, 100);
try {
- signatureGenerator.generate().encode(pOut);
+ if (detachedBcpgOut != null) {
+ signatureGenerator.generate().encode(detachedBcpgOut);
+ } else {
+ signatureGenerator.generate().encode(pOut);
+ }
} catch (NfcSyncPGPContentSignerBuilder.NfcInteractionNeeded e) {
// this secret key diverts to a OpenPGP card, throw exception with hash that will be signed
log.add(LogType.MSG_SE_PENDING_NFC, indent);
@@ -571,27 +632,38 @@ public class PgpSignEncrypt extends BaseOperation {
// Note that the checked key here is the master key, not the signing key
// (although these are always the same on Yubikeys)
result.setNfcData(mSignatureSubKeyId, e.hashToSign, e.hashAlgo, e.creationTimestamp, mSignaturePassphrase);
- Log.d(Constants.TAG, "e.hashToSign"+ Hex.toHexString(e.hashToSign));
+ Log.d(Constants.TAG, "e.hashToSign" + Hex.toHexString(e.hashToSign));
return result;
}
}
// closing outputs
// NOTE: closing needs to be done in the correct order!
- // TODO: closing bcpgOut and pOut???
- if (enableEncryption) {
- if (enableCompression) {
+ if (encryptionOut != null) {
+ if (compressGen != null) {
compressGen.close();
}
encryptionOut.close();
}
- if (mEnableAsciiArmorOutput) {
+ // Note: Closing ArmoredOutputStream does not close the underlying stream
+ if (armorOut != null) {
armorOut.close();
}
-
- out.close();
- mOutStream.close();
+ // Note: Closing ArmoredOutputStream does not close the underlying stream
+ if (detachedArmorOut != null) {
+ detachedArmorOut.close();
+ }
+ // Also closes detachedBcpgOut
+ if (detachedByteOut != null) {
+ detachedByteOut.close();
+ }
+ if (out != null) {
+ out.close();
+ }
+ if (mOutStream != null) {
+ mOutStream.close();
+ }
} catch (SignatureException e) {
log.add(LogType.MSG_SE_ERROR_SIG, indent);
@@ -607,10 +679,22 @@ public class PgpSignEncrypt extends BaseOperation {
updateProgress(R.string.progress_done, 100, 100);
log.add(LogType.MSG_SE_OK, indent);
- return new SignEncryptResult(SignEncryptResult.RESULT_OK, log);
-
+ SignEncryptResult result = new SignEncryptResult(SignEncryptResult.RESULT_OK, log);
+ if (detachedByteOut != null) {
+ try {
+ detachedByteOut.flush();
+ detachedByteOut.close();
+ } catch (IOException e) {
+ // silently catch
+ }
+ result.setDetachedSignature(detachedByteOut.toByteArray());
+ }
+ return result;
}
+ /**
+ * Remove whitespaces on line endings
+ */
private static void processLine(final String pLine, final ArmoredOutputStream pArmoredOutput,
final PGPSignatureGenerator pSignatureGenerator)
throws IOException, SignatureException {
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 04fb955fa..af85bd878 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java
@@ -445,7 +445,7 @@ public class UncachedKeyRing {
}
}
- ArrayList<String> processedUserIds = new ArrayList<String>();
+ ArrayList<String> processedUserIds = new ArrayList<>();
for (byte[] rawUserId : new IterableIterator<byte[]>(masterKey.getRawUserIDs())) {
String userId = Utf8Util.fromUTF8ByteArrayReplaceBadEncoding(rawUserId);
@@ -470,7 +470,7 @@ public class UncachedKeyRing {
@SuppressWarnings("unchecked")
Iterator<PGPSignature> signaturesIt = masterKey.getSignaturesForID(rawUserId);
if (signaturesIt != null) {
- for (PGPSignature zert : new IterableIterator<PGPSignature>(signaturesIt)) {
+ for (PGPSignature zert : new IterableIterator<>(signaturesIt)) {
WrappedSignature cert = new WrappedSignature(zert);
long certId = cert.getKeyId();
@@ -635,7 +635,7 @@ public class UncachedKeyRing {
@SuppressWarnings("unchecked")
Iterator<PGPSignature> signaturesIt = masterKey.getSignaturesForUserAttribute(userAttribute);
if (signaturesIt != null) {
- for (PGPSignature zert : new IterableIterator<PGPSignature>(signaturesIt)) {
+ for (PGPSignature zert : new IterableIterator<>(signaturesIt)) {
WrappedSignature cert = new WrappedSignature(zert);
long certId = cert.getKeyId();
@@ -778,7 +778,7 @@ public class UncachedKeyRing {
}
// Keep track of ids we encountered so far
- Set<Long> knownIds = new HashSet<Long>();
+ Set<Long> knownIds = new HashSet<>();
// Process all keys
for (PGPPublicKey key : new IterableIterator<PGPPublicKey>(ring.getPublicKeys())) {
@@ -1042,7 +1042,7 @@ public class UncachedKeyRing {
}
// remember which certs we already added. this is cheaper than semantic deduplication
- Set<byte[]> certs = new TreeSet<byte[]>(new Comparator<byte[]>() {
+ Set<byte[]> certs = new TreeSet<>(new Comparator<byte[]>() {
public int compare(byte[] left, byte[] right) {
// check for length equality
if (left.length != right.length) {
@@ -1124,7 +1124,7 @@ public class UncachedKeyRing {
if (signaturesIt == null) {
continue;
}
- for (PGPSignature cert : new IterableIterator<PGPSignature>(signaturesIt)) {
+ for (PGPSignature cert : new IterableIterator<>(signaturesIt)) {
// Don't merge foreign stuff into secret keys
if (cert.getKeyID() != masterKeyId && isSecret()) {
continue;
@@ -1149,7 +1149,7 @@ public class UncachedKeyRing {
if (signaturesIt == null) {
continue;
}
- for (PGPSignature cert : new IterableIterator<PGPSignature>(signaturesIt)) {
+ for (PGPSignature cert : new IterableIterator<>(signaturesIt)) {
// Don't merge foreign stuff into secret keys
if (cert.getKeyID() != masterKeyId && isSecret()) {
continue;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedPublicKey.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedPublicKey.java
index 9e3528515..0fe1ccdb6 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedPublicKey.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedPublicKey.java
@@ -20,7 +20,6 @@ package org.sufficientlysecure.keychain.pgp;
import org.spongycastle.bcpg.ECPublicBCPGKey;
import org.spongycastle.bcpg.SignatureSubpacketTags;
-import org.spongycastle.bcpg.sig.KeyFlags;
import org.spongycastle.openpgp.PGPPublicKey;
import org.spongycastle.openpgp.PGPSignature;
import org.spongycastle.openpgp.PGPSignatureSubpacketVector;
@@ -136,7 +135,7 @@ public class UncachedPublicKey {
continue;
}
- for (PGPSignature sig : new IterableIterator<PGPSignature>(signaturesIt)) {
+ for (PGPSignature sig : new IterableIterator<>(signaturesIt)) {
try {
// if this is a revocation, this is not the user id
@@ -200,7 +199,7 @@ public class UncachedPublicKey {
}
public ArrayList<String> getUnorderedUserIds() {
- ArrayList<String> userIds = new ArrayList<String>();
+ ArrayList<String> userIds = new ArrayList<>();
for (byte[] rawUserId : new IterableIterator<byte[]>(mPublicKey.getRawUserIDs())) {
// use our decoding method
userIds.add(Utf8Util.fromUTF8ByteArrayReplaceBadEncoding(rawUserId));
@@ -209,7 +208,7 @@ public class UncachedPublicKey {
}
public ArrayList<byte[]> getUnorderedRawUserIds() {
- ArrayList<byte[]> userIds = new ArrayList<byte[]>();
+ ArrayList<byte[]> userIds = new ArrayList<>();
for (byte[] userId : new IterableIterator<byte[]>(mPublicKey.getRawUserIDs())) {
userIds.add(userId);
}
@@ -217,7 +216,7 @@ public class UncachedPublicKey {
}
public ArrayList<WrappedUserAttribute> getUnorderedUserAttributes() {
- ArrayList<WrappedUserAttribute> userAttributes = new ArrayList<WrappedUserAttribute>();
+ ArrayList<WrappedUserAttribute> userAttributes = new ArrayList<>();
for (PGPUserAttributeSubpacketVector userAttribute :
new IterableIterator<PGPUserAttributeSubpacketVector>(mPublicKey.getUserAttributes())) {
userAttributes.add(new WrappedUserAttribute(userAttribute));
@@ -305,26 +304,56 @@ public class UncachedPublicKey {
*
* Note that this method has package visiblity because it is used in test
* cases. Certificates of UncachedPublicKey instances can NOT be assumed to
- * be verified, so the result of this method should not be used in other
- * places!
+ * be verified or even by the correct key, so the result of this method
+ * should never be used in other places!
*/
@SuppressWarnings("unchecked")
Integer getKeyUsage() {
if (mCacheUsage == null) {
+ PGPSignature mostRecentSig = null;
for (PGPSignature sig : new IterableIterator<PGPSignature>(mPublicKey.getSignatures())) {
if (mPublicKey.isMasterKey() && sig.getKeyID() != mPublicKey.getKeyID()) {
continue;
}
- PGPSignatureSubpacketVector hashed = sig.getHashedSubPackets();
+ switch (sig.getSignatureType()) {
+ case PGPSignature.DEFAULT_CERTIFICATION:
+ case PGPSignature.POSITIVE_CERTIFICATION:
+ case PGPSignature.CASUAL_CERTIFICATION:
+ case PGPSignature.NO_CERTIFICATION:
+ case PGPSignature.SUBKEY_BINDING:
+ break;
+ // if this is not one of the above types, don't care
+ default:
+ continue;
+ }
+
+ // If we have no sig yet, take the first we can get
+ if (mostRecentSig == null) {
+ mostRecentSig = sig;
+ continue;
+ }
+
+ // If the new sig is less recent, skip it
+ if (mostRecentSig.getCreationTime().after(sig.getCreationTime())) {
+ continue;
+ }
+
+ // Otherwise, note it down as the new "most recent" one
+ mostRecentSig = sig;
+ }
+
+ // Initialize to 0 as cached but empty value, if there is no sig (can't happen
+ // for canonicalized keyring), or there is no KEY_FLAGS packet in the sig
+ mCacheUsage = 0;
+ if (mostRecentSig != null) {
+ // If a mostRecentSig has been found, (cache and) return its flags
+ PGPSignatureSubpacketVector hashed = mostRecentSig.getHashedSubPackets();
if (hashed != null && hashed.getSubpacket(SignatureSubpacketTags.KEY_FLAGS) != null) {
- // init if at least one key flag subpacket has been found
- if (mCacheUsage == null) {
- mCacheUsage = 0;
- }
- mCacheUsage |= hashed.getKeyFlags();
+ mCacheUsage = hashed.getKeyFlags();
}
}
+
}
return mCacheUsage;
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedSignature.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedSignature.java
index cb03970e2..ade075d55 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedSignature.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedSignature.java
@@ -36,7 +36,6 @@ import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
import org.sufficientlysecure.keychain.util.Log;
import java.io.IOException;
-import java.security.SignatureException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
@@ -80,7 +79,7 @@ public class WrappedSignature {
}
public ArrayList<WrappedSignature> getEmbeddedSignatures() {
- ArrayList<WrappedSignature> sigs = new ArrayList<WrappedSignature>();
+ ArrayList<WrappedSignature> sigs = new ArrayList<>();
if (!mSig.hasSubpackets()) {
return sigs;
}
@@ -255,7 +254,7 @@ public class WrappedSignature {
}
public HashMap<String,String> getNotation() {
- HashMap<String,String> result = new HashMap<String,String>();
+ HashMap<String,String> result = new HashMap<>();
// If there is any notation data
if (mSig.getHashedSubPackets() != null
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 29b9c5f9f..72475472e 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java
@@ -248,7 +248,7 @@ public class KeychainProvider extends ContentProvider {
case KEY_RINGS_UNIFIED:
case KEY_RINGS_FIND_BY_EMAIL:
case KEY_RINGS_FIND_BY_SUBKEY: {
- HashMap<String, String> projectionMap = new HashMap<String, String>();
+ HashMap<String, String> projectionMap = new HashMap<>();
projectionMap.put(KeyRings._ID, Tables.KEYS + ".oid AS _id");
projectionMap.put(KeyRings.MASTER_KEY_ID, Tables.KEYS + "." + Keys.MASTER_KEY_ID);
projectionMap.put(KeyRings.KEY_ID, Tables.KEYS + "." + Keys.KEY_ID);
@@ -432,7 +432,7 @@ public class KeychainProvider extends ContentProvider {
}
case KEY_RING_KEYS: {
- HashMap<String, String> projectionMap = new HashMap<String, String>();
+ HashMap<String, String> projectionMap = new HashMap<>();
projectionMap.put(Keys._ID, Tables.KEYS + ".oid AS _id");
projectionMap.put(Keys.MASTER_KEY_ID, Tables.KEYS + "." + Keys.MASTER_KEY_ID);
projectionMap.put(Keys.RANK, Tables.KEYS + "." + Keys.RANK);
@@ -460,7 +460,7 @@ public class KeychainProvider extends ContentProvider {
case KEY_RINGS_USER_IDS:
case KEY_RING_USER_IDS: {
- HashMap<String, String> projectionMap = new HashMap<String, String>();
+ HashMap<String, String> projectionMap = new HashMap<>();
projectionMap.put(UserPackets._ID, Tables.USER_PACKETS + ".oid AS _id");
projectionMap.put(UserPackets.MASTER_KEY_ID, Tables.USER_PACKETS + "." + UserPackets.MASTER_KEY_ID);
projectionMap.put(UserPackets.TYPE, Tables.USER_PACKETS + "." + UserPackets.TYPE);
@@ -507,7 +507,7 @@ public class KeychainProvider extends ContentProvider {
case KEY_RINGS_PUBLIC:
case KEY_RING_PUBLIC: {
- HashMap<String, String> projectionMap = new HashMap<String, String>();
+ HashMap<String, String> projectionMap = new HashMap<>();
projectionMap.put(KeyRingData._ID, Tables.KEY_RINGS_PUBLIC + ".oid AS _id");
projectionMap.put(KeyRingData.MASTER_KEY_ID, KeyRingData.MASTER_KEY_ID);
projectionMap.put(KeyRingData.KEY_RING_DATA, KeyRingData.KEY_RING_DATA);
@@ -525,7 +525,7 @@ public class KeychainProvider extends ContentProvider {
case KEY_RINGS_SECRET:
case KEY_RING_SECRET: {
- HashMap<String, String> projectionMap = new HashMap<String, String>();
+ HashMap<String, String> projectionMap = new HashMap<>();
projectionMap.put(KeyRingData._ID, Tables.KEY_RINGS_SECRET + ".oid AS _id");
projectionMap.put(KeyRingData.MASTER_KEY_ID, KeyRingData.MASTER_KEY_ID);
projectionMap.put(KeyRingData.KEY_RING_DATA, KeyRingData.KEY_RING_DATA);
@@ -543,7 +543,7 @@ public class KeychainProvider extends ContentProvider {
case KEY_RING_CERTS:
case KEY_RING_CERTS_SPECIFIC: {
- HashMap<String, String> projectionMap = new HashMap<String, String>();
+ HashMap<String, String> projectionMap = new HashMap<>();
projectionMap.put(Certs._ID, Tables.CERTS + ".oid AS " + Certs._ID);
projectionMap.put(Certs.MASTER_KEY_ID, Tables.CERTS + "." + Certs.MASTER_KEY_ID);
projectionMap.put(Certs.RANK, Tables.CERTS + "." + Certs.RANK);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java
index c3990229d..a229f454f 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java
@@ -170,7 +170,7 @@ public class ProviderHelper {
Cursor cursor = mContentResolver.query(uri, proj, selection, null, null);
try {
- HashMap<String, Object> result = new HashMap<String, Object>(proj.length);
+ HashMap<String, Object> result = new HashMap<>(proj.length);
if (cursor != null && cursor.moveToFirst()) {
int pos = 0;
for (String p : proj) {
@@ -221,7 +221,7 @@ public class ProviderHelper {
}, KeyRings.HAS_ANY_SECRET + " = 1", null, null);
try {
- LongSparseArray<CanonicalizedPublicKey> result = new LongSparseArray<CanonicalizedPublicKey>();
+ LongSparseArray<CanonicalizedPublicKey> result = new LongSparseArray<>();
if (cursor != null && cursor.moveToFirst()) do {
long masterKeyId = cursor.getLong(0);
@@ -350,7 +350,7 @@ public class ProviderHelper {
mIndent += 1;
// save all keys and userIds included in keyRing object in database
- operations = new ArrayList<ContentProviderOperation>();
+ operations = new ArrayList<>();
log(LogType.MSG_IP_INSERT_KEYRING);
{ // insert keyring
@@ -440,7 +440,7 @@ public class ProviderHelper {
// classify and order user ids. primary are moved to the front, revoked to the back,
// otherwise the order in the keyfile is preserved.
- List<UserPacketItem> uids = new ArrayList<UserPacketItem>();
+ List<UserPacketItem> uids = new ArrayList<>();
if (trustedKeys.size() == 0) {
log(LogType.MSG_IP_UID_CLASSIFYING_ZERO);
@@ -460,7 +460,7 @@ public class ProviderHelper {
log(LogType.MSG_IP_UID_PROCESSING, userId);
mIndent += 1;
// look through signatures for this specific key
- for (WrappedSignature cert : new IterableIterator<WrappedSignature>(
+ for (WrappedSignature cert : new IterableIterator<>(
masterKey.getSignaturesForRawId(rawUserId))) {
long certId = cert.getKeyId();
// self signature
@@ -560,7 +560,7 @@ public class ProviderHelper {
}
mIndent += 1;
// look through signatures for this specific key
- for (WrappedSignature cert : new IterableIterator<WrappedSignature>(
+ for (WrappedSignature cert : new IterableIterator<>(
masterKey.getSignaturesForUserAttribute(userAttribute))) {
long certId = cert.getKeyId();
// self signature
@@ -712,10 +712,14 @@ public class ProviderHelper {
boolean isPrimary = false;
boolean isRevoked = false;
WrappedSignature selfCert;
- LongSparseArray<WrappedSignature> trustedCerts = new LongSparseArray<WrappedSignature>();
+ LongSparseArray<WrappedSignature> trustedCerts = new LongSparseArray<>();
@Override
public int compareTo(UserPacketItem o) {
+ // revoked keys always come last!
+ if (isRevoked != o.isRevoked) {
+ return isRevoked ? 1 : -1;
+ }
// if one is a user id, but the other isn't, the user id always comes first.
// we compare for null values here, so != is the correct operator!
// noinspection NumberEquality
@@ -726,10 +730,6 @@ public class ProviderHelper {
if (isPrimary != o.isPrimary) {
return isPrimary ? -1 : 1;
}
- // revoked keys always come last!
- if (isRevoked != o.isRevoked) {
- return isRevoked ? 1 : -1;
- }
return 0;
}
}
@@ -1075,7 +1075,7 @@ public class ProviderHelper {
// No keys existing might be a legitimate option, we write an empty file in that case
cursor.moveToFirst();
ParcelableFileCache<ParcelableKeyRing> cache =
- new ParcelableFileCache<ParcelableKeyRing>(mContext, "consolidate_secret.pcl");
+ new ParcelableFileCache<>(mContext, "consolidate_secret.pcl");
cache.writeCache(cursor.getCount(), new Iterator<ParcelableKeyRing>() {
ParcelableKeyRing ring;
@@ -1137,7 +1137,7 @@ public class ProviderHelper {
// No keys existing might be a legitimate option, we write an empty file in that case
cursor.moveToFirst();
ParcelableFileCache<ParcelableKeyRing> cache =
- new ParcelableFileCache<ParcelableKeyRing>(mContext, "consolidate_public.pcl");
+ new ParcelableFileCache<>(mContext, "consolidate_public.pcl");
cache.writeCache(cursor.getCount(), new Iterator<ParcelableKeyRing>() {
ParcelableKeyRing ring;
@@ -1220,9 +1220,9 @@ public class ProviderHelper {
mContentResolver.delete(KeyRings.buildUnifiedKeyRingsUri(), null, null);
ParcelableFileCache<ParcelableKeyRing> cacheSecret =
- new ParcelableFileCache<ParcelableKeyRing>(mContext, "consolidate_secret.pcl");
+ new ParcelableFileCache<>(mContext, "consolidate_secret.pcl");
ParcelableFileCache<ParcelableKeyRing> cachePublic =
- new ParcelableFileCache<ParcelableKeyRing>(mContext, "consolidate_public.pcl");
+ new ParcelableFileCache<>(mContext, "consolidate_public.pcl");
// Set flag that we have a cached consolidation here
try {
@@ -1380,7 +1380,7 @@ public class ProviderHelper {
public ArrayList<String> getRegisteredApiApps() {
Cursor cursor = mContentResolver.query(ApiApps.CONTENT_URI, null, null, null, null);
- ArrayList<String> packageNames = new ArrayList<String>();
+ ArrayList<String> packageNames = new ArrayList<>();
try {
if (cursor != null) {
int packageNameCol = cursor.getColumnIndex(ApiApps.PACKAGE_NAME);
@@ -1485,7 +1485,7 @@ public class ProviderHelper {
}
public Set<Long> getAllKeyIdsForApp(Uri uri) {
- Set<Long> keyIds = new HashSet<Long>();
+ Set<Long> keyIds = new HashSet<>();
Cursor cursor = mContentResolver.query(uri, null, null, null, null);
try {
@@ -1505,7 +1505,7 @@ public class ProviderHelper {
}
public Set<String> getAllFingerprints(Uri uri) {
- Set<String> fingerprints = new HashSet<String>();
+ Set<String> fingerprints = new HashSet<>();
String[] projection = new String[]{KeyRings.FINGERPRINT};
Cursor cursor = mContentResolver.query(uri, projection, null, null, null);
try {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java
index a5813567a..d967931ce 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java
@@ -85,9 +85,9 @@ public class OpenPgpService extends RemoteService {
boolean missingUserIdsCheck = false;
boolean duplicateUserIdsCheck = false;
- ArrayList<Long> keyIds = new ArrayList<Long>();
- ArrayList<String> missingUserIds = new ArrayList<String>();
- ArrayList<String> duplicateUserIds = new ArrayList<String>();
+ ArrayList<Long> keyIds = new ArrayList<>();
+ ArrayList<String> missingUserIds = new ArrayList<>();
+ ArrayList<String> duplicateUserIds = new ArrayList<>();
if (!noUserIdsCheck) {
for (String email : encryptionUserIds) {
// try to find the key for this specific email
@@ -222,9 +222,10 @@ public class OpenPgpService extends RemoteService {
}
private Intent signImpl(Intent data, ParcelFileDescriptor input,
- ParcelFileDescriptor output, AccountSettings accSettings) {
+ ParcelFileDescriptor output, AccountSettings accSettings,
+ boolean cleartextSign) {
try {
- boolean asciiArmor = data.getBooleanExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true);
+ boolean asciiArmor = cleartextSign || data.getBooleanExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true);
byte[] nfcSignedHash = data.getByteArrayExtra(OpenPgpApi.EXTRA_NFC_SIGNED_HASH);
if (nfcSignedHash != null) {
@@ -243,7 +244,12 @@ public class OpenPgpService extends RemoteService {
// Get Input- and OutputStream from ParcelFileDescriptor
InputStream is = new ParcelFileDescriptor.AutoCloseInputStream(input);
- OutputStream os = new ParcelFileDescriptor.AutoCloseOutputStream(output);
+ OutputStream os = null;
+ if (cleartextSign) {
+ // output stream only needed for cleartext signatures,
+ // detached signatures are returned as extra
+ os = new ParcelFileDescriptor.AutoCloseOutputStream(output);
+ }
try {
long inputLength = is.available();
InputData inputData = new InputData(is, inputLength);
@@ -284,6 +290,8 @@ public class OpenPgpService extends RemoteService {
inputData, os
);
builder.setEnableAsciiArmorOutput(asciiArmor)
+ .setCleartextSignature(cleartextSign)
+ .setDetachedSignature(!cleartextSign)
.setVersionHeader(PgpHelper.getVersionForHeader(this))
.setSignatureHashAlgorithm(accSettings.getHashAlgorithm())
.setSignatureMasterKeyId(accSettings.getKeyId())
@@ -291,9 +299,6 @@ public class OpenPgpService extends RemoteService {
.setSignaturePassphrase(passphrase)
.setNfcState(nfcSignedHash, nfcCreationDate);
- // TODO: currently always assume cleartext input, no sign-only of binary currently!
- builder.setCleartextInput(true);
-
// execute PGP operation!
SignEncryptResult pgpResult = builder.build().execute();
@@ -313,20 +318,22 @@ public class OpenPgpService extends RemoteService {
"Encountered unhandled type of pending action not supported by API!");
}
} else if (pgpResult.success()) {
- // see end of method
+ Intent result = new Intent();
+ if (!cleartextSign) {
+ result.putExtra(OpenPgpApi.RESULT_DETACHED_SIGNATURE, pgpResult.getDetachedSignature());
+ }
+ result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_SUCCESS);
+ return result;
} else {
LogEntryParcel errorMsg = pgpResult.getLog().getLast();
throw new Exception(getString(errorMsg.mType.getMsgId()));
}
-
} finally {
is.close();
- os.close();
+ if (os != null) {
+ os.close();
+ }
}
-
- Intent result = new Intent();
- result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_SUCCESS);
- return result;
} catch (Exception e) {
Log.d(Constants.TAG, "signImpl", e);
Intent result = new Intent();
@@ -444,7 +451,9 @@ public class OpenPgpService extends RemoteService {
"Encountered unhandled type of pending action not supported by API!");
}
} else if (pgpResult.success()) {
- // see end of method
+ Intent result = new Intent();
+ result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_SUCCESS);
+ return result;
} else {
LogEntryParcel errorMsg = pgpResult.getLog().getLast();
throw new Exception(getString(errorMsg.mType.getMsgId()));
@@ -454,10 +463,6 @@ public class OpenPgpService extends RemoteService {
is.close();
os.close();
}
-
- Intent result = new Intent();
- result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_SUCCESS);
- return result;
} catch (Exception e) {
Log.d(Constants.TAG, "encryptAndSignImpl", e);
Intent result = new Intent();
@@ -476,13 +481,13 @@ public class OpenPgpService extends RemoteService {
InputStream is = new ParcelFileDescriptor.AutoCloseInputStream(input);
OutputStream os;
- if (decryptMetadataOnly) {
+ // output is optional, e.g., for verifying detached signatures
+ if (decryptMetadataOnly || output == null) {
os = null;
} else {
os = new ParcelFileDescriptor.AutoCloseOutputStream(output);
}
- Intent result = new Intent();
try {
String passphrase = data.getStringExtra(OpenPgpApi.EXTRA_PASSPHRASE);
long inputLength = is.available();
@@ -494,15 +499,17 @@ public class OpenPgpService extends RemoteService {
byte[] nfcDecryptedSessionKey = data.getByteArrayExtra(OpenPgpApi.EXTRA_NFC_DECRYPTED_SESSION_KEY);
+ byte[] detachedSignature = data.getByteArrayExtra(OpenPgpApi.EXTRA_DETACHED_SIGNATURE);
+
// allow only private keys associated with accounts of this app
// no support for symmetric encryption
builder.setPassphrase(passphrase)
.setAllowSymmetricDecryption(false)
.setAllowedKeyIds(allowedKeyIds)
.setDecryptMetadataOnly(decryptMetadataOnly)
- .setNfcState(nfcDecryptedSessionKey);
+ .setNfcState(nfcDecryptedSessionKey)
+ .setDetachedSignature(detachedSignature);
- // TODO: currently does not support binary signed-only content
DecryptVerifyResult pgpResult = builder.build().execute();
if (pgpResult.isPending()) {
@@ -522,6 +529,7 @@ public class OpenPgpService extends RemoteService {
"Encountered unhandled type of pending action not supported by API!");
}
} else if (pgpResult.success()) {
+ Intent result = new Intent();
OpenPgpSignatureResult signatureResult = pgpResult.getSignatureResult();
if (signatureResult != null) {
@@ -557,6 +565,14 @@ public class OpenPgpService extends RemoteService {
result.putExtra(OpenPgpApi.RESULT_METADATA, metadata);
}
}
+
+ String charset = pgpResult.getCharset();
+ if (charset != null) {
+ result.putExtra(OpenPgpApi.RESULT_CHARSET, charset);
+ }
+
+ result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_SUCCESS);
+ return result;
} else {
LogEntryParcel errorMsg = pgpResult.getLog().getLast();
throw new Exception(getString(errorMsg.mType.getMsgId()));
@@ -567,9 +583,6 @@ public class OpenPgpService extends RemoteService {
os.close();
}
}
-
- result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_SUCCESS);
- return result;
} catch (Exception e) {
Log.d(Constants.TAG, "decryptAndVerifyImpl", e);
Intent result = new Intent();
@@ -668,15 +681,16 @@ public class OpenPgpService extends RemoteService {
// version code is required and needs to correspond to version code of service!
// History of versions in org.openintents.openpgp.util.OpenPgpApi
- // we support 3, 4, 5
+ // we support 3, 4, 5, 6
if (data.getIntExtra(OpenPgpApi.EXTRA_API_VERSION, -1) != 3
&& data.getIntExtra(OpenPgpApi.EXTRA_API_VERSION, -1) != 4
- && data.getIntExtra(OpenPgpApi.EXTRA_API_VERSION, -1) != 5) {
+ && data.getIntExtra(OpenPgpApi.EXTRA_API_VERSION, -1) != 5
+ && data.getIntExtra(OpenPgpApi.EXTRA_API_VERSION, -1) != 6) {
Intent result = new Intent();
OpenPgpError error = new OpenPgpError
(OpenPgpError.INCOMPATIBLE_API_VERSIONS, "Incompatible API versions!\n"
+ "used API version: " + data.getIntExtra(OpenPgpApi.EXTRA_API_VERSION, -1) + "\n"
- + "supported API versions: 3, 4");
+ + "supported API versions: 3, 4, 5, 6");
result.putExtra(OpenPgpApi.RESULT_ERROR, error);
result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR);
return result;
@@ -718,8 +732,14 @@ public class OpenPgpService extends RemoteService {
}
String action = data.getAction();
- if (OpenPgpApi.ACTION_SIGN.equals(action)) {
- return signImpl(data, input, output, accSettings);
+ if (OpenPgpApi.ACTION_CLEARTEXT_SIGN.equals(action)) {
+ return signImpl(data, input, output, accSettings, true);
+ } else if (OpenPgpApi.ACTION_SIGN.equals(action)) {
+ // DEPRECATED: same as ACTION_CLEARTEXT_SIGN
+ Log.w(Constants.TAG, "You are using a deprecated API call, please use ACTION_CLEARTEXT_SIGN instead of ACTION_SIGN!");
+ return signImpl(data, input, output, accSettings, true);
+ } else if (OpenPgpApi.ACTION_DETACHED_SIGN.equals(action)) {
+ return signImpl(data, input, output, accSettings, false);
} else if (OpenPgpApi.ACTION_ENCRYPT.equals(action)) {
return encryptAndSignImpl(data, input, output, accSettings, false);
} else if (OpenPgpApi.ACTION_SIGN_AND_ENCRYPT.equals(action)) {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/RemoteService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/RemoteService.java
index e71b52ccd..672f59285 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/RemoteService.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/RemoteService.java
@@ -27,7 +27,6 @@ import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.Signature;
import android.net.Uri;
import android.os.Binder;
-import android.text.TextUtils;
import org.openintents.openpgp.OpenPgpError;
import org.openintents.openpgp.util.OpenPgpApi;
@@ -216,9 +215,7 @@ public abstract class RemoteService extends Service {
String[] callingPackages = getPackageManager().getPackagesForUid(uid);
// is calling package allowed to use this service?
- for (int i = 0; i < callingPackages.length; i++) {
- String currentPkg = callingPackages[i];
-
+ for (String currentPkg : callingPackages) {
if (isPackageAllowed(currentPkg)) {
return true;
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountSettingsActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountSettingsActivity.java
index 7d77a989d..e5edd6a0f 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountSettingsActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountSettingsActivity.java
@@ -20,7 +20,6 @@ package org.sufficientlysecure.keychain.remote.ui;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
-import android.support.v7.app.ActionBarActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
@@ -28,7 +27,6 @@ import android.view.View;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.ui.BaseActivity;
-import org.sufficientlysecure.keychain.ui.util.ActionBarHelper;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.remote.AccountSettings;
import org.sufficientlysecure.keychain.operations.results.OperationResult;
@@ -46,14 +44,18 @@ public class AccountSettingsActivity extends BaseActivity {
super.onCreate(savedInstanceState);
// Inflate a "Done" custom action bar
- ActionBarHelper.setOneButtonView(getSupportActionBar(),
- R.string.api_settings_save, R.drawable.ic_action_done,
+ setFullScreenDialogDoneClose(R.string.api_settings_save,
new View.OnClickListener() {
@Override
public void onClick(View v) {
- // "Done"
save();
}
+ },
+ new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ finish();
+ }
});
@@ -130,9 +132,4 @@ public class AccountSettingsActivity extends BaseActivity {
}
}
- @Override
- public void onBackPressed() {
- save();
- super.onBackPressed();
- }
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AppSettingsActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AppSettingsActivity.java
index d84a03698..e91482e28 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AppSettingsActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AppSettingsActivity.java
@@ -22,8 +22,6 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
-import android.support.v7.app.ActionBar;
-import android.support.v7.app.ActionBarActivity;
import android.view.Menu;
import android.view.MenuItem;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AppsListActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AppsListActivity.java
index 079b3065e..3b4cc654e 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AppsListActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AppsListActivity.java
@@ -21,19 +21,27 @@ import android.os.Bundle;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.ui.DrawerActivity;
+import org.sufficientlysecure.keychain.ui.NavDrawerActivity;
-public class AppsListActivity extends DrawerActivity {
+public class AppsListActivity extends NavDrawerActivity {
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- activateDrawerNavigation(savedInstanceState);
- }
+// @Override
+// protected void onCreate(Bundle savedInstanceState) {
+// super.onCreate(savedInstanceState);
+//
+// activateDrawerNavigation(savedInstanceState);
+// }
@Override
- protected void initLayout() {
+ public void init(Bundle savedInstanceState) {
+ super.init(savedInstanceState);
setContentView(R.layout.api_apps_list_activity);
}
+
+// @Override
+// protected void initLayout() {
+// setContentView(R.layout.api_apps_list_activity);
+// }
+
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/RemoteServiceActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/RemoteServiceActivity.java
index a9a7c75f5..cbc593b0a 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/RemoteServiceActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/RemoteServiceActivity.java
@@ -22,7 +22,6 @@ import android.graphics.Color;
import android.graphics.Typeface;
import android.net.Uri;
import android.os.Bundle;
-import android.support.v7.app.ActionBarActivity;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.SpannableStringBuilder;
@@ -41,7 +40,6 @@ import org.sufficientlysecure.keychain.remote.AccountSettings;
import org.sufficientlysecure.keychain.remote.AppSettings;
import org.sufficientlysecure.keychain.ui.BaseActivity;
import org.sufficientlysecure.keychain.ui.SelectPublicKeyFragment;
-import org.sufficientlysecure.keychain.ui.util.ActionBarHelper;
import org.sufficientlysecure.keychain.ui.util.Notify;
import org.sufficientlysecure.keychain.util.Log;
@@ -108,234 +106,239 @@ public class RemoteServiceActivity extends BaseActivity {
final Bundle extras = intent.getExtras();
- if (ACTION_REGISTER.equals(action)) {
- final String packageName = extras.getString(EXTRA_PACKAGE_NAME);
- final byte[] packageSignature = extras.getByteArray(EXTRA_PACKAGE_SIGNATURE);
- Log.d(Constants.TAG, "ACTION_REGISTER packageName: " + packageName);
+ switch (action) {
+ case ACTION_REGISTER: {
+ final String packageName = extras.getString(EXTRA_PACKAGE_NAME);
+ final byte[] packageSignature = extras.getByteArray(EXTRA_PACKAGE_SIGNATURE);
+ Log.d(Constants.TAG, "ACTION_REGISTER packageName: " + packageName);
- setContentView(R.layout.api_remote_register_app);
- initToolbar();
+ setContentView(R.layout.api_remote_register_app);
+ initToolbar();
- mAppSettingsFragment = (AppSettingsFragment) getSupportFragmentManager().findFragmentById(
- R.id.api_app_settings_fragment);
+ mAppSettingsFragment = (AppSettingsFragment) getSupportFragmentManager().findFragmentById(
+ R.id.api_app_settings_fragment);
- AppSettings settings = new AppSettings(packageName, packageSignature);
- mAppSettingsFragment.setAppSettings(settings);
+ AppSettings settings = new AppSettings(packageName, packageSignature);
+ mAppSettingsFragment.setAppSettings(settings);
- // Inflate a "Done"/"Cancel" custom action bar view
- ActionBarHelper.setTwoButtonView(getSupportActionBar(),
- R.string.api_register_allow, R.drawable.ic_action_done,
- new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- // Allow
+ // Inflate a "Done"/"Cancel" custom action bar view
+ setFullScreenDialogTwoButtons(
+ R.string.api_register_allow, R.drawable.ic_check_white_24dp,
+ new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ // Allow
- mProviderHelper.insertApiApp(mAppSettingsFragment.getAppSettings());
+ mProviderHelper.insertApiApp(mAppSettingsFragment.getAppSettings());
- // give data through for new service call
- Intent resultData = extras.getParcelable(EXTRA_DATA);
- RemoteServiceActivity.this.setResult(RESULT_OK, resultData);
- RemoteServiceActivity.this.finish();
- }
- }, R.string.api_register_disallow, R.drawable.ic_action_cancel,
- new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- // Disallow
- RemoteServiceActivity.this.setResult(RESULT_CANCELED);
- RemoteServiceActivity.this.finish();
+ // give data through for new service call
+ Intent resultData = extras.getParcelable(EXTRA_DATA);
+ RemoteServiceActivity.this.setResult(RESULT_OK, resultData);
+ RemoteServiceActivity.this.finish();
+ }
+ }, R.string.api_register_disallow, R.drawable.ic_close_white_24dp,
+ new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ // Disallow
+ RemoteServiceActivity.this.setResult(RESULT_CANCELED);
+ RemoteServiceActivity.this.finish();
+ }
}
- }
- );
- } else if (ACTION_CREATE_ACCOUNT.equals(action)) {
- final String packageName = extras.getString(EXTRA_PACKAGE_NAME);
- final String accName = extras.getString(EXTRA_ACC_NAME);
+ );
+ break;
+ }
+ case ACTION_CREATE_ACCOUNT: {
+ final String packageName = extras.getString(EXTRA_PACKAGE_NAME);
+ final String accName = extras.getString(EXTRA_ACC_NAME);
- setContentView(R.layout.api_remote_create_account);
- initToolbar();
+ setContentView(R.layout.api_remote_create_account);
+ initToolbar();
- mAccSettingsFragment = (AccountSettingsFragment) getSupportFragmentManager().findFragmentById(
- R.id.api_account_settings_fragment);
+ mAccSettingsFragment = (AccountSettingsFragment) getSupportFragmentManager().findFragmentById(
+ R.id.api_account_settings_fragment);
- TextView text = (TextView) findViewById(R.id.api_remote_create_account_text);
+ TextView text = (TextView) findViewById(R.id.api_remote_create_account_text);
- // update existing?
- Uri uri = KeychainContract.ApiAccounts.buildByPackageAndAccountUri(packageName, accName);
- AccountSettings settings = mProviderHelper.getApiAccountSettings(uri);
- if (settings == null) {
- // create new account
- settings = new AccountSettings(accName);
- mUpdateExistingAccount = false;
+ // update existing?
+ Uri uri = KeychainContract.ApiAccounts.buildByPackageAndAccountUri(packageName, accName);
+ AccountSettings settings = mProviderHelper.getApiAccountSettings(uri);
+ if (settings == null) {
+ // create new account
+ settings = new AccountSettings(accName);
+ mUpdateExistingAccount = false;
- text.setText(R.string.api_create_account_text);
- } else {
- // update existing account
- mUpdateExistingAccount = true;
+ text.setText(R.string.api_create_account_text);
+ } else {
+ // update existing account
+ mUpdateExistingAccount = true;
- text.setText(R.string.api_update_account_text);
- }
- mAccSettingsFragment.setAccSettings(settings);
-
- // Inflate a "Done"/"Cancel" custom action bar view
- ActionBarHelper.setTwoButtonView(getSupportActionBar(),
- R.string.api_settings_save, R.drawable.ic_action_done,
- new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- // Save
-
- // user needs to select a key if it has explicitly requested (None is only allowed for new accounts)
- if (mUpdateExistingAccount && mAccSettingsFragment.getAccSettings().getKeyId() == Constants.key.none) {
- Notify.showNotify(RemoteServiceActivity.this, getString(R.string.api_register_error_select_key), Notify.Style.ERROR);
- } else {
- if (mUpdateExistingAccount) {
- Uri baseUri = KeychainContract.ApiAccounts.buildBaseUri(packageName);
- Uri accountUri = baseUri.buildUpon().appendEncodedPath(accName).build();
- mProviderHelper.updateApiAccount(
- accountUri,
- mAccSettingsFragment.getAccSettings());
+ text.setText(R.string.api_update_account_text);
+ }
+ mAccSettingsFragment.setAccSettings(settings);
+
+ // Inflate a "Done"/"Cancel" custom action bar view
+ setFullScreenDialogDoneClose(R.string.api_settings_save,
+ new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ // Save
+
+ // user needs to select a key if it has explicitly requested (None is only allowed for new accounts)
+ if (mUpdateExistingAccount && mAccSettingsFragment.getAccSettings().getKeyId() == Constants.key.none) {
+ Notify.showNotify(RemoteServiceActivity.this, getString(R.string.api_register_error_select_key), Notify.Style.ERROR);
} else {
- mProviderHelper.insertApiAccount(
- KeychainContract.ApiAccounts.buildBaseUri(packageName),
- mAccSettingsFragment.getAccSettings());
+ if (mUpdateExistingAccount) {
+ Uri baseUri = KeychainContract.ApiAccounts.buildBaseUri(packageName);
+ Uri accountUri = baseUri.buildUpon().appendEncodedPath(accName).build();
+ mProviderHelper.updateApiAccount(
+ accountUri,
+ mAccSettingsFragment.getAccSettings());
+ } else {
+ mProviderHelper.insertApiAccount(
+ KeychainContract.ApiAccounts.buildBaseUri(packageName),
+ mAccSettingsFragment.getAccSettings());
+ }
+
+ // give data through for new service call
+ Intent resultData = extras.getParcelable(EXTRA_DATA);
+ RemoteServiceActivity.this.setResult(RESULT_OK, resultData);
+ RemoteServiceActivity.this.finish();
}
-
- // give data through for new service call
- Intent resultData = extras.getParcelable(EXTRA_DATA);
- RemoteServiceActivity.this.setResult(RESULT_OK, resultData);
+ }
+ },
+ new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ // Cancel
+ RemoteServiceActivity.this.setResult(RESULT_CANCELED);
RemoteServiceActivity.this.finish();
}
- }
- }, R.string.api_settings_cancel, R.drawable.ic_action_cancel,
- new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- // Cancel
- RemoteServiceActivity.this.setResult(RESULT_CANCELED);
- RemoteServiceActivity.this.finish();
- }
+ });
+
+ break;
+ }
+ case ACTION_SELECT_PUB_KEYS: {
+ long[] selectedMasterKeyIds = intent.getLongArrayExtra(EXTRA_SELECTED_MASTER_KEY_IDS);
+ boolean noUserIdsCheck = intent.getBooleanExtra(EXTRA_NO_USER_IDS_CHECK, true);
+ ArrayList<String> missingUserIds = intent
+ .getStringArrayListExtra(EXTRA_MISSING_USER_IDS);
+ ArrayList<String> dublicateUserIds = intent
+ .getStringArrayListExtra(EXTRA_DUPLICATE_USER_IDS);
+
+ SpannableStringBuilder ssb = new SpannableStringBuilder();
+ final SpannableString textIntro = new SpannableString(
+ noUserIdsCheck ? getString(R.string.api_select_pub_keys_text_no_user_ids)
+ : getString(R.string.api_select_pub_keys_text)
+ );
+ textIntro.setSpan(new StyleSpan(Typeface.BOLD), 0, textIntro.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+ ssb.append(textIntro);
+
+ if (missingUserIds != null && missingUserIds.size() > 0) {
+ ssb.append("\n\n");
+ ssb.append(getString(R.string.api_select_pub_keys_missing_text));
+ ssb.append("\n");
+ for (String userId : missingUserIds) {
+ SpannableString ss = new SpannableString(userId + "\n");
+ ss.setSpan(new BulletSpan(15, Color.BLACK), 0, ss.length(),
+ Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+ ssb.append(ss);
}
- );
-
- } else if (ACTION_SELECT_PUB_KEYS.equals(action)) {
- long[] selectedMasterKeyIds = intent.getLongArrayExtra(EXTRA_SELECTED_MASTER_KEY_IDS);
- boolean noUserIdsCheck = intent.getBooleanExtra(EXTRA_NO_USER_IDS_CHECK, true);
- ArrayList<String> missingUserIds = intent
- .getStringArrayListExtra(EXTRA_MISSING_USER_IDS);
- ArrayList<String> dublicateUserIds = intent
- .getStringArrayListExtra(EXTRA_DUPLICATE_USER_IDS);
-
- SpannableStringBuilder ssb = new SpannableStringBuilder();
- final SpannableString textIntro = new SpannableString(
- noUserIdsCheck ? getString(R.string.api_select_pub_keys_text_no_user_ids)
- : getString(R.string.api_select_pub_keys_text)
- );
- textIntro.setSpan(new StyleSpan(Typeface.BOLD), 0, textIntro.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
- ssb.append(textIntro);
-
- if (missingUserIds != null && missingUserIds.size() > 0) {
- ssb.append("\n\n");
- ssb.append(getString(R.string.api_select_pub_keys_missing_text));
- ssb.append("\n");
- for (String userId : missingUserIds) {
- SpannableString ss = new SpannableString(userId + "\n");
- ss.setSpan(new BulletSpan(15, Color.BLACK), 0, ss.length(),
- Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
- ssb.append(ss);
}
- }
- if (dublicateUserIds != null && dublicateUserIds.size() > 0) {
- ssb.append("\n\n");
- ssb.append(getString(R.string.api_select_pub_keys_dublicates_text));
- ssb.append("\n");
- for (String userId : dublicateUserIds) {
- SpannableString ss = new SpannableString(userId + "\n");
- ss.setSpan(new BulletSpan(15, Color.BLACK), 0, ss.length(),
- Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
- ssb.append(ss);
+ if (dublicateUserIds != null && dublicateUserIds.size() > 0) {
+ ssb.append("\n\n");
+ ssb.append(getString(R.string.api_select_pub_keys_dublicates_text));
+ ssb.append("\n");
+ for (String userId : dublicateUserIds) {
+ SpannableString ss = new SpannableString(userId + "\n");
+ ss.setSpan(new BulletSpan(15, Color.BLACK), 0, ss.length(),
+ Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+ ssb.append(ss);
+ }
}
- }
- setContentView(R.layout.api_remote_select_pub_keys);
- initToolbar();
-
- // Inflate a "Done"/"Cancel" custom action bar view
- ActionBarHelper.setTwoButtonView(getSupportActionBar(),
- R.string.btn_okay, R.drawable.ic_action_done,
- new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- // add key ids to params Bundle for new request
- Intent resultData = extras.getParcelable(EXTRA_DATA);
- resultData.putExtra(OpenPgpApi.EXTRA_KEY_IDS,
- mSelectFragment.getSelectedMasterKeyIds());
-
- RemoteServiceActivity.this.setResult(RESULT_OK, resultData);
- RemoteServiceActivity.this.finish();
- }
- }, R.string.btn_do_not_save, R.drawable.ic_action_cancel, new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- // cancel
- RemoteServiceActivity.this.setResult(RESULT_CANCELED);
- RemoteServiceActivity.this.finish();
- }
- }
- );
+ setContentView(R.layout.api_remote_select_pub_keys);
+ initToolbar();
+ // Inflate a "Done"/"Cancel" custom action bar view
+ setFullScreenDialogDoneClose(R.string.btn_okay,
+ new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ // add key ids to params Bundle for new request
+ Intent resultData = extras.getParcelable(EXTRA_DATA);
+ resultData.putExtra(OpenPgpApi.EXTRA_KEY_IDS,
+ mSelectFragment.getSelectedMasterKeyIds());
- // set text on view
- TextView textView = (TextView) findViewById(R.id.api_select_pub_keys_text);
- textView.setText(ssb, TextView.BufferType.SPANNABLE);
+ RemoteServiceActivity.this.setResult(RESULT_OK, resultData);
+ RemoteServiceActivity.this.finish();
+ }
+ },
+ new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ // cancel
+ RemoteServiceActivity.this.setResult(RESULT_CANCELED);
+ RemoteServiceActivity.this.finish();
+ }
+ });
+
+ // set text on view
+ TextView textView = (TextView) findViewById(R.id.api_select_pub_keys_text);
+ textView.setText(ssb, TextView.BufferType.SPANNABLE);
+
+ /* Load select pub keys fragment */
+ // Check that the activity is using the layout version with
+ // the fragment_container FrameLayout
+ if (findViewById(R.id.api_select_pub_keys_fragment_container) != null) {
+
+ // However, if we're being restored from a previous state,
+ // then we don't need to do anything and should return or else
+ // we could end up with overlapping fragments.
+ if (savedInstanceState != null) {
+ return;
+ }
- /* Load select pub keys fragment */
- // Check that the activity is using the layout version with
- // the fragment_container FrameLayout
- if (findViewById(R.id.api_select_pub_keys_fragment_container) != null) {
+ // Create an instance of the fragment
+ mSelectFragment = SelectPublicKeyFragment.newInstance(selectedMasterKeyIds);
- // However, if we're being restored from a previous state,
- // then we don't need to do anything and should return or else
- // we could end up with overlapping fragments.
- if (savedInstanceState != null) {
- return;
+ // Add the fragment to the 'fragment_container' FrameLayout
+ getSupportFragmentManager().beginTransaction()
+ .add(R.id.api_select_pub_keys_fragment_container, mSelectFragment).commit();
}
-
- // Create an instance of the fragment
- mSelectFragment = SelectPublicKeyFragment.newInstance(selectedMasterKeyIds);
-
- // Add the fragment to the 'fragment_container' FrameLayout
- getSupportFragmentManager().beginTransaction()
- .add(R.id.api_select_pub_keys_fragment_container, mSelectFragment).commit();
+ break;
}
- } else if (ACTION_ERROR_MESSAGE.equals(action)) {
- String errorMessage = intent.getStringExtra(EXTRA_ERROR_MESSAGE);
+ case ACTION_ERROR_MESSAGE: {
+ String errorMessage = intent.getStringExtra(EXTRA_ERROR_MESSAGE);
- Spannable redErrorMessage = new SpannableString(errorMessage);
- redErrorMessage.setSpan(new ForegroundColorSpan(Color.RED), 0, errorMessage.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+ Spannable redErrorMessage = new SpannableString(errorMessage);
+ redErrorMessage.setSpan(new ForegroundColorSpan(Color.RED), 0, errorMessage.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
- setContentView(R.layout.api_remote_error_message);
- initToolbar();
+ setContentView(R.layout.api_remote_error_message);
+ initToolbar();
- // Inflate a "Done" custom action bar view
- ActionBarHelper.setOneButtonView(getSupportActionBar(),
- R.string.btn_okay, R.drawable.ic_action_done,
- new View.OnClickListener() {
+ // Inflate a "Done" custom action bar view
+ setFullScreenDialogClose(
+ new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- RemoteServiceActivity.this.setResult(RESULT_CANCELED);
- RemoteServiceActivity.this.finish();
+ @Override
+ public void onClick(View v) {
+ RemoteServiceActivity.this.setResult(RESULT_CANCELED);
+ RemoteServiceActivity.this.finish();
+ }
}
- }
- );
-
- // set text on view
- TextView textView = (TextView) findViewById(R.id.api_app_error_message_text);
- textView.setText(redErrorMessage);
- } else {
- Log.e(Constants.TAG, "Action does not exist!");
- setResult(RESULT_CANCELED);
- finish();
+ );
+
+ // set text on view
+ TextView textView = (TextView) findViewById(R.id.api_app_error_message_text);
+ textView.setText(redErrorMessage);
+ break;
+ }
+ default:
+ Log.e(Constants.TAG, "Action does not exist!");
+ setResult(RESULT_CANCELED);
+ finish();
+ break;
}
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/CertifyActionsParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/CertifyActionsParcel.java
index dd9c0d769..f0dbf0820 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/CertifyActionsParcel.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/CertifyActionsParcel.java
@@ -34,7 +34,7 @@ public class CertifyActionsParcel implements Parcelable {
final public long mMasterKeyId;
public CertifyLevel mLevel;
- public ArrayList<CertifyAction> mCertifyActions = new ArrayList<CertifyAction>();
+ public ArrayList<CertifyAction> mCertifyActions = new ArrayList<>();
public CertifyActionsParcel(long masterKeyId) {
mMasterKeyId = masterKeyId;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java
index 479810203..264b45035 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java
@@ -30,10 +30,11 @@ import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.operations.CertifyOperation;
import org.sufficientlysecure.keychain.operations.DeleteOperation;
import org.sufficientlysecure.keychain.operations.EditKeyOperation;
+import org.sufficientlysecure.keychain.operations.PromoteKeyOperation;
import org.sufficientlysecure.keychain.operations.results.DeleteResult;
import org.sufficientlysecure.keychain.operations.results.EditKeyResult;
import org.sufficientlysecure.keychain.operations.results.ExportResult;
-import org.sufficientlysecure.keychain.operations.results.PgpEditKeyResult;
+import org.sufficientlysecure.keychain.operations.results.PromoteKeyResult;
import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
import org.sufficientlysecure.keychain.operations.results.CertifyResult;
import org.sufficientlysecure.keychain.util.FileHelper;
@@ -91,6 +92,8 @@ public class KeychainIntentService extends IntentService implements Progressable
public static final String ACTION_EDIT_KEYRING = Constants.INTENT_PREFIX + "EDIT_KEYRING";
+ public static final String ACTION_PROMOTE_KEYRING = Constants.INTENT_PREFIX + "PROMOTE_KEYRING";
+
public static final String ACTION_IMPORT_KEYRING = Constants.INTENT_PREFIX + "IMPORT_KEYRING";
public static final String ACTION_EXPORT_KEYRING = Constants.INTENT_PREFIX + "EXPORT_KEYRING";
@@ -161,6 +164,10 @@ public class KeychainIntentService extends IntentService implements Progressable
// certify key
public static final String CERTIFY_PARCEL = "certify_parcel";
+ // promote key
+ public static final String PROMOTE_MASTER_KEY_ID = "promote_master_key_id";
+ public static final String PROMOTE_TYPE = "promote_type";
+
// consolidate
public static final String CONSOLIDATE_RECOVERY = "consolidate_recovery";
@@ -224,301 +231,304 @@ public class KeychainIntentService extends IntentService implements Progressable
String action = intent.getAction();
// executeServiceMethod action from extra bundle
- if (ACTION_CERTIFY_KEYRING.equals(action)) {
-
- // Input
- CertifyActionsParcel parcel = data.getParcelable(CERTIFY_PARCEL);
- String keyServerUri = data.getString(UPLOAD_KEY_SERVER);
+ switch (action) {
+ case ACTION_CERTIFY_KEYRING: {
- // Operation
- CertifyOperation op = new CertifyOperation(this, providerHelper, this, mActionCanceled);
- CertifyResult result = op.certify(parcel, keyServerUri);
+ // Input
+ CertifyActionsParcel parcel = data.getParcelable(CERTIFY_PARCEL);
+ String keyServerUri = data.getString(UPLOAD_KEY_SERVER);
- // Result
- sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, result);
+ // Operation
+ CertifyOperation op = new CertifyOperation(this, providerHelper, this, mActionCanceled);
+ CertifyResult result = op.certify(parcel, keyServerUri);
- } else if (ACTION_CONSOLIDATE.equals(action)) {
+ // Result
+ sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, result);
- // Operation
- ConsolidateResult result;
- if (data.containsKey(CONSOLIDATE_RECOVERY) && data.getBoolean(CONSOLIDATE_RECOVERY)) {
- result = new ProviderHelper(this).consolidateDatabaseStep2(this);
- } else {
- result = new ProviderHelper(this).consolidateDatabaseStep1(this);
+ break;
}
+ case ACTION_CONSOLIDATE: {
+
+ // Operation
+ ConsolidateResult result;
+ if (data.containsKey(CONSOLIDATE_RECOVERY) && data.getBoolean(CONSOLIDATE_RECOVERY)) {
+ result = new ProviderHelper(this).consolidateDatabaseStep2(this);
+ } else {
+ result = new ProviderHelper(this).consolidateDatabaseStep1(this);
+ }
- // Result
- sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, result);
+ // Result
+ sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, result);
- } else if (ACTION_DECRYPT_METADATA.equals(action)) {
+ break;
+ }
+ case ACTION_DECRYPT_METADATA:
- try {
+ try {
/* Input */
- String passphrase = data.getString(DECRYPT_PASSPHRASE);
- byte[] nfcDecryptedSessionKey = data.getByteArray(DECRYPT_NFC_DECRYPTED_SESSION_KEY);
+ String passphrase = data.getString(DECRYPT_PASSPHRASE);
+ byte[] nfcDecryptedSessionKey = data.getByteArray(DECRYPT_NFC_DECRYPTED_SESSION_KEY);
- InputData inputData = createDecryptInputData(data);
+ InputData inputData = createDecryptInputData(data);
/* Operation */
- Bundle resultData = new Bundle();
+ Bundle resultData = new Bundle();
- // verifyText and decrypt returning additional resultData values for the
- // verification of signatures
- PgpDecryptVerify.Builder builder = new PgpDecryptVerify.Builder(
- this, new ProviderHelper(this), this, inputData, null
- );
- builder.setAllowSymmetricDecryption(true)
- .setPassphrase(passphrase)
- .setDecryptMetadataOnly(true)
- .setNfcState(nfcDecryptedSessionKey);
+ // verifyText and decrypt returning additional resultData values for the
+ // verification of signatures
+ PgpDecryptVerify.Builder builder = new PgpDecryptVerify.Builder(
+ this, new ProviderHelper(this), this, inputData, null
+ );
+ builder.setAllowSymmetricDecryption(true)
+ .setPassphrase(passphrase)
+ .setDecryptMetadataOnly(true)
+ .setNfcState(nfcDecryptedSessionKey);
- DecryptVerifyResult decryptVerifyResult = builder.build().execute();
+ DecryptVerifyResult decryptVerifyResult = builder.build().execute();
- sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, decryptVerifyResult);
- } catch (Exception e) {
- sendErrorToHandler(e);
- }
+ sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, decryptVerifyResult);
+ } catch (Exception e) {
+ sendErrorToHandler(e);
+ }
- } else if (ACTION_DECRYPT_VERIFY.equals(action)) {
+ break;
+ case ACTION_DECRYPT_VERIFY:
- try {
+ try {
/* Input */
- String passphrase = data.getString(DECRYPT_PASSPHRASE);
- byte[] nfcDecryptedSessionKey = data.getByteArray(DECRYPT_NFC_DECRYPTED_SESSION_KEY);
+ String passphrase = data.getString(DECRYPT_PASSPHRASE);
+ byte[] nfcDecryptedSessionKey = data.getByteArray(DECRYPT_NFC_DECRYPTED_SESSION_KEY);
- InputData inputData = createDecryptInputData(data);
- OutputStream outStream = createCryptOutputStream(data);
+ InputData inputData = createDecryptInputData(data);
+ OutputStream outStream = createCryptOutputStream(data);
/* Operation */
- Bundle resultData = new Bundle();
+ Bundle resultData = new Bundle();
- // verifyText and decrypt returning additional resultData values for the
- // verification of signatures
- PgpDecryptVerify.Builder builder = new PgpDecryptVerify.Builder(
- this, new ProviderHelper(this), this,
- inputData, outStream
- );
- builder.setAllowSymmetricDecryption(true)
- .setPassphrase(passphrase)
- .setNfcState(nfcDecryptedSessionKey);
+ // verifyText and decrypt returning additional resultData values for the
+ // verification of signatures
+ PgpDecryptVerify.Builder builder = new PgpDecryptVerify.Builder(
+ this, new ProviderHelper(this), this,
+ inputData, outStream
+ );
+ builder.setAllowSymmetricDecryption(true)
+ .setPassphrase(passphrase)
+ .setNfcState(nfcDecryptedSessionKey);
- DecryptVerifyResult decryptVerifyResult = builder.build().execute();
+ DecryptVerifyResult decryptVerifyResult = builder.build().execute();
- outStream.close();
+ outStream.close();
- resultData.putParcelable(DecryptVerifyResult.EXTRA_RESULT, decryptVerifyResult);
+ resultData.putParcelable(DecryptVerifyResult.EXTRA_RESULT, decryptVerifyResult);
/* Output */
- finalizeDecryptOutputStream(data, resultData, outStream);
+ finalizeDecryptOutputStream(data, resultData, outStream);
- Log.logDebugBundle(resultData, "resultData");
+ Log.logDebugBundle(resultData, "resultData");
- sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, resultData);
- } catch (Exception e) {
- sendErrorToHandler(e);
- }
+ sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, resultData);
+ } catch (Exception e) {
+ sendErrorToHandler(e);
+ }
- } else if (ACTION_DELETE.equals(action)) {
+ break;
+ case ACTION_DELETE: {
+
+ // Input
+ long[] masterKeyIds = data.getLongArray(DELETE_KEY_LIST);
+ boolean isSecret = data.getBoolean(DELETE_IS_SECRET);
- // Input
- long[] masterKeyIds = data.getLongArray(DELETE_KEY_LIST);
- boolean isSecret = data.getBoolean(DELETE_IS_SECRET);
+ // Operation
+ DeleteOperation op = new DeleteOperation(this, new ProviderHelper(this), this);
+ DeleteResult result = op.execute(masterKeyIds, isSecret);
- // Operation
- DeleteOperation op = new DeleteOperation(this, new ProviderHelper(this), this);
- DeleteResult result = op.execute(masterKeyIds, isSecret);
+ // Result
+ sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, result);
- // Result
- sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, result);
+ break;
+ }
+ case ACTION_EDIT_KEYRING: {
- } else if (ACTION_EDIT_KEYRING.equals(action)) {
+ // Input
+ SaveKeyringParcel saveParcel = data.getParcelable(EDIT_KEYRING_PARCEL);
+ String passphrase = data.getString(EDIT_KEYRING_PASSPHRASE);
- // Input
- SaveKeyringParcel saveParcel = data.getParcelable(EDIT_KEYRING_PARCEL);
- String passphrase = data.getString(EDIT_KEYRING_PASSPHRASE);
+ // Operation
+ EditKeyOperation op = new EditKeyOperation(this, providerHelper, this, mActionCanceled);
+ EditKeyResult result = op.execute(saveParcel, passphrase);
- // Operation
- EditKeyOperation op = new EditKeyOperation(this, providerHelper, this, mActionCanceled);
- EditKeyResult result = op.execute(saveParcel, passphrase);
+ // Result
+ sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, result);
- // Result
- sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, result);
+ break;
+ }
+ case ACTION_PROMOTE_KEYRING: {
- } else if (ACTION_EXPORT_KEYRING.equals(action)) {
+ // Input
+ long keyRingId = data.getInt(EXPORT_KEY_RING_MASTER_KEY_ID);
- // Input
- boolean exportSecret = data.getBoolean(EXPORT_SECRET, false);
- String outputFile = data.getString(EXPORT_FILENAME);
- Uri outputUri = data.getParcelable(EXPORT_URI);
+ // Operation
+ PromoteKeyOperation op = new PromoteKeyOperation(this, providerHelper, this, mActionCanceled);
+ PromoteKeyResult result = op.execute(keyRingId);
- boolean exportAll = data.getBoolean(EXPORT_ALL);
- long[] masterKeyIds = exportAll ? null : data.getLongArray(EXPORT_KEY_RING_MASTER_KEY_ID);
+ // Result
+ sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, result);
- // Operation
- ImportExportOperation importExportOperation = new ImportExportOperation(this, new ProviderHelper(this), this);
- ExportResult result;
- if (outputFile != null) {
- result = importExportOperation.exportToFile(masterKeyIds, exportSecret, outputFile);
- } else {
- result = importExportOperation.exportToUri(masterKeyIds, exportSecret, outputUri);
+ break;
}
+ case ACTION_EXPORT_KEYRING: {
- // Result
- sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, result);
+ // Input
+ boolean exportSecret = data.getBoolean(EXPORT_SECRET, false);
+ String outputFile = data.getString(EXPORT_FILENAME);
+ Uri outputUri = data.getParcelable(EXPORT_URI);
- } else if (ACTION_IMPORT_KEYRING.equals(action)) {
+ boolean exportAll = data.getBoolean(EXPORT_ALL);
+ long[] masterKeyIds = exportAll ? null : data.getLongArray(EXPORT_KEY_RING_MASTER_KEY_ID);
- try {
+ // Operation
+ ImportExportOperation importExportOperation = new ImportExportOperation(this, new ProviderHelper(this), this);
+ ExportResult result;
+ if (outputFile != null) {
+ result = importExportOperation.exportToFile(masterKeyIds, exportSecret, outputFile);
+ } else {
+ result = importExportOperation.exportToUri(masterKeyIds, exportSecret, outputUri);
+ }
+
+ // Result
+ sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, result);
+
+ break;
+ }
+ case ACTION_IMPORT_KEYRING: {
// Input
String keyServer = data.getString(IMPORT_KEY_SERVER);
- Iterator<ParcelableKeyRing> entries;
- int numEntries;
- if (data.containsKey(IMPORT_KEY_LIST)) {
- // get entries from intent
- ArrayList<ParcelableKeyRing> list = data.getParcelableArrayList(IMPORT_KEY_LIST);
- entries = list.iterator();
- numEntries = list.size();
- } else {
- // get entries from cached file
- ParcelableFileCache<ParcelableKeyRing> cache =
- new ParcelableFileCache<ParcelableKeyRing>(this, "key_import.pcl");
- IteratorWithSize<ParcelableKeyRing> it = cache.readCache();
- entries = it;
- numEntries = it.getSize();
- }
+ ArrayList<ParcelableKeyRing> list = data.getParcelableArrayList(IMPORT_KEY_LIST);
+ ParcelableFileCache<ParcelableKeyRing> cache =
+ new ParcelableFileCache<>(this, "key_import.pcl");
// Operation
ImportExportOperation importExportOperation = new ImportExportOperation(
this, providerHelper, this, mActionCanceled);
- ImportKeyResult result = importExportOperation.importKeyRings(entries, numEntries, keyServer);
-
- // Special: consolidate on secret key import (cannot be cancelled!)
- if (result.mSecret > 0) {
- // TODO move this into the import operation
- providerHelper.consolidateDatabaseStep1(this);
- }
-
- // Special: make sure new data is synced into contacts
- ContactSyncAdapterService.requestSync();
+ // Either list or cache must be null, no guarantees otherwise.
+ ImportKeyResult result = list != null
+ ? importExportOperation.importKeyRings(list, keyServer)
+ : importExportOperation.importKeyRings(cache, keyServer);
// Result
sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, result);
- } catch (Exception e) {
- sendErrorToHandler(e);
- }
-
- } else if (ACTION_SIGN_ENCRYPT.equals(action)) {
-
- try {
- /* Input */
- int source = data.get(SOURCE) != null ? data.getInt(SOURCE) : data.getInt(TARGET);
- Bundle resultData = new Bundle();
- long sigMasterKeyId = data.getLong(ENCRYPT_SIGNATURE_MASTER_ID);
- String sigKeyPassphrase = data.getString(ENCRYPT_SIGNATURE_KEY_PASSPHRASE);
-
- byte[] nfcHash = data.getByteArray(ENCRYPT_SIGNATURE_NFC_HASH);
- Date nfcTimestamp = (Date) data.getSerializable(ENCRYPT_SIGNATURE_NFC_TIMESTAMP);
-
- String symmetricPassphrase = data.getString(ENCRYPT_SYMMETRIC_PASSPHRASE);
-
- boolean useAsciiArmor = data.getBoolean(ENCRYPT_USE_ASCII_ARMOR);
- long encryptionKeyIds[] = data.getLongArray(ENCRYPT_ENCRYPTION_KEYS_IDS);
- int compressionId = data.getInt(ENCRYPT_COMPRESSION_ID);
- int urisCount = data.containsKey(ENCRYPT_INPUT_URIS) ? data.getParcelableArrayList(ENCRYPT_INPUT_URIS).size() : 1;
- for (int i = 0; i < urisCount; i++) {
- data.putInt(SELECTED_URI, i);
- InputData inputData = createEncryptInputData(data);
- OutputStream outStream = createCryptOutputStream(data);
- String originalFilename = getOriginalFilename(data);
-
- /* Operation */
- PgpSignEncrypt.Builder builder = new PgpSignEncrypt.Builder(
- this, new ProviderHelper(this), this, inputData, outStream
- );
- builder.setEnableAsciiArmorOutput(useAsciiArmor)
- .setVersionHeader(PgpHelper.getVersionForHeader(this))
- .setCompressionId(compressionId)
- .setSymmetricEncryptionAlgorithm(
- Preferences.getPreferences(this).getDefaultEncryptionAlgorithm())
- .setEncryptionMasterKeyIds(encryptionKeyIds)
- .setSymmetricPassphrase(symmetricPassphrase)
- .setOriginalFilename(originalFilename);
+ break;
- try {
+ }
+ case ACTION_SIGN_ENCRYPT:
- // Find the appropriate subkey to sign with
- CachedPublicKeyRing signingRing =
- new ProviderHelper(this).getCachedPublicKeyRing(sigMasterKeyId);
- long sigSubKeyId = signingRing.getSecretSignId();
-
- // Set signature settings
- builder.setSignatureMasterKeyId(sigMasterKeyId)
- .setSignatureSubKeyId(sigSubKeyId)
- .setSignaturePassphrase(sigKeyPassphrase)
- .setSignatureHashAlgorithm(
- Preferences.getPreferences(this).getDefaultHashAlgorithm())
- .setAdditionalEncryptId(sigMasterKeyId);
- if (nfcHash != null && nfcTimestamp != null) {
- builder.setNfcState(nfcHash, nfcTimestamp);
+ try {
+ /* Input */
+ int source = data.get(SOURCE) != null ? data.getInt(SOURCE) : data.getInt(TARGET);
+ Bundle resultData = new Bundle();
+
+ long sigMasterKeyId = data.getLong(ENCRYPT_SIGNATURE_MASTER_ID);
+ String sigKeyPassphrase = data.getString(ENCRYPT_SIGNATURE_KEY_PASSPHRASE);
+
+ byte[] nfcHash = data.getByteArray(ENCRYPT_SIGNATURE_NFC_HASH);
+ Date nfcTimestamp = (Date) data.getSerializable(ENCRYPT_SIGNATURE_NFC_TIMESTAMP);
+
+ String symmetricPassphrase = data.getString(ENCRYPT_SYMMETRIC_PASSPHRASE);
+
+ boolean useAsciiArmor = data.getBoolean(ENCRYPT_USE_ASCII_ARMOR);
+ long encryptionKeyIds[] = data.getLongArray(ENCRYPT_ENCRYPTION_KEYS_IDS);
+ int compressionId = data.getInt(ENCRYPT_COMPRESSION_ID);
+ int urisCount = data.containsKey(ENCRYPT_INPUT_URIS) ? data.getParcelableArrayList(ENCRYPT_INPUT_URIS).size() : 1;
+ for (int i = 0; i < urisCount; i++) {
+ data.putInt(SELECTED_URI, i);
+ InputData inputData = createEncryptInputData(data);
+ OutputStream outStream = createCryptOutputStream(data);
+ String originalFilename = getOriginalFilename(data);
+
+ /* Operation */
+ PgpSignEncrypt.Builder builder = new PgpSignEncrypt.Builder(
+ this, new ProviderHelper(this), this, inputData, outStream
+ );
+ builder.setEnableAsciiArmorOutput(useAsciiArmor)
+ .setCleartextSignature(true)
+ .setVersionHeader(PgpHelper.getVersionForHeader(this))
+ .setCompressionId(compressionId)
+ .setSymmetricEncryptionAlgorithm(
+ Preferences.getPreferences(this).getDefaultEncryptionAlgorithm())
+ .setEncryptionMasterKeyIds(encryptionKeyIds)
+ .setSymmetricPassphrase(symmetricPassphrase)
+ .setOriginalFilename(originalFilename);
+
+ try {
+
+ // Find the appropriate subkey to sign with
+ CachedPublicKeyRing signingRing =
+ new ProviderHelper(this).getCachedPublicKeyRing(sigMasterKeyId);
+ long sigSubKeyId = signingRing.getSecretSignId();
+
+ // Set signature settings
+ builder.setSignatureMasterKeyId(sigMasterKeyId)
+ .setSignatureSubKeyId(sigSubKeyId)
+ .setSignaturePassphrase(sigKeyPassphrase)
+ .setSignatureHashAlgorithm(
+ Preferences.getPreferences(this).getDefaultHashAlgorithm())
+ .setAdditionalEncryptId(sigMasterKeyId);
+ if (nfcHash != null && nfcTimestamp != null) {
+ builder.setNfcState(nfcHash, nfcTimestamp);
+ }
+
+ } catch (PgpKeyNotFoundException e) {
+ // encrypt-only
+ // TODO Just silently drop the requested signature? Shouldn't we throw here?
}
- } catch (PgpKeyNotFoundException e) {
- // encrypt-only
- // TODO Just silently drop the requested signature? Shouldn't we throw here?
- }
-
- // this assumes that the bytes are cleartext (valid for current implementation!)
- if (source == IO_BYTES) {
- builder.setCleartextInput(true);
- }
-
- SignEncryptResult result = builder.build().execute();
- resultData.putParcelable(SignEncryptResult.EXTRA_RESULT, result);
+ SignEncryptResult result = builder.build().execute();
+ resultData.putParcelable(SignEncryptResult.EXTRA_RESULT, result);
- outStream.close();
+ outStream.close();
- /* Output */
+ /* Output */
+ finalizeEncryptOutputStream(data, resultData, outStream);
+ }
- finalizeEncryptOutputStream(data, resultData, outStream);
+ Log.logDebugBundle(resultData, "resultData");
+ sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, resultData);
+ } catch (Exception e) {
+ sendErrorToHandler(e);
}
- Log.logDebugBundle(resultData, "resultData");
-
- sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, resultData);
- } catch (Exception e) {
- sendErrorToHandler(e);
- }
-
- } else if (ACTION_UPLOAD_KEYRING.equals(action)) {
+ break;
+ case ACTION_UPLOAD_KEYRING:
- try {
+ try {
/* Input */
- String keyServer = data.getString(UPLOAD_KEY_SERVER);
- // and dataUri!
+ String keyServer = data.getString(UPLOAD_KEY_SERVER);
+ // and dataUri!
/* Operation */
- HkpKeyserver server = new HkpKeyserver(keyServer);
+ HkpKeyserver server = new HkpKeyserver(keyServer);
- CanonicalizedPublicKeyRing keyring = providerHelper.getCanonicalizedPublicKeyRing(dataUri);
- ImportExportOperation importExportOperation = new ImportExportOperation(this, new ProviderHelper(this), this);
+ CanonicalizedPublicKeyRing keyring = providerHelper.getCanonicalizedPublicKeyRing(dataUri);
+ ImportExportOperation importExportOperation = new ImportExportOperation(this, new ProviderHelper(this), this);
- try {
- importExportOperation.uploadKeyRingToServer(server, keyring);
- } catch (Keyserver.AddKeyException e) {
- throw new PgpGeneralException("Unable to export key to selected server");
- }
+ try {
+ importExportOperation.uploadKeyRingToServer(server, keyring);
+ } catch (Keyserver.AddKeyException e) {
+ throw new PgpGeneralException("Unable to export key to selected server");
+ }
- sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY);
- } catch (Exception e) {
- sendErrorToHandler(e);
- }
+ sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY);
+ } catch (Exception e) {
+ sendErrorToHandler(e);
+ }
+ break;
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java
index 869d2e71b..142814d99 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java
@@ -39,7 +39,6 @@ import android.support.v4.util.LongSparseArray;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
import org.sufficientlysecure.keychain.util.Preferences;
import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey.SecretKeyType;
import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing;
@@ -103,7 +102,7 @@ public class PassphraseCacheService extends Service {
private BroadcastReceiver mIntentReceiver;
- private LongSparseArray<CachedPassphrase> mPassphraseCache = new LongSparseArray<CachedPassphrase>();
+ private LongSparseArray<CachedPassphrase> mPassphraseCache = new LongSparseArray<>();
Context mContext;
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 a314c8768..f5df5858c 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java
@@ -58,7 +58,6 @@ public class SaveKeyringParcel implements Parcelable {
public ArrayList<String> mRevokeUserIds;
public ArrayList<Long> mRevokeSubKeys;
- public ArrayList<Long> mStripSubKeys;
public SaveKeyringParcel() {
reset();
@@ -72,14 +71,30 @@ public class SaveKeyringParcel implements Parcelable {
public void reset() {
mNewUnlock = null;
- mAddUserIds = new ArrayList<String>();
- mAddUserAttribute = new ArrayList<WrappedUserAttribute>();
- mAddSubKeys = new ArrayList<SubkeyAdd>();
+ mAddUserIds = new ArrayList<>();
+ mAddUserAttribute = new ArrayList<>();
+ mAddSubKeys = new ArrayList<>();
mChangePrimaryUserId = null;
- mChangeSubKeys = new ArrayList<SubkeyChange>();
- mRevokeUserIds = new ArrayList<String>();
- mRevokeSubKeys = new ArrayList<Long>();
- mStripSubKeys = new ArrayList<Long>();
+ mChangeSubKeys = new ArrayList<>();
+ mRevokeUserIds = new ArrayList<>();
+ mRevokeSubKeys = new ArrayList<>();
+ }
+
+ /** Returns true iff this parcel does not contain any operations which require a passphrase. */
+ public boolean isRestrictedOnly() {
+ if (mNewUnlock != null || !mAddUserIds.isEmpty() || !mAddUserAttribute.isEmpty()
+ || !mAddSubKeys.isEmpty() || mChangePrimaryUserId != null || !mRevokeSubKeys .isEmpty()
+ || !mRevokeSubKeys.isEmpty()) {
+ return false;
+ }
+
+ for (SubkeyChange change : mChangeSubKeys) {
+ if (change.mRecertify || change.mFlags != null || change.mExpiry != null) {
+ return false;
+ }
+ }
+
+ return true;
}
// performance gain for using Parcelable here would probably be negligible,
@@ -112,26 +127,53 @@ public class SaveKeyringParcel implements Parcelable {
}
public static class SubkeyChange implements Serializable {
- public long mKeyId;
+ public final long mKeyId;
public Integer mFlags;
// this is a long unix timestamp, in seconds (NOT MILLISECONDS!)
public Long mExpiry;
+ // if this flag is true, the key will be recertified even if all above
+ // values are no-ops
+ public boolean mRecertify;
+ // if this flag is true, the subkey should be changed to a stripped key
+ public boolean mDummyStrip;
+ // if this is non-null, the subkey will be changed to a divert-to-card
+ // key for the given serial number
+ public byte[] mDummyDivert;
public SubkeyChange(long keyId) {
mKeyId = keyId;
}
+ public SubkeyChange(long keyId, boolean recertify) {
+ mKeyId = keyId;
+ mRecertify = recertify;
+ }
+
public SubkeyChange(long keyId, Integer flags, Long expiry) {
mKeyId = keyId;
mFlags = flags;
mExpiry = expiry;
}
+ public SubkeyChange(long keyId, boolean dummyStrip, byte[] dummyDivert) {
+ this(keyId, null, null);
+
+ // these flags are mutually exclusive!
+ if (dummyStrip && dummyDivert != null) {
+ throw new AssertionError(
+ "cannot set strip and divert flags at the same time - this is a bug!");
+ }
+ mDummyStrip = dummyStrip;
+ mDummyDivert = dummyDivert;
+ }
+
@Override
public String toString() {
String out = "mKeyId: " + mKeyId + ", ";
out += "mFlags: " + mFlags + ", ";
- out += "mExpiry: " + mExpiry;
+ out += "mExpiry: " + mExpiry + ", ";
+ out += "mDummyStrip: " + mDummyStrip + ", ";
+ out += "mDummyDivert: [" + (mDummyDivert == null ? 0 : mDummyDivert.length) + " bytes]";
return out;
}
@@ -173,7 +215,6 @@ public class SaveKeyringParcel implements Parcelable {
mRevokeUserIds = source.createStringArrayList();
mRevokeSubKeys = (ArrayList<Long>) source.readSerializable();
- mStripSubKeys = (ArrayList<Long>) source.readSerializable();
}
@Override
@@ -196,7 +237,6 @@ public class SaveKeyringParcel implements Parcelable {
destination.writeStringList(mRevokeUserIds);
destination.writeSerializable(mRevokeSubKeys);
- destination.writeSerializable(mStripSubKeys);
}
public static final Creator<SaveKeyringParcel> CREATOR = new Creator<SaveKeyringParcel>() {
@@ -224,8 +264,7 @@ public class SaveKeyringParcel implements Parcelable {
out += "mChangeSubKeys: " + mChangeSubKeys + "\n";
out += "mChangePrimaryUserId: " + mChangePrimaryUserId + "\n";
out += "mRevokeUserIds: " + mRevokeUserIds + "\n";
- out += "mRevokeSubKeys: " + mRevokeSubKeys + "\n";
- out += "mStripSubKeys: " + mStripSubKeys;
+ out += "mRevokeSubKeys: " + mRevokeSubKeys;
return out;
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BaseActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BaseActivity.java
index c38d126d7..7423e6828 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BaseActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BaseActivity.java
@@ -17,14 +17,21 @@
package org.sufficientlysecure.keychain.ui;
+import android.app.Activity;
import android.os.Bundle;
+import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.widget.Toolbar;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
import org.sufficientlysecure.keychain.R;
/**
- * Sets action bar
+ * Setups Toolbar
*/
public abstract class BaseActivity extends ActionBarActivity {
protected Toolbar mToolbar;
@@ -49,4 +56,75 @@ public abstract class BaseActivity extends ActionBarActivity {
protected void setActionBarIcon(int iconRes) {
mToolbar.setNavigationIcon(iconRes);
}
+
+ /**
+ * Inflate custom design to look like a full screen dialog, as specified in Material Design Guidelines
+ * see http://www.google.com/design/spec/components/dialogs.html#dialogs-full-screen-dialogs
+ */
+ protected void setFullScreenDialogDoneClose(int doneText, View.OnClickListener doneOnClickListener,
+ View.OnClickListener cancelOnClickListener) {
+ setActionBarIcon(R.drawable.ic_close_white_24dp);
+
+ // Inflate the custom action bar view
+ final LayoutInflater inflater = (LayoutInflater) getSupportActionBar().getThemedContext()
+ .getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
+ final View customActionBarView = inflater.inflate(R.layout.full_screen_dialog, null);
+
+ TextView firstTextView = ((TextView) customActionBarView.findViewById(R.id.full_screen_dialog_done_text));
+ firstTextView.setText(doneText);
+ customActionBarView.findViewById(R.id.full_screen_dialog_done).setOnClickListener(
+ doneOnClickListener);
+
+ getSupportActionBar().setDisplayShowCustomEnabled(true);
+ getSupportActionBar().setDisplayShowTitleEnabled(true);
+ getSupportActionBar().setCustomView(customActionBarView, new ActionBar.LayoutParams(
+ ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT,
+ Gravity.END));
+ mToolbar.setNavigationOnClickListener(cancelOnClickListener);
+ }
+
+ /**
+ * Close button only
+ */
+ protected void setFullScreenDialogClose(View.OnClickListener cancelOnClickListener) {
+ setActionBarIcon(R.drawable.ic_close_white_24dp);
+ getSupportActionBar().setDisplayShowTitleEnabled(true);
+ mToolbar.setNavigationOnClickListener(cancelOnClickListener);
+ }
+
+ /**
+ * Inflate custom design with two buttons using drawables.
+ * This does not conform to the Material Design Guidelines, but we deviate here as this is used
+ * to indicate "Allow access"/"Disallow access" to the API, which must be clearly indicated
+ */
+ protected void setFullScreenDialogTwoButtons(int firstText, int firstDrawableId, View.OnClickListener firstOnClickListener,
+ int secondText, int secondDrawableId, View.OnClickListener secondOnClickListener) {
+
+ // Inflate the custom action bar view
+ final LayoutInflater inflater = (LayoutInflater) getSupportActionBar().getThemedContext()
+ .getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
+ final View customActionBarView = inflater.inflate(
+ R.layout.full_screen_dialog_2, null);
+
+ TextView firstTextView = ((TextView) customActionBarView.findViewById(R.id.actionbar_done_text));
+ firstTextView.setText(firstText);
+ firstTextView.setCompoundDrawablesWithIntrinsicBounds(firstDrawableId, 0, 0, 0);
+ customActionBarView.findViewById(R.id.actionbar_done).setOnClickListener(
+ firstOnClickListener);
+ TextView secondTextView = ((TextView) customActionBarView.findViewById(R.id.actionbar_cancel_text));
+ secondTextView.setText(secondText);
+ secondTextView.setCompoundDrawablesWithIntrinsicBounds(secondDrawableId, 0, 0, 0);
+ customActionBarView.findViewById(R.id.actionbar_cancel).setOnClickListener(
+ secondOnClickListener);
+
+ // Show the custom action bar view and hide the normal Home icon and title.
+ getSupportActionBar().setDisplayShowTitleEnabled(false);
+ getSupportActionBar().setDisplayShowHomeEnabled(false);
+ getSupportActionBar().setDisplayHomeAsUpEnabled(false);
+ getSupportActionBar().setDisplayShowCustomEnabled(true);
+ getSupportActionBar().setCustomView(customActionBarView, new ActionBar.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
+ }
+
+
}
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 6850eca13..1fb88b182 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java
@@ -18,9 +18,6 @@
package org.sufficientlysecure.keychain.ui;
-import android.os.Bundle;
-import android.support.v7.app.ActionBarActivity;
-
import org.sufficientlysecure.keychain.R;
/**
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 841485c7c..50d5e3229 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyFragment.java
@@ -234,7 +234,7 @@ public class CertifyKeyFragment extends LoaderFragment
long lastMasterKeyId = 0;
String lastName = "";
- ArrayList<String> uids = new ArrayList<String>();
+ ArrayList<String> uids = new ArrayList<>();
boolean header = true;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyActivity.java
index 82d3279f4..62c38d136 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyActivity.java
@@ -20,7 +20,6 @@ package org.sufficientlysecure.keychain.ui;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
-import android.support.v7.app.ActionBarActivity;
import org.sufficientlysecure.keychain.R;
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 2804a5ce6..377a9d1f4 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java
@@ -44,7 +44,6 @@ import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
import org.sufficientlysecure.keychain.operations.results.OperationResult;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Algorithm;
-import org.sufficientlysecure.keychain.operations.results.SaveKeyringResult;
import org.sufficientlysecure.keychain.util.Log;
public class CreateKeyFinalFragment extends Fragment {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyInputFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyInputFragment.java
index 6079062a7..8aa9fa6db 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyInputFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyInputFragment.java
@@ -89,7 +89,7 @@ public class CreateKeyInputFragment extends Fragment {
mEmailEdit.setThreshold(1); // Start working from first character
mEmailEdit.setAdapter(
- new ArrayAdapter<String>
+ new ArrayAdapter<>
(getActivity(), android.R.layout.simple_spinner_dropdown_item,
ContactHelper.getPossibleUserEmails(getActivity())
)
@@ -124,7 +124,7 @@ public class CreateKeyInputFragment extends Fragment {
mNameEdit.setThreshold(1); // Start working from first character
mNameEdit.setAdapter(
- new ArrayAdapter<String>
+ new ArrayAdapter<>
(getActivity(), android.R.layout.simple_spinner_dropdown_item,
ContactHelper.getPossibleUserNames(getActivity())
)
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptActivity.java
index a84461a92..21377bcd2 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptActivity.java
@@ -34,13 +34,13 @@ import org.sufficientlysecure.keychain.ui.util.SubtleAttentionSeeker;
import java.util.regex.Matcher;
-public class DecryptActivity extends DrawerActivity {
+public class DecryptActivity extends BaseActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- activateDrawerNavigation(savedInstanceState);
+// activateDrawerNavigation(savedInstanceState);
View actionFile = findViewById(R.id.decrypt_files);
View actionFromClipboard = findViewById(R.id.decrypt_from_clipboard);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesActivity.java
index 59159929c..7e91889b3 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesActivity.java
@@ -20,7 +20,6 @@ package org.sufficientlysecure.keychain.ui;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
-import android.support.v7.app.ActionBarActivity;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextActivity.java
index 285078dbf..2afc4b7b3 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextActivity.java
@@ -20,7 +20,6 @@ package org.sufficientlysecure.keychain.ui;
import android.content.Intent;
import android.os.Bundle;
-import android.support.v7.app.ActionBarActivity;
import android.text.TextUtils;
import org.sufficientlysecure.keychain.Constants;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextFragment.java
index fa7abf0f5..78333a8d8 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextFragment.java
@@ -41,6 +41,8 @@ import org.sufficientlysecure.keychain.ui.util.Notify;
import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.ShareHelper;
+import java.io.UnsupportedEncodingException;
+
public class DecryptTextFragment extends DecryptFragment {
public static final String ARG_CIPHERTEXT = "ciphertext";
@@ -111,7 +113,7 @@ public class DecryptTextFragment extends DecryptFragment {
Intent prototype = createSendIntent(text);
String title = getString(R.string.title_share_file);
- // we don't want to decrypt the decypted, no inception ;)
+ // we don't want to decrypt the decrypted, no inception ;)
String[] blacklist = new String[]{
Constants.PACKAGE_NAME + ".ui.DecryptTextActivity",
"org.thialfihar.android.apg.ui.DecryptActivity"
@@ -194,7 +196,18 @@ public class DecryptTextFragment extends DecryptFragment {
byte[] decryptedMessage = returnData
.getByteArray(KeychainIntentService.RESULT_DECRYPTED_BYTES);
- mText.setText(new String(decryptedMessage));
+ String displayMessage;
+ if (pgpResult.getCharset() != null) {
+ try {
+ displayMessage = new String(decryptedMessage, pgpResult.getCharset());
+ } catch (UnsupportedEncodingException e) {
+ // if we can't decode properly, just fall back to utf-8
+ displayMessage = new String(decryptedMessage);
+ }
+ } else {
+ displayMessage = new String(decryptedMessage);
+ }
+ mText.setText(displayMessage);
pgpResult.createNotify(getActivity()).show();
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java
index 492c81758..6dc2994cf 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java
@@ -19,7 +19,6 @@ package org.sufficientlysecure.keychain.ui;
import android.net.Uri;
import android.os.Bundle;
-import android.support.v7.app.ActionBarActivity;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
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 afe6afb3c..25ca6e8fd 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java
@@ -29,7 +29,6 @@ import android.os.Messenger;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
-import android.support.v7.app.ActionBarActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
@@ -55,6 +54,7 @@ import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
import org.sufficientlysecure.keychain.service.PassphraseCacheService;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.ChangeUnlockParcel;
+import org.sufficientlysecure.keychain.service.SaveKeyringParcel.SubkeyChange;
import org.sufficientlysecure.keychain.ui.adapter.SubkeysAdapter;
import org.sufficientlysecure.keychain.ui.adapter.SubkeysAddedAdapter;
import org.sufficientlysecure.keychain.ui.adapter.UserIdsAdapter;
@@ -65,7 +65,6 @@ import org.sufficientlysecure.keychain.ui.dialog.EditSubkeyDialogFragment;
import org.sufficientlysecure.keychain.ui.dialog.EditSubkeyExpiryDialogFragment;
import org.sufficientlysecure.keychain.ui.dialog.EditUserIdDialogFragment;
import org.sufficientlysecure.keychain.ui.dialog.SetPassphraseDialogFragment;
-import org.sufficientlysecure.keychain.ui.util.ActionBarHelper;
import org.sufficientlysecure.keychain.ui.util.Notify;
import org.sufficientlysecure.keychain.util.Log;
@@ -147,10 +146,8 @@ public class EditKeyFragment extends LoaderFragment implements
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
-
- // Inflate a "Done"/"Cancel" custom action bar view
- ActionBarHelper.setTwoButtonView(((ActionBarActivity) getActivity()).getSupportActionBar(),
- R.string.btn_save, R.drawable.ic_action_save,
+ ((EditKeyActivity) getActivity()).setFullScreenDialogDoneClose(
+ R.string.btn_save,
new OnClickListener() {
@Override
public void onClick(View v) {
@@ -161,16 +158,13 @@ public class EditKeyFragment extends LoaderFragment implements
saveInDatabase(mCurrentPassphrase);
}
}
- }, R.string.menu_key_edit_cancel, R.drawable.ic_action_cancel,
- new OnClickListener() {
+ }, new OnClickListener() {
@Override
public void onClick(View v) {
- // cancel
getActivity().setResult(Activity.RESULT_CANCELED);
getActivity().finish();
}
- }
- );
+ });
Uri dataUri = getArguments().getParcelable(ARG_DATA_URI);
SaveKeyringParcel saveKeyringParcel = getArguments().getParcelable(ARG_SAVE_KEYRING_PARCEL);
@@ -230,10 +224,7 @@ public class EditKeyFragment extends LoaderFragment implements
mSaveKeyringParcel = new SaveKeyringParcel(masterKeyId, keyRing.getFingerprint());
mPrimaryUserId = keyRing.getPrimaryUserIdWithFallback();
- } catch (PgpKeyNotFoundException e) {
- finishWithError(LogType.MSG_EK_ERROR_NOT_FOUND);
- return;
- } catch (NotFoundException e) {
+ } catch (PgpKeyNotFoundException | NotFoundException e) {
finishWithError(LogType.MSG_EK_ERROR_NOT_FOUND);
return;
}
@@ -395,8 +386,8 @@ public class EditKeyFragment extends LoaderFragment implements
// cache new returned passphrase!
mSaveKeyringParcel.mNewUnlock = new ChangeUnlockParcel(
- data.getString(SetPassphraseDialogFragment.MESSAGE_NEW_PASSPHRASE),
- null
+ data.getString(SetPassphraseDialogFragment.MESSAGE_NEW_PASSPHRASE),
+ null
);
}
}
@@ -478,12 +469,13 @@ public class EditKeyFragment extends LoaderFragment implements
}
break;
case EditSubkeyDialogFragment.MESSAGE_STRIP:
- // toggle
- if (mSaveKeyringParcel.mStripSubKeys.contains(keyId)) {
- mSaveKeyringParcel.mStripSubKeys.remove(keyId);
- } else {
- mSaveKeyringParcel.mStripSubKeys.add(keyId);
+ SubkeyChange change = mSaveKeyringParcel.getSubkeyChange(keyId);
+ if (change == null) {
+ mSaveKeyringParcel.mChangeSubKeys.add(new SubkeyChange(keyId, true, null));
+ break;
}
+ // toggle
+ change.mDummyStrip = !change.mDummyStrip;
break;
}
getLoaderManager().getLoader(LOADER_ID_SUBKEYS).forceLoad();
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java
index b9058a37d..611078f95 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java
@@ -14,7 +14,7 @@ import org.sufficientlysecure.keychain.operations.results.SignEncryptResult;
import java.util.Date;
-public abstract class EncryptActivity extends DrawerActivity {
+public abstract class EncryptActivity extends BaseActivity {
public static final int REQUEST_CODE_PASSPHRASE = 0x00008001;
public static final int REQUEST_CODE_NFC = 0x00008002;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java
index 2d1b66daa..c5404094a 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java
@@ -28,7 +28,6 @@ import com.tokenautocomplete.TokenCompleteTextView;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
@@ -164,8 +163,8 @@ public class EncryptAsymmetricFragment extends Fragment implements EncryptActivi
private void updateEncryptionKeys() {
List<Object> objects = mEncryptKeyView.getObjects();
- List<Long> keyIds = new ArrayList<Long>();
- List<String> userIds = new ArrayList<String>();
+ List<Long> keyIds = new ArrayList<>();
+ List<String> userIds = new ArrayList<>();
for (Object object : objects) {
if (object instanceof EncryptKeyCompletionView.EncryptionKey) {
keyIds.add(((EncryptKeyCompletionView.EncryptionKey) object).getKeyId());
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java
index 1494d05e1..63708ae8e 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java
@@ -122,13 +122,13 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi
@Override
public ArrayList<Uri> getInputUris() {
- if (mInputUris == null) mInputUris = new ArrayList<Uri>();
+ if (mInputUris == null) mInputUris = new ArrayList<>();
return mInputUris;
}
@Override
public ArrayList<Uri> getOutputUris() {
- if (mOutputUris == null) mOutputUris = new ArrayList<Uri>();
+ if (mOutputUris == null) mOutputUris = new ArrayList<>();
return mOutputUris;
}
@@ -252,7 +252,7 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi
sendIntent.setType("application/octet-stream");
if (!isModeSymmetric() && mEncryptionUserIds != null) {
- Set<String> users = new HashSet<String>();
+ Set<String> users = new HashSet<>();
for (String user : mEncryptionUserIds) {
String[] userId = KeyRing.splitUserId(user);
if (userId[1] != null) {
@@ -312,10 +312,10 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi
// if called with an intent action, do not init drawer navigation
if (ACTION_ENCRYPT_DATA.equals(getIntent().getAction())) {
// lock drawer
- deactivateDrawerNavigation();
+// deactivateDrawerNavigation();
// TODO: back button to key?
} else {
- activateDrawerNavigation(savedInstanceState);
+// activateDrawerNavigation(savedInstanceState);
}
// Handle intent actions
@@ -382,7 +382,7 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi
String action = intent.getAction();
Bundle extras = intent.getExtras();
String type = intent.getType();
- ArrayList<Uri> uris = new ArrayList<Uri>();
+ ArrayList<Uri> uris = new ArrayList<>();
if (extras == null) {
extras = new Bundle();
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java
index 6961f5ee7..be305cc58 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java
@@ -59,7 +59,7 @@ public class EncryptFilesFragment extends Fragment implements EncryptActivityInt
private View mShareFile;
private ListView mSelectedFiles;
private SelectedFilesAdapter mAdapter = new SelectedFilesAdapter();
- private final Map<Uri, Bitmap> thumbnailCache = new HashMap<Uri, Bitmap>();
+ private final Map<Uri, Bitmap> thumbnailCache = new HashMap<>();
@Override
public void onAttach(Activity activity) {
@@ -224,7 +224,7 @@ public class EncryptFilesFragment extends Fragment implements EncryptActivityInt
@Override
public void onNotifyUpdate() {
// Clear cache if needed
- for (Uri uri : new HashSet<Uri>(thumbnailCache.keySet())) {
+ for (Uri uri : new HashSet<>(thumbnailCache.keySet())) {
if (!mEncryptInterface.getInputUris().contains(uri)) {
thumbnailCache.remove(uri);
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java
index 757d1fb02..b4c12996e 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java
@@ -121,13 +121,13 @@ public class EncryptTextActivity extends EncryptActivity implements EncryptActiv
@Override
public ArrayList<Uri> getInputUris() {
- if (mInputUris == null) mInputUris = new ArrayList<Uri>();
+ if (mInputUris == null) mInputUris = new ArrayList<>();
return mInputUris;
}
@Override
public ArrayList<Uri> getOutputUris() {
- if (mOutputUris == null) mOutputUris = new ArrayList<Uri>();
+ if (mOutputUris == null) mOutputUris = new ArrayList<>();
return mOutputUris;
}
@@ -240,13 +240,14 @@ public class EncryptTextActivity extends EncryptActivity implements EncryptActiv
sendIntent.putExtra(Intent.EXTRA_TEXT, new String(message.getData().getByteArray(KeychainIntentService.RESULT_BYTES)));
if (!isModeSymmetric() && mEncryptionUserIds != null) {
- Set<String> users = new HashSet<String>();
+ Set<String> users = new HashSet<>();
for (String user : mEncryptionUserIds) {
String[] userId = KeyRing.splitUserId(user);
if (userId[1] != null) {
users.add(userId[1]);
}
}
+ // pass trough email addresses as extra for email applications
sendIntent.putExtra(Intent.EXTRA_EMAIL, users.toArray(new String[users.size()]));
}
return sendIntent;
@@ -291,10 +292,10 @@ public class EncryptTextActivity extends EncryptActivity implements EncryptActiv
// if called with an intent action, do not init drawer navigation
if (ACTION_ENCRYPT_TEXT.equals(getIntent().getAction())) {
// lock drawer
- deactivateDrawerNavigation();
+// deactivateDrawerNavigation();
// TODO: back button to key?
} else {
- activateDrawerNavigation(savedInstanceState);
+// activateDrawerNavigation(savedInstanceState);
}
// Handle intent actions
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/FirstTimeActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/FirstTimeActivity.java
index e487c8947..ce2a049f5 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/FirstTimeActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/FirstTimeActivity.java
@@ -19,7 +19,6 @@ package org.sufficientlysecure.keychain.ui;
import android.content.Intent;
import android.os.Bundle;
-import android.support.v7.app.ActionBarActivity;
import android.view.KeyEvent;
import android.view.View;
import android.view.Window;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java
index f1677cb67..6638c9944 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java
@@ -29,7 +29,6 @@ import android.os.Message;
import android.os.Messenger;
import android.os.Parcelable;
import android.support.v4.app.Fragment;
-import android.support.v7.app.ActionBarActivity;
import android.view.View;
import android.view.View.OnClickListener;
@@ -116,105 +115,123 @@ public class ImportKeysActivity extends BaseActivity {
extras = new Bundle();
}
+ if (action == null) {
+ startCloudFragment(savedInstanceState, null, false);
+ startListFragment(savedInstanceState, null, null, null);
+ return;
+ }
+
if (Intent.ACTION_VIEW.equals(action)) {
// Android's Action when opening file associated to Keychain (see AndroidManifest.xml)
// delegate action to ACTION_IMPORT_KEY
action = ACTION_IMPORT_KEY;
}
- if (ACTION_IMPORT_KEY.equals(action)) {
- /* Keychain's own Actions */
- startFileFragment(savedInstanceState);
+ switch (action) {
+ case ACTION_IMPORT_KEY: {
+ /* Keychain's own Actions */
+ startFileFragment(savedInstanceState);
- if (dataUri != null) {
- // action: directly load data
- startListFragment(savedInstanceState, null, dataUri, null);
- } else if (extras.containsKey(EXTRA_KEY_BYTES)) {
- byte[] importData = extras.getByteArray(EXTRA_KEY_BYTES);
+ if (dataUri != null) {
+ // action: directly load data
+ startListFragment(savedInstanceState, null, dataUri, null);
+ } else if (extras.containsKey(EXTRA_KEY_BYTES)) {
+ byte[] importData = extras.getByteArray(EXTRA_KEY_BYTES);
- // action: directly load data
- startListFragment(savedInstanceState, importData, null, null);
+ // action: directly load data
+ startListFragment(savedInstanceState, importData, null, null);
+ }
+ break;
}
- } else if (ACTION_IMPORT_KEY_FROM_KEYSERVER.equals(action)
- || ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN_TO_SERVICE.equals(action)
- || ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN_RESULT.equals(action)) {
+ case ACTION_IMPORT_KEY_FROM_KEYSERVER:
+ case ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN_TO_SERVICE:
+ case ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN_RESULT: {
- // only used for OpenPgpService
- if (extras.containsKey(EXTRA_PENDING_INTENT_DATA)) {
- mPendingIntentData = extras.getParcelable(EXTRA_PENDING_INTENT_DATA);
- }
- if (extras.containsKey(EXTRA_QUERY) || extras.containsKey(EXTRA_KEY_ID)) {
- /* simple search based on query or key id */
-
- String query = null;
- if (extras.containsKey(EXTRA_QUERY)) {
- query = extras.getString(EXTRA_QUERY);
- } else if (extras.containsKey(EXTRA_KEY_ID)) {
- long keyId = extras.getLong(EXTRA_KEY_ID, 0);
- if (keyId != 0) {
- query = KeyFormattingUtils.convertKeyIdToHex(keyId);
- }
+ // only used for OpenPgpService
+ if (extras.containsKey(EXTRA_PENDING_INTENT_DATA)) {
+ mPendingIntentData = extras.getParcelable(EXTRA_PENDING_INTENT_DATA);
}
+ if (extras.containsKey(EXTRA_QUERY) || extras.containsKey(EXTRA_KEY_ID)) {
+ /* simple search based on query or key id */
+
+ String query = null;
+ if (extras.containsKey(EXTRA_QUERY)) {
+ query = extras.getString(EXTRA_QUERY);
+ } else if (extras.containsKey(EXTRA_KEY_ID)) {
+ long keyId = extras.getLong(EXTRA_KEY_ID, 0);
+ if (keyId != 0) {
+ query = KeyFormattingUtils.convertKeyIdToHex(keyId);
+ }
+ }
- if (query != null && query.length() > 0) {
- // display keyserver fragment with query
- startCloudFragment(savedInstanceState, query, false);
+ if (query != null && query.length() > 0) {
+ // display keyserver fragment with query
+ startCloudFragment(savedInstanceState, query, false);
- // action: search immediately
- startListFragment(savedInstanceState, null, null, query);
- } else {
- Log.e(Constants.TAG, "Query is empty!");
- return;
- }
- } else if (extras.containsKey(EXTRA_FINGERPRINT)) {
- /*
- * search based on fingerprint, here we can enforce a check in the end
- * if the right key has been downloaded
- */
+ // action: search immediately
+ startListFragment(savedInstanceState, null, null, query);
+ } else {
+ Log.e(Constants.TAG, "Query is empty!");
+ return;
+ }
+ } else if (extras.containsKey(EXTRA_FINGERPRINT)) {
+ /*
+ * search based on fingerprint, here we can enforce a check in the end
+ * if the right key has been downloaded
+ */
- String fingerprint = extras.getString(EXTRA_FINGERPRINT);
- if (isFingerprintValid(fingerprint)) {
- String query = "0x" + fingerprint;
+ String fingerprint = extras.getString(EXTRA_FINGERPRINT);
+ if (isFingerprintValid(fingerprint)) {
+ String query = "0x" + fingerprint;
- // display keyserver fragment with query
- startCloudFragment(savedInstanceState, query, true);
+ // display keyserver fragment with query
+ startCloudFragment(savedInstanceState, query, true);
- // action: search immediately
- startListFragment(savedInstanceState, null, null, query);
+ // action: search immediately
+ startListFragment(savedInstanceState, null, null, query);
+ }
+ } else {
+ Log.e(Constants.TAG,
+ "IMPORT_KEY_FROM_KEYSERVER action needs to contain the 'query', 'key_id', or " +
+ "'fingerprint' extra!"
+ );
+ return;
}
- } else {
- Log.e(Constants.TAG,
- "IMPORT_KEY_FROM_KEYSERVER action needs to contain the 'query', 'key_id', or " +
- "'fingerprint' extra!"
- );
- return;
+ break;
}
- } else if (ACTION_IMPORT_KEY_FROM_FILE.equals(action)) {
- // NOTE: this only displays the appropriate fragment, no actions are taken
- startFileFragment(savedInstanceState);
-
- // no immediate actions!
- startListFragment(savedInstanceState, null, null, null);
- } else if (ACTION_IMPORT_KEY_FROM_FILE_AND_RETURN.equals(action)) {
- // NOTE: this only displays the appropriate fragment, no actions are taken
- startFileFragment(savedInstanceState);
+ case ACTION_IMPORT_KEY_FROM_FILE: {
+ // NOTE: this only displays the appropriate fragment, no actions are taken
+ startFileFragment(savedInstanceState);
- // no immediate actions!
- startListFragment(savedInstanceState, null, null, null);
- } else if (ACTION_IMPORT_KEY_FROM_NFC.equals(action)) {
- // NOTE: this only displays the appropriate fragment, no actions are taken
- startFileFragment(savedInstanceState);
- // TODO!!!!!
+ // no immediate actions!
+ startListFragment(savedInstanceState, null, null, null);
+ break;
+ }
+ case ACTION_IMPORT_KEY_FROM_FILE_AND_RETURN: {
+ // NOTE: this only displays the appropriate fragment, no actions are taken
+ startFileFragment(savedInstanceState);
- // no immediate actions!
- startListFragment(savedInstanceState, null, null, null);
- } else {
- startCloudFragment(savedInstanceState, null, false);
- startListFragment(savedInstanceState, null, null, null);
+ // no immediate actions!
+ startListFragment(savedInstanceState, null, null, null);
+ break;
+ }
+ case ACTION_IMPORT_KEY_FROM_NFC: {
+ // NOTE: this only displays the appropriate fragment, no actions are taken
+ startFileFragment(savedInstanceState);
+ // TODO!!!!!
+
+ // no immediate actions!
+ startListFragment(savedInstanceState, null, null, null);
+ break;
+ }
+ default: {
+ startCloudFragment(savedInstanceState, null, false);
+ startListFragment(savedInstanceState, null, null, null);
+ break;
+ }
}
}
-
private void startListFragment(Bundle savedInstanceState, byte[] bytes, Uri dataUri, String serverQuery) {
// However, if we're being restored from a previous state,
// then we don't need to do anything and should return or else
@@ -356,7 +373,7 @@ public class ImportKeysActivity extends BaseActivity {
// We parcel this iteratively into a file - anything we can
// display here, we should be able to import.
ParcelableFileCache<ParcelableKeyRing> cache =
- new ParcelableFileCache<ParcelableKeyRing>(this, "key_import.pcl");
+ new ParcelableFileCache<>(this, "key_import.pcl");
cache.writeCache(selectedEntries);
intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
@@ -388,7 +405,7 @@ public class ImportKeysActivity extends BaseActivity {
data.putString(KeychainIntentService.IMPORT_KEY_SERVER, sls.mCloudPrefs.keyserver);
// get selected key entries
- ArrayList<ParcelableKeyRing> keys = new ArrayList<ParcelableKeyRing>();
+ ArrayList<ParcelableKeyRing> keys = new ArrayList<>();
{
// change the format into ParcelableKeyRing
ArrayList<ImportKeysListEntry> entries = mListFragment.getSelectedEntries();
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysCloudFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysCloudFragment.java
index 89826b8e9..1d12f49f9 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysCloudFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysCloudFragment.java
@@ -81,7 +81,7 @@ public class ImportKeysCloudFragment extends Fragment {
namesAndEmails.addAll(ContactHelper.getContactMails(getActivity()));
mQueryEditText.setThreshold(3);
mQueryEditText.setAdapter(
- new ArrayAdapter<String>
+ new ArrayAdapter<>
(getActivity(), android.R.layout.simple_spinner_dropdown_item,
namesAndEmails
)
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java
index 4fe53fb09..6a6140892 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java
@@ -113,7 +113,7 @@ public class ImportKeysListFragment extends ListFragment implements
return mAdapter.getSelectedEntries();
} else {
Log.e(Constants.TAG, "Adapter not initialized, returning empty list");
- return new ArrayList<ImportKeysListEntry>();
+ return new ArrayList<>();
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListActivity.java
index 1d9a9cf64..b7f3588eb 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListActivity.java
@@ -41,15 +41,19 @@ import org.sufficientlysecure.keychain.util.Preferences;
import java.io.IOException;
-public class KeyListActivity extends DrawerActivity {
+import it.neokree.materialnavigationdrawer.MaterialNavigationDrawer;
+
+public class KeyListActivity extends NavDrawerActivity {
public static final int REQUEST_CODE_RESULT_TO_LIST = 1;
ExportHelper mExportHelper;
@Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
+// public void onCreate(Bundle savedInstanceState) {
+ public void init(Bundle savedInstanceState) {
+ super.init(savedInstanceState);
+// super.onCreate(savedInstanceState);
// setActionBarIcon(R.drawable.ic_ab_drawer);
setTitle(R.string.nav_keys);
@@ -72,13 +76,13 @@ public class KeyListActivity extends DrawerActivity {
}
// now setup navigation drawer in DrawerActivity...
- activateDrawerNavigation(savedInstanceState);
+// activateDrawerNavigation(savedInstanceState);
}
- @Override
- protected void initLayout() {
- setContentView(R.layout.key_list_activity);
- }
+// @Override
+// protected void initLayout() {
+// setContentView(R.layout.key_list_activity);
+// }
@Override
public boolean onCreateOptionsMenu(Menu menu) {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java
index 7fa403485..4e5e8c631 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java
@@ -31,7 +31,6 @@ import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.Messenger;
-import android.support.v4.app.FragmentActivity;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
@@ -52,7 +51,6 @@ import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AbsListView.MultiChoiceModeListener;
import android.widget.AdapterView;
-import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.ListView;
@@ -60,16 +58,14 @@ import android.widget.TextView;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing;
+import org.sufficientlysecure.keychain.operations.results.ConsolidateResult;
import org.sufficientlysecure.keychain.operations.results.DeleteResult;
+import org.sufficientlysecure.keychain.operations.results.OperationResult;
import org.sufficientlysecure.keychain.provider.KeychainContract;
-import org.sufficientlysecure.keychain.provider.ProviderHelper;
+import org.sufficientlysecure.keychain.provider.KeychainDatabase;
import org.sufficientlysecure.keychain.service.KeychainIntentService;
-import org.sufficientlysecure.keychain.operations.results.ImportKeyResult;
-import org.sufficientlysecure.keychain.operations.results.OperationResult;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.util.ExportHelper;
-import org.sufficientlysecure.keychain.util.KeyUpdateHelper;
import org.sufficientlysecure.keychain.pgp.KeyRing;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
@@ -78,15 +74,12 @@ import org.sufficientlysecure.keychain.ui.widget.ListAwareSwipeRefreshLayout;
import org.sufficientlysecure.keychain.ui.util.Highlighter;
import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.ui.util.Notify;
-import org.sufficientlysecure.keychain.util.ParcelableFileCache;
+import org.sufficientlysecure.keychain.util.Preferences;
import java.io.IOException;
-import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
-import edu.cmu.cylab.starslinger.exchange.ExchangeActivity;
-import edu.cmu.cylab.starslinger.exchange.ExchangeConfig;
import se.emilsjolander.stickylistheaders.StickyListHeadersAdapter;
import se.emilsjolander.stickylistheaders.StickyListHeadersListView;
@@ -98,6 +91,8 @@ public class KeyListFragment extends LoaderFragment
implements SearchView.OnQueryTextListener, AdapterView.OnItemClickListener,
LoaderManager.LoaderCallbacks<Cursor> {
+ ExportHelper mExportHelper;
+
private KeyListAdapter mAdapter;
private StickyListHeadersListView mStickyList;
private ListAwareSwipeRefreshLayout mSwipeRefreshLayout;
@@ -110,6 +105,14 @@ public class KeyListFragment extends LoaderFragment
private String mQuery;
private SearchView mSearchView;
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ mExportHelper = new ExportHelper(getActivity());
+
+ }
+
/**
* Load custom layout with StickyListView from library
*/
@@ -453,6 +456,15 @@ public class KeyListFragment extends LoaderFragment
@Override
public void onCreateOptionsMenu(final Menu menu, final MenuInflater inflater) {
+ inflater.inflate(R.menu.key_list, menu);
+
+ if (Constants.DEBUG) {
+ menu.findItem(R.id.menu_key_list_debug_cons).setVisible(true);
+ menu.findItem(R.id.menu_key_list_debug_read).setVisible(true);
+ menu.findItem(R.id.menu_key_list_debug_write).setVisible(true);
+ menu.findItem(R.id.menu_key_list_debug_first_time).setVisible(true);
+ }
+
// Get the searchview
MenuItem searchItem = menu.findItem(R.id.menu_key_list_search);
@@ -489,6 +501,71 @@ public class KeyListFragment extends LoaderFragment
}
@Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case R.id.menu_key_list_add:
+ Intent scanQrCode = new Intent(getActivity(), QrCodeScanActivity.class);
+ scanQrCode.setAction(QrCodeScanActivity.ACTION_SCAN_WITH_RESULT);
+ startActivityForResult(scanQrCode, 0);
+ return true;
+
+ case R.id.menu_key_list_search_cloud:
+ searchCloud();
+ return true;
+
+ case R.id.menu_key_list_create:
+ createKey();
+ return true;
+
+ case R.id.menu_key_list_import_existing_key:
+ Intent intentImportExisting = new Intent(getActivity(), ImportKeysActivity.class);
+ intentImportExisting.setAction(ImportKeysActivity.ACTION_IMPORT_KEY_FROM_FILE_AND_RETURN);
+ startActivityForResult(intentImportExisting, 0);
+ return true;
+
+ case R.id.menu_key_list_export:
+ mExportHelper.showExportKeysDialog(null, Constants.Path.APP_DIR_FILE, true);
+ return true;
+
+ case R.id.menu_key_list_debug_cons:
+ consolidate();
+ return true;
+
+ case R.id.menu_key_list_debug_read:
+ try {
+ KeychainDatabase.debugBackup(getActivity(), true);
+ Notify.showNotify(getActivity(), "Restored debug_backup.db", Notify.Style.INFO);
+ getActivity().getContentResolver().notifyChange(KeychainContract.KeyRings.CONTENT_URI, null);
+ } catch (IOException e) {
+ Log.e(Constants.TAG, "IO Error", e);
+ Notify.showNotify(getActivity(), "IO Error " + e.getMessage(), Notify.Style.ERROR);
+ }
+ return true;
+
+ case R.id.menu_key_list_debug_write:
+ try {
+ KeychainDatabase.debugBackup(getActivity(), false);
+ Notify.showNotify(getActivity(), "Backup to debug_backup.db completed", Notify.Style.INFO);
+ } catch (IOException e) {
+ Log.e(Constants.TAG, "IO Error", e);
+ Notify.showNotify(getActivity(), "IO Error: " + e.getMessage(), Notify.Style.ERROR);
+ }
+ return true;
+
+ case R.id.menu_key_list_debug_first_time:
+ Preferences prefs = Preferences.getPreferences(getActivity());
+ prefs.setFirstTime(true);
+ Intent intent = new Intent(getActivity(), FirstTimeActivity.class);
+ startActivity(intent);
+ getActivity().finish();
+ return true;
+
+ default:
+ return super.onOptionsItemSelected(item);
+ }
+ }
+
+ @Override
public boolean onQueryTextSubmit(String s) {
return true;
}
@@ -510,6 +587,77 @@ public class KeyListFragment extends LoaderFragment
return true;
}
+
+ private void searchCloud() {
+ Intent importIntent = new Intent(getActivity(), ImportKeysActivity.class);
+ importIntent.putExtra(ImportKeysActivity.EXTRA_QUERY, (String) null); // hack to show only cloud tab
+ startActivity(importIntent);
+ }
+
+ private void createKey() {
+ Intent intent = new Intent(getActivity(), CreateKeyActivity.class);
+ startActivityForResult(intent, 0);
+ }
+
+ private void consolidate() {
+ // Message is received after importing is done in KeychainIntentService
+ KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler(
+ getActivity(),
+ getString(R.string.progress_importing),
+ ProgressDialog.STYLE_HORIZONTAL) {
+ public void handleMessage(Message message) {
+ // handle messages by standard KeychainIntentServiceHandler first
+ super.handleMessage(message);
+
+ if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) {
+ // get returned data bundle
+ Bundle returnData = message.getData();
+ if (returnData == null) {
+ return;
+ }
+ final ConsolidateResult result =
+ returnData.getParcelable(OperationResult.EXTRA_RESULT);
+ if (result == null) {
+ return;
+ }
+
+ result.createNotify(getActivity()).show();
+ }
+ }
+ };
+
+ // Send all information needed to service to import key in other thread
+ Intent intent = new Intent(getActivity(), KeychainIntentService.class);
+
+ intent.setAction(KeychainIntentService.ACTION_CONSOLIDATE);
+
+ // fill values for this action
+ Bundle data = new Bundle();
+
+ intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
+
+ // Create a new Messenger for the communication back
+ Messenger messenger = new Messenger(saveHandler);
+ intent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger);
+
+ // show progress dialog
+ saveHandler.showProgressDialog(getActivity());
+
+ // start service with intent
+ getActivity().startService(intent);
+ }
+
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ // if a result has been returned, display a notify
+ if (data != null && data.hasExtra(OperationResult.EXTRA_RESULT)) {
+ OperationResult result = data.getParcelableExtra(OperationResult.EXTRA_RESULT);
+ result.createNotify(getActivity()).show();
+ } else {
+ super.onActivityResult(requestCode, resultCode, data);
+ }
+ }
+
/**
* Implements StickyListHeadersAdapter from library
*/
@@ -517,7 +665,7 @@ public class KeyListFragment extends LoaderFragment
private String mQuery;
private LayoutInflater mInflater;
- private HashMap<Integer, Boolean> mSelection = new HashMap<Integer, Boolean>();
+ private HashMap<Integer, Boolean> mSelection = new HashMap<>();
public KeyListAdapter(Context context, Cursor c, int flags) {
super(context, c, flags);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LogDisplayActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LogDisplayActivity.java
index fd74e1654..0de7bb391 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LogDisplayActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LogDisplayActivity.java
@@ -19,11 +19,9 @@
package org.sufficientlysecure.keychain.ui;
import android.os.Bundle;
-import android.support.v7.app.ActionBarActivity;
import android.view.View;
import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.ui.util.ActionBarHelper;
public class LogDisplayActivity extends BaseActivity {
@@ -32,8 +30,7 @@ public class LogDisplayActivity extends BaseActivity {
super.onCreate(savedInstanceState);
// Inflate a "Done" custom action bar
- ActionBarHelper.setOneButtonView(getSupportActionBar(),
- R.string.btn_okay, R.drawable.ic_action_done,
+ setFullScreenDialogClose(
new View.OnClickListener() {
@Override
public void onClick(View v) {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NavDrawerActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NavDrawerActivity.java
new file mode 100644
index 000000000..5381b1ab3
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NavDrawerActivity.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2015 Dominik Schürmann <dominik@dominikschuermann.de>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.sufficientlysecure.keychain.ui;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+
+import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.remote.ui.AppsListActivity;
+import org.sufficientlysecure.keychain.remote.ui.AppsListFragment;
+
+import it.neokree.materialnavigationdrawer.MaterialNavigationDrawer;
+
+public abstract class NavDrawerActivity extends MaterialNavigationDrawer {
+
+ @Override
+ public void init(Bundle savedInstanceState) {
+ // don't open drawer on first run
+ disableLearningPattern();
+
+// addMultiPaneSupport();
+
+ // set the header image
+ // create and set the header
+ View view = LayoutInflater.from(this).inflate(R.layout.custom_drawer, null);
+ setDrawerHeaderCustom(view);
+
+ // create sections
+ addSection(newSection(getString(R.string.title_keys), R.drawable.ic_vpn_key_black_24dp, new KeyListFragment()));
+
+ addSection(newSection(getString(R.string.title_encrypt_text), R.drawable.ic_lock_outline_black_24dp, new Intent(this, EncryptTextActivity.class)));
+ addSection(newSection(getString(R.string.title_encrypt_files), R.drawable.ic_lock_outline_black_24dp, new Intent(this, EncryptFilesActivity.class)));
+ addSection(newSection(getString(R.string.title_decrypt), R.drawable.ic_lock_open_black_24dp, new Intent(this, DecryptActivity.class)));
+ addSection(newSection(getString(R.string.title_api_registered_apps), R.drawable.ic_apps_black_24dp, new AppsListFragment()));
+
+ // create bottom section
+ addBottomSection(newSection(getString(R.string.menu_preferences), R.drawable.ic_settings_black_24dp, new Intent(this, SettingsActivity.class)));
+ }
+}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcActivity.java
index 3a70502ea..7311f4879 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcActivity.java
@@ -15,7 +15,6 @@ import android.nfc.Tag;
import android.nfc.tech.IsoDep;
import android.os.Build;
import android.os.Bundle;
-import android.support.v7.app.ActionBarActivity;
import android.view.WindowManager;
import android.widget.Toast;
@@ -23,13 +22,11 @@ import org.spongycastle.bcpg.HashAlgorithmTags;
import org.spongycastle.util.encoders.Hex;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.util.Iso7816TLV;
import org.sufficientlysecure.keychain.util.Log;
import java.io.IOException;
import java.nio.ByteBuffer;
-import java.util.Locale;
/**
* This class provides a communication interface to OpenPGP applications on ISO SmartCard compliant
@@ -91,33 +88,38 @@ public class NfcActivity extends BaseActivity {
mKeyId = data.getLong(EXTRA_KEY_ID);
}
- if (ACTION_SIGN_HASH.equals(action)) {
- mAction = action;
- mPin = data.getString(EXTRA_PIN);
- mHashToSign = data.getByteArray(EXTRA_NFC_HASH_TO_SIGN);
- mHashAlgo = data.getInt(EXTRA_NFC_HASH_ALGO);
- mServiceIntent = data.getParcelable(EXTRA_DATA);
-
- Log.d(Constants.TAG, "NfcActivity mAction: " + mAction);
- Log.d(Constants.TAG, "NfcActivity mPin: " + mPin);
- Log.d(Constants.TAG, "NfcActivity mHashToSign as hex: " + getHex(mHashToSign));
- Log.d(Constants.TAG, "NfcActivity mServiceIntent: " + mServiceIntent.toString());
- } else if (ACTION_DECRYPT_SESSION_KEY.equals(action)) {
- mAction = action;
- mPin = data.getString(EXTRA_PIN);
- mEncryptedSessionKey = data.getByteArray(EXTRA_NFC_ENC_SESSION_KEY);
- mServiceIntent = data.getParcelable(EXTRA_DATA);
-
- Log.d(Constants.TAG, "NfcActivity mAction: " + mAction);
- Log.d(Constants.TAG, "NfcActivity mPin: " + mPin);
- Log.d(Constants.TAG, "NfcActivity mEncryptedSessionKey as hex: " + getHex(mEncryptedSessionKey));
- Log.d(Constants.TAG, "NfcActivity mServiceIntent: " + mServiceIntent.toString());
- } else if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(action)) {
- Log.e(Constants.TAG, "This should not happen! NfcActivity.onCreate() is being called instead of onNewIntent()!");
- toast("This should not happen! Please create a new bug report that the NFC screen is restarted!");
- finish();
- } else {
- Log.d(Constants.TAG, "Action not supported: " + action);
+ switch (action) {
+ case ACTION_SIGN_HASH:
+ mAction = action;
+ mPin = data.getString(EXTRA_PIN);
+ mHashToSign = data.getByteArray(EXTRA_NFC_HASH_TO_SIGN);
+ mHashAlgo = data.getInt(EXTRA_NFC_HASH_ALGO);
+ mServiceIntent = data.getParcelable(EXTRA_DATA);
+
+ Log.d(Constants.TAG, "NfcActivity mAction: " + mAction);
+ Log.d(Constants.TAG, "NfcActivity mPin: " + mPin);
+ Log.d(Constants.TAG, "NfcActivity mHashToSign as hex: " + getHex(mHashToSign));
+ Log.d(Constants.TAG, "NfcActivity mServiceIntent: " + mServiceIntent.toString());
+ break;
+ case ACTION_DECRYPT_SESSION_KEY:
+ mAction = action;
+ mPin = data.getString(EXTRA_PIN);
+ mEncryptedSessionKey = data.getByteArray(EXTRA_NFC_ENC_SESSION_KEY);
+ mServiceIntent = data.getParcelable(EXTRA_DATA);
+
+ Log.d(Constants.TAG, "NfcActivity mAction: " + mAction);
+ Log.d(Constants.TAG, "NfcActivity mPin: " + mPin);
+ Log.d(Constants.TAG, "NfcActivity mEncryptedSessionKey as hex: " + getHex(mEncryptedSessionKey));
+ Log.d(Constants.TAG, "NfcActivity mServiceIntent: " + mServiceIntent.toString());
+ break;
+ case NfcAdapter.ACTION_TAG_DISCOVERED:
+ Log.e(Constants.TAG, "This should not happen! NfcActivity.onCreate() is being called instead of onNewIntent()!");
+ toast("This should not happen! Please create a new bug report that the NFC screen is restarted!");
+ finish();
+ break;
+ default:
+ Log.d(Constants.TAG, "Action not supported: " + action);
+ break;
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcIntentActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcIntentActivity.java
index 945d98379..3e8d688fa 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcIntentActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcIntentActivity.java
@@ -15,7 +15,6 @@ import android.nfc.Tag;
import android.nfc.tech.IsoDep;
import android.os.Build;
import android.os.Bundle;
-import android.support.v7.app.ActionBarActivity;
import android.view.WindowManager;
import android.widget.Toast;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseWizardActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseWizardActivity.java
index 93778fd0c..872e888a8 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseWizardActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseWizardActivity.java
@@ -209,9 +209,7 @@ public class PassphraseWizardActivity extends FragmentActivity implements LockPa
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.fragmentContainer, lpf).addToBackStack(null).commit();
}
- } catch (IOException e) {
- e.printStackTrace();
- } catch (FormatException e) {
+ } catch (IOException | FormatException e) {
e.printStackTrace();
}
@@ -236,9 +234,7 @@ public class PassphraseWizardActivity extends FragmentActivity implements LockPa
nfc.setText(R.string.nfc_wrong_tag);
}
}
- } catch (IOException e) {
- e.printStackTrace();
- } catch (FormatException e) {
+ } catch (IOException | FormatException e) {
e.printStackTrace();
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/QrCodeScanActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/QrCodeScanActivity.java
index 28488879b..1a7a028c6 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/QrCodeScanActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/QrCodeScanActivity.java
@@ -203,7 +203,7 @@ public class QrCodeScanActivity extends FragmentActivity {
data.putString(KeychainIntentService.IMPORT_KEY_SERVER, cloudPrefs.keyserver);
ParcelableKeyRing keyEntry = new ParcelableKeyRing(fingerprint, null, null);
- ArrayList<ParcelableKeyRing> selectedEntries = new ArrayList<ParcelableKeyRing>();
+ ArrayList<ParcelableKeyRing> selectedEntries = new ArrayList<>();
selectedEntries.add(keyEntry);
data.putParcelableArrayList(KeychainIntentService.IMPORT_KEY_LIST, selectedEntries);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/QrCodeViewActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/QrCodeViewActivity.java
index 42ad2258a..ef1d797be 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/QrCodeViewActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/QrCodeViewActivity.java
@@ -20,14 +20,12 @@ package org.sufficientlysecure.keychain.ui;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
-import android.support.v7.app.ActionBarActivity;
import android.view.View;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.widget.ImageView;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.ui.util.ActionBarHelper;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
@@ -45,8 +43,7 @@ public class QrCodeViewActivity extends BaseActivity {
super.onCreate(savedInstanceState);
// Inflate a "Done" custom action bar
- ActionBarHelper.setOneButtonView(getSupportActionBar(),
- R.string.btn_okay, R.drawable.ic_action_done,
+ setFullScreenDialogClose(
new View.OnClickListener() {
@Override
public void onClick(View v) {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SafeSlingerActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SafeSlingerActivity.java
index d5193b2a2..f95644aff 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SafeSlingerActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SafeSlingerActivity.java
@@ -27,13 +27,9 @@ import android.os.Bundle;
import android.os.Message;
import android.os.Messenger;
import android.support.v4.app.FragmentActivity;
-import android.support.v7.app.ActionBarActivity;
import android.view.View;
-import android.widget.AdapterView;
-import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.NumberPicker;
-import android.widget.Spinner;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
@@ -50,7 +46,6 @@ import org.sufficientlysecure.keychain.util.ParcelableFileCache;
import java.io.IOException;
import java.util.ArrayList;
-import java.util.List;
import edu.cmu.cylab.starslinger.exchange.ExchangeActivity;
import edu.cmu.cylab.starslinger.exchange.ExchangeConfig;
@@ -192,7 +187,7 @@ public class SafeSlingerActivity extends BaseActivity {
// We parcel this iteratively into a file - anything we can
// display here, we should be able to import.
ParcelableFileCache<ParcelableKeyRing> cache =
- new ParcelableFileCache<ParcelableKeyRing>(activity, "key_import.pcl");
+ new ParcelableFileCache<>(activity, "key_import.pcl");
cache.writeCache(it.size(), it.iterator());
// fill values for this action
@@ -220,7 +215,7 @@ public class SafeSlingerActivity extends BaseActivity {
}
private static ArrayList<ParcelableKeyRing> getSlingedKeys(Bundle extras) {
- ArrayList<ParcelableKeyRing> list = new ArrayList<ParcelableKeyRing>();
+ ArrayList<ParcelableKeyRing> list = new ArrayList<>();
if (extras != null) {
byte[] d;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectPublicKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectPublicKeyActivity.java
index f7e19706e..0e3374833 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectPublicKeyActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectPublicKeyActivity.java
@@ -20,12 +20,10 @@ package org.sufficientlysecure.keychain.ui;
import android.content.Intent;
import android.os.Bundle;
-import android.support.v7.app.ActionBarActivity;
import android.view.View;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.ui.util.ActionBarHelper;
public class SelectPublicKeyActivity extends BaseActivity {
@@ -47,21 +45,19 @@ public class SelectPublicKeyActivity extends BaseActivity {
super.onCreate(savedInstanceState);
// Inflate a "Done"/"Cancel" custom action bar view
- ActionBarHelper.setTwoButtonView(getSupportActionBar(), R.string.btn_okay, R.drawable.ic_action_done,
+ setFullScreenDialogDoneClose(R.string.btn_okay,
new View.OnClickListener() {
@Override
public void onClick(View v) {
- // ok
okClicked();
}
- }, R.string.btn_do_not_save, R.drawable.ic_action_cancel, new View.OnClickListener() {
+ },
+ new View.OnClickListener() {
@Override
public void onClick(View v) {
- // cancel
cancelClicked();
}
- }
- );
+ });
setDefaultKeyMode(DEFAULT_KEYS_SEARCH_LOCAL);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectPublicKeyFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectPublicKeyFragment.java
index af583bf89..afec3bf06 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectPublicKeyFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectPublicKeyFragment.java
@@ -42,7 +42,6 @@ import android.widget.TextView;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.compatibility.ListFragmentWorkaround;
-import org.sufficientlysecure.keychain.pgp.KeyRing;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.provider.KeychainDatabase.Tables;
import org.sufficientlysecure.keychain.ui.adapter.SelectKeyCursorAdapter;
@@ -216,7 +215,7 @@ public class SelectPublicKeyFragment extends ListFragmentWorkaround implements T
public long[] getSelectedMasterKeyIds() {
// mListView.getCheckedItemIds() would give the row ids of the KeyRings not the master key
// ids!
- Vector<Long> vector = new Vector<Long>();
+ Vector<Long> vector = new Vector<>();
for (int i = 0; i < getListView().getCount(); ++i) {
if (getListView().isItemChecked(i)) {
vector.add(mAdapter.getMasterKeyId(i));
@@ -238,7 +237,7 @@ public class SelectPublicKeyFragment extends ListFragmentWorkaround implements T
* @return
*/
public String[] getSelectedUserIds() {
- Vector<String> userIds = new Vector<String>();
+ Vector<String> userIds = new Vector<>();
for (int i = 0; i < getListView().getCount(); ++i) {
if (getListView().isItemChecked(i)) {
userIds.add(mAdapter.getUserId(i));
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsKeyServerActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsKeyServerActivity.java
index 365e8026c..080dc2495 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsKeyServerActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsKeyServerActivity.java
@@ -20,7 +20,6 @@ package org.sufficientlysecure.keychain.ui;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
-import android.support.v7.app.ActionBarActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
@@ -28,7 +27,6 @@ import android.view.ViewGroup;
import android.widget.TextView;
import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.ui.util.ActionBarHelper;
import org.sufficientlysecure.keychain.ui.widget.Editor;
import org.sufficientlysecure.keychain.ui.widget.Editor.EditorListener;
import org.sufficientlysecure.keychain.ui.widget.KeyServerEditor;
@@ -52,21 +50,19 @@ public class SettingsKeyServerActivity extends BaseActivity implements OnClickLi
super.onCreate(savedInstanceState);
// Inflate a "Done"/"Cancel" custom action bar view
- ActionBarHelper.setTwoButtonView(getSupportActionBar(), R.string.btn_okay, R.drawable.ic_action_done,
+ setFullScreenDialogDoneClose(R.string.btn_save,
new View.OnClickListener() {
@Override
public void onClick(View v) {
- // ok
okClicked();
}
- }, R.string.btn_do_not_save, R.drawable.ic_action_cancel, new View.OnClickListener() {
+ },
+ new View.OnClickListener() {
@Override
public void onClick(View v) {
- // cancel
cancelClicked();
}
- }
- );
+ });
mInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
@@ -140,7 +136,7 @@ public class SettingsKeyServerActivity extends BaseActivity implements OnClickLi
}
private Vector<String> serverList() {
- Vector<String> servers = new Vector<String>();
+ Vector<String> servers = new Vector<>();
for (int i = 0; i < mEditors.getChildCount(); ++i) {
KeyServerEditor editor = (KeyServerEditor) mEditors.getChildAt(i);
String tmp = editor.getValue();
@@ -153,7 +149,7 @@ public class SettingsKeyServerActivity extends BaseActivity implements OnClickLi
private void okClicked() {
Intent data = new Intent();
- Vector<String> servers = new Vector<String>();
+ Vector<String> servers = new Vector<>();
for (int i = 0; i < mEditors.getChildCount(); ++i) {
KeyServerEditor editor = (KeyServerEditor) mEditors.getChildAt(i);
String tmp = editor.getValue();
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 6cf346c97..ed86fea0a 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/UploadKeyActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/UploadKeyActivity.java
@@ -24,7 +24,6 @@ import android.os.Bundle;
import android.os.Message;
import android.os.Messenger;
import android.support.v4.app.NavUtils;
-import android.support.v7.app.ActionBarActivity;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
@@ -57,7 +56,7 @@ public class UploadKeyActivity extends BaseActivity {
mUploadButton = findViewById(R.id.upload_key_action_upload);
mKeyServerSpinner = (Spinner) findViewById(R.id.upload_key_keyserver);
- ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
+ ArrayAdapter<String> adapter = new ArrayAdapter<>(this,
android.R.layout.simple_spinner_item, Preferences.getPreferences(this)
.getKeyServers()
);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewCertActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewCertActivity.java
index a88b0f7cf..05d9dd58e 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewCertActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewCertActivity.java
@@ -27,9 +27,6 @@ import android.support.v4.app.NavUtils;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.support.v7.app.ActionBar;
-import android.support.v7.app.ActionBarActivity;
-import android.text.SpannableString;
-import android.text.SpannableStringBuilder;
import android.text.format.DateFormat;
import android.view.MenuItem;
import android.view.View;
@@ -37,7 +34,6 @@ import android.widget.TextView;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.pgp.CanonicalizedPublicKeyRing;
import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.pgp.WrappedSignature;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvancedActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvancedActivity.java
index 7176232c5..471f55c47 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvancedActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvancedActivity.java
@@ -20,14 +20,11 @@ package org.sufficientlysecure.keychain.ui;
import android.net.Uri;
import android.os.Bundle;
-import android.support.v7.app.ActionBar;
-import android.support.v7.app.ActionBarActivity;
import android.view.View;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
-import org.sufficientlysecure.keychain.ui.util.ActionBarHelper;
import org.sufficientlysecure.keychain.util.ExportHelper;
import org.sufficientlysecure.keychain.util.Log;
@@ -44,8 +41,7 @@ public class ViewKeyAdvancedActivity extends BaseActivity {
mProviderHelper = new ProviderHelper(this);
// Inflate a "Done" custom action bar
- ActionBarHelper.setOneButtonView(getSupportActionBar(),
- R.string.btn_okay, R.drawable.ic_action_done,
+ setFullScreenDialogClose(
new View.OnClickListener() {
@Override
public void onClick(View v) {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyShareFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyShareFragment.java
index aa260b654..7c47cbd0d 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyShareFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyShareFragment.java
@@ -228,10 +228,7 @@ public class ViewKeyShareFragment extends LoaderFragment implements
}
startActivity(Intent.createChooser(sendIntent, title));
}
- } catch (PgpGeneralException e) {
- Log.e(Constants.TAG, "error processing key!", e);
- Notify.showNotify(getActivity(), R.string.error_key_processing, Notify.Style.ERROR);
- } catch (IOException e) {
+ } catch (PgpGeneralException | IOException e) {
Log.e(Constants.TAG, "error processing key!", e);
Notify.showNotify(getActivity(), R.string.error_key_processing, Notify.Style.ERROR);
} catch (ProviderHelper.NotFoundException e) {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysAdapter.java
index 6c81e9193..8e82dd7d0 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysAdapter.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysAdapter.java
@@ -95,8 +95,8 @@ public class ImportKeysAdapter extends ArrayAdapter<ImportKeysListEntry> {
* @see org.sufficientlysecure.keychain.operations.ImportExportOperation
*/
public ArrayList<ImportKeysListEntry> getSelectedEntries() {
- ArrayList<ImportKeysListEntry> result = new ArrayList<ImportKeysListEntry>();
- ArrayList<ImportKeysListEntry> secrets = new ArrayList<ImportKeysListEntry>();
+ ArrayList<ImportKeysListEntry> result = new ArrayList<>();
+ ArrayList<ImportKeysListEntry> secrets = new ArrayList<>();
if (mData == null) {
return result;
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListCloudLoader.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListCloudLoader.java
index 176c3ff5b..235fdf1d5 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListCloudLoader.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListCloudLoader.java
@@ -39,7 +39,7 @@ public class ImportKeysListCloudLoader
Preferences.CloudSearchPrefs mCloudPrefs;
String mServerQuery;
- private ArrayList<ImportKeysListEntry> mEntryList = new ArrayList<ImportKeysListEntry>();
+ private ArrayList<ImportKeysListEntry> mEntryList = new ArrayList<>();
private AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>> mEntryListWrapper;
public ImportKeysListCloudLoader(Context context, String serverQuery, Preferences.CloudSearchPrefs cloudPrefs) {
@@ -51,7 +51,7 @@ public class ImportKeysListCloudLoader
@Override
public AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>> loadInBackground() {
- mEntryListWrapper = new AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>(mEntryList, null);
+ mEntryListWrapper = new AsyncTaskResultWrapper<>(mEntryList, null);
if (mServerQuery == null) {
Log.e(Constants.TAG, "mServerQuery is null!");
@@ -119,7 +119,7 @@ public class ImportKeysListCloudLoader
mEntryList.addAll(searchResult);
}
GetKeyResult getKeyResult = new GetKeyResult(GetKeyResult.RESULT_OK, null);
- mEntryListWrapper = new AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>(mEntryList, getKeyResult);
+ mEntryListWrapper = new AsyncTaskResultWrapper<>(mEntryList, getKeyResult);
} catch (Keyserver.CloudSearchFailureException e) {
// convert exception to result parcel
int error = GetKeyResult.RESULT_ERROR;
@@ -140,7 +140,7 @@ public class ImportKeysListCloudLoader
OperationResult.OperationLog log = new OperationResult.OperationLog();
log.add(logType, 0);
GetKeyResult getKeyResult = new GetKeyResult(error, log);
- mEntryListWrapper = new AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>(mEntryList, getKeyResult);
+ mEntryListWrapper = new AsyncTaskResultWrapper<>(mEntryList, getKeyResult);
}
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListLoader.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListLoader.java
index cecad2716..144a16a48 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListLoader.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListLoader.java
@@ -35,28 +35,15 @@ import org.sufficientlysecure.keychain.util.PositionAwareInputStream;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.util.ArrayList;
-import java.util.Iterator;
public class ImportKeysListLoader
extends AsyncTaskLoader<AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>> {
- public static class NonPgpPartException extends Exception {
- private int mCount;
-
- public NonPgpPartException(int count) {
- this.mCount = count;
- }
-
- public int getCount() {
- return mCount;
- }
- }
-
final Context mContext;
final InputData mInputData;
- ArrayList<ImportKeysListEntry> mData = new ArrayList<ImportKeysListEntry>();
- LongSparseArray<ParcelableKeyRing> mParcelableRings = new LongSparseArray<ParcelableKeyRing>();
+ ArrayList<ImportKeysListEntry> mData = new ArrayList<>();
+ LongSparseArray<ParcelableKeyRing> mParcelableRings = new LongSparseArray<>();
AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>> mEntryListWrapper;
public ImportKeysListLoader(Context context, InputData inputData) {
@@ -73,7 +60,7 @@ public class ImportKeysListLoader
}
GetKeyResult getKeyResult = new GetKeyResult(GetKeyResult.RESULT_OK, null);
- mEntryListWrapper = new AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>(mData, getKeyResult);
+ mEntryListWrapper = new AsyncTaskResultWrapper<>(mData, getKeyResult);
if (mInputData == null) {
Log.e(Constants.TAG, "Input data is null!");
@@ -140,7 +127,7 @@ public class ImportKeysListLoader
OperationResult.OperationLog log = new OperationResult.OperationLog();
log.add(OperationResult.LogType.MSG_GET_NO_VALID_KEYS, 0);
GetKeyResult getKeyResult = new GetKeyResult(GetKeyResult.RESULT_ERROR_NO_VALID_KEYS, log);
- mEntryListWrapper = new AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>
+ mEntryListWrapper = new AsyncTaskResultWrapper<>
(mData, getKeyResult);
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyValueSpinnerAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyValueSpinnerAdapter.java
index 80d605fb9..b8fe21941 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyValueSpinnerAdapter.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyValueSpinnerAdapter.java
@@ -33,7 +33,7 @@ public class KeyValueSpinnerAdapter extends ArrayAdapter<String> {
static <K, V extends Comparable<? super V>> SortedSet<Map.Entry<K, V>> entriesSortedByValues(
Map<K, V> map) {
- SortedSet<Map.Entry<K, V>> sortedEntries = new TreeSet<Map.Entry<K, V>>(
+ SortedSet<Map.Entry<K, V>> sortedEntries = new TreeSet<>(
new Comparator<Map.Entry<K, V>>() {
@Override
public int compare(Map.Entry<K, V> e1, Map.Entry<K, V> e2) {
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 9f29826ef..47ad5e664 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
@@ -44,7 +44,7 @@ public class MultiUserIdsAdapter extends CursorAdapter {
public MultiUserIdsAdapter(Context context, Cursor c, int flags) {
super(context, c, flags);
mInflater = LayoutInflater.from(context);
- mCheckStates = new ArrayList<Boolean>();
+ mCheckStates = new ArrayList<>();
}
@Override
@@ -148,7 +148,7 @@ public class MultiUserIdsAdapter extends CursorAdapter {
}
public ArrayList<CertifyAction> getSelectedCertifyActions() {
- LongSparseArray<CertifyAction> actions = new LongSparseArray<CertifyAction>();
+ LongSparseArray<CertifyAction> actions = new LongSparseArray<>();
for (int i = 0; i < mCheckStates.size(); i++) {
if (mCheckStates.get(i)) {
mCursor.moveToPosition(i);
@@ -171,7 +171,7 @@ public class MultiUserIdsAdapter extends CursorAdapter {
}
}
- ArrayList<CertifyAction> result = new ArrayList<CertifyAction>(actions.size());
+ ArrayList<CertifyAction> result = new ArrayList<>(actions.size());
for (int i = 0; i < actions.size(); i++) {
result.add(actions.valueAt(i));
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/PagerTabStripAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/PagerTabStripAdapter.java
index 330254a8f..963e77fe9 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/PagerTabStripAdapter.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/PagerTabStripAdapter.java
@@ -27,7 +27,7 @@ import java.util.ArrayList;
public class PagerTabStripAdapter extends FragmentPagerAdapter {
protected final Activity mActivity;
- protected final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();
+ protected final ArrayList<TabInfo> mTabs = new ArrayList<>();
static final class TabInfo {
public final Class<?> clss;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java
index a032e96fc..5ba09be7e 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java
@@ -35,7 +35,7 @@ import android.widget.ImageView;
import android.widget.TextView;
import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.ui.util.FormattingUtils;
+import org.sufficientlysecure.keychain.service.SaveKeyringParcel.SubkeyChange;
import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey.SecretKeyType;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.provider.KeychainContract.Keys;
@@ -160,7 +160,11 @@ public class SubkeysAdapter extends CursorAdapter {
cursor.getString(INDEX_KEY_CURVE_OID)
));
- if (mSaveKeyringParcel != null && mSaveKeyringParcel.mStripSubKeys.contains(keyId)) {
+ SubkeyChange change = mSaveKeyringParcel != null
+ ? mSaveKeyringParcel.getSubkeyChange(keyId)
+ : null;
+
+ if (change != null && change.mDummyStrip) {
algorithmStr.append(", ");
final SpannableString boldStripped = new SpannableString(
context.getString(R.string.key_stripped)
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/TabsAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/TabsAdapter.java
index 9ddfa90be..44afed351 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/TabsAdapter.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/TabsAdapter.java
@@ -33,7 +33,7 @@ public class TabsAdapter extends FragmentStatePagerAdapter implements ActionBar.
private final Context mContext;
private final ActionBar mActionBar;
private final ViewPager mViewPager;
- private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();
+ private final ArrayList<TabInfo> mTabs = new ArrayList<>();
static final class TabInfo {
public final Class<?> clss;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAdapter.java
index a778c7fa7..52c21e253 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAdapter.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAdapter.java
@@ -221,7 +221,7 @@ public class UserIdsAdapter extends CursorAdapter implements AdapterView.OnItemC
}
public ArrayList<String> getSelectedUserIds() {
- ArrayList<String> result = new ArrayList<String>();
+ ArrayList<String> result = new ArrayList<>();
for (int i = 0; i < mCheckStates.size(); i++) {
if (mCheckStates.get(i)) {
mCursor.moveToPosition(i);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddSubkeyDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddSubkeyDialogFragment.java
index b4119a5eb..d5376cbdc 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddSubkeyDialogFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddSubkeyDialogFragment.java
@@ -145,20 +145,20 @@ public class AddSubkeyDialogFragment extends DialogFragment {
}
{
- ArrayList<Choice<Algorithm>> choices = new ArrayList<Choice<Algorithm>>();
- choices.add(new Choice<Algorithm>(Algorithm.DSA, getResources().getString(
+ ArrayList<Choice<Algorithm>> choices = new ArrayList<>();
+ choices.add(new Choice<>(Algorithm.DSA, getResources().getString(
R.string.dsa)));
if (!mWillBeMasterKey) {
- choices.add(new Choice<Algorithm>(Algorithm.ELGAMAL, getResources().getString(
+ choices.add(new Choice<>(Algorithm.ELGAMAL, getResources().getString(
R.string.elgamal)));
}
- choices.add(new Choice<Algorithm>(Algorithm.RSA, getResources().getString(
+ choices.add(new Choice<>(Algorithm.RSA, getResources().getString(
R.string.rsa)));
- choices.add(new Choice<Algorithm>(Algorithm.ECDSA, getResources().getString(
+ choices.add(new Choice<>(Algorithm.ECDSA, getResources().getString(
R.string.ecdsa)));
- choices.add(new Choice<Algorithm>(Algorithm.ECDH, getResources().getString(
+ choices.add(new Choice<>(Algorithm.ECDH, getResources().getString(
R.string.ecdh)));
- ArrayAdapter<Choice<Algorithm>> adapter = new ArrayAdapter<Choice<Algorithm>>(context,
+ ArrayAdapter<Choice<Algorithm>> adapter = new ArrayAdapter<>(context,
android.R.layout.simple_spinner_item, choices);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
mAlgorithmSpinner.setAdapter(adapter);
@@ -172,20 +172,20 @@ public class AddSubkeyDialogFragment extends DialogFragment {
}
// dynamic ArrayAdapter must be created (instead of ArrayAdapter.getFromResource), because it's content may change
- ArrayAdapter<CharSequence> keySizeAdapter = new ArrayAdapter<CharSequence>(context, android.R.layout.simple_spinner_item,
+ ArrayAdapter<CharSequence> keySizeAdapter = new ArrayAdapter<>(context, android.R.layout.simple_spinner_item,
new ArrayList<CharSequence>(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<Choice<Curve>> choices = new ArrayList<Choice<Curve>>();
+ ArrayList<Choice<Curve>> choices = new ArrayList<>();
- choices.add(new Choice<Curve>(Curve.NIST_P256, getResources().getString(
+ choices.add(new Choice<>(Curve.NIST_P256, getResources().getString(
R.string.key_curve_nist_p256)));
- choices.add(new Choice<Curve>(Curve.NIST_P384, getResources().getString(
+ choices.add(new Choice<>(Curve.NIST_P384, getResources().getString(
R.string.key_curve_nist_p384)));
- choices.add(new Choice<Curve>(Curve.NIST_P521, getResources().getString(
+ choices.add(new Choice<>(Curve.NIST_P521, getResources().getString(
R.string.key_curve_nist_p521)));
/* @see SaveKeyringParcel
@@ -197,7 +197,7 @@ public class AddSubkeyDialogFragment extends DialogFragment {
R.string.key_curve_bp_p512)));
*/
- ArrayAdapter<Choice<Curve>> adapter = new ArrayAdapter<Choice<Curve>>(context,
+ ArrayAdapter<Choice<Curve>> adapter = new ArrayAdapter<>(context,
android.R.layout.simple_spinner_item, choices);
mCurveSpinner.setAdapter(adapter);
// make NIST P-256 the default
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddUserIdDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddUserIdDialogFragment.java
index 3eef04aa7..a4ecc7c27 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddUserIdDialogFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddUserIdDialogFragment.java
@@ -85,7 +85,7 @@ public class AddUserIdDialogFragment extends DialogFragment implements OnEditorA
mMessenger = getArguments().getParcelable(ARG_MESSENGER);
String predefinedName = getArguments().getString(ARG_NAME);
- ArrayAdapter<String> autoCompleteEmailAdapter = new ArrayAdapter<String>
+ ArrayAdapter<String> autoCompleteEmailAdapter = new ArrayAdapter<>
(getActivity(), android.R.layout.simple_spinner_dropdown_item,
ContactHelper.getPossibleUserEmails(getActivity())
);
@@ -150,7 +150,7 @@ public class AddUserIdDialogFragment extends DialogFragment implements OnEditorA
mName.setThreshold(1); // Start working from first character
mName.setAdapter(
- new ArrayAdapter<String>
+ new ArrayAdapter<>
(getActivity(), android.R.layout.simple_spinner_dropdown_item,
ContactHelper.getPossibleUserNames(getActivity())
)
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteFileDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteFileDialogFragment.java
index 0926de1d0..879e3f6da 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteFileDialogFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteFileDialogFragment.java
@@ -28,7 +28,6 @@ import android.support.v4.app.DialogFragment;
import android.support.v4.app.FragmentActivity;
import android.widget.Toast;
-import org.apache.http.conn.scheme.Scheme;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.util.FileHelper;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/ActionBarHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/ActionBarHelper.java
deleted file mode 100644
index edd12ec73..000000000
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/ActionBarHelper.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (C) 2013-2014 Dominik Schürmann <dominik@dominikschuermann.de>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-package org.sufficientlysecure.keychain.ui.util;
-
-import android.app.Activity;
-import android.support.v7.app.ActionBar;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.view.ViewGroup;
-import android.widget.TextView;
-
-import org.sufficientlysecure.keychain.R;
-
-public class ActionBarHelper {
-
- /**
- * Sets custom view on ActionBar for Done/Cancel activities
- *
- * @param actionBar
- * @param firstText
- * @param firstDrawableId
- * @param firstOnClickListener
- * @param secondText
- * @param secondDrawableId
- * @param secondOnClickListener
- */
- public static void setTwoButtonView(ActionBar actionBar,
- int firstText, int firstDrawableId, OnClickListener firstOnClickListener,
- int secondText, int secondDrawableId, OnClickListener secondOnClickListener) {
-
- // Inflate the custom action bar view
- final LayoutInflater inflater = (LayoutInflater) actionBar.getThemedContext()
- .getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
- final View customActionBarView = inflater.inflate(
- R.layout.actionbar_custom_view_done_cancel, null);
-
- TextView firstTextView = ((TextView) customActionBarView.findViewById(R.id.actionbar_done_text));
- firstTextView.setText(firstText);
- firstTextView.setCompoundDrawablesWithIntrinsicBounds(firstDrawableId, 0, 0, 0);
- customActionBarView.findViewById(R.id.actionbar_done).setOnClickListener(
- firstOnClickListener);
- TextView secondTextView = ((TextView) customActionBarView.findViewById(R.id.actionbar_cancel_text));
- secondTextView.setText(secondText);
- secondTextView.setCompoundDrawablesWithIntrinsicBounds(secondDrawableId, 0, 0, 0);
- customActionBarView.findViewById(R.id.actionbar_cancel).setOnClickListener(
- secondOnClickListener);
-
- // Show the custom action bar view and hide the normal Home icon and title.
- actionBar.setDisplayShowTitleEnabled(false);
- actionBar.setDisplayShowHomeEnabled(false);
- actionBar.setDisplayShowCustomEnabled(true);
- actionBar.setCustomView(customActionBarView, new ActionBar.LayoutParams(
- ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
- }
-
- /**
- * Sets custom view on ActionBar for Done activities
- *
- * @param actionBar
- * @param firstText
- * @param firstOnClickListener
- */
- public static void setOneButtonView(ActionBar actionBar, int firstText, int firstDrawableId,
- OnClickListener firstOnClickListener) {
- // Inflate a "Done" custom action bar view to serve as the "Up" affordance.
- final LayoutInflater inflater = (LayoutInflater) actionBar.getThemedContext()
- .getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
- final View customActionBarView = inflater
- .inflate(R.layout.actionbar_custom_view_done, null);
-
- TextView firstTextView = ((TextView) customActionBarView.findViewById(R.id.actionbar_done_text));
- firstTextView.setText(firstText);
- firstTextView.setCompoundDrawablesWithIntrinsicBounds(firstDrawableId, 0, 0, 0);
- customActionBarView.findViewById(R.id.actionbar_done).setOnClickListener(
- firstOnClickListener);
-
- // Show the custom action bar view and hide the normal Home icon and title.
- actionBar.setDisplayShowTitleEnabled(false);
- actionBar.setDisplayShowHomeEnabled(false);
- actionBar.setDisplayShowCustomEnabled(true);
- actionBar.setCustomView(customActionBarView);
- }
-}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/QrCodeUtils.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/QrCodeUtils.java
index 36f38045f..0bb4100c5 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/QrCodeUtils.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/QrCodeUtils.java
@@ -47,7 +47,7 @@ public class QrCodeUtils {
*/
public static Bitmap getQRCodeBitmap(final String input, final int size) {
try {
- final Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
+ final Hashtable<EncodeHintType, Object> hints = new Hashtable<>();
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
final BitMatrix result = new QRCodeWriter().encode(input, BarcodeFormat.QR_CODE, size,
size, hints);
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 14f42eb04..904cde47e 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
@@ -29,7 +29,6 @@ import android.widget.ImageView;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.provider.KeychainDatabase;
-import org.sufficientlysecure.keychain.provider.KeychainDatabase.Tables;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
public class CertifyKeySpinner extends KeySpinner {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionView.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionView.java
index e03a14989..5f6f13181 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionView.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionView.java
@@ -28,7 +28,6 @@ import android.support.v4.app.FragmentActivity;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
-import android.text.SpannableStringBuilder;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
@@ -46,7 +45,6 @@ import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.util.ContactHelper;
import org.sufficientlysecure.keychain.pgp.KeyRing;
-import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.provider.KeychainDatabase.Tables;
@@ -165,7 +163,7 @@ public class EncryptKeyCompletionView extends TokenCompleteTextView {
setAdapter(new EncryptKeyAdapter(Collections.<EncryptionKey>emptyList()));
return;
}
- ArrayList<EncryptionKey> keys = new ArrayList<EncryptionKey>();
+ ArrayList<EncryptionKey> keys = new ArrayList<>();
while (cursor.moveToNext()) {
try {
EncryptionKey key = new EncryptionKey(cursor);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/FoldableLinearLayout.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/FoldableLinearLayout.java
index b456b61ab..34e7b639a 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/FoldableLinearLayout.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/FoldableLinearLayout.java
@@ -33,17 +33,16 @@ import org.sufficientlysecure.keychain.R;
/**
* Class representing a LinearLayout that can fold and hide it's content when pressed
* To use just add the following to your xml layout
-
- <org.sufficientlysecure.keychain.ui.widget.FoldableLinearLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- custom:foldedLabel="@string/TEXT_TO_DISPLAY_WHEN_FOLDED"
- custom:unFoldedLabel="@string/TEXT_TO_DISPLAY_WHEN_UNFOLDED">
-
- <include layout="@layout/ELEMENTS_TO_BE_FOLDED"/>
-
- </org.sufficientlysecure.keychain.ui.widget.FoldableLinearLayout>
-
+ * <p/>
+ * <org.sufficientlysecure.keychain.ui.widget.FoldableLinearLayout
+ * android:layout_width="wrap_content"
+ * android:layout_height="wrap_content"
+ * custom:foldedLabel="@string/TEXT_TO_DISPLAY_WHEN_FOLDED"
+ * custom:unFoldedLabel="@string/TEXT_TO_DISPLAY_WHEN_UNFOLDED">
+ * <p/>
+ * <include layout="@layout/ELEMENTS_TO_BE_FOLDED"/>
+ * <p/>
+ * </org.sufficientlysecure.keychain.ui.widget.FoldableLinearLayout>
*/
public class FoldableLinearLayout extends LinearLayout {
@@ -75,6 +74,7 @@ public class FoldableLinearLayout extends LinearLayout {
/**
* Load given attributes to inner variables,
+ *
* @param context
* @param attrs
*/
@@ -87,8 +87,8 @@ public class FoldableLinearLayout extends LinearLayout {
a.recycle();
}
// If any attribute isn't found then set a default one
- mFoldedLabel = (mFoldedLabel == null) ? context.getString(R.id.none) : mFoldedLabel;
- mUnFoldedLabel = (mUnFoldedLabel == null) ? context.getString(R.id.none) : mUnFoldedLabel;
+ mFoldedLabel = (mFoldedLabel == null) ? context.getString(R.string.none) : mFoldedLabel;
+ mUnFoldedLabel = (mUnFoldedLabel == null) ? context.getString(R.string.none) : mUnFoldedLabel;
}
@Override
@@ -138,7 +138,7 @@ public class FoldableLinearLayout extends LinearLayout {
private void initialiseInnerViews() {
mFoldableIcon = (ImageView) mFoldableLayout.findViewById(R.id.foldableIcon);
- mFoldableIcon.setImageResource(R.drawable.ic_action_expand);
+ mFoldableIcon.setImageResource(R.drawable.ic_expand_more_black_24dp);
mFoldableTextView = (TextView) mFoldableLayout.findViewById(R.id.foldableText);
mFoldableTextView.setText(mFoldedLabel);
@@ -151,7 +151,7 @@ public class FoldableLinearLayout extends LinearLayout {
public void onClick(View view) {
mFolded = !mFolded;
if (mFolded) {
- mFoldableIcon.setImageResource(R.drawable.ic_action_collapse);
+ mFoldableIcon.setImageResource(R.drawable.ic_expand_less_black_24dp);
mFoldableContainer.setVisibility(View.VISIBLE);
AlphaAnimation animation = new AlphaAnimation(0f, 1f);
animation.setDuration(mShortAnimationDuration);
@@ -159,12 +159,13 @@ public class FoldableLinearLayout extends LinearLayout {
mFoldableTextView.setText(mUnFoldedLabel);
} else {
- mFoldableIcon.setImageResource(R.drawable.ic_action_expand);
+ mFoldableIcon.setImageResource(R.drawable.ic_expand_more_black_24dp);
AlphaAnimation animation = new AlphaAnimation(1f, 0f);
animation.setDuration(mShortAnimationDuration);
animation.setAnimationListener(new Animation.AnimationListener() {
@Override
- public void onAnimationStart(Animation animation) { }
+ public void onAnimationStart(Animation animation) {
+ }
@Override
public void onAnimationEnd(Animation animation) {
@@ -173,7 +174,8 @@ public class FoldableLinearLayout extends LinearLayout {
}
@Override
- public void onAnimationRepeat(Animation animation) { }
+ public void onAnimationRepeat(Animation animation) {
+ }
});
mFoldableContainer.startAnimation(animation);
mFoldableTextView.setText(mFoldedLabel);
@@ -185,6 +187,7 @@ public class FoldableLinearLayout extends LinearLayout {
/**
* Adds provided child view to foldableContainer View
+ *
* @param child
*/
@Override
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/ListAwareSwipeRefreshLayout.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/ListAwareSwipeRefreshLayout.java
index b3c3eb417..3403208d7 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/ListAwareSwipeRefreshLayout.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/ListAwareSwipeRefreshLayout.java
@@ -20,13 +20,8 @@ package org.sufficientlysecure.keychain.ui.widget;
import android.content.Context;
import android.support.v4.widget.NoScrollableSwipeRefreshLayout;
import android.util.AttributeSet;
-import android.view.InputDevice;
-import android.view.InputDevice.MotionRange;
import android.view.MotionEvent;
-import org.sufficientlysecure.keychain.Constants;
-import org.sufficientlysecure.keychain.util.Log;
-
import se.emilsjolander.stickylistheaders.StickyListHeadersListView;
public class ListAwareSwipeRefreshLayout extends NoScrollableSwipeRefreshLayout {
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 59d05a62e..9c8e4aedb 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
@@ -26,7 +26,6 @@ import android.support.v4.content.Loader;
import android.util.AttributeSet;
import android.widget.ImageView;
-import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/AlgorithmNames.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/AlgorithmNames.java
index 99db634ac..c1955f75b 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/AlgorithmNames.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/AlgorithmNames.java
@@ -23,7 +23,6 @@ import android.app.Activity;
import org.spongycastle.bcpg.CompressionAlgorithmTags;
import org.spongycastle.bcpg.HashAlgorithmTags;
import org.spongycastle.openpgp.PGPEncryptedData;
-import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import java.util.HashMap;
@@ -32,9 +31,9 @@ import java.util.HashMap;
public class AlgorithmNames {
Activity mActivity;
- HashMap<Integer, String> mEncryptionNames = new HashMap<Integer, String>();
- HashMap<Integer, String> mHashNames = new HashMap<Integer, String>();
- HashMap<Integer, String> mCompressionNames = new HashMap<Integer, String>();
+ HashMap<Integer, String> mEncryptionNames = new HashMap<>();
+ HashMap<Integer, String> mHashNames = new HashMap<>();
+ HashMap<Integer, String> mCompressionNames = new HashMap<>();
public AlgorithmNames(Activity context) {
super();
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ContactHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ContactHelper.java
index 4ce7a1bac..11b29f521 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ContactHelper.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ContactHelper.java
@@ -73,20 +73,20 @@ public class ContactHelper {
ContactsContract.Data.RAW_CONTACT_ID + "=? AND " + ContactsContract.Data.MIMETYPE + "=?";
public static final String ID_SELECTION = ContactsContract.RawContacts._ID + "=?";
- private static final Map<String, Bitmap> photoCache = new HashMap<String, Bitmap>();
+ private static final Map<String, Bitmap> photoCache = new HashMap<>();
public static List<String> getPossibleUserEmails(Context context) {
Set<String> accountMails = getAccountEmails(context);
accountMails.addAll(getMainProfileContactEmails(context));
// now return the Set (without duplicates) as a List
- return new ArrayList<String>(accountMails);
+ return new ArrayList<>(accountMails);
}
public static List<String> getPossibleUserNames(Context context) {
Set<String> accountMails = getAccountEmails(context);
Set<String> names = getContactNamesFromEmails(context, accountMails);
names.addAll(getMainProfileContactName(context));
- return new ArrayList<String>(names);
+ return new ArrayList<>(names);
}
/**
@@ -97,7 +97,7 @@ public class ContactHelper {
*/
private static Set<String> getAccountEmails(Context context) {
final Account[] accounts = AccountManager.get(context).getAccounts();
- final Set<String> emailSet = new HashSet<String>();
+ final Set<String> emailSet = new HashSet<>();
for (Account account : accounts) {
if (Patterns.EMAIL_ADDRESS.matcher(account.name).matches()) {
emailSet.add(account.name);
@@ -116,7 +116,7 @@ public class ContactHelper {
*/
private static Set<String> getContactNamesFromEmails(Context context, Set<String> emails) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
- Set<String> names = new HashSet<String>();
+ Set<String> names = new HashSet<>();
for (String email : emails) {
ContentResolver resolver = context.getContentResolver();
Cursor profileCursor = resolver.query(
@@ -128,7 +128,7 @@ public class ContactHelper {
);
if (profileCursor == null) return null;
- Set<String> currNames = new HashSet<String>();
+ Set<String> currNames = new HashSet<>();
while (profileCursor.moveToNext()) {
String name = profileCursor.getString(1);
if (name != null) {
@@ -140,7 +140,7 @@ public class ContactHelper {
}
return names;
} else {
- return new HashSet<String>();
+ return new HashSet<>();
}
}
@@ -172,7 +172,7 @@ public class ContactHelper {
);
if (profileCursor == null) return null;
- Set<String> emails = new HashSet<String>();
+ Set<String> emails = new HashSet<>();
while (profileCursor.moveToNext()) {
String email = profileCursor.getString(0);
if (email != null) {
@@ -182,7 +182,7 @@ public class ContactHelper {
profileCursor.close();
return emails;
} else {
- return new HashSet<String>();
+ return new HashSet<>();
}
}
@@ -201,7 +201,7 @@ public class ContactHelper {
null, null, null);
if (profileCursor == null) return null;
- Set<String> names = new HashSet<String>();
+ Set<String> names = new HashSet<>();
// should only contain one entry!
while (profileCursor.moveToNext()) {
String name = profileCursor.getString(0);
@@ -210,9 +210,9 @@ public class ContactHelper {
}
}
profileCursor.close();
- return new ArrayList<String>(names);
+ return new ArrayList<>(names);
} else {
- return new ArrayList<String>();
+ return new ArrayList<>();
}
}
@@ -221,9 +221,9 @@ public class ContactHelper {
Cursor mailCursor = resolver.query(ContactsContract.CommonDataKinds.Email.CONTENT_URI,
new String[]{ContactsContract.CommonDataKinds.Email.DATA},
null, null, null);
- if (mailCursor == null) return new ArrayList<String>();
+ if (mailCursor == null) return new ArrayList<>();
- Set<String> mails = new HashSet<String>();
+ Set<String> mails = new HashSet<>();
while (mailCursor.moveToNext()) {
String email = mailCursor.getString(0);
if (email != null) {
@@ -231,7 +231,7 @@ public class ContactHelper {
}
}
mailCursor.close();
- return new ArrayList<String>(mails);
+ return new ArrayList<>(mails);
}
public static List<String> getContactNames(Context context) {
@@ -239,9 +239,9 @@ public class ContactHelper {
Cursor cursor = resolver.query(ContactsContract.Contacts.CONTENT_URI,
new String[]{ContactsContract.Contacts.DISPLAY_NAME},
null, null, null);
- if (cursor == null) return new ArrayList<String>();
+ if (cursor == null) return new ArrayList<>();
- Set<String> names = new HashSet<String>();
+ Set<String> names = new HashSet<>();
while (cursor.moveToNext()) {
String name = cursor.getString(0);
if (name != null) {
@@ -249,7 +249,7 @@ public class ContactHelper {
}
}
cursor.close();
- return new ArrayList<String>(names);
+ return new ArrayList<>(names);
}
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
@@ -309,7 +309,7 @@ public class ContactHelper {
boolean isExpired = !cursor.isNull(4) && new Date(cursor.getLong(4) * 1000).before(new Date());
boolean isRevoked = cursor.getInt(5) > 0;
int rawContactId = findRawContactId(resolver, fingerprint);
- ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
+ ArrayList<ContentProviderOperation> ops = new ArrayList<>();
// Do not store expired or revoked keys in contact db - and remove them if they already exist
if (isExpired || isRevoked) {
@@ -351,7 +351,7 @@ public class ContactHelper {
* @return a set of all key fingerprints currently present in the contact db
*/
private static Set<String> getRawContactFingerprints(ContentResolver resolver) {
- HashSet<String> result = new HashSet<String>();
+ HashSet<String> result = new HashSet<>();
Cursor fingerprints = resolver.query(ContactsContract.RawContacts.CONTENT_URI, SOURCE_ID_PROJECTION,
ACCOUNT_TYPE_SELECTION, new String[]{Constants.ACCOUNT_TYPE}, null);
if (fingerprints != null) {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/EmailKeyHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/EmailKeyHelper.java
index 49d4d8bf8..8334b37ec 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/EmailKeyHelper.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/EmailKeyHelper.java
@@ -42,13 +42,13 @@ public class EmailKeyHelper {
public static void importAll(Context context, Messenger messenger, List<String> mails) {
// Collect all candidates as ImportKeysListEntry (set for deduplication)
- Set<ImportKeysListEntry> entries = new HashSet<ImportKeysListEntry>();
+ Set<ImportKeysListEntry> entries = new HashSet<>();
for (String mail : mails) {
entries.addAll(getEmailKeys(context, mail));
}
// Put them in a list and import
- ArrayList<ParcelableKeyRing> keys = new ArrayList<ParcelableKeyRing>(entries.size());
+ ArrayList<ParcelableKeyRing> keys = new ArrayList<>(entries.size());
for (ImportKeysListEntry entry : entries) {
keys.add(new ParcelableKeyRing(entry.getFingerprintHex(), entry.getKeyIdHex(), null));
}
@@ -56,7 +56,7 @@ public class EmailKeyHelper {
}
public static Set<ImportKeysListEntry> getEmailKeys(Context context, String mail) {
- Set<ImportKeysListEntry> keys = new HashSet<ImportKeysListEntry>();
+ Set<ImportKeysListEntry> keys = new HashSet<>();
// Try _hkp._tcp SRV record first
String[] mailparts = mail.split("@");
@@ -90,7 +90,7 @@ public class EmailKeyHelper {
}
public static List<ImportKeysListEntry> getEmailKeys(String mail, Keyserver keyServer) {
- Set<ImportKeysListEntry> keys = new HashSet<ImportKeysListEntry>();
+ Set<ImportKeysListEntry> keys = new HashSet<>();
try {
for (ImportKeysListEntry key : keyServer.search(mail)) {
if (key.isRevoked() || key.isExpired()) continue;
@@ -103,6 +103,6 @@ public class EmailKeyHelper {
} catch (Keyserver.QueryFailedException ignored) {
} catch (Keyserver.QueryNeedsRepairException ignored) {
}
- return new ArrayList<ImportKeysListEntry>(keys);
+ return new ArrayList<>(keys);
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ExportHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ExportHelper.java
index 7492d95b2..1d78ed80e 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ExportHelper.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ExportHelper.java
@@ -24,13 +24,11 @@ import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.Messenger;
-import android.support.v7.app.ActionBarActivity;
-import android.widget.Toast;
+import android.support.v4.app.FragmentActivity;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.operations.results.ExportResult;
-import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.service.KeychainIntentService;
@@ -42,9 +40,9 @@ import java.io.File;
public class ExportHelper {
protected File mExportFile;
- ActionBarActivity mActivity;
+ FragmentActivity mActivity;
- public ExportHelper(ActionBarActivity activity) {
+ public ExportHelper(FragmentActivity activity) {
super();
this.mActivity = activity;
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Iso7816TLV.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Iso7816TLV.java
index 90afd3bc0..c0483ad04 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Iso7816TLV.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Iso7816TLV.java
@@ -125,7 +125,7 @@ public class Iso7816TLV {
public static Iso7816TLV[] readList(byte[] data, boolean recursive) throws IOException {
ByteBuffer buf = ByteBuffer.wrap(data);
- ArrayList<Iso7816TLV> result = new ArrayList<Iso7816TLV>();
+ ArrayList<Iso7816TLV> result = new ArrayList<>();
// read while data is available. this will fail if there is trailing data!
while (buf.hasRemaining()) {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/KeyUpdateHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/KeyUpdateHelper.java
index 76ec9f75f..943b913d7 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/KeyUpdateHelper.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/KeyUpdateHelper.java
@@ -17,21 +17,6 @@
package org.sufficientlysecure.keychain.util;
-import android.content.Context;
-import android.content.Intent;
-import android.os.AsyncTask;
-import android.os.Bundle;
-import android.os.Messenger;
-
-import org.sufficientlysecure.keychain.keyimport.ImportKeysListEntry;
-import org.sufficientlysecure.keychain.provider.KeychainContract;
-import org.sufficientlysecure.keychain.provider.ProviderHelper;
-import org.sufficientlysecure.keychain.service.KeychainIntentService;
-import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
-
-import java.util.ArrayList;
-import java.util.List;
-
public class KeyUpdateHelper {
/*
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Log.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Log.java
index b4f7c5767..8b165cd57 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Log.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Log.java
@@ -21,9 +21,6 @@ import android.os.Bundle;
import org.sufficientlysecure.keychain.Constants;
-import java.io.IOException;
-import java.io.StreamTokenizer;
-import java.io.StringReader;
import java.util.Iterator;
import java.util.Set;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ParcelableFileCache.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ParcelableFileCache.java
index 3081021cf..5de682fe6 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ParcelableFileCache.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ParcelableFileCache.java
@@ -32,9 +32,7 @@ import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
-import java.util.ArrayList;
import java.util.Iterator;
-import java.util.List;
/**
* When sending large data (over 1MB) through Androids Binder IPC you get
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 5efd6c419..8d4af58d7 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Preferences.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Preferences.java
@@ -200,7 +200,7 @@ public class Preferences {
public String[] getKeyServers() {
String rawData = mSharedPreferences.getString(Constants.Pref.KEY_SERVERS,
Constants.Defaults.KEY_SERVERS);
- Vector<String> servers = new Vector<String>();
+ Vector<String> servers = new Vector<>();
String chunks[] = rawData.split(",");
for (String c : chunks) {
String tmp = c.trim();
@@ -281,7 +281,7 @@ public class Preferences {
case 3: {
// migrate keyserver to hkps
String[] serversArray = getKeyServers();
- ArrayList<String> servers = new ArrayList<String>(Arrays.asList(serversArray));
+ ArrayList<String> servers = new ArrayList<>(Arrays.asList(serversArray));
ListIterator<String> it = servers.listIterator();
while (it.hasNext()) {
String server = it.next();
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ShareHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ShareHelper.java
index 51e58565f..120b84a3b 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ShareHelper.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ShareHelper.java
@@ -43,16 +43,18 @@ public class ShareHelper {
* Put together from some stackoverflow posts...
*/
public Intent createChooserExcluding(Intent prototype, String title, String[] activityBlacklist) {
- // Produced an empty list on Huawei U8860 with Android Version 4.0.3 and weird results on 2.3
+ // Produced an empty list on Huawei U8860 with Android Version 4.0.3
// TODO: test on 4.1, 4.2, 4.3, only tested on 4.4
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
+ // Disabled on 5.0 because using EXTRA_INITIAL_INTENTS prevents the usage based sorting
+ // introduced in 5.0: https://medium.com/@xXxXxXxXxXam/how-lollipops-share-menu-is-organized-d204888f606d
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT || Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
return Intent.createChooser(prototype, title);
}
- List<LabeledIntent> targetedShareIntents = new ArrayList<LabeledIntent>();
+ List<LabeledIntent> targetedShareIntents = new ArrayList<>();
List<ResolveInfo> resInfoList = mContext.getPackageManager().queryIntentActivities(prototype, 0);
- List<ResolveInfo> resInfoListFiltered = new ArrayList<ResolveInfo>();
+ List<ResolveInfo> resInfoListFiltered = new ArrayList<>();
if (!resInfoList.isEmpty()) {
for (ResolveInfo resolveInfo : resInfoList) {
// do not add blacklisted ones
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/TlsHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/TlsHelper.java
index 9946d81aa..7e318281d 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/TlsHelper.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/TlsHelper.java
@@ -50,7 +50,7 @@ public class TlsHelper {
}
}
- private static Map<String, byte[]> sStaticCA = new HashMap<String, byte[]>();
+ private static Map<String, byte[]> sStaticCA = new HashMap<>();
public static void addStaticCA(String domain, byte[] certificate) {
sStaticCA.put(domain, certificate);
@@ -120,13 +120,7 @@ public class TlsHelper {
urlConnection.setSSLSocketFactory(context.getSocketFactory());
return urlConnection;
- } catch (CertificateException e) {
- throw new TlsHelperException(e);
- } catch (NoSuchAlgorithmException e) {
- throw new TlsHelperException(e);
- } catch (KeyStoreException e) {
- throw new TlsHelperException(e);
- } catch (KeyManagementException e) {
+ } catch (CertificateException | KeyManagementException | KeyStoreException | NoSuchAlgorithmException e) {
throw new TlsHelperException(e);
}
}
diff --git a/OpenKeychain/src/main/res/drawable-hdpi/ic_action_collapse.png b/OpenKeychain/src/main/res/drawable-hdpi/ic_action_collapse.png
deleted file mode 100644
index e9d2dcb46..000000000
--- a/OpenKeychain/src/main/res/drawable-hdpi/ic_action_collapse.png
+++ /dev/null
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-hdpi/ic_action_expand.png b/OpenKeychain/src/main/res/drawable-hdpi/ic_action_expand.png
deleted file mode 100644
index 29f4de211..000000000
--- a/OpenKeychain/src/main/res/drawable-hdpi/ic_action_expand.png
+++ /dev/null
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-hdpi/ic_apps_black_24dp.png b/OpenKeychain/src/main/res/drawable-hdpi/ic_apps_black_24dp.png
new file mode 100644
index 000000000..37931a0ad
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-hdpi/ic_apps_black_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-hdpi/ic_check_white_24dp.png b/OpenKeychain/src/main/res/drawable-hdpi/ic_check_white_24dp.png
new file mode 100644
index 000000000..f42a0e2d2
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-hdpi/ic_check_white_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-hdpi/ic_close_white_24dp.png b/OpenKeychain/src/main/res/drawable-hdpi/ic_close_white_24dp.png
new file mode 100644
index 000000000..0fd15563a
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-hdpi/ic_close_white_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-hdpi/ic_cloud_search_24px.png b/OpenKeychain/src/main/res/drawable-hdpi/ic_cloud_search_24px.png
new file mode 100644
index 000000000..6f9b343ad
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-hdpi/ic_cloud_search_24px.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-hdpi/ic_expand_less_black_24dp.png b/OpenKeychain/src/main/res/drawable-hdpi/ic_expand_less_black_24dp.png
new file mode 100644
index 000000000..35e3b426f
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-hdpi/ic_expand_less_black_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-hdpi/ic_expand_more_black_24dp.png b/OpenKeychain/src/main/res/drawable-hdpi/ic_expand_more_black_24dp.png
new file mode 100644
index 000000000..ed993f35d
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-hdpi/ic_expand_more_black_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-hdpi/ic_lock_open_black_24dp.png b/OpenKeychain/src/main/res/drawable-hdpi/ic_lock_open_black_24dp.png
new file mode 100644
index 000000000..8ac075245
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-hdpi/ic_lock_open_black_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-hdpi/ic_lock_outline_black_24dp.png b/OpenKeychain/src/main/res/drawable-hdpi/ic_lock_outline_black_24dp.png
new file mode 100644
index 000000000..fc019db72
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-hdpi/ic_lock_outline_black_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-hdpi/ic_refresh_white_24dp.png b/OpenKeychain/src/main/res/drawable-hdpi/ic_refresh_white_24dp.png
new file mode 100644
index 000000000..cd16fdd50
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-hdpi/ic_refresh_white_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-hdpi/ic_settings_black_24dp.png b/OpenKeychain/src/main/res/drawable-hdpi/ic_settings_black_24dp.png
new file mode 100644
index 000000000..b16209fc1
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-hdpi/ic_settings_black_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-hdpi/ic_vpn_key_black_24dp.png b/OpenKeychain/src/main/res/drawable-hdpi/ic_vpn_key_black_24dp.png
new file mode 100644
index 000000000..c900b8ec7
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-hdpi/ic_vpn_key_black_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-mdpi/ic_action_collapse.png b/OpenKeychain/src/main/res/drawable-mdpi/ic_action_collapse.png
deleted file mode 100644
index 4ac28f270..000000000
--- a/OpenKeychain/src/main/res/drawable-mdpi/ic_action_collapse.png
+++ /dev/null
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-mdpi/ic_action_expand.png b/OpenKeychain/src/main/res/drawable-mdpi/ic_action_expand.png
deleted file mode 100644
index bb46bb315..000000000
--- a/OpenKeychain/src/main/res/drawable-mdpi/ic_action_expand.png
+++ /dev/null
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-mdpi/ic_apps_black_24dp.png b/OpenKeychain/src/main/res/drawable-mdpi/ic_apps_black_24dp.png
new file mode 100644
index 000000000..5b1fd7766
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-mdpi/ic_apps_black_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-mdpi/ic_check_white_24dp.png b/OpenKeychain/src/main/res/drawable-mdpi/ic_check_white_24dp.png
new file mode 100644
index 000000000..e91f9048b
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-mdpi/ic_check_white_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-mdpi/ic_close_white_24dp.png b/OpenKeychain/src/main/res/drawable-mdpi/ic_close_white_24dp.png
new file mode 100644
index 000000000..e80681aeb
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-mdpi/ic_close_white_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-mdpi/ic_cloud_search_24px.png b/OpenKeychain/src/main/res/drawable-mdpi/ic_cloud_search_24px.png
new file mode 100644
index 000000000..7a69993fd
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-mdpi/ic_cloud_search_24px.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-mdpi/ic_expand_less_black_24dp.png b/OpenKeychain/src/main/res/drawable-mdpi/ic_expand_less_black_24dp.png
new file mode 100644
index 000000000..a5ab2c5d3
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-mdpi/ic_expand_less_black_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-mdpi/ic_expand_more_black_24dp.png b/OpenKeychain/src/main/res/drawable-mdpi/ic_expand_more_black_24dp.png
new file mode 100644
index 000000000..73fc3b422
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-mdpi/ic_expand_more_black_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-mdpi/ic_lock_open_black_24dp.png b/OpenKeychain/src/main/res/drawable-mdpi/ic_lock_open_black_24dp.png
new file mode 100644
index 000000000..9e6d0f0ac
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-mdpi/ic_lock_open_black_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-mdpi/ic_lock_outline_black_24dp.png b/OpenKeychain/src/main/res/drawable-mdpi/ic_lock_outline_black_24dp.png
new file mode 100644
index 000000000..1df91994c
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-mdpi/ic_lock_outline_black_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-mdpi/ic_refresh_white_24dp.png b/OpenKeychain/src/main/res/drawable-mdpi/ic_refresh_white_24dp.png
new file mode 100644
index 000000000..235c84f1e
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-mdpi/ic_refresh_white_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-mdpi/ic_settings_black_24dp.png b/OpenKeychain/src/main/res/drawable-mdpi/ic_settings_black_24dp.png
new file mode 100644
index 000000000..3405c951d
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-mdpi/ic_settings_black_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-mdpi/ic_vpn_key_black_24dp.png b/OpenKeychain/src/main/res/drawable-mdpi/ic_vpn_key_black_24dp.png
new file mode 100644
index 000000000..5e8781731
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-mdpi/ic_vpn_key_black_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/ic_action_collapse.png b/OpenKeychain/src/main/res/drawable-xhdpi/ic_action_collapse.png
deleted file mode 100644
index 60ac6b066..000000000
--- a/OpenKeychain/src/main/res/drawable-xhdpi/ic_action_collapse.png
+++ /dev/null
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/ic_action_expand.png b/OpenKeychain/src/main/res/drawable-xhdpi/ic_action_expand.png
deleted file mode 100644
index 76937f57a..000000000
--- a/OpenKeychain/src/main/res/drawable-xhdpi/ic_action_expand.png
+++ /dev/null
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/ic_apps_black_24dp.png b/OpenKeychain/src/main/res/drawable-xhdpi/ic_apps_black_24dp.png
new file mode 100644
index 000000000..c8187799b
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xhdpi/ic_apps_black_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/ic_check_white_24dp.png b/OpenKeychain/src/main/res/drawable-xhdpi/ic_check_white_24dp.png
new file mode 100644
index 000000000..e5024472a
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xhdpi/ic_check_white_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/ic_close_white_24dp.png b/OpenKeychain/src/main/res/drawable-xhdpi/ic_close_white_24dp.png
new file mode 100644
index 000000000..76e07f097
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xhdpi/ic_close_white_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/ic_cloud_search_24px.png b/OpenKeychain/src/main/res/drawable-xhdpi/ic_cloud_search_24px.png
new file mode 100644
index 000000000..1f0db264a
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xhdpi/ic_cloud_search_24px.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/ic_expand_less_black_24dp.png b/OpenKeychain/src/main/res/drawable-xhdpi/ic_expand_less_black_24dp.png
new file mode 100644
index 000000000..47c7b52a1
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xhdpi/ic_expand_less_black_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/ic_expand_more_black_24dp.png b/OpenKeychain/src/main/res/drawable-xhdpi/ic_expand_more_black_24dp.png
new file mode 100644
index 000000000..45d30d999
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xhdpi/ic_expand_more_black_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/ic_lock_open_black_24dp.png b/OpenKeychain/src/main/res/drawable-xhdpi/ic_lock_open_black_24dp.png
new file mode 100644
index 000000000..9cd050100
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xhdpi/ic_lock_open_black_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/ic_lock_outline_black_24dp.png b/OpenKeychain/src/main/res/drawable-xhdpi/ic_lock_outline_black_24dp.png
new file mode 100644
index 000000000..ae48a3bf7
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xhdpi/ic_lock_outline_black_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/ic_refresh_white_24dp.png b/OpenKeychain/src/main/res/drawable-xhdpi/ic_refresh_white_24dp.png
new file mode 100644
index 000000000..5f89fc257
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xhdpi/ic_refresh_white_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/ic_settings_black_24dp.png b/OpenKeychain/src/main/res/drawable-xhdpi/ic_settings_black_24dp.png
new file mode 100644
index 000000000..2b775b646
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xhdpi/ic_settings_black_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/ic_vpn_key_black_24dp.png b/OpenKeychain/src/main/res/drawable-xhdpi/ic_vpn_key_black_24dp.png
new file mode 100644
index 000000000..ccbdce4ab
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xhdpi/ic_vpn_key_black_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/ic_action_collapse.png b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_action_collapse.png
deleted file mode 100644
index 76ec594dc..000000000
--- a/OpenKeychain/src/main/res/drawable-xxhdpi/ic_action_collapse.png
+++ /dev/null
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/ic_action_expand.png b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_action_expand.png
deleted file mode 100644
index 22003198b..000000000
--- a/OpenKeychain/src/main/res/drawable-xxhdpi/ic_action_expand.png
+++ /dev/null
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/ic_apps_black_24dp.png b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_apps_black_24dp.png
new file mode 100644
index 000000000..626543b47
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_apps_black_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/ic_check_white_24dp.png b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_check_white_24dp.png
new file mode 100644
index 000000000..6e03d54cf
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_check_white_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/ic_close_white_24dp.png b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_close_white_24dp.png
new file mode 100644
index 000000000..0eb9d8b08
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_close_white_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/ic_cloud_search_24px.png b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_cloud_search_24px.png
new file mode 100644
index 000000000..852cdc2a6
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_cloud_search_24px.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/ic_expand_less_black_24dp.png b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_expand_less_black_24dp.png
new file mode 100644
index 000000000..0470e3f02
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_expand_less_black_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/ic_expand_more_black_24dp.png b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_expand_more_black_24dp.png
new file mode 100644
index 000000000..aadd04af6
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_expand_more_black_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/ic_lock_open_black_24dp.png b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_lock_open_black_24dp.png
new file mode 100644
index 000000000..529a7724b
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_lock_open_black_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/ic_lock_outline_black_24dp.png b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_lock_outline_black_24dp.png
new file mode 100644
index 000000000..cf149aa37
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_lock_outline_black_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/ic_refresh_white_24dp.png b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_refresh_white_24dp.png
new file mode 100644
index 000000000..72128fe69
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_refresh_white_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/ic_settings_black_24dp.png b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_settings_black_24dp.png
new file mode 100644
index 000000000..47f0e0d82
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_settings_black_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/ic_vpn_key_black_24dp.png b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_vpn_key_black_24dp.png
new file mode 100644
index 000000000..736bde37a
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_vpn_key_black_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_apps_black_24dp.png b/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_apps_black_24dp.png
new file mode 100644
index 000000000..d12d2e796
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_apps_black_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_check_white_24dp.png b/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_check_white_24dp.png
new file mode 100644
index 000000000..87892840e
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_check_white_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_close_white_24dp.png b/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_close_white_24dp.png
new file mode 100644
index 000000000..7b2a480a0
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_close_white_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_expand_less_black_24dp.png b/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_expand_less_black_24dp.png
new file mode 100644
index 000000000..08ae54533
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_expand_less_black_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_expand_more_black_24dp.png b/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_expand_more_black_24dp.png
new file mode 100644
index 000000000..228b2a982
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_expand_more_black_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_lock_open_black_24dp.png b/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_lock_open_black_24dp.png
new file mode 100644
index 000000000..a0fe0156f
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_lock_open_black_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_lock_outline_black_24dp.png b/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_lock_outline_black_24dp.png
new file mode 100644
index 000000000..7460e0894
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_lock_outline_black_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_refresh_white_24dp.png b/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_refresh_white_24dp.png
new file mode 100644
index 000000000..d271d8e03
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_refresh_white_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_settings_black_24dp.png b/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_settings_black_24dp.png
new file mode 100644
index 000000000..bce161d00
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_settings_black_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_vpn_key_black_24dp.png b/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_vpn_key_black_24dp.png
new file mode 100644
index 000000000..3451d9855
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_vpn_key_black_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/layout/actionbar_custom_view_done.xml b/OpenKeychain/src/main/res/layout/actionbar_custom_view_done.xml
deleted file mode 100644
index b219038b2..000000000
--- a/OpenKeychain/src/main/res/layout/actionbar_custom_view_done.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<!--
- Copyright 2013 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:dividerPadding="12dp"
- android:orientation="horizontal"
- android:showDividers="end" >
-
- <include layout="@layout/actionbar_include_done_button" />
-
-</LinearLayout> \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/layout/actionbar_custom_view_done_cancel.xml b/OpenKeychain/src/main/res/layout/actionbar_custom_view_done_cancel.xml
deleted file mode 100644
index e9047e759..000000000
--- a/OpenKeychain/src/main/res/layout/actionbar_custom_view_done_cancel.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<!--
- Copyright 2013 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:dividerPadding="12dp"
- android:orientation="horizontal"
- android:showDividers="middle">
-
- <include layout="@layout/actionbar_include_cancel_button" />
-
- <include layout="@layout/actionbar_include_done_button" />
-
-</LinearLayout> \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/layout/custom_drawer.xml b/OpenKeychain/src/main/res/layout/custom_drawer.xml
new file mode 100644
index 000000000..021226ba3
--- /dev/null
+++ b/OpenKeychain/src/main/res/layout/custom_drawer.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:gravity="center"
+ android:background="@color/colorPrimary">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:text="@string/app_name"
+ android:textColor="@color/white"
+ android:layout_gravity="center_horizontal" />
+</LinearLayout> \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/layout/foldable_linearlayout.xml b/OpenKeychain/src/main/res/layout/foldable_linearlayout.xml
index 13cf7c225..d6165c1e0 100644
--- a/OpenKeychain/src/main/res/layout/foldable_linearlayout.xml
+++ b/OpenKeychain/src/main/res/layout/foldable_linearlayout.xml
@@ -17,7 +17,7 @@
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginRight="10dp"
- android:src="@drawable/ic_action_expand"/>
+ android:src="@drawable/ic_expand_more_black_24dp"/>
<TextView
android:id="@+id/foldableText"
diff --git a/OpenKeychain/src/main/res/layout/full_screen_dialog.xml b/OpenKeychain/src/main/res/layout/full_screen_dialog.xml
new file mode 100644
index 000000000..5eb50da07
--- /dev/null
+++ b/OpenKeychain/src/main/res/layout/full_screen_dialog.xml
@@ -0,0 +1,10 @@
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:dividerPadding="12dp"
+ android:orientation="horizontal"
+ android:showDividers="middle">
+
+ <include layout="@layout/full_screen_dialog_done_button" />
+
+</LinearLayout> \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/layout/full_screen_dialog_2.xml b/OpenKeychain/src/main/res/layout/full_screen_dialog_2.xml
new file mode 100644
index 000000000..b1d5efe76
--- /dev/null
+++ b/OpenKeychain/src/main/res/layout/full_screen_dialog_2.xml
@@ -0,0 +1,12 @@
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:dividerPadding="12dp"
+ android:orientation="horizontal"
+ android:showDividers="middle">
+
+ <include layout="@layout/full_screen_dialog_2_cancel_button" />
+
+ <include layout="@layout/full_screen_dialog_2_done_button" />
+
+</LinearLayout> \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/layout/actionbar_include_cancel_button.xml b/OpenKeychain/src/main/res/layout/full_screen_dialog_2_cancel_button.xml
index ec27e394a..7c2c2a62d 100644
--- a/OpenKeychain/src/main/res/layout/actionbar_include_cancel_button.xml
+++ b/OpenKeychain/src/main/res/layout/full_screen_dialog_2_cancel_button.xml
@@ -1,19 +1,3 @@
-<!--
- Copyright 2013 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/actionbar_cancel"
style="@style/Widget.AppCompat.ActionButton"
@@ -30,12 +14,14 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
- android:drawableLeft="@drawable/ic_action_cancel"
+ android:drawableLeft="@drawable/ic_close_white_24dp"
android:drawablePadding="8dp"
android:gravity="center_vertical"
android:paddingRight="20dp"
android:filterTouchesWhenObscured="true"
style="@style/Widget.AppCompat.Light.ActionBar.TabText"
+ android:textAllCaps="true"
+ android:textSize="14sp"
android:text="Cancel (set in-code!)" />
</FrameLayout> \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/layout/actionbar_include_done_button.xml b/OpenKeychain/src/main/res/layout/full_screen_dialog_2_done_button.xml
index 2590f272c..cd24a1e6d 100644
--- a/OpenKeychain/src/main/res/layout/actionbar_include_done_button.xml
+++ b/OpenKeychain/src/main/res/layout/full_screen_dialog_2_done_button.xml
@@ -1,19 +1,3 @@
-<!--
- Copyright 2013 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/actionbar_done"
style="@style/Widget.AppCompat.ActionButton"
@@ -30,12 +14,14 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
- android:drawableLeft="@drawable/ic_action_done"
+ android:drawableLeft="@drawable/ic_check_white_24dp"
android:drawablePadding="8dp"
android:gravity="center_vertical"
android:paddingRight="20dp"
android:filterTouchesWhenObscured="true"
style="@style/Widget.AppCompat.Light.ActionBar.TabText"
+ android:textAllCaps="true"
+ android:textSize="14sp"
android:text="Done (set in-code!)" />
</FrameLayout> \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/layout/full_screen_dialog_done_button.xml b/OpenKeychain/src/main/res/layout/full_screen_dialog_done_button.xml
new file mode 100644
index 000000000..49018fee1
--- /dev/null
+++ b/OpenKeychain/src/main/res/layout/full_screen_dialog_done_button.xml
@@ -0,0 +1,25 @@
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/full_screen_dialog_done"
+ style="@style/Widget.AppCompat.ActionButton"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent">
+
+ <!--
+ android:filterTouchesWhenObscured="true" to prevent Touch-Event Hijacking
+ https://blog.lookout.com/blog/2010/12/09/android-touch-event-hijacking/
+ -->
+ <TextView
+ android:id="@+id/full_screen_dialog_done_text"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:layout_gravity="center"
+ android:gravity="center_vertical"
+ android:paddingRight="16dp"
+ android:paddingEnd="16dp"
+ style="@style/Widget.AppCompat.Light.ActionBar.TabText"
+ android:textAllCaps="true"
+ android:textSize="14sp"
+ android:filterTouchesWhenObscured="true"
+ android:text="Done (set in-code!)" />
+
+</FrameLayout> \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/layout/full_screen_dialog_old.xml b/OpenKeychain/src/main/res/layout/full_screen_dialog_old.xml
new file mode 100644
index 000000000..ed375094f
--- /dev/null
+++ b/OpenKeychain/src/main/res/layout/full_screen_dialog_old.xml
@@ -0,0 +1,10 @@
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:dividerPadding="12dp"
+ android:orientation="horizontal"
+ android:showDividers="end" >
+
+ <include layout="@layout/full_screen_dialog_2_done_button" />
+
+</LinearLayout> \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/menu/key_list.xml b/OpenKeychain/src/main/res/menu/key_list.xml
index f61172a0a..8a682badc 100644
--- a/OpenKeychain/src/main/res/menu/key_list.xml
+++ b/OpenKeychain/src/main/res/menu/key_list.xml
@@ -11,13 +11,12 @@
<item
android:id="@+id/menu_key_list_search_cloud"
- android:icon="@drawable/ic_action_search_cloud"
+ android:icon="@drawable/ic_cloud_search_24px"
android:title="@string/menu_search_cloud"
app:showAsAction="ifRoom|withText" />
<item
android:id="@+id/menu_key_list_add"
- android:icon="@drawable/ic_action_qr_code"
android:title="@string/import_qr_code_button"
app:showAsAction="ifRoom|withText" />
diff --git a/OpenKeychain/src/main/res/values/strings.xml b/OpenKeychain/src/main/res/values/strings.xml
index de2a77f62..1151644d8 100644
--- a/OpenKeychain/src/main/res/values/strings.xml
+++ b/OpenKeychain/src/main/res/values/strings.xml
@@ -20,7 +20,7 @@
<string name="title_preferences">"Settings"</string>
<string name="title_cloud_search_preferences">"Cloud Search Preferences"</string>
<string name="title_api_registered_apps">"Apps"</string>
- <string name="title_key_server_preference">"Keyserver Preference"</string>
+ <string name="title_key_server_preference">"Keyservers"</string>
<string name="title_change_passphrase">"Change Passphrase"</string>
<string name="title_share_fingerprint_with">"Share fingerprint with…"</string>
<string name="title_share_key">"Share key with…"</string>
@@ -41,6 +41,7 @@
<string name="title_create_key">"Create Key"</string>
<string name="title_exchange_keys">"Exchange Keys"</string>
<string name="title_advanced_key_info">"Advanced Key Info"</string>
+ <string name="title_keys">"Keys"</string>
<!-- section -->
<string name="section_user_ids">"Identities"</string>
@@ -826,6 +827,7 @@
<!-- modifySecretKeyRing -->
<string name="msg_mr">"Modifying keyring %s"</string>
+ <string name="msg_mf_error_divert_serial">"The serial number of a divert-to-card key must be 16 bytes! This is a programming error, please file a bug report!"</string>
<string name="msg_mf_error_encode">"Encoding exception!"</string>
<string name="msg_mf_error_fingerprint">"Actual key fingerprint does not match the expected one!"</string>
<string name="msg_mf_error_keyid">"No key ID. This is an internal error, please file a bug report!"</string>
@@ -833,6 +835,7 @@
<string name="msg_mf_error_master_none">"No master certificate found to operate on! (All revoked?)"</string>
<string name="msg_mf_error_noexist_primary">"Bad primary user ID specified!"</string>
<string name="msg_mf_error_noexist_revoke">"Bad user ID for revocation specified!"</string>
+ <string name="msg_mf_error_restricted">"Tried to execute restricted operation without passphrase! This is a programming error, please file a bug report!"</string>
<string name="msg_mf_error_revoked_primary">"Revoked user IDs cannot be primary!"</string>
<string name="msg_mf_error_null_expiry">"Expiry time cannot be "same as before" on subkey creation. This is a programming error, please file a bug report!"</string>
<string name="msg_mf_error_passphrase_master">"Fatal error decrypting master key! This is likely a programming error, please file a bug report!"</string>
@@ -905,6 +908,13 @@
<string name="msg_ed_fetching">"Fetching key to modify (%s)"</string>
<string name="msg_ed_success">"Key operation successful"</string>
+ <!-- Promote key -->
+ <string name="msg_pr">"Promoting public key to secret key"</string>
+ <string name="msg_pr_error_already_secret">"Key is already a secret key!"</string>
+ <string name="msg_pr_error_key_not_found">"Key not found!"</string>
+ <string name="msg_pr_fetching">"Fetching key to modify (%s)"</string>
+ <string name="msg_pr_success">"Key successfully promoted"</string>
+
<!-- Other messages used in OperationLogs -->
<string name="msg_ek_error_divert">"Editing of NFC keys is not (yet) supported!"</string>
<string name="msg_ek_error_dummy">"Cannot edit keyring with stripped master key!"</string>
@@ -914,6 +924,7 @@
<string name="msg_dc_askip_no_key">"Data not encrypted with known key, skipping…"</string>
<string name="msg_dc_askip_not_allowed">"Data not encrypted with allowed key, skipping…"</string>
<string name="msg_dc_asym">"Found block of asymmetrically encrypted data for key %s"</string>
+ <string name="msg_dc_charset">"Found charset header: '%s'"</string>
<string name="msg_dc_clear_data">"Processing literal data"</string>
<string name="msg_dc_clear_decompress">"Unpacking compressed data"</string>
<string name="msg_dc_clear_meta_file">"Filename: %s"</string>
@@ -1012,6 +1023,7 @@
<string name="msg_import_fingerprint_ok">"Fingerprint check OK"</string>
<string name="msg_import_merge">"Merging retrieved data"</string>
<string name="msg_import_error">"Import operation failed!"</string>
+ <string name="msg_import_error_io">"Import operation failed due to i/o error!"</string>
<string name="msg_import_partial">"Import operation successful, with errors!"</string>
<string name="msg_import_success">"Import operation successful!"</string>
diff --git a/OpenKeychain/src/main/res/values/themes.xml b/OpenKeychain/src/main/res/values/themes.xml
index 602c85247..3b7d66963 100644
--- a/OpenKeychain/src/main/res/values/themes.xml
+++ b/OpenKeychain/src/main/res/values/themes.xml
@@ -9,6 +9,19 @@
<item name="android:windowNoTitle">true</item>
<item name="windowActionBar">false</item>
<item name="searchViewStyle">@style/MySearchViewStyle</item>
+ <item name="colorAccent">@color/accent</item>
+
+ <!-- Navigation Drawer library -->
+ <item name="drawerType">@integer/DRAWERTYPE_CUSTOM</item>
+ <item name="theme">@style/ThemeOverlay.AppCompat.Dark.ActionBar</item>
+ <item name="popupTheme">@style/Base.V21.Theme.AppCompat.Light.Dialog</item>
+ <item name="drawerColor">#fafafa</item>
+ <item name="singleAccount">false</item>
+ <item name="sectionStyle">@style/MaterialSectionTheme.Light</item>
+ <item name="subheaderStyle">@style/MaterialSubheaderTheme.Light</item>
+ <item name="multipaneSupport">false</item>
+ <item name="rippleBackport">false</item>
+ <item name="uniqueToolbarColor">false</item>
</style>
<!-- http://android-developers.blogspot.de/2014/10/appcompat-v21-material-design-for-pre.html -->
@@ -18,7 +31,7 @@
<!-- Background for the actions section (e.g. voice, submit) -->
<!--<item name="submitBackground">...</item>-->
<!-- Close button icon -->
- <!--<item name="closeIcon">...</item>-->
+ <item name="closeIcon">@drawable/ic_close_white_24dp</item>
<!-- Search button icon -->
<!--<item name="searchIcon">...</item>-->
<!-- Go/commit button icon -->