Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sqlmapproject
GitHub Repository: sqlmapproject/sqlmap
Path: blob/master/thirdparty/colorama/ansitowin32.py
2992 views
1
# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file.
2
import re
3
import sys
4
import os
5
6
from .ansi import AnsiFore, AnsiBack, AnsiStyle, Style
7
from .winterm import WinTerm, WinColor, WinStyle
8
from .win32 import windll, winapi_test
9
10
11
winterm = None
12
if windll is not None:
13
winterm = WinTerm()
14
15
16
def is_stream_closed(stream):
17
return not hasattr(stream, 'closed') or stream.closed
18
19
20
def is_a_tty(stream):
21
return hasattr(stream, 'isatty') and stream.isatty()
22
23
24
class StreamWrapper(object):
25
'''
26
Wraps a stream (such as stdout), acting as a transparent proxy for all
27
attribute access apart from method 'write()', which is delegated to our
28
Converter instance.
29
'''
30
def __init__(self, wrapped, converter):
31
# double-underscore everything to prevent clashes with names of
32
# attributes on the wrapped stream object.
33
self.__wrapped = wrapped
34
self.__convertor = converter
35
36
def __getattr__(self, name):
37
return getattr(self.__wrapped, name)
38
39
def write(self, text):
40
self.__convertor.write(text)
41
42
43
class AnsiToWin32(object):
44
'''
45
Implements a 'write()' method which, on Windows, will strip ANSI character
46
sequences from the text, and if outputting to a tty, will convert them into
47
win32 function calls.
48
'''
49
ANSI_CSI_RE = re.compile('\001?\033\\[((?:\\d|;)*)([a-zA-Z])\002?') # Control Sequence Introducer
50
ANSI_OSC_RE = re.compile('\001?\033\\]([^\a]*)(\a)\002?') # Operating System Command (Note: https://github.com/tartley/colorama/issues/247)
51
52
def __init__(self, wrapped, convert=None, strip=None, autoreset=False):
53
# The wrapped stream (normally sys.stdout or sys.stderr)
54
self.wrapped = wrapped
55
56
# should we reset colors to defaults after every .write()
57
self.autoreset = autoreset
58
59
# create the proxy wrapping our output stream
60
self.stream = StreamWrapper(wrapped, self)
61
62
on_windows = os.name == 'nt'
63
# We test if the WinAPI works, because even if we are on Windows
64
# we may be using a terminal that doesn't support the WinAPI
65
# (e.g. Cygwin Terminal). In this case it's up to the terminal
66
# to support the ANSI codes.
67
conversion_supported = on_windows and winapi_test()
68
69
# should we strip ANSI sequences from our output?
70
if strip is None:
71
strip = conversion_supported or (not is_stream_closed(wrapped) and not is_a_tty(wrapped))
72
self.strip = strip
73
74
# should we should convert ANSI sequences into win32 calls?
75
if convert is None:
76
convert = conversion_supported and not is_stream_closed(wrapped) and is_a_tty(wrapped)
77
self.convert = convert
78
79
# dict of ansi codes to win32 functions and parameters
80
self.win32_calls = self.get_win32_calls()
81
82
# are we wrapping stderr?
83
self.on_stderr = self.wrapped is sys.stderr
84
85
def should_wrap(self):
86
'''
87
True if this class is actually needed. If false, then the output
88
stream will not be affected, nor will win32 calls be issued, so
89
wrapping stdout is not actually required. This will generally be
90
False on non-Windows platforms, unless optional functionality like
91
autoreset has been requested using kwargs to init()
92
'''
93
return self.convert or self.strip or self.autoreset
94
95
def get_win32_calls(self):
96
if self.convert and winterm:
97
return {
98
AnsiStyle.RESET_ALL: (winterm.reset_all, ),
99
AnsiStyle.BRIGHT: (winterm.style, WinStyle.BRIGHT),
100
AnsiStyle.DIM: (winterm.style, WinStyle.NORMAL),
101
AnsiStyle.NORMAL: (winterm.style, WinStyle.NORMAL),
102
AnsiFore.BLACK: (winterm.fore, WinColor.BLACK),
103
AnsiFore.RED: (winterm.fore, WinColor.RED),
104
AnsiFore.GREEN: (winterm.fore, WinColor.GREEN),
105
AnsiFore.YELLOW: (winterm.fore, WinColor.YELLOW),
106
AnsiFore.BLUE: (winterm.fore, WinColor.BLUE),
107
AnsiFore.MAGENTA: (winterm.fore, WinColor.MAGENTA),
108
AnsiFore.CYAN: (winterm.fore, WinColor.CYAN),
109
AnsiFore.WHITE: (winterm.fore, WinColor.GREY),
110
AnsiFore.RESET: (winterm.fore, ),
111
AnsiFore.LIGHTBLACK_EX: (winterm.fore, WinColor.BLACK, True),
112
AnsiFore.LIGHTRED_EX: (winterm.fore, WinColor.RED, True),
113
AnsiFore.LIGHTGREEN_EX: (winterm.fore, WinColor.GREEN, True),
114
AnsiFore.LIGHTYELLOW_EX: (winterm.fore, WinColor.YELLOW, True),
115
AnsiFore.LIGHTBLUE_EX: (winterm.fore, WinColor.BLUE, True),
116
AnsiFore.LIGHTMAGENTA_EX: (winterm.fore, WinColor.MAGENTA, True),
117
AnsiFore.LIGHTCYAN_EX: (winterm.fore, WinColor.CYAN, True),
118
AnsiFore.LIGHTWHITE_EX: (winterm.fore, WinColor.GREY, True),
119
AnsiBack.BLACK: (winterm.back, WinColor.BLACK),
120
AnsiBack.RED: (winterm.back, WinColor.RED),
121
AnsiBack.GREEN: (winterm.back, WinColor.GREEN),
122
AnsiBack.YELLOW: (winterm.back, WinColor.YELLOW),
123
AnsiBack.BLUE: (winterm.back, WinColor.BLUE),
124
AnsiBack.MAGENTA: (winterm.back, WinColor.MAGENTA),
125
AnsiBack.CYAN: (winterm.back, WinColor.CYAN),
126
AnsiBack.WHITE: (winterm.back, WinColor.GREY),
127
AnsiBack.RESET: (winterm.back, ),
128
AnsiBack.LIGHTBLACK_EX: (winterm.back, WinColor.BLACK, True),
129
AnsiBack.LIGHTRED_EX: (winterm.back, WinColor.RED, True),
130
AnsiBack.LIGHTGREEN_EX: (winterm.back, WinColor.GREEN, True),
131
AnsiBack.LIGHTYELLOW_EX: (winterm.back, WinColor.YELLOW, True),
132
AnsiBack.LIGHTBLUE_EX: (winterm.back, WinColor.BLUE, True),
133
AnsiBack.LIGHTMAGENTA_EX: (winterm.back, WinColor.MAGENTA, True),
134
AnsiBack.LIGHTCYAN_EX: (winterm.back, WinColor.CYAN, True),
135
AnsiBack.LIGHTWHITE_EX: (winterm.back, WinColor.GREY, True),
136
}
137
return dict()
138
139
def write(self, text):
140
if self.strip or self.convert:
141
self.write_and_convert(text)
142
else:
143
self.wrapped.write(text)
144
self.wrapped.flush()
145
if self.autoreset:
146
self.reset_all()
147
148
149
def reset_all(self):
150
if self.convert:
151
self.call_win32('m', (0,))
152
elif not self.strip and not is_stream_closed(self.wrapped):
153
self.wrapped.write(Style.RESET_ALL)
154
155
156
def write_and_convert(self, text):
157
'''
158
Write the given text to our wrapped stream, stripping any ANSI
159
sequences from the text, and optionally converting them into win32
160
calls.
161
'''
162
cursor = 0
163
text = self.convert_osc(text)
164
for match in self.ANSI_CSI_RE.finditer(text):
165
start, end = match.span()
166
self.write_plain_text(text, cursor, start)
167
self.convert_ansi(*match.groups())
168
cursor = end
169
self.write_plain_text(text, cursor, len(text))
170
171
172
def write_plain_text(self, text, start, end):
173
if start < end:
174
self._write(text[start:end])
175
self.wrapped.flush()
176
177
# Reference: https://github.com/robotframework/robotframework/commit/828c67695d85519e4435c556c43ed1b00985df05
178
# Workaround for Windows 10 console bug:
179
# https://github.com/robotframework/robotframework/issues/2709
180
def _write(self, text, retry=5):
181
try:
182
self.wrapped.write(text)
183
except IOError as err:
184
if not (err.errno == 0 and retry > 0):
185
raise
186
self._write(text, retry-1)
187
except UnicodeError:
188
self.wrapped.write('?')
189
190
def convert_ansi(self, paramstring, command):
191
if self.convert:
192
params = self.extract_params(command, paramstring)
193
self.call_win32(command, params)
194
195
196
def extract_params(self, command, paramstring):
197
if command in 'Hf':
198
params = tuple(int(p) if len(p) != 0 else 1 for p in paramstring.split(';'))
199
while len(params) < 2:
200
# defaults:
201
params = params + (1,)
202
else:
203
params = tuple(int(p) for p in paramstring.split(';') if len(p) != 0)
204
if len(params) == 0:
205
# defaults:
206
if command in 'JKm':
207
params = (0,)
208
elif command in 'ABCD':
209
params = (1,)
210
211
return params
212
213
214
def call_win32(self, command, params):
215
if command == 'm':
216
for param in params:
217
if param in self.win32_calls:
218
func_args = self.win32_calls[param]
219
func = func_args[0]
220
args = func_args[1:]
221
kwargs = dict(on_stderr=self.on_stderr)
222
func(*args, **kwargs)
223
elif command in 'J':
224
winterm.erase_screen(params[0], on_stderr=self.on_stderr)
225
elif command in 'K':
226
winterm.erase_line(params[0], on_stderr=self.on_stderr)
227
elif command in 'Hf': # cursor position - absolute
228
winterm.set_cursor_position(params, on_stderr=self.on_stderr)
229
elif command in 'ABCD': # cursor position - relative
230
n = params[0]
231
# A - up, B - down, C - forward, D - back
232
x, y = {'A': (0, -n), 'B': (0, n), 'C': (n, 0), 'D': (-n, 0)}[command]
233
winterm.cursor_adjust(x, y, on_stderr=self.on_stderr)
234
235
236
def convert_osc(self, text):
237
for match in self.ANSI_OSC_RE.finditer(text):
238
start, end = match.span()
239
text = text[:start] + text[end:]
240
paramstring, command = match.groups()
241
if command in '\x07': # \x07 = BEL
242
params = paramstring.split(";")
243
# 0 - change title and icon (we will only change title)
244
# 1 - change icon (we don't support this)
245
# 2 - change title
246
# if params[0] in '02':
247
# winterm.set_title(params[1])
248
return text
249
250