aboutsummaryrefslogtreecommitdiffstats
path: root/OpenKeychain/src/main/java
diff options
context:
space:
mode:
Diffstat (limited to 'OpenKeychain/src/main/java')
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/HkpKeyserver.java7
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java8
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyFragment.java1
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyYubiImportFragment.java3
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java20
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java4
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java15
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextFragment.java13
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java93
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysCloudFragment.java23
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java56
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysProxyActivity.java70
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java19
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcIntentActivity.java314
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcOperationActivity.java22
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsActivity.java28
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsKeyServerActivity.java60
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java8
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyYubiKeyFragment.java (renamed from OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyYubikeyFragment.java)30
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListLoader.java4
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseNfcActivity.java116
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/CryptoOperationFragment.java (renamed from OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CryptoOperationFragment.java)4
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddKeyserverDialogFragment.java320
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Preferences.java13
26 files changed, 729 insertions, 526 deletions
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/HkpKeyserver.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/HkpKeyserver.java
index 480319081..cb8a53e25 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/HkpKeyserver.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/HkpKeyserver.java
@@ -242,7 +242,7 @@ public class HkpKeyserver extends Keyserver {
String encodedQuery;
try {
- encodedQuery = URLEncoder.encode(query, "utf8");
+ encodedQuery = URLEncoder.encode(query, "UTF8");
} catch (UnsupportedEncodingException e) {
return null;
}
@@ -286,7 +286,7 @@ public class HkpKeyserver extends Keyserver {
entry.setAlgorithm(KeyFormattingUtils.getAlgorithmInfo(algorithmId, bitSize, null));
// group 1 contains the full fingerprint (v4) or the long key id if available
- // see http://bit.ly/1d4bxbk and http://bit.ly/1gD1wwr
+ // see https://bitbucket.org/skskeyserver/sks-keyserver/pull-request/12/fixes-for-machine-readable-indexes/diff
String fingerprintOrKeyId = matcher.group(1).toLowerCase(Locale.ENGLISH);
if (fingerprintOrKeyId.length() > 16) {
entry.setFingerprintHex(fingerprintOrKeyId);
@@ -312,14 +312,13 @@ public class HkpKeyserver extends Keyserver {
String tmp = uidMatcher.group(1).trim();
if (tmp.contains("%")) {
if (tmp.contains("%%")) {
- // This is a fix for issue #683
// The server encodes a percent sign as %%, so it is swapped out with its
// urlencoded counterpart to prevent errors
tmp = tmp.replace("%%", "%25");
}
try {
// converts Strings like "Universit%C3%A4t" to a proper encoding form "Universität".
- tmp = (URLDecoder.decode(tmp, "UTF8"));
+ tmp = URLDecoder.decode(tmp, "UTF8");
} catch (UnsupportedEncodingException ignored) {
// will never happen, because "UTF8" is supported
}
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 71843cd7f..c51edf59c 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java
@@ -167,7 +167,7 @@ public class OpenPgpService extends RemoteService {
switch (requiredInput.mType) {
case NFC_DECRYPT:
case NFC_SIGN: {
- // build PendingIntent for Yubikey NFC operations
+ // build PendingIntent for YubiKey NFC operations
Intent intent = new Intent(context, NfcOperationActivity.class);
// pass params through to activity that it can be returned again later to repeat pgp operation
intent.putExtra(NfcOperationActivity.EXTRA_SERVICE_INTENT, data);
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 03c250035..78137170d 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java
@@ -245,11 +245,11 @@ public class PassphraseCacheService extends Service {
switch (keyType) {
case DIVERT_TO_CARD:
- if (Preferences.getPreferences(this).useDefaultYubikeyPin()) {
- Log.d(Constants.TAG, "PassphraseCacheService: Using default Yubikey PIN: 123456");
- return new Passphrase("123456"); // default Yubikey PIN, see http://www.yubico.com/2012/12/yubikey-neo-openpgp/
+ if (Preferences.getPreferences(this).useDefaultYubiKeyPin()) {
+ Log.d(Constants.TAG, "PassphraseCacheService: Using default YubiKey PIN: 123456");
+ return new Passphrase("123456"); // default YubiKey PIN, see http://www.yubico.com/2012/12/yubikey-neo-openpgp/
} else {
- Log.d(Constants.TAG, "PassphraseCacheService: NOT using default Yubikey PIN");
+ Log.d(Constants.TAG, "PassphraseCacheService: NOT using default YubiKey PIN");
break;
}
case PASSPHRASE_EMPTY:
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyFragment.java
index 20a280a54..59623a610 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyFragment.java
@@ -56,6 +56,7 @@ import org.sufficientlysecure.keychain.service.KeychainIntentService;
import org.sufficientlysecure.keychain.service.ServiceProgressHandler;
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
import org.sufficientlysecure.keychain.ui.adapter.MultiUserIdsAdapter;
+import org.sufficientlysecure.keychain.ui.base.CryptoOperationFragment;
import org.sufficientlysecure.keychain.ui.dialog.ProgressDialogFragment;
import org.sufficientlysecure.keychain.ui.util.Notify;
import org.sufficientlysecure.keychain.ui.widget.CertifyKeySpinner;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyYubiImportFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyYubiImportFragment.java
index 1cd0aaf2f..db62d53c5 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyYubiImportFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyYubiImportFragment.java
@@ -123,7 +123,8 @@ public class CreateKeyYubiImportFragment extends Fragment implements NfcListener
});
}
- mListFragment = ImportKeysListFragment.newInstance(null, null, "0x" + mNfcFingerprint, true);
+ mListFragment = ImportKeysListFragment.newInstance(null, null,
+ "0x" + mNfcFingerprint, true, null);
view.findViewById(R.id.button_search).setOnClickListener(new OnClickListener() {
@Override
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 f320a6d84..33209be86 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java
@@ -29,6 +29,7 @@ import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.operations.results.DecryptVerifyResult;
import org.sufficientlysecure.keychain.pgp.KeyRing;
import org.sufficientlysecure.keychain.provider.KeychainContract;
+import org.sufficientlysecure.keychain.ui.base.CryptoOperationFragment;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils.State;
@@ -85,25 +86,6 @@ public abstract class DecryptFragment extends CryptoOperationFragment {
startActivity(viewKeyIntent);
}
-// protected void startPassphraseDialog(long subkeyId) {
-// Intent intent = new Intent(getActivity(), PassphraseDialogActivity.class);
-// intent.putExtra(PassphraseDialogActivity.EXTRA_SUBKEY_ID, subkeyId);
-// startActivityForResult(intent, REQUEST_CODE_PASSPHRASE);
-// }
-//
-// protected void startNfcDecrypt(long subKeyId, Passphrase pin, byte[] encryptedSessionKey) {
-// // build PendingIntent for Yubikey NFC operations
-// Intent intent = new Intent(getActivity(), NfcActivity.class);
-// intent.setAction(NfcActivity.ACTION_DECRYPT_SESSION_KEY);
-// intent.putExtra(NfcActivity.EXTRA_SERVICE_INTENT, new Intent()); // not used, only relevant to OpenPgpService
-// intent.putExtra(NfcActivity.EXTRA_KEY_ID, subKeyId);
-// intent.putExtra(NfcActivity.EXTRA_PIN, pin);
-//
-// intent.putExtra(NfcActivity.EXTRA_NFC_ENC_SESSION_KEY, encryptedSessionKey);
-//
-// startActivityForResult(intent, REQUEST_CODE_NFC_DECRYPT);
-// }
-
/**
*
* @return returns false if signature is invalid, key is revoked or expired.
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java
index bf17c2991..390efddce 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java
@@ -17,8 +17,6 @@
package org.sufficientlysecure.keychain.ui;
-import java.util.Date;
-
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
@@ -53,7 +51,6 @@ import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.provider.ProviderHelper.NotFoundException;
import org.sufficientlysecure.keychain.service.KeychainIntentService;
import org.sufficientlysecure.keychain.service.ServiceProgressHandler;
-import org.sufficientlysecure.keychain.service.PassphraseCacheService;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.ChangeUnlockParcel;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.SubkeyChange;
@@ -62,6 +59,7 @@ import org.sufficientlysecure.keychain.ui.adapter.SubkeysAdapter;
import org.sufficientlysecure.keychain.ui.adapter.SubkeysAddedAdapter;
import org.sufficientlysecure.keychain.ui.adapter.UserIdsAdapter;
import org.sufficientlysecure.keychain.ui.adapter.UserIdsAddedAdapter;
+import org.sufficientlysecure.keychain.ui.base.CryptoOperationFragment;
import org.sufficientlysecure.keychain.ui.dialog.*;
import org.sufficientlysecure.keychain.ui.util.Notify;
import org.sufficientlysecure.keychain.util.Log;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java
index ddced7cce..458810541 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java
@@ -53,6 +53,7 @@ import org.sufficientlysecure.keychain.service.KeychainIntentService;
import org.sufficientlysecure.keychain.service.ServiceProgressHandler;
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
import org.sufficientlysecure.keychain.ui.adapter.SpacesItemDecoration;
+import org.sufficientlysecure.keychain.ui.base.CryptoOperationFragment;
import org.sufficientlysecure.keychain.ui.dialog.DeleteFileDialogFragment;
import org.sufficientlysecure.keychain.ui.dialog.ProgressDialogFragment;
import org.sufficientlysecure.keychain.ui.util.FormattingUtils;
@@ -201,7 +202,7 @@ public class EncryptFilesFragment extends CryptoOperationFragment {
} catch (IOException e) {
Notify.create(getActivity(),
getActivity().getString(R.string.error_file_added_already, FileHelper.getFilename(getActivity(), inputUri)),
- Notify.Style.ERROR).show();
+ Notify.Style.ERROR).show(this);
return;
}
mSelectedFiles.requestFocus();
@@ -229,7 +230,7 @@ public class EncryptFilesFragment extends CryptoOperationFragment {
private void encryptClicked(boolean share) {
if (mFilesModels.isEmpty()) {
Notify.create(getActivity(), R.string.error_no_file_selected,
- Notify.Style.ERROR).show();
+ Notify.Style.ERROR).show(this);
return;
}
if (share) {
@@ -246,7 +247,7 @@ public class EncryptFilesFragment extends CryptoOperationFragment {
} else {
if (mFilesModels.size() > 1) {
Notify.create(getActivity(), R.string.error_multi_not_supported,
- Notify.Style.ERROR).show();
+ Notify.Style.ERROR).show(this);
return;
}
showOutputFileDialog();
@@ -329,7 +330,7 @@ public class EncryptFilesFragment extends CryptoOperationFragment {
if (mFilesModels.isEmpty()) {
Notify.create(getActivity(), R.string.no_file_selected, Notify.Style.ERROR)
- .show();
+ .show(this);
return false;
} else if (mFilesModels.size() > 1 && !mShareAfterEncrypt) {
Log.e(Constants.TAG, "Aborting: mInputUris.size() > 1 && !mShareAfterEncrypt");
@@ -346,12 +347,12 @@ public class EncryptFilesFragment extends CryptoOperationFragment {
if (mPassphrase == null) {
Notify.create(getActivity(), R.string.passphrases_do_not_match, Notify.Style.ERROR)
- .show();
+ .show(this);
return false;
}
if (mPassphrase.isEmpty()) {
Notify.create(getActivity(), R.string.passphrase_must_not_be_empty, Notify.Style.ERROR)
- .show();
+ .show(this);
return false;
}
@@ -364,7 +365,7 @@ public class EncryptFilesFragment extends CryptoOperationFragment {
// Files must be encrypted, only text can be signed-only right now
if (!gotEncryptionKeys) {
Notify.create(getActivity(), R.string.select_encryption_key, Notify.Style.ERROR)
- .show();
+ .show(this);
return false;
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextFragment.java
index 47645099d..3f9147cc4 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextFragment.java
@@ -44,6 +44,7 @@ import org.sufficientlysecure.keychain.pgp.SignEncryptParcel;
import org.sufficientlysecure.keychain.service.KeychainIntentService;
import org.sufficientlysecure.keychain.service.ServiceProgressHandler;
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
+import org.sufficientlysecure.keychain.ui.base.CryptoOperationFragment;
import org.sufficientlysecure.keychain.ui.dialog.ProgressDialogFragment;
import org.sufficientlysecure.keychain.ui.util.Notify;
import org.sufficientlysecure.keychain.util.Log;
@@ -287,9 +288,9 @@ public class EncryptTextFragment extends CryptoOperationFragment {
}
protected boolean inputIsValid() {
- if (mMessage == null) {
- Notify.create(getActivity(), R.string.error_message, Notify.Style.ERROR)
- .show();
+ if (mMessage == null || mMessage.isEmpty()) {
+ Notify.create(getActivity(), R.string.error_empty_text, Notify.Style.ERROR)
+ .show(this);
return false;
}
@@ -298,12 +299,12 @@ public class EncryptTextFragment extends CryptoOperationFragment {
if (mSymmetricPassphrase == null) {
Notify.create(getActivity(), R.string.passphrases_do_not_match, Notify.Style.ERROR)
- .show();
+ .show(this);
return false;
}
if (mSymmetricPassphrase.isEmpty()) {
Notify.create(getActivity(), R.string.passphrase_must_not_be_empty, Notify.Style.ERROR)
- .show();
+ .show(this);
return false;
}
@@ -315,7 +316,7 @@ public class EncryptTextFragment extends CryptoOperationFragment {
if (!gotEncryptionKeys && mSigningKeyId == 0) {
Notify.create(getActivity(), R.string.select_encryption_or_signature_key, Notify.Style.ERROR)
- .show();
+ .show(this);
return false;
}
}
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 7fe5be793..5d9950db6 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java
@@ -39,6 +39,7 @@ import org.sufficientlysecure.keychain.ui.base.BaseNfcActivity;
import org.sufficientlysecure.keychain.service.CloudImportService;
import org.sufficientlysecure.keychain.service.ServiceProgressHandler;
import org.sufficientlysecure.keychain.ui.dialog.ProgressDialogFragment;
+import org.sufficientlysecure.keychain.ui.util.FormattingUtils;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.ui.util.Notify;
import org.sufficientlysecure.keychain.util.Log;
@@ -62,6 +63,8 @@ public class ImportKeysActivity extends BaseNfcActivity {
// Actions for internal use only:
public static final String ACTION_IMPORT_KEY_FROM_FILE = Constants.INTENT_PREFIX
+ "IMPORT_KEY_FROM_FILE";
+ public static final String ACTION_SEARCH_KEYSERVER_FROM_URL = Constants.INTENT_PREFIX
+ + "SEARCH_KEYSERVER_FROM_URL";
public static final String EXTRA_RESULT = "result";
// only used by ACTION_IMPORT_KEY
@@ -112,15 +115,19 @@ public class ImportKeysActivity extends BaseNfcActivity {
}
if (action == null) {
- startCloudFragment(savedInstanceState, null, false);
- startListFragment(savedInstanceState, null, null, null);
+ startCloudFragment(savedInstanceState, null, false, null);
+ startListFragment(savedInstanceState, null, null, null, null);
return;
}
if (Intent.ACTION_VIEW.equals(action)) {
- // Android's Action when opening file associated to Keychain (see AndroidManifest.xml)
- // delegate action to ACTION_IMPORT_KEY
- action = ACTION_IMPORT_KEY;
+ if (scheme.equals("http") || scheme.equals("https")) {
+ action = ACTION_SEARCH_KEYSERVER_FROM_URL;
+ } else {
+ // Android's Action when opening file associated to Keychain (see AndroidManifest.xml)
+ // delegate action to ACTION_IMPORT_KEY
+ action = ACTION_IMPORT_KEY;
+ }
}
switch (action) {
@@ -130,12 +137,12 @@ public class ImportKeysActivity extends BaseNfcActivity {
if (dataUri != null) {
// action: directly load data
- startListFragment(savedInstanceState, null, dataUri, null);
+ startListFragment(savedInstanceState, null, dataUri, null, null);
} else if (extras.containsKey(EXTRA_KEY_BYTES)) {
byte[] importData = extras.getByteArray(EXTRA_KEY_BYTES);
// action: directly load data
- startListFragment(savedInstanceState, importData, null, null);
+ startListFragment(savedInstanceState, importData, null, null, null);
}
break;
}
@@ -162,10 +169,10 @@ public class ImportKeysActivity extends BaseNfcActivity {
if (query != null && query.length() > 0) {
// display keyserver fragment with query
- startCloudFragment(savedInstanceState, query, false);
+ startCloudFragment(savedInstanceState, query, false, null);
// action: search immediately
- startListFragment(savedInstanceState, null, null, query);
+ startListFragment(savedInstanceState, null, null, query, null);
} else {
Log.e(Constants.TAG, "Query is empty!");
return;
@@ -181,10 +188,10 @@ public class ImportKeysActivity extends BaseNfcActivity {
String query = "0x" + fingerprint;
// display keyserver fragment with query
- startCloudFragment(savedInstanceState, query, true);
+ startCloudFragment(savedInstanceState, query, true, null);
// action: search immediately
- startListFragment(savedInstanceState, null, null, query);
+ startListFragment(savedInstanceState, null, null, query, null);
}
} else {
Log.e(Constants.TAG,
@@ -200,7 +207,29 @@ public class ImportKeysActivity extends BaseNfcActivity {
startFileFragment(savedInstanceState);
// no immediate actions!
- startListFragment(savedInstanceState, null, null, null);
+ startListFragment(savedInstanceState, null, null, null, null);
+ 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(mTopFragment);
+ // we just set the keyserver
+ startCloudFragment(savedInstanceState, null, false, keyserver);
+ // it's not necessary to set the keyserver for ImportKeysListFragment since
+ // it'll be taken care of by ImportKeysCloudFragment when the user clicks
+ // the search button
+ startListFragment(savedInstanceState, null, null, null, null);
+ } else {
+ // we allow our users to edit the query if they wish
+ startCloudFragment(savedInstanceState, query, false, keyserver);
+ // search immediately
+ startListFragment(savedInstanceState, null, null, query, keyserver);
+ }
break;
}
case ACTION_IMPORT_KEY_FROM_FILE_AND_RETURN: {
@@ -208,18 +237,31 @@ public class ImportKeysActivity extends BaseNfcActivity {
startFileFragment(savedInstanceState);
// no immediate actions!
- startListFragment(savedInstanceState, null, null, null);
+ startListFragment(savedInstanceState, null, null, null, null);
break;
}
default: {
- startCloudFragment(savedInstanceState, null, false);
- startListFragment(savedInstanceState, null, null, null);
+ startCloudFragment(savedInstanceState, null, false, null);
+ startListFragment(savedInstanceState, null, null, null, null);
break;
}
}
}
- private void startListFragment(Bundle savedInstanceState, byte[] bytes, Uri dataUri, String serverQuery) {
+
+ /**
+ * if the fragment is started with non-null bytes/dataUri/serverQuery, it will immediately
+ * load content
+ *
+ * @param savedInstanceState
+ * @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
+ */
+ private void startListFragment(Bundle savedInstanceState, byte[] bytes, Uri dataUri,
+ String serverQuery, String keyserver) {
// However, if we're being restored from a previous state,
// then we don't need to do anything and should return or else
// we could end up with overlapping fragments.
@@ -227,8 +269,8 @@ public class ImportKeysActivity extends BaseNfcActivity {
return;
}
- // Create an instance of the fragment
- mListFragment = ImportKeysListFragment.newInstance(bytes, dataUri, serverQuery);
+ mListFragment = ImportKeysListFragment.newInstance(bytes, dataUri, serverQuery, false,
+ keyserver);
// Add the fragment to the 'fragment_container' FrameLayout
// NOTE: We use commitAllowingStateLoss() to prevent weird crashes!
@@ -259,7 +301,18 @@ public class ImportKeysActivity extends BaseNfcActivity {
getSupportFragmentManager().executePendingTransactions();
}
- private void startCloudFragment(Bundle savedInstanceState, String query, boolean disableQueryEdit) {
+ /**
+ * loads the CloudFragment, which consists of the search bar, search button and settings icon
+ * visually.
+ *
+ * @param savedInstanceState
+ * @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
+ */
+
+ private void startCloudFragment(Bundle savedInstanceState, String query, boolean disableQueryEdit, String keyserver) {
// However, if we're being restored from a previous state,
// then we don't need to do anything and should return or else
// we could end up with overlapping fragments.
@@ -268,7 +321,7 @@ public class ImportKeysActivity extends BaseNfcActivity {
}
// Create an instance of the fragment
- mTopFragment = ImportKeysCloudFragment.newInstance(query, disableQueryEdit);
+ mTopFragment = ImportKeysCloudFragment.newInstance(query, disableQueryEdit, keyserver);
// Add the fragment to the 'fragment_container' FrameLayout
// NOTE: We use commitAllowingStateLoss() to prevent weird crashes!
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysCloudFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysCloudFragment.java
index 91ca93c36..1cd5c24f3 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysCloudFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysCloudFragment.java
@@ -45,6 +45,7 @@ import java.util.List;
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";
private ImportKeysActivity mImportActivity;
@@ -54,13 +55,20 @@ public class ImportKeysCloudFragment extends Fragment {
/**
* 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
*/
- public static ImportKeysCloudFragment newInstance(String query, boolean disableQueryEdit) {
+ public static ImportKeysCloudFragment newInstance(String query, boolean disableQueryEdit,
+ String keyserver) {
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);
frag.setArguments(args);
@@ -151,8 +159,17 @@ public class ImportKeysCloudFragment extends Fragment {
}
private void search(String query) {
- Preferences prefs = Preferences.getPreferences(getActivity());
- mImportActivity.loadCallback(new ImportKeysListFragment.CloudLoaderState(query, prefs.getCloudSearchPrefs()));
+ Preferences.CloudSearchPrefs cloudSearchPrefs;
+ String explicitKeyserver = getArguments().getString(ARG_KEYSERVER);
+ // no explicit keyserver passed
+ if (explicitKeyserver == 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 b9fdbea5c..bf7e41045 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java
@@ -58,6 +58,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";
private Activity mActivity;
private ImportKeysAdapter mAdapter;
@@ -78,7 +79,8 @@ public class ImportKeysListFragment extends ListFragment implements
return mAdapter.getData();
}
- /** Returns an Iterator (with size) of the selected data items.
+ /**
+ * Returns an Iterator (with size) of the selected data items.
* This iterator is sort of a tradeoff, it's slightly more complex than an
* ArrayList would have been, but we save some memory by just returning
* relevant elements on demand.
@@ -121,12 +123,36 @@ public class ImportKeysListFragment extends ListFragment implements
}
- public static ImportKeysListFragment newInstance(byte[] bytes, Uri dataUri, String serverQuery) {
- return newInstance(bytes, dataUri, serverQuery, false);
+ /**
+ * Creates an interactive ImportKeyListFragment which reads keyrings from bytes, or file specified
+ * by dataUri, or searches a keyserver for serverQuery, if parameter is not null, in that order
+ *
+ * @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
+ * @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);
}
- public static ImportKeysListFragment newInstance(byte[] bytes, Uri dataUri,
- String serverQuery, boolean nonInteractive) {
+ /**
+ * Visually consists of a list of keyrings with checkboxes to specify which are to be imported
+ * Can immediately load keyrings specified by any of its parameters
+ *
+ * @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
+ * @return fragment with arguments set based on passed parameters
+ */
+ public static ImportKeysListFragment newInstance(byte[] bytes, Uri dataUri, String serverQuery,
+ boolean nonInteractive, String keyserver) {
ImportKeysListFragment frag = new ImportKeysListFragment();
Bundle args = new Bundle();
@@ -134,6 +160,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);
frag.setArguments(args);
@@ -180,16 +207,23 @@ public class ImportKeysListFragment extends ListFragment implements
setListAdapter(mAdapter);
Bundle args = getArguments();
- Uri dataUri = args.containsKey(ARG_DATA_URI) ? args.<Uri>getParcelable(ARG_DATA_URI) : null;
- byte[] bytes = args.containsKey(ARG_BYTES) ? args.getByteArray(ARG_BYTES) : null;
- String query = args.containsKey(ARG_SERVER_QUERY) ? args.getString(ARG_SERVER_QUERY) : null;
- mNonInteractive = args.containsKey(ARG_NON_INTERACTIVE) ? args.getBoolean(ARG_NON_INTERACTIVE) : false;
+ 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);
if (dataUri != null || bytes != null) {
mLoaderState = new BytesLoaderState(bytes, dataUri);
} else if (query != null) {
- Preferences prefs = Preferences.getPreferences(getActivity());
- mLoaderState = new CloudLoaderState(query, prefs.getCloudSearchPrefs());
+ Preferences.CloudSearchPrefs cloudSearchPrefs;
+ if (keyserver == null) {
+ cloudSearchPrefs = Preferences.getPreferences(getActivity()).getCloudSearchPrefs();
+ } else {
+ cloudSearchPrefs = new Preferences.CloudSearchPrefs(true, true, keyserver);
+ }
+
+ mLoaderState = new CloudLoaderState(query, cloudSearchPrefs);
}
getListView().setOnTouchListener(new OnTouchListener() {
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 21747f77b..29f2511a0 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysProxyActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysProxyActivity.java
@@ -20,6 +20,7 @@ package org.sufficientlysecure.keychain.ui;
import android.annotation.TargetApi;
import android.app.ProgressDialog;
import android.content.Intent;
+import android.content.pm.ActivityInfo;
import android.net.Uri;
import android.nfc.NdefMessage;
import android.nfc.NfcAdapter;
@@ -57,13 +58,12 @@ import java.util.Locale;
public class ImportKeysProxyActivity extends FragmentActivity {
public static final String ACTION_QR_CODE_API = OpenKeychainIntents.IMPORT_KEY_FROM_QR_CODE;
+ // implies activity returns scanned fingerprint as extra and does not import
public static final String ACTION_SCAN_WITH_RESULT = Constants.INTENT_PREFIX + "SCAN_QR_CODE_WITH_RESULT";
public static final String ACTION_SCAN_IMPORT = Constants.INTENT_PREFIX + "SCAN_QR_CODE_IMPORT";
public static final String EXTRA_FINGERPRINT = "fingerprint";
- boolean returnResult;
-
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -81,31 +81,18 @@ public class ImportKeysProxyActivity extends FragmentActivity {
if (scheme != null && scheme.toLowerCase(Locale.ENGLISH).equals(Constants.FINGERPRINT_SCHEME)) {
// Scanning a fingerprint directly with Barcode Scanner, thus we already have scanned
- returnResult = false;
processScannedContent(dataUri);
- } else if (ACTION_SCAN_IMPORT.equals(action)) {
- returnResult = false;
- IntentIntegrator integrator = new IntentIntegrator(this);
- integrator.setDesiredBarcodeFormats(IntentIntegrator.QR_CODE_TYPES)
- .setPrompt(getString(R.string.import_qr_code_text))
- .setResultDisplayDuration(0)
- .initiateScan();
- } else if (ACTION_SCAN_WITH_RESULT.equals(action)) {
- returnResult = true;
+ } else if (ACTION_SCAN_WITH_RESULT.equals(action)
+ || ACTION_SCAN_IMPORT.equals(action) || ACTION_QR_CODE_API.equals(action)) {
IntentIntegrator integrator = new IntentIntegrator(this);
integrator.setDesiredBarcodeFormats(IntentIntegrator.QR_CODE_TYPES)
.setPrompt(getString(R.string.import_qr_code_text))
- .setResultDisplayDuration(0)
- .initiateScan();
- } else if (ACTION_QR_CODE_API.equals(action)) {
- // scan using xzing's Barcode Scanner from outside OpenKeychain
-
- returnResult = false;
- new IntentIntegrator(this).initiateScan();
+ .setResultDisplayDuration(0);
+ integrator.setOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
+ integrator.initiateScan();
} else if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(getIntent().getAction())) {
// Check to see if the Activity started due to an Android Beam
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
- returnResult = false;
handleActionNdefDiscovered(getIntent());
} else {
Log.e(Constants.TAG, "Android Beam not supported by Android < 4.1");
@@ -149,69 +136,63 @@ public class ImportKeysProxyActivity extends FragmentActivity {
}
private void processScannedContent(Uri uri) {
+ String action = getIntent().getAction();
Log.d(Constants.TAG, "scanned: " + uri);
- String fingerprint = null;
-
// example: openpgp4fpr:73EE2314F65FA92EC2390D3A718C070100012282
if (uri != null && uri.getScheme() != null && uri.getScheme().toLowerCase(Locale.ENGLISH).equals(Constants.FINGERPRINT_SCHEME)) {
- fingerprint = uri.getEncodedSchemeSpecificPart().toLowerCase(Locale.ENGLISH);
- }
+ String fingerprint = uri.getEncodedSchemeSpecificPart().toLowerCase(Locale.ENGLISH);
- if (fingerprint == null) {
+ if (ACTION_SCAN_WITH_RESULT.equals(action)) {
+ Intent result = new Intent();
+ result.putExtra(EXTRA_FINGERPRINT, fingerprint);
+ setResult(RESULT_OK, result);
+ finish();
+ } else {
+ importKeys(fingerprint);
+ }
+ } else {
SingletonResult result = new SingletonResult(
SingletonResult.RESULT_ERROR, OperationResult.LogType.MSG_WRONG_QR_CODE);
Intent intent = new Intent();
intent.putExtra(SingletonResult.EXTRA_RESULT, result);
returnResult(intent);
- return;
- }
-
- if (returnResult) {
- Intent result = new Intent();
- result.putExtra(EXTRA_FINGERPRINT, fingerprint);
- setResult(RESULT_OK, result);
- finish();
- } else {
- importKeys(fingerprint);
}
}
public void returnResult(Intent data) {
- if (returnResult) {
- setResult(RESULT_OK, data);
- finish();
- } else {
+ String action = getIntent().getAction();
+
+ if (ACTION_QR_CODE_API.equals(action)) {
// display last log message but as Toast for calls from outside OpenKeychain
OperationResult result = data.getParcelableExtra(OperationResult.EXTRA_RESULT);
String str = getString(result.getLog().getLast().mType.getMsgId());
Toast.makeText(this, str, Toast.LENGTH_LONG).show();
finish();
+ } else {
+ setResult(RESULT_OK, data);
+ finish();
}
}
public void importKeys(byte[] keyringData) {
-
ParcelableKeyRing keyEntry = new ParcelableKeyRing(keyringData);
ArrayList<ParcelableKeyRing> selectedEntries = new ArrayList<>();
selectedEntries.add(keyEntry);
startImportService(selectedEntries);
-
}
public void importKeys(String fingerprint) {
-
ParcelableKeyRing keyEntry = new ParcelableKeyRing(fingerprint, null, null);
ArrayList<ParcelableKeyRing> selectedEntries = new ArrayList<>();
selectedEntries.add(keyEntry);
startImportService(selectedEntries);
-
}
- private void startImportService (ArrayList<ParcelableKeyRing> keyRings) {
+ private void startImportService(ArrayList<ParcelableKeyRing> keyRings) {
// Message is received after importing is done in KeychainIntentService
ServiceProgressHandler serviceHandler = new ServiceProgressHandler(
@@ -284,7 +265,6 @@ public class ImportKeysProxyActivity extends FragmentActivity {
// start service with intent
startService(intent);
-
}
/**
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 4733dce01..96ce101b5 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java
@@ -681,17 +681,16 @@ public class KeyListFragment extends LoaderFragment
}
private void showMultiExportDialog(long[] masterKeyIds) {
- mIdsForRepeatAskPassphrase = new ArrayList<Long>();
- for(long id: masterKeyIds) {
+ mIdsForRepeatAskPassphrase = new ArrayList<>();
+ for (long id : masterKeyIds) {
try {
if (PassphraseCacheService.getCachedPassphrase(
getActivity(), id, id) == null) {
- mIdsForRepeatAskPassphrase.add(Long.valueOf(id));
+ mIdsForRepeatAskPassphrase.add(id);
}
} catch (PassphraseCacheService.KeyNotFoundException e) {
// This happens when the master key is stripped
// and ignore this key.
- continue;
}
}
mIndex = 0;
@@ -700,8 +699,8 @@ public class KeyListFragment extends LoaderFragment
return;
}
long[] idsForMultiExport = new long[mIdsForRepeatAskPassphrase.size()];
- for(int i=0; i<mIdsForRepeatAskPassphrase.size(); ++i) {
- idsForMultiExport[i] = mIdsForRepeatAskPassphrase.get(i).longValue();
+ for (int i = 0; i < mIdsForRepeatAskPassphrase.size(); ++i) {
+ idsForMultiExport[i] = mIdsForRepeatAskPassphrase.get(i);
}
mExportHelper.showExportKeysDialog(idsForMultiExport,
Constants.Path.APP_DIR_FILE,
@@ -710,7 +709,7 @@ public class KeyListFragment extends LoaderFragment
private void startPassphraseActivity() {
Intent intent = new Intent(getActivity(), PassphraseDialogActivity.class);
- long masterKeyId = mIdsForRepeatAskPassphrase.get(mIndex++).longValue();
+ long masterKeyId = mIdsForRepeatAskPassphrase.get(mIndex++);
intent.putExtra(PassphraseDialogActivity.EXTRA_SUBKEY_ID, masterKeyId);
startActivityForResult(intent, REQUEST_REPEAT_PASSPHRASE);
}
@@ -718,7 +717,7 @@ public class KeyListFragment extends LoaderFragment
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_REPEAT_PASSPHRASE) {
- if(resultCode != Activity.RESULT_OK) {
+ if (resultCode != Activity.RESULT_OK) {
return;
}
if (mIndex < mIdsForRepeatAskPassphrase.size()) {
@@ -726,8 +725,8 @@ public class KeyListFragment extends LoaderFragment
return;
}
long[] idsForMultiExport = new long[mIdsForRepeatAskPassphrase.size()];
- for(int i=0; i<mIdsForRepeatAskPassphrase.size(); ++i) {
- idsForMultiExport[i] = mIdsForRepeatAskPassphrase.get(i).longValue();
+ for (int i = 0; i < mIdsForRepeatAskPassphrase.size(); ++i) {
+ idsForMultiExport[i] = mIdsForRepeatAskPassphrase.get(i);
}
mExportHelper.showExportKeysDialog(idsForMultiExport,
Constants.Path.APP_DIR_FILE,
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcIntentActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcIntentActivity.java
deleted file mode 100644
index a1affbc39..000000000
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcIntentActivity.java
+++ /dev/null
@@ -1,314 +0,0 @@
-/**
- * Copyright (c) 2013-2014 Philipp Jakubeit, Signe Rüsch, Dominik Schürmann
- *
- * Licensed under the Bouncy Castle License (MIT license). See LICENSE file for details.
- */
-
-package org.sufficientlysecure.keychain.ui;
-
-import android.annotation.TargetApi;
-import android.app.PendingIntent;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.nfc.NfcAdapter;
-import android.nfc.Tag;
-import android.nfc.tech.IsoDep;
-import android.os.Build;
-import android.os.Bundle;
-import android.view.WindowManager;
-import android.widget.Toast;
-
-import org.spongycastle.util.encoders.Hex;
-import org.sufficientlysecure.keychain.Constants;
-import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.ui.base.BaseActivity;
-import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
-import org.sufficientlysecure.keychain.util.Iso7816TLV;
-import org.sufficientlysecure.keychain.util.Log;
-
-import java.io.IOException;
-import java.nio.ByteBuffer;
-
-/**
- * This class provides a communication interface to OpenPGP applications on ISO SmartCard compliant
- * NFC devices.
- *
- * For the full specs, see http://g10code.com/docs/openpgp-card-2.0.pdf
- */
-@TargetApi(Build.VERSION_CODES.GINGERBREAD_MR1)
-public class NfcIntentActivity extends BaseActivity {
-
- // special extra for OpenPgpService
- public static final String EXTRA_DATA = "data";
-
- private Intent mServiceIntent;
-
- private static final int TIMEOUT = 100000;
-
- private NfcAdapter mNfcAdapter;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- Log.d(Constants.TAG, "NfcActivity.onCreate");
-
- getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
-
- Intent intent = getIntent();
- Bundle data = intent.getExtras();
- String action = intent.getAction();
-
- Log.d(Constants.TAG, action);
- Log.d(Constants.TAG, intent.getDataString());
-
- // TODO check fingerprint
- // mFingerprint = data.getByteArray(EXTRA_FINGERPRINT);
-
- if (!NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) {
- Log.d(Constants.TAG, "Action not supported: " + action);
- finish();
- }
-
- try {
- Tag detectedTag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
-
- // Connect to the detected tag, setting a couple of settings
- IsoDep isoDep = IsoDep.get(detectedTag);
- isoDep.setTimeout(TIMEOUT); // timeout is set to 100 seconds to avoid cancellation during calculation
- isoDep.connect();
-
- nfcGreet(isoDep);
- // nfcPin(isoDep, "yoloswag");
- nfcGetFingerprint(isoDep);
-
- } catch (IOException e) {
- Log.e(Constants.TAG, "IOException!", e);
- finish();
- }
- }
-
- @Override
- protected void initLayout() {
- setContentView(R.layout.nfc_activity);
- }
-
- /**
- * Called when the system is about to start resuming a previous activity,
- * disables NFC Foreground Dispatch
- */
- public void onPause() {
- super.onPause();
- Log.d(Constants.TAG, "NfcActivity.onPause");
-
- // disableNfcForegroundDispatch();
- }
-
- /**
- * Called when the activity will start interacting with the user,
- * enables NFC Foreground Dispatch
- */
- public void onResume() {
- super.onResume();
- Log.d(Constants.TAG, "NfcActivity.onResume");
-
- // enableNfcForegroundDispatch();
- }
-
- /** Handle NFC communication and return a result.
- *
- * This method is called by onNewIntent above upon discovery of an NFC tag.
- * It handles initialization and login to the application, subsequently
- * calls either nfcCalculateSignature() or nfcDecryptSessionKey(), then
- * finishes the activity with an appropiate result.
- *
- * On general communication, see also
- * http://www.cardwerk.com/smartcards/smartcard_standard_ISO7816-4_annex-a.aspx
- *
- * References to pages are generally related to the OpenPGP Application
- * on ISO SmartCard Systems specification.
- *
- */
- private void nfcGreet(IsoDep isoDep) throws IOException {
-
- // SW1/2 0x9000 is the generic "ok" response, which we expect most of the time.
- // See specification, page 51
- String accepted = "9000";
-
- // Command APDU (page 51) for SELECT FILE command (page 29)
- String opening =
- "00" // CLA
- + "A4" // INS
- + "04" // P1
- + "00" // P2
- + "06" // Lc (number of bytes)
- + "D27600012401" // Data (6 bytes)
- + "00"; // Le
- if (!card(isoDep, opening).equals(accepted)) { // activate connection
- toast("Opening Error!");
- setResult(RESULT_CANCELED, mServiceIntent);
- finish();
- }
- }
-
- private void nfcPin(IsoDep isoDep, String pin) throws IOException {
-
- String data = "00CA006E00";
- String fingerprint = card(isoDep, data);
-
- // Command APDU for VERIFY command (page 32)
- String login =
- "00" // CLA
- + "20" // INS
- + "00" // P1
- + "82" // P2 (PW1)
- + String.format("%02x", pin.length()) // Lc
- + Hex.toHexString(pin.getBytes());
- if ( ! card(isoDep, login).equals("9000")) { // login
- toast("Pin Error!");
- setResult(RESULT_CANCELED, mServiceIntent);
- finish();
- }
-
- }
-
- /**
- * Gets the user ID
- *
- * @return the user id as "name <email>"
- * @throws java.io.IOException
- */
- public static String getUserId(IsoDep isoDep) throws IOException {
- String info = "00CA006500";
- String data = "00CA005E00";
- return getName(card(isoDep, info)) + " <" + (new String(Hex.decode(getDataField(card(isoDep, data))))) + ">";
- }
-
- /**
- * Gets the long key ID
- *
- * @return the long key id (last 16 bytes of the fingerprint)
- * @throws java.io.IOException
- */
- public static long getKeyId(IsoDep isoDep) throws IOException {
- String keyId = nfcGetFingerprint(isoDep).substring(24);
- Log.d(Constants.TAG, "keyId: " + keyId);
- return Long.parseLong(keyId, 16);
- }
-
- /**
- * Gets the fingerprint of the signature key
- *
- * @return the fingerprint
- * @throws java.io.IOException
- */
- public static String nfcGetFingerprint(IsoDep isoDep) throws IOException {
- String data = "00CA006E00";
- byte[] buf = isoDep.transceive(Hex.decode(data));
-
- Iso7816TLV tlv = Iso7816TLV.readSingle(buf, true);
- Log.d(Constants.TAG, "nfc tlv data:\n" + tlv.prettyPrint());
-
- Iso7816TLV fptlv = Iso7816TLV.findRecursive(tlv, 0xc5);
- if (fptlv != null) {
- ByteBuffer fpbuf = ByteBuffer.wrap(fptlv.mV);
- byte[] fp = new byte[20];
- fpbuf.get(fp);
- Log.d(Constants.TAG, "fingerprint 1: " + KeyFormattingUtils.convertFingerprintToHex(fp));
- fpbuf.get(fp);
- Log.d(Constants.TAG, "fingerprint 2: " + KeyFormattingUtils.convertFingerprintToHex(fp));
- fpbuf.get(fp);
- Log.d(Constants.TAG, "fingerprint 3: " + KeyFormattingUtils.convertFingerprintToHex(fp));
- }
-
- return "nope";
- }
-
- /**
- * Prints a message to the screen
- *
- * @param text the text which should be contained within the toast
- */
- private void toast(String text) {
- Toast.makeText(this, text, Toast.LENGTH_LONG).show();
- }
-
- /**
- * Receive new NFC Intents to this activity only by enabling foreground dispatch.
- * This can only be done in onResume!
- */
- public void enableNfcForegroundDispatch() {
- mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
- Intent nfcI = new Intent(this, NfcIntentActivity.class)
- .addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
- PendingIntent nfcPendingIntent = PendingIntent.getActivity(this, 0, nfcI, 0);
- IntentFilter[] writeTagFilters = new IntentFilter[]{
- new IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED)
- };
-
- // https://code.google.com/p/android/issues/detail?id=62918
- // maybe mNfcAdapter.enableReaderMode(); ?
- try {
- mNfcAdapter.enableForegroundDispatch(this, nfcPendingIntent, writeTagFilters, null);
- } catch (IllegalStateException e) {
- Log.i(Constants.TAG, "NfcForegroundDispatch Error!", e);
- }
- Log.d(Constants.TAG, "NfcForegroundDispatch has been enabled!");
- }
-
- /**
- * Disable foreground dispatch in onPause!
- */
- public void disableNfcForegroundDispatch() {
- mNfcAdapter.disableForegroundDispatch(this);
- Log.d(Constants.TAG, "NfcForegroundDispatch has been disabled!");
- }
-
- /**
- * Gets the name of the user out of the raw card output regarding card holder related data
- *
- * @param name the raw card holder related data from the card
- * @return the name given in this data
- */
- public static String getName(String name) {
- String slength;
- int ilength;
- name = name.substring(6);
- slength = name.substring(0, 2);
- ilength = Integer.parseInt(slength, 16) * 2;
- name = name.substring(2, ilength + 2);
- name = (new String(Hex.decode(name))).replace('<', ' ');
- return (name);
- }
-
- /**
- * Reduces the raw data from the card by four characters
- *
- * @param output the raw data from the card
- * @return the data field of that data
- */
- private static String getDataField(String output) {
- return output.substring(0, output.length() - 4);
- }
-
- /**
- * Communicates with the OpenPgpCard via the APDU
- *
- * @param hex the hexadecimal APDU
- * @return The answer from the card
- * @throws java.io.IOException throws an exception if something goes wrong
- */
- public static String card(IsoDep isoDep, String hex) throws IOException {
- return getHex(isoDep.transceive(Hex.decode(hex)));
- }
-
- /**
- * Converts a byte array into an hex string
- *
- * @param raw the byte array representation
- * @return the hexadecimal string representation
- */
- public static String getHex(byte[] raw) {
- return new String(Hex.encode(raw));
- }
-
-}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcOperationActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcOperationActivity.java
index a0b38c2b2..aa66053fa 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcOperationActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcOperationActivity.java
@@ -6,9 +6,7 @@
package org.sufficientlysecure.keychain.ui;
-import android.annotation.TargetApi;
import android.content.Intent;
-import android.os.Build;
import android.os.Bundle;
import android.view.WindowManager;
@@ -27,10 +25,9 @@ import java.io.IOException;
/**
* This class provides a communication interface to OpenPGP applications on ISO SmartCard compliant
* NFC devices.
- *
+ * <p/>
* For the full specs, see http://g10code.com/docs/openpgp-card-2.0.pdf
*/
-@TargetApi(Build.VERSION_CODES.GINGERBREAD_MR1)
public class NfcOperationActivity extends BaseNfcActivity {
public static final String EXTRA_REQUIRED_INPUT = "required_input";
@@ -57,7 +54,7 @@ public class NfcOperationActivity extends BaseNfcActivity {
mServiceIntent = data.getParcelable(EXTRA_SERVICE_INTENT);
// obtain passphrase for this subkey
- obtainYubikeyPin(RequiredInputParcel.createRequiredPassphrase(mRequiredInput));
+ obtainYubiKeyPin(RequiredInputParcel.createRequiredPassphrase(mRequiredInput));
}
@Override
@@ -71,16 +68,15 @@ public class NfcOperationActivity extends BaseNfcActivity {
CryptoInputParcel inputParcel = new CryptoInputParcel(mRequiredInput.mSignatureTime);
switch (mRequiredInput.mType) {
-
- case NFC_DECRYPT:
+ case NFC_DECRYPT: {
for (int i = 0; i < mRequiredInput.mInputHashes.length; i++) {
byte[] hash = mRequiredInput.mInputHashes[i];
byte[] decryptedSessionKey = nfcDecryptSessionKey(hash);
inputParcel.addCryptoData(hash, decryptedSessionKey);
}
break;
-
- case NFC_SIGN:
+ }
+ case NFC_SIGN: {
for (int i = 0; i < mRequiredInput.mInputHashes.length; i++) {
byte[] hash = mRequiredInput.mInputHashes[i];
int algo = mRequiredInput.mSignAlgos[i];
@@ -88,6 +84,7 @@ public class NfcOperationActivity extends BaseNfcActivity {
inputParcel.addCryptoData(hash, signedHash);
}
break;
+ }
}
if (mServiceIntent != null) {
@@ -100,7 +97,6 @@ public class NfcOperationActivity extends BaseNfcActivity {
}
finish();
-
}
@Override
@@ -108,7 +104,7 @@ public class NfcOperationActivity extends BaseNfcActivity {
// avoid a loop
Preferences prefs = Preferences.getPreferences(this);
- if (prefs.useDefaultYubikeyPin()) {
+ if (prefs.useDefaultYubiKeyPin()) {
toast(getString(R.string.error_pin_nodefault));
setResult(RESULT_CANCELED);
finish();
@@ -119,7 +115,7 @@ public class NfcOperationActivity extends BaseNfcActivity {
PassphraseCacheService.clearCachedPassphrase(
this, mRequiredInput.getMasterKeyId(), mRequiredInput.getSubKeyId());
- obtainYubikeyPin(RequiredInputParcel.createRequiredPassphrase(mRequiredInput));
-
+ obtainYubiKeyPin(RequiredInputParcel.createRequiredPassphrase(mRequiredInput));
}
+
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java
index 84612002f..4e926c0fe 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java
@@ -314,7 +314,7 @@ public class PassphraseDialogActivity extends FragmentActivity {
mPassphraseEditText.setImeActionLabel(getString(android.R.string.ok), EditorInfo.IME_ACTION_DONE);
mPassphraseEditText.setOnEditorActionListener(this);
- if (keyType == CanonicalizedSecretKey.SecretKeyType.DIVERT_TO_CARD && Preferences.getPreferences(activity).useNumKeypadForYubikeyPin()) {
+ if (keyType == CanonicalizedSecretKey.SecretKeyType.DIVERT_TO_CARD && Preferences.getPreferences(activity).useNumKeypadForYubiKeyPin()) {
mPassphraseEditText.setRawInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_TEXT_VARIATION_PASSWORD);
} else if (keyType == CanonicalizedSecretKey.SecretKeyType.PIN) {
mPassphraseEditText.setRawInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_TEXT_VARIATION_PASSWORD);
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 210960b65..442bdf8f7 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsActivity.java
@@ -107,10 +107,10 @@ public class SettingsActivity extends PreferenceActivity {
values[i] = "" + valueIds[i];
}
- initializeUseDefaultYubikeyPin(
+ initializeUseDefaultYubiKeyPin(
(CheckBoxPreference) findPreference(Constants.Pref.USE_DEFAULT_YUBIKEY_PIN));
- initializeUseNumKeypadForYubikeyPin(
+ initializeUseNumKeypadForYubiKeyPin(
(CheckBoxPreference) findPreference(Constants.Pref.USE_NUMKEYPAD_FOR_YUBIKEY_PIN));
}
@@ -262,10 +262,10 @@ public class SettingsActivity extends PreferenceActivity {
values[i] = "" + valueIds[i];
}
- initializeUseDefaultYubikeyPin(
+ initializeUseDefaultYubiKeyPin(
(CheckBoxPreference) findPreference(Constants.Pref.USE_DEFAULT_YUBIKEY_PIN));
- initializeUseNumKeypadForYubikeyPin(
+ initializeUseNumKeypadForYubiKeyPin(
(CheckBoxPreference) findPreference(Constants.Pref.USE_NUMKEYPAD_FOR_YUBIKEY_PIN));
}
}
@@ -335,23 +335,23 @@ public class SettingsActivity extends PreferenceActivity {
return serverSummary + "; " + context.getString(R.string.label_preferred) + ": " + sPreferences.getPreferredKeyserver();
}
- private static void initializeUseDefaultYubikeyPin(final CheckBoxPreference mUseDefaultYubikeyPin) {
- mUseDefaultYubikeyPin.setChecked(sPreferences.useDefaultYubikeyPin());
- mUseDefaultYubikeyPin.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
+ private static void initializeUseDefaultYubiKeyPin(final CheckBoxPreference mUseDefaultYubiKeyPin) {
+ mUseDefaultYubiKeyPin.setChecked(sPreferences.useDefaultYubiKeyPin());
+ mUseDefaultYubiKeyPin.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
public boolean onPreferenceChange(Preference preference, Object newValue) {
- mUseDefaultYubikeyPin.setChecked((Boolean) newValue);
- sPreferences.setUseDefaultYubikeyPin((Boolean) newValue);
+ mUseDefaultYubiKeyPin.setChecked((Boolean) newValue);
+ sPreferences.setUseDefaultYubiKeyPin((Boolean) newValue);
return false;
}
});
}
- private static void initializeUseNumKeypadForYubikeyPin(final CheckBoxPreference mUseNumKeypadForYubikeyPin) {
- mUseNumKeypadForYubikeyPin.setChecked(sPreferences.useNumKeypadForYubikeyPin());
- mUseNumKeypadForYubikeyPin.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
+ 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);
+ mUseNumKeypadForYubiKeyPin.setChecked((Boolean) newValue);
+ sPreferences.setUseNumKeypadForYubiKeyPin((Boolean) newValue);
return false;
}
});
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsKeyServerActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsKeyServerActivity.java
index 9f2e46b38..8f025c769 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsKeyServerActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsKeyServerActivity.java
@@ -20,6 +20,9 @@ package org.sufficientlysecure.keychain.ui;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.os.Messenger;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
@@ -28,6 +31,8 @@ import android.widget.TextView;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.ui.base.BaseActivity;
+import org.sufficientlysecure.keychain.ui.dialog.AddKeyserverDialogFragment;
+import org.sufficientlysecure.keychain.ui.util.Notify;
import org.sufficientlysecure.keychain.ui.widget.Editor;
import org.sufficientlysecure.keychain.ui.widget.Editor.EditorListener;
import org.sufficientlysecure.keychain.ui.widget.KeyServerEditor;
@@ -95,7 +100,7 @@ public class SettingsKeyServerActivity extends BaseActivity implements OnClickLi
Intent intent = getIntent();
String servers[] = intent.getStringArrayExtra(EXTRA_KEY_SERVERS);
makeServerList(servers);
- }
+ }
@Override
protected void initLayout() {
@@ -124,10 +129,63 @@ public class SettingsKeyServerActivity extends BaseActivity implements OnClickLi
}
+ // button to add keyserver clicked
public void onClick(View v) {
+ Handler returnHandler = new Handler() {
+ @Override
+ public void handleMessage(Message message) {
+ Bundle data = message.getData();
+ switch (message.what) {
+ case AddKeyserverDialogFragment.MESSAGE_OKAY: {
+ boolean verified = data.getBoolean(AddKeyserverDialogFragment.MESSAGE_VERIFIED);
+ if (verified) {
+ Notify.create(SettingsKeyServerActivity.this,
+ R.string.add_keyserver_verified, Notify.Style.OK).show();
+ } else {
+ Notify.create(SettingsKeyServerActivity.this,
+ R.string.add_keyserver_without_verification,
+ Notify.Style.WARN).show();
+ }
+ String keyserver = data.getString(AddKeyserverDialogFragment.MESSAGE_KEYSERVER);
+ addKeyserver(keyserver);
+ break;
+ }
+ case AddKeyserverDialogFragment.MESSAGE_VERIFICATION_FAILED: {
+ AddKeyserverDialogFragment.FailureReason failureReason =
+ (AddKeyserverDialogFragment.FailureReason) data.getSerializable(
+ AddKeyserverDialogFragment.MESSAGE_FAILURE_REASON);
+ switch (failureReason) {
+ case CONNECTION_FAILED: {
+ Notify.create(SettingsKeyServerActivity.this,
+ R.string.add_keyserver_connection_failed,
+ Notify.Style.ERROR).show();
+ break;
+ }
+ case INVALID_URL: {
+ Notify.create(SettingsKeyServerActivity.this,
+ R.string.add_keyserver_invalid_url,
+ Notify.Style.ERROR).show();
+ break;
+ }
+ }
+ break;
+ }
+ }
+ }
+ };
+
+ // Create a new Messenger for the communication back
+ Messenger messenger = new Messenger(returnHandler);
+ AddKeyserverDialogFragment dialogFragment = AddKeyserverDialogFragment
+ .newInstance(messenger, R.string.add_keyserver_dialog_title);
+ dialogFragment.show(getSupportFragmentManager(), "addKeyserverDialog");
+ }
+
+ public void addKeyserver(String keyserverUrl) {
KeyServerEditor view = (KeyServerEditor) mInflater.inflate(R.layout.key_server_editor,
mEditors, false);
view.setEditorListener(this);
+ view.setValue(keyserverUrl);
mEditors.addView(view);
}
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 b063df2fb..5466c0b9a 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java
@@ -281,7 +281,7 @@ public class ViewKeyActivity extends BaseNfcActivity implements
byte[] nfcFingerprints = intent.getByteArrayExtra(EXTRA_NFC_FINGERPRINTS);
String nfcUserId = intent.getStringExtra(EXTRA_NFC_USER_ID);
byte[] nfcAid = intent.getByteArrayExtra(EXTRA_NFC_AID);
- showYubikeyFragment(nfcFingerprints, nfcUserId, nfcAid);
+ showYubiKeyFragment(nfcFingerprints, nfcUserId, nfcAid);
}
}
@@ -593,12 +593,12 @@ public class ViewKeyActivity extends BaseNfcActivity implements
}
}
- showYubikeyFragment(nfcFingerprints, nfcUserId, nfcAid);
+ showYubiKeyFragment(nfcFingerprints, nfcUserId, nfcAid);
}
- public void showYubikeyFragment(byte[] nfcFingerprints, String nfcUserId, byte[] nfcAid) {
- ViewKeyYubikeyFragment frag = ViewKeyYubikeyFragment.newInstance(
+ public void showYubiKeyFragment(byte[] nfcFingerprints, String nfcUserId, byte[] nfcAid) {
+ ViewKeyYubiKeyFragment frag = ViewKeyYubiKeyFragment.newInstance(
nfcFingerprints, nfcUserId, nfcAid);
FragmentManager manager = getSupportFragmentManager();
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyYubikeyFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyYubiKeyFragment.java
index 1482b70a7..812874456 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyYubikeyFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyYubiKeyFragment.java
@@ -1,10 +1,26 @@
-package org.sufficientlysecure.keychain.ui;
+/*
+ * Copyright (C) 2015 Dominik Schürmann <dominik@dominikschuermann.de>
+ * Copyright (C) 2015 Vincent Breitmoser <v.breitmoser@mugenguild.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package org.sufficientlysecure.keychain.ui;
import java.nio.ByteBuffer;
import java.util.Arrays;
-import android.app.ProgressDialog;
import android.content.Intent;
import android.database.Cursor;
import android.os.Bundle;
@@ -29,11 +45,9 @@ import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey.SecretKeyType;
import org.sufficientlysecure.keychain.provider.KeychainContract.Keys;
import org.sufficientlysecure.keychain.service.KeychainIntentService;
import org.sufficientlysecure.keychain.service.ServiceProgressHandler;
-import org.sufficientlysecure.keychain.ui.dialog.ProgressDialogFragment;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
-
-public class ViewKeyYubikeyFragment extends Fragment
+public class ViewKeyYubiKeyFragment extends Fragment
implements LoaderCallbacks<Cursor> {
public static final String ARG_FINGERPRINT = "fingerprint";
@@ -46,9 +60,8 @@ public class ViewKeyYubikeyFragment extends Fragment
private Button vButton;
private TextView vStatus;
- public static ViewKeyYubikeyFragment newInstance(byte[] fingerprints, String userId, byte[] aid) {
-
- ViewKeyYubikeyFragment frag = new ViewKeyYubikeyFragment();
+ public static ViewKeyYubiKeyFragment newInstance(byte[] fingerprints, String userId, byte[] aid) {
+ ViewKeyYubiKeyFragment frag = new ViewKeyYubiKeyFragment();
Bundle args = new Bundle();
args.putByteArray(ARG_FINGERPRINT, fingerprints);
@@ -57,7 +70,6 @@ public class ViewKeyYubikeyFragment extends Fragment
frag.setArguments(args);
return frag;
-
}
@Override
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListLoader.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListLoader.java
index 5447c5f96..139512ba9 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListLoader.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListLoader.java
@@ -82,12 +82,12 @@ public class ImportKeysListLoader
@Override
protected void onStartLoading() {
- forceLoad();
+ super.forceLoad();
}
@Override
protected void onStopLoading() {
- cancelLoad();
+ super.cancelLoad();
}
@Override
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseNfcActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseNfcActivity.java
index 4f6d5807e..1d09b281f 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseNfcActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseNfcActivity.java
@@ -1,5 +1,22 @@
-package org.sufficientlysecure.keychain.ui.base;
+/*
+ * Copyright (C) 2015 Dominik Schürmann <dominik@dominikschuermann.de>
+ * Copyright (C) 2015 Vincent Breitmoser <v.breitmoser@mugenguild.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package org.sufficientlysecure.keychain.ui.base;
import java.io.IOException;
import java.nio.ByteBuffer;
@@ -35,12 +52,14 @@ import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.Passphrase;
import org.sufficientlysecure.keychain.util.Preferences;
-
public abstract class BaseNfcActivity extends BaseActivity {
public static final int REQUEST_CODE_PASSPHRASE = 1;
protected Passphrase mPin;
+ protected boolean mPw1ValidForMultipleSignatures;
+ protected boolean mPw1ValidatedForSignature;
+ protected boolean mPw1ValidatedForDecrypt; // Mode 82 does other things; consider renaming?
private NfcAdapter mNfcAdapter;
private IsoDep mIsoDep;
@@ -108,10 +127,10 @@ public abstract class BaseNfcActivity extends BaseActivity {
enableNfcForegroundDispatch();
}
- protected void obtainYubikeyPin(RequiredInputParcel requiredInput) {
+ protected void obtainYubiKeyPin(RequiredInputParcel requiredInput) {
Preferences prefs = Preferences.getPreferences(this);
- if (prefs.useDefaultYubikeyPin()) {
+ if (prefs.useDefaultYubiKeyPin()) {
mPin = new Passphrase("123456");
return;
}
@@ -123,7 +142,7 @@ public abstract class BaseNfcActivity extends BaseActivity {
}
- protected void setYubikeyPin(Passphrase pin) {
+ protected void setYubiKeyPin(Passphrase pin) {
mPin = pin;
}
@@ -181,28 +200,14 @@ public abstract class BaseNfcActivity extends BaseActivity {
+ "06" // Lc (number of bytes)
+ "D27600012401" // Data (6 bytes)
+ "00"; // Le
- if ( ! nfcCommunicate(opening).equals(accepted)) { // activate connection
+ if ( ! nfcCommunicate(opening).endsWith(accepted)) { // activate connection
throw new IOException("Initialization failed!");
}
- if (mPin != null) {
-
- byte[] pin = new String(mPin.getCharArray()).getBytes();
-
- // Command APDU for VERIFY command (page 32)
- String login =
- "00" // CLA
- + "20" // INS
- + "00" // P1
- + "82" // P2 (PW1)
- + String.format("%02x", pin.length) // Lc
- + Hex.toHexString(pin);
- if (!nfcCommunicate(login).equals(accepted)) { // login
- handlePinError();
- return;
- }
-
- }
+ byte[] pwStatusBytes = nfcGetPwStatusBytes();
+ mPw1ValidForMultipleSignatures = (pwStatusBytes[0] == 1);
+ mPw1ValidatedForSignature = false;
+ mPw1ValidatedForDecrypt = false;
onNfcPerform();
@@ -217,7 +222,6 @@ public abstract class BaseNfcActivity extends BaseActivity {
final String nfcUserId = nfcGetUserId();
final byte[] nfcAid = nfcGetAid();
- String fp = KeyFormattingUtils.convertFingerprintToHex(nfcFingerprints);
final long masterKeyId = KeyFormattingUtils.getKeyIdFromFingerprint(nfcFingerprints);
try {
@@ -282,6 +286,15 @@ public abstract class BaseNfcActivity extends BaseActivity {
return fptlv.mV;
}
+ /** Return the PW Status Bytes from the card. This is a simple DO; no TLV decoding needed.
+ *
+ * @return Seven bytes in fixed format, plus 0x9000 status word at the end.
+ */
+ public byte[] nfcGetPwStatusBytes() throws IOException {
+ String data = "00CA00C400";
+ return mIsoDep.transceive(Hex.decode(data));
+ }
+
/** Return the fingerprint from application specific data stored on tag, or
* null if it doesn't exist.
*
@@ -320,6 +333,9 @@ public abstract class BaseNfcActivity extends BaseActivity {
* @return a big integer representing the MPI for the given hash
*/
public byte[] nfcCalculateSignature(byte[] hash, int hashAlgo) throws IOException {
+ if (!mPw1ValidatedForSignature) {
+ nfcVerifyPIN(0x81); // (Verify PW1 with mode 81 for signing)
+ }
// dsi, including Lc
String dsi;
@@ -394,6 +410,10 @@ public abstract class BaseNfcActivity extends BaseActivity {
Log.d(Constants.TAG, "final response:" + status);
+ if (!mPw1ValidForMultipleSignatures) {
+ mPw1ValidatedForSignature = false;
+ }
+
if ( ! "9000".equals(status)) {
throw new IOException("Bad NFC response code: " + status);
}
@@ -413,6 +433,10 @@ public abstract class BaseNfcActivity extends BaseActivity {
* @return the decoded session key
*/
public byte[] nfcDecryptSessionKey(byte[] encryptedSessionKey) throws IOException {
+ if (!mPw1ValidatedForDecrypt) {
+ nfcVerifyPIN(0x82); // (Verify PW1 with mode 82 for decryption)
+ }
+
String firstApdu = "102a8086fe";
String secondApdu = "002a808603";
String le = "00";
@@ -436,6 +460,38 @@ public abstract class BaseNfcActivity extends BaseActivity {
return Hex.decode(decryptedSessionKey);
}
+ /** Verifies the user's PW1 with the appropriate mode.
+ *
+ * @param mode This is 0x81 for signing, 0x82 for everything else
+ */
+ public void nfcVerifyPIN(int mode) throws IOException {
+ if (mPin != null) {
+ byte[] pin = new String(mPin.getCharArray()).getBytes();
+ // SW1/2 0x9000 is the generic "ok" response, which we expect most of the time.
+ // See specification, page 51
+ String accepted = "9000";
+
+ // Command APDU for VERIFY command (page 32)
+ String login =
+ "00" // CLA
+ + "20" // INS
+ + "00" // P1
+ + String.format("%02x", mode) // P2
+ + String.format("%02x", pin.length) // Lc
+ + Hex.toHexString(pin);
+ if (!nfcCommunicate(login).equals(accepted)) { // login
+ handlePinError();
+ throw new IOException("Bad PIN!");
+ }
+
+ if (mode == 0x81) {
+ mPw1ValidatedForSignature = true;
+ } else if (mode == 0x82) {
+ mPw1ValidatedForDecrypt = true;
+ }
+ }
+ }
+
/**
* Prints a message to the screen
*
@@ -451,8 +507,9 @@ public abstract class BaseNfcActivity extends BaseActivity {
*/
public void enableNfcForegroundDispatch() {
mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
- if(mNfcAdapter == null) return;
-
+ if (mNfcAdapter == null) {
+ return;
+ }
Intent nfcI = new Intent(this, getClass())
.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent nfcPendingIntent = PendingIntent.getActivity(this, 0, nfcI, PendingIntent.FLAG_CANCEL_CURRENT);
@@ -474,9 +531,10 @@ public abstract class BaseNfcActivity extends BaseActivity {
* Disable foreground dispatch in onPause!
*/
public void disableNfcForegroundDispatch() {
- if(mNfcAdapter != null) {
- mNfcAdapter.disableForegroundDispatch(this);
+ if (mNfcAdapter == null) {
+ return;
}
+ mNfcAdapter.disableForegroundDispatch(this);
Log.d(Constants.TAG, "NfcForegroundDispatch has been disabled!");
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CryptoOperationFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/CryptoOperationFragment.java
index b136492b4..232a39f86 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CryptoOperationFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/CryptoOperationFragment.java
@@ -16,7 +16,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-package org.sufficientlysecure.keychain.ui;
+package org.sufficientlysecure.keychain.ui.base;
import android.app.Activity;
import android.content.Intent;
@@ -29,6 +29,8 @@ import org.sufficientlysecure.keychain.operations.results.OperationResult;
import org.sufficientlysecure.keychain.service.ServiceProgressHandler;
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
import org.sufficientlysecure.keychain.service.input.RequiredInputParcel;
+import org.sufficientlysecure.keychain.ui.NfcOperationActivity;
+import org.sufficientlysecure.keychain.ui.PassphraseDialogActivity;
/**
* All fragments executing crypto operations need to extend this class.
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddKeyserverDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddKeyserverDialogFragment.java
new file mode 100644
index 000000000..cbef5950f
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddKeyserverDialogFragment.java
@@ -0,0 +1,320 @@
+/*
+ * Copyright (C) 2012-2014 Dominik Schürmann <dominik@dominikschuermann.de>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.sufficientlysecure.keychain.ui.dialog;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.ProgressDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.os.Message;
+import android.os.Messenger;
+import android.os.RemoteException;
+import android.support.v4.app.DialogFragment;
+import android.test.suitebuilder.TestSuiteBuilder;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.Button;
+import android.widget.CheckBox;
+import android.widget.EditText;
+import android.widget.TextView;
+import android.widget.TextView.OnEditorActionListener;
+
+import org.sufficientlysecure.keychain.Constants;
+import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.util.Log;
+import org.sufficientlysecure.keychain.util.TlsHelper;
+
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+
+import javax.net.ssl.HttpsURLConnection;
+
+public class AddKeyserverDialogFragment extends DialogFragment implements OnEditorActionListener {
+ private static final String ARG_MESSENGER = "messenger";
+ private static final String ARG_TITLE = "title";
+
+ public static final int MESSAGE_OKAY = 1;
+ public static final int MESSAGE_VERIFICATION_FAILED = 2;
+
+ public static final String MESSAGE_KEYSERVER = "new_keyserver";
+ public static final String MESSAGE_VERIFIED = "verified";
+ public static final String MESSAGE_FAILURE_REASON = "failure_reason";
+
+ private Messenger mMessenger;
+ private EditText mKeyserverEditText;
+ private CheckBox mVerifyKeyserverCheckBox;
+
+ public static enum FailureReason {
+ INVALID_URL,
+ CONNECTION_FAILED
+ }
+
+ ;
+
+ /**
+ * Creates new instance of this dialog fragment
+ *
+ * @param title title of dialog
+ * @param messenger to communicate back after setting the passphrase
+ * @return
+ */
+ public static AddKeyserverDialogFragment newInstance(Messenger messenger, int title) {
+ AddKeyserverDialogFragment frag = new AddKeyserverDialogFragment();
+ Bundle args = new Bundle();
+ args.putInt(ARG_TITLE, title);
+ args.putParcelable(ARG_MESSENGER, messenger);
+
+ frag.setArguments(args);
+
+ return frag;
+ }
+
+ /**
+ * Creates dialog
+ */
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ final Activity activity = getActivity();
+
+ int title = getArguments().getInt(ARG_TITLE);
+ mMessenger = getArguments().getParcelable(ARG_MESSENGER);
+
+ CustomAlertDialogBuilder alert = new CustomAlertDialogBuilder(activity);
+
+ alert.setTitle(title);
+
+ LayoutInflater inflater = activity.getLayoutInflater();
+ View view = inflater.inflate(R.layout.add_keyserver_dialog, null);
+ alert.setView(view);
+
+ mKeyserverEditText = (EditText) view.findViewById(R.id.keyserver_url_edit_text);
+ mVerifyKeyserverCheckBox = (CheckBox) view.findViewById(R.id.verify_keyserver_checkbox);
+
+ // we don't want dialog to be dismissed on click, thereby requiring the hack seen below
+ // and in onStart
+ alert.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int id) {
+ // we need to have an empty listener to prevent errors on some devices as mentioned
+ // at http://stackoverflow.com/q/13746412/3000919
+ // actual listener set in onStart
+ }
+ });
+
+ alert.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
+
+ @Override
+ public void onClick(DialogInterface dialog, int id) {
+ dismiss();
+ }
+ });
+
+ // Hack to open keyboard.
+ // This is the only method that I found to work across all Android versions
+ // http://turbomanage.wordpress.com/2012/05/02/show-soft-keyboard-automatically-when-edittext-receives-focus/
+ // Notes: * onCreateView can't be used because we want to add buttons to the dialog
+ // * opening in onActivityCreated does not work on Android 4.4
+ mKeyserverEditText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
+ @Override
+ public void onFocusChange(View v, boolean hasFocus) {
+ mKeyserverEditText.post(new Runnable() {
+ @Override
+ public void run() {
+ InputMethodManager imm = (InputMethodManager) getActivity()
+ .getSystemService(Context.INPUT_METHOD_SERVICE);
+ imm.showSoftInput(mKeyserverEditText, InputMethodManager.SHOW_IMPLICIT);
+ }
+ });
+ }
+ });
+ mKeyserverEditText.requestFocus();
+
+ mKeyserverEditText.setImeActionLabel(getString(android.R.string.ok),
+ EditorInfo.IME_ACTION_DONE);
+ mKeyserverEditText.setOnEditorActionListener(this);
+
+ return alert.show();
+ }
+
+ @Override
+ public void onStart() {
+ super.onStart();
+ AlertDialog addKeyserverDialog = (AlertDialog) getDialog();
+ if (addKeyserverDialog != null) {
+ Button positiveButton = addKeyserverDialog.getButton(Dialog.BUTTON_POSITIVE);
+ positiveButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ String keyserverUrl = mKeyserverEditText.getText().toString();
+ if (mVerifyKeyserverCheckBox.isChecked()) {
+ verifyConnection(keyserverUrl);
+ } else {
+ dismiss();
+ // return unverified keyserver back to activity
+ addKeyserver(keyserverUrl, false);
+ }
+ }
+ });
+ }
+ }
+
+ public void addKeyserver(String keyserver, boolean verified) {
+ dismiss();
+ Bundle data = new Bundle();
+ data.putString(MESSAGE_KEYSERVER, keyserver);
+ data.putBoolean(MESSAGE_VERIFIED, verified);
+
+ sendMessageToHandler(MESSAGE_OKAY, data);
+ }
+
+ public void verificationFailed(FailureReason reason) {
+ Bundle data = new Bundle();
+ data.putSerializable(MESSAGE_FAILURE_REASON, reason);
+
+ sendMessageToHandler(MESSAGE_VERIFICATION_FAILED, data);
+ }
+
+ public void verifyConnection(String keyserver) {
+
+ new AsyncTask<String, Void, FailureReason>() {
+ ProgressDialog mProgressDialog;
+ String mKeyserver;
+
+ @Override
+ protected void onPreExecute() {
+ mProgressDialog = new ProgressDialog(getActivity());
+ mProgressDialog.setMessage(getString(R.string.progress_verifying_keyserver_url));
+ mProgressDialog.setCancelable(false);
+ mProgressDialog.show();
+ }
+
+ @Override
+ protected FailureReason doInBackground(String... keyservers) {
+ mKeyserver = keyservers[0];
+ FailureReason reason = null;
+ try {
+ // replace hkps/hkp scheme and reconstruct Uri
+ Uri keyserverUri = Uri.parse(mKeyserver);
+ String scheme = keyserverUri.getScheme();
+ String schemeSpecificPart = keyserverUri.getSchemeSpecificPart();
+ String fragment = keyserverUri.getFragment();
+ if (scheme == null) throw new MalformedURLException();
+ if (scheme.equalsIgnoreCase("hkps")) scheme = "https";
+ else if (scheme.equalsIgnoreCase("hkp")) scheme = "http";
+ URI newKeyserver = new URI(scheme, schemeSpecificPart, fragment);
+
+ Log.d("Converted URL", newKeyserver.toString());
+ TlsHelper.openConnection(newKeyserver.toURL()).getInputStream();
+ } catch (TlsHelper.TlsHelperException e) {
+ reason = FailureReason.CONNECTION_FAILED;
+ } catch (MalformedURLException e) {
+ Log.w(Constants.TAG, "Invalid keyserver URL entered by user.");
+ reason = FailureReason.INVALID_URL;
+ } catch (URISyntaxException e) {
+ Log.w(Constants.TAG, "Invalid keyserver URL entered by user.");
+ reason = FailureReason.INVALID_URL;
+ } catch (IOException e) {
+ Log.w(Constants.TAG, "Could not connect to entered keyserver url");
+ reason = FailureReason.CONNECTION_FAILED;
+ }
+ return reason;
+ }
+
+ @Override
+ protected void onPostExecute(FailureReason failureReason) {
+ mProgressDialog.dismiss();
+ if (failureReason == null) {
+ addKeyserver(mKeyserver, true);
+ } else {
+ verificationFailed(failureReason);
+ }
+ }
+ }.execute(keyserver);
+ }
+
+ @Override
+ public void onDismiss(DialogInterface dialog) {
+ super.onDismiss(dialog);
+
+ // hide keyboard on dismiss
+ hideKeyboard();
+ }
+
+ private void hideKeyboard() {
+ if (getActivity() == null) {
+ return;
+ }
+ InputMethodManager inputManager = (InputMethodManager) getActivity()
+ .getSystemService(Context.INPUT_METHOD_SERVICE);
+
+ //check if no view has focus:
+ View v = getActivity().getCurrentFocus();
+ if (v == null)
+ return;
+
+ inputManager.hideSoftInputFromWindow(v.getWindowToken(), 0);
+ }
+
+ /**
+ * Associate the "done" button on the soft keyboard with the okay button in the view
+ */
+ @Override
+ public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
+ if (EditorInfo.IME_ACTION_DONE == actionId) {
+ AlertDialog dialog = ((AlertDialog) getDialog());
+ Button bt = dialog.getButton(AlertDialog.BUTTON_POSITIVE);
+
+ bt.performClick();
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Send message back to handler which is initialized in a activity
+ *
+ * @param what Message integer you want to send
+ */
+ private void sendMessageToHandler(Integer what, Bundle data) {
+ Message msg = Message.obtain();
+ msg.what = what;
+ if (data != null) {
+ msg.setData(data);
+ }
+
+ try {
+ mMessenger.send(msg);
+ } catch (RemoteException e) {
+ Log.w(Constants.TAG, "Exception sending message, Is handler present?", e);
+ } catch (NullPointerException e) {
+ Log.w(Constants.TAG, "Messenger is null!", e);
+ }
+ }
+}
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 44c1e6b6c..303687315 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Preferences.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Preferences.java
@@ -109,21 +109,21 @@ public class Preferences {
return mSharedPreferences.getBoolean(Constants.Pref.FIRST_TIME, true);
}
- public boolean useDefaultYubikeyPin() {
+ public boolean useDefaultYubiKeyPin() {
return mSharedPreferences.getBoolean(Pref.USE_DEFAULT_YUBIKEY_PIN, false);
}
- public void setUseDefaultYubikeyPin(boolean useDefaultYubikeyPin) {
+ public void setUseDefaultYubiKeyPin(boolean useDefaultYubikeyPin) {
SharedPreferences.Editor editor = mSharedPreferences.edit();
editor.putBoolean(Pref.USE_DEFAULT_YUBIKEY_PIN, useDefaultYubikeyPin);
editor.commit();
}
- public boolean useNumKeypadForYubikeyPin() {
+ public boolean useNumKeypadForYubiKeyPin() {
return mSharedPreferences.getBoolean(Pref.USE_NUMKEYPAD_FOR_YUBIKEY_PIN, true);
}
- public void setUseNumKeypadForYubikeyPin(boolean useNumKeypadForYubikeyPin) {
+ public void setUseNumKeypadForYubiKeyPin(boolean useNumKeypadForYubikeyPin) {
SharedPreferences.Editor editor = mSharedPreferences.edit();
editor.putBoolean(Pref.USE_NUMKEYPAD_FOR_YUBIKEY_PIN, useNumKeypadForYubikeyPin);
editor.commit();
@@ -193,6 +193,11 @@ public class Preferences {
public final boolean searchKeybase;
public final String keyserver;
+ /**
+ * @param searchKeyserver should passed keyserver be searched
+ * @param searchKeybase should keybase.io be searched
+ * @param keyserver the keyserver url authority to search on
+ */
public CloudSearchPrefs(boolean searchKeyserver, boolean searchKeybase, String keyserver) {
this.searchKeyserver = searchKeyserver;
this.searchKeybase = searchKeybase;