From fb53fc86b67efd17288df24dba72085018c29eac Mon Sep 17 00:00:00 2001
From: Loren Burkholder <computersemiexpert@outlook.com>
Date: Thu, 9 Sep 2021 21:31:23 -0400
Subject: [PATCH] Fix invites crashing the whole app

---
 src/Cache.cpp                  | 54 ++++++++++++++++++++++++++++++++++
 src/Cache.h                    |  4 +++
 src/Cache_p.h                  |  8 ++++-
 src/timeline/RoomlistModel.cpp |  5 +---
 4 files changed, 66 insertions(+), 5 deletions(-)

diff --git a/src/Cache.cpp b/src/Cache.cpp
index d009c0d38..6be616338 100644
--- a/src/Cache.cpp
+++ b/src/Cache.cpp
@@ -2614,6 +2614,12 @@ Cache::getInviteRoomName(lmdb::txn &txn, lmdb::dbi &statesdb, lmdb::dbi &members
         return QString("Empty Room");
 }
 
+RoomMember
+Cache::getDirectInviteMember(const std::string &room_id)
+{
+        return getMembersFromInvitedRoom(room_id, 0, 1).front();
+}
+
 QString
 Cache::getInviteRoomAvatarUrl(lmdb::txn &txn, lmdb::dbi &statesdb, lmdb::dbi &membersdb)
 {
@@ -2777,6 +2783,48 @@ Cache::getMembers(const std::string &room_id, std::size_t startIndex, std::size_
         return members;
 }
 
+std::vector<RoomMember>
+Cache::getMembersFromInvitedRoom(const std::string &room_id,
+                                 std::size_t startIndex,
+                                 std::size_t len)
+{
+        auto txn    = ro_txn(env_);
+        auto db     = getInviteMembersDb(txn, room_id);
+        auto cursor = lmdb::cursor::open(txn, db);
+
+        std::size_t currentIndex = 0;
+
+        const auto endIndex = std::min(startIndex + len, db.size(txn));
+
+        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 = json::parse(user_data);
+                        members.emplace_back(
+                          RoomMember{QString::fromStdString(std::string(user_id)),
+                                     QString::fromStdString(tmp.name)});
+                } catch (const json::exception &e) {
+                        nhlog::db()->warn("{}", e.what());
+                }
+
+                currentIndex += 1;
+        }
+
+        cursor.close();
+
+        return members;
+}
+
 bool
 Cache::isRoomMember(const std::string &user_id, const std::string &room_id)
 {
@@ -4816,6 +4864,12 @@ getMembers(const std::string &room_id, std::size_t startIndex, std::size_t len)
         return instance_->getMembers(room_id, startIndex, len);
 }
 
+RoomMember
+getDirectInviteMember(const std::string &room_id)
+{
+        return instance_->getDirectInviteMember(room_id);
+}
+
 void
 saveState(const mtx::responses::Sync &res)
 {
diff --git a/src/Cache.h b/src/Cache.h
index 57a36d73a..2c0247223 100644
--- a/src/Cache.h
+++ b/src/Cache.h
@@ -84,6 +84,10 @@ getRoomAvatarUrl(lmdb::txn &txn, lmdb::dbi &statesdb, lmdb::dbi &membersdb);
 std::vector<RoomMember>
 getMembers(const std::string &room_id, std::size_t startIndex = 0, std::size_t len = 30);
 
+//! Get the other person from an invite to a direct chat.
+RoomMember
+getDirectInviteMember(const std::string &room_id);
+
 bool
 isInitialized();
 
diff --git a/src/Cache_p.h b/src/Cache_p.h
index 6190413fb..d46050489 100644
--- a/src/Cache_p.h
+++ b/src/Cache_p.h
@@ -109,6 +109,10 @@ public:
         std::vector<RoomMember> getMembers(const std::string &room_id,
                                            std::size_t startIndex = 0,
                                            std::size_t len        = 30);
+
+        std::vector<RoomMember> getMembersFromInvitedRoom(const std::string &room_id,
+                                                          std::size_t startIndex = 0,
+                                                          std::size_t len        = 30);
         size_t memberCount(const std::string &room_id);
 
         void saveState(const mtx::responses::Sync &res);
@@ -135,6 +139,9 @@ public:
         //! Retrieve all the user ids from a room.
         std::vector<std::string> roomMembers(const std::string &room_id);
 
+        //! Get the other user from an invite to a direct chat.
+        RoomMember getDirectInviteMember(const std::string &room_id);
+
         //! Check if the given user has power leve greater than than
         //! lowest power level of the given events.
         bool hasEnoughPowerLevel(const std::vector<mtx::events::EventType> &eventTypes,
@@ -313,7 +320,6 @@ public:
 
                 return get_skey(a).compare(get_skey(b));
         }
-
 signals:
         void newReadReceipts(const QString &room_id, const std::vector<QString> &event_ids);
         void roomReadStatus(const std::map<QString, bool> &status);
diff --git a/src/timeline/RoomlistModel.cpp b/src/timeline/RoomlistModel.cpp
index a423090c7..e12348952 100644
--- a/src/timeline/RoomlistModel.cpp
+++ b/src/timeline/RoomlistModel.cpp
@@ -167,10 +167,7 @@ RoomlistModel::data(const QModelIndex &index, int role) const
                         case Roles::IsDirect:
                                 return room.member_count == 1;
                         case Roles::DirectChatOtherUserId:
-                                // if this is a direct chat, the front member is correct; otherwise,
-                                // it won't be used anyway
-                                return QString::fromStdString(
-                                  cache::roomMembers(roomid.toStdString()).front());
+                                return cache::getDirectInviteMember(roomid.toStdString()).user_id;
                         default:
                                 return {};
                         }
-- 
GitLab