from __future__ import annotations import re _IRC_CONTROL_START = 0x00 _IRC_CONTROL_END = 0x1F _IRC_DEL = 0x7F _LITERAL_ESCAPE_PATTERN = re.compile(r"\\x[0-9a-fA-F]{2}") def is_irc_control_char(ch: str) -> bool: if len(ch) != 1: return False cp = ord(ch) return cp < 0x20 or cp == 0x7F def has_irc_control_chars(text: str) -> bool: return any(is_irc_control_char(c) for c in text) def strip_irc_control_chars(text: str) -> str: return "".join(c for c in text if not is_irc_control_char(c)) def decode_literal_escapes(text: str) -> str: """Strip literal escape sequences (\\xNN) from inbound text. Prevents attackers from injecting IRC control characters via literal backslash-x escape representations (e.g. \\x01 for CTCP delimiter). """ return _LITERAL_ESCAPE_PATTERN.sub("", text) def has_literal_escapes(text: str) -> bool: return bool(_LITERAL_ESCAPE_PATTERN.search(text)) def sanitize_outbound_text(text: str) -> str: text = text.replace("\n", " ").replace("\r", " ") return strip_irc_control_chars(text) def sanitize_inbound_text(text: str) -> str: text = decode_literal_escapes(text) return strip_irc_control_chars(text) def sanitize_irc_target(target: str) -> str: cleaned = strip_irc_control_chars(target) cleaned = cleaned.replace(" ", "_") return cleaned