2014-02-28 17:46:01 +00:00
package eu.siacs.conversations.persistance ;
2014-01-24 22:58:51 +00:00
2015-06-25 14:56:34 +00:00
import android.content.ContentValues ;
import android.content.Context ;
import android.database.Cursor ;
2015-07-20 12:56:41 +00:00
import android.database.DatabaseUtils ;
2015-06-25 14:56:34 +00:00
import android.database.sqlite.SQLiteCantOpenDatabaseException ;
import android.database.sqlite.SQLiteDatabase ;
import android.database.sqlite.SQLiteOpenHelper ;
import android.util.Base64 ;
import android.util.Log ;
2015-12-11 12:52:04 +00:00
import android.util.Pair ;
2015-06-25 14:56:34 +00:00
2016-09-16 09:07:52 +00:00
import org.json.JSONObject ;
2015-06-25 14:56:34 +00:00
import org.whispersystems.libaxolotl.AxolotlAddress ;
2015-06-29 11:53:39 +00:00
import org.whispersystems.libaxolotl.IdentityKey ;
import org.whispersystems.libaxolotl.IdentityKeyPair ;
import org.whispersystems.libaxolotl.InvalidKeyException ;
2015-06-25 14:56:34 +00:00
import org.whispersystems.libaxolotl.state.PreKeyRecord ;
import org.whispersystems.libaxolotl.state.SessionRecord ;
import org.whispersystems.libaxolotl.state.SignedPreKeyRecord ;
2015-12-23 18:18:53 +00:00
import java.io.ByteArrayInputStream ;
2015-05-29 09:17:26 +00:00
import java.io.IOException ;
2015-12-23 16:41:26 +00:00
import java.security.cert.CertificateEncodingException ;
2015-12-23 18:18:53 +00:00
import java.security.cert.CertificateException ;
import java.security.cert.CertificateFactory ;
2015-12-23 16:41:26 +00:00
import java.security.cert.X509Certificate ;
2014-01-24 22:58:51 +00:00
import java.util.ArrayList ;
2015-06-29 11:53:39 +00:00
import java.util.HashSet ;
2015-09-20 21:17:32 +00:00
import java.util.Iterator ;
2014-01-24 22:58:51 +00:00
import java.util.List ;
2015-06-29 11:53:39 +00:00
import java.util.Set ;
2014-03-11 16:47:05 +00:00
import java.util.concurrent.CopyOnWriteArrayList ;
2016-01-13 02:53:38 +00:00
import org.json.JSONException ;
2014-01-24 22:58:51 +00:00
2015-05-14 13:25:52 +00:00
import eu.siacs.conversations.Config ;
2015-05-29 09:17:26 +00:00
import eu.siacs.conversations.crypto.axolotl.AxolotlService ;
2015-07-28 20:00:54 +00:00
import eu.siacs.conversations.crypto.axolotl.SQLiteAxolotlStore ;
2015-08-01 16:27:52 +00:00
import eu.siacs.conversations.crypto.axolotl.XmppAxolotlSession ;
2014-02-28 17:46:01 +00:00
import eu.siacs.conversations.entities.Account ;
import eu.siacs.conversations.entities.Contact ;
import eu.siacs.conversations.entities.Conversation ;
import eu.siacs.conversations.entities.Message ;
2016-04-22 19:25:06 +00:00
import eu.siacs.conversations.entities.PresenceTemplate ;
2014-05-19 13:15:09 +00:00
import eu.siacs.conversations.entities.Roster ;
2016-01-13 02:53:38 +00:00
import eu.siacs.conversations.entities.ServiceDiscoveryResult ;
2016-09-16 09:07:52 +00:00
import eu.siacs.conversations.generator.AbstractGenerator ;
2015-05-14 13:25:52 +00:00
import eu.siacs.conversations.xmpp.jid.InvalidJidException ;
2014-11-05 20:55:47 +00:00
import eu.siacs.conversations.xmpp.jid.Jid ;
2014-01-24 22:58:51 +00:00
public class DatabaseBackend extends SQLiteOpenHelper {
2014-01-26 02:27:55 +00:00
2014-01-24 22:58:51 +00:00
private static DatabaseBackend instance = null ;
2014-01-26 02:27:55 +00:00
2014-01-24 22:58:51 +00:00
private static final String DATABASE_NAME = " history " ;
2016-10-26 10:26:04 +00:00
private static final int DATABASE_VERSION = 29 ;
2014-05-19 13:15:09 +00:00
private static String CREATE_CONTATCS_STATEMENT = " create table "
2014-07-29 12:42:17 +00:00
+ Contact . TABLENAME + " ( " + Contact . ACCOUNT + " TEXT, "
+ Contact . SERVERNAME + " TEXT, " + Contact . SYSTEMNAME + " TEXT, "
+ Contact . JID + " TEXT, " + Contact . KEYS + " TEXT, "
+ Contact . PHOTOURI + " TEXT, " + Contact . OPTIONS + " NUMBER, "
2014-08-24 18:53:13 +00:00
+ Contact . SYSTEMACCOUNT + " NUMBER, " + Contact . AVATAR + " TEXT, "
2015-06-26 13:41:02 +00:00
+ Contact . LAST_PRESENCE + " TEXT, " + Contact . LAST_TIME + " NUMBER, "
2014-11-16 16:21:21 +00:00
+ Contact . GROUPS + " TEXT, FOREIGN KEY( " + Contact . ACCOUNT + " ) REFERENCES "
2014-08-24 18:53:13 +00:00
+ Account . TABLENAME + " ( " + Account . UUID
+ " ) ON DELETE CASCADE, UNIQUE( " + Contact . ACCOUNT + " , "
+ Contact . JID + " ) ON CONFLICT REPLACE); " ;
2014-01-24 22:58:51 +00:00
2016-01-13 02:53:38 +00:00
private static String CREATE_DISCOVERY_RESULTS_STATEMENT = " create table "
+ ServiceDiscoveryResult . TABLENAME + " ( "
+ ServiceDiscoveryResult . HASH + " TEXT, "
+ ServiceDiscoveryResult . VER + " TEXT, "
+ ServiceDiscoveryResult . RESULT + " TEXT, "
+ " UNIQUE( " + ServiceDiscoveryResult . HASH + " , "
+ ServiceDiscoveryResult . VER + " ) ON CONFLICT REPLACE); " ;
2016-04-22 19:25:06 +00:00
private static String CREATE_PRESENCE_TEMPLATES_STATEMENT = " CREATE TABLE "
+ PresenceTemplate . TABELNAME + " ( "
+ PresenceTemplate . UUID + " TEXT, "
+ PresenceTemplate . LAST_USED + " NUMBER, "
+ PresenceTemplate . MESSAGE + " TEXT, "
+ PresenceTemplate . STATUS + " TEXT, "
+ " UNIQUE( " + PresenceTemplate . MESSAGE + " , " + PresenceTemplate . STATUS + " ) ON CONFLICT REPLACE); " ;
2015-05-29 09:17:26 +00:00
private static String CREATE_PREKEYS_STATEMENT = " CREATE TABLE "
2015-07-28 20:00:54 +00:00
+ SQLiteAxolotlStore . PREKEY_TABLENAME + " ( "
2015-11-28 19:11:38 +00:00
+ SQLiteAxolotlStore . ACCOUNT + " TEXT, "
+ SQLiteAxolotlStore . ID + " INTEGER, "
+ SQLiteAxolotlStore . KEY + " TEXT, FOREIGN KEY( "
+ SQLiteAxolotlStore . ACCOUNT
+ " ) REFERENCES " + Account . TABLENAME + " ( " + Account . UUID + " ) ON DELETE CASCADE, "
+ " UNIQUE( " + SQLiteAxolotlStore . ACCOUNT + " , "
+ SQLiteAxolotlStore . ID
+ " ) ON CONFLICT REPLACE "
+ " ); " ;
2015-05-29 09:17:26 +00:00
private static String CREATE_SIGNED_PREKEYS_STATEMENT = " CREATE TABLE "
2015-07-28 20:00:54 +00:00
+ SQLiteAxolotlStore . SIGNED_PREKEY_TABLENAME + " ( "
2015-11-28 19:11:38 +00:00
+ SQLiteAxolotlStore . ACCOUNT + " TEXT, "
+ SQLiteAxolotlStore . ID + " INTEGER, "
+ SQLiteAxolotlStore . KEY + " TEXT, FOREIGN KEY( "
+ SQLiteAxolotlStore . ACCOUNT
+ " ) REFERENCES " + Account . TABLENAME + " ( " + Account . UUID + " ) ON DELETE CASCADE, "
+ " UNIQUE( " + SQLiteAxolotlStore . ACCOUNT + " , "
+ SQLiteAxolotlStore . ID
+ " ) ON CONFLICT REPLACE " +
2015-05-29 09:17:26 +00:00
" ); " ;
private static String CREATE_SESSIONS_STATEMENT = " CREATE TABLE "
2015-07-28 20:00:54 +00:00
+ SQLiteAxolotlStore . SESSION_TABLENAME + " ( "
2015-11-28 19:11:38 +00:00
+ SQLiteAxolotlStore . ACCOUNT + " TEXT, "
+ SQLiteAxolotlStore . NAME + " TEXT, "
+ SQLiteAxolotlStore . DEVICE_ID + " INTEGER, "
+ SQLiteAxolotlStore . KEY + " TEXT, FOREIGN KEY( "
+ SQLiteAxolotlStore . ACCOUNT
+ " ) REFERENCES " + Account . TABLENAME + " ( " + Account . UUID + " ) ON DELETE CASCADE, "
+ " UNIQUE( " + SQLiteAxolotlStore . ACCOUNT + " , "
+ SQLiteAxolotlStore . NAME + " , "
+ SQLiteAxolotlStore . DEVICE_ID
+ " ) ON CONFLICT REPLACE "
+ " ); " ;
2015-05-29 09:17:26 +00:00
2015-06-29 11:53:39 +00:00
private static String CREATE_IDENTITIES_STATEMENT = " CREATE TABLE "
2015-07-28 20:00:54 +00:00
+ SQLiteAxolotlStore . IDENTITIES_TABLENAME + " ( "
+ SQLiteAxolotlStore . ACCOUNT + " TEXT, "
+ SQLiteAxolotlStore . NAME + " TEXT, "
+ SQLiteAxolotlStore . OWN + " INTEGER, "
+ SQLiteAxolotlStore . FINGERPRINT + " TEXT, "
2015-12-23 16:41:26 +00:00
+ SQLiteAxolotlStore . CERTIFICATE + " BLOB, "
2015-07-28 20:00:54 +00:00
+ SQLiteAxolotlStore . TRUSTED + " INTEGER, "
+ SQLiteAxolotlStore . KEY + " TEXT, FOREIGN KEY( "
+ SQLiteAxolotlStore . ACCOUNT
2015-07-10 00:24:33 +00:00
+ " ) REFERENCES " + Account . TABLENAME + " ( " + Account . UUID + " ) ON DELETE CASCADE, "
2015-07-28 20:00:54 +00:00
+ " UNIQUE( " + SQLiteAxolotlStore . ACCOUNT + " , "
2015-11-28 19:11:38 +00:00
+ SQLiteAxolotlStore . NAME + " , "
+ SQLiteAxolotlStore . FINGERPRINT
2015-07-10 00:24:33 +00:00
+ " ) ON CONFLICT IGNORE "
2015-11-28 19:11:38 +00:00
+ " ); " ;
2015-06-29 11:53:39 +00:00
2014-09-19 15:21:33 +00:00
private DatabaseBackend ( Context context ) {
2014-01-24 22:58:51 +00:00
super ( context , DATABASE_NAME , null , DATABASE_VERSION ) ;
}
@Override
public void onCreate ( SQLiteDatabase db ) {
2014-01-28 23:15:38 +00:00
db . execSQL ( " PRAGMA foreign_keys=ON; " ) ;
2016-04-25 09:06:17 +00:00
db . execSQL ( " create table " + Account . TABLENAME + " ( " + Account . UUID + " TEXT PRIMARY KEY, "
+ Account . USERNAME + " TEXT, "
+ Account . SERVER + " TEXT, "
+ Account . PASSWORD + " TEXT, "
2015-10-29 12:41:08 +00:00
+ Account . DISPLAY_NAME + " TEXT, "
2016-04-25 09:06:17 +00:00
+ Account . STATUS + " TEXT, "
+ Account . STATUS_MESSAGE + " TEXT, "
+ Account . ROSTERVERSION + " TEXT, "
+ Account . OPTIONS + " NUMBER, "
+ Account . AVATAR + " TEXT, "
+ Account . KEYS + " TEXT, "
+ Account . HOSTNAME + " TEXT, "
+ Account . PORT + " NUMBER DEFAULT 5222) " ) ;
2014-01-26 02:27:55 +00:00
db . execSQL ( " create table " + Conversation . TABLENAME + " ( "
2014-01-27 19:40:42 +00:00
+ Conversation . UUID + " TEXT PRIMARY KEY, " + Conversation . NAME
2014-02-10 14:24:34 +00:00
+ " TEXT, " + Conversation . CONTACT + " TEXT, "
+ Conversation . ACCOUNT + " TEXT, " + Conversation . CONTACTJID
2014-01-27 19:40:42 +00:00
+ " TEXT, " + Conversation . CREATED + " NUMBER, "
2014-09-27 16:16:31 +00:00
+ Conversation . STATUS + " NUMBER, " + Conversation . MODE
2014-09-28 13:21:56 +00:00
+ " NUMBER, " + Conversation . ATTRIBUTES + " TEXT, FOREIGN KEY( "
+ Conversation . ACCOUNT + " ) REFERENCES " + Account . TABLENAME
+ " ( " + Account . UUID + " ) ON DELETE CASCADE); " ) ;
2014-01-27 19:40:42 +00:00
db . execSQL ( " create table " + Message . TABLENAME + " ( " + Message . UUID
2014-01-28 23:15:38 +00:00
+ " TEXT PRIMARY KEY, " + Message . CONVERSATION + " TEXT, "
+ Message . TIME_SENT + " NUMBER, " + Message . COUNTERPART
2014-07-29 12:42:17 +00:00
+ " TEXT, " + Message . TRUE_COUNTERPART + " TEXT, "
+ Message . BODY + " TEXT, " + Message . ENCRYPTION + " NUMBER, "
2014-08-24 18:53:13 +00:00
+ Message . STATUS + " NUMBER, " + Message . TYPE + " NUMBER, "
2014-11-13 20:04:05 +00:00
+ Message . RELATIVE_FILE_PATH + " TEXT, "
2014-12-09 20:41:49 +00:00
+ Message . SERVER_MSG_ID + " TEXT, "
2015-07-09 12:23:17 +00:00
+ Message . FINGERPRINT + " TEXT, "
2015-07-31 11:08:35 +00:00
+ Message . CARBON + " INTEGER, "
2016-02-15 22:15:04 +00:00
+ Message . EDITED + " TEXT, "
2015-10-14 19:18:34 +00:00
+ Message . READ + " NUMBER DEFAULT 1, "
2016-03-04 19:09:21 +00:00
+ Message . OOB + " INTEGER, "
2016-10-26 10:26:04 +00:00
+ Message . ERROR_MESSAGE + " TEXT, "
2014-08-24 18:53:13 +00:00
+ Message . REMOTE_MSG_ID + " TEXT, FOREIGN KEY( "
+ Message . CONVERSATION + " ) REFERENCES "
+ Conversation . TABLENAME + " ( " + Conversation . UUID
+ " ) ON DELETE CASCADE); " ) ;
2014-05-19 13:15:09 +00:00
db . execSQL ( CREATE_CONTATCS_STATEMENT ) ;
2016-01-13 02:53:38 +00:00
db . execSQL ( CREATE_DISCOVERY_RESULTS_STATEMENT ) ;
2015-06-29 11:40:56 +00:00
db . execSQL ( CREATE_SESSIONS_STATEMENT ) ;
db . execSQL ( CREATE_PREKEYS_STATEMENT ) ;
db . execSQL ( CREATE_SIGNED_PREKEYS_STATEMENT ) ;
2015-06-29 11:53:39 +00:00
db . execSQL ( CREATE_IDENTITIES_STATEMENT ) ;
2016-04-22 19:25:06 +00:00
db . execSQL ( CREATE_PRESENCE_TEMPLATES_STATEMENT ) ;
2014-01-24 22:58:51 +00:00
}
@Override
2014-04-03 20:28:37 +00:00
public void onUpgrade ( SQLiteDatabase db , int oldVersion , int newVersion ) {
if ( oldVersion < 2 & & newVersion > = 2 ) {
2014-05-19 13:15:09 +00:00
db . execSQL ( " update " + Account . TABLENAME + " set "
+ Account . OPTIONS + " = " + Account . OPTIONS + " | 8 " ) ;
2014-04-03 20:28:37 +00:00
}
2014-04-06 13:34:08 +00:00
if ( oldVersion < 3 & & newVersion > = 3 ) {
2014-05-19 13:15:09 +00:00
db . execSQL ( " ALTER TABLE " + Message . TABLENAME + " ADD COLUMN "
+ Message . TYPE + " NUMBER " ) ;
}
if ( oldVersion < 5 & & newVersion > = 5 ) {
2014-07-29 12:42:17 +00:00
db . execSQL ( " DROP TABLE " + Contact . TABLENAME ) ;
2014-05-19 13:15:09 +00:00
db . execSQL ( CREATE_CONTATCS_STATEMENT ) ;
2014-07-29 12:42:17 +00:00
db . execSQL ( " UPDATE " + Account . TABLENAME + " SET "
+ Account . ROSTERVERSION + " = NULL " ) ;
}
if ( oldVersion < 6 & & newVersion > = 6 ) {
db . execSQL ( " ALTER TABLE " + Message . TABLENAME + " ADD COLUMN "
+ Message . TRUE_COUNTERPART + " TEXT " ) ;
2014-04-06 13:34:08 +00:00
}
2014-08-21 10:32:50 +00:00
if ( oldVersion < 7 & & newVersion > = 7 ) {
db . execSQL ( " ALTER TABLE " + Message . TABLENAME + " ADD COLUMN "
+ Message . REMOTE_MSG_ID + " TEXT " ) ;
db . execSQL ( " ALTER TABLE " + Contact . TABLENAME + " ADD COLUMN "
+ Contact . AVATAR + " TEXT " ) ;
db . execSQL ( " ALTER TABLE " + Account . TABLENAME + " ADD COLUMN "
+ Account . AVATAR + " TEXT " ) ;
}
2014-09-27 16:16:31 +00:00
if ( oldVersion < 8 & & newVersion > = 8 ) {
db . execSQL ( " ALTER TABLE " + Conversation . TABLENAME + " ADD COLUMN "
+ Conversation . ATTRIBUTES + " TEXT " ) ;
}
2015-06-26 13:41:02 +00:00
if ( oldVersion < 9 & & newVersion > = 9 ) {
db . execSQL ( " ALTER TABLE " + Contact . TABLENAME + " ADD COLUMN "
+ Contact . LAST_TIME + " NUMBER " ) ;
db . execSQL ( " ALTER TABLE " + Contact . TABLENAME + " ADD COLUMN "
+ Contact . LAST_PRESENCE + " TEXT " ) ;
}
2014-11-13 20:04:05 +00:00
if ( oldVersion < 10 & & newVersion > = 10 ) {
db . execSQL ( " ALTER TABLE " + Message . TABLENAME + " ADD COLUMN "
+ Message . RELATIVE_FILE_PATH + " TEXT " ) ;
}
2014-11-16 16:21:21 +00:00
if ( oldVersion < 11 & & newVersion > = 11 ) {
db . execSQL ( " ALTER TABLE " + Contact . TABLENAME + " ADD COLUMN "
+ Contact . GROUPS + " TEXT " ) ;
2015-11-28 19:11:38 +00:00
db . execSQL ( " delete from " + Contact . TABLENAME ) ;
db . execSQL ( " update " + Account . TABLENAME + " set " + Account . ROSTERVERSION + " = NULL " ) ;
2014-11-16 16:21:21 +00:00
}
2014-12-09 20:41:49 +00:00
if ( oldVersion < 12 & & newVersion > = 12 ) {
db . execSQL ( " ALTER TABLE " + Message . TABLENAME + " ADD COLUMN "
+ Message . SERVER_MSG_ID + " TEXT " ) ;
}
2015-01-02 00:21:14 +00:00
if ( oldVersion < 13 & & newVersion > = 13 ) {
2015-11-28 19:11:38 +00:00
db . execSQL ( " delete from " + Contact . TABLENAME ) ;
db . execSQL ( " update " + Account . TABLENAME + " set " + Account . ROSTERVERSION + " = NULL " ) ;
2015-01-02 00:21:14 +00:00
}
2015-05-14 13:25:52 +00:00
if ( oldVersion < 14 & & newVersion > = 14 ) {
2016-09-12 20:48:51 +00:00
canonicalizeJids ( db ) ;
2015-05-14 13:25:52 +00:00
}
2015-11-28 19:11:38 +00:00
if ( oldVersion < 15 & & newVersion > = 15 ) {
2015-07-20 11:15:49 +00:00
recreateAxolotlDb ( db ) ;
2015-07-09 12:23:17 +00:00
db . execSQL ( " ALTER TABLE " + Message . TABLENAME + " ADD COLUMN "
+ Message . FINGERPRINT + " TEXT " ) ;
2016-04-25 09:06:17 +00:00
} else if ( oldVersion < 22 & & newVersion > = 22 ) {
db . execSQL ( " ALTER TABLE " + SQLiteAxolotlStore . IDENTITIES_TABLENAME + " ADD COLUMN " + SQLiteAxolotlStore . CERTIFICATE ) ;
2015-06-25 14:56:34 +00:00
}
2015-07-29 14:41:58 +00:00
if ( oldVersion < 16 & & newVersion > = 16 ) {
db . execSQL ( " ALTER TABLE " + Message . TABLENAME + " ADD COLUMN "
+ Message . CARBON + " INTEGER " ) ;
}
2015-11-06 13:50:55 +00:00
if ( oldVersion < 19 & & newVersion > = 19 ) {
2015-11-28 19:11:38 +00:00
db . execSQL ( " ALTER TABLE " + Account . TABLENAME + " ADD COLUMN " + Account . DISPLAY_NAME + " TEXT " ) ;
}
if ( oldVersion < 20 & & newVersion > = 20 ) {
db . execSQL ( " ALTER TABLE " + Account . TABLENAME + " ADD COLUMN " + Account . HOSTNAME + " TEXT " ) ;
db . execSQL ( " ALTER TABLE " + Account . TABLENAME + " ADD COLUMN " + Account . PORT + " NUMBER DEFAULT 5222 " ) ;
2015-11-06 13:50:55 +00:00
}
2016-04-22 19:25:06 +00:00
if ( oldVersion < 26 & & newVersion > = 26 ) {
db . execSQL ( " ALTER TABLE " + Account . TABLENAME + " ADD COLUMN " + Account . STATUS + " TEXT " ) ;
db . execSQL ( " ALTER TABLE " + Account . TABLENAME + " ADD COLUMN " + Account . STATUS_MESSAGE + " TEXT " ) ;
}
2015-11-06 13:50:55 +00:00
/ * Any migrations that alter the Account table need to happen BEFORE this migration , as it
* depends on account de - serialization .
* /
2015-09-05 15:25:46 +00:00
if ( oldVersion < 17 & & newVersion > = 17 ) {
List < Account > accounts = getAccounts ( db ) ;
for ( Account account : accounts ) {
String ownDeviceIdString = account . getKey ( SQLiteAxolotlStore . JSONKEY_REGISTRATION_ID ) ;
2015-11-28 19:11:38 +00:00
if ( ownDeviceIdString = = null ) {
2015-09-05 15:25:46 +00:00
continue ;
}
int ownDeviceId = Integer . valueOf ( ownDeviceIdString ) ;
2016-10-20 15:31:46 +00:00
AxolotlAddress ownAddress = new AxolotlAddress ( account . getJid ( ) . toBareJid ( ) . toPreppedString ( ) , ownDeviceId ) ;
2015-09-05 15:25:46 +00:00
deleteSession ( db , account , ownAddress ) ;
IdentityKeyPair identityKeyPair = loadOwnIdentityKeyPair ( db , account ) ;
2015-09-05 16:47:37 +00:00
if ( identityKeyPair ! = null ) {
setIdentityKeyTrust ( db , account , identityKeyPair . getPublicKey ( ) . getFingerprint ( ) . replaceAll ( " \\ s " , " " ) , XmppAxolotlSession . Trust . TRUSTED ) ;
} else {
2015-11-28 19:11:38 +00:00
Log . d ( Config . LOGTAG , account . getJid ( ) . toBareJid ( ) + " : could not load own identity key pair " ) ;
2015-09-05 16:47:37 +00:00
}
2015-09-05 15:25:46 +00:00
}
}
2015-10-14 19:18:34 +00:00
if ( oldVersion < 18 & & newVersion > = 18 ) {
2015-11-28 19:11:38 +00:00
db . execSQL ( " ALTER TABLE " + Message . TABLENAME + " ADD COLUMN " + Message . READ + " NUMBER DEFAULT 1 " ) ;
2015-10-14 19:18:34 +00:00
}
2015-12-02 15:43:55 +00:00
if ( oldVersion < 21 & & newVersion > = 21 ) {
List < Account > accounts = getAccounts ( db ) ;
for ( Account account : accounts ) {
account . unsetPgpSignature ( ) ;
db . update ( Account . TABLENAME , account . getContentValues ( ) , Account . UUID
+ " =? " , new String [ ] { account . getUuid ( ) } ) ;
}
}
2015-12-23 16:41:26 +00:00
2016-01-13 02:53:38 +00:00
if ( oldVersion < 23 & & newVersion > = 23 ) {
db . execSQL ( CREATE_DISCOVERY_RESULTS_STATEMENT ) ;
}
2016-02-15 22:15:04 +00:00
if ( oldVersion < 24 & & newVersion > = 24 ) {
db . execSQL ( " ALTER TABLE " + Message . TABLENAME + " ADD COLUMN " + Message . EDITED + " TEXT " ) ;
}
2016-03-04 19:09:21 +00:00
if ( oldVersion < 25 & & newVersion > = 25 ) {
db . execSQL ( " ALTER TABLE " + Message . TABLENAME + " ADD COLUMN " + Message . OOB + " INTEGER " ) ;
}
2016-04-22 19:25:06 +00:00
if ( oldVersion < 26 & & newVersion > = 26 ) {
db . execSQL ( CREATE_PRESENCE_TEMPLATES_STATEMENT ) ;
}
2016-05-19 08:41:56 +00:00
if ( oldVersion < 27 & & newVersion > = 27 ) {
db . execSQL ( " DELETE FROM " + ServiceDiscoveryResult . TABLENAME ) ;
}
2016-09-12 20:48:51 +00:00
if ( oldVersion < 28 & & newVersion > = 28 ) {
canonicalizeJids ( db ) ;
}
2016-10-26 10:26:04 +00:00
if ( oldVersion < 29 & & newVersion > = 29 ) {
db . execSQL ( " ALTER TABLE " + Message . TABLENAME + " ADD COLUMN " + Message . ERROR_MESSAGE + " TEXT " ) ;
}
2016-09-12 20:48:51 +00:00
}
private void canonicalizeJids ( SQLiteDatabase db ) {
// migrate db to new, canonicalized JID domainpart representation
// Conversation table
Cursor cursor = db . rawQuery ( " select * from " + Conversation . TABLENAME , new String [ 0 ] ) ;
while ( cursor . moveToNext ( ) ) {
String newJid ;
try {
newJid = Jid . fromString (
cursor . getString ( cursor . getColumnIndex ( Conversation . CONTACTJID ) )
2016-10-20 15:31:46 +00:00
) . toPreppedString ( ) ;
2016-09-12 20:48:51 +00:00
} catch ( InvalidJidException ignored ) {
Log . e ( Config . LOGTAG , " Failed to migrate Conversation CONTACTJID "
+ cursor . getString ( cursor . getColumnIndex ( Conversation . CONTACTJID ) )
+ " : " + ignored + " . Skipping... " ) ;
continue ;
}
String updateArgs [ ] = {
newJid ,
cursor . getString ( cursor . getColumnIndex ( Conversation . UUID ) ) ,
} ;
db . execSQL ( " update " + Conversation . TABLENAME
+ " set " + Conversation . CONTACTJID + " = ? "
+ " where " + Conversation . UUID + " = ? " , updateArgs ) ;
}
cursor . close ( ) ;
// Contact table
cursor = db . rawQuery ( " select * from " + Contact . TABLENAME , new String [ 0 ] ) ;
while ( cursor . moveToNext ( ) ) {
String newJid ;
try {
newJid = Jid . fromString (
cursor . getString ( cursor . getColumnIndex ( Contact . JID ) )
2016-10-20 15:31:46 +00:00
) . toPreppedString ( ) ;
2016-09-12 20:48:51 +00:00
} catch ( InvalidJidException ignored ) {
Log . e ( Config . LOGTAG , " Failed to migrate Contact JID "
+ cursor . getString ( cursor . getColumnIndex ( Contact . JID ) )
+ " : " + ignored + " . Skipping... " ) ;
continue ;
}
String updateArgs [ ] = {
newJid ,
cursor . getString ( cursor . getColumnIndex ( Contact . ACCOUNT ) ) ,
cursor . getString ( cursor . getColumnIndex ( Contact . JID ) ) ,
} ;
db . execSQL ( " update " + Contact . TABLENAME
+ " set " + Contact . JID + " = ? "
+ " where " + Contact . ACCOUNT + " = ? "
+ " AND " + Contact . JID + " = ? " , updateArgs ) ;
}
cursor . close ( ) ;
// Account table
cursor = db . rawQuery ( " select * from " + Account . TABLENAME , new String [ 0 ] ) ;
while ( cursor . moveToNext ( ) ) {
String newServer ;
try {
newServer = Jid . fromParts (
cursor . getString ( cursor . getColumnIndex ( Account . USERNAME ) ) ,
cursor . getString ( cursor . getColumnIndex ( Account . SERVER ) ) ,
" mobile "
) . getDomainpart ( ) ;
} catch ( InvalidJidException ignored ) {
Log . e ( Config . LOGTAG , " Failed to migrate Account SERVER "
+ cursor . getString ( cursor . getColumnIndex ( Account . SERVER ) )
+ " : " + ignored + " . Skipping... " ) ;
continue ;
}
String updateArgs [ ] = {
newServer ,
cursor . getString ( cursor . getColumnIndex ( Account . UUID ) ) ,
} ;
db . execSQL ( " update " + Account . TABLENAME
+ " set " + Account . SERVER + " = ? "
+ " where " + Account . UUID + " = ? " , updateArgs ) ;
}
cursor . close ( ) ;
2014-01-24 22:58:51 +00:00
}
2014-01-26 02:27:55 +00:00
2014-01-24 22:58:51 +00:00
public static synchronized DatabaseBackend getInstance ( Context context ) {
if ( instance = = null ) {
2014-01-25 18:33:12 +00:00
instance = new DatabaseBackend ( context ) ;
2014-01-24 22:58:51 +00:00
}
return instance ;
}
2014-01-26 02:27:55 +00:00
2014-01-27 19:40:42 +00:00
public void createConversation ( Conversation conversation ) {
2014-01-24 22:58:51 +00:00
SQLiteDatabase db = this . getWritableDatabase ( ) ;
2014-01-27 19:40:42 +00:00
db . insert ( Conversation . TABLENAME , null , conversation . getContentValues ( ) ) ;
}
public void createMessage ( Message message ) {
SQLiteDatabase db = this . getWritableDatabase ( ) ;
db . insert ( Message . TABLENAME , null , message . getContentValues ( ) ) ;
2014-01-24 22:58:51 +00:00
}
2014-01-28 23:15:38 +00:00
2014-01-28 18:21:54 +00:00
public void createAccount ( Account account ) {
SQLiteDatabase db = this . getWritableDatabase ( ) ;
2014-01-28 23:15:38 +00:00
db . insert ( Account . TABLENAME , null , account . getContentValues ( ) ) ;
2014-01-28 18:21:54 +00:00
}
2014-05-19 13:15:09 +00:00
2016-01-13 02:53:38 +00:00
public void insertDiscoveryResult ( ServiceDiscoveryResult result ) {
SQLiteDatabase db = this . getWritableDatabase ( ) ;
db . insert ( ServiceDiscoveryResult . TABLENAME , null , result . getContentValues ( ) ) ;
}
public ServiceDiscoveryResult findDiscoveryResult ( final String hash , final String ver ) {
SQLiteDatabase db = this . getReadableDatabase ( ) ;
String [ ] selectionArgs = { hash , ver } ;
Cursor cursor = db . query ( ServiceDiscoveryResult . TABLENAME , null ,
ServiceDiscoveryResult . HASH + " =? AND " + ServiceDiscoveryResult . VER + " =? " ,
selectionArgs , null , null , null ) ;
2016-03-11 08:01:27 +00:00
if ( cursor . getCount ( ) = = 0 ) {
cursor . close ( ) ;
2016-01-13 02:53:38 +00:00
return null ;
2016-03-11 08:01:27 +00:00
}
2016-01-13 02:53:38 +00:00
cursor . moveToFirst ( ) ;
ServiceDiscoveryResult result = null ;
try {
result = new ServiceDiscoveryResult ( cursor ) ;
} catch ( JSONException e ) { /* result is still null */ }
cursor . close ( ) ;
return result ;
}
2016-04-22 19:25:06 +00:00
public void insertPresenceTemplate ( PresenceTemplate template ) {
SQLiteDatabase db = this . getWritableDatabase ( ) ;
db . insert ( PresenceTemplate . TABELNAME , null , template . getContentValues ( ) ) ;
}
public List < PresenceTemplate > getPresenceTemplates ( ) {
ArrayList < PresenceTemplate > templates = new ArrayList < > ( ) ;
SQLiteDatabase db = this . getReadableDatabase ( ) ;
Cursor cursor = db . query ( PresenceTemplate . TABELNAME , null , null , null , null , null , PresenceTemplate . LAST_USED + " desc " ) ;
while ( cursor . moveToNext ( ) ) {
templates . add ( PresenceTemplate . fromCursor ( cursor ) ) ;
}
cursor . close ( ) ;
return templates ;
}
public void deletePresenceTemplate ( PresenceTemplate template ) {
Log . d ( Config . LOGTAG , " deleting presence template with uuid " + template . getUuid ( ) ) ;
SQLiteDatabase db = this . getWritableDatabase ( ) ;
String where = PresenceTemplate . UUID + " =? " ;
String [ ] whereArgs = { template . getUuid ( ) } ;
db . delete ( PresenceTemplate . TABELNAME , where , whereArgs ) ;
}
2014-07-12 10:41:37 +00:00
public CopyOnWriteArrayList < Conversation > getConversations ( int status ) {
2014-11-05 20:55:47 +00:00
CopyOnWriteArrayList < Conversation > list = new CopyOnWriteArrayList < > ( ) ;
2014-01-24 22:58:51 +00:00
SQLiteDatabase db = this . getReadableDatabase ( ) ;
2015-11-28 19:11:38 +00:00
String [ ] selectionArgs = { Integer . toString ( status ) } ;
2014-01-27 19:40:42 +00:00
Cursor cursor = db . rawQuery ( " select * from " + Conversation . TABLENAME
+ " where " + Conversation . STATUS + " = ? order by "
+ Conversation . CREATED + " desc " , selectionArgs ) ;
2014-01-26 02:27:55 +00:00
while ( cursor . moveToNext ( ) ) {
2014-01-24 22:58:51 +00:00
list . add ( Conversation . fromCursor ( cursor ) ) ;
}
2014-11-15 23:34:16 +00:00
cursor . close ( ) ;
2014-01-24 22:58:51 +00:00
return list ;
}
2014-07-29 12:42:17 +00:00
2014-10-20 19:08:33 +00:00
public ArrayList < Message > getMessages ( Conversation conversations , int limit ) {
2014-07-29 12:42:17 +00:00
return getMessages ( conversations , limit , - 1 ) ;
2014-06-14 14:59:07 +00:00
}
2014-01-24 22:58:51 +00:00
2014-10-20 19:08:33 +00:00
public ArrayList < Message > getMessages ( Conversation conversation , int limit ,
2015-11-28 19:11:38 +00:00
long timestamp ) {
2014-11-05 20:55:47 +00:00
ArrayList < Message > list = new ArrayList < > ( ) ;
2014-01-27 19:40:42 +00:00
SQLiteDatabase db = this . getReadableDatabase ( ) ;
2014-06-14 14:59:07 +00:00
Cursor cursor ;
2014-07-29 12:42:17 +00:00
if ( timestamp = = - 1 ) {
2015-11-28 19:11:38 +00:00
String [ ] selectionArgs = { conversation . getUuid ( ) } ;
2014-06-14 14:59:07 +00:00
cursor = db . query ( Message . TABLENAME , null , Message . CONVERSATION
2014-07-29 12:42:17 +00:00
+ " =? " , selectionArgs , null , null , Message . TIME_SENT
+ " DESC " , String . valueOf ( limit ) ) ;
2014-06-14 14:59:07 +00:00
} else {
2015-11-28 19:11:38 +00:00
String [ ] selectionArgs = { conversation . getUuid ( ) ,
Long . toString ( timestamp ) } ;
2014-06-14 14:59:07 +00:00
cursor = db . query ( Message . TABLENAME , null , Message . CONVERSATION
2015-11-28 19:11:38 +00:00
+ " =? and " + Message . TIME_SENT + " <? " , selectionArgs ,
2014-07-29 12:42:17 +00:00
null , null , Message . TIME_SENT + " DESC " ,
2014-06-14 14:59:07 +00:00
String . valueOf ( limit ) ) ;
}
2014-01-28 23:15:38 +00:00
if ( cursor . getCount ( ) > 0 ) {
2014-01-27 19:40:42 +00:00
cursor . moveToLast ( ) ;
do {
2014-10-19 21:13:55 +00:00
Message message = Message . fromCursor ( cursor ) ;
message . setConversation ( conversation ) ;
list . add ( message ) ;
2014-01-27 19:40:42 +00:00
} while ( cursor . moveToPrevious ( ) ) ;
}
2014-11-15 23:34:16 +00:00
cursor . close ( ) ;
2014-01-27 19:40:42 +00:00
return list ;
}
2015-11-28 19:11:38 +00:00
public Iterable < Message > getMessagesIterable ( final Conversation conversation ) {
2015-09-20 21:17:32 +00:00
return new Iterable < Message > ( ) {
@Override
public Iterator < Message > iterator ( ) {
2015-11-28 19:11:38 +00:00
class MessageIterator implements Iterator < Message > {
2015-09-20 21:17:32 +00:00
SQLiteDatabase db = getReadableDatabase ( ) ;
2015-11-28 19:11:38 +00:00
String [ ] selectionArgs = { conversation . getUuid ( ) } ;
2015-09-20 21:17:32 +00:00
Cursor cursor = db . query ( Message . TABLENAME , null , Message . CONVERSATION
+ " =? " , selectionArgs , null , null , Message . TIME_SENT
+ " ASC " , null ) ;
public MessageIterator ( ) {
cursor . moveToFirst ( ) ;
}
@Override
public boolean hasNext ( ) {
return ! cursor . isAfterLast ( ) ;
}
@Override
public Message next ( ) {
Message message = Message . fromCursor ( cursor ) ;
cursor . moveToNext ( ) ;
return message ;
}
@Override
public void remove ( ) {
throw new UnsupportedOperationException ( ) ;
}
}
return new MessageIterator ( ) ;
}
} ;
}
2014-11-05 20:55:47 +00:00
public Conversation findConversation ( final Account account , final Jid contactJid ) {
2014-01-27 19:40:42 +00:00
SQLiteDatabase db = this . getReadableDatabase ( ) ;
2015-11-28 19:11:38 +00:00
String [ ] selectionArgs = { account . getUuid ( ) ,
2016-10-20 15:31:46 +00:00
contactJid . toBareJid ( ) . toPreppedString ( ) + " /% " ,
contactJid . toBareJid ( ) . toPreppedString ( )
2015-11-28 19:11:38 +00:00
} ;
2014-01-28 23:15:38 +00:00
Cursor cursor = db . query ( Conversation . TABLENAME , null ,
2015-01-21 15:18:57 +00:00
Conversation . ACCOUNT + " =? AND ( " + Conversation . CONTACTJID
2015-05-29 09:17:26 +00:00
+ " like ? OR " + Conversation . CONTACTJID + " =?) " , selectionArgs , null , null , null ) ;
2016-03-31 11:55:46 +00:00
if ( cursor . getCount ( ) = = 0 ) {
cursor . close ( ) ;
2014-01-28 23:15:38 +00:00
return null ;
2016-03-31 11:55:46 +00:00
}
2014-01-27 19:40:42 +00:00
cursor . moveToFirst ( ) ;
2014-11-15 23:34:16 +00:00
Conversation conversation = Conversation . fromCursor ( cursor ) ;
cursor . close ( ) ;
return conversation ;
2014-01-27 19:40:42 +00:00
}
2014-12-21 20:43:58 +00:00
public void updateConversation ( final Conversation conversation ) {
final SQLiteDatabase db = this . getWritableDatabase ( ) ;
2015-11-28 19:11:38 +00:00
final String [ ] args = { conversation . getUuid ( ) } ;
2014-01-28 23:15:38 +00:00
db . update ( Conversation . TABLENAME , conversation . getContentValues ( ) ,
Conversation . UUID + " =? " , args ) ;
2014-01-27 19:40:42 +00:00
}
2014-01-28 23:15:38 +00:00
2014-01-28 18:21:54 +00:00
public List < Account > getAccounts ( ) {
SQLiteDatabase db = this . getReadableDatabase ( ) ;
2015-09-05 15:25:46 +00:00
return getAccounts ( db ) ;
}
private List < Account > getAccounts ( SQLiteDatabase db ) {
List < Account > list = new ArrayList < > ( ) ;
2014-01-28 23:15:38 +00:00
Cursor cursor = db . query ( Account . TABLENAME , null , null , null , null ,
null , null ) ;
2014-01-28 18:21:54 +00:00
while ( cursor . moveToNext ( ) ) {
list . add ( Account . fromCursor ( cursor ) ) ;
}
2014-10-08 12:10:37 +00:00
cursor . close ( ) ;
2014-01-28 18:21:54 +00:00
return list ;
}
2016-09-07 12:34:58 +00:00
public boolean updateAccount ( Account account ) {
2014-01-28 18:21:54 +00:00
SQLiteDatabase db = this . getWritableDatabase ( ) ;
2015-11-28 19:11:38 +00:00
String [ ] args = { account . getUuid ( ) } ;
2016-09-07 12:34:58 +00:00
final int rows = db . update ( Account . TABLENAME , account . getContentValues ( ) , Account . UUID + " =? " , args ) ;
return rows = = 1 ;
2014-01-28 18:21:54 +00:00
}
2016-09-07 12:34:58 +00:00
public boolean deleteAccount ( Account account ) {
2014-01-28 18:21:54 +00:00
SQLiteDatabase db = this . getWritableDatabase ( ) ;
2015-11-28 19:11:38 +00:00
String [ ] args = { account . getUuid ( ) } ;
2016-09-07 12:34:58 +00:00
final int rows = db . delete ( Account . TABLENAME , Account . UUID + " =? " , args ) ;
return rows = = 1 ;
2014-01-28 18:21:54 +00:00
}
2014-09-28 13:21:56 +00:00
2014-09-19 15:21:33 +00:00
public boolean hasEnabledAccounts ( ) {
SQLiteDatabase db = this . getReadableDatabase ( ) ;
2014-09-28 13:21:56 +00:00
Cursor cursor = db . rawQuery ( " select count( " + Account . UUID + " ) from "
+ Account . TABLENAME + " where not options & (1 <<1) " , null ) ;
2014-10-14 16:26:45 +00:00
try {
cursor . moveToFirst ( ) ;
int count = cursor . getInt ( 0 ) ;
return ( count > 0 ) ;
} catch ( SQLiteCantOpenDatabaseException e ) {
2014-10-15 17:32:12 +00:00
return true ; // better safe than sorry
2015-02-28 11:03:53 +00:00
} catch ( RuntimeException e ) {
return true ; // better safe than sorry
2016-03-31 11:55:46 +00:00
} finally {
if ( cursor ! = null ) {
cursor . close ( ) ;
}
2014-10-14 16:26:45 +00:00
}
2014-09-19 15:21:33 +00:00
}
2014-01-27 19:40:42 +00:00
2014-01-28 23:15:38 +00:00
@Override
public SQLiteDatabase getWritableDatabase ( ) {
SQLiteDatabase db = super . getWritableDatabase ( ) ;
db . execSQL ( " PRAGMA foreign_keys=ON; " ) ;
return db ;
}
2014-02-02 15:05:15 +00:00
public void updateMessage ( Message message ) {
SQLiteDatabase db = this . getWritableDatabase ( ) ;
2015-11-28 19:11:38 +00:00
String [ ] args = { message . getUuid ( ) } ;
2014-02-02 15:05:15 +00:00
db . update ( Message . TABLENAME , message . getContentValues ( ) , Message . UUID
+ " =? " , args ) ;
}
2014-02-05 21:33:39 +00:00
2016-02-15 22:15:04 +00:00
public void updateMessage ( Message message , String uuid ) {
SQLiteDatabase db = this . getWritableDatabase ( ) ;
String [ ] args = { uuid } ;
db . update ( Message . TABLENAME , message . getContentValues ( ) , Message . UUID
+ " =? " , args ) ;
}
2014-05-19 13:15:09 +00:00
public void readRoster ( Roster roster ) {
2014-02-05 21:33:39 +00:00
SQLiteDatabase db = this . getReadableDatabase ( ) ;
2014-02-10 02:34:00 +00:00
Cursor cursor ;
2015-11-28 19:11:38 +00:00
String args [ ] = { roster . getAccount ( ) . getUuid ( ) } ;
2015-07-03 19:32:46 +00:00
cursor = db . query ( Contact . TABLENAME , null , Contact . ACCOUNT + " =? " , args , null , null , null ) ;
2014-02-05 21:33:39 +00:00
while ( cursor . moveToNext ( ) ) {
2014-05-19 13:15:09 +00:00
roster . initContact ( Contact . fromCursor ( cursor ) ) ;
2014-02-05 21:33:39 +00:00
}
2014-10-08 12:10:37 +00:00
cursor . close ( ) ;
2014-02-05 21:33:39 +00:00
}
2014-07-29 12:42:17 +00:00
2014-11-05 20:55:47 +00:00
public void writeRoster ( final Roster roster ) {
final Account account = roster . getAccount ( ) ;
final SQLiteDatabase db = this . getWritableDatabase ( ) ;
2016-01-13 07:55:46 +00:00
db . beginTransaction ( ) ;
2014-07-29 12:42:17 +00:00
for ( Contact contact : roster . getContacts ( ) ) {
2014-05-19 19:05:17 +00:00
if ( contact . getOption ( Contact . Options . IN_ROSTER ) ) {
db . insert ( Contact . TABLENAME , null , contact . getContentValues ( ) ) ;
} else {
2014-07-29 12:42:17 +00:00
String where = Contact . ACCOUNT + " =? AND " + Contact . JID + " =? " ;
2016-10-20 15:31:46 +00:00
String [ ] whereArgs = { account . getUuid ( ) , contact . getJid ( ) . toPreppedString ( ) } ;
2014-05-19 19:05:17 +00:00
db . delete ( Contact . TABLENAME , where , whereArgs ) ;
}
}
2016-01-13 07:55:46 +00:00
db . setTransactionSuccessful ( ) ;
db . endTransaction ( ) ;
2014-05-19 19:05:17 +00:00
account . setRosterVersion ( roster . getVersion ( ) ) ;
updateAccount ( account ) ;
2014-02-05 21:33:39 +00:00
}
2014-02-11 22:55:03 +00:00
2014-04-20 18:48:16 +00:00
public void deleteMessagesInConversation ( Conversation conversation ) {
SQLiteDatabase db = this . getWritableDatabase ( ) ;
2015-11-28 19:11:38 +00:00
String [ ] args = { conversation . getUuid ( ) } ;
2014-04-20 18:48:16 +00:00
db . delete ( Message . TABLENAME , Message . CONVERSATION + " =? " , args ) ;
}
2014-02-19 00:35:23 +00:00
2015-12-23 18:18:53 +00:00
public Pair < Long , String > getLastMessageReceived ( Account account ) {
2016-03-31 11:55:46 +00:00
Cursor cursor = null ;
2016-01-15 22:46:52 +00:00
try {
SQLiteDatabase db = this . getReadableDatabase ( ) ;
String sql = " select messages.timeSent,messages.serverMsgId from accounts join conversations on accounts.uuid=conversations.accountUuid join messages on conversations.uuid=messages.conversationUuid where accounts.uuid=? and (messages.status=0 or messages.carbon=1 or messages.serverMsgId not null) order by messages.timesent desc limit 1 " ;
String [ ] args = { account . getUuid ( ) } ;
2016-03-31 11:55:46 +00:00
cursor = db . rawQuery ( sql , args ) ;
2016-01-15 22:46:52 +00:00
if ( cursor . getCount ( ) = = 0 ) {
return null ;
} else {
cursor . moveToFirst ( ) ;
return new Pair < > ( cursor . getLong ( 0 ) , cursor . getString ( 1 ) ) ;
}
} catch ( Exception e ) {
2015-12-11 12:52:04 +00:00
return null ;
2016-03-31 11:55:46 +00:00
} finally {
if ( cursor ! = null ) {
cursor . close ( ) ;
}
2015-12-11 12:52:04 +00:00
}
}
2016-09-16 09:07:52 +00:00
public Pair < Long , String > getLastClearDate ( Account account ) {
SQLiteDatabase db = this . getReadableDatabase ( ) ;
String [ ] columns = { Conversation . ATTRIBUTES } ;
String selection = Conversation . ACCOUNT + " =? " ;
String [ ] args = { account . getUuid ( ) } ;
Cursor cursor = db . query ( Conversation . TABLENAME , columns , selection , args , null , null , null ) ;
long maxClearDate = 0 ;
while ( cursor . moveToNext ( ) ) {
try {
final JSONObject jsonObject = new JSONObject ( cursor . getString ( 0 ) ) ;
maxClearDate = Math . max ( maxClearDate , jsonObject . getLong ( Conversation . ATTRIBUTE_LAST_CLEAR_HISTORY ) ) ;
} catch ( Exception e ) {
//ignored
}
}
cursor . close ( ) ;
return new Pair < > ( maxClearDate , null ) ;
}
2015-05-29 09:17:26 +00:00
private Cursor getCursorForSession ( Account account , AxolotlAddress contact ) {
final SQLiteDatabase db = this . getReadableDatabase ( ) ;
String [ ] selectionArgs = { account . getUuid ( ) ,
contact . getName ( ) ,
Integer . toString ( contact . getDeviceId ( ) ) } ;
2016-09-16 09:07:52 +00:00
return db . query ( SQLiteAxolotlStore . SESSION_TABLENAME ,
null ,
2015-07-28 20:00:54 +00:00
SQLiteAxolotlStore . ACCOUNT + " = ? AND "
+ SQLiteAxolotlStore . NAME + " = ? AND "
+ SQLiteAxolotlStore . DEVICE_ID + " = ? " ,
2015-05-29 09:17:26 +00:00
selectionArgs ,
null , null , null ) ;
}
public SessionRecord loadSession ( Account account , AxolotlAddress contact ) {
SessionRecord session = null ;
2015-06-26 13:41:02 +00:00
Cursor cursor = getCursorForSession ( account , contact ) ;
2015-11-28 19:11:38 +00:00
if ( cursor . getCount ( ) ! = 0 ) {
2015-05-29 09:17:26 +00:00
cursor . moveToFirst ( ) ;
try {
2015-11-28 19:11:38 +00:00
session = new SessionRecord ( Base64 . decode ( cursor . getString ( cursor . getColumnIndex ( SQLiteAxolotlStore . KEY ) ) , Base64 . DEFAULT ) ) ;
2015-05-29 09:17:26 +00:00
} catch ( IOException e ) {
2015-06-29 11:40:56 +00:00
cursor . close ( ) ;
2015-05-29 09:17:26 +00:00
throw new AssertionError ( e ) ;
}
2015-06-26 13:41:02 +00:00
}
cursor . close ( ) ;
2015-05-29 09:17:26 +00:00
return session ;
}
public List < Integer > getSubDeviceSessions ( Account account , AxolotlAddress contact ) {
final SQLiteDatabase db = this . getReadableDatabase ( ) ;
2015-09-05 15:25:46 +00:00
return getSubDeviceSessions ( db , account , contact ) ;
}
private List < Integer > getSubDeviceSessions ( SQLiteDatabase db , Account account , AxolotlAddress contact ) {
List < Integer > devices = new ArrayList < > ( ) ;
2015-07-28 20:00:54 +00:00
String [ ] columns = { SQLiteAxolotlStore . DEVICE_ID } ;
2015-05-29 09:17:26 +00:00
String [ ] selectionArgs = { account . getUuid ( ) ,
contact . getName ( ) } ;
2015-07-28 20:00:54 +00:00
Cursor cursor = db . query ( SQLiteAxolotlStore . SESSION_TABLENAME ,
2015-05-29 09:17:26 +00:00
columns ,
2015-07-28 20:00:54 +00:00
SQLiteAxolotlStore . ACCOUNT + " = ? AND "
+ SQLiteAxolotlStore . NAME + " = ? " ,
2015-05-29 09:17:26 +00:00
selectionArgs ,
null , null , null ) ;
2015-11-28 19:11:38 +00:00
while ( cursor . moveToNext ( ) ) {
2015-05-29 09:17:26 +00:00
devices . add ( cursor . getInt (
2015-07-28 20:00:54 +00:00
cursor . getColumnIndex ( SQLiteAxolotlStore . DEVICE_ID ) ) ) ;
2015-05-29 09:17:26 +00:00
}
cursor . close ( ) ;
return devices ;
}
public boolean containsSession ( Account account , AxolotlAddress contact ) {
Cursor cursor = getCursorForSession ( account , contact ) ;
int count = cursor . getCount ( ) ;
cursor . close ( ) ;
return count ! = 0 ;
}
public void storeSession ( Account account , AxolotlAddress contact , SessionRecord session ) {
SQLiteDatabase db = this . getWritableDatabase ( ) ;
ContentValues values = new ContentValues ( ) ;
2015-07-28 20:00:54 +00:00
values . put ( SQLiteAxolotlStore . NAME , contact . getName ( ) ) ;
values . put ( SQLiteAxolotlStore . DEVICE_ID , contact . getDeviceId ( ) ) ;
2015-11-28 19:11:38 +00:00
values . put ( SQLiteAxolotlStore . KEY , Base64 . encodeToString ( session . serialize ( ) , Base64 . DEFAULT ) ) ;
2015-07-28 20:00:54 +00:00
values . put ( SQLiteAxolotlStore . ACCOUNT , account . getUuid ( ) ) ;
db . insert ( SQLiteAxolotlStore . SESSION_TABLENAME , null , values ) ;
2015-05-29 09:17:26 +00:00
}
public void deleteSession ( Account account , AxolotlAddress contact ) {
SQLiteDatabase db = this . getWritableDatabase ( ) ;
2015-09-05 15:25:46 +00:00
deleteSession ( db , account , contact ) ;
}
private void deleteSession ( SQLiteDatabase db , Account account , AxolotlAddress contact ) {
2015-05-29 09:17:26 +00:00
String [ ] args = { account . getUuid ( ) ,
contact . getName ( ) ,
Integer . toString ( contact . getDeviceId ( ) ) } ;
2015-07-28 20:00:54 +00:00
db . delete ( SQLiteAxolotlStore . SESSION_TABLENAME ,
SQLiteAxolotlStore . ACCOUNT + " = ? AND "
+ SQLiteAxolotlStore . NAME + " = ? AND "
+ SQLiteAxolotlStore . DEVICE_ID + " = ? " ,
2015-05-29 09:17:26 +00:00
args ) ;
}
public void deleteAllSessions ( Account account , AxolotlAddress contact ) {
SQLiteDatabase db = this . getWritableDatabase ( ) ;
String [ ] args = { account . getUuid ( ) , contact . getName ( ) } ;
2015-07-28 20:00:54 +00:00
db . delete ( SQLiteAxolotlStore . SESSION_TABLENAME ,
SQLiteAxolotlStore . ACCOUNT + " =? AND "
+ SQLiteAxolotlStore . NAME + " = ? " ,
2015-05-29 09:17:26 +00:00
args ) ;
}
private Cursor getCursorForPreKey ( Account account , int preKeyId ) {
SQLiteDatabase db = this . getReadableDatabase ( ) ;
2015-07-28 20:00:54 +00:00
String [ ] columns = { SQLiteAxolotlStore . KEY } ;
2015-05-29 09:17:26 +00:00
String [ ] selectionArgs = { account . getUuid ( ) , Integer . toString ( preKeyId ) } ;
2015-07-28 20:00:54 +00:00
Cursor cursor = db . query ( SQLiteAxolotlStore . PREKEY_TABLENAME ,
2015-05-29 09:17:26 +00:00
columns ,
2015-07-28 20:00:54 +00:00
SQLiteAxolotlStore . ACCOUNT + " =? AND "
+ SQLiteAxolotlStore . ID + " =? " ,
2015-05-29 09:17:26 +00:00
selectionArgs ,
null , null , null ) ;
return cursor ;
}
public PreKeyRecord loadPreKey ( Account account , int preKeyId ) {
PreKeyRecord record = null ;
Cursor cursor = getCursorForPreKey ( account , preKeyId ) ;
2015-11-28 19:11:38 +00:00
if ( cursor . getCount ( ) ! = 0 ) {
2015-05-29 09:17:26 +00:00
cursor . moveToFirst ( ) ;
try {
2015-11-28 19:11:38 +00:00
record = new PreKeyRecord ( Base64 . decode ( cursor . getString ( cursor . getColumnIndex ( SQLiteAxolotlStore . KEY ) ) , Base64 . DEFAULT ) ) ;
} catch ( IOException e ) {
2015-05-29 09:17:26 +00:00
throw new AssertionError ( e ) ;
}
}
cursor . close ( ) ;
return record ;
}
public boolean containsPreKey ( Account account , int preKeyId ) {
Cursor cursor = getCursorForPreKey ( account , preKeyId ) ;
int count = cursor . getCount ( ) ;
cursor . close ( ) ;
return count ! = 0 ;
}
public void storePreKey ( Account account , PreKeyRecord record ) {
SQLiteDatabase db = this . getWritableDatabase ( ) ;
ContentValues values = new ContentValues ( ) ;
2015-07-28 20:00:54 +00:00
values . put ( SQLiteAxolotlStore . ID , record . getId ( ) ) ;
2015-11-28 19:11:38 +00:00
values . put ( SQLiteAxolotlStore . KEY , Base64 . encodeToString ( record . serialize ( ) , Base64 . DEFAULT ) ) ;
2015-07-28 20:00:54 +00:00
values . put ( SQLiteAxolotlStore . ACCOUNT , account . getUuid ( ) ) ;
db . insert ( SQLiteAxolotlStore . PREKEY_TABLENAME , null , values ) ;
2015-05-29 09:17:26 +00:00
}
public void deletePreKey ( Account account , int preKeyId ) {
SQLiteDatabase db = this . getWritableDatabase ( ) ;
String [ ] args = { account . getUuid ( ) , Integer . toString ( preKeyId ) } ;
2015-07-28 20:00:54 +00:00
db . delete ( SQLiteAxolotlStore . PREKEY_TABLENAME ,
SQLiteAxolotlStore . ACCOUNT + " =? AND "
+ SQLiteAxolotlStore . ID + " =? " ,
2015-05-29 09:17:26 +00:00
args ) ;
}
private Cursor getCursorForSignedPreKey ( Account account , int signedPreKeyId ) {
SQLiteDatabase db = this . getReadableDatabase ( ) ;
2015-07-28 20:00:54 +00:00
String [ ] columns = { SQLiteAxolotlStore . KEY } ;
2015-05-29 09:17:26 +00:00
String [ ] selectionArgs = { account . getUuid ( ) , Integer . toString ( signedPreKeyId ) } ;
2015-07-28 20:00:54 +00:00
Cursor cursor = db . query ( SQLiteAxolotlStore . SIGNED_PREKEY_TABLENAME ,
2015-05-29 09:17:26 +00:00
columns ,
2015-07-28 20:00:54 +00:00
SQLiteAxolotlStore . ACCOUNT + " =? AND " + SQLiteAxolotlStore . ID + " =? " ,
2015-05-29 09:17:26 +00:00
selectionArgs ,
null , null , null ) ;
return cursor ;
}
public SignedPreKeyRecord loadSignedPreKey ( Account account , int signedPreKeyId ) {
SignedPreKeyRecord record = null ;
2015-06-25 14:56:34 +00:00
Cursor cursor = getCursorForSignedPreKey ( account , signedPreKeyId ) ;
2015-11-28 19:11:38 +00:00
if ( cursor . getCount ( ) ! = 0 ) {
2015-05-29 09:17:26 +00:00
cursor . moveToFirst ( ) ;
try {
2015-11-28 19:11:38 +00:00
record = new SignedPreKeyRecord ( Base64 . decode ( cursor . getString ( cursor . getColumnIndex ( SQLiteAxolotlStore . KEY ) ) , Base64 . DEFAULT ) ) ;
} catch ( IOException e ) {
2015-05-29 09:17:26 +00:00
throw new AssertionError ( e ) ;
}
}
cursor . close ( ) ;
return record ;
}
public List < SignedPreKeyRecord > loadSignedPreKeys ( Account account ) {
List < SignedPreKeyRecord > prekeys = new ArrayList < > ( ) ;
SQLiteDatabase db = this . getReadableDatabase ( ) ;
2015-07-28 20:00:54 +00:00
String [ ] columns = { SQLiteAxolotlStore . KEY } ;
2015-05-29 09:17:26 +00:00
String [ ] selectionArgs = { account . getUuid ( ) } ;
2015-07-28 20:00:54 +00:00
Cursor cursor = db . query ( SQLiteAxolotlStore . SIGNED_PREKEY_TABLENAME ,
2015-05-29 09:17:26 +00:00
columns ,
2015-07-28 20:00:54 +00:00
SQLiteAxolotlStore . ACCOUNT + " =? " ,
2015-05-29 09:17:26 +00:00
selectionArgs ,
null , null , null ) ;
2015-11-28 19:11:38 +00:00
while ( cursor . moveToNext ( ) ) {
2015-05-29 09:17:26 +00:00
try {
2015-07-28 20:00:54 +00:00
prekeys . add ( new SignedPreKeyRecord ( Base64 . decode ( cursor . getString ( cursor . getColumnIndex ( SQLiteAxolotlStore . KEY ) ) , Base64 . DEFAULT ) ) ) ;
2015-05-29 09:17:26 +00:00
} catch ( IOException ignored ) {
}
}
2015-06-29 11:40:56 +00:00
cursor . close ( ) ;
2015-05-29 09:17:26 +00:00
return prekeys ;
}
public boolean containsSignedPreKey ( Account account , int signedPreKeyId ) {
Cursor cursor = getCursorForPreKey ( account , signedPreKeyId ) ;
int count = cursor . getCount ( ) ;
cursor . close ( ) ;
return count ! = 0 ;
}
public void storeSignedPreKey ( Account account , SignedPreKeyRecord record ) {
SQLiteDatabase db = this . getWritableDatabase ( ) ;
ContentValues values = new ContentValues ( ) ;
2015-07-28 20:00:54 +00:00
values . put ( SQLiteAxolotlStore . ID , record . getId ( ) ) ;
2015-11-28 19:11:38 +00:00
values . put ( SQLiteAxolotlStore . KEY , Base64 . encodeToString ( record . serialize ( ) , Base64 . DEFAULT ) ) ;
2015-07-28 20:00:54 +00:00
values . put ( SQLiteAxolotlStore . ACCOUNT , account . getUuid ( ) ) ;
db . insert ( SQLiteAxolotlStore . SIGNED_PREKEY_TABLENAME , null , values ) ;
2015-05-29 09:17:26 +00:00
}
public void deleteSignedPreKey ( Account account , int signedPreKeyId ) {
SQLiteDatabase db = this . getWritableDatabase ( ) ;
String [ ] args = { account . getUuid ( ) , Integer . toString ( signedPreKeyId ) } ;
2015-07-28 20:00:54 +00:00
db . delete ( SQLiteAxolotlStore . SIGNED_PREKEY_TABLENAME ,
SQLiteAxolotlStore . ACCOUNT + " =? AND "
+ SQLiteAxolotlStore . ID + " =? " ,
2015-05-29 09:17:26 +00:00
args ) ;
}
2015-06-29 11:53:39 +00:00
private Cursor getIdentityKeyCursor ( Account account , String name , boolean own ) {
2015-09-05 15:25:46 +00:00
final SQLiteDatabase db = this . getReadableDatabase ( ) ;
return getIdentityKeyCursor ( db , account , name , own ) ;
2015-07-09 12:23:17 +00:00
}
2015-09-05 15:25:46 +00:00
private Cursor getIdentityKeyCursor ( SQLiteDatabase db , Account account , String name , boolean own ) {
2015-11-28 19:11:38 +00:00
return getIdentityKeyCursor ( db , account , name , own , null ) ;
2015-07-15 14:32:42 +00:00
}
2015-09-05 15:25:46 +00:00
private Cursor getIdentityKeyCursor ( Account account , String fingerprint ) {
2015-06-29 11:53:39 +00:00
final SQLiteDatabase db = this . getReadableDatabase ( ) ;
2015-09-05 15:25:46 +00:00
return getIdentityKeyCursor ( db , account , fingerprint ) ;
}
private Cursor getIdentityKeyCursor ( SQLiteDatabase db , Account account , String fingerprint ) {
return getIdentityKeyCursor ( db , account , null , null , fingerprint ) ;
}
private Cursor getIdentityKeyCursor ( SQLiteDatabase db , Account account , String name , Boolean own , String fingerprint ) {
2015-07-28 20:00:54 +00:00
String [ ] columns = { SQLiteAxolotlStore . TRUSTED ,
SQLiteAxolotlStore . KEY } ;
2015-07-09 12:23:17 +00:00
ArrayList < String > selectionArgs = new ArrayList < > ( 4 ) ;
selectionArgs . add ( account . getUuid ( ) ) ;
2015-07-28 20:00:54 +00:00
String selectionString = SQLiteAxolotlStore . ACCOUNT + " = ? " ;
2015-11-28 19:11:38 +00:00
if ( name ! = null ) {
2015-07-15 14:32:42 +00:00
selectionArgs . add ( name ) ;
2015-07-28 20:00:54 +00:00
selectionString + = " AND " + SQLiteAxolotlStore . NAME + " = ? " ;
2015-07-15 14:32:42 +00:00
}
2015-11-28 19:11:38 +00:00
if ( fingerprint ! = null ) {
2015-07-09 12:23:17 +00:00
selectionArgs . add ( fingerprint ) ;
2015-07-28 20:00:54 +00:00
selectionString + = " AND " + SQLiteAxolotlStore . FINGERPRINT + " = ? " ;
2015-07-15 14:32:42 +00:00
}
2015-11-28 19:11:38 +00:00
if ( own ! = null ) {
selectionArgs . add ( own ? " 1 " : " 0 " ) ;
2015-07-28 20:00:54 +00:00
selectionString + = " AND " + SQLiteAxolotlStore . OWN + " = ? " ;
2015-07-09 12:23:17 +00:00
}
2015-07-28 20:00:54 +00:00
Cursor cursor = db . query ( SQLiteAxolotlStore . IDENTITIES_TABLENAME ,
2015-06-29 11:53:39 +00:00
columns ,
2015-07-09 12:23:17 +00:00
selectionString ,
selectionArgs . toArray ( new String [ selectionArgs . size ( ) ] ) ,
2015-06-29 11:53:39 +00:00
null , null , null ) ;
return cursor ;
}
2015-09-05 15:25:46 +00:00
public IdentityKeyPair loadOwnIdentityKeyPair ( Account account ) {
SQLiteDatabase db = getReadableDatabase ( ) ;
return loadOwnIdentityKeyPair ( db , account ) ;
}
private IdentityKeyPair loadOwnIdentityKeyPair ( SQLiteDatabase db , Account account ) {
2016-10-20 15:31:46 +00:00
String name = account . getJid ( ) . toBareJid ( ) . toPreppedString ( ) ;
2015-06-29 11:53:39 +00:00
IdentityKeyPair identityKeyPair = null ;
2015-09-05 15:25:46 +00:00
Cursor cursor = getIdentityKeyCursor ( db , account , name , true ) ;
2015-11-28 19:11:38 +00:00
if ( cursor . getCount ( ) ! = 0 ) {
2015-06-29 11:53:39 +00:00
cursor . moveToFirst ( ) ;
try {
2015-11-28 19:11:38 +00:00
identityKeyPair = new IdentityKeyPair ( Base64 . decode ( cursor . getString ( cursor . getColumnIndex ( SQLiteAxolotlStore . KEY ) ) , Base64 . DEFAULT ) ) ;
2015-06-29 11:53:39 +00:00
} catch ( InvalidKeyException e ) {
2015-11-28 19:11:38 +00:00
Log . d ( Config . LOGTAG , AxolotlService . getLogprefix ( account ) + " Encountered invalid IdentityKey in database for account " + account . getJid ( ) . toBareJid ( ) + " , address: " + name ) ;
2015-06-29 11:53:39 +00:00
}
}
cursor . close ( ) ;
return identityKeyPair ;
}
public Set < IdentityKey > loadIdentityKeys ( Account account , String name ) {
2015-07-19 16:36:28 +00:00
return loadIdentityKeys ( account , name , null ) ;
}
2015-08-01 16:27:52 +00:00
public Set < IdentityKey > loadIdentityKeys ( Account account , String name , XmppAxolotlSession . Trust trust ) {
2015-06-29 11:53:39 +00:00
Set < IdentityKey > identityKeys = new HashSet < > ( ) ;
Cursor cursor = getIdentityKeyCursor ( account , name , false ) ;
2015-11-28 19:11:38 +00:00
while ( cursor . moveToNext ( ) ) {
if ( trust ! = null & &
2015-07-28 20:00:54 +00:00
cursor . getInt ( cursor . getColumnIndex ( SQLiteAxolotlStore . TRUSTED ) )
2015-07-20 23:52:22 +00:00
! = trust . getCode ( ) ) {
2015-07-19 16:36:28 +00:00
continue ;
}
2015-06-29 11:53:39 +00:00
try {
2015-11-28 19:11:38 +00:00
identityKeys . add ( new IdentityKey ( Base64 . decode ( cursor . getString ( cursor . getColumnIndex ( SQLiteAxolotlStore . KEY ) ) , Base64 . DEFAULT ) , 0 ) ) ;
2015-06-29 11:53:39 +00:00
} catch ( InvalidKeyException e ) {
2015-11-28 19:11:38 +00:00
Log . d ( Config . LOGTAG , AxolotlService . getLogprefix ( account ) + " Encountered invalid IdentityKey in database for account " + account . getJid ( ) . toBareJid ( ) + " , address: " + name ) ;
2015-06-29 11:53:39 +00:00
}
}
cursor . close ( ) ;
return identityKeys ;
}
2015-07-20 12:56:41 +00:00
public long numTrustedKeys ( Account account , String name ) {
SQLiteDatabase db = getReadableDatabase ( ) ;
String [ ] args = {
account . getUuid ( ) ,
2015-07-20 20:02:54 +00:00
name ,
2015-10-31 09:57:57 +00:00
String . valueOf ( XmppAxolotlSession . Trust . TRUSTED . getCode ( ) ) ,
String . valueOf ( XmppAxolotlSession . Trust . TRUSTED_X509 . getCode ( ) )
2015-07-20 12:56:41 +00:00
} ;
2015-07-28 20:00:54 +00:00
return DatabaseUtils . queryNumEntries ( db , SQLiteAxolotlStore . IDENTITIES_TABLENAME ,
SQLiteAxolotlStore . ACCOUNT + " = ? "
2015-11-28 19:11:38 +00:00
+ " AND " + SQLiteAxolotlStore . NAME + " = ? "
+ " AND ( " + SQLiteAxolotlStore . TRUSTED + " = ? OR " + SQLiteAxolotlStore . TRUSTED + " = ?) " ,
2015-07-20 12:56:41 +00:00
args
) ;
}
2015-07-09 12:23:17 +00:00
private void storeIdentityKey ( Account account , String name , boolean own , String fingerprint , String base64Serialized ) {
2015-08-01 16:27:52 +00:00
storeIdentityKey ( account , name , own , fingerprint , base64Serialized , XmppAxolotlSession . Trust . UNDECIDED ) ;
2015-07-15 14:32:42 +00:00
}
2015-08-01 16:27:52 +00:00
private void storeIdentityKey ( Account account , String name , boolean own , String fingerprint , String base64Serialized , XmppAxolotlSession . Trust trusted ) {
2015-06-29 11:53:39 +00:00
SQLiteDatabase db = this . getWritableDatabase ( ) ;
ContentValues values = new ContentValues ( ) ;
2015-07-28 20:00:54 +00:00
values . put ( SQLiteAxolotlStore . ACCOUNT , account . getUuid ( ) ) ;
values . put ( SQLiteAxolotlStore . NAME , name ) ;
values . put ( SQLiteAxolotlStore . OWN , own ? 1 : 0 ) ;
values . put ( SQLiteAxolotlStore . FINGERPRINT , fingerprint ) ;
values . put ( SQLiteAxolotlStore . KEY , base64Serialized ) ;
values . put ( SQLiteAxolotlStore . TRUSTED , trusted . getCode ( ) ) ;
db . insert ( SQLiteAxolotlStore . IDENTITIES_TABLENAME , null , values ) ;
2015-06-29 11:53:39 +00:00
}
2015-08-01 16:27:52 +00:00
public XmppAxolotlSession . Trust isIdentityKeyTrusted ( Account account , String fingerprint ) {
2015-07-15 14:32:42 +00:00
Cursor cursor = getIdentityKeyCursor ( account , fingerprint ) ;
2015-08-01 16:27:52 +00:00
XmppAxolotlSession . Trust trust = null ;
2015-07-09 12:23:17 +00:00
if ( cursor . getCount ( ) > 0 ) {
cursor . moveToFirst ( ) ;
2015-07-28 20:00:54 +00:00
int trustValue = cursor . getInt ( cursor . getColumnIndex ( SQLiteAxolotlStore . TRUSTED ) ) ;
2015-08-01 16:27:52 +00:00
trust = XmppAxolotlSession . Trust . fromCode ( trustValue ) ;
2015-07-09 12:23:17 +00:00
}
cursor . close ( ) ;
return trust ;
}
2015-08-01 16:27:52 +00:00
public boolean setIdentityKeyTrust ( Account account , String fingerprint , XmppAxolotlSession . Trust trust ) {
2015-07-09 12:23:17 +00:00
SQLiteDatabase db = this . getWritableDatabase ( ) ;
2015-09-05 15:25:46 +00:00
return setIdentityKeyTrust ( db , account , fingerprint , trust ) ;
}
private boolean setIdentityKeyTrust ( SQLiteDatabase db , Account account , String fingerprint , XmppAxolotlSession . Trust trust ) {
2015-07-09 12:23:17 +00:00
String [ ] selectionArgs = {
account . getUuid ( ) ,
fingerprint
} ;
ContentValues values = new ContentValues ( ) ;
2015-07-28 20:00:54 +00:00
values . put ( SQLiteAxolotlStore . TRUSTED , trust . getCode ( ) ) ;
int rows = db . update ( SQLiteAxolotlStore . IDENTITIES_TABLENAME , values ,
SQLiteAxolotlStore . ACCOUNT + " = ? AND "
2015-11-28 19:11:38 +00:00
+ SQLiteAxolotlStore . FINGERPRINT + " = ? " ,
2015-07-09 12:23:17 +00:00
selectionArgs ) ;
return rows = = 1 ;
}
2015-12-23 16:41:26 +00:00
public boolean setIdentityKeyCertificate ( Account account , String fingerprint , X509Certificate x509Certificate ) {
SQLiteDatabase db = this . getWritableDatabase ( ) ;
String [ ] selectionArgs = {
account . getUuid ( ) ,
fingerprint
} ;
try {
ContentValues values = new ContentValues ( ) ;
values . put ( SQLiteAxolotlStore . CERTIFICATE , x509Certificate . getEncoded ( ) ) ;
return db . update ( SQLiteAxolotlStore . IDENTITIES_TABLENAME , values ,
SQLiteAxolotlStore . ACCOUNT + " = ? AND "
+ SQLiteAxolotlStore . FINGERPRINT + " = ? " ,
selectionArgs ) = = 1 ;
} catch ( CertificateEncodingException e ) {
2015-12-23 18:18:53 +00:00
Log . d ( Config . LOGTAG , " could not encode certificate " ) ;
2015-12-23 16:41:26 +00:00
return false ;
}
}
2015-12-23 18:18:53 +00:00
public X509Certificate getIdentityKeyCertifcate ( Account account , String fingerprint ) {
SQLiteDatabase db = this . getReadableDatabase ( ) ;
String [ ] selectionArgs = {
account . getUuid ( ) ,
fingerprint
} ;
String [ ] colums = { SQLiteAxolotlStore . CERTIFICATE } ;
String selection = SQLiteAxolotlStore . ACCOUNT + " = ? AND " + SQLiteAxolotlStore . FINGERPRINT + " = ? " ;
Cursor cursor = db . query ( SQLiteAxolotlStore . IDENTITIES_TABLENAME , colums , selection , selectionArgs , null , null , null ) ;
if ( cursor . getCount ( ) < 1 ) {
return null ;
} else {
cursor . moveToFirst ( ) ;
byte [ ] certificate = cursor . getBlob ( cursor . getColumnIndex ( SQLiteAxolotlStore . CERTIFICATE ) ) ;
2016-06-12 10:50:31 +00:00
cursor . close ( ) ;
2015-12-23 18:18:53 +00:00
if ( certificate = = null | | certificate . length = = 0 ) {
return null ;
}
try {
CertificateFactory certificateFactory = CertificateFactory . getInstance ( " X.509 " ) ;
return ( X509Certificate ) certificateFactory . generateCertificate ( new ByteArrayInputStream ( certificate ) ) ;
} catch ( CertificateException e ) {
Log . d ( Config . LOGTAG , " certificate exception " + e . getMessage ( ) ) ;
return null ;
}
}
}
2015-06-29 11:53:39 +00:00
public void storeIdentityKey ( Account account , String name , IdentityKey identityKey ) {
2015-07-09 12:23:17 +00:00
storeIdentityKey ( account , name , false , identityKey . getFingerprint ( ) . replaceAll ( " \\ s " , " " ) , Base64 . encodeToString ( identityKey . serialize ( ) , Base64 . DEFAULT ) ) ;
2015-06-29 11:53:39 +00:00
}
2015-09-05 15:25:46 +00:00
public void storeOwnIdentityKeyPair ( Account account , IdentityKeyPair identityKeyPair ) {
2016-10-20 15:31:46 +00:00
storeIdentityKey ( account , account . getJid ( ) . toBareJid ( ) . toPreppedString ( ) , true , identityKeyPair . getPublicKey ( ) . getFingerprint ( ) . replaceAll ( " \\ s " , " " ) , Base64 . encodeToString ( identityKeyPair . serialize ( ) , Base64 . DEFAULT ) , XmppAxolotlSession . Trust . TRUSTED ) ;
2015-06-29 11:53:39 +00:00
}
2015-07-07 17:30:08 +00:00
2015-07-20 11:15:49 +00:00
public void recreateAxolotlDb ( SQLiteDatabase db ) {
2015-11-28 19:11:38 +00:00
Log . d ( Config . LOGTAG , AxolotlService . LOGPREFIX + " : " + " >>> (RE)CREATING AXOLOTL DATABASE <<< " ) ;
2015-07-28 20:00:54 +00:00
db . execSQL ( " DROP TABLE IF EXISTS " + SQLiteAxolotlStore . SESSION_TABLENAME ) ;
2015-07-07 17:30:08 +00:00
db . execSQL ( CREATE_SESSIONS_STATEMENT ) ;
2015-07-28 20:00:54 +00:00
db . execSQL ( " DROP TABLE IF EXISTS " + SQLiteAxolotlStore . PREKEY_TABLENAME ) ;
2015-07-07 17:30:08 +00:00
db . execSQL ( CREATE_PREKEYS_STATEMENT ) ;
2015-07-28 20:00:54 +00:00
db . execSQL ( " DROP TABLE IF EXISTS " + SQLiteAxolotlStore . SIGNED_PREKEY_TABLENAME ) ;
2015-07-07 17:30:08 +00:00
db . execSQL ( CREATE_SIGNED_PREKEYS_STATEMENT ) ;
2015-07-28 20:00:54 +00:00
db . execSQL ( " DROP TABLE IF EXISTS " + SQLiteAxolotlStore . IDENTITIES_TABLENAME ) ;
2015-07-07 17:30:08 +00:00
db . execSQL ( CREATE_IDENTITIES_STATEMENT ) ;
}
2015-11-28 19:11:38 +00:00
2015-07-07 17:36:22 +00:00
public void wipeAxolotlDb ( Account account ) {
String accountName = account . getUuid ( ) ;
2015-11-28 19:11:38 +00:00
Log . d ( Config . LOGTAG , AxolotlService . getLogprefix ( account ) + " >>> WIPING AXOLOTL DATABASE FOR ACCOUNT " + accountName + " <<< " ) ;
2015-07-07 17:36:22 +00:00
SQLiteDatabase db = this . getWritableDatabase ( ) ;
2015-11-28 19:11:38 +00:00
String [ ] deleteArgs = {
2015-07-07 17:36:22 +00:00
accountName
} ;
2015-07-28 20:00:54 +00:00
db . delete ( SQLiteAxolotlStore . SESSION_TABLENAME ,
SQLiteAxolotlStore . ACCOUNT + " = ? " ,
2015-07-07 17:36:22 +00:00
deleteArgs ) ;
2015-07-28 20:00:54 +00:00
db . delete ( SQLiteAxolotlStore . PREKEY_TABLENAME ,
SQLiteAxolotlStore . ACCOUNT + " = ? " ,
2015-07-07 17:36:22 +00:00
deleteArgs ) ;
2015-07-28 20:00:54 +00:00
db . delete ( SQLiteAxolotlStore . SIGNED_PREKEY_TABLENAME ,
SQLiteAxolotlStore . ACCOUNT + " = ? " ,
2015-07-07 17:36:22 +00:00
deleteArgs ) ;
2015-07-28 20:00:54 +00:00
db . delete ( SQLiteAxolotlStore . IDENTITIES_TABLENAME ,
SQLiteAxolotlStore . ACCOUNT + " = ? " ,
2015-07-07 17:36:22 +00:00
deleteArgs ) ;
}
2014-01-24 22:58:51 +00:00
}