use stricter namespace matching in stream parser

Daniel Gultsch created

Change summary

src/main/java/eu/siacs/conversations/xml/LocalizedContent.java |  2 
src/main/java/eu/siacs/conversations/xml/Namespace.java        |  1 
src/main/java/eu/siacs/conversations/xml/Tag.java              |  4 
src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java  | 23 ++-
4 files changed, 21 insertions(+), 9 deletions(-)

Detailed changes

src/main/java/eu/siacs/conversations/xml/LocalizedContent.java 🔗

@@ -29,7 +29,7 @@ public class LocalizedContent {
                 final String childLanguage = child.getAttribute("xml:lang");
                 final String lang = childLanguage == null ? parentLanguage : childLanguage;
                 final String content = child.getContent();
-                if (content != null && (namespace == null || "jabber:client".equals(namespace))) {
+                if (content != null && (namespace == null || Namespace.JABBER_CLIENT.equals(namespace))) {
                     if (contents.put(lang, content) != null) {
                         //anything that has multiple contents for the same language is invalid
                         return null;

src/main/java/eu/siacs/conversations/xml/Namespace.java 🔗

@@ -2,6 +2,7 @@ package eu.siacs.conversations.xml;
 
 public final class Namespace {
     public static final String STREAMS = "http://etherx.jabber.org/streams";
+    public static final String JABBER_CLIENT = "jabber:client";
     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";

src/main/java/eu/siacs/conversations/xml/Tag.java 🔗

@@ -43,6 +43,10 @@ public class Tag {
         return name;
     }
 
+    public String identifier() {
+        return String.format("%s#%s", name, this.attributes.get("xmlns"));
+    }
+
     public String getAttribute(final String attrName) {
         return this.attributes.get(attrName);
     }

src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java 🔗

@@ -604,10 +604,10 @@ public class XmppConnection implements Runnable {
             } else if (nextTag.isStart("enabled", Namespace.STREAM_MANAGEMENT)) {
                 final Element enabled = tagReader.readElement(nextTag);
                 processEnabled(enabled);
-            } else if (nextTag.isStart("resumed")) {
+            } else if (nextTag.isStart("resumed", Namespace.STREAM_MANAGEMENT)) {
                 final Element resumed = tagReader.readElement(nextTag);
                 processResumed(resumed);
-            } else if (nextTag.isStart("r")) {
+            } else if (nextTag.isStart("r", Namespace.STREAM_MANAGEMENT)) {
                 tagReader.readElement(nextTag);
                 if (Config.EXTENDED_SM_LOGGING) {
                     Log.d(
@@ -618,7 +618,7 @@ public class XmppConnection implements Runnable {
                 }
                 final AckPacket ack = new AckPacket(this.stanzasReceived);
                 tagWriter.writeStanzaAsync(ack);
-            } else if (nextTag.isStart("a")) {
+            } else if (nextTag.isStart("a", Namespace.STREAM_MANAGEMENT)) {
                 boolean accountUiNeedsRefresh = false;
                 synchronized (NotificationService.CATCHUP_LOCK) {
                     if (mWaitingForSmCatchup.compareAndSet(true, false)) {
@@ -661,15 +661,22 @@ public class XmppConnection implements Runnable {
                 if (acknowledgedMessages) {
                     mXmppConnectionService.updateConversationUi();
                 }
-            } else if (nextTag.isStart("failed")) {
+            } else if (nextTag.isStart("failed", Namespace.STREAM_MANAGEMENT)) {
                 final Element failed = tagReader.readElement(nextTag);
                 processFailed(failed, true);
-            } else if (nextTag.isStart("iq")) {
+            } else if (nextTag.isStart("iq", Namespace.JABBER_CLIENT)) {
                 processIq(nextTag);
-            } else if (nextTag.isStart("message")) {
+            } else if (nextTag.isStart("message", Namespace.JABBER_CLIENT)) {
                 processMessage(nextTag);
-            } else if (nextTag.isStart("presence")) {
+            } else if (nextTag.isStart("presence", Namespace.JABBER_CLIENT)) {
                 processPresence(nextTag);
+            } else {
+                Log.e(
+                        Config.LOGTAG,
+                        account.getJid().asBareJid()
+                                + ": Encountered unknown stream element"
+                                + nextTag.identifier());
+                throw new StateChangingException(Account.State.INCOMPATIBLE_SERVER);
             }
             nextTag = tagReader.readTag();
         }
@@ -2263,7 +2270,7 @@ public class XmppConnection implements Runnable {
         }
         stream.setAttribute("version", "1.0");
         stream.setAttribute("xml:lang", LocalizedContent.STREAM_LANGUAGE);
-        stream.setAttribute("xmlns", "jabber:client");
+        stream.setAttribute("xmlns", Namespace.JABBER_CLIENT);
         stream.setAttribute("xmlns:stream", Namespace.STREAMS);
         tagWriter.writeTag(stream, flush);
     }