From f29280bbb268d112426c6662e1227118819fb904 Mon Sep 17 00:00:00 2001 From: Adithya Abraham Philip Date: Wed, 25 Nov 2015 01:35:41 +0530 Subject: added Facebook links support, reworked Preferences --- OpenKeychain/src/main/AndroidManifest.xml | 16 ++ .../keychain/keyimport/CloudSearch.java | 3 + .../keychain/keyimport/FacebookKeyserver.java | 197 ++++++++++++++++++ .../keychain/keyimport/ImportKeysList.java | 12 +- .../keychain/keyimport/ImportKeysListEntry.java | 25 ++- .../keychain/keyimport/KeybaseKeyserver.java | 5 +- .../keychain/keyimport/Keyserver.java | 1 - .../keychain/keyimport/ParcelableKeyRing.java | 27 ++- .../keychain/operations/ImportOperation.java | 46 +++++ .../operations/results/OperationResult.java | 13 ++ .../service/KeyserverSyncAdapterService.java | 2 +- .../ui/CreateYubiKeyImportResetFragment.java | 9 +- .../keychain/ui/DecryptFragment.java | 9 +- .../keychain/ui/DecryptListFragment.java | 10 +- .../keychain/ui/ImportKeysActivity.java | 94 +++++---- .../keychain/ui/ImportKeysCloudFragment.java | 37 ++-- .../keychain/ui/ImportKeysListFragment.java | 45 ++-- .../keychain/ui/ImportKeysProxyActivity.java | 11 +- .../keychain/ui/KeyListFragment.java | 9 +- .../keychain/ui/SettingsActivity.java | 228 +++++---------------- .../keychain/ui/ViewKeyActivity.java | 10 +- .../keychain/util/EmailKeyHelper.java | 2 +- .../keychain/util/Preferences.java | 100 +++++---- OpenKeychain/src/main/res/values/strings.xml | 3 + .../src/main/res/xml/experimental_preferences.xml | 10 +- .../src/main/res/xml/passphrase_preferences.xml | 4 +- 26 files changed, 554 insertions(+), 374 deletions(-) create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/FacebookKeyserver.java 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 @@ + + + + + + + + + + + + + + + + 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 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 + * Copyright (C) 2015 Vincent Breitmoser + * Copyright (C) 2015 Adithya Abraham Philip + * + * 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 . + */ + +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 search(String fbUsername) + throws QueryFailedException, QueryNeedsRepairException { + List 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 { 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 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 CREATOR = new Creator() { 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 { 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 { 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 { 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 9877f2318..84bdb3eb6 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 CREATOR = new Parcelable.Creator() { + @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/service/KeyserverSyncAdapterService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeyserverSyncAdapterService.java index fc3224e39..35b4c2a7c 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeyserverSyncAdapterService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeyserverSyncAdapterService.java @@ -440,7 +440,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(); 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 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 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 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 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..0701dbb91 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,9 +84,7 @@ 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 namesAndEmails = ContactHelper.getContactNames(getActivity()); namesAndEmails.addAll(ContactHelper.getContactMails(getActivity())); @@ -96,7 +96,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 +117,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 +161,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 selectedEntries = new ArrayList<>(); selectedEntries.add(keyEntry); @@ -209,12 +207,7 @@ public class ImportKeysProxyActivity extends FragmentActivity private void startImportService(ArrayList 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..2b994e11c 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
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) { @@ -542,7 +541,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 +550,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 +578,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..ea87aa113 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java @@ -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 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/util/EmailKeyHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/EmailKeyHelper.java index a55249842..d3cf74d16 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/EmailKeyHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/EmailKeyHelper.java @@ -57,7 +57,7 @@ public class EmailKeyHelper { // Put them in a list and import ArrayList 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 CREATOR + = new Parcelable.Creator() { + @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/values/strings.xml b/OpenKeychain/src/main/res/values/strings.xml index c9eba5db2..b94c09273 100644 --- a/OpenKeychain/src/main/res/values/strings.xml +++ b/OpenKeychain/src/main/res/values/strings.xml @@ -193,6 +193,8 @@ "Search keys on selected OpenPGP keyservers (HKP protocol)" "keybase.io" "Search keys on keybase.io" + "Facebook" + "Search keys on Facebook by username" "Automatic key updates" "Every three days, keys are updated from the preferred keyserver" @@ -1294,6 +1296,7 @@ "Could not retrieve key from keyservers: %s" "Cannot import secret key from keyserver!" "Retrieving from keybase.io: %s" + "Retrieving from Facebook: %s" "Retrieving from keyserver: %s" "Key retrieval successful" "Using keyserver %s" diff --git a/OpenKeychain/src/main/res/xml/experimental_preferences.xml b/OpenKeychain/src/main/res/xml/experimental_preferences.xml index ff1fa5a95..1c8fae46f 100644 --- a/OpenKeychain/src/main/res/xml/experimental_preferences.xml +++ b/OpenKeychain/src/main/res/xml/experimental_preferences.xml @@ -1,6 +1,6 @@ @@ -8,21 +8,21 @@ @@ -31,7 +31,7 @@ android:entries="@array/theme_entries" android:entryValues="@array/theme_values" android:key="theme" - android:persistent="false" + android:persistent="true" android:title="@string/label_theme" /> 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" /> -- cgit v1.2.3