include caps in outgoing presence

This commit is contained in:
Daniel Gultsch 2023-01-25 16:55:46 +01:00
parent 9a855a57ac
commit 57d264d72e
No known key found for this signature in database
GPG key ID: F43D18AD2A0982C2
17 changed files with 300 additions and 81 deletions

View file

@ -43,6 +43,12 @@ public class Element {
return child; return child;
} }
public void addExtensions(final Collection<? extends Extension> extensions) {
for(final Extension extension : extensions) {
addExtension(extension);
}
}
public Element addChild(String name) { public Element addChild(String name) {
this.content = null; this.content = null;
Element child = new Element(name); Element child = new Element(name);

View file

@ -1,85 +1,90 @@
package eu.siacs.conversations.xml; package eu.siacs.conversations.xml;
public final class Namespace { public final class Namespace {
public static final String STREAMS = "http://etherx.jabber.org/streams"; public static final String AVATAR_CONVERSION = "urn:xmpp:pep-vcard-conversion:0";
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_DATA = "urn:xmpp:avatar:data"; 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_METADATA = "urn:xmpp:avatar:metadata";
public static final String AVATAR_CONVERSION = "urn:xmpp:pep-vcard-conversion:0"; public static final String BIND = "urn:ietf:params:xml:ns:xmpp-bind";
public static final String JINGLE = "urn:xmpp:jingle:1"; public static final String BIND2 = "urn:xmpp:bind:0";
public static final String JINGLE_ERRORS = "urn:xmpp:jingle:errors:1"; public static final String BLOCKING = "urn:xmpp:blocking";
public static final String JINGLE_MESSAGE = "urn:xmpp:jingle-message:0"; public static final String BOOKMARKS = "storage:bookmarks";
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 BOOKMARKS2 = "urn:xmpp:bookmarks:0"; public static final String BOOKMARKS2 = "urn:xmpp:bookmarks:0";
public static final String BOOKMARKS2_COMPAT = BOOKMARKS2 + "#compat"; public static final String BOOKMARKS2_COMPAT = BOOKMARKS2 + "#compat";
public static final String INVITE = "urn:xmpp:invite"; public static final String BOOKMARKS_CONVERSION = "urn:xmpp:bookmarks-conversion:0";
public static final String PARS = "urn:xmpp:pars: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 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 = public static final String OMEMO_DTLS_SRTP_VERIFICATION =
"http://gultsch.de/xmpp/drafts/omemo/dlts-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 OOB = "jabber:x:oob";
public static final String JABBER_CLIENT = "jabber:client"; public static final String PARS = "urn:xmpp:pars:0";
public static final String FORWARD = "urn:xmpp:forward: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 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";
} }

View file

@ -8,6 +8,7 @@ import java.util.List;
import eu.siacs.conversations.crypto.axolotl.XmppAxolotlMessage; import eu.siacs.conversations.crypto.axolotl.XmppAxolotlMessage;
import eu.siacs.conversations.entities.DownloadableFile; import eu.siacs.conversations.entities.DownloadableFile;
import eu.siacs.conversations.xml.Element; import eu.siacs.conversations.xml.Element;
import eu.siacs.conversations.xml.Namespace;
public class FileTransferDescription extends GenericDescription { public class FileTransferDescription extends GenericDescription {
@ -72,9 +73,9 @@ public class FileTransferDescription extends GenericDescription {
} }
public enum Version { public enum Version {
FT_3("urn:xmpp:jingle:apps:file-transfer:3"), FT_3(Namespace.JINGLE_FILE_TRANSFER_3),
FT_4("urn:xmpp:jingle:apps:file-transfer:4"), FT_4(Namespace.JINGLE_FILE_TRANSFER_4),
FT_5("urn:xmpp:jingle:apps:file-transfer:5"); FT_5(Namespace.JINGLE_FILE_TRANSFER_5);
private final String namespace; private final String namespace;

View file

@ -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.Identity;
import im.conversations.android.xmpp.model.disco.info.InfoQuery; import im.conversations.android.xmpp.model.disco.info.InfoQuery;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Comparator; import java.util.Comparator;
import java.util.List; import java.util.List;
@ -101,6 +102,19 @@ public final class EntityCapabilities {
} }
public abstract String capabilityNode(final String node); 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 { public static class EntityCapsHash extends Hash {

View file

@ -18,6 +18,7 @@ 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.info.InfoQuery;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.Collection; import java.util.Collection;
import java.util.Objects;
public class EntityCapabilities2 { public class EntityCapabilities2 {
@ -165,5 +166,19 @@ public class EntityCapabilities2 {
return String.format( return String.format(
"%s#%s.%s", Namespace.ENTITY_CAPABILITIES_2, algorithm.toString(), encoded()); "%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);
}
} }
} }

View file

@ -8,6 +8,7 @@ import im.conversations.android.xmpp.manager.BlockingManager;
import im.conversations.android.xmpp.manager.BookmarkManager; import im.conversations.android.xmpp.manager.BookmarkManager;
import im.conversations.android.xmpp.manager.CarbonsManager; import im.conversations.android.xmpp.manager.CarbonsManager;
import im.conversations.android.xmpp.manager.DiscoManager; import im.conversations.android.xmpp.manager.DiscoManager;
import im.conversations.android.xmpp.manager.PresenceManager;
import im.conversations.android.xmpp.manager.RosterManager; import im.conversations.android.xmpp.manager.RosterManager;
public final class Managers { public final class Managers {
@ -21,6 +22,7 @@ public final class Managers {
.put(BookmarkManager.class, new BookmarkManager(context, connection)) .put(BookmarkManager.class, new BookmarkManager(context, connection))
.put(CarbonsManager.class, new CarbonsManager(context, connection)) .put(CarbonsManager.class, new CarbonsManager(context, connection))
.put(DiscoManager.class, new DiscoManager(context, connection)) .put(DiscoManager.class, new DiscoManager(context, connection))
.put(PresenceManager.class, new PresenceManager(context, connection))
.put(RosterManager.class, new RosterManager(context, connection)) .put(RosterManager.class, new RosterManager(context, connection))
.build(); .build();
} }

View file

@ -5,15 +5,22 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import com.google.common.base.Strings; import com.google.common.base.Strings;
import com.google.common.collect.Collections2; import com.google.common.collect.Collections2;
import com.google.common.collect.ImmutableList;
import com.google.common.io.BaseEncoding; import com.google.common.io.BaseEncoding;
import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.MoreExecutors; 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 eu.siacs.conversations.xmpp.Jid;
import im.conversations.android.xmpp.Entity; import im.conversations.android.xmpp.Entity;
import im.conversations.android.xmpp.EntityCapabilities; import im.conversations.android.xmpp.EntityCapabilities;
import im.conversations.android.xmpp.EntityCapabilities2; import im.conversations.android.xmpp.EntityCapabilities2;
import im.conversations.android.xmpp.XmppConnection; 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.info.InfoQuery;
import im.conversations.android.xmpp.model.disco.items.Item; import im.conversations.android.xmpp.model.disco.items.Item;
import im.conversations.android.xmpp.model.disco.items.ItemsQuery; import im.conversations.android.xmpp.model.disco.items.ItemsQuery;
@ -25,6 +32,42 @@ import java.util.Objects;
public class DiscoManager extends AbstractManager { public class DiscoManager extends AbstractManager {
public static final String CAPABILITY_NODE = "http://conversations.im";
private static final Collection<String> 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<String> 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<String> FEATURES_NOTIFY =
Arrays.asList(Namespace.NICK, Namespace.AVATAR_METADATA, Namespace.BOOKMARKS2);
public DiscoManager(Context context, XmppConnection connection) { public DiscoManager(Context context, XmppConnection connection) {
super(context, connection); super(context, connection);
} }
@ -161,4 +204,52 @@ public class DiscoManager extends AbstractManager {
public boolean hasServerFeature(final String feature) { public boolean hasServerFeature(final String feature) {
return hasFeature(getAccount().address.getDomain(), 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<String> 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<Feature> 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";
}
}
} }

View file

@ -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<EntityCapabilities.Hash, InfoQuery> 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);
}
}

View file

@ -17,6 +17,10 @@ public class Hash extends Extension {
return Algorithm.tryParse(this.getAttribute("algo")); return Algorithm.tryParse(this.getAttribute("algo"));
} }
public void setAlgorithm(final Algorithm algorithm) {
this.setAttribute("algo", algorithm.toString());
}
public enum Algorithm { public enum Algorithm {
SHA_1, SHA_1,
SHA_256, SHA_256,

View file

@ -32,4 +32,11 @@ public class Capabilities extends Extension {
} }
return null; 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);
}
} }

View file

@ -32,4 +32,13 @@ public class LegacyCapabilities extends Extension {
return null; 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());
}
} }

