From 722e6b923fcdb511a72234cb4d06a92759059c9c Mon Sep 17 00:00:00 2001 From: parkerfath <51274393+parkerfath@users.noreply.github.com> Date: Fri, 14 Jan 2022 10:40:28 -0800 Subject: [PATCH] Change delimiter in address fields from ASCII 0 to 1 (#5863) Fixes search by sender name. Co-authored-by: Fath --- .../k9/storage/StoreSchemaDefinition.java | 2 +- .../k9/storage/migrations/MigrationTo84.kt | 60 +++++++++++++++++++ .../fsck/k9/storage/migrations/Migrations.kt | 1 + .../main/java/com/fsck/k9/mail/Address.java | 12 ++-- 4 files changed, 68 insertions(+), 7 deletions(-) create mode 100644 app/storage/src/main/java/com/fsck/k9/storage/migrations/MigrationTo84.kt diff --git a/app/storage/src/main/java/com/fsck/k9/storage/StoreSchemaDefinition.java b/app/storage/src/main/java/com/fsck/k9/storage/StoreSchemaDefinition.java index 0e75735da..88764f4f9 100644 --- a/app/storage/src/main/java/com/fsck/k9/storage/StoreSchemaDefinition.java +++ b/app/storage/src/main/java/com/fsck/k9/storage/StoreSchemaDefinition.java @@ -12,7 +12,7 @@ import timber.log.Timber; class StoreSchemaDefinition implements SchemaDefinition { - static final int DB_VERSION = 83; + static final int DB_VERSION = 84; private final MigrationsHelper migrationsHelper; diff --git a/app/storage/src/main/java/com/fsck/k9/storage/migrations/MigrationTo84.kt b/app/storage/src/main/java/com/fsck/k9/storage/migrations/MigrationTo84.kt new file mode 100644 index 000000000..01db3ebd8 --- /dev/null +++ b/app/storage/src/main/java/com/fsck/k9/storage/migrations/MigrationTo84.kt @@ -0,0 +1,60 @@ +package com.fsck.k9.storage.migrations + +import android.content.ContentValues +import android.database.sqlite.SQLiteDatabase +import androidx.core.database.getStringOrNull +import com.fsck.k9.helper.map + +/** + * Write the address fields to use ASCII 1 instead of ASCII 0 as separator. + * Separator was previously ASCII 0 but this caused problems with LIKE and searching. + */ +internal class MigrationTo84(private val db: SQLiteDatabase) { + + fun rewriteAddresses() { + val addressSets = db.rawQuery( + "SELECT id, to_list, cc_list, bcc_list, reply_to_list, sender_list FROM messages WHERE empty = 0 AND deleted = 0", + null + ).use { cursor -> + cursor.map { + + val messageId = it.getLong(0) + + messageId to AddressSet( + toList = it.getStringOrNull(1), + ccList = it.getStringOrNull(2), + bccList = it.getStringOrNull(3), + replyToList = it.getStringOrNull(4), + senderList = it.getStringOrNull(5) + ) + }.toMap() + } + + for ((messageId, addressSet) in addressSets) { + rewriteAddresses(messageId, addressSet) + } + } + + private fun rewriteAddress(inAddress: String?): String? { + return inAddress?.replace(oldChar = '\u0000', newChar = '\u0001') + } + + private fun rewriteAddresses(messageId: Long, addressSet: AddressSet) { + val cv = ContentValues().apply { + put("to_list", rewriteAddress(addressSet.toList)) + put("cc_list", rewriteAddress(addressSet.ccList)) + put("bcc_list", rewriteAddress(addressSet.bccList)) + put("reply_to_list", rewriteAddress(addressSet.replyToList)) + put("sender_list", rewriteAddress(addressSet.senderList)) + } + db.update("messages", cv, "id = ?", arrayOf(messageId.toString())) + } +} + +private data class AddressSet( + val toList: String?, + val ccList: String?, + val bccList: String?, + val replyToList: String?, + val senderList: String? +) diff --git a/app/storage/src/main/java/com/fsck/k9/storage/migrations/Migrations.kt b/app/storage/src/main/java/com/fsck/k9/storage/migrations/Migrations.kt index 51f373d30..64c020e49 100644 --- a/app/storage/src/main/java/com/fsck/k9/storage/migrations/Migrations.kt +++ b/app/storage/src/main/java/com/fsck/k9/storage/migrations/Migrations.kt @@ -29,5 +29,6 @@ object Migrations { if (oldVersion < 81) MigrationTo81(db).addNotificationsTable() if (oldVersion < 82) MigrationTo82(db).addNewMessageColumn() if (oldVersion < 83) MigrationTo83(db, migrationsHelper).rewriteHighestKnownUid() + if (oldVersion < 84) MigrationTo84(db).rewriteAddresses() } } diff --git a/mail/common/src/main/java/com/fsck/k9/mail/Address.java b/mail/common/src/main/java/com/fsck/k9/mail/Address.java index 11861011f..d90aa220a 100644 --- a/mail/common/src/main/java/com/fsck/k9/mail/Address.java +++ b/mail/common/src/main/java/com/fsck/k9/mail/Address.java @@ -219,11 +219,11 @@ public class Address implements Serializable { int pairEndIndex = 0; int addressEndIndex = 0; while (pairStartIndex < length) { - pairEndIndex = addressList.indexOf(",\u0000", pairStartIndex); + pairEndIndex = addressList.indexOf(",\u0001", pairStartIndex); if (pairEndIndex == -1) { pairEndIndex = length; } - addressEndIndex = addressList.indexOf(";\u0000", pairStartIndex); + addressEndIndex = addressList.indexOf(";\u0001", pairStartIndex); String address = null; String personal = null; if (addressEndIndex == -1 || addressEndIndex > pairEndIndex) { @@ -241,8 +241,8 @@ public class Address implements Serializable { /** * Packs an address list into a String that is very quick to read * and parse. Packed lists can be unpacked with unpackAddressList() - * The packed list is a ",\u0000" separated list of: - * address;\u0000personal + * The packed list is a ",\u0001" separated list of: + * address;\u0001personal * @param addresses Array of addresses to pack. * @return Packed addresses. */ @@ -256,13 +256,13 @@ public class Address implements Serializable { sb.append(address.getAddress()); String personal = address.getPersonal(); if (personal != null) { - sb.append(";\u0000"); + sb.append(";\u0001"); // Escape quotes in the address part on the way in personal = personal.replaceAll("\"", "\\\""); sb.append(personal); } if (i < count - 1) { - sb.append(",\u0000"); + sb.append(",\u0001"); } } return sb.toString();