open-keychain/src/org/thialfihar/android/apg/ImportFromQRCodeActivity.java
2012-03-09 12:13:28 +01:00

134 lines
5.7 KiB
Java

package org.thialfihar.android.apg;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import org.spongycastle.openpgp.PGPKeyRing;
import org.spongycastle.openpgp.PGPPublicKeyRing;
import org.thialfihar.android.apg.KeyServer.QueryException;
import android.content.Intent;
import android.os.Bundle;
import android.os.Message;
import android.util.Log;
import android.widget.Toast;
import com.google.zxing.integration.android.IntentIntegrator;
import com.google.zxing.integration.android.IntentResult;
public class ImportFromQRCodeActivity extends BaseActivity {
private static final String TAG = "ImportFromQRCodeActivity";
private final Bundle status = new Bundle();
private final Message msg = new Message();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
new IntentIntegrator(this).initiateScan();
}
private void importAndSign(final long keyId, final String expectedFingerprint) {
if (expectedFingerprint != null && expectedFingerprint.length() > 0) {
Thread t = new Thread() {
@Override
public void run() {
try {
// TODO: display some sort of spinner here while the user waits
HkpKeyServer server = new HkpKeyServer(mPreferences.getKeyServers()[0]); // TODO: there should be only 1
String encodedKey = server.get(keyId);
PGPKeyRing keyring = Apg.decodeKeyRing(new ByteArrayInputStream(encodedKey.getBytes()));
if (keyring != null && keyring instanceof PGPPublicKeyRing) {
PGPPublicKeyRing publicKeyRing = (PGPPublicKeyRing) keyring;
// make sure the fingerprints match before we cache this thing
String actualFingerprint = Apg.convertToHex(publicKeyRing.getPublicKey().getFingerprint());
if (expectedFingerprint.equals(actualFingerprint)) {
// store the signed key in our local cache
int retval = Apg.storeKeyRingInCache(publicKeyRing);
if (retval != Id.return_value.ok && retval != Id.return_value.updated) {
status.putString(Apg.EXTRA_ERROR, "Failed to store signed key in local cache");
} else {
Intent intent = new Intent(ImportFromQRCodeActivity.this, SignKeyActivity.class);
intent.putExtra(Apg.EXTRA_KEY_ID, keyId);
startActivityForResult(intent, Id.request.sign_key);
}
} else {
status.putString(Apg.EXTRA_ERROR, "Scanned fingerprint does NOT match the fingerprint of the received key. You shouldnt trust this key.");
}
}
} catch (QueryException e) {
Log.e(TAG, "Failed to query KeyServer", e);
status.putString(Apg.EXTRA_ERROR, "Failed to query KeyServer");
status.putInt(Constants.extras.status, Id.message.done);
} catch (IOException e) {
Log.e(TAG, "Failed to query KeyServer", e);
status.putString(Apg.EXTRA_ERROR, "Failed to query KeyServer");
status.putInt(Constants.extras.status, Id.message.done);
}
}
};
t.setName("KeyExchange Download Thread");
t.setDaemon(true);
t.start();
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case IntentIntegrator.REQUEST_CODE: {
boolean debug = true; // TODO: remove this!!!
IntentResult scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, data);
if (debug || (scanResult != null && scanResult.getFormatName() != null)) {
String[] bits = debug ? new String[] { "5993515643896327656", "0816 F68A 6816 68FB 01BF 2CA5 532D 3EB9 1E2F EDE8" } : scanResult.getContents().split(",");
if (bits.length != 2) {
return; // dont know how to handle this. Not a valid code
}
long keyId = Long.parseLong(bits[0]);
String expectedFingerprint = bits[1];
importAndSign(keyId, expectedFingerprint);
break;
}
}
case Id.request.sign_key: {
// signals the end of processing. Signature was either applied, or it wasnt
status.putInt(Constants.extras.status, Id.message.done);
msg.setData(status);
sendMessage(msg);
break;
}
default: {
super.onActivityResult(requestCode, resultCode, data);
}
}
}
@Override
public void doneCallback(Message msg) {
super.doneCallback(msg);
Bundle data = msg.getData();
String error = data.getString(Apg.EXTRA_ERROR);
if (error != null) {
Toast.makeText(this, getString(R.string.errorMessage, error), Toast.LENGTH_SHORT).show();
return;
}
Toast.makeText(this, R.string.keySignSuccess, Toast.LENGTH_SHORT).show(); // TODO
finish();
}
}