mudpy.telnet.negotiate_telnet_options(self)
# separate multiple input lines
- new_input_lines = self.partial_input.split(b"\n")
+ new_input_lines = self.partial_input.split(b"\r\0")
+ if len(new_input_lines) == 1:
+ new_input_lines = new_input_lines[0].split(b"\r\n")
# if input doesn't end in a newline, replace the
# held partial input with the last line of it
- if not self.partial_input.endswith(b"\n"):
+ if not (
+ self.partial_input.endswith(b"\r\0") or
+ self.partial_input.endswith(b"\r\n")):
self.partial_input = new_input_lines.pop()
# otherwise, chop off the extra null input and reset
# the byte following the IAC is our command
command = text[position+1]
- # replace a double (literal) IAC if there's an LF later
+ # replace a double (literal) IAC if there's a CR+NUL or CR+LF later
if command is IAC:
- if text.find(b"\n", position) > 0:
+ if (
+ text.find(b"\r\0", position) > 0 or
+ text.find(b"\r\n", position) > 0):
position += 1
text = text[:position] + text[position + 1:]
else:
(2, "Whom would you like to awaken?", ""),
)
+test_crlf_eol = (
+ # Send a CR+LF at the end of the line instead of the default CR+NUL,
+ # to make sure they're treated the same
+ (2, "> ", b"say I use CR+LF as my EOL, not CR+NUL.\r\n"),
+ (2, r'You say, "I use CR\+LF as my EOL, not CR\+NUL\.".*> ', ""),
+)
+
test_telnet_iac = (
# Send a double (escaped) IAC byte within other text, which should get
# unescaped and deduplicated to a single \xff in the buffer and then
# the line of input discarded as a non-ASCII sequence
- (2, "> ", b"say argle\xff\xffbargle\r\n"),
+ (2, "> ", b"say argle\xff\xffbargle\r\0"),
(2, r"Non-ASCII characters from admin: b'say argle\\xffbargle'.*> ", ""),
)
test_telnet_unknown = (
# Send an unsupported negotiation command #127 which should get filtered
# from the line of input
- (2, "> ", b"say glop\xff\x7fglyf\r\n"),
+ (2, "> ", b"say glop\xff\x7fglyf\r\0"),
(2, r'Unknown Telnet IAC command 127 ignored\..*"Glopglyf\.".*> ', ""),
)
(test_actor_disappears, "actor spontaneous disappearance"),
(test_account1_teardown, "second account teardown"),
(test_admin_setup, "admin account setup"),
+ (test_crlf_eol, "send crlf from the client as eol"),
(test_telnet_iac, "escape stray telnet iac bytes"),
(test_telnet_unknown, "strip unknown telnet command"),
(test_admin_restriction, "restricted admin commands"),
break
if type(answer) is str:
tlog("luser%s sending: %s" % (conversant, answer), quiet=True)
- lusers[conversant].write(("%s\r\n" % answer).encode("utf-8"))
+ lusers[conversant].write(("%s\r\0" % answer).encode("utf-8"))
captures[conversant] += "%s\r\n" % answer
elif type(answer) is bytes:
tlog("luser%s sending raw bytes: %s" % (conversant, answer),