-
Notifications
You must be signed in to change notification settings - Fork 0
/
learning.py
243 lines (213 loc) · 9.76 KB
/
learning.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
r'''
learning.py
A Python 3 tutorial from https://www.liaoxuefeng.com
Usage:
$ python3 learning.py
'''
# check #######################################################################
import sys
from datetime import datetime
CERT_EXPIRES = '2020-08-07'
def check_version():
v = sys.version_info
if v.major == 3 and v.minor >= 6:
return
print('Your current python is %d.%d. Please use Python 3.6.' % (v.major, v.minor))
exit(1)
def check_cert():
today = datetime.now().strftime('%Y-%m-%d')
if today >= CERT_EXPIRES:
print('This learning.py is expired. Please download a newer version.')
exit(1)
check_version()
check_cert()
# start server ################################################################
import os, io, json, subprocess, tempfile, ssl
from urllib import parse
from http.server import HTTPServer, BaseHTTPRequestHandler, SimpleHTTPRequestHandler
EXEC = sys.executable
PORT = 39093
TEMP = tempfile.mkdtemp(suffix='_py', prefix='learn_python_')
HTML_INDEX = r'''
<html>
<head><title>Learning Python</title></head>
<body>
<form method="post" action="/run">
<textarea name="code" style="width:90%;height: 600px"></textarea>
<p><button type="submit">Run</button></p>
</form>
</body>
</html>
'''
class LearningHTTPRequestHandler(BaseHTTPRequestHandler):
def do_GET(self):
self.close_connection = True
if self.path != '/':
return self.send_error(404)
self._sendHttpHeader('text/html')
self._sendHttpBody(HTML_INDEX)
def do_POST(self):
self.close_connection = True
if self.path != '/run':
return self.send_error(400)
print('Prepare code...')
body = self.rfile.read(int(self.headers['Content-length']))
qs = parse.parse_qs(body.decode('utf-8'))
if not 'code' in qs:
return self.send_error(400)
code = qs['code'][0]
r = dict()
try:
fpath = write_py(get_name(), code)
print('Execute: %s %s' % (EXEC, fpath))
r['output'] = decode(subprocess.check_output([EXEC, fpath], stderr=subprocess.STDOUT, timeout=5))
except subprocess.CalledProcessError as e:
r = dict(error='Exception', output=decode(e.output))
except subprocess.TimeoutExpired as e:
r = dict(error='Timeout', output='执行超时')
except subprocess.CalledProcessError as e:
r = dict(error='Error', output='执行错误')
print('Execute done.')
self._sendHttpHeader()
self._sendHttpBody(r)
def _sendHttpHeader(self, contentType='application/json'):
origin = self.headers['Origin'] or 'https://www.liaoxuefeng.com'
self.send_response(200)
self.send_header('Content-Type', contentType)
self.send_header('Access-Control-Allow-Origin', origin)
self.send_header('Access-Control-Allow-Methods', 'GET,POST')
self.send_header('Access-Control-Max-Age', '86400')
self.end_headers()
def _sendHttpBody(self, data):
body = b''
if isinstance(data, bytes):
body = data
elif isinstance(data, str):
body = data.encode('utf-8', errors='ignore')
else:
body = json.dumps(data).encode('utf-8', errors='ignore')
self.wfile.write(body)
def main():
certfile = write_cert()
httpd = HTTPServer(('127.0.0.1', PORT), LearningHTTPRequestHandler)
httpd.socket = ssl.wrap_socket(httpd.socket, certfile=certfile, server_side=True)
print('Ready for Python code on port %d...' % PORT)
print('Press Ctrl + C to exit...')
httpd.serve_forever()
# functions ###################################################################
INDEX = 0
def get_name():
global INDEX
INDEX = INDEX + 1
return 'test_%d' % INDEX
def write_py(name, code):
fpath = os.path.join(TEMP, '%s.py' % name)
with open(fpath, 'w', encoding='utf-8') as f:
f.write(code)
print('Code wrote to: %s' % fpath)
return fpath
def decode(s):
try:
return s.decode('utf-8')
except UnicodeDecodeError:
return s.decode('gbk')
# certificate #################################################################
def write_cert():
fpath = os.path.join(TEMP, 'local.liaoxuefeng.com.pem')
with open(fpath, 'w', encoding='utf-8') as f:
f.write(CERT_DATA)
return fpath
CERT_DATA = r'''
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEArUtX5vRI7RsCBEN8sIPskQyLJhsXzxQ947dcH2so0uuCYodm
wkuKwMtjCvP5nnM2PRaJMSD3ke4OA2BdD+CWGFmoXdD8yJbAOh6da4boOi2Rh174
YlZLcpGBhbqprXlRC1Ip0jzW38y4dOW9m9L1QEALoHZ6vJG1sYouLEfPLubI9+bg
VO1WipHBebuT4OosivsJxBhNqe1dR7rCkCjV1v/iBmbJCujrH9rri12LmksL0HhW
7V5mccae07mao0tfu1esFeLqYWM7+heQ82qXwg1WfbztXWJkP088fPjFGWSAVcZS
9RzPEt/lC34If15AqSEr60zKDkQ1olU36YHO+wIDAQABAoIBAAGuaJ4VLPyelaCX
S7HmDcOt1KRxgIPMpU8SG9gy23S0aTxDJl7oibeWIZIHzO+vHCMalrPTJzkTZK++
sxhw1t6fRrq7nirktN0Q0qPU7WgxwfwyEoSDDtH/5xBLlSgu3veWUVE4sDhVTaLW
Cca7FLsOBAQyB2h7R2vUtImkcWD57c4kDH90hN8htl+KFhMrBctiRbzvcB2tk/xO
e46YJ1GSRQg3OQQGQJeDczAoGzsv20pYuvDmqlhrQC64Zxxz7nZfftbCztvuVoPj
RGLRm/wRXPjujqBXivePanxYLP4dUOa6/NK7J5uea41e3CHIPTk1id4G15Knkypv
vQcJ2/kCgYEA3LAwxc/+DR3uwbcM5ZWeFK+16LfR+fF/ZNtm2vHuN458ZpcbBELO
rhUmye30LE0wwSPgPtjkXQ2r2BZD9fzji2jIGaWtsSvigjhMGRWOhVtlfB5kBNx+
Kk3PjunOId+HodVvOQxxXWbljiLQCNG3di7r+7ojcsj+ruos7iBSZ5kCgYEAyQXO
rLx9WP+xoCu3OV1PD5LFcvb/x9R3xMzEsZGYh/s969bNHkPvT/4BFcMBVv8X0WdE
kY04YJd3m1XzmOXeTR7XSZhG0sekYRbnEl8aWyMTmuhtjXwPHYReTx9ZEl3oRTfY
lubd51QPnArwGD+E9+1i2uCNjbFiDOv/+Tedt7MCgYEAjfLeTD5OoM1CB2PgbcPg
3Flw3nFuJCCL2qms7ON0YFPL/IjxHbqDCkIcowHlbqFv3Ktgz8veh2QFxoX7zLuO
+Nq66pRAtpcNqMjhWbkd5PU2v7EkkGPq2vcVrE0DA5KtwRBx6/Xu7S8ENHp76VBL
ez8PFulRZ8GU35lMsRYlKvECgYEAl1tRBwyREK7NTj08IuwXuDEZi/tgEVTvrPVE
8DIg99n7AJTmMnCSQteMd5cxbhB6HYg0v6bmGQxS2Vm5JZmGbOjYzqfiQ5hgM14s
M8/5pz9c5pk0y3/qXZ4p6EdBKKweU+e9o7lGwYOwkRxHNOq2snpBoW3MBzDVE8eq
Hzp5/TMCgYAomXNpRtHcXt2VhJR0FefYOfj4n4cGAtg8/dNlJSzkhR6ad2KniCz1
KgedQRAsqRSh0UZgTTxPA5Y/zpAvmAHFB7fr9syWb1QSBBvgLWkzpUgaEEJBRjwu
s2urAziMIcPf+mZf9rFscD/JKYQo3fHSd/UWTSM0SkQNu7uHqcgN8g==
-----END RSA PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
MIIFkjCCBHqgAwIBAgIQAt7xtFqJsgRZGvKRMyO9njANBgkqhkiG9w0BAQsFADBy
MQswCQYDVQQGEwJDTjElMCMGA1UEChMcVHJ1c3RBc2lhIFRlY2hub2xvZ2llcywg
SW5jLjEdMBsGA1UECxMURG9tYWluIFZhbGlkYXRlZCBTU0wxHTAbBgNVBAMTFFRy
dXN0QXNpYSBUTFMgUlNBIENBMB4XDTE5MDYwOTAwMDAwMFoXDTIwMDgwNzEyMDAw
MFowIDEeMBwGA1UEAxMVbG9jYWwubGlhb3h1ZWZlbmcuY29tMIIBIjANBgkqhkiG
9w0BAQEFAAOCAQ8AMIIBCgKCAQEArUtX5vRI7RsCBEN8sIPskQyLJhsXzxQ947dc
H2so0uuCYodmwkuKwMtjCvP5nnM2PRaJMSD3ke4OA2BdD+CWGFmoXdD8yJbAOh6d
a4boOi2Rh174YlZLcpGBhbqprXlRC1Ip0jzW38y4dOW9m9L1QEALoHZ6vJG1sYou
LEfPLubI9+bgVO1WipHBebuT4OosivsJxBhNqe1dR7rCkCjV1v/iBmbJCujrH9rr
i12LmksL0HhW7V5mccae07mao0tfu1esFeLqYWM7+heQ82qXwg1WfbztXWJkP088
fPjFGWSAVcZS9RzPEt/lC34If15AqSEr60zKDkQ1olU36YHO+wIDAQABo4ICdDCC
AnAwHwYDVR0jBBgwFoAUf9OZ86BHDjEAVlYijrfMnt3KAYowHQYDVR0OBBYEFOe3
Dec5wHbk5Hf8h6l2DDHgHxHhMCAGA1UdEQQZMBeCFWxvY2FsLmxpYW94dWVmZW5n
LmNvbTAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUF
BwMCMEwGA1UdIARFMEMwNwYJYIZIAYb9bAECMCowKAYIKwYBBQUHAgEWHGh0dHBz
Oi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMwCAYGZ4EMAQIBMH0GCCsGAQUFBwEBBHEw
bzAhBggrBgEFBQcwAYYVaHR0cDovL29jc3AuZGNvY3NwLmNuMEoGCCsGAQUFBzAC
hj5odHRwOi8vY2FjZXJ0cy5kaWdpdGFsY2VydHZhbGlkYXRpb24uY29tL1RydXN0
QXNpYVRMU1JTQUNBLmNydDAJBgNVHRMEAjAAMIIBAwYKKwYBBAHWeQIEAgSB9ASB
8QDvAHUApLkJkLQYWBSHuxOizGdwCjw1mAT5G9+443fNDsgN3BAAAAFrOiI+ygAA
BAMARjBEAiAGlx0z2YTgQMyVva5eRZTnry0rUjPGCXWP1Y4/XgpO9wIgSBtIfCjH
GC+xLuvUOEQZAfnh6xoDFJ6urTk/tdkJ/BYAdgCHdb/nWXz4jEOZX73zbv9WjUdW
Nv9KtWDBtOr/XqCDDwAAAWs6Ij+WAAAEAwBHMEUCIQDNqJG+8r5IwXDOLHyfUkg8
XpkaMYjncE5mSMLwyprt1gIgLAilaTtP0zlar11n3LTVhz/XG8o5kUoFIgps/cDS
PN0wDQYJKoZIhvcNAQELBQADggEBAEPFPqZE03u06PZ9jMpoke4CXHF3iTBABuTA
//g6w7Pn/DlMuHs5OS2S4RXQs5QJfdLpS7TsYatYmfhDO+b13QuBM/09BFh+KXsJ
ITbS9omy8eB/IK+OGCIJwoj1psoU4tw/MO2sly5N8rgJgYytD1U0+BbDIhWY1jlK
lP3rTkV1OkoGfPFzjjqk5VIiNdGXqn/aeXMbycbyyyDGwhLmqMARWLiDvQLywwzu
cGxJS4s+oP4SIYVH+sfyG51fRSTIyqzI8tP1MNuPi1R6r88NijyQ+f/tQs8R3OB+
AHcthgqp6TI5qsN89vJzqD4NTBBrCcyU1PshW5rAjJelnJlmfIU=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIErjCCA5agAwIBAgIQBYAmfwbylVM0jhwYWl7uLjANBgkqhkiG9w0BAQsFADBh
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
QTAeFw0xNzEyMDgxMjI4MjZaFw0yNzEyMDgxMjI4MjZaMHIxCzAJBgNVBAYTAkNO
MSUwIwYDVQQKExxUcnVzdEFzaWEgVGVjaG5vbG9naWVzLCBJbmMuMR0wGwYDVQQL
ExREb21haW4gVmFsaWRhdGVkIFNTTDEdMBsGA1UEAxMUVHJ1c3RBc2lhIFRMUyBS
U0EgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCgWa9X+ph+wAm8
Yh1Fk1MjKbQ5QwBOOKVaZR/OfCh+F6f93u7vZHGcUU/lvVGgUQnbzJhR1UV2epJa
e+m7cxnXIKdD0/VS9btAgwJszGFvwoqXeaCqFoP71wPmXjjUwLT70+qvX4hdyYfO
JcjeTz5QKtg8zQwxaK9x4JT9CoOmoVdVhEBAiD3DwR5fFgOHDwwGxdJWVBvktnoA
zjdTLXDdbSVC5jZ0u8oq9BiTDv7jAlsB5F8aZgvSZDOQeFrwaOTbKWSEInEhnchK
ZTD1dz6aBlk1xGEI5PZWAnVAba/ofH33ktymaTDsE6xRDnW97pDkimCRak6CEbfe
3dXw6OV5AgMBAAGjggFPMIIBSzAdBgNVHQ4EFgQUf9OZ86BHDjEAVlYijrfMnt3K
AYowHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUwDgYDVR0PAQH/BAQD
AgGGMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjASBgNVHRMBAf8ECDAG
AQH/AgEAMDQGCCsGAQUFBwEBBCgwJjAkBggrBgEFBQcwAYYYaHR0cDovL29jc3Au
ZGlnaWNlcnQuY29tMEIGA1UdHwQ7MDkwN6A1oDOGMWh0dHA6Ly9jcmwzLmRpZ2lj
ZXJ0LmNvbS9EaWdpQ2VydEdsb2JhbFJvb3RDQS5jcmwwTAYDVR0gBEUwQzA3Bglg
hkgBhv1sAQIwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cuZGlnaWNlcnQuY29t
L0NQUzAIBgZngQwBAgEwDQYJKoZIhvcNAQELBQADggEBAK3dVOj5dlv4MzK2i233
lDYvyJ3slFY2X2HKTYGte8nbK6i5/fsDImMYihAkp6VaNY/en8WZ5qcrQPVLuJrJ
DSXT04NnMeZOQDUoj/NHAmdfCBB/h1bZ5OGK6Sf1h5Yx/5wR4f3TUoPgGlnU7EuP
ISLNdMRiDrXntcImDAiRvkh5GJuH4YCVE6XEntqaNIgGkRwxKSgnU3Id3iuFbW9F
UQ9Qqtb1GX91AJ7i4153TikGgYCdwYkBURD8gSVe8OAco6IfZOYt/TEwii1Ivi1C
qnuUlWpsF1LdQNIdfbW3TSe0BhQa7ifbVIfvPWHYOu3rkg1ZeMo6XRU9B4n5VyJY
RmE=
-----END CERTIFICATE-----
'''
# start main at last ##########################################################
if __name__ == '__main__':
main()