Merge branch 'development' into linked-identities
Conflicts: OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyFragment.java
4
.gitmodules
vendored
@ -19,9 +19,11 @@
|
||||
[submodule "extern/minidns"]
|
||||
path = extern/minidns
|
||||
url = https://github.com/open-keychain/minidns.git
|
||||
ignore = dirty
|
||||
[submodule "extern/TokenAutoComplete"]
|
||||
path = extern/TokenAutoComplete
|
||||
url = https://github.com/open-keychain/TokenAutoComplete
|
||||
[submodule "extern/safeslinger-exchange"]
|
||||
path = extern/safeslinger-exchange
|
||||
url = https://github.com/open-keychain/exchange-android
|
||||
url = https://github.com/open-keychain/exchange-android
|
||||
ignore = dirty
|
||||
|
15
.tx/config
@ -17,14 +17,9 @@ file_filter = OpenKeychain/src/main/res/raw-<lang>/help_changelog.html
|
||||
source_file = OpenKeychain/src/main/res/raw/help_changelog.html
|
||||
source_lang = en
|
||||
|
||||
[open-keychain.help-wot]
|
||||
file_filter = OpenKeychain/src/main/res/raw-<lang>/help_wot.html
|
||||
source_file = OpenKeychain/src/main/res/raw/help_wot.html
|
||||
source_lang = en
|
||||
|
||||
[open-keychain.help-nfc-beam]
|
||||
file_filter = OpenKeychain/src/main/res/raw-<lang>/help_nfc_beam.html
|
||||
source_file = OpenKeychain/src/main/res/raw/help_nfc_beam.html
|
||||
[open-keychain.help-certification]
|
||||
file_filter = OpenKeychain/src/main/res/raw-<lang>/help_certification.html
|
||||
source_file = OpenKeychain/src/main/res/raw/help_certification.html
|
||||
source_lang = en
|
||||
|
||||
[open-keychain.help-start]
|
||||
@ -32,7 +27,3 @@ file_filter = OpenKeychain/src/main/res/raw-<lang>/help_start.html
|
||||
source_file = OpenKeychain/src/main/res/raw/help_start.html
|
||||
source_lang = en
|
||||
|
||||
[open-keychain.nfc-beam-share]
|
||||
file_filter = OpenKeychain/src/main/res/raw-<lang>/nfc_beam_share.html
|
||||
source_file = OpenKeychain/src/main/res/raw/nfc_beam_share.html
|
||||
source_lang = en
|
||||
|
@ -73,6 +73,9 @@ Mapping vars:
|
||||
|
||||
Options file
|
||||
============
|
||||
|
||||
*In this project, if you need to fetch new icons, rename options.templ.json to options.json. And then run script get-material-icons.sh*
|
||||
|
||||
Named `options.json` in same dir. Sample:
|
||||
```json
|
||||
{
|
||||
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"basePath": "~/Documents",
|
||||
"basePath": "../../",
|
||||
"filenameMap": {
|
||||
"classic": "ic_action_{name}{bgSuffix}.png",
|
||||
"fa": "ic_action_fa_{name}{bgSuffix}.png",
|
||||
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 466 B |
After Width: | Height: | Size: 434 B |
After Width: | Height: | Size: 661 B |
After Width: | Height: | Size: 583 B |
After Width: | Height: | Size: 651 B |
After Width: | Height: | Size: 642 B |
After Width: | Height: | Size: 938 B |
After Width: | Height: | Size: 954 B |
After Width: | Height: | Size: 480 B |
After Width: | Height: | Size: 467 B |
After Width: | Height: | Size: 717 B |
After Width: | Height: | Size: 704 B |
After Width: | Height: | Size: 331 B |
After Width: | Height: | Size: 261 B |
After Width: | Height: | Size: 434 B |
After Width: | Height: | Size: 371 B |
After Width: | Height: | Size: 449 B |
After Width: | Height: | Size: 382 B |
After Width: | Height: | Size: 642 B |
After Width: | Height: | Size: 583 B |
After Width: | Height: | Size: 353 B |
After Width: | Height: | Size: 280 B |
After Width: | Height: | Size: 467 B |
After Width: | Height: | Size: 446 B |
After Width: | Height: | Size: 434 B |
After Width: | Height: | Size: 371 B |
After Width: | Height: | Size: 583 B |
After Width: | Height: | Size: 730 B |
After Width: | Height: | Size: 642 B |
After Width: | Height: | Size: 583 B |
After Width: | Height: | Size: 954 B |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 467 B |
After Width: | Height: | Size: 446 B |
After Width: | Height: | Size: 704 B |
After Width: | Height: | Size: 908 B |
After Width: | Height: | Size: 661 B |
After Width: | Height: | Size: 583 B |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 938 B |
After Width: | Height: | Size: 954 B |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 717 B |
After Width: | Height: | Size: 704 B |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 583 B |
After Width: | Height: | Size: 730 B |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 954 B |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 2.5 KiB |
After Width: | Height: | Size: 704 B |
After Width: | Height: | Size: 908 B |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 2.0 KiB |
@ -0,0 +1,8 @@
|
||||
<!-- drawable/key-plus.xml -->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:height="24dp"
|
||||
android:width="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path android:fillColor="#000" android:pathData="M6.5,3C8.46,3 10.13,4.25 10.74,6H22V9H18V12H15V9H10.74C10.13,10.75 8.46,12 6.5,12C4,12 2,10 2,7.5C2,5 4,3 6.5,3M6.5,6A1.5,1.5 0 0,0 5,7.5A1.5,1.5 0 0,0 6.5,9A1.5,1.5 0 0,0 8,7.5A1.5,1.5 0 0,0 6.5,6M8,17H11V14H13V17H16V19H13V22H11V19H8V17Z" />
|
||||
</vector>
|
5
Graphics/drawables/originals/key-plus/readme.txt
Normal file
@ -0,0 +1,5 @@
|
||||
Thanks for visiting MaterialDesignIcons.com
|
||||
Check back often for new icons and follow @MaterialIcons for updates.
|
||||
|
||||
Icon: key-plus
|
||||
By: Austin Andrews
|
@ -10,6 +10,31 @@ python copy OpenKeychain navigation white refresh 24
|
||||
python copy OpenKeychain av white repeat 24
|
||||
python copy OpenKeychain av grey repeat 24
|
||||
python copy OpenKeychain editor white mode_edit 24
|
||||
python copy OpenKeychain content white save 24
|
||||
|
||||
python copy OpenKeychain action grey delete 24
|
||||
python copy OpenKeychain action grey done 24
|
||||
python copy OpenKeychain action grey search 24
|
||||
python copy OpenKeychain action grey settings 24
|
||||
python copy OpenKeychain action grey view_list 24
|
||||
python copy OpenKeychain action grey lock 24
|
||||
python copy OpenKeychain action grey lock_open 24
|
||||
python copy OpenKeychain alert grey warning 24
|
||||
python copy OpenKeychain av grey play_arrow 24
|
||||
python copy OpenKeychain communication grey import_export 24
|
||||
python copy OpenKeychain content grey content_copy 24
|
||||
python copy OpenKeychain content grey content_paste 24
|
||||
python copy OpenKeychain content grey save 24
|
||||
python copy OpenKeychain content grey select_all 24
|
||||
python copy OpenKeychain editor grey mode_edit 24
|
||||
python copy OpenKeychain file grey cloud 24
|
||||
python copy OpenKeychain file grey folder 24
|
||||
python copy OpenKeychain file grey file_download 24
|
||||
python copy OpenKeychain file grey file_upload 24
|
||||
python copy OpenKeychain navigation grey close 24
|
||||
python copy OpenKeychain social grey person 24
|
||||
python copy OpenKeychain social grey person_add 24
|
||||
python copy OpenKeychain social grey share 24
|
||||
|
||||
# navigation drawer sections
|
||||
python copy OpenKeychain communication black vpn_key 24
|
||||
@ -25,4 +50,4 @@ python copy OpenKeychain av white play_arrow 24
|
||||
python copy OpenKeychain file white folder 24
|
||||
|
||||
# multi select
|
||||
python copy OpenKeychain action white lock 24
|
||||
python copy OpenKeychain action white lock 24
|
||||
|
@ -10,17 +10,6 @@ XXXDPI_DIR=$APP_DIR/res/drawable-xxxhdpi
|
||||
PLAY_DIR=./drawables/
|
||||
SRC_DIR=./drawables/
|
||||
|
||||
|
||||
|
||||
# Launcher Icon:
|
||||
# -----------------------
|
||||
# mdpi: 48x48
|
||||
# hdpi: 72x72
|
||||
# xhdpi: 96x96
|
||||
# xxhdpi: 144x144.
|
||||
# xxxhdpi 192x192.
|
||||
# google play: 512x512
|
||||
|
||||
# Adobe Illustrator (.ai) exports by Tha Phlash are way better than the Inkscape exports (.svg)
|
||||
|
||||
#NAME="ic_launcher"
|
||||
@ -32,38 +21,24 @@ SRC_DIR=./drawables/
|
||||
#inkscape -w 192 -h 192 -e "$XXXDPI_DIR/$NAME.png" $NAME.svg
|
||||
#inkscape -w 512 -h 512 -e "$PLAY_DIR/$NAME.png" $NAME.svg
|
||||
|
||||
# Actionbar Icons
|
||||
# -----------------------
|
||||
# mdpi: 32x32
|
||||
# hdpi: 48x48
|
||||
# xhdpi: 64x64
|
||||
# xxhdpi: 96x96
|
||||
|
||||
for NAME in "ic_action_search_cloud" "ic_cloud_search_24px" "ic_action_encrypt_file" "ic_action_encrypt_text" "ic_action_verified_cutout"
|
||||
for NAME in "ic_cloud_search" "ic_action_encrypt_file" "ic_action_encrypt_text" "ic_action_verified_cutout" "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"
|
||||
do
|
||||
echo $NAME
|
||||
inkscape -w 32 -h 32 -e "$MDPI_DIR/$NAME.png" "$SRC_DIR/$NAME.svg"
|
||||
inkscape -w 48 -h 48 -e "$HDPI_DIR/$NAME.png" "$SRC_DIR/$NAME.svg"
|
||||
inkscape -w 64 -h 64 -e "$XDPI_DIR/$NAME.png" "$SRC_DIR/$NAME.svg"
|
||||
inkscape -w 96 -h 96 -e "$XXDPI_DIR/$NAME.png" "$SRC_DIR/$NAME.svg"
|
||||
done
|
||||
|
||||
for NAME in "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"
|
||||
do
|
||||
echo $NAME
|
||||
inkscape -w 24 -h 24 -e "$MDPI_DIR/${NAME}_24px.png" "$SRC_DIR/$NAME.svg"
|
||||
inkscape -w 32 -h 32 -e "$HDPI_DIR/${NAME}_24px.png" "$SRC_DIR/$NAME.svg"
|
||||
inkscape -w 48 -h 48 -e "$XDPI_DIR/${NAME}_24px.png" "$SRC_DIR/$NAME.svg"
|
||||
inkscape -w 64 -h 64 -e "$XXDPI_DIR/${NAME}_24px.png" "$SRC_DIR/$NAME.svg"
|
||||
inkscape -w 24 -h 24 -e "$MDPI_DIR/${NAME}_24dp.png" "$SRC_DIR/$NAME.svg"
|
||||
inkscape -w 36 -h 36 -e "$HDPI_DIR/${NAME}_24dp.png" "$SRC_DIR/$NAME.svg"
|
||||
inkscape -w 48 -h 48 -e "$XDPI_DIR/${NAME}_24dp.png" "$SRC_DIR/$NAME.svg"
|
||||
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"
|
||||
do
|
||||
echo $NAME
|
||||
inkscape -w 96 -h 96 -e "$MDPI_DIR/${NAME}_96px.png" "$SRC_DIR/$NAME.svg"
|
||||
inkscape -w 128 -h 128 -e "$HDPI_DIR/${NAME}_96px.png" "$SRC_DIR/$NAME.svg"
|
||||
inkscape -w 192 -h 192 -e "$XDPI_DIR/${NAME}_96px.png" "$SRC_DIR/$NAME.svg"
|
||||
inkscape -w 256 -h 256 -e "$XXDPI_DIR/${NAME}_96px.png" "$SRC_DIR/$NAME.svg"
|
||||
inkscape -w 96 -h 96 -e "$MDPI_DIR/${NAME}_96dp.png" "$SRC_DIR/$NAME.svg"
|
||||
inkscape -w 128 -h 128 -e "$HDPI_DIR/${NAME}_96dp.png" "$SRC_DIR/$NAME.svg"
|
||||
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"
|
||||
|
@ -3,11 +3,25 @@ apply plugin: 'witness'
|
||||
|
||||
dependencies {
|
||||
// NOTE: Always use fixed version codes not dynamic ones, e.g. 0.7.3 instead of 0.7.+, see README for more information
|
||||
// NOTE: libraries are pinned to a specific build, see below
|
||||
|
||||
// from local Android SDK
|
||||
compile 'com.android.support:support-v4:21.0.3'
|
||||
compile 'com.android.support:appcompat-v7:21.0.3'
|
||||
compile 'com.android.support:recyclerview-v7:21.0.3'
|
||||
compile 'com.android.support:cardview-v7:21.0.3'
|
||||
|
||||
// JCenter etc.
|
||||
compile 'com.eftimoff:android-patternview:1.0.1@aar'
|
||||
compile 'com.journeyapps:zxing-android-embedded:2.0.1@aar'
|
||||
compile 'com.journeyapps:zxing-android-integration:2.0.1@aar'
|
||||
compile 'com.google.zxing:core:3.0.1'
|
||||
compile 'com.jpardogo.materialtabstrip:library:1.0.9'
|
||||
compile 'it.neokree:MaterialNavigationDrawer:1.3.1'
|
||||
compile 'com.nispok:snackbar:2.9.1'
|
||||
compile 'com.getbase:floatingactionbutton:1.8.0'
|
||||
|
||||
// libs as submodules
|
||||
compile project(':extern:openpgp-api-lib')
|
||||
compile project(':extern:openkeychain-api-lib')
|
||||
compile project(':extern:html-textview')
|
||||
@ -20,16 +34,6 @@ dependencies {
|
||||
compile project(':extern:KeybaseLib:Lib')
|
||||
compile project(':extern:TokenAutoComplete:library')
|
||||
compile project(':extern:safeslinger-exchange')
|
||||
|
||||
// NOTE: libraries are pinned to a specific build, see below
|
||||
compile 'com.eftimoff:android-patternview:1.0.0@aar'
|
||||
compile 'com.journeyapps:zxing-android-embedded:2.0.1@aar'
|
||||
compile 'com.journeyapps:zxing-android-integration:2.0.1@aar'
|
||||
compile 'com.google.zxing:core:3.0.1'
|
||||
compile 'com.jpardogo.materialtabstrip:library:1.0.9'
|
||||
compile 'it.neokree:MaterialNavigationDrawer:1.3.1'
|
||||
compile 'com.nispok:snackbar:2.9.1'
|
||||
compile 'com.getbase:floatingactionbutton:1.8.0'
|
||||
}
|
||||
|
||||
// Output of ./gradlew -q calculateChecksums
|
||||
@ -40,6 +44,16 @@ dependencyVerification {
|
||||
'com.android.support:appcompat-v7:5dbeb5316d0a6027d646ae552804c3baa5e3bd53f7f33db50904d51505c8a0e5',
|
||||
'com.android.support:recyclerview-v7:e525ad3f33c84bb12b73d2dc975b55364a53f0f2d0697e043efba59ba73e22d2',
|
||||
'com.android.support:cardview-v7:45c48c2ab056bc7a8573970b10f8902742c5d443f180dae43c56557397ac39af',
|
||||
'com.eftimoff:android-patternview:cec80e7265b8d8278b3c55b5fcdf551e4600ac2c8bf60d8dd76adca538af0b1e',
|
||||
'com.journeyapps:zxing-android-embedded:5d6ba3931bd0b999695e363b571e95bd6bc9956340c1e6ce740cd0bff3d89a50',
|
||||
'com.journeyapps:zxing-android-integration:6f50bb07c057ac94319777ddfbb66f5d4f6190393418b2fc861e0e60d06f3c0d',
|
||||
'com.google.zxing:core:38c49045765281e4c170062fa3f48e4e988629bf985cab850c7497be5eaa72a1',
|
||||
'com.jpardogo.materialtabstrip:library:c6ef812fba4f74be7dc4a905faa4c2908cba261a94c13d4f96d5e67e4aad4aaa',
|
||||
'it.neokree:MaterialNavigationDrawer:1174d751a54689fccf53c1fbcdf439745926ae19024f4f1017afb6b29643c57d',
|
||||
'com.nispok:snackbar:59dc092a44c877e9ce5f9040c632d99e62d8932b0a4d67ba0ec9e35467d9047c',
|
||||
'com.getbase:floatingactionbutton:e63966148212e9685afad2370780ea239b6dbd2a06f6a3f919b98882318e6a32',
|
||||
'com.android.support:support-annotations:fdee2354787ef66b268e75958de3f7f6c4f8f325510a6dac9f49c929f83a63de',
|
||||
'com.balysv:material-ripple:587f19c1e27f16c7dc67ff9ac73838aa1451086ef05a15cee38bee3e4e1454ae',
|
||||
//'OpenKeychain.extern:openpgp-api-lib:b17bb282321351e4b00b4cd6422a57aadc13decae264019a88707bcb556439ea',
|
||||
//'OpenKeychain.extern:openkeychain-api-lib:5f95f01c066069d4bde68992fd8da5faac21510d009b1fdae7a2e28e43e82cf4',
|
||||
//'OpenKeychain.extern:html-textview:b58e343cf4c145e91f888806d06a2a7770a9e9331a72f08cfcf1128db30dcff3',
|
||||
@ -52,16 +66,6 @@ dependencyVerification {
|
||||
//'OpenKeychain.extern.KeybaseLib:Lib:af9bff087148e0859430d0b99ece096c41b315c5dc1ed500a68580b9b0e5ab11',
|
||||
//'OpenKeychain.extern.TokenAutoComplete:library:40d4212a95e947efdb02f2ca66c95a27d49fba848471a6317eca2b9cc18e8780',
|
||||
//'OpenKeychain.extern:safeslinger-exchange:94a1ce68217af7499579a042758283b1530912c53241bdfa06d1a079a5ae3faf',
|
||||
'com.eftimoff:android-patternview:a031eaed3b5cef8ea06c2d4a6e27693937f89ae483598d61b7027eeee0bed408',
|
||||
'com.journeyapps:zxing-android-embedded:5d6ba3931bd0b999695e363b571e95bd6bc9956340c1e6ce740cd0bff3d89a50',
|
||||
'com.journeyapps:zxing-android-integration:6f50bb07c057ac94319777ddfbb66f5d4f6190393418b2fc861e0e60d06f3c0d',
|
||||
'com.google.zxing:core:38c49045765281e4c170062fa3f48e4e988629bf985cab850c7497be5eaa72a1',
|
||||
'com.jpardogo.materialtabstrip:library:c6ef812fba4f74be7dc4a905faa4c2908cba261a94c13d4f96d5e67e4aad4aaa',
|
||||
'it.neokree:MaterialNavigationDrawer:1174d751a54689fccf53c1fbcdf439745926ae19024f4f1017afb6b29643c57d',
|
||||
'com.nispok:snackbar:59dc092a44c877e9ce5f9040c632d99e62d8932b0a4d67ba0ec9e35467d9047c',
|
||||
'com.getbase:floatingactionbutton:e63966148212e9685afad2370780ea239b6dbd2a06f6a3f919b98882318e6a32',
|
||||
'com.android.support:support-annotations:fdee2354787ef66b268e75958de3f7f6c4f8f325510a6dac9f49c929f83a63de',
|
||||
'com.balysv:material-ripple:587f19c1e27f16c7dc67ff9ac73838aa1451086ef05a15cee38bee3e4e1454ae',
|
||||
]
|
||||
}
|
||||
|
||||
|
@ -67,10 +67,8 @@
|
||||
<uses-permission android:name="android.permission.READ_PROFILE" />
|
||||
|
||||
<!-- android:allowBackup="false": Don't allow backup over adb backup or other apps! -->
|
||||
<!-- tools:replace="android:allowBackup" is a workaround for https://github.com/geftimov/android-patternview/pull/2 -->
|
||||
<application
|
||||
android:name=".KeychainApplication"
|
||||
tools:replace="android:allowBackup"
|
||||
android:allowBackup="false"
|
||||
android:hardwareAccelerated="true"
|
||||
android:icon="@drawable/ic_launcher"
|
||||
|
@ -33,6 +33,7 @@ public final class Constants {
|
||||
|
||||
public static final String ACCOUNT_NAME = "OpenKeychain";
|
||||
public static final String ACCOUNT_TYPE = PACKAGE_NAME + ".account";
|
||||
public static final String CUSTOM_CONTACT_DATA_MIME_TYPE = "vnd.android.cursor.item/vnd.org.sufficientlysecure.keychain.key";
|
||||
|
||||
// as defined in http://tools.ietf.org/html/rfc3156, section 7
|
||||
public static final String NFC_MIME = "application/pgp-keys";
|
||||
@ -49,8 +50,6 @@ public final class Constants {
|
||||
public static final String INTENT_PREFIX = PACKAGE_NAME + ".action.";
|
||||
public static final String EXTRA_PREFIX = PACKAGE_NAME + ".";
|
||||
|
||||
public static final String CUSTOM_CONTACT_DATA_MIME_TYPE = "vnd.android.cursor.item/vnd.org.sufficientlysecure.keychain.key";
|
||||
|
||||
public static final int TEMPFILE_TTL = 24 * 60 * 60 * 1000; // 1 day
|
||||
|
||||
public static final String SAFESLINGER_SERVER = "safeslinger-openpgp.appspot.com";
|
||||
|
@ -140,20 +140,22 @@ public class KeychainApplication extends Application {
|
||||
}
|
||||
|
||||
static void brandGlowEffect(Context context, int brandColor) {
|
||||
try {
|
||||
// terrible hack to brand the edge overscroll glow effect
|
||||
// https://gist.github.com/menny/7878762#file-brandgloweffect_full-java
|
||||
// no hack on Android 5
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
|
||||
try {
|
||||
// terrible hack to brand the edge overscroll glow effect
|
||||
// https://gist.github.com/menny/7878762#file-brandgloweffect_full-java
|
||||
|
||||
//glow
|
||||
int glowDrawableId = context.getResources().getIdentifier("overscroll_glow", "drawable", "android");
|
||||
Drawable androidGlow = context.getResources().getDrawable(glowDrawableId);
|
||||
androidGlow.setColorFilter(brandColor, PorterDuff.Mode.SRC_IN);
|
||||
//edge
|
||||
int edgeDrawableId = context.getResources().getIdentifier("overscroll_edge", "drawable", "android");
|
||||
Drawable androidEdge = context.getResources().getDrawable(edgeDrawableId);
|
||||
androidEdge.setColorFilter(brandColor, PorterDuff.Mode.SRC_IN);
|
||||
} catch (Resources.NotFoundException e) {
|
||||
// no hack on Android 5
|
||||
//glow
|
||||
int glowDrawableId = context.getResources().getIdentifier("overscroll_glow", "drawable", "android");
|
||||
Drawable androidGlow = context.getResources().getDrawable(glowDrawableId);
|
||||
androidGlow.setColorFilter(brandColor, PorterDuff.Mode.SRC_IN);
|
||||
//edge
|
||||
int edgeDrawableId = context.getResources().getIdentifier("overscroll_edge", "drawable", "android");
|
||||
Drawable androidEdge = context.getResources().getDrawable(edgeDrawableId);
|
||||
androidEdge.setColorFilter(brandColor, PorterDuff.Mode.SRC_IN);
|
||||
} catch (Resources.NotFoundException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -38,6 +38,8 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/** Represent the result of an operation.
|
||||
*
|
||||
@ -51,6 +53,56 @@ import java.util.List;
|
||||
public abstract class OperationResult implements Parcelable {
|
||||
|
||||
public static final String EXTRA_RESULT = "operation_result";
|
||||
public static final UUID NULL_UUID = new UUID(0,0);
|
||||
|
||||
/**
|
||||
* A HashMap of UUID:OperationLog which contains logs that we don't need
|
||||
* to care about. This is used such that when we become parceled, we are
|
||||
* well below the 1Mbit boundary that is specified.
|
||||
*/
|
||||
private static ConcurrentHashMap<UUID, OperationLog> dehydratedLogs;
|
||||
static {
|
||||
// Static initializer for ConcurrentHashMap
|
||||
dehydratedLogs = new ConcurrentHashMap<UUID,OperationLog>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Dehydrate a log (such that it is available after deparcelization)
|
||||
*
|
||||
* Returns the NULL uuid (0) if you hand it null.
|
||||
* @param log An OperationLog to dehydrate
|
||||
* @return a UUID, the ticket for your dehydrated log
|
||||
*
|
||||
*/
|
||||
private static UUID dehydrateLog(OperationLog log) {
|
||||
if(log == null) {
|
||||
return NULL_UUID;
|
||||
}
|
||||
else {
|
||||
UUID ticket = UUID.randomUUID();
|
||||
dehydratedLogs.put(ticket, log);
|
||||
return ticket;
|
||||
}
|
||||
}
|
||||
|
||||
/***
|
||||
* Rehydrate a log after going through parcelization, invalidating its place in the
|
||||
* dehydration pool.
|
||||
* This is used such that when parcelized, the parcel is no larger than 1mbit.
|
||||
* @param ticket A UUID ticket that identifies the log in question.
|
||||
* @return An OperationLog.
|
||||
*/
|
||||
private static OperationLog rehydrateLog(UUID ticket) {
|
||||
// UUID.equals isn't well documented; we use compareTo instead.
|
||||
if( NULL_UUID.compareTo(ticket) == 0 ) {
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
OperationLog log = dehydratedLogs.get(ticket);
|
||||
dehydratedLogs.remove(ticket);
|
||||
return log;
|
||||
}
|
||||
}
|
||||
|
||||
/** Holds the overall result, the number specifying varying degrees of success:
|
||||
* - The first bit is 0 on overall success, 1 on overall failure
|
||||
@ -65,7 +117,7 @@ public abstract class OperationResult implements Parcelable {
|
||||
public static final int RESULT_WARNINGS = 4;
|
||||
|
||||
/// A list of log entries tied to the operation result.
|
||||
final OperationLog mLog;
|
||||
protected OperationLog mLog;
|
||||
|
||||
public OperationResult(int result, OperationLog log) {
|
||||
mResult = result;
|
||||
@ -74,8 +126,11 @@ public abstract class OperationResult implements Parcelable {
|
||||
|
||||
public OperationResult(Parcel source) {
|
||||
mResult = source.readInt();
|
||||
mLog = new OperationLog();
|
||||
mLog.addAll(source.createTypedArrayList(LogEntryParcel.CREATOR));
|
||||
long mostSig = source.readLong();
|
||||
long leastSig = source.readLong();
|
||||
UUID mTicket = new UUID(mostSig, leastSig);
|
||||
// fetch the dehydrated log out of storage (this removes it from the dehydration pool)
|
||||
mLog = rehydrateLog(mTicket);
|
||||
}
|
||||
|
||||
public int getResult() {
|
||||
@ -723,6 +778,12 @@ public abstract class OperationResult implements Parcelable {
|
||||
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),
|
||||
|
||||
//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),
|
||||
;
|
||||
|
||||
public final int mMsgId;
|
||||
@ -755,9 +816,11 @@ public abstract class OperationResult implements Parcelable {
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeInt(mResult);
|
||||
if (mLog != null) {
|
||||
dest.writeTypedList(mLog.toList());
|
||||
}
|
||||
// Get a ticket for our log.
|
||||
UUID mTicket = dehydrateLog(mLog);
|
||||
// And write out the UUID most and least significant bits.
|
||||
dest.writeLong(mTicket.getMostSignificantBits());
|
||||
dest.writeLong(mTicket.getLeastSignificantBits());
|
||||
}
|
||||
|
||||
public static class OperationLog implements Iterable<LogEntryParcel> {
|
||||
|
@ -100,8 +100,8 @@ public class PgpKeyOperation {
|
||||
private static final int[] PREFERRED_HASH_ALGORITHMS = new int[]{
|
||||
HashAlgorithmTags.SHA512,
|
||||
HashAlgorithmTags.SHA384,
|
||||
HashAlgorithmTags.SHA224,
|
||||
HashAlgorithmTags.SHA256,
|
||||
HashAlgorithmTags.SHA224,
|
||||
HashAlgorithmTags.RIPEMD160
|
||||
};
|
||||
private static final int[] PREFERRED_COMPRESSION_ALGORITHMS = new int[]{
|
||||
@ -131,6 +131,7 @@ public class PgpKeyOperation {
|
||||
private static final int SECRET_KEY_ENCRYPTOR_S2K_COUNT = 0x90;
|
||||
private static final int SECRET_KEY_ENCRYPTOR_HASH_ALGO = HashAlgorithmTags.SHA256;
|
||||
private static final int SECRET_KEY_ENCRYPTOR_SYMMETRIC_ALGO = SymmetricKeyAlgorithmTags.AES_256;
|
||||
private static final int SECRET_KEY_SIGNATURE_HASH_ALGO = HashAlgorithmTags.SHA256;
|
||||
|
||||
public PgpKeyOperation(Progressable progress) {
|
||||
super();
|
||||
@ -1025,7 +1026,7 @@ public class PgpKeyOperation {
|
||||
|
||||
// add packet with EMPTY notation data (updates old one, but will be stripped later)
|
||||
PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder(
|
||||
masterPrivateKey.getPublicKeyPacket().getAlgorithm(), HashAlgorithmTags.SHA512)
|
||||
masterPrivateKey.getPublicKeyPacket().getAlgorithm(), SECRET_KEY_SIGNATURE_HASH_ALGO)
|
||||
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
|
||||
PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder);
|
||||
{ // set subpackets
|
||||
@ -1051,7 +1052,7 @@ public class PgpKeyOperation {
|
||||
|
||||
// add packet with "pin" notation data
|
||||
PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder(
|
||||
masterPrivateKey.getPublicKeyPacket().getAlgorithm(), HashAlgorithmTags.SHA512)
|
||||
masterPrivateKey.getPublicKeyPacket().getAlgorithm(), SECRET_KEY_SIGNATURE_HASH_ALGO)
|
||||
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
|
||||
PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder);
|
||||
{ // set subpackets
|
||||
@ -1236,7 +1237,7 @@ public class PgpKeyOperation {
|
||||
int flags, long expiry)
|
||||
throws IOException, PGPException, SignatureException {
|
||||
PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder(
|
||||
masterPrivateKey.getPublicKeyPacket().getAlgorithm(), HashAlgorithmTags.SHA512)
|
||||
masterPrivateKey.getPublicKeyPacket().getAlgorithm(), SECRET_KEY_SIGNATURE_HASH_ALGO)
|
||||
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
|
||||
PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder);
|
||||
|
||||
@ -1279,7 +1280,7 @@ public class PgpKeyOperation {
|
||||
PGPUserAttributeSubpacketVector vector)
|
||||
throws IOException, PGPException, SignatureException {
|
||||
PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder(
|
||||
masterPrivateKey.getPublicKeyPacket().getAlgorithm(), HashAlgorithmTags.SHA512)
|
||||
masterPrivateKey.getPublicKeyPacket().getAlgorithm(), SECRET_KEY_SIGNATURE_HASH_ALGO)
|
||||
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
|
||||
PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder);
|
||||
|
||||
@ -1298,7 +1299,7 @@ public class PgpKeyOperation {
|
||||
PGPPrivateKey masterPrivateKey, PGPPublicKey pKey, String userId)
|
||||
throws IOException, PGPException, SignatureException {
|
||||
PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder(
|
||||
masterPrivateKey.getPublicKeyPacket().getAlgorithm(), HashAlgorithmTags.SHA512)
|
||||
masterPrivateKey.getPublicKeyPacket().getAlgorithm(), SECRET_KEY_SIGNATURE_HASH_ALGO)
|
||||
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
|
||||
PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder);
|
||||
PGPSignatureSubpacketGenerator subHashedPacketsGen = new PGPSignatureSubpacketGenerator();
|
||||
@ -1312,7 +1313,7 @@ public class PgpKeyOperation {
|
||||
PGPPublicKey masterPublicKey, PGPPrivateKey masterPrivateKey, PGPPublicKey pKey)
|
||||
throws IOException, PGPException, SignatureException {
|
||||
PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder(
|
||||
masterPublicKey.getAlgorithm(), HashAlgorithmTags.SHA512)
|
||||
masterPublicKey.getAlgorithm(), SECRET_KEY_SIGNATURE_HASH_ALGO)
|
||||
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
|
||||
PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder);
|
||||
PGPSignatureSubpacketGenerator subHashedPacketsGen = new PGPSignatureSubpacketGenerator();
|
||||
@ -1356,7 +1357,7 @@ public class PgpKeyOperation {
|
||||
PGPSignatureSubpacketGenerator subHashedPacketsGen = new PGPSignatureSubpacketGenerator();
|
||||
subHashedPacketsGen.setSignatureCreationTime(false, creationTime);
|
||||
PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder(
|
||||
pKey.getAlgorithm(), HashAlgorithmTags.SHA512)
|
||||
pKey.getAlgorithm(), SECRET_KEY_SIGNATURE_HASH_ALGO)
|
||||
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
|
||||
PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder);
|
||||
sGen.init(PGPSignature.PRIMARYKEY_BINDING, subPrivateKey);
|
||||
@ -1377,7 +1378,7 @@ public class PgpKeyOperation {
|
||||
}
|
||||
|
||||
PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder(
|
||||
masterPublicKey.getAlgorithm(), HashAlgorithmTags.SHA512)
|
||||
masterPublicKey.getAlgorithm(), SECRET_KEY_SIGNATURE_HASH_ALGO)
|
||||
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
|
||||
PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder);
|
||||
sGen.init(PGPSignature.SUBKEY_BINDING, masterPrivateKey);
|
||||
|
@ -28,9 +28,11 @@ public class CreateKeyActivity extends BaseActivity {
|
||||
public static final String EXTRA_NAME = "name";
|
||||
public static final String EXTRA_EMAIL = "email";
|
||||
|
||||
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;
|
||||
public static enum FragAction {
|
||||
START,
|
||||
TO_RIGHT,
|
||||
TO_LEFT
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
@ -42,7 +44,7 @@ public class CreateKeyActivity extends BaseActivity {
|
||||
getIntent().getStringExtra(EXTRA_NAME),
|
||||
getIntent().getStringExtra(EXTRA_EMAIL)
|
||||
);
|
||||
loadFragment(null, frag, FRAG_ACTION_START);
|
||||
loadFragment(null, frag, FragAction.START);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -50,7 +52,7 @@ public class CreateKeyActivity extends BaseActivity {
|
||||
setContentView(R.layout.create_key_activity);
|
||||
}
|
||||
|
||||
public void loadFragment(Bundle savedInstanceState, Fragment fragment, int action) {
|
||||
public void loadFragment(Bundle savedInstanceState, Fragment fragment, FragAction 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.
|
||||
@ -63,15 +65,15 @@ public class CreateKeyActivity extends BaseActivity {
|
||||
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
|
||||
|
||||
switch (action) {
|
||||
case FRAG_ACTION_START:
|
||||
case START:
|
||||
transaction.setCustomAnimations(0, 0);
|
||||
transaction.replace(R.id.create_key_fragment_container, fragment)
|
||||
.commitAllowingStateLoss();
|
||||
break;
|
||||
case FRAG_ACTION_TO_LEFT:
|
||||
case TO_LEFT:
|
||||
getSupportFragmentManager().popBackStackImmediate();
|
||||
break;
|
||||
case FRAG_ACTION_TO_RIGHT:
|
||||
case 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);
|
||||
|
@ -43,6 +43,7 @@ import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
|
||||
import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
|
||||
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Algorithm;
|
||||
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.ChangeUnlockParcel;
|
||||
import org.sufficientlysecure.keychain.ui.CreateKeyActivity.FragAction;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
import org.sufficientlysecure.keychain.util.Preferences;
|
||||
|
||||
@ -117,7 +118,7 @@ public class CreateKeyFinalFragment extends Fragment {
|
||||
mBackButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
mCreateKeyActivity.loadFragment(null, null, CreateKeyActivity.FRAG_ACTION_TO_LEFT);
|
||||
mCreateKeyActivity.loadFragment(null, null, FragAction.TO_LEFT);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -32,6 +32,7 @@ import android.widget.AutoCompleteTextView;
|
||||
import android.widget.EditText;
|
||||
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.ui.CreateKeyActivity.FragAction;
|
||||
import org.sufficientlysecure.keychain.util.ContactHelper;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
@ -161,7 +162,7 @@ public class CreateKeyInputFragment extends Fragment {
|
||||
);
|
||||
|
||||
hideKeyboard();
|
||||
mCreateKeyActivity.loadFragment(null, frag, CreateKeyActivity.FRAG_ACTION_TO_RIGHT);
|
||||
mCreateKeyActivity.loadFragment(null, frag, FragAction.TO_RIGHT);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -31,6 +31,7 @@ import org.sufficientlysecure.keychain.operations.results.DecryptVerifyResult;
|
||||
import org.sufficientlysecure.keychain.pgp.KeyRing;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract;
|
||||
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
|
||||
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils.State;
|
||||
|
||||
public abstract class DecryptFragment extends Fragment {
|
||||
private static final int RESULT_CODE_LOOKUP_KEY = 0x00007006;
|
||||
@ -141,16 +142,16 @@ public abstract class DecryptFragment extends Fragment {
|
||||
|
||||
if (signatureResult.isSignatureOnly()) {
|
||||
mEncryptionText.setText(R.string.decrypt_result_not_encrypted);
|
||||
KeyFormattingUtils.setStatusImage(getActivity(), mEncryptionIcon, mEncryptionText, KeyFormattingUtils.STATE_NOT_ENCRYPTED);
|
||||
KeyFormattingUtils.setStatusImage(getActivity(), mEncryptionIcon, mEncryptionText, State.NOT_ENCRYPTED);
|
||||
} else {
|
||||
mEncryptionText.setText(R.string.decrypt_result_encrypted);
|
||||
KeyFormattingUtils.setStatusImage(getActivity(), mEncryptionIcon, mEncryptionText, KeyFormattingUtils.STATE_ENCRYPTED);
|
||||
KeyFormattingUtils.setStatusImage(getActivity(), mEncryptionIcon, mEncryptionText, State.ENCRYPTED);
|
||||
}
|
||||
|
||||
switch (signatureResult.getStatus()) {
|
||||
case OpenPgpSignatureResult.SIGNATURE_SUCCESS_CERTIFIED: {
|
||||
mSignatureText.setText(R.string.decrypt_result_signature_certified);
|
||||
KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, KeyFormattingUtils.STATE_VERIFIED);
|
||||
KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, State.VERIFIED);
|
||||
|
||||
setSignatureLayoutVisibility(View.VISIBLE);
|
||||
setShowAction(mSignatureKeyId);
|
||||
@ -161,7 +162,7 @@ public abstract class DecryptFragment extends Fragment {
|
||||
|
||||
case OpenPgpSignatureResult.SIGNATURE_SUCCESS_UNCERTIFIED: {
|
||||
mSignatureText.setText(R.string.decrypt_result_signature_uncertified);
|
||||
KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, KeyFormattingUtils.STATE_UNVERIFIED);
|
||||
KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, State.UNVERIFIED);
|
||||
|
||||
setSignatureLayoutVisibility(View.VISIBLE);
|
||||
setShowAction(mSignatureKeyId);
|
||||
@ -172,11 +173,11 @@ public abstract class DecryptFragment extends Fragment {
|
||||
|
||||
case OpenPgpSignatureResult.SIGNATURE_KEY_MISSING: {
|
||||
mSignatureText.setText(R.string.decrypt_result_signature_missing_key);
|
||||
KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, KeyFormattingUtils.STATE_UNKNOWN_KEY);
|
||||
KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, State.UNKNOWN_KEY);
|
||||
|
||||
setSignatureLayoutVisibility(View.VISIBLE);
|
||||
mSignatureAction.setText(R.string.decrypt_result_action_Lookup);
|
||||
mSignatureAction.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_action_download, 0);
|
||||
mSignatureAction.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_file_download_grey_24dp, 0);
|
||||
mSignatureLayout.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
@ -190,7 +191,7 @@ public abstract class DecryptFragment extends Fragment {
|
||||
|
||||
case OpenPgpSignatureResult.SIGNATURE_KEY_EXPIRED: {
|
||||
mSignatureText.setText(R.string.decrypt_result_signature_expired_key);
|
||||
KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, KeyFormattingUtils.STATE_EXPIRED);
|
||||
KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, State.EXPIRED);
|
||||
|
||||
setSignatureLayoutVisibility(View.VISIBLE);
|
||||
setShowAction(mSignatureKeyId);
|
||||
@ -201,7 +202,7 @@ public abstract class DecryptFragment extends Fragment {
|
||||
|
||||
case OpenPgpSignatureResult.SIGNATURE_KEY_REVOKED: {
|
||||
mSignatureText.setText(R.string.decrypt_result_signature_revoked_key);
|
||||
KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, KeyFormattingUtils.STATE_REVOKED);
|
||||
KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, State.REVOKED);
|
||||
|
||||
setSignatureLayoutVisibility(View.VISIBLE);
|
||||
setShowAction(mSignatureKeyId);
|
||||
@ -212,7 +213,7 @@ public abstract class DecryptFragment extends Fragment {
|
||||
|
||||
case OpenPgpSignatureResult.SIGNATURE_ERROR: {
|
||||
mSignatureText.setText(R.string.decrypt_result_invalid_signature);
|
||||
KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, KeyFormattingUtils.STATE_INVALID);
|
||||
KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, State.INVALID);
|
||||
|
||||
setSignatureLayoutVisibility(View.GONE);
|
||||
|
||||
@ -224,9 +225,9 @@ public abstract class DecryptFragment extends Fragment {
|
||||
setSignatureLayoutVisibility(View.GONE);
|
||||
|
||||
mSignatureText.setText(R.string.decrypt_result_no_signature);
|
||||
KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, KeyFormattingUtils.STATE_NOT_SIGNED);
|
||||
KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, State.NOT_SIGNED);
|
||||
mEncryptionText.setText(R.string.decrypt_result_encrypted);
|
||||
KeyFormattingUtils.setStatusImage(getActivity(), mEncryptionIcon, mEncryptionText, KeyFormattingUtils.STATE_ENCRYPTED);
|
||||
KeyFormattingUtils.setStatusImage(getActivity(), mEncryptionIcon, mEncryptionText, State.ENCRYPTED);
|
||||
|
||||
valid = true;
|
||||
}
|
||||
|
@ -32,10 +32,9 @@ public class HelpActivity extends BaseActivity {
|
||||
|
||||
public static final int TAB_START = 0;
|
||||
public static final int TAB_FAQ = 1;
|
||||
public static final int TAB_WOT = 2;
|
||||
public static final int TAB_NFC = 3;
|
||||
public static final int TAB_CHANGELOG = 4;
|
||||
public static final int TAB_ABOUT = 5;
|
||||
public static final int TAB_TRUST = 2;
|
||||
public static final int TAB_CHANGELOG = 3;
|
||||
public static final int TAB_ABOUT = 4;
|
||||
|
||||
ViewPager mViewPager;
|
||||
private PagerTabStripAdapter mTabsAdapter;
|
||||
@ -69,21 +68,11 @@ public class HelpActivity extends BaseActivity {
|
||||
mTabsAdapter.addTab(HelpHtmlFragment.class, startBundle,
|
||||
getString(R.string.help_tab_start));
|
||||
|
||||
Bundle faqBundle = new Bundle();
|
||||
faqBundle.putInt(HelpHtmlFragment.ARG_HTML_FILE, R.raw.help_faq);
|
||||
mTabsAdapter.addTab(HelpHtmlFragment.class, faqBundle,
|
||||
getString(R.string.help_tab_faq));
|
||||
|
||||
Bundle wotBundle = new Bundle();
|
||||
wotBundle.putInt(HelpHtmlFragment.ARG_HTML_FILE, R.raw.help_wot);
|
||||
wotBundle.putInt(HelpHtmlFragment.ARG_HTML_FILE, R.raw.help_certification);
|
||||
mTabsAdapter.addTab(HelpHtmlFragment.class, wotBundle,
|
||||
getString(R.string.help_tab_wot));
|
||||
|
||||
Bundle nfcBundle = new Bundle();
|
||||
nfcBundle.putInt(HelpHtmlFragment.ARG_HTML_FILE, R.raw.help_nfc_beam);
|
||||
mTabsAdapter.addTab(HelpHtmlFragment.class, nfcBundle,
|
||||
getString(R.string.help_tab_nfc_beam));
|
||||
|
||||
Bundle changelogBundle = new Bundle();
|
||||
changelogBundle.putInt(HelpHtmlFragment.ARG_HTML_FILE, R.raw.help_changelog);
|
||||
mTabsAdapter.addTab(HelpHtmlFragment.class, changelogBundle,
|
||||
|
@ -70,6 +70,7 @@ import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
|
||||
import org.sufficientlysecure.keychain.ui.dialog.DeleteKeyDialogFragment;
|
||||
import org.sufficientlysecure.keychain.ui.util.Highlighter;
|
||||
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.util.ExportHelper;
|
||||
import org.sufficientlysecure.keychain.util.FabContainer;
|
||||
@ -77,7 +78,6 @@ import org.sufficientlysecure.keychain.util.Log;
|
||||
import org.sufficientlysecure.keychain.util.Preferences;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
|
||||
import se.emilsjolander.stickylistheaders.StickyListHeadersAdapter;
|
||||
@ -268,7 +268,7 @@ public class KeyListFragment extends LoaderFragment
|
||||
KeyRings.MASTER_KEY_ID,
|
||||
KeyRings.USER_ID,
|
||||
KeyRings.IS_REVOKED,
|
||||
KeyRings.EXPIRY,
|
||||
KeyRings.IS_EXPIRED,
|
||||
KeyRings.VERIFIED,
|
||||
KeyRings.HAS_ANY_SECRET
|
||||
};
|
||||
@ -276,7 +276,7 @@ public class KeyListFragment extends LoaderFragment
|
||||
static final int INDEX_MASTER_KEY_ID = 1;
|
||||
static final int INDEX_USER_ID = 2;
|
||||
static final int INDEX_IS_REVOKED = 3;
|
||||
static final int INDEX_EXPIRY = 4;
|
||||
static final int INDEX_IS_EXPIRED = 4;
|
||||
static final int INDEX_VERIFIED = 5;
|
||||
static final int INDEX_HAS_ANY_SECRET = 6;
|
||||
|
||||
@ -708,21 +708,20 @@ public class KeyListFragment extends LoaderFragment
|
||||
long masterKeyId = cursor.getLong(INDEX_MASTER_KEY_ID);
|
||||
boolean isSecret = cursor.getInt(INDEX_HAS_ANY_SECRET) != 0;
|
||||
boolean isRevoked = cursor.getInt(INDEX_IS_REVOKED) > 0;
|
||||
boolean isExpired = !cursor.isNull(INDEX_EXPIRY)
|
||||
&& new Date(cursor.getLong(INDEX_EXPIRY) * 1000).before(new Date());
|
||||
boolean isExpired = cursor.getInt(INDEX_IS_EXPIRED) != 0;
|
||||
boolean isVerified = cursor.getInt(INDEX_VERIFIED) > 0;
|
||||
|
||||
h.mMasterKeyId = masterKeyId;
|
||||
|
||||
// Note: order is important!
|
||||
if (isRevoked) {
|
||||
KeyFormattingUtils.setStatusImage(getActivity(), h.mStatus, null, KeyFormattingUtils.STATE_REVOKED, R.color.bg_gray);
|
||||
KeyFormattingUtils.setStatusImage(getActivity(), h.mStatus, null, State.REVOKED, R.color.bg_gray);
|
||||
h.mStatus.setVisibility(View.VISIBLE);
|
||||
h.mSlinger.setVisibility(View.GONE);
|
||||
h.mMainUserId.setTextColor(context.getResources().getColor(R.color.bg_gray));
|
||||
h.mMainUserIdRest.setTextColor(context.getResources().getColor(R.color.bg_gray));
|
||||
} else if (isExpired) {
|
||||
KeyFormattingUtils.setStatusImage(getActivity(), h.mStatus, null, KeyFormattingUtils.STATE_EXPIRED, R.color.bg_gray);
|
||||
KeyFormattingUtils.setStatusImage(getActivity(), h.mStatus, null, State.EXPIRED, R.color.bg_gray);
|
||||
h.mStatus.setVisibility(View.VISIBLE);
|
||||
h.mSlinger.setVisibility(View.GONE);
|
||||
h.mMainUserId.setTextColor(context.getResources().getColor(R.color.bg_gray));
|
||||
@ -735,10 +734,10 @@ public class KeyListFragment extends LoaderFragment
|
||||
} else {
|
||||
// this is a public key - show if it's verified
|
||||
if (isVerified) {
|
||||
KeyFormattingUtils.setStatusImage(getActivity(), h.mStatus, KeyFormattingUtils.STATE_VERIFIED);
|
||||
KeyFormattingUtils.setStatusImage(getActivity(), h.mStatus, State.VERIFIED);
|
||||
h.mStatus.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
KeyFormattingUtils.setStatusImage(getActivity(), h.mStatus, KeyFormattingUtils.STATE_UNVERIFIED);
|
||||
KeyFormattingUtils.setStatusImage(getActivity(), h.mStatus, State.UNVERIFIED);
|
||||
h.mStatus.setVisibility(View.VISIBLE);
|
||||
}
|
||||
h.mSlinger.setVisibility(View.GONE);
|
||||
|
@ -22,9 +22,13 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Color;
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcel;
|
||||
import android.support.v4.app.ListFragment;
|
||||
import android.util.TypedValue;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.AdapterView;
|
||||
@ -33,11 +37,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.util.FileHelper;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.Iterator;
|
||||
|
||||
public class LogDisplayFragment extends ListFragment implements OnItemClickListener {
|
||||
|
||||
@ -46,6 +58,12 @@ public class LogDisplayFragment extends ListFragment implements OnItemClickListe
|
||||
OperationResult mResult;
|
||||
|
||||
public static final String EXTRA_RESULT = "log";
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
setHasOptionsMenu(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(Bundle savedInstanceState) {
|
||||
@ -70,6 +88,183 @@ public class LogDisplayFragment extends ListFragment implements OnItemClickListe
|
||||
|
||||
getListView().setFastScrollEnabled(true);
|
||||
getListView().setDividerHeight(0);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(final Menu menu, final MenuInflater inflater) {
|
||||
inflater.inflate(R.menu.log_display, menu);
|
||||
|
||||
super.onCreateOptionsMenu(menu, inflater);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.menu_log_display_export_log:
|
||||
exportLog();
|
||||
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 (Iterator<LogEntryParcel> logIterator = opLog.iterator(); logIterator.hasNext(); ) {
|
||||
log += getPrintableLogEntry(logIterator.next(), 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;
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* trivial but necessary to implement the Parcelable protocol.
|
||||
*/
|
||||
public LogExportResult(Parcel source) {
|
||||
super(source);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -109,7 +304,7 @@ public class LogDisplayFragment extends ListFragment implements OnItemClickListe
|
||||
mSecondImg = secondImg;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if convertView.setPadding is redundant
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
LogEntryParcel entry = getItem(position);
|
||||
@ -132,7 +327,6 @@ public class LogDisplayFragment extends ListFragment implements OnItemClickListe
|
||||
if (entry instanceof SubLogEntryParcel) {
|
||||
ih.mSub.setVisibility(View.VISIBLE);
|
||||
convertView.setClickable(false);
|
||||
|
||||
convertView.setPadding((entry.mIndent) * dipFactor, 0, 0, 0);
|
||||
|
||||
OperationResult result = ((SubLogEntryParcel) entry).getSubResult();
|
||||
|
@ -46,6 +46,7 @@ import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.compatibility.DialogFragmentWorkaround;
|
||||
import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey;
|
||||
import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKeyRing;
|
||||
import org.sufficientlysecure.keychain.pgp.KeyRing;
|
||||
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
|
||||
import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
|
||||
import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing;
|
||||
@ -149,6 +150,7 @@ public class PassphraseDialogActivity extends FragmentActivity {
|
||||
|
||||
public static class PassphraseDialogFragment extends DialogFragment implements TextView.OnEditorActionListener {
|
||||
private EditText mPassphraseEditText;
|
||||
private TextView mPassphraseText;
|
||||
private View mInput, mProgress;
|
||||
|
||||
private CanonicalizedSecretKeyRing mSecretRing = null;
|
||||
@ -167,7 +169,7 @@ public class PassphraseDialogActivity extends FragmentActivity {
|
||||
// if the dialog is displayed from the application class, design is missing
|
||||
// hack to get holo design (which is not automatically applied due to activity's Theme.NoDisplay
|
||||
ContextThemeWrapper theme = new ContextThemeWrapper(activity,
|
||||
R.style.Theme_AppCompat_Light);
|
||||
R.style.Theme_AppCompat_Light_Dialog);
|
||||
|
||||
mSubKeyId = getArguments().getLong(EXTRA_SUBKEY_ID);
|
||||
mServiceIntent = getArguments().getParcelable(EXTRA_DATA);
|
||||
@ -176,13 +178,30 @@ public class PassphraseDialogActivity extends FragmentActivity {
|
||||
|
||||
alert.setTitle(R.string.title_unlock);
|
||||
|
||||
LayoutInflater inflater = LayoutInflater.from(theme);
|
||||
View view = inflater.inflate(R.layout.passphrase_dialog, null);
|
||||
alert.setView(view);
|
||||
|
||||
mPassphraseText = (TextView) view.findViewById(R.id.passphrase_text);
|
||||
mPassphraseEditText = (EditText) view.findViewById(R.id.passphrase_passphrase);
|
||||
mInput = view.findViewById(R.id.input);
|
||||
mProgress = view.findViewById(R.id.progress);
|
||||
|
||||
alert.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
|
||||
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int id) {
|
||||
dialog.cancel();
|
||||
}
|
||||
});
|
||||
|
||||
String userId;
|
||||
CanonicalizedSecretKey.SecretKeyType keyType = CanonicalizedSecretKey.SecretKeyType.PASSPHRASE;
|
||||
|
||||
String message;
|
||||
if (mSubKeyId == Constants.key.symmetric || mSubKeyId == Constants.key.none) {
|
||||
alert.setMessage(R.string.passphrase_for_symmetric_encryption);
|
||||
message = getString(R.string.passphrase_for_symmetric_encryption);
|
||||
} else {
|
||||
String message;
|
||||
try {
|
||||
ProviderHelper helper = new ProviderHelper(activity);
|
||||
mSecretRing = helper.getCanonicalizedSecretKeyRing(
|
||||
@ -191,7 +210,13 @@ public class PassphraseDialogActivity extends FragmentActivity {
|
||||
// above can't be statically verified to have been set in all cases because
|
||||
// the catch clause doesn't return.
|
||||
try {
|
||||
userId = mSecretRing.getPrimaryUserIdWithFallback();
|
||||
String mainUserId = mSecretRing.getPrimaryUserIdWithFallback();
|
||||
String[] mainUserIdSplit = KeyRing.splitUserId(mainUserId);
|
||||
if (mainUserIdSplit[0] != null) {
|
||||
userId = mainUserIdSplit[0];
|
||||
} else {
|
||||
userId = getString(R.string.user_id_no_name);
|
||||
}
|
||||
} catch (PgpKeyNotFoundException e) {
|
||||
userId = null;
|
||||
}
|
||||
@ -231,33 +256,16 @@ public class PassphraseDialogActivity extends FragmentActivity {
|
||||
alert.setCancelable(false);
|
||||
return alert.create();
|
||||
}
|
||||
|
||||
alert.setMessage(message);
|
||||
}
|
||||
|
||||
LayoutInflater inflater = LayoutInflater.from(theme);
|
||||
View view = inflater.inflate(R.layout.passphrase_dialog, null);
|
||||
alert.setView(view);
|
||||
|
||||
mPassphraseEditText = (EditText) view.findViewById(R.id.passphrase_passphrase);
|
||||
mInput = view.findViewById(R.id.input);
|
||||
mProgress = view.findViewById(R.id.progress);
|
||||
|
||||
alert.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
|
||||
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int id) {
|
||||
dialog.cancel();
|
||||
}
|
||||
});
|
||||
|
||||
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.GONE);
|
||||
mInput.setVisibility(View.INVISIBLE);
|
||||
mProgress.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
// Hack to open keyboard.
|
||||
@ -325,7 +333,7 @@ public class PassphraseDialogActivity extends FragmentActivity {
|
||||
return;
|
||||
}
|
||||
|
||||
mInput.setVisibility(View.GONE);
|
||||
mInput.setVisibility(View.INVISIBLE);
|
||||
mProgress.setVisibility(View.VISIBLE);
|
||||
positive.setEnabled(false);
|
||||
|
||||
@ -367,7 +375,7 @@ public class PassphraseDialogActivity extends FragmentActivity {
|
||||
mPassphraseEditText.setText("");
|
||||
mPassphraseEditText.setError(getString(R.string.wrong_passphrase));
|
||||
mInput.setVisibility(View.VISIBLE);
|
||||
mProgress.setVisibility(View.GONE);
|
||||
mProgress.setVisibility(View.INVISIBLE);
|
||||
positive.setEnabled(true);
|
||||
return;
|
||||
}
|
||||
|
@ -46,6 +46,7 @@ import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainDatabase.Tables;
|
||||
import org.sufficientlysecure.keychain.ui.adapter.SelectKeyCursorAdapter;
|
||||
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
|
||||
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils.State;
|
||||
|
||||
import java.util.Vector;
|
||||
|
||||
@ -136,7 +137,7 @@ public class SelectPublicKeyFragment extends ListFragmentWorkaround implements T
|
||||
mSearchView.setId(SEARCH_ID);
|
||||
mSearchView.setHint(R.string.menu_search);
|
||||
mSearchView.setCompoundDrawablesWithIntrinsicBounds(
|
||||
getResources().getDrawable(R.drawable.ic_action_search), null, null, null);
|
||||
getResources().getDrawable(R.drawable.ic_search_grey_24dp), null, null, null);
|
||||
|
||||
linearLayout.addView(mSearchView, new FrameLayout.LayoutParams(
|
||||
ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
|
||||
@ -376,15 +377,15 @@ public class SelectPublicKeyFragment extends ListFragmentWorkaround implements T
|
||||
// Check if key is viable for our purposes
|
||||
if (cursor.getInt(mIndexHasEncrypt) == 0) {
|
||||
h.statusIcon.setVisibility(View.VISIBLE);
|
||||
KeyFormattingUtils.setStatusImage(mContext, h.statusIcon, KeyFormattingUtils.STATE_UNAVAILABLE);
|
||||
KeyFormattingUtils.setStatusImage(mContext, h.statusIcon, State.UNAVAILABLE);
|
||||
enabled = false;
|
||||
} else if (cursor.getInt(mIndexIsVerified) != 0) {
|
||||
h.statusIcon.setVisibility(View.VISIBLE);
|
||||
KeyFormattingUtils.setStatusImage(mContext, h.statusIcon, KeyFormattingUtils.STATE_VERIFIED);
|
||||
KeyFormattingUtils.setStatusImage(mContext, h.statusIcon, State.VERIFIED);
|
||||
enabled = true;
|
||||
} else {
|
||||
h.statusIcon.setVisibility(View.VISIBLE);
|
||||
KeyFormattingUtils.setStatusImage(mContext, h.statusIcon, KeyFormattingUtils.STATE_UNVERIFIED);
|
||||
KeyFormattingUtils.setStatusImage(mContext, h.statusIcon, State.UNVERIFIED);
|
||||
enabled = true;
|
||||
}
|
||||
}
|
||||
|
@ -75,16 +75,15 @@ import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
|
||||
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;
|
||||
import org.sufficientlysecure.keychain.ui.util.Notify;
|
||||
import org.sufficientlysecure.keychain.ui.util.QrCodeUtils;
|
||||
import org.sufficientlysecure.keychain.ui.widget.AspectRatioImageView;
|
||||
import org.sufficientlysecure.keychain.util.ContactHelper;
|
||||
import org.sufficientlysecure.keychain.util.ExportHelper;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
import org.sufficientlysecure.keychain.util.Preferences;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
|
||||
public class ViewKeyActivity extends BaseActivity implements
|
||||
@ -106,7 +105,7 @@ public class ViewKeyActivity extends BaseActivity implements
|
||||
private ImageButton mActionEncryptText;
|
||||
private ImageButton mActionNfc;
|
||||
private FloatingActionButton mFab;
|
||||
private AspectRatioImageView mPhoto;
|
||||
private ImageView mPhoto;
|
||||
private ImageView mQrCode;
|
||||
private CardView mQrCodeLayout;
|
||||
|
||||
@ -122,6 +121,9 @@ public class ViewKeyActivity extends BaseActivity implements
|
||||
private boolean mIsSecret = false;
|
||||
private boolean mHasEncrypt = false;
|
||||
private boolean mIsVerified = false;
|
||||
private boolean mIsRevoked = false;
|
||||
private boolean mIsExpired = false;
|
||||
|
||||
private MenuItem mRefreshItem;
|
||||
private boolean mIsRefreshing;
|
||||
private Animation mRotate, mRotateSpin;
|
||||
@ -148,7 +150,7 @@ public class ViewKeyActivity extends BaseActivity implements
|
||||
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 = (AspectRatioImageView) findViewById(R.id.view_key_photo);
|
||||
mPhoto = (ImageView) findViewById(R.id.view_key_photo);
|
||||
mQrCode = (ImageView) findViewById(R.id.view_key_qr_code);
|
||||
mQrCodeLayout = (CardView) findViewById(R.id.view_key_qr_code_layout);
|
||||
|
||||
@ -174,7 +176,7 @@ public class ViewKeyActivity extends BaseActivity implements
|
||||
|
||||
}
|
||||
});
|
||||
mRotate = AnimationUtils.loadAnimation(this, R.anim.rotate);
|
||||
mRotate = AnimationUtils.loadAnimation(this, R.anim.rotate);
|
||||
mRotate.setRepeatCount(Animation.INFINITE);
|
||||
mRotate.setAnimationListener(new Animation.AnimationListener() {
|
||||
@Override
|
||||
@ -358,7 +360,7 @@ public class ViewKeyActivity extends BaseActivity implements
|
||||
addLinked.setVisible(mIsSecret);
|
||||
|
||||
MenuItem certifyFingerprint = menu.findItem(R.id.menu_key_view_certify_fingerprint);
|
||||
certifyFingerprint.setVisible(!mIsSecret && !mIsVerified);
|
||||
certifyFingerprint.setVisible(!mIsSecret && !mIsVerified && !mIsExpired && !mIsRevoked);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -409,12 +411,12 @@ public class ViewKeyActivity extends BaseActivity implements
|
||||
|
||||
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});
|
||||
|
||||
startCertifyIntent(intent);
|
||||
}
|
||||
|
||||
private void startCertifyIntent (Intent intent) {
|
||||
private void startCertifyIntent(Intent intent) {
|
||||
// Message is received after signing is done in KeychainIntentService
|
||||
KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler(this) {
|
||||
public void handleMessage(Message message) {
|
||||
@ -761,7 +763,7 @@ public class ViewKeyActivity extends BaseActivity implements
|
||||
KeychainContract.KeyRings.MASTER_KEY_ID,
|
||||
KeychainContract.KeyRings.USER_ID,
|
||||
KeychainContract.KeyRings.IS_REVOKED,
|
||||
KeychainContract.KeyRings.EXPIRY,
|
||||
KeychainContract.KeyRings.IS_EXPIRED,
|
||||
KeychainContract.KeyRings.VERIFIED,
|
||||
KeychainContract.KeyRings.HAS_ANY_SECRET,
|
||||
KeychainContract.KeyRings.FINGERPRINT,
|
||||
@ -771,7 +773,7 @@ public class ViewKeyActivity extends BaseActivity implements
|
||||
static final int INDEX_MASTER_KEY_ID = 1;
|
||||
static final int INDEX_USER_ID = 2;
|
||||
static final int INDEX_IS_REVOKED = 3;
|
||||
static final int INDEX_EXPIRY = 4;
|
||||
static final int INDEX_IS_EXPIRED = 4;
|
||||
static final int INDEX_VERIFIED = 5;
|
||||
static final int INDEX_HAS_ANY_SECRET = 6;
|
||||
static final int INDEX_FINGERPRINT = 7;
|
||||
@ -820,9 +822,8 @@ public class ViewKeyActivity extends BaseActivity implements
|
||||
|
||||
mIsSecret = data.getInt(INDEX_HAS_ANY_SECRET) != 0;
|
||||
mHasEncrypt = data.getInt(INDEX_HAS_ENCRYPT) != 0;
|
||||
boolean isRevoked = data.getInt(INDEX_IS_REVOKED) > 0;
|
||||
boolean isExpired = !data.isNull(INDEX_EXPIRY)
|
||||
&& new Date(data.getLong(INDEX_EXPIRY) * 1000).before(new Date());
|
||||
mIsRevoked = data.getInt(INDEX_IS_REVOKED) > 0;
|
||||
mIsExpired = data.getInt(INDEX_IS_EXPIRED) != 0;
|
||||
mIsVerified = data.getInt(INDEX_VERIFIED) > 0;
|
||||
|
||||
// if the refresh animation isn't playing
|
||||
@ -832,10 +833,10 @@ public class ViewKeyActivity extends BaseActivity implements
|
||||
// this is done at the end of the animation otherwise
|
||||
}
|
||||
|
||||
AsyncTask<String, Void, Bitmap> photoTask =
|
||||
new AsyncTask<String, Void, Bitmap>() {
|
||||
protected Bitmap doInBackground(String... fingerprint) {
|
||||
return ContactHelper.photoFromFingerprint(getContentResolver(), fingerprint[0]);
|
||||
AsyncTask<Long, Void, Bitmap> photoTask =
|
||||
new AsyncTask<Long, Void, Bitmap>() {
|
||||
protected Bitmap doInBackground(Long... mMasterKeyId) {
|
||||
return ContactHelper.loadPhotoByMasterKeyId(getContentResolver(), mMasterKeyId[0], true);
|
||||
}
|
||||
|
||||
protected void onPostExecute(Bitmap photo) {
|
||||
@ -846,11 +847,11 @@ public class ViewKeyActivity extends BaseActivity implements
|
||||
|
||||
// Note: order is important
|
||||
int color;
|
||||
if (isRevoked) {
|
||||
if (mIsRevoked) {
|
||||
mStatusText.setText(R.string.view_key_revoked);
|
||||
mStatusImage.setVisibility(View.VISIBLE);
|
||||
KeyFormattingUtils.setStatusImage(this, mStatusImage, mStatusText,
|
||||
KeyFormattingUtils.STATE_REVOKED, R.color.icons, true);
|
||||
State.REVOKED, R.color.icons, true);
|
||||
color = getResources().getColor(R.color.android_red_light);
|
||||
|
||||
mActionEncryptFile.setVisibility(View.GONE);
|
||||
@ -858,7 +859,7 @@ public class ViewKeyActivity extends BaseActivity implements
|
||||
mActionNfc.setVisibility(View.GONE);
|
||||
mFab.setVisibility(View.GONE);
|
||||
mQrCodeLayout.setVisibility(View.GONE);
|
||||
} else if (isExpired) {
|
||||
} else if (mIsExpired) {
|
||||
if (mIsSecret) {
|
||||
mStatusText.setText(R.string.view_key_expired_secret);
|
||||
} else {
|
||||
@ -866,7 +867,7 @@ public class ViewKeyActivity extends BaseActivity implements
|
||||
}
|
||||
mStatusImage.setVisibility(View.VISIBLE);
|
||||
KeyFormattingUtils.setStatusImage(this, mStatusImage, mStatusText,
|
||||
KeyFormattingUtils.STATE_EXPIRED, R.color.icons, true);
|
||||
State.EXPIRED, R.color.icons, true);
|
||||
color = getResources().getColor(R.color.android_red_light);
|
||||
|
||||
mActionEncryptFile.setVisibility(View.GONE);
|
||||
@ -879,10 +880,10 @@ public class ViewKeyActivity extends BaseActivity implements
|
||||
mStatusImage.setVisibility(View.GONE);
|
||||
color = getResources().getColor(R.color.primary);
|
||||
// reload qr code only if the fingerprint changed
|
||||
if ( !mFingerprint.equals(oldFingerprint)) {
|
||||
if (!mFingerprint.equals(oldFingerprint)) {
|
||||
loadQrCode(mFingerprint);
|
||||
}
|
||||
photoTask.execute(mFingerprint);
|
||||
photoTask.execute(mMasterKeyId);
|
||||
mQrCodeLayout.setVisibility(View.VISIBLE);
|
||||
|
||||
// and place leftOf qr code
|
||||
@ -926,16 +927,16 @@ public class ViewKeyActivity extends BaseActivity implements
|
||||
mStatusText.setText(R.string.view_key_verified);
|
||||
mStatusImage.setVisibility(View.VISIBLE);
|
||||
KeyFormattingUtils.setStatusImage(this, mStatusImage, mStatusText,
|
||||
KeyFormattingUtils.STATE_VERIFIED, R.color.icons, true);
|
||||
State.VERIFIED, R.color.icons, true);
|
||||
color = getResources().getColor(R.color.primary);
|
||||
photoTask.execute(mFingerprint);
|
||||
photoTask.execute(mMasterKeyId);
|
||||
|
||||
mFab.setVisibility(View.GONE);
|
||||
} else {
|
||||
mStatusText.setText(R.string.view_key_unverified);
|
||||
mStatusImage.setVisibility(View.VISIBLE);
|
||||
KeyFormattingUtils.setStatusImage(this, mStatusImage, mStatusText,
|
||||
KeyFormattingUtils.STATE_UNVERIFIED, R.color.icons, true);
|
||||
State.UNVERIFIED, R.color.icons, true);
|
||||
color = getResources().getColor(R.color.android_orange_light);
|
||||
|
||||
mFab.setVisibility(View.VISIBLE);
|
||||
@ -943,27 +944,21 @@ public class ViewKeyActivity extends BaseActivity implements
|
||||
}
|
||||
|
||||
if (mPreviousColor == 0 || mPreviousColor == color) {
|
||||
mToolbar.setBackgroundColor(color);
|
||||
mStatusBar.setBackgroundColor(color);
|
||||
mBigToolbar.setBackgroundColor(color);
|
||||
mPreviousColor = color;
|
||||
} else {
|
||||
ObjectAnimator colorFade1 =
|
||||
ObjectAnimator.ofObject(mToolbar, "backgroundColor",
|
||||
new ArgbEvaluator(), mPreviousColor, color);
|
||||
ObjectAnimator colorFade2 =
|
||||
ObjectAnimator.ofObject(mStatusBar, "backgroundColor",
|
||||
new ArgbEvaluator(), mPreviousColor, color);
|
||||
ObjectAnimator colorFade3 =
|
||||
ObjectAnimator colorFade2 =
|
||||
ObjectAnimator.ofObject(mBigToolbar, "backgroundColor",
|
||||
new ArgbEvaluator(), mPreviousColor, color);
|
||||
|
||||
colorFade1.setDuration(1200);
|
||||
colorFade2.setDuration(1200);
|
||||
colorFade3.setDuration(1200);
|
||||
colorFade1.start();
|
||||
colorFade2.start();
|
||||
colorFade3.start();
|
||||
mPreviousColor = color;
|
||||
}
|
||||
|
||||
|
@ -43,8 +43,6 @@ import org.sufficientlysecure.keychain.util.ContactHelper;
|
||||
import org.sufficientlysecure.keychain.util.ExportHelper;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
public class ViewKeyAdvActivity extends BaseActivity implements
|
||||
LoaderManager.LoaderCallbacks<Cursor> {
|
||||
|
||||
@ -159,7 +157,7 @@ public class ViewKeyAdvActivity extends BaseActivity implements
|
||||
KeychainContract.KeyRings.MASTER_KEY_ID,
|
||||
KeychainContract.KeyRings.USER_ID,
|
||||
KeychainContract.KeyRings.IS_REVOKED,
|
||||
KeychainContract.KeyRings.EXPIRY,
|
||||
KeychainContract.KeyRings.IS_EXPIRED,
|
||||
KeychainContract.KeyRings.VERIFIED,
|
||||
KeychainContract.KeyRings.HAS_ANY_SECRET
|
||||
};
|
||||
@ -167,7 +165,7 @@ public class ViewKeyAdvActivity extends BaseActivity implements
|
||||
static final int INDEX_MASTER_KEY_ID = 1;
|
||||
static final int INDEX_USER_ID = 2;
|
||||
static final int INDEX_IS_REVOKED = 3;
|
||||
static final int INDEX_EXPIRY = 4;
|
||||
static final int INDEX_IS_EXPIRED = 4;
|
||||
static final int INDEX_VERIFIED = 5;
|
||||
static final int INDEX_HAS_ANY_SECRET = 6;
|
||||
|
||||
@ -212,8 +210,7 @@ public class ViewKeyAdvActivity extends BaseActivity implements
|
||||
|
||||
boolean isSecret = data.getInt(INDEX_HAS_ANY_SECRET) != 0;
|
||||
boolean isRevoked = data.getInt(INDEX_IS_REVOKED) > 0;
|
||||
boolean isExpired = !data.isNull(INDEX_EXPIRY)
|
||||
&& new Date(data.getLong(INDEX_EXPIRY) * 1000).before(new Date());
|
||||
boolean isExpired = data.getInt(INDEX_IS_EXPIRED) != 0;
|
||||
boolean isVerified = data.getInt(INDEX_VERIFIED) > 0;
|
||||
|
||||
// Note: order is important
|
||||
|
@ -260,7 +260,7 @@ public class ViewKeyAdvShareFragment extends LoaderFragment implements
|
||||
static final String[] UNIFIED_PROJECTION = new String[]{
|
||||
KeyRings._ID, KeyRings.MASTER_KEY_ID, KeyRings.HAS_ANY_SECRET,
|
||||
KeyRings.USER_ID, KeyRings.FINGERPRINT,
|
||||
KeyRings.ALGORITHM, KeyRings.KEY_SIZE, KeyRings.CREATION, KeyRings.EXPIRY,
|
||||
KeyRings.ALGORITHM, KeyRings.KEY_SIZE, KeyRings.CREATION, KeyRings.IS_EXPIRED,
|
||||
|
||||
};
|
||||
static final int INDEX_UNIFIED_MASTER_KEY_ID = 1;
|
||||
@ -270,7 +270,7 @@ public class ViewKeyAdvShareFragment extends LoaderFragment implements
|
||||
static final int INDEX_UNIFIED_ALGORITHM = 5;
|
||||
static final int INDEX_UNIFIED_KEY_SIZE = 6;
|
||||
static final int INDEX_UNIFIED_CREATION = 7;
|
||||
static final int INDEX_UNIFIED_EXPIRY = 8;
|
||||
static final int INDEX_UNIFIED_ID_EXPIRED = 8;
|
||||
|
||||
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
|
||||
setContentShown(false);
|
||||
|
@ -114,12 +114,12 @@ public class ViewKeyAdvUserIdsFragment extends LoaderFragment implements
|
||||
|
||||
static final String[] UNIFIED_PROJECTION = new String[]{
|
||||
KeyRings._ID, KeyRings.MASTER_KEY_ID,
|
||||
KeyRings.HAS_ANY_SECRET, KeyRings.IS_REVOKED, KeyRings.EXPIRY, KeyRings.HAS_ENCRYPT
|
||||
KeyRings.HAS_ANY_SECRET, KeyRings.IS_REVOKED, KeyRings.IS_EXPIRED, KeyRings.HAS_ENCRYPT
|
||||
};
|
||||
static final int INDEX_UNIFIED_MASTER_KEY_ID = 1;
|
||||
static final int INDEX_UNIFIED_HAS_ANY_SECRET = 2;
|
||||
static final int INDEX_UNIFIED_IS_REVOKED = 3;
|
||||
static final int INDEX_UNIFIED_EXPIRY = 4;
|
||||
static final int INDEX_UNIFIED_IS_EXPIRED = 4;
|
||||
static final int INDEX_UNIFIED_HAS_ENCRYPT = 5;
|
||||
|
||||
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
|
||||
|
@ -115,12 +115,12 @@ public class ViewKeyTrustFragment extends LoaderFragment implements
|
||||
}
|
||||
|
||||
static final String[] TRUST_PROJECTION = new String[]{
|
||||
KeyRings._ID, KeyRings.FINGERPRINT, KeyRings.IS_REVOKED, KeyRings.EXPIRY,
|
||||
KeyRings._ID, KeyRings.FINGERPRINT, KeyRings.IS_REVOKED, KeyRings.IS_EXPIRED,
|
||||
KeyRings.HAS_ANY_SECRET, KeyRings.VERIFIED
|
||||
};
|
||||
static final int INDEX_TRUST_FINGERPRINT = 1;
|
||||
static final int INDEX_TRUST_IS_REVOKED = 2;
|
||||
static final int INDEX_TRUST_EXPIRY = 3;
|
||||
static final int INDEX_TRUST_IS_EXPIRED = 3;
|
||||
static final int INDEX_UNIFIED_HAS_ANY_SECRET = 4;
|
||||
static final int INDEX_VERIFIED = 5;
|
||||
|
||||
@ -169,8 +169,7 @@ public class ViewKeyTrustFragment extends LoaderFragment implements
|
||||
|
||||
nothingSpecial = false;
|
||||
} else {
|
||||
Date expiryDate = new Date(data.getLong(INDEX_TRUST_EXPIRY) * 1000);
|
||||
if (!data.isNull(INDEX_TRUST_EXPIRY) && expiryDate.before(new Date())) {
|
||||
if (data.getInt(INDEX_TRUST_IS_EXPIRED) != 0) {
|
||||
|
||||
// if expired, don’t trust it!
|
||||
message.append(getString(R.string.key_trust_expired)).
|
||||
|
@ -37,6 +37,7 @@ import org.sufficientlysecure.keychain.pgp.KeyRing;
|
||||
import org.sufficientlysecure.keychain.ui.util.FormattingUtils;
|
||||
import org.sufficientlysecure.keychain.ui.util.Highlighter;
|
||||
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
|
||||
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils.State;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
@ -175,9 +176,9 @@ public class ImportKeysAdapter extends ArrayAdapter<ImportKeysListEntry> {
|
||||
}
|
||||
|
||||
if (entry.isRevoked()) {
|
||||
KeyFormattingUtils.setStatusImage(getContext(), holder.status, null, KeyFormattingUtils.STATE_REVOKED, R.color.bg_gray);
|
||||
KeyFormattingUtils.setStatusImage(getContext(), holder.status, null, State.REVOKED, R.color.bg_gray);
|
||||
} else if (entry.isExpired()) {
|
||||
KeyFormattingUtils.setStatusImage(getContext(), holder.status, null, KeyFormattingUtils.STATE_EXPIRED, R.color.bg_gray);
|
||||
KeyFormattingUtils.setStatusImage(getContext(), holder.status, null, State.EXPIRED, R.color.bg_gray);
|
||||
}
|
||||
|
||||
if (entry.isRevoked() || entry.isExpired()) {
|
||||
|
@ -39,9 +39,9 @@ import org.sufficientlysecure.keychain.pgp.linked.RawLinkedIdentity;
|
||||
import org.sufficientlysecure.keychain.pgp.linked.resources.DnsResource;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.Certs;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.UserPackets;
|
||||
import org.sufficientlysecure.keychain.ui.ViewKeyFragment;
|
||||
import org.sufficientlysecure.keychain.ui.linked.LinkedIdViewFragment;
|
||||
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
|
||||
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils.State;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.WeakHashMap;
|
||||
@ -66,15 +66,15 @@ public class LinkedIdsAdapter extends UserAttributesAdapter {
|
||||
switch (isVerified) {
|
||||
case Certs.VERIFIED_SECRET:
|
||||
KeyFormattingUtils.setStatusImage(mContext, holder.vVerified,
|
||||
null, KeyFormattingUtils.STATE_VERIFIED, KeyFormattingUtils.DEFAULT_COLOR);
|
||||
null, State.VERIFIED, KeyFormattingUtils.DEFAULT_COLOR);
|
||||
break;
|
||||
case Certs.VERIFIED_SELF:
|
||||
KeyFormattingUtils.setStatusImage(mContext, holder.vVerified,
|
||||
null, KeyFormattingUtils.STATE_UNVERIFIED, KeyFormattingUtils.DEFAULT_COLOR);
|
||||
null, State.UNVERIFIED, KeyFormattingUtils.DEFAULT_COLOR);
|
||||
break;
|
||||
default:
|
||||
KeyFormattingUtils.setStatusImage(mContext, holder.vVerified,
|
||||
null, KeyFormattingUtils.STATE_INVALID, KeyFormattingUtils.DEFAULT_COLOR);
|
||||
null, State.INVALID, KeyFormattingUtils.DEFAULT_COLOR);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -33,6 +33,7 @@ import org.sufficientlysecure.keychain.pgp.KeyRing;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
|
||||
import org.sufficientlysecure.keychain.ui.util.Highlighter;
|
||||
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
|
||||
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils.State;
|
||||
|
||||
|
||||
/**
|
||||
@ -133,11 +134,11 @@ abstract public class SelectKeyCursorAdapter extends CursorAdapter {
|
||||
boolean enabled;
|
||||
if (cursor.getInt(mIndexIsRevoked) != 0) {
|
||||
h.statusIcon.setVisibility(View.VISIBLE);
|
||||
KeyFormattingUtils.setStatusImage(mContext, h.statusIcon, null, KeyFormattingUtils.STATE_REVOKED, R.color.bg_gray);
|
||||
KeyFormattingUtils.setStatusImage(mContext, h.statusIcon, null, State.REVOKED, R.color.bg_gray);
|
||||
enabled = false;
|
||||
} else if (cursor.getInt(mIndexIsExpiry) != 0) {
|
||||
h.statusIcon.setVisibility(View.VISIBLE);
|
||||
KeyFormattingUtils.setStatusImage(mContext, h.statusIcon, null, KeyFormattingUtils.STATE_EXPIRED, R.color.bg_gray);
|
||||
KeyFormattingUtils.setStatusImage(mContext, h.statusIcon, null, State.EXPIRED, R.color.bg_gray);
|
||||
enabled = false;
|
||||
} else {
|
||||
h.statusIcon.setVisibility(View.GONE);
|
||||
|
@ -272,12 +272,12 @@ public class SubkeysAdapter extends CursorAdapter {
|
||||
PorterDuff.Mode.SRC_IN);
|
||||
|
||||
if (isRevoked) {
|
||||
vStatus.setImageResource(R.drawable.status_signature_revoked_cutout_24px);
|
||||
vStatus.setImageResource(R.drawable.status_signature_revoked_cutout_24dp);
|
||||
vStatus.setColorFilter(
|
||||
mContext.getResources().getColor(R.color.bg_gray),
|
||||
PorterDuff.Mode.SRC_IN);
|
||||
} else if (isExpired) {
|
||||
vStatus.setImageResource(R.drawable.status_signature_expired_cutout_24px);
|
||||
vStatus.setImageResource(R.drawable.status_signature_expired_cutout_24dp);
|
||||
vStatus.setColorFilter(
|
||||
mContext.getResources().getColor(R.color.bg_gray),
|
||||
PorterDuff.Mode.SRC_IN);
|
||||
|
@ -36,6 +36,7 @@ import org.sufficientlysecure.keychain.provider.KeychainContract.Certs;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.UserPackets;
|
||||
import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
|
||||
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
|
||||
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils.State;
|
||||
|
||||
public class UserIdsAdapter extends UserAttributesAdapter {
|
||||
protected LayoutInflater mInflater;
|
||||
@ -127,7 +128,7 @@ public class UserIdsAdapter extends UserAttributesAdapter {
|
||||
|
||||
if (isRevoked) {
|
||||
// set revocation icon (can this even be primary?)
|
||||
KeyFormattingUtils.setStatusImage(mContext, vVerified, null, KeyFormattingUtils.STATE_REVOKED, R.color.bg_gray);
|
||||
KeyFormattingUtils.setStatusImage(mContext, vVerified, null, State.REVOKED, R.color.bg_gray);
|
||||
|
||||
// disable revoked user ids
|
||||
vName.setEnabled(false);
|
||||
@ -149,13 +150,13 @@ public class UserIdsAdapter extends UserAttributesAdapter {
|
||||
int isVerified = cursor.getInt(INDEX_VERIFIED);
|
||||
switch (isVerified) {
|
||||
case Certs.VERIFIED_SECRET:
|
||||
KeyFormattingUtils.setStatusImage(mContext, vVerified, null, KeyFormattingUtils.STATE_VERIFIED, KeyFormattingUtils.DEFAULT_COLOR);
|
||||
KeyFormattingUtils.setStatusImage(mContext, vVerified, null, State.VERIFIED, KeyFormattingUtils.DEFAULT_COLOR);
|
||||
break;
|
||||
case Certs.VERIFIED_SELF:
|
||||
KeyFormattingUtils.setStatusImage(mContext, vVerified, null, KeyFormattingUtils.STATE_UNVERIFIED, KeyFormattingUtils.DEFAULT_COLOR);
|
||||
KeyFormattingUtils.setStatusImage(mContext, vVerified, null, State.UNVERIFIED, KeyFormattingUtils.DEFAULT_COLOR);
|
||||
break;
|
||||
default:
|
||||
KeyFormattingUtils.setStatusImage(mContext, vVerified, null, KeyFormattingUtils.STATE_INVALID, KeyFormattingUtils.DEFAULT_COLOR);
|
||||
KeyFormattingUtils.setStatusImage(mContext, vVerified, null, State.INVALID, KeyFormattingUtils.DEFAULT_COLOR);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,6 @@ import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
@ -73,10 +72,8 @@ public class UserIdsAddedAdapter extends ArrayAdapter<String> {
|
||||
holder.vDelete.setVisibility(View.VISIBLE); // always visible
|
||||
|
||||
// not used:
|
||||
CheckBox checkBox = (CheckBox) convertView.findViewById(R.id.user_id_item_check_box);
|
||||
View certifiedLayout = convertView.findViewById(R.id.user_id_item_certified_layout);
|
||||
ImageView editImage = (ImageView) convertView.findViewById(R.id.user_id_item_edit_image);
|
||||
checkBox.setVisibility(View.GONE);
|
||||
certifiedLayout.setVisibility(View.GONE);
|
||||
editImage.setVisibility(View.GONE);
|
||||
|
||||
|
@ -137,12 +137,10 @@ public class AddSubkeyDialogFragment extends DialogFragment {
|
||||
}
|
||||
});
|
||||
|
||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB) {
|
||||
// date picker works based on default time zone
|
||||
Calendar minDateCal = Calendar.getInstance(TimeZone.getDefault());
|
||||
minDateCal.add(Calendar.DAY_OF_YEAR, 1); // at least one day after creation (today)
|
||||
mExpiryDatePicker.setMinDate(minDateCal.getTime().getTime());
|
||||
}
|
||||
// date picker works based on default time zone
|
||||
Calendar minDateCal = Calendar.getInstance(TimeZone.getDefault());
|
||||
minDateCal.add(Calendar.DAY_OF_YEAR, 1); // at least one day after creation (today)
|
||||
mExpiryDatePicker.setMinDate(minDateCal.getTime().getTime());
|
||||
|
||||
{
|
||||
ArrayList<Choice<Algorithm>> choices = new ArrayList<>();
|
||||
@ -283,7 +281,7 @@ public class AddSubkeyDialogFragment extends DialogFragment {
|
||||
// For EC keys, add a curve
|
||||
if (algorithm == Algorithm.ECDH || algorithm == Algorithm.ECDSA) {
|
||||
curve = ((Choice<Curve>) mCurveSpinner.getSelectedItem()).getId();
|
||||
// Otherwise, get a keysize
|
||||
// Otherwise, get a keysize
|
||||
} else {
|
||||
keySize = getProperKeyLength(algorithm, getSelectedKeyLength());
|
||||
}
|
||||
|
@ -1,3 +1,20 @@
|
||||
/*
|
||||
* 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.dialog;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
|
@ -62,12 +62,9 @@ public class DeleteFileDialogFragment extends DialogFragment {
|
||||
|
||||
CustomAlertDialogBuilder alert = new CustomAlertDialogBuilder(activity);
|
||||
|
||||
|
||||
alert.setIcon(R.drawable.ic_dialog_alert_holo_light);
|
||||
alert.setTitle(R.string.warning);
|
||||
alert.setMessage(this.getString(R.string.file_delete_confirmation, deleteFilename));
|
||||
|
||||
alert.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
|
||||
alert.setPositiveButton(R.string.btn_delete, new DialogInterface.OnClickListener() {
|
||||
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int id) {
|
||||
|
@ -83,8 +83,6 @@ public class DeleteKeyDialogFragment extends DialogFragment {
|
||||
|
||||
mMainMessage = (TextView) mInflateView.findViewById(R.id.mainMessage);
|
||||
|
||||
builder.setTitle(R.string.warning);
|
||||
|
||||
final boolean hasSecret;
|
||||
|
||||
// If only a single key has been selected
|
||||
@ -110,12 +108,14 @@ public class DeleteKeyDialogFragment extends DialogFragment {
|
||||
}
|
||||
hasSecret = ((Long) data.get(KeyRings.HAS_ANY_SECRET)) == 1;
|
||||
|
||||
// Set message depending on which key it is.
|
||||
mMainMessage.setText(getString(
|
||||
hasSecret ? R.string.secret_key_deletion_confirmation
|
||||
: R.string.public_key_deletetion_confirmation,
|
||||
name
|
||||
));
|
||||
if (hasSecret) {
|
||||
// show title only for secret key deletions,
|
||||
// see http://www.google.com/design/spec/components/dialogs.html#dialogs-behavior
|
||||
builder.setTitle(getString(R.string.title_delete_secret_key, name));
|
||||
mMainMessage.setText(getString(R.string.secret_key_deletion_confirmation, name));
|
||||
} else {
|
||||
mMainMessage.setText(getString(R.string.public_key_deletetion_confirmation, name));
|
||||
}
|
||||
} catch (ProviderHelper.NotFoundException e) {
|
||||
dismiss();
|
||||
return null;
|
||||
@ -125,7 +125,6 @@ public class DeleteKeyDialogFragment extends DialogFragment {
|
||||
hasSecret = false;
|
||||
}
|
||||
|
||||
builder.setIcon(R.drawable.ic_dialog_alert_holo_light);
|
||||
builder.setPositiveButton(R.string.btn_delete, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
|
@ -25,11 +25,14 @@ import android.os.Message;
|
||||
import android.os.Messenger;
|
||||
import android.os.RemoteException;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
import android.text.format.DateFormat;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.CompoundButton;
|
||||
import android.widget.DatePicker;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
@ -97,62 +100,63 @@ public class EditSubkeyExpiryDialogFragment extends DialogFragment {
|
||||
|
||||
final CheckBox noExpiry = (CheckBox) view.findViewById(R.id.edit_subkey_expiry_no_expiry);
|
||||
final DatePicker datePicker = (DatePicker) view.findViewById(R.id.edit_subkey_expiry_date_picker);
|
||||
final TextView currentExpiry = (TextView) view.findViewById(R.id.edit_subkey_expiry_current_expiry);
|
||||
final LinearLayout expiryLayout = (LinearLayout) view.findViewById(R.id.edit_subkey_expiry_layout);
|
||||
|
||||
noExpiry.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
||||
@Override
|
||||
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
||||
if (isChecked) {
|
||||
datePicker.setVisibility(View.GONE);
|
||||
expiryLayout.setVisibility(View.GONE);
|
||||
} else {
|
||||
datePicker.setVisibility(View.VISIBLE);
|
||||
expiryLayout.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// init date picker with default selected date
|
||||
if (expiry == 0L) {
|
||||
noExpiry.setChecked(true);
|
||||
datePicker.setVisibility(View.GONE);
|
||||
expiryLayout.setVisibility(View.GONE);
|
||||
|
||||
Calendar todayCal = Calendar.getInstance(TimeZone.getDefault());
|
||||
if (creationCal.after(todayCal)) {
|
||||
// Note: This is just for the rare cases where creation is _after_ today
|
||||
|
||||
// set it to creation date +1 day (don't set it to creationCal, it would break crash
|
||||
// datePicker.setMinDate() execution with IllegalArgumentException
|
||||
Calendar creationCalPlusOne = (Calendar) creationCal.clone();
|
||||
creationCalPlusOne.add(Calendar.DAY_OF_YEAR, 1);
|
||||
datePicker.init(
|
||||
creationCalPlusOne.get(Calendar.YEAR),
|
||||
creationCalPlusOne.get(Calendar.MONTH),
|
||||
creationCalPlusOne.get(Calendar.DAY_OF_MONTH),
|
||||
null
|
||||
);
|
||||
|
||||
} else {
|
||||
// normally, just init with today
|
||||
datePicker.init(
|
||||
todayCal.get(Calendar.YEAR),
|
||||
todayCal.get(Calendar.MONTH),
|
||||
todayCal.get(Calendar.DAY_OF_MONTH),
|
||||
null
|
||||
);
|
||||
}
|
||||
currentExpiry.setText(R.string.btn_no_date);
|
||||
} else {
|
||||
noExpiry.setChecked(false);
|
||||
datePicker.setVisibility(View.VISIBLE);
|
||||
expiryLayout.setVisibility(View.VISIBLE);
|
||||
|
||||
// set date picker to current expiry
|
||||
datePicker.init(
|
||||
expiryCal.get(Calendar.YEAR),
|
||||
expiryCal.get(Calendar.MONTH),
|
||||
expiryCal.get(Calendar.DAY_OF_MONTH),
|
||||
null
|
||||
);
|
||||
// convert from UTC to time zone of device
|
||||
Calendar expiryCalTimeZone = (Calendar) expiryCal.clone();
|
||||
expiryCalTimeZone.setTimeZone(TimeZone.getDefault());
|
||||
currentExpiry.setText(DateFormat.getDateFormat(
|
||||
getActivity()).format(expiryCalTimeZone.getTime()));
|
||||
}
|
||||
|
||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB) {
|
||||
datePicker.setMinDate(creationCal.getTime().getTime());
|
||||
// date picker works based on default time zone
|
||||
Calendar todayCal = Calendar.getInstance(TimeZone.getDefault());
|
||||
if (creationCal.after(todayCal)) {
|
||||
// NOTE: This is just for the rare cases where creation is _after_ today
|
||||
// Min Date: Creation date + 1 day
|
||||
|
||||
Calendar creationCalPlusOne = (Calendar) creationCal.clone();
|
||||
creationCalPlusOne.add(Calendar.DAY_OF_YEAR, 1);
|
||||
datePicker.setMinDate(creationCalPlusOne.getTime().getTime());
|
||||
datePicker.init(
|
||||
creationCalPlusOne.get(Calendar.YEAR),
|
||||
creationCalPlusOne.get(Calendar.MONTH),
|
||||
creationCalPlusOne.get(Calendar.DAY_OF_MONTH),
|
||||
null
|
||||
);
|
||||
} else {
|
||||
// Min Date: today + 1 day
|
||||
|
||||
// at least one day after creation (today)
|
||||
todayCal.add(Calendar.DAY_OF_YEAR, 1);
|
||||
datePicker.setMinDate(todayCal.getTime().getTime());
|
||||
datePicker.init(
|
||||
todayCal.get(Calendar.YEAR),
|
||||
todayCal.get(Calendar.MONTH),
|
||||
todayCal.get(Calendar.DAY_OF_MONTH),
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
alert.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
|
||||
|