Search in sources :

Example 96 with SQLiteDatabase

use of android.database.sqlite.SQLiteDatabase in project Signal-Android by WhisperSystems.

the class CanonicalAddressDatabase method fillCache.

private void fillCache() {
    Cursor cursor = null;
    try {
        SQLiteDatabase db = databaseHelper.getReadableDatabase();
        cursor = db.query(TABLE, null, null, null, null, null, null);
        while (cursor != null && cursor.moveToNext()) {
            long id = cursor.getLong(cursor.getColumnIndexOrThrow(ID_COLUMN));
            String address = cursor.getString(cursor.getColumnIndexOrThrow(ADDRESS_COLUMN));
            if (address == null || address.trim().length() == 0)
                address = "Anonymous";
            idCache.put(id, address);
            addressCache.put(address, id);
        }
    } finally {
        if (cursor != null)
            cursor.close();
    }
}
Also used : SQLiteDatabase(android.database.sqlite.SQLiteDatabase) Cursor(android.database.Cursor)

Example 97 with SQLiteDatabase

use of android.database.sqlite.SQLiteDatabase in project Signal-Android by WhisperSystems.

the class DatabaseFactory method onApplicationLevelUpgrade.

public void onApplicationLevelUpgrade(Context context, MasterSecret masterSecret, int fromVersion, DatabaseUpgradeActivity.DatabaseUpgradeListener listener) {
    SQLiteDatabase db = databaseHelper.getWritableDatabase();
    db.beginTransaction();
    if (fromVersion < DatabaseUpgradeActivity.NO_MORE_KEY_EXCHANGE_PREFIX_VERSION) {
        String KEY_EXCHANGE = "?TextSecureKeyExchange";
        String PROCESSED_KEY_EXCHANGE = "?TextSecureKeyExchangd";
        String STALE_KEY_EXCHANGE = "?TextSecureKeyExchangs";
        int ROW_LIMIT = 500;
        MasterCipher masterCipher = new MasterCipher(masterSecret);
        int smsCount = 0;
        int threadCount = 0;
        int skip = 0;
        Cursor cursor = db.query("sms", new String[] { "COUNT(*)" }, "type & " + 0x80000000 + " != 0", null, null, null, null);
        if (cursor != null && cursor.moveToFirst()) {
            smsCount = cursor.getInt(0);
            cursor.close();
        }
        cursor = db.query("thread", new String[] { "COUNT(*)" }, "snippet_type & " + 0x80000000 + " != 0", null, null, null, null);
        if (cursor != null && cursor.moveToFirst()) {
            threadCount = cursor.getInt(0);
            cursor.close();
        }
        Cursor smsCursor = null;
        Log.w("DatabaseFactory", "Upgrade count: " + (smsCount + threadCount));
        do {
            Log.w("DatabaseFactory", "Looping SMS cursor...");
            if (smsCursor != null)
                smsCursor.close();
            smsCursor = db.query("sms", new String[] { "_id", "type", "body" }, "type & " + 0x80000000 + " != 0", null, null, null, "_id", skip + "," + ROW_LIMIT);
            while (smsCursor != null && smsCursor.moveToNext()) {
                listener.setProgress(smsCursor.getPosition() + skip, smsCount + threadCount);
                try {
                    String body = masterCipher.decryptBody(smsCursor.getString(smsCursor.getColumnIndexOrThrow("body")));
                    long type = smsCursor.getLong(smsCursor.getColumnIndexOrThrow("type"));
                    long id = smsCursor.getLong(smsCursor.getColumnIndexOrThrow("_id"));
                    if (body.startsWith(KEY_EXCHANGE)) {
                        body = body.substring(KEY_EXCHANGE.length());
                        body = masterCipher.encryptBody(body);
                        type |= 0x8000;
                        db.execSQL("UPDATE sms SET body = ?, type = ? WHERE _id = ?", new String[] { body, type + "", id + "" });
                    } else if (body.startsWith(PROCESSED_KEY_EXCHANGE)) {
                        body = body.substring(PROCESSED_KEY_EXCHANGE.length());
                        body = masterCipher.encryptBody(body);
                        type |= (0x8000 | 0x2000);
                        db.execSQL("UPDATE sms SET body = ?, type = ? WHERE _id = ?", new String[] { body, type + "", id + "" });
                    } else if (body.startsWith(STALE_KEY_EXCHANGE)) {
                        body = body.substring(STALE_KEY_EXCHANGE.length());
                        body = masterCipher.encryptBody(body);
                        type |= (0x8000 | 0x4000);
                        db.execSQL("UPDATE sms SET body = ?, type = ? WHERE _id = ?", new String[] { body, type + "", id + "" });
                    }
                } catch (InvalidMessageException e) {
                    Log.w("DatabaseFactory", e);
                }
            }
            skip += ROW_LIMIT;
        } while (smsCursor != null && smsCursor.getCount() > 0);
        Cursor threadCursor = null;
        skip = 0;
        do {
            Log.w("DatabaseFactory", "Looping thread cursor...");
            if (threadCursor != null)
                threadCursor.close();
            threadCursor = db.query("thread", new String[] { "_id", "snippet_type", "snippet" }, "snippet_type & " + 0x80000000 + " != 0", null, null, null, "_id", skip + "," + ROW_LIMIT);
            while (threadCursor != null && threadCursor.moveToNext()) {
                listener.setProgress(smsCount + threadCursor.getPosition(), smsCount + threadCount);
                try {
                    String snippet = threadCursor.getString(threadCursor.getColumnIndexOrThrow("snippet"));
                    long snippetType = threadCursor.getLong(threadCursor.getColumnIndexOrThrow("snippet_type"));
                    long id = threadCursor.getLong(threadCursor.getColumnIndexOrThrow("_id"));
                    if (!TextUtils.isEmpty(snippet)) {
                        snippet = masterCipher.decryptBody(snippet);
                    }
                    if (snippet.startsWith(KEY_EXCHANGE)) {
                        snippet = snippet.substring(KEY_EXCHANGE.length());
                        snippet = masterCipher.encryptBody(snippet);
                        snippetType |= 0x8000;
                        db.execSQL("UPDATE thread SET snippet = ?, snippet_type = ? WHERE _id = ?", new String[] { snippet, snippetType + "", id + "" });
                    } else if (snippet.startsWith(PROCESSED_KEY_EXCHANGE)) {
                        snippet = snippet.substring(PROCESSED_KEY_EXCHANGE.length());
                        snippet = masterCipher.encryptBody(snippet);
                        snippetType |= (0x8000 | 0x2000);
                        db.execSQL("UPDATE thread SET snippet = ?, snippet_type = ? WHERE _id = ?", new String[] { snippet, snippetType + "", id + "" });
                    } else if (snippet.startsWith(STALE_KEY_EXCHANGE)) {
                        snippet = snippet.substring(STALE_KEY_EXCHANGE.length());
                        snippet = masterCipher.encryptBody(snippet);
                        snippetType |= (0x8000 | 0x4000);
                        db.execSQL("UPDATE thread SET snippet = ?, snippet_type = ? WHERE _id = ?", new String[] { snippet, snippetType + "", id + "" });
                    }
                } catch (InvalidMessageException e) {
                    Log.w("DatabaseFactory", e);
                }
            }
            skip += ROW_LIMIT;
        } while (threadCursor != null && threadCursor.getCount() > 0);
        if (smsCursor != null)
            smsCursor.close();
        if (threadCursor != null)
            threadCursor.close();
    }
    if (fromVersion < DatabaseUpgradeActivity.MMS_BODY_VERSION) {
        Log.w("DatabaseFactory", "Update MMS bodies...");
        MasterCipher masterCipher = new MasterCipher(masterSecret);
        Cursor mmsCursor = db.query("mms", new String[] { "_id" }, "msg_box & " + 0x80000000L + " != 0", null, null, null, null);
        Log.w("DatabaseFactory", "Got MMS rows: " + (mmsCursor == null ? "null" : mmsCursor.getCount()));
        while (mmsCursor != null && mmsCursor.moveToNext()) {
            listener.setProgress(mmsCursor.getPosition(), mmsCursor.getCount());
            long mmsId = mmsCursor.getLong(mmsCursor.getColumnIndexOrThrow("_id"));
            String body = null;
            int partCount = 0;
            Cursor partCursor = db.query("part", new String[] { "_id", "ct", "_data", "encrypted" }, "mid = ?", new String[] { mmsId + "" }, null, null, null);
            while (partCursor != null && partCursor.moveToNext()) {
                String contentType = partCursor.getString(partCursor.getColumnIndexOrThrow("ct"));
                if (ContentType.isTextType(contentType)) {
                    try {
                        long partId = partCursor.getLong(partCursor.getColumnIndexOrThrow("_id"));
                        String dataLocation = partCursor.getString(partCursor.getColumnIndexOrThrow("_data"));
                        boolean encrypted = partCursor.getInt(partCursor.getColumnIndexOrThrow("encrypted")) == 1;
                        File dataFile = new File(dataLocation);
                        InputStream is;
                        if (encrypted)
                            is = new DecryptingPartInputStream(dataFile, masterSecret);
                        else
                            is = new FileInputStream(dataFile);
                        body = (body == null) ? Util.readFullyAsString(is) : body + " " + Util.readFullyAsString(is);
                        //noinspection ResultOfMethodCallIgnored
                        dataFile.delete();
                        db.delete("part", "_id = ?", new String[] { partId + "" });
                    } catch (IOException e) {
                        Log.w("DatabaseFactory", e);
                    }
                } else if (ContentType.isAudioType(contentType) || ContentType.isImageType(contentType) || ContentType.isVideoType(contentType)) {
                    partCount++;
                }
            }
            if (!TextUtils.isEmpty(body)) {
                body = masterCipher.encryptBody(body);
                db.execSQL("UPDATE mms SET body = ?, part_count = ? WHERE _id = ?", new String[] { body, partCount + "", mmsId + "" });
            } else {
                db.execSQL("UPDATE mms SET part_count = ? WHERE _id = ?", new String[] { partCount + "", mmsId + "" });
            }
            Log.w("DatabaseFactory", "Updated body: " + body + " and part_count: " + partCount);
        }
    }
    if (fromVersion < DatabaseUpgradeActivity.TOFU_IDENTITIES_VERSION) {
        File sessionDirectory = new File(context.getFilesDir() + File.separator + "sessions");
        if (sessionDirectory.exists() && sessionDirectory.isDirectory()) {
            File[] sessions = sessionDirectory.listFiles();
            if (sessions != null) {
                for (File session : sessions) {
                    String name = session.getName();
                    if (name.matches("[0-9]+")) {
                        long recipientId = Long.parseLong(name);
                        IdentityKey identityKey = null;
                        if (identityKey != null) {
                            MasterCipher masterCipher = new MasterCipher(masterSecret);
                            String identityKeyString = Base64.encodeBytes(identityKey.serialize());
                            String macString = Base64.encodeBytes(masterCipher.getMacFor(recipientId + identityKeyString));
                            db.execSQL("REPLACE INTO identities (recipient, key, mac) VALUES (?, ?, ?)", new String[] { recipientId + "", identityKeyString, macString });
                        }
                    }
                }
            }
        }
    }
    if (fromVersion < DatabaseUpgradeActivity.ASYMMETRIC_MASTER_SECRET_FIX_VERSION) {
        if (!MasterSecretUtil.hasAsymmericMasterSecret(context)) {
            MasterSecretUtil.generateAsymmetricMasterSecret(context, masterSecret);
            MasterCipher masterCipher = new MasterCipher(masterSecret);
            Cursor cursor = null;
            try {
                cursor = db.query(SmsDatabase.TABLE_NAME, new String[] { SmsDatabase.ID, SmsDatabase.BODY, SmsDatabase.TYPE }, SmsDatabase.TYPE + " & ? == 0", new String[] { String.valueOf(SmsDatabase.Types.ENCRYPTION_MASK) }, null, null, null);
                while (cursor.moveToNext()) {
                    long id = cursor.getLong(0);
                    String body = cursor.getString(1);
                    long type = cursor.getLong(2);
                    String encryptedBody = masterCipher.encryptBody(body);
                    ContentValues update = new ContentValues();
                    update.put(SmsDatabase.BODY, encryptedBody);
                    update.put(SmsDatabase.TYPE, type | SmsDatabase.Types.ENCRYPTION_SYMMETRIC_BIT);
                    db.update(SmsDatabase.TABLE_NAME, update, SmsDatabase.ID + " = ?", new String[] { String.valueOf(id) });
                }
            } finally {
                if (cursor != null)
                    cursor.close();
            }
        }
    }
    db.setTransactionSuccessful();
    db.endTransaction();
    //    DecryptingQueue.schedulePendingDecrypts(context, masterSecret);
    MessageNotifier.updateNotification(context, masterSecret);
}
Also used : ContentValues(android.content.ContentValues) InvalidMessageException(org.whispersystems.libsignal.InvalidMessageException) IdentityKey(org.whispersystems.libsignal.IdentityKey) FileInputStream(java.io.FileInputStream) DecryptingPartInputStream(org.thoughtcrime.securesms.crypto.DecryptingPartInputStream) InputStream(java.io.InputStream) MasterCipher(org.thoughtcrime.securesms.crypto.MasterCipher) IOException(java.io.IOException) Cursor(android.database.Cursor) FileInputStream(java.io.FileInputStream) SQLiteDatabase(android.database.sqlite.SQLiteDatabase) File(java.io.File) DecryptingPartInputStream(org.thoughtcrime.securesms.crypto.DecryptingPartInputStream)