View file

@ -12,4 +12,8 @@ public class Feature extends Extension {
public String getVar() { public String getVar() {
return this.getAttribute("var"); return this.getAttribute("var");
} }
public void setVar(final String feature) {
this.setAttribute("var", feature);
}
} }

View file

@ -24,4 +24,16 @@ public class Identity extends Extension {
public String getIdentityName() { public String getIdentityName() {
return this.getAttribute("name"); 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);
}
} }

View file

@ -8,6 +8,7 @@ import im.conversations.android.xmpp.XmppConnection;
import im.conversations.android.xmpp.manager.BlockingManager; import im.conversations.android.xmpp.manager.BlockingManager;
import im.conversations.android.xmpp.manager.BookmarkManager; import im.conversations.android.xmpp.manager.BookmarkManager;
import im.conversations.android.xmpp.manager.DiscoManager; import im.conversations.android.xmpp.manager.DiscoManager;
import im.conversations.android.xmpp.manager.PresenceManager;
import im.conversations.android.xmpp.manager.RosterManager; import im.conversations.android.xmpp.manager.RosterManager;
import java.util.function.Consumer; import java.util.function.Consumer;
@ -46,8 +47,6 @@ public class BindProcessor extends XmppConnection.Delegate implements Consumer<J
getManager(BookmarkManager.class).fetch(); getManager(BookmarkManager.class).fetch();
// connection.sendPresencePacket(new Presence()); getManager(PresenceManager.class).sendPresence();
// TODO send initial presence
} }
} }

