From d175843cbda3f62a03e2cb0a3898dce2097c4c6f Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Fri, 16 Feb 2024 16:59:21 +0100 Subject: [PATCH] ignore 'subscribe' presence for blocked contacts --- .../conversations/parser/PresenceParser.java | 738 ++++++++++-------- 1 file changed, 395 insertions(+), 343 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/parser/PresenceParser.java b/src/main/java/eu/siacs/conversations/parser/PresenceParser.java index 8ad582b17..584b8e704 100644 --- a/src/main/java/eu/siacs/conversations/parser/PresenceParser.java +++ b/src/main/java/eu/siacs/conversations/parser/PresenceParser.java @@ -2,11 +2,6 @@ package eu.siacs.conversations.parser; import android.util.Log; -import org.openintents.openpgp.util.OpenPgpUtils; - -import java.util.ArrayList; -import java.util.List; - import eu.siacs.conversations.Config; import eu.siacs.conversations.crypto.PgpEngine; import eu.siacs.conversations.crypto.axolotl.AxolotlService; @@ -28,123 +23,159 @@ import eu.siacs.conversations.xmpp.OnPresencePacketReceived; import eu.siacs.conversations.xmpp.pep.Avatar; import eu.siacs.conversations.xmpp.stanzas.PresencePacket; -public class PresenceParser extends AbstractParser implements - OnPresencePacketReceived { +import org.openintents.openpgp.util.OpenPgpUtils; - public PresenceParser(XmppConnectionService service) { - super(service); - } +import java.util.ArrayList; +import java.util.List; - public void parseConferencePresence(PresencePacket packet, Account account) { - final Conversation conversation = packet.getFrom() == null ? null : mXmppConnectionService.find(account, packet.getFrom().asBareJid()); - if (conversation != null) { - final MucOptions mucOptions = conversation.getMucOptions(); - boolean before = mucOptions.online(); - int count = mucOptions.getUserCount(); - final List tileUserBefore = mucOptions.getUsers(5); - processConferencePresence(packet, conversation); - final List tileUserAfter = mucOptions.getUsers(5); - if (!tileUserAfter.equals(tileUserBefore)) { - mXmppConnectionService.getAvatarService().clear(mucOptions); - } - if (before != mucOptions.online() || (mucOptions.online() && count != mucOptions.getUserCount())) { - mXmppConnectionService.updateConversationUi(); - } else if (mucOptions.online()) { - mXmppConnectionService.updateMucRosterUi(); - } - } - } +public class PresenceParser extends AbstractParser implements OnPresencePacketReceived { - private void processConferencePresence(PresencePacket packet, Conversation conversation) { - final Account account = conversation.getAccount(); - final MucOptions mucOptions = conversation.getMucOptions(); - final Jid jid = conversation.getAccount().getJid(); - final Jid from = packet.getFrom(); - if (!from.isBareJid()) { - final String type = packet.getAttribute("type"); - final Element x = packet.findChild("x", Namespace.MUC_USER); - Avatar avatar = Avatar.parsePresence(packet.findChild("x", "vcard-temp:x:update")); - final List codes = getStatusCodes(x); - if (type == null) { - if (x != null) { - Element item = x.findChild("item"); - if (item != null && !from.isBareJid()) { - mucOptions.setError(MucOptions.Error.NONE); - MucOptions.User user = parseItem(conversation, item, from); - if (codes.contains(MucOptions.STATUS_CODE_SELF_PRESENCE) || (codes.contains(MucOptions.STATUS_CODE_ROOM_CREATED) && jid.equals(InvalidJid.getNullForInvalid(item.getAttributeAsJid("jid"))))) { - if (mucOptions.setOnline()) { - mXmppConnectionService.getAvatarService().clear(mucOptions); - } - if (mucOptions.setSelf(user)) { - Log.d(Config.LOGTAG,"role or affiliation changed"); - mXmppConnectionService.databaseBackend.updateConversation(conversation); - } + public PresenceParser(XmppConnectionService service) { + super(service); + } - mXmppConnectionService.persistSelfNick(user); - invokeRenameListener(mucOptions, true); - } - boolean isNew = mucOptions.updateUser(user); - final AxolotlService axolotlService = conversation.getAccount().getAxolotlService(); - Contact contact = user.getContact(); - if (isNew - && user.getRealJid() != null - && mucOptions.isPrivateAndNonAnonymous() - && (contact == null || !contact.mutualPresenceSubscription()) - && axolotlService.hasEmptyDeviceList(user.getRealJid())) { - axolotlService.fetchDeviceIds(user.getRealJid()); - } - if (codes.contains(MucOptions.STATUS_CODE_ROOM_CREATED) && mucOptions.autoPushConfiguration()) { - Log.d(Config.LOGTAG,account.getJid().asBareJid() - +": room '" - +mucOptions.getConversation().getJid().asBareJid() - +"' created. pushing default configuration"); - mXmppConnectionService.pushConferenceConfiguration(mucOptions.getConversation(), - IqGenerator.defaultChannelConfiguration(), - null); - } - if (mXmppConnectionService.getPgpEngine() != null) { - Element signed = packet.findChild("x", "jabber:x:signed"); - if (signed != null) { - Element status = packet.findChild("status"); - String msg = status == null ? "" : status.getContent(); - long keyId = mXmppConnectionService.getPgpEngine().fetchKeyId(mucOptions.getAccount(), msg, signed.getContent()); - if (keyId != 0) { - user.setPgpKeyId(keyId); - } - } - } - if (avatar != null) { - avatar.owner = from; - if (mXmppConnectionService.getFileBackend().isAvatarCached(avatar)) { - if (user.setAvatar(avatar)) { - mXmppConnectionService.getAvatarService().clear(user); - } - if (user.getRealJid() != null) { - final Contact c = conversation.getAccount().getRoster().getContact(user.getRealJid()); - c.setAvatar(avatar); - mXmppConnectionService.syncRoster(conversation.getAccount()); - mXmppConnectionService.getAvatarService().clear(c); - mXmppConnectionService.updateRosterUi(); - } - } else if (mXmppConnectionService.isDataSaverDisabled()) { - mXmppConnectionService.fetchAvatar(mucOptions.getAccount(), avatar); - } - } - } - } - } else if (type.equals("unavailable")) { - final boolean fullJidMatches = from.equals(mucOptions.getSelf().getFullJid()); - if (x.hasChild("destroy") && fullJidMatches) { - Element destroy = x.findChild("destroy"); - final Jid alternate = destroy == null ? null : InvalidJid.getNullForInvalid(destroy.getAttributeAsJid("jid")); - mucOptions.setError(MucOptions.Error.DESTROYED); - if (alternate != null) { - Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": muc destroyed. alternate location " + alternate); - } - } else if (codes.contains(MucOptions.STATUS_CODE_SHUTDOWN) && fullJidMatches) { - mucOptions.setError(MucOptions.Error.SHUTDOWN); - } else if (codes.contains(MucOptions.STATUS_CODE_SELF_PRESENCE)) { - if (codes.contains(MucOptions.STATUS_CODE_TECHNICAL_REASONS)) { + public void parseConferencePresence(PresencePacket packet, Account account) { + final Conversation conversation = + packet.getFrom() == null + ? null + : mXmppConnectionService.find(account, packet.getFrom().asBareJid()); + if (conversation != null) { + final MucOptions mucOptions = conversation.getMucOptions(); + boolean before = mucOptions.online(); + int count = mucOptions.getUserCount(); + final List tileUserBefore = mucOptions.getUsers(5); + processConferencePresence(packet, conversation); + final List tileUserAfter = mucOptions.getUsers(5); + if (!tileUserAfter.equals(tileUserBefore)) { + mXmppConnectionService.getAvatarService().clear(mucOptions); + } + if (before != mucOptions.online() + || (mucOptions.online() && count != mucOptions.getUserCount())) { + mXmppConnectionService.updateConversationUi(); + } else if (mucOptions.online()) { + mXmppConnectionService.updateMucRosterUi(); + } + } + } + + private void processConferencePresence(PresencePacket packet, Conversation conversation) { + final Account account = conversation.getAccount(); + final MucOptions mucOptions = conversation.getMucOptions(); + final Jid jid = conversation.getAccount().getJid(); + final Jid from = packet.getFrom(); + if (!from.isBareJid()) { + final String type = packet.getAttribute("type"); + final Element x = packet.findChild("x", Namespace.MUC_USER); + Avatar avatar = Avatar.parsePresence(packet.findChild("x", "vcard-temp:x:update")); + final List codes = getStatusCodes(x); + if (type == null) { + if (x != null) { + Element item = x.findChild("item"); + if (item != null && !from.isBareJid()) { + mucOptions.setError(MucOptions.Error.NONE); + MucOptions.User user = parseItem(conversation, item, from); + if (codes.contains(MucOptions.STATUS_CODE_SELF_PRESENCE) + || (codes.contains(MucOptions.STATUS_CODE_ROOM_CREATED) + && jid.equals( + InvalidJid.getNullForInvalid( + item.getAttributeAsJid("jid"))))) { + if (mucOptions.setOnline()) { + mXmppConnectionService.getAvatarService().clear(mucOptions); + } + if (mucOptions.setSelf(user)) { + Log.d(Config.LOGTAG, "role or affiliation changed"); + mXmppConnectionService.databaseBackend.updateConversation( + conversation); + } + + mXmppConnectionService.persistSelfNick(user); + invokeRenameListener(mucOptions, true); + } + boolean isNew = mucOptions.updateUser(user); + final AxolotlService axolotlService = + conversation.getAccount().getAxolotlService(); + Contact contact = user.getContact(); + if (isNew + && user.getRealJid() != null + && mucOptions.isPrivateAndNonAnonymous() + && (contact == null || !contact.mutualPresenceSubscription()) + && axolotlService.hasEmptyDeviceList(user.getRealJid())) { + axolotlService.fetchDeviceIds(user.getRealJid()); + } + if (codes.contains(MucOptions.STATUS_CODE_ROOM_CREATED) + && mucOptions.autoPushConfiguration()) { + Log.d( + Config.LOGTAG, + account.getJid().asBareJid() + + ": room '" + + mucOptions.getConversation().getJid().asBareJid() + + "' created. pushing default configuration"); + mXmppConnectionService.pushConferenceConfiguration( + mucOptions.getConversation(), + IqGenerator.defaultChannelConfiguration(), + null); + } + if (mXmppConnectionService.getPgpEngine() != null) { + Element signed = packet.findChild("x", "jabber:x:signed"); + if (signed != null) { + Element status = packet.findChild("status"); + String msg = status == null ? "" : status.getContent(); + long keyId = + mXmppConnectionService + .getPgpEngine() + .fetchKeyId( + mucOptions.getAccount(), + msg, + signed.getContent()); + if (keyId != 0) { + user.setPgpKeyId(keyId); + } + } + } + if (avatar != null) { + avatar.owner = from; + if (mXmppConnectionService.getFileBackend().isAvatarCached(avatar)) { + if (user.setAvatar(avatar)) { + mXmppConnectionService.getAvatarService().clear(user); + } + if (user.getRealJid() != null) { + final Contact c = + conversation + .getAccount() + .getRoster() + .getContact(user.getRealJid()); + c.setAvatar(avatar); + mXmppConnectionService.syncRoster(conversation.getAccount()); + mXmppConnectionService.getAvatarService().clear(c); + mXmppConnectionService.updateRosterUi(); + } + } else if (mXmppConnectionService.isDataSaverDisabled()) { + mXmppConnectionService.fetchAvatar(mucOptions.getAccount(), avatar); + } + } + } + } + } else if (type.equals("unavailable")) { + final boolean fullJidMatches = from.equals(mucOptions.getSelf().getFullJid()); + if (x.hasChild("destroy") && fullJidMatches) { + Element destroy = x.findChild("destroy"); + final Jid alternate = + destroy == null + ? null + : InvalidJid.getNullForInvalid( + destroy.getAttributeAsJid("jid")); + mucOptions.setError(MucOptions.Error.DESTROYED); + if (alternate != null) { + Log.d( + Config.LOGTAG, + account.getJid().asBareJid() + + ": muc destroyed. alternate location " + + alternate); + } + } else if (codes.contains(MucOptions.STATUS_CODE_SHUTDOWN) && fullJidMatches) { + mucOptions.setError(MucOptions.Error.SHUTDOWN); + } else if (codes.contains(MucOptions.STATUS_CODE_SELF_PRESENCE)) { + if (codes.contains(MucOptions.STATUS_CODE_TECHNICAL_REASONS)) { final boolean wasOnline = mucOptions.online(); mucOptions.setError(MucOptions.Error.TECHNICAL_PROBLEMS); Log.d( @@ -157,238 +188,259 @@ public class PresenceParser extends AbstractParser implements if (wasOnline) { mXmppConnectionService.mucSelfPingAndRejoin(conversation); } - } else if (codes.contains(MucOptions.STATUS_CODE_KICKED)) { - mucOptions.setError(MucOptions.Error.KICKED); - } else if (codes.contains(MucOptions.STATUS_CODE_BANNED)) { - mucOptions.setError(MucOptions.Error.BANNED); - } else if (codes.contains(MucOptions.STATUS_CODE_LOST_MEMBERSHIP)) { - mucOptions.setError(MucOptions.Error.MEMBERS_ONLY); - } else if (codes.contains(MucOptions.STATUS_CODE_AFFILIATION_CHANGE)) { - mucOptions.setError(MucOptions.Error.MEMBERS_ONLY); - } else if (codes.contains(MucOptions.STATUS_CODE_SHUTDOWN)) { - mucOptions.setError(MucOptions.Error.SHUTDOWN); - } else if (!codes.contains(MucOptions.STATUS_CODE_CHANGED_NICK)) { - mucOptions.setError(MucOptions.Error.UNKNOWN); - Log.d(Config.LOGTAG, "unknown error in conference: " + packet); - } - } else if (!from.isBareJid()){ - Element item = x.findChild("item"); - if (item != null) { - mucOptions.updateUser(parseItem(conversation, item, from)); - } - MucOptions.User user = mucOptions.deleteUser(from); - if (user != null) { - mXmppConnectionService.getAvatarService().clear(user); - } - } - } else if (type.equals("error")) { - final Element error = packet.findChild("error"); - if (error == null) { - return; - } - if (error.hasChild("conflict")) { - if (mucOptions.online()) { - invokeRenameListener(mucOptions, false); - } else { - mucOptions.setError(MucOptions.Error.NICK_IN_USE); - } - } else if (error.hasChild("not-authorized")) { - mucOptions.setError(MucOptions.Error.PASSWORD_REQUIRED); - } else if (error.hasChild("forbidden")) { - mucOptions.setError(MucOptions.Error.BANNED); - } else if (error.hasChild("registration-required")) { - mucOptions.setError(MucOptions.Error.MEMBERS_ONLY); - } else if (error.hasChild("resource-constraint")) { - mucOptions.setError(MucOptions.Error.RESOURCE_CONSTRAINT); - } else if (error.hasChild("remote-server-timeout")) { - mucOptions.setError(MucOptions.Error.REMOTE_SERVER_TIMEOUT); - } else if (error.hasChild("gone")) { - final String gone = error.findChildContent("gone"); - final Jid alternate; - if (gone != null) { - final XmppUri xmppUri = new XmppUri(gone); - if (xmppUri.isValidJid()) { - alternate = xmppUri.getJid(); - } else { - alternate = null; - } - } else { - alternate = null; - } - mucOptions.setError(MucOptions.Error.DESTROYED); - if (alternate != null) { - Log.d(Config.LOGTAG, conversation.getAccount().getJid().asBareJid() + ": muc destroyed. alternate location " + alternate); - } - } else { - final String text = error.findChildContent("text"); - if (text != null && text.contains("attribute 'to'")) { - if (mucOptions.online()) { - invokeRenameListener(mucOptions, false); - } else { - mucOptions.setError(MucOptions.Error.INVALID_NICK); - } - } else { - mucOptions.setError(MucOptions.Error.UNKNOWN); - Log.d(Config.LOGTAG, "unknown error in conference: " + packet); - } - } - } - } - } + } else if (codes.contains(MucOptions.STATUS_CODE_KICKED)) { + mucOptions.setError(MucOptions.Error.KICKED); + } else if (codes.contains(MucOptions.STATUS_CODE_BANNED)) { + mucOptions.setError(MucOptions.Error.BANNED); + } else if (codes.contains(MucOptions.STATUS_CODE_LOST_MEMBERSHIP)) { + mucOptions.setError(MucOptions.Error.MEMBERS_ONLY); + } else if (codes.contains(MucOptions.STATUS_CODE_AFFILIATION_CHANGE)) { + mucOptions.setError(MucOptions.Error.MEMBERS_ONLY); + } else if (codes.contains(MucOptions.STATUS_CODE_SHUTDOWN)) { + mucOptions.setError(MucOptions.Error.SHUTDOWN); + } else if (!codes.contains(MucOptions.STATUS_CODE_CHANGED_NICK)) { + mucOptions.setError(MucOptions.Error.UNKNOWN); + Log.d(Config.LOGTAG, "unknown error in conference: " + packet); + } + } else if (!from.isBareJid()) { + Element item = x.findChild("item"); + if (item != null) { + mucOptions.updateUser(parseItem(conversation, item, from)); + } + MucOptions.User user = mucOptions.deleteUser(from); + if (user != null) { + mXmppConnectionService.getAvatarService().clear(user); + } + } + } else if (type.equals("error")) { + final Element error = packet.findChild("error"); + if (error == null) { + return; + } + if (error.hasChild("conflict")) { + if (mucOptions.online()) { + invokeRenameListener(mucOptions, false); + } else { + mucOptions.setError(MucOptions.Error.NICK_IN_USE); + } + } else if (error.hasChild("not-authorized")) { + mucOptions.setError(MucOptions.Error.PASSWORD_REQUIRED); + } else if (error.hasChild("forbidden")) { + mucOptions.setError(MucOptions.Error.BANNED); + } else if (error.hasChild("registration-required")) { + mucOptions.setError(MucOptions.Error.MEMBERS_ONLY); + } else if (error.hasChild("resource-constraint")) { + mucOptions.setError(MucOptions.Error.RESOURCE_CONSTRAINT); + } else if (error.hasChild("remote-server-timeout")) { + mucOptions.setError(MucOptions.Error.REMOTE_SERVER_TIMEOUT); + } else if (error.hasChild("gone")) { + final String gone = error.findChildContent("gone"); + final Jid alternate; + if (gone != null) { + final XmppUri xmppUri = new XmppUri(gone); + if (xmppUri.isValidJid()) { + alternate = xmppUri.getJid(); + } else { + alternate = null; + } + } else { + alternate = null; + } + mucOptions.setError(MucOptions.Error.DESTROYED); + if (alternate != null) { + Log.d( + Config.LOGTAG, + conversation.getAccount().getJid().asBareJid() + + ": muc destroyed. alternate location " + + alternate); + } + } else { + final String text = error.findChildContent("text"); + if (text != null && text.contains("attribute 'to'")) { + if (mucOptions.online()) { + invokeRenameListener(mucOptions, false); + } else { + mucOptions.setError(MucOptions.Error.INVALID_NICK); + } + } else { + mucOptions.setError(MucOptions.Error.UNKNOWN); + Log.d(Config.LOGTAG, "unknown error in conference: " + packet); + } + } + } + } + } - private static void invokeRenameListener(final MucOptions options, boolean success) { - if (options.onRenameListener != null) { - if (success) { - options.onRenameListener.onSuccess(); - } else { - options.onRenameListener.onFailure(); - } - options.onRenameListener = null; - } - } + private static void invokeRenameListener(final MucOptions options, boolean success) { + if (options.onRenameListener != null) { + if (success) { + options.onRenameListener.onSuccess(); + } else { + options.onRenameListener.onFailure(); + } + options.onRenameListener = null; + } + } - private static List getStatusCodes(Element x) { - List codes = new ArrayList<>(); - if (x != null) { - for (Element child : x.getChildren()) { - if (child.getName().equals("status")) { - String code = child.getAttribute("code"); - if (code != null) { - codes.add(code); - } - } - } - } - return codes; - } + private static List getStatusCodes(Element x) { + List codes = new ArrayList<>(); + if (x != null) { + for (Element child : x.getChildren()) { + if (child.getName().equals("status")) { + String code = child.getAttribute("code"); + if (code != null) { + codes.add(code); + } + } + } + } + return codes; + } - private void parseContactPresence(final PresencePacket packet, final Account account) { - final PresenceGenerator mPresenceGenerator = mXmppConnectionService.getPresenceGenerator(); - final Jid from = packet.getFrom(); - if (from == null || from.equals(account.getJid())) { - return; - } - final String type = packet.getAttribute("type"); - final Contact contact = account.getRoster().getContact(from); - if (type == null) { - final String resource = from.isBareJid() ? "" : from.getResource(); - Avatar avatar = Avatar.parsePresence(packet.findChild("x", "vcard-temp:x:update")); - if (avatar != null && (!contact.isSelf() || account.getAvatar() == null)) { - avatar.owner = from.asBareJid(); - if (mXmppConnectionService.getFileBackend().isAvatarCached(avatar)) { - if (avatar.owner.equals(account.getJid().asBareJid())) { - account.setAvatar(avatar.getFilename()); - mXmppConnectionService.databaseBackend.updateAccount(account); - mXmppConnectionService.getAvatarService().clear(account); - mXmppConnectionService.updateConversationUi(); - mXmppConnectionService.updateAccountUi(); - } else { - contact.setAvatar(avatar); - mXmppConnectionService.syncRoster(account); - mXmppConnectionService.getAvatarService().clear(contact); - mXmppConnectionService.updateConversationUi(); - mXmppConnectionService.updateRosterUi(); - } - } else if (mXmppConnectionService.isDataSaverDisabled()){ - mXmppConnectionService.fetchAvatar(account, avatar); - } - } + private void parseContactPresence(final PresencePacket packet, final Account account) { + final PresenceGenerator mPresenceGenerator = mXmppConnectionService.getPresenceGenerator(); + final Jid from = packet.getFrom(); + if (from == null || from.equals(account.getJid())) { + return; + } + final String type = packet.getAttribute("type"); + final Contact contact = account.getRoster().getContact(from); + if (type == null) { + final String resource = from.isBareJid() ? "" : from.getResource(); + final Avatar avatar = + Avatar.parsePresence(packet.findChild("x", "vcard-temp:x:update")); + if (avatar != null && (!contact.isSelf() || account.getAvatar() == null)) { + avatar.owner = from.asBareJid(); + if (mXmppConnectionService.getFileBackend().isAvatarCached(avatar)) { + if (avatar.owner.equals(account.getJid().asBareJid())) { + account.setAvatar(avatar.getFilename()); + mXmppConnectionService.databaseBackend.updateAccount(account); + mXmppConnectionService.getAvatarService().clear(account); + mXmppConnectionService.updateConversationUi(); + mXmppConnectionService.updateAccountUi(); + } else { + contact.setAvatar(avatar); + mXmppConnectionService.syncRoster(account); + mXmppConnectionService.getAvatarService().clear(contact); + mXmppConnectionService.updateConversationUi(); + mXmppConnectionService.updateRosterUi(); + } + } else if (mXmppConnectionService.isDataSaverDisabled()) { + mXmppConnectionService.fetchAvatar(account, avatar); + } + } - if (mXmppConnectionService.isMuc(account, from)) { - return; - } + if (mXmppConnectionService.isMuc(account, from)) { + return; + } - int sizeBefore = contact.getPresences().size(); + final int sizeBefore = contact.getPresences().size(); - final String show = packet.findChildContent("show"); - final Element caps = packet.findChild("c", "http://jabber.org/protocol/caps"); - final String message = packet.findChildContent("status"); - final Presence presence = Presence.parse(show, caps, message); - contact.updatePresence(resource, presence); - if (presence.hasCaps()) { - mXmppConnectionService.fetchCaps(account, from, presence); - } + final String show = packet.findChildContent("show"); + final Element caps = packet.findChild("c", "http://jabber.org/protocol/caps"); + final String message = packet.findChildContent("status"); + final Presence presence = Presence.parse(show, caps, message); + contact.updatePresence(resource, presence); + if (presence.hasCaps()) { + mXmppConnectionService.fetchCaps(account, from, presence); + } - final Element idle = packet.findChild("idle", Namespace.IDLE); - if (idle != null) { - try { - final String since = idle.getAttribute("since"); - contact.setLastseen(AbstractParser.parseTimestamp(since)); - contact.flagInactive(); - } catch (Throwable throwable) { - if (contact.setLastseen(AbstractParser.parseTimestamp(packet))) { - contact.flagActive(); - } - } - } else { - if (contact.setLastseen(AbstractParser.parseTimestamp(packet))) { - contact.flagActive(); - } - } + final Element idle = packet.findChild("idle", Namespace.IDLE); + if (idle != null) { + try { + final String since = idle.getAttribute("since"); + contact.setLastseen(AbstractParser.parseTimestamp(since)); + contact.flagInactive(); + } catch (Throwable throwable) { + if (contact.setLastseen(AbstractParser.parseTimestamp(packet))) { + contact.flagActive(); + } + } + } else { + if (contact.setLastseen(AbstractParser.parseTimestamp(packet))) { + contact.flagActive(); + } + } - PgpEngine pgp = mXmppConnectionService.getPgpEngine(); - Element x = packet.findChild("x", "jabber:x:signed"); - if (pgp != null && x != null) { - final String status = packet.findChildContent("status"); - final long keyId = pgp.fetchKeyId(account, status, x.getContent()); - if (keyId != 0 && contact.setPgpKeyId(keyId)) { - Log.d(Config.LOGTAG,account.getJid().asBareJid()+": found OpenPGP key id for "+contact.getJid()+" "+OpenPgpUtils.convertKeyIdToHex(keyId)); - mXmppConnectionService.syncRoster(account); - } - } - boolean online = sizeBefore < contact.getPresences().size(); - mXmppConnectionService.onContactStatusChanged.onContactStatusChanged(contact, online); - } else if (type.equals("unavailable")) { - if (contact.setLastseen(AbstractParser.parseTimestamp(packet,0L,true))) { - contact.flagInactive(); - } - if (from.isBareJid()) { - contact.clearPresences(); - } else { - contact.removePresence(from.getResource()); - } - if (contact.getShownStatus() == Presence.Status.OFFLINE) { - contact.flagInactive(); - } - mXmppConnectionService.onContactStatusChanged.onContactStatusChanged(contact, false); - } else if (type.equals("subscribe")) { - if (contact.setPresenceName(packet.findChildContent("nick", Namespace.NICK))) { - mXmppConnectionService.syncRoster(account); - mXmppConnectionService.getAvatarService().clear(contact); - } - if (contact.getOption(Contact.Options.PREEMPTIVE_GRANT)) { - mXmppConnectionService.sendPresencePacket(account, - mPresenceGenerator.sendPresenceUpdatesTo(contact)); - } else { - contact.setOption(Contact.Options.PENDING_SUBSCRIPTION_REQUEST); - final Conversation conversation = mXmppConnectionService.findOrCreateConversation( - account, contact.getJid().asBareJid(), false, false); - final String statusMessage = packet.findChildContent("status"); - if (statusMessage != null - && !statusMessage.isEmpty() - && conversation.countMessages() == 0) { - conversation.add(new Message( - conversation, - statusMessage, - Message.ENCRYPTION_NONE, - Message.STATUS_RECEIVED - )); - } - } - } - mXmppConnectionService.updateRosterUi(); - } + final PgpEngine pgp = mXmppConnectionService.getPgpEngine(); + final Element x = packet.findChild("x", "jabber:x:signed"); + if (pgp != null && x != null) { + final String status = packet.findChildContent("status"); + final long keyId = pgp.fetchKeyId(account, status, x.getContent()); + if (keyId != 0 && contact.setPgpKeyId(keyId)) { + Log.d( + Config.LOGTAG, + account.getJid().asBareJid() + + ": found OpenPGP key id for " + + contact.getJid() + + " " + + OpenPgpUtils.convertKeyIdToHex(keyId)); + mXmppConnectionService.syncRoster(account); + } + } + boolean online = sizeBefore < contact.getPresences().size(); + mXmppConnectionService.onContactStatusChanged.onContactStatusChanged(contact, online); + } else if (type.equals("unavailable")) { + if (contact.setLastseen(AbstractParser.parseTimestamp(packet, 0L, true))) { + contact.flagInactive(); + } + if (from.isBareJid()) { + contact.clearPresences(); + } else { + contact.removePresence(from.getResource()); + } + if (contact.getShownStatus() == Presence.Status.OFFLINE) { + contact.flagInactive(); + } + mXmppConnectionService.onContactStatusChanged.onContactStatusChanged(contact, false); + } else if (type.equals("subscribe")) { + if (contact.isBlocked()) { + Log.d( + Config.LOGTAG, + account.getJid().asBareJid() + + ": ignoring 'subscribe' presence from blocked " + + from); + return; + } + if (contact.setPresenceName(packet.findChildContent("nick", Namespace.NICK))) { + mXmppConnectionService.syncRoster(account); + mXmppConnectionService.getAvatarService().clear(contact); + } + if (contact.getOption(Contact.Options.PREEMPTIVE_GRANT)) { + mXmppConnectionService.sendPresencePacket( + account, mPresenceGenerator.sendPresenceUpdatesTo(contact)); + } else { + contact.setOption(Contact.Options.PENDING_SUBSCRIPTION_REQUEST); + final Conversation conversation = + mXmppConnectionService.findOrCreateConversation( + account, contact.getJid().asBareJid(), false, false); + final String statusMessage = packet.findChildContent("status"); + if (statusMessage != null + && !statusMessage.isEmpty() + && conversation.countMessages() == 0) { + conversation.add( + new Message( + conversation, + statusMessage, + Message.ENCRYPTION_NONE, + Message.STATUS_RECEIVED)); + } + } + } + mXmppConnectionService.updateRosterUi(); + } - @Override - public void onPresencePacketReceived(Account account, PresencePacket packet) { - if (packet.hasChild("x", Namespace.MUC_USER)) { - this.parseConferencePresence(packet, account); - } else if (packet.hasChild("x", "http://jabber.org/protocol/muc")) { - this.parseConferencePresence(packet, account); - } else if ("error".equals(packet.getAttribute("type")) && mXmppConnectionService.isMuc(account, packet.getFrom())) { - this.parseConferencePresence(packet, account); - } else { - this.parseContactPresence(packet, account); - } - } + @Override + public void onPresencePacketReceived(Account account, PresencePacket packet) { + if (packet.hasChild("x", Namespace.MUC_USER)) { + this.parseConferencePresence(packet, account); + } else if (packet.hasChild("x", "http://jabber.org/protocol/muc")) { + this.parseConferencePresence(packet, account); + } else if ("error".equals(packet.getAttribute("type")) + && mXmppConnectionService.isMuc(account, packet.getFrom())) { + this.parseConferencePresence(packet, account); + } else { + this.parseContactPresence(packet, account); + } + } }