fixed a couple of muc issues. added jingle listener (which doesn't do anything for now)

Daniel Gultsch created

Change summary

src/eu/siacs/conversations/entities/Conversation.java            |  2 
src/eu/siacs/conversations/entities/MucOptions.java              |  4 
src/eu/siacs/conversations/services/XmppConnectionService.java   | 43 +
src/eu/siacs/conversations/ui/MucDetailsActivity.java            |  8 
src/eu/siacs/conversations/xml/Element.java                      | 27 
src/eu/siacs/conversations/xmpp/OnJinglePacketReceived.java      |  8 
src/eu/siacs/conversations/xmpp/XmppConnection.java              | 33 
src/eu/siacs/conversations/xmpp/stanzas/jingle/Content.java      | 13 
src/eu/siacs/conversations/xmpp/stanzas/jingle/JinglePacket.java | 54 ++
src/eu/siacs/conversations/xmpp/stanzas/jingle/Reason.java       | 13 
10 files changed, 173 insertions(+), 32 deletions(-)

Detailed changes

src/eu/siacs/conversations/entities/Conversation.java 🔗

@@ -293,7 +293,7 @@ public class Conversation extends AbstractEntity {
 		return this.otrFingerprint;
 	}
 
-	public MucOptions getMucOptions() {
+	public synchronized MucOptions getMucOptions() {
 		if (this.mucOptions == null) {
 			this.mucOptions = new MucOptions();
 		}

src/eu/siacs/conversations/entities/MucOptions.java 🔗

@@ -107,7 +107,7 @@ public class MucOptions {
 			String type = packet.getAttribute("type");
 			if (type==null) {
 				User user = new User();
-				Element item = packet.findChild("x").findChild("item");
+				Element item = packet.findChild("x","http://jabber.org/protocol/muc#user").findChild("item");
 				user.setName(name);
 				user.setAffiliation(item.getAttribute("affiliation"));
 				user.setRole(item.getAttribute("role"));
@@ -121,7 +121,7 @@ public class MucOptions {
 				}
 			} else if (type.equals("unavailable")) {
 				if (name.equals(getNick())) {
-					Element item = packet.findChild("x").findChild("item");
+					Element item = packet.findChild("x","http://jabber.org/protocol/muc#user").findChild("item");
 					String nick = item.getAttribute("nick");
 					if (nick!=null) {
 						aboutToRename = false;

src/eu/siacs/conversations/services/XmppConnectionService.java 🔗

@@ -39,6 +39,7 @@ import eu.siacs.conversations.utils.UIHelper;
 import eu.siacs.conversations.xml.Element;
 import eu.siacs.conversations.xmpp.OnBindListener;
 import eu.siacs.conversations.xmpp.OnIqPacketReceived;
+import eu.siacs.conversations.xmpp.OnJinglePacketReceived;
 import eu.siacs.conversations.xmpp.OnMessagePacketReceived;
 import eu.siacs.conversations.xmpp.OnPresencePacketReceived;
 import eu.siacs.conversations.xmpp.OnStatusChanged;
@@ -47,6 +48,7 @@ import eu.siacs.conversations.xmpp.XmppConnection;
 import eu.siacs.conversations.xmpp.stanzas.IqPacket;
 import eu.siacs.conversations.xmpp.stanzas.MessagePacket;
 import eu.siacs.conversations.xmpp.stanzas.PresencePacket;
+import eu.siacs.conversations.xmpp.stanzas.jingle.JinglePacket;
 import android.app.AlarmManager;
 import android.app.PendingIntent;
 import android.app.Service;
@@ -230,12 +232,18 @@ public class XmppConnectionService extends Service {
 		@Override
 		public void onPresencePacketReceived(Account account,
 				PresencePacket packet) {
-			if (packet.hasChild("x")
-					&& (packet.findChild("x").getAttribute("xmlns")
-							.startsWith("http://jabber.org/protocol/muc"))) {
+			if (packet.hasChild("x","http://jabber.org/protocol/muc#user")) {
 				Conversation muc = findMuc(
 						packet.getAttribute("from").split("/")[0], account);
 				if (muc != null) {
+					muc.getMucOptions().processPacket(packet);
+				} else {
+					Log.d(LOGTAG,account.getJid()+": could not find muc for received muc package "+packet.toString());
+				}
+			} else if (packet.hasChild("x","http://jabber.org/protocol/muc")) {
+				Conversation muc = findMuc(packet.getAttribute("from").split("/")[0], account);
+				if (muc != null) {
+					Log.d(LOGTAG,account.getJid()+": reading muc status packet "+packet.toString());
 					int error = muc.getMucOptions().getError();
 					muc.getMucOptions().processPacket(packet);
 					if ((muc.getMucOptions().getError() != error)
@@ -267,10 +275,8 @@ public class XmppConnectionService extends Service {
 							contact.updatePresence(fromParts[1], Presences.parseShow(packet.findChild("show")));
 							PgpEngine pgp = getPgpEngine();
 							if (pgp != null) {
-								Element x = packet.findChild("x");
-								if ((x != null)
-										&& (x.getAttribute("xmlns")
-												.equals("jabber:x:signed"))) {
+								Element x = packet.findChild("x","jabber:x:signed");
+								if (x != null) {
 									try {
 										contact.setPgpKeyId(pgp.fetchKeyId(
 												packet.findChild("status")
@@ -311,7 +317,7 @@ public class XmppConnectionService extends Service {
 							// TODO: ask user to handle it maybe
 						}
 					} else {
-						// Log.d(LOGTAG, packet.toString());
+						//Log.d(LOGTAG, packet.toString());
 					}
 					replaceContactInConversation(contact.getJid(), contact);
 				}
@@ -333,6 +339,14 @@ public class XmppConnectionService extends Service {
 			}
 		}
 	};
+	
+	private OnJinglePacketReceived jingleListener = new OnJinglePacketReceived() {
+		
+		@Override
+		public void onJinglePacketReceived(Account account, JinglePacket packet) {
+			Log.d(LOGTAG,account.getJid()+": jingle packet received"+packet.toString());
+		}
+	};
 
 	private OpenPgpServiceConnection pgpServiceConnection;
 	private PgpEngine mPgpEngine = null;
@@ -498,6 +512,8 @@ public class XmppConnectionService extends Service {
 		databaseBackend = DatabaseBackend.getInstance(getApplicationContext());
 		this.accounts = databaseBackend.getAccounts();
 
+		this.getConversations();
+		
 		getContentResolver().registerContentObserver(
 				ContactsContract.Contacts.CONTENT_URI, true, contactObserver);
 		this.pgpServiceConnection = new OpenPgpServiceConnection(
@@ -569,6 +585,7 @@ public class XmppConnectionService extends Service {
 		connection.setOnPresencePacketReceivedListener(this.presenceListener);
 		connection
 				.setOnUnregisteredIqPacketReceivedListener(this.unknownIqListener);
+		connection.setOnJinglePacketReceivedListener(this.jingleListener);
 		connection
 				.setOnTLSExceptionReceivedListener(new OnTLSExceptionReceived() {
 
@@ -897,9 +914,6 @@ public class XmppConnectionService extends Service {
 			conversation.setAccount(account);
 			if (muc) {
 				conversation.setMode(Conversation.MODE_MULTI);
-				if (account.getStatus() == Account.STATUS_ONLINE) {
-					joinMuc(conversation);
-				}
 			} else {
 				conversation.setMode(Conversation.MODE_SINGLE);
 			}
@@ -919,9 +933,6 @@ public class XmppConnectionService extends Service {
 			if (muc) {
 				conversation = new Conversation(conversationName, account, jid,
 						Conversation.MODE_MULTI);
-				if (account.getStatus() == Account.STATUS_ONLINE) {
-					joinMuc(conversation);
-				}
 			} else {
 				conversation = new Conversation(conversationName, account, jid,
 						Conversation.MODE_SINGLE);
@@ -930,6 +941,9 @@ public class XmppConnectionService extends Service {
 			this.databaseBackend.createConversation(conversation);
 		}
 		this.conversations.add(conversation);
+		if ((account.getStatus() == Account.STATUS_ONLINE)&&(conversation.getMode() == Conversation.MODE_MULTI)) {
+			joinMuc(conversation);
+		}
 		if (this.convChangedListener != null) {
 			this.convChangedListener.onConversationListChanged();
 		}
@@ -1037,6 +1051,7 @@ public class XmppConnectionService extends Service {
 			x.addChild("history").setAttribute("seconds", diff + "");
 		}
 		packet.addChild(x);
+		Log.d(LOGTAG,conversation.getAccount().getJid()+": joining muc "+packet.toString());
 		conversation.getAccount().getXmppConnection()
 				.sendPresencePacket(packet);
 	}

src/eu/siacs/conversations/ui/MucDetailsActivity.java 🔗

@@ -82,9 +82,6 @@ public class MucDetailsActivity extends XmppActivity {
 	@Override
 	protected void onCreate(Bundle savedInstanceState) {
 		super.onCreate(savedInstanceState);
-		if (getIntent().getAction().equals(ACTION_VIEW_MUC)) {
-			this.uuid = getIntent().getExtras().getString("uuid");
-		}
 		setContentView(R.layout.activity_muc_details);
 		mYourNick = (EditText) findViewById(R.id.muc_your_nick);
 		mFullJid = (TextView) findViewById(R.id.muc_jabberid);
@@ -135,6 +132,9 @@ public class MucDetailsActivity extends XmppActivity {
 	void onBackendConnected() {
 		SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
 		boolean useSubject = preferences.getBoolean("use_subject_in_muc", true);
+		if (getIntent().getAction().equals(ACTION_VIEW_MUC)) {
+			this.uuid = getIntent().getExtras().getString("uuid");
+		}
 		if (uuid != null) {
 			for (Conversation mConv : xmppConnectionService.getConversations()) {
 				if (mConv.getUuid().equals(uuid)) {
@@ -183,6 +183,8 @@ public class MucDetailsActivity extends XmppActivity {
 					membersView.addView(view);
 				}
 			}
+		} else {
+			Log.d("xmppService","uuid in muc details was null");
 		}
 	}
 }

src/eu/siacs/conversations/xml/Element.java 🔗

@@ -50,19 +50,34 @@ public class Element {
 		return null;
 	}
 	
-	public boolean hasChild(String name) {
+	public Element findChild(String name, String xmlns) {
 		for(Element child : this.children) {
-			if (child.getName().equals(name)) {
-				return true;
+			if (child.getName().equals(name)&&(child.getAttribute("xmlns").equals(xmlns))) {
+				return child;
 			}
 		}
-		return false;
+		return null;
+	}
+	
+	public boolean hasChild(String name) {
+		return findChild(name) != null;
+	}
+	
+	public boolean hasChild(String name, String xmlns) {
+		return findChild(name, xmlns) != null;
 	}
 	
+	
+	
 	public List<Element> getChildren() {
 		return this.children;
 	}
 	
+	public Element setChildren(List<Element> children) {
+		this.children = children;
+		return this;
+	}
+	
 	public String getContent() {
 		return content;
 	}
@@ -85,6 +100,10 @@ public class Element {
 		}
 	}
 	
+	public Hashtable<String, String> getAttributes() {
+		return this.attributes;
+	}
+	
 	public String toString() {
 		StringBuilder elementOutput = new StringBuilder();
 		if ((content==null)&&(children.size() == 0)) {

src/eu/siacs/conversations/xmpp/OnJinglePacketReceived.java 🔗

@@ -0,0 +1,8 @@
+package eu.siacs.conversations.xmpp;
+
+import eu.siacs.conversations.entities.Account;
+import eu.siacs.conversations.xmpp.stanzas.jingle.JinglePacket;
+
+public interface OnJinglePacketReceived extends PacketReceived {
+	public void onJinglePacketReceived(Account account, JinglePacket packet);
+}

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

@@ -46,6 +46,7 @@ import eu.siacs.conversations.xmpp.stanzas.AbstractStanza;
 import eu.siacs.conversations.xmpp.stanzas.IqPacket;
 import eu.siacs.conversations.xmpp.stanzas.MessagePacket;
 import eu.siacs.conversations.xmpp.stanzas.PresencePacket;
+import eu.siacs.conversations.xmpp.stanzas.jingle.JinglePacket;
 import eu.siacs.conversations.xmpp.stanzas.streammgmt.AckPacket;
 import eu.siacs.conversations.xmpp.stanzas.streammgmt.EnablePacket;
 import eu.siacs.conversations.xmpp.stanzas.streammgmt.RequestPacket;
@@ -86,6 +87,7 @@ public class XmppConnection implements Runnable {
 
 	private Hashtable<String, PacketReceived> packetCallbacks = new Hashtable<String, PacketReceived>();
 	private OnPresencePacketReceived presenceListener = null;
+	private OnJinglePacketReceived jingleListener = null;
 	private OnIqPacketReceived unregisteredIqListener = null;
 	private OnMessagePacketReceived messageListener = null;
 	private OnStatusChanged statusListener = null;
@@ -284,6 +286,10 @@ public class XmppConnection implements Runnable {
 		while (!nextTag.isEnd(element.getName())) {
 			if (!nextTag.isNo()) {
 				Element child = tagReader.readElement(nextTag);
+				if ((packetType == PACKET_IQ)&&("jingle".equals(child.getName()))) {
+					element = new JinglePacket();
+					element.setAttributes(currentTag.getAttributes());
+				}
 				element.addChild(child);
 			}
 			nextTag = tagReader.readTag();
@@ -296,15 +302,22 @@ public class XmppConnection implements Runnable {
 	private void processIq(Tag currentTag) throws XmlPullParserException,
 			IOException {
 		IqPacket packet = (IqPacket) processPacket(currentTag, PACKET_IQ);
-		if (packetCallbacks.containsKey(packet.getId())) {
-			if (packetCallbacks.get(packet.getId()) instanceof OnIqPacketReceived) {
-				((OnIqPacketReceived) packetCallbacks.get(packet.getId()))
-						.onIqPacketReceived(account, packet);
+		
+		if (packet instanceof JinglePacket) {
+			if (this.jingleListener !=null) {
+				this.jingleListener.onJinglePacketReceived(account, (JinglePacket) packet);
+			}
+		} else {
+			if (packetCallbacks.containsKey(packet.getId())) {
+				if (packetCallbacks.get(packet.getId()) instanceof OnIqPacketReceived) {
+					((OnIqPacketReceived) packetCallbacks.get(packet.getId()))
+							.onIqPacketReceived(account, packet);
+				}
+	
+				packetCallbacks.remove(packet.getId());
+			} else if (this.unregisteredIqListener != null) {
+				this.unregisteredIqListener.onIqPacketReceived(account, packet);
 			}
-
-			packetCallbacks.remove(packet.getId());
-		} else if (this.unregisteredIqListener != null) {
-			this.unregisteredIqListener.onIqPacketReceived(account, packet);
 		}
 	}
 
@@ -684,6 +697,10 @@ public class XmppConnection implements Runnable {
 			OnPresencePacketReceived listener) {
 		this.presenceListener = listener;
 	}
+	
+	public void setOnJinglePacketReceivedListener(OnJinglePacketReceived listener) {
+		this.jingleListener = listener;
+	}
 
 	public void setOnStatusChangedListener(OnStatusChanged listener) {
 		this.statusListener = listener;

src/eu/siacs/conversations/xmpp/stanzas/jingle/Content.java 🔗

@@ -0,0 +1,13 @@
+package eu.siacs.conversations.xmpp.stanzas.jingle;
+
+import eu.siacs.conversations.xml.Element;
+
+public class Content extends Element {
+	private Content(String name) {
+		super(name);
+	}
+	
+	public Content() {
+		super("content");
+	}
+}

src/eu/siacs/conversations/xmpp/stanzas/jingle/JinglePacket.java 🔗

@@ -0,0 +1,54 @@
+package eu.siacs.conversations.xmpp.stanzas.jingle;
+
+import eu.siacs.conversations.xml.Element;
+import eu.siacs.conversations.xmpp.stanzas.IqPacket;
+
+public class JinglePacket extends IqPacket {
+	Content content = null;
+	Reason reason = null;
+	
+	@Override
+	public Element addChild(Element child) {
+		if ("jingle".equals(child.getName())) {
+			Element contentElement = child.findChild("content");
+			if (contentElement!=null) {
+				this.content = new Content();
+				this.content.setChildren(contentElement.getChildren());
+				this.content.setAttributes(contentElement.getAttributes());
+			}
+			Element reasonElement = child.findChild("reason");
+			if (reasonElement!=null) {
+				this.reason = new Reason();
+				this.reason.setChildren(reasonElement.getChildren());
+				this.reason.setAttributes(reasonElement.getAttributes());
+			}
+			this.build();
+			this.findChild("jingle").setAttributes(child.getAttributes());
+		}
+		return child;
+	}
+	
+	public JinglePacket setContent(Content content) {
+		this.content = content;
+		this.build();
+		return this;
+	}
+	
+	public JinglePacket setReason(Reason reason) {
+		this.reason = reason;
+		this.build();
+		return this;
+	}
+	
+	private void build() {
+		this.children.clear();
+		Element jingle = addChild("jingle", "urn:xmpp:jingle:1");
+		if (this.content!=null) {
+			jingle.addChild(this.content);
+		}
+		if (this.reason != null) {
+			jingle.addChild(this.reason);
+		}
+		this.children.add(jingle);
+	}
+}

src/eu/siacs/conversations/xmpp/stanzas/jingle/Reason.java 🔗

@@ -0,0 +1,13 @@
+package eu.siacs.conversations.xmpp.stanzas.jingle;
+
+import eu.siacs.conversations.xml.Element;
+
+public class Reason extends Element {
+	private Reason(String name) {
+		super(name);
+	}
+	
+	public Reason() {
+		super("reason");
+	}
+}