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

95 by mattgiuca
Moved some things out of www into their respective dirs, console and
1
#!/usr/bin/python
2
3
# usage:
4
#   python-console <port> <magic>
5
126 by drtomc
A basic version of the console going!
6
import sys
95 by mattgiuca
Moved some things out of www into their respective dirs, console and
7
import web
8
import md5
9
import codeop
10
import cjson
126 by drtomc
A basic version of the console going!
11
import cgi
12
import cStringIO
13
import signal
212 by drtomc
Gosh, it all looks pretty simple in the end!
14
import Queue
15
from threading import Thread
16
17
class StdinFromWeb(object):
18
    def __init__(self, cmdQ, lineQ):
19
        self.cmdQ = cmdQ
20
        self.lineQ = lineQ
21
22
    def readline(self):
23
        # stop the clock!
128 by drtomc
A couple of bug fixes.
24
        signal.alarm(0)
212 by drtomc
Gosh, it all looks pretty simple in the end!
25
        self.cmdQ.put({"input":None})
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
33
class PythonRunner(Thread):
34
    def __init__(self, cmdQ, lineQ):
35
        self.cmdQ = cmdQ
36
        self.lineQ = lineQ
37
        Thread.__init__(self)
38
39
    def run(self):
40
        globs = {}
41
        globs['__builtins__'] = globals()['__builtins__']
42
        locls = {}
43
        compiler = codeop.CommandCompiler()
95 by mattgiuca
Moved some things out of www into their respective dirs, console and
44
        curr_cmd = ''
45
212 by drtomc
Gosh, it all looks pretty simple in the end!
46
        while True:
47
            l = self.lineQ.get()
48
            if curr_cmd == '':
49
                curr_cmd = l
50
            else:
51
                curr_cmd = curr_cmd + '\n' + l
52
            try:
53
                cmd = compiler(curr_cmd)
54
                if cmd is None:
55
                    # The command was incomplete,
56
                    # so send back a None, so the
57
                    # client can print a '...'
58
                    self.cmdQ.put({"more":None})
59
                else:
60
                    # The command was complete,
61
                    # so evaluate it!
62
                    sys.stdin = StdinFromWeb(self.cmdQ, self.lineQ)
63
                    out = cStringIO.StringIO()
64
                    sys.stdout = out
65
                    sys.stderr = out
66
                    signal.alarm(5)
67
                    res = eval(cmd, globs, locls)
68
                    signal.alarm(0)
69
                    self.cmdQ.put({"okay":(out.getvalue(),res)})
70
                    curr_cmd = ''
71
            except Exception, exc:
72
                signal.alarm(0)
73
                self.cmdQ.put({"exc":str(exc)})
74
                curr_cmd = ''
75
95 by mattgiuca
Moved some things out of www into their respective dirs, console and
76
urls = (
77
    '/',            'index',
126 by drtomc
A basic version of the console going!
78
    '/index.html',  'index',
95 by mattgiuca
Moved some things out of www into their respective dirs, console and
79
    '/(.*\.js)',    'jscript',
80
    '/(.*\.css)',   'style',
81
    '/chat',        'chat')
82
83
# The global 'magic' is the secret that the client and server share
84
# which is used to create and md5 digest to authenticate requests.
85
# It is assigned a real value at startup.
86
magic = ''
87
88
class index:
89
    def GET(self):
90
        inp = web.input()
91
92
        # Authenticate
93
        digest = md5.new('hello' + magic).digest().encode('hex')
94
        if inp.digest != digest:
95
            web.ctx.status = '401 Unauthorized'
96
            return
97
98
        # Okay, so the authentication succeeded,
99
        # so all we need to do is send back the static
100
        # HTML for the console app.
101
        web.output(file("index.html", "r").read())
102
103
class jscript:
104
    def GET(self, name):
105
        web.output(file(name, "r").read())
106
107
class style:
108
    def GET(self, name):
109
        web.output(file(name, "r").read())
110
111
class chat:
212 by drtomc
Gosh, it all looks pretty simple in the end!
112
95 by mattgiuca
Moved some things out of www into their respective dirs, console and
113
    def POST(self):
114
        inp = web.input()
115
116
        # Authenticate
117
        digest = md5.new(inp.text + magic).digest().encode('hex')
118
        if inp.digest != digest:
119
            web.ctx.status = '401 Unauthorized'
120
            return
121
122
        # Okay, so the authentication succeeded,
123
        # so now we have the trivial matter of actually
124
        # executing the python....
212 by drtomc
Gosh, it all looks pretty simple in the end!
125
        lineQ.put(inp.text)
126
        r = cmdQ.get()
127
        sys.__stderr__.write(cjson.encode(r) + "\n")
128
        web.output(cjson.encode(r))
129
130
cmdQ = Queue.Queue()
131
lineQ = Queue.Queue()
132
interpThread = PythonRunner(cmdQ, lineQ)
95 by mattgiuca
Moved some things out of www into their respective dirs, console and
133
134
if __name__ == "__main__":
135
    # FIXME jail!
136
    magic = sys.argv[2]
212 by drtomc
Gosh, it all looks pretty simple in the end!
137
    interpThread.start()
95 by mattgiuca
Moved some things out of www into their respective dirs, console and
138
    web.run(urls, globals())