Search in sources :

Example 11 with Address

use of org.thoughtcrime.securesms.database.Address in project Signal-Android by signalapp.

the class MmsDownloadJob method storeRetrievedMms.

private void storeRetrievedMms(String contentLocation, long messageId, long threadId, RetrieveConf retrieved, int subscriptionId, @Nullable Address notificationFrom) throws MmsException, NoSessionException, DuplicateMessageException, InvalidMessageException, LegacyMessageException {
    MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
    SingleUseBlobProvider provider = SingleUseBlobProvider.getInstance();
    Optional<Address> group = Optional.absent();
    Set<Address> members = new HashSet<>();
    String body = null;
    List<Attachment> attachments = new LinkedList<>();
    Address from;
    if (retrieved.getFrom() != null) {
        from = Address.fromExternal(context, Util.toIsoString(retrieved.getFrom().getTextString()));
    } else if (notificationFrom != null) {
        from = notificationFrom;
    } else {
        from = Address.UNKNOWN;
    }
    if (retrieved.getTo() != null) {
        for (EncodedStringValue toValue : retrieved.getTo()) {
            members.add(Address.fromExternal(context, Util.toIsoString(toValue.getTextString())));
        }
    }
    if (retrieved.getCc() != null) {
        for (EncodedStringValue ccValue : retrieved.getCc()) {
            members.add(Address.fromExternal(context, Util.toIsoString(ccValue.getTextString())));
        }
    }
    members.add(from);
    members.add(Address.fromExternal(context, TextSecurePreferences.getLocalNumber(context)));
    if (retrieved.getBody() != null) {
        body = PartParser.getMessageText(retrieved.getBody());
        PduBody media = PartParser.getSupportedMediaParts(retrieved.getBody());
        for (int i = 0; i < media.getPartsNum(); i++) {
            PduPart part = media.getPart(i);
            if (part.getData() != null) {
                Uri uri = provider.createUri(part.getData());
                String name = null;
                if (part.getName() != null)
                    name = Util.toIsoString(part.getName());
                attachments.add(new UriAttachment(uri, Util.toIsoString(part.getContentType()), AttachmentDatabase.TRANSFER_PROGRESS_DONE, part.getData().length, name, false));
            }
        }
    }
    if (members.size() > 2) {
        group = Optional.of(Address.fromSerialized(DatabaseFactory.getGroupDatabase(context).getOrCreateGroupForMembers(new LinkedList<>(members), true)));
    }
    IncomingMediaMessage message = new IncomingMediaMessage(from, group, body, retrieved.getDate() * 1000L, attachments, subscriptionId, 0, false);
    Optional<InsertResult> insertResult = database.insertMessageInbox(message, contentLocation, threadId);
    if (insertResult.isPresent()) {
        database.delete(messageId);
        MessageNotifier.updateNotification(context, insertResult.get().getThreadId());
    }
}
Also used : InsertResult(org.thoughtcrime.securesms.database.MessagingDatabase.InsertResult) EncodedStringValue(com.google.android.mms.pdu_alt.EncodedStringValue) Address(org.thoughtcrime.securesms.database.Address) PduBody(com.google.android.mms.pdu_alt.PduBody) IncomingMediaMessage(org.thoughtcrime.securesms.mms.IncomingMediaMessage) UriAttachment(org.thoughtcrime.securesms.attachments.UriAttachment) Attachment(org.thoughtcrime.securesms.attachments.Attachment) Uri(android.net.Uri) LinkedList(java.util.LinkedList) SingleUseBlobProvider(org.thoughtcrime.securesms.providers.SingleUseBlobProvider) PduPart(com.google.android.mms.pdu_alt.PduPart) UriAttachment(org.thoughtcrime.securesms.attachments.UriAttachment) MmsDatabase(org.thoughtcrime.securesms.database.MmsDatabase) HashSet(java.util.HashSet)

Example 12 with Address

use of org.thoughtcrime.securesms.database.Address in project Signal-Android by signalapp.

the class DirectoryHelper method updateContactsDatabase.

private static void updateContactsDatabase(@NonNull Context context, @NonNull List<Address> activeAddresses, boolean removeMissing) {
    Optional<AccountHolder> account = getOrCreateAccount(context);
    if (account.isPresent()) {
        try {
            DatabaseFactory.getContactsDatabase(context).setRegisteredUsers(account.get().getAccount(), activeAddresses, removeMissing);
            Cursor cursor = ContactAccessor.getInstance().getAllSystemContacts(context);
            RecipientDatabase.BulkOperationsHandle handle = DatabaseFactory.getRecipientDatabase(context).resetAllSystemContactInfo();
            try {
                while (cursor != null && cursor.moveToNext()) {
                    String number = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Phone.NUMBER));
                    if (!TextUtils.isEmpty(number)) {
                        Address address = Address.fromExternal(context, number);
                        String displayName = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
                        String contactPhotoUri = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Phone.PHOTO_URI));
                        String contactLabel = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Phone.LABEL));
                        Uri contactUri = ContactsContract.Contacts.getLookupUri(cursor.getLong(cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Phone._ID)), cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Phone.LOOKUP_KEY)));
                        handle.setSystemContactInfo(address, displayName, contactPhotoUri, contactLabel, contactUri.toString());
                    }
                }
            } finally {
                handle.finish();
            }
        } catch (RemoteException | OperationApplicationException e) {
            Log.w(TAG, e);
        }
    }
}
Also used : RecipientDatabase(org.thoughtcrime.securesms.database.RecipientDatabase) Address(org.thoughtcrime.securesms.database.Address) Cursor(android.database.Cursor) RemoteException(android.os.RemoteException) Uri(android.net.Uri) OperationApplicationException(android.content.OperationApplicationException)

Example 13 with Address

use of org.thoughtcrime.securesms.database.Address in project Signal-Android by signalapp.

the class DirectoryHelper method notifyNewUsers.

private static void notifyNewUsers(@NonNull Context context, @NonNull List<Address> newUsers) {
    if (!TextSecurePreferences.isNewContactsNotificationEnabled(context))
        return;
    for (Address newUser : newUsers) {
        if (!SessionUtil.hasSession(context, newUser) && !Util.isOwnNumber(context, newUser)) {
            IncomingJoinedMessage message = new IncomingJoinedMessage(newUser);
            Optional<InsertResult> insertResult = DatabaseFactory.getSmsDatabase(context).insertMessageInbox(message);
            if (insertResult.isPresent()) {
                int hour = Calendar.getInstance().get(Calendar.HOUR_OF_DAY);
                if (hour >= 9 && hour < 23) {
                    MessageNotifier.updateNotification(context, insertResult.get().getThreadId(), true);
                } else {
                    MessageNotifier.updateNotification(context, insertResult.get().getThreadId(), false);
                }
            }
        }
    }
}
Also used : InsertResult(org.thoughtcrime.securesms.database.MessagingDatabase.InsertResult) Address(org.thoughtcrime.securesms.database.Address) IncomingJoinedMessage(org.thoughtcrime.securesms.sms.IncomingJoinedMessage)

Example 14 with Address

