def log_command(user_input: 'UserInput', window: 'TxWindow', contact_list: 'ContactList', group_list: 'GroupList', settings: 'Settings', c_queue: 'Queue', master_key: 'MasterKey') -> None: """Display message logs or export them to plaintext file on TxM/RxM. TxM processes sent messages, RxM processes sent and received messages for all participants in active window. """ cmd = user_input.plaintext.split()[0] export, header = dict(export=(True, LOG_EXPORT_HEADER), history=(False, LOG_DISPLAY_HEADER))[cmd] try: msg_to_load = int(user_input.plaintext.split()[1]) except ValueError: raise FunctionReturn("Error: Invalid number of messages.") except IndexError: msg_to_load = 0 if export and not yes( f"Export logs for '{window.name}' in plaintext?", head=1, tail=1): raise FunctionReturn("Logfile export aborted.") try: command = header + window.uid.encode() + US_BYTE + int_to_bytes( msg_to_load) except struct.error: raise FunctionReturn("Error: Invalid number of messages.") queue_command(command, settings, c_queue) access_logs(window, contact_list, group_list, settings, master_key, msg_to_load, export)
def log_command(cmd_data: bytes, ts: 'datetime', window_list: 'WindowList', contact_list: 'ContactList', group_list: 'GroupList', settings: 'Settings', master_key: 'MasterKey') -> None: """Display or export log file for the active window. Having the capability to export the log file from the encrypted database is a bad idea, but as it's required by the GDPR (https://gdpr-info.eu/art-20-gdpr/), it should be done as securely as possible. Therefore, before allowing export, TFC will ask for the master password to ensure no unauthorized user who gains momentary access to the system can the export logs from the database. """ export = ts is not None ser_no_msg, uid = separate_header(cmd_data, ENCODED_INTEGER_LENGTH) no_messages = bytes_to_int(ser_no_msg) window = window_list.get_window(uid) access_logs(window, contact_list, group_list, settings, master_key, msg_to_load=no_messages, export=export) if export: local_win = window_list.get_local_window() local_win.add_new( ts, f"Exported log file of {window.type} '{window.name}'.", output=True)
def log_command(user_input: 'UserInput', window: 'TxWindow', contact_list: 'ContactList', group_list: 'GroupList', settings: 'Settings', queues: 'QueueDict', master_key: 'MasterKey') -> None: """Display message logs or export them to plaintext file on TCBs. Transmitter Program processes sent, Receiver Program sent and received, messages of all participants in the active window. Having the capability to export the log file from the encrypted database is a bad idea, but as it's required by the GDPR (https://gdpr-info.eu/art-20-gdpr/), it should be done as securely as possible. Therefore, before allowing export, TFC will ask for the master password to ensure no unauthorized user who gains momentary access to the system can the export logs from the database. """ cmd = user_input.plaintext.split()[0] export, header = dict(export=(True, LOG_EXPORT), history=(False, LOG_DISPLAY))[cmd] try: msg_to_load = int(user_input.plaintext.split()[1]) except ValueError: raise SoftError("Error: Invalid number of messages.", head_clear=True) except IndexError: msg_to_load = 0 try: command = header + int_to_bytes(msg_to_load) + window.uid except struct.error: raise SoftError("Error: Invalid number of messages.", head_clear=True) if export and not yes(f"Export logs for '{window.name}' in plaintext?", abort=False): raise SoftError("Log file export aborted.", tail_clear=True, head=0, delay=1) authenticated = master_key.authenticate_action( ) if settings.ask_password_for_log_access else True if authenticated: queue_command(command, settings, queues) access_logs(window, contact_list, group_list, settings, master_key, msg_to_load, export=export) if export: raise SoftError( f"Exported log file of {window.type} '{window.name}'.", head_clear=True)
def test_export_short_private_message(self, _): # Setup # Test title displayed by the Receiver program. self.settings.software_operation = RX # Add a message from contact Alice to user (Bob). for p in assembly_packet_creator(MESSAGE, 'Hi Bob'): write_log_entry(p, nick_to_pub_key('Alice'), self.settings, self.master_key, origin=ORIGIN_CONTACT_HEADER) # Add a message from user (Bob) to Alice. for p in assembly_packet_creator(MESSAGE, 'Hi Alice'): write_log_entry(p, nick_to_pub_key('Alice'), self.settings, self.master_key) # Test self.assertIsNone(access_logs(*self.args, export=True)) with open("Receiver - Plaintext log (Alice)") as f: self.assertEqual( f.read(), f"""\ Log file of message(s) to/from contact Alice ════════════════════════════════════════════════════════════════════════════════ {self.time} Alice: Hi Bob {self.time} Me: Hi Alice <End of log file> """)
def log_command(cmd_data: bytes, ts: 'datetime', window_list: 'WindowList', contact_list: 'ContactList', group_list: 'GroupList', settings: 'Settings', master_key: 'MasterKey') -> None: """Display or export logfile for active window.""" export = ts is not None win_uid, no_msg_bytes = cmd_data.split(US_BYTE) no_messages = bytes_to_int(no_msg_bytes) window = window_list.get_window(win_uid.decode()) access_logs(window, contact_list, group_list, settings, master_key, msg_to_load=no_messages, export=export) if export: local_win = window_list.get_window(LOCAL_ID) local_win.add_new( ts, f"Exported logfile of {window.type_print} {window.name}.", output=True)
def log_command(cmd_data: bytes, ts: 'datetime', window_list: 'WindowList', contact_list: 'ContactList', group_list: 'GroupList', settings: 'Settings', master_key: 'MasterKey') -> None: """Display or export log file for the active window.""" export = ts is not None ser_no_msg, uid = separate_header(cmd_data, ENCODED_INTEGER_LENGTH) no_messages = bytes_to_int(ser_no_msg) window = window_list.get_window(uid) access_logs(window, contact_list, group_list, settings, master_key, msg_to_load=no_messages, export=export) if export: local_win = window_list.get_local_window() local_win.add_new( ts, f"Exported log file of {window.type} '{window.name}'.", output=True)
def log_command(user_input: 'UserInput', window: 'TxWindow', contact_list: 'ContactList', group_list: 'GroupList', settings: 'Settings', queues: 'QueueDict', master_key: 'MasterKey' ) -> None: """Display message logs or export them to plaintext file on TCBs. Transmitter Program processes sent, Receiver Program sent and received, messages of all participants in the active window. """ cmd = user_input.plaintext.split()[0] export, header = dict(export =(True, LOG_EXPORT), history=(False, LOG_DISPLAY))[cmd] try: msg_to_load = int(user_input.plaintext.split()[1]) except ValueError: raise FunctionReturn("Error: Invalid number of messages.", head_clear=True) except IndexError: msg_to_load = 0 try: command = header + int_to_bytes(msg_to_load) + window.uid except struct.error: raise FunctionReturn("Error: Invalid number of messages.", head_clear=True) if export: if not yes(f"Export logs for '{window.name}' in plaintext?", abort=False): raise FunctionReturn("Log file export aborted.", tail_clear=True, head=0, delay=1) queue_command(command, settings, queues) access_logs(window, contact_list, group_list, settings, master_key, msg_to_load, export) if export: raise FunctionReturn(f"Exported log file of {window.type} '{window.name}'.", head_clear=True)
def test_export_short_private_message(self): # Setup for p in assembly_packet_creator(MESSAGE, b'Hi Bob'): write_log_entry(p, '*****@*****.**', self.settings, self.masterkey, origin=ORIGIN_CONTACT_HEADER) for p in assembly_packet_creator(MESSAGE, b'Hi Alice'): write_log_entry(p, '*****@*****.**', self.settings, self.masterkey) # Test self.assertIsNone(access_logs(self.window, self.contact_list, self.group_list, self.settings, self.masterkey, export=True)) with open("UtM - Plaintext log (Alice)") as f: exported_log = f.read() self.assertEqual(exported_log, f"""\ Logfile of messages to/from Alice ════════════════════════════════════════════════════════════════════════════════ {self.time} Alice: Hi Bob {self.time} Me: Hi Alice <End of logfile> """)
def test_long_group_message(self): # Setup self.window = RxWindow(type=WIN_TYPE_GROUP, uid='test_group', name='test_group') # Add an assembly packet sequence for contact containing cancel packet that the function should skip packets = assembly_packet_creator(MESSAGE, self.msg) packets = packets[2:] + [M_C_HEADER + bytes(PADDING_LEN)] for p in packets: write_log_entry(p, '*****@*****.**', self.settings, self.masterkey) # Add an orphaned 'append' assembly packet that the function should skip write_log_entry(M_A_HEADER + bytes(PADDING_LEN), '*****@*****.**', self.settings, self.masterkey) # Add a private message that the function should skip for p in assembly_packet_creator(MESSAGE, b'This is a short message'): write_log_entry(p, '*****@*****.**', self.settings, self.masterkey) # Add a group management message that the function should skip message = US_BYTE.join([b'test_group', b'*****@*****.**']) for p in assembly_packet_creator(MESSAGE, message, header=GROUP_MSG_INVITEJOIN_HEADER): write_log_entry(p, '*****@*****.**', self.settings, self.masterkey) # Add a group message that the function should skip for p in assembly_packet_creator(MESSAGE, b'This is a short message', group_name='different_group'): write_log_entry(p, '*****@*****.**', self.settings, self.masterkey) for p in assembly_packet_creator(MESSAGE, self.msg, group_name='test_group'): write_log_entry(p, '*****@*****.**', self.settings, self.masterkey) write_log_entry(p, '*****@*****.**', self.settings, self.masterkey, origin=ORIGIN_CONTACT_HEADER) write_log_entry(p, '*****@*****.**', self.settings, self.masterkey) write_log_entry(p, '*****@*****.**', self.settings, self.masterkey, origin=ORIGIN_CONTACT_HEADER) # Test access_logs(self.window, self.contact_list, self.group_list, self.settings, self.masterkey) self.assertPrints((CLEAR_ENTIRE_SCREEN + CURSOR_LEFT_UP_CORNER + f"""\ Logfile of messages to/from test_group ════════════════════════════════════════════════════════════════════════════════ {self.time} Me: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean condimentum consectetur purus quis dapibus. Fusce venenatis lacus ut rhoncus faucibus. Cras sollicitudin commodo sapien, sed bibendum velit maximus in. Aliquam ac metus risus. Sed cursus ornare luctus. Integer aliquet lectus id massa blandit imperdiet. Ut sed massa eget quam facilisis rutrum. Mauris eget luctus nisl. Sed ut elit iaculis, faucibus lacus eget, sodales magna. Nunc sed commodo arcu. In hac habitasse platea dictumst. Integer luctus aliquam justo, at vestibulum dolor iaculis ac. Etiam laoreet est eget odio rutrum, vel malesuada lorem rhoncus. Cras finibus in neque eu euismod. Nulla facilisi. Nunc nec aliquam quam, quis ullamcorper leo. Nunc egestas lectus eget est porttitor, in iaculis felis scelerisque. In sem elit, fringilla id viverra commodo, sagittis varius purus. Pellentesque rutrum lobortis neque a facilisis. Mauris id tortor placerat, aliquam dolor ac, venenatis arcu. {self.time} Alice: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean condimentum consectetur purus quis dapibus. Fusce venenatis lacus ut rhoncus faucibus. Cras sollicitudin commodo sapien, sed bibendum velit maximus in. Aliquam ac metus risus. Sed cursus ornare luctus. Integer aliquet lectus id massa blandit imperdiet. Ut sed massa eget quam facilisis rutrum. Mauris eget luctus nisl. Sed ut elit iaculis, faucibus lacus eget, sodales magna. Nunc sed commodo arcu. In hac habitasse platea dictumst. Integer luctus aliquam justo, at vestibulum dolor iaculis ac. Etiam laoreet est eget odio rutrum, vel malesuada lorem rhoncus. Cras finibus in neque eu euismod. Nulla facilisi. Nunc nec aliquam quam, quis ullamcorper leo. Nunc egestas lectus eget est porttitor, in iaculis felis scelerisque. In sem elit, fringilla id viverra commodo, sagittis varius purus. Pellentesque rutrum lobortis neque a facilisis. Mauris id tortor placerat, aliquam dolor ac, venenatis arcu. {self.time} Charlie: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean condimentum consectetur purus quis dapibus. Fusce venenatis lacus ut rhoncus faucibus. Cras sollicitudin commodo sapien, sed bibendum velit maximus in. Aliquam ac metus risus. Sed cursus ornare luctus. Integer aliquet lectus id massa blandit imperdiet. Ut sed massa eget quam facilisis rutrum. Mauris eget luctus nisl. Sed ut elit iaculis, faucibus lacus eget, sodales magna. Nunc sed commodo arcu. In hac habitasse platea dictumst. Integer luctus aliquam justo, at vestibulum dolor iaculis ac. Etiam laoreet est eget odio rutrum, vel malesuada lorem rhoncus. Cras finibus in neque eu euismod. Nulla facilisi. Nunc nec aliquam quam, quis ullamcorper leo. Nunc egestas lectus eget est porttitor, in iaculis felis scelerisque. In sem elit, fringilla id viverra commodo, sagittis varius purus. Pellentesque rutrum lobortis neque a facilisis. Mauris id tortor placerat, aliquam dolor ac, venenatis arcu. <End of logfile> """), access_logs, self.window, self.contact_list, self.group_list, self.settings, self.masterkey)