parse 'received' carbon-copied error messages. fixes #3803

Daniel Gultsch created

Change summary

src/main/java/eu/siacs/conversations/generator/PresenceGenerator.java | 136 
src/main/java/eu/siacs/conversations/parser/MessageParser.java        |   8 
2 files changed, 75 insertions(+), 69 deletions(-)

Detailed changes

src/main/java/eu/siacs/conversations/generator/PresenceGenerator.java 🔗

@@ -13,81 +13,81 @@ import eu.siacs.conversations.xmpp.stanzas.PresencePacket;
 
 public class PresenceGenerator extends AbstractGenerator {
 
-	public PresenceGenerator(XmppConnectionService service) {
-		super(service);
-	}
+    public PresenceGenerator(XmppConnectionService service) {
+        super(service);
+    }
 
-	private PresencePacket subscription(String type, Contact contact) {
-		PresencePacket packet = new PresencePacket();
-		packet.setAttribute("type", type);
-		packet.setTo(contact.getJid());
-		packet.setFrom(contact.getAccount().getJid().asBareJid());
-		return packet;
-	}
+    private PresencePacket subscription(String type, Contact contact) {
+        PresencePacket packet = new PresencePacket();
+        packet.setAttribute("type", type);
+        packet.setTo(contact.getJid());
+        packet.setFrom(contact.getAccount().getJid().asBareJid());
+        return packet;
+    }
 
-	public PresencePacket requestPresenceUpdatesFrom(Contact contact) {
-		PresencePacket packet = subscription("subscribe", contact);
-		String displayName = contact.getAccount().getDisplayName();
-		if (!TextUtils.isEmpty(displayName)) {
-			packet.addChild("nick",Namespace.NICK).setContent(displayName);
-		}
-		return packet;
-	}
+    public PresencePacket requestPresenceUpdatesFrom(Contact contact) {
+        PresencePacket packet = subscription("subscribe", contact);
+        String displayName = contact.getAccount().getDisplayName();
+        if (!TextUtils.isEmpty(displayName)) {
+            packet.addChild("nick", Namespace.NICK).setContent(displayName);
+        }
+        return packet;
+    }
 
-	public PresencePacket stopPresenceUpdatesFrom(Contact contact) {
-		return subscription("unsubscribe", contact);
-	}
+    public PresencePacket stopPresenceUpdatesFrom(Contact contact) {
+        return subscription("unsubscribe", contact);
+    }
 
-	public PresencePacket stopPresenceUpdatesTo(Contact contact) {
-		return subscription("unsubscribed", contact);
-	}
+    public PresencePacket stopPresenceUpdatesTo(Contact contact) {
+        return subscription("unsubscribed", contact);
+    }
 
-	public PresencePacket sendPresenceUpdatesTo(Contact contact) {
-		return subscription("subscribed", contact);
-	}
+    public PresencePacket sendPresenceUpdatesTo(Contact contact) {
+        return subscription("subscribed", contact);
+    }
 
-	public PresencePacket selfPresence(Account account, Presence.Status status) {
-		return selfPresence(account, status, true);
-	}
+    public PresencePacket selfPresence(Account account, Presence.Status status) {
+        return selfPresence(account, status, true);
+    }
 
-	public PresencePacket selfPresence(final Account account, final Presence.Status status, final boolean personal) {
-		final PresencePacket packet = new PresencePacket();
-		if (personal) {
-			final String sig = account.getPgpSignature();
-			final String message = account.getPresenceStatusMessage();
-			if(status.toShowString() != null) {
-				packet.addChild("show").setContent(status.toShowString());
-			}
-			if (!TextUtils.isEmpty(message)) {
-				packet.addChild(new Element("status").setContent(message));
-			}
-			if (sig != null && mXmppConnectionService.getPgpEngine() != null) {
-				packet.addChild("x", "jabber:x:signed").setContent(sig);
-			}
-		}
-		final String capHash = getCapHash(account);
-		if (capHash != null) {
-			Element cap = packet.addChild("c",
-					"http://jabber.org/protocol/caps");
-			cap.setAttribute("hash", "sha-1");
-			cap.setAttribute("node", "http://conversations.im");
-			cap.setAttribute("ver", capHash);
-		}
-		return packet;
-	}
+    public PresencePacket selfPresence(final Account account, final Presence.Status status, final boolean personal) {
+        final PresencePacket packet = new PresencePacket();
+        if (personal) {
+            final String sig = account.getPgpSignature();
+            final String message = account.getPresenceStatusMessage();
+            if (status.toShowString() != null) {
+                packet.addChild("show").setContent(status.toShowString());
+            }
+            if (!TextUtils.isEmpty(message)) {
+                packet.addChild(new Element("status").setContent(message));
+            }
+            if (sig != null && mXmppConnectionService.getPgpEngine() != null) {
+                packet.addChild("x", "jabber:x:signed").setContent(sig);
+            }
+        }
+        final String capHash = getCapHash(account);
+        if (capHash != null) {
+            Element cap = packet.addChild("c",
+                    "http://jabber.org/protocol/caps");
+            cap.setAttribute("hash", "sha-1");
+            cap.setAttribute("node", "http://conversations.im");
+            cap.setAttribute("ver", capHash);
+        }
+        return packet;
+    }
 
-	public PresencePacket leave(final MucOptions mucOptions) {
-		PresencePacket presencePacket = new PresencePacket();
-		presencePacket.setTo(mucOptions.getSelf().getFullJid());
-		presencePacket.setFrom(mucOptions.getAccount().getJid());
-		presencePacket.setAttribute("type", "unavailable");
-		return presencePacket;
-	}
+    public PresencePacket leave(final MucOptions mucOptions) {
+        PresencePacket presencePacket = new PresencePacket();
+        presencePacket.setTo(mucOptions.getSelf().getFullJid());
+        presencePacket.setFrom(mucOptions.getAccount().getJid());
+        presencePacket.setAttribute("type", "unavailable");
+        return presencePacket;
+    }
 
-	public PresencePacket sendOfflinePresence(Account account) {
-		PresencePacket packet = new PresencePacket();
-		packet.setFrom(account.getJid());
-		packet.setAttribute("type","unavailable");
-		return packet;
-	}
+    public PresencePacket sendOfflinePresence(Account account) {
+        PresencePacket packet = new PresencePacket();
+        packet.setFrom(account.getJid());
+        packet.setAttribute("type", "unavailable");
+        return packet;
+    }
 }

src/main/java/eu/siacs/conversations/parser/MessageParser.java 🔗

@@ -308,8 +308,14 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece
         mXmppConnectionService.updateAccountUi();
     }
 
-    private boolean handleErrorMessage(Account account, MessagePacket packet) {
+    private boolean handleErrorMessage(final Account account, final MessagePacket packet) {
         if (packet.getType() == MessagePacket.TYPE_ERROR) {
+            if (packet.fromServer(account)) {
+                final Pair<MessagePacket, Long> forwarded = packet.getForwardedMessagePacket("received", "urn:xmpp:carbons:2");
+                if (forwarded != null) {
+                    return handleErrorMessage(account, forwarded.first);
+                }
+            }
             final Jid from = packet.getFrom();
             final String id = packet.getId();
             if (from != null && id != null) {