mirror of
https://github.com/bitfireAT/davx5-ose.git
synced 2025-12-23 15:07:51 -05:00
Replace visible collection IDs with steganographic encoding
This commit is contained in:
@@ -22,6 +22,8 @@ import at.bitfire.davdroid.settings.SettingsManager
|
||||
import at.bitfire.davdroid.sync.account.SystemAccountUtils
|
||||
import at.bitfire.davdroid.sync.account.setAndVerifyUserData
|
||||
import at.bitfire.davdroid.util.DavUtils.lastSegment
|
||||
import at.bitfire.davdroid.util.MARKER
|
||||
import at.bitfire.davdroid.util.encodeNumber
|
||||
import com.google.common.base.CharMatcher
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import kotlinx.coroutines.channels.awaitClose
|
||||
@@ -74,7 +76,7 @@ class LocalAddressBookStore @Inject constructor(
|
||||
sb.append(" (${service.accountName})")
|
||||
}
|
||||
// Add the collection ID for uniqueness
|
||||
sb.append(" #${info.id}")
|
||||
sb.append(MARKER + encodeNumber(info.id))
|
||||
return sb.toString()
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,8 @@ import android.accounts.Account
|
||||
import android.accounts.AccountManager
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import at.bitfire.davdroid.util.MARKER
|
||||
import at.bitfire.davdroid.util.decodeWithMarker
|
||||
import java.util.logging.Logger
|
||||
|
||||
object SystemAccountUtils {
|
||||
@@ -67,4 +69,9 @@ fun AccountManager.setAndVerifyUserData(account: Account, key: String, value: St
|
||||
Thread.sleep(100)
|
||||
}
|
||||
Logger.getGlobal().warning("AccountManager failed to set $account user data $key := $value")
|
||||
}
|
||||
}
|
||||
|
||||
fun Account.nameWithNumber(): String {
|
||||
val number = decodeWithMarker(name) ?: return name
|
||||
return name.substringBeforeLast(MARKER) + " (#" + number + ")"
|
||||
}
|
||||
|
||||
@@ -12,6 +12,9 @@ import android.os.Bundle
|
||||
import androidx.annotation.WorkerThread
|
||||
import at.bitfire.davdroid.resource.LocalAddressBookStore
|
||||
import at.bitfire.davdroid.sync.SyncDataType
|
||||
import at.bitfire.davdroid.sync.account.nameWithNumber
|
||||
import at.bitfire.davdroid.util.MARKER
|
||||
import at.bitfire.davdroid.util.decodeWithMarker
|
||||
import dagger.Lazy
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
@@ -256,7 +259,7 @@ class SyncFrameworkIntegration @Inject constructor(
|
||||
private fun anyPendingSync(accounts: List<Account>, authority: String): Boolean =
|
||||
accounts.any { account ->
|
||||
ContentResolver.isSyncPending(account, authority).also { pending ->
|
||||
logger.finer("Sync pending($account, $authority) = $pending")
|
||||
logger.finer("Sync pending(name=${account.nameWithNumber()}, type=${account.type}, $authority) = $pending")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,4 +13,40 @@ fun String.withTrailingSlash() =
|
||||
if (this.endsWith('/'))
|
||||
this
|
||||
else
|
||||
"$this/"
|
||||
"$this/"
|
||||
|
||||
const val MARKER = '\uFEFF' // Start of hidden payload
|
||||
const val ZERO = '\u200B' // Zero Width Space for 0
|
||||
const val ONE = '\u200C' // Zero Width Non-Joiner for 1
|
||||
|
||||
/**
|
||||
* Encodes a number using our own steganographic encoding scheme to hide a number in UTF-8 invisible characters.
|
||||
*/
|
||||
fun encodeNumber(num: Long): String {
|
||||
require(num >= 0) { "Only non-negative integers are supported" }
|
||||
if (num == 0L) return ZERO.toString() // Represent zero as a single zero-width space
|
||||
|
||||
val binary = num.toString(2) // e.g., 8 -> "1000"
|
||||
val builder = StringBuilder()
|
||||
for (bit in binary) {
|
||||
builder.append(
|
||||
if (bit == '0') ZERO // Zero Width Space
|
||||
else ONE // Zero Width Non-Joiner
|
||||
)
|
||||
}
|
||||
return builder.toString()
|
||||
}
|
||||
|
||||
fun decodeWithMarker(text: String): Int? {
|
||||
val markerIndex = text.indexOf(MARKER)
|
||||
if (markerIndex == -1) return null // No hidden payload
|
||||
val hiddenPart = text.substring(markerIndex + 1)
|
||||
val binary = hiddenPart.map {
|
||||
when (it) {
|
||||
ZERO -> '0'
|
||||
ONE -> '1'
|
||||
else -> throw IllegalArgumentException("Invalid hidden character")
|
||||
}
|
||||
}.joinToString("")
|
||||
return binary.toInt(2)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user