1""" 2Generates packet or reconstructed stream output as a HTML page. 3 4Based on colorout module originally written by amm 5""" 6 7from dshell.output.output import Output 8import dshell.util 9import dshell.core 10from xml.sax.saxutils import escape 11 12class HTMLOutput(Output): 13 _DESCRIPTION = "HTML format output" 14 _PACKET_FORMAT = """<h1>Packet %(counter)s (%(protocol)s)</h1><h2>Start: %(ts)s 15%(sip)s:%(sport)s -> %(dip)s:%(dport)s (%(bytes)s bytes) 16</h2> 17%(data)s 18""" 19 _CONNECTION_FORMAT = """<h1>Connection %(counter)s (%(protocol)s)</h1><h2>Start: %(starttime)s 20End: %(endtime)s 21%(clientip)s:%(clientport)s -> %(serverip)s:%(serverport)s (%(clientbytes)s bytes) 22%(serverip)s:%(serverport)s -> %(clientip)s:%(clientport)s (%(serverbytes)s bytes) 23</h2> 24%(data)s 25""" 26 _DEFAULT_FORMAT = _PACKET_FORMAT 27 _DEFAULT_DELIM = "<br />" 28 29 _HTML_HEADER = """ 30<html> 31<head> 32 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> 33 <title>Dshell Output</title> 34 <style> 35 body { 36 font-family: monospace; 37 font-size: 10pt; 38 white-space: pre; 39 } 40 h1 { 41 font-family: helvetica; 42 font-size: 13pt; 43 font-weight: bolder; 44 white-space: pre; 45 } 46 h2 { 47 font-family: helvetica; 48 font-size: 12pt; 49 font-weight: bolder; 50 margin: 0 0; 51 white-space: pre; 52 } 53 </style> 54</head> 55<body> 56""" 57 58 _HTML_FOOTER = """ 59</body> 60</html> 61""" 62 63 def __init__(self, *args, **kwargs): 64 "Can be called with an optional 'hex' argument to display output in hex" 65 super().__init__(*args, **kwargs) 66 self.counter = 1 67 self.colors = { 68 'cs': 'red', # client-to-server is red 69 'sc': 'green', # server-to-client is green 70 '--': 'blue', # everything else is blue 71 } 72 self.hexmode = kwargs.get('hex', False) 73 self.format_is_set = False 74 75 def setup(self): 76 self.fh.write(self._HTML_HEADER) 77 78 def write(self, *args, **kwargs): 79 if not self.format_is_set: 80 if 'clientip' in kwargs: 81 self.set_format(self._CONNECTION_FORMAT) 82 else: 83 self.set_format(self._PACKET_FORMAT) 84 self.format_is_set = True 85 86 # a template string for data output 87 colorformat = '<span style="color:%s;">%s</span>' 88 89 # Iterate over the args and try to parse out any raw data strings 90 rawdata = [] 91 for arg in args: 92 if type(arg) == dshell.core.Blob: 93 if arg.data: 94 rawdata.append((arg.data, arg.direction)) 95 elif type(arg) == dshell.core.Connection: 96 for blob in arg.blobs: 97 if blob.data: 98 rawdata.append((blob.data, blob.direction)) 99 elif type(arg) == dshell.core.Packet: 100 rawdata.append((arg.pkt.body_bytes, kwargs.get('direction', '--'))) 101 elif type(arg) == tuple: 102 rawdata.append(arg) 103 else: 104 rawdata.append((arg, kwargs.get('direction', '--'))) 105 106 # Clean up the rawdata into something more presentable 107 if self.hexmode: 108 cleanup_func = dshell.util.hex_plus_ascii 109 else: 110 cleanup_func = dshell.util.printable_text 111 for k, v in enumerate(rawdata): 112 newdata = cleanup_func(v[0]) 113 newdata = escape(newdata) 114 rawdata[k] = (newdata, v[1]) 115 116 # Convert the raw data strings into color-coded output 117 data = [] 118 for arg in rawdata: 119 datastring = colorformat % (self.colors.get(arg[1], ''), arg[0]) 120 data.append(datastring) 121 122 super().write(counter=self.counter, *data, **kwargs) 123 self.counter += 1 124 125 def close(self): 126 self.fh.write(self._HTML_FOOTER) 127 Output.close(self) 128 129obj = HTMLOutput 130