MessageParser.java

  1package eu.siacs.conversations.parser;
  2
  3import net.java.otr4j.session.Session;
  4import net.java.otr4j.session.SessionStatus;
  5
  6import eu.siacs.conversations.entities.Account;
  7import eu.siacs.conversations.entities.Contact;
  8import eu.siacs.conversations.entities.Conversation;
  9import eu.siacs.conversations.entities.Message;
 10import eu.siacs.conversations.entities.MucOptions;
 11import eu.siacs.conversations.http.HttpConnectionManager;
 12import eu.siacs.conversations.services.MessageArchiveService;
 13import eu.siacs.conversations.services.XmppConnectionService;
 14import eu.siacs.conversations.utils.CryptoHelper;
 15import eu.siacs.conversations.xml.Element;
 16import eu.siacs.conversations.xmpp.OnMessagePacketReceived;
 17import eu.siacs.conversations.xmpp.chatstate.ChatState;
 18import eu.siacs.conversations.xmpp.jid.Jid;
 19import eu.siacs.conversations.xmpp.pep.Avatar;
 20import eu.siacs.conversations.xmpp.stanzas.MessagePacket;
 21
 22public class MessageParser extends AbstractParser implements
 23		OnMessagePacketReceived {
 24	public MessageParser(XmppConnectionService service) {
 25		super(service);
 26	}
 27
 28	private boolean extractChatState(Conversation conversation, final Element element) {
 29		ChatState state = ChatState.parse(element);
 30		if (state != null && conversation != null) {
 31			final Account account = conversation.getAccount();
 32			Jid from = element.getAttributeAsJid("from");
 33			if (from != null && from.toBareJid().equals(account.getJid().toBareJid())) {
 34				conversation.setOutgoingChatState(state);
 35				return false;
 36			} else {
 37				return conversation.setIncomingChatState(state);
 38			}
 39		}
 40		return false;
 41	}
 42
 43	private Message parseChat(MessagePacket packet, Account account) {
 44		final Jid jid = packet.getFrom();
 45		if (jid == null) {
 46			return null;
 47		}
 48		Conversation conversation = mXmppConnectionService.findOrCreateConversation(account, jid.toBareJid(), false);
 49		String pgpBody = getPgpBody(packet);
 50		Message finishedMessage;
 51		if (pgpBody != null) {
 52			finishedMessage = new Message(conversation,
 53					pgpBody, Message.ENCRYPTION_PGP, Message.STATUS_RECEIVED);
 54		} else {
 55			finishedMessage = new Message(conversation,
 56					packet.getBody(), Message.ENCRYPTION_NONE,
 57					Message.STATUS_RECEIVED);
 58		}
 59		finishedMessage.setRemoteMsgId(packet.getId());
 60		finishedMessage.markable = isMarkable(packet);
 61		if (conversation.getMode() == Conversation.MODE_MULTI
 62				&& !jid.isBareJid()) {
 63			final Jid trueCounterpart = conversation.getMucOptions()
 64					.getTrueCounterpart(jid.getResourcepart());
 65			if (trueCounterpart != null) {
 66				updateLastseen(packet, account, trueCounterpart, false);
 67			}
 68			finishedMessage.setType(Message.TYPE_PRIVATE);
 69			finishedMessage.setTrueCounterpart(trueCounterpart);
 70			if (conversation.hasDuplicateMessage(finishedMessage)) {
 71				return null;
 72			}
 73		} else {
 74			updateLastseen(packet, account, true);
 75		}
 76		finishedMessage.setCounterpart(jid);
 77		finishedMessage.setTime(getTimestamp(packet));
 78		extractChatState(conversation,packet);
 79		return finishedMessage;
 80	}
 81
 82	private Message parseOtrChat(MessagePacket packet, Account account) {
 83		final Jid to = packet.getTo();
 84		final Jid from = packet.getFrom();
 85		if (to == null || from == null) {
 86			return null;
 87		}
 88		boolean properlyAddressed = !to.isBareJid() || account.countPresences() == 1;
 89		Conversation conversation = mXmppConnectionService
 90				.findOrCreateConversation(account, from.toBareJid(), false);
 91		String presence;
 92		if (from.isBareJid()) {
 93			presence = "";
 94		} else {
 95			presence = from.getResourcepart();
 96		}
 97		extractChatState(conversation, packet);
 98		updateLastseen(packet, account, true);
 99		String body = packet.getBody();
100		if (body.matches("^\\?OTRv\\d{1,2}\\?.*")) {
101			conversation.endOtrIfNeeded();
102		}
103		if (!conversation.hasValidOtrSession()) {
104			if (properlyAddressed) {
105				conversation.startOtrSession(presence,false);
106			} else {
107				return null;
108			}
109		} else {
110			String foreignPresence = conversation.getOtrSession()
111					.getSessionID().getUserID();
112			if (!foreignPresence.equals(presence)) {
113				conversation.endOtrIfNeeded();
114				if (properlyAddressed) {
115					conversation.startOtrSession(presence, false);
116				} else {
117					return null;
118				}
119			}
120		}
121		try {
122			conversation.setLastReceivedOtrMessageId(packet.getId());
123			Session otrSession = conversation.getOtrSession();
124			SessionStatus before = otrSession.getSessionStatus();
125			body = otrSession.transformReceiving(body);
126			SessionStatus after = otrSession.getSessionStatus();
127			if ((before != after) && (after == SessionStatus.ENCRYPTED)) {
128				conversation.setNextEncryption(Message.ENCRYPTION_OTR);
129				mXmppConnectionService.onOtrSessionEstablished(conversation);
130			} else if ((before != after) && (after == SessionStatus.FINISHED)) {
131				conversation.setNextEncryption(Message.ENCRYPTION_NONE);
132				conversation.resetOtrSession();
133				mXmppConnectionService.updateConversationUi();
134			}
135			if ((body == null) || (body.isEmpty())) {
136				return null;
137			}
138			if (body.startsWith(CryptoHelper.FILETRANSFER)) {
139				String key = body.substring(CryptoHelper.FILETRANSFER.length());
140				conversation.setSymmetricKey(CryptoHelper.hexToBytes(key));
141				return null;
142			}
143			Message finishedMessage = new Message(conversation, body, Message.ENCRYPTION_OTR,
144					Message.STATUS_RECEIVED);
145			finishedMessage.setTime(getTimestamp(packet));
146			finishedMessage.setRemoteMsgId(packet.getId());
147			finishedMessage.markable = isMarkable(packet);
148			finishedMessage.setCounterpart(from);
149			conversation.setLastReceivedOtrMessageId(null);
150			return finishedMessage;
151		} catch (Exception e) {
152			conversation.resetOtrSession();
153			return null;
154		}
155	}
156
157	private Message parseGroupchat(MessagePacket packet, Account account) {
158		int status;
159		final Jid from = packet.getFrom();
160		if (from == null) {
161			return null;
162		}
163		if (mXmppConnectionService.find(account.pendingConferenceLeaves,
164				account, from.toBareJid()) != null) {
165			return null;
166		}
167		Conversation conversation = mXmppConnectionService
168				.findOrCreateConversation(account, from.toBareJid(), true);
169		final Jid trueCounterpart = conversation.getMucOptions().getTrueCounterpart(from.getResourcepart());
170		if (trueCounterpart != null) {
171			updateLastseen(packet, account, trueCounterpart, false);
172		}
173		if (packet.hasChild("subject")) {
174			conversation.setHasMessagesLeftOnServer(true);
175			conversation.getMucOptions().setSubject(packet.findChild("subject").getContent());
176			mXmppConnectionService.updateConversationUi();
177			return null;
178		}
179
180		final Element x = packet.findChild("x", "http://jabber.org/protocol/muc#user");
181		if (from.isBareJid() && (x == null || !x.hasChild("status"))) {
182			return null;
183		} else if (from.isBareJid() && x.hasChild("status")) {
184			for(Element child : x.getChildren()) {
185				if (child.getName().equals("status")) {
186					String code = child.getAttribute("code");
187					if (code.contains(MucOptions.STATUS_CODE_ROOM_CONFIG_CHANGED)) {
188						mXmppConnectionService.fetchConferenceConfiguration(conversation);
189					}
190				}
191			}
192			return null;
193		}
194
195		if (from.getResourcepart().equals(conversation.getMucOptions().getActualNick())) {
196			if (mXmppConnectionService.markMessage(conversation,
197					packet.getId(), Message.STATUS_SEND_RECEIVED)) {
198				return null;
199			} else if (packet.getId() == null) {
200				Message message = conversation.findSentMessageWithBody(packet.getBody());
201				if (message != null) {
202					mXmppConnectionService.markMessage(message,Message.STATUS_SEND_RECEIVED);
203					return null;
204				} else {
205					status = Message.STATUS_SEND;
206				}
207			} else {
208				status = Message.STATUS_SEND;
209			}
210		} else {
211			status = Message.STATUS_RECEIVED;
212		}
213		String pgpBody = getPgpBody(packet);
214		Message finishedMessage;
215		if (pgpBody == null) {
216			finishedMessage = new Message(conversation,
217					packet.getBody(), Message.ENCRYPTION_NONE, status);
218		} else {
219			finishedMessage = new Message(conversation, pgpBody,
220					Message.ENCRYPTION_PGP, status);
221		}
222		finishedMessage.setRemoteMsgId(packet.getId());
223		finishedMessage.markable = isMarkable(packet);
224		finishedMessage.setCounterpart(from);
225		if (status == Message.STATUS_RECEIVED) {
226			finishedMessage.setTrueCounterpart(conversation.getMucOptions()
227					.getTrueCounterpart(from.getResourcepart()));
228		}
229		if (packet.hasChild("delay")
230				&& conversation.hasDuplicateMessage(finishedMessage)) {
231			return null;
232		}
233		finishedMessage.setTime(getTimestamp(packet));
234		return finishedMessage;
235	}
236
237	private Message parseCarbonMessage(final MessagePacket packet, final Account account) {
238		int status;
239		final Jid fullJid;
240		Element forwarded;
241		if (packet.hasChild("received", "urn:xmpp:carbons:2")) {
242			forwarded = packet.findChild("received", "urn:xmpp:carbons:2")
243					.findChild("forwarded", "urn:xmpp:forward:0");
244			status = Message.STATUS_RECEIVED;
245		} else if (packet.hasChild("sent", "urn:xmpp:carbons:2")) {
246			forwarded = packet.findChild("sent", "urn:xmpp:carbons:2")
247					.findChild("forwarded", "urn:xmpp:forward:0");
248			status = Message.STATUS_SEND;
249		} else {
250			return null;
251		}
252		if (forwarded == null) {
253			return null;
254		}
255		Element message = forwarded.findChild("message");
256		if (message == null) {
257			return null;
258		}
259		if (!message.hasChild("body")) {
260			if (status == Message.STATUS_RECEIVED
261					&& message.getAttribute("from") != null) {
262				parseNonMessage(message, account);
263			} else if (status == Message.STATUS_SEND
264					&& message.hasChild("displayed", "urn:xmpp:chat-markers:0")) {
265				final Jid to = message.getAttributeAsJid("to");
266				if (to != null) {
267					final Conversation conversation = mXmppConnectionService.find(
268							mXmppConnectionService.getConversations(), account,
269							to.toBareJid());
270					if (conversation != null) {
271						mXmppConnectionService.markRead(conversation);
272					}
273				}
274			}
275			return null;
276		}
277		if (status == Message.STATUS_RECEIVED) {
278			fullJid = message.getAttributeAsJid("from");
279			if (fullJid == null) {
280				return null;
281			} else {
282				updateLastseen(message, account, true);
283			}
284		} else {
285			fullJid = message.getAttributeAsJid("to");
286			if (fullJid == null) {
287				return null;
288			}
289		}
290		if (message.hasChild("x","http://jabber.org/protocol/muc#user")
291				&& "chat".equals(message.getAttribute("type"))) {
292			return null;
293		}
294		Conversation conversation = mXmppConnectionService
295				.findOrCreateConversation(account, fullJid.toBareJid(), false);
296		String pgpBody = getPgpBody(message);
297		Message finishedMessage;
298		if (pgpBody != null) {
299			finishedMessage = new Message(conversation, pgpBody,
300					Message.ENCRYPTION_PGP, status);
301		} else {
302			String body = message.findChild("body").getContent();
303			finishedMessage = new Message(conversation, body,
304					Message.ENCRYPTION_NONE, status);
305		}
306		extractChatState(conversation,message);
307		finishedMessage.setTime(getTimestamp(message));
308		finishedMessage.setRemoteMsgId(message.getAttribute("id"));
309		finishedMessage.markable = isMarkable(message);
310		finishedMessage.setCounterpart(fullJid);
311		if (conversation.getMode() == Conversation.MODE_MULTI
312				&& !fullJid.isBareJid()) {
313			finishedMessage.setType(Message.TYPE_PRIVATE);
314			finishedMessage.setTrueCounterpart(conversation.getMucOptions()
315					.getTrueCounterpart(fullJid.getResourcepart()));
316			if (conversation.hasDuplicateMessage(finishedMessage)) {
317				return null;
318			}
319		}
320		return finishedMessage;
321	}
322
323	private Message parseMamMessage(MessagePacket packet, final Account account) {
324		final Element result = packet.findChild("result","urn:xmpp:mam:0");
325		if (result == null ) {
326			return null;
327		}
328		final MessageArchiveService.Query query = this.mXmppConnectionService.getMessageArchiveService().findQuery(result.getAttribute("queryid"));
329		if (query!=null) {
330			query.incrementTotalCount();
331		}
332		final Element forwarded = result.findChild("forwarded","urn:xmpp:forward:0");
333		if (forwarded == null) {
334			return null;
335		}
336		final Element message = forwarded.findChild("message");
337		if (message == null) {
338			return null;
339		}
340		final Element body = message.findChild("body");
341		if (body == null || message.hasChild("private","urn:xmpp:carbons:2") || message.hasChild("no-copy","urn:xmpp:hints")) {
342			return null;
343		}
344		int encryption;
345		String content = getPgpBody(message);
346		if (content != null) {
347			encryption = Message.ENCRYPTION_PGP;
348		} else {
349			encryption = Message.ENCRYPTION_NONE;
350			content = body.getContent();
351		}
352		if (content == null) {
353			return null;
354		}
355		final long timestamp = getTimestamp(forwarded);
356		final Jid to = message.getAttributeAsJid("to");
357		final Jid from = message.getAttributeAsJid("from");
358		Jid counterpart;
359		int status;
360		Conversation conversation;
361		if (from!=null && to != null && from.toBareJid().equals(account.getJid().toBareJid())) {
362			status = Message.STATUS_SEND;
363			conversation = this.mXmppConnectionService.findOrCreateConversation(account,to.toBareJid(),false,query);
364			counterpart = to;
365		} else if (from !=null && to != null) {
366			status = Message.STATUS_RECEIVED;
367			conversation = this.mXmppConnectionService.findOrCreateConversation(account,from.toBareJid(),false,query);
368			counterpart = from;
369		} else {
370			return null;
371		}
372		Message finishedMessage = new Message(conversation,content,encryption,status);
373		finishedMessage.setTime(timestamp);
374		finishedMessage.setCounterpart(counterpart);
375		finishedMessage.setRemoteMsgId(message.getAttribute("id"));
376		finishedMessage.setServerMsgId(result.getAttribute("id"));
377		if (conversation.hasDuplicateMessage(finishedMessage)) {
378			return null;
379		}
380		if (query!=null) {
381			query.incrementMessageCount();
382		}
383		return finishedMessage;
384	}
385
386	private void parseError(final MessagePacket packet, final Account account) {
387		final Jid from = packet.getFrom();
388		mXmppConnectionService.markMessage(account, from.toBareJid(),
389				packet.getId(), Message.STATUS_SEND_FAILED);
390	}
391
392	private void parseNonMessage(Element packet, Account account) {
393		final Jid from = packet.getAttributeAsJid("from");
394		if (extractChatState(from == null ? null : mXmppConnectionService.find(account,from), packet)) {
395			mXmppConnectionService.updateConversationUi();
396		}
397		Element invite = extractInvite(packet);
398		if (invite != null) {
399			Conversation conversation = mXmppConnectionService.findOrCreateConversation(account, from, true);
400			if (!conversation.getMucOptions().online()) {
401				Element password = invite.findChild("password");
402				conversation.getMucOptions().setPassword(password == null ? null : password.getContent());
403				mXmppConnectionService.databaseBackend.updateConversation(conversation);
404				mXmppConnectionService.joinMuc(conversation);
405				mXmppConnectionService.updateConversationUi();
406			}
407		}
408		if (packet.hasChild("event", "http://jabber.org/protocol/pubsub#event")) {
409			Element event = packet.findChild("event",
410					"http://jabber.org/protocol/pubsub#event");
411			parseEvent(event, from, account);
412		} else if (from != null && packet.hasChild("displayed", "urn:xmpp:chat-markers:0")) {
413			String id = packet
414					.findChild("displayed", "urn:xmpp:chat-markers:0")
415					.getAttribute("id");
416			updateLastseen(packet, account, true);
417			final Message displayedMessage = mXmppConnectionService.markMessage(account, from.toBareJid(), id, Message.STATUS_SEND_DISPLAYED);
418			Message message = displayedMessage == null ? null :displayedMessage.prev();
419			while (message != null
420					&& message.getStatus() == Message.STATUS_SEND_RECEIVED
421					&& message.getTimeSent() < displayedMessage.getTimeSent()) {
422				mXmppConnectionService.markMessage(message, Message.STATUS_SEND_DISPLAYED);
423				message = message.prev();
424			}
425		} else if (from != null
426				&& packet.hasChild("received", "urn:xmpp:chat-markers:0")) {
427			String id = packet.findChild("received", "urn:xmpp:chat-markers:0")
428					.getAttribute("id");
429			updateLastseen(packet, account, false);
430			mXmppConnectionService.markMessage(account, from.toBareJid(),
431					id, Message.STATUS_SEND_RECEIVED);
432		} else if (from != null
433				&& packet.hasChild("received", "urn:xmpp:receipts")) {
434			String id = packet.findChild("received", "urn:xmpp:receipts")
435					.getAttribute("id");
436			updateLastseen(packet, account, false);
437			mXmppConnectionService.markMessage(account, from.toBareJid(),
438					id, Message.STATUS_SEND_RECEIVED);
439		}
440	}
441
442	private Element extractInvite(Element message) {
443		Element x = message.findChild("x","http://jabber.org/protocol/muc#user");
444		if (x == null) {
445			x = message.findChild("x","jabber:x:conference");
446		}
447		if (x != null && x.hasChild("invite")) {
448			return x;
449		} else {
450			return null;
451		}
452	}
453
454	private void parseEvent(final Element event, final Jid from, final Account account) {
455		Element items = event.findChild("items");
456		if (items == null) {
457			return;
458		}
459		String node = items.getAttribute("node");
460		if (node == null) {
461			return;
462		}
463		if (node.equals("urn:xmpp:avatar:metadata")) {
464			Avatar avatar = Avatar.parseMetadata(items);
465			if (avatar != null) {
466				avatar.owner = from;
467				if (mXmppConnectionService.getFileBackend().isAvatarCached(
468						avatar)) {
469					if (account.getJid().toBareJid().equals(from)) {
470						if (account.setAvatar(avatar.getFilename())) {
471							mXmppConnectionService.databaseBackend
472									.updateAccount(account);
473						}
474						mXmppConnectionService.getAvatarService().clear(
475								account);
476						mXmppConnectionService.updateConversationUi();
477						mXmppConnectionService.updateAccountUi();
478					} else {
479						Contact contact = account.getRoster().getContact(
480								from);
481						contact.setAvatar(avatar.getFilename());
482						mXmppConnectionService.getAvatarService().clear(
483								contact);
484						mXmppConnectionService.updateConversationUi();
485						mXmppConnectionService.updateRosterUi();
486					}
487				} else {
488					mXmppConnectionService.fetchAvatar(account, avatar);
489				}
490			}
491		} else if (node.equals("http://jabber.org/protocol/nick")) {
492			Element item = items.findChild("item");
493			if (item != null) {
494				Element nick = item.findChild("nick",
495						"http://jabber.org/protocol/nick");
496				if (nick != null) {
497					if (from != null) {
498						Contact contact = account.getRoster().getContact(
499								from);
500						contact.setPresenceName(nick.getContent());
501						mXmppConnectionService.getAvatarService().clear(account);
502						mXmppConnectionService.updateConversationUi();
503						mXmppConnectionService.updateAccountUi();
504					}
505				}
506			}
507		}
508	}
509
510	private String getPgpBody(Element message) {
511		Element child = message.findChild("x", "jabber:x:encrypted");
512		if (child == null) {
513			return null;
514		} else {
515			return child.getContent();
516		}
517	}
518
519	private boolean isMarkable(Element message) {
520		return message.hasChild("markable", "urn:xmpp:chat-markers:0");
521	}
522
523	@Override
524	public void onMessagePacketReceived(Account account, MessagePacket packet) {
525		Message message = null;
526		this.parseNick(packet, account);
527		if ((packet.getType() == MessagePacket.TYPE_CHAT || packet.getType() == MessagePacket.TYPE_NORMAL)) {
528			if ((packet.getBody() != null)
529					&& (packet.getBody().startsWith("?OTR"))) {
530				message = this.parseOtrChat(packet, account);
531				if (message != null) {
532					message.markUnread();
533				}
534			} else if (packet.hasChild("body") && extractInvite(packet) == null) {
535				message = this.parseChat(packet, account);
536				if (message != null) {
537					message.markUnread();
538				}
539			} else if (packet.hasChild("received", "urn:xmpp:carbons:2")
540					|| (packet.hasChild("sent", "urn:xmpp:carbons:2"))) {
541				message = this.parseCarbonMessage(packet, account);
542				if (message != null) {
543					if (message.getStatus() == Message.STATUS_SEND) {
544						account.activateGracePeriod();
545						mXmppConnectionService.markRead(message.getConversation());
546					} else {
547						message.markUnread();
548					}
549				}
550			} else if (packet.hasChild("result","urn:xmpp:mam:0")) {
551				message = parseMamMessage(packet, account);
552				if (message != null) {
553					Conversation conversation = message.getConversation();
554					conversation.add(message);
555					mXmppConnectionService.databaseBackend.createMessage(message);
556				}
557				return;
558			} else if (packet.hasChild("fin","urn:xmpp:mam:0")) {
559				Element fin = packet.findChild("fin","urn:xmpp:mam:0");
560				mXmppConnectionService.getMessageArchiveService().processFin(fin);
561			} else {
562				parseNonMessage(packet, account);
563			}
564		} else if (packet.getType() == MessagePacket.TYPE_GROUPCHAT) {
565			message = this.parseGroupchat(packet, account);
566			if (message != null) {
567				if (message.getStatus() == Message.STATUS_RECEIVED) {
568					message.markUnread();
569				} else {
570					mXmppConnectionService.markRead(message.getConversation());
571					account.activateGracePeriod();
572				}
573			}
574		} else if (packet.getType() == MessagePacket.TYPE_ERROR) {
575			this.parseError(packet, account);
576			return;
577		} else if (packet.getType() == MessagePacket.TYPE_HEADLINE) {
578			this.parseHeadline(packet, account);
579			return;
580		}
581		if ((message == null) || (message.getBody() == null)) {
582			return;
583		}
584		if ((mXmppConnectionService.confirmMessages())
585				&& ((packet.getId() != null))) {
586			if (packet.hasChild("markable", "urn:xmpp:chat-markers:0")) {
587				MessagePacket receipt = mXmppConnectionService
588						.getMessageGenerator().received(account, packet,
589								"urn:xmpp:chat-markers:0");
590				mXmppConnectionService.sendMessagePacket(account, receipt);
591			}
592			if (packet.hasChild("request", "urn:xmpp:receipts")) {
593				MessagePacket receipt = mXmppConnectionService
594						.getMessageGenerator().received(account, packet,
595								"urn:xmpp:receipts");
596				mXmppConnectionService.sendMessagePacket(account, receipt);
597			}
598		}
599		Conversation conversation = message.getConversation();
600		conversation.add(message);
601		if (account.getXmppConnection() != null && account.getXmppConnection().getFeatures().advancedStreamFeaturesLoaded()) {
602			if (conversation.setLastMessageTransmitted(System.currentTimeMillis())) {
603				mXmppConnectionService.updateConversation(conversation);
604			}
605		}
606
607		if (message.getStatus() == Message.STATUS_RECEIVED
608				&& conversation.getOtrSession() != null
609				&& !conversation.getOtrSession().getSessionID().getUserID()
610				.equals(message.getCounterpart().getResourcepart())) {
611			conversation.endOtrIfNeeded();
612		}
613
614		if (packet.getType() != MessagePacket.TYPE_ERROR) {
615			if (message.getEncryption() == Message.ENCRYPTION_NONE
616					|| mXmppConnectionService.saveEncryptedMessages()) {
617				mXmppConnectionService.databaseBackend.createMessage(message);
618			}
619		}
620		final HttpConnectionManager manager = this.mXmppConnectionService.getHttpConnectionManager();
621		if (message.trusted() && message.bodyContainsDownloadable() && manager.getAutoAcceptFileSize() > 0) {
622			manager.createNewConnection(message);
623		} else if (!message.isRead()) {
624			mXmppConnectionService.getNotificationService().push(message);
625		}
626		mXmppConnectionService.updateConversationUi();
627	}
628
629	private void parseHeadline(MessagePacket packet, Account account) {
630		if (packet.hasChild("event", "http://jabber.org/protocol/pubsub#event")) {
631			Element event = packet.findChild("event",
632					"http://jabber.org/protocol/pubsub#event");
633			parseEvent(event, packet.getFrom(), account);
634		}
635	}
636
637	private void parseNick(MessagePacket packet, Account account) {
638		Element nick = packet.findChild("nick",
639				"http://jabber.org/protocol/nick");
640		if (nick != null) {
641			if (packet.getFrom() != null) {
642				Contact contact = account.getRoster().getContact(
643						packet.getFrom());
644				contact.setPresenceName(nick.getContent());
645			}
646		}
647	}
648}