0331a01f6b7a136af089a756c80037738a2359c4
[PrivacyBrowser.git] / app / src / main / java / com / stoutner / privacybrowser / helpers / DomainsDatabaseHelper.java
1 /*
2  * Copyright © 2017 Soren Stoutner <soren@stoutner.com>.
3  *
4  * This file is part of Privacy Browser <https://www.stoutner.com/privacy-browser>.
5  *
6  * Privacy Browser is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * Privacy Browser is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with Privacy Browser.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 package com.stoutner.privacybrowser.helpers;
21
22 import android.content.ContentValues;
23 import android.content.Context;
24 import android.database.Cursor;
25 import android.database.sqlite.SQLiteDatabase;
26 import android.database.sqlite.SQLiteOpenHelper;
27
28 public class DomainsDatabaseHelper extends SQLiteOpenHelper {
29     private static final int SCHEMA_VERSION = 4;
30     private static final String DOMAINS_DATABASE = "domains.db";
31     private static final String DOMAINS_TABLE = "domains";
32
33     public static final String _ID = "_id";
34     public static final String DOMAIN_NAME = "domainname";
35     public static final String ENABLE_JAVASCRIPT = "enablejavascript";
36     public static final String ENABLE_FIRST_PARTY_COOKIES = "enablefirstpartycookies";
37     public static final String ENABLE_THIRD_PARTY_COOKIES = "enablethirdpartycookies";
38     public static final String ENABLE_DOM_STORAGE = "enabledomstorage";
39     public static final String ENABLE_FORM_DATA = "enableformdata";
40     public static final String USER_AGENT = "useragent";
41     public static final String FONT_SIZE = "fontsize";
42     public static final String DISPLAY_IMAGES = "displayimages";
43     public static final String NIGHT_MODE = "nightmode";
44     public static final String PINNED_SSL_CERTIFICATE = "pinnedsslcertificate";
45     public static final String SSL_ISSUED_TO_COMMON_NAME = "sslissuedtocommonname";
46     public static final String SSL_ISSUED_TO_ORGANIZATION = "sslissuedtoorganization";
47     public static final String SSL_ISSUED_TO_ORGANIZATIONAL_UNIT = "sslissuedtoorganizationalunit";
48     public static final String SSL_ISSUED_BY_COMMON_NAME = "sslissuedbycommonname";
49     public static final String SSL_ISSUED_BY_ORGANIZATION = "sslissuedbyorganization";
50     public static final String SSL_ISSUED_BY_ORGANIZATIONAL_UNIT = "sslissuedbyorganizationalunit";
51     public static final String SSL_START_DATE = "sslstartdate";
52     public static final String SSL_END_DATE = "sslenddate";
53
54     // Display webpage images constants.
55     public static final int DISPLAY_WEBPAGE_IMAGES_SYSTEM_DEFAULT = 0;
56     public static final int DISPLAY_WEBPAGE_IMAGES_ENABLED = 1;
57     public static final int DISPLAY_WEBPAGE_IMAGES_DISABLED = 2;
58
59     // Night mode constants.
60     public static final int NIGHT_MODE_SYSTEM_DEFAULT = 0;
61     public static final int NIGHT_MODE_ENABLED = 1;
62     public static final int NIGHT_MODE_DISABLED = 2;
63
64     // Initialize the database.  The lint warnings for the unused parameters are suppressed.
65     public DomainsDatabaseHelper(Context context, @SuppressWarnings("UnusedParameters") String name, SQLiteDatabase.CursorFactory cursorFactory, @SuppressWarnings("UnusedParameters") int version) {
66         super(context, DOMAINS_DATABASE, cursorFactory, SCHEMA_VERSION);
67     }
68
69     @Override
70     public void onCreate(SQLiteDatabase domainsDatabase) {
71         // Setup the SQL string to create the `domains` table.
72         String CREATE_DOMAINS_TABLE = "CREATE TABLE " + DOMAINS_TABLE + " (" +
73                 _ID + " INTEGER PRIMARY KEY, " +
74                 DOMAIN_NAME + " TEXT, " +
75                 ENABLE_JAVASCRIPT + " BOOLEAN, " +
76                 ENABLE_FIRST_PARTY_COOKIES + " BOOLEAN, " +
77                 ENABLE_THIRD_PARTY_COOKIES + " BOOLEAN, " +
78                 ENABLE_DOM_STORAGE + " BOOLEAN, " +
79                 ENABLE_FORM_DATA + " BOOLEAN, " +
80                 USER_AGENT + " TEXT, " +
81                 FONT_SIZE + " INTEGER, " +
82                 DISPLAY_IMAGES + " INTEGER, " +
83                 NIGHT_MODE + " INTEGER, " +
84                 PINNED_SSL_CERTIFICATE + " BOOLEAN, " +
85                 SSL_ISSUED_TO_COMMON_NAME + " TEXT, " +
86                 SSL_ISSUED_TO_ORGANIZATION + " TEXT, " +
87                 SSL_ISSUED_TO_ORGANIZATIONAL_UNIT + " TEXT, " +
88                 SSL_ISSUED_BY_COMMON_NAME + " TEXT, " +
89                 SSL_ISSUED_BY_ORGANIZATION + " TEXT, " +
90                 SSL_ISSUED_BY_ORGANIZATIONAL_UNIT + " TEXT, " +
91                 SSL_START_DATE + " INTEGER, " +
92                 SSL_END_DATE + " INTEGER);";
93
94         // Make it so.
95         domainsDatabase.execSQL(CREATE_DOMAINS_TABLE);
96     }
97
98     @Override
99     public void onUpgrade(SQLiteDatabase domainsDatabase, int oldVersion, int newVersion) {
100         // Upgrade `DOMAINS_TABLE`.
101         switch (oldVersion) {
102             // Upgrade from `SCHEMA_VERSION` 1.
103             case 1:
104                 // Add the `DISPLAY_IMAGES` column.
105                 domainsDatabase.execSQL("ALTER TABLE " + DOMAINS_TABLE + " ADD COLUMN " + DISPLAY_IMAGES + " INTEGER");
106
107             // Upgrade from `SCHEMA_VERSION` 2.
108             case 2:
109                 //  Add the SSL certificate columns.
110                 domainsDatabase.execSQL("ALTER TABLE " + DOMAINS_TABLE + " ADD COLUMN " + PINNED_SSL_CERTIFICATE + " BOOLEAN");
111                 domainsDatabase.execSQL("ALTER TABLE " + DOMAINS_TABLE + " ADD COLUMN " + SSL_ISSUED_TO_COMMON_NAME + " TEXT");
112                 domainsDatabase.execSQL("ALTER TABLE " + DOMAINS_TABLE + " ADD COLUMN " + SSL_ISSUED_TO_ORGANIZATION + " TEXT");
113                 domainsDatabase.execSQL("ALTER TABLE " + DOMAINS_TABLE + " ADD COLUMN " + SSL_ISSUED_TO_ORGANIZATIONAL_UNIT + " TEXT");
114                 domainsDatabase.execSQL("ALTER TABLE " + DOMAINS_TABLE + " ADD COLUMN " + SSL_ISSUED_BY_COMMON_NAME + " TEXT");
115                 domainsDatabase.execSQL("ALTER TABLE " + DOMAINS_TABLE + " ADD COLUMN " + SSL_ISSUED_BY_ORGANIZATION + " TEXT");
116                 domainsDatabase.execSQL("ALTER TABLE " + DOMAINS_TABLE + " ADD COLUMN " + SSL_ISSUED_BY_ORGANIZATIONAL_UNIT + " TEXT");
117                 domainsDatabase.execSQL("ALTER TABLE " + DOMAINS_TABLE + " ADD COLUMN " + SSL_START_DATE + " INTEGER");
118                 domainsDatabase.execSQL("ALTER TABLE " + DOMAINS_TABLE + " ADD COLUMN " + SSL_END_DATE + " INTEGER");
119
120             // Upgrade from `SCHEMA_VERSION` 3.
121             case 3:
122                 // Add the `NIGHT_MODE` column.
123                 domainsDatabase.execSQL("ALTER TABLE " + DOMAINS_TABLE + " ADD COLUMN " + NIGHT_MODE + " INTEGER");
124         }
125     }
126
127     public Cursor getDomainNameCursorOrderedByDomain() {
128         // Get a readable database handle.
129         SQLiteDatabase domainsDatabase = this.getReadableDatabase();
130
131         // Get everything in `DOMAINS_TABLE` ordered by `DOMAIN_NAME`.
132         final String GET_CURSOR_ORDERED_BY_DOMAIN = "SELECT " + _ID + ", " + DOMAIN_NAME +
133                 " FROM " + DOMAINS_TABLE +
134                 " ORDER BY " + DOMAIN_NAME + " ASC";
135
136         // Return the results as a `Cursor`.  The second argument is `null` because there are no `selectionArgs`.  We can't close the `Cursor` because we need to use it in the parent activity.
137         return domainsDatabase.rawQuery(GET_CURSOR_ORDERED_BY_DOMAIN, null);
138     }
139
140     public Cursor getDomainNameCursorOrderedByDomainExcept(int databaseId) {
141         // Get a readable database handle.
142         SQLiteDatabase domainsDatabase = this.getReadableDatabase();
143
144         // Prepare the SQL statement to select all rows except that with `databaseId`.
145         final String GET_CURSOR_ORDERED_BY_DOMAIN_EXCEPT = "SELECT " + _ID + ", " + DOMAIN_NAME +
146                 " FROM " + DOMAINS_TABLE +
147                 " WHERE " + _ID + " IS NOT " + databaseId +
148                 " ORDER BY " + DOMAIN_NAME + " ASC";
149
150         // Return the results as a `Cursor`.  The second argument is `null` because there are no `selectionArgs`.  We can't close the `Cursor` because we need to use it in the calling activity.
151         return domainsDatabase.rawQuery(GET_CURSOR_ORDERED_BY_DOMAIN_EXCEPT, null);
152     }
153
154     public Cursor getCursorForId(int databaseId) {
155         // Get a readable database handle.
156         SQLiteDatabase domainsDatabase = this.getReadableDatabase();
157
158         // Prepare the SQL statement to get the `Cursor` for `databaseId`.
159         final String GET_CURSOR_FOR_ID = "SELECT * FROM " + DOMAINS_TABLE +
160                 " WHERE " + _ID + " = " + databaseId;
161
162         // Return the results as a `Cursor`.  The second argument is `null` because there are no `selectionArgs`.  We can't close the `Cursor` because we need to use it in the calling activity.
163         return domainsDatabase.rawQuery(GET_CURSOR_FOR_ID, null);
164     }
165
166     public Cursor getCursorForDomainName(String domainName) {
167         // Get a readable database handle.
168         SQLiteDatabase domainsDatabase = this.getReadableDatabase();
169
170         // Prepare the SQL statement to get the `Cursor` for `domainName`.
171         final String GET_CURSOR_FOR_DOMAIN_NAME = "SELECT * FROM " + DOMAINS_TABLE +
172                 " WHERE " + DOMAIN_NAME + " = " + "\"" + domainName + "\"";
173
174         // Return the results as a `Cursor`.  The second argument is `null` because there are no `selectionArgs`.  We can't close the `Cursor` because we need to us it in the calling activity.
175         return domainsDatabase.rawQuery(GET_CURSOR_FOR_DOMAIN_NAME, null);
176     }
177
178     public int addDomain(String domainName) {
179         // Store the domain data in a `ContentValues`.
180         ContentValues domainContentValues = new ContentValues();
181
182         // Create entries for the database fields.  The ID is created automatically.  The pinned SSL certificate information is not created unless added by the user.
183         domainContentValues.put(DOMAIN_NAME, domainName);
184         domainContentValues.put(ENABLE_JAVASCRIPT, false);
185         domainContentValues.put(ENABLE_FIRST_PARTY_COOKIES, false);
186         domainContentValues.put(ENABLE_THIRD_PARTY_COOKIES, false);
187         domainContentValues.put(ENABLE_DOM_STORAGE, false);
188         domainContentValues.put(ENABLE_FORM_DATA, false);
189         domainContentValues.put(USER_AGENT, "System default user agent");
190         domainContentValues.put(FONT_SIZE, 0);
191         domainContentValues.put(DISPLAY_IMAGES, 0);
192         domainContentValues.put(NIGHT_MODE, 0);
193
194         // Get a writable database handle.
195         SQLiteDatabase domainsDatabase = this.getWritableDatabase();
196
197         // Insert a new row and store the resulting database ID.  The second argument is `null`, which makes it so that a completely null row cannot be created.
198         int newDomainDatabaseId  = (int) domainsDatabase.insert(DOMAINS_TABLE, null, domainContentValues);
199
200         // Close the database handle.
201         domainsDatabase.close();
202
203         // Return the new domain database ID.
204         return newDomainDatabaseId;
205     }
206
207     public void updateDomainExceptCertificate(int databaseId, String domainName, boolean javaScriptEnabled, boolean firstPartyCookiesEnabled, boolean thirdPartyCookiesEnabled, boolean domStorageEnabled, boolean formDataEnabled, String userAgent, int fontSize,
208                                               int displayImages, int nightMode, boolean pinnedSslCertificate) {
209         // Store the domain data in a `ContentValues`.
210         ContentValues domainContentValues = new ContentValues();
211
212         // Add entries for each field in the database.
213         domainContentValues.put(DOMAIN_NAME, domainName);
214         domainContentValues.put(ENABLE_JAVASCRIPT, javaScriptEnabled);
215         domainContentValues.put(ENABLE_FIRST_PARTY_COOKIES, firstPartyCookiesEnabled);
216         domainContentValues.put(ENABLE_THIRD_PARTY_COOKIES, thirdPartyCookiesEnabled);
217         domainContentValues.put(ENABLE_DOM_STORAGE, domStorageEnabled);
218         domainContentValues.put(ENABLE_FORM_DATA, formDataEnabled);
219         domainContentValues.put(USER_AGENT, userAgent);
220         domainContentValues.put(FONT_SIZE, fontSize);
221         domainContentValues.put(DISPLAY_IMAGES, displayImages);
222         domainContentValues.put(NIGHT_MODE, nightMode);
223         domainContentValues.put(PINNED_SSL_CERTIFICATE, pinnedSslCertificate);
224
225         // Get a writable database handle.
226         SQLiteDatabase domainsDatabase = this.getWritableDatabase();
227
228         // Update the row for `databaseId`.  The last argument is `null` because there are no `whereArgs`.
229         domainsDatabase.update(DOMAINS_TABLE, domainContentValues, _ID + " = " + databaseId, null);
230
231         // Close the database handle.
232         domainsDatabase.close();
233     }
234
235     public void updateDomainWithCertificate(int databaseId, String domainName, boolean javaScriptEnabled, boolean firstPartyCookiesEnabled, boolean thirdPartyCookiesEnabled, boolean domStorageEnabled, boolean formDataEnabled, String userAgent, int fontSize,
236                                             int displayImages, int nightMode, boolean pinnedSslCertificate, String sslIssuedToCommonName, String sslIssuedToOrganization, String sslIssuedToOrganizationalUnit, String sslIssuedByCommonName, String sslIssuedByOrganization,
237                                             String sslIssuedByOrganizationalUnit, long sslStartDate, long sslEndDate) {
238         // Store the domain data in a `ContentValues`.
239         ContentValues domainContentValues = new ContentValues();
240
241         // Add entries for each field in the database.
242         domainContentValues.put(DOMAIN_NAME, domainName);
243         domainContentValues.put(ENABLE_JAVASCRIPT, javaScriptEnabled);
244         domainContentValues.put(ENABLE_FIRST_PARTY_COOKIES, firstPartyCookiesEnabled);
245         domainContentValues.put(ENABLE_THIRD_PARTY_COOKIES, thirdPartyCookiesEnabled);
246         domainContentValues.put(ENABLE_DOM_STORAGE, domStorageEnabled);
247         domainContentValues.put(ENABLE_FORM_DATA, formDataEnabled);
248         domainContentValues.put(USER_AGENT, userAgent);
249         domainContentValues.put(FONT_SIZE, fontSize);
250         domainContentValues.put(DISPLAY_IMAGES, displayImages);
251         domainContentValues.put(NIGHT_MODE, nightMode);
252         domainContentValues.put(PINNED_SSL_CERTIFICATE, pinnedSslCertificate);
253         domainContentValues.put(SSL_ISSUED_TO_COMMON_NAME, sslIssuedToCommonName);
254         domainContentValues.put(SSL_ISSUED_TO_ORGANIZATION, sslIssuedToOrganization);
255         domainContentValues.put(SSL_ISSUED_TO_ORGANIZATIONAL_UNIT, sslIssuedToOrganizationalUnit);
256         domainContentValues.put(SSL_ISSUED_BY_COMMON_NAME, sslIssuedByCommonName);
257         domainContentValues.put(SSL_ISSUED_BY_ORGANIZATION, sslIssuedByOrganization);
258         domainContentValues.put(SSL_ISSUED_BY_ORGANIZATIONAL_UNIT, sslIssuedByOrganizationalUnit);
259         domainContentValues.put(SSL_START_DATE, sslStartDate);
260         domainContentValues.put(SSL_END_DATE, sslEndDate);
261
262         // Get a writable database handle.
263         SQLiteDatabase domainsDatabase = this.getWritableDatabase();
264
265         // Update the row for `databaseId`.  The last argument is `null` because there are no `whereArgs`.
266         domainsDatabase.update(DOMAINS_TABLE, domainContentValues, _ID + " = " + databaseId, null);
267
268         // Close the database handle.
269         domainsDatabase.close();
270     }
271
272     public void updateCertificate(int databaseId, String sslIssuedToCommonName, String sslIssuedToOrganization, String sslIssuedToOrganizationalUnit, String sslIssuedByCommonName, String sslIssuedByOrganization, String sslIssuedByOrganizationalUnit,
273                                   long sslStartDate, long sslEndDate) {
274         // Store the domain data in a `ContentValues`.
275         ContentValues domainContentValues = new ContentValues();
276
277         // Add entries for each field in the certificate.
278         domainContentValues.put(SSL_ISSUED_TO_COMMON_NAME, sslIssuedToCommonName);
279         domainContentValues.put(SSL_ISSUED_TO_ORGANIZATION, sslIssuedToOrganization);
280         domainContentValues.put(SSL_ISSUED_TO_ORGANIZATIONAL_UNIT, sslIssuedToOrganizationalUnit);
281         domainContentValues.put(SSL_ISSUED_BY_COMMON_NAME, sslIssuedByCommonName);
282         domainContentValues.put(SSL_ISSUED_BY_ORGANIZATION, sslIssuedByOrganization);
283         domainContentValues.put(SSL_ISSUED_BY_ORGANIZATIONAL_UNIT, sslIssuedByOrganizationalUnit);
284         domainContentValues.put(SSL_START_DATE, sslStartDate);
285         domainContentValues.put(SSL_END_DATE, sslEndDate);
286
287         // Get a writable database handle.
288         SQLiteDatabase domainsDatabase = this.getWritableDatabase();
289
290         // Update the row for `databaseId`.  The last argument is `null` because there are no `whereArgs`.
291         domainsDatabase.update(DOMAINS_TABLE, domainContentValues, _ID + " = " + databaseId, null);
292
293         // Close the database handle.
294         domainsDatabase.close();
295     }
296
297     public void deleteDomain(int databaseId) {
298         // Get a writable database handle.
299         SQLiteDatabase domainsDatabase = this.getWritableDatabase();
300
301         // Delete the row for `databaseId`.  The last argument is `null` because we don't need additional parameters.
302         domainsDatabase.delete(DOMAINS_TABLE, _ID + " = " + databaseId, null);
303
304         // Close the database handle.
305         domainsDatabase.close();
306     }
307 }