Merge main into feat-329-logging-sync

This commit is contained in:
Jason Ross
2026-07-04 21:34:07 -05:00
committed by GitHub
5 changed files with 71 additions and 9 deletions
@@ -2,7 +2,6 @@
package org.libremail.data.local
import android.content.Context
import android.util.Log
import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.booleanPreferencesKey
@@ -15,6 +14,7 @@ import kotlinx.coroutines.withContext
import net.zetetic.database.sqlcipher.SQLiteDatabase
import org.libremail.data.security.DatabaseKeyStore
import org.libremail.data.settings.SettingsRepository
import org.libremail.reporting.AppLog
import java.io.File
import javax.inject.Inject
import javax.inject.Singleton
@@ -181,7 +181,7 @@ class AccountDataMigrator @Inject constructor(
"(SELECT COUNT(*) FROM `accounts` AS ranked WHERE ranked.`email` < `accounts`.`email`)",
)
}
Log.d(TAG, "moved account tables into the account database: $present")
AppLog.d(TAG, "moved account tables into the account database: $present")
} finally {
db.rawExecSQL("DETACH DATABASE cache;")
}
@@ -1,8 +1,8 @@
// SPDX-License-Identifier: GPL-3.0-or-later
package org.libremail.data.local
import android.util.Log
import net.zetetic.database.sqlcipher.SQLiteDatabase
import org.libremail.reporting.AppLog
import java.io.File
/**
@@ -40,6 +40,7 @@ object DatabaseEncryption {
* tables but not that pragma, and a reset version would make Room attempt a bogus migration.
*/
private fun migrate(dbFile: File, sourcePassphrase: String, targetPassphrase: String) {
AppLog.i(TAG, "converting local cache database (targetEncrypted=${targetPassphrase.isNotEmpty()})")
ensureNativeLibraryLoaded()
val dir = dbFile.parentFile ?: error("database file has no parent directory")
val tmp = File(dir, dbFile.name + ".migrate").apply { delete() }
@@ -88,7 +89,7 @@ object DatabaseEncryption {
tmp.copyTo(dbFile, overwrite = true)
tmp.delete()
}
Log.d(TAG, "local cache database converted")
AppLog.d(TAG, "local cache database converted")
}
private fun startsWithSqliteHeader(dbFile: File): Boolean {
@@ -5,7 +5,7 @@ import android.os.Build
import android.security.keystore.KeyGenParameterSpec
import android.security.keystore.KeyPermanentlyInvalidatedException
import android.security.keystore.UserNotAuthenticatedException
import android.util.Log
import org.libremail.reporting.AppLog
import javax.inject.Inject
import javax.inject.Singleton
@@ -43,7 +43,7 @@ class DatabaseKeyCipher @Inject constructor() :
override fun encrypt(plaintext: String): String = try {
super.encrypt(plaintext)
} catch (e: KeyPermanentlyInvalidatedException) {
Log.d(TAG, "replacing invalidated auth-bound key before sealing", e)
AppLog.d(TAG, "replacing invalidated auth-bound key before sealing", e)
deleteKey()
super.encrypt(plaintext)
}
@@ -60,16 +60,16 @@ class DatabaseKeyCipher @Inject constructor() :
initEncryptCipher(key)
false
} catch (e: KeyPermanentlyInvalidatedException) {
Log.d(TAG, "auth-bound database key invalidated", e)
AppLog.d(TAG, "auth-bound database key invalidated", e)
true
} catch (e: UserNotAuthenticatedException) {
// Valid key, just outside its time-bound auth window — not invalidated.
Log.d(TAG, "auth-bound key outside its auth window; not invalidated", e)
AppLog.d(TAG, "auth-bound key outside its auth window; not invalidated", e)
false
} catch (e: Exception) {
// Never let a validity probe crash the foreground pass; a real decrypt later surfaces any
// genuine problem. Treat an unknown probe failure as "not invalidated" (don't wipe).
Log.d(TAG, "auth-bound key validity probe failed; treating as valid", e)
AppLog.d(TAG, "auth-bound key validity probe failed; treating as valid", e)
false
}
}