use of org.thoughtcrime.securesms.database.Address in project Signal-Android by signalapp.

the class ClassicOpenHelper method onUpgrade.

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    db.beginTransaction();
    if (oldVersion < INTRODUCED_IDENTITIES_VERSION) {
        db.execSQL("CREATE TABLE identities (_id INTEGER PRIMARY KEY, key TEXT UNIQUE, name TEXT UNIQUE, mac TEXT);");
    }
    if (oldVersion < INTRODUCED_INDEXES_VERSION) {
        executeStatements(db, new String[] { "CREATE INDEX IF NOT EXISTS sms_thread_id_index ON sms (thread_id);", "CREATE INDEX IF NOT EXISTS sms_read_index ON sms (read);", "CREATE INDEX IF NOT EXISTS sms_read_and_thread_id_index ON sms (read,thread_id);", "CREATE INDEX IF NOT EXISTS sms_type_index ON sms (type);" });
        executeStatements(db, new String[] { "CREATE INDEX IF NOT EXISTS mms_thread_id_index ON mms (thread_id);", "CREATE INDEX IF NOT EXISTS mms_read_index ON mms (read);", "CREATE INDEX IF NOT EXISTS mms_read_and_thread_id_index ON mms (read,thread_id);", "CREATE INDEX IF NOT EXISTS mms_message_box_index ON mms (msg_box);" });
        executeStatements(db, new String[] { "CREATE INDEX IF NOT EXISTS part_mms_id_index ON part (mid);" });
        executeStatements(db, new String[] { "CREATE INDEX IF NOT EXISTS thread_recipient_ids_index ON thread (recipient_ids);" });
        executeStatements(db, new String[] { "CREATE INDEX IF NOT EXISTS mms_addresses_mms_id_index ON mms_addresses (mms_id);" });
    }
    if (oldVersion < INTRODUCED_DATE_SENT_VERSION) {
        db.execSQL("ALTER TABLE sms ADD COLUMN date_sent INTEGER;");
        db.execSQL("UPDATE sms SET date_sent = date;");
        db.execSQL("ALTER TABLE mms ADD COLUMN date_received INTEGER;");
        db.execSQL("UPDATE mms SET date_received = date;");
    }
    if (oldVersion < INTRODUCED_DRAFTS_VERSION) {
        db.execSQL("CREATE TABLE drafts (_id INTEGER PRIMARY KEY, thread_id INTEGER, type TEXT, value TEXT);");
        executeStatements(db, new String[] { "CREATE INDEX IF NOT EXISTS draft_thread_index ON drafts (thread_id);" });
    }
    if (oldVersion < INTRODUCED_NEW_TYPES_VERSION) {
        String KEY_EXCHANGE = "?TextSecureKeyExchange";
        String SYMMETRIC_ENCRYPT = "?TextSecureLocalEncrypt";
        String ASYMMETRIC_ENCRYPT = "?TextSecureAsymmetricEncrypt";
        String ASYMMETRIC_LOCAL_ENCRYPT = "?TextSecureAsymmetricLocalEncrypt";
        String PROCESSED_KEY_EXCHANGE = "?TextSecureKeyExchangd";
        String STALE_KEY_EXCHANGE = "?TextSecureKeyExchangs";
        // SMS Updates
        db.execSQL("UPDATE sms SET type = ? WHERE type = ?", new String[] { 20L + "", 1L + "" });
        db.execSQL("UPDATE sms SET type = ? WHERE type = ?", new String[] { 21L + "", 43L + "" });
        db.execSQL("UPDATE sms SET type = ? WHERE type = ?", new String[] { 22L + "", 4L + "" });
        db.execSQL("UPDATE sms SET type = ? WHERE type = ?", new String[] { 23L + "", 2L + "" });
        db.execSQL("UPDATE sms SET type = ? WHERE type = ?", new String[] { 24L + "", 5L + "" });
        db.execSQL("UPDATE sms SET type = ? WHERE type = ?", new String[] { (21L | 0x800000L) + "", 42L + "" });
        db.execSQL("UPDATE sms SET type = ? WHERE type = ?", new String[] { (23L | 0x800000L) + "", 44L + "" });
        db.execSQL("UPDATE sms SET type = ? WHERE type = ?", new String[] { (20L | 0x800000L) + "", 45L + "" });
        db.execSQL("UPDATE sms SET type = ? WHERE type = ?", new String[] { (20L | 0x800000L | 0x10000000L) + "", 46L + "" });
        db.execSQL("UPDATE sms SET type = ? WHERE type = ?", new String[] { (20L) + "", 47L + "" });
        db.execSQL("UPDATE sms SET type = ? WHERE type = ?", new String[] { (20L | 0x800000L | 0x08000000L) + "", 48L + "" });
        db.execSQL("UPDATE sms SET body = substr(body, ?), type = type | ? WHERE body LIKE ?", new String[] { (SYMMETRIC_ENCRYPT.length() + 1) + "", 0x80000000L + "", SYMMETRIC_ENCRYPT + "%" });
        db.execSQL("UPDATE sms SET body = substr(body, ?), type = type | ? WHERE body LIKE ?", new String[] { (ASYMMETRIC_LOCAL_ENCRYPT.length() + 1) + "", 0x40000000L + "", ASYMMETRIC_LOCAL_ENCRYPT + "%" });
        db.execSQL("UPDATE sms SET body = substr(body, ?), type = type | ? WHERE body LIKE ?", new String[] { (ASYMMETRIC_ENCRYPT.length() + 1) + "", (0x800000L | 0x20000000L) + "", ASYMMETRIC_ENCRYPT + "%" });
        db.execSQL("UPDATE sms SET body = substr(body, ?), type = type | ? WHERE body LIKE ?", new String[] { (KEY_EXCHANGE.length() + 1) + "", 0x8000L + "", KEY_EXCHANGE + "%" });
        db.execSQL("UPDATE sms SET body = substr(body, ?), type = type | ? WHERE body LIKE ?", new String[] { (PROCESSED_KEY_EXCHANGE.length() + 1) + "", (0x8000L | 0x2000L) + "", PROCESSED_KEY_EXCHANGE + "%" });
        db.execSQL("UPDATE sms SET body = substr(body, ?), type = type | ? WHERE body LIKE ?", new String[] { (STALE_KEY_EXCHANGE.length() + 1) + "", (0x8000L | 0x4000L) + "", STALE_KEY_EXCHANGE + "%" });
        // MMS Updates
        db.execSQL("UPDATE mms SET msg_box = ? WHERE msg_box = ?", new String[] { (20L | 0x80000000L) + "", 1 + "" });
        db.execSQL("UPDATE mms SET msg_box = ? WHERE msg_box = ?", new String[] { (23L | 0x80000000L) + "", 2 + "" });
        db.execSQL("UPDATE mms SET msg_box = ? WHERE msg_box = ?", new String[] { (21L | 0x80000000L) + "", 4 + "" });
        db.execSQL("UPDATE mms SET msg_box = ? WHERE msg_box = ?", new String[] { (24L | 0x80000000L) + "", 12 + "" });
        db.execSQL("UPDATE mms SET msg_box = ? WHERE msg_box = ?", new String[] { (21L | 0x80000000L | 0x800000L) + "", 5 + "" });
        db.execSQL("UPDATE mms SET msg_box = ? WHERE msg_box = ?", new String[] { (23L | 0x80000000L | 0x800000L) + "", 6 + "" });
        db.execSQL("UPDATE mms SET msg_box = ? WHERE msg_box = ?", new String[] { (20L | 0x20000000L | 0x800000L) + "", 7 + "" });
        db.execSQL("UPDATE mms SET msg_box = ? WHERE msg_box = ?", new String[] { (20L | 0x80000000L | 0x800000L) + "", 8 + "" });
        db.execSQL("UPDATE mms SET msg_box = ? WHERE msg_box = ?", new String[] { (20L | 0x08000000L | 0x800000L) + "", 9 + "" });
        db.execSQL("UPDATE mms SET msg_box = ? WHERE msg_box = ?", new String[] { (20L | 0x10000000L | 0x800000L) + "", 10 + "" });
        // Thread Updates
        db.execSQL("ALTER TABLE thread ADD COLUMN snippet_type INTEGER;");
        db.execSQL("UPDATE thread SET snippet = substr(snippet, ?), " + "snippet_type = ? WHERE snippet LIKE ?", new String[] { (SYMMETRIC_ENCRYPT.length() + 1) + "", 0x80000000L + "", SYMMETRIC_ENCRYPT + "%" });
        db.execSQL("UPDATE thread SET snippet = substr(snippet, ?), " + "snippet_type = ? WHERE snippet LIKE ?", new String[] { (ASYMMETRIC_LOCAL_ENCRYPT.length() + 1) + "", 0x40000000L + "", ASYMMETRIC_LOCAL_ENCRYPT + "%" });
        db.execSQL("UPDATE thread SET snippet = substr(snippet, ?), " + "snippet_type = ? WHERE snippet LIKE ?", new String[] { (ASYMMETRIC_ENCRYPT.length() + 1) + "", (0x800000L | 0x20000000L) + "", ASYMMETRIC_ENCRYPT + "%" });
        db.execSQL("UPDATE thread SET snippet = substr(snippet, ?), " + "snippet_type = ? WHERE snippet LIKE ?", new String[] { (KEY_EXCHANGE.length() + 1) + "", 0x8000L + "", KEY_EXCHANGE + "%" });
        db.execSQL("UPDATE thread SET snippet = substr(snippet, ?), " + "snippet_type = ? WHERE snippet LIKE ?", new String[] { (STALE_KEY_EXCHANGE.length() + 1) + "", (0x8000L | 0x4000L) + "", STALE_KEY_EXCHANGE + "%" });
        db.execSQL("UPDATE thread SET snippet = substr(snippet, ?), " + "snippet_type = ? WHERE snippet LIKE ?", new String[] { (PROCESSED_KEY_EXCHANGE.length() + 1) + "", (0x8000L | 0x2000L) + "", PROCESSED_KEY_EXCHANGE + "%" });
    }
    if (oldVersion < INTRODUCED_MMS_BODY_VERSION) {
        db.execSQL("ALTER TABLE mms ADD COLUMN body TEXT");
        db.execSQL("ALTER TABLE mms ADD COLUMN part_count INTEGER");
    }
    if (oldVersion < INTRODUCED_MMS_FROM_VERSION) {
        db.execSQL("ALTER TABLE mms ADD COLUMN address TEXT");
        Cursor cursor = db.query("mms_addresses", null, "type = ?", new String[] { 0x89 + "" }, null, null, null);
        while (cursor != null && cursor.moveToNext()) {
            long mmsId = cursor.getLong(cursor.getColumnIndexOrThrow("mms_id"));
            String address = cursor.getString(cursor.getColumnIndexOrThrow("address"));
            if (!TextUtils.isEmpty(address)) {
                db.execSQL("UPDATE mms SET address = ? WHERE _id = ?", new String[] { address, mmsId + "" });
            }
        }
        if (cursor != null)
            cursor.close();
    }
    if (oldVersion < INTRODUCED_TOFU_IDENTITY_VERSION) {
        db.execSQL("DROP TABLE identities");
        db.execSQL("CREATE TABLE identities (_id INTEGER PRIMARY KEY, recipient INTEGER UNIQUE, key TEXT, mac TEXT);");
    }
    if (oldVersion < INTRODUCED_PUSH_DATABASE_VERSION) {
        db.execSQL("CREATE TABLE push (_id INTEGER PRIMARY KEY, type INTEGER, source TEXT, destinations TEXT, body TEXT, TIMESTAMP INTEGER);");
        db.execSQL("ALTER TABLE part ADD COLUMN pending_push INTEGER;");
        db.execSQL("CREATE INDEX IF NOT EXISTS pending_push_index ON part (pending_push);");
    }
    if (oldVersion < INTRODUCED_GROUP_DATABASE_VERSION) {
        db.execSQL("CREATE TABLE groups (_id INTEGER PRIMARY KEY, group_id TEXT, title TEXT, members TEXT, avatar BLOB, avatar_id INTEGER, avatar_key BLOB, avatar_content_type TEXT, avatar_relay TEXT, timestamp INTEGER, active INTEGER DEFAULT 1);");
        db.execSQL("CREATE UNIQUE INDEX IF NOT EXISTS group_id_index ON groups (GROUP_ID);");
        db.execSQL("ALTER TABLE push ADD COLUMN device_id INTEGER DEFAULT 1;");
        db.execSQL("ALTER TABLE sms ADD COLUMN address_device_id INTEGER DEFAULT 1;");
        db.execSQL("ALTER TABLE mms ADD COLUMN address_device_id INTEGER DEFAULT 1;");
    }
    if (oldVersion < INTRODUCED_PUSH_FIX_VERSION) {
        db.execSQL("CREATE TEMPORARY table push_backup (_id INTEGER PRIMARY KEY, type INTEGER, source, TEXT, destinations TEXT, body TEXT, timestamp INTEGER, device_id INTEGER DEFAULT 1);");
        db.execSQL("INSERT INTO push_backup(_id, type, source, body, timestamp, device_id) SELECT _id, type, source, body, timestamp, device_id FROM push;");
        db.execSQL("DROP TABLE push");
        db.execSQL("CREATE TABLE push (_id INTEGER PRIMARY KEY, type INTEGER, source TEXT, body TEXT, timestamp INTEGER, device_id INTEGER DEFAULT 1);");
        db.execSQL("INSERT INTO push (_id, type, source, body, timestamp, device_id) SELECT _id, type, source, body, timestamp, device_id FROM push_backup;");
        db.execSQL("DROP TABLE push_backup;");
    }
    if (oldVersion < INTRODUCED_DELIVERY_RECEIPTS) {
        db.execSQL("ALTER TABLE sms ADD COLUMN delivery_receipt_count INTEGER DEFAULT 0;");
        db.execSQL("ALTER TABLE mms ADD COLUMN delivery_receipt_count INTEGER DEFAULT 0;");
        db.execSQL("CREATE INDEX IF NOT EXISTS sms_date_sent_index ON sms (date_sent);");
        db.execSQL("CREATE INDEX IF NOT EXISTS mms_date_sent_index ON mms (date);");
    }
    if (oldVersion < INTRODUCED_PART_DATA_SIZE_VERSION) {
        db.execSQL("ALTER TABLE part ADD COLUMN data_size INTEGER DEFAULT 0;");
    }
    if (oldVersion < INTRODUCED_THUMBNAILS_VERSION) {
        db.execSQL("ALTER TABLE part ADD COLUMN thumbnail TEXT;");
        db.execSQL("ALTER TABLE part ADD COLUMN aspect_ratio REAL;");
    }
    if (oldVersion < INTRODUCED_IDENTITY_COLUMN_VERSION) {
        db.execSQL("ALTER TABLE sms ADD COLUMN mismatched_identities TEXT");
        db.execSQL("ALTER TABLE mms ADD COLUMN mismatched_identities TEXT");
        db.execSQL("ALTER TABLE mms ADD COLUMN network_failures TEXT");
    }
    if (oldVersion < INTRODUCED_UNIQUE_PART_IDS_VERSION) {
        db.execSQL("ALTER TABLE part ADD COLUMN unique_id INTEGER NOT NULL DEFAULT 0");
    }
    if (oldVersion < INTRODUCED_RECIPIENT_PREFS_DB) {
        db.execSQL("CREATE TABLE recipient_preferences " + "(_id INTEGER PRIMARY KEY, recipient_ids TEXT UNIQUE, block INTEGER DEFAULT 0, " + "notification TEXT DEFAULT NULL, vibrate INTEGER DEFAULT 0, mute_until INTEGER DEFAULT 0)");
    }
    if (oldVersion < INTRODUCED_ENVELOPE_CONTENT_VERSION) {
        db.execSQL("ALTER TABLE push ADD COLUMN content TEXT");
    }
    if (oldVersion < INTRODUCED_COLOR_PREFERENCE_VERSION) {
        db.execSQL("ALTER TABLE recipient_preferences ADD COLUMN color TEXT DEFAULT NULL");
    }
    if (oldVersion < INTRODUCED_DB_OPTIMIZATIONS_VERSION) {
        db.execSQL("UPDATE mms SET date_received = (date_received * 1000), date = (date * 1000);");
        db.execSQL("CREATE INDEX IF NOT EXISTS sms_thread_date_index ON sms (thread_id, date);");
        db.execSQL("CREATE INDEX IF NOT EXISTS mms_thread_date_index ON mms (thread_id, date_received);");
    }
    if (oldVersion < INTRODUCED_INVITE_REMINDERS_VERSION) {
        db.execSQL("ALTER TABLE recipient_preferences ADD COLUMN seen_invite_reminder INTEGER DEFAULT 0");
    }
    if (oldVersion < INTRODUCED_CONVERSATION_LIST_THUMBNAILS_VERSION) {
        db.execSQL("ALTER TABLE thread ADD COLUMN snippet_uri TEXT DEFAULT NULL");
    }
    if (oldVersion < INTRODUCED_ARCHIVE_VERSION) {
        db.execSQL("ALTER TABLE thread ADD COLUMN archived INTEGER DEFAULT 0");
        db.execSQL("CREATE INDEX IF NOT EXISTS archived_index ON thread (archived)");
    }
    if (oldVersion < INTRODUCED_CONVERSATION_LIST_STATUS_VERSION) {
        db.execSQL("ALTER TABLE thread ADD COLUMN status INTEGER DEFAULT -1");
        db.execSQL("ALTER TABLE thread ADD COLUMN delivery_receipt_count INTEGER DEFAULT 0");
    }
    if (oldVersion < MIGRATED_CONVERSATION_LIST_STATUS_VERSION) {
        Cursor threadCursor = db.query("thread", new String[] { "_id" }, null, null, null, null, null);
        while (threadCursor != null && threadCursor.moveToNext()) {
            long threadId = threadCursor.getLong(threadCursor.getColumnIndexOrThrow("_id"));
            Cursor cursor = db.rawQuery("SELECT DISTINCT date AS date_received, status, " + "delivery_receipt_count FROM sms WHERE (thread_id = ?1) " + "UNION ALL SELECT DISTINCT date_received, -1 AS status, " + "delivery_receipt_count FROM mms WHERE (thread_id = ?1) " + "ORDER BY date_received DESC LIMIT 1", new String[] { threadId + "" });
            if (cursor != null && cursor.moveToNext()) {
                int status = cursor.getInt(cursor.getColumnIndexOrThrow("status"));
                int receiptCount = cursor.getInt(cursor.getColumnIndexOrThrow("delivery_receipt_count"));
                db.execSQL("UPDATE thread SET status = ?, delivery_receipt_count = ? WHERE _id = ?", new String[] { status + "", receiptCount + "", threadId + "" });
            }
        }
    }
    if (oldVersion < INTRODUCED_SUBSCRIPTION_ID_VERSION) {
        db.execSQL("ALTER TABLE recipient_preferences ADD COLUMN default_subscription_id INTEGER DEFAULT -1");
        db.execSQL("ALTER TABLE sms ADD COLUMN subscription_id INTEGER DEFAULT -1");
        db.execSQL("ALTER TABLE mms ADD COLUMN subscription_id INTEGER DEFAULT -1");
    }
    if (oldVersion < INTRODUCED_EXPIRE_MESSAGES_VERSION) {
        db.execSQL("ALTER TABLE recipient_preferences ADD COLUMN expire_messages INTEGER DEFAULT 0");
        db.execSQL("ALTER TABLE sms ADD COLUMN expires_in INTEGER DEFAULT 0");
        db.execSQL("ALTER TABLE mms ADD COLUMN expires_in INTEGER DEFAULT 0");
        db.execSQL("ALTER TABLE sms ADD COLUMN expire_started INTEGER DEFAULT 0");
        db.execSQL("ALTER TABLE mms ADD COLUMN expire_started INTEGER DEFAULT 0");
        db.execSQL("ALTER TABLE thread ADD COLUMN expires_in INTEGER DEFAULT 0");
    }
    if (oldVersion < INTRODUCED_LAST_SEEN) {
        db.execSQL("ALTER TABLE thread ADD COLUMN last_seen INTEGER DEFAULT 0");
    }
    if (oldVersion < INTRODUCED_DIGEST) {
        db.execSQL("ALTER TABLE part ADD COLUMN digest BLOB");
        db.execSQL("ALTER TABLE groups ADD COLUMN avatar_digest BLOB");
    }
    if (oldVersion < INTRODUCED_NOTIFIED) {
        db.execSQL("ALTER TABLE sms ADD COLUMN notified INTEGER DEFAULT 0");
        db.execSQL("ALTER TABLE mms ADD COLUMN notified INTEGER DEFAULT 0");
        db.execSQL("DROP INDEX sms_read_and_thread_id_index");
        db.execSQL("CREATE INDEX IF NOT EXISTS sms_read_and_notified_and_thread_id_index ON sms(read,notified,thread_id)");
        db.execSQL("DROP INDEX mms_read_and_thread_id_index");
        db.execSQL("CREATE INDEX IF NOT EXISTS mms_read_and_notified_and_thread_id_index ON mms(read,notified,thread_id)");
    }
    if (oldVersion < INTRODUCED_DOCUMENTS) {
        db.execSQL("ALTER TABLE part ADD COLUMN file_name TEXT");
    }
    if (oldVersion < INTRODUCED_FAST_PREFLIGHT) {
        db.execSQL("ALTER TABLE part ADD COLUMN fast_preflight_id TEXT");
    }
    if (oldVersion < INTRODUCED_VOICE_NOTES) {
        db.execSQL("ALTER TABLE part ADD COLUMN voice_note INTEGER DEFAULT 0");
    }
    if (oldVersion < INTRODUCED_IDENTITY_TIMESTAMP) {
        db.execSQL("ALTER TABLE identities ADD COLUMN timestamp INTEGER DEFAULT 0");
        db.execSQL("ALTER TABLE identities ADD COLUMN first_use INTEGER DEFAULT 0");
        db.execSQL("ALTER TABLE identities ADD COLUMN nonblocking_approval INTEGER DEFAULT 0");
        db.execSQL("ALTER TABLE identities ADD COLUMN verified INTEGER DEFAULT 0");
        db.execSQL("DROP INDEX archived_index");
        db.execSQL("CREATE INDEX IF NOT EXISTS archived_count_index ON thread (archived, message_count)");
    }
    if (oldVersion < SANIFY_ATTACHMENT_DOWNLOAD) {
        db.execSQL("UPDATE part SET pending_push = '2' WHERE pending_push = '1'");
    }
    if (oldVersion < NO_MORE_CANONICAL_ADDRESS_DATABASE) {
        SQLiteOpenHelper canonicalAddressDatabaseHelper = new SQLiteOpenHelper(context, "canonical_address.db", null, 1) {

            @Override
            public void onCreate(SQLiteDatabase db) {
                throw new AssertionError("No canonical address DB?");
            }

            @Override
            public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            }
        };
        SQLiteDatabase canonicalAddressDatabase = canonicalAddressDatabaseHelper.getReadableDatabase();
        NumberMigrator numberMigrator = new NumberMigrator(TextSecurePreferences.getLocalNumber(context));
        // Migrate Thread Database
        Cursor cursor = db.query("thread", new String[] { "_id", "recipient_ids" }, null, null, null, null, null);
        while (cursor != null && cursor.moveToNext()) {
            long threadId = cursor.getLong(0);
            String recipientIdsList = cursor.getString(1);
            String[] recipientIds = recipientIdsList.split(" ");
            String[] addresses = new String[recipientIds.length];
            for (int i = 0; i < recipientIds.length; i++) {
                Cursor resolved = canonicalAddressDatabase.query("canonical_addresses", new String[] { "address" }, "_id = ?", new String[] { recipientIds[i] }, null, null, null);
                if (resolved != null && resolved.moveToFirst()) {
                    String address = resolved.getString(0);
                    addresses[i] = DelimiterUtil.escape(numberMigrator.migrate(address), ' ');
                } else if (TextUtils.isEmpty(recipientIds[i]) || recipientIds[i].equals("-1")) {
                    addresses[i] = "Unknown";
                } else {
                    throw new AssertionError("Unable to resolve: " + recipientIds[i] + ", recipientIdsList: '" + recipientIdsList + "'");
                }
                if (resolved != null)
                    resolved.close();
            }
            Arrays.sort(addresses);
            ContentValues values = new ContentValues(1);
            values.put("recipient_ids", Util.join(addresses, " "));
            db.update("thread", values, "_id = ?", new String[] { String.valueOf(threadId) });
        }
        if (cursor != null)
            cursor.close();
        // Migrate Identity database
        db.execSQL("CREATE TABLE identities_migrated (_id INTEGER PRIMARY KEY, address TEXT UNIQUE, key TEXT, first_use INTEGER DEFAULT 0, timestamp INTEGER DEFAULT 0, verified INTEGER DEFAULT 0, nonblocking_approval INTEGER DEFAULT 0);");
        cursor = db.query("identities", new String[] { "_id, recipient, key, first_use, timestamp, verified, nonblocking_approval" }, null, null, null, null, null);
        while (cursor != null && cursor.moveToNext()) {
            long id = cursor.getLong(0);
            long recipientId = cursor.getLong(1);
            String key = cursor.getString(2);
            int firstUse = cursor.getInt(3);
            long timestamp = cursor.getLong(4);
            int verified = cursor.getInt(5);
            int nonblockingApproval = cursor.getInt(6);
            ContentValues values = new ContentValues(6);
            Cursor resolved = canonicalAddressDatabase.query("canonical_addresses", new String[] { "address" }, "_id = ?", new String[] { String.valueOf(recipientId) }, null, null, null);
            if (resolved != null && resolved.moveToFirst()) {
                String address = resolved.getString(0);
                values.put("address", numberMigrator.migrate(address));
                values.put("key", key);
                values.put("first_use", firstUse);
                values.put("timestamp", timestamp);
                values.put("verified", verified);
                values.put("nonblocking_approval", nonblockingApproval);
            } else {
                throw new AssertionError("Unable to resolve: " + recipientId);
            }
            if (resolved != null)
                resolved.close();
            db.insert("identities_migrated", null, values);
        }
        if (cursor != null)
            cursor.close();
        db.execSQL("DROP TABLE identities");
        db.execSQL("ALTER TABLE identities_migrated RENAME TO identities");
        // Migrate recipient preferences database
        cursor = db.query("recipient_preferences", new String[] { "_id", "recipient_ids" }, null, null, null, null, null);
        while (cursor != null && cursor.moveToNext()) {
            long id = cursor.getLong(0);
            String recipientIdsList = cursor.getString(1);
            String[] recipientIds = recipientIdsList.split(" ");
            String[] addresses = new String[recipientIds.length];
            for (int i = 0; i < recipientIds.length; i++) {
                Cursor resolved = canonicalAddressDatabase.query("canonical_addresses", new String[] { "address" }, "_id = ?", new String[] { recipientIds[i] }, null, null, null);
                if (resolved != null && resolved.moveToFirst()) {
                    String address = resolved.getString(0);
                    addresses[i] = DelimiterUtil.escape(numberMigrator.migrate(address), ' ');
                } else if (TextUtils.isEmpty(recipientIds[i]) || recipientIds[i].equals("-1")) {
                    addresses[i] = "Unknown";
                } else {
                    throw new AssertionError("Unable to resolve: " + recipientIds[i] + ", recipientIdsList: '" + recipientIdsList + "'");
                }
                if (resolved != null)
                    resolved.close();
            }
            Arrays.sort(addresses);
            ContentValues values = new ContentValues(1);
            values.put("recipient_ids", Util.join(addresses, " "));
            try {
                db.update("recipient_preferences", values, "_id = ?", new String[] { String.valueOf(id) });
            } catch (SQLiteConstraintException e) {
                Log.w(TAG, e);
                db.delete("recipient_preferences", "_id = ?", new String[] { String.valueOf(id) });
            }
        }
        if (cursor != null)
            cursor.close();
        // Migrate SMS database
        cursor = db.query("sms", new String[] { "_id", "address" }, null, null, null, null, null);
        while (cursor != null && cursor.moveToNext()) {
            long id = cursor.getLong(0);
            String address = cursor.getString(1);
            if (!TextUtils.isEmpty(address)) {
                ContentValues values = new ContentValues(1);
                values.put("address", numberMigrator.migrate(address));
                db.update("sms", values, "_id = ?", new String[] { String.valueOf(id) });
            }
        }
        if (cursor != null)
            cursor.close();
        // Migrate MMS database
        cursor = db.query("mms", new String[] { "_id", "address" }, null, null, null, null, null);
        while (cursor != null && cursor.moveToNext()) {
            long id = cursor.getLong(0);
            String address = cursor.getString(1);
            if (!TextUtils.isEmpty(address)) {
                ContentValues values = new ContentValues(1);
                values.put("address", numberMigrator.migrate(address));
                db.update("mms", values, "_id = ?", new String[] { String.valueOf(id) });
            }
        }
        if (cursor != null)
            cursor.close();
        // Migrate MmsAddressDatabase
        cursor = db.query("mms_addresses", new String[] { "_id", "address" }, null, null, null, null, null);
        while (cursor != null && cursor.moveToNext()) {
            long id = cursor.getLong(0);
            String address = cursor.getString(1);
            if (!TextUtils.isEmpty(address) && !"insert-address-token".equals(address)) {
                ContentValues values = new ContentValues(1);
                values.put("address", numberMigrator.migrate(address));
                db.update("mms_addresses", values, "_id = ?", new String[] { String.valueOf(id) });
            }
        }
        if (cursor != null)
            cursor.close();
        // Migrate SMS mismatched identities
        cursor = db.query("sms", new String[] { "_id", "mismatched_identities" }, "mismatched_identities IS NOT NULL", null, null, null, null);
        while (cursor != null && cursor.moveToNext()) {
            long id = cursor.getLong(0);
            String document = cursor.getString(1);
            if (!TextUtils.isEmpty(document)) {
                try {
                    PreCanonicalAddressIdentityMismatchList oldDocumentList = JsonUtils.fromJson(document, PreCanonicalAddressIdentityMismatchList.class);
                    List<PostCanonicalAddressIdentityMismatchDocument> newDocumentList = new LinkedList<>();
                    for (PreCanonicalAddressIdentityMismatchDocument oldDocument : oldDocumentList.list) {
                        Cursor resolved = canonicalAddressDatabase.query("canonical_addresses", new String[] { "address" }, "_id = ?", new String[] { String.valueOf(oldDocument.recipientId) }, null, null, null);
                        if (resolved != null && resolved.moveToFirst()) {
                            String address = resolved.getString(0);
                            newDocumentList.add(new PostCanonicalAddressIdentityMismatchDocument(numberMigrator.migrate(address), oldDocument.identityKey));
                        } else {
                            throw new AssertionError("Unable to resolve: " + oldDocument.recipientId);
                        }
                        if (resolved != null)
                            resolved.close();
                    }
                    ContentValues values = new ContentValues(1);
                    values.put("mismatched_identities", JsonUtils.toJson(new PostCanonicalAddressIdentityMismatchList(newDocumentList)));
                    db.update("sms", values, "_id = ?", new String[] { String.valueOf(id) });
                } catch (IOException e) {
                    Log.w(TAG, e);
                }
            }
        }
        if (cursor != null)
            cursor.close();
        // Migrate MMS mismatched identities
        cursor = db.query("mms", new String[] { "_id", "mismatched_identities" }, "mismatched_identities IS NOT NULL", null, null, null, null);
        while (cursor != null && cursor.moveToNext()) {
            long id = cursor.getLong(0);
            String document = cursor.getString(1);
            if (!TextUtils.isEmpty(document)) {
                try {
                    PreCanonicalAddressIdentityMismatchList oldDocumentList = JsonUtils.fromJson(document, PreCanonicalAddressIdentityMismatchList.class);
                    List<PostCanonicalAddressIdentityMismatchDocument> newDocumentList = new LinkedList<>();
                    for (PreCanonicalAddressIdentityMismatchDocument oldDocument : oldDocumentList.list) {
                        Cursor resolved = canonicalAddressDatabase.query("canonical_addresses", new String[] { "address" }, "_id = ?", new String[] { String.valueOf(oldDocument.recipientId) }, null, null, null);
                        if (resolved != null && resolved.moveToFirst()) {
                            String address = resolved.getString(0);
                            newDocumentList.add(new PostCanonicalAddressIdentityMismatchDocument(numberMigrator.migrate(address), oldDocument.identityKey));
                        } else {
                            throw new AssertionError("Unable to resolve: " + oldDocument.recipientId);
                        }
                        if (resolved != null)
                            resolved.close();
                    }
                    ContentValues values = new ContentValues(1);
                    values.put("mismatched_identities", JsonUtils.toJson(new PostCanonicalAddressIdentityMismatchList(newDocumentList)));
                    db.update("mms", values, "_id = ?", new String[] { String.valueOf(id) });
                } catch (IOException e) {
                    Log.w(TAG, e);
                }
            }
        }
        if (cursor != null)
            cursor.close();
        // Migrate MMS network failures
        cursor = db.query("mms", new String[] { "_id", "network_failures" }, "network_failures IS NOT NULL", null, null, null, null);
        while (cursor != null && cursor.moveToNext()) {
            long id = cursor.getLong(0);
            String document = cursor.getString(1);
            if (!TextUtils.isEmpty(document)) {
                try {
                    PreCanonicalAddressNetworkFailureList oldDocumentList = JsonUtils.fromJson(document, PreCanonicalAddressNetworkFailureList.class);
                    List<PostCanonicalAddressNetworkFailureDocument> newDocumentList = new LinkedList<>();
                    for (PreCanonicalAddressNetworkFailureDocument oldDocument : oldDocumentList.list) {
                        Cursor resolved = canonicalAddressDatabase.query("canonical_addresses", new String[] { "address" }, "_id = ?", new String[] { String.valueOf(oldDocument.recipientId) }, null, null, null);
                        if (resolved != null && resolved.moveToFirst()) {
                            String address = resolved.getString(0);
                            newDocumentList.add(new PostCanonicalAddressNetworkFailureDocument(numberMigrator.migrate(address)));
                        } else {
                            throw new AssertionError("Unable to resolve: " + oldDocument.recipientId);
                        }
                        if (resolved != null)
                            resolved.close();
                    }
                    ContentValues values = new ContentValues(1);
                    values.put("network_failures", JsonUtils.toJson(new PostCanonicalAddressNetworkFailureList(newDocumentList)));
                    db.update("mms", values, "_id = ?", new String[] { String.valueOf(id) });
                } catch (IOException e) {
                    Log.w(TAG, e);
                }
            }
        }
        // Migrate sessions
        File sessionsDirectory = new File(context.getFilesDir(), "sessions-v2");
        if (sessionsDirectory.exists() && sessionsDirectory.isDirectory()) {
            File[] sessions = sessionsDirectory.listFiles();
            for (File session : sessions) {
                try {
                    String[] sessionParts = session.getName().split("[.]");
                    long recipientId = Long.parseLong(sessionParts[0]);
                    int deviceId;
                    if (sessionParts.length > 1)
                        deviceId = Integer.parseInt(sessionParts[1]);
                    else
                        deviceId = 1;
                    Cursor resolved = canonicalAddressDatabase.query("canonical_addresses", new String[] { "address" }, "_id = ?", new String[] { String.valueOf(recipientId) }, null, null, null);
                    if (resolved != null && resolved.moveToNext()) {
                        String address = resolved.getString(0);
                        File destination = new File(session.getParentFile(), address + (deviceId != 1 ? "." + deviceId : ""));
                        if (!session.renameTo(destination)) {
                            Log.w(TAG, "Session rename failed: " + destination);
                        }
                    }
                    if (resolved != null)
                        resolved.close();
                } catch (NumberFormatException e) {
                    Log.w(TAG, e);
                }
            }
        }
    }
    if (oldVersion < NO_MORE_RECIPIENTS_PLURAL) {
        db.execSQL("ALTER TABLE groups ADD COLUMN mms INTEGER DEFAULT 0");
        Cursor cursor = db.query("thread", new String[] { "_id", "recipient_ids" }, null, null, null, null, null);
        while (cursor != null && cursor.moveToNext()) {
            long threadId = cursor.getLong(0);
            String addressListString = cursor.getString(1);
            String[] addressList = DelimiterUtil.split(addressListString, ' ');
            if (addressList.length == 1) {
                ContentValues contentValues = new ContentValues();
                contentValues.put("recipient_ids", DelimiterUtil.unescape(addressListString, ' '));
                db.update("thread", contentValues, "_id = ?", new String[] { String.valueOf(threadId) });
            } else {
                byte[] groupId = new byte[16];
                List<String> members = new LinkedList<>();
                new SecureRandom().nextBytes(groupId);
                for (String address : addressList) {
                    members.add(DelimiterUtil.escape(DelimiterUtil.unescape(address, ' '), ','));
                }
                members.add(DelimiterUtil.escape(TextSecurePreferences.getLocalNumber(context), ','));
                Collections.sort(members);
                String encodedGroupId = "__signal_mms_group__!" + Hex.toStringCondensed(groupId);
                ContentValues groupValues = new ContentValues();
                ContentValues threadValues = new ContentValues();
                groupValues.put("group_id", encodedGroupId);
                groupValues.put("members", Util.join(members, ","));
                groupValues.put("mms", 1);
                threadValues.put("recipient_ids", encodedGroupId);
                db.insert("groups", null, groupValues);
                db.update("thread", threadValues, "_id = ?", new String[] { String.valueOf(threadId) });
                db.update("recipient_preferences", threadValues, "recipient_ids = ?", new String[] { addressListString });
            }
        }
        if (cursor != null)
            cursor.close();
        cursor = db.query("recipient_preferences", new String[] { "_id", "recipient_ids" }, null, null, null, null, null);
        while (cursor != null && cursor.moveToNext()) {
            long id = cursor.getLong(0);
            String addressListString = cursor.getString(1);
            String[] addressList = DelimiterUtil.split(addressListString, ' ');
            if (addressList.length == 1) {
                ContentValues contentValues = new ContentValues();
                contentValues.put("recipient_ids", DelimiterUtil.unescape(addressListString, ' '));
                db.update("recipient_preferences", contentValues, "_id = ?", new String[] { String.valueOf(id) });
            } else {
                Log.w(TAG, "Found preferences for MMS thread that appears to be gone: " + addressListString);
                db.delete("recipient_preferences", "_id = ?", new String[] { String.valueOf(id) });
            }
        }
        if (cursor != null)
            cursor.close();
        cursor = db.rawQuery("SELECT mms._id, thread.recipient_ids FROM mms, thread WHERE mms.address IS NULL AND mms.thread_id = thread._id", null);
        while (cursor != null && cursor.moveToNext()) {
            long id = cursor.getLong(0);
            ContentValues contentValues = new ContentValues(1);
            contentValues.put("address", cursor.getString(1));
            db.update("mms", contentValues, "_id = ?", new String[] { String.valueOf(id) });
        }
        if (cursor != null)
            cursor.close();
    }
    if (oldVersion < INTERNAL_DIRECTORY) {
        db.execSQL("ALTER TABLE recipient_preferences ADD COLUMN registered INTEGER DEFAULT 0");
        OldDirectoryDatabaseHelper directoryDatabaseHelper = new OldDirectoryDatabaseHelper(context);
        SQLiteDatabase directoryDatabase = directoryDatabaseHelper.getWritableDatabase();
        Cursor cursor = directoryDatabase.query("directory", new String[] { "number", "registered" }, null, null, null, null, null);
        while (cursor != null && cursor.moveToNext()) {
            String address = new NumberMigrator(TextSecurePreferences.getLocalNumber(context)).migrate(cursor.getString(0));
            ContentValues contentValues = new ContentValues(1);
            contentValues.put("registered", cursor.getInt(1) == 1 ? 1 : 2);
            if (db.update("recipient_preferences", contentValues, "recipient_ids = ?", new String[] { address }) < 1) {
                contentValues.put("recipient_ids", address);
                db.insert("recipient_preferences", null, contentValues);
            }
        }
        if (cursor != null)
            cursor.close();
    }
    if (oldVersion < INTERNAL_SYSTEM_DISPLAY_NAME) {
        db.execSQL("ALTER TABLE recipient_preferences ADD COLUMN system_display_name TEXT DEFAULT NULL");
    }
    if (oldVersion < PROFILES) {
        db.execSQL("ALTER TABLE recipient_preferences ADD COLUMN profile_key TEXT DEFAULT NULL");
        db.execSQL("ALTER TABLE recipient_preferences ADD COLUMN signal_profile_name TEXT DEFAULT NULL");
        db.execSQL("ALTER TABLE recipient_preferences ADD COLUMN signal_profile_avatar TEXT DEFAULT NULL");
    }
    if (oldVersion < PROFILE_SHARING_APPROVAL) {
        db.execSQL("ALTER TABLE recipient_preferences ADD COLUMN profile_sharing_approval INTEGER DEFAULT 0");
    }
    if (oldVersion < UNSEEN_NUMBER_OFFER) {
        db.execSQL("ALTER TABLE thread ADD COLUMN has_sent INTEGER DEFAULT 0");
    }
    if (oldVersion < READ_RECEIPTS) {
        db.execSQL("ALTER TABLE sms ADD COLUMN read_receipt_count INTEGER DEFAULT 0");
        db.execSQL("ALTER TABLE mms ADD COLUMN read_receipt_count INTEGER DEFAULT 0");
        db.execSQL("ALTER TABLE thread ADD COLUMN read_receipt_count INTEGER DEFAULT 0");
    }
    if (oldVersion < GROUP_RECEIPT_TRACKING) {
        db.execSQL("CREATE TABLE group_receipts (_id INTEGER PRIMARY KEY, mms_id  INTEGER, address TEXT, status INTEGER, timestamp INTEGER)");
        db.execSQL("CREATE INDEX IF NOT EXISTS group_receipt_mms_id_index ON group_receipts (mms_id)");
    }
    if (oldVersion < UNREAD_COUNT_VERSION) {
        db.execSQL("ALTER TABLE thread ADD COLUMN unread_count INTEGER DEFAULT 0");
        try (Cursor cursor = db.query("thread", new String[] { "_id" }, "read = 0", null, null, null, null)) {
            while (cursor != null && cursor.moveToNext()) {
                long threadId = cursor.getLong(0);
                int unreadCount = 0;
                try (Cursor smsCursor = db.rawQuery("SELECT COUNT(*) FROM sms WHERE thread_id = ? AND read = '0'", new String[] { String.valueOf(threadId) })) {
                    if (smsCursor != null && smsCursor.moveToFirst()) {
                        unreadCount += smsCursor.getInt(0);
                    }
                }
                try (Cursor mmsCursor = db.rawQuery("SELECT COUNT(*) FROM mms WHERE thread_id = ? AND read = '0'", new String[] { String.valueOf(threadId) })) {
                    if (mmsCursor != null && mmsCursor.moveToFirst()) {
                        unreadCount += mmsCursor.getInt(0);
                    }
                }
                db.execSQL("UPDATE thread SET unread_count = ? WHERE _id = ?", new String[] { String.valueOf(unreadCount), String.valueOf(threadId) });
            }
        }
    }
    if (oldVersion < MORE_RECIPIENT_FIELDS) {
        db.execSQL("ALTER TABLE recipient_preferences ADD COLUMN system_contact_photo TEXT DEFAULT NULL");
        db.execSQL("ALTER TABLE recipient_preferences ADD COLUMN system_phone_label TEXT DEFAULT NULL");
        db.execSQL("ALTER TABLE recipient_preferences ADD COLUMN system_contact_uri TEXT DEFAULT NULL");
        if (Permissions.hasAny(context, Manifest.permission.READ_CONTACTS, Manifest.permission.WRITE_CONTACTS)) {
            try (Cursor cursor = db.query("recipient_preferences", null, null, null, null, null, null)) {
                while (cursor != null && cursor.moveToNext()) {
                    Address address = Address.fromSerialized(cursor.getString(cursor.getColumnIndexOrThrow("recipient_ids")));
                    if (address.isPhone() && !TextUtils.isEmpty(address.toPhoneString())) {
                        Uri lookup = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI, Uri.encode(address.toPhoneString()));
                        try (Cursor contactCursor = context.getContentResolver().query(lookup, new String[] { ContactsContract.PhoneLookup.DISPLAY_NAME, ContactsContract.PhoneLookup.LOOKUP_KEY, ContactsContract.PhoneLookup._ID, ContactsContract.PhoneLookup.NUMBER, ContactsContract.PhoneLookup.LABEL, ContactsContract.PhoneLookup.PHOTO_URI }, null, null, null)) {
                            if (contactCursor != null && contactCursor.moveToFirst()) {
                                ContentValues contentValues = new ContentValues(3);
                                contentValues.put("system_contact_photo", contactCursor.getString(5));
                                contentValues.put("system_phone_label", contactCursor.getString(4));
                                contentValues.put("system_contact_uri", ContactsContract.Contacts.getLookupUri(contactCursor.getLong(2), contactCursor.getString(1)).toString());
                                db.update("recipient_preferences", contentValues, "recipient_ids = ?", new String[] { address.toPhoneString() });
                            }
                        }
                    }
                }
            }
        }
    }
    db.setTransactionSuccessful();
    db.endTransaction();
}
Also used : Address(org.thoughtcrime.securesms.database.Address) Cursor(android.database.Cursor) Uri(android.net.Uri) SQLiteConstraintException(android.database.sqlite.SQLiteConstraintException) SQLiteOpenHelper(android.database.sqlite.SQLiteOpenHelper) ContentValues(android.content.ContentValues) SecureRandom(java.security.SecureRandom) IOException(java.io.IOException) LinkedList(java.util.LinkedList) SQLiteDatabase(android.database.sqlite.SQLiteDatabase) File(java.io.File)

