aboutsummaryrefslogtreecommitdiffstats
path: root/org_apg/src/org/apg/ui/ImportFromQRCodeActivity.java
blob: 593c841df1acef936d6c5ce6f8450f301658d674 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
package org.apg.ui;

import java.io.ByteArrayInputStream;
import java.io.IOException;

import org.apg.Apg;
import org.apg.Constants;
import org.apg.HkpKeyServer;
import org.apg.Id;
import org.apg.KeyServer.QueryException;
import org.spongycastle.openpgp.PGPKeyRing;
import org.spongycastle.openpgp.PGPPublicKeyRing;
import org.apg.R;

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();
    }
}