Beispiel #1
0
 def inputcooker_store_queue(self, char):
     """Put the cooked data in the input queue (no locking needed)"""
     if type(char) in [type(()), type([]), type(b"")]:
         for v in char:
             self.cookedq.put(chr_py3(v))
     else:
         self.cookedq.put(chr_py3(char))
Beispiel #2
0
 def _readline_insert(self, char, echo, insptr, line):
     """Deal properly with inserted chars in a line."""
     if not self._readline_do_echo(echo):
         return
     # Write out the remainder of the line
     self.write(char + b''.join([chr_py3(i) for i in line[insptr:]]))
     # Cursor Left to the current insert point
     char_count = len(line) - insptr
     self.write(self.CODES['CSRLEFT'] * char_count)
Beispiel #3
0
    def process(self, line):
        """Step through the line and process each character"""
        self.raw = self.raw + line
        try:
            if chr_py3(line[-1]) != self.eol_char:
                # Should always be here, but add it just in case.
                line = line + self.eol_char
        except IndexError:
            # Thrown if line == ''
            line = self.eol_char

        for char in line:
            if chr_py3(char) == self.escape_char:
                # Always handle escaped characters.
                self.last_process_char = self.process_char
                self.process_char = self.process_escape
                continue
            self.process_char(chr_py3(char))
        if not self.complete:
            # Ask for more.
            self.process(
                self.handler.readline(prompt=self.handler.CONTINUE_PROMPT,
                                      echo=True))
Beispiel #4
0
 def process_delimiter(self, char):
     """Process chars while not in a part"""
     char = chr_py3(char)
     if char in self.whitespace:
         return
     if char in self.quote_chars:
         # Store the quote type (' or ") and switch to quote processing.
         self.inquote = char
         self.process_char = self.process_quote
         return
     if char == self.eol_char:
         self.complete = True
         return
     # Switch to processing a part.
     self.process_char = self.process_part
     self.process_char(char)
Beispiel #5
0
 def _inputcooker_getc(self, block=True):
     """Get one character from the raw queue. Optionally blocking.
     Raise EOFError on end of stream. SHOULD ONLY BE CALLED FROM THE
     INPUT COOKER."""
     if self.rawq:
         ret = self.rawq[0]
         self.rawq = self.rawq[1:]
         return chr_py3(ret)
     if not block:
         if not self.inputcooker_socket_ready():
             return b''
     ret = self.sock.recv(20)
     self.eof = not ret
     self.rawq = self.rawq + ret
     if self.eof:
         raise EOFError
     return self._inputcooker_getc(block)
Beispiel #6
0
 def process_part(self, char):
     """Process chars while in a part"""
     char = chr_py3(char)
     if char in self.whitespace or char == self.eol_char:
         # End of the part.
         self.parts.append(b''.join(self.part))
         self.part = []
         # Switch back to processing a delimiter.
         self.process_char = self.process_delimiter
         if char == self.eol_char:
             self.complete = True
         return
     if char in self.quote_chars:
         # Store the quote type (' or ") and switch to quote processing.
         self.inquote = char
         self.process_char = self.process_quote
         return
     self.part.append(char)
Beispiel #7
0
    def inputcooker(self):
        """Input Cooker - Transfer from raw queue to cooked queue.

        Set self.eof when connection is closed.  Don't block unless in
        the midst of an IAC sequence.
        """
        try:
            while True:
                c = self._inputcooker_getc()
                if not self.iacseq:
                    if c == IAC:
                        self.iacseq += c
                        continue
                    elif c == chr_py3(13) and not self.sb:
                        c2 = self._inputcooker_getc(block=False)
                        if c2 == theNULL or c2 == b'':
                            c = chr_py3(10)
                        elif c2 == chr_py3(10):
                            c = c2
                        else:
                            self._inputcooker_ungetc(c2)
                            c = chr_py3(10)
                    elif c in [x[0] for x in list(self.ESCSEQ.keys())]:
                        'Looks like the begining of a key sequence'
                        codes = c
                        for keyseq in list(self.ESCSEQ.keys()):
                            if len(keyseq) == 0:
                                continue
                            while codes == keyseq[:len(codes)] and len(
                                    codes) <= keyseq:
                                if codes == keyseq:
                                    c = self.ESCSEQ[keyseq]
                                    break
                                codes = codes + self._inputcooker_getc()
                            if codes == keyseq:
                                break
                            self._inputcooker_ungetc(codes[1:])
                            codes = codes[0]
                    self._inputcooker_store(c)
                elif len(self.iacseq) == 1:
                    'IAC: IAC CMD [OPTION only for WILL/WONT/DO/DONT]'
                    if c in (DO, DONT, WILL, WONT):
                        self.iacseq += c
                        continue
                    self.iacseq = b''
                    if c == IAC:
                        self._inputcooker_store(c)
                    else:
                        if c == SB:  # SB ... SE start.
                            self.sb = 1
                            self.sbdataq = b''
                        elif c == SE:  # SB ... SE end.
                            self.sb = 0
                        # Callback is supposed to look into
                        # the sbdataq
                        self.options_handler(self.sock, c, NOOPT)
                elif len(self.iacseq) == 2:
                    cmd = self.iacseq[1]
                    self.iacseq = b''
                    if cmd in (DO, DONT, WILL, WONT):
                        self.options_handler(self.sock, cmd, c)
        except (EOFError, socket.error):
            pass
Beispiel #8
0
 def write(self, text):
     """Send a packet to the socket. This function cooks output."""
     text = str_to_bytes(text)  # eliminate any unicode or other snigglets
     text = text.replace(IAC, IAC + IAC)
     text = text.replace(chr_py3(10), chr_py3(13) + chr_py3(10))
     self.writecooked(text)
