aboutsummaryrefslogtreecommitdiffstats
path: root/OpenKeychain/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'OpenKeychain/src/main')
-rw-r--r--OpenKeychain/src/main/AndroidManifest.xml16
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java29
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/CloudSearch.java3
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/FacebookKeyserver.java197
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/ImportKeysList.java12
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/ImportKeysListEntry.java25
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/KeybaseKeyserver.java5
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/Keyserver.java1
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/ParcelableKeyRing.java27
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/BenchmarkOperation.java5
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ImportOperation.java46
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java13
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/PgpSignEncryptResult.java10
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java8
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java12
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ContactSyncAdapterService.java38
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeyserverSyncAdapterService.java53
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java9
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateYubiKeyImportResetFragment.java9
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java9
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptListFragment.java10
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java94
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysCloudFragment.java42
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java45
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysProxyActivity.java11
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java9
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsActivity.java230
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java16
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvActivity.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyFragment.java10
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateFinalFragment.java8
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/NotificationUtils.java50
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EmailEditText.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionView.java24
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/NameEditText.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ContactHelper.java287
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/EmailKeyHelper.java4
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Preferences.java100
-rw-r--r--OpenKeychain/src/main/res/layout/encrypt_asymmetric_fragment.xml1
-rw-r--r--OpenKeychain/src/main/res/values/strings.xml5
-rw-r--r--OpenKeychain/src/main/res/xml/experimental_preferences.xml15
-rw-r--r--OpenKeychain/src/main/res/xml/passphrase_preferences.xml4
42 files changed, 809 insertions, 689 deletions
diff --git a/OpenKeychain/src/main/AndroidManifest.xml b/OpenKeychain/src/main/AndroidManifest.xml
index 337ad73e0..1ac9eb257 100644
--- a/OpenKeychain/src/main/AndroidManifest.xml
+++ b/OpenKeychain/src/main/AndroidManifest.xml
@@ -681,6 +681,22 @@
<data android:pathPattern="/pks/lookup.*" />
</intent-filter>
+ <!-- VIEW from facebook public key urls opened in a browser -->
+ <intent-filter android:label="@string/intent_import_key">
+ <action android:name="android.intent.action.VIEW" />
+
+ <category android:name="android.intent.category.BROWSABLE" />
+ <category android:name="android.intent.category.DEFAULT" />
+
+ <data android:scheme="https" />
+ <data android:scheme="http" />
+
+ <data android:host="www.facebook.com" />
+ <data android:host="facebook.com" />
+
+ <data android:pathPattern="/..*/publickey/download" />
+ </intent-filter>
+
<!-- IMPORT_KEY with files TODO: does this work? -->
<intent-filter android:label="@string/intent_import_key">
<action android:name="org.sufficientlysecure.keychain.action.IMPORT_KEY" />
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java
index 3390fb729..57fce633e 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java
@@ -17,6 +17,8 @@
package org.sufficientlysecure.keychain;
+import android.accounts.Account;
+import android.accounts.AccountManager;
import android.app.Application;
import android.content.Context;
import android.content.Intent;
@@ -25,6 +27,7 @@ import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Environment;
+import android.widget.Toast;
import org.spongycastle.jce.provider.BouncyCastleProvider;
import org.sufficientlysecure.keychain.provider.KeychainDatabase;
@@ -90,8 +93,13 @@ public class KeychainApplication extends Application {
FormattingUtils.getColorFromAttr(getApplicationContext(), R.attr.colorPrimary));
// Add OpenKeychain account to Android to link contacts with keys and keyserver sync
- KeyserverSyncAdapterService.enableKeyserverSync(this);
- ContactSyncAdapterService.enableContactsSync(this);
+ createAccountIfNecessary();
+
+ // if first time, enable keyserver and contact sync
+ if (Preferences.getPreferences(this).isFirstTime()) {
+ KeyserverSyncAdapterService.enableKeyserverSync(this);
+ ContactSyncAdapterService.enableContactsSync(this);
+ }
// Update keyserver list as needed
Preferences.getPreferences(this).upgradePreferences(this);
@@ -108,6 +116,23 @@ public class KeychainApplication extends Application {
}
}
+ private void createAccountIfNecessary() {
+ try {
+ AccountManager manager = AccountManager.get(this);
+ Account[] accounts = manager.getAccountsByType(Constants.ACCOUNT_TYPE);
+
+ Account account = new Account(Constants.ACCOUNT_NAME, Constants.ACCOUNT_TYPE);
+ if (accounts.length == 0) {
+ if (!manager.addAccountExplicitly(account, null, null)) {
+ Log.d(Constants.TAG, "account already exists, the account is null, or another error occured");
+ }
+ }
+ } catch (SecurityException e) {
+ Log.e(Constants.TAG, "SecurityException when adding the account", e);
+ Toast.makeText(this, R.string.reinstall_openkeychain, Toast.LENGTH_LONG).show();
+ }
+ }
+
public static HashMap<String,Bitmap> qrCodeCache = new HashMap<>();
@Override
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/CloudSearch.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/CloudSearch.java
index 869d107ab..df45de11f 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/CloudSearch.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/CloudSearch.java
@@ -48,6 +48,9 @@ public class CloudSearch {
if (cloudPrefs.searchKeybase) {
servers.add(new KeybaseKeyserver(proxy));
}
+ if (cloudPrefs.searchFacebook) {
+ servers.add(new FacebookKeyserver(proxy));
+ }
final ImportKeysList results = new ImportKeysList(servers.size());
ArrayList<Thread> searchThreads = new ArrayList<>();
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/FacebookKeyserver.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/FacebookKeyserver.java
new file mode 100644
index 000000000..d87a82a24
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/FacebookKeyserver.java
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2015 Dominik Schürmann <dominik@dominikschuermann.de>
+ * Copyright (C) 2015 Vincent Breitmoser <v.breitmoser@mugenguild.com>
+ * Copyright (C) 2015 Adithya Abraham Philip <adithyaphilip@gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.sufficientlysecure.keychain.keyimport;
+
+import android.net.Uri;
+import android.support.annotation.NonNull;
+
+import com.squareup.okhttp.OkHttpClient;
+import com.squareup.okhttp.Request;
+import com.squareup.okhttp.Response;
+
+import org.sufficientlysecure.keychain.Constants;
+import org.sufficientlysecure.keychain.pgp.PgpHelper;
+import org.sufficientlysecure.keychain.pgp.UncachedKeyRing;
+import org.sufficientlysecure.keychain.pgp.UncachedPublicKey;
+import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
+import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
+import org.sufficientlysecure.keychain.util.Log;
+
+import java.io.IOException;
+import java.net.Proxy;
+
+import java.net.URI;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+
+public class FacebookKeyserver extends Keyserver {
+
+ private static final String FB_KEY_URL_FORMAT
+ = "https://www.facebook.com/%s/publickey/download";
+ private static final String FB_HOST = "facebook.com";
+ private static final String FB_HOST_WWW = "www." + FB_HOST;
+
+ public static final String FB_URL = "https://" + FB_HOST_WWW;
+
+ public static final String ORIGIN = FB_URL;
+
+ private final Proxy mProxy;
+
+ public FacebookKeyserver(Proxy proxy) {
+ mProxy = proxy;
+ }
+
+ @Override
+ public List<ImportKeysListEntry> search(String fbUsername)
+ throws QueryFailedException, QueryNeedsRepairException {
+ List<ImportKeysListEntry> entry = new ArrayList<>(1);
+
+ String data = get(fbUsername);
+ // if we're here that means key retrieval succeeded,
+ // would have thrown an exception otherwise
+ try {
+ UncachedKeyRing keyRing = UncachedKeyRing.decodeFromData(data.getBytes());
+ try {
+ entry.add(getEntry(keyRing, fbUsername));
+ } catch (UnsupportedOperationException e) {
+ Log.e(Constants.TAG, "Parsing retrieved Facebook key failed!");
+ }
+ } catch (PgpGeneralException | IOException e) {
+ Log.e(Constants.TAG, "Failed parsing key from Facebook during search", e);
+ throw new QueryFailedException("No valid key found on Facebook");
+ }
+ return entry;
+ }
+
+ @Override
+ public String get(String fbUsername) throws QueryFailedException {
+ Log.d(Constants.TAG, "FacebookKeyserver get: " + fbUsername + " using Proxy: " + mProxy);
+
+ String data = query(fbUsername);
+
+ if (data == null) {
+ throw new QueryFailedException("data is null");
+ }
+
+ Matcher matcher = PgpHelper.PGP_PUBLIC_KEY.matcher(data);
+ if (matcher.find()) {
+ return matcher.group(1);
+ }
+ throw new QueryFailedException("data is null");
+ }
+
+ private String query(String fbUsername) throws QueryFailedException {
+ try {
+ String request = String.format(FB_KEY_URL_FORMAT, fbUsername);
+ Log.d(Constants.TAG, "fetching from Facebook with: " + request + " proxy: " + mProxy);
+
+ OkHttpClient client = new OkHttpClient();
+ client.setProxy(mProxy);
+
+ URL url = new URL(request);
+
+ Response response = client.newCall(new Request.Builder().url(url).build()).execute();
+
+ // contains body both in case of success or failure
+ String responseBody = response.body().string();
+
+ if (response.isSuccessful()) {
+ return responseBody;
+ } else {
+ // probably a 404 indicating that the key does not exist
+ throw new QueryFailedException("key for " + fbUsername + " not found on Facebook");
+ }
+
+ } catch (IOException e) {
+ Log.e(Constants.TAG, "IOException at Facebook key download", e);
+ throw new QueryFailedException("Cannot connect to Facebook. "
+ + "Check your Internet connection!"
+ + (mProxy == Proxy.NO_PROXY ? "" : " Using proxy " + mProxy));
+ }
+ }
+
+ @Override
+ public void add(String armoredKey) throws AddKeyException {
+ // Implementing will require usage of FB API
+ throw new UnsupportedOperationException("Uploading keys not supported yet");
+ }
+
+ /**
+ * Facebook returns the entire key even during our searching phase.
+ *
+ * @throws UnsupportedOperationException if the key could not be parsed
+ */
+ @NonNull
+ public static ImportKeysListEntry getEntry(UncachedKeyRing ring, String fbUsername)
+ throws UnsupportedOperationException {
+ ImportKeysListEntry entry = new ImportKeysListEntry();
+ entry.setSecretKey(false); // keys imported from Facebook must be public
+ entry.addOrigin(ORIGIN);
+
+ // so we can query for the Facebook username directly, and to identify the source to
+ // download the key from
+ entry.setFbUsername(fbUsername);
+
+ UncachedPublicKey key = ring.getPublicKey();
+
+ entry.setPrimaryUserId(key.getPrimaryUserIdWithFallback());
+ entry.setUserIds(key.getUnorderedUserIds());
+ entry.updateMergedUserIds();
+
+ entry.setPrimaryUserId(key.getPrimaryUserIdWithFallback());
+
+ entry.setKeyId(key.getKeyId());
+ entry.setKeyIdHex(KeyFormattingUtils.convertKeyIdToHex(key.getKeyId()));
+
+ entry.setFingerprintHex(KeyFormattingUtils.convertFingerprintToHex(key.getFingerprint()));
+
+
+ try {
+ if (key.isEC()) { // unsupported key format (ECDH or ECDSA)
+ Log.e(Constants.TAG, "ECDH/ECDSA key - not supported.");
+ throw new UnsupportedOperationException(
+ "ECDH/ECDSA keys not supported yet");
+ }
+ entry.setBitStrength(key.getBitStrength());
+ final int algorithm = key.getAlgorithm();
+ entry.setAlgorithm(KeyFormattingUtils.getAlgorithmInfo(algorithm, key.getBitStrength(),
+ key.getCurveOid()));
+ } catch (NumberFormatException | NullPointerException e) {
+ Log.e(Constants.TAG, "Conversion for bit size, algorithm, or creation date failed.", e);
+ // can't use this key
+ throw new UnsupportedOperationException(
+ "Conversion for bit size, algorithm, or creation date failed.");
+ }
+
+ return entry;
+ }
+
+ public static String getUsernameFromUri(Uri uri) {
+ // path pattern is /username/publickey/download
+ return uri.getPathSegments().get(0);
+ }
+
+ public static boolean isFacebookHost(Uri uri) {
+ String host = uri.getHost();
+ return host.equalsIgnoreCase(FB_HOST) || host.equalsIgnoreCase(FB_HOST_WWW);
+ }
+}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/ImportKeysList.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/ImportKeysList.java
index 03439228b..75a219191 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/ImportKeysList.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/ImportKeysList.java
@@ -77,9 +77,15 @@ public class ImportKeysList extends ArrayList<ImportKeysListEntry> {
for (String origin : incoming.getOrigins()) {
existing.addOrigin(origin);
- // to work properly, Keybase-sourced entries need to pass along the extra
- if (KeybaseKeyserver.ORIGIN.equals(origin)) {
- existing.setExtraData(incoming.getExtraData());
+ // to work properly, Keybase-sourced/Facebook-sourced entries need to pass along the
+ // identifying name/id
+ if (incoming.getKeybaseName() != null) {
+ existing.setKeybaseName(incoming.getKeybaseName());
+ // one of the origins is not a HKP keyserver
+ incomingFromHkpServer = false;
+ }
+ if (incoming.getFbUsername() != null) {
+ existing.setFbUsername(incoming.getFbUsername());
// one of the origins is not a HKP keyserver
incomingFromHkpServer = false;
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/ImportKeysListEntry.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/ImportKeysListEntry.java
index bb86d272f..b3cf70c9f 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/ImportKeysListEntry.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/ImportKeysListEntry.java
@@ -49,7 +49,8 @@ public class ImportKeysListEntry implements Serializable, Parcelable {
private String mAlgorithm;
private boolean mSecretKey;
private String mPrimaryUserId;
- private String mExtraData;
+ private String mKeybaseName;
+ private String mFbUsername;
private String mQuery;
private ArrayList<String> mOrigins;
private Integer mHashCode = null;
@@ -81,7 +82,8 @@ public class ImportKeysListEntry implements Serializable, Parcelable {
dest.writeString(mAlgorithm);
dest.writeByte((byte) (mSecretKey ? 1 : 0));
dest.writeByte((byte) (mSelected ? 1 : 0));
- dest.writeString(mExtraData);
+ dest.writeString(mKeybaseName);
+ dest.writeString(mFbUsername);
dest.writeStringList(mOrigins);
}
@@ -102,7 +104,8 @@ public class ImportKeysListEntry implements Serializable, Parcelable {
vr.mAlgorithm = source.readString();
vr.mSecretKey = source.readByte() == 1;
vr.mSelected = source.readByte() == 1;
- vr.mExtraData = source.readString();
+ vr.mKeybaseName = source.readString();
+ vr.mFbUsername = source.readString();
vr.mOrigins = new ArrayList<>();
source.readStringList(vr.mOrigins);
@@ -229,12 +232,20 @@ public class ImportKeysListEntry implements Serializable, Parcelable {
mPrimaryUserId = uid;
}
- public String getExtraData() {
- return mExtraData;
+ public String getKeybaseName() {
+ return mKeybaseName;
}
- public void setExtraData(String extraData) {
- mExtraData = extraData;
+ public String getFbUsername() {
+ return mFbUsername;
+ }
+
+ public void setKeybaseName(String keybaseName) {
+ mKeybaseName = keybaseName;
+ }
+
+ public void setFbUsername(String fbUsername) {
+ mFbUsername = fbUsername;
}
public String getQuery() {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/KeybaseKeyserver.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/KeybaseKeyserver.java
index e4cd6738b..9243926df 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/KeybaseKeyserver.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/KeybaseKeyserver.java
@@ -81,8 +81,9 @@ public class KeybaseKeyserver extends Keyserver {
entry.setFingerprintHex(fingerprint);
entry.setKeyIdHex("0x" + match.getKeyID());
- // store extra info, so we can query for the keybase id directly
- entry.setExtraData(username);
+ // so we can query for the keybase id directly, and to identify the location from which the
+ // key is to be retrieved
+ entry.setKeybaseName(username);
final int bitStrength = match.getBitStrength();
entry.setBitStrength(bitStrength);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/Keyserver.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/Keyserver.java
index 00e8d6ac5..53e71f7a1 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/Keyserver.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/Keyserver.java
@@ -21,7 +21,6 @@ package org.sufficientlysecure.keychain.keyimport;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.net.Proxy;
import java.util.List;
public abstract class Keyserver {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/ParcelableKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/ParcelableKeyRing.java
index 6f6c816ea..a94ce0dce 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/ParcelableKeyRing.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/ParcelableKeyRing.java
@@ -32,24 +32,39 @@ public class ParcelableKeyRing implements Parcelable {
public final String mExpectedFingerprint;
public final String mKeyIdHex;
public final String mKeybaseName;
+ public final String mFbUsername;
public ParcelableKeyRing(byte[] bytes) {
+ this(null, bytes, false);
+ }
+
+ /**
+ * @param disAmbiguator useless parameter intended to distinguish this overloaded constructor
+ * for when null is passed as first two arguments
+ */
+ public ParcelableKeyRing(String expectedFingerprint, byte[] bytes, boolean disAmbiguator) {
mBytes = bytes;
- mExpectedFingerprint = null;
+ mExpectedFingerprint = expectedFingerprint;
mKeyIdHex = null;
mKeybaseName = null;
+ mFbUsername = null;
}
- public ParcelableKeyRing(String expectedFingerprint, byte[] bytes) {
- mBytes = bytes;
+
+ public ParcelableKeyRing(String expectedFingerprint, String keyIdHex) {
+ mBytes = null;
mExpectedFingerprint = expectedFingerprint;
- mKeyIdHex = null;
+ mKeyIdHex = keyIdHex;
mKeybaseName = null;
+ mFbUsername = null;
}
- public ParcelableKeyRing(String expectedFingerprint, String keyIdHex, String keybaseName) {
+
+ public ParcelableKeyRing(String expectedFingerprint, String keyIdHex, String keybaseName,
+ String fbUsername) {
mBytes = null;
mExpectedFingerprint = expectedFingerprint;
mKeyIdHex = keyIdHex;
mKeybaseName = keybaseName;
+ mFbUsername = fbUsername;
}
private ParcelableKeyRing(Parcel source) {
@@ -58,6 +73,7 @@ public class ParcelableKeyRing implements Parcelable {
mExpectedFingerprint = source.readString();
mKeyIdHex = source.readString();
mKeybaseName = source.readString();
+ mFbUsername = source.readString();
}
public void writeToParcel(Parcel dest, int flags) {
@@ -65,6 +81,7 @@ public class ParcelableKeyRing implements Parcelable {
dest.writeString(mExpectedFingerprint);
dest.writeString(mKeyIdHex);
dest.writeString(mKeybaseName);
+ dest.writeString(mFbUsername);
}
public static final Creator<ParcelableKeyRing> CREATOR = new Creator<ParcelableKeyRing>() {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/BenchmarkOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/BenchmarkOperation.java
index f6e157c74..988a3d16e 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/BenchmarkOperation.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/BenchmarkOperation.java
@@ -41,6 +41,8 @@ import org.sufficientlysecure.keychain.operations.results.OperationResult.Operat
import org.sufficientlysecure.keychain.operations.results.SignEncryptResult;
import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyInputParcel;
import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyOperation;
+import org.sufficientlysecure.keychain.pgp.PgpSecurityConstants;
+import org.sufficientlysecure.keychain.pgp.PgpSecurityConstants.OpenKeychainSymmetricKeyAlgorithmTags;
import org.sufficientlysecure.keychain.pgp.Progressable;
import org.sufficientlysecure.keychain.pgp.SignEncryptParcel;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
@@ -66,7 +68,7 @@ public class BenchmarkOperation extends BaseOperation<BenchmarkInputParcel> {
log.add(LogType.MSG_BENCH, 0);
// random data
- byte[] buf = new byte[1024*1024*5];
+ byte[] buf = new byte[1024*1024*10];
new Random().nextBytes(buf);
Passphrase passphrase = new Passphrase("a");
@@ -83,6 +85,7 @@ public class BenchmarkOperation extends BaseOperation<BenchmarkInputParcel> {
new ProgressScaler(mProgressable, i*(50/numRepeats), (i+1)*(50/numRepeats), 100), mCancelled);
SignEncryptParcel input = new SignEncryptParcel();
input.setSymmetricPassphrase(passphrase);
+ input.setSymmetricEncryptionAlgorithm(OpenKeychainSymmetricKeyAlgorithmTags.AES_128);
input.setBytes(buf);
encryptResult = op.execute(input, new CryptoInputParcel());
log.add(encryptResult, 1);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ImportOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ImportOperation.java
index 70288123f..a20181a00 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ImportOperation.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ImportOperation.java
@@ -38,6 +38,7 @@ import android.support.annotation.NonNull;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.keyimport.FacebookKeyserver;
import org.sufficientlysecure.keychain.keyimport.HkpKeyserver;
import org.sufficientlysecure.keychain.keyimport.KeybaseKeyserver;
import org.sufficientlysecure.keychain.keyimport.Keyserver;
@@ -156,6 +157,7 @@ public class ImportOperation extends BaseOperation<ImportKeyringParcel> {
double progSteps = 100.0 / num;
KeybaseKeyserver keybaseServer = null;
+ FacebookKeyserver facebookServer = null;
HkpKeyserver keyServer = null;
// iterate over all entries
@@ -228,6 +230,12 @@ public class ImportOperation extends BaseOperation<ImportKeyringParcel> {
byte[] data = keybaseServer.get(entry.mKeybaseName).getBytes();
UncachedKeyRing keybaseKey = UncachedKeyRing.decodeFromData(data);
+ if (keybaseKey != null) {
+ log.add(LogType.MSG_IMPORT_FETCH_KEYSERVER_OK, 3);
+ } else {
+ log.add(LogType.MSG_IMPORT_FETCH_ERROR_DECODE, 3);
+ }
+
// If there already is a key, merge the two
if (key != null && keybaseKey != null) {
log.add(LogType.MSG_IMPORT_MERGE, 3);
@@ -247,6 +255,44 @@ public class ImportOperation extends BaseOperation<ImportKeyringParcel> {
log.add(LogType.MSG_IMPORT_FETCH_ERROR_KEYSERVER, 3, e.getMessage());
}
}
+
+ // if the key is from Facebook, fetch from there
+ if (entry.mFbUsername != null) {
+ // Make sure we have this cached
+ if (facebookServer == null) {
+ facebookServer = new FacebookKeyserver(proxy);
+ }
+
+ try {
+ log.add(LogType.MSG_IMPORT_FETCH_FACEBOOK, 2, entry.mFbUsername);
+ byte[] data = facebookServer.get(entry.mFbUsername).getBytes();
+ UncachedKeyRing facebookKey = UncachedKeyRing.decodeFromData(data);
+
+ if (facebookKey != null) {
+ log.add(LogType.MSG_IMPORT_FETCH_KEYSERVER_OK, 3);
+ } else {
+ log.add(LogType.MSG_IMPORT_FETCH_ERROR_DECODE, 3);
+ }
+
+ // If there already is a key, merge the two
+ if (key != null && facebookKey != null) {
+ log.add(LogType.MSG_IMPORT_MERGE, 3);
+ facebookKey = key.merge(facebookKey, log, 4);
+ // If the merge didn't fail, use the new merged key
+ if (facebookKey != null) {
+ key = facebookKey;
+ } else {
+ log.add(LogType.MSG_IMPORT_MERGE_ERROR, 4);
+ }
+ } else if (facebookKey != null) {
+ key = facebookKey;
+ }
+ } catch (Keyserver.QueryFailedException e) {
+ // download failed, too bad. just proceed
+ Log.e(Constants.TAG, "query failed", e);
+ log.add(LogType.MSG_IMPORT_FETCH_ERROR_KEYSERVER, 3, e.getMessage());
+ }
+ }
}
if (key == null) {
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 3f90a08c2..ed2123987 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
@@ -233,6 +233,18 @@ public abstract class OperationResult implements Parcelable {
dest.writeParcelable(mSubResult, 0);
}
+ public static final Parcelable.Creator<SubLogEntryParcel> CREATOR = new Parcelable.Creator<SubLogEntryParcel>() {
+ @Override
+ public SubLogEntryParcel createFromParcel(Parcel in) {
+ return new SubLogEntryParcel(in);
+ }
+
+ @Override
+ public SubLogEntryParcel[] newArray(int size) {
+ return new SubLogEntryParcel[size];
+ }
+ };
+
@Override
StringBuilder getPrintableLogEntry(Resources resources, int indent) {
@@ -757,6 +769,7 @@ public abstract class OperationResult implements Parcelable {
MSG_IMPORT_FETCH_ERROR_KEYSERVER(LogLevel.ERROR, R.string.msg_import_fetch_error_keyserver),
MSG_IMPORT_FETCH_ERROR_KEYSERVER_SECRET (LogLevel.ERROR, R.string.msg_import_fetch_error_keyserver_secret),
MSG_IMPORT_FETCH_KEYBASE (LogLevel.INFO, R.string.msg_import_fetch_keybase),
+ MSG_IMPORT_FETCH_FACEBOOK (LogLevel.INFO, R.string.msg_import_fetch_facebook),
MSG_IMPORT_FETCH_KEYSERVER (LogLevel.INFO, R.string.msg_import_fetch_keyserver),
MSG_IMPORT_FETCH_KEYSERVER_OK (LogLevel.DEBUG, R.string.msg_import_fetch_keyserver_ok),
MSG_IMPORT_KEYSERVER (LogLevel.DEBUG, R.string.msg_import_keyserver),
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/PgpSignEncryptResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/PgpSignEncryptResult.java
index 12b091e32..c4f66b950 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/PgpSignEncryptResult.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/PgpSignEncryptResult.java
@@ -27,6 +27,9 @@ public class PgpSignEncryptResult extends InputPendingResult {
byte[] mDetachedSignature;
public long mOperationTime;
+ // this is the micalg parameter used in PGP/MIME, see RFC3156:
+ // https://tools.ietf.org/html/rfc3156#section-5
+ private String mMicAlgDigestName;
public void setDetachedSignature(byte[] detachedSignature) {
mDetachedSignature = detachedSignature;
@@ -74,4 +77,11 @@ public class PgpSignEncryptResult extends InputPendingResult {
}
};
+ public void setMicAlgDigestName(String micAlgDigestName) {
+ mMicAlgDigestName = micAlgDigestName;
+ }
+
+ public String getMicAlgDigestName() {
+ return mMicAlgDigestName;
+ }
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java
index 45641b33a..40d6a710b 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java
@@ -32,6 +32,7 @@ import org.spongycastle.openpgp.PGPException;
import org.spongycastle.openpgp.PGPLiteralData;
import org.spongycastle.openpgp.PGPLiteralDataGenerator;
import org.spongycastle.openpgp.PGPSignatureGenerator;
+import org.spongycastle.openpgp.PGPUtil;
import org.spongycastle.openpgp.operator.jcajce.JcePBEKeyEncryptionMethodGenerator;
import org.spongycastle.openpgp.operator.jcajce.JcePGPDataEncryptorBuilder;
import org.spongycastle.openpgp.operator.jcajce.NfcSyncPGPContentSignerBuilder;
@@ -574,6 +575,13 @@ public class PgpSignEncryptOperation extends BaseOperation {
// silently catch
}
result.setDetachedSignature(detachedByteOut.toByteArray());
+ try {
+ String digestName = PGPUtil.getDigestName(input.getSignatureHashAlgorithm());
+ // construct micalg parameter according to https://tools.ietf.org/html/rfc3156#section-5
+ result.setMicAlgDigestName("pgp-" + digestName.toLowerCase());
+ } catch (PGPException e) {
+ Log.e(Constants.TAG, "error setting micalg parameter!", e);
+ }
}
return result;
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java
index 5f48e44bd..a6d505763 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java
@@ -327,6 +327,7 @@ public class OpenPgpService extends Service {
Intent result = new Intent();
if (pgpResult.getDetachedSignature() != null && !cleartextSign) {
result.putExtra(OpenPgpApi.RESULT_DETACHED_SIGNATURE, pgpResult.getDetachedSignature());
+ result.putExtra(OpenPgpApi.RESULT_SIGNATURE_MICALG, pgpResult.getMicAlgDigestName());
}
result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_SUCCESS);
return result;
@@ -573,18 +574,11 @@ public class OpenPgpService extends Service {
// case RESULT_NOT_ENCRYPTED, but a signature, fallback to deprecated signatureOnly variable
if (decryptionResult.getResult() == OpenPgpDecryptionResult.RESULT_NOT_ENCRYPTED
&& signatureResult.getResult() != OpenPgpSignatureResult.RESULT_NO_SIGNATURE) {
- // noinspection deprecation, TODO
+ // noinspection deprecation
signatureResult.setSignatureOnly(true);
}
- // case RESULT_INSECURE, fallback to an error
- if (decryptionResult.getResult() == OpenPgpDecryptionResult.RESULT_INSECURE) {
- Intent resultError = new Intent();
- resultError.putExtra(OpenPgpApi.RESULT_ERROR, new OpenPgpError(OpenPgpError.GENERIC_ERROR,
- "Insecure encryption: An outdated algorithm has been used!"));
- resultError.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR);
- return resultError;
- }
+ // case RESULT_INSECURE, simply accept as a fallback like in previous API versions
// case RESULT_ENCRYPTED
// nothing to do!
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ContactSyncAdapterService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ContactSyncAdapterService.java
index f1b4befe6..2985c2030 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ContactSyncAdapterService.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ContactSyncAdapterService.java
@@ -19,8 +19,6 @@ package org.sufficientlysecure.keychain.service;
import android.accounts.Account;
import android.accounts.AccountManager;
-import android.app.Activity;
-import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.AbstractThreadedSyncAdapter;
@@ -29,18 +27,16 @@ import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.SyncResult;
-import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import android.preference.PreferenceActivity;
import android.provider.ContactsContract;
import android.support.v4.app.NotificationCompat;
-import android.widget.Toast;
+import android.support.v4.app.NotificationManagerCompat;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.ui.SettingsActivity;
-import org.sufficientlysecure.keychain.ui.util.NotificationUtils;
import org.sufficientlysecure.keychain.util.ContactHelper;
import org.sufficientlysecure.keychain.util.Log;
@@ -61,7 +57,7 @@ public class ContactSyncAdapterService extends Service {
final SyncResult syncResult) {
Log.d(Constants.TAG, "Performing a contact sync!");
- ContactHelper.writeKeysToContacts(ContactSyncAdapterService.this);
+ new ContactHelper(ContactSyncAdapterService.this).writeKeysToContacts();
importKeys();
}
@@ -86,14 +82,14 @@ public class ContactSyncAdapterService extends Service {
);
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(ContactSyncAdapterService.this)
+ .setAutoCancel(true)
.setSmallIcon(R.drawable.ic_stat_notify_24dp)
- .setLargeIcon(NotificationUtils.getBitmap(R.mipmap.ic_launcher, getBaseContext()))
+ .setColor(getResources().getColor(R.color.primary))
.setContentTitle(getString(R.string.sync_notification_permission_required_title))
.setContentText(getString(R.string.sync_notification_permission_required_text))
.setContentIntent(resultPendingIntent);
- NotificationManager mNotifyMgr =
- (NotificationManager) ContactSyncAdapterService.this.getSystemService(Activity.NOTIFICATION_SERVICE);
- mNotifyMgr.notify(NOTIFICATION_ID_SYNC_SETTINGS, mBuilder.build());
+ NotificationManagerCompat.from(ContactSyncAdapterService.this)
+ .notify(NOTIFICATION_ID_SYNC_SETTINGS, mBuilder.build());
}
}
@@ -155,22 +151,10 @@ public class ContactSyncAdapterService extends Service {
}
public static void enableContactsSync(Context context) {
- try {
- AccountManager manager = AccountManager.get(context);
- Account[] accounts = manager.getAccountsByType(Constants.ACCOUNT_TYPE);
-
- Account account = new Account(Constants.ACCOUNT_NAME, Constants.ACCOUNT_TYPE);
- if (accounts.length == 0) {
- if (!manager.addAccountExplicitly(account, null, null)) {
- Log.d(Constants.TAG, "account already exists, the account is null, or another error occured");
- }
- }
-
- ContentResolver.setIsSyncable(account, ContactsContract.AUTHORITY, 1);
- ContentResolver.setSyncAutomatically(account, ContactsContract.AUTHORITY, true);
- } catch (SecurityException e) {
- Log.e(Constants.TAG, "SecurityException when adding the account", e);
- Toast.makeText(context, R.string.reinstall_openkeychain, Toast.LENGTH_LONG).show();
- }
+ AccountManager manager = AccountManager.get(context);
+ Account account = manager.getAccountsByType(Constants.ACCOUNT_TYPE)[0];
+
+ ContentResolver.setIsSyncable(account, ContactsContract.AUTHORITY, 1);
+ ContentResolver.setSyncAutomatically(account, ContactsContract.AUTHORITY, true);
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeyserverSyncAdapterService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeyserverSyncAdapterService.java
index fc3224e39..bacf56302 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeyserverSyncAdapterService.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeyserverSyncAdapterService.java
@@ -26,7 +26,6 @@ import android.os.Messenger;
import android.os.PowerManager;
import android.os.SystemClock;
import android.support.v4.app.NotificationCompat;
-import android.widget.Toast;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
@@ -55,7 +54,7 @@ public class KeyserverSyncAdapterService extends Service {
// how often a sync should be initiated, in s
public static final long SYNC_INTERVAL =
Constants.DEBUG_KEYSERVER_SYNC
- ? TimeUnit.MINUTES.toSeconds(2) : TimeUnit.DAYS.toSeconds(3);
+ ? TimeUnit.MINUTES.toSeconds(1) : TimeUnit.DAYS.toSeconds(3);
// time since last update after which a key should be updated again, in s
public static final long KEY_UPDATE_LIMIT =
Constants.DEBUG_KEYSERVER_SYNC ? 1 : TimeUnit.DAYS.toSeconds(7);
@@ -82,6 +81,12 @@ public class KeyserverSyncAdapterService extends Service {
// introduced due to https://github.com/open-keychain/open-keychain/issues/1573
return START_NOT_STICKY; // we can't act on this Intent and don't want it redelivered
}
+
+ if (!isSyncEnabled()) {
+ // if we have initiated a sync, but the user disabled it in preferences since
+ return START_NOT_STICKY;
+ }
+
switch (intent.getAction()) {
case ACTION_CANCEL: {
mCancelled.set(true);
@@ -440,7 +445,7 @@ public class KeyserverSyncAdapterService extends Service {
String hexKeyId = KeyFormattingUtils
.convertKeyIdToHex(keyId);
// we aren't updating from keybase as of now
- keyList.add(new ParcelableKeyRing(fingerprint, hexKeyId, null));
+ keyList.add(new ParcelableKeyRing(fingerprint, hexKeyId));
}
keyCursor.close();
@@ -505,30 +510,24 @@ public class KeyserverSyncAdapterService extends Service {
}
public static void enableKeyserverSync(Context context) {
- try {
- AccountManager manager = AccountManager.get(context);
- Account[] accounts = manager.getAccountsByType(Constants.ACCOUNT_TYPE);
-
- Account account = new Account(Constants.ACCOUNT_NAME, Constants.ACCOUNT_TYPE);
- if (accounts.length == 0) {
- if (!manager.addAccountExplicitly(account, null, null)) {
- Log.d(Constants.TAG, "account already exists, the account is null, or another error occured");
- }
- }
- // for keyserver sync
- ContentResolver.setIsSyncable(account, Constants.PROVIDER_AUTHORITY, 1);
- ContentResolver.setSyncAutomatically(account, Constants.PROVIDER_AUTHORITY,
- true);
- ContentResolver.addPeriodicSync(
- account,
- Constants.PROVIDER_AUTHORITY,
- new Bundle(),
- SYNC_INTERVAL
- );
- } catch (SecurityException e) {
- Log.e(Constants.TAG, "SecurityException when adding the account", e);
- Toast.makeText(context, R.string.reinstall_openkeychain, Toast.LENGTH_LONG).show();
- }
+ AccountManager manager = AccountManager.get(context);
+ Account account = manager.getAccountsByType(Constants.ACCOUNT_TYPE)[0];
+
+ ContentResolver.setIsSyncable(account, Constants.PROVIDER_AUTHORITY, 1);
+ ContentResolver.setSyncAutomatically(account, Constants.PROVIDER_AUTHORITY, true);
+ ContentResolver.addPeriodicSync(
+ account,
+ Constants.PROVIDER_AUTHORITY,
+ new Bundle(),
+ SYNC_INTERVAL
+ );
+ }
+
+ private boolean isSyncEnabled() {
+ AccountManager manager = AccountManager.get(this);
+ Account account = manager.getAccountsByType(Constants.ACCOUNT_TYPE)[0];
+
+ return ContentResolver.getSyncAutomatically(account, Constants.PROVIDER_AUTHORITY);
}
private void startServiceWithUpdateAll() {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java
index 67c295b6d..73da3aff9 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java
@@ -18,8 +18,6 @@
package org.sufficientlysecure.keychain.service;
-import java.util.Date;
-
import android.app.AlarmManager;
import android.app.Notification;
import android.app.PendingIntent;
@@ -44,11 +42,12 @@ import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey.SecretKeyType;
import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
-import org.sufficientlysecure.keychain.ui.util.NotificationUtils;
import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.Passphrase;
import org.sufficientlysecure.keychain.util.Preferences;
+import java.util.Date;
+
/**
* This service runs in its own process, but is available to all other processes as the main
* passphrase cache. Use the static methods addCachedPassphrase and getCachedPassphrase for
@@ -473,7 +472,7 @@ public class PassphraseCacheService extends Service {
private Notification getNotification() {
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setSmallIcon(R.drawable.ic_stat_notify_24dp)
- .setLargeIcon(NotificationUtils.getBitmap(R.mipmap.ic_launcher, getBaseContext()))
+ .setColor(getResources().getColor(R.color.primary))
.setContentTitle(getResources().getQuantityString(R.plurals.passp_cache_notif_n_keys,
mPassphraseCache.size(), mPassphraseCache.size()))
.setContentText(getString(R.string.passp_cache_notif_touch_to_clear));
@@ -504,7 +503,7 @@ public class PassphraseCacheService extends Service {
// Add clear PI action below text
builder.addAction(
- R.drawable.abc_ic_clear_mtrl_alpha,
+ R.drawable.ic_close_white_24dp,
getString(R.string.passp_cache_notif_clear),
clearCachePi
);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateYubiKeyImportResetFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateYubiKeyImportResetFragment.java
index 0a2d52617..5712f4452 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateYubiKeyImportResetFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateYubiKeyImportResetFragment.java
@@ -218,15 +218,10 @@ public class CreateYubiKeyImportResetFragment
public void importKey() {
ArrayList<ParcelableKeyRing> keyList = new ArrayList<>();
- keyList.add(new ParcelableKeyRing(mNfcFingerprint, null, null));
+ keyList.add(new ParcelableKeyRing(mNfcFingerprint, null));
mKeyList = keyList;
- {
- Preferences prefs = Preferences.getPreferences(getActivity());
- Preferences.CloudSearchPrefs cloudPrefs =
- new Preferences.CloudSearchPrefs(true, true, prefs.getPreferredKeyserver());
- mKeyserver = cloudPrefs.keyserver;
- }
+ mKeyserver = Preferences.getPreferences(getActivity()).getPreferredKeyserver();
super.setProgressMessageResource(R.string.progress_importing);
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 37dd6afad..351b62ba7 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java
@@ -138,16 +138,11 @@ public abstract class DecryptFragment extends Fragment implements LoaderManager.
final String keyserver;
// search config
- {
- Preferences prefs = Preferences.getPreferences(getActivity());
- Preferences.CloudSearchPrefs cloudPrefs =
- new Preferences.CloudSearchPrefs(true, true, prefs.getPreferredKeyserver());
- keyserver = cloudPrefs.keyserver;
- }
+ keyserver = Preferences.getPreferences(getActivity()).getPreferredKeyserver();
{
ParcelableKeyRing keyEntry = new ParcelableKeyRing(null,
- KeyFormattingUtils.convertKeyIdToHex(unknownKeyId), null);
+ KeyFormattingUtils.convertKeyIdToHex(unknownKeyId));
ArrayList<ParcelableKeyRing> selectedEntries = new ArrayList<>();
selectedEntries.add(keyEntry);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptListFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptListFragment.java
index 922dd7307..9419cf8ce 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptListFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptListFragment.java
@@ -18,7 +18,6 @@
package org.sufficientlysecure.keychain.ui;
-import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
@@ -746,16 +745,11 @@ public class DecryptListFragment
final String keyserver;
// search config
- {
- Preferences prefs = Preferences.getPreferences(getActivity());
- Preferences.CloudSearchPrefs cloudPrefs =
- new Preferences.CloudSearchPrefs(true, true, prefs.getPreferredKeyserver());
- keyserver = cloudPrefs.keyserver;
- }
+ keyserver = Preferences.getPreferences(getActivity()).getPreferredKeyserver();
{
ParcelableKeyRing keyEntry = new ParcelableKeyRing(null,
- KeyFormattingUtils.convertKeyIdToHex(unknownKeyId), null);
+ KeyFormattingUtils.convertKeyIdToHex(unknownKeyId));
ArrayList<ParcelableKeyRing> selectedEntries = new ArrayList<>();
selectedEntries.add(keyEntry);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java
index 7f7532ddf..c54f55b6f 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java
@@ -30,6 +30,7 @@ import android.view.ViewGroup;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.intents.OpenKeychainIntents;
+import org.sufficientlysecure.keychain.keyimport.FacebookKeyserver;
import org.sufficientlysecure.keychain.keyimport.ImportKeysListEntry;
import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing;
import org.sufficientlysecure.keychain.operations.results.ImportKeyResult;
@@ -41,6 +42,7 @@ import org.sufficientlysecure.keychain.ui.util.Notify;
import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.ParcelableFileCache;
import org.sufficientlysecure.keychain.util.ParcelableFileCache.IteratorWithSize;
+import org.sufficientlysecure.keychain.util.Preferences;
import java.io.IOException;
import java.util.ArrayList;
@@ -50,6 +52,8 @@ public class ImportKeysActivity extends BaseNfcActivity
public static final String ACTION_IMPORT_KEY = OpenKeychainIntents.IMPORT_KEY;
public static final String ACTION_IMPORT_KEY_FROM_KEYSERVER = OpenKeychainIntents.IMPORT_KEY_FROM_KEYSERVER;
+ public static final String ACTION_IMPORT_KEY_FROM_FACEBOOK
+ = Constants.INTENT_PREFIX + "IMPORT_KEY_FROM_FACEBOOK";
public static final String ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN_RESULT =
Constants.INTENT_PREFIX + "IMPORT_KEY_FROM_KEY_SERVER_AND_RETURN_RESULT";
public static final String ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN_TO_SERVICE = Constants.INTENT_PREFIX
@@ -101,11 +105,6 @@ public class ImportKeysActivity extends BaseNfcActivity
if (getIntent().hasExtra(EXTRA_PENDING_INTENT_DATA)) {
mPendingIntentData = getIntent().getParcelableExtra(EXTRA_PENDING_INTENT_DATA);
}
-
- // if we aren't being restored, initialize fragments
- if (savedInstanceState == null) {
- handleActions(getIntent());
- }
}
@Override
@@ -113,6 +112,18 @@ public class ImportKeysActivity extends BaseNfcActivity
setContentView(R.layout.import_keys_activity);
}
+ @Override
+ public void onNewIntent(Intent intent) {
+ super.onNewIntent(intent);
+ setIntent(intent);
+ }
+
+ @Override
+ protected void onResumeFragments() {
+ super.onResumeFragments();
+ handleActions(getIntent());
+ }
+
protected void handleActions(Intent intent) {
String action = intent.getAction();
Bundle extras = intent.getExtras();
@@ -124,7 +135,9 @@ public class ImportKeysActivity extends BaseNfcActivity
}
if (Intent.ACTION_VIEW.equals(action)) {
- if ("http".equals(scheme) || "https".equals(scheme)) {
+ if (FacebookKeyserver.isFacebookHost(dataUri)) {
+ action = ACTION_IMPORT_KEY_FROM_FACEBOOK;
+ } else if ("http".equals(scheme) || "https".equals(scheme)) {
action = ACTION_SEARCH_KEYSERVER_FROM_URL;
} else {
// Android's Action when opening file associated to Keychain (see AndroidManifest.xml)
@@ -205,26 +218,31 @@ public class ImportKeysActivity extends BaseNfcActivity
}
break;
}
+ case ACTION_IMPORT_KEY_FROM_FACEBOOK: {
+ String fbUsername = FacebookKeyserver.getUsernameFromUri(dataUri);
+
+ Preferences.CloudSearchPrefs cloudSearchPrefs =
+ new Preferences.CloudSearchPrefs(false, true, true, null);
+ // we allow our users to edit the query if they wish
+ startTopCloudFragment(fbUsername, false, cloudSearchPrefs);
+ // search immediately
+ startListFragment(null, null, fbUsername, cloudSearchPrefs);
+ break;
+ }
case ACTION_SEARCH_KEYSERVER_FROM_URL: {
// need to process URL to get search query and keyserver authority
String query = dataUri.getQueryParameter("search");
- String keyserver = dataUri.getAuthority();
// if query not specified, we still allow users to search the keyserver in the link
if (query == null) {
Notify.create(this, R.string.import_url_warn_no_search_parameter, Notify.LENGTH_INDEFINITE,
Notify.Style.WARN).show();
- // we just set the keyserver
- startTopCloudFragment(null, false, keyserver);
- // we don't set the keyserver for ImportKeysListFragment since
- // it'll be set in the cloudSearchPrefs of ImportKeysCloudFragment
- // which is used when the user clicks on the search button
- startListFragment(null, null, null, null);
- } else {
- // we allow our users to edit the query if they wish
- startTopCloudFragment(query, false, keyserver);
- // search immediately
- startListFragment(null, null, query, keyserver);
}
+ Preferences.CloudSearchPrefs cloudSearchPrefs = new Preferences.CloudSearchPrefs(
+ true, true, true, dataUri.getAuthority());
+ // we allow our users to edit the query if they wish
+ startTopCloudFragment(query, false, cloudSearchPrefs);
+ // search immediately (if query is not null)
+ startListFragment(null, null, query, cloudSearchPrefs);
break;
}
case ACTION_IMPORT_KEY_FROM_FILE:
@@ -254,18 +272,21 @@ public class ImportKeysActivity extends BaseNfcActivity
}
/**
- * if the fragment is started with non-null bytes/dataUri/serverQuery, it will immediately
- * load content
+ * Shows the list of keys to be imported.
+ * If the fragment is started with non-null bytes/dataUri/serverQuery, it will immediately
+ * load content.
*
- * @param bytes bytes containing list of keyrings to import
- * @param dataUri uri to file to import keyrings from
- * @param serverQuery query to search for on the keyserver
- * @param keyserver keyserver authority to search on. If null will use keyserver from
- * user preferences
+ * @param bytes bytes containing list of keyrings to import
+ * @param dataUri uri to file to import keyrings from
+ * @param serverQuery query to search for on the keyserver
+ * @param cloudSearchPrefs search specifications to use. If null will retrieve from user's
+ * preferences.
*/
- private void startListFragment(byte[] bytes, Uri dataUri, String serverQuery, String keyserver) {
+ private void startListFragment(byte[] bytes, Uri dataUri, String serverQuery,
+ Preferences.CloudSearchPrefs cloudSearchPrefs) {
Fragment listFragment =
- ImportKeysListFragment.newInstance(bytes, dataUri, serverQuery, false, keyserver);
+ ImportKeysListFragment.newInstance(bytes, dataUri, serverQuery, false,
+ cloudSearchPrefs);
getSupportFragmentManager().beginTransaction()
.replace(R.id.import_keys_list_container, listFragment, TAG_FRAG_LIST)
.commit();
@@ -283,14 +304,16 @@ public class ImportKeysActivity extends BaseNfcActivity
* loads the CloudFragment, which consists of the search bar, search button and settings icon
* visually.
*
- * @param query search query
- * @param disableQueryEdit if true, user will not be able to edit the search query
- * @param keyserver keyserver authority to use for search, if null will use keyserver
- * specified in user preferences
+ * @param query search query
+ * @param disableQueryEdit if true, user will not be able to edit the search query
+ * @param cloudSearchPrefs keyserver authority to use for search, if null will use keyserver
+ * specified in user preferences
*/
- private void startTopCloudFragment(String query, boolean disableQueryEdit, String keyserver) {
+ private void startTopCloudFragment(String query, boolean disableQueryEdit,
+ Preferences.CloudSearchPrefs cloudSearchPrefs) {
findViewById(R.id.import_keys_top_layout).setVisibility(View.VISIBLE);
- Fragment importCloudFragment = ImportKeysCloudFragment.newInstance(query, disableQueryEdit, keyserver);
+ Fragment importCloudFragment = ImportKeysCloudFragment.newInstance(query, disableQueryEdit,
+ cloudSearchPrefs);
getSupportFragmentManager().beginTransaction()
.replace(R.id.import_keys_top_container, importCloudFragment, TAG_FRAG_TOP)
.commit();
@@ -363,9 +386,8 @@ public class ImportKeysActivity extends BaseNfcActivity
// change the format into ParcelableKeyRing
ArrayList<ImportKeysListEntry> entries = keyListFragment.getSelectedEntries();
for (ImportKeysListEntry entry : entries) {
- keys.add(new ParcelableKeyRing(
- entry.getFingerprintHex(), entry.getKeyIdHex(), entry.getExtraData())
- );
+ keys.add(new ParcelableKeyRing(entry.getFingerprintHex(),
+ entry.getKeyIdHex(), entry.getKeybaseName(), entry.getFbUsername()));
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysCloudFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysCloudFragment.java
index 1cd5c24f3..fb0217cda 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysCloudFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysCloudFragment.java
@@ -42,33 +42,35 @@ import org.sufficientlysecure.keychain.util.Preferences;
import java.util.List;
+/**
+ * Consists of the search bar, search button, and search settings button
+ */
public class ImportKeysCloudFragment extends Fragment {
public static final String ARG_QUERY = "query";
public static final String ARG_DISABLE_QUERY_EDIT = "disable_query_edit";
- public static final String ARG_KEYSERVER = "keyserver";
+ public static final String ARG_CLOUD_SEARCH_PREFS = "cloud_search_prefs";
private ImportKeysActivity mImportActivity;
- private View mSearchButton;
private AutoCompleteTextView mQueryEditText;
- private View mConfigButton;
/**
* Creates new instance of this fragment
*
* @param query query to search for
* @param disableQueryEdit if true, user cannot edit query
- * @param keyserver specified keyserver authority to use. If null, will use keyserver
- * specified in user preferences
+ * @param cloudSearchPrefs search parameters to use. If null will retrieve from user's
+ * preferences.
*/
public static ImportKeysCloudFragment newInstance(String query, boolean disableQueryEdit,
- String keyserver) {
+ Preferences.CloudSearchPrefs
+ cloudSearchPrefs) {
ImportKeysCloudFragment frag = new ImportKeysCloudFragment();
Bundle args = new Bundle();
args.putString(ARG_QUERY, query);
args.putBoolean(ARG_DISABLE_QUERY_EDIT, disableQueryEdit);
- args.putString(ARG_KEYSERVER, keyserver);
+ args.putParcelable(ARG_CLOUD_SEARCH_PREFS, cloudSearchPrefs);
frag.setArguments(args);
@@ -82,12 +84,11 @@ public class ImportKeysCloudFragment extends Fragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.import_keys_cloud_fragment, container, false);
- mSearchButton = view.findViewById(R.id.cloud_import_server_search);
mQueryEditText = (AutoCompleteTextView) view.findViewById(R.id.cloud_import_server_query);
- mConfigButton = view.findViewById(R.id.cloud_import_server_config_button);
- List<String> namesAndEmails = ContactHelper.getContactNames(getActivity());
- namesAndEmails.addAll(ContactHelper.getContactMails(getActivity()));
+ ContactHelper contactHelper = new ContactHelper(getActivity());
+ List<String> namesAndEmails = contactHelper.getContactNames();
+ namesAndEmails.addAll(contactHelper.getContactMails());
mQueryEditText.setThreshold(3);
mQueryEditText.setAdapter(
new ArrayAdapter<>
@@ -96,7 +97,8 @@ public class ImportKeysCloudFragment extends Fragment {
)
);
- mSearchButton.setOnClickListener(new OnClickListener() {
+ View searchButton = view.findViewById(R.id.cloud_import_server_search);
+ searchButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
search(mQueryEditText.getText().toString());
@@ -116,7 +118,8 @@ public class ImportKeysCloudFragment extends Fragment {
}
});
- mConfigButton.setOnClickListener(new OnClickListener() {
+ View configButton = view.findViewById(R.id.cloud_import_server_config_button);
+ configButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(mImportActivity, SettingsActivity.class);
@@ -159,15 +162,14 @@ public class ImportKeysCloudFragment extends Fragment {
}
private void search(String query) {
- Preferences.CloudSearchPrefs cloudSearchPrefs;
- String explicitKeyserver = getArguments().getString(ARG_KEYSERVER);
- // no explicit keyserver passed
- if (explicitKeyserver == null) {
+ Preferences.CloudSearchPrefs cloudSearchPrefs
+ = getArguments().getParcelable(ARG_CLOUD_SEARCH_PREFS);
+
+ // no explicit search preferences passed
+ if (cloudSearchPrefs == null) {
cloudSearchPrefs = Preferences.getPreferences(getActivity()).getCloudSearchPrefs();
- } else {
- // assume we are also meant to search keybase.io
- cloudSearchPrefs = new Preferences.CloudSearchPrefs(true, true, explicitKeyserver);
}
+
mImportActivity.loadCallback(
new ImportKeysListFragment.CloudLoaderState(query, cloudSearchPrefs));
toggleKeyboard(false);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java
index 4955bad6e..b399af950 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java
@@ -65,7 +65,7 @@ public class ImportKeysListFragment extends ListFragment implements
private static final String ARG_BYTES = "bytes";
public static final String ARG_SERVER_QUERY = "query";
public static final String ARG_NON_INTERACTIVE = "non_interactive";
- public static final String ARG_KEYSERVER_URL = "keyserver_url";
+ public static final String ARG_CLOUD_SEARCH_PREFS = "cloud_search_prefs";
private static final int REQUEST_PERMISSION_READ_EXTERNAL_STORAGE = 12;
@@ -140,32 +140,35 @@ public class ImportKeysListFragment extends ListFragment implements
* by dataUri, or searches a keyserver for serverQuery, if parameter is not null, in that order
* Will immediately load data if non-null bytes/dataUri/serverQuery
*
- * @param bytes byte data containing list of keyrings to be imported
- * @param dataUri file from which keyrings are to be imported
- * @param serverQuery query to search for on keyserver
- * @param keyserver if not null, will perform search on specified keyserver. Else, uses
- * keyserver specified in user preferences
+ * @param bytes byte data containing list of keyrings to be imported
+ * @param dataUri file from which keyrings are to be imported
+ * @param serverQuery query to search for on keyserver
+ * @param cloudSearchPrefs search parameters to use. If null will retrieve from user's
+ * preferences.
* @return fragment with arguments set based on passed parameters
*/
public static ImportKeysListFragment newInstance(byte[] bytes, Uri dataUri, String serverQuery,
- String keyserver) {
- return newInstance(bytes, dataUri, serverQuery, false, keyserver);
+ Preferences.CloudSearchPrefs cloudSearchPrefs) {
+ return newInstance(bytes, dataUri, serverQuery, false, cloudSearchPrefs);
}
/**
* Visually consists of a list of keyrings with checkboxes to specify which are to be imported
* Will immediately load data if non-null bytes/dataUri/serverQuery is supplied
*
- * @param bytes byte data containing list of keyrings to be imported
- * @param dataUri file from which keyrings are to be imported
- * @param serverQuery query to search for on keyserver
- * @param nonInteractive if true, users will not be able to check/uncheck items in the list
- * @param keyserver if set, will perform search on specified keyserver. If null, falls back
- * to keyserver specified in user preferences
+ * @param bytes byte data containing list of keyrings to be imported
+ * @param dataUri file from which keyrings are to be imported
+ * @param serverQuery query to search for on keyserver
+ * @param nonInteractive if true, users will not be able to check/uncheck items in the list
+ * @param cloudSearchPrefs search parameters to use. If null will retrieve from user's
+ * preferences.
* @return fragment with arguments set based on passed parameters
*/
- public static ImportKeysListFragment newInstance(byte[] bytes, Uri dataUri, String serverQuery,
- boolean nonInteractive, String keyserver) {
+ public static ImportKeysListFragment newInstance(byte[] bytes,
+ Uri dataUri,
+ String serverQuery,
+ boolean nonInteractive,
+ Preferences.CloudSearchPrefs cloudSearchPrefs) {
ImportKeysListFragment frag = new ImportKeysListFragment();
Bundle args = new Bundle();
@@ -173,7 +176,7 @@ public class ImportKeysListFragment extends ListFragment implements
args.putParcelable(ARG_DATA_URI, dataUri);
args.putString(ARG_SERVER_QUERY, serverQuery);
args.putBoolean(ARG_NON_INTERACTIVE, nonInteractive);
- args.putString(ARG_KEYSERVER_URL, keyserver);
+ args.putParcelable(ARG_CLOUD_SEARCH_PREFS, cloudSearchPrefs);
frag.setArguments(args);
@@ -223,7 +226,6 @@ public class ImportKeysListFragment extends ListFragment implements
Uri dataUri = args.getParcelable(ARG_DATA_URI);
byte[] bytes = args.getByteArray(ARG_BYTES);
String query = args.getString(ARG_SERVER_QUERY);
- String keyserver = args.getString(ARG_KEYSERVER_URL);
mNonInteractive = args.getBoolean(ARG_NON_INTERACTIVE, false);
getListView().setOnTouchListener(new OnTouchListener() {
@@ -241,11 +243,10 @@ public class ImportKeysListFragment extends ListFragment implements
if (dataUri != null || bytes != null) {
mLoaderState = new BytesLoaderState(bytes, dataUri);
} else if (query != null) {
- Preferences.CloudSearchPrefs cloudSearchPrefs;
- if (keyserver == null) {
+ Preferences.CloudSearchPrefs cloudSearchPrefs
+ = args.getParcelable(ARG_CLOUD_SEARCH_PREFS);
+ if (cloudSearchPrefs == null) {
cloudSearchPrefs = Preferences.getPreferences(getActivity()).getCloudSearchPrefs();
- } else {
- cloudSearchPrefs = new Preferences.CloudSearchPrefs(true, true, keyserver);
}
mLoaderState = new CloudLoaderState(query, cloudSearchPrefs);
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 45ce604c3..3969f4039 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysProxyActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysProxyActivity.java
@@ -19,7 +19,6 @@ package org.sufficientlysecure.keychain.ui;
import android.annotation.TargetApi;
import android.content.Intent;
-import android.content.pm.ActivityInfo;
import android.net.Uri;
import android.nfc.NdefMessage;
import android.nfc.NfcAdapter;
@@ -130,7 +129,6 @@ public class ImportKeysProxyActivity extends FragmentActivity
String scannedContent = scanResult.getContents();
processScannedContent(scannedContent);
- return;
}
}
@@ -199,7 +197,7 @@ public class ImportKeysProxyActivity extends FragmentActivity
}
public void importKeys(String fingerprint) {
- ParcelableKeyRing keyEntry = new ParcelableKeyRing(fingerprint, null, null);
+ ParcelableKeyRing keyEntry = new ParcelableKeyRing(fingerprint, null);
ArrayList<ParcelableKeyRing> selectedEntries = new ArrayList<>();
selectedEntries.add(keyEntry);
@@ -209,12 +207,7 @@ public class ImportKeysProxyActivity extends FragmentActivity
private void startImportService(ArrayList<ParcelableKeyRing> keyRings) {
// search config
- {
- Preferences prefs = Preferences.getPreferences(this);
- Preferences.CloudSearchPrefs cloudPrefs =
- new Preferences.CloudSearchPrefs(true, true, prefs.getPreferredKeyserver());
- mKeyserver = cloudPrefs.keyserver;
- }
+ mKeyserver = Preferences.getPreferences(this).getPreferredKeyserver();
mKeyList = keyRings;
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 db31bd0a1..dd8107304 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java
@@ -588,7 +588,7 @@ public class KeyListFragment extends LoaderFragment
while (cursor.moveToNext()) {
byte[] blob = cursor.getBlob(0);//fingerprint column is 0
String fingerprint = KeyFormattingUtils.convertFingerprintToHex(blob);
- ParcelableKeyRing keyEntry = new ParcelableKeyRing(fingerprint, null, null);
+ ParcelableKeyRing keyEntry = new ParcelableKeyRing(fingerprint, null);
keyList.add(keyEntry);
}
mKeyList = keyList;
@@ -597,12 +597,7 @@ public class KeyListFragment extends LoaderFragment
}
// search config
- {
- Preferences prefs = Preferences.getPreferences(getActivity());
- Preferences.CloudSearchPrefs cloudPrefs =
- new Preferences.CloudSearchPrefs(true, true, prefs.getPreferredKeyserver());
- mKeyserver = cloudPrefs.keyserver;
- }
+ mKeyserver = Preferences.getPreferences(getActivity()).getPreferredKeyserver();
mImportOpHelper = new CryptoOperationHelper<>(1, this, this, R.string.progress_updating);
mImportOpHelper.setProgressCancellable(true);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsActivity.java
index 9e962fa0d..cd754d60e 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsActivity.java
@@ -29,11 +29,9 @@ import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
-import android.preference.CheckBoxPreference;
import android.preference.EditTextPreference;
import android.preference.ListPreference;
import android.preference.Preference;
-import android.preference.PreferenceActivity;
import android.preference.PreferenceFragment;
import android.preference.PreferenceScreen;
import android.preference.SwitchPreference;
@@ -115,6 +113,15 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
});
}
+ public static abstract class PresetPreferenceFragment extends PreferenceFragment {
+ @Override
+ public void addPreferencesFromResource(int preferencesResId) {
+ // so that preferences are written to our preference file, not the default
+ Preferences.setPreferenceManagerFileAndMode(this.getPreferenceManager());
+ super.addPreferencesFromResource(preferencesResId);
+ }
+ }
+
@Override
public void onBuildHeaders(List<Header> target) {
super.onBuildHeaders(target);
@@ -124,7 +131,7 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
/**
* This fragment shows the Cloud Search preferences
*/
- public static class CloudSearchPrefsFragment extends PreferenceFragment {
+ public static class CloudSearchPrefsFragment extends PresetPreferenceFragment {
private PreferenceScreen mKeyServerPreference = null;
@@ -149,12 +156,6 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
return false;
}
});
- initializeSearchKeyserver(
- (SwitchPreference) findPreference(Constants.Pref.SEARCH_KEYSERVER)
- );
- initializeSearchKeybase(
- (SwitchPreference) findPreference(Constants.Pref.SEARCH_KEYBASE)
- );
}
@Override
@@ -172,12 +173,20 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
}
}
}
+
+ public static String keyserverSummary(Context context) {
+ String[] servers = sPreferences.getKeyServers();
+ String serverSummary = context.getResources().getQuantityString(
+ R.plurals.n_keyservers, servers.length, servers.length);
+ return serverSummary + "; " + context.getString(R.string.label_preferred) + ": " + sPreferences
+ .getPreferredKeyserver();
+ }
}
/**
* This fragment shows the PIN/password preferences
*/
- public static class PassphrasePrefsFragment extends PreferenceFragment {
+ public static class PassphrasePrefsFragment extends PresetPreferenceFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
@@ -186,18 +195,27 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
// Load the preferences from an XML resource
addPreferencesFromResource(R.xml.passphrase_preferences);
- initializePassphraseCacheSubs(
- (CheckBoxPreference) findPreference(Constants.Pref.PASSPHRASE_CACHE_SUBS));
-
initializePassphraseCacheTtl(
(IntegerListPreference) findPreference(Constants.Pref.PASSPHRASE_CACHE_TTL));
+ }
- initializeUseNumKeypadForYubiKeyPin(
- (CheckBoxPreference) findPreference(Constants.Pref.USE_NUMKEYPAD_FOR_YUBIKEY_PIN));
+ private static void initializePassphraseCacheTtl(
+ final IntegerListPreference passphraseCacheTtl) {
+ passphraseCacheTtl.setValue("" + sPreferences.getPassphraseCacheTtl());
+ passphraseCacheTtl.setSummary(passphraseCacheTtl.getEntry());
+ passphraseCacheTtl
+ .setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ passphraseCacheTtl.setValue(newValue.toString());
+ passphraseCacheTtl.setSummary(passphraseCacheTtl.getEntry());
+ sPreferences.setPassphraseCacheTtl(Integer.parseInt(newValue.toString()));
+ return false;
+ }
+ });
}
}
- public static class ProxyPrefsFragment extends PreferenceFragment {
+ public static class ProxyPrefsFragment extends PresetPreferenceFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
@@ -213,37 +231,18 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
private EditTextPreference mProxyHost;
private EditTextPreference mProxyPort;
private ListPreference mProxyType;
- private PreferenceActivity mActivity;
- private PreferenceFragment mFragment;
+ private PresetPreferenceFragment mFragment;
- public Initializer(PreferenceFragment fragment) {
+ public Initializer(PresetPreferenceFragment fragment) {
mFragment = fragment;
}
- public Initializer(PreferenceActivity activity) {
- mActivity = activity;
- }
-
public Preference automaticallyFindPreference(String key) {
- if (mFragment != null) {
- return mFragment.findPreference(key);
- } else {
- return mActivity.findPreference(key);
- }
+ return mFragment.findPreference(key);
}
public void initialize() {
- // makes android's preference framework write to our file instead of default
- // This allows us to use the "persistent" attribute to simplify code
- if (mFragment != null) {
- Preferences.setPreferenceManagerFileAndMode(mFragment.getPreferenceManager());
- // Load the preferences from an XML resource
- mFragment.addPreferencesFromResource(R.xml.proxy_preferences);
- } else {
- Preferences.setPreferenceManagerFileAndMode(mActivity.getPreferenceManager());
- // Load the preferences from an XML resource
- mActivity.addPreferencesFromResource(R.xml.proxy_preferences);
- }
+ mFragment.addPreferencesFromResource(R.xml.proxy_preferences);
mUseTor = (SwitchPreference) automaticallyFindPreference(Constants.Pref.USE_TOR_PROXY);
mUseNormalProxy = (SwitchPreference) automaticallyFindPreference(Constants.Pref.USE_NORMAL_PROXY);
@@ -268,7 +267,7 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
mUseTor.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
- Activity activity = mFragment != null ? mFragment.getActivity() : mActivity;
+ Activity activity = mFragment.getActivity();
if ((Boolean) newValue) {
boolean installed = OrbotHelper.isOrbotInstalled(activity);
if (!installed) {
@@ -314,7 +313,7 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
mProxyHost.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
- Activity activity = mFragment != null ? mFragment.getActivity() : mActivity;
+ Activity activity = mFragment.getActivity();
if (TextUtils.isEmpty((String) newValue)) {
Notify.create(
activity,
@@ -332,7 +331,7 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
mProxyPort.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
- Activity activity = mFragment != null ? mFragment.getActivity() : mActivity;
+ Activity activity = mFragment.getActivity();
try {
int port = Integer.parseInt((String) newValue);
if (port < 0 || port > 65535) {
@@ -407,7 +406,7 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
/**
* This fragment shows the keyserver/contacts sync preferences
*/
- public static class SyncPrefsFragment extends PreferenceFragment {
+ public static class SyncPrefsFragment extends PresetPreferenceFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
@@ -477,6 +476,8 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
private boolean checkContactsPermission(String authority) {
if (!ContactsContract.AUTHORITY.equals(authority)) {
+ // provides convenience of not using separate checks for keyserver and contact sync
+ // in initializeSyncCheckBox
return true;
}
@@ -542,7 +543,7 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
/**
* This fragment shows experimental features
*/
- public static class ExperimentalPrefsFragment extends PreferenceFragment {
+ public static class ExperimentalPrefsFragment extends PresetPreferenceFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
@@ -551,17 +552,23 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
// Load the preferences from an XML resource
addPreferencesFromResource(R.xml.experimental_preferences);
- initializeExperimentalEnableWordConfirm(
- (SwitchPreference) findPreference(Constants.Pref.EXPERIMENTAL_ENABLE_WORD_CONFIRM));
+ initializeTheme((ListPreference) findPreference(Constants.Pref.THEME));
- initializeExperimentalEnableLinkedIdentities(
- (SwitchPreference) findPreference(Constants.Pref.EXPERIMENTAL_ENABLE_LINKED_IDENTITIES));
+ }
- initializeExperimentalEnableKeybase(
- (SwitchPreference) findPreference(Constants.Pref.EXPERIMENTAL_ENABLE_KEYBASE));
+ private static void initializeTheme(final ListPreference themePref) {
+ themePref.setSummary(themePref.getEntry() + "\n"
+ + themePref.getContext().getString(R.string.label_experimental_settings_theme_summary));
+ themePref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ themePref.setSummary(newValue + "\n"
+ + themePref.getContext().getString(R.string.label_experimental_settings_theme_summary));
- initializeTheme((ListPreference) findPreference(Constants.Pref.THEME));
+ ((SettingsActivity) themePref.getContext()).recreate();
+ return true;
+ }
+ });
}
}
@@ -573,125 +580,4 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
|| ExperimentalPrefsFragment.class.getName().equals(fragmentName)
|| super.isValidFragment(fragmentName);
}
-
- private static void initializePassphraseCacheSubs(final CheckBoxPreference mPassphraseCacheSubs) {
- mPassphraseCacheSubs.setChecked(sPreferences.getPassphraseCacheSubs());
- mPassphraseCacheSubs.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
- public boolean onPreferenceChange(Preference preference, Object newValue) {
- mPassphraseCacheSubs.setChecked((Boolean) newValue);
- sPreferences.setPassphraseCacheSubs((Boolean) newValue);
- return false;
- }
- });
- }
-
- private static void initializePassphraseCacheTtl(final IntegerListPreference mPassphraseCacheTtl) {
- mPassphraseCacheTtl.setValue("" + sPreferences.getPassphraseCacheTtl());
- mPassphraseCacheTtl.setSummary(mPassphraseCacheTtl.getEntry());
- mPassphraseCacheTtl
- .setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
- public boolean onPreferenceChange(Preference preference, Object newValue) {
- mPassphraseCacheTtl.setValue(newValue.toString());
- mPassphraseCacheTtl.setSummary(mPassphraseCacheTtl.getEntry());
- sPreferences.setPassphraseCacheTtl(Integer.parseInt(newValue.toString()));
- return false;
- }
- });
- }
-
- private static void initializeTheme(final ListPreference mTheme) {
- mTheme.setValue(sPreferences.getTheme());
- mTheme.setSummary(mTheme.getEntry() + "\n"
- + mTheme.getContext().getString(R.string.label_experimental_settings_theme_summary));
- mTheme.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
- public boolean onPreferenceChange(Preference preference, Object newValue) {
- mTheme.setValue((String) newValue);
- mTheme.setSummary(mTheme.getEntry() + "\n"
- + mTheme.getContext().getString(R.string.label_experimental_settings_theme_summary));
- sPreferences.setTheme((String) newValue);
-
- ((SettingsActivity) mTheme.getContext()).recreate();
-
- return false;
- }
- });
- }
-
- private static void initializeSearchKeyserver(final SwitchPreference mSearchKeyserver) {
- Preferences.CloudSearchPrefs prefs = sPreferences.getCloudSearchPrefs();
- mSearchKeyserver.setChecked(prefs.searchKeyserver);
- mSearchKeyserver.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
- @Override
- public boolean onPreferenceChange(Preference preference, Object newValue) {
- mSearchKeyserver.setChecked((Boolean) newValue);
- sPreferences.setSearchKeyserver((Boolean) newValue);
- return false;
- }
- });
- }
-
- private static void initializeSearchKeybase(final SwitchPreference mSearchKeybase) {
- Preferences.CloudSearchPrefs prefs = sPreferences.getCloudSearchPrefs();
- mSearchKeybase.setChecked(prefs.searchKeybase);
- mSearchKeybase.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
- @Override
- public boolean onPreferenceChange(Preference preference, Object newValue) {
- mSearchKeybase.setChecked((Boolean) newValue);
- sPreferences.setSearchKeybase((Boolean) newValue);
- return false;
- }
- });
- }
-
- public static String keyserverSummary(Context context) {
- String[] servers = sPreferences.getKeyServers();
- String serverSummary = context.getResources().getQuantityString(
- R.plurals.n_keyservers, servers.length, servers.length);
- return serverSummary + "; " + context.getString(R.string.label_preferred) + ": " + sPreferences
- .getPreferredKeyserver();
- }
-
- private static void initializeUseNumKeypadForYubiKeyPin(final CheckBoxPreference mUseNumKeypadForYubiKeyPin) {
- mUseNumKeypadForYubiKeyPin.setChecked(sPreferences.useNumKeypadForYubiKeyPin());
- mUseNumKeypadForYubiKeyPin.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
- public boolean onPreferenceChange(Preference preference, Object newValue) {
- mUseNumKeypadForYubiKeyPin.setChecked((Boolean) newValue);
- sPreferences.setUseNumKeypadForYubiKeyPin((Boolean) newValue);
- return false;
- }
- });
- }
-
- private static void initializeExperimentalEnableWordConfirm(final SwitchPreference mExperimentalEnableWordConfirm) {
- mExperimentalEnableWordConfirm.setChecked(sPreferences.getExperimentalEnableWordConfirm());
- mExperimentalEnableWordConfirm.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
- public boolean onPreferenceChange(Preference preference, Object newValue) {
- mExperimentalEnableWordConfirm.setChecked((Boolean) newValue);
- sPreferences.setExperimentalEnableWordConfirm((Boolean) newValue);
- return false;
- }
- });
- }
-
- private static void initializeExperimentalEnableLinkedIdentities(final SwitchPreference mExperimentalEnableLinkedIdentities) {
- mExperimentalEnableLinkedIdentities.setChecked(sPreferences.getExperimentalEnableLinkedIdentities());
- mExperimentalEnableLinkedIdentities.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
- public boolean onPreferenceChange(Preference preference, Object newValue) {
- mExperimentalEnableLinkedIdentities.setChecked((Boolean) newValue);
- sPreferences.setExperimentalEnableLinkedIdentities((Boolean) newValue);
- return false;
- }
- });
- }
-
- private static void initializeExperimentalEnableKeybase(final SwitchPreference mExperimentalKeybase) {
- mExperimentalKeybase.setChecked(sPreferences.getExperimentalEnableKeybase());
- mExperimentalKeybase.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
- public boolean onPreferenceChange(Preference preference, Object newValue) {
- mExperimentalKeybase.setChecked((Boolean) newValue);
- sPreferences.setExperimentalEnableKeybase((Boolean) newValue);
- return false;
- }
- });
- }
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java
index e1b796f38..35e00ff21 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java
@@ -243,7 +243,7 @@ public class ViewKeyActivity extends BaseNfcActivity implements
return;
}
if (mDataUri.getHost().equals(ContactsContract.AUTHORITY)) {
- mDataUri = ContactHelper.dataUriFromContactUri(this, mDataUri);
+ mDataUri = new ContactHelper(this).dataUriFromContactUri(mDataUri);
if (mDataUri == null) {
Log.e(Constants.TAG, "Contact Data missing. Should be uri of key!");
Toast.makeText(this, R.string.error_contacts_key_id_missing, Toast.LENGTH_LONG).show();
@@ -855,8 +855,8 @@ public class ViewKeyActivity extends BaseNfcActivity implements
AsyncTask<Long, Void, Bitmap> photoTask =
new AsyncTask<Long, Void, Bitmap>() {
protected Bitmap doInBackground(Long... mMasterKeyId) {
- return ContactHelper.loadPhotoByMasterKeyId(ViewKeyActivity.this,
- getContentResolver(), mMasterKeyId[0], true);
+ return new ContactHelper(ViewKeyActivity.this)
+ .loadPhotoByMasterKeyId(mMasterKeyId[0], true);
}
protected void onPostExecute(Bitmap photo) {
@@ -1038,18 +1038,12 @@ public class ViewKeyActivity extends BaseNfcActivity implements
KeychainContract.Keys.FINGERPRINT, ProviderHelper.FIELD_TYPE_BLOB);
String fingerprint = KeyFormattingUtils.convertFingerprintToHex(blob);
- ParcelableKeyRing keyEntry = new ParcelableKeyRing(fingerprint, null, null);
+ ParcelableKeyRing keyEntry = new ParcelableKeyRing(fingerprint, null);
ArrayList<ParcelableKeyRing> entries = new ArrayList<>();
entries.add(keyEntry);
mKeyList = entries;
- // search config
- {
- Preferences prefs = Preferences.getPreferences(this);
- Preferences.CloudSearchPrefs cloudPrefs =
- new Preferences.CloudSearchPrefs(true, true, prefs.getPreferredKeyserver());
- mKeyserver = cloudPrefs.keyserver;
- }
+ mKeyserver = Preferences.getPreferences(this).getPreferredKeyserver();
mOperationHelper.cryptoOperation();
}
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 bba6a6dc1..94a171f14 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvActivity.java
@@ -88,7 +88,7 @@ public class ViewKeyAdvActivity extends BaseActivity implements
return;
}
if (mDataUri.getHost().equals(ContactsContract.AUTHORITY)) {
- mDataUri = ContactHelper.dataUriFromContactUri(this, mDataUri);
+ mDataUri = new ContactHelper(this).dataUriFromContactUri(mDataUri);
if (mDataUri == null) {
Log.e(Constants.TAG, "Contact Data missing. Should be uri of key!");
Toast.makeText(this, R.string.error_contacts_key_id_missing, Toast.LENGTH_LONG).show();
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 dda2a680a..f75012731 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyFragment.java
@@ -224,17 +224,17 @@ public class ViewKeyFragment extends LoaderFragment implements
if(contactId == -1) return;
final Context context = mSystemContactName.getContext();
- final ContentResolver resolver = context.getContentResolver();
+ ContactHelper contactHelper = new ContactHelper(context);
String contactName = null;
if (mIsSecret) {//all secret keys are linked to "me" profile in contacts
- List<String> mainProfileNames = ContactHelper.getMainProfileContactName(context);
+ List<String> mainProfileNames = contactHelper.getMainProfileContactName();
if (mainProfileNames != null && mainProfileNames.size() > 0) {
contactName = mainProfileNames.get(0);
}
} else {
- contactName = ContactHelper.getContactName(resolver, contactId);
+ contactName = contactHelper.getContactName(contactId);
}
if (contactName != null) {//contact name exists for given master key
@@ -244,9 +244,9 @@ public class ViewKeyFragment extends LoaderFragment implements
Bitmap picture;
if (mIsSecret) {
- picture = ContactHelper.loadMainProfilePhoto(getActivity(), resolver, false);
+ picture = contactHelper.loadMainProfilePhoto(false);
} else {
- picture = ContactHelper.loadPhotoByContactId(getActivity(), resolver, contactId, false);
+ picture = contactHelper.loadPhotoByContactId(contactId, false);
}
if (picture != null) mSystemContactPicture.setImageBitmap(picture);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateFinalFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateFinalFragment.java
index e09b1e755..51f047952 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateFinalFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateFinalFragment.java
@@ -208,18 +208,12 @@ public abstract class LinkedIdCreateFinalFragment extends CryptoOperationFragmen
@Override
public void onCryptoOperationSuccess(OperationResult result) {
- // if bad -> display here!
- if (!result.success()) {
- result.createNotify(getActivity()).show(LinkedIdCreateFinalFragment.this);
- return;
- }
-
getActivity().finish();
}
@Override
public void onCryptoOperationError(OperationResult result) {
-
+ result.createNotify(getActivity()).show(this);
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/NotificationUtils.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/NotificationUtils.java
deleted file mode 100644
index 40ff92a1c..000000000
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/NotificationUtils.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2015 Dominik Schürmann <dominik@dominikschuermann.de>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-package org.sufficientlysecure.keychain.ui.util;
-
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.drawable.Drawable;
-import android.os.Build;
-
-public class NotificationUtils {
-
- // from de.azapps.mirakel.helper.Helpers from https://github.com/MirakelX/mirakel-android
- public static Bitmap getBitmap(int resId, Context context) {
- int mLargeIconWidth = (int) context.getResources().getDimension(
- android.R.dimen.notification_large_icon_width);
- int mLargeIconHeight = (int) context.getResources().getDimension(
- android.R.dimen.notification_large_icon_height);
- Drawable d;
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
- // noinspection deprecation (can't help it at this api level)
- d = context.getResources().getDrawable(resId);
- } else {
- d = context.getDrawable(resId);
- }
- if (d == null) {
- return null;
- }
- Bitmap b = Bitmap.createBitmap(mLargeIconWidth, mLargeIconHeight, Bitmap.Config.ARGB_8888);
- Canvas c = new Canvas(b);
- d.setBounds(0, 0, mLargeIconWidth, mLargeIconHeight);
- d.draw(c);
- return b;
- }
-}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EmailEditText.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EmailEditText.java
index 494ccb6d3..49b37692c 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EmailEditText.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EmailEditText.java
@@ -90,7 +90,7 @@ public class EmailEditText extends AppCompatAutoCompleteTextView {
private void initAdapter() {
setThreshold(1); // Start working from first character
setAdapter(new ArrayAdapter<>(getContext(), android.R.layout.simple_spinner_dropdown_item,
- ContactHelper.getPossibleUserEmails(getContext())));
+ new ContactHelper(getContext()).getPossibleUserEmails()));
}
/**
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 c812edf71..f98fda56f 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
@@ -18,6 +18,7 @@
package org.sufficientlysecure.keychain.ui.widget;
+
import android.content.Context;
import android.database.Cursor;
import android.graphics.Rect;
@@ -37,7 +38,6 @@ import android.view.inputmethod.InputMethodManager;
import android.widget.TextView;
import com.tokenautocomplete.TokenCompleteTextView;
-
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.provider.KeychainContract;
@@ -55,7 +55,6 @@ public class EncryptKeyCompletionView extends TokenCompleteTextView<KeyItem>
private KeyAdapter mAdapter;
private LoaderManager mLoaderManager;
- private CharSequence mPrefix;
public EncryptKeyCompletionView(Context context) {
super(context);
@@ -73,21 +72,13 @@ public class EncryptKeyCompletionView extends TokenCompleteTextView<KeyItem>
}
private void initView() {
- setPrefix(getContext().getString(R.string.label_to) + " ");
-
allowDuplicates(false);
+
mAdapter = new KeyAdapter(getContext(), null, 0);
setAdapter(mAdapter);
}
@Override
- public void setPrefix(CharSequence p) {
- // this one is private in the superclass, but we need it here
- mPrefix = p;
- super.setPrefix(p);
- }
-
- @Override
protected View getViewForObject(KeyItem keyItem) {
LayoutInflater l = LayoutInflater.from(getContext());
View view = l.inflate(R.layout.recipient_box_entry, null);
@@ -97,10 +88,6 @@ public class EncryptKeyCompletionView extends TokenCompleteTextView<KeyItem>
@Override
protected KeyItem defaultObject(String completionText) {
- // TODO: We could try to automagically download the key if it's unknown but a key id
- /*if (completionText.startsWith("0x")) {
-
- }*/
return null;
}
@@ -173,13 +160,10 @@ public class EncryptKeyCompletionView extends TokenCompleteTextView<KeyItem>
@Override
protected void performFiltering(@NonNull CharSequence text, int start, int end, int keyCode) {
- super.performFiltering(text, start, end, keyCode);
- if (start < mPrefix.length()) {
- start = mPrefix.length();
- }
+// super.performFiltering(text, start, end, keyCode);
String query = text.subSequence(start, end).toString();
if (TextUtils.isEmpty(query) || query.length() < 2) {
- mLoaderManager.destroyLoader(0);
+ mAdapter.swapCursor(null);
return;
}
Bundle args = new Bundle();
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/NameEditText.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/NameEditText.java
index 1a034537c..af259ca44 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/NameEditText.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/NameEditText.java
@@ -50,7 +50,7 @@ public class NameEditText extends AppCompatAutoCompleteTextView {
setThreshold(1); // Start working from first character
setAdapter(new ArrayAdapter<>(
getContext(), android.R.layout.simple_spinner_dropdown_item,
- ContactHelper.getPossibleUserNames(getContext())));
+ new ContactHelper(getContext()).getPossibleUserNames()));
}
/**
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 ab9587910..ea038aa1a 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ContactHelper.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ContactHelper.java
@@ -54,14 +54,17 @@ public class ContactHelper {
private static final Map<Long, Bitmap> photoCache = new HashMap<>();
- public static List<String> getPossibleUserEmails(Context context) {
- if (!isContactsPermissionGranted(context)) {
- Log.w(Constants.TAG, "getting emails not possible READ_CONTACTS permission denied!");
- return new ArrayList<>();
- }
+ private Context mContext;
+ private ContentResolver mContentResolver;
- Set<String> accountMails = getAccountEmails(context);
- accountMails.addAll(getMainProfileContactEmails(context));
+ public ContactHelper(Context context) {
+ mContext = context;
+ mContentResolver = context.getContentResolver();
+ }
+
+ public List<String> getPossibleUserEmails() {
+ Set<String> accountMails = getAccountEmails();
+ accountMails.addAll(getMainProfileContactEmails());
// remove items that are not an email
Iterator<String> it = accountMails.iterator();
@@ -77,15 +80,10 @@ public class ContactHelper {
return new ArrayList<>(accountMails);
}
- public static List<String> getPossibleUserNames(Context context) {
- if (!isContactsPermissionGranted(context)) {
- Log.w(Constants.TAG, "getting names not possible READ_CONTACTS permission denied!");
- return new ArrayList<>();
- }
-
- Set<String> accountMails = getAccountEmails(context);
- Set<String> names = getContactNamesFromEmails(context, accountMails);
- names.addAll(getMainProfileContactName(context));
+ public List<String> getPossibleUserNames() {
+ Set<String> accountMails = getAccountEmails();
+ Set<String> names = getContactNamesFromEmails(accountMails);
+ names.addAll(getMainProfileContactName());
// remove items that are an email
Iterator<String> it = names.iterator();
@@ -102,12 +100,9 @@ public class ContactHelper {
/**
* Get emails from AccountManager
- *
- * @param context
- * @return
*/
- private static Set<String> getAccountEmails(Context context) {
- final Account[] accounts = AccountManager.get(context).getAccounts();
+ private Set<String> getAccountEmails() {
+ final Account[] accounts = AccountManager.get(mContext).getAccounts();
final Set<String> emailSet = new HashSet<>();
for (Account account : accounts) {
emailSet.add(account.name);
@@ -118,16 +113,15 @@ public class ContactHelper {
/**
* Search for contact names based on a list of emails (to find out the names of the
* device owner based on the email addresses from AccountsManager)
- *
- * @param context
- * @param emails
- * @return
*/
- private static Set<String> getContactNamesFromEmails(Context context, Set<String> emails) {
+ private Set<String> getContactNamesFromEmails(Set<String> emails) {
+ if (!isContactsPermissionGranted()) {
+ return new HashSet<>();
+ }
+
Set<String> names = new HashSet<>();
for (String email : emails) {
- ContentResolver resolver = context.getContentResolver();
- Cursor profileCursor = resolver.query(
+ Cursor profileCursor = mContentResolver.query(
ContactsContract.CommonDataKinds.Email.CONTENT_URI,
new String[]{
ContactsContract.CommonDataKinds.Email.ADDRESS,
@@ -156,13 +150,13 @@ public class ContactHelper {
/**
* Retrieves the emails of the primary profile contact
* http://developer.android.com/reference/android/provider/ContactsContract.Profile.html
- *
- * @param context
- * @return
*/
- private static Set<String> getMainProfileContactEmails(Context context) {
- ContentResolver resolver = context.getContentResolver();
- Cursor profileCursor = resolver.query(
+ private Set<String> getMainProfileContactEmails() {
+ if (!isContactsPermissionGranted()) {
+ return new HashSet<>();
+ }
+
+ Cursor profileCursor = mContentResolver.query(
Uri.withAppendedPath(
ContactsContract.Profile.CONTENT_URI,
ContactsContract.Contacts.Data.CONTENT_DIRECTORY),
@@ -197,13 +191,13 @@ public class ContactHelper {
/**
* Retrieves the name of the primary profile contact
* http://developer.android.com/reference/android/provider/ContactsContract.Profile.html
- *
- * @param context
- * @return
*/
- public static List<String> getMainProfileContactName(Context context) {
- ContentResolver resolver = context.getContentResolver();
- Cursor profileCursor = resolver.query(
+ public List<String> getMainProfileContactName() {
+ if (!isContactsPermissionGranted()) {
+ return new ArrayList<>();
+ }
+
+ Cursor profileCursor = mContentResolver.query(
ContactsContract.Profile.CONTENT_URI,
new String[]{
ContactsContract.Profile.DISPLAY_NAME
@@ -228,12 +222,9 @@ public class ContactHelper {
/**
* returns the CONTACT_ID of the main ("me") contact
* http://developer.android.com/reference/android/provider/ContactsContract.Profile.html
- *
- * @param resolver
- * @return
*/
- public static long getMainProfileContactId(ContentResolver resolver) {
- Cursor profileCursor = resolver.query(ContactsContract.Profile.CONTENT_URI,
+ private long getMainProfileContactId() {
+ Cursor profileCursor = mContentResolver.query(ContactsContract.Profile.CONTENT_URI,
new String[]{ContactsContract.Profile._ID}, null, null, null);
if (profileCursor != null && profileCursor.getCount() != 0 && profileCursor.moveToNext()) {
@@ -252,18 +243,24 @@ public class ContactHelper {
* loads the profile picture of the main ("me") contact
* http://developer.android.com/reference/android/provider/ContactsContract.Profile.html
*
- * @param contentResolver
- * @param highRes true for large image if present, false for thumbnail
+ * @param highRes true for large image if present, false for thumbnail
* @return bitmap of loaded photo
*/
- public static Bitmap loadMainProfilePhoto(Context context, ContentResolver contentResolver, boolean highRes) {
+ public Bitmap loadMainProfilePhoto(boolean highRes) {
+ if (!isContactsPermissionGranted()) {
+ return null;
+ }
+
try {
- long mainProfileContactId = getMainProfileContactId(contentResolver);
+ long mainProfileContactId = getMainProfileContactId();
Uri contactUri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_URI,
Long.toString(mainProfileContactId));
- InputStream photoInputStream =
- ContactsContract.Contacts.openContactPhotoInputStream(contentResolver, contactUri, highRes);
+ InputStream photoInputStream = ContactsContract.Contacts.openContactPhotoInputStream(
+ mContentResolver,
+ contactUri,
+ highRes
+ );
if (photoInputStream == null) {
return null;
}
@@ -273,9 +270,12 @@ public class ContactHelper {
}
}
- public static List<String> getContactMails(Context context) {
- ContentResolver resolver = context.getContentResolver();
- Cursor mailCursor = resolver.query(ContactsContract.CommonDataKinds.Email.CONTENT_URI,
+ public List<String> getContactMails() {
+ if (!isContactsPermissionGranted()) {
+ return new ArrayList<>();
+ }
+
+ Cursor mailCursor = mContentResolver.query(ContactsContract.CommonDataKinds.Email.CONTENT_URI,
new String[]{ContactsContract.CommonDataKinds.Email.DATA},
null, null, null);
if (mailCursor == null) {
@@ -293,9 +293,12 @@ public class ContactHelper {
return new ArrayList<>(mails);
}
- public static List<String> getContactNames(Context context) {
- ContentResolver resolver = context.getContentResolver();
- Cursor cursor = resolver.query(ContactsContract.Contacts.CONTENT_URI,
+ public List<String> getContactNames() {
+ if (!isContactsPermissionGranted()) {
+ return new ArrayList<>();
+ }
+
+ Cursor cursor = mContentResolver.query(ContactsContract.Contacts.CONTENT_URI,
new String[]{ContactsContract.Contacts.DISPLAY_NAME},
null, null, null);
if (cursor == null) {
@@ -313,9 +316,12 @@ public class ContactHelper {
return new ArrayList<>(names);
}
- public static Uri dataUriFromContactUri(Context context, Uri contactUri) {
+ public Uri dataUriFromContactUri(Uri contactUri) {
+ if (!isContactsPermissionGranted()) {
+ return null;
+ }
- Cursor contactMasterKey = context.getContentResolver().query(contactUri,
+ Cursor contactMasterKey = mContentResolver.query(contactUri,
new String[]{ContactsContract.Data.DATA2}, null, null, null);
if (contactMasterKey != null) {
try {
@@ -333,13 +339,11 @@ public class ContactHelper {
* returns the CONTACT_ID of the raw contact to which a masterKeyId is associated, if the
* raw contact has not been marked for deletion.
*
- * @param resolver
- * @param masterKeyId
* @return CONTACT_ID (id of aggregated contact) linked to masterKeyId
*/
- public static long findContactId(ContentResolver resolver, long masterKeyId) {
+ private long findContactId(long masterKeyId) {
long contactId = -1;
- Cursor raw = resolver.query(ContactsContract.RawContacts.CONTENT_URI,
+ Cursor raw = mContentResolver.query(ContactsContract.RawContacts.CONTENT_URI,
new String[]{
ContactsContract.RawContacts.CONTACT_ID
},
@@ -364,14 +368,12 @@ public class ContactHelper {
* Returns the display name of the system contact associated with contactId, null if the
* contact does not exist
*
- * @param resolver
- * @param contactId
* @return primary display name of system contact associated with contactId, null if it does
* not exist
*/
- public static String getContactName(ContentResolver resolver, long contactId) {
+ public String getContactName(long contactId) {
String contactName = null;
- Cursor raw = resolver.query(ContactsContract.Contacts.CONTENT_URI,
+ Cursor raw = mContentResolver.query(ContactsContract.Contacts.CONTENT_URI,
new String[]{
ContactsContract.Contacts.DISPLAY_NAME_PRIMARY
},
@@ -388,21 +390,18 @@ public class ContactHelper {
return contactName;
}
- public static Bitmap getCachedPhotoByMasterKeyId(Context context, ContentResolver contentResolver,
- long masterKeyId) {
+ private Bitmap getCachedPhotoByMasterKeyId(long masterKeyId) {
if (masterKeyId == -1) {
return null;
}
if (!photoCache.containsKey(masterKeyId)) {
- photoCache.put(masterKeyId, loadPhotoByMasterKeyId(context, contentResolver, masterKeyId, false));
+ photoCache.put(masterKeyId, loadPhotoByMasterKeyId(masterKeyId, false));
}
return photoCache.get(masterKeyId);
}
- public static Bitmap loadPhotoByMasterKeyId(Context context, ContentResolver contentResolver,
- long masterKeyId, boolean highRes) {
- if (!isContactsPermissionGranted(context)) {
- Log.w(Constants.TAG, "loading photo not possible READ_CONTACTS permission denied!");
+ public Bitmap loadPhotoByMasterKeyId(long masterKeyId, boolean highRes) {
+ if (!isContactsPermissionGranted()) {
return null;
}
@@ -410,18 +409,16 @@ public class ContactHelper {
return null;
}
try {
- long contactId = findContactId(contentResolver, masterKeyId);
- return loadPhotoByContactId(context, contentResolver, contactId, highRes);
+ long contactId = findContactId(masterKeyId);
+ return loadPhotoByContactId(contactId, highRes);
} catch (Throwable ignored) {
return null;
}
}
- public static Bitmap loadPhotoByContactId(Context context, ContentResolver contentResolver,
- long contactId, boolean highRes) {
- if (!isContactsPermissionGranted(context)) {
- Log.w(Constants.TAG, "loading photo not possible READ_CONTACTS permission denied!");
+ public Bitmap loadPhotoByContactId(long contactId, boolean highRes) {
+ if (!isContactsPermissionGranted()) {
return null;
}
@@ -436,7 +433,7 @@ public class ContactHelper {
// Also, we don't need a permanent shortcut to the contact since we load it afresh each time
InputStream photoInputStream = ContactsContract.Contacts.openContactPhotoInputStream(
- contentResolver,
+ mContentResolver,
contactUri,
highRes);
@@ -466,40 +463,39 @@ public class ContactHelper {
/**
* Write/Update the current OpenKeychain keys to the contact db
*/
- public static void writeKeysToContacts(Context context) {
- ContentResolver resolver = context.getContentResolver();
-
+ public void writeKeysToContacts() {
if (Constants.DEBUG_SYNC_REMOVE_CONTACTS) {
- debugDeleteRawContacts(resolver);
+ debugDeleteRawContacts();
}
- writeKeysToMainProfileContact(context, resolver);
+ writeKeysToMainProfileContact();
- writeKeysToNormalContacts(context, resolver);
+ writeKeysToNormalContacts();
}
- private static boolean isContactsPermissionGranted(Context context) {
+ private boolean isContactsPermissionGranted() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
return true;
}
- if (ContextCompat.checkSelfPermission(context, Manifest.permission.READ_CONTACTS)
+ if (ContextCompat.checkSelfPermission(mContext, Manifest.permission.READ_CONTACTS)
== PackageManager.PERMISSION_GRANTED) {
return true;
}
+ Log.w(Constants.TAG, "READ_CONTACTS permission denied!");
return false;
}
- private static void writeKeysToNormalContacts(Context context, ContentResolver resolver) {
+ private void writeKeysToNormalContacts() {
// delete raw contacts flagged for deletion by user so they can be reinserted
- deleteFlaggedNormalRawContacts(resolver);
+ deleteFlaggedNormalRawContacts();
- Set<Long> deletedKeys = getRawContactMasterKeyIds(resolver);
+ Set<Long> deletedKeys = getRawContactMasterKeyIds();
// Load all public Keys from OK
// TODO: figure out why using selectionArgs does not work in this case
- Cursor cursor = resolver.query(KeychainContract.KeyRings.buildUnifiedKeyRingsUri(),
+ Cursor cursor = mContentResolver.query(KeychainContract.KeyRings.buildUnifiedKeyRingsUri(),
KEYS_TO_CONTACT_PROJECTION,
KeychainContract.KeyRings.HAS_ANY_SECRET + "=0",
null, null);
@@ -524,28 +520,28 @@ public class ContactHelper {
Log.d(Constants.TAG, "Expired or revoked or unverified: Deleting masterKeyId "
+ masterKeyId);
if (masterKeyId != -1) {
- deleteRawContactByMasterKeyId(resolver, masterKeyId);
+ deleteRawContactByMasterKeyId(masterKeyId);
}
} else if (userIdSplit.name != null) {
// get raw contact to this master key id
- long rawContactId = findRawContactId(resolver, masterKeyId);
+ long rawContactId = findRawContactId(masterKeyId);
Log.d(Constants.TAG, "rawContactId: " + rawContactId);
// Create a new rawcontact with corresponding key if it does not exist yet
if (rawContactId == -1) {
Log.d(Constants.TAG, "Insert new raw contact with masterKeyId " + masterKeyId);
- insertContact(ops, context, masterKeyId);
- writeContactKey(ops, context, rawContactId, masterKeyId, userIdSplit.name);
+ insertContact(ops, masterKeyId);
+ writeContactKey(ops, rawContactId, masterKeyId, userIdSplit.name);
}
// We always update the display name (which is derived from primary user id)
// and email addresses from user id
writeContactDisplayName(ops, rawContactId, userIdSplit.name);
- writeContactEmail(ops, resolver, rawContactId, masterKeyId);
+ writeContactEmail(ops, rawContactId, masterKeyId);
try {
- resolver.applyBatch(ContactsContract.AUTHORITY, ops);
+ mContentResolver.applyBatch(ContactsContract.AUTHORITY, ops);
} catch (Exception e) {
Log.w(Constants.TAG, e);
}
@@ -557,25 +553,23 @@ public class ContactHelper {
// 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);
+ deleteRawContactByMasterKeyId(masterKeyId);
}
}
/**
* Links all keys with secrets to the main ("me") contact
* http://developer.android.com/reference/android/provider/ContactsContract.Profile.html
- *
- * @param context
*/
- public static void writeKeysToMainProfileContact(Context context, ContentResolver resolver) {
+ private void writeKeysToMainProfileContact() {
// deletes contacts hidden by the user so they can be reinserted if necessary
- deleteFlaggedMainProfileRawContacts(resolver);
+ deleteFlaggedMainProfileRawContacts();
- Set<Long> keysToDelete = getMainProfileMasterKeyIds(resolver);
+ Set<Long> keysToDelete = getMainProfileMasterKeyIds();
// get all keys which have associated secret keys
// TODO: figure out why using selectionArgs does not work in this case
- Cursor cursor = resolver.query(KeychainContract.KeyRings.buildUnifiedKeyRingsUri(),
+ Cursor cursor = mContentResolver.query(KeychainContract.KeyRings.buildUnifiedKeyRingsUri(),
KEYS_TO_CONTACT_PROJECTION,
KeychainContract.KeyRings.HAS_ANY_SECRET + "!=0",
null, null);
@@ -597,10 +591,10 @@ public class ContactHelper {
ArrayList<ContentProviderOperation> ops = new ArrayList<>();
insertMainProfileRawContact(ops, masterKeyId);
- writeContactKey(ops, context, rawContactId, masterKeyId, userIdSplit.name);
+ writeContactKey(ops, rawContactId, masterKeyId, userIdSplit.name);
try {
- resolver.applyBatch(ContactsContract.AUTHORITY, ops);
+ mContentResolver.applyBatch(ContactsContract.AUTHORITY, ops);
} catch (Exception e) {
Log.w(Constants.TAG, e);
}
@@ -612,7 +606,7 @@ public class ContactHelper {
}
for (long masterKeyId : keysToDelete) {
- deleteMainProfileRawContactByMasterKeyId(resolver, masterKeyId);
+ deleteMainProfileRawContactByMasterKeyId(masterKeyId);
Log.d(Constants.TAG, "Delete main profile raw contact with masterKeyId " + masterKeyId);
}
}
@@ -620,12 +614,9 @@ public class ContactHelper {
/**
* Inserts a raw contact into the table defined by ContactsContract.Profile
* http://developer.android.com/reference/android/provider/ContactsContract.Profile.html
- *
- * @param ops
- * @param masterKeyId
*/
- private static void insertMainProfileRawContact(ArrayList<ContentProviderOperation> ops,
- long masterKeyId) {
+ private void insertMainProfileRawContact(ArrayList<ContentProviderOperation> ops,
+ long masterKeyId) {
ops.add(ContentProviderOperation.newInsert(ContactsContract.Profile.CONTENT_RAW_CONTACTS_URI)
.withValue(ContactsContract.RawContacts.ACCOUNT_NAME, Constants.ACCOUNT_NAME)
.withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, Constants.ACCOUNT_TYPE)
@@ -637,18 +628,15 @@ public class ContactHelper {
* deletes a raw contact from the main profile table ("me" contact)
* http://developer.android.com/reference/android/provider/ContactsContract.Profile.html
*
- * @param resolver
- * @param masterKeyId
* @return number of rows deleted
*/
- private static int deleteMainProfileRawContactByMasterKeyId(ContentResolver resolver,
- long masterKeyId) {
+ private int deleteMainProfileRawContactByMasterKeyId(long masterKeyId) {
// CALLER_IS_SYNCADAPTER allows us to actually wipe the RawContact from the device, otherwise
// would be just flagged for deletion
Uri deleteUri = ContactsContract.Profile.CONTENT_RAW_CONTACTS_URI.buildUpon().
appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "true").build();
- return resolver.delete(deleteUri,
+ return mContentResolver.delete(deleteUri,
ContactsContract.RawContacts.ACCOUNT_TYPE + "=? AND " +
ContactsContract.RawContacts.SOURCE_ID + "=?",
new String[]{
@@ -660,16 +648,15 @@ public class ContactHelper {
* deletes all raw contact entries in the "me" contact flagged for deletion ('hidden'),
* presumably by the user
*
- * @param resolver
* @return number of raw contacts deleted
*/
- private static int deleteFlaggedMainProfileRawContacts(ContentResolver resolver) {
+ private int deleteFlaggedMainProfileRawContacts() {
// CALLER_IS_SYNCADAPTER allows us to actually wipe the RawContact from the device, otherwise
// would be just flagged for deletion
Uri deleteUri = ContactsContract.Profile.CONTENT_RAW_CONTACTS_URI.buildUpon().
appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "true").build();
- return resolver.delete(deleteUri,
+ return mContentResolver.delete(deleteUri,
ContactsContract.RawContacts.ACCOUNT_TYPE + "=? AND " +
ContactsContract.RawContacts.DELETED + "=?",
new String[]{
@@ -684,14 +671,14 @@ public class ContactHelper {
*
* @return number of rows deleted
*/
- private static int debugDeleteRawContacts(ContentResolver resolver) {
+ private int debugDeleteRawContacts() {
// CALLER_IS_SYNCADAPTER allows us to actually wipe the RawContact from the device, otherwise
// would be just flagged for deletion
Uri deleteUri = ContactsContract.RawContacts.CONTENT_URI.buildUpon().
appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "true").build();
Log.d(Constants.TAG, "Deleting all raw contacts associated to OK...");
- int delete = resolver.delete(deleteUri,
+ int delete = mContentResolver.delete(deleteUri,
ContactsContract.RawContacts.ACCOUNT_TYPE + "=?",
new String[]{
Constants.ACCOUNT_TYPE
@@ -700,7 +687,7 @@ public class ContactHelper {
Uri mainProfileDeleteUri = ContactsContract.Profile.CONTENT_RAW_CONTACTS_URI.buildUpon()
.appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "true").build();
- delete += resolver.delete(mainProfileDeleteUri,
+ delete += mContentResolver.delete(mainProfileDeleteUri,
ContactsContract.RawContacts.ACCOUNT_TYPE + "=?",
new String[]{
Constants.ACCOUNT_TYPE
@@ -713,17 +700,15 @@ public class ContactHelper {
* Deletes raw contacts from ContactsContract.RawContacts based on masterKeyId. Does not
* delete contacts from the "me" contact defined in ContactsContract.Profile
*
- * @param resolver
- * @param masterKeyId
* @return number of rows deleted
*/
- private static int deleteRawContactByMasterKeyId(ContentResolver resolver, long masterKeyId) {
+ private int deleteRawContactByMasterKeyId(long masterKeyId) {
// CALLER_IS_SYNCADAPTER allows us to actually wipe the RawContact from the device, otherwise
// would be just flagged for deletion
Uri deleteUri = ContactsContract.RawContacts.CONTENT_URI.buildUpon().
appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "true").build();
- return resolver.delete(deleteUri,
+ return mContentResolver.delete(deleteUri,
ContactsContract.RawContacts.ACCOUNT_TYPE + "=? AND " +
ContactsContract.RawContacts.SOURCE_ID + "=?",
new String[]{
@@ -731,13 +716,13 @@ public class ContactHelper {
});
}
- private static int deleteFlaggedNormalRawContacts(ContentResolver resolver) {
+ private int deleteFlaggedNormalRawContacts() {
// CALLER_IS_SYNCADAPTER allows us to actually wipe the RawContact from the device, otherwise
// would be just flagged for deletion
Uri deleteUri = ContactsContract.RawContacts.CONTENT_URI.buildUpon().
appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "true").build();
- return resolver.delete(deleteUri,
+ return mContentResolver.delete(deleteUri,
ContactsContract.RawContacts.ACCOUNT_TYPE + "=? AND " +
ContactsContract.RawContacts.DELETED + "=?",
new String[]{
@@ -749,9 +734,9 @@ public class ContactHelper {
/**
* @return a set of all key master key ids currently present in the contact db
*/
- private static Set<Long> getRawContactMasterKeyIds(ContentResolver resolver) {
+ private Set<Long> getRawContactMasterKeyIds() {
HashSet<Long> result = new HashSet<>();
- Cursor masterKeyIds = resolver.query(ContactsContract.RawContacts.CONTENT_URI,
+ Cursor masterKeyIds = mContentResolver.query(ContactsContract.RawContacts.CONTENT_URI,
new String[]{
ContactsContract.RawContacts.SOURCE_ID
},
@@ -771,9 +756,9 @@ public class ContactHelper {
/**
* @return a set of all key master key ids currently present in the contact db
*/
- private static Set<Long> getMainProfileMasterKeyIds(ContentResolver resolver) {
+ private Set<Long> getMainProfileMasterKeyIds() {
HashSet<Long> result = new HashSet<>();
- Cursor masterKeyIds = resolver.query(ContactsContract.Profile.CONTENT_RAW_CONTACTS_URI,
+ Cursor masterKeyIds = mContentResolver.query(ContactsContract.Profile.CONTENT_RAW_CONTACTS_URI,
new String[]{
ContactsContract.RawContacts.SOURCE_ID
},
@@ -795,9 +780,9 @@ public class ContactHelper {
*
* @return raw contact id or -1 if not found
*/
- private static long findRawContactId(ContentResolver resolver, long masterKeyId) {
+ private long findRawContactId(long masterKeyId) {
long rawContactId = -1;
- Cursor raw = resolver.query(ContactsContract.RawContacts.CONTENT_URI,
+ Cursor raw = mContentResolver.query(ContactsContract.RawContacts.CONTENT_URI,
new String[]{
ContactsContract.RawContacts._ID
},
@@ -817,7 +802,7 @@ public class ContactHelper {
/**
* Creates a empty raw contact with a given masterKeyId
*/
- private static void insertContact(ArrayList<ContentProviderOperation> ops, Context context, long masterKeyId) {
+ private void insertContact(ArrayList<ContentProviderOperation> ops, 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)
@@ -830,11 +815,11 @@ public class ContactHelper {
* <p/>
* This creates the link to OK in contact details
*/
- private static void writeContactKey(ArrayList<ContentProviderOperation> ops, Context context, long rawContactId,
- long masterKeyId, String keyName) {
+ private void writeContactKey(ArrayList<ContentProviderOperation> ops, long rawContactId,
+ long masterKeyId, String keyName) {
ops.add(referenceRawContact(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI), rawContactId)
.withValue(ContactsContract.Data.MIMETYPE, Constants.CUSTOM_CONTACT_DATA_MIME_TYPE)
- .withValue(ContactsContract.Data.DATA1, context.getString(R.string.contact_show_key, keyName))
+ .withValue(ContactsContract.Data.DATA1, mContext.getString(R.string.contact_show_key, keyName))
.withValue(ContactsContract.Data.DATA2, masterKeyId)
.build());
}
@@ -842,12 +827,12 @@ 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,
- long rawContactId, long masterKeyId) {
+ private void writeContactEmail(ArrayList<ContentProviderOperation> ops,
+ 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),
+ Cursor ids = mContentResolver.query(UserPackets.buildUserIdsUri(masterKeyId),
new String[]{
UserPackets.USER_ID
},
@@ -870,8 +855,8 @@ public class ContactHelper {
}
}
- private static void writeContactDisplayName(ArrayList<ContentProviderOperation> ops, long rawContactId,
- String displayName) {
+ private void writeContactDisplayName(ArrayList<ContentProviderOperation> ops, long rawContactId,
+ String displayName) {
if (displayName != null) {
ops.add(insertOrUpdateForRawContact(ContactsContract.Data.CONTENT_URI, rawContactId,
ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
@@ -880,15 +865,15 @@ public class ContactHelper {
}
}
- private static ContentProviderOperation.Builder referenceRawContact(ContentProviderOperation.Builder builder,
- long rawContactId) {
+ private ContentProviderOperation.Builder referenceRawContact(ContentProviderOperation.Builder builder,
+ 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, long rawContactId,
- String itemType) {
+ private ContentProviderOperation.Builder insertOrUpdateForRawContact(Uri uri, long rawContactId,
+ String itemType) {
if (rawContactId == -1) {
return referenceRawContact(ContentProviderOperation.newInsert(uri), rawContactId).withValue(
ContactsContract.Data.MIMETYPE, itemType);
@@ -897,7 +882,7 @@ public class ContactHelper {
}
}
- private static ContentProviderOperation.Builder selectByRawContactAndItemType(
+ private ContentProviderOperation.Builder selectByRawContactAndItemType(
ContentProviderOperation.Builder builder, long rawContactId, String itemType) {
return builder.withSelection(
ContactsContract.Data.RAW_CONTACT_ID + "=? AND " + ContactsContract.Data.MIMETYPE + "=?",
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/EmailKeyHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/EmailKeyHelper.java
index a55249842..15ff4d47a 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/EmailKeyHelper.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/EmailKeyHelper.java
@@ -44,7 +44,7 @@ public class EmailKeyHelper {
private String mKeyserver;
public ImportContactKeysCallback(Context context, String keyserver, Proxy proxy) {
- this(context, ContactHelper.getContactMails(context), keyserver, proxy);
+ this(context, new ContactHelper(context).getContactMails(), keyserver, proxy);
}
public ImportContactKeysCallback(Context context, List<String> mails, String keyserver,
@@ -57,7 +57,7 @@ public class EmailKeyHelper {
// Put them in a list and import
ArrayList<ParcelableKeyRing> keys = new ArrayList<>(entries.size());
for (ImportKeysListEntry entry : entries) {
- keys.add(new ParcelableKeyRing(entry.getFingerprintHex(), entry.getKeyIdHex(), null));
+ keys.add(new ParcelableKeyRing(entry.getFingerprintHex(), entry.getKeyIdHex()));
}
mKeyList = keys;
mKeyserver = keyserver;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Preferences.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Preferences.java
index 559c5556f..ce81bbcac 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Preferences.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Preferences.java
@@ -21,10 +21,10 @@ package org.sufficientlysecure.keychain.util;
import android.content.Context;
import android.content.SharedPreferences;
-import android.content.res.Resources;
+import android.os.Parcel;
+import android.os.Parcelable;
import android.preference.PreferenceManager;
import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.Constants.Pref;
@@ -42,7 +42,6 @@ import java.util.Vector;
public class Preferences {
private static Preferences sPreferences;
private SharedPreferences mSharedPreferences;
- private Resources mResources;
private static String PREF_FILE_NAME = "APG.main";
private static int PREF_FILE_MODE = Context.MODE_MULTI_PROCESS;
@@ -62,10 +61,15 @@ public class Preferences {
}
private Preferences(Context context) {
- mResources = context.getResources();
updateSharedPreferences(context);
}
+ /**
+ * Makes android's preference framework write to our file instead of default.
+ * This allows us to use the "persistent" attribute to simplify code, which automatically
+ * writes and reads preference values.
+ * @param manager
+ */
public static void setPreferenceManagerFileAndMode(PreferenceManager manager) {
manager.setSharedPreferencesName(PREF_FILE_NAME);
manager.setSharedPreferencesMode(PREF_FILE_MODE);
@@ -130,12 +134,6 @@ public class Preferences {
return mSharedPreferences.getBoolean(Pref.USE_NUMKEYPAD_FOR_YUBIKEY_PIN, true);
}
- public void setUseNumKeypadForYubiKeyPin(boolean useNumKeypadForYubikeyPin) {
- SharedPreferences.Editor editor = mSharedPreferences.edit();
- editor.putBoolean(Pref.USE_NUMKEYPAD_FOR_YUBIKEY_PIN, useNumKeypadForYubikeyPin);
- editor.commit();
- }
-
public void setFirstTime(boolean value) {
SharedPreferences.Editor editor = mSharedPreferences.edit();
editor.putBoolean(Constants.Pref.FIRST_TIME, value);
@@ -181,18 +179,6 @@ public class Preferences {
editor.commit();
}
- public void setSearchKeyserver(boolean searchKeyserver) {
- SharedPreferences.Editor editor = mSharedPreferences.edit();
- editor.putBoolean(Pref.SEARCH_KEYSERVER, searchKeyserver);
- editor.commit();
- }
-
- public void setSearchKeybase(boolean searchKeybase) {
- SharedPreferences.Editor editor = mSharedPreferences.edit();
- editor.putBoolean(Pref.SEARCH_KEYBASE, searchKeybase);
- editor.commit();
- }
-
public void setFilesUseCompression(boolean compress) {
SharedPreferences.Editor editor = mSharedPreferences.edit();
editor.putBoolean(Pref.FILE_USE_COMPRESSION, compress);
@@ -266,17 +252,6 @@ public class Preferences {
return Integer.parseInt(mSharedPreferences.getString(Pref.PROXY_PORT, "-1"));
}
- /**
- * we store port as String for easy interfacing with EditTextPreference, but return it as an integer
- *
- * @param port proxy port
- */
- public void setProxyPort(String port) {
- SharedPreferences.Editor editor = mSharedPreferences.edit();
- editor.putString(Pref.PROXY_PORT, port);
- editor.commit();
- }
-
public Proxy.Type getProxyType() {
final String typeHttp = Pref.ProxyType.TYPE_HTTP;
final String typeSocks = Pref.ProxyType.TYPE_SOCKS;
@@ -338,12 +313,14 @@ public class Preferences {
public CloudSearchPrefs getCloudSearchPrefs() {
return new CloudSearchPrefs(mSharedPreferences.getBoolean(Pref.SEARCH_KEYSERVER, true),
mSharedPreferences.getBoolean(Pref.SEARCH_KEYBASE, true),
+ false,
getPreferredKeyserver());
}
- public static class CloudSearchPrefs {
+ public static class CloudSearchPrefs implements Parcelable {
public final boolean searchKeyserver;
public final boolean searchKeybase;
+ public final boolean searchFacebook;
public final String keyserver;
/**
@@ -351,41 +328,58 @@ public class Preferences {
* @param searchKeybase should keybase.io be searched
* @param keyserver the keyserver url authority to search on
*/
- public CloudSearchPrefs(boolean searchKeyserver, boolean searchKeybase, String keyserver) {
+ public CloudSearchPrefs(boolean searchKeyserver, boolean searchKeybase,
+ boolean searchFacebook, String keyserver) {
this.searchKeyserver = searchKeyserver;
this.searchKeybase = searchKeybase;
+ this.searchFacebook = searchFacebook;
this.keyserver = keyserver;
}
- }
- // experimental prefs
+ protected CloudSearchPrefs(Parcel in) {
+ searchKeyserver = in.readByte() != 0x00;
+ searchKeybase = in.readByte() != 0x00;
+ searchFacebook = in.readByte() != 0x00;
+ keyserver = in.readString();
+ }
- public void setExperimentalEnableWordConfirm(boolean enableWordConfirm) {
- SharedPreferences.Editor editor = mSharedPreferences.edit();
- editor.putBoolean(Pref.EXPERIMENTAL_ENABLE_WORD_CONFIRM, enableWordConfirm);
- editor.commit();
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeByte((byte) (searchKeyserver ? 0x01 : 0x00));
+ dest.writeByte((byte) (searchKeybase ? 0x01 : 0x00));
+ dest.writeByte((byte) (searchFacebook ? 0x01 : 0x00));
+ dest.writeString(keyserver);
+ }
+
+ public static final Parcelable.Creator<CloudSearchPrefs> CREATOR
+ = new Parcelable.Creator<CloudSearchPrefs>() {
+ @Override
+ public CloudSearchPrefs createFromParcel(Parcel in) {
+ return new CloudSearchPrefs(in);
+ }
+
+ @Override
+ public CloudSearchPrefs[] newArray(int size) {
+ return new CloudSearchPrefs[size];
+ }
+ };
}
+ // experimental prefs
+
public boolean getExperimentalEnableWordConfirm() {
return mSharedPreferences.getBoolean(Pref.EXPERIMENTAL_ENABLE_WORD_CONFIRM, false);
}
- public void setExperimentalEnableLinkedIdentities(boolean enableLinkedIdentities) {
- SharedPreferences.Editor editor = mSharedPreferences.edit();
- editor.putBoolean(Pref.EXPERIMENTAL_ENABLE_LINKED_IDENTITIES, enableLinkedIdentities);
- editor.commit();
- }
-
public boolean getExperimentalEnableLinkedIdentities() {
return mSharedPreferences.getBoolean(Pref.EXPERIMENTAL_ENABLE_LINKED_IDENTITIES, false);
}
- public void setExperimentalEnableKeybase(boolean enableKeybase) {
- SharedPreferences.Editor editor = mSharedPreferences.edit();
- editor.putBoolean(Pref.EXPERIMENTAL_ENABLE_KEYBASE, enableKeybase);
- editor.commit();
- }
-
public boolean getExperimentalEnableKeybase() {
return mSharedPreferences.getBoolean(Pref.EXPERIMENTAL_ENABLE_KEYBASE, false);
}
diff --git a/OpenKeychain/src/main/res/layout/encrypt_asymmetric_fragment.xml b/OpenKeychain/src/main/res/layout/encrypt_asymmetric_fragment.xml
index 56647ec65..ab1bf3d4a 100644
--- a/OpenKeychain/src/main/res/layout/encrypt_asymmetric_fragment.xml
+++ b/OpenKeychain/src/main/res/layout/encrypt_asymmetric_fragment.xml
@@ -40,6 +40,7 @@
<org.sufficientlysecure.keychain.ui.widget.EncryptKeyCompletionView
android:id="@+id/recipient_list"
android:layout_width="match_parent"
+ android:hint="@string/label_to"
android:minHeight="56dip"
android:paddingLeft="8dp"
android:paddingRight="8dp"
diff --git a/OpenKeychain/src/main/res/values/strings.xml b/OpenKeychain/src/main/res/values/strings.xml
index 075d5377c..81f0f2be4 100644
--- a/OpenKeychain/src/main/res/values/strings.xml
+++ b/OpenKeychain/src/main/res/values/strings.xml
@@ -150,7 +150,7 @@
<string name="label_write_version_header_summary">"Writes 'OpenKeychain v2.7' to OpenPGP signatures, ciphertext, and exported keys"</string>
<string name="label_use_num_keypad_for_yubikey_pin">Use number keypad for YubiKey PIN</string>
<string name="label_asymmetric_from">"Sign with:"</string>
- <string name="label_to">"Encrypt to:"</string>
+ <string name="label_to">"Encrypt to"</string>
<string name="label_delete_after_encryption">"Delete files after encryption"</string>
<string name="label_delete_after_decryption">"Delete after decryption"</string>
<string name="label_encryption_algorithm">"Encryption algorithm"</string>
@@ -193,6 +193,8 @@
<string name="pref_keyserver_summary">"Search keys on selected OpenPGP keyservers (HKP protocol)"</string>
<string name="pref_keybase">"keybase.io"</string>
<string name="pref_keybase_summary">"Search keys on keybase.io"</string>
+ <string name="pref_facebook">"Facebook"</string>
+ <string name="pref_facebook_summary">"Search keys on Facebook by username"</string>
<string name="label_sync_settings_keyserver_title">"Automatic key updates"</string>
<string name="label_sync_settings_keyserver_summary_on">"Every three days, keys are updated from the preferred keyserver"</string>
@@ -1294,6 +1296,7 @@
<string name="msg_import_fetch_error_keyserver">"Could not retrieve key from keyservers: %s"</string>
<string name="msg_import_fetch_error_keyserver_secret">"Cannot import secret key from keyserver!"</string>
<string name="msg_import_fetch_keybase">"Retrieving from keybase.io: %s"</string>
+ <string name="msg_import_fetch_facebook">"Retrieving from Facebook: %s"</string>
<string name="msg_import_fetch_keyserver">"Retrieving from keyserver: %s"</string>
<string name="msg_import_fetch_keyserver_ok">"Key retrieval successful"</string>
<string name="msg_import_keyserver">"Using keyserver %s"</string>
diff --git a/OpenKeychain/src/main/res/xml/experimental_preferences.xml b/OpenKeychain/src/main/res/xml/experimental_preferences.xml
index ff1fa5a95..9312997b0 100644
--- a/OpenKeychain/src/main/res/xml/experimental_preferences.xml
+++ b/OpenKeychain/src/main/res/xml/experimental_preferences.xml
@@ -1,37 +1,38 @@
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<Preference
- android:persistent="false"
+ android:persistent="true"
android:selectable="false"
- android:title="@string/label_experimental_settings_desc_title"
- android:summary="@string/label_experimental_settings_desc_summary" />
+ android:summary="@string/label_experimental_settings_desc_summary"
+ android:title="@string/label_experimental_settings_desc_title" />
<SwitchPreference
android:defaultValue="false"
android:key="experimentalEnableWordConfirm"
- android:persistent="false"
+ android:persistent="true"
android:summary="@string/label_experimental_settings_word_confirm_summary"
android:title="@string/label_experimental_settings_word_confirm_title" />
<SwitchPreference
android:defaultValue="false"
android:key="experimentalEnableLinkedIdentities"
- android:persistent="false"
+ android:persistent="true"
android:summary="@string/label_experimental_settings_linked_identities_summary"
android:title="@string/label_experimental_settings_linked_identities_title" />
<SwitchPreference
android:defaultValue="false"
android:key="experimentalEnableKeybase"
- android:persistent="false"
+ android:persistent="true"
android:summary="@string/label_experimental_settings_keybase_summary"
android:title="@string/label_experimental_settings_keybase_title" />
<ListPreference
+ android:defaultValue="light"
android:dialogTitle="@string/label_theme"
android:entries="@array/theme_entries"
android:entryValues="@array/theme_values"
android:key="theme"
- android:persistent="false"
+ android:persistent="true"
android:title="@string/label_theme" />
</PreferenceScreen>
diff --git a/OpenKeychain/src/main/res/xml/passphrase_preferences.xml b/OpenKeychain/src/main/res/xml/passphrase_preferences.xml
index 86de8a4b7..75f293c43 100644
--- a/OpenKeychain/src/main/res/xml/passphrase_preferences.xml
+++ b/OpenKeychain/src/main/res/xml/passphrase_preferences.xml
@@ -7,11 +7,11 @@
android:title="@string/label_passphrase_cache_ttl" />
<CheckBoxPreference
android:key="passphraseCacheSubs"
- android:persistent="false"
+ android:persistent="true"
android:title="@string/label_passphrase_cache_subs" />
<CheckBoxPreference
android:defaultValue="false"
android:key="useNumKeypadForYubikeyPin"
- android:persistent="false"
+ android:persistent="true"
android:title="@string/label_use_num_keypad_for_yubikey_pin" />
</PreferenceScreen>