forked from upstream-mirrors/quik
Stricter check for phone number equality
This commit is contained in:
@@ -18,16 +18,17 @@
|
||||
*/
|
||||
package com.moez.QKSMS.filter
|
||||
|
||||
import android.telephony.PhoneNumberUtils
|
||||
import com.moez.QKSMS.util.PhoneNumberUtils
|
||||
import javax.inject.Inject
|
||||
|
||||
class PhoneNumberFilter @Inject constructor() : Filter<String>() {
|
||||
class PhoneNumberFilter @Inject constructor(
|
||||
private val phoneNumberUtils: PhoneNumberUtils
|
||||
) : Filter<String>() {
|
||||
|
||||
override fun filter(item: String, query: CharSequence): Boolean {
|
||||
val allCharactersDialable = query.all { PhoneNumberUtils.isReallyDialable(it) }
|
||||
|
||||
return allCharactersDialable && (PhoneNumberUtils.compare(item, query.toString()) ||
|
||||
PhoneNumberUtils.stripSeparators(item).contains(PhoneNumberUtils.stripSeparators(query.toString())))
|
||||
val allCharactersDialable = query.all { phoneNumberUtils.isReallyDialable(it) }
|
||||
return allCharactersDialable && (phoneNumberUtils.compare(item, query.toString()) ||
|
||||
phoneNumberUtils.normalizeNumber(item).contains(phoneNumberUtils.normalizeNumber(query.toString())))
|
||||
}
|
||||
|
||||
}
|
||||
@@ -18,20 +18,22 @@
|
||||
*/
|
||||
package com.moez.QKSMS.repository
|
||||
|
||||
import android.telephony.PhoneNumberUtils
|
||||
import com.moez.QKSMS.extensions.anyOf
|
||||
import com.moez.QKSMS.model.BlockedNumber
|
||||
import com.moez.QKSMS.util.PhoneNumberUtils
|
||||
import io.realm.Realm
|
||||
import io.realm.RealmResults
|
||||
import javax.inject.Inject
|
||||
|
||||
class BlockingRepositoryImpl @Inject constructor() : BlockingRepository {
|
||||
class BlockingRepositoryImpl @Inject constructor(
|
||||
private val phoneNumberUtils: PhoneNumberUtils
|
||||
) : BlockingRepository {
|
||||
|
||||
override fun blockNumber(vararg addresses: String) {
|
||||
Realm.getDefaultInstance().use { realm ->
|
||||
val blockedNumbers = realm.where(BlockedNumber::class.java).findAll()
|
||||
val newAddresses = addresses.filter { address ->
|
||||
blockedNumbers.none { number -> PhoneNumberUtils.compare(number.address, address) }
|
||||
blockedNumbers.none { number -> phoneNumberUtils.compare(number.address, address) }
|
||||
}
|
||||
|
||||
val maxId = realm.where(BlockedNumber::class.java)
|
||||
@@ -60,7 +62,7 @@ class BlockingRepositoryImpl @Inject constructor() : BlockingRepository {
|
||||
return Realm.getDefaultInstance().use { realm ->
|
||||
realm.where(BlockedNumber::class.java)
|
||||
.findAll()
|
||||
.any { number -> PhoneNumberUtils.compare(number.address, address) }
|
||||
.any { number -> phoneNumberUtils.compare(number.address, address) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,7 +82,7 @@ class BlockingRepositoryImpl @Inject constructor() : BlockingRepository {
|
||||
val ids = realm.where(BlockedNumber::class.java)
|
||||
.findAll()
|
||||
.filter { number ->
|
||||
addresses.any { address -> PhoneNumberUtils.compare(number.address, address) }
|
||||
addresses.any { address -> phoneNumberUtils.compare(number.address, address) }
|
||||
}
|
||||
.map { number -> number.id }
|
||||
.toLongArray()
|
||||
|
||||
@@ -21,7 +21,6 @@ package com.moez.QKSMS.repository
|
||||
import android.content.ContentUris
|
||||
import android.content.Context
|
||||
import android.provider.Telephony
|
||||
import android.telephony.PhoneNumberUtils
|
||||
import com.moez.QKSMS.compat.TelephonyCompat
|
||||
import com.moez.QKSMS.extensions.anyOf
|
||||
import com.moez.QKSMS.extensions.map
|
||||
@@ -34,6 +33,7 @@ import com.moez.QKSMS.model.Conversation
|
||||
import com.moez.QKSMS.model.Message
|
||||
import com.moez.QKSMS.model.Recipient
|
||||
import com.moez.QKSMS.model.SearchResult
|
||||
import com.moez.QKSMS.util.PhoneNumberUtils
|
||||
import com.moez.QKSMS.util.tryOrNull
|
||||
import io.realm.Case
|
||||
import io.realm.Realm
|
||||
@@ -46,7 +46,8 @@ class ConversationRepositoryImpl @Inject constructor(
|
||||
private val context: Context,
|
||||
private val conversationFilter: ConversationFilter,
|
||||
private val cursorToConversation: CursorToConversation,
|
||||
private val cursorToRecipient: CursorToRecipient
|
||||
private val cursorToRecipient: CursorToRecipient,
|
||||
private val phoneNumberUtils: PhoneNumberUtils
|
||||
) : ConversationRepository {
|
||||
|
||||
override fun getConversations(archived: Boolean): RealmResults<Conversation> {
|
||||
@@ -179,7 +180,7 @@ class ConversationRepositoryImpl @Inject constructor(
|
||||
.findAll()
|
||||
.firstOrNull { conversation ->
|
||||
conversation.recipients.size == recipients.size && conversation.recipients.map { it.address }.all { address ->
|
||||
recipients.any { recipient -> PhoneNumberUtils.compare(recipient, address) }
|
||||
recipients.any { recipient -> phoneNumberUtils.compare(recipient, address) }
|
||||
}
|
||||
}
|
||||
?.id
|
||||
@@ -363,7 +364,7 @@ class ConversationRepositoryImpl @Inject constructor(
|
||||
.map { recipient ->
|
||||
recipient.apply {
|
||||
contact = contacts.firstOrNull {
|
||||
it.numbers.any { PhoneNumberUtils.compare(recipient.address, it.address) }
|
||||
it.numbers.any { phoneNumberUtils.compare(recipient.address, it.address) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,6 @@ import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import android.os.Build
|
||||
import android.provider.Telephony
|
||||
import android.telephony.PhoneNumberUtils
|
||||
import android.telephony.SmsManager
|
||||
import androidx.core.content.contentValuesOf
|
||||
import com.google.android.mms.ContentType
|
||||
@@ -47,6 +46,7 @@ import com.moez.QKSMS.receiver.SendSmsReceiver
|
||||
import com.moez.QKSMS.receiver.SmsDeliveredReceiver
|
||||
import com.moez.QKSMS.receiver.SmsSentReceiver
|
||||
import com.moez.QKSMS.util.ImageUtils
|
||||
import com.moez.QKSMS.util.PhoneNumberUtils
|
||||
import com.moez.QKSMS.util.Preferences
|
||||
import com.moez.QKSMS.util.tryOrNull
|
||||
import io.realm.Case
|
||||
@@ -61,8 +61,9 @@ import javax.inject.Singleton
|
||||
class MessageRepositoryImpl @Inject constructor(
|
||||
private val activeConversationManager: ActiveConversationManager,
|
||||
private val context: Context,
|
||||
private val messageIds: KeyManager,
|
||||
private val imageRepository: ImageRepository,
|
||||
private val messageIds: KeyManager,
|
||||
private val phoneNumberUtils: PhoneNumberUtils,
|
||||
private val prefs: Preferences,
|
||||
private val syncRepository: SyncRepository
|
||||
) : MessageRepository {
|
||||
@@ -290,7 +291,7 @@ class MessageRepositoryImpl @Inject constructor(
|
||||
.map { vCard -> MMSPart("contact", ContentType.TEXT_VCARD, vCard) }
|
||||
|
||||
val transaction = Transaction(context)
|
||||
transaction.sendNewMessage(subId, threadId, addresses.map(PhoneNumberUtils::stripSeparators), parts, null)
|
||||
transaction.sendNewMessage(subId, threadId, addresses.map(phoneNumberUtils::normalizeNumber), parts, null)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,6 @@ import android.content.ContentResolver
|
||||
import android.content.ContentUris
|
||||
import android.net.Uri
|
||||
import android.provider.Telephony
|
||||
import android.telephony.PhoneNumberUtils
|
||||
import com.f2prateek.rx.preferences2.RxSharedPreferences
|
||||
import com.moez.QKSMS.extensions.insertOrUpdate
|
||||
import com.moez.QKSMS.extensions.map
|
||||
@@ -37,6 +36,7 @@ import com.moez.QKSMS.model.Message
|
||||
import com.moez.QKSMS.model.MmsPart
|
||||
import com.moez.QKSMS.model.Recipient
|
||||
import com.moez.QKSMS.model.SyncLog
|
||||
import com.moez.QKSMS.util.PhoneNumberUtils
|
||||
import com.moez.QKSMS.util.tryOrNull
|
||||
import io.reactivex.subjects.BehaviorSubject
|
||||
import io.reactivex.subjects.Subject
|
||||
@@ -54,6 +54,7 @@ class SyncRepositoryImpl @Inject constructor(
|
||||
private val cursorToRecipient: CursorToRecipient,
|
||||
private val cursorToContact: CursorToContact,
|
||||
private val keys: KeyManager,
|
||||
private val phoneNumberUtils: PhoneNumberUtils,
|
||||
private val rxPrefs: RxSharedPreferences
|
||||
) : SyncRepository {
|
||||
|
||||
@@ -170,7 +171,7 @@ class SyncRepositoryImpl @Inject constructor(
|
||||
syncProgress.onNext(SyncRepository.SyncProgress.Running(max, progress, false))
|
||||
cursorToRecipient.map(cursor).apply {
|
||||
contact = contacts.firstOrNull { contact ->
|
||||
contact.numbers.any { PhoneNumberUtils.compare(address, it.address) }
|
||||
contact.numbers.any { phoneNumberUtils.compare(address, it.address) }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -250,7 +251,7 @@ class SyncRepositoryImpl @Inject constructor(
|
||||
val updatedRecipients = recipients.map { recipient ->
|
||||
recipient.apply {
|
||||
contact = contacts.firstOrNull {
|
||||
it.numbers.any { PhoneNumberUtils.compare(recipient.address, it.address) }
|
||||
it.numbers.any { phoneNumberUtils.compare(recipient.address, it.address) }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -264,7 +265,7 @@ class SyncRepositoryImpl @Inject constructor(
|
||||
override fun syncContact(address: String): Boolean {
|
||||
// See if there's a contact that matches this phone number
|
||||
var contact = getContacts().firstOrNull {
|
||||
it.numbers.any { number -> PhoneNumberUtils.compare(number.address, address) }
|
||||
it.numbers.any { number -> phoneNumberUtils.compare(number.address, address) }
|
||||
} ?: return false
|
||||
|
||||
Realm.getDefaultInstance().use { realm ->
|
||||
@@ -277,7 +278,7 @@ class SyncRepositoryImpl @Inject constructor(
|
||||
val updatedRecipients = recipients
|
||||
.filter { recipient ->
|
||||
contact.numbers.any { number ->
|
||||
PhoneNumberUtils.compare(recipient.address, number.address)
|
||||
phoneNumberUtils.compare(recipient.address, number.address)
|
||||
}
|
||||
}
|
||||
.map { recipient -> recipient.apply { this.contact = contact } }
|
||||
|
||||
@@ -20,7 +20,6 @@ package com.moez.QKSMS.util
|
||||
|
||||
import android.content.Context
|
||||
import android.provider.ContactsContract
|
||||
import android.telephony.PhoneNumberUtils
|
||||
import com.bumptech.glide.Priority
|
||||
import com.bumptech.glide.load.DataSource
|
||||
import com.bumptech.glide.load.Key
|
||||
@@ -38,11 +37,12 @@ import java.security.MessageDigest
|
||||
|
||||
class ContactImageLoader(
|
||||
private val context: Context,
|
||||
private val contactRepo: ContactRepository
|
||||
private val contactRepo: ContactRepository,
|
||||
private val phoneNumberUtils: PhoneNumberUtils
|
||||
) : ModelLoader<String, InputStream> {
|
||||
|
||||
override fun handles(model: String): Boolean {
|
||||
return PhoneNumberUtils.isGlobalPhoneNumber(model)
|
||||
return phoneNumberUtils.isPossibleNumber(model)
|
||||
}
|
||||
|
||||
override fun buildLoadData(
|
||||
@@ -51,12 +51,18 @@ class ContactImageLoader(
|
||||
height: Int,
|
||||
options: Options
|
||||
): ModelLoader.LoadData<InputStream>? {
|
||||
return ModelLoader.LoadData(ContactImageKey(model), ContactImageFetcher(context, contactRepo, model))
|
||||
return ModelLoader.LoadData(
|
||||
ContactImageKey(phoneNumberUtils.normalizeNumber(model)),
|
||||
ContactImageFetcher(context, contactRepo, model))
|
||||
}
|
||||
|
||||
class Factory(val context: Context, val prefs: Preferences) : ModelLoaderFactory<String, InputStream> {
|
||||
class Factory(
|
||||
private val context: Context,
|
||||
private val prefs: Preferences
|
||||
) : ModelLoaderFactory<String, InputStream> {
|
||||
|
||||
override fun build(multiFactory: MultiModelLoaderFactory): ContactImageLoader {
|
||||
return ContactImageLoader(context, ContactRepositoryImpl(context, prefs))
|
||||
return ContactImageLoader(context, ContactRepositoryImpl(context, prefs), PhoneNumberUtils(context))
|
||||
}
|
||||
|
||||
override fun teardown() {} // nothing to do here
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Moez Bhatti <moez.bhatti@gmail.com>
|
||||
*
|
||||
* This file is part of QKSMS.
|
||||
*
|
||||
* QKSMS is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* QKSMS is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with QKSMS. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.moez.QKSMS.util
|
||||
|
||||
import android.content.Context
|
||||
import android.telephony.PhoneNumberUtils
|
||||
import io.michaelrocks.libphonenumber.android.PhoneNumberUtil
|
||||
import io.michaelrocks.libphonenumber.android.Phonenumber
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class PhoneNumberUtils @Inject constructor(context: Context) {
|
||||
|
||||
private val countryCode = Locale.getDefault().country
|
||||
private val phoneNumberUtil = PhoneNumberUtil.createInstance(context)
|
||||
|
||||
/**
|
||||
* Android's implementation is too loose and causes false positives
|
||||
* libphonenumber is stricter but too slow
|
||||
*
|
||||
* This method will run successfully stricter checks without compromising much speed
|
||||
*/
|
||||
fun compare(first: String, second: String): Boolean {
|
||||
if (first.equals(second, true)) {
|
||||
return true
|
||||
}
|
||||
|
||||
if (PhoneNumberUtils.compare(first, second)) {
|
||||
if (phoneNumberUtil.isNumberMatch(first, second) >= PhoneNumberUtil.MatchType.NSN_MATCH) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
fun isPossibleNumber(number: CharSequence): Boolean {
|
||||
val phoneNumber = parse(number) ?: return false
|
||||
return phoneNumberUtil.isPossibleNumber(phoneNumber)
|
||||
}
|
||||
|
||||
fun isReallyDialable(digit: Char): Boolean {
|
||||
return PhoneNumberUtils.isReallyDialable(digit)
|
||||
}
|
||||
|
||||
fun formatNumber(number: CharSequence): String {
|
||||
// PhoneNumberUtil doesn't maintain country code input
|
||||
return PhoneNumberUtils.formatNumber(number.toString(), countryCode) ?: number.toString()
|
||||
}
|
||||
|
||||
fun normalizeNumber(number: String): String {
|
||||
return PhoneNumberUtils.stripSeparators(number)
|
||||
}
|
||||
|
||||
private fun parse(number: CharSequence): Phonenumber.PhoneNumber? {
|
||||
return tryOrNull(false) { phoneNumberUtil.parse(number, countryCode) }
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user