Example #1
0
QVector<Character*>* GroupExpression::eval(Card* caster, const Event* e) const
{
    QVector<Character*>* group = caster->owner()->game()->charactersByPlayTime(caster->owner(), m_owner, m_type);

    if (!m_excludedTargets.isNull()) {
        QVector<Character*>* excluded = m_excludedTargets.data()->eval(caster, NULL, e);
        foreach (Character* c, *excluded)
            group->removeOne(c);
        delete excluded;
    }

    return group;
}
Example #2
0
  bool OMEMO::encryptMessage(const QString &ownJid, int account, QDomElement &xml, bool buildSessions, const uint32_t *toDeviceId) {
    std::shared_ptr<Signal> signal = getSignal(account);
    QString recipient = m_contactInfoAccessor->realJid(account, xml.attribute("to")).split("/").first();
    bool isGroup = xml.attribute("type") == "groupchat";
    if (!isEnabledForUser(account, recipient)) {
      return false;
    }

    if (buildSessions) {
      QMap<QString, QVector<uint32_t>> invalidSessions;
      QVector<uint32_t> invalidSessionsWithOwnDevices;
      if (isGroup) {
        forEachMucParticipant(account, ownJid, recipient, [&](const QString &userJid) {
          QVector<uint32_t> sessions = signal->invalidSessions(userJid);
          if (!sessions.isEmpty()) {
            invalidSessions.insert(userJid, sessions);
          }
          return true;
        });
      }
      else {
        QVector<uint32_t> sessions = signal->invalidSessions(recipient);
        if (!sessions.isEmpty()) {
          invalidSessions.insert(recipient, sessions);
        }
      }
      invalidSessionsWithOwnDevices = signal->invalidSessions(ownJid);
      invalidSessionsWithOwnDevices.removeOne(signal->getDeviceId());
      if (!invalidSessions.isEmpty() || !invalidSessionsWithOwnDevices.isEmpty()) {
        buildSessionsFromBundle(invalidSessions, invalidSessionsWithOwnDevices, ownJid, account, xml);
        xml = QDomElement();
        return true;
      }
    }

    signal->processUndecidedDevices(recipient, false);
    signal->processUndecidedDevices(ownJid, true);

    QDomElement encrypted = xml.ownerDocument().createElementNS(OMEMO_XMLNS, "encrypted");
    QDomElement header = xml.ownerDocument().createElement("header");
    header.setAttribute("sid", signal->getDeviceId());
    encrypted.appendChild(header);
    xml.appendChild(encrypted);

    QByteArray iv = Crypto::randomBytes(OMEMO_AES_GCM_IV_LENGTH);

    QDomElement ivElement = xml.ownerDocument().createElement("iv");
    ivElement.appendChild(xml.ownerDocument().createTextNode(iv.toBase64()));
    header.appendChild(ivElement);

    QByteArray key = Crypto::randomBytes(OMEMO_AES_128_KEY_LENGTH);
    QDomElement body = xml.firstChildElement("body");
    QPair<QByteArray, QByteArray> encryptedBody;
    if (!body.isNull()) {
      QString plainText = body.firstChild().nodeValue();
      encryptedBody = Crypto::aes_gcm(Crypto::Encode, iv, key, plainText.toUtf8());
      key += encryptedBody.second;
    }
    QList<EncryptedKey> encryptedKeys;
    if (isGroup) {
      forEachMucParticipant(account, ownJid, recipient, [&](const QString &userJid) {
        encryptedKeys.append(signal->encryptKey(ownJid, userJid, key));
        return true;
      });
    }
    else {
      encryptedKeys = signal->encryptKey(ownJid, recipient, key);
    }

    if (encryptedKeys.isEmpty()) {
      m_accountController->appendSysMsg(account, xml.attribute("to"), "[OMEMO] Unable to build any sessions, the message was not sent");
      xml = QDomElement();
    }
    else {
      foreach (EncryptedKey encKey, encryptedKeys) {
        if (toDeviceId != nullptr && *toDeviceId != encKey.deviceId) {
          continue;
        }
        QDomElement keyElement = xml.ownerDocument().createElement("key");
        keyElement.setAttribute("rid", encKey.deviceId);
        if (encKey.isPreKey) {
          keyElement.setAttribute("prekey", 1);
        }
        setNodeText(keyElement, encKey.key);
        header.appendChild(keyElement);
      }

      if (!body.isNull()) {
        if (isGroup) {
          m_encryptedGroupMessages.insert(xml.attribute("id"), body.firstChild().nodeValue());
        }
        xml.removeChild(body);

        QDomElement payload = xml.ownerDocument().createElement("payload");
        payload.appendChild(xml.ownerDocument().createTextNode(encryptedBody.first.toBase64()));
        encrypted.appendChild(payload);

        QDomElement html = xml.firstChildElement("html");
        if (!html.isNull()) {
          xml.removeChild(html);
        }
      }

      xml.appendChild(xml.ownerDocument().createElementNS("urn:xmpp:hints", "store"));

      QDomElement encryption = xml.ownerDocument().createElementNS("urn:xmpp:eme:0", "encryption");
      encryption.setAttribute("namespace", OMEMO_XMLNS);
      encryption.setAttribute("name", "OMEMO");
      xml.appendChild(encryption);
    }

    return true;
  }