From 57d264d72e19b796ee12cefec4fa380959b13373 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Wed, 25 Jan 2023 16:55:46 +0100 Subject: [PATCH] include caps in outgoing presence --- .../eu/siacs/conversations/xml/Element.java | 6 + .../eu/siacs/conversations/xml/Namespace.java | 151 +++++++++--------- .../stanzas/FileTransferDescription.java | 7 +- .../android/xmpp/EntityCapabilities.java | 14 ++ .../android/xmpp/EntityCapabilities2.java | 15 ++ .../conversations/android/xmpp/Managers.java | 2 + .../android/xmpp/manager/DiscoManager.java | 91 +++++++++++ .../android/xmpp/manager/PresenceManager.java | 48 ++++++ .../android/xmpp/model/Hash.java | 4 + .../xmpp/model/capabilties/Capabilities.java | 7 + .../model/capabilties/LegacyCapabilities.java | 9 ++ .../xmpp/model/disco/info/Feature.java | 4 + .../xmpp/model/disco/info/Identity.java | 12 ++ .../android/xmpp/processor/BindProcessor.java | 5 +- .../android/xmpp/processor/IqProcessor.java | 4 +- src/main/res/values-sw600dp/defaults.xml | 1 + src/main/res/values/defaults.xml | 1 + 17 files changed, 300 insertions(+), 81 deletions(-) create mode 100644 src/main/java/im/conversations/android/xmpp/manager/PresenceManager.java diff --git a/src/main/java/eu/siacs/conversations/xml/Element.java b/src/main/java/eu/siacs/conversations/xml/Element.java index 2cf6b086e..9bf5ea54b 100644 --- a/src/main/java/eu/siacs/conversations/xml/Element.java +++ b/src/main/java/eu/siacs/conversations/xml/Element.java @@ -43,6 +43,12 @@ public class Element { return child; } + public void addExtensions(final Collection extensions) { + for(final Extension extension : extensions) { + addExtension(extension); + } + } + public Element addChild(String name) { this.content = null; Element child = new Element(name); diff --git a/src/main/java/eu/siacs/conversations/xml/Namespace.java b/src/main/java/eu/siacs/conversations/xml/Namespace.java index ccfb3dce4..b0209c735 100644 --- a/src/main/java/eu/siacs/conversations/xml/Namespace.java +++ b/src/main/java/eu/siacs/conversations/xml/Namespace.java @@ -1,85 +1,90 @@ package eu.siacs.conversations.xml; public final class Namespace { - public static final String STREAMS = "http://etherx.jabber.org/streams"; - public static final String DISCO_ITEMS = "http://jabber.org/protocol/disco#items"; - public static final String DISCO_INFO = "http://jabber.org/protocol/disco#info"; - public static final String EXTERNAL_SERVICE_DISCOVERY = "urn:xmpp:extdisco:2"; - - public static final String ENTITY_CAPABILITIES = "http://jabber.org/protocol/caps"; - - public static final String ENTITY_CAPABILITIES_2 = "urn:xmpp:caps"; - - public static final String HASHES = "urn:xmpp:hashes:2"; - - public static final String BLOCKING = "urn:xmpp:blocking"; - public static final String ROSTER = "jabber:iq:roster"; - public static final String REGISTER = "jabber:iq:register"; - public static final String REGISTER_STREAM_FEATURE = "http://jabber.org/features/iq-register"; - public static final String BYTE_STREAMS = "http://jabber.org/protocol/bytestreams"; - public static final String HTTP_UPLOAD = "urn:xmpp:http:upload:0"; - public static final String HTTP_UPLOAD_LEGACY = "urn:xmpp:http:upload"; - public static final String STANZA_IDS = "urn:xmpp:sid:0"; - public static final String IDLE = "urn:xmpp:idle:1"; - public static final String DATA = "jabber:x:data"; - public static final String OOB = "jabber:x:oob"; - public static final String SASL = "urn:ietf:params:xml:ns:xmpp-sasl"; - public static final String SASL_2 = "urn:xmpp:sasl:2"; - public static final String CHANNEL_BINDING = "urn:xmpp:sasl-cb:0"; - public static final String FAST = "urn:xmpp:fast:0"; - public static final String TLS = "urn:ietf:params:xml:ns:xmpp-tls"; - public static final String PUBSUB = "http://jabber.org/protocol/pubsub"; - public static final String PUBSUB_PUBLISH_OPTIONS = PUBSUB + "#publish-options"; - public static final String PUBSUB_ERROR = PUBSUB + "#errors"; - public static final String PUBSUB_OWNER = PUBSUB + "#owner"; - public static final String NICK = "http://jabber.org/protocol/nick"; - public static final String FLEXIBLE_OFFLINE_MESSAGE_RETRIEVAL = - "http://jabber.org/protocol/offline"; - public static final String BIND = "urn:ietf:params:xml:ns:xmpp-bind"; - public static final String BIND2 = "urn:xmpp:bind:0"; - public static final String STREAM_MANAGEMENT = "urn:xmpp:sm:3"; - public static final String CSI = "urn:xmpp:csi:0"; - public static final String CARBONS = "urn:xmpp:carbons:2"; - public static final String BOOKMARKS_CONVERSION = "urn:xmpp:bookmarks-conversion:0"; - public static final String BOOKMARKS = "storage:bookmarks"; - public static final String SYNCHRONIZATION = "im.quicksy.synchronization:0"; + public static final String AVATAR_CONVERSION = "urn:xmpp:pep-vcard-conversion:0"; public static final String AVATAR_DATA = "urn:xmpp:avatar:data"; public static final String AVATAR_METADATA = "urn:xmpp:avatar:metadata"; - public static final String AVATAR_CONVERSION = "urn:xmpp:pep-vcard-conversion:0"; - public static final String JINGLE = "urn:xmpp:jingle:1"; - public static final String JINGLE_ERRORS = "urn:xmpp:jingle:errors:1"; - public static final String JINGLE_MESSAGE = "urn:xmpp:jingle-message:0"; - public static final String JINGLE_ENCRYPTED_TRANSPORT = "urn:xmpp:jingle:jet:0"; - public static final String JINGLE_ENCRYPTED_TRANSPORT_OMEMO = "urn:xmpp:jingle:jet-omemo:0"; - public static final String JINGLE_TRANSPORTS_S5B = "urn:xmpp:jingle:transports:s5b:1"; - public static final String JINGLE_TRANSPORTS_IBB = "urn:xmpp:jingle:transports:ibb:1"; - public static final String JINGLE_TRANSPORT_ICE_UDP = "urn:xmpp:jingle:transports:ice-udp:1"; - public static final String JINGLE_APPS_RTP = "urn:xmpp:jingle:apps:rtp:1"; - public static final String JINGLE_APPS_DTLS = "urn:xmpp:jingle:apps:dtls:0"; - public static final String JINGLE_APPS_GROUPING = "urn:xmpp:jingle:apps:grouping:0"; - public static final String JINGLE_FEATURE_AUDIO = "urn:xmpp:jingle:apps:rtp:audio"; - public static final String JINGLE_FEATURE_VIDEO = "urn:xmpp:jingle:apps:rtp:video"; - public static final String JINGLE_RTP_HEADER_EXTENSIONS = - "urn:xmpp:jingle:apps:rtp:rtp-hdrext:0"; - public static final String JINGLE_RTP_FEEDBACK_NEGOTIATION = - "urn:xmpp:jingle:apps:rtp:rtcp-fb:0"; - public static final String JINGLE_RTP_SOURCE_SPECIFIC_MEDIA_ATTRIBUTES = - "urn:xmpp:jingle:apps:rtp:ssma:0"; - public static final String IBB = "http://jabber.org/protocol/ibb"; - public static final String PING = "urn:xmpp:ping"; - public static final String PUSH = "urn:xmpp:push:0"; - public static final String COMMANDS = "http://jabber.org/protocol/commands"; - public static final String MUC_USER = "http://jabber.org/protocol/muc#user"; + public static final String BIND = "urn:ietf:params:xml:ns:xmpp-bind"; + public static final String BIND2 = "urn:xmpp:bind:0"; + public static final String BLOCKING = "urn:xmpp:blocking"; + public static final String BOOKMARKS = "storage:bookmarks"; public static final String BOOKMARKS2 = "urn:xmpp:bookmarks:0"; public static final String BOOKMARKS2_COMPAT = BOOKMARKS2 + "#compat"; - public static final String INVITE = "urn:xmpp:invite"; - public static final String PARS = "urn:xmpp:pars:0"; + public static final String BOOKMARKS_CONVERSION = "urn:xmpp:bookmarks-conversion:0"; + public static final String BYTE_STREAMS = "http://jabber.org/protocol/bytestreams"; + public static final String CARBONS = "urn:xmpp:carbons:2"; + public static final String CHANNEL_BINDING = "urn:xmpp:sasl-cb:0"; + public static final String CHAT_MARKERS = "urn:xmpp:chat-markers:0"; + public static final String CHAT_STATES = "http://jabber.org/protocol/chatstates"; + public static final String COMMANDS = "http://jabber.org/protocol/commands"; + public static final String CONFERENCE = "jabber:x:conference"; + public static final String CSI = "urn:xmpp:csi:0"; + public static final String DATA = "jabber:x:data"; + public static final String DELIVERY_RECEIPTS = "urn:xmpp:receipts"; + public static final String DISCO_INFO = "http://jabber.org/protocol/disco#info"; + public static final String DISCO_ITEMS = "http://jabber.org/protocol/disco#items"; public static final String EASY_ONBOARDING_INVITE = "urn:xmpp:invite#invite"; + public static final String ENTITY_CAPABILITIES = "http://jabber.org/protocol/caps"; + public static final String ENTITY_CAPABILITIES_2 = "urn:xmpp:caps"; + public static final String EXTERNAL_SERVICE_DISCOVERY = "urn:xmpp:extdisco:2"; + public static final String FAST = "urn:xmpp:fast:0"; + public static final String FLEXIBLE_OFFLINE_MESSAGE_RETRIEVAL = + "http://jabber.org/protocol/offline"; + public static final String FORWARD = "urn:xmpp:forward:0"; + public static final String HASHES = "urn:xmpp:hashes:2"; + public static final String HTTP_UPLOAD = "urn:xmpp:http:upload:0"; + public static final String HTTP_UPLOAD_LEGACY = "urn:xmpp:http:upload"; + public static final String IBB = "http://jabber.org/protocol/ibb"; + public static final String IDLE = "urn:xmpp:idle:1"; + public static final String INVITE = "urn:xmpp:invite"; + public static final String JABBER_CLIENT = "jabber:client"; + public static final String JINGLE = "urn:xmpp:jingle:1"; + public static final String JINGLE_APPS_DTLS = "urn:xmpp:jingle:apps:dtls:0"; + public static final String JINGLE_APPS_GROUPING = "urn:xmpp:jingle:apps:grouping:0"; + public static final String JINGLE_APPS_RTP = "urn:xmpp:jingle:apps:rtp:1"; + public static final String JINGLE_ENCRYPTED_TRANSPORT = "urn:xmpp:jingle:jet:0"; + public static final String JINGLE_ENCRYPTED_TRANSPORT_OMEMO = "urn:xmpp:jingle:jet-omemo:0"; + public static final String JINGLE_ERRORS = "urn:xmpp:jingle:errors:1"; + public static final String JINGLE_FEATURE_AUDIO = "urn:xmpp:jingle:apps:rtp:audio"; + public static final String JINGLE_FEATURE_VIDEO = "urn:xmpp:jingle:apps:rtp:video"; + public static final String JINGLE_FILE_TRANSFER_3 = "urn:xmpp:jingle:apps:file-transfer:3"; + public static final String JINGLE_FILE_TRANSFER_4 = "urn:xmpp:jingle:apps:file-transfer:4"; + public static final String JINGLE_FILE_TRANSFER_5 = "urn:xmpp:jingle:apps:file-transfer:5"; + public static final String JINGLE_MESSAGE = "urn:xmpp:jingle-message:0"; + public static final String JINGLE_RTP_FEEDBACK_NEGOTIATION = + "urn:xmpp:jingle:apps:rtp:rtcp-fb:0"; + public static final String JINGLE_RTP_HEADER_EXTENSIONS = + "urn:xmpp:jingle:apps:rtp:rtp-hdrext:0"; + public static final String JINGLE_RTP_SOURCE_SPECIFIC_MEDIA_ATTRIBUTES = + "urn:xmpp:jingle:apps:rtp:ssma:0"; + public static final String JINGLE_TRANSPORTS_IBB = "urn:xmpp:jingle:transports:ibb:1"; + public static final String JINGLE_TRANSPORTS_S5B = "urn:xmpp:jingle:transports:s5b:1"; + public static final String JINGLE_TRANSPORT_ICE_UDP = "urn:xmpp:jingle:transports:ice-udp:1"; + public static final String LAST_MESSAGE_CORRECTION = "urn:xmpp:message-correct:0"; + public static final String MUC = "http://jabber.org/protocol/muc"; + public static final String MUC_USER = MUC + "#user"; + public static final String NICK = "http://jabber.org/protocol/nick"; public static final String OMEMO_DTLS_SRTP_VERIFICATION = "http://gultsch.de/xmpp/drafts/omemo/dlts-srtp-verification"; - public static final String UNIFIED_PUSH = "http://gultsch.de/xmpp/drafts/unified-push"; - public static final String JABBER_CLIENT = "jabber:client"; - public static final String FORWARD = "urn:xmpp:forward:0"; - + public static final String OOB = "jabber:x:oob"; + public static final String PARS = "urn:xmpp:pars:0"; + public static final String PING = "urn:xmpp:ping"; + public static final String PUBSUB = "http://jabber.org/protocol/pubsub"; + public static final String PUBSUB_ERROR = PUBSUB + "#errors"; + public static final String PUBSUB_OWNER = PUBSUB + "#owner"; + public static final String PUBSUB_PUBLISH_OPTIONS = PUBSUB + "#publish-options"; + public static final String PUSH = "urn:xmpp:push:0"; + public static final String REGISTER = "jabber:iq:register"; + public static final String REGISTER_STREAM_FEATURE = "http://jabber.org/features/iq-register"; + public static final String ROSTER = "jabber:iq:roster"; + public static final String SASL = "urn:ietf:params:xml:ns:xmpp-sasl"; + public static final String SASL_2 = "urn:xmpp:sasl:2"; public static final String STANZAS = "urn:ietf:params:xml:ns:xmpp-stanzas"; + public static final String STANZA_IDS = "urn:xmpp:sid:0"; + public static final String STREAMS = "http://etherx.jabber.org/streams"; + public static final String STREAM_MANAGEMENT = "urn:xmpp:sm:3"; + public static final String SYNCHRONIZATION = "im.quicksy.synchronization:0"; + public static final String TLS = "urn:ietf:params:xml:ns:xmpp-tls"; + public static final String UNIFIED_PUSH = "http://gultsch.de/xmpp/drafts/unified-push"; + public static final String VERSION = "jabber:iq:version"; } diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/stanzas/FileTransferDescription.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/stanzas/FileTransferDescription.java index 8e0f2ebad..a7a7e3177 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/stanzas/FileTransferDescription.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/stanzas/FileTransferDescription.java @@ -8,6 +8,7 @@ import java.util.List; import eu.siacs.conversations.crypto.axolotl.XmppAxolotlMessage; import eu.siacs.conversations.entities.DownloadableFile; import eu.siacs.conversations.xml.Element; +import eu.siacs.conversations.xml.Namespace; public class FileTransferDescription extends GenericDescription { @@ -72,9 +73,9 @@ public class FileTransferDescription extends GenericDescription { } public enum Version { - FT_3("urn:xmpp:jingle:apps:file-transfer:3"), - FT_4("urn:xmpp:jingle:apps:file-transfer:4"), - FT_5("urn:xmpp:jingle:apps:file-transfer:5"); + FT_3(Namespace.JINGLE_FILE_TRANSFER_3), + FT_4(Namespace.JINGLE_FILE_TRANSFER_4), + FT_5(Namespace.JINGLE_FILE_TRANSFER_5); private final String namespace; diff --git a/src/main/java/im/conversations/android/xmpp/EntityCapabilities.java b/src/main/java/im/conversations/android/xmpp/EntityCapabilities.java index 948f075e0..ceb81a1fc 100644 --- a/src/main/java/im/conversations/android/xmpp/EntityCapabilities.java +++ b/src/main/java/im/conversations/android/xmpp/EntityCapabilities.java @@ -12,6 +12,7 @@ import im.conversations.android.xmpp.model.disco.info.Feature; import im.conversations.android.xmpp.model.disco.info.Identity; import im.conversations.android.xmpp.model.disco.info.InfoQuery; import java.nio.charset.StandardCharsets; +import java.util.Arrays; import java.util.Comparator; import java.util.List; @@ -101,6 +102,19 @@ public final class EntityCapabilities { } public abstract String capabilityNode(final String node); + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Hash hash1 = (Hash) o; + return Arrays.equals(hash, hash1.hash); + } + + @Override + public int hashCode() { + return Arrays.hashCode(hash); + } } public static class EntityCapsHash extends Hash { diff --git a/src/main/java/im/conversations/android/xmpp/EntityCapabilities2.java b/src/main/java/im/conversations/android/xmpp/EntityCapabilities2.java index 55ab66a94..f8f4f100c 100644 --- a/src/main/java/im/conversations/android/xmpp/EntityCapabilities2.java +++ b/src/main/java/im/conversations/android/xmpp/EntityCapabilities2.java @@ -18,6 +18,7 @@ import im.conversations.android.xmpp.model.disco.info.Identity; import im.conversations.android.xmpp.model.disco.info.InfoQuery; import java.nio.charset.StandardCharsets; import java.util.Collection; +import java.util.Objects; public class EntityCapabilities2 { @@ -165,5 +166,19 @@ public class EntityCapabilities2 { return String.format( "%s#%s.%s", Namespace.ENTITY_CAPABILITIES_2, algorithm.toString(), encoded()); } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + if (!super.equals(o)) return false; + EntityCaps2Hash that = (EntityCaps2Hash) o; + return algorithm == that.algorithm; + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), algorithm); + } } } diff --git a/src/main/java/im/conversations/android/xmpp/Managers.java b/src/main/java/im/conversations/android/xmpp/Managers.java index 401b1f7c8..117aa1742 100644 --- a/src/main/java/im/conversations/android/xmpp/Managers.java +++ b/src/main/java/im/conversations/android/xmpp/Managers.java @@ -8,6 +8,7 @@ import im.conversations.android.xmpp.manager.BlockingManager; import im.conversations.android.xmpp.manager.BookmarkManager; import im.conversations.android.xmpp.manager.CarbonsManager; import im.conversations.android.xmpp.manager.DiscoManager; +import im.conversations.android.xmpp.manager.PresenceManager; import im.conversations.android.xmpp.manager.RosterManager; public final class Managers { @@ -21,6 +22,7 @@ public final class Managers { .put(BookmarkManager.class, new BookmarkManager(context, connection)) .put(CarbonsManager.class, new CarbonsManager(context, connection)) .put(DiscoManager.class, new DiscoManager(context, connection)) + .put(PresenceManager.class, new PresenceManager(context, connection)) .put(RosterManager.class, new RosterManager(context, connection)) .build(); } diff --git a/src/main/java/im/conversations/android/xmpp/manager/DiscoManager.java b/src/main/java/im/conversations/android/xmpp/manager/DiscoManager.java index 12cb4462e..f2e3224fe 100644 --- a/src/main/java/im/conversations/android/xmpp/manager/DiscoManager.java +++ b/src/main/java/im/conversations/android/xmpp/manager/DiscoManager.java @@ -5,15 +5,22 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.google.common.base.Strings; import com.google.common.collect.Collections2; +import com.google.common.collect.ImmutableList; import com.google.common.io.BaseEncoding; 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.BuildConfig; +import eu.siacs.conversations.R; +import eu.siacs.conversations.xml.Namespace; import eu.siacs.conversations.xmpp.Jid; import im.conversations.android.xmpp.Entity; import im.conversations.android.xmpp.EntityCapabilities; import im.conversations.android.xmpp.EntityCapabilities2; import im.conversations.android.xmpp.XmppConnection; +import im.conversations.android.xmpp.model.disco.info.Feature; +import im.conversations.android.xmpp.model.disco.info.Identity; import im.conversations.android.xmpp.model.disco.info.InfoQuery; import im.conversations.android.xmpp.model.disco.items.Item; import im.conversations.android.xmpp.model.disco.items.ItemsQuery; @@ -25,6 +32,42 @@ import java.util.Objects; public class DiscoManager extends AbstractManager { + public static final String CAPABILITY_NODE = "http://conversations.im"; + + private static final Collection FEATURES_BASE = + Arrays.asList( + Namespace.JINGLE, + Namespace.JINGLE_FILE_TRANSFER_3, + Namespace.JINGLE_FILE_TRANSFER_4, + Namespace.JINGLE_FILE_TRANSFER_5, + Namespace.JINGLE_TRANSPORTS_S5B, + Namespace.JINGLE_TRANSPORTS_IBB, + Namespace.JINGLE_ENCRYPTED_TRANSPORT, + Namespace.JINGLE_ENCRYPTED_TRANSPORT_OMEMO, + Namespace.MUC, + Namespace.CONFERENCE, + Namespace.OOB, + Namespace.ENTITY_CAPABILITIES, + Namespace.ENTITY_CAPABILITIES_2, + Namespace.DISCO_INFO, + Namespace.PING, + Namespace.VERSION, + Namespace.CHAT_STATES, + Namespace.LAST_MESSAGE_CORRECTION, + Namespace.DELIVERY_RECEIPTS); + + private static final Collection FEATURES_AV_CALLS = + Arrays.asList( + Namespace.JINGLE_TRANSPORT_ICE_UDP, + Namespace.JINGLE_FEATURE_AUDIO, + Namespace.JINGLE_FEATURE_VIDEO, + Namespace.JINGLE_APPS_RTP, + Namespace.JINGLE_APPS_DTLS, + Namespace.JINGLE_MESSAGE); + + private static final Collection FEATURES_NOTIFY = + Arrays.asList(Namespace.NICK, Namespace.AVATAR_METADATA, Namespace.BOOKMARKS2); + public DiscoManager(Context context, XmppConnection connection) { super(context, connection); } @@ -161,4 +204,52 @@ public class DiscoManager extends AbstractManager { public boolean hasServerFeature(final String feature) { return hasFeature(getAccount().address.getDomain(), feature); } + + public InfoQuery getInfo() { + return getInfo(false); + } + + private InfoQuery getInfo(final boolean privacyMode) { + final var infoQuery = new InfoQuery(); + final ImmutableList.Builder stringFeatureBuilder = ImmutableList.builder(); + stringFeatureBuilder.addAll(FEATURES_BASE); + stringFeatureBuilder.addAll( + Collections2.transform(FEATURES_NOTIFY, fn -> String.format("%s+notify", fn))); + if (!privacyMode) { + stringFeatureBuilder.addAll(FEATURES_AV_CALLS); + } + final var stringFeatures = stringFeatureBuilder.build(); + final Collection features = + Collections2.transform( + stringFeatures, + sf -> { + final var feature = new Feature(); + feature.setVar(sf); + return feature; + }); + infoQuery.addExtensions(features); + final var identity = infoQuery.addExtension(new Identity()); + identity.setIdentityName(getIdentityName()); + identity.setCategory("client"); + identity.setType(getIdentityType()); + return infoQuery; + } + + String getIdentityVersion() { + return BuildConfig.VERSION_NAME; + } + + String getIdentityName() { + return BuildConfig.APP_NAME; + } + + String getIdentityType() { + if ("chromium".equals(android.os.Build.BRAND)) { + return "pc"; + } else if (context.getResources().getBoolean(R.bool.is_device_table)) { + return "tablet"; + } else { + return "phone"; + } + } } diff --git a/src/main/java/im/conversations/android/xmpp/manager/PresenceManager.java b/src/main/java/im/conversations/android/xmpp/manager/PresenceManager.java new file mode 100644 index 000000000..296f57c8f --- /dev/null +++ b/src/main/java/im/conversations/android/xmpp/manager/PresenceManager.java @@ -0,0 +1,48 @@ +package im.conversations.android.xmpp.manager; + +import android.content.Context; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.HashMap; +import java.util.Map; + +import im.conversations.android.xmpp.EntityCapabilities; +import im.conversations.android.xmpp.EntityCapabilities2; +import im.conversations.android.xmpp.XmppConnection; +import im.conversations.android.xmpp.model.capabilties.Capabilities; +import im.conversations.android.xmpp.model.capabilties.LegacyCapabilities; +import im.conversations.android.xmpp.model.disco.info.InfoQuery; +import im.conversations.android.xmpp.model.stanza.Presence; + +public class PresenceManager extends AbstractManager { + + private static final Logger LOGGER = LoggerFactory.getLogger(PresenceManager.class); + + private final Map outgoingCapsHash = new HashMap<>(); + + public PresenceManager(Context context, XmppConnection connection) { + super(context, connection); + } + + public void sendPresence() { + final var infoQuery = getManager(DiscoManager.class).getInfo(); + final var capsHash = EntityCapabilities.hash(infoQuery); + final var caps2Hash = EntityCapabilities2.hash(infoQuery); + outgoingCapsHash.put(capsHash, infoQuery); + outgoingCapsHash.put(caps2Hash, infoQuery); + final var capabilities = new Capabilities(); + capabilities.setHash(caps2Hash); + final var legacyCapabilities = new LegacyCapabilities(); + legacyCapabilities.setNode(DiscoManager.CAPABILITY_NODE); + legacyCapabilities.setHash(capsHash); + final var presence = new Presence(); + presence.addExtension(capabilities); + presence.addExtension(legacyCapabilities); + + LOGGER.info(presence.toString()); + + connection.sendPresencePacket(presence); + } +} diff --git a/src/main/java/im/conversations/android/xmpp/model/Hash.java b/src/main/java/im/conversations/android/xmpp/model/Hash.java index 9a640e6ef..d26fd3944 100644 --- a/src/main/java/im/conversations/android/xmpp/model/Hash.java +++ b/src/main/java/im/conversations/android/xmpp/model/Hash.java @@ -17,6 +17,10 @@ public class Hash extends Extension { return Algorithm.tryParse(this.getAttribute("algo")); } + public void setAlgorithm(final Algorithm algorithm) { + this.setAttribute("algo", algorithm.toString()); + } + public enum Algorithm { SHA_1, SHA_256, diff --git a/src/main/java/im/conversations/android/xmpp/model/capabilties/Capabilities.java b/src/main/java/im/conversations/android/xmpp/model/capabilties/Capabilities.java index 33b9b18a7..51d284bde 100644 --- a/src/main/java/im/conversations/android/xmpp/model/capabilties/Capabilities.java +++ b/src/main/java/im/conversations/android/xmpp/model/capabilties/Capabilities.java @@ -32,4 +32,11 @@ public class Capabilities extends Extension { } return null; } + + public void setHash(final EntityCapabilities2.EntityCaps2Hash caps2Hash) { + final Hash hash = new Hash(); + hash.setAlgorithm(caps2Hash.algorithm); + hash.setContent(caps2Hash.encoded()); + this.addExtension(hash); + } } diff --git a/src/main/java/im/conversations/android/xmpp/model/capabilties/LegacyCapabilities.java b/src/main/java/im/conversations/android/xmpp/model/capabilties/LegacyCapabilities.java index 43836d203..46ee4c0d3 100644 --- a/src/main/java/im/conversations/android/xmpp/model/capabilties/LegacyCapabilities.java +++ b/src/main/java/im/conversations/android/xmpp/model/capabilties/LegacyCapabilities.java @@ -32,4 +32,13 @@ public class LegacyCapabilities extends Extension { return null; } } + + public void setNode(final String node) { + this.setAttribute("node", node); + } + + public void setHash(final EntityCapabilities.EntityCapsHash hash) { + this.setAttribute("hash", HASH_ALGORITHM); + this.setAttribute("ver", hash.encoded()); + } } diff --git a/src/main/java/im/conversations/android/xmpp/model/disco/info/Feature.java b/src/main/java/im/conversations/android/xmpp/model/disco/info/Feature.java index 191c45e60..dd288918c 100644 --- a/src/main/java/im/conversations/android/xmpp/model/disco/info/Feature.java +++ b/src/main/java/im/conversations/android/xmpp/model/disco/info/Feature.java @@ -12,4 +12,8 @@ public class Feature extends Extension { public String getVar() { return this.getAttribute("var"); } + + public void setVar(final String feature) { + this.setAttribute("var", feature); + } } diff --git a/src/main/java/im/conversations/android/xmpp/model/disco/info/Identity.java b/src/main/java/im/conversations/android/xmpp/model/disco/info/Identity.java index 6b5658a89..6da0a4aa2 100644 --- a/src/main/java/im/conversations/android/xmpp/model/disco/info/Identity.java +++ b/src/main/java/im/conversations/android/xmpp/model/disco/info/Identity.java @@ -24,4 +24,16 @@ public class Identity extends Extension { public String getIdentityName() { return this.getAttribute("name"); } + + public void setIdentityName(final String name) { + this.setAttribute("name", name); + } + + public void setType(final String type) { + this.setAttribute("type", type); + } + + public void setCategory(final String category) { + this.setAttribute("category", category); + } } 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 43a0c0168..4058caf25 100644 --- a/src/main/java/im/conversations/android/xmpp/processor/BindProcessor.java +++ b/src/main/java/im/conversations/android/xmpp/processor/BindProcessor.java @@ -8,6 +8,7 @@ import im.conversations.android.xmpp.XmppConnection; import im.conversations.android.xmpp.manager.BlockingManager; import im.conversations.android.xmpp.manager.BookmarkManager; import im.conversations.android.xmpp.manager.DiscoManager; +import im.conversations.android.xmpp.manager.PresenceManager; import im.conversations.android.xmpp.manager.RosterManager; import java.util.function.Consumer; @@ -46,8 +47,6 @@ public class BindProcessor extends XmppConnection.Delegate implements Consumer for (final Extension extension : extensions) { response.addExtension(extension); } - connection.sendIqPacket(response); + connection.sendIqPacket(response, null); } public void sendErrorFor(final Iq request, final Condition condition) { @@ -82,6 +82,6 @@ public class IqProcessor extends XmppConnection.Delegate implements Consumer response.setId(id); final Error error = response.addExtension(new Error()); error.setCondition(condition); - connection.sendIqPacket(response); + connection.sendIqPacket(response, null); } } diff --git a/src/main/res/values-sw600dp/defaults.xml b/src/main/res/values-sw600dp/defaults.xml index b22a4ca8a..add5cb4a3 100644 --- a/src/main/res/values-sw600dp/defaults.xml +++ b/src/main/res/values-sw600dp/defaults.xml @@ -2,4 +2,5 @@ Tablet false + true \ No newline at end of file diff --git a/src/main/res/values/defaults.xml b/src/main/res/values/defaults.xml index 288e4ae74..f22b37f80 100644 --- a/src/main/res/values/defaults.xml +++ b/src/main/res/values/defaults.xml @@ -1,5 +1,6 @@ + true Phone true false