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			if (status == Message.STATUS_RECIEVED) {
160				parseNormal(message, account);
161			}
162			return null;
163		}
164		if (status == Message.STATUS_RECIEVED) {
165			fullJid = message.getAttribute("from");
166			updateLastseen(message, account,true);
167		} else {
168			fullJid = message.getAttribute("to");
169		}
170		String[] parts = fullJid.split("/");
171		Conversation conversation = mXmppConnectionService
172				.findOrCreateConversation(account, parts[0], false);
173		conversation.setLatestMarkableMessageId(getMarkableMessageId(packet));
174		String pgpBody = getPgpBody(message);
175		Message finishedMessage;
176		if (pgpBody != null) {
177			finishedMessage = new Message(conversation, fullJid, pgpBody,Message.ENCRYPTION_PGP, status);
178		} else {
179			String body = message.findChild("body").getContent();
180			finishedMessage=  new Message(conversation, fullJid, body,Message.ENCRYPTION_NONE, status);
181		}
182		finishedMessage.setTime(getTimestamp(message));
183		return finishedMessage;
184	}
185
186	public void parseError(MessagePacket packet, Account account) {
187		String[] fromParts = packet.getFrom().split("/");
188		mXmppConnectionService.markMessage(account, fromParts[0],
189				packet.getId(), Message.STATUS_SEND_FAILED);
190	}
191	
192	public void parseNormal(Element packet, Account account) {
193		if (packet.hasChild("displayed","urn:xmpp:chat-markers:0")) {
194			String id = packet.findChild("displayed","urn:xmpp:chat-markers:0").getAttribute("id");
195			String[] fromParts = packet.getAttribute("from").split("/");
196			updateLastseen(packet, account,true);
197			mXmppConnectionService.markMessage(account,fromParts[0], id, Message.STATUS_SEND_DISPLAYED);
198		} else if (packet.hasChild("received","urn:xmpp:chat-markers:0")) {
199			String id = packet.findChild("received","urn:xmpp:chat-markers:0").getAttribute("id");
200			String[] fromParts = packet.getAttribute("from").split("/");
201			updateLastseen(packet, account,false);
202			mXmppConnectionService.markMessage(account,fromParts[0], id, Message.STATUS_SEND_RECEIVED);
203		} else if (packet.hasChild("x")) {
204			Element x = packet.findChild("x");
205			if (x.hasChild("invite")) {
206				Conversation conversation = mXmppConnectionService.findOrCreateConversation(account, packet.getAttribute("from"),
207						true);
208				mXmppConnectionService.updateUi(conversation, false);
209			}
210
211		}
212	}
213
214	private String getPgpBody(Element message) {
215		Element child = message.findChild("x", "jabber:x:encrypted");
216		if (child == null) {
217			return null;
218		} else {
219			return child.getContent();
220		}
221	}
222	
223	private String getMarkableMessageId(Element message) {
224		if (message.hasChild("markable", "urn:xmpp:chat-markers:0")) {
225			return message.getAttribute("id");
226		} else {
227			return null;
228		}
229	}
230
231	
232}