Commit 2e7c42943d248083bae01fa5a6a84199fbbc8887

Authored by decalage2
1 parent 435baf80

colorclass is now an external dependency, obsolete copy removed from thirdparty folder

oletools/oledir.py
... ... @@ -51,6 +51,7 @@ from __future__ import print_function
51 51 # 2018-04-11 v0.53 PL: - added table displaying storage tree and CLSIDs
52 52 # 2018-04-13 PL: - moved KNOWN_CLSIDS to common.clsid
53 53 # 2018-08-28 v0.54 PL: - olefile is now a dependency
  54 +# 2018-10-06 - colorclass is now a dependency
54 55  
55 56 __version__ = '0.54dev1'
56 57  
... ... @@ -63,6 +64,13 @@ __version__ = '0.54dev1'
63 64  
64 65 import sys, os, optparse
65 66  
  67 +import olefile
  68 +import colorclass
  69 +
  70 +# On Windows, colorclass needs to be enabled:
  71 +if os.name == 'nt':
  72 + colorclass.Windows.enable(auto_colors=True)
  73 +
66 74 # IMPORTANT: it should be possible to run oletools directly as scripts
67 75 # in any directory without installing them with pip or setup.py.
68 76 # In that case, relative imports are NOT usable.
... ... @@ -75,20 +83,6 @@ _parent_dir = os.path.normpath(os.path.join(_thismodule_dir, '..'))
75 83 if not _parent_dir in sys.path:
76 84 sys.path.insert(0, _parent_dir)
77 85  
78   -# we also need the thirdparty dir for colorclass
79   -# TODO: remove colorclass from thirdparty, make it a dependency
80   -_thirdparty_dir = os.path.normpath(os.path.join(_thismodule_dir, 'thirdparty'))
81   -# print('_thirdparty_dir = %r' % _thirdparty_dir)
82   -if not _thirdparty_dir in sys.path:
83   - sys.path.insert(0, _thirdparty_dir)
84   -
85   -import colorclass
86   -
87   -# On Windows, colorclass needs to be enabled:
88   -if os.name == 'nt':
89   - colorclass.Windows.enable(auto_colors=True)
90   -
91   -import olefile
92 86 from oletools.thirdparty.tablestream import tablestream
93 87 from oletools.thirdparty.xglob import xglob
94 88 from oletools.common.clsid import KNOWN_CLSIDS
... ...
oletools/thirdparty/colorclass/LICENSE.txt deleted
1   -The MIT License (MIT)
2   -
3   -Copyright (c) 2014 Robpol86
4   -
5   -Permission is hereby granted, free of charge, to any person obtaining a copy
6   -of this software and associated documentation files (the "Software"), to deal
7   -in the Software without restriction, including without limitation the rights
8   -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9   -copies of the Software, and to permit persons to whom the Software is
10   -furnished to do so, subject to the following conditions:
11   -
12   -The above copyright notice and this permission notice shall be included in all
13   -copies or substantial portions of the Software.
14   -
15   -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16   -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17   -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18   -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19   -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20   -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21   -SOFTWARE.
oletools/thirdparty/colorclass/__init__.py deleted
1   -"""Colorful worry-free console applications for Linux, Mac OS X, and Windows.
2   -
3   -Supported natively on Linux and Mac OSX (Just Works), and on Windows it works the same if Windows.enable() is called.
4   -
5   -Gives you expected and sane results from methods like len() and .capitalize().
6   -
7   -https://github.com/Robpol86/colorclass
8   -https://pypi.org/project/colorclass/
9   -"""
10   -
11   -from colorclass.codes import list_tags # noqa
12   -from colorclass.color import Color # noqa
13   -from colorclass.toggles import disable_all_colors # noqa
14   -from colorclass.toggles import disable_if_no_tty # noqa
15   -from colorclass.toggles import enable_all_colors # noqa
16   -from colorclass.toggles import is_enabled # noqa
17   -from colorclass.toggles import is_light # noqa
18   -from colorclass.toggles import set_dark_background # noqa
19   -from colorclass.toggles import set_light_background # noqa
20   -from colorclass.windows import Windows # noqa
21   -
22   -
23   -__all__ = (
24   - 'Color',
25   - 'disable_all_colors',
26   - 'enable_all_colors',
27   - 'is_enabled',
28   - 'is_light',
29   - 'list_tags',
30   - 'set_dark_background',
31   - 'set_light_background',
32   - 'Windows',
33   -)
34   -
35   -
36   -__author__ = '@Robpol86'
37   -__license__ = 'MIT'
38   -__version__ = '2.2.0'
oletools/thirdparty/colorclass/__main__.py deleted
1   -"""Called by "python -m". Allows package to be used as a script.
2   -
3   -Example usage:
4   -echo "{red}Red{/red}" |python -m colorclass
5   -"""
6   -
7   -from __future__ import print_function
8   -
9   -import fileinput
10   -import os
11   -
12   -from colorclass.color import Color
13   -from colorclass.toggles import disable_all_colors
14   -from colorclass.toggles import enable_all_colors
15   -from colorclass.toggles import set_dark_background
16   -from colorclass.toggles import set_light_background
17   -from colorclass.windows import Windows
18   -
19   -TRUTHY = ('true', '1', 'yes', 'on')
20   -
21   -
22   -if __name__ == '__main__':
23   - if os.environ.get('COLOR_ENABLE', '').lower() in TRUTHY:
24   - enable_all_colors()
25   - elif os.environ.get('COLOR_DISABLE', '').lower() in TRUTHY:
26   - disable_all_colors()
27   - if os.environ.get('COLOR_LIGHT', '').lower() in TRUTHY:
28   - set_light_background()
29   - elif os.environ.get('COLOR_DARK', '').lower() in TRUTHY:
30   - set_dark_background()
31   - Windows.enable()
32   - for LINE in fileinput.input():
33   - print(Color(LINE))
oletools/thirdparty/colorclass/codes.py deleted
1   -"""Handles mapping between color names and ANSI codes and determining auto color codes."""
2   -
3   -import sys
4   -from collections import Mapping
5   -
6   -BASE_CODES = {
7   - '/all': 0, 'b': 1, 'f': 2, 'i': 3, 'u': 4, 'flash': 5, 'outline': 6, 'negative': 7, 'invis': 8, 'strike': 9,
8   - '/b': 22, '/f': 22, '/i': 23, '/u': 24, '/flash': 25, '/outline': 26, '/negative': 27, '/invis': 28,
9   - '/strike': 29, '/fg': 39, '/bg': 49,
10   -
11   - 'black': 30, 'red': 31, 'green': 32, 'yellow': 33, 'blue': 34, 'magenta': 35, 'cyan': 36, 'white': 37,
12   -
13   - 'bgblack': 40, 'bgred': 41, 'bggreen': 42, 'bgyellow': 43, 'bgblue': 44, 'bgmagenta': 45, 'bgcyan': 46,
14   - 'bgwhite': 47,
15   -
16   - 'hiblack': 90, 'hired': 91, 'higreen': 92, 'hiyellow': 93, 'hiblue': 94, 'himagenta': 95, 'hicyan': 96,
17   - 'hiwhite': 97,
18   -
19   - 'hibgblack': 100, 'hibgred': 101, 'hibggreen': 102, 'hibgyellow': 103, 'hibgblue': 104, 'hibgmagenta': 105,
20   - 'hibgcyan': 106, 'hibgwhite': 107,
21   -
22   - 'autored': None, 'autoblack': None, 'automagenta': None, 'autowhite': None, 'autoblue': None, 'autoyellow': None,
23   - 'autogreen': None, 'autocyan': None,
24   -
25   - 'autobgred': None, 'autobgblack': None, 'autobgmagenta': None, 'autobgwhite': None, 'autobgblue': None,
26   - 'autobgyellow': None, 'autobggreen': None, 'autobgcyan': None,
27   -
28   - '/black': 39, '/red': 39, '/green': 39, '/yellow': 39, '/blue': 39, '/magenta': 39, '/cyan': 39, '/white': 39,
29   - '/hiblack': 39, '/hired': 39, '/higreen': 39, '/hiyellow': 39, '/hiblue': 39, '/himagenta': 39, '/hicyan': 39,
30   - '/hiwhite': 39,
31   -
32   - '/bgblack': 49, '/bgred': 49, '/bggreen': 49, '/bgyellow': 49, '/bgblue': 49, '/bgmagenta': 49, '/bgcyan': 49,
33   - '/bgwhite': 49, '/hibgblack': 49, '/hibgred': 49, '/hibggreen': 49, '/hibgyellow': 49, '/hibgblue': 49,
34   - '/hibgmagenta': 49, '/hibgcyan': 49, '/hibgwhite': 49,
35   -
36   - '/autored': 39, '/autoblack': 39, '/automagenta': 39, '/autowhite': 39, '/autoblue': 39, '/autoyellow': 39,
37   - '/autogreen': 39, '/autocyan': 39,
38   -
39   - '/autobgred': 49, '/autobgblack': 49, '/autobgmagenta': 49, '/autobgwhite': 49, '/autobgblue': 49,
40   - '/autobgyellow': 49, '/autobggreen': 49, '/autobgcyan': 49,
41   -}
42   -
43   -
44   -class ANSICodeMapping(Mapping):
45   - """Read-only dictionary, resolves closing tags and automatic colors. Iterates only used color tags.
46   -
47   - :cvar bool DISABLE_COLORS: Disable colors (strip color codes).
48   - :cvar bool LIGHT_BACKGROUND: Use low intensity color codes.
49   - """
50   -
51   - DISABLE_COLORS = False
52   - LIGHT_BACKGROUND = False
53   -
54   - def __init__(self, value_markup):
55   - """Constructor.
56   -
57   - :param str value_markup: String with {color} tags.
58   - """
59   - self.whitelist = [k for k in BASE_CODES if '{' + k + '}' in value_markup]
60   -
61   - def __getitem__(self, item):
62   - """Return value for key or None if colors are disabled.
63   -
64   - :param str item: Key.
65   -
66   - :return: Color code integer.
67   - :rtype: int
68   - """
69   - if item not in self.whitelist:
70   - raise KeyError(item)
71   - if self.DISABLE_COLORS:
72   - return None
73   - return getattr(self, item, BASE_CODES[item])
74   -
75   - def __iter__(self):
76   - """Iterate dictionary."""
77   - return iter(self.whitelist)
78   -
79   - def __len__(self):
80   - """Dictionary length."""
81   - return len(self.whitelist)
82   -
83   - @classmethod
84   - def disable_all_colors(cls):
85   - """Disable all colors. Strips any color tags or codes."""
86   - cls.DISABLE_COLORS = True
87   -
88   - @classmethod
89   - def enable_all_colors(cls):
90   - """Enable all colors. Strips any color tags or codes."""
91   - cls.DISABLE_COLORS = False
92   -
93   - @classmethod
94   - def disable_if_no_tty(cls):
95   - """Disable all colors only if there is no TTY available.
96   -
97   - :return: True if colors are disabled, False if stderr or stdout is a TTY.
98   - :rtype: bool
99   - """
100   - if sys.stdout.isatty() or sys.stderr.isatty():
101   - return False
102   - cls.disable_all_colors()
103   - return True
104   -
105   - @classmethod
106   - def set_dark_background(cls):
107   - """Choose dark colors for all 'auto'-prefixed codes for readability on light backgrounds."""
108   - cls.LIGHT_BACKGROUND = False
109   -
110   - @classmethod
111   - def set_light_background(cls):
112   - """Choose dark colors for all 'auto'-prefixed codes for readability on light backgrounds."""
113   - cls.LIGHT_BACKGROUND = True
114   -
115   - @property
116   - def autoblack(self):
117   - """Return automatic black foreground color depending on background color."""
118   - return BASE_CODES['black' if ANSICodeMapping.LIGHT_BACKGROUND else 'hiblack']
119   -
120   - @property
121   - def autored(self):
122   - """Return automatic red foreground color depending on background color."""
123   - return BASE_CODES['red' if ANSICodeMapping.LIGHT_BACKGROUND else 'hired']
124   -
125   - @property
126   - def autogreen(self):
127   - """Return automatic green foreground color depending on background color."""
128   - return BASE_CODES['green' if ANSICodeMapping.LIGHT_BACKGROUND else 'higreen']
129   -
130   - @property
131   - def autoyellow(self):
132   - """Return automatic yellow foreground color depending on background color."""
133   - return BASE_CODES['yellow' if ANSICodeMapping.LIGHT_BACKGROUND else 'hiyellow']
134   -
135   - @property
136   - def autoblue(self):
137   - """Return automatic blue foreground color depending on background color."""
138   - return BASE_CODES['blue' if ANSICodeMapping.LIGHT_BACKGROUND else 'hiblue']
139   -
140   - @property
141   - def automagenta(self):
142   - """Return automatic magenta foreground color depending on background color."""
143   - return BASE_CODES['magenta' if ANSICodeMapping.LIGHT_BACKGROUND else 'himagenta']
144   -
145   - @property
146   - def autocyan(self):
147   - """Return automatic cyan foreground color depending on background color."""
148   - return BASE_CODES['cyan' if ANSICodeMapping.LIGHT_BACKGROUND else 'hicyan']
149   -
150   - @property
151   - def autowhite(self):
152   - """Return automatic white foreground color depending on background color."""
153   - return BASE_CODES['white' if ANSICodeMapping.LIGHT_BACKGROUND else 'hiwhite']
154   -
155   - @property
156   - def autobgblack(self):
157   - """Return automatic black background color depending on background color."""
158   - return BASE_CODES['bgblack' if ANSICodeMapping.LIGHT_BACKGROUND else 'hibgblack']
159   -
160   - @property
161   - def autobgred(self):
162   - """Return automatic red background color depending on background color."""
163   - return BASE_CODES['bgred' if ANSICodeMapping.LIGHT_BACKGROUND else 'hibgred']
164   -
165   - @property
166   - def autobggreen(self):
167   - """Return automatic green background color depending on background color."""
168   - return BASE_CODES['bggreen' if ANSICodeMapping.LIGHT_BACKGROUND else 'hibggreen']
169   -
170   - @property
171   - def autobgyellow(self):
172   - """Return automatic yellow background color depending on background color."""
173   - return BASE_CODES['bgyellow' if ANSICodeMapping.LIGHT_BACKGROUND else 'hibgyellow']
174   -
175   - @property
176   - def autobgblue(self):
177   - """Return automatic blue background color depending on background color."""
178   - return BASE_CODES['bgblue' if ANSICodeMapping.LIGHT_BACKGROUND else 'hibgblue']
179   -
180   - @property
181   - def autobgmagenta(self):
182   - """Return automatic magenta background color depending on background color."""
183   - return BASE_CODES['bgmagenta' if ANSICodeMapping.LIGHT_BACKGROUND else 'hibgmagenta']
184   -
185   - @property
186   - def autobgcyan(self):
187   - """Return automatic cyan background color depending on background color."""
188   - return BASE_CODES['bgcyan' if ANSICodeMapping.LIGHT_BACKGROUND else 'hibgcyan']
189   -
190   - @property
191   - def autobgwhite(self):
192   - """Return automatic white background color depending on background color."""
193   - return BASE_CODES['bgwhite' if ANSICodeMapping.LIGHT_BACKGROUND else 'hibgwhite']
194   -
195   -
196   -def list_tags():
197   - """List the available tags.
198   -
199   - :return: List of 4-item tuples: opening tag, closing tag, main ansi value, closing ansi value.
200   - :rtype: list
201   - """
202   - # Build reverse dictionary. Keys are closing tags, values are [closing ansi, opening tag, opening ansi].
203   - reverse_dict = dict()
204   - for tag, ansi in sorted(BASE_CODES.items()):
205   - if tag.startswith('/'):
206   - reverse_dict[tag] = [ansi, None, None]
207   - else:
208   - reverse_dict['/' + tag][1:] = [tag, ansi]
209   -
210   - # Collapse
211   - four_item_tuples = [(v[1], k, v[2], v[0]) for k, v in reverse_dict.items()]
212   -
213   - # Sort.
214   - def sorter(four_item):
215   - """Sort /all /fg /bg first, then b i u flash, then auto colors, then dark colors, finally light colors.
216   -
217   - :param iter four_item: [opening tag, closing tag, main ansi value, closing ansi value]
218   -
219   - :return Sorting weight.
220   - :rtype: int
221   - """
222   - if not four_item[2]: # /all /fg /bg
223   - return four_item[3] - 200
224   - if four_item[2] < 10 or four_item[0].startswith('auto'): # b f i u or auto colors
225   - return four_item[2] - 100
226   - return four_item[2]
227   - four_item_tuples.sort(key=sorter)
228   -
229   - return four_item_tuples
oletools/thirdparty/colorclass/color.py deleted
1   -"""Color class used by library users."""
2   -
3   -from colorclass.core import ColorStr
4   -
5   -
6   -class Color(ColorStr):
7   - """Unicode (str in Python3) subclass with ANSI terminal text color support.
8   -
9   - Example syntax: Color('{red}Sample Text{/red}')
10   -
11   - Example without parsing logic: Color('{red}Sample Text{/red}', keep_tags=True)
12   -
13   - For a list of codes, call: colorclass.list_tags()
14   - """
15   -
16   - @classmethod
17   - def colorize(cls, color, string, auto=False):
18   - """Color-code entire string using specified color.
19   -
20   - :param str color: Color of string.
21   - :param str string: String to colorize.
22   - :param bool auto: Enable auto-color (dark/light terminal).
23   -
24   - :return: Class instance for colorized string.
25   - :rtype: Color
26   - """
27   - tag = '{0}{1}'.format('auto' if auto else '', color)
28   - return cls('{%s}%s{/%s}' % (tag, string, tag))
29   -
30   - @classmethod
31   - def black(cls, string, auto=False):
32   - """Color-code entire string.
33   -
34   - :param str string: String to colorize.
35   - :param bool auto: Enable auto-color (dark/light terminal).
36   -
37   - :return: Class instance for colorized string.
38   - :rtype: Color
39   - """
40   - return cls.colorize('black', string, auto=auto)
41   -
42   - @classmethod
43   - def bgblack(cls, string, auto=False):
44   - """Color-code entire string.
45   -
46   - :param str string: String to colorize.
47   - :param bool auto: Enable auto-color (dark/light terminal).
48   -
49   - :return: Class instance for colorized string.
50   - :rtype: Color
51   - """
52   - return cls.colorize('bgblack', string, auto=auto)
53   -
54   - @classmethod
55   - def red(cls, string, auto=False):
56   - """Color-code entire string.
57   -
58   - :param str string: String to colorize.
59   - :param bool auto: Enable auto-color (dark/light terminal).
60   -
61   - :return: Class instance for colorized string.
62   - :rtype: Color
63   - """
64   - return cls.colorize('red', string, auto=auto)
65   -
66   - @classmethod
67   - def bgred(cls, string, auto=False):
68   - """Color-code entire string.
69   -
70   - :param str string: String to colorize.
71   - :param bool auto: Enable auto-color (dark/light terminal).
72   -
73   - :return: Class instance for colorized string.
74   - :rtype: Color
75   - """
76   - return cls.colorize('bgred', string, auto=auto)
77   -
78   - @classmethod
79   - def green(cls, string, auto=False):
80   - """Color-code entire string.
81   -
82   - :param str string: String to colorize.
83   - :param bool auto: Enable auto-color (dark/light terminal).
84   -
85   - :return: Class instance for colorized string.
86   - :rtype: Color
87   - """
88   - return cls.colorize('green', string, auto=auto)
89   -
90   - @classmethod
91   - def bggreen(cls, string, auto=False):
92   - """Color-code entire string.
93   -
94   - :param str string: String to colorize.
95   - :param bool auto: Enable auto-color (dark/light terminal).
96   -
97   - :return: Class instance for colorized string.
98   - :rtype: Color
99   - """
100   - return cls.colorize('bggreen', string, auto=auto)
101   -
102   - @classmethod
103   - def yellow(cls, string, auto=False):
104   - """Color-code entire string.
105   -
106   - :param str string: String to colorize.
107   - :param bool auto: Enable auto-color (dark/light terminal).
108   -
109   - :return: Class instance for colorized string.
110   - :rtype: Color
111   - """
112   - return cls.colorize('yellow', string, auto=auto)
113   -
114   - @classmethod
115   - def bgyellow(cls, string, auto=False):
116   - """Color-code entire string.
117   -
118   - :param str string: String to colorize.
119   - :param bool auto: Enable auto-color (dark/light terminal).
120   -
121   - :return: Class instance for colorized string.
122   - :rtype: Color
123   - """
124   - return cls.colorize('bgyellow', string, auto=auto)
125   -
126   - @classmethod
127   - def blue(cls, string, auto=False):
128   - """Color-code entire string.
129   -
130   - :param str string: String to colorize.
131   - :param bool auto: Enable auto-color (dark/light terminal).
132   -
133   - :return: Class instance for colorized string.
134   - :rtype: Color
135   - """
136   - return cls.colorize('blue', string, auto=auto)
137   -
138   - @classmethod
139   - def bgblue(cls, string, auto=False):
140   - """Color-code entire string.
141   -
142   - :param str string: String to colorize.
143   - :param bool auto: Enable auto-color (dark/light terminal).
144   -
145   - :return: Class instance for colorized string.
146   - :rtype: Color
147   - """
148   - return cls.colorize('bgblue', string, auto=auto)
149   -
150   - @classmethod
151   - def magenta(cls, string, auto=False):
152   - """Color-code entire string.
153   -
154   - :param str string: String to colorize.
155   - :param bool auto: Enable auto-color (dark/light terminal).
156   -
157   - :return: Class instance for colorized string.
158   - :rtype: Color
159   - """
160   - return cls.colorize('magenta', string, auto=auto)
161   -
162   - @classmethod
163   - def bgmagenta(cls, string, auto=False):
164   - """Color-code entire string.
165   -
166   - :param str string: String to colorize.
167   - :param bool auto: Enable auto-color (dark/light terminal).
168   -
169   - :return: Class instance for colorized string.
170   - :rtype: Color
171   - """
172   - return cls.colorize('bgmagenta', string, auto=auto)
173   -
174   - @classmethod
175   - def cyan(cls, string, auto=False):
176   - """Color-code entire string.
177   -
178   - :param str string: String to colorize.
179   - :param bool auto: Enable auto-color (dark/light terminal).
180   -
181   - :return: Class instance for colorized string.
182   - :rtype: Color
183   - """
184   - return cls.colorize('cyan', string, auto=auto)
185   -
186   - @classmethod
187   - def bgcyan(cls, string, auto=False):
188   - """Color-code entire string.
189   -
190   - :param str string: String to colorize.
191   - :param bool auto: Enable auto-color (dark/light terminal).
192   -
193   - :return: Class instance for colorized string.
194   - :rtype: Color
195   - """
196   - return cls.colorize('bgcyan', string, auto=auto)
197   -
198   - @classmethod
199   - def white(cls, string, auto=False):
200   - """Color-code entire string.
201   -
202   - :param str string: String to colorize.
203   - :param bool auto: Enable auto-color (dark/light terminal).
204   -
205   - :return: Class instance for colorized string.
206   - :rtype: Color
207   - """
208   - return cls.colorize('white', string, auto=auto)
209   -
210   - @classmethod
211   - def bgwhite(cls, string, auto=False):
212   - """Color-code entire string.
213   -
214   - :param str string: String to colorize.
215   - :param bool auto: Enable auto-color (dark/light terminal).
216   -
217   - :return: Class instance for colorized string.
218   - :rtype: Color
219   - """
220   - return cls.colorize('bgwhite', string, auto=auto)
oletools/thirdparty/colorclass/core.py deleted
1   -"""String subclass that handles ANSI color codes."""
2   -
3   -from colorclass.codes import ANSICodeMapping
4   -from colorclass.parse import parse_input, RE_SPLIT
5   -from colorclass.search import build_color_index, find_char_color
6   -
7   -PARENT_CLASS = type(u'')
8   -
9   -
10   -def apply_text(incoming, func):
11   - """Call `func` on text portions of incoming color string.
12   -
13   - :param iter incoming: Incoming string/ColorStr/string-like object to iterate.
14   - :param func: Function to call with string portion as first and only parameter.
15   -
16   - :return: Modified string, same class type as incoming string.
17   - """
18   - split = RE_SPLIT.split(incoming)
19   - for i, item in enumerate(split):
20   - if not item or RE_SPLIT.match(item):
21   - continue
22   - split[i] = func(item)
23   - return incoming.__class__().join(split)
24   -
25   -
26   -class ColorBytes(bytes):
27   - """Str (bytes in Python3) subclass, .decode() overridden to return unicode (str in Python3) subclass instance."""
28   -
29   - def __new__(cls, *args, **kwargs):
30   - """Save original class so decode() returns an instance of it."""
31   - original_class = kwargs.pop('original_class')
32   - combined_args = [cls] + list(args)
33   - instance = bytes.__new__(*combined_args, **kwargs)
34   - instance.original_class = original_class
35   - return instance
36   -
37   - def decode(self, encoding='utf-8', errors='strict'):
38   - """Decode using the codec registered for encoding. Default encoding is 'utf-8'.
39   -
40   - errors may be given to set a different error handling scheme. Default is 'strict' meaning that encoding errors
41   - raise a UnicodeDecodeError. Other possible values are 'ignore' and 'replace' as well as any other name
42   - registered with codecs.register_error that is able to handle UnicodeDecodeErrors.
43   -
44   - :param str encoding: Codec.
45   - :param str errors: Error handling scheme.
46   - """
47   - original_class = getattr(self, 'original_class')
48   - return original_class(super(ColorBytes, self).decode(encoding, errors))
49   -
50   -
51   -class ColorStr(PARENT_CLASS):
52   - """Core color class."""
53   -
54   - def __new__(cls, *args, **kwargs):
55   - """Parse color markup and instantiate."""
56   - keep_tags = kwargs.pop('keep_tags', False)
57   -
58   - # Parse string.
59   - value_markup = args[0] if args else PARENT_CLASS() # e.g. '{red}test{/red}'
60   - value_colors, value_no_colors = parse_input(value_markup, ANSICodeMapping.DISABLE_COLORS, keep_tags)
61   - color_index = build_color_index(value_colors)
62   -
63   - # Instantiate.
64   - color_args = [cls, value_colors] + list(args[1:])
65   - instance = PARENT_CLASS.__new__(*color_args, **kwargs)
66   -
67   - # Add additional attributes and return.
68   - instance.value_colors = value_colors
69   - instance.value_no_colors = value_no_colors
70   - instance.has_colors = value_colors != value_no_colors
71   - instance.color_index = color_index
72   - return instance
73   -
74   - def __add__(self, other):
75   - """Concatenate."""
76   - return self.__class__(self.value_colors + other, keep_tags=True)
77   -
78   - def __getitem__(self, item):
79   - """Retrieve character."""
80   - try:
81   - color_pos = self.color_index[int(item)]
82   - except TypeError: # slice
83   - return super(ColorStr, self).__getitem__(item)
84   - return self.__class__(find_char_color(self.value_colors, color_pos), keep_tags=True)
85   -
86   - def __iter__(self):
87   - """Yield one color-coded character at a time."""
88   - for color_pos in self.color_index:
89   - yield self.__class__(find_char_color(self.value_colors, color_pos))
90   -
91   - def __len__(self):
92   - """Length of string without color codes (what users expect)."""
93   - return self.value_no_colors.__len__()
94   -
95   - def __mod__(self, other):
96   - """String substitution (like printf)."""
97   - return self.__class__(self.value_colors % other, keep_tags=True)
98   -
99   - def __mul__(self, other):
100   - """Multiply string."""
101   - return self.__class__(self.value_colors * other, keep_tags=True)
102   -
103   - def __repr__(self):
104   - """Representation of a class instance (like datetime.datetime.now())."""
105   - return '{name}({value})'.format(name=self.__class__.__name__, value=repr(self.value_colors))
106   -
107   - def capitalize(self):
108   - """Return a copy of the string with only its first character capitalized."""
109   - return apply_text(self, lambda s: s.capitalize())
110   -
111   - def center(self, width, fillchar=None):
112   - """Return centered in a string of length width. Padding is done using the specified fill character or space.
113   -
114   - :param int width: Length of output string.
115   - :param str fillchar: Use this character instead of spaces.
116   - """
117   - if fillchar is not None:
118   - result = self.value_no_colors.center(width, fillchar)
119   - else:
120   - result = self.value_no_colors.center(width)
121   - return self.__class__(result.replace(self.value_no_colors, self.value_colors), keep_tags=True)
122   -
123   - def count(self, sub, start=0, end=-1):
124   - """Return the number of non-overlapping occurrences of substring sub in string[start:end].
125   -
126   - Optional arguments start and end are interpreted as in slice notation.
127   -
128   - :param str sub: Substring to search.
129   - :param int start: Beginning position.
130   - :param int end: Stop comparison at this position.
131   - """
132   - return self.value_no_colors.count(sub, start, end)
133   -
134   - def endswith(self, suffix, start=0, end=None):
135   - """Return True if ends with the specified suffix, False otherwise.
136   -
137   - With optional start, test beginning at that position. With optional end, stop comparing at that position.
138   - suffix can also be a tuple of strings to try.
139   -
140   - :param str suffix: Suffix to search.
141   - :param int start: Beginning position.
142   - :param int end: Stop comparison at this position.
143   - """
144   - args = [suffix, start] + ([] if end is None else [end])
145   - return self.value_no_colors.endswith(*args)
146   -
147   - def encode(self, encoding=None, errors='strict'):
148   - """Encode using the codec registered for encoding. encoding defaults to the default encoding.
149   -
150   - errors may be given to set a different error handling scheme. Default is 'strict' meaning that encoding errors
151   - raise a UnicodeEncodeError. Other possible values are 'ignore', 'replace' and 'xmlcharrefreplace' as well as any
152   - other name registered with codecs.register_error that is able to handle UnicodeEncodeErrors.
153   -
154   - :param str encoding: Codec.
155   - :param str errors: Error handling scheme.
156   - """
157   - return ColorBytes(super(ColorStr, self).encode(encoding, errors), original_class=self.__class__)
158   -
159   - def decode(self, encoding=None, errors='strict'):
160   - """Decode using the codec registered for encoding. encoding defaults to the default encoding.
161   -
162   - errors may be given to set a different error handling scheme. Default is 'strict' meaning that encoding errors
163   - raise a UnicodeDecodeError. Other possible values are 'ignore' and 'replace' as well as any other name
164   - registered with codecs.register_error that is able to handle UnicodeDecodeErrors.
165   -
166   - :param str encoding: Codec.
167   - :param str errors: Error handling scheme.
168   - """
169   - return self.__class__(super(ColorStr, self).decode(encoding, errors), keep_tags=True)
170   -
171   - def find(self, sub, start=None, end=None):
172   - """Return the lowest index where substring sub is found, such that sub is contained within string[start:end].
173   -
174   - Optional arguments start and end are interpreted as in slice notation.
175   -
176   - :param str sub: Substring to search.
177   - :param int start: Beginning position.
178   - :param int end: Stop comparison at this position.
179   - """
180   - return self.value_no_colors.find(sub, start, end)
181   -
182   - def format(self, *args, **kwargs):
183   - """Return a formatted version, using substitutions from args and kwargs.
184   -
185   - The substitutions are identified by braces ('{' and '}').
186   - """
187   - return self.__class__(super(ColorStr, self).format(*args, **kwargs), keep_tags=True)
188   -
189   - def index(self, sub, start=None, end=None):
190   - """Like S.find() but raise ValueError when the substring is not found.
191   -
192   - :param str sub: Substring to search.
193   - :param int start: Beginning position.
194   - :param int end: Stop comparison at this position.
195   - """
196   - return self.value_no_colors.index(sub, start, end)
197   -
198   - def isalnum(self):
199   - """Return True if all characters in string are alphanumeric and there is at least one character in it."""
200   - return self.value_no_colors.isalnum()
201   -
202   - def isalpha(self):
203   - """Return True if all characters in string are alphabetic and there is at least one character in it."""
204   - return self.value_no_colors.isalpha()
205   -
206   - def isdecimal(self):
207   - """Return True if there are only decimal characters in string, False otherwise."""
208   - return self.value_no_colors.isdecimal()
209   -
210   - def isdigit(self):
211   - """Return True if all characters in string are digits and there is at least one character in it."""
212   - return self.value_no_colors.isdigit()
213   -
214   - def isnumeric(self):
215   - """Return True if there are only numeric characters in string, False otherwise."""
216   - return self.value_no_colors.isnumeric()
217   -
218   - def isspace(self):
219   - """Return True if all characters in string are whitespace and there is at least one character in it."""
220   - return self.value_no_colors.isspace()
221   -
222   - def istitle(self):
223   - """Return True if string is a titlecased string and there is at least one character in it.
224   -
225   - That is uppercase characters may only follow uncased characters and lowercase characters only cased ones. Return
226   - False otherwise.
227   - """
228   - return self.value_no_colors.istitle()
229   -
230   - def isupper(self):
231   - """Return True if all cased characters are uppercase and there is at least one cased character in it."""
232   - return self.value_no_colors.isupper()
233   -
234   - def join(self, iterable):
235   - """Return a string which is the concatenation of the strings in the iterable.
236   -
237   - :param iterable: Join items in this iterable.
238   - """
239   - return self.__class__(super(ColorStr, self).join(iterable), keep_tags=True)
240   -
241   - def ljust(self, width, fillchar=None):
242   - """Return left-justified string of length width. Padding is done using the specified fill character or space.
243   -
244   - :param int width: Length of output string.
245   - :param str fillchar: Use this character instead of spaces.
246   - """
247   - if fillchar is not None:
248   - result = self.value_no_colors.ljust(width, fillchar)
249   - else:
250   - result = self.value_no_colors.ljust(width)
251   - return self.__class__(result.replace(self.value_no_colors, self.value_colors), keep_tags=True)
252   -
253   - def rfind(self, sub, start=None, end=None):
254   - """Return the highest index where substring sub is found, such that sub is contained within string[start:end].
255   -
256   - Optional arguments start and end are interpreted as in slice notation.
257   -
258   - :param str sub: Substring to search.
259   - :param int start: Beginning position.
260   - :param int end: Stop comparison at this position.
261   - """
262   - return self.value_no_colors.rfind(sub, start, end)
263   -
264   - def rindex(self, sub, start=None, end=None):
265   - """Like .rfind() but raise ValueError when the substring is not found.
266   -
267   - :param str sub: Substring to search.
268   - :param int start: Beginning position.
269   - :param int end: Stop comparison at this position.
270   - """
271   - return self.value_no_colors.rindex(sub, start, end)
272   -
273   - def rjust(self, width, fillchar=None):
274   - """Return right-justified string of length width. Padding is done using the specified fill character or space.
275   -
276   - :param int width: Length of output string.
277   - :param str fillchar: Use this character instead of spaces.
278   - """
279   - if fillchar is not None:
280   - result = self.value_no_colors.rjust(width, fillchar)
281   - else:
282   - result = self.value_no_colors.rjust(width)
283   - return self.__class__(result.replace(self.value_no_colors, self.value_colors), keep_tags=True)
284   -
285   - def splitlines(self, keepends=False):
286   - """Return a list of the lines in the string, breaking at line boundaries.
287   -
288   - Line breaks are not included in the resulting list unless keepends is given and True.
289   -
290   - :param bool keepends: Include linebreaks.
291   - """
292   - return [self.__class__(l) for l in self.value_colors.splitlines(keepends)]
293   -
294   - def startswith(self, prefix, start=0, end=-1):
295   - """Return True if string starts with the specified prefix, False otherwise.
296   -
297   - With optional start, test beginning at that position. With optional end, stop comparing at that position. prefix
298   - can also be a tuple of strings to try.
299   -
300   - :param str prefix: Prefix to search.
301   - :param int start: Beginning position.
302   - :param int end: Stop comparison at this position.
303   - """
304   - return self.value_no_colors.startswith(prefix, start, end)
305   -
306   - def swapcase(self):
307   - """Return a copy of the string with uppercase characters converted to lowercase and vice versa."""
308   - return apply_text(self, lambda s: s.swapcase())
309   -
310   - def title(self):
311   - """Return a titlecased version of the string.
312   -
313   - That is words start with uppercase characters, all remaining cased characters have lowercase.
314   - """
315   - return apply_text(self, lambda s: s.title())
316   -
317   - def translate(self, table):
318   - """Return a copy of the string, where all characters have been mapped through the given translation table.
319   -
320   - Table must be a mapping of Unicode ordinals to Unicode ordinals, strings, or None. Unmapped characters are left
321   - untouched. Characters mapped to None are deleted.
322   -
323   - :param table: Translation table.
324   - """
325   - return apply_text(self, lambda s: s.translate(table))
326   -
327   - def upper(self):
328   - """Return a copy of the string converted to uppercase."""
329   - return apply_text(self, lambda s: s.upper())
330   -
331   - def zfill(self, width):
332   - """Pad a numeric string with zeros on the left, to fill a field of the specified width.
333   -
334   - The string is never truncated.
335   -
336   - :param int width: Length of output string.
337   - """
338   - if not self.value_no_colors:
339   - result = self.value_no_colors.zfill(width)
340   - else:
341   - result = self.value_colors.replace(self.value_no_colors, self.value_no_colors.zfill(width))
342   - return self.__class__(result, keep_tags=True)
oletools/thirdparty/colorclass/parse.py deleted
1   -"""Parse color markup tags into ANSI escape sequences."""
2   -
3   -import re
4   -
5   -from colorclass.codes import ANSICodeMapping, BASE_CODES
6   -
7   -CODE_GROUPS = (
8   - tuple(set(str(i) for i in BASE_CODES.values() if i and (40 <= i <= 49 or 100 <= i <= 109))), # bg colors
9   - tuple(set(str(i) for i in BASE_CODES.values() if i and (30 <= i <= 39 or 90 <= i <= 99))), # fg colors
10   - ('1', '22'), ('2', '22'), ('3', '23'), ('4', '24'), ('5', '25'), ('6', '26'), ('7', '27'), ('8', '28'), ('9', '29'),
11   -)
12   -RE_ANSI = re.compile(r'(\033\[([\d;]+)m)')
13   -RE_COMBINE = re.compile(r'\033\[([\d;]+)m\033\[([\d;]+)m')
14   -RE_SPLIT = re.compile(r'(\033\[[\d;]+m)')
15   -
16   -
17   -def prune_overridden(ansi_string):
18   - """Remove color codes that are rendered ineffective by subsequent codes in one escape sequence then sort codes.
19   -
20   - :param str ansi_string: Incoming ansi_string with ANSI color codes.
21   -
22   - :return: Color string with pruned color sequences.
23   - :rtype: str
24   - """
25   - multi_seqs = set(p for p in RE_ANSI.findall(ansi_string) if ';' in p[1]) # Sequences with multiple color codes.
26   -
27   - for escape, codes in multi_seqs:
28   - r_codes = list(reversed(codes.split(';')))
29   -
30   - # Nuke everything before {/all}.
31   - try:
32   - r_codes = r_codes[:r_codes.index('0') + 1]
33   - except ValueError:
34   - pass
35   -
36   - # Thin out groups.
37   - for group in CODE_GROUPS:
38   - for pos in reversed([i for i, n in enumerate(r_codes) if n in group][1:]):
39   - r_codes.pop(pos)
40   -
41   - # Done.
42   - reduced_codes = ';'.join(sorted(r_codes, key=int))
43   - if codes != reduced_codes:
44   - ansi_string = ansi_string.replace(escape, '\033[' + reduced_codes + 'm')
45   -
46   - return ansi_string
47   -
48   -
49   -def parse_input(tagged_string, disable_colors, keep_tags):
50   - """Perform the actual conversion of tags to ANSI escaped codes.
51   -
52   - Provides a version of the input without any colors for len() and other methods.
53   -
54   - :param str tagged_string: The input unicode value.
55   - :param bool disable_colors: Strip all colors in both outputs.
56   - :param bool keep_tags: Skip parsing curly bracket tags into ANSI escape sequences.
57   -
58   - :return: 2-item tuple. First item is the parsed output. Second item is a version of the input without any colors.
59   - :rtype: tuple
60   - """
61   - codes = ANSICodeMapping(tagged_string)
62   - output_colors = getattr(tagged_string, 'value_colors', tagged_string)
63   -
64   - # Convert: '{b}{red}' -> '\033[1m\033[31m'
65   - if not keep_tags:
66   - for tag, replacement in (('{' + k + '}', '' if v is None else '\033[%dm' % v) for k, v in codes.items()):
67   - output_colors = output_colors.replace(tag, replacement)
68   -
69   - # Strip colors.
70   - output_no_colors = RE_ANSI.sub('', output_colors)
71   - if disable_colors:
72   - return output_no_colors, output_no_colors
73   -
74   - # Combine: '\033[1m\033[31m' -> '\033[1;31m'
75   - while True:
76   - simplified = RE_COMBINE.sub(r'\033[\1;\2m', output_colors)
77   - if simplified == output_colors:
78   - break
79   - output_colors = simplified
80   -
81   - # Prune: '\033[31;32;33;34;35m' -> '\033[35m'
82   - output_colors = prune_overridden(output_colors)
83   -
84   - # Deduplicate: '\033[1;mT\033[1;mE\033[1;mS\033[1;mT' -> '\033[1;mTEST'
85   - previous_escape = None
86   - segments = list()
87   - for item in (i for i in RE_SPLIT.split(output_colors) if i):
88   - if RE_SPLIT.match(item):
89   - if item != previous_escape:
90   - segments.append(item)
91   - previous_escape = item
92   - else:
93   - segments.append(item)
94   - output_colors = ''.join(segments)
95   -
96   - return output_colors, output_no_colors
oletools/thirdparty/colorclass/search.py deleted
1   -"""Determine color of characters that may or may not be adjacent to ANSI escape sequences."""
2   -
3   -from colorclass.parse import RE_SPLIT
4   -
5   -
6   -def build_color_index(ansi_string):
7   - """Build an index between visible characters and a string with invisible color codes.
8   -
9   - :param str ansi_string: String with color codes (ANSI escape sequences).
10   -
11   - :return: Position of visible characters in color string (indexes match non-color string).
12   - :rtype: tuple
13   - """
14   - mapping = list()
15   - color_offset = 0
16   - for item in (i for i in RE_SPLIT.split(ansi_string) if i):
17   - if RE_SPLIT.match(item):
18   - color_offset += len(item)
19   - else:
20   - for _ in range(len(item)):
21   - mapping.append(color_offset)
22   - color_offset += 1
23   - return tuple(mapping)
24   -
25   -
26   -def find_char_color(ansi_string, pos):
27   - """Determine what color a character is in the string.
28   -
29   - :param str ansi_string: String with color codes (ANSI escape sequences).
30   - :param int pos: Position of the character in the ansi_string.
31   -
32   - :return: Character along with all surrounding color codes.
33   - :rtype: str
34   - """
35   - result = list()
36   - position = 0 # Set to None when character is found.
37   - for item in (i for i in RE_SPLIT.split(ansi_string) if i):
38   - if RE_SPLIT.match(item):
39   - result.append(item)
40   - if position is not None:
41   - position += len(item)
42   - elif position is not None:
43   - for char in item:
44   - if position == pos:
45   - result.append(char)
46   - position = None
47   - break
48   - position += 1
49   - return ''.join(result)
oletools/thirdparty/colorclass/toggles.py deleted
1   -"""Convenience functions to enable/disable features."""
2   -
3   -from colorclass.codes import ANSICodeMapping
4   -
5   -
6   -def disable_all_colors():
7   - """Disable all colors. Strip any color tags or codes."""
8   - ANSICodeMapping.disable_all_colors()
9   -
10   -
11   -def enable_all_colors():
12   - """Enable colors."""
13   - ANSICodeMapping.enable_all_colors()
14   -
15   -
16   -def disable_if_no_tty():
17   - """Disable all colors if there is no TTY available.
18   -
19   - :return: True if colors are disabled, False if stderr or stdout is a TTY.
20   - :rtype: bool
21   - """
22   - return ANSICodeMapping.disable_if_no_tty()
23   -
24   -
25   -def is_enabled():
26   - """Are colors enabled."""
27   - return not ANSICodeMapping.DISABLE_COLORS
28   -
29   -
30   -def set_light_background():
31   - """Choose dark colors for all 'auto'-prefixed codes for readability on light backgrounds."""
32   - ANSICodeMapping.set_light_background()
33   -
34   -
35   -def set_dark_background():
36   - """Choose dark colors for all 'auto'-prefixed codes for readability on light backgrounds."""
37   - ANSICodeMapping.set_dark_background()
38   -
39   -
40   -def is_light():
41   - """Are background colors for light backgrounds."""
42   - return ANSICodeMapping.LIGHT_BACKGROUND
oletools/thirdparty/colorclass/windows.py deleted
1   -"""Windows console screen buffer handlers."""
2   -
3   -from __future__ import print_function
4   -
5   -import atexit
6   -import ctypes
7   -import re
8   -import sys
9   -
10   -from colorclass.codes import ANSICodeMapping, BASE_CODES
11   -from colorclass.core import RE_SPLIT
12   -
13   -ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004
14   -INVALID_HANDLE_VALUE = -1
15   -IS_WINDOWS = sys.platform == 'win32'
16   -RE_NUMBER_SEARCH = re.compile(r'\033\[([\d;]+)m')
17   -STD_ERROR_HANDLE = -12
18   -STD_OUTPUT_HANDLE = -11
19   -WINDOWS_CODES = {
20   - '/all': -33, '/fg': -39, '/bg': -49,
21   -
22   - 'black': 0, 'red': 4, 'green': 2, 'yellow': 6, 'blue': 1, 'magenta': 5, 'cyan': 3, 'white': 7,
23   -
24   - 'bgblack': -8, 'bgred': 64, 'bggreen': 32, 'bgyellow': 96, 'bgblue': 16, 'bgmagenta': 80, 'bgcyan': 48,
25   - 'bgwhite': 112,
26   -
27   - 'hiblack': 8, 'hired': 12, 'higreen': 10, 'hiyellow': 14, 'hiblue': 9, 'himagenta': 13, 'hicyan': 11, 'hiwhite': 15,
28   -
29   - 'hibgblack': 128, 'hibgred': 192, 'hibggreen': 160, 'hibgyellow': 224, 'hibgblue': 144, 'hibgmagenta': 208,
30   - 'hibgcyan': 176, 'hibgwhite': 240,
31   -
32   - '/black': -39, '/red': -39, '/green': -39, '/yellow': -39, '/blue': -39, '/magenta': -39, '/cyan': -39,
33   - '/white': -39, '/hiblack': -39, '/hired': -39, '/higreen': -39, '/hiyellow': -39, '/hiblue': -39, '/himagenta': -39,
34   - '/hicyan': -39, '/hiwhite': -39,
35   -
36   - '/bgblack': -49, '/bgred': -49, '/bggreen': -49, '/bgyellow': -49, '/bgblue': -49, '/bgmagenta': -49,
37   - '/bgcyan': -49, '/bgwhite': -49, '/hibgblack': -49, '/hibgred': -49, '/hibggreen': -49, '/hibgyellow': -49,
38   - '/hibgblue': -49, '/hibgmagenta': -49, '/hibgcyan': -49, '/hibgwhite': -49,
39   -}
40   -
41   -
42   -class COORD(ctypes.Structure):
43   - """COORD structure. http://msdn.microsoft.com/en-us/library/windows/desktop/ms682119."""
44   -
45   - _fields_ = [
46   - ('X', ctypes.c_short),
47   - ('Y', ctypes.c_short),
48   - ]
49   -
50   -
51   -class SmallRECT(ctypes.Structure):
52   - """SMALL_RECT structure. http://msdn.microsoft.com/en-us/library/windows/desktop/ms686311."""
53   -
54   - _fields_ = [
55   - ('Left', ctypes.c_short),
56   - ('Top', ctypes.c_short),
57   - ('Right', ctypes.c_short),
58   - ('Bottom', ctypes.c_short),
59   - ]
60   -
61   -
62   -class ConsoleScreenBufferInfo(ctypes.Structure):
63   - """CONSOLE_SCREEN_BUFFER_INFO structure. http://msdn.microsoft.com/en-us/library/windows/desktop/ms682093."""
64   -
65   - _fields_ = [
66   - ('dwSize', COORD),
67   - ('dwCursorPosition', COORD),
68   - ('wAttributes', ctypes.c_ushort),
69   - ('srWindow', SmallRECT),
70   - ('dwMaximumWindowSize', COORD)
71   - ]
72   -
73   -
74   -def init_kernel32(kernel32=None):
75   - """Load a unique instance of WinDLL into memory, set arg/return types, and get stdout/err handles.
76   -
77   - 1. Since we are setting DLL function argument types and return types, we need to maintain our own instance of
78   - kernel32 to prevent overriding (or being overwritten by) user's own changes to ctypes.windll.kernel32.
79   - 2. While we're doing all this we might as well get the handles to STDOUT and STDERR streams.
80   - 3. If either stream has already been replaced set return value to INVALID_HANDLE_VALUE to indicate it shouldn't be
81   - replaced.
82   -
83   - :raise AttributeError: When called on a non-Windows platform.
84   -
85   - :param kernel32: Optional mock kernel32 object. For testing.
86   -
87   - :return: Loaded kernel32 instance, stderr handle (int), stdout handle (int).
88   - :rtype: tuple
89   - """
90   - if not kernel32:
91   - kernel32 = ctypes.LibraryLoader(ctypes.WinDLL).kernel32 # Load our own instance. Unique memory address.
92   - kernel32.GetStdHandle.argtypes = [ctypes.c_ulong]
93   - kernel32.GetStdHandle.restype = ctypes.c_void_p
94   - kernel32.GetConsoleScreenBufferInfo.argtypes = [
95   - ctypes.c_void_p,
96   - ctypes.POINTER(ConsoleScreenBufferInfo),
97   - ]
98   - kernel32.GetConsoleScreenBufferInfo.restype = ctypes.c_long
99   -
100   - # Get handles.
101   - if hasattr(sys.stderr, '_original_stream'):
102   - stderr = INVALID_HANDLE_VALUE
103   - else:
104   - stderr = kernel32.GetStdHandle(STD_ERROR_HANDLE)
105   - if hasattr(sys.stdout, '_original_stream'):
106   - stdout = INVALID_HANDLE_VALUE
107   - else:
108   - stdout = kernel32.GetStdHandle(STD_OUTPUT_HANDLE)
109   -
110   - return kernel32, stderr, stdout
111   -
112   -
113   -def get_console_info(kernel32, handle):
114   - """Get information about this current console window.
115   -
116   - http://msdn.microsoft.com/en-us/library/windows/desktop/ms683231
117   - https://code.google.com/p/colorama/issues/detail?id=47
118   - https://bitbucket.org/pytest-dev/py/src/4617fe46/py/_io/terminalwriter.py
119   -
120   - Windows 10 Insider since around February 2016 finally introduced support for ANSI colors. No need to replace stdout
121   - and stderr streams to intercept colors and issue multiple SetConsoleTextAttribute() calls for these consoles.
122   -
123   - :raise OSError: When GetConsoleScreenBufferInfo or GetConsoleMode API calls fail.
124   -
125   - :param ctypes.windll.kernel32 kernel32: Loaded kernel32 instance.
126   - :param int handle: stderr or stdout handle.
127   -
128   - :return: Foreground and background colors (integers) as well as native ANSI support (bool).
129   - :rtype: tuple
130   - """
131   - # Query Win32 API.
132   - csbi = ConsoleScreenBufferInfo() # Populated by GetConsoleScreenBufferInfo.
133   - lpcsbi = ctypes.byref(csbi)
134   - dword = ctypes.c_ulong() # Populated by GetConsoleMode.
135   - lpdword = ctypes.byref(dword)
136   - if not kernel32.GetConsoleScreenBufferInfo(handle, lpcsbi) or not kernel32.GetConsoleMode(handle, lpdword):
137   - raise ctypes.WinError()
138   -
139   - # Parse data.
140   - # buffer_width = int(csbi.dwSize.X - 1)
141   - # buffer_height = int(csbi.dwSize.Y)
142   - # terminal_width = int(csbi.srWindow.Right - csbi.srWindow.Left)
143   - # terminal_height = int(csbi.srWindow.Bottom - csbi.srWindow.Top)
144   - fg_color = csbi.wAttributes % 16
145   - bg_color = csbi.wAttributes & 240
146   - native_ansi = bool(dword.value & ENABLE_VIRTUAL_TERMINAL_PROCESSING)
147   -
148   - return fg_color, bg_color, native_ansi
149   -
150   -
151   -def bg_color_native_ansi(kernel32, stderr, stdout):
152   - """Get background color and if console supports ANSI colors natively for both streams.
153   -
154   - :param ctypes.windll.kernel32 kernel32: Loaded kernel32 instance.
155   - :param int stderr: stderr handle.
156   - :param int stdout: stdout handle.
157   -
158   - :return: Background color (int) and native ANSI support (bool).
159   - :rtype: tuple
160   - """
161   - try:
162   - if stderr == INVALID_HANDLE_VALUE:
163   - raise OSError
164   - bg_color, native_ansi = get_console_info(kernel32, stderr)[1:]
165   - except OSError:
166   - try:
167   - if stdout == INVALID_HANDLE_VALUE:
168   - raise OSError
169   - bg_color, native_ansi = get_console_info(kernel32, stdout)[1:]
170   - except OSError:
171   - bg_color, native_ansi = WINDOWS_CODES['black'], False
172   - return bg_color, native_ansi
173   -
174   -
175   -class WindowsStream(object):
176   - """Replacement stream which overrides sys.stdout or sys.stderr. When writing or printing, ANSI codes are converted.
177   -
178   - ANSI (Linux/Unix) color codes are converted into win32 system calls, changing the next character's color before
179   - printing it. Resources referenced:
180   - https://github.com/tartley/colorama
181   - http://www.cplusplus.com/articles/2ywTURfi/
182   - http://thomasfischer.biz/python-and-windows-terminal-colors/
183   - http://stackoverflow.com/questions/17125440/c-win32-console-color
184   - http://www.tysos.org/svn/trunk/mono/corlib/System/WindowsConsoleDriver.cs
185   - http://stackoverflow.com/questions/287871/print-in-terminal-with-colors-using-python
186   - http://msdn.microsoft.com/en-us/library/windows/desktop/ms682088#_win32_character_attributes
187   -
188   - :cvar list ALL_BG_CODES: List of bg Windows codes. Used to determine if requested color is foreground or background.
189   - :cvar dict COMPILED_CODES: Translation dict. Keys are ANSI codes (values of BASE_CODES), values are Windows codes.
190   - :ivar int default_fg: Foreground Windows color code at the time of instantiation.
191   - :ivar int default_bg: Background Windows color code at the time of instantiation.
192   - """
193   -
194   - ALL_BG_CODES = [v for k, v in WINDOWS_CODES.items() if k.startswith('bg') or k.startswith('hibg')]
195   - COMPILED_CODES = dict((v, WINDOWS_CODES[k]) for k, v in BASE_CODES.items() if k in WINDOWS_CODES)
196   -
197   - def __init__(self, kernel32, stream_handle, original_stream):
198   - """Constructor.
199   -
200   - :param ctypes.windll.kernel32 kernel32: Loaded kernel32 instance.
201   - :param int stream_handle: stderr or stdout handle.
202   - :param original_stream: sys.stderr or sys.stdout before being overridden by this class' instance.
203   - """
204   - self._kernel32 = kernel32
205   - self._stream_handle = stream_handle
206   - self._original_stream = original_stream
207   - self.default_fg, self.default_bg = self.colors
208   -
209   - def __getattr__(self, item):
210   - """If an attribute/function/etc is not defined in this function, retrieve the one from the original stream.
211   -
212   - Fixes ipython arrow key presses.
213   - """
214   - return getattr(self._original_stream, item)
215   -
216   - @property
217   - def colors(self):
218   - """Return the current foreground and background colors."""
219   - try:
220   - return get_console_info(self._kernel32, self._stream_handle)[:2]
221   - except OSError:
222   - return WINDOWS_CODES['white'], WINDOWS_CODES['black']
223   -
224   - @colors.setter
225   - def colors(self, color_code):
226   - """Change the foreground and background colors for subsequently printed characters.
227   -
228   - None resets colors to their original values (when class was instantiated).
229   -
230   - Since setting a color requires including both foreground and background codes (merged), setting just the
231   - foreground color resets the background color to black, and vice versa.
232   -
233   - This function first gets the current background and foreground colors, merges in the requested color code, and
234   - sets the result.
235   -
236   - However if we need to remove just the foreground color but leave the background color the same (or vice versa)
237   - such as when {/red} is used, we must merge the default foreground color with the current background color. This
238   - is the reason for those negative values.
239   -
240   - :param int color_code: Color code from WINDOWS_CODES.
241   - """
242   - if color_code is None:
243   - color_code = WINDOWS_CODES['/all']
244   -
245   - # Get current color code.
246   - current_fg, current_bg = self.colors
247   -
248   - # Handle special negative codes. Also determine the final color code.
249   - if color_code == WINDOWS_CODES['/fg']:
250   - final_color_code = self.default_fg | current_bg # Reset the foreground only.
251   - elif color_code == WINDOWS_CODES['/bg']:
252   - final_color_code = current_fg | self.default_bg # Reset the background only.
253   - elif color_code == WINDOWS_CODES['/all']:
254   - final_color_code = self.default_fg | self.default_bg # Reset both.
255   - elif color_code == WINDOWS_CODES['bgblack']:
256   - final_color_code = current_fg # Black background.
257   - else:
258   - new_is_bg = color_code in self.ALL_BG_CODES
259   - final_color_code = color_code | (current_fg if new_is_bg else current_bg)
260   -
261   - # Set new code.
262   - self._kernel32.SetConsoleTextAttribute(self._stream_handle, final_color_code)
263   -
264   - def write(self, p_str):
265   - """Write to stream.
266   -
267   - :param str p_str: string to print.
268   - """
269   - for segment in RE_SPLIT.split(p_str):
270   - if not segment:
271   - # Empty string. p_str probably starts with colors so the first item is always ''.
272   - continue
273   - if not RE_SPLIT.match(segment):
274   - # No color codes, print regular text.
275   - print(segment, file=self._original_stream, end='')
276   - self._original_stream.flush()
277   - continue
278   - for color_code in (int(c) for c in RE_NUMBER_SEARCH.findall(segment)[0].split(';')):
279   - if color_code in self.COMPILED_CODES:
280   - self.colors = self.COMPILED_CODES[color_code]
281   -
282   -
283   -class Windows(object):
284   - """Enable and disable Windows support for ANSI color character codes.
285   -
286   - Call static method Windows.enable() to enable color support for the remainder of the process' lifetime.
287   -
288   - This class is also a context manager. You can do this:
289   - with Windows():
290   - print(Color('{autored}Test{/autored}'))
291   -
292   - Or this:
293   - with Windows(auto_colors=True):
294   - print(Color('{autored}Test{/autored}'))
295   - """
296   -
297   - @classmethod
298   - def disable(cls):
299   - """Restore sys.stderr and sys.stdout to their original objects. Resets colors to their original values.
300   -
301   - :return: If streams restored successfully.
302   - :rtype: bool
303   - """
304   - # Skip if not on Windows.
305   - if not IS_WINDOWS:
306   - return False
307   -
308   - # Restore default colors.
309   - if hasattr(sys.stderr, '_original_stream'):
310   - getattr(sys, 'stderr').color = None
311   - if hasattr(sys.stdout, '_original_stream'):
312   - getattr(sys, 'stdout').color = None
313   -
314   - # Restore original streams.
315   - changed = False
316   - if hasattr(sys.stderr, '_original_stream'):
317   - changed = True
318   - sys.stderr = getattr(sys.stderr, '_original_stream')
319   - if hasattr(sys.stdout, '_original_stream'):
320   - changed = True
321   - sys.stdout = getattr(sys.stdout, '_original_stream')
322   -
323   - return changed
324   -
325   - @staticmethod
326   - def is_enabled():
327   - """Return True if either stderr or stdout has colors enabled."""
328   - return hasattr(sys.stderr, '_original_stream') or hasattr(sys.stdout, '_original_stream')
329   -
330   - @classmethod
331   - def enable(cls, auto_colors=False, reset_atexit=False):
332   - """Enable color text with print() or sys.stdout.write() (stderr too).
333   -
334   - :param bool auto_colors: Automatically selects dark or light colors based on current terminal's background
335   - color. Only works with {autored} and related tags.
336   - :param bool reset_atexit: Resets original colors upon Python exit (in case you forget to reset it yourself with
337   - a closing tag). Does nothing on native ANSI consoles.
338   -
339   - :return: If streams replaced successfully.
340   - :rtype: bool
341   - """
342   - if not IS_WINDOWS:
343   - return False # Windows only.
344   -
345   - # Get values from init_kernel32().
346   - kernel32, stderr, stdout = init_kernel32()
347   - if stderr == INVALID_HANDLE_VALUE and stdout == INVALID_HANDLE_VALUE:
348   - return False # No valid handles, nothing to do.
349   -
350   - # Get console info.
351   - bg_color, native_ansi = bg_color_native_ansi(kernel32, stderr, stdout)
352   -
353   - # Set auto colors:
354   - if auto_colors:
355   - if bg_color in (112, 96, 240, 176, 224, 208, 160):
356   - ANSICodeMapping.set_light_background()
357   - else:
358   - ANSICodeMapping.set_dark_background()
359   -
360   - # Don't replace streams if ANSI codes are natively supported.
361   - if native_ansi:
362   - return False
363   -
364   - # Reset on exit if requested.
365   - if reset_atexit:
366   - atexit.register(cls.disable)
367   -
368   - # Overwrite stream references.
369   - if stderr != INVALID_HANDLE_VALUE:
370   - sys.stderr.flush()
371   - sys.stderr = WindowsStream(kernel32, stderr, sys.stderr)
372   - if stdout != INVALID_HANDLE_VALUE:
373   - sys.stdout.flush()
374   - sys.stdout = WindowsStream(kernel32, stdout, sys.stdout)
375   -
376   - return True
377   -
378   - def __init__(self, auto_colors=False):
379   - """Constructor."""
380   - self.auto_colors = auto_colors
381   -
382   - def __enter__(self):
383   - """Context manager, enables colors on Windows."""
384   - self.enable(auto_colors=self.auto_colors)
385   -
386   - def __exit__(self, *_):
387   - """Context manager, disabled colors on Windows."""
388   - self.disable()
oletools/thirdparty/tablestream/tablestream.py
... ... @@ -19,7 +19,7 @@ License: BSD, see source code or documentation
19 19  
20 20 #=== LICENSE ==================================================================
21 21  
22   -# tablestream is copyright (c) 2015-2016 Philippe Lagadec (http://www.decalage.info)
  22 +# tablestream is copyright (c) 2015-2018 Philippe Lagadec (http://www.decalage.info)
