Merge branch 'master' of https://github.com/open-keychain/open-keychain into improve-file

This commit is contained in:
mar-v-in
2014-06-19 13:57:35 +02:00
47 changed files with 1038 additions and 432 deletions

View File

@@ -53,15 +53,16 @@ public class KeybaseKeyserver extends Keyserver {
// only list them if they have a key
if (JWalk.optObject(match, "components", "key_fingerprint") != null) {
String keybaseId = JWalk.getString(match, "components", "username", "val");
String fingerprint = JWalk.getString(match, "components", "key_fingerprint", "val");
fingerprint = fingerprint.replace(" ", "").toUpperCase();
if (keybaseId.equals(query) || fingerprint.startsWith(query.toUpperCase())) {
results.add(makeEntry(match));
} else {
results.add(makeEntry(match));
}
// TODO: needed anymore?
// String keybaseId = JWalk.getString(match, "components", "username", "val");
// String fingerprint = JWalk.getString(match, "components", "key_fingerprint", "val");
// fingerprint = fingerprint.replace(" ", "").toUpperCase();
// if (keybaseId.equals(query) || fingerprint.startsWith(query.toUpperCase())) {
// results.add(makeEntry(match));
// } else {
// results.add(makeEntry(match));
// }
results.add(makeEntry(match));
}
}
} catch (Exception e) {

View File

@@ -35,7 +35,6 @@ public class OpenPgpSignatureResultBuilder {
private boolean mSignatureAvailable = false;
private boolean mKnownKey = false;
private boolean mValidSignature = false;
private boolean mValidKeyBinding = false;
private boolean mIsSignatureKeyCertified = false;
public void signatureOnly(boolean signatureOnly) {
@@ -58,10 +57,6 @@ public class OpenPgpSignatureResultBuilder {
this.mValidSignature = validSignature;
}
public void validKeyBinding(boolean validKeyBinding) {
this.mValidKeyBinding = validKeyBinding;
}
public void signatureKeyCertified(boolean isSignatureKeyCertified) {
this.mIsSignatureKeyCertified = isSignatureKeyCertified;
}
@@ -77,7 +72,7 @@ public class OpenPgpSignatureResultBuilder {
// valid sig!
if (mKnownKey) {
if (mValidKeyBinding && mValidSignature) {
if (mValidSignature) {
result.setKeyId(mKeyId);
result.setUserId(mUserId);
@@ -89,8 +84,7 @@ public class OpenPgpSignatureResultBuilder {
result.setStatus(OpenPgpSignatureResult.SIGNATURE_SUCCESS_UNCERTIFIED);
}
} else {
Log.d(Constants.TAG, "Error!\nvalidKeyBinding: " + mValidKeyBinding
+ "\nvalidSignature: " + mValidSignature);
Log.d(Constants.TAG, "Error! Invalid signature.");
result.setStatus(OpenPgpSignatureResult.SIGNATURE_ERROR);
}
} else {

View File

@@ -122,9 +122,6 @@ public class PgpDecryptVerify {
/**
* Allow these key ids alone for decryption.
* This means only ciphertexts encrypted for one of these private key can be decrypted.
*
* @param allowedKeyIds
* @return
*/
public Builder setAllowedKeyIds(Set<Long> allowedKeyIds) {
this.mAllowedKeyIds = allowedKeyIds;
@@ -496,10 +493,7 @@ public class PgpDecryptVerify {
// Verify signature and check binding signatures
boolean validSignature = signature.verify(messageSignature);
boolean validKeyBinding = signingRing.verifySubkeyBinding(signingKey);
signatureResultBuilder.validSignature(validSignature);
signatureResultBuilder.validKeyBinding(validKeyBinding);
}
}
@@ -643,10 +637,8 @@ public class PgpDecryptVerify {
// Verify signature and check binding signatures
boolean validSignature = signature.verify();
boolean validKeyBinding = signingRing.verifySubkeyBinding(signingKey);
signatureResultBuilder.validSignature(validSignature);
signatureResultBuilder.validKeyBinding(validKeyBinding);
}
result.setSignatureResult(signatureResultBuilder.build());
@@ -657,10 +649,6 @@ public class PgpDecryptVerify {
/**
* Mostly taken from ClearSignedFileProcessor in Bouncy Castle
*
* @param sig
* @param line
* @throws SignatureException
*/
private static void processLine(PGPSignature sig, byte[] line)
throws SignatureException {

View File

@@ -60,7 +60,7 @@ public class PgpHelper {
}
public static String getFullVersion(Context context) {
return "OpenPGP Keychain v" + getVersion(context);
return "OpenKeychain v" + getVersion(context);
}
// public static final class content {

View File

@@ -226,7 +226,7 @@ public class PgpImportExport {
try {
WrappedPublicKeyRing ring = mProviderHelper.getWrappedPublicKeyRing(
KeychainContract.KeyRings.buildGenericKeyRingUri(pubKeyMasterId)
KeychainContract.KeyRings.buildUnifiedKeyRingUri(pubKeyMasterId)
);
ring.encode(arOutStream);

View File

@@ -547,6 +547,7 @@ public class UncachedKeyRing {
// if we already have a cert, and this one is not newer: skip it
if (selfCert != null && selfCert.getCreationTime().before(cert.getCreationTime())) {
log.add(LogLevel.DEBUG, LogType.MSG_KC_SUB_DUP, indent);
redundantCerts += 1;
continue;
}
@@ -574,8 +575,9 @@ public class UncachedKeyRing {
continue;
}
// if there is no binding (yet), or the revocation is newer than the binding: keep it
// if there is a certification that is newer than this revocation, don't bother
if (selfCert != null && selfCert.getCreationTime().after(cert.getCreationTime())) {
log.add(LogLevel.DEBUG, LogType.MSG_KC_SUB_REVOKE_DUP, indent);
redundantCerts += 1;
continue;
}

View File

@@ -1,24 +1,16 @@
package org.sufficientlysecure.keychain.pgp;
import org.spongycastle.bcpg.ArmoredOutputStream;
import org.spongycastle.bcpg.SignatureSubpacketTags;
import org.spongycastle.openpgp.PGPException;
import org.spongycastle.openpgp.PGPKeyRing;
import org.spongycastle.openpgp.PGPObjectFactory;
import org.spongycastle.openpgp.PGPPublicKey;
import org.spongycastle.openpgp.PGPPublicKeyRing;
import org.spongycastle.openpgp.PGPSignature;
import org.spongycastle.openpgp.PGPSignatureList;
import org.spongycastle.openpgp.PGPSignatureSubpacketVector;
import org.spongycastle.openpgp.operator.jcajce.JcaPGPContentVerifierBuilderProvider;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
import org.sufficientlysecure.keychain.util.IterableIterator;
import org.sufficientlysecure.keychain.util.Log;
import java.io.IOException;
import java.security.SignatureException;
import java.util.Arrays;
import java.util.Iterator;
public class WrappedPublicKeyRing extends WrappedKeyRing {
@@ -70,106 +62,11 @@ public class WrappedPublicKeyRing extends WrappedKeyRing {
}
return cKey;
}
// TODO handle with proper exception
throw new PgpGeneralException("no encryption key available");
}
public boolean verifySubkeyBinding(WrappedPublicKey cachedSubkey) {
boolean validSubkeyBinding = false;
boolean validTempSubkeyBinding = false;
boolean validPrimaryKeyBinding = false;
PGPPublicKey masterKey = getRing().getPublicKey();
PGPPublicKey subKey = cachedSubkey.getPublicKey();
// Is this the master key? Match automatically, then.
if(Arrays.equals(masterKey.getFingerprint(), subKey.getFingerprint())) {
return true;
}
JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider =
new JcaPGPContentVerifierBuilderProvider()
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
Iterator<PGPSignature> itr = subKey.getSignatures();
while (itr.hasNext()) { //what does gpg do if the subkey binding is wrong?
//gpg has an invalid subkey binding error on key import I think, but doesn't shout
//about keys without subkey signing. Can't get it to import a slightly broken one
//either, so we will err on bad subkey binding here.
PGPSignature sig = itr.next();
if (sig.getKeyID() == masterKey.getKeyID() &&
sig.getSignatureType() == PGPSignature.SUBKEY_BINDING) {
//check and if ok, check primary key binding.
try {
sig.init(contentVerifierBuilderProvider, masterKey);
validTempSubkeyBinding = sig.verifyCertification(masterKey, subKey);
} catch (PGPException e) {
continue;
} catch (SignatureException e) {
continue;
}
if (validTempSubkeyBinding) {
validSubkeyBinding = true;
}
if (validTempSubkeyBinding) {
validPrimaryKeyBinding = verifyPrimaryKeyBinding(sig.getUnhashedSubPackets(),
masterKey, subKey);
if (validPrimaryKeyBinding) {
break;
}
validPrimaryKeyBinding = verifyPrimaryKeyBinding(sig.getHashedSubPackets(),
masterKey, subKey);
if (validPrimaryKeyBinding) {
break;
}
}
}
}
return validSubkeyBinding && validPrimaryKeyBinding;
}
static boolean verifyPrimaryKeyBinding(PGPSignatureSubpacketVector pkts,
PGPPublicKey masterPublicKey,
PGPPublicKey signingPublicKey) {
boolean validPrimaryKeyBinding = false;
JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider =
new JcaPGPContentVerifierBuilderProvider()
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
PGPSignatureList eSigList;
if (pkts.hasSubpacket(SignatureSubpacketTags.EMBEDDED_SIGNATURE)) {
try {
eSigList = pkts.getEmbeddedSignatures();
} catch (IOException e) {
return false;
} catch (PGPException e) {
return false;
}
for (int j = 0; j < eSigList.size(); ++j) {
PGPSignature emSig = eSigList.get(j);
if (emSig.getSignatureType() == PGPSignature.PRIMARYKEY_BINDING) {
try {
emSig.init(contentVerifierBuilderProvider, signingPublicKey);
validPrimaryKeyBinding = emSig.verifyCertification(masterPublicKey, signingPublicKey);
if (validPrimaryKeyBinding) {
break;
}
} catch (PGPException e) {
continue;
} catch (SignatureException e) {
continue;
}
}
}
}
return validPrimaryKeyBinding;
}
public IterableIterator<WrappedPublicKey> publicKeyIterator() {
@SuppressWarnings("unchecked")
final Iterator<PGPPublicKey> it = getRing().getPublicKeys();
return new IterableIterator<WrappedPublicKey>(new Iterator<WrappedPublicKey>() {
@Override

View File

@@ -201,6 +201,7 @@ public class OperationResultParcel implements Parcelable {
MSG_KC_SUB_BAD_KEYID(R.string.msg_kc_sub_bad_keyid),
MSG_KC_SUB_BAD_TIME(R.string.msg_kc_sub_bad_time),
MSG_KC_SUB_BAD_TYPE(R.string.msg_kc_sub_bad_type),
MSG_KC_SUB_DUP (R.string.msg_kc_sub_dup),
MSG_KC_SUB_PRIMARY_BAD(R.string.msg_kc_sub_primary_bad),
MSG_KC_SUB_PRIMARY_BAD_ERR(R.string.msg_kc_sub_primary_bad_err),
MSG_KC_SUB_PRIMARY_NONE(R.string.msg_kc_sub_primary_none),

View File

@@ -18,9 +18,7 @@
package org.sufficientlysecure.keychain.ui;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.nfc.NdefMessage;
@@ -31,16 +29,12 @@ import android.os.Message;
import android.os.Messenger;
import android.os.Parcelable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.view.ViewPager;
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBarActivity;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import com.github.johnpersano.supertoasts.SuperCardToast;
import com.github.johnpersano.supertoasts.SuperToast;
@@ -51,7 +45,6 @@ import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.helper.OtherHelper;
import org.sufficientlysecure.keychain.keyimport.ImportKeysListEntry;
import org.sufficientlysecure.keychain.keyimport.KeybaseKeyserver;
import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing;
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
import org.sufficientlysecure.keychain.service.KeychainIntentService;
@@ -130,60 +123,13 @@ public class ImportKeysActivity extends ActionBarActivity {
mNavigationStrings = getResources().getStringArray(R.array.import_action_list);
if (ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN.equals(getIntent().getAction())) {
setTitle(R.string.nav_import);
} else {
initTabs();
}
// TODO: add actionbar button for this action?
// if (ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN.equals(getIntent().getAction())) {
// }
handleActions(savedInstanceState, getIntent());
}
private void initTabs() {
mTabsAdapter = new PagerTabStripAdapter(this);
mViewPager.setAdapter(mTabsAdapter);
mSlidingTabLayout.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
// resize view pager back to 64 if keyserver settings have been collapsed
if (getViewPagerHeight() > VIEW_PAGER_HEIGHT) {
resizeViewPager(VIEW_PAGER_HEIGHT);
}
}
@Override
public void onPageSelected(int position) {
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
Bundle serverBundle = new Bundle();
// serverBundle.putParcelable(ViewKeyMainFragment.ARG_DATA_URI, dataUri);
mTabsAdapter.addTab(ImportKeysServerFragment.class,
serverBundle, getString(R.string.import_tab_keyserver));
Bundle qrCodeBundle = new Bundle();
// importBundle.putParcelable(ViewKeyMainFragment.ARG_DATA_URI, dataUri);
mTabsAdapter.addTab(ImportKeysQrCodeFragment.class,
qrCodeBundle, getString(R.string.import_tab_qr_code));
Bundle fileBundle = new Bundle();
// importBundle.putParcelable(ViewKeyMainFragment.ARG_DATA_URI, dataUri);
mTabsAdapter.addTab(ImportKeysFileFragment.class,
fileBundle, getString(R.string.import_tab_direct));
Bundle keybaseBundle = new Bundle();
// keybaseBundle.putParcelable(ViewKeyMainFragment.ARG_DATA_URI, dataUri);
mTabsAdapter.addTab(ImportKeysKeybaseFragment.class,
keybaseBundle, getString(R.string.import_tab_keybase));
// update layout after operations
mSlidingTabLayout.setViewPager(mViewPager);
}
protected void handleActions(Bundle savedInstanceState, Intent intent) {
String action = intent.getAction();
Bundle extras = intent.getExtras();
@@ -200,6 +146,8 @@ public class ImportKeysActivity extends ActionBarActivity {
action = ACTION_IMPORT_KEY;
}
Bundle serverBundle = null;
boolean serverOnly = false;
if (scheme != null && scheme.toLowerCase(Locale.ENGLISH).equals(Constants.FINGERPRINT_SCHEME)) {
/* Scanning a fingerprint directly with Barcode Scanner */
loadFromFingerprintUri(savedInstanceState, dataUri);
@@ -240,10 +188,8 @@ public class ImportKeysActivity extends ActionBarActivity {
if (query != null && query.length() > 0) {
// display keyserver fragment with query
Bundle args = new Bundle();
args.putString(ImportKeysServerFragment.ARG_QUERY, query);
// loadNavFragment(NAV_SERVER, args);
//TODO: load afterwards!
serverBundle = new Bundle();
serverBundle.putString(ImportKeysServerFragment.ARG_QUERY, query);
mSwitchToTab = NAV_SERVER;
// action: search immediately
@@ -259,7 +205,19 @@ public class ImportKeysActivity extends ActionBarActivity {
*/
String fingerprint = intent.getStringExtra(EXTRA_FINGERPRINT);
loadFromFingerprint(savedInstanceState, fingerprint);
if (isFingerprintValid(fingerprint)) {
String query = "0x" + fingerprint;
// display keyserver fragment with query
serverBundle = new Bundle();
serverBundle.putString(ImportKeysServerFragment.ARG_QUERY, query);
serverBundle.putBoolean(ImportKeysServerFragment.ARG_DISABLE_QUERY_EDIT, true);
serverOnly = true;
mSwitchToTab = NAV_SERVER;
// action: search immediately
startListFragment(savedInstanceState, null, null, query);
}
} else {
Log.e(Constants.TAG,
"IMPORT_KEY_FROM_KEYSERVER action needs to contain the 'query', 'key_id', or " +
@@ -298,6 +256,44 @@ public class ImportKeysActivity extends ActionBarActivity {
startListFragment(savedInstanceState, null, null, null);
}
initTabs(serverBundle, serverOnly);
}
private void initTabs(Bundle serverBundle, boolean serverOnly) {
mTabsAdapter = new PagerTabStripAdapter(this);
mViewPager.setAdapter(mTabsAdapter);
mSlidingTabLayout.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
// resize view pager back to 64 if keyserver settings have been collapsed
if (getViewPagerHeight() > VIEW_PAGER_HEIGHT) {
resizeViewPager(VIEW_PAGER_HEIGHT);
}
}
@Override
public void onPageSelected(int position) {
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
mTabsAdapter.addTab(ImportKeysServerFragment.class,
serverBundle, getString(R.string.import_tab_keyserver));
if (!serverOnly) {
mTabsAdapter.addTab(ImportKeysQrCodeFragment.class,
null, getString(R.string.import_tab_qr_code));
mTabsAdapter.addTab(ImportKeysFileFragment.class,
null, getString(R.string.import_tab_direct));
mTabsAdapter.addTab(ImportKeysKeybaseFragment.class,
null, getString(R.string.import_tab_keybase));
}
// update layout after operations
mSlidingTabLayout.setViewPager(mViewPager);
mViewPager.setCurrentItem(mSwitchToTab);
}
@@ -338,35 +334,52 @@ public class ImportKeysActivity extends ActionBarActivity {
Log.d(Constants.TAG, "fingerprint: " + fingerprint);
loadFromFingerprint(savedInstanceState, fingerprint);
// TODO: reload fragment when coming from qr code!
// loadFromFingerprint(savedInstanceState, fingerprint);
// String query = "0x" + fingerprint;
//
// // display keyserver fragment with query
// Bundle serverBundle = new Bundle();
// serverBundle.putString(ImportKeysServerFragment.ARG_QUERY, query);
// serverBundle.putBoolean(ImportKeysServerFragment.ARG_DISABLE_QUERY_EDIT, true);
//
// return serverBundle;
}
public void loadFromFingerprint(Bundle savedInstanceState, String fingerprint) {
private boolean isFingerprintValid(String fingerprint) {
if (fingerprint == null || fingerprint.length() < 40) {
SuperCardToast toast = SuperCardToast.create(this,
getString(R.string.import_qr_code_too_short_fingerprint),
SuperToast.Duration.LONG);
toast.setBackground(SuperToast.Background.RED);
toast.show();
return;
return false;
} else {
return true;
}
String query = "0x" + fingerprint;
// display keyserver fragment with query
Bundle args = new Bundle();
args.putString(ImportKeysServerFragment.ARG_QUERY, query);
args.putBoolean(ImportKeysServerFragment.ARG_DISABLE_QUERY_EDIT, true);
// loadNavFragment(NAV_SERVER, args);
//TODO
// action: search directly
startListFragment(savedInstanceState, null, null, query);
}
public void loadCallback(byte[] importData, Uri dataUri, String serverQuery, String keyServer, String keybaseQuery) {
mListFragment.loadNew(importData, dataUri, serverQuery, keyServer, keybaseQuery);
/**
* Scroll ViewPager left and right
*
* @param event
* @return
*/
@Override
public boolean onTouchEvent(MotionEvent event) {
boolean result = super.onTouchEvent(event);
if (!result) {
mViewPager.onTouchEvent(event);
}
return result;
}
public void loadCallback(ImportKeysListFragment.LoaderState loaderState) {
mListFragment.loadNew(loaderState);
}
/**
@@ -477,7 +490,8 @@ public class ImportKeysActivity extends ActionBarActivity {
}
};
if (mListFragment.getKeyBytes() != null || mListFragment.getDataUri() != null) {
ImportKeysListFragment.LoaderState ls = mListFragment.getLoaderState();
if (ls instanceof ImportKeysListFragment.BytesLoaderState) {
Log.d(Constants.TAG, "importKeys started");
// Send all information needed to service to import key in other thread
@@ -503,7 +517,9 @@ public class ImportKeysActivity extends ActionBarActivity {
// start service with intent
startService(intent);
} else if (mListFragment.getServerQuery() != null) {
} else if (ls instanceof ImportKeysListFragment.KeyserverLoaderState) {
ImportKeysListFragment.KeyserverLoaderState sls = (ImportKeysListFragment.KeyserverLoaderState) ls;
// Send all information needed to service to query keys in other thread
Intent intent = new Intent(this, KeychainIntentService.class);
@@ -512,7 +528,7 @@ public class ImportKeysActivity extends ActionBarActivity {
// fill values for this action
Bundle data = new Bundle();
data.putString(KeychainIntentService.DOWNLOAD_KEY_SERVER, mListFragment.getKeyServer());
data.putString(KeychainIntentService.DOWNLOAD_KEY_SERVER, sls.keyserver);
// get selected key entries
ArrayList<ImportKeysListEntry> selectedEntries = mListFragment.getSelectedEntries();
@@ -529,7 +545,7 @@ public class ImportKeysActivity extends ActionBarActivity {
// start service with intent
startService(intent);
} else if (mListFragment.getKeybaseQuery() != null) {
} else if (ls instanceof ImportKeysListFragment.KeybaseLoaderState) {
// Send all information needed to service to query keys in other thread
Intent intent = new Intent(this, KeychainIntentService.class);

View File

@@ -85,7 +85,7 @@ public class ImportKeysFileFragment extends Fragment {
return;
}
}
mImportActivity.loadCallback(sendText.getBytes(), null, null, null, null);
mImportActivity.loadCallback(new ImportKeysListFragment.BytesLoaderState(sendText.getBytes(), null));
}
});
@@ -107,7 +107,7 @@ public class ImportKeysFileFragment extends Fragment {
if (resultCode == Activity.RESULT_OK && data != null) {
// load data
mImportActivity.loadCallback(null, data.getData(), null, null, null);
mImportActivity.loadCallback(new ImportKeysListFragment.BytesLoaderState(null, data.getData()));
}
break;

View File

@@ -117,6 +117,6 @@ public class ImportKeysKeybaseFragment extends Fragment {
}
private void search(String query) {
mImportActivity.loadCallback(null, null, null, null, query);
mImportActivity.loadCallback(new ImportKeysListFragment.KeybaseLoaderState(query));
}
}

View File

@@ -27,8 +27,6 @@ import android.support.v4.util.LongSparseArray;
import android.view.View;
import android.widget.ListView;
import com.devspark.appmsg.AppMsg;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.helper.Preferences;
@@ -60,11 +58,7 @@ public class ImportKeysListFragment extends ListFragment implements
private Activity mActivity;
private ImportKeysAdapter mAdapter;
private byte[] mKeyBytes;
private Uri mDataUri;
private String mServerQuery;
private String mKeyServer;
private String mKeybaseQuery;
private LoaderState mLoaderState;
private static final int LOADER_ID_BYTES = 0;
private static final int LOADER_ID_SERVER_QUERY = 1;
@@ -72,24 +66,8 @@ public class ImportKeysListFragment extends ListFragment implements
private LongSparseArray<ParcelableKeyRing> mCachedKeyData;
public byte[] getKeyBytes() {
return mKeyBytes;
}
public Uri getDataUri() {
return mDataUri;
}
public String getServerQuery() {
return mServerQuery;
}
public String getKeybaseQuery() {
return mKeybaseQuery;
}
public String getKeyServer() {
return mKeyServer;
public LoaderState getLoaderState() {
return mLoaderState;
}
public List<ImportKeysListEntry> getData() {
@@ -124,6 +102,37 @@ public class ImportKeysListFragment extends ListFragment implements
return frag;
}
static public class LoaderState {
}
static public class BytesLoaderState extends LoaderState {
byte[] keyBytes;
Uri dataUri;
BytesLoaderState(byte[] keyBytes, Uri dataUri) {
this.keyBytes = keyBytes;
this.dataUri = dataUri;
}
}
static public class KeyserverLoaderState extends LoaderState {
String serverQuery;
String keyserver;
KeyserverLoaderState(String serverQuery, String keyserver) {
this.serverQuery = serverQuery;
this.keyserver = keyserver;
}
}
static public class KeybaseLoaderState extends LoaderState {
String keybaseQuery;
KeybaseLoaderState(String keybaseQuery) {
this.keybaseQuery = keybaseQuery;
}
}
/**
* Define Adapter and Loader on create of Activity
*/
@@ -140,43 +149,20 @@ public class ImportKeysListFragment extends ListFragment implements
mAdapter = new ImportKeysAdapter(mActivity);
setListAdapter(mAdapter);
mDataUri = getArguments().getParcelable(ARG_DATA_URI);
mKeyBytes = getArguments().getByteArray(ARG_BYTES);
mServerQuery = getArguments().getString(ARG_SERVER_QUERY);
// TODO: this is used when scanning QR Code. Currently it simply uses keyserver nr 0
mKeyServer = Preferences.getPreferences(getActivity())
.getKeyServers()[0];
if (mDataUri != null || mKeyBytes != null) {
// Start out with a progress indicator.
setListShown(false);
// Prepare the loader. Either re-connect with an existing one,
// or start a new one.
// give arguments to onCreateLoader()
getLoaderManager().initLoader(LOADER_ID_BYTES, null, this);
if (getArguments().containsKey(ARG_DATA_URI) || getArguments().containsKey(ARG_BYTES)) {
Uri dataUri = getArguments().getParcelable(ARG_DATA_URI);
byte[] bytes = getArguments().getByteArray(ARG_BYTES);
mLoaderState = new BytesLoaderState(bytes, dataUri);
} else if (getArguments().containsKey(ARG_SERVER_QUERY)) {
String query = getArguments().getString(ARG_SERVER_QUERY);
// TODO: this is used when scanning QR Code or updating a key.
// Currently it simply uses keyserver nr 0
String keyserver = Preferences.getPreferences(getActivity())
.getKeyServers()[0];
mLoaderState = new KeyserverLoaderState(query, keyserver);
}
if (mServerQuery != null && mKeyServer != null) {
// Start out with a progress indicator.
setListShown(false);
// Prepare the loader. Either re-connect with an existing one,
// or start a new one.
// give arguments to onCreateLoader()
getLoaderManager().initLoader(LOADER_ID_SERVER_QUERY, null, this);
}
if (mKeybaseQuery != null) {
// Start out with a progress indicator.
setListShown(false);
// Prepare the loader. Either re-connect with an existing one,
// or start a new one.
// give arguments to onCreateLoader()
getLoaderManager().initLoader(LOADER_ID_KEYBASE, null, this);
}
restartLoaders();
}
@Override
@@ -192,31 +178,33 @@ public class ImportKeysListFragment extends ListFragment implements
mAdapter.notifyDataSetChanged();
}
public void loadNew(byte[] keyBytes, Uri dataUri, String serverQuery, String keyServer, String keybaseQuery) {
mKeyBytes = keyBytes;
mDataUri = dataUri;
mServerQuery = serverQuery;
mKeyServer = keyServer;
mKeybaseQuery = keybaseQuery;
public void loadNew(LoaderState loaderState) {
mLoaderState = loaderState;
if (mKeyBytes != null || mDataUri != null) {
restartLoaders();
}
private void restartLoaders() {
if (mLoaderState instanceof BytesLoaderState) {
// Start out with a progress indicator.
setListShown(false);
getLoaderManager().restartLoader(LOADER_ID_BYTES, null, this);
}
if (mServerQuery != null && mKeyServer != null) {
getLoaderManager().destroyLoader(LOADER_ID_SERVER_QUERY);
getLoaderManager().destroyLoader(LOADER_ID_KEYBASE);
} else if (mLoaderState instanceof KeyserverLoaderState) {
// Start out with a progress indicator.
setListShown(false);
getLoaderManager().destroyLoader(LOADER_ID_BYTES);
getLoaderManager().restartLoader(LOADER_ID_SERVER_QUERY, null, this);
}
if (mKeybaseQuery != null) {
getLoaderManager().destroyLoader(LOADER_ID_KEYBASE);
} else if (mLoaderState instanceof KeybaseLoaderState) {
// Start out with a progress indicator.
setListShown(false);
getLoaderManager().destroyLoader(LOADER_ID_BYTES);
getLoaderManager().destroyLoader(LOADER_ID_SERVER_QUERY);
getLoaderManager().restartLoader(LOADER_ID_KEYBASE, null, this);
}
}
@@ -226,14 +214,17 @@ public class ImportKeysListFragment extends ListFragment implements
onCreateLoader(int id, Bundle args) {
switch (id) {
case LOADER_ID_BYTES: {
InputData inputData = getInputData(mKeyBytes, mDataUri);
BytesLoaderState ls = (BytesLoaderState) mLoaderState;
InputData inputData = getInputData(ls.keyBytes, ls.dataUri);
return new ImportKeysListLoader(mActivity, inputData);
}
case LOADER_ID_SERVER_QUERY: {
return new ImportKeysListServerLoader(getActivity(), mServerQuery, mKeyServer);
KeyserverLoaderState ls = (KeyserverLoaderState) mLoaderState;
return new ImportKeysListServerLoader(getActivity(), ls.serverQuery, ls.keyserver);
}
case LOADER_ID_KEYBASE: {
return new ImportKeysListKeybaseLoader(getActivity(), mKeybaseQuery);
KeybaseLoaderState ls = (KeybaseLoaderState) mLoaderState;
return new ImportKeysListKeybaseLoader(getActivity(), ls.keybaseQuery);
}
default:
@@ -280,7 +271,8 @@ public class ImportKeysListFragment extends ListFragment implements
((ImportKeysListLoader.NonPgpPart) error).getCount() + " " + getResources().
getQuantityString(R.plurals.error_import_non_pgp_part,
((ImportKeysListLoader.NonPgpPart) error).getCount()),
Notify.Style.OK);
Notify.Style.OK
);
} else {
Notify.showNotify(getActivity(), R.string.error_generic_report_bug, Notify.Style.ERROR);
}
@@ -289,7 +281,6 @@ public class ImportKeysListFragment extends ListFragment implements
case LOADER_ID_SERVER_QUERY:
case LOADER_ID_KEYBASE:
// TODO: possibly fine-tune message building for these two cases
if (error == null) {
// No error
} else if (error instanceof Keyserver.QueryTooShortException) {

View File

@@ -25,8 +25,6 @@ import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.google.zxing.integration.android.IntentResult;
@@ -36,18 +34,13 @@ import org.sufficientlysecure.keychain.util.IntentIntegratorSupportV4;
import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.Notify;
import java.util.ArrayList;
import java.util.Locale;
public class ImportKeysQrCodeFragment extends Fragment {
private ImportKeysActivity mImportActivity;
private View mNfcButton;
private View mQrCodeButton;
private TextView mQrCodeText;
private ProgressBar mQrCodeProgress;
private String[] mQrCodeContent;
/**
* Creates new instance of this fragment
@@ -81,8 +74,6 @@ public class ImportKeysQrCodeFragment extends Fragment {
});
mQrCodeButton = view.findViewById(R.id.import_qrcode_button);
mQrCodeText = (TextView) view.findViewById(R.id.import_qrcode_text);
mQrCodeProgress = (ProgressBar) view.findViewById(R.id.import_qrcode_progress);
mQrCodeButton.setOnClickListener(new View.OnClickListener() {
@@ -120,16 +111,9 @@ public class ImportKeysQrCodeFragment extends Fragment {
return;
}
// look if it is the whole key
String[] parts = scannedContent.split(",");
if (parts.length == 3) {
importParts(parts);
return;
}
// is this a full key encoded as qr code?
if (scannedContent.startsWith("-----BEGIN PGP")) {
mImportActivity.loadCallback(scannedContent.getBytes(), null, null, null, null);
mImportActivity.loadCallback(new ImportKeysListFragment.BytesLoaderState(scannedContent.getBytes(), null));
return;
}
@@ -147,68 +131,8 @@ public class ImportKeysQrCodeFragment extends Fragment {
}
}
public void importFingerprint(Uri dataUri) {
mImportActivity.loadFromFingerprintUri(null, dataUri);
}
private void importParts(String[] parts) {
int counter = Integer.valueOf(parts[0]);
int size = Integer.valueOf(parts[1]);
String content = parts[2];
Log.d(Constants.TAG, "" + counter);
Log.d(Constants.TAG, "" + size);
Log.d(Constants.TAG, "" + content);
// first qr code -> setup
if (counter == 0) {
mQrCodeContent = new String[size];
mQrCodeProgress.setMax(size);
mQrCodeProgress.setVisibility(View.VISIBLE);
mQrCodeText.setVisibility(View.VISIBLE);
}
if (mQrCodeContent == null || counter > mQrCodeContent.length) {
Notify.showNotify(getActivity(), R.string.import_qr_code_start_with_one, Notify.Style.ERROR);
return;
}
// save scanned content
mQrCodeContent[counter] = content;
// get missing numbers
ArrayList<Integer> missing = new ArrayList<Integer>();
for (int i = 0; i < mQrCodeContent.length; i++) {
if (mQrCodeContent[i] == null) {
missing.add(i);
}
}
// update progress and text
int alreadyScanned = mQrCodeContent.length - missing.size();
mQrCodeProgress.setProgress(alreadyScanned);
String missingString = "";
for (int m : missing) {
if (!missingString.equals("")) {
missingString += ", ";
}
missingString += String.valueOf(m + 1);
}
String missingText = getResources().getQuantityString(R.plurals.import_qr_code_missing,
missing.size(), missingString);
mQrCodeText.setText(missingText);
// finished!
if (missing.size() == 0) {
mQrCodeText.setText(R.string.import_qr_code_finished);
String result = "";
for (String in : mQrCodeContent) {
result += in;
}
mImportActivity.loadCallback(result.getBytes(), null, null, null, null);
}
}
}

View File

@@ -170,8 +170,8 @@ public class ImportKeysServerFragment extends Fragment {
mImportActivity = (ImportKeysActivity) activity;
}
private void search(String query, String keyServer) {
mImportActivity.loadCallback(null, null, query, keyServer, null);
private void search(String query, String keyserver) {
mImportActivity.loadCallback(new ImportKeysListFragment.KeyserverLoaderState(query, keyserver));
}
}