- def negotiate_telnet_options(self):
- u"""Reply to/remove partial_input telnet negotiation options."""
-
- # start at the begining of the input
- position = 0
-
- # make a local copy to play with
- text = self.partial_input
-
- # as long as we haven't checked it all
- while position < len(text):
-
- # jump to the first IAC you find
- position = text.find(telnet_proto([u"IAC"]), position)
-
- # if there wasn't an IAC in the input, we're done
- if position < 0: break
-
- # replace a double (literal) IAC if there's an LF later
- elif len(text) > position+1 and text[position+1] == telnet_proto(
- [u"IAC"]
- ):
- if text.find("\n", position) > 0:
- text = text.replace(
- telnet_proto([u"IAC",u"IAC"]), telnet_proto([u"IAC"])
- )
- else: position += 1
- position += 1
-
- # implement an RFC 1143 option negotiation queue here
- elif len(text) > position+2 and text[position+1] in (
- telnet_proto([u"DO",u"DONT",u"WILL",u"WONT"])
- ):
- negotiation = text[position+1:position+3]
-
- # if we turned echo off, ignore the confirmation
- if not self.echoing and negotiation == telnet_proto(
- [u"DO",u"TELOPT_ECHO"]
- ):
- self.send(
- telnet_proto([u"IAC",u"WILL",u"TELOPT_ECHO"]), raw=True
- )
-
- # BINARY mode handling for unicode support (RFC 856)
- elif negotiation == telnet_proto([u"DO",u"TELOPT_BINARY"]):
- self.send(
- telnet_proto([u"IAC",u"WILL",u"TELOPT_BINARY"]), raw=True
- )
- self.client_displays_binary = True
- elif negotiation == telnet_proto([u"DONT",u"TELOPT_BINARY"]):
- self.send(
- telnet_proto([u"IAC",u"WONT",u"TELOPT_BINARY"]), raw=True
- )
- self.client_displays_binary = False
- elif negotiation == telnet_proto([u"WILL",u"TELOPT_BINARY"]):
- self.send(
- telnet_proto([u"IAC",u"DO",u"TELOPT_BINARY"]), raw=True
- )
- self.client_sends_binary = True
- elif negotiation == telnet_proto([u"WONT",u"TELOPT_BINARY"]):
- self.send(
- telnet_proto([u"IAC",u"DONT",u"TELOPT_BINARY"]), raw=True
- )
- self.client_sends_binary = False
-
- # allow LINEMODE (RFC 1184)
- elif negotiation == telnet_proto([u"WILL",u"TELOPT_LINEMODE"]):
- self.send(
- telnet_proto([u"IAC",u"DO",u"TELOPT_LINEMODE"]), raw=True
- )
- elif negotiation == telnet_proto([u"WONT",u"TELOPT_LINEMODE"]):
- self.send(
- telnet_proto([u"IAC",u"DONT",u"TELOPT_LINEMODE"]), raw=True
- )
-
- # allow NAWS (RFC 1073)
- elif negotiation == telnet_proto([u"WILL",u"TELOPT_NAWS"]):
- self.send(
- telnet_proto([u"IAC",u"DO",u"TELOPT_NAWS"]), raw=True
- )
- elif negotiation == telnet_proto([u"WONT",u"TELOPT_NAWS"]):
- self.send(
- telnet_proto([u"IAC",u"DONT",u"TELOPT_NAWS"]), raw=True
- )
-
- # if the client likes EOR (RFC 885) instead of GA, note it
- elif negotiation == telnet_proto([u"DO",u"TELOPT_EOR"]):
- self.send(
- telnet_proto([u"IAC",u"WILL",u"TELOPT_EOR"]), raw=True
- )
- self.terminator = telnet_proto([u"IAC",u"EOR"])
- elif negotiation == telnet_proto([u"DONT",u"TELOPT_EOR"]):
- self.send(
- telnet_proto([u"IAC",u"WONT",u"TELOPT_EOR"]), raw=True
- )
- if self.terminator == telnet_proto([u"IAC",u"EOR"]):
- self.terminator = telnet_proto([u"IAC",u"GA"])
-
- # if the client doesn't want GA, oblige (RFC 858)
- elif negotiation == telnet_proto([u"DO",u"TELOPT_SGA"]):
- self.send(telnet_proto([u"IAC",u"WILL",u"TELOPT_SGA"]),
- raw=True)
- if self.terminator == telnet_proto([u"IAC",u"GA"]):
- self.terminator = ""
-
- # we don't want to allow anything else
- elif text[position+1] == telnet_proto([u"DO"]):
- self.send(
- telnet_proto([u"IAC",u"WONT"])+text[position+2], raw=True
- )
- elif text[position+1] == telnet_proto([u"WILL"]):
- self.send(
- telnet_proto([u"IAC",u"DONT"])+text[position+2], raw=True
- )
-
- # strip the negotiation from the input
- text = text.replace(text[position:position+3], "")
-
- # subnegotiation options
- elif len(text) > position+4 and text[
- position:position+2
- ] == telnet_proto([u"IAC",u"SB"]):
- if text[position+2] == telnet_proto([u"TELOPT_NAWS"]):
- self.columns = ord(text[position+3])*256+ord(text[position+4])
- end_subnegotiation = text.find(
- telnet_proto([u"IAC",u"SE"]), position
- )
- if end_subnegotiation > 0:
- text = text[:position] + text[end_subnegotiation+2:]
- else: position += 1
-
- # otherwise, strip out a two-byte IAC command
- elif len(text) > position+2:
- text = text.replace(text[position:position+2], "")
-
- # and this means we got the begining of an IAC
- else: position += 1
-
- # replace the input with our cleaned-up text
- self.partial_input = text
-