diff options
Diffstat (limited to 'src/main/java/eu/siacs/conversations/parser')
4 files changed, 0 insertions, 1431 deletions
diff --git a/src/main/java/eu/siacs/conversations/parser/AbstractParser.java b/src/main/java/eu/siacs/conversations/parser/AbstractParser.java deleted file mode 100644 index 4699d2868..000000000 --- a/src/main/java/eu/siacs/conversations/parser/AbstractParser.java +++ /dev/null @@ -1,95 +0,0 @@ -package eu.siacs.conversations.parser; - -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Locale; - -import eu.siacs.conversations.entities.Account; -import eu.siacs.conversations.entities.Contact; -import eu.siacs.conversations.entities.Conversation; -import eu.siacs.conversations.entities.MucOptions; -import eu.siacs.conversations.services.XmppConnectionService; -import eu.siacs.conversations.xml.Element; -import eu.siacs.conversations.xmpp.jid.InvalidJidException; -import eu.siacs.conversations.xmpp.jid.Jid; - -public abstract class AbstractParser { - - protected XmppConnectionService mXmppConnectionService; - - protected AbstractParser(XmppConnectionService service) { - this.mXmppConnectionService = service; - } - - public static Long parseTimestamp(Element element, Long d) { - Element delay = element.findChild("delay","urn:xmpp:delay"); - if (delay != null) { - String stamp = delay.getAttribute("stamp"); - if (stamp != null) { - try { - return AbstractParser.parseTimestamp(delay.getAttribute("stamp")); - } catch (ParseException e) { - return d; - } - } - } - return d; - } - - public static long parseTimestamp(Element element) { - return parseTimestamp(element, System.currentTimeMillis()); - } - - public static long parseTimestamp(String timestamp) throws ParseException { - timestamp = timestamp.replace("Z", "+0000"); - SimpleDateFormat dateFormat; - long ms; - if (timestamp.charAt(19) == '.' && timestamp.length() >= 25) { - String millis = timestamp.substring(19,timestamp.length() - 5); - try { - double fractions = Double.parseDouble("0" + millis); - ms = Math.round(1000 * fractions); - } catch (NumberFormatException e) { - ms = 0; - } - } else { - ms = 0; - } - timestamp = timestamp.substring(0,19)+timestamp.substring(timestamp.length() -5,timestamp.length()); - dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ",Locale.US); - return Math.min(dateFormat.parse(timestamp).getTime()+ms, System.currentTimeMillis()); - } - - protected void updateLastseen(final Account account, final Jid from) { - final Contact contact = account.getRoster().getContact(from); - contact.setLastPresence(from.isBareJid() ? "" : from.getResourcepart()); - } - - protected String avatarData(Element items) { - Element item = items.findChild("item"); - if (item == null) { - return null; - } - return item.findChildContent("data", "urn:xmpp:avatar:data"); - } - - public static MucOptions.User parseItem(Conversation conference, Element item) { - final String local = conference.getJid().getLocalpart(); - final String domain = conference.getJid().getDomainpart(); - String affiliation = item.getAttribute("affiliation"); - String role = item.getAttribute("role"); - String nick = item.getAttribute("nick"); - Jid fullJid; - try { - fullJid = nick != null ? Jid.fromParts(local, domain, nick) : null; - } catch (InvalidJidException e) { - fullJid = null; - } - Jid realJid = item.getAttributeAsJid("jid"); - MucOptions.User user = new MucOptions.User(conference.getMucOptions(), nick == null ? null : fullJid); - user.setRealJid(realJid); - user.setAffiliation(affiliation); - user.setRole(role); - return user; - } -} diff --git a/src/main/java/eu/siacs/conversations/parser/IqParser.java b/src/main/java/eu/siacs/conversations/parser/IqParser.java deleted file mode 100644 index 4e925e97d..000000000 --- a/src/main/java/eu/siacs/conversations/parser/IqParser.java +++ /dev/null @@ -1,380 +0,0 @@ -package eu.siacs.conversations.parser; - -import android.support.annotation.NonNull; -import android.util.Base64; -import android.util.Log; -import android.util.Pair; - -import org.whispersystems.libaxolotl.IdentityKey; -import org.whispersystems.libaxolotl.ecc.Curve; -import org.whispersystems.libaxolotl.ecc.ECPublicKey; -import org.whispersystems.libaxolotl.state.PreKeyBundle; - -import java.io.ByteArrayInputStream; -import java.security.cert.CertificateException; -import java.security.cert.CertificateFactory; -import java.security.cert.X509Certificate; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import eu.siacs.conversations.Config; -import eu.siacs.conversations.crypto.axolotl.AxolotlService; -import eu.siacs.conversations.entities.Account; -import eu.siacs.conversations.entities.Contact; -import eu.siacs.conversations.services.XmppConnectionService; -import eu.siacs.conversations.utils.Xmlns; -import eu.siacs.conversations.xml.Element; -import eu.siacs.conversations.xmpp.OnIqPacketReceived; -import eu.siacs.conversations.xmpp.OnUpdateBlocklist; -import eu.siacs.conversations.xmpp.jid.Jid; -import eu.siacs.conversations.xmpp.stanzas.IqPacket; - -public class IqParser extends AbstractParser implements OnIqPacketReceived { - - public IqParser(final XmppConnectionService service) { - super(service); - } - - private void rosterItems(final Account account, final Element query) { - final String version = query.getAttribute("ver"); - if (version != null) { - account.getRoster().setVersion(version); - } - for (final Element item : query.getChildren()) { - if (item.getName().equals("item")) { - final Jid jid = item.getAttributeAsJid("jid"); - if (jid == null) { - continue; - } - final String name = item.getAttribute("name"); - final String subscription = item.getAttribute("subscription"); - final Contact contact = account.getRoster().getContact(jid); - boolean bothPre = contact.getOption(Contact.Options.TO) && contact.getOption(Contact.Options.FROM); - if (!contact.getOption(Contact.Options.DIRTY_PUSH)) { - contact.setServerName(name); - contact.parseGroupsFromElement(item); - } - if (subscription != null) { - if (subscription.equals("remove")) { - contact.resetOption(Contact.Options.IN_ROSTER); - contact.resetOption(Contact.Options.DIRTY_DELETE); - contact.resetOption(Contact.Options.PREEMPTIVE_GRANT); - } else { - contact.setOption(Contact.Options.IN_ROSTER); - contact.resetOption(Contact.Options.DIRTY_PUSH); - contact.parseSubscriptionFromElement(item); - } - } - boolean both = contact.getOption(Contact.Options.TO) && contact.getOption(Contact.Options.FROM); - if ((both != bothPre) && both) { - Log.d(Config.LOGTAG,account.getJid().toBareJid()+": gained mutual presence subscription with "+contact.getJid()); - AxolotlService axolotlService = account.getAxolotlService(); - if (axolotlService != null) { - axolotlService.clearErrorsInFetchStatusMap(contact.getJid()); - } - } - mXmppConnectionService.getAvatarService().clear(contact); - } - } - mXmppConnectionService.updateConversationUi(); - mXmppConnectionService.updateRosterUi(); - } - - public String avatarData(final IqPacket packet) { - final Element pubsub = packet.findChild("pubsub", - "http://jabber.org/protocol/pubsub"); - if (pubsub == null) { - return null; - } - final Element items = pubsub.findChild("items"); - if (items == null) { - return null; - } - return super.avatarData(items); - } - - public Element getItem(final IqPacket packet) { - final Element pubsub = packet.findChild("pubsub", - "http://jabber.org/protocol/pubsub"); - if (pubsub == null) { - return null; - } - final Element items = pubsub.findChild("items"); - if (items == null) { - return null; - } - return items.findChild("item"); - } - - @NonNull - public Set<Integer> deviceIds(final Element item) { - Set<Integer> deviceIds = new HashSet<>(); - if (item != null) { - final Element list = item.findChild("list"); - if (list != null) { - for (Element device : list.getChildren()) { - if (!device.getName().equals("device")) { - continue; - } - try { - Integer id = Integer.valueOf(device.getAttribute("id")); - deviceIds.add(id); - } catch (NumberFormatException e) { - Log.e(Config.LOGTAG, AxolotlService.LOGPREFIX+" : "+"Encountered invalid <device> node in PEP ("+e.getMessage()+"):" + device.toString()+ ", skipping..."); - continue; - } - } - } - } - return deviceIds; - } - - public Integer signedPreKeyId(final Element bundle) { - final Element signedPreKeyPublic = bundle.findChild("signedPreKeyPublic"); - if(signedPreKeyPublic == null) { - return null; - } - return Integer.valueOf(signedPreKeyPublic.getAttribute("signedPreKeyId")); - } - - public ECPublicKey signedPreKeyPublic(final Element bundle) { - ECPublicKey publicKey = null; - final Element signedPreKeyPublic = bundle.findChild("signedPreKeyPublic"); - if(signedPreKeyPublic == null) { - return null; - } - try { - publicKey = Curve.decodePoint(Base64.decode(signedPreKeyPublic.getContent(),Base64.DEFAULT), 0); - } catch (Throwable e) { - Log.e(Config.LOGTAG, AxolotlService.LOGPREFIX+" : "+"Invalid signedPreKeyPublic in PEP: " + e.getMessage()); - } - return publicKey; - } - - public byte[] signedPreKeySignature(final Element bundle) { - final Element signedPreKeySignature = bundle.findChild("signedPreKeySignature"); - if(signedPreKeySignature == null) { - return null; - } - try { - return Base64.decode(signedPreKeySignature.getContent(), Base64.DEFAULT); - } catch (Throwable e) { - Log.e(Config.LOGTAG,AxolotlService.LOGPREFIX+" : Invalid base64 in signedPreKeySignature"); - return null; - } - } - - public IdentityKey identityKey(final Element bundle) { - IdentityKey identityKey = null; - final Element identityKeyElement = bundle.findChild("identityKey"); - if(identityKeyElement == null) { - return null; - } - try { - identityKey = new IdentityKey(Base64.decode(identityKeyElement.getContent(), Base64.DEFAULT), 0); - } catch (Throwable e) { - Log.e(Config.LOGTAG,AxolotlService.LOGPREFIX+" : "+"Invalid identityKey in PEP: "+e.getMessage()); - } - return identityKey; - } - - public Map<Integer, ECPublicKey> preKeyPublics(final IqPacket packet) { - Map<Integer, ECPublicKey> preKeyRecords = new HashMap<>(); - Element item = getItem(packet); - if (item == null) { - Log.d(Config.LOGTAG, AxolotlService.LOGPREFIX+" : "+"Couldn't find <item> in bundle IQ packet: " + packet); - return null; - } - final Element bundleElement = item.findChild("bundle"); - if(bundleElement == null) { - return null; - } - final Element prekeysElement = bundleElement.findChild("prekeys"); - if(prekeysElement == null) { - Log.d(Config.LOGTAG, AxolotlService.LOGPREFIX+" : "+"Couldn't find <prekeys> in bundle IQ packet: " + packet); - return null; - } - for(Element preKeyPublicElement : prekeysElement.getChildren()) { - if(!preKeyPublicElement.getName().equals("preKeyPublic")){ - Log.d(Config.LOGTAG, AxolotlService.LOGPREFIX+" : "+"Encountered unexpected tag in prekeys list: " + preKeyPublicElement); - continue; - } - Integer preKeyId = Integer.valueOf(preKeyPublicElement.getAttribute("preKeyId")); - try { - ECPublicKey preKeyPublic = Curve.decodePoint(Base64.decode(preKeyPublicElement.getContent(), Base64.DEFAULT), 0); - preKeyRecords.put(preKeyId, preKeyPublic); - } catch (Throwable e) { - Log.e(Config.LOGTAG, AxolotlService.LOGPREFIX+" : "+"Invalid preKeyPublic (ID="+preKeyId+") in PEP: "+ e.getMessage()+", skipping..."); - continue; - } - } - return preKeyRecords; - } - - public Pair<X509Certificate[],byte[]> verification(final IqPacket packet) { - Element item = getItem(packet); - Element verification = item != null ? item.findChild("verification",AxolotlService.PEP_PREFIX) : null; - Element chain = verification != null ? verification.findChild("chain") : null; - Element signature = verification != null ? verification.findChild("signature") : null; - if (chain != null && signature != null) { - List<Element> certElements = chain.getChildren(); - X509Certificate[] certificates = new X509Certificate[certElements.size()]; - try { - CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509"); - int i = 0; - for(Element cert : certElements) { - certificates[i] = (X509Certificate) certificateFactory.generateCertificate(new ByteArrayInputStream(Base64.decode(cert.getContent(),Base64.DEFAULT))); - ++i; - } - return new Pair<>(certificates,Base64.decode(signature.getContent(),Base64.DEFAULT)); - } catch (CertificateException e) { - return null; - } - } else { - return null; - } - } - - public PreKeyBundle bundle(final IqPacket bundle) { - Element bundleItem = getItem(bundle); - if(bundleItem == null) { - return null; - } - final Element bundleElement = bundleItem.findChild("bundle"); - if(bundleElement == null) { - return null; - } - ECPublicKey signedPreKeyPublic = signedPreKeyPublic(bundleElement); - Integer signedPreKeyId = signedPreKeyId(bundleElement); - byte[] signedPreKeySignature = signedPreKeySignature(bundleElement); - IdentityKey identityKey = identityKey(bundleElement); - if(signedPreKeyPublic == null || identityKey == null) { - return null; - } - - return new PreKeyBundle(0, 0, 0, null, - signedPreKeyId, signedPreKeyPublic, signedPreKeySignature, identityKey); - } - - public List<PreKeyBundle> preKeys(final IqPacket preKeys) { - List<PreKeyBundle> bundles = new ArrayList<>(); - Map<Integer, ECPublicKey> preKeyPublics = preKeyPublics(preKeys); - if ( preKeyPublics != null) { - for (Integer preKeyId : preKeyPublics.keySet()) { - ECPublicKey preKeyPublic = preKeyPublics.get(preKeyId); - bundles.add(new PreKeyBundle(0, 0, preKeyId, preKeyPublic, - 0, null, null, null)); - } - } - - return bundles; - } - - @Override - public void onIqPacketReceived(final Account account, final IqPacket packet) { - final boolean isGet = packet.getType() == IqPacket.TYPE.GET; - if (packet.getType() == IqPacket.TYPE.ERROR || packet.getType() == IqPacket.TYPE.TIMEOUT) { - return; - } else if (packet.hasChild("query", Xmlns.ROSTER) && packet.fromServer(account)) { - final Element query = packet.findChild("query"); - // If this is in response to a query for the whole roster: - if (packet.getType() == IqPacket.TYPE.RESULT) { - account.getRoster().markAllAsNotInRoster(); - } - this.rosterItems(account, query); - } else if ((packet.hasChild("block", Xmlns.BLOCKING) || packet.hasChild("blocklist", Xmlns.BLOCKING)) && - packet.fromServer(account)) { - // Block list or block push. - Log.d(Config.LOGTAG, "Received blocklist update from server"); - final Element blocklist = packet.findChild("blocklist", Xmlns.BLOCKING); - final Element block = packet.findChild("block", Xmlns.BLOCKING); - final Collection<Element> items = blocklist != null ? blocklist.getChildren() : - (block != null ? block.getChildren() : null); - // If this is a response to a blocklist query, clear the block list and replace with the new one. - // Otherwise, just update the existing blocklist. - if (packet.getType() == IqPacket.TYPE.RESULT) { - account.clearBlocklist(); - account.getXmppConnection().getFeatures().setBlockListRequested(true); - } - if (items != null) { - final Collection<Jid> jids = new ArrayList<>(items.size()); - // Create a collection of Jids from the packet - for (final Element item : items) { - if (item.getName().equals("item")) { - final Jid jid = item.getAttributeAsJid("jid"); - if (jid != null) { - jids.add(jid); - } - } - } - account.getBlocklist().addAll(jids); - } - // Update the UI - mXmppConnectionService.updateBlocklistUi(OnUpdateBlocklist.Status.BLOCKED); - if (packet.getType() == IqPacket.TYPE.SET) { - final IqPacket response = packet.generateResponse(IqPacket.TYPE.RESULT); - mXmppConnectionService.sendIqPacket(account, response, null); - } - } else if (packet.hasChild("unblock", Xmlns.BLOCKING) && - packet.fromServer(account) && packet.getType() == IqPacket.TYPE.SET) { - Log.d(Config.LOGTAG, "Received unblock update from server"); - final Collection<Element> items = packet.findChild("unblock", Xmlns.BLOCKING).getChildren(); - if (items.size() == 0) { - // No children to unblock == unblock all - account.getBlocklist().clear(); - } else { - final Collection<Jid> jids = new ArrayList<>(items.size()); - for (final Element item : items) { - if (item.getName().equals("item")) { - final Jid jid = item.getAttributeAsJid("jid"); - if (jid != null) { - jids.add(jid); - } - } - } - account.getBlocklist().removeAll(jids); - } - mXmppConnectionService.updateBlocklistUi(OnUpdateBlocklist.Status.UNBLOCKED); - final IqPacket response = packet.generateResponse(IqPacket.TYPE.RESULT); - mXmppConnectionService.sendIqPacket(account, response, null); - } else if (packet.hasChild("open", "http://jabber.org/protocol/ibb") - || packet.hasChild("data", "http://jabber.org/protocol/ibb")) { - mXmppConnectionService.getJingleConnectionManager() - .deliverIbbPacket(account, packet); - } else if (packet.hasChild("query", "http://jabber.org/protocol/disco#info")) { - final IqPacket response = mXmppConnectionService.getIqGenerator().discoResponse(packet); - mXmppConnectionService.sendIqPacket(account, response, null); - } else if (packet.hasChild("query","jabber:iq:version") && isGet) { - final IqPacket response = mXmppConnectionService.getIqGenerator().versionResponse(packet); - mXmppConnectionService.sendIqPacket(account,response,null); - } else if (packet.hasChild("ping", "urn:xmpp:ping") && isGet) { - final IqPacket response = packet.generateResponse(IqPacket.TYPE.RESULT); - mXmppConnectionService.sendIqPacket(account, response, null); - } else if (packet.hasChild("time","urn:xmpp:time") && isGet) { - final IqPacket response; - if (mXmppConnectionService.useTorToConnect()) { - response = packet.generateResponse(IqPacket.TYPE.ERROR); - final Element error = response.addChild("error"); - error.setAttribute("type","cancel"); - error.addChild("not-allowed","urn:ietf:params:xml:ns:xmpp-stanzas"); - } else { - response = mXmppConnectionService.getIqGenerator().entityTimeResponse(packet); - } - mXmppConnectionService.sendIqPacket(account,response, null); - } else { - if (packet.getType() == IqPacket.TYPE.GET || packet.getType() == IqPacket.TYPE.SET) { - final IqPacket response = packet.generateResponse(IqPacket.TYPE.ERROR); - final Element error = response.addChild("error"); - error.setAttribute("type", "cancel"); - error.addChild("feature-not-implemented","urn:ietf:params:xml:ns:xmpp-stanzas"); - account.getXmppConnection().sendIqPacket(response, null); - } - } - } - -} diff --git a/src/main/java/eu/siacs/conversations/parser/MessageParser.java b/src/main/java/eu/siacs/conversations/parser/MessageParser.java deleted file mode 100644 index f3958621c..000000000 --- a/src/main/java/eu/siacs/conversations/parser/MessageParser.java +++ /dev/null @@ -1,682 +0,0 @@ -package eu.siacs.conversations.parser; - -import android.text.Html; -import android.util.Log; -import android.util.Pair; - -import net.java.otr4j.session.Session; -import net.java.otr4j.session.SessionStatus; - -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Date; -import java.util.List; -import java.util.Set; -import java.util.UUID; - -import eu.siacs.conversations.Config; -import eu.siacs.conversations.crypto.OtrService; -import eu.siacs.conversations.crypto.axolotl.AxolotlService; -import eu.siacs.conversations.crypto.axolotl.XmppAxolotlMessage; -import eu.siacs.conversations.entities.Account; -import eu.siacs.conversations.entities.Bookmark; -import eu.siacs.conversations.entities.Contact; -import eu.siacs.conversations.entities.Conversation; -import eu.siacs.conversations.entities.Message; -import eu.siacs.conversations.entities.MucOptions; -import eu.siacs.conversations.entities.Presence; -import eu.siacs.conversations.entities.ServiceDiscoveryResult; -import eu.siacs.conversations.http.HttpConnectionManager; -import eu.siacs.conversations.services.MessageArchiveService; -import eu.siacs.conversations.services.XmppConnectionService; -import eu.siacs.conversations.utils.CryptoHelper; -import eu.siacs.conversations.xml.Element; -import eu.siacs.conversations.xmpp.OnMessagePacketReceived; -import eu.siacs.conversations.xmpp.chatstate.ChatState; -import eu.siacs.conversations.xmpp.jid.Jid; -import eu.siacs.conversations.xmpp.pep.Avatar; -import eu.siacs.conversations.xmpp.stanzas.MessagePacket; - -public class MessageParser extends AbstractParser implements OnMessagePacketReceived { - - private static final List<String> CLIENTS_SENDING_HTML_IN_OTR = Arrays.asList("Pidgin","Adium","Trillian"); - - public MessageParser(XmppConnectionService service) { - super(service); - } - - private boolean extractChatState(Conversation conversation, final MessagePacket packet) { - ChatState state = ChatState.parse(packet); - if (state != null && conversation != null) { - final Account account = conversation.getAccount(); - Jid from = packet.getFrom(); - if (from.toBareJid().equals(account.getJid().toBareJid())) { - conversation.setOutgoingChatState(state); - if (state == ChatState.ACTIVE || state == ChatState.COMPOSING) { - mXmppConnectionService.markRead(conversation); - activateGracePeriod(account); - } - return false; - } else { - return conversation.setIncomingChatState(state); - } - } - return false; - } - - private Message parseOtrChat(String body, Jid from, String id, Conversation conversation) { - String presence; - if (from.isBareJid()) { - presence = ""; - } else { - presence = from.getResourcepart(); - } - if (body.matches("^\\?OTRv\\d{1,2}\\?.*")) { - conversation.endOtrIfNeeded(); - } - if (!conversation.hasValidOtrSession()) { - conversation.startOtrSession(presence,false); - } else { - String foreignPresence = conversation.getOtrSession().getSessionID().getUserID(); - if (!foreignPresence.equals(presence)) { - conversation.endOtrIfNeeded(); - conversation.startOtrSession(presence, false); - } - } - try { - conversation.setLastReceivedOtrMessageId(id); - Session otrSession = conversation.getOtrSession(); - body = otrSession.transformReceiving(body); - SessionStatus status = otrSession.getSessionStatus(); - if (body == null && status == SessionStatus.ENCRYPTED) { - mXmppConnectionService.onOtrSessionEstablished(conversation); - return null; - } else if (body == null && status == SessionStatus.FINISHED) { - conversation.resetOtrSession(); - mXmppConnectionService.updateConversationUi(); - return null; - } else if (body == null || (body.isEmpty())) { - return null; - } - if (body.startsWith(CryptoHelper.FILETRANSFER)) { - String key = body.substring(CryptoHelper.FILETRANSFER.length()); - conversation.setSymmetricKey(CryptoHelper.hexToBytes(key)); - return null; - } - if (clientMightSendHtml(conversation.getAccount(), from)) { - Log.d(Config.LOGTAG,conversation.getAccount().getJid().toBareJid()+": received OTR message from bad behaving client. escaping HTML…"); - body = Html.fromHtml(body).toString(); - } - - final OtrService otrService = conversation.getAccount().getOtrService(); - Message finishedMessage = new Message(conversation, body, Message.ENCRYPTION_OTR, Message.STATUS_RECEIVED); - finishedMessage.setFingerprint(otrService.getFingerprint(otrSession.getRemotePublicKey())); - conversation.setLastReceivedOtrMessageId(null); - - return finishedMessage; - } catch (Exception e) { - conversation.resetOtrSession(); - return null; - } - } - - private static boolean clientMightSendHtml(Account account, Jid from) { - String resource = from.getResourcepart(); - if (resource == null) { - return false; - } - Presence presence = account.getRoster().getContact(from).getPresences().getPresences().get(resource); - ServiceDiscoveryResult disco = presence == null ? null : presence.getServiceDiscoveryResult(); - if (disco == null) { - return false; - } - return hasIdentityKnowForSendingHtml(disco.getIdentities()); - } - - private static boolean hasIdentityKnowForSendingHtml(List<ServiceDiscoveryResult.Identity> identities) { - for(ServiceDiscoveryResult.Identity identity : identities) { - if (identity.getName() != null) { - if (CLIENTS_SENDING_HTML_IN_OTR.contains(identity.getName())) { - return true; - } - } - } - return false; - } - - private Message parseAxolotlChat(Element axolotlMessage, Jid from, Conversation conversation, int status) { - AxolotlService service = conversation.getAccount().getAxolotlService(); - XmppAxolotlMessage xmppAxolotlMessage; - try { - xmppAxolotlMessage = XmppAxolotlMessage.fromElement(axolotlMessage, from.toBareJid()); - } catch (Exception e) { - Log.d(Config.LOGTAG,conversation.getAccount().getJid().toBareJid()+": invalid omemo message received "+e.getMessage()); - return null; - } - XmppAxolotlMessage.XmppAxolotlPlaintextMessage plaintextMessage = service.processReceivingPayloadMessage(xmppAxolotlMessage); - if(plaintextMessage != null) { - Message finishedMessage = new Message(conversation, plaintextMessage.getPlaintext(), Message.ENCRYPTION_AXOLOTL, status); - finishedMessage.setFingerprint(plaintextMessage.getFingerprint()); - Log.d(Config.LOGTAG, AxolotlService.getLogprefix(finishedMessage.getConversation().getAccount())+" Received Message with session fingerprint: "+plaintextMessage.getFingerprint()); - return finishedMessage; - } else { - return null; - } - } - - private class Invite { - Jid jid; - String password; - Invite(Jid jid, String password) { - this.jid = jid; - this.password = password; - } - - 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; - } - } - - private Invite extractInvite(Element message) { - Element x = message.findChild("x", "http://jabber.org/protocol/muc#user"); - 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); - } - } else { - x = message.findChild("x","jabber:x:conference"); - if (x != null) { - return new Invite(x.getAttributeAsJid("jid"),x.getAttribute("password")); - } - } - return null; - } - - private static String extractStanzaId(Element packet, Jid by) { - for(Element child : packet.getChildren()) { - if (child.getName().equals("stanza-id") - && "urn:xmpp:sid:0".equals(child.getNamespace()) - && by.equals(child.getAttributeAsJid("by"))) { - return child.getAttribute("id"); - } - } - return null; - } - - private void parseEvent(final Element event, final Jid from, final Account account) { - Element items = event.findChild("items"); - String node = items == null ? null : items.getAttribute("node"); - if ("urn:xmpp:avatar:metadata".equals(node)) { - Avatar avatar = Avatar.parseMetadata(items); - if (avatar != null) { - avatar.owner = from.toBareJid(); - if (mXmppConnectionService.getFileBackend().isAvatarCached(avatar)) { - if (account.getJid().toBareJid().equals(from)) { - if (account.setAvatar(avatar.getFilename())) { - mXmppConnectionService.databaseBackend.updateAccount(account); - } - mXmppConnectionService.getAvatarService().clear(account); - mXmppConnectionService.updateConversationUi(); - mXmppConnectionService.updateAccountUi(); - } else { - Contact contact = account.getRoster().getContact(from); - contact.setAvatar(avatar); - mXmppConnectionService.getAvatarService().clear(contact); - mXmppConnectionService.updateConversationUi(); - mXmppConnectionService.updateRosterUi(); - } - } else { - mXmppConnectionService.fetchAvatar(account, avatar); - } - } - } 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"); - if (nick != null && nick.getContent() != null) { - Contact contact = account.getRoster().getContact(from); - contact.setPresenceName(nick.getContent()); - mXmppConnectionService.getAvatarService().clear(account); - mXmppConnectionService.updateConversationUi(); - mXmppConnectionService.updateAccountUi(); - } - } else if (AxolotlService.PEP_DEVICE_LIST.equals(node)) { - Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account)+"Received PEP device list update from "+ from + ", processing..."); - Element item = items.findChild("item"); - Set<Integer> deviceIds = mXmppConnectionService.getIqParser().deviceIds(item); - AxolotlService axolotlService = account.getAxolotlService(); - axolotlService.registerDevices(from, deviceIds); - mXmppConnectionService.updateAccountUi(); - } - } - - private boolean handleErrorMessage(Account account, MessagePacket packet) { - if (packet.getType() == MessagePacket.TYPE_ERROR) { - Jid from = packet.getFrom(); - if (from != null) { - 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); - } - Message message = mXmppConnectionService.markMessage(account, - from.toBareJid(), - packet.getId(), - Message.STATUS_SEND_FAILED); - if (message != null && message.getEncryption() == Message.ENCRYPTION_OTR) { - message.getConversation().endOtrIfNeeded(); - } - } - return true; - } - return false; - } - - @Override - public void onMessagePacketReceived(Account account, MessagePacket original) { - if (handleErrorMessage(account, original)) { - return; - } - final MessagePacket packet; - Long timestamp = null; - final boolean isForwarded; - boolean isCarbon = false; - String serverMsgId = null; - 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.incrementMessageCount(); - } else if (query != null) { - Log.d(Config.LOGTAG,account.getJid().toBareJid()+": received mam result from invalid sender"); - return; - } else if (original.fromServer(account)) { - 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; - if (handleErrorMessage(account, packet)) { - return; - } - timestamp = f != null ? f.second : null; - isCarbon = f != null; - isForwarded = isCarbon; - } else { - packet = original; - isForwarded = false; - } - - if (timestamp == null) { - timestamp = AbstractParser.parseTimestamp(packet); - } - final String body = packet.getBody(); - final Element mucUserElement = packet.findChild("x", "http://jabber.org/protocol/muc#user"); - final String pgpEncrypted = packet.findChildContent("x", "jabber:x:encrypted"); - final Element replaceElement = packet.findChild("replace", "urn:xmpp:message-correct:0"); - final Element oob = packet.findChild("x", "jabber:x:oob"); - final boolean isOob = oob!= null && body != null && body.equals(oob.findChildContent("url")); - final String replacementId = replaceElement == null ? null : replaceElement.getAttribute("id"); - final Element axolotlEncrypted = packet.findChild(XmppAxolotlMessage.CONTAINERTAG, AxolotlService.PEP_PREFIX); - int status; - final Jid counterpart; - final Jid to = packet.getTo(); - final Jid from = packet.getFrom(); - final String remoteMsgId = packet.getId(); - boolean notify = false; - - if (from == null) { - Log.d(Config.LOGTAG,"no from in: "+packet.toString()); - return; - } - - boolean isTypeGroupChat = packet.getType() == MessagePacket.TYPE_GROUPCHAT; - boolean isProperlyAddressed = (to != null ) && (!to.isBareJid() || account.countPresences() == 0); - boolean isMucStatusMessage = from.isBareJid() && mucUserElement != null && mucUserElement.hasChild("status"); - if (packet.fromAccount(account)) { - status = Message.STATUS_SEND; - counterpart = to != null ? to : account.getJid(); - } else { - status = Message.STATUS_RECEIVED; - counterpart = from; - } - - Invite invite = extractInvite(packet); - if (invite != null && invite.execute(account)) { - return; - } - - if (!isTypeGroupChat - && query == null - && extractChatState(mXmppConnectionService.find(account, counterpart.toBareJid()), packet)) { - mXmppConnectionService.updateConversationUi(); - } - - if ((body != null || pgpEncrypted != null || axolotlEncrypted != null) && !isMucStatusMessage) { - Conversation conversation = mXmppConnectionService.findOrCreateConversation(account, counterpart.toBareJid(), isTypeGroupChat, query); - final boolean conversationMultiMode = conversation.getMode() == Conversation.MODE_MULTI; - if (isTypeGroupChat) { - if (counterpart.getResourcepart().equals(conversation.getMucOptions().getActualNick())) { - status = Message.STATUS_SEND_RECEIVED; - isCarbon = true; //not really carbon but received from another resource - if (mXmppConnectionService.markMessage(conversation, remoteMsgId, status)) { - return; - } else if (remoteMsgId == null || Config.IGNORE_ID_REWRITE_IN_MUC) { - Message message = conversation.findSentMessageWithBody(packet.getBody()); - if (message != null) { - mXmppConnectionService.markMessage(message, status); - return; - } - } - } else { - status = Message.STATUS_RECEIVED; - } - } - final Message message; - if (body != null && body.startsWith("?OTR") && Config.supportOtr()) { - if (!isForwarded && !isTypeGroupChat && isProperlyAddressed && !conversationMultiMode) { - message = parseOtrChat(body, from, remoteMsgId, conversation); - if (message == null) { - return; - } - } else { - Log.d(Config.LOGTAG,account.getJid().toBareJid()+": ignoring OTR message from "+from+" isForwarded="+Boolean.toString(isForwarded)+", isProperlyAddressed="+Boolean.valueOf(isProperlyAddressed)); - message = new Message(conversation, body, Message.ENCRYPTION_NONE, status); - } - } else if (pgpEncrypted != null && Config.supportOpenPgp()) { - message = new Message(conversation, pgpEncrypted, Message.ENCRYPTION_PGP, status); - } else if (axolotlEncrypted != null && Config.supportOmemo()) { - Jid origin; - if (conversationMultiMode) { - final Jid fallback = conversation.getMucOptions().getTrueCounterpart(counterpart); - origin = getTrueCounterpart(query != null ? mucUserElement : null, fallback); - if (origin == null) { - Log.d(Config.LOGTAG,"axolotl message in non anonymous conference received"); - return; - } - } else { - origin = from; - } - message = parseAxolotlChat(axolotlEncrypted, origin, conversation, status); - if (message == null) { - return; - } - if (conversationMultiMode) { - message.setTrueCounterpart(origin); - } - } else { - message = new Message(conversation, body, Message.ENCRYPTION_NONE, status); - } - - if (serverMsgId == null) { - serverMsgId = extractStanzaId(packet, isTypeGroupChat ? conversation.getJid().toBareJid() : account.getServer()); - } - - message.setCounterpart(counterpart); - message.setRemoteMsgId(remoteMsgId); - message.setServerMsgId(serverMsgId); - message.setCarbon(isCarbon); - message.setTime(timestamp); - message.setOob(isOob); - message.markable = packet.hasChild("markable", "urn:xmpp:chat-markers:0"); - if (conversationMultiMode) { - final Jid fallback = conversation.getMucOptions().getTrueCounterpart(counterpart); - Jid trueCounterpart; - if (message.getEncryption() == Message.ENCRYPTION_AXOLOTL) { - trueCounterpart = message.getTrueCounterpart(); - } else if (Config.PARSE_REAL_JID_FROM_MUC_MAM) { - trueCounterpart = getTrueCounterpart(query != null ? mucUserElement : null, fallback); - } else { - trueCounterpart = fallback; - } - if (trueCounterpart != null && trueCounterpart.toBareJid().equals(account.getJid().toBareJid())) { - status = isTypeGroupChat ? Message.STATUS_SEND_RECEIVED : Message.STATUS_SEND; - } - message.setStatus(status); - message.setTrueCounterpart(trueCounterpart); - if (!isTypeGroupChat) { - message.setType(Message.TYPE_PRIVATE); - } - } else { - updateLastseen(account, from); - } - - if (replacementId != null && mXmppConnectionService.allowMessageCorrection()) { - Message replacedMessage = conversation.findMessageWithRemoteIdAndCounterpart(replacementId, - counterpart, - message.getStatus() == Message.STATUS_RECEIVED, - message.isCarbon()); - if (replacedMessage != null) { - final boolean fingerprintsMatch = replacedMessage.getFingerprint() == null - || replacedMessage.getFingerprint().equals(message.getFingerprint()); - final boolean trueCountersMatch = replacedMessage.getTrueCounterpart() != null - && replacedMessage.getTrueCounterpart().equals(message.getTrueCounterpart()); - if (fingerprintsMatch && (trueCountersMatch || !conversationMultiMode)) { - Log.d(Config.LOGTAG, "replaced message '" + replacedMessage.getBody() + "' with '" + message.getBody() + "'"); - synchronized (replacedMessage) { - final String uuid = replacedMessage.getUuid(); - replacedMessage.setUuid(UUID.randomUUID().toString()); - replacedMessage.setBody(message.getBody()); - replacedMessage.setEdited(replacedMessage.getRemoteMsgId()); - replacedMessage.setRemoteMsgId(remoteMsgId); - replacedMessage.setEncryption(message.getEncryption()); - if (replacedMessage.getStatus() == Message.STATUS_RECEIVED) { - replacedMessage.markUnread(); - } - mXmppConnectionService.updateMessage(replacedMessage, uuid); - mXmppConnectionService.getNotificationService().updateNotification(false); - if (mXmppConnectionService.confirmMessages() && remoteMsgId != null && !isForwarded && !isTypeGroupChat) { - sendMessageReceipts(account, packet); - } - if (replacedMessage.getEncryption() == Message.ENCRYPTION_PGP) { - conversation.getAccount().getPgpDecryptionService().discard(replacedMessage); - conversation.getAccount().getPgpDecryptionService().decrypt(replacedMessage, false); - } - } - return; - } else { - Log.d(Config.LOGTAG,account.getJid().toBareJid()+": received message correction but verification didn't check out"); - } - } - } - - boolean checkForDuplicates = query != null - || (isTypeGroupChat && packet.hasChild("delay","urn:xmpp:delay")) - || message.getType() == Message.TYPE_PRIVATE; - if (checkForDuplicates && conversation.hasDuplicateMessage(message)) { - Log.d(Config.LOGTAG,"skipping duplicate message from "+message.getCounterpart().toString()+" "+message.getBody()); - return; - } - - if (query != null && query.getPagingOrder() == MessageArchiveService.PagingOrder.REVERSE) { - conversation.prepend(message); - } else { - conversation.add(message); - } - - if (query == null || query.getWith() == null) { //either no mam or catchup - if (status == Message.STATUS_SEND || status == Message.STATUS_SEND_RECEIVED) { - mXmppConnectionService.markRead(conversation); - if (query == null) { - activateGracePeriod(account); - } - } else { - message.markUnread(); - notify = true; - } - } - - if (message.getEncryption() == Message.ENCRYPTION_PGP) { - notify = conversation.getAccount().getPgpDecryptionService().decrypt(message, notify); - } - - if (query == null) { - mXmppConnectionService.updateConversationUi(); - } - - if (mXmppConnectionService.confirmMessages() && remoteMsgId != null && !isForwarded && !isTypeGroupChat) { - sendMessageReceipts(account, packet); - } - - if (message.getStatus() == Message.STATUS_RECEIVED - && conversation.getOtrSession() != null - && !conversation.getOtrSession().getSessionID().getUserID() - .equals(message.getCounterpart().getResourcepart())) { - conversation.endOtrIfNeeded(); - } - - if (message.getEncryption() == Message.ENCRYPTION_NONE || mXmppConnectionService.saveEncryptedMessages()) { - mXmppConnectionService.databaseBackend.createMessage(message); - } - final HttpConnectionManager manager = this.mXmppConnectionService.getHttpConnectionManager(); - if (message.trusted() && message.treatAsDownloadable() != Message.Decision.NEVER && manager.getAutoAcceptFileSize() > 0) { - manager.createNewDownloadConnection(message); - } else if (notify) { - if (query == null) { - mXmppConnectionService.getNotificationService().push(message); - } else if (query.getWith() == null) { // mam catchup - mXmppConnectionService.getNotificationService().pushFromBacklog(message); - } - } - } else if (!packet.hasChild("body")){ //no body - Conversation conversation = mXmppConnectionService.find(account, from.toBareJid()); - if (isTypeGroupChat) { - if (packet.hasChild("subject")) { - if (conversation != null && conversation.getMode() == Conversation.MODE_MULTI) { - conversation.setHasMessagesLeftOnServer(conversation.countMessages() > 0); - String subject = packet.findChildContent("subject"); - conversation.getMucOptions().setSubject(subject); - final Bookmark bookmark = conversation.getBookmark(); - if (bookmark != null && bookmark.getBookmarkName() == null) { - if (bookmark.setBookmarkName(subject)) { - mXmppConnectionService.pushBookmarks(account); - } - } - mXmppConnectionService.updateConversationUi(); - return; - } - } - } - if (conversation != null && mucUserElement != null && from.isBareJid()) { - if (mucUserElement.hasChild("status")) { - for (Element child : mucUserElement.getChildren()) { - if (child.getName().equals("status") - && MucOptions.STATUS_CODE_ROOM_CONFIG_CHANGED.equals(child.getAttribute("code"))) { - mXmppConnectionService.fetchConferenceConfiguration(conversation); - } - } - } else if (mucUserElement.hasChild("item")) { - for(Element child : mucUserElement.getChildren()) { - if ("item".equals(child.getName())) { - MucOptions.User user = AbstractParser.parseItem(conversation,child); - Log.d(Config.LOGTAG,account.getJid()+": changing affiliation for " - +user.getRealJid()+" to "+user.getAffiliation()+" in " - +conversation.getJid().toBareJid()); - if (!user.realJidMatchesAccount()) { - conversation.getMucOptions().addUser(user); - mXmppConnectionService.getAvatarService().clear(conversation); - mXmppConnectionService.updateMucRosterUi(); - mXmppConnectionService.updateConversationUi(); - } - } - } - } - } - } - - - - 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()); - if (conversation != null) { - mXmppConnectionService.markRead(conversation); - } - } else { - 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(); - } - } - } - - Element event = packet.findChild("event", "http://jabber.org/protocol/pubsub#event"); - if (event != null) { - parseEvent(event, from, account); - } - - String nick = packet.findChildContent("nick", "http://jabber.org/protocol/nick"); - if (nick != null) { - Contact contact = account.getRoster().getContact(from); - contact.setPresenceName(nick); - } - } - - private static Jid getTrueCounterpart(Element mucUserElement, Jid fallback) { - final Element item = mucUserElement == null ? null : mucUserElement.findChild("item"); - Jid result = item == null ? null : item.getAttributeAsJid("jid"); - return result != null ? result : fallback; - } - - private void sendMessageReceipts(Account account, MessagePacket packet) { - ArrayList<String> receiptsNamespaces = new ArrayList<>(); - if (packet.hasChild("markable", "urn:xmpp:chat-markers:0")) { - receiptsNamespaces.add("urn:xmpp:chat-markers:0"); - } - if (packet.hasChild("request", "urn:xmpp:receipts")) { - receiptsNamespaces.add("urn:xmpp:receipts"); - } - if (receiptsNamespaces.size() > 0) { - MessagePacket receipt = mXmppConnectionService.getMessageGenerator().received(account, - packet, - receiptsNamespaces, - packet.getType()); - mXmppConnectionService.sendMessagePacket(account, receipt); - } - } - - private static SimpleDateFormat TIME_FORMAT = new SimpleDateFormat("HH:mm:ss"); - - private void activateGracePeriod(Account account) { - long duration = mXmppConnectionService.getPreferences().getLong("race_period_length", 144) * 1000; - Log.d(Config.LOGTAG,account.getJid().toBareJid()+": activating grace period till "+TIME_FORMAT.format(new Date(System.currentTimeMillis() + duration))); - account.activateGracePeriod(duration); - } -} diff --git a/src/main/java/eu/siacs/conversations/parser/PresenceParser.java b/src/main/java/eu/siacs/conversations/parser/PresenceParser.java deleted file mode 100644 index 30732fd2d..000000000 --- a/src/main/java/eu/siacs/conversations/parser/PresenceParser.java +++ /dev/null @@ -1,274 +0,0 @@ -package eu.siacs.conversations.parser; - -import android.util.Log; - -import java.text.ParseException; -import java.util.ArrayList; -import java.util.List; - -import eu.siacs.conversations.Config; -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.Message; -import eu.siacs.conversations.entities.MucOptions; -import eu.siacs.conversations.entities.Presence; -import eu.siacs.conversations.generator.IqGenerator; -import eu.siacs.conversations.generator.PresenceGenerator; -import eu.siacs.conversations.services.XmppConnectionService; -import eu.siacs.conversations.xml.Element; -import eu.siacs.conversations.xmpp.OnPresencePacketReceived; -import eu.siacs.conversations.xmpp.jid.Jid; -import eu.siacs.conversations.xmpp.pep.Avatar; -import eu.siacs.conversations.xmpp.stanzas.PresencePacket; - -public class PresenceParser extends AbstractParser implements - OnPresencePacketReceived { - - public PresenceParser(XmppConnectionService service) { - super(service); - } - - public void parseConferencePresence(PresencePacket packet, Account account) { - final Conversation conversation = packet.getFrom() == null ? null : mXmppConnectionService.find(account, packet.getFrom().toBareJid()); - if (conversation != null) { - final MucOptions mucOptions = conversation.getMucOptions(); - boolean before = mucOptions.online(); - int count = mucOptions.getUserCount(); - final List<MucOptions.User> tileUserBefore = mucOptions.getUsers(5); - processConferencePresence(packet, mucOptions); - final List<MucOptions.User> 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, MucOptions mucOptions) { - final Jid from = packet.getFrom(); - if (!from.isBareJid()) { - final String type = packet.getAttribute("type"); - final Element x = packet.findChild("x", "http://jabber.org/protocol/muc#user"); - Avatar avatar = Avatar.parsePresence(packet.findChild("x", "vcard-temp:x:update")); - final List<String> 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 = new MucOptions.User(mucOptions, from); - user.setAffiliation(item.getAttribute("affiliation")); - user.setRole(item.getAttribute("role")); - user.setRealJid(item.getAttributeAsJid("jid")); - if (codes.contains(MucOptions.STATUS_CODE_SELF_PRESENCE) || packet.getFrom().equals(mucOptions.getConversation().getJid())) { - mucOptions.setOnline(); - mucOptions.setSelf(user); - if (mucOptions.mNickChangingInProgress) { - if (mucOptions.onRenameListener != null) { - mucOptions.onRenameListener.onSuccess(); - } - mucOptions.mNickChangingInProgress = false; - } - } else { - mucOptions.addUser(user); - } - if (codes.contains(MucOptions.STATUS_CODE_ROOM_CREATED) && mucOptions.autoPushConfiguration()) { - Log.d(Config.LOGTAG,mucOptions.getAccount().getJid().toBareJid() - +": room '" - +mucOptions.getConversation().getJid().toBareJid() - +"' created. pushing default configuration"); - mXmppConnectionService.pushConferenceConfiguration(mucOptions.getConversation(), - IqGenerator.defaultRoomConfiguration(), - 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); - } - } else { - mXmppConnectionService.fetchAvatar(mucOptions.getAccount(), avatar); - } - } - } - } - } else if (type.equals("unavailable")) { - if (codes.contains(MucOptions.STATUS_CODE_SELF_PRESENCE) || - packet.getFrom().equals(mucOptions.getConversation().getJid())) { - if (codes.contains(MucOptions.STATUS_CODE_CHANGED_NICK)) { - mucOptions.mNickChangingInProgress = true; - } 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 { - mucOptions.setError(MucOptions.Error.UNKNOWN); - Log.d(Config.LOGTAG, "unknown error in conference: " + packet); - } - } else if (!from.isBareJid()){ - MucOptions.User user = mucOptions.deleteUser(from); - if (user != null) { - mXmppConnectionService.getAvatarService().clear(user); - } - } - } else if (type.equals("error")) { - Element error = packet.findChild("error"); - if (error != null && error.hasChild("conflict")) { - if (mucOptions.online()) { - if (mucOptions.onRenameListener != null) { - mucOptions.onRenameListener.onFailure(); - } - } else { - mucOptions.setError(MucOptions.Error.NICK_IN_USE); - } - } else if (error != null && error.hasChild("not-authorized")) { - mucOptions.setError(MucOptions.Error.PASSWORD_REQUIRED); - } else if (error != null && error.hasChild("forbidden")) { - mucOptions.setError(MucOptions.Error.BANNED); - } else if (error != null && error.hasChild("registration-required")) { - mucOptions.setError(MucOptions.Error.MEMBERS_ONLY); - } - } - } - } - - private static List<String> getStatusCodes(Element x) { - List<String> 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; - } - - public 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.getResourcepart(); - contact.setPresenceName(packet.findChildContent("nick", "http://jabber.org/protocol/nick")); - Avatar avatar = Avatar.parsePresence(packet.findChild("x", "vcard-temp:x:update")); - if (avatar != null && !contact.isSelf()) { - avatar.owner = from.toBareJid(); - if (mXmppConnectionService.getFileBackend().isAvatarCached(avatar)) { - if (contact.setAvatar(avatar)) { - mXmppConnectionService.getAvatarService().clear(contact); - mXmppConnectionService.updateConversationUi(); - mXmppConnectionService.updateRosterUi(); - } - } else { - mXmppConnectionService.fetchAvatar(account, avatar); - } - } - 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 Element idle = packet.findChild("idle","urn:xmpp:idle:1"); - if (idle != null) { - contact.flagInactive(); - String since = idle.getAttribute("since"); - try { - contact.setLastseen(AbstractParser.parseTimestamp(since)); - } catch (NullPointerException | ParseException e) { - contact.setLastseen(System.currentTimeMillis()); - } - } else { - contact.flagActive(); - contact.setLastseen(AbstractParser.parseTimestamp(packet)); - } - - PgpEngine pgp = mXmppConnectionService.getPgpEngine(); - Element x = packet.findChild("x", "jabber:x:signed"); - if (pgp != null && x != null) { - Element status = packet.findChild("status"); - String msg = status != null ? status.getContent() : ""; - contact.setPgpKeyId(pgp.fetchKeyId(account, msg, x.getContent())); - } - boolean online = sizeBefore < contact.getPresences().size(); - mXmppConnectionService.onContactStatusChanged.onContactStatusChanged(contact, online); - } else if (type.equals("unavailable")) { - if (from.isBareJid()) { - contact.clearPresences(); - } else { - contact.removePresence(from.getResourcepart()); - } - mXmppConnectionService.onContactStatusChanged.onContactStatusChanged(contact, false); - } else if (type.equals("subscribe")) { - 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().toBareJid(), 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", "http://jabber.org/protocol/muc#user")) { - this.parseConferencePresence(packet, account); - } else if (packet.hasChild("x", "http://jabber.org/protocol/muc")) { - this.parseConferencePresence(packet, account); - } else { - this.parseContactPresence(packet, account); - } - } - -} |