Example 15 with Address

use of org.thoughtcrime.securesms.database.Address in project Signal-Android by signalapp.

the class GroupManager method updateGroup.

public static GroupActionResult updateGroup(@NonNull Context context, @NonNull String groupId, @NonNull Set<Recipient> members, @Nullable Bitmap avatar, @Nullable String name) throws InvalidNumberException {
    final GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(context);
    final Set<Address> memberAddresses = getMemberAddresses(members);
    final byte[] avatarBytes = BitmapUtil.toByteArray(avatar);
    memberAddresses.add(Address.fromSerialized(TextSecurePreferences.getLocalNumber(context)));
    groupDatabase.updateMembers(groupId, new LinkedList<>(memberAddresses));
    groupDatabase.updateTitle(groupId, name);
    groupDatabase.updateAvatar(groupId, avatarBytes);
    if (!GroupUtil.isMmsGroup(groupId)) {
        return sendGroupUpdate(context, groupId, memberAddresses, name, avatarBytes);
    } else {
        Recipient groupRecipient = Recipient.from(context, Address.fromSerialized(groupId), true);
        long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(groupRecipient);
        return new GroupActionResult(groupRecipient, threadId);
    }
}
Also used : Address(org.thoughtcrime.securesms.database.Address) GroupDatabase(org.thoughtcrime.securesms.database.GroupDatabase) Recipient(org.thoughtcrime.securesms.recipients.Recipient)

Aggregations

Address (org.thoughtcrime.securesms.database.Address)40 Recipient (org.thoughtcrime.securesms.recipients.Recipient)13 LinkedList (java.util.LinkedList)10 Uri (android.net.Uri)9 GroupDatabase (org.thoughtcrime.securesms.database.GroupDatabase)7 Cursor (android.database.Cursor)6 ByteString (com.google.protobuf.ByteString)6 IOException (java.io.IOException)6 File (java.io.File)5 GroupContext (org.whispersystems.signalservice.internal.push.SignalServiceProtos.GroupContext)5 NonNull (android.support.annotation.NonNull)4 Attachment (org.thoughtcrime.securesms.attachments.Attachment)4 InsertResult (org.thoughtcrime.securesms.database.MessagingDatabase.InsertResult)4 SignalServiceAttachment (org.whispersystems.signalservice.api.messages.SignalServiceAttachment)4 SignalServiceAddress (org.whispersystems.signalservice.api.push.SignalServiceAddress)4 SuppressLint (android.annotation.SuppressLint)3 Nullable (android.support.annotation.Nullable)3 HashSet (java.util.HashSet)3 List (java.util.List)3 ContentValues (android.content.ContentValues)2