Fix crash when creating link to room preview

This commit is contained in:
Nicolas Werner 2022-07-19 18:57:08 +02:00
parent 5524a2a199
commit 07bb95fbcd
No known key found for this signature in database
GPG key ID: C8D75E610773F2D9
5 changed files with 119 additions and 56 deletions

View file

@ -3006,49 +3006,54 @@ Cache::getMember(const std::string &room_id, const std::string &user_id)
std::vector<RoomMember> std::vector<RoomMember>
Cache::getMembers(const std::string &room_id, std::size_t startIndex, std::size_t len) Cache::getMembers(const std::string &room_id, std::size_t startIndex, std::size_t len)
{ {
auto txn = ro_txn(env_); try {
auto db = getMembersDb(txn, room_id); auto txn = ro_txn(env_);
auto cursor = lmdb::cursor::open(txn, db); auto db = getMembersDb(txn, room_id);
auto cursor = lmdb::cursor::open(txn, db);
std::size_t currentIndex = 0; std::size_t currentIndex = 0;
const auto endIndex = std::min(startIndex + len, db.size(txn)); const auto endIndex = std::min(startIndex + len, db.size(txn));
std::vector<RoomMember> members; std::vector<RoomMember> members;
std::string_view user_id, user_data;
while (cursor.get(user_id, user_data, MDB_NEXT)) {
if (currentIndex < startIndex) {
currentIndex += 1;
continue;
}
if (currentIndex >= endIndex)
break;
try {
MemberInfo tmp = nlohmann::json::parse(user_data).get<MemberInfo>();
members.emplace_back(RoomMember{QString::fromStdString(std::string(user_id)),
QString::fromStdString(tmp.name)});
} catch (const nlohmann::json::exception &e) {
nhlog::db()->warn("{}", e.what());
}
std::string_view user_id, user_data;
while (cursor.get(user_id, user_data, MDB_NEXT)) {
if (currentIndex < startIndex) {
currentIndex += 1; currentIndex += 1;
continue;
} }
if (currentIndex >= endIndex) cursor.close();
break;
try { return members;
MemberInfo tmp = nlohmann::json::parse(user_data).get<MemberInfo>(); } catch (const lmdb::error &e) {
members.emplace_back(RoomMember{QString::fromStdString(std::string(user_id)), nhlog::db()->error("Failed to retrieve members from db in room {}: {}", room_id, e.what());
QString::fromStdString(tmp.name)}); return {};
} catch (const nlohmann::json::exception &e) {
nhlog::db()->warn("{}", e.what());
}
currentIndex += 1;
} }
cursor.close();
return members;
} }
std::vector<RoomMember> std::vector<RoomMember>
Cache::getMembersFromInvite(const std::string &room_id, std::size_t startIndex, std::size_t len) Cache::getMembersFromInvite(const std::string &room_id, std::size_t startIndex, std::size_t len)
{ {
auto txn = ro_txn(env_);
std::vector<RoomMember> members;
try { try {
auto txn = ro_txn(env_);
std::vector<RoomMember> members;
auto db = getInviteMembersDb(txn, room_id); auto db = getInviteMembersDb(txn, room_id);
auto cursor = lmdb::cursor::open(txn, db); auto cursor = lmdb::cursor::open(txn, db);
@ -3079,11 +3084,12 @@ Cache::getMembersFromInvite(const std::string &room_id, std::size_t startIndex,
} }
cursor.close(); cursor.close();
} catch (const lmdb::error &e) {
nhlog::db()->warn("Failed to retrieve members {}", e.what());
}
return members; return members;
} catch (const lmdb::error &e) {
nhlog::db()->error("Failed to retrieve members from db in room {}: {}", room_id, e.what());
return {};
}
} }
bool bool
@ -4033,17 +4039,22 @@ Cache::roomMembers(const std::string &room_id)
{ {
auto txn = ro_txn(env_); auto txn = ro_txn(env_);
std::vector<std::string> members; try {
std::string_view user_id, unused; std::vector<std::string> members;
std::string_view user_id, unused;
auto db = getMembersDb(txn, room_id); auto db = getMembersDb(txn, room_id);
auto cursor = lmdb::cursor::open(txn, db); auto cursor = lmdb::cursor::open(txn, db);
while (cursor.get(user_id, unused, MDB_NEXT)) while (cursor.get(user_id, unused, MDB_NEXT))
members.emplace_back(user_id); members.emplace_back(user_id);
cursor.close(); cursor.close();
return members; return members;
} catch (const lmdb::error &e) {
nhlog::db()->error("Failed to retrieve members from db in room {}: {}", room_id, e.what());
return {};
}
} }
crypto::Trust crypto::Trust

