finish ui flow for yubikey import

This commit is contained in:
Vincent Breitmoser 2015-03-22 06:36:27 +01:00
parent 2151411219
commit 212bba1869
9 changed files with 397 additions and 222 deletions

View File

@ -230,7 +230,7 @@ public class ImportExportOperation extends BaseOperation {
} }
} catch (Keyserver.QueryFailedException e) { } catch (Keyserver.QueryFailedException e) {
Log.e(Constants.TAG, "query failed", e); Log.e(Constants.TAG, "query failed", e);
log.add(LogType.MSG_IMPORT_FETCH_KEYSERVER_ERROR, 3); log.add(LogType.MSG_IMPORT_FETCH_KEYSERVER_ERROR, 3, e.getMessage());
} }
} }

View File

@ -20,6 +20,7 @@ package org.sufficientlysecure.keychain.ui;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.support.v4.app.Fragment; import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction; import android.support.v4.app.FragmentTransaction;
import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.R;
@ -29,9 +30,6 @@ import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.ui.base.BaseNfcActivity; import org.sufficientlysecure.keychain.ui.base.BaseNfcActivity;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.ui.util.Notify;
import org.sufficientlysecure.keychain.ui.util.Notify.ActionListener;
import org.sufficientlysecure.keychain.ui.util.Notify.Style;
import org.sufficientlysecure.keychain.util.Passphrase; import org.sufficientlysecure.keychain.util.Passphrase;
import java.io.IOException; import java.io.IOException;
@ -45,6 +43,10 @@ public class CreateKeyActivity extends BaseNfcActivity {
public static final String EXTRA_ADDITIONAL_EMAILS = "additional_emails"; public static final String EXTRA_ADDITIONAL_EMAILS = "additional_emails";
public static final String EXTRA_PASSPHRASE = "passphrase"; public static final String EXTRA_PASSPHRASE = "passphrase";
public static final String EXTRA_NFC_USER_ID = "nfc_user_id";
public static final String EXTRA_NFC_AID = "nfc_aid";
public static final String EXTRA_NFC_FINGERPRINTS = "nfc_fingerprints";
public static final String FRAGMENT_TAG = "currentFragment"; public static final String FRAGMENT_TAG = "currentFragment";
String mName; String mName;
@ -70,14 +72,29 @@ public class CreateKeyActivity extends BaseNfcActivity {
mCurrentFragment = getSupportFragmentManager().findFragmentByTag(FRAGMENT_TAG); mCurrentFragment = getSupportFragmentManager().findFragmentByTag(FRAGMENT_TAG);
} else { } else {
// Initialize members with default values for a new instance
mName = getIntent().getStringExtra(EXTRA_NAME);
mEmail = getIntent().getStringExtra(EXTRA_EMAIL);
mFirstTime = getIntent().getBooleanExtra(EXTRA_FIRST_TIME, false);
// Start with first fragment of wizard Intent intent = getIntent();
CreateKeyStartFragment frag = CreateKeyStartFragment.newInstance(); // Initialize members with default values for a new instance
loadFragment(frag, FragAction.START); mName = intent.getStringExtra(EXTRA_NAME);
mEmail = intent.getStringExtra(EXTRA_EMAIL);
mFirstTime = intent.getBooleanExtra(EXTRA_FIRST_TIME, false);
if (intent.hasExtra(EXTRA_NFC_FINGERPRINTS)) {
byte[] nfcFingerprints = intent.getByteArrayExtra(EXTRA_NFC_FINGERPRINTS);
String nfcUserId = intent.getStringExtra(EXTRA_NFC_USER_ID);
byte[] nfcAid = intent.getByteArrayExtra(EXTRA_NFC_AID);
Fragment frag2 = CreateKeyYubiImportFragment.createInstance(
nfcFingerprints, nfcAid, nfcUserId);
loadFragment(frag2, FragAction.START);
setTitle(R.string.title_import_keys);
return;
} else {
CreateKeyStartFragment frag = CreateKeyStartFragment.newInstance();
loadFragment(frag, FragAction.START);
}
} }
if (mFirstTime) { if (mFirstTime) {
@ -97,15 +114,14 @@ public class CreateKeyActivity extends BaseNfcActivity {
} }
byte[] scannedFingerprints = nfcGetFingerprints(); byte[] scannedFingerprints = nfcGetFingerprints();
byte[] nfcAid = nfcGetAid();
String userId = nfcGetUserId();
try { try {
long masterKeyId = KeyFormattingUtils.getKeyIdFromFingerprint(scannedFingerprints); long masterKeyId = KeyFormattingUtils.getKeyIdFromFingerprint(scannedFingerprints);
CachedPublicKeyRing ring = new ProviderHelper(this).getCachedPublicKeyRing(masterKeyId); CachedPublicKeyRing ring = new ProviderHelper(this).getCachedPublicKeyRing(masterKeyId);
ring.getMasterKeyId(); ring.getMasterKeyId();
String userId = nfcGetUserId();
byte[] nfcAid = nfcGetAid();
Intent intent = new Intent(this, ViewKeyActivity.class); Intent intent = new Intent(this, ViewKeyActivity.class);
intent.setData(KeyRings.buildGenericKeyRingUri(masterKeyId)); intent.setData(KeyRings.buildGenericKeyRingUri(masterKeyId));
intent.putExtra(ViewKeyActivity.EXTRA_NFC_AID, nfcAid); intent.putExtra(ViewKeyActivity.EXTRA_NFC_AID, nfcAid);
@ -115,7 +131,8 @@ public class CreateKeyActivity extends BaseNfcActivity {
finish(); finish();
} catch (PgpKeyNotFoundException e) { } catch (PgpKeyNotFoundException e) {
Fragment frag = CreateKeyYubiFragment.createInstance(scannedFingerprints); Fragment frag = CreateKeyYubiImportFragment.createInstance(
scannedFingerprints, nfcAid, userId);
loadFragment(frag, FragAction.TO_RIGHT); loadFragment(frag, FragAction.TO_RIGHT);
} }
@ -167,8 +184,10 @@ public class CreateKeyActivity extends BaseNfcActivity {
break; break;
} }
// do it immediately! // do it immediately!
getSupportFragmentManager().executePendingTransactions(); getSupportFragmentManager().executePendingTransactions();
} }
interface NfcListenerFragment { interface NfcListenerFragment {

View File

@ -1,171 +0,0 @@
/*
* Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.sufficientlysecure.keychain.ui;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import android.app.Activity;
import android.content.Intent;
import android.database.Cursor;
import android.os.Bundle;
import android.os.Message;
import android.os.Messenger;
import android.support.v4.app.Fragment;
import android.support.v4.app.LoaderManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing;
import org.sufficientlysecure.keychain.operations.results.DecryptVerifyResult;
import org.sufficientlysecure.keychain.operations.results.ImportKeyResult;
import org.sufficientlysecure.keychain.service.KeychainIntentService;
import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
import org.sufficientlysecure.keychain.ui.CreateKeyActivity.FragAction;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.util.Preferences;
public class CreateKeyYubiFragment extends Fragment {
private static final String ARG_FINGERPRINT = "fingerprint";
CreateKeyActivity mCreateKeyActivity;
private byte[] mScannedFingerprint;
private long mScannedMasterKeyId;
private TextView mUnknownFingerprint;
public static Fragment createInstance(byte[] scannedFingerprint) {
Bundle args = new Bundle();
args.putByteArray(ARG_FINGERPRINT, scannedFingerprint);
CreateKeyYubiFragment frag = new CreateKeyYubiFragment();
frag.setArguments(args);
return frag;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mScannedFingerprint = getArguments().getByteArray(ARG_FINGERPRINT);
mScannedMasterKeyId = getKeyIdFromFingerprint(mScannedFingerprint);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.create_yubikey_fragment, container, false);
mUnknownFingerprint = (TextView) view.findViewById(R.id.create_yubikey_unknown_fp);
View mBackButton = view.findViewById(R.id.create_key_back_button);
View mNextButton = view.findViewById(R.id.create_key_next_button);
mBackButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mCreateKeyActivity.loadFragment(null, FragAction.TO_LEFT);
}
});
mNextButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
nextClicked();
}
});
return view;
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
mCreateKeyActivity = (CreateKeyActivity) getActivity();
}
private void nextClicked() {
importKey();
}
public void importKey() {
// Message is received after decrypting is done in KeychainIntentService
KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler(getActivity()) {
public void handleMessage(Message message) {
// handle messages by standard KeychainIntentServiceHandler first
super.handleMessage(message);
if (message.arg1 == MessageStatus.OKAY.ordinal()) {
// get returned data bundle
Bundle returnData = message.getData();
ImportKeyResult result =
returnData.getParcelable(DecryptVerifyResult.EXTRA_RESULT);
result.createNotify(getActivity()).show();
}
}
};
// Send all information needed to service to decrypt in other thread
Intent intent = new Intent(getActivity(), KeychainIntentService.class);
// fill values for this action
Bundle data = new Bundle();
intent.setAction(KeychainIntentService.ACTION_IMPORT_KEYRING);
String hexFp = KeyFormattingUtils.convertFingerprintToHex(mScannedFingerprint);
ArrayList<ParcelableKeyRing> keyList = new ArrayList<>();
keyList.add(new ParcelableKeyRing(hexFp, null, null));
data.putParcelableArrayList(KeychainIntentService.IMPORT_KEY_LIST, keyList);
{
Preferences prefs = Preferences.getPreferences(getActivity());
Preferences.CloudSearchPrefs cloudPrefs =
new Preferences.CloudSearchPrefs(true, true, prefs.getPreferredKeyserver());
data.putString(KeychainIntentService.IMPORT_KEY_SERVER, cloudPrefs.keyserver);
}
intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
// Create a new Messenger for the communication back
Messenger messenger = new Messenger(saveHandler);
intent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger);
// start service with intent
getActivity().startService(intent);
}
static long getKeyIdFromFingerprint(byte[] fingerprint) {
ByteBuffer buf = ByteBuffer.wrap(fingerprint);
// skip first 12 bytes of the fingerprint
buf.position(12);
// the last eight bytes are the key id (big endian, which is default order in ByteBuffer)
return buf.getLong();
}
}

View File

@ -0,0 +1,256 @@
/*
* Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.sufficientlysecure.keychain.ui;
import java.io.IOException;
import java.util.ArrayList;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.os.Bundle;
import android.os.Message;
import android.os.Messenger;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.TextView;
import org.spongycastle.util.encoders.Hex;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing;
import org.sufficientlysecure.keychain.operations.results.DecryptVerifyResult;
import org.sufficientlysecure.keychain.operations.results.ImportKeyResult;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.service.KeychainIntentService;
import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
import org.sufficientlysecure.keychain.ui.CreateKeyActivity.FragAction;
import org.sufficientlysecure.keychain.ui.CreateKeyActivity.NfcListenerFragment;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.util.Preferences;
public class CreateKeyYubiImportFragment extends Fragment implements NfcListenerFragment {
private static final String ARG_FINGERPRINT = "fingerprint";
public static final String ARG_AID = "aid";
public static final String ARG_USER_ID = "user_ids";
CreateKeyActivity mCreateKeyActivity;
private byte[] mNfcFingerprints;
private long mNfcMasterKeyId;
private byte[] mNfcAid;
private String mNfcUserId;
private String mNfcFingerprint;
private ImportKeysListFragment mListFragment;
private TextView vSerNo;
private TextView vUserId;
public static Fragment createInstance(byte[] scannedFingerprints, byte[] nfcAid, String userId) {
CreateKeyYubiImportFragment frag = new CreateKeyYubiImportFragment();
Bundle args = new Bundle();
args.putByteArray(ARG_FINGERPRINT, scannedFingerprints);
args.putByteArray(ARG_AID, nfcAid);
args.putString(ARG_USER_ID, userId);
frag.setArguments(args);
return frag;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle args = savedInstanceState != null ? savedInstanceState : getArguments();
mNfcFingerprints = args.getByteArray(ARG_FINGERPRINT);
mNfcAid = args.getByteArray(ARG_AID);
mNfcUserId = args.getString(ARG_USER_ID);
mNfcMasterKeyId = KeyFormattingUtils.getKeyIdFromFingerprint(mNfcFingerprints);
mNfcFingerprint = KeyFormattingUtils.convertFingerprintToHex(mNfcFingerprints);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.create_yubikey_import_fragment, container, false);
vSerNo = (TextView) view.findViewById(R.id.yubikey_serno);
vUserId = (TextView) view.findViewById(R.id.yubikey_userid);
{
View mBackButton = view.findViewById(R.id.create_key_back_button);
mBackButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (getFragmentManager().getBackStackEntryCount() == 0) {
getActivity().setResult(Activity.RESULT_CANCELED);
getActivity().finish();
} else {
mCreateKeyActivity.loadFragment(null, FragAction.TO_LEFT);
}
}
});
View mNextButton = view.findViewById(R.id.create_key_next_button);
mNextButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
importKey();
}
});
}
mListFragment = ImportKeysListFragment.newInstance(null, null, "0x" + mNfcFingerprint, true);
view.findViewById(R.id.button_search).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
refreshSearch();
}
});
setData();
getFragmentManager().beginTransaction()
.replace(R.id.yubikey_import_fragment, mListFragment, "yubikey_import")
.commit();
return view;
}
@Override
public void onSaveInstanceState(Bundle args) {
super.onSaveInstanceState(args);
args.putByteArray(ARG_FINGERPRINT, mNfcFingerprints);
args.putByteArray(ARG_AID, mNfcAid);
args.putString(ARG_USER_ID, mNfcUserId);
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
mCreateKeyActivity = (CreateKeyActivity) getActivity();
}
public void setData() {
String serno = Hex.toHexString(mNfcAid, 10, 4);
vSerNo.setText(getString(R.string.yubikey_serno, serno));
if (!mNfcUserId.isEmpty()) {
vUserId.setText(getString(R.string.yubikey_key_holder, mNfcUserId));
} else {
vUserId.setText(getString(R.string.yubikey_key_holder_unset));
}
}
public void refreshSearch() {
mListFragment.loadNew(new ImportKeysListFragment.CloudLoaderState("0x" + mNfcFingerprint,
Preferences.getPreferences(getActivity()).getCloudSearchPrefs()));
}
public void importKey() {
// Message is received after decrypting is done in KeychainIntentService
KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler(getActivity(),
getString(R.string.progress_importing), ProgressDialog.STYLE_HORIZONTAL) {
public void handleMessage(Message message) {
// handle messages by standard KeychainIntentServiceHandler first
super.handleMessage(message);
if (message.arg1 == MessageStatus.OKAY.ordinal()) {
// get returned data bundle
Bundle returnData = message.getData();
ImportKeyResult result =
returnData.getParcelable(DecryptVerifyResult.EXTRA_RESULT);
if (!result.success()) {
result.createNotify(getActivity()).show();
return;
}
Intent intent = new Intent(getActivity(), ViewKeyActivity.class);
intent.setData(KeyRings.buildGenericKeyRingUri(mNfcMasterKeyId));
intent.putExtra(ViewKeyActivity.EXTRA_DISPLAY_RESULT, result);
intent.putExtra(ViewKeyActivity.EXTRA_NFC_AID, mNfcAid);
intent.putExtra(ViewKeyActivity.EXTRA_NFC_USER_ID, mNfcUserId);
intent.putExtra(ViewKeyActivity.EXTRA_NFC_FINGERPRINTS, mNfcFingerprints);
startActivity(intent);
getActivity().finish();
}
}
};
// Send all information needed to service to decrypt in other thread
Intent intent = new Intent(getActivity(), KeychainIntentService.class);
// fill values for this action
Bundle data = new Bundle();
intent.setAction(KeychainIntentService.ACTION_IMPORT_KEYRING);
String hexFp = KeyFormattingUtils.convertFingerprintToHex(mNfcFingerprints);
ArrayList<ParcelableKeyRing> keyList = new ArrayList<>();
keyList.add(new ParcelableKeyRing(hexFp, null, null));
data.putParcelableArrayList(KeychainIntentService.IMPORT_KEY_LIST, keyList);
{
Preferences prefs = Preferences.getPreferences(getActivity());
Preferences.CloudSearchPrefs cloudPrefs =
new Preferences.CloudSearchPrefs(true, true, prefs.getPreferredKeyserver());
data.putString(KeychainIntentService.IMPORT_KEY_SERVER, cloudPrefs.keyserver);
}
intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
// Create a new Messenger for the communication back
Messenger messenger = new Messenger(saveHandler);
intent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger);
saveHandler.showProgressDialog(getActivity());
// start service with intent
getActivity().startService(intent);
}
@Override
public void onNfcPerform() throws IOException {
mNfcFingerprints = mCreateKeyActivity.nfcGetFingerprints();
mNfcAid = mCreateKeyActivity.nfcGetAid();
mNfcUserId = mCreateKeyActivity.nfcGetUserId();
mNfcMasterKeyId = KeyFormattingUtils.getKeyIdFromFingerprint(mNfcFingerprints);
mNfcFingerprint = KeyFormattingUtils.convertFingerprintToHex(mNfcFingerprints);
setData();
refreshSearch();
}
}

View File

@ -53,9 +53,11 @@ import java.util.List;
public class ImportKeysListFragment extends ListFragment implements public class ImportKeysListFragment extends ListFragment implements
LoaderManager.LoaderCallbacks<AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>> { LoaderManager.LoaderCallbacks<AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>> {
private static final String ARG_DATA_URI = "uri"; private static final String ARG_DATA_URI = "uri";
private static final String ARG_BYTES = "bytes"; private static final String ARG_BYTES = "bytes";
private static final String ARG_SERVER_QUERY = "query"; public static final String ARG_SERVER_QUERY = "query";
public static final String ARG_NON_INTERACTIVE = "non_interactive";
private Activity mActivity; private Activity mActivity;
private ImportKeysAdapter mAdapter; private ImportKeysAdapter mAdapter;
@ -66,6 +68,7 @@ public class ImportKeysListFragment extends ListFragment implements
private static final int LOADER_ID_CLOUD = 1; private static final int LOADER_ID_CLOUD = 1;
private LongSparseArray<ParcelableKeyRing> mCachedKeyData; private LongSparseArray<ParcelableKeyRing> mCachedKeyData;
private boolean mNonInteractive;
public LoaderState getLoaderState() { public LoaderState getLoaderState() {
return mLoaderState; return mLoaderState;
@ -118,16 +121,19 @@ public class ImportKeysListFragment extends ListFragment implements
} }
/**
* Creates new instance of this fragment
*/
public static ImportKeysListFragment newInstance(byte[] bytes, Uri dataUri, String serverQuery) { public static ImportKeysListFragment newInstance(byte[] bytes, Uri dataUri, String serverQuery) {
return newInstance(bytes, dataUri, serverQuery, false);
}
public static ImportKeysListFragment newInstance(byte[] bytes, Uri dataUri,
String serverQuery, boolean nonInteractive) {
ImportKeysListFragment frag = new ImportKeysListFragment(); ImportKeysListFragment frag = new ImportKeysListFragment();
Bundle args = new Bundle(); Bundle args = new Bundle();
args.putByteArray(ARG_BYTES, bytes); args.putByteArray(ARG_BYTES, bytes);
args.putParcelable(ARG_DATA_URI, dataUri); args.putParcelable(ARG_DATA_URI, dataUri);
args.putString(ARG_SERVER_QUERY, serverQuery); args.putString(ARG_SERVER_QUERY, serverQuery);
args.putBoolean(ARG_NON_INTERACTIVE, nonInteractive);
frag.setArguments(args); frag.setArguments(args);
@ -173,9 +179,11 @@ public class ImportKeysListFragment extends ListFragment implements
mAdapter = new ImportKeysAdapter(mActivity); mAdapter = new ImportKeysAdapter(mActivity);
setListAdapter(mAdapter); setListAdapter(mAdapter);
Uri dataUri = getArguments().getParcelable(ARG_DATA_URI); Bundle args = getArguments();
byte[] bytes = getArguments().getByteArray(ARG_BYTES); Uri dataUri = args.containsKey(ARG_DATA_URI) ? args.<Uri>getParcelable(ARG_DATA_URI) : null;
String query = getArguments().getString(ARG_SERVER_QUERY); 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;
if (dataUri != null || bytes != null) { if (dataUri != null || bytes != null) {
mLoaderState = new BytesLoaderState(bytes, dataUri); mLoaderState = new BytesLoaderState(bytes, dataUri);
@ -203,6 +211,10 @@ public class ImportKeysListFragment extends ListFragment implements
public void onListItemClick(ListView l, View v, int position, long id) { public void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id); super.onListItemClick(l, v, position, id);
if (mNonInteractive) {
return;
}
// Select checkbox! // Select checkbox!
// Update underlying data and notify adapter of change. The adapter will // Update underlying data and notify adapter of change. The adapter will
// update the view automatically. // update the view automatically.

View File

@ -98,6 +98,7 @@ public class ViewKeyActivity extends BaseNfcActivity implements
static final int REQUEST_QR_FINGERPRINT = 1; static final int REQUEST_QR_FINGERPRINT = 1;
static final int REQUEST_DELETE = 2; static final int REQUEST_DELETE = 2;
static final int REQUEST_EXPORT = 3; static final int REQUEST_EXPORT = 3;
public static final String EXTRA_DISPLAY_RESULT = "display_result";
ExportHelper mExportHelper; ExportHelper mExportHelper;
ProviderHelper mProviderHelper; ProviderHelper mProviderHelper;
@ -268,6 +269,11 @@ public class ViewKeyActivity extends BaseNfcActivity implements
mNfcHelper = new NfcHelper(this, mProviderHelper); mNfcHelper = new NfcHelper(this, mProviderHelper);
mNfcHelper.initNfc(mDataUri); mNfcHelper.initNfc(mDataUri);
if (savedInstanceState == null && getIntent().hasExtra(EXTRA_DISPLAY_RESULT)) {
OperationResult result = getIntent().getParcelableExtra(EXTRA_DISPLAY_RESULT);
result.createNotify(this).show();
}
startFragment(savedInstanceState, mDataUri); startFragment(savedInstanceState, mDataUri);
if (savedInstanceState == null && getIntent().hasExtra(EXTRA_NFC_AID)) { if (savedInstanceState == null && getIntent().hasExtra(EXTRA_NFC_AID)) {
@ -570,7 +576,19 @@ public class ViewKeyActivity extends BaseNfcActivity implements
return; return;
} catch (PgpKeyNotFoundException e) { } catch (PgpKeyNotFoundException e) {
Notify.create(this, "Different key stored on Yubikey!", Style.ERROR).show(); Notify.create(this, "Different key stored on Yubikey!", Notify.LENGTH_LONG,
Style.WARN, new ActionListener() {
@Override
public void onAction() {
Intent intent = new Intent(
ViewKeyActivity.this, CreateKeyActivity.class);
intent.putExtra(ViewKeyActivity.EXTRA_NFC_AID, nfcAid);
intent.putExtra(ViewKeyActivity.EXTRA_NFC_USER_ID, nfcUserId);
intent.putExtra(ViewKeyActivity.EXTRA_NFC_FINGERPRINTS, nfcFingerprints);
startActivity(intent);
finish();
}
}, R.string.snack_yubikey_import).show();
return; return;
} }
} }

View File

@ -196,11 +196,9 @@ public class ViewKeyYubikeyFragment extends Fragment
vStatus.setText(R.string.yubikey_status_bound); vStatus.setText(R.string.yubikey_status_bound);
} else { } else {
vButton.setVisibility(View.VISIBLE); vButton.setVisibility(View.VISIBLE);
if (noneBound) { vStatus.setText(noneBound
vStatus.setText(R.string.yubikey_status_unbound); ? R.string.yubikey_status_unbound
} else { : R.string.yubikey_status_partly);
vStatus.setText(R.string.yubikey_status_partly);
}
} }
} }

