aboutsummaryrefslogtreecommitdiffstats
path: root/OpenKeychain/src/main/java
diff options
context:
space:
mode:
Diffstat (limited to 'OpenKeychain/src/main/java')
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java3
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java30
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java69
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java19
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/HelpActivity.java19
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysProxyActivity.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java8
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java58
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectPublicKeyFragment.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java46
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvActivity.java9
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvShareFragment.java4
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvUserIdsFragment.java4
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyFragment.java32
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyTrustFragment.java7
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java4
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserAttributesAdapter.java49
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAdapter.java131
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAddedAdapter.java3
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsSelectableAdapter.java88
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddSubkeyDialogFragment.java12
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/CustomAlertDialogBuilder.java17
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteFileDialogFragment.java5
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteKeyDialogFragment.java17
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditSubkeyExpiryDialogFragment.java78
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/SetPassphraseDialogFragment.java1
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/KeyFormattingUtils.java28
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionView.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ContactHelper.java393
30 files changed, 643 insertions, 499 deletions
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java
index 67fa30a44..2d3ee6188 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java
@@ -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";
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java
index 01f6735ea..a4dc12a37 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java
@@ -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
-
- //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
+ // 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) {
+ }
}
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java
index aef61075f..54cd9b1b4 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java
@@ -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() {
@@ -746,9 +801,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> {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java
index 1a251eb79..da0394573 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java
@@ -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);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java
index 8723c7255..846acb9cb 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java
@@ -176,7 +176,7 @@ public abstract class DecryptFragment extends Fragment {
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) {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/HelpActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/HelpActivity.java
index 2eb35351e..cd6cdf4d6 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/HelpActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/HelpActivity.java
@@ -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,
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysProxyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysProxyActivity.java
index 94eaa8171..948da94d8 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysProxyActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysProxyActivity.java
@@ -149,7 +149,7 @@ public class ImportKeysProxyActivity extends FragmentActivity {
private void processScannedContent(Uri uri) {
- Log.d(Constants.TAG, "scanned: " + uri.toString());
+ Log.d(Constants.TAG, "scanned: " + uri);
String fingerprint = null;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java
index b56da463a..2e571a7db 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java
@@ -77,7 +77,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 +267,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 +275,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,8 +707,7 @@ 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;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java
index d5ca08936..bb669f6b8 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java
@@ -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;
}
@@ -228,33 +253,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.
@@ -322,7 +330,7 @@ public class PassphraseDialogActivity extends FragmentActivity {
return;
}
- mInput.setVisibility(View.GONE);
+ mInput.setVisibility(View.INVISIBLE);
mProgress.setVisibility(View.VISIBLE);
positive.setEnabled(false);
@@ -364,7 +372,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;
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectPublicKeyFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectPublicKeyFragment.java
index afec3bf06..6f19d1de9 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectPublicKeyFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectPublicKeyFragment.java
@@ -136,7 +136,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));
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java
index 3bc207419..f90326a7d 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java
@@ -20,6 +20,7 @@ package org.sufficientlysecure.keychain.ui;
import android.animation.ArgbEvaluator;
import android.animation.ObjectAnimator;
+import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.ActivityOptions;
@@ -75,14 +76,12 @@ import org.sufficientlysecure.keychain.ui.util.FormattingUtils;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.ui.util.Notify;
import org.sufficientlysecure.keychain.ui.util.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
@@ -104,7 +103,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;
@@ -127,6 +126,7 @@ public class ViewKeyActivity extends BaseActivity implements
private String mFingerprint;
private long mMasterKeyId;
+ @SuppressLint("InflateParams")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -145,7 +145,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);
@@ -210,7 +210,7 @@ public class ViewKeyActivity extends BaseActivity implements
}
}
- Log.i(Constants.TAG, "mDataUri: " + mDataUri.toString());
+ Log.i(Constants.TAG, "mDataUri: " + mDataUri);
mActionEncryptFile.setOnClickListener(new View.OnClickListener() {
@Override
@@ -624,8 +624,6 @@ public class ViewKeyActivity extends BaseActivity implements
/**
* Load QR Code asynchronously and with a fade in animation
- *
- * @param fingerprint
*/
private void loadQrCode(final String fingerprint) {
AsyncTask<Void, Void, Bitmap> loadTask =
@@ -750,7 +748,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,
@@ -760,7 +758,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;
@@ -803,14 +801,14 @@ public class ViewKeyActivity extends BaseActivity implements
mName.setText(R.string.user_id_no_name);
}
+ String oldFingerprint = mFingerprint;
mMasterKeyId = data.getLong(INDEX_MASTER_KEY_ID);
mFingerprint = KeyFormattingUtils.convertFingerprintToHex(data.getBlob(INDEX_FINGERPRINT));
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());
+ boolean isExpired = data.getInt(INDEX_IS_EXPIRED) != 0;
mIsVerified = data.getInt(INDEX_VERIFIED) > 0;
// if the refresh animation isn't playing
@@ -820,10 +818,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) {
@@ -866,8 +864,11 @@ public class ViewKeyActivity extends BaseActivity implements
mStatusText.setText(R.string.view_key_my_key);
mStatusImage.setVisibility(View.GONE);
color = getResources().getColor(R.color.primary);
- photoTask.execute(mFingerprint);
- loadQrCode(mFingerprint);
+ // reload qr code only if the fingerprint changed
+ if ( !mFingerprint.equals(oldFingerprint)) {
+ loadQrCode(mFingerprint);
+ }
+ photoTask.execute(mMasterKeyId);
mQrCodeLayout.setVisibility(View.VISIBLE);
// and place leftOf qr code
@@ -913,7 +914,7 @@ public class ViewKeyActivity extends BaseActivity implements
KeyFormattingUtils.setStatusImage(this, mStatusImage, mStatusText,
KeyFormattingUtils.STATE_VERIFIED, R.color.icons, true);
color = getResources().getColor(R.color.primary);
- photoTask.execute(mFingerprint);
+ photoTask.execute(mMasterKeyId);
mFab.setVisibility(View.GONE);
} else {
@@ -928,30 +929,25 @@ 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;
}
+ //noinspection deprecation
mStatusImage.setAlpha(80);
break;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvActivity.java
index 9d79b377c..9390e8a69 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvActivity.java
@@ -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
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvShareFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvShareFragment.java
index 8d0a2dd1d..95a6faea9 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvShareFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvShareFragment.java
@@ -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);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvUserIdsFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvUserIdsFragment.java
index c4e6639a8..7bfebaf62 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvUserIdsFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvUserIdsFragment.java
@@ -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) {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyFragment.java
index 453bfd499..628970b27 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyFragment.java
@@ -34,14 +34,10 @@ import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.compatibility.DialogFragmentWorkaround;
import org.sufficientlysecure.keychain.provider.KeychainContract;
-import org.sufficientlysecure.keychain.provider.KeychainContract.UserPackets;
-import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.ui.adapter.UserIdsAdapter;
import org.sufficientlysecure.keychain.ui.dialog.UserIdInfoDialogFragment;
import org.sufficientlysecure.keychain.util.Log;
-import java.util.Date;
-
public class ViewKeyFragment extends LoaderFragment implements
LoaderManager.LoaderCallbacks<Cursor> {
@@ -58,8 +54,6 @@ public class ViewKeyFragment extends LoaderFragment implements
private Uri mDataUri;
- ProviderHelper mProviderHelper;
-
/**
* Creates new instance of this fragment
*/
@@ -78,8 +72,6 @@ public class ViewKeyFragment extends LoaderFragment implements
View root = super.onCreateView(inflater, superContainer, savedInstanceState);
View view = inflater.inflate(R.layout.view_key_fragment, getContainer());
- mProviderHelper = new ProviderHelper(getActivity());
-
mUserIds = (ListView) view.findViewById(R.id.view_key_user_ids);
mUserIds.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@@ -129,7 +121,7 @@ public class ViewKeyFragment extends LoaderFragment 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,
@@ -139,7 +131,7 @@ public class ViewKeyFragment extends LoaderFragment 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;
@@ -148,16 +140,14 @@ public class ViewKeyFragment extends LoaderFragment implements
private void loadData(Uri dataUri) {
mDataUri = dataUri;
- Log.i(Constants.TAG, "mDataUri: " + mDataUri.toString());
+ Log.i(Constants.TAG, "mDataUri: " + mDataUri);
// Prepare the loaders. Either re-connect with an existing ones,
// or start new ones.
+ // TODO Is this loader the same as the one in the activity?
getLoaderManager().initLoader(LOADER_ID_UNIFIED, null, this);
}
- // don't show revoked user ids here, irrelevant for average users
- public static final String USER_IDS_WHERE = UserPackets.IS_REVOKED + " = 0";
-
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
setContentShown(false);
@@ -166,11 +156,8 @@ public class ViewKeyFragment extends LoaderFragment implements
Uri baseUri = KeychainContract.KeyRings.buildUnifiedKeyRingUri(mDataUri);
return new CursorLoader(getActivity(), baseUri, UNIFIED_PROJECTION, null, null, null);
}
- case LOADER_ID_USER_IDS: {
- Uri baseUri = UserPackets.buildUserIdsUri(mDataUri);
- return new CursorLoader(getActivity(), baseUri,
- UserIdsAdapter.USER_IDS_PROJECTION, USER_IDS_WHERE, null, null);
- }
+ case LOADER_ID_USER_IDS:
+ return UserIdsAdapter.createLoader(getActivity(), mDataUri);
default:
return null;
@@ -192,14 +179,9 @@ public class ViewKeyFragment extends LoaderFragment implements
if (data.moveToFirst()) {
mIsSecret = data.getInt(INDEX_HAS_ANY_SECRET) != 0;
- boolean hasEncrypt = 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());
- boolean isVerified = data.getInt(INDEX_VERIFIED) > 0;
// load user ids after we know if it's a secret key
- mUserIdsAdapter = new UserIdsAdapter(getActivity(), null, 0, false, !mIsSecret, null);
+ mUserIdsAdapter = new UserIdsAdapter(getActivity(), null, 0, !mIsSecret, null);
mUserIds.setAdapter(mUserIdsAdapter);
getLoaderManager().initLoader(LOADER_ID_USER_IDS, null, this);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyTrustFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyTrustFragment.java
index 25edc7a02..d22f01a48 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyTrustFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyTrustFragment.java
@@ -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)).
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java
index ff5fbb49a..096dea51f 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java
@@ -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);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserAttributesAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserAttributesAdapter.java
new file mode 100644
index 000000000..457083770
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserAttributesAdapter.java
@@ -0,0 +1,49 @@
+package org.sufficientlysecure.keychain.ui.adapter;
+
+import android.content.Context;
+import android.database.Cursor;
+import android.support.v4.widget.CursorAdapter;
+import android.view.View;
+
+import org.sufficientlysecure.keychain.provider.KeychainContract.UserPackets;
+
+public abstract class UserAttributesAdapter extends CursorAdapter {
+ public static final String[] USER_IDS_PROJECTION = new String[]{
+ UserPackets._ID,
+ UserPackets.TYPE,
+ UserPackets.USER_ID,
+ UserPackets.RANK,
+ UserPackets.VERIFIED,
+ UserPackets.IS_PRIMARY,
+ UserPackets.IS_REVOKED
+ };
+ protected static final int INDEX_ID = 0;
+ protected static final int INDEX_TYPE = 1;
+ protected static final int INDEX_USER_ID = 2;
+ protected static final int INDEX_RANK = 3;
+ protected static final int INDEX_VERIFIED = 4;
+ protected static final int INDEX_IS_PRIMARY = 5;
+ protected static final int INDEX_IS_REVOKED = 6;
+
+ public UserAttributesAdapter(Context context, Cursor c, int flags) {
+ super(context, c, flags);
+ }
+
+ @Override
+ public abstract void bindView(View view, Context context, Cursor cursor);
+
+ public String getUserId(int position) {
+ mCursor.moveToPosition(position);
+ return mCursor.getString(INDEX_USER_ID);
+ }
+
+ public boolean getIsRevoked(int position) {
+ mCursor.moveToPosition(position);
+ return mCursor.getInt(INDEX_IS_REVOKED) > 0;
+ }
+
+ public int getIsVerified(int position) {
+ mCursor.moveToPosition(position);
+ return mCursor.getInt(INDEX_VERIFIED);
+ }
+}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAdapter.java
index 8c0ab9165..6a4f61f4b 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAdapter.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAdapter.java
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
+ * Copyright (C) 2014-2015 Dominik Schürmann <dominik@dominikschuermann.de>
+ * Copyright (C) 2015 Vincent Breitmoser <v.breitmoser@mugenguild.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -17,16 +18,15 @@
package org.sufficientlysecure.keychain.ui.adapter;
+import android.app.Activity;
import android.content.Context;
import android.database.Cursor;
import android.graphics.Typeface;
-import android.support.v4.widget.CursorAdapter;
+import android.net.Uri;
+import android.support.v4.content.CursorLoader;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.AdapterView;
-import android.widget.CheckBox;
-import android.widget.CompoundButton;
import android.widget.ImageView;
import android.widget.TextView;
@@ -37,73 +37,26 @@ import org.sufficientlysecure.keychain.provider.KeychainContract.UserPackets;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
-import java.util.ArrayList;
-
-public class UserIdsAdapter extends CursorAdapter implements AdapterView.OnItemClickListener {
- private LayoutInflater mInflater;
- private final ArrayList<Boolean> mCheckStates;
+public class UserIdsAdapter extends UserAttributesAdapter {
+ protected LayoutInflater mInflater;
private SaveKeyringParcel mSaveKeyringParcel;
private boolean mShowStatusImages;
- public static final String[] USER_IDS_PROJECTION = new String[]{
- UserPackets._ID,
- UserPackets.USER_ID,
- UserPackets.RANK,
- UserPackets.VERIFIED,
- UserPackets.IS_PRIMARY,
- UserPackets.IS_REVOKED
- };
- private static final int INDEX_ID = 0;
- private static final int INDEX_USER_ID = 1;
- private static final int INDEX_RANK = 2;
- private static final int INDEX_VERIFIED = 3;
- private static final int INDEX_IS_PRIMARY = 4;
- private static final int INDEX_IS_REVOKED = 5;
-
- public UserIdsAdapter(Context context, Cursor c, int flags, boolean showCheckBoxes,
+ public UserIdsAdapter(Context context, Cursor c, int flags,
boolean showStatusImages, SaveKeyringParcel saveKeyringParcel) {
super(context, c, flags);
mInflater = LayoutInflater.from(context);
- mCheckStates = showCheckBoxes ? new ArrayList<Boolean>() : null;
mSaveKeyringParcel = saveKeyringParcel;
mShowStatusImages = showStatusImages;
}
- public UserIdsAdapter(Context context, Cursor c, int flags, boolean showCheckBoxes,
- SaveKeyringParcel saveKeyringParcel) {
- this(context, c, flags, showCheckBoxes, true, saveKeyringParcel);
- }
-
- public UserIdsAdapter(Context context, Cursor c, int flags, boolean showCheckBoxes) {
- this(context, c, flags, showCheckBoxes, true, null);
- }
-
public UserIdsAdapter(Context context, Cursor c, int flags, SaveKeyringParcel saveKeyringParcel) {
- this(context, c, flags, false, true, saveKeyringParcel);
+ this(context, c, flags, true, saveKeyringParcel);
}
public UserIdsAdapter(Context context, Cursor c, int flags) {
- this(context, c, flags, false, true, null);
- }
-
- @Override
- public Cursor swapCursor(Cursor newCursor) {
- if (mCheckStates != null) {
- mCheckStates.clear();
- if (newCursor != null) {
- int count = newCursor.getCount();
- mCheckStates.ensureCapacity(count);
- // initialize to true (use case knowledge: we usually want to sign all uids)
- for (int i = 0; i < count; i++) {
- newCursor.moveToPosition(i);
- int verified = newCursor.getInt(INDEX_VERIFIED);
- mCheckStates.add(verified != Certs.VERIFIED_SECRET);
- }
- }
- }
-
- return super.swapCursor(newCursor);
+ this(context, c, flags, true, null);
}
@Override
@@ -206,56 +159,6 @@ public class UserIdsAdapter extends CursorAdapter implements AdapterView.OnItemC
break;
}
}
-
- // don't care further if checkboxes aren't shown
- if (mCheckStates == null) {
- return;
- }
-
- final CheckBox vCheckBox = (CheckBox) view.findViewById(R.id.user_id_item_check_box);
- final int position = cursor.getPosition();
- vCheckBox.setOnCheckedChangeListener(null);
- vCheckBox.setChecked(mCheckStates.get(position));
- vCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
- @Override
- public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
- mCheckStates.set(position, b);
- }
- });
- vCheckBox.setClickable(false);
- }
-
- public void onItemClick(AdapterView<?> adapter, View view, int position, long id) {
- CheckBox box = ((CheckBox) view.findViewById(R.id.user_id_item_check_box));
- if (box != null) {
- box.toggle();
- }
- }
-
- public ArrayList<String> getSelectedUserIds() {
- ArrayList<String> result = new ArrayList<>();
- for (int i = 0; i < mCheckStates.size(); i++) {
- if (mCheckStates.get(i)) {
- mCursor.moveToPosition(i);
- result.add(mCursor.getString(INDEX_USER_ID));
- }
- }
- return result;
- }
-
- public String getUserId(int position) {
- mCursor.moveToPosition(position);
- return mCursor.getString(INDEX_USER_ID);
- }
-
- public boolean getIsRevoked(int position) {
- mCursor.moveToPosition(position);
- return mCursor.getInt(INDEX_IS_REVOKED) > 0;
- }
-
- public int getIsVerified(int position) {
- mCursor.moveToPosition(position);
- return mCursor.getInt(INDEX_VERIFIED);
}
public boolean getIsRevokedPending(int position) {
@@ -275,10 +178,16 @@ public class UserIdsAdapter extends CursorAdapter implements AdapterView.OnItemC
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
- View view = mInflater.inflate(R.layout.view_key_adv_user_id_item, null);
- // only need to do this once ever, since mShowCheckBoxes is final
- view.findViewById(R.id.user_id_item_check_box).setVisibility(mCheckStates != null ? View.VISIBLE : View.GONE);
- return view;
+ return mInflater.inflate(R.layout.view_key_adv_user_id_item, null);
+ }
+
+ // don't show revoked user ids, irrelevant for average users
+ public static final String USER_IDS_WHERE = UserPackets.IS_REVOKED + " = 0";
+
+ public static CursorLoader createLoader(Activity activity, Uri dataUri) {
+ Uri baseUri = UserPackets.buildUserIdsUri(dataUri);
+ return new CursorLoader(activity, baseUri,
+ UserIdsAdapter.USER_IDS_PROJECTION, USER_IDS_WHERE, null, null);
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAddedAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAddedAdapter.java
index 01218a4e4..970855c77 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAddedAdapter.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAddedAdapter.java
@@ -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);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsSelectableAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsSelectableAdapter.java
new file mode 100644
index 000000000..947d911c3
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsSelectableAdapter.java
@@ -0,0 +1,88 @@
+package org.sufficientlysecure.keychain.ui.adapter;
+
+import android.content.Context;
+import android.database.Cursor;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.CheckBox;
+import android.widget.CompoundButton;
+
+import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.provider.KeychainContract.Certs;
+import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
+
+import java.util.ArrayList;
+
+public class UserIdsSelectableAdapter extends UserIdsAdapter implements AdapterView.OnItemClickListener {
+
+ private final ArrayList<Boolean> mCheckStates;
+
+ public UserIdsSelectableAdapter(Context context, Cursor c, int flags, SaveKeyringParcel saveKeyringParcel) {
+ super(context, c, flags, saveKeyringParcel);
+
+ mCheckStates = new ArrayList<Boolean>();
+ }
+
+ @Override
+ public Cursor swapCursor(Cursor newCursor) {
+ if (mCheckStates != null) {
+ mCheckStates.clear();
+ if (newCursor != null) {
+ int count = newCursor.getCount();
+ mCheckStates.ensureCapacity(count);
+ // initialize to true (use case knowledge: we usually want to sign all uids)
+ for (int i = 0; i < count; i++) {
+ newCursor.moveToPosition(i);
+ int verified = newCursor.getInt(INDEX_VERIFIED);
+ mCheckStates.add(verified != Certs.VERIFIED_SECRET);
+ }
+ }
+ }
+
+ return super.swapCursor(newCursor);
+ }
+
+ @Override
+ public void onItemClick(AdapterView<?> adapter, View view, int position, long id) {
+ CheckBox box = ((CheckBox) view.findViewById(R.id.user_id_item_check_box));
+ if (box != null) {
+ box.toggle();
+ }
+ }
+
+ @Override
+ public void bindView(View view, Context context, Cursor cursor) {
+ super.bindView(view, context, cursor);
+
+ final CheckBox vCheckBox = (CheckBox) view.findViewById(R.id.user_id_item_check_box);
+ final int position = cursor.getPosition();
+ vCheckBox.setOnCheckedChangeListener(null);
+ vCheckBox.setChecked(mCheckStates.get(position));
+ vCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
+ mCheckStates.set(position, b);
+ }
+ });
+ vCheckBox.setClickable(false);
+ }
+
+ public ArrayList<String> getSelectedUserIds() {
+ ArrayList<String> result = new ArrayList<>();
+ for (int i = 0; i < mCheckStates.size(); i++) {
+ if (mCheckStates.get(i)) {
+ mCursor.moveToPosition(i);
+ result.add(mCursor.getString(INDEX_USER_ID));
+ }
+ }
+ return result;
+ }
+
+ @Override
+ public View newView(Context context, Cursor cursor, ViewGroup parent) {
+ View view = mInflater.inflate(R.layout.view_key_selectable_user_id_item, null);
+ return view;
+ }
+
+}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddSubkeyDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddSubkeyDialogFragment.java
index d5376cbdc..0b1d39fc1 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddSubkeyDialogFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddSubkeyDialogFragment.java
@@ -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());
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/CustomAlertDialogBuilder.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/CustomAlertDialogBuilder.java
index d405b1dda..794af5b15 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/CustomAlertDialogBuilder.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/CustomAlertDialogBuilder.java
@@ -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;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteFileDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteFileDialogFragment.java
index 879e3f6da..07462b4ff 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteFileDialogFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteFileDialogFragment.java
@@ -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) {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteKeyDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteKeyDialogFragment.java
index 802f0c11b..32789d53b 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteKeyDialogFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteKeyDialogFragment.java
@@ -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) {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditSubkeyExpiryDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditSubkeyExpiryDialogFragment.java
index f46e253c0..37e05a61d 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditSubkeyExpiryDialogFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditSubkeyExpiryDialogFragment.java
@@ -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);
-
- 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
- );
- }
+ expiryLayout.setVisibility(View.GONE);
+
+ currentExpiry.setText(R.string.btn_no_date);
} else {
noExpiry.setChecked(false);
- datePicker.setVisibility(View.VISIBLE);
+ expiryLayout.setVisibility(View.VISIBLE);
+
+ // 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()));
+ }
+
+ // 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
- // set date picker to current expiry
+ Calendar creationCalPlusOne = (Calendar) creationCal.clone();
+ creationCalPlusOne.add(Calendar.DAY_OF_YEAR, 1);
+ datePicker.setMinDate(creationCalPlusOne.getTime().getTime());
datePicker.init(
- expiryCal.get(Calendar.YEAR),
- expiryCal.get(Calendar.MONTH),
- expiryCal.get(Calendar.DAY_OF_MONTH),
+ creationCalPlusOne.get(Calendar.YEAR),
+ creationCalPlusOne.get(Calendar.MONTH),
+ creationCalPlusOne.get(Calendar.DAY_OF_MONTH),
null
);
- }
+ } else {
+ // Min Date: today + 1 day
- if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB) {
- datePicker.setMinDate(creationCal.getTime().getTime());
+ // 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() {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/SetPassphraseDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/SetPassphraseDialogFragment.java
index a05719072..a3ffe250b 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/SetPassphraseDialogFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/SetPassphraseDialogFragment.java
@@ -92,7 +92,6 @@ public class SetPassphraseDialogFragment extends DialogFragment implements OnEdi
CustomAlertDialogBuilder alert = new CustomAlertDialogBuilder(activity);
alert.setTitle(title);
- alert.setMessage(R.string.enter_passphrase_twice);
LayoutInflater inflater = activity.getLayoutInflater();
View view = inflater.inflate(R.layout.passphrase_repeat_dialog, null);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/KeyFormattingUtils.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/KeyFormattingUtils.java
index 38ed88b9c..3a2177e8d 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/KeyFormattingUtils.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/KeyFormattingUtils.java
@@ -413,10 +413,10 @@ public class KeyFormattingUtils {
case STATE_VERIFIED: {
if (big) {
statusIcon.setImageDrawable(
- context.getResources().getDrawable(R.drawable.status_signature_verified_cutout_96px));
+ context.getResources().getDrawable(R.drawable.status_signature_verified_cutout_96dp));
} else {
statusIcon.setImageDrawable(
- context.getResources().getDrawable(R.drawable.status_signature_verified_cutout_24px));
+ context.getResources().getDrawable(R.drawable.status_signature_verified_cutout_24dp));
}
if (color == KeyFormattingUtils.DEFAULT_COLOR) {
color = R.color.android_green_light;
@@ -430,7 +430,7 @@ public class KeyFormattingUtils {
}
case STATE_ENCRYPTED: {
statusIcon.setImageDrawable(
- context.getResources().getDrawable(R.drawable.status_lock_closed_24px));
+ context.getResources().getDrawable(R.drawable.status_lock_closed_24dp));
if (color == KeyFormattingUtils.DEFAULT_COLOR) {
color = R.color.android_green_light;
}
@@ -445,10 +445,10 @@ public class KeyFormattingUtils {
case STATE_UNVERIFIED: {
if (big) {
statusIcon.setImageDrawable(
- context.getResources().getDrawable(R.drawable.status_signature_unverified_cutout_96px));
+ context.getResources().getDrawable(R.drawable.status_signature_unverified_cutout_96dp));
} else {
statusIcon.setImageDrawable(
- context.getResources().getDrawable(R.drawable.status_signature_unverified_cutout_24px));
+ context.getResources().getDrawable(R.drawable.status_signature_unverified_cutout_24dp));
}
if (color == KeyFormattingUtils.DEFAULT_COLOR) {
color = R.color.android_orange_light;
@@ -462,7 +462,7 @@ public class KeyFormattingUtils {
}
case STATE_UNKNOWN_KEY: {
statusIcon.setImageDrawable(
- context.getResources().getDrawable(R.drawable.status_signature_unknown_cutout_24px));
+ context.getResources().getDrawable(R.drawable.status_signature_unknown_cutout_24dp));
if (color == KeyFormattingUtils.DEFAULT_COLOR) {
color = R.color.android_orange_light;
}
@@ -477,10 +477,10 @@ public class KeyFormattingUtils {
case STATE_REVOKED: {
if (big) {
statusIcon.setImageDrawable(
- context.getResources().getDrawable(R.drawable.status_signature_revoked_cutout_96px));
+ context.getResources().getDrawable(R.drawable.status_signature_revoked_cutout_96dp));
} else {
statusIcon.setImageDrawable(
- context.getResources().getDrawable(R.drawable.status_signature_revoked_cutout_24px));
+ context.getResources().getDrawable(R.drawable.status_signature_revoked_cutout_24dp));
}
if (color == KeyFormattingUtils.DEFAULT_COLOR) {
color = R.color.android_red_light;
@@ -495,10 +495,10 @@ public class KeyFormattingUtils {
case STATE_EXPIRED: {
if (big) {
statusIcon.setImageDrawable(
- context.getResources().getDrawable(R.drawable.status_signature_expired_cutout_96px));
+ context.getResources().getDrawable(R.drawable.status_signature_expired_cutout_96dp));
} else {
statusIcon.setImageDrawable(
- context.getResources().getDrawable(R.drawable.status_signature_expired_cutout_24px));
+ context.getResources().getDrawable(R.drawable.status_signature_expired_cutout_24dp));
}
if (color == KeyFormattingUtils.DEFAULT_COLOR) {
color = R.color.android_red_light;
@@ -512,7 +512,7 @@ public class KeyFormattingUtils {
}
case STATE_NOT_ENCRYPTED: {
statusIcon.setImageDrawable(
- context.getResources().getDrawable(R.drawable.status_lock_open_24px));
+ context.getResources().getDrawable(R.drawable.status_lock_open_24dp));
if (color == KeyFormattingUtils.DEFAULT_COLOR) {
color = R.color.android_red_light;
}
@@ -525,7 +525,7 @@ public class KeyFormattingUtils {
}
case STATE_NOT_SIGNED: {
statusIcon.setImageDrawable(
- context.getResources().getDrawable(R.drawable.status_signature_unknown_cutout_24px));
+ context.getResources().getDrawable(R.drawable.status_signature_unknown_cutout_24dp));
if (color == KeyFormattingUtils.DEFAULT_COLOR) {
color = R.color.android_red_light;
}
@@ -538,7 +538,7 @@ public class KeyFormattingUtils {
}
case STATE_INVALID: {
statusIcon.setImageDrawable(
- context.getResources().getDrawable(R.drawable.status_signature_invalid_cutout_24px));
+ context.getResources().getDrawable(R.drawable.status_signature_invalid_cutout_24dp));
if (color == KeyFormattingUtils.DEFAULT_COLOR) {
color = R.color.android_red_light;
}
@@ -552,7 +552,7 @@ public class KeyFormattingUtils {
/** special **/
case STATE_UNAVAILABLE: {
statusIcon.setImageDrawable(
- context.getResources().getDrawable(R.drawable.status_signature_invalid_cutout_24px));
+ context.getResources().getDrawable(R.drawable.status_signature_invalid_cutout_24dp));
if (color == KeyFormattingUtils.DEFAULT_COLOR) {
color = R.color.bg_gray;
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionView.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionView.java
index f05f5f96b..d20e2bc99 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionView.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionView.java
@@ -90,7 +90,7 @@ public class EncryptKeyCompletionView extends TokenCompleteTextView {
}
private void setImageByKey(ImageView view, EncryptionKey key) {
- Bitmap photo = ContactHelper.photoFromFingerprint(getContext().getContentResolver(), key.getFingerprint());
+ Bitmap photo = ContactHelper.getCachedPhotoByMasterKeyId(getContext().getContentResolver(), key.getKeyId());
if (photo != null) {
view.setImageBitmap(photo);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ContactHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ContactHelper.java
index 3cf201ed7..44bcc52a5 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ContactHelper.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ContactHelper.java
@@ -41,7 +41,6 @@ import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import java.io.InputStream;
import java.util.ArrayList;
-import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@@ -50,40 +49,7 @@ import java.util.Set;
public class ContactHelper {
- public static final String[] KEYS_TO_CONTACT_PROJECTION = new String[]{
- KeychainContract.KeyRings.USER_ID,
- KeychainContract.KeyRings.FINGERPRINT,
- KeychainContract.KeyRings.KEY_ID,
- KeychainContract.KeyRings.MASTER_KEY_ID,
- KeychainContract.KeyRings.EXPIRY,
- KeychainContract.KeyRings.IS_REVOKED};
-
- public static final int INDEX_USER_ID = 0;
- public static final int INDEX_FINGERPRINT = 1;
- public static final int INDEX_KEY_ID = 2;
- public static final int INDEX_MASTER_KEY_ID = 3;
- public static final int INDEX_EXPIRY = 4;
- public static final int INDEX_IS_REVOKED = 5;
-
- public static final String[] USER_IDS_PROJECTION = new String[]{
- UserPackets.USER_ID
- };
-
- public static final int INDEX_USER_IDS_USER_ID = 0;
-
- public static final String NON_REVOKED_SELECTION = UserPackets.IS_REVOKED + "=0";
-
- public static final String[] ID_PROJECTION = new String[]{ContactsContract.RawContacts._ID};
- public static final String[] SOURCE_ID_PROJECTION = new String[]{ContactsContract.RawContacts.SOURCE_ID};
-
- public static final String ACCOUNT_TYPE_AND_SOURCE_ID_SELECTION =
- ContactsContract.RawContacts.ACCOUNT_TYPE + "=? AND " + ContactsContract.RawContacts.SOURCE_ID + "=?";
- public static final String ACCOUNT_TYPE_SELECTION = ContactsContract.RawContacts.ACCOUNT_TYPE + "=?";
- public static final String RAW_CONTACT_AND_MIMETYPE_SELECTION =
- ContactsContract.Data.RAW_CONTACT_ID + "=? AND " + ContactsContract.Data.MIMETYPE + "=?";
- public static final String ID_SELECTION = ContactsContract.RawContacts._ID + "=?";
-
- private static final Map<String, Bitmap> photoCache = new HashMap<>();
+ private static final Map<Long, Bitmap> photoCache = new HashMap<>();
public static List<String> getPossibleUserEmails(Context context) {
Set<String> accountMails = getAccountEmails(context);
@@ -125,33 +91,33 @@ public class ContactHelper {
* @return
*/
private static Set<String> getContactNamesFromEmails(Context context, Set<String> emails) {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
- Set<String> names = new HashSet<>();
- for (String email : emails) {
- ContentResolver resolver = context.getContentResolver();
- Cursor profileCursor = resolver.query(
- ContactsContract.CommonDataKinds.Email.CONTENT_URI,
- new String[]{ContactsContract.CommonDataKinds.Email.ADDRESS,
- ContactsContract.Contacts.DISPLAY_NAME},
- ContactsContract.CommonDataKinds.Email.ADDRESS + "=?",
- new String[]{email}, null
- );
- if (profileCursor == null) return null;
-
- Set<String> currNames = new HashSet<>();
- while (profileCursor.moveToNext()) {
- String name = profileCursor.getString(1);
- if (name != null) {
- currNames.add(name);
- }
+ Set<String> names = new HashSet<>();
+ for (String email : emails) {
+ ContentResolver resolver = context.getContentResolver();
+ Cursor profileCursor = resolver.query(
+ ContactsContract.CommonDataKinds.Email.CONTENT_URI,
+ new String[]{
+ ContactsContract.CommonDataKinds.Email.ADDRESS,
+ ContactsContract.Contacts.DISPLAY_NAME
+ },
+ ContactsContract.CommonDataKinds.Email.ADDRESS + "=?",
+ new String[]{email}, null
+ );
+ if (profileCursor == null) {
+ return null;
+ }
+
+ Set<String> currNames = new HashSet<>();
+ while (profileCursor.moveToNext()) {
+ String name = profileCursor.getString(1);
+ if (name != null) {
+ currNames.add(name);
}
- profileCursor.close();
- names.addAll(currNames);
}
- return names;
- } else {
- return new HashSet<>();
+ profileCursor.close();
+ names.addAll(currNames);
}
+ return names;
}
/**
@@ -162,38 +128,37 @@ public class ContactHelper {
* @return
*/
private static Set<String> getMainProfileContactEmails(Context context) {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
- ContentResolver resolver = context.getContentResolver();
- Cursor profileCursor = resolver.query(
- Uri.withAppendedPath(
- ContactsContract.Profile.CONTENT_URI,
- ContactsContract.Contacts.Data.CONTENT_DIRECTORY),
- new String[]{ContactsContract.CommonDataKinds.Email.ADDRESS,
- ContactsContract.CommonDataKinds.Email.IS_PRIMARY},
-
- // Selects only email addresses
- ContactsContract.Contacts.Data.MIMETYPE + "=?",
- new String[]{
- ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE,
- },
- // Show primary rows first. Note that there won't be a primary email address if the
- // user hasn't specified one.
- ContactsContract.Contacts.Data.IS_PRIMARY + " DESC"
- );
- if (profileCursor == null) return null;
+ ContentResolver resolver = context.getContentResolver();
+ Cursor profileCursor = resolver.query(
+ Uri.withAppendedPath(
+ ContactsContract.Profile.CONTENT_URI,
+ ContactsContract.Contacts.Data.CONTENT_DIRECTORY),
+ new String[]{
+ ContactsContract.CommonDataKinds.Email.ADDRESS,
+ ContactsContract.CommonDataKinds.Email.IS_PRIMARY
+ },
+ // Selects only email addresses
+ ContactsContract.Contacts.Data.MIMETYPE + "=?",
+ new String[]{
+ ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE,
+ },
+ // Show primary rows first. Note that there won't be a primary email address if the
+ // user hasn't specified one.
+ ContactsContract.Contacts.Data.IS_PRIMARY + " DESC"
+ );
+ if (profileCursor == null) {
+ return null;
+ }
- Set<String> emails = new HashSet<>();
- while (profileCursor.moveToNext()) {
- String email = profileCursor.getString(0);
- if (email != null) {
- emails.add(email);
- }
+ Set<String> emails = new HashSet<>();
+ while (profileCursor.moveToNext()) {
+ String email = profileCursor.getString(0);
+ if (email != null) {
+ emails.add(email);
}
- profileCursor.close();
- return emails;
- } else {
- return new HashSet<>();
}
+ profileCursor.close();
+ return emails;
}
/**
@@ -204,26 +169,27 @@ public class ContactHelper {
* @return
*/
private static List<String> getMainProfileContactName(Context context) {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
- ContentResolver resolver = context.getContentResolver();
- Cursor profileCursor = resolver.query(ContactsContract.Profile.CONTENT_URI,
- new String[]{ContactsContract.Profile.DISPLAY_NAME},
- null, null, null);
- if (profileCursor == null) return null;
+ ContentResolver resolver = context.getContentResolver();
+ Cursor profileCursor = resolver.query(
+ ContactsContract.Profile.CONTENT_URI,
+ new String[]{
+ ContactsContract.Profile.DISPLAY_NAME
+ },
+ null, null, null);
+ if (profileCursor == null) {
+ return null;
+ }
- Set<String> names = new HashSet<>();
- // should only contain one entry!
- while (profileCursor.moveToNext()) {
- String name = profileCursor.getString(0);
- if (name != null) {
- names.add(name);
- }
+ Set<String> names = new HashSet<>();
+ // should only contain one entry!
+ while (profileCursor.moveToNext()) {
+ String name = profileCursor.getString(0);
+ if (name != null) {
+ names.add(name);
}
- profileCursor.close();
- return new ArrayList<>(names);
- } else {
- return new ArrayList<>();
}
+ profileCursor.close();
+ return new ArrayList<>(names);
}
public static List<String> getContactMails(Context context) {
@@ -231,7 +197,9 @@ public class ContactHelper {
Cursor mailCursor = resolver.query(ContactsContract.CommonDataKinds.Email.CONTENT_URI,
new String[]{ContactsContract.CommonDataKinds.Email.DATA},
null, null, null);
- if (mailCursor == null) return new ArrayList<>();
+ if (mailCursor == null) {
+ return new ArrayList<>();
+ }
Set<String> mails = new HashSet<>();
while (mailCursor.moveToNext()) {
@@ -249,7 +217,9 @@ public class ContactHelper {
Cursor cursor = resolver.query(ContactsContract.Contacts.CONTENT_URI,
new String[]{ContactsContract.Contacts.DISPLAY_NAME},
null, null, null);
- if (cursor == null) return new ArrayList<>();
+ if (cursor == null) {
+ return new ArrayList<>();
+ }
Set<String> names = new HashSet<>();
while (cursor.moveToNext()) {
@@ -275,72 +245,111 @@ public class ContactHelper {
return null;
}
- public static Bitmap photoFromFingerprint(ContentResolver contentResolver, String fingerprint) {
- if (fingerprint == null) return null;
- if (!photoCache.containsKey(fingerprint)) {
- photoCache.put(fingerprint, loadPhotoFromFingerprint(contentResolver, fingerprint));
+ public static Bitmap getCachedPhotoByMasterKeyId(ContentResolver contentResolver, long masterKeyId) {
+ if (masterKeyId == -1) {
+ return null;
}
- return photoCache.get(fingerprint);
+ if (!photoCache.containsKey(masterKeyId)) {
+ photoCache.put(masterKeyId, loadPhotoByMasterKeyId(contentResolver, masterKeyId, false));
+ }
+ return photoCache.get(masterKeyId);
}
- private static Bitmap loadPhotoFromFingerprint(ContentResolver contentResolver, String fingerprint) {
- if (fingerprint == null) return null;
+ public static Bitmap loadPhotoByMasterKeyId(ContentResolver contentResolver, long masterKeyId,
+ boolean highRes) {
+ if (masterKeyId == -1) {
+ return null;
+ }
try {
- int rawContactId = findRawContactId(contentResolver, fingerprint);
- if (rawContactId == -1) return null;
+ long rawContactId = findRawContactId(contentResolver, masterKeyId);
+ if (rawContactId == -1) {
+ return null;
+ }
Uri rawContactUri = ContentUris.withAppendedId(ContactsContract.RawContacts.CONTENT_URI, rawContactId);
Uri contactUri = ContactsContract.RawContacts.getContactLookupUri(contentResolver, rawContactUri);
InputStream photoInputStream =
- ContactsContract.Contacts.openContactPhotoInputStream(contentResolver, contactUri);
- if (photoInputStream == null) return null;
+ ContactsContract.Contacts.openContactPhotoInputStream(contentResolver, contactUri, highRes);
+ if (photoInputStream == null) {
+ return null;
+ }
return BitmapFactory.decodeStream(photoInputStream);
} catch (Throwable ignored) {
return null;
}
}
+ public static final String[] KEYS_TO_CONTACT_PROJECTION = new String[]{
+ KeychainContract.KeyRings.MASTER_KEY_ID,
+ KeychainContract.KeyRings.USER_ID,
+ KeychainContract.KeyRings.IS_EXPIRED,
+ KeychainContract.KeyRings.IS_REVOKED};
+
+ public static final int INDEX_MASTER_KEY_ID = 0;
+ public static final int INDEX_USER_ID = 1;
+ public static final int INDEX_IS_EXPIRED = 2;
+ public static final int INDEX_IS_REVOKED = 3;
+
/**
- * Write the current Keychain to the contact db
+ * Write/Update the current OpenKeychain keys to the contact db
*/
public static void writeKeysToContacts(Context context) {
ContentResolver resolver = context.getContentResolver();
- Set<String> contactFingerprints = getRawContactFingerprints(resolver);
+ Set<Long> deletedKeys = getRawContactMasterKeyIds(resolver);
+
+// debugDeleteRawContacts(resolver);
+
+// ContentProviderClient client = resolver.acquireContentProviderClient(ContactsContract.AUTHORITY_URI);
+// ContentValues values = new ContentValues();
+// Account account = new Account(Constants.ACCOUNT_NAME, Constants.ACCOUNT_TYPE);
+// values.put(ContactsContract.Settings.ACCOUNT_NAME, account.name);
+// values.put(ContactsContract.Settings.ACCOUNT_TYPE, account.type);
+// values.put(ContactsContract.Settings.UNGROUPED_VISIBLE, true);
+// try {
+// client.insert(ContactsContract.Settings.CONTENT_URI.buildUpon().appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "true").build(), values);
+// } catch (RemoteException e) {
+// e.printStackTrace();
+// }
// Load all Keys from OK
Cursor cursor = resolver.query(KeychainContract.KeyRings.buildUnifiedKeyRingsUri(), KEYS_TO_CONTACT_PROJECTION,
null, null, null);
if (cursor != null) {
while (cursor.moveToNext()) {
- String[] primaryUserId = KeyRing.splitUserId(cursor.getString(INDEX_USER_ID));
- String fingerprint = KeyFormattingUtils.convertFingerprintToHex(cursor.getBlob(INDEX_FINGERPRINT));
- contactFingerprints.remove(fingerprint);
- String keyIdShort = KeyFormattingUtils.convertKeyIdToHexShort(cursor.getLong(INDEX_KEY_ID));
long masterKeyId = cursor.getLong(INDEX_MASTER_KEY_ID);
- boolean isExpired = !cursor.isNull(INDEX_EXPIRY)
- && new Date(cursor.getLong(INDEX_EXPIRY) * 1000).before(new Date());
+ String[] userIdSplit = KeyRing.splitUserId(cursor.getString(INDEX_USER_ID));
+ String keyIdShort = KeyFormattingUtils.convertKeyIdToHexShort(cursor.getLong(INDEX_MASTER_KEY_ID));
+ boolean isExpired = cursor.getInt(INDEX_IS_EXPIRED) != 0;
boolean isRevoked = cursor.getInt(INDEX_IS_REVOKED) > 0;
- int rawContactId = findRawContactId(resolver, fingerprint);
- ArrayList<ContentProviderOperation> ops = new ArrayList<>();
- Log.d(Constants.TAG, "raw contact id: "+rawContactId);
+ Log.d(Constants.TAG, "masterKeyId: " + masterKeyId);
+
+ deletedKeys.remove(masterKeyId);
+
+ // get raw contact to this master key id
+ long rawContactId = findRawContactId(resolver, masterKeyId);
+ Log.d(Constants.TAG, "rawContactId: " + rawContactId);
+
+ ArrayList<ContentProviderOperation> ops = new ArrayList<>();
// Do not store expired or revoked keys in contact db - and remove them if they already exist
if (isExpired || isRevoked) {
+ Log.d(Constants.TAG, "Expired or revoked: Deleting " + rawContactId);
if (rawContactId != -1) {
- resolver.delete(ContactsContract.RawContacts.CONTENT_URI, ID_SELECTION,
- new String[]{Integer.toString(rawContactId)});
+ deleteRawContactById(resolver, rawContactId);
}
- } else if (primaryUserId[0] != null) {
+ } else if (userIdSplit[0] != null) {
// Create a new rawcontact with corresponding key if it does not exist yet
if (rawContactId == -1) {
- insertContact(ops, context, fingerprint);
+ Log.d(Constants.TAG, "Insert new raw contact with masterKeyId " + masterKeyId);
+
+ insertContact(ops, context, masterKeyId);
writeContactKey(ops, context, rawContactId, masterKeyId, keyIdShort);
}
// We always update the display name (which is derived from primary user id)
// and email addresses from user id
- writeContactDisplayName(ops, rawContactId, primaryUserId[0]);
+ writeContactDisplayName(ops, rawContactId, userIdSplit[0]);
writeContactEmail(ops, resolver, rawContactId, masterKeyId);
try {
resolver.applyBatch(ContactsContract.AUTHORITY, ops);
@@ -352,43 +361,84 @@ public class ContactHelper {
cursor.close();
}
- // Delete fingerprints that are no longer present in OK
- for (String fingerprint : contactFingerprints) {
- resolver.delete(ContactsContract.RawContacts.CONTENT_URI, ACCOUNT_TYPE_AND_SOURCE_ID_SELECTION,
- new String[]{Constants.ACCOUNT_TYPE, fingerprint});
+ // Delete master key ids that are no longer present in OK
+ for (Long masterKeyId : deletedKeys) {
+ Log.d(Constants.TAG, "Delete raw contact with masterKeyId " + masterKeyId);
+ deleteRawContactByMasterKeyId(resolver, masterKeyId);
}
+ }
+
+ /**
+ * Delete all raw contacts associated to OpenKeychain.
+ * <p/>
+ * TODO: Does this work?
+ */
+ private static int debugDeleteRawContacts(ContentResolver resolver) {
+ Log.d(Constants.TAG, "Deleting all raw contacts associated to OK...");
+ return resolver.delete(ContactsContract.RawContacts.CONTENT_URI,
+ ContactsContract.RawContacts.ACCOUNT_TYPE + "=?",
+ new String[]{
+ Constants.ACCOUNT_TYPE
+ });
+ }
+
+ private static int deleteRawContactById(ContentResolver resolver, long rawContactId) {
+ return resolver.delete(ContactsContract.RawContacts.CONTENT_URI,
+ ContactsContract.RawContacts.ACCOUNT_TYPE + "=? AND " + ContactsContract.RawContacts._ID + "=?",
+ new String[]{
+ Constants.ACCOUNT_TYPE, Long.toString(rawContactId)
+ });
+ }
+ private static int deleteRawContactByMasterKeyId(ContentResolver resolver, long masterKeyId) {
+ return resolver.delete(ContactsContract.RawContacts.CONTENT_URI,
+ ContactsContract.RawContacts.ACCOUNT_TYPE + "=? AND " + ContactsContract.RawContacts.SOURCE_ID + "=?",
+ new String[]{
+ Constants.ACCOUNT_TYPE, Long.toString(masterKeyId)
+ });
}
/**
- * @return a set of all key fingerprints currently present in the contact db
+ * @return a set of all key master key ids currently present in the contact db
*/
- private static Set<String> getRawContactFingerprints(ContentResolver resolver) {
- HashSet<String> result = new HashSet<>();
- Cursor fingerprints = resolver.query(ContactsContract.RawContacts.CONTENT_URI, SOURCE_ID_PROJECTION,
- ACCOUNT_TYPE_SELECTION, new String[]{Constants.ACCOUNT_TYPE}, null);
- if (fingerprints != null) {
- while (fingerprints.moveToNext()) {
- result.add(fingerprints.getString(0));
+ private static Set<Long> getRawContactMasterKeyIds(ContentResolver resolver) {
+ HashSet<Long> result = new HashSet<>();
+ Cursor masterKeyIds = resolver.query(ContactsContract.RawContacts.CONTENT_URI,
+ new String[]{
+ ContactsContract.RawContacts.SOURCE_ID
+ },
+ ContactsContract.RawContacts.ACCOUNT_TYPE + "=?",
+ new String[]{
+ Constants.ACCOUNT_TYPE
+ }, null);
+ if (masterKeyIds != null) {
+ while (masterKeyIds.moveToNext()) {
+ result.add(masterKeyIds.getLong(0));
}
- fingerprints.close();
+ masterKeyIds.close();
}
return result;
}
/**
- * This will search the contact db for a raw contact with a given fingerprint
+ * This will search the contact db for a raw contact with a given master key id
*
* @return raw contact id or -1 if not found
*/
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
- private static int findRawContactId(ContentResolver resolver, String fingerprint) {
- int rawContactId = -1;
- Cursor raw = resolver.query(ContactsContract.RawContacts.CONTENT_URI, ID_PROJECTION,
- ACCOUNT_TYPE_AND_SOURCE_ID_SELECTION, new String[]{Constants.ACCOUNT_TYPE, fingerprint}, null, null);
+ private static long findRawContactId(ContentResolver resolver, long masterKeyId) {
+ long rawContactId = -1;
+ Cursor raw = resolver.query(ContactsContract.RawContacts.CONTENT_URI,
+ new String[]{
+ ContactsContract.RawContacts._ID
+ },
+ ContactsContract.RawContacts.ACCOUNT_TYPE + "=? AND " + ContactsContract.RawContacts.SOURCE_ID + "=?",
+ new String[]{
+ Constants.ACCOUNT_TYPE, Long.toString(masterKeyId)
+ }, null, null);
if (raw != null) {
if (raw.moveToNext()) {
- rawContactId = raw.getInt(0);
+ rawContactId = raw.getLong(0);
}
raw.close();
}
@@ -396,13 +446,13 @@ public class ContactHelper {
}
/**
- * Creates a empty raw contact with a given fingerprint
+ * Creates a empty raw contact with a given masterKeyId
*/
- private static void insertContact(ArrayList<ContentProviderOperation> ops, Context context, String fingerprint) {
+ private static void insertContact(ArrayList<ContentProviderOperation> ops, Context context, long masterKeyId) {
ops.add(ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI)
.withValue(ContactsContract.RawContacts.ACCOUNT_NAME, Constants.ACCOUNT_NAME)
.withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, Constants.ACCOUNT_TYPE)
- .withValue(ContactsContract.RawContacts.SOURCE_ID, fingerprint)
+ .withValue(ContactsContract.RawContacts.SOURCE_ID, Long.toString(masterKeyId))
.build());
}
@@ -411,7 +461,7 @@ public class ContactHelper {
* <p/>
* This creates the link to OK in contact details
*/
- private static void writeContactKey(ArrayList<ContentProviderOperation> ops, Context context, int rawContactId,
+ private static void writeContactKey(ArrayList<ContentProviderOperation> ops, Context context, long rawContactId,
long masterKeyId, String keyIdShort) {
ops.add(referenceRawContact(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI), rawContactId)
.withValue(ContactsContract.Data.MIMETYPE, Constants.CUSTOM_CONTACT_DATA_MIME_TYPE)
@@ -424,16 +474,22 @@ public class ContactHelper {
* Write all known email addresses of a key (derived from user ids) to a given raw contact
*/
private static void writeContactEmail(ArrayList<ContentProviderOperation> ops, ContentResolver resolver,
- int rawContactId, long masterKeyId) {
- ops.add(selectByRawContactAndItemType(ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI),
+ long rawContactId, long masterKeyId) {
+ ops.add(selectByRawContactAndItemType(
+ ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI),
rawContactId, ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE).build());
Cursor ids = resolver.query(UserPackets.buildUserIdsUri(masterKeyId),
- USER_IDS_PROJECTION, NON_REVOKED_SELECTION, null, null);
+ new String[]{
+ UserPackets.USER_ID
+ },
+ UserPackets.IS_REVOKED + "=0",
+ null, null);
if (ids != null) {
while (ids.moveToNext()) {
String[] userId = KeyRing.splitUserId(ids.getString(0));
if (userId[1] != null) {
- ops.add(referenceRawContact(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI),
+ ops.add(referenceRawContact(
+ ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI),
rawContactId)
.withValue(ContactsContract.Data.MIMETYPE,
ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE)
@@ -445,7 +501,7 @@ public class ContactHelper {
}
}
- private static void writeContactDisplayName(ArrayList<ContentProviderOperation> ops, int rawContactId,
+ private static void writeContactDisplayName(ArrayList<ContentProviderOperation> ops, long rawContactId,
String displayName) {
if (displayName != null) {
ops.add(insertOrUpdateForRawContact(ContactsContract.Data.CONTENT_URI, rawContactId,
@@ -456,13 +512,13 @@ public class ContactHelper {
}
private static ContentProviderOperation.Builder referenceRawContact(ContentProviderOperation.Builder builder,
- int rawContactId) {
+ long rawContactId) {
return rawContactId == -1 ?
builder.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) :
builder.withValue(ContactsContract.Data.RAW_CONTACT_ID, rawContactId);
}
- private static ContentProviderOperation.Builder insertOrUpdateForRawContact(Uri uri, int rawContactId,
+ private static ContentProviderOperation.Builder insertOrUpdateForRawContact(Uri uri, long rawContactId,
String itemType) {
if (rawContactId == -1) {
return referenceRawContact(ContentProviderOperation.newInsert(uri), rawContactId).withValue(
@@ -473,8 +529,11 @@ public class ContactHelper {
}
private static ContentProviderOperation.Builder selectByRawContactAndItemType(
- ContentProviderOperation.Builder builder, int rawContactId, String itemType) {
- return builder.withSelection(RAW_CONTACT_AND_MIMETYPE_SELECTION,
- new String[]{Integer.toString(rawContactId), itemType});
+ ContentProviderOperation.Builder builder, long rawContactId, String itemType) {
+ return builder.withSelection(
+ ContactsContract.Data.RAW_CONTACT_ID + "=? AND " + ContactsContract.Data.MIMETYPE + "=?",
+ new String[]{
+ Long.toString(rawContactId), itemType
+ });
}
}