MessageParser.java

  1package eu.siacs.conversations.parser;
  2
  3import java.util.List;
  4
  5import net.java.otr4j.session.Session;
  6import net.java.otr4j.session.SessionStatus;
  7import android.util.Log;
  8import eu.siacs.conversations.entities.Account;
  9import eu.siacs.conversations.entities.Conversation;
 10import eu.siacs.conversations.entities.Message;
 11import eu.siacs.conversations.services.XmppConnectionService;
 12import eu.siacs.conversations.xml.Element;
 13import eu.siacs.conversations.xmpp.stanzas.MessagePacket;
 14
 15public class MessageParser extends AbstractParser {
 16
 17	public MessageParser(XmppConnectionService service) {
 18		super(service);
 19	}
 20
 21	public Message parseChat(MessagePacket packet, Account account) {
 22		String[] fromParts = packet.getFrom().split("/");
 23		Conversation conversation = mXmppConnectionService
 24				.findOrCreateConversation(account, fromParts[0], false);
 25		conversation.setLatestMarkableMessageId(getMarkableMessageId(packet));
 26		updateLastseen(packet, account,true);
 27		String pgpBody = getPgpBody(packet);
 28		if (pgpBody != null) {
 29			return new Message(conversation, packet.getFrom(), pgpBody,
 30					Message.ENCRYPTION_PGP, Message.STATUS_RECIEVED);
 31		} else {
 32			return new Message(conversation, packet.getFrom(),
 33					packet.getBody(), Message.ENCRYPTION_NONE,
 34					Message.STATUS_RECIEVED);
 35		}
 36	}
 37
 38	public Message parseOtrChat(MessagePacket packet, Account account) {
 39		boolean properlyAddressed = (packet.getTo().split("/").length == 2)
 40				|| (account.countPresences() == 1);
 41		String[] fromParts = packet.getFrom().split("/");
 42		Conversation conversation = mXmppConnectionService
 43				.findOrCreateConversation(account, fromParts[0], false);
 44		updateLastseen(packet, account,true);
 45		String body = packet.getBody();
 46		if (!conversation.hasValidOtrSession()) {
 47			if (properlyAddressed) {
 48				Log.d("xmppService",
 49						"starting new otr session with "
 50								+ packet.getFrom()
 51								+ " because no valid otr session has been found");
 52				conversation.startOtrSession(
 53						mXmppConnectionService.getApplicationContext(),
 54						fromParts[1], false);
 55			} else {
 56				Log.d("xmppService", account.getJid()
 57						+ ": ignoring otr session with " + fromParts[0]);
 58				return null;
 59			}
 60		} else {
 61			String foreignPresence = conversation.getOtrSession()
 62					.getSessionID().getUserID();
 63			if (!foreignPresence.equals(fromParts[1])) {
 64				conversation.resetOtrSession();
 65				if (properlyAddressed) {
 66					Log.d("xmppService",
 67							"replacing otr session with " + packet.getFrom());
 68					conversation.startOtrSession(
 69							mXmppConnectionService.getApplicationContext(),
 70							fromParts[1], false);
 71				} else {
 72					return null;
 73				}
 74			}
 75		}
 76		try {
 77			Session otrSession = conversation.getOtrSession();
 78			SessionStatus before = otrSession.getSessionStatus();
 79			body = otrSession.transformReceiving(body);
 80			SessionStatus after = otrSession.getSessionStatus();
 81			if ((before != after) && (after == SessionStatus.ENCRYPTED)) {
 82				mXmppConnectionService.onOtrSessionEstablished(conversation);
 83			} else if ((before != after) && (after == SessionStatus.FINISHED)) {
 84				conversation.resetOtrSession();
 85			}
 86			// isEmpty is a work around for some weird clients which send emtpty
 87			// strings over otr
 88			if ((body == null) || (body.isEmpty())) {
 89				return null;
 90			}
 91			conversation.setLatestMarkableMessageId(getMarkableMessageId(packet));
 92			Message finishedMessage = new Message(conversation, packet.getFrom(), body,
 93					Message.ENCRYPTION_OTR, Message.STATUS_RECIEVED);
 94			finishedMessage.setTime(getTimestamp(packet));
 95			return finishedMessage;
 96		} catch (Exception e) {
 97			conversation.resetOtrSession();
 98			return null;
 99		}
100	}
101
102	public Message parseGroupchat(MessagePacket packet, Account account) {
103		int status;
104		String[] fromParts = packet.getFrom().split("/");
105		Conversation conversation = mXmppConnectionService
106				.findOrCreateConversation(account, fromParts[0], true);
107		if (packet.hasChild("subject")) {
108			conversation.getMucOptions().setSubject(
109					packet.findChild("subject").getContent());
110			mXmppConnectionService.updateUi(conversation, false);
111			return null;
112		}
113		if ((fromParts.length == 1)) {
114			return null;
115		}
116		String counterPart = fromParts[1];
117		if (counterPart.equals(conversation.getMucOptions().getNick())) {
118			if (mXmppConnectionService.markMessage(conversation,
119					packet.getId(), Message.STATUS_SEND)) {
120				return null;
121			} else {
122				status = Message.STATUS_SEND;
123			}
124		} else {
125			status = Message.STATUS_RECIEVED;
126		}
127		String pgpBody = getPgpBody(packet);
128		conversation.setLatestMarkableMessageId(getMarkableMessageId(packet));
129		Message finishedMessage;
130		if (pgpBody == null) {
131			finishedMessage = new Message(conversation, counterPart, packet.getBody(),
132					Message.ENCRYPTION_NONE, status);
133		} else {
134			finishedMessage=  new Message(conversation, counterPart, pgpBody,
135					Message.ENCRYPTION_PGP, status);
136		}
137		finishedMessage.setTime(getTimestamp(packet));
138		return finishedMessage;
139	}
140
141	public Message parseCarbonMessage(MessagePacket packet, Account account) {
142		int status;
143		String fullJid;
144		Element forwarded;
145		if (packet.hasChild("received")) {
146			forwarded = packet.findChild("received").findChild("forwarded");
147			status = Message.STATUS_RECIEVED;
148		} else if (packet.hasChild("sent")) {
149			forwarded = packet.findChild("sent").findChild("forwarded");
150			status = Message.STATUS_SEND;
151		} else {
152			return null;
153		}
154		if (forwarded == null) {
155			return null;
156		}
157		Element message = forwarded.findChild("message");
158		if ((message == null) || (!message.hasChild("body")))
159			return null; // either malformed or boring
160		if (status == Message.STATUS_RECIEVED) {
161			fullJid = message.getAttribute("from");
162			updateLastseen(message, account,true);
163		} else {
164			fullJid = message.getAttribute("to");
165		}
166		String[] parts = fullJid.split("/");
167		Conversation conversation = mXmppConnectionService
168				.findOrCreateConversation(account, parts[0], false);
169		conversation.setLatestMarkableMessageId(getMarkableMessageId(packet));
170		String pgpBody = getPgpBody(message);
171		Message finishedMessage;
172		if (pgpBody != null) {
173			finishedMessage = new Message(conversation, fullJid, pgpBody,Message.ENCRYPTION_PGP, status);
174		} else {
175			String body = message.findChild("body").getContent();
176			finishedMessage=  new Message(conversation, fullJid, body,Message.ENCRYPTION_NONE, status);
177		}
178		finishedMessage.setTime(getTimestamp(message));
179		return finishedMessage;
180	}
181
182	public void parseError(MessagePacket packet, Account account) {
183		String[] fromParts = packet.getFrom().split("/");
184		mXmppConnectionService.markMessage(account, fromParts[0],
185				packet.getId(), Message.STATUS_SEND_FAILED);
186	}
187	
188	public void parseNormal(MessagePacket packet, Account account) {
189		if (packet.hasChild("displayed","urn:xmpp:chat-markers:0")) {
190			String id = packet.findChild("displayed","urn:xmpp:chat-markers:0").getAttribute("id");
191			String[] fromParts = packet.getFrom().split("/");
192			updateLastseen(packet, account,true);
193			mXmppConnectionService.markMessage(account,fromParts[0], id, Message.STATUS_SEND_DISPLAYED);
194		} else if (packet.hasChild("received","urn:xmpp:chat-markers:0")) {
195			String id = packet.findChild("received","urn:xmpp:chat-markers:0").getAttribute("id");
196			String[] fromParts = packet.getFrom().split("/");
197			updateLastseen(packet, account,false);
198			mXmppConnectionService.markMessage(account,fromParts[0], id, Message.STATUS_SEND_RECEIVED);
199		} else if (packet.hasChild("x")) {
200			Element x = packet.findChild("x");
201			if (x.hasChild("invite")) {
202				Conversation conversation = mXmppConnectionService.findOrCreateConversation(account, packet.getFrom(),
203						true);
204				mXmppConnectionService.updateUi(conversation, false);
205			}
206
207		}
208	}
209
210	private String getPgpBody(Element message) {
211		Element child = message.findChild("x", "jabber:x:encrypted");
212		if (child == null) {
213			return null;
214		} else {
215			return child.getContent();
216		}
217	}
218	
219	private String getMarkableMessageId(Element message) {
220		if (message.hasChild("markable", "urn:xmpp:chat-markers:0")) {
221			return message.getAttribute("id");
222		} else {
223			return null;
224		}
225	}
226
227	
228}