View File

@ -3,38 +3,79 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
<ScrollView <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="wrap_content"
android:fillViewport="true" android:padding="4dp"
android:layout_above="@+id/create_key_buttons"> android:orientation="horizontal"
android:id="@+id/yubikey_status_layout" >
<ImageView
android:layout_margin="14dp"
android:layout_width="32dp"
android:layout_height="32dp"
android:scaleType="centerCrop"
android:src="@drawable/yubi_icon"/>
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:orientation="vertical"> android:orientation="vertical">
<TextView <TextView
android:id="@+id/yubikey_serno"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="16dp" android:layout_gravity="center_vertical"
android:layout_marginLeft="8dp" android:text="Yubikey #"
android:textAppearance="?android:attr/textAppearanceMedium" />
android:id="@+id/create_yubikey_unknown_fp"
android:text="(yubikey fingerprint)" />
<TextView <TextView
android:id="@+id/yubikey_userid"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="16dp" android:layout_gravity="center_vertical"
android:layout_marginLeft="8dp" android:text="User ID"
android:textAppearance="?android:attr/textAppearanceMedium" />
android:text="Hit next to import this key"
<TextView
android:id="@+id/yubikey_status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:text="Unknown key, hit next to import"
/> />
</LinearLayout> </LinearLayout>
</ScrollView> <ImageButton
android:id="@+id/button_search"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:padding="8dp"
android:src="@drawable/ic_search_grey_24dp"
android:layout_gravity="center_vertical"
android:background="?android:selectableItemBackground" />
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_marginTop="4dp"
android:layout_height="1dip"
android:layout_below="@id/yubikey_status_layout"
android:background="?android:attr/listDivider" />
<FrameLayout
android:id="@+id/yubikey_import_fragment"
android:layout_marginTop="8dp"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="@id/yubikey_status_layout"
android:layout_above="@id/create_key_buttons"
/>
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
@ -71,10 +112,10 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1" android:layout_weight="1"
android:text="@string/btn_next" android:text="@string/btn_import"
android:textAllCaps="true" android:textAllCaps="true"
android:minHeight="?android:attr/listPreferredItemHeight" android:minHeight="?android:attr/listPreferredItemHeight"
android:drawableRight="@drawable/ic_chevron_right_grey_24dp" android:drawableRight="@drawable/ic_key_plus_grey600_24dp"
android:drawablePadding="8dp" android:drawablePadding="8dp"
android:gravity="right|center_vertical" android:gravity="right|center_vertical"
android:clickable="true" android:clickable="true"

