refactored presence parsing into dedicated class

This commit is contained in:
Daniel Gultsch 2014-06-06 18:26:40 +02:00
parent 5cd750cb5e
commit 476ab656ef
4 changed files with 178 additions and 138 deletions

View File

@ -0,0 +1,53 @@
package eu.siacs.conversations.parser;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.entities.Contact;
import eu.siacs.conversations.services.XmppConnectionService;
import eu.siacs.conversations.xml.Element;
public abstract class AbstractParser {
protected XmppConnectionService mXmppConnectionService;
protected AbstractParser(XmppConnectionService service) {
this.mXmppConnectionService = service;
}
protected long getTimestamp(Element packet) {
if (packet.hasChild("delay")) {
try {
String stamp = packet.findChild("delay").getAttribute(
"stamp");
stamp = stamp.replace("Z", "+0000");
Date date = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")
.parse(stamp);
return date.getTime();
} catch (ParseException e) {
return System.currentTimeMillis();
}
} else {
return System.currentTimeMillis();
}
}
protected void updateLastseen(Element packet, Account account) {
String[] fromParts = packet.getAttribute("from").split("/");
String from = fromParts[0];
String presence = null;
if (fromParts.length >= 2) {
presence = fromParts[1];
}
Contact contact = account.getRoster().getContact(from);
long timestamp = getTimestamp(packet);
if (timestamp >= contact.lastseen.time) {
contact.lastseen.time = timestamp;
if (presence!=null) {
contact.lastseen.presence = presence;
}
}
}
}

View File

