aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVincent Breitmoser <valodim@mugenguild.com>2015-09-14 16:21:04 +0200
committerVincent Breitmoser <valodim@mugenguild.com>2015-09-14 16:21:04 +0200
commit3814ae7d53a22ba89f1e39d7a4661016f76cf8c8 (patch)
treed83d41d3c424a784da144515665fb41ef650aa52
parentdbaf7070ead596f5c70ad48fc55aada2f77a856a (diff)
parentd5dd6a49c8156a699b3fbbbeef06658e1c232c16 (diff)
downloadopen-keychain-3814ae7d53a22ba89f1e39d7a4661016f76cf8c8.tar.gz
open-keychain-3814ae7d53a22ba89f1e39d7a4661016f76cf8c8.tar.bz2
open-keychain-3814ae7d53a22ba89f1e39d7a4661016f76cf8c8.zip
Merge branch 'master' into mime4j
Conflicts: OpenKeychain/build.gradle OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptListFragment.java OpenKeychain/src/main/res/values/strings.xml
-rw-r--r--.tx/config2
-rw-r--r--Graphics/drawables/account_key.svg1
-rw-r--r--Graphics/drawables/link.svg1
-rw-r--r--Graphics/drawables/linked_dns.svg4
-rw-r--r--Graphics/drawables/linked_github.svg4
-rw-r--r--Graphics/drawables/linked_https.svg4
-rw-r--r--Graphics/drawables/linked_twitter.svg4
-rw-r--r--Graphics/drawables/octo_link.svg3
-rw-r--r--Graphics/drawables/status_signature_verified_inner.svg77
-rwxr-xr-xGraphics/get-material-icons.sh8
-rwxr-xr-xGraphics/update-drawables.sh6
-rw-r--r--OpenKeychain/build.gradle22
-rw-r--r--OpenKeychain/src/debug/res/mipmap-hdpi/ic_launcher.png (renamed from OpenKeychain/src/debug/res/drawable-hdpi/ic_launcher.png)bin6863 -> 6863 bytes
-rw-r--r--OpenKeychain/src/debug/res/mipmap-mdpi/ic_launcher.png (renamed from OpenKeychain/src/debug/res/drawable-mdpi/ic_launcher.png)bin4609 -> 4609 bytes
-rw-r--r--OpenKeychain/src/debug/res/mipmap-xhdpi/ic_launcher.png (renamed from OpenKeychain/src/debug/res/drawable-xhdpi/ic_launcher.png)bin8887 -> 8887 bytes
-rw-r--r--OpenKeychain/src/debug/res/mipmap-xxhdpi/ic_launcher.png (renamed from OpenKeychain/src/debug/res/drawable-xxhdpi/ic_launcher.png)bin13422 -> 13422 bytes
-rw-r--r--OpenKeychain/src/debug/res/mipmap-xxxhdpi/ic_launcher.png (renamed from OpenKeychain/src/debug/res/drawable-xxxhdpi/ic_launcher.png)bin16655 -> 16655 bytes
-rw-r--r--OpenKeychain/src/main/AndroidManifest.xml49
-rw-r--r--OpenKeychain/src/main/assets/word_confirm_list.txt12032
-rw-r--r--OpenKeychain/src/main/java/android/support/v4/widget/FlingNestedScrollView.java1355
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java27
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java12
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/HkpKeyserver.java8
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/linked/LinkedAttribute.java32
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/linked/LinkedResource.java25
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/linked/LinkedTokenResource.java300
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/linked/UriAttribute.java79
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/linked/resources/DnsResource.java130
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/linked/resources/GenericHttpsResource.java95
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/linked/resources/GithubResource.java218
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/linked/resources/TwitterResource.java250
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ExportOperation.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ImportOperation.java153
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/KeybaseVerificationOperation.java4
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/RevokeOperation.java52
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/LinkedVerifyResult.java49
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java117
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedKeyRing.java12
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerifyOperation.java (renamed from OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java)693
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpHelper.java32
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSecurityConstants.java74
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java11
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedPublicKey.java1
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedUserAttribute.java8
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java32
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java18
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java83
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java97
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java189
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService2.java72
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AppsListFragment.java4
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/SelectSignKeyIdActivity.java25
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/CertifyActionsParcel.java16
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ContactSyncAdapterService.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainService.java4
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeyserverSyncAdapterService.java516
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java8
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BackupFragment.java38
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyFingerprintActivity.java9
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyFingerprintFragment.java47
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyFragment.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptActivity.java25
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptListFragment.java140
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DeleteKeyDialogActivity.java1
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptDecryptOverviewFragment.java6
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java26
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysFileFragment.java4
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java14
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LogDisplayFragment.java189
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcOperationActivity.java29
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/OrbotRequiredDialogActivity.java63
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java73
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseWizardActivity.java577
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsActivity.java190
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsKeyServerActivity.java14
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java157
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvActivity.java6
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvUserIdsFragment.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyFragment.java164
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyKeybaseFragment.java (renamed from OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyTrustFragment.java)171
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyAdapter.java3
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/LinkedIdsAdapter.java238
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/LinkedIdsCertAdapter.java57
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/MultiUserIdsAdapter.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SelectKeyCursorAdapter.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserAttributesAdapter.java19
-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/base/BaseActivity.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/CryptoOperationFragment.java12
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/CryptoOperationHelper.java26
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/FileDialogFragment.java22
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateFinalFragment.java225
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateGithubFragment.java706
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateHttpsStep1Fragment.java127
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateHttpsStep2Fragment.java172
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateTwitterStep1Fragment.java132
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateTwitterStep2Fragment.java121
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdSelectFragment.java105
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdViewFragment.java560
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdWizard.java164
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/ExperimentalWordConfirm.java126
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/KeyFormattingUtils.java4
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/SubtleAttentionSeeker.java24
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/ThemeChanger.java4
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/CertListWidget.java143
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/CertifyKeySpinner.java18
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java14
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/PrefixedEditText.java45
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/StatusIndicator.java45
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ExportHelper.java9
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/FileHelper.java197
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/FilterCursorWrapper.java76
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Preferences.java61
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/orbot/OrbotHelper.java36
-rw-r--r--OpenKeychain/src/main/res/anim/fade_in_down.xml11
-rw-r--r--OpenKeychain/src/main/res/anim/fade_in_quick.xml7
-rw-r--r--OpenKeychain/src/main/res/anim/fade_in_up.xml11
-rw-r--r--OpenKeychain/src/main/res/anim/fade_out_down.xml11
-rw-r--r--OpenKeychain/src/main/res/anim/fade_out_quick.xml7
-rw-r--r--OpenKeychain/src/main/res/anim/fade_out_up.xml11
-rw-r--r--OpenKeychain/src/main/res/drawable-hdpi/account_key.pngbin0 -> 1078 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-hdpi/ic_cloud_black_24dp.pngbin0 -> 296 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-hdpi/ic_extension_black_24dp.pngbin0 -> 329 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-hdpi/ic_ic_stat_tor.pngbin0 -> 920 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-hdpi/ic_repeat_black_24dp.pngbin0 -> 183 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-hdpi/ic_settings_ethernet_black_24dp.pngbin0 -> 350 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-hdpi/ic_stat_tor.pngbin0 -> 920 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-hdpi/ic_stat_tor_off.pngbin0 -> 1090 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-hdpi/ic_sync_black_24dp.pngbin0 -> 368 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-hdpi/link_24dp.pngbin0 -> 597 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-hdpi/linked_dns.pngbin0 -> 667 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-hdpi/linked_github.pngbin0 -> 1437 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-hdpi/linked_https.pngbin0 -> 1345 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-hdpi/linked_twitter.pngbin0 -> 1265 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-hdpi/octo_link_24dp.pngbin0 -> 792 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-hdpi/status_signature_verified_inner_24dp.pngbin0 -> 544 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-hdpi/status_signature_verified_inner_96dp.pngbin0 -> 2031 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-mdpi/account_key.pngbin0 -> 678 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-mdpi/ic_cloud_black_24dp.pngbin0 -> 212 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-mdpi/ic_extension_black_24dp.pngbin0 -> 224 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-mdpi/ic_ic_stat_tor.pngbin0 -> 540 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-mdpi/ic_repeat_black_24dp.pngbin0 -> 122 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-mdpi/ic_settings_ethernet_black_24dp.pngbin0 -> 253 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-mdpi/ic_stat_tor.pngbin0 -> 540 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-mdpi/ic_stat_tor_off.pngbin0 -> 727 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-mdpi/ic_sync_black_24dp.pngbin0 -> 250 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-mdpi/link_24dp.pngbin0 -> 357 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-mdpi/linked_dns.pngbin0 -> 371 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-mdpi/linked_github.pngbin0 -> 999 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-mdpi/linked_https.pngbin0 -> 1010 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-mdpi/linked_twitter.pngbin0 -> 880 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-mdpi/octo_link_24dp.pngbin0 -> 556 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-mdpi/status_signature_verified_inner_24dp.pngbin0 -> 429 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-mdpi/status_signature_verified_inner_96dp.pngbin0 -> 1437 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xhdpi/account_key.pngbin0 -> 1414 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xhdpi/ic_cloud_black_24dp.pngbin0 -> 357 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xhdpi/ic_extension_black_24dp.pngbin0 -> 331 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xhdpi/ic_ic_stat_tor.pngbin0 -> 1188 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xhdpi/ic_repeat_black_24dp.pngbin0 -> 168 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xhdpi/ic_settings_ethernet_black_24dp.pngbin0 -> 447 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xhdpi/ic_stat_tor.pngbin0 -> 1188 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xhdpi/ic_stat_tor_off.pngbin0 -> 2037 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xhdpi/ic_sync_black_24dp.pngbin0 -> 467 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xhdpi/link_24dp.pngbin0 -> 719 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xhdpi/linked_dns.pngbin0 -> 736 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xhdpi/linked_github.pngbin0 -> 2153 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xhdpi/linked_https.pngbin0 -> 1955 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xhdpi/linked_twitter.pngbin0 -> 1916 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xhdpi/octo_link_24dp.pngbin0 -> 888 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xhdpi/status_signature_expired_cutout_96dp.pngbin4973 -> 0 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xhdpi/status_signature_verified_inner_24dp.pngbin0 -> 717 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xhdpi/status_signature_verified_inner_96dp.pngbin0 -> 3022 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xxhdpi/account_key.pngbin0 -> 2266 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xxhdpi/ic_cloud_black_24dp.pngbin0 -> 518 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xxhdpi/ic_extension_black_24dp.pngbin0 -> 495 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xxhdpi/ic_ic_stat_tor.pngbin0 -> 2589 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xxhdpi/ic_repeat_black_24dp.pngbin0 -> 214 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xxhdpi/ic_settings_ethernet_black_24dp.pngbin0 -> 649 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xxhdpi/ic_stat_tor.pngbin0 -> 2589 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xxhdpi/ic_stat_tor_off.pngbin0 -> 3776 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xxhdpi/ic_sync_black_24dp.pngbin0 -> 669 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xxhdpi/link_24dp.pngbin0 -> 1087 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xxhdpi/linked_dns.pngbin0 -> 1498 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xxhdpi/linked_github.pngbin0 -> 3179 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xxhdpi/linked_https.pngbin0 -> 3222 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xxhdpi/linked_twitter.pngbin0 -> 2666 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xxhdpi/octo_link_24dp.pngbin0 -> 1554 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xxhdpi/status_signature_verified_inner_24dp.pngbin0 -> 1095 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xxhdpi/status_signature_verified_inner_96dp.pngbin0 -> 4214 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xxxhdpi/ic_cloud_black_24dp.pngbin0 -> 669 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xxxhdpi/ic_extension_black_24dp.pngbin0 -> 605 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xxxhdpi/ic_ic_stat_tor.pngbin0 -> 4105 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xxxhdpi/ic_repeat_black_24dp.pngbin0 -> 243 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xxxhdpi/ic_settings_ethernet_black_24dp.pngbin0 -> 894 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xxxhdpi/ic_stat_tor.pngbin0 -> 4105 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xxxhdpi/ic_stat_tor_off.pngbin0 -> 5960 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xxxhdpi/ic_sync_black_24dp.pngbin0 -> 875 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xxxhdpi/link_24dp.pngbin0 -> 1418 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xxxhdpi/octo_link_24dp.pngbin0 -> 1952 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xxxhdpi/status_signature_verified_inner_24dp.pngbin0 -> 1437 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable/divider.xml11
-rw-r--r--OpenKeychain/src/main/res/drawable/scrim_bottom.xml8
-rw-r--r--OpenKeychain/src/main/res/layout/api_app_settings_activity.xml4
-rw-r--r--OpenKeychain/src/main/res/layout/api_app_settings_fragment.xml4
-rw-r--r--OpenKeychain/src/main/res/layout/api_apps_adapter_list_item.xml4
-rw-r--r--OpenKeychain/src/main/res/layout/cert_list_widget.xml44
-rw-r--r--OpenKeychain/src/main/res/layout/certify_fingerprint_fragment.xml1
-rw-r--r--OpenKeychain/src/main/res/layout/decrypt_text_fragment.xml10
-rw-r--r--OpenKeychain/src/main/res/layout/help_about_fragment.xml2
-rw-r--r--OpenKeychain/src/main/res/layout/key_list_fragment.xml6
-rw-r--r--OpenKeychain/src/main/res/layout/keyspinner_item_none.xml6
-rw-r--r--OpenKeychain/src/main/res/layout/linked_create_github_fragment.xml235
-rw-r--r--OpenKeychain/src/main/res/layout/linked_create_https_fragment_step1.xml129
-rw-r--r--OpenKeychain/src/main/res/layout/linked_create_https_fragment_step2.xml165
-rw-r--r--OpenKeychain/src/main/res/layout/linked_create_twitter_fragment_step1.xml123
-rw-r--r--OpenKeychain/src/main/res/layout/linked_create_twitter_fragment_step2.xml154
-rw-r--r--OpenKeychain/src/main/res/layout/linked_create_verify.xml78
-rw-r--r--OpenKeychain/src/main/res/layout/linked_id_item.xml75
-rw-r--r--OpenKeychain/src/main/res/layout/linked_id_view_fragment.xml193
-rw-r--r--OpenKeychain/src/main/res/layout/linked_select_fragment.xml188
-rw-r--r--OpenKeychain/src/main/res/layout/loader_layout.xml10
-rw-r--r--OpenKeychain/src/main/res/layout/main_activity.xml2
-rw-r--r--OpenKeychain/src/main/res/layout/nfc_operation_activity.xml4
-rw-r--r--OpenKeychain/src/main/res/layout/oauth_webview.xml12
-rw-r--r--OpenKeychain/src/main/res/layout/status_indicator.xml30
-rw-r--r--OpenKeychain/src/main/res/layout/toolbar_inner_layout.xml2
-rw-r--r--OpenKeychain/src/main/res/layout/toolbar_inner_layout_white.xml2
-rw-r--r--OpenKeychain/src/main/res/layout/view_key_activity.xml383
-rw-r--r--OpenKeychain/src/main/res/layout/view_key_adv_keybase_fragment.xml169
-rw-r--r--OpenKeychain/src/main/res/layout/view_key_adv_keybase_proof.xml4
-rw-r--r--OpenKeychain/src/main/res/layout/view_key_fragment.xml193
-rw-r--r--OpenKeychain/src/main/res/menu/decrypt_item_context_menu.xml6
-rw-r--r--OpenKeychain/src/main/res/menu/decrypt_menu.xml2
-rw-r--r--OpenKeychain/src/main/res/menu/key_view.xml13
-rw-r--r--OpenKeychain/src/main/res/menu/log_display.xml4
-rw-r--r--OpenKeychain/src/main/res/mipmap-hdpi/ic_launcher.png (renamed from OpenKeychain/src/main/res/drawable-hdpi/ic_launcher.png)bin6885 -> 6885 bytes
-rw-r--r--OpenKeychain/src/main/res/mipmap-mdpi/ic_launcher.png (renamed from OpenKeychain/src/main/res/drawable-mdpi/ic_launcher.png)bin4641 -> 4641 bytes
-rw-r--r--OpenKeychain/src/main/res/mipmap-xhdpi/ic_launcher.png (renamed from OpenKeychain/src/main/res/drawable-xhdpi/ic_launcher.png)bin8916 -> 8916 bytes
-rw-r--r--OpenKeychain/src/main/res/mipmap-xxhdpi/ic_launcher.png (renamed from OpenKeychain/src/main/res/drawable-xxhdpi/ic_launcher.png)bin13548 -> 13548 bytes
-rw-r--r--OpenKeychain/src/main/res/mipmap-xxxhdpi/ic_launcher.png (renamed from OpenKeychain/src/main/res/drawable-xxxhdpi/ic_launcher.png)bin16742 -> 16742 bytes
-rw-r--r--OpenKeychain/src/main/res/raw-bg/help_about.md65
-rw-r--r--OpenKeychain/src/main/res/raw-bg/help_certification.md28
-rw-r--r--OpenKeychain/src/main/res/raw-bg/help_changelog.md283
-rw-r--r--OpenKeychain/src/main/res/raw-bg/help_start.md16
-rw-r--r--OpenKeychain/src/main/res/raw-cs/help_about.md37
-rw-r--r--OpenKeychain/src/main/res/raw-cs/help_changelog.md7
-rw-r--r--OpenKeychain/src/main/res/raw-de/help_about.md37
-rw-r--r--OpenKeychain/src/main/res/raw-de/help_changelog.md119
-rw-r--r--OpenKeychain/src/main/res/raw-de/help_start.md8
-rw-r--r--OpenKeychain/src/main/res/raw-es/help_about.md39
-rw-r--r--OpenKeychain/src/main/res/raw-es/help_changelog.md13
-rw-r--r--OpenKeychain/src/main/res/raw-et/help_about.md37
-rw-r--r--OpenKeychain/src/main/res/raw-et/help_changelog.md7
-rw-r--r--OpenKeychain/src/main/res/raw-eu/help_about.md37
-rw-r--r--OpenKeychain/src/main/res/raw-eu/help_certification.md12
-rw-r--r--OpenKeychain/src/main/res/raw-eu/help_changelog.md85
-rw-r--r--OpenKeychain/src/main/res/raw-fa/help_about.md (renamed from OpenKeychain/src/main/res/raw-ar/help_about.md)49
-rw-r--r--OpenKeychain/src/main/res/raw-fa/help_certification.md (renamed from OpenKeychain/src/main/res/raw-is/help_certification.md)6
-rw-r--r--OpenKeychain/src/main/res/raw-fa/help_changelog.md (renamed from OpenKeychain/src/main/res/raw-ar/help_changelog.md)21
-rw-r--r--OpenKeychain/src/main/res/raw-fa/help_start.md16
-rw-r--r--OpenKeychain/src/main/res/raw-fi/help_about.md37
-rw-r--r--OpenKeychain/src/main/res/raw-fi/help_changelog.md7
-rw-r--r--OpenKeychain/src/main/res/raw-fr/help_about.md37
-rw-r--r--OpenKeychain/src/main/res/raw-fr/help_changelog.md13
-rw-r--r--OpenKeychain/src/main/res/raw-hu/help_about.md (renamed from OpenKeychain/src/main/res/raw-is/help_about.md)37
-rw-r--r--OpenKeychain/src/main/res/raw-hu/help_certification.md (renamed from OpenKeychain/src/main/res/raw-ar/help_certification.md)0
-rw-r--r--OpenKeychain/src/main/res/raw-hu/help_changelog.md (renamed from OpenKeychain/src/main/res/raw-is/help_changelog.md)7
-rw-r--r--OpenKeychain/src/main/res/raw-hu/help_start.md (renamed from OpenKeychain/src/main/res/raw-ar/help_start.md)0
-rw-r--r--OpenKeychain/src/main/res/raw-is/help_start.md16
-rw-r--r--OpenKeychain/src/main/res/raw-it/help_about.md37
-rw-r--r--OpenKeychain/src/main/res/raw-it/help_changelog.md7
-rw-r--r--OpenKeychain/src/main/res/raw-ja/help_about.md37
-rw-r--r--OpenKeychain/src/main/res/raw-ja/help_changelog.md13
-rw-r--r--OpenKeychain/src/main/res/raw-kn/help_about.md65
-rw-r--r--OpenKeychain/src/main/res/raw-kn/help_certification.md28
-rw-r--r--OpenKeychain/src/main/res/raw-kn/help_changelog.md283
-rw-r--r--OpenKeychain/src/main/res/raw-kn/help_start.md16
-rw-r--r--OpenKeychain/src/main/res/raw-nl/help_about.md37
-rw-r--r--OpenKeychain/src/main/res/raw-nl/help_changelog.md13
-rw-r--r--OpenKeychain/src/main/res/raw-pl/help_about.md37
-rw-r--r--OpenKeychain/src/main/res/raw-pl/help_changelog.md7
-rw-r--r--OpenKeychain/src/main/res/raw-pt/help_about.md65
-rw-r--r--OpenKeychain/src/main/res/raw-pt/help_certification.md28
-rw-r--r--OpenKeychain/src/main/res/raw-pt/help_changelog.md283
-rw-r--r--OpenKeychain/src/main/res/raw-pt/help_start.md16
-rw-r--r--OpenKeychain/src/main/res/raw-ro/help_about.md65
-rw-r--r--OpenKeychain/src/main/res/raw-ro/help_certification.md28
-rw-r--r--OpenKeychain/src/main/res/raw-ro/help_changelog.md283
-rw-r--r--OpenKeychain/src/main/res/raw-ro/help_start.md16
-rw-r--r--OpenKeychain/src/main/res/raw-ru/help_about.md37
-rw-r--r--OpenKeychain/src/main/res/raw-ru/help_certification.md2
-rw-r--r--OpenKeychain/src/main/res/raw-ru/help_changelog.md7
-rw-r--r--OpenKeychain/src/main/res/raw-ru/help_start.md4
-rw-r--r--OpenKeychain/src/main/res/raw-sl/help_about.md37
-rw-r--r--OpenKeychain/src/main/res/raw-sl/help_changelog.md7
-rw-r--r--OpenKeychain/src/main/res/raw-sr/help_about.md37
-rw-r--r--OpenKeychain/src/main/res/raw-sr/help_certification.md12
-rw-r--r--OpenKeychain/src/main/res/raw-sr/help_changelog.md13
-rw-r--r--OpenKeychain/src/main/res/raw-sv/help_about.md37
-rw-r--r--OpenKeychain/src/main/res/raw-sv/help_changelog.md7
-rw-r--r--OpenKeychain/src/main/res/raw-tr/help_about.md37
-rw-r--r--OpenKeychain/src/main/res/raw-tr/help_changelog.md7
-rw-r--r--OpenKeychain/src/main/res/raw-uk/help_about.md37
-rw-r--r--OpenKeychain/src/main/res/raw-uk/help_changelog.md7
-rw-r--r--OpenKeychain/src/main/res/raw-vi/help_about.md65
-rw-r--r--OpenKeychain/src/main/res/raw-vi/help_certification.md28
-rw-r--r--OpenKeychain/src/main/res/raw-vi/help_changelog.md283
-rw-r--r--OpenKeychain/src/main/res/raw-vi/help_start.md16
-rw-r--r--OpenKeychain/src/main/res/raw-zh-rTW/help_about.md37
-rw-r--r--OpenKeychain/src/main/res/raw-zh-rTW/help_changelog.md13
-rw-r--r--OpenKeychain/src/main/res/raw-zh/help_about.md37
-rw-r--r--OpenKeychain/src/main/res/raw-zh/help_changelog.md7
-rw-r--r--OpenKeychain/src/main/res/raw/help_about.md35
-rw-r--r--OpenKeychain/src/main/res/raw/help_changelog.md7
-rw-r--r--OpenKeychain/src/main/res/transition/linked_id_card_trans.xml4
-rw-r--r--OpenKeychain/src/main/res/values-bg/strings.xml78
-rw-r--r--OpenKeychain/src/main/res/values-cs/strings.xml22
-rw-r--r--OpenKeychain/src/main/res/values-de/strings.xml810
-rw-r--r--OpenKeychain/src/main/res/values-es/strings.xml145
-rw-r--r--OpenKeychain/src/main/res/values-et/strings.xml9
-rw-r--r--OpenKeychain/src/main/res/values-eu/strings.xml254
-rw-r--r--OpenKeychain/src/main/res/values-fa/strings.xml333
-rw-r--r--OpenKeychain/src/main/res/values-fi/strings.xml10
-rw-r--r--OpenKeychain/src/main/res/values-fr/strings.xml194
-rw-r--r--OpenKeychain/src/main/res/values-hu/strings.xml (renamed from OpenKeychain/src/main/res/values-ar/strings.xml)7
-rw-r--r--OpenKeychain/src/main/res/values-is/strings.xml78
-rw-r--r--OpenKeychain/src/main/res/values-it/strings.xml37
-rw-r--r--OpenKeychain/src/main/res/values-ja/strings.xml410
-rw-r--r--OpenKeychain/src/main/res/values-kn/strings.xml78
-rw-r--r--OpenKeychain/src/main/res/values-nl/strings.xml62
-rw-r--r--OpenKeychain/src/main/res/values-pl/strings.xml13
-rw-r--r--OpenKeychain/src/main/res/values-pt/strings.xml78
-rw-r--r--OpenKeychain/src/main/res/values-ro/strings.xml78
-rw-r--r--OpenKeychain/src/main/res/values-ru/strings.xml256
-rw-r--r--OpenKeychain/src/main/res/values-sl/strings.xml22
-rw-r--r--OpenKeychain/src/main/res/values-sr/strings.xml564
-rw-r--r--OpenKeychain/src/main/res/values-sv/strings.xml22
-rw-r--r--OpenKeychain/src/main/res/values-tr/strings.xml13
-rw-r--r--OpenKeychain/src/main/res/values-uk/strings.xml13
-rw-r--r--OpenKeychain/src/main/res/values-vi/strings.xml78
-rw-r--r--OpenKeychain/src/main/res/values-zh-rTW/strings.xml192
-rw-r--r--OpenKeychain/src/main/res/values-zh/strings.xml45
-rw-r--r--OpenKeychain/src/main/res/values/arrays.xml6
-rw-r--r--OpenKeychain/src/main/res/values/attr.xml4
-rw-r--r--OpenKeychain/src/main/res/values/colors.xml4
-rw-r--r--OpenKeychain/src/main/res/values/strings.xml235
-rw-r--r--OpenKeychain/src/main/res/values/styles.xml4
-rw-r--r--OpenKeychain/src/main/res/values/themes.xml18
-rw-r--r--OpenKeychain/src/main/res/xml/account_desc.xml2
-rw-r--r--OpenKeychain/src/main/res/xml/cloud_search_prefs.xml4
-rw-r--r--OpenKeychain/src/main/res/xml/experimental_preferences.xml37
-rw-r--r--OpenKeychain/src/main/res/xml/keyserver_sync_adapter_desc.xml8
-rw-r--r--OpenKeychain/src/main/res/xml/passphrase_preferences.xml (renamed from OpenKeychain/src/main/res/xml/adv_preferences.xml)0
-rw-r--r--OpenKeychain/src/main/res/xml/preference_headers.xml21
-rw-r--r--OpenKeychain/src/main/res/xml/proxy_prefs.xml6
-rw-r--r--OpenKeychain/src/main/res/xml/sync_preferences.xml10
-rw-r--r--OpenKeychain/src/test/java/org/sufficientlysecure/keychain/operations/CertifyOperationTest.java10
-rw-r--r--OpenKeychain/src/test/java/org/sufficientlysecure/keychain/operations/PromoteKeyOperationTest.java2
-rw-r--r--OpenKeychain/src/test/java/org/sufficientlysecure/keychain/pgp/PgpEncryptDecryptTest.java90
-rw-r--r--OpenKeychain/src/test/java/org/sufficientlysecure/keychain/pgp/UncachedKeyringMergeTest.java2
-rw-r--r--OpenKeychain/src/test/java/org/sufficientlysecure/keychain/provider/ProviderHelperSaveTest.java2
-rw-r--r--OpenKeychain/src/test/java/org/sufficientlysecure/keychain/support/KeyringTestingHelper.java2
-rw-r--r--OpenKeychain/src/test/java/org/sufficientlysecure/keychain/util/KeyFormattingUtilsTest.java46
m---------extern/openpgp-api-lib0
365 files changed, 26155 insertions, 6323 deletions
diff --git a/.tx/config b/.tx/config
index 16292a787..f3a8543aa 100644
--- a/.tx/config
+++ b/.tx/config
@@ -1,6 +1,6 @@
[main]
host = https://www.transifex.com
-lang_map = af_ZA: af-rZA, am_ET: am-rET, ar_AE: ar-rAE, ar_BH: ar-rBH, ar_DZ: ar-rDZ, ar_EG: ar-rEG, ar_IQ: ar-rIQ, ar_JO: ar-rJO, ar_KW: ar-rKW, ar_LB: ar-rLB, ar_LY: ar-rLY, ar_MA: ar-rMA, ar_OM: ar-rOM, ar_QA: ar-rQA, ar_SA: ar-rSA, ar_SY: ar-rSY, ar_TN: ar-rTN, ar_YE: ar-rYE, arn_CL: arn-rCL, as_IN: as-rIN, az_AZ: az-rAZ, ba_RU: ba-rRU, be_BY: be-rBY, bg_BG: bg-rBG, bn_BD: bn-rBD, bn_IN: bn-rIN, bo_CN: bo-rCN, br_FR: br-rFR, bs_BA: bs-rBA, ca_ES: ca-rES, co_FR: co-rFR, cs_CZ: cs-rCZ, cy_GB: cy-rGB, da_DK: da-rDK, de_AT: de-rAT, de_CH: de-rCH, de_DE: de-rDE, de_LI: de-rLI, de_LU: de-rLU, dsb_DE: dsb-rDE, dv_MV: dv-rMV, el_GR: el-rGR, en_AU: en-rAU, en_BZ: en-rBZ, en_CA: en-rCA, en_GB: en-rGB, en_IE: en-rIE, en_IN: en-rIN, en_JM: en-rJM, en_MY: en-rMY, en_NZ: en-rNZ, en_PH: en-rPH, en_SG: en-rSG, en_TT: en-rTT, en_US: en-rUS, en_ZA: en-rZA, en_ZW: en-rZW, es_AR: es-rAR, es_BO: es-rBO, es_CL: es-rCL, es_CO: es-rCO, es_CR: es-rCR, es_DO: es-rDO, es_EC: es-rEC, es_ES: es-rES, es_GT: es-rGT, es_HN: es-rHN, es_MX: es-rMX, es_NI: es-rNI, es_PA: es-rPA, es_PE: es-rPE, es_PR: es-rPR, es_PY: es-rPY, es_SV: es-rSV, es_US: es-rUS, es_UY: es-rUY, es_VE: es-rVE, et_EE: et-rEE, eu_ES: eu-rES, fa_IR: fa-rIR, fi_FI: fi-rFI, fil_PH: fil-rPH, fo_FO: fo-rFO, fr_BE: fr-rBE, fr_CA: fr-rCA, fr_CH: fr-rCH, fr_FR: fr-rFR, fr_LU: fr-rLU, fr_MC: fr-rMC, fy_NL: fy-rNL, ga_IE: ga-rIE, gd_GB: gd-rGB, gl_ES: gl-rES, gsw_FR: gsw-rFR, gu_IN: gu-rIN, ha_NG: ha-rNG, hi_IN: hi-rIN, hr_BA: hr-rBA, hr_HR: hr-rHR, hsb_DE: hsb-rDE, hu_HU: hu-rHU, hy_AM: hy-rAM, id_ID: id-rID, ig_NG: ig-rNG, ii_CN: ii-rCN, is_IS: is-rIS, it_CH: it-rCH, it_IT: it-rIT, iu_CA: iu-rCA, ja_JP: ja-rJP, ka_GE: ka-rGE, kk_KZ: kk-rKZ, kl_GL: kl-rGL, km_KH: km-rKH, kn_IN: kn-rIN, ko_KR: ko-rKR, kok_IN: kok-rIN, ky_KG: ky-rKG, lb_LU: lb-rLU, lo_LA: lo-rLA, lt_LT: lt-rLT, lv_LV: lv-rLV, mi_NZ: mi-rNZ, mk_MK: mk-rMK, ml_IN: ml-rIN, mn_CN: mn-rCN, mn_MN: mn-rMN, moh_CA: moh-rCA, mr_IN: mr-rIN, ms_BN: ms-rBN, ms_MY: ms-rMY, mt_MT: mt-rMT, nb_NO: nb-rNO, ne_NP: ne-rNP, nl_BE: nl-rBE, nl_NL: nl-rNL, nn_NO: nn-rNO, nso_ZA: nso-rZA, oc_FR: oc-rFR, or_IN: or-rIN, pa_IN: pa-rIN, pl_PL: pl-rPL, prs_AF: prs-rAF, ps_AF: ps-rAF, pt_BR: pt-rBR, pt_PT: pt-rPT, qut_GT: qut-rGT, quz_BO: quz-rBO, quz_EC: quz-rEC, quz_PE: quz-rPE, rm_CH: rm-rCH, ro_RO: ro-rRO, ru_RU: ru-rRU, rw_RW: rw-rRW, sa_IN: sa-rIN, sah_RU: sah-rRU, se_FI: se-rFI, se_NO: se-rNO, se_SE: se-rSE, si_LK: si-rLK, sk_SK: sk-rSK, sl_SI: sl-rSI, sma_NO: sma-rNO, sma_SE: sma-rSE, smj_NO: smj-rNO, smj_SE: smj-rSE, smn_FI: smn-rFI, sms_FI: sms-rFI, sq_AL: sq-rAL, sr_BA: sr-rBA, sr_CS: sr-rCS, sr_ME: sr-rME, sr_RS: sr-rRS, sv_FI: sv-rFI, sv_SE: sv-rSE, sw_KE: sw-rKE, syr_SY: syr-rSY, ta_IN: ta-rIN, te_IN: te-rIN, tg_TJ: tg-rTJ, th_TH: th-rTH, tk_TM: tk-rTM, tn_ZA: tn-rZA, tr_TR: tr-rTR, tt_RU: tt-rRU, tzm_DZ: tzm-rDZ, ug_CN: ug-rCN, uk_UA: uk-rUA, ur_PK: ur-rPK, uz_UZ: uz-rUZ, vi_VN: vi-rVN, wo_SN: wo-rSN, xh_ZA: xh-rZA, yo_NG: yo-rNG, zh_CN: zh-rCN, zh_HK: zh-rHK, zh_MO: zh-rMO, zh_SG: zh-rSG, zh_TW: zh-rTW, zu_ZA: zu-rZA, no_NO: no-rNO, he_IL: iw-rIL, he: iw
+lang_map = he: iw, zh_TW: zh-rTW
[open-keychain.strings]
file_filter = OpenKeychain/src/main/res/values-<lang>/strings.xml
diff --git a/Graphics/drawables/account_key.svg b/Graphics/drawables/account_key.svg
new file mode 100644
index 000000000..d4965a384
--- /dev/null
+++ b/Graphics/drawables/account_key.svg
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M11,10V12H10V14H8V12H5.83C5.42,13.17 4.31,14 3,14A3,3 0 0,1 0,11A3,3 0 0,1 3,8C4.31,8 5.42,8.83 5.83,10H11M3,10A1,1 0 0,0 2,11A1,1 0 0,0 3,12A1,1 0 0,0 4,11A1,1 0 0,0 3,10M16,14C18.67,14 24,15.34 24,18V20H8V18C8,15.34 13.33,14 16,14M16,12A4,4 0 0,1 12,8A4,4 0 0,1 16,4A4,4 0 0,1 20,8A4,4 0 0,1 16,12Z" /></svg> \ No newline at end of file
diff --git a/Graphics/drawables/link.svg b/Graphics/drawables/link.svg
new file mode 100644
index 000000000..11d3be9b2
--- /dev/null
+++ b/Graphics/drawables/link.svg
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M16,6H13V7.9H16C18.26,7.9 20.1,9.73 20.1,12A4.1,4.1 0 0,1 16,16.1H13V18H16A6,6 0 0,0 22,12C22,8.68 19.31,6 16,6M3.9,12C3.9,9.73 5.74,7.9 8,7.9H11V6H8A6,6 0 0,0 2,12A6,6 0 0,0 8,18H11V16.1H8C5.74,16.1 3.9,14.26 3.9,12M8,13H16V11H8V13Z" /></svg> \ No newline at end of file
diff --git a/Graphics/drawables/linked_dns.svg b/Graphics/drawables/linked_dns.svg
new file mode 100644
index 000000000..c04c265c2
--- /dev/null
+++ b/Graphics/drawables/linked_dns.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg viewBox="0 0 24 24">
+ <path fill="#000000" d="M7,9A2,2 0 0,1 5,7A2,2 0 0,1 7,5A2,2 0 0,1 9,7A2,2 0 0,1 7,9M20,3H4A1,1 0 0,0 3,4V10A1,1 0 0,0 4,11H20A1,1 0 0,0 21,10V4A1,1 0 0,0 20,3M7,19A2,2 0 0,1 5,17A2,2 0 0,1 7,15A2,2 0 0,1 9,17A2,2 0 0,1 7,19M20,13H4A1,1 0 0,0 3,14V20A1,1 0 0,0 4,21H20A1,1 0 0,0 21,20V14A1,1 0 0,0 20,13Z" />
+</svg>
diff --git a/Graphics/drawables/linked_github.svg b/Graphics/drawables/linked_github.svg
new file mode 100644
index 000000000..11f4076d5
--- /dev/null
+++ b/Graphics/drawables/linked_github.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg viewBox="0 0 24 24">
+ <path fill="#000000" d="M12,2A10,10 0 0,0 2,12C2,16.42 4.87,20.17 8.84,21.5C9.34,21.58 9.5,21.27 9.5,21C9.5,20.77 9.5,20.14 9.5,19.31C6.73,19.91 6.14,17.97 6.14,17.97C5.68,16.81 5.03,16.5 5.03,16.5C4.12,15.88 5.1,15.9 5.1,15.9C6.1,15.97 6.63,16.93 6.63,16.93C7.5,18.45 8.97,18 9.54,17.76C9.63,17.11 9.89,16.67 10.17,16.42C7.95,16.17 5.62,15.31 5.62,11.5C5.62,10.39 6,9.5 6.65,8.79C6.55,8.54 6.2,7.5 6.75,6.15C6.75,6.15 7.59,5.88 9.5,7.17C10.29,6.95 11.15,6.84 12,6.84C12.85,6.84 13.71,6.95 14.5,7.17C16.41,5.88 17.25,6.15 17.25,6.15C17.8,7.5 17.45,8.54 17.35,8.79C18,9.5 18.38,10.39 18.38,11.5C18.38,15.32 16.04,16.16 13.81,16.41C14.17,16.72 14.5,17.33 14.5,18.26C14.5,19.6 14.5,20.68 14.5,21C14.5,21.27 14.66,21.59 15.17,21.5C19.14,20.16 22,16.42 22,12A10,10 0 0,0 12,2Z" />
+</svg>
diff --git a/Graphics/drawables/linked_https.svg b/Graphics/drawables/linked_https.svg
new file mode 100644
index 000000000..876f46276
--- /dev/null
+++ b/Graphics/drawables/linked_https.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg viewBox="0 0 24 24">
+ <path fill="#000000" d="M16.36,14C16.44,13.34 16.5,12.68 16.5,12C16.5,11.32 16.44,10.66 16.36,10H19.74C19.9,10.64 20,11.31 20,12C20,12.69 19.9,13.36 19.74,14M14.59,19.56C15.19,18.45 15.65,17.25 15.97,16H18.92C17.96,17.65 16.43,18.93 14.59,19.56M14.34,14H9.66C9.56,13.34 9.5,12.68 9.5,12C9.5,11.32 9.56,10.65 9.66,10H14.34C14.43,10.65 14.5,11.32 14.5,12C14.5,12.68 14.43,13.34 14.34,14M12,19.96C11.17,18.76 10.5,17.43 10.09,16H13.91C13.5,17.43 12.83,18.76 12,19.96M8,8H5.08C6.03,6.34 7.57,5.06 9.4,4.44C8.8,5.55 8.35,6.75 8,8M5.08,16H8C8.35,17.25 8.8,18.45 9.4,19.56C7.57,18.93 6.03,17.65 5.08,16M4.26,14C4.1,13.36 4,12.69 4,12C4,11.31 4.1,10.64 4.26,10H7.64C7.56,10.66 7.5,11.32 7.5,12C7.5,12.68 7.56,13.34 7.64,14M12,4.03C12.83,5.23 13.5,6.57 13.91,8H10.09C10.5,6.57 11.17,5.23 12,4.03M18.92,8H15.97C15.65,6.75 15.19,5.55 14.59,4.44C16.43,5.07 17.96,6.34 18.92,8M12,2C6.47,2 2,6.5 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2Z" />
+</svg>
diff --git a/Graphics/drawables/linked_twitter.svg b/Graphics/drawables/linked_twitter.svg
new file mode 100644
index 000000000..38028f2e9
--- /dev/null
+++ b/Graphics/drawables/linked_twitter.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg viewBox="0 0 24 24">
+ <path fill="#000000" d="M22.46,6C21.69,6.35 20.86,6.58 20,6.69C20.88,6.16 21.56,5.32 21.88,4.31C21.05,4.81 20.13,5.16 19.16,5.36C18.37,4.5 17.26,4 16,4C13.65,4 11.73,5.92 11.73,8.29C11.73,8.63 11.77,8.96 11.84,9.27C8.28,9.09 5.11,7.38 3,4.79C2.63,5.42 2.42,6.16 2.42,6.94C2.42,8.43 3.17,9.75 4.33,10.5C3.62,10.5 2.96,10.3 2.38,10C2.38,10 2.38,10 2.38,10.03C2.38,12.11 3.86,13.85 5.82,14.24C5.46,14.34 5.08,14.39 4.69,14.39C4.42,14.39 4.15,14.36 3.89,14.31C4.43,16 6,17.26 7.89,17.29C6.43,18.45 4.58,19.13 2.56,19.13C2.22,19.13 1.88,19.11 1.54,19.07C3.44,20.29 5.7,21 8.12,21C16,21 20.33,14.46 20.33,8.79C20.33,8.6 20.33,8.42 20.32,8.23C21.16,7.63 21.88,6.87 22.46,6Z" />
+</svg>
diff --git a/Graphics/drawables/octo_link.svg b/Graphics/drawables/octo_link.svg
new file mode 100644
index 000000000..5a56a8825
--- /dev/null
+++ b/Graphics/drawables/octo_link.svg
@@ -0,0 +1,3 @@
+<svg height="1024" width="1024" xmlns="http://www.w3.org/2000/svg">
+ <path d="M256 576h64v64h-64c-96 0-192-108-192-224s99-224 192-224h256c93 0 192 108 192 224 0 90-58 174-128 208v-74c37-29 64-81 64-134 0-82-65-160-128-160H256c-63 0-128 78-128 160s64 160 128 160z m576-192h-64v64h64c64 0 128 78 128 160s-65 160-128 160H576c-63 0-128-78-128-160 0-53 27-105 64-134v-74c-70 34-128 118-128 208 0 116 99 224 192 224h256c93 0 192-108 192-224s-96-224-192-224z" />
+</svg>
diff --git a/Graphics/drawables/status_signature_verified_inner.svg b/Graphics/drawables/status_signature_verified_inner.svg
new file mode 100644
index 000000000..554df0643
--- /dev/null
+++ b/Graphics/drawables/status_signature_verified_inner.svg
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:sketch="http://www.bohemiancoding.com/sketch/ns"
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="100px"
+ height="100px"
+ viewBox="0 0 100 100"
+ version="1.1"
+ id="svg2"
+ inkscape:version="0.48.5 r10040"
+ sodipodi:docname="status_signature_verified_cutout.svg">
+ <metadata
+ id="metadata16">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>signature-verified-cutout</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1280"
+ inkscape:window-height="784"
+ id="namedview14"
+ showgrid="false"
+ inkscape:zoom="2.36"
+ inkscape:cx="50"
+ inkscape:cy="50"
+ inkscape:window-x="0"
+ inkscape:window-y="16"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="signature-verified-cutout" />
+ <!-- Generator: Sketch 3.0.4 (8053) - http://www.bohemiancoding.com/sketch -->
+ <title
+ id="title4">signature-verified-cutout</title>
+ <desc
+ id="desc6">Created with Sketch.</desc>
+ <defs
+ id="defs8" />
+ <g
+ id="Page-1"
+ sketch:type="MSPage"
+ stroke-width="1"
+ stroke="none"
+ fill-rule="evenodd"
+ fill="none">
+ <g
+ id="signature-verified-cutout"
+ sketch:type="MSArtboardGroup"
+ transform="translate(0.110156, 0.000000)"
+ fill="#000000">
+ <path
+ d="M 46.273291,77.5085 20,57.830916 27.91844,47.63497 43.309686,59.515226 70.31112,23 80.867825,30.778219 z"
+ sketch:type="MSShapeGroup"
+ id="path12"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccc" />
+ </g>
+ </g>
+</svg>
diff --git a/Graphics/get-material-icons.sh b/Graphics/get-material-icons.sh
index 758ddc8aa..67370afc2 100755
--- a/Graphics/get-material-icons.sh
+++ b/Graphics/get-material-icons.sh
@@ -9,6 +9,7 @@ python copy OpenKeychain navigation black expand_more 24
python copy OpenKeychain navigation white refresh 24
python copy OpenKeychain av white repeat 24
python copy OpenKeychain av grey repeat 24
+python copy OpenKeychain av black repeat 24
python copy OpenKeychain editor white mode_edit 24
python copy OpenKeychain content white save 24
python copy OpenKeychain navigation black close 24
@@ -63,3 +64,10 @@ python copy OpenKeychain action white delete 24
# yubikey dialog
python copy OpenKeychain action black check_circle 48
+
+# preference header
+python copy OpenKeychain file black cloud 24 # cloud
+python copy OpenKeychain action black lock 24 # password settings
+python copy OpenKeychain action black settings_ethernet 24 # proxy
+python copy OpenKeychain notification black sync 24 # sync
+python copy OpenKeychain action black extension 24 # experimental
diff --git a/Graphics/update-drawables.sh b/Graphics/update-drawables.sh
index 5acfba19a..7dcf1d60f 100755
--- a/Graphics/update-drawables.sh
+++ b/Graphics/update-drawables.sh
@@ -22,7 +22,7 @@ SRC_DIR=./drawables/
#inkscape -w 512 -h 512 -e "$PLAY_DIR/$NAME.png" $NAME.svg
-for NAME in "ic_cloud_search" "ic_action_encrypt_file" "ic_action_encrypt_text" "ic_action_verified_cutout" "ic_action_encrypt_copy" "ic_action_encrypt_save" "ic_action_encrypt_share" "status_lock_closed" "status_lock_error" "status_lock_open" "status_signature_expired_cutout" "status_signature_invalid_cutout" "status_signature_revoked_cutout" "status_signature_unknown_cutout" "status_signature_unverified_cutout" "status_signature_verified_cutout" "key_flag_authenticate" "key_flag_certify" "key_flag_encrypt" "key_flag_sign" "yubi_icon" "ic_stat_notify"
+for NAME in "ic_cloud_search" "ic_action_encrypt_file" "ic_action_encrypt_text" "ic_action_verified_cutout" "ic_action_encrypt_copy" "ic_action_encrypt_save" "ic_action_encrypt_share" "status_lock_closed" "status_lock_error" "status_lock_open" "status_signature_expired_cutout" "status_signature_invalid_cutout" "status_signature_revoked_cutout" "status_signature_unknown_cutout" "status_signature_unverified_cutout" "status_signature_verified_cutout" "key_flag_authenticate" "key_flag_certify" "key_flag_encrypt" "key_flag_sign" "yubi_icon" "ic_stat_notify" "status_signature_verified_inner" "link" "octo_link"
do
echo $NAME
inkscape -w 24 -h 24 -e "$MDPI_DIR/${NAME}_24dp.png" "$SRC_DIR/$NAME.svg"
@@ -32,7 +32,7 @@ inkscape -w 72 -h 72 -e "$XXDPI_DIR/${NAME}_24dp.png" "$SRC_DIR/$NAME.svg"
inkscape -w 96 -h 96 -e "$XXXDPI_DIR/${NAME}_24dp.png" "$SRC_DIR/$NAME.svg"
done
-for NAME in "status_signature_expired_cutout" "status_signature_invalid_cutout" "status_signature_revoked_cutout" "status_signature_unknown_cutout" "status_signature_unverified_cutout" "status_signature_verified_cutout"
+for NAME in "status_signature_expired_cutout" "status_signature_invalid_cutout" "status_signature_revoked_cutout" "status_signature_unknown_cutout" "status_signature_unverified_cutout" "status_signature_verified_cutout" "status_signature_verified_inner"
do
echo $NAME
inkscape -w 96 -h 96 -e "$MDPI_DIR/${NAME}_96dp.png" "$SRC_DIR/$NAME.svg"
@@ -41,7 +41,7 @@ inkscape -w 192 -h 192 -e "$XDPI_DIR/${NAME}_96dp.png" "$SRC_DIR/$NAME.svg"
inkscape -w 256 -h 256 -e "$XXDPI_DIR/${NAME}_96dp.png" "$SRC_DIR/$NAME.svg"
done
-for NAME in "create_key_robot"
+for NAME in "create_key_robot" "linked_dns" "linked_https" "linked_github" "linked_twitter" "account_key"
do
echo $NAME
inkscape -w 48 -h 48 -e "$MDPI_DIR/$NAME.png" "$SRC_DIR/$NAME.svg"
diff --git a/OpenKeychain/build.gradle b/OpenKeychain/build.gradle
index 5bf8f6d1b..ab640b1ca 100644
--- a/OpenKeychain/build.gradle
+++ b/OpenKeychain/build.gradle
@@ -46,7 +46,8 @@ dependencies {
compile 'com.jpardogo.materialtabstrip:library:1.0.9'
compile 'com.getbase:floatingactionbutton:1.9.0'
compile 'org.commonjava.googlecode.markdown4j:markdown4j:2.2-cj-1.0'
- compile 'com.splitwise:tokenautocomplete:1.3.3@aar'
+ compile 'org.ocpsoft.prettytime:prettytime:3.2.7.Final'
+ compile "com.splitwise:tokenautocomplete:1.3.3@aar"
compile 'se.emilsjolander:stickylistheaders:2.6.0'
compile 'org.sufficientlysecure:html-textview:1.2'
compile 'com.mikepenz:materialdrawer:3.0.9@aar'
@@ -58,6 +59,7 @@ dependencies {
compile 'com.squareup.okhttp:okhttp:2.4.0'
compile 'org.apache.james:apache-mime4j-core:0.7.2'
compile 'org.apache.james:apache-mime4j-dom:0.7.2'
+ compile 'org.thoughtcrime.ssl.pinning:AndroidPinning:1.0.0'
// libs as submodules
compile project(':extern:openpgp-api-lib:openpgp-api')
@@ -119,8 +121,8 @@ android {
defaultConfig {
minSdkVersion 15
targetSdkVersion 22
- versionCode 34100
- versionName "3.4.1"
+ versionCode 35100
+ versionName "3.5.1"
applicationId "org.sufficientlysecure.keychain"
// the androidjunitrunner is broken regarding coverage, see here:
// https://code.google.com/p/android/issues/detail?id=170607
@@ -143,9 +145,11 @@ android {
// Reference them in the java files with e.g. BuildConfig.ACCOUNT_TYPE.
buildConfigField "String", "ACCOUNT_TYPE", "\"org.sufficientlysecure.keychain.account\""
+ buildConfigField "String", "PROVIDER_CONTENT_AUTHORITY", "\"org.sufficientlysecure.keychain.provider\""
// Reference them in .xml files.
resValue "string", "account_type", "org.sufficientlysecure.keychain.account"
+ resValue "string", "provider_content_authority", "org.sufficientlysecure.keychain.provider"
}
debug {
@@ -153,9 +157,15 @@ android {
// Reference them in the java files with e.g. BuildConfig.ACCOUNT_TYPE.
buildConfigField "String", "ACCOUNT_TYPE", "\"org.sufficientlysecure.keychain.debug.account\""
+ buildConfigField "String", "PROVIDER_CONTENT_AUTHORITY", "\"org.sufficientlysecure.keychain.debug.provider\""
+
+ // Github api for debug build only
+ buildConfigField "String", "GITHUB_CLIENT_ID", "\"7a011b66275f244d3f21\""
+ buildConfigField "String", "GITHUB_CLIENT_SECRET", "\"eaced8a6655719d8c6848396de97b3f5d7a89fec\""
// Reference them in .xml files.
resValue "string", "account_type", "org.sufficientlysecure.keychain.debug.account"
+ resValue "string", "provider_content_authority", "org.sufficientlysecure.keychain.debug.provider"
// Enable code coverage (Jacoco)
testCoverageEnabled true
@@ -202,11 +212,11 @@ android {
}
dexOptions {
+ incremental = true
// Disable preDexing, causes com.android.dx.cf.iface.ParseException: bad class file magic (cafebabe) or version (0034.0000) on some systems
preDexLibraries = false
- // faster with incremental?
-// incremental true
- javaMaxHeapSize "4g"
+ jumboMode = true
+ javaMaxHeapSize "2g"
}
packagingOptions {
diff --git a/OpenKeychain/src/debug/res/drawable-hdpi/ic_launcher.png b/OpenKeychain/src/debug/res/mipmap-hdpi/ic_launcher.png
index bb5104aec..bb5104aec 100644
--- a/OpenKeychain/src/debug/res/drawable-hdpi/ic_launcher.png
+++ b/OpenKeychain/src/debug/res/mipmap-hdpi/ic_launcher.png
Binary files differ
diff --git a/OpenKeychain/src/debug/res/drawable-mdpi/ic_launcher.png b/OpenKeychain/src/debug/res/mipmap-mdpi/ic_launcher.png
index e709f735d..e709f735d 100644
--- a/OpenKeychain/src/debug/res/drawable-mdpi/ic_launcher.png
+++ b/OpenKeychain/src/debug/res/mipmap-mdpi/ic_launcher.png
Binary files differ
diff --git a/OpenKeychain/src/debug/res/drawable-xhdpi/ic_launcher.png b/OpenKeychain/src/debug/res/mipmap-xhdpi/ic_launcher.png
index fb4f2737a..fb4f2737a 100644
--- a/OpenKeychain/src/debug/res/drawable-xhdpi/ic_launcher.png
+++ b/OpenKeychain/src/debug/res/mipmap-xhdpi/ic_launcher.png
Binary files differ
diff --git a/OpenKeychain/src/debug/res/drawable-xxhdpi/ic_launcher.png b/OpenKeychain/src/debug/res/mipmap-xxhdpi/ic_launcher.png
index 37d0958ff..37d0958ff 100644
--- a/OpenKeychain/src/debug/res/drawable-xxhdpi/ic_launcher.png
+++ b/OpenKeychain/src/debug/res/mipmap-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/OpenKeychain/src/debug/res/drawable-xxxhdpi/ic_launcher.png b/OpenKeychain/src/debug/res/mipmap-xxxhdpi/ic_launcher.png
index e5183fb05..e5183fb05 100644
--- a/OpenKeychain/src/debug/res/drawable-xxxhdpi/ic_launcher.png
+++ b/OpenKeychain/src/debug/res/mipmap-xxxhdpi/ic_launcher.png
Binary files differ
diff --git a/OpenKeychain/src/main/AndroidManifest.xml b/OpenKeychain/src/main/AndroidManifest.xml
index d422c3da1..63e1a5ce7 100644
--- a/OpenKeychain/src/main/AndroidManifest.xml
+++ b/OpenKeychain/src/main/AndroidManifest.xml
@@ -71,7 +71,7 @@
android:name=".KeychainApplication"
android:allowBackup="false"
android:hardwareAccelerated="true"
- android:icon="@drawable/ic_launcher"
+ android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/Theme.Keychain.Light">
<activity
@@ -111,6 +111,13 @@
android:label="@string/title_edit_key" />
<!-- NOTE: Dont use configChanges for QR Code view! We use a different layout for landscape -->
<activity
+ android:name=".ui.linked.LinkedIdWizard"
+ android:configChanges="orientation|screenSize|keyboardHidden|keyboard"
+ android:label="@string/title_linked_create"
+ android:parentActivityName=".ui.ViewKeyActivity"
+ >
+ </activity>
+ <activity
android:name=".ui.QrCodeViewActivity"
android:label="@string/share_qr_code_dialog_title" />
<activity
@@ -691,7 +698,6 @@
<activity
android:name=".ui.OrbotRequiredDialogActivity"
android:theme="@android:style/Theme.NoDisplay" />
- <activity android:name=".ui.PassphraseWizardActivity" />
<!--
NOTE: singleTop is set to get NFC foreground dispatch to work.
Then, all NFC intents will be broadcasted to onNewIntent() of this activity!
@@ -701,7 +707,7 @@
-->
<activity
android:name=".ui.NfcOperationActivity"
- android:theme="@style/Theme.Keychain.Light.Dialog.SecurityToken"
+ android:theme="@style/Theme.Keychain.Light.Dialog"
android:allowTaskReparenting="true"
android:launchMode="singleTop"
android:taskAffinity=":Nfc" />
@@ -723,10 +729,13 @@
android:name=".service.KeychainService"
android:exported="false" />
+ <!-- label is made to be "Keyserver Sync" since that is the only context in which
+ the user will see it-->
<provider
android:name=".provider.KeychainProvider"
android:authorities="${applicationId}.provider"
- android:exported="false" />
+ android:exported="false"
+ android:label="@string/keyserver_sync_settings_title"/>
<!-- Internal classes of the remote APIs (not exported) -->
<activity
@@ -758,8 +767,9 @@
android:configChanges="orientation|screenSize|keyboardHidden|keyboard"
android:exported="false" />
- <!-- OpenPGP Remote API, this service has explicitly no permission requirements
- because we are using our own package based allow/disallow system -->
+ <!-- DEPRECATED service,
+ using this service may lead to truncated data being returned to the caller
+ -->
<service
android:name=".remote.OpenPgpService"
android:enabled="true"
@@ -771,6 +781,19 @@
</intent-filter>
</service>
+ <!-- OpenPGP Remote API, this service has explicitly no permission requirements
+ because we are using our own package based allow/disallow system -->
+ <service
+ android:name=".remote.OpenPgpService2"
+ android:enabled="true"
+ android:exported="true"
+ android:process=":remote_api_2"
+ tools:ignore="ExportedService">
+ <intent-filter>
+ <action android:name="org.openintents.openpgp.IOpenPgpService2" />
+ </intent-filter>
+ </service>
+
<!-- Contact Sync services -->
<service
android:name=".service.DummyAccountService"
@@ -800,6 +823,20 @@
android:resource="@xml/custom_pgp_contacts_structure" />
</service>
+ <service
+ android:name=".service.KeyserverSyncAdapterService"
+ android:exported="true"
+ android:process=":sync"
+ tools:ignore="ExportedService">
+ <intent-filter>
+ <action android:name="android.content.SyncAdapter" />
+ </intent-filter>
+
+ <meta-data
+ android:name="android.content.SyncAdapter"
+ android:resource="@xml/keyserver_sync_adapter_desc" />
+ </service>
+
<!-- Storage Provider for temporary decrypted files -->
<provider
android:name=".provider.TemporaryStorageProvider"
diff --git a/OpenKeychain/src/main/assets/word_confirm_list.txt b/OpenKeychain/src/main/assets/word_confirm_list.txt
new file mode 100644
index 000000000..080c7ce81
--- /dev/null
+++ b/OpenKeychain/src/main/assets/word_confirm_list.txt
@@ -0,0 +1,12032 @@
+you
+the
+a
+and
+that
+what
+this
+for
+your
+have
+don
+are
+not
+was
+can
+know
+with
+all
+but
+here
+there
+they
+get
+just
+like
+come
+right
+she
+him
+out
+now
+one
+about
+how
+want
+got
+her
+will
+well
+see
+good
+let
+yes
+think
+who
+why
+yeah
+did
+from
+his
+when
+going
+man
+take
+where
+time
+them
+back
+look
+would
+say
+were
+been
+then
+had
+tell
+some
+our
+okay
+too
+down
+could
+hey
+never
+way
+very
+more
+really
+has
+make
+over
+please
+only
+love
+give
+little
+need
+people
+off
+two
+said
+sorry
+thank
+sir
+should
+mean
+any
+much
+sure
+even
+doing
+must
+these
+thing
+help
+god
+day
+first
+won
+life
+again
+away
+stop
+wait
+night
+find
+into
+work
+still
+put
+home
+call
+before
+better
+their
+other
+talk
+after
+maybe
+great
+than
+those
+always
+long
+money
+old
+leave
+keep
+new
+told
+things
+name
+last
+father
+around
+years
+does
+hello
+ever
+place
+big
+nice
+feel
+girl
+stay
+thanks
+made
+mother
+listen
+three
+may
+guy
+hear
+coming
+world
+enough
+left
+fine
+every
+house
+course
+done
+boy
+wrong
+bad
+which
+woman
+lot
+kind
+wanted
+guys
+came
+ask
+son
+today
+show
+own
+care
+mind
+try
+being
+same
+car
+might
+dad
+miss
+else
+many
+men
+friend
+baby
+next
+move
+huh
+live
+hold
+real
+saw
+went
+seen
+room
+best
+found
+wife
+job
+once
+such
+matter
+head
+most
+heard
+alone
+ready
+haven
+happy
+days
+run
+play
+door
+bring
+mom
+myself
+open
+yet
+trying
+knew
+whole
+meet
+excuse
+family
+used
+while
+use
+start
+took
+pretty
+gone
+called
+idea
+since
+watch
+turn
+hope
+year
+guess
+end
+sit
+hard
+says
+hand
+bit
+school
+both
+worry
+minute
+true
+face
+soon
+lost
+forget
+bye
+young
+five
+killed
+heart
+few
+wants
+later
+eat
+drink
+ago
+shut
+pay
+police
+each
+water
+anyone
+dear
+also
+shall
+looks
+saying
+until
+crazy
+late
+phone
+eyes
+easy
+sleep
+mine
+afraid
+doctor
+nobody
+four
+under
+second
+music
+change
+far
+hands
+kids
+knows
+hit
+case
+its
+gave
+read
+times
+speak
+anyway
+stand
+part
+wish
+word
+having
+cut
+stuff
+comes
+war
+number
+happen
+hurry
+quite
+rest
+close
+check
+inside
+hurt
+half
+moment
+girls
+makes
+lady
+women
+asked
+set
+boys
+taking
+story
+town
+chance
+child
+yours
+lord
+point
+deal
+sister
+goes
+party
+week
+walk
+means
+honey
+dog
+shot
+high
+bed
+game
+person
+body
+break
+free
+making
+side
+fun
+almost
+buy
+least
+truth
+six
+along
+met
+city
+behind
+send
+though
+hours
+blood
+light
+stupid
+gets
+funny
+ahead
+answer
+full
+line
+front
+hate
+white
+poor
+hot
+order
+reason
+king
+tried
+seems
+either
+couple
+trust
+months
+alive
+hour
+pick
+able
+save
+clear
+office
+john
+become
+book
+living
+food
+daddy
+cool
+dance
+red
+news
+lose
+cold
+touch
+power
+scared
+boss
+fact
+dinner
+jack
+master
+uncle
+small
+quiet
+write
+taken
+ten
+luck
+sent
+cannot
+air
+earth
+glad
+law
+till
+needs
+dream
+street
+drive
+hair
+sort
+others
+bet
+lives
+follow
+whoa
+fast
+sweet
+sound
+catch
+words
+human
+safe
+hang
+beat
+rather
+top
+plan
+seem
+known
+coffee
+ladies
+wow
+lucky
+win
+past
+calm
+pull
+lie
+sign
+return
+fall
+team
+longer
+kiss
+asking
+tired
+feet
+learn
+drop
+quick
+wake
+marry
+train
+throw
+loved
+road
+sounds
+land
+felt
+step
+eye
+piece
+weeks
+secret
+sense
+takes
+pass
+voice
+clean
+looked
+wonder
+song
+fault
+state
+seven
+born
+less
+film
+ride
+joe
+class
+act
+none
+given
+fool
+early
+worth
+ones
+future
+strong
+army
+mouth
+moving
+george
+frank
+sing
+sun
+chief
+worked
+horse
+report
+sell
+turned
+dark
+peace
+month
+movie
+lovely
+boat
+blue
+seeing
+hotel
+eight
+york
+ship
+rock
+sam
+age
+christ
+murder
+finish
+letter
+court
+works
+swear
+expect
+bill
+giving
+near
+worse
+busy
+pain
+kept
+ball
+floor
+laughs
+wear
+sea
+fly
+count
+gold
+forgot
+radio
+french
+caught
+short
+soul
+figure
+paid
+simple
+bag
+tom
+fish
+date
+rich
+paul
+broke
+miles
+during
+ring
+choice
+bank
+david
+relax
+except
+attack
+join
+table
+across
+mary
+paper
+star
+dude
+stick
+meant
+round
+honor
+fair
+hungry
+middle
+thinks
+buddy
+lying
+unless
+spend
+major
+charge
+needed
+deep
+hide
+handle
+bought
+key
+cry
+trip
+lead
+window
+enjoy
+system
+sake
+fell
+cover
+ran
+church
+carry
+tea
+smart
+force
+teach
+paris
+box
+holy
+often
+plane
+dress
+lunch
+smell
+third
+ground
+crying
+talked
+ice
+tough
+heaven
+proud
+laugh
+sad
+sighs
+lived
+art
+harry
+mark
+single
+dare
+group
+record
+wind
+cops
+fix
+club
+upon
+mike
+mess
+quit
+entire
+wine
+normal
+visit
+offer
+public
+missed
+prison
+smoke
+agree
+saved
+river
+broken
+madam
+weird
+green
+arms
+evil
+south
+bob
+wall
+bar
+judge
+orders
+seat
+bear
+wrote
+queen
+slow
+cause
+dreams
+loves
+cop
+liked
+north
+glass
+accept
+cross
+scene
+double
+share
+honest
+moon
+joke
+beer
+space
+jump
+whose
+jail
+area
+tree
+foot
+test
+cat
+dying
+within
+ought
+brain
+nine
+peter
+field
+bother
+bus
+lots
+doubt
+camera
+became
+german
+books
+gives
+shoes
+truck
+ben
+kick
+card
+cash
+push
+moved
+likes
+calls
+cute
+max
+park
+store
+grow
+owe
+aunt
+reach
+guard
+spent
+summer
+rules
+duty
+island
+johnny
+eating
+smile
+silly
+san
+folks
+knock
+pardon
+crowd
+henry
+beg
+stuck
+action
+upset
+begin
+prove
+feels
+grand
+using
+guns
+legs
+nose
+rid
+mum
+list
+sky
+shop
+arm
+escape
+mommy
+gas
+low
+jimmy
+self
+hat
+ray
+bell
+price
+cell
+rain
+warm
+west
+passed
+board
+london
+nor
+lawyer
+lay
+closed
+gift
+favor
+tony
+jim
+empty
+prince
+papa
+suit
+press
+asleep
+type
+grab
+spirit
+arrest
+papers
+band
+indeed
+pop
+played
+dogs
+agent
+above
+wild
+nick
+race
+mrs
+spot
+fellow
+whom
+leg
+awful
+killer
+fit
+aye
+beauty
+twenty
+bird
+named
+lock
+blame
+heavy
+choose
+allow
+twice
+magic
+waste
+plenty
+raise
+flying
+notice
+gasps
+doc
+decide
+taste
+flight
+picked
+billy
+fresh
+cost
+nature
+hero
+james
+places
+planet
+search
+battle
+steal
+lights
+neck
+mate
+hardly
+sold
+study
+famous
+simply
+keys
+memory
+names
+worst
+throat
+guilty
+ways
+shame
+stone
+bottle
+states
+mister
+pray
+bunch
+camp
+starts
+seemed
+form
+stars
+stage
+animal
+roll
+east
+faster
+locked
+van
+final
+apart
+match
+admit
+tight
+engine
+build
+treat
+sight
+closer
+huge
+beach
+bigger
+keeps
+stole
+united
+among
+hall
+danger
+itself
+cup
+milk
+fired
+pants
+built
+lies
+cousin
+steve
+main
+cook
+meat
+ill
+angel
+risk
+plans
+tape
+taught
+sword
+extra
+corner
+beyond
+hiding
+belong
+sarah
+wash
+drugs
+cars
+skin
+large
+leaves
+driver
+health
+ugly
+helped
+note
+bridge
+martin
+rose
+pig
+acting
+horses
+level
+nuts
+sunday
+track
+plays
+anna
+heads
+walked
+strike
+rule
+turns
+common
+madame
+grunts
+roger
+losing
+weil
+speed
+tells
+due
+serve
+teeth
+began
+lee
+shirt
+rings
+robert
+spoke
+size
+feed
+held
+bobby
+coach
+dry
+pack
+ideas
+grace
+prefer
+bottom
+movies
+view
+breath
+ticket
+energy
+code
+hurts
+cheers
+remain
+pal
+usual
+groans
+showed
+weapon
+brown
+center
+coat
+ours
+copy
+market
+jerry
+noise
+birds
+fill
+advice
+rome
+cream
+ghost
+exist
+oil
+jake
+tie
+leader
+draw
+loud
+lift
+nearly
+post
+travel
+surely
+bread
+cards
+older
+heat
+games
+crew
+cake
+bucks
+pity
+brave
+chair
+gotten
+bless
+wet
+priest
+shows
+thy
+agreed
+truly
+gate
+nurse
+paying
+slowly
+thou
+local
+style
+soft
+spring
+grown
+pieces
+dig
+shake
+settle
+maria
+ends
+larry
+lonely
+garden
+stayed
+enter
+weak
+fate
+split
+flat
+proof
+jane
+loose
+gang
+trial
+speaks
+afford
+snow
+bright
+trees
+friday
+guest
+ears
+santa
+career
+threw
+color
+bodies
+mayor
+manage
+victim
+finger
+opened
+roof
+file
+lake
+plus
+sees
+spare
+farm
+rent
+repeat
+sugar
+alarm
+winter
+insane
+base
+total
+stops
+thief
+hill
+fancy
+stolen
+female
+tongue
+sooner
+liar
+target
+joy
+mail
+client
+easier
+cheap
+brings
+pulled
+doors
+credit
+lines
+harm
+castle
+male
+birth
+spread
+storm
+arthur
+paint
+slept
+lover
+hoping
+bath
+cares
+taxi
+trade
+lately
+video
+weight
+thomas
+lied
+square
+tears
+march
+block
+thee
+eggs
+onto
+forest
+europe
+pool
+tiny
+jean
+super
+walter
+nights
+pete
+signal
+signed
+rat
+mercy
+yellow
+dan
+desk
+shower
+simon
+scare
+regret
+remind
+swim
+merry
+pocket
+path
+ended
+speech
+aware
+drinks
+pair
+ocean
+waited
+page
+andy
+runs
+rise
+fake
+amen
+ate
+pure
+bullet
+photo
+social
+genius
+desert
+forced
+player
+grave
+map
+staff
+vote
+headed
+easily
+monkey
+rough
+create
+scott
+wise
+harder
+guests
+sudden
+silver
+higher
+fought
+pounds
+fixed
+add
+lower
+desire
+bro
+failed
+monday
+louis
+badly
+below
+clock
+member
+piano
+lesson
+kate
+gods
+rush
+lips
+unit
+tall
+safety
+fred
+adam
+season
+points
+thirty
+odd
+wood
+clever
+royal
+parts
+artist
+suffer
+dawn
+rights
+grew
+union
+nation
+theory
+mood
+filled
+soup
+model
+hung
+period
+opens
+ear
+golden
+hearts
+cheese
+plant
+proper
+shape
+ruin
+legal
+faces
+ruined
+issue
+refuse
+per
+bride
+awake
+cow
+load
+forces
+smith
+based
+grant
+woods
+scream
+freak
+temple
+decent
+hidden
+joking
+arrive
+sin
+jacket
+invite
+boring
+bang
+wolf
+mirror
+lucy
+dies
+alice
+walls
+annie
+saint
+avoid
+bike
+carl
+sat
+talent
+fifty
+chest
+buying
+tear
+jobs
+guards
+image
+indian
+finds
+brian
+trap
+burned
+eve
+shock
+iron
+wide
+marie
+hunt
+poison
+flower
+anne
+bones
+matt
+dollar
+rooms
+owner
+brains
+glory
+cab
+riding
+meal
+freeze
+damned
+candy
+shots
+raised
+tower
+stood
+bravo
+dust
+alan
+warn
+toast
+virgin
+bags
+appear
+caused
+pride
+switch
+pilot
+damage
+helen
+led
+loving
+rice
+knees
+coast
+songs
+babies
+duke
+silent
+tour
+sons
+daniel
+fourth
+actor
+victor
+armed
+moves
+palace
+troops
+rate
+writer
+hired
+junior
+phil
+amount
+false
+affair
+rob
+susan
+falls
+tied
+bull
+fallen
+saving
+snake
+loss
+mighty
+youth
+smells
+lab
+border
+kicked
+cast
+drove
+rescue
+sharp
+zero
+borrow
+humans
+eric
+flesh
+row
+jason
+modern
+score
+pills
+gee
+studio
+fail
+tip
+defend
+eaten
+steps
+cases
+climb
+role
+event
+egg
+joey
+effect
+seek
+chase
+wave
+houses
+blows
+rocks
+stairs
+rope
+dragon
+bow
+winner
+barely
+aboard
+hated
+mass
+grade
+leo
+aside
+bone
+wire
+ted
+yard
+button
+jews
+plate
+dump
+tail
+bored
+salt
+metal
+talks
+sand
+joseph
+films
+fruit
+gosh
+claim
+goal
+penny
+clears
+shadow
+firm
+powers
+rachel
+prime
+punch
+wishes
+non
+steady
+tiger
+giant
+edge
+woke
+chuck
+loser
+assume
+behave
+direct
+jones
+blew
+pen
+chose
+wheel
+drag
+sexual
+maid
+county
+chick
+remove
+jenny
+nope
+spell
+terms
+focus
+stock
+valley
+duck
+chosen
+likely
+wound
+object
+sale
+spoken
+buck
+mummy
+tank
+pie
+notes
+shout
+guts
+bound
+scary
+hop
+value
+slip
+result
+amy
+los
+photos
+shine
+mostly
+rare
+hitler
+witch
+served
+texas
+jury
+intend
+wings
+albert
+kinds
+com
+pink
+cruel
+bury
+doll
+terry
+facts
+range
+brand
+shy
+kong
+screen
+rabbit
+apple
+swing
+prize
+marks
+deeply
+laws
+wing
+mile
+coward
+site
+thus
+closes
+june
+mixed
+earn
+hong
+rude
+begins
+linda
+kitty
+curse
+chain
+cure
+spy
+noble
+juice
+source
+circle
+plain
+sue
+ann
+twelve
+rotten
+lad
+thrown
+minds
+grass
+kelly
+kissed
+squad
+jungle
+bond
+effort
+series
+expert
+filthy
+belt
+edward
+lets
+thin
+berlin
+commit
+boots
+punk
+stands
+cheer
+sheep
+guitar
+access
+ships
+bust
+flag
+panic
+pizza
+morgan
+deny
+sally
+ali
+bush
+asks
+deck
+tokyo
+term
+hunter
+former
+tim
+insist
+estate
+martha
+assure
+hates
+navy
+debt
+fever
+luke
+joined
+reward
+karen
+ease
+fetch
+garage
+jumped
+signs
+shoe
+threat
+zone
+solve
+title
+policy
+ages
+crown
+leads
+lion
+hire
+guide
+bay
+demand
+trash
+tone
+vision
+supper
+voices
+hip
+route
+lack
+port
+cats
+dozen
+dirt
+helps
+media
+bruce
+puts
+exact
+secure
+stays
+april
+lousy
+deaf
+caesar
+rip
+fox
+urgent
+maggie
+russia
+tricks
+mask
+gather
+warned
+betty
+highly
+useful
+tires
+forty
+gentle
+suits
+carter
+jesse
+solid
+wipe
+launch
+emily
+hank
+sweat
+steel
+tests
+alert
+fifth
+script
+lend
+costs
+toward
+aim
+latest
+tune
+agency
+sacred
+empire
+events
+vice
+argue
+rick
+vegas
+mental
+loaded
+anger
+clark
+breaks
+sonny
+museum
+tax
+miller
+flash
+pushed
+data
+dean
+lily
+gray
+brad
+sports
+pierre
+senior
+roman
+reckon
+singer
+cap
+stones
+firing
+handed
+beside
+walks
+daily
+fully
+clue
+wilson
+souls
+kills
+banks
+circus
+shift
+clouds
+closet
+hits
+forth
+jackie
+prayer
+loan
+fools
+fields
+trace
+civil
+orange
+wayne
+carol
+nerve
+outfit
+degree
+flies
+andrew
+bills
+cheat
+idiots
+chat
+ending
+noon
+cabin
+detail
+hug
+planes
+ghosts
+hills
+alien
+pigs
+mix
+hail
+supply
+struck
+bat
+files
+cents
+sides
+opera
+bug
+jokes
+angels
+design
+ken
+pour
+cave
+gear
+dating
+beaten
+herr
+legend
+nephew
+belly
+dancer
+thick
+ignore
+fuel
+pat
+cried
+lane
+ellen
+bowl
+butter
+bombs
+francs
+net
+wasted
+defeat
+bars
+bells
+toy
+sport
+wallet
+trunk
+homes
+wore
+coke
+ouch
+obey
+fort
+norman
+trail
+league
+shore
+task
+doug
+wins
+rats
+motion
+blast
+mouse
+merely
+lads
+busted
+anti
+monk
+wives
+agents
+seats
+inform
+waves
+gary
+moscow
+accent
+beings
+attend
+shown
+josh
+robin
+tunnel
+drew
+recall
+drank
+greek
+poetry
+swell
+knight
+earl
+units
+chill
+harold
+mars
+holes
+jay
+rifle
+bishop
+beth
+robbed
+hoped
+fond
+rocky
+unique
+goods
+pound
+louise
+crush
+nancy
+golf
+fence
+woo
+patrol
+sire
+resist
+stan
+cloud
+habit
+pays
+blown
+von
+lovers
+novel
+august
+wagon
+packed
+widow
+boo
+siren
+ruth
+exit
+beef
+exists
+tracks
+bud
+actors
+nail
+ugh
+skip
+july
+passes
+crisis
+sins
+washed
+sink
+sail
+dough
+baron
+pet
+wicked
+flow
+halt
+aid
+charm
+cattle
+owns
+worker
+hood
+nerves
+jam
+purse
+smooth
+divine
+seal
+hopes
+chop
+heroes
+equal
+virus
+sec
+gates
+powder
+mickey
+mud
+wrap
+sang
+beeps
+begun
+couch
+flew
+jacob
+skills
+arts
+lewis
+tries
+print
+pole
+ward
+theme
+fans
+soap
+string
+farmer
+kung
+gain
+poem
+issues
+inch
+greg
+teddy
+burns
+polish
+beats
+chef
+frozen
+pro
+yell
+waters
+device
+davis
+bend
+basic
+slap
+earned
+cowboy
+boston
+wee
+praise
+cable
+moral
+permit
+behalf
+messed
+plants
+knee
+holds
+clown
+shouts
+placed
+worthy
+cinema
+cage
+finest
+waiter
+junk
+strip
+guilt
+buzz
+kit
+deputy
+granny
+hers
+shark
+eagle
+poet
+oscar
+cliff
+boats
+tyler
+counts
+parker
+holmes
+softly
+snap
+sets
+nina
+bail
+beard
+hut
+yen
+tale
+heck
+chip
+crimes
+steven
+bitter
+juan
+uses
+hid
+eleven
+scoffs
+mount
+dealer
+limit
+liquor
+sauce
+miami
+odds
+combat
+baker
+corn
+images
+cries
+yards
+shed
+insult
+pitch
+beans
+salad
+corpse
+gym
+lazy
+nearby
+landed
+roses
+goat
+foul
+beep
+meters
+yells
+acts
+frame
+cancel
+link
+pin
+daisy
+absurd
+slaves
+hammer
+admire
+tastes
+benny
+motor
+boxes
+gifts
+ace
+loyal
+cities
+blonde
+punish
+clan
+native
+cells
+dumped
+skull
+stroke
+fights
+pearl
+avenue
+tooth
+timing
+rocket
+grief
+brush
+sucker
+chicks
+alley
+dennis
+judy
+brief
+robot
+angle
+ail
+mobile
+drives
+sends
+pope
+status
+profit
+wounds
+actual
+nut
+tent
+host
+barn
+stress
+broad
+chips
+sack
+cooper
+stink
+oxygen
+raped
+ranch
+whip
+coughs
+labor
+relief
+soviet
+wars
+oliver
+blade
+upper
+sings
+scale
+alike
+drown
+spoil
+salary
+jazz
+harris
+palm
+fleet
+pump
+unable
+clinic
+sailor
+horror
+eats
+clay
+forms
+stinks
+dame
+jet
+polite
+deeper
+dishes
+blah
+drama
+minor
+editor
+wheels
+roads
+ford
+sandy
+humble
+throne
+backup
+shave
+sore
+driven
+pit
+socks
+bunny
+delay
+colors
+sneak
+sung
+rub
+tap
+walker
+vodka
+diet
+wisdom
+ripped
+holly
+statue
+louder
+tracy
+grows
+gently
+manner
+recent
+groups
+spin
+ralph
+lamb
+humor
+pages
+anyhow
+pale
+pile
+grey
+sid
+jan
+khan
+chaos
+soda
+fits
+claims
+jersey
+apply
+kisses
+skinny
+torn
+cotton
+kings
+champ
+burnt
+spider
+twins
+gloves
+bears
+dutch
+misery
+facing
+sales
+pan
+drawn
+joan
+remote
+exam
+phones
+cows
+allen
+brandy
+cherry
+diego
+maya
+bid
+donna
+toys
+bee
+plot
+cared
+parade
+crane
+advise
+patch
+dna
+envy
+option
+hush
+casino
+shell
+nicely
+drill
+twist
+temper
+min
+steak
+ham
+blocks
+sorrow
+rear
+coin
+janet
+ashes
+clicks
+format
+drops
+safely
+wealth
+jess
+medal
+coffin
+que
+goose
+gloria
+appeal
+pill
+sub
+towel
+slide
+ups
+tragic
+claus
+fires
+leon
+faced
+core
+motel
+worn
+romeo
+global
+rhythm
+nest
+soccer
+fried
+betray
+terror
+stable
+liver
+solar
+wreck
+howdy
+wears
+dull
+checks
+dish
+rap
+basis
+unlike
+kindly
+fog
+sticks
+bugs
+zoo
+pulse
+lamp
+taxes
+abroad
+dates
+burden
+oath
+award
+marine
+felix
+tools
+rusty
+irish
+cooked
+rising
+rubber
+hunger
+scenes
+faint
+cellar
+troy
+item
+niece
+sarge
+badge
+frog
+smash
+shove
+sunny
+toes
+sixth
+reveal
+tennis
+mob
+gene
+proved
+poker
+nails
+ram
+symbol
+pork
+inner
+makeup
+fanny
+bits
+soil
+vain
+sum
+hatred
+kenny
+scout
+boot
+album
+buddha
+senses
+tender
+plates
+lap
+deadly
+tanks
+entry
+puppy
+watson
+warren
+shared
+tin
+philip
+warden
+inches
+rosa
+fuss
+stiff
+folk
+cent
+asses
+cart
+liz
+scotch
+tend
+pistol
+del
+cookie
+flip
+bucket
+booze
+inn
+math
+tons
+acted
+bets
+bare
+vast
+crawl
+ruby
+forbid
+owned
+sis
+basket
+rank
+branch
+active
+depend
+eyed
+chi
+lit
+gum
+barrel
+drum
+sheets
+connie
+stare
+potato
+causes
+needle
+darn
+heal
+wished
+muscle
+cuts
+rage
+raid
+leak
+blank
+breast
+flame
+feast
+sorts
+unfair
+areas
+chap
+porter
+tense
+tire
+marked
+fooled
+neat
+nelson
+duties
+impact
+ideal
+diary
+steam
+text
+rumors
+limits
+bait
+fist
+carpet
+dining
+safer
+toe
+teams
+burst
+bore
+fame
+lean
+review
+rounds
+bureau
+foster
+jewels
+horns
+sobs
+trains
+dime
+pre
+raw
+cursed
+lick
+donkey
+method
+sits
+bump
+worm
+silk
+hooked
+rod
+upside
+sealed
+alpha
+comedy
+dong
+prints
+retire
+lands
+tattoo
+weed
+worlds
+donald
+sample
+column
+suite
+skirt
+bingo
+hears
+skies
+sheet
+denied
+apples
+korea
+alfred
+ladder
+booth
+ding
+plague
+phase
+sunset
+mason
+trucks
+snakes
+toss
+fridge
+unto
+pops
+danced
+racing
+brick
+region
+growls
+gal
+picnic
+clerk
+rio
+mall
+sleepy
+psycho
+mere
+yang
+scar
+sober
+sweep
+handy
+root
+budget
+shirts
+cigar
+whale
+height
+log
+wolves
+drawer
+creep
+spite
+rot
+graham
+drums
+boxing
+harbor
+las
+tomb
+repair
+fund
+writes
+stuart
+collar
+lemon
+villa
+affect
+brakes
+purple
+tapes
+tube
+solved
+murphy
+radar
+error
+coal
+cease
+mortal
+cannon
+tag
+demons
+winds
+shield
+fears
+turner
+motive
+sleeps
+locker
+laying
+fairly
+oldest
+deaths
+rode
+breeze
+korean
+seated
+click
+sylvia
+heels
+adults
+subway
+pigeon
+swore
+fee
+minus
+deed
+thumb
+dizzy
+blues
+grip
+dale
+prom
+pepper
+skill
+ballet
+beds
+candle
+slight
+vital
+plug
+elder
+flames
+types
+homer
+groom
+reply
+hon
+fur
+sixty
+melody
+pillow
+outer
+stream
+clubs
+bald
+loses
+beware
+diana
+quote
+hath
+spots
+sirens
+dreamt
+era
+copies
+fry
+tub
+ana
+sector
+chess
+nanny
+dummy
+belief
+added
+wizard
+lance
+rang
+tables
+aliens
+booked
+walt
+bench
+whores
+owes
+stab
+cathy
+dial
+mill
+edgar
+creepy
+irene
+doubts
+acid
+lungs
+vera
+chorus
+author
+visual
+adore
+arrow
+barks
+helmet
+random
+deer
+larger
+ling
+tribe
+deals
+blond
+parent
+tide
+gig
+bold
+sakes
+seed
+severe
+nap
+hatch
+twin
+fixing
+moans
+lip
+prices
+gossip
+cruise
+triple
+hawk
+hockey
+chains
+parked
+debts
+meets
+lame
+maniac
+brat
+wang
+greedy
+bacon
+bleed
+tarzan
+dug
+galaxy
+chased
+depth
+rumor
+mid
+ape
+pencil
+lions
+flood
+jolly
+cargo
+hats
+beam
+banana
+vault
+cheek
+jill
+phoned
+turtle
+ginger
+rely
+beers
+coma
+corps
+elvis
+formed
+cured
+bloom
+narrow
+serial
+heir
+cough
+aha
+greet
+gamble
+organ
+losers
+react
+judges
+sandra
+levels
+backs
+rolls
+naive
+starve
+income
+bean
+heroin
+custom
+wiped
+easter
+pirate
+bass
+strict
+slice
+ties
+harsh
+roast
+marc
+moses
+slim
+lobby
+liquid
+rivers
+solo
+bounce
+bonus
+regard
+tore
+madrid
+length
+bent
+tested
+chapel
+meals
+cloth
+dice
+yea
+cape
+lung
+ton
+tales
+breed
+tango
+herd
+parole
+web
+deeds
+tool
+coins
+nun
+kansas
+den
+ditch
+shares
+hector
+venice
+pub
+chew
+razor
+hawaii
+noah
+whisky
+comic
+dallas
+minded
+slams
+scares
+brass
+mines
+doomed
+sworn
+sharks
+autumn
+logan
+swords
+swine
+pace
+bloke
+wooden
+vessel
+harper
+bon
+drain
+pond
+debbie
+butler
+wade
+bin
+shrink
+fled
+dam
+carlo
+alibi
+cafe
+chow
+smoked
+models
+reads
+stores
+rum
+kent
+theirs
+glove
+violin
+behold
+mon
+roots
+hanged
+rebel
+rains
+rented
+diane
+hugo
+fatal
+gut
+bark
+menu
+orphan
+honks
+luxury
+ahem
+fare
+worms
+rascal
+formal
+mouths
+hah
+risky
+salute
+nicer
+peggy
+riot
+risks
+racket
+tasty
+theft
+swamp
+yankee
+voyage
+saddle
+serves
+lawn
+potter
+shoots
+ritual
+sucked
+offers
+brutal
+float
+rarely
+oven
+hay
+sidney
+petty
+waking
+morris
+modest
+grain
+injury
+lester
+swiss
+sells
+nazis
+votes
+debate
+milan
+draft
+mice
+savage
+arabic
+ransom
+knives
+repay
+sydney
+spill
+wit
+leaf
+arnold
+seas
+medium
+dock
+proves
+loudly
+crow
+choir
+belle
+tech
+thats
+tick
+ski
+ruins
+weigh
+rico
+prey
+venus
+online
+covers
+bubble
+echo
+dried
+wells
+bandit
+stove
+rex
+dot
+flee
+values
+wax
+mae
+ducks
+eager
+funds
+scent
+hangs
+scheme
+romans
+meter
+samuel
+growth
+tricky
+wrist
+helena
+franz
+reed
+amber
+marina
+asylum
+creek
+kneel
+ash
+mule
+fold
+kirk
+nurses
+noises
+locate
+shaw
+senate
+thrill
+chairs
+cycle
+poems
+jose
+volume
+spray
+smiles
+seeds
+cakes
+owners
+sole
+learnt
+bully
+gypsy
+rays
+mini
+pilots
+tips
+phrase
+rosie
+begged
+keen
+static
+spoon
+vienna
+disco
+cane
+virtue
+kicks
+loads
+via
+dated
+tan
+ming
+mature
+sofa
+stir
+joyce
+pine
+joker
+fries
+armor
+wander
+peanut
+scores
+picks
+mafia
+olive
+madman
+floors
+awhile
+logic
+manual
+rolled
+mates
+ink
+voted
+snack
+pledge
+crook
+laser
+bands
+hamlet
+races
+rebels
+aged
+endure
+mia
+shade
+stamp
+lasted
+buster
+beasts
+batman
+brake
+occur
+dolly
+delta
+orbit
+pulls
+fork
+campus
+rig
+dances
+dodge
+allies
+hooray
+hereby
+wig
+alas
+joel
+dealt
+misses
+maker
+hobby
+tails
+spies
+oui
+devils
+andre
+feared
+clues
+pals
+nickel
+auto
+towns
+notion
+flush
+straw
+sigh
+stunt
+veins
+buys
+maiden
+whack
+bonnie
+kidnap
+owl
+rally
+seize
+canyon
+lords
+barber
+abe
+weep
+spying
+esther
+shorts
+wakes
+phony
+cans
+jeep
+burger
+haul
+myth
+duel
+sour
+spike
+throws
+stall
+rug
+adams
+robe
+roars
+ninety
+gladly
+pierce
+asia
+ego
+tissue
+ranger
+sherry
+karate
+dudes
+choke
+sheila
+vow
+cue
+allows
+queens
+bees
+curly
+shiny
+camel
+prior
+melt
+jewel
+freaks
+bonds
+evans
+anchor
+zip
+morgue
+hotels
+ruled
+pose
+exams
+carbon
+shops
+pony
+assist
+altar
+graves
+jun
+untie
+thud
+ensure
+mainly
+ashore
+doris
+jar
+resign
+accuse
+prayed
+violet
+butch
+copper
+camps
+scan
+awaits
+freely
+offend
+dip
+owed
+ants
+hint
+wired
+pooh
+fade
+ankle
+knocks
+rides
+stew
+trips
+urge
+ping
+attic
+jaw
+sweets
+boil
+darwin
+dolls
+porch
+noisy
+cant
+eighty
+sync
+origin
+mutual
+visits
+pastor
+tease
+dagger
+caring
+stereo
+sniffs
+rack
+gown
+issued
+stark
+hairy
+proven
+grades
+leap
+posted
+items
+divide
+engage
+plead
+sting
+lifted
+kathy
+dared
+waits
+baba
+clumsy
+wages
+ropes
+denver
+apollo
+cord
+rifles
+fails
+diving
+habits
+lust
+troop
+puzzle
+lined
+ferry
+filed
+woody
+luther
+heel
+jeanne
+bolt
+bra
+label
+drake
+cups
+tomato
+shorty
+colony
+dove
+filth
+dings
+tuck
+ghetto
+submit
+torch
+val
+avenge
+bounty
+pipes
+virgil
+puppet
+locks
+mole
+wires
+lively
+resort
+waltz
+joshua
+dante
+pursue
+strain
+hudson
+sought
+gained
+recipe
+austin
+iris
+tucker
+glue
+annual
+jelly
+hunch
+mug
+amazed
+ridge
+sissy
+atomic
+hence
+invent
+cheque
+thread
+erase
+salmon
+boxer
+patty
+sofia
+buzzer
+saints
+hike
+scarf
+globe
+usa
+swan
+palmer
+tops
+ally
+comb
+pains
+eighth
+breach
+canal
+rogers
+runner
+messy
+subtle
+wheat
+adopt
+peach
+shrimp
+ribs
+fierce
+rises
+seoul
+popped
+fuse
+banker
+quest
+spark
+warmth
+expose
+shelf
+peak
+shaft
+rupees
+rash
+blamed
+jeans
+glow
+crab
+jammed
+sip
+roar
+beggar
+cope
+pinch
+organs
+hips
+shaped
+towers
+towels
+clip
+pad
+ninth
+hugh
+meg
+phoebe
+favors
+carson
+lodge
+delhi
+cheeks
+rue
+hack
+feds
+lasts
+yacht
+greed
+goals
+spends
+hen
+shook
+des
+masks
+yuan
+nailed
+rider
+bumped
+mamma
+paulo
+stern
+agenda
+resume
+armies
+tasted
+drift
+thirst
+treats
+vulgar
+waist
+creeps
+grasp
+monte
+heroic
+slam
+smiled
+onions
+sultan
+extend
+marcel
+baked
+tigers
+shack
+gaze
+eden
+chart
+tidy
+monks
+codes
+lyrics
+rushed
+hum
+est
+fax
+shoo
+vacuum
+notify
+bribe
+mock
+plea
+flint
+frost
+clap
+trauma
+stoned
+parrot
+dozens
+stray
+axe
+freed
+calvin
+refer
+herb
+shells
+pinky
+crop
+paths
+garlic
+kin
+veil
+robber
+whew
+cracks
+gasp
+setup
+kilos
+wont
+bosses
+sew
+fisher
+reform
+dearly
+junkie
+sock
+courts
+spared
+intact
+agony
+scored
+stack
+oak
+ohio
+stain
+fran
+pier
+liking
+loosen
+comet
+obtain
+piggy
+roller
+flown
+refuge
+traces
+rag
+vile
+scouts
+scram
+reduce
+eugene
+exotic
+dusty
+peel
+swept
+heap
+shines
+pasta
+versus
+surf
+grease
+backed
+clowns
+shovel
+cooler
+fades
+ambush
+superb
+hollow
+pawn
+jingle
+slit
+byron
+moose
+zeus
+knots
+buenos
+topic
+hustle
+mute
+metro
+dash
+peek
+waving
+etc
+burial
+cuban
+ammo
+quid
+gag
+smokes
+keeper
+factor
+equals
+spear
+await
+views
+shin
+sleeve
+bunk
+glen
+arabs
+naval
+losses
+boogie
+julius
+hose
+millie
+bushes
+vanish
+slower
+lire
+flour
+miriam
+bitten
+pearls
+scars
+womb
+treaty
+stamps
+finals
+weary
+stalin
+lent
+unite
+tong
+poles
+spine
+lucia
+sadly
+masses
+zombie
+wan
+bliss
+isaac
+saloon
+verse
+reign
+purely
+biting
+elaine
+cozy
+token
+archer
+elite
+tray
+steer
+craft
+flock
+ripe
+tubes
+horace
+coop
+ant
+trophy
+ruler
+brute
+hog
+lease
+squeal
+boiled
+potion
+grapes
+tuna
+dwarf
+lounge
+robots
+invest
+franco
+rogue
+taller
+ranks
+fluid
+asian
+mayday
+spice
+poster
+liable
+rail
+thai
+giants
+hart
+timer
+sunk
+shelly
+toxic
+lethal
+info
+alaska
+nuns
+adjust
+parlor
+sticky
+prague
+lang
+hides
+sane
+rainy
+dose
+kidney
+whoops
+gutter
+legacy
+bake
+bites
+absent
+lid
+bricks
+whites
+unlock
+poke
+panel
+gap
+condom
+traps
+visa
+tailor
+linked
+reject
+maps
+ark
+buzzes
+flute
+diner
+shaved
+acres
+rival
+agrees
+puff
+banner
+dixie
+fees
+jumps
+bats
+sights
+daring
+listed
+blink
+cigars
+sway
+vest
+healed
+sketch
+soaked
+claw
+pupil
+chico
+casual
+knot
+stud
+salon
+fabric
+skate
+sheer
+racist
+onion
+heave
+enters
+ale
+amelia
+finch
+exile
+spells
+extent
+fatty
+glance
+vet
+flows
+assets
+calf
+thugs
+whales
+realm
+kitten
+slick
+poppy
+edith
+elders
+filmed
+medals
+buyer
+strap
+bundle
+saves
+toad
+cement
+seduce
+stroll
+utter
+classy
+scrap
+apache
+hardy
+yield
+runway
+reich
+lump
+limo
+tow
+cognac
+warmer
+frogs
+unity
+lone
+whitey
+define
+dine
+amigo
+grudge
+cobb
+sewer
+pairs
+punks
+newton
+nicest
+vase
+hebrew
+parish
+vows
+marble
+savior
+raft
+monroe
+hogan
+angus
+holler
+preach
+tab
+depths
+framed
+arrows
+mint
+brace
+broom
+arena
+splash
+intent
+ernest
+scoop
+abused
+woe
+ivy
+noses
+fright
+repent
+nixon
+petrol
+velvet
+steals
+fuller
+gulf
+probe
+aisle
+select
+lens
+pupils
+legion
+plaza
+puerto
+coats
+grim
+vanity
+void
+idle
+fang
+nay
+psst
+colt
+pickup
+sol
+loop
+lizard
+skiing
+sorted
+layer
+poured
+fury
+shrine
+thorn
+costa
+trials
+cola
+naples
+medic
+motto
+mal
+nasa
+grid
+hairs
+belts
+shuts
+sewing
+stakes
+goats
+snaps
+swap
+blacks
+curve
+sinner
+retard
+videos
+tenth
+yummy
+elbow
+bombay
+charts
+golly
+doe
+pets
+newly
+scrub
+rhyme
+carrot
+gangs
+wagner
+beck
+audio
+flavor
+judith
+morons
+cradle
+ruling
+sniper
+judas
+milton
+gerald
+thrust
+bunker
+mode
+slack
+males
+novels
+coup
+funky
+cult
+aspect
+pesos
+burton
+wage
+bluff
+gifted
+karma
+boards
+hunted
+disk
+willis
+sloppy
+wrath
+rapid
+buses
+urban
+turk
+storms
+riddle
+mild
+beau
+moss
+jerks
+draws
+judged
+pause
+milady
+bathe
+bombed
+warsaw
+abort
+willow
+seized
+dexter
+merci
+tickle
+flags
+scam
+chili
+swat
+bomber
+flora
+thug
+tempo
+decade
+grove
+ideals
+crows
+sparks
+shalt
+yelled
+signor
+jonah
+blouse
+numb
+quack
+greeks
+arise
+havana
+richer
+piglet
+fruits
+dares
+thine
+bates
+ethics
+alter
+crowds
+lotus
+shakes
+wager
+bulls
+doggy
+fishy
+curfew
+geneva
+vague
+slug
+ironic
+lure
+summon
+hiring
+butts
+cosmic
+turf
+flirt
+semi
+hound
+sahib
+pint
+wretch
+seldom
+loot
+mozart
+partly
+claws
+wool
+woof
+clive
+thighs
+doth
+sites
+trout
+packs
+noted
+hotter
+caviar
+eldest
+banned
+jasper
+norma
+dim
+mills
+chilly
+fuzzy
+hurrah
+gibson
+beaver
+turks
+convoy
+birdie
+sniff
+cain
+dent
+merlin
+yale
+mutt
+med
+bleep
+resent
+lace
+calmly
+freaky
+memo
+lowest
+ribbon
+pod
+midst
+wagons
+dome
+tackle
+reef
+midget
+marker
+relate
+chalk
+hayes
+swift
+charms
+esteem
+pike
+weasel
+dental
+opium
+critic
+unload
+heidi
+ache
+polo
+tossed
+cutter
+chiefs
+insect
+regime
+flank
+barge
+oxford
+crank
+streak
+lex
+gong
+basil
+crabs
+samba
+aiming
+gale
+fiddle
+limp
+marian
+risked
+fiance
+holden
+shaggy
+hitch
+aires
+moi
+invade
+wits
+stitch
+cuckoo
+coco
+pow
+expand
+tipped
+osaka
+peas
+rags
+peep
+amazon
+shifts
+gospel
+voting
+mare
+finn
+parks
+bun
+infant
+curry
+crops
+buckle
+trim
+plum
+marsh
+mop
+scope
+idol
+cuffs
+paddy
+sailed
+cobra
+macho
+sinned
+forged
+sails
+toll
+chaps
+mining
+rehab
+merit
+flea
+dandy
+traded
+kyoto
+reader
+fists
+crooks
+rates
+bind
+reborn
+grind
+stinky
+thesis
+haste
+crib
+stocks
+blades
+damp
+hating
+munich
+amuse
+warp
+sly
+gloomy
+atom
+anders
+awards
+spa
+mixing
+undo
+thumbs
+rookie
+sweaty
+marge
+blunt
+grill
+verify
+haired
+chimes
+crews
+pasha
+canvas
+recite
+weighs
+geek
+mist
+wales
+padre
+stated
+brooks
+wesley
+purity
+reno
+weekly
+survey
+bender
+feeds
+polar
+athens
+allied
+valid
+ronald
+jock
+truce
+tribes
+alma
+tumor
+madly
+spooky
+riches
+liars
+erased
+para
+pas
+oceans
+nova
+bums
+hag
+sonar
+gandhi
+trusts
+funk
+lining
+motors
+fills
+tummy
+stash
+tel
+patron
+hump
+kite
+irony
+carved
+tutor
+tanner
+traced
+crowns
+detect
+pots
+locals
+perish
+cloak
+hast
+baths
+chops
+spicy
+caves
+wed
+plains
+cam
+pong
+crude
+consul
+exits
+bronx
+juicy
+morals
+valve
+melted
+bash
+zoom
+farms
+slips
+halls
+dicks
+gamma
+roles
+mccoy
+employ
+cooks
+arch
+ole
+bangs
+scrape
+solemn
+blend
+ounce
+typing
+toto
+mein
+raven
+update
+stool
+shades
+necks
+lime
+honors
+boar
+teller
+grams
+hare
+pact
+immune
+sawyer
+sponge
+genes
+heed
+yank
+bio
+truman
+yoga
+apes
+pins
+bryan
+caller
+saturn
+joints
+cuff
+adding
+beta
+trench
+bakery
+newest
+wink
+depart
+disc
+bah
+fuhrer
+panda
+kettle
+tsar
+leash
+gadget
+abbey
+dub
+hull
+verge
+haunt
+ban
+gravy
+buns
+openly
+prank
+asthma
+annoy
+martyr
+doggie
+sicily
+poets
+knox
+peg
+tart
+nod
+helm
+pest
+upbeat
+crate
+warner
+dwight
+pinned
+posts
+icy
+babes
+occupy
+styles
+rover
+squash
+seals
+morale
+beacon
+prep
+cairo
+czech
+rests
+alarms
+poorly
+mend
+essay
+pies
+paws
+hums
+ethel
+denial
+bikes
+rib
+mao
+snorts
+cereal
+rene
+tonic
+depot
+eater
+pip
+milky
+hasty
+rattle
+greta
+pea
+debris
+wedded
+coral
+snacks
+tens
+fewer
+ida
+berry
+eagles
+castro
+tavern
+stench
+syrup
+donor
+elf
+falcon
+firmly
+reel
+harlem
+erin
+yonder
+shaken
+summit
+guru
+suited
+whilst
+smelly
+remark
+loans
+stages
+maine
+boost
+spits
+remedy
+jockey
+errand
+kilo
+maids
+oppose
+slot
+bred
+nevada
+foods
+dwell
+stored
+roam
+laurel
+hunk
+hyde
+viva
+freud
+vent
+posse
+occurs
+squire
+serge
+tex
+chump
+hallo
+morton
+crappy
+tying
+chores
+rodeo
+pickle
+packet
+noel
+tenant
+echoes
+paddle
+stains
+hoover
+marx
+sod
+tapped
+wrists
+jap
+amos
+revs
+tee
+nearer
+limb
+laden
+eddy
+fading
+rental
+doodle
+trek
+seeks
+defy
+groove
+steed
+gents
+creaks
+jets
+demo
+piper
+bamboo
+dye
+tuned
+paw
+moons
+tyrant
+tunes
+guided
+adapt
+cork
+cosmos
+revoir
+sermon
+lisbon
+kat
+poetic
+patsy
+dread
+hooks
+menace
+fasten
+rosy
+bulb
+clutch
+reg
+raises
+raging
+ceo
+quiz
+miners
+links
+parted
+utmost
+utah
+squirt
+loaf
+lam
+lava
+outlaw
+donate
+voodoo
+lists
+learns
+reds
+argued
+beads
+foam
+goody
+decree
+hazard
+uptown
+batch
+bosom
+hicks
+bases
+dowry
+meteor
+flare
+strung
+adds
+weirdo
+saul
+raja
+corny
+anthem
+batter
+aimed
+groan
+squid
+moms
+cadet
+revolt
+chum
+greasy
+meow
+mat
+tar
+islam
+raving
+sow
+lays
+bugle
+maxim
+howl
+herbs
+cutie
+aces
+garcia
+cetera
+limbs
+adolf
+weaker
+lice
+boiler
+peters
+dorm
+mourn
+screws
+docks
+regain
+cocoa
+valet
+shapes
+goofy
+excess
+wimp
+felony
+siege
+comics
+cheeky
+soy
+iced
+chubby
+prop
+muddy
+reagan
+taped
+slate
+shogun
+impose
+sank
+rudder
+sized
+steep
+hash
+windy
+grabs
+froze
+slash
+arctic
+chic
+spades
+crunch
+stared
+canned
+hopper
+tad
+dames
+nero
+jinx
+domain
+noodle
+stuffy
+yin
+angles
+email
+frau
+skates
+rigged
+grunt
+epic
+choked
+veer
+hurray
+swings
+harmed
+caress
+convey
+nobel
+whoop
+fling
+abbot
+darker
+faking
+sneaky
+manor
+puss
+caps
+danish
+mace
+daft
+multi
+jumbo
+scales
+stance
+blush
+touchy
+apiece
+banged
+grub
+asset
+skirts
+mutiny
+enjoys
+casper
+radius
+nerd
+thigh
+masked
+copied
+nosy
+crust
+colder
+sleigh
+joanne
+skins
+wiser
+moor
+flop
+serum
+geisha
+bronze
+zen
+jude
+fiery
+undone
+norm
+snuck
+carve
+pluck
+jab
+par
+loco
+matrix
+facial
+legged
+bled
+seller
+tame
+pry
+inmate
+ridden
+snitch
+sands
+tung
+rouge
+alias
+abide
+skunk
+yahoo
+relay
+blaze
+rained
+ere
+foe
+coca
+mosque
+sap
+eerie
+chant
+cod
+bing
+salty
+dirk
+mart
+bowls
+tribal
+spade
+awaken
+flyer
+dane
+recess
+drip
+lira
+dew
+riots
+soak
+heated
+tempt
+stein
+marcia
+oregon
+spears
+brag
+poking
+teen
+orion
+fiend
+abyss
+pumps
+moan
+coyote
+jumper
+clam
+broker
+jaws
+tread
+rust
+subs
+unreal
+witty
+buffet
+loony
+lunar
+vacant
+riders
+shores
+litter
+ramp
+pup
+fin
+cinch
+rye
+lenin
+gunner
+mold
+gays
+risen
+lamps
+sierra
+humbly
+slob
+slay
+ripper
+whim
+dryer
+zipper
+vocal
+ankles
+lama
+rep
+elect
+spaces
+faded
+armour
+vicar
+grape
+sacks
+wrench
+squeak
+rhodes
+xavier
+elves
+jared
+dense
+sioux
+adored
+cub
+genie
+arc
+manly
+bikini
+veal
+cohen
+palms
+weaver
+mink
+nag
+turbo
+vermin
+diesel
+mutant
+meadow
+moody
+geese
+emerge
+ultra
+loft
+squat
+shoved
+harp
+okey
+bumper
+ahoy
+adios
+trunks
+dairy
+weave
+wilt
+awe
+cello
+jug
+pits
+amused
+inc
+flick
+swam
+rites
+wider
+flats
+pros
+titles
+builds
+moo
+flap
+tiring
+voters
+groovy
+yelps
+barb
+sphere
+ingrid
+lassie
+beams
+baking
+psych
+slain
+downs
+lakes
+hindi
+hassle
+hale
+omen
+hindu
+laptop
+runt
+shady
+grin
+uneasy
+forge
+linen
+plato
+hacked
+sinful
+howls
+bout
+braces
+uncles
+curb
+hub
+lawful
+dusk
+nile
+hippie
+wails
+viking
+slope
+cubs
+aurora
+bounds
+omega
+muffin
+mules
+cables
+stem
+diaper
+baton
+clocks
+licked
+camels
+plasma
+routes
+farce
+ludwig
+pools
+fags
+gauge
+sensed
+lever
+ferris
+layers
+brink
+canoe
+beetle
+filter
+canary
+senile
+mails
+antony
+tally
+radios
+snappy
+mann
+pluto
+germs
+thump
+blares
+rim
+rested
+steaks
+deuce
+snowy
+sully
+lacks
+maple
+cube
+pep
+outs
+unpack
+eel
+geezer
+crisp
+faults
+dost
+patent
+sect
+grande
+spank
+jumpy
+pumped
+tends
+dakota
+debut
+titus
+rows
+layout
+cling
+weeds
+trifle
+oblige
+wilder
+ration
+dots
+pens
+taps
+knob
+eta
+scold
+sizes
+wright
+nets
+jacks
+digs
+rake
+import
+brew
+manu
+sham
+laps
+woken
+goon
+posing
+hazel
+grumpy
+paints
+chunk
+atoms
+skulls
+minnie
+ese
+hoax
+gals
+tents
+ivory
+ogre
+quits
+shah
+fluffy
+duffy
+astray
+dos
+barren
+crates
+filing
+lark
+herald
+slimy
+ares
+horrid
+edited
+cramp
+sued
+brats
+govern
+detour
+shush
+logs
+vine
+paso
+carver
+tinker
+fowler
+zurich
+trans
+zebra
+mating
+aerial
+muck
+notre
+hawks
+attach
+sauna
+safest
+douche
+gem
+rubles
+viper
+stingy
+scalp
+devote
+rhymes
+fidel
+cloudy
+asap
+aging
+redeem
+chute
+mambo
+nato
+inhale
+pastry
+widows
+unions
+ezra
+fusion
+budge
+sitter
+gavel
+ave
+revive
+scroll
+bruise
+joys
+deacon
+bonnet
+cone
+fossil
+dublin
+tug
+wench
+shaky
+tram
+plunge
+wail
+tucked
+hacker
+retain
+homey
+deb
+fleas
+iraqi
+disney
+edges
+fret
+notch
+mayo
+wept
+bridal
+mentor
+parcel
+cages
+mush
+polls
+zodiac
+liras
+krauts
+prizes
+scarce
+gears
+beak
+lifts
+uphold
+errors
+folly
+export
+uno
+taco
+casket
+grieve
+lest
+titan
+bumps
+biggie
+bop
+kimono
+banjo
+bows
+toot
+griff
+clone
+merger
+broads
+lass
+napkin
+sen
+gao
+tibet
+noose
+blinds
+fender
+finale
+hymn
+flaw
+afar
+warmed
+mashed
+slides
+adieu
+pagan
+joyful
+heist
+bowie
+paste
+bummer
+sirs
+trance
+famine
+tablet
+clause
+pascal
+maze
+clarke
+stale
+cactus
+folded
+tours
+din
+domino
+troupe
+pronto
+amulet
+attila
+olives
+decay
+morse
+vouch
+tiles
+itchy
+pedal
+quarry
+thor
+grail
+puck
+goons
+mailed
+artery
+props
+needy
+haw
+rated
+calmed
+toots
+intern
+thuds
+pushes
+vivid
+fishes
+ounces
+eiffel
+ufo
+longed
+brow
+bach
+hooper
+moth
+tags
+dads
+labs
+magnet
+aching
+riggs
+insert
+tones
+buyers
+aft
+digest
+legit
+furry
+defect
+bumpy
+sprung
+leaks
+climax
+henrik
+slater
+tasks
+ledge
+cliffs
+fours
+dona
+acute
+crater
+ordeal
+giddy
+marvel
+wiping
+suing
+portal
+lesser
+vein
+athena
+heater
+feeble
+racial
+gunnar
+cawing
+joins
+rumble
+barker
+crummy
+fabian
+basin
+hiking
+finer
+corky
+rating
+edit
+aloud
+tao
+futile
+derby
+bearer
+lotion
+cove
+hilary
+lefty
+whines
+deploy
+rubbed
+cutest
+laddie
+venom
+picky
+una
+snot
+sneeze
+bailed
+crotch
+aunts
+arabia
+capone
+troll
+opener
+robes
+verbal
+overdo
+emery
+rubble
+blanks
+lenses
+module
+clash
+sash
+goof
+spur
+frames
+blokes
+rom
+hounds
+walkie
+dung
+mellow
+buff
+condo
+valium
+yogurt
+cuddle
+bypass
+evolve
+sanity
+isle
+labels
+unseen
+obeyed
+verses
+sage
+mast
+snob
+ref
+kosher
+kisser
+posh
+comply
+span
+nutty
+scoot
+muller
+mort
+snuff
+sled
+extras
+input
+teeny
+decoy
+irons
+timber
+devour
+dart
+growl
+aches
+thorns
+creed
+elbows
+vista
+chewed
+sums
+marrow
+voila
+rite
+frying
+taj
+jog
+wiggle
+tat
+mecca
+saucer
+booing
+apron
+index
+gabby
+reset
+spoilt
+salsa
+fudge
+fences
+kaiser
+trot
+salami
+meows
+pear
+drying
+spoils
+softer
+mar
+floats
+knack
+surge
+spoons
+ulcer
+trader
+vie
+jive
+tofu
+pecker
+buffy
+orchid
+piles
+differ
+craven
+pricks
+hutch
+staged
+lambs
+cons
+glued
+yanks
+tack
+hangar
+neighs
+mortar
+oyster
+shred
+gram
+saliva
+texts
+wand
+cot
+renew
+assign
+coo
+acre
+fay
+lair
+boxers
+lyon
+aloha
+aide
+onward
+fitted
+sliced
+slogan
+gallon
+paces
+decker
+user
+rugby
+plank
+gogh
+drunks
+sling
+margin
+raids
+chord
+knit
+munch
+myrtle
+mater
+salaam
+delete
+drone
+spinal
+matron
+hansen
+badger
+greens
+mantle
+viola
+hoist
+ore
+makers
+thirds
+kip
+chug
+admits
+deceit
+rinse
+ell
+stoop
+slowed
+comfy
+lei
+hisses
+gender
+gore
+johns
+adores
+dire
+aryan
+hens
+smug
+haines
+versa
+duct
+pillar
+buds
+swede
+ins
+tucson
+civic
+diver
+bowman
+oddly
+speedy
+iowa
+hark
+omaha
+manure
+ballad
+trend
+stump
+refund
+gorge
+guides
+axis
+mystic
+baboon
+hoot
+snail
+faked
+giggle
+vale
+ceased
+pug
+crumbs
+snails
+hoop
+strive
+unjust
+mugs
+offs
+bolts
+fiber
+leaked
+brawl
+brook
+excite
+saigon
+gator
+homage
+wholly
+stomp
+balboa
+truths
+sparky
+cosmo
+dumps
+cheats
+cupid
+brig
+dada
+emmy
+puddle
+cleans
+pulp
+hosts
+wisely
+sacked
+rivals
+nicked
+amends
+expel
+bribed
+hugged
+rave
+humane
+curls
+muse
+earns
+guild
+sinks
+bey
+taro
+clamp
+covert
+manson
+spat
+gall
+decks
+ponies
+wills
+crave
+helper
+stung
+sturdy
+tights
+crest
+cooing
+washes
+absorb
+tuning
+holder
+marsha
+lowly
+poe
+omelet
+ensign
+ether
+welsh
+melts
+polka
+buggy
+furs
+solely
+postal
+grazie
+curves
+digger
+flyers
+poodle
+phoney
+havoc
+inland
+tahiti
+smear
+wildly
+loathe
+lumber
+wiener
+albums
+spook
+messes
+valued
+crazed
+pads
+stride
+scot
+spouse
+louse
+macy
+gunman
+pepsi
+detain
+render
+shaman
+morbid
+raided
+whine
+demise
+darned
+barbed
+writ
+mugged
+morrow
+sewers
+reload
+neon
+garret
+elmer
+basics
+lain
+saxon
+dunk
+safari
+pager
+reflex
+sonic
+zones
+reaper
+unfit
+boils
+notary
+stormy
+stag
+wines
+darts
+kelvin
+bugged
+aviv
+curl
+accord
+fig
+shawl
+trump
+caste
+gravel
+popeye
+mil
+arson
+bodily
+miner
+talker
+peril
+regent
+meddle
+lagoon
+stings
+abc
+fink
+rails
+flaws
+midday
+leone
+widely
+dues
+sordid
+galley
+barley
+shalom
+moist
+champs
+feat
+reeves
+herbal
+denies
+intro
+joyous
+jest
+hun
+rabble
+hades
+tuxedo
+bribes
+hulk
+hostel
+borne
+alps
+snoop
+encore
+upsets
+hogs
+quota
+carton
+dell
+wiring
+lima
+burma
+vortex
+posed
+edison
+huddle
+flares
+mascot
+garde
+fluids
+sedan
+peer
+inject
+petals
+reap
+hugs
+plow
+newark
+hermit
+forum
+saga
+bulk
+lacked
+dodger
+cavity
+bogus
+apt
+rugged
+slag
+rhino
+cosy
+ducky
+exhale
+hind
+fumes
+payday
+snarls
+cecil
+smoker
+server
+vowed
+donuts
+mango
+floods
+boyle
+slum
+satin
+jackal
+clink
+grants
+icon
+dicky
+hedge
+hooves
+attain
+shabby
+cures
+spiral
+clover
+swears
+wacky
+misty
+lug
+tilt
+unkind
+rocker
+dreary
+gurney
+rigid
+exiled
+boon
+oasis
+jacked
+speeds
+castor
+loaned
+broth
+rah
+ozone
+rubin
+bathed
+frown
+curses
+snore
+blames
+trails
+jell
+peeled
+penal
+leech
+mow
+chimp
+saudi
+speck
+array
+foxy
+slices
+locket
+inter
+poorer
+cider
+smokey
+shiva
+triad
+floss
+vinci
+divert
+poll
+orient
+frenzy
+airs
+enlist
+wham
+waved
+rods
+holdup
+cranky
+hinges
+swung
+aids
+ratio
+gains
+nosed
+plots
+clips
+latter
+divers
+sweeps
+wad
+carts
+nobles
+unwell
+timid
+shun
+hybrid
+foxes
+fern
+gases
+tumble
+unfold
+bowen
+ante
+tanker
+tacky
+sesame
+peers
+bursts
+corral
+pouch
+serene
+untrue
+pushy
+linger
+sluts
+frail
+calves
+nectar
+boast
+franks
+cutler
+surfer
+ports
+roofs
+coy
+lilies
+hick
+clams
+malice
+yawns
+penn
+latch
+magnum
+jaguar
+chino
+vulcan
+stares
+scraps
+spun
+whiff
+spree
+basque
+amaze
+gaius
+rican
+levi
+rand
+parson
+rewind
+yogi
+afro
+yak
+delays
+fulfil
+goblin
+aura
+owning
+beirut
+bog
+watts
+spices
+tailed
+hearty
+rabies
+relic
+forks
+shocks
+slugs
+mingle
+gloom
+rung
+herds
+plugs
+tactic
+badges
+sassy
+chords
+levy
+bids
+cubes
+slows
+pizzas
+glide
+tic
+amigos
+combo
+oracle
+sided
+gen
+specs
+qui
+timed
+logo
+rowing
+mag
+pilar
+bogey
+tile
+healer
+fatter
+barred
+quaint
+haze
+vents
+pans
+costly
+mirage
+refill
+cheesy
+wedge
+rotate
+odor
+tarts
+curt
+rocked
+mound
+pious
+gala
+whoosh
+twig
+sahara
+utopia
+hornet
+ethnic
+zed
+patio
+jars
+manic
+fussy
+outrun
+wary
+detest
+naming
+stout
+friar
+quebec
+micro
+goner
+anew
+bowels
+czar
+tov
+cartel
+taxis
+imply
+zulu
+cluck
+wasp
+plano
+enable
+rook
+spins
+pinkie
+hubby
+dialed
+carnal
+judo
+clans
+alms
+dreamy
+barrow
+midway
+sox
+hoods
+crock
+soften
+drapes
+elk
+gobble
+dears
+hither
+snort
+micah
+plumb
+scorn
+moods
+gras
+blasts
+mammal
+temp
+entity
+flaps
+blur
+sentry
+dearie
+merge
+shreds
+zap
+gant
+stunts
+toil
+owls
+slab
+talkie
+twitch
+jester
+lineup
+bono
+edgy
+gigs
+wraps
+vendor
+tout
+plaque
+slums
+rural
+keg
+gaul
+cyborg
+flakes
+seaman
+fungus
+sheik
+sewed
+yap
+thaw
+pap
+lemons
+chills
+gaming
+potent
+oars
+bleak
+heath
+hearse
+spurs
+mayhem
+dazzle
+tabs
+piled
+strand
+weaken
+muzzle
+typed
+lorry
+thrive
+ballot
+rink
+nil
+lured
+rhode
+hoops
+sleazy
+faucet
+dharma
+stork
+irs
+starry
+picket
+possum
+gehrig
+reggae
+hula
+tombs
+doves
+begs
+petit
+riff
+mutton
+gags
+hive
+chunks
+wreath
+bazaar
+psyche
+dipped
+solace
+oxen
+vested
+malt
+disarm
+rhea
+meek
+mormon
+cedar
+gent
+unborn
+bestow
+plight
+cadets
+stat
+urn
+porky
+gemma
+donut
+retail
+peking
+brunch
+honky
+refers
+thrash
+banish
+sensor
+flair
+overly
+assess
+drool
+icebox
+holed
+jiffy
+output
+frosty
+carp
+kroner
+racism
+clang
+folder
+helium
+stalk
+lanes
+duo
+lash
+mooing
+ragged
+fangs
+sera
+wigs
+brood
+dukes
+pantry
+whirl
+purge
+bleach
+snores
+shiver
+alba
+winged
+brooch
+dyed
+bulbs
+quill
+racer
+dinars
+merits
+maggot
+washer
+plump
+reopen
+coded
+fluke
+molten
+peaks
+payoff
+doses
+strips
+minors
+pours
+teens
+pimps
+shone
+timers
+dory
+blazes
+comma
+slaps
+toledo
+nausea
+elijah
+venue
+rushes
+hauled
+rents
+wring
+louvre
+twain
+maddox
+rosary
+chime
+lumps
+infect
+tux
+mead
+hitter
+harass
+grad
+reins
+namely
+lodged
+slayer
+clerks
+crypt
+trough
+calms
+shrewd
+grains
+dover
+trades
+neatly
+vogue
+occult
+hombre
+berg
+bern
+bends
+volts
+vines
+spleen
+ashton
+sao
+soar
+unrest
+ravine
+skis
+gazing
+relish
+arcade
+stalls
+prune
+muster
+pence
+genre
+maitre
+amidst
+tidal
+pox
+fished
+cashed
+tvs
+gill
+heals
+canton
+prima
+cooled
+bonny
+wraith
+kappa
+oslo
+gauls
+gowns
+canon
+digits
+straws
+awoke
+prone
+urged
+lax
+lard
+halo
+lush
+usher
+tagged
+arouse
+skid
+pilate
+wick
+dud
+dimes
+lupin
+roper
+beeper
+saber
+quo
+hiss
+salem
+squads
+walnut
+fats
+keats
+idaho
+casing
+rooted
+cretin
+ample
+persia
+caliph
+envoy
+eskimo
+gage
+stokes
+biker
+tori
+bleeds
+cooped
+viable
+gulls
+oats
+tides
+pooch
+torah
+goalie
+coil
+gulps
+arose
+albany
+swells
+lyons
+loch
+yippee
+perch
+bookie
+avatar
+lazar
+urges
+felon
+awol
+eaters
+gigolo
+wrongs
+uproar
+ruckus
+ami
+fakes
+heirs
+nerds
+mazel
+taping
+owing
+paced
+strife
+aroma
+grocer
+relics
+ringer
+mccall
+bras
+cougar
+frigid
+towed
+spilt
+firms
+quail
+slopes
+majors
+gums
+opal
+newt
+sodium
+loner
+jailed
+thames
+jig
+myths
+rips
+chit
+sari
+suitor
+corpus
+rubies
+raf
+leper
+yearn
+seine
+boa
+bali
+mesa
+deli
+juno
+mets
+swarm
+poses
+edible
+tramps
+feud
+outing
+foggy
+mash
+gems
+colon
+nix
+salts
+elope
+hindus
+dwarfs
+seeker
+bene
+weir
+trojan
+rapper
+nab
+locke
+fringe
+aims
+manila
+casts
+bidder
+fins
+sewn
+conned
+kahn
+evils
+nappy
+tulip
+hyena
+buick
+hunts
+pups
+gulp
+flashy
+fuzz
+parry
+conn
+atone
+nigh
+mite
+abode
+hyper
+nugget
+leaned
+hors
+renoir
+paging
+bison
+jerky
+diva
+cicero
+oaks
+pollen
+lyra
+wipes
+hock
+suns
+fates
+glare
+ado
+lashes
+rulers
+cramps
+emir
+heresy
+brides
+quince
+envied
+outlet
+lumpy
+horde
+chimps
+tended
+flier
+mats
+rodent
+stow
+inning
+bolted
+bogart
+germ
+hap
+weber
+enigma
+rev
+tory
+honda
+hectic
+hopped
+swiped
+coarse
+swamps
+soothe
+fluff
+sprout
+disks
+neural
+swims
+puffs
+splits
+snows
+viewed
+pints
+flask
+hanky
+warms
+mane
+ruddy
+puffy
+mala
+dumber
+dunes
+straps
+wither
+crafty
+slop
+scab
+faulty
+queers
+atlas
+moors
+buoy
+pebble
+valves
+panels
+gaulle
+vacate
+pun
+chaser
+deluxe
+breeds
+puny
+gallop
+canopy
+vive
+orb
+pres
+baa
+geiger
+gusto
+rumba
+graces
+vector
+tolls
+ware
+weeps
+strut
+turnip
+siam
+swoop
+dept
+stacks
+perks
+rabid
+audit
+candid
+glum
+ussr
+dole
+burner
+sequel
+borg
+largo
+clank
+uterus
+users
+sulfur
+exceed
+walrus
+mixer
+simmer
+bongo
+dow
+gel
+dahlia
+spawn
+gentry
+pranks
+foil
+whips
+mangy
+piazza
+ticks
+ploy
+beagle
+welch
+scuba
+tenor
+chokes
+tingle
+turin
+bowed
+sac
+melons
+cuss
+grover
+liege
+fronts
+oaf
+spikes
+oft
+liner
+crumb
+rica
+upward
+cycles
+impure
+hurl
+craps
+shucks
+peachy
+berth
+drains
+birch
+kebab
+limbo
+skater
+odin
+jag
+danube
+rut
+quotes
+yarn
+ratted
+wharf
+cabs
+sumo
+pointy
+eels
+sever
+hex
+chaste
+dosage
+pubic
+vices
+soles
+hoof
+kinder
+twos
+quoted
+hairdo
+jihad
+kiev
+banzai
+duly
+snout
+yon
+prays
+lag
+abner
+hippo
+yorker
+fiesta
+rowdy
+burps
+pusher
+auld
+deemed
+swipe
+jigsaw
+chirps
+draper
+stun
+dei
+taffy
+flowed
+blower
+plough
+thrice
+avail
+isaiah
+afloat
+trait
+fated
+crick
+algae
+hijack
+indies
+bayou
+hippy
+fetish
+herpes
+chases
+afghan
+moths
+homing
+lapse
+clergy
+itches
+embark
+puking
+minion
+trusty
+daffy
+cabins
+staked
+fiasco
+gills
+amour
+fouled
+cords
+oval
+arises
+unsure
+funded
+soho
+soiled
+squawk
+fickle
+repaid
+iceman
+bony
+twit
+jams
+redo
+python
+hanks
+snag
+unholy
+cuter
+cubans
+mower
+crispy
+pang
+fester
+iodine
+hints
+hussy
+thong
+hem
+plait
+desks
+poked
+chrome
+leaps
+grange
+glitch
+mercer
+gunned
+duet
+bashed
+glands
+drags
+podium
+coney
+prying
+nos
+haunts
+elm
+catchy
+juices
+sci
+alamo
+fetus
+lucid
+fixes
+canine
+armada
+medina
+liters
+whims
+cram
+deduct
+mumble
+manned
+novice
+sewage
+tinkle
+torso
+bowler
+briar
+flake
+rejoin
+snug
+dual
+piling
+clot
+cocked
+moat
+yam
+hermes
+brit
+theta
+serbs
+murmur
+trolls
+huts
+mould
+scans
+rift
+reefs
+croak
+mont
+attire
+spout
+fuses
+mantis
+dries
+finder
+vary
+drills
+beards
+rummy
+waffle
+tangle
+prompt
+funnel
+tubby
+cantor
+threes
+aggie
+moped
+embryo
+bowel
+fend
+screwy
+traits
+invoke
+morn
+hooch
+boxed
+winch
+camper
+ankara
+baht
+fined
+hooky
+looker
+odessa
+misled
+shamed
+naught
+dune
+reside
+tau
+camped
+ceases
+flunk
+amid
+crept
+rhine
+sphinx
+fiver
+fives
+sulk
+staten
+snotty
+crutch
+gothic
+vans
+graze
+paved
+relive
+caper
+nests
+proofs
+madden
+chants
+keaton
+shroud
+raced
+bran
+rad
+bijou
+marek
+bores
+ascend
+shrunk
+unwise
+tulips
+chopin
+aspire
+actin
+bails
+mousse
+quint
+valor
+purest
+themes
+dopey
+hobson
+sixes
+topped
+smelt
+damsel
+metals
+gemini
+blitz
+tamed
+pears
+rustle
+snowed
+indoor
+pail
+typhus
+mit
+turban
+boldly
+nibble
+foes
+beige
+aiding
+reacts
+whence
+mime
+clangs
+grit
+abrupt
+sheikh
+sickly
+verb
+fibers
+barf
+purify
+willed
+blurry
+zeros
+stub
+cipher
+weakly
+youths
+genoa
+gaps
+quart
+umpire
+lingo
+adrift
+nitwit
+sadist
+flung
+chefs
+quake
+creak
+vita
+flawed
+mach
+equity
+wards
+oily
+fie
+raisin
+bough
+privy
+batty
+defied
+gaping
+coping
+roster
+mans
+devout
+viewer
+koran
+bagged
+corned
+braid
+sodas
+replay
+wart
+bossy
+visas
+paine
+medics
+sexist
+tuba
+logged
+chisel
+pigsty
+prix
+anglo
+smudge
+pseudo
+ferret
+nebula
+feisty
+riled
+jolt
+latino
+chests
+slang
+ion
+laces
+vial
+hasten
+sax
+alto
+mags
+aspen
+bagel
+lotto
+nabbed
+reeks
+spied
+hover
+alleys
+brands
+tycoon
+cad
+harlot
+mended
+baggy
+stripe
+tact
+siding
+stank
+toxins
+duce
+medusa
+tenure
+pegged
+uglier
+pliers
+smithy
+fathom
+evade
+dismal
+bubbly
+bowing
+hype
+chunky
+piracy
+swans
+celery
+cob
+tacos
+gland
+silky
+dashed
+mania
+fluent
+slew
+druid
+frisk
+bead
+lobe
+loins
+fryer
+beret
+unsafe
+annoys
+ponder
+shes
+armory
+caged
+pines
+barman
+ironed
+taft
+otter
+amuses
+crease
+sutra
+retro
+lasers
+bikers
+toke
+ufos
+faust
+folds
+untied
+climbs
+creams
+gunmen
+tripe
+hiccup
+induce
+barter
+bronco
+warped
+stems
+pods
+brazen
+cleric
+cubic
+cortex
+fleece
+reigns
+cavern
+bonded
+lout
+mushy
+soot
+binds
+raffle
+primal
+lawman
+nylon
+digit
+quench
+lofty
+sloth
+java
+tipsy
+halves
+ignite
+blanc
+flips
+aloft
+cones
+tulsa
+yeti
+groin
+ranked
+linden
+vaults
+dodo
+hymns
+bale
+cabot
+brando
+measly
+creamy
+ledger
+rugs
+cokes
+bummed
+selves
+tweet
+mocked
+ardent
+juror
+laced
+unpaid
+fad
+snip
+teased
+eject
+gutted
+fines
+burp
+aqua
+trendy
+prowl
+giver
+bitchy
+jails
+graft
+lyric
+wasps
+marino
+vegan
+synced
+zion
+vitals
+sender
+cuddly
+prof
+dined
+mildly
+plated
+kennel
+gopher
+nev
+uncool
+elixir
+pleas
+mimics
+juggle
+eros
+takers
+taipei
+phi
+mendel
+almond
+sweats
+tarot
+sparta
+zeta
+gull
+keel
+slid
+mumbo
+swedes
+solves
+pocus
+snare
+smacks
+loon
+rec
+socket
+unison
+calmer
+sonata
+teapot
+smarty
+witted
+figs
+vixen
+dorado
+seams
+claps
+condor
+vibes
+luau
+sneaks
+pining
+clair
+corset
+sable
+alpine
+plums
+repel
+obi
+cools
+grips
+rotted
+nursed
+suede
+famed
+gassed
+volga
+beryl
+pooped
+twists
+curled
+titans
+lament
+dieter
+sic
+filly
+toddy
+rots
+phobia
+varied
+klan
+intake
+uss
+viral
+fruity
+wrecks
+braver
+drones
+taker
+hires
+flex
+suburb
+moro
+wanton
+ditto
+shay
+sup
+hyenas
+woes
+hue
+joss
+maxi
+movers
+puked
+glee
+wisest
+strays
+miser
+axes
+corona
+combed
+hocus
+dill
+bilge
+coals
+fiscal
+moles
+aria
+ruff
+dinky
+bona
+zing
+jurors
+hanger
+insure
+fliers
+bugler
+rouse
+chore
+ruse
+dainty
+canaan
+urging
+ganges
+bwana
+wield
+dab
+lockup
+pacing
+pus
+flak
+putt
+robs
+blooms
+dubbed
+vat
+ripple
+drowns
+pant
+levine
+pelvis
+fresno
+mined
+lurch
+rein
+upload
+jokers
+spaced
+dangle
+rapids
+licks
+yawn
+yip
+fares
+warts
+bengal
+fiends
+bossa
+cynic
+sears
+taurus
+sunup
+ducats
+sodom
+paged
+avant
+stirs
+eights
+mumps
+brahms
+bower
+vipers
+hazy
+femme
+trois
+unwind
+twerp
+donors
+sui
+kicker
+essays
+teal
+grammy
+jagger
+agile
+cordon
+vigil
+sores
+amiss
+waxed
+rogues
+sawed
+moping
+eureka
+mishap
+sledge
+canals
+swab
+camden
+tanned
+tartar
+fir
+napalm
+blip
+fora
+diem
+nines
+icing
+doings
+uphill
+devoid
+tho
+girdle
+smoky
+lowers
+operas
+dingo
+sevens
+yeast
+kaput
+twigs
+fiat
+wag
+savor
+savvy
+navel
+exert
+biased
+hoe
+char
+mullet
+mayan
+tiara
+rubs
+yeller
+guise
+untold
+pari
+sheds
+teas
+ninny
+brewer
+exempt
+babble
+rusted
+prissy
+rapes
+oink
+swami
+duds
+lewd
+plural
+fray
+eloped
+oar
+trays
+quilt
+frock
+enmity
+newer
+nosey
+guppy
+prose
+nudge
+grubby
+polio
+topics
+salted
+begone
+nasal
+verde
+modify
+liter
+gout
+width
+remake
+imam
+idols
+gourd
+bland
+vocals
+virgo
+hydra
+bleeps
+minh
+beaut
+wastes
+musket
+astern
+boars
+bustle
+dramas
+cravat
+braids
+dozed
+grouch
+expire
+bosun
+armpit
+fawn
+albino
+stooge
+ulcers
+petal
+coupon
+def
+arty
+bouncy
+humid
+loops
+jus
+ails
+madmen
+orgies
+frisky
+mosaic
+hep
+hefty
+regal
+amazes
+sickle
+sri
+petite
+gleam
+emblem
+ablaze
+rube
+sown
+relied
+longs
+footed
+libel
+pounce
+jailer
+sugars
+crosby
+grovel
+aught
+perm
+huns
+clad
+uranus
+lager
+wallop
+quiver
+mince
+dilly
+blot
+packer
+robust
+racine
+palate
+alumni
+gook
+injure
+kale
+poised
+greets
+dawned
+censor
+revere
+mongol
+ducked
+bros
+kites
+lister
+durham
+clones
+priors
+buffer
+meaner
+puffed
+bard
+garter
+dally
+putty
+banal
+facade
+pimple
+fisk
+menus
+argo
+gizmo
+mays
+quark
+dazed
+knave
+evenly
+picker
+res
+frolic
+sexes
+dimwit
+ticker
+hickey
+reek
+bins
+dolce
+quad
+splat
+clout
+browns
+douse
+wallow
+shafts
+taint
+yoke
+hordes
+fodder
+stiffs
+benign
+hedges
+byes
+curved
+comets
+cloned
+dusted
+piety
+exodus
+presto
+ornery
+sadder
+scamp
+zeal
+hinder
+afoot
+scurvy
+fide
+toxin
+ghouls
+caw
+sachs
+cappy
+toying
+revise
+stats
+choosy
+swig
+typist
+drafts
+alibis
+boned
+tunic
+yanked
+shifty
+reels
+enzyme
+cocoon
+narc
+sexier
+vinyl
+acne
+vapor
+carte
+refuel
+niche
+stair
+pauper
+deem
+grits
+docked
+deport
+burrow
+cooker
+acorn
+confer
+marlin
+hushed
+sicker
+compel
+coated
+craze
+timely
+jerked
+malls
+hoses
+goethe
+stead
+faro
+lunacy
+unruly
+tier
+fowl
+heaps
+olden
+shaker
+henna
+scots
+orbits
+salads
+squish
+kafka
+expo
+shriek
+nieces
+briefs
+devise
+watery
+grate
+rigor
+duped
+chirp
+undies
+pitied
+rajah
+proxy
+voter
+gable
+dives
+dials
+kits
+hops
+brogan
+papaya
+lahore
+silo
+sundae
+cong
+faxed
+terra
+deux
+padded
+glows
+faker
+anvil
+gar
+curing
+waive
+sprint
+subdue
+jugs
+ailing
+priced
+goto
+curie
+soggy
+cranes
+runny
+hanoi
+cheery
+trashy
+balm
+deity
+celtic
+befall
+lepers
+unites
+wobbly
+arches
+flabby
+bibles
+binge
+grazed
+enema
+brutes
+mardi
+rages
+census
+relies
+vests
+gab
+bias
+drowsy
+crawls
+toads
+bois
+mounts
+dotty
+suntan
+roost
+starch
+spiked
+slots
+shimmy
+mew
+tampa
+kiosk
+flops
+finely
+odious
+col
+spills
+getup
+suites
+bulge
+triads
+deduce
+dipper
+capped
+lupus
+nobis
+prod
+fuels
+deejay
+iraqis
+amish
+arming
+shiv
+sunken
+radish
+shears
+fused
+strait
+abuses
+godson
+lastly
+manchu
+huff
+garner
+toupee
+lilac
+tokens
+lute
+gloss
+saucy
+aline
+hobbit
+perky
+mortem
+oils
+bunks
+unused
+axle
+muted
+roamed
+mixes
+llama
+talon
+kelp
+tees
+septic
+flicks
+exec
+hearth
+cur
+atop
+assert
+mora
+braves
+pew
+aloof
+pester
+doubly
+hater
+gander
+borneo
+tins
+coupe
+spruce
+gauze
+aztec
+studs
+booker
+hailed
+rarest
+galore
+filet
+soir
+manger
+perk
+pores
+andes
+isis
+sawing
+fumble
+whiter
+gully
+tiptoe
+dias
+purses
+klutz
+mowing
+jiggle
+lube
+antics
+pellet
+lavish
+forte
+asher
+caved
+optic
+concur
+heifer
+sprang
+woven
+jour
+twirl
+crusty
+mints
+wicket
+sorely
+kook
+loaves
+jocks
+hernia
+cliche
+mire
+floppy
+fib
+sandal
+daze
+harpo
+nifty
+probes
+fable
+tiff
+clanks
+bitsy
+obeys
+pelt
+blob
+lope
+magma
+mitt
+serb
+dunce
+pawned
+madder
+hives
+alight
+humbug
+crafts
+creole
+vis
+dinghy
+acorns
+ethic
+smog
+discs
+prude
+shank
+amp
+slump
+gnome
+suave
+kimchi
+latent
+gazed
+homely
+eulogy
+warmly
+moll
+somber
+grimm
+leaky
+meats
+rustic
+bile
+conga
+chatty
+idling
+glazed
+kraft
+slurps
+lends
+cosa
+leapt
+avert
+tract
+ode
+danes
+clasp
+scenic
+stony
+booths
+diddle
+pips
+bowers
+spud
+ebony
+bodied
+covet
+gung
+rector
+mono
+rims
+hilly
+baltic
+housed
+lackey
+seamen
+rani
+waxing
+garbo
+tripod
+liven
+brawn
+minx
+toffee
+infamy
+hemp
+jigger
+dotted
+enroll
+hatter
+carina
+tehran
+gaff
+doped
+spooks
+graph
+ranges
+gipsy
+moines
+widen
+cited
+hoots
+ouija
+decor
+furies
+cater
+combs
+balkan
+tweed
+murky
+uppity
+nighty
+crete
+tremor
+tarp
+grotto
+dwells
+gilded
+phooey
+pianos
+raps
+peddle
+gust
+haggle
+swish
+zephyr
+fixer
+brim
+weld
+flanks
+hilt
+cite
+vane
+loafer
+crass
+evens
+resin
+grouse
+queasy
+oxide
+yuppie
+downed
+titled
+stills
+prized
+trends
+pout
+defies
+roving
+leans
+pearly
+pane
+peaked
+fresco
+soaps
+breezy
+leach
+roe
+rigs
+moos
+annex
+evict
+fonda
+welded
+mod
+ani
+leased
+unplug
+motels
+uneven
+walled
+corp
+racers
+goings
+mitts
+pedals
+edged
+fife
+supple
+honeys
+stowed
+labors
+fueled
+masons
+kern
+ooze
+mimic
+guile
+clothe
+handel
+stoker
+drivel
+pippin
+colds
+copped
+plume
+mapped
+woolly
+towing
+spar
+innate
+busts
+clinks
+farrow
+golfer
+syrian
+sheen
+satire
+pisces
+drover
+because
+nothing
+thought
+believe
+another
+through
+someone
+morning
+talking
+looking
+getting
+without
+already
+brother
+tonight
+friends
+problem
+waiting
+minutes
+married
+against
+working
+exactly
+husband
+trouble
+captain
+anymore
+country
+between
+brought
+welcome
+started
+anybody
+outside
+perhaps
+playing
+telling
+leaving
+promise
+evening
+himself
+darling
+feeling
+serious
+running
+company
+special
+careful
+goodbye
+perfect
+million
+happens
+parents
+alright
+general
+control
+suppose
+strange
+picture
+forgive
+calling
+changed
+explain
+meeting
+finally
+clothes
+officer
+present
+kidding
+imagine
+forever
+charlie
+decided
+mistake
+station
+wedding
+worried
+message
+america
+instead
+certain
+hundred
+english
+history
+michael
+quickly
+sitting
+colonel
+missing
+service
+respect
+stopped
+besides
+forward
+killing
+neither
+whether
+teacher
+protect
+machine
+amazing
+totally
+private
+realize
+singing
+village
+wearing
+walking
+dollars
+seconds
+staying
+driving
+college
+arrived
+nervous
+contact
+writing
+majesty
+further
+flowers
+written
+partner
+address
+learned
+mission
+kitchen
+chicken
+holding
+allowed
+however
+putting
+usually
+destroy
+animals
+herself
+dancing
+reading
+soldier
+dressed
+support
+mention
+charles
+grandma
+screams
+freedom
+chinese
+breathe
+command
+patient
+figured
+weapons
+england
+stories
+sheriff
+keeping
+richard
+natural
+witness
+correct
+earlier
+weekend
+account
+hanging
+deserve
+ringing
+example
+grandpa
+several
+monster
+silence
+prepare
+justice
+letters
+knowing
+society
+russian
+willing
+student
+jealous
+weather
+opinion
+suicide
+biggest
+noticed
+helping
+nowhere
+meaning
+somehow
+towards
+streets
+manager
+suspect
+dropped
+excited
+whoever
+sweetie
+science
+discuss
+spanish
+medical
+pleased
+invited
+purpose
+survive
+ordered
+hearing
+pretend
+numbers
+suggest
+ashamed
+turning
+falling
+release
+fortune
+fingers
+matters
+subject
+selling
+stomach
+british
+opening
+reality
+funeral
+airport
+program
+defense
+project
+checked
+covered
+clearly
+created
+tickets
+burning
+glasses
+foreign
+courage
+yelling
+depends
+warning
+belongs
+success
+reasons
+italian
+journey
+century
+ancient
+factory
+sending
+records
+william
+changes
+heading
+letting
+bedroom
+finding
+revenge
+divorce
+someday
+useless
+awesome
+miracle
+smoking
+deliver
+victory
+planned
+showing
+growing
+reached
+doctors
+request
+passing
+younger
+becomes
+chicago
+members
+obvious
+workers
+touched
+regular
+details
+emperor
+destiny
+enemies
+sisters
+thunder
+watched
+central
+traffic
+process
+carried
+beating
+percent
+license
+offered
+holiday
+theater
+germans
+whistle
+answers
+receive
+uniform
+screwed
+escaped
+hunting
+disease
+mystery
+beloved
+comrade
+section
+fishing
+senator
+healthy
+curious
+staring
+kingdom
+quarter
+secrets
+barking
+concern
+beeping
+picking
+windows
+managed
+passion
+panting
+engaged
+wounded
+treated
+johnson
+surface
+remains
+closing
+moments
+popular
+reports
+chances
+dealing
+pulling
+unusual
+blowing
+charges
+advance
+cooking
+collect
+winning
+wasting
+capable
+confess
+settled
+results
+illegal
+leading
+appears
+knocked
+gasping
+victims
+garbage
+federal
+council
+jackson
+tuesday
+express
+blessed
+bullets
+billion
+wanting
+degrees
+parties
+trained
+robbery
+servant
+foolish
+unknown
+trapped
+unhappy
+crossed
+culture
+failure
+hitting
+library
+sobbing
+greater
+cutting
+quality
+alcohol
+rolling
+nuclear
+proceed
+vehicle
+fashion
+setting
+arrange
+gunshot
+violent
+quietly
+refused
+fifteen
+hurting
+capital
+channel
+parking
+chasing
+anytime
+angeles
+diamond
+torture
+actress
+comfort
+article
+attempt
+kissing
+despite
+scratch
+entered
+concert
+spirits
+surgery
+indians
+pushing
+whiskey
+selfish
+similar
+drawing
+provide
+barbara
+patrick
+affairs
+heavens
+current
+enjoyed
+traitor
+frankly
+stanley
+distant
+accused
+plastic
+landing
+dreamed
+marshal
+trusted
+western
+stephen
+begging
+vincent
+package
+balance
+citizen
+cameras
+routine
+perform
+eternal
+awfully
+figures
+liberty
+painful
+smiling
+admiral
+clients
+warrant
+ability
+thieves
+players
+cleaned
+thirsty
+bitches
+disturb
+trigger
+reminds
+stretch
+average
+worries
+charity
+francis
+species
+moaning
+lessons
+tragedy
+antonio
+martial
+contest
+highway
+vampire
+network
+chatter
+systems
+highest
+related
+classes
+studied
+bottles
+manners
+laundry
+beneath
+schools
+exhales
+fighter
+smaller
+swallow
+removed
+painted
+sounded
+madness
+raymond
+slipped
+effects
+prevent
+warrior
+injured
+shelter
+chamber
+produce
+costume
+succeed
+propose
+complex
+murders
+raining
+granted
+benefit
+replace
+therapy
+fantasy
+charged
+cleared
+custody
+mothers
+version
+counter
+jumping
+prayers
+florida
+rubbish
+romance
+anxious
+naughty
+product
+actions
+testing
+lawyers
+assault
+anthony
+kicking
+squeeze
+crystal
+hostage
+fellows
+extreme
+october
+luggage
+shaking
+cheated
+pockets
+abandon
+washing
+offense
+confirm
+digging
+typical
+shining
+returns
+african
+heavily
+praying
+academy
+matthew
+humming
+honking
+attacks
+capture
+battery
+buzzing
+messing
+classic
+musical
+matches
+lincoln
+dignity
+massive
+shocked
+respond
+comment
+studies
+laughed
+mexican
+leaders
+feeding
+shortly
+happily
+chapter
+mankind
+breasts
+serving
+grabbed
+measure
+illness
+arguing
+retired
+demands
+artists
+blanket
+loyalty
+fooling
+samurai
+perfume
+banging
+bargain
+payment
+dragged
+russell
+drowned
+bernard
+pattern
+pacific
+conduct
+goddess
+engines
+stepped
+visited
+lighter
+apology
+session
+supreme
+masters
+shadows
+fathers
+arrives
+arrival
+wailing
+butcher
+houston
+happier
+joining
+protest
+retreat
+operate
+various
+gravity
+leather
+nations
+embassy
+instant
+penalty
+packing
+giggles
+honored
+halfway
+closely
+testify
+amongst
+achieve
+buffalo
+approve
+islands
+deposit
+strikes
+visitor
+dessert
+awkward
+scandal
+grounds
+causing
+concept
+wrapped
+explode
+cookies
+killers
+surgeon
+raising
+privacy
+sharing
+economy
+existed
+largest
+dearest
+stabbed
+content
+gabriel
+require
+profile
+reverse
+declare
+defence
+planets
+connect
+options
+eastern
+embrace
+shirley
+passage
+buddies
+develop
+intense
+lecture
+counsel
+limited
+painter
+recover
+observe
+examine
+muffled
+persons
+candles
+reserve
+monkeys
+roaring
+episode
+leonard
+worship
+gunfire
+dresses
+choices
+massage
+twisted
+curtain
+helpful
+kennedy
+spotted
+damaged
+dorothy
+heather
+spoiled
+phoenix
+follows
+emotion
+exposed
+bearing
+dentist
+seventh
+january
+excuses
+ceiling
+improve
+magical
+monitor
+lunatic
+genuine
+desires
+jewelry
+crashed
+farmers
+skipper
+stuffed
+obliged
+collins
+include
+amusing
+sailing
+elected
+poverty
+muscles
+objects
+regards
+bicycle
+despair
+trailer
+impress
+strings
+priests
+crowded
+smarter
+britain
+methods
+shotgun
+display
+planted
+blocked
+douglas
+howling
+gallery
+endless
+smashed
+handled
+bandits
+crushed
+pervert
+cracked
+nearest
+orleans
+customs
+formula
+filming
+physics
+sweater
+sighing
+seeking
+circles
+adopted
+verdict
+efforts
+charley
+guessed
+tobacco
+elegant
+cabinet
+closest
+missile
+noodles
+located
+sucking
+maximum
+sausage
+furious
+minimum
+signing
+element
+buttons
+watches
+tension
+bothers
+compare
+welfare
+devoted
+assumed
+fiction
+carries
+harvest
+harmony
+speaker
+pirates
+arizona
+absence
+vicious
+decides
+cocaine
+gesture
+amateur
+whisper
+cousins
+claimed
+cleaner
+savings
+wealthy
+pointed
+sixteen
+bombing
+stadium
+marines
+counted
+divided
+footage
+seattle
+luckily
+lottery
+honesty
+roberts
+whining
+assured
+touches
+balcony
+lesbian
+filling
+primary
+samples
+mansion
+stewart
+precise
+harvard
+resting
+platoon
+pension
+triumph
+experts
+sadness
+conquer
+quicker
+relaxed
+snoring
+signals
+cavalry
+logical
+haunted
+possess
+psychic
+regrets
+presume
+knights
+focused
+wonders
+shooter
+fragile
+sources
+sincere
+legally
+compete
+prophet
+balloon
+receipt
+climate
+consent
+autopsy
+haircut
+reaches
+hunters
+peasant
+rainbow
+colored
+treason
+refuses
+hostile
+threats
+blaring
+pouring
+couples
+screech
+needing
+feather
+pursuit
+turkish
+scaring
+satisfy
+swedish
+detroit
+marilyn
+shuttle
+drivers
+cottage
+applied
+warming
+seventy
+holland
+heights
+corpses
+ruining
+ireland
+tourist
+drunken
+rabbits
+quarrel
+writers
+hardest
+opposed
+convict
+circuit
+chopper
+corrupt
+journal
+travels
+ticking
+bizarre
+anxiety
+gilbert
+storage
+fulfill
+farther
+expense
+jupiter
+genetic
+convent
+rescued
+battles
+contain
+trading
+springs
+profits
+railway
+hallway
+villain
+advised
+despise
+fainted
+delayed
+attract
+judging
+catches
+foreman
+betting
+bowling
+explore
+tricked
+trumpet
+skipped
+dracula
+cowards
+aspirin
+fascist
+rooster
+targets
+harriet
+baggage
+rushing
+pudding
+spencer
+melissa
+reduced
+wishing
+restore
+smelled
+echoing
+hissing
+tearing
+delight
+choking
+crooked
+freaked
+essence
+handful
+madison
+eleanor
+failing
+cheaper
+offices
+robbing
+empress
+phantom
+unlucky
+shorter
+hearted
+griffin
+execute
+pumpkin
+fastest
+duchess
+variety
+cricket
+dealers
+climbed
+feature
+robbers
+whipped
+sinking
+sunrise
+auction
+pressed
+abraham
+finance
+flowing
+blaming
+equally
+dancers
+bedtime
+utterly
+horizon
+crucial
+gregory
+behaved
+greatly
+corners
+clayton
+boiling
+gardens
+grenade
+ignored
+publish
+bathing
+involve
+initial
+brigade
+reunion
+forcing
+peanuts
+whereas
+beatles
+radical
+madonna
+chewing
+maestro
+listens
+antique
+visible
+edition
+healing
+terrace
+organic
+mirrors
+herbert
+torment
+creates
+fitting
+bananas
+tiffany
+cunning
+bubbles
+visions
+decades
+printed
+offence
+deepest
+resolve
+backing
+needles
+solomon
+blossom
+muslims
+jasmine
+lightly
+deceive
+camping
+caution
+mustard
+justify
+hideous
+volcano
+barrier
+marquis
+coroner
+martini
+popcorn
+relieve
+niggers
+casting
+lobster
+insects
+witches
+seasons
+atlanta
+venture
+yankees
+showers
+bathtub
+talents
+slapped
+teaches
+montana
+pitched
+jackass
+risking
+stripes
+crosses
+carrier
+nursing
+dislike
+popping
+longing
+richest
+exhibit
+evolved
+lookout
+bridges
+starved
+gorilla
+longest
+winners
+spilled
+sailors
+chuckle
+borders
+sundays
+chopped
+housing
+pigeons
+inquiry
+tougher
+olympic
+expects
+peoples
+forests
+punched
+shallow
+torpedo
+natives
+shields
+tapping
+blooded
+teasing
+chester
+grocery
+blasted
+rapidly
+rockets
+teenage
+nursery
+lambert
+confuse
+dismiss
+onboard
+gestapo
+bourbon
+shouted
+referee
+wrecked
+liberal
+trainer
+cabbage
+plumber
+slavery
+digital
+puppies
+beliefs
+weeping
+undress
+audible
+scholar
+admired
+tactics
+females
+compass
+tractor
+neutral
+orphans
+cruelty
+gambler
+busting
+suzanne
+pyramid
+blanche
+shaving
+janitor
+tequila
+reflect
+biology
+chimney
+skating
+flights
+pharaoh
+orderly
+consult
+loading
+savages
+devices
+sponsor
+pitiful
+decency
+kenneth
+tribute
+airline
+founded
+outcome
+sinners
+inherit
+pajamas
+predict
+dolores
+israeli
+suckers
+ecstasy
+messiah
+toilets
+disgust
+rocking
+freezer
+cherish
+krishna
+brothel
+shrieks
+dragons
+pleases
+glimpse
+tracked
+hottest
+annoyed
+lighten
+tunnels
+sparrow
+lifting
+tempted
+banquet
+flooded
+impulse
+mutters
+scooter
+vatican
+unarmed
+symbols
+cowboys
+editing
+bombers
+inmates
+insists
+portion
+inhales
+signora
+posters
+burglar
+secured
+coconut
+tremble
+fiancee
+recruit
+creator
+forgets
+militia
+affects
+simpler
+rotting
+provoke
+heating
+condoms
+surfing
+leopard
+elderly
+handing
+guarded
+ketchup
+spiders
+banking
+rebuild
+payroll
+avoided
+drummer
+flatter
+picasso
+peaches
+pumping
+princes
+fairies
+invaded
+studios
+tongues
+hamburg
+quantum
+promote
+scenery
+frances
+idiotic
+cracker
+mercury
+tighter
+bouquet
+oneself
+locking
+leaning
+bidding
+legends
+caravan
+bruises
+hostess
+decline
+courses
+singers
+praised
+advisor
+shutter
+athlete
+crashes
+ripping
+suffers
+octopus
+amounts
+rangers
+damages
+inspire
+beaches
+denying
+rejoice
+walling
+melting
+baghdad
+winters
+mineral
+condemn
+modesty
+daytime
+bandage
+remorse
+drawers
+webster
+unaware
+penguin
+cartoon
+cannons
+handles
+shampoo
+swollen
+monthly
+secrecy
+revving
+jackpot
+biscuit
+summers
+designs
+resumes
+licking
+forrest
+warfare
+easiest
+squeaks
+statues
+postman
+glowing
+diapers
+tripped
+dynasty
+bankers
+dolphin
+roughly
+throats
+vanilla
+critics
+snapped
+rubbing
+gypsies
+bravery
+immense
+proudly
+repairs
+bottoms
+runaway
+carrots
+bugging
+prefers
+squeals
+freeway
+proving
+dangers
+wheeler
+cashier
+cynical
+edwards
+babylon
+uptight
+motives
+prisons
+flipped
+shipped
+funding
+blinded
+steward
+pauline
+lawsuit
+columns
+faculty
+chooses
+convert
+mermaid
+dreamer
+immoral
+context
+memphis
+freight
+escapes
+pennies
+oysters
+sensors
+skilled
+readers
+barrels
+chained
+dungeon
+punches
+altered
+descent
+dumping
+suburbs
+console
+stained
+excused
+oranges
+aspects
+mixture
+viewers
+zombies
+lucifer
+fireman
+timothy
+partial
+insults
+alabama
+sundown
+virgins
+lucille
+kidneys
+amnesia
+forming
+gaining
+tighten
+protein
+scarlet
+upright
+exploit
+doorway
+veteran
+pickles
+extinct
+courier
+beggars
+gallant
+dispose
+tightly
+bangkok
+donovan
+ratings
+drugged
+farming
+titanic
+obscene
+heroine
+crawled
+briefly
+sorrows
+extract
+boredom
+earning
+plaster
+markets
+outrage
+tattoos
+panther
+marries
+breaker
+powered
+serpent
+redhead
+matched
+leaking
+stunned
+culprit
+mounted
+lasting
+desired
+seduced
+getaway
+coolest
+mocking
+chaplin
+schultz
+anguish
+lacking
+pistols
+siberia
+alarmed
+royalty
+lantern
+pitcher
+analyze
+chronic
+indiana
+combine
+inspect
+remarks
+wrestle
+snowing
+slowing
+rations
+sabbath
+gallons
+temples
+weighed
+heavier
+marbles
+notices
+doubled
+eclipse
+sighted
+caliber
+patriot
+whacked
+armored
+parting
+johnnie
+dresser
+overall
+insight
+hookers
+mailbox
+clearer
+dispute
+fanfare
+toronto
+educate
+vessels
+errands
+shelley
+refined
+charmed
+fearful
+payback
+cologne
+sleeves
+conceal
+acquire
+ashtray
+trivial
+refugee
+doorman
+thanked
+breaths
+islamic
+alleged
+arrests
+admirer
+darkest
+commune
+martian
+stables
+tolling
+tyranny
+chemist
+ominous
+leisure
+lettuce
+tuition
+valiant
+replied
+jackets
+gallows
+flaming
+diploma
+trooper
+canteen
+indoors
+skinner
+indulge
+sanders
+descend
+spreads
+belgian
+fleeing
+pianist
+periods
+anarchy
+awarded
+surname
+outfits
+chateau
+charter
+hideout
+appoint
+chiming
+qualify
+cabaret
+zealand
+patrols
+placing
+sustain
+sweeter
+burgers
+reveals
+standby
+peacock
+pending
+severed
+mumbles
+reactor
+ribbons
+obscure
+terrain
+tenants
+scrooge
+dialing
+dinners
+vintage
+furnace
+abigail
+prairie
+capsule
+rightly
+sublime
+captive
+rituals
+handbag
+prevail
+amnesty
+takeoff
+twinkle
+scatter
+emerged
+reviews
+neglect
+carmine
+harness
+soviets
+antenna
+sharply
+anatomy
+burying
+swimmer
+neptune
+seizure
+starter
+founder
+expired
+beseech
+vaccine
+liaison
+nagging
+radiant
+sliding
+ghastly
+accepts
+shuffle
+emerald
+solving
+freshen
+turtles
+doubted
+fertile
+pinched
+arsenal
+malaria
+clarify
+firstly
+hugging
+settles
+transit
+herring
+baptist
+bladder
+pioneer
+virtues
+endured
+scanner
+rumbles
+cruiser
+orlando
+marched
+berries
+hooting
+winding
+strokes
+credits
+intrude
+invites
+catcher
+buckets
+rewrite
+origins
+defined
+rattles
+cooling
+vinegar
+drought
+overdue
+pierced
+earthly
+skinned
+blazing
+seminar
+gagging
+prefect
+thinner
+manages
+install
+ranking
+lullaby
+insured
+vitamin
+dynamic
+jerking
+appeals
+salvage
+pageant
+hustler
+permits
+persian
+roasted
+mustang
+horrors
+garland
+soaking
+newborn
+drained
+firemen
+pilgrim
+vermont
+vulture
+willard
+analyst
+runners
+lowered
+hotshot
+seniors
+trinity
+uranium
+stalker
+stirred
+batting
+forgave
+mildred
+slammed
+consume
+merrily
+forfeit
+orchard
+careers
+pursued
+isolate
+bullied
+capitol
+dilemma
+crusade
+aroused
+disobey
+cursing
+faggots
+intends
+bruised
+grammar
+bailiff
+collier
+roaming
+fencing
+incense
+envious
+lazarus
+imitate
+hygiene
+dictate
+hopeful
+worldly
+squares
+regions
+evident
+drafted
+earring
+outlaws
+renting
+cockpit
+cheetah
+peeping
+penance
+bending
+flashes
+suspend
+bounced
+sandals
+fleming
+katrina
+clarity
+adapted
+premier
+sparkle
+puzzles
+fearing
+coaster
+dickens
+boarded
+rascals
+genesis
+wichita
+revenue
+fascism
+sleeper
+smuggle
+olympus
+centers
+cackles
+applies
+meadows
+doubles
+applaud
+mortals
+chariot
+squawks
+passive
+invalid
+shelves
+shoving
+virtual
+crowned
+glamour
+goliath
+spelled
+refrain
+wyoming
+rapping
+serbian
+peppers
+squared
+emptied
+sneezes
+tablets
+carolyn
+harding
+pencils
+whitney
+tribune
+guineas
+drastic
+ongoing
+dashing
+junkies
+bravely
+jogging
+coffins
+puppets
+morally
+grilled
+slander
+reacted
+negroes
+mammals
+dialect
+bravest
+pillows
+itching
+hatchet
+stashed
+manhood
+plugged
+summons
+removal
+schemes
+vaguely
+prosper
+quieter
+imposed
+wildest
+thermal
+inhuman
+helmets
+platter
+donated
+rewards
+goodman
+coffees
+doggone
+kittens
+tangled
+outline
+repeats
+atheist
+gibbons
+tickles
+cushion
+flushed
+streams
+giraffe
+refresh
+addicts
+bermuda
+posture
+confide
+cheater
+spinach
+implore
+wilhelm
+tornado
+cardiac
+raphael
+fatigue
+mitzvah
+lending
+minding
+violate
+slumber
+gateway
+murmurs
+pompous
+lurking
+insides
+faraway
+snipers
+voyager
+riviera
+puberty
+tossing
+bologna
+manning
+turmoil
+hopping
+costing
+stating
+weights
+suffice
+chaotic
+stylish
+sulking
+jukebox
+drifted
+brownie
+tracker
+pancake
+rounded
+inquire
+clatter
+guiding
+craving
+cheerio
+apaches
+sterile
+bygones
+factors
+alimony
+ethical
+legions
+snowman
+booking
+waiters
+trashed
+stumble
+seafood
+strauss
+printer
+hawking
+sensual
+uncover
+hitched
+largely
+lengths
+builder
+scripts
+lunches
+koreans
+raiders
+finnish
+charade
+singles
+toaster
+screens
+enhance
+lizards
+marital
+unclear
+enforce
+widower
+museums
+peeking
+trolley
+bottled
+drinker
+waffles
+tedious
+okinawa
+pasture
+masseur
+hobbies
+camelot
+valleys
+cyclops
+rooftop
+graphic
+closure
+workout
+hauling
+iceberg
+deprive
+freeman
+viewing
+carving
+jamming
+seaside
+bellies
+greeted
+frantic
+shifted
+tasting
+quoting
+emerson
+ulysses
+threads
+blacked
+crucify
+exhaust
+endings
+grizzly
+ditched
+stamped
+fanatic
+sinatra
+authors
+recital
+leagues
+presses
+steamed
+compose
+orchids
+hateful
+hippies
+cyanide
+fancies
+riddles
+nickels
+typhoon
+dioxide
+outdoor
+hacking
+redneck
+heathen
+sneaked
+mockery
+baloney
+crumble
+earnest
+catfish
+deserts
+colleen
+perjury
+pickled
+awaited
+praises
+pesetas
+notions
+bedside
+scalpel
+glasgow
+methane
+hooking
+scoring
+thicker
+cornell
+booster
+implant
+unicorn
+carpets
+harmful
+poisons
+devised
+refusal
+hillary
+brushed
+phrases
+patches
+fetched
+siamese
+carcass
+torches
+gourmet
+kiddies
+niagara
+florist
+mailman
+plainly
+gangway
+urgency
+bergman
+cleanse
+bumping
+shatter
+coaches
+behaves
+seaweed
+sticker
+phoning
+sellers
+coppers
+goodies
+novelty
+glacier
+swiftly
+odyssey
+rebuilt
+docking
+anomaly
+eyeball
+commend
+hamster
+wronged
+baptism
+dumbest
+brushes
+buggers
+pledged
+outpost
+compact
+unheard
+galahad
+eyelids
+pretext
+upgrade
+cuisine
+mammoth
+burrows
+cholera
+catalog
+ironing
+memoirs
+stealth
+staging
+slipper
+syringe
+touring
+marking
+bedford
+estates
+entrust
+renewed
+prudent
+hurried
+aladdin
+upwards
+varsity
+stacked
+fancied
+festive
+maggots
+bulldog
+napkins
+tailing
+seagull
+paradox
+berserk
+funnier
+binding
+castles
+boulder
+bonfire
+clemens
+elusive
+pegasus
+psyched
+flushes
+cupcake
+upstate
+smacked
+hiccups
+stamina
+guitars
+cluster
+copying
+blindly
+adviser
+crimson
+frontal
+granite
+striped
+butters
+premium
+cramped
+branded
+bonding
+lasagna
+crazier
+jacuzzi
+reclaim
+proverb
+mistook
+seasick
+martyrs
+machete
+habitat
+freshly
+voltage
+goggles
+maniacs
+rebound
+measles
+whatnot
+bristol
+pinball
+wizards
+thyself
+traders
+dodgers
+casinos
+editors
+signore
+hayward
+booming
+forgery
+eminent
+playful
+glitter
+minimal
+bullies
+motions
+matador
+unified
+relying
+sarcasm
+forbids
+baskets
+recipes
+deleted
+tainted
+patrons
+spooked
+lodging
+futures
+oatmeal
+nirvana
+quixote
+maidens
+brewing
+pandora
+belches
+saddest
+sprayed
+stutter
+heretic
+pillars
+everest
+trainee
+meowing
+density
+algebra
+blurred
+thereby
+pottery
+rebirth
+wartime
+leeches
+consort
+coupons
+texture
+surplus
+parsons
+knuckle
+bayonet
+slashed
+stature
+hoodlum
+cocking
+soprano
+robbins
+bearded
+coastal
+presley
+ghostly
+rejects
+garment
+nonstop
+galileo
+weakest
+implies
+wrinkle
+bloated
+arabian
+clipped
+dwarves
+unleash
+caramel
+hangman
+induced
+milking
+evasive
+bellows
+outlook
+morales
+puzzled
+summary
+barging
+nearing
+coyotes
+undergo
+sorting
+forsake
+hatched
+blondes
+vikings
+dreaded
+briefed
+jehovah
+wrongly
+hancock
+demonic
+cleaver
+marches
+avenged
+dubious
+milkman
+janeiro
+stifler
+mandate
+breakup
+gambled
+fossils
+plucked
+windsor
+kibbutz
+hosting
+meanest
+chipped
+sharpen
+fridays
+goblins
+thinker
+tsunami
+disrupt
+derrick
+plunder
+abdomen
+bashful
+lovable
+plunged
+abusive
+pleaded
+memento
+heroism
+devious
+turkeys
+persist
+evicted
+residue
+midwife
+tropics
+yawning
+overrun
+midwest
+startle
+strayed
+scolded
+seating
+monarch
+slender
+faraday
+cobbler
+whitman
+orgasms
+tissues
+buzzard
+candies
+nightly
+statute
+violets
+scraped
+sweetly
+peabody
+concede
+linking
+fullest
+tourism
+silicon
+uncanny
+outcast
+stormed
+cheques
+mongrel
+sensing
+sedated
+cossack
+hormone
+posting
+billing
+tracing
+rooting
+algiers
+setback
+volumes
+raccoon
+beastly
+ugliest
+keepers
+bribery
+inquest
+fallout
+fussing
+wallets
+reptile
+midgets
+galilee
+lowlife
+augusta
+caveman
+weaving
+tibetan
+borough
+mutants
+plateau
+custard
+looting
+crowbar
+archers
+insulin
+addison
+grazing
+updated
+tolstoy
+scourge
+smitten
+squeaky
+abiding
+swaying
+allergy
+heinous
+dummies
+dodging
+fitness
+piccolo
+scarred
+norfolk
+sweeney
+collide
+patched
+pendant
+banners
+nephews
+fiddler
+foresee
+latrine
+closets
+bangles
+pebbles
+blender
+neutron
+nucleus
+artwork
+flutter
+donkeys
+suction
+bullock
+chilled
+steamer
+genghis
+rosebud
+malachi
+abusing
+raisins
+arsenic
+dipping
+leaping
+symptom
+violins
+packets
+crybaby
+jingles
+spartan
+archive
+alerted
+utility
+outward
+floated
+daisies
+newport
+listing
+thrills
+recount
+commits
+freezes
+stalled
+mileage
+default
+planner
+babysit
+baptize
+brewery
+mouthed
+tidings
+warhead
+bunnies
+scrawny
+heiress
+calcium
+holster
+charger
+charmer
+shorten
+sprouts
+tiniest
+larceny
+bouncer
+swindle
+onwards
+quartet
+turnout
+railing
+plotted
+chilean
+ostrich
+scrolls
+smeared
+burgess
+markers
+trotter
+soaring
+sandman
+gadgets
+tickled
+palaces
+hammers
+pimples
+muffins
+striker
+swapped
+learner
+orpheus
+nemesis
+defiant
+sorcery
+yapping
+checkup
+regroup
+optical
+labeled
+roaches
+inflict
+enabled
+cleanup
+firearm
+folding
+endowed
+escorts
+suzette
+shaping
+sardine
+parched
+deficit
+resides
+revived
+bazooka
+preview
+dormant
+winslow
+sipping
+eyebrow
+dossier
+godless
+monsoon
+discard
+wildcat
+kindest
+greased
+mondays
+waldorf
+sectors
+rethink
+sermons
+rapture
+excites
+grinder
+clement
+curator
+appetit
+cuckold
+bailing
+decreed
+replies
+flunked
+plagued
+watered
+carnage
+rigging
+emerges
+daggers
+segment
+limping
+guesses
+shivers
+exclude
+collars
+ballast
+tending
+forbade
+trapeze
+defects
+confine
+revered
+swamped
+seville
+extends
+sharper
+twelfth
+cheered
+diverse
+caterer
+literal
+electra
+vibrant
+strains
+flashed
+tallest
+defying
+circled
+richter
+topside
+scented
+absolve
+cutters
+whoring
+secular
+betrays
+smashes
+wanders
+saffron
+elastic
+gunning
+bigfoot
+yelping
+faintly
+peeling
+zapping
+saddled
+apostle
+frisbee
+banning
+shrinks
+harshly
+erratic
+anything
+remember
+happened
+yourself
+together
+tomorrow
+business
+everyone
+somebody
+actually
+children
+thinking
+probably
+whatever
+daughter
+supposed
+question
+possible
+straight
+laughing
+hospital
+american
+speaking
+finished
+terrible
+birthday
+pleasure
+building
+watching
+chuckles
+anywhere
+surprise
+problems
+thousand
+accident
+security
+marriage
+fighting
+standing
+personal
+position
+promised
+continue
+sergeant
+sleeping
+bullshit
+evidence
+suddenly
+starting
+pictures
+brothers
+upstairs
+involved
+drinking
+shouting
+shooting
+decision
+princess
+language
+interest
+director
+innocent
+military
+computer
+soldiers
+complete
+feelings
+bathroom
+nonsense
+pregnant
+strength
+greatest
+consider
+favorite
+japanese
+mountain
+national
+practice
+pressure
+horrible
+minister
+although
+cheering
+monsieur
+possibly
+handsome
+prepared
+saturday
+arrested
+powerful
+medicine
+breaking
+murdered
+bringing
+believed
+laughter
+training
+whenever
+students
+criminal
+received
+distance
+followed
+returned
+universe
+contract
+expected
+thoughts
+murderer
+grunting
+property
+planning
+goodness
+audience
+research
+realized
+bastards
+painting
+football
+wherever
+officers
+vacation
+governor
+original
+carrying
+honestly
+exciting
+romantic
+midnight
+millions
+charming
+stranger
+recently
+familiar
+memories
+prisoner
+violence
+sometime
+precious
+changing
+confused
+grateful
+official
+applause
+families
+knocking
+ordinary
+creature
+treasure
+friendly
+highness
+positive
+darkness
+groaning
+terrific
+shopping
+attorney
+presence
+terribly
+bleeding
+attacked
+stronger
+becoming
+stealing
+hundreds
+magazine
+checking
+dreaming
+reporter
+physical
+politics
+throwing
+gorgeous
+elevator
+sentence
+attitude
+shoulder
+material
+cleaning
+exchange
+separate
+progress
+properly
+swimming
+champion
+directly
+movement
+thursday
+counting
+solution
+mistakes
+pleasant
+district
+patients
+schedule
+negative
+studying
+pathetic
+accepted
+entirely
+religion
+released
+location
+paradise
+learning
+stopping
+narrator
+convince
+approach
+spending
+teaching
+arranged
+farewell
+opposite
+disaster
+mistress
+struggle
+presents
+entrance
+customer
+campaign
+patience
+ceremony
+starving
+citizens
+baseball
+incident
+suffered
+services
+generous
+neighbor
+delivery
+lifetime
+transfer
+behavior
+instance
+passport
+producer
+exercise
+believes
+touching
+betrayed
+basement
+downtown
+partners
+diamonds
+growling
+division
+sandwich
+margaret
+reported
+coughing
+adjusted
+everyday
+marrying
+chairman
+messages
+normally
+mistaken
+reverend
+enjoying
+cheating
+machines
+identity
+describe
+worrying
+wondered
+complain
+answered
+invented
+visiting
+designed
+occasion
+survived
+electric
+comrades
+jonathan
+splendid
+standard
+valuable
+russians
+homework
+informed
+industry
+offering
+punished
+fabulous
+discover
+headache
+dramatic
+reaction
+suitcase
+stubborn
+divorced
+engineer
+whispers
+deserves
+doorbell
+appeared
+absolute
+captured
+peaceful
+listened
+superior
+contrary
+imagined
+argument
+operator
+williams
+identify
+quarters
+election
+specific
+catholic
+troubles
+dressing
+elephant
+freezing
+teachers
+gambling
+enormous
+humanity
+judgment
+potatoes
+directed
+southern
+response
+festival
+sunshine
+visitors
+promises
+nowadays
+corporal
+slightly
+occurred
+meantime
+faithful
+crossing
+dropping
+maintain
+stations
+cemetery
+servants
+supplies
+increase
+hopeless
+rumbling
+delicate
+almighty
+compared
+virginia
+activity
+entering
+bothered
+accounts
+talented
+gathered
+blessing
+giggling
+december
+catching
+kindness
+hercules
+gunshots
+monsters
+previous
+superman
+republic
+emotions
+homicide
+november
+survival
+boarding
+airplane
+necklace
+lawrence
+belonged
+countess
+european
+produced
+glorious
+searched
+required
+chanting
+borrowed
+weakness
+attached
+deserved
+daylight
+recorded
+sticking
+suspects
+meetings
+announce
+grandson
+register
+congress
+intended
+chickens
+anderson
+carriage
+arriving
+proposal
+dreadful
+railroad
+treating
+internal
+northern
+disgrace
+eternity
+critical
+telegram
+constant
+marshall
+chemical
+brooklyn
+holidays
+floating
+defeated
+provided
+obsessed
+poisoned
+whistles
+somewhat
+advanced
+tracking
+aircraft
+annoying
+creating
+scotland
+victoria
+executed
+freaking
+strategy
+creative
+audition
+offended
+relative
+strictly
+dialogue
+appetite
+ministry
+function
+ultimate
+nicholas
+concerns
+covering
+dynamite
+homeless
+creation
+graduate
+fighters
+insisted
+employee
+document
+whirring
+sequence
+helpless
+facility
+screwing
+envelope
+miracles
+elements
+warriors
+requires
+climbing
+napoleon
+conflict
+expenses
+clicking
+trousers
+entitled
+assigned
+hostages
+shepherd
+vanished
+clothing
+sympathy
+overcome
+guardian
+sensible
+tortured
+educated
+remained
+forgiven
+illusion
+benjamin
+portrait
+regiment
+infected
+husbands
+declared
+relieved
+respects
+civilian
+admitted
+invasion
+threaten
+sickness
+crashing
+platform
+economic
+ignorant
+veronica
+paranoid
+designer
+instinct
+analysis
+umbrella
+occupied
+vampires
+priority
+addition
+stinking
+disguise
+revealed
+inspired
+reaching
+harmless
+salesman
+pounding
+assassin
+withdraw
+frighten
+preacher
+mitchell
+replaced
+gangster
+collapse
+imperial
+spinning
+ambition
+controls
+franklin
+gracious
+alliance
+marching
+atlantic
+broadway
+february
+crawling
+concrete
+florence
+musician
+heavenly
+contacts
+thompson
+einstein
+waitress
+chirping
+subjects
+bachelor
+persuade
+roommate
+explains
+deserted
+jealousy
+uniforms
+adorable
+tolerate
+whimpers
+drowning
+arrogant
+secretly
+traveled
+cracking
+corridor
+reminded
+majority
+lipstick
+handling
+products
+rattling
+affected
+cocktail
+shanghai
+included
+troubled
+feathers
+forehead
+intimate
+lighting
+deceased
+magician
+opponent
+clearing
+tourists
+password
+rejected
+creaking
+hesitate
+curtains
+thrilled
+abortion
+immortal
+capacity
+multiple
+pointing
+approval
+courtesy
+peculiar
+robinson
+quitting
+restless
+fourteen
+reliable
+eighteen
+suitable
+clarence
+preserve
+thirteen
+homeland
+guessing
+campbell
+symptoms
+cheerful
+accurate
+barracks
+recovery
+fletcher
+childish
+assembly
+fountain
+youngest
+scissors
+wretched
+assuming
+measures
+missiles
+proposed
+approved
+landlord
+isolated
+cultural
+shocking
+domestic
+peasants
+switched
+happiest
+inviting
+benefits
+stepping
+strongly
+costumes
+achieved
+insulted
+squadron
+mortgage
+sniffing
+sneaking
+merciful
+egyptian
+theories
+projects
+disagree
+billions
+chambers
+nickname
+reserved
+wardrobe
+mechanic
+unlikely
+artistic
+vehicles
+expelled
+dragging
+dispatch
+evacuate
+retarded
+indicate
+bracelet
+sunlight
+examined
+carnival
+fortress
+sweating
+prettier
+canadian
+pentagon
+mentally
+relation
+interior
+weekends
+backyard
+disorder
+disposal
+merchant
+articles
+infinite
+definite
+distress
+promoted
+traitors
+allergic
+calendar
+cardinal
+guidance
+barbecue
+villages
+selected
+insanity
+memorial
+province
+injuries
+discount
+terminal
+purchase
+tomatoes
+hamilton
+overtime
+ordering
+deceived
+swinging
+souvenir
+starring
+branches
+behaving
+blocking
+shipment
+gasoline
+destined
+canceled
+drawings
+mourning
+generals
+patricia
+sexually
+opinions
+deadline
+notebook
+speeches
+requests
+escaping
+contempt
+pressing
+careless
+hometown
+software
+carolina
+mattress
+slipping
+improved
+gardener
+magnetic
+charging
+italians
+lonesome
+pancakes
+thankful
+nuisance
+whooping
+accusing
+altitude
+purposes
+ruthless
+striking
+exploded
+features
+choosing
+diseases
+reckless
+earrings
+distract
+discreet
+squirrel
+slippers
+scenario
+profound
+solitary
+colorado
+protocol
+screamed
+programs
+rehearse
+equipped
+chatting
+allowing
+channels
+avoiding
+strangle
+blackout
+trusting
+lemonade
+betrayal
+mustache
+overseas
+teenager
+postcard
+workshop
+shipping
+stressed
+compound
+restored
+comments
+cupboard
+precinct
+sounding
+sweetest
+breeding
+patterns
+infantry
+recorder
+combined
+survivor
+leonardo
+coverage
+includes
+launched
+flirting
+devotion
+summoned
+peterson
+hardware
+incoming
+stunning
+muhammad
+mumbling
+phillips
+grounded
+semester
+blankets
+premises
+bankrupt
+treasury
+skeleton
+unstable
+acquired
+prophecy
+currency
+overhead
+reindeer
+morphine
+sniffles
+invested
+garrison
+rational
+petition
+commands
+crippled
+attended
+suggests
+mcdonald
+morrison
+sabotage
+employed
+speakers
+morality
+attempts
+cheyenne
+cadillac
+fugitive
+payments
+refugees
+michigan
+resolved
+exposure
+feminine
+repeated
+cautious
+addicted
+smelling
+fearless
+breathes
+relevant
+slippery
+parallel
+weddings
+rosemary
+churches
+smashing
+awaiting
+smallest
+observed
+spitting
+practise
+historic
+nineteen
+frontier
+commence
+activate
+biscuits
+juvenile
+confront
+triangle
+eminence
+syndrome
+tropical
+baroness
+columbus
+figuring
+solitude
+numerous
+greeting
+thorough
+evenings
+drifting
+estimate
+holiness
+dripping
+bluffing
+snarling
+clapping
+resigned
+apparent
+sidewalk
+resident
+likewise
+godzilla
+chandler
+oklahoma
+mainland
+panicked
+columbia
+monument
+guarding
+hydrogen
+detailed
+wandered
+protects
+mosquito
+claiming
+refusing
+freshman
+surround
+shortcut
+managing
+olympics
+referred
+shameful
+employer
+whinnies
+dolphins
+comedian
+stitches
+dinosaur
+stripper
+rewarded
+extended
+antidote
+cowardly
+operated
+disabled
+intercom
+academic
+demanded
+missions
+violated
+abducted
+epidemic
+stripped
+ignition
+mornings
+istanbul
+steering
+backpack
+crackers
+briefing
+repaired
+balloons
+specimen
+speeding
+gigantic
+kentucky
+printing
+imbecile
+assemble
+involves
+measured
+rustling
+shutting
+secondly
+retrieve
+sinister
+smartest
+anyplace
+provides
+ignoring
+contents
+postpone
+pussycat
+punching
+werewolf
+moreover
+stalking
+grabbing
+sherlock
+settling
+receiver
+benedict
+pharmacy
+dedicate
+sausages
+richards
+sessions
+twilight
+grenades
+defended
+babbling
+brighter
+publicly
+cannabis
+revolver
+severely
+bulletin
+literary
+backward
+reminder
+montreal
+galaxies
+adoption
+vitamins
+confined
+richmond
+gertrude
+stanford
+bouncing
+airborne
+toughest
+composed
+category
+obtained
+eyebrows
+prospect
+cultures
+sweeping
+airlines
+departed
+hangover
+initials
+traveler
+composer
+relaxing
+theodore
+missouri
+consumed
+salvador
+commerce
+plumbing
+clanging
+stirring
+scottish
+policies
+donation
+finishes
+disciple
+mischief
+brussels
+feedback
+intruder
+scorpion
+amateurs
+cleaners
+doorstep
+urgently
+garfield
+athletic
+detected
+sardines
+tactical
+metaphor
+premiere
+inclined
+spelling
+obstacle
+equation
+heritage
+packages
+snatched
+medieval
+brunette
+unlocked
+informer
+mattered
+regional
+bacteria
+conclude
+matching
+bursting
+smoothly
+bandages
+database
+noticing
+sneakers
+banished
+hormones
+agencies
+portland
+existing
+sporting
+cromwell
+destroys
+deciding
+stumbled
+humility
+stalling
+tempting
+notified
+goldfish
+inferior
+swearing
+landlady
+symphony
+watchman
+villains
+comeback
+starters
+stranded
+something
+beautiful
+everybody
+important
+different
+sometimes
+gentlemen
+wonderful
+somewhere
+president
+yesterday
+certainly
+christmas
+questions
+continues
+attention
+happening
+afternoon
+dangerous
+situation
+professor
+difficult
+screaming
+beginning
+apartment
+seriously
+listening
+boyfriend
+ourselves
+otherwise
+breakfast
+necessary
+detective
+excellent
+surprised
+following
+obviously
+forgotten
+gentleman
+wondering
+commander
+according
+emergency
+inspector
+happiness
+apologize
+operation
+recognize
+perfectly
+character
+telephone
+introduce
+fantastic
+destroyed
+condition
+expecting
+thousands
+concerned
+brilliant
+cigarette
+secretary
+expensive
+breathing
+political
+mountains
+carefully
+americans
+therefore
+christian
+champagne
+suffering
+knowledge
+insurance
+assistant
+interview
+celebrate
+chocolate
+community
+mentioned
+committed
+direction
+statement
+naturally
+disappear
+including
+chuckling
+newspaper
+delicious
+prisoners
+sacrifice
+subtitles
+advantage
+extremely
+available
+hollywood
+basically
+desperate
+education
+challenge
+equipment
+authority
+committee
+ambulance
+convinced
+elizabeth
+miserable
+customers
+treatment
+guarantee
+nightmare
+surrender
diff --git a/OpenKeychain/src/main/java/android/support/v4/widget/FlingNestedScrollView.java b/OpenKeychain/src/main/java/android/support/v4/widget/FlingNestedScrollView.java
new file mode 100644
index 000000000..2bfda5fa8
--- /dev/null
+++ b/OpenKeychain/src/main/java/android/support/v4/widget/FlingNestedScrollView.java
@@ -0,0 +1,1355 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+package android.support.v4.widget;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.support.v4.view.AccessibilityDelegateCompat;
+import android.support.v4.view.MotionEventCompat;
+import android.support.v4.view.NestedScrollingChild;
+import android.support.v4.view.NestedScrollingChildHelper;
+import android.support.v4.view.NestedScrollingParent;
+import android.support.v4.view.NestedScrollingParentHelper;
+import android.support.v4.view.VelocityTrackerCompat;
+import android.support.v4.view.ViewCompat;
+import android.support.v4.view.accessibility.AccessibilityEventCompat;
+import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
+import android.support.v4.view.accessibility.AccessibilityRecordCompat;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.TypedValue;
+import android.view.FocusFinder;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.VelocityTracker;
+import android.view.View;
+import android.view.ViewConfiguration;
+import android.view.ViewGroup;
+import android.view.ViewParent;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.animation.AnimationUtils;
+import android.view.animation.Interpolator;
+import android.widget.FrameLayout;
+import android.widget.ScrollView;
+
+import java.util.ArrayList;
+
+/**
+ * Workaround for bug in support lib. From https://code.google.com/p/android/issues/detail?id=177729
+ *
+ * Also see workaround with padding in view_key_fragment.xml
+ */
+public class FlingNestedScrollView extends FrameLayout implements NestedScrollingParent, NestedScrollingChild {
+ static final int ANIMATED_SCROLL_GAP = 250;
+ static final float MAX_SCROLL_FACTOR = 0.5F;
+ private static final String TAG = "FlingNestedScrollView";
+ private long mLastScroll;
+ private final Rect mTempRect;
+ private ScrollerCompat mScroller;
+ private EdgeEffectCompat mEdgeGlowTop;
+ private EdgeEffectCompat mEdgeGlowBottom;
+ private int mLastMotionY;
+ private boolean mIsLayoutDirty;
+ private boolean mIsLaidOut;
+ private View mChildToScrollTo;
+ private boolean mIsBeingDragged;
+ private VelocityTracker mVelocityTracker;
+ private boolean mFillViewport;
+ private boolean mSmoothScrollingEnabled;
+ private int mTouchSlop;
+ private int mMinimumVelocity;
+ private int mMaximumVelocity;
+ private int mActivePointerId;
+ private final int[] mScrollOffset;
+ private final int[] mScrollConsumed;
+ private int mNestedYOffset;
+ private static final int INVALID_POINTER = -1;
+ private FlingNestedScrollView.SavedState mSavedState;
+ private static final FlingNestedScrollView.AccessibilityDelegate ACCESSIBILITY_DELEGATE = new FlingNestedScrollView.AccessibilityDelegate();
+ private static final int[] SCROLLVIEW_STYLEABLE = new int[]{16843130};
+ private final NestedScrollingParentHelper mParentHelper;
+ private final NestedScrollingChildHelper mChildHelper;
+ private float mVerticalScrollFactor;
+
+ public FlingNestedScrollView(Context context) {
+ this(context, (AttributeSet)null);
+ }
+
+ public FlingNestedScrollView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public FlingNestedScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ this.mTempRect = new Rect();
+ this.mIsLayoutDirty = true;
+ this.mIsLaidOut = false;
+ this.mChildToScrollTo = null;
+ this.mIsBeingDragged = false;
+ this.mSmoothScrollingEnabled = true;
+ this.mActivePointerId = -1;
+ this.mScrollOffset = new int[2];
+ this.mScrollConsumed = new int[2];
+ this.initScrollView();
+ TypedArray a = context.obtainStyledAttributes(attrs, SCROLLVIEW_STYLEABLE, defStyleAttr, 0);
+ this.setFillViewport(a.getBoolean(0, false));
+ a.recycle();
+ this.mParentHelper = new NestedScrollingParentHelper(this);
+ this.mChildHelper = new NestedScrollingChildHelper(this);
+ this.setNestedScrollingEnabled(true);
+ ViewCompat.setAccessibilityDelegate(this, ACCESSIBILITY_DELEGATE);
+ }
+
+ public void setNestedScrollingEnabled(boolean enabled) {
+ this.mChildHelper.setNestedScrollingEnabled(enabled);
+ }
+
+ public boolean isNestedScrollingEnabled() {
+ return this.mChildHelper.isNestedScrollingEnabled();
+ }
+
+ public boolean startNestedScroll(int axes) {
+ return this.mChildHelper.startNestedScroll(axes);
+ }
+
+ public void stopNestedScroll() {
+ this.mChildHelper.stopNestedScroll();
+ }
+
+ public boolean hasNestedScrollingParent() {
+ return this.mChildHelper.hasNestedScrollingParent();
+ }
+
+ public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, int[] offsetInWindow) {
+ return this.mChildHelper.dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, offsetInWindow);
+ }
+
+ public boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow) {
+ return this.mChildHelper.dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow);
+ }
+
+ public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
+ return this.mChildHelper.dispatchNestedFling(velocityX, velocityY, consumed);
+ }
+
+ public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
+ return this.mChildHelper.dispatchNestedPreFling(velocityX, velocityY);
+ }
+
+ public boolean onStartNestedScroll(View child, View target, int nestedScrollAxes) {
+ return (nestedScrollAxes & 2) != 0;
+ }
+
+ public void onNestedScrollAccepted(View child, View target, int nestedScrollAxes) {
+ this.mParentHelper.onNestedScrollAccepted(child, target, nestedScrollAxes);
+ this.startNestedScroll(2);
+ }
+
+ public void onStopNestedScroll(View target) {
+ this.stopNestedScroll();
+ }
+
+ public void onNestedScroll(View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) {
+ int oldScrollY = this.getScrollY();
+ this.scrollBy(0, dyUnconsumed);
+ int myConsumed = this.getScrollY() - oldScrollY;
+ int myUnconsumed = dyUnconsumed - myConsumed;
+ this.dispatchNestedScroll(0, myConsumed, 0, myUnconsumed, (int[])null);
+ }
+
+ public void onNestedPreScroll(View target, int dx, int dy, int[] consumed) {
+ }
+
+ public boolean onNestedFling(View target, float velocityX, float velocityY, boolean consumed) {
+ if(!consumed) {
+ this.flingWithNestedDispatch((int)velocityY);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public boolean onNestedPreFling(View target, float velocityX, float velocityY) {
+ return false;
+ }
+
+ public int getNestedScrollAxes() {
+ return this.mParentHelper.getNestedScrollAxes();
+ }
+
+ public boolean shouldDelayChildPressedState() {
+ return true;
+ }
+
+ protected float getTopFadingEdgeStrength() {
+ if(this.getChildCount() == 0) {
+ return 0.0F;
+ } else {
+ int length = this.getVerticalFadingEdgeLength();
+ int scrollY = this.getScrollY();
+ return scrollY < length?(float)scrollY / (float)length:1.0F;
+ }
+ }
+
+ protected float getBottomFadingEdgeStrength() {
+ if(this.getChildCount() == 0) {
+ return 0.0F;
+ } else {
+ int length = this.getVerticalFadingEdgeLength();
+ int bottomEdge = this.getHeight() - this.getPaddingBottom();
+ int span = this.getChildAt(0).getBottom() - this.getScrollY() - bottomEdge;
+ return span < length?(float)span / (float)length:1.0F;
+ }
+ }
+
+ public int getMaxScrollAmount() {
+ return (int)(0.5F * (float)this.getHeight());
+ }
+
+ private void initScrollView() {
+ this.mScroller = new ScrollerCompat(this.getContext(), (Interpolator)null);
+ this.setFocusable(true);
+ //noinspection ResourceType
+ this.setDescendantFocusability(262144);
+ this.setWillNotDraw(false);
+ ViewConfiguration configuration = ViewConfiguration.get(this.getContext());
+ this.mTouchSlop = configuration.getScaledTouchSlop();
+ this.mMinimumVelocity = configuration.getScaledMinimumFlingVelocity();
+ this.mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();
+ }
+
+ public void addView(View child) {
+ if(this.getChildCount() > 0) {
+ throw new IllegalStateException("ScrollView can host only one direct child");
+ } else {
+ super.addView(child);
+ }
+ }
+
+ public void addView(View child, int index) {
+ if(this.getChildCount() > 0) {
+ throw new IllegalStateException("ScrollView can host only one direct child");
+ } else {
+ super.addView(child, index);
+ }
+ }
+
+ public void addView(View child, LayoutParams params) {
+ if(this.getChildCount() > 0) {
+ throw new IllegalStateException("ScrollView can host only one direct child");
+ } else {
+ super.addView(child, params);
+ }
+ }
+
+ public void addView(View child, int index, LayoutParams params) {
+ if(this.getChildCount() > 0) {
+ throw new IllegalStateException("ScrollView can host only one direct child");
+ } else {
+ super.addView(child, index, params);
+ }
+ }
+
+ private boolean canScroll() {
+ View child = this.getChildAt(0);
+ if(child != null) {
+ int childHeight = child.getHeight();
+ return this.getHeight() < childHeight + this.getPaddingTop() + this.getPaddingBottom();
+ } else {
+ return false;
+ }
+ }
+
+ public boolean isFillViewport() {
+ return this.mFillViewport;
+ }
+
+ public void setFillViewport(boolean fillViewport) {
+ if(fillViewport != this.mFillViewport) {
+ this.mFillViewport = fillViewport;
+ this.requestLayout();
+ }
+
+ }
+
+ public boolean isSmoothScrollingEnabled() {
+ return this.mSmoothScrollingEnabled;
+ }
+
+ public void setSmoothScrollingEnabled(boolean smoothScrollingEnabled) {
+ this.mSmoothScrollingEnabled = smoothScrollingEnabled;
+ }
+
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ if(this.mFillViewport) {
+ int heightMode = MeasureSpec.getMode(heightMeasureSpec);
+ if(heightMode != 0) {
+ if(this.getChildCount() > 0) {
+ View child = this.getChildAt(0);
+ int height = this.getMeasuredHeight();
+ if(child.getMeasuredHeight() < height) {
+ android.widget.FrameLayout.LayoutParams lp = (android.widget.FrameLayout.LayoutParams)child.getLayoutParams();
+ int childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec, this.getPaddingLeft() + this.getPaddingRight(), lp.width);
+ height -= this.getPaddingTop();
+ height -= this.getPaddingBottom();
+ //noinspection ResourceType
+ int childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(height, 1073741824);
+ child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
+ }
+ }
+
+ }
+ }
+ }
+
+ public boolean dispatchKeyEvent(KeyEvent event) {
+ return super.dispatchKeyEvent(event) || this.executeKeyEvent(event);
+ }
+
+ public boolean executeKeyEvent(KeyEvent event) {
+ this.mTempRect.setEmpty();
+ if(this.canScroll()) {
+ boolean handled1 = false;
+ if(event.getAction() == 0) {
+ switch(event.getKeyCode()) {
+ case 19:
+ if(!event.isAltPressed()) {
+ handled1 = this.arrowScroll(33);
+ } else {
+ handled1 = this.fullScroll(33);
+ }
+ break;
+ case 20:
+ if(!event.isAltPressed()) {
+ handled1 = this.arrowScroll(130);
+ } else {
+ handled1 = this.fullScroll(130);
+ }
+ break;
+ case 62:
+ this.pageScroll(event.isShiftPressed()?33:130);
+ }
+ }
+
+ return handled1;
+ } else if(this.isFocused() && event.getKeyCode() != 4) {
+ View handled = this.findFocus();
+ if(handled == this) {
+ handled = null;
+ }
+
+ View nextFocused = FocusFinder.getInstance().findNextFocus(this, handled, 130);
+ return nextFocused != null && nextFocused != this && nextFocused.requestFocus(130);
+ } else {
+ return false;
+ }
+ }
+
+ private boolean inChild(int x, int y) {
+ if(this.getChildCount() <= 0) {
+ return false;
+ } else {
+ int scrollY = this.getScrollY();
+ View child = this.getChildAt(0);
+ return y >= child.getTop() - scrollY && y < child.getBottom() - scrollY && x >= child.getLeft() && x < child.getRight();
+ }
+ }
+
+ private void initOrResetVelocityTracker() {
+ if(this.mVelocityTracker == null) {
+ this.mVelocityTracker = VelocityTracker.obtain();
+ } else {
+ this.mVelocityTracker.clear();
+ }
+
+ }
+
+ private void initVelocityTrackerIfNotExists() {
+ if(this.mVelocityTracker == null) {
+ this.mVelocityTracker = VelocityTracker.obtain();
+ }
+
+ }
+
+ private void recycleVelocityTracker() {
+ if(this.mVelocityTracker != null) {
+ this.mVelocityTracker.recycle();
+ this.mVelocityTracker = null;
+ }
+
+ }
+
+ public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {
+ if(disallowIntercept) {
+ this.recycleVelocityTracker();
+ }
+
+ super.requestDisallowInterceptTouchEvent(disallowIntercept);
+ }
+
+ public boolean onInterceptTouchEvent(MotionEvent ev) {
+ int action = ev.getAction();
+ if(action == 2 && this.mIsBeingDragged) {
+ return true;
+ } else if(this.getScrollY() == 0 && !ViewCompat.canScrollVertically(this, 1)) {
+ return false;
+ } else {
+ int y;
+ switch(action & 255) {
+ case 0:
+ y = (int)ev.getY();
+ if(!this.inChild((int)ev.getX(), y)) {
+ this.mIsBeingDragged = false;
+ this.recycleVelocityTracker();
+ } else {
+ this.mLastMotionY = y;
+ this.mActivePointerId = MotionEventCompat.getPointerId(ev, 0);
+ this.initOrResetVelocityTracker();
+ this.mVelocityTracker.addMovement(ev);
+ this.mIsBeingDragged = !this.mScroller.isFinished();
+ this.startNestedScroll(2);
+ }
+ break;
+ case 1:
+ case 3:
+ this.mIsBeingDragged = false;
+ this.mActivePointerId = -1;
+ this.recycleVelocityTracker();
+ this.stopNestedScroll();
+ break;
+ case 2:
+ y = this.mActivePointerId;
+ if(y != -1) {
+ int pointerIndex = MotionEventCompat.findPointerIndex(ev, y);
+ if(pointerIndex == -1) {
+ Log.e("FlingNestedScrollView", "Invalid pointerId=" + y + " in onInterceptTouchEvent");
+ } else {
+ int y1 = (int)MotionEventCompat.getY(ev, pointerIndex);
+ int yDiff = Math.abs(y1 - this.mLastMotionY);
+ if(yDiff > this.mTouchSlop && (this.getNestedScrollAxes() & 2) == 0) {
+ this.mIsBeingDragged = true;
+ this.mLastMotionY = y1;
+ this.initVelocityTrackerIfNotExists();
+ this.mVelocityTracker.addMovement(ev);
+ this.mNestedYOffset = 0;
+ ViewParent parent = this.getParent();
+ if(parent != null) {
+ parent.requestDisallowInterceptTouchEvent(true);
+ }
+ }
+ }
+ }
+ case 4:
+ case 5:
+ default:
+ break;
+ case 6:
+ this.onSecondaryPointerUp(ev);
+ }
+
+ return this.mIsBeingDragged;
+ }
+ }
+
+ public boolean onTouchEvent(MotionEvent ev) {
+ this.initVelocityTrackerIfNotExists();
+ MotionEvent vtev = MotionEvent.obtain(ev);
+ int actionMasked = MotionEventCompat.getActionMasked(ev);
+ if(actionMasked == 0) {
+ this.mNestedYOffset = 0;
+ }
+
+ vtev.offsetLocation(0.0F, (float)this.mNestedYOffset);
+ int index;
+ int initialVelocity;
+ switch(actionMasked) {
+ case 0:
+ if(this.getChildCount() == 0) {
+ return false;
+ }
+
+ if(this.mIsBeingDragged = !this.mScroller.isFinished()) {
+ ViewParent activePointerIndex1 = this.getParent();
+ if(activePointerIndex1 != null) {
+ activePointerIndex1.requestDisallowInterceptTouchEvent(true);
+ }
+ }
+
+ if(!this.mScroller.isFinished()) {
+ this.mScroller.abortAnimation();
+ }
+
+ this.mLastMotionY = (int)ev.getY();
+ this.mActivePointerId = MotionEventCompat.getPointerId(ev, 0);
+ this.startNestedScroll(2);
+ break;
+ case 1:
+ if(this.mIsBeingDragged) {
+ VelocityTracker index2 = this.mVelocityTracker;
+ index2.computeCurrentVelocity(1000, (float)this.mMaximumVelocity);
+ initialVelocity = (int) VelocityTrackerCompat.getYVelocity(index2, this.mActivePointerId);
+ if(Math.abs(initialVelocity) > this.mMinimumVelocity) {
+ this.flingWithNestedDispatch(-initialVelocity);
+ }
+
+ this.mActivePointerId = -1;
+ this.endDrag();
+ }
+ break;
+ case 2:
+ int activePointerIndex = MotionEventCompat.findPointerIndex(ev, this.mActivePointerId);
+ if(activePointerIndex == -1) {
+ Log.e("FlingNestedScrollView", "Invalid pointerId=" + this.mActivePointerId + " in onTouchEvent");
+ } else {
+ int y = (int)MotionEventCompat.getY(ev, activePointerIndex);
+ int deltaY = this.mLastMotionY - y;
+ if(this.dispatchNestedPreScroll(0, deltaY, this.mScrollConsumed, this.mScrollOffset)) {
+ deltaY -= this.mScrollConsumed[1];
+ vtev.offsetLocation(0.0F, (float)this.mScrollOffset[1]);
+ this.mNestedYOffset += this.mScrollOffset[1];
+ }
+
+ if(!this.mIsBeingDragged && Math.abs(deltaY) > this.mTouchSlop) {
+ ViewParent index1 = this.getParent();
+ if(index1 != null) {
+ index1.requestDisallowInterceptTouchEvent(true);
+ }
+
+ this.mIsBeingDragged = true;
+ if(deltaY > 0) {
+ deltaY -= this.mTouchSlop;
+ } else {
+ deltaY += this.mTouchSlop;
+ }
+ }
+
+ if(this.mIsBeingDragged) {
+ this.mLastMotionY = y - this.mScrollOffset[1];
+ index = this.getScrollY();
+ initialVelocity = this.getScrollRange();
+ int overscrollMode = ViewCompat.getOverScrollMode(this);
+ boolean canOverscroll = overscrollMode == 0 || overscrollMode == 1 && initialVelocity > 0;
+ if(this.overScrollByCompat(0, deltaY, 0, this.getScrollY(), 0, initialVelocity, 0, 0, true) && !this.hasNestedScrollingParent()) {
+ this.mVelocityTracker.clear();
+ }
+
+ int scrolledDeltaY = this.getScrollY() - index;
+ int unconsumedY = deltaY - scrolledDeltaY;
+ if(this.dispatchNestedScroll(0, scrolledDeltaY, 0, unconsumedY, this.mScrollOffset)) {
+ this.mLastMotionY -= this.mScrollOffset[1];
+ vtev.offsetLocation(0.0F, (float)this.mScrollOffset[1]);
+ this.mNestedYOffset += this.mScrollOffset[1];
+ } else if(canOverscroll) {
+ this.ensureGlows();
+ int pulledToY = index + deltaY;
+ if(pulledToY < 0) {
+ this.mEdgeGlowTop.onPull((float)deltaY / (float)this.getHeight(), MotionEventCompat.getX(ev, activePointerIndex) / (float)this.getWidth());
+ if(!this.mEdgeGlowBottom.isFinished()) {
+ this.mEdgeGlowBottom.onRelease();
+ }
+ } else if(pulledToY > initialVelocity) {
+ this.mEdgeGlowBottom.onPull((float)deltaY / (float)this.getHeight(), 1.0F - MotionEventCompat.getX(ev, activePointerIndex) / (float)this.getWidth());
+ if(!this.mEdgeGlowTop.isFinished()) {
+ this.mEdgeGlowTop.onRelease();
+ }
+ }
+
+ if(this.mEdgeGlowTop != null && (!this.mEdgeGlowTop.isFinished() || !this.mEdgeGlowBottom.isFinished())) {
+ ViewCompat.postInvalidateOnAnimation(this);
+ }
+ }
+ }
+ }
+ break;
+ case 3:
+ if(this.mIsBeingDragged && this.getChildCount() > 0) {
+ this.mActivePointerId = -1;
+ this.endDrag();
+ }
+ case 4:
+ default:
+ break;
+ case 5:
+ index = MotionEventCompat.getActionIndex(ev);
+ this.mLastMotionY = (int)MotionEventCompat.getY(ev, index);
+ this.mActivePointerId = MotionEventCompat.getPointerId(ev, index);
+ break;
+ case 6:
+ this.onSecondaryPointerUp(ev);
+ this.mLastMotionY = (int)MotionEventCompat.getY(ev, MotionEventCompat.findPointerIndex(ev, this.mActivePointerId));
+ }
+
+ if(this.mVelocityTracker != null) {
+ this.mVelocityTracker.addMovement(vtev);
+ }
+
+ vtev.recycle();
+ return true;
+ }
+
+ private void onSecondaryPointerUp(MotionEvent ev) {
+ int pointerIndex = (ev.getAction() & '\uff00') >> 8;
+ int pointerId = MotionEventCompat.getPointerId(ev, pointerIndex);
+ if(pointerId == this.mActivePointerId) {
+ int newPointerIndex = pointerIndex == 0?1:0;
+ this.mLastMotionY = (int)MotionEventCompat.getY(ev, newPointerIndex);
+ this.mActivePointerId = MotionEventCompat.getPointerId(ev, newPointerIndex);
+ if(this.mVelocityTracker != null) {
+ this.mVelocityTracker.clear();
+ }
+ }
+
+ }
+
+ public boolean onGenericMotionEvent(MotionEvent event) {
+ if((MotionEventCompat.getSource(event) & 2) != 0) {
+ switch(event.getAction()) {
+ case 8:
+ if(!this.mIsBeingDragged) {
+ float vscroll = MotionEventCompat.getAxisValue(event, 9);
+ if(vscroll != 0.0F) {
+ int delta = (int)(vscroll * this.getVerticalScrollFactorCompat());
+ int range = this.getScrollRange();
+ int oldScrollY = this.getScrollY();
+ int newScrollY = oldScrollY - delta;
+ if(newScrollY < 0) {
+ newScrollY = 0;
+ } else if(newScrollY > range) {
+ newScrollY = range;
+ }
+
+ if(newScrollY != oldScrollY) {
+ super.scrollTo(this.getScrollX(), newScrollY);
+ return true;
+ }
+ }
+ }
+ }
+ }
+
+ return false;
+ }
+
+ private float getVerticalScrollFactorCompat() {
+ if(this.mVerticalScrollFactor == 0.0F) {
+ TypedValue outValue = new TypedValue();
+ Context context = this.getContext();
+ if(!context.getTheme().resolveAttribute(16842829, outValue, true)) {
+ throw new IllegalStateException("Expected theme to define listPreferredItemHeight.");
+ }
+
+ this.mVerticalScrollFactor = outValue.getDimension(context.getResources().getDisplayMetrics());
+ }
+
+ return this.mVerticalScrollFactor;
+ }
+
+ protected void onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY) {
+ super.scrollTo(scrollX, scrollY);
+ }
+
+ boolean overScrollByCompat(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX, int scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) {
+ int overScrollMode = ViewCompat.getOverScrollMode(this);
+ boolean canScrollHorizontal = this.computeHorizontalScrollRange() > this.computeHorizontalScrollExtent();
+ boolean canScrollVertical = this.computeVerticalScrollRange() > this.computeVerticalScrollExtent();
+ boolean overScrollHorizontal = overScrollMode == 0 || overScrollMode == 1 && canScrollHorizontal;
+ boolean overScrollVertical = overScrollMode == 0 || overScrollMode == 1 && canScrollVertical;
+ int newScrollX = scrollX + deltaX;
+ if(!overScrollHorizontal) {
+ maxOverScrollX = 0;
+ }
+
+ int newScrollY = scrollY + deltaY;
+ if(!overScrollVertical) {
+ maxOverScrollY = 0;
+ }
+
+ int left = -maxOverScrollX;
+ int right = maxOverScrollX + scrollRangeX;
+ int top = -maxOverScrollY;
+ int bottom = maxOverScrollY + scrollRangeY;
+ boolean clampedX = false;
+ if(newScrollX > right) {
+ newScrollX = right;
+ clampedX = true;
+ } else if(newScrollX < left) {
+ newScrollX = left;
+ clampedX = true;
+ }
+
+ boolean clampedY = false;
+ if(newScrollY > bottom) {
+ newScrollY = bottom;
+ clampedY = true;
+ } else if(newScrollY < top) {
+ newScrollY = top;
+ clampedY = true;
+ }
+
+ this.onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
+ return clampedX || clampedY;
+ }
+
+ private int getScrollRange() {
+ int scrollRange = 0;
+ if(this.getChildCount() > 0) {
+ View child = this.getChildAt(0);
+ scrollRange = Math.max(0, child.getHeight() - (this.getHeight() - this.getPaddingBottom() - this.getPaddingTop()));
+ }
+
+ return scrollRange;
+ }
+
+ private View findFocusableViewInBounds(boolean topFocus, int top, int bottom) {
+ //noinspection ResourceType
+ ArrayList focusables = this.getFocusables(2);
+ View focusCandidate = null;
+ boolean foundFullyContainedFocusable = false;
+ int count = focusables.size();
+
+ for(int i = 0; i < count; ++i) {
+ View view = (View)focusables.get(i);
+ int viewTop = view.getTop();
+ int viewBottom = view.getBottom();
+ if(top < viewBottom && viewTop < bottom) {
+ boolean viewIsFullyContained = top < viewTop && viewBottom < bottom;
+ if(focusCandidate == null) {
+ focusCandidate = view;
+ foundFullyContainedFocusable = viewIsFullyContained;
+ } else {
+ boolean viewIsCloserToBoundary = topFocus && viewTop < focusCandidate.getTop() || !topFocus && viewBottom > focusCandidate.getBottom();
+ if(foundFullyContainedFocusable) {
+ if(viewIsFullyContained && viewIsCloserToBoundary) {
+ focusCandidate = view;
+ }
+ } else if(viewIsFullyContained) {
+ focusCandidate = view;
+ foundFullyContainedFocusable = true;
+ } else if(viewIsCloserToBoundary) {
+ focusCandidate = view;
+ }
+ }
+ }
+ }
+
+ return focusCandidate;
+ }
+
+ public boolean pageScroll(int direction) {
+ boolean down = direction == 130;
+ int height = this.getHeight();
+ if(down) {
+ this.mTempRect.top = this.getScrollY() + height;
+ int count = this.getChildCount();
+ if(count > 0) {
+ View view = this.getChildAt(count - 1);
+ if(this.mTempRect.top + height > view.getBottom()) {
+ this.mTempRect.top = view.getBottom() - height;
+ }
+ }
+ } else {
+ this.mTempRect.top = this.getScrollY() - height;
+ if(this.mTempRect.top < 0) {
+ this.mTempRect.top = 0;
+ }
+ }
+
+ this.mTempRect.bottom = this.mTempRect.top + height;
+ return this.scrollAndFocus(direction, this.mTempRect.top, this.mTempRect.bottom);
+ }
+
+ public boolean fullScroll(int direction) {
+ boolean down = direction == 130;
+ int height = this.getHeight();
+ this.mTempRect.top = 0;
+ this.mTempRect.bottom = height;
+ if(down) {
+ int count = this.getChildCount();
+ if(count > 0) {
+ View view = this.getChildAt(count - 1);
+ this.mTempRect.bottom = view.getBottom() + this.getPaddingBottom();
+ this.mTempRect.top = this.mTempRect.bottom - height;
+ }
+ }
+
+ return this.scrollAndFocus(direction, this.mTempRect.top, this.mTempRect.bottom);
+ }
+
+ private boolean scrollAndFocus(int direction, int top, int bottom) {
+ boolean handled = true;
+ int height = this.getHeight();
+ int containerTop = this.getScrollY();
+ int containerBottom = containerTop + height;
+ boolean up = direction == 33;
+ Object newFocused = this.findFocusableViewInBounds(up, top, bottom);
+ if(newFocused == null) {
+ newFocused = this;
+ }
+
+ if(top >= containerTop && bottom <= containerBottom) {
+ handled = false;
+ } else {
+ int delta = up?top - containerTop:bottom - containerBottom;
+ this.doScrollY(delta);
+ }
+
+ if(newFocused != this.findFocus()) {
+ ((View)newFocused).requestFocus(direction);
+ }
+
+ return handled;
+ }
+
+ public boolean arrowScroll(int direction) {
+ View currentFocused = this.findFocus();
+ if(currentFocused == this) {
+ currentFocused = null;
+ }
+
+ View nextFocused = FocusFinder.getInstance().findNextFocus(this, currentFocused, direction);
+ int maxJump = this.getMaxScrollAmount();
+ int descendantFocusability;
+ if(nextFocused != null && this.isWithinDeltaOfScreen(nextFocused, maxJump, this.getHeight())) {
+ nextFocused.getDrawingRect(this.mTempRect);
+ this.offsetDescendantRectToMyCoords(nextFocused, this.mTempRect);
+ descendantFocusability = this.computeScrollDeltaToGetChildRectOnScreen(this.mTempRect);
+ this.doScrollY(descendantFocusability);
+ nextFocused.requestFocus(direction);
+ } else {
+ descendantFocusability = maxJump;
+ if(direction == 33 && this.getScrollY() < maxJump) {
+ descendantFocusability = this.getScrollY();
+ } else if(direction == 130 && this.getChildCount() > 0) {
+ int daBottom = this.getChildAt(0).getBottom();
+ int screenBottom = this.getScrollY() + this.getHeight() - this.getPaddingBottom();
+ if(daBottom - screenBottom < maxJump) {
+ descendantFocusability = daBottom - screenBottom;
+ }
+ }
+
+ if(descendantFocusability == 0) {
+ return false;
+ }
+
+ this.doScrollY(direction == 130?descendantFocusability:-descendantFocusability);
+ }
+
+ if(currentFocused != null && currentFocused.isFocused() && this.isOffScreen(currentFocused)) {
+ descendantFocusability = this.getDescendantFocusability();
+ //noinspection ResourceType
+ this.setDescendantFocusability(131072);
+ this.requestFocus();
+ this.setDescendantFocusability(descendantFocusability);
+ }
+
+ return true;
+ }
+
+ private boolean isOffScreen(View descendant) {
+ return !this.isWithinDeltaOfScreen(descendant, 0, this.getHeight());
+ }
+
+ private boolean isWithinDeltaOfScreen(View descendant, int delta, int height) {
+ descendant.getDrawingRect(this.mTempRect);
+ this.offsetDescendantRectToMyCoords(descendant, this.mTempRect);
+ return this.mTempRect.bottom + delta >= this.getScrollY() && this.mTempRect.top - delta <= this.getScrollY() + height;
+ }
+
+ private void doScrollY(int delta) {
+ if(delta != 0) {
+ if(this.mSmoothScrollingEnabled) {
+ this.smoothScrollBy(0, delta);
+ } else {
+ this.scrollBy(0, delta);
+ }
+ }
+
+ }
+
+ public final void smoothScrollBy(int dx, int dy) {
+ if(this.getChildCount() != 0) {
+ long duration = AnimationUtils.currentAnimationTimeMillis() - this.mLastScroll;
+ if(duration > 250L) {
+ int height = this.getHeight() - this.getPaddingBottom() - this.getPaddingTop();
+ int bottom = this.getChildAt(0).getHeight();
+ int maxY = Math.max(0, bottom - height);
+ int scrollY = this.getScrollY();
+ dy = Math.max(0, Math.min(scrollY + dy, maxY)) - scrollY;
+ this.mScroller.startScroll(this.getScrollX(), scrollY, 0, dy);
+ ViewCompat.postInvalidateOnAnimation(this);
+ } else {
+ if(!this.mScroller.isFinished()) {
+ this.mScroller.abortAnimation();
+ }
+
+ this.scrollBy(dx, dy);
+ }
+
+ this.mLastScroll = AnimationUtils.currentAnimationTimeMillis();
+ }
+ }
+
+ public final void smoothScrollTo(int x, int y) {
+ this.smoothScrollBy(x - this.getScrollX(), y - this.getScrollY());
+ }
+
+ protected int computeVerticalScrollRange() {
+ int count = this.getChildCount();
+ int contentHeight = this.getHeight() - this.getPaddingBottom() - this.getPaddingTop();
+ if(count == 0) {
+ return contentHeight;
+ } else {
+ int scrollRange = this.getChildAt(0).getBottom();
+ int scrollY = this.getScrollY();
+ int overscrollBottom = Math.max(0, scrollRange - contentHeight);
+ if(scrollY < 0) {
+ scrollRange -= scrollY;
+ } else if(scrollY > overscrollBottom) {
+ scrollRange += scrollY - overscrollBottom;
+ }
+
+ return scrollRange;
+ }
+ }
+
+ protected int computeVerticalScrollOffset() {
+ return Math.max(0, super.computeVerticalScrollOffset());
+ }
+
+ protected void measureChild(View child, int parentWidthMeasureSpec, int parentHeightMeasureSpec) {
+ LayoutParams lp = (LayoutParams) child.getLayoutParams();
+ int childWidthMeasureSpec = getChildMeasureSpec(parentWidthMeasureSpec, this.getPaddingLeft() + this.getPaddingRight(), lp.width);
+ //noinspection ResourceType
+ int childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(0, 0);
+ child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
+ }
+
+ protected void measureChildWithMargins(View child, int parentWidthMeasureSpec, int widthUsed, int parentHeightMeasureSpec, int heightUsed) {
+ MarginLayoutParams lp = (MarginLayoutParams)child.getLayoutParams();
+ int childWidthMeasureSpec = getChildMeasureSpec(parentWidthMeasureSpec, this.getPaddingLeft() + this.getPaddingRight() + lp.leftMargin + lp.rightMargin + widthUsed, lp.width);
+ //noinspection ResourceType
+ int childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(lp.topMargin + lp.bottomMargin, 0);
+ child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
+ }
+
+ public void computeScroll() {
+ if(this.mScroller.computeScrollOffset()) {
+ int oldX = this.getScrollX();
+ int oldY = this.getScrollY();
+ int x = this.mScroller.getCurrX();
+ int y = this.mScroller.getCurrY();
+ if(oldX != x || oldY != y) {
+ int range = this.getScrollRange();
+ int overscrollMode = ViewCompat.getOverScrollMode(this);
+ boolean canOverscroll = overscrollMode == 0 || overscrollMode == 1 && range > 0;
+ this.overScrollByCompat(x - oldX, y - oldY, oldX, oldY, 0, range, 0, 0, false);
+ if(canOverscroll) {
+ this.ensureGlows();
+ if(y <= 0 && oldY > 0) {
+ this.mEdgeGlowTop.onAbsorb((int)this.mScroller.getCurrVelocity());
+ } else if(y >= range && oldY < range) {
+ this.mEdgeGlowBottom.onAbsorb((int)this.mScroller.getCurrVelocity());
+ }
+ }
+ }
+ }
+
+ }
+
+ private void scrollToChild(View child) {
+ child.getDrawingRect(this.mTempRect);
+ this.offsetDescendantRectToMyCoords(child, this.mTempRect);
+ int scrollDelta = this.computeScrollDeltaToGetChildRectOnScreen(this.mTempRect);
+ if(scrollDelta != 0) {
+ this.scrollBy(0, scrollDelta);
+ }
+
+ }
+
+ private boolean scrollToChildRect(Rect rect, boolean immediate) {
+ int delta = this.computeScrollDeltaToGetChildRectOnScreen(rect);
+ boolean scroll = delta != 0;
+ if(scroll) {
+ if(immediate) {
+ this.scrollBy(0, delta);
+ } else {
+ this.smoothScrollBy(0, delta);
+ }
+ }
+
+ return scroll;
+ }
+
+ protected int computeScrollDeltaToGetChildRectOnScreen(Rect rect) {
+ if(this.getChildCount() == 0) {
+ return 0;
+ } else {
+ int height = this.getHeight();
+ int screenTop = this.getScrollY();
+ int screenBottom = screenTop + height;
+ int fadingEdge = this.getVerticalFadingEdgeLength();
+ if(rect.top > 0) {
+ screenTop += fadingEdge;
+ }
+
+ if(rect.bottom < this.getChildAt(0).getHeight()) {
+ screenBottom -= fadingEdge;
+ }
+
+ int scrollYDelta = 0;
+ if(rect.bottom > screenBottom && rect.top > screenTop) {
+ if(rect.height() > height) {
+ scrollYDelta += rect.top - screenTop;
+ } else {
+ scrollYDelta += rect.bottom - screenBottom;
+ }
+
+ int bottom = this.getChildAt(0).getBottom();
+ int distanceToBottom = bottom - screenBottom;
+ scrollYDelta = Math.min(scrollYDelta, distanceToBottom);
+ } else if(rect.top < screenTop && rect.bottom < screenBottom) {
+ if(rect.height() > height) {
+ scrollYDelta -= screenBottom - rect.bottom;
+ } else {
+ scrollYDelta -= screenTop - rect.top;
+ }
+
+ scrollYDelta = Math.max(scrollYDelta, -this.getScrollY());
+ }
+
+ return scrollYDelta;
+ }
+ }
+
+ public void requestChildFocus(View child, View focused) {
+ if(!this.mIsLayoutDirty) {
+ this.scrollToChild(focused);
+ } else {
+ this.mChildToScrollTo = focused;
+ }
+
+ super.requestChildFocus(child, focused);
+ }
+
+ protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
+ if(direction == 2) {
+ direction = 130;
+ } else if(direction == 1) {
+ direction = 33;
+ }
+
+ View nextFocus = previouslyFocusedRect == null?FocusFinder.getInstance().findNextFocus(this, (View)null, direction):FocusFinder.getInstance().findNextFocusFromRect(this, previouslyFocusedRect, direction);
+ return nextFocus == null?false:(this.isOffScreen(nextFocus)?false:nextFocus.requestFocus(direction, previouslyFocusedRect));
+ }
+
+ public boolean requestChildRectangleOnScreen(View child, Rect rectangle, boolean immediate) {
+ rectangle.offset(child.getLeft() - child.getScrollX(), child.getTop() - child.getScrollY());
+ return this.scrollToChildRect(rectangle, immediate);
+ }
+
+ public void requestLayout() {
+ this.mIsLayoutDirty = true;
+ super.requestLayout();
+ }
+
+ protected void onLayout(boolean changed, int l, int t, int r, int b) {
+ super.onLayout(changed, l, t, r, b);
+ this.mIsLayoutDirty = false;
+ if(this.mChildToScrollTo != null && isViewDescendantOf(this.mChildToScrollTo, this)) {
+ this.scrollToChild(this.mChildToScrollTo);
+ }
+
+ this.mChildToScrollTo = null;
+ if(!this.mIsLaidOut) {
+ if(this.mSavedState != null) {
+ this.scrollTo(this.getScrollX(), this.mSavedState.scrollPosition);
+ this.mSavedState = null;
+ }
+
+ int childHeight = this.getChildCount() > 0?this.getChildAt(0).getMeasuredHeight():0;
+ int scrollRange = Math.max(0, childHeight - (b - t - this.getPaddingBottom() - this.getPaddingTop()));
+ if(this.getScrollY() > scrollRange) {
+ this.scrollTo(this.getScrollX(), scrollRange);
+ } else if(this.getScrollY() < 0) {
+ this.scrollTo(this.getScrollX(), 0);
+ }
+ }
+
+ this.scrollTo(this.getScrollX(), this.getScrollY());
+ this.mIsLaidOut = true;
+ }
+
+ @SuppressLint("MissingSuperCall")
+ public void onAttachedToWindow() {
+ this.mIsLaidOut = false;
+ }
+
+ protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+ super.onSizeChanged(w, h, oldw, oldh);
+ View currentFocused = this.findFocus();
+ if(null != currentFocused && this != currentFocused) {
+ if(this.isWithinDeltaOfScreen(currentFocused, 0, oldh)) {
+ currentFocused.getDrawingRect(this.mTempRect);
+ this.offsetDescendantRectToMyCoords(currentFocused, this.mTempRect);
+ int scrollDelta = this.computeScrollDeltaToGetChildRectOnScreen(this.mTempRect);
+ this.doScrollY(scrollDelta);
+ }
+
+ }
+ }
+
+ private static boolean isViewDescendantOf(View child, View parent) {
+ if(child == parent) {
+ return true;
+ } else {
+ ViewParent theParent = child.getParent();
+ return theParent instanceof ViewGroup && isViewDescendantOf((View)theParent, parent);
+ }
+ }
+
+ /**
+ * Adjusted from AppCompat v23.0.0 so that the function returns true if the nested fling will
+ * end at the top of the scroll view. Which means that it should be dispatched to the
+ * CoordinatorLayout/AppBarLayout
+ * @param velocityY
+ * @return
+ */
+ public boolean fling(int velocityY) {
+ if(this.getChildCount() > 0) {
+ int height = this.getHeight() - this.getPaddingBottom() - this.getPaddingTop();
+ int bottom = this.getChildAt(0).getHeight();
+ this.mScroller.fling(this.getScrollX(), this.getScrollY(), 0, velocityY, 0, 0, 0, Math.max(0, bottom - height), 0, height / 2);
+ ViewCompat.postInvalidateOnAnimation(this);
+ return mScroller.getFinalY() == 0;
+ }
+ return false;
+ }
+
+ private void flingWithNestedDispatch(int velocityY) {
+ int scrollY = this.getScrollY();
+ boolean canFling = (scrollY > 0 || velocityY > 0) && (scrollY < this.getScrollRange() || velocityY < 0);
+ if(!this.dispatchNestedPreFling(0.0F, (float)velocityY)) {
+ boolean dispatchFling = true;
+ if (canFling)
+ dispatchFling = fling(velocityY);
+ this.dispatchNestedFling(0.0F, (float)velocityY, !dispatchFling);
+ }
+
+ }
+
+ private void endDrag() {
+ this.mIsBeingDragged = false;
+ this.recycleVelocityTracker();
+ this.stopNestedScroll();
+ if(this.mEdgeGlowTop != null) {
+ this.mEdgeGlowTop.onRelease();
+ this.mEdgeGlowBottom.onRelease();
+ }
+
+ }
+
+ public void scrollTo(int x, int y) {
+ if(this.getChildCount() > 0) {
+ View child = this.getChildAt(0);
+ x = clamp(x, this.getWidth() - this.getPaddingRight() - this.getPaddingLeft(), child.getWidth());
+ y = clamp(y, this.getHeight() - this.getPaddingBottom() - this.getPaddingTop(), child.getHeight());
+ if(x != this.getScrollX() || y != this.getScrollY()) {
+ super.scrollTo(x, y);
+ }
+ }
+
+ }
+
+ private void ensureGlows() {
+ if(ViewCompat.getOverScrollMode(this) != 2) {
+ if(this.mEdgeGlowTop == null) {
+ Context context = this.getContext();
+ this.mEdgeGlowTop = new EdgeEffectCompat(context);
+ this.mEdgeGlowBottom = new EdgeEffectCompat(context);
+ }
+ } else {
+ this.mEdgeGlowTop = null;
+ this.mEdgeGlowBottom = null;
+ }
+
+ }
+
+ public void draw(Canvas canvas) {
+ super.draw(canvas);
+ if(this.mEdgeGlowTop != null) {
+ int scrollY = this.getScrollY();
+ int restoreCount;
+ int width;
+ if(!this.mEdgeGlowTop.isFinished()) {
+ restoreCount = canvas.save();
+ width = this.getWidth() - this.getPaddingLeft() - this.getPaddingRight();
+ canvas.translate((float)this.getPaddingLeft(), (float)Math.min(0, scrollY));
+ this.mEdgeGlowTop.setSize(width, this.getHeight());
+ if(this.mEdgeGlowTop.draw(canvas)) {
+ ViewCompat.postInvalidateOnAnimation(this);
+ }
+
+ canvas.restoreToCount(restoreCount);
+ }
+
+ if(!this.mEdgeGlowBottom.isFinished()) {
+ restoreCount = canvas.save();
+ width = this.getWidth() - this.getPaddingLeft() - this.getPaddingRight();
+ int height = this.getHeight();
+ canvas.translate((float)(-width + this.getPaddingLeft()), (float)(Math.max(this.getScrollRange(), scrollY) + height));
+ canvas.rotate(180.0F, (float)width, 0.0F);
+ this.mEdgeGlowBottom.setSize(width, height);
+ if(this.mEdgeGlowBottom.draw(canvas)) {
+ ViewCompat.postInvalidateOnAnimation(this);
+ }
+
+ canvas.restoreToCount(restoreCount);
+ }
+ }
+
+ }
+
+ private static int clamp(int n, int my, int child) {
+ return my < child && n >= 0?(my + n > child?child - my:n):0;
+ }
+
+ protected void onRestoreInstanceState(Parcelable state) {
+ FlingNestedScrollView.SavedState ss = (FlingNestedScrollView.SavedState)state;
+ super.onRestoreInstanceState(ss.getSuperState());
+ this.mSavedState = ss;
+ this.requestLayout();
+ }
+
+ protected Parcelable onSaveInstanceState() {
+ Parcelable superState = super.onSaveInstanceState();
+ FlingNestedScrollView.SavedState ss = new FlingNestedScrollView.SavedState(superState);
+ ss.scrollPosition = this.getScrollY();
+ return ss;
+ }
+
+ static class AccessibilityDelegate extends AccessibilityDelegateCompat {
+ AccessibilityDelegate() {
+ }
+
+ public boolean performAccessibilityAction(View host, int action, Bundle arguments) {
+ if(super.performAccessibilityAction(host, action, arguments)) {
+ return true;
+ } else {
+ FlingNestedScrollView nsvHost = (FlingNestedScrollView)host;
+ if(!nsvHost.isEnabled()) {
+ return false;
+ } else {
+ int viewportHeight;
+ int targetScrollY;
+ switch(action) {
+ case 4096:
+ viewportHeight = nsvHost.getHeight() - nsvHost.getPaddingBottom() - nsvHost.getPaddingTop();
+ targetScrollY = Math.min(nsvHost.getScrollY() + viewportHeight, nsvHost.getScrollRange());
+ if(targetScrollY != nsvHost.getScrollY()) {
+ nsvHost.smoothScrollTo(0, targetScrollY);
+ return true;
+ }
+
+ return false;
+ case 8192:
+ viewportHeight = nsvHost.getHeight() - nsvHost.getPaddingBottom() - nsvHost.getPaddingTop();
+ targetScrollY = Math.max(nsvHost.getScrollY() - viewportHeight, 0);
+ if(targetScrollY != nsvHost.getScrollY()) {
+ nsvHost.smoothScrollTo(0, targetScrollY);
+ return true;
+ }
+
+ return false;
+ default:
+ return false;
+ }
+ }
+ }
+ }
+
+ public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfoCompat info) {
+ super.onInitializeAccessibilityNodeInfo(host, info);
+ FlingNestedScrollView nsvHost = (FlingNestedScrollView)host;
+ info.setClassName(ScrollView.class.getName());
+ if(nsvHost.isEnabled()) {
+ int scrollRange = nsvHost.getScrollRange();
+ if(scrollRange > 0) {
+ info.setScrollable(true);
+ if(nsvHost.getScrollY() > 0) {
+ info.addAction(8192);
+ }
+
+ if(nsvHost.getScrollY() < scrollRange) {
+ info.addAction(4096);
+ }
+ }
+ }
+
+ }
+
+ public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
+ super.onInitializeAccessibilityEvent(host, event);
+ FlingNestedScrollView nsvHost = (FlingNestedScrollView)host;
+ event.setClassName(ScrollView.class.getName());
+ AccessibilityRecordCompat record = AccessibilityEventCompat.asRecord(event);
+ boolean scrollable = nsvHost.getScrollRange() > 0;
+ record.setScrollable(scrollable);
+ record.setScrollX(nsvHost.getScrollX());
+ record.setScrollY(nsvHost.getScrollY());
+ record.setMaxScrollX(nsvHost.getScrollX());
+ record.setMaxScrollY(nsvHost.getScrollRange());
+ }
+ }
+
+ static class SavedState extends BaseSavedState {
+ public int scrollPosition;
+ public static final Creator<FlingNestedScrollView.SavedState> CREATOR = new Creator() {
+ public FlingNestedScrollView.SavedState createFromParcel(Parcel in) {
+ return new FlingNestedScrollView.SavedState(in);
+ }
+
+ public FlingNestedScrollView.SavedState[] newArray(int size) {
+ return new FlingNestedScrollView.SavedState[size];
+ }
+ };
+
+ SavedState(Parcelable superState) {
+ super(superState);
+ }
+
+ public SavedState(Parcel source) {
+ super(source);
+ this.scrollPosition = source.readInt();
+ }
+
+ public void writeToParcel(Parcel dest, int flags) {
+ super.writeToParcel(dest, flags);
+ dest.writeInt(this.scrollPosition);
+ }
+
+ public String toString() {
+ return "HorizontalScrollView.SavedState{" + Integer.toHexString(System.identityHashCode(this)) + " scrollPosition=" + this.scrollPosition + "}";
+ }
+ }
+}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java
index 3d58602ab..6a9656b28 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java
@@ -19,14 +19,9 @@ package org.sufficientlysecure.keychain;
import android.os.Environment;
-import org.spongycastle.bcpg.HashAlgorithmTags;
-import org.spongycastle.bcpg.SymmetricKeyAlgorithmTags;
import org.spongycastle.jce.provider.BouncyCastleProvider;
-import org.sufficientlysecure.keychain.BuildConfig;
-
import java.io.File;
-import java.net.InetSocketAddress;
import java.net.Proxy;
public final class Constants {
@@ -34,6 +29,7 @@ public final class Constants {
public static final boolean DEBUG = BuildConfig.DEBUG;
public static final boolean DEBUG_LOG_DB_QUERIES = false;
public static final boolean DEBUG_SYNC_REMOVE_CONTACTS = false;
+ public static final boolean DEBUG_KEYSERVER_SYNC = false;
public static final String TAG = DEBUG ? "Keychain D" : "Keychain";
@@ -43,7 +39,7 @@ public final class Constants {
public static final String ACCOUNT_TYPE = BuildConfig.ACCOUNT_TYPE;
public static final String CUSTOM_CONTACT_DATA_MIME_TYPE = "vnd.android.cursor.item/vnd.org.sufficientlysecure.keychain.key";
- public static final String PROVIDER_AUTHORITY = BuildConfig.APPLICATION_ID + ".provider";
+ public static final String PROVIDER_AUTHORITY = BuildConfig.PROVIDER_CONTENT_AUTHORITY;
public static final String TEMPSTORAGE_AUTHORITY = BuildConfig.APPLICATION_ID + ".tempstorage";
public static final String CLIPBOARD_LABEL = "Keychain";
@@ -81,6 +77,11 @@ public final class Constants {
public static final File APP_DIR_FILE = new File(APP_DIR, "export.asc");
}
+ public static final class Notification {
+ public static final int PASSPHRASE_CACHE = 1;
+ public static final int KEYSERVER_SYNC_FAIL_ORBOT = 2;
+ }
+
public static final class Pref {
public static final String PASSPHRASE_CACHE_TTL = "passphraseCacheTtl";
public static final String PASSPHRASE_CACHE_SUBS = "passphraseCacheSubs";
@@ -104,12 +105,24 @@ public final class Constants {
public static final String PROXY_PORT = "proxyPort";
public static final String PROXY_TYPE = "proxyType";
public static final String THEME = "theme";
+ // keyserver sync settings
+ public static final String SYNC_CONTACTS = "syncContacts";
+ public static final String SYNC_KEYSERVER = "syncKeyserver";
+ // other settings
+ public static final String EXPERIMENTAL_ENABLE_WORD_CONFIRM = "experimentalEnableWordConfirm";
+ public static final String EXPERIMENTAL_ENABLE_LINKED_IDENTITIES = "experimentalEnableLinkedIdentities";
+ public static final String EXPERIMENTAL_ENABLE_KEYBASE = "experimentalEnableKeybase";
public static final class Theme {
public static final String LIGHT = "light";
public static final String DARK = "dark";
public static final String DEFAULT = Constants.Pref.Theme.LIGHT;
}
+
+ public static final class ProxyType {
+ public static final String TYPE_HTTP = "proxyHttp";
+ public static final String TYPE_SOCKS = "proxySocks";
+ }
}
/**
@@ -123,7 +136,7 @@ public final class Constants {
public static final class Defaults {
public static final String KEY_SERVERS = "hkps://hkps.pool.sks-keyservers.net, hkps://pgp.mit.edu";
- public static final int PREF_VERSION = 5;
+ public static final int PREF_VERSION = 6;
}
public static final class key {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java
index cd24394d7..311ef2d3b 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java
@@ -23,7 +23,6 @@ import android.app.Application;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
-import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
@@ -35,7 +34,7 @@ import android.widget.Toast;
import org.spongycastle.jce.provider.BouncyCastleProvider;
import org.sufficientlysecure.keychain.provider.KeychainDatabase;
import org.sufficientlysecure.keychain.provider.TemporaryStorageProvider;
-import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.service.KeyserverSyncAdapterService;
import org.sufficientlysecure.keychain.ui.ConsolidateDialogActivity;
import org.sufficientlysecure.keychain.ui.util.FormattingUtils;
import org.sufficientlysecure.keychain.util.Log;
@@ -97,7 +96,7 @@ public class KeychainApplication extends Application {
setupAccountAsNeeded(this);
// Update keyserver list as needed
- Preferences.getPreferences(this).upgradePreferences();
+ Preferences.getPreferences(this).upgradePreferences(this);
TlsHelper.addStaticCA("pool.sks-keyservers.net", getAssets(), "sks-keyservers.netCA.cer");
@@ -136,17 +135,20 @@ public class KeychainApplication extends Application {
}
/**
- * Add OpenKeychain account to Android to link contacts with keys
+ * Add OpenKeychain account to Android to link contacts with keys and keyserver sync
*/
public static void setupAccountAsNeeded(Context context) {
try {
AccountManager manager = AccountManager.get(context);
Account[] accounts = manager.getAccountsByType(Constants.ACCOUNT_TYPE);
- if (accounts == null || accounts.length == 0) {
+
+ if (accounts.length == 0) {
Account account = new Account(Constants.ACCOUNT_NAME, Constants.ACCOUNT_TYPE);
if (manager.addAccountExplicitly(account, null, null)) {
+ // for contact sync
ContentResolver.setIsSyncable(account, ContactsContract.AUTHORITY, 1);
ContentResolver.setSyncAutomatically(account, ContactsContract.AUTHORITY, true);
+ KeyserverSyncAdapterService.enableKeyserverSync(context);
} else {
Log.e(Constants.TAG, "Adding account failed!");
}
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 2cf6d8b34..558b8ce7d 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/HkpKeyserver.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/HkpKeyserver.java
@@ -196,9 +196,9 @@ public class HkpKeyserver extends Keyserver {
/**
* returns a client with pinned certificate if necessary
*
- * @param url
- * @param proxy
- * @return
+ * @param url url to be queried by client
+ * @param proxy proxy to be used by client
+ * @return client with a pinned certificate if necesary
*/
public static OkHttpClient getClient(URL url, Proxy proxy) throws IOException {
OkHttpClient client = new OkHttpClient();
@@ -360,7 +360,7 @@ public class HkpKeyserver extends Keyserver {
try {
data = query(request, proxy);
} catch (HttpError httpError) {
- Log.e(Constants.TAG, "Failed to get key at HkpKeyserver", httpError);
+ Log.d(Constants.TAG, "Failed to get key at HkpKeyserver", httpError);
throw new QueryFailedException("not found");
}
Matcher matcher = PgpHelper.PGP_PUBLIC_KEY.matcher(data);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/linked/LinkedAttribute.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/linked/LinkedAttribute.java
new file mode 100644
index 000000000..3b05afbb3
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/linked/LinkedAttribute.java
@@ -0,0 +1,32 @@
+package org.sufficientlysecure.keychain.linked;
+
+import java.net.URI;
+
+import android.content.Context;
+import android.support.annotation.DrawableRes;
+
+public class LinkedAttribute extends UriAttribute {
+
+ public final LinkedResource mResource;
+
+ protected LinkedAttribute(URI uri, LinkedResource resource) {
+ super(uri);
+ if (resource == null) {
+ throw new AssertionError("resource must not be null in a LinkedIdentity!");
+ }
+ mResource = resource;
+ }
+
+ public @DrawableRes int getDisplayIcon() {
+ return mResource.getDisplayIcon();
+ }
+
+ public String getDisplayTitle(Context context) {
+ return mResource.getDisplayTitle(context);
+ }
+
+ public String getDisplayComment(Context context) {
+ return mResource.getDisplayComment(context);
+ }
+
+}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/linked/LinkedResource.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/linked/LinkedResource.java
new file mode 100644
index 000000000..dffeea65e
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/linked/LinkedResource.java
@@ -0,0 +1,25 @@
+package org.sufficientlysecure.keychain.linked;
+
+import java.net.URI;
+
+import android.content.Context;
+import android.content.Intent;
+import android.support.annotation.DrawableRes;
+import android.support.annotation.StringRes;
+
+public abstract class LinkedResource {
+
+ public abstract URI toUri();
+
+ public abstract @DrawableRes int getDisplayIcon();
+ public abstract @StringRes int getVerifiedText(boolean isSecret);
+ public abstract String getDisplayTitle(Context context);
+ public abstract String getDisplayComment(Context context);
+ public boolean isViewable() {
+ return false;
+ }
+ public Intent getViewIntent() {
+ return null;
+ }
+
+}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/linked/LinkedTokenResource.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/linked/LinkedTokenResource.java
new file mode 100644
index 000000000..998ec3ad4
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/linked/LinkedTokenResource.java
@@ -0,0 +1,300 @@
+package org.sufficientlysecure.keychain.linked;
+
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.methods.HttpRequestBase;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.apache.http.params.BasicHttpParams;
+import org.json.JSONException;
+import org.sufficientlysecure.keychain.Constants;
+import org.sufficientlysecure.keychain.linked.resources.DnsResource;
+import org.sufficientlysecure.keychain.linked.resources.GenericHttpsResource;
+import org.sufficientlysecure.keychain.linked.resources.GithubResource;
+import org.sufficientlysecure.keychain.linked.resources.TwitterResource;
+import org.sufficientlysecure.keychain.operations.results.LinkedVerifyResult;
+import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType;
+import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog;
+import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
+import org.sufficientlysecure.keychain.util.Log;
+import org.thoughtcrime.ssl.pinning.util.PinningHelper;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import android.content.Context;
+
+
+public abstract class LinkedTokenResource extends LinkedResource {
+
+ protected final URI mSubUri;
+ protected final Set<String> mFlags;
+ protected final HashMap<String,String> mParams;
+
+ public static Pattern magicPattern =
+ Pattern.compile("\\[Verifying my (?:Open|)?PGP key(?::|) openpgp4fpr:([a-zA-Z0-9]+)]");
+
+ protected LinkedTokenResource(Set<String> flags, HashMap<String, String> params, URI uri) {
+ mFlags = flags;
+ mParams = params;
+ mSubUri = uri;
+ }
+
+ @SuppressWarnings("unused")
+ public URI getSubUri () {
+ return mSubUri;
+ }
+
+ public Set<String> getFlags () {
+ return new HashSet<>(mFlags);
+ }
+
+ public HashMap<String,String> getParams () {
+ return new HashMap<>(mParams);
+ }
+
+ public static String generate (byte[] fingerprint) {
+ return String.format("[Verifying my OpenPGP key: openpgp4fpr:%s]",
+ KeyFormattingUtils.convertFingerprintToHex(fingerprint));
+ }
+
+ protected static LinkedTokenResource fromUri (URI uri) {
+
+ if (!"openpgpid+token".equals(uri.getScheme())
+ && !"openpgpid+cookie".equals(uri.getScheme())) {
+ Log.e(Constants.TAG, "unknown uri scheme in (suspected) linked id packet");
+ return null;
+ }
+
+ if (!uri.isOpaque()) {
+ Log.e(Constants.TAG, "non-opaque uri in (suspected) linked id packet");
+ return null;
+ }
+
+ String specific = uri.getSchemeSpecificPart();
+ if (!specific.contains("@")) {
+ Log.e(Constants.TAG, "unknown uri scheme in linked id packet");
+ return null;
+ }
+
+ String[] pieces = specific.split("@", 2);
+ URI subUri = URI.create(pieces[1]);
+
+ Set<String> flags = new HashSet<>();
+ HashMap<String,String> params = new HashMap<>();
+ if (!pieces[0].isEmpty()) {
+ String[] rawParams = pieces[0].split(";");
+ for (String param : rawParams) {
+ String[] p = param.split("=", 2);
+ if (p.length == 1) {
+ flags.add(param);
+ } else {
+ params.put(p[0], p[1]);
+ }
+ }
+ }
+
+ return findResourceType(flags, params, subUri);
+
+ }
+
+ protected static LinkedTokenResource findResourceType (Set<String> flags,
+ HashMap<String,String> params, URI subUri) {
+
+ LinkedTokenResource res;
+
+ res = GenericHttpsResource.create(flags, params, subUri);
+ if (res != null) {
+ return res;
+ }
+ // res = DnsResource.create(flags, params, subUri);
+ // if (res != null) {
+ // return res;
+ // }
+ res = TwitterResource.create(flags, params, subUri);
+ if (res != null) {
+ return res;
+ }
+ res = GithubResource.create(flags, params, subUri);
+ if (res != null) {
+ return res;
+ }
+
+ return null;
+
+ }
+
+ public URI toUri () {
+
+ StringBuilder b = new StringBuilder();
+ b.append("openpgpid+token:");
+
+ // add flags
+ if (mFlags != null) {
+ boolean first = true;
+ for (String flag : mFlags) {
+ if (!first) {
+ b.append(";");
+ }
+ first = false;
+ b.append(flag);
+ }
+ }
+
+ // add parameters
+ if (mParams != null) {
+ boolean first = true;
+ for (Entry<String, String> stringStringEntry : mParams.entrySet()) {
+ if (!first) {
+ b.append(";");
+ }
+ first = false;
+ b.append(stringStringEntry.getKey()).append("=").append(stringStringEntry.getValue());
+ }
+ }
+
+ b.append("@");
+ b.append(mSubUri);
+
+ return URI.create(b.toString());
+
+ }
+
+ public LinkedVerifyResult verify(Context context, byte[] fingerprint) {
+
+ OperationLog log = new OperationLog();
+ log.add(LogType.MSG_LV, 0);
+
+ // Try to fetch resource. Logs for itself
+ String res = null;
+ try {
+ res = fetchResource(context, log, 1);
+ } catch (HttpStatusException e) {
+ // log verbose output to logcat
+ Log.e(Constants.TAG, "http error (" + e.getStatus() + "): " + e.getReason());
+ log.add(LogType.MSG_LV_FETCH_ERROR, 2, Integer.toString(e.getStatus()));
+ } catch (MalformedURLException e) {
+ log.add(LogType.MSG_LV_FETCH_ERROR_URL, 2);
+ } catch (IOException e) {
+ Log.e(Constants.TAG, "io error", e);
+ log.add(LogType.MSG_LV_FETCH_ERROR_IO, 2);
+ } catch (JSONException e) {
+ Log.e(Constants.TAG, "json error", e);
+ log.add(LogType.MSG_LV_FETCH_ERROR_FORMAT, 2);
+ }
+
+ if (res == null) {
+ // if this is null, an error was recorded in fetchResource above
+ return new LinkedVerifyResult(LinkedVerifyResult.RESULT_ERROR, log);
+ }
+
+ Log.d(Constants.TAG, "Resource data: '" + res + "'");
+
+ return verifyString(log, 1, res, fingerprint);
+
+ }
+
+ protected abstract String fetchResource (Context context, OperationLog log, int indent)
+ throws HttpStatusException, IOException, JSONException;
+
+ protected Matcher matchResource (OperationLog log, int indent, String res) {
+ return magicPattern.matcher(res);
+ }
+
+ protected LinkedVerifyResult verifyString (OperationLog log, int indent,
+ String res,
+ byte[] fingerprint) {
+
+ log.add(LogType.MSG_LV_MATCH, indent);
+ Matcher match = matchResource(log, indent+1, res);
+ if (!match.find()) {
+ log.add(LogType.MSG_LV_MATCH_ERROR, 2);
+ return new LinkedVerifyResult(LinkedVerifyResult.RESULT_ERROR, log);
+ }
+
+ String candidateFp = match.group(1).toLowerCase();
+ String fp = KeyFormattingUtils.convertFingerprintToHex(fingerprint);
+ if (!fp.equals(candidateFp)) {
+ log.add(LogType.MSG_LV_FP_ERROR, indent);
+ return new LinkedVerifyResult(LinkedVerifyResult.RESULT_ERROR, log);
+ }
+ log.add(LogType.MSG_LV_FP_OK, indent);
+
+ return new LinkedVerifyResult(LinkedVerifyResult.RESULT_OK, log);
+
+ }
+
+ @SuppressWarnings("deprecation") // HttpRequestBase is deprecated
+ public static String getResponseBody(Context context, HttpRequestBase request)
+ throws IOException, HttpStatusException {
+ return getResponseBody(context, request, null);
+ }
+
+ @SuppressWarnings("deprecation") // HttpRequestBase is deprecated
+ public static String getResponseBody(Context context, HttpRequestBase request, String[] pins)
+ throws IOException, HttpStatusException {
+ StringBuilder sb = new StringBuilder();
+
+ request.setHeader("User-Agent", "Open Keychain");
+
+
+ HttpClient httpClient;
+ if (pins == null) {
+ httpClient = new DefaultHttpClient(new BasicHttpParams());
+ } else {
+ httpClient = PinningHelper.getPinnedHttpClient(context, pins);
+ }
+
+ HttpResponse response = httpClient.execute(request);
+ int statusCode = response.getStatusLine().getStatusCode();
+ String reason = response.getStatusLine().getReasonPhrase();
+
+ if (statusCode != 200) {
+ throw new HttpStatusException(statusCode, reason);
+ }
+
+ HttpEntity entity = response.getEntity();
+ InputStream inputStream = entity.getContent();
+
+ BufferedReader bReader = new BufferedReader(
+ new InputStreamReader(inputStream, "UTF-8"), 8);
+ String line;
+ while ((line = bReader.readLine()) != null) {
+ sb.append(line);
+ }
+
+ return sb.toString();
+ }
+
+ public static class HttpStatusException extends Throwable {
+
+ private final int mStatusCode;
+ private final String mReason;
+
+ HttpStatusException(int statusCode, String reason) {
+ super("http status " + statusCode + ": " + reason);
+ mStatusCode = statusCode;
+ mReason = reason;
+ }
+
+ public int getStatus() {
+ return mStatusCode;
+ }
+
+ public String getReason() {
+ return mReason;
+ }
+
+ }
+
+}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/linked/UriAttribute.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/linked/UriAttribute.java
new file mode 100644
index 000000000..7a8ece2cb
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/linked/UriAttribute.java
@@ -0,0 +1,79 @@
+package org.sufficientlysecure.keychain.linked;
+
+import org.spongycastle.util.Strings;
+import org.sufficientlysecure.keychain.Constants;
+import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.pgp.WrappedUserAttribute;
+import org.sufficientlysecure.keychain.util.Log;
+
+import java.io.IOException;
+import java.net.URI;
+
+import android.content.Context;
+import android.support.annotation.DrawableRes;
+
+/** The RawLinkedIdentity contains raw parsed data from a Linked Identity subpacket. */
+public class UriAttribute {
+
+ public final URI mUri;
+
+ protected UriAttribute(URI uri) {
+ mUri = uri;
+ }
+
+ public byte[] getEncoded() {
+ return Strings.toUTF8ByteArray(mUri.toASCIIString());
+ }
+
+ public static UriAttribute fromAttributeData(byte[] data) throws IOException {
+ WrappedUserAttribute att = WrappedUserAttribute.fromData(data);
+
+ byte[][] subpackets = att.getSubpackets();
+ if (subpackets.length >= 1) {
+ return fromSubpacketData(subpackets[0]);
+ }
+
+ throw new IOException("no subpacket data");
+ }
+
+ static UriAttribute fromSubpacketData(byte[] data) {
+
+ try {
+ String uriStr = Strings.fromUTF8ByteArray(data);
+ URI uri = URI.create(uriStr);
+
+ LinkedResource res = LinkedTokenResource.fromUri(uri);
+ if (res == null) {
+ return new UriAttribute(uri);
+ }
+
+ return new LinkedAttribute(uri, res);
+
+ } catch (IllegalArgumentException e) {
+ Log.e(Constants.TAG, "error parsing uri in (suspected) linked id packet");
+ return null;
+ }
+ }
+
+ public static UriAttribute fromResource (LinkedTokenResource res) {
+ return new UriAttribute(res.toUri());
+ }
+
+
+ public WrappedUserAttribute toUserAttribute () {
+ return WrappedUserAttribute.fromSubpacket(WrappedUserAttribute.UAT_URI_ATTRIBUTE, getEncoded());
+ }
+
+ public @DrawableRes int getDisplayIcon() {
+ return R.drawable.ic_warning_grey_24dp;
+ }
+
+ public String getDisplayTitle(Context context) {
+ return "Unknown Identity";
+ }
+
+ public String getDisplayComment(Context context) {
+ return null;
+ }
+
+}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/linked/resources/DnsResource.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/linked/resources/DnsResource.java
new file mode 100644
index 000000000..86b672cc1
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/linked/resources/DnsResource.java
@@ -0,0 +1,130 @@
+package org.sufficientlysecure.keychain.linked.resources;
+
+import android.content.Context;
+import android.support.annotation.DrawableRes;
+import android.support.annotation.StringRes;
+
+import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog;
+import org.sufficientlysecure.keychain.linked.LinkedTokenResource;
+import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
+
+import java.net.URI;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import de.measite.minidns.Client;
+import de.measite.minidns.DNSMessage;
+import de.measite.minidns.Question;
+import de.measite.minidns.Record;
+import de.measite.minidns.Record.CLASS;
+import de.measite.minidns.Record.TYPE;
+import de.measite.minidns.record.TXT;
+
+public class DnsResource extends LinkedTokenResource {
+
+ final static Pattern magicPattern =
+ Pattern.compile("openpgpid\\+token=([a-zA-Z0-9]+)(?:#|;)([a-zA-Z0-9]+)");
+
+ String mFqdn;
+ CLASS mClass;
+ TYPE mType;
+
+ DnsResource(Set<String> flags, HashMap<String, String> params, URI uri,
+ String fqdn, CLASS clazz, TYPE type) {
+ super(flags, params, uri);
+
+ mFqdn = fqdn;
+ mClass = clazz;
+ mType = type;
+ }
+
+ public static String generateText(byte[] fingerprint) {
+
+ return String.format("openpgp4fpr=%s",
+ KeyFormattingUtils.convertFingerprintToHex(fingerprint));
+
+ }
+
+ public static DnsResource createNew (String domain) {
+ HashSet<String> flags = new HashSet<>();
+ HashMap<String,String> params = new HashMap<>();
+ URI uri = URI.create("dns:" + domain + "?TYPE=TXT");
+ return create(flags, params, uri);
+ }
+
+ public static DnsResource create(Set<String> flags, HashMap<String,String> params, URI uri) {
+ if ( ! ("dns".equals(uri.getScheme())
+ && (flags == null || flags.isEmpty())
+ && (params == null || params.isEmpty()))) {
+ return null;
+ }
+
+ //
+ String spec = uri.getSchemeSpecificPart();
+ // If there are // at the beginning, this includes an authority - we don't support those!
+ if (spec.startsWith("//")) {
+ return null;
+ }
+
+ String[] pieces = spec.split("\\?", 2);
+ // In either case, part before a ? is the fqdn
+ String fqdn = pieces[0];
+ // There may be a query part
+ /*
+ if (pieces.length > 1) {
+ // parse CLASS and TYPE query paramters
+ }
+ */
+
+ CLASS clazz = CLASS.IN;
+ TYPE type = TYPE.TXT;
+
+ return new DnsResource(flags, params, uri, fqdn, clazz, type);
+ }
+
+ @SuppressWarnings("unused")
+ public String getFqdn() {
+ return mFqdn;
+ }
+
+ @Override
+ protected String fetchResource (Context context, OperationLog log, int indent) {
+
+ Client c = new Client();
+ DNSMessage msg = c.query(new Question(mFqdn, mType, mClass));
+ Record aw = msg.getAnswers()[0];
+ TXT txt = (TXT) aw.getPayload();
+ return txt.getText().toLowerCase();
+
+ }
+
+ @Override
+ protected Matcher matchResource(OperationLog log, int indent, String res) {
+ return magicPattern.matcher(res);
+ }
+
+ @Override
+ public @StringRes
+ int getVerifiedText(boolean isSecret) {
+ return isSecret ? R.string.linked_verified_secret_dns : R.string.linked_verified_dns;
+ }
+
+ @Override
+ public @DrawableRes int getDisplayIcon() {
+ return R.drawable.linked_dns;
+ }
+
+ @Override
+ public String getDisplayTitle(Context context) {
+ return context.getString(R.string.linked_title_dns);
+ }
+
+ @Override
+ public String getDisplayComment(Context context) {
+ return mFqdn;
+ }
+}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/linked/resources/GenericHttpsResource.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/linked/resources/GenericHttpsResource.java
new file mode 100644
index 000000000..82240c405
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/linked/resources/GenericHttpsResource.java
@@ -0,0 +1,95 @@
+package org.sufficientlysecure.keychain.linked.resources;
+
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.support.annotation.DrawableRes;
+import android.support.annotation.StringRes;
+
+import org.apache.http.client.methods.HttpGet;
+import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType;
+import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog;
+import org.sufficientlysecure.keychain.linked.LinkedTokenResource;
+import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
+
+import java.io.IOException;
+import java.net.URI;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Set;
+
+public class GenericHttpsResource extends LinkedTokenResource {
+
+ GenericHttpsResource(Set<String> flags, HashMap<String,String> params, URI uri) {
+ super(flags, params, uri);
+ }
+
+ public static String generateText (Context context, byte[] fingerprint) {
+ String token = LinkedTokenResource.generate(fingerprint);
+
+ return String.format(context.getResources().getString(R.string.linked_id_generic_text),
+ token, "0x" + KeyFormattingUtils.convertFingerprintToHex(fingerprint).substring(24));
+ }
+
+ @SuppressWarnings("deprecation") // HttpGet is deprecated
+ @Override
+ protected String fetchResource (Context context, OperationLog log, int indent)
+ throws HttpStatusException, IOException {
+
+ log.add(LogType.MSG_LV_FETCH, indent, mSubUri.toString());
+ HttpGet httpGet = new HttpGet(mSubUri);
+ return getResponseBody(context, httpGet);
+
+ }
+
+ public static GenericHttpsResource createNew (URI uri) {
+ HashSet<String> flags = new HashSet<>();
+ flags.add("generic");
+ HashMap<String,String> params = new HashMap<>();
+ return create(flags, params, uri);
+ }
+
+ public static GenericHttpsResource create(Set<String> flags, HashMap<String,String> params, URI uri) {
+ if ( ! ("https".equals(uri.getScheme())
+ && flags != null && flags.size() == 1 && flags.contains("generic")
+ && (params == null || params.isEmpty()))) {
+ return null;
+ }
+ return new GenericHttpsResource(flags, params, uri);
+ }
+
+ @Override
+ public @DrawableRes
+ int getDisplayIcon() {
+ return R.drawable.linked_https;
+ }
+
+ @Override
+ public @StringRes
+ int getVerifiedText(boolean isSecret) {
+ return isSecret ? R.string.linked_verified_secret_https : R.string.linked_verified_https;
+ }
+
+ @Override
+ public String getDisplayTitle(Context context) {
+ return context.getString(R.string.linked_title_https);
+ }
+
+ @Override
+ public String getDisplayComment(Context context) {
+ return mSubUri.toString();
+ }
+
+ @Override
+ public boolean isViewable() {
+ return true;
+ }
+
+ @Override
+ public Intent getViewIntent() {
+ Intent intent = new Intent(Intent.ACTION_VIEW);
+ intent.setData(Uri.parse(mSubUri.toString()));
+ return intent;
+ }
+}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/linked/resources/GithubResource.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/linked/resources/GithubResource.java
new file mode 100644
index 000000000..7a97ffd96
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/linked/resources/GithubResource.java
@@ -0,0 +1,218 @@
+package org.sufficientlysecure.keychain.linked.resources;
+
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.support.annotation.DrawableRes;
+import android.support.annotation.StringRes;
+
+import org.apache.http.client.methods.HttpGet;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.sufficientlysecure.keychain.Constants;
+import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType;
+import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog;
+import org.sufficientlysecure.keychain.linked.LinkedTokenResource;
+import org.sufficientlysecure.keychain.util.Log;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+
+public class GithubResource extends LinkedTokenResource {
+
+ final String mHandle;
+ final String mGistId;
+
+ GithubResource(Set<String> flags, HashMap<String,String> params, URI uri,
+ String handle, String gistId) {
+ super(flags, params, uri);
+
+ mHandle = handle;
+ mGistId = gistId;
+ }
+
+ public static String generate(Context context, byte[] fingerprint) {
+ String token = LinkedTokenResource.generate(fingerprint);
+
+ return String.format(context.getResources().getString(R.string.linked_id_github_text), token);
+ }
+
+ @SuppressWarnings("deprecation") // HttpGet is deprecated
+ @Override
+ protected String fetchResource (Context context, OperationLog log, int indent)
+ throws HttpStatusException, IOException, JSONException {
+
+ log.add(LogType.MSG_LV_FETCH, indent, mSubUri.toString());
+ indent += 1;
+
+ HttpGet httpGet = new HttpGet("https://api.github.com/gists/" + mGistId);
+ String response = getResponseBody(context, httpGet);
+
+ JSONObject obj = new JSONObject(response);
+
+ JSONObject owner = obj.getJSONObject("owner");
+ if (!mHandle.equals(owner.getString("login"))) {
+ log.add(LogType.MSG_LV_ERROR_GITHUB_HANDLE, indent);
+ return null;
+ }
+
+ JSONObject files = obj.getJSONObject("files");
+ Iterator<String> it = files.keys();
+ if (it.hasNext()) {
+ // TODO can there be multiple candidates?
+ JSONObject file = files.getJSONObject(it.next());
+ return file.getString("content");
+ }
+
+ log.add(LogType.MSG_LV_ERROR_GITHUB_NOT_FOUND, indent);
+ return null;
+
+ }
+
+ @Deprecated // not used for now, but could be used to pick up earlier posted gist if already present?
+ @SuppressWarnings({ "deprecation", "unused" })
+ public static GithubResource searchInGithubStream(
+ Context context, String screenName, String needle, OperationLog log) {
+
+ // narrow the needle down to important part
+ Matcher matcher = magicPattern.matcher(needle);
+ if (!matcher.find()) {
+ throw new AssertionError("Needle must contain token pattern! This is a programming error, please report.");
+ }
+ needle = matcher.group();
+
+ try {
+
+ JSONArray array; {
+ HttpGet httpGet =
+ new HttpGet("https://api.github.com/users/" + screenName + "/gists");
+ httpGet.setHeader("Content-Type", "application/json");
+ httpGet.setHeader("User-Agent", "OpenKeychain");
+
+ String response = getResponseBody(context, httpGet);
+ array = new JSONArray(response);
+ }
+
+ for (int i = 0, j = Math.min(array.length(), 5); i < j; i++) {
+ JSONObject obj = array.getJSONObject(i);
+
+ JSONObject files = obj.getJSONObject("files");
+ Iterator<String> it = files.keys();
+ if (it.hasNext()) {
+
+ JSONObject file = files.getJSONObject(it.next());
+ String type = file.getString("type");
+ if (!"text/plain".equals(type)) {
+ continue;
+ }
+ String id = obj.getString("id");
+ HttpGet httpGet = new HttpGet("https://api.github.com/gists/" + id);
+ httpGet.setHeader("User-Agent", "OpenKeychain");
+
+ JSONObject gistObj = new JSONObject(getResponseBody(context, httpGet));
+ JSONObject gistFiles = gistObj.getJSONObject("files");
+ Iterator<String> gistIt = gistFiles.keys();
+ if (!gistIt.hasNext()) {
+ continue;
+ }
+ // TODO can there be multiple candidates?
+ JSONObject gistFile = gistFiles.getJSONObject(gistIt.next());
+ String content = gistFile.getString("content");
+ if (!content.contains(needle)) {
+ continue;
+ }
+
+ URI uri = URI.create("https://gist.github.com/" + screenName + "/" + id);
+ return create(uri);
+ }
+ }
+
+ // update the results with the body of the response
+ log.add(LogType.MSG_LV_FETCH_ERROR_NOTHING, 2);
+ return null;
+
+ } catch (HttpStatusException e) {
+ // log verbose output to logcat
+ Log.e(Constants.TAG, "http error (" + e.getStatus() + "): " + e.getReason());
+ log.add(LogType.MSG_LV_FETCH_ERROR, 2, Integer.toString(e.getStatus()));
+ } catch (MalformedURLException e) {
+ log.add(LogType.MSG_LV_FETCH_ERROR_URL, 2);
+ } catch (IOException e) {
+ Log.e(Constants.TAG, "io error", e);
+ log.add(LogType.MSG_LV_FETCH_ERROR_IO, 2);
+ } catch (JSONException e) {
+ Log.e(Constants.TAG, "json error", e);
+ log.add(LogType.MSG_LV_FETCH_ERROR_FORMAT, 2);
+ }
+
+ return null;
+ }
+
+ public static GithubResource create(URI uri) {
+ return create(new HashSet<String>(), new HashMap<String,String>(), uri);
+ }
+
+ public static GithubResource create(Set<String> flags, HashMap<String,String> params, URI uri) {
+
+ // no params or flags
+ if (!flags.isEmpty() || !params.isEmpty()) {
+ return null;
+ }
+
+ Pattern p = Pattern.compile("https://gist\\.github\\.com/([a-zA-Z0-9_]+)/([0-9a-f]+)");
+ Matcher match = p.matcher(uri.toString());
+ if (!match.matches()) {
+ return null;
+ }
+ String handle = match.group(1);
+ String gistId = match.group(2);
+
+ return new GithubResource(flags, params, uri, handle, gistId);
+
+ }
+
+
+ @Override
+ public @DrawableRes
+ int getDisplayIcon() {
+ return R.drawable.linked_github;
+ }
+
+ @Override
+ public @StringRes
+ int getVerifiedText(boolean isSecret) {
+ return isSecret ? R.string.linked_verified_secret_github : R.string.linked_verified_github;
+ }
+
+ @Override
+ public String getDisplayTitle(Context context) {
+ return context.getString(R.string.linked_title_github);
+ }
+
+ @Override
+ public String getDisplayComment(Context context) {
+ return mHandle;
+ }
+
+ @Override
+ public boolean isViewable() {
+ return true;
+ }
+
+ @Override
+ public Intent getViewIntent() {
+ Intent intent = new Intent(Intent.ACTION_VIEW);
+ intent.setData(Uri.parse(mSubUri.toString()));
+ return intent;
+ }
+}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/linked/resources/TwitterResource.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/linked/resources/TwitterResource.java
new file mode 100644
index 000000000..73e3d3643
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/linked/resources/TwitterResource.java
@@ -0,0 +1,250 @@
+package org.sufficientlysecure.keychain.linked.resources;
+
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.support.annotation.DrawableRes;
+import android.support.annotation.StringRes;
+import android.util.Log;
+
+import com.textuality.keybase.lib.JWalk;
+
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.StringEntity;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.sufficientlysecure.keychain.Constants;
+import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType;
+import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog;
+import org.sufficientlysecure.keychain.linked.LinkedTokenResource;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class TwitterResource extends LinkedTokenResource {
+
+ public static final String[] CERT_PINS = null; /*(new String[] {
+ // Symantec Class 3 Secure Server CA - G4
+ "513fb9743870b73440418d30930699ff"
+ };*/
+
+ final String mHandle;
+ final String mTweetId;
+
+ TwitterResource(Set<String> flags, HashMap<String,String> params,
+ URI uri, String handle, String tweetId) {
+ super(flags, params, uri);
+
+ mHandle = handle;
+ mTweetId = tweetId;
+ }
+
+ public static TwitterResource create(URI uri) {
+ return create(new HashSet<String>(), new HashMap<String,String>(), uri);
+ }
+
+ public static TwitterResource create(Set<String> flags, HashMap<String,String> params, URI uri) {
+
+ // no params or flags
+ if (!flags.isEmpty() || !params.isEmpty()) {
+ return null;
+ }
+
+ Pattern p = Pattern.compile("https://twitter\\.com/([a-zA-Z0-9_]+)/status/([0-9]+)");
+ Matcher match = p.matcher(uri.toString());
+ if (!match.matches()) {
+ return null;
+ }
+ String handle = match.group(1);
+ String tweetId = match.group(2);
+
+ return new TwitterResource(flags, params, uri, handle, tweetId);
+
+ }
+
+ @SuppressWarnings("deprecation")
+ @Override
+ protected String fetchResource(Context context, OperationLog log, int indent)
+ throws IOException, HttpStatusException, JSONException {
+
+ String authToken;
+ try {
+ authToken = getAuthToken(context);
+ } catch (IOException | HttpStatusException | JSONException e) {
+ log.add(LogType.MSG_LV_ERROR_TWITTER_AUTH, indent);
+ return null;
+ }
+
+ HttpGet httpGet =
+ new HttpGet("https://api.twitter.com/1.1/statuses/show.json"
+ + "?id=" + mTweetId
+ + "&include_entities=false");
+
+ // construct a normal HTTPS request and include an Authorization
+ // header with the value of Bearer <>
+ httpGet.setHeader("Authorization", "Bearer " + authToken);
+ httpGet.setHeader("Content-Type", "application/json");
+
+ try {
+ String response = getResponseBody(context, httpGet, CERT_PINS);
+ JSONObject obj = new JSONObject(response);
+ JSONObject user = obj.getJSONObject("user");
+ if (!mHandle.equalsIgnoreCase(user.getString("screen_name"))) {
+ log.add(LogType.MSG_LV_ERROR_TWITTER_HANDLE, indent);
+ return null;
+ }
+
+ // update the results with the body of the response
+ return obj.getString("text");
+ } catch (JSONException e) {
+ log.add(LogType.MSG_LV_ERROR_TWITTER_RESPONSE, indent);
+ return null;
+ }
+
+ }
+
+ @Override
+ public @DrawableRes int getDisplayIcon() {
+ return R.drawable.linked_twitter;
+ }
+
+ @Override
+ public @StringRes
+ int getVerifiedText(boolean isSecret) {
+ return isSecret ? R.string.linked_verified_secret_twitter : R.string.linked_verified_twitter;
+ }
+
+ @Override
+ public String getDisplayTitle(Context context) {
+ return context.getString(R.string.linked_title_twitter);
+ }
+
+ @Override
+ public String getDisplayComment(Context context) {
+ return "@" + mHandle;
+ }
+
+ @Override
+ public boolean isViewable() {
+ return true;
+ }
+
+ @Override
+ public Intent getViewIntent() {
+ Intent intent = new Intent(Intent.ACTION_VIEW);
+ intent.setData(Uri.parse(mSubUri.toString()));
+ return intent;
+ }
+
+ @SuppressWarnings("deprecation")
+ public static TwitterResource searchInTwitterStream(
+ Context context, String screenName, String needle, OperationLog log) {
+
+ String authToken;
+ try {
+ authToken = getAuthToken(context);
+ } catch (IOException | HttpStatusException | JSONException e) {
+ log.add(LogType.MSG_LV_ERROR_TWITTER_AUTH, 1);
+ return null;
+ }
+
+ HttpGet httpGet =
+ new HttpGet("https://api.twitter.com/1.1/statuses/user_timeline.json"
+ + "?screen_name=" + screenName
+ + "&count=15"
+ + "&include_rts=false"
+ + "&trim_user=true"
+ + "&exclude_replies=true");
+
+ // construct a normal HTTPS request and include an Authorization
+ // header with the value of Bearer <>
+ httpGet.setHeader("Authorization", "Bearer " + authToken);
+ httpGet.setHeader("Content-Type", "application/json");
+
+ try {
+ String response = getResponseBody(context, httpGet, CERT_PINS);
+ JSONArray array = new JSONArray(response);
+
+ for (int i = 0; i < array.length(); i++) {
+ JSONObject obj = array.getJSONObject(i);
+ String tweet = obj.getString("text");
+ if (tweet.contains(needle)) {
+ String id = obj.getString("id_str");
+ URI uri = URI.create("https://twitter.com/" + screenName + "/status/" + id);
+ return create(uri);
+ }
+ }
+
+ // update the results with the body of the response
+ log.add(LogType.MSG_LV_FETCH_ERROR_NOTHING, 1);
+ return null;
+
+ } catch (HttpStatusException e) {
+ // log verbose output to logcat
+ Log.e(Constants.TAG, "http error (" + e.getStatus() + "): " + e.getReason());
+ log.add(LogType.MSG_LV_FETCH_ERROR, 1, Integer.toString(e.getStatus()));
+ } catch (MalformedURLException e) {
+ log.add(LogType.MSG_LV_FETCH_ERROR_URL, 1);
+ } catch (IOException e) {
+ Log.e(Constants.TAG, "io error", e);
+ log.add(LogType.MSG_LV_FETCH_ERROR_IO, 1);
+ } catch (JSONException e) {
+ Log.e(Constants.TAG, "json error", e);
+ log.add(LogType.MSG_LV_FETCH_ERROR_FORMAT, 1);
+ }
+
+ return null;
+ }
+
+ private static String cachedAuthToken;
+
+ @SuppressWarnings("deprecation")
+ private static String getAuthToken(Context context)
+ throws IOException, HttpStatusException, JSONException {
+ if (cachedAuthToken != null) {
+ return cachedAuthToken;
+ }
+ String base64Encoded = rot13("D293FQqanH0jH29KIaWJER5DomqSGRE2Ewc1LJACn3cbD1c"
+ + "Fq1bmqSAQAz5MI2cIHKOuo3cPoRAQI1OyqmIVFJS6LHMXq2g6MRLkIj") + "==";
+
+ // Step 2: Obtain a bearer token
+ HttpPost httpPost = new HttpPost("https://api.twitter.com/oauth2/token");
+ httpPost.setHeader("Authorization", "Basic " + base64Encoded);
+ httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");
+ httpPost.setEntity(new StringEntity("grant_type=client_credentials"));
+ JSONObject rawAuthorization = new JSONObject(getResponseBody(context, httpPost, CERT_PINS));
+
+ // Applications should verify that the value associated with the
+ // token_type key of the returned object is bearer
+ if (!"bearer".equals(JWalk.getString(rawAuthorization, "token_type"))) {
+ throw new JSONException("Expected bearer token in response!");
+ }
+
+ cachedAuthToken = rawAuthorization.getString("access_token");
+ return cachedAuthToken;
+
+ }
+
+ public static String rot13(String input) {
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < input.length(); i++) {
+ char c = input.charAt(i);
+ if (c >= 'a' && c <= 'm') c += 13;
+ else if (c >= 'A' && c <= 'M') c += 13;
+ else if (c >= 'n' && c <= 'z') c -= 13;
+ else if (c >= 'N' && c <= 'Z') c -= 13;
+ sb.append(c);
+ }
+ return sb.toString();
+ }
+
+}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ExportOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ExportOperation.java
index a5b70a41f..531ac01f2 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ExportOperation.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ExportOperation.java
@@ -145,6 +145,8 @@ public class ExportOperation extends BaseOperation<ExportKeyringParcel> {
return new ExportResult(ExportResult.RESULT_ERROR, log);
}
+ log.add(LogType.MSG_EXPORT_FILE_NAME, 1, outputFile);
+
// check if storage is ready
if (!FileHelper.isStorageMounted(outputFile)) {
log.add(LogType.MSG_EXPORT_ERROR_STORAGE, 1);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ImportOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ImportOperation.java
index 4acfd6e30..89575338f 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ImportOperation.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ImportOperation.java
@@ -22,9 +22,8 @@ package org.sufficientlysecure.keychain.operations;
import java.io.IOException;
import java.net.Proxy;
import java.util.ArrayList;
-import java.util.HashSet;
+import java.util.GregorianCalendar;
import java.util.Iterator;
-import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
@@ -99,29 +98,9 @@ public class ImportOperation extends BaseOperation<ImportKeyringParcel> {
return serialKeyRingImport(entries, num, keyServerUri, mProgressable, proxy);
}
- public ImportKeyResult serialKeyRingImport(List<ParcelableKeyRing> entries,
- String keyServerUri, Proxy proxy) {
-
- Iterator<ParcelableKeyRing> it = entries.iterator();
- int numEntries = entries.size();
-
- return serialKeyRingImport(it, numEntries, keyServerUri, mProgressable, proxy);
-
- }
-
- public ImportKeyResult serialKeyRingImport(List<ParcelableKeyRing> entries, String keyServerUri,
- Progressable progressable, Proxy proxy) {
-
- Iterator<ParcelableKeyRing> it = entries.iterator();
- int numEntries = entries.size();
-
- return serialKeyRingImport(it, numEntries, keyServerUri, progressable, proxy);
-
- }
-
@NonNull
- public ImportKeyResult serialKeyRingImport(ParcelableFileCache<ParcelableKeyRing> cache,
- String keyServerUri, Proxy proxy) {
+ private ImportKeyResult serialKeyRingImport(ParcelableFileCache<ParcelableKeyRing> cache,
+ String keyServerUri, Proxy proxy) {
// get entries from cached file
try {
@@ -143,7 +122,7 @@ public class ImportOperation extends BaseOperation<ImportKeyringParcel> {
/**
* Since the introduction of multithreaded import, we expect calling functions to handle the
- * key sync i,eContactSyncAdapterService.requestSync()
+ * contact-to-key sync i.e ContactSyncAdapterService.requestSync()
*
* @param entries keys to import
* @param num number of keys to import
@@ -152,9 +131,9 @@ public class ImportOperation extends BaseOperation<ImportKeyringParcel> {
* progress of a single key being imported
*/
@NonNull
- public ImportKeyResult serialKeyRingImport(Iterator<ParcelableKeyRing> entries, int num,
- String keyServerUri, Progressable progressable,
- Proxy proxy) {
+ private ImportKeyResult serialKeyRingImport(Iterator<ParcelableKeyRing> entries, int num,
+ String keyServerUri, Progressable progressable,
+ Proxy proxy) {
if (progressable != null) {
progressable.setProgress(R.string.progress_importing, 0, 100);
}
@@ -231,8 +210,8 @@ public class ImportOperation extends BaseOperation<ImportKeyringParcel> {
log.add(LogType.MSG_IMPORT_FETCH_ERROR_DECODE, 3);
}
} catch (Keyserver.QueryFailedException e) {
- Log.e(Constants.TAG, "query failed", e);
- log.add(LogType.MSG_IMPORT_FETCH_KEYSERVER_ERROR, 3, e.getMessage());
+ Log.d(Constants.TAG, "query failed", e);
+ log.add(LogType.MSG_IMPORT_FETCH_ERROR_KEYSERVER, 3, e.getMessage());
}
}
@@ -264,7 +243,7 @@ public class ImportOperation extends BaseOperation<ImportKeyringParcel> {
} catch (Keyserver.QueryFailedException e) {
// download failed, too bad. just proceed
Log.e(Constants.TAG, "query failed", e);
- log.add(LogType.MSG_IMPORT_FETCH_KEYSERVER_ERROR, 3, e.getMessage());
+ log.add(LogType.MSG_IMPORT_FETCH_ERROR_KEYSERVER, 3, e.getMessage());
}
}
}
@@ -275,15 +254,11 @@ public class ImportOperation extends BaseOperation<ImportKeyringParcel> {
continue;
}
- // If we have an expected fingerprint, make sure it matches
- if (entry.mExpectedFingerprint != null) {
- if (!key.containsSubkey(entry.mExpectedFingerprint)) {
- log.add(LogType.MSG_IMPORT_FINGERPRINT_ERROR, 2);
- badKeys += 1;
- continue;
- } else {
- log.add(LogType.MSG_IMPORT_FINGERPRINT_OK, 2);
- }
+ // never import secret keys from keyserver!
+ if (entry.mBytes == null && key.isSecret()) {
+ log.add(LogType.MSG_IMPORT_FETCH_ERROR_KEYSERVER_SECRET, 2);
+ badKeys += 1;
+ continue;
}
// Another check if we have been cancelled
@@ -293,31 +268,44 @@ public class ImportOperation extends BaseOperation<ImportKeyringParcel> {
}
SaveKeyringResult result;
- mProviderHelper.clearLog();
- if (key.isSecret()) {
- result = mProviderHelper.saveSecretKeyRing(key,
- new ProgressScaler(progressable, (int) (position * progSteps),
- (int) ((position + 1) * progSteps), 100));
- } else {
- result = mProviderHelper.savePublicKeyRing(key,
- new ProgressScaler(progressable, (int) (position * progSteps),
- (int) ((position + 1) * progSteps), 100));
+ // synchronizing prevents https://github.com/open-keychain/open-keychain/issues/1221
+ // and https://github.com/open-keychain/open-keychain/issues/1480
+ synchronized (mProviderHelper) {
+ mProviderHelper.clearLog();
+ if (key.isSecret()) {
+ result = mProviderHelper.saveSecretKeyRing(key,
+ new ProgressScaler(progressable, (int) (position * progSteps),
+ (int) ((position + 1) * progSteps), 100));
+ } else {
+ result = mProviderHelper.savePublicKeyRing(key,
+ new ProgressScaler(progressable, (int) (position * progSteps),
+ (int) ((position + 1) * progSteps), 100), entry.mExpectedFingerprint);
+ }
}
if (!result.success()) {
badKeys += 1;
- } else if (result.updated()) {
- updatedKeys += 1;
- importedMasterKeyIds.add(key.getMasterKeyId());
} else {
- newKeys += 1;
- if (key.isSecret()) {
- secret += 1;
+ if (result.updated()) {
+ updatedKeys += 1;
+ importedMasterKeyIds.add(key.getMasterKeyId());
+ } else {
+ newKeys += 1;
+ if (key.isSecret()) {
+ secret += 1;
+ }
+ importedMasterKeyIds.add(key.getMasterKeyId());
+ }
+ if (entry.mBytes == null) {
+ // synonymous to isDownloadFromKeyserver.
+ // If no byte data was supplied, import from keyserver took place
+ // this prevents file imports being noted as keyserver imports
+ mProviderHelper.renewKeyLastUpdatedTime(key.getMasterKeyId(),
+ GregorianCalendar.getInstance().getTimeInMillis(),
+ TimeUnit.MILLISECONDS);
}
- importedMasterKeyIds.add(key.getMasterKeyId());
}
log.add(result, 2);
-
} catch (IOException | PgpGeneralException e) {
Log.e(Constants.TAG, "Encountered bad key on import!", e);
++badKeys;
@@ -327,9 +315,15 @@ public class ImportOperation extends BaseOperation<ImportKeyringParcel> {
}
// Special: consolidate on secret key import (cannot be cancelled!)
+ // synchronized on mProviderHelper to prevent
+ // https://github.com/open-keychain/open-keychain/issues/1221 since a consolidate deletes
+ // and re-inserts keys, which could conflict with a parallel db key update
if (secret > 0) {
setPreventCancel();
- ConsolidateResult result = mProviderHelper.consolidateDatabaseStep1(progressable);
+ ConsolidateResult result;
+ synchronized (mProviderHelper) {
+ result = mProviderHelper.consolidateDatabaseStep1(progressable);
+ }
log.add(result, 1);
}
@@ -386,7 +380,7 @@ public class ImportOperation extends BaseOperation<ImportKeyringParcel> {
@NonNull
@Override
- public OperationResult execute(ImportKeyringParcel importInput, CryptoInputParcel cryptoInput) {
+ public ImportKeyResult execute(ImportKeyringParcel importInput, CryptoInputParcel cryptoInput) {
ArrayList<ParcelableKeyRing> keyList = importInput.mKeyList;
String keyServer = importInput.mKeyserver;
@@ -411,20 +405,8 @@ public class ImportOperation extends BaseOperation<ImportKeyringParcel> {
} else {
proxy = cryptoInput.getParcelableProxy().getProxy();
}
- // if there is more than one key with the same fingerprint, we do a serial import to
- // prevent
- // https://github.com/open-keychain/open-keychain/issues/1221
- HashSet<String> keyFingerprintSet = new HashSet<>();
- for (int i = 0; i < keyList.size(); i++) {
- keyFingerprintSet.add(keyList.get(i).mExpectedFingerprint);
- }
- if (keyFingerprintSet.size() == keyList.size()) {
- // all keys have unique fingerprints
- result = multiThreadedKeyImport(keyList.iterator(), keyList.size(), keyServer,
- proxy);
- } else {
- result = serialKeyRingImport(keyList, keyServer, proxy);
- }
+
+ result = multiThreadedKeyImport(keyList.iterator(), keyList.size(), keyServer, proxy);
}
ContactSyncAdapterService.requestSync();
@@ -462,7 +444,8 @@ public class ImportOperation extends BaseOperation<ImportKeyringParcel> {
ArrayList<ParcelableKeyRing> list = new ArrayList<>();
list.add(pkRing);
- return serialKeyRingImport(list, keyServer, ignoreProgressable, proxy);
+ return serialKeyRingImport(list.iterator(), 1, keyServer,
+ ignoreProgressable, proxy);
}
};
@@ -486,18 +469,18 @@ public class ImportOperation extends BaseOperation<ImportKeyringParcel> {
}
return accumulator.getConsolidatedResult();
}
- return null; // TODO: Decide if we should just crash instead of returning null
+ return new ImportKeyResult(ImportKeyResult.RESULT_FAIL_NOTHING, new OperationLog());
}
/**
* Used to accumulate the results of individual key imports
*/
- private class KeyImportAccumulator {
+ public static class KeyImportAccumulator {
private OperationResult.OperationLog mImportLog = new OperationResult.OperationLog();
Progressable mProgressable;
private int mTotalKeys;
private int mImportedKeys = 0;
- ArrayList<Long> mImportedMasterKeyIds = new ArrayList<Long>();
+ ArrayList<Long> mImportedMasterKeyIds = new ArrayList<>();
private int mBadKeys = 0;
private int mNewKeys = 0;
private int mUpdatedKeys = 0;
@@ -515,21 +498,17 @@ public class ImportOperation extends BaseOperation<ImportKeyringParcel> {
public KeyImportAccumulator(int totalKeys, Progressable externalProgressable) {
mTotalKeys = totalKeys;
mProgressable = externalProgressable;
- mProgressable.setProgress(0, totalKeys);
- }
-
- public int getTotalKeys() {
- return mTotalKeys;
- }
-
- public int getImportedKeys() {
- return mImportedKeys;
+ if (mProgressable != null) {
+ mProgressable.setProgress(0, totalKeys);
+ }
}
public synchronized void accumulateKeyImport(ImportKeyResult result) {
mImportedKeys++;
- mProgressable.setProgress(mImportedKeys, mTotalKeys);
+ if (mProgressable != null) {
+ mProgressable.setProgress(mImportedKeys, mTotalKeys);
+ }
mImportLog.addAll(result.getLog().toList());//accumulates log
mBadKeys += result.mBadKeys;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/KeybaseVerificationOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/KeybaseVerificationOperation.java
index 30f37dd4f..8f1abde83 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/KeybaseVerificationOperation.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/KeybaseVerificationOperation.java
@@ -43,7 +43,7 @@ import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.operations.results.DecryptVerifyResult;
import org.sufficientlysecure.keychain.operations.results.KeybaseVerificationResult;
import org.sufficientlysecure.keychain.operations.results.OperationResult;
-import org.sufficientlysecure.keychain.pgp.PgpDecryptVerify;
+import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyOperation;
import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyInputParcel;
import org.sufficientlysecure.keychain.pgp.Progressable;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
@@ -141,7 +141,7 @@ public class KeybaseVerificationOperation extends BaseOperation<KeybaseVerificat
}
}
- PgpDecryptVerify op = new PgpDecryptVerify(mContext, mProviderHelper, mProgressable);
+ PgpDecryptVerifyOperation op = new PgpDecryptVerifyOperation(mContext, mProviderHelper, mProgressable);
PgpDecryptVerifyInputParcel input = new PgpDecryptVerifyInputParcel(messageBytes)
.setSignedLiteralData(true)
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/RevokeOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/RevokeOperation.java
index ecf64e1af..975cf541a 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/RevokeOperation.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/RevokeOperation.java
@@ -20,7 +20,6 @@
package org.sufficientlysecure.keychain.operations;
import android.content.Context;
-import android.database.Cursor;
import android.net.Uri;
import android.support.annotation.NonNull;
@@ -39,7 +38,7 @@ import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.util.Log;
-public class RevokeOperation extends BaseOperation<RevokeKeyringParcel> {
+public class RevokeOperation extends BaseOperation<RevokeKeyringParcel> {
public RevokeOperation(Context context, ProviderHelper providerHelper, Progressable progressable) {
super(context, providerHelper, progressable);
@@ -71,13 +70,15 @@ public class RevokeOperation extends BaseOperation<RevokeKeyringParcel> {
return new RevokeResult(RevokeResult.RESULT_ERROR, log, masterKeyId);
}
- SaveKeyringParcel saveKeyringParcel = getRevokedSaveKeyringParcel(masterKeyId,
- keyRing.getFingerprint());
+ SaveKeyringParcel saveKeyringParcel =
+ new SaveKeyringParcel(masterKeyId, keyRing.getFingerprint());
// all revoke operations are made atomic as of now
saveKeyringParcel.setUpdateOptions(revokeKeyringParcel.mUpload, true,
revokeKeyringParcel.mKeyserver);
+ saveKeyringParcel.mRevokeSubKeys.add(masterKeyId);
+
InputPendingResult revokeAndUploadResult = new EditKeyOperation(mContext,
mProviderHelper, mProgressable, mCancelled)
.execute(saveKeyringParcel, cryptoInputParcel);
@@ -92,54 +93,15 @@ public class RevokeOperation extends BaseOperation<RevokeKeyringParcel> {
log.add(OperationResult.LogType.MSG_REVOKE_OK, 1);
return new RevokeResult(RevokeResult.RESULT_OK, log, masterKeyId);
} else {
- log.add(OperationResult.LogType.MSG_REVOKE_KEY_FAIL, 1);
+ log.add(OperationResult.LogType.MSG_REVOKE_ERROR_KEY_FAIL, 1);
return new RevokeResult(RevokeResult.RESULT_ERROR, log, masterKeyId);
}
} catch (PgpKeyNotFoundException | ProviderHelper.NotFoundException e) {
Log.e(Constants.TAG, "could not find key to revoke", e);
- log.add(OperationResult.LogType.MSG_REVOKE_KEY_FAIL, 1);
+ log.add(OperationResult.LogType.MSG_REVOKE_ERROR_KEY_FAIL, 1);
return new RevokeResult(RevokeResult.RESULT_ERROR, log, masterKeyId);
}
}
- private SaveKeyringParcel getRevokedSaveKeyringParcel(long masterKeyId, byte[] fingerprint) {
- final String[] SUBKEYS_PROJECTION = new String[]{
- KeychainContract.Keys.KEY_ID
- };
- final int INDEX_KEY_ID = 0;
-
- Uri keysUri = KeychainContract.Keys.buildKeysUri(masterKeyId);
- Cursor subKeyCursor =
- mContext.getContentResolver().query(keysUri, SUBKEYS_PROJECTION, null, null, null);
-
- SaveKeyringParcel saveKeyringParcel =
- new SaveKeyringParcel(masterKeyId, fingerprint);
-
- // add all subkeys, for revocation
- while (subKeyCursor != null && subKeyCursor.moveToNext()) {
- saveKeyringParcel.mRevokeSubKeys.add(subKeyCursor.getLong(INDEX_KEY_ID));
- }
- if (subKeyCursor != null) {
- subKeyCursor.close();
- }
-
- final String[] USER_IDS_PROJECTION = new String[]{
- KeychainContract.UserPackets.USER_ID
- };
- final int INDEX_USER_ID = 0;
-
- Uri userIdsUri = KeychainContract.UserPackets.buildUserIdsUri(masterKeyId);
- Cursor userIdCursor = mContext.getContentResolver().query(
- userIdsUri, USER_IDS_PROJECTION, null, null, null);
-
- while (userIdCursor != null && userIdCursor.moveToNext()) {
- saveKeyringParcel.mRevokeUserIds.add(userIdCursor.getString(INDEX_USER_ID));
- }
- if (userIdCursor != null) {
- userIdCursor.close();
- }
-
- return saveKeyringParcel;
- }
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/LinkedVerifyResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/LinkedVerifyResult.java
new file mode 100644
index 000000000..42e9ec3f0
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/LinkedVerifyResult.java
@@ -0,0 +1,49 @@
+/*
+ * 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 LinkedVerifyResult extends OperationResult {
+
+ public LinkedVerifyResult(int result, OperationLog log) {
+ super(result, log);
+ }
+
+ /** Construct from a parcel - trivial because we have no extra data. */
+ public LinkedVerifyResult(Parcel source) {
+ super(source);
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ super.writeToParcel(dest, flags);
+ }
+
+ public static Creator<LinkedVerifyResult> CREATOR = new Creator<LinkedVerifyResult>() {
+ public LinkedVerifyResult createFromParcel(final Parcel source) {
+ return new LinkedVerifyResult(source);
+ }
+
+ public LinkedVerifyResult[] newArray(final int size) {
+ return new LinkedVerifyResult[size];
+ }
+ };
+
+}
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 3c15a2e7b..3856209b3 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
@@ -20,6 +20,7 @@ package org.sufficientlysecure.keychain.operations.results;
import android.app.Activity;
import android.content.Intent;
+import android.content.res.Resources;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.annotation.NonNull;
@@ -52,6 +53,8 @@ import java.util.List;
*/
public abstract class OperationResult implements Parcelable {
+ final static String INDENTATION_WHITESPACE = " ";
+
public static final String EXTRA_RESULT = "operation_result";
/**
@@ -166,6 +169,27 @@ public abstract class OperationResult implements Parcelable {
", mIndent=" + mIndent +
'}';
}
+
+ StringBuilder getPrintableLogEntry(Resources resources, int indent) {
+
+ StringBuilder result = new StringBuilder();
+ int padding = mIndent +indent;
+ if (padding > INDENTATION_WHITESPACE.length()) {
+ padding = INDENTATION_WHITESPACE.length();
+ }
+ result.append(INDENTATION_WHITESPACE, 0, padding);
+ result.append(LOG_LEVEL_NAME[mType.mLevel.ordinal()]).append(' ');
+
+ // special case: first parameter may be a quantity
+ if (mParameters != null && mParameters.length > 0 && mParameters[0] instanceof Integer) {
+ result.append(resources.getQuantityString(mType.getMsgId(), (Integer) mParameters[0], mParameters));
+ } else {
+ result.append(resources.getString(mType.getMsgId(), mParameters));
+ }
+
+ return result;
+ }
+
}
public static class SubLogEntryParcel extends LogEntryParcel {
@@ -202,6 +226,17 @@ public abstract class OperationResult implements Parcelable {
dest.writeParcelable(mSubResult, 0);
}
+ @Override
+ StringBuilder getPrintableLogEntry(Resources resources, int indent) {
+
+ LogEntryParcel subEntry = mSubResult.getLog().getLast();
+ if (subEntry != null) {
+ return subEntry.getPrintableLogEntry(resources, mIndent +indent);
+ } else {
+ return super.getPrintableLogEntry(resources, indent);
+ }
+ }
+
}
public Showable createNotify(final Activity activity) {
@@ -245,15 +280,15 @@ public abstract class OperationResult implements Parcelable {
}
return Notify.create(activity, logText, Notify.LENGTH_LONG, style,
- new ActionListener() {
- @Override
- public void onAction() {
- Intent intent = new Intent(
- activity, LogDisplayActivity.class);
- intent.putExtra(LogDisplayFragment.EXTRA_RESULT, OperationResult.this);
- activity.startActivity(intent);
- }
- }, R.string.snackbar_details);
+ new ActionListener() {
+ @Override
+ public void onAction() {
+ Intent intent = new Intent(
+ activity, LogDisplayActivity.class);
+ intent.putExtra(LogDisplayFragment.EXTRA_RESULT, OperationResult.this);
+ activity.startActivity(intent);
+ }
+ }, R.string.snackbar_details);
}
@@ -289,6 +324,8 @@ public abstract class OperationResult implements Parcelable {
MSG_IP_ERROR_IO_EXC (LogLevel.ERROR, R.string.msg_ip_error_io_exc),
MSG_IP_ERROR_OP_EXC (LogLevel.ERROR, R.string.msg_ip_error_op_exc),
MSG_IP_ERROR_REMOTE_EX (LogLevel.ERROR, R.string.msg_ip_error_remote_ex),
+ MSG_IP_FINGERPRINT_ERROR (LogLevel.ERROR, R.string.msg_ip_fingerprint_error),
+ MSG_IP_FINGERPRINT_OK (LogLevel.INFO, R.string.msg_ip_fingerprint_ok),
MSG_IP_INSERT_KEYRING (LogLevel.DEBUG, R.string.msg_ip_insert_keyring),
MSG_IP_INSERT_SUBKEYS (LogLevel.DEBUG, R.string.msg_ip_insert_keys),
MSG_IP_PREPARE (LogLevel.DEBUG, R.string.msg_ip_prepare),
@@ -631,6 +668,7 @@ public abstract class OperationResult implements Parcelable {
MSG_DC_TRAIL_SYM (LogLevel.DEBUG, R.string.msg_dc_trail_sym),
MSG_DC_TRAIL_UNKNOWN (LogLevel.DEBUG, R.string.msg_dc_trail_unknown),
MSG_DC_UNLOCKING (LogLevel.INFO, R.string.msg_dc_unlocking),
+ MSG_DC_INSECURE_ENCRYPTION_KEY (LogLevel.WARN, R.string.msg_dc_insecure_encryption_key),
MSG_DC_INSECURE_SYMMETRIC_ENCRYPTION_ALGO(LogLevel.WARN, R.string.msg_dc_insecure_symmetric_encryption_algo),
MSG_DC_INSECURE_HASH_ALGO(LogLevel.ERROR, R.string.msg_dc_insecure_hash_algo),
MSG_DC_INSECURE_MDC_MISSING(LogLevel.ERROR, R.string.msg_dc_insecure_mdc_missing),
@@ -704,21 +742,21 @@ public abstract class OperationResult implements Parcelable {
MSG_IMPORT_FETCH_ERROR (LogLevel.ERROR, R.string.msg_import_fetch_error),
MSG_IMPORT_FETCH_ERROR_DECODE (LogLevel.ERROR, R.string.msg_import_fetch_error_decode),
+ MSG_IMPORT_FETCH_ERROR_KEYSERVER(LogLevel.ERROR, R.string.msg_import_fetch_error_keyserver),
+ MSG_IMPORT_FETCH_ERROR_KEYSERVER_SECRET (LogLevel.ERROR, R.string.msg_import_fetch_error_keyserver_secret),
+ MSG_IMPORT_FETCH_KEYBASE (LogLevel.INFO, R.string.msg_import_fetch_keybase),
MSG_IMPORT_FETCH_KEYSERVER (LogLevel.INFO, R.string.msg_import_fetch_keyserver),
MSG_IMPORT_FETCH_KEYSERVER_OK (LogLevel.DEBUG, R.string.msg_import_fetch_keyserver_ok),
- MSG_IMPORT_FETCH_KEYSERVER_ERROR (LogLevel.ERROR, R.string.msg_import_fetch_keyserver_error),
- MSG_IMPORT_FETCH_KEYBASE (LogLevel.INFO, R.string.msg_import_fetch_keybase),
MSG_IMPORT_KEYSERVER (LogLevel.DEBUG, R.string.msg_import_keyserver),
MSG_IMPORT_MERGE (LogLevel.DEBUG, R.string.msg_import_merge),
MSG_IMPORT_MERGE_ERROR (LogLevel.ERROR, R.string.msg_import_merge_error),
- 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),
MSG_EXPORT (LogLevel.START, R.plurals.msg_export),
+ MSG_EXPORT_FILE_NAME (LogLevel.INFO, R.string.msg_export_file_name),
MSG_EXPORT_UPLOAD_PUBLIC (LogLevel.START, R.string.msg_export_upload_public),
MSG_EXPORT_PUBLIC (LogLevel.DEBUG, R.string.msg_export_public),
MSG_EXPORT_SECRET (LogLevel.DEBUG, R.string.msg_export_secret),
@@ -763,10 +801,9 @@ public abstract class OperationResult implements Parcelable {
MSG_DEL_FAIL (LogLevel.WARN, R.plurals.msg_del_fail),
MSG_REVOKE_ERROR_EMPTY (LogLevel.ERROR, R.string.msg_revoke_error_empty),
- MSG_REVOKE_ERROR_MULTI_SECRET (LogLevel.DEBUG, R.string.msg_revoke_error_multi_secret),
- MSG_REVOKE_ERROR_NOT_FOUND (LogLevel.DEBUG, R.string.msg_revoke_error_multi_secret),
+ MSG_REVOKE_ERROR_NOT_FOUND (LogLevel.ERROR, R.string.msg_revoke_error_not_found),
MSG_REVOKE (LogLevel.DEBUG, R.string.msg_revoke_key),
- MSG_REVOKE_KEY_FAIL (LogLevel.ERROR, R.string.msg_revoke_key_fail),
+ MSG_REVOKE_ERROR_KEY_FAIL (LogLevel.ERROR, R.string.msg_revoke_key_fail),
MSG_REVOKE_OK (LogLevel.OK, R.string.msg_revoke_ok),
// keybase verification
@@ -781,17 +818,31 @@ public abstract class OperationResult implements Parcelable {
MSG_KEYBASE_ERROR_PAYLOAD_MISMATCH(LogLevel.ERROR,
R.string.msg_keybase_error_msg_payload_mismatch),
- // export log
- MSG_EXPORT_LOG(LogLevel.START,R.string.msg_export_log_start),
- MSG_EXPORT_LOG_EXPORT_ERROR_NO_FILE(LogLevel.ERROR,R.string.msg_export_log_error_no_file),
- MSG_EXPORT_LOG_EXPORT_ERROR_FOPEN(LogLevel.ERROR,R.string.msg_export_log_error_fopen),
- MSG_EXPORT_LOG_EXPORT_ERROR_WRITING(LogLevel.ERROR,R.string.msg_export_log_error_writing),
- MSG_EXPORT_LOG_EXPORT_SUCCESS (LogLevel.OK, R.string.msg_export_log_success),
-
- // mim parsing
+ // mime parsing
MSG_MIME_PARSING(LogLevel.START,R.string.msg_mime_parsing_start),
MSG_MIME_PARSING_ERROR(LogLevel.ERROR,R.string.msg_mime_parsing_error),
MSG_MIME_PARSING_SUCCESS(LogLevel.OK,R.string.msg_mime_parsing_success),
+
+ MSG_LV (LogLevel.START, R.string.msg_lv),
+ MSG_LV_MATCH (LogLevel.DEBUG, R.string.msg_lv_match),
+ MSG_LV_MATCH_ERROR (LogLevel.ERROR, R.string.msg_lv_match_error),
+ MSG_LV_FP_OK (LogLevel.DEBUG, R.string.msg_lv_fp_ok),
+ MSG_LV_FP_ERROR (LogLevel.ERROR, R.string.msg_lv_fp_error),
+
+ MSG_LV_ERROR_TWITTER_AUTH (LogLevel.ERROR, R.string.msg_lv_error_twitter_auth),
+ MSG_LV_ERROR_TWITTER_HANDLE (LogLevel.ERROR, R.string.msg_lv_error_twitter_handle),
+ MSG_LV_ERROR_TWITTER_RESPONSE (LogLevel.ERROR, R.string.msg_lv_error_twitter_response),
+ MSG_LV_ERROR_GITHUB_HANDLE (LogLevel.ERROR, R.string.msg_lv_error_github_handle),
+ MSG_LV_ERROR_GITHUB_NOT_FOUND (LogLevel.ERROR, R.string.msg_lv_error_github_not_found),
+
+ MSG_LV_FETCH (LogLevel.DEBUG, R.string.msg_lv_fetch),
+ MSG_LV_FETCH_REDIR (LogLevel.DEBUG, R.string.msg_lv_fetch_redir),
+ MSG_LV_FETCH_OK (LogLevel.DEBUG, R.string.msg_lv_fetch_ok),
+ MSG_LV_FETCH_ERROR (LogLevel.ERROR, R.string.msg_lv_fetch_error),
+ MSG_LV_FETCH_ERROR_URL (LogLevel.ERROR, R.string.msg_lv_fetch_error_url),
+ MSG_LV_FETCH_ERROR_IO (LogLevel.ERROR, R.string.msg_lv_fetch_error_io),
+ MSG_LV_FETCH_ERROR_FORMAT(LogLevel.ERROR, R.string.msg_lv_fetch_error_format),
+ MSG_LV_FETCH_ERROR_NOTHING (LogLevel.ERROR, R.string.msg_lv_fetch_error_nothing),
;
public final int mMsgId;
@@ -815,6 +866,10 @@ public abstract class OperationResult implements Parcelable {
OK, // should occur once at the end of a successful operation
CANCELLED, // should occur once at the end of a cancelled operation
}
+ // for print of debug log. keep those in sync with above!
+ static final String[] LOG_LEVEL_NAME = new String[] {
+ "[DEBUG]", "[INFO]", "[WARN]", "[ERROR]", "[START]", "[OK]", "[CANCEL]"
+ };
@Override
public int describeContents() {
@@ -913,6 +968,20 @@ public abstract class OperationResult implements Parcelable {
public Iterator<LogEntryParcel> iterator() {
return mParcels.iterator();
}
+
+ /**
+ * returns an indented String of an entire OperationLog
+ * @param indent padding to add at the start of all log entries, made for use with SubLogs
+ * @return printable, indented version of passed operationLog
+ */
+ public String getPrintableOperationLog(Resources resources, int indent) {
+ StringBuilder log = new StringBuilder();
+ for (LogEntryParcel entry : this) {
+ log.append(entry.getPrintableLogEntry(resources, indent)).append("\n");
+ }
+ return log.toString().substring(0, log.length() -1); // get rid of extra new line
+ }
+
}
}
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 770e8de91..18a27dd96 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedKeyRing.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedKeyRing.java
@@ -21,6 +21,7 @@ package org.sufficientlysecure.keychain.pgp;
import org.spongycastle.openpgp.PGPKeyRing;
import org.spongycastle.openpgp.PGPPublicKey;
import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
+import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.util.IterableIterator;
import java.io.IOException;
@@ -28,6 +29,7 @@ import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.Set;
@@ -152,4 +154,14 @@ public abstract class CanonicalizedKeyRing extends KeyRing {
return getRing().getEncoded();
}
+ public boolean containsSubkey(String expectedFingerprint) {
+ for (CanonicalizedPublicKey key : publicKeyIterator()) {
+ if (KeyFormattingUtils.convertFingerprintToHex(
+ key.getFingerprint()).equalsIgnoreCase(expectedFingerprint)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerifyOperation.java
index 1e51403fc..dda15f382 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerifyOperation.java
@@ -79,9 +79,9 @@ import java.security.SignatureException;
import java.util.Date;
import java.util.Iterator;
-public class PgpDecryptVerify extends BaseOperation<PgpDecryptVerifyInputParcel> {
+public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInputParcel> {
- public PgpDecryptVerify(Context context, ProviderHelper providerHelper, Progressable progressable) {
+ public PgpDecryptVerifyOperation(Context context, ProviderHelper providerHelper, Progressable progressable) {
super(context, providerHelper, progressable);
}
@@ -313,6 +313,27 @@ public class PgpDecryptVerify extends BaseOperation<PgpDecryptVerifyInputParcel>
return result;
}
+ private static class EncryptStreamResult {
+
+ // this is non-null iff an error occured, return directly
+ DecryptVerifyResult errorResult;
+
+ // for verification
+ PGPEncryptedData encryptedData;
+ InputStream cleartextStream;
+
+ int symmetricEncryptionAlgo = 0;
+
+ boolean skippedDisallowedKey = false;
+ boolean insecureEncryptionKey = false;
+
+ // convenience method to return with error
+ public EncryptStreamResult with(DecryptVerifyResult result) {
+ errorResult = result;
+ return this;
+ }
+
+ }
/** Decrypt and/or verify binary or ascii armored pgp data. */
@NonNull
@@ -320,42 +341,14 @@ public class PgpDecryptVerify extends BaseOperation<PgpDecryptVerifyInputParcel>
PgpDecryptVerifyInputParcel input, CryptoInputParcel cryptoInput,
InputStream in, OutputStream out, int indent) throws IOException, PGPException {
- OpenPgpSignatureResultBuilder signatureResultBuilder = new OpenPgpSignatureResultBuilder();
- OpenPgpDecryptionResultBuilder decryptionResultBuilder = new OpenPgpDecryptionResultBuilder();
OperationLog log = new OperationLog();
log.add(LogType.MSG_DC, indent);
indent += 1;
- JcaPGPObjectFactory pgpF = new JcaPGPObjectFactory(in);
- PGPEncryptedDataList enc;
- Object o = pgpF.nextObject();
-
int currentProgress = 0;
updateProgress(R.string.progress_reading_data, currentProgress, 100);
- if (o instanceof PGPEncryptedDataList) {
- enc = (PGPEncryptedDataList) o;
- } else {
- enc = (PGPEncryptedDataList) pgpF.nextObject();
- }
-
- if (enc == null) {
- log.add(LogType.MSG_DC_ERROR_INVALID_DATA, indent);
- return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log);
- }
-
- InputStream clear;
- PGPEncryptedData encryptedData;
-
- PGPPublicKeyEncryptedData encryptedDataAsymmetric = null;
- PGPPBEEncryptedData encryptedDataSymmetric = null;
- CanonicalizedSecretKey secretEncryptionKey = null;
- Iterator<?> it = enc.getEncryptedDataObjects();
- boolean asymmetricPacketFound = false;
- 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;
@@ -375,8 +368,332 @@ public class PgpDecryptVerify extends BaseOperation<PgpDecryptVerifyInputParcel>
}
}
+ OpenPgpSignatureResultBuilder signatureResultBuilder = new OpenPgpSignatureResultBuilder();
+ OpenPgpDecryptionResultBuilder decryptionResultBuilder = new OpenPgpDecryptionResultBuilder();
+
+ JcaPGPObjectFactory plainFact;
+ Object dataChunk;
+ EncryptStreamResult esResult = null;
+ { // resolve encrypted (symmetric and asymmetric) packets
+ JcaPGPObjectFactory pgpF = new JcaPGPObjectFactory(in);
+ Object obj = pgpF.nextObject();
+
+ if (obj instanceof PGPEncryptedDataList) {
+ esResult = handleEncryptedPacket(
+ input, cryptoInput, (PGPEncryptedDataList) obj, log, indent, currentProgress);
+
+ // if there is an error, nothing left to do here
+ if (esResult.errorResult != null) {
+ return esResult.errorResult;
+ }
+
+ // if this worked out so far, the data is encrypted
+ decryptionResultBuilder.setEncrypted(true);
+
+ if (esResult.insecureEncryptionKey) {
+ log.add(LogType.MSG_DC_INSECURE_SYMMETRIC_ENCRYPTION_ALGO, indent + 1);
+ decryptionResultBuilder.setInsecure(true);
+ }
+
+ // Check for insecure encryption algorithms!
+ if (!PgpSecurityConstants.isSecureSymmetricAlgorithm(esResult.symmetricEncryptionAlgo)) {
+ log.add(LogType.MSG_DC_INSECURE_SYMMETRIC_ENCRYPTION_ALGO, indent + 1);
+ decryptionResultBuilder.setInsecure(true);
+ }
+
+ plainFact = new JcaPGPObjectFactory(esResult.cleartextStream);
+ dataChunk = plainFact.nextObject();
+
+ } else {
+ decryptionResultBuilder.setEncrypted(false);
+
+ plainFact = pgpF;
+ dataChunk = obj;
+ }
+
+ }
+
+ log.add(LogType.MSG_DC_PREP_STREAMS, indent);
+
+ int signatureIndex = -1;
+ CanonicalizedPublicKeyRing signingRing = null;
+ CanonicalizedPublicKey signingKey = null;
+
+ log.add(LogType.MSG_DC_CLEAR, indent);
+ indent += 1;
+
+ // resolve compressed data
+ if (dataChunk instanceof PGPCompressedData) {
+ log.add(LogType.MSG_DC_CLEAR_DECOMPRESS, indent + 1);
+ currentProgress += 2;
+ updateProgress(R.string.progress_decompressing_data, currentProgress, 100);
+
+ PGPCompressedData compressedData = (PGPCompressedData) dataChunk;
+
+ JcaPGPObjectFactory fact = new JcaPGPObjectFactory(compressedData.getDataStream());
+ dataChunk = fact.nextObject();
+ plainFact = fact;
+ }
+
+ // resolve leading signature data
+ PGPOnePassSignature signature = null;
+ if (dataChunk instanceof PGPOnePassSignatureList) {
+ 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) {
+ 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...");
+ }
+ }
+
+ 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());
+ }
+ }
+
+ // check for insecure signing key
+ // TODO: checks on signingRing ?
+ if (signingKey != null && ! PgpSecurityConstants.isSecureKey(signingKey)) {
+ log.add(LogType.MSG_DC_INSECURE_KEY, indent + 1);
+ signatureResultBuilder.setInsecure(true);
+ }
+
+ dataChunk = plainFact.nextObject();
+ }
+
+ if (dataChunk instanceof PGPSignatureList) {
+ // skip
+ dataChunk = plainFact.nextObject();
+ }
+
+ OpenPgpMetadata metadata;
+
+ if ( ! (dataChunk instanceof PGPLiteralData)) {
+
+ log.add(LogType.MSG_DC_ERROR_INVALID_DATA, indent);
+ return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log);
+
+ }
+
+ log.add(LogType.MSG_DC_CLEAR_DATA, indent + 1);
+ indent += 2;
+ currentProgress += 4;
+ updateProgress(R.string.progress_decrypting, currentProgress, 100);
+
+ PGPLiteralData literalData = (PGPLiteralData) dataChunk;
+
+ String originalFilename = literalData.getFileName();
+ if (originalFilename.contains("/")) {
+ originalFilename = originalFilename.substring(originalFilename.lastIndexOf('/'));
+ }
+ String mimeType = null;
+ if (literalData.getFormat() == PGPLiteralData.TEXT
+ || literalData.getFormat() == PGPLiteralData.UTF8) {
+ mimeType = "text/plain";
+ } else {
+ // try to guess from file ending
+ String extension = MimeTypeMap.getFileExtensionFromUrl(originalFilename);
+ if (extension != null) {
+ MimeTypeMap mime = MimeTypeMap.getSingleton();
+ mimeType = mime.getMimeTypeFromExtension(extension);
+ }
+ if (mimeType == null) {
+ mimeType = "application/octet-stream";
+ }
+ }
+
+ if (!"".equals(originalFilename)) {
+ log.add(LogType.MSG_DC_CLEAR_META_FILE, indent + 1, originalFilename);
+ }
+ log.add(LogType.MSG_DC_CLEAR_META_MIME, indent + 1,
+ mimeType);
+ log.add(LogType.MSG_DC_CLEAR_META_TIME, indent + 1,
+ new Date(literalData.getModificationTime().getTime()).toString());
+
+ // return here if we want to decrypt the metadata only
+ if (input.isDecryptMetadataOnly()) {
+
+ // this operation skips the entire stream to find the data length!
+ Long originalSize = literalData.findDataLength();
+
+ if (originalSize != null) {
+ log.add(LogType.MSG_DC_CLEAR_META_SIZE, indent + 1,
+ Long.toString(originalSize));
+ } else {
+ log.add(LogType.MSG_DC_CLEAR_META_SIZE_UNKNOWN, indent + 1);
+ }
+
+ metadata = new OpenPgpMetadata(
+ originalFilename,
+ mimeType,
+ literalData.getModificationTime().getTime(),
+ originalSize == null ? 0 : originalSize);
+
+ log.add(LogType.MSG_DC_OK_META_ONLY, indent);
+ DecryptVerifyResult result =
+ new DecryptVerifyResult(DecryptVerifyResult.RESULT_OK, log);
+ result.setCharset(charset);
+ result.setDecryptionMetadata(metadata);
+ return result;
+ }
+
+ int endProgress;
+ if (signature != null) {
+ endProgress = 90;
+ } else if (esResult != null && esResult.encryptedData.isIntegrityProtected()) {
+ endProgress = 95;
+ } else {
+ endProgress = 100;
+ }
+ ProgressScaler progressScaler =
+ new ProgressScaler(mProgressable, currentProgress, endProgress, 100);
+
+ InputStream dataIn = literalData.getInputStream();
+
+ long alreadyWritten = 0;
+ long wholeSize = 0; // TODO inputData.getSize() - inputData.getStreamPosition();
+ int length;
+ byte[] buffer = new byte[1 << 16];
+ while ((length = dataIn.read(buffer)) > 0) {
+ // Log.d(Constants.TAG, "read bytes: " + length);
+ if (out != null) {
+ out.write(buffer, 0, length);
+ }
+
+ // update signature buffer if signature is also present
+ if (signature != null) {
+ 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);
+ }
+ // TODO: slow annealing to fake a progress?
+ }
+
+ metadata = new OpenPgpMetadata(
+ originalFilename, mimeType, literalData.getModificationTime().getTime(), alreadyWritten);
+
+ if (signature != null) {
+ updateProgress(R.string.progress_verifying_signature, 90, 100);
+ log.add(LogType.MSG_DC_CLEAR_SIGNATURE_CHECK, indent);
+
+ PGPSignatureList signatureList = (PGPSignatureList) plainFact.nextObject();
+ PGPSignature messageSignature = signatureList.get(signatureIndex);
+
+ // Verify signature
+ boolean validSignature = signature.verify(messageSignature);
+ if (validSignature) {
+ log.add(LogType.MSG_DC_CLEAR_SIGNATURE_OK, indent + 1);
+ } else {
+ log.add(LogType.MSG_DC_CLEAR_SIGNATURE_BAD, indent + 1);
+ }
+
+ // check for insecure hash algorithms
+ if (!PgpSecurityConstants.isSecureHashAlgorithm(signature.getHashAlgorithm())) {
+ log.add(LogType.MSG_DC_INSECURE_HASH_ALGO, indent + 1);
+ signatureResultBuilder.setInsecure(true);
+ }
+
+ signatureResultBuilder.setValidSignature(validSignature);
+ }
+
+ indent -= 1;
+
+ if (esResult != null) {
+ if (esResult.encryptedData.isIntegrityProtected()) {
+ updateProgress(R.string.progress_verifying_integrity, 95, 100);
+
+ if (esResult.encryptedData.verify()) {
+ log.add(LogType.MSG_DC_INTEGRITY_CHECK_OK, indent);
+ } else {
+ log.add(LogType.MSG_DC_ERROR_INTEGRITY_CHECK, indent);
+ return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log);
+ }
+ } else if (signature == null) {
+ // If no signature is present, we *require* an MDC!
+ // Handle missing integrity protection like failed integrity protection!
+ // The MDC packet can be stripped by an attacker!
+ log.add(LogType.MSG_DC_INSECURE_MDC_MISSING, indent);
+ decryptionResultBuilder.setInsecure(true);
+ }
+ }
+
+ updateProgress(R.string.progress_done, 100, 100);
+
+ log.add(LogType.MSG_DC_OK, indent);
+
+ // Return a positive result, with metadata and verification info
+ DecryptVerifyResult result = new DecryptVerifyResult(DecryptVerifyResult.RESULT_OK, log);
+
+ result.setCachedCryptoInputParcel(cryptoInput);
+ result.setSignatureResult(signatureResultBuilder.build());
+ result.setCharset(charset);
+ result.setDecryptionResult(decryptionResultBuilder.build());
+ result.setDecryptionMetadata(metadata);
+
+ return result;
+
+ }
+
+ private EncryptStreamResult handleEncryptedPacket(PgpDecryptVerifyInputParcel input, CryptoInputParcel cryptoInput,
+ PGPEncryptedDataList enc, OperationLog log, int indent, int currentProgress) throws PGPException {
+
+ // TODO is this necessary?
+ /*
+ else if (obj instanceof PGPEncryptedDataList) {
+ enc = (PGPEncryptedDataList) pgpF.nextObject();
+ }
+ */
+
+ EncryptStreamResult result = new EncryptStreamResult();
+
+ boolean asymmetricPacketFound = false;
+ boolean symmetricPacketFound = false;
+ boolean anyPacketFound = false;
+
+ PGPPublicKeyEncryptedData encryptedDataAsymmetric = null;
+ PGPPBEEncryptedData encryptedDataSymmetric = null;
+ CanonicalizedSecretKey secretEncryptionKey = null;
+
Passphrase passphrase = null;
- boolean skippedDisallowedKey = false;
+
+ Iterator<?> it = enc.getEncryptedDataObjects();
// go through all objects and find one we can decrypt
while (it.hasNext()) {
@@ -420,7 +737,7 @@ public class PgpDecryptVerify extends BaseOperation<PgpDecryptVerifyInputParcel>
if (!input.getAllowedKeyIds().contains(masterKeyId)) {
// this key is in our db, but NOT allowed!
// continue with the next packet in the while loop
- skippedDisallowedKey = true;
+ result.skippedDisallowedKey = true;
log.add(LogType.MSG_DC_ASKIP_NOT_ALLOWED, indent + 1);
continue;
}
@@ -451,23 +768,23 @@ public class PgpDecryptVerify extends BaseOperation<PgpDecryptVerifyInputParcel>
log.add(LogType.MSG_DC_PASS_CACHED, indent + 1);
} catch (PassphraseCacheInterface.NoSecretKeyException e) {
log.add(LogType.MSG_DC_ERROR_NO_KEY, indent + 1);
- return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log);
+ return result.with(new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log));
}
// if passphrase was not cached, return here indicating that a passphrase is missing!
if (passphrase == null) {
log.add(LogType.MSG_DC_PENDING_PASSPHRASE, indent + 1);
- return new DecryptVerifyResult(log,
+ return result.with(new DecryptVerifyResult(log,
RequiredInputParcel.createRequiredDecryptPassphrase(
- secretKeyRing.getMasterKeyId(), secretEncryptionKey.getKeyId()),
- cryptoInput);
+ secretKeyRing.getMasterKeyId(), secretEncryptionKey.getKeyId()),
+ cryptoInput));
}
}
// check for insecure encryption key
if ( ! PgpSecurityConstants.isSecureKey(secretEncryptionKey)) {
log.add(LogType.MSG_DC_INSECURE_KEY, indent + 1);
- decryptionResultBuilder.setInsecure(true);
+ result.insecureEncryptionKey = true;
}
// break out of while, only decrypt the first packet where we have a key
@@ -504,9 +821,9 @@ public class PgpDecryptVerify extends BaseOperation<PgpDecryptVerifyInputParcel>
if (passphrase == null) {
log.add(LogType.MSG_DC_PENDING_PASSPHRASE, indent + 1);
- return new DecryptVerifyResult(log,
+ return result.with(new DecryptVerifyResult(log,
RequiredInputParcel.createRequiredSymmetricPassphrase(),
- cryptoInput);
+ cryptoInput));
}
} else {
@@ -533,10 +850,7 @@ public class PgpDecryptVerify extends BaseOperation<PgpDecryptVerifyInputParcel>
}
}
- log.add(LogType.MSG_DC_PREP_STREAMS, indent);
-
// we made sure above one of these two would be true
- int symmetricEncryptionAlgo;
if (symmetricPacketFound) {
currentProgress += 2;
updateProgress(R.string.progress_preparing_streams, currentProgress, 100);
@@ -548,16 +862,16 @@ public class PgpDecryptVerify extends BaseOperation<PgpDecryptVerifyInputParcel>
passphrase.getCharArray());
try {
- clear = encryptedDataSymmetric.getDataStream(decryptorFactory);
+ result.cleartextStream = encryptedDataSymmetric.getDataStream(decryptorFactory);
} catch (PGPDataValidationException e) {
- log.add(LogType.MSG_DC_ERROR_SYM_PASSPHRASE, indent +1);
- return new DecryptVerifyResult(log,
- RequiredInputParcel.createRequiredSymmetricPassphrase(), cryptoInput);
+ log.add(LogType.MSG_DC_ERROR_SYM_PASSPHRASE, indent + 1);
+ return result.with(new DecryptVerifyResult(log,
+ RequiredInputParcel.createRequiredSymmetricPassphrase(), cryptoInput));
}
- encryptedData = encryptedDataSymmetric;
+ result.encryptedData = encryptedDataSymmetric;
- symmetricEncryptionAlgo = encryptedDataSymmetric.getSymmetricAlgorithm(decryptorFactory);
+ result.symmetricEncryptionAlgo = encryptedDataSymmetric.getSymmetricAlgorithm(decryptorFactory);
} else if (asymmetricPacketFound) {
currentProgress += 2;
updateProgress(R.string.progress_extracting_key, currentProgress, 100);
@@ -566,11 +880,11 @@ public class PgpDecryptVerify extends BaseOperation<PgpDecryptVerifyInputParcel>
log.add(LogType.MSG_DC_UNLOCKING, indent + 1);
if (!secretEncryptionKey.unlock(passphrase)) {
log.add(LogType.MSG_DC_ERROR_BAD_PASSPHRASE, indent + 1);
- return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log);
+ return result.with(new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log));
}
} catch (PgpGeneralException e) {
log.add(LogType.MSG_DC_ERROR_EXTRACT_KEY, indent + 1);
- return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log);
+ return result.with(new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log));
}
currentProgress += 2;
@@ -585,300 +899,41 @@ public class PgpDecryptVerify extends BaseOperation<PgpDecryptVerifyInputParcel>
&& !decryptorFactory.hasCachedSessionData(encryptedDataAsymmetric)) {
log.add(LogType.MSG_DC_PENDING_NFC, indent + 1);
- return new DecryptVerifyResult(log, RequiredInputParcel.createNfcDecryptOperation(
+ return result.with(new DecryptVerifyResult(log, RequiredInputParcel.createNfcDecryptOperation(
secretEncryptionKey.getRing().getMasterKeyId(),
secretEncryptionKey.getKeyId(), encryptedDataAsymmetric.getSessionKey()[0]
- ),
- cryptoInput);
+ ), cryptoInput));
}
try {
- clear = encryptedDataAsymmetric.getDataStream(decryptorFactory);
+ result.cleartextStream = encryptedDataAsymmetric.getDataStream(decryptorFactory);
} catch (PGPKeyValidationException | ArrayIndexOutOfBoundsException e) {
log.add(LogType.MSG_DC_ERROR_CORRUPT_DATA, indent + 1);
- return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log);
+ return result.with(new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log));
}
- symmetricEncryptionAlgo = encryptedDataAsymmetric.getSymmetricAlgorithm(decryptorFactory);
+ result.symmetricEncryptionAlgo = encryptedDataAsymmetric.getSymmetricAlgorithm(decryptorFactory);
+ result.encryptedData = encryptedDataAsymmetric;
cryptoInput.addCryptoData(decryptorFactory.getCachedSessionKeys());
- encryptedData = encryptedDataAsymmetric;
} else {
// there wasn't even any useful data
if (!anyPacketFound) {
log.add(LogType.MSG_DC_ERROR_NO_DATA, indent + 1);
- return new DecryptVerifyResult(DecryptVerifyResult.RESULT_NO_DATA, log);
+ return result.with(new DecryptVerifyResult(DecryptVerifyResult.RESULT_NO_DATA, log));
}
// there was data but key wasn't allowed
- if (skippedDisallowedKey) {
+ if (result.skippedDisallowedKey) {
log.add(LogType.MSG_DC_ERROR_NO_KEY, indent + 1);
- return new DecryptVerifyResult(DecryptVerifyResult.RESULT_KEY_DISALLOWED, log);
+ return result.with(new DecryptVerifyResult(DecryptVerifyResult.RESULT_KEY_DISALLOWED, log));
}
// no packet has been found where we have the corresponding secret key in our db
log.add(LogType.MSG_DC_ERROR_NO_KEY, indent + 1);
- return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log);
- }
- decryptionResultBuilder.setEncrypted(true);
-
- // Check for insecure encryption algorithms!
- if (!PgpSecurityConstants.isSecureSymmetricAlgorithm(symmetricEncryptionAlgo)) {
- log.add(LogType.MSG_DC_INSECURE_SYMMETRIC_ENCRYPTION_ALGO, indent + 1);
- decryptionResultBuilder.setInsecure(true);
- }
-
- JcaPGPObjectFactory plainFact = new JcaPGPObjectFactory(clear);
- Object dataChunk = plainFact.nextObject();
- int signatureIndex = -1;
- CanonicalizedPublicKeyRing signingRing = null;
- CanonicalizedPublicKey signingKey = null;
-
- log.add(LogType.MSG_DC_CLEAR, indent);
- indent += 1;
-
- if (dataChunk instanceof PGPCompressedData) {
- log.add(LogType.MSG_DC_CLEAR_DECOMPRESS, indent + 1);
- currentProgress += 2;
- updateProgress(R.string.progress_decompressing_data, currentProgress, 100);
-
- PGPCompressedData compressedData = (PGPCompressedData) dataChunk;
-
- 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);
- 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) {
- 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...");
- }
- }
-
- 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());
- }
- }
-
- // check for insecure signing key
- // TODO: checks on signingRing ?
- if (signingKey != null && ! PgpSecurityConstants.isSecureKey(signingKey)) {
- log.add(LogType.MSG_DC_INSECURE_KEY, indent + 1);
- signatureResultBuilder.setInsecure(true);
- }
-
- dataChunk = plainFact.nextObject();
+ return result.with(new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log));
}
- if (dataChunk instanceof PGPSignatureList) {
- // skip
- dataChunk = plainFact.nextObject();
- }
-
- OpenPgpMetadata metadata;
-
- if (dataChunk instanceof PGPLiteralData) {
- log.add(LogType.MSG_DC_CLEAR_DATA, indent + 1);
- indent += 2;
- currentProgress += 4;
- updateProgress(R.string.progress_decrypting, currentProgress, 100);
-
- PGPLiteralData literalData = (PGPLiteralData) dataChunk;
-
- String originalFilename = literalData.getFileName();
- String mimeType = null;
- if (literalData.getFormat() == PGPLiteralData.TEXT
- || literalData.getFormat() == PGPLiteralData.UTF8) {
- mimeType = "text/plain";
- } else {
- // try to guess from file ending
- String extension = MimeTypeMap.getFileExtensionFromUrl(originalFilename);
- if (extension != null) {
- MimeTypeMap mime = MimeTypeMap.getSingleton();
- mimeType = mime.getMimeTypeFromExtension(extension);
- }
- if (mimeType == null) {
- mimeType = "application/octet-stream";
- }
- }
-
- if (!"".equals(originalFilename)) {
- log.add(LogType.MSG_DC_CLEAR_META_FILE, indent + 1, originalFilename);
- }
- log.add(LogType.MSG_DC_CLEAR_META_MIME, indent + 1,
- mimeType);
- log.add(LogType.MSG_DC_CLEAR_META_TIME, indent + 1,
- new Date(literalData.getModificationTime().getTime()).toString());
-
- // return here if we want to decrypt the metadata only
- if (input.isDecryptMetadataOnly()) {
-
- // this operation skips the entire stream to find the data length!
- Long originalSize = literalData.findDataLength();
-
- if (originalSize != null) {
- log.add(LogType.MSG_DC_CLEAR_META_SIZE, indent + 1,
- Long.toString(originalSize));
- } else {
- log.add(LogType.MSG_DC_CLEAR_META_SIZE_UNKNOWN, indent + 1);
- }
-
- metadata = new OpenPgpMetadata(
- originalFilename,
- mimeType,
- literalData.getModificationTime().getTime(),
- originalSize == null ? 0 : originalSize);
-
- log.add(LogType.MSG_DC_OK_META_ONLY, indent);
- DecryptVerifyResult result =
- new DecryptVerifyResult(DecryptVerifyResult.RESULT_OK, log);
- result.setCharset(charset);
- result.setDecryptionMetadata(metadata);
- return result;
- }
-
- int endProgress;
- if (signature != null) {
- endProgress = 90;
- } else if (encryptedData.isIntegrityProtected()) {
- endProgress = 95;
- } else {
- endProgress = 100;
- }
- ProgressScaler progressScaler =
- new ProgressScaler(mProgressable, currentProgress, endProgress, 100);
-
- InputStream dataIn = literalData.getInputStream();
-
- long alreadyWritten = 0;
- long wholeSize = 0; // TODO inputData.getSize() - inputData.getStreamPosition();
- int length;
- byte[] buffer = new byte[1 << 16];
- while ((length = dataIn.read(buffer)) > 0) {
- // Log.d(Constants.TAG, "read bytes: " + length);
- if (out != null) {
- out.write(buffer, 0, length);
- }
-
- // update signature buffer if signature is also present
- if (signature != null) {
- 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);
- }
- // TODO: slow annealing to fake a progress?
- }
-
- metadata = new OpenPgpMetadata(
- originalFilename,
- mimeType,
- literalData.getModificationTime().getTime(),
- alreadyWritten);
-
- if (signature != null) {
- updateProgress(R.string.progress_verifying_signature, 90, 100);
- log.add(LogType.MSG_DC_CLEAR_SIGNATURE_CHECK, indent);
-
- PGPSignatureList signatureList = (PGPSignatureList) plainFact.nextObject();
- PGPSignature messageSignature = signatureList.get(signatureIndex);
-
- // TODO: what about binary signatures?
-
- // Verify signature
- boolean validSignature = signature.verify(messageSignature);
- if (validSignature) {
- log.add(LogType.MSG_DC_CLEAR_SIGNATURE_OK, indent + 1);
- } else {
- log.add(LogType.MSG_DC_CLEAR_SIGNATURE_BAD, indent + 1);
- }
-
- // check for insecure hash algorithms
- if (!PgpSecurityConstants.isSecureHashAlgorithm(signature.getHashAlgorithm())) {
- log.add(LogType.MSG_DC_INSECURE_HASH_ALGO, indent + 1);
- signatureResultBuilder.setInsecure(true);
- }
-
- signatureResultBuilder.setValidSignature(validSignature);
- }
-
- indent -= 1;
- } else {
- // If there is no literalData, we don't have any metadata
- metadata = null;
- }
-
- if (encryptedData.isIntegrityProtected()) {
- updateProgress(R.string.progress_verifying_integrity, 95, 100);
-
- if (encryptedData.verify()) {
- log.add(LogType.MSG_DC_INTEGRITY_CHECK_OK, indent);
- } else {
- log.add(LogType.MSG_DC_ERROR_INTEGRITY_CHECK, indent);
- return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log);
- }
- } else {
- // If no valid signature is present:
- // Handle missing integrity protection like failed integrity protection!
- // The MDC packet can be stripped by an attacker!
- Log.d(Constants.TAG, "MDC fail");
- if (!signatureResultBuilder.isValidSignature()) {
- log.add(LogType.MSG_DC_INSECURE_MDC_MISSING, indent);
- decryptionResultBuilder.setInsecure(true);
- }
- }
-
- updateProgress(R.string.progress_done, 100, 100);
-
- log.add(LogType.MSG_DC_OK, indent);
-
- // Return a positive result, with metadata and verification info
- DecryptVerifyResult result = new DecryptVerifyResult(DecryptVerifyResult.RESULT_OK, log);
- result.setCachedCryptoInputParcel(cryptoInput);
- result.setSignatureResult(signatureResultBuilder.build());
- result.setCharset(charset);
- result.setDecryptionResult(decryptionResultBuilder.build());
- result.setDecryptionMetadata(metadata);
return result;
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpHelper.java
index 32718fb4e..e8d1d3111 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpHelper.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpHelper.java
@@ -21,6 +21,7 @@ package org.sufficientlysecure.keychain.pgp;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager.NameNotFoundException;
+import android.support.annotation.NonNull;
import android.text.TextUtils;
import org.sufficientlysecure.keychain.Constants;
@@ -116,32 +117,27 @@ public class PgpHelper {
}
}
- public static String getPgpContent(CharSequence input) {
- // only decrypt if clipboard content is available and a pgp message or cleartext signature
- if (!TextUtils.isEmpty(input)) {
- Log.dEscaped(Constants.TAG, "input: " + input);
+ public static String getPgpContent(@NonNull CharSequence input) {
+ Log.dEscaped(Constants.TAG, "input: " + input);
+
+ Matcher matcher = PgpHelper.PGP_MESSAGE.matcher(input);
+ if (matcher.matches()) {
+ String text = matcher.group(1);
+ text = fixPgpMessage(text);
- Matcher matcher = PgpHelper.PGP_MESSAGE.matcher(input);
+ Log.dEscaped(Constants.TAG, "input fixed: " + text);
+ return text;
+ } else {
+ matcher = PgpHelper.PGP_CLEARTEXT_SIGNATURE.matcher(input);
if (matcher.matches()) {
String text = matcher.group(1);
- text = fixPgpMessage(text);
+ text = fixPgpCleartextSignature(text);
Log.dEscaped(Constants.TAG, "input fixed: " + text);
return text;
} else {
- matcher = PgpHelper.PGP_CLEARTEXT_SIGNATURE.matcher(input);
- if (matcher.matches()) {
- String text = matcher.group(1);
- text = fixPgpCleartextSignature(text);
-
- Log.dEscaped(Constants.TAG, "input fixed: " + text);
- return text;
- } else {
- return null;
- }
+ return null;
}
- } else {
- return null;
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSecurityConstants.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSecurityConstants.java
index 3fa549946..cbd8ce47a 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSecurityConstants.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSecurityConstants.java
@@ -23,6 +23,7 @@ import org.spongycastle.bcpg.HashAlgorithmTags;
import org.spongycastle.bcpg.PublicKeyAlgorithmTags;
import org.spongycastle.bcpg.SymmetricKeyAlgorithmTags;
+import java.util.Arrays;
import java.util.HashSet;
/**
@@ -42,24 +43,23 @@ public class PgpSecurityConstants {
* Whitelist of accepted symmetric encryption algorithms
* all other algorithms are rejected with OpenPgpDecryptionResult.RESULT_INSECURE
*/
- private static HashSet<Integer> sSymmetricAlgorithmsWhitelist = new HashSet<>();
- static {
- // General remarks: We try to keep the whitelist short to reduce attack surface
- // TODO: block IDEA?: Bad key schedule (weak keys), implementation difficulties (easy to make errors)
- sSymmetricAlgorithmsWhitelist.add(SymmetricKeyAlgorithmTags.IDEA);
- sSymmetricAlgorithmsWhitelist.add(SymmetricKeyAlgorithmTags.TRIPLE_DES); // a MUST in RFC
- sSymmetricAlgorithmsWhitelist.add(SymmetricKeyAlgorithmTags.CAST5); // default in many gpg, pgp versions, 128 bit key
- // BLOWFISH: Twofish is the successor
- // SAFER: not used widely
- // DES: < 128 bit security
- sSymmetricAlgorithmsWhitelist.add(SymmetricKeyAlgorithmTags.AES_128);
- sSymmetricAlgorithmsWhitelist.add(SymmetricKeyAlgorithmTags.AES_192);
- sSymmetricAlgorithmsWhitelist.add(SymmetricKeyAlgorithmTags.AES_256);
- sSymmetricAlgorithmsWhitelist.add(SymmetricKeyAlgorithmTags.TWOFISH); // 128 bit
- // CAMELLIA_128: not used widely
- // CAMELLIA_192: not used widely
- // CAMELLIA_256: not used widely
- }
+ private static HashSet<Integer> sSymmetricAlgorithmsWhitelist = new HashSet<>(Arrays.asList(
+ // General remarks: We try to keep the whitelist short to reduce attack surface
+ // TODO: block IDEA?: Bad key schedule (weak keys), implementation difficulties (easy to make errors)
+ SymmetricKeyAlgorithmTags.IDEA,
+ SymmetricKeyAlgorithmTags.TRIPLE_DES, // a MUST in RFC
+ SymmetricKeyAlgorithmTags.CAST5, // default in many gpg, pgp versions, 128 bit key
+ // BLOWFISH: Twofish is the successor
+ // SAFER: not used widely
+ // DES: < 128 bit security
+ SymmetricKeyAlgorithmTags.AES_128,
+ SymmetricKeyAlgorithmTags.AES_192,
+ SymmetricKeyAlgorithmTags.AES_256,
+ SymmetricKeyAlgorithmTags.TWOFISH // 128 bit
+ // CAMELLIA_128: not used widely
+ // CAMELLIA_192: not used widely
+ // CAMELLIA_256: not used widely
+ ));
public static boolean isSecureSymmetricAlgorithm(int id) {
return sSymmetricAlgorithmsWhitelist.contains(id);
@@ -77,20 +77,19 @@ public class PgpSecurityConstants {
* ((collision resistance of 112-bits))
* Implementations SHOULD NOT sign SHA-256 hashes. They MUST NOT default to signing SHA-256 hashes.
*/
- private static HashSet<Integer> sHashAlgorithmsWhitelist = new HashSet<>();
- static {
- // MD5: broken
- // SHA1: broken
- // RIPEMD160: same security properties as SHA1
- // DOUBLE_SHA: not used widely
- // MD2: not used widely
- // TIGER_192: not used widely
- // HAVAL_5_160: not used widely
- sHashAlgorithmsWhitelist.add(HashAlgorithmTags.SHA256); // compatibility for old Mailvelope versions
- sHashAlgorithmsWhitelist.add(HashAlgorithmTags.SHA384);
- sHashAlgorithmsWhitelist.add(HashAlgorithmTags.SHA512);
- // SHA224: Not used widely, Yahoo argues against it
- }
+ private static HashSet<Integer> sHashAlgorithmsWhitelist = new HashSet<>(Arrays.asList(
+ // MD5: broken
+ // SHA1: broken
+ // RIPEMD160: same security properties as SHA1
+ // DOUBLE_SHA: not used widely
+ // MD2: not used widely
+ // TIGER_192: not used widely
+ // HAVAL_5_160: not used widely
+ HashAlgorithmTags.SHA256, // compatibility for old Mailvelope versions
+ HashAlgorithmTags.SHA384,
+ HashAlgorithmTags.SHA512
+ // SHA224: Not used widely, Yahoo argues against it
+ ));
public static boolean isSecureHashAlgorithm(int id) {
return sHashAlgorithmsWhitelist.contains(id);
@@ -106,12 +105,11 @@ public class PgpSecurityConstants {
* bitlength less than 1023 bits.
* Implementations MUST NOT accept any RSA keys with bitlength less than 2047 bits after January 1, 2016.
*/
- private static HashSet<String> sCurveWhitelist = new HashSet<>();
- static {
- sCurveWhitelist.add(NISTNamedCurves.getOID("P-256").getId());
- sCurveWhitelist.add(NISTNamedCurves.getOID("P-384").getId());
- sCurveWhitelist.add(NISTNamedCurves.getOID("P-521").getId());
- }
+ private static HashSet<String> sCurveWhitelist = new HashSet<>(Arrays.asList(
+ NISTNamedCurves.getOID("P-256").getId(),
+ NISTNamedCurves.getOID("P-384").getId(),
+ NISTNamedCurves.getOID("P-521").getId()
+ ));
public static boolean isSecureKey(CanonicalizedPublicKey key) {
switch (key.getAlgorithm()) {
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 a7baddf8b..ca98882d8 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java
@@ -216,17 +216,6 @@ public class UncachedKeyRing implements Serializable {
}
- public boolean containsSubkey(String expectedFingerprint) {
- Iterator<PGPPublicKey> it = mRing.getPublicKeys();
- while (it.hasNext()) {
- if (KeyFormattingUtils.convertFingerprintToHex(
- it.next().getFingerprint()).equalsIgnoreCase(expectedFingerprint)) {
- return true;
- }
- }
- return false;
- }
-
public interface IteratorWithIOThrow<E> {
public boolean hasNext() throws IOException;
public E next() throws IOException;
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 26f046372..013a6bf14 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedPublicKey.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedPublicKey.java
@@ -368,4 +368,5 @@ public class UncachedPublicKey {
return calendar.getTime();
}
+
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedUserAttribute.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedUserAttribute.java
index 2c7f0187a..535314607 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedUserAttribute.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedUserAttribute.java
@@ -1,4 +1,8 @@
/*
+<<<<<<< HEAD
+ * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
+=======
+>>>>>>> development
* Copyright (C) 2014 Vincent Breitmoser <v.breitmoser@mugenguild.com>
*
* This program is free software: you can redistribute it and/or modify
@@ -37,6 +41,7 @@ public class WrappedUserAttribute implements Serializable {
public static final int UAT_NONE = 0;
public static final int UAT_IMAGE = UserAttributeSubpacketTags.IMAGE_ATTRIBUTE;
+ public static final int UAT_URI_ATTRIBUTE = 101;
private PGPUserAttributeSubpacketVector mVector;
@@ -77,7 +82,7 @@ public class WrappedUserAttribute implements Serializable {
public static WrappedUserAttribute fromData (byte[] data) throws IOException {
UserAttributeSubpacketInputStream in =
new UserAttributeSubpacketInputStream(new ByteArrayInputStream(data));
- ArrayList<UserAttributeSubpacket> list = new ArrayList<UserAttributeSubpacket>();
+ ArrayList<UserAttributeSubpacket> list = new ArrayList<>();
while (in.available() > 0) {
list.add(in.readPacket());
}
@@ -121,6 +126,7 @@ public class WrappedUserAttribute implements Serializable {
private void readObjectNoData() throws ObjectStreamException {
}
+ @SuppressWarnings("SimplifiableIfStatement")
@Override
public boolean equals(Object o) {
if (!WrappedUserAttribute.class.isInstance(o)) {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java
index 0d9a4ac16..ee28b5f36 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java
@@ -51,6 +51,11 @@ public class KeychainContract {
String EXPIRY = "expiry";
}
+ interface UpdatedKeysColumns {
+ String MASTER_KEY_ID = "master_key_id"; // not a database id
+ String LAST_UPDATED = "last_updated"; // time since epoch in seconds
+ }
+
interface UserPacketsColumns {
String MASTER_KEY_ID = "master_key_id"; // foreign key to key_rings._ID
String TYPE = "type"; // not a database id
@@ -97,6 +102,8 @@ public class KeychainContract {
public static final String BASE_KEY_RINGS = "key_rings";
+ public static final String BASE_UPDATED_KEYS = "updated_keys";
+
public static final String PATH_UNIFIED = "unified";
public static final String PATH_FIND = "find";
@@ -106,6 +113,7 @@ public class KeychainContract {
public static final String PATH_PUBLIC = "public";
public static final String PATH_SECRET = "secret";
public static final String PATH_USER_IDS = "user_ids";
+ public static final String PATH_LINKED_IDS = "linked_ids";
public static final String PATH_KEYS = "keys";
public static final String PATH_CERTS = "certs";
@@ -234,6 +242,16 @@ public class KeychainContract {
}
+ public static class UpdatedKeys implements UpdatedKeysColumns, BaseColumns {
+ public static final Uri CONTENT_URI = BASE_CONTENT_URI_INTERNAL.buildUpon()
+ .appendPath(BASE_UPDATED_KEYS).build();
+
+ public static final String CONTENT_TYPE
+ = "vnd.android.cursor.dir/vnd.org.sufficientlysecure.keychain.provider.updated_keys";
+ public static final String CONTENT_ITEM_TYPE
+ = "vnd.android.cursor.item/vnd.org.sufficientlysecure.keychain.provider.updated_keys";
+ }
+
public static class UserPackets implements UserPacketsColumns, BaseColumns {
public static final String VERIFIED = "verified";
public static final Uri CONTENT_URI = BASE_CONTENT_URI_INTERNAL.buildUpon()
@@ -262,6 +280,11 @@ public class KeychainContract {
public static Uri buildUserIdsUri(Uri uri) {
return CONTENT_URI.buildUpon().appendPath(uri.getPathSegments().get(1)).appendPath(PATH_USER_IDS).build();
}
+
+ public static Uri buildLinkedIdsUri(Uri uri) {
+ return CONTENT_URI.buildUpon().appendPath(uri.getPathSegments().get(1)).appendPath(PATH_LINKED_IDS).build();
+ }
+
}
public static class ApiApps implements ApiAppsColumns, BaseColumns {
@@ -350,7 +373,14 @@ public class KeychainContract {
}
public static Uri buildCertsUri(Uri uri) {
- return CONTENT_URI.buildUpon().appendPath(uri.getPathSegments().get(1)).appendPath(PATH_CERTS).build();
+ return CONTENT_URI.buildUpon().appendPath(uri.getPathSegments().get(1))
+ .appendPath(PATH_CERTS).build();
+ }
+
+ public static Uri buildLinkedIdCertsUri(Uri uri, int rank) {
+ return CONTENT_URI.buildUpon().appendPath(uri.getPathSegments().get(1))
+ .appendPath(PATH_LINKED_IDS).appendPath(Integer.toString(rank))
+ .appendPath(PATH_CERTS).build();
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java
index 4d16d44c5..d7fb738fc 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java
@@ -34,6 +34,7 @@ import org.sufficientlysecure.keychain.provider.KeychainContract.ApiAppsColumns;
import org.sufficientlysecure.keychain.provider.KeychainContract.CertsColumns;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRingsColumns;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeysColumns;
+import org.sufficientlysecure.keychain.provider.KeychainContract.UpdatedKeysColumns;
import org.sufficientlysecure.keychain.provider.KeychainContract.UserPacketsColumns;
import org.sufficientlysecure.keychain.ui.ConsolidateDialogActivity;
import org.sufficientlysecure.keychain.util.Log;
@@ -53,7 +54,7 @@ import java.io.IOException;
*/
public class KeychainDatabase extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "openkeychain.db";
- private static final int DATABASE_VERSION = 11;
+ private static final int DATABASE_VERSION = 12;
static Boolean apgHack = false;
private Context mContext;
@@ -61,6 +62,7 @@ public class KeychainDatabase extends SQLiteOpenHelper {
String KEY_RINGS_PUBLIC = "keyrings_public";
String KEY_RINGS_SECRET = "keyrings_secret";
String KEYS = "keys";
+ String UPDATED_KEYS = "updated_keys";
String USER_PACKETS = "user_packets";
String CERTS = "certs";
String API_APPS = "api_apps";
@@ -144,6 +146,14 @@ public class KeychainDatabase extends SQLiteOpenHelper {
+ Tables.USER_PACKETS + "(" + UserPacketsColumns.MASTER_KEY_ID + ", " + UserPacketsColumns.RANK + ") ON DELETE CASCADE"
+ ")";
+ private static final String CREATE_UPDATE_KEYS =
+ "CREATE TABLE IF NOT EXISTS " + Tables.UPDATED_KEYS + " ("
+ + UpdatedKeysColumns.MASTER_KEY_ID + " INTEGER PRIMARY KEY, "
+ + UpdatedKeysColumns.LAST_UPDATED + " INTEGER, "
+ + "FOREIGN KEY(" + UpdatedKeysColumns.MASTER_KEY_ID + ") REFERENCES "
+ + Tables.KEY_RINGS_PUBLIC + "(" + KeyRingsColumns.MASTER_KEY_ID + ") ON DELETE CASCADE"
+ + ")";
+
private static final String CREATE_API_APPS =
"CREATE TABLE IF NOT EXISTS " + Tables.API_APPS + " ("
+ BaseColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
@@ -206,6 +216,7 @@ public class KeychainDatabase extends SQLiteOpenHelper {
db.execSQL(CREATE_KEYS);
db.execSQL(CREATE_USER_PACKETS);
db.execSQL(CREATE_CERTS);
+ db.execSQL(CREATE_UPDATE_KEYS);
db.execSQL(CREATE_API_APPS);
db.execSQL(CREATE_API_APPS_ACCOUNTS);
db.execSQL(CREATE_API_APPS_ALLOWED_KEYS);
@@ -278,8 +289,11 @@ public class KeychainDatabase extends SQLiteOpenHelper {
// fix problems in database, see #1402 for details
// https://github.com/open-keychain/open-keychain/issues/1402
db.execSQL("DELETE FROM api_accounts WHERE key_id BETWEEN 0 AND 3");
+ case 12:
+ db.execSQL(CREATE_UPDATE_KEYS);
if (oldVersion == 10) {
- // no consolidate if we are updating from 10, we're just here for the api_accounts fix
+ // no consolidate if we are updating from 10, we're just here for
+ // the api_accounts fix and the new update keys table
return;
}
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 3ed9b1da9..d722fa9e7 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java
@@ -31,6 +31,7 @@ import android.net.Uri;
import android.text.TextUtils;
import org.sufficientlysecure.keychain.Constants;
+import org.sufficientlysecure.keychain.pgp.WrappedUserAttribute;
import org.sufficientlysecure.keychain.provider.KeychainContract.ApiAccounts;
import org.sufficientlysecure.keychain.provider.KeychainContract.ApiAllowedKeys;
import org.sufficientlysecure.keychain.provider.KeychainContract.ApiApps;
@@ -38,6 +39,7 @@ import org.sufficientlysecure.keychain.provider.KeychainContract.Certs;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRingData;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.provider.KeychainContract.Keys;
+import org.sufficientlysecure.keychain.provider.KeychainContract.UpdatedKeys;
import org.sufficientlysecure.keychain.provider.KeychainContract.UserPackets;
import org.sufficientlysecure.keychain.provider.KeychainContract.UserPacketsColumns;
import org.sufficientlysecure.keychain.provider.KeychainDatabase.Tables;
@@ -62,6 +64,8 @@ public class KeychainProvider extends ContentProvider {
private static final int KEY_RING_SECRET = 204;
private static final int KEY_RING_CERTS = 205;
private static final int KEY_RING_CERTS_SPECIFIC = 206;
+ private static final int KEY_RING_LINKED_IDS = 207;
+ private static final int KEY_RING_LINKED_ID_CERTS = 208;
private static final int API_APPS = 301;
private static final int API_APPS_BY_PACKAGE_NAME = 302;
@@ -72,6 +76,9 @@ public class KeychainProvider extends ContentProvider {
private static final int KEY_RINGS_FIND_BY_EMAIL = 400;
private static final int KEY_RINGS_FIND_BY_SUBKEY = 401;
+ private static final int UPDATED_KEYS = 500;
+ private static final int UPDATED_KEYS_SPECIFIC = 501;
+
protected UriMatcher mUriMatcher;
/**
@@ -127,6 +134,9 @@ public class KeychainProvider extends ContentProvider {
* key_rings/_/unified
* key_rings/_/keys
* key_rings/_/user_ids
+ * key_rings/_/linked_ids
+ * key_rings/_/linked_ids/_
+ * key_rings/_/linked_ids/_/certs
* key_rings/_/public
* key_rings/_/secret
* key_rings/_/certs
@@ -143,6 +153,13 @@ public class KeychainProvider extends ContentProvider {
+ KeychainContract.PATH_USER_IDS,
KEY_RING_USER_IDS);
matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/*/"
+ + KeychainContract.PATH_LINKED_IDS,
+ KEY_RING_LINKED_IDS);
+ matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/*/"
+ + KeychainContract.PATH_LINKED_IDS + "/*/"
+ + KeychainContract.PATH_CERTS,
+ KEY_RING_LINKED_ID_CERTS);
+ matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/*/"
+ KeychainContract.PATH_PUBLIC,
KEY_RING_PUBLIC);
matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/*/"
@@ -179,6 +196,12 @@ public class KeychainProvider extends ContentProvider {
matcher.addURI(authority, KeychainContract.BASE_API_APPS + "/*/"
+ KeychainContract.PATH_ALLOWED_KEYS, API_ALLOWED_KEYS);
+ /**
+ * to access table containing last updated dates of keys
+ */
+ matcher.addURI(authority, KeychainContract.BASE_UPDATED_KEYS, UPDATED_KEYS);
+ matcher.addURI(authority, KeychainContract.BASE_UPDATED_KEYS + "/*", UPDATED_KEYS_SPECIFIC);
+
return matcher;
}
@@ -218,6 +241,11 @@ public class KeychainProvider extends ContentProvider {
case KEY_RING_SECRET:
return KeyRings.CONTENT_ITEM_TYPE;
+ case UPDATED_KEYS:
+ return UpdatedKeys.CONTENT_TYPE;
+ case UPDATED_KEYS_SPECIFIC:
+ return UpdatedKeys.CONTENT_ITEM_TYPE;
+
case API_APPS:
return ApiApps.CONTENT_TYPE;
@@ -477,7 +505,8 @@ public class KeychainProvider extends ContentProvider {
}
case KEY_RINGS_USER_IDS:
- case KEY_RING_USER_IDS: {
+ case KEY_RING_USER_IDS:
+ case KEY_RING_LINKED_IDS: {
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);
@@ -502,13 +531,15 @@ public class KeychainProvider extends ContentProvider {
groupBy = Tables.USER_PACKETS + "." + UserPackets.MASTER_KEY_ID
+ ", " + Tables.USER_PACKETS + "." + UserPackets.RANK;
- // for now, we only respect user ids here, so TYPE must be NULL
- // TODO expand with KEY_RING_USER_PACKETS query type which lifts this restriction
- qb.appendWhere(Tables.USER_PACKETS + "." + UserPackets.TYPE + " IS NULL");
+ if (match == KEY_RING_LINKED_IDS) {
+ qb.appendWhere(Tables.USER_PACKETS + "." + UserPackets.TYPE + " = "
+ + WrappedUserAttribute.UAT_URI_ATTRIBUTE);
+ } else {
+ qb.appendWhere(Tables.USER_PACKETS + "." + UserPackets.TYPE + " IS NULL");
+ }
// If we are searching for a particular keyring's ids, add where
- if (match == KEY_RING_USER_IDS) {
- // TODO remove with the thing above
+ if (match == KEY_RING_USER_IDS || match == KEY_RING_LINKED_IDS) {
qb.appendWhere(" AND ");
qb.appendWhere(Tables.USER_PACKETS + "." + UserPackets.MASTER_KEY_ID + " = ");
qb.appendWhereEscapeString(uri.getPathSegments().get(1));
@@ -559,7 +590,8 @@ public class KeychainProvider extends ContentProvider {
}
case KEY_RING_CERTS:
- case KEY_RING_CERTS_SPECIFIC: {
+ case KEY_RING_CERTS_SPECIFIC:
+ case KEY_RING_LINKED_ID_CERTS: {
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);
@@ -580,10 +612,6 @@ public class KeychainProvider extends ContentProvider {
+ " AND "
+ Tables.CERTS + "." + Certs.RANK + " = "
+ Tables.USER_PACKETS + "." + UserPackets.RANK
- // for now, we only return user ids here, so TYPE must be NULL
- // TODO at some point, we should lift this restriction
- + " AND "
- + Tables.USER_PACKETS + "." + UserPackets.TYPE + " IS NULL"
+ ") LEFT JOIN " + Tables.USER_PACKETS + " AS signer ON ("
+ Tables.CERTS + "." + Certs.KEY_ID_CERTIFIER + " = "
+ "signer." + UserPackets.MASTER_KEY_ID
@@ -603,6 +631,33 @@ public class KeychainProvider extends ContentProvider {
qb.appendWhereEscapeString(uri.getPathSegments().get(4));
}
+ if (match == KEY_RING_LINKED_ID_CERTS) {
+ qb.appendWhere(" AND " + Tables.USER_PACKETS + "."
+ + UserPackets.TYPE + " IS NOT NULL");
+
+ qb.appendWhere(" AND " + Tables.USER_PACKETS + "."
+ + UserPackets.RANK + " = ");
+ qb.appendWhereEscapeString(uri.getPathSegments().get(3));
+ } else {
+ qb.appendWhere(" AND " + Tables.USER_PACKETS + "." + UserPackets.TYPE + " IS NULL");
+ }
+
+ break;
+ }
+
+ case UPDATED_KEYS:
+ case UPDATED_KEYS_SPECIFIC: {
+ HashMap<String, String> projectionMap = new HashMap<>();
+ qb.setTables(Tables.UPDATED_KEYS);
+ projectionMap.put(UpdatedKeys.MASTER_KEY_ID, Tables.UPDATED_KEYS + "."
+ + UpdatedKeys.MASTER_KEY_ID);
+ projectionMap.put(UpdatedKeys.LAST_UPDATED, Tables.UPDATED_KEYS + "."
+ + UpdatedKeys.LAST_UPDATED);
+ qb.setProjectionMap(projectionMap);
+ if (match == UPDATED_KEYS_SPECIFIC) {
+ qb.appendWhere(UpdatedKeys.MASTER_KEY_ID + " = ");
+ qb.appendWhereEscapeString(uri.getPathSegments().get(1));
+ }
break;
}
@@ -726,6 +781,12 @@ public class KeychainProvider extends ContentProvider {
keyId = values.getAsLong(Certs.MASTER_KEY_ID);
break;
}
+ case UPDATED_KEYS: {
+ long updatedKeyId = db.replace(Tables.UPDATED_KEYS, null, values);
+ rowUri = UpdatedKeys.CONTENT_URI.buildUpon().appendPath("" + updatedKeyId)
+ .build();
+ break;
+ }
case API_APPS: {
db.insertOrThrow(Tables.API_APPS, null, values);
break;
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 0c37bfc2a..a6823d3ac 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java
@@ -32,10 +32,15 @@ import android.support.v4.util.LongSparseArray;
import org.spongycastle.bcpg.CompressionAlgorithmTags;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.operations.results.ImportKeyResult;
+import org.sufficientlysecure.keychain.pgp.WrappedUserAttribute;
+import org.sufficientlysecure.keychain.provider.KeychainContract.UserPackets;
+import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
+import org.sufficientlysecure.keychain.util.ParcelableFileCache.IteratorWithSize;
+import org.sufficientlysecure.keychain.util.Preferences;
import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing;
import org.sufficientlysecure.keychain.operations.ImportOperation;
import org.sufficientlysecure.keychain.operations.results.ConsolidateResult;
-import org.sufficientlysecure.keychain.operations.results.ImportKeyResult;
import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType;
import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog;
import org.sufficientlysecure.keychain.operations.results.SaveKeyringResult;
@@ -50,7 +55,6 @@ import org.sufficientlysecure.keychain.pgp.Progressable;
import org.sufficientlysecure.keychain.pgp.UncachedKeyRing;
import org.sufficientlysecure.keychain.pgp.UncachedPublicKey;
import org.sufficientlysecure.keychain.pgp.WrappedSignature;
-import org.sufficientlysecure.keychain.pgp.WrappedUserAttribute;
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
import org.sufficientlysecure.keychain.provider.KeychainContract.ApiAllowedKeys;
import org.sufficientlysecure.keychain.provider.KeychainContract.ApiApps;
@@ -59,14 +63,12 @@ import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRingData;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.provider.KeychainContract.Keys;
import org.sufficientlysecure.keychain.provider.KeychainContract.UserPackets;
+import org.sufficientlysecure.keychain.provider.KeychainContract.UpdatedKeys;
import org.sufficientlysecure.keychain.remote.AccountSettings;
import org.sufficientlysecure.keychain.remote.AppSettings;
-import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.util.IterableIterator;
import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.ParcelableFileCache;
-import org.sufficientlysecure.keychain.util.ParcelableFileCache.IteratorWithSize;
-import org.sufficientlysecure.keychain.util.Preferences;
import org.sufficientlysecure.keychain.util.ProgressFixedScaler;
import org.sufficientlysecure.keychain.util.ProgressScaler;
import org.sufficientlysecure.keychain.util.Utf8Util;
@@ -82,6 +84,7 @@ import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
+import java.util.concurrent.TimeUnit;
/**
* This class contains high level methods for database access. Despite its
@@ -685,6 +688,36 @@ public class ProviderHelper {
mIndent -= 1;
}
+ // before deleting key, retrieve it's last updated time
+ final int INDEX_MASTER_KEY_ID = 0;
+ final int INDEX_LAST_UPDATED = 1;
+ Cursor lastUpdatedCursor = mContentResolver.query(
+ UpdatedKeys.CONTENT_URI,
+ new String[]{
+ UpdatedKeys.MASTER_KEY_ID,
+ UpdatedKeys.LAST_UPDATED
+ },
+ UpdatedKeys.MASTER_KEY_ID + " = ?",
+ new String[]{"" + masterKeyId},
+ null
+ );
+ if (lastUpdatedCursor.moveToNext()) {
+ // there was an entry to re-insert
+ // this operation must happen after the new key is inserted
+ ContentValues lastUpdatedEntry = new ContentValues(2);
+ lastUpdatedEntry.put(UpdatedKeys.MASTER_KEY_ID,
+ lastUpdatedCursor.getLong(INDEX_MASTER_KEY_ID));
+ lastUpdatedEntry.put(UpdatedKeys.LAST_UPDATED,
+ lastUpdatedCursor.getLong(INDEX_LAST_UPDATED));
+ operations.add(
+ ContentProviderOperation
+ .newInsert(UpdatedKeys.CONTENT_URI)
+ .withValues(lastUpdatedEntry)
+ .build()
+ );
+ }
+ lastUpdatedCursor.close();
+
try {
// delete old version of this keyRing, which also deletes all keys and userIds on cascade
int deleted = mContentResolver.delete(
@@ -738,6 +771,11 @@ public class ProviderHelper {
if (type != o.type) {
return type == null ? -1 : 1;
}
+ // if one is *trusted* but the other isn't, that one comes first
+ // this overrides the primary attribute, even!
+ if ( (trustedCerts.size() == 0) != (o.trustedCerts.size() == 0) ) {
+ return trustedCerts.size() > o.trustedCerts.size() ? -1 : 1;
+ }
// if one key is primary but the other isn't, the primary one always comes first
if (isPrimary != o.isPrimary) {
return isPrimary ? -1 : 1;
@@ -845,7 +883,7 @@ public class ProviderHelper {
}
public SaveKeyringResult savePublicKeyRing(UncachedKeyRing keyRing) {
- return savePublicKeyRing(keyRing, new ProgressScaler());
+ return savePublicKeyRing(keyRing, new ProgressScaler(), null);
}
/**
@@ -854,7 +892,7 @@ public class ProviderHelper {
* This is a high level method, which takes care of merging all new information into the old and
* keep public and secret keyrings in sync.
*/
- public SaveKeyringResult savePublicKeyRing(UncachedKeyRing publicRing, Progressable progress) {
+ public SaveKeyringResult savePublicKeyRing(UncachedKeyRing publicRing, Progressable progress, String expectedFingerprint) {
try {
long masterKeyId = publicRing.getMasterKeyId();
@@ -927,6 +965,17 @@ public class ProviderHelper {
canSecretRing = null;
}
+
+ // If we have an expected fingerprint, make sure it matches
+ if (expectedFingerprint != null) {
+ if (!canPublicRing.containsSubkey(expectedFingerprint)) {
+ log(LogType.MSG_IP_FINGERPRINT_ERROR);
+ return new SaveKeyringResult(SaveKeyringResult.RESULT_ERROR, mLog, null);
+ } else {
+ log(LogType.MSG_IP_FINGERPRINT_OK);
+ }
+ }
+
int result = saveCanonicalizedPublicKeyRing(canPublicRing, progress, canSecretRing != null);
// Save the saved keyring (if any)
@@ -1239,6 +1288,28 @@ public class ProviderHelper {
}
// 2. wipe database (IT'S DANGEROUS)
+
+ // first, backup our list of updated key times
+ ArrayList<ContentValues> updatedKeysValues = new ArrayList<>();
+ final int INDEX_MASTER_KEY_ID = 0;
+ final int INDEX_LAST_UPDATED = 1;
+ Cursor lastUpdatedCursor = mContentResolver.query(
+ UpdatedKeys.CONTENT_URI,
+ new String[]{
+ UpdatedKeys.MASTER_KEY_ID,
+ UpdatedKeys.LAST_UPDATED
+ },
+ null, null, null);
+ while (lastUpdatedCursor.moveToNext()) {
+ ContentValues values = new ContentValues();
+ values.put(UpdatedKeys.MASTER_KEY_ID,
+ lastUpdatedCursor.getLong(INDEX_MASTER_KEY_ID));
+ values.put(UpdatedKeys.LAST_UPDATED,
+ lastUpdatedCursor.getLong(INDEX_LAST_UPDATED));
+ updatedKeysValues.add(values);
+ }
+ lastUpdatedCursor.close();
+
log.add(LogType.MSG_CON_DB_CLEAR, indent);
mContentResolver.delete(KeyRings.buildUnifiedKeyRingsUri(), null, null);
@@ -1288,6 +1359,10 @@ public class ProviderHelper {
new ProgressFixedScaler(progress, 25, 99, 100, R.string.progress_con_reimport))
.serialKeyRingImport(itPublics, numPublics, null, null);
log.add(result, indent);
+ // re-insert our backed up list of updated key times
+ // TODO: can this cause issues in case a public key re-import failed?
+ mContentResolver.bulkInsert(UpdatedKeys.CONTENT_URI,
+ updatedKeysValues.toArray(new ContentValues[updatedKeysValues.size()]));
} else {
log.add(LogType.MSG_CON_REIMPORT_PUBLIC_SKIP, indent);
}
@@ -1397,6 +1472,14 @@ public class ProviderHelper {
return getKeyRingAsArmoredString(data);
}
+ public Uri renewKeyLastUpdatedTime(long masterKeyId, long time, TimeUnit timeUnit) {
+ ContentValues values = new ContentValues();
+ values.put(UpdatedKeys.MASTER_KEY_ID, masterKeyId);
+ values.put(UpdatedKeys.LAST_UPDATED, timeUnit.toSeconds(time));
+
+ return mContentResolver.insert(UpdatedKeys.CONTENT_URI, values);
+ }
+
public ArrayList<String> getRegisteredApiApps() {
Cursor cursor = mContentResolver.query(ApiApps.CONTENT_URI, null, null, null, null);
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 ea016c657..57dd068ef 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java
@@ -25,6 +25,7 @@ import android.net.Uri;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
import android.os.Parcelable;
+import android.support.annotation.Nullable;
import android.text.TextUtils;
import org.openintents.openpgp.IOpenPgpService;
@@ -38,7 +39,7 @@ import org.sufficientlysecure.keychain.operations.results.DecryptVerifyResult;
import org.sufficientlysecure.keychain.operations.results.OperationResult.LogEntryParcel;
import org.sufficientlysecure.keychain.operations.results.PgpSignEncryptResult;
import org.sufficientlysecure.keychain.pgp.PgpSecurityConstants;
-import org.sufficientlysecure.keychain.pgp.PgpDecryptVerify;
+import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyOperation;
import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyInputParcel;
import org.sufficientlysecure.keychain.pgp.PgpSignEncryptInputParcel;
import org.sufficientlysecure.keychain.pgp.PgpSignEncryptOperation;
@@ -65,8 +66,10 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Date;
import java.util.HashSet;
+import java.util.List;
public class OpenPgpService extends RemoteService {
@@ -533,7 +536,7 @@ public class OpenPgpService extends RemoteService {
byte[] detachedSignature = data.getByteArrayExtra(OpenPgpApi.EXTRA_DETACHED_SIGNATURE);
- PgpDecryptVerify op = new PgpDecryptVerify(this, mProviderHelper, null);
+ PgpDecryptVerifyOperation op = new PgpDecryptVerifyOperation(this, mProviderHelper, null);
long inputLength = inputStream.available();
InputData inputData = new InputData(inputStream, inputLength);
@@ -715,28 +718,40 @@ public class OpenPgpService extends RemoteService {
}
private Intent getSignKeyIdImpl(Intent data) {
- String preferredUserId = data.getStringExtra(OpenPgpApi.EXTRA_USER_ID);
+ // if data already contains EXTRA_SIGN_KEY_ID, it has been executed again
+ // after user interaction. Then, we just need to return the long again!
+ if (data.hasExtra(OpenPgpApi.EXTRA_SIGN_KEY_ID)) {
+ long signKeyId = data.getLongExtra(OpenPgpApi.EXTRA_SIGN_KEY_ID,
+ Constants.key.none);
- Intent intent = new Intent(getBaseContext(), SelectSignKeyIdActivity.class);
- String currentPkg = getCurrentCallingPackage();
- intent.setData(KeychainContract.ApiApps.buildByPackageNameUri(currentPkg));
- intent.putExtra(SelectSignKeyIdActivity.EXTRA_USER_ID, preferredUserId);
- intent.putExtra(SelectSignKeyIdActivity.EXTRA_DATA, data);
+ Intent result = new Intent();
+ result.putExtra(OpenPgpApi.EXTRA_SIGN_KEY_ID, signKeyId);
+ result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_SUCCESS);
+ return result;
+ } else {
+ String preferredUserId = data.getStringExtra(OpenPgpApi.EXTRA_USER_ID);
- PendingIntent pi = PendingIntent.getActivity(getBaseContext(), 0,
- intent,
- PendingIntent.FLAG_CANCEL_CURRENT);
+ Intent intent = new Intent(getBaseContext(), SelectSignKeyIdActivity.class);
+ String currentPkg = getCurrentCallingPackage();
+ intent.setData(KeychainContract.ApiApps.buildByPackageNameUri(currentPkg));
+ intent.putExtra(SelectSignKeyIdActivity.EXTRA_USER_ID, preferredUserId);
+ intent.putExtra(SelectSignKeyIdActivity.EXTRA_DATA, data);
- // return PendingIntent to be executed by client
- Intent result = new Intent();
- result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED);
- result.putExtra(OpenPgpApi.RESULT_INTENT, pi);
+ PendingIntent pi = PendingIntent.getActivity(getBaseContext(), 0,
+ intent,
+ PendingIntent.FLAG_CANCEL_CURRENT);
+
+ // return PendingIntent to be executed by client
+ Intent result = new Intent();
+ result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED);
+ result.putExtra(OpenPgpApi.RESULT_INTENT, pi);
- return result;
+ return result;
+ }
}
private Intent getKeyIdsImpl(Intent data) {
- // if data already contains key ids extra GET_KEY_IDS has been executed again
+ // if data already contains EXTRA_KEY_IDS, it has been executed again
// after user interaction. Then, we just need to return the array again!
if (data.hasExtra(OpenPgpApi.EXTRA_KEY_IDS)) {
long[] keyIdsArray = data.getLongArrayExtra(OpenPgpApi.EXTRA_KEY_IDS);
@@ -800,19 +815,14 @@ 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, 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) != 6
- && data.getIntExtra(OpenPgpApi.EXTRA_API_VERSION, -1) != 7
- && data.getIntExtra(OpenPgpApi.EXTRA_API_VERSION, -1) != 8) {
+ // History of versions in openpgp-api's CHANGELOG.md
+ List<Integer> supportedVersions = Arrays.asList(3, 4, 5, 6, 7, 8, 9);
+ if (!supportedVersions.contains(data.getIntExtra(OpenPgpApi.EXTRA_API_VERSION, -1))) {
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-8");
+ + "supported API versions: " + supportedVersions.toString());
result.putExtra(OpenPgpApi.RESULT_ERROR, error);
result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR);
return result;
@@ -830,67 +840,8 @@ public class OpenPgpService extends RemoteService {
private final IOpenPgpService.Stub mBinder = new IOpenPgpService.Stub() {
@Override
public Intent execute(Intent data, ParcelFileDescriptor input, ParcelFileDescriptor output) {
- try {
- Intent errorResult = checkRequirements(data);
- if (errorResult != null) {
- return errorResult;
- }
-
- String action = data.getAction();
- switch (action) {
- case OpenPgpApi.ACTION_CLEARTEXT_SIGN: {
- return signImpl(data, input, output, true);
- }
- case OpenPgpApi.ACTION_SIGN: {
- // 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, true);
- }
- case OpenPgpApi.ACTION_DETACHED_SIGN: {
- return signImpl(data, input, output, false);
- }
- case OpenPgpApi.ACTION_ENCRYPT: {
- return encryptAndSignImpl(data, input, output, false);
- }
- case OpenPgpApi.ACTION_SIGN_AND_ENCRYPT: {
- return encryptAndSignImpl(data, input, output, true);
- }
- case OpenPgpApi.ACTION_DECRYPT_VERIFY: {
- return decryptAndVerifyImpl(data, input, output, false);
- }
- case OpenPgpApi.ACTION_DECRYPT_METADATA: {
- return decryptAndVerifyImpl(data, input, output, true);
- }
- case OpenPgpApi.ACTION_GET_SIGN_KEY_ID: {
- return getSignKeyIdImpl(data);
- }
- case OpenPgpApi.ACTION_GET_KEY_IDS: {
- return getKeyIdsImpl(data);
- }
- case OpenPgpApi.ACTION_GET_KEY: {
- return getKeyImpl(data);
- }
- default: {
- return null;
- }
- }
- } finally {
- // always close input and output file descriptors even in error cases
- if (input != null) {
- try {
- input.close();
- } catch (IOException e) {
- Log.e(Constants.TAG, "IOException when closing input ParcelFileDescriptor", e);
- }
- }
- if (output != null) {
- try {
- output.close();
- } catch (IOException e) {
- Log.e(Constants.TAG, "IOException when closing output ParcelFileDescriptor", e);
- }
- }
- }
+ Log.w(Constants.TAG, "You are using a deprecated service which may lead to truncated data on return, please use IOpenPgpService2!");
+ return executeInternal(data, input, output);
}
};
@@ -900,4 +851,68 @@ public class OpenPgpService extends RemoteService {
return mBinder;
}
+
+ protected Intent executeInternal(Intent data, ParcelFileDescriptor input, ParcelFileDescriptor output) {
+ try {
+ Intent errorResult = checkRequirements(data);
+ if (errorResult != null) {
+ return errorResult;
+ }
+
+ String action = data.getAction();
+ switch (action) {
+ case OpenPgpApi.ACTION_CLEARTEXT_SIGN: {
+ return signImpl(data, input, output, true);
+ }
+ case OpenPgpApi.ACTION_SIGN: {
+ // 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, true);
+ }
+ case OpenPgpApi.ACTION_DETACHED_SIGN: {
+ return signImpl(data, input, output, false);
+ }
+ case OpenPgpApi.ACTION_ENCRYPT: {
+ return encryptAndSignImpl(data, input, output, false);
+ }
+ case OpenPgpApi.ACTION_SIGN_AND_ENCRYPT: {
+ return encryptAndSignImpl(data, input, output, true);
+ }
+ case OpenPgpApi.ACTION_DECRYPT_VERIFY: {
+ return decryptAndVerifyImpl(data, input, output, false);
+ }
+ case OpenPgpApi.ACTION_DECRYPT_METADATA: {
+ return decryptAndVerifyImpl(data, input, output, true);
+ }
+ case OpenPgpApi.ACTION_GET_SIGN_KEY_ID: {
+ return getSignKeyIdImpl(data);
+ }
+ case OpenPgpApi.ACTION_GET_KEY_IDS: {
+ return getKeyIdsImpl(data);
+ }
+ case OpenPgpApi.ACTION_GET_KEY: {
+ return getKeyImpl(data);
+ }
+ default: {
+ return null;
+ }
+ }
+ } finally {
+ // always close input and output file descriptors even in error cases
+ if (input != null) {
+ try {
+ input.close();
+ } catch (IOException e) {
+ Log.e(Constants.TAG, "IOException when closing input ParcelFileDescriptor", e);
+ }
+ }
+ if (output != null) {
+ try {
+ output.close();
+ } catch (IOException e) {
+ Log.e(Constants.TAG, "IOException when closing output ParcelFileDescriptor", e);
+ }
+ }
+ }
+ }
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService2.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService2.java
new file mode 100644
index 000000000..110302e55
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService2.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2015 Dominik Schürmann <dominik@dominikschuermann.de>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.sufficientlysecure.keychain.remote;
+
+import android.content.Intent;
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.ParcelFileDescriptor;
+
+import org.openintents.openpgp.IOpenPgpService2;
+import org.sufficientlysecure.keychain.Constants;
+import org.sufficientlysecure.keychain.util.Log;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+public class OpenPgpService2 extends OpenPgpService {
+
+ private Map<Long, ParcelFileDescriptor> mOutputPipeMap = new HashMap<Long, ParcelFileDescriptor>();
+
+ private long createKey(int id) {
+ int callingPid = Binder.getCallingPid();
+ return ((long) callingPid << 32) | ((long) id & 0xFFFFFFFL);
+ }
+
+ private final IOpenPgpService2.Stub mBinder = new IOpenPgpService2.Stub() {
+
+ @Override
+ public ParcelFileDescriptor createOutputPipe(int outputPipeId) {
+ try {
+ ParcelFileDescriptor[] pipe = ParcelFileDescriptor.createPipe();
+ mOutputPipeMap.put(createKey(outputPipeId), pipe[1]);
+ return pipe[0];
+ } catch (IOException e) {
+ Log.e(Constants.TAG, "IOException in OpenPgpService2", e);
+ return null;
+ }
+
+ }
+
+ @Override
+ public Intent execute(Intent data, ParcelFileDescriptor input, int outputPipeId) {
+ long key = createKey(outputPipeId);
+ ParcelFileDescriptor output = mOutputPipeMap.get(key);
+ mOutputPipeMap.remove(key);
+ return executeInternal(data, input, output);
+ }
+
+ };
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return mBinder;
+ }
+
+}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AppsListFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AppsListFragment.java
index 2deb33a67..a1451fb09 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AppsListFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AppsListFragment.java
@@ -243,7 +243,7 @@ public class AppsListFragment extends ListFragment implements
null,
isInstalled(packageName),
1, // registered!
- R.drawable.ic_launcher // icon is retrieved later
+ R.mipmap.ic_launcher // icon is retrieved later
});
break;
}
@@ -265,7 +265,7 @@ public class AppsListFragment extends ListFragment implements
name,
isInstalled(packageName),
1, // registered!
- R.drawable.ic_launcher // icon is retrieved later
+ R.mipmap.ic_launcher // icon is retrieved later
});
break;
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/SelectSignKeyIdActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/SelectSignKeyIdActivity.java
index cb9f46f7f..bed49a6f6 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/SelectSignKeyIdActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/SelectSignKeyIdActivity.java
@@ -40,14 +40,9 @@ public class SelectSignKeyIdActivity extends BaseActivity {
private static final int REQUEST_CODE_CREATE_KEY = 0x00008884;
- private Uri mAppUri;
private String mPreferredUserId;
private Intent mData;
- private SelectSignKeyIdListFragment mListFragment;
- private TextView mActionCreateKey;
- private TextView mNone;
-
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -62,15 +57,15 @@ public class SelectSignKeyIdActivity extends BaseActivity {
}
});
- mActionCreateKey = (TextView) findViewById(R.id.api_select_sign_key_create_key);
- mActionCreateKey.setOnClickListener(new View.OnClickListener() {
+ TextView createKeyButton = (TextView) findViewById(R.id.api_select_sign_key_create_key);
+ createKeyButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
createKey(mPreferredUserId);
}
});
- mNone = (TextView) findViewById(R.id.api_select_sign_key_none);
- mNone.setOnClickListener(new View.OnClickListener() {
+ TextView noneButton = (TextView) findViewById(R.id.api_select_sign_key_none);
+ noneButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 0 is "none"
@@ -82,16 +77,16 @@ public class SelectSignKeyIdActivity extends BaseActivity {
});
Intent intent = getIntent();
- mAppUri = intent.getData();
+ Uri appUri = intent.getData();
mPreferredUserId = intent.getStringExtra(EXTRA_USER_ID);
mData = intent.getParcelableExtra(EXTRA_DATA);
- if (mAppUri == null) {
+ if (appUri == null) {
Log.e(Constants.TAG, "Intent data missing. Should be Uri of app!");
finish();
return;
} else {
- Log.d(Constants.TAG, "uri: " + mAppUri);
- startListFragments(savedInstanceState, mAppUri, mData);
+ Log.d(Constants.TAG, "uri: " + appUri);
+ startListFragments(savedInstanceState, appUri, mData);
}
}
@@ -113,11 +108,11 @@ public class SelectSignKeyIdActivity extends BaseActivity {
}
// Create an instance of the fragments
- mListFragment = SelectSignKeyIdListFragment.newInstance(dataUri, data);
+ SelectSignKeyIdListFragment listFragment = SelectSignKeyIdListFragment.newInstance(dataUri, data);
// Add the fragment to the 'fragment_container' FrameLayout
// NOTE: We use commitAllowingStateLoss() to prevent weird crashes!
getSupportFragmentManager().beginTransaction()
- .replace(R.id.api_select_sign_key_list_fragment, mListFragment)
+ .replace(R.id.api_select_sign_key_list_fragment, listFragment)
.commitAllowingStateLoss();
// do it immediately!
getSupportFragmentManager().executePendingTransactions();
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 e76dcfb49..3cdbca633 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/CertifyActionsParcel.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/CertifyActionsParcel.java
@@ -23,6 +23,9 @@ import android.os.Parcelable;
import java.io.Serializable;
import java.util.ArrayList;
+import java.util.List;
+import java.util.Date;
+import java.util.Map;
import org.sufficientlysecure.keychain.pgp.WrappedUserAttribute;
import org.sufficientlysecure.keychain.util.ParcelableProxy;
@@ -86,17 +89,10 @@ public class CertifyActionsParcel implements Parcelable {
final public ArrayList<String> mUserIds;
final public ArrayList<WrappedUserAttribute> mUserAttributes;
- public CertifyAction(long masterKeyId, ArrayList<String> userIds) {
+ public CertifyAction(long masterKeyId, List<String> userIds, List<WrappedUserAttribute> attributes) {
mMasterKeyId = masterKeyId;
- mUserIds = userIds;
- mUserAttributes = null;
- }
-
- public CertifyAction(long masterKeyId, ArrayList<String> userIds,
- ArrayList<WrappedUserAttribute> attributes) {
- mMasterKeyId = masterKeyId;
- mUserIds = userIds;
- mUserAttributes = attributes;
+ mUserIds = userIds == null ? null : new ArrayList<>(userIds);
+ mUserAttributes = attributes == null ? null : new ArrayList<>(attributes);
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ContactSyncAdapterService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ContactSyncAdapterService.java
index 7688b9252..b36d23775 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ContactSyncAdapterService.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ContactSyncAdapterService.java
@@ -45,7 +45,7 @@ public class ContactSyncAdapterService extends Service {
@Override
public void onPerformSync(Account account, Bundle extras, String authority, ContentProviderClient provider,
final SyncResult syncResult) {
- Log.d(Constants.TAG, "Performing a sync!");
+ Log.d(Constants.TAG, "Performing a contact sync!");
// TODO: Import is currently disabled for 2.8, until we implement proper origin management
// importDone.set(false);
// KeychainApplication.setupAccountAsNeeded(ContactSyncAdapterService.this);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainService.java
index ce4381140..d2128cd77 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainService.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainService.java
@@ -41,7 +41,7 @@ import org.sufficientlysecure.keychain.operations.PromoteKeyOperation;
import org.sufficientlysecure.keychain.operations.RevokeOperation;
import org.sufficientlysecure.keychain.operations.SignEncryptOperation;
import org.sufficientlysecure.keychain.operations.results.OperationResult;
-import org.sufficientlysecure.keychain.pgp.PgpDecryptVerify;
+import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyOperation;
import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyInputParcel;
import org.sufficientlysecure.keychain.pgp.Progressable;
import org.sufficientlysecure.keychain.pgp.SignEncryptParcel;
@@ -112,7 +112,7 @@ public class KeychainService extends Service implements Progressable {
op = new SignEncryptOperation(outerThis, new ProviderHelper(outerThis),
outerThis, mActionCanceled);
} else if (inputParcel instanceof PgpDecryptVerifyInputParcel) {
- op = new PgpDecryptVerify(outerThis, new ProviderHelper(outerThis), outerThis);
+ op = new PgpDecryptVerifyOperation(outerThis, new ProviderHelper(outerThis), outerThis);
} else if (inputParcel instanceof SaveKeyringParcel) {
op = new EditKeyOperation(outerThis, new ProviderHelper(outerThis), outerThis,
mActionCanceled);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeyserverSyncAdapterService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeyserverSyncAdapterService.java
new file mode 100644
index 000000000..8aebae7aa
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeyserverSyncAdapterService.java
@@ -0,0 +1,516 @@
+package org.sufficientlysecure.keychain.service;
+
+import android.accounts.Account;
+import android.accounts.AccountManager;
+import android.app.AlarmManager;
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.app.Service;
+import android.content.AbstractThreadedSyncAdapter;
+import android.content.ContentProviderClient;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SyncResult;
+import android.database.Cursor;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.drawable.Drawable;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.Messenger;
+import android.os.PowerManager;
+import android.os.SystemClock;
+import android.support.v4.app.NotificationCompat;
+import android.widget.Toast;
+
+import org.sufficientlysecure.keychain.Constants;
+import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing;
+import org.sufficientlysecure.keychain.operations.ImportOperation;
+import org.sufficientlysecure.keychain.operations.results.ImportKeyResult;
+import org.sufficientlysecure.keychain.operations.results.OperationResult;
+import org.sufficientlysecure.keychain.provider.KeychainContract;
+import org.sufficientlysecure.keychain.provider.ProviderHelper;
+import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
+import org.sufficientlysecure.keychain.ui.OrbotRequiredDialogActivity;
+import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
+import org.sufficientlysecure.keychain.util.Log;
+import org.sufficientlysecure.keychain.util.ParcelableProxy;
+import org.sufficientlysecure.keychain.util.Preferences;
+import org.sufficientlysecure.keychain.util.orbot.OrbotHelper;
+
+import java.util.ArrayList;
+import java.util.GregorianCalendar;
+import java.util.Random;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+public class KeyserverSyncAdapterService extends Service {
+
+ // how often a sync should be initiated, in s
+ public static final long SYNC_INTERVAL =
+ Constants.DEBUG_KEYSERVER_SYNC
+ ? TimeUnit.MINUTES.toSeconds(2) : TimeUnit.DAYS.toSeconds(3);
+ // time since last update after which a key should be updated again, in s
+ public static final long KEY_UPDATE_LIMIT =
+ Constants.DEBUG_KEYSERVER_SYNC ? 1 : TimeUnit.DAYS.toSeconds(7);
+ // time by which a sync is postponed in case of a
+ public static final long SYNC_POSTPONE_TIME =
+ Constants.DEBUG_KEYSERVER_SYNC ? 30 * 1000 : TimeUnit.MINUTES.toMillis(5);
+ // Time taken by Orbot before a new circuit is created
+ public static final int ORBOT_CIRCUIT_TIMEOUT = (int) TimeUnit.MINUTES.toMillis(10);
+
+
+ private static final String ACTION_IGNORE_TOR = "ignore_tor";
+ private static final String ACTION_UPDATE_ALL = "update_all";
+ private static final String ACTION_SYNC_NOW = "sync_now";
+ private static final String ACTION_DISMISS_NOTIFICATION = "cancel_sync";
+ private static final String ACTION_START_ORBOT = "start_orbot";
+ private static final String ACTION_CANCEL = "cancel";
+
+ private AtomicBoolean mCancelled = new AtomicBoolean(false);
+
+ @Override
+ public int onStartCommand(final Intent intent, int flags, final int startId) {
+ switch (intent.getAction()) {
+ case ACTION_CANCEL: {
+ mCancelled.set(true);
+ break;
+ }
+ // the reason for the separation betweyeen SYNC_NOW and UPDATE_ALL is so that starting
+ // the sync directly from the notification is possible while the screen is on with
+ // UPDATE_ALL, but a postponed sync is only started if screen is off
+ case ACTION_SYNC_NOW: {
+ // this checks for screen on/off before sync, and postpones the sync if on
+ ContentResolver.requestSync(
+ new Account(Constants.ACCOUNT_NAME, Constants.ACCOUNT_TYPE),
+ Constants.PROVIDER_AUTHORITY,
+ new Bundle()
+ );
+ break;
+ }
+ case ACTION_UPDATE_ALL: {
+ // does not check for screen on/off
+ asyncKeyUpdate(this, new CryptoInputParcel());
+ break;
+ }
+ case ACTION_IGNORE_TOR: {
+ NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
+ manager.cancel(Constants.Notification.KEYSERVER_SYNC_FAIL_ORBOT);
+ asyncKeyUpdate(this, new CryptoInputParcel(ParcelableProxy.getForNoProxy()));
+ break;
+ }
+ case ACTION_START_ORBOT: {
+ NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
+ manager.cancel(Constants.Notification.KEYSERVER_SYNC_FAIL_ORBOT);
+ Intent startOrbot = new Intent(this, OrbotRequiredDialogActivity.class);
+ startOrbot.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ startOrbot.putExtra(OrbotRequiredDialogActivity.EXTRA_START_ORBOT, true);
+ Messenger messenger = new Messenger(
+ new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case OrbotRequiredDialogActivity.MESSAGE_ORBOT_STARTED: {
+ asyncKeyUpdate(KeyserverSyncAdapterService.this,
+ new CryptoInputParcel());
+ break;
+ }
+ case OrbotRequiredDialogActivity.MESSAGE_ORBOT_IGNORE: {
+ asyncKeyUpdate(KeyserverSyncAdapterService.this,
+ new CryptoInputParcel(
+ ParcelableProxy.getForNoProxy()));
+ break;
+ }
+ case OrbotRequiredDialogActivity.MESSAGE_DIALOG_CANCEL: {
+ // just stop service
+ stopSelf();
+ break;
+ }
+ }
+ }
+ }
+ );
+ startOrbot.putExtra(OrbotRequiredDialogActivity.EXTRA_MESSENGER, messenger);
+ startActivity(startOrbot);
+ break;
+ }
+ case ACTION_DISMISS_NOTIFICATION: {
+ NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
+ manager.cancel(Constants.Notification.KEYSERVER_SYNC_FAIL_ORBOT);
+ stopSelf(startId);
+ break;
+ }
+ }
+ return START_NOT_STICKY;
+ }
+
+ private class KeyserverSyncAdapter extends AbstractThreadedSyncAdapter {
+
+ public KeyserverSyncAdapter() {
+ super(KeyserverSyncAdapterService.this, true);
+ }
+
+ @Override
+ public void onPerformSync(Account account, Bundle extras, String authority,
+ ContentProviderClient provider, SyncResult syncResult) {
+ Log.d(Constants.TAG, "Performing a keyserver sync!");
+
+ PowerManager pm = (PowerManager) KeyserverSyncAdapterService.this
+ .getSystemService(Context.POWER_SERVICE);
+ @SuppressWarnings("deprecation") // our min is API 15, deprecated only in 20
+ boolean isScreenOn = pm.isScreenOn();
+
+ if (!isScreenOn) {
+ Intent serviceIntent = new Intent(KeyserverSyncAdapterService.this,
+ KeyserverSyncAdapterService.class);
+ serviceIntent.setAction(ACTION_UPDATE_ALL);
+ startService(serviceIntent);
+ } else {
+ postponeSync();
+ }
+ }
+
+ @Override
+ public void onSyncCanceled() {
+ super.onSyncCanceled();
+ cancelUpdates(KeyserverSyncAdapterService.this);
+ }
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return new KeyserverSyncAdapter().getSyncAdapterBinder();
+ }
+
+ private void handleUpdateResult(ImportKeyResult result) {
+ if (result.isPending()) {
+ // result is pending due to Orbot not being started
+ // try to start it silently, if disabled show notifications
+ new OrbotHelper.SilentStartManager() {
+ @Override
+ protected void onOrbotStarted() {
+ // retry the update
+ asyncKeyUpdate(KeyserverSyncAdapterService.this,
+ new CryptoInputParcel());
+ }
+
+ @Override
+ protected void onSilentStartDisabled() {
+ // show notification
+ NotificationManager manager =
+ (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
+ manager.notify(Constants.Notification.KEYSERVER_SYNC_FAIL_ORBOT,
+ getOrbotNoification(KeyserverSyncAdapterService.this));
+ }
+ }.startOrbotAndListen(this, false);
+ } else if (isUpdateCancelled()) {
+ Log.d(Constants.TAG, "Keyserver sync cancelled, postponing by" + SYNC_POSTPONE_TIME
+ + "ms");
+ postponeSync();
+ } else {
+ Log.d(Constants.TAG, "Keyserver sync completed: Updated: " + result.mUpdatedKeys
+ + " Failed: " + result.mBadKeys);
+ stopSelf();
+ }
+ }
+
+ private void postponeSync() {
+ AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
+ Intent serviceIntent = new Intent(this, KeyserverSyncAdapterService.class);
+ serviceIntent.setAction(ACTION_SYNC_NOW);
+ PendingIntent pi = PendingIntent.getService(this, 0, serviceIntent,
+ PendingIntent.FLAG_UPDATE_CURRENT);
+ alarmManager.set(
+ AlarmManager.ELAPSED_REALTIME_WAKEUP,
+ SystemClock.elapsedRealtime() + SYNC_POSTPONE_TIME,
+ pi
+ );
+ }
+
+ private void asyncKeyUpdate(final Context context,
+ final CryptoInputParcel cryptoInputParcel) {
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ ImportKeyResult result = updateKeysFromKeyserver(context, cryptoInputParcel);
+ handleUpdateResult(result);
+ }
+ }).start();
+ }
+
+ private synchronized ImportKeyResult updateKeysFromKeyserver(final Context context,
+ final CryptoInputParcel cryptoInputParcel) {
+ mCancelled.set(false);
+
+ ArrayList<ParcelableKeyRing> keyList = getKeysToUpdate(context);
+
+ if (isUpdateCancelled()) { // if we've already been cancelled
+ return new ImportKeyResult(OperationResult.RESULT_CANCELLED,
+ new OperationResult.OperationLog());
+ }
+
+ if (cryptoInputParcel.getParcelableProxy() == null) {
+ // no explicit proxy, retrieve from preferences. Check if we should do a staggered sync
+ if (Preferences.getPreferences(context).getProxyPrefs().torEnabled) {
+ return staggeredUpdate(context, keyList, cryptoInputParcel);
+ } else {
+ return directUpdate(context, keyList, cryptoInputParcel);
+ }
+ } else {
+ return directUpdate(context, keyList, cryptoInputParcel);
+ }
+ }
+
+ private ImportKeyResult directUpdate(Context context, ArrayList<ParcelableKeyRing> keyList,
+ CryptoInputParcel cryptoInputParcel) {
+ Log.d(Constants.TAG, "Starting normal update");
+ ImportOperation importOp = new ImportOperation(context, new ProviderHelper(context), null);
+ return importOp.execute(
+ new ImportKeyringParcel(keyList,
+ Preferences.getPreferences(context).getPreferredKeyserver()),
+ cryptoInputParcel
+ );
+ }
+
+
+ /**
+ * will perform a staggered update of user's keys using delays to ensure new Tor circuits, as
+ * performed by parcimonie. Relevant issue and method at:
+ * https://github.com/open-keychain/open-keychain/issues/1337
+ *
+ * @return result of the sync
+ */
+ private ImportKeyResult staggeredUpdate(Context context, ArrayList<ParcelableKeyRing> keyList,
+ CryptoInputParcel cryptoInputParcel) {
+ Log.d(Constants.TAG, "Starting staggered update");
+ // final int WEEK_IN_SECONDS = (int) TimeUnit.DAYS.toSeconds(7);
+ final int WEEK_IN_SECONDS = 0;
+ ImportOperation.KeyImportAccumulator accumulator
+ = new ImportOperation.KeyImportAccumulator(keyList.size(), null);
+ for (ParcelableKeyRing keyRing : keyList) {
+ int waitTime;
+ int staggeredTime = new Random().nextInt(1 + 2 * (WEEK_IN_SECONDS / keyList.size()));
+ if (staggeredTime >= ORBOT_CIRCUIT_TIMEOUT) {
+ waitTime = staggeredTime;
+ } else {
+ waitTime = ORBOT_CIRCUIT_TIMEOUT + new Random().nextInt(ORBOT_CIRCUIT_TIMEOUT);
+ }
+ Log.d(Constants.TAG, "Updating key with fingerprint " + keyRing.mExpectedFingerprint +
+ " with a wait time of " + waitTime + "s");
+ try {
+ Thread.sleep(waitTime * 1000);
+ } catch (InterruptedException e) {
+ Log.e(Constants.TAG, "Exception during sleep between key updates", e);
+ // skip this one
+ continue;
+ }
+ ArrayList<ParcelableKeyRing> keyWrapper = new ArrayList<>();
+ keyWrapper.add(keyRing);
+ if (isUpdateCancelled()) {
+ return new ImportKeyResult(ImportKeyResult.RESULT_CANCELLED,
+ new OperationResult.OperationLog());
+ }
+ ImportKeyResult result =
+ new ImportOperation(context, new ProviderHelper(context), null, mCancelled)
+ .execute(
+ new ImportKeyringParcel(
+ keyWrapper,
+ Preferences.getPreferences(context)
+ .getPreferredKeyserver()
+ ),
+ cryptoInputParcel
+ );
+ if (result.isPending()) {
+ return result;
+ }
+ accumulator.accumulateKeyImport(result);
+ }
+ return accumulator.getConsolidatedResult();
+ }
+
+ /**
+ * 1. Get keys which have been updated recently and therefore do not need to
+ * be updated now
+ * 2. Get list of all keys and filter out ones that don't need to be updated
+ * 3. Return keys to be updated
+ *
+ * @return list of keys that require update
+ */
+ private ArrayList<ParcelableKeyRing> getKeysToUpdate(Context context) {
+
+ // 1. Get keys which have been updated recently and don't need to updated now
+ final int INDEX_UPDATED_KEYS_MASTER_KEY_ID = 0;
+ final int INDEX_LAST_UPDATED = 1;
+
+ // all time in seconds not milliseconds
+ final long CURRENT_TIME = GregorianCalendar.getInstance().getTimeInMillis() / 1000;
+ Cursor updatedKeysCursor = context.getContentResolver().query(
+ KeychainContract.UpdatedKeys.CONTENT_URI,
+ new String[]{
+ KeychainContract.UpdatedKeys.MASTER_KEY_ID,
+ KeychainContract.UpdatedKeys.LAST_UPDATED
+ },
+ "? - " + KeychainContract.UpdatedKeys.LAST_UPDATED + " < " + KEY_UPDATE_LIMIT,
+ new String[]{"" + CURRENT_TIME},
+ null
+ );
+
+ ArrayList<Long> ignoreMasterKeyIds = new ArrayList<>();
+ while (updatedKeysCursor.moveToNext()) {
+ long masterKeyId = updatedKeysCursor.getLong(INDEX_UPDATED_KEYS_MASTER_KEY_ID);
+ Log.d(Constants.TAG, "Keyserver sync: Ignoring {" + masterKeyId + "} last updated at {"
+ + updatedKeysCursor.getLong(INDEX_LAST_UPDATED) + "}s");
+ ignoreMasterKeyIds.add(masterKeyId);
+ }
+ updatedKeysCursor.close();
+
+ // 2. Make a list of public keys which should be updated
+ final int INDEX_MASTER_KEY_ID = 0;
+ final int INDEX_FINGERPRINT = 1;
+ Cursor keyCursor = context.getContentResolver().query(
+ KeychainContract.KeyRings.buildUnifiedKeyRingsUri(),
+ new String[]{
+ KeychainContract.KeyRings.MASTER_KEY_ID,
+ KeychainContract.KeyRings.FINGERPRINT
+ },
+ null,
+ null,
+ null
+ );
+
+ if (keyCursor == null) {
+ return new ArrayList<>();
+ }
+
+ ArrayList<ParcelableKeyRing> keyList = new ArrayList<>();
+ while (keyCursor.moveToNext()) {
+ long keyId = keyCursor.getLong(INDEX_MASTER_KEY_ID);
+ if (ignoreMasterKeyIds.contains(keyId)) {
+ continue;
+ }
+ Log.d(Constants.TAG, "Keyserver sync: Updating {" + keyId + "}");
+ String fingerprint = KeyFormattingUtils
+ .convertFingerprintToHex(keyCursor.getBlob(INDEX_FINGERPRINT));
+ String hexKeyId = KeyFormattingUtils
+ .convertKeyIdToHex(keyId);
+ // we aren't updating from keybase as of now
+ keyList.add(new ParcelableKeyRing(fingerprint, hexKeyId, null));
+ }
+ keyCursor.close();
+
+ return keyList;
+ }
+
+ private boolean isUpdateCancelled() {
+ return mCancelled.get();
+ }
+
+ /**
+ * will cancel an update already in progress. We send an Intent to cancel it instead of simply
+ * modifying a static variable sync the service is running in a process that is different from
+ * the default application process where the UI code runs.
+ *
+ * @param context used to send an Intent to the service requesting cancellation.
+ */
+ public static void cancelUpdates(Context context) {
+ Intent intent = new Intent(context, KeyserverSyncAdapterService.class);
+ intent.setAction(ACTION_CANCEL);
+ context.startService(intent);
+ }
+
+ private Notification getOrbotNoification(Context context) {
+ NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
+ builder.setSmallIcon(R.drawable.ic_stat_notify_24dp)
+ .setLargeIcon(getBitmap(R.mipmap.ic_launcher, context))
+ .setContentTitle(context.getString(R.string.keyserver_sync_orbot_notif_title))
+ .setContentText(context.getString(R.string.keyserver_sync_orbot_notif_msg))
+ .setAutoCancel(true);
+
+ // In case the user decides to not use tor
+ Intent ignoreTorIntent = new Intent(context, KeyserverSyncAdapterService.class);
+ ignoreTorIntent.setAction(ACTION_IGNORE_TOR);
+ PendingIntent ignoreTorPi = PendingIntent.getService(
+ context,
+ 0, // security not issue since we're giving this pending intent to Notification Manager
+ ignoreTorIntent,
+ PendingIntent.FLAG_CANCEL_CURRENT
+ );
+
+ builder.addAction(R.drawable.ic_stat_tor_off,
+ context.getString(R.string.keyserver_sync_orbot_notif_ignore),
+ ignoreTorPi);
+
+ Intent startOrbotIntent = new Intent(context, KeyserverSyncAdapterService.class);
+ startOrbotIntent.setAction(ACTION_START_ORBOT);
+ PendingIntent startOrbotPi = PendingIntent.getService(
+ context,
+ 0, // security not issue since we're giving this pending intent to Notification Manager
+ startOrbotIntent,
+ PendingIntent.FLAG_CANCEL_CURRENT
+ );
+
+ builder.addAction(R.drawable.ic_stat_tor,
+ context.getString(R.string.keyserver_sync_orbot_notif_start),
+ startOrbotPi
+ );
+ builder.setContentIntent(startOrbotPi);
+
+ return builder.build();
+ }
+
+ public static void enableKeyserverSync(Context context) {
+ try {
+ AccountManager manager = AccountManager.get(context);
+ Account[] accounts = manager.getAccountsByType(Constants.ACCOUNT_TYPE);
+
+ Account account = new Account(Constants.ACCOUNT_NAME, Constants.ACCOUNT_TYPE);
+ if (accounts.length == 0) {
+ if (!manager.addAccountExplicitly(account, null, null)) {
+ Log.e(Constants.TAG, "Adding account failed!");
+ }
+ }
+ // for keyserver sync
+ ContentResolver.setIsSyncable(account, Constants.PROVIDER_AUTHORITY, 1);
+ ContentResolver.setSyncAutomatically(account, Constants.PROVIDER_AUTHORITY,
+ true);
+ ContentResolver.addPeriodicSync(
+ account,
+ Constants.PROVIDER_AUTHORITY,
+ new Bundle(),
+ SYNC_INTERVAL
+ );
+ } catch (SecurityException e) {
+ Log.e(Constants.TAG, "SecurityException when adding the account", e);
+ Toast.makeText(context, R.string.reinstall_openkeychain, Toast.LENGTH_LONG).show();
+ }
+ }
+
+ // from de.azapps.mirakel.helper.Helpers from https://github.com/MirakelX/mirakel-android
+ private Bitmap getBitmap(int resId, Context context) {
+ int mLargeIconWidth = (int) context.getResources().getDimension(
+ android.R.dimen.notification_large_icon_width);
+ int mLargeIconHeight = (int) context.getResources().getDimension(
+ android.R.dimen.notification_large_icon_height);
+ Drawable d;
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
+ // noinspection deprecation (can't help it at this api level)
+ d = context.getResources().getDrawable(resId);
+ } else {
+ d = context.getDrawable(resId);
+ }
+ if (d == null) {
+ return null;
+ }
+ Bitmap b = Bitmap.createBitmap(mLargeIconWidth, mLargeIconHeight, Bitmap.Config.ARGB_8888);
+ Canvas c = new Canvas(b);
+ d.setBounds(0, 0, mLargeIconWidth, mLargeIconHeight);
+ d.draw(c);
+ return b;
+ }
+}
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 2a258b7e3..5d04317b3 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java
@@ -101,8 +101,6 @@ public class PassphraseCacheService extends Service {
private static final long DEFAULT_TTL = 15;
- private static final int NOTIFICATION_ID = 1;
-
private static final int MSG_PASSPHRASE_CACHE_GET_OKAY = 1;
private static final int MSG_PASSPHRASE_CACHE_GET_KEY_NOT_FOUND = 2;
@@ -477,7 +475,7 @@ public class PassphraseCacheService extends Service {
private void updateService() {
if (mPassphraseCache.size() > 0) {
- startForeground(NOTIFICATION_ID, getNotification());
+ startForeground(Constants.Notification.PASSPHRASE_CACHE, getNotification());
} else {
// stop whole service if no cached passphrases remaining
Log.d(Constants.TAG, "PassphraseCacheService: No passphrases remaining in memory, stopping service!");
@@ -511,7 +509,7 @@ public class PassphraseCacheService extends Service {
private Notification getNotification() {
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setSmallIcon(R.drawable.ic_stat_notify_24dp)
- .setLargeIcon(getBitmap(R.drawable.ic_launcher, getBaseContext()))
+ .setLargeIcon(getBitmap(R.mipmap.ic_launcher, getBaseContext()))
.setContentTitle(getResources().getQuantityString(R.plurals.passp_cache_notif_n_keys,
mPassphraseCache.size(), mPassphraseCache.size()))
.setContentText(getString(R.string.passp_cache_notif_click_to_clear));
@@ -603,4 +601,4 @@ public class PassphraseCacheService extends Service {
this.passphrase = passphrase;
}
}
-} \ No newline at end of file
+}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BackupFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BackupFragment.java
index 2d9ac6ee3..a3ea8ad9a 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BackupFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BackupFragment.java
@@ -18,7 +18,11 @@
package org.sufficientlysecure.keychain.ui;
+import java.io.File;
+import java.text.SimpleDateFormat;
import java.util.ArrayList;
+import java.util.Date;
+import java.util.Locale;
import android.app.Activity;
import android.content.ContentResolver;
@@ -47,7 +51,20 @@ public class BackupFragment extends Fragment {
private int mIndex;
static final int REQUEST_REPEAT_PASSPHRASE = 1;
+ private ExportHelper mExportHelper;
+ @Override
+ public void onAttach(Activity activity) {
+ super.onAttach(activity);
+ // we won't get attached to a non-fragment activity, so the cast should be safe
+ mExportHelper = new ExportHelper((FragmentActivity) activity);
+ }
+
+ @Override
+ public void onDetach() {
+ super.onDetach();
+ mExportHelper = null;
+ }
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
@@ -80,8 +97,7 @@ public class BackupFragment extends Fragment {
}
if (!includeSecretKeys) {
- ExportHelper exportHelper = new ExportHelper(activity);
- exportHelper.showExportKeysDialog(null, Constants.Path.APP_DIR_FILE, false);
+ startBackup(false);
return;
}
@@ -136,8 +152,7 @@ public class BackupFragment extends Fragment {
return;
}
- ExportHelper exportHelper = new ExportHelper(activity);
- exportHelper.showExportKeysDialog(null, Constants.Path.APP_DIR_FILE, true);
+ startBackup(true);
}
}.execute(activity.getContentResolver());
@@ -167,8 +182,19 @@ public class BackupFragment extends Fragment {
return;
}
- ExportHelper exportHelper = new ExportHelper(getActivity());
- exportHelper.showExportKeysDialog(null, Constants.Path.APP_DIR_FILE, true);
+ startBackup(true);
}
}
+
+ private void startBackup(boolean exportSecret) {
+ File filename;
+ String date = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).format(new Date());
+ if (exportSecret) {
+ filename = new File(Constants.Path.APP_DIR, "keys_" + date + ".asc");
+ } else {
+ filename = new File(Constants.Path.APP_DIR, "keys_" + date + ".pub.asc");
+ }
+ mExportHelper.showExportKeysDialog(null, filename, exportSecret);
+ }
+
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyFingerprintActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyFingerprintActivity.java
index 016ab5f3c..c5528e40b 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyFingerprintActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyFingerprintActivity.java
@@ -30,6 +30,8 @@ public class CertifyFingerprintActivity extends BaseActivity {
protected Uri mDataUri;
+ public static final String EXTRA_ENABLE_WORD_CONFIRM = "enable_word_confirm";
+
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -40,6 +42,7 @@ public class CertifyFingerprintActivity extends BaseActivity {
finish();
return;
}
+ boolean enableWordConfirm = getIntent().getBooleanExtra(EXTRA_ENABLE_WORD_CONFIRM, false);
setFullScreenDialogClose(new View.OnClickListener() {
@Override
@@ -50,7 +53,7 @@ public class CertifyFingerprintActivity extends BaseActivity {
Log.i(Constants.TAG, "mDataUri: " + mDataUri.toString());
- startFragment(savedInstanceState, mDataUri);
+ startFragment(savedInstanceState, mDataUri, enableWordConfirm);
}
@Override
@@ -58,7 +61,7 @@ public class CertifyFingerprintActivity extends BaseActivity {
setContentView(R.layout.certify_fingerprint_activity);
}
- private void startFragment(Bundle savedInstanceState, Uri dataUri) {
+ private void startFragment(Bundle savedInstanceState, Uri dataUri, boolean enableWordConfirm) {
// 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.
@@ -67,7 +70,7 @@ public class CertifyFingerprintActivity extends BaseActivity {
}
// Create an instance of the fragment
- CertifyFingerprintFragment frag = CertifyFingerprintFragment.newInstance(dataUri);
+ CertifyFingerprintFragment frag = CertifyFingerprintFragment.newInstance(dataUri, enableWordConfirm);
// Add the fragment to the 'fragment_container' FrameLayout
// NOTE: We use commitAllowingStateLoss() to prevent weird crashes!
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyFingerprintFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyFingerprintFragment.java
index a6b8a0e85..552fa34c0 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyFingerprintFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyFingerprintFragment.java
@@ -19,6 +19,7 @@ package org.sufficientlysecure.keychain.ui;
import android.content.Intent;
import android.database.Cursor;
+import android.graphics.Typeface;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.LoaderManager;
@@ -34,6 +35,7 @@ import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
+import org.sufficientlysecure.keychain.ui.util.ExperimentalWordConfirm;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.util.Log;
@@ -44,23 +46,24 @@ public class CertifyFingerprintFragment extends LoaderFragment implements
static final int REQUEST_CERTIFY = 1;
public static final String ARG_DATA_URI = "uri";
+ public static final String ARG_ENABLE_WORD_CONFIRM = "enable_word_confirm";
private TextView mFingerprint;
+ private TextView mIntro;
private static final int LOADER_ID_UNIFIED = 0;
private Uri mDataUri;
-
- private View mActionNo;
- private View mActionYes;
+ private boolean mEnableWordConfirm;
/**
* Creates new instance of this fragment
*/
- public static CertifyFingerprintFragment newInstance(Uri dataUri) {
+ public static CertifyFingerprintFragment newInstance(Uri dataUri, boolean enableWordConfirm) {
CertifyFingerprintFragment frag = new CertifyFingerprintFragment();
Bundle args = new Bundle();
args.putParcelable(ARG_DATA_URI, dataUri);
+ args.putBoolean(ARG_ENABLE_WORD_CONFIRM, enableWordConfirm);
frag.setArguments(args);
@@ -72,18 +75,19 @@ public class CertifyFingerprintFragment extends LoaderFragment implements
View root = super.onCreateView(inflater, superContainer, savedInstanceState);
View view = inflater.inflate(R.layout.certify_fingerprint_fragment, getContainer());
- mActionNo = view.findViewById(R.id.certify_fingerprint_button_no);
- mActionYes = view.findViewById(R.id.certify_fingerprint_button_yes);
+ View actionNo = view.findViewById(R.id.certify_fingerprint_button_no);
+ View actionYes = view.findViewById(R.id.certify_fingerprint_button_yes);
mFingerprint = (TextView) view.findViewById(R.id.certify_fingerprint_fingerprint);
+ mIntro = (TextView) view.findViewById(R.id.certify_fingerprint_intro);
- mActionNo.setOnClickListener(new View.OnClickListener() {
+ actionNo.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
getActivity().finish();
}
});
- mActionYes.setOnClickListener(new View.OnClickListener() {
+ actionYes.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
certify(mDataUri);
@@ -103,6 +107,11 @@ public class CertifyFingerprintFragment extends LoaderFragment implements
getActivity().finish();
return;
}
+ mEnableWordConfirm = getArguments().getBoolean(ARG_ENABLE_WORD_CONFIRM);
+
+ if (mEnableWordConfirm) {
+ mIntro.setText(R.string.certify_fingerprint_text_words);
+ }
loadData(dataUri);
}
@@ -149,10 +158,13 @@ public class CertifyFingerprintFragment extends LoaderFragment implements
switch (loader.getId()) {
case LOADER_ID_UNIFIED: {
if (data.moveToFirst()) {
-
byte[] fingerprintBlob = data.getBlob(INDEX_UNIFIED_FINGERPRINT);
- String fingerprint = KeyFormattingUtils.convertFingerprintToHex(fingerprintBlob);
- mFingerprint.setText(KeyFormattingUtils.colorizeFingerprint(fingerprint));
+
+ if (mEnableWordConfirm) {
+ displayWordConfirm(fingerprintBlob);
+ } else {
+ displayHexConfirm(fingerprintBlob);
+ }
break;
}
@@ -162,6 +174,19 @@ public class CertifyFingerprintFragment extends LoaderFragment implements
setContentShown(true);
}
+ private void displayHexConfirm(byte[] fingerprintBlob) {
+ String fingerprint = KeyFormattingUtils.convertFingerprintToHex(fingerprintBlob);
+ mFingerprint.setText(KeyFormattingUtils.colorizeFingerprint(fingerprint));
+ }
+
+ private void displayWordConfirm(byte[] fingerprintBlob) {
+ String fingerprint = ExperimentalWordConfirm.getWords(getActivity(), fingerprintBlob);
+
+ mFingerprint.setTextSize(24);
+ mFingerprint.setTypeface(Typeface.DEFAULT, Typeface.BOLD);
+ mFingerprint.setText(fingerprint);
+ }
+
/**
* This is called when the last Cursor provided to onLoadFinished() above is about to be closed.
* We need to make sure we are no longer using it.
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 5ca7c6bc7..357b445f0 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyFragment.java
@@ -83,7 +83,9 @@ public class CertifyKeyFragment
};
private static final int INDEX_MASTER_KEY_ID = 1;
private static final int INDEX_USER_ID = 2;
+ @SuppressWarnings("unused")
private static final int INDEX_IS_PRIMARY = 3;
+ @SuppressWarnings("unused")
private static final int INDEX_IS_REVOKED = 4;
private MultiUserIdsAdapter mUserIdsAdapter;
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 e581e069b..881190ae2 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptActivity.java
@@ -29,13 +29,14 @@ import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
+import android.support.annotation.Nullable;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
-import android.view.View;
import android.widget.Toast;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.intents.OpenKeychainIntents;
+import org.sufficientlysecure.keychain.pgp.PgpHelper;
import org.sufficientlysecure.keychain.provider.TemporaryStorageProvider;
import org.sufficientlysecure.keychain.ui.base.BaseActivity;
@@ -93,7 +94,9 @@ public class DecryptActivity extends BaseActivity {
} else if (intent.hasExtra(Intent.EXTRA_TEXT)) {
String text = intent.getStringExtra(Intent.EXTRA_TEXT);
Uri uri = readToTempFile(text);
- uris.add(uri);
+ if (uri != null) {
+ uris.add(uri);
+ }
}
break;
@@ -105,7 +108,9 @@ public class DecryptActivity extends BaseActivity {
} else if (intent.hasExtra(Intent.EXTRA_TEXT)) {
for (String text : intent.getStringArrayListExtra(Intent.EXTRA_TEXT)) {
Uri uri = readToTempFile(text);
- uris.add(uri);
+ if (uri != null) {
+ uris.add(uri);
+ }
}
}
@@ -139,7 +144,9 @@ public class DecryptActivity extends BaseActivity {
String text = clip.getItemAt(0).coerceToText(this).toString();
uri = readToTempFile(text);
}
- uris.add(uri);
+ if (uri != null) {
+ uris.add(uri);
+ }
break;
}
@@ -170,9 +177,17 @@ public class DecryptActivity extends BaseActivity {
}
- public Uri readToTempFile(String text) throws IOException {
+ @Nullable public Uri readToTempFile(String text) throws IOException {
Uri tempFile = TemporaryStorageProvider.createFile(this);
OutputStream outStream = getContentResolver().openOutputStream(tempFile);
+
+ // clean up ascii armored message, fixing newlines and stuff
+ String cleanedText = PgpHelper.getPgpContent(text);
+ if (cleanedText == null) {
+ return null;
+ }
+
+ // if cleanup didn't work, just try the raw data
outStream.write(text.getBytes());
outStream.close();
return tempFile;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptListFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptListFragment.java
index 640755ef3..3dda47ac5 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptListFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptListFragment.java
@@ -35,7 +35,6 @@ import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.AsyncTask;
-import android.os.Build;
import android.os.Bundle;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
@@ -222,18 +221,6 @@ public class DecryptListFragment
}
}
- private void askForOutputFilename(Uri inputUri, String originalFilename, String mimeType) {
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
- File file = new File(inputUri.getPath());
- File parentDir = file.exists() ? file.getParentFile() : Constants.Path.APP_DIR;
- File targetFile = new File(parentDir, originalFilename);
- FileHelper.saveFile(this, getString(R.string.title_decrypt_to_file),
- getString(R.string.specify_file_to_decrypt_to), targetFile, REQUEST_CODE_OUTPUT);
- } else {
- FileHelper.saveDocument(this, mimeType, originalFilename, REQUEST_CODE_OUTPUT);
- }
- }
-
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
@@ -388,7 +375,7 @@ public class DecryptListFragment
onFileClick = new OnClickListener() {
@Override
public void onClick(View view) {
- displayWithViewIntent(uri);
+ displayWithViewIntent(uri, false);
}
};
}
@@ -413,7 +400,7 @@ public class DecryptListFragment
}
- public void displayWithViewIntent(final Uri uri) {
+ public void displayWithViewIntent(final Uri uri, boolean share) {
Activity activity = getActivity();
if (activity == null || mCurrentInputUri != null) {
return;
@@ -432,104 +419,47 @@ public class DecryptListFragment
// OpenKeychain's internal viewer
if ("text/plain".equals(metadata.getMimeType())) {
- parseMime(outputUri);
-
- // this is a significant i/o operation, use an asynctask
-// new AsyncTask<Void,Void,Intent>() {
-//
-// @Override
-// protected Intent doInBackground(Void... params) {
-//
-// Activity activity = getActivity();
-// if (activity == null) {
-// return null;
-// }
-//
-// Intent intent = new Intent(Intent.ACTION_VIEW);
-// intent.setDataAndType(outputUri, "text/plain");
-// intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
-// return intent;
-// }
-//
-// @Override
-// protected void onPostExecute(Intent intent) {
-// // for result so we can possibly get a snackbar error from internal viewer
-// Activity activity = getActivity();
-// if (intent == null || activity == null) {
-// return;
-// }
-//
-// LabeledIntent internalIntent = new LabeledIntent(
-// new Intent(intent)
-// .setClass(activity, DisplayTextActivity.class)
-// .putExtra(DisplayTextActivity.EXTRA_METADATA, result),
-// BuildConfig.APPLICATION_ID, R.string.view_internal, R.drawable.ic_launcher);
-//
-// Intent chooserIntent = Intent.createChooser(intent, getString(R.string.intent_show));
-// chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS,
-// new Parcelable[] { internalIntent });
-//
-// activity.startActivity(chooserIntent);
-// }
-//
-// }.execute();
+ if (share) {
+ try {
+ String plaintext = FileHelper.readTextFromUri(activity, outputUri, result.getCharset());
- } else {
- Intent intent = new Intent(Intent.ACTION_VIEW);
- intent.setDataAndType(outputUri, metadata.getMimeType());
- intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ Intent intent = new Intent(Intent.ACTION_SEND);
+ intent.setType(metadata.getMimeType());
+ intent.putExtra(Intent.EXTRA_TEXT, plaintext);
+ startActivity(intent);
- Intent chooserIntent = Intent.createChooser(intent, getString(R.string.intent_show));
- chooserIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
- activity.startActivity(chooserIntent);
- }
-
- }
-
- private void parseMime(final Uri inputUri) {
-
- CryptoOperationHelper.Callback<MimeParsingParcel, MimeParsingResult> callback
- = new CryptoOperationHelper.Callback<MimeParsingParcel, MimeParsingResult>() {
-
- @Override
- public MimeParsingParcel createOperationInput() {
- return new MimeParsingParcel(inputUri, null);
- }
+ } catch (IOException e) {
+ Notify.create(activity, R.string.error_preparing_data, Style.ERROR).show();
+ }
- @Override
- public void onCryptoOperationSuccess(MimeParsingResult result) {
- handleResult(result);
+ return;
}
- @Override
- public void onCryptoOperationCancelled() {
+ Intent intent = new Intent(activity, DisplayTextActivity.class);
+ intent.setAction(Intent.ACTION_VIEW);
+ intent.setDataAndType(outputUri, metadata.getMimeType());
+ intent.putExtra(DisplayTextActivity.EXTRA_METADATA, result);
+ activity.startActivity(intent);
- }
+ } else {
- @Override
- public void onCryptoOperationError(MimeParsingResult result) {
- handleResult(result);
+ Intent intent;
+ if (share) {
+ intent = new Intent(Intent.ACTION_SEND);
+ intent.setType(metadata.getMimeType());
+ intent.putExtra(Intent.EXTRA_STREAM, outputUri);
+ } else {
+ intent = new Intent(Intent.ACTION_VIEW);
+ intent.setDataAndType(outputUri, metadata.getMimeType());
}
- public void handleResult(MimeParsingResult result) {
- // TODO: merge with other log
-// saveKeyResult.getLog().add(result, 0);
-
- mOutputUris = new HashMap<>(result.getTemporaryUris().size());
- for (Uri tempUri : result.getTemporaryUris()) {
- // TODO: use same inputUri for all?
- mOutputUris.put(inputUri, tempUri);
- }
- }
+ intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
- @Override
- public boolean onCryptoSetProgress(String msg, int progress, int max) {
- return false;
- }
- };
+ Intent chooserIntent = Intent.createChooser(intent, getString(R.string.intent_show));
+ chooserIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ activity.startActivity(chooserIntent);
+ }
- CryptoOperationHelper mimeParsingHelper = new CryptoOperationHelper<>(3, this, callback, R.string.progress_uploading);
- mimeParsingHelper.cryptoOperation();
}
@Override
@@ -576,13 +506,17 @@ public class DecryptListFragment
intent.putExtra(LogDisplayFragment.EXTRA_RESULT, result);
activity.startActivity(intent);
return true;
+ case R.id.decrypt_share:
+ displayWithViewIntent(model.mInputUri, true);
+ return true;
case R.id.decrypt_save:
OpenPgpMetadata metadata = result.getDecryptionMetadata();
if (metadata == null) {
return true;
}
mCurrentInputUri = model.mInputUri;
- askForOutputFilename(model.mInputUri, metadata.getFilename(), metadata.getMimeType());
+ FileHelper.saveDocument(this, metadata.getFilename(), model.mInputUri, metadata.getMimeType(),
+ R.string.title_decrypt_to_file, R.string.specify_file_to_decrypt_to, REQUEST_CODE_OUTPUT);
return true;
case R.id.decrypt_delete:
deleteFile(activity, model.mInputUri);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DeleteKeyDialogActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DeleteKeyDialogActivity.java
index b22053df1..478259133 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DeleteKeyDialogActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DeleteKeyDialogActivity.java
@@ -48,7 +48,6 @@ import org.sufficientlysecure.keychain.service.RevokeKeyringParcel;
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
import org.sufficientlysecure.keychain.ui.base.CryptoOperationHelper;
import org.sufficientlysecure.keychain.ui.dialog.CustomAlertDialogBuilder;
-import org.sufficientlysecure.keychain.ui.util.Notify;
import org.sufficientlysecure.keychain.ui.util.ThemeChanger;
import org.sufficientlysecure.keychain.util.Log;
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 4769e68d8..07b0a12d3 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java
@@ -280,7 +280,7 @@ public class EditKeyFragment extends QueueingCryptoOperationFragment<SaveKeyring
case LOADER_ID_USER_IDS: {
Uri baseUri = UserPackets.buildUserIdsUri(mDataUri);
return new CursorLoader(getActivity(), baseUri,
- UserIdsAdapter.USER_IDS_PROJECTION, null, null, null);
+ UserIdsAdapter.USER_PACKETS_PROJECTION, null, null, null);
}
case LOADER_ID_SUBKEYS: {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptDecryptOverviewFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptDecryptOverviewFragment.java
index fc72a6c9f..84660ca7a 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptDecryptOverviewFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptDecryptOverviewFragment.java
@@ -83,11 +83,7 @@ public class EncryptDecryptOverviewFragment extends Fragment {
mDecryptFile.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
- FileHelper.openDocument(EncryptDecryptOverviewFragment.this, "*/*", REQUEST_CODE_INPUT);
- } else {
- FileHelper.openFile(EncryptDecryptOverviewFragment.this, null, "*/*", REQUEST_CODE_INPUT);
- }
+ FileHelper.openDocument(EncryptDecryptOverviewFragment.this, null, "*/*", false, REQUEST_CODE_INPUT);
}
});
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 63d37f296..8572a5712 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java
@@ -18,7 +18,6 @@
package org.sufficientlysecure.keychain.ui;
-import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
@@ -196,13 +195,9 @@ public class EncryptFilesFragment
}
private void addInputUri() {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
- FileHelper.openDocument(EncryptFilesFragment.this, "*/*", true, REQUEST_CODE_INPUT);
- } else {
- FileHelper.openFile(EncryptFilesFragment.this, mFilesAdapter.getModelCount() == 0 ?
- null : mFilesAdapter.getModelItem(mFilesAdapter.getModelCount() - 1).inputUri,
- "*/*", REQUEST_CODE_INPUT);
- }
+ FileHelper.openDocument(EncryptFilesFragment.this, mFilesAdapter.getModelCount() == 0 ?
+ null : mFilesAdapter.getModelItem(mFilesAdapter.getModelCount() - 1).inputUri,
+ "*/*", true, REQUEST_CODE_INPUT);
}
private void addInputUri(Uri inputUri) {
@@ -230,19 +225,8 @@ public class EncryptFilesFragment
(mEncryptFilenames ? "1" : FileHelper.getFilename(getActivity(), model.inputUri))
+ (mUseArmor ? Constants.FILE_EXTENSION_ASC : Constants.FILE_EXTENSION_PGP_MAIN);
Uri inputUri = model.inputUri;
- saveDocumentIntent(targetName, inputUri);
- }
-
- private void saveDocumentIntent(String targetName, Uri inputUri) {
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
- File file = new File(inputUri.getPath());
- File parentDir = file.exists() ? file.getParentFile() : Constants.Path.APP_DIR;
- File targetFile = new File(parentDir, targetName);
- FileHelper.saveFile(this, getString(R.string.title_encrypt_to_file),
- getString(R.string.specify_file_to_encrypt_to), targetFile, REQUEST_CODE_OUTPUT);
- } else {
- FileHelper.saveDocument(this, "*/*", targetName, REQUEST_CODE_OUTPUT);
- }
+ FileHelper.saveDocument(this, targetName, inputUri,
+ R.string.title_encrypt_to_file, R.string.specify_file_to_encrypt_to, REQUEST_CODE_OUTPUT);
}
public void addFile(Intent data) {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysFileFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysFileFragment.java
index 538fa16c7..746c75600 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysFileFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysFileFragment.java
@@ -64,8 +64,8 @@ public class ImportKeysFileFragment extends Fragment {
// open .asc or .gpg files
// setting it to text/plain prevents Cyanogenmod's file manager from selecting asc
// or gpg types!
- FileHelper.openFile(ImportKeysFileFragment.this, Uri.fromFile(Constants.Path.APP_DIR),
- "*/*", REQUEST_CODE_FILE);
+ FileHelper.openDocument(ImportKeysFileFragment.this,
+ Uri.fromFile(Constants.Path.APP_DIR), "*/*", false, REQUEST_CODE_FILE);
}
});
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 8c46876be..ce6994ba4 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java
@@ -18,11 +18,6 @@
package org.sufficientlysecure.keychain.ui;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashMap;
-
import android.animation.ObjectAnimator;
import android.annotation.TargetApi;
import android.app.Activity;
@@ -70,16 +65,19 @@ import org.sufficientlysecure.keychain.service.ConsolidateInputParcel;
import org.sufficientlysecure.keychain.service.ImportKeyringParcel;
import org.sufficientlysecure.keychain.ui.adapter.KeyAdapter;
import org.sufficientlysecure.keychain.ui.base.CryptoOperationHelper;
-import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.ui.util.FormattingUtils;
+import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.ui.util.Notify;
-import org.sufficientlysecure.keychain.ui.util.Notify.Style;
import org.sufficientlysecure.keychain.util.FabContainer;
import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.Preferences;
import se.emilsjolander.stickylistheaders.StickyListHeadersAdapter;
import se.emilsjolander.stickylistheaders.StickyListHeadersListView;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+
/**
* Public key list with sticky list headers. It does _not_ extend ListFragment because it uses
* StickyListHeaders library which does not extend upon ListView.
@@ -536,7 +534,7 @@ public class KeyListFragment extends LoaderFragment
);
if (cursor == null) {
- Notify.create(activity, R.string.error_loading_keys, Style.ERROR);
+ Notify.create(activity, R.string.error_loading_keys, Notify.Style.ERROR);
return;
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LogDisplayFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LogDisplayFragment.java
index 1cd1a3099..43c8d2643 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LogDisplayFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LogDisplayFragment.java
@@ -18,11 +18,12 @@
package org.sufficientlysecure.keychain.ui;
+import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
+import android.net.Uri;
import android.os.Bundle;
-import android.os.Parcel;
import android.support.v4.app.ListFragment;
import android.util.TypedValue;
import android.view.LayoutInflater;
@@ -37,19 +38,19 @@ import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
-import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.operations.results.OperationResult;
import org.sufficientlysecure.keychain.operations.results.OperationResult.LogEntryParcel;
import org.sufficientlysecure.keychain.operations.results.OperationResult.LogLevel;
import org.sufficientlysecure.keychain.operations.results.OperationResult.SubLogEntryParcel;
+import org.sufficientlysecure.keychain.provider.TemporaryStorageProvider;
import org.sufficientlysecure.keychain.ui.util.FormattingUtils;
-import org.sufficientlysecure.keychain.util.FileHelper;
-import org.sufficientlysecure.keychain.util.Log;
+import org.sufficientlysecure.keychain.ui.util.Notify;
+import org.sufficientlysecure.keychain.ui.util.Notify.Style;
+
+import java.io.IOException;
+import java.io.OutputStream;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.PrintWriter;
public class LogDisplayFragment extends ListFragment implements OnItemClickListener {
@@ -60,6 +61,8 @@ public class LogDisplayFragment extends ListFragment implements OnItemClickListe
public static final String EXTRA_RESULT = "log";
protected int mTextColor;
+ private Uri mLogTempFile;
+
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -118,170 +121,40 @@ public class LogDisplayFragment extends ListFragment implements OnItemClickListe
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_log_display_export_log:
- exportLog();
+ shareLog();
break;
}
return super.onOptionsItemSelected(item);
}
- private void exportLog() {
- showExportLogDialog(new File(Constants.Path.APP_DIR, "export.log"));
- }
-
- private void writeToLogFile(final OperationResult.OperationLog operationLog, final File f) {
- OperationResult.OperationLog currLog = new OperationResult.OperationLog();
- currLog.add(OperationResult.LogType.MSG_EXPORT_LOG, 0);
-
- boolean error = false;
-
- PrintWriter pw = null;
- try {
- pw = new PrintWriter(f);
- pw.print(getPrintableOperationLog(operationLog, ""));
- if (pw.checkError()) {//IOException
- Log.e(Constants.TAG, "Log Export I/O Exception " + f.getAbsolutePath());
- currLog.add(OperationResult.LogType.MSG_EXPORT_LOG_EXPORT_ERROR_WRITING, 1);
- error = true;
- }
- } catch (FileNotFoundException e) {
- Log.e(Constants.TAG, "File not found for exporting log " + f.getAbsolutePath());
- currLog.add(OperationResult.LogType.MSG_EXPORT_LOG_EXPORT_ERROR_FOPEN, 1);
- error = true;
- }
- if (pw != null) {
- pw.close();
- if (!error && pw.checkError()) {//check if it is only pw.close() which generated error
- currLog.add(OperationResult.LogType.MSG_EXPORT_LOG_EXPORT_ERROR_WRITING, 1);
- error = true;
- }
- }
-
- if (!error) {
- currLog.add(OperationResult.LogType.MSG_EXPORT_LOG_EXPORT_SUCCESS, 1);
- }
-
- int opResultCode = error ? OperationResult.RESULT_ERROR : OperationResult.RESULT_OK;
- OperationResult opResult = new LogExportResult(opResultCode, currLog);
- opResult.createNotify(getActivity()).show();
- }
-
- /**
- * returns an indented String of an entire OperationLog
- *
- * @param opLog log to be converted to indented, printable format
- * @param basePadding padding to add at the start of all log entries, made for use with SubLogs
- * @return printable, indented version of passed operationLog
- */
- private String getPrintableOperationLog(OperationResult.OperationLog opLog, String basePadding) {
- String log = "";
- for (LogEntryParcel anOpLog : opLog) {
- log += getPrintableLogEntry(anOpLog, basePadding) + "\n";
- }
- log = log.substring(0, log.length() - 1);//gets rid of extra new line
- return log;
- }
-
- /**
- * returns an indented String of a LogEntryParcel including any sub-logs it may contain
- *
- * @param entryParcel log entryParcel whose String representation is to be obtained
- * @return indented version of passed log entryParcel in a readable format
- */
- private String getPrintableLogEntry(OperationResult.LogEntryParcel entryParcel,
- String basePadding) {
-
- final String indent = " ";//4 spaces = 1 Indent level
-
- String padding = basePadding;
- for (int i = 0; i < entryParcel.mIndent; i++) {
- padding += indent;
- }
- String logText = padding;
-
- switch (entryParcel.mType.mLevel) {
- case DEBUG:
- logText += "[DEBUG]";
- break;
- case INFO:
- logText += "[INFO]";
- break;
- case WARN:
- logText += "[WARN]";
- break;
- case ERROR:
- logText += "[ERROR]";
- break;
- case START:
- logText += "[START]";
- break;
- case OK:
- logText += "[OK]";
- break;
- case CANCELLED:
- logText += "[CANCELLED]";
- break;
- }
+ private void shareLog() {
- // special case: first parameter may be a quantity
- if (entryParcel.mParameters != null && entryParcel.mParameters.length > 0
- && entryParcel.mParameters[0] instanceof Integer) {
- logText += getResources().getQuantityString(entryParcel.mType.getMsgId(),
- (Integer) entryParcel.mParameters[0],
- entryParcel.mParameters);
- } else {
- logText += getResources().getString(entryParcel.mType.getMsgId(),
- entryParcel.mParameters);
+ Activity activity = getActivity();
+ if (activity == null) {
+ return;
}
- if (entryParcel instanceof SubLogEntryParcel) {
- OperationResult subResult = ((SubLogEntryParcel) entryParcel).getSubResult();
- LogEntryParcel subEntry = subResult.getLog().getLast();
- if (subEntry != null) {
- //the first line of log of subResult is same as entryParcel, so replace logText
- logText = getPrintableOperationLog(subResult.getLog(), padding);
+ String log = mResult.getLog().getPrintableOperationLog(getResources(), 0);
+
+ // if there is no log temp file yet, create one
+ if (mLogTempFile == null) {
+ mLogTempFile = TemporaryStorageProvider.createFile(getActivity(), "openkeychain_log.txt", "text/plain");
+ try {
+ OutputStream outputStream = activity.getContentResolver().openOutputStream(mLogTempFile);
+ outputStream.write(log.getBytes());
+ } catch (IOException e) {
+ Notify.create(activity, R.string.error_log_share_internal, Style.ERROR).show();
+ return;
}
}
- return logText;
- }
-
- private void showExportLogDialog(final File exportFile) {
-
- String title = this.getString(R.string.title_export_log);
-
- String message = this.getString(R.string.specify_file_to_export_log_to);
-
- FileHelper.saveFile(new FileHelper.FileDialogCallback() {
- @Override
- public void onFileSelected(File file, boolean checked) {
- writeToLogFile(mResult.getLog(), file);
- }
- }, this.getActivity().getSupportFragmentManager(), title, message, exportFile, null);
- }
-
- private static class LogExportResult extends OperationResult {
-
- public static Creator<LogExportResult> CREATOR = new Creator<LogExportResult>() {
- public LogExportResult createFromParcel(final Parcel source) {
- return new LogExportResult(source);
- }
-
- public LogExportResult[] newArray(final int size) {
- return new LogExportResult[size];
- }
- };
-
- public LogExportResult(int result, OperationLog log) {
- super(result, log);
- }
+ Intent intent = new Intent(Intent.ACTION_SEND);
+ intent.putExtra(Intent.EXTRA_STREAM, mLogTempFile);
+ intent.setType("text/plain");
+ intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ startActivity(intent);
- /**
- * trivial but necessary to implement the Parcelable protocol.
- */
- public LogExportResult(Parcel source) {
- super(source);
- }
}
@Override
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcOperationActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcOperationActivity.java
index e6591595e..b811b218e 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcOperationActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcOperationActivity.java
@@ -21,7 +21,6 @@
package org.sufficientlysecure.keychain.ui;
import android.content.Intent;
-import android.content.pm.ActivityInfo;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
@@ -50,15 +49,11 @@ import org.sufficientlysecure.keychain.util.Preferences;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Arrays;
-import java.util.Date;
/**
* This class provides a communication interface to OpenPGP applications on ISO SmartCard compliant
* NFC devices.
- * <p/>
* For the full specs, see http://g10code.com/docs/openpgp-card-2.0.pdf
- * NOTE: If no CryptoInputParcel is passed via EXTRA_CRYPTO_INPUT, the CryptoInputParcel is created
- * internally and is NOT meant to be used by signing operations before adding signature time
*/
public class NfcOperationActivity extends BaseNfcActivity {
@@ -84,8 +79,8 @@ public class NfcOperationActivity extends BaseNfcActivity {
@Override
protected void initTheme() {
mThemeChanger = new ThemeChanger(this);
- mThemeChanger.setThemes(R.style.Theme_Keychain_Light_Dialog_SecurityToken,
- R.style.Theme_Keychain_Dark_Dialog_SecurityToken);
+ mThemeChanger.setThemes(R.style.Theme_Keychain_Light_Dialog,
+ R.style.Theme_Keychain_Dark_Dialog);
mThemeChanger.changeTheme();
}
@@ -101,13 +96,6 @@ public class NfcOperationActivity extends BaseNfcActivity {
mInputParcel = getIntent().getParcelableExtra(EXTRA_CRYPTO_INPUT);
- if (mInputParcel == null) {
- // for compatibility when used from OpenPgpService
- // (or any place other than CryptoOperationHelper)
- // NOTE: This CryptoInputParcel cannot be used for signing without adding signature time
- mInputParcel = new CryptoInputParcel();
- }
-
setTitle(R.string.nfc_text);
vAnimator = (ViewAnimator) findViewById(R.id.view_animator);
@@ -163,9 +151,8 @@ public class NfcOperationActivity extends BaseNfcActivity {
break;
}
case NFC_SIGN: {
- if (mInputParcel.getSignatureTime() == null) {
- mInputParcel.addSignatureTime(new Date());
- }
+ mInputParcel.addSignatureTime(mRequiredInput.mSignatureTime);
+
for (int i = 0; i < mRequiredInput.mInputData.length; i++) {
byte[] hash = mRequiredInput.mInputData[i];
int algo = mRequiredInput.mSignAlgos[i];
@@ -240,7 +227,7 @@ public class NfcOperationActivity extends BaseNfcActivity {
throw new IOException("Inappropriate key flags for smart card key.");
}
- // TODO: Is this really needed?
+ // TODO: Is this really used anywhere?
mInputParcel.addCryptoData(subkeyBytes, cardSerialNumber);
}
@@ -261,15 +248,13 @@ public class NfcOperationActivity extends BaseNfcActivity {
protected void onNfcPostExecute() throws IOException {
if (mServiceIntent != null) {
// if we're triggered by OpenPgpService
+ // save updated cryptoInputParcel in cache
CryptoInputParcelCacheService.addCryptoInputParcel(this, mServiceIntent, mInputParcel);
- mServiceIntent.putExtra(EXTRA_CRYPTO_INPUT,
- getIntent().getParcelableExtra(EXTRA_CRYPTO_INPUT));
setResult(RESULT_OK, mServiceIntent);
} else {
Intent result = new Intent();
+ // send back the CryptoInputParcel we received
result.putExtra(RESULT_CRYPTO_INPUT, mInputParcel);
- // send back the CryptoInputParcel we receive, to conform with the pattern in
- // CryptoOperationHelper
setResult(RESULT_OK, result);
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/OrbotRequiredDialogActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/OrbotRequiredDialogActivity.java
index d1c247a76..0e70cda14 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/OrbotRequiredDialogActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/OrbotRequiredDialogActivity.java
@@ -18,12 +18,22 @@
package org.sufficientlysecure.keychain.ui;
+import android.app.ProgressDialog;
import android.content.Intent;
import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.os.Messenger;
+import android.os.RemoteException;
import android.support.v4.app.FragmentActivity;
+import android.view.ContextThemeWrapper;
+import org.sufficientlysecure.keychain.Constants;
+import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.compatibility.DialogFragmentWorkaround;
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
+import org.sufficientlysecure.keychain.ui.util.ThemeChanger;
+import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.ParcelableProxy;
import org.sufficientlysecure.keychain.util.orbot.OrbotHelper;
@@ -34,8 +44,14 @@ import org.sufficientlysecure.keychain.util.orbot.OrbotHelper;
public class OrbotRequiredDialogActivity extends FragmentActivity
implements OrbotHelper.DialogActions {
+ public static final int MESSAGE_ORBOT_STARTED = 1;
+ public static final int MESSAGE_ORBOT_IGNORE = 2;
+ public static final int MESSAGE_DIALOG_CANCEL = 3;
+
// if suppplied and true will start Orbot directly without showing dialog
public static final String EXTRA_START_ORBOT = "start_orbot";
+ // used for communicating results when triggered from a service
+ public static final String EXTRA_MESSENGER = "messenger";
// to provide any previous crypto input into which proxy preference is merged
public static final String EXTRA_CRYPTO_INPUT = "extra_crypto_input";
@@ -43,6 +59,9 @@ public class OrbotRequiredDialogActivity extends FragmentActivity
public static final String RESULT_CRYPTO_INPUT = "result_crypto_input";
private CryptoInputParcel mCryptoInputParcel;
+ private Messenger mMessenger;
+
+ private ProgressDialog mShowOrbotProgressDialog;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -54,9 +73,16 @@ public class OrbotRequiredDialogActivity extends FragmentActivity
mCryptoInputParcel = new CryptoInputParcel();
}
+ mMessenger = getIntent().getParcelableExtra(EXTRA_MESSENGER);
+
boolean startOrbotDirect = getIntent().getBooleanExtra(EXTRA_START_ORBOT, false);
if (startOrbotDirect) {
- OrbotHelper.bestPossibleOrbotStart(this, this);
+ ContextThemeWrapper theme = ThemeChanger.getDialogThemeWrapper(this);
+ mShowOrbotProgressDialog = new ProgressDialog(theme);
+ mShowOrbotProgressDialog.setTitle(R.string.progress_starting_orbot);
+ mShowOrbotProgressDialog.setCancelable(false);
+ mShowOrbotProgressDialog.show();
+ OrbotHelper.bestPossibleOrbotStart(this, this, false);
} else {
showDialog();
}
@@ -84,13 +110,32 @@ public class OrbotRequiredDialogActivity extends FragmentActivity
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case OrbotHelper.START_TOR_RESULT: {
- onOrbotStarted(); // assumption that orbot was started, no way to tell for sure
+ dismissOrbotProgressDialog();
+ // unfortunately, this result is returned immediately and not when Orbot is started
+ // 10s is approximately the longest time Orbot has taken to start
+ new Handler().postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ onOrbotStarted(); // assumption that orbot was started
+ }
+ }, 10000);
}
}
}
+ /**
+ * for when Orbot is started without showing the dialog by the EXTRA_START_ORBOT intent extra
+ */
+ private void dismissOrbotProgressDialog() {
+ if (mShowOrbotProgressDialog != null) {
+ mShowOrbotProgressDialog.dismiss();
+ }
+ }
+
@Override
public void onOrbotStarted() {
+ dismissOrbotProgressDialog();
+ sendMessage(MESSAGE_ORBOT_STARTED);
Intent intent = new Intent();
// send back unmodified CryptoInputParcel for a retry
intent.putExtra(RESULT_CRYPTO_INPUT, mCryptoInputParcel);
@@ -100,6 +145,7 @@ public class OrbotRequiredDialogActivity extends FragmentActivity
@Override
public void onNeutralButton() {
+ sendMessage(MESSAGE_ORBOT_IGNORE);
Intent intent = new Intent();
mCryptoInputParcel.addParcelableProxy(ParcelableProxy.getForNoProxy());
intent.putExtra(RESULT_CRYPTO_INPUT, mCryptoInputParcel);
@@ -109,6 +155,19 @@ public class OrbotRequiredDialogActivity extends FragmentActivity
@Override
public void onCancel() {
+ sendMessage(MESSAGE_DIALOG_CANCEL);
finish();
}
+
+ private void sendMessage(int what) {
+ if (mMessenger != null) {
+ Message msg = Message.obtain();
+ msg.what = what;
+ try {
+ mMessenger.send(msg);
+ } catch (RemoteException e) {
+ Log.e(Constants.TAG, "Could not deliver message", e);
+ }
+ }
+ }
} \ No newline at end of file
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java
index d7224bd04..e71349880 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java
@@ -71,6 +71,7 @@ import org.sufficientlysecure.keychain.util.Preferences;
* internally and is NOT meant to be used by signing operations before adding a signature time
*/
public class PassphraseDialogActivity extends FragmentActivity {
+
public static final String RESULT_CRYPTO_INPUT = "result_data";
public static final String EXTRA_REQUIRED_INPUT = "required_input";
@@ -261,6 +262,9 @@ public class PassphraseDialogActivity extends FragmentActivity {
case DIVERT_TO_CARD:
message = getString(R.string.yubikey_pin_for, userId);
break;
+ // special case: empty passphrase just returns the empty passphrase
+ case PASSPHRASE_EMPTY:
+ finishCaching(new Passphrase(""));
default:
throw new AssertionError("Unhandled SecretKeyType (should not happen)");
}
@@ -280,51 +284,42 @@ public class PassphraseDialogActivity extends FragmentActivity {
mPassphraseText.setText(message);
- if (keyType == CanonicalizedSecretKey.SecretKeyType.PATTERN) {
- // start pattern dialog and show progress circle here...
-// Intent patternActivity = new Intent(getActivity(), LockPatternActivity.class);
-// patternActivity.putExtra(LockPatternActivity.EXTRA_PATTERN, "123");
-// startActivityForResult(patternActivity, REQUEST_CODE_ENTER_PATTERN);
- mInput.setVisibility(View.INVISIBLE);
- mProgress.setVisibility(View.VISIBLE);
- } else {
- // Hack to open keyboard.
- // This is the only method that I found to work across all Android versions
- // http://turbomanage.wordpress.com/2012/05/02/show-soft-keyboard-automatically-when-edittext-receives-focus/
- // Notes: * onCreateView can't be used because we want to add buttons to the dialog
- // * opening in onActivityCreated does not work on Android 4.4
- mPassphraseEditText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
- @Override
- public void onFocusChange(View v, boolean hasFocus) {
- mPassphraseEditText.post(new Runnable() {
- @Override
- public void run() {
- if (getActivity() == null || mPassphraseEditText == null) {
- return;
- }
- InputMethodManager imm = (InputMethodManager) getActivity()
- .getSystemService(Context.INPUT_METHOD_SERVICE);
- imm.showSoftInput(mPassphraseEditText, InputMethodManager.SHOW_IMPLICIT);
+ // Hack to open keyboard.
+ // This is the only method that I found to work across all Android versions
+ // http://turbomanage.wordpress.com/2012/05/02/show-soft-keyboard-automatically-when-edittext-receives-focus/
+ // Notes: * onCreateView can't be used because we want to add buttons to the dialog
+ // * opening in onActivityCreated does not work on Android 4.4
+ mPassphraseEditText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
+ @Override
+ public void onFocusChange(View v, boolean hasFocus) {
+ mPassphraseEditText.post(new Runnable() {
+ @Override
+ public void run() {
+ if (getActivity() == null || mPassphraseEditText == null) {
+ return;
}
- });
- }
- });
- mPassphraseEditText.requestFocus();
-
- mPassphraseEditText.setImeActionLabel(getString(android.R.string.ok), EditorInfo.IME_ACTION_DONE);
- mPassphraseEditText.setOnEditorActionListener(this);
-
- if ((keyType == CanonicalizedSecretKey.SecretKeyType.DIVERT_TO_CARD && Preferences.getPreferences(activity).useNumKeypadForYubiKeyPin())
- || keyType == CanonicalizedSecretKey.SecretKeyType.PIN) {
- mPassphraseEditText.setInputType(InputType.TYPE_CLASS_NUMBER);
- mPassphraseEditText.setTransformationMethod(PasswordTransformationMethod.getInstance());
- } else {
- mPassphraseEditText.setRawInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
+ InputMethodManager imm = (InputMethodManager) getActivity()
+ .getSystemService(Context.INPUT_METHOD_SERVICE);
+ imm.showSoftInput(mPassphraseEditText, InputMethodManager.SHOW_IMPLICIT);
+ }
+ });
}
+ });
+ mPassphraseEditText.requestFocus();
+ mPassphraseEditText.setImeActionLabel(getString(android.R.string.ok), EditorInfo.IME_ACTION_DONE);
+ mPassphraseEditText.setOnEditorActionListener(this);
+
+ if ((keyType == CanonicalizedSecretKey.SecretKeyType.DIVERT_TO_CARD && Preferences.getPreferences(activity).useNumKeypadForYubiKeyPin())
+ || keyType == CanonicalizedSecretKey.SecretKeyType.PIN) {
+ mPassphraseEditText.setInputType(InputType.TYPE_CLASS_NUMBER);
mPassphraseEditText.setTransformationMethod(PasswordTransformationMethod.getInstance());
+ } else {
+ mPassphraseEditText.setRawInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
}
+ mPassphraseEditText.setTransformationMethod(PasswordTransformationMethod.getInstance());
+
AlertDialog dialog = alert.create();
dialog.setButton(DialogInterface.BUTTON_POSITIVE,
activity.getString(R.string.btn_unlock), (DialogInterface.OnClickListener) null);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseWizardActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseWizardActivity.java
deleted file mode 100644
index e55494145..000000000
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseWizardActivity.java
+++ /dev/null
@@ -1,577 +0,0 @@
-/*
- * Copyright (C) 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;
-
-import android.annotation.TargetApi;
-import android.support.v7.app.AlertDialog;
-import android.app.PendingIntent;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.nfc.FormatException;
-import android.nfc.NdefMessage;
-import android.nfc.NdefRecord;
-import android.nfc.NfcAdapter;
-import android.nfc.Tag;
-import android.nfc.tech.Ndef;
-import android.os.Build;
-import android.os.Bundle;
-import android.provider.Settings;
-import android.support.v4.app.Fragment;
-import android.support.v4.app.FragmentActivity;
-import android.support.v4.app.FragmentTransaction;
-import android.text.TextUtils;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.EditText;
-import android.widget.TextView;
-import android.widget.Toast;
-
-import org.sufficientlysecure.keychain.Constants;
-import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.util.Log;
-
-import java.io.IOException;
-import java.io.UnsupportedEncodingException;
-import java.security.SecureRandom;
-import java.util.Arrays;
-import java.util.List;
-
-@TargetApi(Build.VERSION_CODES.HONEYCOMB)
-public class PassphraseWizardActivity extends FragmentActivity {
-//public class PassphraseWizardActivity extends FragmentActivity implements LockPatternView.OnPatternListener {
- //create or authenticate
- public String selectedAction;
- //for lockpattern
- public static char[] pattern;
- private static String passphrase = "";
- //nfc string
- private static byte[] output = new byte[8];
-
- public static final String CREATE_METHOD = "create";
- public static final String AUTHENTICATION = "authenticate";
-
- NfcAdapter adapter;
- PendingIntent pendingIntent;
- IntentFilter writeTagFilters[];
- boolean writeMode;
- Tag myTag;
- boolean writeNFC = false;
- boolean readNFC = false;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- if (getActionBar() != null) {
- getActionBar().setTitle(R.string.unlock_method);
- }
-
- selectedAction = getIntent().getAction();
- if (savedInstanceState == null) {
- SelectMethods selectMethods = new SelectMethods();
- FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
- transaction.add(R.id.fragmentContainer, selectMethods).commit();
- }
- setContentView(R.layout.passphrase_wizard);
-
- adapter = NfcAdapter.getDefaultAdapter(this);
- if (adapter != null) {
- pendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, PassphraseWizardActivity.class).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
- IntentFilter tagDetected = new IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED);
- tagDetected.addCategory(Intent.CATEGORY_DEFAULT);
- writeTagFilters = new IntentFilter[]{tagDetected};
- }
- }
-
- public void noPassphrase(View view) {
- passphrase = "";
- Toast.makeText(this, R.string.no_passphrase_set, Toast.LENGTH_SHORT).show();
- this.finish();
- }
-
- public void passphrase(View view) {
- Passphrase passphrase = new Passphrase();
- FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
- transaction.replace(R.id.fragmentContainer, passphrase).addToBackStack(null).commit();
- }
-
- public void startLockpattern(View view) {
- if (getActionBar() != null) {
- getActionBar().setTitle(R.string.draw_lockpattern);
- }
-// LockPatternFragmentOld lpf = LockPatternFragmentOld.newInstance(selectedAction);
-// LockPatternFragment lpf = LockPatternFragment.newInstance("asd");
-
-// FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
-// transaction.replace(R.id.fragmentContainer, lpf).addToBackStack(null).commit();
- }
-
- public void cancel(View view) {
- this.finish();
- }
-
- public void savePassphrase(View view) {
- EditText passphrase = (EditText) findViewById(R.id.passphrase);
- passphrase.setError(null);
- String pw = passphrase.getText().toString();
- //check and save passphrase
- if (selectedAction.equals(CREATE_METHOD)) {
- EditText passphraseAgain = (EditText) findViewById(R.id.passphraseAgain);
- passphraseAgain.setError(null);
- String pwAgain = passphraseAgain.getText().toString();
-
- if (!TextUtils.isEmpty(pw)) {
- if (!TextUtils.isEmpty(pwAgain)) {
- if (pw.equals(pwAgain)) {
- PassphraseWizardActivity.passphrase = pw;
- Toast.makeText(this, getString(R.string.passphrase_saved), Toast.LENGTH_SHORT).show();
- this.finish();
- } else {
- passphrase.setError(getString(R.string.passphrase_invalid));
- passphrase.requestFocus();
- }
- } else {
- passphraseAgain.setError(getString(R.string.missing_passphrase));
- passphraseAgain.requestFocus();
- }
- } else {
- passphrase.setError(getString(R.string.missing_passphrase));
- passphrase.requestFocus();
- }
- }
- //check for right passphrase
- if (selectedAction.equals(AUTHENTICATION)) {
- if (pw.equals(PassphraseWizardActivity.passphrase)) {
- Toast.makeText(this, getString(R.string.unlocked), Toast.LENGTH_SHORT).show();
- this.finish();
- } else {
- passphrase.setError(getString(R.string.passphrase_invalid));
- passphrase.requestFocus();
- }
- }
- }
-
- public void NFC(View view) {
- if (adapter != null) {
- if (getActionBar() != null) {
- getActionBar().setTitle(R.string.nfc_title);
- }
- NFCFragment nfc = new NFCFragment();
- FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
- transaction.replace(R.id.fragmentContainer, nfc).addToBackStack(null).commit();
-
- //if you want to create a new method or just authenticate
- if (CREATE_METHOD.equals(selectedAction)) {
- writeNFC = true;
- } else if (AUTHENTICATION.equals(selectedAction)) {
- readNFC = true;
- }
-
- if (!adapter.isEnabled()) {
- showAlertDialog(getString(R.string.enable_nfc), true);
- }
- } else {
- showAlertDialog(getString(R.string.no_nfc_support), false);
- }
- }
-
- @Override
- protected void onNewIntent(Intent intent) {
- if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(intent.getAction())) {
- myTag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
-
- if (writeNFC && CREATE_METHOD.equals(selectedAction)) {
- //write new password on NFC tag
- try {
- if (myTag != null) {
- write(myTag);
- writeNFC = false; //just write once
- Toast.makeText(this, R.string.nfc_write_succesful, Toast.LENGTH_SHORT).show();
- //advance to lockpattern
-// LockPatternFragmentOld lpf = LockPatternFragmentOld.newInstance(selectedAction);
-// FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
-// transaction.replace(R.id.fragmentContainer, lpf).addToBackStack(null).commit();
- }
- } catch (IOException | FormatException e) {
- Log.e(Constants.TAG, "Failed to write on NFC tag", e);
- }
-
- } else if (readNFC && AUTHENTICATION.equals(selectedAction)) {
- //read pw from NFC tag
- try {
- if (myTag != null) {
- //if tag detected, read tag
- String pwtag = read(myTag);
- if (output != null && pwtag.equals(output.toString())) {
-
- //passwort matches, go to next view
- Toast.makeText(this, R.string.passphrases_match + "!", Toast.LENGTH_SHORT).show();
-
-// LockPatternFragmentOld lpf = LockPatternFragmentOld.newInstance(selectedAction);
-// FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
-// transaction.replace(R.id.fragmentContainer, lpf).addToBackStack(null).commit();
- readNFC = false; //just once
- } else {
- //passwort doesnt match
- TextView nfc = (TextView) findViewById(R.id.nfcText);
- nfc.setText(R.string.nfc_wrong_tag);
- }
- }
- } catch (IOException | FormatException e) {
- Log.e(Constants.TAG, "Failed to read NFC tag", e);
- }
- }
- }
- }
-
- private void write(Tag tag) throws IOException, FormatException {
- //generate new random key and write them on the tag
- SecureRandom sr = new SecureRandom();
- sr.nextBytes(output);
- NdefRecord[] records = {createRecord(output.toString())};
- NdefMessage message = new NdefMessage(records);
- Ndef ndef = Ndef.get(tag);
- ndef.connect();
- ndef.writeNdefMessage(message);
- ndef.close();
- }
-
- private String read(Tag tag) throws IOException, FormatException {
- //read string from tag
- String password = null;
- Ndef ndef = Ndef.get(tag);
- ndef.connect();
- NdefMessage ndefMessage = ndef.getCachedNdefMessage();
-
- NdefRecord[] records = ndefMessage.getRecords();
- for (NdefRecord ndefRecord : records) {
- if (ndefRecord.getTnf() == NdefRecord.TNF_WELL_KNOWN && Arrays.equals(ndefRecord.getType(), NdefRecord.RTD_TEXT)) {
- try {
- password = readText(ndefRecord);
- } catch (UnsupportedEncodingException e) {
- Log.e(Constants.TAG, "Failed to read password from tag", e);
- }
- }
- }
- ndef.close();
- return password;
- }
-
- private String readText(NdefRecord record) throws UnsupportedEncodingException {
- //low-level method for reading nfc
- byte[] payload = record.getPayload();
- String textEncoding = ((payload[0] & 128) == 0) ? "UTF-8" : "UTF-16";
- int languageCodeLength = payload[0] & 0063;
- return new String(payload, languageCodeLength + 1, payload.length - languageCodeLength - 1, textEncoding);
- }
-
- private NdefRecord createRecord(String text) throws UnsupportedEncodingException {
- //low-level method for writing nfc
- String lang = "en";
- byte[] textBytes = text.getBytes();
- byte[] langBytes = lang.getBytes("US-ASCII");
- int langLength = langBytes.length;
- int textLength = textBytes.length;
- byte[] payload = new byte[1 + langLength + textLength];
-
- // set status byte (see NDEF spec for actual bits)
- payload[0] = (byte) langLength;
- // copy langbytes and textbytes into payload
- System.arraycopy(langBytes, 0, payload, 1, langLength);
- System.arraycopy(textBytes, 0, payload, 1 + langLength, textLength);
- return new NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_TEXT, new byte[0], payload);
- }
-
- public void showAlertDialog(String message, boolean nfc) {
- //This method shows an AlertDialog
- AlertDialog.Builder alert = new AlertDialog.Builder(this);
- alert.setTitle("Information").setMessage(message).setPositiveButton("Ok",
- new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialogInterface, int i) {
- }
- }
- );
- if (nfc) {
-
- alert.setNeutralButton(R.string.nfc_settings,
- new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialogInterface, int i) {
- startActivity(new Intent(Settings.ACTION_NFC_SETTINGS));
- }
- }
- );
- }
- alert.show();
- }
-
- @Override
- public void onPause() {
- //pause this app and free nfc intent
- super.onPause();
- if (adapter != null) {
- WriteModeOff();
- }
- }
-
- @Override
- public void onResume() {
- //resume this app and get nfc intent
- super.onResume();
- if (adapter != null) {
- WriteModeOn();
- }
- }
-
- private void WriteModeOn() {
- //enable nfc for this view
- writeMode = true;
- adapter.enableForegroundDispatch(this, pendingIntent, writeTagFilters, null);
- }
-
- private void WriteModeOff() {
- //disable nfc for this view
- writeMode = false;
- adapter.disableForegroundDispatch(this);
- }
-
- public static class SelectMethods extends Fragment {
-// private OnFragmentInteractionListener mListener;
-
- /**
- * Use this factory method to create a new instance of
- * this fragment using the provided parameters.
- */
- public SelectMethods() {
-
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- }
-
- @Override
- public void onResume() {
- super.onResume();
- if (getActivity().getActionBar() != null) {
- getActivity().getActionBar().setTitle(R.string.unlock_method);
- }
- }
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
- // Inflate the layout for this fragment
- return inflater.inflate(R.layout.passphrase_wizard_fragment_select_methods, container, false);
- }
-
-// @Override
-// public void onAttach(Activity activity) {
-// super.onAttach(activity);
-// try {
-// mListener = (OnFragmentInteractionListener) activity;
-// } catch (ClassCastException e) {
-// throw new ClassCastException(activity.toString()
-// + " must implement OnFragmentInteractionListener");
-// }
-// }
-//
-// @Override
-// public void onDetach() {
-// super.onDetach();
-// mListener = null;
-// }
-
- /**
- * This interface must be implemented by activities that contain this
- * fragment to allow an interaction in this fragment to be communicated
- * to the activity and potentially other fragments contained in that
- * activity.
- * <p/>
- * See the Android Training lesson <a href=
- * "http://developer.android.com/training/basics/fragments/communicating.html"
- * >Communicating with Other Fragments</a> for more information.
- */
-// public static interface OnFragmentInteractionListener {
-// public void onFragmentInteraction(Uri uri);
-// }
-
- }
-
-
- // /**
-// * A simple {@link android.support.v4.app.Fragment} subclass.
-// * Activities that contain this fragment must implement the
-// * {@link com.haibison.android.lockpattern.Passphrase.OnFragmentInteractionListener} interface
-// * to handle interaction events.
-// */
- public static class Passphrase extends Fragment {
-
-// private OnFragmentInteractionListener mListener;
-
- public Passphrase() {
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- }
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
- // Inflate the layout for this fragment
- View view = inflater.inflate(R.layout.passphrase_wizard_fragment_passphrase, container, false);
- EditText passphraseAgain = (EditText) view.findViewById(R.id.passphraseAgain);
- TextView passphraseText = (TextView) view.findViewById(R.id.passphraseText);
- TextView passphraseTextAgain = (TextView) view.findViewById(R.id.passphraseTextAgain);
- String selectedAction = getActivity().getIntent().getAction();
- if (selectedAction.equals(AUTHENTICATION)) {
- passphraseAgain.setVisibility(View.GONE);
- passphraseTextAgain.setVisibility(View.GONE);
- passphraseText.setText(R.string.enter_passphrase);
-// getActivity().getActionBar().setTitle(R.string.enter_passphrase);
- } else if (selectedAction.equals(CREATE_METHOD)) {
- passphraseAgain.setVisibility(View.VISIBLE);
- passphraseTextAgain.setVisibility(View.VISIBLE);
- passphraseText.setText(R.string.passphrase);
-// getActivity().getActionBar().setTitle(R.string.set_passphrase);
- }
- return view;
- }
-
-// @Override
-// public void onAttach(Activity activity) {
-// super.onAttach(activity);
-// try {
-// mListener = (OnFragmentInteractionListener) activity;
-// } catch (ClassCastException e) {
-// throw new ClassCastException(activity.toString()
-// + " must implement OnFragmentInteractionListener");
-// }
-// }
-//
-// @Override
-// public void onDetach() {
-// super.onDetach();
-// mListener = null;
-// }
-
-// /**
-// * This interface must be implemented by activities that contain this
-// * fragment to allow an interaction in this fragment to be communicated
-// * to the activity and potentially other fragments contained in that
-// * activity.
-// * <p/>
-// * See the Android Training lesson <a href=
-// * "http://developer.android.com/training/basics/fragments/communicating.html"
-// * >Communicating with Other Fragments</a> for more information.
-// */
-// public interface OnFragmentInteractionListener {
-// public void onFragmentInteraction(Uri uri);
-// }
- }
-
-
- /**
- * A simple {@link android.support.v4.app.Fragment} subclass.
- * Activities that contain this fragment must implement the
- * interface
- * to handle interaction events.
- * Use the method to
- * create an instance of this fragment.
- */
- public static class NFCFragment extends Fragment {
- // TODO: Rename parameter arguments, choose names that match
- // the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
- private static final String ARG_PARAM1 = "param1";
- private static final String ARG_PARAM2 = "param2";
-
- // TODO: Rename and change types of parameters
- private String mParam1;
- private String mParam2;
-
-// private OnFragmentInteractionListener mListener;
-
- /**
- * Use this factory method to create a new instance of
- * this fragment using the provided parameters.
- *
- * @param param1 Parameter 1.
- * @param param2 Parameter 2.
- * @return A new instance of fragment SelectMethods.
- */
- // TODO: Rename and change types and number of parameters
- public static NFCFragment newInstance(String param1, String param2) {
- NFCFragment fragment = new NFCFragment();
- Bundle args = new Bundle();
- args.putString(ARG_PARAM1, param1);
- args.putString(ARG_PARAM2, param2);
- fragment.setArguments(args);
- return fragment;
- }
-
- public NFCFragment() {
- // Required empty public constructor
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- if (getArguments() != null) {
- mParam1 = getArguments().getString(ARG_PARAM1);
- mParam2 = getArguments().getString(ARG_PARAM2);
- }
- }
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
- // Inflate the layout for this fragment
- return inflater.inflate(R.layout.passphrase_wizard_fragment_nfc, container, false);
- }
-
-// // TODO: Rename method, update argument and hook method into UI event
-// public void onButtonPressed(Uri uri) {
-// if (mListener != null) {
-// mListener.onFragmentInteraction(uri);
-// }
-// }
-
-// @Override
-// public void onAttach(Activity activity) {
-// super.onAttach(activity);
-// try {
-// mListener = (OnFragmentInteractionListener) activity;
-// } catch (ClassCastException e) {
-// throw new ClassCastException(activity.toString()
-// + " must implement OnFragmentInteractionListener");
-// }
-// }
-
-
-// @Override
-// public void onDetach() {
-// super.onDetach();
-// mListener = null;
-// }
- }
-
-}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsActivity.java
index c18156428..eb9ee05af 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsActivity.java
@@ -18,11 +18,12 @@
package org.sufficientlysecure.keychain.ui;
-import android.annotation.TargetApi;
+import android.accounts.Account;
+import android.accounts.AccountManager;
import android.app.Activity;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
-import android.os.Build;
import android.os.Bundle;
import android.preference.CheckBoxPreference;
import android.preference.EditTextPreference;
@@ -31,6 +32,8 @@ import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.preference.PreferenceFragment;
import android.preference.PreferenceScreen;
+import android.preference.SwitchPreference;
+import android.provider.ContactsContract;
import android.support.v7.widget.Toolbar;
import android.text.TextUtils;
import android.view.View;
@@ -74,7 +77,7 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
String action = getIntent().getAction();
- if (action != null && action.equals(ACTION_PREFS_CLOUD)) {
+ if (ACTION_PREFS_CLOUD.equals(action)) {
addPreferencesFromResource(R.xml.cloud_search_prefs);
mKeyServerPreference = (PreferenceScreen) findPreference(Constants.Pref.KEY_SERVERS);
@@ -91,14 +94,14 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
}
});
initializeSearchKeyserver(
- (CheckBoxPreference) findPreference(Constants.Pref.SEARCH_KEYSERVER)
+ (SwitchPreference) findPreference(Constants.Pref.SEARCH_KEYSERVER)
);
initializeSearchKeybase(
- (CheckBoxPreference) findPreference(Constants.Pref.SEARCH_KEYBASE)
+ (SwitchPreference) findPreference(Constants.Pref.SEARCH_KEYBASE)
);
- } else if (action != null && action.equals(ACTION_PREFS_ADV)) {
- addPreferencesFromResource(R.xml.adv_preferences);
+ } else if (ACTION_PREFS_ADV.equals(action)) {
+ addPreferencesFromResource(R.xml.passphrase_preferences);
initializePassphraseCacheSubs(
(CheckBoxPreference) findPreference(Constants.Pref.PASSPHRASE_CACHE_SUBS));
@@ -112,7 +115,7 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
initializeUseNumKeypadForYubiKeyPin(
(CheckBoxPreference) findPreference(Constants.Pref.USE_NUMKEYPAD_FOR_YUBIKEY_PIN));
- } else if (action != null && action.equals(ACTION_PREFS_GUI)) {
+ } else if (ACTION_PREFS_GUI.equals(action)) {
addPreferencesFromResource(R.xml.gui_preferences);
initializeTheme((ListPreference) findPreference(Constants.Pref.THEME));
@@ -192,10 +195,10 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
}
});
initializeSearchKeyserver(
- (CheckBoxPreference) findPreference(Constants.Pref.SEARCH_KEYSERVER)
+ (SwitchPreference) findPreference(Constants.Pref.SEARCH_KEYSERVER)
);
initializeSearchKeybase(
- (CheckBoxPreference) findPreference(Constants.Pref.SEARCH_KEYBASE)
+ (SwitchPreference) findPreference(Constants.Pref.SEARCH_KEYBASE)
);
}
@@ -219,14 +222,14 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
/**
* This fragment shows the PIN/password preferences
*/
- public static class AdvancedPrefsFragment extends PreferenceFragment {
+ public static class PassphrasePrefsFragment extends PreferenceFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Load the preferences from an XML resource
- addPreferencesFromResource(R.xml.adv_preferences);
+ addPreferencesFromResource(R.xml.passphrase_preferences);
initializePassphraseCacheSubs(
(CheckBoxPreference) findPreference(Constants.Pref.PASSPHRASE_CACHE_SUBS));
@@ -253,8 +256,8 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
}
public static class Initializer {
- private CheckBoxPreference mUseTor;
- private CheckBoxPreference mUseNormalProxy;
+ private SwitchPreference mUseTor;
+ private SwitchPreference mUseNormalProxy;
private EditTextPreference mProxyHost;
private EditTextPreference mProxyPort;
private ListPreference mProxyType;
@@ -290,8 +293,8 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
mActivity.addPreferencesFromResource(R.xml.proxy_prefs);
}
- mUseTor = (CheckBoxPreference) automaticallyFindPreference(Constants.Pref.USE_TOR_PROXY);
- mUseNormalProxy = (CheckBoxPreference) automaticallyFindPreference(Constants.Pref.USE_NORMAL_PROXY);
+ mUseTor = (SwitchPreference) automaticallyFindPreference(Constants.Pref.USE_TOR_PROXY);
+ mUseNormalProxy = (SwitchPreference) automaticallyFindPreference(Constants.Pref.USE_NORMAL_PROXY);
mProxyHost = (EditTextPreference) automaticallyFindPreference(Constants.Pref.PROXY_HOST);
mProxyPort = (EditTextPreference) automaticallyFindPreference(Constants.Pref.PROXY_PORT);
mProxyType = (ListPreference) automaticallyFindPreference(Constants.Pref.PROXY_TYPE);
@@ -467,11 +470,121 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
}
}
+ /**
+ * This fragment shows the keyserver/contacts sync preferences
+ */
+ public static class SyncPrefsFragment extends PreferenceFragment {
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Load the preferences from an XML resource
+ addPreferencesFromResource(R.xml.sync_preferences);
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ // this needs to be done in onResume since the user can change sync values from Android
+ // settings and we need to reflect that change when the user navigates back
+ AccountManager manager = AccountManager.get(getActivity());
+ final Account account = manager.getAccountsByType(Constants.ACCOUNT_TYPE)[0];
+ // for keyserver sync
+ initializeSyncCheckBox(
+ (SwitchPreference) findPreference(Constants.Pref.SYNC_KEYSERVER),
+ account,
+ Constants.PROVIDER_AUTHORITY
+ );
+ // for contacts sync
+ initializeSyncCheckBox(
+ (SwitchPreference) findPreference(Constants.Pref.SYNC_CONTACTS),
+ account,
+ ContactsContract.AUTHORITY
+ );
+ }
+
+ private void initializeSyncCheckBox(final SwitchPreference syncCheckBox,
+ final Account account,
+ final String authority) {
+ boolean syncEnabled = ContentResolver.getSyncAutomatically(account, authority);
+ syncCheckBox.setChecked(syncEnabled);
+ setSummary(syncCheckBox, authority, syncEnabled);
+
+ syncCheckBox.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ boolean syncEnabled = (Boolean) newValue;
+ if (syncEnabled) {
+ ContentResolver.setSyncAutomatically(account, authority, true);
+ } else {
+ // disable syncs
+ ContentResolver.setSyncAutomatically(account, authority, false);
+ // cancel any ongoing/pending syncs
+ ContentResolver.cancelSync(account, authority);
+ }
+ setSummary(syncCheckBox, authority, syncEnabled);
+ return true;
+ }
+ });
+ }
+
+ private void setSummary(SwitchPreference syncCheckBox, String authority,
+ boolean checked) {
+ switch (authority) {
+ case Constants.PROVIDER_AUTHORITY: {
+ if (checked) {
+ syncCheckBox.setSummary(R.string.label_sync_settings_keyserver_summary_on);
+ } else {
+ syncCheckBox.setSummary(R.string.label_sync_settings_keyserver_summary_off);
+ }
+ break;
+ }
+ case ContactsContract.AUTHORITY: {
+ if (checked) {
+ syncCheckBox.setSummary(R.string.label_sync_settings_contacts_summary_on);
+ } else {
+ syncCheckBox.setSummary(R.string.label_sync_settings_contacts_summary_off);
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ /**
+ * This fragment shows experimental features
+ */
+ public static class ExperimentalPrefsFragment extends PreferenceFragment {
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Load the preferences from an XML resource
+ addPreferencesFromResource(R.xml.experimental_preferences);
+
+ initializeExperimentalEnableWordConfirm(
+ (SwitchPreference) findPreference(Constants.Pref.EXPERIMENTAL_ENABLE_WORD_CONFIRM));
+
+ initializeExperimentalEnableLinkedIdentities(
+ (SwitchPreference) findPreference(Constants.Pref.EXPERIMENTAL_ENABLE_LINKED_IDENTITIES));
+
+ initializeExperimentalEnableKeybase(
+ (SwitchPreference) findPreference(Constants.Pref.EXPERIMENTAL_ENABLE_KEYBASE));
+
+ initializeTheme((ListPreference) findPreference(Constants.Pref.THEME));
+
+ }
+ }
+
protected boolean isValidFragment(String fragmentName) {
- return AdvancedPrefsFragment.class.getName().equals(fragmentName)
+ return PassphrasePrefsFragment.class.getName().equals(fragmentName)
|| CloudSearchPrefsFragment.class.getName().equals(fragmentName)
|| ProxyPrefsFragment.class.getName().equals(fragmentName)
|| GuiPrefsFragment.class.getName().equals(fragmentName)
+ || SyncPrefsFragment.class.getName().equals(fragmentName)
+ || ExperimentalPrefsFragment.class.getName().equals(fragmentName)
|| super.isValidFragment(fragmentName);
}
@@ -502,11 +615,13 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
private static void initializeTheme(final ListPreference mTheme) {
mTheme.setValue(sPreferences.getTheme());
- mTheme.setSummary(mTheme.getEntry());
+ mTheme.setSummary(mTheme.getEntry() + "\n"
+ + mTheme.getContext().getString(R.string.label_experimental_settings_theme_summary));
mTheme.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
public boolean onPreferenceChange(Preference preference, Object newValue) {
mTheme.setValue((String) newValue);
- mTheme.setSummary(mTheme.getEntry());
+ mTheme.setSummary(mTheme.getEntry() + "\n"
+ + mTheme.getContext().getString(R.string.label_experimental_settings_theme_summary));
sPreferences.setTheme((String) newValue);
((SettingsActivity) mTheme.getContext()).recreate();
@@ -516,7 +631,7 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
});
}
- private static void initializeSearchKeyserver(final CheckBoxPreference mSearchKeyserver) {
+ private static void initializeSearchKeyserver(final SwitchPreference mSearchKeyserver) {
Preferences.CloudSearchPrefs prefs = sPreferences.getCloudSearchPrefs();
mSearchKeyserver.setChecked(prefs.searchKeyserver);
mSearchKeyserver.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
@@ -529,7 +644,7 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
});
}
- private static void initializeSearchKeybase(final CheckBoxPreference mSearchKeybase) {
+ private static void initializeSearchKeybase(final SwitchPreference mSearchKeybase) {
Preferences.CloudSearchPrefs prefs = sPreferences.getCloudSearchPrefs();
mSearchKeybase.setChecked(prefs.searchKeybase);
mSearchKeybase.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
@@ -571,4 +686,37 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
}
});
}
+
+ private static void initializeExperimentalEnableWordConfirm(final SwitchPreference mExperimentalEnableWordConfirm) {
+ mExperimentalEnableWordConfirm.setChecked(sPreferences.getExperimentalEnableWordConfirm());
+ mExperimentalEnableWordConfirm.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ mExperimentalEnableWordConfirm.setChecked((Boolean) newValue);
+ sPreferences.setExperimentalEnableWordConfirm((Boolean) newValue);
+ return false;
+ }
+ });
+ }
+
+ private static void initializeExperimentalEnableLinkedIdentities(final SwitchPreference mExperimentalEnableLinkedIdentities) {
+ mExperimentalEnableLinkedIdentities.setChecked(sPreferences.getExperimentalEnableLinkedIdentities());
+ mExperimentalEnableLinkedIdentities.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ mExperimentalEnableLinkedIdentities.setChecked((Boolean) newValue);
+ sPreferences.setExperimentalEnableLinkedIdentities((Boolean) newValue);
+ return false;
+ }
+ });
+ }
+
+ private static void initializeExperimentalEnableKeybase(final SwitchPreference mExperimentalKeybase) {
+ mExperimentalKeybase.setChecked(sPreferences.getExperimentalEnableKeybase());
+ mExperimentalKeybase.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ mExperimentalKeybase.setChecked((Boolean) newValue);
+ sPreferences.setExperimentalEnableKeybase((Boolean) newValue);
+ return false;
+ }
+ });
+ }
}
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 f61ada84f..7dd92c45f 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsKeyServerActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsKeyServerActivity.java
@@ -19,6 +19,7 @@ package org.sufficientlysecure.keychain.ui;
import android.content.Intent;
import android.os.Bundle;
+import android.view.MenuItem;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.ui.base.BaseActivity;
@@ -34,6 +35,19 @@ public class SettingsKeyServerActivity extends BaseActivity {
Intent intent = getIntent();
String servers[] = intent.getStringArrayExtra(EXTRA_KEY_SERVERS);
loadFragment(savedInstanceState, servers);
+
+ getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ finish();
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
}
@Override
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java
index 1d0e085da..930c1fc26 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java
@@ -18,6 +18,11 @@
package org.sufficientlysecure.keychain.ui;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+
import android.animation.ArgbEvaluator;
import android.animation.ObjectAnimator;
import android.annotation.SuppressLint;
@@ -32,6 +37,9 @@ import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.provider.ContactsContract;
+import android.support.design.widget.AppBarLayout;
+import android.support.design.widget.CollapsingToolbarLayout;
+import android.support.design.widget.FloatingActionButton;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.LoaderManager;
@@ -45,14 +53,13 @@ import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.Animation.AnimationListener;
import android.view.animation.AnimationUtils;
+import android.widget.FrameLayout;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
-import com.getbase.floatingactionbutton.FloatingActionButton;
-
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing;
@@ -65,8 +72,10 @@ import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.service.ImportKeyringParcel;
+import org.sufficientlysecure.keychain.ui.ViewKeyFragment.PostponeType;
import org.sufficientlysecure.keychain.ui.base.BaseNfcActivity;
import org.sufficientlysecure.keychain.ui.base.CryptoOperationHelper;
+import org.sufficientlysecure.keychain.ui.linked.LinkedIdWizard;
import org.sufficientlysecure.keychain.ui.util.FormattingUtils;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils.State;
@@ -80,8 +89,6 @@ import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.NfcHelper;
import org.sufficientlysecure.keychain.util.Preferences;
-import java.io.IOException;
-import java.util.ArrayList;
public class ViewKeyActivity extends BaseNfcActivity implements
LoaderManager.LoaderCallbacks<Cursor>,
@@ -97,6 +104,7 @@ public class ViewKeyActivity extends BaseNfcActivity implements
static final int REQUEST_DELETE = 4;
public static final String EXTRA_DISPLAY_RESULT = "display_result";
+ public static final String EXTRA_LINKED_TRANSITION = "linked_transition";
ProviderHelper mProviderHelper;
@@ -107,16 +115,17 @@ public class ViewKeyActivity extends BaseNfcActivity implements
private ArrayList<ParcelableKeyRing> mKeyList;
private CryptoOperationHelper<ImportKeyringParcel, ImportKeyResult> mOperationHelper;
- private TextView mName;
private TextView mStatusText;
private ImageView mStatusImage;
- private RelativeLayout mBigToolbar;
+ private AppBarLayout mAppBarLayout;
+ private CollapsingToolbarLayout mCollapsingToolbarLayout;
private ImageButton mActionEncryptFile;
private ImageButton mActionEncryptText;
private ImageButton mActionNfc;
private FloatingActionButton mFab;
private ImageView mPhoto;
+ private FrameLayout mPhotoLayout;
private ImageView mQrCode;
private CardView mQrCodeLayout;
@@ -156,16 +165,17 @@ public class ViewKeyActivity extends BaseNfcActivity implements
setTitle(null);
- mName = (TextView) findViewById(R.id.view_key_name);
mStatusText = (TextView) findViewById(R.id.view_key_status);
mStatusImage = (ImageView) findViewById(R.id.view_key_status_image);
- mBigToolbar = (RelativeLayout) findViewById(R.id.toolbar_big);
+ mAppBarLayout = (AppBarLayout) findViewById(R.id.app_bar_layout);
+ mCollapsingToolbarLayout = (CollapsingToolbarLayout) findViewById(R.id.collapsing_toolbar);
mActionEncryptFile = (ImageButton) findViewById(R.id.view_key_action_encrypt_files);
mActionEncryptText = (ImageButton) findViewById(R.id.view_key_action_encrypt_text);
mActionNfc = (ImageButton) findViewById(R.id.view_key_action_nfc);
mFab = (FloatingActionButton) findViewById(R.id.fab);
mPhoto = (ImageView) findViewById(R.id.view_key_photo);
+ mPhotoLayout = (FrameLayout) findViewById(R.id.view_key_photo_layout);
mQrCode = (ImageView) findViewById(R.id.view_key_qr_code);
mQrCodeLayout = (CardView) findViewById(R.id.view_key_qr_code_layout);
@@ -287,13 +297,26 @@ public class ViewKeyActivity extends BaseNfcActivity implements
return;
}
+ boolean linkedTransition = getIntent().getBooleanExtra(EXTRA_LINKED_TRANSITION, false);
+ if (linkedTransition && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+ postponeEnterTransition();
+ }
+
FragmentManager manager = getSupportFragmentManager();
// Create an instance of the fragment
- final ViewKeyFragment frag = ViewKeyFragment.newInstance(mDataUri);
+ final ViewKeyFragment frag = ViewKeyFragment.newInstance(mDataUri,
+ linkedTransition ? PostponeType.LINKED : PostponeType.NONE);
manager.beginTransaction()
.replace(R.id.view_key_fragment, frag)
.commit();
+ if (Preferences.getPreferences(this).getExperimentalEnableKeybase()) {
+ final ViewKeyKeybaseFragment keybaseFrag = ViewKeyKeybaseFragment.newInstance(mDataUri);
+ manager.beginTransaction()
+ .replace(R.id.view_key_keybase_fragment, keybaseFrag)
+ .commit();
+ }
+
// need to postpone loading of the yubikey fragment until after mMasterKeyId
// is available, but we mark here that this should be done
mShowYubikeyAfterCreation = true;
@@ -344,12 +367,23 @@ public class ViewKeyActivity extends BaseNfcActivity implements
}
return true;
}
+ case R.id.menu_key_view_add_linked_identity: {
+ Intent intent = new Intent(this, LinkedIdWizard.class);
+ intent.setData(mDataUri);
+ startActivity(intent);
+ finish();
+ return true;
+ }
case R.id.menu_key_view_edit: {
editKey(mDataUri);
return true;
}
case R.id.menu_key_view_certify_fingerprint: {
- certifyFingeprint(mDataUri);
+ certifyFingeprint(mDataUri, false);
+ return true;
+ }
+ case R.id.menu_key_view_certify_fingerprint_word: {
+ certifyFingeprint(mDataUri, true);
return true;
}
}
@@ -360,10 +394,19 @@ public class ViewKeyActivity extends BaseNfcActivity implements
public boolean onPrepareOptionsMenu(Menu menu) {
MenuItem editKey = menu.findItem(R.id.menu_key_view_edit);
editKey.setVisible(mIsSecret);
+
MenuItem exportKey = menu.findItem(R.id.menu_key_view_export_file);
exportKey.setVisible(mIsSecret);
+
+ MenuItem addLinked = menu.findItem(R.id.menu_key_view_add_linked_identity);
+ addLinked.setVisible(mIsSecret
+ && Preferences.getPreferences(this).getExperimentalEnableLinkedIdentities());
+
MenuItem certifyFingerprint = menu.findItem(R.id.menu_key_view_certify_fingerprint);
certifyFingerprint.setVisible(!mIsSecret && !mIsVerified && !mIsExpired && !mIsRevoked);
+ MenuItem certifyFingerprintWord = menu.findItem(R.id.menu_key_view_certify_fingerprint_word);
+ certifyFingerprintWord.setVisible(!mIsSecret && !mIsVerified && !mIsExpired && !mIsRevoked
+ && Preferences.getPreferences(this).getExperimentalEnableWordConfirm());
return true;
}
@@ -375,16 +418,17 @@ public class ViewKeyActivity extends BaseNfcActivity implements
startActivityForResult(scanQrCode, REQUEST_QR_FINGERPRINT);
}
- private void certifyFingeprint(Uri dataUri) {
+ private void certifyFingeprint(Uri dataUri, boolean enableWordConfirm) {
Intent intent = new Intent(this, CertifyFingerprintActivity.class);
intent.setData(dataUri);
+ intent.putExtra(CertifyFingerprintActivity.EXTRA_ENABLE_WORD_CONFIRM, enableWordConfirm);
startActivityForResult(intent, REQUEST_CERTIFY);
}
private void certifyImmediate() {
Intent intent = new Intent(this, CertifyKeyActivity.class);
- intent.putExtra(CertifyKeyActivity.EXTRA_KEY_IDS, new long[]{mMasterKeyId});
+ intent.putExtra(CertifyKeyActivity.EXTRA_KEY_IDS, new long[] { mMasterKeyId });
startActivityForResult(intent, REQUEST_CERTIFY);
}
@@ -413,7 +457,8 @@ public class ViewKeyActivity extends BaseNfcActivity implements
private void backupToFile() {
new ExportHelper(this).showExportKeysDialog(
- mMasterKeyId, Constants.Path.APP_DIR_FILE, true);
+ mMasterKeyId, new File(Constants.Path.APP_DIR,
+ KeyFormattingUtils.convertKeyIdToHex(mMasterKeyId) + ".sec.asc"), true);
}
private void deleteKey() {
@@ -437,13 +482,13 @@ public class ViewKeyActivity extends BaseNfcActivity implements
return;
}
- if (resultCode != Activity.RESULT_OK) {
- return;
- }
-
switch (requestCode) {
case REQUEST_QR_FINGERPRINT: {
+ if (resultCode != Activity.RESULT_OK) {
+ return;
+ }
+
// If there is an EXTRA_RESULT, that's an error. Just show it.
if (data.hasExtra(OperationResult.EXTRA_RESULT)) {
OperationResult result = data.getParcelableExtra(OperationResult.EXTRA_RESULT);
@@ -465,11 +510,19 @@ public class ViewKeyActivity extends BaseNfcActivity implements
}
case REQUEST_BACKUP: {
+ if (resultCode != Activity.RESULT_OK) {
+ return;
+ }
+
backupToFile();
return;
}
case REQUEST_CERTIFY: {
+ if (resultCode != Activity.RESULT_OK) {
+ return;
+ }
+
if (data.hasExtra(OperationResult.EXTRA_RESULT)) {
OperationResult result = data.getParcelableExtra(OperationResult.EXTRA_RESULT);
result.createNotify(this).show();
@@ -478,6 +531,10 @@ public class ViewKeyActivity extends BaseNfcActivity implements
}
case REQUEST_DELETE: {
+ if (resultCode != Activity.RESULT_OK) {
+ return;
+ }
+
setResult(RESULT_OK, data);
finish();
return;
@@ -530,7 +587,6 @@ public class ViewKeyActivity extends BaseNfcActivity implements
finish();
}
}, R.string.snack_yubikey_view).show();
-
// and if it's not found, offer import
} catch (PgpKeyNotFoundException e) {
Notify.create(this, R.string.snack_yubi_other, Notify.LENGTH_LONG,
@@ -728,9 +784,9 @@ public class ViewKeyActivity extends BaseNfcActivity implements
// get name, email, and comment from USER_ID
KeyRing.UserId mainUserId = KeyRing.splitUserId(data.getString(INDEX_USER_ID));
if (mainUserId.name != null) {
- mName.setText(mainUserId.name);
+ mCollapsingToolbarLayout.setTitle(mainUserId.name);
} else {
- mName.setText(R.string.user_id_no_name);
+ mCollapsingToolbarLayout.setTitle(getString(R.string.user_id_no_name));
}
mMasterKeyId = data.getLong(INDEX_MASTER_KEY_ID);
@@ -767,8 +823,12 @@ public class ViewKeyActivity extends BaseNfcActivity implements
}
protected void onPostExecute(Bitmap photo) {
+ if (photo == null) {
+ return;
+ }
+
mPhoto.setImageBitmap(photo);
- mPhoto.setVisibility(View.VISIBLE);
+ mPhotoLayout.setVisibility(View.VISIBLE);
}
};
@@ -781,9 +841,9 @@ public class ViewKeyActivity extends BaseNfcActivity implements
State.REVOKED, R.color.icons, true);
color = getResources().getColor(R.color.key_flag_red);
- mActionEncryptFile.setVisibility(View.GONE);
- mActionEncryptText.setVisibility(View.GONE);
- mActionNfc.setVisibility(View.GONE);
+ mActionEncryptFile.setVisibility(View.INVISIBLE);
+ mActionEncryptText.setVisibility(View.INVISIBLE);
+ mActionNfc.setVisibility(View.INVISIBLE);
mFab.setVisibility(View.GONE);
mQrCodeLayout.setVisibility(View.GONE);
} else if (mIsExpired) {
@@ -797,9 +857,9 @@ public class ViewKeyActivity extends BaseNfcActivity implements
State.EXPIRED, R.color.icons, true);
color = getResources().getColor(R.color.key_flag_red);
- mActionEncryptFile.setVisibility(View.GONE);
- mActionEncryptText.setVisibility(View.GONE);
- mActionNfc.setVisibility(View.GONE);
+ mActionEncryptFile.setVisibility(View.INVISIBLE);
+ mActionEncryptText.setVisibility(View.INVISIBLE);
+ mActionNfc.setVisibility(View.INVISIBLE);
mFab.setVisibility(View.GONE);
mQrCodeLayout.setVisibility(View.GONE);
} else if (mIsSecret) {
@@ -814,15 +874,15 @@ public class ViewKeyActivity extends BaseNfcActivity implements
mQrCodeLayout.setVisibility(View.VISIBLE);
// and place leftOf qr code
- RelativeLayout.LayoutParams nameParams = (RelativeLayout.LayoutParams)
- mName.getLayoutParams();
- // remove right margin
- nameParams.setMargins(FormattingUtils.dpToPx(this, 48), 0, 0, 0);
- if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
- nameParams.setMarginEnd(0);
- }
- nameParams.addRule(RelativeLayout.LEFT_OF, R.id.view_key_qr_code_layout);
- mName.setLayoutParams(nameParams);
+// RelativeLayout.LayoutParams nameParams = (RelativeLayout.LayoutParams)
+// mName.getLayoutParams();
+// // remove right margin
+// nameParams.setMargins(FormattingUtils.dpToPx(this, 48), 0, 0, 0);
+// if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
+// nameParams.setMarginEnd(0);
+// }
+// nameParams.addRule(RelativeLayout.LEFT_OF, R.id.view_key_qr_code_layout);
+// mName.setLayoutParams(nameParams);
RelativeLayout.LayoutParams statusParams = (RelativeLayout.LayoutParams)
mStatusText.getLayoutParams();
@@ -844,7 +904,7 @@ public class ViewKeyActivity extends BaseNfcActivity implements
}
mFab.setVisibility(View.VISIBLE);
// noinspection deprecation (no getDrawable with theme at current minApi level 15!)
- mFab.setIconDrawable(getResources().getDrawable(R.drawable.ic_repeat_white_24dp));
+ mFab.setImageDrawable(getResources().getDrawable(R.drawable.ic_repeat_white_24dp));
} else {
mActionEncryptFile.setVisibility(View.VISIBLE);
mActionEncryptText.setVisibility(View.VISIBLE);
@@ -872,22 +932,19 @@ public class ViewKeyActivity extends BaseNfcActivity implements
}
if (mPreviousColor == 0 || mPreviousColor == color) {
- mStatusBar.setBackgroundColor(getStatusBarBackgroundColor(color));
- mBigToolbar.setBackgroundColor(color);
+ mAppBarLayout.setBackgroundColor(color);
+ mCollapsingToolbarLayout.setContentScrimColor(color);
+ mCollapsingToolbarLayout.setStatusBarScrimColor(getStatusBarBackgroundColor(color));
mPreviousColor = color;
} else {
- ObjectAnimator colorFade1 =
- ObjectAnimator.ofObject(mStatusBar, "backgroundColor",
- new ArgbEvaluator(), mPreviousColor,
- getStatusBarBackgroundColor(color));
- ObjectAnimator colorFade2 =
- ObjectAnimator.ofObject(mBigToolbar, "backgroundColor",
+ ObjectAnimator colorFade =
+ ObjectAnimator.ofObject(mAppBarLayout, "backgroundColor",
new ArgbEvaluator(), mPreviousColor, color);
+ mCollapsingToolbarLayout.setContentScrimColor(color);
+ mCollapsingToolbarLayout.setStatusBarScrimColor(getStatusBarBackgroundColor(color));
- colorFade1.setDuration(1200);
- colorFade2.setDuration(1200);
- colorFade1.start();
- colorFade2.start();
+ colorFade.setDuration(1200);
+ colorFade.start();
mPreviousColor = color;
}
@@ -963,4 +1020,6 @@ public class ViewKeyActivity extends BaseNfcActivity implements
public boolean onCryptoSetProgress(String msg, int progress, int max) {
return true;
}
+
}
+
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvActivity.java
index 673092e61..edd9feec9 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvActivity.java
@@ -57,7 +57,6 @@ public class ViewKeyAdvActivity extends BaseActivity implements
public static final int TAB_IDENTITIES = 1;
public static final int TAB_SUBKEYS = 2;
public static final int TAB_CERTS = 3;
- public static final int TAB_KEYBASE = 4;
// view
private ViewPager mViewPager;
@@ -140,11 +139,6 @@ public class ViewKeyAdvActivity extends BaseActivity implements
adapter.addTab(ViewKeyAdvCertsFragment.class,
certsBundle, getString(R.string.key_view_tab_certs));
- Bundle trustBundle = new Bundle();
- trustBundle.putParcelable(ViewKeyTrustFragment.ARG_DATA_URI, dataUri);
- adapter.addTab(ViewKeyTrustFragment.class,
- trustBundle, getString(R.string.key_view_tab_keybase));
-
// update layout after operations
mSlidingTabLayout.setViewPager(mViewPager);
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvUserIdsFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvUserIdsFragment.java
index 7bfebaf62..ad437f924 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvUserIdsFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvUserIdsFragment.java
@@ -133,7 +133,7 @@ public class ViewKeyAdvUserIdsFragment extends LoaderFragment implements
case LOADER_ID_USER_IDS: {
Uri baseUri = UserPackets.buildUserIdsUri(mDataUri);
return new CursorLoader(getActivity(), baseUri,
- UserIdsAdapter.USER_IDS_PROJECTION, null, null, null);
+ UserIdsAdapter.USER_PACKETS_PROJECTION, null, null, null);
}
default:
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyFragment.java
index a929d52f0..7be695de0 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyFragment.java
@@ -18,52 +18,73 @@
package org.sufficientlysecure.keychain.ui;
+
+import java.io.IOException;
+import java.util.List;
+
+import android.annotation.TargetApi;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.net.Uri;
+import android.os.Build;
+import android.os.Build.VERSION_CODES;
import android.os.Bundle;
+import android.os.Handler;
import android.provider.ContactsContract;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.support.v7.widget.CardView;
+import android.transition.Fade;
+import android.transition.Transition;
+import android.transition.TransitionInflater;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.*;
+import android.view.ViewTreeObserver;
+import android.view.ViewTreeObserver.OnPreDrawListener;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemClickListener;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.ListView;
+import android.widget.TextView;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.compatibility.DialogFragmentWorkaround;
import org.sufficientlysecure.keychain.provider.KeychainContract;
+import org.sufficientlysecure.keychain.ui.adapter.LinkedIdsAdapter;
import org.sufficientlysecure.keychain.ui.adapter.UserIdsAdapter;
import org.sufficientlysecure.keychain.ui.dialog.UserIdInfoDialogFragment;
+import org.sufficientlysecure.keychain.ui.linked.LinkedIdViewFragment;
+import org.sufficientlysecure.keychain.ui.linked.LinkedIdViewFragment.OnIdentityLoadedListener;
import org.sufficientlysecure.keychain.util.ContactHelper;
import org.sufficientlysecure.keychain.util.Log;
-
-import java.util.List;
+import org.sufficientlysecure.keychain.util.Preferences;
public class ViewKeyFragment extends LoaderFragment implements
LoaderManager.LoaderCallbacks<Cursor> {
public static final String ARG_DATA_URI = "uri";
+ public static final String ARG_POSTPONE_TYPE = "postpone_type";
private ListView mUserIds;
//private ListView mLinkedSystemContact;
- boolean mIsSecret = false;
+ enum PostponeType {
+ NONE, LINKED;
+ }
- CardView mSystemContactCard;
- LinearLayout mSystemContactLayout;
- ImageView mSystemContactPicture;
- TextView mSystemContactName;
+ boolean mIsSecret = false;
private static final int LOADER_ID_UNIFIED = 0;
private static final int LOADER_ID_USER_IDS = 1;
private static final int LOADER_ID_LINKED_CONTACT = 2;
+ private static final int LOADER_ID_LINKED_IDS = 3;
private static final String LOADER_EXTRA_LINKED_CONTACT_MASTER_KEY_ID
= "loader_linked_contact_master_key_id";
@@ -71,16 +92,29 @@ public class ViewKeyFragment extends LoaderFragment implements
= "loader_linked_contact_is_secret";
private UserIdsAdapter mUserIdsAdapter;
+ private LinkedIdsAdapter mLinkedIdsAdapter;
private Uri mDataUri;
+ private PostponeType mPostponeType;
+
+ private CardView mSystemContactCard;
+ private LinearLayout mSystemContactLayout;
+ private ImageView mSystemContactPicture;
+ private TextView mSystemContactName;
+
+ private ListView mLinkedIds;
+ private CardView mLinkedIdsCard;
+ private byte[] mFingerprint;
+ private TextView mLinkedIdsExpander;
/**
* Creates new instance of this fragment
*/
- public static ViewKeyFragment newInstance(Uri dataUri) {
+ public static ViewKeyFragment newInstance(Uri dataUri, PostponeType postponeType) {
ViewKeyFragment frag = new ViewKeyFragment();
Bundle args = new Bundle();
args.putParcelable(ARG_DATA_URI, dataUri);
+ args.putInt(ARG_POSTPONE_TYPE, postponeType.ordinal());
frag.setArguments(args);
@@ -93,6 +127,11 @@ public class ViewKeyFragment extends LoaderFragment implements
View view = inflater.inflate(R.layout.view_key_fragment, getContainer());
mUserIds = (ListView) view.findViewById(R.id.view_key_user_ids);
+ mLinkedIdsCard = (CardView) view.findViewById(R.id.card_linked_ids);
+
+ mLinkedIds = (ListView) view.findViewById(R.id.view_key_linked_ids);
+
+ mLinkedIdsExpander = (TextView) view.findViewById(R.id.view_key_linked_ids_expander);
mUserIds.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
@@ -100,6 +139,12 @@ public class ViewKeyFragment extends LoaderFragment implements
showUserIdInfo(position);
}
});
+ mLinkedIds.setOnItemClickListener(new OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ showLinkedId(position);
+ }
+ });
mSystemContactCard = (CardView) view.findViewById(R.id.linked_system_contact_card);
mSystemContactLayout = (LinearLayout) view.findViewById(R.id.system_contact_layout);
@@ -109,6 +154,47 @@ public class ViewKeyFragment extends LoaderFragment implements
return root;
}
+ private void showLinkedId(final int position) {
+ final LinkedIdViewFragment frag;
+ try {
+ frag = mLinkedIdsAdapter.getLinkedIdFragment(mDataUri, position, mFingerprint);
+ } catch (IOException e) {
+ e.printStackTrace();
+ return;
+ }
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+ Transition trans = TransitionInflater.from(getActivity())
+ .inflateTransition(R.transition.linked_id_card_trans);
+ // setSharedElementReturnTransition(trans);
+ setExitTransition(new Fade());
+ frag.setSharedElementEnterTransition(trans);
+ }
+
+ getFragmentManager().beginTransaction()
+ .add(R.id.view_key_fragment, frag)
+ .hide(frag)
+ .commit();
+
+ frag.setOnIdentityLoadedListener(new OnIdentityLoadedListener() {
+ @Override
+ public void onIdentityLoaded() {
+ new Handler().post(new Runnable() {
+ @Override
+ public void run() {
+ getFragmentManager().beginTransaction()
+ .show(frag)
+ .addSharedElement(mLinkedIdsCard, "card_linked_ids")
+ .remove(ViewKeyFragment.this)
+ .addToBackStack("linked_id")
+ .commit();
+ }
+ });
+ }
+ });
+
+ }
+
private void showUserIdInfo(final int position) {
if (!mIsSecret) {
final boolean isRevoked = mUserIdsAdapter.getIsRevoked(position);
@@ -129,8 +215,6 @@ public class ViewKeyFragment extends LoaderFragment implements
* Hides card if no linked system contact exists. Sets name, picture
* and onClickListener for the linked system contact's layout.
* In the case of a secret key, "me" (own profile) contact details are loaded.
- *
- * @param contactId
*/
private void loadLinkedSystemContact(final long contactId) {
// contact doesn't exist, stop
@@ -188,7 +272,6 @@ public class ViewKeyFragment extends LoaderFragment implements
* ContactsContract.Contact table)
*
* @param contactId _ID for row in ContactsContract.Contacts table
- * @param context
*/
private void launchContactActivity(final long contactId, Context context) {
Intent intent = new Intent(Intent.ACTION_VIEW);
@@ -202,6 +285,7 @@ public class ViewKeyFragment extends LoaderFragment implements
super.onActivityCreated(savedInstanceState);
Uri dataUri = getArguments().getParcelable(ARG_DATA_URI);
+ mPostponeType = PostponeType.values()[getArguments().getInt(ARG_POSTPONE_TYPE, 0)];
if (dataUri == null) {
Log.e(Constants.TAG, "Data missing. Should be Uri of key!");
getActivity().finish();
@@ -225,12 +309,17 @@ public class ViewKeyFragment extends LoaderFragment implements
};
static final int INDEX_MASTER_KEY_ID = 1;
+ @SuppressWarnings("unused")
static final int INDEX_USER_ID = 2;
+ @SuppressWarnings("unused")
static final int INDEX_IS_REVOKED = 3;
+ @SuppressWarnings("unused")
static final int INDEX_IS_EXPIRED = 4;
+ @SuppressWarnings("unused")
static final int INDEX_VERIFIED = 5;
static final int INDEX_HAS_ANY_SECRET = 6;
static final int INDEX_FINGERPRINT = 7;
+ @SuppressWarnings("unused")
static final int INDEX_HAS_ENCRYPT = 8;
private static final String[] RAWCONTACT_PROJECTION = {
@@ -246,21 +335,26 @@ public class ViewKeyFragment extends LoaderFragment implements
// Prepare the loaders. Either re-connect with an existing ones,
// or start new ones.
- // TODO Is this loader the same as the one in the activity?
getLoaderManager().initLoader(LOADER_ID_UNIFIED, null, this);
}
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
- setContentShown(false);
switch (id) {
case LOADER_ID_UNIFIED: {
+ setContentShown(false, false);
Uri baseUri = KeychainContract.KeyRings.buildUnifiedKeyRingUri(mDataUri);
return new CursorLoader(getActivity(), baseUri, UNIFIED_PROJECTION, null, null, null);
}
- case LOADER_ID_USER_IDS:
+
+ case LOADER_ID_USER_IDS: {
return UserIdsAdapter.createLoader(getActivity(), mDataUri);
+ }
+
+ case LOADER_ID_LINKED_IDS: {
+ return LinkedIdsAdapter.createLoader(getActivity(), mDataUri);
+ }
//we need a separate loader for linked contact to ensure refreshing on verification
case LOADER_ID_LINKED_CONTACT: {
@@ -310,19 +404,21 @@ public class ViewKeyFragment extends LoaderFragment implements
if (data.moveToFirst()) {
mIsSecret = data.getInt(INDEX_HAS_ANY_SECRET) != 0;
+ mFingerprint = data.getBlob(INDEX_FINGERPRINT);
+ long masterKeyId = data.getLong(INDEX_MASTER_KEY_ID);
// load user ids after we know if it's a secret key
mUserIdsAdapter = new UserIdsAdapter(getActivity(), null, 0, !mIsSecret, null);
mUserIds.setAdapter(mUserIdsAdapter);
getLoaderManager().initLoader(LOADER_ID_USER_IDS, null, this);
- long masterKeyId = data.getLong(INDEX_MASTER_KEY_ID);
- // we need to load linked contact here to prevent lag introduced by loader
- // for the linked contact
- long contactId = ContactHelper.findContactId(
- getActivity().getContentResolver(),
- masterKeyId);
- loadLinkedSystemContact(contactId);
+ if (Preferences.getPreferences(getActivity()).getExperimentalEnableLinkedIdentities()) {
+ mLinkedIdsAdapter =
+ new LinkedIdsAdapter(getActivity(), null, 0, mIsSecret, mLinkedIdsExpander);
+ mLinkedIds.setAdapter(mLinkedIdsAdapter);
+ getLoaderManager().initLoader(LOADER_ID_LINKED_IDS, null, this);
+ }
+
Bundle linkedContactData = new Bundle();
linkedContactData.putLong(LOADER_EXTRA_LINKED_CONTACT_MASTER_KEY_ID, masterKeyId);
@@ -336,10 +432,28 @@ public class ViewKeyFragment extends LoaderFragment implements
}
case LOADER_ID_USER_IDS: {
+ setContentShown(true, false);
mUserIdsAdapter.swapCursor(data);
break;
}
+ case LOADER_ID_LINKED_IDS: {
+ mLinkedIdsAdapter.swapCursor(data);
+ mLinkedIdsCard.setVisibility(mLinkedIdsAdapter.getCount() > 0 ? View.VISIBLE : View.GONE);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && mPostponeType == PostponeType.LINKED) {
+ mLinkedIdsCard.getViewTreeObserver().addOnPreDrawListener(new OnPreDrawListener() {
+ @TargetApi(VERSION_CODES.LOLLIPOP)
+ @Override
+ public boolean onPreDraw() {
+ mLinkedIdsCard.getViewTreeObserver().removeOnPreDrawListener(this);
+ getActivity().startPostponedEnterTransition();
+ return true;
+ }
+ });
+ }
+ break;
+ }
+
case LOADER_ID_LINKED_CONTACT: {
if (data.moveToFirst()) {// if we have a linked contact
long contactId = data.getLong(INDEX_CONTACT_ID);
@@ -349,7 +463,6 @@ public class ViewKeyFragment extends LoaderFragment implements
}
}
- setContentShown(true);
}
/**
@@ -363,6 +476,11 @@ public class ViewKeyFragment extends LoaderFragment implements
mUserIdsAdapter.swapCursor(null);
break;
}
+ case LOADER_ID_LINKED_IDS: {
+ mLinkedIdsCard.setVisibility(View.GONE);
+ mLinkedIdsAdapter.swapCursor(null);
+ break;
+ }
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyTrustFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyKeybaseFragment.java
index 150acdc90..266633061 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyTrustFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyKeybaseFragment.java
@@ -59,14 +59,12 @@ import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
-public class ViewKeyTrustFragment extends LoaderFragment implements
+public class ViewKeyKeybaseFragment extends LoaderFragment implements
LoaderManager.LoaderCallbacks<Cursor>,
CryptoOperationHelper.Callback<KeybaseVerificationParcel, KeybaseVerificationResult> {
public static final String ARG_DATA_URI = "uri";
- private View mStartSearch;
- private TextView mTrustReadout;
private TextView mReportHeader;
private TableLayout mProofListing;
private LayoutInflater mInflater;
@@ -86,15 +84,25 @@ public class ViewKeyTrustFragment extends LoaderFragment implements
private CryptoOperationHelper<KeybaseVerificationParcel, KeybaseVerificationResult>
mKeybaseOpHelper;
+ /**
+ * Creates new instance of this fragment
+ */
+ public static ViewKeyKeybaseFragment newInstance(Uri dataUri) {
+ ViewKeyKeybaseFragment frag = new ViewKeyKeybaseFragment();
+ Bundle args = new Bundle();
+ args.putParcelable(ARG_DATA_URI, dataUri);
+
+ frag.setArguments(args);
+
+ return frag;
+ }
+
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup superContainer, Bundle savedInstanceState) {
View root = super.onCreateView(inflater, superContainer, savedInstanceState);
View view = inflater.inflate(R.layout.view_key_adv_keybase_fragment, getContainer());
mInflater = inflater;
- mTrustReadout = (TextView) view.findViewById(R.id.view_key_trust_readout);
- mStartSearch = view.findViewById(R.id.view_key_trust_search_cloud);
- mStartSearch.setEnabled(false);
mReportHeader = (TextView) view.findViewById(R.id.view_key_trust_cloud_narrative);
mProofListing = (TableLayout) view.findViewById(R.id.view_key_proof_list);
mProofVerifyHeader = view.findViewById(R.id.view_key_proof_verify_header);
@@ -157,83 +165,45 @@ public class ViewKeyTrustFragment extends LoaderFragment implements
}
boolean nothingSpecial = true;
- StringBuilder message = new StringBuilder();
// Swap the new cursor in. (The framework will take care of closing the
// old cursor once we return.)
if (data.moveToFirst()) {
- if (data.getInt(INDEX_UNIFIED_HAS_ANY_SECRET) != 0) {
- message.append(getString(R.string.key_trust_it_is_yours)).append("\n");
- nothingSpecial = false;
- } else if (data.getInt(INDEX_VERIFIED) != 0) {
- message.append(getString(R.string.key_trust_already_verified)).append("\n");
- nothingSpecial = false;
- }
+ final byte[] fp = data.getBlob(INDEX_TRUST_FINGERPRINT);
+ final String fingerprint = KeyFormattingUtils.convertFingerprintToHex(fp);
- // If this key is revoked, don’t trust it!
- if (data.getInt(INDEX_TRUST_IS_REVOKED) != 0) {
- message.append(getString(R.string.key_trust_revoked)).
- append(getString(R.string.key_trust_old_keys));
+ startSearch(fingerprint);
+ }
- nothingSpecial = false;
- } else {
- if (data.getInt(INDEX_TRUST_IS_EXPIRED) != 0) {
+ setContentShown(true);
+ }
- // if expired, don’t trust it!
- message.append(getString(R.string.key_trust_expired)).
- append(getString(R.string.key_trust_old_keys));
+ private void startSearch(final String fingerprint) {
+ final Preferences.ProxyPrefs proxyPrefs =
+ Preferences.getPreferences(getActivity()).getProxyPrefs();
- nothingSpecial = false;
- }
+ OrbotHelper.DialogActions dialogActions = new OrbotHelper.DialogActions() {
+ @Override
+ public void onOrbotStarted() {
+ new DescribeKey(proxyPrefs.parcelableProxy).execute(fingerprint);
}
- if (nothingSpecial) {
- message.append(getString(R.string.key_trust_maybe));
+ @Override
+ public void onNeutralButton() {
+ new DescribeKey(ParcelableProxy.getForNoProxy())
+ .execute(fingerprint);
}
- final byte[] fp = data.getBlob(INDEX_TRUST_FINGERPRINT);
- final String fingerprint = KeyFormattingUtils.convertFingerprintToHex(fp);
- if (fingerprint != null) {
+ @Override
+ public void onCancel() {
- mStartSearch.setEnabled(true);
- mStartSearch.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- final Preferences.ProxyPrefs proxyPrefs =
- Preferences.getPreferences(getActivity()).getProxyPrefs();
-
- OrbotHelper.DialogActions dialogActions = new OrbotHelper.DialogActions() {
- @Override
- public void onOrbotStarted() {
- mStartSearch.setEnabled(false);
- new DescribeKey(proxyPrefs.parcelableProxy).execute(fingerprint);
- }
-
- @Override
- public void onNeutralButton() {
- mStartSearch.setEnabled(false);
- new DescribeKey(ParcelableProxy.getForNoProxy())
- .execute(fingerprint);
- }
-
- @Override
- public void onCancel() {
-
- }
- };
-
- if (OrbotHelper.putOrbotInRequiredState(dialogActions, getActivity())) {
- mStartSearch.setEnabled(false);
- new DescribeKey(proxyPrefs.parcelableProxy).execute(fingerprint);
- }
- }
- });
}
- }
+ };
- mTrustReadout.setText(message);
- setContentShown(true);
+ if (OrbotHelper.putOrbotInRequiredState(dialogActions, getActivity())) {
+ new DescribeKey(proxyPrefs.parcelableProxy).execute(fingerprint);
+ }
}
/**
@@ -299,17 +269,16 @@ public class ViewKeyTrustFragment extends LoaderFragment implements
return new ResultPage(getString(R.string.key_trust_results_prefix), proofList);
}
- private SpannableStringBuilder formatSpannableString(SpannableStringBuilder proofLinks,String proofType){
+ private SpannableStringBuilder formatSpannableString(SpannableStringBuilder proofLinks, String proofType) {
//Formatting SpannableStringBuilder with String.format() causes the links to stop working.
//This method is to insert the links while reserving the links
SpannableStringBuilder ssb = new SpannableStringBuilder();
ssb.append(proofType);
- if(proofType.contains("%s")){
+ if (proofType.contains("%s")) {
int i = proofType.indexOf("%s");
- ssb.replace(i,i+2,proofLinks);
- }
- else ssb.append(proofLinks);
+ ssb.replace(i, i + 2, proofLinks);
+ } else ssb.append(proofLinks);
return ssb;
}
@@ -343,7 +312,6 @@ public class ViewKeyTrustFragment extends LoaderFragment implements
result.mHeader = getActivity().getString(R.string.key_trust_no_cloud_evidence);
}
- mStartSearch.setVisibility(View.GONE);
mReportHeader.setVisibility(View.VISIBLE);
mProofListing.setVisibility(View.VISIBLE);
mReportHeader.setText(result.mHeader);
@@ -358,22 +326,35 @@ public class ViewKeyTrustFragment extends LoaderFragment implements
text.setMovementMethod(LinkMovementMethod.getInstance());
mProofListing.addView(row);
}
-
- // mSearchReport.loadDataWithBaseURL("file:///android_res/drawable/", s, "text/html", "UTF-8", null);
}
}
private String getProofNarrative(int proofType) {
int stringIndex;
switch (proofType) {
- case Proof.PROOF_TYPE_TWITTER: stringIndex = R.string.keybase_narrative_twitter; break;
- case Proof.PROOF_TYPE_GITHUB: stringIndex = R.string.keybase_narrative_github; break;
- case Proof.PROOF_TYPE_DNS: stringIndex = R.string.keybase_narrative_dns; break;
- case Proof.PROOF_TYPE_WEB_SITE: stringIndex = R.string.keybase_narrative_web_site; break;
- case Proof.PROOF_TYPE_HACKERNEWS: stringIndex = R.string.keybase_narrative_hackernews; break;
- case Proof.PROOF_TYPE_COINBASE: stringIndex = R.string.keybase_narrative_coinbase; break;
- case Proof.PROOF_TYPE_REDDIT: stringIndex = R.string.keybase_narrative_reddit; break;
- default: stringIndex = R.string.keybase_narrative_unknown;
+ case Proof.PROOF_TYPE_TWITTER:
+ stringIndex = R.string.keybase_narrative_twitter;
+ break;
+ case Proof.PROOF_TYPE_GITHUB:
+ stringIndex = R.string.keybase_narrative_github;
+ break;
+ case Proof.PROOF_TYPE_DNS:
+ stringIndex = R.string.keybase_narrative_dns;
+ break;
+ case Proof.PROOF_TYPE_WEB_SITE:
+ stringIndex = R.string.keybase_narrative_web_site;
+ break;
+ case Proof.PROOF_TYPE_HACKERNEWS:
+ stringIndex = R.string.keybase_narrative_hackernews;
+ break;
+ case Proof.PROOF_TYPE_COINBASE:
+ stringIndex = R.string.keybase_narrative_coinbase;
+ break;
+ case Proof.PROOF_TYPE_REDDIT:
+ stringIndex = R.string.keybase_narrative_reddit;
+ break;
+ default:
+ stringIndex = R.string.keybase_narrative_unknown;
}
return getActivity().getString(stringIndex);
}
@@ -390,14 +371,22 @@ public class ViewKeyTrustFragment extends LoaderFragment implements
// which proofs do we have working verifiers for?
private boolean haveProofFor(int proofType) {
switch (proofType) {
- case Proof.PROOF_TYPE_TWITTER: return true;
- case Proof.PROOF_TYPE_GITHUB: return true;
- case Proof.PROOF_TYPE_DNS: return true;
- case Proof.PROOF_TYPE_WEB_SITE: return true;
- case Proof.PROOF_TYPE_HACKERNEWS: return true;
- case Proof.PROOF_TYPE_COINBASE: return true;
- case Proof.PROOF_TYPE_REDDIT: return true;
- default: return false;
+ case Proof.PROOF_TYPE_TWITTER:
+ return true;
+ case Proof.PROOF_TYPE_GITHUB:
+ return true;
+ case Proof.PROOF_TYPE_DNS:
+ return true;
+ case Proof.PROOF_TYPE_WEB_SITE:
+ return true;
+ case Proof.PROOF_TYPE_HACKERNEWS:
+ return true;
+ case Proof.PROOF_TYPE_COINBASE:
+ return true;
+ case Proof.PROOF_TYPE_REDDIT:
+ return true;
+ default:
+ return false;
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyAdapter.java
index 59d772d63..56d273c7c 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyAdapter.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyAdapter.java
@@ -23,6 +23,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
+import java.util.Date;
import android.content.Context;
import android.database.Cursor;
@@ -193,9 +194,9 @@ public class KeyAdapter extends CursorAdapter {
String dateTime = DateUtils.formatDateTime(context,
item.mCreation.getTime(),
DateUtils.FORMAT_SHOW_DATE
+ | DateUtils.FORMAT_SHOW_TIME
| DateUtils.FORMAT_SHOW_YEAR
| DateUtils.FORMAT_ABBREV_MONTH);
-
mCreationDate.setText(context.getString(R.string.label_key_created,
dateTime));
mCreationDate.setTextColor(textColor);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/LinkedIdsAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/LinkedIdsAdapter.java
new file mode 100644
index 000000000..5cf0e6e08
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/LinkedIdsAdapter.java
@@ -0,0 +1,238 @@
+/*
+ * Copyright (C) 2014-2015 Dominik Schürmann <dominik@dominikschuermann.de>
+ * Copyright (C) 2015 Vincent Breitmoser <v.breitmoser@mugenguild.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.sufficientlysecure.keychain.ui.adapter;
+
+import android.animation.ObjectAnimator;
+import android.app.Activity;
+import android.content.Context;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Build;
+import android.support.v4.content.CursorLoader;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import org.sufficientlysecure.keychain.Constants;
+import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.linked.LinkedAttribute;
+import org.sufficientlysecure.keychain.linked.UriAttribute;
+import org.sufficientlysecure.keychain.provider.KeychainContract.Certs;
+import org.sufficientlysecure.keychain.provider.KeychainContract.UserPackets;
+import org.sufficientlysecure.keychain.ui.linked.LinkedIdViewFragment;
+import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
+import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils.State;
+import org.sufficientlysecure.keychain.ui.util.SubtleAttentionSeeker;
+import org.sufficientlysecure.keychain.util.FilterCursorWrapper;
+
+import java.io.IOException;
+import java.util.WeakHashMap;
+
+public class LinkedIdsAdapter extends UserAttributesAdapter {
+ private final boolean mIsSecret;
+ protected LayoutInflater mInflater;
+ WeakHashMap<Integer,UriAttribute> mLinkedIdentityCache = new WeakHashMap<>();
+
+ private Cursor mUnfilteredCursor;
+
+ private TextView mExpander;
+
+ public LinkedIdsAdapter(Context context, Cursor c, int flags,
+ boolean isSecret, TextView expander) {
+ super(context, c, flags);
+ mInflater = LayoutInflater.from(context);
+ mIsSecret = isSecret;
+
+ if (expander != null) {
+ expander.setVisibility(View.GONE);
+ /* don't show an expander (maybe in some sort of advanced view?)
+ mExpander = expander;
+ mExpander.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ showUnfiltered();
+ }
+ });
+ */
+ }
+ }
+
+ @Override
+ public Cursor swapCursor(Cursor cursor) {
+ if (cursor == null) {
+ mUnfilteredCursor = null;
+ return super.swapCursor(null);
+ }
+ mUnfilteredCursor = cursor;
+ FilterCursorWrapper filteredCursor = new FilterCursorWrapper(cursor) {
+ @Override
+ public boolean isVisible(Cursor cursor) {
+ UriAttribute id = getItemAtPosition(cursor);
+ return id instanceof LinkedAttribute;
+ }
+ };
+
+ if (mExpander != null) {
+ int hidden = filteredCursor.getHiddenCount();
+ if (hidden == 0) {
+ mExpander.setVisibility(View.GONE);
+ } else {
+ mExpander.setVisibility(View.VISIBLE);
+ mExpander.setText(mContext.getResources().getQuantityString(
+ R.plurals.linked_id_expand, hidden));
+ }
+ }
+
+ return super.swapCursor(filteredCursor);
+ }
+
+ private void showUnfiltered() {
+ mExpander.setVisibility(View.GONE);
+ super.swapCursor(mUnfilteredCursor);
+ }
+
+ @Override
+ public void bindView(View view, Context context, Cursor cursor) {
+
+ ViewHolder holder = (ViewHolder) view.getTag();
+
+ if (!mIsSecret) {
+ int isVerified = cursor.getInt(INDEX_VERIFIED);
+ switch (isVerified) {
+ case Certs.VERIFIED_SECRET:
+ KeyFormattingUtils.setStatusImage(mContext, holder.vVerified,
+ null, State.VERIFIED, KeyFormattingUtils.DEFAULT_COLOR);
+ break;
+ case Certs.VERIFIED_SELF:
+ KeyFormattingUtils.setStatusImage(mContext, holder.vVerified,
+ null, State.UNVERIFIED, KeyFormattingUtils.DEFAULT_COLOR);
+ break;
+ default:
+ KeyFormattingUtils.setStatusImage(mContext, holder.vVerified,
+ null, State.INVALID, KeyFormattingUtils.DEFAULT_COLOR);
+ break;
+ }
+ }
+
+ UriAttribute id = getItemAtPosition(cursor);
+ holder.setData(mContext, id);
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+ view.setTransitionName(id.mUri.toString());
+ }
+
+ }
+
+ public UriAttribute getItemAtPosition(Cursor cursor) {
+ int rank = cursor.getInt(INDEX_RANK);
+ Log.d(Constants.TAG, "requested rank: " + rank);
+
+ UriAttribute ret = mLinkedIdentityCache.get(rank);
+ if (ret != null) {
+ Log.d(Constants.TAG, "cached!");
+ return ret;
+ }
+ Log.d(Constants.TAG, "not cached!");
+
+ try {
+ byte[] data = cursor.getBlob(INDEX_ATTRIBUTE_DATA);
+ ret = LinkedAttribute.fromAttributeData(data);
+ mLinkedIdentityCache.put(rank, ret);
+ return ret;
+ } catch (IOException e) {
+ Log.e(Constants.TAG, "could not read linked identity subpacket data", e);
+ return null;
+ }
+ }
+
+ @Override
+ public UriAttribute getItem(int position) {
+ Cursor cursor = getCursor();
+ cursor.moveToPosition(position);
+ return getItemAtPosition(cursor);
+ }
+
+ @Override
+ public View newView(Context context, Cursor cursor, ViewGroup parent) {
+ View v = mInflater.inflate(R.layout.linked_id_item, null);
+ ViewHolder holder = new ViewHolder(v);
+ v.setTag(holder);
+ return v;
+ }
+
+ // don't show revoked user ids, irrelevant for average users
+ public static final String LINKED_IDS_WHERE = UserPackets.IS_REVOKED + " = 0";
+
+ public static CursorLoader createLoader(Activity activity, Uri dataUri) {
+ Uri baseUri = UserPackets.buildLinkedIdsUri(dataUri);
+ return new CursorLoader(activity, baseUri,
+ UserIdsAdapter.USER_PACKETS_PROJECTION, LINKED_IDS_WHERE, null, null);
+ }
+
+ public LinkedIdViewFragment getLinkedIdFragment(Uri baseUri,
+ int position, byte[] fingerprint) throws IOException {
+ Cursor c = getCursor();
+ c.moveToPosition(position);
+ int rank = c.getInt(UserIdsAdapter.INDEX_RANK);
+
+ Uri dataUri = UserPackets.buildLinkedIdsUri(baseUri);
+ return LinkedIdViewFragment.newInstance(dataUri, rank, mIsSecret, fingerprint);
+ }
+
+ public static class ViewHolder {
+ final public ImageView vVerified;
+ final public ImageView vIcon;
+ final public TextView vTitle;
+ final public TextView vComment;
+
+ public ViewHolder(View view) {
+ vVerified = (ImageView) view.findViewById(R.id.linked_id_certified_icon);
+ vIcon = (ImageView) view.findViewById(R.id.linked_id_type_icon);
+ vTitle = (TextView) view.findViewById(R.id.linked_id_title);
+ vComment = (TextView) view.findViewById(R.id.linked_id_comment);
+ }
+
+ public void setData(Context context, UriAttribute id) {
+
+ vTitle.setText(id.getDisplayTitle(context));
+
+ String comment = id.getDisplayComment(context);
+ if (comment != null) {
+ vComment.setVisibility(View.VISIBLE);
+ vComment.setText(comment);
+ } else {
+ vComment.setVisibility(View.GONE);
+ }
+
+ vIcon.setImageResource(id.getDisplayIcon());
+
+ }
+
+ public void seekAttention() {
+ ObjectAnimator anim = SubtleAttentionSeeker.tintText(vComment, 1000);
+ anim.setStartDelay(200);
+ anim.start();
+ }
+
+ }
+
+}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/LinkedIdsCertAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/LinkedIdsCertAdapter.java
new file mode 100644
index 000000000..5ecd9f408
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/LinkedIdsCertAdapter.java
@@ -0,0 +1,57 @@
+package org.sufficientlysecure.keychain.ui.adapter;
+
+
+import android.app.Activity;
+import android.content.Context;
+import android.database.Cursor;
+import android.net.Uri;
+import android.support.v4.content.CursorLoader;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.CursorAdapter;
+
+import org.sufficientlysecure.keychain.provider.KeychainContract.UserPackets;
+
+
+public class LinkedIdsCertAdapter extends CursorAdapter {
+
+ public static final String[] USER_CERTS_PROJECTION = new String[]{
+ UserPackets._ID,
+ UserPackets.TYPE,
+ UserPackets.USER_ID,
+ UserPackets.ATTRIBUTE_DATA,
+ UserPackets.RANK,
+ UserPackets.VERIFIED,
+ UserPackets.IS_PRIMARY,
+ UserPackets.IS_REVOKED
+ };
+ protected static final int INDEX_ID = 0;
+ protected static final int INDEX_TYPE = 1;
+ protected static final int INDEX_USER_ID = 2;
+ protected static final int INDEX_ATTRIBUTE_DATA = 3;
+ protected static final int INDEX_RANK = 4;
+ protected static final int INDEX_VERIFIED = 5;
+ protected static final int INDEX_IS_PRIMARY = 6;
+ protected static final int INDEX_IS_REVOKED = 7;
+
+ public LinkedIdsCertAdapter(Context context, Cursor c, int flags) {
+ super(context, c, flags);
+ }
+
+ @Override
+ public void bindView(View view, Context context, Cursor cursor) {
+
+ }
+
+ @Override
+ public View newView(Context context, Cursor cursor, ViewGroup parent) {
+ return null;
+ }
+
+ public static CursorLoader createLoader(Activity activity, Uri dataUri) {
+ Uri baseUri = UserPackets.buildLinkedIdsUri(dataUri);
+ return new CursorLoader(activity, baseUri,
+ UserIdsAdapter.USER_PACKETS_PROJECTION, null, null, null);
+ }
+
+}
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 6b16e8445..b91abf076 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
@@ -171,7 +171,7 @@ public class MultiUserIdsAdapter extends CursorAdapter {
CertifyAction action = actions.get(keyId);
if (actions.get(keyId) == null) {
- actions.put(keyId, new CertifyAction(keyId, uids));
+ actions.put(keyId, new CertifyAction(keyId, uids, null));
} else {
action.mUserIds.addAll(uids);
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SelectKeyCursorAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SelectKeyCursorAdapter.java
index 4ea651bb5..f01f25200 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SelectKeyCursorAdapter.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SelectKeyCursorAdapter.java
@@ -137,9 +137,9 @@ abstract public class SelectKeyCursorAdapter extends CursorAdapter {
String dateTime = DateUtils.formatDateTime(context,
cursor.getLong(mIndexCreation) * 1000,
DateUtils.FORMAT_SHOW_DATE
+ | DateUtils.FORMAT_SHOW_TIME
| DateUtils.FORMAT_SHOW_YEAR
| DateUtils.FORMAT_ABBREV_MONTH);
-
h.creation.setText(context.getString(R.string.label_key_created, dateTime));
h.creation.setVisibility(View.VISIBLE);
} else {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserAttributesAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserAttributesAdapter.java
index 457083770..e0abaf4b0 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserAttributesAdapter.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserAttributesAdapter.java
@@ -8,22 +8,24 @@ import android.view.View;
import org.sufficientlysecure.keychain.provider.KeychainContract.UserPackets;
public abstract class UserAttributesAdapter extends CursorAdapter {
- public static final String[] USER_IDS_PROJECTION = new String[]{
+ public static final String[] USER_PACKETS_PROJECTION = new String[]{
UserPackets._ID,
UserPackets.TYPE,
UserPackets.USER_ID,
+ UserPackets.ATTRIBUTE_DATA,
UserPackets.RANK,
UserPackets.VERIFIED,
UserPackets.IS_PRIMARY,
UserPackets.IS_REVOKED
};
- protected static final int INDEX_ID = 0;
- protected static final int INDEX_TYPE = 1;
- protected static final int INDEX_USER_ID = 2;
- protected static final int INDEX_RANK = 3;
- protected static final int INDEX_VERIFIED = 4;
- protected static final int INDEX_IS_PRIMARY = 5;
- protected static final int INDEX_IS_REVOKED = 6;
+ public static final int INDEX_ID = 0;
+ public static final int INDEX_TYPE = 1;
+ public static final int INDEX_USER_ID = 2;
+ public static final int INDEX_ATTRIBUTE_DATA = 3;
+ public static final int INDEX_RANK = 4;
+ public static final int INDEX_VERIFIED = 5;
+ public static final int INDEX_IS_PRIMARY = 6;
+ public static final int INDEX_IS_REVOKED = 7;
public UserAttributesAdapter(Context context, Cursor c, int flags) {
super(context, c, flags);
@@ -46,4 +48,5 @@ public abstract class UserAttributesAdapter extends CursorAdapter {
mCursor.moveToPosition(position);
return mCursor.getInt(INDEX_VERIFIED);
}
+
}
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 e2c6b0928..0f4312dad 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
@@ -188,7 +188,7 @@ public class UserIdsAdapter extends UserAttributesAdapter {
public static CursorLoader createLoader(Activity activity, Uri dataUri) {
Uri baseUri = UserPackets.buildUserIdsUri(dataUri);
return new CursorLoader(activity, baseUri,
- UserIdsAdapter.USER_IDS_PROJECTION, USER_IDS_WHERE, null, null);
+ UserIdsAdapter.USER_PACKETS_PROJECTION, USER_IDS_WHERE, null, null);
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseActivity.java
index fcf5dc11e..aa4e7d840 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseActivity.java
@@ -30,6 +30,7 @@ import android.view.ViewGroup;
import android.widget.TextView;
import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.service.KeyserverSyncAdapterService;
import org.sufficientlysecure.keychain.ui.util.ThemeChanger;
/**
@@ -51,6 +52,7 @@ public abstract class BaseActivity extends AppCompatActivity {
@Override
protected void onResume() {
super.onResume();
+ KeyserverSyncAdapterService.cancelUpdates(this);
if (mThemeChanger.changeTheme()) {
Intent intent = getIntent();
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/CryptoOperationFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/CryptoOperationFragment.java
index 52507f3e9..de90d48fd 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/CryptoOperationFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/CryptoOperationFragment.java
@@ -18,9 +18,9 @@
package org.sufficientlysecure.keychain.ui.base;
+
import android.content.Context;
import android.content.Intent;
-import android.os.Bundle;
import android.os.Parcelable;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
@@ -50,17 +50,21 @@ import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
* @see KeychainService
*
*/
-abstract class CryptoOperationFragment<T extends Parcelable, S extends OperationResult>
+public abstract class CryptoOperationFragment<T extends Parcelable, S extends OperationResult>
extends Fragment implements CryptoOperationHelper.Callback<T, S> {
final private CryptoOperationHelper<T, S> mOperationHelper;
+ public CryptoOperationFragment() {
+ mOperationHelper = new CryptoOperationHelper<>(1, this, this, R.string.progress_processing);
+ }
+
public CryptoOperationFragment(Integer initialProgressMsg) {
mOperationHelper = new CryptoOperationHelper<>(1, this, this, initialProgressMsg);
}
- public CryptoOperationFragment() {
- mOperationHelper = new CryptoOperationHelper<>(1, this, this, R.string.progress_processing);
+ public CryptoOperationFragment(int id, Integer initialProgressMsg) {
+ mOperationHelper = new CryptoOperationHelper<>(id, this, this, initialProgressMsg);
}
@Override
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/CryptoOperationHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/CryptoOperationHelper.java
index b33128978..52c6797d5 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/CryptoOperationHelper.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/CryptoOperationHelper.java
@@ -19,6 +19,8 @@
package org.sufficientlysecure.keychain.ui.base;
+import java.util.Date;
+
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
@@ -70,9 +72,11 @@ public class CryptoOperationHelper<T extends Parcelable, S extends OperationResu
// particular helper. a request code looks as follows:
// (id << 9) + (1<<8) + REQUEST_CODE_X
// that is, starting from LSB, there are 8 bits request code, 1
- // fixed bit set, then 7 bit operator-id code. the first two
- // summands are stored in the mId for easy operation.
- private final int mId;
+ // fixed bit set, then 7 bit helper-id code. the first two
+ // summands are stored in the mHelperId for easy operation.
+ private final int mHelperId;
+ // bitmask for helperId is everything except the least 8 bits
+ public static final int HELPER_ID_BITMASK = ~0xff;
public static final int REQUEST_CODE_PASSPHRASE = 1;
public static final int REQUEST_CODE_NFC = 2;
@@ -92,7 +96,7 @@ public class CryptoOperationHelper<T extends Parcelable, S extends OperationResu
*/
public CryptoOperationHelper(int id, FragmentActivity activity, Callback<T, S> callback,
Integer progressMessageString) {
- mId = (id << 9) + (1<<8);
+ mHelperId = (id << 9) + (1<<8);
mActivity = activity;
mUseFragment = false;
mCallback = callback;
@@ -103,7 +107,7 @@ public class CryptoOperationHelper<T extends Parcelable, S extends OperationResu
* if OperationHelper is being integrated into a fragment
*/
public CryptoOperationHelper(int id, Fragment fragment, Callback<T, S> callback, Integer progressMessageString) {
- mId = (id << 9) + (1<<8);
+ mHelperId = (id << 9) + (1<<8);
mFragment = fragment;
mUseFragment = true;
mProgressMessageResource = progressMessageString;
@@ -162,9 +166,9 @@ public class CryptoOperationHelper<T extends Parcelable, S extends OperationResu
protected void startActivityForResult(Intent intent, int requestCode) {
if (mUseFragment) {
- mFragment.startActivityForResult(intent, mId + requestCode);
+ mFragment.startActivityForResult(intent, mHelperId + requestCode);
} else {
- mActivity.startActivityForResult(intent, mId + requestCode);
+ mActivity.startActivityForResult(intent, mHelperId + requestCode);
}
}
@@ -176,13 +180,13 @@ public class CryptoOperationHelper<T extends Parcelable, S extends OperationResu
public boolean handleActivityResult(int requestCode, int resultCode, Intent data) {
Log.d(Constants.TAG, "received activity result in OperationHelper");
- if ((requestCode & mId) != mId) {
+ if ((requestCode & HELPER_ID_BITMASK) != mHelperId) {
// this wasn't meant for us to handle
return false;
}
Log.d(Constants.TAG, "handling activity result in OperationHelper");
- // filter out mId from requestCode
- requestCode ^= mId;
+ // filter out mHelperId from requestCode
+ requestCode ^= mHelperId;
if (resultCode == Activity.RESULT_CANCELED) {
mCallback.onCryptoOperationCancelled();
@@ -313,7 +317,7 @@ public class CryptoOperationHelper<T extends Parcelable, S extends OperationResu
}
public void cryptoOperation() {
- cryptoOperation(new CryptoInputParcel());
+ cryptoOperation(new CryptoInputParcel(new Date()));
}
public void onHandleResult(OperationResult result) {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/FileDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/FileDialogFragment.java
index 5ef8618ce..84774ae5e 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/FileDialogFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/FileDialogFragment.java
@@ -23,6 +23,7 @@ import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
+import android.os.Build;
import android.os.Bundle;
import android.os.Message;
import android.os.Messenger;
@@ -119,14 +120,19 @@ public class FileDialogFragment extends DialogFragment {
mFilename = (EditText) view.findViewById(R.id.input);
mFilename.setText(mFile.getName());
mBrowse = (ImageButton) view.findViewById(R.id.btn_browse);
- mBrowse.setOnClickListener(new View.OnClickListener() {
- public void onClick(View v) {
- // only .asc or .gpg files
- // setting it to text/plain prevents Cynaogenmod's file manager from selecting asc
- // or gpg types!
- FileHelper.openFile(FileDialogFragment.this, Uri.fromFile(mFile), "*/*", REQUEST_CODE);
- }
- });
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
+ mBrowse.setVisibility(View.GONE);
+ } else {
+ mBrowse.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ // only .asc or .gpg files
+ // setting it to text/plain prevents Cynaogenmod's file manager from selecting asc
+ // or gpg types!
+ FileHelper.saveDocumentKitKat(
+ FileDialogFragment.this, "*/*", mFile.getName(), REQUEST_CODE);
+ }
+ });
+ }
mCheckBox = (CheckBox) view.findViewById(R.id.checkbox);
if (checkboxText == null) {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateFinalFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateFinalFragment.java
new file mode 100644
index 000000000..e09b1e755
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateFinalFragment.java
@@ -0,0 +1,225 @@
+package org.sufficientlysecure.keychain.ui.linked;
+
+
+import android.graphics.PorterDuff;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.os.Parcelable;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.TextView;
+import android.widget.ViewAnimator;
+
+import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.linked.LinkedAttribute;
+import org.sufficientlysecure.keychain.linked.LinkedTokenResource;
+import org.sufficientlysecure.keychain.operations.results.LinkedVerifyResult;
+import org.sufficientlysecure.keychain.operations.results.OperationResult;
+import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog;
+import org.sufficientlysecure.keychain.pgp.WrappedUserAttribute;
+import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
+import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
+import org.sufficientlysecure.keychain.ui.base.CryptoOperationFragment;
+import org.sufficientlysecure.keychain.ui.util.Notify;
+
+
+public abstract class LinkedIdCreateFinalFragment extends CryptoOperationFragment {
+
+ protected LinkedIdWizard mLinkedIdWizard;
+
+ private ImageView mVerifyImage;
+ private TextView mVerifyStatus;
+ private ViewAnimator mVerifyAnimator;
+
+ // This is a resource, set AFTER it has been verified
+ LinkedTokenResource mVerifiedResource = null;
+ private ViewAnimator mVerifyButtonAnimator;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ mLinkedIdWizard = (LinkedIdWizard) getActivity();
+ }
+
+ protected abstract View newView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState);
+
+ @Override @NonNull
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ final View view = newView(inflater, container, savedInstanceState);
+
+ View nextButton = view.findViewById(R.id.next_button);
+ if (nextButton != null) {
+ nextButton.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ cryptoOperation();
+ }
+ });
+ }
+
+ view.findViewById(R.id.back_button).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mLinkedIdWizard.loadFragment(null, null, LinkedIdWizard.FRAG_ACTION_TO_LEFT);
+ }
+ });
+
+ mVerifyAnimator = (ViewAnimator) view.findViewById(R.id.verify_progress);
+ mVerifyImage = (ImageView) view.findViewById(R.id.verify_image);
+ mVerifyStatus = (TextView) view.findViewById(R.id.verify_status);
+ mVerifyButtonAnimator = (ViewAnimator) view.findViewById(R.id.verify_buttons);
+
+ view.findViewById(R.id.button_verify).setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ proofVerify();
+ }
+ });
+
+ view.findViewById(R.id.button_retry).setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ proofVerify();
+ }
+ });
+
+ setVerifyProgress(false, null);
+ mVerifyStatus.setText(R.string.linked_verify_pending);
+
+ return view;
+ }
+
+ abstract LinkedTokenResource getResource(OperationLog log);
+
+ private void setVerifyProgress(boolean on, Boolean success) {
+ if (success == null) {
+ mVerifyStatus.setText(R.string.linked_verifying);
+ displayButton(on ? 2 : 0);
+ } else if (success) {
+ mVerifyStatus.setText(R.string.linked_verify_success);
+ mVerifyImage.setImageResource(R.drawable.status_signature_verified_cutout_24dp);
+ mVerifyImage.setColorFilter(getResources().getColor(R.color.android_green_dark),
+ PorterDuff.Mode.SRC_IN);
+ displayButton(2);
+ } else {
+ mVerifyStatus.setText(R.string.linked_verify_error);
+ mVerifyImage.setImageResource(R.drawable.status_signature_unknown_cutout_24dp);
+ mVerifyImage.setColorFilter(getResources().getColor(R.color.android_red_dark),
+ PorterDuff.Mode.SRC_IN);
+ displayButton(1);
+ }
+ mVerifyAnimator.setDisplayedChild(on ? 1 : 0);
+ }
+
+ public void displayButton(int button) {
+ if (mVerifyButtonAnimator.getDisplayedChild() == button) {
+ return;
+ }
+ mVerifyButtonAnimator.setDisplayedChild(button);
+ }
+
+ protected void proofVerify() {
+ setVerifyProgress(true, null);
+
+ new AsyncTask<Void,Void,LinkedVerifyResult>() {
+
+ @Override
+ protected LinkedVerifyResult doInBackground(Void... params) {
+ long timer = System.currentTimeMillis();
+
+ OperationLog log = new OperationLog();
+ LinkedTokenResource resource = getResource(log);
+ if (resource == null) {
+ return new LinkedVerifyResult(LinkedVerifyResult.RESULT_ERROR, log);
+ }
+
+ LinkedVerifyResult result = resource.verify(getActivity(), mLinkedIdWizard.mFingerprint);
+
+ // ux flow: this operation should take at last a second
+ timer = System.currentTimeMillis() -timer;
+ if (timer < 1000) try {
+ Thread.sleep(1000 -timer);
+ } catch (InterruptedException e) {
+ // never mind
+ }
+
+ if (result.success()) {
+ mVerifiedResource = resource;
+ }
+ return result;
+ }
+
+ @Override
+ protected void onPostExecute(LinkedVerifyResult result) {
+ super.onPostExecute(result);
+ if (result.success()) {
+ setVerifyProgress(false, true);
+ } else {
+ setVerifyProgress(false, false);
+ // on error, show error message
+ result.createNotify(getActivity()).show(LinkedIdCreateFinalFragment.this);
+ }
+ }
+ }.execute();
+
+ }
+
+ @Override
+ protected void cryptoOperation() {
+ if (mVerifiedResource == null) {
+ Notify.create(getActivity(), R.string.linked_need_verify, Notify.Style.ERROR)
+ .show(LinkedIdCreateFinalFragment.this);
+ return;
+ }
+
+ super.cryptoOperation();
+ }
+
+ @Override
+ protected void cryptoOperation(CryptoInputParcel cryptoInput) {
+ if (mVerifiedResource == null) {
+ Notify.create(getActivity(), R.string.linked_need_verify, Notify.Style.ERROR)
+ .show(LinkedIdCreateFinalFragment.this);
+ return;
+ }
+
+ super.cryptoOperation(cryptoInput);
+ }
+
+ @Nullable
+ @Override
+ public Parcelable createOperationInput() {
+ SaveKeyringParcel skp =
+ new SaveKeyringParcel(mLinkedIdWizard.mMasterKeyId, mLinkedIdWizard.mFingerprint);
+
+ WrappedUserAttribute ua =
+ LinkedAttribute.fromResource(mVerifiedResource).toUserAttribute();
+
+ skp.mAddUserAttribute.add(ua);
+
+ return skp;
+ }
+
+ @Override
+ public void onCryptoOperationSuccess(OperationResult result) {
+ // if bad -> display here!
+ if (!result.success()) {
+ result.createNotify(getActivity()).show(LinkedIdCreateFinalFragment.this);
+ return;
+ }
+
+ getActivity().finish();
+ }
+
+ @Override
+ public void onCryptoOperationError(OperationResult result) {
+
+ }
+
+}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateGithubFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateGithubFragment.java
new file mode 100644
index 000000000..ccb20a764
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateGithubFragment.java
@@ -0,0 +1,706 @@
+/*
+ * Copyright (C) 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.linked;
+
+
+import java.io.BufferedInputStream;
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.net.SocketTimeoutException;
+import java.net.URI;
+import java.net.URL;
+import java.util.Random;
+
+import android.app.Activity;
+import android.app.Dialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.DialogInterface.OnDismissListener;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.os.Build;
+import android.os.Build.VERSION;
+import android.os.Build.VERSION_CODES;
+import android.os.Bundle;
+import android.os.Handler;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.v4.app.ActivityOptionsCompat;
+import android.support.v4.app.FragmentActivity;
+import android.util.Base64;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.webkit.CookieManager;
+import android.webkit.WebView;
+import android.webkit.WebViewClient;
+import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.TextView;
+import android.widget.ViewAnimator;
+
+import javax.net.ssl.HttpsURLConnection;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.spongycastle.util.encoders.Hex;
+import org.sufficientlysecure.keychain.BuildConfig;
+import org.sufficientlysecure.keychain.Constants;
+import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.linked.LinkedAttribute;
+import org.sufficientlysecure.keychain.linked.resources.GithubResource;
+import org.sufficientlysecure.keychain.operations.results.EditKeyResult;
+import org.sufficientlysecure.keychain.pgp.WrappedUserAttribute;
+import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
+import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
+import org.sufficientlysecure.keychain.ui.ViewKeyActivity;
+import org.sufficientlysecure.keychain.ui.base.CryptoOperationFragment;
+import org.sufficientlysecure.keychain.ui.util.Notify;
+import org.sufficientlysecure.keychain.ui.util.Notify.Style;
+import org.sufficientlysecure.keychain.ui.widget.StatusIndicator;
+import org.sufficientlysecure.keychain.ui.widget.StatusIndicator.Status;
+import org.sufficientlysecure.keychain.util.Log;
+
+
+public class LinkedIdCreateGithubFragment extends CryptoOperationFragment<SaveKeyringParcel,EditKeyResult> {
+
+ public static final String ARG_GITHUB_COOKIE = "github_cookie";
+ private Button mRetryButton;
+
+ enum State {
+ IDLE, AUTH_PROCESS, AUTH_ERROR, POST_PROCESS, POST_ERROR, LID_PROCESS, LID_ERROR, DONE
+ }
+
+ ViewAnimator mButtonContainer;
+
+ StatusIndicator mStatus1, mStatus2, mStatus3;
+
+ byte[] mFingerprint;
+ long mMasterKeyId;
+ private SaveKeyringParcel mSaveKeyringParcel;
+ private TextView mLinkedIdTitle, mLinkedIdComment;
+ private boolean mFinishOnStop;
+
+ public static LinkedIdCreateGithubFragment newInstance() {
+ return new LinkedIdCreateGithubFragment();
+ }
+
+ public LinkedIdCreateGithubFragment() {
+ super(null);
+ }
+
+ @Override @NonNull
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ View view = inflater.inflate(R.layout.linked_create_github_fragment, container, false);
+
+ mButtonContainer = (ViewAnimator) view.findViewById(R.id.button_container);
+
+ mStatus1 = (StatusIndicator) view.findViewById(R.id.linked_status_step1);
+ mStatus2 = (StatusIndicator) view.findViewById(R.id.linked_status_step2);
+ mStatus3 = (StatusIndicator) view.findViewById(R.id.linked_status_step3);
+
+ mRetryButton = (Button) view.findViewById(R.id.button_retry);
+
+ ((ImageView) view.findViewById(R.id.linked_id_type_icon)).setImageResource(R.drawable.linked_github);
+ ((ImageView) view.findViewById(R.id.linked_id_certified_icon)).setImageResource(R.drawable.octo_link_24dp);
+ mLinkedIdTitle = (TextView) view.findViewById(R.id.linked_id_title);
+ mLinkedIdComment = (TextView) view.findViewById(R.id.linked_id_comment);
+
+ view.findViewById(R.id.back_button).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ LinkedIdWizard activity = (LinkedIdWizard) getActivity();
+ if (activity == null) {
+ return;
+ }
+ activity.loadFragment(null, null, LinkedIdWizard.FRAG_ACTION_TO_LEFT);
+ }
+ });
+
+ view.findViewById(R.id.button_send).setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ step1GetOAuthCode();
+ // for animation testing
+ // onCryptoOperationSuccess(null);
+ }
+ });
+
+ return view;
+ }
+
+ @Override
+ public void onActivityCreated(@Nullable Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+
+ LinkedIdWizard wizard = (LinkedIdWizard) getActivity();
+ mFingerprint = wizard.mFingerprint;
+ mMasterKeyId = wizard.mMasterKeyId;
+ }
+
+ private void step1GetOAuthCode() {
+
+ setState(State.AUTH_PROCESS);
+
+ mButtonContainer.setDisplayedChild(1);
+
+ new Handler().postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ oAuthRequest("github.com/login/oauth/authorize", BuildConfig.GITHUB_CLIENT_ID, "gist");
+ }
+ }, 300);
+
+ }
+
+ private void showRetryForOAuth() {
+
+ mRetryButton.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ v.setOnClickListener(null);
+ step1GetOAuthCode();
+ }
+ });
+ mButtonContainer.setDisplayedChild(3);
+
+ }
+
+ private void step1GetOAuthToken() {
+
+ if (mOAuthCode == null) {
+ setState(State.AUTH_ERROR);
+ showRetryForOAuth();
+ return;
+ }
+
+ Activity activity = getActivity();
+ if (activity == null) {
+ return;
+ }
+
+ final String gistText = GithubResource.generate(activity, mFingerprint);
+
+ new AsyncTask<Void,Void,JSONObject>() {
+
+ Exception mException;
+
+ @Override
+ protected JSONObject doInBackground(Void... dummy) {
+ try {
+
+ JSONObject params = new JSONObject();
+ params.put("client_id", BuildConfig.GITHUB_CLIENT_ID);
+ params.put("client_secret", BuildConfig.GITHUB_CLIENT_SECRET);
+ params.put("code", mOAuthCode);
+ params.put("state", mOAuthState);
+
+ return jsonHttpRequest("https://github.com/login/oauth/access_token", params, null);
+
+ } catch (IOException | HttpResultException e) {
+ mException = e;
+ } catch (JSONException e) {
+ throw new AssertionError("json error, this is a bug!");
+ }
+ return null;
+ }
+
+ @Override
+ protected void onPostExecute(JSONObject result) {
+ super.onPostExecute(result);
+
+ Activity activity = getActivity();
+ if (activity == null) {
+ // we couldn't show an error anyways
+ return;
+ }
+
+ Log.d(Constants.TAG, "response: " + result);
+
+ if (result == null || result.optString("access_token", null) == null) {
+ setState(State.AUTH_ERROR);
+ showRetryForOAuth();
+
+ if (result != null) {
+ Notify.create(activity, R.string.linked_error_auth_failed, Style.ERROR).show();
+ return;
+ }
+
+ if (mException instanceof SocketTimeoutException) {
+ Notify.create(activity, R.string.linked_error_timeout, Style.ERROR).show();
+ } else if (mException instanceof HttpResultException) {
+ Notify.create(activity, activity.getString(R.string.linked_error_http,
+ ((HttpResultException) mException).mResponse),
+ Style.ERROR).show();
+ } else if (mException instanceof IOException) {
+ Notify.create(activity, R.string.linked_error_network, Style.ERROR).show();
+ }
+
+ return;
+ }
+
+ step2PostGist(result.optString("access_token"), gistText);
+
+ }
+ }.execute();
+
+ }
+
+ private void step2PostGist(final String accessToken, final String gistText) {
+
+ setState(State.POST_PROCESS);
+
+ new AsyncTask<Void,Void,JSONObject>() {
+
+ Exception mException;
+
+ @Override
+ protected JSONObject doInBackground(Void... dummy) {
+ try {
+
+ long timer = System.currentTimeMillis();
+
+ JSONObject file = new JSONObject();
+ file.put("content", gistText);
+
+ JSONObject files = new JSONObject();
+ files.put("openpgp.txt", file);
+
+ JSONObject params = new JSONObject();
+ params.put("public", true);
+ params.put("description", getString(R.string.linked_gist_description));
+ params.put("files", files);
+
+ JSONObject result = jsonHttpRequest("https://api.github.com/gists", params, accessToken);
+
+ // ux flow: this operation should take at last a second
+ timer = System.currentTimeMillis() -timer;
+ if (timer < 1000) try {
+ Thread.sleep(1000 -timer);
+ } catch (InterruptedException e) {
+ // never mind
+ }
+
+ return result;
+
+ } catch (IOException | HttpResultException e) {
+ mException = e;
+ } catch (JSONException e) {
+ throw new AssertionError("json error, this is a bug!");
+ }
+ return null;
+ }
+
+ @Override
+ protected void onPostExecute(JSONObject result) {
+ super.onPostExecute(result);
+
+ Log.d(Constants.TAG, "response: " + result);
+
+ Activity activity = getActivity();
+ if (activity == null) {
+ // we couldn't show an error anyways
+ return;
+ }
+
+ if (result == null) {
+ setState(State.POST_ERROR);
+ showRetryForOAuth();
+
+ if (mException instanceof SocketTimeoutException) {
+ Notify.create(activity, R.string.linked_error_timeout, Style.ERROR).show();
+ } else if (mException instanceof HttpResultException) {
+ Notify.create(activity, activity.getString(R.string.linked_error_http,
+ ((HttpResultException) mException).mResponse),
+ Style.ERROR).show();
+ } else if (mException instanceof IOException) {
+ Notify.create(activity, R.string.linked_error_network, Style.ERROR).show();
+ }
+
+ return;
+ }
+
+ GithubResource resource;
+
+ try {
+ String gistId = result.getString("id");
+ JSONObject owner = result.getJSONObject("owner");
+ String gistLogin = owner.getString("login");
+
+ URI uri = URI.create("https://gist.github.com/" + gistLogin + "/" + gistId);
+ resource = GithubResource.create(uri);
+ } catch (JSONException e) {
+ setState(State.POST_ERROR);
+ return;
+ }
+
+ View linkedItem = mButtonContainer.getChildAt(2);
+ if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
+ linkedItem.setTransitionName(resource.toUri().toString());
+ }
+
+ // we only need authorization for this one operation, drop it afterwards
+ revokeToken(accessToken);
+
+ step3EditKey(resource);
+ }
+
+ }.execute();
+
+ }
+
+ private void revokeToken(final String token) {
+
+ new AsyncTask<Void,Void,Void>() {
+ @Override
+ protected Void doInBackground(Void... dummy) {
+ try {
+ HttpsURLConnection nection = (HttpsURLConnection) new URL(
+ "https://api.github.com/applications/" + BuildConfig.GITHUB_CLIENT_ID + "/tokens/" + token)
+ .openConnection();
+ nection.setRequestMethod("DELETE");
+ String encoded = Base64.encodeToString(
+ (BuildConfig.GITHUB_CLIENT_ID + ":" + BuildConfig.GITHUB_CLIENT_SECRET).getBytes(), Base64.DEFAULT);
+ nection.setRequestProperty("Authorization", "Basic " + encoded);
+ nection.connect();
+ } catch (IOException e) {
+ // nvm
+ }
+ return null;
+ }
+ }.execute();
+
+ }
+
+ private void step3EditKey(final GithubResource resource) {
+
+ // set item data while we're there
+ {
+ Context context = getActivity();
+ mLinkedIdTitle.setText(resource.getDisplayTitle(context));
+ mLinkedIdComment.setText(resource.getDisplayComment(context));
+ }
+
+ setState(State.LID_PROCESS);
+
+ new Handler().postDelayed(new Runnable() {
+ @Override
+ public void run() {
+
+ WrappedUserAttribute ua = LinkedAttribute.fromResource(resource).toUserAttribute();
+ mSaveKeyringParcel = new SaveKeyringParcel(mMasterKeyId, mFingerprint);
+ mSaveKeyringParcel.mAddUserAttribute.add(ua);
+
+ cryptoOperation();
+
+ }
+ }, 250);
+
+ }
+
+ @Nullable
+ @Override
+ public SaveKeyringParcel createOperationInput() {
+ // if this is null, the cryptoOperation silently aborts - which is what we want in that case
+ return mSaveKeyringParcel;
+ }
+
+ @Override
+ public void onCryptoOperationSuccess(EditKeyResult result) {
+
+ setState(State.DONE);
+
+ mButtonContainer.getInAnimation().setDuration(750);
+ mButtonContainer.setDisplayedChild(2);
+
+ new Handler().postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ FragmentActivity activity = getActivity();
+ Intent intent = new Intent(activity, ViewKeyActivity.class);
+ intent.setData(KeyRings.buildGenericKeyRingUri(mMasterKeyId));
+ // intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+ intent.putExtra(ViewKeyActivity.EXTRA_LINKED_TRANSITION, true);
+ View linkedItem = mButtonContainer.getChildAt(2);
+
+ Bundle options = ActivityOptionsCompat.makeSceneTransitionAnimation(
+ activity, linkedItem, linkedItem.getTransitionName()).toBundle();
+ activity.startActivity(intent, options);
+ mFinishOnStop = true;
+ } else {
+ activity.startActivity(intent);
+ activity.finish();
+ }
+ }
+ }, 1000);
+ }
+
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+
+ // cookies are automatically saved, we don't want that
+ CookieManager cookieManager = CookieManager.getInstance();
+ String cookie = cookieManager.getCookie("https://github.com/");
+ outState.putString(ARG_GITHUB_COOKIE, cookie);
+ }
+
+ @Override
+ public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+
+ if (savedInstanceState != null) {
+ String cookie = savedInstanceState.getString(ARG_GITHUB_COOKIE);
+ CookieManager cookieManager = CookieManager.getInstance();
+ cookieManager.setCookie("https://github.com/", cookie);
+ }
+ }
+
+ @Override
+ public void onDestroyView() {
+ super.onDestroyView();
+ try {
+ // cookies are automatically saved, we don't want that
+ CookieManager cookieManager = CookieManager.getInstance();
+ // noinspection deprecation (replacement is api lvl 21)
+ cookieManager.removeAllCookie();
+ } catch (Exception e) {
+ // no biggie if this fails
+ }
+ }
+
+ @Override
+ public void onStop() {
+ super.onStop();
+
+ if (mFinishOnStop) {
+ Activity activity = getActivity();
+ activity.setResult(Activity.RESULT_OK);
+ activity.finish();
+ }
+ }
+
+ @Override
+ public void onCryptoOperationError(EditKeyResult result) {
+ result.createNotify(getActivity()).show(this);
+ setState(State.LID_ERROR);
+ }
+
+ @Override
+ public void onCryptoOperationCancelled() {
+ mRetryButton.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ v.setOnClickListener(null);
+ mButtonContainer.setDisplayedChild(1);
+ setState(State.LID_PROCESS);
+ cryptoOperation();
+ }
+ });
+ mButtonContainer.setDisplayedChild(3);
+ setState(State.LID_ERROR);
+ }
+
+ private String mOAuthCode, mOAuthState;
+
+ public void oAuthRequest(String hostAndPath, String clientId, String scope) {
+
+ Activity activity = getActivity();
+ if (activity == null) {
+ return;
+ }
+
+ byte[] buf = new byte[16];
+ new Random().nextBytes(buf);
+ mOAuthState = new String(Hex.encode(buf));
+ mOAuthCode = null;
+
+ final Dialog auth_dialog = new Dialog(activity);
+ auth_dialog.setContentView(R.layout.oauth_webview);
+ WebView web = (WebView) auth_dialog.findViewById(R.id.web_view);
+ web.getSettings().setSaveFormData(false);
+ web.getSettings().setUserAgentString("OpenKeychain " + BuildConfig.VERSION_NAME);
+ web.setWebViewClient(new WebViewClient() {
+
+ @Override
+ public boolean shouldOverrideUrlLoading(WebView view, String url) {
+ Uri uri = Uri.parse(url);
+ if ("oauth-openkeychain".equals(uri.getScheme())) {
+
+ if (mOAuthCode != null) {
+ return true;
+ }
+
+ if (uri.getQueryParameter("error") != null) {
+ Log.i(Constants.TAG, "got oauth error: " + uri.getQueryParameter("error"));
+ auth_dialog.dismiss();
+ return true;
+ }
+
+ // check if mOAuthState == queryParam[state]
+ mOAuthCode = uri.getQueryParameter("code");
+
+ auth_dialog.dismiss();
+ return true;
+ }
+ // don't surf away from github!
+ if (!"github.com".equals(uri.getHost())) {
+ auth_dialog.dismiss();
+ return true;
+ }
+ return false;
+ }
+
+ });
+
+ auth_dialog.setTitle(R.string.linked_webview_title_github);
+ auth_dialog.setCancelable(true);
+ auth_dialog.setOnDismissListener(new OnDismissListener() {
+ @Override
+ public void onDismiss(DialogInterface dialog) {
+ step1GetOAuthToken();
+ }
+ });
+ auth_dialog.show();
+
+ web.loadUrl("https://" + hostAndPath +
+ "?client_id=" + clientId +
+ "&scope=" + scope +
+ "&redirect_uri=oauth-openkeychain://linked/" +
+ "&state=" + mOAuthState);
+
+ }
+
+ public void setState(State state) {
+ switch (state) {
+ case IDLE:
+ mStatus1.setDisplayedChild(Status.IDLE);
+ mStatus2.setDisplayedChild(Status.IDLE);
+ mStatus3.setDisplayedChild(Status.IDLE);
+ break;
+ case AUTH_PROCESS:
+ mStatus1.setDisplayedChild(Status.PROGRESS);
+ mStatus2.setDisplayedChild(Status.IDLE);
+ mStatus3.setDisplayedChild(Status.IDLE);
+ break;
+ case AUTH_ERROR:
+ mStatus1.setDisplayedChild(Status.ERROR);
+ mStatus2.setDisplayedChild(Status.IDLE);
+ mStatus3.setDisplayedChild(Status.IDLE);
+ break;
+ case POST_PROCESS:
+ mStatus1.setDisplayedChild(Status.OK);
+ mStatus2.setDisplayedChild(Status.PROGRESS);
+ mStatus3.setDisplayedChild(Status.IDLE);
+ break;
+ case POST_ERROR:
+ mStatus1.setDisplayedChild(Status.OK);
+ mStatus2.setDisplayedChild(Status.ERROR);
+ mStatus3.setDisplayedChild(Status.IDLE);
+ break;
+ case LID_PROCESS:
+ mStatus1.setDisplayedChild(Status.OK);
+ mStatus2.setDisplayedChild(Status.OK);
+ mStatus3.setDisplayedChild(Status.PROGRESS);
+ break;
+ case LID_ERROR:
+ mStatus1.setDisplayedChild(Status.OK);
+ mStatus2.setDisplayedChild(Status.OK);
+ mStatus3.setDisplayedChild(Status.ERROR);
+ break;
+ case DONE:
+ mStatus1.setDisplayedChild(Status.OK);
+ mStatus2.setDisplayedChild(Status.OK);
+ mStatus3.setDisplayedChild(Status.OK);
+ }
+ }
+
+ private static JSONObject jsonHttpRequest(String url, JSONObject params, String accessToken)
+ throws IOException, HttpResultException {
+
+ HttpsURLConnection nection = (HttpsURLConnection) new URL(url).openConnection();
+ nection.setDoInput(true);
+ nection.setDoOutput(true);
+ nection.setConnectTimeout(2000);
+ nection.setReadTimeout(1000);
+ nection.setRequestProperty("Content-Type", "application/json");
+ nection.setRequestProperty("Accept", "application/json");
+ nection.setRequestProperty("User-Agent", "OpenKeychain " + BuildConfig.VERSION_NAME);
+ if (accessToken != null) {
+ nection.setRequestProperty("Authorization", "token " + accessToken);
+ }
+
+ OutputStream os = nection.getOutputStream();
+ BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os, "UTF-8"));
+ writer.write(params.toString());
+ writer.flush();
+ writer.close();
+ os.close();
+
+ try {
+
+ nection.connect();
+
+ int code = nection.getResponseCode();
+ if (code != HttpsURLConnection.HTTP_CREATED && code != HttpsURLConnection.HTTP_OK) {
+ throw new HttpResultException(nection.getResponseCode(), nection.getResponseMessage());
+ }
+
+ InputStream in = new BufferedInputStream(nection.getInputStream());
+ BufferedReader reader = new BufferedReader(new InputStreamReader(in));
+ StringBuilder response = new StringBuilder();
+ while (true) {
+ String line = reader.readLine();
+ if (line == null) {
+ break;
+ }
+ response.append(line);
+ }
+
+ try {
+ return new JSONObject(response.toString());
+ } catch (JSONException e) {
+ throw new IOException(e);
+ }
+
+ } finally {
+ nection.disconnect();
+ }
+
+ }
+
+ static class HttpResultException extends Exception {
+ final int mCode;
+ final String mResponse;
+
+ HttpResultException(int code, String response) {
+ mCode = code;
+ mResponse = response;
+ }
+
+ }
+
+}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateHttpsStep1Fragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateHttpsStep1Fragment.java
new file mode 100644
index 000000000..8a05c35db
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateHttpsStep1Fragment.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 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.linked;
+
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.text.Editable;
+import android.text.TextWatcher;
+import android.util.Patterns;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.widget.EditText;
+
+import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.linked.resources.GenericHttpsResource;
+
+public class LinkedIdCreateHttpsStep1Fragment extends Fragment {
+
+ LinkedIdWizard mLinkedIdWizard;
+
+ EditText mEditUri;
+
+ public static LinkedIdCreateHttpsStep1Fragment newInstance() {
+ LinkedIdCreateHttpsStep1Fragment frag = new LinkedIdCreateHttpsStep1Fragment();
+
+ Bundle args = new Bundle();
+ frag.setArguments(args);
+
+ return frag;
+ }
+
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+
+ mLinkedIdWizard = (LinkedIdWizard) getActivity();
+
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ final View view = inflater.inflate(R.layout.linked_create_https_fragment_step1, container, false);
+
+ view.findViewById(R.id.next_button).setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+
+ String uri = "https://" + mEditUri.getText();
+
+ if (!checkUri(uri)) {
+ return;
+ }
+
+ String proofText = GenericHttpsResource.generateText(getActivity(),
+ mLinkedIdWizard.mFingerprint);
+
+ LinkedIdCreateHttpsStep2Fragment frag =
+ LinkedIdCreateHttpsStep2Fragment.newInstance(uri, proofText);
+
+ mLinkedIdWizard.loadFragment(null, frag, LinkedIdWizard.FRAG_ACTION_TO_RIGHT);
+
+ }
+ });
+
+ view.findViewById(R.id.back_button).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mLinkedIdWizard.loadFragment(null, null, LinkedIdWizard.FRAG_ACTION_TO_LEFT);
+ }
+ });
+
+ mEditUri = (EditText) view.findViewById(R.id.linked_create_https_uri);
+
+ mEditUri.addTextChangedListener(new TextWatcher() {
+ @Override
+ public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) {
+ }
+
+ @Override
+ public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) {
+ }
+
+ @Override
+ public void afterTextChanged(Editable editable) {
+ String uri = "https://" + editable;
+ if (uri.length() > 0) {
+ if (checkUri(uri)) {
+ mEditUri.setCompoundDrawablesWithIntrinsicBounds(0, 0,
+ R.drawable.ic_stat_retyped_ok, 0);
+ } else {
+ mEditUri.setCompoundDrawablesWithIntrinsicBounds(0, 0,
+ R.drawable.ic_stat_retyped_bad, 0);
+ }
+ } else {
+ // remove drawable if email is empty
+ mEditUri.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
+ }
+ }
+ });
+
+ // mEditUri.setText("mugenguild.com/pgpkey.txt");
+
+ return view;
+ }
+
+ private static boolean checkUri(String uri) {
+ return Patterns.WEB_URL.matcher(uri).matches();
+ }
+
+}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateHttpsStep2Fragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateHttpsStep2Fragment.java
new file mode 100644
index 000000000..22a201ba3
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateHttpsStep2Fragment.java
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 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.linked;
+
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Environment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.widget.EditText;
+
+import org.sufficientlysecure.keychain.Constants;
+import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog;
+import org.sufficientlysecure.keychain.linked.resources.GenericHttpsResource;
+import org.sufficientlysecure.keychain.ui.util.Notify;
+import org.sufficientlysecure.keychain.ui.util.Notify.Style;
+import org.sufficientlysecure.keychain.util.FileHelper;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.PrintWriter;
+import java.net.URI;
+import java.net.URISyntaxException;
+
+public class LinkedIdCreateHttpsStep2Fragment extends LinkedIdCreateFinalFragment {
+
+ private static final int REQUEST_CODE_OUTPUT = 0x00007007;
+
+ public static final String ARG_URI = "uri", ARG_TEXT = "text";
+
+ EditText mEditUri;
+
+ URI mResourceUri;
+ String mResourceString;
+
+ public static LinkedIdCreateHttpsStep2Fragment newInstance
+ (String uri, String proofText) {
+
+ LinkedIdCreateHttpsStep2Fragment frag = new LinkedIdCreateHttpsStep2Fragment();
+
+ Bundle args = new Bundle();
+ args.putString(ARG_URI, uri);
+ args.putString(ARG_TEXT, proofText);
+ frag.setArguments(args);
+
+ return frag;
+ }
+
+ @Override
+ GenericHttpsResource getResource(OperationLog log) {
+ return GenericHttpsResource.createNew(mResourceUri);
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ try {
+ mResourceUri = new URI(getArguments().getString(ARG_URI));
+ } catch (URISyntaxException e) {
+ e.printStackTrace();
+ getActivity().finish();
+ }
+
+ mResourceString = getArguments().getString(ARG_TEXT);
+
+ }
+
+ protected View newView(LayoutInflater inflater,
+ ViewGroup container, Bundle savedInstanceState) {
+ return inflater.inflate(R.layout.linked_create_https_fragment_step2, container, false);
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ View view = super.onCreateView(inflater, container, savedInstanceState);
+
+ if (view != null) {
+
+ view.findViewById(R.id.button_send).setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ proofSend();
+ }
+ });
+
+ view.findViewById(R.id.button_save).setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ proofSave();
+ }
+ });
+
+ mEditUri = (EditText) view.findViewById(R.id.linked_create_https_uri);
+ mEditUri.setText(mResourceUri.toString());
+ }
+
+ return view;
+ }
+
+ private void proofSend () {
+ Intent sendIntent = new Intent();
+ sendIntent.setAction(Intent.ACTION_SEND);
+ sendIntent.putExtra(Intent.EXTRA_TEXT, mResourceString);
+ sendIntent.setType("text/plain");
+ startActivity(sendIntent);
+ }
+
+ private void proofSave () {
+ String state = Environment.getExternalStorageState();
+ if (!Environment.MEDIA_MOUNTED.equals(state)) {
+ Notify.create(getActivity(), "External storage not available!", Style.ERROR);
+ return;
+ }
+
+ String targetName = "pgpkey.txt";
+
+ FileHelper.saveDocument(this,
+ targetName, Uri.fromFile(new File(Constants.Path.APP_DIR, targetName)),
+ "text/plain", R.string.title_decrypt_to_file, R.string.specify_file_to_decrypt_to,
+ REQUEST_CODE_OUTPUT);
+ }
+
+ private void saveFile(Uri uri) {
+ try {
+ PrintWriter out =
+ new PrintWriter(getActivity().getContentResolver().openOutputStream(uri));
+ out.print(mResourceString);
+ if (out.checkError()) {
+ Notify.create(getActivity(), "Error writing file!", Style.ERROR).show();
+ }
+ } catch (FileNotFoundException e) {
+ Notify.create(getActivity(), "File could not be opened for writing!", Style.ERROR).show();
+ }
+ }
+
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ switch (requestCode) {
+ // For saving a file
+ case REQUEST_CODE_OUTPUT:
+ if (data == null) {
+ return;
+ }
+ Uri uri = data.getData();
+ saveFile(uri);
+ break;
+ default:
+ super.onActivityResult(requestCode, resultCode, data);
+ }
+ }
+
+}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateTwitterStep1Fragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateTwitterStep1Fragment.java
new file mode 100644
index 000000000..c25f775b0
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateTwitterStep1Fragment.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 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.linked;
+
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.widget.EditText;
+
+import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.ui.util.Notify;
+
+public class LinkedIdCreateTwitterStep1Fragment extends Fragment {
+
+ LinkedIdWizard mLinkedIdWizard;
+
+ EditText mEditHandle;
+
+ public static LinkedIdCreateTwitterStep1Fragment newInstance() {
+ LinkedIdCreateTwitterStep1Fragment frag = new LinkedIdCreateTwitterStep1Fragment();
+
+ Bundle args = new Bundle();
+ frag.setArguments(args);
+
+ return frag;
+ }
+
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+
+ mLinkedIdWizard = (LinkedIdWizard) getActivity();
+
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ final View view = inflater.inflate(R.layout.linked_create_twitter_fragment_step1, container, false);
+
+ view.findViewById(R.id.next_button).setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+
+ final String handle = mEditHandle.getText().toString();
+
+ if ("".equals(handle)) {
+ mEditHandle.setError("Please input a Twitter handle!");
+ return;
+ }
+
+ new AsyncTask<Void,Void,Boolean>() {
+
+ @Override
+ protected Boolean doInBackground(Void... params) {
+ return true;
+ // return checkHandle(handle);
+ }
+
+ @Override
+ protected void onPostExecute(Boolean result) {
+ super.onPostExecute(result);
+
+ if (result == null) {
+ Notify.create(getActivity(),
+ "Connection error while checking username!",
+ Notify.Style.ERROR).show(LinkedIdCreateTwitterStep1Fragment.this);
+ return;
+ }
+
+ if (!result) {
+ Notify.create(getActivity(),
+ "This handle does not exist on Twitter!",
+ Notify.Style.ERROR).show(LinkedIdCreateTwitterStep1Fragment.this);
+ return;
+ }
+
+ LinkedIdCreateTwitterStep2Fragment frag =
+ LinkedIdCreateTwitterStep2Fragment.newInstance(handle);
+
+ mLinkedIdWizard.loadFragment(null, frag, LinkedIdWizard.FRAG_ACTION_TO_RIGHT);
+ }
+ }.execute();
+
+ }
+ });
+
+ view.findViewById(R.id.back_button).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mLinkedIdWizard.loadFragment(null, null, LinkedIdWizard.FRAG_ACTION_TO_LEFT);
+ }
+ });
+
+ mEditHandle = (EditText) view.findViewById(R.id.linked_create_twitter_handle);
+
+ return view;
+ }
+
+ /* not used at this point, too many problems
+ private static Boolean checkHandle(String handle) {
+ try {
+ HttpURLConnection nection =
+ (HttpURLConnection) new URL("https://twitter.com/" + handle).openConnection();
+ nection.setRequestMethod("HEAD");
+ nection.setRequestProperty("User-Agent", "OpenKeychain");
+ return nection.getResponseCode() == 200;
+ } catch (IOException e) {
+ return null;
+ }
+ }
+ */
+
+}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateTwitterStep2Fragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateTwitterStep2Fragment.java
new file mode 100644
index 000000000..362798bc8
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateTwitterStep2Fragment.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 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.linked;
+
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+import android.text.Html;
+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;
+import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog;
+import org.sufficientlysecure.keychain.linked.LinkedTokenResource;
+import org.sufficientlysecure.keychain.linked.resources.TwitterResource;
+
+public class LinkedIdCreateTwitterStep2Fragment extends LinkedIdCreateFinalFragment {
+
+ public static final String ARG_HANDLE = "handle";
+
+ String mResourceHandle;
+ String mResourceString;
+
+ public static LinkedIdCreateTwitterStep2Fragment newInstance
+ (String handle) {
+
+ LinkedIdCreateTwitterStep2Fragment frag = new LinkedIdCreateTwitterStep2Fragment();
+
+ Bundle args = new Bundle();
+ args.putString(ARG_HANDLE, handle);
+ frag.setArguments(args);
+
+ return frag;
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ mResourceString =
+ TwitterResource.generate(mLinkedIdWizard.mFingerprint);
+
+ mResourceHandle = getArguments().getString(ARG_HANDLE);
+
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ View view = super.onCreateView(inflater, container, savedInstanceState);
+
+ if (view != null) {
+ view.findViewById(R.id.button_send).setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ proofSend();
+ }
+ });
+
+ view.findViewById(R.id.button_share).setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ proofShare();
+ }
+ });
+
+ ((TextView) view.findViewById(R.id.linked_tweet_published)).setText(
+ Html.fromHtml(getString(R.string.linked_create_twitter_2_3, mResourceHandle))
+ );
+ }
+
+ return view;
+ }
+
+ @Override
+ LinkedTokenResource getResource(OperationLog log) {
+ return TwitterResource.searchInTwitterStream(getActivity(),
+ mResourceHandle, mResourceString, log);
+ }
+
+ @Override
+ protected View newView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ return inflater.inflate(R.layout.linked_create_twitter_fragment_step2, container, false);
+ }
+
+ private void proofShare() {
+ Intent sendIntent = new Intent();
+ sendIntent.setAction(Intent.ACTION_SEND);
+ sendIntent.putExtra(Intent.EXTRA_TEXT, mResourceString);
+ sendIntent.setType("text/plain");
+ startActivity(sendIntent);
+ }
+
+ private void proofSend() {
+
+ Uri.Builder builder = Uri.parse("https://twitter.com/intent/tweet").buildUpon();
+ builder.appendQueryParameter("text", mResourceString);
+ Uri uri = builder.build();
+
+ Intent intent = new Intent(Intent.ACTION_VIEW, uri);
+ getActivity().startActivity(intent);
+ }
+
+}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdSelectFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdSelectFragment.java
new file mode 100644
index 000000000..a17a97013
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdSelectFragment.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 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.linked;
+
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import org.sufficientlysecure.keychain.R;
+
+public class LinkedIdSelectFragment extends Fragment {
+
+ LinkedIdWizard mLinkedIdWizard;
+
+ /**
+ * Creates new instance of this fragment
+ */
+ public static LinkedIdSelectFragment newInstance() {
+ LinkedIdSelectFragment frag = new LinkedIdSelectFragment();
+
+ Bundle args = new Bundle();
+ frag.setArguments(args);
+
+ return frag;
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ View view = inflater.inflate(R.layout.linked_select_fragment, container, false);
+
+ view.findViewById(R.id.linked_create_https_button)
+ .setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ LinkedIdCreateHttpsStep1Fragment frag =
+ LinkedIdCreateHttpsStep1Fragment.newInstance();
+
+ mLinkedIdWizard.loadFragment(null, frag, LinkedIdWizard.FRAG_ACTION_TO_RIGHT);
+ }
+ });
+
+ /*
+ view.findViewById(R.id.linked_create_dns_button)
+ .setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ LinkedIdCreateDnsStep1Fragment frag =
+ LinkedIdCreateDnsStep1Fragment.newInstance();
+
+ mLinkedIdWizard.loadFragment(null, frag, LinkedIdWizard.FRAG_ACTION_TO_RIGHT);
+ }
+ });
+ */
+
+ view.findViewById(R.id.linked_create_twitter_button)
+ .setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ LinkedIdCreateTwitterStep1Fragment frag =
+ LinkedIdCreateTwitterStep1Fragment.newInstance();
+
+ mLinkedIdWizard.loadFragment(null, frag, LinkedIdWizard.FRAG_ACTION_TO_RIGHT);
+ }
+ });
+
+ view.findViewById(R.id.linked_create_github_button)
+ .setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ LinkedIdCreateGithubFragment frag =
+ LinkedIdCreateGithubFragment.newInstance();
+
+ mLinkedIdWizard.loadFragment(null, frag, LinkedIdWizard.FRAG_ACTION_TO_RIGHT);
+ }
+ });
+
+
+ return view;
+ }
+
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+
+ mLinkedIdWizard = (LinkedIdWizard) getActivity();
+ }
+
+}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdViewFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdViewFragment.java
new file mode 100644
index 000000000..5630932b4
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdViewFragment.java
@@ -0,0 +1,560 @@
+package org.sufficientlysecure.keychain.ui.linked;
+
+import java.io.IOException;
+import java.util.Collections;
+
+import android.content.Context;
+import android.content.Intent;
+import android.database.Cursor;
+import android.graphics.PorterDuff;
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Parcelable;
+import android.support.annotation.Nullable;
+import android.support.v4.app.FragmentManager;
+import android.support.v4.app.FragmentManager.OnBackStackChangedListener;
+import android.support.v4.app.LoaderManager;
+import android.support.v4.content.CursorLoader;
+import android.support.v4.content.Loader;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.TextSwitcher;
+import android.widget.TextView;
+import android.widget.ViewAnimator;
+
+import org.sufficientlysecure.keychain.Constants;
+import org.sufficientlysecure.keychain.Constants.key;
+import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.operations.results.LinkedVerifyResult;
+import org.sufficientlysecure.keychain.linked.LinkedTokenResource;
+import org.sufficientlysecure.keychain.linked.LinkedAttribute;
+import org.sufficientlysecure.keychain.linked.LinkedResource;
+import org.sufficientlysecure.keychain.linked.UriAttribute;
+import org.sufficientlysecure.keychain.operations.results.OperationResult;
+import org.sufficientlysecure.keychain.provider.KeychainContract.Certs;
+import org.sufficientlysecure.keychain.provider.KeychainContract.UserPackets;
+import org.sufficientlysecure.keychain.provider.KeychainDatabase.Tables;
+import org.sufficientlysecure.keychain.service.CertifyActionsParcel;
+import org.sufficientlysecure.keychain.service.CertifyActionsParcel.CertifyAction;
+import org.sufficientlysecure.keychain.ui.adapter.LinkedIdsAdapter;
+import org.sufficientlysecure.keychain.ui.adapter.UserIdsAdapter;
+import org.sufficientlysecure.keychain.ui.base.CryptoOperationFragment;
+import org.sufficientlysecure.keychain.ui.linked.LinkedIdViewFragment.ViewHolder.VerifyState;
+import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
+import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils.State;
+import org.sufficientlysecure.keychain.ui.util.Notify;
+import org.sufficientlysecure.keychain.ui.util.Notify.Style;
+import org.sufficientlysecure.keychain.ui.util.SubtleAttentionSeeker;
+import org.sufficientlysecure.keychain.ui.widget.CertListWidget;
+import org.sufficientlysecure.keychain.ui.widget.CertifyKeySpinner;
+import org.sufficientlysecure.keychain.util.Log;
+
+public class LinkedIdViewFragment extends CryptoOperationFragment implements
+ LoaderManager.LoaderCallbacks<Cursor>, OnBackStackChangedListener {
+
+ private static final String ARG_DATA_URI = "data_uri";
+ private static final String ARG_LID_RANK = "rank";
+ private static final String ARG_IS_SECRET = "verified";
+ private static final String ARG_FINGERPRINT = "fingerprint";
+ private static final int LOADER_ID_LINKED_ID = 1;
+
+ private UriAttribute mLinkedId;
+ private LinkedTokenResource mLinkedResource;
+ private boolean mIsSecret;
+
+ private Context mContext;
+ private byte[] mFingerprint;
+
+ private AsyncTask mInProgress;
+
+ private Uri mDataUri;
+ private ViewHolder mViewHolder;
+ private int mLidRank;
+ private OnIdentityLoadedListener mIdLoadedListener;
+ private long mCertifyKeyId;
+
+ public static LinkedIdViewFragment newInstance(Uri dataUri, int rank,
+ boolean isSecret, byte[] fingerprint) throws IOException {
+ LinkedIdViewFragment frag = new LinkedIdViewFragment();
+
+ Bundle args = new Bundle();
+ args.putParcelable(ARG_DATA_URI, dataUri);
+ args.putInt(ARG_LID_RANK, rank);
+ args.putBoolean(ARG_IS_SECRET, isSecret);
+ args.putByteArray(ARG_FINGERPRINT, fingerprint);
+ frag.setArguments(args);
+
+ return frag;
+ }
+
+ public LinkedIdViewFragment() {
+ // IMPORTANT: the id must be unique in the ViewKeyActivity CryptoOperationHelper id namespace!
+ // no initial progress message -> we handle progress ourselves!
+ super(5, null);
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ Bundle args = getArguments();
+ mDataUri = args.getParcelable(ARG_DATA_URI);
+ mLidRank = args.getInt(ARG_LID_RANK);
+
+ mIsSecret = args.getBoolean(ARG_IS_SECRET);
+ mFingerprint = args.getByteArray(ARG_FINGERPRINT);
+
+ mContext = getActivity();
+
+ getLoaderManager().initLoader(LOADER_ID_LINKED_ID, null, this);
+
+ }
+
+ @Override
+ public Loader<Cursor> onCreateLoader(int id, Bundle args) {
+ switch (id) {
+ case LOADER_ID_LINKED_ID:
+ return new CursorLoader(getActivity(), mDataUri,
+ UserIdsAdapter.USER_PACKETS_PROJECTION,
+ Tables.USER_PACKETS + "." + UserPackets.RANK
+ + " = " + Integer.toString(mLidRank), null, null);
+ default:
+ return null;
+ }
+ }
+
+ @Override
+ public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
+ switch (loader.getId()) {
+ case LOADER_ID_LINKED_ID:
+
+ // Nothing to load means break if we are *expected* to load
+ if (!cursor.moveToFirst()) {
+ if (mIdLoadedListener != null) {
+ Notify.create(getActivity(), "Error loading identity!",
+ Notify.LENGTH_LONG, Style.ERROR).show();
+ finishFragment();
+ }
+ // Or just ignore, this is probably some intermediate state during certify
+ break;
+ }
+
+ try {
+ int certStatus = cursor.getInt(UserIdsAdapter.INDEX_VERIFIED);
+
+ byte[] data = cursor.getBlob(UserIdsAdapter.INDEX_ATTRIBUTE_DATA);
+ UriAttribute linkedId = LinkedAttribute.fromAttributeData(data);
+
+ loadIdentity(linkedId, certStatus);
+
+ if (mIdLoadedListener != null) {
+ mIdLoadedListener.onIdentityLoaded();
+ mIdLoadedListener = null;
+ }
+
+ } catch (IOException e) {
+ Log.e(Constants.TAG, "error parsing identity", e);
+ Notify.create(getActivity(), "Error parsing identity!",
+ Notify.LENGTH_LONG, Style.ERROR).show();
+ finishFragment();
+ }
+
+ break;
+ }
+ }
+
+ public void finishFragment() {
+ new Handler().post(new Runnable() {
+ @Override
+ public void run() {
+ FragmentManager manager = getFragmentManager();
+ manager.removeOnBackStackChangedListener(LinkedIdViewFragment.this);
+ manager.popBackStack("linked_id", FragmentManager.POP_BACK_STACK_INCLUSIVE);
+ }
+ });
+ }
+
+ public interface OnIdentityLoadedListener {
+ void onIdentityLoaded();
+ }
+
+ public void setOnIdentityLoadedListener(OnIdentityLoadedListener listener) {
+ mIdLoadedListener = listener;
+ }
+
+ private void loadIdentity(UriAttribute linkedId, int certStatus) {
+ mLinkedId = linkedId;
+
+ if (mLinkedId instanceof LinkedAttribute) {
+ LinkedResource res = ((LinkedAttribute) mLinkedId).mResource;
+ mLinkedResource = (LinkedTokenResource) res;
+ }
+
+ if (!mIsSecret) {
+ switch (certStatus) {
+ case Certs.VERIFIED_SECRET:
+ KeyFormattingUtils.setStatusImage(mContext, mViewHolder.mLinkedIdHolder.vVerified,
+ null, State.VERIFIED, KeyFormattingUtils.DEFAULT_COLOR);
+ break;
+ case Certs.VERIFIED_SELF:
+ KeyFormattingUtils.setStatusImage(mContext, mViewHolder.mLinkedIdHolder.vVerified,
+ null, State.UNVERIFIED, KeyFormattingUtils.DEFAULT_COLOR);
+ break;
+ default:
+ KeyFormattingUtils.setStatusImage(mContext, mViewHolder.mLinkedIdHolder.vVerified,
+ null, State.INVALID, KeyFormattingUtils.DEFAULT_COLOR);
+ break;
+ }
+ } else {
+ mViewHolder.mLinkedIdHolder.vVerified.setImageResource(R.drawable.octo_link_24dp);
+ }
+
+ mViewHolder.mLinkedIdHolder.setData(mContext, mLinkedId);
+
+ setShowVerifying(false);
+
+ // no resource, nothing further we can do…
+ if (mLinkedResource == null) {
+ mViewHolder.vButtonView.setVisibility(View.GONE);
+ mViewHolder.vButtonVerify.setVisibility(View.GONE);
+ return;
+ }
+
+ if (mLinkedResource.isViewable()) {
+ mViewHolder.vButtonView.setVisibility(View.VISIBLE);
+ mViewHolder.vButtonView.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ Intent intent = mLinkedResource.getViewIntent();
+ if (intent == null) {
+ return;
+ }
+ getActivity().startActivity(intent);
+ }
+ });
+ } else {
+ mViewHolder.vButtonView.setVisibility(View.GONE);
+ }
+
+ }
+
+ @Override
+ public void onLoaderReset(Loader<Cursor> loader) {
+
+ }
+
+ static class ViewHolder {
+ private final View vButtonView;
+ private final ViewAnimator vVerifyingContainer;
+ private final ViewAnimator vItemCertified;
+ private final View vKeySpinnerContainer;
+ LinkedIdsAdapter.ViewHolder mLinkedIdHolder;
+
+ private ViewAnimator vButtonSwitcher;
+ private CertListWidget vLinkedCerts;
+ private CertifyKeySpinner vKeySpinner;
+ private final View vButtonVerify;
+ private final View vButtonRetry;
+ private final View vButtonConfirm;
+
+ private final ViewAnimator vProgress;
+ private final TextSwitcher vText;
+
+ ViewHolder(View root) {
+ vLinkedCerts = (CertListWidget) root.findViewById(R.id.linked_id_certs);
+ vKeySpinner = (CertifyKeySpinner) root.findViewById(R.id.cert_key_spinner);
+ vKeySpinnerContainer = root.findViewById(R.id.cert_key_spincontainer);
+ vButtonSwitcher = (ViewAnimator) root.findViewById(R.id.button_animator);
+
+ mLinkedIdHolder = new LinkedIdsAdapter.ViewHolder(root);
+
+ vButtonVerify = root.findViewById(R.id.button_verify);
+ vButtonRetry = root.findViewById(R.id.button_retry);
+ vButtonConfirm = root.findViewById(R.id.button_confirm);
+ vButtonView = root.findViewById(R.id.button_view);
+
+ vVerifyingContainer = (ViewAnimator) root.findViewById(R.id.linked_verify_container);
+ vItemCertified = (ViewAnimator) root.findViewById(R.id.linked_id_certified);
+
+ vProgress = (ViewAnimator) root.findViewById(R.id.linked_cert_progress);
+ vText = (TextSwitcher) root.findViewById(R.id.linked_cert_text);
+ }
+
+ enum VerifyState {
+ VERIFYING, VERIFY_OK, VERIFY_ERROR, CERTIFYING
+ }
+
+ void setVerifyingState(Context context, VerifyState state, boolean isSecret) {
+ switch (state) {
+ case VERIFYING:
+ vProgress.setDisplayedChild(0);
+ vText.setText(context.getString(R.string.linked_text_verifying));
+ vKeySpinnerContainer.setVisibility(View.GONE);
+ break;
+
+ case VERIFY_OK:
+ vProgress.setDisplayedChild(1);
+ if (!isSecret) {
+ showButton(2);
+ if (!vKeySpinner.isSingleEntry()) {
+ vKeySpinnerContainer.setVisibility(View.VISIBLE);
+ }
+ } else {
+ showButton(1);
+ vKeySpinnerContainer.setVisibility(View.GONE);
+ }
+ break;
+
+ case VERIFY_ERROR:
+ showButton(1);
+ vProgress.setDisplayedChild(2);
+ vText.setText(context.getString(R.string.linked_text_error));
+ vKeySpinnerContainer.setVisibility(View.GONE);
+ break;
+
+ case CERTIFYING:
+ vProgress.setDisplayedChild(0);
+ vText.setText(context.getString(R.string.linked_text_confirming));
+ vKeySpinnerContainer.setVisibility(View.GONE);
+ break;
+ }
+ }
+
+ void showVerifyingContainer(Context context, boolean show, boolean isSecret) {
+ if (vVerifyingContainer.getDisplayedChild() == (show ? 1 : 0)) {
+ return;
+ }
+
+ vVerifyingContainer.setInAnimation(context, show ? R.anim.fade_in_up : R.anim.fade_in_down);
+ vVerifyingContainer.setOutAnimation(context, show ? R.anim.fade_out_up : R.anim.fade_out_down);
+ vVerifyingContainer.setDisplayedChild(show ? 1 : 0);
+
+ vItemCertified.setInAnimation(context, show ? R.anim.fade_in_up : R.anim.fade_in_down);
+ vItemCertified.setOutAnimation(context, show ? R.anim.fade_out_up : R.anim.fade_out_down);
+ vItemCertified.setDisplayedChild(show || isSecret ? 1 : 0);
+ }
+
+ void showButton(int which) {
+ if (vButtonSwitcher.getDisplayedChild() == which) {
+ return;
+ }
+ vButtonSwitcher.setDisplayedChild(which);
+ }
+
+ }
+
+ private boolean mVerificationState = false;
+ /** Switches between the 'verifying' ui bit and certificate status. This method
+ * must behave correctly in all states, showing or hiding the appropriate views
+ * and cancelling pending operations where necessary.
+ *
+ * This method also handles back button functionality in combination with
+ * onBackStateChanged.
+ */
+ void setShowVerifying(boolean show) {
+ if (!show) {
+ if (mInProgress != null) {
+ mInProgress.cancel(false);
+ mInProgress = null;
+ }
+ getFragmentManager().removeOnBackStackChangedListener(this);
+ new Handler().post(new Runnable() {
+ @Override
+ public void run() {
+ getFragmentManager().popBackStack("verification",
+ FragmentManager.POP_BACK_STACK_INCLUSIVE);
+ }
+ });
+
+ if (!mVerificationState) {
+ return;
+ }
+ mVerificationState = false;
+
+ mViewHolder.showButton(0);
+ mViewHolder.vKeySpinnerContainer.setVisibility(View.GONE);
+ mViewHolder.showVerifyingContainer(mContext, false, mIsSecret);
+ return;
+ }
+
+ if (mVerificationState) {
+ return;
+ }
+ mVerificationState = true;
+
+ FragmentManager manager = getFragmentManager();
+ manager.beginTransaction().addToBackStack("verification").commit();
+ manager.executePendingTransactions();
+ manager.addOnBackStackChangedListener(this);
+ mViewHolder.showVerifyingContainer(mContext, true, mIsSecret);
+
+ }
+
+ @Override
+ public void onBackStackChanged() {
+ setShowVerifying(false);
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup superContainer, Bundle savedInstanceState) {
+ View root = inflater.inflate(R.layout.linked_id_view_fragment, null);
+
+ mViewHolder = new ViewHolder(root);
+ root.setTag(mViewHolder);
+
+ ((ImageView) root.findViewById(R.id.status_icon_verified))
+ .setColorFilter(mContext.getResources().getColor(R.color.android_green_light),
+ PorterDuff.Mode.SRC_IN);
+ ((ImageView) root.findViewById(R.id.status_icon_invalid))
+ .setColorFilter(mContext.getResources().getColor(R.color.android_red_light),
+ PorterDuff.Mode.SRC_IN);
+
+ mViewHolder.vButtonVerify.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ verifyResource();
+ }
+ });
+ mViewHolder.vButtonRetry.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ verifyResource();
+ }
+ });
+ mViewHolder.vButtonConfirm.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ initiateCertifying();
+ }
+ });
+
+ {
+ Bundle args = new Bundle();
+ args.putParcelable(CertListWidget.ARG_URI, Certs.buildLinkedIdCertsUri(mDataUri, mLidRank));
+ args.putBoolean(CertListWidget.ARG_IS_SECRET, mIsSecret);
+ getLoaderManager().initLoader(CertListWidget.LOADER_ID_LINKED_CERTS,
+ args, mViewHolder.vLinkedCerts);
+ }
+
+ return root;
+ }
+
+ void verifyResource() {
+
+ // only one at a time (no sync needed, mInProgress is only touched in ui thread)
+ if (mInProgress != null) {
+ return;
+ }
+
+ setShowVerifying(true);
+
+ mViewHolder.vKeySpinnerContainer.setVisibility(View.GONE);
+ mViewHolder.setVerifyingState(mContext, VerifyState.VERIFYING, mIsSecret);
+
+ mInProgress = new AsyncTask<Void,Void,LinkedVerifyResult>() {
+ @Override
+ protected LinkedVerifyResult doInBackground(Void... params) {
+ long timer = System.currentTimeMillis();
+ LinkedVerifyResult result = mLinkedResource.verify(getActivity(), mFingerprint);
+
+ // ux flow: this operation should take at last a second
+ timer = System.currentTimeMillis() -timer;
+ if (timer < 1000) try {
+ Thread.sleep(1000 -timer);
+ } catch (InterruptedException e) {
+ // never mind
+ }
+
+ return result;
+ }
+
+ @Override
+ protected void onPostExecute(LinkedVerifyResult result) {
+ if (isCancelled()) {
+ return;
+ }
+ if (result.success()) {
+ mViewHolder.vText.setText(getString(mLinkedResource.getVerifiedText(mIsSecret)));
+ // hack to preserve bold text
+ ((TextView) mViewHolder.vText.getCurrentView()).setText(
+ mLinkedResource.getVerifiedText(mIsSecret));
+ mViewHolder.setVerifyingState(mContext, VerifyState.VERIFY_OK, mIsSecret);
+ mViewHolder.mLinkedIdHolder.seekAttention();
+ } else {
+ mViewHolder.setVerifyingState(mContext, VerifyState.VERIFY_ERROR, mIsSecret);
+ result.createNotify(getActivity()).show();
+ }
+ mInProgress = null;
+ }
+ }.execute();
+
+ }
+
+ private void initiateCertifying() {
+
+ if (mIsSecret) {
+ return;
+ }
+
+ // get the user's passphrase for this key (if required)
+ mCertifyKeyId = mViewHolder.vKeySpinner.getSelectedKeyId();
+ if (mCertifyKeyId == key.none || mCertifyKeyId == key.symmetric) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+ SubtleAttentionSeeker.tintBackground(mViewHolder.vKeySpinnerContainer, 600).start();
+ } else {
+ Notify.create(getActivity(), R.string.select_key_to_certify, Style.ERROR).show();
+ }
+ return;
+ }
+
+ mViewHolder.setVerifyingState(mContext, VerifyState.CERTIFYING, false);
+ cryptoOperation();
+
+ }
+
+ @Override
+ public void onCryptoOperationCancelled() {
+ super.onCryptoOperationCancelled();
+
+ // go back to 'verified ok'
+ setShowVerifying(false);
+
+ }
+
+ @Nullable
+ @Override
+ public Parcelable createOperationInput() {
+ long masterKeyId = KeyFormattingUtils.convertFingerprintToKeyId(mFingerprint);
+ CertifyAction action = new CertifyAction(masterKeyId, null,
+ Collections.singletonList(mLinkedId.toUserAttribute()));
+
+ // fill values for this action
+ CertifyActionsParcel parcel = new CertifyActionsParcel(mCertifyKeyId);
+ parcel.mCertifyActions.addAll(Collections.singletonList(action));
+
+ return parcel;
+ }
+
+ @Override
+ public void onCryptoOperationSuccess(OperationResult result) {
+ result.createNotify(getActivity()).show();
+ // no need to do anything else, we will get a loader refresh!
+ }
+
+ @Override
+ public void onCryptoOperationError(OperationResult result) {
+ result.createNotify(getActivity()).show();
+ }
+
+ @Override
+ public boolean onCryptoSetProgress(String msg, int progress, int max) {
+ return true;
+ }
+
+}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdWizard.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdWizard.java
new file mode 100644
index 000000000..8c677199d
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdWizard.java
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 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.linked;
+
+
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentTransaction;
+import android.support.v4.app.NavUtils;
+import android.support.v4.app.TaskStackBuilder;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.inputmethod.InputMethodManager;
+
+import org.sufficientlysecure.keychain.Constants;
+import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
+import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing;
+import org.sufficientlysecure.keychain.provider.KeychainContract;
+import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
+import org.sufficientlysecure.keychain.provider.ProviderHelper;
+import org.sufficientlysecure.keychain.ui.base.BaseActivity;
+import org.sufficientlysecure.keychain.util.Log;
+
+public class LinkedIdWizard extends BaseActivity {
+
+ public static final int FRAG_ACTION_START = 0;
+ public static final int FRAG_ACTION_TO_RIGHT = 1;
+ public static final int FRAG_ACTION_TO_LEFT = 2;
+
+ long mMasterKeyId;
+ byte[] mFingerprint;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setTitle(getString(R.string.title_linked_id_create));
+
+ try {
+ Uri uri = getIntent().getData();
+ uri = KeychainContract.KeyRings.buildUnifiedKeyRingUri(uri);
+ CachedPublicKeyRing ring = new ProviderHelper(this).getCachedPublicKeyRing(uri);
+ if (!ring.hasAnySecret()) {
+ Log.e(Constants.TAG, "Linked Identities can only be added to secret keys!");
+ finish();
+ return;
+ }
+
+ mMasterKeyId = ring.extractOrGetMasterKeyId();
+ mFingerprint = ring.getFingerprint();
+ } catch (PgpKeyNotFoundException e) {
+ Log.e(Constants.TAG, "Invalid uri given, key does not exist!");
+ finish();
+ return;
+ }
+
+ // pass extras into fragment
+ LinkedIdSelectFragment frag = LinkedIdSelectFragment.newInstance();
+ loadFragment(null, frag, FRAG_ACTION_START);
+ }
+
+ @Override
+ protected void initLayout() {
+ setContentView(R.layout.create_key_activity);
+ }
+
+ public void loadFragment(Bundle savedInstanceState, Fragment fragment, int action) {
+ // 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;
+ }
+
+ hideKeyboard();
+
+ // Add the fragment to the 'fragment_container' FrameLayout
+ // NOTE: We use commitAllowingStateLoss() to prevent weird crashes!
+ FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
+
+ switch (action) {
+ case FRAG_ACTION_START:
+ transaction.setCustomAnimations(0, 0);
+ transaction.replace(R.id.create_key_fragment_container, fragment)
+ .commitAllowingStateLoss();
+ break;
+ case FRAG_ACTION_TO_LEFT:
+ getSupportFragmentManager().popBackStackImmediate();
+ break;
+ case FRAG_ACTION_TO_RIGHT:
+ transaction.setCustomAnimations(R.anim.frag_slide_in_from_right, R.anim.frag_slide_out_to_left,
+ R.anim.frag_slide_in_from_left, R.anim.frag_slide_out_to_right);
+ transaction.addToBackStack(null);
+ transaction.replace(R.id.create_key_fragment_container, fragment)
+ .commitAllowingStateLoss();
+ break;
+
+ }
+ // do it immediately!
+ getSupportFragmentManager().executePendingTransactions();
+ }
+
+ private void hideKeyboard() {
+ InputMethodManager inputManager = (InputMethodManager)
+ getSystemService(Context.INPUT_METHOD_SERVICE);
+
+ // check if no view has focus
+ View v = getCurrentFocus();
+ if (v == null)
+ return;
+
+ inputManager.hideSoftInputFromWindow(v.getWindowToken(), 0);
+ }
+
+ @Override
+ public void onBackPressed() {
+ if (!getFragmentManager().popBackStackImmediate()) {
+ navigateBack();
+ }
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ // Respond to the action bar's Up/Home button
+ case android.R.id.home:
+ navigateBack();
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+ private void navigateBack() {
+ Intent upIntent = NavUtils.getParentActivityIntent(this);
+ upIntent.setData(KeyRings.buildGenericKeyRingUri(mMasterKeyId));
+ // This activity is NOT part of this app's task, so create a new task
+ // when navigating up, with a synthesized back stack.
+ TaskStackBuilder.create(this)
+ // Add all of this activity's parents to the back stack
+ .addNextIntentWithParentStack(upIntent)
+ // Navigate up to the closest parent
+ .startActivities();
+ }
+
+}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/ExperimentalWordConfirm.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/ExperimentalWordConfirm.java
new file mode 100644
index 000000000..43ccac24f
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/ExperimentalWordConfirm.java
@@ -0,0 +1,126 @@
+/*
+ * 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.util;
+
+import android.content.Context;
+
+import org.spongycastle.util.Arrays;
+import org.sufficientlysecure.keychain.Constants;
+import org.sufficientlysecure.keychain.util.Log;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.BitSet;
+
+public class ExperimentalWordConfirm {
+
+ public static String getWords(Context context, byte[] fingerprintBlob) {
+ ArrayList<String> words = new ArrayList<>();
+
+ BufferedReader reader = null;
+ try {
+ reader = new BufferedReader(new InputStreamReader(
+ context.getAssets().open("word_confirm_list.txt"),
+ "UTF-8"
+ ));
+
+ String line = reader.readLine();
+ while (line != null) {
+ words.add(line);
+
+ line = reader.readLine();
+ }
+ } catch (IOException e) {
+ throw new RuntimeException("IOException", e);
+ } finally {
+ if (reader != null) {
+ try {
+ reader.close();
+ } catch (IOException ignored) {
+ }
+ }
+ }
+
+ String fingerprint = "";
+
+ // NOTE: 160 bit SHA-1 truncated to 156 bit
+ byte[] fingerprintBlobTruncated = Arrays.copyOfRange(fingerprintBlob, 0, 156 / 8);
+
+ // TODO: implement key stretching to minimize fp length?
+
+ // BitSet bits = BitSet.valueOf(fingerprintBlob); // min API 19 and little endian!
+ BitSet bits = bitSetToByteArray(fingerprintBlobTruncated);
+ Log.d(Constants.TAG, "bits: " + bits.toString());
+
+ final int CHUNK_SIZE = 13;
+ final int LAST_CHUNK_INDEX = fingerprintBlobTruncated.length * 8 / CHUNK_SIZE; // 12
+ Log.d(Constants.TAG, "LAST_CHUNK_INDEX: " + LAST_CHUNK_INDEX);
+
+ int from = 0;
+ int to = CHUNK_SIZE;
+ for (int i = 0; i < (LAST_CHUNK_INDEX + 1); i++) {
+ Log.d(Constants.TAG, "from: " + from + " to: " + to);
+
+ BitSet setIndex = bits.get(from, to);
+ int wordIndex = (int) bitSetToLong(setIndex);
+ // int wordIndex = (int) setIndex.toLongArray()[0]; // min API 19
+
+ fingerprint += words.get(wordIndex);
+
+ if (i != LAST_CHUNK_INDEX) {
+ // line break every 3 words
+ if (to % (CHUNK_SIZE * 3) == 0) {
+ fingerprint += "\n";
+ } else {
+ fingerprint += " ";
+ }
+ }
+
+ from = to;
+ to += CHUNK_SIZE;
+ }
+
+ return fingerprint;
+ }
+
+ /**
+ * Returns a BitSet containing the values in bytes.
+ * BIG ENDIAN!
+ */
+ private static BitSet bitSetToByteArray(byte[] bytes) {
+ int arrayLength = bytes.length * 8;
+ BitSet bits = new BitSet();
+
+ for (int i = 0; i < arrayLength; i++) {
+ if ((bytes[bytes.length - i / 8 - 1] & (1 << (i % 8))) > 0) {
+ bits.set(i);
+ }
+ }
+ return bits;
+ }
+
+ private static long bitSetToLong(BitSet bits) {
+ long value = 0L;
+ for (int i = 0; i < bits.length(); ++i) {
+ value += bits.get(i) ? (1L << i) : 0L;
+ }
+ return value;
+ }
+}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/KeyFormattingUtils.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/KeyFormattingUtils.java
index 9984c245e..284c17e7a 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/KeyFormattingUtils.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/KeyFormattingUtils.java
@@ -269,6 +269,10 @@ public class KeyFormattingUtils {
return hexString;
}
+ public static long convertFingerprintToKeyId(byte[] fingerprint) {
+ return ByteBuffer.wrap(fingerprint, 12, 8).getLong();
+ }
+
/**
* Makes a human-readable version of a key ID, which is usually 64 bits: lower-case, no
* leading 0x, space-separated quartets (for keys whose length in hex is divisible by 4)
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/SubtleAttentionSeeker.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/SubtleAttentionSeeker.java
index 87444c226..4549e8993 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/SubtleAttentionSeeker.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/SubtleAttentionSeeker.java
@@ -17,13 +17,19 @@
package org.sufficientlysecure.keychain.ui.util;
+import android.animation.AnimatorInflater;
+import android.animation.ArgbEvaluator;
import android.animation.Keyframe;
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.annotation.TargetApi;
+import android.content.Context;
import android.os.Build.VERSION_CODES;
import android.view.View;
+import org.sufficientlysecure.keychain.R;
+
+
@TargetApi(VERSION_CODES.ICE_CREAM_SANDWICH)
/** Simple animation helper for subtle attention seeker stuff.
*
@@ -36,6 +42,10 @@ public class SubtleAttentionSeeker {
}
public static ObjectAnimator tada(View view, float shakeFactor) {
+ return tada(view, shakeFactor, 1400);
+ }
+
+ public static ObjectAnimator tada(View view, float shakeFactor, int duration) {
PropertyValuesHolder pvhScaleX = PropertyValuesHolder.ofKeyframe(View.SCALE_X,
Keyframe.ofFloat(0f, 1f),
@@ -80,7 +90,19 @@ public class SubtleAttentionSeeker {
);
return ObjectAnimator.ofPropertyValuesHolder(view, pvhScaleX, pvhScaleY, pvhRotate).
- setDuration(1400);
+ setDuration(duration);
+ }
+
+ @TargetApi(VERSION_CODES.LOLLIPOP)
+ public static ObjectAnimator tintBackground(View view, int duration) {
+ return ObjectAnimator.ofArgb(view, "backgroundColor",
+ 0x00FF0000, 0x33FF0000, 0x00FF0000).setDuration(duration);
+ }
+
+ @TargetApi(VERSION_CODES.LOLLIPOP)
+ public static ObjectAnimator tintText(View view, int duration) {
+ return ObjectAnimator.ofArgb(view, "backgroundColor",
+ 0x00FF7F00, 0x33FF7F00, 0x00FF7F00).setDuration(duration);
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/ThemeChanger.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/ThemeChanger.java
index 75a0d1ea5..375483d89 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/ThemeChanger.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/ThemeChanger.java
@@ -40,9 +40,9 @@ public class ThemeChanger {
// hack to get holo design (which is not automatically applied due to activity's
// Theme.NoDisplay)
if (Constants.Pref.Theme.DARK.equals(preferences.getTheme())) {
- return new ContextThemeWrapper(context, R.style.Theme_AppCompat_Dialog);
+ return new ContextThemeWrapper(context, R.style.Theme_Keychain_Dark);
} else {
- return new ContextThemeWrapper(context, R.style.Theme_AppCompat_Light_Dialog);
+ return new ContextThemeWrapper(context, R.style.Theme_Keychain_Light);
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/CertListWidget.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/CertListWidget.java
new file mode 100644
index 000000000..c413a00be
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/CertListWidget.java
@@ -0,0 +1,143 @@
+package org.sufficientlysecure.keychain.ui.widget;
+
+import java.util.Date;
+
+import android.content.Context;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Bundle;
+import android.support.v4.app.LoaderManager;
+import android.support.v4.content.CursorLoader;
+import android.support.v4.content.Loader;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.ListView;
+import android.widget.TextView;
+import android.widget.ViewAnimator;
+
+import org.ocpsoft.prettytime.PrettyTime;
+import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.provider.KeychainContract;
+import org.sufficientlysecure.keychain.provider.KeychainContract.Certs;
+
+public class CertListWidget extends ViewAnimator
+ implements LoaderManager.LoaderCallbacks<Cursor> {
+
+ public static final int LOADER_ID_LINKED_CERTS = 38572;
+
+ public static final String ARG_URI = "uri";
+ public static final String ARG_IS_SECRET = "is_secret";
+
+
+ // These are the rows that we will retrieve.
+ static final String[] CERTS_PROJECTION = new String[]{
+ KeychainContract.Certs._ID,
+ KeychainContract.Certs.MASTER_KEY_ID,
+ KeychainContract.Certs.VERIFIED,
+ KeychainContract.Certs.TYPE,
+ KeychainContract.Certs.RANK,
+ KeychainContract.Certs.KEY_ID_CERTIFIER,
+ KeychainContract.Certs.USER_ID,
+ KeychainContract.Certs.SIGNER_UID,
+ KeychainContract.Certs.CREATION
+ };
+ public static final int INDEX_MASTER_KEY_ID = 1;
+ public static final int INDEX_VERIFIED = 2;
+ public static final int INDEX_TYPE = 3;
+ public static final int INDEX_RANK = 4;
+ public static final int INDEX_KEY_ID_CERTIFIER = 5;
+ public static final int INDEX_USER_ID = 6;
+ public static final int INDEX_SIGNER_UID = 7;
+ public static final int INDEX_CREATION = 8;
+
+ private TextView vCollapsed;
+ private ListView vExpanded;
+ private View vExpandButton;
+ private boolean mIsSecret;
+
+ public CertListWidget(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+
+ View root = getRootView();
+ vCollapsed = (TextView) root.findViewById(R.id.cert_collapsed_list);
+ vExpanded = (ListView) root.findViewById(R.id.cert_expanded_list);
+ vExpandButton = root.findViewById(R.id.cert_expand_button);
+
+ // for now
+ vExpandButton.setVisibility(View.GONE);
+ vExpandButton.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ toggleExpanded();
+ }
+ });
+
+ // vExpanded.setAdapter(null);
+
+ }
+
+ void toggleExpanded() {
+ setDisplayedChild(getDisplayedChild() == 1 ? 0 : 1);
+ }
+
+ void setExpanded(boolean expanded) {
+ setDisplayedChild(expanded ? 1 : 0);
+ }
+
+ @Override
+ public Loader<Cursor> onCreateLoader(int id, Bundle args) {
+ Uri uri = args.getParcelable(ARG_URI);
+ mIsSecret = args.getBoolean(ARG_IS_SECRET, false);
+ return new CursorLoader(getContext(), uri,
+ CERTS_PROJECTION, null, null, null);
+ }
+
+ @Override
+ public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
+
+ if (data == null || !data.moveToFirst()) {
+ return;
+ }
+
+ // TODO support external certificates
+ Date userCert = null;
+ while (!data.isAfterLast()) {
+
+ int verified = data.getInt(INDEX_VERIFIED);
+ Date creation = new Date(data.getLong(INDEX_CREATION) * 1000);
+
+ if (verified == Certs.VERIFIED_SECRET) {
+ if (userCert == null || userCert.after(creation)) {
+ userCert = creation;
+ }
+ }
+
+ data.moveToNext();
+ }
+
+ if (userCert != null) {
+ PrettyTime format = new PrettyTime();
+ if (mIsSecret) {
+ vCollapsed.setText("You created this identity "
+ + format.format(userCert) + ".");
+ } else {
+ vCollapsed.setText("You verified and confirmed this identity "
+ + format.format(userCert) + ".");
+ }
+ } else {
+ vCollapsed.setText("This identity is not yet verified or confirmed.");
+ }
+
+ }
+
+ @Override
+ public void onLoaderReset(Loader<Cursor> loader) {
+ setVisibility(View.GONE);
+ }
+
+}
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 6cd33aada..6a51085f3 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
@@ -17,25 +17,24 @@
package org.sufficientlysecure.keychain.ui.widget;
-
-import java.util.Arrays;
-import java.util.List;
-
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
+import android.support.annotation.StringRes;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.util.AttributeSet;
import org.sufficientlysecure.keychain.Constants;
+import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.provider.KeychainDatabase;
import org.sufficientlysecure.keychain.ui.adapter.KeyAdapter;
public class CertifyKeySpinner extends KeySpinner {
private long mHiddenMasterKeyId = Constants.key.none;
+ private boolean mIsSingle;
public CertifyKeySpinner(Context context) {
super(context);
@@ -94,9 +93,11 @@ public class CertifyKeySpinner extends KeySpinner {
if (!data.isNull(mIndexHasCertify)) {
if (selection == -1) {
selection = data.getPosition() + 1;
+ mIsSingle = true;
} else {
// if selection is already set, we have more than one certify key!
// get back to "none"!
+ mIsSingle = false;
selection = 0;
}
}
@@ -106,6 +107,9 @@ public class CertifyKeySpinner extends KeySpinner {
}
}
+ public boolean isSingleEntry() {
+ return mIsSingle && getSelectedItemPosition() != 0;
+ }
@Override
boolean isItemEnabled(Cursor cursor) {
@@ -128,4 +132,10 @@ public class CertifyKeySpinner extends KeySpinner {
return true;
}
+ @Override
+ public @StringRes int getNoneString() {
+ return R.string.choice_select_cert;
+ }
+
+
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java
index 1884daf12..04ed35deb 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java
@@ -23,6 +23,7 @@ import android.database.Cursor;
import android.os.Bundle;
import android.os.Parcelable;
import android.support.annotation.NonNull;
+import android.support.annotation.StringRes;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.Loader;
@@ -34,6 +35,7 @@ import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.SpinnerAdapter;
+import android.widget.TextView;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
@@ -117,8 +119,7 @@ public abstract class KeySpinner extends AppCompatSpinner implements
if (getContext() instanceof FragmentActivity) {
((FragmentActivity) getContext()).getSupportLoaderManager().restartLoader(LOADER_ID, null, this);
} else {
- throw new AssertionError("KeySpinner must be attached to FragmentActivity, this is "
- + getContext().getClass());
+ // ignore, this happens during preview! we use fragmentactivities everywhere either way
}
}
@@ -226,9 +227,11 @@ public abstract class KeySpinner extends AppCompatSpinner implements
return inner.getView(position -1, convertView, parent);
}
- return convertView != null ? convertView :
+ View view = convertView != null ? convertView :
LayoutInflater.from(getContext()).inflate(
R.layout.keyspinner_item_none, parent, false);
+ ((TextView) view.findViewById(R.id.keyspinner_key_name)).setText(getNoneString());
+ return view;
}
}
@@ -259,4 +262,9 @@ public abstract class KeySpinner extends AppCompatSpinner implements
bundle.putLong(ARG_KEY_ID, getSelectedKeyId());
return bundle;
}
+
+ public @StringRes int getNoneString() {
+ return R.string.cert_none;
+ }
+
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/PrefixedEditText.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/PrefixedEditText.java
new file mode 100644
index 000000000..3cbb114e8
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/PrefixedEditText.java
@@ -0,0 +1,45 @@
+package org.sufficientlysecure.keychain.ui.widget;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.*;
+import android.support.annotation.NonNull;
+import android.util.AttributeSet;
+import android.widget.EditText;
+
+import org.sufficientlysecure.keychain.R;
+
+public class PrefixedEditText extends EditText {
+
+ private String mPrefix;
+ private Rect mPrefixRect = new Rect();
+
+ public PrefixedEditText(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ TypedArray style = context.getTheme().obtainStyledAttributes(
+ attrs, R.styleable.PrefixedEditText, 0, 0);
+ mPrefix = style.getString(R.styleable.PrefixedEditText_prefix);
+ if (mPrefix == null) {
+ mPrefix = "";
+ }
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ getPaint().getTextBounds(mPrefix, 0, mPrefix.length(), mPrefixRect);
+
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ }
+
+ @Override
+ protected void onDraw(@NonNull Canvas canvas) {
+ super.onDraw(canvas);
+ canvas.drawText(mPrefix, super.getCompoundPaddingLeft(), getBaseline(), getPaint());
+ }
+
+ @Override
+ public int getCompoundPaddingLeft() {
+ return super.getCompoundPaddingLeft() + mPrefixRect.width();
+ }
+
+} \ No newline at end of file
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/StatusIndicator.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/StatusIndicator.java
new file mode 100644
index 000000000..2784ac5f0
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/StatusIndicator.java
@@ -0,0 +1,45 @@
+package org.sufficientlysecure.keychain.ui.widget;
+
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.animation.AnimationUtils;
+
+import org.sufficientlysecure.keychain.R;
+
+
+public class StatusIndicator extends ToolableViewAnimator {
+
+ public enum Status {
+ IDLE, PROGRESS, OK, ERROR
+ }
+
+ public StatusIndicator(Context context) {
+ super(context);
+
+ LayoutInflater.from(context).inflate(R.layout.status_indicator, this, true);
+ setInAnimation(AnimationUtils.loadAnimation(context, R.anim.fade_in));
+ setOutAnimation(AnimationUtils.loadAnimation(context, R.anim.fade_out));
+ }
+
+ public StatusIndicator(Context context, AttributeSet attrs) {
+ super(context, attrs);
+
+ LayoutInflater.from(context).inflate(R.layout.status_indicator, this, true);
+ setInAnimation(AnimationUtils.loadAnimation(context, R.anim.fade_in));
+ setOutAnimation(AnimationUtils.loadAnimation(context, R.anim.fade_out));
+ }
+
+ @Override
+ public void setDisplayedChild(int whichChild) {
+ if (whichChild != getDisplayedChild()) {
+ super.setDisplayedChild(whichChild);
+ }
+ }
+
+ public void setDisplayedChild(Status status) {
+ setDisplayedChild(status.ordinal());
+ }
+
+}
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 5f2329170..45dc33906 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ExportHelper.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ExportHelper.java
@@ -20,6 +20,8 @@ package org.sufficientlysecure.keychain.util;
import java.io.File;
+import android.content.Intent;
+import android.net.Uri;
import android.support.v4.app.FragmentActivity;
import org.sufficientlysecure.keychain.Constants;
@@ -67,7 +69,7 @@ public class ExportHelper
: R.string.specify_backup_dest_single);
}
- FileHelper.saveFile(new FileHelper.FileDialogCallback() {
+ FileHelper.saveDocumentDialog(new FileHelper.FileDialogCallback() {
@Override
public void onFileSelected(File file, boolean checked) {
mExportFile = file;
@@ -98,7 +100,10 @@ public class ExportHelper
}
@Override
- public void onCryptoOperationSuccess(ExportResult result) {
+ final public void onCryptoOperationSuccess(ExportResult result) {
+ // trigger scan of the created 'media' file so it shows up on MTP
+ // http://stackoverflow.com/questions/13737261/nexus-4-not-showing-files-via-mtp
+ mActivity.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(mExportFile)));
result.createNotify(mActivity).show();
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/FileHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/FileHelper.java
index 4a00f46cb..9fb362412 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/FileHelper.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/FileHelper.java
@@ -28,16 +28,19 @@ import android.graphics.Bitmap;
import android.graphics.Point;
import android.net.Uri;
import android.os.Build;
+import android.os.Build.VERSION_CODES;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.os.Messenger;
import android.provider.DocumentsContract;
import android.provider.OpenableColumns;
+import android.support.annotation.StringRes;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.widget.Toast;
+import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.compatibility.DialogFragmentWorkaround;
import org.sufficientlysecure.keychain.ui.dialog.FileDialogFragment;
@@ -46,42 +49,95 @@ import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
-import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.text.DecimalFormat;
+
+/** This class offers a number of helper functions for saving documents.
+ *
+ * There are three entry points here: openDocument, saveDocument and
+ * saveDocumentDialog. Each behaves a little differently depending on whether
+ * the Android version used is pre or post KitKat.
+ *
+ * - openDocument queries for a document for reading. Used in "open encrypted
+ * file" ui flow. On pre-kitkat, this relies on an external file manager,
+ * and will fail with a toast message if none is installed.
+ *
+ * - saveDocument queries for a document name for saving. on pre-kitkat, this
+ * shows a dialog where a filename can be input. on kitkat and up, it
+ * directly triggers a "save document" intent. Used in "save encrypted file"
+ * ui flow.
+ *
+ * - saveDocumentDialog queries for a document. this shows a dialog on all
+ * versions of android. the browse button opens an external browser on
+ * pre-kitkat or the "save document" intent on post-kitkat devices. Used in
+ * "backup key" ui flow.
+ *
+ * It is noteworthy that the "saveDocument" call is essentially substituted
+ * by the "saveDocumentDialog" on pre-kitkat devices.
+ *
+ */
public class FileHelper {
- /**
- * Checks if external storage is mounted if file is located on external storage
- *
- * @return true if storage is mounted
- */
- public static boolean isStorageMounted(String file) {
- if (file.startsWith(Environment.getExternalStorageDirectory().getAbsolutePath())) {
- if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
- return false;
- }
+ public static void openDocument(Fragment fragment, Uri last, String mimeType, boolean multiple, int requestCode) {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
+ openDocumentPreKitKat(fragment, last, mimeType, multiple, requestCode);
+ } else {
+ openDocumentKitKat(fragment, mimeType, multiple, requestCode);
}
+ }
- return true;
+ public static void saveDocument(Fragment fragment, String targetName, Uri inputUri,
+ @StringRes int title, @StringRes int message, int requestCode) {
+ saveDocument(fragment, targetName, inputUri, "*/*", title, message, requestCode);
}
- /**
- * Opens the preferred installed file manager on Android and shows a toast if no manager is
- * installed.
- *
- * @param last default selected Uri, not supported by all file managers
- * @param mimeType can be text/plain for example
- * @param requestCode requestCode used to identify the result coming back from file manager to
- * onActivityResult() in your activity
- */
- public static void openFile(Fragment fragment, Uri last, String mimeType, int requestCode) {
+ public static void saveDocument(Fragment fragment, String targetName, Uri inputUri, String mimeType,
+ @StringRes int title, @StringRes int message, int requestCode) {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
+ saveDocumentDialog(fragment, targetName, inputUri, title, message, requestCode);
+ } else {
+ saveDocumentKitKat(fragment, mimeType, targetName, requestCode);
+ }
+ }
+
+ public static void saveDocumentDialog(final Fragment fragment, String targetName, Uri inputUri,
+ @StringRes int title, @StringRes int message, final int requestCode) {
+
+ saveDocumentDialog(fragment, targetName, inputUri, title, message, new FileDialogCallback() {
+ // is this a good idea? seems hacky...
+ @Override
+ public void onFileSelected(File file, boolean checked) {
+ Intent intent = new Intent();
+ intent.setData(Uri.fromFile(file));
+ fragment.onActivityResult(requestCode, Activity.RESULT_OK, intent);
+ }
+ });
+ }
+
+ public static void saveDocumentDialog(final Fragment fragment, String targetName, Uri inputUri,
+ @StringRes int title, @StringRes int message, FileDialogCallback callback) {
+
+ File file = inputUri == null ? null : new File(inputUri.getPath());
+ File parentDir = file != null && file.exists() ? file.getParentFile() : Constants.Path.APP_DIR;
+ File targetFile = new File(parentDir, targetName);
+ saveDocumentDialog(callback, fragment.getActivity().getSupportFragmentManager(),
+ fragment.getString(title), fragment.getString(message), targetFile, null);
+
+ }
+
+ /** Opens the preferred installed file manager on Android and shows a toast
+ * if no manager is installed. */
+ private static void openDocumentPreKitKat(
+ Fragment fragment, Uri last, String mimeType, boolean multiple, int requestCode) {
+
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
-
+ if (Build.VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN_MR2) {
+ intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, multiple);
+ }
intent.setData(last);
intent.setType(mimeType);
@@ -92,11 +148,34 @@ public class FileHelper {
Toast.makeText(fragment.getActivity(), R.string.no_filemanager_installed,
Toast.LENGTH_SHORT).show();
}
+
+ }
+
+ /** Opens the storage browser on Android 4.4 or later for opening a file */
+ @TargetApi(Build.VERSION_CODES.KITKAT)
+ private static void openDocumentKitKat(Fragment fragment, String mimeType, boolean multiple, int requestCode) {
+ Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
+ intent.addCategory(Intent.CATEGORY_OPENABLE);
+ intent.setType(mimeType);
+ intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, multiple);
+ fragment.startActivityForResult(intent, requestCode);
+ }
+
+ /** Opens the storage browser on Android 4.4 or later for saving a file. */
+ @TargetApi(Build.VERSION_CODES.KITKAT)
+ public static void saveDocumentKitKat(Fragment fragment, String mimeType, String suggestedName, int requestCode) {
+ Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
+ intent.addCategory(Intent.CATEGORY_OPENABLE);
+ intent.setType(mimeType);
+ intent.putExtra("android.content.extra.SHOW_ADVANCED", true); // Note: This is not documented, but works
+ intent.putExtra(Intent.EXTRA_TITLE, suggestedName);
+ fragment.startActivityForResult(intent, requestCode);
}
- public static void saveFile(final FileDialogCallback callback, final FragmentManager fragmentManager,
- final String title, final String message, final File defaultFile,
- final String checkMsg) {
+ public static void saveDocumentDialog(
+ final FileDialogCallback callback, final FragmentManager fragmentManager,
+ final String title, final String message, final File defaultFile,
+ final String checkMsg) {
// Message is received after file is selected
Handler returnHandler = new Handler() {
@Override
@@ -123,61 +202,6 @@ public class FileHelper {
});
}
- public static void saveFile(Fragment fragment, String title, String message, File defaultFile, int requestCode) {
- saveFile(fragment, title, message, defaultFile, requestCode, null);
- }
-
- public static void saveFile(final Fragment fragment, String title, String message, File defaultFile,
- final int requestCode, String checkMsg) {
- saveFile(new FileDialogCallback() {
- @Override
- public void onFileSelected(File file, boolean checked) {
- Intent intent = new Intent();
- intent.setData(Uri.fromFile(file));
- fragment.onActivityResult(requestCode, Activity.RESULT_OK, intent);
- }
- }, fragment.getActivity().getSupportFragmentManager(), title, message, defaultFile, checkMsg);
- }
-
- @TargetApi(Build.VERSION_CODES.KITKAT)
- public static void openDocument(Fragment fragment, String mimeType, int requestCode) {
- openDocument(fragment, mimeType, false, requestCode);
- }
-
- /**
- * Opens the storage browser on Android 4.4 or later for opening a file
- *
- * @param mimeType can be text/plain for example
- * @param multiple allow file chooser to return multiple files
- * @param requestCode used to identify the result coming back from storage browser onActivityResult() in your
- */
- @TargetApi(Build.VERSION_CODES.KITKAT)
- public static void openDocument(Fragment fragment, String mimeType, boolean multiple, int requestCode) {
- Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
- intent.addCategory(Intent.CATEGORY_OPENABLE);
- intent.setType(mimeType);
- intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, multiple);
-
- fragment.startActivityForResult(intent, requestCode);
- }
-
- /**
- * Opens the storage browser on Android 4.4 or later for saving a file
- *
- * @param mimeType can be text/plain for example
- * @param suggestedName a filename desirable for the file to be saved
- * @param requestCode used to identify the result coming back from storage browser onActivityResult() in your
- */
- @TargetApi(Build.VERSION_CODES.KITKAT)
- public static void saveDocument(Fragment fragment, String mimeType, String suggestedName, int requestCode) {
- Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
- intent.addCategory(Intent.CATEGORY_OPENABLE);
- intent.setType(mimeType);
- intent.putExtra("android.content.extra.SHOW_ADVANCED", true); // Note: This is not documented, but works
- intent.putExtra(Intent.EXTRA_TITLE, suggestedName);
- fragment.startActivityForResult(intent, requestCode);
- }
-
public static String getFilename(Context context, Uri uri) {
String filename = null;
try {
@@ -298,6 +322,17 @@ public class FileHelper {
}
}
+ /** Checks if external storage is mounted if file is located on external storage. */
+ public static boolean isStorageMounted(String file) {
+ if (file.startsWith(Environment.getExternalStorageDirectory().getAbsolutePath())) {
+ if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
public interface FileDialogCallback {
void onFileSelected(File file, boolean checked);
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/FilterCursorWrapper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/FilterCursorWrapper.java
new file mode 100644
index 000000000..ab73f59b8
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/FilterCursorWrapper.java
@@ -0,0 +1,76 @@
+package org.sufficientlysecure.keychain.util;
+
+
+import android.database.Cursor;
+import android.database.CursorWrapper;
+
+public abstract class FilterCursorWrapper extends CursorWrapper {
+ private int[] mIndex;
+ private int mCount = 0;
+ private int mPos = 0;
+
+ public abstract boolean isVisible(Cursor cursor);
+
+ public FilterCursorWrapper(Cursor cursor) {
+ super(cursor);
+ mCount = super.getCount();
+ mIndex = new int[mCount];
+ for (int i = 0; i < mCount; i++) {
+ super.moveToPosition(i);
+ if (isVisible(cursor)) {
+ mIndex[mPos++] = i;
+ }
+ }
+ mCount = mPos;
+ mPos = 0;
+ super.moveToFirst();
+ }
+
+ @Override
+ public boolean move(int offset) {
+ return this.moveToPosition(mPos + offset);
+ }
+
+ @Override
+ public boolean moveToNext() {
+ return this.moveToPosition(mPos + 1);
+ }
+
+ @Override
+ public boolean moveToPrevious() {
+ return this.moveToPosition(mPos - 1);
+ }
+
+ @Override
+ public boolean moveToFirst() {
+ return this.moveToPosition(0);
+ }
+
+ @Override
+ public boolean moveToLast() {
+ return this.moveToPosition(mCount - 1);
+ }
+
+ @Override
+ public boolean moveToPosition(int position) {
+ if (position >= mCount || position < 0) {
+ return false;
+ }
+ return super.moveToPosition(mIndex[position]);
+ }
+
+ @Override
+ public int getCount() {
+ return mCount;
+ }
+
+ public int getHiddenCount() {
+ return super.getCount() - mCount;
+ }
+
+ @Override
+ public int getPosition() {
+ return mPos;
+ }
+
+} \ No newline at end of file
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 0596b0079..4ef215036 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Preferences.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Preferences.java
@@ -25,7 +25,7 @@ import android.content.res.Resources;
import android.preference.PreferenceManager;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.Constants.Pref;
-import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.service.KeyserverSyncAdapterService;
import java.net.Proxy;
import java.util.ArrayList;
@@ -285,16 +285,19 @@ public class Preferences {
}
public Proxy.Type getProxyType() {
- final String typeHttp = mResources.getString(R.string.pref_proxy_type_value_http);
- final String typeSocks = mResources.getString(R.string.pref_proxy_type_value_socks);
+ final String typeHttp = Pref.ProxyType.TYPE_HTTP;
+ final String typeSocks = Pref.ProxyType.TYPE_SOCKS;
String type = mSharedPreferences.getString(Pref.PROXY_TYPE, typeHttp);
- if (type.equals(typeHttp)) return Proxy.Type.HTTP;
- else if (type.equals(typeSocks)) return Proxy.Type.SOCKS;
- else { // shouldn't happen
- Log.e(Constants.TAG, "Invalid Proxy Type in preferences");
- return null;
+ switch (type) {
+ case typeHttp:
+ return Proxy.Type.HTTP;
+ case typeSocks:
+ return Proxy.Type.SOCKS;
+ default: // shouldn't happen
+ Log.e(Constants.TAG, "Invalid Proxy Type in preferences");
+ return null;
}
}
@@ -306,7 +309,7 @@ public class Preferences {
return new ProxyPrefs(true, false, Constants.Orbot.PROXY_HOST, Constants.Orbot.PROXY_PORT,
Constants.Orbot.PROXY_TYPE);
} else if (useNormalProxy) {
- return new ProxyPrefs(useTor, useNormalProxy, getProxyHost(), getProxyPort(), getProxyType());
+ return new ProxyPrefs(false, true, getProxyHost(), getProxyPort(), getProxyType());
} else {
return new ProxyPrefs(false, false, null, -1, null);
}
@@ -331,7 +334,7 @@ public class Preferences {
}
}
- // proxy preference functions ends here
+ // cloud prefs
public CloudSearchPrefs getCloudSearchPrefs() {
return new CloudSearchPrefs(mSharedPreferences.getBoolean(Pref.SEARCH_KEYSERVER, true),
@@ -356,7 +359,39 @@ public class Preferences {
}
}
- public void upgradePreferences() {
+ // experimental prefs
+
+ public void setExperimentalEnableWordConfirm(boolean enableWordConfirm) {
+ SharedPreferences.Editor editor = mSharedPreferences.edit();
+ editor.putBoolean(Pref.EXPERIMENTAL_ENABLE_WORD_CONFIRM, enableWordConfirm);
+ editor.commit();
+ }
+
+ public boolean getExperimentalEnableWordConfirm() {
+ return mSharedPreferences.getBoolean(Pref.EXPERIMENTAL_ENABLE_WORD_CONFIRM, false);
+ }
+
+ public void setExperimentalEnableLinkedIdentities(boolean enableLinkedIdentities) {
+ SharedPreferences.Editor editor = mSharedPreferences.edit();
+ editor.putBoolean(Pref.EXPERIMENTAL_ENABLE_LINKED_IDENTITIES, enableLinkedIdentities);
+ editor.commit();
+ }
+
+ public boolean getExperimentalEnableLinkedIdentities() {
+ return mSharedPreferences.getBoolean(Pref.EXPERIMENTAL_ENABLE_LINKED_IDENTITIES, false);
+ }
+
+ public void setExperimentalEnableKeybase(boolean enableKeybase) {
+ SharedPreferences.Editor editor = mSharedPreferences.edit();
+ editor.putBoolean(Pref.EXPERIMENTAL_ENABLE_KEYBASE, enableKeybase);
+ editor.commit();
+ }
+
+ public boolean getExperimentalEnableKeybase() {
+ return mSharedPreferences.getBoolean(Pref.EXPERIMENTAL_ENABLE_KEYBASE, false);
+ }
+
+ public void upgradePreferences(Context context) {
if (mSharedPreferences.getInt(Constants.Pref.PREF_DEFAULT_VERSION, 0) !=
Constants.Defaults.PREF_VERSION) {
switch (mSharedPreferences.getInt(Constants.Pref.PREF_DEFAULT_VERSION, 0)) {
@@ -394,6 +429,10 @@ public class Preferences {
}
// fall through
case 5: {
+ KeyserverSyncAdapterService.enableKeyserverSync(context);
+ }
+ // fall through
+ case 6: {
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/orbot/OrbotHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/orbot/OrbotHelper.java
index d5ee75f9b..d85ad9128 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/orbot/OrbotHelper.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/orbot/OrbotHelper.java
@@ -361,7 +361,7 @@ public class OrbotHelper {
.show(fragmentActivity.getSupportFragmentManager(),
"OrbotHelperOrbotStartDialog");
}
- }.startOrbotAndListen(fragmentActivity);
+ }.startOrbotAndListen(fragmentActivity, true);
return false;
} else {
@@ -385,7 +385,8 @@ public class OrbotHelper {
* activities wishing to respond to a change in Orbot state.
*/
public static void bestPossibleOrbotStart(final DialogActions dialogActions,
- final Activity activity) {
+ final Activity activity,
+ boolean showProgress) {
new SilentStartManager() {
@Override
@@ -397,23 +398,23 @@ public class OrbotHelper {
protected void onSilentStartDisabled() {
requestShowOrbotStart(activity);
}
- }.startOrbotAndListen(activity);
+ }.startOrbotAndListen(activity, showProgress);
}
/**
* base class for listening to silent orbot starts. Also handles display of progress dialog.
*/
- private static abstract class SilentStartManager {
+ public static abstract class SilentStartManager {
private ProgressDialog mProgressDialog;
- public void startOrbotAndListen(Context context) {
- mProgressDialog = new ProgressDialog(ThemeChanger.getDialogThemeWrapper(context));
- mProgressDialog.setMessage(context.getString(R.string.progress_starting_orbot));
- mProgressDialog.setCancelable(false);
- mProgressDialog.show();
+ public void startOrbotAndListen(final Context context, final boolean showProgress) {
+ Log.d(Constants.TAG, "starting orbot listener");
+ if (showProgress) {
+ showProgressDialog(context);
+ }
- BroadcastReceiver receiver = new BroadcastReceiver() {
+ final BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
switch (intent.getStringExtra(OrbotHelper.EXTRA_STATUS)) {
@@ -423,14 +424,18 @@ public class OrbotHelper {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
- mProgressDialog.dismiss();
+ if (showProgress) {
+ mProgressDialog.dismiss();
+ }
onOrbotStarted();
}
}, 1000);
break;
case OrbotHelper.STATUS_STARTS_DISABLED:
context.unregisterReceiver(this);
- mProgressDialog.dismiss();
+ if (showProgress) {
+ mProgressDialog.dismiss();
+ }
onSilentStartDisabled();
break;
@@ -444,6 +449,13 @@ public class OrbotHelper {
requestStartTor(context);
}
+ private void showProgressDialog(Context context) {
+ mProgressDialog = new ProgressDialog(ThemeChanger.getDialogThemeWrapper(context));
+ mProgressDialog.setMessage(context.getString(R.string.progress_starting_orbot));
+ mProgressDialog.setCancelable(false);
+ mProgressDialog.show();
+ }
+
protected abstract void onOrbotStarted();
protected abstract void onSilentStartDisabled();
diff --git a/OpenKeychain/src/main/res/anim/fade_in_down.xml b/OpenKeychain/src/main/res/anim/fade_in_down.xml
new file mode 100644
index 000000000..fb9ed416e
--- /dev/null
+++ b/OpenKeychain/src/main/res/anim/fade_in_down.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+ <translate android:fromYDelta="-10" android:toYDelta="0"
+ android:interpolator="@android:anim/decelerate_interpolator"
+ android:duration="200"
+ />
+ <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
+ android:interpolator="@android:anim/accelerate_interpolator"
+ android:duration="200"
+ />
+</set> \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/anim/fade_in_quick.xml b/OpenKeychain/src/main/res/anim/fade_in_quick.xml
new file mode 100644
index 000000000..e0725de3d
--- /dev/null
+++ b/OpenKeychain/src/main/res/anim/fade_in_quick.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+ <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
+ android:interpolator="@android:anim/bounce_interpolator"
+ android:duration="400"
+ />
+</set> \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/anim/fade_in_up.xml b/OpenKeychain/src/main/res/anim/fade_in_up.xml
new file mode 100644
index 000000000..c190c0f53
--- /dev/null
+++ b/OpenKeychain/src/main/res/anim/fade_in_up.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+ <translate android:fromYDelta="10" android:toYDelta="0"
+ android:interpolator="@android:anim/decelerate_interpolator"
+ android:duration="200"
+ />
+ <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
+ android:interpolator="@android:anim/accelerate_interpolator"
+ android:duration="200"
+ />
+</set> \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/anim/fade_out_down.xml b/OpenKeychain/src/main/res/anim/fade_out_down.xml
new file mode 100644
index 000000000..523b180af
--- /dev/null
+++ b/OpenKeychain/src/main/res/anim/fade_out_down.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+ <translate android:fromYDelta="0.0" android:toYDelta="10"
+ android:interpolator="@android:anim/decelerate_interpolator"
+ android:duration="200"
+ />
+ <alpha android:fromAlpha="1.0" android:toAlpha="0.0"
+ android:interpolator="@android:anim/decelerate_interpolator"
+ android:duration="150"
+ />
+</set> \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/anim/fade_out_quick.xml b/OpenKeychain/src/main/res/anim/fade_out_quick.xml
new file mode 100644
index 000000000..94fc508d7
--- /dev/null
+++ b/OpenKeychain/src/main/res/anim/fade_out_quick.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+ <alpha android:fromAlpha="1.0" android:toAlpha="0.0"
+ android:interpolator="@android:anim/decelerate_interpolator"
+ android:duration="150"
+ />
+</set> \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/anim/fade_out_up.xml b/OpenKeychain/src/main/res/anim/fade_out_up.xml
new file mode 100644
index 000000000..65049a387
--- /dev/null
+++ b/OpenKeychain/src/main/res/anim/fade_out_up.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+ <translate android:fromYDelta="0.0" android:toYDelta="-10"
+ android:interpolator="@android:anim/decelerate_interpolator"
+ android:duration="200"
+ />
+ <alpha android:fromAlpha="1.0" android:toAlpha="0.0"
+ android:interpolator="@android:anim/decelerate_interpolator"
+ android:duration="150"
+ />
+</set> \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/drawable-hdpi/account_key.png b/OpenKeychain/src/main/res/drawable-hdpi/account_key.png
new file mode 100644
index 000000000..b6a99772e
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-hdpi/account_key.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-hdpi/ic_cloud_black_24dp.png b/OpenKeychain/src/main/res/drawable-hdpi/ic_cloud_black_24dp.png
new file mode 100644
index 000000000..c3445cb8d
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-hdpi/ic_cloud_black_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-hdpi/ic_extension_black_24dp.png b/OpenKeychain/src/main/res/drawable-hdpi/ic_extension_black_24dp.png
new file mode 100644
index 000000000..e711e87e2
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-hdpi/ic_extension_black_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-hdpi/ic_ic_stat_tor.png b/OpenKeychain/src/main/res/drawable-hdpi/ic_ic_stat_tor.png
new file mode 100644
index 000000000..b6e040adb
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-hdpi/ic_ic_stat_tor.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-hdpi/ic_repeat_black_24dp.png b/OpenKeychain/src/main/res/drawable-hdpi/ic_repeat_black_24dp.png
new file mode 100644
index 000000000..d8b42bbe4
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-hdpi/ic_repeat_black_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-hdpi/ic_settings_ethernet_black_24dp.png b/OpenKeychain/src/main/res/drawable-hdpi/ic_settings_ethernet_black_24dp.png
new file mode 100644
index 000000000..c97350f3f
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-hdpi/ic_settings_ethernet_black_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-hdpi/ic_stat_tor.png b/OpenKeychain/src/main/res/drawable-hdpi/ic_stat_tor.png
new file mode 100644
index 000000000..b6e040adb
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-hdpi/ic_stat_tor.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-hdpi/ic_stat_tor_off.png b/OpenKeychain/src/main/res/drawable-hdpi/ic_stat_tor_off.png
new file mode 100644
index 000000000..e72d7ca4b
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-hdpi/ic_stat_tor_off.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-hdpi/ic_sync_black_24dp.png b/OpenKeychain/src/main/res/drawable-hdpi/ic_sync_black_24dp.png
new file mode 100644
index 000000000..a5ebdbd07
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-hdpi/ic_sync_black_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-hdpi/link_24dp.png b/OpenKeychain/src/main/res/drawable-hdpi/link_24dp.png
new file mode 100644
index 000000000..17482011b
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-hdpi/link_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-hdpi/linked_dns.png b/OpenKeychain/src/main/res/drawable-hdpi/linked_dns.png
new file mode 100644
index 000000000..41719efd6
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-hdpi/linked_dns.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-hdpi/linked_github.png b/OpenKeychain/src/main/res/drawable-hdpi/linked_github.png
new file mode 100644
index 000000000..2a1ae67d7
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-hdpi/linked_github.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-hdpi/linked_https.png b/OpenKeychain/src/main/res/drawable-hdpi/linked_https.png
new file mode 100644
index 000000000..278fac4f8
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-hdpi/linked_https.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-hdpi/linked_twitter.png b/OpenKeychain/src/main/res/drawable-hdpi/linked_twitter.png
new file mode 100644
index 000000000..dd0fce197
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-hdpi/linked_twitter.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-hdpi/octo_link_24dp.png b/OpenKeychain/src/main/res/drawable-hdpi/octo_link_24dp.png
new file mode 100644
index 000000000..dc1b2bc4d
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-hdpi/octo_link_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-hdpi/status_signature_verified_inner_24dp.png b/OpenKeychain/src/main/res/drawable-hdpi/status_signature_verified_inner_24dp.png
new file mode 100644
index 000000000..e9dfc47a4
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-hdpi/status_signature_verified_inner_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-hdpi/status_signature_verified_inner_96dp.png b/OpenKeychain/src/main/res/drawable-hdpi/status_signature_verified_inner_96dp.png
new file mode 100644
index 000000000..4a3f2b2b5
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-hdpi/status_signature_verified_inner_96dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-mdpi/account_key.png b/OpenKeychain/src/main/res/drawable-mdpi/account_key.png
new file mode 100644
index 000000000..d5e22f248
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-mdpi/account_key.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-mdpi/ic_cloud_black_24dp.png b/OpenKeychain/src/main/res/drawable-mdpi/ic_cloud_black_24dp.png
new file mode 100644
index 000000000..633105072
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-mdpi/ic_cloud_black_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-mdpi/ic_extension_black_24dp.png b/OpenKeychain/src/main/res/drawable-mdpi/ic_extension_black_24dp.png
new file mode 100644
index 000000000..075d6ca15
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-mdpi/ic_extension_black_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-mdpi/ic_ic_stat_tor.png b/OpenKeychain/src/main/res/drawable-mdpi/ic_ic_stat_tor.png
new file mode 100644
index 000000000..49b475fcb
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-mdpi/ic_ic_stat_tor.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-mdpi/ic_repeat_black_24dp.png b/OpenKeychain/src/main/res/drawable-mdpi/ic_repeat_black_24dp.png
new file mode 100644
index 000000000..c00a24ebf
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-mdpi/ic_repeat_black_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-mdpi/ic_settings_ethernet_black_24dp.png b/OpenKeychain/src/main/res/drawable-mdpi/ic_settings_ethernet_black_24dp.png
new file mode 100644
index 000000000..a9efbf176
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-mdpi/ic_settings_ethernet_black_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-mdpi/ic_stat_tor.png b/OpenKeychain/src/main/res/drawable-mdpi/ic_stat_tor.png
new file mode 100644
index 000000000..49b475fcb
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-mdpi/ic_stat_tor.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-mdpi/ic_stat_tor_off.png b/OpenKeychain/src/main/res/drawable-mdpi/ic_stat_tor_off.png
new file mode 100644
index 000000000..9d6447799
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-mdpi/ic_stat_tor_off.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-mdpi/ic_sync_black_24dp.png b/OpenKeychain/src/main/res/drawable-mdpi/ic_sync_black_24dp.png
new file mode 100644
index 000000000..9685e8e16
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-mdpi/ic_sync_black_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-mdpi/link_24dp.png b/OpenKeychain/src/main/res/drawable-mdpi/link_24dp.png
new file mode 100644
index 000000000..df43ca5f4
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-mdpi/link_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-mdpi/linked_dns.png b/OpenKeychain/src/main/res/drawable-mdpi/linked_dns.png
new file mode 100644
index 000000000..c6f3e9a06
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-mdpi/linked_dns.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-mdpi/linked_github.png b/OpenKeychain/src/main/res/drawable-mdpi/linked_github.png
new file mode 100644
index 000000000..ba3d2e4b7
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-mdpi/linked_github.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-mdpi/linked_https.png b/OpenKeychain/src/main/res/drawable-mdpi/linked_https.png
new file mode 100644
index 000000000..54b085aaf
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-mdpi/linked_https.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-mdpi/linked_twitter.png b/OpenKeychain/src/main/res/drawable-mdpi/linked_twitter.png
new file mode 100644
index 000000000..86ca9d46e
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-mdpi/linked_twitter.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-mdpi/octo_link_24dp.png b/OpenKeychain/src/main/res/drawable-mdpi/octo_link_24dp.png
new file mode 100644
index 000000000..5e0542f39
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-mdpi/octo_link_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-mdpi/status_signature_verified_inner_24dp.png b/OpenKeychain/src/main/res/drawable-mdpi/status_signature_verified_inner_24dp.png
new file mode 100644
index 000000000..28e37d9f3
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-mdpi/status_signature_verified_inner_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-mdpi/status_signature_verified_inner_96dp.png b/OpenKeychain/src/main/res/drawable-mdpi/status_signature_verified_inner_96dp.png
new file mode 100644
index 000000000..cc7091df0
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-mdpi/status_signature_verified_inner_96dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/account_key.png b/OpenKeychain/src/main/res/drawable-xhdpi/account_key.png
new file mode 100644
index 000000000..14ce08dbc
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xhdpi/account_key.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/ic_cloud_black_24dp.png b/OpenKeychain/src/main/res/drawable-xhdpi/ic_cloud_black_24dp.png
new file mode 100644
index 000000000..b688b3146
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xhdpi/ic_cloud_black_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/ic_extension_black_24dp.png b/OpenKeychain/src/main/res/drawable-xhdpi/ic_extension_black_24dp.png
new file mode 100644
index 000000000..8f5d4e64d
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xhdpi/ic_extension_black_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/ic_ic_stat_tor.png b/OpenKeychain/src/main/res/drawable-xhdpi/ic_ic_stat_tor.png
new file mode 100644
index 000000000..e76c09f8d
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xhdpi/ic_ic_stat_tor.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/ic_repeat_black_24dp.png b/OpenKeychain/src/main/res/drawable-xhdpi/ic_repeat_black_24dp.png
new file mode 100644
index 000000000..75ecb0462
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xhdpi/ic_repeat_black_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/ic_settings_ethernet_black_24dp.png b/OpenKeychain/src/main/res/drawable-xhdpi/ic_settings_ethernet_black_24dp.png
new file mode 100644
index 000000000..306338a77
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xhdpi/ic_settings_ethernet_black_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/ic_stat_tor.png b/OpenKeychain/src/main/res/drawable-xhdpi/ic_stat_tor.png
new file mode 100644
index 000000000..e76c09f8d
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xhdpi/ic_stat_tor.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/ic_stat_tor_off.png b/OpenKeychain/src/main/res/drawable-xhdpi/ic_stat_tor_off.png
new file mode 100644
index 000000000..5b1777c8e
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xhdpi/ic_stat_tor_off.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/ic_sync_black_24dp.png b/OpenKeychain/src/main/res/drawable-xhdpi/ic_sync_black_24dp.png
new file mode 100644
index 000000000..860a5db38
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xhdpi/ic_sync_black_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/link_24dp.png b/OpenKeychain/src/main/res/drawable-xhdpi/link_24dp.png
new file mode 100644
index 000000000..95eaeb381
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xhdpi/link_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/linked_dns.png b/OpenKeychain/src/main/res/drawable-xhdpi/linked_dns.png
new file mode 100644
index 000000000..ec87cdd1c
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xhdpi/linked_dns.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/linked_github.png b/OpenKeychain/src/main/res/drawable-xhdpi/linked_github.png
new file mode 100644
index 000000000..0934f1840
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xhdpi/linked_github.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/linked_https.png b/OpenKeychain/src/main/res/drawable-xhdpi/linked_https.png
new file mode 100644
index 000000000..f627d2b3b
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xhdpi/linked_https.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/linked_twitter.png b/OpenKeychain/src/main/res/drawable-xhdpi/linked_twitter.png
new file mode 100644
index 000000000..35bb1fd3b
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xhdpi/linked_twitter.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/octo_link_24dp.png b/OpenKeychain/src/main/res/drawable-xhdpi/octo_link_24dp.png
new file mode 100644
index 000000000..4c6420e08
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xhdpi/octo_link_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/status_signature_expired_cutout_96dp.png b/OpenKeychain/src/main/res/drawable-xhdpi/status_signature_expired_cutout_96dp.png
index 568b48c43..e69de29bb 100644
--- a/OpenKeychain/src/main/res/drawable-xhdpi/status_signature_expired_cutout_96dp.png
+++ b/OpenKeychain/src/main/res/drawable-xhdpi/status_signature_expired_cutout_96dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/status_signature_verified_inner_24dp.png b/OpenKeychain/src/main/res/drawable-xhdpi/status_signature_verified_inner_24dp.png
new file mode 100644
index 000000000..ea801c45a
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xhdpi/status_signature_verified_inner_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/status_signature_verified_inner_96dp.png b/OpenKeychain/src/main/res/drawable-xhdpi/status_signature_verified_inner_96dp.png
new file mode 100644
index 000000000..61610df19
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xhdpi/status_signature_verified_inner_96dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/account_key.png b/OpenKeychain/src/main/res/drawable-xxhdpi/account_key.png
new file mode 100644
index 000000000..c100a3034
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xxhdpi/account_key.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/ic_cloud_black_24dp.png b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_cloud_black_24dp.png
new file mode 100644
index 000000000..13c994e7d
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_cloud_black_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/ic_extension_black_24dp.png b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_extension_black_24dp.png
new file mode 100644
index 000000000..25c6154a1
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_extension_black_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/ic_ic_stat_tor.png b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_ic_stat_tor.png
new file mode 100644
index 000000000..5fdedd3b9
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_ic_stat_tor.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/ic_repeat_black_24dp.png b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_repeat_black_24dp.png
new file mode 100644
index 000000000..965a319ff
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_repeat_black_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/ic_settings_ethernet_black_24dp.png b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_settings_ethernet_black_24dp.png
new file mode 100644
index 000000000..2b31aa022
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_settings_ethernet_black_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/ic_stat_tor.png b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_stat_tor.png
new file mode 100644
index 000000000..5fdedd3b9
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_stat_tor.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/ic_stat_tor_off.png b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_stat_tor_off.png
new file mode 100644
index 000000000..2fb280a1b
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_stat_tor_off.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/ic_sync_black_24dp.png b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_sync_black_24dp.png
new file mode 100644
index 000000000..f7990080d
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_sync_black_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/link_24dp.png b/OpenKeychain/src/main/res/drawable-xxhdpi/link_24dp.png
new file mode 100644
index 000000000..a87af0738
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xxhdpi/link_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/linked_dns.png b/OpenKeychain/src/main/res/drawable-xxhdpi/linked_dns.png
new file mode 100644
index 000000000..9b3ee8572
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xxhdpi/linked_dns.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/linked_github.png b/OpenKeychain/src/main/res/drawable-xxhdpi/linked_github.png
new file mode 100644
index 000000000..19a3421bf
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xxhdpi/linked_github.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/linked_https.png b/OpenKeychain/src/main/res/drawable-xxhdpi/linked_https.png
new file mode 100644
index 000000000..c41ab6c1c
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xxhdpi/linked_https.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/linked_twitter.png b/OpenKeychain/src/main/res/drawable-xxhdpi/linked_twitter.png
new file mode 100644
index 000000000..0710a12f1
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xxhdpi/linked_twitter.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/octo_link_24dp.png b/OpenKeychain/src/main/res/drawable-xxhdpi/octo_link_24dp.png
new file mode 100644
index 000000000..02d3c6148
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xxhdpi/octo_link_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/status_signature_verified_inner_24dp.png b/OpenKeychain/src/main/res/drawable-xxhdpi/status_signature_verified_inner_24dp.png
new file mode 100644
index 000000000..bcd73b09b
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xxhdpi/status_signature_verified_inner_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/status_signature_verified_inner_96dp.png b/OpenKeychain/src/main/res/drawable-xxhdpi/status_signature_verified_inner_96dp.png
new file mode 100644
index 000000000..71e563218
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xxhdpi/status_signature_verified_inner_96dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_cloud_black_24dp.png b/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_cloud_black_24dp.png
new file mode 100644
index 000000000..9ac14e86a
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_cloud_black_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_extension_black_24dp.png b/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_extension_black_24dp.png
new file mode 100644
index 000000000..73067affc
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_extension_black_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_ic_stat_tor.png b/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_ic_stat_tor.png
new file mode 100644
index 000000000..306b94793
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_ic_stat_tor.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_repeat_black_24dp.png b/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_repeat_black_24dp.png
new file mode 100644
index 000000000..fd4d0c028
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_repeat_black_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_settings_ethernet_black_24dp.png b/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_settings_ethernet_black_24dp.png
new file mode 100644
index 000000000..e3848e5f2
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_settings_ethernet_black_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_stat_tor.png b/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_stat_tor.png
new file mode 100644
index 000000000..306b94793
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_stat_tor.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_stat_tor_off.png b/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_stat_tor_off.png
new file mode 100644
index 000000000..317c86717
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_stat_tor_off.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_sync_black_24dp.png b/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_sync_black_24dp.png
new file mode 100644
index 000000000..b9f56f327
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_sync_black_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xxxhdpi/link_24dp.png b/OpenKeychain/src/main/res/drawable-xxxhdpi/link_24dp.png
new file mode 100644
index 000000000..b8778938f
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xxxhdpi/link_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xxxhdpi/octo_link_24dp.png b/OpenKeychain/src/main/res/drawable-xxxhdpi/octo_link_24dp.png
new file mode 100644
index 000000000..deb16c07d
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xxxhdpi/octo_link_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xxxhdpi/status_signature_verified_inner_24dp.png b/OpenKeychain/src/main/res/drawable-xxxhdpi/status_signature_verified_inner_24dp.png
new file mode 100644
index 000000000..cc7091df0
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xxxhdpi/status_signature_verified_inner_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable/divider.xml b/OpenKeychain/src/main/res/drawable/divider.xml
new file mode 100644
index 000000000..b3800c459
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable/divider.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle" >
+
+ <size
+ android:height="1px"
+ android:width="1000dp" />
+
+ <solid android:color="#eeeeee" />
+
+</shape> \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/drawable/scrim_bottom.xml b/OpenKeychain/src/main/res/drawable/scrim_bottom.xml
new file mode 100644
index 000000000..b0c203835
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable/scrim_bottom.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+ <gradient
+ android:angle="90"
+ android:startColor="@color/translucent_scrim_bottom"
+ android:centerColor="@color/translucent_scrim_bottom_center"
+ android:endColor="@android:color/transparent"/>
+</shape> \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/layout/api_app_settings_activity.xml b/OpenKeychain/src/main/res/layout/api_app_settings_activity.xml
index ea20b77b3..5955fe8b5 100644
--- a/OpenKeychain/src/main/res/layout/api_app_settings_activity.xml
+++ b/OpenKeychain/src/main/res/layout/api_app_settings_activity.xml
@@ -29,7 +29,7 @@
android:minHeight="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:overScrollMode="always"
- app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
+ android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
tools:ignore="UnusedAttribute"
android:transitionGroup="false"
@@ -46,7 +46,7 @@
android:id="@+id/api_app_settings_app_icon"
android:layout_width="48dp"
android:layout_height="48dp"
- android:src="@drawable/ic_launcher" />
+ android:src="@mipmap/ic_launcher" />
<TextView
android:id="@+id/api_app_settings_app_name"
diff --git a/OpenKeychain/src/main/res/layout/api_app_settings_fragment.xml b/OpenKeychain/src/main/res/layout/api_app_settings_fragment.xml
index 20abb3965..c02b506af 100644
--- a/OpenKeychain/src/main/res/layout/api_app_settings_fragment.xml
+++ b/OpenKeychain/src/main/res/layout/api_app_settings_fragment.xml
@@ -17,7 +17,7 @@
android:layout_height="48dp"
android:layout_alignParentTop="true"
android:layout_marginRight="6dp"
- android:src="@drawable/ic_launcher" />
+ android:src="@mipmap/ic_launcher" />
<TextView
android:id="@+id/api_app_settings_app_name"
@@ -65,4 +65,4 @@
</org.sufficientlysecure.keychain.ui.widget.FoldableLinearLayout>
-</LinearLayout> \ No newline at end of file
+</LinearLayout>
diff --git a/OpenKeychain/src/main/res/layout/api_apps_adapter_list_item.xml b/OpenKeychain/src/main/res/layout/api_apps_adapter_list_item.xml
index 9166f958e..f6eafdbda 100644
--- a/OpenKeychain/src/main/res/layout/api_apps_adapter_list_item.xml
+++ b/OpenKeychain/src/main/res/layout/api_apps_adapter_list_item.xml
@@ -11,7 +11,7 @@
android:layout_height="48dp"
android:layout_marginLeft="8dp"
android:layout_centerVertical="true"
- android:src="@drawable/ic_launcher" />
+ android:src="@mipmap/ic_launcher" />
<ImageView
android:id="@+id/api_apps_adapter_install_icon"
@@ -34,4 +34,4 @@
android:layout_toLeftOf="@+id/api_apps_adapter_install_icon"
android:layout_toRightOf="@+id/api_apps_adapter_item_icon" />
-</RelativeLayout> \ No newline at end of file
+</RelativeLayout>
diff --git a/OpenKeychain/src/main/res/layout/cert_list_widget.xml b/OpenKeychain/src/main/res/layout/cert_list_widget.xml
new file mode 100644
index 000000000..7e3dbcdf4
--- /dev/null
+++ b/OpenKeychain/src/main/res/layout/cert_list_widget.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<org.sufficientlysecure.keychain.ui.widget.CertListWidget
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:id="@+id/linked_id_certs"
+ tools:showIn="@layout/linked_id_view_fragment">
+
+ <LinearLayout
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ tools:ignore="UseCompoundDrawables">
+
+ <TextView
+ android:id="@+id/cert_collapsed_list"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:gravity="center_vertical"
+ android:layout_weight="1"
+ tools:text="The identity is not yet verified or confirmed."
+ />
+
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:src="@drawable/ic_expand_more_black_24dp"
+ android:id="@+id/cert_expand_button"
+ android:padding="4dp"
+ />
+
+ </LinearLayout>
+
+ <ListView
+ android:id="@+id/cert_expanded_list"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+ </ListView>
+
+</org.sufficientlysecure.keychain.ui.widget.CertListWidget> \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/layout/certify_fingerprint_fragment.xml b/OpenKeychain/src/main/res/layout/certify_fingerprint_fragment.xml
index bd7b00823..239cdcc95 100644
--- a/OpenKeychain/src/main/res/layout/certify_fingerprint_fragment.xml
+++ b/OpenKeychain/src/main/res/layout/certify_fingerprint_fragment.xml
@@ -16,6 +16,7 @@
android:padding="16dp">
<TextView
+ android:id="@+id/certify_fingerprint_intro"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
diff --git a/OpenKeychain/src/main/res/layout/decrypt_text_fragment.xml b/OpenKeychain/src/main/res/layout/decrypt_text_fragment.xml
index 9362b35bb..f6237ec69 100644
--- a/OpenKeychain/src/main/res/layout/decrypt_text_fragment.xml
+++ b/OpenKeychain/src/main/res/layout/decrypt_text_fragment.xml
@@ -8,11 +8,11 @@
<LinearLayout
android:visibility="gone"
- tools:visibility="visible"
android:id="@+id/decrypt_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:orientation="vertical">
+ android:orientation="vertical"
+ tools:visibility="visible">
<ScrollView
android:fillViewport="true"
@@ -39,12 +39,12 @@
</LinearLayout>
<LinearLayout
- android:visibility="gone"
android:id="@+id/decrypt_error_overlay"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="vertical"
- android:gravity="center_vertical">
+ android:gravity="center_vertical"
+ android:visibility="gone">
<TextView
android:layout_width="wrap_content"
@@ -65,4 +65,4 @@
android:layout_gravity="center_horizontal" />
</LinearLayout>
-</org.sufficientlysecure.keychain.ui.widget.ToolableViewAnimator> \ No newline at end of file
+</org.sufficientlysecure.keychain.ui.widget.ToolableViewAnimator>
diff --git a/OpenKeychain/src/main/res/layout/help_about_fragment.xml b/OpenKeychain/src/main/res/layout/help_about_fragment.xml
index dbcd97bfd..cbe1c3331 100644
--- a/OpenKeychain/src/main/res/layout/help_about_fragment.xml
+++ b/OpenKeychain/src/main/res/layout/help_about_fragment.xml
@@ -32,7 +32,7 @@
android:layout_height="wrap_content"
android:layout_gravity="top"
android:layout_marginRight="10dp"
- android:src="@drawable/ic_launcher" />
+ android:src="@mipmap/ic_launcher" />
</LinearLayout>
<LinearLayout
diff --git a/OpenKeychain/src/main/res/layout/key_list_fragment.xml b/OpenKeychain/src/main/res/layout/key_list_fragment.xml
index 9c41590db..26cedd362 100644
--- a/OpenKeychain/src/main/res/layout/key_list_fragment.xml
+++ b/OpenKeychain/src/main/res/layout/key_list_fragment.xml
@@ -63,7 +63,7 @@
fab:fab_icon="@drawable/ic_qrcode_white_24dp"
fab:fab_colorNormal="?attr/colorPrimary"
fab:fab_colorPressed="?attr/colorPrimaryDark"
- fab:fab_title="Scan QR Code"
+ fab:fab_title="@string/key_list_fab_qr_code"
fab:fab_size="mini" />
<com.getbase.floatingactionbutton.FloatingActionButton
@@ -73,7 +73,7 @@
fab:fab_icon="@drawable/ic_cloud_search_24dp"
fab:fab_colorNormal="?attr/colorPrimary"
fab:fab_colorPressed="?attr/colorPrimaryDark"
- fab:fab_title="Search Cloud"
+ fab:fab_title="@string/key_list_fab_search"
fab:fab_size="mini" />
<com.getbase.floatingactionbutton.FloatingActionButton
@@ -83,7 +83,7 @@
fab:fab_icon="@drawable/ic_folder_white_24dp"
fab:fab_colorNormal="?attr/colorPrimary"
fab:fab_colorPressed="?attr/colorPrimaryDark"
- fab:fab_title="Import from File"
+ fab:fab_title="@string/key_list_fab_import"
fab:fab_size="mini" />
</com.getbase.floatingactionbutton.FloatingActionsMenu>
diff --git a/OpenKeychain/src/main/res/layout/keyspinner_item_none.xml b/OpenKeychain/src/main/res/layout/keyspinner_item_none.xml
index bd1d4ac11..a7a7a10df 100644
--- a/OpenKeychain/src/main/res/layout/keyspinner_item_none.xml
+++ b/OpenKeychain/src/main/res/layout/keyspinner_item_none.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
@@ -13,7 +14,8 @@
android:id="@+id/keyspinner_key_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:text="@string/choice_none"
- android:textAppearance="?android:attr/textAppearanceMedium" />
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ tools:text="@string/choice_none"
+ />
</LinearLayout> \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/layout/linked_create_github_fragment.xml b/OpenKeychain/src/main/res/layout/linked_create_github_fragment.xml
new file mode 100644
index 000000000..e1c8db383
--- /dev/null
+++ b/OpenKeychain/src/main/res/layout/linked_create_github_fragment.xml
@@ -0,0 +1,235 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ xmlns:custom="http://schemas.android.com/apk/res-auto">
+
+ <ScrollView
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:fillViewport="false"
+ android:layout_above="@+id/create_key_button_divider">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:padding="16dp"
+ android:orientation="vertical">
+
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal">
+
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_margin="8dp"
+ android:src="@drawable/linked_github" />
+
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:layout_margin="8dp"
+ android:src="@drawable/octo_link_24dp" />
+
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:layout_margin="8dp"
+ android:src="@drawable/account_key" />
+
+ </LinearLayout>
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="16dp"
+ android:layout_marginBottom="16dp"
+ android:text="@string/linked_github_text"
+ style="?android:textAppearanceSmall"/>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:layout_marginTop="8dp"
+ android:layout_marginBottom="8dp">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <org.sufficientlysecure.keychain.ui.widget.StatusIndicator
+ android:layout_width="24dp"
+ android:layout_height="24dp"
+ android:id="@+id/linked_status_step1"
+ android:layout_margin="4dp" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:text="@string/linked_progress_auth_github"
+ style="?android:textAppearanceMedium"
+ />
+
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <org.sufficientlysecure.keychain.ui.widget.StatusIndicator
+ android:layout_width="24dp"
+ android:layout_height="24dp"
+ android:id="@+id/linked_status_step2"
+ android:layout_margin="4dp" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:text="@string/linked_progress_post_gist"
+ style="?android:textAppearanceMedium"
+ />
+
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <org.sufficientlysecure.keychain.ui.widget.StatusIndicator
+ android:layout_width="24dp"
+ android:layout_height="24dp"
+ android:id="@+id/linked_status_step3"
+ android:layout_margin="4dp" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:text="@string/linked_progress_update_key"
+ style="?android:textAppearanceMedium"
+ />
+ </LinearLayout>
+
+ </LinearLayout>
+
+ <org.sufficientlysecure.keychain.ui.widget.ToolableViewAnimator
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:id="@+id/button_container"
+ android:layout_marginTop="16dp"
+ android:layout_marginBottom="16dp"
+ android:layout_marginRight="4dp"
+ android:layout_marginLeft="4dp"
+ android:inAnimation="@anim/fade_in"
+ android:outAnimation="@anim/fade_out"
+ android:clipChildren="false"
+ custom:initialView="3">
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:drawableLeft="@drawable/link_24dp"
+ android:drawableStart="@drawable/link_24dp"
+ android:drawablePadding="12dp"
+ android:text="@string/linked_button_start"
+ android:id="@+id/button_send"
+ />
+
+ <Space
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
+ <include layout="@layout/linked_id_item" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:drawableLeft="@drawable/ic_repeat_black_24dp"
+ android:drawableStart="@drawable/ic_repeat_black_24dp"
+ android:drawablePadding="12dp"
+ android:text="@string/linked_button_retry"
+ android:id="@+id/button_retry"
+ />
+
+ </org.sufficientlysecure.keychain.ui.widget.ToolableViewAnimator>
+
+ </LinearLayout>
+
+ </ScrollView>
+
+ <View
+ android:id="@+id/create_key_button_divider"
+ android:layout_width="match_parent"
+ android:layout_height="1dip"
+ android:layout_marginLeft="16dp"
+ android:layout_marginRight="16dp"
+ android:background="?android:attr/listDivider"
+ android:layout_alignTop="@+id/create_key_buttons"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentStart="true" />
+
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:layout_alignParentBottom="true"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentStart="true"
+ android:layout_marginLeft="16dp"
+ android:layout_marginRight="16dp"
+ android:id="@+id/create_key_buttons">
+
+ <TextView
+ android:id="@+id/back_button"
+ android:paddingLeft="8dp"
+ android:paddingRight="8dp"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text="@string/btn_back"
+ android:minHeight="?android:attr/listPreferredItemHeight"
+ android:textAllCaps="true"
+ style="?android:attr/borderlessButtonStyle"
+ android:drawableLeft="@drawable/ic_chevron_left_grey_24dp"
+ android:drawablePadding="8dp"
+ android:gravity="center_vertical"
+ android:clickable="true"
+ android:layout_gravity="center_vertical" />
+
+ <View
+ android:layout_width="1dp"
+ android:layout_height="match_parent"
+ android:layout_marginTop="8dp"
+ android:layout_marginBottom="8dp"
+ android:background="?android:attr/listDivider" />
+
+ <TextView
+ android:paddingLeft="8dp"
+ android:paddingRight="8dp"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text="@string/btn_finish"
+ android:minHeight="?android:attr/listPreferredItemHeight"
+ android:textAllCaps="true"
+ android:drawableRight="@drawable/ic_person_add_grey_24dp"
+ android:drawablePadding="8dp"
+ style="?android:attr/borderlessButtonStyle"
+ android:gravity="center_vertical|right"
+ android:layout_gravity="center_vertical"
+ android:visibility="invisible" />
+ </LinearLayout>
+
+</RelativeLayout> \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/layout/linked_create_https_fragment_step1.xml b/OpenKeychain/src/main/res/layout/linked_create_https_fragment_step1.xml
new file mode 100644
index 000000000..8b6047e21
--- /dev/null
+++ b/OpenKeychain/src/main/res/layout/linked_create_https_fragment_step1.xml
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:custom="http://schemas.android.com/apk/res-auto"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent">
+
+ <ScrollView
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:fillViewport="false"
+ android:layout_above="@+id/create_key_button_divider">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:padding="16dp"
+ android:orientation="vertical">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:drawableLeft="@drawable/linked_https"
+ android:drawablePadding="8dp"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:text="@string/linked_create_https_1_1" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="16dp"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:text="@string/linked_create_https_1_2" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="16dp"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:text="@string/linked_create_https_1_3" />
+
+ <org.sufficientlysecure.keychain.ui.widget.PrefixedEditText
+ android:id="@+id/linked_create_https_uri"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:imeOptions="actionNext"
+ android:layout_marginTop="16dp"
+ android:ems="10"
+ android:inputType="textUri"
+ android:layout_gravity="center_horizontal"
+ custom:prefix="https://"
+ />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="16dp"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:text="@string/linked_create_https_1_4" />
+
+ </LinearLayout>
+
+ </ScrollView>
+
+ <View
+ android:id="@+id/create_key_button_divider"
+ android:layout_width="match_parent"
+ android:layout_height="1dip"
+ android:layout_marginLeft="16dp"
+ android:layout_marginRight="16dp"
+ android:background="?android:attr/listDivider"
+ android:layout_alignTop="@+id/create_key_buttons"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentStart="true" />
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:layout_alignParentBottom="true"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentStart="true"
+ android:layout_marginLeft="16dp"
+ android:layout_marginRight="16dp"
+ android:id="@+id/create_key_buttons">
+
+ <TextView
+ android:id="@+id/back_button"
+ android:paddingLeft="8dp"
+ android:paddingRight="8dp"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text="@string/btn_back"
+ android:clickable="true"
+ android:minHeight="?android:attr/listPreferredItemHeight"
+ android:textAllCaps="true"
+ style="?android:attr/borderlessButtonStyle"
+ android:drawableLeft="@drawable/ic_chevron_left_grey_24dp"
+ android:drawablePadding="8dp"
+ android:gravity="center_vertical"
+ android:layout_gravity="center_vertical" />
+
+ <View
+ android:layout_width="1dp"
+ android:layout_height="match_parent"
+ android:layout_marginTop="8dp"
+ android:layout_marginBottom="8dp"
+ android:background="?android:attr/listDivider" />
+
+ <TextView
+ android:id="@+id/next_button"
+ android:paddingLeft="8dp"
+ android:paddingRight="8dp"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text="@string/btn_next"
+ android:minHeight="?android:attr/listPreferredItemHeight"
+ android:textAllCaps="true"
+ android:drawableRight="@drawable/ic_chevron_right_grey_24dp"
+ android:drawablePadding="8dp"
+ android:gravity="center_vertical|right"
+ style="?android:attr/borderlessButtonStyle"
+ android:clickable="true"
+ android:layout_gravity="center_vertical" />
+ </LinearLayout>
+</RelativeLayout> \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/layout/linked_create_https_fragment_step2.xml b/OpenKeychain/src/main/res/layout/linked_create_https_fragment_step2.xml
new file mode 100644
index 000000000..dc6895a54
--- /dev/null
+++ b/OpenKeychain/src/main/res/layout/linked_create_https_fragment_step2.xml
@@ -0,0 +1,165 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent">
+
+ <ScrollView
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:fillViewport="false"
+ android:layout_above="@+id/create_key_button_divider">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingLeft="16dp"
+ android:paddingRight="16dp"
+ android:orientation="vertical">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="16dp"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:text="@string/linked_create_https_2_1" />
+
+ <EditText
+ android:id="@+id/linked_create_https_uri"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:imeOptions="actionNext"
+ android:layout_marginTop="8dp"
+ android:hint="uri"
+ android:ems="10"
+ android:layout_gravity="center_horizontal"
+ android:inputType="textUri|none"
+ android:enabled="false"/>
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="16dp"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:text="@string/linked_create_https_2_2" />
+
+ <LinearLayout
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dp"
+ android:layout_gravity="center_horizontal"
+ style="?android:buttonBarStyle"
+ >
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:layout_marginLeft="8dp"
+ android:layout_marginRight="8dp"
+ style="?android:buttonBarButtonStyle"
+ android:drawableLeft="@android:drawable/ic_menu_save"
+ android:drawableStart="@android:drawable/ic_menu_save"
+ android:text="Save"
+ android:id="@+id/button_save"
+ />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:layout_marginLeft="8dp"
+ android:layout_marginRight="8dp"
+ style="?android:buttonBarButtonStyle"
+ android:drawableLeft="@android:drawable/ic_menu_share"
+ android:drawableStart="@android:drawable/ic_menu_share"
+ android:text="Share"
+ android:id="@+id/button_send"
+ />
+
+ </LinearLayout>
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="16dp"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:text="@string/linked_create_https_2_3" />
+
+ <include layout="@layout/linked_create_verify" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="16dp"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:text="@string/linked_create_https_2_4" />
+
+ </LinearLayout>
+
+ </ScrollView>
+
+ <View
+ android:id="@+id/create_key_button_divider"
+ android:layout_width="match_parent"
+ android:layout_height="1dip"
+ android:layout_marginLeft="16dp"
+ android:layout_marginRight="16dp"
+ android:background="?android:attr/listDivider"
+ android:layout_alignTop="@+id/create_key_buttons"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentStart="true" />
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:layout_alignParentBottom="true"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentStart="true"
+ android:layout_marginLeft="16dp"
+ android:layout_marginRight="16dp"
+ android:id="@+id/create_key_buttons">
+
+ <TextView
+ android:id="@+id/back_button"
+ android:paddingLeft="8dp"
+ android:paddingRight="8dp"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text="@string/btn_back"
+ android:minHeight="?android:attr/listPreferredItemHeight"
+ android:clickable="true"
+ android:textAllCaps="true"
+ style="?android:attr/borderlessButtonStyle"
+ android:drawableLeft="@drawable/ic_chevron_left_grey_24dp"
+ android:drawablePadding="8dp"
+ android:gravity="center_vertical"
+ android:layout_gravity="center_vertical" />
+
+ <View
+ android:layout_width="1dp"
+ android:layout_height="match_parent"
+ android:layout_marginTop="8dp"
+ android:layout_marginBottom="8dp"
+ android:background="?android:attr/listDivider" />
+
+ <TextView
+ android:id="@+id/next_button"
+ android:paddingLeft="8dp"
+ android:paddingRight="8dp"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text="@string/btn_finish"
+ android:minHeight="?android:attr/listPreferredItemHeight"
+ android:textAllCaps="true"
+ android:drawableRight="@drawable/ic_person_add_grey_24dp"
+ android:drawablePadding="8dp"
+ style="?android:attr/borderlessButtonStyle"
+ android:gravity="center_vertical|right"
+ android:layout_gravity="center_vertical" />
+ </LinearLayout>
+</RelativeLayout> \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/layout/linked_create_twitter_fragment_step1.xml b/OpenKeychain/src/main/res/layout/linked_create_twitter_fragment_step1.xml
new file mode 100644
index 000000000..848ee47f4
--- /dev/null
+++ b/OpenKeychain/src/main/res/layout/linked_create_twitter_fragment_step1.xml
@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:custom="http://schemas.android.com/apk/res-auto"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ >
+
+ <ScrollView
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:fillViewport="false"
+ android:layout_above="@+id/create_key_button_divider">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:padding="16dp"
+ android:orientation="vertical">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:drawableLeft="@drawable/linked_twitter"
+ android:drawablePadding="8dp"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:text="@string/linked_create_twitter_1_1" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="16dp"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:text="@string/linked_create_twitter_1_2" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="16dp"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:text="@string/linked_create_twitter_1_3" />
+
+ <org.sufficientlysecure.keychain.ui.widget.PrefixedEditText
+ android:id="@+id/linked_create_twitter_handle"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:imeOptions="actionNext"
+ android:layout_marginTop="16dp"
+ android:ems="10"
+ android:layout_gravity="center_horizontal"
+ android:inputType="text"
+ android:hint="@string/linked_create_twitter_handle"
+ custom:prefix="\@"
+ />
+
+ </LinearLayout>
+
+ </ScrollView>
+
+ <View
+ android:id="@+id/create_key_button_divider"
+ android:layout_width="match_parent"
+ android:layout_height="1dip"
+ android:layout_marginLeft="16dp"
+ android:layout_marginRight="16dp"
+ android:background="?android:attr/listDivider"
+ android:layout_alignTop="@+id/create_key_buttons"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentStart="true" />
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:layout_alignParentBottom="true"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentStart="true"
+ android:layout_marginLeft="16dp"
+ android:layout_marginRight="16dp"
+ android:id="@+id/create_key_buttons">
+
+ <TextView
+ android:id="@+id/back_button"
+ android:paddingLeft="8dp"
+ android:paddingRight="8dp"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text="@string/btn_back"
+ android:minHeight="?android:attr/listPreferredItemHeight"
+ android:textAllCaps="true"
+ style="?android:attr/borderlessButtonStyle"
+ android:drawableLeft="@drawable/ic_chevron_left_grey_24dp"
+ android:drawablePadding="8dp"
+ android:clickable="true"
+ android:gravity="center_vertical"
+ android:layout_gravity="center_vertical" />
+
+ <View
+ android:layout_width="1dp"
+ android:layout_height="match_parent"
+ android:layout_marginTop="8dp"
+ android:layout_marginBottom="8dp"
+ android:background="?android:attr/listDivider" />
+
+ <TextView
+ android:id="@+id/next_button"
+ android:paddingLeft="8dp"
+ android:paddingRight="8dp"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text="@string/btn_next"
+ android:minHeight="?android:attr/listPreferredItemHeight"
+ android:textAllCaps="true"
+ style="?android:attr/borderlessButtonStyle"
+ android:drawableRight="@drawable/ic_chevron_right_grey_24dp"
+ android:drawablePadding="8dp"
+ android:gravity="center_vertical|right"
+ android:layout_gravity="center_vertical" />
+ </LinearLayout>
+</RelativeLayout> \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/layout/linked_create_twitter_fragment_step2.xml b/OpenKeychain/src/main/res/layout/linked_create_twitter_fragment_step2.xml
new file mode 100644
index 000000000..e66946482
--- /dev/null
+++ b/OpenKeychain/src/main/res/layout/linked_create_twitter_fragment_step2.xml
@@ -0,0 +1,154 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent">
+
+ <ScrollView
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:fillViewport="false"
+ android:layout_above="@+id/create_key_button_divider">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingLeft="16dp"
+ android:paddingRight="16dp"
+ android:orientation="vertical">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="16dp"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:text="@string/linked_create_twitter_2_1" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="16dp"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:text="@string/linked_create_twitter_2_2" />
+
+ <LinearLayout
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dp"
+ android:layout_gravity="center_horizontal"
+ style="?android:buttonBarStyle">
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:layout_marginLeft="8dp"
+ android:layout_marginRight="8dp"
+ style="?android:buttonBarButtonStyle"
+ android:drawableLeft="@android:drawable/ic_menu_send"
+ android:drawableStart="@android:drawable/ic_menu_send"
+ android:text="Tweet"
+ android:id="@+id/button_send"
+ />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:layout_marginLeft="8dp"
+ android:layout_marginRight="8dp"
+ style="?android:buttonBarButtonStyle"
+ android:drawableLeft="@android:drawable/ic_menu_share"
+ android:drawableStart="@android:drawable/ic_menu_share"
+ android:text="Share"
+ android:id="@+id/button_share"
+ />
+
+ </LinearLayout>
+
+ <TextView
+ android:id="@+id/linked_tweet_published"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="16dp"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ tools:text="@string/linked_create_twitter_2_3" />
+
+ <include layout="@layout/linked_create_verify" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="16dp"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:text="@string/linked_create_twitter_2_4" />
+
+ </LinearLayout>
+
+ </ScrollView>
+
+ <View
+ android:id="@+id/create_key_button_divider"
+ android:layout_width="match_parent"
+ android:layout_height="1dip"
+ android:layout_marginLeft="16dp"
+ android:layout_marginRight="16dp"
+ android:background="?android:attr/listDivider"
+ android:layout_alignTop="@+id/create_key_buttons"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentStart="true" />
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:layout_alignParentBottom="true"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentStart="true"
+ android:layout_marginLeft="16dp"
+ android:layout_marginRight="16dp"
+ android:id="@+id/create_key_buttons">
+
+ <TextView
+ android:id="@+id/back_button"
+ android:paddingLeft="8dp"
+ android:paddingRight="8dp"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text="@string/btn_back"
+ android:minHeight="?android:attr/listPreferredItemHeight"
+ android:textAllCaps="true"
+ style="?android:attr/borderlessButtonStyle"
+ android:drawableLeft="@drawable/ic_chevron_left_grey_24dp"
+ android:drawablePadding="8dp"
+ android:gravity="center_vertical"
+ android:clickable="true"
+ android:layout_gravity="center_vertical" />
+
+ <View
+ android:layout_width="1dp"
+ android:layout_height="match_parent"
+ android:layout_marginTop="8dp"
+ android:layout_marginBottom="8dp"
+ android:background="?android:attr/listDivider" />
+
+ <TextView
+ android:id="@+id/next_button"
+ android:paddingLeft="8dp"
+ android:paddingRight="8dp"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text="@string/btn_finish"
+ android:minHeight="?android:attr/listPreferredItemHeight"
+ android:textAllCaps="true"
+ android:drawableRight="@drawable/ic_person_add_grey_24dp"
+ android:drawablePadding="8dp"
+ style="?android:attr/borderlessButtonStyle"
+ android:gravity="center_vertical|right"
+ android:layout_gravity="center_vertical" />
+ </LinearLayout>
+</RelativeLayout> \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/layout/linked_create_verify.xml b/OpenKeychain/src/main/res/layout/linked_create_verify.xml
new file mode 100644
index 000000000..9f9dbcd97
--- /dev/null
+++ b/OpenKeychain/src/main/res/layout/linked_create_verify.xml
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ tools:showIn="@layout/linked_create_github_fragment_step2">
+
+ <ViewAnimator
+ android:id="@+id/verify_progress"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="16dip"
+ android:layout_marginStart="16dip"
+ android:layout_gravity="center_vertical"
+ android:inAnimation="@anim/fade_in"
+ android:outAnimation="@anim/fade_out"
+ >
+
+ <ImageView
+ android:layout_width="24dp"
+ android:layout_height="24dp"
+ android:id="@+id/verify_image"
+ android:src="@drawable/status_signature_unverified_cutout_24dp"
+ />
+
+ <ProgressBar
+ android:layout_width="24dp"
+ android:layout_height="24dp"
+ android:indeterminateOnly="true" />
+
+ </ViewAnimator>
+
+ <TextView
+ android:id="@+id/verify_status"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:text="@string/linked_verify_pending"
+ android:layout_marginLeft="16dip"
+ android:layout_marginStart="16dip"
+ android:layout_weight="1"
+ />
+
+ <ViewAnimator
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginRight="16dp"
+ android:layout_marginEnd="16dip"
+ android:inAnimation="@anim/fade_in"
+ android:outAnimation="@anim/fade_out"
+ android:id="@+id/verify_buttons"
+ >
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ style="?android:buttonBarButtonStyle"
+ android:text="@string/linked_button_verify"
+ android:id="@+id/button_verify"
+ />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ style="?android:buttonBarButtonStyle"
+ android:text="@string/linked_button_retry"
+ android:id="@+id/button_retry"
+ />
+
+ <Space
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
+ </ViewAnimator>
+
+</LinearLayout> \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/layout/linked_id_item.xml b/OpenKeychain/src/main/res/layout/linked_id_item.xml
new file mode 100644
index 000000000..e4fe58551
--- /dev/null
+++ b/OpenKeychain/src/main/res/layout/linked_id_item.xml
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:minHeight="?android:attr/listPreferredItemHeight"
+ android:orientation="horizontal"
+ android:singleLine="true"
+ android:background="#ffffff"
+ tools:showIn="@layout/linked_id_view_fragment">
+
+ <ImageView
+ android:layout_width="32dp"
+ android:layout_height="32dp"
+ android:id="@+id/linked_id_type_icon"
+ android:layout_marginLeft="14dp"
+ android:layout_marginStart="14dp"
+ tools:src="@drawable/linked_dns"
+ android:layout_gravity="center_vertical"
+ android:scaleType="fitCenter" />
+
+ <LinearLayout
+ android:orientation="vertical"
+ android:layout_gravity="center_vertical"
+ android:layout_width="0dip"
+ android:layout_marginLeft="8dp"
+ android:layout_marginTop="4dp"
+ android:layout_marginBottom="4dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1">
+
+ <TextView
+ android:id="@+id/linked_id_title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ tools:text="Title"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ />
+
+ <TextView
+ android:id="@+id/linked_id_comment"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ tools:text="comment"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ />
+
+ </LinearLayout>
+
+ <ViewAnimator
+ android:id="@+id/linked_id_certified"
+ android:layout_width="22dp"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="16dp"
+ android:layout_marginRight="16dp"
+ android:outAnimation="@anim/fade_out_down"
+ android:inAnimation="@anim/fade_in_up"
+ android:layout_gravity="center_vertical"
+ android:orientation="vertical">
+
+ <ImageView
+ android:id="@+id/linked_id_certified_icon"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ tools:src="@drawable/status_signature_unknown_cutout_24dp"
+ />
+
+ <Space
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content" />
+
+ </ViewAnimator>
+
+</LinearLayout>
diff --git a/OpenKeychain/src/main/res/layout/linked_id_view_fragment.xml b/OpenKeychain/src/main/res/layout/linked_id_view_fragment.xml
new file mode 100644
index 000000000..377ce4fb6
--- /dev/null
+++ b/OpenKeychain/src/main/res/layout/linked_id_view_fragment.xml
@@ -0,0 +1,193 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:card_view="http://schemas.android.com/apk/res-auto"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:paddingTop="16dp"
+ android:paddingBottom="16dp"
+ android:paddingLeft="16dp"
+ android:paddingRight="16dp">
+
+ <android.support.v7.widget.CardView
+ android:id="@+id/card_linked_ids"
+ android:transitionName="card_linked_ids"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ card_view:cardBackgroundColor="@android:color/white"
+ card_view:cardElevation="2dp"
+ card_view:cardUseCompatPadding="true"
+ card_view:cardCornerRadius="4dp">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:animateLayoutChanges="true"
+ android:orientation="vertical">
+
+ <TextView
+ style="@style/CardViewHeader"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/card_linked_identity" />
+
+ <include layout="@layout/linked_id_item" />
+
+ <ViewAnimator
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:id="@+id/linked_verify_container"
+ android:layout_marginLeft="12dp"
+ android:layout_marginRight="12dp"
+ android:measureAllChildren="false"
+ >
+
+ <include layout="@layout/cert_list_widget" />
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:baselineAligned="false"
+ android:animateLayoutChanges="true"
+ >
+
+ <TextSwitcher
+ android:id="@+id/linked_cert_text"
+ android:layout_height="wrap_content"
+ android:layout_width="0dip"
+ android:layout_marginLeft="8dp"
+ android:layout_marginTop="4dp"
+ android:layout_marginBottom="4dp"
+ android:inAnimation="@anim/fade_in_quick"
+ android:outAnimation="@anim/fade_out_quick"
+ android:measureAllChildren="false"
+ android:layout_weight="1">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceSmall" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceSmall" />
+
+ </TextSwitcher>
+
+ <ViewAnimator
+ android:layout_width="22dp"
+ android:layout_height="22dp"
+ android:layout_marginLeft="16dp"
+ android:layout_marginRight="4dp"
+ android:layout_gravity="center"
+ android:id="@+id/linked_cert_progress"
+ android:inAnimation="@anim/fade_in"
+ android:outAnimation="@anim/fade_out">
+
+ <ProgressBar
+ android:layout_width="22dp"
+ android:layout_height="22dp"
+ android:indeterminate="true"
+ />
+
+ <ImageView
+ android:id="@+id/status_icon_verified"
+ android:layout_width="22dp"
+ android:layout_height="wrap_content"
+ android:src="@drawable/status_signature_verified_inner_24dp"
+ />
+
+ <ImageView
+ android:id="@+id/status_icon_invalid"
+ android:layout_width="22dp"
+ android:layout_height="wrap_content"
+ android:src="@drawable/status_signature_invalid_cutout_24dp"
+ />
+
+ </ViewAnimator>
+
+ </LinearLayout>
+
+ </ViewAnimator>
+
+ <!-- this layout is used for a highlight thing, so we use padding instead of margin -->
+ <LinearLayout
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:paddingLeft="14dp"
+ android:paddingRight="14dp"
+ android:id="@+id/cert_key_spincontainer"
+ android:visibility="gone"
+ tools:visibility="visible"
+ >
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:layout_marginRight="4dp"
+ android:layout_marginEnd="4dp"
+ android:text="@string/add_keys_my_key" />
+
+ <org.sufficientlysecure.keychain.ui.widget.CertifyKeySpinner
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:id="@+id/cert_key_spinner">
+ </org.sufficientlysecure.keychain.ui.widget.CertifyKeySpinner>
+
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:gravity="right|end">
+
+ <Button
+ android:id="@+id/button_view"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/linked_button_view"
+ android:textColor="@color/link_text_material_light"
+ style="?android:attr/borderlessButtonStyle"
+ />
+
+ <ViewAnimator
+ android:id="@+id/button_animator"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:inAnimation="@anim/fade_in"
+ android:outAnimation="@anim/fade_out">
+ <Button
+ android:id="@+id/button_verify"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/linked_button_verify"
+ android:textColor="@color/link_text_material_light"
+ style="?android:attr/borderlessButtonStyle" />
+ <Button
+ android:id="@+id/button_retry"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/linked_button_retry"
+ android:textColor="@color/link_text_material_light"
+ style="?android:attr/borderlessButtonStyle" />
+ <Button
+ android:id="@+id/button_confirm"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/linked_button_confirm"
+ android:textColor="@color/link_text_material_light"
+ style="?android:attr/borderlessButtonStyle" />
+ </ViewAnimator>
+
+ </LinearLayout>
+
+ </LinearLayout>
+
+ </android.support.v7.widget.CardView>
+
+</ScrollView> \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/layout/linked_select_fragment.xml b/OpenKeychain/src/main/res/layout/linked_select_fragment.xml
new file mode 100644
index 000000000..a8d7b408b
--- /dev/null
+++ b/OpenKeychain/src/main/res/layout/linked_select_fragment.xml
@@ -0,0 +1,188 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingLeft="16dp"
+ android:paddingRight="16dp"
+ android:orientation="vertical">
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="16dp"
+ android:layout_marginBottom="8dp"
+ android:layout_marginLeft="8dp"
+ android:layout_marginRight="8dp"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:text="@string/linked_select_1"
+ android:id="@+id/textView"
+ android:layout_weight="1" />
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="8dp"
+ android:layout_marginLeft="8dp"
+ android:layout_marginRight="8dp"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:text="@string/linked_select_2"
+ android:layout_weight="1" />
+
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="1dip"
+ android:background="?android:attr/listDivider" />
+
+ <LinearLayout
+ android:id="@+id/linked_create_github_button"
+ android:layout_width="match_parent"
+ android:layout_height="?android:attr/listPreferredItemHeight"
+ android:layout_marginTop="2dp"
+ android:layout_marginBottom="2dp"
+ android:clickable="true"
+ android:background="?android:selectableItemBackground"
+ android:orientation="horizontal">
+
+ <!-- separate ImageView required for recoloring -->
+ <ImageView
+ android:layout_width="60dip"
+ android:layout_height="60dip"
+ android:padding="8dp"
+ android:src="@drawable/linked_github"
+ android:layout_gravity="center"
+ />
+
+ <TextView
+ android:paddingLeft="8dp"
+ android:paddingRight="8dp"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:layout_width="0dip"
+ android:layout_height="match_parent"
+ android:text="@string/linked_title_github"
+ android:layout_weight="1"
+ android:gravity="center_vertical" />
+
+ </LinearLayout>
+
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="1dip"
+ android:background="?android:attr/listDivider" />
+
+ <LinearLayout
+ android:id="@+id/linked_create_twitter_button"
+ android:layout_width="match_parent"
+ android:layout_height="?android:attr/listPreferredItemHeight"
+ android:layout_marginTop="2dp"
+ android:layout_marginBottom="2dp"
+ android:clickable="true"
+ android:background="?android:selectableItemBackground"
+ android:orientation="horizontal">
+
+ <!-- separate ImageView required for recoloring -->
+ <ImageView
+ android:layout_width="60dip"
+ android:layout_height="60dip"
+ android:padding="8dp"
+ android:src="@drawable/linked_twitter"
+ android:layout_gravity="center"
+ />
+
+ <TextView
+ android:paddingLeft="8dp"
+ android:paddingRight="8dp"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:layout_width="0dip"
+ android:layout_height="match_parent"
+ android:text="@string/linked_title_twitter"
+ android:layout_weight="1"
+ android:gravity="center_vertical" />
+
+ </LinearLayout>
+
+ <!--
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="1dip"
+ android:layout_marginBottom="4dp"
+ android:background="?android:attr/listDivider" />
+
+ <LinearLayout
+ android:id="@+id/linked_create_dns_button"
+ android:layout_width="match_parent"
+ android:layout_height="?android:attr/listPreferredItemHeight"
+ android:clickable="true"
+ android:background="?android:selectableItemBackground"
+ android:orientation="horizontal">
+
+ <!- separate ImageView required for recoloring ->
+ <ImageView
+ android:layout_width="60dip"
+ android:layout_height="60dip"
+ android:padding="8dp"
+ android:src="@drawable/linked_dns"
+ android:layout_gravity="center"
+ />
+
+ <TextView
+ android:paddingLeft="8dp"
+ android:paddingRight="8dp"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:layout_width="0dip"
+ android:layout_height="match_parent"
+ android:text="@string/linked_title_dns"
+ android:layout_weight="1"
+ android:gravity="center_vertical" />
+
+ </LinearLayout>
+ -->
+
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="1dip"
+ android:background="?android:attr/listDivider" />
+
+ <LinearLayout
+ android:id="@+id/linked_create_https_button"
+ android:layout_width="match_parent"
+ android:layout_height="?android:attr/listPreferredItemHeight"
+ android:layout_marginTop="2dp"
+ android:layout_marginBottom="2dp"
+ android:clickable="true"
+ android:background="?android:selectableItemBackground"
+ android:orientation="horizontal">
+
+ <!-- separate ImageView required for recoloring -->
+ <ImageView
+ android:id="@+id/certify_key_action_certify_image"
+ android:layout_width="60dip"
+ android:layout_height="60dip"
+ android:padding="8dp"
+ android:src="@drawable/linked_https"
+ android:layout_gravity="center_vertical" />
+
+ <TextView
+ android:paddingLeft="8dp"
+ android:paddingRight="8dp"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:layout_width="0dip"
+ android:layout_height="match_parent"
+ android:text="@string/linked_title_https"
+ android:layout_weight="1"
+ android:gravity="center_vertical" />
+
+ </LinearLayout>
+
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="1dip"
+ android:layout_marginBottom="4dp"
+ android:background="?android:attr/listDivider" />
+
+ </LinearLayout>
+
+</ScrollView> \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/layout/loader_layout.xml b/OpenKeychain/src/main/res/layout/loader_layout.xml
index 61dd48635..6f94384dc 100644
--- a/OpenKeychain/src/main/res/layout/loader_layout.xml
+++ b/OpenKeychain/src/main/res/layout/loader_layout.xml
@@ -4,7 +4,6 @@
android:layout_height="match_parent"
android:orientation="vertical">
- <!--rebuild functionality of ListFragment -->
<LinearLayout
android:id="@+id/loader_progress"
android:orientation="vertical"
@@ -15,15 +14,8 @@
<ProgressBar
style="?android:attr/progressBarStyleLarge"
android:layout_width="wrap_content"
- android:layout_height="wrap_content" />
-
- <TextView
- android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:text=""
- android:paddingTop="4dip"
- android:singleLine="true" />
+ android:gravity="center" />
</LinearLayout>
diff --git a/OpenKeychain/src/main/res/layout/main_activity.xml b/OpenKeychain/src/main/res/layout/main_activity.xml
index 45df0df71..e65969227 100644
--- a/OpenKeychain/src/main/res/layout/main_activity.xml
+++ b/OpenKeychain/src/main/res/layout/main_activity.xml
@@ -13,7 +13,7 @@
android:elevation="4dp"
android:background="?attr/colorPrimary"
android:minHeight="?attr/actionBarSize"
- app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
+ android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
tools:ignore="UnusedAttribute" />
diff --git a/OpenKeychain/src/main/res/layout/nfc_operation_activity.xml b/OpenKeychain/src/main/res/layout/nfc_operation_activity.xml
index 8b043861f..9a9738825 100644
--- a/OpenKeychain/src/main/res/layout/nfc_operation_activity.xml
+++ b/OpenKeychain/src/main/res/layout/nfc_operation_activity.xml
@@ -162,15 +162,13 @@
<Button
android:id="@+id/nfc_activity_3_error_try_again"
- style="?android:attr/borderlessButtonStyle"
android:layout_width="wrap_content"
android:layout_height="48dp"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_below="@+id/nfc_activity_3_placeholder"
android:layout_margin="8dp"
- android:text="@string/error_nfc_try_again"
- android:textColor="@color/accent" />
+ android:text="@string/error_nfc_try_again" />
</RelativeLayout>
diff --git a/OpenKeychain/src/main/res/layout/oauth_webview.xml b/OpenKeychain/src/main/res/layout/oauth_webview.xml
new file mode 100644
index 000000000..f00fdfd17
--- /dev/null
+++ b/OpenKeychain/src/main/res/layout/oauth_webview.xml
@@ -0,0 +1,12 @@
+<?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">
+
+ <WebView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:id="@+id/web_view"/>
+
+</LinearLayout> \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/layout/status_indicator.xml b/OpenKeychain/src/main/res/layout/status_indicator.xml
new file mode 100644
index 000000000..6419e3e34
--- /dev/null
+++ b/OpenKeychain/src/main/res/layout/status_indicator.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <ImageView
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:src="@drawable/ic_chevron_right_grey_24dp"
+ />
+
+ <ProgressBar
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:indeterminate="true"
+ />
+
+ <ImageView
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:src="@drawable/ic_check_white_24dp"
+ android:tint="@color/android_green_light"
+ />
+
+ <ImageView
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:src="@drawable/ic_close_white_24dp"
+ android:tint="@color/android_red_light"
+ />
+
+</merge> \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/layout/toolbar_inner_layout.xml b/OpenKeychain/src/main/res/layout/toolbar_inner_layout.xml
index 047225394..b3228ea06 100644
--- a/OpenKeychain/src/main/res/layout/toolbar_inner_layout.xml
+++ b/OpenKeychain/src/main/res/layout/toolbar_inner_layout.xml
@@ -20,7 +20,7 @@
android:layout_height="wrap_content"
android:minHeight="?attr/actionBarSize"
android:background="@color/transparent"
- app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
+ android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
tools:ignore="UnusedAttribute" />
</merge> \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/layout/toolbar_inner_layout_white.xml b/OpenKeychain/src/main/res/layout/toolbar_inner_layout_white.xml
index a626efb09..477967edd 100644
--- a/OpenKeychain/src/main/res/layout/toolbar_inner_layout_white.xml
+++ b/OpenKeychain/src/main/res/layout/toolbar_inner_layout_white.xml
@@ -20,7 +20,7 @@
android:layout_height="wrap_content"
android:minHeight="?attr/actionBarSize"
android:background="@color/transparent"
- app:theme="@style/ThemeOverlay.AppCompat.ActionBar"
+ android:theme="@style/ThemeOverlay.AppCompat.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
tools:ignore="UnusedAttribute" />
</merge> \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/layout/view_key_activity.xml b/OpenKeychain/src/main/res/layout/view_key_activity.xml
index 8e04f6899..560180407 100644
--- a/OpenKeychain/src/main/res/layout/view_key_activity.xml
+++ b/OpenKeychain/src/main/res/layout/view_key_activity.xml
@@ -1,206 +1,225 @@
<?xml version="1.0" encoding="utf-8"?>
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
- xmlns:tools="http://schemas.android.com/tools"
- xmlns:fab="http://schemas.android.com/apk/res-auto"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:id="@+id/main_content"
android:layout_width="match_parent"
- android:layout_height="match_parent">
+ android:layout_height="match_parent"
+ android:fitsSystemWindows="true">
- <RelativeLayout
- android:id="@+id/toolbar_big"
+ <android.support.design.widget.AppBarLayout
+ android:id="@+id/app_bar_layout"
android:layout_width="match_parent"
- android:layout_height="@dimen/huge_toolbar"
- android:elevation="4dp"
- android:background="?attr/colorPrimary"
- android:orientation="horizontal">
-
- <ImageView
- android:id="@+id/view_key_photo"
- android:visibility="gone"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_below="@+id/status_bar"
- android:layout_alignParentLeft="true"
- android:layout_alignParentStart="true"
- android:src="@drawable/ic_launcher"
- android:baselineAlignBottom="false"
- android:cropToPadding="false"
- android:focusable="false"
- android:adjustViewBounds="false"
- android:layout_alignParentTop="false"
- android:scaleType="centerCrop" />
-
- <ImageView
- android:id="@+id/status_bar"
- android:layout_width="match_parent"
- android:layout_height="@dimen/statusbar_height"
- android:background="?attr/colorPrimary" />
+ android:layout_height="wrap_content"
+ android:background="@color/primary"
+ android:fitsSystemWindows="true"
+ android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
- <android.support.v7.widget.Toolbar
- android:id="@+id/toolbar"
- android:background="@color/transparent"
- android:layout_below="@+id/status_bar"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:minHeight="?attr/actionBarSize"
- android:overScrollMode="always"
- app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
- app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
- tools:ignore="UnusedAttribute"
- android:transitionGroup="false"
- android:touchscreenBlocksFocus="false" />
-
- <TextView
- android:id="@+id/view_key_name"
+ <android.support.design.widget.CollapsingToolbarLayout
+ android:id="@+id/collapsing_toolbar"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginLeft="48dp"
- android:layout_marginStart="48dp"
- android:layout_marginRight="48dp"
- android:layout_marginEnd="48dp"
- android:text=""
- tools:text="Alice Skywalker"
- android:textColor="@color/icons"
- android:textAppearance="?android:attr/textAppearanceLarge"
- android:layout_above="@+id/view_key_status" />
-
- <TextView
- android:id="@+id/view_key_status"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginLeft="48dp"
- android:layout_marginStart="48dp"
- android:layout_marginRight="48dp"
- android:layout_marginEnd="48dp"
- android:text=""
- tools:text="My Key"
- android:textColor="?attr/colorTabText"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:layout_above="@+id/toolbar2" />
-
- <LinearLayout
- android:id="@+id/toolbar2"
- android:orientation="horizontal"
- android:layout_alignParentBottom="true"
- android:layout_width="wrap_content"
- android:minHeight="?attr/actionBarSize"
- android:layout_height="wrap_content"
- android:layout_alignParentLeft="true"
- android:layout_alignParentStart="true"
- android:layout_marginLeft="32dp"
- android:layout_alignParentRight="true"
- android:layout_alignParentEnd="true">
-
- <ImageButton
- android:id="@+id/view_key_action_encrypt_files"
- android:layout_width="64dp"
- android:layout_height="64dp"
- android:visibility="invisible"
- tools:visibility="visible"
- style="?android:attr/borderlessButtonStyle"
- android:src="@drawable/ic_action_encrypt_file_24dp" />
-
- <ImageButton
- android:id="@+id/view_key_action_encrypt_text"
- android:layout_width="64dp"
- android:layout_height="64dp"
- android:visibility="invisible"
- tools:visibility="visible"
- style="?android:attr/borderlessButtonStyle"
- android:src="@drawable/ic_action_encrypt_text_24dp" />
-
- <ImageButton
- android:id="@+id/view_key_action_nfc"
- android:layout_width="64dp"
- android:layout_height="64dp"
- android:visibility="invisible"
- tools:visibility="visible"
- style="?android:attr/borderlessButtonStyle"
- android:src="@drawable/ic_nfc_white_24dp" />
-
- </LinearLayout>
-
- <ImageView
- android:id="@+id/view_key_status_image"
- android:layout_width="96dp"
- android:visibility="invisible"
- tools:visibility="visible"
- android:src="@drawable/status_signature_unverified_cutout_96dp"
- android:layout_height="96dp"
- android:layout_above="@id/toolbar2"
- android:layout_alignParentRight="true"
- android:layout_alignParentEnd="true"
- android:layout_marginRight="16dp" />
-
- <android.support.v7.widget.CardView
- android:id="@+id/view_key_qr_code_layout"
- android:transitionName="qr_code"
- android:visibility="visible"
- android:layout_above="@id/toolbar2"
- android:layout_alignParentRight="true"
- android:layout_alignParentEnd="true"
- android:layout_marginRight="20dp"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:clickable="true"
- android:foreground="?android:attr/selectableItemBackground"
- tools:visibility="invisible"
- card_view:cardBackgroundColor="@android:color/white"
- card_view:cardElevation="2dp"
- card_view:cardUseCompatPadding="true"
- card_view:cardCornerRadius="4dp">
-
- <ImageView
- android:id="@+id/view_key_qr_code"
- android:layout_width="96dp"
- android:layout_height="96dp"
- />
- </android.support.v7.widget.CardView>
-
- </RelativeLayout>
-
- <LinearLayout
- android:id="@+id/body"
- android:layout_below="@id/toolbar_big"
- android:orientation="vertical"
+ android:layout_height="match_parent"
+ android:fitsSystemWindows="true"
+ app:contentScrim="@color/primary"
+ app:expandedTitleMarginBottom="102dp"
+ app:expandedTitleMarginEnd="128dp"
+ app:expandedTitleMarginStart="47dp"
+ app:expandedTitleTextAppearance="@style/TextAppearance.AppCompat.Headline"
+ app:layout_scrollFlags="scroll|exitUntilCollapsed">
+
+ <RelativeLayout
+ android:layout_width="match_parent"
+ android:layout_height="238dp"
+ android:fitsSystemWindows="true"
+ app:layout_collapseMode="parallax">
+
+ <FrameLayout
+ android:id="@+id/view_key_photo_layout"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentStart="true"
+ android:layout_alignParentTop="false"
+ android:fitsSystemWindows="true"
+ android:visibility="gone">
+
+ <ImageView
+ android:id="@+id/view_key_photo"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:adjustViewBounds="false"
+ android:baselineAlignBottom="false"
+ android:cropToPadding="false"
+ android:fitsSystemWindows="true"
+ android:focusable="false"
+ android:scaleType="centerCrop"
+ android:src="@mipmap/ic_launcher" />
+
+ <!-- text protection scrim -->
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_gravity="bottom"
+ android:background="@drawable/scrim_bottom" />
+
+ </FrameLayout>
+
+ <TextView
+ android:id="@+id/view_key_status"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_above="@+id/toolbar2"
+ android:layout_marginEnd="48dp"
+ android:layout_marginLeft="48dp"
+ android:layout_marginRight="48dp"
+ android:layout_marginStart="48dp"
+ android:text=""
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textColor="?attr/colorTabText"
+ tools:text="My Key" />
+
+ <LinearLayout
+ android:id="@+id/toolbar2"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentBottom="true"
+ android:layout_alignParentEnd="true"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentRight="true"
+ android:layout_alignParentStart="true"
+ android:layout_marginLeft="32dp"
+ android:minHeight="?attr/actionBarSize"
+ android:orientation="horizontal">
+
+ <ImageButton
+ android:id="@+id/view_key_action_encrypt_files"
+ style="?android:attr/borderlessButtonStyle"
+ android:layout_width="64dp"
+ android:layout_height="64dp"
+ android:src="@drawable/ic_action_encrypt_file_24dp"
+ android:visibility="invisible"
+ tools:visibility="visible" />
+
+ <ImageButton
+ android:id="@+id/view_key_action_encrypt_text"
+ style="?android:attr/borderlessButtonStyle"
+ android:layout_width="64dp"
+ android:layout_height="64dp"
+ android:src="@drawable/ic_action_encrypt_text_24dp"
+ android:visibility="invisible"
+ tools:visibility="visible" />
+
+ <ImageButton
+ android:id="@+id/view_key_action_nfc"
+ style="?android:attr/borderlessButtonStyle"
+ android:layout_width="64dp"
+ android:layout_height="64dp"
+ android:src="@drawable/ic_nfc_white_24dp"
+ android:visibility="invisible"
+ tools:visibility="visible" />
+
+ </LinearLayout>
+
+ <ImageView
+ android:id="@+id/view_key_status_image"
+ android:layout_width="96dp"
+ android:layout_height="96dp"
+ android:layout_above="@id/toolbar2"
+ android:layout_alignParentEnd="true"
+ android:layout_alignParentRight="true"
+ android:layout_marginRight="16dp"
+ android:src="@drawable/status_signature_unverified_cutout_96dp"
+ android:visibility="invisible"
+ tools:visibility="visible" />
+
+ <android.support.v7.widget.CardView
+ android:id="@+id/view_key_qr_code_layout"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_above="@id/toolbar2"
+ android:layout_alignParentEnd="true"
+ android:layout_alignParentRight="true"
+ android:layout_marginRight="20dp"
+ android:clickable="true"
+ android:foreground="?android:attr/selectableItemBackground"
+ android:transitionName="qr_code"
+ android:visibility="visible"
+ app:layout_collapseMode="parallax"
+ card_view:cardBackgroundColor="@android:color/white"
+ card_view:cardCornerRadius="4dp"
+ card_view:cardElevation="2dp"
+ card_view:cardUseCompatPadding="true"
+ tools:visibility="invisible">
+
+ <ImageView
+ android:id="@+id/view_key_qr_code"
+ android:layout_width="96dp"
+ android:layout_height="96dp" />
+ </android.support.v7.widget.CardView>
+
+ </RelativeLayout>
+
+ <android.support.v7.widget.Toolbar
+ android:id="@+id/toolbar"
+ android:layout_width="match_parent"
+ android:layout_height="?attr/actionBarSize"
+ android:elevation="4dp"
+ android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
+ android:touchscreenBlocksFocus="false"
+ android:transitionGroup="false"
+ app:layout_collapseMode="pin"
+ app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
+ tools:ignore="UnusedAttribute" />
+ </android.support.design.widget.CollapsingToolbarLayout>
+
+ </android.support.design.widget.AppBarLayout>
+
+ <android.support.v4.widget.FlingNestedScrollView
+ android:id="@+id/scroll"
android:layout_width="match_parent"
- android:layout_height="match_parent">
-
- <View
- android:layout_width="match_parent"
- android:layout_height="1dip"
- android:background="?android:attr/listDivider"
- android:visibility="gone"
- android:id="@+id/view_key_status_divider" />
+ android:layout_height="match_parent"
+ android:layout_gravity="fill_vertical"
+ app:layout_behavior="@string/appbar_scrolling_view_behavior">
- <FrameLayout
+ <LinearLayout
android:id="@+id/content_frame"
android:layout_width="match_parent"
- android:layout_height="match_parent">
+ android:layout_height="match_parent"
+ android:orientation="vertical">
<FrameLayout
android:id="@+id/view_key_fragment"
android:layout_width="match_parent"
- android:layout_height="match_parent"
+ android:layout_height="wrap_content" />
+
+ <FrameLayout
+ android:id="@+id/view_key_keybase_fragment"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" />
+
+ <!--
+ placeholder to improve the scrolling.
+ Somehow the content must be large enough to enable scrolling on NestedScrollView
+ -->
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="230dp"
android:orientation="vertical" />
- </FrameLayout>
- </LinearLayout>
+ </LinearLayout>
+
+ </android.support.v4.widget.FlingNestedScrollView>
- <com.getbase.floatingactionbutton.FloatingActionButton
+ <android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
- android:layout_alignBottom="@id/toolbar_big"
- android:layout_alignParentRight="true"
- android:layout_marginRight="20dp"
- android:layout_marginBottom="-40dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:layout_margin="24dp"
+ android:src="@drawable/ic_qrcode_white_24dp"
android:visibility="invisible"
- tools:visibility="visible"
- android:elevation="4dp"
- fab:fab_icon="@drawable/ic_qrcode_white_24dp"
- fab:fab_colorNormal="?attr/colorFab"
- fab:fab_colorPressed="?attr/colorFabPressed" />
+ app:layout_anchor="@id/app_bar_layout"
+ app:layout_anchorGravity="bottom|right|end"
+ tools:visibility="visible" />
-</RelativeLayout>
+</android.support.design.widget.CoordinatorLayout>
diff --git a/OpenKeychain/src/main/res/layout/view_key_adv_keybase_fragment.xml b/OpenKeychain/src/main/res/layout/view_key_adv_keybase_fragment.xml
index eecb19000..75d56e092 100644
--- a/OpenKeychain/src/main/res/layout/view_key_adv_keybase_fragment.xml
+++ b/OpenKeychain/src/main/res/layout/view_key_adv_keybase_fragment.xml
@@ -1,126 +1,95 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical">
-
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:background="?attr/colorButtonRow"
- android:padding="8dp"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:text="@string/key_trust_header_text"
- android:gravity="center_horizontal" />
-
- <View
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:paddingBottom="16dp"
+ android:paddingLeft="16dp"
+ android:paddingRight="16dp"
+ android:paddingTop="16dp">
+
+ <android.support.v7.widget.CardView
+ android:id="@+id/card_view"
android:layout_width="match_parent"
- android:layout_height="1dip"
- android:background="?android:attr/listDivider" />
-
- <ScrollView
- android:layout_width="match_parent"
- android:layout_height="match_parent">
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ card_view:cardBackgroundColor="?attr/colorCardViewBackground"
+ card_view:cardCornerRadius="4dp"
+ card_view:cardElevation="2dp"
+ card_view:cardUseCompatPadding="true">
- <!-- focusable and related properties to workaround http://stackoverflow.com/q/16182331-->
- <LinearLayout
+ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:focusable="true"
- android:focusableInTouchMode="true"
- android:descendantFocusability="beforeDescendants"
- android:orientation="vertical"
- android:paddingLeft="16dp"
- android:paddingRight="16dp">
-
- <TextView
- style="@style/SectionHeader"
- android:layout_width="wrap_content"
- android:layout_height="0dp"
- android:layout_marginTop="8dp"
- android:text="@string/section_should_you_trust"
- android:layout_weight="1" />
+ android:orientation="vertical">
<TextView
- android:id="@+id/view_key_trust_readout"
+ style="@style/CardViewHeader"
android:layout_width="wrap_content"
- android:layout_height="0dp"
- android:layout_marginTop="14dp"
- android:layout_marginLeft="8dp"
- android:layout_weight="1"
- style="?android:attr/textAppearanceMedium" />
+ android:layout_height="wrap_content"
+ android:text="@string/section_keybase_proofs" />
<TextView
- style="@style/SectionHeader"
android:layout_width="wrap_content"
- android:layout_height="0dp"
- android:layout_marginTop="14dp"
- android:text="@string/section_cloud_evidence"
- android:layout_weight="1" />
+ android:layout_height="wrap_content"
+ android:background="?attr/colorButtonRow"
+ android:gravity="center_horizontal"
+ android:padding="8dp"
+ android:text="@string/key_trust_header_text"
+ android:textAppearance="?android:attr/textAppearanceSmall" />
+
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="1dip"
+ android:background="?android:attr/listDivider" />
<LinearLayout
- android:id="@+id/view_key_trust_search_cloud"
android:layout_width="match_parent"
- android:layout_height="?android:attr/listPreferredItemHeight"
- android:clickable="true"
- android:paddingRight="4dp"
- style="?android:attr/borderlessButtonStyle"
- android:orientation="horizontal">
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:paddingBottom="16dp"
+ android:paddingLeft="16dp"
+ android:paddingRight="16dp"
+ android:paddingTop="16dp">
<TextView
- android:paddingLeft="8dp"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:layout_width="0dip"
- android:layout_height="match_parent"
- android:text="@string/key_trust_start_cloud_search"
- android:layout_weight="1"
- android:gravity="center_vertical" />
+ android:id="@+id/view_key_trust_cloud_narrative"
+ style="?android:attr/textAppearanceMedium"
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_marginBottom="14dp"
+ android:layout_marginLeft="8dp"
+ android:layout_weight="1" />
+
+ <TableLayout
+ android:id="@+id/view_key_proof_list"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" />
- <ImageView
+ <TextView
+ android:id="@+id/view_key_proof_verify_header"
+ style="@style/SectionHeader"
android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:padding="8dp"
- android:src="@drawable/ic_action_search_cloud"
- android:layout_gravity="center_vertical" />
-
- </LinearLayout>
-
-
- <TextView
- android:id="@+id/view_key_trust_cloud_narrative"
- android:layout_width="wrap_content"
- android:layout_height="0dp"
- android:layout_marginTop="14dp"
- android:layout_marginBottom="14dp"
- android:layout_marginLeft="8dp"
- android:layout_weight="1"
- style="?android:attr/textAppearanceMedium" />
-
- <TableLayout
- android:id="@+id/view_key_proof_list"
- android:layout_width="match_parent"
- android:layout_height="wrap_content" />
+ android:layout_height="0dp"
+ android:layout_marginTop="16dp"
+ android:layout_weight="1"
+ android:text="@string/section_proof_details" />
- <TextView
- android:id="@+id/view_key_proof_verify_header"
- style="@style/SectionHeader"
- android:layout_width="wrap_content"
- android:layout_height="0dp"
- android:layout_marginTop="16dp"
- android:text="@string/section_proof_details"
- android:layout_weight="1" />
+ <TextView
+ android:id="@+id/view_key_proof_verify_detail"
+ style="?android:attr/textAppearanceMedium"
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_marginLeft="8dp"
+ android:layout_marginTop="14dp"
+ android:layout_weight="1" />
- <TextView
- android:id="@+id/view_key_proof_verify_detail"
- android:layout_width="wrap_content"
- android:layout_height="0dp"
- android:layout_marginTop="14dp"
- android:layout_marginLeft="8dp"
- android:layout_weight="1"
- style="?android:attr/textAppearanceMedium" />
+ </LinearLayout>
</LinearLayout>
- </ScrollView>
-</LinearLayout>
+ </android.support.v7.widget.CardView>
+
+</LinearLayout> \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/layout/view_key_adv_keybase_proof.xml b/OpenKeychain/src/main/res/layout/view_key_adv_keybase_proof.xml
index 0ffd151c1..033282305 100644
--- a/OpenKeychain/src/main/res/layout/view_key_adv_keybase_proof.xml
+++ b/OpenKeychain/src/main/res/layout/view_key_adv_keybase_proof.xml
@@ -7,7 +7,7 @@
android:layout_height="wrap_content"
android:paddingLeft="6dip"
android:text="1."
- style="?android:attr/textAppearanceMedium" />
+ style="?android:attr/textAppearanceSmall" />
<TextView
android:id="@+id/proof_text"
@@ -15,5 +15,5 @@
android:layout_height="wrap_content"
android:paddingLeft="6dip"
android:text="Posts to twitter as Timbray"
- style="?android:attr/textAppearanceMedium" />
+ style="?android:attr/textAppearanceSmall" />
</TableRow>
diff --git a/OpenKeychain/src/main/res/layout/view_key_fragment.xml b/OpenKeychain/src/main/res/layout/view_key_fragment.xml
index 8c1023427..5bf36f564 100644
--- a/OpenKeychain/src/main/res/layout/view_key_fragment.xml
+++ b/OpenKeychain/src/main/res/layout/view_key_fragment.xml
@@ -1,95 +1,148 @@
-<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:card_view="http://schemas.android.com/apk/res-auto"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:card_view="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:orientation="vertical"
+ android:paddingBottom="16dp"
+ android:paddingLeft="16dp"
+ android:paddingRight="16dp"
+ android:paddingTop="16dp">
+
+ <android.support.v7.widget.CardView
+ android:id="@+id/card_linked_ids"
+ android:transitionName="card_linked_ids"
+ android:layout_gravity="center"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:visibility="gone"
+ tools:visibility="visible"
+ card_view:cardBackgroundColor="@android:color/white"
+ card_view:cardElevation="2dp"
+ card_view:cardUseCompatPadding="true"
+ card_view:cardCornerRadius="4dp">
+
+ <LinearLayout
android:layout_width="match_parent"
- android:layout_height="match_parent">
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <TextView
+ style="@style/CardViewHeader"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/section_linked_identities" />
+
+ <org.sufficientlysecure.keychain.ui.widget.FixedListView
+ android:id="@+id/view_key_linked_ids"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="4dp" />
+
+ <TextView
+ android:id="@+id/view_key_linked_ids_expander"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="4dp"
+ android:layout_marginBottom="4dp"
+ android:gravity="center_vertical"
+ android:drawableTop="@drawable/divider"
+ android:drawableRight="@drawable/ic_expand_more_black_24dp"
+ android:drawableEnd="@drawable/ic_expand_more_black_24dp"
+ android:drawablePadding="3dp"
+ android:clickable="true"
+ android:text="@string/linked_ids_more_unknown"
+ android:paddingLeft="8dp"
+ android:paddingRight="8dp"
+ android:background="?android:selectableItemBackground"
+ android:visibility="gone"
+ tools:visibility="visible"
+ />
- <LinearLayout
+ </LinearLayout>
+
+ </android.support.v7.widget.CardView>
+
+ <android.support.v7.widget.CardView
+ android:id="@+id/card_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:orientation="vertical"
- android:paddingTop="16dp"
- android:paddingBottom="16dp"
- android:paddingLeft="16dp"
- android:paddingRight="16dp">
-
- <android.support.v7.widget.CardView
- android:id="@+id/card_view"
- android:layout_gravity="center"
+ android:layout_gravity="center"
+ card_view:cardBackgroundColor="?attr/colorCardViewBackground"
+ card_view:cardCornerRadius="4dp"
+ card_view:cardElevation="2dp"
+ card_view:cardUseCompatPadding="true">
+
+ <LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
- card_view:cardBackgroundColor="?attr/colorCardViewBackground"
- card_view:cardElevation="2dp"
- card_view:cardUseCompatPadding="true"
- card_view:cardCornerRadius="4dp">
+ android:orientation="vertical">
- <LinearLayout
+ <TextView
+ style="@style/CardViewHeader"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/section_user_ids" />
+
+ <org.sufficientlysecure.keychain.ui.widget.FixedListView
+ android:id="@+id/view_key_user_ids"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:orientation="vertical">
+ android:layout_marginBottom="4dp" />
- <TextView
- style="@style/CardViewHeader"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/section_user_ids"/>
+ </LinearLayout>
- <org.sufficientlysecure.keychain.ui.widget.FixedListView
- android:id="@+id/view_key_user_ids"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginBottom="4dp"/>
- </LinearLayout>
- </android.support.v7.widget.CardView>
+ </android.support.v7.widget.CardView>
+
+ <android.support.v7.widget.CardView
+ android:id="@+id/linked_system_contact_card"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:visibility="gone"
+ card_view:cardBackgroundColor="?attr/colorCardViewBackground"
+ card_view:cardCornerRadius="4dp"
+ card_view:cardElevation="2dp"
+ card_view:cardUseCompatPadding="true">
- <android.support.v7.widget.CardView
- android:id="@+id/linked_system_contact_card"
- android:layout_gravity="center"
+ <LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:visibility="gone"
- card_view:cardBackgroundColor="?attr/colorCardViewBackground"
- card_view:cardElevation="2dp"
- card_view:cardUseCompatPadding="true"
- card_view:cardCornerRadius="4dp">
+ android:orientation="vertical">
+
+ <TextView
+ style="@style/CardViewHeader"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/section_linked_system_contact" />
<LinearLayout
+ android:id='@+id/system_contact_layout'
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:orientation="vertical">
+ android:background="?android:selectableItemBackground"
+ android:clickable="true"
+ android:orientation="horizontal">
+
+ <ImageView
+ android:id="@+id/system_contact_picture"
+ android:layout_width="48dp"
+ android:layout_height="48dp"
+ android:layout_margin="6dp"
+ android:scaleType="centerCrop"
+ android:src="@drawable/ic_person_grey_48dp" />
<TextView
- style="@style/CardViewHeader"
+ android:id="@+id/system_contact_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:text="@string/section_linked_system_contact"/>
-
- <LinearLayout
- android:id='@+id/system_contact_layout'
- android:clickable="true"
- android:background="?android:selectableItemBackground"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal">
-
- <ImageView
- android:id="@+id/system_contact_picture"
- android:layout_margin="6dp"
- android:layout_width="48dp"
- android:layout_height="48dp"
- android:scaleType="centerCrop"
- android:src="@drawable/ic_person_grey_48dp"/>
-
- <TextView
- android:id="@+id/system_contact_name"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center_vertical"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:text="@string/view_key_fragment_no_system_contact"/>
- </LinearLayout>
+ android:layout_gravity="center_vertical"
+ android:text="@string/view_key_fragment_no_system_contact"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
</LinearLayout>
- </android.support.v7.widget.CardView>
- </LinearLayout>
+ </LinearLayout>
+
+ </android.support.v7.widget.CardView>
-</ScrollView>
+</LinearLayout>
diff --git a/OpenKeychain/src/main/res/menu/decrypt_item_context_menu.xml b/OpenKeychain/src/main/res/menu/decrypt_item_context_menu.xml
index 97bf65c0d..ab526c4a5 100644
--- a/OpenKeychain/src/main/res/menu/decrypt_item_context_menu.xml
+++ b/OpenKeychain/src/main/res/menu/decrypt_item_context_menu.xml
@@ -8,6 +8,12 @@
/>
<item
+ android:id="@+id/decrypt_share"
+ android:title="@string/btn_share_decrypted_text"
+ android:icon="@drawable/ic_share_grey_24dp"
+ />
+
+ <item
android:id="@+id/decrypt_save"
android:title="@string/btn_save_file"
android:icon="@drawable/ic_action_encrypt_file_24dp"
diff --git a/OpenKeychain/src/main/res/menu/decrypt_menu.xml b/OpenKeychain/src/main/res/menu/decrypt_menu.xml
index 9e90fc9c7..0b81ea1db 100644
--- a/OpenKeychain/src/main/res/menu/decrypt_menu.xml
+++ b/OpenKeychain/src/main/res/menu/decrypt_menu.xml
@@ -14,4 +14,4 @@
android:icon="@drawable/ic_share_black_24dp"
app:showAsAction="ifRoom" />
-</menu> \ No newline at end of file
+</menu>
diff --git a/OpenKeychain/src/main/res/menu/key_view.xml b/OpenKeychain/src/main/res/menu/key_view.xml
index 4a9fe16c7..14ea099f4 100644
--- a/OpenKeychain/src/main/res/menu/key_view.xml
+++ b/OpenKeychain/src/main/res/menu/key_view.xml
@@ -37,4 +37,15 @@
android:visible="false"
android:title="@string/menu_certify_fingerprint" />
-</menu> \ No newline at end of file
+ <item
+ android:id="@+id/menu_key_view_certify_fingerprint_word"
+ app:showAsAction="never"
+ android:visible="false"
+ android:title="@string/menu_certify_fingerprint_word" />
+
+ <item
+ android:id="@+id/menu_key_view_add_linked_identity"
+ app:showAsAction="never"
+ android:title="@string/menu_linked_add_identity" />
+
+</menu>
diff --git a/OpenKeychain/src/main/res/menu/log_display.xml b/OpenKeychain/src/main/res/menu/log_display.xml
index 7a2f77b79..a7f7e286d 100644
--- a/OpenKeychain/src/main/res/menu/log_display.xml
+++ b/OpenKeychain/src/main/res/menu/log_display.xml
@@ -4,8 +4,8 @@
<item
android:id="@+id/menu_log_display_export_log"
- android:icon="@drawable/ic_save_white_24dp"
- android:title="@string/menu_export_log"
+ android:icon="@drawable/ic_share_black_24dp"
+ android:title="@string/menu_share_log"
app:showAsAction="ifRoom|withText" />
</menu>
diff --git a/OpenKeychain/src/main/res/drawable-hdpi/ic_launcher.png b/OpenKeychain/src/main/res/mipmap-hdpi/ic_launcher.png
index 6133816d2..6133816d2 100644
--- a/OpenKeychain/src/main/res/drawable-hdpi/ic_launcher.png
+++ b/OpenKeychain/src/main/res/mipmap-hdpi/ic_launcher.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-mdpi/ic_launcher.png b/OpenKeychain/src/main/res/mipmap-mdpi/ic_launcher.png
index d945a01de..d945a01de 100644
--- a/OpenKeychain/src/main/res/drawable-mdpi/ic_launcher.png
+++ b/OpenKeychain/src/main/res/mipmap-mdpi/ic_launcher.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/ic_launcher.png b/OpenKeychain/src/main/res/mipmap-xhdpi/ic_launcher.png
index 825b18b38..825b18b38 100644
--- a/OpenKeychain/src/main/res/drawable-xhdpi/ic_launcher.png
+++ b/OpenKeychain/src/main/res/mipmap-xhdpi/ic_launcher.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/ic_launcher.png b/OpenKeychain/src/main/res/mipmap-xxhdpi/ic_launcher.png
index 4809acc39..4809acc39 100644
--- a/OpenKeychain/src/main/res/drawable-xxhdpi/ic_launcher.png
+++ b/OpenKeychain/src/main/res/mipmap-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_launcher.png b/OpenKeychain/src/main/res/mipmap-xxxhdpi/ic_launcher.png
index fab324e93..fab324e93 100644
--- a/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_launcher.png
+++ b/OpenKeychain/src/main/res/mipmap-xxxhdpi/ic_launcher.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/raw-bg/help_about.md b/OpenKeychain/src/main/res/raw-bg/help_about.md
deleted file mode 100644
index e80a2c766..000000000
--- a/OpenKeychain/src/main/res/raw-bg/help_about.md
+++ /dev/null
@@ -1,65 +0,0 @@
-[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
-
-[http://www.openkeychain.org](http://www.openkeychain.org)
-
-[OpenKeychain](http://www.openkeychain.org) is an OpenPGP implementation for Android.
-
-License: GPLv3+
-
-## Main Developers
- * Dominik Schürmann (Maintainer)
- * Vincent Breitmoser
-
-## Contributors
- * Adithya Abraham Philip
- * Art O Cathain
- * Ash Hughes
- * Brian C. Barnes
- * Bahtiar 'kalkin' Gadimov
- * Daniel Albert
- * Daniel Hammann
- * Daniel Haß
- * Daniel Nelz
- * Daniel Ramos
- * Greg Witczak
- * 'iseki'
- * Ishan Khanna
- * 'jellysheep'
- * 'Jesperbk'
- * 'jkolo'
- * Joey Castillo
- * Kai Jiang
- * Kartik Arora
- * 'Kent'
- * 'ligi'
- * Lukas Zorich
- * Manoj Khanna
- * 'mar-v-in'
- * Markus Doits
- * Miroojin Bakshi
- * Morgan Gangwere
- * Nikhil Peter Raj
- * Paul Sarbinowski
- * 'Senecaso'
- * Signe Rüsch
- * Sreeram Boyapati
- * 'steelman'
- * 'Thialfihar' (APG developer)
- * Tim Bray
-
-## Libraries
- * [SpongyCastle](http://rtyley.github.com/spongycastle/) (MIT X11 License)
- * [SafeSlinger Exchange library](https://github.com/SafeSlingerProject/exchange-android) (MIT License)
- * [Android Support Libraries](http://developer.android.com/tools/support-library/index.html) (Apache License v2)
- * [KeybaseLib](https://github.com/timbray/KeybaseLib) (Apache License v2)
- * [TokenAutoComplete](https://github.com/splitwise/TokenAutoComplete) (Apache License v2)
- * [MiniDNS](https://github.com/rtreffer/minidns) (Apache License v2)
- * [StickyListHeaders](https://github.com/emilsjolander/StickyListHeaders) (Apache License v2)
- * [ZXing](https://github.com/zxing/zxing) (Apache License v2)
- * [ZXing Android Minimal](https://github.com/journeyapps/zxing-android-embedded) (Apache License v2)
- * [PagerSlidingTabStrip](https://github.com/jpardogo/PagerSlidingTabStrip) (Material Design) (Apache License v2)
- * [MaterialDrawer](https://github.com/mikepenz/MaterialDrawer) (Apache License v2)
- * [Snackbar](https://github.com/nispok/snackbar) (MIT License)
- * [FloatingActionButton](https://github.com/futuresimple/android-floating-action-button) (Apache License v2)
- * [HtmlTextView](https://github.com/sufficientlysecure/html-textview) (Apache License v2)
- * [Markdown4J](https://github.com/jdcasey/markdown4j) (Apache License v2) \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-bg/help_certification.md b/OpenKeychain/src/main/res/raw-bg/help_certification.md
deleted file mode 100644
index 3518adf73..000000000
--- a/OpenKeychain/src/main/res/raw-bg/help_certification.md
+++ /dev/null
@@ -1,28 +0,0 @@
-[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
-
-## Key Confirmation
-Without confirmation, you cannot be sure if a key really corresponds to a specific person.
-The simplest way to confirm a key is by scanning the QR Code or exchanging it via NFC.
-To confirm keys between more than two persons, we suggest to use the key exchange method available for your keys.
-
-## Key Status
-
-<img src="status_signature_verified_cutout_24dp"/>
-Confirmed: You have already confirmed this key, e.g., by scanning the QR Code.
-<img src="status_signature_unverified_cutout_24dp"/>
-Unconfirmed: This key has not been confirmed yet. You cannot be sure if the key really corresponds to a specific person.
-<img src="status_signature_expired_cutout_24dp"/>
-Expired: This key is no longer valid. Only the owner can extend its validity.
-<img src="status_signature_revoked_cutout_24dp"/>
-Revoked: This key is no longer valid. It has been revoked by its owner.
-
-## Advanced Information
-A "key confirmation" in OpenKeychain is implemented by creating a certification according to the OpenPGP standard.
-This certification is a ["generic certification (0x10)"](http://tools.ietf.org/html/rfc4880#section-5.2.1) described in the standard by:
-"The issuer of this certification does not make any particular assertion as to how well the certifier has checked that the owner of the key is in fact the person described by the User ID."
-
-Traditionally, certifications (also with higher certification levels, such as "positive certifications" (0x13)) are organized in OpenPGP's Web of Trust.
-Our model of key confirmation is a much simpler concept to avoid common usability problems related to this Web of Trust.
-We assume that keys are verified only to a certain degree that is still usable enough to be executed "on the go".
-We also do not implement (potentially transitive) trust signatures or an ownertrust database like in GnuPG.
-Furthermore, keys which contain at least one user ID certified by a trusted key will be marked as "confirmed" in the key listings. \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-bg/help_changelog.md b/OpenKeychain/src/main/res/raw-bg/help_changelog.md
deleted file mode 100644
index 45ac104e0..000000000
--- a/OpenKeychain/src/main/res/raw-bg/help_changelog.md
+++ /dev/null
@@ -1,283 +0,0 @@
-[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
-
-## 3.4
-
- * Anonymous key download over Tor
- * Proxy support
- * Better YubiKey error handling
-
-## 3.3
-
- * New decryption screen
- * Decryption of multiple files at once
- * Better handling of YubiKey errors
-
-## 3.2
-
- * First version with full YubiKey support available from the user interface: Edit keys, bind YubiKey to keys,...
- * Material design
- * Integration of QR Code Scanning (New permissions required)
- * Improved key creation wizard
- * Fix missing contacts after sync
- * Requires Android 4
- * Redesigned key screen
- * Simplify crypto preferences, better selection of secure ciphers
- * API: Detached signatures, free selection of signing key,...
- * Fix: Some valid keys were shown revoked or expired
- * Don't accept signatures by expired or revoked subkeys
- * Keybase.io support in advanced view
- * Method to update all keys at once
-
-
-## 3.1.2
-
- * Fix key export to files (now for real)
-
-
-## 3.1.1
-
- * Fix key export to files (they were written partially)
- * Fix crash on Android 2.3
-
-
-## 3.1
-
- * Fix crash on Android 5
- * New certify screen
- * Secure Exchange directly from key list (SafeSlinger library)
- * New QR Code program flow
- * Redesigned decrypt screen
- * New icon usage and colors
- * Fix import of secret keys from Symantec Encryption Desktop
- * Experimental YubiKey support: Subkey IDs are now checked correctly
-
-
-## 3.0.1
-
- * Better handling of large key imports
- * Improved subkey selection
-
-
-## 3.0
-
- * Propose installable compatible apps in apps list
- * New design for decryption screens
- * Many fixes for key import, also fixes stripped keys
- * Honor and display key authenticate flags
- * User interface to generate custom keys
- * Fixing user id revocation certificates
- * New cloud search (searches over traditional keyservers and keybase.io)
- * Support for stripping keys inside OpenKeychain
- * Experimental YubiKey support: Support for signature generation and decryption
-
-
-## 2.9.2
-
- * Fix keys broken in 2.9.1
- * Experimental YubiKey support: Decryption now working via API
-
-
-## 2.9.1
-
- * Split encrypt screen into two
- * Fix key flags handling (now supporting Mailvelope 0.7 keys)
- * Improved passphrase handling
- * Key sharing via SafeSlinger
- * Experimental YubiKey support: Preference to allow other PINs, currently only signing via the OpenPGP API works, not inside of OpenKeychain
- * Fix usage of stripped keys
- * SHA256 as default for compatibility
- * Intent API has changed, see https://github.com/open-keychain/open-keychain/wiki/Intent-API
- * OpenPGP API now handles revoked/expired keys and returns all user ids
-
-
-## 2.9
-
- * Fixing crashes introduced in v2.8
- * Experimental ECC support
- * Experimental YubiKey support: Only signing with imported keys
-
-
-## 2.8
-
- * So many bugs have been fixed in this release that we focus on the main new features
- * Key edit: awesome new design, key revocation
- * Key import: awesome new design, secure keyserver connections via hkps, keyserver resolving via DNS SRV records
- * New first time screen
- * New key creation screen: autocompletion of name and email based on your personal Android accounts
- * File encryption: awesome new design, support for encrypting multiple files
- * New icons to show status of key (by Brennan Novak)
- * Important bug fix: Importing of large key collections from a file is now possible
- * Notification showing cached passphrases
- * Keys are connected to Android's contacts
-
-This release wouldn't be possible without the work of Vincent Breitmoser (GSoC 2014), mar-v-in (GSoC 2014), Daniel Albert, Art O Cathain, Daniel Haß, Tim Bray, Thialfihar
-
-## 2.7
-
- * Purple! (Dominik, Vincent)
- * New key view design (Dominik, Vincent)
- * New flat Android buttons (Dominik, Vincent)
- * API fixes (Dominik)
- * Keybase.io import (Tim Bray)
-
-
-## 2.6.1
-
- * Some fixes for regression bugs
-
-
-## 2.6
-
- * Key certifications (thanks to Vincent Breitmoser)
- * Support for GnuPG partial secret keys (thanks to Vincent Breitmoser)
- * New design for signature verification
- * Custom key length (thanks to Greg Witczak)
- * Fix share-functionality from other apps
-
-
-## 2.5
-
- * Fix decryption of symmetric OpenPGP messages/files
- * Refactored key edit screen (thanks to Ash Hughes)
- * New modern design for encrypt/decrypt screens
- * OpenPGP API version 3 (multiple api accounts, internal fixes, key lookup)
-
-
-## 2.4
-Thanks to all applicants of Google Summer of Code 2014 who made this release feature rich and bug free!
-Besides several small patches, a notable number of patches are made by the following people (in alphabetical order):
-Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Paul Sarbinowski, Sreeram Boyapati, Vincent Breitmoser.
-
- * New unified key list
- * Colorized key fingerprint
- * Support for keyserver ports
- * Deactivate possibility to generate weak keys
- * Much more internal work on the API
- * Certify user ids
- * Keyserver query based on machine-readable output
- * Lock navigation drawer on tablets
- * Suggestions for emails on creation of keys
- * Search in public key lists
- * And much more improvements and fixes…
-
-
-## 2.3.1
-
- * Hotfix for crash when upgrading from old versions
-
-
-## 2.3
-
- * Remove unnecessary export of public keys when exporting secret key (thanks to Ash Hughes)
- * Fix setting expiry dates on keys (thanks to Ash Hughes)
- * More internal fixes when editing keys (thanks to Ash Hughes)
- * Querying keyservers directly from the import screen
- * Fix layout and dialog style on Android 2.2-3.0
- * Fix crash on keys with empty user ids
- * Fix crash and empty lists when coming back from signing screen
- * Bouncy Castle (cryptography library) updated from 1.47 to 1.50 and build from source
- * Fix upload of key from signing screen
-
-
-## 2.2
-
- * New design with navigation drawer
- * New public key list design
- * New public key view
- * Bug fixes for importing of keys
- * Key cross-certification (thanks to Ash Hughes)
- * Handle UTF-8 passwords properly (thanks to Ash Hughes)
- * First version with new languages (thanks to the contributors on Transifex)
- * Sharing of keys via QR Codes fixed and improved
- * Package signature verification for API
-
-
-## 2.1.1
-
- * API Updates, preparation for K-9 Mail integration
-
-
-## 2.1
-
- * Lots of bug fixes
- * New API for developers
- * PRNG bug fix by Google
-
-
-## 2.0
-
- * Complete redesign
- * Share public keys via QR codes, NFC beam
- * Sign keys
- * Upload keys to server
- * Fixes import issues
- * New AIDL API
-
-
-## 1.0.8
-
- * Basic keyserver support
- * App2sd
- * More choices for passphrase cache: 1, 2, 4, 8, hours
- * Translations: Norwegian (thanks, Sander Danielsen), Chinese (thanks, Zhang Fredrick)
- * Bugfixes
- * Optimizations
-
-
-## 1.0.7
-
- * Fixed problem with signature verification of texts with trailing newline
- * More options for passphrase cache time to live (20, 40, 60 mins)
-
-
-## 1.0.6
-
- * Account adding crash on Froyo fixed
- * Secure file deletion
- * Option to delete key file after import
- * Stream encryption/decryption (gallery, etc.)
- * New options (language, force v3 signatures)
- * Interface changes
- * Bugfixes
-
-
-## 1.0.5
-
- * German and Italian translation
- * Much smaller package, due to reduced BC sources
- * New preferences GUI
- * Layout adjustment for localization
- * Signature bugfix
-
-
-## 1.0.4
-
- * Fixed another crash caused by some SDK bug with query builder
-
-
-## 1.0.3
-
- * Fixed crashes during encryption/signing and possibly key export
-
-
-## 1.0.2
-
- * Filterable key lists
- * Smarter pre-selection of encryption keys
- * New Intent handling for VIEW and SEND, allows files to be encrypted/decrypted out of file managers
- * Fixes and additional features (key preselection) for K-9 Mail, new beta build available
-
-
-## 1.0.1
-
- * GMail account listing was broken in 1.0.0, fixed again
-
-
-## 1.0.0
-
- * K-9 Mail integration, APG supporting beta build of K-9 Mail
- * Support of more file managers (including ASTRO)
- * Slovenian translation
- * New database, much faster, less memory usage
- * Defined Intents and content provider for other apps
- * Bugfixes \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-bg/help_start.md b/OpenKeychain/src/main/res/raw-bg/help_start.md
deleted file mode 100644
index 4cc331942..000000000
--- a/OpenKeychain/src/main/res/raw-bg/help_start.md
+++ /dev/null
@@ -1,16 +0,0 @@
-[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
-
-## How do I activate OpenKeychain in K-9 Mail?
-To use OpenKeychain with K-9 Mail, you want to follow these steps:
- 1. Open K-9 Mail and long-tap on the account you want to use OpenKeychain with.
- 2. Select "Account settings", scroll to the very bottom and click "Cryptography".
- 3. Click on "OpenPGP Provider" and select OpenKeychain from the list.
-
-## I found a bug in OpenKeychain!
-Please report the bug using the [issue tracker of OpenKeychain](https://github.com/openpgp-keychain/openpgp-keychain/issues).
-
-## Contribute
-If you want to help us developing OpenKeychain by contributing code [follow our small guide on Github](https://github.com/openpgp-keychain/openpgp-keychain#contribute-code).
-
-## Translations
-Help translating OpenKeychain! Everybody can participate at [OpenKeychain on Transifex](https://www.transifex.com/projects/p/open-keychain/). \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-cs/help_about.md b/OpenKeychain/src/main/res/raw-cs/help_about.md
index e80a2c766..06bed0021 100644
--- a/OpenKeychain/src/main/res/raw-cs/help_about.md
+++ b/OpenKeychain/src/main/res/raw-cs/help_about.md
@@ -6,14 +6,21 @@
License: GPLv3+
+[//]: # (NOTE: Alphabetic ordering)
+
## Main Developers
* Dominik Schürmann (Maintainer)
* Vincent Breitmoser
-## Contributors
+## Top Contributors
* Adithya Abraham Philip
- * Art O Cathain
* Ash Hughes
+ * 'mar-v-in'
+ * 'Thialfihar' (APG developer)
+ * Tim Bray
+
+## Occasional Contributors
+ * Art O Cathain
* Brian C. Barnes
* Bahtiar 'kalkin' Gadimov
* Daniel Albert
@@ -34,7 +41,6 @@ License: GPLv3+
* 'ligi'
* Lukas Zorich
* Manoj Khanna
- * 'mar-v-in'
* Markus Doits
* Miroojin Bakshi
* Morgan Gangwere
@@ -44,22 +50,23 @@ License: GPLv3+
* Signe Rüsch
* Sreeram Boyapati
* 'steelman'
- * 'Thialfihar' (APG developer)
- * Tim Bray
+
+[//]: # (NOTE: Alphabetic ordering)
## Libraries
- * [SpongyCastle](http://rtyley.github.com/spongycastle/) (MIT X11 License)
- * [SafeSlinger Exchange library](https://github.com/SafeSlingerProject/exchange-android) (MIT License)
* [Android Support Libraries](http://developer.android.com/tools/support-library/index.html) (Apache License v2)
+ * [FloatingActionButton](https://github.com/futuresimple/android-floating-action-button) (Apache License v2)
+ * [HtmlTextView](https://github.com/sufficientlysecure/html-textview) (Apache License v2)
* [KeybaseLib](https://github.com/timbray/KeybaseLib) (Apache License v2)
- * [TokenAutoComplete](https://github.com/splitwise/TokenAutoComplete) (Apache License v2)
+ * [Markdown4J](https://github.com/jdcasey/markdown4j) (Apache License v2)
+ * [MaterialDrawer](https://github.com/mikepenz/MaterialDrawer) (Apache License v2)
* [MiniDNS](https://github.com/rtreffer/minidns) (Apache License v2)
- * [StickyListHeaders](https://github.com/emilsjolander/StickyListHeaders) (Apache License v2)
- * [ZXing](https://github.com/zxing/zxing) (Apache License v2)
- * [ZXing Android Minimal](https://github.com/journeyapps/zxing-android-embedded) (Apache License v2)
+ * [OkHttp](http://square.github.io/okhttp/) (Apache License v2)
* [PagerSlidingTabStrip](https://github.com/jpardogo/PagerSlidingTabStrip) (Material Design) (Apache License v2)
- * [MaterialDrawer](https://github.com/mikepenz/MaterialDrawer) (Apache License v2)
+ * [SafeSlinger Exchange library](https://github.com/SafeSlingerProject/exchange-android) (MIT License)
* [Snackbar](https://github.com/nispok/snackbar) (MIT License)
- * [FloatingActionButton](https://github.com/futuresimple/android-floating-action-button) (Apache License v2)
- * [HtmlTextView](https://github.com/sufficientlysecure/html-textview) (Apache License v2)
- * [Markdown4J](https://github.com/jdcasey/markdown4j) (Apache License v2) \ No newline at end of file
+ * [SpongyCastle](http://rtyley.github.com/spongycastle/) (MIT X11 License)
+ * [StickyListHeaders](https://github.com/emilsjolander/StickyListHeaders) (Apache License v2)
+ * [TokenAutoComplete](https://github.com/splitwise/TokenAutoComplete) (Apache License v2)
+ * [ZXing](https://github.com/zxing/zxing) (Apache License v2)
+ * [ZXing Android Minimal](https://github.com/journeyapps/zxing-android-embedded) (Apache License v2) \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-cs/help_changelog.md b/OpenKeychain/src/main/res/raw-cs/help_changelog.md
index 45ac104e0..11d7975b1 100644
--- a/OpenKeychain/src/main/res/raw-cs/help_changelog.md
+++ b/OpenKeychain/src/main/res/raw-cs/help_changelog.md
@@ -1,5 +1,12 @@
[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
+## 3.5
+
+ * Key revocation on key deletion
+ * Improved checks for insecure cryptography
+ * Fix: Don't close OpenKeychain after first time wizard succeeds
+ * API: Version 8
+
## 3.4
* Anonymous key download over Tor
diff --git a/OpenKeychain/src/main/res/raw-de/help_about.md b/OpenKeychain/src/main/res/raw-de/help_about.md
index 3932fa748..c19b9d8a6 100644
--- a/OpenKeychain/src/main/res/raw-de/help_about.md
+++ b/OpenKeychain/src/main/res/raw-de/help_about.md
@@ -6,14 +6,21 @@
Lizenz: GPLv3+
+[//]: # (Beachte: alphabethisch Sortiert)
+
## Hauptentwickler
* Dominik Schürmann (Leitender Entwickler)
* Vincent Breitmoser
-## Beitragende
+## Haupt-Mitwirkende
* Adithya Abraham Philip
- * Art O Cathain
* Ash Hughes
+ * 'mar-v-in'
+ * 'Thialfihar' (APG-Entwickler)
+ * Tim Bray
+
+## gelegentlich Mitwirkende
+ * Art O Cathain
* Brian C. Barnes
* Bahtiar 'kalkin' Gadimov
* Daniel Albert
@@ -34,7 +41,6 @@ Lizenz: GPLv3+
* 'ligi'
* Lukas Zorich
* Manoj Khanna
- * 'mar-v-in'
* Markus Doits
* Miroojin Bakshi
* Morgan Gangwere
@@ -44,22 +50,23 @@ Lizenz: GPLv3+
* Signe Rüsch
* Sreeram Boyapati
* 'steelman'
- * 'Thialfihar' (APG-Entwickler)
- * Tim Bray
+
+[//]: # (Beachte: alphabethisch Sortiert)
## Bibliotheken
- * [SpongyCastle](http://rtyley.github.com/spongycastle/) (MIT X11-Lizenz)
- * [SafeSlinger Exchange library](https://github.com/SafeSlingerProject/exchange-android) (MIT-Lizenz)
* [Android Support Libraries](http://developer.android.com/tools/support-library/index.html) (Apache-Lizenz v2)
+ * [FloatingActionButton](https://github.com/futuresimple/android-floating-action-button) (Apache-Lizenz v2)
+ * [HtmlTextView](https://github.com/sufficientlysecure/html-textview) (Apache-Lizenz v2)
* [KeybaseLib](https://github.com/timbray/KeybaseLib) (Apache-Lizenz v2)
- * [TokenAutoComplete](https://github.com/splitwise/TokenAutoComplete) (Apache-Lizenz v2)
+ * [Markdown4J](https://github.com/jdcasey/markdown4j) (Apache-Lizenz v2)
+ * [MaterialDrawer](https://github.com/mikepenz/MaterialDrawer) (Apache-Lizenz v2)
* [MiniDNS](https://github.com/rtreffer/minidns) (Apache-Lizenz v2)
+ * [OkHttp](http://square.github.io/okhttp/) (Apache-Lizenz v2)
+ * [PagerSlidingTabStrip](https://github.com/jpardogo/PagerSlidingTabStrip) (Material Design) (Apache-Lizenz v2)
+ * [SafeSlinger Exchange library](https://github.com/SafeSlingerProject/exchange-android) (MIT-Lizenz)
+ * [Snackbar](https://github.com/nispok/snackbar) (MIT-Lizenz)
+ * [SpongyCastle](http://rtyley.github.com/spongycastle/) (MIT X11-Lizenz)
* [StickyListHeaders](https://github.com/emilsjolander/StickyListHeaders) (Apache-Lizenz v2)
+ * [TokenAutoComplete](https://github.com/splitwise/TokenAutoComplete) (Apache-Lizenz v2)
* [ZXing](https://github.com/zxing/zxing) (Apache-Lizenz v2)
- * [ZXing Android Minimal](https://github.com/journeyapps/zxing-android-embedded) (Apache-Lizenz v2)
- * [PagerSlidingTabStrip](https://github.com/jpardogo/PagerSlidingTabStrip) (Material Design) (Apache License v2)
- * [MaterialDrawer](https://github.com/mikepenz/MaterialDrawer) (Apache-Lizenz v2)
- * [Snackbar](https://github.com/nispok/snackbar) (MIT-Lizenz)
- * [FloatingActionButton](https://github.com/futuresimple/android-floating-action-button) (Apache-Lizenz v2)
- * [HtmlTextView](https://github.com/sufficientlysecure/html-textview) (Apache-Lizenz v2)
- * [Markdown4J](https://github.com/jdcasey/markdown4j) (Apache-Lizenz v2) \ No newline at end of file
+ * [ZXing Android Minimal](https://github.com/journeyapps/zxing-android-embedded) (Apache-Lizenz v2) \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-de/help_changelog.md b/OpenKeychain/src/main/res/raw-de/help_changelog.md
index 80551b8d7..91f2ffedc 100644
--- a/OpenKeychain/src/main/res/raw-de/help_changelog.md
+++ b/OpenKeychain/src/main/res/raw-de/help_changelog.md
@@ -1,10 +1,17 @@
-[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
+[//]: # (NOTITZ: Bitte setze jeden Satz in eine eigene Zeile, Transifex setzt jede Zeile in ein eigenes Übersetzungsfeld!)
+
+## 3.5
+
+ * Schlüsselwiderruf bei Schlüssellöschung
+ * Verbesserte Kontrollen für unsichere Verschlüsselung
+ * Behoben: OpenKeychain nach Abschluss des Anfängerassistenten nicht schließen
+ * API: Version 8
## 3.4
- * Anonymous key download over Tor
- * Proxy support
- * Better YubiKey error handling
+ * Anonymer Schlüsseldownload über Tor
+ * Proxyunterstützung
+ * Bessere YubiKey Fehlerbehandlung
## 3.3
@@ -83,7 +90,7 @@
* Behoben: Fehler bei Handhabung von Schlüsselattributen (unterstützt nun Schlüssel aus Mailvelope 0.7)
* Handhabung von Passwörtern verbessert
* Schlüsselaustausch mit SafeSlinger
- * Experimental YubiKey support: Preference to allow other PINs, currently only signing via the OpenPGP API works, not inside of OpenKeychain
+ * Experimentelle YubiKey-Unterstützung: Einstellung zum Erlauben anderer PINs, derzeit funktioniert nur die Beglaubigung über die OpenPGP API, nicht innerhalb von OpenKeychain
* Nutzung gekürzter Schlüssel repariert
* Standardmäßig SHA256 aufgrund von Kompatibilität
* Intent-API hat sich geändert, siehe https://github.com/open-keychain/open-keychain/wiki/Intent-API
@@ -123,7 +130,7 @@ Dieser Release wäre ohne die Arbeit von Vincent Breitmoser (GSoC 2014), mar-v-i
## 2.6.1
- * Some fixes for regression bugs
+ * Einige Korrekturen für Regressionsfehler
## 2.6
@@ -150,67 +157,67 @@ Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Pa
* Neue einheitliche Schlüsselliste
* Eingefärbter Schlüsselfingerabdruck
- * Support for keyserver ports
- * Deactivate possibility to generate weak keys
- * Much more internal work on the API
- * Certify user ids
- * Keyserver query based on machine-readable output
- * Lock navigation drawer on tablets
- * Suggestions for emails on creation of keys
+ * Unterstützt Schlüsselserver ports
+ * Deaktiviere Möglichkeit unsichere Schlüssel zu erstellen
+ * Viel mehr interne Arbeit an der API
+ * Benutzerkennungen beglaubigen
+ * Schlüsselserver-Suchanfrage basierend auf maschinenlesbarer Ausgabe
+ * "Navigation Drawer" auf Tablets sperren
+ * Vorschläge für E-Mails bei Schlüsselerzeugung
* Suchen in öffentlichen Schlüssellisten
- * And much more improvements and fixes…
+ * Und viele weitere Verbesserungen und Fehlerbehebungen...
## 2.3.1
- * Hotfix for crash when upgrading from old versions
+ * Hotfix für Absturz beim Aktualisieren von alten Versionen
## 2.3
- * Remove unnecessary export of public keys when exporting secret key (thanks to Ash Hughes)
- * Fix setting expiry dates on keys (thanks to Ash Hughes)
- * More internal fixes when editing keys (thanks to Ash Hughes)
- * Querying keyservers directly from the import screen
- * Fix layout and dialog style on Android 2.2-3.0
- * Fix crash on keys with empty user ids
- * Fix crash and empty lists when coming back from signing screen
- * Bouncy Castle (cryptography library) updated from 1.47 to 1.50 and build from source
- * Fix upload of key from signing screen
+ * Kein unnötiger Export öffentlicher Schlüssel beim Export der geheimen Schlüssel (Dank an Ash Hughes)
+ * Behoben: Setzen des Schlüsselablaufdatums (Dank an Ash Hughes)
+ * Weitere interne Fehlerbehebungen für das Editieren von Schlüsseln (Dank an Ash Hughes)
+ * Schlüsselserverabfrage direkt aus dem Importierungsbildschirm
+ * Behoben: Layout und Dialogstil auf Android 2.2-3.0
+ * Behoben: Absturz bei leeren Benutzer-IDs
+ * Absturz und leere Listen nach der Rückkehr vom Signierbildschirm behoben
+ * Bouncy Castle (Kryptographie-Bibliothek) von 1.47 auf 1.50 aktualisiert und aus Quellcode kompiliert
+ * Hochladen des Schlüssels aus dem Signierbildschirm behoben
## 2.2
- * New design with navigation drawer
- * New public key list design
+ * Neues Design mit "Navigation Drawer"
+ * Neues Design der Liste öffentlicher Schlüssel
* Neue Ansicht für öffentliche Schlüssel
- * Bug fixes for importing of keys
- * Key cross-certification (thanks to Ash Hughes)
- * Handle UTF-8 passwords properly (thanks to Ash Hughes)
- * First version with new languages (thanks to the contributors on Transifex)
- * Sharing of keys via QR Codes fixed and improved
- * Package signature verification for API
+ * Fehler beim Importieren von Schlüsseln behoben
+ * Schlüsselbeglaubigung über Kreuz (Dank an Ash Hughes)
+ * Korrekte Verarbeitung von UTF-8-Passwörtern (Dank an Ash Hughes)
+ * Erste Version mit neuen Sprachen (Dank an die Unterstützer auf Transifex)
+ * Teilen von Schlüsseln über QR-Codes behoben und verbessert
+ * Paket-Signaturprüfung für API
## 2.1.1
- * API Updates, preparation for K-9 Mail integration
+ * API-Aktualisierungen, Vorbereitung für die K-9-Mail-Integration
## 2.1
- * Lots of bug fixes
+ * Viele Fehlerbehebungen
* Neue API für Entwickler
- * PRNG bug fix by Google
+ * PRNG-Fehlerbehebung von Google
## 2.0
- * Complete redesign
- * Share public keys via QR codes, NFC beam
+ * Komplette Neugestaltung
+ * Öffentliche Schlüssel über QR-Codes oder NFC-Beam teilen
* Schlüssel unterschreiben
* Schlüssel auf den Server hochladen
- * Fixes import issues
+ * Behebt Importprobleme
* Neue AIDL-API
@@ -218,25 +225,25 @@ Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Pa
* Grundlegende Schlüsselserverunterstützung
* App2SD
- * More choices for passphrase cache: 1, 2, 4, 8, hours
- * Translations: Norwegian (thanks, Sander Danielsen), Chinese (thanks, Zhang Fredrick)
+ * Mehr Auswahlmöglichkeiten für den Passwortzwischenspeicher: 1, 2, 4, 8, Stunden
+ * Übersetzungen: Norwegisch (Dank an Sander Danielsen), Chinesisch (Dank an Zhang Fredrick)
* Fehlerbehebungen
* Optimierungen
## 1.0.7
- * Fixed problem with signature verification of texts with trailing newline
- * More options for passphrase cache time to live (20, 40, 60 mins)
+ * Problem mit Signaturprüfung von Texten mit angehängtem Zeilenvorschub behoben
+ * Mehr Optionen für die Länge der Passwortzwischenspeicherung (20, 40, 60 Minuten)
## 1.0.6
- * Account adding crash on Froyo fixed
+ * Absturz bei Kontoerstellung unter Froyo behoben
* Sichere Dateilöschung
- * Option to delete key file after import
+ * Option zum Löschen der Schlüsseldatei nach dem Import
* Streamverschlüsselung/-entschlüsselung (Galerie, usw.)
- * New options (language, force v3 signatures)
+ * Neue Optionen (Sprache, v3-Signaturen erzwingen)
* Oberflächenänderungen
* Fehlerbehebungen
@@ -244,40 +251,40 @@ Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Pa
## 1.0.5
* Deutsche und Italienische Übersetzung
- * Much smaller package, due to reduced BC sources
+ * Viel kleineres Paket durch reduzierte BC-Quellen
* Neues Einstellungen-Benutzeroberfläche
- * Layout adjustment for localization
- * Signature bugfix
+ * Anpassung der Anordnung für Übersetzungen
+ Fehler in der Signatur behoben
## 1.0.4
- * Fixed another crash caused by some SDK bug with query builder
+ * Weiteren Absturz durch einen SDK-Fehler mit "query builder" behoben
## 1.0.3
- * Fixed crashes during encryption/signing and possibly key export
+ * Abstürze während Verschlüsselung/Beglaubigung und möglicherweise Schlüsselexport behoben
## 1.0.2
* Filterbare Schlüsselliste
- * Smarter pre-selection of encryption keys
- * New Intent handling for VIEW and SEND, allows files to be encrypted/decrypted out of file managers
- * Fixes and additional features (key preselection) for K-9 Mail, new beta build available
+ * Intelligentere Vorauswahl von Verschlüsselungsschlüsseln
+ * Neue Absichtsbehandlung für VIEW und SEND, ermöglicht das Ver-/Entschlüsseln von Dateien aus Dateimanagern
+ * Fehlerbehebungen und zusätzliche Funktionen (Schlüsselvorauswahl) für K-9 Mail, neuer Beta-Build verfügbar
## 1.0.1
- * GMail account listing was broken in 1.0.0, fixed again
+ * GMail-Konto-Auflistung war fehlerhaft in 1.0.0, erneut behoben
## 1.0.0
- * K-9 Mail integration, APG supporting beta build of K-9 Mail
+ * K-9Mail-Integration, APG-unterstützendes Beta-Build von K-9 Mail
* Unterstützung von mehr Dateimanagern (einschließlich ASTRO)
* Slowenische Übersetzung
* Neue Datenbank, viel schneller, weniger Speicherbelegung
- * Defined Intents and content provider for other apps
+ * Definierte Absichten und Inhaltsanbieter für andere Apps
* Fehlerbehebungen \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-de/help_start.md b/OpenKeychain/src/main/res/raw-de/help_start.md
index 768d62737..81adbf136 100644
--- a/OpenKeychain/src/main/res/raw-de/help_start.md
+++ b/OpenKeychain/src/main/res/raw-de/help_start.md
@@ -4,13 +4,13 @@
Um OpenKeychain mit K-9 Mail zu nutzen, bitte folgenden Schritten folgen:
1. Öffne K-9 Mail und drücke lange auf den Account, mit dem du OpenKeychain nutzen willst.
2. Wähle "Kontoeinstellungen", blättere ganz nach unten und klicke auf "Kryptographie".
- 3. Drücke auf "OpenPGP-Provider" und OpenKeychain in der Liste auswählen.
+ 3. Drücke auf "OpenPGP-Provider" und wähle OpenKeychain aus der Liste aus.
-## Ich habe einen Fehler in OpenKeychail gefunden!
+## Ich habe einen Fehler in OpenKeychain gefunden!
Bitte melde den Fehler mithilfe des [Fehlertrackers von OpenKeychain](https://github.com/openpgp-keychain/openpgp-keychain/issues).
-## Unterstützen
-Wenn du uns bei der Entwicklung von OpenKeychain, z.B. durch das Beisteuern von Code, helfen willst, [schaue dir unsere kurze Anleitung auf GitHub an](https://github.com/openpgp-keychain/openpgp-keychain#contribute-code).
+## Mitwirken
+Wenn du uns bei der Entwicklung von OpenKeychain, z.B. durch das Beisteuern von Code, helfen willst, [schaue dir unsere Kurzanleitung auf GitHub an](https://github.com/openpgp-keychain/openpgp-keychain#contribute-code).
## Übersetzungen
Hilf mit, OpenKeychain zu übersetzen! Jeder kann mitmachen, [besuche OpenKeychain auf Transifex](https://www.transifex.com/projects/p/open-keychain/). \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-es/help_about.md b/OpenKeychain/src/main/res/raw-es/help_about.md
index fdf0e7063..194adfd3a 100644
--- a/OpenKeychain/src/main/res/raw-es/help_about.md
+++ b/OpenKeychain/src/main/res/raw-es/help_about.md
@@ -1,4 +1,4 @@
-[//]: # (NOTA: ¡Por favor ponga cada frase en su propia línea, Transifex pone cada línea en su propio campo de traducción!)
+[//]: # (NOTA: ¡Ponga cada frase en su propia línea, Transifex pone cada línea en su propio campo de traducción!)
[http://www.openkeychain.org](http://www.openkeychain.org)
@@ -6,14 +6,21 @@
Licencia: GPLv3+
+[//]: # (NOTA: Orden alfabético)
+
## Desarrolladores principales
* Dominik Schürmann (Mantenedor)
* Vincent Breitmoser
-## Contribuidores
+## Máximos contribuidores
* Adithya Abraham Philip
- * Art O Cathain
* Ash Hughes
+ * 'mar-v-in'
+ * 'Thialfihar' (desarrollador APG)
+ * Tim Bray
+
+## Contribuidores ocasionales
+ * Art O Cathain
* Brian C. Barnes
* Bahtiar 'kalkin' Gadimov
* Daniel Albert
@@ -34,7 +41,6 @@ Licencia: GPLv3+
* 'ligi'
* Lukas Zorich
* Manoj Khanna
- * 'mar-v-in'
* Markus Doits
* Miroojin Bakshi
* Morgan Gangwere
@@ -44,22 +50,23 @@ Licencia: GPLv3+
* Signe Rüsch
* Sreeram Boyapati
* 'steelman'
- * 'Thialfihar' (desarrollador APG)
- * Tim Bray
+
+[//]: # (NOTA: Orden alfabético)
## Librerías
- * [SpongyCastle](http://rtyley.github.com/spongycastle/) (Licencia MIT X11)
- * [Librería SafeSlinger Exchange](https://github.com/SafeSlingerProject/exchange-android) (Licencia MIT)
* [Librerías de Soporte Android](http://developer.android.com/tools/support-library/index.html) (Licencia Apache v2)
+ * [FloatingActionButton](https://github.com/futuresimple/android-floating-action-button) (Licencia Apache v2)
+ * [HtmlTextView](https://github.com/sufficientlysecure/html-textview) (Licencia Apache v2)
* [KeybaseLib](https://github.com/timbray/KeybaseLib) (Licencia Apache v2)
- * [TokenAutoComplete](https://github.com/splitwise/TokenAutoComplete) (Licencia Apache v2)
+ * [Markdown4J](https://github.com/jdcasey/markdown4j) (Licencia Apache v2)
+ * [MaterialDrawer](https://github.com/mikepenz/MaterialDrawer) (Licencia Apache v2)
* [MiniDNS](https://github.com/rtreffer/minidns) (Licencia Apache v2)
- * [StickyListHeaders](https://github.com/emilsjolander/StickyListHeaders) (Licencia Apache v2)
- * [ZXing](https://github.com/zxing/zxing) (Licencia Apache v2)
- * [ZXing Android Minimal](https://github.com/journeyapps/zxing-android-embedded) (Licencia Apache v2)
+ * [OkHttp](http://square.github.io/okhttp/) (Licencia Apache v2)
* [PagerSlidingTabStrip](https://github.com/jpardogo/PagerSlidingTabStrip) (Material Design) (Licencia Apache v2)
- * [MaterialDrawer](https://github.com/mikepenz/MaterialDrawer) (Licencia Apache v2)
+ * [Librería SafeSlinger Exchange](https://github.com/SafeSlingerProject/exchange-android) (Licencia MIT)
* [Snackbar](https://github.com/nispok/snackbar) (Licencia MIT)
- * [FloatingActionButton](https://github.com/futuresimple/android-floating-action-button) (Licencia Apache v2)
- * [HtmlTextView](https://github.com/sufficientlysecure/html-textview) (Licencia Apache v2)
- * [Markdown4J](https://github.com/jdcasey/markdown4j) (Licencia Apache v2) \ No newline at end of file
+ * [SpongyCastle](http://rtyley.github.com/spongycastle/) (Licencia MIT X11)
+ * [StickyListHeaders](https://github.com/emilsjolander/StickyListHeaders) (Licencia Apache v2)
+ * [TokenAutoComplete](https://github.com/splitwise/TokenAutoComplete) (Licencia Apache v2)
+ * [ZXing](https://github.com/zxing/zxing) (Licencia Apache v2)
+ * [ZXing Android Minimal](https://github.com/journeyapps/zxing-android-embedded) (Licencia Apache v2) \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-es/help_changelog.md b/OpenKeychain/src/main/res/raw-es/help_changelog.md
index 909a95fa9..49855890d 100644
--- a/OpenKeychain/src/main/res/raw-es/help_changelog.md
+++ b/OpenKeychain/src/main/res/raw-es/help_changelog.md
@@ -1,10 +1,17 @@
[//]: # (NOTA: ¡Por favor ponga cada frase en su propia línea, Transifex pone cada línea en su propio campo de traducción!)
+## 3.5
+
+ * Revocación de clave al borrar clave
+ * Comprobaciones mejoradas de criptografía no segura
+ * Reparacion: No cierra OpenKeychain tras completar el asistente de primera ejecución
+ * API: Versión 8
+
## 3.4
- * Anonymous key download over Tor
- * Proxy support
- * Better YubiKey error handling
+ * Descarga de clave anónima sobre Tor
+ * Soporte para proxy
+ * Manejo de errores de YubiKey mejorado
## 3.3
diff --git a/OpenKeychain/src/main/res/raw-et/help_about.md b/OpenKeychain/src/main/res/raw-et/help_about.md
index e80a2c766..06bed0021 100644
--- a/OpenKeychain/src/main/res/raw-et/help_about.md
+++ b/OpenKeychain/src/main/res/raw-et/help_about.md
@@ -6,14 +6,21 @@
License: GPLv3+
+[//]: # (NOTE: Alphabetic ordering)
+
## Main Developers
* Dominik Schürmann (Maintainer)
* Vincent Breitmoser
-## Contributors
+## Top Contributors
* Adithya Abraham Philip
- * Art O Cathain
* Ash Hughes
+ * 'mar-v-in'
+ * 'Thialfihar' (APG developer)
+ * Tim Bray
+
+## Occasional Contributors
+ * Art O Cathain
* Brian C. Barnes
* Bahtiar 'kalkin' Gadimov
* Daniel Albert
@@ -34,7 +41,6 @@ License: GPLv3+
* 'ligi'
* Lukas Zorich
* Manoj Khanna
- * 'mar-v-in'
* Markus Doits
* Miroojin Bakshi
* Morgan Gangwere
@@ -44,22 +50,23 @@ License: GPLv3+
* Signe Rüsch
* Sreeram Boyapati
* 'steelman'
- * 'Thialfihar' (APG developer)
- * Tim Bray
+
+[//]: # (NOTE: Alphabetic ordering)
## Libraries
- * [SpongyCastle](http://rtyley.github.com/spongycastle/) (MIT X11 License)
- * [SafeSlinger Exchange library](https://github.com/SafeSlingerProject/exchange-android) (MIT License)
* [Android Support Libraries](http://developer.android.com/tools/support-library/index.html) (Apache License v2)
+ * [FloatingActionButton](https://github.com/futuresimple/android-floating-action-button) (Apache License v2)
+ * [HtmlTextView](https://github.com/sufficientlysecure/html-textview) (Apache License v2)
* [KeybaseLib](https://github.com/timbray/KeybaseLib) (Apache License v2)
- * [TokenAutoComplete](https://github.com/splitwise/TokenAutoComplete) (Apache License v2)
+ * [Markdown4J](https://github.com/jdcasey/markdown4j) (Apache License v2)
+ * [MaterialDrawer](https://github.com/mikepenz/MaterialDrawer) (Apache License v2)
* [MiniDNS](https://github.com/rtreffer/minidns) (Apache License v2)
- * [StickyListHeaders](https://github.com/emilsjolander/StickyListHeaders) (Apache License v2)
- * [ZXing](https://github.com/zxing/zxing) (Apache License v2)
- * [ZXing Android Minimal](https://github.com/journeyapps/zxing-android-embedded) (Apache License v2)
+ * [OkHttp](http://square.github.io/okhttp/) (Apache License v2)
* [PagerSlidingTabStrip](https://github.com/jpardogo/PagerSlidingTabStrip) (Material Design) (Apache License v2)
- * [MaterialDrawer](https://github.com/mikepenz/MaterialDrawer) (Apache License v2)
+ * [SafeSlinger Exchange library](https://github.com/SafeSlingerProject/exchange-android) (MIT License)
* [Snackbar](https://github.com/nispok/snackbar) (MIT License)
- * [FloatingActionButton](https://github.com/futuresimple/android-floating-action-button) (Apache License v2)
- * [HtmlTextView](https://github.com/sufficientlysecure/html-textview) (Apache License v2)
- * [Markdown4J](https://github.com/jdcasey/markdown4j) (Apache License v2) \ No newline at end of file
+ * [SpongyCastle](http://rtyley.github.com/spongycastle/) (MIT X11 License)
+ * [StickyListHeaders](https://github.com/emilsjolander/StickyListHeaders) (Apache License v2)
+ * [TokenAutoComplete](https://github.com/splitwise/TokenAutoComplete) (Apache License v2)
+ * [ZXing](https://github.com/zxing/zxing) (Apache License v2)
+ * [ZXing Android Minimal](https://github.com/journeyapps/zxing-android-embedded) (Apache License v2) \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-et/help_changelog.md b/OpenKeychain/src/main/res/raw-et/help_changelog.md
index 45ac104e0..11d7975b1 100644
--- a/OpenKeychain/src/main/res/raw-et/help_changelog.md
+++ b/OpenKeychain/src/main/res/raw-et/help_changelog.md
@@ -1,5 +1,12 @@
[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
+## 3.5
+
+ * Key revocation on key deletion
+ * Improved checks for insecure cryptography
+ * Fix: Don't close OpenKeychain after first time wizard succeeds
+ * API: Version 8
+
## 3.4
* Anonymous key download over Tor
diff --git a/OpenKeychain/src/main/res/raw-eu/help_about.md b/OpenKeychain/src/main/res/raw-eu/help_about.md
index ce443f234..09a7737d4 100644
--- a/OpenKeychain/src/main/res/raw-eu/help_about.md
+++ b/OpenKeychain/src/main/res/raw-eu/help_about.md
@@ -6,14 +6,21 @@
Baimena: GPLv3+
+[//]: # (NOTE: Alphabetic ordering)
+
## Garatzaile Nagusiak
* Dominik Schürmann (Mantentzaileak)
* Vincent Breitmoser
-## Laguntzaileak
+## Top Contributors
* Adithya Abraham Philip
- * Art O Cathain
* Ash Hughes
+ * 'mar-v-in'
+ * 'Thialfihar' (APG garatzailea)
+ * Tim Bray
+
+## Occasional Contributors
+ * Art O Cathain
* Brian C. Barnes
* Bahtiar 'kalkin' Gadimov
* Daniel Albert
@@ -34,7 +41,6 @@ Baimena: GPLv3+
* 'ligi'
* Lukas Zorich
* Manoj Khanna
- * 'mar-v-in'
* Markus Doits
* Miroojin Bakshi
* Morgan Gangwere
@@ -44,22 +50,23 @@ Baimena: GPLv3+
* Signe Rüsch
* Sreeram Boyapati
* 'steelman'
- * 'Thialfihar' (APG garatzailea)
- * Tim Bray
+
+[//]: # (NOTE: Alphabetic ordering)
## Liburutegiak
- * [SpongyCastle](http://rtyley.github.com/spongycastle/) (MIT X11 Baimena)
- * [SafeSlinger Exchange library](https://github.com/SafeSlingerProject/exchange-android) (MIT Baimena)
* [Android Support Libraries](http://developer.android.com/tools/support-library/index.html) (Apache Baimena v2)
+ * [FloatingActionButton](https://github.com/futuresimple/android-floating-action-button) (Apache Baimena v2)
+ * [HtmlTextView](https://github.com/sufficientlysecure/html-textview) (Apache Baimena v2)
* [KeybaseLib](https://github.com/timbray/KeybaseLib) (Apache Baimena v2)
- * [TokenAutoComplete](https://github.com/splitwise/TokenAutoComplete) (Apache Baimena v2)
+ * [Markdown4J](https://github.com/jdcasey/markdown4j) (Apache Baimena v2)
+ * [MaterialDrawer](https://github.com/mikepenz/MaterialDrawer) (Apache Baimena v2)
* [MiniDNS](https://github.com/rtreffer/minidns) (Apache Baimena v2)
- * [StickyListHeaders](https://github.com/emilsjolander/StickyListHeaders) (Apache Baimena v2)
- * [ZXing](https://github.com/zxing/zxing) (Apache Baimena v2)
- * [ZXing Android Minimal](https://github.com/journeyapps/zxing-android-embedded) (Apache Baimena v2)
+ * [OkHttp](http://square.github.io/okhttp/) (Apache License v2)
* [PagerSlidingTabStrip](https://github.com/jpardogo/PagerSlidingTabStrip) (Material Diseinua) (Apache Baimena 2 bertsioa)
- * [MaterialDrawer](https://github.com/mikepenz/MaterialDrawer) (Apache Baimena v2)
+ * [SafeSlinger Exchange library](https://github.com/SafeSlingerProject/exchange-android) (MIT Baimena)
* [Snackbar](https://github.com/nispok/snackbar) (MIT Baimena)
- * [FloatingActionButton](https://github.com/futuresimple/android-floating-action-button) (Apache Baimena v2)
- * [HtmlTextView](https://github.com/sufficientlysecure/html-textview) (Apache Baimena v2)
- * [Markdown4J](https://github.com/jdcasey/markdown4j) (Apache Baimena v2) \ No newline at end of file
+ * [SpongyCastle](http://rtyley.github.com/spongycastle/) (MIT X11 Baimena)
+ * [StickyListHeaders](https://github.com/emilsjolander/StickyListHeaders) (Apache Baimena v2)
+ * [TokenAutoComplete](https://github.com/splitwise/TokenAutoComplete) (Apache Baimena v2)
+ * [ZXing](https://github.com/zxing/zxing) (Apache Baimena v2)
+ * [ZXing Android Minimal](https://github.com/journeyapps/zxing-android-embedded) (Apache Baimena v2) \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-eu/help_certification.md b/OpenKeychain/src/main/res/raw-eu/help_certification.md
index 1b6eff123..8e72cc063 100644
--- a/OpenKeychain/src/main/res/raw-eu/help_certification.md
+++ b/OpenKeychain/src/main/res/raw-eu/help_certification.md
@@ -19,10 +19,10 @@ Ukatua: Giltza hau aurrerantzean ez da baliozkoa. Bere jabeak ukatua izan da.
## Argibide Aurreratuak
OpenKeychain-en "giltza baieztapen" bat OpenPGP estandarraren araberako egiaztagiri bat sortuz egokitzen da.
Egiaztapen hau da ["egiaztapen generikoa (0x10)"](http://tools.ietf.org/html/rfc4880#section-5.2.1) estandarrean azaltzen duena honek:
-"The issuer of this certification does not make any particular assertion as to how well the certifier has checked that the owner of the key is in fact the person described by the User ID."
+"Egiaztagiri honen jaulkitzaileak ez du inolako baieztapen berezirik egin egiaztatzaileak zein ongi egiaztatu duen Erabiltzaile ID-ak azaltzen duen norbanakoa egitan den giltzaren jabea."
-Traditionally, certifications (also with higher certification levels, such as "positive certifications" (0x13)) are organized in OpenPGP's Web of Trust.
-Our model of key confirmation is a much simpler concept to avoid common usability problems related to this Web of Trust.
-We assume that keys are verified only to a certain degree that is still usable enough to be executed "on the go".
-We also do not implement (potentially transitive) trust signatures or an ownertrust database like in GnuPG.
-Furthermore, keys which contain at least one user ID certified by a trusted key will be marked as "confirmed" in the key listings. \ No newline at end of file
+Arrunt, egiaztagiriak (baita egiaztagiritze maila handienekoak, "egiaztagiritze positiboak" bezalakoak (0x13)) OpenPGP-ren Fidagarritasun Webean daude antolatuta.
+Gure giltza baieztapena adigai askoz errazagoa da Fidagarritasun Webaren erabiltze arrunteko arazoak saihesteko.
+Onartzen dugu giltzak maila batean bakarrik daudela egiaztatuta oraindik nahikoa erabilgarria dena "joanean" exekutatuak izateko.
+Ez dugu ezartzen ere (potentzialki transitiboa) sinadura fidagarriak edo jabe-fidagarritasuneko datubase bat GnuPG-n bezala.
+Gainera, gutxienez giltza fidagarri batek egiaztatuta dauden erabiltzaile ID egiaztagiritu bat duten giltzak "baieztatua" bezala markatuko dira giltza zerrendan. \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-eu/help_changelog.md b/OpenKeychain/src/main/res/raw-eu/help_changelog.md
index f7af66c5b..d9a918b92 100644
--- a/OpenKeychain/src/main/res/raw-eu/help_changelog.md
+++ b/OpenKeychain/src/main/res/raw-eu/help_changelog.md
@@ -1,10 +1,17 @@
[//]: # (OHARRA: Meseez jarri esaldi bakoitza bere lerroan, Transifex-ek lerroak bere itzulpen eremuan jartzen ditu!)
+## 3.5
+
+ * Key revocation on key deletion
+ * Improved checks for insecure cryptography
+ * Fix: Don't close OpenKeychain after first time wizard succeeds
+ * API: Version 8
+
## 3.4
- * Anonymous key download over Tor
- * Proxy support
- * Better YubiKey error handling
+ * Izengabeko giltza jeisketa Tor gain
+ * Proxy sostengua
+ * YubiKey akats kudeaketa hobea
## 3.3
@@ -79,68 +86,68 @@
## 2.9.1
- * Split encrypt screen into two
- * Fix key flags handling (now supporting Mailvelope 0.7 keys)
- * Improved passphrase handling
- * Key sharing via SafeSlinger
- * Experimental YubiKey support: Preference to allow other PINs, currently only signing via the OpenPGP API works, not inside of OpenKeychain
+ * Banandu enkriptaketa ikusleihoa bitan
+ * Zuzenduta giltza ikur kudeaketa (orain Mailvelope 0.7 giltzak sostengatzen dira)
+ * Hobetuta sar-esaldi kudeaketa
+ * Giltza elkarbanatzea SafeSlinger bidez
+ * YubiKey sostengu esperimentala: Hobespena beste PIN batzuk ahalbidetzeko, oraingoz OpenPGP API bidezko sinaketak besterik ez du lan egiten, ez OpenKeychain-en barne
* Fix usage of stripped keys
- * SHA256 as default for compatibility
- * Intent API has changed, see https://github.com/open-keychain/open-keychain/wiki/Intent-API
- * OpenPGP API now handles revoked/expired keys and returns all user ids
+ * SHA256 berezkoa bezala bateragarritasunagaitik
+ * Intent API aldatu egin da, ikusi https://github.com/open-keychain/open-keychain/wiki/Intent-API
+ * OpenPGP API-k orain ukatutako/iraungitutako giltzak kudeatzen ditu eta erabiltzaile id guztiak itzultzen ditu
## 2.9
- * Fixing crashes introduced in v2.8
- * Experimental ECC support
- * Experimental YubiKey support: Only signing with imported keys
+ * v2.8-ko matxurak zuzentzen
+ * ECC sostengu esperimentala
+ * YubiKey sostengu esperimentala: Sinadura inportatutako giltzekin bakarrik
## 2.8
- * So many bugs have been fixed in this release that we focus on the main new features
- * Key edit: awesome new design, key revocation
- * Key import: awesome new design, secure keyserver connections via hkps, keyserver resolving via DNS SRV records
- * New first time screen
- * New key creation screen: autocompletion of name and email based on your personal Android accounts
- * File encryption: awesome new design, support for encrypting multiple files
- * New icons to show status of key (by Brennan Novak)
- * Important bug fix: Importing of large key collections from a file is now possible
- * Notification showing cached passphrases
- * Keys are connected to Android's contacts
+ * Akats asko zuzendu dira ezaugarri berri nagusietan foku garen argitalpen honetan.
+ * Giltza edizioa: diseinu berri zoragarria, giltza ukapena
+ * Giltza inportazioa: diseinu berri zoragarria, giltz-zerbitzari elkarketa segurua hkps bidez, giltza-zerbitzari ebazpena DNS SRV erregistroen bidez
+ * Lehen aldia ikusleiho berria
+ * Giltza sortze ikusleiho berrria: izenaren eta postaren berez-osaketa zure Android-eko kontu pertsonaletan ohinarrituta
+ * Agiri enkriptaketa: diseinu berri zoragarria, agiri ugari enkriptazeko sostengua
+ * Ikur berriak giltzaren egoera erakusteko (Brennan Novak-ek egina)
+ * Akats zuzenketa garrantzitsua: Giltza bilduma handiak inportatzea agiri batetik orain ahal da
+ * Jakinarazpenak katxeatutako sar-esaldiak erakusten ditu
+ * Giltzak Android-ren harremanetara elkartuta daude
-This release wouldn't be possible without the work of Vincent Breitmoser (GSoC 2014), mar-v-in (GSoC 2014), Daniel Albert, Art O Cathain, Daniel Haß, Tim Bray, Thialfihar
+Argitalpen hau ezinezkoa litzake Breitmoser (GSoC 2014), mar-v-in (GSoC 2014), Daniel Albert, Art O Cathain, Daniel Haß, Tim Bray eta Thialfihar-ren lanik gabe
## 2.7
* Purple! (Dominik, Vincent)
- * New key view design (Dominik, Vincent)
- * New flat Android buttons (Dominik, Vincent)
- * API fixes (Dominik)
- * Keybase.io import (Tim Bray)
+ * Giltza ikuspegi diseinu berria (Dominik, Vincent)
+ * Android botoi lau berriak (Dominik, Vincent)
+ * API zuzenketak (Dominik)
+ * Keybase.io inportazioa (Tim Bray)
## 2.6.1
- * Some fixes for regression bugs
+ * Zenbait zuzenketa akats zaharrentzat
## 2.6
- * Key certifications (thanks to Vincent Breitmoser)
- * Support for GnuPG partial secret keys (thanks to Vincent Breitmoser)
- * New design for signature verification
- * Custom key length (thanks to Greg Witczak)
- * Fix share-functionality from other apps
+ * Giltza egiaztagiritzeak (Vincent Breitmoser-ri esker)
+ * GnuPG giltza sekretu partzialentzako sostengua (Vincent Breitmoser-ri esker)
+ * Diseinu berria sinadura egiaztapenerako
+ * Norbere giltza luzera (Greg Witczak-ri esker)
+ * Zuzenduta elkarbanatze-eginkizuna beste aplikazio batzuetatik
## 2.5
- * Fix decryption of symmetric OpenPGP messages/files
- * Refactored key edit screen (thanks to Ash Hughes)
- * New modern design for encrypt/decrypt screens
- * OpenPGP API version 3 (multiple api accounts, internal fixes, key lookup)
+ * Zuzenduta OpenPGP mezu/agiri simetrikoen dekriptaketa
+ * Berreginda giltza edizio ikusleihoa (Ash Hughes-ri esker)
+ * Diseinu moderno berria enkriptaketa/dekriptaketa ikusleihoentzat
+ * OpenPGP API bertsioa 3 (api kontu ugari, barneko zuzenketak, giltza bilaketa)
## 2.4
diff --git a/OpenKeychain/src/main/res/raw-ar/help_about.md b/OpenKeychain/src/main/res/raw-fa/help_about.md
index e80a2c766..daecd5cbf 100644
--- a/OpenKeychain/src/main/res/raw-ar/help_about.md
+++ b/OpenKeychain/src/main/res/raw-fa/help_about.md
@@ -1,19 +1,26 @@
-[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
+[//]: # (تذکر: هر جمله در همان خط!)
[http://www.openkeychain.org](http://www.openkeychain.org)
-[OpenKeychain](http://www.openkeychain.org) is an OpenPGP implementation for Android.
+[OpenKeychain](http://www.openkeychain.org) یک نسخه از OpenPGP برای اندروید است.
-License: GPLv3+
+مجوز: GPLv3+
-## Main Developers
- * Dominik Schürmann (Maintainer)
+[//]: # (NOTE: Alphabetic ordering)
+
+توسعه‌دهنده‌گان اصلی
+ * Dominik Schürmann (نگه دارنده)
* Vincent Breitmoser
-## Contributors
+## بیشترین مشارکت کنندگان
* Adithya Abraham Philip
- * Art O Cathain
* Ash Hughes
+ * 'mar-v-in'
+ * 'Thialfihar' (توسعه‌دهندۀ APG)
+ * Tim Bray
+
+## مشارکت کنندگان مقطعی
+ * Art O Cathain
* Brian C. Barnes
* Bahtiar 'kalkin' Gadimov
* Daniel Albert
@@ -34,7 +41,6 @@ License: GPLv3+
* 'ligi'
* Lukas Zorich
* Manoj Khanna
- * 'mar-v-in'
* Markus Doits
* Miroojin Bakshi
* Morgan Gangwere
@@ -44,22 +50,23 @@ License: GPLv3+
* Signe Rüsch
* Sreeram Boyapati
* 'steelman'
- * 'Thialfihar' (APG developer)
- * Tim Bray
-## Libraries
- * [SpongyCastle](http://rtyley.github.com/spongycastle/) (MIT X11 License)
- * [SafeSlinger Exchange library](https://github.com/SafeSlingerProject/exchange-android) (MIT License)
+[//]: # (NOTE: Alphabetic ordering)
+
+کتابخانه‌ها
* [Android Support Libraries](http://developer.android.com/tools/support-library/index.html) (Apache License v2)
+ * [FloatingActionButton](https://github.com/futuresimple/android-floating-action-button) (Apache License v2)
+ * [HtmlTextView](https://github.com/sufficientlysecure/html-textview) (Apache License v2)
* [KeybaseLib](https://github.com/timbray/KeybaseLib) (Apache License v2)
- * [TokenAutoComplete](https://github.com/splitwise/TokenAutoComplete) (Apache License v2)
+ * [Markdown4J](https://github.com/jdcasey/markdown4j) (Apache License v2)
+ * [MaterialDrawer](https://github.com/mikepenz/MaterialDrawer) (Apache License v2)
* [MiniDNS](https://github.com/rtreffer/minidns) (Apache License v2)
- * [StickyListHeaders](https://github.com/emilsjolander/StickyListHeaders) (Apache License v2)
- * [ZXing](https://github.com/zxing/zxing) (Apache License v2)
- * [ZXing Android Minimal](https://github.com/journeyapps/zxing-android-embedded) (Apache License v2)
+ * [OkHttp](http://square.github.io/okhttp/) (Apache License v2)
* [PagerSlidingTabStrip](https://github.com/jpardogo/PagerSlidingTabStrip) (Material Design) (Apache License v2)
- * [MaterialDrawer](https://github.com/mikepenz/MaterialDrawer) (Apache License v2)
+ * [SafeSlinger Exchange library](https://github.com/SafeSlingerProject/exchange-android) (MIT License)
* [Snackbar](https://github.com/nispok/snackbar) (MIT License)
- * [FloatingActionButton](https://github.com/futuresimple/android-floating-action-button) (Apache License v2)
- * [HtmlTextView](https://github.com/sufficientlysecure/html-textview) (Apache License v2)
- * [Markdown4J](https://github.com/jdcasey/markdown4j) (Apache License v2) \ No newline at end of file
+ * [SpongyCastle](http://rtyley.github.com/spongycastle/) (MIT X11 License)
+ * [StickyListHeaders](https://github.com/emilsjolander/StickyListHeaders) (Apache License v2)
+ * [TokenAutoComplete](https://github.com/splitwise/TokenAutoComplete) (Apache License v2)
+ * [ZXing](https://github.com/zxing/zxing) (Apache License v2)
+ * [ZXing Android Minimal](https://github.com/journeyapps/zxing-android-embedded) (Apache License v2) \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-is/help_certification.md b/OpenKeychain/src/main/res/raw-fa/help_certification.md
index 3518adf73..94a0dc26b 100644
--- a/OpenKeychain/src/main/res/raw-is/help_certification.md
+++ b/OpenKeychain/src/main/res/raw-fa/help_certification.md
@@ -1,7 +1,7 @@
-[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
+[//]: # (تذکر: هر جمله در همان خط!)
-## Key Confirmation
-Without confirmation, you cannot be sure if a key really corresponds to a specific person.
+## تأیید کلید
+بدون تأیید، شما نمی‌توانید مطمئن باشید که یک کلید متعلق به همان شخص است.
The simplest way to confirm a key is by scanning the QR Code or exchanging it via NFC.
To confirm keys between more than two persons, we suggest to use the key exchange method available for your keys.
diff --git a/OpenKeychain/src/main/res/raw-ar/help_changelog.md b/OpenKeychain/src/main/res/raw-fa/help_changelog.md
index 45ac104e0..e84775421 100644
--- a/OpenKeychain/src/main/res/raw-ar/help_changelog.md
+++ b/OpenKeychain/src/main/res/raw-fa/help_changelog.md
@@ -1,10 +1,17 @@
-[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
+[//]: # (تذکر: هر جمله در همان خط!)
+
+## 3.5
+
+ * Key revocation on key deletion
+ * Improved checks for insecure cryptography
+ * Fix: Don't close OpenKeychain after first time wizard succeeds
+ * API: Version 8
## 3.4
- * Anonymous key download over Tor
- * Proxy support
- * Better YubiKey error handling
+ * دانلود کلید به صورت مخفی توسط Tor
+ * پشتیبانی از پراکسی
+ * مدیریت بهترِ خطاهای کلید Yubi
## 3.3
@@ -220,7 +227,7 @@ Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Pa
* App2sd
* More choices for passphrase cache: 1, 2, 4, 8, hours
* Translations: Norwegian (thanks, Sander Danielsen), Chinese (thanks, Zhang Fredrick)
- * Bugfixes
+ تعمیر باگ‌ها
* Optimizations
@@ -238,7 +245,7 @@ Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Pa
* Stream encryption/decryption (gallery, etc.)
* New options (language, force v3 signatures)
* Interface changes
- * Bugfixes
+ تعمیر باگ‌ها
## 1.0.5
@@ -280,4 +287,4 @@ Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Pa
* Slovenian translation
* New database, much faster, less memory usage
* Defined Intents and content provider for other apps
- * Bugfixes \ No newline at end of file
+ تعمیر باگ‌ها \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-fa/help_start.md b/OpenKeychain/src/main/res/raw-fa/help_start.md
new file mode 100644
index 000000000..5bf44a862
--- /dev/null
+++ b/OpenKeychain/src/main/res/raw-fa/help_start.md
@@ -0,0 +1,16 @@
+[//]: # (تذکر: هر جمله در همان خط!)
+
+## چگونه OpenKeychain را در برنامهٔ K-9 Mail فعال کنم؟
+برای استفاده از OpenKeychain در برنامهٔ K-9 Mail، مراحل زیر را دنبال کنید:
+ 1. برنامهٔ K-9 Mail را باز کنید و روی حسابی که می‌خواهید در آن از OpenKeychain استفاده کنید، تَپ کرده و نگه دارید.
+ 2. "تنظیمات حساب" را انتخاب کنید، به پایین صفحه بروید و "رمزنگاری" را انتخاب کنید.
+ 3. روی "فراهم‌کنندهٔ OpenPGP" تپ کرده و OpenKeychain را از لیست انتخاب کنید.
+
+## من یک باگ در OpenKeychain پیدا کردم!
+لطفاً باگ را از این طریق [دنبال‌کنندهٔ مسائلِ OpenKeychain](https://github.com/openpgp-keychain/openpgp-keychain/issues) گزارش کنید.
+
+## مشارکت
+اگر می‌خواهید با نوشتن کد به ما در توسعهٔ OpenKeychain کمک کنید، [راهنمایی ما را در Github دنبال کنید](https://github.com/openpgp-keychain/openpgp-keychain#contribute-code).
+
+## ترجمه‌ها
+کمک کنید تا OpenKeychain را ترجمه کنیم! هر کسی می‌تواند از طریق [OpenKeychain بر روی Transifex](https://www.transifex.com/projects/p/open-keychain/) مشارکت داشته باشد. \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-fi/help_about.md b/OpenKeychain/src/main/res/raw-fi/help_about.md
index e80a2c766..06bed0021 100644
--- a/OpenKeychain/src/main/res/raw-fi/help_about.md
+++ b/OpenKeychain/src/main/res/raw-fi/help_about.md
@@ -6,14 +6,21 @@
License: GPLv3+
+[//]: # (NOTE: Alphabetic ordering)
+
## Main Developers
* Dominik Schürmann (Maintainer)
* Vincent Breitmoser
-## Contributors
+## Top Contributors
* Adithya Abraham Philip
- * Art O Cathain
* Ash Hughes
+ * 'mar-v-in'
+ * 'Thialfihar' (APG developer)
+ * Tim Bray
+
+## Occasional Contributors
+ * Art O Cathain
* Brian C. Barnes
* Bahtiar 'kalkin' Gadimov
* Daniel Albert
@@ -34,7 +41,6 @@ License: GPLv3+
* 'ligi'
* Lukas Zorich
* Manoj Khanna
- * 'mar-v-in'
* Markus Doits
* Miroojin Bakshi
* Morgan Gangwere
@@ -44,22 +50,23 @@ License: GPLv3+
* Signe Rüsch
* Sreeram Boyapati
* 'steelman'
- * 'Thialfihar' (APG developer)
- * Tim Bray
+
+[//]: # (NOTE: Alphabetic ordering)
## Libraries
- * [SpongyCastle](http://rtyley.github.com/spongycastle/) (MIT X11 License)
- * [SafeSlinger Exchange library](https://github.com/SafeSlingerProject/exchange-android) (MIT License)
* [Android Support Libraries](http://developer.android.com/tools/support-library/index.html) (Apache License v2)
+ * [FloatingActionButton](https://github.com/futuresimple/android-floating-action-button) (Apache License v2)
+ * [HtmlTextView](https://github.com/sufficientlysecure/html-textview) (Apache License v2)
* [KeybaseLib](https://github.com/timbray/KeybaseLib) (Apache License v2)
- * [TokenAutoComplete](https://github.com/splitwise/TokenAutoComplete) (Apache License v2)
+ * [Markdown4J](https://github.com/jdcasey/markdown4j) (Apache License v2)
+ * [MaterialDrawer](https://github.com/mikepenz/MaterialDrawer) (Apache License v2)
* [MiniDNS](https://github.com/rtreffer/minidns) (Apache License v2)
- * [StickyListHeaders](https://github.com/emilsjolander/StickyListHeaders) (Apache License v2)
- * [ZXing](https://github.com/zxing/zxing) (Apache License v2)
- * [ZXing Android Minimal](https://github.com/journeyapps/zxing-android-embedded) (Apache License v2)
+ * [OkHttp](http://square.github.io/okhttp/) (Apache License v2)
* [PagerSlidingTabStrip](https://github.com/jpardogo/PagerSlidingTabStrip) (Material Design) (Apache License v2)
- * [MaterialDrawer](https://github.com/mikepenz/MaterialDrawer) (Apache License v2)
+ * [SafeSlinger Exchange library](https://github.com/SafeSlingerProject/exchange-android) (MIT License)
* [Snackbar](https://github.com/nispok/snackbar) (MIT License)
- * [FloatingActionButton](https://github.com/futuresimple/android-floating-action-button) (Apache License v2)
- * [HtmlTextView](https://github.com/sufficientlysecure/html-textview) (Apache License v2)
- * [Markdown4J](https://github.com/jdcasey/markdown4j) (Apache License v2) \ No newline at end of file
+ * [SpongyCastle](http://rtyley.github.com/spongycastle/) (MIT X11 License)
+ * [StickyListHeaders](https://github.com/emilsjolander/StickyListHeaders) (Apache License v2)
+ * [TokenAutoComplete](https://github.com/splitwise/TokenAutoComplete) (Apache License v2)
+ * [ZXing](https://github.com/zxing/zxing) (Apache License v2)
+ * [ZXing Android Minimal](https://github.com/journeyapps/zxing-android-embedded) (Apache License v2) \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-fi/help_changelog.md b/OpenKeychain/src/main/res/raw-fi/help_changelog.md
index 45ac104e0..11d7975b1 100644
--- a/OpenKeychain/src/main/res/raw-fi/help_changelog.md
+++ b/OpenKeychain/src/main/res/raw-fi/help_changelog.md
@@ -1,5 +1,12 @@
[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
+## 3.5
+
+ * Key revocation on key deletion
+ * Improved checks for insecure cryptography
+ * Fix: Don't close OpenKeychain after first time wizard succeeds
+ * API: Version 8
+
## 3.4
* Anonymous key download over Tor
diff --git a/OpenKeychain/src/main/res/raw-fr/help_about.md b/OpenKeychain/src/main/res/raw-fr/help_about.md
index 0eb1e9823..5994ae4df 100644
--- a/OpenKeychain/src/main/res/raw-fr/help_about.md
+++ b/OpenKeychain/src/main/res/raw-fr/help_about.md
@@ -6,14 +6,21 @@
Licence : GPLv3+
+[//] : # (NOTE : tri alphabétique)
+
## Développeurs principaux
* Dominik Schürmann (mainteneur)
* Vincent Breitmoser
-## Contributeurs
+## Meilleurs contributeurs
* Adithya Abraham Philip
- * Art O Cathain
* Ash Hughes
+ * « mar-v-in »
+ * 'Thialfihar' (développeur APG)
+ * Tim Bray
+
+## Contributeurs occasionnels
+ * Art O Cathain
* Brian C. Barnes
* Bahtiar « kalkin » Gadimov
* Daniel Albert
@@ -34,7 +41,6 @@ Licence : GPLv3+
* 'ligi'
* Lukas Zorich
* Manoj Khanna
- * « mar-v-in »
* Markus Doits
* Miroojin Bakshi
* Morgan Gangwere
@@ -44,22 +50,23 @@ Licence : GPLv3+
* Signe Rüsch
* Sreeram Boyapati
* 'steelman'
- * 'Thialfihar' (développeur APG)
- * Tim Bray
+
+[//] : # (NOTE : tri alphabétique)
## Bibliothèques
- * [SpongyCastle](http://rtyley.github.com/spongycastle/) (Licence MIT X11)
- * [Bibliothèque d'échange SafeSlinger](https://github.com/SafeSlingerProject/exchange-android) (Licence MIT)
* [Bibliothèques de soutien Android](http://developer.android.com/tools/support-library/index.html) (Licence Apache v2)
+ * [FloatingActionButton](https://github.com/futuresimple/android-floating-action-button) (Licence Apache v2)
+ * [HtmlTextView](https://github.com/sufficientlysecure/html-textview) (Licence Apache v2)
* [KeybaseLib](https://github.com/timbray/KeybaseLib) (Licence Apache v2)
- * [TokenAutoComplete](https://github.com/splitwise/TokenAutoComplete) (Licence Apache v2)
+ * [Markdown4J](https://github.com/jdcasey/markdown4j) (Licence Apache v2)
+ * [MaterialDrawer](https://github.com/mikepenz/MaterialDrawer) (Licence Apache v2)
* [MiniDNS](https://github.com/rtreffer/minidns) (Licence Apache v2)
- * [StickyListHeaders](https://github.com/emilsjolander/StickyListHeaders) (Licence Apache v2)
- * [ZXing](https://github.com/zxing/zxing) (Licence Apache v2)
- * [ZXing Android Minimal](https://github.com/journeyapps/zxing-android-embedded) (Licence Apache v2)
+ * [OkHttp](http://square.github.io/okhttp/) (licence Apache v2)
* [PagerSlidingTabStrip](https://github.com/jpardogo/PagerSlidingTabStrip) (Conception matérielle)</a> (Licence Apache v2)
- * [MaterialDrawer](https://github.com/mikepenz/MaterialDrawer) (Licence Apache v2)
+ * [Bibliothèque d'échange SafeSlinger](https://github.com/SafeSlingerProject/exchange-android) (Licence MIT)
* [Snackbar](https://github.com/nispok/snackbar) (Licence MIT)
- * [FloatingActionButton](https://github.com/futuresimple/android-floating-action-button) (Licence Apache v2)
- * [HtmlTextView](https://github.com/sufficientlysecure/html-textview) (Licence Apache v2)
- * [Markdown4J](https://github.com/jdcasey/markdown4j) (Licence Apache v2) \ No newline at end of file
+ * [SpongyCastle](http://rtyley.github.com/spongycastle/) (Licence MIT X11)
+ * [StickyListHeaders](https://github.com/emilsjolander/StickyListHeaders) (Licence Apache v2)
+ * [TokenAutoComplete](https://github.com/splitwise/TokenAutoComplete) (Licence Apache v2)
+ * [ZXing](https://github.com/zxing/zxing) (Licence Apache v2)
+ * [ZXing Android Minimal](https://github.com/journeyapps/zxing-android-embedded) (Licence Apache v2) \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-fr/help_changelog.md b/OpenKeychain/src/main/res/raw-fr/help_changelog.md
index 4bbea2d1b..44e949c77 100644
--- a/OpenKeychain/src/main/res/raw-fr/help_changelog.md
+++ b/OpenKeychain/src/main/res/raw-fr/help_changelog.md
@@ -1,10 +1,17 @@
[//] : # (NOTE : veuillez mettre chaque phrase sur sa propre ligne. Transifex met chaque ligne dans son propre champ de traduction !)
+## 3.5
+
+ * révocation de la clef lors de la suppression de la clef
+ * Vérifications améliorées à la recherche d'une cryptographie non fiable
+ * Correctif : ne pas fermer OpenKeychain après une réussite de l'assistant de première utilisation
+ * API : version 8
+
## 3.4
- * Anonymous key download over Tor
- * Proxy support
- * Better YubiKey error handling
+ * Téléchargement anonyme de clefs avec Tor
+ * Prise en charge des serveurs mandataires
+ * Meilleur gestion des erreurs de la ClefYubi
## 3.3
diff --git a/OpenKeychain/src/main/res/raw-is/help_about.md b/OpenKeychain/src/main/res/raw-hu/help_about.md
index e80a2c766..06bed0021 100644
--- a/OpenKeychain/src/main/res/raw-is/help_about.md
+++ b/OpenKeychain/src/main/res/raw-hu/help_about.md
@@ -6,14 +6,21 @@
License: GPLv3+
+[//]: # (NOTE: Alphabetic ordering)
+
## Main Developers
* Dominik Schürmann (Maintainer)
* Vincent Breitmoser
-## Contributors
+## Top Contributors
* Adithya Abraham Philip
- * Art O Cathain
* Ash Hughes
+ * 'mar-v-in'
+ * 'Thialfihar' (APG developer)
+ * Tim Bray
+
+## Occasional Contributors
+ * Art O Cathain
* Brian C. Barnes
* Bahtiar 'kalkin' Gadimov
* Daniel Albert
@@ -34,7 +41,6 @@ License: GPLv3+
* 'ligi'
* Lukas Zorich
* Manoj Khanna
- * 'mar-v-in'
* Markus Doits
* Miroojin Bakshi
* Morgan Gangwere
@@ -44,22 +50,23 @@ License: GPLv3+
* Signe Rüsch
* Sreeram Boyapati
* 'steelman'
- * 'Thialfihar' (APG developer)
- * Tim Bray
+
+[//]: # (NOTE: Alphabetic ordering)
## Libraries
- * [SpongyCastle](http://rtyley.github.com/spongycastle/) (MIT X11 License)
- * [SafeSlinger Exchange library](https://github.com/SafeSlingerProject/exchange-android) (MIT License)
* [Android Support Libraries](http://developer.android.com/tools/support-library/index.html) (Apache License v2)
+ * [FloatingActionButton](https://github.com/futuresimple/android-floating-action-button) (Apache License v2)
+ * [HtmlTextView](https://github.com/sufficientlysecure/html-textview) (Apache License v2)
* [KeybaseLib](https://github.com/timbray/KeybaseLib) (Apache License v2)
- * [TokenAutoComplete](https://github.com/splitwise/TokenAutoComplete) (Apache License v2)
+ * [Markdown4J](https://github.com/jdcasey/markdown4j) (Apache License v2)
+ * [MaterialDrawer](https://github.com/mikepenz/MaterialDrawer) (Apache License v2)
* [MiniDNS](https://github.com/rtreffer/minidns) (Apache License v2)
- * [StickyListHeaders](https://github.com/emilsjolander/StickyListHeaders) (Apache License v2)
- * [ZXing](https://github.com/zxing/zxing) (Apache License v2)
- * [ZXing Android Minimal](https://github.com/journeyapps/zxing-android-embedded) (Apache License v2)
+ * [OkHttp](http://square.github.io/okhttp/) (Apache License v2)
* [PagerSlidingTabStrip](https://github.com/jpardogo/PagerSlidingTabStrip) (Material Design) (Apache License v2)
- * [MaterialDrawer](https://github.com/mikepenz/MaterialDrawer) (Apache License v2)
+ * [SafeSlinger Exchange library](https://github.com/SafeSlingerProject/exchange-android) (MIT License)
* [Snackbar](https://github.com/nispok/snackbar) (MIT License)
- * [FloatingActionButton](https://github.com/futuresimple/android-floating-action-button) (Apache License v2)
- * [HtmlTextView](https://github.com/sufficientlysecure/html-textview) (Apache License v2)
- * [Markdown4J](https://github.com/jdcasey/markdown4j) (Apache License v2) \ No newline at end of file
+ * [SpongyCastle](http://rtyley.github.com/spongycastle/) (MIT X11 License)
+ * [StickyListHeaders](https://github.com/emilsjolander/StickyListHeaders) (Apache License v2)
+ * [TokenAutoComplete](https://github.com/splitwise/TokenAutoComplete) (Apache License v2)
+ * [ZXing](https://github.com/zxing/zxing) (Apache License v2)
+ * [ZXing Android Minimal](https://github.com/journeyapps/zxing-android-embedded) (Apache License v2) \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-ar/help_certification.md b/OpenKeychain/src/main/res/raw-hu/help_certification.md
index 3518adf73..3518adf73 100644
--- a/OpenKeychain/src/main/res/raw-ar/help_certification.md
+++ b/OpenKeychain/src/main/res/raw-hu/help_certification.md
diff --git a/OpenKeychain/src/main/res/raw-is/help_changelog.md b/OpenKeychain/src/main/res/raw-hu/help_changelog.md
index 45ac104e0..11d7975b1 100644
--- a/OpenKeychain/src/main/res/raw-is/help_changelog.md
+++ b/OpenKeychain/src/main/res/raw-hu/help_changelog.md
@@ -1,5 +1,12 @@
[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
+## 3.5
+
+ * Key revocation on key deletion
+ * Improved checks for insecure cryptography
+ * Fix: Don't close OpenKeychain after first time wizard succeeds
+ * API: Version 8
+
## 3.4
* Anonymous key download over Tor
diff --git a/OpenKeychain/src/main/res/raw-ar/help_start.md b/OpenKeychain/src/main/res/raw-hu/help_start.md
index 4cc331942..4cc331942 100644
--- a/OpenKeychain/src/main/res/raw-ar/help_start.md
+++ b/OpenKeychain/src/main/res/raw-hu/help_start.md
diff --git a/OpenKeychain/src/main/res/raw-is/help_start.md b/OpenKeychain/src/main/res/raw-is/help_start.md
deleted file mode 100644
index 4cc331942..000000000
--- a/OpenKeychain/src/main/res/raw-is/help_start.md
+++ /dev/null
@@ -1,16 +0,0 @@
-[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
-
-## How do I activate OpenKeychain in K-9 Mail?
-To use OpenKeychain with K-9 Mail, you want to follow these steps:
- 1. Open K-9 Mail and long-tap on the account you want to use OpenKeychain with.
- 2. Select "Account settings", scroll to the very bottom and click "Cryptography".
- 3. Click on "OpenPGP Provider" and select OpenKeychain from the list.
-
-## I found a bug in OpenKeychain!
-Please report the bug using the [issue tracker of OpenKeychain](https://github.com/openpgp-keychain/openpgp-keychain/issues).
-
-## Contribute
-If you want to help us developing OpenKeychain by contributing code [follow our small guide on Github](https://github.com/openpgp-keychain/openpgp-keychain#contribute-code).
-
-## Translations
-Help translating OpenKeychain! Everybody can participate at [OpenKeychain on Transifex](https://www.transifex.com/projects/p/open-keychain/). \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-it/help_about.md b/OpenKeychain/src/main/res/raw-it/help_about.md
index d69eaaf89..dbf7b57a7 100644
--- a/OpenKeychain/src/main/res/raw-it/help_about.md
+++ b/OpenKeychain/src/main/res/raw-it/help_about.md
@@ -6,14 +6,21 @@
Licenza: GPLv3+
+[//]: # (NOTE: Alphabetic ordering)
+
## Sviluppatori principali
* Dominik Schürmann (Manutentore)
* Vincent Breitmoser
-## Collaboratori
+## Top Contributors
* Adithya Abraham Philip
- * Art O Cathain
* Ash Hughes
+ * 'mar-v-in'
+ * 'Thialfihar' (Sviluppatore APG)
+ * Tim Bray
+
+## Occasional Contributors
+ * Art O Cathain
* Brian C. Barnes
* Bahtiar 'kalkin' Gadimov
* Daniel Albert
@@ -34,7 +41,6 @@ Licenza: GPLv3+
* 'ligi'
* Lukas Zorich
* Manoj Khanna
- * 'mar-v-in'
* Markus Doits
* Miroojin Bakshi
* Morgan Gangwere
@@ -44,22 +50,23 @@ Licenza: GPLv3+
* Signe Rüsch
* Sreeram Boyapati
* 'steelman'
- * 'Thialfihar' (Sviluppatore APG)
- * Tim Bray
+
+[//]: # (NOTE: Alphabetic ordering)
## Librerie
- * [SpongyCastle](http://rtyley.github.com/spongycastle/) (MIT X11 License)
- * [SafeSlinger Exchange library](https://github.com/SafeSlingerProject/exchange-android) (MIT License)
* [Android Support Libraries](http://developer.android.com/tools/support-library/index.html) (Apache License v2)
+ * [FloatingActionButton](https://github.com/futuresimple/android-floating-action-button) (Apache License v2)
+ * [HtmlTextView](https://github.com/sufficientlysecure/html-textview) (Apache License v2)
* [KeybaseLib](https://github.com/timbray/KeybaseLib) (Apache License v2)
- * [TokenAutoComplete](https://github.com/splitwise/TokenAutoComplete) (Apache License v2)
+ * [Markdown4J](https://github.com/jdcasey/markdown4j) (Apache License v2)
+ * [MaterialDrawer](https://github.com/mikepenz/MaterialDrawer) (Apache License v2)
* [MiniDNS](https://github.com/rtreffer/minidns) (Apache License v2)
- * [StickyListHeaders](https://github.com/emilsjolander/StickyListHeaders) (Apache License v2)
- * [ZXing](https://github.com/zxing/zxing) (Apache License v2)
- * [ZXing Android Minimal](https://github.com/journeyapps/zxing-android-embedded) (Apache License v2)
+ * [OkHttp](http://square.github.io/okhttp/) (Apache License v2)
* [PagerSlidingTabStrip](https://github.com/jpardogo/PagerSlidingTabStrip) (Design materiale) (Apache License v2)
- * [MaterialDrawer](https://github.com/mikepenz/MaterialDrawer) (Apache License v2)
+ * [SafeSlinger Exchange library](https://github.com/SafeSlingerProject/exchange-android) (MIT License)
* [Snackbar](https://github.com/nispok/snackbar) (MIT License)
- * [FloatingActionButton](https://github.com/futuresimple/android-floating-action-button) (Apache License v2)
- * [HtmlTextView](https://github.com/sufficientlysecure/html-textview) (Apache License v2)
- * [Markdown4J](https://github.com/jdcasey/markdown4j) (Apache License v2) \ No newline at end of file
+ * [SpongyCastle](http://rtyley.github.com/spongycastle/) (MIT X11 License)
+ * [StickyListHeaders](https://github.com/emilsjolander/StickyListHeaders) (Apache License v2)
+ * [TokenAutoComplete](https://github.com/splitwise/TokenAutoComplete) (Apache License v2)
+ * [ZXing](https://github.com/zxing/zxing) (Apache License v2)
+ * [ZXing Android Minimal](https://github.com/journeyapps/zxing-android-embedded) (Apache License v2) \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-it/help_changelog.md b/OpenKeychain/src/main/res/raw-it/help_changelog.md
index 21b05c8d2..e5ebfc8c1 100644
--- a/OpenKeychain/src/main/res/raw-it/help_changelog.md
+++ b/OpenKeychain/src/main/res/raw-it/help_changelog.md
@@ -1,5 +1,12 @@
[//]: # (NOTA: Si prega di mettere ogni frase in una propria linea, Transifex mette ogni riga nel proprio campo di traduzione!)
+## 3.5
+
+ * Key revocation on key deletion
+ * Improved checks for insecure cryptography
+ * Fix: Don't close OpenKeychain after first time wizard succeeds
+ * API: Version 8
+
## 3.4
* Anonymous key download over Tor
diff --git a/OpenKeychain/src/main/res/raw-ja/help_about.md b/OpenKeychain/src/main/res/raw-ja/help_about.md
index ea3fc701f..17e3e17e3 100644
--- a/OpenKeychain/src/main/res/raw-ja/help_about.md
+++ b/OpenKeychain/src/main/res/raw-ja/help_about.md
@@ -6,14 +6,21 @@
ライセンス: GPLv3以降
+[//]: # (NOTE: Alphabetic ordering)
+
## メイン開発者
* Dominik Schürmann (メンテナ)
* Vincent Breitmoser
-## 貢献者
+## 最優秀貢献者たち
* Adithya Abraham Philip
- * Art O Cathain
* Ash Hughes
+ * 'mar-v-in'
+ * 'Thialfihar' (APG 開発者)
+ * Tim Bray
+
+## 時折貢献してくれる方たち
+ * Art O Cathain
* Brian C. Barnes
* Bahtiar 'kalkin' Gadimov
* Daniel Albert
@@ -34,7 +41,6 @@
* 'ligi'
* Lukas Zorich
* Manoj Khanna
- * 'mar-v-in'
* Markus Doits
* Miroojin Bakshi
* Morgan Gangwere
@@ -44,22 +50,23 @@
* Signe Rüsch
* Sreeram Boyapati
* 'steelman'
- * 'Thialfihar' (APG 開発者)
- * Tim Bray
+
+[//]: # (NOTE: Alphabetic ordering)
## ライブラリ
- * [SpongyCastle](http://rtyley.github.com/spongycastle/) (MIT X11 License)
- * [SafeSlinger Exchange library](https://github.com/SafeSlingerProject/exchange-android) (MIT License)
* [Android Support Libraries](http://developer.android.com/tools/support-library/index.html) (Apache License v2)
+ * [FloatingActionButton](https://github.com/futuresimple/android-floating-action-button) (Apache License v2)
+ * [HtmlTextView](https://github.com/sufficientlysecure/html-textview) (Apache License v2)
* [KeybaseLib](https://github.com/timbray/KeybaseLib) (Apache License v2)
- * [TokenAutoComplete](https://github.com/splitwise/TokenAutoComplete) (Apache License v2)
+ * [Markdown4J](https://github.com/jdcasey/markdown4j) (Apache License v2)
+ * [MaterialDrawer](https://github.com/mikepenz/MaterialDrawer) (Apache License v2)
* [MiniDNS](https://github.com/rtreffer/minidns) (Apache License v2)
- * [StickyListHeaders](https://github.com/emilsjolander/StickyListHeaders) (Apache License v2)
- * [ZXing](https://github.com/zxing/zxing) (Apache License v2)
- * [ZXing Android Minimal](https://github.com/journeyapps/zxing-android-embedded) (Apache License v2)
+ * [OkHttp](http://square.github.io/okhttp/) (Apache License v2)
* [PagerSlidingTabStrip](https://github.com/jpardogo/PagerSlidingTabStrip) (Material Design) (Apache License v2)
- * [MaterialDrawer](https://github.com/mikepenz/MaterialDrawer) (Apache License v2)
+ * [SafeSlinger Exchange library](https://github.com/SafeSlingerProject/exchange-android) (MIT License)
* [Snackbar](https://github.com/nispok/snackbar) (MIT License)
- * [FloatingActionButton](https://github.com/futuresimple/android-floating-action-button) (Apache License v2)
- * [HtmlTextView](https://github.com/sufficientlysecure/html-textview) (Apache License v2)
- * [Markdown4J](https://github.com/jdcasey/markdown4j) (Apache License v2) \ No newline at end of file
+ * [SpongyCastle](http://rtyley.github.com/spongycastle/) (MIT X11 License)
+ * [StickyListHeaders](https://github.com/emilsjolander/StickyListHeaders) (Apache License v2)
+ * [TokenAutoComplete](https://github.com/splitwise/TokenAutoComplete) (Apache License v2)
+ * [ZXing](https://github.com/zxing/zxing) (Apache License v2)
+ * [ZXing Android Minimal](https://github.com/journeyapps/zxing-android-embedded) (Apache License v2) \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-ja/help_changelog.md b/OpenKeychain/src/main/res/raw-ja/help_changelog.md
index 9c6dc7208..148a33206 100644
--- a/OpenKeychain/src/main/res/raw-ja/help_changelog.md
+++ b/OpenKeychain/src/main/res/raw-ja/help_changelog.md
@@ -1,10 +1,17 @@
[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
+## 3.5
+
+ * 鍵削除時の鍵の破棄
+ * セキュアではない暗号についてのチェックの改善
+ * 修正: OpenKeychainの初回ウィザード成功後クローズされない問題
+ * API: Version 8
+
## 3.4
- * Anonymous key download over Tor
- * Proxy support
- * Better YubiKey error handling
+ * Tor経由での匿名鍵ダウンロード
+ * プロキシのサポート
+ * よりよりYubiKeyのエラーの扱い
## 3.3
diff --git a/OpenKeychain/src/main/res/raw-kn/help_about.md b/OpenKeychain/src/main/res/raw-kn/help_about.md
deleted file mode 100644
index e80a2c766..000000000
--- a/OpenKeychain/src/main/res/raw-kn/help_about.md
+++ /dev/null
@@ -1,65 +0,0 @@
-[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
-
-[http://www.openkeychain.org](http://www.openkeychain.org)
-
-[OpenKeychain](http://www.openkeychain.org) is an OpenPGP implementation for Android.
-
-License: GPLv3+
-
-## Main Developers
- * Dominik Schürmann (Maintainer)
- * Vincent Breitmoser
-
-## Contributors
- * Adithya Abraham Philip
- * Art O Cathain
- * Ash Hughes
- * Brian C. Barnes
- * Bahtiar 'kalkin' Gadimov
- * Daniel Albert
- * Daniel Hammann
- * Daniel Haß
- * Daniel Nelz
- * Daniel Ramos
- * Greg Witczak
- * 'iseki'
- * Ishan Khanna
- * 'jellysheep'
- * 'Jesperbk'
- * 'jkolo'
- * Joey Castillo
- * Kai Jiang
- * Kartik Arora
- * 'Kent'
- * 'ligi'
- * Lukas Zorich
- * Manoj Khanna
- * 'mar-v-in'
- * Markus Doits
- * Miroojin Bakshi
- * Morgan Gangwere
- * Nikhil Peter Raj
- * Paul Sarbinowski
- * 'Senecaso'
- * Signe Rüsch
- * Sreeram Boyapati
- * 'steelman'
- * 'Thialfihar' (APG developer)
- * Tim Bray
-
-## Libraries
- * [SpongyCastle](http://rtyley.github.com/spongycastle/) (MIT X11 License)
- * [SafeSlinger Exchange library](https://github.com/SafeSlingerProject/exchange-android) (MIT License)
- * [Android Support Libraries](http://developer.android.com/tools/support-library/index.html) (Apache License v2)
- * [KeybaseLib](https://github.com/timbray/KeybaseLib) (Apache License v2)
- * [TokenAutoComplete](https://github.com/splitwise/TokenAutoComplete) (Apache License v2)
- * [MiniDNS](https://github.com/rtreffer/minidns) (Apache License v2)
- * [StickyListHeaders](https://github.com/emilsjolander/StickyListHeaders) (Apache License v2)
- * [ZXing](https://github.com/zxing/zxing) (Apache License v2)
- * [ZXing Android Minimal](https://github.com/journeyapps/zxing-android-embedded) (Apache License v2)
- * [PagerSlidingTabStrip](https://github.com/jpardogo/PagerSlidingTabStrip) (Material Design) (Apache License v2)
- * [MaterialDrawer](https://github.com/mikepenz/MaterialDrawer) (Apache License v2)
- * [Snackbar](https://github.com/nispok/snackbar) (MIT License)
- * [FloatingActionButton](https://github.com/futuresimple/android-floating-action-button) (Apache License v2)
- * [HtmlTextView](https://github.com/sufficientlysecure/html-textview) (Apache License v2)
- * [Markdown4J](https://github.com/jdcasey/markdown4j) (Apache License v2) \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-kn/help_certification.md b/OpenKeychain/src/main/res/raw-kn/help_certification.md
deleted file mode 100644
index 3518adf73..000000000
--- a/OpenKeychain/src/main/res/raw-kn/help_certification.md
+++ /dev/null
@@ -1,28 +0,0 @@
-[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
-
-## Key Confirmation
-Without confirmation, you cannot be sure if a key really corresponds to a specific person.
-The simplest way to confirm a key is by scanning the QR Code or exchanging it via NFC.
-To confirm keys between more than two persons, we suggest to use the key exchange method available for your keys.
-
-## Key Status
-
-<img src="status_signature_verified_cutout_24dp"/>
-Confirmed: You have already confirmed this key, e.g., by scanning the QR Code.
-<img src="status_signature_unverified_cutout_24dp"/>
-Unconfirmed: This key has not been confirmed yet. You cannot be sure if the key really corresponds to a specific person.
-<img src="status_signature_expired_cutout_24dp"/>
-Expired: This key is no longer valid. Only the owner can extend its validity.
-<img src="status_signature_revoked_cutout_24dp"/>
-Revoked: This key is no longer valid. It has been revoked by its owner.
-
-## Advanced Information
-A "key confirmation" in OpenKeychain is implemented by creating a certification according to the OpenPGP standard.
-This certification is a ["generic certification (0x10)"](http://tools.ietf.org/html/rfc4880#section-5.2.1) described in the standard by:
-"The issuer of this certification does not make any particular assertion as to how well the certifier has checked that the owner of the key is in fact the person described by the User ID."
-
-Traditionally, certifications (also with higher certification levels, such as "positive certifications" (0x13)) are organized in OpenPGP's Web of Trust.
-Our model of key confirmation is a much simpler concept to avoid common usability problems related to this Web of Trust.
-We assume that keys are verified only to a certain degree that is still usable enough to be executed "on the go".
-We also do not implement (potentially transitive) trust signatures or an ownertrust database like in GnuPG.
-Furthermore, keys which contain at least one user ID certified by a trusted key will be marked as "confirmed" in the key listings. \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-kn/help_changelog.md b/OpenKeychain/src/main/res/raw-kn/help_changelog.md
deleted file mode 100644
index 45ac104e0..000000000
--- a/OpenKeychain/src/main/res/raw-kn/help_changelog.md
+++ /dev/null
@@ -1,283 +0,0 @@
-[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
-
-## 3.4
-
- * Anonymous key download over Tor
- * Proxy support
- * Better YubiKey error handling
-
-## 3.3
-
- * New decryption screen
- * Decryption of multiple files at once
- * Better handling of YubiKey errors
-
-## 3.2
-
- * First version with full YubiKey support available from the user interface: Edit keys, bind YubiKey to keys,...
- * Material design
- * Integration of QR Code Scanning (New permissions required)
- * Improved key creation wizard
- * Fix missing contacts after sync
- * Requires Android 4
- * Redesigned key screen
- * Simplify crypto preferences, better selection of secure ciphers
- * API: Detached signatures, free selection of signing key,...
- * Fix: Some valid keys were shown revoked or expired
- * Don't accept signatures by expired or revoked subkeys
- * Keybase.io support in advanced view
- * Method to update all keys at once
-
-
-## 3.1.2
-
- * Fix key export to files (now for real)
-
-
-## 3.1.1
-
- * Fix key export to files (they were written partially)
- * Fix crash on Android 2.3
-
-
-## 3.1
-
- * Fix crash on Android 5
- * New certify screen
- * Secure Exchange directly from key list (SafeSlinger library)
- * New QR Code program flow
- * Redesigned decrypt screen
- * New icon usage and colors
- * Fix import of secret keys from Symantec Encryption Desktop
- * Experimental YubiKey support: Subkey IDs are now checked correctly
-
-
-## 3.0.1
-
- * Better handling of large key imports
- * Improved subkey selection
-
-
-## 3.0
-
- * Propose installable compatible apps in apps list
- * New design for decryption screens
- * Many fixes for key import, also fixes stripped keys
- * Honor and display key authenticate flags
- * User interface to generate custom keys
- * Fixing user id revocation certificates
- * New cloud search (searches over traditional keyservers and keybase.io)
- * Support for stripping keys inside OpenKeychain
- * Experimental YubiKey support: Support for signature generation and decryption
-
-
-## 2.9.2
-
- * Fix keys broken in 2.9.1
- * Experimental YubiKey support: Decryption now working via API
-
-
-## 2.9.1
-
- * Split encrypt screen into two
- * Fix key flags handling (now supporting Mailvelope 0.7 keys)
- * Improved passphrase handling
- * Key sharing via SafeSlinger
- * Experimental YubiKey support: Preference to allow other PINs, currently only signing via the OpenPGP API works, not inside of OpenKeychain
- * Fix usage of stripped keys
- * SHA256 as default for compatibility
- * Intent API has changed, see https://github.com/open-keychain/open-keychain/wiki/Intent-API
- * OpenPGP API now handles revoked/expired keys and returns all user ids
-
-
-## 2.9
-
- * Fixing crashes introduced in v2.8
- * Experimental ECC support
- * Experimental YubiKey support: Only signing with imported keys
-
-
-## 2.8
-
- * So many bugs have been fixed in this release that we focus on the main new features
- * Key edit: awesome new design, key revocation
- * Key import: awesome new design, secure keyserver connections via hkps, keyserver resolving via DNS SRV records
- * New first time screen
- * New key creation screen: autocompletion of name and email based on your personal Android accounts
- * File encryption: awesome new design, support for encrypting multiple files
- * New icons to show status of key (by Brennan Novak)
- * Important bug fix: Importing of large key collections from a file is now possible
- * Notification showing cached passphrases
- * Keys are connected to Android's contacts
-
-This release wouldn't be possible without the work of Vincent Breitmoser (GSoC 2014), mar-v-in (GSoC 2014), Daniel Albert, Art O Cathain, Daniel Haß, Tim Bray, Thialfihar
-
-## 2.7
-
- * Purple! (Dominik, Vincent)
- * New key view design (Dominik, Vincent)
- * New flat Android buttons (Dominik, Vincent)
- * API fixes (Dominik)
- * Keybase.io import (Tim Bray)
-
-
-## 2.6.1
-
- * Some fixes for regression bugs
-
-
-## 2.6
-
- * Key certifications (thanks to Vincent Breitmoser)
- * Support for GnuPG partial secret keys (thanks to Vincent Breitmoser)
- * New design for signature verification
- * Custom key length (thanks to Greg Witczak)
- * Fix share-functionality from other apps
-
-
-## 2.5
-
- * Fix decryption of symmetric OpenPGP messages/files
- * Refactored key edit screen (thanks to Ash Hughes)
- * New modern design for encrypt/decrypt screens
- * OpenPGP API version 3 (multiple api accounts, internal fixes, key lookup)
-
-
-## 2.4
-Thanks to all applicants of Google Summer of Code 2014 who made this release feature rich and bug free!
-Besides several small patches, a notable number of patches are made by the following people (in alphabetical order):
-Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Paul Sarbinowski, Sreeram Boyapati, Vincent Breitmoser.
-
- * New unified key list
- * Colorized key fingerprint
- * Support for keyserver ports
- * Deactivate possibility to generate weak keys
- * Much more internal work on the API
- * Certify user ids
- * Keyserver query based on machine-readable output
- * Lock navigation drawer on tablets
- * Suggestions for emails on creation of keys
- * Search in public key lists
- * And much more improvements and fixes…
-
-
-## 2.3.1
-
- * Hotfix for crash when upgrading from old versions
-
-
-## 2.3
-
- * Remove unnecessary export of public keys when exporting secret key (thanks to Ash Hughes)
- * Fix setting expiry dates on keys (thanks to Ash Hughes)
- * More internal fixes when editing keys (thanks to Ash Hughes)
- * Querying keyservers directly from the import screen
- * Fix layout and dialog style on Android 2.2-3.0
- * Fix crash on keys with empty user ids
- * Fix crash and empty lists when coming back from signing screen
- * Bouncy Castle (cryptography library) updated from 1.47 to 1.50 and build from source
- * Fix upload of key from signing screen
-
-
-## 2.2
-
- * New design with navigation drawer
- * New public key list design
- * New public key view
- * Bug fixes for importing of keys
- * Key cross-certification (thanks to Ash Hughes)
- * Handle UTF-8 passwords properly (thanks to Ash Hughes)
- * First version with new languages (thanks to the contributors on Transifex)
- * Sharing of keys via QR Codes fixed and improved
- * Package signature verification for API
-
-
-## 2.1.1
-
- * API Updates, preparation for K-9 Mail integration
-
-
-## 2.1
-
- * Lots of bug fixes
- * New API for developers
- * PRNG bug fix by Google
-
-
-## 2.0
-
- * Complete redesign
- * Share public keys via QR codes, NFC beam
- * Sign keys
- * Upload keys to server
- * Fixes import issues
- * New AIDL API
-
-
-## 1.0.8
-
- * Basic keyserver support
- * App2sd
- * More choices for passphrase cache: 1, 2, 4, 8, hours
- * Translations: Norwegian (thanks, Sander Danielsen), Chinese (thanks, Zhang Fredrick)
- * Bugfixes
- * Optimizations
-
-
-## 1.0.7
-
- * Fixed problem with signature verification of texts with trailing newline
- * More options for passphrase cache time to live (20, 40, 60 mins)
-
-
-## 1.0.6
-
- * Account adding crash on Froyo fixed
- * Secure file deletion
- * Option to delete key file after import
- * Stream encryption/decryption (gallery, etc.)
- * New options (language, force v3 signatures)
- * Interface changes
- * Bugfixes
-
-
-## 1.0.5
-
- * German and Italian translation
- * Much smaller package, due to reduced BC sources
- * New preferences GUI
- * Layout adjustment for localization
- * Signature bugfix
-
-
-## 1.0.4
-
- * Fixed another crash caused by some SDK bug with query builder
-
-
-## 1.0.3
-
- * Fixed crashes during encryption/signing and possibly key export
-
-
-## 1.0.2
-
- * Filterable key lists
- * Smarter pre-selection of encryption keys
- * New Intent handling for VIEW and SEND, allows files to be encrypted/decrypted out of file managers
- * Fixes and additional features (key preselection) for K-9 Mail, new beta build available
-
-
-## 1.0.1
-
- * GMail account listing was broken in 1.0.0, fixed again
-
-
-## 1.0.0
-
- * K-9 Mail integration, APG supporting beta build of K-9 Mail
- * Support of more file managers (including ASTRO)
- * Slovenian translation
- * New database, much faster, less memory usage
- * Defined Intents and content provider for other apps
- * Bugfixes \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-kn/help_start.md b/OpenKeychain/src/main/res/raw-kn/help_start.md
deleted file mode 100644
index 4cc331942..000000000
--- a/OpenKeychain/src/main/res/raw-kn/help_start.md
+++ /dev/null
@@ -1,16 +0,0 @@
-[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
-
-## How do I activate OpenKeychain in K-9 Mail?
-To use OpenKeychain with K-9 Mail, you want to follow these steps:
- 1. Open K-9 Mail and long-tap on the account you want to use OpenKeychain with.
- 2. Select "Account settings", scroll to the very bottom and click "Cryptography".
- 3. Click on "OpenPGP Provider" and select OpenKeychain from the list.
-
-## I found a bug in OpenKeychain!
-Please report the bug using the [issue tracker of OpenKeychain](https://github.com/openpgp-keychain/openpgp-keychain/issues).
-
-## Contribute
-If you want to help us developing OpenKeychain by contributing code [follow our small guide on Github](https://github.com/openpgp-keychain/openpgp-keychain#contribute-code).
-
-## Translations
-Help translating OpenKeychain! Everybody can participate at [OpenKeychain on Transifex](https://www.transifex.com/projects/p/open-keychain/). \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-nl/help_about.md b/OpenKeychain/src/main/res/raw-nl/help_about.md
index e5206fd84..5c0bc3327 100644
--- a/OpenKeychain/src/main/res/raw-nl/help_about.md
+++ b/OpenKeychain/src/main/res/raw-nl/help_about.md
@@ -6,14 +6,21 @@
Licentie: GPLv3+
+[//]: # (NOTE: Alphabetic ordering)
+
## Hoofdontwikkelaars
* Dominik Schürmann (beheerder)
* Vincent Breitmoser
-## Medewerkers
+## Topmedewerkers
* Adithya Abraham Philip
- * Art O Cathain
* Ash Hughes
+ * 'mar-v-in'
+ * 'Thialfihar' (ontwikkelaar van APG)
+ * Tim Bray
+
+## Occasionele medewerkers
+ * Art O Cathain
* Brian C. Barnes
* Bahtiar 'kalkin' Gadimov
* Daniel Albert
@@ -34,7 +41,6 @@ Licentie: GPLv3+
* 'ligi'
* Lukas Zorich
* Manoj Khanna
- * 'mar-v-in'
* Markus Doits
* Miroojin Bakshi
* Morgan Gangwere
@@ -44,22 +50,23 @@ Licentie: GPLv3+
* Signe Rüsch
* Sreeram Boyapati
* 'steelman'
- * 'Thialfihar' (ontwikkelaar van APG)
- * Tim Bray
+
+[//]: # (NOTE: Alphabetic ordering)
## Bibliotheken
- * [SpongyCastle](http://rtyley.github.com/spongycastle/) (MIT X11 licentie)
- * [SafeSlinger Exchange library](https://github.com/SafeSlingerProject/exchange-android) (MIT licentie)
* [Android Support Libraries](http://developer.android.com/tools/support-library/index.html) (Apache licentie v2)
+ * [FloatingActionButton](https://github.com/futuresimple/android-floating-action-button) (Apache licentie v2)
+ * [HtmlTextView](https://github.com/sufficientlysecure/html-textview) (Apache licentie v2)
* [KeybaseLib](https://github.com/timbray/KeybaseLib) (Apache licentie v2)
- * [TokenAutoComplete](https://github.com/splitwise/TokenAutoComplete) (Apache licentie v2)
+ * [Markdown4J](https://github.com/jdcasey/markdown4j) (Apache licentie v2)
+ * [MaterialDrawer](https://github.com/mikepenz/MaterialDrawer) (Apache licentie v2)
* [MiniDNS](https://github.com/rtreffer/minidns) (Apache licentie v2)
- * [StickyListHeaders](https://github.com/emilsjolander/StickyListHeaders) (Apache licentie v2)
- * [ZXing](https://github.com/zxing/zxing) (Apache licentie v2)
- * [ZXing Android Minimal](https://github.com/journeyapps/zxing-android-embedded) (Apache licentie v2)
+ * [OkHttp](http://square.github.io/okhttp/) (Apache licentie v2)
* [PagerSlidingTabStrip](https://github.com/jpardogo/PagerSlidingTabStrip) (Material Design) (Apache licentie v2)
- * [MaterialDrawer](https://github.com/mikepenz/MaterialDrawer) (Apache licentie v2)
+ * [SafeSlinger Exchange library](https://github.com/SafeSlingerProject/exchange-android) (MIT licentie)
* [Snackbar](https://github.com/nispok/snackbar) (MIT licentie)
- * [FloatingActionButton](https://github.com/futuresimple/android-floating-action-button) (Apache licentie v2)
- * [HtmlTextView](https://github.com/sufficientlysecure/html-textview) (Apache licentie v2)
- * [Markdown4J](https://github.com/jdcasey/markdown4j) (Apache licentie v2) \ No newline at end of file
+ * [SpongyCastle](http://rtyley.github.com/spongycastle/) (MIT X11 licentie)
+ * [StickyListHeaders](https://github.com/emilsjolander/StickyListHeaders) (Apache licentie v2)
+ * [TokenAutoComplete](https://github.com/splitwise/TokenAutoComplete) (Apache licentie v2)
+ * [ZXing](https://github.com/zxing/zxing) (Apache licentie v2)
+ * [ZXing Android Minimal](https://github.com/journeyapps/zxing-android-embedded) (Apache licentie v2) \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-nl/help_changelog.md b/OpenKeychain/src/main/res/raw-nl/help_changelog.md
index 88b23916b..d378550c4 100644
--- a/OpenKeychain/src/main/res/raw-nl/help_changelog.md
+++ b/OpenKeychain/src/main/res/raw-nl/help_changelog.md
@@ -1,10 +1,17 @@
[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
+## 3.5
+
+ * Sleutel intrekken bij verwijderen
+ * Verbeterde controles voor onveilige cryptografie
+ * Opgelost: Sluit OpenKeychain niet na eerste gebruik
+ * API: versie 8
+
## 3.4
- * Anonymous key download over Tor
- * Proxy support
- * Better YubiKey error handling
+ * Anoniem sleutels downloaden via Tor
+ * Proxy-ondersteuning
+ * Beter verwerken van YubiKey-fouten
## 3.3
diff --git a/OpenKeychain/src/main/res/raw-pl/help_about.md b/OpenKeychain/src/main/res/raw-pl/help_about.md
index eb3328cfa..7262dfefd 100644
--- a/OpenKeychain/src/main/res/raw-pl/help_about.md
+++ b/OpenKeychain/src/main/res/raw-pl/help_about.md
@@ -6,14 +6,21 @@
Licencja: GPLv3+
+[//]: # (NOTE: Alphabetic ordering)
+
## Główni deweloperzy
* Dominik Schürmann (Opiekun projektu)
* Vincent Breitmoser
-## Contributors
+## Top Contributors
* Adithya Abraham Philip
- * Art O Cathain
* Ash Hughes
+ * 'mar-v-in'
+ * 'Thialfihar' (APG developer)
+ * Tim Bray
+
+## Occasional Contributors
+ * Art O Cathain
* Brian C. Barnes
* Bahtiar 'kalkin' Gadimov
* Daniel Albert
@@ -34,7 +41,6 @@ Licencja: GPLv3+
* 'ligi'
* Lukas Zorich
* Manoj Khanna
- * 'mar-v-in'
* Markus Doits
* Miroojin Bakshi
* Morgan Gangwere
@@ -44,22 +50,23 @@ Licencja: GPLv3+
* Signe Rüsch
* Sreeram Boyapati
* 'steelman'
- * 'Thialfihar' (APG developer)
- * Tim Bray
+
+[//]: # (NOTE: Alphabetic ordering)
## Biblioteki
- * [SpongyCastle](http://rtyley.github.com/spongycastle/) (MIT X11 License)
- * [SafeSlinger Exchange library](https://github.com/SafeSlingerProject/exchange-android) (MIT License)
* [Android Support Libraries](http://developer.android.com/tools/support-library/index.html) (Apache License v2)
+ * [FloatingActionButton](https://github.com/futuresimple/android-floating-action-button) (Apache License v2)
+ * [HtmlTextView](https://github.com/sufficientlysecure/html-textview) (Apache License v2)
* [KeybaseLib](https://github.com/timbray/KeybaseLib) (Apache License v2)
- * [TokenAutoComplete](https://github.com/splitwise/TokenAutoComplete) (Apache License v2)
+ * [Markdown4J](https://github.com/jdcasey/markdown4j) (Apache License v2)
+ * [MaterialDrawer](https://github.com/mikepenz/MaterialDrawer) (Apache License v2)
* [MiniDNS](https://github.com/rtreffer/minidns) (Apache License v2)
- * [StickyListHeaders](https://github.com/emilsjolander/StickyListHeaders) (Apache License v2)
- * [ZXing](https://github.com/zxing/zxing) (Apache License v2)
- * [ZXing Android Minimal](https://github.com/journeyapps/zxing-android-embedded) (Apache License v2)
+ * [OkHttp](http://square.github.io/okhttp/) (Apache License v2)
* [PagerSlidingTabStrip](https://github.com/jpardogo/PagerSlidingTabStrip) (Material Design) (Apache License v2)
- * [MaterialDrawer](https://github.com/mikepenz/MaterialDrawer) (Apache License v2)
+ * [SafeSlinger Exchange library](https://github.com/SafeSlingerProject/exchange-android) (MIT License)
* [Snackbar](https://github.com/nispok/snackbar) (MIT License)
- * [FloatingActionButton](https://github.com/futuresimple/android-floating-action-button) (Apache License v2)
- * [HtmlTextView](https://github.com/sufficientlysecure/html-textview) (Apache License v2)
- * [Markdown4J](https://github.com/jdcasey/markdown4j) (Apache License v2) \ No newline at end of file
+ * [SpongyCastle](http://rtyley.github.com/spongycastle/) (MIT X11 License)
+ * [StickyListHeaders](https://github.com/emilsjolander/StickyListHeaders) (Apache License v2)
+ * [TokenAutoComplete](https://github.com/splitwise/TokenAutoComplete) (Apache License v2)
+ * [ZXing](https://github.com/zxing/zxing) (Apache License v2)
+ * [ZXing Android Minimal](https://github.com/journeyapps/zxing-android-embedded) (Apache License v2) \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-pl/help_changelog.md b/OpenKeychain/src/main/res/raw-pl/help_changelog.md
index 45ac104e0..11d7975b1 100644
--- a/OpenKeychain/src/main/res/raw-pl/help_changelog.md
+++ b/OpenKeychain/src/main/res/raw-pl/help_changelog.md
@@ -1,5 +1,12 @@
[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
+## 3.5
+
+ * Key revocation on key deletion
+ * Improved checks for insecure cryptography
+ * Fix: Don't close OpenKeychain after first time wizard succeeds
+ * API: Version 8
+
## 3.4
* Anonymous key download over Tor
diff --git a/OpenKeychain/src/main/res/raw-pt/help_about.md b/OpenKeychain/src/main/res/raw-pt/help_about.md
deleted file mode 100644
index e80a2c766..000000000
--- a/OpenKeychain/src/main/res/raw-pt/help_about.md
+++ /dev/null
@@ -1,65 +0,0 @@
-[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
-
-[http://www.openkeychain.org](http://www.openkeychain.org)
-
-[OpenKeychain](http://www.openkeychain.org) is an OpenPGP implementation for Android.
-
-License: GPLv3+
-
-## Main Developers
- * Dominik Schürmann (Maintainer)
- * Vincent Breitmoser
-
-## Contributors
- * Adithya Abraham Philip
- * Art O Cathain
- * Ash Hughes
- * Brian C. Barnes
- * Bahtiar 'kalkin' Gadimov
- * Daniel Albert
- * Daniel Hammann
- * Daniel Haß
- * Daniel Nelz
- * Daniel Ramos
- * Greg Witczak
- * 'iseki'
- * Ishan Khanna
- * 'jellysheep'
- * 'Jesperbk'
- * 'jkolo'
- * Joey Castillo
- * Kai Jiang
- * Kartik Arora
- * 'Kent'
- * 'ligi'
- * Lukas Zorich
- * Manoj Khanna
- * 'mar-v-in'
- * Markus Doits
- * Miroojin Bakshi
- * Morgan Gangwere
- * Nikhil Peter Raj
- * Paul Sarbinowski
- * 'Senecaso'
- * Signe Rüsch
- * Sreeram Boyapati
- * 'steelman'
- * 'Thialfihar' (APG developer)
- * Tim Bray
-
-## Libraries
- * [SpongyCastle](http://rtyley.github.com/spongycastle/) (MIT X11 License)
- * [SafeSlinger Exchange library](https://github.com/SafeSlingerProject/exchange-android) (MIT License)
- * [Android Support Libraries](http://developer.android.com/tools/support-library/index.html) (Apache License v2)
- * [KeybaseLib](https://github.com/timbray/KeybaseLib) (Apache License v2)
- * [TokenAutoComplete](https://github.com/splitwise/TokenAutoComplete) (Apache License v2)
- * [MiniDNS](https://github.com/rtreffer/minidns) (Apache License v2)
- * [StickyListHeaders](https://github.com/emilsjolander/StickyListHeaders) (Apache License v2)
- * [ZXing](https://github.com/zxing/zxing) (Apache License v2)
- * [ZXing Android Minimal](https://github.com/journeyapps/zxing-android-embedded) (Apache License v2)
- * [PagerSlidingTabStrip](https://github.com/jpardogo/PagerSlidingTabStrip) (Material Design) (Apache License v2)
- * [MaterialDrawer](https://github.com/mikepenz/MaterialDrawer) (Apache License v2)
- * [Snackbar](https://github.com/nispok/snackbar) (MIT License)
- * [FloatingActionButton](https://github.com/futuresimple/android-floating-action-button) (Apache License v2)
- * [HtmlTextView](https://github.com/sufficientlysecure/html-textview) (Apache License v2)
- * [Markdown4J](https://github.com/jdcasey/markdown4j) (Apache License v2) \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-pt/help_certification.md b/OpenKeychain/src/main/res/raw-pt/help_certification.md
deleted file mode 100644
index 3518adf73..000000000
--- a/OpenKeychain/src/main/res/raw-pt/help_certification.md
+++ /dev/null
@@ -1,28 +0,0 @@
-[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
-
-## Key Confirmation
-Without confirmation, you cannot be sure if a key really corresponds to a specific person.
-The simplest way to confirm a key is by scanning the QR Code or exchanging it via NFC.
-To confirm keys between more than two persons, we suggest to use the key exchange method available for your keys.
-
-## Key Status
-
-<img src="status_signature_verified_cutout_24dp"/>
-Confirmed: You have already confirmed this key, e.g., by scanning the QR Code.
-<img src="status_signature_unverified_cutout_24dp"/>
-Unconfirmed: This key has not been confirmed yet. You cannot be sure if the key really corresponds to a specific person.
-<img src="status_signature_expired_cutout_24dp"/>
-Expired: This key is no longer valid. Only the owner can extend its validity.
-<img src="status_signature_revoked_cutout_24dp"/>
-Revoked: This key is no longer valid. It has been revoked by its owner.
-
-## Advanced Information
-A "key confirmation" in OpenKeychain is implemented by creating a certification according to the OpenPGP standard.
-This certification is a ["generic certification (0x10)"](http://tools.ietf.org/html/rfc4880#section-5.2.1) described in the standard by:
-"The issuer of this certification does not make any particular assertion as to how well the certifier has checked that the owner of the key is in fact the person described by the User ID."
-
-Traditionally, certifications (also with higher certification levels, such as "positive certifications" (0x13)) are organized in OpenPGP's Web of Trust.
-Our model of key confirmation is a much simpler concept to avoid common usability problems related to this Web of Trust.
-We assume that keys are verified only to a certain degree that is still usable enough to be executed "on the go".
-We also do not implement (potentially transitive) trust signatures or an ownertrust database like in GnuPG.
-Furthermore, keys which contain at least one user ID certified by a trusted key will be marked as "confirmed" in the key listings. \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-pt/help_changelog.md b/OpenKeychain/src/main/res/raw-pt/help_changelog.md
deleted file mode 100644
index 45ac104e0..000000000
--- a/OpenKeychain/src/main/res/raw-pt/help_changelog.md
+++ /dev/null
@@ -1,283 +0,0 @@
-[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
-
-## 3.4
-
- * Anonymous key download over Tor
- * Proxy support
- * Better YubiKey error handling
-
-## 3.3
-
- * New decryption screen
- * Decryption of multiple files at once
- * Better handling of YubiKey errors
-
-## 3.2
-
- * First version with full YubiKey support available from the user interface: Edit keys, bind YubiKey to keys,...
- * Material design
- * Integration of QR Code Scanning (New permissions required)
- * Improved key creation wizard
- * Fix missing contacts after sync
- * Requires Android 4
- * Redesigned key screen
- * Simplify crypto preferences, better selection of secure ciphers
- * API: Detached signatures, free selection of signing key,...
- * Fix: Some valid keys were shown revoked or expired
- * Don't accept signatures by expired or revoked subkeys
- * Keybase.io support in advanced view
- * Method to update all keys at once
-
-
-## 3.1.2
-
- * Fix key export to files (now for real)
-
-
-## 3.1.1
-
- * Fix key export to files (they were written partially)
- * Fix crash on Android 2.3
-
-
-## 3.1
-
- * Fix crash on Android 5
- * New certify screen
- * Secure Exchange directly from key list (SafeSlinger library)
- * New QR Code program flow
- * Redesigned decrypt screen
- * New icon usage and colors
- * Fix import of secret keys from Symantec Encryption Desktop
- * Experimental YubiKey support: Subkey IDs are now checked correctly
-
-
-## 3.0.1
-
- * Better handling of large key imports
- * Improved subkey selection
-
-
-## 3.0
-
- * Propose installable compatible apps in apps list
- * New design for decryption screens
- * Many fixes for key import, also fixes stripped keys
- * Honor and display key authenticate flags
- * User interface to generate custom keys
- * Fixing user id revocation certificates
- * New cloud search (searches over traditional keyservers and keybase.io)
- * Support for stripping keys inside OpenKeychain
- * Experimental YubiKey support: Support for signature generation and decryption
-
-
-## 2.9.2
-
- * Fix keys broken in 2.9.1
- * Experimental YubiKey support: Decryption now working via API
-
-
-## 2.9.1
-
- * Split encrypt screen into two
- * Fix key flags handling (now supporting Mailvelope 0.7 keys)
- * Improved passphrase handling
- * Key sharing via SafeSlinger
- * Experimental YubiKey support: Preference to allow other PINs, currently only signing via the OpenPGP API works, not inside of OpenKeychain
- * Fix usage of stripped keys
- * SHA256 as default for compatibility
- * Intent API has changed, see https://github.com/open-keychain/open-keychain/wiki/Intent-API
- * OpenPGP API now handles revoked/expired keys and returns all user ids
-
-
-## 2.9
-
- * Fixing crashes introduced in v2.8
- * Experimental ECC support
- * Experimental YubiKey support: Only signing with imported keys
-
-
-## 2.8
-
- * So many bugs have been fixed in this release that we focus on the main new features
- * Key edit: awesome new design, key revocation
- * Key import: awesome new design, secure keyserver connections via hkps, keyserver resolving via DNS SRV records
- * New first time screen
- * New key creation screen: autocompletion of name and email based on your personal Android accounts
- * File encryption: awesome new design, support for encrypting multiple files
- * New icons to show status of key (by Brennan Novak)
- * Important bug fix: Importing of large key collections from a file is now possible
- * Notification showing cached passphrases
- * Keys are connected to Android's contacts
-
-This release wouldn't be possible without the work of Vincent Breitmoser (GSoC 2014), mar-v-in (GSoC 2014), Daniel Albert, Art O Cathain, Daniel Haß, Tim Bray, Thialfihar
-
-## 2.7
-
- * Purple! (Dominik, Vincent)
- * New key view design (Dominik, Vincent)
- * New flat Android buttons (Dominik, Vincent)
- * API fixes (Dominik)
- * Keybase.io import (Tim Bray)
-
-
-## 2.6.1
-
- * Some fixes for regression bugs
-
-
-## 2.6
-
- * Key certifications (thanks to Vincent Breitmoser)
- * Support for GnuPG partial secret keys (thanks to Vincent Breitmoser)
- * New design for signature verification
- * Custom key length (thanks to Greg Witczak)
- * Fix share-functionality from other apps
-
-
-## 2.5
-
- * Fix decryption of symmetric OpenPGP messages/files
- * Refactored key edit screen (thanks to Ash Hughes)
- * New modern design for encrypt/decrypt screens
- * OpenPGP API version 3 (multiple api accounts, internal fixes, key lookup)
-
-
-## 2.4
-Thanks to all applicants of Google Summer of Code 2014 who made this release feature rich and bug free!
-Besides several small patches, a notable number of patches are made by the following people (in alphabetical order):
-Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Paul Sarbinowski, Sreeram Boyapati, Vincent Breitmoser.
-
- * New unified key list
- * Colorized key fingerprint
- * Support for keyserver ports
- * Deactivate possibility to generate weak keys
- * Much more internal work on the API
- * Certify user ids
- * Keyserver query based on machine-readable output
- * Lock navigation drawer on tablets
- * Suggestions for emails on creation of keys
- * Search in public key lists
- * And much more improvements and fixes…
-
-
-## 2.3.1
-
- * Hotfix for crash when upgrading from old versions
-
-
-## 2.3
-
- * Remove unnecessary export of public keys when exporting secret key (thanks to Ash Hughes)
- * Fix setting expiry dates on keys (thanks to Ash Hughes)
- * More internal fixes when editing keys (thanks to Ash Hughes)
- * Querying keyservers directly from the import screen
- * Fix layout and dialog style on Android 2.2-3.0
- * Fix crash on keys with empty user ids
- * Fix crash and empty lists when coming back from signing screen
- * Bouncy Castle (cryptography library) updated from 1.47 to 1.50 and build from source
- * Fix upload of key from signing screen
-
-
-## 2.2
-
- * New design with navigation drawer
- * New public key list design
- * New public key view
- * Bug fixes for importing of keys
- * Key cross-certification (thanks to Ash Hughes)
- * Handle UTF-8 passwords properly (thanks to Ash Hughes)
- * First version with new languages (thanks to the contributors on Transifex)
- * Sharing of keys via QR Codes fixed and improved
- * Package signature verification for API
-
-
-## 2.1.1
-
- * API Updates, preparation for K-9 Mail integration
-
-
-## 2.1
-
- * Lots of bug fixes
- * New API for developers
- * PRNG bug fix by Google
-
-
-## 2.0
-
- * Complete redesign
- * Share public keys via QR codes, NFC beam
- * Sign keys
- * Upload keys to server
- * Fixes import issues
- * New AIDL API
-
-
-## 1.0.8
-
- * Basic keyserver support
- * App2sd
- * More choices for passphrase cache: 1, 2, 4, 8, hours
- * Translations: Norwegian (thanks, Sander Danielsen), Chinese (thanks, Zhang Fredrick)
- * Bugfixes
- * Optimizations
-
-
-## 1.0.7
-
- * Fixed problem with signature verification of texts with trailing newline
- * More options for passphrase cache time to live (20, 40, 60 mins)
-
-
-## 1.0.6
-
- * Account adding crash on Froyo fixed
- * Secure file deletion
- * Option to delete key file after import
- * Stream encryption/decryption (gallery, etc.)
- * New options (language, force v3 signatures)
- * Interface changes
- * Bugfixes
-
-
-## 1.0.5
-
- * German and Italian translation
- * Much smaller package, due to reduced BC sources
- * New preferences GUI
- * Layout adjustment for localization
- * Signature bugfix
-
-
-## 1.0.4
-
- * Fixed another crash caused by some SDK bug with query builder
-
-
-## 1.0.3
-
- * Fixed crashes during encryption/signing and possibly key export
-
-
-## 1.0.2
-
- * Filterable key lists
- * Smarter pre-selection of encryption keys
- * New Intent handling for VIEW and SEND, allows files to be encrypted/decrypted out of file managers
- * Fixes and additional features (key preselection) for K-9 Mail, new beta build available
-
-
-## 1.0.1
-
- * GMail account listing was broken in 1.0.0, fixed again
-
-
-## 1.0.0
-
- * K-9 Mail integration, APG supporting beta build of K-9 Mail
- * Support of more file managers (including ASTRO)
- * Slovenian translation
- * New database, much faster, less memory usage
- * Defined Intents and content provider for other apps
- * Bugfixes \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-pt/help_start.md b/OpenKeychain/src/main/res/raw-pt/help_start.md
deleted file mode 100644
index 4cc331942..000000000
--- a/OpenKeychain/src/main/res/raw-pt/help_start.md
+++ /dev/null
@@ -1,16 +0,0 @@
-[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
-
-## How do I activate OpenKeychain in K-9 Mail?
-To use OpenKeychain with K-9 Mail, you want to follow these steps:
- 1. Open K-9 Mail and long-tap on the account you want to use OpenKeychain with.
- 2. Select "Account settings", scroll to the very bottom and click "Cryptography".
- 3. Click on "OpenPGP Provider" and select OpenKeychain from the list.
-
-## I found a bug in OpenKeychain!
-Please report the bug using the [issue tracker of OpenKeychain](https://github.com/openpgp-keychain/openpgp-keychain/issues).
-
-## Contribute
-If you want to help us developing OpenKeychain by contributing code [follow our small guide on Github](https://github.com/openpgp-keychain/openpgp-keychain#contribute-code).
-
-## Translations
-Help translating OpenKeychain! Everybody can participate at [OpenKeychain on Transifex](https://www.transifex.com/projects/p/open-keychain/). \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-ro/help_about.md b/OpenKeychain/src/main/res/raw-ro/help_about.md
deleted file mode 100644
index e80a2c766..000000000
--- a/OpenKeychain/src/main/res/raw-ro/help_about.md
+++ /dev/null
@@ -1,65 +0,0 @@
-[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
-
-[http://www.openkeychain.org](http://www.openkeychain.org)
-
-[OpenKeychain](http://www.openkeychain.org) is an OpenPGP implementation for Android.
-
-License: GPLv3+
-
-## Main Developers
- * Dominik Schürmann (Maintainer)
- * Vincent Breitmoser
-
-## Contributors
- * Adithya Abraham Philip
- * Art O Cathain
- * Ash Hughes
- * Brian C. Barnes
- * Bahtiar 'kalkin' Gadimov
- * Daniel Albert
- * Daniel Hammann
- * Daniel Haß
- * Daniel Nelz
- * Daniel Ramos
- * Greg Witczak
- * 'iseki'
- * Ishan Khanna
- * 'jellysheep'
- * 'Jesperbk'
- * 'jkolo'
- * Joey Castillo
- * Kai Jiang
- * Kartik Arora
- * 'Kent'
- * 'ligi'
- * Lukas Zorich
- * Manoj Khanna
- * 'mar-v-in'
- * Markus Doits
- * Miroojin Bakshi
- * Morgan Gangwere
- * Nikhil Peter Raj
- * Paul Sarbinowski
- * 'Senecaso'
- * Signe Rüsch
- * Sreeram Boyapati
- * 'steelman'
- * 'Thialfihar' (APG developer)
- * Tim Bray
-
-## Libraries
- * [SpongyCastle](http://rtyley.github.com/spongycastle/) (MIT X11 License)
- * [SafeSlinger Exchange library](https://github.com/SafeSlingerProject/exchange-android) (MIT License)
- * [Android Support Libraries](http://developer.android.com/tools/support-library/index.html) (Apache License v2)
- * [KeybaseLib](https://github.com/timbray/KeybaseLib) (Apache License v2)
- * [TokenAutoComplete](https://github.com/splitwise/TokenAutoComplete) (Apache License v2)
- * [MiniDNS](https://github.com/rtreffer/minidns) (Apache License v2)
- * [StickyListHeaders](https://github.com/emilsjolander/StickyListHeaders) (Apache License v2)
- * [ZXing](https://github.com/zxing/zxing) (Apache License v2)
- * [ZXing Android Minimal](https://github.com/journeyapps/zxing-android-embedded) (Apache License v2)
- * [PagerSlidingTabStrip](https://github.com/jpardogo/PagerSlidingTabStrip) (Material Design) (Apache License v2)
- * [MaterialDrawer](https://github.com/mikepenz/MaterialDrawer) (Apache License v2)
- * [Snackbar](https://github.com/nispok/snackbar) (MIT License)
- * [FloatingActionButton](https://github.com/futuresimple/android-floating-action-button) (Apache License v2)
- * [HtmlTextView](https://github.com/sufficientlysecure/html-textview) (Apache License v2)
- * [Markdown4J](https://github.com/jdcasey/markdown4j) (Apache License v2) \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-ro/help_certification.md b/OpenKeychain/src/main/res/raw-ro/help_certification.md
deleted file mode 100644
index 3518adf73..000000000
--- a/OpenKeychain/src/main/res/raw-ro/help_certification.md
+++ /dev/null
@@ -1,28 +0,0 @@
-[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
-
-## Key Confirmation
-Without confirmation, you cannot be sure if a key really corresponds to a specific person.
-The simplest way to confirm a key is by scanning the QR Code or exchanging it via NFC.
-To confirm keys between more than two persons, we suggest to use the key exchange method available for your keys.
-
-## Key Status
-
-<img src="status_signature_verified_cutout_24dp"/>
-Confirmed: You have already confirmed this key, e.g., by scanning the QR Code.
-<img src="status_signature_unverified_cutout_24dp"/>
-Unconfirmed: This key has not been confirmed yet. You cannot be sure if the key really corresponds to a specific person.
-<img src="status_signature_expired_cutout_24dp"/>
-Expired: This key is no longer valid. Only the owner can extend its validity.
-<img src="status_signature_revoked_cutout_24dp"/>
-Revoked: This key is no longer valid. It has been revoked by its owner.
-
-## Advanced Information
-A "key confirmation" in OpenKeychain is implemented by creating a certification according to the OpenPGP standard.
-This certification is a ["generic certification (0x10)"](http://tools.ietf.org/html/rfc4880#section-5.2.1) described in the standard by:
-"The issuer of this certification does not make any particular assertion as to how well the certifier has checked that the owner of the key is in fact the person described by the User ID."
-
-Traditionally, certifications (also with higher certification levels, such as "positive certifications" (0x13)) are organized in OpenPGP's Web of Trust.
-Our model of key confirmation is a much simpler concept to avoid common usability problems related to this Web of Trust.
-We assume that keys are verified only to a certain degree that is still usable enough to be executed "on the go".
-We also do not implement (potentially transitive) trust signatures or an ownertrust database like in GnuPG.
-Furthermore, keys which contain at least one user ID certified by a trusted key will be marked as "confirmed" in the key listings. \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-ro/help_changelog.md b/OpenKeychain/src/main/res/raw-ro/help_changelog.md
deleted file mode 100644
index 45ac104e0..000000000
--- a/OpenKeychain/src/main/res/raw-ro/help_changelog.md
+++ /dev/null
@@ -1,283 +0,0 @@
-[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
-
-## 3.4
-
- * Anonymous key download over Tor
- * Proxy support
- * Better YubiKey error handling
-
-## 3.3
-
- * New decryption screen
- * Decryption of multiple files at once
- * Better handling of YubiKey errors
-
-## 3.2
-
- * First version with full YubiKey support available from the user interface: Edit keys, bind YubiKey to keys,...
- * Material design
- * Integration of QR Code Scanning (New permissions required)
- * Improved key creation wizard
- * Fix missing contacts after sync
- * Requires Android 4
- * Redesigned key screen
- * Simplify crypto preferences, better selection of secure ciphers
- * API: Detached signatures, free selection of signing key,...
- * Fix: Some valid keys were shown revoked or expired
- * Don't accept signatures by expired or revoked subkeys
- * Keybase.io support in advanced view
- * Method to update all keys at once
-
-
-## 3.1.2
-
- * Fix key export to files (now for real)
-
-
-## 3.1.1
-
- * Fix key export to files (they were written partially)
- * Fix crash on Android 2.3
-
-
-## 3.1
-
- * Fix crash on Android 5
- * New certify screen
- * Secure Exchange directly from key list (SafeSlinger library)
- * New QR Code program flow
- * Redesigned decrypt screen
- * New icon usage and colors
- * Fix import of secret keys from Symantec Encryption Desktop
- * Experimental YubiKey support: Subkey IDs are now checked correctly
-
-
-## 3.0.1
-
- * Better handling of large key imports
- * Improved subkey selection
-
-
-## 3.0
-
- * Propose installable compatible apps in apps list
- * New design for decryption screens
- * Many fixes for key import, also fixes stripped keys
- * Honor and display key authenticate flags
- * User interface to generate custom keys
- * Fixing user id revocation certificates
- * New cloud search (searches over traditional keyservers and keybase.io)
- * Support for stripping keys inside OpenKeychain
- * Experimental YubiKey support: Support for signature generation and decryption
-
-
-## 2.9.2
-
- * Fix keys broken in 2.9.1
- * Experimental YubiKey support: Decryption now working via API
-
-
-## 2.9.1
-
- * Split encrypt screen into two
- * Fix key flags handling (now supporting Mailvelope 0.7 keys)
- * Improved passphrase handling
- * Key sharing via SafeSlinger
- * Experimental YubiKey support: Preference to allow other PINs, currently only signing via the OpenPGP API works, not inside of OpenKeychain
- * Fix usage of stripped keys
- * SHA256 as default for compatibility
- * Intent API has changed, see https://github.com/open-keychain/open-keychain/wiki/Intent-API
- * OpenPGP API now handles revoked/expired keys and returns all user ids
-
-
-## 2.9
-
- * Fixing crashes introduced in v2.8
- * Experimental ECC support
- * Experimental YubiKey support: Only signing with imported keys
-
-
-## 2.8
-
- * So many bugs have been fixed in this release that we focus on the main new features
- * Key edit: awesome new design, key revocation
- * Key import: awesome new design, secure keyserver connections via hkps, keyserver resolving via DNS SRV records
- * New first time screen
- * New key creation screen: autocompletion of name and email based on your personal Android accounts
- * File encryption: awesome new design, support for encrypting multiple files
- * New icons to show status of key (by Brennan Novak)
- * Important bug fix: Importing of large key collections from a file is now possible
- * Notification showing cached passphrases
- * Keys are connected to Android's contacts
-
-This release wouldn't be possible without the work of Vincent Breitmoser (GSoC 2014), mar-v-in (GSoC 2014), Daniel Albert, Art O Cathain, Daniel Haß, Tim Bray, Thialfihar
-
-## 2.7
-
- * Purple! (Dominik, Vincent)
- * New key view design (Dominik, Vincent)
- * New flat Android buttons (Dominik, Vincent)
- * API fixes (Dominik)
- * Keybase.io import (Tim Bray)
-
-
-## 2.6.1
-
- * Some fixes for regression bugs
-
-
-## 2.6
-
- * Key certifications (thanks to Vincent Breitmoser)
- * Support for GnuPG partial secret keys (thanks to Vincent Breitmoser)
- * New design for signature verification
- * Custom key length (thanks to Greg Witczak)
- * Fix share-functionality from other apps
-
-
-## 2.5
-
- * Fix decryption of symmetric OpenPGP messages/files
- * Refactored key edit screen (thanks to Ash Hughes)
- * New modern design for encrypt/decrypt screens
- * OpenPGP API version 3 (multiple api accounts, internal fixes, key lookup)
-
-
-## 2.4
-Thanks to all applicants of Google Summer of Code 2014 who made this release feature rich and bug free!
-Besides several small patches, a notable number of patches are made by the following people (in alphabetical order):
-Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Paul Sarbinowski, Sreeram Boyapati, Vincent Breitmoser.
-
- * New unified key list
- * Colorized key fingerprint
- * Support for keyserver ports
- * Deactivate possibility to generate weak keys
- * Much more internal work on the API
- * Certify user ids
- * Keyserver query based on machine-readable output
- * Lock navigation drawer on tablets
- * Suggestions for emails on creation of keys
- * Search in public key lists
- * And much more improvements and fixes…
-
-
-## 2.3.1
-
- * Hotfix for crash when upgrading from old versions
-
-
-## 2.3
-
- * Remove unnecessary export of public keys when exporting secret key (thanks to Ash Hughes)
- * Fix setting expiry dates on keys (thanks to Ash Hughes)
- * More internal fixes when editing keys (thanks to Ash Hughes)
- * Querying keyservers directly from the import screen
- * Fix layout and dialog style on Android 2.2-3.0
- * Fix crash on keys with empty user ids
- * Fix crash and empty lists when coming back from signing screen
- * Bouncy Castle (cryptography library) updated from 1.47 to 1.50 and build from source
- * Fix upload of key from signing screen
-
-
-## 2.2
-
- * New design with navigation drawer
- * New public key list design
- * New public key view
- * Bug fixes for importing of keys
- * Key cross-certification (thanks to Ash Hughes)
- * Handle UTF-8 passwords properly (thanks to Ash Hughes)
- * First version with new languages (thanks to the contributors on Transifex)
- * Sharing of keys via QR Codes fixed and improved
- * Package signature verification for API
-
-
-## 2.1.1
-
- * API Updates, preparation for K-9 Mail integration
-
-
-## 2.1
-
- * Lots of bug fixes
- * New API for developers
- * PRNG bug fix by Google
-
-
-## 2.0
-
- * Complete redesign
- * Share public keys via QR codes, NFC beam
- * Sign keys
- * Upload keys to server
- * Fixes import issues
- * New AIDL API
-
-
-## 1.0.8
-
- * Basic keyserver support
- * App2sd
- * More choices for passphrase cache: 1, 2, 4, 8, hours
- * Translations: Norwegian (thanks, Sander Danielsen), Chinese (thanks, Zhang Fredrick)
- * Bugfixes
- * Optimizations
-
-
-## 1.0.7
-
- * Fixed problem with signature verification of texts with trailing newline
- * More options for passphrase cache time to live (20, 40, 60 mins)
-
-
-## 1.0.6
-
- * Account adding crash on Froyo fixed
- * Secure file deletion
- * Option to delete key file after import
- * Stream encryption/decryption (gallery, etc.)
- * New options (language, force v3 signatures)
- * Interface changes
- * Bugfixes
-
-
-## 1.0.5
-
- * German and Italian translation
- * Much smaller package, due to reduced BC sources
- * New preferences GUI
- * Layout adjustment for localization
- * Signature bugfix
-
-
-## 1.0.4
-
- * Fixed another crash caused by some SDK bug with query builder
-
-
-## 1.0.3
-
- * Fixed crashes during encryption/signing and possibly key export
-
-
-## 1.0.2
-
- * Filterable key lists
- * Smarter pre-selection of encryption keys
- * New Intent handling for VIEW and SEND, allows files to be encrypted/decrypted out of file managers
- * Fixes and additional features (key preselection) for K-9 Mail, new beta build available
-
-
-## 1.0.1
-
- * GMail account listing was broken in 1.0.0, fixed again
-
-
-## 1.0.0
-
- * K-9 Mail integration, APG supporting beta build of K-9 Mail
- * Support of more file managers (including ASTRO)
- * Slovenian translation
- * New database, much faster, less memory usage
- * Defined Intents and content provider for other apps
- * Bugfixes \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-ro/help_start.md b/OpenKeychain/src/main/res/raw-ro/help_start.md
deleted file mode 100644
index 4cc331942..000000000
--- a/OpenKeychain/src/main/res/raw-ro/help_start.md
+++ /dev/null
@@ -1,16 +0,0 @@
-[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
-
-## How do I activate OpenKeychain in K-9 Mail?
-To use OpenKeychain with K-9 Mail, you want to follow these steps:
- 1. Open K-9 Mail and long-tap on the account you want to use OpenKeychain with.
- 2. Select "Account settings", scroll to the very bottom and click "Cryptography".
- 3. Click on "OpenPGP Provider" and select OpenKeychain from the list.
-
-## I found a bug in OpenKeychain!
-Please report the bug using the [issue tracker of OpenKeychain](https://github.com/openpgp-keychain/openpgp-keychain/issues).
-
-## Contribute
-If you want to help us developing OpenKeychain by contributing code [follow our small guide on Github](https://github.com/openpgp-keychain/openpgp-keychain#contribute-code).
-
-## Translations
-Help translating OpenKeychain! Everybody can participate at [OpenKeychain on Transifex](https://www.transifex.com/projects/p/open-keychain/). \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-ru/help_about.md b/OpenKeychain/src/main/res/raw-ru/help_about.md
index 63978e0e0..1243a5d14 100644
--- a/OpenKeychain/src/main/res/raw-ru/help_about.md
+++ b/OpenKeychain/src/main/res/raw-ru/help_about.md
@@ -6,14 +6,21 @@
Лицензия: GPLv3+
+[//]: # (NOTE: Alphabetic ordering)
+
## Ведущие разработчики
* Dominik Schürmann (Ведущий разработчик)
* Vincent Breitmoser
-## Участники
+## Top Contributors
* Adithya Abraham Philip
- * Art O Cathain
* Ash Hughes
+ * 'mar-v-in'
+ * 'Thialfihar' (разработчик APG)
+ * Tim Bray
+
+## Occasional Contributors
+ * Art O Cathain
* Brian C. Barnes
* Bahtiar 'kalkin' Gadimov
* Daniel Albert
@@ -34,7 +41,6 @@
* 'ligi'
* Lukas Zorich
* Manoj Khanna
- * 'mar-v-in'
* Markus Doits
* Miroojin Bakshi
* Morgan Gangwere
@@ -44,22 +50,23 @@
* Signe Rüsch
* Sreeram Boyapati
* 'steelman'
- * 'Thialfihar' (разработчик APG)
- * Tim Bray
+
+[//]: # (NOTE: Alphabetic ordering)
## Используемые библиотеки
- * [SpongyCastle](http://rtyley.github.com/spongycastle/) (MIT X11 License)
- * [SafeSlinger Exchange library](https://github.com/SafeSlingerProject/exchange-android) (MIT License)
* [Android Support Libraries](http://developer.android.com/tools/support-library/index.html) (Apache License v2)
+ * [FloatingActionButton](https://github.com/futuresimple/android-floating-action-button) (Apache License v2)
+ * [HtmlTextView](https://github.com/sufficientlysecure/html-textview) (Apache License v2)
* [KeybaseLib](https://github.com/timbray/KeybaseLib) (Apache License v2)
- * [TokenAutoComplete](https://github.com/splitwise/TokenAutoComplete) (Apache License v2)
+ * [Markdown4J](https://github.com/jdcasey/markdown4j) (Apache License v2)
+ * [MaterialDrawer](https://github.com/mikepenz/MaterialDrawer) (Apache License v2)
* [MiniDNS](https://github.com/rtreffer/minidns) (Apache License v2)
- * [StickyListHeaders](https://github.com/emilsjolander/StickyListHeaders) (Apache License v2)
- * [ZXing](https://github.com/zxing/zxing) (Apache License v2)
- * [ZXing Android Minimal](https://github.com/journeyapps/zxing-android-embedded) (Apache License v2)
+ * [OkHttp](http://square.github.io/okhttp/) (Apache License v2)
* [PagerSlidingTabStrip](https://github.com/jpardogo/PagerSlidingTabStrip) (Material Design) (Apache License v2)
- * [MaterialDrawer](https://github.com/mikepenz/MaterialDrawer) (Apache License v2)
+ * [SafeSlinger Exchange library](https://github.com/SafeSlingerProject/exchange-android) (MIT License)
* [Snackbar](https://github.com/nispok/snackbar) (MIT License)
- * [FloatingActionButton](https://github.com/futuresimple/android-floating-action-button) (Apache License v2)
- * [HtmlTextView](https://github.com/sufficientlysecure/html-textview) (Apache License v2)
- * [Markdown4J](https://github.com/jdcasey/markdown4j) (Apache License v2) \ No newline at end of file
+ * [SpongyCastle](http://rtyley.github.com/spongycastle/) (MIT X11 License)
+ * [StickyListHeaders](https://github.com/emilsjolander/StickyListHeaders) (Apache License v2)
+ * [TokenAutoComplete](https://github.com/splitwise/TokenAutoComplete) (Apache License v2)
+ * [ZXing](https://github.com/zxing/zxing) (Apache License v2)
+ * [ZXing Android Minimal](https://github.com/journeyapps/zxing-android-embedded) (Apache License v2) \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-ru/help_certification.md b/OpenKeychain/src/main/res/raw-ru/help_certification.md
index 06ef290f6..787588b05 100644
--- a/OpenKeychain/src/main/res/raw-ru/help_certification.md
+++ b/OpenKeychain/src/main/res/raw-ru/help_certification.md
@@ -2,7 +2,7 @@
## Подтверждение ключей
Без подтверждения Вы не можете быть уверены, что ключ принадлежит определенному человеку.
-Простейший способ подтвердить - отсканировать QR код или получить ключ через NFC.
+Простейший способ подтвердить ключ — отсканировать QR-код или получить его через NFC.
Для подтверждения ключей более чем двух человек, мы рекомендуем использовать один из доступных методов обмена ключами.
## Статус ключей
diff --git a/OpenKeychain/src/main/res/raw-ru/help_changelog.md b/OpenKeychain/src/main/res/raw-ru/help_changelog.md
index 45ac104e0..11d7975b1 100644
--- a/OpenKeychain/src/main/res/raw-ru/help_changelog.md
+++ b/OpenKeychain/src/main/res/raw-ru/help_changelog.md
@@ -1,5 +1,12 @@
[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
+## 3.5
+
+ * Key revocation on key deletion
+ * Improved checks for insecure cryptography
+ * Fix: Don't close OpenKeychain after first time wizard succeeds
+ * API: Version 8
+
## 3.4
* Anonymous key download over Tor
diff --git a/OpenKeychain/src/main/res/raw-ru/help_start.md b/OpenKeychain/src/main/res/raw-ru/help_start.md
index 9f40e679c..d883f21ec 100644
--- a/OpenKeychain/src/main/res/raw-ru/help_start.md
+++ b/OpenKeychain/src/main/res/raw-ru/help_start.md
@@ -2,8 +2,8 @@
## Как мне активировать OpenKeychain в K-9 Mail?
Для использования OpenKeychain с K-9 Mail, необходимо выполнить следующие шаги:
- 1. Открыть K-9 Mail и долгим нажатием выбрать учетную запись с которой будет использоваться OpenKeychain.
- 2. Выбрать "Настойки учетной записи" и опуститься в самый конец меню до пункта "Шифрование".
+ 1. Открыть K-9 Mail и долгим нажатием выбрать учетную запись с которой будет использоваться OpenKeychain.
+ 2. Выбрать "Настройки учетной записи" и опуститься в самый конец меню до пункта "Шифрование".
3. Нажать на "OpenPGP Provider" и выбрать OpenKeychain из списка.
## Я нашел ошибку в OpenKeychain!
diff --git a/OpenKeychain/src/main/res/raw-sl/help_about.md b/OpenKeychain/src/main/res/raw-sl/help_about.md
index f3319c2dd..3fe72beef 100644
--- a/OpenKeychain/src/main/res/raw-sl/help_about.md
+++ b/OpenKeychain/src/main/res/raw-sl/help_about.md
@@ -6,14 +6,21 @@
Licenca: GPLv3+
+[//]: # (NOTE: Alphabetic ordering)
+
## Main Developers
* Dominik Schürmann (Skrbnik)
* Vincent Breitmoser
-## Contributors
+## Top Contributors
* Adithya Abraham Philip
- * Art O Cathain
* Ash Hughes
+ * 'mar-v-in'
+ * 'Thialfihar' (APG developer)
+ * Tim Bray
+
+## Occasional Contributors
+ * Art O Cathain
* Brian C. Barnes
* Bahtiar 'kalkin' Gadimov
* Daniel Albert
@@ -34,7 +41,6 @@ Licenca: GPLv3+
* 'ligi'
* Lukas Zorich
* Manoj Khanna
- * 'mar-v-in'
* Markus Doits
* Miroojin Bakshi
* Morgan Gangwere
@@ -44,22 +50,23 @@ Licenca: GPLv3+
* Signe Rüsch
* Sreeram Boyapati
* 'steelman'
- * 'Thialfihar' (APG developer)
- * Tim Bray
+
+[//]: # (NOTE: Alphabetic ordering)
## Knjižnice
- * [SpongyCastle](http://rtyley.github.com/spongycastle/) (Licenca MIT X11)
- * [SafeSlinger Exchange library](https://github.com/SafeSlingerProject/exchange-android) (Licenca MIT)
* [Android Support Libraries](http://developer.android.com/tools/support-library/index.html) (Licenca Apache v2)
+ * [FloatingActionButton](https://github.com/futuresimple/android-floating-action-button) (Licenca Apache v2)
+ * [HtmlTextView](https://github.com/sufficientlysecure/html-textview) (Apache License v2)
* [KeybaseLib](https://github.com/timbray/KeybaseLib) (Licenca Apache v2)
- * [TokenAutoComplete](https://github.com/splitwise/TokenAutoComplete) (Licenca Apache v2)
+ * [Markdown4J](https://github.com/jdcasey/markdown4j) (Licenca Apache v2)
+ * [MaterialDrawer](https://github.com/mikepenz/MaterialDrawer) (Apache License v2)
* [MiniDNS](https://github.com/rtreffer/minidns) (Licenca Apache v2)
- * [StickyListHeaders](https://github.com/emilsjolander/StickyListHeaders) (Licenca Apache v2)
- * [ZXing](https://github.com/zxing/zxing) (Licenca Apache v2)
- * [ZXing Android Minimal](https://github.com/journeyapps/zxing-android-embedded) (Licenca Apache v2)
+ * [OkHttp](http://square.github.io/okhttp/) (Apache License v2)
* [PagerSlidingTabStrip](https://github.com/jpardogo/PagerSlidingTabStrip) (Material Design) (Apache License v2)
- * [MaterialDrawer](https://github.com/mikepenz/MaterialDrawer) (Apache License v2)
+ * [SafeSlinger Exchange library](https://github.com/SafeSlingerProject/exchange-android) (Licenca MIT)
* [Snackbar](https://github.com/nispok/snackbar) (Licenca MIT)
- * [FloatingActionButton](https://github.com/futuresimple/android-floating-action-button) (Licenca Apache v2)
- * [HtmlTextView](https://github.com/sufficientlysecure/html-textview) (Apache License v2)
- * [Markdown4J](https://github.com/jdcasey/markdown4j) (Licenca Apache v2) \ No newline at end of file
+ * [SpongyCastle](http://rtyley.github.com/spongycastle/) (Licenca MIT X11)
+ * [StickyListHeaders](https://github.com/emilsjolander/StickyListHeaders) (Licenca Apache v2)
+ * [TokenAutoComplete](https://github.com/splitwise/TokenAutoComplete) (Licenca Apache v2)
+ * [ZXing](https://github.com/zxing/zxing) (Licenca Apache v2)
+ * [ZXing Android Minimal](https://github.com/journeyapps/zxing-android-embedded) (Licenca Apache v2) \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-sl/help_changelog.md b/OpenKeychain/src/main/res/raw-sl/help_changelog.md
index 45ac104e0..11d7975b1 100644
--- a/OpenKeychain/src/main/res/raw-sl/help_changelog.md
+++ b/OpenKeychain/src/main/res/raw-sl/help_changelog.md
@@ -1,5 +1,12 @@
[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
+## 3.5
+
+ * Key revocation on key deletion
+ * Improved checks for insecure cryptography
+ * Fix: Don't close OpenKeychain after first time wizard succeeds
+ * API: Version 8
+
## 3.4
* Anonymous key download over Tor
diff --git a/OpenKeychain/src/main/res/raw-sr/help_about.md b/OpenKeychain/src/main/res/raw-sr/help_about.md
index d4b6ba700..5bfbbc6ff 100644
--- a/OpenKeychain/src/main/res/raw-sr/help_about.md
+++ b/OpenKeychain/src/main/res/raw-sr/help_about.md
@@ -6,14 +6,21 @@
Лиценца: ГПЛв3+
+[//]:
+
## Главни програмери
* Доминик Ширман (Dominik Schürmann, одржавалац)
* Винсент Брајтмозер (Vincent Breitmoser)
-## Доприносиоци
+## Главни доприносиоци
* Adithya Abraham Philip
- * Арт Окатаин (Art O Cathain)
* Еш Хјуџис (Ash Hughes)
+ * „mar-v-in“
+ * „Thialfihar“ (АПГ програмер)
+ * Tim Bray
+
+## Повремени доприносиоци
+ * Арт Окатаин (Art O Cathain)
* Брајан Ц. Барнс (Brian C. Barnes)
* Бахтјар „kalkin“ Гадимов (Bahtiar Gadimov)
* Данијел Алберт (Daniel Albert)
@@ -34,7 +41,6 @@
* „ligi“
* Лукас Зорић (Lukas Zorich)
* Маноџ Кана (Manoj Khanna)
- * „mar-v-in“
* Маркус Доитс (Markus Doits)
* Мироџин Бакши (Miroojin Bakshi)
* Морган Гангвер (Morgan Gangwere)
@@ -44,22 +50,23 @@
* Signe Rüsch
* Sreeram Boyapati
* „steelman“
- * „Thialfihar“ (АПГ програмер)
- * Tim Bray
+
+[//]:
## Библиотеке
- * [SpongyCastle](http://rtyley.github.com/spongycastle/) (МИТ Икс11 лиценца)
- * [SafeSlinger Exchange library](https://github.com/SafeSlingerProject/exchange-android) (МИТ лиценца)
* [Андроидове библиотеке подршке](http://developer.android.com/tools/support-library/index.html) (Апачи лиценца в2)
+ * [FloatingActionButton](https://github.com/futuresimple/android-floating-action-button) (Апачи лиценца в2)
+ * [HtmlTextView](https://github.com/sufficientlysecure/html-textview) (Апачи лиценца в2)
* [KeybaseLib](https://github.com/timbray/KeybaseLib) (Апачи лиценца в2)
- * [TokenAutoComplete](https://github.com/splitwise/TokenAutoComplete) (Апачи лиценца в2)
+ * [Markdown4J](https://github.com/jdcasey/markdown4j) (Апачи лиценца в2)
+ * [MaterialDrawer](https://github.com/mikepenz/MaterialDrawer) (Апачи лиценца в2)
* [MiniDNS](https://github.com/rtreffer/minidns) (Апачи лиценца в2)
- * [StickyListHeaders](https://github.com/emilsjolander/StickyListHeaders) (Апачи лиценца в2)
- * [ZXing](https://github.com/zxing/zxing) (Апачи лиценца в2)
- * [ZXing Android Minimal](https://github.com/journeyapps/zxing-android-embedded) (Апачи лиценца в2)
+ * [OkHttp](http://square.github.io/okhttp/) (Apache License v2)
* [PagerSlidingTabStrip](https://github.com/jpardogo/PagerSlidingTabStrip) (Материјал дизајн) (Апачи лиценца в2)
- * [MaterialDrawer](https://github.com/mikepenz/MaterialDrawer) (Апачи лиценца в2)
+ * [SafeSlinger Exchange library](https://github.com/SafeSlingerProject/exchange-android) (МИТ лиценца)
* [Snackbar](https://github.com/nispok/snackbar) (МИТ лиценца)
- * [FloatingActionButton](https://github.com/futuresimple/android-floating-action-button) (Апачи лиценца в2)
- * [HtmlTextView](https://github.com/sufficientlysecure/html-textview) (Апачи лиценца в2)
- * [Markdown4J](https://github.com/jdcasey/markdown4j) (Апачи лиценца в2) \ No newline at end of file
+ * [SpongyCastle](http://rtyley.github.com/spongycastle/) (МИТ Икс11 лиценца)
+ * [StickyListHeaders](https://github.com/emilsjolander/StickyListHeaders) (Апачи лиценца в2)
+ * [TokenAutoComplete](https://github.com/splitwise/TokenAutoComplete) (Апачи лиценца в2)
+ * [ZXing](https://github.com/zxing/zxing) (Апачи лиценца в2)
+ * [ZXing Android Minimal](https://github.com/journeyapps/zxing-android-embedded) (Апачи лиценца в2) \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-sr/help_certification.md b/OpenKeychain/src/main/res/raw-sr/help_certification.md
index 2d5da8230..2456ee374 100644
--- a/OpenKeychain/src/main/res/raw-sr/help_certification.md
+++ b/OpenKeychain/src/main/res/raw-sr/help_certification.md
@@ -19,10 +19,10 @@
## Напредни подаци
„Потврда кључа“ у Отвореном кључарнику се реализује прављењем сертификације по ОпенПГП стандарду.
Ова сертификација је [„општа сертификација (0x10)“](http://tools.ietf.org/html/rfc4880#section-5.2.1) описана у стандарду:
-"The issuer of this certification does not make any particular assertion as to how well the certifier has checked that the owner of the key is in fact the person described by the User ID."
+„Издавач ове сертификације не наводи посебно са којом сигурношћу је сертификатор утврдио да је власник кључа у ствари особа описана корисничким ИД-ом.“
-Traditionally, certifications (also with higher certification levels, such as "positive certifications" (0x13)) are organized in OpenPGP's Web of Trust.
-Our model of key confirmation is a much simpler concept to avoid common usability problems related to this Web of Trust.
-We assume that keys are verified only to a certain degree that is still usable enough to be executed "on the go".
-We also do not implement (potentially transitive) trust signatures or an ownertrust database like in GnuPG.
-Furthermore, keys which contain at least one user ID certified by a trusted key will be marked as "confirmed" in the key listings. \ No newline at end of file
+Традиционално, сертификације (такође оне са вишим нивоима овере, као нпр. „позитивне сертификације“ (0x13)) су организоване у ОпенПГП-овом Вебу поверења.
+Наш модел потврде кључа је много једноставнији концепт да би се избегли уобичајени проблеми са коришћењем везаним за овај Веб поверења.
+Ми претпостављамо да су кључеви потврђени само до одређеног степена, довољно употребљивог за коришћење „у покрету“.
+Такође не имплементирамо (потенцијално прелазне) потписе поверења или базу података поузданих власника као у ГнуПГ-у.
+Штавише, кључеви који садрже бар један кориснички ИД потврђен поузданим кључем биће означен као „потврђен“ на списку кључева. \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-sr/help_changelog.md b/OpenKeychain/src/main/res/raw-sr/help_changelog.md
index 3fe45259b..680664a6d 100644
--- a/OpenKeychain/src/main/res/raw-sr/help_changelog.md
+++ b/OpenKeychain/src/main/res/raw-sr/help_changelog.md
@@ -1,10 +1,17 @@
[//]: #
+## 3.5
+
+ * Опозив кључа при брисању кључа
+ * Побољшане провере за небезбедну криптографију
+ * Поправка: не затварај Отворени кључарник након успеха чаробњака за прво покретање
+ * АПИ: издање 8
+
## 3.4
- * Anonymous key download over Tor
- * Proxy support
- * Better YubiKey error handling
+ * Анонимна преузимања кључева преко Тора
+ * Подршка за прокси
+ * Боље руковање грешкама Јубикључа
## 3.3
diff --git a/OpenKeychain/src/main/res/raw-sv/help_about.md b/OpenKeychain/src/main/res/raw-sv/help_about.md
index 32426e26e..0fd4713bb 100644
--- a/OpenKeychain/src/main/res/raw-sv/help_about.md
+++ b/OpenKeychain/src/main/res/raw-sv/help_about.md
@@ -6,14 +6,21 @@
Licens: GPLv3+
+[//]: # (NOTE: Alphabetic ordering)
+
## Huvudsakliga utvecklare
* Dominik Schürmann (Projektledare)
* Vincent Breitmoser
-## Medarbetare
+## Top Contributors
* Adithya Abraham Philip
- * Art O Cathain
* Ash Hughes
+ * 'mar-v-in'
+ * 'Thialfihar' (APG-utvecklare)
+ * Tim Bray
+
+## Occasional Contributors
+ * Art O Cathain
* Brian C. Barnes
* Bahtiar 'kalkin' Gadimov
* Daniel Albert
@@ -34,7 +41,6 @@ Licens: GPLv3+
* 'ligi'
* Lukas Zorich
* Manoj Khanna
- * 'mar-v-in'
* Markus Doits
* Miroojin Bakshi
* Morgan Gangwere
@@ -44,22 +50,23 @@ Licens: GPLv3+
* Signe Rüsch
* Sreeram Boyapati
* 'steelman'
- * 'Thialfihar' (APG-utvecklare)
- * Tim Bray
+
+[//]: # (NOTE: Alphabetic ordering)
## Biblioteken
- * [SpongyCastle](http://rtyley.github.com/spongycastle/) (MIT X11-licens)
- * [SafeSlinger's bibliotek för utbyte](https://github.com/SafeSlingerProject/exchange-android) (MIT-licens)
* [Android Support Libraries](http://developer.android.com/tools/support-library/index.html) (Apache License v2)
+ * [FloatingActionButton](https://github.com/futuresimple/android-floating-action-button) (Apache License v2)
+ * [HtmlTextView](https://github.com/sufficientlysecure/html-textview) (Apache License v2)
* [KeybaseLib](https://github.com/timbray/KeybaseLib) (Apache License v2)
- * [TokenAutoComplete](https://github.com/splitwise/TokenAutoComplete) (Apache License v2)
+ * [Markdown4J](https://github.com/jdcasey/markdown4j) (Apache License v2)
+ * [MaterialDrawer](https://github.com/mikepenz/MaterialDrawer) (Apache License v2)
* [MiniDNS](https://github.com/rtreffer/minidns) (Apache License v2)
- * [StickyListHeaders](https://github.com/emilsjolander/StickyListHeaders) (Apache License v2)
- * [ZXing](https://github.com/zxing/zxing) (Apache License v2)
- * [ZXing Android Minimal](https://github.com/journeyapps/zxing-android-embedded) (Apache License v2)
+ * [OkHttp](http://square.github.io/okhttp/) (Apache License v2)
* [PagerSlidingTabStrip](https://github.com/jpardogo/PagerSlidingTabStrip) (Material Design) (Apache License v2)
- * [MaterialDrawer](https://github.com/mikepenz/MaterialDrawer) (Apache License v2)
+ * [SafeSlinger's bibliotek för utbyte](https://github.com/SafeSlingerProject/exchange-android) (MIT-licens)
* [Snackbar](https://github.com/nispok/snackbar) (MIT License)
- * [FloatingActionButton](https://github.com/futuresimple/android-floating-action-button) (Apache License v2)
- * [HtmlTextView](https://github.com/sufficientlysecure/html-textview) (Apache License v2)
- * [Markdown4J](https://github.com/jdcasey/markdown4j) (Apache License v2) \ No newline at end of file
+ * [SpongyCastle](http://rtyley.github.com/spongycastle/) (MIT X11-licens)
+ * [StickyListHeaders](https://github.com/emilsjolander/StickyListHeaders) (Apache License v2)
+ * [TokenAutoComplete](https://github.com/splitwise/TokenAutoComplete) (Apache License v2)
+ * [ZXing](https://github.com/zxing/zxing) (Apache License v2)
+ * [ZXing Android Minimal](https://github.com/journeyapps/zxing-android-embedded) (Apache License v2) \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-sv/help_changelog.md b/OpenKeychain/src/main/res/raw-sv/help_changelog.md
index 83e4a8e06..2bec6c216 100644
--- a/OpenKeychain/src/main/res/raw-sv/help_changelog.md
+++ b/OpenKeychain/src/main/res/raw-sv/help_changelog.md
@@ -1,5 +1,12 @@
[//]: # (NOTERING: Var vänlig och sätt varje mening på sin egen rad, Transifex sätter varje rad i sitt eget fält för översättningar!)
+## 3.5
+
+ * Key revocation on key deletion
+ * Improved checks for insecure cryptography
+ * Fix: Don't close OpenKeychain after first time wizard succeeds
+ * API: Version 8
+
## 3.4
* Anonymous key download over Tor
diff --git a/OpenKeychain/src/main/res/raw-tr/help_about.md b/OpenKeychain/src/main/res/raw-tr/help_about.md
index e80a2c766..06bed0021 100644
--- a/OpenKeychain/src/main/res/raw-tr/help_about.md
+++ b/OpenKeychain/src/main/res/raw-tr/help_about.md
@@ -6,14 +6,21 @@
License: GPLv3+
+[//]: # (NOTE: Alphabetic ordering)
+
## Main Developers
* Dominik Schürmann (Maintainer)
* Vincent Breitmoser
-## Contributors
+## Top Contributors
* Adithya Abraham Philip
- * Art O Cathain
* Ash Hughes
+ * 'mar-v-in'
+ * 'Thialfihar' (APG developer)
+ * Tim Bray
+
+## Occasional Contributors
+ * Art O Cathain
* Brian C. Barnes
* Bahtiar 'kalkin' Gadimov
* Daniel Albert
@@ -34,7 +41,6 @@ License: GPLv3+
* 'ligi'
* Lukas Zorich
* Manoj Khanna
- * 'mar-v-in'
* Markus Doits
* Miroojin Bakshi
* Morgan Gangwere
@@ -44,22 +50,23 @@ License: GPLv3+
* Signe Rüsch
* Sreeram Boyapati
* 'steelman'
- * 'Thialfihar' (APG developer)
- * Tim Bray
+
+[//]: # (NOTE: Alphabetic ordering)
## Libraries
- * [SpongyCastle](http://rtyley.github.com/spongycastle/) (MIT X11 License)
- * [SafeSlinger Exchange library](https://github.com/SafeSlingerProject/exchange-android) (MIT License)
* [Android Support Libraries](http://developer.android.com/tools/support-library/index.html) (Apache License v2)
+ * [FloatingActionButton](https://github.com/futuresimple/android-floating-action-button) (Apache License v2)
+ * [HtmlTextView](https://github.com/sufficientlysecure/html-textview) (Apache License v2)
* [KeybaseLib](https://github.com/timbray/KeybaseLib) (Apache License v2)
- * [TokenAutoComplete](https://github.com/splitwise/TokenAutoComplete) (Apache License v2)
+ * [Markdown4J](https://github.com/jdcasey/markdown4j) (Apache License v2)
+ * [MaterialDrawer](https://github.com/mikepenz/MaterialDrawer) (Apache License v2)
* [MiniDNS](https://github.com/rtreffer/minidns) (Apache License v2)
- * [StickyListHeaders](https://github.com/emilsjolander/StickyListHeaders) (Apache License v2)
- * [ZXing](https://github.com/zxing/zxing) (Apache License v2)
- * [ZXing Android Minimal](https://github.com/journeyapps/zxing-android-embedded) (Apache License v2)
+ * [OkHttp](http://square.github.io/okhttp/) (Apache License v2)
* [PagerSlidingTabStrip](https://github.com/jpardogo/PagerSlidingTabStrip) (Material Design) (Apache License v2)
- * [MaterialDrawer](https://github.com/mikepenz/MaterialDrawer) (Apache License v2)
+ * [SafeSlinger Exchange library](https://github.com/SafeSlingerProject/exchange-android) (MIT License)
* [Snackbar](https://github.com/nispok/snackbar) (MIT License)
- * [FloatingActionButton](https://github.com/futuresimple/android-floating-action-button) (Apache License v2)
- * [HtmlTextView](https://github.com/sufficientlysecure/html-textview) (Apache License v2)
- * [Markdown4J](https://github.com/jdcasey/markdown4j) (Apache License v2) \ No newline at end of file
+ * [SpongyCastle](http://rtyley.github.com/spongycastle/) (MIT X11 License)
+ * [StickyListHeaders](https://github.com/emilsjolander/StickyListHeaders) (Apache License v2)
+ * [TokenAutoComplete](https://github.com/splitwise/TokenAutoComplete) (Apache License v2)
+ * [ZXing](https://github.com/zxing/zxing) (Apache License v2)
+ * [ZXing Android Minimal](https://github.com/journeyapps/zxing-android-embedded) (Apache License v2) \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-tr/help_changelog.md b/OpenKeychain/src/main/res/raw-tr/help_changelog.md
index 45ac104e0..11d7975b1 100644
--- a/OpenKeychain/src/main/res/raw-tr/help_changelog.md
+++ b/OpenKeychain/src/main/res/raw-tr/help_changelog.md
@@ -1,5 +1,12 @@
[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
+## 3.5
+
+ * Key revocation on key deletion
+ * Improved checks for insecure cryptography
+ * Fix: Don't close OpenKeychain after first time wizard succeeds
+ * API: Version 8
+
## 3.4
* Anonymous key download over Tor
diff --git a/OpenKeychain/src/main/res/raw-uk/help_about.md b/OpenKeychain/src/main/res/raw-uk/help_about.md
index e80a2c766..06bed0021 100644
--- a/OpenKeychain/src/main/res/raw-uk/help_about.md
+++ b/OpenKeychain/src/main/res/raw-uk/help_about.md
@@ -6,14 +6,21 @@
License: GPLv3+
+[//]: # (NOTE: Alphabetic ordering)
+
## Main Developers
* Dominik Schürmann (Maintainer)
* Vincent Breitmoser
-## Contributors
+## Top Contributors
* Adithya Abraham Philip
- * Art O Cathain
* Ash Hughes
+ * 'mar-v-in'
+ * 'Thialfihar' (APG developer)
+ * Tim Bray
+
+## Occasional Contributors
+ * Art O Cathain
* Brian C. Barnes
* Bahtiar 'kalkin' Gadimov
* Daniel Albert
@@ -34,7 +41,6 @@ License: GPLv3+
* 'ligi'
* Lukas Zorich
* Manoj Khanna
- * 'mar-v-in'
* Markus Doits
* Miroojin Bakshi
* Morgan Gangwere
@@ -44,22 +50,23 @@ License: GPLv3+
* Signe Rüsch
* Sreeram Boyapati
* 'steelman'
- * 'Thialfihar' (APG developer)
- * Tim Bray
+
+[//]: # (NOTE: Alphabetic ordering)
## Libraries
- * [SpongyCastle](http://rtyley.github.com/spongycastle/) (MIT X11 License)
- * [SafeSlinger Exchange library](https://github.com/SafeSlingerProject/exchange-android) (MIT License)
* [Android Support Libraries](http://developer.android.com/tools/support-library/index.html) (Apache License v2)
+ * [FloatingActionButton](https://github.com/futuresimple/android-floating-action-button) (Apache License v2)
+ * [HtmlTextView](https://github.com/sufficientlysecure/html-textview) (Apache License v2)
* [KeybaseLib](https://github.com/timbray/KeybaseLib) (Apache License v2)
- * [TokenAutoComplete](https://github.com/splitwise/TokenAutoComplete) (Apache License v2)
+ * [Markdown4J](https://github.com/jdcasey/markdown4j) (Apache License v2)
+ * [MaterialDrawer](https://github.com/mikepenz/MaterialDrawer) (Apache License v2)
* [MiniDNS](https://github.com/rtreffer/minidns) (Apache License v2)
- * [StickyListHeaders](https://github.com/emilsjolander/StickyListHeaders) (Apache License v2)
- * [ZXing](https://github.com/zxing/zxing) (Apache License v2)
- * [ZXing Android Minimal](https://github.com/journeyapps/zxing-android-embedded) (Apache License v2)
+ * [OkHttp](http://square.github.io/okhttp/) (Apache License v2)
* [PagerSlidingTabStrip](https://github.com/jpardogo/PagerSlidingTabStrip) (Material Design) (Apache License v2)
- * [MaterialDrawer](https://github.com/mikepenz/MaterialDrawer) (Apache License v2)
+ * [SafeSlinger Exchange library](https://github.com/SafeSlingerProject/exchange-android) (MIT License)
* [Snackbar](https://github.com/nispok/snackbar) (MIT License)
- * [FloatingActionButton](https://github.com/futuresimple/android-floating-action-button) (Apache License v2)
- * [HtmlTextView](https://github.com/sufficientlysecure/html-textview) (Apache License v2)
- * [Markdown4J](https://github.com/jdcasey/markdown4j) (Apache License v2) \ No newline at end of file
+ * [SpongyCastle](http://rtyley.github.com/spongycastle/) (MIT X11 License)
+ * [StickyListHeaders](https://github.com/emilsjolander/StickyListHeaders) (Apache License v2)
+ * [TokenAutoComplete](https://github.com/splitwise/TokenAutoComplete) (Apache License v2)
+ * [ZXing](https://github.com/zxing/zxing) (Apache License v2)
+ * [ZXing Android Minimal](https://github.com/journeyapps/zxing-android-embedded) (Apache License v2) \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-uk/help_changelog.md b/OpenKeychain/src/main/res/raw-uk/help_changelog.md
index 45ac104e0..11d7975b1 100644
--- a/OpenKeychain/src/main/res/raw-uk/help_changelog.md
+++ b/OpenKeychain/src/main/res/raw-uk/help_changelog.md
@@ -1,5 +1,12 @@
[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
+## 3.5
+
+ * Key revocation on key deletion
+ * Improved checks for insecure cryptography
+ * Fix: Don't close OpenKeychain after first time wizard succeeds
+ * API: Version 8
+
## 3.4
* Anonymous key download over Tor
diff --git a/OpenKeychain/src/main/res/raw-vi/help_about.md b/OpenKeychain/src/main/res/raw-vi/help_about.md
deleted file mode 100644
index e80a2c766..000000000
--- a/OpenKeychain/src/main/res/raw-vi/help_about.md
+++ /dev/null
@@ -1,65 +0,0 @@
-[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
-
-[http://www.openkeychain.org](http://www.openkeychain.org)
-
-[OpenKeychain](http://www.openkeychain.org) is an OpenPGP implementation for Android.
-
-License: GPLv3+
-
-## Main Developers
- * Dominik Schürmann (Maintainer)
- * Vincent Breitmoser
-
-## Contributors
- * Adithya Abraham Philip
- * Art O Cathain
- * Ash Hughes
- * Brian C. Barnes
- * Bahtiar 'kalkin' Gadimov
- * Daniel Albert
- * Daniel Hammann
- * Daniel Haß
- * Daniel Nelz
- * Daniel Ramos
- * Greg Witczak
- * 'iseki'
- * Ishan Khanna
- * 'jellysheep'
- * 'Jesperbk'
- * 'jkolo'
- * Joey Castillo
- * Kai Jiang
- * Kartik Arora
- * 'Kent'
- * 'ligi'
- * Lukas Zorich
- * Manoj Khanna
- * 'mar-v-in'
- * Markus Doits
- * Miroojin Bakshi
- * Morgan Gangwere
- * Nikhil Peter Raj
- * Paul Sarbinowski
- * 'Senecaso'
- * Signe Rüsch
- * Sreeram Boyapati
- * 'steelman'
- * 'Thialfihar' (APG developer)
- * Tim Bray
-
-## Libraries
- * [SpongyCastle](http://rtyley.github.com/spongycastle/) (MIT X11 License)
- * [SafeSlinger Exchange library](https://github.com/SafeSlingerProject/exchange-android) (MIT License)
- * [Android Support Libraries](http://developer.android.com/tools/support-library/index.html) (Apache License v2)
- * [KeybaseLib](https://github.com/timbray/KeybaseLib) (Apache License v2)
- * [TokenAutoComplete](https://github.com/splitwise/TokenAutoComplete) (Apache License v2)
- * [MiniDNS](https://github.com/rtreffer/minidns) (Apache License v2)
- * [StickyListHeaders](https://github.com/emilsjolander/StickyListHeaders) (Apache License v2)
- * [ZXing](https://github.com/zxing/zxing) (Apache License v2)
- * [ZXing Android Minimal](https://github.com/journeyapps/zxing-android-embedded) (Apache License v2)
- * [PagerSlidingTabStrip](https://github.com/jpardogo/PagerSlidingTabStrip) (Material Design) (Apache License v2)
- * [MaterialDrawer](https://github.com/mikepenz/MaterialDrawer) (Apache License v2)
- * [Snackbar](https://github.com/nispok/snackbar) (MIT License)
- * [FloatingActionButton](https://github.com/futuresimple/android-floating-action-button) (Apache License v2)
- * [HtmlTextView](https://github.com/sufficientlysecure/html-textview) (Apache License v2)
- * [Markdown4J](https://github.com/jdcasey/markdown4j) (Apache License v2) \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-vi/help_certification.md b/OpenKeychain/src/main/res/raw-vi/help_certification.md
deleted file mode 100644
index 3518adf73..000000000
--- a/OpenKeychain/src/main/res/raw-vi/help_certification.md
+++ /dev/null
@@ -1,28 +0,0 @@
-[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
-
-## Key Confirmation
-Without confirmation, you cannot be sure if a key really corresponds to a specific person.
-The simplest way to confirm a key is by scanning the QR Code or exchanging it via NFC.
-To confirm keys between more than two persons, we suggest to use the key exchange method available for your keys.
-
-## Key Status
-
-<img src="status_signature_verified_cutout_24dp"/>
-Confirmed: You have already confirmed this key, e.g., by scanning the QR Code.
-<img src="status_signature_unverified_cutout_24dp"/>
-Unconfirmed: This key has not been confirmed yet. You cannot be sure if the key really corresponds to a specific person.
-<img src="status_signature_expired_cutout_24dp"/>
-Expired: This key is no longer valid. Only the owner can extend its validity.
-<img src="status_signature_revoked_cutout_24dp"/>
-Revoked: This key is no longer valid. It has been revoked by its owner.
-
-## Advanced Information
-A "key confirmation" in OpenKeychain is implemented by creating a certification according to the OpenPGP standard.
-This certification is a ["generic certification (0x10)"](http://tools.ietf.org/html/rfc4880#section-5.2.1) described in the standard by:
-"The issuer of this certification does not make any particular assertion as to how well the certifier has checked that the owner of the key is in fact the person described by the User ID."
-
-Traditionally, certifications (also with higher certification levels, such as "positive certifications" (0x13)) are organized in OpenPGP's Web of Trust.
-Our model of key confirmation is a much simpler concept to avoid common usability problems related to this Web of Trust.
-We assume that keys are verified only to a certain degree that is still usable enough to be executed "on the go".
-We also do not implement (potentially transitive) trust signatures or an ownertrust database like in GnuPG.
-Furthermore, keys which contain at least one user ID certified by a trusted key will be marked as "confirmed" in the key listings. \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-vi/help_changelog.md b/OpenKeychain/src/main/res/raw-vi/help_changelog.md
deleted file mode 100644
index 45ac104e0..000000000
--- a/OpenKeychain/src/main/res/raw-vi/help_changelog.md
+++ /dev/null
@@ -1,283 +0,0 @@
-[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
-
-## 3.4
-
- * Anonymous key download over Tor
- * Proxy support
- * Better YubiKey error handling
-
-## 3.3
-
- * New decryption screen
- * Decryption of multiple files at once
- * Better handling of YubiKey errors
-
-## 3.2
-
- * First version with full YubiKey support available from the user interface: Edit keys, bind YubiKey to keys,...
- * Material design
- * Integration of QR Code Scanning (New permissions required)
- * Improved key creation wizard
- * Fix missing contacts after sync
- * Requires Android 4
- * Redesigned key screen
- * Simplify crypto preferences, better selection of secure ciphers
- * API: Detached signatures, free selection of signing key,...
- * Fix: Some valid keys were shown revoked or expired
- * Don't accept signatures by expired or revoked subkeys
- * Keybase.io support in advanced view
- * Method to update all keys at once
-
-
-## 3.1.2
-
- * Fix key export to files (now for real)
-
-
-## 3.1.1
-
- * Fix key export to files (they were written partially)
- * Fix crash on Android 2.3
-
-
-## 3.1
-
- * Fix crash on Android 5
- * New certify screen
- * Secure Exchange directly from key list (SafeSlinger library)
- * New QR Code program flow
- * Redesigned decrypt screen
- * New icon usage and colors
- * Fix import of secret keys from Symantec Encryption Desktop
- * Experimental YubiKey support: Subkey IDs are now checked correctly
-
-
-## 3.0.1
-
- * Better handling of large key imports
- * Improved subkey selection
-
-
-## 3.0
-
- * Propose installable compatible apps in apps list
- * New design for decryption screens
- * Many fixes for key import, also fixes stripped keys
- * Honor and display key authenticate flags
- * User interface to generate custom keys
- * Fixing user id revocation certificates
- * New cloud search (searches over traditional keyservers and keybase.io)
- * Support for stripping keys inside OpenKeychain
- * Experimental YubiKey support: Support for signature generation and decryption
-
-
-## 2.9.2
-
- * Fix keys broken in 2.9.1
- * Experimental YubiKey support: Decryption now working via API
-
-
-## 2.9.1
-
- * Split encrypt screen into two
- * Fix key flags handling (now supporting Mailvelope 0.7 keys)
- * Improved passphrase handling
- * Key sharing via SafeSlinger
- * Experimental YubiKey support: Preference to allow other PINs, currently only signing via the OpenPGP API works, not inside of OpenKeychain
- * Fix usage of stripped keys
- * SHA256 as default for compatibility
- * Intent API has changed, see https://github.com/open-keychain/open-keychain/wiki/Intent-API
- * OpenPGP API now handles revoked/expired keys and returns all user ids
-
-
-## 2.9
-
- * Fixing crashes introduced in v2.8
- * Experimental ECC support
- * Experimental YubiKey support: Only signing with imported keys
-
-
-## 2.8
-
- * So many bugs have been fixed in this release that we focus on the main new features
- * Key edit: awesome new design, key revocation
- * Key import: awesome new design, secure keyserver connections via hkps, keyserver resolving via DNS SRV records
- * New first time screen
- * New key creation screen: autocompletion of name and email based on your personal Android accounts
- * File encryption: awesome new design, support for encrypting multiple files
- * New icons to show status of key (by Brennan Novak)
- * Important bug fix: Importing of large key collections from a file is now possible
- * Notification showing cached passphrases
- * Keys are connected to Android's contacts
-
-This release wouldn't be possible without the work of Vincent Breitmoser (GSoC 2014), mar-v-in (GSoC 2014), Daniel Albert, Art O Cathain, Daniel Haß, Tim Bray, Thialfihar
-
-## 2.7
-
- * Purple! (Dominik, Vincent)
- * New key view design (Dominik, Vincent)
- * New flat Android buttons (Dominik, Vincent)
- * API fixes (Dominik)
- * Keybase.io import (Tim Bray)
-
-
-## 2.6.1
-
- * Some fixes for regression bugs
-
-
-## 2.6
-
- * Key certifications (thanks to Vincent Breitmoser)
- * Support for GnuPG partial secret keys (thanks to Vincent Breitmoser)
- * New design for signature verification
- * Custom key length (thanks to Greg Witczak)
- * Fix share-functionality from other apps
-
-
-## 2.5
-
- * Fix decryption of symmetric OpenPGP messages/files
- * Refactored key edit screen (thanks to Ash Hughes)
- * New modern design for encrypt/decrypt screens
- * OpenPGP API version 3 (multiple api accounts, internal fixes, key lookup)
-
-
-## 2.4
-Thanks to all applicants of Google Summer of Code 2014 who made this release feature rich and bug free!
-Besides several small patches, a notable number of patches are made by the following people (in alphabetical order):
-Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Paul Sarbinowski, Sreeram Boyapati, Vincent Breitmoser.
-
- * New unified key list
- * Colorized key fingerprint
- * Support for keyserver ports
- * Deactivate possibility to generate weak keys
- * Much more internal work on the API
- * Certify user ids
- * Keyserver query based on machine-readable output
- * Lock navigation drawer on tablets
- * Suggestions for emails on creation of keys
- * Search in public key lists
- * And much more improvements and fixes…
-
-
-## 2.3.1
-
- * Hotfix for crash when upgrading from old versions
-
-
-## 2.3
-
- * Remove unnecessary export of public keys when exporting secret key (thanks to Ash Hughes)
- * Fix setting expiry dates on keys (thanks to Ash Hughes)
- * More internal fixes when editing keys (thanks to Ash Hughes)
- * Querying keyservers directly from the import screen
- * Fix layout and dialog style on Android 2.2-3.0
- * Fix crash on keys with empty user ids
- * Fix crash and empty lists when coming back from signing screen
- * Bouncy Castle (cryptography library) updated from 1.47 to 1.50 and build from source
- * Fix upload of key from signing screen
-
-
-## 2.2
-
- * New design with navigation drawer
- * New public key list design
- * New public key view
- * Bug fixes for importing of keys
- * Key cross-certification (thanks to Ash Hughes)
- * Handle UTF-8 passwords properly (thanks to Ash Hughes)
- * First version with new languages (thanks to the contributors on Transifex)
- * Sharing of keys via QR Codes fixed and improved
- * Package signature verification for API
-
-
-## 2.1.1
-
- * API Updates, preparation for K-9 Mail integration
-
-
-## 2.1
-
- * Lots of bug fixes
- * New API for developers
- * PRNG bug fix by Google
-
-
-## 2.0
-
- * Complete redesign
- * Share public keys via QR codes, NFC beam
- * Sign keys
- * Upload keys to server
- * Fixes import issues
- * New AIDL API
-
-
-## 1.0.8
-
- * Basic keyserver support
- * App2sd
- * More choices for passphrase cache: 1, 2, 4, 8, hours
- * Translations: Norwegian (thanks, Sander Danielsen), Chinese (thanks, Zhang Fredrick)
- * Bugfixes
- * Optimizations
-
-
-## 1.0.7
-
- * Fixed problem with signature verification of texts with trailing newline
- * More options for passphrase cache time to live (20, 40, 60 mins)
-
-
-## 1.0.6
-
- * Account adding crash on Froyo fixed
- * Secure file deletion
- * Option to delete key file after import
- * Stream encryption/decryption (gallery, etc.)
- * New options (language, force v3 signatures)
- * Interface changes
- * Bugfixes
-
-
-## 1.0.5
-
- * German and Italian translation
- * Much smaller package, due to reduced BC sources
- * New preferences GUI
- * Layout adjustment for localization
- * Signature bugfix
-
-
-## 1.0.4
-
- * Fixed another crash caused by some SDK bug with query builder
-
-
-## 1.0.3
-
- * Fixed crashes during encryption/signing and possibly key export
-
-
-## 1.0.2
-
- * Filterable key lists
- * Smarter pre-selection of encryption keys
- * New Intent handling for VIEW and SEND, allows files to be encrypted/decrypted out of file managers
- * Fixes and additional features (key preselection) for K-9 Mail, new beta build available
-
-
-## 1.0.1
-
- * GMail account listing was broken in 1.0.0, fixed again
-
-
-## 1.0.0
-
- * K-9 Mail integration, APG supporting beta build of K-9 Mail
- * Support of more file managers (including ASTRO)
- * Slovenian translation
- * New database, much faster, less memory usage
- * Defined Intents and content provider for other apps
- * Bugfixes \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-vi/help_start.md b/OpenKeychain/src/main/res/raw-vi/help_start.md
deleted file mode 100644
index 4cc331942..000000000
--- a/OpenKeychain/src/main/res/raw-vi/help_start.md
+++ /dev/null
@@ -1,16 +0,0 @@
-[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
-
-## How do I activate OpenKeychain in K-9 Mail?
-To use OpenKeychain with K-9 Mail, you want to follow these steps:
- 1. Open K-9 Mail and long-tap on the account you want to use OpenKeychain with.
- 2. Select "Account settings", scroll to the very bottom and click "Cryptography".
- 3. Click on "OpenPGP Provider" and select OpenKeychain from the list.
-
-## I found a bug in OpenKeychain!
-Please report the bug using the [issue tracker of OpenKeychain](https://github.com/openpgp-keychain/openpgp-keychain/issues).
-
-## Contribute
-If you want to help us developing OpenKeychain by contributing code [follow our small guide on Github](https://github.com/openpgp-keychain/openpgp-keychain#contribute-code).
-
-## Translations
-Help translating OpenKeychain! Everybody can participate at [OpenKeychain on Transifex](https://www.transifex.com/projects/p/open-keychain/). \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-zh-rTW/help_about.md b/OpenKeychain/src/main/res/raw-zh-rTW/help_about.md
index 4e3a03b4b..ed32e0d5d 100644
--- a/OpenKeychain/src/main/res/raw-zh-rTW/help_about.md
+++ b/OpenKeychain/src/main/res/raw-zh-rTW/help_about.md
@@ -6,14 +6,21 @@
授權:GPLv3+
+[//]: # (備註: 字母順序排序)
+
##主要開發者
* Dominik Schürmann (維護人)
* Vincent Breitmoser
-##貢獻者
+主要開發者
* Adithya Abraham Philip
- * Art O Cathain
* Ash Hughes
+ * 'mar-v-in'
+ * 'Thialfihar' (APG開發者)
+ * Tim Bray
+
+##不固定的貢獻者
+ * Art O Cathain
* Brian C. Barnes
* Bahtiar 'kalkin' Gadimov
* Daniel Albert
@@ -34,7 +41,6 @@
* 'ligi'
* Lukas Zorich
* Manoj Khanna
- * 'mar-v-in'
* Markus Doits
* Miroojin Bakshi
* Morgan Gangwere
@@ -44,22 +50,23 @@
* Signe Rüsch
* Sreeram Boyapati
* 'steelman'
- * 'Thialfihar' (APG開發者)
- * Tim Bray
+
+[//]: # (備註: 字母順序排序)
##函式庫
- * [SpongyCastle](http://rtyley.github.com/spongycastle/) (MIT X11 License)
- * [SafeSlinger Exchange library](https://github.com/SafeSlingerProject/exchange-android) (MIT License)
* [Android Support Libraries](http://developer.android.com/tools/support-library/index.html) (Apache License v2)
+ * [FloatingActionButton](https://github.com/futuresimple/android-floating-action-button) (Apache License v2)
+ * [HtmlTextView](https://github.com/sufficientlysecure/html-textview) (Apache License v2)
* [KeybaseLib](https://github.com/timbray/KeybaseLib) (Apache License v2)
- * [TokenAutoComplete](https://github.com/splitwise/TokenAutoComplete) (Apache License v2)
+ * [Markdown4J](https://github.com/jdcasey/markdown4j) (Apache License v2)
+ * [MaterialDrawer](https://github.com/mikepenz/MaterialDrawer) (Apache License v2)
* [MiniDNS](https://github.com/rtreffer/minidns) (Apache License v2)
- * [StickyListHeaders](https://github.com/emilsjolander/StickyListHeaders) (Apache License v2)
- * [ZXing](https://github.com/zxing/zxing) (Apache License v2)
- * [ZXing Android Minimal](https://github.com/journeyapps/zxing-android-embedded) (Apache License v2)
+ * [OkHttp](http://square.github.io/okhttp/) (Apache License v2)
* [PagerSlidingTabStrip](https://github.com/jpardogo/PagerSlidingTabStrip) (Material Design) (Apache License v2)
- * [MaterialDrawer](https://github.com/mikepenz/MaterialDrawer) (Apache License v2)
+ * [SafeSlinger Exchange library](https://github.com/SafeSlingerProject/exchange-android) (MIT License)
* [Snackbar](https://github.com/nispok/snackbar) (MIT License)
- * [FloatingActionButton](https://github.com/futuresimple/android-floating-action-button) (Apache License v2)
- * [HtmlTextView](https://github.com/sufficientlysecure/html-textview) (Apache License v2)
- * [Markdown4J](https://github.com/jdcasey/markdown4j) (Apache License v2) \ No newline at end of file
+ * [SpongyCastle](http://rtyley.github.com/spongycastle/) (MIT X11 License)
+ * [StickyListHeaders](https://github.com/emilsjolander/StickyListHeaders) (Apache License v2)
+ * [TokenAutoComplete](https://github.com/splitwise/TokenAutoComplete) (Apache License v2)
+ * [ZXing](https://github.com/zxing/zxing) (Apache License v2)
+ * [ZXing Android Minimal](https://github.com/journeyapps/zxing-android-embedded) (Apache License v2) \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-zh-rTW/help_changelog.md b/OpenKeychain/src/main/res/raw-zh-rTW/help_changelog.md
index ad9be42be..20f2ef6c5 100644
--- a/OpenKeychain/src/main/res/raw-zh-rTW/help_changelog.md
+++ b/OpenKeychain/src/main/res/raw-zh-rTW/help_changelog.md
@@ -1,15 +1,22 @@
[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
+## 3.5
+
+ *可以在刪除金鑰時撤銷金鑰
+ *改進對加密安全性進行檢查
+ *修正:在OpenKeychain第一次執行精靈成功後不自動關閉程式
+ * API: Version 8
+
## 3.4
* Anonymous key download over Tor
- * Proxy support
+ *支援代理伺服器
* Better YubiKey error handling
## 3.3
- * New decryption screen
- * Decryption of multiple files at once
+ *新的解密畫面
+ *可同時解密多個檔案
* Better handling of YubiKey errors
## 3.2
diff --git a/OpenKeychain/src/main/res/raw-zh/help_about.md b/OpenKeychain/src/main/res/raw-zh/help_about.md
index d7f61d16c..d8bc20016 100644
--- a/OpenKeychain/src/main/res/raw-zh/help_about.md
+++ b/OpenKeychain/src/main/res/raw-zh/help_about.md
@@ -6,14 +6,21 @@
许可协议:GPLv3+
+[//]: # (NOTE: Alphabetic ordering)
+
## 主要开发者
* Dominik Schürmann (维护者)
* Vincent Breitmoser
-## 贡献者
+## Top Contributors
* Adithya Abraham Philip
- * Art O Cathain
* Ash Hughes
+ * 'mar-v-in'
+ * 'Thialfihar' (APG 开发者)
+ * Tim Bray
+
+## Occasional Contributors
+ * Art O Cathain
* Brian C. Barnes
* Bahtiar 'kalkin' Gadimov
* Daniel Albert
@@ -34,7 +41,6 @@
* 'ligi'
* Lukas Zorich
* Manoj Khanna
- * 'mar-v-in'
* Markus Doits
* Miroojin Bakshi
* Morgan Gangwere
@@ -44,22 +50,23 @@
* Signe Rüsch
* Sreeram Boyapati
* 'steelman'
- * 'Thialfihar' (APG 开发者)
- * Tim Bray
+
+[//]: # (NOTE: Alphabetic ordering)
## 库
- * [SpongyCastle](http://rtyley.github.com/spongycastle/) (MIT X11 许可证)
- * [SafeSlinger Exchange library](https://github.com/SafeSlingerProject/exchange-android) (MIT 许可证)
[Android Support Libraries](http://developer.android.com/tools/support-library/index.html) (Apache 许可证 v2)
+ * [FloatingActionButton](https://github.com/futuresimple/android-floating-action-button) (Apache 许可证 v2)
+ * [HtmlTextView](https://github.com/sufficientlysecure/html-textview) (Apache 许可证 v2)
* [KeybaseLib](https://github.com/timbray/KeybaseLib) (Apache 许可证 v2)
- * [TokenAutoComplete](https://github.com/splitwise/TokenAutoComplete) (Apache 许可证 v2)
+ * [Markdown4J](https://github.com/jdcasey/markdown4j) (Apache 许可证 v2)
+ * [MaterialDrawer](https://github.com/mikepenz/MaterialDrawer) (Apache 许可证 v2)
* [MiniDNS](https://github.com/rtreffer/minidns) (Apache 许可证 v2)
+ * [OkHttp](http://square.github.io/okhttp/) (Apache License v2)
+ * [PagerSlidingTabStrip](https://github.com/jpardogo/PagerSlidingTabStrip) (Material Design)</a> (Apache 许可证 v2)
+ * [SafeSlinger Exchange library](https://github.com/SafeSlingerProject/exchange-android) (MIT 许可证)
+ * [Snackbar](https://github.com/nispok/snackbar) (MIT 许可证)
+ * [SpongyCastle](http://rtyley.github.com/spongycastle/) (MIT X11 许可证)
* [StickyListHeaders](https://github.com/emilsjolander/StickyListHeaders) (Apache 许可证 v2)
+ * [TokenAutoComplete](https://github.com/splitwise/TokenAutoComplete) (Apache 许可证 v2)
* [ZXing](https://github.com/zxing/zxing) (Apache 许可证 v2)
- * [ZXing Android Minimal](https://github.com/journeyapps/zxing-android-embedded) (Apache 许可证 v2)
- * [PagerSlidingTabStrip](https://github.com/jpardogo/PagerSlidingTabStrip) (Material Design) (Apache License v2)
- * [MaterialDrawer](https://github.com/mikepenz/MaterialDrawer) (Apache 许可证 v2)
- * [Snackbar](https://github.com/nispok/snackbar) (MIT 许可证)
- * [FloatingActionButton](https://github.com/futuresimple/android-floating-action-button) (Apache 许可证 v2)
- * [HtmlTextView](https://github.com/sufficientlysecure/html-textview) (Apache 许可证 v2)
- * [Markdown4J](https://github.com/jdcasey/markdown4j) (Apache 许可证 v2) \ No newline at end of file
+ * [ZXing Android Minimal](https://github.com/journeyapps/zxing-android-embedded) (Apache 许可证 v2) \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/raw-zh/help_changelog.md b/OpenKeychain/src/main/res/raw-zh/help_changelog.md
index 45ac104e0..11d7975b1 100644
--- a/OpenKeychain/src/main/res/raw-zh/help_changelog.md
+++ b/OpenKeychain/src/main/res/raw-zh/help_changelog.md
@@ -1,5 +1,12 @@
[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
+## 3.5
+
+ * Key revocation on key deletion
+ * Improved checks for insecure cryptography
+ * Fix: Don't close OpenKeychain after first time wizard succeeds
+ * API: Version 8
+
## 3.4
* Anonymous key download over Tor
diff --git a/OpenKeychain/src/main/res/raw/help_about.md b/OpenKeychain/src/main/res/raw/help_about.md
index 93bcaad34..45d326daa 100644
--- a/OpenKeychain/src/main/res/raw/help_about.md
+++ b/OpenKeychain/src/main/res/raw/help_about.md
@@ -6,14 +6,21 @@
License: GPLv3+
+[//]: # (NOTE: Alphabetic ordering)
+
## Main Developers
* Dominik Schürmann (Maintainer)
* Vincent Breitmoser
-## Contributors
+## Top Contributors
* Adithya Abraham Philip
- * Art O Cathain
* Ash Hughes
+ * 'mar-v-in'
+ * 'Thialfihar' (APG developer)
+ * Tim Bray
+
+## Occasional Contributors
+ * Art O Cathain
* Brian C. Barnes
* Bahtiar 'kalkin' Gadimov
* Daniel Albert
@@ -34,7 +41,6 @@ License: GPLv3+
* 'ligi'
* Lukas Zorich
* Manoj Khanna
- * 'mar-v-in'
* Markus Doits
* Miroojin Bakshi
* Morgan Gangwere
@@ -44,22 +50,23 @@ License: GPLv3+
* Signe Rüsch
* Sreeram Boyapati
* 'steelman'
- * 'Thialfihar' (APG developer)
- * Tim Bray
+
+[//]: # (NOTE: Alphabetic ordering)
## Libraries
- * [SpongyCastle](http://rtyley.github.com/spongycastle/) (MIT X11 License)
- * [SafeSlinger Exchange library](https://github.com/SafeSlingerProject/exchange-android) (MIT License)
* [Android Support Libraries](http://developer.android.com/tools/support-library/index.html) (Apache License v2)
+ * [FloatingActionButton](https://github.com/futuresimple/android-floating-action-button) (Apache License v2)
+ * [HtmlTextView](https://github.com/sufficientlysecure/html-textview) (Apache License v2)
* [KeybaseLib](https://github.com/timbray/KeybaseLib) (Apache License v2)
- * [TokenAutoComplete](https://github.com/splitwise/TokenAutoComplete) (Apache License v2)
+ * [Markdown4J](https://github.com/jdcasey/markdown4j) (Apache License v2)
+ * [MaterialDrawer](https://github.com/mikepenz/MaterialDrawer) (Apache License v2)
* [MiniDNS](https://github.com/rtreffer/minidns) (Apache License v2)
+ * [OkHttp](http://square.github.io/okhttp/) (Apache License v2)
+ * [PagerSlidingTabStrip](https://github.com/jpardogo/PagerSlidingTabStrip) (Material Design) (Apache License v2)
+ * [SafeSlinger Exchange library](https://github.com/SafeSlingerProject/exchange-android) (MIT License)
+ * [Snackbar](https://github.com/nispok/snackbar) (MIT License)
+ * [SpongyCastle](http://rtyley.github.com/spongycastle/) (MIT X11 License)
* [StickyListHeaders](https://github.com/emilsjolander/StickyListHeaders) (Apache License v2)
+ * [TokenAutoComplete](https://github.com/splitwise/TokenAutoComplete) (Apache License v2)
* [ZXing](https://github.com/zxing/zxing) (Apache License v2)
* [ZXing Android Minimal](https://github.com/journeyapps/zxing-android-embedded) (Apache License v2)
- * [PagerSlidingTabStrip](https://github.com/jpardogo/PagerSlidingTabStrip) (Material Design) (Apache License v2)
- * [MaterialDrawer](https://github.com/mikepenz/MaterialDrawer) (Apache License v2)
- * [Snackbar](https://github.com/nispok/snackbar) (MIT License)
- * [FloatingActionButton](https://github.com/futuresimple/android-floating-action-button) (Apache License v2)
- * [HtmlTextView](https://github.com/sufficientlysecure/html-textview) (Apache License v2)
- * [Markdown4J](https://github.com/jdcasey/markdown4j) (Apache License v2)
diff --git a/OpenKeychain/src/main/res/raw/help_changelog.md b/OpenKeychain/src/main/res/raw/help_changelog.md
index df61f3472..d35d52500 100644
--- a/OpenKeychain/src/main/res/raw/help_changelog.md
+++ b/OpenKeychain/src/main/res/raw/help_changelog.md
@@ -1,5 +1,12 @@
[//]: # (NOTE: Please put every sentence in its own line, Transifex puts every line in its own translation field!)
+## 3.5
+
+ * Key revocation on key deletion
+ * Improved checks for insecure cryptography
+ * Fix: Don't close OpenKeychain after first time wizard succeeds
+ * API: Version 8
+
## 3.4
* Anonymous key download over Tor
diff --git a/OpenKeychain/src/main/res/transition/linked_id_card_trans.xml b/OpenKeychain/src/main/res/transition/linked_id_card_trans.xml
new file mode 100644
index 000000000..8d6e75cee
--- /dev/null
+++ b/OpenKeychain/src/main/res/transition/linked_id_card_trans.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
+ <changeBounds />
+</transitionSet> \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/values-bg/strings.xml b/OpenKeychain/src/main/res/values-bg/strings.xml
deleted file mode 100644
index 0713e39ad..000000000
--- a/OpenKeychain/src/main/res/values-bg/strings.xml
+++ /dev/null
@@ -1,78 +0,0 @@
-<?xml version='1.0' encoding='UTF-8'?>
-<resources>
- <!--GENERAL: Please put all strings inside quotes as described in example 1 on
- http://developer.android.com/guide/topics/resources/string-resource.html (scroll down to "Escaping apostrophes and quotes").-->
- <!--title-->
- <!--section-->
- <!--button-->
- <!--menu-->
- <!--label-->
- <!--Proxy Preferences-->
- <!--proxy type choices and values-->
- <!--OrbotHelper strings-->
- <!--InstallDialogFragment strings-->
- <!--StartOrbotDialogFragment strings-->
- <!--choice-->
- <!--key flags-->
- <!--sentences-->
- <!--errors
- no punctuation, all lowercase,
- they will be put after "error_message", e.g. "Error: file not found"-->
- <!--errors without preceeding Error:-->
- <!--results shown after decryption/verification-->
- <!--Add keys-->
- <!--progress dialogs, usually ending in '…'-->
- <!--action strings-->
- <!--key bit length selections-->
- <!--elliptic curve names-->
- <!--not in for now, see SaveKeyringParcel
- <string name="key_curve_bp_p256">"Brainpool P-256"</string>
- <string name="key_curve_bp_p384">"Brainpool P-384"</string>
- <string name="key_curve_bp_p512">"Brainpool P-512"</string>-->
- <!--compression-->
- <!--Help-->
- <!--Import-->
- <!--Import from URL-->
- <!--Generic result toast-->
- <!--Import result toast-->
- <!--Delete result toast-->
- <!--Certify result toast-->
- <!--Intent labels-->
- <!--Remote API-->
- <!--Share-->
- <!--Key list-->
- <!--Key view-->
- <!--Key trust-->
- <!--keybase proof stuff-->
- <!--Edit key-->
- <!--Create key-->
- <!--View key-->
- <!--Add/Edit keyserver-->
- <!--Navigation Drawer-->
- <!--hints-->
- <!--certs-->
- <!--LogType log messages. Errors should have _ERROR_ in their name and end with a !-->
- <!--Import Public log entries-->
- <!--Import Secret log entries-->
- <!--Keyring Canonicalization log entries-->
- <!--Keyring merging log entries-->
- <!--createSecretKeyRing-->
- <!--modifySecretKeyRing-->
- <!--Consolidate-->
- <!--Edit Key (higher level than modify)-->
- <!--Promote key-->
- <!--Other messages used in OperationLogs-->
- <!--Messages for DecryptVerify operation-->
- <!--Messages for VerifySignedLiteralData operation-->
- <!--Messages for SignEncrypt operation-->
- <!--Messages for PgpSignEncrypt operation-->
- <!--Messages for Keybase Verification operation-->
- <!--Messages for Export Log operation-->
- <!--PassphraseCache-->
- <!--First Time-->
- <!--unsorted-->
- <!--Passphrase wizard-->
- <!--TODO: rename all the things!-->
- <!--<string name="enter_passphrase_twice">Enter password twice</string>-->
- <!--<string name="nfc_text">Please place a NFC tag near your device</string>-->
-</resources>
diff --git a/OpenKeychain/src/main/res/values-cs/strings.xml b/OpenKeychain/src/main/res/values-cs/strings.xml
index 4b367a5b3..6b6bc956b 100644
--- a/OpenKeychain/src/main/res/values-cs/strings.xml
+++ b/OpenKeychain/src/main/res/values-cs/strings.xml
@@ -20,8 +20,6 @@
<string name="title_encrypt_to_file">Zašifrovat do souboru</string>
<string name="title_decrypt_to_file">Rozšifrovat do souboru</string>
<string name="title_import_keys">Importovat klíče</string>
- <string name="title_export_key">Exportovat klíče</string>
- <string name="title_export_keys">Exportovat klíče</string>
<string name="title_key_not_found">Klíč nebyl nalezen</string>
<string name="title_send_key">Nahrát na keyserver</string>
<string name="title_certify_key">Potvrdit klíč</string>
@@ -80,7 +78,6 @@
<!--menu-->
<string name="menu_preferences">Nastavení</string>
<string name="menu_help">Nápověda</string>
- <string name="menu_export_key">Exportovat do souboru</string>
<string name="menu_delete_key">Smazat klíč</string>
<string name="menu_manage_keys">Spravovat klíče</string>
<string name="menu_search">Hledat</string>
@@ -144,6 +141,7 @@
<string name="pref_keyserver_summary">Vyhledat klíče na vybraném OpenPGP keyserveru (protokol HKP)</string>
<string name="pref_keybase">keybase.io</string>
<string name="pref_keybase_summary">Hledat klíče na keybase.io</string>
+ <!--label shown in Android settings under the OpenKeychain account-->
<!--Proxy Preferences-->
<!--proxy type choices and values-->
<!--OrbotHelper strings-->
@@ -206,7 +204,6 @@
<string name="select_encryption_key">Vyberte alespoň jeden šifrovací klíč.</string>
<string name="specify_file_to_encrypt_to">Prosím specifikujte do kterého souboru zašifrovat.\nVAROVÁNÍ: Pokud soubor již existuje, bude přepsán.</string>
<string name="specify_file_to_decrypt_to">Prosím specifikujte do kterého souboru rozšifrovat.\nVAROVÁNÍ: Pokud soubor již existuje, bude přepsán.</string>
- <string name="specify_backup_dest">Prosím specifikujte do kterého souboru exportovat.\nVAROVÁNÍ: Pokud soubor již existuje, bude přepsán.</string>
<string name="key_deletion_confirmation_multi">Opravdu chcete smazat všechny vybrané soubory?</string>
<string name="secret_key_deletion_confirmation">Po smazání již nebudete schopni přečíst zprávy zašifrované tímto klíčem a stratíte všechny potvrzení udělané tímto klíčem!</string>
<string name="public_key_deletetion_confirmation">Smazat klíč \'%s\'?</string>
@@ -373,6 +370,7 @@
<!--Delete result toast-->
<string name="delete_nothing">Nic ke smazání.</string>
<string name="delete_cancelled">Operace smazání zrušena.</string>
+ <!--Revoke result toast (snackbar)-->
<!--Certify result toast-->
<!--Intent labels-->
<string name="intent_decrypt_file">Dešifrovat soubor pomocí OpenKeychain</string>
@@ -389,15 +387,12 @@
<string name="api_settings_start">Spustit aplikaci</string>
<string name="api_settings_delete_account">Smazat účet</string>
<string name="api_settings_package_name">Jméno balíčku</string>
- <string name="api_settings_package_certificate">SHA-256 z podpisu balíčku</string>
<string name="api_settings_settings">Nastavení</string>
<string name="api_settings_key">Klíč účtu:</string>
<string name="api_settings_accounts_empty">Žádné účty nejsou specifikovány pro tuto appku.</string>
<string name="api_register_allow">Povolit přístup</string>
<string name="api_register_disallow">Zamítnout přístup</string>
<string name="api_register_error_select_key">Prosím vyberte klíč!</string>
- <string name="api_select_pub_keys_missing_text">Nebyly nalezeny žádné klíče pro tyto identity:</string>
- <string name="api_select_pub_keys_dublicates_text">Existuje více jak jeden klíč pro tyto identity:</string>
<string name="api_select_pub_keys_text">Zkontrolujte prosím seznam příjemců!</string>
<string name="api_select_pub_keys_text_no_user_ids">Vyberte prosím příjemce!</string>
<string name="api_error_wrong_signature">Selhala kontrola podpisu! Instalovali jste tuto aplikaci z jiného zdroje? Pokud jste si jistí, že toto není útok, zneplatněte registraci této aplikace v OpenKeychain a poté ji znovu zaregistrujte.</string>
@@ -406,6 +401,9 @@
<!--Share-->
<string name="share_qr_code_dialog_title">Sdílet pomocí QR kódu</string>
<string name="share_nfc_dialog">Sdílet pomocí NFC</string>
+ <!--retry upload dialog-->
+ <!--Delete or revoke private key dialog-->
+ <!--Delete Or Revoke Dialog spinner-->
<!--Key list-->
<plurals name="key_list_selected_keys">
<item quantity="one">1 kíč vybrán</item>
@@ -449,14 +447,6 @@
<string name="key_trust_results_prefix">Keybase.io nabízí “důkazy” které tvrdí, že vlastníkem tohoto klíče je: </string>
<string name="key_trust_header_text">Poznámka: Keybase.io důkazy jsou experimentální fíčura OpenKeychainu. Doporučujeme vám navíc potvrdit je pomocí naskenování QR kódu nebo si vyměnit klíče pomocí NFC.</string>
<!--keybase proof stuff-->
- <string name="keybase_narrative_twitter">Na Twitteru je znám jako</string>
- <string name="keybase_narrative_github">Je znám na GitHubu jako</string>
- <string name="keybase_narrative_dns">Spravuje doménové jméno (jména)</string>
- <string name="keybase_narrative_web_site">Může přispívat na webovou stránku (webové stránky)</string>
- <string name="keybase_narrative_reddit">Přispívá na Reddit jako</string>
- <string name="keybase_narrative_coinbase">Je znám na Coinbase jako</string>
- <string name="keybase_narrative_hackernews">Přispívá na Hacker News jako</string>
- <string name="keybase_narrative_unknown">Neznámý typ důkazu</string>
<string name="keybase_a_post">Příspěvek</string>
<string name="keybase_twitter_proof">tweet</string>
<string name="keybase_web_site_proof">textový soubor</string>
@@ -661,6 +651,7 @@
<!--Messages for Keybase Verification operation-->
<!--Messages for Export Log operation-->
<!--PassphraseCache-->
+ <!--Keyserver sync-->
<!--First Time-->
<string name="first_time_text1">Převezměte opět kontrolu nad svým soukromím s OpenKeychain!</string>
<string name="first_time_skip">Přeskočit nastavení</string>
@@ -681,6 +672,7 @@
<string name="error_no_encrypt_subkey">Není dostupný šifrovací podklíč!</string>
<string name="contact_show_key">Zobrazit klíč (%s)</string>
<string name="swipe_to_update">Potáhnout dolů pro aktualizaci z keyserveru</string>
+ <!--Android Account-->
<!--Passphrase wizard-->
<!--TODO: rename all the things!-->
<!--<string name="enter_passphrase_twice">Enter password twice</string>-->
diff --git a/OpenKeychain/src/main/res/values-de/strings.xml b/OpenKeychain/src/main/res/values-de/strings.xml
index 084216301..291ebf238 100644
--- a/OpenKeychain/src/main/res/values-de/strings.xml
+++ b/OpenKeychain/src/main/res/values-de/strings.xml
@@ -20,8 +20,8 @@
<string name="title_encrypt_to_file">In eine Datei verschlüsseln</string>
<string name="title_decrypt_to_file">In eine Datei entschlüsseln</string>
<string name="title_import_keys">Schlüssel importieren</string>
- <string name="title_export_key">Schlüssel exportieren</string>
- <string name="title_export_keys">Schlüssel exportieren</string>
+ <string name="title_export_key">Backup erstellen</string>
+ <string name="title_export_keys">Backup erstellen</string>
<string name="title_key_not_found">Schlüssel nicht gefunden</string>
<string name="title_send_key">Auf Schlüsselserver hochladen</string>
<string name="title_certify_key">Schlüssel bestätigen</string>
@@ -38,10 +38,14 @@
<string name="section_yubikey">YubiKey</string>
<string name="section_linked_system_contact">Verknüpfter Systemkontakt</string>
<string name="section_should_you_trust">Sollte ich diesem Schlüssel vertrauen?</string>
- <string name="section_proof_details">Nachweis überprüfen</string>
+ <string name="section_proof_details">Nachweis verifizieren</string>
<string name="section_cloud_evidence">Nachweise aus der Cloud</string>
<string name="section_keys">Unterschlüssel</string>
<string name="section_cloud_search">Cloudsuche</string>
+ <string name="section_passphrase_cache">Passwort/PIN-Handhabung</string>
+ <string name="section_proxy_settings">Proxy-Einstellungen</string>
+ <string name="section_gui">Oberfläche</string>
+ <string name="section_sync_settings">Synchronisierungseinstellungen</string>
<string name="section_certify">Bestätigen</string>
<string name="section_actions">Aktionen</string>
<string name="section_share_key">Schlüssel</string>
@@ -57,7 +61,7 @@
<string name="btn_encrypt_save_file">Datei verschlüsseln und speichern</string>
<string name="btn_save_file">Datei speichern</string>
<string name="btn_save">Speichern</string>
- <string name="btn_view_log">Log ansehen</string>
+ <string name="btn_view_log">Log anzeigen</string>
<string name="btn_do_not_save">Abbrechen</string>
<string name="btn_delete">Löschen</string>
<string name="btn_no_date">Kein Ablaufdatum</string>
@@ -67,7 +71,7 @@
<string name="btn_back">Zurück</string>
<string name="btn_no">Nein</string>
<string name="btn_match">Fingerabdrücke stimmen überein</string>
- <string name="btn_share_encrypted_signed">Nachricht verschlüsseln und teilen</string>
+ <string name="btn_share_encrypted_signed">Text verschlüsseln und teilen</string>
<string name="btn_copy_encrypted_signed">Text verschlüsseln und kopieren</string>
<string name="btn_view_cert_key">Beglaubigungsschlüssel anzeigen</string>
<string name="btn_create_key">Schlüssel erzeugen</string>
@@ -75,7 +79,7 @@
<string name="btn_share_decrypted_text">Entschlüsselten Text teilen</string>
<string name="btn_copy_decrypted_text">Entschlüsselten Text kopieren</string>
<string name="btn_decrypt_clipboard">Aus Zwischenablage lesen</string>
- <string name="btn_decrypt_files">Input Datei auswählen.</string>
+ <string name="btn_decrypt_files">Datei auswählen</string>
<string name="btn_encrypt_files">Dateien verschlüsseln</string>
<string name="btn_encrypt_text">Text verschlüsseln</string>
<string name="btn_add_email">Weitere E-Mail-Adresse hinzufügen</string>
@@ -86,7 +90,7 @@
<!--menu-->
<string name="menu_preferences">Einstellungen</string>
<string name="menu_help">Hilfe</string>
- <string name="menu_export_key">In Datei exportieren</string>
+ <string name="menu_export_key">Backup erstellen</string>
<string name="menu_delete_key">Schlüssel löschen</string>
<string name="menu_manage_keys">Meine Schlüssel verwalten</string>
<string name="menu_search">Suchen</string>
@@ -97,10 +101,11 @@
<string name="menu_export_all_keys">Alle Schlüssel exportieren</string>
<string name="menu_update_all_keys">Alle Schlüssel aktualisieren</string>
<string name="menu_advanced">Erweiterte Informationen</string>
- <string name="menu_certify_fingerprint">Über Fingerabdruckvergleich bestätigen</string>
+ <string name="menu_certify_fingerprint">Durch Vergleich der Fingerabdrücke bestätigen</string>
<string name="menu_export_log">Log exportieren</string>
+ <string name="menu_keyserver_add">Hinzufügen</string>
<!--label-->
- <string name="label_message">Nachricht</string>
+ <string name="label_message">Text</string>
<string name="label_file">Datei</string>
<string name="label_files">Datei(en)</string>
<string name="label_file_colon">Datei:</string>
@@ -114,20 +119,23 @@
<string name="label_file_ascii_armor">Aktiviere ASCII Armor</string>
<string name="label_write_version_header">Lass andere wissen dass du OpenKeychain nutzt</string>
<string name="label_write_version_header_summary">Fügt \'OpenKeychain v2.7\' zu OpenPGP-Signaturen, Daten und exportierten Schlüsseln hinzu</string>
- <string name="label_use_default_yubikey_pin">Standard-YubiKey-PIN verwenden</string>
- <string name="label_use_num_keypad_for_yubikey_pin">Zifferntastatur für YubiKey PIN verwenden</string>
- <string name="label_label_use_default_yubikey_pin_summary">Verwendet zum Zugriff auf YubiKeys über NFC die Standard-PIN (123456)</string>
+ <string name="label_use_default_yubikey_pin">Voreingestellte YubiKey-PIN verwenden</string>
+ <string name="label_use_num_keypad_for_yubikey_pin">Zifferntastatur für YubiKey-PINs verwenden</string>
+ <string name="label_label_use_default_yubikey_pin_summary">Verwendet die voreingestellte PIN (123456) um YubiKeys über NFC anzusprechen</string>
+ <string name="label_asymmetric_from">Signiere mit:</string>
<string name="label_to">Verschlüsselt an:</string>
<string name="label_delete_after_encryption">Dateien nach Verschlüsselung löschen</string>
<string name="label_delete_after_decryption">Nach Entschlüsselung löschen</string>
<string name="label_encryption_algorithm">Verschlüsselungsalgorithmus</string>
<string name="label_hash_algorithm">Hash-Algorithmus</string>
<string name="label_symmetric">Mit Passwort verschlüsseln</string>
- <string name="label_message_compression">Nachrichtenkomprimierung</string>
- <string name="label_file_compression">Datei Kompression</string>
+ <string name="label_passphrase_cache_ttl">Merkdauer von Passwörtern</string>
+ <string name="label_passphrase_cache_subs">Passwort pro Unterschlüssel merken</string>
+ <string name="label_message_compression">Textkomprimierung</string>
+ <string name="label_file_compression">Dateikomprimierung</string>
<string name="label_keyservers">OpenPGP-Schlüsselserver auswählen</string>
<string name="label_key_id">Schlüssel-ID</string>
- <string name="label_key_created">Schlüssel erstellt %s</string>
+ <string name="label_key_created">Schlüssel erzeugt %s</string>
<string name="label_creation">Erstellungsdatum</string>
<string name="label_expiry">Ablaufdatum</string>
<string name="label_usage">Verwendungszweck</string>
@@ -140,21 +148,56 @@
<string name="label_send_key">Mit der Cloud synchronisieren</string>
<string name="label_fingerprint">Fingerabdruck</string>
<string name="expiry_date_dialog_title">Ablaufdatum festsetzen</string>
+ <string name="label_keyservers_title">Schlüsselserver</string>
+ <string name="label_keyserver_settings_hint">Ziehen zum Ändern der Sortierung, tippen zum Bearbeiten/Löschen</string>
+ <string name="label_selected_keyserver_title">Ausgewählter Schlüsselserver</string>
<string name="label_preferred">bevorzugt</string>
<string name="label_enable_compression">Komprimierung aktivieren</string>
<string name="label_encrypt_filenames">Dateinamen verschlüsseln</string>
<string name="label_hidden_recipients">Empfänger verbergen</string>
- <string name="label_verify_keyserver">Schlüsselserver überprüfen</string>
+ <string name="label_verify_keyserver">Schlüsselserver verifizieren</string>
<string name="label_enter_keyserver_url">Schlüsselserver-URL eingeben</string>
+ <string name="label_keyserver_dialog_delete">Schlüsselserver löschen</string>
+ <string name="label_theme">Design</string>
<string name="pref_keyserver">OpenPGP-Schlüsselserver</string>
<string name="pref_keyserver_summary">Schlüssel auf ausgewählten OpenPGP-Schlüsselservern suchen (HKP-Protokoll)</string>
<string name="pref_keybase">keybase.io</string>
<string name="pref_keybase_summary">Schlüssel auf keybase.io suchen</string>
+ <string name="label_sync_settings_keyserver_title">Schlüssel automatisch aktualisieren</string>
+ <string name="label_sync_settings_keyserver_summary_on">Schlüssel, die älter als eine Woche sind, werden vom ausgewählten Schlüsselserver aktualisiert</string>
+ <string name="label_sync_settings_keyserver_summary_off">Schlüssel werden nicht automatisch aktualisiert</string>
+ <string name="label_sync_settings_contacts_title">Kontakte mit Schlüsseln synchronisieren</string>
+ <string name="label_sync_settings_contacts_summary_on">Verknüpfungen zwischen Schlüsseln und Kontakten mit übereinstimmenden E-Mail-Adressen, erfolgen komplett offline</string>
+ <string name="label_sync_settings_contacts_summary_off">Neue Schlüssel werden nicht mit Kontakten verknüpft</string>
+ <!--label shown in Android settings under the OpenKeychain account-->
+ <string name="keyserver_sync_settings_title">Schlüssel automatisch aktualisieren</string>
<!--Proxy Preferences-->
+ <string name="pref_proxy_tor_title">Tor aktivieren</string>
+ <string name="pref_proxy_tor_summary">Orbot muss installiert sein</string>
+ <string name="pref_proxy_normal_title">Anderen Proxy aktivieren</string>
+ <string name="pref_proxy_host_title">Proxy-Host</string>
+ <string name="pref_proxy_host_err_invalid">Proxy-Host darf nicht leer sein</string>
+ <string name="pref_proxy_port_title">Proxy-Port</string>
+ <string name="pref_proxy_port_err_invalid">Ungültige Portnummer eingegeben</string>
+ <string name="pref_proxy_type_title">Proxy-Typ</string>
<!--proxy type choices and values-->
+ <string name="pref_proxy_type_choice_http">HTTP</string>
+ <string name="pref_proxy_type_choice_socks">SOCKS</string>
<!--OrbotHelper strings-->
+ <string name="orbot_ignore_tor">Tor wird nicht verwendet</string>
<!--InstallDialogFragment strings-->
+ <string name="orbot_install_dialog_title">Orbot installieren, um Tor zu nutzen?</string>
+ <string name="orbot_install_dialog_install">Installieren</string>
+ <string name="orbot_install_dialog_content">Du musst Orbot installiert und aktiviert haben, um Netzwerverkehr hindurchleiten zu können. Möchtest du es installieren?</string>
+ <string name="orbot_install_dialog_cancel">Abbrechen</string>
+ <string name="orbot_install_dialog_ignore_tor">Tor nicht verwendet</string>
<!--StartOrbotDialogFragment strings-->
+ <string name="orbot_start_dialog_title">Orbot starten?</string>
+ <string name="orbot_start_dialog_content">Orbot scheint nicht zu laufen. Möchtest du es starten und mit Tor verbinden?</string>
+ <string name="orbot_start_btn">Orbot starten</string>
+ <string name="orbot_start_dialog_start">Orbot starten</string>
+ <string name="orbot_start_dialog_cancel">Abbrechen</string>
+ <string name="orbot_start_dialog_ignore_tor">Tor nicht verwendet</string>
<string name="user_id_no_name">&lt;kein Name&gt;</string>
<string name="none">&lt;keine&gt;</string>
<plurals name="n_keys">
@@ -188,6 +231,8 @@
<string name="filemanager_title_open">Öffnen...</string>
<string name="error">Fehler</string>
<string name="error_message">Fehler: %s</string>
+ <string name="theme_dark">Dunkel</string>
+ <string name="theme_light">Hell</string>
<!--key flags-->
<string name="flag_certify">Beglaubigen</string>
<string name="flag_sign">Signieren</string>
@@ -197,43 +242,51 @@
<string name="wrong_passphrase">Falsches Passwort.</string>
<string name="no_filemanager_installed">Kein passender Dateimanager installiert.</string>
<string name="passphrases_do_not_match">Die Passwörter stimmten nicht überein.</string>
- <string name="passphrase_must_not_be_empty">Bitte geben Sie ein Passwort ein.</string>
+ <string name="passphrase_must_not_be_empty">Bitte ein Passwort eingeben.</string>
<string name="passphrase_for_symmetric_encryption">Symmetrische Verschlüsselung.</string>
<string name="passphrase_for">Passwort für \'%s\' eingeben</string>
<string name="pin_for">PIN für \'%s\' eingeben</string>
- <string name="yubikey_pin_for">PIN für Zugriff auf Yubikey für \'%s\' eingeben</string>
+ <string name="yubikey_pin_for">PIN des YubiKeys für \'%s\' eingeben</string>
+ <string name="nfc_text">Halte den YubiKey gegen die Rückseite deines Geräts in die Nähe der NFC-Markierung.</string>
+ <string name="nfc_wait">Halte den YubiKey an die Rückseite!</string>
+ <string name="nfc_finished">Entferne jetzt den YubiKey.</string>
+ <string name="nfc_try_again_text">Nimm den YubiKey jetzt weg und drücke ERNEUT VERSUCHEN.</string>
<string name="file_delete_confirmation_title">Originaldateien löschen?</string>
<string name="file_delete_confirmation">Die folgenden Dateien werden gelöscht: %s</string>
<string name="file_delete_successful">%1$d von %2$d Dateien wurden gelöscht.%3$s</string>
<string name="no_file_selected">Keine Datei ausgewählt.</string>
<string name="encrypt_sign_successful">Erfolgreich signiert und/oder verschlüsselt.</string>
- <string name="encrypt_sign_clipboard_successful">Erfolgreich in die Zwischenablage signiert und/oder verschlüsselt.</string>
+ <string name="encrypt_sign_clipboard_successful">Erfolgreich in die Zwischenablage signiert und/oder verschlüsselt.</string>
<string name="select_encryption_key">Mindestens einen Schlüssel zum Verschlüsseln auswählen.</string>
+ <string name="error_no_encryption_or_signature_key">Mindestens einen Schlüssel zum Verschlüsseln oder Signieren auswählen.</string>
<string name="specify_file_to_encrypt_to">Bitte angeben in welche Datei verschlüsselt werden soll.\nWARNUNG: Datei wird überschrieben, wenn sie bereits existiert.</string>
<string name="specify_file_to_decrypt_to">Bitte angeben in welche Datei entschlüsselt werden soll.\nWARNUNG: Datei wird überschrieben, wenn sie bereits existiert.</string>
- <string name="specify_backup_dest">Bitte angeben in welche Datei exportiert werden soll.\nWARNUNG: Datei wird überschrieben, wenn sie bereits existiert.</string>
+ <string name="specify_backup_dest">Ein Backup ohne deine Schlüssel wird erstellt, bitte wähle eine Zieldatei.\nWARNUNG: Die Datei wird überschrieben, falls sie schon existiert!</string>
+ <string name="specify_backup_dest_single">Dieser Schlüssel wir geteilt, bitte wähle eine Zieldatei.\nWARNUNG: Die Datei wird überschrieben, falls sie schon existiert!</string>
+ <string name="specify_backup_dest_secret_single">Ein vollständiges Backup deiner Schlüssel wird erstellt, bitte wähle eine Zieldatei.\nWARNUNG: Die Datei wird überschrieben, falls sie schon existiert!</string>
+ <string name="specify_backup_dest_secret">Ein vollständiges Backup aller Schlüssel, inklusive deiner eigenen, wird erstellt, bitte wähle eine Zieldatei.\nWARNUNG: Die Datei wird überschrieben, falls sie schon existiert!</string>
<string name="key_deletion_confirmation_multi">Möchtest du wirklich alle ausgewählten Schlüssel löschen?</string>
- <string name="secret_key_deletion_confirmation">Nach dem Löschen wird es dir nicht mehr möglich sein mit diesem Schlüssel verschlüsselte Nachrichten zu lesen und zudem wirst du alle damit getätigten Bestätigungen verlieren!</string>
+ <string name="secret_key_deletion_confirmation">Nach dem Löschen wird es dir nicht mehr möglich sein mit diesem Schlüssel verschlüsselte Nachrichten zu lesen, zudem wirst du alle damit getätigten Bestätigungen verlieren!</string>
<string name="public_key_deletetion_confirmation">Schlüssel \'%s\' löschen?</string>
<string name="also_export_secret_keys">Exportiere auch private Schlüssel</string>
- <string name="reinstall_openkeychain">Du bist auf einen bekannten Fehler in Android gestoßen. Bitte installiere OpenKeychain erneut, wenn du deine Kontakte mit Schlüsseln verknüpfen willst.</string>
+ <string name="reinstall_openkeychain">Es ist ein bekannter Fehler im Zusammenhang mit Android aufgetreten. Bitte installiere OpenKeychain erneut, wenn du deine Kontakte mit Schlüsseln verknüpfen willst.</string>
<string name="key_exported">1 Schlüssel erfolgreich exportiert.</string>
<string name="keys_exported">%d Schlüssel erfolgreich exportiert.</string>
<string name="no_keys_exported">Keine Schlüssel exportiert.</string>
<string name="key_creation_el_gamal_info">Beachte: Nur Unterschlüssel unterstützen ElGamal.</string>
<string name="key_not_found">Schlüssel %08X konnte nicht gefunden werden.</string>
- <string name="specify_file_to_export_log_to">Bitte Datei zum exportieren angeben.\nWARNUNG: Die Datei wird überschrieben, falls sie bereits existiert.</string>
+ <string name="specify_file_to_export_log_to">Bitte Datei zum Exportieren angeben.\nWARNUNG: Die Datei wird überschrieben, falls sie bereits existiert.</string>
<plurals name="bad_keys_encountered">
- <item quantity="one">%d kaputter privater Schlüssel ignoriert. Evtl. wurde er mit folgender Option exportiert:\n --export-secret-subkeys\nUnbedingt mit der Option\n --export-secret-keys\n exportieren.</item>
- <item quantity="other">%d kaputte private Schlüssel ignoriert. Evtl. wurden sie mit folgender Option exportiert:\n --export-secret-subkeys\nUnbedingt mit der Option\n --export-secret-keys\n exportieren.</item>
+ <item quantity="one">%d fehlerhafter privater Schlüssel ignoriert. Evtl. wurde er mit folgender Option exportiert:\n --export-secret-subkeys\nUnbedingt mit dieser Option exportieren:\n --export-secret-keys</item>
+ <item quantity="other">%d fehlerhafte private Schlüssel ignoriert. Evtl. wurden sie mit folgender Option exportiert:\n --export-secret-subkeys\nUnbedingt mit dieser Option exportieren:\n --export-secret-keys</item>
</plurals>
<string name="list_empty">Diese Liste ist leer!</string>
<string name="nfc_successful">Schlüssel erfolgreich mit NFC-Beam gesendet!</string>
<string name="key_copied_to_clipboard">Schlüssel wurde in die Zwischenablage kopiert!</string>
<string name="fingerprint_copied_to_clipboard">Fingerabdruck wurde in die Zwischenablage kopiert!</string>
- <string name="select_key_to_certify">Bitte einen Schlüssel auswählen der für die Bestätigung genutzt werden soll!</string>
+ <string name="select_key_to_certify">Bitte wähle einen Schlüssel aus, der für die Bestätigung genutzt werden soll!</string>
<string name="key_too_big_for_sharing">Schlüssel ist zu groß um so geteilt zu werden!</string>
- <string name="text_copied_to_clipboard">Text wurde in Zwischenablage kopiert!</string>
+ <string name="text_copied_to_clipboard">Text wurde in die Zwischenablage kopiert!</string>
<!--errors
no punctuation, all lowercase,
they will be put after "error_message", e.g. "Error: file not found"-->
@@ -242,18 +295,18 @@
<string name="error_file_not_found">Datei nicht gefunden</string>
<string name="error_no_secret_key_found">kein geeigneter privater Schlüssel gefunden</string>
<string name="error_external_storage_not_ready">Externes Laufwerk ist nicht bereit</string>
- <string name="error_key_size_minimum512bit">Schlüssel muss mindestens 512 Bit lang sein</string>
- <string name="error_unknown_algorithm_choice">Unbekannte Auswahl für Algorithmus</string>
+ <string name="error_key_size_minimum512bit">Schlüssellänge muss mindestens 512 Bit betragen</string>
+ <string name="error_unknown_algorithm_choice">Unbekannter Algorithmus ausgewählt </string>
<string name="error_user_id_no_email">keine E-Mail-Adresse gefunden</string>
<string name="error_key_needs_a_user_id">Mindestens eine Identität wird benötigt</string>
<string name="error_no_signature_passphrase">kein Passwort angegeben</string>
<string name="error_no_signature_key">kein Signaturschlüssel angegeben</string>
<string name="error_invalid_data">Kein gültiger verschlüsselter oder signierter OpenPGP-Inhalt!</string>
- <string name="error_integrity_check_failed">Integritätscheck fehlgeschlagen! Die Daten wurden modifiziert!</string>
+ <string name="error_integrity_check_failed">Integritätscheck fehlgeschlagen! Die Daten wurden verändert!</string>
<string name="error_wrong_passphrase">falsches Passwort</string>
<string name="error_could_not_extract_private_key">Privater Schlüssel konnte nicht extrahiert werden</string>
<!--errors without preceeding Error:-->
- <string name="error_jelly_bean_needed">Android 4.1 wird benötigt um Androids NFC Beam nutzen zu können!</string>
+ <string name="error_jelly_bean_needed">Android 4.1 wird benötigt um Androids NFC-Beam nutzen zu können!</string>
<string name="error_nfc_needed">NFC muss aktiviert sein!</string>
<string name="error_beam_needed">Beam muss aktiviert sein!</string>
<string name="error_nothing_import">Keine Schlüssel gefunden!</string>
@@ -263,36 +316,39 @@
<!--results shown after decryption/verification-->
<string name="decrypt_result_no_signature">Nicht Signiert</string>
<string name="decrypt_result_invalid_signature">Ungültige Signatur!</string>
- <string name="decrypt_result_signature_uncertified">Signiert von einem <b>unbestätigten</b> Schlüssel</string>
- <string name="decrypt_result_signature_secret">Signiert von Ihrem Schlüssel</string>
- <string name="decrypt_result_signature_certified">Signiert von einem bestätigten Schlüssel</string>
- <string name="decrypt_result_signature_expired_key">Signiert von einem <b>abgelaufenem</b> Schlüssel!</string>
- <string name="decrypt_result_signature_revoked_key">Signiert von einem <b>zurückgezogenem</b> Schlüssel!</string>
- <string name="decrypt_result_signature_missing_key">Signiert von einem <b>unbekannten öffentlichen Schlüssel</b></string>
+ <string name="decrypt_result_insecure_cryptography">Unsichere Signatur (Unsichere Kryptographie)!</string>
+ <string name="decrypt_result_signature_uncertified">Von einem <b>unbestätigten</b> Schlüssel signiert</string>
+ <string name="decrypt_result_signature_secret">Von deinem Schlüssel signiert</string>
+ <string name="decrypt_result_signature_certified">Von einem bestätigten Schlüssel signiert</string>
+ <string name="decrypt_result_signature_expired_key">Von einem <b>abgelaufenen</b> Schlüssel signiert!</string>
+ <string name="decrypt_result_signature_revoked_key">Von einem <b>widerrufenen</b> Schlüssel signiert!</string>
+ <string name="decrypt_result_signature_missing_key">Von einem <b>unbekannten öffentlichen Schlüssel</b> signiert</string>
<string name="decrypt_result_encrypted">Verschlüsselt</string>
<string name="decrypt_result_not_encrypted">Nicht Verschlüsselt</string>
+ <string name="decrypt_result_insecure">Unsichere Verschlüsselung</string>
<string name="decrypt_result_action_show">Anzeigen</string>
<string name="decrypt_result_action_Lookup">Nachschlagen</string>
- <string name="decrypt_invalid_text">Entweder ist die Signatur ungültig oder der Schlüssel wurde widerrufen. Es ist nicht sicher, wer den Text geschrieben hat. Soll er trotzdem angezeigt werden?</string>
- <string name="decrypt_invalid_button">Ich verstehe das Risiko, Nachricht anzeigen!</string>
+ <string name="decrypt_invalid_text">Entweder die Signatur ist ungültig oder der Schlüssel wurde widerrufen. Es ist nicht sicher, wer den Text geschrieben hat. Soll er trotzdem angezeigt werden?</string>
+ <string name="decrypt_invalid_button">Ich kenne die Risiken, Nachricht anzeigen!</string>
<!--Add keys-->
<string name="add_keys_my_key">Mein Schlüssel:</string>
<!--progress dialogs, usually ending in '…'-->
<string name="progress_done">Fertig.</string>
<string name="progress_cancel">Abbrechen</string>
- <string name="progress_cancelling">Abbrechen...</string>
+ <string name="progress_cancelling">Wird abgebrochen...</string>
<string name="progress_saving">Wird gespeichert…</string>
<string name="progress_importing">Wird importiert…</string>
- <string name="progress_updating">Aktualisiere Schlüssel...</string>
+ <string name="progress_revoking_uploading">Schlüssel wird widerrufen und hochgeladen..</string>
+ <string name="progress_updating">Schlüssel werden aktualisiert...</string>
<string name="progress_exporting">Wird exportiert…</string>
<string name="progress_uploading">Wird hochgeladen...</string>
<string name="progress_building_key">Schlüssel wird erstellt…</string>
<string name="progress_building_master_key">Hauptschlüssel wird erstellt…</string>
- <string name="progress_generating_rsa">Erzeuge neuen RSA-Schlüssel...</string>
- <string name="progress_generating_dsa">Erzeuge neuen DSA-Schlüssel...</string>
- <string name="progress_generating_elgamal">Erzeuge neuen ElGamal-Schlüssel...</string>
- <string name="progress_generating_ecdsa">\'Erzeuge neuen ECDSA Schlüssel...</string>
- <string name="progress_generating_ecdh">\'Erzeuge neuen ECDH Schlüssel...</string>
+ <string name="progress_generating_rsa">Neuer RSA-Schlüssel wird erzeugt...</string>
+ <string name="progress_generating_dsa">Neuer DSA-Schlüssel wird erzeugt...</string>
+ <string name="progress_generating_elgamal">Neuen ElGamal-Schlüssel wird erzeugt...</string>
+ <string name="progress_generating_ecdsa">Neuer ECDSA-Schlüssel wird erzeugt...</string>
+ <string name="progress_generating_ecdh">Neuer ECDH-Schlüssel wird erzeugt...</string>
<string name="progress_modify">Schlüsselbund wird verändert...</string>
<string name="progress_modify_unlock">Schlüsselbund wird entsperrt...</string>
<string name="progress_modify_adduid">User-ID wird hinzugefügt...</string>
@@ -300,10 +356,12 @@
<string name="progress_modify_revokeuid">User-IDs werden widerrufen...</string>
<string name="progress_modify_primaryuid">Primäre User-ID wird geändert...</string>
<string name="progress_modify_subkeychange">Unterschlüssel werden verändert...</string>
- <string name="progress_modify_subkeyrevoke">Unterschlüssel wird widerrufen...</string>
- <string name="progress_modify_subkeystrip">Kürze Unterschlüssel...</string>
- <string name="progress_modify_subkeyadd">Unterschlüssel wird hinzugefügt...</string>
+ <string name="progress_modify_subkeyrevoke">Unterschlüssel werden widerrufen...</string>
+ <string name="progress_modify_subkeystrip">Unterschlüssel werden gekürzt...</string>
+ <string name="progress_modify_subkeyadd">Unterschlüssel werden hinzugefügt...</string>
<string name="progress_modify_passphrase">Passwort wird geändert…</string>
+ <string name="progress_modify_pin">PIN wird geändert…</string>
+ <string name="progress_modify_admin_pin">Admin-PIN wird geändert…</string>
<plurals name="progress_exporting_key">
<item quantity="one">Schlüssel wird exportiert…</item>
<item quantity="other">Schlüssel werden exportiert…</item>
@@ -315,7 +373,7 @@
<string name="progress_encrypting">Daten werden verschlüsselt…</string>
<string name="progress_decrypting">Daten werden entschlüsselt…</string>
<string name="progress_preparing_signature">Signatur wird vorbereitet…</string>
- <string name="progress_generating_signature">Signatur wird erstellt…</string>
+ <string name="progress_generating_signature">Signatur wird erzeugt…</string>
<string name="progress_processing_signature">Signatur wird verarbeitet…</string>
<string name="progress_verifying_signature">Signatur wird verifiziert…</string>
<string name="progress_signing">Wird signiert…</string>
@@ -323,14 +381,15 @@
<string name="progress_reading_data">Daten werden gelesen…</string>
<string name="progress_finding_key">Schlüssel wird gesucht…</string>
<string name="progress_decompressing_data">Daten werden entpackt…</string>
- <string name="progress_verifying_integrity">Integrität wird überprüft…</string>
+ <string name="progress_verifying_integrity">Integrität wird verifiziert…</string>
<string name="progress_deleting_securely">\'%s\' wird sicher gelöscht…</string>
- <string name="progress_deleting">Lösche Schlüssel</string>
- <string name="progress_con_saving">Zusammenführung: Im Cache speichern...</string>
- <string name="progress_con_reimport">Zusammenführung: Neuimportierung...</string>
- <string name="progress_verifying_keyserver_url">Schlüsselserver wird überprüft…</string>
+ <string name="progress_deleting">Lösche Schlüssel…</string>
+ <string name="progress_con_saving">Zusammenführung: Sichere in den Zwischenspeicher...</string>
+ <string name="progress_con_reimport">Zusammenführung: Reimportiere...</string>
+ <string name="progress_verifying_keyserver_url">Schlüsselserver wird verifiziert…</string>
+ <string name="progress_starting_orbot">Orbot wird gestartet…</string>
<!--action strings-->
- <string name="hint_cloud_search_hint">Via Name, E-Mail durchsuchen...</string>
+ <string name="hint_cloud_search_hint">Via Name, E-Mail suchen...</string>
<!--key bit length selections-->
<string name="key_size_512">512</string>
<string name="key_size_768">768</string>
@@ -342,8 +401,8 @@
<string name="key_size_8192">8192</string>
<string name="key_size_custom">Benutzerdefinierte Schlüssellänge</string>
<string name="key_size_custom_info">Benutzerdefinierte Schlüssellänge (in Bit):</string>
- <string name="key_size_custom_info_rsa">Die RSA-Schlüssellänge muss grösser als 1024 und höchstens 16384 sein. Sie muss auch ein Mehrfaches von 8 sein.</string>
- <string name="key_size_custom_info_dsa">Die DSA-Schlüssellänge muss mindestens 512 und höchstens 1024 sein. Auch muss sie ein Mehrfaches von 64 sein.</string>
+ <string name="key_size_custom_info_rsa">Die RSA-Schlüssellänge muss grösser als 1024 und kleiner als 16384 sein. Sie muss außerdem ein Vielfaches von 8 sein.</string>
+ <string name="key_size_custom_info_dsa">Die DSA-Schlüssellänge muss mindestens 512 und höchstens 1024 sein. Sie muss außerdem ein Vielfaches von 64 sein.</string>
<!--elliptic curve names-->
<string name="key_curve_nist_p256">NIST P-256</string>
<string name="key_curve_nist_p384">NIST P-384</string>
@@ -365,37 +424,37 @@
<string name="help_about_version">Version:</string>
<!--Import-->
<string name="import_tab_keyserver">Schlüsselserver</string>
- <string name="import_tab_cloud">Cloud durchsuchen</string>
+ <string name="import_tab_cloud">In der Cloud suchen</string>
<string name="import_tab_direct">Datei/Zwischenablage</string>
<string name="import_tab_qr_code">QR-Code/NFC</string>
<string name="import_import">Ausgewählte Schlüssel importieren</string>
- <string name="import_qr_code_wrong">Falsch formatierter QR-Code! Bitte erneut versuchen!</string>
- <string name="import_qr_code_fp">Fingerabdruck ist beschädigt oder zu kurz!</string>
+ <string name="import_qr_code_wrong">QR-Code ist fehlerhaft! Bitte erneut versuchen!</string>
+ <string name="import_qr_code_fp">Fingerabdruck ist fehlerhaft oder zu kurz!</string>
<string name="import_qr_code_too_short_fingerprint">Fingerabdruck ist zu kurz!</string>
- <string name="import_qr_code_button">QR-Code scannen</string>
+ <string name="import_qr_code_button">QR-Code einscannen</string>
<string name="import_qr_code_text">Halte deine Kamera über den QR-Code!</string>
<!--Import from URL-->
- <string name="import_url_warn_no_search_parameter">Kein Suchbegriff angegeben. Sie können trotzdem manuell auf dem Keyserver suchen.</string>
+ <string name="import_url_warn_no_search_parameter">Kein Suchbegriff angegeben. Eine manuelle Suche auf diesem Schlüsselserver ist trotzdem möglich.</string>
<!--Generic result toast-->
<string name="snackbar_details">Details</string>
<string name="with_warnings">, mit Warnungen</string>
- <string name="with_cancelled">. bis abgebrochen wurde</string>
+ <string name="with_cancelled">, bis abgebrochen wurde</string>
<!--Import result toast-->
<plurals name="import_keys_added_and_updated_1">
- <item quantity="one">1 Schlüssel erfolgreich importiert</item>
- <item quantity="other">%1$d Schlüssel erfolgreich importiert</item>
+ <item quantity="one">Schlüssel wurde erfolgreich importiert</item>
+ <item quantity="other">%1$d Schlüssel wurden erfolgreich importiert</item>
</plurals>
<plurals name="import_keys_added_and_updated_2">
- <item quantity="one">und aktuallisierter Schlüssel%2$s.</item>
- <item quantity="other">und aktuallisierte %1$d Schlüssel%2$s.</item>
+ <item quantity="one">und Schlüssel aktualisiert%2$s.</item>
+ <item quantity="other">und %1$d Schlüssel aktualisiert%2$s.</item>
</plurals>
<plurals name="import_keys_added">
- <item quantity="one">Schlüssel %2$s erfolgreich importiert</item>
- <item quantity="other">%1$d Schlüssel erfolgreich importiert: %2$s.</item>
+ <item quantity="one">Schlüssel erfolgreich importiert%2$s.</item>
+ <item quantity="other">%1$d Schlüssel erfolgreich importiert%2$s.</item>
</plurals>
<plurals name="import_keys_updated">
- <item quantity="one">Schlüssel %2$s erfolgreich aktualisiert.</item>
- <item quantity="other">%1$d Schlüssel erfolgreich aktualisiert: %2$s.</item>
+ <item quantity="one">Schlüssel erfolgreich aktualisiert%2$s.</item>
+ <item quantity="other">%1$d Schlüssel erfolgreich aktualisiert%2$s.</item>
</plurals>
<plurals name="import_keys_with_errors">
<item quantity="one">Import eines Schlüssels fehlgeschlagen!</item>
@@ -409,27 +468,32 @@
<string name="import_error_nothing_cancelled">Import abgebrochen.</string>
<!--Delete result toast-->
<plurals name="delete_ok_but_fail_1">
- <item quantity="one">Der Schlüssel wurde erfolgreich gelöscht.</item>
+ <item quantity="one">Schlüssel wurde erfolgreich gelöscht</item>
<item quantity="other">%1$d Schlüssel wurden erfolgreich gelöscht</item>
</plurals>
<plurals name="delete_ok_but_fail_2">
- <item quantity="one">, aber das Löschen eines Schlüssels%2$s ist fehlgeschlagen.</item>
- <item quantity="other">, aber das Löschen von %1$d Schlüsseln%2$s ist fehlgeschlagen.</item>
+ <item quantity="one">, aber das Löschen eines Schlüssels ist fehlgeschlagen%2$s.</item>
+ <item quantity="other">, aber das Löschen von %1$d Schlüsseln ist fehlgeschlagen%2$s.</item>
</plurals>
<plurals name="delete_ok">
- <item quantity="one">Erfolgreich gelöscht key%2$s.</item>
- <item quantity="other">Erfolgreich gelöscht %1$d keys%2$s.</item>
+ <item quantity="one">Schlüssel wurde erfolgreich gelöscht%2$s.</item>
+ <item quantity="other">%1$d Schlüssel wurden erfolgreich gelöscht%2$s.</item>
</plurals>
<plurals name="delete_fail">
<item quantity="one">Fehler beim Löschen eines Schlüssels%2$s.</item>
<item quantity="other">Fehler beim Löschen von %1$d Schlüsseln.</item>
</plurals>
<string name="delete_nothing">Nichts zu löschen.</string>
- <string name="delete_cancelled">Löschen abgebrochen.</string>
+ <string name="delete_cancelled">Löschvorgang abgebrochen.</string>
+ <!--Revoke result toast (snackbar)-->
+ <string name="revoke_ok">Schlüssel erfolgreich widerrufen.</string>
+ <string name="revoke_fail">Fehler beim Widerrufen des Schlüssels!</string>
+ <string name="revoke_nothing">Nichts zu widerrufen.</string>
+ <string name="revoke_cancelled">Widerrufvorgang abgebrochen.</string>
<!--Certify result toast-->
<plurals name="certify_keys_ok">
- <item quantity="one">Schlüssel%2$s erfolgreich beglaubigt.</item>
- <item quantity="other">%1$d Schlüssel%2$s erfolgreich beglaubigt.</item>
+ <item quantity="one">Schlüssel wurde erfolgreich beglaubigt%2$s.</item>
+ <item quantity="other">%1$d Schlüssel wurden erfolgreich beglaubigt%2$s.</item>
</plurals>
<plurals name="certify_keys_with_errors">
<item quantity="one">Beglaubigung fehlgeschlagen!</item>
@@ -456,32 +520,45 @@
<string name="api_settings_save_msg">Benutzerkonto wurde gespeichert</string>
<string name="api_settings_cancel">Abbrechen</string>
<string name="api_settings_revoke">Zugriff widerufen</string>
- <string name="api_settings_start">Starte Anwendung</string>
+ <string name="api_settings_start">Anwendung starten</string>
<string name="api_settings_delete_account">Benutzerkonto löschen</string>
<string name="api_settings_package_name">Paketname</string>
- <string name="api_settings_package_certificate">SHA-256 der Paketsignatur</string>
+ <string name="api_settings_package_certificate">SHA-256 des Paketzertifikats</string>
<string name="api_settings_accounts">Benutzerkonten (veraltete API)</string>
<string name="api_settings_advanced">Erweiterte Informationen</string>
<string name="api_settings_allowed_keys">Erlaubte Schlüssel</string>
<string name="api_settings_settings">Einstellungen</string>
- <string name="api_settings_key">Benutzerkontoschlüssel:</string>
+ <string name="api_settings_key">Schlüssel des Kontos:</string>
<string name="api_settings_accounts_empty">Keine Benutzerkonten mit dieser Anwendung verknüpft.</string>
<string name="api_create_account_text">Für dieses Benutzerkonto ist kein Schlüssel konfiguriert. Bitte wähle einen deiner existierenden Schlüssel aus oder erzeuge einen neuen.\nApps können nur hier ausgewählte Schlüssel nutzen!</string>
<string name="api_update_account_text">Der Schlüssel für dieses Benutzerkonto wurde gelöscht. Bitte wähle einen anderen aus!\nApps können nur hier ausgewählte Schlüssel nutzen.</string>
- <string name="api_register_text">Folgende Anwendung möchte Nachrichten ver-/entschlüsseln und in deinem Namen signieren. Zugriff erlauben?\n\nVORSICHT: Solltest du nicht wissen warum dieses Fenster erscheint, erlaube den Zugriff nicht! Du kannst den Zugriff später über den \'Apps\'-Bildschirm widerrufen.</string>
+ <string name="api_register_text">Folgende Anwendung möchte Nachrichten ver-/entschlüsseln und in deinem Namen signieren.\nZugriff erlauben?\n\nVORSICHT: Solltest du nicht wissen warum dieser Bildschirm angezeigt wird, erlaube den Zugriff nicht! Du kannst den Zugriff später über den \'Apps\'-Bildschirm widerrufen.</string>
<string name="api_register_allow">Zugriff erlauben</string>
<string name="api_register_disallow">Zugriff verbieten</string>
<string name="api_register_error_select_key">Bitte einen Schlüssel auswählen!</string>
- <string name="api_select_pub_keys_missing_text">Für diese Identitäten wurden keine Schlüssel gefunden:</string>
- <string name="api_select_pub_keys_dublicates_text">Für diese Identität existiert mehr als ein Schlüssel:</string>
+ <string name="api_select_pub_keys_missing_text">Für diese E-Mail-Adressen wurden keine Schlüssel gefunden:</string>
+ <string name="api_select_pub_keys_dublicates_text">Es exisitert mehr als ein Schlüssel für diese E-Mail-Adressen:</string>
<string name="api_select_pub_keys_text">Bitte die Liste der Empfänger überprüfen!</string>
- <string name="api_select_pub_keys_text_no_user_ids">Bitte wählen sie einen Empfänger!</string>
- <string name="api_error_wrong_signature">Signaturüberprüfung fehlgeschlagen! Haben Sie diese Anwendung aus einer anderen Quelle installiert? Wenn Sie eine Attacke ausschliessen können, sollten Sie die Registrierung der App in OpenKeychain widerrufen und die Anwendung erneut registrieren.</string>
+ <string name="api_select_pub_keys_text_no_user_ids">Bitte die Empfänger auswählen!</string>
+ <string name="api_error_wrong_signature">Signaturverifikation fehlgeschlagen! Wurde diese App aus einer anderen Quelle installiert? Wenn du eine Attacke ausschließen kannst, solltest du die Registrierung der App in OpenKeychain widerrufen und die App erneut registrieren.</string>
<string name="api_select_sign_key_text">Bitte wähle einen deiner vorhandenen Schlüssel aus oder erzeuge einen neuen.</string>
- <string name="api_select_keys_text">Keiner der zugelassenen Schlüssel kann den Inhalt entschlüsseln. Bitte wählen Sie die zugelassenen Schlüssel aus.</string>
+ <string name="api_select_keys_text">Keiner der erlaubten Schlüssel kann den Inhalt entschlüsseln, bitte die erlaubten Schlüssel auswählen.</string>
<!--Share-->
<string name="share_qr_code_dialog_title">Über QR-Code teilen</string>
<string name="share_nfc_dialog">Über NFC teilen</string>
+ <!--retry upload dialog-->
+ <string name="retry_up_dialog_title">Hochladen fehlgeschlagen</string>
+ <string name="retry_up_dialog_message">Hochladen fehlgeschlagen. Soll der Vorgang wiederholt werden?</string>
+ <string name="retry_up_dialog_btn_reupload">Vorgang wiederholen</string>
+ <string name="retry_up_dialog_btn_cancel">Vorgang abbrechen</string>
+ <!--Delete or revoke private key dialog-->
+ <string name="del_rev_dialog_message">Wenn du diesen Schlüssel nicht mehr länger nutzen möchtest, sollte er widerrufen und hochgeladen werden. Wähle \'NUR LÖSCHEN\' aus, wenn du den Schlüssel aus OpenKeychain entfernen, ihn aber an anderer Stelle weiternutzen möchtest.</string>
+ <string name="del_rev_dialog_title">Schlüssel \'%s\' widerrufen/löschen</string>
+ <string name="del_rev_dialog_btn_revoke">Widerrufen und hochladen</string>
+ <string name="del_rev_dialog_btn_delete">Nur löschen</string>
+ <!--Delete Or Revoke Dialog spinner-->
+ <string name="del_rev_dialog_choice_delete">Nur löschen</string>
+ <string name="del_rev_dialog_choice_rev_upload">Widerrufen und hochladen</string>
<!--Key list-->
<plurals name="key_list_selected_keys">
<item quantity="one">1 Schlüssel ausgewählt.</item>
@@ -492,10 +569,10 @@
<string name="key_list_filter_show_certified">Nur beglaubigte Schlüssel anzeigen</string>
<!--Key view-->
<string name="key_view_action_edit">Schlüssel bearbeiten</string>
- <string name="key_view_action_encrypt">Text Verschlüsseln</string>
+ <string name="key_view_action_encrypt">Text verschlüsseln</string>
<string name="key_view_action_encrypt_files">Dateien</string>
<string name="key_view_action_certify">Schlüssel bestätigen</string>
- <string name="key_view_action_update">Von Schlüsselserver aktualisieren</string>
+ <string name="key_view_action_update">Vom Schlüsselserver aktualisieren</string>
<string name="key_view_action_share_with">Teilen über...</string>
<string name="key_view_action_share_nfc">Über NFC teilen</string>
<string name="key_view_action_upload">Auf Schlüsselserver hochladen</string>
@@ -511,7 +588,7 @@
<string name="user_id_info_uncertified_title">Nicht beglaubigt</string>
<string name="user_id_info_uncertified_text">Diese Identität wurde noch nicht beglaubigt. Du kannst nicht sicher sein, dass diese Identität wirklich zu einer bestimmten Person gehört.</string>
<string name="user_id_info_invalid_title">Ungültig</string>
- <string name="user_id_info_invalid_text">Irgend etwas ist mit dieser Identität nicht in Ordnung!</string>
+ <string name="user_id_info_invalid_text">Etwas ist mit dieser Identität nicht in Ordnung!</string>
<!--Key trust-->
<string name="key_trust_already_verified">Du hast diesen Schlüssel bereits bestätigt!</string>
<string name="key_trust_it_is_yours">Dies ist einer deiner Schlüssel!</string>
@@ -521,27 +598,27 @@
<string name="key_trust_old_keys">Es ist möglicherweise in Ordnung dies zu nutzen, um eine alte Nachricht zu entschlüsseln, die aus der Zeit stammt, als der Schlüssel noch gültig war.</string>
<string name="key_trust_no_cloud_evidence">Kein Nachweis aus der Cloud zur Vertrauenswürdigkeit dieses Schlüssels.</string>
<string name="key_trust_start_cloud_search">Suche beginnen</string>
- <string name="key_trust_results_prefix">Keybase.io bietet \"Nachweise\" die versichern, dass der Schlüsselinhaber:</string>
- <string name="key_trust_header_text">Hinweis: Keybase.io-Nachweise sind ein experimentelles Feature von OpenKeychain. Wir rufen dazu auf, zusätzlich zur Überprüfung, QR-Codes zu nutzen oder Schlüssel via NFC auszutauschen.</string>
+ <string name="key_trust_results_prefix">Keybase.io bietet \"Nachweise\" die bestätigen, dass der Schlüsselinhaber:</string>
+ <string name="key_trust_header_text">Hinweis: Keybase.io-Nachweise sind ein experimentelles Feature von OpenKeychain. Wir rufen dazu auf, zusätzlich zur Bestätigung, QR-Codes zu nutzen oder Schlüssel via NFC auszutauschen.</string>
<!--keybase proof stuff-->
- <string name="keybase_narrative_twitter">Schreibt auf Twitter als</string>
- <string name="keybase_narrative_github">Ist auf GitHub bekannt als</string>
- <string name="keybase_narrative_dns">Kontrolliert diese Domainnamen</string>
- <string name="keybase_narrative_web_site">Kann auf diesen Webseiten veröffentlichen</string>
- <string name="keybase_narrative_reddit">Veröffentlicht auf Reddit als</string>
- <string name="keybase_narrative_coinbase">Ist auf Coinbase bekannt als</string>
- <string name="keybase_narrative_hackernews">Veröffentlicht auf Hacker News als</string>
- <string name="keybase_narrative_unknown">Unbekannter Nachweistyp</string>
+ <string name="keybase_narrative_twitter">Auf Twitter schreibt, als %s</string>
+ <string name="keybase_narrative_github">Auf GitHub bekannt ist, als %s</string>
+ <string name="keybase_narrative_dns">Kontrolliert den/die Domainname(n) %s</string>
+ <string name="keybase_narrative_web_site">Auf diese Webseite(n) veröffentlichen kann %s</string>
+ <string name="keybase_narrative_reddit">Auf Reddit veröffentlicht, als %s</string>
+ <string name="keybase_narrative_coinbase">Auf Coinbase bekannt ist, als %s</string>
+ <string name="keybase_narrative_hackernews">Auf Hacker News veröffentlicht, als %s</string>
+ <string name="keybase_narrative_unknown">Unbekannter Nachweistyp %s</string>
<string name="keybase_proof_failure">Leider kann dieser Nachweis nicht überprüft werden.</string>
- <string name="keybase_unknown_proof_failure">Unbekanntes Problem mit dem Nachweis-Prüfer</string>
+ <string name="keybase_unknown_proof_failure">Unbekanntes Problem mit dem Nachweisprüfer</string>
<string name="keybase_problem_fetching_evidence">Problem mit dem Nachweis</string>
- <string name="keybase_key_mismatch">Schlüssel-Fingerabdruck stimmt nicht mit dem Fingerabdruck im Nachweis überein</string>
+ <string name="keybase_key_mismatch">Fingerabdruck des Schlüssels stimmt nicht mit dem Fingerabdruck im Nachweis überein</string>
<string name="keybase_dns_query_failure">Abfrage des DNS-TXT-Eintrags fehlgeschlagen</string>
- <string name="keybase_no_prover_found">Kein Nachweis-Prüfer gefunden für</string>
+ <string name="keybase_no_prover_found">Kein Nachweisprüfer gefunden für</string>
<string name="keybase_message_payload_mismatch">Entschlüsselter Nachweis entspricht nicht dem erwarteten Wert</string>
- <string name="keybase_message_fetching_data">Hole Nachweis</string>
- <string name="keybase_proof_succeeded">Dieser Nachweis wurde überprüft!</string>
- <string name="keybase_a_post">Ein Posting</string>
+ <string name="keybase_message_fetching_data">Nachweis wird abgerufen</string>
+ <string name="keybase_proof_succeeded">Dieser Nachweis wurde verifiziert!</string>
+ <string name="keybase_a_post">Ein Posting / eine Veröffentlichung</string>
<string name="keybase_fetched_from">abgerufen von</string>
<string name="keybase_for_the_domain">für die Domain</string>
<string name="keybase_contained_signature">enthält eine Nachricht, die nur vom Schlüsselinhaber hätte erzeugt werden können.</string>
@@ -551,34 +628,34 @@
<string name="keybase_github_proof">Ein Gist</string>
<string name="keybase_reddit_proof">Eine JSON-Datei</string>
<string name="keybase_reddit_attribution">von Reddit zugeordnet an</string>
- <string name="keybase_verify">Überprüfen</string>
+ <string name="keybase_verify">Verifizieren</string>
<!--Edit key-->
<string name="edit_key_action_change_passphrase">Passwort ändern</string>
<string name="edit_key_action_add_identity">Identität hinzufügen</string>
<string name="edit_key_action_add_subkey">Unterschlüssel hinzufügen</string>
- <string name="edit_key_edit_user_id_title">Eine Aktion auswählen</string>
+ <string name="edit_key_edit_user_id_title">Wähle eine Aktion aus!</string>
<string-array name="edit_key_edit_user_id">
- <item>Als primäre Identität definieren</item>
+ <item>Als Hauptidentität festlegen</item>
<item>Identität widerrufen</item>
</string-array>
<string-array name="edit_key_edit_user_id_revert_revocation">
- <item>Widerruf widerrufen</item>
+ <item>Widerruf rückgängig machen</item>
</string-array>
<string name="edit_key_edit_user_id_revoked">Diese Identität wurde widerrufen. Dies kann nicht rückgängig gemacht werden.</string>
- <string name="edit_key_edit_subkey_title">Aktion auswählen!</string>
+ <string name="edit_key_edit_subkey_title">Wähle eine Aktion aus!</string>
<string-array name="edit_key_edit_subkey">
<item>Ablaufdatum ändern</item>
<item>Unterschlüssel widerrufen</item>
<item>Unterschlüssel kürzen</item>
- <item>Unterschlüssel auf Yubikey/Smartcard verschieben</item>
+ <item>Unterschlüssel auf YubiKey / Smartcard verschieben</item>
</string-array>
<string name="edit_key_new_subkey">neuer Unterschlüssel</string>
- <string name="edit_key_select_flag">Mindestens ein Attribut wählen!</string>
+ <string name="edit_key_select_flag">Bitte mindestens ein Attribut wählen!</string>
<string name="edit_key_error_add_identity">Füge mindestens eine Identität hinzu!</string>
- <string name="edit_key_error_add_subkey">Fügen Sie mindestens einen Unterschlüssel hinzu!</string>
+ <string name="edit_key_error_add_subkey">Füge mindestens einen Unterschlüssel hinzu!</string>
<string name="edit_key_error_bad_nfc_algo">Hash-Algorithmus wird von dieser Smartcard nicht unterstützt!</string>
- <string name="edit_key_error_bad_nfc_size">Schlüssellänge wird von dieser Smartcard nicht unterstützt!</string>
- <string name="edit_key_error_bad_nfc_stripped">Kann Schlüssel nicht auf Smartcard verschieben (entweder gekürzt oder \'auf Karte umleiten\')!</string>
+ <string name="edit_key_error_bad_nfc_size">Die Schlüssellänge wird von dieser Smartcard nicht unterstützt!</string>
+ <string name="edit_key_error_bad_nfc_stripped">Schlüssel kann nicht auf Smartcard verschoben werden (entweder er ist gekürzt oder \'auf Karte umgeleitet\')!</string>
<!--Create key-->
<string name="create_key_upload">Mit der Cloud synchronisieren</string>
<string name="create_key_empty">Dieses Feld wird benötigt</string>
@@ -586,30 +663,40 @@
<string name="create_key_final_text">Du hast folgende Identität eingegeben:</string>
<string name="create_key_final_robot_text">Einen Schlüssel zu erzeugen braucht eine Weile, trink in der Zeit einen Kaffee...</string>
<string name="create_key_rsa">(3 Unterschlüssel, RSA, 4096 Bit)</string>
- <string name="create_key_custom">(Benutzerdefinierte Schlüsseleinstellung)</string>
- <string name="create_key_name_text">Verknüpfe einen Namen mit diesem Schlüssel. Es kann ein voller Name, z.B. \"John Doe\", oder ein Spitzname, z.B. \"Johnny\", sein.</string>
+ <string name="create_key_custom">(Benutzerdefinierte Schlüsselkonfiguration)</string>
+ <string name="create_key_name_text">Verknüpfe einen Namen mit diesem Schlüssel. Es kann ein voller Name wie z.B. \"John Doe\", oder ein Spitzname wie z.B. \"Johnny\", sein.</string>
<string name="create_key_email_text">Gib deine Haupt-E-Mail-Adresse ein, die du für sichere Kommunikation nutzen möchtest.</string>
- <string name="create_key_passphrase_text">Wählen Sie ein langes Passwort. Es schützt Ihre Schlüssel, wenn Ihr Gerät gestohlen werden sollte.</string>
+ <string name="create_key_passphrase_text">Wähle ein starkes Passwort. Es schützt den Schlüssel, wenn dein Gerät gestohlen werden sollte.</string>
<string name="create_key_hint_full_name">Vollständiger Name oder Spitzname</string>
<string name="create_key_edit">Schlüsselkonfiguration ändern</string>
<string name="create_key_add_email">E-Mail-Adresse hinzufügen</string>
<string name="create_key_add_email_text">Es sind zusätzliche E-Mail-Adressen mit diesem Schlüssel verknüpft, die zur sicheren Kommunikation verwendet werden können.</string>
<string name="create_key_email_already_exists_text">E-Mail-Adresse wurde bereits hinzugefügt</string>
- <string name="create_key_email_invalid_email">E-Mail-Adressformat ist ungültig</string>
+ <string name="create_key_email_invalid_email">Format der E-Mail-Adresse ist ungültig</string>
+ <string name="create_key_yubi_key_pin_text">Bitte die PIN gut merken, sie wird benötigt um später deinen YubiKey verwenden zu können. Schreibe zudem die Admin-PIN auf und hinterlege sie an einem sicheren Ort.</string>
+ <string name="create_key_yubi_key_pin">PIN</string>
+ <string name="create_key_yubi_key_admin_pin">Admin-PIN</string>
+ <string name="create_key_yubi_key_pin_repeat_text">Zum Fortfahren bitte PIN und Admin-PIN eingeben.</string>
+ <string name="create_key_yubi_key_pin_repeat">PIN wiederholen</string>
+ <string name="create_key_yubi_key_admin_pin_repeat">Admin-PIN wiederholen</string>
+ <string name="create_key_yubi_key_pin_not_correct">PIN ist nicht richtig!</string>
<!--View key-->
<string name="view_key_revoked">Widerrufen: Schlüssel darf nicht mehr genutzt werden!</string>
<string name="view_key_expired">Abgelaufen: Der Kontakt muss die Gültigkeit des Schlüssels verlängern!</string>
- <string name="view_key_expired_secret">Abgelaufen: Du kannst die Gültigkeit des Schlüssels verlängern indem du ihn editierst.</string>
+ <string name="view_key_expired_secret">Abgelaufen: Du kannst die Gültigkeit des Schlüssels verlängern, indem du ihn bearbeitest.</string>
<string name="view_key_my_key">Mein Schlüssel</string>
<string name="view_key_verified">Bestätigter Schlüssel</string>
- <string name="view_key_unverified">Unbestätigt: QR-Code scannen, um den Schlüssel zu bestätigen!</string>
+ <string name="view_key_unverified">Unbestätigt: QR-Code einscannen, um den Schlüssel zu bestätigen!</string>
<string name="view_key_fragment_no_system_contact">&lt;keine&gt;</string>
<!--Add/Edit keyserver-->
<string name="add_keyserver_dialog_title">Schlüsselserver hinzufügen</string>
- <string name="add_keyserver_verified">Schlüsselserver bestätigt!</string>
- <string name="add_keyserver_without_verification">Schlüsselserver ohne Überprüfung hinzugefügt.</string>
+ <string name="edit_keyserver_dialog_title">Schlüsselserver bearbeiten</string>
+ <string name="add_keyserver_verified">Schlüsselserver verifiziert!</string>
+ <string name="add_keyserver_without_verification">Schlüsselserver ohne Verifikation hinzugefügt.</string>
<string name="add_keyserver_invalid_url">Ungültige URL!</string>
- <string name="add_keyserver_connection_failed">Kann sich nicht mit Keyserver verbinden. Bitte überprüfen Sie die URL und Ihre Internetverbindung.</string>
+ <string name="add_keyserver_connection_failed">Verbindung zum Schlüsselserver fehlgeschlagen. Bitte überprüfe die URL und deine Internetverbindung.</string>
+ <string name="keyserver_preference_deleted">%s gelöscht</string>
+ <string name="keyserver_preference_cannot_delete_last">Kann letzten Schlüsselserver nicht löschen. Mindestens einer wird benötigt!</string>
<!--Navigation Drawer-->
<string name="nav_keys">Schlüssel</string>
<string name="nav_encrypt_decrypt">Verschlüsseln/Entschlüsseln</string>
@@ -617,6 +704,7 @@
<string name="drawer_open">Menü öffnen</string>
<string name="drawer_close">Menü schließen</string>
<string name="my_keys">Meine Schlüssel</string>
+ <string name="nav_backup">Backup</string>
<!--hints-->
<string name="encrypt_content_edit_text_hint">Text eingeben</string>
<!--certs-->
@@ -633,72 +721,72 @@
<string name="msg_internal_error">Interner Fehler!</string>
<string name="msg_cancelled">Vorgang abgebrochen.</string>
<!--Import Public log entries-->
- <string name="msg_ip_apply_batch">Eingabeoperationen werden angewendet.</string>
- <string name="msg_ip_bad_type_secret">Es wurde versucht einen geheimen Schlüsselbund als Öffentlich zu importieren. Dies ist ein Fehler, bitte reiche einen Fehlerbericht ein!</string>
+ <string name="msg_ip_apply_batch">Stapel-Einfügeoperationen werden angewendet.</string>
+ <string name="msg_ip_bad_type_secret">Es wurde versucht einen privaten Schlüsselbund als öffentlichen zu importieren. Dies ist ein Fehler, bitte reiche einen Fehlerbericht ein!</string>
<string name="msg_ip_delete_old_fail">Kein alter Schlüssel gelöscht (Einen neuen erzeugen?)</string>
<string name="msg_ip_delete_old_ok">Alte Schlüssel aus der Datenbank löschen</string>
- <string name="msg_ip_encode_fail">Vorgang aufgrund Kodierungsfehler fehlgeschlagen</string>
- <string name="msg_ip_error_io_exc">Vorgang augrund Eingabe/Ausgabe-Fehler fehlgeschlagen</string>
+ <string name="msg_ip_encode_fail">Vorgang aufgrund eines Kodierungsfehlers fehlgeschlagen</string>
+ <string name="msg_ip_error_io_exc">Vorgang aufgrund eines Ein-/Ausgabefehlers fehlgeschlagen</string>
<string name="msg_ip_error_op_exc">Vorgang aufgrund eines Datenbankfehlers fehlgeschlagen</string>
- <string name="msg_ip_error_remote_ex">Vorgang augrund internem Fehler fehlgeschlagen</string>
+ <string name="msg_ip_error_remote_ex">Vorgang aufgrund eines internen Fehlers fehlgeschlagen</string>
<string name="msg_ip">Importiere öffentlichen Schlüsselbund %s</string>
<string name="msg_ip_insert_keyring">Schlüsselbunddaten werden kodiert</string>
<string name="msg_ip_insert_keys">Analysiere Schlüssel</string>
- <string name="msg_ip_prepare">Datenbank-Transaktionen werden vorbereitet</string>
+ <string name="msg_ip_prepare">Datenbankvorgänge werden vorbereitet</string>
<string name="msg_ip_master">Hauptschlüssel %s wird verarbeitet</string>
<string name="msg_ip_master_expired">Schlüsselbund abgelaufen am %s</string>
<string name="msg_ip_master_expires">Schlüsselbund läuft ab am %s</string>
<string name="msg_ip_master_flags_unspecified">Haupt-Attribute: Unspezifiziert (alle angenommen)</string>
- <string name="msg_ip_master_flags_cesa">Haupt-Attribute: beglaubigen, verschlüsseln, signieren, authentifizieren</string>
- <string name="msg_ip_master_flags_cesx">Haupt-Attribute: beglaubigen, verschlüsseln, signieren</string>
- <string name="msg_ip_master_flags_cexa">Haupt-Attribute: beglaubigen, verschlüsseln, authentifizieren</string>
- <string name="msg_ip_master_flags_cexx">Haupt-Attribute: beglaubigen, verschlüsseln</string>
- <string name="msg_ip_master_flags_cxsa">Haupt-Attribute: beglaubigen, signieren, authentifizieren</string>
- <string name="msg_ip_master_flags_cxsx">Haupt-Attribute: beglaubigen, signieren</string>
- <string name="msg_ip_master_flags_cxxa">Haupt-Attribute: beglaubigen, authentifizieren</string>
+ <string name="msg_ip_master_flags_cesa">Haupt-Attribute: beglaubigen, verschlüsseln, signieren und authentifizieren</string>
+ <string name="msg_ip_master_flags_cesx">Haupt-Attribute: beglaubigen, verschlüsseln und signieren</string>
+ <string name="msg_ip_master_flags_cexa">Haupt-Attribute: beglaubigen, verschlüsseln und authentifizieren</string>
+ <string name="msg_ip_master_flags_cexx">Haupt-Attribute: beglaubigen und verschlüsseln</string>
+ <string name="msg_ip_master_flags_cxsa">Haupt-Attribute: beglaubigen, signieren und authentifizieren</string>
+ <string name="msg_ip_master_flags_cxsx">Haupt-Attribute: beglaubigen und signieren</string>
+ <string name="msg_ip_master_flags_cxxa">Haupt-Attribute: beglaubigen und authentifizieren</string>
<string name="msg_ip_master_flags_cxxx">Haupt-Attribute: beglaubigen</string>
- <string name="msg_ip_master_flags_xesa">Haupt-Attribute: verschlüsseln, signieren, authentifizieren</string>
- <string name="msg_ip_master_flags_xesx">Haupt-Attribute: verschlüsseln, signieren</string>
- <string name="msg_ip_master_flags_xexa">Haupt-Attribute: verschlüsseln, authentifizieren</string>
- <string name="msg_ip_master_flags_xexx">Haupt-Attribute: verschlüsseln</string>
- <string name="msg_ip_master_flags_xxsa">Haupt-Attribute: signieren, authentifizieren</string>
+ <string name="msg_ip_master_flags_xesa">Haupt-Attribute: verschlüsseln, signieren und authentifizieren</string>
+ <string name="msg_ip_master_flags_xesx">Haupt-Attribute: verschlüsseln und signieren</string>
+ <string name="msg_ip_master_flags_xexa">Haupt-Attribute: verschlüsseln und authentifizieren</string>
+ <string name="msg_ip_master_flags_xexx">Haupt-Attribut: verschlüsseln</string>
+ <string name="msg_ip_master_flags_xxsa">Haupt-Attribute: signieren und authentifizieren</string>
<string name="msg_ip_master_flags_xxsx">Haupt-Attribute: signieren</string>
<string name="msg_ip_master_flags_xxxa">Haupt-Attribute: authentifizieren</string>
- <string name="msg_ip_master_flags_xxxx">Haupt-Attribute: Keine</string>
- <string name="msg_ip_merge_public">Füge importierte Daten in existierend öffentlichen Schlüsselbund ein</string>
- <string name="msg_ip_merge_secret">Importierte Daten werden in vorhandenen öffentlichen Schlüsselbund eingefügt</string>
- <string name="msg_ip_subkey">Unterschlüssel %s wird bearbeitet</string>
- <string name="msg_ip_subkey_expired">Unterschlüssel am %s abgelaufen</string>
- <string name="msg_ip_subkey_expires">Unterschlüssel läuft am %s ab</string>
- <string name="msg_ip_subkey_flags_unspecified">Unterschlüssel Attribute: Unspezifiziert (alle angenommen)</string>
- <string name="msg_ip_subkey_flags_cesa">Unterschlüssel Attribute: beglaubigen, verschlüsseln, signieren, authentifizieren</string>
- <string name="msg_ip_subkey_flags_cesx">Unterschlüssel Attribute: beglaubigen, verschlüsseln, signieren</string>
- <string name="msg_ip_subkey_flags_cexa">Unterschlüssel Attribute: beglaubigen, verschlüsseln, authentifizieren</string>
- <string name="msg_ip_subkey_flags_cexx">Unterschlüssel Attribute: beglaubigen, verschlüsseln</string>
- <string name="msg_ip_subkey_flags_cxsa">Unterschlüssel Attribute: beglaubigen, signieren, authentifizieren</string>
- <string name="msg_ip_subkey_flags_cxsx">Unterschlüssel Attribute: beglaubigen, signieren</string>
- <string name="msg_ip_subkey_flags_cxxa">Unterschlüssel Attribute: beglaubigen, authentifizieren</string>
- <string name="msg_ip_subkey_flags_cxxx">Unterschlüssel Attribute: beglaubigen</string>
- <string name="msg_ip_subkey_flags_xesa">Unterschlüssel Attribute: verschlüsseln, signieren, authentifizieren</string>
- <string name="msg_ip_subkey_flags_xesx">Unterschlüssel Attribute: verschlüsseln, signieren</string>
- <string name="msg_ip_subkey_flags_xexa">Unterschlüssel Attribute: verschlüsseln, authentifizieren</string>
- <string name="msg_ip_subkey_flags_xexx">Unterschlüssel Attribute: verschlüsseln</string>
- <string name="msg_ip_subkey_flags_xxsa">Unterschlüssel Attribute: signieren, authentifizieren</string>
- <string name="msg_ip_subkey_flags_xxsx">Unterschlüssel Attribute: signieren</string>
- <string name="msg_ip_subkey_flags_xxxa">Unterschlüssel Attribute: authentifizieren</string>
- <string name="msg_ip_subkey_flags_xxxx">Unterschlüssel Attribute: Keine</string>
+ <string name="msg_ip_master_flags_xxxx">Haupt-Attribute: keine</string>
+ <string name="msg_ip_merge_public">Importierte Daten werden in vorhandenen öffentlichen Schlüsselbund eingefügt</string>
+ <string name="msg_ip_merge_secret">Importierte Daten werden in vorhandenen privaten Schlüsselbund eingefügt</string>
+ <string name="msg_ip_subkey">Verarbeite Unterschlüssel %s</string>
+ <string name="msg_ip_subkey_expired">Unterschlüssel abgelaufen am %s</string>
+ <string name="msg_ip_subkey_expires">Unterschlüssel läuft ab am %s</string>
+ <string name="msg_ip_subkey_flags_unspecified">Unterschlüssel-Attribute: Unspezifiziert (alle angenommen)</string>
+ <string name="msg_ip_subkey_flags_cesa">Unterschlüssel-Attribute: beglaubigen, verschlüsseln, signieren und authentifizieren</string>
+ <string name="msg_ip_subkey_flags_cesx">Unterschlüssel-Attribute: beglaubigen, verschlüsseln und signieren</string>
+ <string name="msg_ip_subkey_flags_cexa">Unterschlüssel-Attribute: beglaubigen, verschlüsseln und authentifizieren</string>
+ <string name="msg_ip_subkey_flags_cexx">Unterschlüssel-Attribute: beglaubigen und verschlüsseln</string>
+ <string name="msg_ip_subkey_flags_cxsa">Unterschlüssel-Attribute: beglaubigen, signieren und authentifizieren</string>
+ <string name="msg_ip_subkey_flags_cxsx">Unterschlüssel-Attribute: beglaubigen und signieren</string>
+ <string name="msg_ip_subkey_flags_cxxa">Unterschlüssel-Attribute: beglaubigen und authentifizieren</string>
+ <string name="msg_ip_subkey_flags_cxxx">Unterschlüssel-Attribut: beglaubigen</string>
+ <string name="msg_ip_subkey_flags_xesa">Unterschlüssel-Attribute: verschlüsseln, signieren und authentifizieren</string>
+ <string name="msg_ip_subkey_flags_xesx">Unterschlüssel-Attribute: verschlüsseln und signieren</string>
+ <string name="msg_ip_subkey_flags_xexa">Unterschlüssel-Attribute: verschlüsseln und authentifizieren</string>
+ <string name="msg_ip_subkey_flags_xexx">Unterschlüssel-Attribut: verschlüsseln</string>
+ <string name="msg_ip_subkey_flags_xxsa">Unterschlüssel-Attribute: signieren und authentifizieren</string>
+ <string name="msg_ip_subkey_flags_xxsx">Unterschlüssel-Attribut: signieren</string>
+ <string name="msg_ip_subkey_flags_xxxa">Unterschlüssel-Attribut: authentifizieren</string>
+ <string name="msg_ip_subkey_flags_xxxx">Unterschlüssel-Attribute: keine</string>
<string name="msg_ip_success">Öffentlicher Schlüsselbund erfolgreich importiert</string>
- <string name="msg_ip_success_identical">Schlüsselbund enthält keine neuen Daten, es gibt nichts zu tun.</string>
- <string name="msg_ip_reinsert_secret">Geheimen Schlüssel wiedereinfügen</string>
- <string name="msg_ip_uid_cert_bad">Fehlerhafte Beglaubigung aufgetreten!</string>
+ <string name="msg_ip_success_identical">Schlüsselbund enthält keine neuen Daten, es gibt nichts zu tun</string>
+ <string name="msg_ip_reinsert_secret">Privaten Schlüssel wiedereinfügen</string>
+ <string name="msg_ip_uid_cert_bad">Fehlerhafte Beglaubigung gefunden!</string>
<string name="msg_ip_uid_cert_error">Fehler beim Verarbeiten der Beglaubigung!</string>
- <string name="msg_ip_uid_cert_nonrevoke">Besitzt bereits eine nicht widerrufbare Beglaubigung, überspringe.</string>
- <string name="msg_ip_uid_cert_old">Beglaubgigung ist älter als Vorherige, überspringe.</string>
- <string name="msg_ip_uid_cert_new">Beglaubigung ist aktueller, ersetze Vorherhige.</string>
+ <string name="msg_ip_uid_cert_nonrevoke">Besitzt bereits eine nicht widerrufbare Beglaubigung, wird übersprungen.</string>
+ <string name="msg_ip_uid_cert_old">Beglaubgigung ist älter als Vorherige, wird übersprungen.</string>
+ <string name="msg_ip_uid_cert_new">Beglaubigung ist aktueller, Vorherhige wird ersetzt.</string>
<string name="msg_ip_uid_cert_good">Korrekte Beglaubigung von %1$s gefunden</string>
<string name="msg_ip_uid_cert_good_revoke">Korrekten Beglaubigungwiderruf von %1$s gefunden</string>
<plurals name="msg_ip_uid_certs_unknown">
- <item quantity="one">Ignoriere eine Beglaubigung, ausgestellt von unbekanntm öffentlichen Schlüssel</item>
+ <item quantity="one">Ignoriere eine Beglaubigung, ausgestellt von unbekanntem öffentlichen Schlüssel</item>
<item quantity="other">Ignoriere %s Beglaubigungen, ausgestellt von unbekannten öffentlichen Schlüsseln</item>
</plurals>
<string name="msg_ip_uid_classifying_zero">User-IDs werden klassifiziert (keine vertrauenswürdigen Schlüssel verfügbar)</string>
@@ -709,9 +797,9 @@
<string name="msg_ip_uid_reorder">User-IDs werden neu geordnet</string>
<string name="msg_ip_uid_processing">User-ID %s wird verarbeitet</string>
<string name="msg_ip_uid_revoked">User-ID wurde widerrufen</string>
- <string name="msg_ip_uat_processing_image">Bilder werden verarbeitet</string>
- <string name="msg_ip_uat_processing_unknown">Unbekannte Benutzerattribute werden verarbeitet</string>
- <string name="msg_ip_uat_cert_bad">Ungültige Beglaubigung gefunden!</string>
+ <string name="msg_ip_uat_processing_image">Bild-Benutzerattribut wird verarbeitet</string>
+ <string name="msg_ip_uat_processing_unknown">Unbekanntes Benutzerattribut wird verarbeitet</string>
+ <string name="msg_ip_uat_cert_bad">Fehlerhafte Beglaubigung gefunden!</string>
<string name="msg_ip_uat_cert_error">Fehler beim Verarbeiten der Beglaubigung!</string>
<string name="msg_ip_uat_cert_nonrevoke">Nicht widerrufbare Beglaubigung bereits vorhanden, überspringe.</string>
<string name="msg_ip_uat_cert_old">Beglaubgigung ist älter als Vorherige, überspringe.</string>
@@ -724,52 +812,52 @@
</plurals>
<string name="msg_ip_uat_classifying">Klassifiziere Benutzerattribute</string>
<string name="msg_ip_uat_revoked">Benutzerattribut wurde widerrufen</string>
- <string name="msg_is_bad_type_public">Es wurde versucht einen öffentlichen Schlüsselbund als Geheim zu importieren. Dies ist ein Fehler, bitte reiche einen Fehlerbericht ein!</string>
- <string name="msg_is_bad_type_uncanon">Es wurde versucht, einen Schlüsselbund ohne Anpassung zu importieren. Dies ist ein Fehler, bitte reiche einen Fehlerbericht ein!</string>
+ <string name="msg_is_bad_type_public">Es wurde versucht einen öffentlichen Schlüsselbund als privaten zu importieren. Dies ist ein Fehler, bitte reiche einen Fehlerbericht ein!</string>
+ <string name="msg_is_bad_type_uncanon">Es wurde versucht, einen Schlüsselbund ohne vorschriftsmäßiges Format zu importieren. Dies ist ein Fehler, bitte reiche einen Fehlerbericht ein!</string>
<!--Import Secret log entries-->
- <string name="msg_is">Importiere geheimen Schlüssel %s</string>
+ <string name="msg_is">Importiere privaten Schlüssel %s</string>
<string name="msg_is_db_exception">Datenbankfehler!</string>
- <string name="msg_is_importing_subkeys">Geheime Unterschlüssel werden bearbeitet</string>
+ <string name="msg_is_importing_subkeys">Private Unterschlüssel werden verarbeitet</string>
<string name="msg_is_error_io_exc">Fehler bei Kordierung des Schlüsselbunds</string>
<string name="msg_is_merge_public">Importierte Daten werden in vorhandenen öffentlichen Schlüsselbund eingefügt</string>
- <string name="msg_is_merge_secret">Importierte Daten werden in vorhandenen öffentlichen Schlüsselbund eingefügt</string>
+ <string name="msg_is_merge_secret">Importierte Daten werden in vorhandenen privaten Schlüsselbund eingefügt</string>
<string name="msg_is_merge_special">Eigenbeglaubigungsdaten aus öffentlichem Schlüsselbund werden eingefügt</string>
- <string name="msg_is_pubring_generate">Generiere öffentlichen Schlüsselbund aus geheimem Schlüsselbund</string>
- <string name="msg_is_subkey_nonexistent">Unterschlüssel %s in privatem Schlüssel nicht verfügbar.</string>
- <string name="msg_is_subkey_ok">Geheimen Unterschlüssel %s als verfügbar markiert</string>
- <string name="msg_is_subkey_empty">Geheimen Unterschlüssel %s als verfügbar markiert, mit leerem Passwort</string>
- <string name="msg_is_subkey_pin">Geheimen Unterschlüssel %s als verfügbar markiert, mit PIN</string>
+ <string name="msg_is_pubring_generate">Öffentlicher Schlüsselbund wird aus privatem Schlüsselbund erzeugt</string>
+ <string name="msg_is_subkey_nonexistent">Unterschlüssel %s in privatem Schlüssel nicht verfügbar</string>
+ <string name="msg_is_subkey_ok">Privater Unterschlüssel %s als verfügbar markiert</string>
+ <string name="msg_is_subkey_empty">Privater Unterschlüssel %s als verfügbar, mit leerem Passwort, markiert</string>
+ <string name="msg_is_subkey_pin">Privater Unterschlüssel %s als verfügbar markiert, mit PIN</string>
<string name="msg_is_subkey_stripped">Privater Unterschlüssel %s als gekürzt markiert</string>
- <string name="msg_is_subkey_divert">Geheimen Unterschlüssel %s als \'Umgeleitet zu Smartcard/NFC\' markiert</string>
+ <string name="msg_is_subkey_divert">Privater Unterschlüssel %s als \'auf Karte umgeleitet\' markiert</string>
<string name="msg_is_success_identical">Schlüsselbund enthält keine neuen Daten, es gibt nichts zu tun</string>
- <string name="msg_is_success">Geheimer Schlüsselbund erfolgreich importiert</string>
+ <string name="msg_is_success">Privater Schlüsselbund erfolgreich importiert</string>
<!--Keyring Canonicalization log entries-->
- <string name="msg_kc_public">Öffentlicher Schlüsselbund %s wird in vorschriftsgemäße Form gebracht</string>
- <string name="msg_kc_secret">Geheimer Schlüsselbund %s wird in vorschriftsgemäße Form gebracht</string>
+ <string name="msg_kc_public">Öffentlicher Schlüsselbund %s wird in vorschriftsmäßiges Format gebracht</string>
+ <string name="msg_kc_secret">Privater Schlüsselbund %s wird in vorschriftsmäßiges Format gebracht</string>
<string name="msg_kc_error_v3">Dies ist ein OpenPGP Schlüssel der Version 3, welche hinfällig sind und nicht weiter unterstützt werden!</string>
<string name="msg_kc_error_no_uid">Schlüsselbund hat keine gültigen User-IDs!</string>
<string name="msg_kc_error_master_algo">Der Hauptschlüssel verwendet einen unbekannten (%s) Algorithmus!</string>
- <string name="msg_kc_error_dup_key">Unterschlüssel %s kommt zweimal im Schlüsselbund vor. Schlüsselbund ist fehlerhaft, wird nicht importiert!</string>
- <string name="msg_kc_master">Verarbeite Hauptschlüssel</string>
+ <string name="msg_kc_error_dup_key">Unterschlüssel %s kommt zweimal im Schlüsselbund vor. Schlüsselbund ist fehlerhaft und wird nicht importiert!</string>
+ <string name="msg_kc_master">Hauptschlüssel wird verarbeitet</string>
<string name="msg_kc_master_bad_type">Hauptschlüsselbeglaubigung unbekannter Art wird entfernt (%s)</string>
- <string name="msg_kc_master_bad_local">Entferne Hauptschlüsselbeglaubigung mit \'Lokal\'-Attribut</string>
+ <string name="msg_kc_master_bad_local">Hauptschlüsselbeglaubigung mit \'Lokal\'-Attribut wird entfernt</string>
<string name="msg_kc_master_bad_err">Fehlerhafte Hauptschlüsselbeglaubigung wird entfernt</string>
<string name="msg_kc_master_bad_time">Schlüsselbund-Widerrufszertifikat mit zukünftigem Zeitstempel wird entfernt</string>
<string name="msg_kc_master_bad_type_uid">User-ID-Beglaubigung an falscher Position wird entfernt</string>
<string name="msg_kc_master_bad">Fehlerhafte Hauptschlüsselbeglaubigung wird entfernt</string>
- <string name="msg_kc_master_local">Entferne Hauptschlüsselbeglaubigung mit \'Lokal\'-Attribut</string>
- <string name="msg_kc_revoke_dup">Entferne redundante Schlüsselbund-Widerrufszertifikat</string>
+ <string name="msg_kc_master_local">Hauptschlüsselbeglaubigung mit \'Lokal\'-Attribut wird entfernt</string>
+ <string name="msg_kc_revoke_dup">Entferne redundantes Schlüsselbund-Widerrufszertifikat</string>
<string name="msg_kc_notation_dup">Entferne redundante Vermerk-Beglaubigung</string>
<string name="msg_kc_notation_empty">Entferne leere Vermerk-Beglaubigung</string>
<string name="msg_kc_sub">Verarbeite Unterschlüssel %s</string>
<string name="msg_kc_sub_bad">Entferne ungültige Unterschlüssel-Zwischenbeglaubigung</string>
<string name="msg_kc_sub_bad_err">Entferne fehlerhafte Unterschlüssel-Zwischenbeglaubigung</string>
- <string name="msg_kc_sub_bad_local">Entferne Unterschlüssel-Zwischenbeglaubigung mit \"Lokal\"-Attribut</string>
- <string name="msg_kc_sub_bad_keyid">Ungleiche Zwischenausstellerkennung beim Unterschlüssels</string>
+ <string name="msg_kc_sub_bad_local">Zwischenbeglaubigung des Unterschlüssels mit \"Lokal\"-Attribut wird entfernt</string>
+ <string name="msg_kc_sub_bad_keyid">Unterschlüssel-Zwischenausstellerkennung stimmt nicht überein</string>
<string name="msg_kc_sub_bad_time">Entferne Unterschlüssel-Zwischenbeglaubigung mit zukünftigem Zeitstempel</string>
- <string name="msg_kc_sub_bad_time_early">Zwischenbeglaubigung des Unterschlüssels hat früheren Zeitstempel als sein Schlüssel!</string>
- <string name="msg_kc_sub_bad_type">Unbekannte Unterschlüsselbeglaubigungart: %s</string>
- <string name="msg_kc_sub_dup">Entferne redundante Unterschlüssel-Zwischenbeglaubigung</string>
+ <string name="msg_kc_sub_bad_time_early">Die Unterschlüssel-Zwischenbeglaubigung hat einen früheren Zeitstempel als sein Hauptschlüssel!</string>
+ <string name="msg_kc_sub_bad_type">Unbekannte Unterschlüsselbeglaubigungsart: %s</string>
+ <string name="msg_kc_sub_dup">Entferne redundate Unterschlüssel-Zwischenbeglaubigung</string>
<string name="msg_kc_sub_primary_bad">Entferne Unterschlüssel-Zwischenbeglaubigung aufgrund ungültiger primärer Zwischenbeglaubigung</string>
<string name="msg_kc_sub_primary_bad_err">Entferne Unterschlüssel-Zwischenbeglaubigung aufgrund fehlerhafter primärer Zwischenbeglaubigung</string>
<string name="msg_kc_sub_primary_none">Entferne Unterschlüssel-Zwischenbeglaubigung aufgrund fehlender primärer Zwischenbeglaubigung</string>
@@ -779,19 +867,19 @@
<string name="msg_kc_sub_revoke_dup">Entferne redundantes Unterschlüssel-Widerrufszertifikat</string>
<string name="msg_kc_sub_unknown_algo">Unterschlüssel verwendet unbekannten Algorithmus, wird nicht importiert...</string>
<string name="msg_kc_sub_algo_bad_encrpyt">Der Unterschlüssel soll für die Verschlüsselung genutzt werden, der zu verwendende Algorithmus unterstützt dies jedoch nicht.</string>
- <string name="msg_kc_sub_algo_bad_sign">Der Unterschlüssel soll zum Unterschreiben genutzt werden, der zu verwendende Algorithmus unterstützt dies jedoch nicht.</string>
- <string name="msg_kc_success">Schlüsselbund wurde erfolgreich in vorschriftsgemäße Form gebracht, keine Änderungen</string>
+ <string name="msg_kc_sub_algo_bad_sign">Der Unterschlüssel soll zum Signieren genutzt werden, der zu verwendende Algorithmus unterstützt dies jedoch nicht.</string>
+ <string name="msg_kc_success">Schlüsselbund wurde erfolgreich in vorschriftsmäßiges Format gebracht, keine Änderungen</string>
<plurals name="msg_kc_success_bad">
- <item quantity="one">Schlüsselbund wurde erfolgreich in vorschriftsgemäße Form gebracht, eine fehlerhafte Beglaubigung entfernt</item>
- <item quantity="other">Schlüsselbund wurde erfolgreich in vorschriftsgemäße Form gebracht, %d fehlerhafte Beglaubigungen entfernt</item>
+ <item quantity="one">Schlüsselbund wurde erfolgreich in vorschriftsmäßiges Format gebracht, eine fehlerhafte Beglaubigung wurde entfernt</item>
+ <item quantity="other">Schlüsselbund wurde erfolgreich in vorschriftsmäßiges Format gebracht, %d fehlerhafte Beglaubigungen wurden entfernt</item>
</plurals>
- <string name="msg_kc_success_bad_and_red">Schlüsselbund wurde erfolgreich in vorschriftsgemäße Form gebracht, %1$s fehlerhafte und %2$s redundante Beglaubigungen entfernt</string>
+ <string name="msg_kc_success_bad_and_red">Schlüsselbund wurde erfolgreich in vorschriftsmäßiges Format gebracht, %1$s fehlerhafte und %2$s redundante Beglaubigungen wurden entfernt</string>
<plurals name="msg_kc_success_redundant">
- <item quantity="one">Schlüsselbund wurde erfolgreich in vorschriftsgemäße Form gebracht, eine redundante Beglaubigung entfernt</item>
- <item quantity="other">Schlüsselbund wurde erfolgreich in vorschriftsgemäße Form gebracht, %d redundante Beglaubigungen entfernt</item>
+ <item quantity="one">Schlüsselbund wurde erfolgreich in vorschriftsmäßiges Format gebracht, eine redundante Beglaubigung wurde entfernt</item>
+ <item quantity="other">Schlüsselbund wurde erfolgreich in vorschriftsmäßiges Format gebracht, %d redundante Beglaubigungen wurden entfernt</item>
</plurals>
<string name="msg_kc_uid_bad_err">Fehlerhafte Eigenbeglaubigung für User-ID \'%s\' wird entfernt</string>
- <string name="msg_kc_uid_bad_local">Entferne User-ID-Beglaubigung mit \'Lokal\'-Attribut</string>
+ <string name="msg_kc_uid_bad_local">User-ID-Beglaubigung mit \'Lokal\'-Attribut wird entfernt</string>
<string name="msg_kc_uid_bad_time">User-ID mit zukünftigem Zeitstempel wird entfernt</string>
<string name="msg_kc_uid_bad_type">User-ID-Beglaubigung unbekannter Art wird entfernt (%s)</string>
<string name="msg_kc_uid_bad">Fehlerhafte Eigenbeglaubigung für User-ID \'%s\' wird entfernt</string>
@@ -802,13 +890,13 @@
<string name="msg_kc_uid_no_cert">Keine gültige Eigenbeglaubigung für User-ID \'%s\' gefunden, wird aus Schlüsselbund entfernt</string>
<string name="msg_kc_uid_remove">Ungültige User-ID \'%s\' wird entfernt</string>
<string name="msg_kc_uid_dup">Doppelte User-ID \'%s\' wird entfernt. Der Schlüsselbund enthielt zwei davon. Hieraus könnten fehlende Beglaubigungen resultieren!</string>
- <string name="msg_kc_uid_warn_encoding">Benutzerkennung nicht als UTF-8 bestätigt!</string>
- <string name="msg_kc_uat_jpeg">Das Benutzerattribut JPEG wird verarbeitet</string>
- <string name="msg_kc_uat_unknown">Ein unbekanntes Benutzerattribut wird verarbeitet</string>
+ <string name="msg_kc_uid_warn_encoding">User-ID nicht als UTF-8 verifiziert!</string>
+ <string name="msg_kc_uat_jpeg">JPEG-Benutzerattribut wird verarbeitet</string>
+ <string name="msg_kc_uat_unknown">Unbekanntes Benutzerattribut wird verarbeitet</string>
<string name="msg_kc_uat_bad_err">Entferne fehlerhafte Eigenbeglaubigung für Benutzerattribut</string>
- <string name="msg_kc_uat_bad_local">Entferne Benutzerattributs-Beglaubigung mit \'Lokal\'-Attribut</string>
- <string name="msg_kc_uat_bad_time">Entferne fehlerhaftes Benutzerattribute mit zukünftigem Zeitstempel</string>
- <string name="msg_kc_uat_bad_type">Entferne Benutzerattributbeglaubigung unbekannter Art (%s)</string>
+ <string name="msg_kc_uat_bad_local">Benutzerattributsbeglaubigung mit \'Lokal\'-Attribut wird entfernt</string>
+ <string name="msg_kc_uat_bad_time">Entferne Benutzerattribut mit zukünftigem Zeitstempel</string>
+ <string name="msg_kc_uat_bad_type">Entferne Benutzerattributsbeglaubigung unbekannter Art (%s)</string>
<string name="msg_kc_uat_bad">Entferne fehlerhafte Eigenbeglaubigung für Benutzerattribut</string>
<string name="msg_kc_uat_cert_dup">Entferne abgelaufene Eigenbeglaubigung für Benutzerattribut</string>
<string name="msg_kc_uat_dup">Doppeltes Benutzerattribut wird entfernt. Der Schlüsselbund enthielt zwei davon. Hieraus könnten fehlende Beglaubigungen resultieren!</string>
@@ -817,64 +905,71 @@
<string name="msg_kc_uat_revoke_old">Entferne abgelaufenes Widerrufszertifikat der Benutzerattribute</string>
<string name="msg_kc_uat_no_cert">Keine gültige Eigenbeglaubigung für das Benutzerattribut gefunden, wird aus Schlüsselbund entfernt</string>
<string name="msg_kc_uat_remove">Ungültiges Benutzerattribut wird entfernt</string>
- <string name="msg_kc_uat_warn_encoding">Benutzerkennung nicht als UTF-8 bestätigt!</string>
+ <string name="msg_kc_uat_warn_encoding">User-ID nicht als UTF-8 verifiziert!</string>
<!--Keyring merging log entries-->
- <string name="msg_mg_error_secret_dummy">Neuer öffentlicher Unterschlüssel gefunden, aber Erstellung von geheimen Unterschlüsseldummys wird nicht unterstützt!</string>
+ <string name="msg_mg_error_secret_dummy">Neuer öffentlicher Unterschlüssel gefunden, aber Erzeugung von privaten Unterschlüsseldummys wird nicht unterstützt!</string>
<string name="msg_mg_error_heterogeneous">Versuch Schlüsselbünde mit unterschiedlichen Fingerabdrücken zusammenzuführen!</string>
<string name="msg_mg_error_encode">Schwerer Fehler bei Kodierung der Signatur!</string>
<string name="msg_mg_public">Wird in öffentlichen Schlüsselbund %s eingefügt
</string>
- <string name="msg_mg_secret">Wird in geheimen Schlüsselbund %s eingefügt</string>
+ <string name="msg_mg_secret">In privaten Schlüsselbund %s einfügen</string>
<string name="msg_mg_new_subkey">Neuer Unterschlüssel %s wird hinzugefügt</string>
<string name="msg_mg_found_new">%s neue Beglaubigungen in Schlüsselbund gefunden</string>
- <string name="msg_mg_unchanged">Nichts zum zusammenführen</string>
+ <string name="msg_mg_unchanged">Nichts zusammenzuführen</string>
<!--createSecretKeyRing-->
- <string name="msg_cr">Neuer Masterschlüssel wird erzeugt</string>
- <string name="msg_cr_error_no_master">Keine Hauptschlüsseloptionen definiert!</string>
+ <string name="msg_cr">Neuer Hauptschlüssel wird erzeugt</string>
+ <string name="msg_cr_error_no_master">Keine Hauptschlüsseloptionen spezifiziert!</string>
<string name="msg_cr_error_no_user_id">Schlüsselbünde müssen mindestens eine User-ID enthalten!</string>
<string name="msg_cr_error_no_certify">Hauptschlüssel benötigt das Attribut beglaubigen!</string>
<string name="msg_cr_error_null_expiry">Ablaufdatum kann bei Schlüsselerstellung nicht \'gleiche wie vorher\' sein. Dies ist ein Programmierfehler, bitte reiche einen Fehlerbericht ein!</string>
- <string name="msg_cr_error_keysize_512">Schlüsselgröße muss größer/gleich 512 sein!</string>
- <string name="msg_cr_error_no_curve">Keine Schlüsselgröße angegeben. Dies ist ein Progammierfehler, bitte reiche einen Fehlerbericht ein!</string>
- <string name="msg_cr_error_no_keysize">Keine Elliptische Kurve angegeben. Dies ist ein Progammierfehler, bitte reiche einen Fehlerbericht ein!</string>
+ <string name="msg_cr_error_keysize_512">Schlüssellänge muss größer/gleich 512 sein!</string>
+ <string name="msg_cr_error_no_curve">Keine Schlüssellänge spezifiziert! Dies ist ein Progammierfehler, bitte reiche einen Fehlerbericht ein!</string>
+ <string name="msg_cr_error_no_keysize">Keine Elliptische Kurve spezifiziert! Dies ist ein Progammierfehler, bitte reiche einen Fehlerbericht ein!</string>
<string name="msg_cr_error_internal_pgp">Interner OpenPGP Fehler!</string>
<string name="msg_cr_error_unknown_algo">Unbekannter Algorithmus ausgewählt. Dies ist ein Progammierfehler, bitte reiche einen Fehlerbericht ein!</string>
- <string name="msg_cr_error_flags_dsa">Falsche Schlüsselattribute gewählt, DSA kann nicht zum verschlüsseln verwendet werden!</string>
- <string name="msg_cr_error_flags_elgamal">Falsche Schlüsselattribute gewählt, ElGamal kann nicht zum signieren verwendet werden!</string>
- <string name="msg_cr_error_flags_ecdsa">Falsche Schlüsselattribute gewählt, ECDSA kann nicht zum verschlüsseln verwendet werden!</string>
- <string name="msg_cr_error_flags_ecdh">Falsche Schlüsselattribute gewählt, ECDH kann nicht zum signieren verwendet werden!</string>
+ <string name="msg_cr_error_flags_dsa">Falsche Schlüsselattribute ausgewählt, DSA kann nicht zum Verschlüsseln verwendet werden!</string>
+ <string name="msg_cr_error_flags_elgamal">Falsche Schlüsselattribute ausgewählt, ElGamal kann nicht zum Signieren verwendet werden!</string>
+ <string name="msg_cr_error_flags_ecdsa">Falsche Schlüsselattribute ausgewählt, ECDSA kann nicht zum Verschlüsseln verwendet werden!</string>
+ <string name="msg_cr_error_flags_ecdh">Falsche Schlüsselattribute ausgewählt, ECDH kann nicht zum Signieren verwendet werden!</string>
<!--modifySecretKeyRing-->
- <string name="msg_mr">Verändere Schlüsselbund %s</string>
- <string name="msg_mf_divert">Werde für Verschlüsselungsoperationen auf Smartcard umleiten</string>
- <string name="msg_mf_error_divert_serial">Die Seriennummer eines \'Auf Smartcard/NFC umleiten\'-Schlüssels muss 16 Byte lang sein! Dies ist ein Programmierfehler, bitte reiche einen Fehlerbericht ein!</string>
+ <string name="msg_mr">Schlüsselbund %s wird verändert</string>
+ <string name="msg_mf_divert">Kryptographische Vorgänge werden auf Smartcard umgeleitet</string>
+ <string name="msg_mf_error_divert_newsub">Erzeugung neuer Unterschlüssel wird für \'auf Karte umgeleitete\' Hauptschlüssel nicht unterstützt!</string>
+ <string name="msg_mf_error_divert_serial">Die Seriennummer eines \'auf Karte umgeleiteten\' Schlüssels muss 16 Byte lang sein! Dies ist ein Programmierfehler, bitte reiche einen Fehlerbericht ein!</string>
<string name="msg_mf_error_encode">Kodierungsfehler!</string>
<string name="msg_mf_error_fingerprint">Tatsächlicher Fingerabdruck des Schlüssels entspricht nicht dem Erwarteten!</string>
<string name="msg_mf_error_keyid">Keine Schlüssel-ID. Dies ist ein interner Fehler, bitte reiche einen Fehlerbericht ein!</string>
<string name="msg_mf_error_integrity">Interner Fehler, Integritätsprüfung fehlgeschlagen!</string>
- <string name="msg_mf_error_master_none">Keine Hauptbeglaubigung zum arbeiten gefunden! (Alle widerrufen?)</string>
- <string name="msg_mf_error_noexist_primary">Falsche primäre User-ID festgelegt!</string>
- <string name="msg_mf_error_noexist_revoke">Falsche User-ID für Widerruf festgelegt!</string>
+ <string name="msg_mf_error_master_none">Keine Hauptbeglaubigung zum damit Arbeiten gefunden! (Alle widerrufen?)</string>
+ <string name="msg_mf_error_noexist_primary">Falsche primäre User-ID spezifiziert!</string>
+ <string name="msg_mf_error_noexist_revoke">Falsche User-ID für Widerruf spezifiziert!</string>
+ <string name="msg_mf_error_restricted">Versuch einen eingeschränkten Vorgang ohne Passwort auszuführen! Dies ist ein Programmierfehler, bitte reiche einen Fehlerbericht ein!</string>
<string name="msg_mf_error_revoked_primary">Widerrufene User-IDs können nicht primäre IDs sein!</string>
<string name="msg_mf_error_null_expiry">Ablaufdatum kann bei Unterschlüsselerstellung nicht \"identisch wie vorher\" sein. Dies ist ein Programmierfehler, bitte reiche einen Fehlerbericht ein!</string>
<string name="msg_mf_error_noop">Nichts zu machen!</string>
<string name="msg_mf_error_passphrase_master">Schwerer Fehler beim Entschlüsseln des Hauptschlüssels! Dies ist wahrscheinlich ein Programmierfehler, bitte reiche einen Fehlerbericht ein!</string>
<string name="msg_mf_error_pgp">Interner OpenPGP Fehler!</string>
<string name="msg_mf_error_sig">Signaturfehler!</string>
+ <string name="msg_mf_error_sub_stripped">Gekürzter Unterschlüssel %s kann nicht verändert werden!</string>
<string name="msg_mf_error_subkey_missing">Versuch mit fehlendem Unterschlüssel %s zu arbeiten!</string>
+ <string name="msg_mf_error_conflicting_nfc_commands">Der Schlüssel kann nicht im selben Vorgang auf die Smartcard verschoben werden, der auf der Smartcard eine Signatur erzeugt.</string>
<string name="msg_mf_error_duplicate_keytocard_for_slot">Smartcard unterstützt nur einen Slot pro Schlüsseltyp.</string>
- <string name="msg_mf_error_invalid_flags_for_keytocard">Unangebrachte Schlüsselattribute für Schlüssel auf Smartcard.</string>
- <string name="msg_mf_master">Verändere Hauptbeglaubigungen</string>
+ <string name="msg_mf_error_invalid_flags_for_keytocard">Ungeeignete Schlüsselattribute für Schlüssel auf Smartcard.</string>
+ <string name="msg_mf_master">Hauptbeglaubigungen werden verändert</string>
<string name="msg_mf_notation_empty">Füge leeres Vermerk-Paket hinzu</string>
<string name="msg_mf_notation_pin">Füge PIN-Vermerk-Paket hinzu</string>
<string name="msg_mf_passphrase">Passwort für Schlüsselbund wird geändert</string>
+ <string name="msg_mf_pin">PIN auf Karte wird geändert</string>
+ <string name="msg_mf_admin_pin">Admin-PIN auf Karte wird geändert</string>
<string name="msg_mf_passphrase_key">Erneute Verschlüsselung des Unterschlüssels %s mit neuem Passwort</string>
- <string name="msg_mf_passphrase_empty_retry">Setzen eines neuen Passworts fehlgeschlagen, versuche erneut mit leerem altem Passwort</string>
- <string name="msg_mf_passphrase_fail">Passwort für Unterschlüssel konnte nicht geändert werden! (Hat es ein anderes Passwort als die anderen Schlüssel?)</string>
+ <string name="msg_mf_passphrase_empty_retry">Festlegen eines neuen Passworts fehlgeschlagen, erneuter Versuch mit leerem altem Passwort</string>
+ <string name="msg_mf_passphrase_fail">Passwort des Unterschlüssels konnte nicht geändert werden! (Hat er ein anderes Passwort als die anderen Schlüssel?)</string>
<string name="msg_mf_primary_replace_old">Beglaubigung von vorheriger primärer User-ID wird ersetzt</string>
<string name="msg_mf_primary_new">Neue Beglaubigung für neue primäre User-ID wird erzeugt</string>
- <string name="msg_mf_subkey_change">Unterschlüssel %s wird geändert</string>
- <string name="msg_mf_require_divert">Leite für Verschlüsselungsoperationen auf Smartcard um</string>
- <string name="msg_mf_require_passphrase">Passwort für die Vorgänge erforderlich</string>
+ <string name="msg_mf_restricted_mode">Wechsle zu eingeschränktem Vorgangsmodus</string>
+ <string name="msg_mf_subkey_change">Unterschlüssel %s wird verändert</string>
+ <string name="msg_mf_require_divert">Leite Kryptographische Vorgänge auf Smartcard um</string>
+ <string name="msg_mf_require_passphrase">Für die Vorgänge ist ein Passwort erforderlich</string>
<string name="msg_mf_subkey_new">Füge neuen Unterschlüssel vom Typ %s hinzu</string>
<string name="msg_mf_subkey_new_id">Neue Unterschlüsselkennung: %s</string>
<string name="msg_mf_error_past_expiry">Ablaufdatum kann nicht in der Vergangenheit liegen!</string>
@@ -884,31 +979,31 @@
<string name="msg_mf_keytocard_finish">%1$s auf Smartcard %2$s verschoben</string>
<string name="msg_mf_success">Schlüsselbund erfolgreich verändert</string>
<string name="msg_mf_uid_add">User-ID %s wird hinzugefügt</string>
- <string name="msg_mf_uid_primary">Primäre User-ID wird geändert zu %s</string>
+ <string name="msg_mf_uid_primary">Primäre User-ID wird geändert in %s</string>
<string name="msg_mf_uid_revoke">Widerrufe User-ID %s</string>
<string name="msg_mf_uid_error_empty">User-ID darf nicht leer sein!</string>
<string name="msg_mf_uat_error_empty">Benutzerattribut darf nicht leer sein!</string>
- <string name="msg_mf_uat_add_image">Benutzerattribut vom Typ Bild wird hinzugefügt</string>
- <string name="msg_mf_uat_add_unknown">Benutzerattribut unbekannter Art wird hinzugefügt</string>
+ <string name="msg_mf_uat_add_image">Bild-Benutzerattribut wird hinzugefügt</string>
+ <string name="msg_mf_uat_add_unknown">Unbekannter Benutzerattributstyp wird hinzugefügt</string>
<string name="msg_mf_unlock_error">Fehler beim entsperren des Schlüsselbunds</string>
<string name="msg_mf_unlock">Schlüsselbund wird entsperrt</string>
<!--Consolidate-->
<string name="msg_con">Datenbank wird zusammengeführt</string>
- <string name="msg_con_error_bad_state">Zusammenführung wurde gestartet während keine Datenbank zwischengespeichert war! Dies ist wahrscheinlich ein Programmierfehler, bitte reiche einen Fehlerbericht ein!</string>
- <string name="msg_con_error_concurrent">Zusammenführung abgebrochen, läuft bereits auf einem anderen Thread!</string>
- <string name="msg_con_save_secret">Geheime Schlüsselbünde werden gespeichert</string>
+ <string name="msg_con_error_bad_state">Zusammenführung wurde gestartet, während keine Datenbank zwischengespeichert war! Dies ist wahrscheinlich ein Programmierfehler, bitte reiche einen Fehlerbericht ein!</string>
+ <string name="msg_con_error_concurrent">Zusammenführung abgebrochen, läuft bereits in einem anderen Thread!</string>
+ <string name="msg_con_save_secret">Private Schlüsselbünde werden gespeichert</string>
<string name="msg_con_save_public">Öffentliche Schlüsselbünde werden gespeichert</string>
<string name="msg_con_db_clear">Datenbank wird geleert</string>
<string name="msg_con_success">Datenbank erfolgreich zusammengeführt!</string>
<string name="msg_con_critical_in">Beginne kritische Phase!</string>
<string name="msg_con_critical_out">Verlasse kritische Phase</string>
- <string name="msg_con_delete_public">Lösche Cache-Datei des öffentlichen Schlüsselbundes</string>
- <string name="msg_con_delete_secret">Lösche Cache-Datei des geheimen Schlüsselbundes</string>
+ <string name="msg_con_delete_public">Lösche Zwischenspeicherdatei des öffentlichen Schlüsselbundes</string>
+ <string name="msg_con_delete_secret">Lösche Zwischenspeicherdatei des privaten Schlüsselbundes</string>
<string name="msg_con_error_db">Fehler bei der Öffnung der Datenbank!</string>
- <string name="msg_con_error_io_public">Ein-/Ausgabefehler beim Schreiben von öffentlichen Schlüsseln in den Cache!</string>
- <string name="msg_con_error_io_secret">Ein-/Ausgabefehler beim Schreiben von geheimen Schlüsseln in den Cache!</string>
- <string name="msg_con_error_public">Fehler beim reimportieren der öffentlichen Schlüssel!</string>
- <string name="msg_con_error_secret">Fehler beim reimportieren der geheimen Schlüssel!</string>
+ <string name="msg_con_error_io_public">Ein-/Ausgabefehler beim Schreiben von öffentlichen Schlüsseln in den Zwischenspeicher!</string>
+ <string name="msg_con_error_io_secret">Ein-/Ausgabefehler beim Schreiben von privaten Schlüsseln in den Zwischenspeicher!</string>
+ <string name="msg_con_error_public">Fehler beim Reimportieren der öffentlichen Schlüssel!</string>
+ <string name="msg_con_error_secret">Fehler beim reimportieren der privaten Schlüssel!</string>
<string name="msg_con_recover">Zusammenführungsvorgang wird fortgesetzt</string>
<string name="msg_con_recursive">Rekursive Zusammenführung wird übersprungen</string>
<string name="msg_con_recover_unknown">Zusammenführungsvorgang aus unbekanntem Zustand wird fortgesetzt</string>
@@ -918,33 +1013,36 @@
</plurals>
<string name="msg_con_reimport_public_skip">Keine öffentlichen Schlüssel für Reimport, überspringe...</string>
<plurals name="msg_con_reimport_secret">
- <item quantity="one">Reimportiere einen geheimen Schlüssel</item>
- <item quantity="other">Reimportiere %d geheime Schlüssel</item>
+ <item quantity="one">Reimportiere einen privaten Schlüssel</item>
+ <item quantity="other">Reimportiere %d private Schlüssel</item>
</plurals>
- <string name="msg_con_reimport_secret_skip">Keine geheimen Schlüssel für Reimport, überspringe...</string>
- <string name="msg_con_warn_delete_public">Fehler beim Löschen der Öffentlichen Cache-Datei</string>
- <string name="msg_con_warn_delete_secret">Fehler beim Löschen der Geheimen Cache-Datei</string>
+ <string name="msg_con_reimport_secret_skip">Keine privaten Schlüssel für Reimport, überspringe...</string>
+ <string name="msg_con_warn_delete_public">Ausnahmefehler beim Löschen der öffentlichen Zwischenspeicherdatei</string>
+ <string name="msg_con_warn_delete_secret">Ausnahmefehler beim Löschen der privaten Zwischenspeicherdatei</string>
<!--Edit Key (higher level than modify)-->
- <string name="msg_ed">Schlüsselvorgang wird durchgeführt</string>
+ <string name="msg_ed">Schlüsselvorgang wird ausgeführt</string>
<string name="msg_ed_caching_new">Neues Passwort wird zwischengespeichert</string>
<string name="msg_ed_error_no_parcel">\"SaveKeyringParcel\" fehlt! (Dies ist ein Fehler, bitte reiche einen Fehlerbericht ein!)</string>
<string name="msg_ed_error_key_not_found">Schlüssel nicht gefunden!</string>
- <string name="msg_ed_fetching">Zu ändernder Schlüssel wird abgerufen (%s)</string>
+ <string name="msg_ed_error_extract_public_upload">Fehler beim Extrahieren des öffentlichen Schlüssels fürs Hochladen!</string>
+ <string name="msg_ed_fetching">Zu bearbeitender Schlüssel wird abgerufen (%s)</string>
<string name="msg_ed_success">Schlüsselvorgang erfolgreich</string>
<!--Promote key-->
- <string name="msg_pr">Befördere öffentlichen Schlüssel zum geheimen Schlüssel</string>
+ <string name="msg_pr">Öffentlicher Schlüssel zu privatem Schlüssel hochgestuft</string>
+ <string name="msg_pr_all">Stufe alle Unterschlüssel hoch</string>
<string name="msg_pr_error_key_not_found">Schlüssel nicht gefunden!</string>
- <string name="msg_pr_fetching">Zu ändernder Schlüssel wird abgerufen (%s)</string>
+ <string name="msg_pr_fetching">Zu bearbeitender Schlüssel wird abgerufen (%s)</string>
+ <string name="msg_pr_subkey_match">Stufe Unterschlüssel hoch: %s</string>
<string name="msg_pr_subkey_nomatch">Unterschlüssel nicht auf YubiKey: %s</string>
- <string name="msg_pr_success">Schlüssel erfolgreich befördert</string>
+ <string name="msg_pr_success">Schlüssel erfolgreich hochgestuft</string>
<!--Other messages used in OperationLogs-->
- <string name="msg_ek_error_dummy">Kann Schlüsselbund nicht mit gekürztem Hauptschlüssel bearbeiten!</string>
+ <string name="msg_ek_error_dummy">Schlüsselbund mit gekürztem Hauptschlüssel kann nicht bearbeitet werden!</string>
<string name="msg_ek_error_not_found">Schlüssel nicht gefunden!</string>
<!--Messages for DecryptVerify operation-->
<string name="msg_dc_askip_no_key">Daten mit unbekanntem Schlüssel verschlüsselt, überspringe...</string>
<string name="msg_dc_askip_not_allowed">Daten mit nicht zugelassenem Schlüssel verschlüsselt, überspringe...</string>
<string name="msg_dc_asym">Block asymmetrisch verschlüsselter Daten für Schlüssel %s gefunden</string>
- <string name="msg_dc_charset">Ein Zeichensatz-Header wurde gefunden: \'%s\'</string>
+ <string name="msg_dc_charset">Zeichensatz-Header gefunden: \'%s\'</string>
<string name="msg_dc_clear_data">Verarbeite Klartextdaten</string>
<string name="msg_dc_clear_decompress">Entpacke komprimierte Daten</string>
<string name="msg_dc_clear_meta_file">Dateiname: %s</string>
@@ -953,35 +1051,39 @@
<string name="msg_dc_clear_meta_size_unknown">Dateigröße unbekannt</string>
<string name="msg_dc_clear_meta_time">Änderungszeit: %s</string>
<string name="msg_dc_clear_signature_bad">Signaturprüfung NICHT OK!</string>
- <string name="msg_dc_insecure_hash_algo">Nicht unterstützter und potentiell unsicherer Hash-Algorithmus!</string>
- <string name="msg_dc_clear_signature_check">Signaturdaten werden überprüft</string>
+ <string name="msg_dc_clear_signature_check">Signaturdaten werden verifiziert</string>
<string name="msg_dc_clear_signature_ok">Signaturprüfung OK</string>
<string name="msg_dc_clear_signature">Speichere Signatur für später</string>
<string name="msg_dc_clear">Verarbeite Klartextdaten</string>
<string name="msg_dc_error_bad_passphrase">Fehler beim Entsperren des Schlüssels, falsches Passwort!</string>
+ <string name="msg_dc_error_sym_passphrase">Fehler beim Entschlüsseln der Daten, falsche Passphrase?</string>
<string name="msg_dc_error_corrupt_data">Daten beschädigt!</string>
<string name="msg_dc_error_extract_key">Unbekannter Fehler bei Schlüsselentsperrung!</string>
<string name="msg_dc_error_integrity_check">Integritätsprüfungsfehler!</string>
- <string name="msg_dc_insecure_mdc_missing">Fehlende Integritätsprüfung Dies kann passieren, wenn die Verschlüsselungsanwendung veraltet ist oder durch einen Downgrade-Angriff.</string>
- <string name="msg_dc_error_invalid_data">Kein gültiger OpenPGP-verschlüsselter oder -signierter Inhalt!</string>
- <string name="msg_dc_error_no_data">Keine verschlüsselten Daten in Datenstrom gefunden!</string>
- <string name="msg_dc_error_no_key">Keine verschlüsselten Daten mit bekanntem geheimen Schlüssel in Datenstrom gefunden!</string>
- <string name="msg_dc_error_pgp_exception">Es ist ein OpenPGP-Ausnahmefehler während des Vorgangs aufgetreten!</string>
+ <string name="msg_dc_error_invalid_data">Kein gültiger OpenPGP-verschlüsselter oder -signierter Inhalt gefunden!</string>
+ <string name="msg_dc_error_io">Beim Einlesen der Eingangsdaten ist ein Fehler aufgetreten!</string>
+ <string name="msg_dc_error_input">Fehler beim Öffnen des eingehenden Datenstroms!</string>
+ <string name="msg_dc_error_no_data">Keine verschlüsselten Daten im Datenstrom gefunden!</string>
+ <string name="msg_dc_error_no_key">Keine verschlüsselten Daten mit bekanntem privatem Schlüssel im Datenstrom gefunden!</string>
+ <string name="msg_dc_error_pgp_exception">Während eines Vorgangs ist ein OpenPGP-Ausnahmefehler aufgetreten!</string>
<string name="msg_dc_integrity_check_ok">Integritätsprüfung OK!</string>
<string name="msg_dc_ok_meta_only">Es wurden nur Metadaten angefragt, überspringe Entschlüsselung</string>
- <string name="msg_dc_ok">Entschlüsselung/Überprüfung abgeschlossen</string>
+ <string name="msg_dc_ok">Entschlüsselung/Verifikation abgeschlossen</string>
<string name="msg_dc_pass_cached">Passwort aus Zwischenspeicher verwenden</string>
- <string name="msg_dc_pending_nfc">NFC-Token benötigt, verlange Benutzereingabe...</string>
+ <string name="msg_dc_pending_nfc">NFC-Token benötigt, Benutzereingabe wird angefordert…</string>
<string name="msg_dc_pending_passphrase">Passwort erforderlich, Benutzereingabe wird angefordert…</string>
- <string name="msg_dc_prep_streams">Bereite Datenkette </string>
+ <string name="msg_dc_prep_streams">Bereite Datenströme zur Entschlüsselung vor</string>
<string name="msg_dc">Starte Entschlüsselungsvorgang...</string>
<string name="msg_dc_sym_skip">Symmetrische Daten nicht erlaubt, überspringe...</string>
<string name="msg_dc_sym">Block symmetrisch verschlüsselter Daten gefunden</string>
<string name="msg_dc_trail_asym">Anhängende, asymmetrisch verschlüsselte Daten für Schlüssel %s gefunden</string>
- <string name="msg_dc_trail_sym">Anhang gefunden, symmetrisch verschlüsselte Daten</string>
+ <string name="msg_dc_trail_sym">Anhängende, symmetrisch verschlüsselte Daten gefunden</string>
<string name="msg_dc_trail_unknown">Anhängende Daten unbekannter Art gefunden</string>
- <string name="msg_dc_unlocking">Geheimer Schlüssel wird entsperrt</string>
- <string name="msg_dc_insecure_symmetric_encryption_algo">Ein potentiell unsicherer Verschlüsselungsalgorithmus wurde verwendet!</string>
+ <string name="msg_dc_unlocking">Privater Schlüssel wird entsperrt</string>
+ <string name="msg_dc_insecure_symmetric_encryption_algo">Es wurde ein unsicherer Verschlüsselungsalgorithmus verwendet! Das kann vorkommen wenn die Anwendung veraltet ist, oder durch einen Angriff.</string>
+ <string name="msg_dc_insecure_hash_algo">Es wurde ein unsicherer Hash-Algorithmus verwendet! Das kann vorkommen wenn die Anwendung veraltet ist, oder durch einen Angriff.</string>
+ <string name="msg_dc_insecure_mdc_missing">Modifikationserkennungscode-Paket (engl. MDC packet) fehlt! Das kann passieren wenn die Verschlüsselungsanwendung veraltet ist, oder durch einen Zurückstufungsangriff.</string>
+ <string name="msg_dc_insecure_key">Unsicherer Schlüssel: Entweder ist die Bitlänge von RSA/DSA/ElGamal zu kurz oder die ECC-Kurve bzw. der ECC-Algorithmus wird als unsicher angesehen! Das kann vorkommen wenn die Anwendung veraltet ist, oder durch einen Angriff.</string>
<!--Messages for VerifySignedLiteralData operation-->
<string name="msg_vl">Starte Signaturprüfung</string>
<string name="msg_vl_error_no_siglist">Keine Signaturliste in signierten Literaldaten</string>
@@ -991,38 +1093,37 @@
<string name="msg_vl_clear_meta_mime">MIME-Typ: %s</string>
<string name="msg_vl_clear_meta_time">Änderungszeit: %s</string>
<string name="msg_vl_clear_meta_size">Dateigröße: %s</string>
- <string name="msg_vl_clear_signature_check">Signaturdaten werden überprüft</string>
+ <string name="msg_vl_clear_signature_check">Signaturdaten werden verifiziert</string>
<string name="msg_vl_error_integrity_check">Integritätsprüfung fehlgeschlagen!</string>
<string name="msg_vl_ok">OK</string>
<!--Messages for SignEncrypt operation-->
<string name="msg_se">Starte Signier-/Verschlüsselungsvorgang</string>
<string name="msg_se_input_bytes">Verarbeite Eingabe aus Bytearray</string>
- <string name="msg_se_input_uri">Verarbeite Eingabe von URI</string>
- <string name="msg_se_error_no_input">Keine Eingabe gegeben!</string>
- <string name="msg_se_error_input_uri_not_found">Fehler beim öffnen der URI zum lesen!</string>
- <string name="msg_se_error_output_uri_not_found">Fehler beim öffnen der URI zum schreiben!</string>
- <string name="msg_se_error_too_many_inputs">Mehr Eingaben als Ausgaben angegeben! Dies ist vermutlich ein Programmierfehler, diesen bitte melden!</string>
- <string name="msg_se_success">Signier-/Verschlüsselungsvorgang erfolgreich!</string>
+ <string name="msg_se_input_uri">Verarbeite Eingabe aus URI</string>
+ <string name="msg_se_error_no_input">Keine Eingabe vorhanden!</string>
+ <string name="msg_se_error_input_uri_not_found">Fehler beim Öffnen des URI zum Lesen!</string>
+ <string name="msg_se_error_output_uri_not_found">Fehler beim Öffnen des URI zum Schreiben!</string>
+ <string name="msg_se_error_too_many_inputs">Mehr Eingaben als Ausgaben spezifiziert! Dies ist vermutlich ein Programmierfehler, diesen bitte melden!</string>
+ <string name="msg_se_success">Signier-/Verschlüsselungsvorgang erfolgreich</string>
<!--Messages for PgpSignEncrypt operation-->
<string name="msg_pse_asymmetric">Bereite öffentliche Schlüssel für Verschlüsselung vor</string>
<string name="msg_pse_clearsign_only">Signieren von Klartexteingaben wird nicht unterstützt!</string>
<string name="msg_pse_compressing">Bereite Kompression vor</string>
<string name="msg_pse_encrypting">Daten werden verschlüsselt</string>
<string name="msg_pse_error_bad_passphrase">Falsches Passwort!</string>
- <string name="msg_pse_error_hash_algo">Angeforderter Hash-Algorithmus wird von diesem Schlüssel nicht unterstützt!</string>
- <string name="msg_pse_error_io">Ein-/Ausgabefehler während Vorgang aufgetreten!</string>
- <string name="msg_pse_error_key_sign">Gewählter Signaturschlüssel kann keine Daten signieren!</string>
+ <string name="msg_pse_error_io">Während eines Vorgangs ist ein Ein-/Ausgabefehler aufgetreten!</string>
+ <string name="msg_pse_error_key_sign">Ausgewählter Signaturschlüssel kann keine Daten signieren!</string>
<string name="msg_pse_error_sign_key">Fehler bei Abruf des Signaturschlüssels!</string>
<string name="msg_pse_error_nfc">NFC-Datenfehler!</string>
<string name="msg_pse_error_no_passphrase">Kein Passwort angegeben!</string>
<string name="msg_pse_error_pgp">Interner OpenPGP Fehler!</string>
- <string name="msg_pse_error_sig">OpenPGP-Signaturfehler aufgetreten!</string>
+ <string name="msg_pse_error_sig">Während eines Vorgang ist ein OpenPGP-Signatur-Ausnahmefehler aufgetreten!</string>
<string name="msg_pse_error_unlock">Unbekannter Fehler bei Schlüsselentsperrung!</string>
<string name="msg_pse_key_ok">Verschlüssele für Schlüssel: %s</string>
<string name="msg_pse_key_unknown">Fehlender Schlüssel für Verschlüsselung: %s</string>
- <string name="msg_pse_key_warn">Falscher Schlüssel für Verschlüsselung: %s</string>
+ <string name="msg_pse_key_warn">Fehlerhafter Schlüssel für Verschlüsselung: %s</string>
<string name="msg_pse_ok">Signierungs-/Verschlüsselungsvorgang erfolgreich!</string>
- <string name="msg_pse_pending_nfc">NFC-Token benötigt, verlange Benutzereingabe...</string>
+ <string name="msg_pse_pending_nfc">NFC-Token benötigt, Benutzereingabe wird angefordert…</string>
<string name="msg_pse_pending_passphrase">Passwort erforderlich, Benutzereingabe wird angefordert…</string>
<string name="msg_pse_signing">Signiere Daten (ohne Verschlüsselung)</string>
<string name="msg_pse_signing_cleartext">Erstelle Klartextsignatur</string>
@@ -1052,7 +1153,8 @@
<string name="msg_crt_success">Identitäten erfolgreich beglaubigt</string>
<string name="msg_crt_warn_not_found">Schlüssel nicht gefunden!</string>
<string name="msg_crt_warn_cert_failed">Erzeugen der Beglaubigung fehlgeschlagen!</string>
- <string name="msg_crt_warn_save_failed">Speichern fehlgeschlagen!</string>
+ <string name="msg_crt_warn_save_failed">Speichervorgang fehlgeschlagen!</string>
+ <string name="msg_crt_warn_upload_failed">Hochladevorgang fehlgeschlagen!</string>
<string name="msg_crt_upload_success">Schlüssel wurde erfolgreich hochgeladen</string>
<plurals name="msg_import">
<item quantity="one">Schlüssel wird importiert</item>
@@ -1061,43 +1163,47 @@
<string name="msg_import_fetch_error_decode">Fehler beim Dekodieren des abgerufenen Schlüsselbundes!</string>
<string name="msg_import_fetch_error">Schlüssel konnte nicht abgerufen werden! (Netzwerkprobleme?)</string>
<string name="msg_import_fetch_keybase">Empfange von keybase.io: %s</string>
- <string name="msg_import_fetch_keyserver_error">Konnte Schlüssel nicht von Keyserver abrufen: %s</string>
- <string name="msg_import_fetch_keyserver">Von einem Schlüsselserver abrufen: %s</string>
- <string name="msg_import_fetch_keyserver_ok">Schlüsselabruf erfolgreich!</string>
- <string name="msg_import_keyserver">Schlüsselserver %s wird verwendet</string>
+ <string name="msg_import_fetch_error_keyserver">Konnte Schlüssel nicht vom Schlüsselserver abrufen: %s</string>
+ <string name="msg_import_fetch_keyserver">Empfange von Schlüsselserver: %s</string>
+ <string name="msg_import_fetch_keyserver_ok">Schlüssel erfolgreich heruntergeladen</string>
+ <string name="msg_import_keyserver">Verwende Schlüsselserver %s</string>
<string name="msg_import_fingerprint_error">Fingerabdruck des abgerufenen Schlüssels entspricht nicht dem Erwarteten!</string>
<string name="msg_import_fingerprint_ok">Fingerabdrucktest in Ordnung</string>
<string name="msg_import_merge">Abgerufene Daten werden eingefügt</string>
<string name="msg_import_merge_error">Fehler beim Zusammenführen der abgerufenen Daten!</string>
- <string name="msg_import_error">Importieren fehlgeschlagen!</string>
- <string name="msg_import_error_io">Der Import ist aufgrund eines Eingabe/Ausgabe-Fehlers fehlgeschlagen!</string>
+ <string name="msg_import_error">Importvorgang fehlgeschlagen!</string>
+ <string name="msg_import_error_io">Importvorgang ist aufgrund eines Ein-/Ausgabefehlers fehlgeschlagen!</string>
<string name="msg_import_partial">Importvorgang erfolgreich, mit Fehlern!</string>
<string name="msg_import_success">Importvorgang erfolgreich!</string>
<plurals name="msg_export">
- <item quantity="one">Ein Schlüssel wird exportiert</item>
+ <item quantity="one">Schlüssel wird exportiert</item>
<item quantity="other">%d Schlüssel werden exportiert</item>
</plurals>
+ <string name="msg_export_file_name">Dateiname: %s</string>
<string name="msg_export_all">Exportiere alle Schlüssel</string>
<string name="msg_export_public">Exportiere öffentlichen Schlüssel %s</string>
+ <string name="msg_export_upload_public">Öffentlicher Schlüssel %s wird hochgeladen</string>
<string name="msg_export_secret">Exportiere privaten Schlüssel %s</string>
- <string name="msg_export_error_no_file">Kein Dateiname angegeben!</string>
+ <string name="msg_export_error_no_file">Kein Dateiname spezifiziert!</string>
<string name="msg_export_error_fopen">Fehler beim Öffnen der Datei !</string>
- <string name="msg_export_error_no_uri">Keine URI angegeben!</string>
+ <string name="msg_export_error_no_uri">Keine URI spezifiziert!</string>
<string name="msg_export_error_uri_open">Fehler beim Öffnen des URI-Streams!</string>
<string name="msg_export_error_storage">Speicher ist nicht Schreibbereit !</string>
<string name="msg_export_error_db">Datenbankfehler!</string>
<string name="msg_export_error_io">Eingabe/Ausgabe Fehler!</string>
<string name="msg_export_error_key">Fehlber bei der Vorverarbeitung der Schlüsseldaten!</string>
+ <string name="msg_export_error_upload">Fehler beim Hochladen des Schlüssels zum Server! Bitte überprüfe deine Internetverbindung</string>
<string name="msg_export_success">Exportvorgang erfolgreich!</string>
+ <string name="msg_export_upload_success">Hochladen auf Schlüsselserver erfolgreich</string>
<string name="msg_del_error_empty">Nichts zu löschen!</string>
- <string name="msg_del_error_multi_secret">Geheime Schlüssel können nur einzeln gelöscht werden!</string>
+ <string name="msg_del_error_multi_secret">Private Schlüssel können nur einzeln gelöscht werden!</string>
<plurals name="msg_del">
<item quantity="one">Schlüssel wird gelöscht</item>
<item quantity="other">%d Schlüssel werden gelöscht</item>
</plurals>
<string name="msg_del_key">Lösche Schlüssel %s</string>
<string name="msg_del_key_fail">Fehler beim Löschen von Schlüssel %s</string>
- <string name="msg_del_consolidate">Datenbank wird nach Löschung des geheimen Schlüssels zusammengeführt</string>
+ <string name="msg_del_consolidate">Datenbank wird nach Löschung des privaten Schlüssels zusammengeführt</string>
<plurals name="msg_del_ok">
<item quantity="one">Schlüssel erfolgreich gelöscht</item>
<item quantity="other">%d Schlüssel erfolgreich gelöscht</item>
@@ -1106,37 +1212,63 @@
<item quantity="one">Fehler beim Löschen eines Schlüssels</item>
<item quantity="other">Fehler beim Löschen von %d Schlüsseln</item>
</plurals>
+ <string name="msg_revoke_error_empty">Nichts zu widerrufen!</string>
+ <string name="msg_revoke_error_not_found">Schlüssel zum Widerrufen nicht gefunden!</string>
+ <string name="msg_revoke_key">Widerrufe Schlüssel %s</string>
+ <string name="msg_revoke_key_fail">Fehler beim Widerrufen des Schlüssels</string>
+ <string name="msg_revoke_ok">Schlüssel erfolgreich widerrufen</string>
<string name="msg_acc_saved">Benutzerkonto gespeichert</string>
<string name="msg_download_success">Erfolgreich heruntergeladen!</string>
<string name="msg_download_no_valid_keys">Keine gültigen Schlüssel in der Datei/Zwischenablage gefunden!</string>
<string name="msg_download_no_pgp_parts">NOCH ZU MACHEN: Plurale!</string>
<plurals name="error_import_non_pgp_part">
- <item quantity="one">Ein Teil der geladenen Datei ist ein gültiges OpenPGP Objekt aber kein OpenPGP Schlüssel</item>
- <item quantity="other">Teile der geladenen Dateien sind gültige OpenPGP Objekte aber keine OpenPGP Schlüssel</item>
+ <item quantity="one">ein Teil der geladenen Datei ist ein gültiges OpenPGP-Objekt, aber kein OpenPGP-Schlüssel</item>
+ <item quantity="other">Teile der geladenen Dateien sind gültige OpenPGP-Objekte, aber keine OpenPGP-Schlüssel</item>
</plurals>
<string name="msg_download_query_too_short">Die Suchanfrage ist zu kurz, bitte die Suchanfrage verfeinern!</string>
<string name="msg_download_too_many_responses">Schlüsselsuchanfrage lieferte zu viele Kandidaten, bitte die Suchanfrage verfeinern!</string>
<string name="msg_download_query_too_short_or_too_many_responses">Entweder keine oder zu viele Schlüssel wurden gefunden, bitte die Suchanfrage prä­zi­sie­ren!</string>
<string name="msg_download_query_failed">Beim Suchen der Schlüssel ist ein Fehler aufgetreten.</string>
<!--Messages for Keybase Verification operation-->
+ <string name="msg_keybase_verification">Versuche Keybase-Verifikation für %s</string>
<string name="msg_keybase_error_no_prover">Kein Nachweis-Prüfer gefunden für %s</string>
<string name="msg_keybase_error_fetching_evidence">Problem beim Holen des Nachweises</string>
<string name="msg_keybase_error_key_mismatch">Schlüssel-Fingerabdruck stimmt nicht mit dem Fingerabdruck im Nachweis überein</string>
+ <string name="msg_keybase_error_dns_fail">Abfrage des DNS-TXT-Eintrags fehlgeschlagen</string>
+ <string name="msg_keybase_error_specific">%s</string>
+ <string name="msg_keybase_error_msg_payload_mismatch">Entschlüsselter Nachweis entspricht nicht dem erwarteten Wert</string>
<!--Messages for Export Log operation-->
<string name="msg_export_log_start">Exportiere Protokoll</string>
<string name="msg_export_log_error_fopen">Fehler beim Öffnen der Datei</string>
- <string name="msg_export_log_error_no_file">Kein Dateiname angegeben!</string>
- <string name="msg_export_log_error_writing">Ein-/Ausgabefehler beim schreiben in die Datei!</string>
+ <string name="msg_export_log_error_no_file">Kein Dateiname spezifiziert!</string>
+ <string name="msg_export_log_error_writing">Ein-/Ausgabefehler beim Schreiben in die Datei!</string>
<string name="msg_export_log_success">Protokoll erfolgreich exportiert!</string>
<!--PassphraseCache-->
+ <string name="passp_cache_notif_click_to_clear">Passwörter löschen</string>
+ <plurals name="passp_cache_notif_n_keys">
+ <item quantity="one">%d Passwort gemerkt</item>
+ <item quantity="other">%d Passwörter gemerkt</item>
+ </plurals>
+ <string name="passp_cache_notif_keys">Gemerkte Passwörter</string>
+ <string name="passp_cache_notif_clear">Passwörter vergessen</string>
<string name="passp_cache_notif_pwd">Passwort</string>
+ <!--Keyserver sync-->
+ <string name="keyserver_sync_orbot_notif_title">Synchronisierung aus der Cloud erfordert Orbot</string>
+ <string name="keyserver_sync_orbot_notif_msg">Zum Starten von Orbot tippen</string>
+ <string name="keyserver_sync_orbot_notif_start">Orbot starten</string>
+ <string name="keyserver_sync_orbot_notif_ignore">Direkt</string>
<!--First Time-->
<string name="first_time_text1">Hol dir deine Privatsphäre mit OpenKeychain zurück!</string>
<string name="first_time_create_key">Meinen Schlüssel erzeugen</string>
<string name="first_time_import_key">Schlüssel aus Datei importieren</string>
<string name="first_time_yubikey">YubiKey NEO verwenden</string>
<string name="first_time_skip">Setup überspringen</string>
+ <string name="first_time_blank_yubikey">Möchtest du diesen leeren YubiKey NEO mit OpenKeychain verwenden?\n\nBitte nimm den YubiKey nun weg, du wirst aufgefordert, wenn er erneut benötigt wird!</string>
<string name="first_time_blank_yubikey_yes">Diesen YubiKey verwenden</string>
+ <string name="backup_text">Backups, die deine eigenen Schlüssel beinhalten, dürfen unter keinen Umständen an anderen Personen gegeben werden.</string>
+ <string name="backup_all">Alle Schlüssel + deine eigenen Schlüssel</string>
+ <string name="backup_public_keys">Alle Schlüssel</string>
+ <string name="backup_section">Backup</string>
<!--unsorted-->
<string name="section_certifier_id">Beglaubiger</string>
<string name="section_cert">Beglaubigungsdetails</string>
@@ -1145,7 +1277,7 @@
<string name="empty_certs">Keine Beglaubigungen für diesen Schlüssel</string>
<string name="certs_text">Nur geprüfte Eigenbeglaubigungen und geprüfte Beglaubigungen, die mit deinen Schlüsseln erzeugt wurden, werden hier angezeigt.</string>
<string name="section_uids_to_certify">Identitäten für</string>
- <string name="certify_text">Die Schlüssel, die importiert werden, enthalten \"Identitäten\": Namen und E-Mail-Adressen. Wähle genau diejenigen zum Bestätigen aus, die deinen Erwartungen entsprechen.</string>
+ <string name="certify_text">Die zu importierenden Schlüssel enthalten \"Identitäten\": Namen und E-Mail-Adressen. Wähle genau diejenigen zum Bestätigen aus, die deinen Erwartungen entsprechen.</string>
<string name="certify_fingerprint_text">Vergleiche den angezeigten Fingerabdruck zeichenweise mit dem, der auf dem Gerät deines Gegenübers angezeigt wird.</string>
<string name="certify_fingerprint_text2">Stimmen die angezeigten Fingerabdrücke überein?</string>
<string name="label_revocation">Widerrufsgrund</string>
@@ -1153,23 +1285,29 @@
<string name="error_key_not_found">Schlüssel nicht gefunden!</string>
<string name="error_key_processing">Fehler bei der Verarbeitung des Schlüssels!</string>
<string name="key_stripped">nicht verfügbar</string>
- <string name="key_divert">Auf Smartcard umleiten</string>
+ <string name="key_divert">auf Smartcard umleiten</string>
<string name="key_no_passphrase">kein Passwort</string>
<string name="key_unavailable">nicht verfügbar</string>
<string name="secret_cannot_multiple">Deine eigenen Schlüssel können nur einzeln gelöscht werden!</string>
<string name="title_view_cert">Beglaubigungsdetails anzeigen</string>
<string name="unknown_algorithm">unbekannt</string>
- <string name="can_sign_not">Kann nicht unterschreiben</string>
+ <string name="can_sign_not">kann nicht signieren</string>
<string name="error_no_encrypt_subkey">Kein Unterschlüssel zum Verschlüsseln verfügbar!</string>
- <string name="account_no_manual_account_creation">Erstelle OpenKeychain-Benutzerkonten nicht manuell.\nFür mehr Informationen sieh in die Hilfe.</string>
<string name="contact_show_key">Schlüssel anzeigen (%s)</string>
- <string name="swipe_to_update">Nach unten wischen um von Schlüsselserver zu aktualisieren</string>
+ <string name="swipe_to_update">Nach unten wischen, um vom Schlüsselserver zu aktualisieren</string>
<string name="error_no_file_selected">Mindestens eine Datei zum Verschlüsseln auswählen!</string>
+ <string name="error_multi_files">Das speichern von mehreren Dateien wird nicht unterstützt. Dies ist eine Einschränkung der aktuellen Android Version.</string>
+ <string name="error_multi_clipboard">Verschlüsselung mehrerer Dateien in die Zwischenablage wird nicht unterstützt.</string>
+ <string name="error_detached_signature">Nur-signieren-Vorgang von Binärdateien wird nicht unterstützt, bitte mindestens einen Verschlüsselungsschlüssel auswählen.</string>
<string name="error_empty_text">Zu verschlüsselnden Text eingeben</string>
<string name="key_colon">Schlüssel:</string>
<string name="exchange_description">Um einen Schlüsselaustausch zu starten wähle auf der rechten Seite die Teilnehmer aus, drücke dann den \"Austausch starten\"-Knopf.\n\nDu wirst zusätzlich zwei Fragen gestellt bekommen um sicherzustellen, dass nur die richtigen Teilnehmer am Austausch beteiligt sind und deren Fingerabdrücke korrekt sind.</string>
<string name="btn_start_exchange">Austausch starten</string>
<string name="user_id_none"><![CDATA[<kein>]]></string>
+ <!--Android Account-->
+ <string name="account_no_manual_account_creation">OpenKeychain-Benutzerkonten können nicht manuell angelegt werden.</string>
+ <string name="account_privacy_title">Datenschutz</string>
+ <string name="account_privacy_text">OpenKeychain synchronisiert deine Kontakte nicht mit dem Internet. Es verknüpft lediglich Kontakte mit Schlüsseln auf der Basis von Namen und E-Mail-Adressen. Das alles findet offline auf deinem Gerät statt.</string>
<!--Passphrase wizard-->
<!--TODO: rename all the things!-->
<string name="title_unlock_method">Wähle eine Entsperrmethode</string>
@@ -1178,7 +1316,7 @@
<string name="passphrase">Passwort</string>
<string name="noPassphrase">Kein Passwort</string>
<string name="no_passphrase_set">Kein Passwort festgelegt</string>
- <string name="passphrases_match">Passwörter stimmen nicht überein</string>
+ <string name="passphrases_match">Passwörter stimmen überein</string>
<string name="passphrase_saved">Passwort gespeichert</string>
<string name="passphrase_invalid">Passwort ungültig</string>
<string name="missing_passphrase">Fehlendes Passwort</string>
@@ -1190,7 +1328,7 @@
<string name="draw_lockpattern">Zeichne Entsperrcode</string>
<string name="nfc_title">NFC</string>
<!--<string name="nfc_text">Please place a NFC tag near your device</string>-->
- <string name="nfc_wrong_tag">Falscher Tag. Bitte versuche es erneut.</string>
+ <string name="nfc_wrong_tag">Falscher Tag, bitte versuche es erneut.</string>
<string name="enable_nfc">Bitte aktiviere NFC in deinen Einstellungen.</string>
<string name="no_nfc_support">Dieses Gerät unterstützt kein NFC</string>
<string name="nfc_write_succesful">Erfolgreich auf den NFC-Tag geschrieben</string>
@@ -1202,16 +1340,32 @@
<string name="yubikey_serno">Seriennummer: %s</string>
<string name="yubikey_key_holder">Schlüsselinhaber:</string>
<string name="yubikey_key_holder_not_set">Schlüsselnhaber: &lt;nicht gesetzt&gt;</string>
- <string name="yubikey_status_bound">YubiKey stimmt überein und ist mit dem Schlüssel verbunden</string>
- <string name="yubikey_status_unbound">YubiKey stimmt überein und kann mit dem Schlüssel verbunden werden</string>
- <string name="yubikey_status_partly">YubiKey stimmt überein und ist teilweise mit dem Schlüssel verbunden</string>
- <string name="yubikey_create">Halte YubiKey gegen die Rückseite Deines Geräts.</string>
+ <string name="yubikey_status_bound">YubiKey stimmt überein und ist mit dem Schlüssel gekoppelt</string>
+ <string name="yubikey_status_unbound">YubiKey stimmt überein und kann mit dem Schlüssel gekoppelt werden</string>
+ <string name="yubikey_status_partly">YubiKey stimmt überein und ist teilweise mit dem Schlüssel gekoppelt</string>
+ <string name="yubikey_create">Halte den YubiKey gegen die Rückseite deines Geräts.</string>
<string name="btn_import">Import</string>
<string name="snack_yubi_other">Anderer Schlüssel auf YubiKey gespeichert!</string>
<string name="error_nfc">NFC-Fehler: %s</string>
+ <plurals name="error_pin">
+ <item quantity="one">PIN falsch!\n%d Versuch verbleibend.</item>
+ <item quantity="other">PIN falsch!\n%d Versuche verbleibend.</item>
+ </plurals>
+ <string name="error_nfc_terminated">YubiKey befindet sich in beendetem Zustand.</string>
+ <string name="error_nfc_wrong_length">Eingegebene PIN zu kurz. PINs müssen aus mindestens 6 Ziffern bestehen.</string>
+ <string name="error_nfc_conditions_not_satisfied">Nutzungsbedingungen werden nicht erfüllt. </string>
+ <string name="error_nfc_security_not_satisfied">Sicherheitsstatus nicht erfüllt.</string>
+ <string name="error_nfc_authentication_blocked">PIN nach zu vielen Versuchen gesperrt.</string>
+ <string name="error_nfc_data_not_found">Schlüssel oder Objekt nicht gefunden.</string>
+ <string name="error_nfc_unknown">Unbekannter Fehler</string>
+ <string name="error_nfc_bad_data">YubiKey meldete ungültige Daten.</string>
+ <string name="error_nfc_chaining_error">YubiKey erwartete das letzte Kommando in einer Kette.</string>
+ <string name="error_nfc_header">YubiKey meldete ungültige %s Byte.</string>
+ <string name="error_nfc_tag_lost">YubiKey wurde zu früh abgenommen. Halte den YubiKey an die Rückseite, bis der Vorgang beendet ist.</string>
+ <string name="error_nfc_try_again">Erneut versuchen</string>
<string name="error_pin_nodefault">Standard-PIN abgelehnt</string>
<string name="error_temp_file">Erstellen der temporären Datei fehlgeschlagen.</string>
- <string name="btn_delete_original">Original Datei löschen</string>
+ <string name="btn_delete_original">Originaldatei löschen</string>
<string name="snack_encrypt_filenames_on">Dateinamen <b>sind</b> verschlüsselt.</string>
<string name="snack_encrypt_filenames_off">Dateinamen <b>sind nicht</b> verschlüsselt.</string>
<string name="snack_armor_on">Ausgabe als Text kodiert.</string>
@@ -1219,15 +1373,23 @@
<string name="snack_compression_on">Komprimierung <b>aktiviert</b>.</string>
<string name="snack_compression_off">Komprimierung <b>deaktiviert</b>.</string>
<string name="error_loading_keys">Fehler beim Laden der Schlüssel!</string>
- <string name="error_empty_log">(Fehler, leeres Protokoll)</string>
+ <string name="error_empty_log">(Fehler, Protokoll leer)</string>
+ <string name="error_reading_text">Konnte Eingabe zur Entschlüsselung nicht lesen!</string>
+ <string name="filename_unknown">&lt;kein Dateiname&gt;</string>
+ <string name="filename_unknown_text">&lt;Klartextdaten&gt;</string>
+ <string name="intent_show">Signierten/verschlüsselten Inhalt anzeigen</string>
<string name="view_internal">In OpenKeychain ansehen</string>
<string name="error_preparing_data">Fehler beim Vorbereiten der Daten!</string>
<string name="label_clip_title">Verschlüsselte Daten</string>
- <string name="progress_processing">Verarbeiten...</string>
+ <string name="progress_processing">Wird verarbeitet...</string>
<string name="error_saving_file">Fehler beim Speichern der Datei!</string>
<string name="file_saved">Datei gespeichert!</string>
- <string name="file_delete_ok">Original Datei gelöscht</string>
+ <string name="file_delete_ok">Originaldatei gelöscht.</string>
<string name="file_delete_none">Keine Datei gelöscht! (bereits gelöscht?)</string>
- <string name="file_delete_exception">Original Datei konnte nicht gelöscht werden!</string>
+ <string name="file_delete_exception">Originaldatei konnte nicht gelöscht werden!</string>
<string name="error_clipboard_empty">Zwischenablage ist leer!</string>
+ <string name="error_clipboard_copy">Fehler beim Kopieren der Daten in die Zwischenablage!</string>
+ <string name="error_scan_fp">Fehler beim Scannen des Fingerabdrucks!</string>
+ <string name="error_scan_match">Fingerabdrücke stimmten nicht überein!</string>
+ <string name="error_expiry_past">Ablaufdatum liegt in der Vergangenheit!</string>
</resources>
diff --git a/OpenKeychain/src/main/res/values-es/strings.xml b/OpenKeychain/src/main/res/values-es/strings.xml
index a86e576ec..043918c64 100644
--- a/OpenKeychain/src/main/res/values-es/strings.xml
+++ b/OpenKeychain/src/main/res/values-es/strings.xml
@@ -20,8 +20,8 @@
<string name="title_encrypt_to_file">Cifrar hacia archivo</string>
<string name="title_decrypt_to_file">Descifrar hacia archivo</string>
<string name="title_import_keys">Importar claves</string>
- <string name="title_export_key">Exportar clave</string>
- <string name="title_export_keys">Exportar claves</string>
+ <string name="title_export_key">Hacer copia de seguridad de la clave</string>
+ <string name="title_export_keys">Hacer copia de seguridad de las claves</string>
<string name="title_key_not_found">Clave no encontrada</string>
<string name="title_send_key">Cargar al servidor de claves</string>
<string name="title_certify_key">Confirmar clave</string>
@@ -44,6 +44,8 @@
<string name="section_cloud_search">Búsqueda en la nube</string>
<string name="section_passphrase_cache">Manejo de contraseña/PIN</string>
<string name="section_proxy_settings">Configuración para proxy</string>
+ <string name="section_gui">Interfaz</string>
+ <string name="section_sync_settings">Sincronizar configuración</string>
<string name="section_certify">Confirmar</string>
<string name="section_actions">Acciones</string>
<string name="section_share_key">Clave</string>
@@ -88,7 +90,7 @@
<!--menu-->
<string name="menu_preferences">Ajustes</string>
<string name="menu_help">Ayuda</string>
- <string name="menu_export_key">Exportar hacia archivo</string>
+ <string name="menu_export_key">Hacer copia de seguridad hacia fichero</string>
<string name="menu_delete_key">Borrar clave</string>
<string name="menu_manage_keys">Administrar mis claves</string>
<string name="menu_search">Buscar</string>
@@ -120,6 +122,7 @@
<string name="label_use_default_yubikey_pin">Utilizar PIN predeterminado de la YubiKey</string>
<string name="label_use_num_keypad_for_yubikey_pin">Utilizar teclado numérico para el PIN de la YubiKey</string>
<string name="label_label_use_default_yubikey_pin_summary">Utiliza el PIN predeterminado (123456) para acceder a las YubiKeys sobre NFC</string>
+ <string name="label_asymmetric_from">Firmar con:</string>
<string name="label_to">Cifrar hacia:</string>
<string name="label_delete_after_encryption">Borrar ficheros después del cifrado</string>
<string name="label_delete_after_decryption">Eliminar fichero después del descifrado</string>
@@ -155,10 +158,19 @@
<string name="label_verify_keyserver">Verificar servidor de claves</string>
<string name="label_enter_keyserver_url">Introduzca URL de servidor de claves</string>
<string name="label_keyserver_dialog_delete">Borrar servidor de claves</string>
+ <string name="label_theme">Tema decorativo</string>
<string name="pref_keyserver">Servidores de claves OpenPGP</string>
<string name="pref_keyserver_summary">Busca claves en los servidores de claves OpenPGP seleccionados (protocolo HKP)</string>
<string name="pref_keybase">keybase.io</string>
<string name="pref_keybase_summary">Busca claves en keybase.io</string>
+ <string name="label_sync_settings_keyserver_title">Actualizar claves automáticamente</string>
+ <string name="label_sync_settings_keyserver_summary_on">Las claves con más de una semana de vida se actualizarán desde el servidor de claves preferido</string>
+ <string name="label_sync_settings_keyserver_summary_off">Las claves no se actualizarán automáticamente</string>
+ <string name="label_sync_settings_contacts_title">Sincronizar contactos con claves</string>
+ <string name="label_sync_settings_contacts_summary_on">Las claves se vincularon a contactos con correos coincidentes, ocurre de forma completamente desconectada</string>
+ <string name="label_sync_settings_contacts_summary_off">Las claves nuevas no se vincularán a contactos</string>
+ <!--label shown in Android settings under the OpenKeychain account-->
+ <string name="keyserver_sync_settings_title">Actualizar claves automáticamente</string>
<!--Proxy Preferences-->
<string name="pref_proxy_tor_title">Habilitar Tor</string>
<string name="pref_proxy_tor_summary">Requiere que Orbot esté instalado</string>
@@ -171,8 +183,6 @@
<!--proxy type choices and values-->
<string name="pref_proxy_type_choice_http">HTTP</string>
<string name="pref_proxy_type_choice_socks">SOCKS</string>
- <string name="pref_proxy_type_value_http">proxyHttp</string>
- <string name="pref_proxy_type_value_socks">proxySocks</string>
<!--OrbotHelper strings-->
<string name="orbot_ignore_tor">No usar Tor</string>
<!--InstallDialogFragment strings-->
@@ -221,6 +231,8 @@
<string name="filemanager_title_open">Abrir...</string>
<string name="error">Error</string>
<string name="error_message">Error: %s</string>
+ <string name="theme_dark">Oscuro</string>
+ <string name="theme_light">Claro</string>
<!--key flags-->
<string name="flag_certify">Certificar</string>
<string name="flag_sign">Firmar</string>
@@ -237,6 +249,8 @@
<string name="yubikey_pin_for">Introduzca el PIN para acceder a la YubiKey para \'%s\'</string>
<string name="nfc_text">Sostenga la YubiKey contra el marcador NFC en el reverso de su dispositivo.</string>
<string name="nfc_wait">¡Mantenga la YubiKey en el reverso!</string>
+ <string name="nfc_finished">Retire la YubiKey ahora.</string>
+ <string name="nfc_try_again_text">Retire la YubiKey ahora y pulse INTENTAR DE NUEVO.</string>
<string name="file_delete_confirmation_title">¿Borrar ficheros originales?</string>
<string name="file_delete_confirmation">Los siguientes ficheros se borrarán:%s</string>
<string name="file_delete_successful">%1$d de %2$d ficheros han sido borrados.%3$s</string>
@@ -247,7 +261,10 @@
<string name="error_no_encryption_or_signature_key">Seleccionar al menos una clave de cifrado o una clave de firma.</string>
<string name="specify_file_to_encrypt_to">Por favor especifique hacia qué fichero cifrar.\nADVERTENCIA: ¡El fichero se sobreescribirá si existe!</string>
<string name="specify_file_to_decrypt_to">Por favor especifique hacia qué fichero descifrar.\nADVERTENCIA: ¡El fichero se sobreescribirá si existe!</string>
- <string name="specify_backup_dest">Por favor especifique hacia qué fichero exportar.\nADVERTENCIA: ¡El fichero se sobreescribirá si existe!</string>
+ <string name="specify_backup_dest">Se realizará una copia de seguridad excluyendo sus claves, por favor, especifique un fichero de destino.\nADVERTENCIA: ¡El fichero se sobreescribirá si existe!</string>
+ <string name="specify_backup_dest_single">Esta clave se compartirá, por favor, especifique un fichero de destino.\nADVERTENCIA: ¡El fichero se sobreescribirá si existe!</string>
+ <string name="specify_backup_dest_secret_single">Se realizará una copia de seguridad completa de su clave, por favor, especifique un fichero de destino.\nADVERTENCIA: ¡El fichero se sobreescribirá si existe!</string>
+ <string name="specify_backup_dest_secret">Se realizará una copia de seguridad completa de todas sus claves incluyendo las suyas, por favor, especifique un fichero de destino.\nADVERTENCIA: ¡El fichero se sobreescribirá si existe!</string>
<string name="key_deletion_confirmation_multi">¿De verdad quiere borrar todas las claves seleccionadas?</string>
<string name="secret_key_deletion_confirmation">¡Después del borrado no podrá leer mensajes cifrados con esta clave y perderá todas las confirmaciones de clave hechas con ella!</string>
<string name="public_key_deletetion_confirmation">¿Borrar clave \'%s\'?</string>
@@ -299,6 +316,7 @@
<!--results shown after decryption/verification-->
<string name="decrypt_result_no_signature">No firmado</string>
<string name="decrypt_result_invalid_signature">¡Firma no válida!</string>
+ <string name="decrypt_result_insecure_cryptography">¡Firma no válida (criptografía no segura)!</string>
<string name="decrypt_result_signature_uncertified">Firmado por clave <b>no confirmada</b></string>
<string name="decrypt_result_signature_secret">Firmado por la clave de usted</string>
<string name="decrypt_result_signature_certified">Firmado por clave confirmada</string>
@@ -307,6 +325,7 @@
<string name="decrypt_result_signature_missing_key">Firmado por <b>clave pública desconocida</b></string>
<string name="decrypt_result_encrypted">Cifrado</string>
<string name="decrypt_result_not_encrypted">No cifrado</string>
+ <string name="decrypt_result_insecure">Cifrado no seguro</string>
<string name="decrypt_result_action_show">Mostrar</string>
<string name="decrypt_result_action_Lookup">Buscar</string>
<string name="decrypt_invalid_text">O bien la firma no es válida o la clave ha sido revocada. No puede estar seguro de quién escribió el texto. ¿Quiere aún mostrarlo?</string>
@@ -319,6 +338,7 @@
<string name="progress_cancelling">cancelando...</string>
<string name="progress_saving">guardando...</string>
<string name="progress_importing">importando...</string>
+ <string name="progress_revoking_uploading">Revocando y subiendo clave...</string>
<string name="progress_updating">Actualizando claves...</string>
<string name="progress_exporting">exportando...</string>
<string name="progress_uploading">subiendo...</string>
@@ -367,6 +387,7 @@
<string name="progress_con_saving">consolidación: guardando en caché...</string>
<string name="progress_con_reimport">consolidación: reimportando</string>
<string name="progress_verifying_keyserver_url">verificando servidor de claves...</string>
+ <string name="progress_starting_orbot">Iniciando Orbot...</string>
<!--action strings-->
<string name="hint_cloud_search_hint">Buscar mediante Nombre, Correo electrónico...</string>
<!--key bit length selections-->
@@ -408,8 +429,8 @@
<string name="import_tab_qr_code">Código QR/NFC</string>
<string name="import_import">Importar las claves seleccionadas</string>
<string name="import_qr_code_wrong">¡El código QR está deformado! ¡Por favor, prueba de nuevo!</string>
- <string name="import_qr_code_fp">¡La huella de validación (fingerprint) está malformada o es demasiado corta!</string>
- <string name="import_qr_code_too_short_fingerprint">¡La huella de validación (fingerprint) es demasiado corta!</string>
+ <string name="import_qr_code_fp">¡La huella de validación de clave está malformada o es demasiado corta!</string>
+ <string name="import_qr_code_too_short_fingerprint">¡La huella de validación de clave es demasiado corta!</string>
<string name="import_qr_code_button">Escanear código QR</string>
<string name="import_qr_code_text">¡Sitúe su cámara sobre el código QR!</string>
<!--Import from URL-->
@@ -464,6 +485,11 @@
</plurals>
<string name="delete_nothing">No hay nada que borrar.</string>
<string name="delete_cancelled">Operación de borrado cancelada.</string>
+ <!--Revoke result toast (snackbar)-->
+ <string name="revoke_ok">Clave revocada con éxito.</string>
+ <string name="revoke_fail">¡Error revocando clave!</string>
+ <string name="revoke_nothing">Nada que revocar.</string>
+ <string name="revoke_cancelled">Se canceló la operación de revocado.</string>
<!--Certify result toast-->
<plurals name="certify_keys_ok">
<item quantity="one">Clave%2$s certificada con éxito.</item>
@@ -497,7 +523,7 @@
<string name="api_settings_start">Iniciar aplicación</string>
<string name="api_settings_delete_account">Borrar cuenta</string>
<string name="api_settings_package_name">Nombre de paquete</string>
- <string name="api_settings_package_certificate">SHA-256 de firma de paquete</string>
+ <string name="api_settings_package_certificate">SHA-256 del certificado del paquete</string>
<string name="api_settings_accounts">Cuentas (API antigua)</string>
<string name="api_settings_advanced">Información extendida</string>
<string name="api_settings_allowed_keys">Claves permitidas</string>
@@ -510,8 +536,8 @@
<string name="api_register_allow">Permitir el acceso</string>
<string name="api_register_disallow">Denegar el acceso</string>
<string name="api_register_error_select_key">¡Por favor, selecciona una clave!</string>
- <string name="api_select_pub_keys_missing_text">No se encontraron claves para estas identificaciones:</string>
- <string name="api_select_pub_keys_dublicates_text">Existe más de una clave para estas identificaciones:</string>
+ <string name="api_select_pub_keys_missing_text">No se encontraron claves para estas direcciones de correo electrónico:</string>
+ <string name="api_select_pub_keys_dublicates_text">Existe más de una clave para estas direcciones de correo electrónico:</string>
<string name="api_select_pub_keys_text">¡Por favor, revisa la lista de destinatarios!</string>
<string name="api_select_pub_keys_text_no_user_ids">¡Por favor seleccione los receptores!</string>
<string name="api_error_wrong_signature">¡La comprobación de la firma ha fallado! ¿Has instalado esta app desde una fuente distinta? Si estás seguro de que esto no es un ataque, revoca el registro de esta app en OpenKeychain y regístrala de nuevo.</string>
@@ -520,6 +546,19 @@
<!--Share-->
<string name="share_qr_code_dialog_title">Compartir con código QR</string>
<string name="share_nfc_dialog">Compartir con NFC</string>
+ <!--retry upload dialog-->
+ <string name="retry_up_dialog_title">Fallo al subir</string>
+ <string name="retry_up_dialog_message">Fallo al subir. ¿Desea reintentar la operación?</string>
+ <string name="retry_up_dialog_btn_reupload">Reintentar operación</string>
+ <string name="retry_up_dialog_btn_cancel">Cancelar operación</string>
+ <!--Delete or revoke private key dialog-->
+ <string name="del_rev_dialog_message">Si ya no desea usar esta clave, debe ser revocada y subida. Seleccione \'SÓLO BORRAR\' si desea eliminar la clave de OpenKeychain pero continuar usándola desde cualquier otro sitio.</string>
+ <string name="del_rev_dialog_title">Revocar/Borrar Clave \'%s\'</string>
+ <string name="del_rev_dialog_btn_revoke">Revocar y subir</string>
+ <string name="del_rev_dialog_btn_delete">Sólo borrar</string>
+ <!--Delete Or Revoke Dialog spinner-->
+ <string name="del_rev_dialog_choice_delete">Sólo borrar</string>
+ <string name="del_rev_dialog_choice_rev_upload">Revocar y subir</string>
<!--Key list-->
<plurals name="key_list_selected_keys">
<item quantity="one">1 clave seleccionada.</item>
@@ -562,14 +601,14 @@
<string name="key_trust_results_prefix">Keybase.io ofrece \"comprobantes\" que sostienen que el propietario de esta clave:</string>
<string name="key_trust_header_text">Nota: Los comprobantes de Keybase.io son una característica experimental de OpenKeychain. Le animamos a que escanee los Códigos QR o intercambie claves vía NFC además de confirmarlas.</string>
<!--keybase proof stuff-->
- <string name="keybase_narrative_twitter">Publica en Twitter como</string>
- <string name="keybase_narrative_github">Es conocido en GitHub como</string>
- <string name="keybase_narrative_dns">Controla el(los) nombre(s) de dominio</string>
- <string name="keybase_narrative_web_site">Puede publicar en el(los) sitio(s) web</string>
- <string name="keybase_narrative_reddit">Publica en Reddit como </string>
- <string name="keybase_narrative_coinbase">Es conocido en Coinbase como</string>
- <string name="keybase_narrative_hackernews">Publica en Hacker News como</string>
- <string name="keybase_narrative_unknown">Tipo de comprobante desconocido</string>
+ <string name="keybase_narrative_twitter">Publica en Twitter como %s</string>
+ <string name="keybase_narrative_github">Es conocido en GitHub como %s</string>
+ <string name="keybase_narrative_dns">Controla el/los nombre(s) de dominio %s</string>
+ <string name="keybase_narrative_web_site">Puede publicar en el/los sitio(s) web %s</string>
+ <string name="keybase_narrative_reddit">Publica en Reddit como %s</string>
+ <string name="keybase_narrative_coinbase">Es conocido en Coinbase como %s</string>
+ <string name="keybase_narrative_hackernews">Publica en Hacker News como %s</string>
+ <string name="keybase_narrative_unknown">Prueba de tipo desconocido %s</string>
<string name="keybase_proof_failure">Desafortunadamente este comprobante no se puede verificar.</string>
<string name="keybase_unknown_proof_failure">Problema no reconocido con el chequeador del comprobante</string>
<string name="keybase_problem_fetching_evidence">Problema con el comprobante</string>
@@ -665,6 +704,7 @@
<string name="drawer_open">Abrir el Navigation Drawer</string>
<string name="drawer_close">Cerrar el Navigation Drawer</string>
<string name="my_keys">Mis claves</string>
+ <string name="nav_backup">Copia de seguridad</string>
<!--hints-->
<string name="encrypt_content_edit_text_hint">Escriba el texto</string>
<!--certs-->
@@ -868,7 +908,7 @@
<string name="msg_kc_uat_warn_encoding">¡La identificación de usuario no se confirma como UTF-8!</string>
<!--Keyring merging log entries-->
<string name="msg_mg_error_secret_dummy">Nueva subclave pública encontrada, ¡pero la generación de subclaves secretas (privadas) ficticias no está soportada!</string>
- <string name="msg_mg_error_heterogeneous">¡Se intentaron fusionar juegos de claves con diferentes huellas de validación!</string>
+ <string name="msg_mg_error_heterogeneous">¡Se intentaron fusionar juegos de claves con diferentes huellas de validación de claves!</string>
<string name="msg_mg_error_encode">¡Error fatal codificando firma!</string>
<string name="msg_mg_public">Incorporándolas en el juego de claves públicas %s</string>
<string name="msg_mg_secret">Incorporándolas en el juego de claves secretas (privadas) %s</string>
@@ -892,7 +932,8 @@
<string name="msg_cr_error_flags_ecdh">¡Seleccionados indicativos de clave defectuosa, ECDH no puede usarse para firmado!</string>
<!--modifySecretKeyRing-->
<string name="msg_mr">Modificando el juego de claves %s</string>
- <string name="msg_mf_divert">Derivará a la tarjeta inteligente para operaciones de criptografía</string>
+ <string name="msg_mf_divert">Se derivará a la tarjeta inteligente para operaciones de criptografía</string>
+ <string name="msg_mf_error_divert_newsub">¡La creación de nuevas claves no está soportada para claves primarias marcadas \'derivar-a-tarjeta\'!</string>
<string name="msg_mf_error_divert_serial">¡El número de serie de una clave \'derivar-a-tarjeta\' ha de tener 16 bytes! Esto es un error de programación, por favor, ¡consigne un infome de fallo!</string>
<string name="msg_mf_error_encode">¡Excepción en la codificación!</string>
<string name="msg_mf_error_fingerprint">¡La actual huella de validación de clave no coincide con la esperada!</string>
@@ -908,6 +949,7 @@
<string name="msg_mf_error_passphrase_master">¡Error fatal descrifrando la clave maestra! Probablemente esto se daba a un error de programación, por favor ¡rellene un informe de fallo!</string>
<string name="msg_mf_error_pgp">¡Error OpenPGP interno!</string>
<string name="msg_mf_error_sig">¡Excepción con la firma!</string>
+ <string name="msg_mf_error_sub_stripped">¡No se pueden modificar subclaves desnudas %s!</string>
<string name="msg_mf_error_subkey_missing">¡Se intentó operar sobre una subclave desaparecida %s!</string>
<string name="msg_mf_error_conflicting_nfc_commands">No se puede mover la clave a la tarjeta inteligente en la misma operación que crea una firma en la tarjeta.</string>
<string name="msg_mf_error_duplicate_keytocard_for_slot">La tarjeta inteligente sólo soporta un lector por cada tipo de clave.</string>
@@ -981,6 +1023,7 @@
<string name="msg_ed_caching_new">Guardando en caché la nueva contraseña</string>
<string name="msg_ed_error_no_parcel">¡SaveKeyringParcel ausente! (esto es un fallo, por favor notifíquelo)</string>
<string name="msg_ed_error_key_not_found">¡Clave no encontrada!</string>
+ <string name="msg_ed_error_extract_public_upload">¡Error al extraer la clave pública para subirla!</string>
<string name="msg_ed_fetching">Descargando clave a modificar (%s)</string>
<string name="msg_ed_success">Operación en la clave completada</string>
<!--Promote key-->
@@ -1007,16 +1050,15 @@
<string name="msg_dc_clear_meta_size_unknown">Tamaño de fichero desconocido</string>
<string name="msg_dc_clear_meta_time">Hora de la modificación: %s</string>
<string name="msg_dc_clear_signature_bad">¡Comprobación de firma NO CORRECTA!</string>
- <string name="msg_dc_insecure_hash_algo">¡Algoritmo de identificador criptográfico (hash) no soportado y potencialmente inseguro!</string>
<string name="msg_dc_clear_signature_check">Verificando datos de firma</string>
<string name="msg_dc_clear_signature_ok">Comprobación de firma CORRECTA</string>
<string name="msg_dc_clear_signature">Guardando datos de firma para más tarde</string>
<string name="msg_dc_clear">Procesando datos de texto no cifrado (`cleartext`)</string>
<string name="msg_dc_error_bad_passphrase">Error desbloqueando clave, ¡contraseña incorrecta!</string>
+ <string name="msg_dc_error_sym_passphrase">¡Error al descifrar datos! (¿frase-contraseña errónea?)</string>
<string name="msg_dc_error_corrupt_data">¡Los datos están corruptos!</string>
<string name="msg_dc_error_extract_key">¡Error desconocido al desbloquear clave!</string>
<string name="msg_dc_error_integrity_check">¡Error de comprobación de integridad!</string>
- <string name="msg_dc_insecure_mdc_missing">¡Verificación de integridad ausente! Esto puede ocurrir porque la aplicación de cifrado no está actualizada, o debido a un ataque desactualización.</string>
<string name="msg_dc_error_invalid_data">¡No se encontraron datos firmados o cifrados con OpenPGP válidos!</string>
<string name="msg_dc_error_io">¡Se encontró un error al leer los datos de entrada!</string>
<string name="msg_dc_error_input">¡Error al abrir el flujo de datos de entrada!</string>
@@ -1037,7 +1079,10 @@
<string name="msg_dc_trail_sym">Se encontró huella, datos cifrados simétricamente</string>
<string name="msg_dc_trail_unknown">Se encontró huella, datos de tipo desconocido</string>
<string name="msg_dc_unlocking">Desbloqueando clave secreta (privada)</string>
- <string name="msg_dc_insecure_symmetric_encryption_algo">¡Se ha usado un algoritmo de cifrado potencialmente inseguro!</string>
+ <string name="msg_dc_insecure_symmetric_encryption_algo">¡Se ha usado un algoritmo de cifrado no seguro! Esto puede ocurrir porque la aplicación no esté actualizada, o por un ataque.</string>
+ <string name="msg_dc_insecure_hash_algo">¡Se ha usado un algoritmo de identificador criptográfico (hash) no seguro! Esto puede ocurrir porque la aplicación no esté actualizada, o por un ataque de degradación de versión.</string>
+ <string name="msg_dc_insecure_mdc_missing">¡El paquete de Código de Detección de Modificación (MDC) está ausente! Esto puede ocurrir porque la aplicación de cifrado no esté actualizada, o por un ataque de degradación de versión.</string>
+ <string name="msg_dc_insecure_key">Clave no segura: O bien el número de bits de la clave RSA/DSA/ElGamal es demasiado pequeño o la curva/algoritmo ECC es considerado no seguro! Esto puede ocurrir porque la aplicación no esté actualizada, o por un ataque de degradación de versión.</string>
<!--Messages for VerifySignedLiteralData operation-->
<string name="msg_vl">Comenzando comprobación de firma</string>
<string name="msg_vl_error_no_siglist">No hay lista de firmas en los datos literales firmados</string>
@@ -1065,7 +1110,6 @@
<string name="msg_pse_compressing">Preparando compresión</string>
<string name="msg_pse_encrypting">Cifrando datos</string>
<string name="msg_pse_error_bad_passphrase">¡Contraseña incorrecta!</string>
- <string name="msg_pse_error_hash_algo">¡El algoritmo de identificación criptográfica (hash) solicitado no está soportado por esta clave!</string>
<string name="msg_pse_error_io">¡Se encontró una excepción de E/S durante la operación!</string>
<string name="msg_pse_error_key_sign">¡La clave de firmado seleccionada no puede firmar datos!</string>
<string name="msg_pse_error_sign_key">¡Error al descargar clave de firmado!</string>
@@ -1118,12 +1162,12 @@
<string name="msg_import_fetch_error_decode">¡Error al descifrar juego de claves descargado!</string>
<string name="msg_import_fetch_error">¡La clave no se pudo descargar! (¿problemas con la red?)</string>
<string name="msg_import_fetch_keybase">Descargando desde keybase.io: %s</string>
- <string name="msg_import_fetch_keyserver_error">No se pudo obtener clave de los servidores de claves: %s</string>
+ <string name="msg_import_fetch_error_keyserver">No se pudo obtener clave de los servidores de claves: %s</string>
<string name="msg_import_fetch_keyserver">Descargando desde el servidor de claves: %s</string>
<string name="msg_import_fetch_keyserver_ok">La clave se descargó con éxito</string>
<string name="msg_import_keyserver">Usando el servidor de claves %s</string>
<string name="msg_import_fingerprint_error">¡La huella de validación de la clave descargada no coincidió con la esperada!</string>
- <string name="msg_import_fingerprint_ok">Comprobación de la huella de validación correcta</string>
+ <string name="msg_import_fingerprint_ok">La comprobación de la huella de validación de clave es Correcta</string>
<string name="msg_import_merge">Incorporando datos descargados</string>
<string name="msg_import_merge_error">¡Error al fusionar datos descargados!</string>
<string name="msg_import_error">¡La operación de importación falló!</string>
@@ -1134,6 +1178,7 @@
<item quantity="one">Exportando una clave</item>
<item quantity="other">Exportando %d claves</item>
</plurals>
+ <string name="msg_export_file_name">Nombre de fichero: %s</string>
<string name="msg_export_all">Exportando todas las claves</string>
<string name="msg_export_public">Exportando clave pública %s</string>
<string name="msg_export_upload_public">Subiendo clave pública %s</string>
@@ -1166,6 +1211,11 @@
<item quantity="one">No se pudo borrar una clave</item>
<item quantity="other">No se pudieron borrar %d claves</item>
</plurals>
+ <string name="msg_revoke_error_empty">¡Nada que revocar!</string>
+ <string name="msg_revoke_error_not_found">¡No se pudo encontrar clave a revocar!</string>
+ <string name="msg_revoke_key">Revocando clave %s</string>
+ <string name="msg_revoke_key_fail">Fallo al revocar clave</string>
+ <string name="msg_revoke_ok">Clave revocada con éxito</string>
<string name="msg_acc_saved">Cuenta guardada</string>
<string name="msg_download_success">¡Descargado con éxito!</string>
<string name="msg_download_no_valid_keys">¡No se encontraron claves vigentes en el fichero/portapapeles!</string>
@@ -1182,7 +1232,7 @@
<string name="msg_keybase_verification">Intentando la verificación con Keybase para %s</string>
<string name="msg_keybase_error_no_prover">No se encontró prueba verificadora para %s</string>
<string name="msg_keybase_error_fetching_evidence">Problema al descargar prueba</string>
- <string name="msg_keybase_error_key_mismatch">La huella de validación (fingerprint) de la clave no coincide con la prueba publicada</string>
+ <string name="msg_keybase_error_key_mismatch">La huella de validación de la clave no coincide con la prueba publicada</string>
<string name="msg_keybase_error_dns_fail">Fallo al obtener Registro DNS TXT</string>
<string name="msg_keybase_error_specific">%s</string>
<string name="msg_keybase_error_msg_payload_mismatch">La prueba descifrada publicada no coincide con el valor esperado</string>
@@ -1201,6 +1251,11 @@
<string name="passp_cache_notif_keys">Contraseñas recordadas</string>
<string name="passp_cache_notif_clear">Limpiar contraseñas</string>
<string name="passp_cache_notif_pwd">Contraseña</string>
+ <!--Keyserver sync-->
+ <string name="keyserver_sync_orbot_notif_title">La sincronizacion desde la nube requiere Orbot</string>
+ <string name="keyserver_sync_orbot_notif_msg">Pulse para iniciar Orbot</string>
+ <string name="keyserver_sync_orbot_notif_start">Iniciar Orbot</string>
+ <string name="keyserver_sync_orbot_notif_ignore">Directamente</string>
<!--First Time-->
<string name="first_time_text1">¡Recupere su privacidad con OpenKeychain!</string>
<string name="first_time_create_key">Crear mi clave</string>
@@ -1209,6 +1264,10 @@
<string name="first_time_skip">Omitir configuración</string>
<string name="first_time_blank_yubikey">¿Desea usar esta YubiKey NEO en blanco con OpenKeychain?\n\n¡Por favor, retire ahora la YubiKey, se le solicitará cuando sea necesaria de nuevo!</string>
<string name="first_time_blank_yubikey_yes">Usar esta YubiKey</string>
+ <string name="backup_text">¡Las copias de seguridad que incluyen sus propias claves nunca se deben compartir con otras personas!</string>
+ <string name="backup_all">Todas las claves + sus propias claves</string>
+ <string name="backup_public_keys">Todas las claves</string>
+ <string name="backup_section">Copia de seguridad</string>
<!--unsorted-->
<string name="section_certifier_id">Certificador</string>
<string name="section_cert">Detalles del certificado</string>
@@ -1218,8 +1277,8 @@
<string name="certs_text">Aquí sólo se muestran auto-certificados validados y certificados validados creados con sus claves.</string>
<string name="section_uids_to_certify">Identificaciones para</string>
<string name="certify_text">Las claves que está importando contienen \"identidades\": nombres y direcciones de correo electrónico. Para confirmación seleccione exactamente aquellas que coincidan con lo que esperaba.</string>
- <string name="certify_fingerprint_text">Compare la huella de validación mostrada, caracter por caracter, con la que se muestra en el dispositivo de su colega.</string>
- <string name="certify_fingerprint_text2">¿Coinciden las huellas de validación mostradas?</string>
+ <string name="certify_fingerprint_text">Compare la huella de validación de clave mostrada, caracter por caracter, con la que se muestra en el dispositivo de su colega.</string>
+ <string name="certify_fingerprint_text2">¿Coinciden las huellas de validación de clave mostradas?</string>
<string name="label_revocation">Razón de la revocación</string>
<string name="label_cert_type">Tipo</string>
<string name="error_key_not_found">¡Clave no encontrada!</string>
@@ -1233,7 +1292,6 @@
<string name="unknown_algorithm">desconocido</string>
<string name="can_sign_not">no puede firmarse</string>
<string name="error_no_encrypt_subkey">¡No hay subclave de cifrado disponible!</string>
- <string name="account_no_manual_account_creation">No crear Cuentas-OpenKeychain manualmente.\nPara más información, vea la Ayuda.</string>
<string name="contact_show_key">Mostrar clave (%s)</string>
<string name="swipe_to_update">Gesto de barrido hacia abajo para actualizar desde el servidor de claves</string>
<string name="error_no_file_selected">¡Seleccione al menos un fichero a cifrar!</string>
@@ -1242,9 +1300,13 @@
<string name="error_detached_signature">La operación de sólo-firmado de ficheros binarios no está soportada, seleccione al menos una clave de cifrado.</string>
<string name="error_empty_text">¡Escriba algún texto a cifrar!</string>
<string name="key_colon">Clave:</string>
- <string name="exchange_description">Para iniciar un intercambio de claves, en el lado derecho elija el número de participantes, y luego pulse el botón \"Iniciar intercambio\".\n\nSe le formularán dos preguntas más para asegurar que sólo están en el intercambio los participantes debidos, y que sus huellas de validación son correctas.</string>
+ <string name="exchange_description">Para iniciar un intercambio de claves, en el lado derecho elija el número de participantes, y luego pulse el botón \"Iniciar intercambio\".\n\nSe le formularán dos preguntas más para asegurar que sólo están en el intercambio los participantes debidos, y que las huellas de validación de sus claves son correctas.</string>
<string name="btn_start_exchange">Comenzar intercambio</string>
<string name="user_id_none"><![CDATA[<ninguno>]]></string>
+ <!--Android Account-->
+ <string name="account_no_manual_account_creation">No puede crear cuentas de OpenKeychain manualmente.</string>
+ <string name="account_privacy_title">Privacidad</string>
+ <string name="account_privacy_text">OpenKeychain no sincroniza sus contactos con Internet. Sólo vincula contactos a claves basándose en nombres y direcciones de correo electrónico. Hace esto de forma desconectada en su dispositivo.</string>
<!--Passphrase wizard-->
<!--TODO: rename all the things!-->
<string name="title_unlock_method">Escoja un método de desbloqueo</string>
@@ -1284,6 +1346,22 @@
<string name="btn_import">Importar</string>
<string name="snack_yubi_other">¡Clave almacenada en YubiKey distinta!</string>
<string name="error_nfc">Error de NFC: %s</string>
+ <plurals name="error_pin">
+ <item quantity="one">¡PIN incorrecto!\nLe queda %d intento.</item>
+ <item quantity="other">¡PIN incorrecto!\nLe quedan %d intentos.</item>
+ </plurals>
+ <string name="error_nfc_terminated">YubiKey en estado de vencimiento.</string>
+ <string name="error_nfc_wrong_length">El PIN introducido es demasiado corto. Los PINs tienen al menos 6 dígitos de largo.</string>
+ <string name="error_nfc_conditions_not_satisfied">Condiciones de uso no satisfechas.</string>
+ <string name="error_nfc_security_not_satisfied">Estado de seguridad no satisfecho.</string>
+ <string name="error_nfc_authentication_blocked">PIN bloqueado después de demasiados intentos.</string>
+ <string name="error_nfc_data_not_found">Clave u objeto no encontrado.</string>
+ <string name="error_nfc_unknown">Error desconocido</string>
+ <string name="error_nfc_bad_data">La YubiKey informó de datos no válidos.</string>
+ <string name="error_nfc_chaining_error">La YubiKey esperaba el último comando en una cadena.</string>
+ <string name="error_nfc_header">La YubiKey informó de un byte %s no válido.</string>
+ <string name="error_nfc_tag_lost">La YubiKey ha sido retirada demasiado pronto. Mantenga la YubiKey en el reverso hasta que la operación finalice.</string>
+ <string name="error_nfc_try_again">Intentar de nuevo</string>
<string name="error_pin_nodefault">¡El PIN por defecto fue rechazado!</string>
<string name="error_temp_file">Error al crear fichero temporal.</string>
<string name="btn_delete_original">Borrar fichero original</string>
@@ -1310,4 +1388,7 @@
<string name="file_delete_exception">¡No se pudo borrar el fichero original!</string>
<string name="error_clipboard_empty">¡Portapapeles vacío!</string>
<string name="error_clipboard_copy">¡Error al copiar datos al portapapeles!</string>
+ <string name="error_scan_fp">¡Error al escanear huella de validación de clave!</string>
+ <string name="error_scan_match">¡Las huellas de validación de clave no coinciden!</string>
+ <string name="error_expiry_past">¡La fecha de caducidad es del pasado!</string>
</resources>
diff --git a/OpenKeychain/src/main/res/values-et/strings.xml b/OpenKeychain/src/main/res/values-et/strings.xml
index 8a0481cac..7952c6ab0 100644
--- a/OpenKeychain/src/main/res/values-et/strings.xml
+++ b/OpenKeychain/src/main/res/values-et/strings.xml
@@ -6,8 +6,6 @@
<string name="title_decrypt">Dekrüpteeri</string>
<string name="title_edit_key">Muuda võtit</string>
<string name="title_import_keys">Impordi võtmeid</string>
- <string name="title_export_key">Ekspordi võti</string>
- <string name="title_export_keys">Ekspordi võtmed</string>
<string name="title_key_not_found">Võtit ei leitud</string>
<string name="title_send_key">Lae võtmeserverisse</string>
<string name="title_help">Abi</string>
@@ -32,6 +30,7 @@
<string name="label_name">Nimi</string>
<string name="label_comment">Kommentaar</string>
<string name="label_email">E-mail</string>
+ <!--label shown in Android settings under the OpenKeychain account-->
<!--Proxy Preferences-->
<!--proxy type choices and values-->
<!--OrbotHelper strings-->
@@ -80,10 +79,14 @@
<!--Generic result toast-->
<!--Import result toast-->
<!--Delete result toast-->
+ <!--Revoke result toast (snackbar)-->
<!--Certify result toast-->
<!--Intent labels-->
<!--Remote API-->
<!--Share-->
+ <!--retry upload dialog-->
+ <!--Delete or revoke private key dialog-->
+ <!--Delete Or Revoke Dialog spinner-->
<!--Key list-->
<!--Key view-->
<!--Key trust-->
@@ -113,8 +116,10 @@
<!--Messages for Keybase Verification operation-->
<!--Messages for Export Log operation-->
<!--PassphraseCache-->
+ <!--Keyserver sync-->
<!--First Time-->
<!--unsorted-->
+ <!--Android Account-->
<!--Passphrase wizard-->
<!--TODO: rename all the things!-->
<!--<string name="enter_passphrase_twice">Enter password twice</string>-->
diff --git a/OpenKeychain/src/main/res/values-eu/strings.xml b/OpenKeychain/src/main/res/values-eu/strings.xml
index d591d93e4..de4fb68d6 100644
--- a/OpenKeychain/src/main/res/values-eu/strings.xml
+++ b/OpenKeychain/src/main/res/values-eu/strings.xml
@@ -20,11 +20,11 @@
<string name="title_encrypt_to_file">Enkriptatu Agirira</string>
<string name="title_decrypt_to_file">Dekriptatu Agirira</string>
<string name="title_import_keys">Inportatu Giltzak</string>
- <string name="title_export_key">Esportatu Giltza</string>
- <string name="title_export_keys">Esportatu Giltzak</string>
+ <string name="title_export_key">Babeskopiatu Giltza</string>
+ <string name="title_export_keys">Babeskopiatu Giltzak</string>
<string name="title_key_not_found">Giltza Ez da Aurkitu</string>
<string name="title_send_key">Igo Giltza-zerbitzarira</string>
- <string name="title_certify_key">Baieztatu Giltza</string>
+ <string name="title_certify_key">Baieztatutako Giltza</string>
<string name="title_key_details">Giltzaren Xehetasunak</string>
<string name="title_help">Laguntza</string>
<string name="title_log_display">Oharra</string>
@@ -37,13 +37,14 @@
<string name="section_user_ids">Nortasunak</string>
<string name="section_yubikey">YubiKey</string>
<string name="section_linked_system_contact">Loturatutako Sistema Harremana</string>
- <string name="section_should_you_trust">Fildatu behar zara giltza honetaz?</string>
+ <string name="section_should_you_trust">Fidatu behar zara giltza honetaz?</string>
<string name="section_proof_details">Probatu egiaztapena</string>
<string name="section_cloud_evidence">Hodeiko probak</string>
<string name="section_keys">Azpigiltzak</string>
<string name="section_cloud_search">Hodei bilaketa</string>
<string name="section_passphrase_cache">Sarhitz/PIN Kudeaketa</string>
<string name="section_proxy_settings">Proxy Ezarpenak</string>
+ <string name="section_gui">Interfazea</string>
<string name="section_certify">Baieztatu</string>
<string name="section_actions">Ekintzak</string>
<string name="section_share_key">Giltza</string>
@@ -88,7 +89,7 @@
<!--menu-->
<string name="menu_preferences">Ezarpenak</string>
<string name="menu_help">Laguntza</string>
- <string name="menu_export_key">Esportatu agirira</string>
+ <string name="menu_export_key">Babeskopiatu Agirira</string>
<string name="menu_delete_key">Ezabatu giltza</string>
<string name="menu_manage_keys">Kudeatu nire giltzak</string>
<string name="menu_search">Bilatu</string>
@@ -120,12 +121,14 @@
<string name="label_use_default_yubikey_pin">Erabili berezko YubiKey PIN-a</string>
<string name="label_use_num_keypad_for_yubikey_pin">Erabili zenbaki teklatua YubiKey PIN-erako</string>
<string name="label_label_use_default_yubikey_pin_summary">Berezko PIN (123456) erabiltzen du NFC bidezko YubiKeys sarbiderako </string>
+ <string name="label_asymmetric_from">Hasi saioa honekin:</string>
<string name="label_to">Enkriptatu hona:</string>
<string name="label_delete_after_encryption">Ezabatu agiriak enkriptatu ondoren</string>
<string name="label_delete_after_decryption">Ezabatu dekriptatu ondoren</string>
<string name="label_encryption_algorithm">Enkriptaketa algoritmoa</string>
<string name="label_hash_algorithm">Hash algoritmoa</string>
<string name="label_symmetric">Enkriptatu sarhitzarekin</string>
+ <string name="label_passphrase_cache_ttl">Gogoratu ordua</string>
<string name="label_passphrase_cache_subs">Gogoratu sarhitzak azpigiltzaz</string>
<string name="label_message_compression">Idazki konpresioa</string>
<string name="label_file_compression">Agiri konpresioa</string>
@@ -154,10 +157,12 @@
<string name="label_verify_keyserver">Egiaztatu giltza-zerbitzaria</string>
<string name="label_enter_keyserver_url">Sartu giltza-zerbitzariaren URL-a</string>
<string name="label_keyserver_dialog_delete">Ezabatu giltza-zerbitzaria</string>
+ <string name="label_theme">Azalgaia</string>
<string name="pref_keyserver">OpenPGP giltza-zerbitzariak</string>
<string name="pref_keyserver_summary">Bilatu giltzak hautaturiko OpenPGP giltza-zerbitzarietan (HKP protokoloa)</string>
<string name="pref_keybase">keybase.io</string>
<string name="pref_keybase_summary">Bilatu giltzak keybase.io-an</string>
+ <!--label shown in Android settings under the OpenKeychain account-->
<!--Proxy Preferences-->
<string name="pref_proxy_tor_title">Gaitu Tor</string>
<string name="pref_proxy_tor_summary">Orbot ezarrita egotea behar du</string>
@@ -170,8 +175,6 @@
<!--proxy type choices and values-->
<string name="pref_proxy_type_choice_http">HTTP</string>
<string name="pref_proxy_type_choice_socks">SOCKS</string>
- <string name="pref_proxy_type_value_http">proxyHttp</string>
- <string name="pref_proxy_type_value_socks">proxySocks</string>
<!--OrbotHelper strings-->
<string name="orbot_ignore_tor">Ez erabili Tor</string>
<!--InstallDialogFragment strings-->
@@ -220,6 +223,8 @@
<string name="filemanager_title_open">Ireki...</string>
<string name="error">Akatsa</string>
<string name="error_message">Akatsa: %s</string>
+ <string name="theme_dark">Iluna</string>
+ <string name="theme_light">Argia</string>
<!--key flags-->
<string name="flag_certify">Egiaztatu</string>
<string name="flag_sign">Sinatu</string>
@@ -234,7 +239,10 @@
<string name="passphrase_for">Sartu \'%s\'-rako sarhitza</string>
<string name="pin_for">Sartu PIN-a \'%s\'-rako</string>
<string name="yubikey_pin_for">Sartu PIN-a YubKey-ra sartzeko \'%s\'-rentzat</string>
+ <string name="nfc_text">Heutsi YubiKey NFC markatzailearen kontra zure gailuaren atzealdean.</string>
<string name="nfc_wait">Eduki YubiKey atzealdean!</string>
+ <string name="nfc_finished">Irten YubiKey-tik orain</string>
+ <string name="nfc_try_again_text">Irten YubiKey-tik orain eta sakatu SAIATU BERRIRO.</string>
<string name="file_delete_confirmation_title">Ezabatu jatorrizko agiriak?</string>
<string name="file_delete_confirmation">Hurrengo agiriak ezabatu egingo dira: %s</string>
<string name="file_delete_successful">%1$d -&gt; %2$d-tik agiri ezbatu dira.%3$s</string>
@@ -245,7 +253,10 @@
<string name="error_no_encryption_or_signature_key">Hautatu gutxienez enkriptaketa giltza bat edo sinadura giltza bat.</string>
<string name="specify_file_to_encrypt_to">Mesedez adierazi zein agirira enkriptatu.\nKONTUZ: Agiria gainidatzi egingo da egonez gero!</string>
<string name="specify_file_to_decrypt_to">Mesedez adierazi zein agirira dekriptatu.\nKONTUZ: Agiria gainidatzi egingo da egonez gero!</string>
- <string name="specify_backup_dest">Mesedez adierazi zein agirira esportatu.\nKONTUZ: Agiria gainidatzi egingo da egonez gero!</string>
+ <string name="specify_backup_dest">Babeskopia bat egingo da, zure giltzak salbu barneratuz, mesedez adierazi helmuga agiri bat.\nKONTUZ: Agiria gainidatzi egingo da egonez gero!</string>
+ <string name="specify_backup_dest_single">Giltza hau elkarbanatu egingo da, mesedez adierazi helmuga agiria.\nKONTUZ: Agiria gainidatzi egingo da egonez gero!</string>
+ <string name="specify_backup_dest_secret_single">Zure giltzaren babeskopia oso bat egingo da, mesedez adierazi helmuga agiria.\nKONTUZ: Agiria gainidatzi egingo da egonez gero!</string>
+ <string name="specify_backup_dest_secret">Giltza guztien, zeureak barne, babeskopia oso bat egingo da, mesedez adierazi helmuga agiriak.\nKONTUZ: Agiria gainidatzi egingo da egonez gero!</string>
<string name="key_deletion_confirmation_multi">Egitan nahi duzu hautaturiko giltzak ezabatzea?</string>
<string name="secret_key_deletion_confirmation">Ezabatu ondoren ezingo dituzu giltza honekin enkriptatutako mezuak irakurri eta berarekin egindako giltza baieztapen guztiak galduko dira!</string>
<string name="public_key_deletetion_confirmation">Ezabatu \'%s\' giltza?</string>
@@ -257,9 +268,13 @@
<string name="key_creation_el_gamal_info">Oharra: azpigiltzek bakarrik sostengatzen dute EIGamal.</string>
<string name="key_not_found">Ezin da %08X giltza aurkitu.</string>
<string name="specify_file_to_export_log_to">Mesedez adierazi zein agirira esportatu. \nKONTUZ: Agiria gainidatzi egingo da egonez gero.</string>
+ <plurals name="bad_keys_encountered">
+ <item quantity="one">%d giltza sekretu gaitz ezikusita. Badaiteke esportatu izana\n --export-secret-subkeys aukerarekin.\nZihurtatu esportatzen duzula --export-secret-keys aukerarekin ordez.</item>
+ <item quantity="other">%d giltza sekretu gaitz ezikusita. Badaiteke esportatu izana\n --export-secret-subkeys aukerarekin.\nZihurtatu esportatzen duzula --export-secret-keys aukerarekin ordez.</item>
+ </plurals>
<string name="list_empty">Zerrenda hau hutsik dago!</string>
<string name="nfc_successful">Giltza ongi bidali da NFC Beam-rekin!</string>
- <string name="key_copied_to_clipboard">Giltz gakora kopiatu da!</string>
+ <string name="key_copied_to_clipboard">Giltza gakora kopiatu da!</string>
<string name="fingerprint_copied_to_clipboard">Hatz-aztarna gakora kopiatu da!</string>
<string name="select_key_to_certify">Mesedez hautatu baiztapenerako erabiltzeko giltza!</string>
<string name="key_too_big_for_sharing">Giltza handiegia da modu honetan elkarbanatzeko!</string>
@@ -279,7 +294,7 @@
<string name="error_no_signature_passphrase">ez da sarhitzik eman</string>
<string name="error_no_signature_key">ez da sinadura giltzarik eman</string>
<string name="error_invalid_data">OpenPGP eduki enkriptatu edo sinatu baliogabea!</string>
- <string name="error_integrity_check_failed">osotasun egiaztapen hutsigitea! Datuak aldatuak izan dira!</string>
+ <string name="error_integrity_check_failed">osotasun egiaztapen hutsegitea! Datuak aldatuak izan dira!</string>
<string name="error_wrong_passphrase">sarhitz okerra</string>
<string name="error_could_not_extract_private_key">ezin da giltza pribatua atera</string>
<!--errors without preceeding Error:-->
@@ -293,7 +308,8 @@
<!--results shown after decryption/verification-->
<string name="decrypt_result_no_signature">Sinatu Gabe</string>
<string name="decrypt_result_invalid_signature">Sinadura baliogabea!</string>
- <string name="decrypt_result_signature_uncertified"><b>baieztatugabeko</b> giltzak sinatua</string>
+ <string name="decrypt_result_insecure_cryptography">Sinadura baliogabea (Kriptografia segurtasun gabea)!</string>
+ <string name="decrypt_result_signature_uncertified"><b>baieztatu gabeko</b> giltzak sinatua</string>
<string name="decrypt_result_signature_secret">Zure giltzak sinatuta</string>
<string name="decrypt_result_signature_certified">Baieztatutako giltzak sinatuta</string>
<string name="decrypt_result_signature_expired_key"><b>iraungitutako</b> giltzak sinatua!</string>
@@ -301,7 +317,9 @@
<string name="decrypt_result_signature_missing_key"><b>giltza publiko ezezagunak</b> sinatuta</string>
<string name="decrypt_result_encrypted">Enkriptatuta</string>
<string name="decrypt_result_not_encrypted">Enkriptatu Gabea</string>
+ <string name="decrypt_result_insecure">Enkriptaketa Segurtasun-gabea</string>
<string name="decrypt_result_action_show">Erakutsi</string>
+ <string name="decrypt_invalid_text">Bietako bat, sinadura baliogabea da edo giltza ukatua izan da. Ezin zara zihur egon nork idatzi duen idazkia. Oraindik ere erakutsi dadin nahi duzu?</string>
<string name="decrypt_invalid_button">Ulertzen ditut arriskuak, erakutsi!</string>
<!--Add keys-->
<string name="add_keys_my_key">Nire giltza:</string>
@@ -311,6 +329,7 @@
<string name="progress_cancelling">ezeztatzen...</string>
<string name="progress_saving">gordetzen...</string>
<string name="progress_importing">inportatzen...</string>
+ <string name="progress_revoking_uploading">Giltza ukatzen eta igotzen...</string>
<string name="progress_updating">Giltzak eguneratzen...</string>
<string name="progress_exporting">esportatzen...</string>
<string name="progress_uploading">igotzen...</string>
@@ -358,6 +377,7 @@
<string name="progress_con_saving">sendotu: katxean gordetzen...</string>
<string name="progress_con_reimport">sendotu: berrinportatzen...</string>
<string name="progress_verifying_keyserver_url">giltza-zerbitzaria egiaztatzen...</string>
+ <string name="progress_starting_orbot">Orbot Abiarazten...</string>
<!--action strings-->
<string name="hint_cloud_search_hint">Bilatu Izena, Post@... bidez</string>
<!--key bit length selections-->
@@ -385,7 +405,7 @@
<string name="compression_fast">azkarra</string>
<string name="compression_very_slow">oso astiroa</string>
<!--Help-->
- <string name="help_tab_start">Hasi</string>
+ <string name="help_tab_start">Hasiera</string>
<string name="help_tab_faq">SEG</string>
<string name="help_tab_wot">Giltza Baieztapena</string>
<string name="help_tab_nfc_beam">NFC Beam</string>
@@ -441,6 +461,10 @@
<item quantity="one">Ongi ezabatu da bat giltza</item>
<item quantity="other">Ongi ezabatu dira %1$d giltza</item>
</plurals>
+ <plurals name="delete_ok_but_fail_2">
+ <item quantity="one">, baina hutsegitea egon da ezabatzerakoan bat giltza%2$s.</item>
+ <item quantity="other">, baina hutsegitea egon da ezabatzerakoan %1$d giltza%2$s.</item>
+ </plurals>
<plurals name="delete_ok">
<item quantity="one">Ongi ezabatu da giltza%2$s.</item>
<item quantity="other">Ongi ezabatu dira %1$d giltza%2$s.</item>
@@ -451,7 +475,24 @@
</plurals>
<string name="delete_nothing">Ez dago ezer ezabatzeko</string>
<string name="delete_cancelled">Ezabapen eragiketa ezeztaturik.</string>
+ <!--Revoke result toast (snackbar)-->
+ <string name="revoke_ok">Giltza ongi ukatu da.</string>
+ <string name="revoke_fail">Akatsa giltza ukatzerakoan!</string>
+ <string name="revoke_nothing">Ez dago ezer ukatzeko.</string>
+ <string name="revoke_cancelled">Ukatze eragiketa ezeztatuta.</string>
<!--Certify result toast-->
+ <plurals name="certify_keys_ok">
+ <item quantity="one">Ongi egiaztatuta giltza%2$s.</item>
+ <item quantity="other">Ongi egiaztatuta %1$d giltza%2$s.</item>
+ </plurals>
+ <plurals name="certify_keys_with_errors">
+ <item quantity="one">Egiaztagiritze hutsegitea!</item>
+ <item quantity="other">Egiaztagiritzeak huts egindu %d giltzekin!</item>
+ </plurals>
+ <plurals name="certify_error">
+ <item quantity="one">Egiaztagiritze hutsegitea!</item>
+ <item quantity="other">Hutsegitea %d giltzen egiaztagiritzean!</item>
+ </plurals>
<!--Intent labels-->
<string name="intent_decrypt_file">Dekriptatu Agiria OpenKeychain-rekin</string>
<string name="intent_import_key">Inportatu Giltza OpenKeychain-rekin</string>
@@ -472,7 +513,7 @@
<string name="api_settings_start">Abiarazi aplikazioa</string>
<string name="api_settings_delete_account">Ezabatu kontua</string>
<string name="api_settings_package_name">Pakete Izena</string>
- <string name="api_settings_package_certificate">Sinadura Paketearen SHA-256</string>
+ <string name="api_settings_package_certificate">Pakete Egiaztagiriaren SHA-256</string>
<string name="api_settings_accounts">Kontuak (API zaharra)</string>
<string name="api_settings_advanced">Argibide Hedatuak</string>
<string name="api_settings_allowed_keys">Ahalbidetutako Giltzak</string>
@@ -481,19 +522,31 @@
<string name="api_settings_accounts_empty">Ez dago konturik app honi erantsita.</string>
<string name="api_create_account_text">Ez dago giltzarik itxuratuta kontu honentzat. Mesedez hautatu dauden giltzetako bat edo sortu berri bat.\nAplikazioek hemen hautaturiko giltzekin bakarrik dekriptatu/sinatu dezakete.</string>
<string name="api_update_account_text">Kontu honetarako gordetako giltza ezabatua izan da. Mesedez hautatu beste bat!\nApliazioek hemen hautaturiko giltzekin bakarrik dekriptatu/sinatu dezakete!</string>
+ <string name="api_register_text">Erakusten den aplikazioak mezuak enkriptatu/dekriptatu eta sinatzea nahi ditu zure izenean.\nAhalbidetu sarbidea?\n\nKONTUZ: Ez badakizu zergaitik agertzen den ikusleiho hau, ez ahalbidetu sarbidea! Sarbidea ukatu dezakezu geroago \'Aplikazioak\' ikusleihoa erabiliz.</string>
<string name="api_register_allow">Ahalbidetu sarbidea</string>
<string name="api_register_disallow">Ez ahalbidetu sarbidea</string>
<string name="api_register_error_select_key">Mesedez hautatu giltza bat!</string>
- <string name="api_select_pub_keys_missing_text">Ez da giltzarik aurkitu nortasun hauentzat:</string>
- <string name="api_select_pub_keys_dublicates_text">Giltza bat baino gehiago dago nortasun hauentzat:</string>
- <string name="api_select_pub_keys_text">Mesedz berrikusi jasotzaile zerrenda!</string>
+ <string name="api_select_pub_keys_missing_text">Ez da giltzarik aurkitu posta helbide hauentzat:</string>
+ <string name="api_select_pub_keys_dublicates_text">Giltza bat baino gehiago daude posta helbide honekin:</string>
+ <string name="api_select_pub_keys_text">Mesedez berrikusi jasotzaile zerrenda!</string>
<string name="api_select_pub_keys_text_no_user_ids">Mesedez hautatu jasotzaileak!</string>
- <string name="api_error_wrong_signature">Sinadura egiaztapen hutsegitea! Aplikazio hau beste iturubur batetik duzu ezarrita? Zihur bazaude hau ez dela eraso bat, ukatu aplikazio honen erregistrazioa OpenKeychain eta orduan erregistratu aplikazioa berriro.</string>
+ <string name="api_error_wrong_signature">Sinadura egiaztapen hutsegitea! Aplikazio hau beste iturburu batetik duzu ezarrita? Zihur bazaude hau ez dela eraso bat, ukatu aplikazio honen erregistrazioa OpenKeychain eta orduan erregistratu aplikazioa berriro.</string>
<string name="api_select_sign_key_text">Mesedez hautatu zure giltzetako bat edo sortu berri bat.</string>
<string name="api_select_keys_text">Ahalbidetutako giltza batek ere ezin du edukia dekriptatu. Mesedez hautatu ahalbidetutako giltzak.</string>
<!--Share-->
<string name="share_qr_code_dialog_title">Elkarbanatu QR Kodearekin</string>
<string name="share_nfc_dialog">Elkarbanatu NFC-rekin</string>
+ <!--retry upload dialog-->
+ <string name="retry_up_dialog_title">Igoera hutsegitea!</string>
+ <string name="retry_up_dialog_message">Igoera hutsegitea. Nahi duzu eragiketa berriro saiatzea?</string>
+ <string name="retry_up_dialog_btn_reupload">Bersaiatu Eragiketa</string>
+ <string name="retry_up_dialog_btn_cancel">Ezeztatu Eragiketa</string>
+ <!--Delete or revoke private key dialog-->
+ <string name="del_rev_dialog_btn_revoke">Ukatu eta igo</string>
+ <string name="del_rev_dialog_btn_delete">Ezabatu bakarrik</string>
+ <!--Delete Or Revoke Dialog spinner-->
+ <string name="del_rev_dialog_choice_delete">Ezabatu bakarrik</string>
+ <string name="del_rev_dialog_choice_rev_upload">Ukatu eta Igo</string>
<!--Key list-->
<plurals name="key_list_selected_keys">
<item quantity="one">1 giltza hautaturik.</item>
@@ -518,7 +571,7 @@
<string name="key_view_tab_keybase">Keybase.io</string>
<string name="user_id_info_revoked_title">Ukatuta</string>
<string name="user_id_info_revoked_text">Nortasun hau ukatua izan da giltzaren jabeagaitik. Aurrerantzean ez da baliozkoa.</string>
- <string name="user_id_info_certified_title">Egiaztuta</string>
+ <string name="user_id_info_certified_title">Egiaztatuta</string>
<string name="user_id_info_certified_text">Nortasun hau zeuk egiaztatua da.</string>
<string name="user_id_info_uncertified_title">Egiaztatu gabea</string>
<string name="user_id_info_uncertified_text">Nortasun hau ez da egiaztagiritua izan oraindik. Ezin zara zihur egon nortasuna egitan dagokion adierazitako norbanakoari.</string>
@@ -536,14 +589,13 @@
<string name="key_trust_results_prefix">Keybase.io \"probak\" eskaintzen ditu giltza honen jabea baieztatzeko:</string>
<string name="key_trust_header_text">Oharra: Keybase.io egiaztapenak OpenKeychain-en ezaugarri esperimental bat da. QR kodeak eskaneatzea edo giltzak NFC bidez aldatzea gomendatzen dizugu hauek baieztatu ahal izateko.</string>
<!--keybase proof stuff-->
- <string name="keybase_narrative_twitter">Argitaratu Twitter-en honela</string>
- <string name="keybase_narrative_github">GitHub-en honela ezagutzen da</string>
- <string name="keybase_narrative_dns">Domeinu izena(k) kontrolatzen ditu</string>
- <string name="keybase_narrative_web_site">Ezin da Web gune(et)an aurkeztu</string>
- <string name="keybase_narrative_reddit">Argitaratu Reddit-en honela</string>
- <string name="keybase_narrative_coinbase">Coinbasen honela ezagutzen da</string>
- <string name="keybase_narrative_hackernews">Argitaratu Hacker News-en honela</string>
- <string name="keybase_narrative_unknown">Proba mota ezezaguna</string>
+ <string name="keybase_narrative_twitter">Argitaratu Twitter-en honela %s</string>
+ <string name="keybase_narrative_github">GitHub-en %s bezala ezagutzen da</string>
+ <string name="keybase_narrative_dns">%s domeinu izena(k) agintzen ditu</string>
+ <string name="keybase_narrative_web_site">%s Web gune(et)an argitaratu dezake</string>
+ <string name="keybase_narrative_reddit">Argitaratu Reddit-en %s bezala</string>
+ <string name="keybase_narrative_coinbase">Coinbasen %s bezala ezagutzen da</string>
+ <string name="keybase_narrative_hackernews">Argitaratu Hacker News-en %s bezala</string>
<string name="keybase_proof_failure">Zorigaitzez proba hau ezin da egiaztatu.</string>
<string name="keybase_unknown_proof_failure">Arazo ezezaguna proba egiaztatzailearekin</string>
<string name="keybase_problem_fetching_evidence">Arazoa probarekin</string>
@@ -553,6 +605,8 @@
<string name="keybase_message_payload_mismatch">Dekriptatutako proba ez dator bat itxarondako balioarekin</string>
<string name="keybase_message_fetching_data">Proba lortzen</string>
<string name="keybase_proof_succeeded">Proba hau egiaztatua izan da!</string>
+ <string name="keybase_a_post">Posta bat</string>
+ <string name="keybase_fetched_from">hemendik lortuta</string>
<string name="keybase_for_the_domain">domeinurako</string>
<string name="keybase_contained_signature">giltza honen jabeak bakarrik sortu ahal izan duen mezu bat du.</string>
<string name="keybase_twitter_proof">Txio bat</string>
@@ -634,6 +688,7 @@
<string name="drawer_open">Ireki nabigazio marraztzailea</string>
<string name="drawer_close">Itxi nabigazio marraztzailea</string>
<string name="my_keys">Nire Giltzak</string>
+ <string name="nav_backup">Babeskopia</string>
<!--hints-->
<string name="encrypt_content_edit_text_hint">Idatzi idazkia</string>
<!--certs-->
@@ -650,14 +705,14 @@
<string name="msg_cancelled">Eragiketa ezeztaturik.</string>
<!--Import Public log entries-->
<string name="msg_ip_bad_type_secret">Giltza-uztai sekretua publiko bezala inportatzeko saiakera. Hau akats bat da, mesedez agiritu jakinarazpen bat!</string>
- <string name="msg_ip_delete_old_fail">Ez da giltza zaharreik ezabatu (berri bat sortzen?)</string>
+ <string name="msg_ip_delete_old_fail">Ez da giltza zaharrik ezabatu (berri bat sortzen?)</string>
<string name="msg_ip_delete_old_ok">Giltza zaharra datubasetik ezabatu da</string>
<string name="msg_ip_encode_fail">Eragiketa hutsegitea kodeaketa akats bategaitik</string>
<string name="msg_ip_error_io_exc">Eragiketa hutsegitea s/i akats bategaitik</string>
<string name="msg_ip_error_op_exc">Eragiketa hutsegitea datubase akats bategaitik</string>
<string name="msg_ip_error_remote_ex">Eragiketa hutsegitea barneko akats bategaitik</string>
<string name="msg_ip">%s giltza-uztai publikoa inportatzen</string>
- <string name="msg_ip_insert_keyring">Giltza-uztai dautak kodeatzen</string>
+ <string name="msg_ip_insert_keyring">Giltza-uztai datuak kodeatzen</string>
<string name="msg_ip_insert_keys">Giltzak aztertzen</string>
<string name="msg_ip_prepare">Datubase eragiketak gertatzen</string>
<string name="msg_ip_master">%s maisu giltza prozesatzen</string>
@@ -702,7 +757,7 @@
<string name="msg_ip_subkey_flags_xxsx">Azpigiltza ikurrak: sinatu</string>
<string name="msg_ip_subkey_flags_xxxa">Azpigiltza ikurrak: egiaztatu</string>
<string name="msg_ip_subkey_flags_xxxx">Azpigiltza ikurrak: ezer ez</string>
- <string name="msg_ip_success">Giltza-uztai publikoa ongi iinportatu da</string>
+ <string name="msg_ip_success">Giltza-uztai publikoa ongi inportatu da</string>
<string name="msg_ip_success_identical">Giltza-uztaiak ez du datu berririk, ezer ez egiteko</string>
<string name="msg_ip_reinsert_secret">Giltza sekretua bir-txertatzen</string>
<string name="msg_ip_uid_cert_bad">Egiaztagiri gaitza aurkitu da!</string>
@@ -711,43 +766,73 @@
<string name="msg_ip_uid_cert_old">Egiaztagiria aurrekoa baino zaharragoa da, jauzi egiten.</string>
<string name="msg_ip_uid_cert_new">Egiaztagiria berriagoa da, aurrekoa ordezten.</string>
<string name="msg_ip_uid_cert_good">Egiaztagiri ona aurkitu da %1$s-rako</string>
+ <string name="msg_ip_uid_cert_good_revoke">%1$s-ren egiaztagiri ukatze ona aurkitu da </string>
+ <plurals name="msg_ip_uid_certs_unknown">
+ <item quantity="one">Ezikusten giltza publiko ezezagunak jaulkitako bat egiaztagiri</item>
+ <item quantity="other">Ezikusten giltza publiko ezezagunek jaulkitako %s egiaztagiri</item>
+ </plurals>
+ <string name="msg_ip_uid_classifying_zero">Erabiltzaile ID-ak sailkatzen (giltza ez fidagarriak erabiltzen)</string>
+ <plurals name="msg_ip_uid_classifying">
+ <item quantity="one">Erabiltzaile ID-ak sailkatzen (giltza fidagarri bat erabiltzen)</item>
+ <item quantity="other">Erabiltzaile ID-ak sailkatzen (%s giltza fidagarri erabiltzen)</item>
+ </plurals>
<string name="msg_ip_uid_reorder">Erabiltzaile ID-ak ber-antolatzen</string>
<string name="msg_ip_uid_processing">Erabiltzaile ID-a %s prozesatzen</string>
<string name="msg_ip_uid_revoked">Erabiltzaile ID-a ukatua dago</string>
+ <string name="msg_ip_uat_processing_image">Irudi motako erabiltzaile ezaugarria prozesatzen</string>
+ <string name="msg_ip_uat_processing_unknown">Mota ezezaguneko erabiltzaile ezaugarri prozesatzen</string>
<string name="msg_ip_uat_cert_bad">Egiaztagiri gaitza aurkitu da!</string>
<string name="msg_ip_uat_cert_error">Akatsa egiaztagiria prozesatzerakoan!</string>
<string name="msg_ip_uat_cert_nonrevoke">Jadanik badu ez-ukatu egiaztagiri bat, jauzi egiten.</string>
<string name="msg_ip_uat_cert_old">Egiaztagiria aurrekoa baino zaharragoa da, jauzi egiten.</string>
<string name="msg_ip_uat_cert_new">Egiaztagiria berriagoa da, aurrekoa ordezten.</string>
<string name="msg_ip_uat_cert_good">Egiaztagiri ona aurkitu da %1$s-rako</string>
+ <string name="msg_ip_uat_cert_good_revoke">Egiaztagiri ukatze ona aurkitu da %1$s-rentzat</string>
+ <plurals name="msg_ip_uat_certs_unknown">
+ <item quantity="one">Giltza publiko ezezagunak jaulkitako egiaztagiri bat ezikusten</item>
+ <item quantity="other">Giltza publiko ezezagunek jaulkitako %s egiaztagiri ezikusten</item>
+ </plurals>
<string name="msg_ip_uat_classifying">Erabiltzaile ezaugarriak sailkatzen</string>
<string name="msg_ip_uat_revoked">Erabiltzaile ezaugarria ukatua dago</string>
+ <string name="msg_is_bad_type_public">Giltza-uztai publiko sekretu bezala inportatzeko saiakera. Hau akats bat da, mesedez agiritu jakinarazpen bat!</string>
+ <string name="msg_is_bad_type_uncanon">Giltza-uztaia kanonikalizaziorik gabe inportatzeko saiakera. Hau akats bat da, mesedez agiritu jakinarazpen bat!</string>
<!--Import Secret log entries-->
- <string name="msg_is">%s giltza sekretua inportazen</string>
+ <string name="msg_is">%s giltza sekretua inportatzen</string>
<string name="msg_is_db_exception">Datubase akatsa!</string>
<string name="msg_is_importing_subkeys">Azpigiltza sekretuak prozesatzen</string>
<string name="msg_is_error_io_exc">Akatsa giltza-uztaia kodeatzerakoan</string>
<string name="msg_is_merge_public">Inportatutako datuak dagoen giltza-uztai publikoan batzen</string>
<string name="msg_is_merge_secret">Inportatutako datuak dagoen giltza-uztai publikoan batzen</string>
<string name="msg_is_pubring_generate">Giltza-uztai publikoa sortzen giltza-uztai sekreturako</string>
- <string name="msg_is_subkey_nonexistent">%s azpigailtza eskuraezina da giltza sekretuan</string>
+ <string name="msg_is_subkey_nonexistent">%s azpigiltza eskuraezina da giltza sekretuan</string>
<string name="msg_is_subkey_ok">%s azpigiltza eskuragarria bezala markatuta</string>
+ <string name="msg_is_subkey_pin">%s azpigiltza sekretua eskuragarri bezala markatuta, PIN-arekin</string>
<string name="msg_is_success_identical">Giltza-uztaiak ez du datu berririk, ezer ez egiteko</string>
<string name="msg_is_success">Giltza-uztai sekretua ongi inportatu da</string>
<!--Keyring Canonicalization log entries-->
+ <string name="msg_kc_error_v3">Hau OpenPGP 3 bertsioko giltza bat da, zeina zaharkituta dago eta ez da gehiago sostengatzen!</string>
<string name="msg_kc_error_no_uid">Giltza-uztaiak ez du baliozko erabiltzaile ID-rik!</string>
<string name="msg_kc_error_master_algo">Giltza maisuak algoritmo ezezagun bat erabiltzen du (%s)!</string>
<string name="msg_kc_master">Maisu giltza prozesatzen</string>
<string name="msg_kc_master_bad_type">Mota ezezaguneko (%s) maisu giltza egiaztagiria kentzen</string>
<string name="msg_kc_master_bad_err">Maisu giltza egiaztagiri gaitza kentzen</string>
+ <string name="msg_kc_master_bad_type_uid">Erabiltzaile ID egiaztagiria kentzen kokapen okerretik</string>
<string name="msg_kc_master_bad">Maisu giltza egiaztagiri gaitza kentzen</string>
<string name="msg_kc_sub">%s azpigiltza prozesatzen</string>
<string name="msg_kc_sub_bad_type">Azpigiltza egiaztagiri mota ezezaguna: %s</string>
<string name="msg_kc_sub_no_cert">Ez da baliozko egiaztagiririk aurkitu %s-rentzat, eraztunetik kentzen</string>
+ <string name="msg_kc_sub_revoke_bad_err">Azpigiltza ukatze egiaztagiri gaitza kentzen</string>
+ <string name="msg_kc_sub_revoke_bad">Azpigiltza ukatze egiaztagiri gaitza kentzen</string>
+ <string name="msg_kc_sub_unknown_algo">Azpigiltzak algoritmo ezezagun bat erabiltzen du, ez inportatzen...</string>
+ <string name="msg_kc_sub_algo_bad_encrpyt">Azpigiltzak enkriptaketa erabilpen ikurra du, baina ezin da enkriptaketarako algoritmoa aurkitu.</string>
+ <string name="msg_kc_sub_algo_bad_sign">Azpigiltzak sinadura erabilpen ikurra du, baina ezin da sinadurarako algoritmoa aurkitu.</string>
<string name="msg_kc_uid_bad_local">\'local\' ikurra duen erabiltzaile ID egiaztagiria kentzen</string>
<string name="msg_kc_uid_remove">Erabiltzaile ID \'%s\' baliogabea kentzen</string>
<string name="msg_kc_uid_warn_encoding">Erabiltzaile ID-a ez da UTF-8 bezala egiaztatu!</string>
+ <string name="msg_kc_uat_jpeg">JPEG motako erabiltzaile ezaugarria prozesatzen</string>
<string name="msg_kc_uat_unknown">Mota ezezaguneko erabiltzaile ezaugarria prozesatzen</string>
+ <string name="msg_kc_uat_dup">Erabiltzaile ezaugarri bikoiztua kentzen. Giltza-uztaiak beraietako bi ditu. Honek egiaztagiriak galtzea eragin dezake!</string>
+ <string name="msg_kc_uat_revoke_old">Erabiltzaile ezaugarrirako ukatze egiaztagiri zaharkitua kentzen </string>
<string name="msg_kc_uat_remove">Erabiltzaile ezaugarri baliogabea kentzen</string>
<string name="msg_kc_uat_warn_encoding">Erabiltzaile ID-a ez da UTF-8 bezala egiaztatu!</string>
<!--Keyring merging log entries-->
@@ -757,26 +842,40 @@
<string name="msg_mg_public">%s giltza-uztai publikoan batzen</string>
<string name="msg_mg_secret">%s giltza-uztai sekretuan batzen</string>
<string name="msg_mg_new_subkey">%s azpigiltza berria gehitzen</string>
- <string name="msg_mg_found_new">%s egiaztagiri berri aurkitu dira giltzuztaian</string>
+ <string name="msg_mg_found_new">%s egiaztagiri berri aurkitu dira giltza-uztaian</string>
<string name="msg_mg_unchanged">Ez dago ezer batzeko</string>
<!--createSecretKeyRing-->
<string name="msg_cr">Giltza maisu berria sortzen</string>
<string name="msg_cr_error_no_master">Ez da maisu giltza aukerarik adierazi!</string>
<string name="msg_cr_error_no_user_id">Giltza-uztaiak gutxienez erabiltzaile ID batekin sortu behar dira!</string>
- <string name="msg_cr_error_no_certify">Maisu giltzk egiaztagiri ikurra izan behar du!</string>
+ <string name="msg_cr_error_no_certify">Maisu giltzak egiaztagiri ikurra izan behar du!</string>
+ <string name="msg_cr_error_null_expiry">Epemuga ezin daiteke giltza sortzea baino \'lehenago\' izan. Hau programazio akats bat da, mesedez agiritu akats jakinarazpen bat!</string>
<string name="msg_cr_error_keysize_512">Giltza neurria 512 edo handiagoa izan behar da!</string>
<string name="msg_cr_error_no_curve">Ez da giltzaren neurria adierazi! Hau programazio akats bat da, mesedez agiritu akats jakinarazpen bat!</string>
<string name="msg_cr_error_internal_pgp">Barneko OpenPGP akatsa!</string>
<string name="msg_cr_error_unknown_algo">Algoritmo ezezaguna hautatu da! Hau programazio akats bat da, mesedez agiritu akats jakinarazpen bat!</string>
+ <string name="msg_cr_error_flags_dsa">Giltza ikur okerrak hautatuta, DSA ezin da erabili enkriptatzeko!</string>
+ <string name="msg_cr_error_flags_elgamal">Giltza ikur okerrak hautatuta, EIGamal ezin da erabili sinatzeko!</string>
+ <string name="msg_cr_error_flags_ecdsa">Giltza ikur okerrak hautatuta, ECDSA ezin da erabili enkriptatzeko!</string>
+ <string name="msg_cr_error_flags_ecdh">Giltza ikur okerrak hautatuta, ECDH ezin da erabili sinatzeko!</string>
<!--modifySecretKeyRing-->
<string name="msg_mr">%s giltza-uztaia aldatzen</string>
+ <string name="msg_mf_divert">Txartel adimentsura desbideratuko da kripto eragiketarako</string>
<string name="msg_mf_error_encode">Kodeaketa salbuespena!</string>
+ <string name="msg_mf_error_fingerprint">Oraingo giltzaren hatz-aztarna ez dator bat itxarondakoarekin!</string>
+ <string name="msg_mf_error_keyid">Ez dago giltza ID-rik. Hau barneko akats bat da, mesedez agiritu akats jakinarazpen bat!</string>
<string name="msg_mf_error_integrity">Barneko akatsa, osotasun egiaztapen hutsegitea!</string>
+ <string name="msg_mf_error_master_none">Ez da egiaztagiri maisuri aurkitu eragiketarako! (Guztiak ukatuta?)</string>
<string name="msg_mf_error_noexist_primary">Lehen erabiltzaile ID gaitza adierazi da!</string>
+ <string name="msg_mf_error_noexist_revoke">Erabiltzaile ID okerra adierazi da ukatzeko!</string>
+ <string name="msg_mf_error_restricted">Eragiketa murriztua sarhitzik gabe exekutatzeko saiakera! Hau programazio akats bat da, mesedez agiritu akats jakinarazpen bat!</string>
<string name="msg_mf_error_revoked_primary">Ukatutako erabiltzaile ID-ak ezin dira lehena izan!</string>
+ <string name="msg_mf_error_null_expiry">Epemuga ezin daiteke azpigiltza sortzea baino \'lehenago\' izan. Hau programazio akats bat da, mesedez agiritu akats jakinarazpen bat!</string>
<string name="msg_mf_error_noop">Ez dago ezer egiteko!</string>
+ <string name="msg_mf_error_passphrase_master">Akats larria giltza maisua dekriptatzerakoan! Hau programazio akats bat da, mesedez agiritu akats jakinarazpen bat!</string>
<string name="msg_mf_error_pgp">Barneko OpenPGP akatsa!</string>
<string name="msg_mf_error_sig">Sinadura salbuespena!</string>
+ <string name="msg_mf_error_conflicting_nfc_commands">Ezin da giltza txartel adimentsura mugitu txartelean sinadura sortzen duen eragiketa berean.</string>
<string name="msg_mf_error_invalid_flags_for_keytocard">Giltza ikur ezegokiak txartel adimentsu giltzarako.</string>
<string name="msg_mf_master">Maisu egiaztagiriak aldatzen</string>
<string name="msg_mf_notation_pin">PIN jakinarazpen paketea gehitzen</string>
@@ -785,21 +884,31 @@
<string name="msg_mf_admin_pin">Administrari PIN-a aldatzen txartelean</string>
<string name="msg_mf_passphrase_key">%s azpigiltza ber-enkriptatzen sarhitz berriarekin</string>
<string name="msg_mf_passphrase_empty_retry">Hutsegitea sarhitz berria ezartzerakoan, berriro saiatzen sarhitz zahar huts batekin</string>
+ <string name="msg_mf_passphrase_fail">Azpigiltzarentzako sarhitza ezin da aldatu! (Beste giltzen ezberdina du?)</string>
+ <string name="msg_mf_primary_replace_old">Aurreko lehen erabiltzaile ID-aren egiaztagiria ordezten</string>
+ <string name="msg_mf_primary_new">Egiaztagiri berria sortzen lehen erabiltzaile ID berriarentzat</string>
<string name="msg_mf_restricted_mode">Eragiketa modu murriztura aldatzen</string>
<string name="msg_mf_subkey_change">%s azpigiltza aldatzen</string>
<string name="msg_mf_require_passphrase">Sarhitza behar da eragiketetarako</string>
+ <string name="msg_mf_subkey_new">%s motako azpigiltza berria gehitzen</string>
<string name="msg_mf_subkey_new_id">Azpigiltza berriaren ID-a: %s</string>
<string name="msg_mf_error_past_expiry">Iraungitze eguna ezin da iraganean izan!</string>
<string name="msg_mf_subkey_revoke">%s azpigiltza ukatzen</string>
<string name="msg_mf_keytocard_start">%s azpigiltza txartel adimentsura mugitzen</string>
+ <string name="msg_mf_keytocard_finish">%1$s --&gt; %2$s txartel adimentsura mugitu da</string>
<string name="msg_mf_success">Giltza-uztaia ongi aldatu da</string>
+ <string name="msg_mf_uid_add">Erabiltzaile ID-a %s gehitzen</string>
<string name="msg_mf_uid_primary">Lehen erabiltzaile ID-a %s-ra aldatzen</string>
+ <string name="msg_mf_uid_revoke">Erabiltzaile ID-a %s ukatzen</string>
<string name="msg_mf_uid_error_empty">Erabiltzaile ID-a ezin da hutsik egon!</string>
<string name="msg_mf_uat_error_empty">Erabiltzaile ezaugarria ezin da hutsik egon!</string>
+ <string name="msg_mf_uat_add_image">Irudi motaren erabiltzaile ezaugarria gehitzen</string>
+ <string name="msg_mf_uat_add_unknown">Mota ezezaguneko erabiltzaile ezaugarria gehitzen</string>
<string name="msg_mf_unlock_error">Akatsa giltza-uztaia desblokeatzerakoan!</string>
<string name="msg_mf_unlock">Giltza-uztaia desblokeatzerakoan</string>
<!--Consolidate-->
<string name="msg_con">Datubasea sendotzen</string>
+ <string name="msg_con_error_bad_state">Sendotzea abiatu da datubasea katxeatu gabe! Hau zihurrenik programazio akats bat da, mesedez agiritu akats jakinarazpen bat.</string>
<string name="msg_con_error_concurrent">Sendotzea utzita, jadanik beste hari batean ekinean!</string>
<string name="msg_con_save_secret">Giltza-uztai sekretuak gordetzen</string>
<string name="msg_con_save_public">Giltza-uztai publikoak gordetzen</string>
@@ -818,22 +927,36 @@
<item quantity="other">%d giltza publiko berrinportatzen</item>
</plurals>
<string name="msg_con_reimport_public_skip">Ez dago giltza publikorik berrinportatzeko, jauzi egiten...</string>
+ <plurals name="msg_con_reimport_secret">
+ <item quantity="one">Giltza sekretu bat berrinportatzen</item>
+ <item quantity="other">%d giltza sekretu berrinportatzen</item>
+ </plurals>
<string name="msg_con_reimport_secret_skip">Ez dago giltza sekreturik berrinportatzeko, jauzi egiten...</string>
<string name="msg_con_warn_delete_public">Salbuespena katxe publikoaren agiria ezabatzerakoan</string>
+ <string name="msg_con_warn_delete_secret">Salbuespena katxe agiri sekretua ezabatzerakoan</string>
<!--Edit Key (higher level than modify)-->
<string name="msg_ed">Giltza eragiketa burutzen</string>
<string name="msg_ed_caching_new">Sarhitz berria katxeatzen</string>
+ <string name="msg_ed_error_no_parcel">Ez dago Gorde_Giltza-uztai_Eremua (hau akats bat da, mesedez jakinarazi)</string>
<string name="msg_ed_error_key_not_found">Giltza ez da aurkitu!</string>
+ <string name="msg_ed_error_extract_public_upload">Akatsa giltza publikoa igotzeko ateratzerakoan!</string>
+ <string name="msg_ed_fetching">Giltza lortzen aldatzeko (%s)</string>
<string name="msg_ed_success">Giltza eragiketa ongi burutu da</string>
<!--Promote key-->
<string name="msg_pr">Giltza publikoa giltza sekretura bultzatzen</string>
<string name="msg_pr_all">Azpigiltza guztiak sustatzen</string>
<string name="msg_pr_error_key_not_found">Giltza ez da aurkitu!</string>
+ <string name="msg_pr_fetching">Giltza lortzen aldatzeko (%s)</string>
<string name="msg_pr_subkey_match">Azpigiltza sustatzen: %s</string>
+ <string name="msg_pr_subkey_nomatch">Azpigiltza ez dago YubiKey-n: %s</string>
<string name="msg_pr_success">Giltza ongi sustatu da</string>
<!--Other messages used in OperationLogs-->
<string name="msg_ek_error_not_found">Giltza ez da aurkitu!</string>
<!--Messages for DecryptVerify operation-->
+ <string name="msg_dc_askip_no_key">Datuak ez daude giltza ezagun batekin enkriptatuta, jauzi egiten...</string>
+ <string name="msg_dc_askip_not_allowed">Datuak ez daude giltza ahalbidetu batekin enkriptatuta, jauzi egiten...</string>
+ <string name="msg_dc_charset">Idazburu hizkikodea aurkitu da: \'%s\'</string>
+ <string name="msg_dc_clear_data">Datu literalak prozesatzen</string>
<string name="msg_dc_clear_decompress">Konprimitutako datuak despaketatzen</string>
<string name="msg_dc_clear_meta_file">Agirizena: %s</string>
<string name="msg_dc_clear_meta_mime">MIME mota: %s</string>
@@ -841,16 +964,18 @@
<string name="msg_dc_clear_meta_size_unknown">Agiri neurria ezezaguna da</string>
<string name="msg_dc_clear_meta_time">Aldaketa ordua: %s</string>
<string name="msg_dc_clear_signature_bad">Sinadura egiaztapena EZ ONGI!</string>
- <string name="msg_dc_insecure_hash_algo">Hash algoritmo sostengatu gabea eta potentzialki segurtasun gabea!</string>
<string name="msg_dc_clear_signature_check">Sinadura datuak egiaztatzen</string>
<string name="msg_dc_clear_signature_ok">Sinadura egiaztapena ONGI</string>
<string name="msg_dc_clear_signature">Sinadura datuak gerorako gordetzen</string>
<string name="msg_dc_clear">Cleartext datuak prozesatzen</string>
<string name="msg_dc_error_bad_passphrase">Akatsa giltza desblokeatzerakoan, sarhitz gaitza!</string>
+ <string name="msg_dc_error_sym_passphrase">Akatsa datuak dekriptatzerakoan! (Sar-esaldi gaitza?)</string>
<string name="msg_dc_error_corrupt_data">Datuak hondatuta daude!</string>
<string name="msg_dc_error_extract_key">Akats ezezaguna giltza desblokeatzerakoan!</string>
<string name="msg_dc_error_integrity_check">Osotasun egiaztapen akatsa!</string>
<string name="msg_dc_error_invalid_data">OpenPGP eduki enkriptatu edo sinatu baliogabea!</string>
+ <string name="msg_dc_error_io">Akats bat aurkitu da sarrera datuak irakurtzerakoan!</string>
+ <string name="msg_dc_error_input">Akatsa sarrerako datu jarioa irekitzerakoan!</string>
<string name="msg_dc_error_no_data">Ez da datu enkriptaturik aurkitu jarioan!</string>
<string name="msg_dc_error_no_key">Ez da enkriptatutako daturik giltza sekretu ezagunarekin aurkitu jarioan!</string>
<string name="msg_dc_error_pgp_exception">OpenPGP Salbuespen bat aurkitu da eragiketan zehar!</string>
@@ -864,7 +989,10 @@
<string name="msg_dc">Dekriptaketa eragiketa abiatzen...</string>
<string name="msg_dc_sym_skip">Datu simetrikoak ez daude ahalbidetuta, jauzi egiten...</string>
<string name="msg_dc_unlocking">Giltza sekretua desblokeatzen</string>
- <string name="msg_dc_insecure_symmetric_encryption_algo">Potentzialki segurtasun gabea den enkriptaketa algoritmoa erabili da!</string>
+ <string name="msg_dc_insecure_symmetric_encryption_algo">Enkriptaketa algoritmo segurtasun gabea erabili da! Hau aplikazioa eguneratu gabe dagoelako, edo eraso bategaitik gertatu daiteke.</string>
+ <string name="msg_dc_insecure_hash_algo">Hash algoritmo segurtasun gabea erabili da! Hau aplikazioa eguneratu gabe dagoelako, edo eraso bategaitik gertatu daiteke.</string>
+ <string name="msg_dc_insecure_mdc_missing">Ez dago Aldaketa Atzemate Kodea (MDC) paketea! Hau aplikazioa eguneratu gabe dagoelako edo beheratze eraso bategaitik gertatu daiteke.</string>
+ <string name="msg_dc_insecure_key">Segurtasun gabeko giltza: Bietako bat, edo RSA/DSA/ElGamal bit luzera laburregia da edo ECC bihurgune/algoritmoa segurtasun gabekotzat hartzen da! Hau aplikazioa eguneratu gabe dagoelako, edo eraso bategaitik gertatu daiteke.</string>
<!--Messages for VerifySignedLiteralData operation-->
<string name="msg_vl">Sinadura egiaztapena abiatzen</string>
<string name="msg_vl_error_wrong_key">Mezua ez dago giltza zuzenarekin sinatuta</string>
@@ -885,10 +1013,10 @@
<string name="msg_se_success">Sinadura/enkriptaketa eragiketa ongi</string>
<!--Messages for PgpSignEncrypt operation-->
<string name="msg_pse_asymmetric">Giltza publikoak gertatzen enkriptaketarako</string>
+ <string name="msg_pse_clearsign_only">Cleartext sarrera sinadura ez dago sostengatuta!</string>
<string name="msg_pse_compressing">Konpresioa gertatzen</string>
<string name="msg_pse_encrypting">Datuak enkriptatzen</string>
<string name="msg_pse_error_bad_passphrase">Sarhitz gaitza!</string>
- <string name="msg_pse_error_hash_algo">Eskatutako hash algoritmoa ez dago sostengatuta giltza honetan!</string>
<string name="msg_pse_error_io">SI Salbuespen bat aurkitu da eragiketan zehar!</string>
<string name="msg_pse_error_key_sign">Hautaturiko sinatze giltzak ezin du daturik sinatu!</string>
<string name="msg_pse_error_sign_key">Akatsa giltza sinatua lortzerakoan!</string>
@@ -905,7 +1033,7 @@
<string name="msg_pse_pending_passphrase">Sarhitza beharrezkoa, erabiltzaile sarrera eskatzen...</string>
<string name="msg_pse_signing">Datuak sinatzen (enkriptaketa gabe)</string>
<string name="msg_pse_signing_cleartext">Cleartext sinadura sortzen</string>
- <string name="msg_pse_signing_detached">Sinadura deserntsia sortzen</string>
+ <string name="msg_pse_signing_detached">Sinadura deserantsia sortzen</string>
<string name="msg_pse_sigcrypting">Datuak sinadurarekin enkriptatzen</string>
<string name="msg_pse">Sinadura eta/edo enkriptaketa eragiketa abiatzen</string>
<string name="msg_pse_symmetric">Enkriptaketa simetrikoa gertatzen</string>
@@ -932,7 +1060,7 @@
<string name="msg_import_fetch_error_decode">Akatsa berreskuratutako giltza-uztai dekodeatzerakoan!</string>
<string name="msg_import_fetch_error">Giltza ezin da berreskuratu! (Sare arazoak?)</string>
<string name="msg_import_fetch_keybase">keybase.io-tik berreskuratzen: %s</string>
- <string name="msg_import_fetch_keyserver_error">Ezin da giltza giltza-zerbitzarietatik berreskuratu: %s</string>
+ <string name="msg_import_fetch_error_keyserver">Ezin da giltza giltza-zerbitzarietatik berreskuratu: %s</string>
<string name="msg_import_fetch_keyserver">Giltza-zerbitzaritik berreskuratzen: %s</string>
<string name="msg_import_fetch_keyserver_ok">Giltza ongi berreskuratu da</string>
<string name="msg_import_keyserver">%s giltza-zerbitzaria erabiltzen</string>
@@ -960,7 +1088,7 @@
<string name="msg_export_error_db">Datubase akatsa!</string>
<string name="msg_export_error_io">Sarrera/irteera akatsa!</string>
<string name="msg_export_error_key">Akatsa giltza datuak aurre-prozesatzerakoan!</string>
- <string name="msg_export_error_upload">Hutsegitea giltza zerbitzara igotzean! Mesedez egiaztatu zure internet elkarketa.</string>
+ <string name="msg_export_error_upload">Hutsegitea giltza zerbitzarira igotzean! Mesedez egiaztatu zure internet elkarketa.</string>
<string name="msg_export_success">Esportatze eragiketa ongi burutu da!</string>
<string name="msg_export_upload_success">Giltza-zerbitzarira igotzea ongi!</string>
<string name="msg_del_error_empty">Ez dago ezer ezabatzeko!</string>
@@ -980,11 +1108,25 @@
<item quantity="one">Hutsegitea giltza bat ezabatzerakoan</item>
<item quantity="other">Hutsegitea %d giltza ezabatzerakoan</item>
</plurals>
+ <string name="msg_revoke_error_empty">Ez dago ezer ukatzeko!</string>
+ <string name="msg_revoke_error_not_found">Ezin da giltza aurkitu ukatzeko!</string>
+ <string name="msg_revoke_key">%s giltza ukatzen</string>
+ <string name="msg_revoke_key_fail">Hutsegitea giltza ukatzerakoan</string>
+ <string name="msg_revoke_ok">Giltza ongi ukatu da</string>
<string name="msg_acc_saved">Kontua gordeta</string>
<string name="msg_download_success">Ongi jeitsi da!</string>
<string name="msg_download_no_valid_keys">Ez da baliozko giltzarik aurkitu agiri/gakoan!</string>
+ <string name="msg_download_no_pgp_parts">TODO: anitzak!</string>
+ <plurals name="error_import_non_pgp_part">
+ <item quantity="one">gertatutako agiriaren zati bat baliozko OpenPGP objetua da baina ez OpenPGP giltza</item>
+ <item quantity="other">gertatutako agiriaren zati batzuk baliozko OpenPGP objetuak dira baina ez OpenPGP giltzak</item>
+ </plurals>
+ <string name="msg_download_query_too_short">Bilaketa eskaera laburregia. Mesedez zehaztu zure eskaera!</string>
+ <string name="msg_download_too_many_responses">Giltza bilaketa eskaerak hautagai gehiegi itzuli ditu. Mesedez zehaztu zure eskaera!</string>
+ <string name="msg_download_query_too_short_or_too_many_responses">Ez dago giltzarik edo gehiegi aurkitu dira. Mesedez hobetu zure eskaera!</string>
<string name="msg_download_query_failed">Akats bat gertatu da giltzak bilatzerakoan.</string>
<!--Messages for Keybase Verification operation-->
+ <string name="msg_keybase_verification">Giltzabase egiaztapen saiakera %s-rentzat</string>
<string name="msg_keybase_error_dns_fail">DNS TXT Grabaketa berreskurapen hutsegitea</string>
<string name="msg_keybase_error_specific">%s</string>
<!--Messages for Export Log operation-->
@@ -1002,6 +1144,7 @@
<string name="passp_cache_notif_keys">Gogoratutako sarhitzak</string>
<string name="passp_cache_notif_clear">Garbitu Sarhitzak</string>
<string name="passp_cache_notif_pwd">Sarhitza</string>
+ <!--Keyserver sync-->
<!--First Time-->
<string name="first_time_text1">Berreskuratu zure pribatutasuna OpenKeychain-ekin!</string>
<string name="first_time_create_key">Sortu nire giltza</string>
@@ -1010,6 +1153,10 @@
<string name="first_time_skip">Jauzi Ezarpena</string>
<string name="first_time_blank_yubikey">YubiKey huts hau erabiltzea nahi duzu OpenKeychain-ekin?\n\nMesedez irten Yubikey-tik orain, berriro galdetuko zaizu beharrezkoa denean!</string>
<string name="first_time_blank_yubikey_yes">Erabili YubiKey hau</string>
+ <string name="backup_text">Zure jabetzako giltzak dituzten babeskopiak inoiz ez dira besteekin elkarbanatu behar!</string>
+ <string name="backup_all">Giltza guztiak + zeure jabetzako giltzak</string>
+ <string name="backup_public_keys">Giltza guztiak</string>
+ <string name="backup_section">Babeskopia</string>
<!--unsorted-->
<string name="section_certifier_id">Egiaztatzailea</string>
<string name="section_cert">Egiaztagiriaren Xehetasunak</string>
@@ -1025,6 +1172,7 @@
<string name="label_cert_type">Mota</string>
<string name="error_key_not_found">Giltza ez da aurkitu!</string>
<string name="error_key_processing">Akatsa giltza prozesatzerakoan!</string>
+ <string name="key_divert">desbideratu txartel adimentsura</string>
<string name="key_no_passphrase">sarhitzik gabe</string>
<string name="key_unavailable">eskuraezina</string>
<string name="secret_cannot_multiple">Zure jabetzako giltzak banaka bakarrik ezabatu daitezke!</string>
@@ -1032,7 +1180,6 @@
<string name="unknown_algorithm">ezezaguna</string>
<string name="can_sign_not">ezin da sinatu</string>
<string name="error_no_encrypt_subkey">Ez dago enkriptaketa azpigiltzarik eskuragarri!</string>
- <string name="account_no_manual_account_creation">Ez sortu OpenKeychain-Kontuak eskuz.\n.Argibide gehiagorako, ikusi Laguntza.</string>
<string name="contact_show_key">Erakutsi (%s) giltza</string>
<string name="swipe_to_update">Irristatu behera giltza-zerbitzaritik eguneratzeko</string>
<string name="error_no_file_selected">Hautatu agiri bat gutxienez enkriptatzeko!</string>
@@ -1043,6 +1190,11 @@
<string name="key_colon">Giltza:</string>
<string name="exchange_description">Giltza trukatzea bat hasteko, hautatu eskuinaldean kide zenbatekoa, orduan sakatu \"Hasi trukatzea\" botoia.\n\nBeste bi galdera egingo zaizkizu kide zuzenek besterik ez dutela eskuhartzen eta beren hatz-aztarnak zuzenak direla zihurtatzeko.</string>
<string name="btn_start_exchange">Hasi trukatzea</string>
+ <string name="user_id_none"><![CDATA[<none>]]></string>
+ <!--Android Account-->
+ <string name="account_no_manual_account_creation">Ezin duzu OpenKeychain konturik sortu eskuz.</string>
+ <string name="account_privacy_title">Pribatutasuna</string>
+ <string name="account_privacy_text">OpenKeychain-ek ez ditu zure harremanak Internet-ekin aldiberetzen. Harremanak giltzekin loturatzen ditu besterik gabe izen eta post@ helbideetan ohinarrituta. Hau lineaz-kanpo egiten du zure gailuan.</string>
<!--Passphrase wizard-->
<!--TODO: rename all the things!-->
<string name="title_unlock_method">Hautatu desblokeatze metodo bat</string>
@@ -1070,11 +1222,27 @@
<string name="nfc_settings">Ezarpenak</string>
<string name="snack_yubikey_view">Ikusi</string>
<string name="snack_yubikey_import">Inportatu</string>
+ <string name="button_bind_key">Blindatu Giltza</string>
<string name="yubikey_serno">Serie Zbk: %s</string>
<string name="yubikey_create">Jarri YubiKey zure gailuaren atzealdean.</string>
<string name="btn_import">Inportatu</string>
<string name="snack_yubi_other">Giltza ezberdina biltegiratuta YubiKey-n!</string>
<string name="error_nfc">NFC Akatsa: %s</string>
+ <plurals name="error_pin">
+ <item quantity="one">PIN okerra!\n%d saiakera gelditzen da.</item>
+ <item quantity="other">PIN okerra!\n%d saiakera gelditzen dira.</item>
+ </plurals>
+ <string name="error_nfc_terminated">YubiKey amaiera egoeran.</string>
+ <string name="error_nfc_wrong_length">Sartutako PIN-a laburregia da. PIN-ak gutxienez 6 digituko luzera du.</string>
+ <string name="error_nfc_conditions_not_satisfied">Ez dira erabilpen baldintzak asetu.</string>
+ <string name="error_nfc_security_not_satisfied">Ez da segurtasun egoera asetu.</string>
+ <string name="error_nfc_authentication_blocked">PIN-a blokeatuta saiakera gehiegiren ondoren.</string>
+ <string name="error_nfc_data_not_found">Giltza edo objetua ez da aurkitu.</string>
+ <string name="error_nfc_unknown">Akats Ezezaguna</string>
+ <string name="error_nfc_bad_data">YubiKeyk datu baliogabeak jakinarazi ditu.</string>
+ <string name="error_nfc_chaining_error">YubiKeyk itxaroten zuen azken agindua kate batean.</string>
+ <string name="error_nfc_header">YubiKeyk %s byte baliogabe jakinarazi ditu.</string>
+ <string name="error_nfc_try_again">Saitu berriro</string>
<string name="error_pin_nodefault">Berezko PIN-a baztertua izan da!</string>
<string name="error_temp_file">Akatsa aldibaterako agiria sortzerakoan.</string>
<string name="btn_delete_original">Ezabatu jatorrizko agiria</string>
@@ -1092,7 +1260,7 @@
<string name="intent_show">Erakutsi Sinatutako/Enkriptatutako Edukia</string>
<string name="view_internal">Ikusi OpenKeychain-en</string>
<string name="error_preparing_data">Akatsa datuak gertatzerakoan!</string>
- <string name="label_clip_title">Enkriptatutatako Datuak</string>
+ <string name="label_clip_title">Enkriptatutako Datuak</string>
<string name="progress_processing">Prozesatzen...</string>
<string name="error_saving_file">Akatsa agiria gordetzerakoan!</string>
<string name="file_saved">Agiria gordeta!</string>
@@ -1100,4 +1268,8 @@
<string name="file_delete_none">Ez da agiria ezabatu! (Jadanik ezabatuta?)</string>
<string name="file_delete_exception">Jatorrizko agiria ezin da ezabatu!</string>
<string name="error_clipboard_empty">Gakoa hutsik dago!</string>
+ <string name="error_clipboard_copy">Akatsa datuak gakora kopiatzerakoan!</string>
+ <string name="error_scan_fp">Akatsa hatz-aztarna eskaneatzerakoan!</string>
+ <string name="error_scan_match">Hatz-aztarnak ez datoz bat!</string>
+ <string name="error_expiry_past">Iraungitze eguna iraganda dago!</string>
</resources>
diff --git a/OpenKeychain/src/main/res/values-fa/strings.xml b/OpenKeychain/src/main/res/values-fa/strings.xml
new file mode 100644
index 000000000..86d8ab5cd
--- /dev/null
+++ b/OpenKeychain/src/main/res/values-fa/strings.xml
@@ -0,0 +1,333 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<resources>
+ <!--GENERAL: Please put all strings inside quotes as described in example 1 on
+ http://developer.android.com/guide/topics/resources/string-resource.html (scroll down to "Escaping apostrophes and quotes").-->
+ <string name="app_name">دسته کلید باز</string>
+ <!--title-->
+ <string name="title_encrypt_text">رمزگذاری</string>
+ <string name="title_encrypt_files">رمزگذاری</string>
+ <string name="title_decrypt">رمزگشایی</string>
+ <string name="title_add_subkey">اضافه کردن زیرکلید</string>
+ <string name="title_edit_key">ویرایش کید</string>
+ <string name="title_preferences">تنظیمات</string>
+ <string name="title_api_registered_apps">برنامه‌ها</string>
+ <string name="title_key_server_preference">سرورهای کلید OpenPGP</string>
+ <string name="title_change_passphrase">تغییر رمزعبور</string>
+ <string name="title_share_fingerprint_with">به اشتراک گذاری اثر انگشت با...</string>
+ <string name="title_share_key">به اشتراک گذاری کلید با...</string>
+ <string name="title_share_file">به اشتراک گذاری فایل با...</string>
+ <string name="title_share_message">به اشتراک گذاری متن با...</string>
+ <string name="title_encrypt_to_file">رمزگذاری به فایل</string>
+ <string name="title_decrypt_to_file">رمزگشایی از فایل</string>
+ <string name="title_import_keys">وارد کردن کلیدها</string>
+ <string name="title_export_key">پشتیبان‌گیری از کلید</string>
+ <string name="title_export_keys">پشتیبان‌گیری از کلیدها</string>
+ <string name="title_key_not_found">کلید پیدا نشد</string>
+ <string name="title_send_key">آپلود در سرور کلید</string>
+ <string name="title_certify_key">تأیید کلید</string>
+ <string name="title_key_details">جزئیات کلید</string>
+ <string name="title_help">کمک</string>
+ <string name="title_log_display">لاگ</string>
+ <string name="title_exchange_keys">مبادلهٔ کلیدها</string>
+ <string name="title_advanced_key_info">اطلاعات بیشتر</string>
+ <string name="title_delete_secret_key">آیا کلید \'%s\' خود را پاک می‌کنید؟</string>
+ <string name="title_export_log">خروج لاگ</string>
+ <string name="title_manage_my_keys">مدیریت کلیدهام</string>
+ <!--section-->
+ <string name="section_user_ids">هویت‌ها</string>
+ <string name="section_yubikey">کلید Yubi</string>
+ <string name="section_should_you_trust">آیا به این کلید اعتماد دارید؟</string>
+ <string name="section_keys">زیرکلیدها</string>
+ <string name="section_cloud_search">جستجوی اینترنت</string>
+ <string name="section_proxy_settings">تنظیمات پراکسی</string>
+ <string name="section_gui">رابط</string>
+ <string name="section_certify">تأیید</string>
+ <string name="section_share_key">کلید</string>
+ <string name="section_key_server">سرور کلید</string>
+ <string name="section_fingerprint">اثر انگشت</string>
+ <string name="section_encrypt">رمزگذاری</string>
+ <string name="section_decrypt">رمزگشایی/بررسی</string>
+ <string name="section_current_expiry">انقضأ فعلی</string>
+ <string name="section_new_expiry">انقضأ جدید</string>
+ <!--button-->
+ <string name="btn_decrypt_verify_file">رمزگشایی، بررسی و ذخیره فایل</string>
+ <string name="btn_encrypt_share_file">رمزگذاری و به اشتراک گذاری فایل</string>
+ <string name="btn_encrypt_save_file">رمزگذاری و ذخیرهٔ فایل</string>
+ <string name="btn_save_file">ذخیرهٔ فایل</string>
+ <string name="btn_save">ذخیره</string>
+ <string name="btn_view_log">مشاهدهٔ لاگ</string>
+ <string name="btn_do_not_save">انصراف</string>
+ <string name="btn_delete">حذف</string>
+ <string name="btn_no_date">بدون انقضأ</string>
+ <string name="btn_okay">تأیید</string>
+ <string name="btn_export_to_server">آپلود در سرور کلید</string>
+ <string name="btn_next">بعدی</string>
+ <string name="btn_back">قبلی</string>
+ <string name="btn_no">نه</string>
+ <string name="btn_match">اثر انگشت‌ها مطابقت دارد</string>
+ <string name="btn_share_encrypted_signed">رمزگذاری و به اشتراک گذاری متن</string>
+ <string name="btn_copy_encrypted_signed">رمزگذاری و کپی متن</string>
+ <string name="btn_create_key">ساخت کلید</string>
+ <string name="btn_add_files">اضافه کردن فایل(ها)</string>
+ <string name="btn_share_decrypted_text">اشتراک گذاری متن رمزگشایی شده</string>
+ <string name="btn_copy_decrypted_text">کپی متن رمزگشایی شده</string>
+ <string name="btn_decrypt_clipboard">خواندن از متن کپی‌شده</string>
+ <string name="btn_decrypt_files">انتخاب فایل ورودی</string>
+ <string name="btn_encrypt_files">رمزگذاری فایلها</string>
+ <string name="btn_encrypt_text">رمزگذاری فایل</string>
+ <string name="btn_add_email">اضافه کردن ایمیلی دیگر</string>
+ <string name="btn_unlock">بازکردن قفل</string>
+ <string name="btn_add_keyserver">اضافه‌کردن</string>
+ <string name="btn_save_default">ذخیره به عنوان پیش‌فرض</string>
+ <string name="btn_saved">ذخیره شد!</string>
+ <!--menu-->
+ <string name="menu_preferences">تنظیمات</string>
+ <string name="menu_help">کمک</string>
+ <string name="menu_export_key">پشتیبان‌گیری به فایل</string>
+ <string name="menu_delete_key">حذف کلید</string>
+ <string name="menu_manage_keys">مدیریت کلیدهای من</string>
+ <string name="menu_search">جستجو</string>
+ <string name="menu_nfc_preferences">تنظیمات NFC</string>
+ <string name="menu_beam_preferences">تنظیمات Beam</string>
+ <string name="menu_encrypt_to">رمزگذاری به...</string>
+ <string name="menu_select_all">انتخاب همه</string>
+ <string name="menu_export_all_keys">خروج همهٔ کلیدها</string>
+ <string name="menu_update_all_keys">آپدیت همهٔ کلیدها</string>
+ <string name="menu_advanced">اطلاعات بیشتر</string>
+ <string name="menu_certify_fingerprint">تأیید با مقایسهٔ اثر انگشت</string>
+ <string name="menu_export_log">خروج لاگ</string>
+ <string name="menu_keyserver_add">اضافه‌کردن</string>
+ <!--label-->
+ <string name="label_message">متن</string>
+ <string name="label_file">فایل</string>
+ <string name="label_files">فایل(ها)</string>
+ <string name="label_file_colon">فایل</string>
+ <string name="label_no_passphrase">بدون رمزعبور</string>
+ <string name="label_passphrase">رمزعبور</string>
+ <string name="label_unlock">در حال بازکردن...</string>
+ <string name="label_passphrase_again">تکرار رمزعبور</string>
+ <string name="label_show_passphrase">نمایش رمزعبور</string>
+ <string name="label_algorithm">الگوریتم</string>
+ <string name="label_ascii_armor">فایل ASCII Armor</string>
+ <string name="label_file_ascii_armor">فعال‌کردن ASCII Armor</string>
+ <string name="label_write_version_header">به دیگران اطلاع دهید که شما از OpenKeyChain استفاده می‌کنید</string>
+ <string name="label_write_version_header_summary">عبارت \'OpenKeychain v2.7\' را در امضاها، متن رمزگذاری‌شده و کلیدها می‌نویسید</string>
+ <string name="label_use_default_yubikey_pin">از رمزِ PIN پیش‌فرضِ کلید Yubi استفاده کن</string>
+ <string name="label_use_num_keypad_for_yubikey_pin">از صفحه‌کلیدِ شماره‌ای برای وارد کردن رمز کلیدِ Yubi استفاده کن</string>
+ <string name="label_asymmetric_from">امضاء با:</string>
+ <string name="label_to">رمزگذاری به:</string>
+ <string name="label_delete_after_encryption">حذف فایل‌ها پس از رمزگذاری</string>
+ <string name="label_delete_after_decryption">حذف پس از رمزگشایی</string>
+ <string name="label_encryption_algorithm">الگوریتم رمزگذاری</string>
+ <string name="label_hash_algorithm">الگوریتم هَش</string>
+ <string name="label_symmetric">رمزگذاری با رمز عبور</string>
+ <string name="label_passphrase_cache_ttl">زمان را به یاد داشته باش</string>
+ <string name="label_passphrase_cache_subs">رمز‌عبورها را با زیرکلیدها به یاد داشته باش</string>
+ <string name="label_message_compression">فشرده‌کردن متن</string>
+ <string name="label_file_compression">فشرده‌کردن فایل</string>
+ <string name="label_keyservers">سرور کلید OpenPGP را انتخاب کنید</string>
+ <string name="label_key_id">هویت کلید</string>
+ <string name="label_key_created">کلید ساخته شد %s</string>
+ <string name="label_creation">ساخت</string>
+ <string name="label_expiry">انقضأ</string>
+ <string name="label_usage">مصرف</string>
+ <string name="label_key_size">اندازهٔ کلید</string>
+ <string name="label_main_user_id">هویت اصلی</string>
+ <string name="label_name">نام</string>
+ <string name="label_comment">توضیحات</string>
+ <string name="label_email">ایمیل</string>
+ <string name="label_send_key">همگام‌سازی با اینترنت</string>
+ <string name="label_fingerprint">اثر انگشت</string>
+ <string name="expiry_date_dialog_title">تعیین تاریخ انقضأ</string>
+ <string name="label_keyservers_title">سرورِ کلیدها</string>
+ <string name="label_keyserver_settings_hint">برای ویرایش/حذف تَپ کنید و برای تغییر ترتیب بکشید</string>
+ <string name="label_selected_keyserver_title">سرور کلیدِ انتخاب شده</string>
+ <string name="label_preferred">ترجیح داده‌شده</string>
+ <string name="label_enable_compression">فشرده‌کردن</string>
+ <string name="label_encrypt_filenames">رمزگذاری اسمِ فایل‌ها</string>
+ <string name="label_hidden_recipients">مخفی‌کردن گیرنده‌ها</string>
+ <string name="label_verify_keyserver">بررسی سرورِ کلیدها</string>
+ <string name="label_enter_keyserver_url">آدرس URL سرورِ کلید را وارد کنید</string>
+ <string name="label_keyserver_dialog_delete">حذف سرورهای کلید</string>
+ <string name="label_theme">قالب</string>
+ <string name="pref_keyserver">سرورهای کلید OpenPGP</string>
+ <!--label shown in Android settings under the OpenKeychain account-->
+ <!--Proxy Preferences-->
+ <string name="pref_proxy_tor_title">فعال‌کردن Tor</string>
+ <string name="pref_proxy_tor_summary">برنامهٔ Orbot باید نصب شده باشد</string>
+ <string name="pref_proxy_normal_title">فعال کردن پراکسی دیگر</string>
+ <!--proxy type choices and values-->
+ <!--OrbotHelper strings-->
+ <!--InstallDialogFragment strings-->
+ <!--StartOrbotDialogFragment strings-->
+ <!--choice-->
+ <!--key flags-->
+ <string name="flag_sign">امضاء کردن</string>
+ <string name="flag_encrypt">رمزگذاری</string>
+ <string name="flag_authenticate">تصدیق کردن</string>
+ <!--sentences-->
+ <string name="wrong_passphrase">رمزعبور اشتباه است.</string>
+ <string name="no_filemanager_installed">برنامهٔ مدیریتِ فایل سازگاری نصب نیست.</string>
+ <string name="passphrases_do_not_match">رمز عبور‌ها مطابقت ندارند.</string>
+ <string name="passphrase_must_not_be_empty">لطفاً یک رمزعبور وارد کنید.</string>
+ <string name="passphrase_for_symmetric_encryption">رمزگذاری متقارن(فقط با یک رمزعبور)</string>
+ <string name="passphrase_for">وارد کردن رمز عبور برای \'%s\'</string>
+ <string name="pin_for">وارد کردن رمزِ پین برای \'%s\'</string>
+ <string name="keys_exported">%d کلید با موفقیت خارج شد.</string>
+ <string name="list_empty">این لیست خالی است!</string>
+ <string name="key_copied_to_clipboard">کلید در حافظه کپی شده است!</string>
+ <string name="fingerprint_copied_to_clipboard">اثر انگشت در حافظه کپی شده است!</string>
+ <string name="select_key_to_certify">لطفاً یک کلید برای تأیید کردن انتخاب کنید!</string>
+ <string name="key_too_big_for_sharing">کلید خیلی بزرگ است و نمی‌توان آن را از این طریق به اشتراک گذاشت!</string>
+ <string name="text_copied_to_clipboard">متن در حافظه کپی شده است!</string>
+ <!--errors
+ no punctuation, all lowercase,
+ they will be put after "error_message", e.g. "Error: file not found"-->
+ <string name="error_file_delete_failed">حذف نشد. به صورت دستی آن را حذف کنید!</string>
+ <string name="error_file_added_already">%s قبلاً اضافه شده است.</string>
+ <string name="error_file_not_found">فایل یافت نشد</string>
+ <string name="error_no_secret_key_found">کلید شخصیِ متناسبی یافت نشد</string>
+ <string name="error_external_storage_not_ready">حافظهٔ خارجی آماده نیست</string>
+ <string name="error_key_size_minimum512bit">اندازهٔ کلید باید حداقل ۵۱۲بیت باشد</string>
+ <string name="error_unknown_algorithm_choice">الگوریتم انتخابی ناشناخته است</string>
+ <string name="error_user_id_no_email">آدرس ایمیلی یافت نشد</string>
+ <string name="error_key_needs_a_user_id">حداقل به یک هویت نیاز است</string>
+ <string name="error_no_signature_passphrase">رمزعبوری داده نشد</string>
+ <string name="error_no_signature_key">کلیدی برای امضاء کردن داده نشد</string>
+ <string name="error_wrong_passphrase">رمزعبور اشتباه است</string>
+ <string name="error_could_not_extract_private_key">نمی‌توان کلید شخصی را خارج کرد</string>
+ <!--errors without preceeding Error:-->
+ <!--results shown after decryption/verification-->
+ <string name="decrypt_result_no_signature">امضاء نشده</string>
+ <string name="decrypt_result_invalid_signature">امضاء معتبر نیست!</string>
+ <string name="decrypt_result_insecure_cryptography">امضاء معتبر نیست(رمزنگاری امن نیست)!</string>
+ <string name="decrypt_result_signature_uncertified">توسط کلیدی <b>تأیید نشده</b> امضاء شده است</string>
+ <string name="decrypt_result_signature_secret">با کلیدتان امضاء شده است</string>
+ <string name="decrypt_result_signature_certified">با کلیدی تأیید شده امضاء شده است</string>
+ <string name="decrypt_result_signature_expired_key">با کلیدی <b>منقضی شده</b> امضاء شده است!</string>
+ <string name="decrypt_result_encrypted">رمزگذاری شده</string>
+ <string name="decrypt_result_not_encrypted">رمزگذاری نشده</string>
+ <string name="decrypt_result_insecure">رمزگذاریِ نا امن</string>
+ <string name="decrypt_result_action_show">نمایش</string>
+ <string name="decrypt_result_action_Lookup">جستجو</string>
+ <string name="decrypt_invalid_text">امضاء نامعتبر است یا کلید فسخ شده‌است. شما نمی‌توانید مطمئن باشید که چه کسی متن را نوشته است. آیا متن نمایش داده شود؟</string>
+ <string name="decrypt_invalid_button">من متوجهٔ ریسک‌اش هستم. نمایش‌ بده!</string>
+ <!--Add keys-->
+ <string name="add_keys_my_key">کلید من:</string>
+ <!--progress dialogs, usually ending in '…'-->
+ <string name="progress_done">انجام شد.</string>
+ <string name="progress_cancel">انصراف</string>
+ <string name="progress_cancelling">در حال انصراف...</string>
+ <string name="progress_saving">در حال ذخیره‌سازی...</string>
+ <string name="progress_importing">در حال وارد کردن...</string>
+ <string name="progress_revoking_uploading">در حال فسخ‌ و آپلود‌کردن کلید...</string>
+ <string name="progress_updating">درحال آپدیت‌کردن کلیدها...</string>
+ <string name="progress_exporting">در حال خارج‌کردن...</string>
+ <string name="progress_uploading">در حال آپلود کردن...</string>
+ <string name="progress_building_key">در حال ساخت کلید...</string>
+ <string name="progress_building_master_key">در حال ساخت حلقهٔ اصلی...</string>
+ <string name="progress_generating_rsa">در حال تولید کلید RSA جدید...</string>
+ <string name="progress_generating_dsa">در حال تولید کلید DSA جدید...</string>
+ <string name="progress_generating_elgamal">در حال تولید کلید EIGamal جدید...</string>
+ <string name="progress_generating_ecdsa">در حال تولید کلید ECDSA جدید...</string>
+ <string name="progress_generating_ecdh">در حال تولید کلید ECDH جدید...</string>
+ <string name="progress_modify">در حال ویرایش حلقه کلید...</string>
+ <string name="progress_modify_unlock">در حال بازکردن حلقه کلید...</string>
+ <!--action strings-->
+ <!--key bit length selections-->
+ <!--elliptic curve names-->
+ <!--not in for now, see SaveKeyringParcel
+ <string name="key_curve_bp_p256">"Brainpool P-256"</string>
+ <string name="key_curve_bp_p384">"Brainpool P-384"</string>
+ <string name="key_curve_bp_p512">"Brainpool P-512"</string>-->
+ <!--compression-->
+ <!--Help-->
+ <!--Import-->
+ <!--Import from URL-->
+ <!--Generic result toast-->
+ <!--Import result toast-->
+ <!--Delete result toast-->
+ <!--Revoke result toast (snackbar)-->
+ <!--Certify result toast-->
+ <!--Intent labels-->
+ <!--Remote API-->
+ <!--Share-->
+ <!--retry upload dialog-->
+ <!--Delete or revoke private key dialog-->
+ <!--Delete Or Revoke Dialog spinner-->
+ <!--Key list-->
+ <!--Key view-->
+ <string name="user_id_info_invalid_title">نامعتبر</string>
+ <string name="user_id_info_invalid_text">هویت مشکل دارد!</string>
+ <!--Key trust-->
+ <string name="key_trust_already_verified">شما قبلاً این کلید را تأیید کرده‌اید!</string>
+ <string name="key_trust_it_is_yours">این یکی از کلیدهای‌تان است!</string>
+ <string name="key_trust_maybe">این کلید نه لغو شده و نه منقضی شده است.\nشما آن را تأیید نکرده‌اید، ولی می‌توانید اعتماد به آن کلید را انتخاب کنید.</string>
+ <string name="key_trust_revoked">این کلید توسط صاحب‌اش لغو شده است. نباید به آن اعتماد کنید.</string>
+ <string name="key_trust_expired">این کلید منقضی شده است. نباید به آن اعتماد کنید.</string>
+ <string name="key_trust_old_keys">اگر از این برای رمزگشاییِ یک پیغام قدیمی مربوط به قبل از منقضی شدن‌اش استفاده می‌کنید، مشکلی نیست.</string>
+ <string name="key_trust_no_cloud_evidence">هیچ دلیلی برای اعتماد به این کلید بر روی اینترنت نیست.</string>
+ <string name="key_trust_start_cloud_search">آغاز جستجو</string>
+ <!--keybase proof stuff-->
+ <string name="keybase_narrative_twitter">روی Twitter پست می‌کند به عنوان %s</string>
+ <string name="keybase_narrative_github">بر روی GitHub شناخته شده است به عنوان %s</string>
+ <string name="keybase_narrative_dns">کنترل می‌کند نام دامنه‌(های) %s</string>
+ <!--Edit key-->
+ <string name="edit_key_action_change_passphrase">تغییر رمزعبور</string>
+ <string name="edit_key_action_add_identity">اضافه‌کردن هویت</string>
+ <string name="edit_key_action_add_subkey">اضافه کردن زیرکلید</string>
+ <string name="edit_key_edit_user_id_title">یک عمل را انتخاب کنید!</string>
+ <string name="edit_key_edit_user_id_revoked">این هویت لغو شده‌است. انصراف از این عمل شدنی نیست.</string>
+ <string name="edit_key_edit_subkey_title">یک عمل را انتخاب کنید!</string>
+ <string name="edit_key_new_subkey">زیرکلیدِ جدید</string>
+ <string name="edit_key_select_flag">لطفاً حداقل یک پرچم انتخاب کنید!</string>
+ <string name="edit_key_error_add_identity">حداقل یک هویت اصافه کنید!</string>
+ <string name="edit_key_error_add_subkey">حداقل یک زیر‌کلید اضافه کنید</string>
+ <!--Create key-->
+ <string name="create_key_empty">این فیلد لازم است</string>
+ <string name="create_key_passphrases_not_equal">رمز عبور‌ها مطابقت ندارند</string>
+ <string name="create_key_final_text">شما هویتِ زیر را وارد کردید:</string>
+ <string name="create_key_rsa">(3 زیرکلید, RSA, 4096 بیت)</string>
+ <string name="create_key_custom">(تنظیمات شخصیِ کلید)</string>
+ <!--View key-->
+ <!--Add/Edit keyserver-->
+ <!--Navigation Drawer-->
+ <!--hints-->
+ <!--certs-->
+ <!--LogType log messages. Errors should have _ERROR_ in their name and end with a !-->
+ <!--Import Public log entries-->
+ <!--Import Secret log entries-->
+ <!--Keyring Canonicalization log entries-->
+ <!--Keyring merging log entries-->
+ <!--createSecretKeyRing-->
+ <!--modifySecretKeyRing-->
+ <!--Consolidate-->
+ <string name="msg_con_reimport_secret_skip">هیچ کلید خصوصی‌ای برای ورود یافت نشد، نادیده گرفته شد...</string>
+ <string name="msg_con_warn_delete_public">استثنا در حذف کردن فایل عمومیِ cache</string>
+ <string name="msg_con_warn_delete_secret">استثنا در حذف کردن فایل خصوصیِ cache</string>
+ <!--Edit Key (higher level than modify)-->
+ <string name="msg_ed">در حال انجام عملیات کلید</string>
+ <string name="msg_ed_caching_new">در حال کَش کردنِ رمزعبور جدید</string>
+ <string name="msg_ed_error_no_parcel">SaveKeyringParcel یافت نشد! (این یک باگ است، لطفاً گزارش کنید)</string>
+ <string name="msg_ed_error_key_not_found">کلید یافت نشد!</string>
+ <string name="msg_ed_error_extract_public_upload">خطا در خارج کردنِ کلید عمومی برای آپلود!</string>
+ <string name="msg_ed_fetching">در حال واکشیِ کلید برای ویرایش (%s)</string>
+ <string name="msg_ed_success">عملیات کلید با موفقیت انجام شد</string>
+ <!--Promote key-->
+ <!--Other messages used in OperationLogs-->
+ <!--Messages for DecryptVerify operation-->
+ <!--Messages for VerifySignedLiteralData operation-->
+ <!--Messages for SignEncrypt operation-->
+ <!--Messages for PgpSignEncrypt operation-->
+ <!--Messages for Keybase Verification operation-->
+ <!--Messages for Export Log operation-->
+ <!--PassphraseCache-->
+ <!--Keyserver sync-->
+ <!--First Time-->
+ <!--unsorted-->
+ <!--Android Account-->
+ <!--Passphrase wizard-->
+ <!--TODO: rename all the things!-->
+ <!--<string name="enter_passphrase_twice">Enter password twice</string>-->
+ <!--<string name="nfc_text">Please place a NFC tag near your device</string>-->
+</resources>
diff --git a/OpenKeychain/src/main/res/values-fi/strings.xml b/OpenKeychain/src/main/res/values-fi/strings.xml
index 724cd7b5c..a8bbd7f79 100644
--- a/OpenKeychain/src/main/res/values-fi/strings.xml
+++ b/OpenKeychain/src/main/res/values-fi/strings.xml
@@ -14,8 +14,6 @@
<string name="title_encrypt_to_file">Salaa Tiedostoon</string>
<string name="title_decrypt_to_file">Pura Tiedostoon</string>
<string name="title_import_keys">Tuo Avaimia</string>
- <string name="title_export_key">Vie Avain</string>
- <string name="title_export_keys">Vie Avaimia</string>
<string name="title_key_not_found">Avainta Ei Löydy</string>
<string name="title_send_key">Lähetä Avainpalvelimelle</string>
<string name="title_key_details">Avaimen Tiedot</string>
@@ -46,7 +44,6 @@
<!--menu-->
<string name="menu_preferences">Asetukset</string>
<string name="menu_help">Apua</string>
- <string name="menu_export_key">Vie tiedostoon</string>
<string name="menu_delete_key">Poista avain</string>
<string name="menu_search">Etsi</string>
<string name="menu_beam_preferences">Beam asetukset</string>
@@ -85,6 +82,7 @@
<string name="label_fingerprint">Sormenjälki</string>
<string name="expiry_date_dialog_title">Aseta umpeutumispäivämäärä</string>
<string name="label_preferred">ensisijainen</string>
+ <!--label shown in Android settings under the OpenKeychain account-->
<!--Proxy Preferences-->
<!--proxy type choices and values-->
<!--OrbotHelper strings-->
@@ -153,10 +151,14 @@
<!--Generic result toast-->
<!--Import result toast-->
<!--Delete result toast-->
+ <!--Revoke result toast (snackbar)-->
<!--Certify result toast-->
<!--Intent labels-->
<!--Remote API-->
<!--Share-->
+ <!--retry upload dialog-->
+ <!--Delete or revoke private key dialog-->
+ <!--Delete Or Revoke Dialog spinner-->
<!--Key list-->
<!--Key view-->
<!--Key trust-->
@@ -186,8 +188,10 @@
<!--Messages for Keybase Verification operation-->
<!--Messages for Export Log operation-->
<!--PassphraseCache-->
+ <!--Keyserver sync-->
<!--First Time-->
<!--unsorted-->
+ <!--Android Account-->
<!--Passphrase wizard-->
<!--TODO: rename all the things!-->
<!--<string name="enter_passphrase_twice">Enter password twice</string>-->
diff --git a/OpenKeychain/src/main/res/values-fr/strings.xml b/OpenKeychain/src/main/res/values-fr/strings.xml
index fad65f955..4a6c2bbfe 100644
--- a/OpenKeychain/src/main/res/values-fr/strings.xml
+++ b/OpenKeychain/src/main/res/values-fr/strings.xml
@@ -20,8 +20,8 @@
<string name="title_encrypt_to_file">Chiffrer vers un fichier</string>
<string name="title_decrypt_to_file">Déchiffrer vers un fichier</string>
<string name="title_import_keys">importer des clefs</string>
- <string name="title_export_key">Exporter la clef</string>
- <string name="title_export_keys">Exporter les clefs</string>
+ <string name="title_export_key">Sauvegarder la clef</string>
+ <string name="title_export_keys">Sauvegarder les clefs</string>
<string name="title_key_not_found">Clef introuvable</string>
<string name="title_send_key">Téléverser vers le serveur de clefs</string>
<string name="title_certify_key">Confirmer la clef</string>
@@ -43,6 +43,9 @@
<string name="section_keys">Sous-clefs</string>
<string name="section_cloud_search">Recherche nuagique</string>
<string name="section_passphrase_cache">Gestion des mots de passe/NIP</string>
+ <string name="section_proxy_settings">Paramètres du mandataire</string>
+ <string name="section_gui">Interface</string>
+ <string name="section_sync_settings">Paramètres de synchro</string>
<string name="section_certify">Confirmer</string>
<string name="section_actions">Actions</string>
<string name="section_share_key">Clef</string>
@@ -87,7 +90,7 @@
<!--menu-->
<string name="menu_preferences">Paramètres</string>
<string name="menu_help">Aide</string>
- <string name="menu_export_key">Exporter vers un fichier</string>
+ <string name="menu_export_key">Sauvegarder vers un fichier</string>
<string name="menu_delete_key">Supprimer la clef</string>
<string name="menu_manage_keys">Gérer mes clefs</string>
<string name="menu_search">Rechercher</string>
@@ -119,6 +122,7 @@
<string name="label_use_default_yubikey_pin">Utiliser le NIP par défaut de la ClefYubi</string>
<string name="label_use_num_keypad_for_yubikey_pin">Utiliser le pavé numérique pour le NIP de la ClefYubi</string>
<string name="label_label_use_default_yubikey_pin_summary">Utilise le NIP par défaut (123456) pour accéder aux ClefsYubi par la NFC</string>
+ <string name="label_asymmetric_from">Signer avec :</string>
<string name="label_to">Chiffrer pour :</string>
<string name="label_delete_after_encryption">Supprimer les fichiers après chiffrement</string>
<string name="label_delete_after_decryption">Supprimer le fichier après le déchiffrement</string>
@@ -154,15 +158,46 @@
<string name="label_verify_keyserver">Vérifier le serveur de clefs</string>
<string name="label_enter_keyserver_url">Saisir l\'URL du serveur de clefs</string>
<string name="label_keyserver_dialog_delete">Supprimer le serveur de clefs</string>
+ <string name="label_theme">Thème</string>
<string name="pref_keyserver">Serveurs de clefs OpenPGP</string>
<string name="pref_keyserver_summary">Rechercher les clefs dans les serveurs de clefs OpenPGP choisis (protocole HKP)</string>
<string name="pref_keybase">keybase.io</string>
<string name="pref_keybase_summary">Rechercher les clefs sur keybase.io</string>
+ <string name="label_sync_settings_keyserver_title">Mettre les clefs à jour automatiquement</string>
+ <string name="label_sync_settings_keyserver_summary_on">Les clefs de plus d\'une semaine sont misent à jour à partir du serveur de clefs</string>
+ <string name="label_sync_settings_keyserver_summary_off">Les clefs ne sont pas mises à jour automatiquement</string>
+ <string name="label_sync_settings_contacts_title">Synchroniser les contacts avec les clefs</string>
+ <string name="label_sync_settings_contacts_summary_on">Les clefs sont reliées aux contacts dont les adresses courriels correspondantes, ce qui se passe complètement hors ligne</string>
+ <string name="label_sync_settings_contacts_summary_off">Les nouvelles clefs ne seront pas reliées aux contacts</string>
+ <!--label shown in Android settings under the OpenKeychain account-->
+ <string name="keyserver_sync_settings_title">Mettre les clefs à jour automatiquement</string>
<!--Proxy Preferences-->
+ <string name="pref_proxy_tor_title">Activer Tor</string>
+ <string name="pref_proxy_tor_summary">Orbot doit être installé</string>
+ <string name="pref_proxy_normal_title">Activer un autre mandataire</string>
+ <string name="pref_proxy_host_title">Hôte du mandataire</string>
+ <string name="pref_proxy_host_err_invalid">L\'hôte du mandataire ne peut pas être vide</string>
+ <string name="pref_proxy_port_title">Port du mandataire</string>
+ <string name="pref_proxy_port_err_invalid">Le numéro de port saisi est invalide</string>
+ <string name="pref_proxy_type_title">Type de mandataire</string>
<!--proxy type choices and values-->
+ <string name="pref_proxy_type_choice_http">HTTP</string>
+ <string name="pref_proxy_type_choice_socks">SOCKS</string>
<!--OrbotHelper strings-->
+ <string name="orbot_ignore_tor">Ne pas utiliser Tor</string>
<!--InstallDialogFragment strings-->
+ <string name="orbot_install_dialog_title">Installer Orbot pour utiliser Tor ?</string>
+ <string name="orbot_install_dialog_install">Installer</string>
+ <string name="orbot_install_dialog_content">Orbot doit être installé et doit relayer le trafic. Voulez-vous l\'installer maintenant ?</string>
+ <string name="orbot_install_dialog_cancel">Annuler</string>
+ <string name="orbot_install_dialog_ignore_tor">Ne pas utiliser Tor</string>
<!--StartOrbotDialogFragment strings-->
+ <string name="orbot_start_dialog_title">Démarrer Orbot ?</string>
+ <string name="orbot_start_dialog_content">Orbot ne semble pas tourner. Voulez-vous le démarrer et vous connecter à Tor ?</string>
+ <string name="orbot_start_btn">Démarrer Orbot</string>
+ <string name="orbot_start_dialog_start">Démarrer Orbot</string>
+ <string name="orbot_start_dialog_cancel">Annuler</string>
+ <string name="orbot_start_dialog_ignore_tor">Ne pas utiliser Tor</string>
<string name="user_id_no_name">&lt;aucun nom&gt;</string>
<string name="none">&lt;aucune&gt;</string>
<plurals name="n_keys">
@@ -196,6 +231,8 @@
<string name="filemanager_title_open">Ouvrir...</string>
<string name="error">Erreur</string>
<string name="error_message">Erreur : %s</string>
+ <string name="theme_dark">Sombre</string>
+ <string name="theme_light">Clair</string>
<!--key flags-->
<string name="flag_certify">Certifier</string>
<string name="flag_sign">Signer</string>
@@ -211,6 +248,9 @@
<string name="pin_for">Saisir le NIP pour « %s »</string>
<string name="yubikey_pin_for">Saisir le NIP pour accéder à la ClefYubi pour « %s »</string>
<string name="nfc_text">Tenez la ClefYubi contre le logo NFC au dos de votre appareil.</string>
+ <string name="nfc_wait">Conservez la ClefYubi contre le dos !</string>
+ <string name="nfc_finished">Retirez la ClefYubi maintenant.</string>
+ <string name="nfc_try_again_text">Retirez la ClefYubi maintenant et appuyez sur RESSAYER.</string>
<string name="file_delete_confirmation_title">Supprimer les fichiers originaux ?</string>
<string name="file_delete_confirmation">Les fichiers suivants seront détruits : %s</string>
<string name="file_delete_successful">%1$d fichiers sur %2$d ont déjà été supprimés. %3$s</string>
@@ -221,7 +261,10 @@
<string name="error_no_encryption_or_signature_key">Choisir au moins une clef de chiffrement ou une clef de signature.</string>
<string name="specify_file_to_encrypt_to">Veuillez spécifier vers quel fichier chiffrer.\nAVERTISSEMENT : le fichier sera écrasé s\'il existe !</string>
<string name="specify_file_to_decrypt_to">Veuillez spécifier vers quel fichier déchiffrer.\nAVERTISSEMENT : le fichier sera écrasé s\'il existe !</string>
- <string name="specify_backup_dest">Veuillez spécifier vers quel fichier exporter.\nAVERTISSEMENT : le fichier sera écrasé s\'il existe !</string>
+ <string name="specify_backup_dest">Une sauvegarde excluant vos clefs sera faite. Veuillez spécifier un fichier de destination.\nAVERTISSEMENT : le fichier sera écrasé s\'il existe !</string>
+ <string name="specify_backup_dest_single">Cette clef sera partagée. Veuillez spécifier un fichier de destination.\nAVERTISSEMENT : le fichier sera écrasé s\'il existe !</string>
+ <string name="specify_backup_dest_secret_single">Une sauvegarde complète de votre clef sera faite. Veuillez spécifier un fichier de destination.\nAVERTISSEMENT : le fichier sera écrasé s\'il existe !</string>
+ <string name="specify_backup_dest_secret">Une sauvegarde complète de toutes les clefs, la vôtre incluse, sera faite. Veuillez spécifier un fichier de destination.\nAVERTISSEMENT : le fichier sera écrasé s\'il existe !</string>
<string name="key_deletion_confirmation_multi">Voulez-vous vraiment supprimer toutes les clefs sélectionnées ?</string>
<string name="secret_key_deletion_confirmation">Après suppression vous ne pourrez plus lire les messages chiffrés avec cette clef et vous perdrez toutes les confirmations de clefs faites avec elle !</string>
<string name="public_key_deletetion_confirmation">Supprimer la clef \'%s\' ?</string>
@@ -273,6 +316,7 @@
<!--results shown after decryption/verification-->
<string name="decrypt_result_no_signature">Non signé</string>
<string name="decrypt_result_invalid_signature">Signature invalide !</string>
+ <string name="decrypt_result_insecure_cryptography">Signature invalide (cryptographie non fiable) !</string>
<string name="decrypt_result_signature_uncertified">Signé par un clef <b>non confirmée</b></string>
<string name="decrypt_result_signature_secret">Signé par votre clef</string>
<string name="decrypt_result_signature_certified">Signé par une clef confirmée</string>
@@ -281,6 +325,7 @@
<string name="decrypt_result_signature_missing_key">Signé par une <b>clef publique inconnue</b></string>
<string name="decrypt_result_encrypted">Chiffré</string>
<string name="decrypt_result_not_encrypted">Non chiffré</string>
+ <string name="decrypt_result_insecure">Chiffrement non fiable</string>
<string name="decrypt_result_action_show">Montrer</string>
<string name="decrypt_result_action_Lookup">Rechercher</string>
<string name="decrypt_invalid_text">Soit la signature est invalide, soit la clef a été révoquée. Vous ne pouvez pas être certain de l\'identité du rédacteur du texte. Voulez-vous quand même l\'afficher ?</string>
@@ -293,6 +338,7 @@
<string name="progress_cancelling">annulation...</string>
<string name="progress_saving">sauvegarde...</string>
<string name="progress_importing">importation...</string>
+ <string name="progress_revoking_uploading">Révocation et téléversement de la clef...</string>
<string name="progress_updating">Mise à jour des clefs...</string>
<string name="progress_exporting">exportation...</string>
<string name="progress_uploading">téléversement...</string>
@@ -341,6 +387,7 @@
<string name="progress_con_saving">consolider : enregistrement dans le cache...</string>
<string name="progress_con_reimport">consolider : réimportation...</string>
<string name="progress_verifying_keyserver_url">vérification du serveur de clefs...</string>
+ <string name="progress_starting_orbot">Démarrage d\'Orbot...</string>
<!--action strings-->
<string name="hint_cloud_search_hint">Chercher par nom, adresse courriel...</string>
<!--key bit length selections-->
@@ -438,6 +485,11 @@
</plurals>
<string name="delete_nothing">Rien à supprimer.</string>
<string name="delete_cancelled">Opération de suppression annulée.</string>
+ <!--Revoke result toast (snackbar)-->
+ <string name="revoke_ok">Clef révoquée avec succès.</string>
+ <string name="revoke_fail">Erreur de révocation de la clef !</string>
+ <string name="revoke_nothing">Rien à révoquer.</string>
+ <string name="revoke_cancelled">Opération de révocation annulée.</string>
<!--Certify result toast-->
<plurals name="certify_keys_ok">
<item quantity="one">Une key%2$s certifiée avec succès.</item>
@@ -471,7 +523,7 @@
<string name="api_settings_start">Lancer l\'application</string>
<string name="api_settings_delete_account">Supprimer le compte</string>
<string name="api_settings_package_name">Nom du paquet</string>
- <string name="api_settings_package_certificate">SHA-256 de la signature du paquet</string>
+ <string name="api_settings_package_certificate">SHA-256 du certificat du paquet</string>
<string name="api_settings_accounts">Comptes (ancienne API)</string>
<string name="api_settings_advanced">Informations détaillées</string>
<string name="api_settings_allowed_keys">Clefs autorisées</string>
@@ -484,8 +536,8 @@
<string name="api_register_allow">Permettre l\'accès</string>
<string name="api_register_disallow">Enlever l\'accès</string>
<string name="api_register_error_select_key">Veuillez choisir une clef !</string>
- <string name="api_select_pub_keys_missing_text">Aucune clef n\'a été trouvée pour ces identités :</string>
- <string name="api_select_pub_keys_dublicates_text">Plus d\'une clef existe pour ces identités :</string>
+ <string name="api_select_pub_keys_missing_text">Aucune clef trouvée pour ces adresses courriel :</string>
+ <string name="api_select_pub_keys_dublicates_text">Plus d\'une clef existe pour ces adresses courriel :</string>
<string name="api_select_pub_keys_text">Veuillez revoir la liste des destinataires !</string>
<string name="api_select_pub_keys_text_no_user_ids">Veuillez choisir les destinataires !</string>
<string name="api_error_wrong_signature">La vérification de la signature a échoué ! Avez-vous installé cette appli à partir d\'une source différente ? Si vous êtes sûr que ce n\'est pas une attaque, révoquez l\'enregistrement de cette appli dans OpenKeychain et enregistrez-la à nouveau.</string>
@@ -494,6 +546,19 @@
<!--Share-->
<string name="share_qr_code_dialog_title">Partager par un code QR</string>
<string name="share_nfc_dialog">Partager par la NFC</string>
+ <!--retry upload dialog-->
+ <string name="retry_up_dialog_title">Échec de téléversement</string>
+ <string name="retry_up_dialog_message">Échec de téléversement. Souhaitez-vous ressayer l\'opération ?</string>
+ <string name="retry_up_dialog_btn_reupload">Ressayer l\'opération</string>
+ <string name="retry_up_dialog_btn_cancel">Annuler l\'opération</string>
+ <!--Delete or revoke private key dialog-->
+ <string name="del_rev_dialog_message">Si vous ne voulez plus utiliser cette clef, elle devrait être révoquée et téléversée. Choisissez \'SUPPRIMER SEULEMENT\' si vous souhaitez retirer la clef d\'OpenKeychain mais continuerez à l\'utiliser ailleurs.</string>
+ <string name="del_rev_dialog_title">Révoquer/supprimer la clef \'%s\' </string>
+ <string name="del_rev_dialog_btn_revoke">Révoquer et téléverser</string>
+ <string name="del_rev_dialog_btn_delete">Supprimer seulement</string>
+ <!--Delete Or Revoke Dialog spinner-->
+ <string name="del_rev_dialog_choice_delete">Supprimer seulement</string>
+ <string name="del_rev_dialog_choice_rev_upload">Révoquer et téléverser</string>
<!--Key list-->
<plurals name="key_list_selected_keys">
<item quantity="one">1 clef choisie</item>
@@ -536,14 +601,14 @@
<string name="key_trust_results_prefix">Keybase.io offre des « preuves » affirmant que le propriétaire de cette clef : </string>
<string name="key_trust_header_text">Note : les preuves de keybase.io sont une fonction expérimentales d\'OpenKeychain. Nous vous encourageons à lire des codes QR ou à échanger des clefs via NFC en plus de les confirmer.</string>
<!--keybase proof stuff-->
- <string name="keybase_narrative_twitter">Publie vers Twitter en tant que</string>
- <string name="keybase_narrative_github">Est connu sur GitHub en tant que</string>
- <string name="keybase_narrative_dns">Contrôle le/les nom(s) de domaine</string>
- <string name="keybase_narrative_web_site">Peut publier vers le/les site(s) Web</string>
- <string name="keybase_narrative_reddit">Publie sur Reddit en tant que</string>
- <string name="keybase_narrative_coinbase">Est connu sur Coinbase en tant que</string>
- <string name="keybase_narrative_hackernews">Publie sur « Hacker News » en tant que</string>
- <string name="keybase_narrative_unknown">Type de preuve inconnu</string>
+ <string name="keybase_narrative_twitter">Publie sur Twitter en tant que %s</string>
+ <string name="keybase_narrative_github">Est connu sur GitHub en tant que %s</string>
+ <string name="keybase_narrative_dns">Contrôle le/les nom(s) de domaine %s</string>
+ <string name="keybase_narrative_web_site">Peut publier vers le/les site(s) Web %s</string>
+ <string name="keybase_narrative_reddit">Publie sur Reddit en tant que %s</string>
+ <string name="keybase_narrative_coinbase">Est connu sur Coinbase en tant que %s</string>
+ <string name="keybase_narrative_hackernews">Publie sur « Hacker News » en tant que %s</string>
+ <string name="keybase_narrative_unknown">Type de preuve inconnu %s</string>
<string name="keybase_proof_failure">Malheureusement cette preuve ne peut pas être vérifiée.</string>
<string name="keybase_unknown_proof_failure">Problème inconnu avec le vérificateur de preuve</string>
<string name="keybase_problem_fetching_evidence">Problème avec la preuve</string>
@@ -576,7 +641,7 @@
<string-array name="edit_key_edit_user_id_revert_revocation">
<item>Renverser la révocation</item>
</string-array>
- <string name="edit_key_edit_user_id_revoked">Cette identité a été révoquée ! Ceci ne peut pas être annulé.</string>
+ <string name="edit_key_edit_user_id_revoked">Cette identité a été révoquée ! Cela ne peut pas être annulé.</string>
<string name="edit_key_edit_subkey_title">Choisissez une action !</string>
<string-array name="edit_key_edit_subkey">
<item>Changer l\'expiration</item>
@@ -639,6 +704,7 @@
<string name="drawer_open">Ouvrir le tiroir de navigation</string>
<string name="drawer_close">Fermer le tiroir de navigation</string>
<string name="my_keys">Mes clefs</string>
+ <string name="nav_backup">Sauvegarde</string>
<!--hints-->
<string name="encrypt_content_edit_text_hint">Saisir le texte</string>
<!--certs-->
@@ -656,7 +722,7 @@
<string name="msg_cancelled">Opération annulée.</string>
<!--Import Public log entries-->
<string name="msg_ip_apply_batch">Application de l\'opération d\'insertion par lot.</string>
- <string name="msg_ip_bad_type_secret">Tentative d\'importer le trousseau secret comme public. Ceci est un bogue, veuillez remplir un rapport !</string>
+ <string name="msg_ip_bad_type_secret">Tentative d\'importer le trousseau secret comme public. C\'est un bogue, veuillez remplir un rapport !</string>
<string name="msg_ip_delete_old_fail">Aucune ancienne clef de supprimée (création d\'une nouvelle ?)</string>
<string name="msg_ip_delete_old_ok">L\'ancienne clef a été supprimée de la base de données</string>
<string name="msg_ip_encode_fail">Échec de l\'opération causé par une erreur d\'encodage</string>
@@ -746,8 +812,8 @@
</plurals>
<string name="msg_ip_uat_classifying">Organisation des attributs utilisateur</string>
<string name="msg_ip_uat_revoked">L\'attribut utilisateur est révoqué</string>
- <string name="msg_is_bad_type_public">Tentative d\'importer le trousseau public comme secret. Ceci est un bogue, veuillez remplir un rapport !</string>
- <string name="msg_is_bad_type_uncanon">Tentative d\'importer un trousseau sans canonicalisation. Ceci est un bogue, veuillez remplir un rapport !</string>
+ <string name="msg_is_bad_type_public">Tentative d\'importer le trousseau public comme secret. C\'est un bogue, veuillez remplir un rapport !</string>
+ <string name="msg_is_bad_type_uncanon">Tentative d\'importer un trousseau sans canonicalisation. C\'est un bogue, veuillez remplir un rapport !</string>
<!--Import Secret log entries-->
<string name="msg_is">Importation de la clef secrète %s</string>
<string name="msg_is_db_exception">Erreur de base de données !</string>
@@ -768,7 +834,7 @@
<!--Keyring Canonicalization log entries-->
<string name="msg_kc_public">Canonicalisation du trousseau public %s</string>
<string name="msg_kc_secret">Canonicalisation du trousseau secret %s</string>
- <string name="msg_kc_error_v3">Ceci est une clef OpenPGP version 3, qui a été déprécié et n\'est plus pris en charge !</string>
+ <string name="msg_kc_error_v3">C\'est une clef OpenPGP version 3, qui a été déprécié et n\'est plus pris en charge !</string>
<string name="msg_kc_error_no_uid">Le trousseau n\'a pas d\'ID utilisateur valide !</string>
<string name="msg_kc_error_master_algo">La clef maîtresse utilise un algorithme (%s) inconnu ! </string>
<string name="msg_kc_error_dup_key">La sous-clef %s se présente deux fois dans le trousseau. Le trousseau est mal formé, pas d\'importation ! </string>
@@ -823,7 +889,7 @@
<string name="msg_kc_uid_revoke_old">Suppression du certificat de révocation périmé pour l\'ID utilisateur « %s »</string>
<string name="msg_kc_uid_no_cert">Aucun auto-certificat valide trouvé pour l\'ID utilisateur « %s », qui est maintenant enlevé du trousseau</string>
<string name="msg_kc_uid_remove">Suppression de l\'ID utilisateur invalide « %s »</string>
- <string name="msg_kc_uid_dup">Suppression de l\'ID d\'utilisateur en double « %s ». Le trousseau en contenait deux. Ceci pourrait entraîner des certificats manquants !</string>
+ <string name="msg_kc_uid_dup">Suppression de l\'ID d\'utilisateur en double « %s ». Le trousseau en contenait deux. Cela pourrait entraîner des certificats manquants !</string>
<string name="msg_kc_uid_warn_encoding">L\'ID d\'utilisateur ne passe pas le test UTF-8 !</string>
<string name="msg_kc_uat_jpeg">Traitement de l\'attribut utilisateur de type JPEG</string>
<string name="msg_kc_uat_unknown">Traitement de l\'attribut utilisateur de type inconnu</string>
@@ -833,7 +899,7 @@
<string name="msg_kc_uat_bad_type">Suppression du certificat d\'attribut utilisateur de type inconnu (%s)</string>
<string name="msg_kc_uat_bad">Suppression du mauvais auto-certificat pour l\'attribut utilisateur</string>
<string name="msg_kc_uat_cert_dup">Suppression de l\'auto-certificat périmé pour l\'attribut utilisateur</string>
- <string name="msg_kc_uat_dup">Suppression de l\'attribut utilisateur en double. Le trousseau en contenait deux. Ceci pourrait entraîner des certificats manquants !</string>
+ <string name="msg_kc_uat_dup">Suppression de l\'attribut utilisateur en double. Le trousseau en contenait deux. Cela pourrait entraîner des certificats manquants !</string>
<string name="msg_kc_uat_foreign">Suppression du certificat étranger d\'attribut utilisateur par</string>
<string name="msg_kc_uat_revoke_dup">Suppression du certificat de révocation redondant pour l\'attribut utilisateur</string>
<string name="msg_kc_uat_revoke_old">Suppression de l\'auto-certificat périmé pour l\'attribut utilisateur</string>
@@ -854,12 +920,12 @@
<string name="msg_cr_error_no_master">Aucune option de clef maîtresse n\'a été spécifiée !</string>
<string name="msg_cr_error_no_user_id">Les trousseaux doivent être créés avec au moins un ID utilisateur !</string>
<string name="msg_cr_error_no_certify">La clef maîtresse doit avoir le drapeau « certifié » !</string>
- <string name="msg_cr_error_null_expiry">L\'expiration ne peut pas être « pareille qu\'avant » à la création de la clef. Ceci est une erreur du programme, veuillez remplir un rapport de bogue !</string>
+ <string name="msg_cr_error_null_expiry">L\'expiration ne peut pas être « pareille qu\'avant » à la création de la clef. C\'est une erreur du programme, veuillez remplir un rapport de bogue !</string>
<string name="msg_cr_error_keysize_512">La taille de la clef doit être supérieure ou égale à 512 !</string>
- <string name="msg_cr_error_no_curve">Aucune taille de clef n\'a été spécifiée ! Ceci est une erreur de programmation, veuillez remplir un rapport de bogue !</string>
- <string name="msg_cr_error_no_keysize">Aucune courbe elliptique n\'a été spécifiée ! Ceci est une erreur de programmation, veuillez remplir un rapport de bogue !</string>
+ <string name="msg_cr_error_no_curve">Aucune taille de clef n\'a été spécifiée ! C\'est une erreur de programmation, veuillez remplir un rapport de bogue !</string>
+ <string name="msg_cr_error_no_keysize">Aucune courbe elliptique n\'a été spécifiée ! C\'est une erreur de programmation, veuillez remplir un rapport de bogue !</string>
<string name="msg_cr_error_internal_pgp">Erreur interne OpenPGP !</string>
- <string name="msg_cr_error_unknown_algo">L\'algorithme choisi est inconnu ! Ceci est une erreur de programmation, veuillez remplir un rapport de bogue !</string>
+ <string name="msg_cr_error_unknown_algo">L\'algorithme choisi est inconnu ! C\'est une erreur de programmation, veuillez remplir un rapport de bogue !</string>
<string name="msg_cr_error_flags_dsa">Les drapeaux de clef choisis sont incorrects, DSA ne peut pas être utilisé pour le chiffrement ! </string>
<string name="msg_cr_error_flags_elgamal">Les drapeaux de clef choisis sont incorrects, ElGamal ne peut pas être utilisé pour le chiffrement ! </string>
<string name="msg_cr_error_flags_ecdsa">Les drapeaux de clef choisis sont incorrects, ECDSA ne peut pas être utilisé pour le chiffrement ! </string>
@@ -867,21 +933,23 @@
<!--modifySecretKeyRing-->
<string name="msg_mr">Modification du trousseau %s</string>
<string name="msg_mf_divert">Déviera vers la carte à puce pour les opérations de chiffrement</string>
- <string name="msg_mf_error_divert_serial">Le numéro de série d\'une clef « dévier-vers-la-carte » doit avoir 16 bytes ! Ceci est une erreur de programmation, veuillez remplir un rapport de bogue !</string>
+ <string name="msg_mf_error_divert_newsub">La création de nouvelles sous-clef n\'est pas prise en charge pour les clefs primaires « dévier-vers-la-carte » ! </string>
+ <string name="msg_mf_error_divert_serial">Le numéro de série d\'une clef « dévier-vers-la-carte » doit avoir 16 bytes ! C\'est une erreur de programmation, veuillez remplir un rapport de bogue !</string>
<string name="msg_mf_error_encode">Exception d\'encodage !</string>
<string name="msg_mf_error_fingerprint">L\'empreinte de clef effective ne correspond pas à celle attendue !</string>
- <string name="msg_mf_error_keyid">Aucune ID de clef. Ceci est une erreur interne, veuillez remplir un rapport de bogue !</string>
+ <string name="msg_mf_error_keyid">Aucune ID de clef. C\'est une erreur interne, veuillez remplir un rapport de bogue !</string>
<string name="msg_mf_error_integrity">Erreur interne, le contrôle d\'intégrité a échoué !</string>
<string name="msg_mf_error_master_none">Aucun certificat maître sur lequel se basé n\'a été trouvé ! (Tous révoqués ?)</string>
<string name="msg_mf_error_noexist_primary">Mauvais ID utilisateur principal spécifié !</string>
<string name="msg_mf_error_noexist_revoke">Mauvais ID utilisateur spécifié pour la révocation !</string>
- <string name="msg_mf_error_restricted">Tentative d\'exécution d\'une opération restreinte sans mot de passe ! Ceci est une erreur de programmation, veuillez remplir un rapport de bogue !</string>
+ <string name="msg_mf_error_restricted">Tentative d\'exécution d\'une opération restreinte sans mot de passe ! C\'est une erreur de programmation, veuillez remplir un rapport de bogue !</string>
<string name="msg_mf_error_revoked_primary">Les ID utilisateurs révoqués ne peuvent pas être principaux !</string>
- <string name="msg_mf_error_null_expiry">L\'expiration ne peut pas être « pareille qu\'avant » lors de la création de sous-clefs. Ceci est une erreur de programmation, veuillez remplir un rapport de bogue !</string>
+ <string name="msg_mf_error_null_expiry">L\'expiration ne peut pas être « pareille qu\'avant » lors de la création de sous-clefs. C\'est une erreur de programmation, veuillez remplir un rapport de bogue !</string>
<string name="msg_mf_error_noop">Rien à faire !</string>
- <string name="msg_mf_error_passphrase_master">Erreur fatale de déchiffrement de la clef maîtresse ! Ceci est probablement une erreur de programmation, veuillez remplir un rapport de bogue !</string>
+ <string name="msg_mf_error_passphrase_master">Erreur fatale de déchiffrement de la clef maîtresse ! C\'est probablement une erreur de programmation, veuillez remplir un rapport de bogue !</string>
<string name="msg_mf_error_pgp">Erreur interne OpenPGP !</string>
<string name="msg_mf_error_sig">Exception de signature !</string>
+ <string name="msg_mf_error_sub_stripped">Impossible de modifier la sous-clef dépouillée %s !</string>
<string name="msg_mf_error_subkey_missing">Une action a été tentée sur la sous-clef manquante %s !</string>
<string name="msg_mf_error_conflicting_nfc_commands">Impossible de déplacer la clef vers la carte à puce dans une même opération créant une signature sur la carte.</string>
<string name="msg_mf_error_duplicate_keytocard_for_slot">La carte à puce ne prend en charge qu\'un emplacement par type de clef.</string>
@@ -920,7 +988,7 @@
<string name="msg_mf_unlock">Déverrouillage du trousseau</string>
<!--Consolidate-->
<string name="msg_con">Consolidation de la base de données</string>
- <string name="msg_con_error_bad_state">La consolidation a été commencée alors qu\'aucune base de données n\'était en cache ! Ceci est probablement une erreur de programmation, veuillez remplir un rapport de bogue !</string>
+ <string name="msg_con_error_bad_state">La consolidation a été commencée alors qu\'aucune base de données n\'était en cache ! C\'est probablement une erreur de programmation, veuillez remplir un rapport de bogue !</string>
<string name="msg_con_error_concurrent">La consolidation a été abandonnée, elle est déjà en cours sur un autre exétron !</string>
<string name="msg_con_save_secret">Enregistrement des trousseaux secrets</string>
<string name="msg_con_save_public">Enregistrement des trousseaux publiques</string>
@@ -953,8 +1021,9 @@
<!--Edit Key (higher level than modify)-->
<string name="msg_ed">Exécution de l\'opération sur la clef</string>
<string name="msg_ed_caching_new">Mise en cache du nouveau mot de passe</string>
- <string name="msg_ed_error_no_parcel">SaveKeyringParcel absent ! (Ceci est un bogue, veuillez le rapporter)</string>
+ <string name="msg_ed_error_no_parcel">SaveKeyringParcel absent ! (C\'est un bogue, veuillez le signaler)</string>
<string name="msg_ed_error_key_not_found">Clef introuvable !</string>
+ <string name="msg_ed_error_extract_public_upload">Erreur d\'extraction de la clef publique pour le téléversement !</string>
<string name="msg_ed_fetching">Obtention de la clef à modifier (%s)</string>
<string name="msg_ed_success">Opération sur la clef réussie</string>
<!--Promote key-->
@@ -981,17 +1050,18 @@
<string name="msg_dc_clear_meta_size_unknown">La taille du fichier est inconnue</string>
<string name="msg_dc_clear_meta_time">Heure de modification : %s</string>
<string name="msg_dc_clear_signature_bad">La vérification de la signature n\'est PAS CORRECTE !</string>
- <string name="msg_dc_insecure_hash_algo">Algorithme de hachage non pris en charge et potentiellement non sécurisé ! </string>
<string name="msg_dc_clear_signature_check">Vérification des données de signature</string>
<string name="msg_dc_clear_signature_ok">La vérification de la signature OK</string>
<string name="msg_dc_clear_signature">Enregistrement des données de signature pour plus tard</string>
<string name="msg_dc_clear">Traitement des données de texte en clair</string>
<string name="msg_dc_error_bad_passphrase">Erreur de déverrouillage de la clef, mot de passe erroné !</string>
+ <string name="msg_dc_error_sym_passphrase">Erreur de déchiffrement de données (phrase de passe erronée ?)</string>
<string name="msg_dc_error_corrupt_data"> Les données sont corrompues !</string>
<string name="msg_dc_error_extract_key">Erreur inconnue de déverrouillage de la clef !</string>
<string name="msg_dc_error_integrity_check">Erreur de vérification de l\'intégrité !</string>
- <string name="msg_dc_insecure_mdc_missing">Vérification de l\'intégrité absente ! Ceci peut arriver car l\'application n\'est pas à jour, ou à cause d\'une attaque par mise à niveau inférieur.</string>
<string name="msg_dc_error_invalid_data">Aucune donnée OpenPGP valide chiffrée ou signée n\'a été trouvée !</string>
+ <string name="msg_dc_error_io">Erreur de lecture des données d\'entrée !</string>
+ <string name="msg_dc_error_input">Erreur d\'ouverture du flux de données d\'entrée !</string>
<string name="msg_dc_error_no_data">Aucune donnée chiffrée n\'a été trouvée dans le flux !</string>
<string name="msg_dc_error_no_key">Aucune donnée chiffrée avec une clef secrète connue n\'a été trouvée dans le flux !</string>
<string name="msg_dc_error_pgp_exception">Une exception OpenPGP a été rencontrée durant l\'opération !</string>
@@ -1009,7 +1079,10 @@
<string name="msg_dc_trail_sym">Des données traînantes chiffrées symétriquement ont été rencontrées</string>
<string name="msg_dc_trail_unknown">Des données traînantes de type inconnu ont été rencontrées</string>
<string name="msg_dc_unlocking">Déverrouillage de la clef secrète</string>
- <string name="msg_dc_insecure_symmetric_encryption_algo">Un algorithme de chiffrement possiblement non sécurisé à été utilisé !</string>
+ <string name="msg_dc_insecure_symmetric_encryption_algo">Un algorithme de chiffrement non fiable a été utilisé ! Cela peut être dû à une application ancienne ou à une attaque.</string>
+ <string name="msg_dc_insecure_hash_algo">Un algorithme de hachage non fiable a été utilisé ! Cela peut être dû à une application ancienne ou à une attaque.</string>
+ <string name="msg_dc_insecure_mdc_missing">Il manque le paquet du code de détection des modifications (MDC) ! Cela peut être dû à une application de chiffrement ancienne ou à une attaque par mise à niveau inférieur.</string>
+ <string name="msg_dc_insecure_key">Clef non fiable : soit la longueur de donnée de RSA/DSA/ElGamal est trop courte ou la courbe/algorithme ECC est considérée comme non fiable ! Cela peut être dû à une application ancienne ou à une attaque.</string>
<!--Messages for VerifySignedLiteralData operation-->
<string name="msg_vl">Lancement de la vérification de la signature</string>
<string name="msg_vl_error_no_siglist">Aucune liste de signatures dans les données littérales signées</string>
@@ -1029,7 +1102,7 @@
<string name="msg_se_error_no_input">Aucune entrée donnée !</string>
<string name="msg_se_error_input_uri_not_found">Erreur d\'ouverture de l\'URI en lecture !</string>
<string name="msg_se_error_output_uri_not_found">Erreur d\'ouverture de l\'URI en écriture !</string>
- <string name="msg_se_error_too_many_inputs">Plus d\'entrées spécifiées que de sorties ! Ceci est probablement une erreur de programmation, veuillez remplir un rapport de bogue !</string>
+ <string name="msg_se_error_too_many_inputs">Plus d\'entrées spécifiées que de sorties ! C\'est probablement une erreur de programmation, veuillez remplir un rapport de bogue !</string>
<string name="msg_se_success">Opération de signature/chiffrement réussie</string>
<!--Messages for PgpSignEncrypt operation-->
<string name="msg_pse_asymmetric">Préparation des clefs publiques pour le chiffrement</string>
@@ -1037,7 +1110,6 @@
<string name="msg_pse_compressing">Préparation de la compression</string>
<string name="msg_pse_encrypting">Chiffrement des données</string>
<string name="msg_pse_error_bad_passphrase">Mot de passe erroné !</string>
- <string name="msg_pse_error_hash_algo">L’algorithme de hachage demandé n\'est pas pris en charge par cette clef ! </string>
<string name="msg_pse_error_io">Une exception E/S a été rencontrée durant l\'opération !</string>
<string name="msg_pse_error_key_sign">La clef de signature choisie ne peut pas signer les données !</string>
<string name="msg_pse_error_sign_key">Erreur de récupération de la clef de signature !</string>
@@ -1081,6 +1153,7 @@
<string name="msg_crt_warn_not_found">Clef introuvable !</string>
<string name="msg_crt_warn_cert_failed">Échec de génération du certificat !</string>
<string name="msg_crt_warn_save_failed">Échec de l\'opération d\'enregistrement !</string>
+ <string name="msg_crt_warn_upload_failed">Échec de l\'opération de téléversement !</string>
<string name="msg_crt_upload_success">Clef téléversée vers le serveur avec succès</string>
<plurals name="msg_import">
<item quantity="one">Importation de la clef</item>
@@ -1089,7 +1162,7 @@
<string name="msg_import_fetch_error_decode">Erreur de décodage du trousseau récupéré !</string>
<string name="msg_import_fetch_error">La clef n\'a pas pu être récupérée ! (problèmes réseau ?)</string>
<string name="msg_import_fetch_keybase">Récupération en provenance du keybase.io : %s</string>
- <string name="msg_import_fetch_keyserver_error">Impossible de récupérer la clef sur les serveurs de clefs : %s</string>
+ <string name="msg_import_fetch_error_keyserver">Impossible de récupérer la clef sur les serveurs de clefs : %s</string>
<string name="msg_import_fetch_keyserver">Récupération en provenance du serveur de clefs : %s</string>
<string name="msg_import_fetch_keyserver_ok">Récupération de la clef est réussie !</string>
<string name="msg_import_keyserver">Utilisation du serveur de clefs %s</string>
@@ -1105,8 +1178,10 @@
<item quantity="one">Exportation d\'une clef</item>
<item quantity="other">Exportation de %d clefs</item>
</plurals>
+ <string name="msg_export_file_name">Nom de fichier : %s</string>
<string name="msg_export_all">Exportation de toutes les clefs</string>
<string name="msg_export_public">Exportation de la clef publique %s</string>
+ <string name="msg_export_upload_public">Téléversement de la clef publique %s</string>
<string name="msg_export_secret">Exportation de la clef secrète %s</string>
<string name="msg_export_error_no_file">Aucun nom de fichier spécifié !</string>
<string name="msg_export_error_fopen">Erreur d\'ouverture du fichier !</string>
@@ -1116,7 +1191,9 @@
<string name="msg_export_error_db">Erreur de base de données !</string>
<string name="msg_export_error_io">Erreur d\'entrée/sortie !</string>
<string name="msg_export_error_key">Erreur de prétraitement des données de la clef !</string>
+ <string name="msg_export_error_upload">Échec de téléversement de la clef vers le serveur. Veuillez vérifier votre connexion Internet.</string>
<string name="msg_export_success">Opération d\'exportation réussie !</string>
+ <string name="msg_export_upload_success">Téléversement vers le serveur de clefs réussi</string>
<string name="msg_del_error_empty">Rien à supprimer !</string>
<string name="msg_del_error_multi_secret">Les clefs secrètes ne peuvent être supprimées qu\'individuellement !</string>
<plurals name="msg_del">
@@ -1134,6 +1211,11 @@
<item quantity="one">Échec de suppression d\'une clef</item>
<item quantity="other">Échec de suppression de %d clefs</item>
</plurals>
+ <string name="msg_revoke_error_empty">Rien à révoquer !</string>
+ <string name="msg_revoke_error_not_found">Impossible de trouver la clef a révoquer !</string>
+ <string name="msg_revoke_key">Révocation de la clef %s</string>
+ <string name="msg_revoke_key_fail">Échec de révocation de la clef</string>
+ <string name="msg_revoke_ok">Clef révoquée avec succès</string>
<string name="msg_acc_saved">Compte enregistré</string>
<string name="msg_download_success">Téléchargement réussi !</string>
<string name="msg_download_no_valid_keys">Aucune clef valide n\'a été trouvée dans le fichier/presse-papiers |</string>
@@ -1169,6 +1251,11 @@
<string name="passp_cache_notif_keys">Mots de passe mémorisés</string>
<string name="passp_cache_notif_clear">Effacer les mots de passe</string>
<string name="passp_cache_notif_pwd">Mot de passe</string>
+ <!--Keyserver sync-->
+ <string name="keyserver_sync_orbot_notif_title">Synchroniser à partir du nuage (Orbot exigé)</string>
+ <string name="keyserver_sync_orbot_notif_msg">Toquer pour lancer Orbot</string>
+ <string name="keyserver_sync_orbot_notif_start">Lancer Orbot</string>
+ <string name="keyserver_sync_orbot_notif_ignore">Directe</string>
<!--First Time-->
<string name="first_time_text1">Reprenez le contrôle de votre vie privée avec OpenKeychain |</string>
<string name="first_time_create_key">Créer ma clef</string>
@@ -1177,6 +1264,10 @@
<string name="first_time_skip">Ignorer le paramétrage</string>
<string name="first_time_blank_yubikey">Voulez-vous utiliser cette ClefYubi NEO vide avec OpenKeychain ?\n\nVeuillez retirer la ClefYubi maintenant, vous serez informé quand elle sera requise de nouveau !</string>
<string name="first_time_blank_yubikey_yes">Utiliser cette ClefYubi</string>
+ <string name="backup_text">Les sauvegardes incluant vos propres clefs ne doivent jamais être partagées avec d\'autres personnes !</string>
+ <string name="backup_all">Toutes les clefs + vos propres clefs</string>
+ <string name="backup_public_keys">Toutes les clefs</string>
+ <string name="backup_section">Sauvegarde</string>
<!--unsorted-->
<string name="section_certifier_id">Certificateur</string>
<string name="section_cert">Détails du certificat</string>
@@ -1201,7 +1292,6 @@
<string name="unknown_algorithm">inconnu</string>
<string name="can_sign_not">impossible de signer</string>
<string name="error_no_encrypt_subkey">Aucune sous-clef de chiffrement n\'est proposée !</string>
- <string name="account_no_manual_account_creation">Ne pas créer de comptes-OpenKeychain manuellement.\nPour plus d\'informations, consultez l\'Aide.</string>
<string name="contact_show_key">Montrer la clef (%s)</string>
<string name="swipe_to_update">Glisser vers le bas pour mettre à jour à partir du serveur de clefs</string>
<string name="error_no_file_selected">Choisir au moins un fichier à chiffrer !</string>
@@ -1213,6 +1303,10 @@
<string name="exchange_description">Pour démarrer un échange de clef, choisir le nombre de participants du côté droit, puis cliquer sur le bouton « Démarrer l\'échange ».\n\Deux questions de plus seront posées pour s\'assurer que seuls les bons participants sont dans l\'échange et que les empreintes sont correctes.</string>
<string name="btn_start_exchange">Démarrer l\'échange</string>
<string name="user_id_none"><![CDATA[<none>]]></string>
+ <!--Android Account-->
+ <string name="account_no_manual_account_creation">Vous ne pouvez pas créer de compte OpenKeychain manuellement..</string>
+ <string name="account_privacy_title">Confidentialité</string>
+ <string name="account_privacy_text">OpenKeychain ne synchronise pas vos contacts avec l\'Internet. Il ne fait que relier les contacts aux clefs d\'après les noms et les adresses courriel. Il le fait hors ligne sur votre appareil.</string>
<!--Passphrase wizard-->
<!--TODO: rename all the things!-->
<string name="title_unlock_method">Choisir une méthode de déverrouillage</string>
@@ -1252,6 +1346,22 @@
<string name="btn_import">Importer</string>
<string name="snack_yubi_other">Une clef différente est stockée sur la ClefYubi !</string>
<string name="error_nfc">Erreur NFC ; %s</string>
+ <plurals name="error_pin">
+ <item quantity="one">NIP erroné !\nil reste %d essai.</item>
+ <item quantity="other">NIP erroné !\nil reste %d essais.</item>
+ </plurals>
+ <string name="error_nfc_terminated">La ClefYubi est en état de fin d\'opération.</string>
+ <string name="error_nfc_wrong_length">Le NIP saisi est trop court. Les NIP comportent au moins 6 chiffres.</string>
+ <string name="error_nfc_conditions_not_satisfied">Les conditions d\'utilisation ne sont pas satisfaites.</string>
+ <string name="error_nfc_security_not_satisfied">L\'état de sécurité n\'est pas satisfait.</string>
+ <string name="error_nfc_authentication_blocked">NIP bloqué après trop d\'essais.</string>
+ <string name="error_nfc_data_not_found">Clef ou objet introuvable.</string>
+ <string name="error_nfc_unknown">Erreur inconnue</string>
+ <string name="error_nfc_bad_data">La ClefYubi a signalé des données invalides.</string>
+ <string name="error_nfc_chaining_error">La ClefYubi attendait la dernière commande d\'une chaîne.</string>
+ <string name="error_nfc_header">La ClefYubi a signalé %s bytes invalides.</string>
+ <string name="error_nfc_tag_lost">La ClefYubi a été retirée trop tôt. Conservez la ClefYubi contre le dos jusqu\'à la fin de l\'opération.</string>
+ <string name="error_nfc_try_again">Ressayer</string>
<string name="error_pin_nodefault">Le NIP par défaut a été rejeté !</string>
<string name="error_temp_file">Erreur de création du fichier temporaire.</string>
<string name="btn_delete_original">Supprimer le fichier original</string>
@@ -1277,4 +1387,8 @@
<string name="file_delete_none">Aucun fichier supprimé (déjà supprimé ?)</string>
<string name="file_delete_exception">Impossible de supprimer le fichier original !</string>
<string name="error_clipboard_empty">Le presse-papiers est vide !</string>
+ <string name="error_clipboard_copy">Erreur de copie des données vers le presse-papiers !</string>
+ <string name="error_scan_fp">Erreur de numérisation de l\'empreinte !</string>
+ <string name="error_scan_match">Les empreintes ne correspondent pas !</string>
+ <string name="error_expiry_past">La date d\'expiration est dans le passé !</string>
</resources>
diff --git a/OpenKeychain/src/main/res/values-ar/strings.xml b/OpenKeychain/src/main/res/values-hu/strings.xml
index 0713e39ad..b0fd66dfe 100644
--- a/OpenKeychain/src/main/res/values-ar/strings.xml
+++ b/OpenKeychain/src/main/res/values-hu/strings.xml
@@ -7,6 +7,7 @@
<!--button-->
<!--menu-->
<!--label-->
+ <!--label shown in Android settings under the OpenKeychain account-->
<!--Proxy Preferences-->
<!--proxy type choices and values-->
<!--OrbotHelper strings-->
@@ -36,10 +37,14 @@
<!--Generic result toast-->
<!--Import result toast-->
<!--Delete result toast-->
+ <!--Revoke result toast (snackbar)-->
<!--Certify result toast-->
<!--Intent labels-->
<!--Remote API-->
<!--Share-->
+ <!--retry upload dialog-->
+ <!--Delete or revoke private key dialog-->
+ <!--Delete Or Revoke Dialog spinner-->
<!--Key list-->
<!--Key view-->
<!--Key trust-->
@@ -69,8 +74,10 @@
<!--Messages for Keybase Verification operation-->
<!--Messages for Export Log operation-->
<!--PassphraseCache-->
+ <!--Keyserver sync-->
<!--First Time-->
<!--unsorted-->
+ <!--Android Account-->
<!--Passphrase wizard-->
<!--TODO: rename all the things!-->
<!--<string name="enter_passphrase_twice">Enter password twice</string>-->
diff --git a/OpenKeychain/src/main/res/values-is/strings.xml b/OpenKeychain/src/main/res/values-is/strings.xml
deleted file mode 100644
index 0713e39ad..000000000
--- a/OpenKeychain/src/main/res/values-is/strings.xml
+++ /dev/null
@@ -1,78 +0,0 @@
-<?xml version='1.0' encoding='UTF-8'?>
-<resources>
- <!--GENERAL: Please put all strings inside quotes as described in example 1 on
- http://developer.android.com/guide/topics/resources/string-resource.html (scroll down to "Escaping apostrophes and quotes").-->
- <!--title-->
- <!--section-->
- <!--button-->
- <!--menu-->
- <!--label-->
- <!--Proxy Preferences-->
- <!--proxy type choices and values-->
- <!--OrbotHelper strings-->
- <!--InstallDialogFragment strings-->
- <!--StartOrbotDialogFragment strings-->
- <!--choice-->
- <!--key flags-->
- <!--sentences-->
- <!--errors
- no punctuation, all lowercase,
- they will be put after "error_message", e.g. "Error: file not found"-->
- <!--errors without preceeding Error:-->
- <!--results shown after decryption/verification-->
- <!--Add keys-->
- <!--progress dialogs, usually ending in '…'-->
- <!--action strings-->
- <!--key bit length selections-->
- <!--elliptic curve names-->
- <!--not in for now, see SaveKeyringParcel
- <string name="key_curve_bp_p256">"Brainpool P-256"</string>
- <string name="key_curve_bp_p384">"Brainpool P-384"</string>
- <string name="key_curve_bp_p512">"Brainpool P-512"</string>-->
- <!--compression-->
- <!--Help-->
- <!--Import-->
- <!--Import from URL-->
- <!--Generic result toast-->
- <!--Import result toast-->
- <!--Delete result toast-->
- <!--Certify result toast-->
- <!--Intent labels-->
- <!--Remote API-->
- <!--Share-->
- <!--Key list-->
- <!--Key view-->
- <!--Key trust-->
- <!--keybase proof stuff-->
- <!--Edit key-->
- <!--Create key-->
- <!--View key-->
- <!--Add/Edit keyserver-->
- <!--Navigation Drawer-->
- <!--hints-->
- <!--certs-->
- <!--LogType log messages. Errors should have _ERROR_ in their name and end with a !-->
- <!--Import Public log entries-->
- <!--Import Secret log entries-->
- <!--Keyring Canonicalization log entries-->
- <!--Keyring merging log entries-->
- <!--createSecretKeyRing-->
- <!--modifySecretKeyRing-->
- <!--Consolidate-->
- <!--Edit Key (higher level than modify)-->
- <!--Promote key-->
- <!--Other messages used in OperationLogs-->
- <!--Messages for DecryptVerify operation-->
- <!--Messages for VerifySignedLiteralData operation-->
- <!--Messages for SignEncrypt operation-->
- <!--Messages for PgpSignEncrypt operation-->
- <!--Messages for Keybase Verification operation-->
- <!--Messages for Export Log operation-->
- <!--PassphraseCache-->
- <!--First Time-->
- <!--unsorted-->
- <!--Passphrase wizard-->
- <!--TODO: rename all the things!-->
- <!--<string name="enter_passphrase_twice">Enter password twice</string>-->
- <!--<string name="nfc_text">Please place a NFC tag near your device</string>-->
-</resources>
diff --git a/OpenKeychain/src/main/res/values-it/strings.xml b/OpenKeychain/src/main/res/values-it/strings.xml
index 9a479c947..9f58dc3ba 100644
--- a/OpenKeychain/src/main/res/values-it/strings.xml
+++ b/OpenKeychain/src/main/res/values-it/strings.xml
@@ -20,8 +20,8 @@
<string name="title_encrypt_to_file">Codifica File</string>
<string name="title_decrypt_to_file">Decodifica File</string>
<string name="title_import_keys">Importa Chiavi</string>
- <string name="title_export_key">Esporta Chiave</string>
- <string name="title_export_keys">Esporta Chiavi</string>
+ <string name="title_export_key">Backup chiave</string>
+ <string name="title_export_keys">Backup chiavi</string>
<string name="title_key_not_found">Chiave Non Trovata</string>
<string name="title_send_key">Carica sul Server delle Chiavi</string>
<string name="title_certify_key">Conferma chiave</string>
@@ -86,7 +86,6 @@
<!--menu-->
<string name="menu_preferences">Impostazioni</string>
<string name="menu_help">Aiuto</string>
- <string name="menu_export_key">Esporta su un file</string>
<string name="menu_delete_key">Cancella chiave</string>
<string name="menu_manage_keys">Gestisci mie chiavi</string>
<string name="menu_search">Cerca</string>
@@ -157,11 +156,25 @@
<string name="pref_keyserver_summary">Cerca chiavi su server chiavi OpenPGP selezionati (protocollo HKP)</string>
<string name="pref_keybase">keybase.io</string>
<string name="pref_keybase_summary">Ricerca chiavi su keybase.io</string>
+ <!--label shown in Android settings under the OpenKeychain account-->
<!--Proxy Preferences-->
+ <string name="pref_proxy_type_title">Tipo proxy</string>
<!--proxy type choices and values-->
+ <string name="pref_proxy_type_choice_http">HTTP</string>
+ <string name="pref_proxy_type_choice_socks">SOCKS</string>
<!--OrbotHelper strings-->
+ <string name="orbot_ignore_tor">Non usare Tor</string>
<!--InstallDialogFragment strings-->
+ <string name="orbot_install_dialog_title">Installa Orbot per usare Tor?</string>
+ <string name="orbot_install_dialog_install">Installa</string>
+ <string name="orbot_install_dialog_content">Orbot deve essere installato e attivato per fare attraversare il traffico dei dati tramite proxy. Vuoi installare Orbot?</string>
+ <string name="orbot_install_dialog_cancel">Annulla</string>
+ <string name="orbot_install_dialog_ignore_tor">Non usare Tor</string>
<!--StartOrbotDialogFragment strings-->
+ <string name="orbot_start_dialog_title">Attivare Orbot?</string>
+ <string name="orbot_start_btn">Attivare Orbot</string>
+ <string name="orbot_start_dialog_start">Attivare Orbot</string>
+ <string name="orbot_start_dialog_cancel">Annulla</string>
<string name="user_id_no_name">&lt;nessun nome&gt;</string>
<string name="none">&lt;nessuno&gt;</string>
<plurals name="n_keys">
@@ -219,7 +232,6 @@
<string name="error_no_encryption_or_signature_key">Selezionare almeno una chiave per la cifratura o una chiave per la firma.</string>
<string name="specify_file_to_encrypt_to">Per favore specifica il file da codificare entro.\nATTENZIONE: Il file sarà sovrascritto se esistente.</string>
<string name="specify_file_to_decrypt_to">Per favore specifica il file da decifrare entro.\nATTENZIONE: Il file sarà sovrascritto se esistente.</string>
- <string name="specify_backup_dest">Per favore specifica il file da esportare entro.\nATTENZIONE: Il file sarà sovrascritto se esistente.</string>
<string name="key_deletion_confirmation_multi">Vuoi veramente eliminare tutte le chiavi selezionate?</string>
<string name="secret_key_deletion_confirmation">Dopo la cancellazione non sarai in grado di leggere i messaggi cifrati con questa chiave e perderai tutte le conferme principali fatti con essa!</string>
<string name="public_key_deletetion_confirmation">Elimnina chiave \'%s\'?</string>
@@ -288,6 +300,7 @@
<string name="progress_cancelling">cancellando...</string>
<string name="progress_saving">salvataggio...</string>
<string name="progress_importing">importazione...</string>
+ <string name="progress_updating">Aggiorna chiavi...</string>
<string name="progress_exporting">esportazione...</string>
<string name="progress_uploading">caricamento...</string>
<string name="progress_building_key">fabbricazione chiave...</string>
@@ -307,6 +320,8 @@
<string name="progress_modify_subkeystrip">pulizia sottochiavi...</string>
<string name="progress_modify_subkeyadd">Aggiunta sottochiave...</string>
<string name="progress_modify_passphrase">cambiando la password...</string>
+ <string name="progress_modify_pin">cambiando PIN...</string>
+ <string name="progress_modify_admin_pin">cambiando Admin PIN...</string>
<plurals name="progress_exporting_key">
<item quantity="one">esportazione chiave...</item>
<item quantity="other">esportazione chiavi...</item>
@@ -370,8 +385,10 @@
<string name="import_tab_qr_code">Codice QR/NFC</string>
<string name="import_import">Importa chiavi selezionate</string>
<string name="import_qr_code_wrong">Codica QR deformato! Prova di nuovo!</string>
+ <string name="import_qr_code_button">Scansione codice QR</string>
<!--Import from URL-->
<!--Generic result toast-->
+ <string name="snackbar_details">Dettagli</string>
<string name="with_warnings">, con avvisi</string>
<string name="with_cancelled">, fino all\'annullamento</string>
<!--Import result toast-->
@@ -404,6 +421,7 @@
<!--Delete result toast-->
<string name="delete_nothing">Niente da cancellare.</string>
<string name="delete_cancelled">Operazione di eliminazione cancellata.</string>
+ <!--Revoke result toast (snackbar)-->
<!--Certify result toast-->
<!--Intent labels-->
<string name="intent_decrypt_file">Decodifica File con OpenKeychain</string>
@@ -413,6 +431,7 @@
<!--Remote API-->
<string name="api_settings_no_key">Nessuna chiave selezionata</string>
<string name="api_settings_select_key">Seleziona chiave</string>
+ <string name="api_settings_create_key">Crea chiave nuova</string>
<string name="api_settings_save">Salva</string>
<string name="api_settings_save_msg">L\'account è stato salvato</string>
<string name="api_settings_cancel">Annulla</string>
@@ -420,7 +439,6 @@
<string name="api_settings_start">Avvia applicazione</string>
<string name="api_settings_delete_account">Cancella account</string>
<string name="api_settings_package_name">Nome Pacchetto</string>
- <string name="api_settings_package_certificate">SHA-256 della Firma del Pacchetto</string>
<string name="api_settings_settings">Impostazioni</string>
<string name="api_settings_key">Chiave account:</string>
<string name="api_settings_accounts_empty">Nessun account collegato a questa applicazione</string>
@@ -431,14 +449,15 @@ Permetti accesso?\n\nATTENZIONE: Se non sai perche\' questo schermata e\' appars
<string name="api_register_allow">Permetti accesso</string>
<string name="api_register_disallow">Nega accesso</string>
<string name="api_register_error_select_key">Per favore selezionare una chiave!</string>
- <string name="api_select_pub_keys_missing_text">Nessuna chiave trovata per queste identità:</string>
- <string name="api_select_pub_keys_dublicates_text">Esistono piu\' di una chiave per queste identità:</string>
<string name="api_select_pub_keys_text">Per favore ricontrolla la lista destinatari!</string>
<string name="api_select_pub_keys_text_no_user_ids">Per favore seleziona i destinatari!</string>
<string name="api_error_wrong_signature">Controllo della firma fallito! Hai installato questa app da una fonte diversa? Se sei sicuro che non sia un attacco, revoca la registrazione di questa app in OpenKeychain e dopo registra di nuovo l\'app.</string>
<!--Share-->
<string name="share_qr_code_dialog_title">Condividi tramite Codice QR</string>
<string name="share_nfc_dialog">Condividi tramite NFC</string>
+ <!--retry upload dialog-->
+ <!--Delete or revoke private key dialog-->
+ <!--Delete Or Revoke Dialog spinner-->
<!--Key list-->
<plurals name="key_list_selected_keys">
<item quantity="one">1 chiave selezionata.</item>
@@ -723,6 +742,7 @@ Permetti accesso?\n\nATTENZIONE: Se non sai perche\' questo schermata e\' appars
<!--Messages for Keybase Verification operation-->
<!--Messages for Export Log operation-->
<!--PassphraseCache-->
+ <!--Keyserver sync-->
<!--First Time-->
<string name="first_time_text1">Riappropriati della tua privacy con OpenKeychain!</string>
<string name="first_time_skip">Salta Installazione</string>
@@ -743,12 +763,13 @@ Permetti accesso?\n\nATTENZIONE: Se non sai perche\' questo schermata e\' appars
<string name="unknown_algorithm">sconosciuto</string>
<string name="can_sign_not">non può firmare</string>
<string name="error_no_encrypt_subkey">Nessuna sottochiave di codifica disponibile!</string>
- <string name="account_no_manual_account_creation">Non creare account OpenKeychain manualmente.\nPer ulteriori informazioni, vedere la Guida.</string>
<string name="contact_show_key">Mostra chiave (%s)</string>
<string name="error_no_file_selected">Seleziona almeno un file da codificare!</string>
<string name="key_colon">Chiave:</string>
+ <!--Android Account-->
<!--Passphrase wizard-->
<!--TODO: rename all the things!-->
<!--<string name="enter_passphrase_twice">Enter password twice</string>-->
<!--<string name="nfc_text">Please place a NFC tag near your device</string>-->
+ <string name="file_saved">File salvato!</string>
</resources>
diff --git a/OpenKeychain/src/main/res/values-ja/strings.xml b/OpenKeychain/src/main/res/values-ja/strings.xml
index 5de95f3c1..6f735b35b 100644
--- a/OpenKeychain/src/main/res/values-ja/strings.xml
+++ b/OpenKeychain/src/main/res/values-ja/strings.xml
@@ -7,13 +7,12 @@
<string name="title_encrypt_text">暗号化</string>
<string name="title_encrypt_files">暗号化</string>
<string name="title_decrypt">復号化</string>
- <string name="title_unlock">鍵のロック解除</string>
<string name="title_add_subkey">副鍵の追加</string>
<string name="title_edit_key">鍵の編集</string>
<string name="title_preferences">設定</string>
<string name="title_api_registered_apps">アプリ</string>
- <string name="title_key_server_preference">鍵サーバ</string>
- <string name="title_change_passphrase">パスフレーズの変更</string>
+ <string name="title_key_server_preference">OpenPGP鍵サーバ</string>
+ <string name="title_change_passphrase">パスワードの変更</string>
<string name="title_share_fingerprint_with">...で指紋の共有</string>
<string name="title_share_key">...で鍵の共有</string>
<string name="title_share_file">...でファイルの共有</string>
@@ -21,8 +20,8 @@
<string name="title_encrypt_to_file">暗号化してファイルに</string>
<string name="title_decrypt_to_file">復号化してファイルに</string>
<string name="title_import_keys">鍵のインポート</string>
- <string name="title_export_key">鍵のエクスポート</string>
- <string name="title_export_keys">複数鍵のエクスポート</string>
+ <string name="title_export_key">鍵のバックアップ</string>
+ <string name="title_export_keys">鍵のバックアップ</string>
<string name="title_key_not_found">鍵が見当りません</string>
<string name="title_send_key">鍵サーバへアップロード</string>
<string name="title_certify_key">鍵の確認</string>
@@ -30,33 +29,39 @@
<string name="title_help">ヘルプ</string>
<string name="title_log_display">ログ</string>
<string name="title_exchange_keys">鍵の交換</string>
- <string name="title_advanced_key_info">鍵の詳細情報</string>
+ <string name="title_advanced_key_info">拡張情報</string>
<string name="title_delete_secret_key">あなたの鍵 \'%s\' を削除しますか?</string>
<string name="title_export_log">エクスポートログ</string>
<string name="title_manage_my_keys">自分の鍵の管理</string>
<!--section-->
<string name="section_user_ids">ユーザID</string>
+ <string name="section_yubikey">YubiKey</string>
<string name="section_linked_system_contact">リンクしているシステムの連絡先</string>
<string name="section_should_you_trust">この鍵を信頼しますか?</string>
<string name="section_proof_details">証明検証</string>
<string name="section_cloud_evidence">クラウドからの証明</string>
<string name="section_keys">副鍵</string>
<string name="section_cloud_search">クラウド検索</string>
- <string name="section_passphrase_cache">パスフレーズキャッシュ</string>
+ <string name="section_passphrase_cache">パスワード/PINの取り扱い</string>
+ <string name="section_proxy_settings">プロキシの設定</string>
+ <string name="section_gui">インタフェース</string>
+ <string name="section_sync_settings">同期設定</string>
<string name="section_certify">確認</string>
<string name="section_actions">アクション</string>
<string name="section_share_key">鍵</string>
<string name="section_key_server">鍵サーバ</string>
<string name="section_fingerprint">指紋</string>
<string name="section_encrypt">暗号化</string>
- <string name="section_decrypt">復号化</string>
+ <string name="section_decrypt">復号 / 検証</string>
<string name="section_current_expiry">現在の期限</string>
<string name="section_new_expiry">新しい期限</string>
<!--button-->
<string name="btn_decrypt_verify_file">復号化と検証、そしてファイルの保存</string>
<string name="btn_encrypt_share_file">暗号化してファイルを共有</string>
<string name="btn_encrypt_save_file">暗号化してファイルを保存</string>
+ <string name="btn_save_file">ファイルの保存</string>
<string name="btn_save">保存</string>
+ <string name="btn_view_log">ログを見る</string>
<string name="btn_do_not_save">キャンセル</string>
<string name="btn_delete">削除</string>
<string name="btn_no_date">満了なし</string>
@@ -71,17 +76,21 @@
<string name="btn_view_cert_key">検証した鍵を見る</string>
<string name="btn_create_key">鍵の生成</string>
<string name="btn_add_files">ファイルの追加</string>
- <string name="btn_add_share_decrypted_text">復号化したテキストの共有</string>
- <string name="btn_decrypt_clipboard">クリップボードからテキストを復号化</string>
- <string name="btn_decrypt_and_verify">と署名の検証</string>
- <string name="btn_decrypt_files">ファイルの復号化</string>
+ <string name="btn_share_decrypted_text">復号化したテキストの共有</string>
+ <string name="btn_copy_decrypted_text">復号化したテキストのコピー</string>
+ <string name="btn_decrypt_clipboard">クリップボードから読み取り</string>
+ <string name="btn_decrypt_files">入力ファイルの選択</string>
<string name="btn_encrypt_files">ファイルの暗号化</string>
<string name="btn_encrypt_text">テキストの暗号化</string>
<string name="btn_add_email">追加のEメールアドレスを追加</string>
+ <string name="btn_unlock">アンロック</string>
+ <string name="btn_add_keyserver">追加</string>
+ <string name="btn_save_default">デフォルトとして保存</string>
+ <string name="btn_saved">保存しました!</string>
<!--menu-->
<string name="menu_preferences">設定</string>
<string name="menu_help">ヘルプ</string>
- <string name="menu_export_key">ファイルへのエクスポート</string>
+ <string name="menu_export_key">ファイルへバックアップ</string>
<string name="menu_delete_key">鍵の削除</string>
<string name="menu_manage_keys">自分の鍵の管理</string>
<string name="menu_search">検索</string>
@@ -91,19 +100,20 @@
<string name="menu_select_all">すべて選択</string>
<string name="menu_export_all_keys">すべての鍵のエクスポート</string>
<string name="menu_update_all_keys">全部のキーをアップデートする</string>
- <string name="menu_advanced">詳細情報を表示</string>
+ <string name="menu_advanced">拡張情報</string>
<string name="menu_certify_fingerprint">指紋比較による確認</string>
<string name="menu_export_log">エクスポートログ</string>
+ <string name="menu_keyserver_add">追加</string>
<!--label-->
<string name="label_message">テキスト</string>
<string name="label_file">ファイル</string>
<string name="label_files">ファイル</string>
<string name="label_file_colon">ファイル:</string>
- <string name="label_no_passphrase">パスフレーズなし</string>
- <string name="label_passphrase">パスフレーズ</string>
+ <string name="label_no_passphrase">パスワードなし</string>
+ <string name="label_passphrase">パスワード</string>
<string name="label_unlock">アンロック...</string>
- <string name="label_passphrase_again">再度パスフレーズを入力</string>
- <string name="label_show_passphrase">パスフレーズ表示</string>
+ <string name="label_passphrase_again">再度パスワードを入力</string>
+ <string name="label_show_passphrase">パスワード表示</string>
<string name="label_algorithm">アルゴリズム</string>
<string name="label_ascii_armor">アスキー形式ファイル</string>
<string name="label_file_ascii_armor">アスキー形式ファイルを有効</string>
@@ -118,13 +128,14 @@
<string name="label_delete_after_decryption">復号化後に削除</string>
<string name="label_encryption_algorithm">暗号化アルゴリズム</string>
<string name="label_hash_algorithm">ハッシュアルゴリズム</string>
- <string name="label_symmetric">パスフレーズで暗号化</string>
- <string name="label_passphrase_cache_ttl">キャッシュ時間</string>
- <string name="label_passphrase_cache_subs">副鍵のパスフレーズをキャッシュ</string>
+ <string name="label_symmetric">パスワードで暗号化</string>
+ <string name="label_passphrase_cache_ttl">時刻を忘れない</string>
+ <string name="label_passphrase_cache_subs">副鍵のパスワードを忘れない</string>
<string name="label_message_compression">テキストの圧縮</string>
<string name="label_file_compression">ファイルの圧縮</string>
- <string name="label_keyservers">鍵サーバ</string>
+ <string name="label_keyservers">OpenPGP鍵サーバを選択</string>
<string name="label_key_id">鍵ID</string>
+ <string name="label_key_created">%s で鍵を生成</string>
<string name="label_creation">生成</string>
<string name="label_expiry">満了</string>
<string name="label_usage">使い方</string>
@@ -137,15 +148,55 @@
<string name="label_send_key">クラウドによる同期</string>
<string name="label_fingerprint">指紋</string>
<string name="expiry_date_dialog_title">期限日時を設定</string>
- <string name="label_first_keyserver_is_used">(リストの最初の鍵サーバが優先されます)</string>
+ <string name="label_keyservers_title">鍵サーバ</string>
+ <string name="label_keyserver_settings_hint">ドラッグで順序変更、タップで編集/削除</string>
+ <string name="label_selected_keyserver_title">選択した鍵サーバ</string>
<string name="label_preferred">優先</string>
<string name="label_enable_compression">圧縮を有効</string>
<string name="label_encrypt_filenames">暗号化するファイル名</string>
<string name="label_hidden_recipients">受信者を隠す</string>
- <string name="pref_keyserver">キーサーバーで探す</string>
- <string name="pref_keyserver_summary">HKPキーサーバーで探す</string>
- <string name="pref_keybase">Keybase.ioで探す</string>
- <string name="pref_keybase_summary">Keybase.ioのインデックスで探す</string>
+ <string name="label_verify_keyserver">鍵サーバを検証</string>
+ <string name="label_enter_keyserver_url">鍵サーバのURLを入力</string>
+ <string name="label_keyserver_dialog_delete">鍵サーバの削除</string>
+ <string name="label_theme">テーマ</string>
+ <string name="pref_keyserver">OpenPGP鍵サーバ</string>
+ <string name="pref_keyserver_summary">選択したOpenPGP鍵サーバで鍵を探す (HKPプロトコル)</string>
+ <string name="pref_keybase">Keybase.io</string>
+ <string name="pref_keybase_summary">Keybase.ioで鍵を探す</string>
+ <string name="label_sync_settings_keyserver_title">鍵の自動アップデート</string>
+ <string name="label_sync_settings_keyserver_summary_on">1週間以上古い鍵なら鍵サーバへアップデートを問合せる</string>
+ <string name="label_sync_settings_keyserver_summary_off">鍵を自動でアップデートしない</string>
+ <string name="label_sync_settings_contacts_title">鍵の連絡先を同期する</string>
+ <string name="label_sync_settings_contacts_summary_on">オフランで完結した、鍵と連絡先のメールアドレスでの関連付けを行う</string>
+ <string name="label_sync_settings_contacts_summary_off">新しい鍵は連絡先と関連付けしない</string>
+ <!--label shown in Android settings under the OpenKeychain account-->
+ <string name="keyserver_sync_settings_title">鍵の自動アップデート</string>
+ <!--Proxy Preferences-->
+ <string name="pref_proxy_tor_title">Torを有効</string>
+ <string name="pref_proxy_tor_summary">Orbotのインストールが要求されます</string>
+ <string name="pref_proxy_normal_title">その他のプロキシを有効</string>
+ <string name="pref_proxy_host_title">プロキシのホスト</string>
+ <string name="pref_proxy_host_err_invalid">プロキシのホストは空にはできません</string>
+ <string name="pref_proxy_port_title">プロキシのポート</string>
+ <string name="pref_proxy_port_err_invalid">入力したポート番号が正しくない</string>
+ <string name="pref_proxy_type_title">プロキシの種別</string>
+ <!--proxy type choices and values-->
+ <string name="pref_proxy_type_choice_http">HTTP</string>
+ <string name="pref_proxy_type_choice_socks">SOCKS</string>
+ <!--OrbotHelper strings-->
+ <string name="orbot_ignore_tor">Torを使わない</string>
+ <!--InstallDialogFragment strings-->
+ <string name="orbot_install_dialog_title">Torで使うOrbotをインストールしますか?</string>
+ <string name="orbot_install_dialog_install">インストール</string>
+ <string name="orbot_install_dialog_cancel">キャンセル</string>
+ <string name="orbot_install_dialog_ignore_tor">Torを使わない</string>
+ <!--StartOrbotDialogFragment strings-->
+ <string name="orbot_start_dialog_title">Orbotを始めますか?</string>
+ <string name="orbot_start_dialog_content">Orbot は動作しても表れません。スタートしてTorに接続しますか?</string>
+ <string name="orbot_start_btn">Orbotを始める</string>
+ <string name="orbot_start_dialog_start">Orbotを始める</string>
+ <string name="orbot_start_dialog_cancel">キャンセル</string>
+ <string name="orbot_start_dialog_ignore_tor">Torを使わない</string>
<string name="user_id_no_name">&lt;名前なし&gt;</string>
<string name="none">&lt;無し&gt;</string>
<plurals name="n_keys">
@@ -177,32 +228,36 @@
<string name="filemanager_title_open">開く...</string>
<string name="error">エラー</string>
<string name="error_message">エラー: %s</string>
+ <string name="theme_dark">ダーク</string>
+ <string name="theme_light">ライト</string>
<!--key flags-->
<string name="flag_certify">証明</string>
<string name="flag_sign">署名</string>
<string name="flag_encrypt">暗号化</string>
<string name="flag_authenticate">認証</string>
<!--sentences-->
- <string name="wrong_passphrase">良くないパスフレーズ</string>
+ <string name="wrong_passphrase">正しくないパスワードです。</string>
<string name="no_filemanager_installed">互換性のないファイルマネージャがインストールされています。</string>
- <string name="passphrases_do_not_match">パスフレーズが一致しません。</string>
- <string name="passphrase_must_not_be_empty">パスフレーズを入れてください。</string>
+ <string name="passphrases_do_not_match">パスワードが一致しません。</string>
+ <string name="passphrase_must_not_be_empty">パスワードを入れてください。</string>
<string name="passphrase_for_symmetric_encryption">対称暗号。</string>
- <string name="passphrase_for">\'%s\' にパスフレーズを入れてください。</string>
+ <string name="passphrase_for">\'%s\' にパスワードを入れてください</string>
<string name="pin_for">\'%s\' にPINを入力してください</string>
<string name="yubikey_pin_for">\'%s\' の Yubikey にアクセスするためのPINを入力してください</string>
- <string name="nfc_text">あなたのデバイスの背面にYubiKeyを固定してください。</string>
+ <string name="nfc_text">YubiKeyをあなたのデバイスの背中にあるNFCの印に対向させて固定してください。</string>
+ <string name="nfc_wait">YubiKeyを背後に維持してください!</string>
+ <string name="nfc_finished">YubiKeyを取り外してください。</string>
+ <string name="nfc_try_again_text">Yubikeyを離し、再実行を推してください。</string>
<string name="file_delete_confirmation_title">オリジナルのファイルを削除しますか?</string>
<string name="file_delete_confirmation">以下のファイルを削除します:%s</string>
<string name="file_delete_successful">%1$d 中の %2$d のファイルの削除が完了しました。%3$s</string>
- <string name="no_file_selected">最初にファイルを選択してください。</string>
+ <string name="no_file_selected">ファイルが選択されていません。</string>
<string name="encrypt_sign_successful">署名/暗号化に成功しました。</string>
<string name="encrypt_sign_clipboard_successful">クリップボードの中身の署名/暗号化に成功しました。</string>
<string name="select_encryption_key">少なくとも1つの暗号化鍵を選択して下さい。</string>
<string name="error_no_encryption_or_signature_key">少なくとも1つの暗号化鍵か署名鍵を選択して下さい。</string>
<string name="specify_file_to_encrypt_to">どれのファイルを暗号化するのを入力してください。\n注意:ファイルが存在しているなら上書きされる!</string>
<string name="specify_file_to_decrypt_to">どれのファイルを暗号するのを入力してください。\n注意:ファイルが存在しているなら上書きされる!</string>
- <string name="specify_backup_dest">どれのファイルを復号化するのを入力してください。\n注意:ファイルが存在しているなら上書きされる!</string>
<string name="key_deletion_confirmation_multi">選択したすべての鍵を本当に削除してよいですか?</string>
<string name="secret_key_deletion_confirmation">削除後はこの鍵で暗号化されたメッセージが読めなくなります、またその鍵で行われたすべての鍵確認を失います!</string>
<string name="public_key_deletetion_confirmation">鍵 \'%s\' を削除しますか?</string>
@@ -239,31 +294,35 @@
<string name="error_external_storage_not_ready">外部ストレージが準備できていません</string>
<string name="error_key_size_minimum512bit">鍵サイズは最低でも512bit必要です</string>
<string name="error_unknown_algorithm_choice">未知のアルゴリズムを選択しています</string>
- <string name="error_user_id_no_email">メールが見付かりません</string>
+ <string name="error_user_id_no_email">メールアドレスが見付かりません</string>
<string name="error_key_needs_a_user_id">最低でも1つのユーザIDが必要です</string>
- <string name="error_no_signature_passphrase">パスフレーズが与えられていません</string>
+ <string name="error_no_signature_passphrase">パスワードが与えられていません</string>
<string name="error_no_signature_key">署名鍵を与えられていません</string>
<string name="error_invalid_data">暗号化もしくは署名の検証されてないOpenPGPの内容!</string>
<string name="error_integrity_check_failed">完全性チェックが失敗しました! データに変更があります!</string>
- <string name="error_wrong_passphrase">正しくないパスフレーズです</string>
+ <string name="error_wrong_passphrase">正しくないパスワードです</string>
<string name="error_could_not_extract_private_key">秘密鍵を取り出すことができません</string>
<!--errors without preceeding Error:-->
<string name="error_jelly_bean_needed">Android NFC Beam機能を使うにはAndroid 4.1 が必要です!</string>
<string name="error_nfc_needed">NFCを有効にしてください!</string>
<string name="error_beam_needed">Beamを有効にしてください!</string>
<string name="error_nothing_import">鍵が見当りません!</string>
+ <string name="error_nothing_import_selected">インポートの鍵が選択されていません!</string>
<string name="error_contacts_key_id_missing">連絡帳から鍵IDの回収が失敗しました!</string>
<string name="error_generic_report_bug">一般エラーが発生しました、この新しいバグの情報をOpenKeychainプロジェクトに送ってください</string>
<!--results shown after decryption/verification-->
<string name="decrypt_result_no_signature">未署名</string>
<string name="decrypt_result_invalid_signature">無効な署名です!</string>
- <string name="decrypt_result_signature_uncertified">署名(未検証!)</string>
- <string name="decrypt_result_signature_certified">署名</string>
- <string name="decrypt_result_signature_expired_key">鍵が期限切れ!</string>
- <string name="decrypt_result_signature_revoked_key">鍵が破棄されています!</string>
- <string name="decrypt_result_signature_missing_key">不明な公開鍵</string>
+ <string name="decrypt_result_insecure_cryptography">不正な署名 (セキュアではない暗号による)!</string>
+ <string name="decrypt_result_signature_uncertified"><b>未検証</b> の鍵で署名</string>
+ <string name="decrypt_result_signature_secret">あなたの鍵で署名</string>
+ <string name="decrypt_result_signature_certified">確認済みの鍵での署名</string>
+ <string name="decrypt_result_signature_expired_key"><b>期限切れ</b> の鍵での署名!</string>
+ <string name="decrypt_result_signature_revoked_key"><b>破棄された</b> 鍵での署名!</string>
+ <string name="decrypt_result_signature_missing_key"><b>不明な公開鍵</b> での署名</string>
<string name="decrypt_result_encrypted">暗号化</string>
<string name="decrypt_result_not_encrypted">未暗号化</string>
+ <string name="decrypt_result_insecure">セキュアではない暗号化</string>
<string name="decrypt_result_action_show">表示</string>
<string name="decrypt_result_action_Lookup">検出</string>
<string name="decrypt_invalid_text">署名が無効もしくは鍵が破棄された/期限が切れています。なのでだれかがあなたへ文書を書くなどとても出きません。まだ表示しますか?</string>
@@ -276,6 +335,7 @@
<string name="progress_cancelling">キャンセル中...</string>
<string name="progress_saving">保存...</string>
<string name="progress_importing">インポート...</string>
+ <string name="progress_revoking_uploading">鍵の破棄とアップロード...</string>
<string name="progress_updating">キーをアップデート中。。。</string>
<string name="progress_exporting">エクスポート...</string>
<string name="progress_uploading">アップロード中...</string>
@@ -296,10 +356,13 @@
<string name="progress_modify_subkeyrevoke">副鍵の破棄中...</string>
<string name="progress_modify_subkeystrip">副鍵のストリップ中...</string>
<string name="progress_modify_subkeyadd">副鍵を追加中...</string>
- <string name="progress_modify_passphrase">パスフレーズの変更中...</string>
+ <string name="progress_modify_passphrase">パスワードの変更中...</string>
+ <string name="progress_modify_pin">PINを変更...</string>
+ <string name="progress_modify_admin_pin">管理者PINを変更...</string>
<plurals name="progress_exporting_key">
<item quantity="other">鍵のエクスポート...</item>
</plurals>
+ <string name="progress_start">操作準備中...</string>
<string name="progress_extracting_signature_key">署名鍵の取り出し中...</string>
<string name="progress_extracting_key">鍵の取り出し中...</string>
<string name="progress_preparing_streams">ストリームの準備中...</string>
@@ -319,6 +382,8 @@
<string name="progress_deleting">鍵の削除中...</string>
<string name="progress_con_saving">統合: キャッシュへ保存…</string>
<string name="progress_con_reimport">統合: 再インポート中…</string>
+ <string name="progress_verifying_keyserver_url">鍵サーバの検証...</string>
+ <string name="progress_starting_orbot">Orbotを始める...</string>
<!--action strings-->
<string name="hint_cloud_search_hint">名前、Email...で検索</string>
<!--key bit length selections-->
@@ -360,11 +425,14 @@
<string name="import_tab_qr_code">QRコード/NFC</string>
<string name="import_import">選択した鍵のインポート</string>
<string name="import_qr_code_wrong">不適QRコード! もう一度!</string>
- <string name="import_qr_code_too_short_fingerprint">指紋が短かすぎます (&lt; 16 文字)</string>
+ <string name="import_qr_code_fp">指紋が正しくないか短かすぎます!</string>
+ <string name="import_qr_code_too_short_fingerprint">指紋が短かすぎます!</string>
<string name="import_qr_code_button">QCコードのスキャン</string>
<string name="import_qr_code_text">カメラをQRコードにかざしてください!</string>
+ <!--Import from URL-->
+ <string name="import_url_warn_no_search_parameter">検索要求が定義されていません。手動で鍵サーバで検索を試みることができます。</string>
<!--Generic result toast-->
- <string name="snackbar_details">概要</string>
+ <string name="snackbar_details">詳細</string>
<string name="with_warnings">、とワーニング</string>
<string name="with_cancelled">、キャンセルされるまで</string>
<!--Import result toast-->
@@ -403,6 +471,11 @@
</plurals>
<string name="delete_nothing">削除するものがありません。</string>
<string name="delete_cancelled">削除操作をキャンセルしました。</string>
+ <!--Revoke result toast (snackbar)-->
+ <string name="revoke_ok">鍵の破棄に成功しました。</string>
+ <string name="revoke_fail">鍵の破棄エラー!</string>
+ <string name="revoke_nothing">破棄するものがありません。</string>
+ <string name="revoke_cancelled">破棄操作をキャンセルしました。</string>
<!--Certify result toast-->
<plurals name="certify_keys_ok">
<item quantity="other">%1$d 個の鍵 %2$s の検証に成功。</item>
@@ -419,10 +492,10 @@
<string name="intent_send_encrypt">OpenKeychainで暗号化</string>
<string name="intent_send_decrypt">OpenKeychainで復号化</string>
<!--Remote API-->
- <string name="api_settings_show_info">詳細情報を表示</string>
- <string name="api_settings_hide_info">詳細情報を非表示</string>
+ <string name="api_settings_show_info">拡張情報を表示</string>
+ <string name="api_settings_hide_info">拡張情報を非表示</string>
<string name="api_settings_show_advanced">拡張設定を表示</string>
- <string name="api_settings_hide_advanced">拡張設定を隠す</string>
+ <string name="api_settings_hide_advanced">拡張設定を非表示</string>
<string name="api_settings_no_key">鍵が選択されていない</string>
<string name="api_settings_select_key">鍵の選択</string>
<string name="api_settings_create_key">新しい鍵の生成</string>
@@ -434,8 +507,8 @@
<string name="api_settings_delete_account">アカウントを削除</string>
<string name="api_settings_package_name">パッケージ名</string>
<string name="api_settings_package_certificate">パッケージの署名 SHA-256</string>
- <string name="api_settings_accounts">アカウント(deprecated API)</string>
- <string name="api_settings_advanced">詳細情報</string>
+ <string name="api_settings_accounts">アカウント(古いAPI)</string>
+ <string name="api_settings_advanced">拡張情報</string>
<string name="api_settings_allowed_keys">受け入れる鍵</string>
<string name="api_settings_settings">設定</string>
<string name="api_settings_key">アカウント鍵:</string>
@@ -451,15 +524,26 @@
<string name="api_register_allow">許可されたアクセス</string>
<string name="api_register_disallow">許可されないアクセス</string>
<string name="api_register_error_select_key">鍵を選択してください!</string>
- <string name="api_select_pub_keys_missing_text">このユーザIDについて鍵が見付かりません:</string>
- <string name="api_select_pub_keys_dublicates_text">このユーザIDについて1つ以上の鍵が存在します:</string>
+ <string name="api_select_pub_keys_missing_text">このメールアドレスの鍵が見付からない</string>
+ <string name="api_select_pub_keys_dublicates_text">このメールアドレスについて1つ以上の鍵が存在します:</string>
<string name="api_select_pub_keys_text">受信者リストを確認してください!</string>
<string name="api_select_pub_keys_text_no_user_ids">受信者を選択してください!</string>
<string name="api_error_wrong_signature">署名チェックが失敗! 違うところからこのアプリをインストールしましたか? もし攻撃されてでなくそうであるなら、OpenKeychainにあるこのアプリの登録を破棄し、再度アプリを登録してください。</string>
<string name="api_select_sign_key_text">すでにある鍵1つを選択するか新規に作成してください。</string>
+ <string name="api_select_keys_text">この内容を復号化することができる許可された鍵がありません。許可する鍵を選択してください。</string>
<!--Share-->
<string name="share_qr_code_dialog_title">QRコードで共有</string>
<string name="share_nfc_dialog">NFCで共有</string>
+ <!--retry upload dialog-->
+ <string name="retry_up_dialog_title">アップロード失敗</string>
+ <string name="retry_up_dialog_btn_reupload">操作再実行</string>
+ <string name="retry_up_dialog_btn_cancel">操作取り止め</string>
+ <!--Delete or revoke private key dialog-->
+ <string name="del_rev_dialog_btn_revoke">破棄とアップロード</string>
+ <string name="del_rev_dialog_btn_delete">削除のみ</string>
+ <!--Delete Or Revoke Dialog spinner-->
+ <string name="del_rev_dialog_choice_delete">削除のみ</string>
+ <string name="del_rev_dialog_choice_rev_upload">破棄とアップロード</string>
<!--Key list-->
<plurals name="key_list_selected_keys">
<item quantity="other">%d の鍵を選択。</item>
@@ -501,14 +585,14 @@
<string name="key_trust_results_prefix">Keybase.ioはこのキーのオーナーだと言う証拠を提供している:</string>
<string name="key_trust_header_text">注意:Keybase.ioのオーナー証拠は実験的な機会です。キーを確認することに加えて、QRコードや、NFCでキーを交換するのもお勧めする。</string>
<!--keybase proof stuff-->
- <string name="keybase_narrative_twitter">Twitterへ以下のIDで投稿</string>
- <string name="keybase_narrative_github">Githubでは以下のIDで知られています</string>
- <string name="keybase_narrative_dns">制御下にあるドメイン名(たち)</string>
- <string name="keybase_narrative_web_site">サイトに投稿できる</string>
- <string name="keybase_narrative_reddit">Redditへ以下のIDで投稿</string>
- <string name="keybase_narrative_coinbase">Coinbaseでは以下で知られています</string>
- <string name="keybase_narrative_hackernews">Hacker Newsへ以下のIDで投稿</string>
- <string name="keybase_narrative_unknown">不明な確認種別</string>
+ <string name="keybase_narrative_twitter">Twitterへ以下のIDで投稿 %s</string>
+ <string name="keybase_narrative_github">Githubでは %s で知られています</string>
+ <string name="keybase_narrative_dns">ドメイン名 %s を制御しています</string>
+ <string name="keybase_narrative_web_site">Webサイト %s に投稿できます</string>
+ <string name="keybase_narrative_reddit">Redditへ以下のIDで投稿 %s</string>
+ <string name="keybase_narrative_coinbase">Conbaseでは %s で知られています</string>
+ <string name="keybase_narrative_hackernews">Hacker Newsへ以下のIDで投稿 %s</string>
+ <string name="keybase_narrative_unknown">不明な検証種別 %s</string>
<string name="keybase_proof_failure">不幸にもこの証明は検証されていません。</string>
<string name="keybase_unknown_proof_failure">証明チェッカで正当に評価されない問題</string>
<string name="keybase_problem_fetching_evidence">確認に問題があります</string>
@@ -530,7 +614,7 @@
<string name="keybase_reddit_attribution">Redditの属性</string>
<string name="keybase_verify">検証</string>
<!--Edit key-->
- <string name="edit_key_action_change_passphrase">パスフレーズの変更</string>
+ <string name="edit_key_action_change_passphrase">パスワードの変更</string>
<string name="edit_key_action_add_identity">ユーザIDの追加</string>
<string name="edit_key_action_add_subkey">副鍵の追加</string>
<string name="edit_key_edit_user_id_title">アクションを選んでください!</string>
@@ -547,28 +631,38 @@
<item>期限の変更</item>
<item>副鍵の破棄</item>
<item>副鍵のストリップ</item>
- <item>"Move Subkey to Yubikey / Smart Card"</item>
+ <item>副鍵をYubiKey/スマートカードへ移動</item>
</string-array>
<string name="edit_key_new_subkey">新しい副鍵</string>
<string name="edit_key_select_flag">最低1つフラグを選択してください!</string>
<string name="edit_key_error_add_identity">最低でも1つのユーザIDを追加!</string>
<string name="edit_key_error_add_subkey">最低でも1つの副鍵を追加!</string>
+ <string name="edit_key_error_bad_nfc_algo">スマートカードではアルゴリズムをサポートしません!</string>
+ <string name="edit_key_error_bad_nfc_size">スマートカードでは鍵サイズをサポートしません!</string>
+ <string name="edit_key_error_bad_nfc_stripped">鍵をスマートカードに移動できません(ストリップしてあるか、\'カードへ迂回\'がない)</string>
<!--Create key-->
<string name="create_key_upload">クラウドとの同期</string>
<string name="create_key_empty">このフィールドは必須です</string>
- <string name="create_key_passphrases_not_equal">パスフレーズが一致しない</string>
+ <string name="create_key_passphrases_not_equal">パスワードが一致しない</string>
<string name="create_key_final_text">あたなが入力したIDは以下です:</string>
<string name="create_key_final_robot_text">しばらくの間鍵を生成しています、その間はコーヒーでもどうぞ....</string>
<string name="create_key_rsa">(3副鍵、RSA, 4096 bit)</string>
<string name="create_key_custom">(個別の鍵設定)</string>
<string name="create_key_name_text">この鍵に紐付ける名前を選択してください。これにはフルネーム、例えば「山田太郎」かニックネーム、例えば「たろすけ」にできます。</string>
<string name="create_key_email_text">あなたが秘密の通信で使うメインのEメールアドレスを入力してください。</string>
- <string name="create_key_passphrase_text">強度の高いパスフレーズを選択してください。そうすることであなたのデバイスが盗まれてもあなたの鍵を守ります。</string>
+ <string name="create_key_passphrase_text">強度の高いパスワードを選択してください。そうすることであなたのデバイスが盗まれてもあなたの鍵を守ります。</string>
<string name="create_key_hint_full_name">フルネームかニックネーム</string>
<string name="create_key_edit">鍵の設定変更</string>
<string name="create_key_add_email">Eメールアドレスの追加</string>
<string name="create_key_add_email_text">追加のEメールアドレスがこの鍵に紐付きそしてセキュアな通信に使うことができます。</string>
- <string name="create_key_email_already_exists_text">メールはすでに追加している</string>
+ <string name="create_key_email_already_exists_text">メールアドレスがすでに追加されている</string>
+ <string name="create_key_email_invalid_email">メールアドレスのフォーマットが無効です</string>
+ <string name="create_key_yubi_key_pin">PIN</string>
+ <string name="create_key_yubi_key_admin_pin">管理者PIN</string>
+ <string name="create_key_yubi_key_pin_repeat_text">処理を続けるためPINおよび管理者PINの入力をしてください。</string>
+ <string name="create_key_yubi_key_pin_repeat">再度PINを入力</string>
+ <string name="create_key_yubi_key_admin_pin_repeat">再度管理者PINを入力</string>
+ <string name="create_key_yubi_key_pin_not_correct">PINが正しくありません!</string>
<!--View key-->
<string name="view_key_revoked">破棄: 鍵はもう使われません!</string>
<string name="view_key_expired">期限切れ: この連絡先は鍵の妥当性を拡張する必要があります!</string>
@@ -577,6 +671,14 @@
<string name="view_key_verified">確認済みの鍵</string>
<string name="view_key_unverified">未確認: QRコードをスキャンして鍵を確認!</string>
<string name="view_key_fragment_no_system_contact">&lt;なし&gt;</string>
+ <!--Add/Edit keyserver-->
+ <string name="add_keyserver_dialog_title">鍵サーバを追加</string>
+ <string name="edit_keyserver_dialog_title">鍵サーバの編集</string>
+ <string name="add_keyserver_verified">鍵サーバを検証しました!</string>
+ <string name="add_keyserver_without_verification">鍵サーバを検証なしで追加した。</string>
+ <string name="add_keyserver_invalid_url">無効なURLです!</string>
+ <string name="add_keyserver_connection_failed">鍵サーバへの接続し失敗。URLとあなたのインターネット接続をチェックしてください。</string>
+ <string name="keyserver_preference_deleted">%s を削除</string>
<!--Navigation Drawer-->
<string name="nav_keys">鍵</string>
<string name="nav_encrypt_decrypt">暗号化/復号化</string>
@@ -584,6 +686,7 @@
<string name="drawer_open">ナビゲーションドロワーを開く</string>
<string name="drawer_close">ナビゲーションドロワーを閉める</string>
<string name="my_keys">自分の鍵</string>
+ <string name="nav_backup">バックアップ</string>
<!--hints-->
<string name="encrypt_content_edit_text_hint">テキストを入力</string>
<!--certs-->
@@ -701,10 +804,10 @@
<string name="msg_is_pubring_generate">秘密鍵の鍵輪から公開鍵の鍵輪を生成中</string>
<string name="msg_is_subkey_nonexistent">秘密鍵の副鍵 %s が利用不可能</string>
<string name="msg_is_subkey_ok">秘密鍵の副鍵 %s を利用可能としてマーク</string>
- <string name="msg_is_subkey_empty">秘密鍵の副鍵 %s を利用可能としてマーク、空のパスフレーズで</string>
+ <string name="msg_is_subkey_empty">空のパスワードで秘密鍵の副鍵 %s を利用可能としてマーク</string>
<string name="msg_is_subkey_pin">秘密鍵の副鍵 %s をPINとして利用可能とマーク</string>
<string name="msg_is_subkey_stripped">秘密鍵の副鍵 %s をストリップとしてマーク</string>
- <string name="msg_is_subkey_divert">秘密鍵の副鍵 %s を\'スマートカード/NFCへ迂回\'としてマーク</string>
+ <string name="msg_is_subkey_divert">秘密副鍵 %s を\'カードへ迂回\' としてマーク</string>
<string name="msg_is_success_identical">鍵輪にデータがないため、なにもしません</string>
<string name="msg_is_success">秘密鍵の鍵輪のインポートに成功</string>
<!--Keyring Canonicalization log entries-->
@@ -731,6 +834,7 @@
<string name="msg_kc_sub_bad_local">\'ローカル\'フラグ付きの証明が付随する副鍵を破棄中</string>
<string name="msg_kc_sub_bad_keyid">副鍵の発行者のIDと付随するIDがミスマッチ</string>
<string name="msg_kc_sub_bad_time">未来にタイムスタンプがある証明が付随する副鍵を破棄中</string>
+ <string name="msg_kc_sub_bad_time_early">副鍵と結びついている証明は鍵のタイムスタンプより前の日時です!</string>
<string name="msg_kc_sub_bad_type">不明な検証のタイプ: %sの副鍵</string>
<string name="msg_kc_sub_dup">証明が付随する重複する副鍵を破棄中</string>
<string name="msg_kc_sub_primary_bad">付随する主たる証明が無効であるものが付随する副鍵を破棄中</string>
@@ -805,6 +909,7 @@
<string name="msg_cr_error_flags_ecdh">問題のある鍵フラグが選択されています、楕円曲線DHは署名に使えません!</string>
<!--modifySecretKeyRing-->
<string name="msg_mr">鍵輪 %s を変更中</string>
+ <string name="msg_mf_divert">カードでの暗号化操作に切り替えられます</string>
<string name="msg_mf_error_divert_serial">カードに対比した鍵のシリアル番号には16バイトは必要です!これはプロラグラムエラーで、バグレポートでファイルの提出をお願いします!</string>
<string name="msg_mf_error_encode">エンコード例外!</string>
<string name="msg_mf_error_fingerprint">現実の鍵指紋が想定の1つと合致しませんでした!</string>
@@ -813,28 +918,40 @@
<string name="msg_mf_error_master_none">マスター認証が操作で見付かりませんでした(すべて破棄しましたか?)</string>
<string name="msg_mf_error_noexist_primary">問題のある主ユーザIDが指定された!</string>
<string name="msg_mf_error_noexist_revoke">破棄において問題のあるユーザIDが指定された!</string>
- <string name="msg_mf_error_restricted">パスフレーズのない厳密な捜査を実行してみてください!それはプロラミングエラーで、バグレポートでファイルの提出をお願いします!</string>
+ <string name="msg_mf_error_restricted">パスパスワードのない厳密な操作を実行してみてください!これはプロラミングエラーで、バグレポートでファイルの提出をお願いします!</string>
<string name="msg_mf_error_revoked_primary">主ユーザIDの破棄はできません!</string>
<string name="msg_mf_error_null_expiry">副鍵の生成時に期限を\"過去\"とすることはできません。これはプログラムエラーで、バグレポートでファイルの提出をお願いします!</string>
+ <string name="msg_mf_error_noop">なにもできません!</string>
<string name="msg_mf_error_passphrase_master">主鍵の復号で致命的な失敗! これはプログラムエラーの場合がありますので、バグレポートでファイルの提出をお願いします!</string>
<string name="msg_mf_error_pgp">PGP内部エラー!</string>
<string name="msg_mf_error_sig">署名例外!</string>
+ <string name="msg_mf_error_sub_stripped">ストリップした副鍵である %s は変更できません!</string>
+ <string name="msg_mf_error_subkey_missing">見付からない副鍵 %s の操作をしようとした!</string>
+ <string name="msg_mf_error_conflicting_nfc_commands">カード上で鍵の署名を作るのと同じ操作でスマートカードに移動できません</string>
+ <string name="msg_mf_error_duplicate_keytocard_for_slot">スマートカードでは鍵の種別ごとに1つのスロットのみサポートします。</string>
+ <string name="msg_mf_error_invalid_flags_for_keytocard">スマートカードの鍵に不適合な鍵のフラグです。</string>
<string name="msg_mf_master">マスター認証を変更</string>
<string name="msg_mf_notation_empty">空のノーテーションパケットを追加</string>
<string name="msg_mf_notation_pin">PINノーテーションパケットを追加</string>
- <string name="msg_mf_passphrase">鍵輪のパスフレーズの変更中</string>
- <string name="msg_mf_passphrase_key">副鍵 %s を新しいパスフレーズで再暗号化</string>
- <string name="msg_mf_passphrase_empty_retry">新しいパスフレーズの設定に失敗しました、空の古いパスフレーズで再度試してください</string>
- <string name="msg_mf_passphrase_fail">副鍵のパスフレーズは変更されていません! (他の鍵とは異なるになっていませんか?)</string>
+ <string name="msg_mf_passphrase">鍵輪のパスワードを変更中</string>
+ <string name="msg_mf_pin">カードのPINを変更</string>
+ <string name="msg_mf_admin_pin">カードの管理者PINを変更</string>
+ <string name="msg_mf_passphrase_key">副鍵 %s を新しいパスワードで再暗号化</string>
+ <string name="msg_mf_passphrase_empty_retry">新しいパスワードの設定に失敗しました、空の古いパスフレーズで再度試してください</string>
+ <string name="msg_mf_passphrase_fail">副鍵のパスワードは変更されていません! (他の鍵とは異なっていませんか?)</string>
<string name="msg_mf_primary_replace_old">以前の主ユーザIDで証明を入れ替え中</string>
<string name="msg_mf_primary_new">新しい主ユーザIDで新しい証明を生成中</string>
+ <string name="msg_mf_restricted_mode">制限操作モードへ変更</string>
<string name="msg_mf_subkey_change">副鍵 %s を変更中</string>
- <string name="msg_mf_error_subkey_missing">見付からない副鍵 %s の操作をしようとした!</string>
+ <string name="msg_mf_require_divert">スマートカードでの暗号化操作に切り替え</string>
+ <string name="msg_mf_require_passphrase">操作にパスワードが必要です</string>
<string name="msg_mf_subkey_new">種類%sの新しい副鍵を追加</string>
<string name="msg_mf_subkey_new_id">新しい副鍵 ID: %s</string>
<string name="msg_mf_error_past_expiry">期限切れ日を過去にはできません!</string>
<string name="msg_mf_subkey_revoke">副鍵 %s を破棄中</string>
<string name="msg_mf_subkey_strip">副鍵 %s のストリップ中</string>
+ <string name="msg_mf_keytocard_start">副鍵 %s をスマートカードへ移動</string>
+ <string name="msg_mf_keytocard_finish">%1$s をスマートカード %2$s へ移動した</string>
<string name="msg_mf_success">鍵輪の変更に成功</string>
<string name="msg_mf_uid_add">ユーザID %s を追加中</string>
<string name="msg_mf_uid_primary">主UIDを %s に変更中</string>
@@ -877,19 +994,20 @@
<string name="msg_con_warn_delete_secret">秘密鍵のキャッシュファイルを削除中に例外発生</string>
<!--Edit Key (higher level than modify)-->
<string name="msg_ed">キー操作の実行</string>
- <string name="msg_ed_caching_new">新しいパスフレーズをキャッシュ</string>
+ <string name="msg_ed_caching_new">新しいパスワードをキャッシュ</string>
<string name="msg_ed_error_no_parcel">SaveKeyringParcel欠落!(これはバグです、レポートしてください)</string>
<string name="msg_ed_error_key_not_found">鍵が見当りません!</string>
<string name="msg_ed_fetching">フェッチした鍵を変更 (%s)</string>
<string name="msg_ed_success">鍵の操作に成功</string>
<!--Promote key-->
<string name="msg_pr">公開鍵が秘密鍵に昇格しました</string>
- <string name="msg_pr_error_already_secret">鍵はすでに秘密鍵となっています!</string>
+ <string name="msg_pr_all">副鍵すべてを昇格</string>
<string name="msg_pr_error_key_not_found">鍵が見当りません!</string>
<string name="msg_pr_fetching">フェッチした鍵を変更 (%s)</string>
+ <string name="msg_pr_subkey_match">副鍵を昇格: %s</string>
+ <string name="msg_pr_subkey_nomatch">YubiKeyに副鍵がありません: %s</string>
<string name="msg_pr_success">鍵は正常に昇格しました</string>
<!--Other messages used in OperationLogs-->
- <string name="msg_ek_error_divert">NFCの鍵の編集は(まだ)サポートされていません!</string>
<string name="msg_ek_error_dummy">ストリップした主鍵では鍵輪を編集できません!</string>
<string name="msg_ek_error_not_found">鍵が見当りません!</string>
<!--Messages for DecryptVerify operation-->
@@ -905,26 +1023,25 @@
<string name="msg_dc_clear_meta_size_unknown">ファイルサイズが不明</string>
<string name="msg_dc_clear_meta_time">更新日時: %s</string>
<string name="msg_dc_clear_signature_bad">署名の確認がOKではありません!</string>
- <string name="msg_dc_insecure_hash_algo">サポート外かつセキュアでない可能性があるハッシュアルゴリズム!</string>
<string name="msg_dc_clear_signature_check">署名データの検証中</string>
<string name="msg_dc_clear_signature_ok">署名の確認はOKです</string>
<string name="msg_dc_clear_signature">後程署名データを保存します</string>
<string name="msg_dc_clear">平文データの処理中</string>
- <string name="msg_dc_error_bad_passphrase">鍵のロック解除エラー、パスフレーズに問題があります!</string>
+ <string name="msg_dc_error_bad_passphrase">鍵のロック解除エラー、パスワードに問題があります!</string>
+ <string name="msg_dc_error_corrupt_data">データが破損しています!</string>
<string name="msg_dc_error_extract_key">鍵のロック解除で不明なエラー!</string>
<string name="msg_dc_error_integrity_check">完全性チェックエラー!</string>
- <string name="msg_dc_insecure_mdc_missing">完全聖チェックの欠落!これは暗号化アプリケーションが期限切れになった場合、もしくは暗号強度低下攻撃がある場合に発生します。</string>
- <string name="msg_dc_error_invalid_data">正常な署名データが見付からなかった!</string>
- <string name="msg_dc_error_io">操作中にIO例外に当たりました!</string>
+ <string name="msg_dc_error_invalid_data">正常ではないOpenPGPの暗号化か署名のデーータを検出しました!</string>
+ <string name="msg_dc_error_input">入力データストリームのオープンエラー!</string>
<string name="msg_dc_error_no_data">ストリーム中に暗号化されたデータが見付からなかった!</string>
<string name="msg_dc_error_no_key">ストリーム中に既知の秘密鍵で暗号化されたデータが見付からなかった!</string>
<string name="msg_dc_error_pgp_exception">操作中にPGP例外に当たりました!</string>
<string name="msg_dc_integrity_check_ok">完全性チェックOK!</string>
<string name="msg_dc_ok_meta_only">メタデータだけが要求され、暗号化をスキップしました</string>
<string name="msg_dc_ok">復号化/検証完了</string>
- <string name="msg_dc_pass_cached">キャッシュからパスフレーズを利用します。</string>
+ <string name="msg_dc_pass_cached">キャッシュからパスワードを利用します。</string>
<string name="msg_dc_pending_nfc">NFCトークンが必要、ユーザー入力を要求中...</string>
- <string name="msg_dc_pending_passphrase">パスフレーズが必要、ユーザー入力を要求中...</string>
+ <string name="msg_dc_pending_passphrase">パスワードが必要、ユーザー入力を要求中...</string>
<string name="msg_dc_prep_streams">暗号化のストリームの検証</string>
<string name="msg_dc">復号化操作を開始します...</string>
<string name="msg_dc_sym_skip">受け入れできない対称暗号データです、スキップします...</string>
@@ -933,7 +1050,6 @@
<string name="msg_dc_trail_sym">追跡で遭遇、対称暗号化されたデータ</string>
<string name="msg_dc_trail_unknown">追跡で未知のタイプのデータに遭遇</string>
<string name="msg_dc_unlocking">秘密鍵のロック解除</string>
- <string name="msg_dc_insecure_symmetric_encryption_algo">セキュアでない可能性がある暗号化アルゴリズムが利用されています!</string>
<!--Messages for VerifySignedLiteralData operation-->
<string name="msg_vl">署名の確認開始</string>
<string name="msg_vl_error_no_siglist">署名済み固定データに署名リストがありません</string>
@@ -954,20 +1070,18 @@
<string name="msg_se_error_input_uri_not_found">読み出すためにURIを開く時にエラー!</string>
<string name="msg_se_error_output_uri_not_found">書き込むためにURIを開く時にエラー!</string>
<string name="msg_se_error_too_many_inputs">不明な出力以上の入力過多です! これはプログラミングのエラーで、バグレポートの提出をお願いします!</string>
- <string name="msg_se_warn_output_left">得られた出力が入力から乖離している。これはプログラミングのエラーで、バグレポートの提出をお願いします!</string>
<string name="msg_se_success">署名/暗号化操作に成功!</string>
<!--Messages for PgpSignEncrypt operation-->
<string name="msg_pse_asymmetric">暗号化のための公開鍵の準備</string>
<string name="msg_pse_clearsign_only">クリアテキスト署名の入力はサポートされていません!</string>
<string name="msg_pse_compressing">圧縮の準備</string>
<string name="msg_pse_encrypting">データ暗号化</string>
- <string name="msg_pse_error_bad_passphrase">駄目なパスフレーズ!</string>
- <string name="msg_pse_error_hash_algo">この鍵ではサポートされていないハッシュアルゴリズムを要求されています!</string>
+ <string name="msg_pse_error_bad_passphrase">駄目なパスワード!</string>
<string name="msg_pse_error_io">操作中にIO例外に当たりました!</string>
<string name="msg_pse_error_key_sign">選択した署名鍵で署名データを作れません!</string>
<string name="msg_pse_error_sign_key">署名鍵の取得エラー!</string>
<string name="msg_pse_error_nfc">NFC データエラー!</string>
- <string name="msg_pse_error_no_passphrase">パスフレーズが提供されてない!</string>
+ <string name="msg_pse_error_no_passphrase">パスワードが提供されてない!</string>
<string name="msg_pse_error_pgp">OpenPGP内部エラー!</string>
<string name="msg_pse_error_sig">OpenPGP署名例外に当たりました!</string>
<string name="msg_pse_error_unlock">鍵のロック解除で不明なエラー!</string>
@@ -976,7 +1090,7 @@
<string name="msg_pse_key_warn">暗号化に問題のある鍵: %s</string>
<string name="msg_pse_ok">署名/暗号化操作に成功!</string>
<string name="msg_pse_pending_nfc">NFCトークンが必要、ユーザー入力を要求中...</string>
- <string name="msg_pse_pending_passphrase">パスフレーズが必要、ユーザー入力を要求中...</string>
+ <string name="msg_pse_pending_passphrase">パスワードが必要、ユーザー入力を要求中...</string>
<string name="msg_pse_signing">署名データ(暗号化なし)</string>
<string name="msg_pse_signing_cleartext">クリアテキスト署名作成中</string>
<string name="msg_pse_signing_detached">分離署名作成中</string>
@@ -984,13 +1098,19 @@
<string name="msg_pse">署名/暗号化操作を開始します</string>
<string name="msg_pse_symmetric">対称暗号の準備</string>
<string name="msg_crt_certifying">検証の生成中</string>
+ <plurals name="msg_crt_certify_uids">
+ <item quantity="other">%1$d のユーザIDで鍵 %2$s の検証中</item>
+ </plurals>
+ <plurals name="msg_crt_certify_uats">
+ <item quantity="other">%1$d のユーザ属性で鍵 %2$s の検証中</item>
+ </plurals>
<string name="msg_crt_error_self">自己証明書的な発行は行えません!</string>
<string name="msg_crt_error_master_not_found">主鍵が見当りません!</string>
<string name="msg_crt_error_nothing">検証できた鍵がない!</string>
<string name="msg_crt_error_unlock">主鍵のロック解除エラー!</string>
- <string name="msg_crt_error_divert">NFCでの検証は(まだ)サポートしていません!</string>
<string name="msg_crt">鍵輪の検証</string>
<string name="msg_crt_master_fetch">検証中の主鍵のフェッチ</string>
+ <string name="msg_crt_nfc_return">NFCの画面に復帰</string>
<string name="msg_crt_save">検証した鍵の保存中 %s</string>
<string name="msg_crt_saving">鍵輪の保存中</string>
<string name="msg_crt_unlock">主鍵のロック解除</string>
@@ -998,6 +1118,7 @@
<string name="msg_crt_warn_not_found">鍵が見当りません!</string>
<string name="msg_crt_warn_cert_failed">証明の生成が失敗!</string>
<string name="msg_crt_warn_save_failed">保存操作が失敗!</string>
+ <string name="msg_crt_warn_upload_failed">アップロード操作に失敗!</string>
<string name="msg_crt_upload_success">鍵をサーバにアップロードしました</string>
<plurals name="msg_import">
<item quantity="other">%d 個の鍵のインポート</item>
@@ -1005,13 +1126,14 @@
<string name="msg_import_fetch_error_decode">鍵輪のデコードエラー</string>
<string name="msg_import_fetch_error">鍵の展開ができません! (ネットワークの問題?)</string>
<string name="msg_import_fetch_keybase">keybase.ioから回収: %s</string>
- <string name="msg_import_fetch_keyserver_error">keybaseからの鍵の展開ができません!</string>
+ <string name="msg_import_fetch_error_keyserver">鍵サーバからの展開: %s</string>
<string name="msg_import_fetch_keyserver">鍵サーバからの回収: %s</string>
<string name="msg_import_fetch_keyserver_ok">鍵の展開に成功</string>
<string name="msg_import_keyserver">鍵サーバ %s を使う</string>
<string name="msg_import_fingerprint_error">フェッチした鍵の鍵指紋が完全には一致しませんでした!</string>
<string name="msg_import_fingerprint_ok">指紋チェックOK!</string>
<string name="msg_import_merge">展開したデータをマージ</string>
+ <string name="msg_import_merge_error">展開したデータのマージでエラー!</string>
<string name="msg_import_error">インポート操作に失敗!</string>
<string name="msg_import_error_io">I/Oエラーによりインポート操作が失敗しました!</string>
<string name="msg_import_partial">インポート操作に成功、ただしエラーあり!</string>
@@ -1031,6 +1153,7 @@
<string name="msg_export_error_io">入出力エラー!</string>
<string name="msg_export_error_key">鍵データの事前処理のエラー!</string>
<string name="msg_export_success">エクスポート操作に成功!</string>
+ <string name="msg_export_upload_success">鍵サーバへアップロードに成功</string>
<string name="msg_del_error_empty">削除するものがありません!</string>
<string name="msg_del_error_multi_secret">秘密鍵は個別にしか削除できません!</string>
<plurals name="msg_del">
@@ -1045,6 +1168,11 @@
<plurals name="msg_del_fail">
<item quantity="other">%d 個の鍵の削除に失敗</item>
</plurals>
+ <string name="msg_revoke_error_empty">破棄するものがありません!</string>
+ <string name="msg_revoke_error_not_found">破棄する鍵が見付かりません!</string>
+ <string name="msg_revoke_key">鍵 %s を破棄中</string>
+ <string name="msg_revoke_key_fail">鍵の破棄に失敗しました</string>
+ <string name="msg_revoke_ok">鍵の破棄に成功しました</string>
<string name="msg_acc_saved">アカウント保存</string>
<string name="msg_download_success">ダウンロードに成功しました!</string>
<string name="msg_download_no_valid_keys">ファイル/クリップボードにて正しい鍵が見付かりません!</string>
@@ -1056,6 +1184,13 @@
<string name="msg_download_too_many_responses">鍵検索のクエリが沢山の候補を返しました。クエリを精密化してください!</string>
<string name="msg_download_query_too_short_or_too_many_responses">鍵がまったく無いか、多すぎる鍵が見付かりました。クエリを改善してください!</string>
<string name="msg_download_query_failed">鍵の検索時にエラーが発生しました。</string>
+ <!--Messages for Keybase Verification operation-->
+ <string name="msg_keybase_error_no_prover">%s で検証チェッカを見付けることができませんでした</string>
+ <string name="msg_keybase_error_fetching_evidence">検証の取得で問題がある</string>
+ <string name="msg_keybase_error_key_mismatch">鍵の指紋が証明ポストと一致しませんでした</string>
+ <string name="msg_keybase_error_dns_fail">DNS TXT レコードの検索が失敗</string>
+ <string name="msg_keybase_error_specific">%s</string>
+ <string name="msg_keybase_error_msg_payload_mismatch">復号化した検証ポストが指定した値と一致しない</string>
<!--Messages for Export Log operation-->
<string name="msg_export_log_start">ログのエクスポート</string>
<string name="msg_export_log_error_fopen">ファイルオープン中のエラー</string>
@@ -1063,17 +1198,24 @@
<string name="msg_export_log_error_writing">ファイルへの書き込みでI/Oエラー!</string>
<string name="msg_export_log_success">ログのエクスポートに成功しました!</string>
<!--PassphraseCache-->
- <string name="passp_cache_notif_click_to_clear">クリックしてパスフレーズのキャッシュをクリア</string>
- <string name="passp_cache_notif_n_keys">OpenKeychainは %d のパスフレーズをキャッシュしています</string>
- <string name="passp_cache_notif_keys">パスフレーズのキャッシュ:</string>
- <string name="passp_cache_notif_clear">キャッシュクリア</string>
- <string name="passp_cache_notif_pwd">パスフレーズ</string>
+ <string name="passp_cache_notif_click_to_clear">タッチしてパスワードをクリア。</string>
+ <plurals name="passp_cache_notif_n_keys">
+ <item quantity="other">%d のパスワードを忘れない</item>
+ </plurals>
+ <string name="passp_cache_notif_keys">パスワードを忘れない</string>
+ <string name="passp_cache_notif_clear">パスワードのクリア</string>
+ <string name="passp_cache_notif_pwd">パスワード</string>
+ <!--Keyserver sync-->
<!--First Time-->
<string name="first_time_text1">OpenKeychainであなたのプライバシーを取り戻しましょう!</string>
<string name="first_time_create_key">自分のキーを作る</string>
<string name="first_time_import_key">ファイルから鍵をインポート</string>
<string name="first_time_yubikey">YubiKey NEOを使用する</string>
<string name="first_time_skip">セットアップをスキップ</string>
+ <string name="first_time_blank_yubikey_yes">YubiKeyを使用する</string>
+ <string name="backup_all">すべての鍵とあなた所有の鍵</string>
+ <string name="backup_public_keys">すべての鍵</string>
+ <string name="backup_section">バックアップ</string>
<!--unsorted-->
<string name="section_certifier_id">検証者</string>
<string name="section_cert">証明の詳細</string>
@@ -1082,6 +1224,7 @@
<string name="empty_certs">この鍵に証明がない</string>
<string name="certs_text">あなたの検証された自己証明とあなたの鍵で生成された証明がここに表示されます</string>
<string name="section_uids_to_certify">ユーザID</string>
+ <string name="certify_text">インポートした鍵には\"アイデンティティ\": 名前とメールアドレス を含みます。正確に期待したものと一致しているか認定されているものを選択します。</string>
<string name="certify_fingerprint_text">表示している指紋を、文字対文字で、あなたのパートナーの表示しているものと比較</string>
<string name="certify_fingerprint_text2">表示している指紋は一致しましたか?</string>
<string name="label_revocation">破棄の理由</string>
@@ -1089,41 +1232,42 @@
<string name="error_key_not_found">鍵が見当りません!</string>
<string name="error_key_processing">鍵処理中のエラー!</string>
<string name="key_stripped">スリム化</string>
- <string name="key_divert">カード/NFCへ迂回</string>
- <string name="key_no_passphrase">パスフレーズなし</string>
+ <string name="key_divert">スマートカードへ迂回</string>
+ <string name="key_no_passphrase">パスワードなし</string>
<string name="key_unavailable">存在しない</string>
<string name="secret_cannot_multiple">あなたが所有者の鍵は個別にしか削除できません!</string>
<string name="title_view_cert">証明の詳細を見る</string>
<string name="unknown_algorithm">不明</string>
<string name="can_sign_not">署名不可</string>
<string name="error_no_encrypt_subkey">暗号化の副鍵がありません!</string>
- <string name="account_no_manual_account_creation">OpenKeychainのアカウントを手動では生成できません.
-より詳細は、ヘルプを参照のこと。</string>
<string name="contact_show_key">鍵 (%s) を表示</string>
<string name="swipe_to_update">下スワイプでキーサーバから更新します</string>
<string name="error_no_file_selected">暗号化するファイルを少なくとも1つ選択して下さい。</string>
- <string name="error_multi_files">複数ファイルの保存はサポートされていません。これは現在のAndroidでの制限です。</string>
+ <string name="error_detached_signature">バイナリファイルの署名のみの操作はサポートされません、最低1つは暗号化鍵を選択してください。</string>
+ <string name="error_empty_text">テキストの入力を暗号化!</string>
<string name="key_colon">鍵:</string>
<string name="exchange_description">鍵交換の開始は、右側の参加者の番号を選択し、その後、\"交換開始\"ボタンを推します。\n\n2つ以上の質問で交換にいる右の参加者とその指紋が正しいかを確認してください。</string>
<string name="btn_start_exchange">交換開始</string>
<string name="user_id_none"><![CDATA[<none>]]></string>
+ <!--Android Account-->
+ <string name="account_privacy_title">プライバシー</string>
<!--Passphrase wizard-->
<!--TODO: rename all the things!-->
<string name="title_unlock_method">アンロックする手段を選択してください</string>
- <!--<string name="enter_passphrase_twice">Enter passphrase twice</string>-->
- <string name="enter_passphrase">パスフレーズの入力</string>
- <string name="passphrase">パスフレーズ</string>
- <string name="noPassphrase">パスフレーズなし</string>
- <string name="no_passphrase_set">パスフレーズが設定されてない</string>
- <string name="passphrases_match">パスフレーズが一致しない</string>
- <string name="passphrase_saved">パスフレーズを保存</string>
- <string name="passphrase_invalid">無効なパスフレーズ</string>
- <string name="missing_passphrase">パスフレーズがありません</string>
+ <!--<string name="enter_passphrase_twice">Enter password twice</string>-->
+ <string name="enter_passphrase">パスワードの入力</string>
+ <string name="passphrase">パスワード</string>
+ <string name="noPassphrase">パスワードなし</string>
+ <string name="no_passphrase_set">パスワードなしに設定</string>
+ <string name="passphrases_match">パスワードが一致</string>
+ <string name="passphrase_saved">パスワードを保存</string>
+ <string name="passphrase_invalid">無効なパスワード</string>
+ <string name="missing_passphrase">パスワードがありません</string>
<string name="passphrase_again">もう一度</string>
<string name="lockpattern">ロックパターン</string>
<string name="lockpatternNFC">NFCとロックパターン</string>
<string name="unlock_method">アンロック手段</string>
- <string name="set_passphrase">パスフレーズの設定</string>
+ <string name="set_passphrase">パスワードを設定</string>
<string name="draw_lockpattern">ロックパターンを描いてください</string>
<string name="nfc_title">NFC</string>
<!--<string name="nfc_text">Please place a NFC tag near your device</string>-->
@@ -1133,4 +1277,48 @@
<string name="nfc_write_succesful">NFCタグに書けました!</string>
<string name="unlocked">アンロック</string>
<string name="nfc_settings">設定</string>
+ <string name="snack_yubikey_view">閲覧</string>
+ <string name="snack_yubikey_import">インポート</string>
+ <string name="button_bind_key">鍵と紐付け</string>
+ <string name="yubikey_serno">シリアルナンバー: %s</string>
+ <string name="yubikey_key_holder">鍵ホルダ:</string>
+ <string name="yubikey_key_holder_not_set">鍵ホルダ: &lt;未設定&gt;</string>
+ <string name="yubikey_status_bound">鍵がYubiKeyがマッチし紐付いている</string>
+ <string name="yubikey_status_unbound">YubiKeyがマッチ、鍵に紐付けることができる</string>
+ <string name="yubikey_status_partly">YubiKeyがマッチ、鍵に部分的に紐付いている</string>
+ <string name="yubikey_create">あなたのデバイスの背面にYubiKeyを固定してください。</string>
+ <string name="btn_import">インポート</string>
+ <string name="snack_yubi_other">違う鍵がYubiKeyに格納されています!</string>
+ <string name="error_nfc">NFCエラー: %s</string>
+ <string name="error_nfc_terminated">YubiKeyが完了状態</string>
+ <string name="error_nfc_data_not_found">鍵もしくはオブジェクトが見当りません。</string>
+ <string name="error_nfc_unknown">不明なエラー</string>
+ <string name="error_nfc_bad_data">YubiKeyが不正なデータを報告した。</string>
+ <string name="error_nfc_header">YubiKeyが不正な%sバイトを報告。</string>
+ <string name="error_nfc_try_again">再実行</string>
+ <string name="error_pin_nodefault">デフォルトのPINは棄却されました!</string>
+ <string name="error_temp_file">一時ファイルの生成でエラーしました。</string>
+ <string name="btn_delete_original">オリジナルのファイルを削除します</string>
+ <string name="snack_encrypt_filenames_on">ファイル名を暗号化<b>した</b>。</string>
+ <string name="snack_encrypt_filenames_off">ファイル名を暗号化<b>していません</b>。</string>
+ <string name="snack_armor_on">エンコードしたものをテキストとして出力。</string>
+ <string name="snack_armor_off">エンコードしたものをバイナリとして出力。</string>
+ <string name="snack_compression_on">圧縮を<b>有効化</b>。</string>
+ <string name="snack_compression_off">圧縮を<b>無効化</b>。</string>
+ <string name="error_loading_keys">鍵の読み込みエラー!</string>
+ <string name="error_empty_log">(エラー、空のログ)</string>
+ <string name="error_reading_text">復号化のための入力が読めない!</string>
+ <string name="intent_show">署名/暗号化した内容を表示</string>
+ <string name="view_internal">OpenKeychainで閲覧</string>
+ <string name="error_preparing_data">データの処理でエラー!</string>
+ <string name="label_clip_title">暗号化データ</string>
+ <string name="progress_processing">処理中...</string>
+ <string name="error_saving_file">ファイルの保存でエラー!</string>
+ <string name="file_saved">ファイルを保存した!</string>
+ <string name="file_delete_ok">元のファイルを削除。</string>
+ <string name="error_clipboard_empty">クリップボードが空です!</string>
+ <string name="error_clipboard_copy">クリップボードへのデータコピーでエラー!</string>
+ <string name="error_scan_fp">指紋の読み取りエラー!</string>
+ <string name="error_scan_match">指紋が一致しません!</string>
+ <string name="error_expiry_past">期限切れ日が過去です!</string>
</resources>
diff --git a/OpenKeychain/src/main/res/values-kn/strings.xml b/OpenKeychain/src/main/res/values-kn/strings.xml
deleted file mode 100644
index 0713e39ad..000000000
--- a/OpenKeychain/src/main/res/values-kn/strings.xml
+++ /dev/null
@@ -1,78 +0,0 @@
-<?xml version='1.0' encoding='UTF-8'?>
-<resources>
- <!--GENERAL: Please put all strings inside quotes as described in example 1 on
- http://developer.android.com/guide/topics/resources/string-resource.html (scroll down to "Escaping apostrophes and quotes").-->
- <!--title-->
- <!--section-->
- <!--button-->
- <!--menu-->
- <!--label-->
- <!--Proxy Preferences-->
- <!--proxy type choices and values-->
- <!--OrbotHelper strings-->
- <!--InstallDialogFragment strings-->
- <!--StartOrbotDialogFragment strings-->
- <!--choice-->
- <!--key flags-->
- <!--sentences-->
- <!--errors
- no punctuation, all lowercase,
- they will be put after "error_message", e.g. "Error: file not found"-->
- <!--errors without preceeding Error:-->
- <!--results shown after decryption/verification-->
- <!--Add keys-->
- <!--progress dialogs, usually ending in '…'-->
- <!--action strings-->
- <!--key bit length selections-->
- <!--elliptic curve names-->
- <!--not in for now, see SaveKeyringParcel
- <string name="key_curve_bp_p256">"Brainpool P-256"</string>
- <string name="key_curve_bp_p384">"Brainpool P-384"</string>
- <string name="key_curve_bp_p512">"Brainpool P-512"</string>-->
- <!--compression-->
- <!--Help-->
- <!--Import-->
- <!--Import from URL-->
- <!--Generic result toast-->
- <!--Import result toast-->
- <!--Delete result toast-->
- <!--Certify result toast-->
- <!--Intent labels-->
- <!--Remote API-->
- <!--Share-->
- <!--Key list-->
- <!--Key view-->
- <!--Key trust-->
- <!--keybase proof stuff-->
- <!--Edit key-->
- <!--Create key-->
- <!--View key-->
- <!--Add/Edit keyserver-->
- <!--Navigation Drawer-->
- <!--hints-->
- <!--certs-->
- <!--LogType log messages. Errors should have _ERROR_ in their name and end with a !-->
- <!--Import Public log entries-->
- <!--Import Secret log entries-->
- <!--Keyring Canonicalization log entries-->
- <!--Keyring merging log entries-->
- <!--createSecretKeyRing-->
- <!--modifySecretKeyRing-->
- <!--Consolidate-->
- <!--Edit Key (higher level than modify)-->
- <!--Promote key-->
- <!--Other messages used in OperationLogs-->
- <!--Messages for DecryptVerify operation-->
- <!--Messages for VerifySignedLiteralData operation-->
- <!--Messages for SignEncrypt operation-->
- <!--Messages for PgpSignEncrypt operation-->
- <!--Messages for Keybase Verification operation-->
- <!--Messages for Export Log operation-->
- <!--PassphraseCache-->
- <!--First Time-->
- <!--unsorted-->
- <!--Passphrase wizard-->
- <!--TODO: rename all the things!-->
- <!--<string name="enter_passphrase_twice">Enter password twice</string>-->
- <!--<string name="nfc_text">Please place a NFC tag near your device</string>-->
-</resources>
diff --git a/OpenKeychain/src/main/res/values-nl/strings.xml b/OpenKeychain/src/main/res/values-nl/strings.xml
index 15c3f12d2..1a02fdc07 100644
--- a/OpenKeychain/src/main/res/values-nl/strings.xml
+++ b/OpenKeychain/src/main/res/values-nl/strings.xml
@@ -20,8 +20,6 @@
<string name="title_encrypt_to_file">Versleutelen naar bestand</string>
<string name="title_decrypt_to_file">Ontsleutelen naar bestand</string>
<string name="title_import_keys">Sleutels importeren</string>
- <string name="title_export_key">Sleutels exporteren</string>
- <string name="title_export_keys">Sleutels exporteren</string>
<string name="title_key_not_found">Sleutel niet gevonden</string>
<string name="title_send_key">Upload naar sleutelserver</string>
<string name="title_certify_key">Sleutel bevestigen</string>
@@ -44,6 +42,7 @@
<string name="section_cloud_search">Cloud zoeken</string>
<string name="section_passphrase_cache">Verwerken van wachtwoorden/PINs</string>
<string name="section_proxy_settings">Proxy-instellingen</string>
+ <string name="section_gui">Interface</string>
<string name="section_certify">Bevestigen</string>
<string name="section_actions">Acties</string>
<string name="section_share_key">Sleutel</string>
@@ -88,7 +87,6 @@
<!--menu-->
<string name="menu_preferences">Instellingen</string>
<string name="menu_help">Help</string>
- <string name="menu_export_key">Exporteren naar bestand</string>
<string name="menu_delete_key">Sleutel verwijderen</string>
<string name="menu_manage_keys">Beheer mijn sleutels</string>
<string name="menu_search">Zoeken</string>
@@ -120,6 +118,7 @@
<string name="label_use_default_yubikey_pin">Gebruik standaard YubiKey PIN</string>
<string name="label_use_num_keypad_for_yubikey_pin">Gebruik numeriek toetsenbord voor YubiKey PIN</string>
<string name="label_label_use_default_yubikey_pin_summary">Gebruikt standaard PIN (123456) om YubiKeys over NFC te bereiken</string>
+ <string name="label_asymmetric_from">Ondertekenen met:</string>
<string name="label_to">Versleutelen naar:</string>
<string name="label_delete_after_encryption">Verwijder bestanden na versleuteling</string>
<string name="label_delete_after_decryption">Verwijderen na ontsleuteling</string>
@@ -155,10 +154,12 @@
<string name="label_verify_keyserver">Sleutelserver verifiëren</string>
<string name="label_enter_keyserver_url">Voer sleutelserver-URL in</string>
<string name="label_keyserver_dialog_delete">Sleutelserver verwijderen</string>
+ <string name="label_theme">Thema</string>
<string name="pref_keyserver">OpenPGP-sleutelservers</string>
<string name="pref_keyserver_summary">Zoek sleutels op geselecteerde OpenPGP-sleutelservers (HKP-protocol)</string>
<string name="pref_keybase">keybase.io</string>
<string name="pref_keybase_summary">Zoek sleutels op keybase.io</string>
+ <!--label shown in Android settings under the OpenKeychain account-->
<!--Proxy Preferences-->
<string name="pref_proxy_tor_title">Tor aanzetten</string>
<string name="pref_proxy_tor_summary">Vereist dat Orbot geïnstalleerd is</string>
@@ -171,8 +172,6 @@
<!--proxy type choices and values-->
<string name="pref_proxy_type_choice_http">HTTP</string>
<string name="pref_proxy_type_choice_socks">SOCKS</string>
- <string name="pref_proxy_type_value_http">proxyHttp</string>
- <string name="pref_proxy_type_value_socks">proxySocks</string>
<!--OrbotHelper strings-->
<string name="orbot_ignore_tor">Gebruik Tor niet</string>
<!--InstallDialogFragment strings-->
@@ -237,6 +236,8 @@
<string name="yubikey_pin_for">Voer PIN in om toegang te verkrijgen tot YubiKey voor \'%s\'</string>
<string name="nfc_text">Hou de YubiKey tegen de NFC-aanduiding aan de achterkant van je toestel.</string>
<string name="nfc_wait">Hou de YubiKey tegen de achterkant!</string>
+ <string name="nfc_finished">Neem de YubiKey nu weg.</string>
+ <string name="nfc_try_again_text">Neem de YubiKey nu weg en druk op Opnieuw proberen.</string>
<string name="file_delete_confirmation_title">Oorspronkelijke bestanden verwijderen?</string>
<string name="file_delete_confirmation">De volgende bestanden zullen worden verwijderd:%s</string>
<string name="file_delete_successful">%1$d van %2$d bestanden zijn verwijderd.%3$s</string>
@@ -247,7 +248,6 @@
<string name="error_no_encryption_or_signature_key">Kies ten minste één versleutelingssleutel of een ondertekeningssleutel.</string>
<string name="specify_file_to_encrypt_to">Gelieve aan te geven naar welk bestand versleuteld moet worden.\nWAARSCHUWING: Als het bestand al bestaat, zal het overschreven worden!</string>
<string name="specify_file_to_decrypt_to">Gelieve aan te geven naar welk bestand ontsleuteld moet worden.\nWAARSCHUWING: Als het bestand al bestaat, zal het overschreven worden!</string>
- <string name="specify_backup_dest">Gelieve aan te geven naar welk bestand geëxporteerd moet worden.\nWAARSCHUWING: Als het bestand al bestaat, zal het overschreven worden!</string>
<string name="key_deletion_confirmation_multi">Ben je zeker dat je alle geselecteerde sleutels wil verwijderen?</string>
<string name="secret_key_deletion_confirmation">Na verwijderen zal je niet langer berichten versleuteld met deze sleutel kunnen lezen, en alle sleutelbevestigingen die ermee gedaan zijn verliezen!</string>
<string name="public_key_deletetion_confirmation">Sleutel \'%s\' verwijderen?</string>
@@ -464,6 +464,7 @@
</plurals>
<string name="delete_nothing">Niets te verwijderen.</string>
<string name="delete_cancelled">Verwijderen geannuleerd.</string>
+ <!--Revoke result toast (snackbar)-->
<!--Certify result toast-->
<plurals name="certify_keys_ok">
<item quantity="one">Sleutel%2$s succesvol gecertificeerd.</item>
@@ -497,7 +498,7 @@
<string name="api_settings_start">Start applicatie</string>
<string name="api_settings_delete_account">Verwijder account</string>
<string name="api_settings_package_name">Pakketnaam</string>
- <string name="api_settings_package_certificate">SHA-256 van Pakkethandtekening</string>
+ <string name="api_settings_package_certificate">SHA-256 van Pakketcertificaat</string>
<string name="api_settings_accounts">Accounts (oude API)</string>
<string name="api_settings_advanced">Uitgebreide informatie</string>
<string name="api_settings_allowed_keys">Toegestane sleutels</string>
@@ -510,8 +511,8 @@
<string name="api_register_allow">Toegang toestaan</string>
<string name="api_register_disallow">Toegang weigeren</string>
<string name="api_register_error_select_key">Selecteert u a.u.b. een sleutel</string>
- <string name="api_select_pub_keys_missing_text">Geen sleutels gevonden voor deze identiteiten:</string>
- <string name="api_select_pub_keys_dublicates_text">Meer dan een sleutel bestaat voor deze identiteiten:</string>
+ <string name="api_select_pub_keys_missing_text">Geen sleutels gevonden voor deze e-mailadressen:</string>
+ <string name="api_select_pub_keys_dublicates_text">Er bestaat meer dan een sleutel voor deze e-mailadressen:</string>
<string name="api_select_pub_keys_text">Bekijkt u a.u.b. de ontvangers</string>
<string name="api_select_pub_keys_text_no_user_ids">Gelieve de ontvangers te selecteren!</string>
<string name="api_error_wrong_signature">Handtekening check mislukt! Hebt u deze app van een andere bron geïnstalleerd? Als u zeker weet dat dit geen aanval is, haal dan de registratie van deze app in OpenKeychain weg en registreer de app opnieuw.</string>
@@ -520,6 +521,9 @@
<!--Share-->
<string name="share_qr_code_dialog_title">Delen met QR-code</string>
<string name="share_nfc_dialog">Deel met NFC</string>
+ <!--retry upload dialog-->
+ <!--Delete or revoke private key dialog-->
+ <!--Delete Or Revoke Dialog spinner-->
<!--Key list-->
<plurals name="key_list_selected_keys">
<item quantity="one">1 sleutel geselecteerd.</item>
@@ -562,14 +566,6 @@
<string name="key_trust_results_prefix">Keybase.io geeft “bewijzen” die stellen dat de eigenaar van deze sleutel:</string>
<string name="key_trust_header_text">Let op: Keybase.io-bewijzen zijn een experimentele functie van OpenKeychain. We moedigen je aan QR-codes te scannen of sleutels uit te wisselen via NFC bovenop het bevestigen ervan.</string>
<!--keybase proof stuff-->
- <string name="keybase_narrative_twitter">Post op Twitter als</string>
- <string name="keybase_narrative_github">Bekend is op GitHub als</string>
- <string name="keybase_narrative_dns">De volgende domeinnamen beheert</string>
- <string name="keybase_narrative_web_site">Kan posten op de website(s)</string>
- <string name="keybase_narrative_reddit">Post op Reddit als</string>
- <string name="keybase_narrative_coinbase">Bekend is op Coinbase als</string>
- <string name="keybase_narrative_hackernews">Post op Hacker News als</string>
- <string name="keybase_narrative_unknown">Onbekend bewijstype</string>
<string name="keybase_proof_failure">Helaas kan dit bewijs niet geverifieerd worden.</string>
<string name="keybase_unknown_proof_failure">Niet-herkend probleem met de bewijschecker</string>
<string name="keybase_problem_fetching_evidence">Probleem met bewijs</string>
@@ -908,6 +904,7 @@
<string name="msg_mf_error_passphrase_master">Fatale fout bij ontsleutelen van hoofdsleutel. Dit is waarschijnlijk een bug, gelieve een verslag in te dienen!</string>
<string name="msg_mf_error_pgp">Interne OpenPGP-fout!</string>
<string name="msg_mf_error_sig">Ondertekeningsuitzondering!</string>
+ <string name="msg_mf_error_sub_stripped">Kan gestripte subsleutel %s niet wijzigen!</string>
<string name="msg_mf_error_subkey_missing">Geprobeerd om bewerking uit te voeren op ontbrekende subsleutel %s!</string>
<string name="msg_mf_error_conflicting_nfc_commands">Kan sleutel niet tegelijk verplaatsen naar smartcard en een on-card-ondertekening aanmaken.</string>
<string name="msg_mf_error_duplicate_keytocard_for_slot">Smartcard ondersteunt slechts een slot per sleuteltype</string>
@@ -1007,17 +1004,18 @@
<string name="msg_dc_clear_meta_size_unknown">Bestandsgrootte onbekend</string>
<string name="msg_dc_clear_meta_time">Wijzigingstijd: %s</string>
<string name="msg_dc_clear_signature_bad">Ondertekeningscontrole NIET OKÉ!</string>
- <string name="msg_dc_insecure_hash_algo">Niet ondersteund en mogelijk onveilig hash-algoritme!</string>
<string name="msg_dc_clear_signature_check">Bezig met verifiëren van ondertekeningsgegevens</string>
<string name="msg_dc_clear_signature_ok">Ondertekeningscontrole OKÉ</string>
<string name="msg_dc_clear_signature">Bezig met opslaan van ondertekeningsgegevens voor later</string>
<string name="msg_dc_clear">Bezig met verwerken van platte tekst-gegevens</string>
<string name="msg_dc_error_bad_passphrase">Fout bij ontgrendelen van sleutel, verkeerd wachtwoord!</string>
+ <string name="msg_dc_error_sym_passphrase">Fout bij ontsleutelen van gegevens! (Verkeerd wachtwoord?)</string>
<string name="msg_dc_error_corrupt_data">Gegevens zijn corrupt!</string>
<string name="msg_dc_error_extract_key">Onbekende fout bij ontgrendelen van sleutel!</string>
<string name="msg_dc_error_integrity_check">Fout bij integriteitscontrole!</string>
- <string name="msg_dc_insecure_mdc_missing">Integriteitscheck ontbreekt! Dit kan gebeuren omdat de versleutelingsapplicatie verouderd is, of door een downgrade-aanval.</string>
<string name="msg_dc_error_invalid_data">Geen geldige OpenPGP-versleutelde of ondertekende inhoud gevonden!</string>
+ <string name="msg_dc_error_io">Fout bij lezen van invoergegevens!</string>
+ <string name="msg_dc_error_input">Fout bij openen van invoergegevensstream!</string>
<string name="msg_dc_error_no_data">Geen versleutelde gegevens gevonden!</string>
<string name="msg_dc_error_no_key">Geen versleutelde gegevens met bekende geheime sleutel gevonden!</string>
<string name="msg_dc_error_pgp_exception">OpenPGP-uitzondering tegengekomen tijdens bewerking!</string>
@@ -1035,7 +1033,6 @@
<string name="msg_dc_trail_sym">Achterlopende, symmetrisch versleutelde gegevens tegengekomen</string>
<string name="msg_dc_trail_unknown">Achterlopende gegevens van onbekend type tegengekomen</string>
<string name="msg_dc_unlocking">Bezig met ontgrendelen van geheime sleutel</string>
- <string name="msg_dc_insecure_symmetric_encryption_algo">Mogelijk onveilig versleutelingsalgoritme gebruikt!</string>
<!--Messages for VerifySignedLiteralData operation-->
<string name="msg_vl">Ondertekeningscontrole wordt gestart</string>
<string name="msg_vl_error_no_siglist">Geen ondertekeningslijst in ondertekende letterlijke gegevens</string>
@@ -1063,7 +1060,6 @@
<string name="msg_pse_compressing">Bezig met voorbereiden van comprimeren</string>
<string name="msg_pse_encrypting">Bezig met versleutelen van gegevens</string>
<string name="msg_pse_error_bad_passphrase">Wachtwoord verkeerd!</string>
- <string name="msg_pse_error_hash_algo">Het gevraagde hashing-algoritme wordt niet ondersteund door deze sleutel!</string>
<string name="msg_pse_error_io">I/O-uitzondering tegengekomen tijdens bewerking!</string>
<string name="msg_pse_error_key_sign">Geselecteerde sleutel kan geen gegevens ondertekenen!</string>
<string name="msg_pse_error_sign_key">Fout bij ophalen van ondertekeningssleutel!</string>
@@ -1116,7 +1112,7 @@
<string name="msg_import_fetch_error_decode">Fout bij decoderen van opgehaalde sleutelbos!</string>
<string name="msg_import_fetch_error">Sleutel kon niet opgehaald worden! (Netwerkproblemen?)</string>
<string name="msg_import_fetch_keybase">Bezig met ophalen van keybase.io: %s</string>
- <string name="msg_import_fetch_keyserver_error">Kon sleutel niet ophalen van sleutelservers: %s</string>
+ <string name="msg_import_fetch_error_keyserver">Kon sleutel niet ophalen van sleutelservers: %s</string>
<string name="msg_import_fetch_keyserver">Bezig met ophalen van sleutelserver: %s</string>
<string name="msg_import_fetch_keyserver_ok">Ophalen van sleutel geslaagd!</string>
<string name="msg_import_keyserver">Sleutelserver %s wordt gebruikt</string>
@@ -1199,6 +1195,7 @@
<string name="passp_cache_notif_keys">Onthouden wachtwoorden</string>
<string name="passp_cache_notif_clear">Wachtwoorden wissen</string>
<string name="passp_cache_notif_pwd">Wachtwoord</string>
+ <!--Keyserver sync-->
<!--First Time-->
<string name="first_time_text1">Neem je privacy terug met OpenKeychain!</string>
<string name="first_time_create_key">Mijn sleutel aanmaken</string>
@@ -1207,6 +1204,8 @@
<string name="first_time_skip">Setup overslaan</string>
<string name="first_time_blank_yubikey">Wil je deze lege YubiKey NEO gebruiken met OpenKeychain?\n\nNeem de YubiKey nu weg, je zal gevraagd worden deze terug boven te halen wanneer nodig!</string>
<string name="first_time_blank_yubikey_yes">Gebruik deze YubiKey</string>
+ <string name="backup_all">Alle sleutels + je eigen sleutels</string>
+ <string name="backup_public_keys">Alle sleutels</string>
<!--unsorted-->
<string name="section_certifier_id">Certificeer</string>
<string name="section_cert">Certificaat Details</string>
@@ -1231,7 +1230,6 @@
<string name="unknown_algorithm">onbekend</string>
<string name="can_sign_not">kan niet ondertekenen</string>
<string name="error_no_encrypt_subkey">Geen codeer-subsleutel beschikbaar!</string>
- <string name="account_no_manual_account_creation">Maak OpenKeychain-accounts niet handmatig aan.\nVoor meer informatie, zie Help.</string>
<string name="contact_show_key">Toon sleutel (%s)</string>
<string name="swipe_to_update">Veeg naar beneden om van sleutelserver te updaten</string>
<string name="error_no_file_selected">Selecteer minstens een bestand om te versleutelen!</string>
@@ -1243,6 +1241,8 @@
<string name="exchange_description">Selecteer om een sleuteluitwisseling te starten het aantal deelnemers aan de rechterkant, en klik vervolgens op de knop \'Start uitwisseling\'.\n\nJe zal twee vragne gesteld worden om zeker te zijn dat enkel de juiste deelnemers zich in de uitwisseling bevinden en dat hun vingerafdrukken correct zijn.</string>
<string name="btn_start_exchange">Uitwisseling starten</string>
<string name="user_id_none"><![CDATA[<none>]]></string>
+ <!--Android Account-->
+ <string name="account_privacy_title">Privacy</string>
<!--Passphrase wizard-->
<!--TODO: rename all the things!-->
<string name="title_unlock_method">Kies een ontgrendelingsmethode</string>
@@ -1282,6 +1282,18 @@
<string name="btn_import">Importeren</string>
<string name="snack_yubi_other">Andere sleutel opgeslagen op YubiKey!</string>
<string name="error_nfc">NFC-fout: %s</string>
+ <plurals name="error_pin">
+ <item quantity="one">Ongeldige PIN!\n%d resterende poging.</item>
+ <item quantity="other">Ongeldige PIN!\n%d resterende pogingen.</item>
+ </plurals>
+ <string name="error_nfc_terminated">YubiKey in beëindigingsstaat.</string>
+ <string name="error_nfc_wrong_length">Ingevoerde PIN is te kort. PIN\'s zijn minstens 6 tekens lang.</string>
+ <string name="error_nfc_conditions_not_satisfied">Gebruiksvoorwaarden niet voldaan.</string>
+ <string name="error_nfc_security_not_satisfied">Veiligheidsstatus niet voldaan.</string>
+ <string name="error_nfc_authentication_blocked">PIN geblokkeerd na te veel pogingen.</string>
+ <string name="error_nfc_data_not_found">Sleutel of object niet gevonden.</string>
+ <string name="error_nfc_unknown">Onbekende fout</string>
+ <string name="error_nfc_try_again">Opnieuw proberen</string>
<string name="error_pin_nodefault">Standaard-PIN geweigerd!</string>
<string name="error_temp_file">Fout bij aanmaken van tijdelijk bestand.</string>
<string name="btn_delete_original">Oorspronkelijk bestand verwijderen</string>
@@ -1307,4 +1319,8 @@
<string name="file_delete_none">Geen bestand verwijderd! (Misschien was het al verwijderd?)</string>
<string name="file_delete_exception">Oorspronkelijk bestand kon niet worden verwijderd!</string>
<string name="error_clipboard_empty">Klembord is leeg!</string>
+ <string name="error_clipboard_copy">Fout bij kopiëren van gegevens naar klembord!</string>
+ <string name="error_scan_fp">Fout bij scannen van vingerafdruk!</string>
+ <string name="error_scan_match">Vingerafdrukken komen niet overeen!</string>
+ <string name="error_expiry_past">Verloopdatum is in het verleden!</string>
</resources>
diff --git a/OpenKeychain/src/main/res/values-pl/strings.xml b/OpenKeychain/src/main/res/values-pl/strings.xml
index db15b3e67..bf46e5c42 100644
--- a/OpenKeychain/src/main/res/values-pl/strings.xml
+++ b/OpenKeychain/src/main/res/values-pl/strings.xml
@@ -20,8 +20,6 @@
<string name="title_encrypt_to_file">Zaszyfruj do pliku</string>
<string name="title_decrypt_to_file">Odszyfruj do pliku</string>
<string name="title_import_keys">Importuj klucze</string>
- <string name="title_export_key">Eksportuj klucz</string>
- <string name="title_export_keys">Eksportuj klucze</string>
<string name="title_key_not_found">Nie znaleziono klucza</string>
<string name="title_send_key">Wyślij do serwera kluczy</string>
<string name="title_key_details">Szczegóły klucza</string>
@@ -57,7 +55,6 @@
<!--menu-->
<string name="menu_preferences">Ustawienia</string>
<string name="menu_help">Pomoc</string>
- <string name="menu_export_key">Eksportuj do pliku</string>
<string name="menu_delete_key">Usuń klucz</string>
<string name="menu_search">Szukaj</string>
<string name="menu_beam_preferences">Ustawienia Beam</string>
@@ -96,6 +93,7 @@
<string name="label_fingerprint">Odcisk</string>
<string name="expiry_date_dialog_title">Ustaw datę wygaśnięcia</string>
<string name="label_preferred">preferowany</string>
+ <!--label shown in Android settings under the OpenKeychain account-->
<!--Proxy Preferences-->
<!--proxy type choices and values-->
<!--OrbotHelper strings-->
@@ -341,6 +339,7 @@
</plurals>
<string name="delete_nothing">Nie ma nic do usunięcia.</string>
<string name="delete_cancelled">Operacja usuwania anulowana.</string>
+ <!--Revoke result toast (snackbar)-->
<!--Certify result toast-->
<plurals name="certify_keys_ok">
<item quantity="one">Pomyślnie certyfikowano klucz%2$s.</item>
@@ -372,7 +371,6 @@
<string name="api_settings_start">Uruchom aplikację</string>
<string name="api_settings_delete_account">Usuń konto</string>
<string name="api_settings_package_name">Nazwa paczki</string>
- <string name="api_settings_package_certificate">Skrót SHA-256 podpisu paczki</string>
<string name="api_settings_settings">Ustawienia</string>
<string name="api_settings_key">Klucz konta:</string>
<string name="api_settings_accounts_empty">Brak kont połączonych z tą aplikacją.</string>
@@ -384,14 +382,15 @@ OSTRZEŻENIE: Jeżeli nie wiesz, czemu wyświetlił się ten komunikat, nie zezw
<string name="api_register_allow">Zezwól na dostęp</string>
<string name="api_register_disallow">Odmów dostępu</string>
<string name="api_register_error_select_key">Wybierz klucz!</string>
- <string name="api_select_pub_keys_missing_text">Nie znaleziono kluczy dla następujących tożsamości:</string>
- <string name="api_select_pub_keys_dublicates_text">Więcej niż jeden klucz istnieje dla następujących tożsamości:</string>
<string name="api_select_pub_keys_text">Proszę przejrzeć listę adresatów!</string>
<string name="api_select_pub_keys_text_no_user_ids">Prosimy o wybranie odbiorców!</string>
<string name="api_error_wrong_signature">Sprawdzanie podpisu zakończone niepowodzeniem! Czy zainstalowałeś tę aplikację z innego źródła? Jeżeli jesteś pewien, że nie jest to atak, odwołaj rejestrację teg aplikacji w OpenKeychain, a następnie zarejestruj ją ponownie.</string>
<!--Share-->
<string name="share_qr_code_dialog_title">Udostępnij przez kod QR</string>
<string name="share_nfc_dialog">Udostępnij przez NFC</string>
+ <!--retry upload dialog-->
+ <!--Delete or revoke private key dialog-->
+ <!--Delete Or Revoke Dialog spinner-->
<!--Key list-->
<plurals name="key_list_selected_keys">
<item quantity="one">1 klucz wybrany.</item>
@@ -565,6 +564,7 @@ OSTRZEŻENIE: Jeżeli nie wiesz, czemu wyświetlił się ten komunikat, nie zezw
<!--Messages for Keybase Verification operation-->
<!--Messages for Export Log operation-->
<!--PassphraseCache-->
+ <!--Keyserver sync-->
<!--First Time-->
<string name="first_time_text1">Weź prywatność w swoje ręce używając OpenKeychain!</string>
<string name="first_time_skip">Pomiń ustawienia</string>
@@ -591,6 +591,7 @@ OSTRZEŻENIE: Jeżeli nie wiesz, czemu wyświetlił się ten komunikat, nie zezw
<string name="error_no_file_selected">Wybierz przynajmniej jeden plik, aby szyfrować!</string>
<string name="key_colon">Klucz:</string>
<string name="btn_start_exchange">Rozpocznij wymianę</string>
+ <!--Android Account-->
<!--Passphrase wizard-->
<!--TODO: rename all the things!-->
<!--<string name="enter_passphrase_twice">Enter password twice</string>-->
diff --git a/OpenKeychain/src/main/res/values-pt/strings.xml b/OpenKeychain/src/main/res/values-pt/strings.xml
deleted file mode 100644
index 0713e39ad..000000000
--- a/OpenKeychain/src/main/res/values-pt/strings.xml
+++ /dev/null
@@ -1,78 +0,0 @@
-<?xml version='1.0' encoding='UTF-8'?>
-<resources>
- <!--GENERAL: Please put all strings inside quotes as described in example 1 on
- http://developer.android.com/guide/topics/resources/string-resource.html (scroll down to "Escaping apostrophes and quotes").-->
- <!--title-->
- <!--section-->
- <!--button-->
- <!--menu-->
- <!--label-->
- <!--Proxy Preferences-->
- <!--proxy type choices and values-->
- <!--OrbotHelper strings-->
- <!--InstallDialogFragment strings-->
- <!--StartOrbotDialogFragment strings-->
- <!--choice-->
- <!--key flags-->
- <!--sentences-->
- <!--errors
- no punctuation, all lowercase,
- they will be put after "error_message", e.g. "Error: file not found"-->
- <!--errors without preceeding Error:-->
- <!--results shown after decryption/verification-->
- <!--Add keys-->
- <!--progress dialogs, usually ending in '…'-->
- <!--action strings-->
- <!--key bit length selections-->
- <!--elliptic curve names-->
- <!--not in for now, see SaveKeyringParcel
- <string name="key_curve_bp_p256">"Brainpool P-256"</string>
- <string name="key_curve_bp_p384">"Brainpool P-384"</string>
- <string name="key_curve_bp_p512">"Brainpool P-512"</string>-->
- <!--compression-->
- <!--Help-->
- <!--Import-->
- <!--Import from URL-->
- <!--Generic result toast-->
- <!--Import result toast-->
- <!--Delete result toast-->
- <!--Certify result toast-->
- <!--Intent labels-->
- <!--Remote API-->
- <!--Share-->
- <!--Key list-->
- <!--Key view-->
- <!--Key trust-->
- <!--keybase proof stuff-->
- <!--Edit key-->
- <!--Create key-->
- <!--View key-->
- <!--Add/Edit keyserver-->
- <!--Navigation Drawer-->
- <!--hints-->
- <!--certs-->
- <!--LogType log messages. Errors should have _ERROR_ in their name and end with a !-->
- <!--Import Public log entries-->
- <!--Import Secret log entries-->
- <!--Keyring Canonicalization log entries-->
- <!--Keyring merging log entries-->
- <!--createSecretKeyRing-->
- <!--modifySecretKeyRing-->
- <!--Consolidate-->
- <!--Edit Key (higher level than modify)-->
- <!--Promote key-->
- <!--Other messages used in OperationLogs-->
- <!--Messages for DecryptVerify operation-->
- <!--Messages for VerifySignedLiteralData operation-->
- <!--Messages for SignEncrypt operation-->
- <!--Messages for PgpSignEncrypt operation-->
- <!--Messages for Keybase Verification operation-->
- <!--Messages for Export Log operation-->
- <!--PassphraseCache-->
- <!--First Time-->
- <!--unsorted-->
- <!--Passphrase wizard-->
- <!--TODO: rename all the things!-->
- <!--<string name="enter_passphrase_twice">Enter password twice</string>-->
- <!--<string name="nfc_text">Please place a NFC tag near your device</string>-->
-</resources>
diff --git a/OpenKeychain/src/main/res/values-ro/strings.xml b/OpenKeychain/src/main/res/values-ro/strings.xml
deleted file mode 100644
index 0713e39ad..000000000
--- a/OpenKeychain/src/main/res/values-ro/strings.xml
+++ /dev/null
@@ -1,78 +0,0 @@
-<?xml version='1.0' encoding='UTF-8'?>
-<resources>
- <!--GENERAL: Please put all strings inside quotes as described in example 1 on
- http://developer.android.com/guide/topics/resources/string-resource.html (scroll down to "Escaping apostrophes and quotes").-->
- <!--title-->
- <!--section-->
- <!--button-->
- <!--menu-->
- <!--label-->
- <!--Proxy Preferences-->
- <!--proxy type choices and values-->
- <!--OrbotHelper strings-->
- <!--InstallDialogFragment strings-->
- <!--StartOrbotDialogFragment strings-->
- <!--choice-->
- <!--key flags-->
- <!--sentences-->
- <!--errors
- no punctuation, all lowercase,
- they will be put after "error_message", e.g. "Error: file not found"-->
- <!--errors without preceeding Error:-->
- <!--results shown after decryption/verification-->
- <!--Add keys-->
- <!--progress dialogs, usually ending in '…'-->
- <!--action strings-->
- <!--key bit length selections-->
- <!--elliptic curve names-->
- <!--not in for now, see SaveKeyringParcel
- <string name="key_curve_bp_p256">"Brainpool P-256"</string>
- <string name="key_curve_bp_p384">"Brainpool P-384"</string>
- <string name="key_curve_bp_p512">"Brainpool P-512"</string>-->
- <!--compression-->
- <!--Help-->
- <!--Import-->
- <!--Import from URL-->
- <!--Generic result toast-->
- <!--Import result toast-->
- <!--Delete result toast-->
- <!--Certify result toast-->
- <!--Intent labels-->
- <!--Remote API-->
- <!--Share-->
- <!--Key list-->
- <!--Key view-->
- <!--Key trust-->
- <!--keybase proof stuff-->
- <!--Edit key-->
- <!--Create key-->
- <!--View key-->
- <!--Add/Edit keyserver-->
- <!--Navigation Drawer-->
- <!--hints-->
- <!--certs-->
- <!--LogType log messages. Errors should have _ERROR_ in their name and end with a !-->
- <!--Import Public log entries-->
- <!--Import Secret log entries-->
- <!--Keyring Canonicalization log entries-->
- <!--Keyring merging log entries-->
- <!--createSecretKeyRing-->
- <!--modifySecretKeyRing-->
- <!--Consolidate-->
- <!--Edit Key (higher level than modify)-->
- <!--Promote key-->
- <!--Other messages used in OperationLogs-->
- <!--Messages for DecryptVerify operation-->
- <!--Messages for VerifySignedLiteralData operation-->
- <!--Messages for SignEncrypt operation-->
- <!--Messages for PgpSignEncrypt operation-->
- <!--Messages for Keybase Verification operation-->
- <!--Messages for Export Log operation-->
- <!--PassphraseCache-->
- <!--First Time-->
- <!--unsorted-->
- <!--Passphrase wizard-->
- <!--TODO: rename all the things!-->
- <!--<string name="enter_passphrase_twice">Enter password twice</string>-->
- <!--<string name="nfc_text">Please place a NFC tag near your device</string>-->
-</resources>
diff --git a/OpenKeychain/src/main/res/values-ru/strings.xml b/OpenKeychain/src/main/res/values-ru/strings.xml
index 47c171728..55a5afa5e 100644
--- a/OpenKeychain/src/main/res/values-ru/strings.xml
+++ b/OpenKeychain/src/main/res/values-ru/strings.xml
@@ -7,12 +7,11 @@
<string name="title_encrypt_text">Зашифровать текст</string>
<string name="title_encrypt_files">Зашифровать файлы</string>
<string name="title_decrypt">Расшифровать</string>
- <string name="title_unlock">Разблокировать ключ</string>
<string name="title_add_subkey">Добавить подключ</string>
<string name="title_edit_key">Изменить ключ</string>
<string name="title_preferences">Настройки</string>
<string name="title_api_registered_apps">Приложения</string>
- <string name="title_key_server_preference">Серверы ключей</string>
+ <string name="title_key_server_preference">Серверы OpenPGP</string>
<string name="title_change_passphrase">Изменить пароль</string>
<string name="title_share_fingerprint_with">Отправить отпечаток...</string>
<string name="title_share_key">Отправить ключ...</string>
@@ -21,8 +20,8 @@
<string name="title_encrypt_to_file">Зашифровать в файл</string>
<string name="title_decrypt_to_file">Расшифровать в файл</string>
<string name="title_import_keys">Импорт ключей</string>
- <string name="title_export_key">Экспортировать ключ</string>
- <string name="title_export_keys">Экспорт ключей</string>
+ <string name="title_export_key">Резервный ключ</string>
+ <string name="title_export_keys">Резервные ключи</string>
<string name="title_key_not_found">Ключ не найден</string>
<string name="title_send_key">Загрузить на сервер ключей</string>
<string name="title_certify_key">Сертифицировать ключ</string>
@@ -30,29 +29,37 @@
<string name="title_help">Помощь</string>
<string name="title_log_display">Журнал</string>
<string name="title_exchange_keys">Обмен ключами</string>
- <string name="title_advanced_key_info">Детальная информация о ключе</string>
+ <string name="title_advanced_key_info">Дополнительные сведения</string>
<string name="title_delete_secret_key">Удалить ВАШ ключ \'%s\'?</string>
+ <string name="title_export_log">Экспорт журнала</string>
+ <string name="title_manage_my_keys">Управление ключами</string>
<!--section-->
<string name="section_user_ids">Идентификаторы</string>
+ <string name="section_yubikey">YubiKey</string>
<string name="section_linked_system_contact">Связанные контакты</string>
<string name="section_should_you_trust">Должны ли Вы доверять этому ключу?</string>
<string name="section_proof_details">Подтвердить верификацию</string>
<string name="section_cloud_evidence">Подтвердить из облака</string>
<string name="section_keys">Доп. ключи</string>
<string name="section_cloud_search">Облачный поиск</string>
- <string name="section_passphrase_cache">Кэш пароля</string>
+ <string name="section_proxy_settings">Настройки прокси</string>
+ <string name="section_gui">Интерфейс</string>
+ <string name="section_certify">Подтвердить</string>
<string name="section_actions">Действия</string>
<string name="section_share_key">Ключ</string>
<string name="section_key_server">Сервер ключей</string>
<string name="section_fingerprint">Отпечаток ключа</string>
<string name="section_encrypt">Зашифровать</string>
- <string name="section_decrypt">Расшифровать</string>
+ <string name="section_decrypt">Расшифровка / Подтверждение</string>
<string name="section_current_expiry">Текущий срок годности</string>
<string name="section_new_expiry">Новый срок годности</string>
<!--button-->
<string name="btn_decrypt_verify_file">Расшифровать, проверить и сохранить файл</string>
<string name="btn_encrypt_share_file">Зашифровать и отправить файл</string>
+ <string name="btn_encrypt_save_file">Зашифровать и сохранить файл</string>
+ <string name="btn_save_file">Сохранить файл</string>
<string name="btn_save">Сохранить</string>
+ <string name="btn_view_log">Смотреть журнал</string>
<string name="btn_do_not_save">Отмена</string>
<string name="btn_delete">Удалить</string>
<string name="btn_no_date">Бесконечно</string>
@@ -62,28 +69,41 @@
<string name="btn_back">Назад</string>
<string name="btn_no">Нет</string>
<string name="btn_match">Отпечатки совпадают</string>
+ <string name="btn_share_encrypted_signed">Зашифровать и отправить текст</string>
+ <string name="btn_copy_encrypted_signed">Зашифровать и скопировать текст</string>
<string name="btn_view_cert_key">Просмотр ключа</string>
<string name="btn_create_key">Создать ключ</string>
<string name="btn_add_files">Добавить файл(ы)</string>
- <string name="btn_add_share_decrypted_text">Поделиться расшифрованным текстом</string>
- <string name="btn_decrypt_clipboard">Расшифровать текст из буфера обмена</string>
- <string name="btn_decrypt_and_verify">и проверить подписи</string>
- <string name="btn_decrypt_files">Расшифровать файлы</string>
+ <string name="btn_share_decrypted_text">Отправить расшифрованный текст</string>
+ <string name="btn_copy_decrypted_text">Копировать расшифрованный текст</string>
+ <string name="btn_decrypt_clipboard">Прочитать из буфера</string>
+ <string name="btn_decrypt_files">Выберите входной файл</string>
<string name="btn_encrypt_files">Зашифровать файлы</string>
<string name="btn_encrypt_text">Зашифровать текст</string>
+ <string name="btn_add_email">Добавить дополнительные адреса почты</string>
+ <string name="btn_unlock">Разблокировать</string>
+ <string name="btn_add_keyserver">Добавить</string>
+ <string name="btn_save_default">Сохранить по умолчанию</string>
+ <string name="btn_saved">Сохранено!</string>
<!--menu-->
<string name="menu_preferences">Настройки</string>
<string name="menu_help">Помощь</string>
- <string name="menu_export_key">Экспорт в файл</string>
+ <string name="menu_export_key">Поместить резервную копию в файл</string>
<string name="menu_delete_key">Удалить ключ</string>
+ <string name="menu_manage_keys">Управление ключами</string>
<string name="menu_search">Поиск</string>
<string name="menu_nfc_preferences">Настройки NFC</string>
<string name="menu_beam_preferences">Настройки Beam</string>
<string name="menu_encrypt_to">Зашифровать....</string>
<string name="menu_select_all">Выбрать все</string>
<string name="menu_export_all_keys">Экспорт всех ключей</string>
- <string name="menu_advanced">Подробные данные</string>
+ <string name="menu_update_all_keys">Обновить все ключи</string>
+ <string name="menu_advanced">Дополнительные сведения</string>
+ <string name="menu_certify_fingerprint">Подтвердить по отпечатку</string>
+ <string name="menu_export_log">Экспорт журнала</string>
+ <string name="menu_keyserver_add">Добавить</string>
<!--label-->
+ <string name="label_message">Текст</string>
<string name="label_file">Файл</string>
<string name="label_files">Файл(ы)</string>
<string name="label_file_colon">Файл:</string>
@@ -91,6 +111,7 @@
<string name="label_passphrase">Пароль</string>
<string name="label_unlock">Идет разблокировка...</string>
<string name="label_passphrase_again">Повторите пароль</string>
+ <string name="label_show_passphrase">Показать пароль</string>
<string name="label_algorithm">Алгоритм</string>
<string name="label_ascii_armor">ASCII формат</string>
<string name="label_file_ascii_armor">Использовать ASCII формат</string>
@@ -99,18 +120,19 @@
<string name="label_use_default_yubikey_pin">Использовать YubiKey PIN по умолчанию</string>
<string name="label_use_num_keypad_for_yubikey_pin">Использовать цифровую клавиатуру для YubiKey PIN</string>
<string name="label_label_use_default_yubikey_pin_summary">Использовать PIN по умолчанию (123456) для доступа к YubiKeys через NFC</string>
- <string name="label_asymmetric_from">Подписано:</string>
+ <string name="label_asymmetric_from">Подписать:</string>
<string name="label_to">Зашифровать для:</string>
+ <string name="label_delete_after_encryption">Удалить файлы после шифрования</string>
<string name="label_delete_after_decryption">Удалить после шифрования</string>
<string name="label_encryption_algorithm">Алгоритм шифрования</string>
<string name="label_hash_algorithm">ХЭШ-алгоритм</string>
- <string name="label_symmetric">Зашифровать паролем</string>
- <string name="label_passphrase_cache_ttl">Время хранения в кэше</string>
- <string name="label_passphrase_cache_subs">Кэшировать пароли по доп. ключу</string>
+ <string name="label_symmetric">Зашифровать с паролем</string>
+ <string name="label_passphrase_cache_ttl">Запомнить время</string>
<string name="label_message_compression">Сжатие текста</string>
<string name="label_file_compression">Сжатие файла</string>
- <string name="label_keyservers">Серверы ключей</string>
+ <string name="label_keyservers">Выберите серверы OpenPGP</string>
<string name="label_key_id">ID ключа</string>
+ <string name="label_key_created">Создан ключ %s</string>
<string name="label_creation">Создан</string>
<string name="label_expiry">Годен до</string>
<string name="label_usage">Применение</string>
@@ -123,8 +145,48 @@
<string name="label_send_key">Синхронизировать с облаком</string>
<string name="label_fingerprint">Отпечаток</string>
<string name="expiry_date_dialog_title">Срок годности</string>
- <string name="label_first_keyserver_is_used">(Предпочесть первый сервер ключей)</string>
+ <string name="label_keyservers_title">Серверы ключей</string>
+ <string name="label_keyserver_settings_hint">Переместите для смены приоритета, зажмите чтобы редактировать/удалить</string>
+ <string name="label_selected_keyserver_title">Выбранные серверы ключей</string>
<string name="label_preferred">предпочитаемый</string>
+ <string name="label_enable_compression">Использовать сжатие</string>
+ <string name="label_encrypt_filenames">Шифровать имена файлов</string>
+ <string name="label_hidden_recipients">Скрыть получателей</string>
+ <string name="label_verify_keyserver">Подтвердить сервер ключей</string>
+ <string name="label_enter_keyserver_url">Введите адрес сервера ключей</string>
+ <string name="label_keyserver_dialog_delete">Удалить сервер ключей</string>
+ <string name="label_theme">Тема</string>
+ <string name="pref_keyserver">Серверы OpenPGP</string>
+ <string name="pref_keyserver_summary">Искать ключи на выбранных серверах OpenPGP (протокол HKP)</string>
+ <string name="pref_keybase">keybase.io</string>
+ <string name="pref_keybase_summary">Искать ключи на Keybase.io</string>
+ <!--label shown in Android settings under the OpenKeychain account-->
+ <!--Proxy Preferences-->
+ <string name="pref_proxy_tor_title">Использовать Tor</string>
+ <string name="pref_proxy_tor_summary">Требуется установка Orbot</string>
+ <string name="pref_proxy_normal_title">Использовать другой прокси</string>
+ <string name="pref_proxy_host_title">Хост прокси</string>
+ <string name="pref_proxy_host_err_invalid">Хост прокси не может быть пустым</string>
+ <string name="pref_proxy_port_title">Порт прокси</string>
+ <string name="pref_proxy_port_err_invalid">Введён неверный номер порта</string>
+ <string name="pref_proxy_type_title">Тип прокси</string>
+ <!--proxy type choices and values-->
+ <string name="pref_proxy_type_choice_http">HTTP</string>
+ <string name="pref_proxy_type_choice_socks">SOCKS</string>
+ <!--OrbotHelper strings-->
+ <string name="orbot_ignore_tor">Не использовать Tor</string>
+ <!--InstallDialogFragment strings-->
+ <string name="orbot_install_dialog_title">Установить Orbot чтобы использовать Tor?</string>
+ <string name="orbot_install_dialog_install">Установка</string>
+ <string name="orbot_install_dialog_content">Вам необходимо установить Orbot и пустить трафик прокси через него. Хотите установить Orbot?</string>
+ <string name="orbot_install_dialog_cancel">Отмена</string>
+ <string name="orbot_install_dialog_ignore_tor">Не использовать Tor</string>
+ <!--StartOrbotDialogFragment strings-->
+ <string name="orbot_start_dialog_title">Запустить Orbot?</string>
+ <string name="orbot_start_btn">Запустить Orbot</string>
+ <string name="orbot_start_dialog_start">Запустить Orbot</string>
+ <string name="orbot_start_dialog_cancel">Отмена</string>
+ <string name="orbot_start_dialog_ignore_tor">Не использовать Tor</string>
<string name="user_id_no_name">&lt;нет имени&gt;</string>
<string name="none">&lt;нет&gt;</string>
<plurals name="n_keys">
@@ -162,29 +224,36 @@
<string name="filemanager_title_open">Открыть...</string>
<string name="error">Ошибка</string>
<string name="error_message">Ошибка: %s</string>
+ <string name="theme_dark">Темная</string>
+ <string name="theme_light">Светлая</string>
<!--key flags-->
<string name="flag_certify">Сертификация</string>
<string name="flag_sign">Подписание</string>
<string name="flag_encrypt">Шифрование</string>
<string name="flag_authenticate">Аутентификация</string>
<!--sentences-->
- <string name="wrong_passphrase">Неправ. пароль</string>
+ <string name="wrong_passphrase">Неправильный пароль</string>
<string name="no_filemanager_installed">Нет совместимого менеджера файлов.</string>
<string name="passphrases_do_not_match">Пароли не совпадают.</string>
<string name="passphrase_must_not_be_empty">Пожалуйста, введите пароль.</string>
<string name="passphrase_for_symmetric_encryption">Симметричное шифрование.</string>
- <string name="passphrase_for">Введите пароль для
-\'%s\'</string>
+ <string name="passphrase_for">Введите пароль для \'%s\'</string>
<string name="pin_for">Введите PIN для
\'%s\'</string>
<string name="yubikey_pin_for">Введите PIN для доступа к YubiKey для
\'%s\'</string>
- <string name="nfc_text">Держите YubiKey возле задней части вашего устройства.</string>
- <string name="no_file_selected">Сначала выберите файл.</string>
+ <string name="file_delete_confirmation_title">Удалить исходные файлы?</string>
+ <string name="file_delete_confirmation">Следующие файлы будут удалены:%s</string>
+ <string name="no_file_selected">Файл не выбран</string>
<string name="encrypt_sign_successful">Успешно подписано и/или зашифровано.</string>
<string name="encrypt_sign_clipboard_successful">Успешно подписано и/или зашифровано в буфер обмена.</string>
<string name="select_encryption_key">Укажите хотя бы один ключ.</string>
<string name="error_no_encryption_or_signature_key">Выберите хотя бы один ключ для шифрования или подписи.</string>
+ <string name="specify_file_to_encrypt_to">Пожалуйста, укажите, в какой файл произвести шифрование.\nВНИМАНИЕ: Файл будет перезаписан, если он уже существует!</string>
+ <string name="specify_file_to_decrypt_to">Пожалуйста, укажите, в какой файл произвести расшифровку.\nВНИМАНИЕ: Файл будет перезаписан, если он уже существует!</string>
+ <string name="key_deletion_confirmation_multi">Вы правда хотите удалить выбранные ключи?</string>
+ <string name="secret_key_deletion_confirmation">После удаления будет невозможно прочесть сообщения зашифрованные данным ключом и утрачены все подтверждения ключей выполненные с его помощью!</string>
+ <string name="public_key_deletetion_confirmation">Удалить ключ \'%s\'?</string>
<string name="also_export_secret_keys">Экспортировать секретные ключи</string>
<string name="reinstall_openkeychain">Вы столкнулись с багом Андроид. Пожалуйста, переустановите OpenKeychain чтобы связать ваши контакты и ключи. </string>
<string name="key_exported">Успешный экспорт 1 ключа.</string>
@@ -192,21 +261,25 @@
<string name="no_keys_exported">Ключи не были экспортированы.</string>
<string name="key_creation_el_gamal_info">Прим.: только вторичные ключи поддерживают ElGamal.</string>
<string name="key_not_found">Не удается найти ключ %08X.</string>
+ <string name="specify_file_to_export_log_to">Пожалуйста, выберите файл в который произвести экспорт.\nВНИМАНИЕ! Файл будет перезаписан если он уже существует!</string>
<string name="list_empty">Список пуст!</string>
<string name="nfc_successful">Ключ успешно передан через NFC!</string>
<string name="key_copied_to_clipboard">Ключ скопирован в буфер обмена!</string>
<string name="fingerprint_copied_to_clipboard">Отпечаток ключа скопирован в буфер обмена!</string>
+ <string name="select_key_to_certify">Выберите ключ, используемый для подтверждения!</string>
<string name="key_too_big_for_sharing">Ключ слишком большой для этого способа передачи!</string>
<string name="text_copied_to_clipboard">Тест скопирован в буфер обмена!</string>
<!--errors
no punctuation, all lowercase,
they will be put after "error_message", e.g. "Error: file not found"-->
+ <string name="error_file_delete_failed">не удалены. Удалите их самостоятельно!</string>
+ <string name="error_file_added_already">%s уже был добавлен.</string>
<string name="error_file_not_found">файл не найден</string>
<string name="error_no_secret_key_found">нет подходящего секретного ключа</string>
<string name="error_external_storage_not_ready">внешняя память не готова</string>
<string name="error_key_size_minimum512bit">размер ключа должен быть не менее 512бит</string>
<string name="error_unknown_algorithm_choice">выбран неизвестный алгоритм</string>
- <string name="error_user_id_no_email">email не найден</string>
+ <string name="error_user_id_no_email">адрес почты не найден</string>
<string name="error_key_needs_a_user_id">необходим хотя бы один идентификатор</string>
<string name="error_no_signature_passphrase">пароль не задан</string>
<string name="error_no_signature_key">ключ для подписи не задан</string>
@@ -219,21 +292,22 @@
<string name="error_nfc_needed">Необходимо включить NFC!</string>
<string name="error_beam_needed">Необходимо включить Beam!</string>
<string name="error_nothing_import">Ключи не найдены!</string>
+ <string name="error_nothing_import_selected">Ключи для импорта не выбраны!</string>
<string name="error_contacts_key_id_missing">Ошибка извлечения идентификатора ключа из контактов!</string>
<string name="error_generic_report_bug">Выявлена ошибка. Пожалуйста, сообщите о ней разработчику.</string>
<!--results shown after decryption/verification-->
<string name="decrypt_result_no_signature">Не подписано</string>
<string name="decrypt_result_invalid_signature">Неверная подпись!</string>
- <string name="decrypt_result_signature_uncertified">Подписано (не удостоверено!)</string>
- <string name="decrypt_result_signature_certified">Подписано:</string>
- <string name="decrypt_result_signature_expired_key">Срок годности ключа истёк!</string>
- <string name="decrypt_result_signature_revoked_key">Ключ аннулирован!</string>
- <string name="decrypt_result_signature_missing_key">Неизвестный открытый ключ</string>
+ <string name="decrypt_result_signature_uncertified">Подписано <b>неподтверждённым</b> ключом!</string>
+ <string name="decrypt_result_signature_secret">Подписано Вашим ключом</string>
+ <string name="decrypt_result_signature_certified">Подписано подтверждённым ключом</string>
+ <string name="decrypt_result_signature_expired_key">Подписано <b>просроченным</b> ключом!</string>
+ <string name="decrypt_result_signature_revoked_key">Подписано <b>отозванным</b> ключом!</string>
+ <string name="decrypt_result_signature_missing_key">Подписано <b>неизвестным ключом</b>!</string>
<string name="decrypt_result_encrypted">Зашифровано</string>
<string name="decrypt_result_not_encrypted">Не зашифровано</string>
<string name="decrypt_result_action_show">Показать</string>
<string name="decrypt_result_action_Lookup">Искать</string>
- <string name="decrypt_invalid_text">Неверная подпись или ключ был отозван или просрочен. Авторство текста невозможно проверить. Показать текст?</string>
<string name="decrypt_invalid_button">Мне понятны все риски, показать!</string>
<!--Add keys-->
<string name="add_keys_my_key">Мой ключ:</string>
@@ -243,6 +317,7 @@
<string name="progress_cancelling">отмена...</string>
<string name="progress_saving">сохранение...</string>
<string name="progress_importing">импорт...</string>
+ <string name="progress_updating">Обновление ключей...</string>
<string name="progress_exporting">экспорт...</string>
<string name="progress_uploading">загружается...</string>
<string name="progress_building_key">создание ключа...</string>
@@ -269,6 +344,7 @@
<item quantity="many">экспорт ключей...</item>
<item quantity="other">экспорт ключей...</item>
</plurals>
+ <string name="progress_start">подготовка действия...</string>
<string name="progress_extracting_signature_key">извлечение подписи ключа...</string>
<string name="progress_extracting_key">извлечение ключа...</string>
<string name="progress_preparing_streams">подготовка к передаче...</string>
@@ -288,6 +364,7 @@
<string name="progress_deleting">удаление ключей...</string>
<string name="progress_con_saving">объединение: сохранение в кэш...</string>
<string name="progress_con_reimport">объединение: реимпорт...</string>
+ <string name="progress_verifying_keyserver_url">подтверждение сервера ключей...</string>
<!--action strings-->
<string name="hint_cloud_search_hint">Искать через Имя, Email...</string>
<!--key bit length selections-->
@@ -317,6 +394,7 @@
<!--Help-->
<string name="help_tab_start">Начать</string>
<string name="help_tab_faq">ЧаВо</string>
+ <string name="help_tab_wot">Подтверждение ключей</string>
<string name="help_tab_nfc_beam">NFC Beam</string>
<string name="help_tab_changelog">Изменения</string>
<string name="help_tab_about">О программе</string>
@@ -328,9 +406,11 @@
<string name="import_tab_qr_code">QR код/NFC</string>
<string name="import_import">Импорт выбранных ключей</string>
<string name="import_qr_code_wrong">Некорректный QR код. Попробуйте снова!</string>
- <string name="import_qr_code_too_short_fingerprint">Отпечаток слишком коротнкий (&lt; 16 символов)</string>
+ <string name="import_qr_code_fp">Отпечаток нарушен или слишком короткий!</string>
+ <string name="import_qr_code_too_short_fingerprint">Отпечаток слишком короткий!</string>
<string name="import_qr_code_button">Сканировать QR код...</string>
<string name="import_qr_code_text">Расположите вашу камеру над QR кодом!</string>
+ <!--Import from URL-->
<!--Generic result toast-->
<string name="snackbar_details">Сведения</string>
<string name="with_warnings">, с предупреждениями</string>
@@ -347,6 +427,7 @@
<!--Delete result toast-->
<string name="delete_nothing">Нет данных для удаления!</string>
<string name="delete_cancelled">Удаление отменено.</string>
+ <!--Revoke result toast (snackbar)-->
<!--Certify result toast-->
<!--Intent labels-->
<string name="intent_decrypt_file">OpenKeychain: Расшифровать файл</string>
@@ -355,11 +436,12 @@
<string name="intent_send_decrypt">OpenKeychain: Расшифровать</string>
<!--Remote API-->
<string name="api_settings_show_info">Показать подробную информацию</string>
- <string name="api_settings_hide_info">Скрыть подробную информацию</string>
+ <string name="api_settings_hide_info">Скрыть дополнительную информацию</string>
<string name="api_settings_show_advanced">Показать расширенные настройки</string>
<string name="api_settings_hide_advanced">Скрыть расширенные настройки</string>
<string name="api_settings_no_key">Ключ не выбран</string>
<string name="api_settings_select_key">Выбрать ключ</string>
+ <string name="api_settings_create_key">Создать новый ключ</string>
<string name="api_settings_save">Сохранить</string>
<string name="api_settings_save_msg">Аккаунт сохранен</string>
<string name="api_settings_cancel">Отмена</string>
@@ -367,9 +449,8 @@
<string name="api_settings_start">Запустить приложение</string>
<string name="api_settings_delete_account">Удалить аккаунт</string>
<string name="api_settings_package_name">Наименование пакета</string>
- <string name="api_settings_package_certificate">SHA-256 подписи пакета</string>
<string name="api_settings_accounts">Аккаунты (устаревший API)</string>
- <string name="api_settings_advanced">Подробная информация</string>
+ <string name="api_settings_advanced">Дополнительные сведения</string>
<string name="api_settings_allowed_keys">Разрешённые ключи</string>
<string name="api_settings_settings">Настройки</string>
<string name="api_settings_key">Ключ аккаунта:</string>
@@ -380,14 +461,17 @@
<string name="api_register_allow">Разрешить доступ</string>
<string name="api_register_disallow">Запретить доступ</string>
<string name="api_register_error_select_key">Пожалуйста, выберите ключ!</string>
- <string name="api_select_pub_keys_missing_text">Для данных лиц ключи не найдены:</string>
- <string name="api_select_pub_keys_dublicates_text">Для данных лиц имеется более одного ключа: </string>
<string name="api_select_pub_keys_text">Пожалуйста, проверьте получателей!</string>
<string name="api_select_pub_keys_text_no_user_ids">Пожалуйста, выберите получателей!</string>
<string name="api_error_wrong_signature">Проверка подписи пакета не удалась! Если вы установили программу из другого источника, отзовите для неё доступ к этой программе или обновите право доступа.</string>
+ <string name="api_select_sign_key_text">Пожалуйста, выберите свой ключ или создайте новый.</string>
+ <string name="api_select_keys_text">Ни один из доступных ключей не позволил расшифровать содержимое. Пожалуйста, выберите правильный ключ.</string>
<!--Share-->
<string name="share_qr_code_dialog_title">Отправить как QR код</string>
<string name="share_nfc_dialog">Отправить через NFC</string>
+ <!--retry upload dialog-->
+ <!--Delete or revoke private key dialog-->
+ <!--Delete Or Revoke Dialog spinner-->
<!--Key list-->
<plurals name="key_list_selected_keys">
<item quantity="one">1 ключ выбран.</item>
@@ -402,6 +486,7 @@
<string name="key_view_action_edit">Изменить ключ</string>
<string name="key_view_action_encrypt">Зашифровать текст</string>
<string name="key_view_action_encrypt_files">файлы</string>
+ <string name="key_view_action_certify">Подтвердить ключ</string>
<string name="key_view_action_update">Обновить с сервера ключей</string>
<string name="key_view_action_share_with">Отправить...</string>
<string name="key_view_action_share_nfc">Отправить через NFC</string>
@@ -420,24 +505,25 @@
<string name="user_id_info_invalid_title">Недействительно</string>
<string name="user_id_info_invalid_text">Что-то не так с идентификатором!</string>
<!--Key trust-->
+ <string name="key_trust_already_verified">Этот ключ уже подтверждён!</string>
<string name="key_trust_it_is_yours">Это один из ваших ключей!</string>
<string name="key_trust_revoked">Этот ключ отозван владельцем. Вы не должны доверять ему.</string>
<string name="key_trust_expired">У этого ключа истек срок годности. Вы не должны доверять ему.</string>
<string name="key_trust_start_cloud_search">Начать поиск</string>
<!--keybase proof stuff-->
- <string name="keybase_narrative_twitter">Отправить в Твиттер как</string>
- <string name="keybase_narrative_github">Это известно на GitHub как</string>
- <string name="keybase_narrative_dns">Управлять доменным именем(именами)</string>
- <string name="keybase_narrative_reddit">Опубликовать на Reddit как</string>
- <string name="keybase_narrative_hackernews">Опубликовать на Hacker News как</string>
- <string name="keybase_narrative_unknown">Неизвестный тип доказательства</string>
<string name="keybase_proof_failure">К сожалению это доказательство не может быть верифицировано.</string>
<string name="keybase_unknown_proof_failure">Неопознанная проблема с проверкой доказательства </string>
<string name="keybase_problem_fetching_evidence">Проблема с доказательством</string>
<string name="keybase_key_mismatch">Отпечаток ключа не совпадает с таковым в доказательной записи.</string>
+ <string name="keybase_dns_query_failure">Сбой получения записи DNS TXT</string>
<string name="keybase_no_prover_found">Не найдено проверки доказательства для </string>
<string name="keybase_message_payload_mismatch">Расшифрованная доказательная запись не соответствует ожидаемому значению</string>
+ <string name="keybase_message_fetching_data">Получение подтверждения</string>
+ <string name="keybase_proof_succeeded">Подтверждение успешно проверено!</string>
+ <string name="keybase_dns_proof">Запись DNS TXT</string>
+ <string name="keybase_web_site_proof">Текстовый файл</string>
<string name="keybase_reddit_proof">JSON file</string>
+ <string name="keybase_verify">Подтвердить</string>
<!--Edit key-->
<string name="edit_key_action_change_passphrase">Изменить пароль</string>
<string name="edit_key_action_add_identity">Добавить идентификатор</string>
@@ -452,28 +538,39 @@
</string-array>
<string name="edit_key_edit_user_id_revoked">Этот идентификатор был отозван. Это не может быть отменено.</string>
<string name="edit_key_edit_subkey_title">Выберите действие!</string>
- <string-array name="edit_key_edit_subkey">
- <item>Изменить срок годности</item>
- <item>Отозвать доп. ключ</item>
- <item>Отделить доп. ключ</item>
- <item>"Move Subkey to Yubikey / Smart Card"</item>
- </string-array>
<string name="edit_key_new_subkey">новый доп. ключ</string>
<string name="edit_key_select_flag">Пожалуйста, выберите хотя бы один флаг!</string>
<string name="edit_key_error_add_identity">Добавьте хотя бы один идентификатор!</string>
<string name="edit_key_error_add_subkey">Добавьте хотя бы один доп. ключ!</string>
<!--Create key-->
+ <string name="create_key_upload">Синхронизировать с облаком</string>
<string name="create_key_empty">Это обязательне поле</string>
- <string name="create_key_passphrases_not_equal">Пароли не совпадают.</string>
+ <string name="create_key_passphrases_not_equal">Пароли не совпадают</string>
<string name="create_key_final_text">Вы указали следующие данные:</string>
<string name="create_key_final_robot_text">Создание ключа займет некоторое время, можете пока выпить чашечку кофе...</string>
<string name="create_key_rsa">(3 доп. ключа, RSA, 4096 bit)</string>
<string name="create_key_custom">(произвольная конфигурация ключа)</string>
+ <string name="create_key_name_text">Выберите имя для данного ключа. Это может быть полное имя, например, \'Иван Петров\', или сокращенно, как например, \'Ванька\'.</string>
+ <string name="create_key_email_text">Введите Ваш главный адрес эл.почты, используемый для безопасной переписки.</string>
+ <string name="create_key_passphrase_text">Выберите надежный пароль. Он защитит Ваш ключ, в случае кражи вашего устройства.</string>
+ <string name="create_key_hint_full_name">Полное имя или псевдоним</string>
<string name="create_key_edit">Изменить конфигурацию ключа</string>
+ <string name="create_key_add_email">Введите адрес эл.почты</string>
+ <string name="create_key_email_already_exists_text">Почтовый адрес уже был добавлен</string>
+ <string name="create_key_email_invalid_email">Неправильный формат почтового адреса</string>
<!--View key-->
<string name="view_key_revoked">Аннулирован: Ключ не должен использоваться когда-либо в будущем!</string>
+ <string name="view_key_expired">Срок годности истёк: Контакт должен продлить срок!</string>
<string name="view_key_expired_secret">Срок годности истёк: Вы можете продлить срок, изменив ключ!</string>
<string name="view_key_my_key">Мой ключ</string>
+ <string name="view_key_verified">Подтверждённый ключ</string>
+ <string name="view_key_unverified">Не подтверждён: Сканируйте QR для подтверждения!</string>
+ <string name="view_key_fragment_no_system_contact">&lt;нет&gt;</string>
+ <!--Add/Edit keyserver-->
+ <string name="add_keyserver_dialog_title">Добавить сервер ключей</string>
+ <string name="add_keyserver_verified">Сервер ключей подтверждён!</string>
+ <string name="add_keyserver_without_verification">Сервер ключей добавлен без подтверждения.</string>
+ <string name="add_keyserver_invalid_url">Неправильный адрес!</string>
<!--Navigation Drawer-->
<string name="nav_keys">Ключи</string>
<string name="nav_encrypt_decrypt">Зашифровать/Расшифровать</string>
@@ -589,10 +686,8 @@
<string name="msg_is_pubring_generate">Формирование публичной связки из секретной связки</string>
<string name="msg_is_subkey_nonexistent">Доп. ключ %s недоступен в секретном ключе</string>
<string name="msg_is_subkey_ok">Секретный доп. ключ %s отмечен как доступный</string>
- <string name="msg_is_subkey_empty">Секретный доп. ключ %s отмечен как доступный, с пустым паролем</string>
<string name="msg_is_subkey_pin">Секретный доп. ключ %s отмечен как доступный, с PIN</string>
<string name="msg_is_subkey_stripped">Секретный доп. ключ %s отмечен как отделённый</string>
- <string name="msg_is_subkey_divert">Секретный доп. ключ %s отмечен как \'переключенный на смарт-карту/NFC\'</string>
<string name="msg_is_success_identical">Связка ключей не содержит новых данных, нечего делать</string>
<string name="msg_is_success">Успешно добавлена связка секретных ключей</string>
<!--Keyring Canonicalization log entries-->
@@ -642,6 +737,7 @@
<string name="msg_kc_uid_no_cert">Нет допустимого самостоятельного сертификата для ID \'%s\', удаление из связки</string>
<string name="msg_kc_uid_remove">Удаление неверного ID \'%s\'</string>
<string name="msg_kc_uid_dup">Удаление повторяющегося ID \'%s\'. Связка содержит их два. Это может привести к отсутствию сертификатов!</string>
+ <string name="msg_kc_uid_warn_encoding">ID пользователя не соответствует UTF-8!</string>
<string name="msg_kc_uat_jpeg">Обработка атрибута пользователя типа JPEG</string>
<string name="msg_kc_uat_unknown">Обработка атрибута пользователя неизвестного типа</string>
<string name="msg_kc_uat_bad_err">Удаление плохого самостоятельного сертификата для атрибута пользователя</string>
@@ -656,6 +752,7 @@
<string name="msg_kc_uat_revoke_old">Удаление устаревшего сертификата аннулирования для атрибута пользователя</string>
<string name="msg_kc_uat_no_cert">Нет допустимого самостоятельного сертификата для атрибута пользователя, удаление из связки</string>
<string name="msg_kc_uat_remove">Удаление неверного атрибута пользователя</string>
+ <string name="msg_kc_uat_warn_encoding">ID пользователя не соответствует UTF-8!</string>
<!--Keyring merging log entries-->
<string name="msg_mg_error_secret_dummy">Найден новый публичный доп. ключ, но фиктивное создание секретного доп. ключа не поддерживается!</string>
<string name="msg_mg_error_heterogeneous">Попытка объединить связки с различными отпечатками!</string>
@@ -688,13 +785,16 @@
<string name="msg_mf_error_integrity">Внутренняя ошибка, сбой проверки целостности!</string>
<string name="msg_mf_error_master_none">Не найден основной сертификат! (Все отозваны?)</string>
<string name="msg_mf_error_revoked_primary">Аннулированные идентификаторы не могут быть основными!</string>
+ <string name="msg_mf_error_noop">Выполнять нечего!</string>
<string name="msg_mf_error_pgp">Внутренняя ошибка OpenPGP!</string>
<string name="msg_mf_error_sig">Ошибка подписи!</string>
+ <string name="msg_mf_error_subkey_missing">Попытка работы с отсутствующим доп. ключом %s!</string>
<string name="msg_mf_master">Изменение основного сертификата</string>
- <string name="msg_mf_passphrase_key">Перешифрование доп. ключа %s новым паролем</string>
+ <string name="msg_mf_passphrase">Изменение пароля для связки ключей</string>
+ <string name="msg_mf_passphrase_empty_retry">Ошибка установки нового пароля, пробую снова используя старый пустой пароль</string>
<string name="msg_mf_primary_new">Создание нового сертификата для основного идентификатора</string>
<string name="msg_mf_subkey_change">Изменение доп. ключа %s</string>
- <string name="msg_mf_error_subkey_missing">Попытка работы с отсутствующим доп. ключом %s!</string>
+ <string name="msg_mf_require_passphrase">Для действий необходим пароль</string>
<string name="msg_mf_subkey_new">Добавление нового доп. ключа типа %s</string>
<string name="msg_mf_subkey_new_id">Идентификатор нового доп. ключа: %s</string>
<string name="msg_mf_error_past_expiry">Срок годности не может быть в прошлом!</string>
@@ -707,6 +807,8 @@
<!--Consolidate-->
<string name="msg_con">Консолидация базы данных</string>
<string name="msg_con_error_bad_state">Консолидация началась но база не кэширована! Это программная ошибка, пожалуйста, сообщите об этом.</string>
+ <string name="msg_con_save_secret">Сохранение секретной связки ключей</string>
+ <string name="msg_con_save_public">Сохранение публичной связки ключей</string>
<string name="msg_con_db_clear">Очистка базы данных</string>
<string name="msg_con_error_db">Ошибка открытия базы данных!</string>
<string name="msg_con_error_io_public">Ошибка записи публичных ключей в кэш!</string>
@@ -714,30 +816,31 @@
<string name="msg_con_error_public">Ошибка переимпортирования публичных ключей!</string>
<string name="msg_con_error_secret">Ошибка переимпортирования приватных ключей!</string>
<!--Edit Key (higher level than modify)-->
+ <string name="msg_ed">Выполнение операции ключа</string>
+ <string name="msg_ed_caching_new">Кэширование нового пароля</string>
<string name="msg_ed_error_key_not_found">Ключ не найден!</string>
<string name="msg_ed_success">Операция с ключом успешна!</string>
<!--Promote key-->
- <string name="msg_pr_error_already_secret">Этот ключ уже приватный!</string>
<string name="msg_pr_error_key_not_found">Ключ не найден!</string>
<!--Other messages used in OperationLogs-->
- <string name="msg_ek_error_divert">Редактирование NFC ключей (еще) не поддерживается!</string>
<string name="msg_ek_error_not_found">Ключ не найден!</string>
<!--Messages for DecryptVerify operation-->
<string name="msg_dc_clear_decompress">Распаковка сжатых данных</string>
<string name="msg_dc_clear_meta_size_unknown">Неизвестный размер файла</string>
<string name="msg_dc_clear_signature_bad">Проверка подписи НЕ ПРОЙДЕНА!</string>
- <string name="msg_dc_insecure_hash_algo">Неподдерживаемый, и потенциально небезопасный алгоритм хэширования!</string>
<string name="msg_dc_clear_signature_check">Проверка подписи данных</string>
<string name="msg_dc_clear_signature_ok">Проверка подписи ПРОЙДЕНА</string>
<string name="msg_dc_clear_signature">Сохранение данных подписи</string>
- <string name="msg_dc_error_bad_passphrase">Ошибка разблокирования ключа, неверная фраза-пароль!</string>
+ <string name="msg_dc_error_bad_passphrase">Ошибка разблокировки ключа, неправильный пароль!</string>
<string name="msg_dc_error_extract_key">Неизвестная ошибка разблокировения ключа!</string>
<string name="msg_dc_error_no_data">Зашифрованные данные не найдены!</string>
<string name="msg_dc_error_no_key">Зашифрованные данные с известным приватным ключом не найдены!</string>
<string name="msg_dc_ok">Расшифрование/проверка закончена</string>
- <string name="msg_dc_pass_cached">Использование фразы-пароля из кэша</string>
+ <string name="msg_dc_pass_cached">Применяю кэшированный пароль</string>
+ <string name="msg_dc_pending_passphrase">Требуется пароль, жду действий пользователя...</string>
+ <string name="msg_dc">Расшифровка началась...</string>
+ <string name="msg_dc_sym">Обнаружена симметрично зашифрованная информация</string>
<string name="msg_dc_unlocking">Разблокировка секретного ключа</string>
- <string name="msg_dc_insecure_symmetric_encryption_algo">Был использован потенциально небезопасный алгоритм шифрования!</string>
<!--Messages for VerifySignedLiteralData operation-->
<string name="msg_vl_clear_signature_check">Проверка подписи данных</string>
<string name="msg_vl_ok">ОК</string>
@@ -755,14 +858,17 @@
<string name="msg_pse_clearsign_only">Подписание пустого текста не поддерживается!</string>
<string name="msg_pse_compressing">Подготовка сжатия</string>
<string name="msg_pse_encrypting">Шифрование данных</string>
- <string name="msg_pse_error_bad_passphrase">Неправильный пароль!</string>
- <string name="msg_pse_error_hash_algo">Запрашиваемый алгоритм хеширования не поддерживается этим ключом!</string>
+ <string name="msg_pse_error_bad_passphrase">Неверный пароль!</string>
<string name="msg_pse_error_io">Обнаружена исключительная ситуация ввода\вывода во время выполнения операции!</string>
<string name="msg_pse_error_key_sign">Выбранным ключом подписи нельзя подписать данные! </string>
<string name="msg_pse_error_sign_key">Ошибка при выборке ключа подписи!</string>
<string name="msg_pse_error_nfc">Ошибка данных NFC!</string>
- <string name="msg_pse_error_no_passphrase">Парольных фраз не найдено!</string>
<string name="msg_pse_error_pgp">Внутренняя ошибка OpenPGP!</string>
+ <string name="msg_pse_key_ok">Шифрование для ключа: %s</string>
+ <string name="msg_pse_ok">Подпись/Шифрование успешно произведены!</string>
+ <string name="msg_pse_pending_passphrase">Требуется пароль, жду действий пользователя...</string>
+ <string name="msg_pse">Подпись и/или шифрование начаты</string>
+ <string name="msg_pse_symmetric">Подготовка симметричного шифрования</string>
<string name="msg_crt_certifying">Генерация сертификатов</string>
<string name="msg_crt_error_master_not_found">Основной ключ не найден!</string>
<string name="msg_crt_error_nothing">Нет сертифицированных ключей!</string>
@@ -788,21 +894,23 @@
<string name="msg_del_error_empty">Нет данных для удаления!</string>
<string name="msg_del_error_multi_secret">Секретные ключи можно удалять только по одному!</string>
<string name="msg_acc_saved">Аккаунт сохранен</string>
+ <string name="msg_download_success">Загрузка завершена!</string>
<plurals name="error_import_non_pgp_part">
<item quantity="one">часть загруженного файла содержит данные OpenPGP, но это не ключ</item>
<item quantity="few">части загруженного файла содержат данные OpenPGP, но это не ключ</item>
<item quantity="many">части загруженного файла содержат данные OpenPGP, но это не ключ</item>
<item quantity="other">части загруженного файла содержат данные OpenPGP, но это не ключ</item>
</plurals>
+ <!--Messages for Keybase Verification operation-->
<!--Messages for Export Log operation-->
+ <string name="msg_export_log_start">Экспорт журнала...</string>
<string name="msg_export_log_error_fopen">Ошибка открытия файла</string>
<string name="msg_export_log_error_no_file">Не выбрано имя файла!</string>
<string name="msg_export_log_error_writing">Ошибка записи в файл!</string>
<string name="msg_export_log_success">Лог успешно экспортирован!</string>
<!--PassphraseCache-->
- <string name="passp_cache_notif_keys">Кэшированные пароли:</string>
- <string name="passp_cache_notif_clear">Очистить кэш</string>
<string name="passp_cache_notif_pwd">Пароль</string>
+ <!--Keyserver sync-->
<!--First Time-->
<string name="first_time_text1">Верните вашу приватность с помощью OpenKeychain!</string>
<string name="first_time_create_key">Создать свой ключ</string>
@@ -819,25 +927,39 @@
<string name="label_cert_type">Тип</string>
<string name="error_key_not_found">Ключ не найден!</string>
<string name="error_key_processing">Ошибка обработки ключа!</string>
- <string name="key_no_passphrase">Без фразы-пароля</string>
<string name="key_unavailable">недоступно</string>
<string name="title_view_cert">Просмотреть детали сертификации</string>
<string name="unknown_algorithm">неизв.</string>
<string name="can_sign_not">не для подписания</string>
<string name="error_no_encrypt_subkey">Нет доп. ключа для шифрования!</string>
<string name="contact_show_key">Показать ключ (%s)</string>
+ <string name="error_no_file_selected">Выберите хотя бы один файл для шифрования!</string>
+ <string name="error_empty_text">Введите текст для шифрования!</string>
<string name="key_colon">Ключ:</string>
<string name="btn_start_exchange">Начать обмен</string>
+ <!--Android Account-->
<!--Passphrase wizard-->
<!--TODO: rename all the things!-->
<string name="title_unlock_method">Выберите метод разблокировки</string>
- <!--<string name="enter_passphrase_twice">Enter passphrase twice</string>-->
+ <!--<string name="enter_passphrase_twice">Enter password twice</string>-->
<string name="enter_passphrase">Введите пароль</string>
<string name="passphrase">Пароль</string>
+ <string name="noPassphrase">Без пароля</string>
+ <string name="no_passphrase_set">Пароль не установлен</string>
+ <string name="passphrases_match">Пароли совпадают</string>
+ <string name="passphrase_saved">Пароль сохранён</string>
<string name="passphrase_invalid">Неверный пароль</string>
<string name="passphrase_again">Еще раз</string>
+ <string name="lockpattern">Рисунок блокировки</string>
+ <string name="lockpatternNFC">NFC + рисунок блокировки</string>
+ <string name="unlock_method">Метод разблокировки</string>
+ <string name="set_passphrase">Задать пароль</string>
<string name="nfc_title">NFC</string>
<!--<string name="nfc_text">Please place a NFC tag near your device</string>-->
<string name="unlocked">Разблокирован</string>
<string name="nfc_settings">Настройки</string>
+ <string name="snack_yubikey_view">Просмотр</string>
+ <string name="snack_yubikey_import">Импорт</string>
+ <string name="yubikey_key_holder">Владелец ключа:</string>
+ <string name="error_nfc">Ошибка NFC: %s</string>
</resources>
diff --git a/OpenKeychain/src/main/res/values-sl/strings.xml b/OpenKeychain/src/main/res/values-sl/strings.xml
index ab3f009df..32f63b9b4 100644
--- a/OpenKeychain/src/main/res/values-sl/strings.xml
+++ b/OpenKeychain/src/main/res/values-sl/strings.xml
@@ -18,8 +18,6 @@
<string name="title_encrypt_to_file">Šifriraj v datoteko</string>
<string name="title_decrypt_to_file">Dešifriraj v datoteko</string>
<string name="title_import_keys">Uvozi ključe</string>
- <string name="title_export_key">Izvozi kluč</string>
- <string name="title_export_keys">Izvozi ključe</string>
<string name="title_key_not_found">Ključ ni bil najden</string>
<string name="title_send_key">Naloži na strežnik</string>
<string name="title_certify_key">Potrdi ključ</string>
@@ -70,7 +68,6 @@
<!--menu-->
<string name="menu_preferences">Nastavitve</string>
<string name="menu_help">Pomoč</string>
- <string name="menu_export_key">Izvozi v datoteko</string>
<string name="menu_delete_key">Izbriši ključ</string>
<string name="menu_manage_keys">Upravljanje mojih ključev</string>
<string name="menu_search">Išči</string>
@@ -120,6 +117,7 @@
<string name="label_enable_compression">Omogoči kompresijo</string>
<string name="label_encrypt_filenames">Šifriraj imena datotek</string>
<string name="label_hidden_recipients">Skrij prejemnike</string>
+ <!--label shown in Android settings under the OpenKeychain account-->
<!--Proxy Preferences-->
<!--proxy type choices and values-->
<!--OrbotHelper strings-->
@@ -180,7 +178,6 @@
<string name="select_encryption_key">Izberite vsaj en šifrirni ključ.</string>
<string name="specify_file_to_encrypt_to">Določite datoteko, v katero želite šifrirati vsebino.\nPOZOR: če datoteka že obstaja, bo prepisana.</string>
<string name="specify_file_to_decrypt_to">Določite datoteko, v katero želite dešifrirati vsebino.\nPOZOR: če datoteka že obstaja, bo prepisana.</string>
- <string name="specify_backup_dest">Določite datoteko, v katero želite izvoziti vsebino.\nPOZOR: če datoteka že obstaja, bo prepisana.</string>
<string name="key_deletion_confirmation_multi">Ali zares želite izbrisati vse izbrane ključe?</string>
<string name="secret_key_deletion_confirmation">Po izbrisu ne bo več mogoče prebirati sporočil šifriranih s tem ključem! Izgubljene bodo tudi vse z njim narejene potrditve.</string>
<string name="public_key_deletetion_confirmation">Izbrišem ključ \'%s\'?</string>
@@ -401,6 +398,7 @@
</plurals>
<string name="delete_nothing">Ničesar ni za izbrisati.</string>
<string name="delete_cancelled">Operacija brisanja prekinjena.</string>
+ <!--Revoke result toast (snackbar)-->
<!--Certify result toast-->
<plurals name="certify_keys_ok">
<item quantity="one">Uspešno potrjen ključ%2$s.</item>
@@ -436,7 +434,6 @@
<string name="api_settings_start">Zaženi aplikacijo</string>
<string name="api_settings_delete_account">Izbriši račun</string>
<string name="api_settings_package_name">Ime paketa</string>
- <string name="api_settings_package_certificate">SHA-256 podpisa paketa</string>
<string name="api_settings_allowed_keys">Dovoljeni ključi</string>
<string name="api_settings_settings">Nastavitve</string>
<string name="api_settings_key">Ključ računa:</string>
@@ -447,8 +444,6 @@
<string name="api_register_allow">Dovoli dostop</string>
<string name="api_register_disallow">Zavrni dostop</string>
<string name="api_register_error_select_key">Izberite ključ!</string>
- <string name="api_select_pub_keys_missing_text">Za te identitete ni bil najden noben ključ:</string>
- <string name="api_select_pub_keys_dublicates_text">Za te identitete obstaja več ključev:</string>
<string name="api_select_pub_keys_text">Preverite seznam prejemnikov!</string>
<string name="api_select_pub_keys_text_no_user_ids">Prosim, izberite prejemnike!</string>
<string name="api_error_wrong_signature">Preverjanje podpisa ni uspelo! Ste namestili to aplikacijo iz drugega vira? Če ste prepričani, da to ni napad, prekličite registracijo te aplikacije v OpenKeychain in jo izvedite znova.</string>
@@ -456,6 +451,9 @@
<!--Share-->
<string name="share_qr_code_dialog_title">Deli s kodo QR</string>
<string name="share_nfc_dialog">Deli preko NFC</string>
+ <!--retry upload dialog-->
+ <!--Delete or revoke private key dialog-->
+ <!--Delete Or Revoke Dialog spinner-->
<!--Key list-->
<plurals name="key_list_selected_keys">
<item quantity="one">Izbran 1 ključ.</item>
@@ -500,14 +498,6 @@
<string name="key_trust_results_prefix">Keybase.io ponuja \"dokazilo\", da je lastnik tega kluča:</string>
<string name="key_trust_header_text">Pozor: Dokazila Keybase.io v aplikaciji OpenKeychain so eksperimantalne narave. Za večjo zanesljivost priporočamo, da dodatno skenirate kode QR ali izmenjate ključe preko NFC.</string>
<!--keybase proof stuff-->
- <string name="keybase_narrative_twitter">Objavlja na Twitterju kot</string>
- <string name="keybase_narrative_github">Prisoten na GitHub-u kot</string>
- <string name="keybase_narrative_dns">Upravlja domeno(e)</string>
- <string name="keybase_narrative_web_site">Objavlja na spletni strani(eh)</string>
- <string name="keybase_narrative_reddit">Objavlja na Reddit-u kot</string>
- <string name="keybase_narrative_coinbase">Prisoten na Coinbase-u kot</string>
- <string name="keybase_narrative_hackernews">Objavlja na Hacker News kot</string>
- <string name="keybase_narrative_unknown">Neznano dokazilo</string>
<string name="keybase_proof_failure">Dokazila se žal ne da preveriti.</string>
<string name="keybase_unknown_proof_failure">Neznan problem pri pregledovalniku dokazil</string>
<string name="keybase_problem_fetching_evidence">Problem z dokazilom</string>
@@ -818,6 +808,7 @@
<!--Messages for Keybase Verification operation-->
<!--Messages for Export Log operation-->
<!--PassphraseCache-->
+ <!--Keyserver sync-->
<!--First Time-->
<string name="first_time_text1">Vzemite si svojo zasebnost nazaj v svoje roke z OpenKeychain!</string>
<string name="first_time_skip">Preskoči nastavitev</string>
@@ -840,6 +831,7 @@
<string name="error_no_encrypt_subkey">Ni nobenega podključa za šifriranje!</string>
<string name="contact_show_key">Prikaži ključ (%s)</string>
<string name="key_colon">Ključ:</string>
+ <!--Android Account-->
<!--Passphrase wizard-->
<!--TODO: rename all the things!-->
<!--<string name="enter_passphrase_twice">Enter password twice</string>-->
diff --git a/OpenKeychain/src/main/res/values-sr/strings.xml b/OpenKeychain/src/main/res/values-sr/strings.xml
index 9d5121c44..5c6d03950 100644
--- a/OpenKeychain/src/main/res/values-sr/strings.xml
+++ b/OpenKeychain/src/main/res/values-sr/strings.xml
@@ -4,66 +4,64 @@
http://developer.android.com/guide/topics/resources/string-resource.html (scroll down to "Escaping apostrophes and quotes").-->
<string name="app_name">Отворени кључарник</string>
<!--title-->
- <string name="title_select_recipients">Изаберите кључ</string>
- <string name="title_select_secret_key">Изаберите ваш кључ</string>
- <string name="title_encrypt_text">Шифруј текст</string>
- <string name="title_encrypt_files">Шифруј фајлове</string>
+ <string name="title_encrypt_text">Шифруј</string>
+ <string name="title_encrypt_files">Шифруј</string>
<string name="title_decrypt">Дешифруј</string>
- <string name="title_unlock">Откључај кључ</string>
<string name="title_add_subkey">Додај поткључ</string>
<string name="title_edit_key">Уреди кључ</string>
<string name="title_preferences">Поставке</string>
- <string name="title_cloud_search_preferences">Поставке клауд претраге</string>
<string name="title_api_registered_apps">Апликације</string>
- <string name="title_key_server_preference">Сервери кључева</string>
- <string name="title_change_passphrase">Измени лозинку</string>
+ <string name="title_key_server_preference">ОпенПГП сервери кључева</string>
+ <string name="title_change_passphrase">Измена лозинке</string>
<string name="title_share_fingerprint_with">Подели отисак са…</string>
- <string name="title_share_key">Подели кључ са…</string>
- <string name="title_share_file">Подели фајл са…</string>
- <string name="title_share_message">Подели поруку са…</string>
+ <string name="title_share_key">Подели кључ преко…</string>
+ <string name="title_share_file">Подели фајл преко…</string>
+ <string name="title_share_message">Подели текст преко…</string>
<string name="title_encrypt_to_file">Шифруј у фајл</string>
<string name="title_decrypt_to_file">Дешифруј у фајл</string>
<string name="title_import_keys">Увези кључеве</string>
- <string name="title_add_keys">Додај кључеве</string>
- <string name="title_export_key">Извези кључ</string>
- <string name="title_export_keys">Извези кључеве</string>
+ <string name="title_export_key">Направи резерву кључа</string>
+ <string name="title_export_keys">Направи резерву кључева</string>
<string name="title_key_not_found">Кључ није нађен</string>
<string name="title_send_key">Отпреми на сервер кључева</string>
- <string name="title_certify_key">Овери идентитете</string>
+ <string name="title_certify_key">Потврда кључа</string>
<string name="title_key_details">Детаљи кључа</string>
<string name="title_help">Помоћ</string>
<string name="title_log_display">Дневник</string>
- <string name="title_create_key">Направи кључ</string>
<string name="title_exchange_keys">Размена кључева</string>
- <string name="title_advanced_key_info">Напредни подаци о кључу</string>
- <string name="title_keys">Кључеви</string>
+ <string name="title_advanced_key_info">Додатни подаци</string>
+ <string name="title_delete_secret_key">Обрисати ВАШ кључ „%s“?</string>
+ <string name="title_export_log">Извоз дневника</string>
+ <string name="title_manage_my_keys">Управљање мојим кључевима</string>
<!--section-->
<string name="section_user_ids">Идентитети</string>
+ <string name="section_yubikey">Јубикључ</string>
+ <string name="section_linked_system_contact">Повезани контакт</string>
+ <string name="section_should_you_trust">Смијете ли да се поуздате у овај кључ?</string>
+ <string name="section_proof_details">Овера доказа</string>
+ <string name="section_cloud_evidence">Докази са клауда</string>
<string name="section_keys">Поткључеви</string>
<string name="section_cloud_search">Претрага клауда</string>
- <string name="section_general">Опште</string>
- <string name="section_defaults">Подразумевано</string>
- <string name="section_advanced">Напредно</string>
- <string name="section_passphrase_cache">Кеширај лозинку</string>
- <string name="section_certify">Овера</string>
+ <string name="section_passphrase_cache">Руковање лозинком/ПИНом</string>
+ <string name="section_proxy_settings">Поставке проксија</string>
+ <string name="section_gui">Сучеље</string>
+ <string name="section_sync_settings">Поставке синхронизације</string>
+ <string name="section_certify">Потврда</string>
<string name="section_actions">Радње</string>
<string name="section_share_key">Кључ</string>
- <string name="section_certification_key">Ваш кључ за оверу</string>
- <string name="section_upload_key">Синхронизуј кључ</string>
<string name="section_key_server">Сервер кључева</string>
<string name="section_fingerprint">Отисак</string>
- <string name="section_key_to_certify">Кључ за оверавање</string>
- <string name="section_decrypt_files">Фајлови</string>
- <string name="section_decrypt_text">Текст</string>
- <string name="section_certs">Сертификати</string>
<string name="section_encrypt">Шифровање</string>
- <string name="section_decrypt">Дешифровање</string>
+ <string name="section_decrypt">Дешифруј/овери</string>
+ <string name="section_current_expiry">Текући истек</string>
+ <string name="section_new_expiry">Нови истек</string>
<!--button-->
<string name="btn_decrypt_verify_file">Дешифруј, овери и сачувај фајл</string>
- <string name="btn_decrypt_verify_message">Дешифруј и овери поруку</string>
- <string name="btn_encrypt_file">Шифруј и сачувај фајл</string>
<string name="btn_encrypt_share_file">Шифруј и подели фајл</string>
+ <string name="btn_encrypt_save_file">Шифруј и сачувај фајл</string>
+ <string name="btn_save_file">Сачувај фајл</string>
<string name="btn_save">Сачувај</string>
+ <string name="btn_view_log">Прикажи дневник</string>
<string name="btn_do_not_save">Одустани</string>
<string name="btn_delete">Обриши</string>
<string name="btn_no_date">Не истиче</string>
@@ -73,37 +71,41 @@
<string name="btn_back">Назад</string>
<string name="btn_no">Не</string>
<string name="btn_match">Отисци се поклапају</string>
- <string name="btn_lookup_key">Потражи кључ</string>
- <string name="btn_share_encrypted_signed">Шифруј и подели поруку</string>
+ <string name="btn_share_encrypted_signed">Шифруј и подели текст</string>
+ <string name="btn_copy_encrypted_signed">Шифруј и копирај текст</string>
<string name="btn_view_cert_key">Прикажи кључ за оверавање</string>
<string name="btn_create_key">Направи кључ</string>
<string name="btn_add_files">Додај фајл(ове)</string>
- <string name="btn_add_share_decrypted_text">Подели дешифрован текст</string>
- <string name="btn_decrypt_clipboard">Дешифруј текст са клипборда</string>
- <string name="btn_decrypt_and_verify">и овери потписе</string>
- <string name="btn_decrypt_files">Дешифруј фајлове</string>
+ <string name="btn_share_decrypted_text">Подели дешифровани текст</string>
+ <string name="btn_copy_decrypted_text">Копирај дешифровани текст</string>
+ <string name="btn_decrypt_clipboard">Учитај са клипборда</string>
+ <string name="btn_decrypt_files">Изабери фајл</string>
<string name="btn_encrypt_files">Шифруј фајлове</string>
<string name="btn_encrypt_text">Шифруј текст</string>
+ <string name="btn_add_email">Додај додатну е-адресу</string>
+ <string name="btn_unlock">Откључај</string>
+ <string name="btn_add_keyserver">Додај</string>
+ <string name="btn_save_default">Сачувај за подразумевано</string>
+ <string name="btn_saved">Сачувано!</string>
<!--menu-->
<string name="menu_preferences">Поставке</string>
<string name="menu_help">Помоћ</string>
- <string name="menu_export_key">Извези у фајл</string>
+ <string name="menu_export_key">Направи резерву у фајл</string>
<string name="menu_delete_key">Обриши кључ</string>
- <string name="menu_manage_keys">Направи ми кључ</string>
- <string name="menu_import_existing_key">Увези из фајла</string>
+ <string name="menu_manage_keys">Управљај мојим кључевима</string>
<string name="menu_search">Претрага</string>
<string name="menu_nfc_preferences">НФЦ поставке</string>
<string name="menu_beam_preferences">Поставке Снопа</string>
- <string name="menu_key_edit_cancel">Одустани</string>
<string name="menu_encrypt_to">Шифруј у…</string>
<string name="menu_select_all">Изабери све</string>
- <string name="menu_add_keys">Додај кључеве</string>
- <string name="menu_search_cloud">Клауд претрага</string>
<string name="menu_export_all_keys">Извези све кључеве</string>
- <string name="menu_advanced">Прикажи напредне податке</string>
- <string name="menu_certify_fingerprint">Овери поређењем отисака</string>
+ <string name="menu_update_all_keys">Ажурирај све кључеве</string>
+ <string name="menu_advanced">Додатни подаци</string>
+ <string name="menu_certify_fingerprint">Потврди поређењем отисака</string>
+ <string name="menu_export_log">Извези дневник</string>
+ <string name="menu_keyserver_add">Додај</string>
<!--label-->
- <string name="label_message">Порука</string>
+ <string name="label_message">Текст</string>
<string name="label_file">Фајл</string>
<string name="label_files">Фајл(ови)</string>
<string name="label_file_colon">Фајл:</string>
@@ -111,6 +113,7 @@
<string name="label_passphrase">Лозинка</string>
<string name="label_unlock">Откључавам…</string>
<string name="label_passphrase_again">Лозинка поново</string>
+ <string name="label_show_passphrase">Прикажи лозинку</string>
<string name="label_algorithm">Алгоритам</string>
<string name="label_ascii_armor">Аски оклоп фајла</string>
<string name="label_file_ascii_armor">Омогући Аски оклоп</string>
@@ -119,19 +122,20 @@
<string name="label_use_default_yubikey_pin">Користи подразумевани Јубикључ ПИН</string>
<string name="label_use_num_keypad_for_yubikey_pin">Користи бројчану тастатуру за Јубикључ ПИН</string>
<string name="label_label_use_default_yubikey_pin_summary">Користи подразумевани ПИН (123456) за приступ Јубикључевима преко НФЦ-а</string>
- <string name="label_asymmetric_from">Потписник:</string>
+ <string name="label_asymmetric_from">Потпиши помоћу:</string>
<string name="label_to">Шифруј за:</string>
- <string name="label_delete_after_encryption">Обриши фајл након шифровања</string>
+ <string name="label_delete_after_encryption">Обриши фајлове након шифровања</string>
<string name="label_delete_after_decryption">Обриши након дешифровања</string>
<string name="label_encryption_algorithm">Алгоритам шифровања</string>
<string name="label_hash_algorithm">Алгоритам хеша</string>
<string name="label_symmetric">Шифровање са лозинком</string>
- <string name="label_passphrase_cache_ttl">Време кеширања</string>
- <string name="label_passphrase_cache_subs">Кеширај по поткључу</string>
- <string name="label_message_compression">Компресија поруке</string>
+ <string name="label_passphrase_cache_ttl">Време памћења</string>
+ <string name="label_passphrase_cache_subs">Памти лозинке по поткључу</string>
+ <string name="label_message_compression">Компресија текста</string>
<string name="label_file_compression">Компресија фајла</string>
- <string name="label_keyservers">Сервери кључева</string>
+ <string name="label_keyservers">Изаберите ОпенПГП сервере кључева</string>
<string name="label_key_id">ИД кључа</string>
+ <string name="label_key_created">Кључ направљен %s</string>
<string name="label_creation">Створен</string>
<string name="label_expiry">Истиче</string>
<string name="label_usage">Употреба</string>
@@ -144,17 +148,58 @@
<string name="label_send_key">Синхронизуј са клаудом</string>
<string name="label_fingerprint">Отисак</string>
<string name="expiry_date_dialog_title">Датум истицања</string>
- <string name="label_first_keyserver_is_used">(Први сервер кључева на списку је приоритетан)</string>
+ <string name="label_keyservers_title">Сервери кључева</string>
+ <string name="label_keyserver_settings_hint">Превлачите за измену редоследа, тапните за уређивање/брисање</string>
+ <string name="label_selected_keyserver_title">Изабрани сервер кључева</string>
<string name="label_preferred">приоритетан</string>
+ <string name="label_enable_compression">Омогући компресију</string>
+ <string name="label_encrypt_filenames">Шифруј имена фајлова</string>
+ <string name="label_hidden_recipients">Сакриј примаоце</string>
+ <string name="label_verify_keyserver">Овери сервер кључева</string>
+ <string name="label_enter_keyserver_url">Унесите УРЛ сервера кључева</string>
+ <string name="label_keyserver_dialog_delete">Обриши сервер кључева</string>
+ <string name="label_theme">Тема</string>
+ <string name="pref_keyserver">ОпенПГП сервера кључева</string>
+ <string name="pref_keyserver_summary">Тражи кључеве на изабраним ОпенПГП серверима кључева (ХКП протокол)</string>
+ <string name="pref_keybase">keybase.io</string>
+ <string name="pref_keybase_summary">Тражи кључеве на keybase.io</string>
+ <string name="label_sync_settings_keyserver_title">Аутоматски ажурирај кључеве</string>
+ <string name="label_sync_settings_keyserver_summary_on">Кључеви старији од седам дана се ажурирају са пожељног сервера кључева</string>
+ <string name="label_sync_settings_keyserver_summary_off">Кључеви се не ажурирају аутоматски</string>
+ <string name="label_sync_settings_contacts_title">Синхронизуј контакте са кључевима</string>
+ <string name="label_sync_settings_contacts_summary_on">Кључеви повезани са контактима са поклапајућим е-адресама, одвија се у потпуности ван везе</string>
+ <string name="label_sync_settings_contacts_summary_off">Нови кључеви неће бити повезани са контактима</string>
+ <!--label shown in Android settings under the OpenKeychain account-->
+ <string name="keyserver_sync_settings_title">Аутоматски ажурирај кључеве</string>
+ <!--Proxy Preferences-->
+ <string name="pref_proxy_tor_title">Омогући Тор</string>
+ <string name="pref_proxy_tor_summary">Захтева Орбот</string>
+ <string name="pref_proxy_normal_title">Омогући други прокси</string>
+ <string name="pref_proxy_host_title">Домаћин проксија</string>
+ <string name="pref_proxy_host_err_invalid">Домаћин проксија не може бити празан</string>
+ <string name="pref_proxy_port_title">Порт проксија</string>
+ <string name="pref_proxy_port_err_invalid">Унесен неисправан број порта</string>
+ <string name="pref_proxy_type_title">Тип проксија</string>
+ <!--proxy type choices and values-->
+ <string name="pref_proxy_type_choice_http">ХТТП</string>
+ <string name="pref_proxy_type_choice_socks">СОЦКС</string>
+ <!--OrbotHelper strings-->
+ <string name="orbot_ignore_tor">Не користи Тор</string>
+ <!--InstallDialogFragment strings-->
+ <string name="orbot_install_dialog_title">Инсталирати Орбот да бих користио Тор?</string>
+ <string name="orbot_install_dialog_install">Инсталирај</string>
+ <string name="orbot_install_dialog_content">Морате имати Орбот инсталиран и активиран да бисте преусмерили саобраћај кроз њега. Желите ли да га инсталирате?</string>
+ <string name="orbot_install_dialog_cancel">Одустани</string>
+ <string name="orbot_install_dialog_ignore_tor">Не користи Тор</string>
+ <!--StartOrbotDialogFragment strings-->
+ <string name="orbot_start_dialog_title">Да покренем Орбот?</string>
+ <string name="orbot_start_dialog_content">Чини се да Орбот није покренут. Желите ли да га покренете и повежете са Тором?</string>
+ <string name="orbot_start_btn">Покрени Орбот</string>
+ <string name="orbot_start_dialog_start">Покрени Орбот</string>
+ <string name="orbot_start_dialog_cancel">Одустани</string>
+ <string name="orbot_start_dialog_ignore_tor">Не користи Тор</string>
<string name="user_id_no_name">&lt;нема имена&gt;</string>
<string name="none">&lt;нема&gt;</string>
- <string name="no_key">&lt;нема кључа&gt;</string>
- <string name="can_encrypt">може да шифрује</string>
- <string name="can_sign">може да потпише</string>
- <string name="can_certify">може да овери</string>
- <string name="can_certify_not">не може да овери</string>
- <string name="expired">истекао</string>
- <string name="revoked">опозван</string>
<plurals name="n_keys">
<item quantity="one">%d кључ</item>
<item quantity="few">%d кључа</item>
@@ -186,9 +231,10 @@
<string name="ecdh">ЕЦДХ</string>
<string name="ecdsa">ЕЦДСА</string>
<string name="filemanager_title_open">Отвори…</string>
- <string name="warning">Упозорење</string>
<string name="error">Грешка</string>
<string name="error_message">Грешка: %s</string>
+ <string name="theme_dark">Тамна</string>
+ <string name="theme_light">Светла</string>
<!--key flags-->
<string name="flag_certify">Овера</string>
<string name="flag_sign">Потпис</string>
@@ -203,19 +249,27 @@
<string name="passphrase_for">Унесите лозинку за „%s“</string>
<string name="pin_for">Унесите ПИН за „%s“</string>
<string name="yubikey_pin_for">Унесите ПИН за приступ Јубикључу за „%s“</string>
- <string name="nfc_text">Држите Јубикључ на полеђини вашег уређаја.</string>
- <string name="no_file_selected">Најпре изаберите фајл.</string>
+ <string name="nfc_text">Држите Јубикључ на НФЦ ознаци на полеђини вашег уређаја.</string>
+ <string name="nfc_wait">Држите Јубикључ на полеђини!</string>
+ <string name="nfc_finished">Склоните сада Јубикључ.</string>
+ <string name="nfc_try_again_text">Склоните сада Јубикључ и тапните на ПОКУШАЈ ПОНОВО.</string>
+ <string name="file_delete_confirmation_title">Обрисати оригиналне фајлове?</string>
+ <string name="file_delete_confirmation">Следећи фајлови ће бити обрисани:%s</string>
+ <string name="file_delete_successful">%1$d од %2$d фајлова је обрисано.%3$s</string>
+ <string name="no_file_selected">Ниједан фајл није изабран.</string>
<string name="encrypt_sign_successful">Потписивање и/или шифровање је успело.</string>
<string name="encrypt_sign_clipboard_successful">Потписивање и/или шифровање на клипборд је успело.</string>
- <string name="enter_passphrase_twice">Унесите лозинку два пута.</string>
<string name="select_encryption_key">Изаберите бар један кључ за шифровање.</string>
<string name="error_no_encryption_or_signature_key">Изаберите бар један кључ за шифровање или потписивање.</string>
- <string name="specify_file_to_encrypt_to">Одредите у који фајл да шифрујем.\nУПОЗОРЕЊЕ: Фајл ће бити пребрисан ако постоји.</string>
- <string name="specify_file_to_decrypt_to">Одредите у који фајл да дешифрујем.\nУПОЗОРЕЊЕ: Фајл ће бити пребрисан ако постоји.</string>
- <string name="specify_backup_dest">Одредите у који фајл да извезем.\nУПОЗОРЕЊЕ: Фајл ће бити пребрисан ако постоји.</string>
- <string name="key_deletion_confirmation_multi">Желите ли заиста да обришете све изабране јавне кључеве?\nОво не можете да поништите!</string>
- <string name="secret_key_deletion_confirmation">Желите ли заиста да обришете ТАЈНИ кључ „%s“?\nОво не можете да поништите!</string>
- <string name="public_key_deletetion_confirmation">Желите ли заиста да обришете јавни кључ „%s“??\nОво не можете да поништите!</string>
+ <string name="specify_file_to_encrypt_to">Одредите у који фајл да шифрујем.\nУПОЗОРЕЊЕ: Фајл ће бити пребрисан ако постоји!</string>
+ <string name="specify_file_to_decrypt_to">Одредите у који фајл да дешифрујем.\nУПОЗОРЕЊЕ: Фајл ће бити пребрисан ако постоји!</string>
+ <string name="specify_backup_dest">Биће направљена резерва без ваших кључева, наведите одредишни фајл.\nУПОЗОРЕЊЕ: Фајл ће бити пребрисан ако већ постоји!</string>
+ <string name="specify_backup_dest_single">Овај кључ ће бити подељен, наведите одредишни фајл.\nУПОЗОРЕЊЕ: Фајл ће бити пребрисан ако већ постоји!</string>
+ <string name="specify_backup_dest_secret_single">Биће направљена потпуна резерва вашег кључа, наведите одредишни фајл.\nУПОЗОРЕЊЕ: Фајл ће бити пребрисан ако већ постоји!</string>
+ <string name="specify_backup_dest_secret">Биће направљена потпуна резерва свих кључева укључујући и ваше, наведите одредишни фајл.\nУПОЗОРЕЊЕ: Фајл ће бити пребрисан ако већ постоји!</string>
+ <string name="key_deletion_confirmation_multi">Желите ли заиста да обришете све изабране кључеве?</string>
+ <string name="secret_key_deletion_confirmation">Након брисања нећете моћи да читате поруке шифроване овим кључем и изгубићете све потврде кључева направљене њиме!</string>
+ <string name="public_key_deletetion_confirmation">Да обришем кључ „%s“?</string>
<string name="also_export_secret_keys">Такође извези тајне кључеве</string>
<string name="reinstall_openkeychain">Наишли сте на познату грешку у Андроиду. Поново инсталирајте Отворени кључарник ако желите да повежете ваше контакте са кључевима.</string>
<string name="key_exported">Успешно извезен 1 кључ.</string>
@@ -223,6 +277,7 @@
<string name="no_keys_exported">Ниједан кључ није извезен.</string>
<string name="key_creation_el_gamal_info">Напомена: само поткључеви подржавају Елгамал.</string>
<string name="key_not_found">Нисам могао да нађем кључ %08X.</string>
+ <string name="specify_file_to_export_log_to">Наведите у који фајл да извезем.\nУПОЗОРЕЊЕ: Фајл ће бити пребрисан ако постоји.</string>
<plurals name="bad_keys_encountered">
<item quantity="one">%d лош тајни кључ игнорисан. Можда сте извезли са аргументом\n --export-secret-subkeys\nУместо тога извезите са\n --export-secret-keys\"</item>
<item quantity="few">%d лоша тајна кључа игнорисана. Можда сте извезли са аргументом\n --export-secret-subkeys\nУместо тога извезите са\n --export-secret-keys\"</item>
@@ -232,18 +287,20 @@
<string name="nfc_successful">Кључ је успешно послат преко НФЦ Снопа!</string>
<string name="key_copied_to_clipboard">Кључ је копиран на клипборд!</string>
<string name="fingerprint_copied_to_clipboard">Отисак је копиран на клипборд!</string>
- <string name="select_key_to_certify">Изаберите кључ који ће бити коришћен за оверавање!</string>
+ <string name="select_key_to_certify">Изаберите кључ којим ћете извршити потврду!</string>
<string name="key_too_big_for_sharing">Кључ је превелик да би се делио на овај начин!</string>
<string name="text_copied_to_clipboard">Текст је копиран на клипборд!</string>
<!--errors
no punctuation, all lowercase,
they will be put after "error_message", e.g. "Error: file not found"-->
- <string name="error_file_not_found">фајл није нађен</string>
+ <string name="error_file_delete_failed">нису обрисани. Обришите их ручно!</string>
+ <string name="error_file_added_already">„%s“ је већ додат.</string>
+ <string name="error_file_not_found">фајл није нађен</string>
<string name="error_no_secret_key_found">одговарајући тајни кључ није нађен</string>
<string name="error_external_storage_not_ready">спољашње складиште није спремно</string>
<string name="error_key_size_minimum512bit">величина кључа мора да буде најмање 512 бита</string>
<string name="error_unknown_algorithm_choice">непознат избор алгоритма</string>
- <string name="error_user_id_no_email">е-адреса није нађена</string>
+ <string name="error_user_id_no_email">није нађена е-адреса</string>
<string name="error_key_needs_a_user_id">потребан је бар један идентитет</string>
<string name="error_no_signature_passphrase">није задата лозинка</string>
<string name="error_no_signature_key">није задат кључ за потпис</string>
@@ -256,21 +313,25 @@
<string name="error_nfc_needed">НФЦ мора бити укључен!</string>
<string name="error_beam_needed">Бим мора бити укључен</string>
<string name="error_nothing_import">Нема нађених кључева!</string>
+ <string name="error_nothing_import_selected">Није изабран ниједан кључ за увоз!</string>
<string name="error_contacts_key_id_missing">Добављање ИД кључа из контаката није успело!</string>
<string name="error_generic_report_bug">Дошло је до опште грешке, направите нови извештај о грешци за Отворени кључарник.</string>
<!--results shown after decryption/verification-->
<string name="decrypt_result_no_signature">Није потписано</string>
<string name="decrypt_result_invalid_signature">Неисправан потпис!</string>
- <string name="decrypt_result_signature_uncertified">Потписник (није оверено!)</string>
- <string name="decrypt_result_signature_certified">Потписник</string>
- <string name="decrypt_result_signature_expired_key">Кључ је истекао!</string>
- <string name="decrypt_result_signature_revoked_key">Кључ је опозван!</string>
- <string name="decrypt_result_signature_missing_key">Непознат јавни кључ</string>
+ <string name="decrypt_result_insecure_cryptography">Неисправан потпис (небезбедна криптографија)!</string>
+ <string name="decrypt_result_signature_uncertified">Потписано <b>непотврђеним</b> кључем</string>
+ <string name="decrypt_result_signature_secret">Потписано вашим кључем</string>
+ <string name="decrypt_result_signature_certified">Потписано потврђеним кључем</string>
+ <string name="decrypt_result_signature_expired_key">Потписано <b>истеклим</b> кључем!</string>
+ <string name="decrypt_result_signature_revoked_key">Потписано <b>опозваним</b> кључем!</string>
+ <string name="decrypt_result_signature_missing_key">Потписано <b>непознатим јавним кључем</b></string>
<string name="decrypt_result_encrypted">Шифровано</string>
<string name="decrypt_result_not_encrypted">Није шифровано</string>
+ <string name="decrypt_result_insecure">Небезбедно шифровање</string>
<string name="decrypt_result_action_show">Прикажи</string>
<string name="decrypt_result_action_Lookup">Потражи</string>
- <string name="decrypt_invalid_text">Или је потпис неисправан или је кључ опозван/истекао. Не можете бити сигурни ко је написао текст. Желите ли свеједно да га прикажете?</string>
+ <string name="decrypt_invalid_text">Или је потпис неисправан или је кључ опозван. Не можете бити сигурни ко је написао текст. Желите ли свеједно да га прикажете?</string>
<string name="decrypt_invalid_button">Свестан сам ризика, прикажи!</string>
<!--Add keys-->
<string name="add_keys_my_key">Мој кључ:</string>
@@ -280,6 +341,8 @@
<string name="progress_cancelling">одустајем…</string>
<string name="progress_saving">уписујем…</string>
<string name="progress_importing">увозим…</string>
+ <string name="progress_revoking_uploading">Опозивам и отпремам кључ…</string>
+ <string name="progress_updating">Ажурирам кључеве…</string>
<string name="progress_exporting">извозим…</string>
<string name="progress_uploading">отпремам…</string>
<string name="progress_building_key">градим кључ…</string>
@@ -300,11 +363,14 @@
<string name="progress_modify_subkeystrip">огољавам поткључеве…</string>
<string name="progress_modify_subkeyadd">додајем поткључеве…</string>
<string name="progress_modify_passphrase">мењам лозинку…</string>
+ <string name="progress_modify_pin">мењам ПИН…</string>
+ <string name="progress_modify_admin_pin">мењам администраторски ПИН…</string>
<plurals name="progress_exporting_key">
<item quantity="one">извозим кључ…</item>
<item quantity="few">извозим кључеве…</item>
<item quantity="other">извозим кључеве…</item>
</plurals>
+ <string name="progress_start">припремам радњу…</string>
<string name="progress_extracting_signature_key">извлачим кључ потписа…</string>
<string name="progress_extracting_key">извлачим кључ…</string>
<string name="progress_preparing_streams">припремам токове…</string>
@@ -324,9 +390,10 @@
<string name="progress_deleting">бришем кључеве…</string>
<string name="progress_con_saving">учвршћивање: уписујем у кеш…</string>
<string name="progress_con_reimport">учвршћивање: поново увозим…</string>
+ <string name="progress_verifying_keyserver_url">оверавам сервер кључева…</string>
+ <string name="progress_starting_orbot">Покрећем Орбот…</string>
<!--action strings-->
- <string name="hint_keyserver_search_hint">Име/е-пошта/ИД кључа…</string>
- <string name="hint_cloud_search_hint">Име/е-пошта/доказ/кључ…</string>
+ <string name="hint_cloud_search_hint">Тражи преко имена, е-адресе…</string>
<!--key bit length selections-->
<string name="key_size_512">512</string>
<string name="key_size_768">768</string>
@@ -354,7 +421,7 @@
<!--Help-->
<string name="help_tab_start">Старт</string>
<string name="help_tab_faq">Честа питања</string>
- <string name="help_tab_wot">Веб поверења</string>
+ <string name="help_tab_wot">Потврда кључа</string>
<string name="help_tab_nfc_beam">НФЦ Сноп</string>
<string name="help_tab_changelog">Дневник измена</string>
<string name="help_tab_about">О програму</string>
@@ -363,12 +430,15 @@
<string name="import_tab_keyserver">Сервер кључева</string>
<string name="import_tab_cloud">Клауд претрага</string>
<string name="import_tab_direct">Фајл/клипборд</string>
- <string name="import_tab_qr_code">Бар-код/НФЦ</string>
+ <string name="import_tab_qr_code">Бар-кôд/НФЦ</string>
<string name="import_import">Увези изабране кључеве</string>
- <string name="import_qr_code_wrong">Бар-код деформисан! Покушајте поново!</string>
- <string name="import_qr_code_too_short_fingerprint">Отисак је прекратак (&lt; 16 знакова)</string>
- <string name="import_qr_code_button">Очитај бар-код</string>
- <string name="import_qr_code_text">Усмерите камеру на бар-код!</string>
+ <string name="import_qr_code_wrong">Бар-кôд деформисан! Покушајте поново!</string>
+ <string name="import_qr_code_fp">Отисак је деформисан или прекратак!</string>
+ <string name="import_qr_code_too_short_fingerprint">Отисак је прекратак!</string>
+ <string name="import_qr_code_button">Очитај бар-кôд</string>
+ <string name="import_qr_code_text">Усмерите камеру на бар-кôд!</string>
+ <!--Import from URL-->
+ <string name="import_url_warn_no_search_parameter">Упит за претрагу није дефинисан. И даље можете ручно да тражите на овом серверу кључева.</string>
<!--Generic result toast-->
<string name="snackbar_details">Детаљи</string>
<string name="with_warnings">, са упозорењима</string>
@@ -429,6 +499,11 @@
</plurals>
<string name="delete_nothing">Нема ништа за брисање.</string>
<string name="delete_cancelled">Радња брисања је отказана.</string>
+ <!--Revoke result toast (snackbar)-->
+ <string name="revoke_ok">Успешно опозван кључ.</string>
+ <string name="revoke_fail">Грешка опозивања кључа!</string>
+ <string name="revoke_nothing">Нема ништа за опозив.</string>
+ <string name="revoke_cancelled">Радња опозива је отказана.</string>
<!--Certify result toast-->
<plurals name="certify_keys_ok">
<item quantity="one">Успешно оверен кључ%2$s.</item>
@@ -451,13 +526,13 @@
<string name="intent_send_encrypt">Шифруј помоћу Отвореног кључарника</string>
<string name="intent_send_decrypt">Дешифруј помоћу Отвореног кључарника</string>
<!--Remote API-->
- <string name="api_settings_show_info">Прикажи напредне податке</string>
- <string name="api_settings_hide_info">Сакриј напредне податке</string>
- <string name="api_settings_show_advanced">Прикажи напредне поставке</string>
- <string name="api_settings_hide_advanced">Сакриј напредне поставке</string>
+ <string name="api_settings_show_info">Прикажи додатне податке</string>
+ <string name="api_settings_hide_info">Сакриј додатне податке</string>
+ <string name="api_settings_show_advanced">Прикажи додатне поставке</string>
+ <string name="api_settings_hide_advanced">Сакриј додатне поставке</string>
<string name="api_settings_no_key">Није изабран кључ</string>
<string name="api_settings_select_key">Изаберите кључ</string>
- <string name="api_settings_create_key">Направи нови кључ за овај налог</string>
+ <string name="api_settings_create_key">Направи нови кључ</string>
<string name="api_settings_save">Сачувај</string>
<string name="api_settings_save_msg">Налог је сачуван</string>
<string name="api_settings_cancel">Одустани</string>
@@ -465,9 +540,9 @@
<string name="api_settings_start">Покрени апликацију</string>
<string name="api_settings_delete_account">Обриши налог</string>
<string name="api_settings_package_name">Име пакета</string>
- <string name="api_settings_package_certificate">СХА-256 потписа пакета</string>
- <string name="api_settings_accounts">Налози (застарели АПИ)</string>
- <string name="api_settings_advanced">Напредни подаци</string>
+ <string name="api_settings_package_certificate">СХА-256 сертификата пакета</string>
+ <string name="api_settings_accounts">Налози (стари АПИ)</string>
+ <string name="api_settings_advanced">Додатни подаци</string>
<string name="api_settings_allowed_keys">Дозвољени кључеви</string>
<string name="api_settings_settings">Поставке</string>
<string name="api_settings_key">Кључ налога:</string>
@@ -478,14 +553,29 @@
<string name="api_register_allow">Дозволи приступ</string>
<string name="api_register_disallow">Одбиј приступ</string>
<string name="api_register_error_select_key">Изаберите кључ!</string>
- <string name="api_select_pub_keys_missing_text">Нема кључева за ове идентитете:</string>
- <string name="api_select_pub_keys_dublicates_text">Постоји више кључева за ове идентитете:</string>
+ <string name="api_select_pub_keys_missing_text">Нема кључева за ове е-адресе:</string>
+ <string name="api_select_pub_keys_dublicates_text">Постоји више кључева за ове е-адресе:</string>
<string name="api_select_pub_keys_text">Ревидирајте списак прималаца!</string>
<string name="api_select_pub_keys_text_no_user_ids">Изаберите примаоце!</string>
<string name="api_error_wrong_signature">Провера потписа није успела! Да ли сте инсталирали ову апликацију са другог извора? Ако сте сигурни да ово није напад, опозовите регистрацију ове апликације у Отвореном кључарнику и региструјте је поново.</string>
+ <string name="api_select_sign_key_text">Изаберите ваш постојећи кључ или направите нови.</string>
+ <string name="api_select_keys_text">Ниједан од дозвољених кључева није у стању да дешифрује садржај. Изаберите дозвољене кључеве.</string>
<!--Share-->
- <string name="share_qr_code_dialog_title">Поделите бар-кодом</string>
+ <string name="share_qr_code_dialog_title">Поделите бар-кôдом</string>
<string name="share_nfc_dialog">Поделите преко НФЦ-а</string>
+ <!--retry upload dialog-->
+ <string name="retry_up_dialog_title">Отпремање није успело</string>
+ <string name="retry_up_dialog_message">Отпремање није успело. Желите ли да покушам поново?</string>
+ <string name="retry_up_dialog_btn_reupload">Понови радњу</string>
+ <string name="retry_up_dialog_btn_cancel">Откажи радњу</string>
+ <!--Delete or revoke private key dialog-->
+ <string name="del_rev_dialog_message">Ако више не желите да користите овај кључ, требали бисте да га опозовете и отпремите. Изаберите „САМО ОБРИШИ“ ако желите да га уклоните из Отвореног кључарника али наставите да га користите на другде.</string>
+ <string name="del_rev_dialog_title">Опозови/обриши кључ „%s“</string>
+ <string name="del_rev_dialog_btn_revoke">Опозови и отпреми</string>
+ <string name="del_rev_dialog_btn_delete">Само обриши</string>
+ <!--Delete Or Revoke Dialog spinner-->
+ <string name="del_rev_dialog_choice_delete">Само обриши</string>
+ <string name="del_rev_dialog_choice_rev_upload">Опозови и отпреми</string>
<!--Key list-->
<plurals name="key_list_selected_keys">
<item quantity="one">%d кључ изабран.</item>
@@ -499,13 +589,13 @@
<string name="key_view_action_edit">Уреди кључ</string>
<string name="key_view_action_encrypt">Шифруј текст</string>
<string name="key_view_action_encrypt_files">фајлови</string>
- <string name="key_view_action_certify">Овери идентитете</string>
+ <string name="key_view_action_certify">Потврди кључ</string>
<string name="key_view_action_update">Ажурирај са сервера кључева</string>
- <string name="key_view_action_share_with">Подели са…</string>
+ <string name="key_view_action_share_with">Подели преко…</string>
<string name="key_view_action_share_nfc">Подели преко НФЦ</string>
<string name="key_view_action_upload">Отпреми на сервер кључева</string>
<string name="key_view_tab_main">Главни подаци</string>
- <string name="key_view_tab_share">Подели</string>
+ <string name="key_view_tab_share">Подела</string>
<string name="key_view_tab_keys">Поткључеви</string>
<string name="key_view_tab_certs">Сертификати</string>
<string name="key_view_tab_keybase">Keybase.io</string>
@@ -518,11 +608,44 @@
<string name="user_id_info_invalid_title">Неисправан</string>
<string name="user_id_info_invalid_text">Нешто није у реду са овим идентитетом!</string>
<!--Key trust-->
+ <string name="key_trust_already_verified">Већ сте потврдили овај кључ!</string>
<string name="key_trust_it_is_yours">Ово је један од ваших кључева!</string>
- <string name="key_trust_revoked">Власни је опозвао овај кључ. Не бисте требали да се поуздате у њега.</string>
+ <string name="key_trust_maybe">Кључ није ни опозван нити је истекао.\nЈош га нисте потврдили, али можете да се поуздате у њега ако желите.</string>
+ <string name="key_trust_revoked">Власник је опозвао овај кључ. Не бисте требали да се поуздате у њега.</string>
<string name="key_trust_expired">Овај кључ је истекао. Не бисте требали да се поуздате у њега.</string>
+ <string name="key_trust_old_keys">Можда је у реду користити овај кључ за дешифровање старе поруке из времена кад је био важећи.</string>
+ <string name="key_trust_no_cloud_evidence">Нема доказа са клауда о поузданости овог кључа.</string>
<string name="key_trust_start_cloud_search">Почни претрагу</string>
+ <string name="key_trust_results_prefix">Keybase.io нуди „доказе“ који потврђују да власник овог кључа: </string>
+ <string name="key_trust_header_text">Напомена: Докази са Keybase.io су експериментална функција Отвореног кључарника. Препорука је да очитавате бар-кôдове или размењујете кључеве преко НФЦ-а како бисте их потврдили.</string>
<!--keybase proof stuff-->
+ <string name="keybase_narrative_twitter">Објављује на Твитеру као %s</string>
+ <string name="keybase_narrative_github">Познат је на Гитхабу као %s</string>
+ <string name="keybase_narrative_dns">Управља доменима %s</string>
+ <string name="keybase_narrative_web_site">Може да објављује на вебсајтовима %s</string>
+ <string name="keybase_narrative_reddit">Објављује на Редиту као %s</string>
+ <string name="keybase_narrative_coinbase">Познат на Коинбејсу као %s</string>
+ <string name="keybase_narrative_hackernews">Објављује на Хакер Њуз као %s</string>
+ <string name="keybase_narrative_unknown">Непознат тип доказа %s</string>
+ <string name="keybase_proof_failure">Нажалост, овај доказ не може да се овери.</string>
+ <string name="keybase_unknown_proof_failure">Непрепознат проблем са провером доказа</string>
+ <string name="keybase_problem_fetching_evidence">Проблем са доказом</string>
+ <string name="keybase_key_mismatch">Отисак кључа се не поклапа са оним у објави доказа</string>
+ <string name="keybase_dns_query_failure">Добављање ДНС ТЕКСТ записа није успело</string>
+ <string name="keybase_no_prover_found">Нема провере доказа за</string>
+ <string name="keybase_message_payload_mismatch">Дешифрована објава доказа се не поклапа са очекиваном вредношћу</string>
+ <string name="keybase_message_fetching_data">Добављам доказ</string>
+ <string name="keybase_proof_succeeded">Овај доказ је оверен!</string>
+ <string name="keybase_a_post">Објава</string>
+ <string name="keybase_fetched_from">добављен/а са</string>
+ <string name="keybase_for_the_domain">за домен</string>
+ <string name="keybase_contained_signature">садржи поруку коју је могао да направи само власник овог кључа:</string>
+ <string name="keybase_twitter_proof">Твит</string>
+ <string name="keybase_dns_proof">ДНС ТЕКСТ запис</string>
+ <string name="keybase_web_site_proof">текстуални фајл</string>
+ <string name="keybase_github_proof">гист</string>
+ <string name="keybase_reddit_proof">ЈСОН фајл</string>
+ <string name="keybase_reddit_attribution">приписује Редит за</string>
<string name="keybase_verify">Овери</string>
<!--Edit key-->
<string name="edit_key_action_change_passphrase">Измени лозинку</string>
@@ -542,30 +665,56 @@
<item>Измени истицање</item>
<item>Опозови поткључ</item>
<item>Оголи поткључ</item>
- <item>"Move Subkey to Yubikey / Smart Card"</item>
+ <item>Премести поткључ у Јубикључ/Смарт картицу</item>
</string-array>
<string name="edit_key_new_subkey">нови поткључ</string>
<string name="edit_key_select_flag">Изаберите бар једну заставицу!</string>
<string name="edit_key_error_add_identity">Додајте бар један идентитет!</string>
<string name="edit_key_error_add_subkey">Додајте бар један поткључ!</string>
+ <string name="edit_key_error_bad_nfc_algo">Смарт картица не подржава овај алгоритам!</string>
+ <string name="edit_key_error_bad_nfc_size">Смарт картица не подржава ову величину кључа!</string>
+ <string name="edit_key_error_bad_nfc_stripped">Не могу да преместим кључ на смарт картицу (или је огољен или је „преусмери-на-картицу“)!</string>
<!--Create key-->
- <string name="create_key_upload">Отпреми кључ на сервер кључева</string>
+ <string name="create_key_upload">Синхронизуј са клаудом</string>
<string name="create_key_empty">Ово поље је обавезно</string>
<string name="create_key_passphrases_not_equal">Лозинке се не поклапају</string>
<string name="create_key_final_text">Унели сте следећи идентитет:</string>
<string name="create_key_final_robot_text">Прављење кључа може да потраје, попијте кафу у међувремену…</string>
<string name="create_key_rsa">(3 поткључа, РСА, 4096 бита)</string>
<string name="create_key_custom">(прилагођена конфигурација кључа)</string>
- <string name="create_key_identity_text">Унесите пуно име, адресу е-поште и укуцајте лозинку.</string>
- <string name="create_key_hint_full_name">Пуно име, нпр. Петар Петровић</string>
+ <string name="create_key_name_text">Одредите име које се односи на овај кључ. То може да буде пуно име, нпр. „Јован Јовановић“, или надимак, нпр. „Змај“.</string>
+ <string name="create_key_email_text">Унесите вашу главну е-адресу коју користите за безбедну комуникацију.</string>
+ <string name="create_key_passphrase_text">Одредите јаку лозинку. Она штити ваш кључ ако вам украду уређај.</string>
+ <string name="create_key_hint_full_name">Пуно име или надимак</string>
<string name="create_key_edit">Промени конфигурацију кључа</string>
+ <string name="create_key_add_email">Додај е-адресу</string>
+ <string name="create_key_add_email_text">Додатне е-адресе се такође односе на овај кљул и могу да се користе за безбедну комуникацију.</string>
+ <string name="create_key_email_already_exists_text">Е-адреса је већ додата</string>
+ <string name="create_key_email_invalid_email">Формат е-адресе није исправан</string>
+ <string name="create_key_yubi_key_pin_text">Запамтите ПИН, биће вам потребан за касније коришћење Јубикључа. Запишите администраторски ПИН и сачувајте га на безбедном месту.</string>
+ <string name="create_key_yubi_key_pin">ПИН</string>
+ <string name="create_key_yubi_key_admin_pin">Администраторски ПИН</string>
+ <string name="create_key_yubi_key_pin_repeat_text">Унесите ПИН и администраторски ПИН да бисте наставили.</string>
+ <string name="create_key_yubi_key_pin_repeat">Поновите ПИН</string>
+ <string name="create_key_yubi_key_admin_pin_repeat">Поновите администраторски ПИН</string>
+ <string name="create_key_yubi_key_pin_not_correct">ПИН није тачан!</string>
<!--View key-->
<string name="view_key_revoked">Опозван: кључ више не смије бити коришћен!</string>
<string name="view_key_expired">Истекао: контакт мора да продужи ваљаност кључа!</string>
<string name="view_key_expired_secret">Истекао: можете да уредите кључ и продужите му ваљаност!</string>
<string name="view_key_my_key">Мој кључ</string>
- <string name="view_key_verified">Оверен кључ</string>
- <string name="view_key_unverified">Неоверен: очитајте бар-код да бисте оверили кључ!</string>
+ <string name="view_key_verified">Потврђен кључ</string>
+ <string name="view_key_unverified">Непотврђен: очитајте бар-кôд да бисте потврдили кључ!</string>
+ <string name="view_key_fragment_no_system_contact">&lt;ништа&gt;</string>
+ <!--Add/Edit keyserver-->
+ <string name="add_keyserver_dialog_title">Додај сервер кључева</string>
+ <string name="edit_keyserver_dialog_title">Промени сервер кључева</string>
+ <string name="add_keyserver_verified">Сервер кључева оверен!</string>
+ <string name="add_keyserver_without_verification">Сервер кључева додат без оверивања.</string>
+ <string name="add_keyserver_invalid_url">Неисправан УРЛ!</string>
+ <string name="add_keyserver_connection_failed">Неуспех повезивања са сервером кључева. Проверите УРЛ и вашу везу са интернетом.</string>
+ <string name="keyserver_preference_deleted">%s обрисан</string>
+ <string name="keyserver_preference_cannot_delete_last">Не могу да обришем последњи сервер кључева. Потребан је бар један!</string>
<!--Navigation Drawer-->
<string name="nav_keys">Кључеви</string>
<string name="nav_encrypt_decrypt">Шифруј/дешифруј</string>
@@ -573,6 +722,7 @@
<string name="drawer_open">Отвори навигациону фиоку</string>
<string name="drawer_close">Затвори навигациону фиоку</string>
<string name="my_keys">Моји кључеви</string>
+ <string name="nav_backup">Резерва</string>
<!--hints-->
<string name="encrypt_content_edit_text_hint">Укуцајте текст</string>
<!--certs-->
@@ -696,10 +846,10 @@
<string name="msg_is_pubring_generate">Генеришем јавни привезак од тајног привеска</string>
<string name="msg_is_subkey_nonexistent">Поткључ %s није доступан у тајном кључу</string>
<string name="msg_is_subkey_ok">Тајни поткључ %d означен као доступан</string>
- <string name="msg_is_subkey_empty">Тајни поткључ %d означен као доступан, без лозинке</string>
+ <string name="msg_is_subkey_empty">Тајни поткључ %s означен као доступан, са празном лозинком</string>
<string name="msg_is_subkey_pin">Тајни поткључ %s означен као доступан, са ПИНом</string>
<string name="msg_is_subkey_stripped">Тајни поткључ %d означен као огољен</string>
- <string name="msg_is_subkey_divert">Тајни поткључ %d означен као „преусмерен на картицу/НФЦ“</string>
+ <string name="msg_is_subkey_divert">Тајни поткључ %s означен као „преусмери-на-картицу“</string>
<string name="msg_is_success_identical">Привезак не садржи нове податке, нема шта да се ради</string>
<string name="msg_is_success">Успешно увезен тајни привезак</string>
<!--Keyring Canonicalization log entries-->
@@ -726,6 +876,7 @@
<string name="msg_kc_sub_bad_local">Уклањам повезујући сертификат поткључа са заставицом „локални“</string>
<string name="msg_kc_sub_bad_keyid">Неслагање ид-а издаваоца везивања поткључа</string>
<string name="msg_kc_sub_bad_time">Уклањам повезујући сертификат поткључа са временском ознаком у будућности</string>
+ <string name="msg_kc_sub_bad_time_early">Повезујући сертификат поткључа има ранију временску ознаку него његов кључ!</string>
<string name="msg_kc_sub_bad_type">Непознат тип сертификата поткључа: %s</string>
<string name="msg_kc_sub_dup">Уклањам сувишни повезујући сертификат поткључа</string>
<string name="msg_kc_sub_primary_bad">Уклањам повезујући сертификат поткључа због неисправног примарног повезујућег сертификата</string>
@@ -804,7 +955,9 @@
<string name="msg_cr_error_flags_ecdh">Изабране су погрешне заставице кључа, ЕЦДХ не може да се користи за потписивање!</string>
<!--modifySecretKeyRing-->
<string name="msg_mr">Модификујем привезак %s</string>
- <string name="msg_mf_error_divert_serial">Серијски број преусмеравање-у-картицу кључа мора бити 16 бита. Ово је грешка у програмирању, поднесите извештај о грешци!</string>
+ <string name="msg_mf_divert">Преусмеревам на смарт картицу за криптографске радње</string>
+ <string name="msg_mf_error_divert_newsub">Прављење нових поткључева није подржано за „преусмери-на-картицу“ примарне кључеве!</string>
+ <string name="msg_mf_error_divert_serial">Серијски број „преусмери-на-картицу“ кључа мора бити 16 бита! Ово је грешка у програмирању, поднесите извештај о грешци!</string>
<string name="msg_mf_error_encode">Изузетак кодирања!</string>
<string name="msg_mf_error_fingerprint">Стварни отисак кључа не одговара очекиваном!</string>
<string name="msg_mf_error_keyid">Нема ИД-а кључа. Ово је унутрашња грешка, поднесите извештај о грешци!</string>
@@ -815,25 +968,37 @@
<string name="msg_mf_error_restricted">Покушај извршења ограничене радње без лозинке! Ово је грешка у програмирању, поднесите извештај о грешци!</string>
<string name="msg_mf_error_revoked_primary">Опозвани кориснички ИД-ови не могу бити примарни!</string>
<string name="msg_mf_error_null_expiry">Датум истицања не може бити „исти као пре“ на стварању поткључа. Ово је грешка у програмирању, поднесите извештај о грешци!</string>
+ <string name="msg_mf_error_noop">Нема ништа за радити!</string>
<string name="msg_mf_error_passphrase_master">Кобна грешка дешифровања главног кључа! Ово је вероватно грешка у програмирању, поднесите извештај о грешци!</string>
<string name="msg_mf_error_pgp">Унутрашња ОпенПГП грешка!</string>
<string name="msg_mf_error_sig">Изузетак потписа!</string>
+ <string name="msg_mf_error_sub_stripped">Не могу да модификујем огољени поткључ %s!</string>
+ <string name="msg_mf_error_subkey_missing">Покушај радње на недостајућем поткључу %s!</string>
+ <string name="msg_mf_error_conflicting_nfc_commands">Не могу да преместим кључ на смарт картицу истом радњом која прави потпис на картици.</string>
+ <string name="msg_mf_error_duplicate_keytocard_for_slot">Смарт картица подржава само један слот по типу кључа.</string>
+ <string name="msg_mf_error_invalid_flags_for_keytocard">Неодговарајуће заставице кључа за кључ смарт картице.</string>
<string name="msg_mf_master">Модификујем главне сертификате</string>
<string name="msg_mf_notation_empty">Додајем празни пакет нотације</string>
<string name="msg_mf_notation_pin">Додајем ПИН пакет нотације</string>
<string name="msg_mf_passphrase">Мењам лозинку за привезак</string>
+ <string name="msg_mf_pin">Мењам ПИН на картици</string>
+ <string name="msg_mf_admin_pin">Мењам администраторски ПИН на картици</string>
<string name="msg_mf_passphrase_key">Поново шифрујем поткључ %s новом лозинком</string>
<string name="msg_mf_passphrase_empty_retry">Постављање нове лозинке није успело, покушавам поново са празном старом лозинком</string>
<string name="msg_mf_passphrase_fail">Не могу да променим лозинку за поткључ! (Да ли се разликује од оне у осталим кључевима?)</string>
<string name="msg_mf_primary_replace_old">Замењујем сертификат претходног примарног корисничког ИД-а</string>
<string name="msg_mf_primary_new">Генеришем нови сертификат за нови примарни кориснички ИД</string>
+ <string name="msg_mf_restricted_mode">Пребацујем на ограничени режим рада</string>
<string name="msg_mf_subkey_change">Модификујем поткључ %s</string>
- <string name="msg_mf_error_subkey_missing">Покушај радње на недостајућем поткључу %s!</string>
+ <string name="msg_mf_require_divert">Преусмеравам на смарт картицу за крипто радње</string>
+ <string name="msg_mf_require_passphrase">Потребна је лозинка за извршење радњи</string>
<string name="msg_mf_subkey_new">Додајем нови поткључ типа %s</string>
<string name="msg_mf_subkey_new_id">ИД новог поткључа: %s</string>
<string name="msg_mf_error_past_expiry">Датум истицања не може бити у прошлости!</string>
<string name="msg_mf_subkey_revoke">Опозивам поткључ %s</string>
<string name="msg_mf_subkey_strip">Огољавам поткључ %s</string>
+ <string name="msg_mf_keytocard_start">Премештам поткључ %s у Смарт картицу</string>
+ <string name="msg_mf_keytocard_finish">Премештен %1$s на смарт картицу %2$s</string>
<string name="msg_mf_success">Привезак успешно модификован</string>
<string name="msg_mf_uid_add">Додајем кориснички ИД %s</string>
<string name="msg_mf_uid_primary">Постављам примарни кориснички ИД на %s</string>
@@ -883,16 +1048,18 @@
<string name="msg_ed_caching_new">Кеширам нову лозинку</string>
<string name="msg_ed_error_no_parcel">Недостаје SaveKeyringParcel! (ово је грешка, пријавите је)</string>
<string name="msg_ed_error_key_not_found">Кључ није нађен!</string>
+ <string name="msg_ed_error_extract_public_upload">Грешка извлачења јавног кључа за отпремање!</string>
<string name="msg_ed_fetching">Добављам кључ за модификовање (%s)</string>
<string name="msg_ed_success">Радња на кључу је успела</string>
<!--Promote key-->
<string name="msg_pr">Унапређујем јавни кључ у тајни кључ</string>
- <string name="msg_pr_error_already_secret">Кључ је већ тајни кључ!</string>
+ <string name="msg_pr_all">Унапређујем све поткључеве</string>
<string name="msg_pr_error_key_not_found">Кључ није нађен!</string>
<string name="msg_pr_fetching">Добављам кључ за модификовање (%s)</string>
+ <string name="msg_pr_subkey_match">Унапређујем поткључ: %s</string>
+ <string name="msg_pr_subkey_nomatch">Поткључ није на Јубикључу: %s</string>
<string name="msg_pr_success">Кључ успешно унапређен</string>
<!--Other messages used in OperationLogs-->
- <string name="msg_ek_error_divert">Уређивање НФЦ кључева (још) није подржано!</string>
<string name="msg_ek_error_dummy">Не могу да уредим кључ са огољеним главним кључем!</string>
<string name="msg_ek_error_not_found">Кључ није нађен!</string>
<!--Messages for DecryptVerify operation-->
@@ -913,17 +1080,19 @@
<string name="msg_dc_clear_signature">Уписујем податке потписа за касније</string>
<string name="msg_dc_clear">Обрађујем податке обичног текста</string>
<string name="msg_dc_error_bad_passphrase">Грешка откључавања кључа, погрешна лозинка!</string>
+ <string name="msg_dc_error_sym_passphrase">Грешка дешифровања података! (Лоша лозинка?)</string>
+ <string name="msg_dc_error_corrupt_data">Подаци су оштећени!</string>
<string name="msg_dc_error_extract_key">Непозната грешка откључавања кључа!</string>
<string name="msg_dc_error_integrity_check">Грешка провере интегритета!</string>
- <string name="msg_dc_insecure_mdc_missing">Недостаје провера интегритета! Ово може да се деси ако је апликација за шифровање застарела, или услед напада старијег издања.</string>
- <string name="msg_dc_error_invalid_data">Нису нађени исправни подаци потписа!</string>
- <string name="msg_dc_error_io">Наиђох на У/И изузетак током радње!</string>
+ <string name="msg_dc_error_invalid_data">Нема исправних ОпенПГП шифрованих или потписаних података!</string>
+ <string name="msg_dc_error_io">Наиђох на грешку при читању улазних података!</string>
+ <string name="msg_dc_error_input">Грешка отварања тока улазних података!</string>
<string name="msg_dc_error_no_data">Шифровани подаци нису нађени у току!</string>
<string name="msg_dc_error_no_key">Подаци шифровани познатим тајним кључем нису нађени у току!</string>
<string name="msg_dc_error_pgp_exception">Наиђох на ОпенПГП изузетак током радње!</string>
<string name="msg_dc_integrity_check_ok">Провера интегритета је у реду!</string>
<string name="msg_dc_ok_meta_only">Само су метаподаци затражени, прескачем дешифровање</string>
- <string name="msg_dc_ok">У реду</string>
+ <string name="msg_dc_ok">Дешифровање/оверавање завршено</string>
<string name="msg_dc_pass_cached">Користим лозинку из кеша</string>
<string name="msg_dc_pending_nfc">Потребан је НФЦ токен, захтевам унос корисника…</string>
<string name="msg_dc_pending_passphrase">Потребна је лозинка, захтевам унос корисника…</string>
@@ -935,8 +1104,15 @@
<string name="msg_dc_trail_sym">Наиђох на пратеће симетрично шифроване податке</string>
<string name="msg_dc_trail_unknown">Наиђох на пратеће податке непознатог типа</string>
<string name="msg_dc_unlocking">Откључавам тајни кључ</string>
+ <string name="msg_dc_insecure_symmetric_encryption_algo">Коришћен је небезбедан алгоритам шифровања. Ово може да се деси ако је апликација за застарела, или услед напада.</string>
+ <string name="msg_dc_insecure_hash_algo">Коришћен је небезбедан алгоритам хеша. Ово може да се деси ако је апликација застарела, или услед напада.</string>
+ <string name="msg_dc_insecure_mdc_missing">Недостаје пакет Кôда детекције измена (МДЦ)! Ово може да се деси ако је апликација за шифровање застарела, или услед напада старијег издања.</string>
+ <string name="msg_dc_insecure_key">Небезбедан кључ: или је дужина РСА/ДСА/Елгамал кључа прекратка или је ЕЦЦ кривуља/алгоритам сматрана небезбедном! Ово може да се деси ако је апликација застарела, или услед напада.</string>
<!--Messages for VerifySignedLiteralData operation-->
<string name="msg_vl">Почињем проверу потписа</string>
+ <string name="msg_vl_error_no_siglist">Нема списка потписа у потписаним дословним подацима</string>
+ <string name="msg_vl_error_wrong_key">Порука није потписана правим кључем</string>
+ <string name="msg_vl_error_missing_literal">Нема корисних података у потписаним дословним подацима</string>
<string name="msg_vl_clear_meta_file">Име фајла: %s</string>
<string name="msg_vl_clear_meta_mime">МИМЕ тип: %s</string>
<string name="msg_vl_clear_meta_time">Време измене: %s</string>
@@ -952,7 +1128,6 @@
<string name="msg_se_error_input_uri_not_found">Грешка отварања УРИ-ја за читање!</string>
<string name="msg_se_error_output_uri_not_found">Грешка отварања УРИ-ја за упис!</string>
<string name="msg_se_error_too_many_inputs">Наведено више улаза него излаза! Ово је грешка у програмирању, поднесите извештај о грешци!</string>
- <string name="msg_se_warn_output_left">Преостали су излази али нема улаза. Ово је вероватно грешка у програмирању, поднесите извештај о грешци.</string>
<string name="msg_se_success">Радња потписивања/шифровања је успела!</string>
<!--Messages for PgpSignEncrypt operation-->
<string name="msg_pse_asymmetric">Припремам јавне кључеве за шифровање</string>
@@ -960,7 +1135,6 @@
<string name="msg_pse_compressing">Припремам компресију</string>
<string name="msg_pse_encrypting">Шифрујем податке</string>
<string name="msg_pse_error_bad_passphrase">Нетачна лозинка!</string>
- <string name="msg_pse_error_hash_algo">Овај кључ не подржава захтевани хеш алгоритам!</string>
<string name="msg_pse_error_io">Наиђох на У/И изузетак током радње!</string>
<string name="msg_pse_error_key_sign">Изабрани кључ за потписивање не може да потпише податке!</string>
<string name="msg_pse_error_sign_key">Грешка добављања кључа за потписивање!</string>
@@ -982,19 +1156,23 @@
<string name="msg_pse">Почињем радњу потписивања и/или шифровања</string>
<string name="msg_pse_symmetric">Припремам симетрично шифровање</string>
<string name="msg_crt_certifying">Генеришем сертификате</string>
- <string name="msg_crt_certify_all">Оверавам све корисничке ИД-ове за кључ %s</string>
- <plurals name="msg_crt_certify_some">
- <item quantity="one">Оверавам један кориснички ИД за кључ %2$s</item>
- <item quantity="few">Оверавам %1$d корисничка ИД-а за кључ %2$s</item>
- <item quantity="other">Оверавам %1$d корисничких ИД-ова за кључ %2$s</item>
+ <plurals name="msg_crt_certify_uids">
+ <item quantity="one">Потврђујем кориснички ИД за кључ %2$s</item>
+ <item quantity="few">Потврђујем %1$d корисничка ИД-а за кључ %2$s</item>
+ <item quantity="other">Потврђујем %1$d корисничких ИД-ова за кључ %2$s</item>
+ </plurals>
+ <plurals name="msg_crt_certify_uats">
+ <item quantity="one">Потврђујем кориснички атрибут за кључ %2$s</item>
+ <item quantity="few">Потврђујем %1$d корисничка атрибута за кључ %2$s</item>
+ <item quantity="other">Потврђујем %1$d корисничких атрибута за кључ %2$s</item>
</plurals>
<string name="msg_crt_error_self">Не могу да издам овакав самопотписани сертификат!</string>
<string name="msg_crt_error_master_not_found">Главни кључ није нађен!</string>
<string name="msg_crt_error_nothing">Нема оверених кључева!</string>
<string name="msg_crt_error_unlock">Грешка откључавања главног кључа!</string>
- <string name="msg_crt_error_divert">Оверавање помоћу НФЦ-а (још) није подржано!</string>
<string name="msg_crt">Оверавам привеске</string>
<string name="msg_crt_master_fetch">Добављам главни кључ за оверавање</string>
+ <string name="msg_crt_nfc_return">Враћам на НФЦ екран</string>
<string name="msg_crt_save">Уписујем оверени кључ %s</string>
<string name="msg_crt_saving">Уписујем привеске</string>
<string name="msg_crt_unlock">Откључавам главни кључ</string>
@@ -1002,6 +1180,7 @@
<string name="msg_crt_warn_not_found">Кључ није нађен!</string>
<string name="msg_crt_warn_cert_failed">Генерисање сертификата није успело!</string>
<string name="msg_crt_warn_save_failed">Радња уписа није успела!</string>
+ <string name="msg_crt_warn_upload_failed">Радња отпремања није успела!</string>
<string name="msg_crt_upload_success">Кључ успешно отпремљен на сервер</string>
<plurals name="msg_import">
<item quantity="one">Увозим кључ</item>
@@ -1011,13 +1190,14 @@
<string name="msg_import_fetch_error_decode">Грешка декодирања добављеног привеска!</string>
<string name="msg_import_fetch_error">Не могу да добавим кључ! (Проблеми са мрежом?)</string>
<string name="msg_import_fetch_keybase">Добављам са keybase.io: %s</string>
- <string name="msg_import_fetch_keyserver_error">Не могу да добавим кључ из базе кључева!</string>
+ <string name="msg_import_fetch_error_keyserver">Не могу да добавим кључ са сервера кључева: %s</string>
<string name="msg_import_fetch_keyserver">Добављам са сервера кључева: %s</string>
<string name="msg_import_fetch_keyserver_ok">Добављање кључева је успело</string>
<string name="msg_import_keyserver">Користим сервер кључева %s</string>
<string name="msg_import_fingerprint_error">Отисак добављеног кључа не одговара очекиваном!</string>
<string name="msg_import_fingerprint_ok">Провера отиска је у реду</string>
<string name="msg_import_merge">Спајам добављене податке</string>
+ <string name="msg_import_merge_error">Грешка спајања добављених података!</string>
<string name="msg_import_error">Радња увоза није успела!</string>
<string name="msg_import_error_io">Радња увоза није успела због У/И грешке!</string>
<string name="msg_import_partial">Радња увоза је успела, са грешкама!</string>
@@ -1027,8 +1207,10 @@
<item quantity="few">Извозим %d кључа</item>
<item quantity="other">Извозим %d кључева</item>
</plurals>
+ <string name="msg_export_file_name">Име фајла: %s</string>
<string name="msg_export_all">Извозим све кључеве</string>
<string name="msg_export_public">Извозим јавни кључ %s</string>
+ <string name="msg_export_upload_public">Отпремам јавни кључ %s</string>
<string name="msg_export_secret">Извозим тајни кључ %s</string>
<string name="msg_export_error_no_file">Није наведено име фајла!</string>
<string name="msg_export_error_fopen">Грешка отварања фајла!</string>
@@ -1038,7 +1220,9 @@
<string name="msg_export_error_db">Грешка базе података!</string>
<string name="msg_export_error_io">Грешка улаза/излаза!</string>
<string name="msg_export_error_key">Грешка предобраде података кључа!</string>
+ <string name="msg_export_error_upload">Грешка отпремања кључа на сервер. Проверите вашу везу са интернетом.</string>
<string name="msg_export_success">Радња извоза је успела</string>
+ <string name="msg_export_upload_success">Отпремање на сервер кључева је успело</string>
<string name="msg_del_error_empty">Нема ништа за брисање!</string>
<string name="msg_del_error_multi_secret">Тајне кључеве можете брисати само појединачно!</string>
<plurals name="msg_del">
@@ -1059,6 +1243,11 @@
<item quantity="few">Брисање %d кључа није успело</item>
<item quantity="other">Брисање %d кључева није успело</item>
</plurals>
+ <string name="msg_revoke_error_empty">Нема ништа за опозив!</string>
+ <string name="msg_revoke_error_not_found">Не могу да нађем кључ за опозив!</string>
+ <string name="msg_revoke_key">Опозивам кључ %s</string>
+ <string name="msg_revoke_key_fail">Неуспех опозивања кључа</string>
+ <string name="msg_revoke_ok">Успешно опозван кључ</string>
<string name="msg_acc_saved">Налог је сачуван</string>
<string name="msg_download_success">Успешно преузето!</string>
<string name="msg_download_no_valid_keys">Нема исправних кључева у фајлу/клипборду!</string>
@@ -1072,17 +1261,47 @@
<string name="msg_download_too_many_responses">Претрага кључева је вратила превише кандидата. Прецизирајте упит!</string>
<string name="msg_download_query_too_short_or_too_many_responses">Или није нађен ниједан кључ или их је нађено превише. Побољшајте ваш упит!</string>
<string name="msg_download_query_failed">Дошло је до грешке приликом претраге кључева.</string>
+ <!--Messages for Keybase Verification operation-->
+ <string name="msg_keybase_verification">Покушавам оверавање на keybase.io за %s</string>
+ <string name="msg_keybase_error_no_prover">Нема провере доказа за %s</string>
+ <string name="msg_keybase_error_fetching_evidence">Проблем са добављањем доказа</string>
+ <string name="msg_keybase_error_key_mismatch">Отисак кључа се не поклапа са оним у објави доказа</string>
+ <string name="msg_keybase_error_dns_fail">Добављање ДНС ТЕКСТ записа није успело</string>
+ <string name="msg_keybase_error_specific">%s</string>
+ <string name="msg_keybase_error_msg_payload_mismatch">Дешифрована објава доказа се не поклапа са очекиваном вредношћу</string>
+ <!--Messages for Export Log operation-->
+ <string name="msg_export_log_start">Извозим дневник</string>
+ <string name="msg_export_log_error_fopen">Грешка отварања фајла</string>
+ <string name="msg_export_log_error_no_file">Није наведено име фајла!</string>
+ <string name="msg_export_log_error_writing">У/И грешка уписа у фајл!</string>
+ <string name="msg_export_log_success">Дневник успешно извезен!</string>
<!--PassphraseCache-->
- <string name="passp_cache_notif_click_to_clear">Кликните да уклоните лозинке из кеша</string>
- <string name="passp_cache_notif_n_keys">Отворени кључарник је кеширао %d лозинки</string>
- <string name="passp_cache_notif_keys">Кеширане лозинке:</string>
- <string name="passp_cache_notif_clear">Очисти кеш</string>
+ <string name="passp_cache_notif_click_to_clear">Тапните да очистите лозинке.</string>
+ <plurals name="passp_cache_notif_n_keys">
+ <item quantity="one">%d лозинка запамћена</item>
+ <item quantity="few">%d лозинке запамћене</item>
+ <item quantity="other">%d лозинки запамћено</item>
+ </plurals>
+ <string name="passp_cache_notif_keys">Запамћене лозинке</string>
+ <string name="passp_cache_notif_clear">Очисти лозинке</string>
<string name="passp_cache_notif_pwd">Лозинка</string>
+ <!--Keyserver sync-->
+ <string name="keyserver_sync_orbot_notif_title">Синхронизација са облака захтева Орбот</string>
+ <string name="keyserver_sync_orbot_notif_msg">Тапните да бисте покренули Орбот</string>
+ <string name="keyserver_sync_orbot_notif_start">Покрени Орбот</string>
+ <string name="keyserver_sync_orbot_notif_ignore">Директно</string>
<!--First Time-->
<string name="first_time_text1">Преузмите вашу приватност помоћу Отвореног кључарника!</string>
<string name="first_time_create_key">Направи ми кључ</string>
- <string name="first_time_import_key">Увези из фајла</string>
+ <string name="first_time_import_key">Увези кључ из фајла</string>
+ <string name="first_time_yubikey">Користи Јубикључ НЕО</string>
<string name="first_time_skip">Прескочи поставу</string>
+ <string name="first_time_blank_yubikey">Желите ли да користите овај празни Јубикључ НЕО са Отвореним кључарником?\n\nСклоните сада Јубикључ, бићете упитани када опет буде потребан!</string>
+ <string name="first_time_blank_yubikey_yes">Користи овај Јубикључ</string>
+ <string name="backup_text">Резерве које укључују ваше сопствене кључеве никад немојте делити са другима!</string>
+ <string name="backup_all">Свих кључева + сопствених</string>
+ <string name="backup_public_keys">Свих кључева</string>
+ <string name="backup_section">Резерва</string>
<!--unsorted-->
<string name="section_certifier_id">Сертификатор</string>
<string name="section_cert">Детаљи сертификата</string>
@@ -1091,16 +1310,15 @@
<string name="empty_certs">Нема сертификата за овај кључ</string>
<string name="certs_text">Приказани су само потврђени сопствени сертификати и потврђени сертификати направљени вашим кључем.</string>
<string name="section_uids_to_certify">Идентитети за</string>
- <string name="certify_text">Кључеви које увозите садрже „идентитете“: имена и е-адресе. Одредите за оверу само оне који одговарају ономе што очекујете.</string>
+ <string name="certify_text">Кључеви које увозите садрже „идентитете“: имена и е-адресе. Одредите за потврду само оне који одговарају ономе што очекујете.</string>
<string name="certify_fingerprint_text">Упоредите приказани отисак, знак по знак, са оним приказаним на другаревом уређају.</string>
<string name="certify_fingerprint_text2">Да ли се приказани отисци поклапају?</string>
<string name="label_revocation">Разлог опозива</string>
- <string name="label_verify_status">Стање овере</string>
<string name="label_cert_type">Тип</string>
<string name="error_key_not_found">Кључ није нађен!</string>
<string name="error_key_processing">Грешка обраде кључа!</string>
<string name="key_stripped">огољен</string>
- <string name="key_divert">преусмери на картицу/НФЦ</string>
+ <string name="key_divert">преусмери на картицу</string>
<string name="key_no_passphrase">нема лозинке</string>
<string name="key_unavailable">недоступан</string>
<string name="secret_cannot_multiple">Сопствене кључеве можете брисати само појединачно!</string>
@@ -1108,24 +1326,30 @@
<string name="unknown_algorithm">непознат</string>
<string name="can_sign_not">не може да потпише</string>
<string name="error_no_encrypt_subkey">Поткључ за шифровање није доступан!</string>
- <string name="account_no_manual_account_creation">Не прави налоге Отвореног кључарника ручно.\nПогледајте Помоћ за више информација.</string>
<string name="contact_show_key">Прикажи кључ (%s)</string>
<string name="swipe_to_update">Превуците прстом доле да ажурирате са сервера кључева</string>
<string name="error_no_file_selected">Изаберите бар један фајл за шифровање!</string>
<string name="error_multi_files">Упис више фајлова није подржан. Ово је ограничење у текућем издању Андроида.</string>
+ <string name="error_multi_clipboard">Дешифровање више фајлова на клипборд није подржано.</string>
+ <string name="error_detached_signature">Радња само потписивања бинарних фајлова није подржана, одредите бар један кључ шифровања.</string>
+ <string name="error_empty_text">Укуцајте неки текст за шифровање!</string>
<string name="key_colon">Кључ:</string>
<string name="exchange_description">Да бисте почели размену кључева, са десне стране изаберите број учесника и додирните дугме „Почни размену“.\n\nБиће вам постављено још два питања да би се осигурало да су само исправни учесници у размени и да су њихови отисци тачни.</string>
<string name="btn_start_exchange">Почни размену</string>
<string name="user_id_none"><![CDATA[<ништа>]]></string>
+ <!--Android Account-->
+ <string name="account_no_manual_account_creation">Не можете да направите налоге Отвореног кључарника ручно.</string>
+ <string name="account_privacy_title">Приватност</string>
+ <string name="account_privacy_text">Отворени кључарник не синхронизује ваше контакте на интернет. Само повезује контакте са кључевима засновано на именима и е-адресама. Ово ради ван везе на вашем уређају.</string>
<!--Passphrase wizard-->
<!--TODO: rename all the things!-->
<string name="title_unlock_method">Одредите методу откључавања</string>
- <!--<string name="enter_passphrase_twice">Enter passphrase twice</string>-->
+ <!--<string name="enter_passphrase_twice">Enter password twice</string>-->
<string name="enter_passphrase">Унесите лозинку</string>
<string name="passphrase">Лозинка</string>
- <string name="noPassphrase">Без лозинке</string>
+ <string name="noPassphrase">Нема лозинке</string>
<string name="no_passphrase_set">Лозинка није постављена</string>
- <string name="passphrases_match">Лозинке се поклапају</string>
+ <string name="passphrases_match">Лозинке се не поклапају</string>
<string name="passphrase_saved">Лозинка сачувана</string>
<string name="passphrase_invalid">Лозинка није исправна</string>
<string name="missing_passphrase">Недостаје лозинка</string>
@@ -1143,5 +1367,63 @@
<string name="nfc_write_succesful">Успешно уписах на НФЦ ознаку</string>
<string name="unlocked">Откључан</string>
<string name="nfc_settings">Поставке</string>
- <string name="file_delete_successful"></string>
+ <string name="snack_yubikey_view">Приказ</string>
+ <string name="snack_yubikey_import">Увоз</string>
+ <string name="button_bind_key">Повежи кључ</string>
+ <string name="yubikey_serno">Серијски број: %s</string>
+ <string name="yubikey_key_holder">Власник кључа: </string>
+ <string name="yubikey_key_holder_not_set">Власник кључа: &lt;није постављен&gt;</string>
+ <string name="yubikey_status_bound">Јубикључ одговара и повезан са кључем</string>
+ <string name="yubikey_status_unbound">Јубикључ одговара, може да се повеже са кључем</string>
+ <string name="yubikey_status_partly">Јубикључ одговара, делимично повезан са кључем</string>
+ <string name="yubikey_create">Држите Јубикључ на полеђини вашег уређаја.</string>
+ <string name="btn_import">Увези</string>
+ <string name="snack_yubi_other">Други кључ је смештен на Јубикључу!</string>
+ <string name="error_nfc">НФЦ грешка: %s</string>
+ <plurals name="error_pin">
+ <item quantity="one">Нетачан ПИН!\n%d покушај преостао.</item>
+ <item quantity="few">Нетачан ПИН!\n%d покушаај преостала.</item>
+ <item quantity="other">Нетачан ПИН!\n%d покушаја преостало.</item>
+ </plurals>
+ <string name="error_nfc_terminated">Јубикључ у завршном стању.</string>
+ <string name="error_nfc_wrong_length">Унети ПИН је прекратак. ПИНови су дуги најмање 6 бројки.</string>
+ <string name="error_nfc_conditions_not_satisfied">Услови употребе нису задовољени.</string>
+ <string name="error_nfc_security_not_satisfied">Безбедносно стање није задовољено.</string>
+ <string name="error_nfc_authentication_blocked">ПИН блокиран након превише покушаја.</string>
+ <string name="error_nfc_data_not_found">Кључ или објекат нису нађени!</string>
+ <string name="error_nfc_unknown">Непозната грешка</string>
+ <string name="error_nfc_bad_data">Јубикључ је пријавио неисправне податке.</string>
+ <string name="error_nfc_chaining_error">Јубикључ је очекивао последњу наредбу у ланцу.</string>
+ <string name="error_nfc_header">Јубикључ је пријавио неисправан %s бит.</string>
+ <string name="error_nfc_tag_lost">Јубикључ је прерано склоњен. Држите Јубикључ на полеђини уређаја док се радња не заврши.</string>
+ <string name="error_nfc_try_again">Покушај поново</string>
+ <string name="error_pin_nodefault">Подразумевани ПИН је одбијен!</string>
+ <string name="error_temp_file">Грешка стварања привременог фајла.</string>
+ <string name="btn_delete_original">Обриши оригинални фајл</string>
+ <string name="snack_encrypt_filenames_on">Имена фајлова <b>су</b> шифрована.</string>
+ <string name="snack_encrypt_filenames_off">Имена фајлова <b>нису</b> шифрована.</string>
+ <string name="snack_armor_on">Излаз кодиран као текст.</string>
+ <string name="snack_armor_off">Излаз кодиран као бинарна.</string>
+ <string name="snack_compression_on">Компресија је <b>омогућена</b>.</string>
+ <string name="snack_compression_off">Компресија је <b>онемогућена</b>.</string>
+ <string name="error_loading_keys">Грешка учитавања кључева!</string>
+ <string name="error_empty_log">(грешка, празан дневник)</string>
+ <string name="error_reading_text">Не могу да очитам унос за дешифровање!</string>
+ <string name="filename_unknown">&lt;нема имена&gt;</string>
+ <string name="filename_unknown_text">&lt;обични текстуални подаци&gt;</string>
+ <string name="intent_show">Прикажи потписани/шифровани садржај</string>
+ <string name="view_internal">Прикажи у Отвореном кључарнику</string>
+ <string name="error_preparing_data">Грешка припремања података!</string>
+ <string name="label_clip_title">Шифровани подаци</string>
+ <string name="progress_processing">Обрађујем…</string>
+ <string name="error_saving_file">Грешка уписа фајла!</string>
+ <string name="file_saved">Фајл сачуван!</string>
+ <string name="file_delete_ok">Оригинални фајл обрисан.</string>
+ <string name="file_delete_none">Ниједан фајл није обрисан! (Већ обрисано?)</string>
+ <string name="file_delete_exception">Оригинални фајл није обрисан!</string>
+ <string name="error_clipboard_empty">Клипборд је празан!</string>
+ <string name="error_clipboard_copy">Грешка копирања података на клипборд!</string>
+ <string name="error_scan_fp">Грешка очитавања отиска!</string>
+ <string name="error_scan_match">Отисци се не поклапају!</string>
+ <string name="error_expiry_past">Датум истицања је у прошлости!</string>
</resources>
diff --git a/OpenKeychain/src/main/res/values-sv/strings.xml b/OpenKeychain/src/main/res/values-sv/strings.xml
index 0d9d4e205..1ccac9199 100644
--- a/OpenKeychain/src/main/res/values-sv/strings.xml
+++ b/OpenKeychain/src/main/res/values-sv/strings.xml
@@ -20,8 +20,6 @@
<string name="title_encrypt_to_file">Kryptera till fil</string>
<string name="title_decrypt_to_file">Dekryptera till fil</string>
<string name="title_import_keys">Importera nycklar</string>
- <string name="title_export_key">Exportera nyckel</string>
- <string name="title_export_keys">Exportera nycklar</string>
<string name="title_key_not_found">Nyckel hittades inte</string>
<string name="title_send_key">Ladda upp till nyckelserver</string>
<string name="title_certify_key">Bekräfta nyckel</string>
@@ -80,7 +78,6 @@
<!--menu-->
<string name="menu_preferences">Inställningar</string>
<string name="menu_help">Hjälp</string>
- <string name="menu_export_key">Exportera till fil</string>
<string name="menu_delete_key">Radera nyckel</string>
<string name="menu_manage_keys">Hantera mina nycklar</string>
<string name="menu_search">Sök</string>
@@ -144,6 +141,7 @@
<string name="pref_keyserver_summary">Sök nycklar på valda OpenPGP nyckelservrar (HKP-protokollet)</string>
<string name="pref_keybase">keybase.io</string>
<string name="pref_keybase_summary">Sök nycklar på keybase.io</string>
+ <!--label shown in Android settings under the OpenKeychain account-->
<!--Proxy Preferences-->
<!--proxy type choices and values-->
<!--OrbotHelper strings-->
@@ -204,7 +202,6 @@
<string name="select_encryption_key">Välj åtminstone en krypteringsnyckel.</string>
<string name="specify_file_to_encrypt_to">Ange vilken fil du vill kryptera till.\nVARNING: Om filen redan finns kommer den att skrivas över!</string>
<string name="specify_file_to_decrypt_to">Ange vilken fil du vill kryptera till.\nVARNING: Om filen redan finns kommer den att skrivas över!</string>
- <string name="specify_backup_dest">Ange vilken fil du vill exportera till.\nVARNING: Om filen redan finns kommer den att skrivas över!</string>
<string name="key_deletion_confirmation_multi">Vill du verkligen radera alla markerade nycklar?</string>
<string name="secret_key_deletion_confirmation">Efter radering kommer du inte kunna läsa meddelande krypterade med den här nyckeln samt förlora alla nyckelbekräftningar som gjorts med den!</string>
<string name="public_key_deletetion_confirmation">Radera nyckel \'%s\'?</string>
@@ -411,6 +408,7 @@
</plurals>
<string name="delete_nothing">Inget att radera.</string>
<string name="delete_cancelled">Raderingsoperation avbruten.</string>
+ <!--Revoke result toast (snackbar)-->
<!--Certify result toast-->
<plurals name="certify_keys_ok">
<item quantity="one">Certifierade nyckel%2$s.</item>
@@ -444,7 +442,6 @@
<string name="api_settings_start">Starta app</string>
<string name="api_settings_delete_account">Radera konto</string>
<string name="api_settings_package_name">Paketnamn</string>
- <string name="api_settings_package_certificate">SHA-256 för paketsignatur</string>
<string name="api_settings_accounts">Konton (gamla API:t)</string>
<string name="api_settings_advanced">Utökad information</string>
<string name="api_settings_allowed_keys">Tillåtna nycklar</string>
@@ -457,8 +454,6 @@
<string name="api_register_allow">Tillåt åtkomst</string>
<string name="api_register_disallow">Tillåt inte åtkomst</string>
<string name="api_register_error_select_key">Välj en nyckel!</string>
- <string name="api_select_pub_keys_missing_text">Inga nycklar hittades för dessa identiteter:</string>
- <string name="api_select_pub_keys_dublicates_text">Mer än en nyckel finns för dessa identiteter:</string>
<string name="api_select_pub_keys_text">Se över listan med mottagare!</string>
<string name="api_select_pub_keys_text_no_user_ids">Välj mottagare!</string>
<string name="api_error_wrong_signature">Signaturkontroll misslyckades! Har du installerat appen från en annan källa? Om du är säker på att det här inte är en attack, återkalla den här appens registrering i OpenKeychain och registrera sen om appen igen.</string>
@@ -467,6 +462,9 @@
<!--Share-->
<string name="share_qr_code_dialog_title">Dela med QR-kod</string>
<string name="share_nfc_dialog">Dela med NFC</string>
+ <!--retry upload dialog-->
+ <!--Delete or revoke private key dialog-->
+ <!--Delete Or Revoke Dialog spinner-->
<!--Key list-->
<plurals name="key_list_selected_keys">
<item quantity="one">1 nyckel vald.</item>
@@ -509,13 +507,6 @@
<string name="key_trust_results_prefix">Keybase.io erbjuder \"bevis\" som hävdar att ägaren av den här nyckeln:</string>
<string name="key_trust_header_text">Observera: Keybase.io bevis är en experimentell funktion i OpenKeychain. Vi uppmanar dig att skanna QR-koder eller utbyta nycklar via NFC utöver att bekräfta dem.</string>
<!--keybase proof stuff-->
- <string name="keybase_narrative_twitter">Postar på Twitter som</string>
- <string name="keybase_narrative_github">Är känd på GitHub som</string>
- <string name="keybase_narrative_dns">Kontrollerar domännamne(t|s)</string>
- <string name="keybase_narrative_reddit">Postar på Reddit som</string>
- <string name="keybase_narrative_coinbase">Är känd på Coinbase som</string>
- <string name="keybase_narrative_hackernews">Postar på Hacker News som</string>
- <string name="keybase_narrative_unknown">Okänd bevistyp</string>
<string name="keybase_proof_failure">Tyvärr kan detta bevis inte verifieras.</string>
<string name="keybase_problem_fetching_evidence">Problem med bevis</string>
<string name="keybase_dns_query_failure">Hämtning av DNS TXT-post misslyckades</string>
@@ -884,6 +875,7 @@
<!--Messages for Keybase Verification operation-->
<!--Messages for Export Log operation-->
<!--PassphraseCache-->
+ <!--Keyserver sync-->
<!--First Time-->
<string name="first_time_text1">Ta tillbaka din integritet med OpenKeychain!</string>
<string name="first_time_create_key">Skapa min nyckel</string>
@@ -907,12 +899,12 @@
<string name="unknown_algorithm">okänd</string>
<string name="can_sign_not">kan inte signera</string>
<string name="error_no_encrypt_subkey">Ingen krypteringsundernyckel tillgänglig!</string>
- <string name="account_no_manual_account_creation">Skapa inte OpenKeychain-konton manuellt. \nFör mer information, se Hjälp.</string>
<string name="contact_show_key">Visa nyckel (%s)</string>
<string name="swipe_to_update">Dra nedåt för att uppdatera från nyckelserver</string>
<string name="error_no_file_selected">Välj åtminstone en fil att kryptera!</string>
<string name="key_colon">Nyckel:</string>
<string name="user_id_none"><![CDATA[<none>]]></string>
+ <!--Android Account-->
<!--Passphrase wizard-->
<!--TODO: rename all the things!-->
<!--<string name="enter_passphrase_twice">Enter password twice</string>-->
diff --git a/OpenKeychain/src/main/res/values-tr/strings.xml b/OpenKeychain/src/main/res/values-tr/strings.xml
index 529e80aa7..090356f9d 100644
--- a/OpenKeychain/src/main/res/values-tr/strings.xml
+++ b/OpenKeychain/src/main/res/values-tr/strings.xml
@@ -14,8 +14,6 @@
<string name="title_encrypt_to_file">Dosyaya Şifrele</string>
<string name="title_decrypt_to_file">Dosyaya Çözümle</string>
<string name="title_import_keys">Anahtarları Al</string>
- <string name="title_export_key">Anahtarı Ver</string>
- <string name="title_export_keys">Anahtarları Ver</string>
<string name="title_key_not_found">Anahtar Bulunamadı</string>
<string name="title_send_key">Anahtar Sunucusuna Yükle</string>
<string name="title_key_details">Anahtar Detayları</string>
@@ -46,7 +44,6 @@
<!--menu-->
<string name="menu_preferences">Ayarlar</string>
<string name="menu_help">Yardım</string>
- <string name="menu_export_key">Dosyaya ver</string>
<string name="menu_delete_key">Anahtar sil</string>
<string name="menu_search">Ara</string>
<string name="menu_beam_preferences">NFC ayarları</string>
@@ -85,6 +82,7 @@
<string name="label_fingerprint">Parmak izi</string>
<string name="expiry_date_dialog_title">Zaman aşımı tarihini ayarla</string>
<string name="label_preferred">tercih edilen</string>
+ <!--label shown in Android settings under the OpenKeychain account-->
<!--Proxy Preferences-->
<!--proxy type choices and values-->
<!--OrbotHelper strings-->
@@ -284,6 +282,7 @@
<!--Delete result toast-->
<string name="delete_nothing">Silinecek bir şey yok.</string>
<string name="delete_cancelled">Silme işlemi iptal edildi.</string>
+ <!--Revoke result toast (snackbar)-->
<!--Certify result toast-->
<!--Intent labels-->
<string name="intent_decrypt_file">OpenKeychain ile Dosya Çözümle</string>
@@ -304,13 +303,14 @@
<string name="api_register_allow">Erişime izin ver</string>
<string name="api_register_disallow">Erişime izin verme</string>
<string name="api_register_error_select_key">Lütfen bir anahtar seçin!</string>
- <string name="api_select_pub_keys_missing_text">Bu kimlikler için anahtar bulunamadı:</string>
- <string name="api_select_pub_keys_dublicates_text">Bu kimlikler için birden fazla anahtar var:</string>
<string name="api_select_pub_keys_text">Lütfen alıcıların listesini gözden geçirin!</string>
<string name="api_select_pub_keys_text_no_user_ids">Lütfen alıcıları seçin!</string>
<!--Share-->
<string name="share_qr_code_dialog_title">QR Kod ile Paylaş</string>
<string name="share_nfc_dialog">NFC ile Paylaş</string>
+ <!--retry upload dialog-->
+ <!--Delete or revoke private key dialog-->
+ <!--Delete Or Revoke Dialog spinner-->
<!--Key list-->
<plurals name="key_list_selected_keys">
<item quantity="one">1 anahtar seçildi.</item>
@@ -420,6 +420,7 @@
<!--Messages for Keybase Verification operation-->
<!--Messages for Export Log operation-->
<!--PassphraseCache-->
+ <!--Keyserver sync-->
<!--First Time-->
<string name="first_time_text1">Gizliliğinizi OpenKeychain ile geri alın!</string>
<string name="first_time_skip">Kurulumu Atla</string>
@@ -439,12 +440,12 @@
<string name="unknown_algorithm">bilinmeyen</string>
<string name="can_sign_not">imzalanamadı</string>
<string name="error_no_encrypt_subkey">Şifreleme için kullanılabilecek altanahtar mevcut değil!</string>
- <string name="account_no_manual_account_creation">OpenKeychain-hesaplarını kendiniz oluşturmayın.\nDaha fazla bilgi için Yardım bölümüne bakın.</string>
<string name="contact_show_key">Anahtarı göster (%s)</string>
<string name="swipe_to_update">Anahtar sunucudan güncelleme almak için parmağınızı aşağıya doğru kaydırın</string>
<string name="error_no_file_selected">Şifrelemek için en az bir dosya seçin!</string>
<string name="key_colon">Anahtar:</string>
<string name="exchange_description">Anahtar değiş tokuşu başlatmak için sağ taraftan katılımcıların sayısını seçin ve \"Değiş tokuşu başlat\" tuşuna tıklayın.\n\nSadece istenilen katılımcıların değişim işleminde olduğundan ve parmak izlerinin doğruluğundan emin olmak için size iki soru daha sorulacak.</string>
+ <!--Android Account-->
<!--Passphrase wizard-->
<!--TODO: rename all the things!-->
<!--<string name="enter_passphrase_twice">Enter password twice</string>-->
diff --git a/OpenKeychain/src/main/res/values-uk/strings.xml b/OpenKeychain/src/main/res/values-uk/strings.xml
index 40d588bca..6c0420c0b 100644
--- a/OpenKeychain/src/main/res/values-uk/strings.xml
+++ b/OpenKeychain/src/main/res/values-uk/strings.xml
@@ -14,8 +14,6 @@
<string name="title_encrypt_to_file">Зашифрувати до файлу</string>
<string name="title_decrypt_to_file">Розшифрувати до файлу</string>
<string name="title_import_keys">Імпортувати ключі</string>
- <string name="title_export_key">Експортувати ключ</string>
- <string name="title_export_keys">Експортувати ключі</string>
<string name="title_key_not_found">Ключ не знайдено</string>
<string name="title_send_key">Завантажити на сервер ключів</string>
<string name="title_key_details">Подробиці про ключ</string>
@@ -46,7 +44,6 @@
<!--menu-->
<string name="menu_preferences">Параметри</string>
<string name="menu_help">Довідка</string>
- <string name="menu_export_key">Експорт до файлу</string>
<string name="menu_delete_key">Вилучити ключ</string>
<string name="menu_search">Пошук</string>
<string name="menu_beam_preferences">Налаштування променя</string>
@@ -85,6 +82,7 @@
<string name="label_fingerprint">Відбиток</string>
<string name="expiry_date_dialog_title">Задати термін дії</string>
<string name="label_preferred">бажаний</string>
+ <!--label shown in Android settings under the OpenKeychain account-->
<!--Proxy Preferences-->
<!--proxy type choices and values-->
<!--OrbotHelper strings-->
@@ -293,6 +291,7 @@
<!--Delete result toast-->
<string name="delete_nothing">Нема що вилучати.</string>
<string name="delete_cancelled">Операція вилучення скасована.</string>
+ <!--Revoke result toast (snackbar)-->
<!--Certify result toast-->
<!--Intent labels-->
<string name="intent_decrypt_file">Розшифрувати файл з OpenKeychain</string>
@@ -308,20 +307,20 @@
<string name="api_settings_start">Запустити програму</string>
<string name="api_settings_delete_account">Видалити профіль</string>
<string name="api_settings_package_name">Назва пакунку</string>
- <string name="api_settings_package_certificate">SHA-256 підписку пакунку</string>
<string name="api_settings_settings">Параметри</string>
<string name="api_settings_accounts_empty">Немає облікового запису приєднаного до цієї програми.</string>
<string name="api_register_allow">Дозволити доступ</string>
<string name="api_register_disallow">Не дозволити доступ</string>
<string name="api_register_error_select_key">Будь ласка, виберіть ключ!</string>
- <string name="api_select_pub_keys_missing_text">Не знайдено жодного ключа для цих сутностей:</string>
- <string name="api_select_pub_keys_dublicates_text">Наявно більше одного ключа для цих сутностей:</string>
<string name="api_select_pub_keys_text">Будь ласка, перевірте список одержувачів!</string>
<string name="api_select_pub_keys_text_no_user_ids">Будь ласка, виберіть одержувачів!</string>
<string name="api_error_wrong_signature">Перевірка підпису пакету не вдалася! Може ви встановили програму з іншого джерела? Якщо ви впевнені, що це не атака, то відкличте реєстрацію програми у OpenKeychain та знову зареєструйте її.</string>
<!--Share-->
<string name="share_qr_code_dialog_title">Відправити як штрих-код</string>
<string name="share_nfc_dialog">Поділитися з NFC</string>
+ <!--retry upload dialog-->
+ <!--Delete or revoke private key dialog-->
+ <!--Delete Or Revoke Dialog spinner-->
<!--Key list-->
<plurals name="key_list_selected_keys">
<item quantity="one">1 ключ вибрано.</item>
@@ -510,6 +509,7 @@
<!--Messages for Keybase Verification operation-->
<!--Messages for Export Log operation-->
<!--PassphraseCache-->
+ <!--Keyserver sync-->
<!--First Time-->
<string name="first_time_text1">Заберіть вашу приватність із OpenKeychain!</string>
<string name="first_time_skip">Пропустити установку</string>
@@ -530,6 +530,7 @@
<string name="can_sign_not">не можна підписати</string>
<string name="error_no_encrypt_subkey">Жодний підключ шифрування недоступний!</string>
<string name="contact_show_key">Показати ключ (%s)</string>
+ <!--Android Account-->
<!--Passphrase wizard-->
<!--TODO: rename all the things!-->
<!--<string name="enter_passphrase_twice">Enter password twice</string>-->
diff --git a/OpenKeychain/src/main/res/values-vi/strings.xml b/OpenKeychain/src/main/res/values-vi/strings.xml
deleted file mode 100644
index 0713e39ad..000000000
--- a/OpenKeychain/src/main/res/values-vi/strings.xml
+++ /dev/null
@@ -1,78 +0,0 @@
-<?xml version='1.0' encoding='UTF-8'?>
-<resources>
- <!--GENERAL: Please put all strings inside quotes as described in example 1 on
- http://developer.android.com/guide/topics/resources/string-resource.html (scroll down to "Escaping apostrophes and quotes").-->
- <!--title-->
- <!--section-->
- <!--button-->
- <!--menu-->
- <!--label-->
- <!--Proxy Preferences-->
- <!--proxy type choices and values-->
- <!--OrbotHelper strings-->
- <!--InstallDialogFragment strings-->
- <!--StartOrbotDialogFragment strings-->
- <!--choice-->
- <!--key flags-->
- <!--sentences-->
- <!--errors
- no punctuation, all lowercase,
- they will be put after "error_message", e.g. "Error: file not found"-->
- <!--errors without preceeding Error:-->
- <!--results shown after decryption/verification-->
- <!--Add keys-->
- <!--progress dialogs, usually ending in '…'-->
- <!--action strings-->
- <!--key bit length selections-->
- <!--elliptic curve names-->
- <!--not in for now, see SaveKeyringParcel
- <string name="key_curve_bp_p256">"Brainpool P-256"</string>
- <string name="key_curve_bp_p384">"Brainpool P-384"</string>
- <string name="key_curve_bp_p512">"Brainpool P-512"</string>-->
- <!--compression-->
- <!--Help-->
- <!--Import-->
- <!--Import from URL-->
- <!--Generic result toast-->
- <!--Import result toast-->
- <!--Delete result toast-->
- <!--Certify result toast-->
- <!--Intent labels-->
- <!--Remote API-->
- <!--Share-->
- <!--Key list-->
- <!--Key view-->
- <!--Key trust-->
- <!--keybase proof stuff-->
- <!--Edit key-->
- <!--Create key-->
- <!--View key-->
- <!--Add/Edit keyserver-->
- <!--Navigation Drawer-->
- <!--hints-->
- <!--certs-->
- <!--LogType log messages. Errors should have _ERROR_ in their name and end with a !-->
- <!--Import Public log entries-->
- <!--Import Secret log entries-->
- <!--Keyring Canonicalization log entries-->
- <!--Keyring merging log entries-->
- <!--createSecretKeyRing-->
- <!--modifySecretKeyRing-->
- <!--Consolidate-->
- <!--Edit Key (higher level than modify)-->
- <!--Promote key-->
- <!--Other messages used in OperationLogs-->
- <!--Messages for DecryptVerify operation-->
- <!--Messages for VerifySignedLiteralData operation-->
- <!--Messages for SignEncrypt operation-->
- <!--Messages for PgpSignEncrypt operation-->
- <!--Messages for Keybase Verification operation-->
- <!--Messages for Export Log operation-->
- <!--PassphraseCache-->
- <!--First Time-->
- <!--unsorted-->
- <!--Passphrase wizard-->
- <!--TODO: rename all the things!-->
- <!--<string name="enter_passphrase_twice">Enter password twice</string>-->
- <!--<string name="nfc_text">Please place a NFC tag near your device</string>-->
-</resources>
diff --git a/OpenKeychain/src/main/res/values-zh-rTW/strings.xml b/OpenKeychain/src/main/res/values-zh-rTW/strings.xml
index 7005543bc..74d1cd781 100644
--- a/OpenKeychain/src/main/res/values-zh-rTW/strings.xml
+++ b/OpenKeychain/src/main/res/values-zh-rTW/strings.xml
@@ -11,7 +11,8 @@
<string name="title_edit_key">編輯金鑰</string>
<string name="title_preferences">設定</string>
<string name="title_api_registered_apps">應用程式</string>
- <string name="title_change_passphrase">修改密碼</string>
+ <string name="title_key_server_preference">OpenPGP金鑰伺服器</string>
+ <string name="title_change_passphrase">修改金鑰密碼</string>
<string name="title_share_fingerprint_with">分享指紋…</string>
<string name="title_share_key">分享金鑰…</string>
<string name="title_share_file">分享檔案…</string>
@@ -20,11 +21,11 @@
<string name="title_decrypt_to_file">解密到檔案</string>
<string name="title_import_keys">匯入金鑰</string>
<string name="title_export_key">匯出金鑰</string>
- <string name="title_export_keys">匯出所有金鑰</string>
+ <string name="title_export_keys">匯出金鑰</string>
<string name="title_key_not_found">找不到金鑰</string>
<string name="title_send_key">上傳到金鑰伺服器</string>
- <string name="title_certify_key">確認金鑰</string>
- <string name="title_key_details">金鑰內容</string>
+ <string name="title_certify_key">認證金鑰</string>
+ <string name="title_key_details">詳細內容</string>
<string name="title_help">說明</string>
<string name="title_log_display">紀錄</string>
<string name="title_exchange_keys">交換金鑰</string>
@@ -39,16 +40,24 @@
<string name="section_should_you_trust">您信任這把金鑰嗎?</string>
<string name="section_keys">子金鑰</string>
<string name="section_cloud_search">雲端查詢</string>
+ <string name="section_passphrase_cache">金鑰密碼快取</string>
+ <string name="section_proxy_settings">代理伺服器設定</string>
<string name="section_certify">確認</string>
<string name="section_actions">操作</string>
<string name="section_share_key">金鑰</string>
<string name="section_key_server">金鑰伺服器</string>
<string name="section_fingerprint">指紋</string>
<string name="section_encrypt">加密</string>
+ <string name="section_decrypt">解密/驗證</string>
+ <string name="section_current_expiry">目前有效期限</string>
+ <string name="section_new_expiry">新的有效期限</string>
<!--button-->
<string name="btn_decrypt_verify_file">解密並驗證檔案</string>
<string name="btn_encrypt_share_file">加密並分享檔案</string>
<string name="btn_encrypt_save_file">加密並儲存檔案</string>
+ <string name="btn_save_file">儲存檔案</string>
+ <string name="btn_save">儲存</string>
+ <string name="btn_view_log">查看紀錄</string>
<string name="btn_do_not_save">取消</string>
<string name="btn_delete">刪除</string>
<string name="btn_no_date">永不過期</string>
@@ -57,15 +66,23 @@
<string name="btn_next">下一步</string>
<string name="btn_back">返回</string>
<string name="btn_no">不</string>
- <string name="btn_match">指紋符合</string>
+ <string name="btn_match">指紋相符</string>
<string name="btn_share_encrypted_signed">加密並分享文字</string>
<string name="btn_copy_encrypted_signed">加密並複製文字</string>
<string name="btn_view_cert_key">檢視簽署的金鑰</string>
<string name="btn_create_key">建立金鑰</string>
<string name="btn_add_files">加入檔案</string>
+ <string name="btn_share_decrypted_text">分享已解密的訊息</string>
+ <string name="btn_copy_decrypted_text">複製已解密的訊息</string>
+ <string name="btn_decrypt_clipboard">從剪貼簿中讀取</string>
+ <string name="btn_decrypt_files">選擇要解密的檔案</string>
<string name="btn_encrypt_files">加密檔案</string>
<string name="btn_encrypt_text">加密文字</string>
<string name="btn_add_email">增加額外的電子郵件信箱</string>
+ <string name="btn_unlock">解鎖</string>
+ <string name="btn_add_keyserver">加入新伺服器</string>
+ <string name="btn_save_default">設為預設值</string>
+ <string name="btn_saved">已儲存</string>
<!--menu-->
<string name="menu_preferences">設定</string>
<string name="menu_help">說明</string>
@@ -78,9 +95,11 @@
<string name="menu_encrypt_to">加密到...</string>
<string name="menu_select_all">全選</string>
<string name="menu_export_all_keys">匯出所有金鑰</string>
- <string name="menu_update_all_keys">上傳所有金鑰</string>
+ <string name="menu_update_all_keys">更新所有金鑰</string>
+ <string name="menu_advanced">附加訊息</string>
<string name="menu_certify_fingerprint">藉由指紋比對來認證</string>
<string name="menu_export_log">匯出記錄</string>
+ <string name="menu_keyserver_add">新增</string>
<!--label-->
<string name="label_message">文字</string>
<string name="label_file">檔案</string>
@@ -92,21 +111,27 @@
<string name="label_passphrase_again">再次輸入密碼</string>
<string name="label_show_passphrase">顯示密碼</string>
<string name="label_algorithm">演算法</string>
+ <string name="label_file_ascii_armor">以ASCII輸出</string>
<string name="label_write_version_header">讓別人知道我在使用OpenKeychain</string>
<string name="label_write_version_header_summary">在簽名、密文與匯出的金鑰裡寫入\'OpenKeychain v2.7\'</string>
<string name="label_use_default_yubikey_pin">使用預設的 Yubikey PIN</string>
<string name="label_use_num_keypad_for_yubikey_pin">輸入 YubiKey PIN 時使用數字鍵盤</string>
<string name="label_label_use_default_yubikey_pin_summary">使用預設的 PIN (123456) 來使用 NFC 存取 Yubikeys</string>
+ <string name="label_asymmetric_from">簽名:</string>
<string name="label_to">加密給:</string>
<string name="label_delete_after_encryption">加密後刪除檔案</string>
<string name="label_delete_after_decryption">解密後刪除檔案</string>
<string name="label_encryption_algorithm">加密演算法</string>
<string name="label_hash_algorithm">雜湊演算法</string>
+ <string name="label_symmetric">透過密碼加密</string>
+ <string name="label_passphrase_cache_ttl">快取保存時間</string>
<string name="label_message_compression">文字壓縮</string>
<string name="label_file_compression">檔案壓縮</string>
+ <string name="label_keyservers">選擇OpenPGP金鑰伺服器</string>
<string name="label_key_id">金鑰ID</string>
+ <string name="label_key_created">金鑰 %s 已建立</string>
<string name="label_creation">建立</string>
- <string name="label_expiry">效期</string>
+ <string name="label_expiry">有效期限</string>
<string name="label_usage">用途</string>
<string name="label_key_size">金鑰長度</string>
<string name="label_ecc_curve">橢圓曲線</string>
@@ -116,16 +141,50 @@
<string name="label_email">電子郵件</string>
<string name="label_send_key">與雲端同步</string>
<string name="label_fingerprint">指紋</string>
- <string name="expiry_date_dialog_title">設定效期</string>
+ <string name="expiry_date_dialog_title">設定有效期限</string>
+ <string name="label_keyservers_title">金鑰伺服器</string>
+ <string name="label_keyserver_settings_hint">拖曳改變順序,點擊編輯或刪除。</string>
+ <string name="label_selected_keyserver_title">已選擇的金鑰伺服器</string>
<string name="label_preferred">優先</string>
<string name="label_enable_compression">啓用壓縮</string>
<string name="label_encrypt_filenames">加密檔名</string>
<string name="label_hidden_recipients">隱藏收件人</string>
+ <string name="label_verify_keyserver">驗證金鑰伺服器</string>
+ <string name="label_enter_keyserver_url">輸入金鑰伺服器網址</string>
+ <string name="label_keyserver_dialog_delete">刪除金鑰伺服器</string>
+ <string name="label_theme">主題</string>
+ <string name="pref_keyserver">OpenPGP金鑰伺服器</string>
+ <string name="pref_keyserver_summary">透過已選擇的金鑰伺服器搜尋金鑰(HKP 協定)</string>
+ <string name="pref_keybase">keybase.io</string>
+ <string name="pref_keybase_summary">在keybase.io上搜尋金鑰</string>
+ <!--label shown in Android settings under the OpenKeychain account-->
<!--Proxy Preferences-->
+ <string name="pref_proxy_tor_title">啟用洋蔥(Tor)網路</string>
+ <string name="pref_proxy_tor_summary">必須已安裝 Orbot</string>
+ <string name="pref_proxy_normal_title">啟用其他代理伺服器</string>
+ <string name="pref_proxy_host_title">Proxy主機位置</string>
+ <string name="pref_proxy_host_err_invalid">Proxy主機位置不能為空白</string>
+ <string name="pref_proxy_port_title">連接埠</string>
+ <string name="pref_proxy_port_err_invalid">無效的連結埠</string>
+ <string name="pref_proxy_type_title">Proxy類型</string>
<!--proxy type choices and values-->
+ <string name="pref_proxy_type_choice_http">HTTP</string>
+ <string name="pref_proxy_type_choice_socks">SOCKS</string>
<!--OrbotHelper strings-->
+ <string name="orbot_ignore_tor">不使用Tor</string>
<!--InstallDialogFragment strings-->
+ <string name="orbot_install_dialog_title">是否安裝Orbot以使用Tor?</string>
+ <string name="orbot_install_dialog_install">安裝</string>
+ <string name="orbot_install_dialog_content">您必須安裝Orbot並透過它進行網路代理。您是否要安裝Orbot?</string>
+ <string name="orbot_install_dialog_cancel">取消</string>
+ <string name="orbot_install_dialog_ignore_tor">不使用Tor</string>
<!--StartOrbotDialogFragment strings-->
+ <string name="orbot_start_dialog_title">啟動Orbot?</string>
+ <string name="orbot_start_dialog_content">Orbot尚未執行,您希望啟動它並連結到Tor嗎?</string>
+ <string name="orbot_start_btn">啟動Orbot</string>
+ <string name="orbot_start_dialog_start">啟動Orbot</string>
+ <string name="orbot_start_dialog_cancel">取消</string>
+ <string name="orbot_start_dialog_ignore_tor">不使用Tor</string>
<string name="user_id_no_name">&lt;無名&gt;</string>
<string name="none">&lt;無&gt;</string>
<plurals name="n_keys">
@@ -134,7 +193,7 @@
<plurals name="n_keyservers">
<item quantity="other">%d 金鑰伺服器</item>
</plurals>
- <string name="secret_key">密鑰:</string>
+ <string name="secret_key">私鑰:</string>
<!--choice-->
<string name="choice_none">無</string>
<string name="choice_15secs">15秒</string>
@@ -157,25 +216,36 @@
<string name="filemanager_title_open">開啟…</string>
<string name="error">錯誤</string>
<string name="error_message">錯誤: %s</string>
+ <string name="theme_dark">深色</string>
+ <string name="theme_light">亮色</string>
<!--key flags-->
<string name="flag_certify">簽署</string>
<string name="flag_sign">簽名</string>
<string name="flag_encrypt">加密</string>
<string name="flag_authenticate">驗證</string>
<!--sentences-->
+ <string name="wrong_passphrase">密碼錯誤。</string>
<string name="no_filemanager_installed">找不到相容的檔案管理員。</string>
+ <string name="passphrases_do_not_match">密碼不相符。</string>
+ <string name="passphrase_must_not_be_empty">請輸入密碼。</string>
<string name="passphrase_for_symmetric_encryption">對稱加密。</string>
+ <string name="passphrase_for">輸入 %s 的密碼</string>
<string name="pin_for">輸入 \'%s\' 的 PIN</string>
<string name="yubikey_pin_for">輸入 PIN 來存取 \'%s\' 的 YubiKey</string>
<string name="file_delete_confirmation_title">刪除原始檔案?</string>
<string name="file_delete_confirmation">下列的檔案將會被刪除:%s</string>
<string name="file_delete_successful">%1$d 之 %2$d 的檔案已經被刪除。%3$s</string>
+ <string name="no_file_selected">沒有選擇檔案。</string>
<string name="encrypt_sign_successful">成功簽名並/或加密。</string>
<string name="encrypt_sign_clipboard_successful">成功簽名並/或加密到剪貼簿。</string>
<string name="select_encryption_key">選擇至少一把加密金鑰。</string>
+ <string name="error_no_encryption_or_signature_key">請選擇至少一把加密用金鑰或簽名用金鑰。</string>
<string name="specify_file_to_encrypt_to">請指定欲加密的檔案。\n警告:已經存在的檔案將被覆蓋。</string>
<string name="specify_file_to_decrypt_to">請指定欲解密的檔案。\n警告:已經存在的檔案將被覆蓋。</string>
- <string name="specify_backup_dest">請指定欲輸出的檔案。\n警告:已經存在的檔案將被覆蓋。</string>
+ <string name="specify_backup_dest">將匯出不包含您自己金鑰的備份,請選擇輸出檔案位置。\n注意:已經存在的檔案將被覆蓋。</string>
+ <string name="specify_backup_dest_single">將匯出這把公鑰,請選擇輸出檔案位置。\n警告:已經存在的檔案將被覆蓋。</string>
+ <string name="specify_backup_dest_secret_single">將匯出公鑰及私鑰,請選擇輸出檔案位置。\n注意:已經存在的檔案將被覆蓋。</string>
+ <string name="specify_backup_dest_secret">將匯出所有金鑰,包含您自己的公鑰及私鑰,請選擇輸出檔案位置。\n注意:已經存在的檔案將被覆蓋。</string>
<string name="key_deletion_confirmation_multi">您真的想要刪除所有已選金鑰嗎?</string>
<string name="secret_key_deletion_confirmation">刪除之後您將無法閱讀以這把金鑰加密的訊息,而且所有用這把金鑰做的認證都會失效!</string>
<string name="public_key_deletetion_confirmation">刪除金鑰 \'%s\' ?</string>
@@ -207,31 +277,37 @@
<string name="error_external_storage_not_ready">外部儲存空間尚未就緒</string>
<string name="error_key_size_minimum512bit">金鑰長度必須大於512位元</string>
<string name="error_unknown_algorithm_choice">不明的演算法選擇</string>
+ <string name="error_user_id_no_email">沒有找到電子郵件</string>
<string name="error_key_needs_a_user_id">需要至少一個身分識別</string>
<string name="error_no_signature_key">找不到簽名金鑰</string>
<string name="error_invalid_data">沒有有效的 OpenPGP 加密或簽署內容 !</string>
<string name="error_integrity_check_failed">完整性檢查失敗!資料已被修改!</string>
+ <string name="error_wrong_passphrase">密碼錯誤</string>
<string name="error_could_not_extract_private_key">無法抽取私鑰</string>
<!--errors without preceeding Error:-->
<string name="error_jelly_bean_needed">需要Android 4.1以上才能使用NFC Beam功能!</string>
<string name="error_nfc_needed">NFC 必須開啓 !</string>
<string name="error_beam_needed">Bean 必須開啓 !</string>
<string name="error_nothing_import">找不到金鑰!</string>
+ <string name="error_nothing_import_selected">沒有選擇匯入的金鑰!</string>
<string name="error_contacts_key_id_missing">從聯絡人取回金鑰 ID 失敗 !</string>
<string name="error_generic_report_bug">發生錯誤,請建立一個新的錯誤回報給 OpenKeychain。</string>
<!--results shown after decryption/verification-->
<string name="decrypt_result_no_signature">尚未簽名</string>
<string name="decrypt_result_invalid_signature">無效的簽章!</string>
+ <string name="decrypt_result_insecure_cryptography">無效的簽名(此加密不安全)!</string>
<string name="decrypt_result_signature_uncertified">由<b>未確認</b>的金鑰所簽署</string>
- <string name="decrypt_result_signature_secret">由你的金鑰所簽署</string>
+ <string name="decrypt_result_signature_secret">由您的金鑰所簽署</string>
<string name="decrypt_result_signature_certified">由已確認的金鑰所簽署</string>
<string name="decrypt_result_signature_expired_key">由<b>已過期</b>的金鑰所簽署!</string>
<string name="decrypt_result_signature_revoked_key">由<b>已撤銷</b>的金鑰所簽署!</string>
<string name="decrypt_result_signature_missing_key">由<b>未知的金鑰</b>所簽署</string>
<string name="decrypt_result_encrypted">已加密</string>
<string name="decrypt_result_not_encrypted">未加密</string>
+ <string name="decrypt_result_insecure">不安全的加密</string>
<string name="decrypt_result_action_show">顯示</string>
<string name="decrypt_result_action_Lookup">查詢</string>
+ <string name="decrypt_invalid_text">包含無效的簽名或已撤銷得金鑰,您並無法確保此加密的來源,您依舊要顯示內容嗎?</string>
<string name="decrypt_invalid_button">我明白這樣做的風險,顯示它!</string>
<!--Add keys-->
<string name="add_keys_my_key">我的金鑰:</string>
@@ -241,6 +317,7 @@
<string name="progress_cancelling">正在取消…</string>
<string name="progress_saving">正在儲存…</string>
<string name="progress_importing">匯入中…</string>
+ <string name="progress_revoking_uploading">正在撤銷並上傳金鑰...</string>
<string name="progress_updating">正在更新金鑰...</string>
<string name="progress_exporting">匯出中…</string>
<string name="progress_uploading">正在上傳…</string>
@@ -261,9 +338,13 @@
<string name="progress_modify_subkeyrevoke">正在撤銷子金鑰…</string>
<string name="progress_modify_subkeystrip">正在卸除子金鑰...</string>
<string name="progress_modify_subkeyadd">正在新增子金鑰…</string>
+ <string name="progress_modify_passphrase">正在變更金鑰密碼...</string>
+ <string name="progress_modify_pin">正在變更PIN碼...</string>
+ <string name="progress_modify_admin_pin">正在變更管理者PIN碼...</string>
<plurals name="progress_exporting_key">
<item quantity="other">正在匯出金鑰…</item>
</plurals>
+ <string name="progress_start">正在準備進行操作...</string>
<string name="progress_extracting_signature_key">正在抽取簽名金鑰…</string>
<string name="progress_extracting_key">正在抽取金鑰…</string>
<string name="progress_preparing_streams">正在準備串流…</string>
@@ -281,6 +362,8 @@
<string name="progress_verifying_integrity">正在驗證完整性…</string>
<string name="progress_deleting_securely">正在安全地刪除 \'%s\'...</string>
<string name="progress_deleting">正在刪除金鑰…</string>
+ <string name="progress_verifying_keyserver_url">正在驗證金鑰伺服器...</string>
+ <string name="progress_starting_orbot">正在啟動Orbot...</string>
<!--action strings-->
<string name="hint_cloud_search_hint">使用姓名,電子郵件尋找...</string>
<!--key bit length selections-->
@@ -322,10 +405,13 @@
<string name="import_tab_qr_code">二維條碼/NFC</string>
<string name="import_import">匯入選擇的金鑰</string>
<string name="import_qr_code_wrong">QR Code 異常 ! 請再試一次 !</string>
+ <string name="import_qr_code_fp">指紋異常或長度不足!</string>
+ <string name="import_qr_code_too_short_fingerprint">長度不足!</string>
<string name="import_qr_code_button">掃描二維條碼</string>
<string name="import_qr_code_text">將您的相機對準 QR Code !</string>
<!--Import from URL-->
<!--Generic result toast-->
+ <string name="snackbar_details">詳細資訊</string>
<string name="with_warnings">,包含警告</string>
<string name="with_cancelled">,直到被取消</string>
<!--Import result toast-->
@@ -364,6 +450,11 @@
</plurals>
<string name="delete_nothing">沒有東西可以刪除。</string>
<string name="delete_cancelled">刪除已取消。</string>
+ <!--Revoke result toast (snackbar)-->
+ <string name="revoke_ok">成功撤銷金鑰。</string>
+ <string name="revoke_fail">錯誤的撤銷金鑰!</string>
+ <string name="revoke_nothing">沒有任何金鑰被撤銷。</string>
+ <string name="revoke_cancelled">撤銷動作被取消。</string>
<!--Certify result toast-->
<plurals name="certify_keys_ok">
<item quantity="other">成功認證 %1$d 金鑰%2$s。</item>
@@ -394,7 +485,7 @@
<string name="api_settings_start">開啟應用程式</string>
<string name="api_settings_delete_account">移除帳戶</string>
<string name="api_settings_package_name">打包名稱</string>
- <string name="api_settings_package_certificate">SHA-256 所打包的簽章</string>
+ <string name="api_settings_package_certificate">封裝證書的SHA-256</string>
<string name="api_settings_accounts">帳戶(舊版API)</string>
<string name="api_settings_advanced">延伸資訊</string>
<string name="api_settings_allowed_keys">允許的金鑰</string>
@@ -406,10 +497,24 @@
<string name="api_register_text">應用程式試圖以您的名義加/解密訊息並簽名,是否允許存取?\n\n警告:如果你不知道為什麼出現這個畫面,請拒絕存取!你可以稍後在〝應用程式〞畫面撤銷存取。</string>
<string name="api_register_allow">允許存取</string>
<string name="api_register_disallow">拒絕存取</string>
- <string name="api_error_wrong_signature">簽名檢查失敗!你是否從其他來源安裝此應用?如果你確定這不是個攻擊,撤銷並重新註冊應用程式到OpenKeychain。</string>
+ <string name="api_register_error_select_key">請選擇一個金鑰!</string>
+ <string name="api_select_pub_keys_text">請檢查收件人清單!</string>
+ <string name="api_select_pub_keys_text_no_user_ids">請選擇一份清單!</string>
+ <string name="api_error_wrong_signature">簽名檢查失敗!你是否從其他來源安裝此應用程式?如果你確定這不是個攻擊,撤銷並重新註冊應用程式到OpenKeychain。</string>
+ <string name="api_select_sign_key_text">請選擇一個您的金鑰或建立一個新的金鑰。</string>
+ <string name="api_select_keys_text">沒有被允許的金鑰可以解密內容,請選擇被允許的金鑰。</string>
<!--Share-->
<string name="share_qr_code_dialog_title">以二維條碼分享</string>
<string name="share_nfc_dialog">以NFC分享</string>
+ <!--retry upload dialog-->
+ <string name="retry_up_dialog_title">上傳失敗</string>
+ <string name="retry_up_dialog_message">上傳失敗。是否再次嘗試上傳?</string>
+ <string name="retry_up_dialog_btn_reupload">重試</string>
+ <string name="retry_up_dialog_btn_cancel">取消</string>
+ <!--Delete or revoke private key dialog-->
+ <string name="del_rev_dialog_btn_delete">只刪除金鑰</string>
+ <!--Delete Or Revoke Dialog spinner-->
+ <string name="del_rev_dialog_choice_delete">只刪除金鑰</string>
<!--Key list-->
<string name="key_list_empty_text1">找不到金鑰!</string>
<!--Key view-->
@@ -422,6 +527,7 @@
<string name="key_view_tab_main">摘要</string>
<string name="key_view_tab_share">分享</string>
<string name="key_view_tab_keys">子金鑰</string>
+ <string name="key_view_tab_certs">簽署</string>
<string name="key_view_tab_keybase">Keybase.io</string>
<string name="user_id_info_revoked_title">已撤銷</string>
<string name="user_id_info_revoked_text">這個身分識別被金鑰持有人撤銷,已不再有效。</string>
@@ -430,24 +536,20 @@
<string name="user_id_info_uncertified_title">未認證</string>
<string name="user_id_info_uncertified_text">這個身分識別尚未經過認證,你不能確認這個身分識別是否屬於真的某個人。</string>
<string name="user_id_info_invalid_title">無效</string>
+ <string name="user_id_info_invalid_text">這個身份有些錯誤!</string>
<!--Key trust-->
+ <string name="key_trust_already_verified">您已經確認這把金鑰!</string>
+ <string name="key_trust_it_is_yours">這把是您的金鑰!</string>
<string name="key_trust_maybe">這把金鑰未被撤銷且尚未過期。\n金鑰尚未進行確認,但你可以選擇信任它。</string>
- <string name="key_trust_revoked">這把金鑰已被持有者撤銷。你不應該信任它。</string>
- <string name="key_trust_expired">這把金鑰已經過期。你不應該信任它。</string>
+ <string name="key_trust_revoked">這把金鑰已被持有者撤銷。您不應該信任它。</string>
+ <string name="key_trust_expired">這把金鑰已經過期。您不應該信任它。</string>
<string name="key_trust_old_keys">用來解密在金鑰失效前加密的訊息還勉強可以接受。</string>
- <string name="key_trust_no_cloud_evidence">雲端上沒有證據能證明這把金鑰可信度。</string>
+ <string name="key_trust_no_cloud_evidence">雲端上沒有證據能證明這把金鑰的可信度。</string>
<string name="key_trust_start_cloud_search">開始搜尋</string>
<string name="key_trust_results_prefix">Keybase.io提供“證據”證明這把金鑰的持有人:</string>
<string name="key_trust_header_text">注意:Keybase.io證據是個OpenKeychain實驗性功能。我們推薦你另外以QR條碼或是NFC交換金鑰進行確認。</string>
<!--keybase proof stuff-->
- <string name="keybase_narrative_twitter">用下列身分在Twitter發布訊息:</string>
- <string name="keybase_narrative_github">用下列身分在GitHub活動:</string>
- <string name="keybase_narrative_dns">掌控這些域名:</string>
- <string name="keybase_narrative_web_site">能在這些網站張貼文章:</string>
- <string name="keybase_narrative_reddit">用下列身分在Reddit參與討論:</string>
- <string name="keybase_narrative_coinbase">擁有這些Coinbase帳戶:</string>
- <string name="keybase_narrative_hackernews">用下列身分在Hacker News發表文章:</string>
- <string name="keybase_narrative_unknown">未知的證據型態</string>
+ <string name="keybase_narrative_twitter">用下列身分在Twitter參與討論:%s</string>
<string name="keybase_proof_failure">很不幸地我們沒法驗證這些證據。</string>
<string name="keybase_unknown_proof_failure">檢查證據的過程遇到無法辨識的問題</string>
<string name="keybase_message_fetching_data">取得證據中</string>
@@ -460,15 +562,21 @@
<string name="keybase_dns_proof">一筆DNS TXT記錄</string>
<string name="keybase_web_site_proof">一個文字檔案</string>
<string name="keybase_reddit_proof">一個JSON檔案</string>
+ <string name="keybase_verify">驗證</string>
<!--Edit key-->
+ <string name="edit_key_action_change_passphrase">變更金鑰密碼</string>
<string name="edit_key_action_add_identity">新增身分識別</string>
<string name="edit_key_action_add_subkey">新增子金鑰</string>
+ <string name="edit_key_edit_user_id_title">選擇一個動作!</string>
<string-array name="edit_key_edit_user_id">
<item>變更為主身分識別</item>
<item>撤銷身分識別</item>
</string-array>
+ <string-array name="edit_key_edit_user_id_revert_revocation">
+ <item>還原撤銷</item>
+ </string-array>
<string name="edit_key_edit_user_id_revoked">這個身分識別已被撤銷。此動作無法還原。</string>
- <string name="edit_key_edit_subkey_title">選擇操作動作!</string>
+ <string name="edit_key_edit_subkey_title">選擇一個動作!</string>
<string-array name="edit_key_edit_subkey">
<item>變更效期</item>
<item>撤銷子金鑰</item>
@@ -476,6 +584,7 @@
<item>移動子金鑰至YubiKey / 智慧卡</item>
</string-array>
<string name="edit_key_new_subkey">新增子金鑰</string>
+ <string name="edit_key_select_flag">請至少選擇一個用途!</string>
<string name="edit_key_error_add_identity">新增至少一組身分識別!</string>
<string name="edit_key_error_add_subkey">新增至少一組子金鑰!</string>
<string name="edit_key_error_bad_nfc_algo">智慧卡不支援該算法!</string>
@@ -485,15 +594,26 @@
<string name="create_key_upload">與雲端同步</string>
<string name="create_key_empty">必填欄位</string>
<string name="create_key_passphrases_not_equal">密碼不相符</string>
+ <string name="create_key_final_text">您輸入了以下資訊:</string>
<string name="create_key_final_robot_text">建立金鑰可能需要一點時間,來杯咖啡吧…</string>
<string name="create_key_rsa">(3把子金鑰,RSA,4096位元)</string>
<string name="create_key_custom">(自定義金鑰組合)</string>
<string name="create_key_name_text">選擇一個名字有關這個金鑰。 這可以是全名John Doe或是暱稱Johnny。</string>
+ <string name="create_key_email_text">輸入您的主要電子郵件,這提供您安全的通訊。</string>
+ <string name="create_key_passphrase_text">請選擇一個強度足夠的金鑰密碼,當您的裝置遺失時它將保護您的金鑰。</string>
<string name="create_key_hint_full_name">全名或暱稱</string>
<string name="create_key_edit">變更金鑰設置</string>
<string name="create_key_add_email">新增電子郵件</string>
+ <string name="create_key_add_email_text">附加的電子郵件同樣與您的金鑰有所關聯,可以提供您安全的通訊。</string>
<string name="create_key_email_already_exists_text">電子郵件地址已經存在</string>
<string name="create_key_email_invalid_email">電子郵件地址無效</string>
+ <string name="create_key_yubi_key_pin_text">請記住您的PIN碼,等會兒您的YubiKey需要它。請紀錄下管理者PIN碼並且將它保存在安全的地方。</string>
+ <string name="create_key_yubi_key_pin">PIN碼</string>
+ <string name="create_key_yubi_key_admin_pin">管理者PIN碼</string>
+ <string name="create_key_yubi_key_pin_repeat_text">請輸入PIN碼及管理者PIN碼以繼續執行。</string>
+ <string name="create_key_yubi_key_pin_repeat">重複PIN碼</string>
+ <string name="create_key_yubi_key_admin_pin_repeat">重複管理者PIN碼</string>
+ <string name="create_key_yubi_key_pin_not_correct">PIN碼不正確!</string>
<!--View key-->
<string name="view_key_revoked">已撤銷:不該再使用此金鑰!</string>
<string name="view_key_expired">已過期:聯絡人需要去展延金鑰的效期!</string>
@@ -503,21 +623,34 @@
<string name="view_key_unverified">未確認:掃描QR條碼來確認該金鑰!</string>
<string name="view_key_fragment_no_system_contact">&lt;無&gt;</string>
<!--Add/Edit keyserver-->
+ <string name="add_keyserver_dialog_title">新增金鑰伺服器</string>
+ <string name="edit_keyserver_dialog_title">編輯金鑰伺服器</string>
+ <string name="add_keyserver_verified">已驗證金鑰伺服器!</string>
+ <string name="add_keyserver_without_verification">已新增金鑰伺服器但並未進行驗證。</string>
<string name="add_keyserver_invalid_url">URL無效!</string>
+ <string name="add_keyserver_connection_failed">連線到金鑰伺服器失敗。請確認金鑰伺服器網址及網路連線。</string>
+ <string name="keyserver_preference_deleted">已刪除 %s</string>
+ <string name="keyserver_preference_cannot_delete_last">無法刪除金鑰伺服器。請至少保留一個金鑰伺服器!</string>
<!--Navigation Drawer-->
<string name="nav_keys">金鑰</string>
<string name="nav_encrypt_decrypt">加密/解密</string>
<string name="nav_apps">應用程式</string>
+ <string name="drawer_open">開啟導航列</string>
+ <string name="drawer_close">關閉導航列</string>
<string name="my_keys">我的金鑰</string>
+ <string name="nav_backup">備份</string>
<!--hints-->
+ <string name="encrypt_content_edit_text_hint">輸入文字</string>
<!--certs-->
<string name="cert_default">預設</string>
<string name="cert_none">無</string>
<string name="cert_casual">隨意的</string>
<string name="cert_positive">積極的</string>
+ <string name="cert_revoke">已撤銷</string>
<string name="cert_verify_ok">OK</string>
<string name="cert_verify_failed">失敗!</string>
<string name="cert_verify_error">錯誤!</string>
+ <string name="cert_verify_unavailable">金鑰無法使用</string>
<!--LogType log messages. Errors should have _ERROR_ in their name and end with a !-->
<string name="msg_internal_error">內部錯誤!</string>
<string name="msg_cancelled">操作已取消。</string>
@@ -527,6 +660,9 @@
<string name="msg_ip_error_io_exc">操作失敗,因為I/O錯誤</string>
<string name="msg_ip_error_op_exc">操作失敗,因為資料庫錯誤</string>
<string name="msg_ip_error_remote_ex">操作失敗,因為內部錯誤</string>
+ <string name="msg_ip">匯入公鑰鑰匙圈 %s</string>
+ <string name="msg_ip_insert_keys">正在解析金鑰</string>
+ <string name="msg_ip_prepare">正在準備資料庫</string>
<string name="msg_ip_master_flags_unspecified">主要標記:未指定(全用途)</string>
<string name="msg_ip_master_flags_cesa">主要標記:認證、加密、簽署、驗證</string>
<string name="msg_ip_master_flags_cesx">主要標記:認證、加密、簽署</string>
@@ -607,7 +743,7 @@
<string name="msg_export_error_io">輸入/輸出錯誤!</string>
<string name="msg_export_success">匯出處理成功</string>
<string name="msg_del_error_empty">沒有東西可以刪除!</string>
- <string name="msg_del_error_multi_secret">密鑰只能分別刪除!</string>
+ <string name="msg_del_error_multi_secret">私鑰只能分別刪除!</string>
<string name="msg_acc_saved">帳戶已儲存</string>
<string name="msg_download_success">下載成功!</string>
<string name="msg_download_no_valid_keys">在檔案/剪貼簿中找不到有效的金鑰!</string>
@@ -615,6 +751,7 @@
<!--Messages for Keybase Verification operation-->
<!--Messages for Export Log operation-->
<!--PassphraseCache-->
+ <!--Keyserver sync-->
<!--First Time-->
<string name="first_time_create_key">建立金鑰</string>
<string name="first_time_import_key">從檔案匯入金鑰</string>
@@ -627,12 +764,13 @@
<string name="label_revocation">撤銷原因</string>
<string name="error_key_not_found">找不到金鑰!</string>
<string name="key_unavailable">無法使用</string>
+ <string name="secret_cannot_multiple">您的金鑰只能個別地刪除!</string>
<string name="title_view_cert">查看認證內容</string>
<string name="unknown_algorithm">未知</string>
<string name="error_no_encrypt_subkey">沒有可供加密的子金鑰!</string>
- <string name="account_no_manual_account_creation">請不要自行建立OpenKeychain帳戶。\n更多資訊請參考說明。</string>
<string name="exchange_description">要發起金鑰交換,先在右邊選擇與會人數,然後點選〝開始交換〞。\n\n接下來會詢問你兩個問題,以確保會議成員與交換的指紋是正確的。</string>
<string name="btn_start_exchange">開始交換</string>
+ <!--Android Account-->
<!--Passphrase wizard-->
<!--TODO: rename all the things!-->
<!--<string name="enter_passphrase_twice">Enter password twice</string>-->
diff --git a/OpenKeychain/src/main/res/values-zh/strings.xml b/OpenKeychain/src/main/res/values-zh/strings.xml
index 180167e3e..ad85fd8ce 100644
--- a/OpenKeychain/src/main/res/values-zh/strings.xml
+++ b/OpenKeychain/src/main/res/values-zh/strings.xml
@@ -29,22 +29,38 @@
<string name="title_help">帮助</string>
<string name="title_log_display">日志</string>
<string name="title_exchange_keys">交换密钥</string>
+ <string name="title_advanced_key_info">更多信息</string>
+ <string name="title_delete_secret_key">删除你的密钥 \'%s\' ?</string>
<string name="title_export_log">导出日志</string>
<string name="title_manage_my_keys">管理我的密钥</string>
<!--section-->
<string name="section_user_ids">用户名</string>
<string name="section_yubikey">YubiKey</string>
+ <string name="section_linked_system_contact">关联系统联系人</string>
<string name="section_should_you_trust">应该相信此密钥?</string>
+ <string name="section_proof_details">验证</string>
+ <string name="section_cloud_evidence">云端验证</string>
<string name="section_keys">子密钥</string>
<string name="section_cloud_search">在线搜索</string>
+ <string name="section_passphrase_cache">密码缓存</string>
+ <string name="section_proxy_settings">代理服务器设置</string>
+ <string name="section_gui">界面</string>
<string name="section_certify">确认</string>
<string name="section_actions">动作</string>
+ <string name="section_share_key">分享密钥</string>
<string name="section_key_server">密钥服务器</string>
<string name="section_fingerprint">签名</string>
<string name="section_encrypt">加密</string>
+ <string name="section_decrypt">解密/验证</string>
+ <string name="section_current_expiry">当前有效期</string>
+ <string name="section_new_expiry">新有效期</string>
<!--button-->
<string name="btn_decrypt_verify_file">解密并验证文件</string>
<string name="btn_encrypt_share_file">加密并分享文件</string>
+ <string name="btn_encrypt_save_file">加密至文件</string>
+ <string name="btn_save_file">保存文件</string>
+ <string name="btn_save">保存</string>
+ <string name="btn_view_log">查看日志</string>
<string name="btn_do_not_save">取消</string>
<string name="btn_delete">删除</string>
<string name="btn_no_date">没有日期</string>
@@ -52,6 +68,8 @@
<string name="btn_export_to_server">导出到服务器</string>
<string name="btn_next">下一步</string>
<string name="btn_back">返回</string>
+ <string name="btn_no">否</string>
+ <string name="btn_match">密钥指纹符合</string>
<string name="btn_share_encrypted_signed">加密并分享</string>
<string name="btn_copy_encrypted_signed">加密并复制</string>
<string name="btn_view_cert_key">显示密钥</string>
@@ -59,16 +77,19 @@
<string name="btn_add_files">添加密钥</string>
<string name="btn_share_decrypted_text">分享解密文本</string>
<string name="btn_copy_decrypted_text">复制解密文本</string>
+ <string name="btn_decrypt_clipboard">从剪贴板导入</string>
+ <string name="btn_decrypt_files">选择导入文件</string>
<string name="btn_encrypt_files">加密文件</string>
<string name="btn_encrypt_text">加密文本</string>
<string name="btn_add_email">添加额外的邮件地址</string>
<string name="btn_unlock">解锁</string>
<string name="btn_add_keyserver">添加</string>
+ <string name="btn_save_default">保存为默认值</string>
<string name="btn_saved">已保存</string>
<!--menu-->
<string name="menu_preferences">参数设置</string>
<string name="menu_help">帮助</string>
- <string name="menu_export_key">导出密钥</string>
+ <string name="menu_export_key">导出到文件</string>
<string name="menu_delete_key">删除密钥</string>
<string name="menu_manage_keys">管理我的密钥</string>
<string name="menu_search">搜索</string>
@@ -79,10 +100,14 @@
<string name="menu_export_all_keys">导出全部密钥</string>
<string name="menu_update_all_keys">更新所有密钥</string>
<string name="menu_advanced">更多信息</string>
+ <string name="menu_certify_fingerprint">通过密钥指纹比较确认</string>
<string name="menu_export_log">导出日志</string>
+ <string name="menu_keyserver_add">添加</string>
<!--label-->
+ <string name="label_message">文本</string>
<string name="label_file">文件</string>
<string name="label_files">多个文件</string>
+ <string name="label_file_colon">文件:</string>
<string name="label_no_passphrase">没有密码</string>
<string name="label_passphrase">密码</string>
<string name="label_unlock">解锁中...</string>
@@ -92,7 +117,10 @@
<string name="label_ascii_armor">文件ASCII文本化</string>
<string name="label_file_ascii_armor">启用ASCII文本化</string>
<string name="label_write_version_header">写入文件头信息</string>
+ <string name="label_write_version_header_summary">在OpenPGP签名、加密文本和导出密钥中写入 \'OpenKeychain v2.7\' 标记。</string>
<string name="label_use_default_yubikey_pin">使用默认YubiKey PIN</string>
+ <string name="label_use_num_keypad_for_yubikey_pin">为YubiKey PIN使用数字键盘</string>
+ <string name="label_label_use_default_yubikey_pin_summary">使用默认PIN (123456)访问YubiKeys</string>
<string name="label_message_compression">文本压缩</string>
<string name="label_file_compression">文件压缩</string>
<string name="label_keyservers">选择OpenPGP 密钥服务器</string>
@@ -108,8 +136,17 @@
<string name="expiry_date_dialog_title">有效期</string>
<string name="label_encrypt_filenames">加密文件名</string>
<string name="pref_keyserver">OpenPGP 密钥服务器</string>
+ <!--label shown in Android settings under the OpenKeychain account-->
<!--Proxy Preferences-->
+ <string name="pref_proxy_normal_title">启用其它代理服务器</string>
+ <string name="pref_proxy_host_title">服务器地址</string>
+ <string name="pref_proxy_host_err_invalid">服务器地址不能为空</string>
+ <string name="pref_proxy_port_title">端口</string>
+ <string name="pref_proxy_port_err_invalid">不正确的端口</string>
+ <string name="pref_proxy_type_title">类型</string>
<!--proxy type choices and values-->
+ <string name="pref_proxy_type_choice_http">HTTP</string>
+ <string name="pref_proxy_type_choice_socks">SOCKS</string>
<!--OrbotHelper strings-->
<!--InstallDialogFragment strings-->
<!--StartOrbotDialogFragment strings-->
@@ -218,6 +255,7 @@
<!--Generic result toast-->
<!--Import result toast-->
<!--Delete result toast-->
+ <!--Revoke result toast (snackbar)-->
<!--Certify result toast-->
<!--Intent labels-->
<!--Remote API-->
@@ -231,6 +269,9 @@
<string name="api_select_pub_keys_text">请重审收件人列表</string>
<!--Share-->
<string name="share_nfc_dialog">使用NFC分享</string>
+ <!--retry upload dialog-->
+ <!--Delete or revoke private key dialog-->
+ <!--Delete Or Revoke Dialog spinner-->
<!--Key list-->
<!--Key view-->
<!--Key trust-->
@@ -260,8 +301,10 @@
<!--Messages for Keybase Verification operation-->
<!--Messages for Export Log operation-->
<!--PassphraseCache-->
+ <!--Keyserver sync-->
<!--First Time-->
<!--unsorted-->
+ <!--Android Account-->
<!--Passphrase wizard-->
<!--TODO: rename all the things!-->
<!--<string name="enter_passphrase_twice">Enter password twice</string>-->
diff --git a/OpenKeychain/src/main/res/values/arrays.xml b/OpenKeychain/src/main/res/values/arrays.xml
index ef3970672..28b6fcd78 100644
--- a/OpenKeychain/src/main/res/values/arrays.xml
+++ b/OpenKeychain/src/main/res/values/arrays.xml
@@ -34,8 +34,8 @@
<item>@string/pref_proxy_type_choice_socks</item>
</string-array>
<string-array name="pref_proxy_type_values" translatable="false">
- <item>@string/pref_proxy_type_value_http</item>
- <item>@string/pref_proxy_type_value_socks</item>
+ <item>"proxyHttp"</item>
+ <item>"proxySocks"</item>
</string-array>
<string-array name="rev_del_dialog_entries" translatable="true">
<item>@string/del_rev_dialog_choice_rev_upload</item>
@@ -67,6 +67,6 @@
</string-array>
<string-array name="theme_values" translatable="false">
<item>"dark"</item>
- <item>"ligh"</item>
+ <item>"light"</item>
</string-array>
</resources>
diff --git a/OpenKeychain/src/main/res/values/attr.xml b/OpenKeychain/src/main/res/values/attr.xml
index 04642cabb..1a414e6d9 100644
--- a/OpenKeychain/src/main/res/values/attr.xml
+++ b/OpenKeychain/src/main/res/values/attr.xml
@@ -33,4 +33,8 @@
<attr name="color_strong" format="color" />
</declare-styleable>
+ <declare-styleable name="PrefixedEditText">
+ <attr name="prefix" format="string" />
+ </declare-styleable>
+
</resources> \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/values/colors.xml b/OpenKeychain/src/main/res/values/colors.xml
index 5db66b945..06fe2a9cd 100644
--- a/OpenKeychain/src/main/res/values/colors.xml
+++ b/OpenKeychain/src/main/res/values/colors.xml
@@ -29,4 +29,8 @@
<color name="android_green_light">#7bad45</color>
<color name="android_green_dark">#6c983d</color>
+ <!-- text protection scrim colors -->
+ <color name="translucent_scrim_bottom">#2A000000</color>
+ <color name="translucent_scrim_bottom_center">#2A000000</color>
+
</resources>
diff --git a/OpenKeychain/src/main/res/values/strings.xml b/OpenKeychain/src/main/res/values/strings.xml
index 6aa968756..56bb95f3f 100644
--- a/OpenKeychain/src/main/res/values/strings.xml
+++ b/OpenKeychain/src/main/res/values/strings.xml
@@ -14,6 +14,7 @@
<string name="title_decrypt">"Decrypt"</string>
<string name="title_add_subkey">"Add subkey"</string>
<string name="title_edit_key">"Edit Key"</string>
+ <string name="title_linked_create">"Create a Linked Identity"</string>
<string name="title_preferences">"Settings"</string>
<string name="title_api_registered_apps">"Apps"</string>
<string name="title_key_server_preference">"OpenPGP keyservers"</string>
@@ -36,21 +37,26 @@
<string name="title_exchange_keys">"Exchange Keys"</string>
<string name="title_advanced_key_info">"Extended Information"</string>
<string name="title_delete_secret_key">"Delete YOUR key '%s'?"</string>
- <string name="title_export_log">"Export Log"</string>
<string name="title_manage_my_keys">"Manage my keys"</string>
<!-- section -->
<string name="section_user_ids">"Identities"</string>
<string name="section_yubikey">"YubiKey"</string>
<string name="section_linked_system_contact">"Linked System Contact"</string>
+ <string name="section_keybase_proofs">"Keybase.io Proofs"</string>
<string name="section_should_you_trust">"Should you trust this key?"</string>
<string name="section_proof_details">Proof verification</string>
- <string name="section_cloud_evidence">"Proofs from the cloud"</string>
<string name="section_keys">"Subkeys"</string>
- <string name="section_cloud_search">"Cloud search"</string>
- <string name="section_passphrase_cache">"Password/PIN Handling"</string>
- <string name="section_proxy_settings">"Proxy Settings"</string>
+ <string name="section_cloud_search">"Key Search"</string>
+ <string name="section_cloud_search_summary">"Keyserver, keybase.io"</string>
+ <string name="section_passphrase_cache">"Passwords and PINs"</string>
+ <string name="section_passphrase_cache_summary">"Handling, user interface, remember time"</string>
+ <string name="section_proxy_settings">"Network Anonymity"</string>
+ <string name="section_proxy_settings_summary">"Tor, Proxy Settings"</string>
<string name="section_gui">"Interface"</string>
+ <string name="section_sync_settings">"Synchronization"</string>
+ <string name="section_sync_settings_summary">"Automatic key updates, contact linking"</string>
+ <string name="section_experimental_features">"Experimental Features"</string>
<string name="section_certify">"Confirm"</string>
<string name="section_actions">"Actions"</string>
<string name="section_share_key">"Key"</string>
@@ -77,12 +83,12 @@
<string name="btn_back">"Back"</string>
<string name="btn_no">"No"</string>
<string name="btn_match">"Fingerprints match"</string>
- <string name="btn_share_encrypted_signed">"Encrypt and share text"</string>
- <string name="btn_copy_encrypted_signed">"Encrypt and copy text"</string>
+ <string name="btn_share_encrypted_signed">"Encrypt/sign and share text"</string>
+ <string name="btn_copy_encrypted_signed">"Encrypt/sign and copy text"</string>
<string name="btn_view_cert_key">"View certification key"</string>
<string name="btn_create_key">"Create key"</string>
<string name="btn_add_files">"Add file(s)"</string>
- <string name="btn_share_decrypted_text">"Share decrypted text"</string>
+ <string name="btn_share_decrypted_text">"Share"</string>
<string name="btn_copy_decrypted_text">"Copy decrypted text"</string>
<string name="btn_decrypt_clipboard">"Read from clipboard"</string>
<string name="btn_decrypt_files">"Select input file"</string>
@@ -108,8 +114,9 @@
<string name="menu_export_all_keys">"Export all keys"</string>
<string name="menu_update_all_keys">"Update all keys"</string>
<string name="menu_advanced">"Extended information"</string>
- <string name="menu_certify_fingerprint">"Confirm via fingerprint comparison"</string>
- <string name="menu_export_log">"Export Log"</string>
+ <string name="menu_certify_fingerprint">"Confirm via fingerprint"</string>
+ <string name="menu_certify_fingerprint_word">"Confirm via words"</string>
+ <string name="menu_share_log">"Share Log"</string>
<string name="menu_keyserver_add">"Add"</string>
@@ -154,7 +161,7 @@
<string name="label_name">"Name"</string>
<string name="label_comment">"Comment"</string>
<string name="label_email">"Email"</string>
- <string name="label_send_key">"Synchronize with the cloud"</string>
+ <string name="label_send_key">"Synchronize with the Internet"</string>
<string name="label_fingerprint">"Fingerprint"</string>
<string name="expiry_date_dialog_title">"Set expiry date"</string>
<string name="label_keyservers_title">"Keyservers"</string>
@@ -175,6 +182,26 @@
<string name="pref_keybase">"keybase.io"</string>
<string name="pref_keybase_summary">"Search keys on keybase.io"</string>
+ <string name="label_sync_settings_keyserver_title">"Automatically update keys"</string>
+ <string name="label_sync_settings_keyserver_summary_on">"Keys older than a week are updated from the preferred keyserver"</string>
+ <string name="label_sync_settings_keyserver_summary_off">"Keys not automatically updated"</string>
+ <string name="label_sync_settings_contacts_title">"Link keys to contacts"</string>
+ <string name="label_sync_settings_contacts_summary_on">"Link keys to contacts based on names and email addresses. This happens completely offline on your device."</string>
+ <string name="label_sync_settings_contacts_summary_off">"New keys will not be linked to contacts"</string>
+ <!-- label shown in Android settings under the OpenKeychain account -->
+ <string name="keyserver_sync_settings_title">"Automatically update keys"</string>
+
+ <string name="label_experimental_settings_desc_title">"Warning"</string>
+ <string name="label_experimental_settings_desc_summary">"These features are not yet finished or results of user experience/security research. Thus, don't rely on their security and please don't report issues you encounter!"</string>
+
+ <string name="label_experimental_settings_word_confirm_title">"Word Confirm"</string>
+ <string name="label_experimental_settings_word_confirm_summary">"Confirm keys with words instead of hexadecimal fingerprints"</string>
+ <string name="label_experimental_settings_linked_identities_title">"Linked Identities"</string>
+ <string name="label_experimental_settings_linked_identities_summary">"Link keys to Twitter, GitHub, websites or DNS (similar to keybase.io but decentralized)"</string>
+ <string name="label_experimental_settings_keybase_title">"Keybase.io Proofs"</string>
+ <string name="label_experimental_settings_keybase_summary">"Contact keybase.io for key proofs and show them every time a key is displayed"</string>
+ <string name="label_experimental_settings_theme_summary">"(The icons and many screens are not yet adjusted accordingly for the dark theme)"</string>
+
<!-- Proxy Preferences -->
<string name="pref_proxy_tor_title">"Enable Tor"</string>
<string name="pref_proxy_tor_summary">"Requires Orbot to be installed"</string>
@@ -188,8 +215,6 @@
<!-- proxy type choices and values -->
<string name="pref_proxy_type_choice_http">"HTTP"</string>
<string name="pref_proxy_type_choice_socks">"SOCKS"</string>
- <string name="pref_proxy_type_value_http">"proxyHttp"</string>
- <string name="pref_proxy_type_value_socks">"proxySocks"</string>
<!-- OrbotHelper strings -->
<string name="orbot_ignore_tor">"Don\'t use Tor"</string>
@@ -210,8 +235,8 @@
<string name="orbot_start_dialog_ignore_tor">"Don\'t use Tor"</string>
- <string name="user_id_no_name">"&lt;no name&gt;"</string>
- <string name="none">"&lt;none&gt;"</string>
+ <string name="user_id_no_name"><![CDATA[<no name>]]></string>
+ <string name="none"><![CDATA[<none>]]></string>
<plurals name="n_keys">
<item quantity="one">"1 key"</item>
@@ -239,6 +264,7 @@
<string name="choice_4hours">"4 hours"</string>
<string name="choice_8hours">"8 hours"</string>
<string name="choice_forever">"forever"</string>
+ <string name="choice_select_cert">"Select a Key"</string>
<string name="dsa">"DSA"</string>
<string name="elgamal">"ElGamal"</string>
<string name="rsa">"RSA"</string>
@@ -295,8 +321,6 @@
<string name="key_creation_el_gamal_info">"Note: only subkeys support ElGamal."</string>
<string name="key_not_found">"Couldn't find key %08X."</string>
- <string name="specify_file_to_export_log_to">"Please specify file to export to. \nWARNING: File will be overwritten if it exists."</string>
-
<plurals name="bad_keys_encountered">"
<item quantity="one">"%d bad secret key ignored. Perhaps you exported with the option\n --export-secret-subkeys\nMake sure you export with\n --export-secret-keys\ninstead.""</item>
<item quantity="other">"%d bad secret keys ignored. Perhaps you exported with the option\n --export-secret-subkeys\nMake sure you export with\n --export-secret-keys\ninstead.""</item>
@@ -467,7 +491,7 @@
<!-- Import -->
<string name="import_tab_keyserver">"Keyserver"</string>
- <string name="import_tab_cloud">"Search Cloud"</string>
+ <string name="import_tab_cloud">"Key Search"</string>
<string name="import_tab_direct">"File/Clipboard"</string>
<string name="import_tab_qr_code">"QR Code/NFC"</string>
<string name="import_import">"Import selected keys"</string>
@@ -487,11 +511,11 @@
<!-- Import result toast -->
<plurals name="import_keys_added_and_updated_1">
- <item quantity="one">"Successfully imported key"</item>
+ <item quantity="one">"Successfully imported one key"</item>
<item quantity="other">"Successfully imported %1$d keys"</item>
</plurals>
<plurals name="import_keys_added_and_updated_2">
- <item quantity="one">"and updated key%2$s."</item>
+ <item quantity="one">"and updated one key%2$s."</item>
<item quantity="other">"and updated %1$d keys%2$s."</item>
</plurals>
<plurals name="import_keys_added">
@@ -541,8 +565,8 @@
<!-- Certify result toast -->
<plurals name="certify_keys_ok">
- <item quantity="one">"Successfully certified key%2$s."</item>
- <item quantity="other">"Successfully certified %1$d keys%2$s."</item>
+ <item quantity="one">"Successfully confirmed key%2$s."</item>
+ <item quantity="other">"Successfully confirmed %1$d keys%2$s."</item>
</plurals>
<plurals name="certify_keys_with_errors">
<item quantity="one">"Certification failed!"</item>
@@ -606,8 +630,8 @@
<string name="retry_up_dialog_btn_cancel">"Cancel Operation"</string>
<!-- Delete or revoke private key dialog -->
- <string name="del_rev_dialog_message">"If you would no longer like to use this key, it should be revoked and uploaded. Select delete only if you wish to remove the key from OpenKeychain but continue to use it from somewhere else."</string>
- <string name="del_rev_dialog_title">"Revoke/Delete key \"%s\""</string>
+ <string name="del_rev_dialog_message">"If you would no longer like to use this key, it should be revoked and uploaded. Select 'DELETE ONLY' if you wish to remove the key from OpenKeychain but continue to use it from somewhere else."</string>
+ <string name="del_rev_dialog_title">"Revoke/Delete key '%s'"</string>
<string name="del_rev_dialog_btn_revoke">"Revoke and upload"</string>
<string name="del_rev_dialog_btn_delete">"Delete only"</string>
@@ -624,7 +648,10 @@
<string name="key_list_empty_text1">"No keys found!"</string>
<string name="key_list_filter_show_all">"Show all keys"</string>
- <string name="key_list_filter_show_certified">"Show certified keys only"</string>
+ <string name="key_list_filter_show_certified">"Show confirmed keys only"</string>
+ <string name="key_list_fab_qr_code">"Scan QR Code"</string>
+ <string name="key_list_fab_search">"Key Search"</string>
+ <string name="key_list_fab_import">"Import from File"</string>
<!-- Key view -->
<string name="key_view_action_edit">"Edit key"</string>
@@ -642,21 +669,15 @@
<string name="key_view_tab_keybase">"Keybase.io"</string>
<string name="user_id_info_revoked_title">"Revoked"</string>
<string name="user_id_info_revoked_text">"This identity has been revoked by the key owner. It is no longer valid."</string>
- <string name="user_id_info_certified_title">"Certified"</string>
- <string name="user_id_info_certified_text">"This identity has been certified by you."</string>
- <string name="user_id_info_uncertified_title">"Not certified"</string>
- <string name="user_id_info_uncertified_text">"This identity has not been certified yet. You cannot be sure if the identity really corresponds to a specific person."</string>
+ <string name="user_id_info_certified_title">"Confirmed"</string>
+ <string name="user_id_info_certified_text">"This identity has been confirmed by you."</string>
+ <string name="user_id_info_uncertified_title">"Not confirmed"</string>
+ <string name="user_id_info_uncertified_text">"This identity has not been confirmed yet. You cannot be sure if the identity really corresponds to a specific person."</string>
<string name="user_id_info_invalid_title">"Invalid"</string>
<string name="user_id_info_invalid_text">"Something is wrong with this identity!"</string>
<!-- Key trust -->
- <string name="key_trust_already_verified">"You have already confirmed this key!"</string>
- <string name="key_trust_it_is_yours">"This is one of your keys!"</string>
- <string name="key_trust_maybe">"This key is neither revoked nor expired.\nYou haven’t confirmed it, but you may choose to trust it."</string>
- <string name="key_trust_revoked">"This key has been revoked by its owner. You should not trust it."</string>
- <string name="key_trust_expired">"This key has expired. You should not trust it."</string>
- <string name="key_trust_old_keys">"It may be OK to use this to decrypt an old message dating from the time when this key was valid."</string>
- <string name="key_trust_no_cloud_evidence">"No proof from the cloud on this key’s trustworthiness."</string>
+ <string name="key_trust_no_cloud_evidence">"No proof from the Internet on this key’s trustworthiness."</string>
<string name="key_trust_start_cloud_search">"Start search"</string>
<string name="key_trust_results_prefix">"Keybase.io offers “proofs” which assert that the owner of this key: "</string>
<string name="key_trust_header_text">"Note: Keybase.io proofs are an experimental feature of OpenKeychain. We encourage you to scan QR Codes or exchange keys via NFC in addition to confirming them."</string>
@@ -720,7 +741,7 @@
<string name="edit_key_error_bad_nfc_stripped">"Cannot move key to smart card (either stripped or 'divert-to-card')!"</string>
<!-- Create key -->
- <string name="create_key_upload">"Synchronize with the cloud"</string>
+ <string name="create_key_upload">"Synchronize with the Internet"</string>
<string name="create_key_empty">"This field is required"</string>
<string name="create_key_passphrases_not_equal">"Passwords do not match"</string>
<string name="create_key_final_text">"You entered the following identity:"</string>
@@ -760,7 +781,7 @@
<string name="add_keyserver_verified">"Keyserver verified!"</string>
<string name="add_keyserver_without_verification">"Keyserver added without verification."</string>
<string name="add_keyserver_invalid_url">"Invalid URL!"</string>
- <string name="add_keyserver_connection_failed">"Failed to connect to keyserver. Please check the URL and your internet connection."</string>
+ <string name="add_keyserver_connection_failed">"Failed to connect to keyserver. Please check the URL and your Internet connection."</string>
<string name="keyserver_preference_deleted">"%s deleted"</string>
<string name="keyserver_preference_cannot_delete_last">"Cannot delete last keyserver. At least one is required!"</string>
@@ -802,6 +823,8 @@
<string name="msg_ip_error_op_exc">"Operation failed due to database error"</string>
<string name="msg_ip_error_remote_ex">"Operation failed due to internal error"</string>
<string name="msg_ip">"Importing public keyring %s"</string>
+ <string name="msg_ip_fingerprint_error">"Fingerprint of importing key does not match expected!"</string>
+ <string name="msg_ip_fingerprint_ok">"Fingerprint check OK"</string>
<string name="msg_ip_insert_keyring">"Encoding keyring data"</string>
<string name="msg_ip_insert_keys">"Parsing keys"</string>
<string name="msg_ip_prepare">"Preparing database operations"</string>
@@ -826,7 +849,7 @@
<string name="msg_ip_master_flags_xxxa">"Master flags: authenticate"</string>
<string name="msg_ip_master_flags_xxxx">"Master flags: none"</string>
<string name="msg_ip_merge_public">"Merging imported data into existing public keyring"</string>
- <string name="msg_ip_merge_secret">"Merging imported data into existing public keyring"</string>
+ <string name="msg_ip_merge_secret">"Merging imported data into existing secret keyring"</string>
<string name="msg_ip_subkey">"Processing subkey %s"</string>
<string name="msg_ip_subkey_expired">"Subkey expired on %s"</string>
<string name="msg_ip_subkey_expires">"Subkey expires on %s"</string>
@@ -895,7 +918,7 @@
<string name="msg_is_importing_subkeys">"Processing secret subkeys"</string>
<string name="msg_is_error_io_exc">"Error encoding keyring"</string>
<string name="msg_is_merge_public">"Merging imported data into existing public keyring"</string>
- <string name="msg_is_merge_secret">"Merging imported data into existing public keyring"</string>
+ <string name="msg_is_merge_secret">"Merging imported data into existing secret keyring"</string>
<string name="msg_is_merge_special">"Merging in self-certificates data from public keyring"</string>
<string name="msg_is_pubring_generate">"Generating public keyring from secret keyring"</string>
<string name="msg_is_subkey_nonexistent">"Subkey %s unavailable in secret key"</string>
@@ -1163,6 +1186,7 @@
<string name="msg_dc_trail_sym">"Encountered trailing, symmetrically encrypted data"</string>
<string name="msg_dc_trail_unknown">"Encountered trailing data of unknown type"</string>
<string name="msg_dc_unlocking">"Unlocking secret key"</string>
+ <string name="msg_dc_insecure_encryption_key">"Insecure encryption key was used! This can happen because the key is old, or from an attack."</string>
<string name="msg_dc_insecure_symmetric_encryption_algo">"Insecure encryption algorithm has been used! This can happen because the application is out of date, or from an attack."</string>
<string name="msg_dc_insecure_hash_algo">"Insecure hash algorithm has been used! This can happen because the application is out of date, or from an attack."</string>
<string name="msg_dc_insecure_mdc_missing">"Missing the Modification Detection Code (MDC) packet! This can happen because the encrypting application is out of date, or from a downgrade attack."</string>
@@ -1251,13 +1275,12 @@
</plurals>
<string name="msg_import_fetch_error_decode">"Error decoding retrieved keyring!"</string>
<string name="msg_import_fetch_error">"Key could not be retrieved! (Network problems?)"</string>
+ <string name="msg_import_fetch_error_keyserver">"Could not retrieve key from keyservers: %s"</string>
+ <string name="msg_import_fetch_error_keyserver_secret">"Cannot import secret key from keyserver!"</string>
<string name="msg_import_fetch_keybase">"Retrieving from keybase.io: %s"</string>
- <string name="msg_import_fetch_keyserver_error">"Could not retrieve key from keyservers: %s"</string>
<string name="msg_import_fetch_keyserver">"Retrieving from keyserver: %s"</string>
<string name="msg_import_fetch_keyserver_ok">"Key retrieval successful"</string>
<string name="msg_import_keyserver">"Using keyserver %s"</string>
- <string name="msg_import_fingerprint_error">"Fingerprint of fetched key didn't match expected!"</string>
- <string name="msg_import_fingerprint_ok">"Fingerprint check OK"</string>
<string name="msg_import_merge">"Merging retrieved data"</string>
<string name="msg_import_merge_error">"Error merging retrieved data!"</string>
<string name="msg_import_error">"Import operation failed!"</string>
@@ -1269,6 +1292,7 @@
<item quantity="one">"Exporting one key"</item>
<item quantity="other">"Exporting %d keys"</item>
</plurals>
+ <string name="msg_export_file_name">"Filename: %s"</string>
<string name="msg_export_all">"Exporting all keys"</string>
<string name="msg_export_public">"Exporting public key %s"</string>
<string name="msg_export_upload_public">"Uploading public key %s"</string>
@@ -1281,7 +1305,7 @@
<string name="msg_export_error_db">"Database error!"</string>
<string name="msg_export_error_io">"Input/output error!"</string>
<string name="msg_export_error_key">"Error preprocessing key data!"</string>
- <string name="msg_export_error_upload">"Error uploading key to server! Please check your internet connection"</string>
+ <string name="msg_export_error_upload">"Error uploading key to server! Please check your Internet connection"</string>
<string name="msg_export_success">"Export operation successful"</string>
<string name="msg_export_upload_success">"Upload to keyserver successful"</string>
@@ -1304,12 +1328,34 @@
</plurals>
<string name="msg_revoke_error_empty">"Nothing to revoke!"</string>
- <string name="msg_revoke_error_multi_secret">"Secret keys can only be revoked individually!"</string>
<string name="msg_revoke_error_not_found">"Cannot find key to revoke!"</string>
<string name="msg_revoke_key">"Revoking key %s"</string>
<string name="msg_revoke_key_fail">"Failed revoking key"</string>
<string name="msg_revoke_ok">"Successfully revoked key"</string>
+ <!-- Linked Identity verification -->
+ <string name="msg_lv">"Verifying linked identity…"</string>
+ <string name="msg_lv_match">"Searching for token"</string>
+ <string name="msg_lv_match_error">"No token found in resource!"</string>
+ <string name="msg_lv_fp_ok">"Fingerprint OK."</string>
+ <string name="msg_lv_fp_error">"Fingerprint mismatch!"</string>
+
+ <string name="msg_lv_error_twitter_auth">"Error obtaining Twitter auth token!"</string>
+ <string name="msg_lv_error_twitter_handle">"Twitter account handle mismatch in response!"</string>
+ <string name="msg_lv_error_twitter_response">"Unexpected response from Twitter API!"</string>
+ <string name="msg_lv_error_github_handle">"GitHub account handle mismatch in response!"</string>
+ <string name="msg_lv_error_github_not_found">"Gist contains no matching files!"</string>
+
+ <string name="msg_lv_fetch">"Fetching URI '%s'"</string>
+ <string name="msg_lv_fetch_redir">"Following redirect to '%s'"</string>
+ <string name="msg_lv_fetch_ok">"Successfully fetched (HTTP %s)"</string>
+ <string name="msg_lv_fetch_error">"Server error (HTTP %s)"</string>
+ <string name="msg_lv_fetch_error_url">"URL is malformed!"</string>
+ <string name="msg_lv_fetch_error_io">"IO Error!"</string>
+ <string name="msg_lv_fetch_error_format">"Format error!"</string>
+ <string name="msg_lv_fetch_error_nothing">"Resource not found!"</string>
+
+
<string name="msg_acc_saved">"Account saved"</string>
<string name="msg_download_success">"Downloaded successfully!"</string>
@@ -1334,13 +1380,6 @@
<string name="msg_keybase_error_specific">"%s"</string>
<string name="msg_keybase_error_msg_payload_mismatch">"Decrypted proof post does not match expected value"</string>
- <!-- Messages for Export Log operation -->
- <string name="msg_export_log_start">"Exporting log"</string>
- <string name="msg_export_log_error_fopen">"Error opening file"</string>
- <string name="msg_export_log_error_no_file">"No file name specified!"</string>
- <string name="msg_export_log_error_writing">"I/O error writing to file!"</string>
- <string name="msg_export_log_success">"Log exported successfully!"</string>
-
<!-- Messages for Mime parsing operation -->
<string name="msg_mime_parsing_start">"Parsing the MIME structure"</string>
<string name="msg_mime_parsing_error">"MIME parsing failed"</string>
@@ -1356,6 +1395,12 @@
<string name="passp_cache_notif_clear">"Clear Passwords"</string>
<string name="passp_cache_notif_pwd">"Password"</string>
+ <!-- Keyserver sync -->
+ <string name="keyserver_sync_orbot_notif_title">"Sync From Servers requires Orbot"</string>
+ <string name="keyserver_sync_orbot_notif_msg">"Tap to start orbot"</string>
+ <string name="keyserver_sync_orbot_notif_start">"Start Orbot"</string>
+ <string name="keyserver_sync_orbot_notif_ignore">"Direct"</string>
+
<!-- First Time -->
<string name="first_time_text1">"Take back your privacy with OpenKeychain!"</string>
<string name="first_time_create_key">"Create my key"</string>
@@ -1374,13 +1419,14 @@
<string name="section_certifier_id">"Certifier"</string>
<string name="section_cert">"Certificate Details"</string>
<string name="label_user_id">"Identity"</string>
- <string name="unknown_uid">"&lt;unknown&gt;"</string>
+ <string name="unknown_uid"><![CDATA[<unknown>]]></string>
<string name="empty_certs">"No certificates for this key"</string>
<string name="certs_text">"Only validated self-certificates and validated certificates created with your keys are displayed here."</string>
<string name="section_uids_to_certify">"Identities for "</string>
<string name="certify_text">"The keys you are importing contain “identities”: names and email addresses. Select exactly those for confirmation which match what you expected."</string>
<string name="certify_fingerprint_text">"Compare the displayed fingerprint, character by character, with the one displayed on your partners device."</string>
- <string name="certify_fingerprint_text2">"Do the displayed fingerprints match?"</string>
+ <string name="certify_fingerprint_text_words">"Compare the displayed fingerprint, word by word, with the one displayed on your partners device."</string>
+ <string name="certify_fingerprint_text2">"Do the fingerprints match?"</string>
<string name="label_revocation">"Revocation Reason"</string>
<string name="label_cert_type">"Type"</string>
<string name="error_key_not_found">"Key not found!"</string>
@@ -1401,6 +1447,7 @@
<string name="error_multi_clipboard">"Encryption of multiple files to clipboard not supported."</string>
<string name="error_detached_signature">"Sign-only operation of binary files is not supported, select at least one encryption key."</string>
<string name="error_empty_text">"Type some text to encrypt!"</string>
+ <string name="error_log_share_internal">"Internal error while preparing log!"</string>
<string name="key_colon">"Key:"</string>
<string name="exchange_description">"To start a key exchange, choose the number of participants on the right side, then hit the “Start exchange” button.\n\nYou will be asked two more questions to make sure only the right participants are in the exchange and their fingerprints are correct."</string>
<string name="btn_start_exchange">"Start exchange"</string>
@@ -1442,7 +1489,7 @@
<string name="button_bind_key">"Bind Key"</string>
<string name="yubikey_serno">"Serial No: %s"</string>
<string name="yubikey_key_holder">"Key holder: "</string>
- <string name="yubikey_key_holder_not_set">"Key holder: &lt;not set&gt;"</string>
+ <string name="yubikey_key_holder_not_set"><![CDATA[Key holder: <not set>]]></string>
<string name="yubikey_status_bound">"YubiKey matches and is bound to key"</string>
<string name="yubikey_status_unbound">"YubiKey matches, can be bound to key"</string>
<string name="yubikey_status_partly">"YubiKey matches, partly bound to key"</string>
@@ -1479,8 +1526,8 @@
<string name="error_loading_keys">"Error loading keys!"</string>
<string name="error_empty_log">"(error, empty log)"</string>
<string name="error_reading_text">"Could not read input to decrypt!"</string>
- <string name="filename_unknown">"&lt;no filename&gt;"</string>
- <string name="filename_unknown_text">"&lt;plain text data&gt;"</string>
+ <string name="filename_unknown">Unknown filename (click to open)</string>
+ <string name="filename_unknown_text">Text (click to show)</string>
<string name="intent_show">Show Signed/Encrypted Content</string>
<string name="view_internal">"View in OpenKeychain"</string>
<string name="error_preparing_data">"Error preparing data!"</string>
@@ -1497,4 +1544,78 @@
<string name="error_scan_match">"Fingerprints did not match!"</string>
<string name="error_expiry_past">"Expiry date is in the past!"</string>
+ <string name="linked_create_https_1_1">"By creating a Linked Identity of this type, you can link your key to a website you control."</string>
+ <string name="linked_create_https_1_2">"To do this, you publish a text file on this website, then create a Linked Identity which links to it."</string>
+ <string name="linked_create_https_1_3">"Please enter a URL where you are able to place a text file for proof. Note that your server must support https and have a valid TLS certificate!"</string>
+ <string name="linked_create_https_1_4">"Example: https://example.com/pgpkey.txt"</string>
+ <string name="linked_create_https_created">"The proof file has been created. For the next step, you should save and upload it to the URI you indicated:"</string>
+ <string name="linked_create_https_2_1">"A proof file for this URI has been created:"</string>
+ <string name="linked_create_https_2_2">"For the next step, you should save and upload this file."</string>
+ <string name="linked_create_https_2_3">"Make sure the file is reachable at the correct URI, then verify your setup."</string>
+ <string name="linked_create_https_2_4">"After successful verification, press the Finish button to add the Linked Identity to your keyring and finish the process."</string>
+
+ <string name="linked_create_twitter_1_1">"By creating a Linked Identity of this type, you can link your key to a Twitter account you control."</string>
+ <string name="linked_create_twitter_1_2">"To do this, you publish a specific Tweet on your timeline, then create a Linked Identity which links to this Tweet."</string>
+ <string name="linked_create_twitter_1_3">"Please enter your Twitter screen name to proceed."</string>
+ <string name="linked_create_twitter_handle">Twitter Handle</string>
+ <string name="linked_create_twitter_2_1">"Click either button to tweet the message!"</string>
+ <string name="linked_create_twitter_2_2">"You can edit the Tweet before posting it, so long as the text inside the brackets is unmodified."</string>
+ <string name="linked_create_twitter_2_3">"Once your Tweet is published as &lt;b&gt;@%s&lt;/b&gt;, click the Verify button to scan your timeline for it."</string>
+ <string name="linked_create_twitter_2_4">"After successful verification, press the Finish button to add the Linked Identity to your keyring and finish the process."</string>
+
+ <string name="linked_create_verify">"Verify"</string>
+ <string name="linked_text_clipboard">Text has been copied to clipboard</string>
+ <string name="linked_verified_https">"The link between this Website and key was securely verified. <b>If you believe the Website is genuine</b>, confirm this verification with your key."</string>
+ <string name="linked_verified_github">"The link between this GitHub account and key was securely verified. <b>If you believe the account is genuine</b>, confirm this verification with your key."</string>
+ <string name="linked_verified_dns">"The link between this Domain Name and key was securely verified. <b>If you believe the Domain is genuine</b>, confirm this verification with your key."</string>
+ <string name="linked_verified_twitter">"The link between this Twitter account and key was securely verified. <b>If you believe the account is genuine</b>, confirm this verification with your key."</string>
+ <string name="linked_verified_secret_https">"Everything looks in order."</string>
+ <string name="linked_verified_secret_github">"Everything looks in order."</string>
+ <string name="linked_verified_secret_dns">"Everything looks in order."</string>
+ <string name="linked_verified_secret_twitter">"Everything looks in order."</string>
+
+ <plurals name="linked_id_expand">
+ <item quantity="one">"There is one more unknown identity type"</item>
+ <item quantity="other">"There are %d more unknown identity types"</item>
+ </plurals>
+
+ <!-- Other Linked Identity strings -->
+ <string name="linked_select_1">"A \'linked identity\' connects your pgp key to a resource on the web."</string>
+ <string name="linked_select_2">"Please select a type:"</string>
+ <string name="linked_id_generic_text">"This file claims ownership of the OpenPGP key with long id %2$s.\n\nToken for proof:\n%1$s"</string>
+ <string name="linked_id_github_text">"This Gist confirms the Linked Identity in my OpenPGP key, and links it to this GitHub account.\n\nToken for proof:\n%1$s"</string>
+ <string name="linked_verifying">"Verifying…"</string>
+ <string name="linked_verify_success">"Verified!"</string>
+ <string name="linked_verify_error">"Verification error!"</string>
+ <string name="linked_verify_pending">"Not yet verified"</string>
+ <string name="linked_need_verify">The resource needs to be verified before you can proceed!</string>
+ <string name="menu_linked_add_identity">"Link to Account"</string>
+ <string name="section_linked_identities">"Linked Identities"</string>
+ <string name="btn_finish">"Finish"</string>
+ <string name="linked_title_https">"Website (HTTPS)"</string>
+ <string name="linked_title_dns">"Domain Name (DNS)"</string>
+ <string name="linked_title_github">"GitHub"</string>
+ <string name="linked_title_twitter">"Twitter"</string>
+ <string name="card_linked_identity">"Linked Identity"</string>
+ <string name="linked_button_verify">"Verify"</string>
+ <string name="linked_button_retry">"Retry last step"</string>
+ <string name="linked_button_confirm">"Confirm"</string>
+ <string name="linked_button_view">"View"</string>
+ <string name="linked_text_verifying">"Verifying…"</string>
+ <string name="linked_text_error">"Error"</string>
+ <string name="linked_text_confirming">"Confirming…"</string>
+ <string name="linked_ids_more_unknown">"%d more unknown identity types"</string>
+ <string name="title_linked_id_create">"Create Linked Identity"</string>
+ <string name="linked_github_text">"This operation links your key to your GitHub account.\nJust press the button to continue."</string>
+ <string name="linked_progress_auth_github">"Authorize with GitHub…"</string>
+ <string name="linked_progress_post_gist">"Post Gist…"</string>
+ <string name="linked_progress_update_key">"Update Key…"</string>
+ <string name="linked_button_start">"Link to Github Account"</string>
+ <string name="linked_error_auth_failed">"Authorization failed!"</string>
+ <string name="linked_error_timeout">"Connection timeout!"</string>
+ <string name="linked_error_network">"Network error!"</string>
+ <string name="linked_error_http">"Communication error: %s"</string>
+ <string name="linked_webview_title_github">"GitHub Authorization"</string>
+ <string name="linked_gist_description">"OpenKeychain API Tests"</string>
+
</resources>
diff --git a/OpenKeychain/src/main/res/values/styles.xml b/OpenKeychain/src/main/res/values/styles.xml
index c5710dadf..55c4e2220 100644
--- a/OpenKeychain/src/main/res/values/styles.xml
+++ b/OpenKeychain/src/main/res/values/styles.xml
@@ -34,4 +34,8 @@
<item name="android:background">?android:attr/listDivider</item>
</style>
+ <style name="MaterialFlatButton" parent="@style/Widget.AppCompat.Button.Borderless">
+ <item name="android:textColor">?attr/colorAccent</item>
+ </style>
+
</resources>
diff --git a/OpenKeychain/src/main/res/values/themes.xml b/OpenKeychain/src/main/res/values/themes.xml
index 2b1c00ba9..38cf8a3db 100644
--- a/OpenKeychain/src/main/res/values/themes.xml
+++ b/OpenKeychain/src/main/res/values/themes.xml
@@ -39,7 +39,7 @@
<item name="searchViewStyle">@style/Widget.Keychain.SearchView</item>
<!-- style dialogs -->
- <item name="alertDialogTheme">@style/Theme.Keychain.Light.Dialog</item>
+ <item name="alertDialogTheme">@style/Theme.Keychain.Light.Dialog.Alert</item>
</style>
<style name="Base.Theme.Keychain.Dark" parent="MaterialDrawerTheme.ActionBar">
@@ -82,7 +82,7 @@
<item name="searchViewStyle">@style/Widget.Keychain.SearchView</item>
<!-- style dialogs -->
- <item name="alertDialogTheme">@style/Theme.Keychain.Dark.Dialog</item>
+ <item name="alertDialogTheme">@style/Theme.Keychain.Dark.Dialog.Alert</item>
</style>
<style name="Theme.Keychain.Light" parent="Base.Theme.Keychain.Light">
@@ -111,20 +111,26 @@
<!--<item name="suggestionRowLayout">...</item>-->
</style>
- <style name="Theme.Keychain.Light.Dialog" parent="Base.Theme.AppCompat.Light.Dialog.Alert">
+ <style name="Theme.Keychain.Light.Dialog.Alert" parent="Base.Theme.AppCompat.Light.Dialog.Alert">
<item name="colorAccent">#7bad45</item>
</style>
- <style name="Theme.Keychain.Dark.Dialog" parent="Base.Theme.AppCompat.Dialog.Alert">
+ <style name="Theme.Keychain.Dark.Dialog.Alert" parent="Base.Theme.AppCompat.Dialog.Alert">
<item name="colorAccent">#268bd2</item>
</style>
- <style name="Theme.Keychain.Light.Dialog.SecurityToken" parent="Theme.AppCompat.Light.Dialog.MinWidth">
+ <style name="Theme.Keychain.Light.Dialog" parent="Theme.AppCompat.Light.Dialog.MinWidth">
+ <item name="colorAccent">#7bad45</item>
+ <item name="android:buttonStyle">@style/MaterialFlatButton</item>
+
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
</style>
- <style name="Theme.Keychain.Dark.Dialog.SecurityToken" parent="Theme.AppCompat.Dialog.MinWidth">
+ <style name="Theme.Keychain.Dark.Dialog" parent="Theme.AppCompat.Dialog.MinWidth">
+ <item name="colorAccent">#268bd2</item>
+ <item name="android:buttonStyle">@style/MaterialFlatButton</item>
+
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
</style>
diff --git a/OpenKeychain/src/main/res/xml/account_desc.xml b/OpenKeychain/src/main/res/xml/account_desc.xml
index e04160c5c..942909dbe 100644
--- a/OpenKeychain/src/main/res/xml/account_desc.xml
+++ b/OpenKeychain/src/main/res/xml/account_desc.xml
@@ -2,5 +2,5 @@
<account-authenticator xmlns:android="http://schemas.android.com/apk/res/android"
android:accountPreferences="@xml/account_preferences"
android:accountType="@string/account_type"
- android:icon="@drawable/ic_launcher"
+ android:icon="@mipmap/ic_launcher"
android:label="@string/app_name" />
diff --git a/OpenKeychain/src/main/res/xml/cloud_search_prefs.xml b/OpenKeychain/src/main/res/xml/cloud_search_prefs.xml
index d14f0bc40..85d6a6bca 100644
--- a/OpenKeychain/src/main/res/xml/cloud_search_prefs.xml
+++ b/OpenKeychain/src/main/res/xml/cloud_search_prefs.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
- <CheckBoxPreference
+ <SwitchPreference
android:defaultValue="true"
android:key="search_keyserver_pref"
android:summary="@string/pref_keyserver_summary"
@@ -12,7 +12,7 @@
android:persistent="false"
android:title="@string/label_keyservers" />
- <CheckBoxPreference
+ <SwitchPreference
android:defaultValue="true"
android:key="search_keybase_pref"
android:summary="@string/pref_keybase_summary"
diff --git a/OpenKeychain/src/main/res/xml/experimental_preferences.xml b/OpenKeychain/src/main/res/xml/experimental_preferences.xml
new file mode 100644
index 000000000..ff1fa5a95
--- /dev/null
+++ b/OpenKeychain/src/main/res/xml/experimental_preferences.xml
@@ -0,0 +1,37 @@
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
+ <Preference
+ android:persistent="false"
+ android:selectable="false"
+ android:title="@string/label_experimental_settings_desc_title"
+ android:summary="@string/label_experimental_settings_desc_summary" />
+
+ <SwitchPreference
+ android:defaultValue="false"
+ android:key="experimentalEnableWordConfirm"
+ android:persistent="false"
+ android:summary="@string/label_experimental_settings_word_confirm_summary"
+ android:title="@string/label_experimental_settings_word_confirm_title" />
+
+ <SwitchPreference
+ android:defaultValue="false"
+ android:key="experimentalEnableLinkedIdentities"
+ android:persistent="false"
+ android:summary="@string/label_experimental_settings_linked_identities_summary"
+ android:title="@string/label_experimental_settings_linked_identities_title" />
+
+ <SwitchPreference
+ android:defaultValue="false"
+ android:key="experimentalEnableKeybase"
+ android:persistent="false"
+ android:summary="@string/label_experimental_settings_keybase_summary"
+ android:title="@string/label_experimental_settings_keybase_title" />
+
+ <ListPreference
+ android:dialogTitle="@string/label_theme"
+ android:entries="@array/theme_entries"
+ android:entryValues="@array/theme_values"
+ android:key="theme"
+ android:persistent="false"
+ android:title="@string/label_theme" />
+
+</PreferenceScreen>
diff --git a/OpenKeychain/src/main/res/xml/keyserver_sync_adapter_desc.xml b/OpenKeychain/src/main/res/xml/keyserver_sync_adapter_desc.xml
new file mode 100644
index 000000000..3923fae59
--- /dev/null
+++ b/OpenKeychain/src/main/res/xml/keyserver_sync_adapter_desc.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<sync-adapter xmlns:android="http://schemas.android.com/apk/res/android"
+ android:contentAuthority="@string/provider_content_authority"
+ android:accountType="@string/account_type"
+ android:supportsUploading="false"
+ android:userVisible="true"
+ android:allowParallelSyncs="false"
+ android:isAlwaysSyncable="true" /> \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/xml/adv_preferences.xml b/OpenKeychain/src/main/res/xml/passphrase_preferences.xml
index 7dd649e5d..7dd649e5d 100644
--- a/OpenKeychain/src/main/res/xml/adv_preferences.xml
+++ b/OpenKeychain/src/main/res/xml/passphrase_preferences.xml
diff --git a/OpenKeychain/src/main/res/xml/preference_headers.xml b/OpenKeychain/src/main/res/xml/preference_headers.xml
index b7512b062..0c171467b 100644
--- a/OpenKeychain/src/main/res/xml/preference_headers.xml
+++ b/OpenKeychain/src/main/res/xml/preference_headers.xml
@@ -1,14 +1,29 @@
<preference-headers xmlns:android="http://schemas.android.com/apk/res/android">
<!--<header-->
- <!--android:fragment="org.sufficientlysecure.keychain.ui.SettingsActivity$GuiPrefsFragment"-->
- <!--android:title="@string/section_gui" />-->
+ <!--android:fragment="org.sufficientlysecure.keychain.ui.SettingsActivity$GuiPrefsFragment"-->
+ <!--android:title="@string/section_gui" />-->
<header
android:fragment="org.sufficientlysecure.keychain.ui.SettingsActivity$CloudSearchPrefsFragment"
+ android:icon="@drawable/ic_cloud_black_24dp"
+ android:summary="Keyserver, keybase.io"
android:title="@string/section_cloud_search" />
<header
- android:fragment="org.sufficientlysecure.keychain.ui.SettingsActivity$AdvancedPrefsFragment"
+ android:fragment="org.sufficientlysecure.keychain.ui.SettingsActivity$PassphrasePrefsFragment"
+ android:icon="@drawable/ic_lock_black_24dp"
+ android:summary="@string/section_passphrase_cache_summary"
android:title="@string/section_passphrase_cache" />
<header
android:fragment="org.sufficientlysecure.keychain.ui.SettingsActivity$ProxyPrefsFragment"
+ android:icon="@drawable/ic_settings_ethernet_black_24dp"
+ android:summary="@string/section_proxy_settings_summary"
android:title="@string/section_proxy_settings" />
+ <header
+ android:fragment="org.sufficientlysecure.keychain.ui.SettingsActivity$SyncPrefsFragment"
+ android:icon="@drawable/ic_sync_black_24dp"
+ android:summary="@string/section_sync_settings_summary"
+ android:title="@string/section_sync_settings" />
+ <header
+ android:fragment="org.sufficientlysecure.keychain.ui.SettingsActivity$ExperimentalPrefsFragment"
+ android:icon="@drawable/ic_extension_black_24dp"
+ android:title="@string/section_experimental_features" />
</preference-headers>
diff --git a/OpenKeychain/src/main/res/xml/proxy_prefs.xml b/OpenKeychain/src/main/res/xml/proxy_prefs.xml
index 94e101cb6..fbb83eb12 100644
--- a/OpenKeychain/src/main/res/xml/proxy_prefs.xml
+++ b/OpenKeychain/src/main/res/xml/proxy_prefs.xml
@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
- <CheckBoxPreference
+ <SwitchPreference
android:key="useTorProxy"
android:persistent="true"
android:title="@string/pref_proxy_tor_title"
android:summary="@string/pref_proxy_tor_summary" />
- <CheckBoxPreference
+ <SwitchPreference
android:key="useNormalProxy"
android:persistent="true"
android:title="@string/pref_proxy_normal_title" />
@@ -27,7 +27,7 @@
<ListPreference
android:entries="@array/pref_proxy_type_entries"
android:entryValues="@array/pref_proxy_type_values"
- android:defaultValue="@string/pref_proxy_type_value_http"
+ android:defaultValue="proxyHttp"
android:key="proxyType"
android:persistent="true"
android:title="@string/pref_proxy_type_title" />
diff --git a/OpenKeychain/src/main/res/xml/sync_preferences.xml b/OpenKeychain/src/main/res/xml/sync_preferences.xml
new file mode 100644
index 000000000..de41ff030
--- /dev/null
+++ b/OpenKeychain/src/main/res/xml/sync_preferences.xml
@@ -0,0 +1,10 @@
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
+ <SwitchPreference
+ android:key="syncKeyserver"
+ android:persistent="false"
+ android:title="@string/label_sync_settings_keyserver_title"/>
+ <SwitchPreference
+ android:key="syncContacts"
+ android:persistent="false"
+ android:title="@string/label_sync_settings_contacts_title" />
+</PreferenceScreen>
diff --git a/OpenKeychain/src/test/java/org/sufficientlysecure/keychain/operations/CertifyOperationTest.java b/OpenKeychain/src/test/java/org/sufficientlysecure/keychain/operations/CertifyOperationTest.java
index 472e4507a..c1aa5a76f 100644
--- a/OpenKeychain/src/test/java/org/sufficientlysecure/keychain/operations/CertifyOperationTest.java
+++ b/OpenKeychain/src/test/java/org/sufficientlysecure/keychain/operations/CertifyOperationTest.java
@@ -127,7 +127,7 @@ public class CertifyOperationTest {
ShadowLog.stream = oldShadowStream;
providerHelper.saveSecretKeyRing(mStaticRing1, new ProgressScaler());
- providerHelper.savePublicKeyRing(mStaticRing2.extractPublicKeyRing(), new ProgressScaler());
+ providerHelper.savePublicKeyRing(mStaticRing2.extractPublicKeyRing(), new ProgressScaler(), null);
// ok NOW log verbosely!
ShadowLog.stream = System.out;
@@ -158,7 +158,7 @@ public class CertifyOperationTest {
CertifyActionsParcel actions = new CertifyActionsParcel(mStaticRing1.getMasterKeyId());
actions.add(new CertifyAction(mStaticRing2.getMasterKeyId(),
- mStaticRing2.getPublicKey().getUnorderedUserIds()));
+ mStaticRing2.getPublicKey().getUnorderedUserIds(), null));
CertifyResult result = op.execute(actions, new CryptoInputParcel(new Date(), mKeyPhrase1));
Assert.assertTrue("certification must succeed", result.success());
@@ -208,7 +208,7 @@ public class CertifyOperationTest {
CertifyActionsParcel actions = new CertifyActionsParcel(mStaticRing1.getMasterKeyId());
actions.add(new CertifyAction(mStaticRing1.getMasterKeyId(),
- mStaticRing2.getPublicKey().getUnorderedUserIds()));
+ mStaticRing2.getPublicKey().getUnorderedUserIds(), null));
CertifyResult result = op.execute(actions, new CryptoInputParcel(new Date(), mKeyPhrase1));
@@ -227,7 +227,7 @@ public class CertifyOperationTest {
CertifyActionsParcel actions = new CertifyActionsParcel(mStaticRing1.getMasterKeyId());
ArrayList<String> uids = new ArrayList<String>();
uids.add("nonexistent");
- actions.add(new CertifyAction(1234L, uids));
+ actions.add(new CertifyAction(1234L, uids, null));
CertifyResult result = op.execute(actions, new CryptoInputParcel(new Date(),
mKeyPhrase1));
@@ -240,7 +240,7 @@ public class CertifyOperationTest {
{
CertifyActionsParcel actions = new CertifyActionsParcel(1234L);
actions.add(new CertifyAction(mStaticRing1.getMasterKeyId(),
- mStaticRing2.getPublicKey().getUnorderedUserIds()));
+ mStaticRing2.getPublicKey().getUnorderedUserIds(), null));
CertifyResult result = op.execute(actions, new CryptoInputParcel(new Date(),
mKeyPhrase1));
diff --git a/OpenKeychain/src/test/java/org/sufficientlysecure/keychain/operations/PromoteKeyOperationTest.java b/OpenKeychain/src/test/java/org/sufficientlysecure/keychain/operations/PromoteKeyOperationTest.java
index a4854d7b9..e6c8c0efe 100644
--- a/OpenKeychain/src/test/java/org/sufficientlysecure/keychain/operations/PromoteKeyOperationTest.java
+++ b/OpenKeychain/src/test/java/org/sufficientlysecure/keychain/operations/PromoteKeyOperationTest.java
@@ -98,7 +98,7 @@ public class PromoteKeyOperationTest {
// don't log verbosely here, we're not here to test imports
ShadowLog.stream = oldShadowStream;
- providerHelper.savePublicKeyRing(mStaticRing.extractPublicKeyRing(), new ProgressScaler());
+ providerHelper.savePublicKeyRing(mStaticRing.extractPublicKeyRing(), new ProgressScaler(), null);
// ok NOW log verbosely!
ShadowLog.stream = System.out;
diff --git a/OpenKeychain/src/test/java/org/sufficientlysecure/keychain/pgp/PgpEncryptDecryptTest.java b/OpenKeychain/src/test/java/org/sufficientlysecure/keychain/pgp/PgpEncryptDecryptTest.java
index cd6f115ec..727464429 100644
--- a/OpenKeychain/src/test/java/org/sufficientlysecure/keychain/pgp/PgpEncryptDecryptTest.java
+++ b/OpenKeychain/src/test/java/org/sufficientlysecure/keychain/pgp/PgpEncryptDecryptTest.java
@@ -23,9 +23,9 @@ import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.security.Security;
import java.util.ArrayList;
+import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
-import java.util.Date;
import org.junit.Assert;
import org.junit.Before;
@@ -196,7 +196,7 @@ public class PgpEncryptDecryptTest {
ByteArrayInputStream in = new ByteArrayInputStream(ciphertext);
InputData data = new InputData(in, in.available());
- PgpDecryptVerify op = new PgpDecryptVerify(RuntimeEnvironment.application,
+ PgpDecryptVerifyOperation op = new PgpDecryptVerifyOperation(RuntimeEnvironment.application,
new ProviderHelper(RuntimeEnvironment.application), null);
PgpDecryptVerifyInputParcel input = new PgpDecryptVerifyInputParcel();
input.setAllowSymmetricDecryption(true);
@@ -226,7 +226,7 @@ public class PgpEncryptDecryptTest {
ByteArrayInputStream in = new ByteArrayInputStream(ciphertext);
InputData data = new InputData(in, in.available());
- PgpDecryptVerify op = new PgpDecryptVerify(RuntimeEnvironment.application,
+ PgpDecryptVerifyOperation op = new PgpDecryptVerifyOperation(RuntimeEnvironment.application,
new ProviderHelper(RuntimeEnvironment.application), null);
PgpDecryptVerifyInputParcel input = new PgpDecryptVerifyInputParcel();
input.setAllowSymmetricDecryption(true);
@@ -248,7 +248,7 @@ public class PgpEncryptDecryptTest {
ByteArrayInputStream in = new ByteArrayInputStream(ciphertext);
InputData data = new InputData(in, in.available());
- PgpDecryptVerify op = new PgpDecryptVerify(RuntimeEnvironment.application,
+ PgpDecryptVerifyOperation op = new PgpDecryptVerifyOperation(RuntimeEnvironment.application,
new ProviderHelper(RuntimeEnvironment.application), null);
PgpDecryptVerifyInputParcel input = new PgpDecryptVerifyInputParcel();
input.setAllowSymmetricDecryption(true);
@@ -269,7 +269,7 @@ public class PgpEncryptDecryptTest {
ByteArrayInputStream in = new ByteArrayInputStream(ciphertext);
InputData data = new InputData(in, in.available());
- PgpDecryptVerify op = new PgpDecryptVerify(RuntimeEnvironment.application,
+ PgpDecryptVerifyOperation op = new PgpDecryptVerifyOperation(RuntimeEnvironment.application,
new ProviderHelper(RuntimeEnvironment.application), null);
PgpDecryptVerifyInputParcel input = new PgpDecryptVerifyInputParcel();
input.setAllowSymmetricDecryption(false);
@@ -287,6 +287,60 @@ public class PgpEncryptDecryptTest {
}
@Test
+ public void testAsymmetricSign() {
+
+ String plaintext = "dies ist ein plaintext ☭" + TestingUtils.genPassphrase(true);
+ byte[] ciphertext;
+
+ { // encrypt data with key
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ ByteArrayInputStream in = new ByteArrayInputStream(plaintext.getBytes());
+
+ PgpSignEncryptOperation op = new PgpSignEncryptOperation(RuntimeEnvironment.application,
+ new ProviderHelper(RuntimeEnvironment.application), null);
+
+ InputData data = new InputData(in, in.available());
+ PgpSignEncryptInputParcel input = new PgpSignEncryptInputParcel();
+
+ // only sign, and not as cleartext
+ input.setSignatureMasterKeyId(mStaticRing1.getMasterKeyId());
+ input.setSignatureSubKeyId(KeyringTestingHelper.getSubkeyId(mStaticRing1, 1));
+ input.setCleartextSignature(false);
+ input.setDetachedSignature(false);
+
+ PgpSignEncryptResult result = op.execute(input, new CryptoInputParcel(mKeyPhrase1), data, out);
+ Assert.assertTrue("signing must succeed", result.success());
+
+ ciphertext = out.toByteArray();
+ }
+
+ { // verification should succeed
+
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ ByteArrayInputStream in = new ByteArrayInputStream(ciphertext);
+ InputData data = new InputData(in, in.available());
+
+ PgpDecryptVerifyOperation op = operationWithFakePassphraseCache(null, null, null);
+ PgpDecryptVerifyInputParcel input = new PgpDecryptVerifyInputParcel();
+ DecryptVerifyResult result = op.execute(input, new CryptoInputParcel(), data, out);
+
+ Assert.assertTrue("verification must succeed", result.success());
+ Assert.assertArrayEquals("verification text should equal plaintext",
+ out.toByteArray(), plaintext.getBytes());
+ Assert.assertEquals("decryptionResult should be RESULT_NOT_ENCRYPTED",
+ OpenPgpDecryptionResult.RESULT_NOT_ENCRYPTED, result.getDecryptionResult().getResult());
+ Assert.assertEquals("signatureResult should be RESULT_VALID_CONFIRMED",
+ OpenPgpSignatureResult.RESULT_VALID_CONFIRMED, result.getSignatureResult().getResult());
+
+ OpenPgpMetadata metadata = result.getDecryptionMetadata();
+ Assert.assertEquals("filesize must be correct",
+ out.toByteArray().length, metadata.getOriginalSize());
+
+ }
+
+ }
+
+ @Test
public void testAsymmetricEncryptDecrypt() {
String plaintext = "dies ist ein plaintext ☭" + TestingUtils.genPassphrase(true);
@@ -318,7 +372,7 @@ public class PgpEncryptDecryptTest {
ByteArrayInputStream in = new ByteArrayInputStream(ciphertext);
InputData data = new InputData(in, in.available());
- PgpDecryptVerify op = operationWithFakePassphraseCache(null, null, null);
+ PgpDecryptVerifyOperation op = operationWithFakePassphraseCache(null, null, null);
PgpDecryptVerifyInputParcel input = new PgpDecryptVerifyInputParcel();
DecryptVerifyResult result = op.execute(input, new CryptoInputParcel(mKeyPhrase1), data, out);
@@ -346,7 +400,7 @@ public class PgpEncryptDecryptTest {
ByteArrayInputStream in = new ByteArrayInputStream(ciphertext);
InputData data = new InputData(in, in.available());
- PgpDecryptVerify op = operationWithFakePassphraseCache(
+ PgpDecryptVerifyOperation op = operationWithFakePassphraseCache(
mKeyPhrase1, mStaticRing1.getMasterKeyId(), null);
PgpDecryptVerifyInputParcel input = new PgpDecryptVerifyInputParcel();
DecryptVerifyResult result = op.execute(input, new CryptoInputParcel(), data, out);
@@ -370,7 +424,7 @@ public class PgpEncryptDecryptTest {
ByteArrayInputStream in = new ByteArrayInputStream(ciphertext);
InputData data = new InputData(in, in.available());
- PgpDecryptVerify op = operationWithFakePassphraseCache(
+ PgpDecryptVerifyOperation op = operationWithFakePassphraseCache(
null, mStaticRing1.getMasterKeyId(), null);
PgpDecryptVerifyInputParcel input = new PgpDecryptVerifyInputParcel();
DecryptVerifyResult result = op.execute(input, new CryptoInputParcel(), data, out);
@@ -519,7 +573,7 @@ public class PgpEncryptDecryptTest {
ByteArrayInputStream in = new ByteArrayInputStream(ciphertext);
InputData data = new InputData(in, in.available());
- PgpDecryptVerify op = operationWithFakePassphraseCache(
+ PgpDecryptVerifyOperation op = operationWithFakePassphraseCache(
mKeyPhrase1, mStaticRing1.getMasterKeyId(), null);
PgpDecryptVerifyInputParcel input = new PgpDecryptVerifyInputParcel();
DecryptVerifyResult result = op.execute(input, new CryptoInputParcel(), data, out);
@@ -548,7 +602,7 @@ public class PgpEncryptDecryptTest {
allowed.add(mStaticRing2.getMasterKeyId());
// provide passphrase for the second, and check that the first is never asked for!
- PgpDecryptVerify op = operationWithFakePassphraseCache(
+ PgpDecryptVerifyOperation op = operationWithFakePassphraseCache(
mKeyPhrase2, mStaticRing2.getMasterKeyId(), null);
PgpDecryptVerifyInputParcel input = new PgpDecryptVerifyInputParcel();
input.setAllowedKeyIds(allowed);
@@ -571,7 +625,7 @@ public class PgpEncryptDecryptTest {
InputData data = new InputData(in, in.available());
// provide passphrase for the second, and check that the first is never asked for!
- PgpDecryptVerify op = operationWithFakePassphraseCache(
+ PgpDecryptVerifyOperation op = operationWithFakePassphraseCache(
mKeyPhrase2, mStaticRing2.getMasterKeyId(), null);
PgpDecryptVerifyInputParcel input = new PgpDecryptVerifyInputParcel();
input.setAllowedKeyIds(new HashSet<Long>());
@@ -594,7 +648,7 @@ public class PgpEncryptDecryptTest {
ByteArrayInputStream in = new ByteArrayInputStream(ciphertext);
InputData data = new InputData(in, in.available());
- PgpDecryptVerify op = operationWithFakePassphraseCache(
+ PgpDecryptVerifyOperation op = operationWithFakePassphraseCache(
mKeyPhrase2, mStaticRing2.getMasterKeyId(), null);
PgpDecryptVerifyInputParcel input = new PgpDecryptVerifyInputParcel();
DecryptVerifyResult result = op.execute(input, new CryptoInputParcel(), data, out);
@@ -648,7 +702,7 @@ public class PgpEncryptDecryptTest {
ByteArrayInputStream in = new ByteArrayInputStream(ciphertext);
InputData data = new InputData(in, in.available());
- PgpDecryptVerify op = operationWithFakePassphraseCache(
+ PgpDecryptVerifyOperation op = operationWithFakePassphraseCache(
mKeyPhrase1, mStaticRing1.getMasterKeyId(), null);
PgpDecryptVerifyInputParcel input = new PgpDecryptVerifyInputParcel();
DecryptVerifyResult result = op.execute(input, new CryptoInputParcel(), data, out);
@@ -675,7 +729,7 @@ public class PgpEncryptDecryptTest {
ByteArrayInputStream in = new ByteArrayInputStream(ciphertext);
InputData data = new InputData(in, in.available());
- PgpDecryptVerify op = operationWithFakePassphraseCache(
+ PgpDecryptVerifyOperation op = operationWithFakePassphraseCache(
mKeyPhrase2, mStaticRing2.getMasterKeyId(), null);
PgpDecryptVerifyInputParcel input = new PgpDecryptVerifyInputParcel();
DecryptVerifyResult result = op.execute(input, new CryptoInputParcel(), data, out);
@@ -730,7 +784,7 @@ public class PgpEncryptDecryptTest {
ByteArrayInputStream in = new ByteArrayInputStream(ciphertext);
InputData data = new InputData(in, in.available());
- PgpDecryptVerify op = operationWithFakePassphraseCache(null, null, null);
+ PgpDecryptVerifyOperation op = operationWithFakePassphraseCache(null, null, null);
PgpDecryptVerifyInputParcel input = new PgpDecryptVerifyInputParcel();
DecryptVerifyResult result = op.execute(input, new CryptoInputParcel(mKeyPhrase1), data, out);
@@ -796,7 +850,7 @@ public class PgpEncryptDecryptTest {
ByteArrayInputStream in = new ByteArrayInputStream(ciphertext);
InputData data = new InputData(in, in.available());
- PgpDecryptVerify op = operationWithFakePassphraseCache(null, null, null);
+ PgpDecryptVerifyOperation op = operationWithFakePassphraseCache(null, null, null);
PgpDecryptVerifyInputParcel input = new PgpDecryptVerifyInputParcel();
DecryptVerifyResult result = op.execute(input, new CryptoInputParcel(passphrase), data, out);
@@ -819,10 +873,10 @@ public class PgpEncryptDecryptTest {
}
}
- private PgpDecryptVerify operationWithFakePassphraseCache(
+ private PgpDecryptVerifyOperation operationWithFakePassphraseCache(
final Passphrase passphrase, final Long checkMasterKeyId, final Long checkSubKeyId) {
- return new PgpDecryptVerify(RuntimeEnvironment.application,
+ return new PgpDecryptVerifyOperation(RuntimeEnvironment.application,
new ProviderHelper(RuntimeEnvironment.application), null) {
@Override
public Passphrase getCachedPassphrase(long masterKeyId, long subKeyId)
diff --git a/OpenKeychain/src/test/java/org/sufficientlysecure/keychain/pgp/UncachedKeyringMergeTest.java b/OpenKeychain/src/test/java/org/sufficientlysecure/keychain/pgp/UncachedKeyringMergeTest.java
index bb2c1323f..90189e377 100644
--- a/OpenKeychain/src/test/java/org/sufficientlysecure/keychain/pgp/UncachedKeyringMergeTest.java
+++ b/OpenKeychain/src/test/java/org/sufficientlysecure/keychain/pgp/UncachedKeyringMergeTest.java
@@ -304,7 +304,7 @@ public class UncachedKeyringMergeTest {
ringB.getEncoded(), false, 0).getSecretKey();
secretKey.unlock(new Passphrase());
PgpCertifyOperation op = new PgpCertifyOperation();
- CertifyAction action = new CertifyAction(pubRing.getMasterKeyId(), publicRing.getPublicKey().getUnorderedUserIds());
+ CertifyAction action = new CertifyAction(pubRing.getMasterKeyId(), publicRing.getPublicKey().getUnorderedUserIds(), null);
// sign all user ids
PgpCertifyResult result = op.certify(secretKey, publicRing, new OperationLog(), 0, action, null, new Date());
Assert.assertTrue("certification must succeed", result.success());
diff --git a/OpenKeychain/src/test/java/org/sufficientlysecure/keychain/provider/ProviderHelperSaveTest.java b/OpenKeychain/src/test/java/org/sufficientlysecure/keychain/provider/ProviderHelperSaveTest.java
index 04851ebbb..60cbe098c 100644
--- a/OpenKeychain/src/test/java/org/sufficientlysecure/keychain/provider/ProviderHelperSaveTest.java
+++ b/OpenKeychain/src/test/java/org/sufficientlysecure/keychain/provider/ProviderHelperSaveTest.java
@@ -201,7 +201,7 @@ public class ProviderHelperSaveTest {
SaveKeyringResult result;
- result = mProviderHelper.savePublicKeyRing(key, new ProgressScaler());
+ result = mProviderHelper.savePublicKeyRing(key, new ProgressScaler(), null);
Assert.assertTrue("import of keyring should succeed", result.success());
CanonicalizedPublicKeyRing ring = mProviderHelper.getCanonicalizedPublicKeyRing(keyId);
diff --git a/OpenKeychain/src/test/java/org/sufficientlysecure/keychain/support/KeyringTestingHelper.java b/OpenKeychain/src/test/java/org/sufficientlysecure/keychain/support/KeyringTestingHelper.java
index 4ac994c99..262b4da28 100644
--- a/OpenKeychain/src/test/java/org/sufficientlysecure/keychain/support/KeyringTestingHelper.java
+++ b/OpenKeychain/src/test/java/org/sufficientlysecure/keychain/support/KeyringTestingHelper.java
@@ -59,7 +59,7 @@ public class KeyringTestingHelper {
// Should throw an exception; key is not yet saved
retrieveKeyAndExpectNotFound(providerHelper, masterKeyId);
- SaveKeyringResult saveKeyringResult = providerHelper.savePublicKeyRing(ring, new ProgressScaler());
+ SaveKeyringResult saveKeyringResult = providerHelper.savePublicKeyRing(ring, new ProgressScaler(), null);
boolean saveSuccess = saveKeyringResult.success();
diff --git a/OpenKeychain/src/test/java/org/sufficientlysecure/keychain/util/KeyFormattingUtilsTest.java b/OpenKeychain/src/test/java/org/sufficientlysecure/keychain/util/KeyFormattingUtilsTest.java
new file mode 100644
index 000000000..44e383d85
--- /dev/null
+++ b/OpenKeychain/src/test/java/org/sufficientlysecure/keychain/util/KeyFormattingUtilsTest.java
@@ -0,0 +1,46 @@
+package org.sufficientlysecure.keychain.util;
+
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricGradleTestRunner;
+import org.robolectric.annotation.Config;
+import org.sufficientlysecure.keychain.WorkaroundBuildConfig;
+import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
+
+
+@RunWith(RobolectricGradleTestRunner.class)
+@Config(constants = WorkaroundBuildConfig.class, sdk = 21, manifest = "src/main/AndroidManifest.xml")
+public class KeyFormattingUtilsTest {
+
+ static final byte[] fp = new byte[] {
+ (byte) 0xD4, (byte) 0xAB, (byte) 0x19, (byte) 0x29, (byte) 0x64,
+ (byte) 0xF7, (byte) 0x6A, (byte) 0x7F, (byte) 0x8F, (byte) 0x8A,
+ (byte) 0x9B, (byte) 0x35, (byte) 0x7B, (byte) 0xD1, (byte) 0x83,
+ (byte) 0x20, (byte) 0xDE, (byte) 0xAD, (byte) 0xFA, (byte) 0x11
+ };
+ static final long keyId = 0x7bd18320deadfa11L;
+
+ @Test
+ public void testStuff() {
+ Assert.assertEquals(KeyFormattingUtils.convertFingerprintToKeyId(fp), keyId);
+
+ Assert.assertEquals(
+ "d4ab192964f76a7f8f8a9b357bd18320deadfa11",
+ KeyFormattingUtils.convertFingerprintToHex(fp)
+ );
+
+ Assert.assertEquals(
+ "0x7bd18320deadfa11",
+ KeyFormattingUtils.convertKeyIdToHex(keyId)
+ );
+
+ Assert.assertEquals(
+ "0xdeadfa11",
+ KeyFormattingUtils.convertKeyIdToHexShort(keyId)
+ );
+
+ }
+
+}
diff --git a/extern/openpgp-api-lib b/extern/openpgp-api-lib
-Subproject b42636ec3ec63bef61af264a0a9b09998db8186
+Subproject 13492ba19fcc1767f5589227b8fa0a9c845696d