View File

@ -1124,7 +1124,7 @@
<string name="msg_import_fetch_error_decode">"Error decoding retrieved keyring!"</string> <string name="msg_import_fetch_error_decode">"Error decoding retrieved keyring!"</string>
<string name="msg_import_fetch_error">"Key could not be retrieved! (Network problems?)"</string> <string name="msg_import_fetch_error">"Key could not be retrieved! (Network problems?)"</string>
<string name="msg_import_fetch_keybase">"Retrieving from keybase.io: %s"</string> <string name="msg_import_fetch_keybase">"Retrieving from keybase.io: %s"</string>
<string name="msg_import_fetch_keyserver_error">"Could not retrieve key from keybase!"</string> <string name="msg_import_fetch_keyserver_error">"Could not retrieve key from keyservers: %s"</string>
<string name="msg_import_fetch_keyserver">"Retrieving from keyserver: %s"</string> <string name="msg_import_fetch_keyserver">"Retrieving from keyserver: %s"</string>
<string name="msg_import_fetch_keyserver_ok">"Key retrieval successful"</string> <string name="msg_import_fetch_keyserver_ok">"Key retrieval successful"</string>
<string name="msg_import_keyserver">"Using keyserver %s"</string> <string name="msg_import_keyserver">"Using keyserver %s"</string>
@ -1267,13 +1267,15 @@
<string name="nfc_write_succesful">Successfully written on NFC tag</string> <string name="nfc_write_succesful">Successfully written on NFC tag</string>
<string name="unlocked">Unlocked</string> <string name="unlocked">Unlocked</string>
<string name="nfc_settings">Settings</string> <string name="nfc_settings">Settings</string>
<string name="snack_yubikey_view">View</string> <string name="snack_yubikey_view">"View"</string>
<string name="button_bind_key">Bind Key</string> <string name="snack_yubikey_import">"Import"</string>
<string name="button_bind_key">"Bind Key"</string>
<string name="yubikey_serno">"Serial No: %s"</string> <string name="yubikey_serno">"Serial No: %s"</string>
<string name="yubikey_key_holder">"Key holder: "</string> <string name="yubikey_key_holder">"Key holder: "</string>
<string name="yubikey_key_holder_unset">"Key holder: &lt;unset&gt;"</string> <string name="yubikey_key_holder_unset">"Key holder: &lt;unset&gt;"</string>
<string name="yubikey_status_bound">Yubikey matches, bound to key</string> <string name="yubikey_status_bound">"Yubikey matches, bound to key"</string>
<string name="yubikey_status_unbound">Yubikey matches, can be bound to key</string> <string name="yubikey_status_unbound">"Yubikey matches, can be bound to key"</string>
<string name="yubikey_status_partly">Yubikey matches, partly bound to key</string> <string name="yubikey_status_partly">"Yubikey matches, partly bound to key"</string>
<string name="btn_import">"Import"</string>
</resources> </resources>