Example 98 with SQLiteDatabase

use of android.database.sqlite.SQLiteDatabase in project Signal-Android by WhisperSystems.

the class DraftDatabase method getDrafts.

public List<Draft> getDrafts(MasterCipher masterCipher, long threadId) {
    SQLiteDatabase db = databaseHelper.getReadableDatabase();
    List<Draft> results = new LinkedList<Draft>();
    Cursor cursor = null;
    try {
        cursor = db.query(TABLE_NAME, null, THREAD_ID + " = ?", new String[] { threadId + "" }, null, null, null);
        while (cursor != null && cursor.moveToNext()) {
            try {
                String encryptedType = cursor.getString(cursor.getColumnIndexOrThrow(DRAFT_TYPE));
                String encryptedValue = cursor.getString(cursor.getColumnIndexOrThrow(DRAFT_VALUE));
                results.add(new Draft(masterCipher.decryptBody(encryptedType), masterCipher.decryptBody(encryptedValue)));
            } catch (InvalidMessageException ime) {
                Log.w("DraftDatabase", ime);
            }
        }
        return results;
    } finally {
        if (cursor != null)
            cursor.close();
    }
}
Also used : InvalidMessageException(org.whispersystems.libsignal.InvalidMessageException) SQLiteDatabase(android.database.sqlite.SQLiteDatabase) Cursor(android.database.Cursor) LinkedList(java.util.LinkedList)

