# coding: utf-8 from argparse import ArgumentParser, FileType from contextlib import closing from io import open as copen from json import dumps from math import ceil import datetime import time import re import os from os.path import basename, dirname, exists, join from struct import unpack from subprocess import Popen from sys import platform, prefix, stderr from tempfile import NamedTemporaryFile from jinja2 import FileSystemLoader, Template from jinja2.environment import Environment from jumpserver.api import BASE_DIR, logger from jlog.models import Log DEFAULT_TEMPLATE = join(BASE_DIR, 'templates', 'jlog', 'static.jinja2') rz_pat = re.compile(r'\x18B\w+\r\x8a(\x11)?') def escapeString(string): string = rz_pat.sub('', string) try: string = string.encode('unicode_escape').decode('utf-8', 'ignore') except (UnicodeEncodeError, UnicodeDecodeError): string = string.decode('utf-8', 'ignore') string = string.replace("'", "\\'") string = '\'' + string + '\'' return string def getTiming(timef): timing = None with closing(timef): timing = [l.strip().split(' ') for l in timef] timing = [(int(ceil(float(r[0]) * 1000)), int(r[1])) for r in timing] return timing def scriptToJSON(scriptf, timing=None): ret = [] with closing(scriptf): scriptf.readline() # ignore first header line from script file offset = 0 for t in timing: dt = scriptf.read(t[1]) data = escapeString(dt) # print ('###### (%s, %s)' % (t[1], repr(data))) offset += t[0] ret.append((data, offset)) return dumps(ret) def renderTemplate(script_path, time_file_path, dimensions=(24, 80), templatename=DEFAULT_TEMPLATE): with copen(script_path, encoding='utf-8', errors='replace', newline='\r\n') as scriptf: # with open(script_path) as scriptf: with open(time_file_path) as timef: timing = getTiming(timef) json = scriptToJSON(scriptf, timing) fsl = FileSystemLoader(dirname(templatename), 'utf-8') e = Environment() e.loader = fsl templatename = basename(templatename) rendered = e.get_template(templatename).render(json=json, dimensions=dimensions) return rendered def renderJSON(script_path, time_file_path): with copen(script_path, encoding='utf-8', errors='replace', newline='\r\n') as scriptf: # with open(script_path) as scriptf: with open(time_file_path) as timef: timing = getTiming(timef) ret = {} with closing(scriptf): scriptf.readline() # ignore first header line from script file offset = 0 for t in timing: dt = scriptf.read(t[1]) offset += t[0] ret[str(offset/float(1000))] = dt.decode('utf-8', 'replace') return dumps(ret) def kill_invalid_connection(): unfinished_logs = Log.objects.filter(is_finished=False) now = datetime.datetime.now() now_timestamp = int(time.mktime(now.timetuple())) for log in unfinished_logs: try: log_file_mtime = int(os.stat('%s.log' % log.log_path).st_mtime) except OSError: log_file_mtime = 0 if (now_timestamp - log_file_mtime) > 3600: if log.login_type == 'ssh': try: os.kill(int(log.pid), 9) except OSError: pass elif (now - log.start_time).days < 1: continue log.is_finished = True log.end_time = now log.save() logger.warn('kill log %s' % log.log_path)