View file

@ -881,3 +881,63 @@ utils::markRoomAsDirect(QString roomid, std::vector<RoomMember> members)
}); });
}); });
} }
std::vector<std::string>
utils::roomVias(const std::string &roomid)
{
std::vector<std::string> vias;
{
auto members = cache::getMembers(roomid, 0, 100);
if (!members.empty()) {
vias.push_back(http::client()->user_id().hostname());
for (const auto &m : members) {
if (vias.size() >= 4)
break;
auto user_id =
mtx::identifiers::parse<mtx::identifiers::User>(m.user_id.toStdString());
auto server = user_id.hostname();
if (std::find(begin(vias), end(vias), server) == vias.end())
vias.push_back(server);
}
}
}
if (vias.empty()) {
auto members = cache::getMembersFromInvite(roomid, 0, 100);
if (!members.empty()) {
vias.push_back(http::client()->user_id().hostname());
for (const auto &m : members) {
if (vias.size() >= 4)
break;
auto user_id =
mtx::identifiers::parse<mtx::identifiers::User>(m.user_id.toStdString());
auto server = user_id.hostname();
if (std::find(begin(vias), end(vias), server) == vias.end())
vias.push_back(server);
}
}
}
if (vias.empty()) {
auto parents = cache::client()->getParentRoomIds(roomid);
for (const auto &p : parents) {
auto child =
cache::client()->getStateEvent<mtx::events::state::space::Child>(p, roomid);
if (child && child->content.via)
vias.insert(vias.end(), child->content.via->begin(), child->content.via->end());
}
std::sort(begin(vias), end(vias));
auto last = std::unique(begin(vias), end(vias));
vias.erase(last, end(vias));
// if (vias.size()> 3)
// vias.erase(begin(vias)+3, end(vias));
}
return vias;
}

View file

@ -311,4 +311,7 @@ removeDirectFromRoom(QString roomid);
void void
markRoomAsDirect(QString roomid, std::vector<RoomMember> members); markRoomAsDirect(QString roomid, std::vector<RoomMember> members);
std::vector<std::string>
roomVias(const std::string &roomid);
} }

View file

@ -645,15 +645,8 @@ void
RoomlistModel::joinPreview(QString roomid) RoomlistModel::joinPreview(QString roomid)
{ {
if (previewedRooms.contains(roomid)) { if (previewedRooms.contains(roomid)) {
std::vector<std::string> vias; ChatPage::instance()->joinRoomVia(
auto parents = cache::client()->getParentRoomIds(roomid.toStdString()); roomid.toStdString(), utils::roomVias(roomid.toStdString()), false);
for (const auto &p : parents) {
auto child = cache::client()->getStateEvent<mtx::events::state::space::Child>(
p, roomid.toStdString());
if (child && child->content.via)
vias.insert(vias.end(), child->content.via->begin(), child->content.via->end());
}
ChatPage::instance()->joinRoomVia(roomid.toStdString(), vias, false);
} }
} }
void void

View file

@ -1813,16 +1813,12 @@ TimelineModel::getRoomVias(const QString &roomId)
{ {
QStringList vias; QStringList vias;
vias.push_back(QStringLiteral("via=%1").arg(QString( for (const auto &m : utils::roomVias(roomId.toStdString())) {
QUrl::toPercentEncoding(QString::fromStdString(http::client()->user_id().hostname())))));
auto members = cache::getMembers(roomId.toStdString(), 0, 100);
for (const auto &m : members) {
if (vias.size() >= 4) if (vias.size() >= 4)
break; break;
auto user_id = mtx::identifiers::parse<mtx::identifiers::User>(m.user_id.toStdString()); QString server =
QString server = QStringLiteral("via=%1").arg( QStringLiteral("via=%1").arg(QString(QUrl::toPercentEncoding(QString::fromStdString(m))));
QString(QUrl::toPercentEncoding(QString::fromStdString(user_id.hostname()))));
if (!vias.contains(server)) if (!vias.contains(server))
vias.push_back(server); vias.push_back(server);