Beispiel #9
0
 def writemessage(self, text):
     """Write out an asynchr_py3onous message, then reconstruct the prompt and entered text."""
     log.debug('writing message %r', text)
     self.write(chr_py3(10) + str_to_bytes(text) + chr_py3(10))
     self.write(self._current_prompt +
                b''.join([chr_py3(i) for i in self._current_line]))
Beispiel #10
0
 def writeline(self, text):
     """Send a packet with line ending."""
     text = str_to_bytes(text) if isinstance(text, str) else text
     log.debug('writing line %r' % text)
     self.write(text + chr_py3(10))
Beispiel #11
0
    def readline(self, echo=None, prompt='', use_history=True):
        """Return a line of text, including the terminating LF
           If echo is true always echo, if echo is false never echo
           If echo is None follow the negotiated setting.
           prompt is the current prompt to write (and rewrite if needed)
           use_history controls if this current line uses (and adds to) the command history.
        """

        line = []
        insptr = 0
        ansi = 0
        histptr = len(self.history)
        prompt = str_to_bytes(prompt) if isinstance(prompt, str) else prompt
        if self.DOECHO:
            self.write(prompt)
            self._current_prompt = prompt
        else:
            self._current_prompt = b''
        self._current_line = b''

        while True:
            c = self.getc(block=True)
            c = self.ansi_to_curses(c)
            if c == theNULL:
                continue

            elif c == curses.KEY_LEFT:
                if insptr > 0:
                    insptr = insptr - 1
                    self._readline_echo(self.CODES['CSRLEFT'], echo)
                else:
                    self._readline_echo(BELL, echo)
                continue
            elif c == curses.KEY_RIGHT:
                if insptr < len(line):
                    insptr = insptr + 1
                    self._readline_echo(self.CODES['CSRRIGHT'], echo)
                else:
                    self._readline_echo(BELL, echo)
                continue
            elif c == curses.KEY_UP or c == curses.KEY_DOWN:
                if not use_history:
                    self._readline_echo(BELL, echo)
                    continue
                if c == curses.KEY_UP:
                    if histptr > 0:
                        histptr = histptr - 1
                    else:
                        self._readline_echo(BELL, echo)
                        continue
                elif c == curses.KEY_DOWN:
                    if histptr < len(self.history):
                        histptr = histptr + 1
                    else:
                        self._readline_echo(BELL, echo)
                        continue
                line = []
                if histptr < len(self.history):
                    line.extend(self.history[histptr])
                for char in range(insptr):
                    self._readline_echo(self.CODES['CSRLEFT'], echo)
                self._readline_echo(self.CODES['DEOL'], echo)
                self._readline_echo(b''.join([chr_py3(i) for i in line]), echo)
                insptr = len(line)
                continue
            elif c == chr_py3(3):
                self._readline_echo(
                    b'\n' + str_to_bytes(curses.ascii.unctrl(ord(c))) +
                    b' ABORT\n', echo)
                return b''
            elif c == chr_py3(4):
                if len(line) > 0:
                    self._readline_echo(
                        b'\n' + str_to_bytes(curses.ascii.unctrl(ord(c))) +
                        b' ABORT (QUIT)\n', echo)
                    return b''
                self._readline_echo(
                    b'\n' + str_to_bytes(curses.ascii.unctrl(ord(c))) +
                    b' QUIT\n', echo)
                return b'QUIT'
            elif c == chr_py3(10):
                self._readline_echo(c, echo)
                result = b''.join([chr_py3(i) for i in line])
                if use_history:
                    self.history.append(result)
                if echo is False:
                    if prompt:
                        self.write(chr_py3(10))
                    log.debug('readline: %s(hidden text)',
                              bytes_to_str(prompt))
                else:
                    log.debug('readline: %s%r', bytes_to_str(prompt),
                              bytes_to_str(result))
                return result
            elif c == curses.KEY_BACKSPACE or c == chr_py3(
                    127) or c == chr_py3(8):
                if insptr > 0:
                    self._readline_echo(
                        self.CODES['CSRLEFT'] + self.CODES['DEL'], echo)
                    insptr = insptr - 1
                    del line[insptr]
                else:
                    self._readline_echo(BELL, echo)
                continue
            elif c == curses.KEY_DC:
                if insptr < len(line):
                    self._readline_echo(self.CODES['DEL'], echo)
                    del line[insptr]
                else:
                    self._readline_echo(BELL, echo)
                continue
            else:
                if ord(c) < 32:
                    c = curses.ascii.unctrl(ord(c))
                if len(line) > insptr:
                    self._readline_insert(c, echo, insptr, line)
                else:
                    self._readline_echo(c, echo)
            line[insptr:insptr] = c
            insptr = insptr + len(c)
            if self._readline_do_echo(echo):
                self._current_line = line
Beispiel #12
0
                   Function.__doc__ should be long help
                   Function.aliases may be a list of alternative spellings
"""

import socket
import socketserver
import sys
import traceback
import curses
from curses import ascii, has_key
from telnetsrv.utils import chr_py3, str_to_bytes, bytes_to_str
import logging

log = logging.getLogger(__name__)

BELL = chr_py3(7)
ESC = chr_py3(27)
ANSI_START_SEQ = b'['
ANSI_KEY_TO_CURSES = {
    b'A': curses.KEY_UP,
    b'B': curses.KEY_DOWN,
    b'C': curses.KEY_RIGHT,
    b'D': curses.KEY_LEFT,
}

IAC = chr_py3(255)  # "Interpret As Command"
DONT = chr_py3(254)
DO = chr_py3(253)
WONT = chr_py3(252)
WILL = chr_py3(251)
theNULL = chr_py3(0)