buffer: Store undecrytped events so we can try to decrypt them later.

This commit is contained in:
Damir Jelić 2018-11-22 13:52:09 +01:00
parent bdb7f4509e
commit a0199109be
2 changed files with 67 additions and 0 deletions

View file

@ -20,6 +20,7 @@ from __future__ import unicode_literals
import time import time
from builtins import super from builtins import super
from functools import partial from functools import partial
from collections import deque
from typing import Dict, List, NamedTuple, Optional, Set from typing import Dict, List, NamedTuple, Optional, Set
from uuid import UUID from uuid import UUID
@ -816,6 +817,7 @@ class RoomBuffer(object):
self.sent_messages_queue = dict() # type: Dict[UUID, OwnMessage] self.sent_messages_queue = dict() # type: Dict[UUID, OwnMessage]
self.printed_before_ack_queue = list() # type: List[UUID] self.printed_before_ack_queue = list() # type: List[UUID]
self.undecrypted_events = deque(maxlen=5000)
buffer_name = "{}.{}".format(server_name, room.room_id) buffer_name = "{}.{}".format(server_name, room.room_id)
@ -1300,6 +1302,8 @@ class RoomBuffer(object):
self.get_event_tags(event) + [session_id_tag] self.get_event_tags(event) + [session_id_tag]
) )
self.undecrypted_events.append(event)
else: else:
W.prnt( W.prnt(
"", "Unhandled event of type {}.".format(type(event).__name__) "", "Unhandled event of type {}.".format(type(event).__name__)
@ -1384,6 +1388,43 @@ class RoomBuffer(object):
new_tags.append(SCRIPT_NAME + "_id_" + new_message.event_id) new_tags.append(SCRIPT_NAME + "_id_" + new_message.event_id)
line.tags = new_tags line.tags = new_tags
def replace_undecrypted_line(self, event):
"""Find a undecrypted message in the buffer and replace it with the now
decrypted event."""
# TODO different messages need different formatting
# To implement this, refactor out the different formatting code
# snippets to a Formatter class and reuse them here.
if not isinstance(event, RoomMessageText):
return
def predicate(event_id, line):
event_tag = SCRIPT_NAME + "_id_{}".format(event_id)
if event_tag in line.tags:
return True
return False
lines = self.weechat_buffer.find_lines(
partial(predicate, event.event_id)
)
if not lines:
return
formatted = None
if event.formatted_body:
formatted = Formatted.from_html(event.formatted_body)
data = formatted.to_weechat() if formatted else event.body
# TODO this isn't right if the data has multiple lines, that is
# everything is printed on a signle line and newlines are shown as a
# space.
# Weechat should support deleting lines and printing new ones at an
# arbitrary position.
# To implement this without weechat support either only handle single
# line messages or edit the first line in place, print new ones at the
# bottom and sort the buffer lines.
lines[0].message = data
def old_redacted(self, event): def old_redacted(self, event):
tags = [ tags = [
SCRIPT_NAME + "_message", SCRIPT_NAME + "_message",

View file

@ -957,6 +957,28 @@ class MatrixServer(object):
"matrix_load_users_cb", self.name) "matrix_load_users_cb", self.name)
self.lazy_load_hook = hook self.lazy_load_hook = hook
def decrypt_printed_messages(self, key_event):
"""Decrypt already printed messages and send them to the buffer"""
try:
room_buffer = self.find_room_from_id(key_event.room_id)
except KeyError:
return
decrypted_events = []
for undecrypted_event in room_buffer.undecrypted_events:
if undecrypted_event.session_id != key_event.session_id:
continue
event = self.client.decrypt_event(undecrypted_event)
if event:
decrypted_events.append((undecrypted_event, event))
for event_pair in decrypted_events:
undecrypted_event, event = event_pair
room_buffer.undecrypted_events.remove(undecrypted_event)
room_buffer.replace_undecrypted_line(event)
def _handle_sync(self, response): def _handle_sync(self, response):
# we got the same batch again, nothing to do # we got the same batch again, nothing to do
if self.next_batch == response.next_batch: if self.next_batch == response.next_batch:
@ -979,6 +1001,10 @@ class MatrixServer(object):
} }
W.hook_hsignal_send("matrix_room_key_received", message) W.hook_hsignal_send("matrix_room_key_received", message)
# TODO try to decrypt some cached undecrypted messages with the
# new key
# self.decrypt_printed_messages(event)
# Full sync response handle everything. # Full sync response handle everything.
if isinstance(response, SyncResponse): if isinstance(response, SyncResponse):
if self.client.should_upload_keys: if self.client.should_upload_keys: