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