@ -13,13 +13,10 @@ import eu.siacs.conversations.services.XmppConnectionService;
import eu.siacs.conversations.xml.Element; import eu.siacs.conversations.xml.Element;
import eu.siacs.conversations.xmpp.stanzas.MessagePacket; import eu.siacs.conversations.xmpp.stanzas.MessagePacket;
public class MessageParser { public class MessageParser extends AbstractParser {
protected static final String LOGTAG = "xmppService";
private XmppConnectionService mXmppConnectionService;
public MessageParser(XmppConnectionService service) { public MessageParser(XmppConnectionService service) {
this.mXmppConnectionService = service; super(service);
} }
public Message parseChat(MessagePacket packet, Account account) { public Message parseChat(MessagePacket packet, Account account) {
@ -83,7 +80,6 @@ public class MessageParser {
body = otrSession.transformReceiving(body); body = otrSession.transformReceiving(body);
SessionStatus after = otrSession.getSessionStatus(); SessionStatus after = otrSession.getSessionStatus();
if ((before != after) && (after == SessionStatus.ENCRYPTED)) { if ((before != after) && (after == SessionStatus.ENCRYPTED)) {
Log.d(LOGTAG, "otr session etablished");
List<Message> messages = conversation.getMessages(); List<Message> messages = conversation.getMessages();
for (int i = 0; i < messages.size(); ++i) { for (int i = 0; i < messages.size(); ++i) {
Message msg = messages.get(i); Message msg = messages.get(i);
@ -101,7 +97,6 @@ public class MessageParser {
mXmppConnectionService.updateUi(conversation, false); mXmppConnectionService.updateUi(conversation, false);
} else if ((before != after) && (after == SessionStatus.FINISHED)) { } else if ((before != after) && (after == SessionStatus.FINISHED)) {
conversation.resetOtrSession(); conversation.resetOtrSession();
Log.d(LOGTAG, "otr session stoped");
} }
// isEmpty is a work around for some weird clients which send emtpty // isEmpty is a work around for some weird clients which send emtpty
// strings over otr // strings over otr
@ -109,8 +104,10 @@ public class MessageParser {
return null; return null;
} }
conversation.setLatestMarkableMessageId(getMarkableMessageId(packet)); conversation.setLatestMarkableMessageId(getMarkableMessageId(packet));
return new Message(conversation, packet.getFrom(), body, Message finishedMessage = new Message(conversation, packet.getFrom(), body,
Message.ENCRYPTION_OTR, Message.STATUS_RECIEVED); Message.ENCRYPTION_OTR, Message.STATUS_RECIEVED);
finishedMessage.setTime(getTimestamp(packet));
return finishedMessage;
} catch (Exception e) { } catch (Exception e) {
conversation.resetOtrSession(); conversation.resetOtrSession();
return null; return null;
@ -144,13 +141,16 @@ public class MessageParser {
} }
String pgpBody = getPgpBody(packet); String pgpBody = getPgpBody(packet);
conversation.setLatestMarkableMessageId(getMarkableMessageId(packet)); conversation.setLatestMarkableMessageId(getMarkableMessageId(packet));
Message finishedMessage;
if (pgpBody == null) { if (pgpBody == null) {
return new Message(conversation, counterPart, packet.getBody(), finishedMessage = new Message(conversation, counterPart, packet.getBody(),
Message.ENCRYPTION_NONE, status); Message.ENCRYPTION_NONE, status);
} else { } else {
return new Message(conversation, counterPart, pgpBody, finishedMessage= new Message(conversation, counterPart, pgpBody,
Message.ENCRYPTION_PGP, status); Message.ENCRYPTION_PGP, status);
} }
finishedMessage.setTime(getTimestamp(packet));
return finishedMessage;
} }
public Message parseCarbonMessage(MessagePacket packet, Account account) { public Message parseCarbonMessage(MessagePacket packet, Account account) {
@ -183,14 +183,15 @@ public class MessageParser {
.findOrCreateConversation(account, parts[0], false); .findOrCreateConversation(account, parts[0], false);
conversation.setLatestMarkableMessageId(getMarkableMessageId(packet)); conversation.setLatestMarkableMessageId(getMarkableMessageId(packet));
String pgpBody = getPgpBody(message); String pgpBody = getPgpBody(message);
Message finishedMessage;
if (pgpBody != null) { if (pgpBody != null) {
return new Message(conversation, fullJid, pgpBody, finishedMessage = new Message(conversation, fullJid, pgpBody,Message.ENCRYPTION_PGP, status);
Message.ENCRYPTION_PGP, status);
} else { } else {
String body = message.findChild("body").getContent(); String body = message.findChild("body").getContent();
return new Message(conversation, fullJid, body, finishedMessage= new Message(conversation, fullJid, body,Message.ENCRYPTION_NONE, status);
Message.ENCRYPTION_NONE, status);
} }
finishedMessage.setTime(getTimestamp(message));
return finishedMessage;
} }
public void parseError(MessagePacket packet, Account account) { public void parseError(MessagePacket packet, Account account) {
@ -215,23 +216,4 @@ public class MessageParser {
return null; return null;
} }
} }
private void updateLastseen(Element message, Account account) {
String[] fromParts = message.getAttribute("from").split("/");
String from = fromParts[0];
String presence = null;
if (fromParts.length >= 2) {
presence = fromParts[1];
}
Contact contact = account.getRoster().getContact(from);
if (presence!=null) {
contact.lastseen.presence = presence;
contact.lastseen.time = System.currentTimeMillis();
} else if ((contact.getPresences().size() == 1)&&(contact.getPresences().containsKey(contact.lastseen.presence))) {
contact.lastseen.time = System.currentTimeMillis();
} else {
contact.lastseen.presence = null;
contact.lastseen.time = System.currentTimeMillis();
}
}
} }

View File

@ -0,0 +1,103 @@
package eu.siacs.conversations.parser;
import android.util.Log;
import eu.siacs.conversations.crypto.PgpEngine;
import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.entities.Contact;
import eu.siacs.conversations.entities.Conversation;
import eu.siacs.conversations.entities.Presences;
import eu.siacs.conversations.services.XmppConnectionService;
import eu.siacs.conversations.xml.Element;
import eu.siacs.conversations.xmpp.stanzas.PresencePacket;
public class PresenceParser extends AbstractParser {
public PresenceParser(XmppConnectionService service) {
super(service);
}
public void parseConferencePresence(PresencePacket packet, Account account) {
PgpEngine mPgpEngine = mXmppConnectionService.getPgpEngine();
if (packet.hasChild("x", "http://jabber.org/protocol/muc#user")) {
Conversation muc = mXmppConnectionService.findMuc(packet
.getAttribute("from").split("/")[0], account);
if (muc != null) {
muc.getMucOptions().processPacket(packet, mPgpEngine);
}
} else if (packet.hasChild("x", "http://jabber.org/protocol/muc")) {
Conversation muc = mXmppConnectionService.findMuc(packet
.getAttribute("from").split("/")[0], account);
if (muc != null) {
int error = muc.getMucOptions().getError();
muc.getMucOptions().processPacket(packet, mPgpEngine);
if (muc.getMucOptions().getError() != error) {
mXmppConnectionService.updateUi(muc, false);
}
}
}
}
public void parseContactPresence(PresencePacket packet, Account account) {
String[] fromParts = packet.getAttribute("from").split("/");
String type = packet.getAttribute("type");
if (fromParts[0].equals(account.getJid())) {
if (fromParts.length == 2) {
if (type == null) {
account.updatePresence(fromParts[1],
Presences.parseShow(packet.findChild("show")));
} else if (type.equals("unavailable")) {
account.removePresence(fromParts[1]);
}
}
} else {
Contact contact = account.getRoster().getContact(packet.getFrom());
if (type == null) {
if (fromParts.length == 2) {
contact.updatePresence(fromParts[1],
Presences.parseShow(packet.findChild("show")));
PgpEngine pgp = mXmppConnectionService.getPgpEngine();
if (pgp != null) {
Element x = packet.findChild("x", "jabber:x:signed");
if (x != null) {
Element status = packet.findChild("status");
String msg;
if (status != null) {
msg = status.getContent();
} else {
msg = "";
}
contact.setPgpKeyId(pgp.fetchKeyId(account, msg,
x.getContent()));
}
}
mXmppConnectionService.onContactStatusChanged
.onContactStatusChanged(contact);
updateLastseen(packet, account);
}
} else if (type.equals("unavailable")) {
if (fromParts.length != 2) {
contact.clearPresences();
} else {
contact.removePresence(fromParts[1]);
}
mXmppConnectionService.onContactStatusChanged
.onContactStatusChanged(contact);
} else if (type.equals("subscribe")) {
if (contact.getOption(Contact.Options.PREEMPTIVE_GRANT)) {
mXmppConnectionService.sendPresenceUpdatesTo(contact);
contact.setOption(Contact.Options.FROM);
contact.resetOption(Contact.Options.PREEMPTIVE_GRANT);
if ((contact.getOption(Contact.Options.ASKING))
&& (!contact.getOption(Contact.Options.TO))) {
mXmppConnectionService
.requestPresenceUpdatesFrom(contact);
}
} else {
contact.setOption(Contact.Options.PENDING_SUBSCRIPTION_REQUEST);
}
}
}
}
}

View File

@ -1,10 +1,7 @@
package eu.siacs.conversations.services; package eu.siacs.conversations.services;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.Date;
import java.util.Hashtable; import java.util.Hashtable;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
@ -23,8 +20,8 @@ import eu.siacs.conversations.entities.Conversation;
import eu.siacs.conversations.entities.Message; import eu.siacs.conversations.entities.Message;
import eu.siacs.conversations.entities.MucOptions; import eu.siacs.conversations.entities.MucOptions;
import eu.siacs.conversations.entities.MucOptions.OnRenameListener; import eu.siacs.conversations.entities.MucOptions.OnRenameListener;
import eu.siacs.conversations.entities.Presences;
import eu.siacs.conversations.parser.MessageParser; import eu.siacs.conversations.parser.MessageParser;
import eu.siacs.conversations.parser.PresenceParser;
import eu.siacs.conversations.persistance.DatabaseBackend; import eu.siacs.conversations.persistance.DatabaseBackend;
import eu.siacs.conversations.persistance.FileBackend; import eu.siacs.conversations.persistance.FileBackend;
import eu.siacs.conversations.ui.OnAccountListChangedListener; import eu.siacs.conversations.ui.OnAccountListChangedListener;
@ -86,6 +83,7 @@ public class XmppConnectionService extends Service {
private static String ACTION_MERGE_PHONE_CONTACTS = "merge_phone_contacts"; private static String ACTION_MERGE_PHONE_CONTACTS = "merge_phone_contacts";
private MessageParser mMessageParser = new MessageParser(this); private MessageParser mMessageParser = new MessageParser(this);
private PresenceParser mPresenceParser = new PresenceParser(this);
private List<Account> accounts; private List<Account> accounts;
private List<Conversation> conversations = null; private List<Conversation> conversations = null;
@ -96,7 +94,7 @@ public class XmppConnectionService extends Service {
private int convChangedListenerCount = 0; private int convChangedListenerCount = 0;
private OnAccountListChangedListener accountChangedListener = null; private OnAccountListChangedListener accountChangedListener = null;
private OnTLSExceptionReceived tlsException = null; private OnTLSExceptionReceived tlsException = null;
private OnContactStatusChanged onContactStatusChanged = new OnContactStatusChanged() { public OnContactStatusChanged onContactStatusChanged = new OnContactStatusChanged() {
@Override @Override
public void onContactStatusChanged(Contact contact) { public void onContactStatusChanged(Contact contact) {
@ -208,18 +206,6 @@ public class XmppConnectionService extends Service {
if ((message == null) || (message.getBody() == null)) { if ((message == null) || (message.getBody() == null)) {
return; return;
} }
if (packet.hasChild("delay")) {
try {
String stamp = packet.findChild("delay").getAttribute(
"stamp");
stamp = stamp.replace("Z", "+0000");
Date date = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")
.parse(stamp);
message.setTime(date.getTime());
} catch (ParseException e) {
Log.d(LOGTAG, "error trying to parse date" + e.getMessage());
}
}
if ((confirmMessages()) && ((packet.getId() != null))) { if ((confirmMessages()) && ((packet.getId() != null))) {
MessagePacket receivedPacket = new MessagePacket(); MessagePacket receivedPacket = new MessagePacket();
receivedPacket.setType(MessagePacket.TYPE_NORMAL); receivedPacket.setType(MessagePacket.TYPE_NORMAL);
@ -298,95 +284,11 @@ public class XmppConnectionService extends Service {
public void onPresencePacketReceived(final Account account, public void onPresencePacketReceived(final Account account,
PresencePacket packet) { PresencePacket packet) {
if (packet.hasChild("x", "http://jabber.org/protocol/muc#user")) { if (packet.hasChild("x", "http://jabber.org/protocol/muc#user")) {
Conversation muc = findMuc( mPresenceParser.parseConferencePresence(packet, account);
packet.getAttribute("from").split("/")[0], account);
if (muc != null) {
muc.getMucOptions().processPacket(packet, getPgpEngine());
} else {
Log.d(LOGTAG, account.getJid()
+ ": could not find muc for received muc package "
+ packet.toString());
}
} else if (packet.hasChild("x", "http://jabber.org/protocol/muc")) { } else if (packet.hasChild("x", "http://jabber.org/protocol/muc")) {
Conversation muc = findMuc( mPresenceParser.parseConferencePresence(packet, account);
packet.getAttribute("from").split("/")[0], account);
if (muc != null) {
Log.d(LOGTAG,
account.getJid() + ": reading muc status packet "
+ packet.toString());
int error = muc.getMucOptions().getError();
muc.getMucOptions().processPacket(packet, getPgpEngine());
if ((muc.getMucOptions().getError() != error)
&& (convChangedListener != null)) {
Log.d(LOGTAG, "muc error status changed");
convChangedListener.onConversationListChanged();
}
}
} else { } else {
String[] fromParts = packet.getAttribute("from").split("/"); mPresenceParser.parseContactPresence(packet,account);
String type = packet.getAttribute("type");
if (fromParts[0].equals(account.getJid())) {
if (fromParts.length == 2) {
if (type == null) {
account.updatePresence(fromParts[1], Presences
.parseShow(packet.findChild("show")));
} else if (type.equals("unavailable")) {
account.removePresence(fromParts[1]);
}
}
} else {
Contact contact = account.getRoster().getContact(
packet.getFrom());
if (type == null) {
if (fromParts.length == 2) {
contact.updatePresence(fromParts[1], Presences
.parseShow(packet.findChild("show")));
PgpEngine pgp = getPgpEngine();
if (pgp != null) {
Element x = packet.findChild("x",
"jabber:x:signed");
if (x != null) {
Element status = packet.findChild("status");
String msg;
if (status != null) {
msg = status.getContent();
} else {
msg = "";
}
contact.setPgpKeyId(pgp.fetchKeyId(account,
msg, x.getContent()));
}
}
onContactStatusChanged
.onContactStatusChanged(contact);
}
} else if (type.equals("unavailable")) {
if (fromParts.length != 2) {
contact.clearPresences();
} else {
contact.removePresence(fromParts[1]);
}
onContactStatusChanged.onContactStatusChanged(contact);
} else if (type.equals("subscribe")) {
Log.d(LOGTAG, "received subscribe packet from "
+ packet.getFrom());
if (contact.getOption(Contact.Options.PREEMPTIVE_GRANT)) {
Log.d(LOGTAG, "preemptive grant; granting");
sendPresenceUpdatesTo(contact);
contact.setOption(Contact.Options.FROM);
contact.resetOption(Contact.Options.PREEMPTIVE_GRANT);
if ((contact.getOption(Contact.Options.ASKING))
&& (!contact.getOption(Contact.Options.TO))) {
requestPresenceUpdatesFrom(contact);
}
} else {
contact.setOption(Contact.Options.PENDING_SUBSCRIPTION_REQUEST);
}
} else {
// Log.d(LOGTAG, packet.toString());
}
}
} }
} }
}; };
@ -507,7 +409,7 @@ public class XmppConnectionService extends Service {
return message; return message;
} }
protected Conversation findMuc(String name, Account account) { public Conversation findMuc(String name, Account account) {
for (Conversation conversation : this.conversations) { for (Conversation conversation : this.conversations) {
if (conversation.getContactJid().split("/")[0].equals(name) if (conversation.getContactJid().split("/")[0].equals(name)
&& (conversation.getAccount() == account)) { && (conversation.getAccount() == account)) {