23 23 # All rights reserved.
24 24 #
25 25 # Redistribution and use in source and binary forms, with or without modification,
... ... @@ -54,8 +54,9 @@ from __future__ import print_function
54 54 # 2016-07-31 v0.06 PL: - handle newline characters properly in each cell
55 55 # 2016-08-28 v0.07 PL: - support for both Python 2.6+ and 3.x
56 56 # - all cells are converted to unicode
  57 +# 2018-09-22 v0.08 PL: - removed mention to oletools' thirdparty folder
57 58  
58   -__version__ = '0.07'
  59 +__version__ = '0.08'
59 60  
60 61 #------------------------------------------------------------------------------
61 62 # TODO:
... ... @@ -70,15 +71,6 @@ __version__ = &#39;0.07&#39;
70 71 import textwrap
71 72 import sys, os
72 73  
73   -# add the thirdparty subfolder to sys.path (absolute+normalized path):
74   -_thismodule_dir = os.path.normpath(os.path.abspath(os.path.dirname(__file__)))
75   -# print('_thismodule_dir = %r' % _thismodule_dir)
76   -# assumption: this module is in a subfolder of thirdparty:
77   -_thirdparty_dir = os.path.normpath(os.path.join(_thismodule_dir, '..'))
78   -# print('_thirdparty_dir = %r' % _thirdparty_dir)
79   -if not _thirdparty_dir in sys.path:
80   - sys.path.insert(0, _thirdparty_dir)
81   -
82 74 import colorclass
83 75  
84 76 # On Windows, colorclass needs to be enabled:
... ...
setup.py
... ... @@ -26,6 +26,7 @@ to install this package.
26 26 # 2018-03-19 v0.52.3 PL: - added install_requires, removed thirdparty.pyparsing
27 27 # 2018-09-11 v0.54 PL: - olefile is now a dependency
28 28 # 2018-09-15 PL: - easygui is now a dependency
  29 +# 2018-09-22 PL: - colorclass is now a dependency
29 30  
30 31 #--- TODO ---------------------------------------------------------------------
31 32  
... ... @@ -85,7 +86,6 @@ packages=[
85 86 'oletools.thirdparty.prettytable',
86 87 'oletools.thirdparty.xglob',
87 88 'oletools.thirdparty.DridexUrlDecoder',
88   - 'oletools.thirdparty.colorclass',
89 89 'oletools.thirdparty.tablestream',
90 90 'oletools.thirdparty.zipfile27',
91 91 ]
... ... @@ -175,9 +175,6 @@ package_data={
175 175 'oletools.thirdparty.DridexUrlDecoder': [
176 176 'LICENSE.txt',
177 177 ],
178   - 'oletools.thirdparty.colorclass': [
179   - 'LICENSE.txt',
180   - ],
181 178 'oletools.thirdparty.zipfile27': [
182 179 'LICENSE.txt',
183 180 ],
... ... @@ -318,6 +315,7 @@ def main():
318 315 "pyparsing>=2.2.0",
319 316 "olefile>=0.46",
320 317 "easygui",
  318 + 'colorclass',
321 319 ],
322 320 )
323 321  
... ...