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 | 43 +++++++++++-------- .../siacs/conversations/entities/Entry.java | 16 +++---- .../services/QuickConversationsService.java | 14 +++++- 5 files changed, 57 insertions(+), 29 deletions(-) diff --git a/src/conversations/java/eu/siacs/conversations/utils/PhoneNumberUtilWrapper.java b/src/conversations/java/eu/siacs/conversations/utils/PhoneNumberUtilWrapper.java index 89d58e220d150b4e84446d5404c0cf5f8c5ff2b4..2f7963cf69d20ae746b3aff661a036606e86415f 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 2c2c4fe48256fd6f77f6822f85f8d8846f3cc207..21032ea04d94407674a20a5a744ab02665ebf8d4 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 6afb5a0d75b1620e7e7a04399fd1c72dc1537ac1..a8bbf88d9579451ba8e6c88d4df7649352531521 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); - } 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); + 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 IllegalArgumentException e) { - Log.d(Config.LOGTAG, e.getMessage()); } - } - if (cursor != null) { - cursor.close(); + } catch (final Exception e) { + return ImmutableMap.of(); } 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 6ff19f09d9303b240410c1e9e891baf2fa6e990a..c202be4707a0344143a3e6be3553e062aaa7d33d 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 f977758f2ae547e0a9a9953d16370378379c6544..14a2c1734cfb8fcd013165f57de222958e3bb49b 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);