~azzar1/unity/add-show-desktop-key

« back to all changes in this revision

Viewing changes to console/python-console

  • Committer: mattgiuca
  • Date: 2008-01-29 02:57:10 UTC
  • Revision ID: svn-v3-trunk0:2b9c9e99-6f39-0410-b283-7f802c844ae2:trunk:322
Added doc/setup - a setup guide specific to our configuration. This is the
result of my successfully configuring IVLE on a production server.

Show diffs side-by-side

added added

removed removed

Lines of Context:
3
3
# usage:
4
4
#   python-console <port> <magic>
5
5
 
 
6
import sys
 
7
import web
 
8
import md5
 
9
import codeop
6
10
import cjson
7
 
import codeop
 
11
import cgi
8
12
import cStringIO
9
 
import md5
10
 
import os
 
13
import signal
11
14
import Queue
12
 
import signal
13
 
import socket
14
 
import sys
15
15
from threading import Thread
16
16
 
17
17
class StdinFromWeb(object):
23
23
        # stop the clock!
24
24
        signal.alarm(0)
25
25
        self.cmdQ.put({"input":None})
26
 
        ln = self.lineQ.get()
27
 
        if 'chat' in ln:
28
 
            # restart the clock:
29
 
            # Some of our 5 seconds may have elapsed, but never mind.
30
 
            signal.alarm(5)
31
 
            return ln['chat']
 
26
        l = self.lineQ.get()
 
27
        # restart the clock:
 
28
        # Some of our 5 seconds may have elapsed, but
 
29
        # never mind.
 
30
        signal.alarm(5)
 
31
        return l
32
32
 
33
33
class PythonRunner(Thread):
34
34
    def __init__(self, cmdQ, lineQ):
35
35
        self.cmdQ = cmdQ
36
36
        self.lineQ = lineQ
37
 
        self.out = cStringIO.StringIO()
38
37
        Thread.__init__(self)
39
38
 
40
 
    def execCmd(self, cmd):
41
 
        try:
42
 
            sys.stdin = StdinFromWeb(self.cmdQ, self.lineQ)
43
 
            sys.stdout = self.out
44
 
            sys.stderr = self.out
45
 
            signal.alarm(5)
46
 
            res = eval(cmd, self.globs, self.locls)
47
 
            signal.alarm(0)
48
 
            self.cmdQ.put({"okay":(self.out.getvalue(),res)})
49
 
            self.curr_cmd = ''
50
 
            self.out = cStringIO.StringIO()
51
 
        except Exception, exc:
52
 
            signal.alarm(0)
53
 
            self.cmdQ.put({"exc":(self.out.getvalue(),str(exc))})
54
 
            self.curr_cmd = ''
55
 
            self.out = cStringIO.StringIO()
56
 
 
57
39
    def run(self):
58
40
        self.init_state()
59
41
        compiler = codeop.CommandCompiler()
60
42
 
61
43
        while True:
62
 
            ln = self.lineQ.get()
63
 
            if 'chat' in ln:
64
 
                if self.curr_cmd == '':
65
 
                    self.curr_cmd = ln['chat']
 
44
            l = self.lineQ.get()
 
45
            if self.curr_cmd == '':
 
46
                self.curr_cmd = l
 
47
            else:
 
48
                self.curr_cmd = self.curr_cmd + '\n' + l
 
49
            try:
 
50
                cmd = compiler(self.curr_cmd)
 
51
                if cmd is None:
 
52
                    # The command was incomplete,
 
53
                    # so send back a None, so the
 
54
                    # client can print a '...'
 
55
                    self.cmdQ.put({"more":None})
66
56
                else:
67
 
                    self.curr_cmd = self.curr_cmd + '\n' + ln['chat']
68
 
                try:
69
 
                    cmd = compiler(self.curr_cmd)
70
 
                    if cmd is None:
71
 
                        # The command was incomplete,
72
 
                        # so send back a None, so the
73
 
                        # client can print a '...'
74
 
                        self.cmdQ.put({"more":None})
75
 
                    else:
76
 
                        self.execCmd(cmd)
77
 
                except Exception, exc:
78
 
                    signal.alarm(0)
79
 
                    self.cmdQ.put({"exc":(self.out.getvalue(),str(exc))})
80
 
                    self.curr_cmd = ''
81
 
                    self.out = cStringIO.StringIO()
82
 
            if 'block' in ln:
83
 
                # throw away a partial command.
84
 
                try:
85
 
                    cmd = compile(ln['block'], "<web session>", 'exec');
86
 
                    self.execCmd(cmd)
87
 
                except Exception, exc:
88
 
                    signal.alarm(0)
89
 
                    self.cmdQ.put({"exc":(self.out.getvalue(),str(exc))})
90
 
                    self.curr_cmd = ''
91
 
                    self.out = cStringIO.StringIO()
 
57
                    # The command was complete,
 
58
                    # so evaluate it!
 
59
                    sys.stdin = StdinFromWeb(self.cmdQ, self.lineQ)
 
