| Index: third_party/pexpect/examples/cgishell.cgi | 
| diff --git a/third_party/pexpect/examples/cgishell.cgi b/third_party/pexpect/examples/cgishell.cgi | 
| new file mode 100644 | 
| index 0000000000000000000000000000000000000000..23bef5f54f7eb4745ccca1ef5fc689a55eef4082 | 
| --- /dev/null | 
| +++ b/third_party/pexpect/examples/cgishell.cgi | 
| @@ -0,0 +1,766 @@ | 
| +#!/usr/bin/python | 
| +##!/usr/bin/env python | 
| +"""CGI shell server | 
| + | 
| +This exposes a shell terminal on a web page. | 
| +It uses AJAX to send keys and receive screen updates. | 
| +The client web browser needs nothing but CSS and Javascript. | 
| + | 
| +    --hostname : sets the remote host name to open an ssh connection to. | 
| +    --username : sets the user name to login with | 
| +    --password : (optional) sets the password to login with | 
| +    --port     : set the local port for the server to listen on | 
| +    --watch    : show the virtual screen after each client request | 
| + | 
| +This project is probably not the most security concious thing I've ever built. | 
| +This should be considered an experimental tool -- at best. | 
| +""" | 
| + | 
| +from __future__ import absolute_import | 
| +from __future__ import print_function | 
| + | 
| +import sys,os | 
| +sys.path.insert (0,os.getcwd()) # let local modules precede any installed modules | 
| +import socket, random, string, traceback, cgi, time, getopt, getpass, threading, resource, signal | 
| +import pxssh, pexpect, ANSI | 
| + | 
| +def exit_with_usage(exit_code=1): | 
| +    print(globals()['__doc__']) | 
| +    os._exit(exit_code) | 
| + | 
| +def client (command, host='localhost', port=-1): | 
| +    """This sends a request to the server and returns the response. | 
| +    If port <= 0 then host is assumed to be the filename of a Unix domain socket. | 
| +    If port > 0 then host is an inet hostname. | 
| +    """ | 
| +    if port <= 0: | 
| +        s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) | 
| +        s.connect(host) | 
| +    else: | 
| +        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) | 
| +        s.connect((host, port)) | 
| +    s.send(command) | 
| +    data = s.recv (2500) | 
| +    s.close() | 
| +    return data | 
| + | 
| +def server (hostname, username, password, socket_filename='/tmp/server_sock', daemon_mode = True, verbose=False): | 
| +    """This starts and services requests from a client. | 
| +        If daemon_mode is True then this forks off a separate daemon process and returns the daemon's pid. | 
| +        If daemon_mode is False then this does not return until the server is done. | 
| +    """ | 
| +    if daemon_mode: | 
| +        mypid_name = '/tmp/%d.pid' % os.getpid() | 
| +        daemon_pid = daemonize(daemon_pid_filename=mypid_name) | 
| +        time.sleep(1) | 
| +        if daemon_pid != 0: | 
| +            os.unlink(mypid_name) | 
| +            return daemon_pid | 
| + | 
| +    virtual_screen = ANSI.ANSI (24,80) | 
| +    child = pxssh.pxssh() | 
| +    try: | 
| +        child.login (hostname, username, password, login_naked=True) | 
| +    except: | 
| +        return | 
| +    if verbose: print('login OK') | 
| +    virtual_screen.write (child.before) | 
| +    virtual_screen.write (child.after) | 
| + | 
| +    if os.path.exists(socket_filename): os.remove(socket_filename) | 
| +    s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) | 
| +    s.bind(socket_filename) | 
| +    os.chmod(socket_filename, 0o777) | 
| +    if verbose: print('Listen') | 
| +    s.listen(1) | 
| + | 
| +    r = roller (endless_poll, (child, child.PROMPT, virtual_screen)) | 
| +    r.start() | 
| +    if verbose: print("started screen-poll-updater in background thread") | 
| +    sys.stdout.flush() | 
| +    try: | 
| +        while True: | 
| +            conn, addr = s.accept() | 
| +            if verbose: print('Connected by', addr) | 
| +            data = conn.recv(1024) | 
| +            request = data.split(' ', 1) | 
| +            if len(request)>1: | 
| +                cmd = request[0].strip() | 
| +                arg = request[1].strip() | 
| +            else: | 
| +                cmd = request[0].strip() | 
| +                arg = '' | 
| + | 
| +            if cmd == 'exit': | 
| +                r.cancel() | 
| +                break | 
| +            elif cmd == 'sendline': | 
| +                child.sendline (arg) | 
| +                time.sleep(0.1) | 
| +                shell_window = str(virtual_screen) | 
| +            elif cmd == 'send' or cmd=='xsend': | 
| +                if cmd=='xsend': | 
| +                    arg = arg.decode("hex") | 
| +                child.send (arg) | 
| +                time.sleep(0.1) | 
| +                shell_window = str(virtual_screen) | 
| +            elif cmd == 'cursor': | 
| +                shell_window = '%x,%x' % (virtual_screen.cur_r, virtual_screen.cur_c) | 
| +            elif cmd == 'refresh': | 
| +                shell_window = str(virtual_screen) | 
| +            elif cmd == 'hash': | 
| +                shell_window = str(hash(str(virtual_screen))) | 
| + | 
| +            response = [] | 
| +            response.append (shell_window) | 
| +            if verbose: print('\n'.join(response)) | 
| +            sent = conn.send('\n'.join(response)) | 
| +            if sent < len (response): | 
| +                if verbose: print("Sent is too short. Some data was cut off.") | 
| +            conn.close() | 
| +    except e: | 
| +        pass | 
| +    r.cancel() | 
| +    if verbose: print("cleaning up socket") | 
| +    s.close() | 
| +    if os.path.exists(socket_filename): os.remove(socket_filename) | 
| +    if verbose: print("server done!") | 
| + | 
| +class roller (threading.Thread): | 
| +    """This class continuously loops a function in a thread. | 
| +        This is basically a thin layer around Thread with a | 
| +        while loop and a cancel. | 
| +    """ | 
| +    def __init__(self, function, args=[], kwargs={}): | 
| +        threading.Thread.__init__(self) | 
| +        self.function = function | 
| +        self.args = args | 
| +        self.kwargs = kwargs | 
| +        self.finished = threading.Event() | 
| +    def cancel(self): | 
| +        """Stop the roller.""" | 
| +        self.finished.set() | 
| +    def run(self): | 
| +        while not self.finished.isSet(): | 
| +            self.function(*self.args, **self.kwargs) | 
| + | 
| +def endless_poll (child, prompt, screen, refresh_timeout=0.1): | 
| +    """This keeps the screen updated with the output of the child. | 
| +        This will be run in a separate thread. See roller class. | 
| +    """ | 
| +    #child.logfile_read = screen | 
| +    try: | 
| +        s = child.read_nonblocking(4000, 0.1) | 
| +        screen.write(s) | 
| +    except: | 
| +        pass | 
| + | 
| +def daemonize (stdin=None, stdout=None, stderr=None, daemon_pid_filename=None): | 
| +    """This runs the current process in the background as a daemon. | 
| +    The arguments stdin, stdout, stderr allow you to set the filename that the daemon reads and writes to. | 
| +    If they are set to None then all stdio for the daemon will be directed to /dev/null. | 
| +    If daemon_pid_filename is set then the pid of the daemon will be written to it as plain text | 
| +    and the pid will be returned. If daemon_pid_filename is None then this will return None. | 
| +    """ | 
| +    UMASK = 0 | 
| +    WORKINGDIR = "/" | 
| +    MAXFD = 1024 | 
| + | 
| +    # The stdio file descriptors are redirected to /dev/null by default. | 
| +    if hasattr(os, "devnull"): | 
| +        DEVNULL = os.devnull | 
| +    else: | 
| +        DEVNULL = "/dev/null" | 
| +    if stdin is None: stdin = DEVNULL | 
| +    if stdout is None: stdout = DEVNULL | 
| +    if stderr is None: stderr = DEVNULL | 
| + | 
| +    try: | 
| +        pid = os.fork() # fork first child | 
| +    except OSError as e: | 
| +        raise Exception("%s [%d]" % (e.strerror, e.errno)) | 
| + | 
| +    if pid != 0: | 
| +        os.waitpid(pid,0) | 
| +        if daemon_pid_filename is not None: | 
| +            daemon_pid = int(file(daemon_pid_filename,'r').read()) | 
| +            return daemon_pid | 
| +        else: | 
| +            return None | 
| + | 
| +    # first child | 
| +    os.setsid() | 
| +    signal.signal(signal.SIGHUP, signal.SIG_IGN) | 
| + | 
| +    try: | 
| +        pid = os.fork() # fork second child | 
| +    except OSError as e: | 
| +        raise Exception("%s [%d]" % (e.strerror, e.errno)) | 
| + | 
| +    if pid != 0: | 
| +        if daemon_pid_filename is not None: | 
| +            file(daemon_pid_filename,'w').write(str(pid)) | 
| +        os._exit(0) # exit parent (the first child) of the second child. | 
| + | 
| +    # second child | 
| +    os.chdir(WORKINGDIR) | 
| +    os.umask(UMASK) | 
| + | 
| +    maxfd = resource.getrlimit(resource.RLIMIT_NOFILE)[1] | 
| +    if maxfd == resource.RLIM_INFINITY: | 
| +        maxfd = MAXFD | 
| + | 
| +    # close all file descriptors | 
| +    for fd in range(0, maxfd): | 
| +        try: | 
| +            os.close(fd) | 
| +        except OSError:   # fd wasn't open to begin with (ignored) | 
| +            pass | 
| + | 
| +    os.open (DEVNULL, os.O_RDWR)  # standard input | 
| + | 
| +    # redirect standard file descriptors | 
| +    si = open(stdin, 'r') | 
| +    so = open(stdout, 'a+') | 
| +    se = open(stderr, 'a+', 0) | 
| +    os.dup2(si.fileno(), sys.stdin.fileno()) | 
| +    os.dup2(so.fileno(), sys.stdout.fileno()) | 
| +    os.dup2(se.fileno(), sys.stderr.fileno()) | 
| + | 
| +    return 0 | 
| + | 
| +def client_cgi (): | 
| +    """This handles the request if this script was called as a cgi. | 
| +    """ | 
| +    sys.stderr = sys.stdout | 
| +    ajax_mode = False | 
| +    TITLE="Shell" | 
| +    SHELL_OUTPUT="" | 
| +    SID="NOT" | 
| +    print("Content-type: text/html;charset=utf-8\r\n") | 
| +    try: | 
| +        form = cgi.FieldStorage() | 
| +        if 'ajax' in form: | 
| +            ajax_mode = True | 
| +            ajax_cmd = form['ajax'].value | 
| +            SID=form['sid'].value | 
| +            if ajax_cmd == 'send': | 
| +                command = 'xsend' | 
| +                arg = form['arg'].value.encode('hex') | 
| +                result = client (command + ' ' + arg, '/tmp/'+SID) | 
| +                print(result) | 
| +            elif ajax_cmd == 'refresh': | 
| +                command = 'refresh' | 
| +                result = client (command, '/tmp/'+SID) | 
| +                print(result) | 
| +            elif ajax_cmd == 'cursor': | 
| +                command = 'cursor' | 
| +                result = client (command, '/tmp/'+SID) | 
| +                print(result) | 
| +            elif ajax_cmd == 'exit': | 
| +                command = 'exit' | 
| +                result = client (command, '/tmp/'+SID) | 
| +                print(result) | 
| +            elif ajax_cmd == 'hash': | 
| +                command = 'hash' | 
| +                result = client (command, '/tmp/'+SID) | 
| +                print(result) | 
| +        elif 'sid' not in form: | 
| +            SID=random_sid() | 
| +            print(LOGIN_HTML % locals()); | 
| +        else: | 
| +            SID=form['sid'].value | 
| +            if 'start_server' in form: | 
| +                USERNAME = form['username'].value | 
| +                PASSWORD = form['password'].value | 
| +                dpid = server ('127.0.0.1', USERNAME, PASSWORD, '/tmp/'+SID) | 
| +                SHELL_OUTPUT="daemon pid: " + str(dpid) | 
| +            else: | 
| +                if 'cli' in form: | 
| +                    command = 'sendline ' + form['cli'].value | 
| +                else: | 
| +                    command = 'sendline' | 
| +                SHELL_OUTPUT = client (command, '/tmp/'+SID) | 
| +            print(CGISH_HTML % locals()) | 
| +    except: | 
| +        tb_dump = traceback.format_exc() | 
| +        if ajax_mode: | 
| +            print(str(tb_dump)) | 
| +        else: | 
| +            SHELL_OUTPUT=str(tb_dump) | 
| +            print(CGISH_HTML % locals()) | 
| + | 
| +def server_cli(): | 
| +    """This is the command line interface to starting the server. | 
| +    This handles things if the script was not called as a CGI | 
| +    (if you run it from the command line). | 
| +    """ | 
| +    try: | 
| +        optlist, args = getopt.getopt(sys.argv[1:], 'h?d', ['help','h','?', 'hostname=', 'username=', 'password=', 'port=', 'watch']) | 
| +    except Exception as e: | 
| +        print(str(e)) | 
| +        exit_with_usage() | 
| + | 
| +    command_line_options = dict(optlist) | 
| +    options = dict(optlist) | 
| +    # There are a million ways to cry for help. These are but a few of them. | 
| +    if [elem for elem in command_line_options if elem in ['-h','--h','-?','--?','--help']]: | 
| +        exit_with_usage(0) | 
| + | 
| +    hostname = "127.0.0.1" | 
| +    #port = 1664 | 
| +    username = os.getenv('USER') | 
| +    password = "" | 
| +    daemon_mode = False | 
| +    if '-d' in options: | 
| +        daemon_mode = True | 
| +    if '--watch' in options: | 
| +        watch_mode = True | 
| +    else: | 
| +        watch_mode = False | 
| +    if '--hostname' in options: | 
| +        hostname = options['--hostname'] | 
| +    if '--port' in options: | 
| +        port = int(options['--port']) | 
| +    if '--username' in options: | 
| +        username = options['--username'] | 
| +    if '--password' in options: | 
| +        password = options['--password'] | 
| +    else: | 
| +        password = getpass.getpass('password: ') | 
| + | 
| +    server (hostname, username, password, '/tmp/mysock', daemon_mode) | 
| + | 
| +def random_sid (): | 
| +    a=random.randint(0,65535) | 
| +    b=random.randint(0,65535) | 
| +    return '%04x%04x.sid' % (a,b) | 
| + | 
| +def parse_host_connect_string (hcs): | 
| +    """This parses a host connection string in the form | 
| +    username:password@hostname:port. All fields are options expcet hostname. A | 
| +    dictionary is returned with all four keys. Keys that were not included are | 
| +    set to empty strings ''. Note that if your password has the '@' character | 
| +    then you must backslash escape it. | 
| +    """ | 
| +    if '@' in hcs: | 
| +        p = re.compile (r'(?P<username>[^@:]*)(:?)(?P<password>.*)(?!\\)@(?P<hostname>[^:]*):?(?P<port>[0-9]*)') | 
| +    else: | 
| +        p = re.compile (r'(?P<username>)(?P<password>)(?P<hostname>[^:]*):?(?P<port>[0-9]*)') | 
| +    m = p.search (hcs) | 
| +    d = m.groupdict() | 
| +    d['password'] = d['password'].replace('\\@','@') | 
| +    return d | 
| + | 
| +def pretty_box (s, rows=24, cols=80): | 
| +    """This puts an ASCII text box around the given string. | 
| +    """ | 
| +    top_bot = '+' + '-'*cols + '+\n' | 
| +    return top_bot + '\n'.join(['|'+line+'|' for line in s.split('\n')]) + '\n' + top_bot | 
| + | 
| +def main (): | 
| +    if os.getenv('REQUEST_METHOD') is None: | 
| +        server_cli() | 
| +    else: | 
| +        client_cgi() | 
| + | 
| +# It's mostly HTML and Javascript from here on out. | 
| +CGISH_HTML="""<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> | 
| +<html> | 
| +<head> | 
| +<title>%(TITLE)s %(SID)s</title> | 
| +<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> | 
| +<style type=text/css> | 
| +a {color: #9f9; text-decoration: none} | 
| +a:hover {color: #0f0} | 
| +hr {color: #0f0} | 
| +html,body,textarea,input,form | 
| +{ | 
| +font-family: "Courier New", Courier, mono; | 
| +font-size: 8pt; | 
| +color: #0c0; | 
| +background-color: #020; | 
| +margin:0; | 
| +padding:0; | 
| +border:0; | 
| +} | 
| +input { background-color: #010; } | 
| +textarea { | 
| +border-width:1; | 
| +border-style:solid; | 
| +border-color:#0c0; | 
| +padding:3; | 
| +margin:3; | 
| +} | 
| +</style> | 
| + | 
| +<script language="JavaScript"> | 
| +function focus_first() | 
| +{if (document.forms.length > 0) | 
| +{var TForm = document.forms[0]; | 
| +for (i=0;i<TForm.length;i++){ | 
| +if ((TForm.elements[i].type=="text")|| | 
| +(TForm.elements[i].type=="textarea")|| | 
| +(TForm.elements[i].type.toString().charAt(0)=="s")) | 
| +{document.forms[0].elements[i].focus();break;}}}} | 
| + | 
| +// JavaScript Virtual Keyboard | 
| +// If you like this code then buy me a sandwich. | 
| +// Noah Spurrier <noah@noah.org> | 
| +var flag_shift=0; | 
| +var flag_shiftlock=0; | 
| +var flag_ctrl=0; | 
| +var ButtonOnColor="#ee0"; | 
| + | 
| +function init () | 
| +{ | 
| +    // hack to set quote key to show both single quote and double quote | 
| +    document.form['quote'].value = "'" + '  "'; | 
| +    //refresh_screen(); | 
| +    poll(); | 
| +    document.form["cli"].focus(); | 
| +} | 
| +function get_password () | 
| +{ | 
| +    var username = prompt("username?",""); | 
| +    var password = prompt("password?",""); | 
| +    start_server (username, password); | 
| +} | 
| +function multibrowser_ajax () | 
| +{ | 
| +    var xmlHttp = false; | 
| +/*@cc_on @*/ | 
| +/*@if (@_jscript_version >= 5) | 
| +    try | 
| +    { | 
| +        xmlHttp = new ActiveXObject("Msxml2.XMLHTTP"); | 
| +    } | 
| +    catch (e) | 
| +    { | 
| +        try | 
| +        { | 
| +            xmlHttp = new ActiveXObject("Microsoft.XMLHTTP"); | 
| +        } | 
| +        catch (e2) | 
| +        { | 
| +              xmlHttp = false; | 
| +        } | 
| +    } | 
| +@end @*/ | 
| + | 
| +    if (!xmlHttp && typeof XMLHttpRequest != 'undefined') | 
| +    { | 
| +        xmlHttp = new XMLHttpRequest(); | 
| +    } | 
| +    return xmlHttp; | 
| +} | 
| +function load_url_to_screen(url) | 
| +{ | 
| +    xmlhttp = multibrowser_ajax(); | 
| +    //window.XMLHttpRequest?new XMLHttpRequest(): new ActiveXObject("Microsoft.XMLHTTP"); | 
| +    xmlhttp.onreadystatechange = update_virtual_screen; | 
| +    xmlhttp.open("GET", url); | 
| +    xmlhttp.setRequestHeader("If-Modified-Since", "Sat, 1 Jan 2000 00:00:00 GMT"); | 
| +    xmlhttp.send(null); | 
| +} | 
| +function update_virtual_screen() | 
| +{ | 
| +    if ((xmlhttp.readyState == 4) && (xmlhttp.status == 200)) | 
| +    { | 
| +        var screen_text = xmlhttp.responseText; | 
| +        document.form["screen_text"].value = screen_text; | 
| +        //var json_data = json_parse(xmlhttp.responseText); | 
| +    } | 
| +} | 
| +function poll() | 
| +{ | 
| +    refresh_screen(); | 
| +    timerID  = setTimeout("poll()", 2000); | 
| +    // clearTimeout(timerID); | 
| +} | 
| +//function start_server (username, password) | 
| +//{ | 
| +//    load_url_to_screen('cgishell.cgi?ajax=serverstart&username=' + escape(username) + '&password=' + escape(password); | 
| +//} | 
| +function refresh_screen() | 
| +{ | 
| +    load_url_to_screen('cgishell.cgi?ajax=refresh&sid=%(SID)s'); | 
| +} | 
| +function query_hash() | 
| +{ | 
| +    load_url_to_screen('cgishell.cgi?ajax=hash&sid=%(SID)s'); | 
| +} | 
| +function query_cursor() | 
| +{ | 
| +    load_url_to_screen('cgishell.cgi?ajax=cursor&sid=%(SID)s'); | 
| +} | 
| +function exit_server() | 
| +{ | 
| +    load_url_to_screen('cgishell.cgi?ajax=exit&sid=%(SID)s'); | 
| +} | 
| +function type_key (chars) | 
| +{ | 
| +    var ch = '?'; | 
| +    if (flag_shiftlock || flag_shift) | 
| +    { | 
| +        ch = chars.substr(1,1); | 
| +    } | 
| +    else if (flag_ctrl) | 
| +    { | 
| +        ch = chars.substr(2,1); | 
| +    } | 
| +    else | 
| +    { | 
| +        ch = chars.substr(0,1); | 
| +    } | 
| +    load_url_to_screen('cgishell.cgi?ajax=send&sid=%(SID)s&arg=' + escape(ch)); | 
| +    if (flag_shift || flag_ctrl) | 
| +    { | 
| +        flag_shift = 0; | 
| +        flag_ctrl = 0; | 
| +    } | 
| +    update_button_colors(); | 
| +} | 
| + | 
| +function key_shiftlock() | 
| +{ | 
| +    flag_ctrl = 0; | 
| +    flag_shift = 0; | 
| +    if (flag_shiftlock) | 
| +    { | 
| +        flag_shiftlock = 0; | 
| +    } | 
| +    else | 
| +    { | 
| +        flag_shiftlock = 1; | 
| +    } | 
| +    update_button_colors(); | 
| +} | 
| + | 
| +function key_shift() | 
| +{ | 
| +    if (flag_shift) | 
| +    { | 
| +        flag_shift = 0; | 
| +    } | 
| +    else | 
| +    { | 
| +        flag_ctrl = 0; | 
| +        flag_shiftlock = 0; | 
| +        flag_shift = 1; | 
| +    } | 
| +    update_button_colors(); | 
| +} | 
| +function key_ctrl () | 
| +{ | 
| +    if (flag_ctrl) | 
| +    { | 
| +        flag_ctrl = 0; | 
| +    } | 
| +    else | 
| +    { | 
| +        flag_ctrl = 1; | 
| +        flag_shiftlock = 0; | 
| +        flag_shift = 0; | 
| +    } | 
| + | 
| +    update_button_colors(); | 
| +} | 
| +function update_button_colors () | 
| +{ | 
| +    if (flag_ctrl) | 
| +    { | 
| +        document.form['Ctrl'].style.backgroundColor = ButtonOnColor; | 
| +        document.form['Ctrl2'].style.backgroundColor = ButtonOnColor; | 
| +    } | 
| +    else | 
| +    { | 
| +        document.form['Ctrl'].style.backgroundColor = document.form.style.backgroundColor; | 
| +        document.form['Ctrl2'].style.backgroundColor = document.form.style.backgroundColor; | 
| +    } | 
| +    if (flag_shift) | 
| +    { | 
| +        document.form['Shift'].style.backgroundColor = ButtonOnColor; | 
| +        document.form['Shift2'].style.backgroundColor = ButtonOnColor; | 
| +    } | 
| +    else | 
| +    { | 
| +        document.form['Shift'].style.backgroundColor = document.form.style.backgroundColor; | 
| +        document.form['Shift2'].style.backgroundColor = document.form.style.backgroundColor; | 
| +    } | 
| +    if (flag_shiftlock) | 
| +    { | 
| +        document.form['ShiftLock'].style.backgroundColor = ButtonOnColor; | 
| +    } | 
| +    else | 
| +    { | 
| +        document.form['ShiftLock'].style.backgroundColor = document.form.style.backgroundColor; | 
| +    } | 
| + | 
| +} | 
| +function keyHandler(e) | 
| +{ | 
| +    var pressedKey; | 
| +    if (document.all)    { e = window.event; } | 
| +    if (document.layers) { pressedKey = e.which; } | 
| +    if (document.all)    { pressedKey = e.keyCode; } | 
| +    pressedCharacter = String.fromCharCode(pressedKey); | 
| +    type_key(pressedCharacter+pressedCharacter+pressedCharacter); | 
| +    alert(pressedCharacter); | 
| +//    alert(' Character = ' + pressedCharacter + ' [Decimal value = ' + pressedKey + ']'); | 
| +} | 
| +//document.onkeypress = keyHandler; | 
| +//if (document.layers) | 
| +//    document.captureEvents(Event.KEYPRESS); | 
| +//http://sniptools.com/jskeys | 
| +//document.onkeyup = KeyCheck; | 
| +function KeyCheck(e) | 
| +{ | 
| +    var KeyID = (window.event) ? event.keyCode : e.keyCode; | 
| +    type_key(String.fromCharCode(KeyID)); | 
| +    e.cancelBubble = true; | 
| +    window.event.cancelBubble = true; | 
| +} | 
| +</script> | 
| + | 
| +</head> | 
| + | 
| +<body onload="init()"> | 
| +<form id="form" name="form" action="/cgi-bin/cgishell.cgi" method="POST"> | 
| +<input name="sid" value="%(SID)s" type="hidden"> | 
| +<textarea name="screen_text" cols="81" rows="25">%(SHELL_OUTPUT)s</textarea> | 
| +<hr noshade="1"> | 
| + <input name="cli" id="cli" type="text" size="80"><br> | 
| +<table border="0" align="left"> | 
| +<tr> | 
| +<td width="86%%" align="center"> | 
| +    <input name="submit" type="submit" value="Submit"> | 
| +    <input name="refresh" type="button" value="REFRESH" onclick="refresh_screen()"> | 
| +    <input name="refresh" type="button" value="CURSOR" onclick="query_cursor()"> | 
| +    <input name="hash" type="button" value="HASH" onclick="query_hash()"> | 
| +    <input name="exit" type="button" value="EXIT" onclick="exit_server()"> | 
| +    <br> | 
| +    <input type="button" value="Esc" onclick="type_key('\\x1b\\x1b')" /> | 
| +    <input type="button" value="` ~" onclick="type_key('`~')" /> | 
| +    <input type="button" value="1!" onclick="type_key('1!')" /> | 
| +    <input type="button" value="2@" onclick="type_key('2@\\x00')" /> | 
| +    <input type="button" value="3#" onclick="type_key('3#')" /> | 
| +    <input type="button" value="4$" onclick="type_key('4$')" /> | 
| +    <input type="button" value="5%%" onclick="type_key('5%%')" /> | 
| +    <input type="button" value="6^" onclick="type_key('6^\\x1E')" /> | 
| +    <input type="button" value="7&" onclick="type_key('7&')" /> | 
| +    <input type="button" value="8*" onclick="type_key('8*')" /> | 
| +    <input type="button" value="9(" onclick="type_key('9(')" /> | 
| +    <input type="button" value="0)" onclick="type_key('0)')" /> | 
| +    <input type="button" value="-_" onclick="type_key('-_\\x1F')" /> | 
| +    <input type="button" value="=+" onclick="type_key('=+')" /> | 
| +    <input type="button" value="BkSp" onclick="type_key('\\x08\\x08\\x08')" /> | 
| +    <br> | 
| +    <input type="button" value="Tab" onclick="type_key('\\t\\t')" /> | 
| +    <input type="button" value="Q" onclick="type_key('qQ\\x11')" /> | 
| +    <input type="button" value="W" onclick="type_key('wW\\x17')" /> | 
| +    <input type="button" value="E" onclick="type_key('eE\\x05')" /> | 
| +    <input type="button" value="R" onclick="type_key('rR\\x12')" /> | 
| +    <input type="button" value="T" onclick="type_key('tT\\x14')" /> | 
| +    <input type="button" value="Y" onclick="type_key('yY\\x19')" /> | 
| +    <input type="button" value="U" onclick="type_key('uU\\x15')" /> | 
| +    <input type="button" value="I" onclick="type_key('iI\\x09')" /> | 
| +    <input type="button" value="O" onclick="type_key('oO\\x0F')" /> | 
| +    <input type="button" value="P" onclick="type_key('pP\\x10')" /> | 
| +    <input type="button" value="[ {" onclick="type_key('[{\\x1b')" /> | 
| +    <input type="button" value="] }" onclick="type_key(']}\\x1d')" /> | 
| +    <input type="button" value="\\ |" onclick="type_key('\\\\|\\x1c')" /> | 
| +    <br> | 
| +    <input type="button" id="Ctrl" value="Ctrl" onclick="key_ctrl()" /> | 
| +    <input type="button" value="A" onclick="type_key('aA\\x01')" /> | 
| +    <input type="button" value="S" onclick="type_key('sS\\x13')" /> | 
| +    <input type="button" value="D" onclick="type_key('dD\\x04')" /> | 
| +    <input type="button" value="F" onclick="type_key('fF\\x06')" /> | 
| +    <input type="button" value="G" onclick="type_key('gG\\x07')" /> | 
| +    <input type="button" value="H" onclick="type_key('hH\\x08')" /> | 
| +    <input type="button" value="J" onclick="type_key('jJ\\x0A')" /> | 
| +    <input type="button" value="K" onclick="type_key('kK\\x0B')" /> | 
| +    <input type="button" value="L" onclick="type_key('lL\\x0C')" /> | 
| +    <input type="button" value="; :" onclick="type_key(';:')" /> | 
| +    <input type="button" id="quote" value="'" onclick="type_key('\\x27\\x22')" /> | 
| +    <input type="button" value="Enter" onclick="type_key('\\n\\n')" /> | 
| +    <br> | 
| +    <input type="button" id="ShiftLock" value="Caps Lock" onclick="key_shiftlock()" /> | 
| +    <input type="button" id="Shift" value="Shift" onclick="key_shift()"  /> | 
| +    <input type="button" value="Z" onclick="type_key('zZ\\x1A')" /> | 
| +    <input type="button" value="X" onclick="type_key('xX\\x18')" /> | 
| +    <input type="button" value="C" onclick="type_key('cC\\x03')" /> | 
| +    <input type="button" value="V" onclick="type_key('vV\\x16')" /> | 
| +    <input type="button" value="B" onclick="type_key('bB\\x02')" /> | 
| +    <input type="button" value="N" onclick="type_key('nN\\x0E')" /> | 
| +    <input type="button" value="M" onclick="type_key('mM\\x0D')" /> | 
| +    <input type="button" value=", <" onclick="type_key(',<')" /> | 
| +    <input type="button" value=". >" onclick="type_key('.>')" /> | 
| +    <input type="button" value="/ ?" onclick="type_key('/?')" /> | 
| +    <input type="button" id="Shift2" value="Shift" onclick="key_shift()" /> | 
| +    <input type="button" id="Ctrl2" value="Ctrl" onclick="key_ctrl()" /> | 
| +    <br> | 
| +    <input type="button" value="        FINAL FRONTIER        " onclick="type_key('  ')" /> | 
| +</td> | 
| +</tr> | 
| +</table> | 
| +</form> | 
| +</body> | 
| +</html> | 
| +""" | 
| + | 
| +LOGIN_HTML="""<html> | 
| +<head> | 
| +<title>Shell Login</title> | 
| +<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> | 
| +<style type=text/css> | 
| +a {color: #9f9; text-decoration: none} | 
| +a:hover {color: #0f0} | 
| +hr {color: #0f0} | 
| +html,body,textarea,input,form | 
| +{ | 
| +font-family: "Courier New", Courier, mono; | 
| +font-size: 8pt; | 
| +color: #0c0; | 
| +background-color: #020; | 
| +margin:3; | 
| +padding:0; | 
| +border:0; | 
| +} | 
| +input { background-color: #010; } | 
| +input,textarea { | 
| +border-width:1; | 
| +border-style:solid; | 
| +border-color:#0c0; | 
| +padding:3; | 
| +margin:3; | 
| +} | 
| +</style> | 
| +<script language="JavaScript"> | 
| +function init () | 
| +{ | 
| +    document.login_form["username"].focus(); | 
| +} | 
| +</script> | 
| +</head> | 
| +<body onload="init()"> | 
| +<form name="login_form" method="POST"> | 
| +<input name="start_server" value="1" type="hidden"> | 
| +<input name="sid" value="%(SID)s" type="hidden"> | 
| +username: <input name="username" type="text" size="30"><br> | 
| +password: <input name="password" type="password" size="30"><br> | 
| +<input name="submit" type="submit" value="enter"> | 
| +</form> | 
| +<br> | 
| +</body> | 
| +</html> | 
| +""" | 
| + | 
| +if __name__ == "__main__": | 
| +    try: | 
| +        main() | 
| +    except Exception as e: | 
| +        print(str(e)) | 
| +        tb_dump = traceback.format_exc() | 
| +        print(str(tb_dump)) | 
| + | 
|  |