Example 99 with SQLiteDatabase

use of android.database.sqlite.SQLiteDatabase in project Signal-Android by WhisperSystems.

the class MmsDatabase method deleteAllThreads.

public void deleteAllThreads() {
    DatabaseFactory.getAttachmentDatabase(context).deleteAllAttachments();
    DatabaseFactory.getMmsAddressDatabase(context).deleteAllAddresses();
    SQLiteDatabase database = databaseHelper.getWritableDatabase();
    database.delete(TABLE_NAME, null, null);
}
Also used : SQLiteDatabase(android.database.sqlite.SQLiteDatabase)

Example 100 with SQLiteDatabase

use of android.database.sqlite.SQLiteDatabase in project Signal-Android by WhisperSystems.

the class MmsDatabase method incrementDeliveryReceiptCount.

public void incrementDeliveryReceiptCount(SyncMessageId messageId) {
    MmsAddressDatabase addressDatabase = DatabaseFactory.getMmsAddressDatabase(context);
    SQLiteDatabase database = databaseHelper.getWritableDatabase();
    Cursor cursor = null;
    boolean found = false;
    try {
        cursor = database.query(TABLE_NAME, new String[] { ID, THREAD_ID, MESSAGE_BOX }, DATE_SENT + " = ?", new String[] { String.valueOf(messageId.getTimetamp()) }, null, null, null, null);
        while (cursor.moveToNext()) {
            if (Types.isOutgoingMessageType(cursor.getLong(cursor.getColumnIndexOrThrow(MESSAGE_BOX)))) {
                List<String> addresses = addressDatabase.getAddressesListForId(cursor.getLong(cursor.getColumnIndexOrThrow(ID)));
                for (String storedAddress : addresses) {
                    try {
                        String ourAddress = canonicalizeNumber(context, messageId.getAddress());
                        String theirAddress = canonicalizeNumberOrGroup(context, storedAddress);
                        if (ourAddress.equals(theirAddress) || GroupUtil.isEncodedGroup(theirAddress)) {
                            long id = cursor.getLong(cursor.getColumnIndexOrThrow(ID));
                            long threadId = cursor.getLong(cursor.getColumnIndexOrThrow(THREAD_ID));
                            found = true;
                            database.execSQL("UPDATE " + TABLE_NAME + " SET " + RECEIPT_COUNT + " = " + RECEIPT_COUNT + " + 1 WHERE " + ID + " = ?", new String[] { String.valueOf(id) });
                            DatabaseFactory.getThreadDatabase(context).update(threadId, false);
                            notifyConversationListeners(threadId);
                        }
                    } catch (InvalidNumberException e) {
                        Log.w("MmsDatabase", e);
                    }
                }
            }
        }
        if (!found) {
            try {
                earlyReceiptCache.increment(messageId.getTimetamp(), canonicalizeNumber(context, messageId.getAddress()));
            } catch (InvalidNumberException e) {
                Log.w(TAG, e);
            }
        }
    } finally {
        if (cursor != null)
            cursor.close();
    }
}
Also used : SQLiteDatabase(android.database.sqlite.SQLiteDatabase) InvalidNumberException(org.whispersystems.signalservice.api.util.InvalidNumberException) Cursor(android.database.Cursor)

Aggregations

SQLiteDatabase (android.database.sqlite.SQLiteDatabase)1553 Cursor (android.database.Cursor)499 ContentValues (android.content.ContentValues)321 ArrayList (java.util.ArrayList)105 File (java.io.File)65 Test (org.junit.Test)57 SQLiteException (android.database.sqlite.SQLiteException)45 SQLiteQueryBuilder (android.database.sqlite.SQLiteQueryBuilder)44 Uri (android.net.Uri)44 ServiceStatus (com.vodafone360.people.service.ServiceStatus)42 IOException (java.io.IOException)41 SQLException (android.database.SQLException)36 SQLiteOpenHelper (android.database.sqlite.SQLiteOpenHelper)36 RemoteException (android.os.RemoteException)36 Pair (android.util.Pair)31 MediumTest (android.test.suitebuilder.annotation.MediumTest)30 Account (android.accounts.Account)29 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)25 ContactDetail (com.vodafone360.people.datatypes.ContactDetail)22 HashMap (java.util.HashMap)21