16 |
16 |
import os
|
17 |
17 |
import re
|
18 |
18 |
import json
|
|
19 |
import signal
|
19 |
20 |
import subprocess
|
20 |
21 |
import logging
|
21 |
|
import multiprocessing
|
22 |
22 |
|
23 |
23 |
from django.conf import settings
|
24 |
24 |
|
... | ... | |
29 |
29 |
logger = logging.getLogger(__name__)
|
30 |
30 |
|
31 |
31 |
|
|
32 |
class Timeout(object):
|
|
33 |
|
|
34 |
class TimeoutError(Exception):
|
|
35 |
pass
|
|
36 |
|
|
37 |
def __init__(self, timeout):
|
|
38 |
self.timeout = timeout
|
|
39 |
|
|
40 |
def __enter__(self):
|
|
41 |
signal.signal(signal.SIGALRM, self.raise_timeout)
|
|
42 |
signal.alarm(self.timeout)
|
|
43 |
|
|
44 |
def __exit__(self, *args):
|
|
45 |
signal.alarm(0)
|
|
46 |
|
|
47 |
def raise_timeout(self, *args):
|
|
48 |
raise Timeout.TimeoutError
|
|
49 |
|
|
50 |
|
32 |
51 |
def exec_phantom(data, script='do_login.js'):
|
33 |
52 |
|
34 |
|
def run(send_end):
|
35 |
|
phantom = subprocess.Popen([
|
36 |
|
settings.PHANTOM_JS_BINARY,
|
37 |
|
'--ignore-ssl-errors=yes', '--ssl-protocol=any',
|
38 |
|
os.path.join(settings.BASE_DIR, 'mandayejs', script)],
|
39 |
|
close_fds=True,
|
40 |
|
stdin=subprocess.PIPE,
|
41 |
|
stdout=subprocess.PIPE
|
42 |
|
)
|
43 |
|
stdout, stderr = phantom.communicate(json.dumps(data))
|
44 |
|
|
45 |
|
try:
|
46 |
|
output = re.search('<mandayejs>(.*?)</mandayejs>', stdout, re.DOTALL)
|
47 |
|
if not output:
|
48 |
|
raise ValueError
|
49 |
|
stdout = output.group(1)
|
50 |
|
result = json.loads(stdout)
|
51 |
|
except (ValueError,):
|
52 |
|
result = {"result": "json_error"}
|
53 |
|
logger.error("invalid json: %s" % stdout)
|
54 |
|
|
55 |
|
if result.get('stderr'):
|
56 |
|
logger.warning(result['stderr'])
|
57 |
|
if result.get('error'):
|
58 |
|
logger.error('Error occured: %s' % result.get('reason'))
|
59 |
|
|
60 |
|
send_end.send(result)
|
61 |
|
|
62 |
|
recv_end, send_end = multiprocessing.Pipe(False)
|
63 |
|
process = multiprocessing.Process(target=run, args=(send_end,))
|
64 |
|
process.start()
|
65 |
|
process.join(settings.PHANTOM_JS_TIMEOUT)
|
66 |
|
|
67 |
|
if process.is_alive():
|
68 |
|
process.terminate()
|
|
53 |
phantom = subprocess.Popen([
|
|
54 |
settings.PHANTOM_JS_BINARY,
|
|
55 |
'--ignore-ssl-errors=yes', '--ssl-protocol=any',
|
|
56 |
os.path.join(settings.BASE_DIR, 'mandayejs', script)],
|
|
57 |
close_fds=True,
|
|
58 |
stdin=subprocess.PIPE,
|
|
59 |
stdout=subprocess.PIPE
|
|
60 |
)
|
|
61 |
|
|
62 |
# terminate subprocess if timeout
|
|
63 |
try:
|
|
64 |
with Timeout(settings.PHANTOM_JS_TIMEOUT):
|
|
65 |
stdout, stderr = phantom.communicate(json.dumps(data))
|
|
66 |
except (Timeout.TimeoutError,):
|
69 |
67 |
# Don't log locators, they may contain credentials (passwords)
|
|
68 |
phantom.terminate()
|
70 |
69 |
context = {k: v for k, v in data.items() if k != 'locators'}
|
71 |
70 |
logger.error("PhantomJS process timeout, context: %s" % context)
|
72 |
|
result = {'result': 'timeout'}
|
73 |
|
else:
|
74 |
|
result = recv_end.recv()
|
|
71 |
return {'result': 'timeout'}
|
|
72 |
|
|
73 |
try:
|
|
74 |
output = re.search('<mandayejs>(.*?)</mandayejs>', stdout, re.DOTALL)
|
|
75 |
if not output:
|
|
76 |
raise ValueError
|
|
77 |
stdout = output.group(1)
|
|
78 |
result = json.loads(stdout)
|
|
79 |
except (ValueError,):
|
|
80 |
result = {"result": "json_error"}
|
|
81 |
logger.error("invalid json: %s" % stdout)
|
|
82 |
|
|
83 |
if result.get('stderr'):
|
|
84 |
logger.warning(result['stderr'])
|
|
85 |
if result.get('error'):
|
|
86 |
logger.error('Error occured: %s' % result.get('reason'))
|
75 |
87 |
|
76 |
88 |
return result
|
77 |
89 |
|