2014-05-14 06:56:34 -04:00
package eu.siacs.conversations.parser ;
2014-02-18 19:35:23 -05:00
2015-05-14 23:14:15 -04:00
import android.util.Log ;
import android.util.Pair ;
2015-10-15 18:21:47 -04:00
import eu.siacs.conversations.crypto.PgpDecryptionService ;
2014-02-18 19:35:23 -05:00
import net.java.otr4j.session.Session ;
import net.java.otr4j.session.SessionStatus ;
2014-11-04 12:27:20 -05:00
2015-06-29 08:22:26 -04:00
import java.util.Set ;
2015-06-25 10:58:24 -04:00
2015-05-14 23:14:15 -04:00
import eu.siacs.conversations.Config ;
2015-06-25 10:58:24 -04:00
import eu.siacs.conversations.crypto.axolotl.AxolotlService ;
import eu.siacs.conversations.crypto.axolotl.XmppAxolotlMessage ;
2014-02-28 12:46:01 -05:00
import eu.siacs.conversations.entities.Account ;
2014-08-05 16:58:46 -04:00
import eu.siacs.conversations.entities.Contact ;
2014-02-28 12:46:01 -05:00
import eu.siacs.conversations.entities.Conversation ;
import eu.siacs.conversations.entities.Message ;
2015-01-07 12:34:24 -05:00
import eu.siacs.conversations.entities.MucOptions ;
2015-01-11 16:18:18 -05:00
import eu.siacs.conversations.http.HttpConnectionManager ;
2014-12-13 06:25:52 -05:00
import eu.siacs.conversations.services.MessageArchiveService ;
2014-02-28 12:46:01 -05:00
import eu.siacs.conversations.services.XmppConnectionService ;
2014-06-20 11:30:19 -04:00
import eu.siacs.conversations.utils.CryptoHelper ;
2014-02-28 12:46:01 -05:00
import eu.siacs.conversations.xml.Element ;
2014-07-11 20:36:37 -04:00
import eu.siacs.conversations.xmpp.OnMessagePacketReceived ;
2015-02-21 05:06:52 -05:00
import eu.siacs.conversations.xmpp.chatstate.ChatState ;
2014-11-06 14:10:03 -05:00
import eu.siacs.conversations.xmpp.jid.Jid ;
2014-08-05 16:58:46 -04:00
import eu.siacs.conversations.xmpp.pep.Avatar ;
2014-03-10 14:22:13 -04:00
import eu.siacs.conversations.xmpp.stanzas.MessagePacket ;
2014-02-18 19:35:23 -05:00
2014-07-11 20:36:37 -04:00
public class MessageParser extends AbstractParser implements
OnMessagePacketReceived {
2014-05-14 06:56:34 -04:00
public MessageParser ( XmppConnectionService service ) {
2014-06-06 12:26:40 -04:00
super ( service ) ;
2014-05-14 06:56:34 -04:00
}
2014-06-04 06:31:19 -04:00
2015-05-14 23:14:15 -04:00
private boolean extractChatState ( Conversation conversation , final MessagePacket packet ) {
ChatState state = ChatState . parse ( packet ) ;
2015-02-21 05:06:52 -05:00
if ( state ! = null & & conversation ! = null ) {
final Account account = conversation . getAccount ( ) ;
2015-05-14 23:14:15 -04:00
Jid from = packet . getFrom ( ) ;
if ( from . toBareJid ( ) . equals ( account . getJid ( ) . toBareJid ( ) ) ) {
2015-02-21 05:06:52 -05:00
conversation . setOutgoingChatState ( state ) ;
2015-10-06 05:44:27 -04:00
if ( state = = ChatState . ACTIVE | | state = = ChatState . COMPOSING ) {
mXmppConnectionService . markRead ( conversation ) ;
account . activateGracePeriod ( ) ;
}
2015-02-21 05:06:52 -05:00
return false ;
} else {
return conversation . setIncomingChatState ( state ) ;
}
}
return false ;
}
2015-05-14 23:14:15 -04:00
private Message parseOtrChat ( String body , Jid from , String id , Conversation conversation ) {
2014-08-11 07:46:32 -04:00
String presence ;
2014-11-06 14:10:03 -05:00
if ( from . isBareJid ( ) ) {
2015-03-16 18:23:51 -04:00
presence = " " ;
2014-08-11 07:46:32 -04:00
} else {
2014-11-06 14:10:03 -05:00
presence = from . getResourcepart ( ) ;
2014-08-11 07:46:32 -04:00
}
2015-01-24 10:19:58 -05:00
if ( body . matches ( " ^ \\ ?OTRv \\ d{1,2} \\ ?.* " ) ) {
2014-10-05 05:14:50 -04:00
conversation . endOtrIfNeeded ( ) ;
2014-09-06 12:21:31 -04:00
}
2014-02-18 19:35:23 -05:00
if ( ! conversation . hasValidOtrSession ( ) ) {
2015-05-14 23:14:15 -04:00
conversation . startOtrSession ( presence , false ) ;
2014-03-07 18:48:52 -05:00
} else {
2015-05-14 23:14:15 -04:00
String foreignPresence = conversation . getOtrSession ( ) . getSessionID ( ) . getUserID ( ) ;
2014-08-11 07:46:32 -04:00
if ( ! foreignPresence . equals ( presence ) ) {
2014-06-25 10:55:47 -04:00
conversation . endOtrIfNeeded ( ) ;
2015-05-14 23:14:15 -04:00
conversation . startOtrSession ( presence , false ) ;
2014-03-07 18:48:52 -05:00
}
2014-02-18 19:35:23 -05:00
}
try {
2015-05-14 23:14:15 -04:00
conversation . setLastReceivedOtrMessageId ( id ) ;
2014-02-18 19:35:23 -05:00
Session otrSession = conversation . getOtrSession ( ) ;
body = otrSession . transformReceiving ( body ) ;
2015-07-21 05:46:51 -04:00
SessionStatus status = otrSession . getSessionStatus ( ) ;
if ( body = = null & & status = = SessionStatus . ENCRYPTED ) {
2014-06-11 15:53:25 -04:00
mXmppConnectionService . onOtrSessionEstablished ( conversation ) ;
2015-07-21 05:46:51 -04:00
return null ;
} else if ( body = = null & & status = = SessionStatus . FINISHED ) {
2014-02-18 19:35:23 -05:00
conversation . resetOtrSession ( ) ;
2014-07-20 06:36:57 -04:00
mXmppConnectionService . updateConversationUi ( ) ;
2015-07-21 05:46:51 -04:00
return null ;
} else if ( body = = null | | ( body . isEmpty ( ) ) ) {
2014-03-23 09:15:14 -04:00
return null ;
}
2014-06-20 11:30:19 -04:00
if ( body . startsWith ( CryptoHelper . FILETRANSFER ) ) {
String key = body . substring ( CryptoHelper . FILETRANSFER . length ( ) ) ;
conversation . setSymmetricKey ( CryptoHelper . hexToBytes ( key ) ) ;
return null ;
}
2015-05-14 23:14:15 -04:00
Message finishedMessage = new Message ( conversation , body , Message . ENCRYPTION_OTR , Message . STATUS_RECEIVED ) ;
2015-03-21 11:07:17 -04:00
conversation . setLastReceivedOtrMessageId ( null ) ;
2014-06-06 12:26:40 -04:00
return finishedMessage ;
2014-02-18 19:35:23 -05:00
} catch ( Exception e ) {
2014-09-06 12:21:31 -04:00
conversation . resetOtrSession ( ) ;
2014-02-18 19:35:23 -05:00
return null ;
}
}
2014-06-04 06:31:19 -04:00
2015-07-03 07:27:35 -04:00
private Message parseAxolotlChat ( Element axolotlMessage , Jid from , String id , Conversation conversation , int status ) {
2015-06-26 09:41:02 -04:00
Message finishedMessage = null ;
AxolotlService service = conversation . getAccount ( ) . getAxolotlService ( ) ;
2015-07-31 15:12:34 -04:00
XmppAxolotlMessage xmppAxolotlMessage = XmppAxolotlMessage . fromElement ( axolotlMessage , from . toBareJid ( ) ) ;
2015-07-31 17:28:09 -04:00
XmppAxolotlMessage . XmppAxolotlPlaintextMessage plaintextMessage = service . processReceivingPayloadMessage ( xmppAxolotlMessage ) ;
2015-06-26 09:41:02 -04:00
if ( plaintextMessage ! = null ) {
2015-07-03 07:27:35 -04:00
finishedMessage = new Message ( conversation , plaintextMessage . getPlaintext ( ) , Message . ENCRYPTION_AXOLOTL , status ) ;
2015-07-09 08:23:17 -04:00
finishedMessage . setAxolotlFingerprint ( plaintextMessage . getFingerprint ( ) ) ;
Log . d ( Config . LOGTAG , AxolotlService . getLogprefix ( finishedMessage . getConversation ( ) . getAccount ( ) ) + " Received Message with session fingerprint: " + plaintextMessage . getFingerprint ( ) ) ;
2015-06-26 09:41:02 -04:00
}
2015-06-25 10:58:24 -04:00
2015-06-26 09:41:02 -04:00
return finishedMessage ;
}
2015-06-25 10:58:24 -04:00
2015-10-15 18:21:47 -04:00
private Message parsePGPChat ( final Conversation conversation , String pgpEncrypted , int status ) {
final Message message = new Message ( conversation , pgpEncrypted , Message . ENCRYPTION_PGP , status ) ;
PgpDecryptionService pgpDecryptionService = conversation . getAccount ( ) . getPgpDecryptionService ( ) ;
pgpDecryptionService . add ( message ) ;
return message ;
}
2015-04-21 12:36:11 -04:00
private class Invite {
Jid jid ;
String password ;
Invite ( Jid jid , String password ) {
this . jid = jid ;
this . password = password ;
2015-01-07 10:45:44 -05:00
}
2015-05-19 02:23:12 -04:00
public boolean execute ( Account account ) {
if ( jid ! = null ) {
Conversation conversation = mXmppConnectionService . findOrCreateConversation ( account , jid , true ) ;
if ( ! conversation . getMucOptions ( ) . online ( ) ) {
conversation . getMucOptions ( ) . setPassword ( password ) ;
mXmppConnectionService . databaseBackend . updateConversation ( conversation ) ;
mXmppConnectionService . joinMuc ( conversation ) ;
mXmppConnectionService . updateConversationUi ( ) ;
}
return true ;
}
return false ;
}
2015-04-21 12:36:11 -04:00
}
private Invite extractInvite ( Element message ) {
2015-05-14 23:14:15 -04:00
Element x = message . findChild ( " x " , " http://jabber.org/protocol/muc#user " ) ;
2015-04-21 12:36:11 -04:00
if ( x ! = null ) {
Element invite = x . findChild ( " invite " ) ;
if ( invite ! = null ) {
Element pw = x . findChild ( " password " ) ;
return new Invite ( message . getAttributeAsJid ( " from " ) , pw ! = null ? pw . getContent ( ) : null ) ;
}
2015-01-07 10:45:44 -05:00
} else {
2015-04-21 12:36:11 -04:00
x = message . findChild ( " x " , " jabber:x:conference " ) ;
if ( x ! = null ) {
return new Invite ( x . getAttributeAsJid ( " jid " ) , x . getAttribute ( " password " ) ) ;
}
2014-06-06 12:49:35 -04:00
}
2015-04-21 12:36:11 -04:00
return null ;
2014-06-06 12:49:35 -04:00
}
2014-02-27 18:22:56 -05:00
2014-11-06 14:10:03 -05:00
private void parseEvent ( final Element event , final Jid from , final Account account ) {
2014-08-04 19:36:17 -04:00
Element items = event . findChild ( " items " ) ;
2015-05-19 02:23:12 -04:00
String node = items = = null ? null : items . getAttribute ( " node " ) ;
if ( " urn:xmpp:avatar:metadata " . equals ( node ) ) {
2014-11-20 12:42:47 -05:00
Avatar avatar = Avatar . parseMetadata ( items ) ;
if ( avatar ! = null ) {
avatar . owner = from ;
2015-05-19 02:23:12 -04:00
if ( mXmppConnectionService . getFileBackend ( ) . isAvatarCached ( avatar ) ) {
2014-11-20 12:42:47 -05:00
if ( account . getJid ( ) . toBareJid ( ) . equals ( from ) ) {
if ( account . setAvatar ( avatar . getFilename ( ) ) ) {
2015-05-19 02:23:12 -04:00
mXmppConnectionService . databaseBackend . updateAccount ( account ) ;
2014-08-15 07:11:33 -04:00
}
2015-05-19 02:23:12 -04:00
mXmppConnectionService . getAvatarService ( ) . clear ( account ) ;
2014-11-20 12:42:47 -05:00
mXmppConnectionService . updateConversationUi ( ) ;
mXmppConnectionService . updateAccountUi ( ) ;
2014-08-05 16:58:46 -04:00
} else {
2015-05-19 02:23:12 -04:00
Contact contact = account . getRoster ( ) . getContact ( from ) ;
2015-05-05 00:17:34 -04:00
contact . setAvatar ( avatar ) ;
2015-05-19 02:23:12 -04:00
mXmppConnectionService . getAvatarService ( ) . clear ( contact ) ;
2014-11-20 12:42:47 -05:00
mXmppConnectionService . updateConversationUi ( ) ;
mXmppConnectionService . updateRosterUi ( ) ;
2014-08-05 16:58:46 -04:00
}
2014-11-20 12:42:47 -05:00
} else {
mXmppConnectionService . fetchAvatar ( account , avatar ) ;
2014-08-05 16:58:46 -04:00
}
2014-11-20 12:42:47 -05:00
}
2015-05-19 02:23:12 -04:00
} else if ( " http://jabber.org/protocol/nick " . equals ( node ) ) {
Element i = items . findChild ( " item " ) ;
Element nick = i = = null ? null : i . findChild ( " nick " , " http://jabber.org/protocol/nick " ) ;
2015-10-29 08:41:08 -04:00
if ( nick ! = null & & nick . getContent ( ) ! = null ) {
2015-05-19 02:23:12 -04:00
Contact contact = account . getRoster ( ) . getContact ( from ) ;
contact . setPresenceName ( nick . getContent ( ) ) ;
mXmppConnectionService . getAvatarService ( ) . clear ( account ) ;
mXmppConnectionService . updateConversationUi ( ) ;
mXmppConnectionService . updateAccountUi ( ) ;
2014-08-05 16:58:46 -04:00
}
2015-06-25 10:58:24 -04:00
} else if ( AxolotlService . PEP_DEVICE_LIST . equals ( node ) ) {
2015-07-08 11:44:24 -04:00
Log . d ( Config . LOGTAG , AxolotlService . getLogprefix ( account ) + " Received PEP device list update from " + from + " , processing... " ) ;
2015-06-26 09:41:02 -04:00
Element item = items . findChild ( " item " ) ;
2015-06-29 08:22:26 -04:00
Set < Integer > deviceIds = mXmppConnectionService . getIqParser ( ) . deviceIds ( item ) ;
2015-06-26 09:41:02 -04:00
AxolotlService axolotlService = account . getAxolotlService ( ) ;
2015-06-29 08:22:26 -04:00
axolotlService . registerDevices ( from , deviceIds ) ;
2015-07-07 13:32:52 -04:00
mXmppConnectionService . updateAccountUi ( ) ;
2014-08-04 19:36:17 -04:00
}
}
2015-05-19 02:23:12 -04:00
private boolean handleErrorMessage ( Account account , MessagePacket packet ) {
if ( packet . getType ( ) = = MessagePacket . TYPE_ERROR ) {
Jid from = packet . getFrom ( ) ;
if ( from ! = null ) {
2015-07-28 08:44:11 -04:00
Element error = packet . findChild ( " error " ) ;
String text = error = = null ? null : error . findChildContent ( " text " ) ;
if ( text ! = null ) {
Log . d ( Config . LOGTAG , account . getJid ( ) . toBareJid ( ) + " : sending message to " + from + " failed - " + text ) ;
} else if ( error ! = null ) {
Log . d ( Config . LOGTAG , account . getJid ( ) . toBareJid ( ) + " : sending message to " + from + " failed - " + error ) ;
}
2015-07-21 05:52:49 -04:00
Message message = mXmppConnectionService . markMessage ( account ,
from . toBareJid ( ) ,
packet . getId ( ) ,
Message . STATUS_SEND_FAILED ) ;
2015-07-21 13:44:25 -04:00
if ( message ! = null & & message . getEncryption ( ) = = Message . ENCRYPTION_OTR ) {
2015-07-21 05:52:49 -04:00
message . getConversation ( ) . endOtrIfNeeded ( ) ;
}
2015-05-19 02:23:12 -04:00
}
return true ;
}
return false ;
}
2015-05-14 23:14:15 -04:00
@Override
public void onMessagePacketReceived ( Account account , MessagePacket original ) {
2015-05-19 02:23:12 -04:00
if ( handleErrorMessage ( account , original ) ) {
return ;
}
2015-05-14 23:14:15 -04:00
final MessagePacket packet ;
Long timestamp = null ;
final boolean isForwarded ;
2015-07-29 10:41:58 -04:00
boolean isCarbon = false ;
2015-05-15 00:31:27 -04:00
String serverMsgId = null ;
2015-05-15 06:29:45 -04:00
final Element fin = original . findChild ( " fin " , " urn:xmpp:mam:0 " ) ;
if ( fin ! = null ) {
mXmppConnectionService . getMessageArchiveService ( ) . processFin ( fin , original . getFrom ( ) ) ;
return ;
}
final Element result = original . findChild ( " result " , " urn:xmpp:mam:0 " ) ;
final MessageArchiveService . Query query = result = = null ? null : mXmppConnectionService . getMessageArchiveService ( ) . findQuery ( result . getAttribute ( " queryid " ) ) ;
if ( query ! = null & & query . validFrom ( original . getFrom ( ) ) ) {
Pair < MessagePacket , Long > f = original . getForwardedMessagePacket ( " result " , " urn:xmpp:mam:0 " ) ;
if ( f = = null ) {
return ;
}
timestamp = f . second ;
packet = f . first ;
isForwarded = true ;
serverMsgId = result . getAttribute ( " id " ) ;
query . incrementTotalCount ( ) ;
} else if ( query ! = null ) {
Log . d ( Config . LOGTAG , account . getJid ( ) . toBareJid ( ) + " : received mam result from invalid sender " ) ;
return ;
} else if ( original . fromServer ( account ) ) {
2015-05-14 23:14:15 -04:00
Pair < MessagePacket , Long > f ;
f = original . getForwardedMessagePacket ( " received " , " urn:xmpp:carbons:2 " ) ;
f = f = = null ? original . getForwardedMessagePacket ( " sent " , " urn:xmpp:carbons:2 " ) : f ;
packet = f ! = null ? f . first : original ;
2015-05-19 02:23:12 -04:00
if ( handleErrorMessage ( account , packet ) ) {
return ;
}
2015-05-14 23:14:15 -04:00
timestamp = f ! = null ? f . second : null ;
2015-07-29 10:41:58 -04:00
isCarbon = f ! = null ;
isForwarded = isCarbon ;
2014-05-22 10:17:51 -04:00
} else {
2015-05-14 23:14:15 -04:00
packet = original ;
isForwarded = false ;
}
2015-05-19 02:23:12 -04:00
2015-05-14 23:14:15 -04:00
if ( timestamp = = null ) {
timestamp = AbstractParser . getTimestamp ( packet , System . currentTimeMillis ( ) ) ;
}
final String body = packet . getBody ( ) ;
2015-07-22 08:15:00 -04:00
final Element mucUserElement = packet . findChild ( " x " , " http://jabber.org/protocol/muc#user " ) ;
2015-06-25 10:58:24 -04:00
final String pgpEncrypted = packet . findChildContent ( " x " , " jabber:x:encrypted " ) ;
2015-07-31 15:12:34 -04:00
final Element axolotlEncrypted = packet . findChild ( XmppAxolotlMessage . CONTAINERTAG , AxolotlService . PEP_PREFIX ) ;
2015-05-14 23:14:15 -04:00
int status ;
2015-05-15 06:29:45 -04:00
final Jid counterpart ;
2015-05-14 23:14:15 -04:00
final Jid to = packet . getTo ( ) ;
final Jid from = packet . getFrom ( ) ;
2015-05-15 00:31:27 -04:00
final String remoteMsgId = packet . getId ( ) ;
2015-07-02 12:02:32 -04:00
if ( from = = null | | to = = null ) {
Log . d ( Config . LOGTAG , " no to or from in: " + packet . toString ( ) ) ;
return ;
}
2015-05-14 23:14:15 -04:00
boolean isTypeGroupChat = packet . getType ( ) = = MessagePacket . TYPE_GROUPCHAT ;
2015-06-28 16:14:40 -04:00
boolean isProperlyAddressed = ! to . isBareJid ( ) | | account . countPresences ( ) = = 1 ;
boolean isMucStatusMessage = from . isBareJid ( ) & & mucUserElement ! = null & & mucUserElement . hasChild ( " status " ) ;
2015-05-14 23:14:15 -04:00
if ( packet . fromAccount ( account ) ) {
status = Message . STATUS_SEND ;
counterpart = to ;
} else {
status = Message . STATUS_RECEIVED ;
counterpart = from ;
2014-02-27 18:22:56 -05:00
}
2014-07-11 20:36:37 -04:00
2015-05-14 23:14:15 -04:00
Invite invite = extractInvite ( packet ) ;
2015-05-19 02:23:12 -04:00
if ( invite ! = null & & invite . execute ( account ) ) {
2015-05-14 23:14:15 -04:00
return ;
}
2015-10-06 05:44:27 -04:00
if ( extractChatState ( mXmppConnectionService . find ( account , counterpart . toBareJid ( ) ) , packet ) ) {
2015-05-14 23:14:15 -04:00
mXmppConnectionService . updateConversationUi ( ) ;
}
2015-06-25 10:58:24 -04:00
if ( ( body ! = null | | pgpEncrypted ! = null | | axolotlEncrypted ! = null ) & & ! isMucStatusMessage ) {
2015-05-14 23:14:15 -04:00
Conversation conversation = mXmppConnectionService . findOrCreateConversation ( account , counterpart . toBareJid ( ) , isTypeGroupChat ) ;
if ( isTypeGroupChat ) {
if ( counterpart . getResourcepart ( ) . equals ( conversation . getMucOptions ( ) . getActualNick ( ) ) ) {
2015-06-02 06:21:35 -04:00
status = Message . STATUS_SEND_RECEIVED ;
if ( mXmppConnectionService . markMessage ( conversation , remoteMsgId , status ) ) {
2015-05-14 23:14:15 -04:00
return ;
2015-10-14 05:15:18 -04:00
} else if ( remoteMsgId = = null | | Config . IGNORE_ID_REWRITE_IN_MUC ) {
2015-08-26 05:39:18 -04:00
Message message = conversation . findSentMessageWithBody ( packet . getBody ( ) ) ;
2015-05-14 23:14:15 -04:00
if ( message ! = null ) {
2015-06-02 06:21:35 -04:00
mXmppConnectionService . markMessage ( message , status ) ;
2015-05-14 23:14:15 -04:00
return ;
}
2014-07-11 20:36:37 -04:00
}
2015-05-14 23:14:15 -04:00
} else {
status = Message . STATUS_RECEIVED ;
2014-07-11 20:36:37 -04:00
}
2015-05-14 23:14:15 -04:00
}
Message message ;
if ( body ! = null & & body . startsWith ( " ?OTR " ) ) {
2015-06-28 16:14:40 -04:00
if ( ! isForwarded & & ! isTypeGroupChat & & isProperlyAddressed ) {
2015-05-15 00:31:27 -04:00
message = parseOtrChat ( body , from , remoteMsgId , conversation ) ;
2015-05-14 23:14:15 -04:00
if ( message = = null ) {
return ;
}
} else {
message = new Message ( conversation , body , Message . ENCRYPTION_NONE , status ) ;
2014-12-04 19:54:16 -05:00
}
2015-06-25 10:58:24 -04:00
} else if ( pgpEncrypted ! = null ) {
2015-10-15 18:21:47 -04:00
message = parsePGPChat ( conversation , pgpEncrypted , status ) ;
2015-06-26 09:41:02 -04:00
} else if ( axolotlEncrypted ! = null ) {
2015-07-03 07:27:35 -04:00
message = parseAxolotlChat ( axolotlEncrypted , from , remoteMsgId , conversation , status ) ;
2015-06-26 09:41:02 -04:00
if ( message = = null ) {
return ;
}
2014-07-23 08:30:27 -04:00
} else {
2015-05-14 23:14:15 -04:00
message = new Message ( conversation , body , Message . ENCRYPTION_NONE , status ) ;
2014-07-11 20:36:37 -04:00
}
2015-05-14 23:14:15 -04:00
message . setCounterpart ( counterpart ) ;
2015-05-15 00:31:27 -04:00
message . setRemoteMsgId ( remoteMsgId ) ;
message . setServerMsgId ( serverMsgId ) ;
2015-07-29 10:41:58 -04:00
message . setCarbon ( isCarbon ) ;
2015-05-14 23:14:15 -04:00
message . setTime ( timestamp ) ;
message . markable = packet . hasChild ( " markable " , " urn:xmpp:chat-markers:0 " ) ;
if ( conversation . getMode ( ) = = Conversation . MODE_MULTI ) {
2015-10-19 17:20:33 -04:00
Jid trueCounterpart = conversation . getMucOptions ( ) . getTrueCounterpart ( counterpart . getResourcepart ( ) ) ;
message . setTrueCounterpart ( trueCounterpart ) ;
if ( trueCounterpart ! = null ) {
updateLastseen ( packet , account , trueCounterpart , false ) ;
}
2015-05-14 23:14:15 -04:00
if ( ! isTypeGroupChat ) {
message . setType ( Message . TYPE_PRIVATE ) ;
2014-07-11 20:36:37 -04:00
}
}
2015-05-14 23:14:15 -04:00
updateLastseen ( packet , account , true ) ;
2015-05-26 06:00:55 -04:00
boolean checkForDuplicates = serverMsgId ! = null
| | ( isTypeGroupChat & & packet . hasChild ( " delay " , " urn:xmpp:delay " ) )
| | message . getType ( ) = = Message . TYPE_PRIVATE ;
2015-05-15 00:31:27 -04:00
if ( checkForDuplicates & & conversation . hasDuplicateMessage ( message ) ) {
Log . d ( Config . LOGTAG , " skipping duplicate message from " + message . getCounterpart ( ) . toString ( ) + " " + message . getBody ( ) ) ;
return ;
}
if ( query ! = null ) {
query . incrementMessageCount ( ) ;
}
2015-05-14 23:14:15 -04:00
conversation . add ( message ) ;
2015-05-15 05:51:20 -04:00
if ( serverMsgId = = null ) {
2015-06-03 20:47:24 -04:00
if ( status = = Message . STATUS_SEND | | status = = Message . STATUS_SEND_RECEIVED ) {
2015-05-15 05:51:20 -04:00
mXmppConnectionService . markRead ( conversation ) ;
account . activateGracePeriod ( ) ;
} else {
message . markUnread ( ) ;
}
2015-05-15 06:29:45 -04:00
mXmppConnectionService . updateConversationUi ( ) ;
2014-07-23 19:04:25 -04:00
}
2015-05-14 23:14:15 -04:00
2015-07-22 08:15:00 -04:00
if ( mXmppConnectionService . confirmMessages ( ) & & remoteMsgId ! = null & & ! isForwarded & & ! isTypeGroupChat ) {
2015-05-14 23:14:15 -04:00
if ( packet . hasChild ( " markable " , " urn:xmpp:chat-markers:0 " ) ) {
2015-07-22 08:15:00 -04:00
MessagePacket receipt = mXmppConnectionService . getMessageGenerator ( ) . received ( account ,
packet ,
" urn:xmpp:chat-markers:0 " ,
MessagePacket . TYPE_CHAT ) ;
2015-05-14 23:14:15 -04:00
mXmppConnectionService . sendMessagePacket ( account , receipt ) ;
}
if ( packet . hasChild ( " request " , " urn:xmpp:receipts " ) ) {
2015-07-22 08:15:00 -04:00
MessagePacket receipt = mXmppConnectionService . getMessageGenerator ( ) . received ( account ,
packet ,
" urn:xmpp:receipts " ,
packet . getType ( ) ) ;
2015-05-14 23:14:15 -04:00
mXmppConnectionService . sendMessagePacket ( account , receipt ) ;
}
2014-07-11 20:36:37 -04:00
}
2015-05-14 23:14:15 -04:00
if ( account . getXmppConnection ( ) ! = null & & account . getXmppConnection ( ) . getFeatures ( ) . advancedStreamFeaturesLoaded ( ) ) {
if ( conversation . setLastMessageTransmitted ( System . currentTimeMillis ( ) ) ) {
mXmppConnectionService . updateConversation ( conversation ) ;
}
2014-12-08 15:59:14 -05:00
}
2014-10-28 13:02:12 -04:00
2015-05-14 23:14:15 -04:00
if ( message . getStatus ( ) = = Message . STATUS_RECEIVED
& & conversation . getOtrSession ( ) ! = null
& & ! conversation . getOtrSession ( ) . getSessionID ( ) . getUserID ( )
. equals ( message . getCounterpart ( ) . getResourcepart ( ) ) ) {
conversation . endOtrIfNeeded ( ) ;
}
2014-10-28 13:02:12 -04:00
2015-05-15 06:29:45 -04:00
if ( message . getEncryption ( ) = = Message . ENCRYPTION_NONE | | mXmppConnectionService . saveEncryptedMessages ( ) ) {
2014-09-08 07:37:22 -04:00
mXmppConnectionService . databaseBackend . createMessage ( message ) ;
}
2015-05-14 23:14:15 -04:00
final HttpConnectionManager manager = this . mXmppConnectionService . getHttpConnectionManager ( ) ;
2015-07-01 10:01:18 -04:00
if ( message . trusted ( ) & & message . treatAsDownloadable ( ) ! = Message . Decision . NEVER & & manager . getAutoAcceptFileSize ( ) > 0 ) {
2015-07-10 09:14:13 -04:00
manager . createNewDownloadConnection ( message ) ;
2015-05-14 23:14:15 -04:00
} else if ( ! message . isRead ( ) ) {
mXmppConnectionService . getNotificationService ( ) . push ( message ) ;
}
2015-05-15 06:29:45 -04:00
} else { //no body
2015-06-28 14:11:28 -04:00
if ( isTypeGroupChat ) {
2015-05-14 23:14:15 -04:00
Conversation conversation = mXmppConnectionService . find ( account , from . toBareJid ( ) ) ;
2015-06-28 14:11:28 -04:00
if ( packet . hasChild ( " subject " ) ) {
if ( conversation ! = null & & conversation . getMode ( ) = = Conversation . MODE_MULTI ) {
conversation . setHasMessagesLeftOnServer ( conversation . countMessages ( ) > 0 ) ;
conversation . getMucOptions ( ) . setSubject ( packet . findChildContent ( " subject " ) ) ;
mXmppConnectionService . updateConversationUi ( ) ;
return ;
}
}
2015-06-28 16:14:40 -04:00
if ( conversation ! = null & & isMucStatusMessage ) {
for ( Element child : mucUserElement . getChildren ( ) ) {
2015-06-28 14:11:28 -04:00
if ( child . getName ( ) . equals ( " status " )
& & MucOptions . STATUS_CODE_ROOM_CONFIG_CHANGED . equals ( child . getAttribute ( " code " ) ) ) {
mXmppConnectionService . fetchConferenceConfiguration ( conversation ) ;
}
}
2015-05-14 23:14:15 -04:00
}
}
2014-07-11 20:36:37 -04:00
}
2015-05-14 23:14:15 -04:00
Element received = packet . findChild ( " received " , " urn:xmpp:chat-markers:0 " ) ;
if ( received = = null ) {
received = packet . findChild ( " received " , " urn:xmpp:receipts " ) ;
}
if ( received ! = null & & ! packet . fromAccount ( account ) ) {
mXmppConnectionService . markMessage ( account , from . toBareJid ( ) , received . getAttribute ( " id " ) , Message . STATUS_SEND_RECEIVED ) ;
}
Element displayed = packet . findChild ( " displayed " , " urn:xmpp:chat-markers:0 " ) ;
if ( displayed ! = null ) {
if ( packet . fromAccount ( account ) ) {
Conversation conversation = mXmppConnectionService . find ( account , counterpart . toBareJid ( ) ) ;
2015-05-16 06:43:38 -04:00
if ( conversation ! = null ) {
mXmppConnectionService . markRead ( conversation ) ;
}
2015-05-14 23:14:15 -04:00
} else {
updateLastseen ( packet , account , true ) ;
final Message displayedMessage = mXmppConnectionService . markMessage ( account , from . toBareJid ( ) , displayed . getAttribute ( " id " ) , Message . STATUS_SEND_DISPLAYED ) ;
Message message = displayedMessage = = null ? null : displayedMessage . prev ( ) ;
while ( message ! = null
& & message . getStatus ( ) = = Message . STATUS_SEND_RECEIVED
& & message . getTimeSent ( ) < displayedMessage . getTimeSent ( ) ) {
mXmppConnectionService . markMessage ( message , Message . STATUS_SEND_DISPLAYED ) ;
message = message . prev ( ) ;
}
}
2014-09-28 09:21:56 -04:00
}
2014-08-04 19:36:17 -04:00
2015-05-14 23:14:15 -04:00
Element event = packet . findChild ( " event " , " http://jabber.org/protocol/pubsub#event " ) ;
if ( event ! = null ) {
parseEvent ( event , from , account ) ;
2014-08-04 19:36:17 -04:00
}
2014-09-04 04:50:06 -04:00
2015-05-14 23:14:15 -04:00
String nick = packet . findChildContent ( " nick " , " http://jabber.org/protocol/nick " ) ;
2014-09-04 04:50:06 -04:00
if ( nick ! = null ) {
2015-05-14 23:14:15 -04:00
Contact contact = account . getRoster ( ) . getContact ( from ) ;
contact . setPresenceName ( nick ) ;
2014-09-04 04:50:06 -04:00
}
}
2015-08-15 08:26:37 -04:00
}