MessageParser.java

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