From 15bfce952cf50897002f8dca06348e38917cd571 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Fri, 23 May 2025 11:55:56 +0200 Subject: [PATCH] modify bookmarks vie respective managers --- .../conversations/entities/Bookmark.java | 10 +- .../conversations/generator/IqGenerator.java | 21 --- .../services/XmppConnectionService.java | 175 +++++++++--------- .../conversations/xmpp/XmppConnection.java | 11 -- .../xmpp/manager/AvatarManager.java | 5 + .../xmpp/manager/BookmarkManager.java | 31 +++- .../xmpp/manager/DiscoManager.java | 7 +- .../xmpp/manager/LegacyBookmarkManager.java | 22 ++- ...essageDisplayedSynchronizationManager.java | 8 +- .../xmpp/manager/NickManager.java | 12 +- .../xmpp/manager/PepManager.java | 16 ++ .../xmpp/manager/PrivateStorageManager.java | 13 ++ .../xmpp/manager/PubSubManager.java | 10 + .../android/xmpp/NodeConfiguration.java | 6 + .../xmpp/model/bookmark2/Conference.java | 4 + .../xmpp/model/bookmark2/Password.java | 12 ++ .../xmpp/model/pubsub/owner/Delete.java | 16 ++ .../android/xmpp/processor/BindProcessor.java | 18 +- 18 files changed, 243 insertions(+), 154 deletions(-) create mode 100644 src/main/java/im/conversations/android/xmpp/model/bookmark2/Password.java create mode 100644 src/main/java/im/conversations/android/xmpp/model/pubsub/owner/Delete.java diff --git a/src/main/java/eu/siacs/conversations/entities/Bookmark.java b/src/main/java/eu/siacs/conversations/entities/Bookmark.java index 3245da705a2beb0b8f3e1b5a52f86d963ddef8e2..934c10a2d48b73fda974181a46f6db4fe50c00bb 100644 --- a/src/main/java/eu/siacs/conversations/entities/Bookmark.java +++ b/src/main/java/eu/siacs/conversations/entities/Bookmark.java @@ -8,10 +8,10 @@ import com.google.common.collect.ImmutableList; import eu.siacs.conversations.utils.StringUtils; import eu.siacs.conversations.utils.UIHelper; import eu.siacs.conversations.xml.Element; -import eu.siacs.conversations.xml.Namespace; import eu.siacs.conversations.xmpp.Jid; import im.conversations.android.xmpp.model.bookmark.Storage; import im.conversations.android.xmpp.model.bookmark2.Conference; +import im.conversations.android.xmpp.model.bookmark2.Extensions; import java.lang.ref.WeakReference; import java.util.Collections; import java.util.HashMap; @@ -24,7 +24,7 @@ public class Bookmark extends Element implements ListItem { private final Account account; private WeakReference conversation; private Jid jid; - protected Element extensions = new Element("extensions", Namespace.BOOKMARKS2); + protected Extensions extensions = new Extensions(); public Bookmark(final Account account, final Jid jid) { super("conference"); @@ -90,14 +90,14 @@ public class Bookmark extends Element implements ListItem { bookmark.setAutojoin(conference.getAttributeAsBoolean("autojoin")); bookmark.setNick(conference.findChildContent("nick")); bookmark.setPassword(conference.findChildContent("password")); - final Element extensions = conference.findChild("extensions", Namespace.BOOKMARKS2); + final var extensions = conference.getExtensions(); if (extensions != null) { - bookmark.extensions = extensions; + bookmark.extensions = conference.getExtensions(); } return bookmark; } - public Element getExtensions() { + public Extensions getExtensions() { return extensions; } diff --git a/src/main/java/eu/siacs/conversations/generator/IqGenerator.java b/src/main/java/eu/siacs/conversations/generator/IqGenerator.java index fcb8273cda6dc4fda32cb0e957151421cccf8cdf..3394f9b4ec309cc9f320400d94206148d8f56fe2 100644 --- a/src/main/java/eu/siacs/conversations/generator/IqGenerator.java +++ b/src/main/java/eu/siacs/conversations/generator/IqGenerator.java @@ -6,7 +6,6 @@ import android.util.Log; import eu.siacs.conversations.Config; import eu.siacs.conversations.crypto.axolotl.AxolotlService; import eu.siacs.conversations.entities.Account; -import eu.siacs.conversations.entities.Bookmark; import eu.siacs.conversations.entities.Conversation; import eu.siacs.conversations.entities.DownloadableFile; import eu.siacs.conversations.services.MessageArchiveService; @@ -193,26 +192,6 @@ public class IqGenerator extends AbstractGenerator { return publish(AxolotlService.PEP_DEVICE_LIST, item, publishOptions); } - public Element publishBookmarkItem(final Bookmark bookmark) { - final String name = bookmark.getBookmarkName(); - final String nick = bookmark.getNick(); - final String password = bookmark.getPassword(); - final boolean autojoin = bookmark.autojoin(); - final Element conference = new Element("conference", Namespace.BOOKMARKS2); - if (name != null) { - conference.setAttribute("name", name); - } - if (nick != null) { - conference.addChild("nick").setContent(nick); - } - if (password != null) { - conference.addChild("password").setContent(password); - } - conference.setAttribute("autojoin", String.valueOf(autojoin)); - conference.addChild(bookmark.getExtensions()); - return conference; - } - public Element mdsDisplayed(final String stanzaId, final Conversation conversation) { final Jid by; if (conversation.getMode() == Conversation.MODE_MULTI) { diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index c7f9baacdbf0bc51a8040286c99a57c234b9f09d..b96cd096adbcae06e2caeaaa4b476285052a2689 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -132,9 +132,14 @@ import eu.siacs.conversations.xmpp.jingle.JingleConnectionManager; import eu.siacs.conversations.xmpp.jingle.Media; import eu.siacs.conversations.xmpp.jingle.RtpEndUserState; import eu.siacs.conversations.xmpp.mam.MamReference; +import eu.siacs.conversations.xmpp.manager.AvatarManager; import eu.siacs.conversations.xmpp.manager.BlockingManager; +import eu.siacs.conversations.xmpp.manager.BookmarkManager; import eu.siacs.conversations.xmpp.manager.DiscoManager; +import eu.siacs.conversations.xmpp.manager.LegacyBookmarkManager; +import eu.siacs.conversations.xmpp.manager.NickManager; import eu.siacs.conversations.xmpp.manager.PresenceManager; +import eu.siacs.conversations.xmpp.manager.PrivateStorageManager; import eu.siacs.conversations.xmpp.manager.RosterManager; import eu.siacs.conversations.xmpp.pep.Avatar; import eu.siacs.conversations.xmpp.pep.PublishOptions; @@ -230,16 +235,6 @@ public class XmppConnectionService extends Service { private final Set mInProgressAvatarFetches = new HashSet<>(); private final Set mOmittedPepAvatarFetches = new HashSet<>(); public final HashSet mLowPingTimeoutMode = new HashSet<>(); - private final Consumer mDefaultIqHandler = - (packet) -> { - if (packet.getType() != Iq.Type.RESULT) { - final var error = packet.getError(); - String text = error != null ? error.findChildContent("text") : null; - if (text != null) { - Log.d(Config.LOGTAG, "received iq error: " + text); - } - } - }; public DatabaseBackend databaseBackend; private final ReplacingSerialSingleThreadExecutor mContactMergerExecutor = new ReplacingSerialSingleThreadExecutor("ContactMerger"); @@ -2040,81 +2035,76 @@ public class XmppConnectionService extends Service { public void createBookmark(final Account account, final Bookmark bookmark) { account.putBookmark(bookmark); final XmppConnection connection = account.getXmppConnection(); - if (connection == null) { - Log.d( - Config.LOGTAG, - account.getJid().asBareJid() + ": no connection. ignoring bookmark creation"); - } else if (connection.getFeatures().bookmarks2()) { - Log.d( - Config.LOGTAG, - account.getJid().asBareJid() + ": pushing bookmark via Bookmarks 2"); - final Element item = mIqGenerator.publishBookmarkItem(bookmark); - pushNodeAndEnforcePublishOptions( - account, - Namespace.BOOKMARKS2, - item, - bookmark.getJid().asBareJid().toString(), - PublishOptions.persistentWhitelistAccessMaxItems()); - } else if (connection.getFeatures().bookmarksConversion()) { - pushBookmarksPep(account); + final ListenableFuture future; + if (connection.getManager(BookmarkManager.class).hasFeature()) { + future = connection.getManager(BookmarkManager.class).publish(bookmark); + } else if (connection.getManager(LegacyBookmarkManager.class).hasConversion()) { + future = + connection + .getManager(LegacyBookmarkManager.class) + .publish(account.getBookmarks()); } else { - pushBookmarksPrivateXml(account); + future = + connection + .getManager(PrivateStorageManager.class) + .publishBookmarks(account.getBookmarks()); } + Futures.addCallback( + future, + new FutureCallback() { + @Override + public void onSuccess(Void result) { + Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": created bookmark"); + } + + @Override + public void onFailure(@NonNull Throwable t) { + Log.d( + Config.LOGTAG, + account.getJid().asBareJid() + ": could not create bookmark", + t); + } + }, + MoreExecutors.directExecutor()); } public void deleteBookmark(final Account account, final Bookmark bookmark) { account.removeBookmark(bookmark); final XmppConnection connection = account.getXmppConnection(); - if (connection.getFeatures().bookmarks2()) { - final Iq request = - mIqGenerator.deleteItem( - Namespace.BOOKMARKS2, bookmark.getJid().asBareJid().toString()); - Log.d( - Config.LOGTAG, - account.getJid().asBareJid() + ": removing bookmark via Bookmarks 2"); - sendIqPacket( - account, - request, - (response) -> { - if (response.getType() == Iq.Type.ERROR) { - Log.d( - Config.LOGTAG, - account.getJid().asBareJid() - + ": unable to delete bookmark " - + response.getErrorCondition()); - } - }); - } else if (connection.getFeatures().bookmarksConversion()) { - pushBookmarksPep(account); + final ListenableFuture future; + if (connection.getManager(BookmarkManager.class).hasFeature()) { + future = + connection + .getManager(BookmarkManager.class) + .retract(bookmark.getJid().asBareJid()); + } else if (connection.getManager(LegacyBookmarkManager.class).hasConversion()) { + future = + connection + .getManager(LegacyBookmarkManager.class) + .publish(account.getBookmarks()); } else { - pushBookmarksPrivateXml(account); - } - } - - private void pushBookmarksPrivateXml(Account account) { - Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": pushing bookmarks via private xml"); - final Iq iqPacket = new Iq(Iq.Type.SET); - // TODO we have extensions for that - Element query = iqPacket.query("jabber:iq:private"); - Element storage = query.addChild("storage", "storage:bookmarks"); - for (final Bookmark bookmark : account.getBookmarks()) { - storage.addChild(bookmark); + future = + connection + .getManager(PrivateStorageManager.class) + .publishBookmarks(account.getBookmarks()); } - sendIqPacket(account, iqPacket, mDefaultIqHandler); - } + Futures.addCallback( + future, + new FutureCallback() { + @Override + public void onSuccess(Void result) { + Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": deleted bookmark"); + } - private void pushBookmarksPep(Account account) { - Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": pushing bookmarks via pep"); - final Element storage = new Element("storage", "storage:bookmarks"); - for (final Bookmark bookmark : account.getBookmarks()) { - storage.addChild(bookmark); - } - pushNodeAndEnforcePublishOptions( - account, - Namespace.BOOKMARKS, - storage, - "current", - PublishOptions.persistentWhitelistAccess()); + @Override + public void onFailure(@NonNull Throwable t) { + Log.d( + Config.LOGTAG, + account.getJid().asBareJid() + ": could not delete bookmark", + t); + } + }, + MoreExecutors.directExecutor()); } private void pushNodeAndEnforcePublishOptions( @@ -4942,7 +4932,8 @@ public class XmppConnectionService extends Service { public void notifyAccountAvatarHasChanged(final Account account) { final XmppConnection connection = account.getXmppConnection(); - if (connection != null && connection.getFeatures().bookmarksConversion()) { + // this was bookmark conversion for a bit which doesn't make sense + if (connection.getManager(AvatarManager.class).hasPepToVCardConversion()) { Log.d( Config.LOGTAG, account.getJid().asBareJid() @@ -5831,26 +5822,26 @@ public class XmppConnectionService extends Service { } public void publishDisplayName(final Account account) { - String displayName = account.getDisplayName(); - final Iq request; - if (TextUtils.isEmpty(displayName)) { - request = mIqGenerator.deleteNode(Namespace.NICK); - } else { - request = mIqGenerator.publishNick(displayName); - } + final var connection = account.getXmppConnection(); + final String displayName = account.getDisplayName(); mAvatarService.clear(account); - sendIqPacket( - account, - request, - (packet) -> { - if (packet.getType() == Iq.Type.ERROR) { + final var future = connection.getManager(NickManager.class).publish(displayName); + Futures.addCallback( + future, + new FutureCallback() { + @Override + public void onSuccess(Void result) { Log.d( Config.LOGTAG, - account.getJid().asBareJid() - + ": unable to modify nick name " - + packet); + account.getJid().asBareJid() + ": published User Nick"); } - }); + + @Override + public void onFailure(@NonNull Throwable t) { + Log.d(Config.LOGTAG, "could not publish User Nick", t); + } + }, + MoreExecutors.directExecutor()); } public void fetchMamPreferences(final Account account, final OnMamPreferencesFetched callback) { diff --git a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java index b5db98f80ab0f6c95582090b3554abe93d830545..9cd3f96409e521757219dc1462912a6078e8fdb0 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java @@ -3093,11 +3093,6 @@ public class XmppConnection implements Runnable { } } - public boolean bookmarksConversion() { - return hasDiscoFeature(account.getJid().asBareJid(), Namespace.BOOKMARKS_CONVERSION) - && pepPublishOptions(); - } - public boolean blocking() { return connection.getManager(BlockingManager.class).hasFeature(); } @@ -3262,12 +3257,6 @@ public class XmppConnection implements Runnable { return hasDiscoFeature(account.getJid().asBareJid(), Namespace.STANZA_IDS); } - public boolean bookmarks2() { - return pepPublishOptions() - && pepConfigNodeMax() - && hasDiscoFeature(account.getJid().asBareJid(), Namespace.BOOKMARKS2_COMPAT); - } - public boolean externalServiceDiscovery() { return hasDiscoFeature(account.getDomain(), Namespace.EXTERNAL_SERVICE_DISCOVERY); } diff --git a/src/main/java/eu/siacs/conversations/xmpp/manager/AvatarManager.java b/src/main/java/eu/siacs/conversations/xmpp/manager/AvatarManager.java index e173197fcfc64968af5f95142753a7ec6d74653d..7eac27a005d219363a747a00cfee1b91993dfcec 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/manager/AvatarManager.java +++ b/src/main/java/eu/siacs/conversations/xmpp/manager/AvatarManager.java @@ -4,6 +4,7 @@ import android.util.Log; import eu.siacs.conversations.Config; import eu.siacs.conversations.entities.Contact; import eu.siacs.conversations.services.XmppConnectionService; +import eu.siacs.conversations.xml.Namespace; import eu.siacs.conversations.xmpp.Jid; import eu.siacs.conversations.xmpp.XmppConnection; import eu.siacs.conversations.xmpp.pep.Avatar; @@ -61,4 +62,8 @@ public class AvatarManager extends AbstractManager { Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": deleted avatar metadata node"); } } + + public boolean hasPepToVCardConversion() { + return getManager(DiscoManager.class).hasAccountFeature(Namespace.AVATAR_CONVERSION); + } } diff --git a/src/main/java/eu/siacs/conversations/xmpp/manager/BookmarkManager.java b/src/main/java/eu/siacs/conversations/xmpp/manager/BookmarkManager.java index ab8fffab1e6138c1fa28fa39f6a988b8af49aab8..03a8cc3f3b085221e393214467bf25be2e88ecab 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/manager/BookmarkManager.java +++ b/src/main/java/eu/siacs/conversations/xmpp/manager/BookmarkManager.java @@ -16,6 +16,7 @@ import eu.siacs.conversations.xmpp.XmppConnection; import im.conversations.android.xmpp.NodeConfiguration; import im.conversations.android.xmpp.model.bookmark2.Conference; import im.conversations.android.xmpp.model.bookmark2.Nick; +import im.conversations.android.xmpp.model.bookmark2.Password; import im.conversations.android.xmpp.model.pubsub.Items; import im.conversations.android.xmpp.model.pubsub.event.Retract; import java.util.Collection; @@ -89,18 +90,24 @@ public class BookmarkManager extends AbstractBookmarkManager { } } - public ListenableFuture publishBookmark(final Jid address, final boolean autoJoin) { - return publishBookmark(address, autoJoin, null); - } - - public ListenableFuture publishBookmark( - final Jid address, final boolean autoJoin, final String nick) { + public ListenableFuture publish(final Bookmark bookmark) { + final var address = bookmark.getJid(); + final var name = bookmark.getBookmarkName(); + final var nick = bookmark.getNick(); + final String password = bookmark.getPassword(); final var itemId = address.toString(); final var conference = new Conference(); - conference.setAutoJoin(autoJoin); + conference.setAutoJoin(bookmark.autojoin()); if (nick != null) { conference.addExtension(new Nick()).setContent(nick); } + if (name != null) { + conference.setConferenceName(name); + } + if (password != null) { + conference.addExtension(new Password()).setContent(password); + } + conference.addExtension(bookmark.getExtensions()); return Futures.transform( getManager(PepManager.class) .publish(conference, itemId, NodeConfiguration.WHITELIST_MAX_ITEMS), @@ -108,7 +115,7 @@ public class BookmarkManager extends AbstractBookmarkManager { MoreExecutors.directExecutor()); } - public ListenableFuture retractBookmark(final Jid address) { + public ListenableFuture retract(final Jid address) { final var itemId = address.toString(); return Futures.transform( getManager(PepManager.class).retract(itemId, Namespace.BOOKMARKS2), @@ -132,4 +139,12 @@ public class BookmarkManager extends AbstractBookmarkManager { Log.d(Config.LOGTAG, getAccount().getJid().asBareJid() + ": purged bookmarks"); this.deleteAllItems(); } + + public boolean hasFeature() { + final var pep = getManager(PepManager.class); + final var disco = getManager(DiscoManager.class); + return pep.hasPublishOptions() + && pep.hasConfigNodeMax() + && disco.hasAccountFeature(Namespace.BOOKMARKS2_COMPAT); + } } diff --git a/src/main/java/eu/siacs/conversations/xmpp/manager/DiscoManager.java b/src/main/java/eu/siacs/conversations/xmpp/manager/DiscoManager.java index cb143bb7b96c585dabb5126f2a3c54097645696d..d13856f0be5b0d6551c8066c66107d241e0810f4 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/manager/DiscoManager.java +++ b/src/main/java/eu/siacs/conversations/xmpp/manager/DiscoManager.java @@ -331,7 +331,7 @@ public class DiscoManager extends AbstractManager { if (appSettings.isBroadcastLastActivity()) { features.add(Namespace.IDLE); } - if (connection.getFeatures().bookmarks2()) { + if (getManager(BookmarkManager.class).hasFeature()) { features.add(Namespace.BOOKMARKS2 + "+notify"); } else { features.add(Namespace.BOOKMARKS + "+notify"); @@ -427,6 +427,11 @@ public class DiscoManager extends AbstractManager { return infoQuery != null && infoQuery.hasFeature(feature); } + public boolean hasAccountFeature(final String feature) { + final var infoQuery = this.get(getAccount().getJid().asBareJid()); + return infoQuery != null && infoQuery.hasFeature(feature); + } + private void put(final Jid address, final InfoQuery infoQuery) { synchronized (this.entityInformation) { this.entityInformation.put(address, infoQuery); diff --git a/src/main/java/eu/siacs/conversations/xmpp/manager/LegacyBookmarkManager.java b/src/main/java/eu/siacs/conversations/xmpp/manager/LegacyBookmarkManager.java index e58f541de66928a4950321f52894e05224f9194a..0730ab088b671e801b661db20709129e28615e88 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/manager/LegacyBookmarkManager.java +++ b/src/main/java/eu/siacs/conversations/xmpp/manager/LegacyBookmarkManager.java @@ -1,13 +1,17 @@ package eu.siacs.conversations.xmpp.manager; import android.util.Log; +import com.google.common.util.concurrent.ListenableFuture; import eu.siacs.conversations.Config; import eu.siacs.conversations.entities.Bookmark; import eu.siacs.conversations.services.XmppConnectionService; +import eu.siacs.conversations.xml.Namespace; import eu.siacs.conversations.xmpp.Jid; import eu.siacs.conversations.xmpp.XmppConnection; +import im.conversations.android.xmpp.NodeConfiguration; import im.conversations.android.xmpp.model.bookmark.Storage; import im.conversations.android.xmpp.model.pubsub.Items; +import java.util.Collection; import java.util.Map; public class LegacyBookmarkManager extends AbstractBookmarkManager { @@ -19,9 +23,8 @@ public class LegacyBookmarkManager extends AbstractBookmarkManager { public void handleItems(final Items items) { final var account = this.getAccount(); - final var connection = this.connection; - if (connection.getFeatures().bookmarksConversion()) { - if (connection.getFeatures().bookmarks2()) { + if (this.hasConversion()) { + if (getManager(BookmarkManager.class).hasFeature()) { Log.w( Config.LOGTAG, account.getJid().asBareJid() @@ -40,4 +43,17 @@ public class LegacyBookmarkManager extends AbstractBookmarkManager { + " not detected"); } } + + public boolean hasConversion() { + return getManager(PepManager.class).hasPublishOptions() + && getManager(DiscoManager.class).hasAccountFeature(Namespace.BOOKMARKS_CONVERSION); + } + + public ListenableFuture publish(final Collection bookmarks) { + final var storage = new Storage(); + for (final var bookmark : bookmarks) { + storage.addChild(bookmark); + } + return getManager(PepManager.class).publishSingleton(storage, NodeConfiguration.WHITELIST); + } } diff --git a/src/main/java/eu/siacs/conversations/xmpp/manager/MessageDisplayedSynchronizationManager.java b/src/main/java/eu/siacs/conversations/xmpp/manager/MessageDisplayedSynchronizationManager.java index 6c1af04b382548b985b8b1adcdf817dca2ea64ee..8d2c4b65748cd1d9bb8ced1de16f47e1e4e692e9 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/manager/MessageDisplayedSynchronizationManager.java +++ b/src/main/java/eu/siacs/conversations/xmpp/manager/MessageDisplayedSynchronizationManager.java @@ -1,12 +1,10 @@ package eu.siacs.conversations.xmpp.manager; import android.util.Log; - import androidx.annotation.NonNull; import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.MoreExecutors; - import eu.siacs.conversations.Config; import eu.siacs.conversations.entities.Conversation; import eu.siacs.conversations.services.XmppConnectionService; @@ -62,7 +60,11 @@ public class MessageDisplayedSynchronizationManager extends AbstractManager { @Override public void onFailure(@NonNull Throwable t) { - Log.d(Config.LOGTAG,getAccount().getJid().asBareJid()+": could not retrieve MDS items", t); + Log.d( + Config.LOGTAG, + getAccount().getJid().asBareJid() + + ": could not retrieve MDS items", + t); } }, MoreExecutors.directExecutor()); diff --git a/src/main/java/eu/siacs/conversations/xmpp/manager/NickManager.java b/src/main/java/eu/siacs/conversations/xmpp/manager/NickManager.java index 9beeaf4c4830389614c9537393d17ecea7b51ef9..93a509551245497e40fc3c25a6144a8219f28165 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/manager/NickManager.java +++ b/src/main/java/eu/siacs/conversations/xmpp/manager/NickManager.java @@ -5,6 +5,7 @@ import com.google.common.util.concurrent.ListenableFuture; import eu.siacs.conversations.entities.Contact; import eu.siacs.conversations.services.QuickConversationsService; import eu.siacs.conversations.services.XmppConnectionService; +import eu.siacs.conversations.xml.Namespace; import eu.siacs.conversations.xmpp.Jid; import eu.siacs.conversations.xmpp.XmppConnection; import im.conversations.android.xmpp.NodeConfiguration; @@ -48,10 +49,13 @@ public class NickManager extends AbstractManager { service.updateAccountUi(); } - public ListenableFuture publishNick(final String name) { - final Nick nick = new Nick(); - nick.setContent(name); - return getManager(PepManager.class).publishSingleton(nick, NodeConfiguration.PRESENCE); + public ListenableFuture publish(final String name) { + if (Strings.isNullOrEmpty(name)) { + return getManager(PepManager.class).delete(Namespace.NICK); + } else { + return getManager(PepManager.class) + .publishSingleton(new Nick(name), NodeConfiguration.PRESENCE); + } } public void handleDelete(final Jid from) { diff --git a/src/main/java/eu/siacs/conversations/xmpp/manager/PepManager.java b/src/main/java/eu/siacs/conversations/xmpp/manager/PepManager.java index 6ba8534588cd6fcff3c0dced7b5bde417a014ff4..fd5bd6f155b9040d2ff37797021914e077486c24 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/manager/PepManager.java +++ b/src/main/java/eu/siacs/conversations/xmpp/manager/PepManager.java @@ -1,7 +1,10 @@ package eu.siacs.conversations.xmpp.manager; import android.content.Context; +import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.MoreExecutors; +import eu.siacs.conversations.xml.Namespace; import eu.siacs.conversations.xmpp.Jid; import eu.siacs.conversations.xmpp.XmppConnection; import im.conversations.android.xmpp.NodeConfiguration; @@ -43,6 +46,19 @@ public class PepManager extends AbstractManager { return pubSubManager().retract(pepService(), itemId, node); } + public ListenableFuture delete(final String node) { + final var future = pubSubManager().delete(pepService(), node); + return Futures.transform(future, iq -> null, MoreExecutors.directExecutor()); + } + + public boolean hasPublishOptions() { + return getManager(DiscoManager.class).hasAccountFeature(Namespace.PUBSUB_PUBLISH_OPTIONS); + } + + public boolean hasConfigNodeMax() { + return getManager(DiscoManager.class).hasAccountFeature(Namespace.PUBSUB_CONFIG_NODE_MAX); + } + private PubSubManager pubSubManager() { return getManager(PubSubManager.class); } diff --git a/src/main/java/eu/siacs/conversations/xmpp/manager/PrivateStorageManager.java b/src/main/java/eu/siacs/conversations/xmpp/manager/PrivateStorageManager.java index 1a5bd56c62939c39bedfe18871b16ae02f85edbf..b65a4fd56d83a12c4a169fe3cf6641b68bc1d4b7 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/manager/PrivateStorageManager.java +++ b/src/main/java/eu/siacs/conversations/xmpp/manager/PrivateStorageManager.java @@ -4,6 +4,7 @@ import android.util.Log; import androidx.annotation.NonNull; import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.MoreExecutors; import eu.siacs.conversations.Config; import eu.siacs.conversations.entities.Bookmark; @@ -13,6 +14,7 @@ import eu.siacs.conversations.xmpp.XmppConnection; import im.conversations.android.xmpp.model.bookmark.Storage; import im.conversations.android.xmpp.model.stanza.Iq; import im.conversations.android.xmpp.model.storage.PrivateStorage; +import java.util.Collection; import java.util.Map; public class PrivateStorageManager extends AbstractBookmarkManager { @@ -52,4 +54,15 @@ public class PrivateStorageManager extends AbstractBookmarkManager { }, MoreExecutors.directExecutor()); } + + public ListenableFuture publishBookmarks(Collection bookmarks) { + final var iq = new Iq(Iq.Type.SET); + final var privateStorage = iq.addExtension(new PrivateStorage()); + final var storage = privateStorage.addExtension(new Storage()); + for (final var bookmark : bookmarks) { + storage.addChild(bookmark); + } + return Futures.transform( + connection.sendIqPacket(iq), result -> null, MoreExecutors.directExecutor()); + } } diff --git a/src/main/java/eu/siacs/conversations/xmpp/manager/PubSubManager.java b/src/main/java/eu/siacs/conversations/xmpp/manager/PubSubManager.java index 2d1132b96f966722f7129d5c381570404c553c38..956049335d9db2f2e724b16807b0cb1f4991afb7 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/manager/PubSubManager.java +++ b/src/main/java/eu/siacs/conversations/xmpp/manager/PubSubManager.java @@ -345,6 +345,16 @@ public class PubSubManager extends AbstractManager { return connection.sendIqPacket(iq); } + public ListenableFuture delete(final Jid address, final String node) { + final var iq = new Iq(Iq.Type.SET); + iq.setTo(address); + final var pubSub = iq.addExtension(new PubSubOwner()); + final var delete = + pubSub.addExtension(new im.conversations.android.xmpp.model.pubsub.owner.Delete()); + delete.setNode(node); + return connection.sendIqPacket(iq); + } + private static class PubSubExceptionTransformer implements AsyncFunction { diff --git a/src/main/java/im/conversations/android/xmpp/NodeConfiguration.java b/src/main/java/im/conversations/android/xmpp/NodeConfiguration.java index 81a55f18c5a80b7acf2a90ccda9661169ff0e05f..e96e453e200547056d0ce45837d63265d3997f97 100644 --- a/src/main/java/im/conversations/android/xmpp/NodeConfiguration.java +++ b/src/main/java/im/conversations/android/xmpp/NodeConfiguration.java @@ -28,6 +28,12 @@ public class NodeConfiguration implements Map { .put(PERSIST_ITEMS, Boolean.TRUE) .put(ACCESS_MODEL, "presence") .build()); + public static final NodeConfiguration WHITELIST = + new NodeConfiguration( + new ImmutableMap.Builder() + .put(PERSIST_ITEMS, Boolean.TRUE) + .put(ACCESS_MODEL, "whitelist") + .build()); public static final NodeConfiguration WHITELIST_MAX_ITEMS = new NodeConfiguration( new ImmutableMap.Builder() diff --git a/src/main/java/im/conversations/android/xmpp/model/bookmark2/Conference.java b/src/main/java/im/conversations/android/xmpp/model/bookmark2/Conference.java index 265c80e3fd7db0d2e56572eb700f94592af12a5e..691a80364b1fb8f93977ce536c07ea56762a927d 100644 --- a/src/main/java/im/conversations/android/xmpp/model/bookmark2/Conference.java +++ b/src/main/java/im/conversations/android/xmpp/model/bookmark2/Conference.java @@ -29,4 +29,8 @@ public class Conference extends Extension { public Extensions getExtensions() { return this.getExtension(Extensions.class); } + + public void setConferenceName(String name) { + this.setAttribute("name", name); + } } diff --git a/src/main/java/im/conversations/android/xmpp/model/bookmark2/Password.java b/src/main/java/im/conversations/android/xmpp/model/bookmark2/Password.java new file mode 100644 index 0000000000000000000000000000000000000000..85204a5e786c7425ce357c8ebacd45d7dd8c9ee5 --- /dev/null +++ b/src/main/java/im/conversations/android/xmpp/model/bookmark2/Password.java @@ -0,0 +1,12 @@ +package im.conversations.android.xmpp.model.bookmark2; + +import im.conversations.android.annotation.XmlElement; +import im.conversations.android.xmpp.model.Extension; + +@XmlElement +public class Password extends Extension { + + public Password() { + super(Password.class); + } +} diff --git a/src/main/java/im/conversations/android/xmpp/model/pubsub/owner/Delete.java b/src/main/java/im/conversations/android/xmpp/model/pubsub/owner/Delete.java new file mode 100644 index 0000000000000000000000000000000000000000..ca60593aaa6ecf6d123938c6c1df9693cdb6f1d1 --- /dev/null +++ b/src/main/java/im/conversations/android/xmpp/model/pubsub/owner/Delete.java @@ -0,0 +1,16 @@ +package im.conversations.android.xmpp.model.pubsub.owner; + +import im.conversations.android.annotation.XmlElement; +import im.conversations.android.xmpp.model.Extension; + +@XmlElement +public class Delete extends Extension { + + public Delete() { + super(Delete.class); + } + + public void setNode(final String node) { + this.setAttribute("node", node); + } +} diff --git a/src/main/java/im/conversations/android/xmpp/processor/BindProcessor.java b/src/main/java/im/conversations/android/xmpp/processor/BindProcessor.java index 96b2be840c80b04aa6659c00a4cafedda148a2b5..6116649a449eb0187a73b28ef6addccc6a1c0fae 100644 --- a/src/main/java/im/conversations/android/xmpp/processor/BindProcessor.java +++ b/src/main/java/im/conversations/android/xmpp/processor/BindProcessor.java @@ -1,14 +1,16 @@ package im.conversations.android.xmpp.processor; -import android.text.TextUtils; import android.util.Log; +import com.google.common.base.Strings; import eu.siacs.conversations.Config; import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.generator.IqGenerator; import eu.siacs.conversations.services.XmppConnectionService; import eu.siacs.conversations.xmpp.XmppConnection; import eu.siacs.conversations.xmpp.manager.BookmarkManager; +import eu.siacs.conversations.xmpp.manager.LegacyBookmarkManager; import eu.siacs.conversations.xmpp.manager.MessageDisplayedSynchronizationManager; +import eu.siacs.conversations.xmpp.manager.NickManager; import eu.siacs.conversations.xmpp.manager.PrivateStorageManager; import eu.siacs.conversations.xmpp.manager.RosterManager; import im.conversations.android.xmpp.model.stanza.Iq; @@ -45,12 +47,13 @@ public class BindProcessor extends XmppConnection.Delegate implements Runnable { } if (loggedInSuccessfully) { - if (!TextUtils.isEmpty(account.getDisplayName())) { + final String displayName = account.getDisplayName(); + if (!Strings.isNullOrEmpty(displayName)) { Log.d( Config.LOGTAG, account.getJid().asBareJid() + ": display name wasn't empty on first log in. publishing"); - service.publishDisplayName(account); + getManager(NickManager.class).publish(displayName); } } @@ -66,10 +69,13 @@ public class BindProcessor extends XmppConnection.Delegate implements Runnable { getManager(RosterManager.class).request(); - if (features.bookmarks2()) { + if (getManager(BookmarkManager.class).hasFeature()) { connection.getManager(BookmarkManager.class).fetch(); - // log that we use bookmarks 1 and wait for +notify - } else if (!features.bookmarksConversion()) { + } else if (getManager(LegacyBookmarkManager.class).hasConversion()) { + Log.d( + Config.LOGTAG, + account.getJid() + ": not fetching bookmarks. waiting for server to push"); + } else { connection.getManager(PrivateStorageManager.class).fetchBookmarks(); }