Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sqlmapproject
GitHub Repository: sqlmapproject/sqlmap
Path: blob/master/lib/core/convert.py
3554 views
1
#!/usr/bin/env python
2
3
"""
4
Copyright (c) 2006-2026 sqlmap developers (https://sqlmap.org)
5
See the file 'LICENSE' for copying permission
6
"""
7
8
try:
9
import cPickle as pickle
10
except:
11
import pickle
12
13
import base64
14
import binascii
15
import codecs
16
import json
17
import re
18
import sys
19
import time
20
21
from lib.core.bigarray import BigArray
22
from lib.core.compat import xrange
23
from lib.core.data import conf
24
from lib.core.data import kb
25
from lib.core.settings import INVALID_UNICODE_PRIVATE_AREA
26
from lib.core.settings import IS_TTY
27
from lib.core.settings import IS_WIN
28
from lib.core.settings import NULL
29
from lib.core.settings import PICKLE_PROTOCOL
30
from lib.core.settings import SAFE_HEX_MARKER
31
from lib.core.settings import UNICODE_ENCODING
32
from thirdparty import six
33
from thirdparty.six import unichr as _unichr
34
from thirdparty.six.moves import html_parser
35
from thirdparty.six.moves import collections_abc as _collections
36
37
try:
38
from html import escape as htmlEscape
39
except ImportError:
40
from cgi import escape as htmlEscape
41
42
def base64pickle(value):
43
"""
44
Serializes (with pickle) and encodes to Base64 format supplied (binary) value
45
46
>>> base64unpickle(base64pickle([1, 2, 3])) == [1, 2, 3]
47
True
48
"""
49
50
retVal = None
51
52
try:
53
retVal = encodeBase64(pickle.dumps(value, PICKLE_PROTOCOL), binary=False)
54
except:
55
warnMsg = "problem occurred while serializing "
56
warnMsg += "instance of a type '%s'" % type(value)
57
singleTimeWarnMessage(warnMsg)
58
59
try:
60
retVal = encodeBase64(pickle.dumps(value), binary=False)
61
except:
62
raise
63
64
return retVal
65
66
def base64unpickle(value):
67
"""
68
Decodes value from Base64 to plain format and deserializes (with pickle) its content
69
70
>>> type(base64unpickle('gAJjX19idWlsdGluX18Kb2JqZWN0CnEBKYFxAi4=')) == object
71
True
72
"""
73
74
retVal = None
75
76
try:
77
retVal = pickle.loads(decodeBase64(value))
78
except TypeError:
79
retVal = pickle.loads(decodeBase64(bytes(value)))
80
81
return retVal
82
83
def htmlUnescape(value):
84
"""
85
Returns HTML unescaped value
86
87
>>> htmlUnescape('a&lt;b') == 'a<b'
88
True
89
>>> htmlUnescape('a&lt;b') == 'a<b'
90
True
91
>>> htmlUnescape('&#x66;&#x6f;&#x6f;&#x62;&#x61;&#x72;') == 'foobar'
92
True
93
>>> htmlUnescape('&#102;&#111;&#111;&#98;&#97;&#114;') == 'foobar'
94
True
95
>>> htmlUnescape('&copy;&euro;') == htmlUnescape('&#xA9;&#x20AC;')
96
True
97
"""
98
99
if value and isinstance(value, six.string_types):
100
if six.PY3:
101
import html
102
return html.unescape(value)
103
else:
104
return html_parser.HTMLParser().unescape(value)
105
return value
106
107
def singleTimeWarnMessage(message): # Cross-referenced function
108
sys.stdout.write(message)
109
sys.stdout.write("\n")
110
sys.stdout.flush()
111
112
def filterNone(values): # Cross-referenced function
113
return [_ for _ in values if _] if isinstance(values, _collections.Iterable) else values
114
115
def isListLike(value): # Cross-referenced function
116
return isinstance(value, (list, tuple, set, BigArray))
117
118
def shellExec(cmd): # Cross-referenced function
119
raise NotImplementedError
120
121
def jsonize(data):
122
"""
123
Returns JSON serialized data
124
125
>>> jsonize({'foo':'bar'})
126
'{\\n "foo": "bar"\\n}'
127
"""
128
129
return json.dumps(data, sort_keys=False, indent=4)
130
131
def dejsonize(data):
132
"""
133
Returns JSON deserialized data
134
135
>>> dejsonize('{\\n "foo": "bar"\\n}') == {u'foo': u'bar'}
136
True
137
"""
138
139
return json.loads(data)
140
141
def decodeHex(value, binary=True):
142
"""
143
Returns a decoded representation of the provided hexadecimal value
144
145
>>> decodeHex("313233") == b"123"
146
True
147
>>> decodeHex("313233", binary=False) == u"123"
148
True
149
"""
150
151
retVal = value
152
153
if isinstance(value, six.binary_type):
154
value = getText(value)
155
156
if value.lower().startswith("0x"):
157
value = value[2:]
158
159
try:
160
retVal = codecs.decode(value, "hex")
161
except LookupError:
162
retVal = binascii.unhexlify(value)
163
164
if not binary:
165
retVal = getText(retVal)
166
167
return retVal
168
169
def encodeHex(value, binary=True):
170
"""
171
Returns an encoded representation of the provided value
172
173
>>> encodeHex(b"123") == b"313233"
174
True
175
>>> encodeHex("123", binary=False)
176
'313233'
177
>>> encodeHex(b"123"[0]) == b"31"
178
True
179
>>> encodeHex(123, binary=False)
180
'7b'
181
"""
182
183
if isinstance(value, int):
184
value = six.int2byte(value)
185
186
if isinstance(value, six.text_type):
187
value = value.encode(UNICODE_ENCODING)
188
189
try:
190
retVal = codecs.encode(value, "hex")
191
except LookupError:
192
retVal = binascii.hexlify(value)
193
194
if not binary:
195
retVal = getText(retVal)
196
197
return retVal
198
199
def decodeBase64(value, binary=True, encoding=None):
200
"""
201
Returns a decoded representation of provided Base64 value
202
203
>>> decodeBase64("MTIz") == b"123"
204
True
205
>>> decodeBase64("MTIz", binary=False)
206
'123'
207
>>> decodeBase64("A-B_CDE") == decodeBase64("A+B/CDE")
208
True
209
>>> decodeBase64(b"MTIzNA") == b"1234"
210
True
211
>>> decodeBase64("MTIzNA") == b"1234"
212
True
213
>>> decodeBase64("MTIzNA==") == b"1234"
214
True
215
"""
216
217
if value is None:
218
return None
219
220
padding = b'=' if isinstance(value, bytes) else '='
221
222
# Reference: https://stackoverflow.com/a/49459036
223
if not value.endswith(padding):
224
value += 3 * padding
225
226
# Reference: https://en.wikipedia.org/wiki/Base64#URL_applications
227
# Reference: https://perldoc.perl.org/MIME/Base64.html
228
if isinstance(value, bytes):
229
value = value.replace(b'-', b'+').replace(b'_', b'/')
230
else:
231
value = value.replace('-', '+').replace('_', '/')
232
233
retVal = base64.b64decode(value)
234
235
if not binary:
236
retVal = getText(retVal, encoding)
237
238
return retVal
239
240
def encodeBase64(value, binary=True, encoding=None, padding=True, safe=False):
241
"""
242
Returns a Base64 encoded representation of the provided value
243
244
>>> encodeBase64(b"123") == b"MTIz"
245
True
246
>>> encodeBase64(u"1234", binary=False)
247
'MTIzNA=='
248
>>> encodeBase64(u"1234", binary=False, padding=False)
249
'MTIzNA'
250
>>> encodeBase64(decodeBase64("A-B_CDE"), binary=False, safe=True)
251
'A-B_CDE'
252
"""
253
254
if value is None:
255
return None
256
257
if isinstance(value, six.text_type):
258
value = value.encode(encoding or UNICODE_ENCODING)
259
260
retVal = base64.b64encode(value)
261
262
if not binary:
263
retVal = getText(retVal, encoding)
264
265
if safe:
266
padding = False
267
268
# Reference: https://en.wikipedia.org/wiki/Base64#URL_applications
269
# Reference: https://perldoc.perl.org/MIME/Base64.html
270
if isinstance(retVal, bytes):
271
retVal = retVal.replace(b'+', b'-').replace(b'/', b'_')
272
else:
273
retVal = retVal.replace('+', '-').replace('/', '_')
274
275
if not padding:
276
retVal = retVal.rstrip(b'=' if isinstance(retVal, bytes) else '=')
277
278
return retVal
279
280
def getBytes(value, encoding=None, errors="strict", unsafe=True):
281
"""
282
Returns byte representation of provided Unicode value
283
284
>>> getBytes(u"foo\\\\x01\\\\x83\\\\xffbar") == b"foo\\x01\\x83\\xffbar"
285
True
286
"""
287
288
retVal = value
289
290
if encoding is None:
291
encoding = conf.get("encoding") or UNICODE_ENCODING
292
293
try:
294
codecs.lookup(encoding)
295
except (LookupError, TypeError):
296
encoding = UNICODE_ENCODING
297
298
if isinstance(value, bytearray):
299
return bytes(value)
300
elif isinstance(value, memoryview):
301
return value.tobytes()
302
elif isinstance(value, six.text_type):
303
if INVALID_UNICODE_PRIVATE_AREA:
304
if unsafe:
305
for char in xrange(0xF0000, 0xF00FF + 1):
306
value = value.replace(_unichr(char), "%s%02x" % (SAFE_HEX_MARKER, char - 0xF0000))
307
308
retVal = value.encode(encoding, errors)
309
310
if unsafe:
311
retVal = re.sub((r"%s([0-9a-f]{2})" % SAFE_HEX_MARKER).encode(), lambda _: decodeHex(_.group(1)), retVal)
312
else:
313
try:
314
retVal = value.encode(encoding, errors)
315
except UnicodeError:
316
retVal = value.encode(UNICODE_ENCODING, errors="replace")
317
318
if unsafe:
319
retVal = re.sub(b"\\\\x([0-9a-f]{2})", lambda _: decodeHex(_.group(1)), retVal)
320
321
return retVal
322
323
def getOrds(value):
324
"""
325
Returns ORD(...) representation of provided string value
326
327
>>> getOrds(u'fo\\xf6bar')
328
[102, 111, 246, 98, 97, 114]
329
>>> getOrds(b"fo\\xc3\\xb6bar")
330
[102, 111, 195, 182, 98, 97, 114]
331
"""
332
333
return [_ if isinstance(_, int) else ord(_) for _ in value]
334
335
def getUnicode(value, encoding=None, noneToNull=False):
336
"""
337
Returns the unicode representation of the supplied value
338
339
>>> getUnicode('test') == u'test'
340
True
341
>>> getUnicode(1) == u'1'
342
True
343
>>> getUnicode(None) == 'None'
344
True
345
>>> getUnicode(b'/etc/passwd') == '/etc/passwd'
346
True
347
"""
348
349
# Best position for --time-limit mechanism
350
if conf.get("timeLimit") and kb.get("startTime") and (time.time() - kb.startTime > conf.timeLimit):
351
raise SystemExit
352
353
if noneToNull and value is None:
354
return NULL
355
356
if isinstance(value, six.text_type):
357
return value
358
elif isinstance(value, six.binary_type):
359
# Heuristics (if encoding not explicitly specified)
360
candidates = filterNone((encoding, kb.get("pageEncoding") if kb.get("originalPage") else None, conf.get("encoding"), UNICODE_ENCODING, sys.getfilesystemencoding()))
361
if all(_ in value for _ in (b'<', b'>')):
362
pass
363
elif b'\n' not in value and re.search(r"(?i)\w+\.\w{2,3}\Z|\A(\w:\\|/\w+)", six.text_type(value, UNICODE_ENCODING, errors="ignore")):
364
candidates = filterNone((encoding, sys.getfilesystemencoding(), kb.get("pageEncoding") if kb.get("originalPage") else None, UNICODE_ENCODING, conf.get("encoding")))
365
elif conf.get("encoding") and b'\n' not in value:
366
candidates = filterNone((encoding, conf.get("encoding"), kb.get("pageEncoding") if kb.get("originalPage") else None, sys.getfilesystemencoding(), UNICODE_ENCODING))
367
368
for candidate in candidates:
369
try:
370
return six.text_type(value, candidate)
371
except (UnicodeDecodeError, LookupError):
372
pass
373
374
try:
375
return six.text_type(value, encoding or (kb.get("pageEncoding") if kb.get("originalPage") else None) or UNICODE_ENCODING)
376
except UnicodeDecodeError:
377
return six.text_type(value, UNICODE_ENCODING, errors="reversible")
378
elif isListLike(value):
379
value = list(getUnicode(_, encoding, noneToNull) for _ in value)
380
return value
381
else:
382
try:
383
return six.text_type(value)
384
except UnicodeDecodeError:
385
return six.text_type(str(value), errors="ignore") # encoding ignored for non-basestring instances
386
387
def getText(value, encoding=None):
388
"""
389
Returns textual value of a given value (Note: not necessary Unicode on Python2)
390
391
>>> getText(b"foobar")
392
'foobar'
393
>>> isinstance(getText(u"fo\\u2299bar"), six.text_type)
394
True
395
"""
396
397
retVal = value
398
399
if isinstance(value, six.binary_type):
400
retVal = getUnicode(value, encoding)
401
402
if six.PY2:
403
try:
404
retVal = str(retVal)
405
except:
406
pass
407
408
return retVal
409
410
def stdoutEncode(value):
411
"""
412
Returns textual representation of a given value safe for writing to stdout
413
>>> stdoutEncode(b"foobar")
414
'foobar'
415
"""
416
417
if value is None:
418
value = ""
419
420
if IS_WIN and IS_TTY and kb.get("codePage", -1) is None:
421
output = shellExec("chcp")
422
match = re.search(r": (\d{3,})", output or "")
423
424
if match:
425
try:
426
candidate = "cp%s" % match.group(1)
427
codecs.lookup(candidate)
428
kb.codePage = candidate
429
except (LookupError, TypeError):
430
pass
431
432
kb.codePage = kb.codePage or ""
433
434
encoding = kb.get("codePage") or getattr(sys.stdout, "encoding", None) or UNICODE_ENCODING
435
436
if six.PY3:
437
if isinstance(value, (bytes, bytearray)):
438
value = getUnicode(value, encoding)
439
elif not isinstance(value, str):
440
value = str(value)
441
442
try:
443
retVal = value.encode(encoding, errors="replace").decode(encoding, errors="replace")
444
except (LookupError, TypeError):
445
retVal = value.encode("ascii", errors="replace").decode("ascii", errors="replace")
446
else:
447
if isinstance(value, six.text_type):
448
try:
449
retVal = value.encode(encoding, errors="replace")
450
except (LookupError, TypeError):
451
retVal = value.encode("ascii", errors="replace")
452
else:
453
retVal = value
454
455
return retVal
456
457
def getConsoleLength(value):
458
"""
459
Returns console width of unicode values
460
461
>>> getConsoleLength("abc")
462
3
463
>>> getConsoleLength(u"\\u957f\\u6c5f")
464
4
465
"""
466
467
if isinstance(value, six.text_type):
468
retVal = len(value) + sum(ord(_) >= 0x3000 for _ in value)
469
else:
470
retVal = len(value)
471
472
return retVal
473
474