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 ;
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-05-29 09:17:26 +00:00
import java.io.IOException ;
2014-01-24 22:58:51 +00:00
import java.util.ArrayList ;
2015-06-29 11:53:39 +00:00
import java.util.HashSet ;
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 ;
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 ;
2014-05-19 13:15:09 +00:00
import eu.siacs.conversations.entities.Roster ;
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 " ;
2015-07-29 14:41:58 +00:00
private static final int DATABASE_VERSION = 16 ;
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
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 + " ( "
+ SQLiteAxolotlStore . ACCOUNT + " TEXT, "
+ SQLiteAxolotlStore . ID + " INTEGER, "
+ SQLiteAxolotlStore . KEY + " TEXT, FOREIGN KEY( "
+ SQLiteAxolotlStore . ACCOUNT
2015-05-29 09:17:26 +00:00
+ " ) REFERENCES " + Account . TABLENAME + " ( " + Account . UUID + " ) ON DELETE CASCADE, "
2015-07-28 20:00:54 +00:00
+ " UNIQUE( " + SQLiteAxolotlStore . ACCOUNT + " , "
+ SQLiteAxolotlStore . ID
2015-05-29 09:17:26 +00:00
+ " ) ON CONFLICT REPLACE "
+ " ); " ;
private static String CREATE_SIGNED_PREKEYS_STATEMENT = " CREATE TABLE "
2015-07-28 20:00:54 +00:00
+ SQLiteAxolotlStore . SIGNED_PREKEY_TABLENAME + " ( "
+ SQLiteAxolotlStore . ACCOUNT + " TEXT, "
+ SQLiteAxolotlStore . ID + " INTEGER, "
+ SQLiteAxolotlStore . KEY + " TEXT, FOREIGN KEY( "
+ SQLiteAxolotlStore . ACCOUNT
2015-05-29 09:17:26 +00:00
+ " ) REFERENCES " + Account . TABLENAME + " ( " + Account . UUID + " ) ON DELETE CASCADE, "
2015-07-28 20:00:54 +00:00
+ " UNIQUE( " + SQLiteAxolotlStore . ACCOUNT + " , "
+ SQLiteAxolotlStore . ID
2015-05-29 09:17:26 +00:00
+ " ) ON CONFLICT REPLACE " +
" ); " ;
private static String CREATE_SESSIONS_STATEMENT = " CREATE TABLE "
2015-07-28 20:00:54 +00:00
+ SQLiteAxolotlStore . SESSION_TABLENAME + " ( "
+ SQLiteAxolotlStore . ACCOUNT + " TEXT, "
+ SQLiteAxolotlStore . NAME + " TEXT, "
+ SQLiteAxolotlStore . DEVICE_ID + " INTEGER, "
+ SQLiteAxolotlStore . KEY + " TEXT, FOREIGN KEY( "
+ SQLiteAxolotlStore . ACCOUNT
2015-05-29 09:17:26 +00:00
+ " ) REFERENCES " + Account . TABLENAME + " ( " + Account . UUID + " ) ON DELETE CASCADE, "
2015-07-28 20:00:54 +00:00
+ " UNIQUE( " + SQLiteAxolotlStore . ACCOUNT + " , "
+ SQLiteAxolotlStore . NAME + " , "
+ SQLiteAxolotlStore . DEVICE_ID
2015-05-29 09:17:26 +00:00
+ " ) ON CONFLICT REPLACE "
+ " ); " ;
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, "
+ 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 + " , "
+ SQLiteAxolotlStore . NAME + " , "
+ SQLiteAxolotlStore . FINGERPRINT
2015-07-10 00:24:33 +00:00
+ " ) ON CONFLICT IGNORE "
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; " ) ;
db . execSQL ( " create table " + Account . TABLENAME + " ( " + Account . UUID
2014-02-02 15:05:15 +00:00
+ " TEXT PRIMARY KEY, " + Account . USERNAME + " TEXT, "
+ Account . SERVER + " TEXT, " + Account . PASSWORD + " TEXT, "
+ Account . ROSTERVERSION + " TEXT, " + Account . OPTIONS
2014-08-24 18:53:13 +00:00
+ " NUMBER, " + Account . AVATAR + " TEXT, " + Account . KEYS
+ " TEXT) " ) ;
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, "
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 ) ;
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 ) ;
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 " ) ;
db . execSQL ( " delete from " + Contact . TABLENAME ) ;
db . execSQL ( " update " + Account . TABLENAME + " set " + Account . ROSTERVERSION + " = NULL " ) ;
}
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 ) {
db . execSQL ( " delete from " + Contact . TABLENAME ) ;
db . execSQL ( " update " + Account . TABLENAME + " set " + Account . ROSTERVERSION + " = NULL " ) ;
}
2015-05-14 13:25:52 +00:00
if ( oldVersion < 14 & & newVersion > = 14 ) {
// 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 ) )
) . toString ( ) ;
} 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 ) )
) . toString ( ) ;
} 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 ( ) ;
}
2015-06-25 14:56:34 +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 " ) ;
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 " ) ;
}
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
2014-02-05 21:33:39 +00:00
public void createContact ( Contact contact ) {
SQLiteDatabase db = this . getWritableDatabase ( ) ;
db . insert ( Contact . TABLENAME , null , contact . getContentValues ( ) ) ;
}
2014-01-26 02:27:55 +00:00
2014-01-24 22:58:51 +00:00
public int getConversationCount ( ) {
SQLiteDatabase db = this . getReadableDatabase ( ) ;
2014-01-28 23:15:38 +00:00
Cursor cursor = db . rawQuery ( " select count(uuid) as count from "
+ Conversation . TABLENAME + " where " + Conversation . STATUS
+ " = " + Conversation . STATUS_AVAILABLE , null ) ;
2014-01-24 22:58:51 +00:00
cursor . moveToFirst ( ) ;
2014-11-15 23:34:16 +00:00
int count = cursor . getInt ( 0 ) ;
cursor . close ( ) ;
return count ;
2014-01-24 22:58:51 +00:00
}
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 ( ) ;
2014-09-01 08:40:45 +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 ,
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 ) {
2014-06-14 14:59:07 +00:00
String [ ] selectionArgs = { conversation . getUuid ( ) } ;
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 {
2014-09-08 21:58:37 +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
2014-07-29 12:42:17 +00:00
+ " =? and " + Message . TIME_SENT + " <? " , selectionArgs ,
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 ;
}
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-01-21 15:18:57 +00:00
String [ ] selectionArgs = { account . getUuid ( ) ,
contactJid . toBareJid ( ) . toString ( ) + " /% " ,
contactJid . toBareJid ( ) . toString ( )
} ;
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 ) ;
2014-01-28 23:15:38 +00:00
if ( cursor . getCount ( ) = = 0 )
return null ;
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 ( ) ;
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 ( ) {
2014-11-05 20:55:47 +00:00
List < Account > list = new ArrayList < > ( ) ;
2014-01-28 18:21:54 +00:00
SQLiteDatabase db = this . getReadableDatabase ( ) ;
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 ;
}
public void updateAccount ( Account account ) {
SQLiteDatabase db = this . getWritableDatabase ( ) ;
2014-01-28 23:15:38 +00:00
String [ ] args = { account . getUuid ( ) } ;
db . update ( Account . TABLENAME , account . getContentValues ( ) , Account . UUID
+ " =? " , args ) ;
2014-01-28 18:21:54 +00:00
}
public void deleteAccount ( Account account ) {
SQLiteDatabase db = this . getWritableDatabase ( ) ;
2014-01-28 23:15:38 +00:00
String [ ] args = { account . getUuid ( ) } ;
db . delete ( Account . TABLENAME , Account . UUID + " =? " , args ) ;
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 ) ;
cursor . close ( ) ;
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
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 ( ) ;
String [ ] args = { message . getUuid ( ) } ;
db . update ( Message . TABLENAME , message . getContentValues ( ) , Message . UUID
+ " =? " , args ) ;
}
2014-02-05 21:33:39 +00:00
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 ;
2014-05-19 13:15:09 +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 ( ) ;
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 + " =? " ;
2014-11-05 20:55:47 +00:00
String [ ] whereArgs = { account . getUuid ( ) , contact . getJid ( ) . toString ( ) } ;
2014-05-19 19:05:17 +00:00
db . delete ( Contact . TABLENAME , where , whereArgs ) ;
}
}
account . setRosterVersion ( roster . getVersion ( ) ) ;
updateAccount ( account ) ;
2014-02-05 21:33:39 +00:00
}
2014-02-11 22:55:03 +00:00
public void deleteMessage ( Message message ) {
SQLiteDatabase db = this . getWritableDatabase ( ) ;
String [ ] args = { message . getUuid ( ) } ;
db . delete ( Message . TABLENAME , Message . UUID + " =? " , args ) ;
}
2014-05-19 13:15:09 +00:00
2014-04-20 18:48:16 +00:00
public void deleteMessagesInConversation ( Conversation conversation ) {
SQLiteDatabase db = this . getWritableDatabase ( ) ;
String [ ] args = { conversation . getUuid ( ) } ;
db . delete ( Message . TABLENAME , Message . CONVERSATION + " =? " , args ) ;
}
2014-02-19 00:35:23 +00:00
2014-04-21 17:51:03 +00:00
public Conversation findConversationByUuid ( String conversationUuid ) {
SQLiteDatabase db = this . getReadableDatabase ( ) ;
String [ ] selectionArgs = { conversationUuid } ;
2014-05-19 13:15:09 +00:00
Cursor cursor = db . query ( Conversation . TABLENAME , null ,
Conversation . UUID + " =? " , selectionArgs , null , null , null ) ;
2014-04-21 17:51:03 +00:00
if ( cursor . getCount ( ) = = 0 ) {
return null ;
}
cursor . moveToFirst ( ) ;
2014-11-15 23:34:16 +00:00
Conversation conversation = Conversation . fromCursor ( cursor ) ;
cursor . close ( ) ;
return conversation ;
2014-04-21 17:51:03 +00:00
}
public Message findMessageByUuid ( String messageUuid ) {
SQLiteDatabase db = this . getReadableDatabase ( ) ;
String [ ] selectionArgs = { messageUuid } ;
2014-05-19 13:15:09 +00:00
Cursor cursor = db . query ( Message . TABLENAME , null , Message . UUID + " =? " ,
selectionArgs , null , null , null ) ;
2014-04-21 17:51:03 +00:00
if ( cursor . getCount ( ) = = 0 ) {
return null ;
}
cursor . moveToFirst ( ) ;
2014-11-15 23:34:16 +00:00
Message message = Message . fromCursor ( cursor ) ;
cursor . close ( ) ;
return message ;
2014-04-21 17:51:03 +00:00
}
2014-05-19 13:15:09 +00:00
2014-04-21 17:51:03 +00:00
public Account findAccountByUuid ( String accountUuid ) {
SQLiteDatabase db = this . getReadableDatabase ( ) ;
String [ ] selectionArgs = { accountUuid } ;
2014-05-19 13:15:09 +00:00
Cursor cursor = db . query ( Account . TABLENAME , null , Account . UUID + " =? " ,
selectionArgs , null , null , null ) ;
2014-04-21 17:51:03 +00:00
if ( cursor . getCount ( ) = = 0 ) {
return null ;
}
cursor . moveToFirst ( ) ;
2014-11-15 23:34:16 +00:00
Account account = Account . fromCursor ( cursor ) ;
cursor . close ( ) ;
return account ;
2014-04-21 17:51:03 +00:00
}
2014-10-29 23:31:44 +00:00
public List < Message > getImageMessages ( Conversation conversation ) {
2014-11-05 20:55:47 +00:00
ArrayList < Message > list = new ArrayList < > ( ) ;
2014-10-29 23:31:44 +00:00
SQLiteDatabase db = this . getReadableDatabase ( ) ;
Cursor cursor ;
String [ ] selectionArgs = { conversation . getUuid ( ) , String . valueOf ( Message . TYPE_IMAGE ) } ;
cursor = db . query ( Message . TABLENAME , null , Message . CONVERSATION
+ " =? AND " + Message . TYPE + " =? " , selectionArgs , null , null , null ) ;
if ( cursor . getCount ( ) > 0 ) {
cursor . moveToLast ( ) ;
do {
Message message = Message . fromCursor ( cursor ) ;
message . setConversation ( conversation ) ;
list . add ( message ) ;
} while ( cursor . moveToPrevious ( ) ) ;
}
2014-11-15 23:34:16 +00:00
cursor . close ( ) ;
2014-10-29 23:31:44 +00:00
return list ;
}
2015-05-29 09:17:26 +00:00
private Cursor getCursorForSession ( Account account , AxolotlAddress contact ) {
final SQLiteDatabase db = this . getReadableDatabase ( ) ;
String [ ] columns = null ;
String [ ] selectionArgs = { account . getUuid ( ) ,
contact . getName ( ) ,
Integer . toString ( contact . getDeviceId ( ) ) } ;
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 + " = ? AND "
+ SQLiteAxolotlStore . DEVICE_ID + " = ? " ,
2015-05-29 09:17:26 +00:00
selectionArgs ,
null , null , null ) ;
return cursor ;
}
public SessionRecord loadSession ( Account account , AxolotlAddress contact ) {
SessionRecord session = null ;
2015-06-26 13:41:02 +00:00
Cursor cursor = getCursorForSession ( account , contact ) ;
2015-05-29 09:17:26 +00:00
if ( cursor . getCount ( ) ! = 0 ) {
cursor . moveToFirst ( ) ;
try {
2015-07-28 20:00:54 +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 ) {
List < Integer > devices = new ArrayList < > ( ) ;
final SQLiteDatabase db = this . getReadableDatabase ( ) ;
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 ) ;
while ( cursor . moveToNext ( ) ) {
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 ( ) ) ;
values . put ( SQLiteAxolotlStore . KEY , Base64 . encodeToString ( session . serialize ( ) , Base64 . DEFAULT ) ) ;
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 ( ) ;
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 ) ;
if ( cursor . getCount ( ) ! = 0 ) {
cursor . moveToFirst ( ) ;
try {
2015-07-28 20:00:54 +00:00
record = new PreKeyRecord ( Base64 . decode ( cursor . getString ( cursor . getColumnIndex ( SQLiteAxolotlStore . KEY ) ) , Base64 . DEFAULT ) ) ;
2015-05-29 09:17:26 +00:00
} catch ( IOException e ) {
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 ( ) ) ;
values . put ( SQLiteAxolotlStore . KEY , Base64 . encodeToString ( record . serialize ( ) , Base64 . DEFAULT ) ) ;
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-05-29 09:17:26 +00:00
if ( cursor . getCount ( ) ! = 0 ) {
cursor . moveToFirst ( ) ;
try {
2015-07-28 20:00:54 +00:00
record = new SignedPreKeyRecord ( Base64 . decode ( cursor . getString ( cursor . getColumnIndex ( SQLiteAxolotlStore . KEY ) ) , Base64 . DEFAULT ) ) ;
2015-05-29 09:17:26 +00:00
} catch ( IOException e ) {
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 ) ;
while ( cursor . moveToNext ( ) ) {
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 ( ) ) ;
values . put ( SQLiteAxolotlStore . KEY , Base64 . encodeToString ( record . serialize ( ) , Base64 . DEFAULT ) ) ;
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-07-09 12:23:17 +00:00
return getIdentityKeyCursor ( account , name , own , null ) ;
}
2015-07-15 14:32:42 +00:00
private Cursor getIdentityKeyCursor ( Account account , String fingerprint ) {
return getIdentityKeyCursor ( account , null , null , fingerprint ) ;
}
private Cursor getIdentityKeyCursor ( Account account , String name , Boolean own , String fingerprint ) {
2015-06-29 11:53:39 +00:00
final SQLiteDatabase db = this . getReadableDatabase ( ) ;
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-07-15 14:32:42 +00:00
if ( name ! = null ) {
selectionArgs . add ( name ) ;
2015-07-28 20:00:54 +00:00
selectionString + = " AND " + SQLiteAxolotlStore . NAME + " = ? " ;
2015-07-15 14:32:42 +00:00
}
2015-07-09 12:23:17 +00:00
if ( fingerprint ! = null ) {
selectionArgs . add ( fingerprint ) ;
2015-07-28 20:00:54 +00:00
selectionString + = " AND " + SQLiteAxolotlStore . FINGERPRINT + " = ? " ;
2015-07-15 14:32:42 +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 ;
}
public IdentityKeyPair loadOwnIdentityKeyPair ( Account account , String name ) {
IdentityKeyPair identityKeyPair = null ;
Cursor cursor = getIdentityKeyCursor ( account , name , true ) ;
if ( cursor . getCount ( ) ! = 0 ) {
cursor . moveToFirst ( ) ;
try {
2015-07-28 20:00:54 +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-07-08 15:44:24 +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 ) ;
while ( cursor . moveToNext ( ) ) {
2015-07-19 16:36:28 +00:00
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-07-28 20:00:54 +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-07-08 15:44:24 +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-08-01 16:27:52 +00:00
String . valueOf ( XmppAxolotlSession . Trust . TRUSTED . 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 + " = ? "
+ " AND " + SQLiteAxolotlStore . NAME + " = ? "
+ " AND " + 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 ( ) ;
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 "
+ SQLiteAxolotlStore . FINGERPRINT + " = ? " ,
2015-07-09 12:23:17 +00:00
selectionArgs ) ;
return rows = = 1 ;
}
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
}
public void storeOwnIdentityKeyPair ( Account account , String name , IdentityKeyPair identityKeyPair ) {
2015-08-01 16:27:52 +00:00
storeIdentityKey ( account , name , 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
public void recreateAxolotlDb ( ) {
2015-07-20 11:15:49 +00:00
recreateAxolotlDb ( getWritableDatabase ( ) ) ;
}
public void recreateAxolotlDb ( SQLiteDatabase db ) {
2015-07-08 15:44:24 +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-07-07 17:36:22 +00:00
public void wipeAxolotlDb ( Account account ) {
String accountName = account . getUuid ( ) ;
2015-07-08 15:44:24 +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 ( ) ;
String [ ] deleteArgs = {
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
}