MessageParser.java

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