예제 #1
0
 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();
   }
 }
예제 #2
0
  @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.incrementTotalCount();
    } 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.getTimestamp(packet, System.currentTimeMillis());
    }
    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 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();

    if (from == null || to == null) {
      Log.d(Config.LOGTAG, "no to or from in: " + packet.toString());
      return;
    }

    boolean isTypeGroupChat = packet.getType() == MessagePacket.TYPE_GROUPCHAT;
    boolean isProperlyAddressed = !to.isBareJid() || account.countPresences() == 1;
    boolean isMucStatusMessage =
        from.isBareJid() && mucUserElement != null && mucUserElement.hasChild("status");
    if (packet.fromAccount(account)) {
      status = Message.STATUS_SEND;
      counterpart = to;
    } else {
      status = Message.STATUS_RECEIVED;
      counterpart = from;
    }

    Invite invite = extractInvite(packet);
    if (invite != null && invite.execute(account)) {
      return;
    }

    if (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);
      if (isTypeGroupChat) {
        if (counterpart.getResourcepart().equals(conversation.getMucOptions().getActualNick())) {
          status = Message.STATUS_SEND_RECEIVED;
          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;
        }
      }
      Message message;
      if (body != null && body.startsWith("?OTR")) {
        if (!isForwarded && !isTypeGroupChat && isProperlyAddressed) {
          message = parseOtrChat(body, from, remoteMsgId, conversation);
          if (message == null) {
            return;
          }
        } else {
          message = new Message(conversation, body, Message.ENCRYPTION_NONE, status);
        }
      } else if (pgpEncrypted != null) {
        message = parsePGPChat(conversation, pgpEncrypted, status);
      } else if (axolotlEncrypted != null) {
        message = parseAxolotlChat(axolotlEncrypted, from, remoteMsgId, conversation, status);
        if (message == null) {
          return;
        }
      } 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.markable = packet.hasChild("markable", "urn:xmpp:chat-markers:0");
      if (conversation.getMode() == Conversation.MODE_MULTI) {
        Jid trueCounterpart =
            conversation.getMucOptions().getTrueCounterpart(counterpart.getResourcepart());
        message.setTrueCounterpart(trueCounterpart);
        if (trueCounterpart != null) {
          updateLastseen(packet, account, trueCounterpart, false);
        }
        if (!isTypeGroupChat) {
          message.setType(Message.TYPE_PRIVATE);
        }
      }
      updateLastseen(packet, account, true);
      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;
      }

      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) {
            account.activateGracePeriod();
          }
        } else {
          message.markUnread();
        }
      }

      if (query != null) {
        query.incrementMessageCount();
      } else {
        mXmppConnectionService.updateConversationUi();
      }

      if (mXmppConnectionService.confirmMessages()
          && remoteMsgId != null
          && !isForwarded
          && !isTypeGroupChat) {
        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);
        }
      }

      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 (!message.isRead()) {
        if (query == null) {
          mXmppConnectionService.getNotificationService().push(message);
        } else if (query.getWith() == null) { // mam catchup
          mXmppConnectionService.getNotificationService().pushFromBacklog(message);
        }
      }
    } else { // no body
      if (isTypeGroupChat) {
        Conversation conversation = mXmppConnectionService.find(account, from.toBareJid());
        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 && isMucStatusMessage) {
          for (Element child : mucUserElement.getChildren()) {
            if (child.getName().equals("status")
                && MucOptions.STATUS_CODE_ROOM_CONFIG_CHANGED.equals(child.getAttribute("code"))) {
              mXmppConnectionService.fetchConferenceConfiguration(conversation);
            }
          }
        }
      }
    }

    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 {
        updateLastseen(packet, account, true);
        final Message displayedMessage =
            mXmppConnectionService.markMessage(
                account,
                from.toBareJid(),
                displayed.getAttribute("id"),
                Message.STATUS_SEND_DISPLAYED);
        Message message = displayedMessage == null ? null : displayedMessage.prev();
        while (message != null
            && message.getStatus() == Message.STATUS_SEND_RECEIVED
            && message.getTimeSent() < displayedMessage.getTimeSent()) {
          mXmppConnectionService.markMessage(message, Message.STATUS_SEND_DISPLAYED);
          message = message.prev();
        }
      }
    }

    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);
    }
  }
  public void parseContactPresence(final PresencePacket packet, final Account account) {
    final PresenceGenerator mPresenceGenerator = mXmppConnectionService.getPresenceGenerator();
    final Jid from = packet.getFrom();
    if (from == null) {
      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 Element show = packet.findChild("show");
      final Element caps = packet.findChild("c", "http://jabber.org/protocol/caps");
      final Presence presence = Presence.parse(show, caps);
      contact.updatePresence(resource, presence);
      if (presence.hasCaps() && Config.REQUEST_DISCO) {
        mXmppConnectionService.fetchCaps(account, from, presence);
      }

      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();
      updateLastseen(packet, account, false);
      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();
  }