aboutsummaryrefslogtreecommitdiff
path: root/third_party/Python/module/pexpect-2.4/examples/cgishell.cgi
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/Python/module/pexpect-2.4/examples/cgishell.cgi')
-rw-r--r--third_party/Python/module/pexpect-2.4/examples/cgishell.cgi762
1 files changed, 762 insertions, 0 deletions
diff --git a/third_party/Python/module/pexpect-2.4/examples/cgishell.cgi b/third_party/Python/module/pexpect-2.4/examples/cgishell.cgi
new file mode 100644
index 000000000000..1e3affc1cab6
--- /dev/null
+++ b/third_party/Python/module/pexpect-2.4/examples/cgishell.cgi
@@ -0,0 +1,762 @@
+#!/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.
+"""
+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, 0777)
+ 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()
+ except OSError, e:
+ raise Exception, "%s [%d]" % (e.strerror, e.errno)
+
+ if pid != 0: # The first child.
+ 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, 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 xrange(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 form.has_key('ajax'):
+ 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 not form.has_key('sid'):
+ SID=random_sid()
+ print LOGIN_HTML % locals();
+ else:
+ SID=form['sid'].value
+ if form.has_key('start_server'):
+ 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 form.has_key('cli'):
+ 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, 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">
+&nbsp;<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, e:
+ print str(e)
+ tb_dump = traceback.format_exc()
+ print str(tb_dump)
+