From 75c20a7a2b99db8e46639a4f6a67bcdccdf50d1a Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Tue, 21 Sep 2021 10:20:21 +0200 Subject: [PATCH] handle on-device contacts with unstable system uri on device contacts (contacts not synced) have an unstable system uri. For quicksy.im contacts we can identify the contact based on the phone number instead. fixes #4174 --- .../utils/PhoneNumberUtilWrapper.java | 11 ++++- .../ui/ConversationsActivity.java | 2 +- .../android/PhoneNumberContact.java | 45 +++++++++++-------- .../siacs/conversations/entities/Entry.java | 16 +++---- .../services/QuickConversationsService.java | 14 +++++- 5 files changed, 58 insertions(+), 30 deletions(-) diff --git a/src/conversations/java/eu/siacs/conversations/utils/PhoneNumberUtilWrapper.java b/src/conversations/java/eu/siacs/conversations/utils/PhoneNumberUtilWrapper.java index 89d58e220..2f7963cf6 100644 --- a/src/conversations/java/eu/siacs/conversations/utils/PhoneNumberUtilWrapper.java +++ b/src/conversations/java/eu/siacs/conversations/utils/PhoneNumberUtilWrapper.java @@ -1,2 +1,11 @@ -package eu.siacs.conversations.utils;public class PhoneNumberUtilWrapper { +package eu.siacs.conversations.utils; + +import android.content.Context; + +import eu.siacs.conversations.xmpp.Jid; + +public class PhoneNumberUtilWrapper { + public static String toFormattedPhoneNumber(Context context, Jid jid) { + throw new AssertionError("This method is not implemented in Conversations"); + } } diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationsActivity.java b/src/main/java/eu/siacs/conversations/ui/ConversationsActivity.java index 2c2c4fe48..21032ea04 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConversationsActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ConversationsActivity.java @@ -538,6 +538,7 @@ public class ConversationsActivity extends XmppActivity implements OnConversatio @Override protected void onStart() { + super.onStart(); final int theme = findTheme(); if (this.mTheme != theme) { this.mSkipBackgroundBinding = true; @@ -546,7 +547,6 @@ public class ConversationsActivity extends XmppActivity implements OnConversatio this.mSkipBackgroundBinding = false; } mRedirectInProcess.set(false); - super.onStart(); } @Override diff --git a/src/quicksy/java/eu/siacs/conversations/android/PhoneNumberContact.java b/src/quicksy/java/eu/siacs/conversations/android/PhoneNumberContact.java index 6afb5a0d7..a8bbf88d9 100644 --- a/src/quicksy/java/eu/siacs/conversations/android/PhoneNumberContact.java +++ b/src/quicksy/java/eu/siacs/conversations/android/PhoneNumberContact.java @@ -46,30 +46,30 @@ public class PhoneNumberContact extends AbstractPhoneContact { ContactsContract.Data.PHOTO_URI, ContactsContract.Data.LOOKUP_KEY, ContactsContract.CommonDataKinds.Phone.NUMBER}; - final Cursor cursor; - try { - cursor = context.getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, PROJECTION, null, null, null); + final HashMap contacts = new HashMap<>(); + try (final Cursor cursor = context.getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, PROJECTION, null, null, null)){ + while (cursor != null && cursor.moveToNext()) { + try { + final PhoneNumberContact contact = new PhoneNumberContact(context, cursor); + final PhoneNumberContact preexisting = contacts.get(contact.getPhoneNumber()); + if (preexisting == null || preexisting.rating() < contact.rating()) { + contacts.put(contact.getPhoneNumber(), contact); + } + } catch (final IllegalArgumentException ignored) { + + } + } } catch (final Exception e) { return ImmutableMap.of(); } - final HashMap contacts = new HashMap<>(); - while (cursor != null && cursor.moveToNext()) { - try { - final PhoneNumberContact contact = new PhoneNumberContact(context, cursor); - final PhoneNumberContact preexisting = contacts.get(contact.getPhoneNumber()); - if (preexisting == null || preexisting.rating() < contact.rating()) { - contacts.put(contact.getPhoneNumber(), contact); - } - } catch (final IllegalArgumentException e) { - Log.d(Config.LOGTAG, e.getMessage()); - } - } - if (cursor != null) { - cursor.close(); - } return ImmutableMap.copyOf(contacts); } + public static PhoneNumberContact findByUriOrNumber(Collection haystack, Uri uri, String number) { + final PhoneNumberContact byUri = findByUri(haystack, uri); + return byUri != null || number == null ? byUri : findByNumber(haystack, number); + } + public static PhoneNumberContact findByUri(Collection haystack, Uri needle) { for (PhoneNumberContact contact : haystack) { if (needle.equals(contact.getLookupUri())) { @@ -78,4 +78,13 @@ public class PhoneNumberContact extends AbstractPhoneContact { } return null; } + + private static PhoneNumberContact findByNumber(Collection haystack, String needle) { + for (PhoneNumberContact contact : haystack) { + if (needle.equals(contact.getPhoneNumber())) { + return contact; + } + } + return null; + } } diff --git a/src/quicksy/java/eu/siacs/conversations/entities/Entry.java b/src/quicksy/java/eu/siacs/conversations/entities/Entry.java index 6ff19f09d..c202be470 100644 --- a/src/quicksy/java/eu/siacs/conversations/entities/Entry.java +++ b/src/quicksy/java/eu/siacs/conversations/entities/Entry.java @@ -2,6 +2,9 @@ package eu.siacs.conversations.entities; import android.util.Base64; +import com.google.common.base.Charsets; +import com.google.common.hash.Hashing; + import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; @@ -63,20 +66,15 @@ public class Entry implements Comparable { builder.append(jid.asBareJid().toEscapedString()); } } - MessageDigest md; - try { - md = MessageDigest.getInstance("SHA-1"); - } catch (NoSuchAlgorithmException e) { - return ""; - } - byte[] sha1 = md.digest(builder.toString().getBytes()); + @SuppressWarnings("deprecation") + final byte[] sha1 = Hashing.sha1().hashString(builder.toString(), Charsets.UTF_8).asBytes(); return new String(Base64.encode(sha1, Base64.DEFAULT)).trim(); } private static List ofPhoneNumberContactsAndContacts(final Collection phoneNumberContacts, Collection systemContacts) { - ArrayList entries = new ArrayList<>(); + final ArrayList entries = new ArrayList<>(); for(Contact contact : systemContacts) { - PhoneNumberContact phoneNumberContact = PhoneNumberContact.findByUri(phoneNumberContacts, contact.getSystemAccount()); + final PhoneNumberContact phoneNumberContact = PhoneNumberContact.findByUri(phoneNumberContacts, contact.getSystemAccount()); if (phoneNumberContact != null && phoneNumberContact.getPhoneNumber() != null) { Entry entry = findOrCreateByPhoneNumber(entries, phoneNumberContact.getPhoneNumber()); entry.jids.add(contact.getJid().asBareJid()); diff --git a/src/quicksy/java/eu/siacs/conversations/services/QuickConversationsService.java b/src/quicksy/java/eu/siacs/conversations/services/QuickConversationsService.java index f977758f2..14a2c1734 100644 --- a/src/quicksy/java/eu/siacs/conversations/services/QuickConversationsService.java +++ b/src/quicksy/java/eu/siacs/conversations/services/QuickConversationsService.java @@ -382,9 +382,13 @@ public class QuickConversationsService extends AbstractQuickConversationsService if (uri == null) { continue; } - PhoneNumberContact phoneNumberContact = PhoneNumberContact.findByUri(contacts, uri); + final String number = getNumber(contact); + final PhoneNumberContact phoneNumberContact = PhoneNumberContact.findByUriOrNumber(contacts, uri, number); final boolean needsCacheClean; if (phoneNumberContact != null) { + if (!uri.equals(phoneNumberContact.getLookupUri())) { + Log.d(Config.LOGTAG, "lookupUri has changed from " + uri + " to " + phoneNumberContact.getLookupUri()); + } needsCacheClean = contact.setPhoneContact(phoneNumberContact); } else { needsCacheClean = contact.unsetPhoneContact(PhoneNumberContact.class); @@ -396,6 +400,14 @@ public class QuickConversationsService extends AbstractQuickConversationsService } } + private static String getNumber(final Contact contact) { + final Jid jid = contact.getJid(); + if (jid.getLocal() != null && Config.QUICKSY_DOMAIN.equals(jid.getDomain())) { + return jid.getLocal(); + } + return null; + } + private boolean considerSync(final Account account, final Map contacts, final boolean forced) { final int hash = contacts.keySet().hashCode(); Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": consider sync of " + hash);