Skip to content
4 changes: 2 additions & 2 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ configurations.configureEach {
exclude(module = "commons-logging")
}

val canonicalVersionCode = 421
val canonicalVersionName = "1.28.0"
val canonicalVersionCode = 424
val canonicalVersionName = "1.28.1"

val postFixSize = 10
val abiPostFix = mapOf(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ data class OpenGroup(
val room: String,
@SerialName("displayName") // This rename caters for existing data
val name: String,
val description: String?,
val description: String? = null,
val publicKey: String,
val imageId: String?,
val infoUpdates: Int,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import static org.thoughtcrime.securesms.database.MmsSmsColumns.ID;
import static org.thoughtcrime.securesms.database.MmsSmsColumns.NOTIFIED;
import static org.thoughtcrime.securesms.database.MmsSmsColumns.READ;
import static org.thoughtcrime.securesms.database.MmsSmsColumns.THREAD_ID;

import android.content.ContentValues;
import android.content.Context;
Expand Down Expand Up @@ -525,6 +526,8 @@ public int getMessagePositionInConversation(long threadId, long sentTimestamp, @
return -1;
}

// Please note this migration contain a mistake (message_id used as thread_id), it's corrected in the subsequent release,
// so you shouldn't try to fix it here.
private static void migrateLegacyCommunityAddresses(final SQLiteDatabase db, final String tableName) {
final String query = "SELECT " + ID + ", " + MmsSmsColumns.ADDRESS + " FROM " + tableName;
try (final Cursor cursor = db.rawQuery(query)) {
Expand Down Expand Up @@ -578,11 +581,80 @@ private static void migrateLegacyCommunityAddresses(final SQLiteDatabase db, fin
}
}

// This is an attempt to fix the issue in migrateLegacyCommunityAddresses
private static void migrateLegacyCommunityAddresses2(final SQLiteDatabase db, final String tableName) {
final String query = "SELECT " + ID + ", " + THREAD_ID + ", " + MmsSmsColumns.ADDRESS + " FROM " + tableName;
try (final Cursor cursor = db.rawQuery(query)) {
while (cursor.moveToNext()) {
final long messageId = cursor.getLong(0);
final long threadId = cursor.getLong(1);
final String address = cursor.getString(2);
final String newAddress;

try {
if (address.startsWith(GroupUtil.COMMUNITY_PREFIX)) {
// First, if a message has a sender being a community address, it suggests the message
// is sent by us (this is an assumption from other part of the code).
// This also means that the address will be the thread's address, if the thread address
// is indeed a community address
final String threadSql = "SELECT " + ThreadDatabase.ADDRESS + " FROM " +
ThreadDatabase.TABLE_NAME + " WHERE " + ThreadDatabase.ID + " = ?";
try (final Cursor threadCursor = db.rawQuery(threadSql, threadId)) {
if (threadCursor.moveToNext()) {
final Address threadAddress = Address.fromSerialized(threadCursor.getString(0));
if (threadAddress instanceof Address.Community) {
newAddress = threadAddress.getAddress();
} else {
// If this message has a sender being a community address, but the thread address
// is not community(!), we'll have to fall back to unsafe group id migration
final String groupId = GroupUtil.getDecodedGroupID(address);
final int dotIndex = groupId.lastIndexOf('.');
if (dotIndex > 0 && dotIndex < groupId.length() - 1) {
newAddress = new Address.Community(
groupId.substring(0, dotIndex),
groupId.substring(dotIndex + 1)
).getAddress();
} else {
Log.w(TAG, "Unable to decode group id from address: " + address);
continue;
}
}
} else {
Log.w(TAG, "Thread not found for message id = " + messageId);
// Thread not found? - this is strange but if we don't have threads these messages
// aren't visible anyway.
continue;
}
}
} else {
continue;
}
} catch (Throwable e) {
Log.e(TAG, "Error while migrating address " + address, e);
continue;
}

if (!newAddress.equals(address)) {
Log.i(TAG, "Migrating message ID=" + messageId);
ContentValues contentValues = new ContentValues(1);
contentValues.put(MmsSmsColumns.ADDRESS, newAddress);
db.update(tableName, contentValues, ID + " = ?", new String[]{String.valueOf(messageId)});
}
}
}

}

public static void migrateLegacyCommunityAddresses(final SQLiteDatabase db) {
migrateLegacyCommunityAddresses(db, SmsDatabase.TABLE_NAME);
migrateLegacyCommunityAddresses(db, MmsDatabase.TABLE_NAME);
}

public static void migrateLegacyCommunityAddresses2(final SQLiteDatabase db) {
migrateLegacyCommunityAddresses2(db, SmsDatabase.TABLE_NAME);
migrateLegacyCommunityAddresses2(db, MmsDatabase.TABLE_NAME);
}

private Cursor queryTables(String[] projection, String selection, String order, String limit) {
String reactionsColumn = "json_group_array(json_object(" +
"'" + ReactionDatabase.ROW_ID + "', " + ReactionDatabase.TABLE_NAME + "." + ReactionDatabase.ROW_ID + ", " +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import android.database.Cursor
import kotlinx.coroutines.channels.BufferOverflow
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow
import net.zetetic.database.sqlcipher.SQLiteDatabase
import org.json.JSONArray
import org.json.JSONException
import org.session.libsignal.utilities.JsonUtil.SaneJSONObject
Expand Down Expand Up @@ -86,15 +87,15 @@ class ReactionDatabase(context: Context, helper: Provider<SQLCipherOpenHelper>)
@JvmField
val CREATE_MESSAGE_ID_MMS_INDEX = arrayOf("CREATE INDEX IF NOT EXISTS reaction_message_id_mms_idx ON $TABLE_NAME ($MESSAGE_ID, $IS_MMS)")

@JvmField
val MIGRATE_REACTION_TABLE_TO_USE_RECIPIENT_SETTINGS = arrayOf(
fun migrateToDropForeignConstraint(db: SQLiteDatabase) {
// Create the new table with updated schema
"""
db.rawExecSQL(
"""
CREATE TABLE ${TABLE_NAME}_new (
$ROW_ID INTEGER PRIMARY KEY,
$MESSAGE_ID INTEGER NOT NULL,
$IS_MMS INTEGER NOT NULL,
$AUTHOR_ID INTEGER NOT NULL REFERENCES ${RecipientSettingsDatabase.TABLE_NAME} (${RecipientSettingsDatabase.COL_ADDRESS}) ON DELETE CASCADE,
$AUTHOR_ID TEXT NOT NULL,
$EMOJI TEXT NOT NULL,
$SERVER_ID TEXT NOT NULL,
$COUNT INTEGER NOT NULL,
Expand All @@ -103,27 +104,34 @@ class ReactionDatabase(context: Context, helper: Provider<SQLCipherOpenHelper>)
$DATE_RECEIVED INTEGER NOT NULL,
UNIQUE($MESSAGE_ID, $IS_MMS, $EMOJI, $AUTHOR_ID) ON CONFLICT REPLACE
)
""",
"""
)

// Copy data from the old table to the new table
"""
INSERT INTO ${TABLE_NAME}_new ($ROW_ID, $MESSAGE_ID, $IS_MMS, $AUTHOR_ID, $EMOJI, $SERVER_ID, $COUNT, $SORT_ID, $DATE_SENT, $DATE_RECEIVED)
SELECT $ROW_ID, $MESSAGE_ID, $IS_MMS, ${AUTHOR_ID}, $EMOJI, $SERVER_ID, $COUNT, $SORT_ID, $DATE_SENT, $DATE_RECEIVED
db.rawExecSQL(
"""
INSERT OR REPLACE INTO ${TABLE_NAME}_new ($ROW_ID, $MESSAGE_ID, $IS_MMS, $AUTHOR_ID, $EMOJI, $SERVER_ID, $COUNT, $SORT_ID, $DATE_SENT, $DATE_RECEIVED)
SELECT $ROW_ID, $MESSAGE_ID, $IS_MMS, $AUTHOR_ID, $EMOJI, $SERVER_ID, $COUNT, $SORT_ID, $DATE_SENT, $DATE_RECEIVED
FROM $TABLE_NAME
""",
""")

// Drop the old table and their triggers
"DROP TABLE $TABLE_NAME",
"DROP TRIGGER reactions_sms_delete",
"DROP TRIGGER reactions_mms_delete",
db.rawExecSQL("DROP TRIGGER IF EXISTS reactions_sms_delete")
db.rawExecSQL("DROP TRIGGER IF EXISTS reactions_mms_delete")
db.rawExecSQL("DROP TABLE IF EXISTS $TABLE_NAME")

// Rename the new table to the original table name
"ALTER TABLE ${TABLE_NAME}_new RENAME TO $TABLE_NAME",
db.rawExecSQL("ALTER TABLE ${TABLE_NAME}_new RENAME TO $TABLE_NAME")

// Add the necessary indexes and triggers to the new table
*CREATE_INDEXS,
*CREATE_REACTION_TRIGGERS,
)
for (indexCmd in CREATE_INDEXS) {
db.rawExecSQL(indexCmd)
}

for (triggerCmd in CREATE_REACTION_TRIGGERS) {
db.rawExecSQL(triggerCmd)
}
}

private fun readReaction(cursor: Cursor): ReactionRecord {
return ReactionRecord(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,9 +98,10 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
private static final int lokiV50 = 71;
private static final int lokiV51 = 72;
private static final int lokiV52 = 73;
private static final int lokiV53 = 74;

// Loki - onUpgrade(...) must be updated to use Loki version numbers if Signal makes any database changes
private static final int DATABASE_VERSION = lokiV52;
private static final int DATABASE_VERSION = lokiV53;
private static final int MIN_DATABASE_VERSION = lokiV7;
public static final String DATABASE_NAME = "session.db";

Expand Down Expand Up @@ -248,8 +249,8 @@ public void onCreate(SQLiteDatabase db) {
db.execSQL(ThreadDatabase.ADD_SNIPPET_CONTENT_COLUMN);

executeStatements(db, RecipientSettingsDatabase.Companion.getMIGRATION_CREATE_TABLE());
ReactionDatabase.Companion.migrateToDropForeignConstraint(db);
db.execSQL(RecipientSettingsDatabase.MIGRATE_DROP_OLD_TABLE);
executeStatements(db, ReactionDatabase.MIGRATE_REACTION_TABLE_TO_USE_RECIPIENT_SETTINGS);
db.execSQL(BlindedIdMappingDatabase.DROP_TABLE_COMMAND);
db.execSQL(ExpirationConfigurationDatabase.DROP_TABLE_COMMAND);
db.execSQL(SessionContactDatabase.getDropTableCommand());
Expand Down Expand Up @@ -570,8 +571,8 @@ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

executeStatements(db, RecipientSettingsDatabase.Companion.getMIGRATION_CREATE_TABLE());
db.execSQL(RecipientSettingsDatabase.MIGRATE_MOVE_DATA_FROM_OLD_TABLE);
ReactionDatabase.Companion.migrateToDropForeignConstraint(db);
db.execSQL(RecipientSettingsDatabase.MIGRATE_DROP_OLD_TABLE);
executeStatements(db, ReactionDatabase.MIGRATE_REACTION_TABLE_TO_USE_RECIPIENT_SETTINGS);
db.execSQL(BlindedIdMappingDatabase.DROP_TABLE_COMMAND);
db.execSQL(ExpirationConfigurationDatabase.DROP_TABLE_COMMAND);
db.execSQL(SessionContactDatabase.getDropTableCommand());
Expand All @@ -582,6 +583,10 @@ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
executeStatements(db, CommunityDatabase.Companion.getMIGRATE_DROP_OLD_TABLES());
}

if (oldVersion < lokiV53) {
MmsSmsDatabase.migrateLegacyCommunityAddresses2(db);
}

db.setTransactionSuccessful();
} finally {
db.endTransaction();
Expand Down
2 changes: 1 addition & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ kotlinVersion = "2.2.20"
kryoVersion = "5.6.2"
kspVersion = "2.2.10-2.0.2"
legacySupportV13Version = "1.0.0"
libsessionUtilAndroidVersion = "1.0.8"
libsessionUtilAndroidVersion = "1.0.8-1-g27817b4"
media3ExoplayerVersion = "1.8.0"
mockitoCoreVersion = "5.20.0"
navVersion = "2.9.4"
Expand Down