Search in sources :

Example 46 with ContentValues

use of android.content.ContentValues in project Signal-Android by WhisperSystems.

the class AttachmentDatabase method insertAttachment.

private AttachmentId insertAttachment(MasterSecretUnion masterSecret, long mmsId, Attachment attachment) throws MmsException {
    Log.w(TAG, "Inserting attachment for mms id: " + mmsId);
    SQLiteDatabase database = databaseHelper.getWritableDatabase();
    Pair<File, Long> partData = null;
    long uniqueId = System.currentTimeMillis();
    if (masterSecret.getMasterSecret().isPresent() && attachment.getDataUri() != null) {
        partData = setAttachmentData(masterSecret.getMasterSecret().get(), attachment.getDataUri());
        Log.w(TAG, "Wrote part to file: " + partData.first.getAbsolutePath());
    }
    ContentValues contentValues = new ContentValues();
    contentValues.put(MMS_ID, mmsId);
    contentValues.put(CONTENT_TYPE, attachment.getContentType());
    contentValues.put(TRANSFER_STATE, attachment.getTransferState());
    contentValues.put(UNIQUE_ID, uniqueId);
    contentValues.put(CONTENT_LOCATION, attachment.getLocation());
    contentValues.put(DIGEST, attachment.getDigest());
    contentValues.put(CONTENT_DISPOSITION, attachment.getKey());
    contentValues.put(NAME, attachment.getRelay());
    if (partData != null) {
        contentValues.put(DATA, partData.first.getAbsolutePath());
        contentValues.put(SIZE, partData.second);
    }
    long rowId = database.insert(TABLE_NAME, null, contentValues);
    AttachmentId attachmentId = new AttachmentId(rowId, uniqueId);
    if (partData != null) {
        Log.w(TAG, "Submitting thumbnail generation job...");
        thumbnailExecutor.submit(new ThumbnailFetchCallable(masterSecret.getMasterSecret().get(), attachmentId));
    }
    return attachmentId;
}
Also used : ContentValues(android.content.ContentValues) SQLiteDatabase(android.database.sqlite.SQLiteDatabase) File(java.io.File) AttachmentId(org.thoughtcrime.securesms.attachments.AttachmentId)

Example 47 with ContentValues

use of android.content.ContentValues 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 48 with ContentValues

use of android.content.ContentValues in project Signal-Android by WhisperSystems.

the class SmsDatabase method setAllMessagesRead.

public void setAllMessagesRead() {
    SQLiteDatabase database = databaseHelper.getWritableDatabase();
    ContentValues contentValues = new ContentValues();
    contentValues.put(READ, 1);
    database.update(TABLE_NAME, contentValues, null, null);
}
Also used : ContentValues(android.content.ContentValues) SQLiteDatabase(android.database.sqlite.SQLiteDatabase)

Example 49 with ContentValues

use of android.content.ContentValues in project Signal-Android by WhisperSystems.

the class SmsDatabase method insertCallLog.

@NonNull
private Pair<Long, Long> insertCallLog(@NonNull String number, long type, boolean unread) {
    Recipients recipients = RecipientFactory.getRecipientsFromString(context, number, true);
    long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipients);
    ContentValues values = new ContentValues(6);
    values.put(ADDRESS, number);
    values.put(ADDRESS_DEVICE_ID, 1);
    values.put(DATE_RECEIVED, System.currentTimeMillis());
    values.put(DATE_SENT, System.currentTimeMillis());
    values.put(READ, unread ? 0 : 1);
    values.put(TYPE, type);
    values.put(THREAD_ID, threadId);
    SQLiteDatabase db = databaseHelper.getWritableDatabase();
    long messageId = db.insert(TABLE_NAME, null, values);
    DatabaseFactory.getThreadDatabase(context).update(threadId, true);
    notifyConversationListeners(threadId);
    jobManager.add(new TrimThreadJob(context, threadId));
    if (unread) {
        DatabaseFactory.getThreadDatabase(context).setUnread(threadId);
    }
    return new Pair<>(messageId, threadId);
}
Also used : ContentValues(android.content.ContentValues) TrimThreadJob(org.thoughtcrime.securesms.jobs.TrimThreadJob) Recipients(org.thoughtcrime.securesms.recipients.Recipients) SQLiteDatabase(android.database.sqlite.SQLiteDatabase) Pair(android.util.Pair) NonNull(android.support.annotation.NonNull)

Example 50 with ContentValues

use of android.content.ContentValues in project Signal-Android by WhisperSystems.

the class SmsDatabase method copyMessageInbox.

public Pair<Long, Long> copyMessageInbox(long messageId) {
    Reader reader = readerFor(getMessage(messageId));
    SmsMessageRecord record = reader.getNext();
    ContentValues contentValues = new ContentValues();
    contentValues.put(TYPE, (record.getType() & ~Types.BASE_TYPE_MASK) | Types.BASE_INBOX_TYPE);
    contentValues.put(ADDRESS, record.getIndividualRecipient().getNumber());
    contentValues.put(ADDRESS_DEVICE_ID, record.getRecipientDeviceId());
    contentValues.put(DATE_RECEIVED, System.currentTimeMillis());
    contentValues.put(DATE_SENT, record.getDateSent());
    contentValues.put(PROTOCOL, 31337);
    contentValues.put(READ, 0);
    contentValues.put(BODY, record.getBody().getBody());
    contentValues.put(THREAD_ID, record.getThreadId());
    contentValues.put(EXPIRES_IN, record.getExpiresIn());
    SQLiteDatabase db = databaseHelper.getWritableDatabase();
    long newMessageId = db.insert(TABLE_NAME, null, contentValues);
    DatabaseFactory.getThreadDatabase(context).update(record.getThreadId(), true);
    notifyConversationListeners(record.getThreadId());
    jobManager.add(new TrimThreadJob(context, record.getThreadId()));
    reader.close();
    return new Pair<>(newMessageId, record.getThreadId());
}
Also used : ContentValues(android.content.ContentValues) TrimThreadJob(org.thoughtcrime.securesms.jobs.TrimThreadJob) SQLiteDatabase(android.database.sqlite.SQLiteDatabase) SmsMessageRecord(org.thoughtcrime.securesms.database.model.SmsMessageRecord) Pair(android.util.Pair)

Aggregations

ContentValues (android.content.ContentValues)3993 Cursor (android.database.Cursor)720 SQLiteDatabase (android.database.sqlite.SQLiteDatabase)638 Uri (android.net.Uri)619 Test (org.junit.Test)374 SQLException (android.database.SQLException)231 ContentResolver (android.content.ContentResolver)212 ArrayList (java.util.ArrayList)192 Intent (android.content.Intent)162 File (java.io.File)156 IOException (java.io.IOException)131 RemoteException (android.os.RemoteException)96 CursorAssert.assertThatCursor (org.hisp.dhis.android.core.data.database.CursorAssert.assertThatCursor)91 NonNull (android.support.annotation.NonNull)74 Date (java.util.Date)73 MediumTest (android.test.suitebuilder.annotation.MediumTest)63 HashMap (java.util.HashMap)62 JSONException (org.json.JSONException)60 SQLiteException (android.database.sqlite.SQLiteException)53 ContentProviderOperation (android.content.ContentProviderOperation)49