예제 #1
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);
    }
  }