60
                    out = cStringIO.StringIO()
 
61
                    sys.stdout = out
 
62
                    sys.stderr = out
 
63
                    signal.alarm(5)
 
64
                    res = eval(cmd, globs, locls)
 
65
                    signal.alarm(0)
 
66
                    self.cmdQ.put({"okay":(out.getvalue(),res)})
 
67
                    curr_cmd = ''
 
68
            except Exception, exc:
 
69
                signal.alarm(0)
 
70
                self.cmdQ.put({"exc":str(exc)})
 
71
                curr_cmd = ''
92
72
 
93
73
    def init_state(self):
94
74
        self.globs = {}
96
76
        self.locls = {}
97
77
        self.curr_cmd = ''
98
78
 
99
 
def daemonize():
100
 
    if os.fork():   # launch child and...
101
 
        os._exit(0) # kill off parent
102
 
    os.setsid()
103
 
    if os.fork():   # launch child and...
104
 
        os._exit(0) # kill off parent again.
105
 
    os.umask(077)
 
79
urls = (
 
80
    '/',            'index',
 
81
    '/index.html',  'index',
 
82
    '/(.*\.js)',    'jscript',
 
83
    '/(.*\.css)',   'style',
 
84
    '/chat',        'chat')
106
85
 
107
86
# The global 'magic' is the secret that the client and server share
108
87
# which is used to create and md5 digest to authenticate requests.
109
88
# It is assigned a real value at startup.
110
89
magic = ''
111
90
 
 
91
class index:
 
92
    def GET(self):
 
93
        inp = web.input()
 
94
 
 
95
        # Authenticate
 
96
        digest = md5.new('hello' + magic).digest().encode('hex')
 
97
        if inp.digest != digest:
 
98
            web.ctx.status = '401 Unauthorized'
 
99
            return
 
100
 
 
101
        # Okay, so the authentication succeeded,
 
102
        # so all we need to do is send back the static
 
103
        # HTML for the console app.
 
104
        web.output(file("index.html", "r").read())
 
105
 
 
106
class jscript:
 
107
    def GET(self, name):
 
108
        web.output(file(name, "r").read())
 
109
 
 
110
class style:
 
111
    def GET(self, name):
 
112
        web.output(file(name, "r").read())
 
113
 
 
114
class chat:
 
115
 
 
116
    def POST(self):
 
117
        inp = web.input()
 
118
 
 
119
        # Authenticate
 
120
        digest = md5.new(inp.text + magic).digest().encode('hex')
 
121
        if inp.digest != digest:
 
122
            web.output("401 Unauthorized")
 
123
            web.ctx.status = '401 Unauthorized'
 
124
            return
 
125
 
 
126
        # Okay, so the authentication succeeded,
 
127
        # so now we have the trivial matter of actually
 
128
        # executing the python....
 
129
        lineQ.put(inp.text)
 
130
        r = cmdQ.get()
 
131
        sys.__stderr__.write(cjson.encode(r) + "\n")
 
132
        web.output(cjson.encode(r))
 
133
 
112
134
cmdQ = Queue.Queue()
113
135
lineQ = Queue.Queue()
114
136
interpThread = PythonRunner(cmdQ, lineQ)
115
137
 
116
138
if __name__ == "__main__":
117
 
    port = int(sys.argv[1])
118
139
    magic = sys.argv[2]
119
 
 
120
 
    # Attempt to open the socket.
121
 
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
122
 
    s.bind(('', port))
123
 
    s.listen(1)
124
 
 
125
 
    # Excellent! It worked. Let's turn ourself into a daemon,
126
 
    # then get on with the job of being a python interpreter.
127
 
    daemonize()
128
 
 
129
140
    interpThread.setDaemon(True)
130
141
    interpThread.start()
131
 
 
132
 
    while True:
133
 
        (conn, addr) = s.accept()
134
 
        try:
135
 
            # Grab the input
136
 
            buf = cStringIO.StringIO()
137
 
            blk = conn.recv(1024)
138
 
            while blk:
139
 
                buf.write(blk)
140
 
                try:
141
 
                    blk = conn.recv(1024, socket.MSG_DONTWAIT)
142
 
                except:
143
 
                    # Exception thrown if it WOULD block (but we
144
 
                    # told it not to wait) - ie. we are done
145
 
                    blk = None
146
 
            inp = buf.getvalue()
147
 
            msg = cjson.decode(inp)
148
 
            
149
 
            # Check that the message is 
150
 
            digest = md5.new(msg['text'] + magic).digest().encode('hex')
151
 
            if msg['digest'] != digest:
152
 
                conn.close()
153
 
                continue
154
 
 
155
 
            lineQ.put({msg['cmd']:msg['text']})
156
 
            r = cmdQ.get()
157
 
            conn.sendall(cjson.encode(r))
158
 
            conn.close()
159
 
        except Exception, e:
160
 
            conn.close()
 
142
    web.run(urls, globals())