1212from typing import Any , Callable , Dict , List , Tuple
1313from volatility3 .cli import text_filter
1414
15- from volatility3 .framework import interfaces , renderers
15+ from volatility3 .framework import exceptions , interfaces , renderers
1616from volatility3 .framework .renderers import format_hints
1717
1818vollog = logging .getLogger (__name__ )
@@ -141,6 +141,30 @@ class CLIRenderer(interfaces.renderers.Renderer):
141141 name = "unnamed"
142142 structured_output = False
143143 filter : text_filter .CLIFilter = None
144+ column_hide_list : list = None
145+
146+ def ignored_columns (
147+ self ,
148+ grid : interfaces .renderers .TreeGrid ,
149+ ) -> List [interfaces .renderers .Column ]:
150+ ignored_column_list = []
151+ if self .column_hide_list :
152+ for column in grid .columns :
153+ accept = True
154+ for column_prefix in self .column_hide_list :
155+ if column .name .lower ().startswith (column_prefix .lower ()):
156+ accept = False
157+ if not accept :
158+ ignored_column_list .append (column )
159+ elif self .column_hide_list is None :
160+ return []
161+
162+ if len (ignored_column_list ) == len (grid .columns ):
163+ raise exceptions .RenderException ("No visible columns to render" )
164+ vollog .info (
165+ f"Hiding columns: { [column .name for column in ignored_column_list ]} "
166+ )
167+ return ignored_column_list
144168
145169
146170class QuickTextRenderer (CLIRenderer ):
@@ -173,9 +197,11 @@ def render(self, grid: interfaces.renderers.TreeGrid) -> None:
173197 outfd = sys .stdout
174198
175199 line = []
200+ ignore_columns = self .ignored_columns (grid )
176201 for column in grid .columns :
177202 # Ignore the type because namedtuples don't realize they have accessible attributes
178- line .append (f"{ column .name } " )
203+ if column not in ignore_columns :
204+ line .append (f"{ column .name } " )
179205 outfd .write ("\n {}\n " .format ("\t " .join (line )))
180206
181207 def visitor (node : interfaces .renderers .TreeNode , accumulator ):
@@ -184,7 +210,8 @@ def visitor(node: interfaces.renderers.TreeNode, accumulator):
184210 renderer = self ._type_renderers .get (
185211 column .type , self ._type_renderers ["default" ]
186212 )
187- line .append (renderer (node .values [column_index ]))
213+ if column not in ignore_columns :
214+ line .append (renderer (node .values [column_index ]))
188215
189216 if self .filter and self .filter .filter (line ):
190217 return accumulator
@@ -245,11 +272,13 @@ def render(self, grid: interfaces.renderers.TreeGrid) -> None:
245272 grid: The TreeGrid object to render
246273 """
247274 outfd = sys .stdout
275+ ignore_columns = self .ignored_columns (grid )
248276
249277 header_list = ["TreeDepth" ]
250278 for column in grid .columns :
251279 # Ignore the type because namedtuples don't realize they have accessible attributes
252- header_list .append (f"{ column .name } " )
280+ if column not in ignore_columns :
281+ header_list .append (f"{ column .name } " )
253282
254283 writer = csv .DictWriter (
255284 outfd , header_list , lineterminator = "\n " , escapechar = "\\ "
@@ -265,7 +294,10 @@ def visitor(node: interfaces.renderers.TreeNode, accumulator):
265294 column .type , self ._type_renderers ["default" ]
266295 )
267296 row [f"{ column .name } " ] = renderer (node .values [column_index ])
268- line .append (row [f"{ column .name } " ])
297+ if column not in ignore_columns :
298+ line .append (row [f"{ column .name } " ])
299+ else :
300+ del row [f"{ column .name } " ]
269301
270302 if self .filter and self .filter .filter (line ):
271303 return accumulator
@@ -303,6 +335,7 @@ def render(self, grid: interfaces.renderers.TreeGrid) -> None:
303335
304336 sys .stderr .write ("Formatting...\n " )
305337
338+ ignore_columns = self .ignored_columns (grid )
306339 display_alignment = ">"
307340 column_separator = " | "
308341
@@ -335,7 +368,8 @@ def visitor(
335368 max_column_widths [column .name ] = max (
336369 max_column_widths .get (column .name , len (column .name )), field_width
337370 )
338- line [column ] = data .split ("\n " )
371+ if column not in ignore_columns :
372+ line [column ] = data .split ("\n " )
339373 rendered_line .append (data )
340374
341375 if self .filter and self .filter .filter (rendered_line ):
@@ -354,43 +388,49 @@ def visitor(
354388 format_string_list = [
355389 "{0:<" + str (max_column_widths .get (tree_indent_column , 0 )) + "s}"
356390 ]
391+ column_offset = 0
357392 for column_index , column in enumerate (grid .columns ):
358- format_string_list .append (
359- "{"
360- + str (column_index + 1 )
361- + ":"
362- + display_alignment
363- + str (max_column_widths [column .name ])
364- + "s}"
365- )
393+ if column not in ignore_columns :
394+ format_string_list .append (
395+ "{"
396+ + str (column_index - column_offset + 1 )
397+ + ":"
398+ + display_alignment
399+ + str (max_column_widths [column .name ])
400+ + "s}"
401+ )
402+ else :
403+ column_offset += 1
366404
367405 format_string = column_separator .join (format_string_list ) + "\n "
368406
369- column_titles = ["" ] + [column .name for column in grid .columns ]
407+ column_titles = ["" ] + [
408+ column .name for column in grid .columns if column not in ignore_columns
409+ ]
410+
370411 outfd .write (format_string .format (* column_titles ))
371412 for depth , line in final_output :
372413 nums_line = max ([len (line [column ]) for column in line ])
373414 for column in line :
374- line [column ] = line [column ] + (["" ] * (nums_line - len (line [column ])))
415+ if column in ignore_columns :
416+ del line [column ]
417+ else :
418+ line [column ] = line [column ] + (
419+ ["" ] * (nums_line - len (line [column ]))
420+ )
375421 for index in range (nums_line ):
376422 if index == 0 :
377423 outfd .write (
378424 format_string .format (
379425 "*" * depth ,
380- * [
381- self .tab_stop (line [column ][index ])
382- for column in grid .columns
383- ],
426+ * [self .tab_stop (line [column ][index ]) for column in line ],
384427 )
385428 )
386429 else :
387430 outfd .write (
388431 format_string .format (
389432 " " * depth ,
390- * [
391- self .tab_stop (line [column ][index ])
392- for column in grid .columns
393- ],
433+ * [self .tab_stop (line [column ][index ]) for column in line ],
394434 )
395435 )
396436
@@ -436,6 +476,8 @@ def render(self, grid: interfaces.renderers.TreeGrid):
436476 List [interfaces .renderers .TreeNode ],
437477 ] = ({}, [])
438478
479+ ignore_columns = self .ignored_columns (grid )
480+
439481 def visitor (
440482 node : interfaces .renderers .TreeNode ,
441483 accumulator : Tuple [Dict [str , Dict [str , Any ]], List [Dict [str , Any ]]],
@@ -445,6 +487,8 @@ def visitor(
445487 node_dict : Dict [str , Any ] = {"__children" : []}
446488 line = []
447489 for column_index , column in enumerate (grid .columns ):
490+ if column in ignore_columns :
491+ continue
448492 renderer = self ._type_renderers .get (
449493 column .type , self ._type_renderers ["default" ]
450494 )
0 commit comments