View file

@ -71,7 +71,7 @@ public class IqProcessor extends XmppConnection.Delegate implements Consumer<Iq>
for (final Extension extension : extensions) { for (final Extension extension : extensions) {
response.addExtension(extension); response.addExtension(extension);
} }
connection.sendIqPacket(response); connection.sendIqPacket(response, null);
} }
public void sendErrorFor(final Iq request, final Condition condition) { public void sendErrorFor(final Iq request, final Condition condition) {
@ -82,6 +82,6 @@ public class IqProcessor extends XmppConnection.Delegate implements Consumer<Iq>
response.setId(id); response.setId(id);
final Error error = response.addExtension(new Error()); final Error error = response.addExtension(new Error());
error.setCondition(condition); error.setCondition(condition);
connection.sendIqPacket(response); connection.sendIqPacket(response, null);
} }
} }

View file

@ -2,4 +2,5 @@
<resources> <resources>
<string name="default_resource">Tablet</string> <string name="default_resource">Tablet</string>
<bool name="portrait_only">false</bool> <bool name="portrait_only">false</bool>
<bool name="is_device_table">true</bool>
</resources> </resources>

View file

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<bool name="is_device_table">true</bool>
<string name="default_resource">Phone</string> <string name="default_resource">Phone</string>
<bool name="portrait_only">true</bool> <bool name="portrait_only">true</bool>
<bool name="enter_is_send">false</bool> <bool name="enter_is_send">false</bool>