~w-shackleton/droidpad-android/stable

« back to all changes in this revision

Viewing changes to src/uk/digitalsquid/droidpad/Pairing.java

  • Committer: William Shackleton
  • Date: 2013-04-03 20:21:22 UTC
  • mfrom: (51.2.10 secure)
  • mto: This revision was merged to the branch mainline in revision 52.
  • Revision ID: w.shackleton@gmail.com-20130403202122-w9xcr2y1qifvh45s
Merged support for TLS connections. Still a few bugs.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*  This file is part of DroidPad.
 
2
 *
 
3
 *  DroidPad is free software: you can redistribute it and/or modify
 
4
 *  it under the terms of the GNU General Public License as published by
 
5
 *  the Free Software Foundation, either version 3 of the License, or
 
6
 *  (at your option) any later version.
 
7
 *
 
8
 *  DroidPad is distributed in the hope that it will be useful,
 
9
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
11
 *  GNU General Public License for more details.
 
12
 *
 
13
 *  You should have received a copy of the GNU General Public License
 
14
 *  along with DroidPad.  If not, see <http://www.gnu.org/licenses/>.
 
15
 */
 
16
 
 
17
package uk.digitalsquid.droidpad;
 
18
 
 
19
import java.io.IOException;
 
20
import java.util.StringTokenizer;
 
21
import java.util.UUID;
 
22
 
 
23
import uk.digitalsquid.ext.Base64;
 
24
import android.content.ContentValues;
 
25
import android.content.Context;
 
26
import android.database.Cursor;
 
27
import android.database.SQLException;
 
28
import android.database.sqlite.SQLiteDatabase;
 
29
import android.database.sqlite.SQLiteOpenHelper;
 
30
import android.util.Log;
 
31
 
 
32
public class Pairing implements LogTag {
 
33
        
 
34
        private final PairedDevices pairingDB;
 
35
        
 
36
        public Pairing(Context context) {
 
37
                pairingDB = new PairedDevices(context);
 
38
        }
 
39
        
 
40
        public static final class DevicePair {
 
41
                private final UUID computerId;
 
42
                private final String computerName;
 
43
                private final UUID deviceId;
 
44
                private final byte[] psk;
 
45
                
 
46
                public DevicePair(UUID computerId, String computerName, UUID deviceId, byte[] psk) {
 
47
                        this.computerId = computerId;
 
48
                        this.computerName = computerName;
 
49
                        this.deviceId = deviceId;
 
50
                        this.psk = psk;
 
51
                }
 
52
 
 
53
                public UUID getComputerId() {
 
54
                        return computerId;
 
55
                }
 
56
 
 
57
                public String getComputerName() {
 
58
                        return computerName;
 
59
                }
 
60
 
 
61
                public UUID getDeviceId() {
 
62
                        return deviceId;
 
63
                }
 
64
 
 
65
                public byte[] getPsk() {
 
66
                        return psk;
 
67
                }
 
68
        }
 
69
        
 
70
        protected static class PairedDevices extends SQLiteOpenHelper {
 
71
                public static final String DB_NAME = "pairing";
 
72
                public static final int DB_VERSION = 1;
 
73
                public PairedDevices(Context context) {
 
74
                        super(context, DB_NAME, null, DB_VERSION);
 
75
                }
 
76
                @Override
 
77
                public void onCreate(SQLiteDatabase db) {
 
78
                        try {
 
79
                                db.execSQL("CREATE TABLE pairs (" +
 
80
                                                "id INTEGER PRIMARY KEY NOT NULL," +
 
81
                                                "computerId TEXT NOT NULL," +
 
82
                                                "computerName TEXT," +
 
83
                                                "deviceId TEXT NOT NULL," +
 
84
                                                "psk TEXT NOT NULL);");
 
85
                        } catch(SQLException e) {
 
86
                                Log.e(TAG, "Failed to create DB tables", e);
 
87
                        }
 
88
                }
 
89
                @Override
 
90
                public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
 
91
                }
 
92
                
 
93
                public void addPairing(UUID computerId, String computerName, UUID deviceId, byte[] psk) throws IOException {
 
94
                        SQLiteDatabase db = getWritableDatabase();
 
95
                        ContentValues values = new ContentValues(4);
 
96
                        values.put("computerId", computerId.toString());
 
97
                        values.put("computerName", computerName);
 
98
                        values.put("deviceId", deviceId.toString());
 
99
                        values.put("psk", Base64.encodeBytes(psk));
 
100
                        if(db.insert("pairs", null, values) == -1)
 
101
                                throw new IOException("Failed to add a new device pair to the database");
 
102
                        db.close();
 
103
                }
 
104
                
 
105
                public DevicePair findPairing(UUID computerId) throws IOException {
 
106
                        SQLiteDatabase db = getReadableDatabase();
 
107
                        Cursor c = db.query("pairs",
 
108
                                        new String[] {
 
109
                                                "computerName",
 
110
                                                "deviceId",
 
111
                                                "psk"},
 
112
                                        "computerId = ?",
 
113
                                        new String[] {
 
114
                                                computerId.toString()
 
115
                                        },
 
116
                                        null, null, null);
 
117
                        if(c.getCount() < 1) return null;
 
118
                        c.moveToFirst();
 
119
                        UUID deviceId;
 
120
                        String computerName; byte[] psk;
 
121
                        computerName = c.getString(0);
 
122
                        deviceId = UUID.fromString(c.getString(1));
 
123
                        psk = Base64.decode(c.getString(2));
 
124
                        c.close();
 
125
                        db.close();
 
126
                        return new DevicePair(computerId, computerName, deviceId, psk);
 
127
                }
 
128
        }
 
