diff --git a/gajim/common/connection_handlers_events.py b/gajim/common/connection_handlers_events.py index 98d03a64d..2c8596a57 100644 --- a/gajim/common/connection_handlers_events.py +++ b/gajim/common/connection_handlers_events.py @@ -1061,6 +1061,7 @@ class MamMessageReceivedEvent(nec.NetworkIncomingEvent, HelperEvent): self.nick = None def generate(self): + account = self.conn.name archive_jid = self.stanza.getFrom() own_jid = self.conn.get_own_jid() if archive_jid and not archive_jid.bareMatch(own_jid): @@ -1076,7 +1077,8 @@ class MamMessageReceivedEvent(nec.NetworkIncomingEvent, HelperEvent): self.unique_id, origin_id = self.get_unique_id() # Check for duplicates - if app.logger.find_stanza_id(own_jid.getStripped(), + if app.logger.find_stanza_id(account, + own_jid.getStripped(), self.unique_id, origin_id): return @@ -1151,6 +1153,7 @@ class MamGcMessageReceivedEvent(nec.NetworkIncomingEvent, HelperEvent): self.kind = KindConstant.GC_MSG def generate(self): + account = self.conn.name self.msg_ = self.forwarded.getTag('message', protocol=True) if self.msg_.getType() != 'groupchat': @@ -1161,7 +1164,9 @@ class MamGcMessageReceivedEvent(nec.NetworkIncomingEvent, HelperEvent): self.unique_id = self.get_stanza_id(self.result, query=True) # Check for duplicates - if app.logger.find_stanza_id(self.room_jid, self.unique_id, + if app.logger.find_stanza_id(account, + self.room_jid, + self.unique_id, groupchat=True): return @@ -1285,7 +1290,8 @@ class MessageReceivedEvent(nec.NetworkIncomingEvent, HelperEvent): # Check groupchat messages for duplicates, # We do this because of MUC History messages if self.stanza.getType() == 'groupchat': - if app.logger.find_stanza_id(self.stanza.getFrom().getStripped(), + if app.logger.find_stanza_id(account, + self.stanza.getFrom().getStripped(), self.unique_id, groupchat=True): return diff --git a/gajim/common/logger.py b/gajim/common/logger.py index 6fe0bddda..cb2b3a2de 100644 --- a/gajim/common/logger.py +++ b/gajim/common/logger.py @@ -1057,10 +1057,12 @@ class Logger: self.con.executescript(sql) self._timeout_commit() - def search_for_duplicate(self, jid, timestamp, msg): + def search_for_duplicate(self, account, jid, timestamp, msg): """ Check if a message is already in the `logs` table + :param account: The account + :param jid: The jid as string :param timestamp: The timestamp in UTC epoch @@ -1072,27 +1074,31 @@ class Logger: start_time = timestamp - 10 end_time = timestamp + 10 + account_id = self.get_account_id(account) log.debug('start: %s, end: %s, jid: %s, message: %s', start_time, end_time, jid, msg) sql = ''' SELECT * FROM logs - NATURAL JOIN jids WHERE jid = ? AND message = ? + NATURAL JOIN jids WHERE jid = ? AND message = ? AND account_id = ? AND time BETWEEN ? AND ? ''' - result = self.con.execute(sql, (jid, msg, start_time, end_time)).fetchone() + result = self.con.execute( + sql, (jid, msg, account_id, start_time, end_time)).fetchone() if result is not None: log.debug('Message already in DB') return True return False - def find_stanza_id(self, archive_jid, stanza_id, origin_id=None, + def find_stanza_id(self, account, archive_jid, stanza_id, origin_id=None, groupchat=False): """ Checks if a stanza-id is already in the `logs` table + :param account: The account + :param archive_jid: The jid of the archive the stanza-id belongs to :param stanza_id: The stanza-id @@ -1113,22 +1119,30 @@ class Logger: return False archive_id = self.get_jid_id(archive_jid) + account_id = self.get_account_id(account) + if groupchat: - column = 'jid_id' + # Stanza ID is only unique within a specific archive. + # So a Stanza ID could be repeated in different MUCs, so we + # filter also for the archive JID + sql = ''' + SELECT stanza_id FROM logs + WHERE stanza_id IN ({values}) + AND jid_id = ? AND account_id = ? LIMIT 1 + '''.format(values=', '.join('?' * len(ids))) + result = self.con.execute( + sql, tuple(ids) + (archive_id, account_id)).fetchone() else: - column = 'account_id' - - sql = ''' - SELECT stanza_id FROM logs - WHERE stanza_id IN ({values}) AND {archive} = ? LIMIT 1 - '''.format(values=', '.join('?' * len(ids)), - archive=column) - - result = self.con.execute(sql, tuple(ids) + (archive_id,)).fetchone() + sql = ''' + SELECT stanza_id FROM logs + WHERE stanza_id IN ({values}) AND account_id = ? LIMIT 1 + '''.format(values=', '.join('?' * len(ids))) + result = self.con.execute( + sql, tuple(ids) + (account_id,)).fetchone() if result is not None: - log.info('Found duplicated message, stanza-id: %s, origin-id: %s', - stanza_id, origin_id) + log.info('Found duplicated message, stanza-id: %s, origin-id: %s, ' + 'archive-jid: %s, account: %s', stanza_id, origin_id, archive_id, account_id) return True return False diff --git a/gajim/common/message_archiving.py b/gajim/common/message_archiving.py index f4d300419..affeaca16 100644 --- a/gajim/common/message_archiving.py +++ b/gajim/common/message_archiving.py @@ -203,7 +203,7 @@ class ConnectionArchive313: # if self.archiving_namespace != nbxmpp.NS_MAM_2: # Fallback duplicate search without stanza-id duplicate = app.logger.search_for_duplicate( - obj.with_, obj.timestamp, obj.msgtxt) + self.name, obj.with_, obj.timestamp, obj.msgtxt) if duplicate: # dont propagate the event further return True