]>
Commit | Line | Data |
---|---|---|
d799cbf6 | 1 | /* |
13ead876 | 2 | * Copyright (C) 2012-2017 Tobias Brunner |
d799cbf6 TB |
3 | * Copyright (C) 2012 Giuliano Grassi |
4 | * Copyright (C) 2012 Ralf Sager | |
89149dbb | 5 | * HSR Hochschule fuer Technik Rapperswil |
d799cbf6 TB |
6 | * |
7 | * This program is free software; you can redistribute it and/or modify it | |
8 | * under the terms of the GNU General Public License as published by the | |
9 | * Free Software Foundation; either version 2 of the License, or (at your | |
10 | * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. | |
11 | * | |
12 | * This program is distributed in the hope that it will be useful, but | |
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | |
14 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
15 | * for more details. | |
16 | */ | |
17 | ||
18 | package org.strongswan.android.data; | |
19 | ||
d799cbf6 TB |
20 | import android.content.ContentValues; |
21 | import android.content.Context; | |
22 | import android.database.Cursor; | |
23 | import android.database.SQLException; | |
24 | import android.database.sqlite.SQLiteDatabase; | |
25 | import android.database.sqlite.SQLiteOpenHelper; | |
3f9e90f6 | 26 | import android.database.sqlite.SQLiteQueryBuilder; |
d799cbf6 TB |
27 | import android.util.Log; |
28 | ||
13ead876 TB |
29 | import java.util.ArrayList; |
30 | import java.util.List; | |
31 | import java.util.UUID; | |
32 | ||
d799cbf6 TB |
33 | public class VpnProfileDataSource |
34 | { | |
35 | private static final String TAG = VpnProfileDataSource.class.getSimpleName(); | |
36 | public static final String KEY_ID = "_id"; | |
c4ab9af7 | 37 | public static final String KEY_UUID = "_uuid"; |
d799cbf6 TB |
38 | public static final String KEY_NAME = "name"; |
39 | public static final String KEY_GATEWAY = "gateway"; | |
48f51d94 | 40 | public static final String KEY_VPN_TYPE = "vpn_type"; |
d799cbf6 TB |
41 | public static final String KEY_USERNAME = "username"; |
42 | public static final String KEY_PASSWORD = "password"; | |
43 | public static final String KEY_CERTIFICATE = "certificate"; | |
e09f4120 | 44 | public static final String KEY_USER_CERTIFICATE = "user_certificate"; |
7e2a6c4a | 45 | public static final String KEY_MTU = "mtu"; |
5b11855f | 46 | public static final String KEY_PORT = "port"; |
f3d8da76 | 47 | public static final String KEY_SPLIT_TUNNELING = "split_tunneling"; |
89149dbb TB |
48 | public static final String KEY_LOCAL_ID = "local_id"; |
49 | public static final String KEY_REMOTE_ID = "remote_id"; | |
13ead876 | 50 | public static final String KEY_EXCLUDED_SUBNETS = "excluded_subnets"; |
a9875259 | 51 | public static final String KEY_INCLUDED_SUBNETS = "included_subnets"; |
d799cbf6 TB |
52 | |
53 | private DatabaseHelper mDbHelper; | |
54 | private SQLiteDatabase mDatabase; | |
55 | private final Context mContext; | |
56 | ||
57 | private static final String DATABASE_NAME = "strongswan.db"; | |
58 | private static final String TABLE_VPNPROFILE = "vpnprofile"; | |
59 | ||
a9875259 | 60 | private static final int DATABASE_VERSION = 11; |
d799cbf6 TB |
61 | |
62 | public static final String DATABASE_CREATE = | |
63 | "CREATE TABLE " + TABLE_VPNPROFILE + " (" + | |
64 | KEY_ID + " INTEGER PRIMARY KEY AUTOINCREMENT," + | |
c4ab9af7 | 65 | KEY_UUID + " TEXT UNIQUE," + |
d799cbf6 TB |
66 | KEY_NAME + " TEXT NOT NULL," + |
67 | KEY_GATEWAY + " TEXT NOT NULL," + | |
48f51d94 | 68 | KEY_VPN_TYPE + " TEXT NOT NULL," + |
3f9e90f6 | 69 | KEY_USERNAME + " TEXT," + |
d799cbf6 | 70 | KEY_PASSWORD + " TEXT," + |
e09f4120 | 71 | KEY_CERTIFICATE + " TEXT," + |
7e2a6c4a | 72 | KEY_USER_CERTIFICATE + " TEXT," + |
5b11855f | 73 | KEY_MTU + " INTEGER," + |
f3d8da76 | 74 | KEY_PORT + " INTEGER," + |
89149dbb TB |
75 | KEY_SPLIT_TUNNELING + " INTEGER," + |
76 | KEY_LOCAL_ID + " TEXT," + | |
13ead876 | 77 | KEY_REMOTE_ID + " TEXT," + |
a9875259 TB |
78 | KEY_EXCLUDED_SUBNETS + " TEXT," + |
79 | KEY_INCLUDED_SUBNETS + " TEXT" + | |
d799cbf6 | 80 | ");"; |
3f9e90f6 | 81 | private static final String[] ALL_COLUMNS = new String[] { |
d799cbf6 | 82 | KEY_ID, |
c4ab9af7 | 83 | KEY_UUID, |
d799cbf6 TB |
84 | KEY_NAME, |
85 | KEY_GATEWAY, | |
48f51d94 | 86 | KEY_VPN_TYPE, |
d799cbf6 TB |
87 | KEY_USERNAME, |
88 | KEY_PASSWORD, | |
e09f4120 TB |
89 | KEY_CERTIFICATE, |
90 | KEY_USER_CERTIFICATE, | |
7e2a6c4a | 91 | KEY_MTU, |
5b11855f | 92 | KEY_PORT, |
f3d8da76 | 93 | KEY_SPLIT_TUNNELING, |
89149dbb TB |
94 | KEY_LOCAL_ID, |
95 | KEY_REMOTE_ID, | |
13ead876 | 96 | KEY_EXCLUDED_SUBNETS, |
a9875259 | 97 | KEY_INCLUDED_SUBNETS, |
d799cbf6 TB |
98 | }; |
99 | ||
100 | private static class DatabaseHelper extends SQLiteOpenHelper | |
101 | { | |
102 | public DatabaseHelper(Context context) | |
103 | { | |
104 | super(context, DATABASE_NAME, null, DATABASE_VERSION); | |
105 | } | |
106 | ||
107 | @Override | |
108 | public void onCreate(SQLiteDatabase database) | |
109 | { | |
110 | database.execSQL(DATABASE_CREATE); | |
111 | } | |
112 | ||
113 | @Override | |
114 | public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) | |
115 | { | |
116 | Log.w(TAG, "Upgrading database from version " + oldVersion + | |
e09f4120 TB |
117 | " to " + newVersion); |
118 | if (oldVersion < 2) | |
119 | { | |
120 | db.execSQL("ALTER TABLE " + TABLE_VPNPROFILE + " ADD " + KEY_USER_CERTIFICATE + | |
121 | " TEXT;"); | |
122 | } | |
48f51d94 TB |
123 | if (oldVersion < 3) |
124 | { | |
125 | db.execSQL("ALTER TABLE " + TABLE_VPNPROFILE + " ADD " + KEY_VPN_TYPE + | |
126 | " TEXT DEFAULT '';"); | |
127 | } | |
3f9e90f6 TB |
128 | if (oldVersion < 4) |
129 | { /* remove NOT NULL constraint from username column */ | |
130 | updateColumns(db); | |
131 | } | |
7e2a6c4a TB |
132 | if (oldVersion < 5) |
133 | { | |
134 | db.execSQL("ALTER TABLE " + TABLE_VPNPROFILE + " ADD " + KEY_MTU + | |
135 | " INTEGER;"); | |
136 | } | |
5b11855f TB |
137 | if (oldVersion < 6) |
138 | { | |
139 | db.execSQL("ALTER TABLE " + TABLE_VPNPROFILE + " ADD " + KEY_PORT + | |
140 | " INTEGER;"); | |
141 | } | |
f3d8da76 TB |
142 | if (oldVersion < 7) |
143 | { | |
144 | db.execSQL("ALTER TABLE " + TABLE_VPNPROFILE + " ADD " + KEY_SPLIT_TUNNELING + | |
145 | " INTEGER;"); | |
146 | } | |
89149dbb TB |
147 | if (oldVersion < 8) |
148 | { | |
149 | db.execSQL("ALTER TABLE " + TABLE_VPNPROFILE + " ADD " + KEY_LOCAL_ID + | |
150 | " TEXT;"); | |
151 | db.execSQL("ALTER TABLE " + TABLE_VPNPROFILE + " ADD " + KEY_REMOTE_ID + | |
152 | " TEXT;"); | |
153 | } | |
c4ab9af7 TB |
154 | if (oldVersion < 9) |
155 | { | |
156 | db.execSQL("ALTER TABLE " + TABLE_VPNPROFILE + " ADD " + KEY_UUID + | |
157 | " TEXT;"); | |
158 | updateColumns(db); | |
159 | } | |
13ead876 TB |
160 | if (oldVersion < 10) |
161 | { | |
162 | db.execSQL("ALTER TABLE " + TABLE_VPNPROFILE + " ADD " + KEY_EXCLUDED_SUBNETS + | |
163 | " TEXT;"); | |
164 | } | |
a9875259 TB |
165 | if (oldVersion < 11) |
166 | { | |
167 | db.execSQL("ALTER TABLE " + TABLE_VPNPROFILE + " ADD " + KEY_INCLUDED_SUBNETS + | |
168 | " TEXT;"); | |
169 | } | |
3f9e90f6 TB |
170 | } |
171 | ||
172 | private void updateColumns(SQLiteDatabase db) | |
173 | { | |
174 | db.beginTransaction(); | |
175 | try | |
176 | { | |
177 | db.execSQL("ALTER TABLE " + TABLE_VPNPROFILE + " RENAME TO tmp_" + TABLE_VPNPROFILE + ";"); | |
178 | db.execSQL(DATABASE_CREATE); | |
179 | StringBuilder insert = new StringBuilder("INSERT INTO " + TABLE_VPNPROFILE + " SELECT "); | |
180 | SQLiteQueryBuilder.appendColumns(insert, ALL_COLUMNS); | |
181 | db.execSQL(insert.append(" FROM tmp_" + TABLE_VPNPROFILE + ";").toString()); | |
182 | db.execSQL("DROP TABLE tmp_" + TABLE_VPNPROFILE + ";"); | |
183 | db.setTransactionSuccessful(); | |
184 | } | |
185 | finally | |
186 | { | |
187 | db.endTransaction(); | |
188 | } | |
d799cbf6 TB |
189 | } |
190 | } | |
191 | ||
192 | /** | |
193 | * Construct a new VPN profile data source. The context is used to | |
194 | * open/create the database. | |
195 | * @param context context used to access the database | |
196 | */ | |
197 | public VpnProfileDataSource(Context context) | |
198 | { | |
199 | this.mContext = context; | |
200 | } | |
201 | ||
202 | /** | |
203 | * Open the VPN profile data source. The database is automatically created | |
204 | * if it does not yet exist. If that fails an exception is thrown. | |
205 | * @return itself (allows to chain initialization calls) | |
206 | * @throws SQLException if the database could not be opened or created | |
207 | */ | |
208 | public VpnProfileDataSource open() throws SQLException | |
209 | { | |
210 | if (mDbHelper == null) | |
211 | { | |
212 | mDbHelper = new DatabaseHelper(mContext); | |
213 | mDatabase = mDbHelper.getWritableDatabase(); | |
214 | } | |
215 | return this; | |
216 | } | |
217 | ||
218 | /** | |
219 | * Close the data source. | |
220 | */ | |
221 | public void close() | |
222 | { | |
223 | if (mDbHelper != null) | |
224 | { | |
225 | mDbHelper.close(); | |
226 | mDbHelper = null; | |
227 | } | |
228 | } | |
229 | ||
230 | /** | |
231 | * Insert the given VPN profile into the database. On success the Id of | |
232 | * the object is updated and the object returned. | |
233 | * | |
234 | * @param profile the profile to add | |
235 | * @return the added VPN profile or null, if failed | |
236 | */ | |
237 | public VpnProfile insertProfile(VpnProfile profile) | |
238 | { | |
239 | ContentValues values = ContentValuesFromVpnProfile(profile); | |
240 | long insertId = mDatabase.insert(TABLE_VPNPROFILE, null, values); | |
241 | if (insertId == -1) | |
242 | { | |
243 | return null; | |
244 | } | |
245 | profile.setId(insertId); | |
246 | return profile; | |
247 | } | |
248 | ||
249 | /** | |
250 | * Updates the given VPN profile in the database. | |
251 | * @param profile the profile to update | |
252 | * @return true if update succeeded, false otherwise | |
253 | */ | |
254 | public boolean updateVpnProfile(VpnProfile profile) | |
255 | { | |
256 | long id = profile.getId(); | |
257 | ContentValues values = ContentValuesFromVpnProfile(profile); | |
258 | return mDatabase.update(TABLE_VPNPROFILE, values, KEY_ID + " = " + id, null) > 0; | |
259 | } | |
260 | ||
261 | /** | |
262 | * Delete the given VPN profile from the database. | |
263 | * @param profile the profile to delete | |
264 | * @return true if deleted, false otherwise | |
265 | */ | |
266 | public boolean deleteVpnProfile(VpnProfile profile) | |
267 | { | |
268 | long id = profile.getId(); | |
269 | return mDatabase.delete(TABLE_VPNPROFILE, KEY_ID + " = " + id, null) > 0; | |
270 | } | |
271 | ||
272 | /** | |
273 | * Get a single VPN profile from the database. | |
274 | * @param id the ID of the VPN profile | |
275 | * @return the profile or null, if not found | |
276 | */ | |
277 | public VpnProfile getVpnProfile(long id) | |
278 | { | |
279 | VpnProfile profile = null; | |
280 | Cursor cursor = mDatabase.query(TABLE_VPNPROFILE, ALL_COLUMNS, | |
281 | KEY_ID + "=" + id, null, null, null, null); | |
282 | if (cursor.moveToFirst()) | |
283 | { | |
284 | profile = VpnProfileFromCursor(cursor); | |
285 | } | |
286 | cursor.close(); | |
287 | return profile; | |
288 | } | |
289 | ||
c4ab9af7 TB |
290 | /** |
291 | * Get a single VPN profile from the database by its UUID. | |
292 | * @param uuid the UUID of the VPN profile | |
293 | * @return the profile or null, if not found | |
294 | */ | |
295 | public VpnProfile getVpnProfile(UUID uuid) | |
296 | { | |
297 | VpnProfile profile = null; | |
298 | Cursor cursor = mDatabase.query(TABLE_VPNPROFILE, ALL_COLUMNS, | |
299 | KEY_UUID + "='" + uuid.toString() + "'", null, null, null, null); | |
300 | if (cursor.moveToFirst()) | |
301 | { | |
302 | profile = VpnProfileFromCursor(cursor); | |
303 | } | |
304 | cursor.close(); | |
305 | return profile; | |
306 | } | |
307 | ||
d799cbf6 TB |
308 | /** |
309 | * Get a list of all VPN profiles stored in the database. | |
310 | * @return list of VPN profiles | |
311 | */ | |
312 | public List<VpnProfile> getAllVpnProfiles() | |
313 | { | |
314 | List<VpnProfile> vpnProfiles = new ArrayList<VpnProfile>(); | |
315 | ||
316 | Cursor cursor = mDatabase.query(TABLE_VPNPROFILE, ALL_COLUMNS, null, null, null, null, null); | |
317 | cursor.moveToFirst(); | |
318 | while (!cursor.isAfterLast()) | |
319 | { | |
320 | VpnProfile vpnProfile = VpnProfileFromCursor(cursor); | |
321 | vpnProfiles.add(vpnProfile); | |
322 | cursor.moveToNext(); | |
323 | } | |
324 | cursor.close(); | |
325 | return vpnProfiles; | |
326 | } | |
327 | ||
328 | private VpnProfile VpnProfileFromCursor(Cursor cursor) | |
329 | { | |
330 | VpnProfile profile = new VpnProfile(); | |
331 | profile.setId(cursor.getLong(cursor.getColumnIndex(KEY_ID))); | |
c4ab9af7 | 332 | profile.setUUID(getUUID(cursor, cursor.getColumnIndex(KEY_UUID))); |
d799cbf6 TB |
333 | profile.setName(cursor.getString(cursor.getColumnIndex(KEY_NAME))); |
334 | profile.setGateway(cursor.getString(cursor.getColumnIndex(KEY_GATEWAY))); | |
48f51d94 | 335 | profile.setVpnType(VpnType.fromIdentifier(cursor.getString(cursor.getColumnIndex(KEY_VPN_TYPE)))); |
d799cbf6 TB |
336 | profile.setUsername(cursor.getString(cursor.getColumnIndex(KEY_USERNAME))); |
337 | profile.setPassword(cursor.getString(cursor.getColumnIndex(KEY_PASSWORD))); | |
338 | profile.setCertificateAlias(cursor.getString(cursor.getColumnIndex(KEY_CERTIFICATE))); | |
e09f4120 | 339 | profile.setUserCertificateAlias(cursor.getString(cursor.getColumnIndex(KEY_USER_CERTIFICATE))); |
7e2a6c4a | 340 | profile.setMTU(getInt(cursor, cursor.getColumnIndex(KEY_MTU))); |
5b11855f | 341 | profile.setPort(getInt(cursor, cursor.getColumnIndex(KEY_PORT))); |
f3d8da76 | 342 | profile.setSplitTunneling(getInt(cursor, cursor.getColumnIndex(KEY_SPLIT_TUNNELING))); |
89149dbb TB |
343 | profile.setLocalId(cursor.getString(cursor.getColumnIndex(KEY_LOCAL_ID))); |
344 | profile.setRemoteId(cursor.getString(cursor.getColumnIndex(KEY_REMOTE_ID))); | |
13ead876 | 345 | profile.setExcludedSubnets(cursor.getString(cursor.getColumnIndex(KEY_EXCLUDED_SUBNETS))); |
a9875259 | 346 | profile.setIncludedSubnets(cursor.getString(cursor.getColumnIndex(KEY_INCLUDED_SUBNETS))); |
d799cbf6 TB |
347 | return profile; |
348 | } | |
349 | ||
350 | private ContentValues ContentValuesFromVpnProfile(VpnProfile profile) | |
351 | { | |
352 | ContentValues values = new ContentValues(); | |
c4ab9af7 | 353 | values.put(KEY_UUID, profile.getUUID() != null ? profile.getUUID().toString() : null); |
d799cbf6 TB |
354 | values.put(KEY_NAME, profile.getName()); |
355 | values.put(KEY_GATEWAY, profile.getGateway()); | |
48f51d94 | 356 | values.put(KEY_VPN_TYPE, profile.getVpnType().getIdentifier()); |
d799cbf6 TB |
357 | values.put(KEY_USERNAME, profile.getUsername()); |
358 | values.put(KEY_PASSWORD, profile.getPassword()); | |
359 | values.put(KEY_CERTIFICATE, profile.getCertificateAlias()); | |
e09f4120 | 360 | values.put(KEY_USER_CERTIFICATE, profile.getUserCertificateAlias()); |
7e2a6c4a | 361 | values.put(KEY_MTU, profile.getMTU()); |
5b11855f | 362 | values.put(KEY_PORT, profile.getPort()); |
f3d8da76 | 363 | values.put(KEY_SPLIT_TUNNELING, profile.getSplitTunneling()); |
89149dbb TB |
364 | values.put(KEY_LOCAL_ID, profile.getLocalId()); |
365 | values.put(KEY_REMOTE_ID, profile.getRemoteId()); | |
13ead876 | 366 | values.put(KEY_EXCLUDED_SUBNETS, profile.getExcludedSubnets()); |
a9875259 | 367 | values.put(KEY_INCLUDED_SUBNETS, profile.getIncludedSubnets()); |
d799cbf6 TB |
368 | return values; |
369 | } | |
7e2a6c4a TB |
370 | |
371 | private Integer getInt(Cursor cursor, int columnIndex) | |
372 | { | |
373 | return cursor.isNull(columnIndex) ? null : cursor.getInt(columnIndex); | |
374 | } | |
c4ab9af7 TB |
375 | |
376 | private UUID getUUID(Cursor cursor, int columnIndex) | |
377 | { | |
378 | try | |
379 | { | |
380 | return cursor.isNull(columnIndex) ? null : UUID.fromString(cursor.getString(columnIndex)); | |
381 | } | |
382 | catch (Exception e) | |
383 | { | |
384 | return null; | |
385 | } | |
386 | } | |
d799cbf6 | 387 | } |