129
        
 
130
        /**
 
131
         * Adds a new paired device to the database. String must be in the form:
 
132
         * "Computer uuid
 
133
         * Computer name
 
134
         * Device uuid
 
135
         * PSK (base64)"
 
136
         * @param pairingString The {@link String} to add
 
137
         * @throws IOException An error occurs during database IO
 
138
         * @throws IllegalArgumentException An error occurs decoding the data
 
139
         */
 
140
        public DevicePair pairNewDevice(String pairingString) throws IOException, IllegalArgumentException {
 
141
                StringTokenizer tkz = new StringTokenizer(pairingString, "\n");
 
142
                if(tkz.countTokens() < 4)
 
143
                        throw new IllegalArgumentException("Incorrect format for pairing string");
 
144
                UUID computerId, deviceId;
 
145
                String computerName; byte[] psk;
 
146
                try {
 
147
                        computerId = UUID.fromString(tkz.nextToken());
 
148
                        computerName = tkz.nextToken();
 
149
                        deviceId = UUID.fromString(tkz.nextToken());
 
150
                        psk = Base64.decode(tkz.nextToken());
 
151
                } catch (IllegalArgumentException e) {
 
152
                        throw new IllegalArgumentException("Incorrect format for pairing string", e);
 
153
                } catch (IOException e) {
 
154
                        throw new IllegalArgumentException("Incorrect format for pairing string", e);
 
155
                }
 
156
                pairingDB.addPairing(computerId, computerName, deviceId, psk);
 
157
                return new DevicePair(computerId, computerName, deviceId, psk);
 
158
        }
 
159
        
 
160
        public DevicePair findDevicePair(String computerId) {
 
161
                try {
 
162
                        return findDevicePair(UUID.fromString(computerId));
 
163
                } catch(NullPointerException e) {
 
164
                        Log.e(TAG, "Incorrectly formatted uuid", e);
 
165
                } catch(IllegalArgumentException e) {
 
166
                        Log.e(TAG, "Incorrectly formatted uuid", e);
 
167
                }
 
168
                return null;
 
169
        }
 
170
        
 
171
        /**
 
172
         * finds a device pair in the DB. Returns <code>null</code> if no pair found.
 
173
         * @param computerId
 
174
         * @return
 
175
         */
 
176
        public DevicePair findDevicePair(UUID computerId) {
 
177
                try {
 
178
                        return pairingDB.findPairing(computerId);
 
179
                } catch (IOException e) {
 
180
                        Log.e(TAG, "Couldn't find device pairing", e);
 
181
                } catch (NullPointerException e) {
 
182
                        Log.e(TAG, "Couldn't find device pairing", e);
 
183
                }
 
184
                return null;
 
185
        }
 
186
}