MessageParser.java

  1package eu.siacs.conversations.parser;
  2
  3import net.java.otr4j.session.Session;
  4import net.java.otr4j.session.SessionStatus;
  5import eu.siacs.conversations.entities.Account;
  6import eu.siacs.conversations.entities.Conversation;
  7import eu.siacs.conversations.entities.Message;
  8import eu.siacs.conversations.services.XmppConnectionService;
  9import eu.siacs.conversations.utils.CryptoHelper;
 10import eu.siacs.conversations.xml.Element;
 11import eu.siacs.conversations.xmpp.stanzas.MessagePacket;
 12
 13public class MessageParser extends AbstractParser {
 14
 15	public MessageParser(XmppConnectionService service) {
 16		super(service);
 17	}
 18
 19	public Message parseChat(MessagePacket packet, Account account) {
 20		String[] fromParts = packet.getFrom().split("/");
 21		Conversation conversation = mXmppConnectionService
 22				.findOrCreateConversation(account, fromParts[0], false);
 23		conversation.setLatestMarkableMessageId(getMarkableMessageId(packet));
 24		updateLastseen(packet, account,true);
 25		String pgpBody = getPgpBody(packet);
 26		Message finishedMessage;
 27		if (pgpBody != null) {
 28			finishedMessage = new Message(conversation, packet.getFrom(), pgpBody,
 29					Message.ENCRYPTION_PGP, Message.STATUS_RECIEVED);
 30		} else {
 31			finishedMessage = new Message(conversation, packet.getFrom(),
 32					packet.getBody(), Message.ENCRYPTION_NONE,
 33					Message.STATUS_RECIEVED);
 34		}
 35		finishedMessage.setTime(getTimestamp(packet));
 36		return finishedMessage;
 37	}
 38
 39	public Message parseOtrChat(MessagePacket packet, Account account) {
 40		boolean properlyAddressed = (packet.getTo().split("/").length == 2)
 41				|| (account.countPresences() == 1);
 42		String[] fromParts = packet.getFrom().split("/");
 43		Conversation conversation = mXmppConnectionService
 44				.findOrCreateConversation(account, fromParts[0], false);
 45		updateLastseen(packet, account,true);
 46		String body = packet.getBody();
 47		if (!conversation.hasValidOtrSession()) {
 48			if (properlyAddressed) {
 49				conversation.startOtrSession(
 50						mXmppConnectionService.getApplicationContext(),
 51						fromParts[1], false);
 52			} else {
 53				return null;
 54			}
 55		} else {
 56			String foreignPresence = conversation.getOtrSession()
 57					.getSessionID().getUserID();
 58			if (!foreignPresence.equals(fromParts[1])) {
 59				conversation.endOtrIfNeeded();
 60				if (properlyAddressed) {
 61					conversation.startOtrSession(
 62							mXmppConnectionService.getApplicationContext(),
 63							fromParts[1], false);
 64				} else {
 65					return null;
 66				}
 67			}
 68		}
 69		try {
 70			Session otrSession = conversation.getOtrSession();
 71			SessionStatus before = otrSession.getSessionStatus();
 72			body = otrSession.transformReceiving(body);
 73			SessionStatus after = otrSession.getSessionStatus();
 74			if ((before != after) && (after == SessionStatus.ENCRYPTED)) {
 75				mXmppConnectionService.onOtrSessionEstablished(conversation);
 76			} else if ((before != after) && (after == SessionStatus.FINISHED)) {
 77				conversation.resetOtrSession();
 78			}
 79			if ((body == null) || (body.isEmpty())) {
 80				return null;
 81			}
 82			if (body.startsWith(CryptoHelper.FILETRANSFER)) {
 83				String key = body.substring(CryptoHelper.FILETRANSFER.length());
 84				conversation.setSymmetricKey(CryptoHelper.hexToBytes(key));
 85				return null;
 86			}
 87			conversation.setLatestMarkableMessageId(getMarkableMessageId(packet));
 88			Message finishedMessage = new Message(conversation, packet.getFrom(), body,
 89					Message.ENCRYPTION_OTR, Message.STATUS_RECIEVED);
 90			finishedMessage.setTime(getTimestamp(packet));
 91			return finishedMessage;
 92		} catch (Exception e) {
 93			String receivedId = packet.getId();
 94			if (receivedId!=null) {
 95				mXmppConnectionService.replyWithNotAcceptable(account,packet);
 96			}
 97			conversation.endOtrIfNeeded();
 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}