Better nickname parsing, warn other clients when they does not provide a parsable nickname

Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
This commit is contained in:
Yohann D'ANELLO 2020-12-21 16:04:15 +01:00
parent e37c43b78d
commit 9f070f594b
Signed by: ynerant
GPG Key ID: 3A75C55819C8CF85
2 changed files with 32 additions and 8 deletions

View File

@ -15,7 +15,7 @@ class Hazelnut:
""" """
A hazelnut is a connected client, with its socket. A hazelnut is a connected client, with its socket.
""" """
def __init__(self, nickname: str = "anonymous", address: str = "localhost", port: int = 2500): def __init__(self, nickname: str = None, address: str = "localhost", port: int = 2500):
self.nickname = nickname self.nickname = nickname
try: try:
@ -174,7 +174,7 @@ class Squirrel(Hazelnut):
elif key != "\n": elif key != "\n":
# Insert the pressed key in the current message # Insert the pressed key in the current message
new_buffer = self.input_buffer[:self.input_index] + key + self.input_buffer[self.input_index:] new_buffer = self.input_buffer[:self.input_index] + key + self.input_buffer[self.input_index:]
if len(DataTLV.construct(f"<{self.nickname}> {new_buffer}")) > 255 - 8 - 4: if len(DataTLV.construct(f"{self.nickname}: {new_buffer}")) > 255 - 8 - 4:
# The message is too long to be sent once. We don't allow the user to type any other character. # The message is too long to be sent once. We don't allow the user to type any other character.
curses.beep() curses.beep()
return return
@ -190,7 +190,7 @@ class Squirrel(Hazelnut):
if not msg: if not msg:
return return
msg = f"<{self.nickname}> {msg}" msg = f"{self.nickname}: {msg}"
self.add_message(msg) self.add_message(msg)
pkt = Packet.construct(DataTLV.construct(msg)) pkt = Packet.construct(DataTLV.construct(msg))
@ -257,7 +257,7 @@ class Squirrel(Hazelnut):
Add a new system log message. Add a new system log message.
TODO: Configure logging levels to ignore some messages. TODO: Configure logging levels to ignore some messages.
""" """
return self.add_message(f"<system> *{msg}*") return self.add_message(f"system: *{msg}*")
def print_markdown(self, pad: Any, y: int, x: int, msg: str, def print_markdown(self, pad: Any, y: int, x: int, msg: str,
bold: bool = False, italic: bool = False, underline: bool = False, strike: bool = False) -> int: bold: bool = False, italic: bool = False, underline: bool = False, strike: bool = False) -> int:
@ -363,6 +363,8 @@ class Squirrel(Hazelnut):
if i + y_offset > curses.LINES - 3: if i + y_offset > curses.LINES - 3:
break break
msg = re.sub("([^:]*): (.*)", "<\\1> \\2", msg, 1)
if not re.match("<.*> .*", msg): if not re.match("<.*> .*", msg):
msg = "<unknown> " + msg msg = "<unknown> " + msg
match = re.match("<(.*)> (.*)", msg) match = re.match("<(.*)> (.*)", msg)

View File

@ -1,6 +1,6 @@
# Copyright (C) 2020 by eichhornchen, ÿnérant # Copyright (C) 2020 by eichhornchen, ÿnérant
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
import re
from typing import Any, List, Optional from typing import Any, List, Optional
from ipaddress import IPv6Address from ipaddress import IPv6Address
from enum import Enum from enum import Enum
@ -207,7 +207,21 @@ class DataTLV(TLV):
A message has been sent. We log it. A message has been sent. We log it.
TODO: Check that the tuple (sender_id, nonce) is unique to avoid duplicates. TODO: Check that the tuple (sender_id, nonce) is unique to avoid duplicates.
""" """
squirrel.add_message(self.data.decode('UTF-8')) msg = self.data.decode('UTF-8')
squirrel.add_message(msg)
nickname_match = re.match("(.*): (.*)", msg)
if nickname_match is None:
squirrel.send_packet(sender, Packet.construct(WarningTLV.construct(
"Unable to retrieve your username. Please use the syntax 'nickname: message'")))
else:
nickname = nickname_match.group(1)
if sender.nickname is None:
sender.nickname = nickname
elif sender.nickname != nickname:
squirrel.send_packet(sender, Packet.construct(WarningTLV.construct(
"It seems that you used two different nicknames. "
f"Known nickname: {sender.nickname}, found: {nickname}")))
sender.nickname = nickname
@staticmethod @staticmethod
def construct(message: str) -> "DataTLV": def construct(message: str) -> "DataTLV":
@ -281,7 +295,7 @@ class WarningTLV(TLV):
def unmarshal(self, raw_data: bytes) -> None: def unmarshal(self, raw_data: bytes) -> None:
self.type = raw_data[0] self.type = raw_data[0]
self.length = raw_data[1] self.length = raw_data[1]
self.message = raw_data[2:self.length].decode("UTF-8") self.message = raw_data[2:self.length + 2].decode("UTF-8")
def marshal(self) -> bytes: def marshal(self) -> bytes:
return self.type.to_bytes(1, sys.byteorder) + \ return self.type.to_bytes(1, sys.byteorder) + \
@ -289,7 +303,15 @@ class WarningTLV(TLV):
self.message.encode("UTF-8")[:self.length] self.message.encode("UTF-8")[:self.length]
def handle(self, squirrel: Any, sender: Any) -> None: def handle(self, squirrel: Any, sender: Any) -> None:
squirrel.add_message(f"<warning> *A client warned you: {self.message}*") squirrel.add_message(f"warning: *A client warned you: {self.message}*")
@staticmethod
def construct(message: str) -> "WarningTLV":
tlv = WarningTLV()
tlv.type = 7
tlv.message = message
tlv.length = len(tlv.message.encode("UTF-8"))
return tlv
class Packet: class Packet: