Compare commits
4 Commits
ce7a834b3e
...
3cad0e85ec
Author | SHA1 | Date |
---|---|---|
Xavier Del Campo Romero | 3cad0e85ec | |
Xavier Del Campo Romero | 4a4c6ba6b5 | |
Xavier Del Campo Romero | b17d4325c5 | |
Xavier Del Campo Romero | e157a7222c |
13
client.cpp
13
client.cpp
|
@ -3,7 +3,8 @@
|
|||
Client::Client(const QString &jid, QObject *const parent) :
|
||||
QXmppClient(parent),
|
||||
jid(jid),
|
||||
trust_db(jid),
|
||||
db(jid),
|
||||
trust_db(jid, db),
|
||||
trust(&trust_db),
|
||||
omemo_db(jid),
|
||||
omemo(&omemo_db)
|
||||
|
@ -18,3 +19,13 @@ QString Client::jidBare()
|
|||
{
|
||||
return configuration().jidBare();
|
||||
}
|
||||
|
||||
const JidDb &Client::database() const
|
||||
{
|
||||
return db;
|
||||
}
|
||||
|
||||
JidDb &Client::database()
|
||||
{
|
||||
return db;
|
||||
}
|
||||
|
|
4
client.h
4
client.h
|
@ -2,6 +2,7 @@
|
|||
#define CLIENT_H
|
||||
|
||||
#include "omemo_db.h"
|
||||
#include "jiddb.h"
|
||||
#include "trust_db.h"
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
|
@ -17,9 +18,12 @@ class Client : public QXmppClient
|
|||
public:
|
||||
Client(const QString &jid, QObject *parent = nullptr);
|
||||
QString jidBare();
|
||||
const JidDb &database() const;
|
||||
JidDb &database();
|
||||
|
||||
private:
|
||||
const QString jid;
|
||||
JidDb db;
|
||||
TrustDb trust_db;
|
||||
QXmppTrustManager trust;
|
||||
QXmppPubSubManager pubsub;
|
||||
|
|
|
@ -3,16 +3,16 @@
|
|||
#include <QListWidgetItem>
|
||||
#include <QScroller>
|
||||
|
||||
Contacts::Contacts(const QHash<QString, JidDb *> &databases,
|
||||
Contacts::Contacts(const QList<Client *> &clients,
|
||||
QWidget *const parent) :
|
||||
QDialog(parent)
|
||||
{
|
||||
ui.setupUi(this);
|
||||
QScroller::grabGesture(ui.contacts_list, QScroller::TouchGesture);
|
||||
|
||||
for (const auto db : databases)
|
||||
for (const auto &contact : db->roster())
|
||||
add(db->jid, contact);
|
||||
for (const auto c : clients)
|
||||
for (const auto &contact : c->database().roster())
|
||||
add(c->jidBare(), contact);
|
||||
|
||||
connect(ui.contacts_list, &QListWidget::itemActivated, this,
|
||||
[this]
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#define CONTACTS_H
|
||||
|
||||
#include "ui_contacts.h"
|
||||
#include "jiddb.h"
|
||||
#include "client.h"
|
||||
#include <QDialog>
|
||||
#include <QHash>
|
||||
#include <QString>
|
||||
|
@ -13,7 +13,7 @@ class Contacts : public QDialog
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Contacts(const QHash<QString, JidDb *> &databases,
|
||||
Contacts(const QList<Client *> &clients,
|
||||
QWidget *parent = nullptr);
|
||||
void add(const QString &own, const QString &other);
|
||||
|
||||
|
|
20
jiddb.cpp
20
jiddb.cpp
|
@ -84,7 +84,7 @@ int JidDb::ensureContactDb(const QString &jid) const
|
|||
return 0;
|
||||
}
|
||||
|
||||
QList<JidDb::Message> JidDb::getMessages(const QString &jid,
|
||||
QList<JidDb::Message> JidDb::messages(const QString &jid,
|
||||
const int tail) const
|
||||
{
|
||||
QSqlQuery q(db);
|
||||
|
@ -95,14 +95,14 @@ QList<JidDb::Message> JidDb::getMessages(const QString &jid,
|
|||
{
|
||||
if (!q.exec("select * from '" + jid + "' order by time;"))
|
||||
{
|
||||
std::cerr << "JidDb::getMessages: query exec failed";
|
||||
std::cerr << "JidDb::messages: query exec failed";
|
||||
return QList<Message>();
|
||||
}
|
||||
}
|
||||
else if (!q.exec("select * from '" + jid + "' order by time desc limit "
|
||||
+ QString::number(tail) + ";"))
|
||||
{
|
||||
std::cerr << "JidDb::getMessages: query exec failed" << std::endl;
|
||||
std::cerr << "JidDb::messages: query exec failed" << std::endl;
|
||||
return QList<Message>();
|
||||
}
|
||||
|
||||
|
@ -116,7 +116,7 @@ QList<JidDb::Message> JidDb::getMessages(const QString &jid,
|
|||
|
||||
if (!ok)
|
||||
{
|
||||
std::cerr << "JidDb::getMessages: invalid time" << std::endl;
|
||||
std::cerr << "JidDb::messages: invalid time" << std::endl;
|
||||
// Attempt to read other messages.
|
||||
continue;
|
||||
}
|
||||
|
@ -132,7 +132,7 @@ QList<JidDb::Message> JidDb::getMessages(const QString &jid,
|
|||
m.direction = Direction::Out;
|
||||
else
|
||||
{
|
||||
std::cerr << "JidDb::getMessages: invalid direction" << std::endl;
|
||||
std::cerr << "JidDb::messages: invalid direction" << std::endl;
|
||||
// Attempt to read other messages.
|
||||
continue;
|
||||
}
|
||||
|
@ -181,7 +181,7 @@ QStringList JidDb::tables() const
|
|||
if (!q.exec("select name from sqlite_schema where "
|
||||
"type = 'table' and name not like 'sqlite_%'"))
|
||||
{
|
||||
std::cerr << "JidDb::getConversations: query failed" << std::endl;
|
||||
std::cerr << "JidDb::conversations: query failed" << std::endl;
|
||||
return QStringList();
|
||||
}
|
||||
|
||||
|
@ -193,7 +193,7 @@ QStringList JidDb::tables() const
|
|||
return ret;
|
||||
}
|
||||
|
||||
QList<JidDb::Conversation> JidDb::getConversations() const
|
||||
QList<JidDb::Conversation> JidDb::conversations() const
|
||||
{
|
||||
const auto conversations = tables();
|
||||
QList<Conversation> ret;
|
||||
|
@ -201,11 +201,11 @@ QList<JidDb::Conversation> JidDb::getConversations() const
|
|||
for (const auto &jid : conversations)
|
||||
if (jid.contains('@'))
|
||||
{
|
||||
const auto messages = getMessages(jid, 1);
|
||||
const auto msgs = messages(jid, 1);
|
||||
|
||||
if (!messages.isEmpty())
|
||||
if (!msgs.isEmpty())
|
||||
{
|
||||
const auto &m = messages.first();
|
||||
const auto &m = msgs.first();
|
||||
|
||||
ret << Conversation(jid, m.body, m.dt);
|
||||
}
|
||||
|
|
32
jiddb.h
32
jiddb.h
|
@ -2,12 +2,15 @@
|
|||
#define JID_DB_H
|
||||
|
||||
#include "direction.h"
|
||||
#include <QByteArray>
|
||||
#include <QDateTime>
|
||||
#include <QList>
|
||||
#include <QObject>
|
||||
#include <QPair>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <QSqlDatabase>
|
||||
#include <QVariant>
|
||||
|
||||
class JidDb : public QObject
|
||||
{
|
||||
|
@ -30,17 +33,40 @@ public:
|
|||
QDateTime dt;
|
||||
};
|
||||
|
||||
struct Trust
|
||||
{
|
||||
QString security_policy;
|
||||
};
|
||||
|
||||
struct Keys
|
||||
{
|
||||
Keys(const QString &owner, const QString &trust_level,
|
||||
const QList<QByteArray> &keys) :
|
||||
owner(owner),
|
||||
trust_level(trust_level),
|
||||
keys(keys)
|
||||
{}
|
||||
QString owner, trust_level;
|
||||
QList<QByteArray> keys;
|
||||
};
|
||||
|
||||
JidDb(const QString &jid);
|
||||
QStringList roster() const;
|
||||
const QString jid;
|
||||
const QString &jid;
|
||||
|
||||
public Q_SLOTS:
|
||||
QList<Conversation> getConversations() const;
|
||||
QList<Message> getMessages(const QString &jid,
|
||||
QList<Conversation> conversations() const;
|
||||
QList<Message> messages(const QString &jid,
|
||||
int tail = -1) const;
|
||||
QString securityPolicy(const QString &encryption) const;
|
||||
QList<Keys> keys(const QString &encryption) const;
|
||||
int storeMessage(const Message &msg) const;
|
||||
int addToRoster(const QString &jid);
|
||||
int addToRoster(const QStringList &roster);
|
||||
int storeSecurityPolicy(const QString &encryption,
|
||||
const QString &policy) const;
|
||||
int storeKeys(const QString &encryption, const Keys &keys) const;
|
||||
void removeKeys(void) const;
|
||||
|
||||
Q_SIGNALS:
|
||||
void addedToRoster(QString jid);
|
||||
|
|
282
trust_db.cpp
282
trust_db.cpp
|
@ -1,4 +1,6 @@
|
|||
#include "trust_db.h"
|
||||
#include <QXmppTrustLevel.h>
|
||||
#include <QXmppTrustSecurityPolicy.h>
|
||||
#include <QXmppConfiguration.h>
|
||||
#include <QXmppFutureUtils_p.h>
|
||||
#include <QXmppPromise.h>
|
||||
|
@ -7,21 +9,50 @@
|
|||
#include <QtConcurrent>
|
||||
#include <iostream>
|
||||
|
||||
TrustDb::TrustDb(const QString &jid) :
|
||||
jid(jid)
|
||||
TrustDb::TrustDb(const QString &jid, const JidDb &db) :
|
||||
jid(jid),
|
||||
db(db)
|
||||
{
|
||||
}
|
||||
|
||||
static const struct
|
||||
{
|
||||
QXmpp::TrustLevel level;
|
||||
const char *str;
|
||||
} trustlevels[] =
|
||||
{
|
||||
{QXmpp::TrustLevel::Undecided, "Undecided"},
|
||||
{QXmpp::TrustLevel::AutomaticallyDistrusted, "AutomaticallyDistrusted"},
|
||||
{QXmpp::TrustLevel::ManuallyDistrusted, "ManuallyDistrusted"},
|
||||
{QXmpp::TrustLevel::AutomaticallyTrusted, "AutomaticallyTrusted"},
|
||||
{QXmpp::TrustLevel::ManuallyTrusted, "ManuallyTrusted"},
|
||||
{QXmpp::TrustLevel::Authenticated, "Authenticated"}
|
||||
};
|
||||
|
||||
static const struct
|
||||
{
|
||||
QXmpp::TrustSecurityPolicy policy;
|
||||
const char *str;
|
||||
} tsp_levels[] =
|
||||
{
|
||||
{QXmpp::NoSecurityPolicy, "NoSecurityPolicy"},
|
||||
{QXmpp::Toakafa, "Toakafa"}
|
||||
};
|
||||
|
||||
static QString toString(const QXmpp::TrustSecurityPolicy securityPolicy)
|
||||
{
|
||||
switch (securityPolicy)
|
||||
{
|
||||
case QXmpp::NoSecurityPolicy:
|
||||
return "NoSecurityPolicy";
|
||||
for (const auto &t : tsp_levels)
|
||||
if (t.policy == securityPolicy)
|
||||
return t.str;
|
||||
|
||||
case QXmpp::Toakafa:
|
||||
return "Toakafa";
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
static QString toString(const QXmpp::TrustLevel &trustLevel)
|
||||
{
|
||||
for (const auto &t : trustlevels)
|
||||
if (t.level == trustLevel)
|
||||
return t.str;
|
||||
|
||||
return "unknown";
|
||||
}
|
||||
|
@ -29,16 +60,24 @@ static QString toString(const QXmpp::TrustSecurityPolicy securityPolicy)
|
|||
static int toSecurityPolicy(const QString &s,
|
||||
QXmpp::TrustSecurityPolicy &securityPolicy)
|
||||
{
|
||||
if (s == "NoSecurityPolicy")
|
||||
{
|
||||
securityPolicy = QXmpp::NoSecurityPolicy;
|
||||
return 0;
|
||||
}
|
||||
else if (s == "Toakafa")
|
||||
{
|
||||
securityPolicy = QXmpp::Toakafa;
|
||||
return 0;
|
||||
}
|
||||
for (const auto &t : tsp_levels)
|
||||
if (t.str == s)
|
||||
{
|
||||
securityPolicy = t.policy;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int toTrustLevel(const QString &tstr, QXmpp::TrustLevel &trustLevel)
|
||||
{
|
||||
for (const auto &t : trustlevels)
|
||||
if (t.str == tstr)
|
||||
{
|
||||
trustLevel = t.level;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
@ -51,35 +90,18 @@ QString TrustDb::service() const
|
|||
QXmppTask<void> TrustDb::setSecurityPolicy(const QString &encryption,
|
||||
const QXmpp::TrustSecurityPolicy securityPolicy)
|
||||
{
|
||||
QKeychain::WritePasswordJob job(service());
|
||||
QEventLoop loop;
|
||||
|
||||
job.setKey("securityPolicy/" + encryption);
|
||||
job.setTextData(toString(securityPolicy));
|
||||
job.connect(&job, &QKeychain::Job::finished, &loop, &QEventLoop::quit);
|
||||
job.start();
|
||||
loop.exec();
|
||||
|
||||
if (job.error())
|
||||
std::cerr << "Failed to store security policy: "
|
||||
<< qPrintable(job.errorString()) << std::endl;
|
||||
if (db.storeSecurityPolicy(encryption, toString(securityPolicy)))
|
||||
std::cerr << "TrustDb::setSecurityPolicy: storeSecurityPolicy failed"
|
||||
<< std::endl;
|
||||
|
||||
return QXmpp::Private::makeReadyTask();
|
||||
}
|
||||
|
||||
QXmppTask<void> TrustDb::resetSecurityPolicy(const QString &encryption)
|
||||
{
|
||||
QKeychain::DeletePasswordJob job(service());
|
||||
QEventLoop loop;
|
||||
|
||||
job.setKey("securityPolicy/" + encryption);
|
||||
job.connect(&job, &QKeychain::Job::finished, &loop, &QEventLoop::quit);
|
||||
job.start();
|
||||
loop.exec();
|
||||
|
||||
if (job.error())
|
||||
std::cerr << "Failed to reset security policy: "
|
||||
<< qPrintable(job.errorString()) << std::endl;
|
||||
if (db.storeSecurityPolicy(encryption, QString()))
|
||||
std::cerr << "TrustDb::resetSecurityPolicy: storeSecurityPolicy failed"
|
||||
<< std::endl;
|
||||
|
||||
return QXmpp::Private::makeReadyTask();
|
||||
}
|
||||
|
@ -87,23 +109,11 @@ QXmppTask<void> TrustDb::resetSecurityPolicy(const QString &encryption)
|
|||
QXmppTask<QXmpp::TrustSecurityPolicy> TrustDb::securityPolicy(
|
||||
const QString &encryption)
|
||||
{
|
||||
QKeychain::ReadPasswordJob job(service());
|
||||
QEventLoop loop;
|
||||
const auto s = db.securityPolicy(encryption);
|
||||
QXmpp::TrustSecurityPolicy policy;
|
||||
|
||||
job.setKey("securityPolicy/" + encryption);
|
||||
job.connect(&job, &QKeychain::Job::finished, &loop, &QEventLoop::quit);
|
||||
job.start();
|
||||
loop.exec();
|
||||
|
||||
if (job.error())
|
||||
std::cerr << "Failed to read security policy: "
|
||||
<< qPrintable(job.errorString()) << std::endl;
|
||||
|
||||
QXmpp::TrustSecurityPolicy policy = QXmpp::Toakafa;
|
||||
const QString data = job.textData();
|
||||
|
||||
if (toSecurityPolicy(data, policy))
|
||||
std::cerr << "Invalid security policy " << qPrintable(data)
|
||||
if (toSecurityPolicy(s, policy))
|
||||
std::cerr << "TrustDb::securityPolicy: toSecurityPolicy failed"
|
||||
<< std::endl;
|
||||
|
||||
return QXmpp::Private::makeReadyTask(QXmpp::TrustSecurityPolicy(policy));
|
||||
|
@ -170,23 +180,60 @@ QXmppTask<void> TrustDb::addKeys(const QString &encryption,
|
|||
const QString &keyOwnerJid, const QList<QByteArray> &keyIds,
|
||||
const QXmpp::TrustLevel trustLevel)
|
||||
{
|
||||
const struct JidDb::Keys keys(keyOwnerJid, toString(trustLevel), keyIds);
|
||||
|
||||
if (db.storeKeys(encryption, keys))
|
||||
std::cerr << "TrustDb::addKeys: storeKeys failed" << std::endl;
|
||||
|
||||
return QXmpp::Private::makeReadyTask();
|
||||
}
|
||||
|
||||
QXmppTask<void> TrustDb::removeKeys(const QString &encryption,
|
||||
const QList<QByteArray> &keyIds)
|
||||
{
|
||||
auto keys = db.keys(encryption);
|
||||
|
||||
for (const auto &id : keyIds)
|
||||
for (auto &k : keys)
|
||||
{
|
||||
const auto i = k.keys.indexOf(id);
|
||||
|
||||
if (i != -1)
|
||||
{
|
||||
k.keys.removeAt(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto &k : keys)
|
||||
if (db.storeKeys(encryption, k))
|
||||
std::cerr << "TrustDb::removeKeys: storeKeys failed" << std::endl;
|
||||
|
||||
return QXmpp::Private::makeReadyTask();
|
||||
}
|
||||
|
||||
QXmppTask<void> TrustDb::removeKeys(const QString &encryption,
|
||||
const QString &keyOwnerJid)
|
||||
{
|
||||
auto keys = db.keys(encryption);
|
||||
|
||||
for (int i = 0; i < keys.count(); i++)
|
||||
if (keys[i].owner == keyOwnerJid)
|
||||
{
|
||||
keys.removeAt(i);
|
||||
break;
|
||||
}
|
||||
|
||||
for (const auto &k : keys)
|
||||
if (db.storeKeys(encryption, k))
|
||||
std::cerr << "TrustDb::removeKeys: storeKeys failed" << std::endl;
|
||||
|
||||
return QXmpp::Private::makeReadyTask();
|
||||
}
|
||||
|
||||
QXmppTask<void> TrustDb::removeKeys(const QString &encryption)
|
||||
{
|
||||
db.removeKeys();
|
||||
return QXmpp::Private::makeReadyTask();
|
||||
}
|
||||
|
||||
|
@ -194,8 +241,32 @@ QXmppTask<QHash<QXmpp::TrustLevel,
|
|||
QMultiHash<QString, QByteArray>>> TrustDb::keys(const QString &encryption,
|
||||
const QXmpp::TrustLevels trustLevels)
|
||||
{
|
||||
QHash<QXmpp::TrustLevel, QMultiHash<QString, QByteArray>> ret;
|
||||
const auto keys = db.keys(encryption);
|
||||
|
||||
for (const auto &k : keys)
|
||||
{
|
||||
QXmpp::TrustLevel level;
|
||||
|
||||
if (toTrustLevel(k.trust_level, level))
|
||||
{
|
||||
std::cerr << "TrustDb::keys: invalid trust level: "
|
||||
<< qPrintable(k.trust_level) << std::endl;
|
||||
continue;
|
||||
}
|
||||
else if (!trustLevels.testFlag(level))
|
||||
continue;
|
||||
|
||||
QMultiHash<QString, QByteArray> mh;
|
||||
|
||||
for (const auto &key : k.keys)
|
||||
mh.insert(k.owner, key);
|
||||
|
||||
ret.insert(level, mh);
|
||||
}
|
||||
|
||||
return QXmpp::Private::makeReadyTask(QHash<QXmpp::TrustLevel,
|
||||
QMultiHash<QString, QByteArray>>());
|
||||
QMultiHash<QString, QByteArray>>(ret));
|
||||
}
|
||||
|
||||
QXmppTask<QHash<QString,
|
||||
|
@ -203,14 +274,66 @@ QXmppTask<QHash<QString,
|
|||
const QList<QString> &keyOwnerJids,
|
||||
const QXmpp::TrustLevels trustLevels)
|
||||
{
|
||||
QHash<QString, QHash<QByteArray, QXmpp::TrustLevel>> ret;
|
||||
const auto keys = db.keys(encryption);
|
||||
|
||||
for (const auto &jid : keyOwnerJids)
|
||||
for (const auto &k : keys)
|
||||
{
|
||||
if (k.owner != jid)
|
||||
continue;
|
||||
|
||||
QXmpp::TrustLevel level;
|
||||
|
||||
if (toTrustLevel(k.trust_level, level))
|
||||
{
|
||||
std::cerr << "TrustDb::keys: invalid trust level: "
|
||||
<< qPrintable(k.trust_level) << std::endl;
|
||||
continue;
|
||||
}
|
||||
else if (!trustLevels.testFlag(level))
|
||||
continue;
|
||||
|
||||
QHash<QByteArray, QXmpp::TrustLevel> h;
|
||||
|
||||
for (const auto &key : k.keys)
|
||||
h.insert(key, level);
|
||||
|
||||
ret.insert(jid, h);
|
||||
break;
|
||||
}
|
||||
|
||||
return QXmpp::Private::makeReadyTask(QHash<QString,
|
||||
QHash<QByteArray, QXmpp::TrustLevel>>());
|
||||
QHash<QByteArray, QXmpp::TrustLevel>>(ret));
|
||||
}
|
||||
|
||||
QXmppTask<bool> TrustDb::hasKey(const QString &encryption,
|
||||
const QString &keyOwnerJid, QXmpp::TrustLevels trustLevels)
|
||||
{
|
||||
return QXmpp::Private::makeReadyTask(bool());
|
||||
bool ret = false;
|
||||
const auto keys = db.keys(encryption);
|
||||
|
||||
for (const auto &k : keys)
|
||||
{
|
||||
if (k.owner != keyOwnerJid)
|
||||
continue;
|
||||
|
||||
QXmpp::TrustLevel level;
|
||||
|
||||
if (toTrustLevel(k.trust_level, level))
|
||||
{
|
||||
std::cerr << "TrustDb::keys: invalid trust level: "
|
||||
<< qPrintable(k.trust_level) << std::endl;
|
||||
break;
|
||||
}
|
||||
else if (!trustLevels.testFlag(level))
|
||||
break;
|
||||
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
|
||||
return QXmpp::Private::makeReadyTask(bool(ret));
|
||||
}
|
||||
|
||||
QXmppTask<QHash<QString,
|
||||
|
@ -219,8 +342,33 @@ QXmppTask<QHash<QString,
|
|||
const QMultiHash<QString, QByteArray> &keyIds,
|
||||
const QXmpp::TrustLevel trustLevel)
|
||||
{
|
||||
QHash<QString, QMultiHash<QString, QByteArray>> ret;
|
||||
auto keys = db.keys(encryption);
|
||||
const auto str = toString(trustLevel);
|
||||
|
||||
for (const auto &owner : keyIds.keys())
|
||||
for (auto &k : keys)
|
||||
{
|
||||
if (k.owner != owner)
|
||||
continue;
|
||||
|
||||
k.trust_level = str;
|
||||
QMultiHash<QString, QByteArray> mh;
|
||||
|
||||
for (const auto &id : k.keys)
|
||||
mh.insert(owner, id);
|
||||
|
||||
ret.insert(owner, mh);
|
||||
break;
|
||||
}
|
||||
|
||||
for (const auto &key : keys)
|
||||
if (db.storeKeys(encryption, key))
|
||||
std::cerr << "TrustDb::setTrustLevel: storeKeys failed"
|
||||
<< std::endl;
|
||||
|
||||
return QXmpp::Private::makeReadyTask(QHash<QString,
|
||||
QMultiHash<QString, QByteArray>>());
|
||||
QMultiHash<QString, QByteArray>>(ret));
|
||||
}
|
||||
|
||||
QXmppTask<QHash<QString,
|
||||
|
@ -244,3 +392,13 @@ QXmppTask<void> TrustDb::resetAll(const QString &encryption)
|
|||
{
|
||||
return QXmpp::Private::makeReadyTask();
|
||||
}
|
||||
|
||||
namespace QXmpp
|
||||
{
|
||||
|
||||
uint qHash(const TrustLevel &key, uint seed)
|
||||
{
|
||||
return qHash(key, seed);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#ifndef TRUST_DB_H
|
||||
#define TRUST_DB_H
|
||||
|
||||
#include "jiddb.h"
|
||||
#include <QXmppClient.h>
|
||||
#include <QXmppTask.h>
|
||||
#include <QXmppTrustLevel.h>
|
||||
|
@ -14,7 +15,7 @@
|
|||
class TrustDb : virtual public QXmppTrustStorage
|
||||
{
|
||||
public:
|
||||
TrustDb(const QString &jid);
|
||||
TrustDb(const QString &jid, const JidDb &db);
|
||||
|
||||
QXmppTask<void> setSecurityPolicy(const QString &encryption,
|
||||
QXmpp::TrustSecurityPolicy securityPolicy) override;
|
||||
|
@ -64,6 +65,7 @@ public:
|
|||
|
||||
private:
|
||||
const QString &jid;
|
||||
const JidDb &db;
|
||||
QString service() const;
|
||||
};
|
||||
|
||||
|
|
62
xxcc.cpp
62
xxcc.cpp
|
@ -23,7 +23,6 @@ xxcc::xxcc(QWidget *const parent) :
|
|||
ui.setupUi(this);
|
||||
QScroller::grabGesture(ui.conversations_list, QScroller::TouchGesture);
|
||||
QScroller::grabGesture(ui.messages, QScroller::TouchGesture);
|
||||
setupDatabases(pairs);
|
||||
connectAccounts(pairs);
|
||||
retrieveConversations();
|
||||
connect(ui.accounts, &QPushButton::released, this,
|
||||
|
@ -39,16 +38,20 @@ xxcc::xxcc(QWidget *const parent) :
|
|||
connect(ui.contacts, &QPushButton::released, this,
|
||||
[this]
|
||||
{
|
||||
Contacts c(databases, this);
|
||||
Contacts c(clients, this);
|
||||
|
||||
connect(&c, &Contacts::startChat, this, &xxcc::startChat);
|
||||
|
||||
for (const auto db : databases)
|
||||
for (const auto cl : clients)
|
||||
{
|
||||
const auto db = &cl->database();
|
||||
|
||||
c.connect(db, &JidDb::addedToRoster, &c,
|
||||
[&c, db] (const QString jid)
|
||||
{
|
||||
c.add(db->jid, jid);
|
||||
});
|
||||
}
|
||||
|
||||
c.exec();
|
||||
});
|
||||
|
@ -74,11 +77,11 @@ xxcc::xxcc(QWidget *const parent) :
|
|||
break;
|
||||
}
|
||||
|
||||
if (databases.contains(selected->jidBare()))
|
||||
if (selected)
|
||||
{
|
||||
const auto db = databases[selected->jidBare()];
|
||||
const auto &db = selected->database();
|
||||
static const auto n_messages = 20;
|
||||
const auto messages = db->getMessages(conv->to, n_messages);
|
||||
const auto messages = db.messages(conv->to, n_messages);
|
||||
|
||||
for (auto it = messages.rbegin(); it != messages.rend(); it++)
|
||||
new Message(it->body, it->dt, it->direction, ui.messages);
|
||||
|
@ -97,9 +100,6 @@ xxcc::~xxcc()
|
|||
{
|
||||
for (const auto c : clients)
|
||||
delete c;
|
||||
|
||||
for (const auto db : databases)
|
||||
delete db;
|
||||
}
|
||||
|
||||
void xxcc::connectAccounts(const QList<Credentials::Pair> &pairs)
|
||||
|
@ -120,12 +120,6 @@ void xxcc::connectAccounts(const QList<Credentials::Pair> &pairs)
|
|||
}
|
||||
}
|
||||
|
||||
void xxcc::setupDatabases(const QList<Credentials::Pair> &pairs)
|
||||
{
|
||||
for (const auto &p : pairs)
|
||||
databases[p.first] = new JidDb(p.first);
|
||||
}
|
||||
|
||||
void xxcc::startChat(const QString from, const QString to)
|
||||
{
|
||||
bool found = false;
|
||||
|
@ -194,12 +188,7 @@ void xxcc::addAccount(Client *const c)
|
|||
roster->connect(roster, &QXmppRosterManager::rosterReceived, c,
|
||||
[this, c, roster]
|
||||
{
|
||||
if (databases.contains(c->jidBare()))
|
||||
{
|
||||
const auto db = databases[c->jidBare()];
|
||||
|
||||
db->addToRoster(roster->getRosterBareJids());
|
||||
}
|
||||
c->database().addToRoster(roster->getRosterBareJids());
|
||||
});
|
||||
else
|
||||
throw std::runtime_error("Expected non-null QXmppRosterManager");
|
||||
|
@ -239,23 +228,30 @@ void xxcc::storeMessage(const QXmppMessage &msg, const Direction dir) const
|
|||
break;
|
||||
}
|
||||
|
||||
if (databases.contains(jid))
|
||||
for (const auto c : clients)
|
||||
{
|
||||
const auto db = databases[jid];
|
||||
JidDb::Message m;
|
||||
if (c->jidBare() == jid)
|
||||
{
|
||||
const auto &db = c->database();
|
||||
JidDb::Message m;
|
||||
|
||||
m.body = msg.body();
|
||||
m.dt = msg.stamp();
|
||||
m.direction = dir;
|
||||
m.contact = contact;
|
||||
db->storeMessage(m);
|
||||
m.body = msg.body();
|
||||
m.dt = msg.stamp();
|
||||
m.direction = dir;
|
||||
m.contact = contact;
|
||||
db.storeMessage(m);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void xxcc::retrieveConversations()
|
||||
{
|
||||
for (const auto db : databases)
|
||||
for (const auto &conv : db->getConversations())
|
||||
new Conversation(db->jid, conv.to,
|
||||
ui.conversations_list, conv.last_msg, conv.dt);
|
||||
for (const auto c : clients)
|
||||
{
|
||||
const auto &db = c->database();
|
||||
|
||||
for (const auto &conv : db.conversations())
|
||||
new Conversation(db.jid, conv.to,
|
||||
ui.conversations_list, conv.last_msg, conv.dt);
|
||||
}
|
||||
}
|
||||
|
|
3
xxcc.h
3
xxcc.h
|
@ -6,7 +6,6 @@
|
|||
#include "credentials.h"
|
||||
#include "jiddb.h"
|
||||
#include <QDateTime>
|
||||
#include <QHash>
|
||||
#include <QList>
|
||||
#include <QWidget>
|
||||
#include <QSqlDatabase>
|
||||
|
@ -25,10 +24,8 @@ private:
|
|||
enum Tab {Conversations, Chat};
|
||||
Ui_main ui;
|
||||
QList<Client *> clients;
|
||||
QHash<QString, JidDb *> databases;
|
||||
Credentials creds;
|
||||
Client *selected;
|
||||
void setupDatabases(const QList<Credentials::Pair> &pairs);
|
||||
void connectAccounts(const QList<Credentials::Pair> &pairs);
|
||||
void storeMessage(const QXmppMessage &msg, Direction dir) const;
|
||||
void retrieveConversations();
|
||||
|
|
Loading…
Reference in New Issue