Commit 0d8d1a28b46abbb4e5c3a3dfc8b8bd62f071de99

Authored by decalage2
1 parent 0acaf934

mraptor3: import tablestream, removed tablestream3

oletools/mraptor3.py
@@ -66,7 +66,7 @@ import sys, logging, optparse, re @@ -66,7 +66,7 @@ import sys, logging, optparse, re
66 from thirdparty.xglob import xglob 66 from thirdparty.xglob import xglob
67 67
68 # import the python 3 version of tablestream: 68 # import the python 3 version of tablestream:
69 -from thirdparty.tablestream import tablestream3 as tablestream 69 +from thirdparty.tablestream import tablestream
70 70
71 # import the python 3 version of olevba 71 # import the python 3 version of olevba
72 import olevba3 as olevba 72 import olevba3 as olevba
oletools/thirdparty/tablestream/tablestream3.py deleted
1 -#!/usr/bin/env python  
2 -"""  
3 -tablestream  
4 -  
5 -tablestream can format table data for pretty printing as text,  
6 -to be displayed on the console or written to any file-like object.  
7 -The table data can be provided as rows, each row is an iterable of  
8 -cells. The text in each cell is wrapped to fit into a maximum width  
9 -set for each column.  
10 -Contrary to many table pretty printing libraries, TableStream writes  
11 -each row to the output as soon as it is provided, and the whole table  
12 -does not need to be built in memory before printing.  
13 -It is therefore suitable for large tables, or tables that take time to  
14 -be processed row by row.  
15 -  
16 -Author: Philippe Lagadec - http://www.decalage.info  
17 -License: BSD, see source code or documentation  
18 -"""  
19 -  
20 -#=== LICENSE ==================================================================  
21 -  
22 -# tablestream is copyright (c) 2015-2016 Philippe Lagadec (http://www.decalage.info)  
23 -# All rights reserved.  
24 -#  
25 -# Redistribution and use in source and binary forms, with or without modification,  
26 -# are permitted provided that the following conditions are met:  
27 -#  
28 -# * Redistributions of source code must retain the above copyright notice, this  
29 -# list of conditions and the following disclaimer.  
30 -# * Redistributions in binary form must reproduce the above copyright notice,  
31 -# this list of conditions and the following disclaimer in the documentation  
32 -# and/or other materials provided with the distribution.  
33 -#  
34 -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND  
35 -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED  
36 -# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE  
37 -# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE  
38 -# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL  
39 -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR  
40 -# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER  
41 -# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,  
42 -# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE  
43 -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  
44 -  
45 -from __future__ import print_function  
46 -  
47 -#------------------------------------------------------------------------------  
48 -# CHANGELOG:  
49 -# 2015-11-01 v0.01 PL: - first version  
50 -# 2016-01-01 v0.02 PL: - added styles, color support  
51 -# 2016-04-19 v0.03 PL: - enable colorclass on Windows, fixed issue #39  
52 -# 2016-05-25 v0.04 PL: - updated for colorclass 2.2.0 (now a package)  
53 -# 2016-07-29 v0.05 PL: - fixed oletools issue #57, bug when importing colorclass  
54 -# 2016-07-31 v0.06 PL: - handle newline characters properly in each cell  
55 -  
56 -__version__ = '0.06'  
57 -  
58 -#------------------------------------------------------------------------------  
59 -# TODO:  
60 -# - several styles  
61 -# - colorized rows or cells  
62 -# - automatic width for the last column, based on max total width  
63 -# - automatic width for selected columns, based on N first lines  
64 -# - determine the console width  
65 -  
66 -# === IMPORTS =================================================================  
67 -  
68 -import textwrap  
69 -import sys, os  
70 -  
71 -# add the thirdparty subfolder to sys.path (absolute+normalized path):  
72 -_thismodule_dir = os.path.normpath(os.path.abspath(os.path.dirname(__file__)))  
73 -# print('_thismodule_dir = %r' % _thismodule_dir)  
74 -# assumption: this module is in a subfolder of thirdparty:  
75 -_thirdparty_dir = os.path.normpath(os.path.join(_thismodule_dir, '..'))  
76 -# print('_thirdparty_dir = %r' % _thirdparty_dir)  
77 -if not _thirdparty_dir in sys.path:  
78 - sys.path.insert(0, _thirdparty_dir)  
79 -  
80 -import colorclass  
81 -  
82 -# On Windows, colorclass needs to be enabled:  
83 -if os.name == 'nt':  
84 - colorclass.Windows.enable(auto_colors=True)  
85 -  
86 -  
87 -# === CLASSES =================================================================  
88 -  
89 -  
90 -class TableStyle(object):  
91 - """  
92 - Style for a TableStream.  
93 - This base class can be derived to create new styles.  
94 - Default style:  
95 - +------+---+  
96 - |Header| +  
97 - +------+---+  
98 - | | |  
99 - +------+---+  
100 - """  
101 - # Header rows:  
102 - header_top = True  
103 - header_top_left = '+'  
104 - header_top_horiz = '-'  
105 - header_top_middle = '+'  
106 - header_top_right = '+'  
107 -  
108 - header_vertical_left = '|'  
109 - header_vertical_middle = '|'  
110 - header_vertical_right = '|'  
111 -  
112 - # Separator line between header and normal rows:  
113 - header_sep = True  
114 - header_sep_left = '+'  
115 - header_sep_horiz = '-'  
116 - header_sep_middle = '+'  
117 - header_sep_right = '+'  
118 -  
119 - # Top row if there is no header:  
120 - noheader_top = True  
121 - noheader_top_left = '+'  
122 - noheader_top_horiz = '-'  
123 - noheader_top_middle = '+'  
124 - noheader_top_right = '+'  
125 -  
126 - # Normal rows  
127 - vertical_left = '|'  
128 - vertical_middle = '|'  
129 - vertical_right = '|'  
130 -  
131 - # Separator line between rows:  
132 - sep = False  
133 - sep_left = '+'  
134 - sep_horiz = '-'  
135 - sep_middle = '+'  
136 - sep_right = '+'  
137 -  
138 - # Bottom line  
139 - bottom = True  
140 - bottom_left = '+'  
141 - bottom_horiz = '-'  
142 - bottom_middle = '+'  
143 - bottom_right = '+'  
144 -  
145 -  
146 -class TableStyleSlim(object):  
147 - """  
148 - Style for a TableStream.  
149 - Example:  
150 - ------+---  
151 - Header|  
152 - ------+---  
153 - |  
154 - ------+---  
155 - """  
156 - # Header rows:  
157 - header_top = True  
158 - header_top_left = ''  
159 - header_top_horiz = '-'  
160 - header_top_middle = '+'  
161 - header_top_right = ''  
162 -  
163 - header_vertical_left = ''  
164 - header_vertical_middle = '|'  
165 - header_vertical_right = ''  
166 -  
167 - # Separator line between header and normal rows:  
168 - header_sep = True  
169 - header_sep_left = ''  
170 - header_sep_horiz = '-'  
171 - header_sep_middle = '+'  
172 - header_sep_right = ''  
173 -  
174 - # Top row if there is no header:  
175 - noheader_top = True  
176 - noheader_top_left = ''  
177 - noheader_top_horiz = '-'  
178 - noheader_top_middle = '+'  
179 - noheader_top_right = ''  
180 -  
181 - # Normal rows  
182 - vertical_left = ''  
183 - vertical_middle = '|'  
184 - vertical_right = ''  
185 -  
186 - # Separator line between rows:  
187 - sep = False  
188 - sep_left = ''  
189 - sep_horiz = '-'  
190 - sep_middle = '+'  
191 - sep_right = ''  
192 -  
193 - # Bottom line  
194 - bottom = True  
195 - bottom_left = ''  
196 - bottom_horiz = '-'  
197 - bottom_middle = '+'  
198 - bottom_right = ''  
199 -  
200 -  
201 -  
202 -class TableStream(object):  
203 - """  
204 - a TableStream object can format table data for pretty printing as text,  
205 - to be displayed on the console or written to any file-like object.  
206 - The table data can be provided as rows, each row is an iterable of  
207 - cells. The text in each cell is wrapped to fit into a maximum width  
208 - set for each column.  
209 - Contrary to many table pretty printing libraries, TableStream writes  
210 - each row to the output as soon as it is provided, and the whole table  
211 - does not need to be built in memory before printing.  
212 - It is therefore suitable for large tables, or tables that take time to  
213 - be processed row by row.  
214 - """  
215 -  
216 - def __init__(self, column_width, header_row=None, style=TableStyle, outfile=sys.stdout):  
217 - self.column_width = column_width  
218 - self.num_columns = len(column_width)  
219 - self.header_row = header_row  
220 - assert (header_row is None) or len(header_row) == self.num_columns  
221 - self.style = style  
222 - self.outfile = outfile  
223 - if header_row is not None:  
224 - self.write_header()  
225 - elif self.style.noheader_top:  
226 - self.write_noheader_top()  
227 -  
228 -  
229 - def write(self, s):  
230 - """  
231 - shortcut for self.outfile.write()  
232 - """  
233 - self.outfile.write(s)  
234 -  
235 - def write_row(self, row, last=False, colors=None):  
236 - assert len(row) == self.num_columns  
237 - columns = []  
238 - max_lines = 0  
239 - for i in range(self.num_columns):  
240 - cell = row[i]  
241 - # Convert to string:  
242 - # TODO: handle unicode properly  
243 - # TODO: use only unicode for textwrapper, to avoid str length issues  
244 - if isinstance(cell, bytes):  
245 - # encode to UTF8, avoiding errors  
246 - cell = cell.decode('utf-8', errors='replace')  
247 - else:  
248 - cell = cell  
249 - # Wrap cell text according to the column width  
250 - # TODO: use a TextWrapper object for each column instead  
251 - # split the string if it contains newline characters, otherwise  
252 - # textwrap replaces them with spaces:  
253 - column = []  
254 - for line in cell.splitlines():  
255 - column.extend(textwrap.wrap(line, width=self.column_width[i]))  
256 - # apply colors to each line of the cell if needed:  
257 - if colors is not None and self.outfile.isatty():  
258 - color = colors[i]  
259 - if color:  
260 - for j in range(len(column)):  
261 - # print '%r: %s' % (column[j], type(column[j]))  
262 - column[j] = colorclass.Color('{auto%s}%s{/%s}' % (color, column[j], color))  
263 - columns.append(column)  
264 - # determine which column has the highest number of lines  
265 - max_lines = max(len(columns[i]), max_lines)  
266 - # transpose: write output line by line  
267 - for j in range(max_lines):  
268 - self.write(self.style.vertical_left)  
269 - for i in range(self.num_columns):  
270 - column = columns[i]  
271 - if j<len(column):  
272 - # text to be written  
273 - text_width = len(column[j])  
274 - self.write(column[j] + ' '*(self.column_width[i]-text_width))  
275 - else:  
276 - # no more lines for this column  
277 - # TODO: precompute empty cells once  
278 - self.write(' '*(self.column_width[i]))  
279 - if i < (self.num_columns - 1):  
280 - self.write(self.style.vertical_middle)  
281 - self.write(self.style.vertical_right)  
282 - self.write('\n')  
283 - if self.style.sep and not last:  
284 - self.write_sep()  
285 -  
286 - def make_line(self, left, horiz, middle, right):  
287 - """  
288 - build a line based on the provided elements  
289 - example: '+---+--+-------+'  
290 - :param left:  
291 - :param horiz:  
292 - :param middle:  
293 - :param right:  
294 - :return:  
295 - """  
296 - return left + middle.join([horiz * width for width in self.column_width]) + right + '\n'  
297 -  
298 - def write_header_top(self):  
299 - s = self.style  
300 - line = self.make_line(left=s.header_top_left, horiz=s.header_top_horiz,  
301 - middle=s.header_top_middle, right=s.header_top_right)  
302 - self.write(line)  
303 -  
304 - def write_header_sep(self):  
305 - s = self.style  
306 - line = self.make_line(left=s.header_sep_left, horiz=s.header_sep_horiz,  
307 - middle=s.header_sep_middle, right=s.header_sep_right)  
308 - self.write(line)  
309 -  
310 - def write_header(self):  
311 - if self.style.header_top:  
312 - self.write_header_top()  
313 - self.write_row(self.header_row)  
314 - if self.style.header_sep:  
315 - self.write_header_sep()  
316 -  
317 - def write_noheader_top(self):  
318 - s = self.style  
319 - line = self.make_line(left=s.noheader_top_left, horiz=s.noheader_top_horiz,  
320 - middle=s.noheader_top_middle, right=s.noheader_top_right)  
321 - self.write(line)  
322 -  
323 - def write_sep(self):  
324 - s = self.style  
325 - line = self.make_line(left=s.sep_left, horiz=s.sep_horiz,  
326 - middle=s.sep_middle, right=s.sep_right)  
327 - self.write(line)  
328 -  
329 - def write_bottom(self):  
330 - s = self.style  
331 - line = self.make_line(left=s.bottom_left, horiz=s.bottom_horiz,  
332 - middle=s.bottom_middle, right=s.bottom_right)  
333 - self.write(line)  
334 -  
335 - def close(self):  
336 - self.write_bottom()  
337 -  
338 -  
339 -if __name__ == '__main__':  
340 - t = TableStream([10, 5, 20], header_row=['i', 'i*i', '2**i'], style=TableStyleSlim)  
341 - t.write_row(['test', 'test', 'test'])  
342 - cell = 'a very very long text'  
343 - t.write_row([cell, cell, cell], colors=['blue', None, 'red'])  
344 - for i in range(1, 11):  
345 - t.write_row([i, i*i, 2**i])  
346 - t.close()  
347 -  
348 -