support mam:1
This commit is contained in:
parent
0fa97bdc11
commit
48e366e410
|
@ -11,6 +11,7 @@ import java.util.Set;
|
||||||
|
|
||||||
import eu.siacs.conversations.Config;
|
import eu.siacs.conversations.Config;
|
||||||
import eu.siacs.conversations.R;
|
import eu.siacs.conversations.R;
|
||||||
|
import eu.siacs.conversations.services.MessageArchiveService;
|
||||||
import eu.siacs.conversations.utils.JidHelper;
|
import eu.siacs.conversations.utils.JidHelper;
|
||||||
import eu.siacs.conversations.utils.UIHelper;
|
import eu.siacs.conversations.utils.UIHelper;
|
||||||
import eu.siacs.conversations.xml.Namespace;
|
import eu.siacs.conversations.xml.Namespace;
|
||||||
|
@ -66,6 +67,10 @@ public class MucOptions {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean mamSupport() {
|
||||||
|
return MessageArchiveService.Version.has(getFeatures());
|
||||||
|
}
|
||||||
|
|
||||||
public enum Affiliation {
|
public enum Affiliation {
|
||||||
OWNER("owner", 4, R.string.owner),
|
OWNER("owner", 4, R.string.owner),
|
||||||
ADMIN("admin", 3, R.string.admin),
|
ADMIN("admin", 3, R.string.admin),
|
||||||
|
@ -456,12 +461,9 @@ public class MucOptions {
|
||||||
return conversation.getBooleanAttribute(Conversation.ATTRIBUTE_MEMBERS_ONLY, false);
|
return conversation.getBooleanAttribute(Conversation.ATTRIBUTE_MEMBERS_ONLY, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean mamSupport() {
|
|
||||||
return hasFeature(Namespace.MAM) || hasFeature(Namespace.MAM_LEGACY);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean mamLegacy() {
|
public List<String> getFeatures() {
|
||||||
return hasFeature(Namespace.MAM_LEGACY) && !hasFeature(Namespace.MAM);
|
return this.serviceDiscoveryResult != null ? this.serviceDiscoveryResult.features : Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean nonanonymous() {
|
public boolean nonanonymous() {
|
||||||
|
|
|
@ -248,10 +248,10 @@ public class IqGenerator extends AbstractGenerator {
|
||||||
|
|
||||||
public IqPacket queryMessageArchiveManagement(final MessageArchiveService.Query mam) {
|
public IqPacket queryMessageArchiveManagement(final MessageArchiveService.Query mam) {
|
||||||
final IqPacket packet = new IqPacket(IqPacket.TYPE.SET);
|
final IqPacket packet = new IqPacket(IqPacket.TYPE.SET);
|
||||||
final Element query = packet.query(mam.isLegacy() ? Namespace.MAM_LEGACY : Namespace.MAM);
|
final Element query = packet.query(mam.version.namespace);
|
||||||
query.setAttribute("queryid", mam.getQueryId());
|
query.setAttribute("queryid", mam.getQueryId());
|
||||||
final Data data = new Data();
|
final Data data = new Data();
|
||||||
data.setFormType(mam.isLegacy() ? Namespace.MAM_LEGACY : Namespace.MAM);
|
data.setFormType(mam.version.namespace);
|
||||||
if (mam.muc()) {
|
if (mam.muc()) {
|
||||||
packet.setTo(mam.getWith());
|
packet.setTo(mam.getWith());
|
||||||
} else if (mam.getWith() != null) {
|
} else if (mam.getWith() != null) {
|
||||||
|
|
|
@ -239,16 +239,15 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece
|
||||||
Long timestamp = null;
|
Long timestamp = null;
|
||||||
boolean isCarbon = false;
|
boolean isCarbon = false;
|
||||||
String serverMsgId = null;
|
String serverMsgId = null;
|
||||||
final Element fin = original.findChild("fin", Namespace.MAM_LEGACY);
|
final Element fin = original.findChild("fin", MessageArchiveService.Version.MAM_0.namespace);
|
||||||
if (fin != null) {
|
if (fin != null) {
|
||||||
mXmppConnectionService.getMessageArchiveService().processFinLegacy(fin, original.getFrom());
|
mXmppConnectionService.getMessageArchiveService().processFinLegacy(fin, original.getFrom());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final boolean mamLegacy = original.hasChild("result", Namespace.MAM_LEGACY);
|
final Element result = MessageArchiveService.Version.findResult(original);
|
||||||
final Element result = original.findChild("result", mamLegacy ? Namespace.MAM_LEGACY : Namespace.MAM);
|
|
||||||
final MessageArchiveService.Query query = result == null ? null : mXmppConnectionService.getMessageArchiveService().findQuery(result.getAttribute("queryid"));
|
final MessageArchiveService.Query query = result == null ? null : mXmppConnectionService.getMessageArchiveService().findQuery(result.getAttribute("queryid"));
|
||||||
if (query != null && query.validFrom(original.getFrom())) {
|
if (query != null && query.validFrom(original.getFrom())) {
|
||||||
Pair<MessagePacket, Long> f = original.getForwardedMessagePacket("result", mamLegacy ? Namespace.MAM_LEGACY : Namespace.MAM);
|
Pair<MessagePacket, Long> f = original.getForwardedMessagePacket("result", query.version.namespace);
|
||||||
if (f == null) {
|
if (f == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ import eu.siacs.conversations.xml.Element;
|
||||||
import eu.siacs.conversations.xmpp.OnAdvancedStreamFeaturesLoaded;
|
import eu.siacs.conversations.xmpp.OnAdvancedStreamFeaturesLoaded;
|
||||||
import eu.siacs.conversations.xmpp.mam.MamReference;
|
import eu.siacs.conversations.xmpp.mam.MamReference;
|
||||||
import eu.siacs.conversations.xmpp.stanzas.IqPacket;
|
import eu.siacs.conversations.xmpp.stanzas.IqPacket;
|
||||||
|
import eu.siacs.conversations.xmpp.stanzas.MessagePacket;
|
||||||
import rocks.xmpp.addr.Jid;
|
import rocks.xmpp.addr.Jid;
|
||||||
|
|
||||||
public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded {
|
public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded {
|
||||||
|
@ -29,6 +30,66 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded {
|
||||||
private final HashSet<Query> queries = new HashSet<>();
|
private final HashSet<Query> queries = new HashSet<>();
|
||||||
private final ArrayList<Query> pendingQueries = new ArrayList<>();
|
private final ArrayList<Query> pendingQueries = new ArrayList<>();
|
||||||
|
|
||||||
|
public enum Version {
|
||||||
|
MAM_0("urn:xmpp:mam:0", true),
|
||||||
|
MAM_1("urn:xmpp:mam:1", false),
|
||||||
|
MAM_2("urn:xmpp:mam:2", false);
|
||||||
|
|
||||||
|
public final boolean legacy;
|
||||||
|
public final String namespace;
|
||||||
|
|
||||||
|
Version(String namespace, boolean legacy) {
|
||||||
|
this.namespace = namespace;
|
||||||
|
this.legacy = legacy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Version get(Account account) {
|
||||||
|
return get(account,null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Version get(Account account, Conversation conversation) {
|
||||||
|
if (conversation == null || conversation.getMode() == Conversation.MODE_SINGLE) {
|
||||||
|
return get(account.getXmppConnection().getFeatures().getAccountFeatures());
|
||||||
|
} else {
|
||||||
|
return get(conversation.getMucOptions().getFeatures());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Version get(List<String> features) {
|
||||||
|
final Version[] values = values();
|
||||||
|
for(int i = values.length -1; i >= 0; --i) {
|
||||||
|
for(String feature : features) {
|
||||||
|
if (values[i].namespace.equals(feature)) {
|
||||||
|
return values[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return MAM_0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean has(List<String> features) {
|
||||||
|
for(String feature : features) {
|
||||||
|
for(Version version : values()) {
|
||||||
|
if (version.namespace.equals(feature)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Element findResult(MessagePacket packet) {
|
||||||
|
for(Version version : values()) {
|
||||||
|
Element result = packet.findChild("result", version.namespace);
|
||||||
|
if (result != null) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
MessageArchiveService(final XmppConnectionService service) {
|
MessageArchiveService(final XmppConnectionService service) {
|
||||||
this.mXmppConnectionService = service;
|
this.mXmppConnectionService = service;
|
||||||
}
|
}
|
||||||
|
@ -168,7 +229,7 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded {
|
||||||
Log.d(Config.LOGTAG, account.getJid().asBareJid().toString() + ": running mam query " + query.toString());
|
Log.d(Config.LOGTAG, account.getJid().asBareJid().toString() + ": running mam query " + query.toString());
|
||||||
IqPacket packet = this.mXmppConnectionService.getIqGenerator().queryMessageArchiveManagement(query);
|
IqPacket packet = this.mXmppConnectionService.getIqGenerator().queryMessageArchiveManagement(query);
|
||||||
this.mXmppConnectionService.sendIqPacket(account, packet, (a, p) -> {
|
this.mXmppConnectionService.sendIqPacket(account, packet, (a, p) -> {
|
||||||
Element fin = p.findChild("fin", Namespace.MAM);
|
Element fin = p.findChild("fin", query.version.namespace);
|
||||||
if (p.getType() == IqPacket.TYPE.TIMEOUT) {
|
if (p.getType() == IqPacket.TYPE.TIMEOUT) {
|
||||||
synchronized (MessageArchiveService.this.queries) {
|
synchronized (MessageArchiveService.this.queries) {
|
||||||
MessageArchiveService.this.queries.remove(query);
|
MessageArchiveService.this.queries.remove(query);
|
||||||
|
@ -390,16 +451,21 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded {
|
||||||
private PagingOrder pagingOrder = PagingOrder.NORMAL;
|
private PagingOrder pagingOrder = PagingOrder.NORMAL;
|
||||||
private XmppConnectionService.OnMoreMessagesLoaded callback = null;
|
private XmppConnectionService.OnMoreMessagesLoaded callback = null;
|
||||||
private boolean catchup = true;
|
private boolean catchup = true;
|
||||||
|
public final Version version;
|
||||||
|
|
||||||
|
|
||||||
Query(Conversation conversation, MamReference start, long end, boolean catchup) {
|
Query(Conversation conversation, MamReference start, long end, boolean catchup) {
|
||||||
this(conversation.getAccount(), catchup ? start : start.timeOnly(), end);
|
this(conversation.getAccount(), Version.get(conversation.getAccount(), conversation), catchup ? start : start.timeOnly(), end);
|
||||||
this.conversation = conversation;
|
this.conversation = conversation;
|
||||||
this.pagingOrder = catchup ? PagingOrder.NORMAL : PagingOrder.REVERSE;
|
this.pagingOrder = catchup ? PagingOrder.NORMAL : PagingOrder.REVERSE;
|
||||||
this.catchup = catchup;
|
this.catchup = catchup;
|
||||||
}
|
}
|
||||||
|
|
||||||
Query(Account account, MamReference start, long end) {
|
Query(Account account, MamReference start, long end) {
|
||||||
|
this(account, Version.get(account), start, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
Query(Account account, Version version, MamReference start, long end) {
|
||||||
this.account = account;
|
this.account = account;
|
||||||
if (start.getReference() != null) {
|
if (start.getReference() != null) {
|
||||||
this.reference = start.getReference();
|
this.reference = start.getReference();
|
||||||
|
@ -408,10 +474,11 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded {
|
||||||
}
|
}
|
||||||
this.end = end;
|
this.end = end;
|
||||||
this.queryId = new BigInteger(50, mXmppConnectionService.getRNG()).toString(32);
|
this.queryId = new BigInteger(50, mXmppConnectionService.getRNG()).toString(32);
|
||||||
|
this.version = version;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Query page(String reference) {
|
private Query page(String reference) {
|
||||||
Query query = new Query(this.account, new MamReference(this.start, reference), this.end);
|
Query query = new Query(this.account, this.version, new MamReference(this.start, reference), this.end);
|
||||||
query.conversation = conversation;
|
query.conversation = conversation;
|
||||||
query.totalCount = totalCount;
|
query.totalCount = totalCount;
|
||||||
query.actualCount = actualCount;
|
query.actualCount = actualCount;
|
||||||
|
@ -433,11 +500,7 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isLegacy() {
|
public boolean isLegacy() {
|
||||||
if (conversation == null || conversation.getMode() == Conversation.MODE_SINGLE) {
|
return version.legacy;
|
||||||
return account.getXmppConnection().getFeatures().mamLegacy();
|
|
||||||
} else {
|
|
||||||
return conversation.getMucOptions().mamLegacy();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean safeToExtractTrueCounterpart() {
|
public boolean safeToExtractTrueCounterpart() {
|
||||||
|
@ -570,6 +633,7 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded {
|
||||||
builder.append(this.reference);
|
builder.append(this.reference);
|
||||||
}
|
}
|
||||||
builder.append(", catchup=").append(Boolean.toString(catchup));
|
builder.append(", catchup=").append(Boolean.toString(catchup));
|
||||||
|
builder.append(", ns=").append(version.namespace);
|
||||||
return builder.toString();
|
return builder.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3766,11 +3766,11 @@ public class XmppConnectionService extends Service {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void fetchMamPreferences(Account account, final OnMamPreferencesFetched callback) {
|
public void fetchMamPreferences(Account account, final OnMamPreferencesFetched callback) {
|
||||||
final boolean legacy = account.getXmppConnection().getFeatures().mamLegacy();
|
final MessageArchiveService.Version version = MessageArchiveService.Version.get(account);
|
||||||
IqPacket request = new IqPacket(IqPacket.TYPE.GET);
|
IqPacket request = new IqPacket(IqPacket.TYPE.GET);
|
||||||
request.addChild("prefs", legacy ? Namespace.MAM_LEGACY : Namespace.MAM);
|
request.addChild("prefs", version.namespace);
|
||||||
sendIqPacket(account, request, (account1, packet) -> {
|
sendIqPacket(account, request, (account1, packet) -> {
|
||||||
Element prefs = packet.findChild("prefs", legacy ? Namespace.MAM_LEGACY : Namespace.MAM);
|
Element prefs = packet.findChild("prefs", version.namespace);
|
||||||
if (packet.getType() == IqPacket.TYPE.RESULT && prefs != null) {
|
if (packet.getType() == IqPacket.TYPE.RESULT && prefs != null) {
|
||||||
callback.onPreferencesFetched(prefs);
|
callback.onPreferencesFetched(prefs);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -8,8 +8,6 @@ public final class Namespace {
|
||||||
public static final String HTTP_UPLOAD = "urn:xmpp:http:upload:0";
|
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 HTTP_UPLOAD_LEGACY = "urn:xmpp:http:upload";
|
||||||
public static final String STANZA_IDS = "urn:xmpp:sid:0";
|
public static final String STANZA_IDS = "urn:xmpp:sid:0";
|
||||||
public static final String MAM = "urn:xmpp:mam:2";
|
|
||||||
public static final String MAM_LEGACY = "urn:xmpp:mam:0";
|
|
||||||
public static final String IDLE = "urn:xmpp:idle:1";
|
public static final String IDLE = "urn:xmpp:idle:1";
|
||||||
public static final String DATA = "jabber:x:data";
|
public static final String DATA = "jabber:x:data";
|
||||||
public static final String OOB = "jabber:x:oob";
|
public static final String OOB = "jabber:x:oob";
|
||||||
|
|
|
@ -31,6 +31,7 @@ import java.security.PrivateKey;
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Hashtable;
|
import java.util.Hashtable;
|
||||||
|
@ -70,6 +71,7 @@ import eu.siacs.conversations.entities.ServiceDiscoveryResult;
|
||||||
import eu.siacs.conversations.generator.IqGenerator;
|
import eu.siacs.conversations.generator.IqGenerator;
|
||||||
import eu.siacs.conversations.persistance.FileBackend;
|
import eu.siacs.conversations.persistance.FileBackend;
|
||||||
import eu.siacs.conversations.services.MemorizingTrustManager;
|
import eu.siacs.conversations.services.MemorizingTrustManager;
|
||||||
|
import eu.siacs.conversations.services.MessageArchiveService;
|
||||||
import eu.siacs.conversations.services.NotificationService;
|
import eu.siacs.conversations.services.NotificationService;
|
||||||
import eu.siacs.conversations.services.XmppConnectionService;
|
import eu.siacs.conversations.services.XmppConnectionService;
|
||||||
import eu.siacs.conversations.utils.CryptoHelper;
|
import eu.siacs.conversations.utils.CryptoHelper;
|
||||||
|
@ -1786,13 +1788,12 @@ public class XmppConnection implements Runnable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean mam() {
|
public boolean mam() {
|
||||||
return hasDiscoFeature(account.getJid().asBareJid(), Namespace.MAM)
|
return MessageArchiveService.Version.has(getAccountFeatures());
|
||||||
|| hasDiscoFeature(account.getJid().asBareJid(), Namespace.MAM_LEGACY);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean mamLegacy() {
|
public List<String> getAccountFeatures() {
|
||||||
return !hasDiscoFeature(account.getJid().asBareJid(), Namespace.MAM)
|
ServiceDiscoveryResult result = connection.disco.get(account.getJid().asBareJid());
|
||||||
&& hasDiscoFeature(account.getJid().asBareJid(), Namespace.MAM_LEGACY);
|
return result == null ? Collections.emptyList() : result.getFeatures();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean push() {
|
public boolean push() {
|
||||||
|
|
Loading…
Reference in a new issue