Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sqlmapproject
GitHub Repository: sqlmapproject/sqlmap
Path: blob/master/lib/core/compat.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
from __future__ import division
9
10
import binascii
11
import functools
12
import math
13
import os
14
import random
15
import re
16
import sys
17
import time
18
import uuid
19
20
class WichmannHill(random.Random):
21
"""
22
Reference: https://svn.python.org/projects/python/trunk/Lib/random.py
23
"""
24
25
VERSION = 1 # used by getstate/setstate
26
27
def seed(self, a=None):
28
"""Initialize internal state from hashable object.
29
30
None or no argument seeds from current time or from an operating
31
system specific randomness source if available.
32
33
If a is not None or an int or long, hash(a) is used instead.
34
35
If a is an int or long, a is used directly. Distinct values between
36
0 and 27814431486575L inclusive are guaranteed to yield distinct
37
internal states (this guarantee is specific to the default
38
Wichmann-Hill generator).
39
"""
40
41
if a is None:
42
try:
43
a = int(binascii.hexlify(os.urandom(16)), 16)
44
except NotImplementedError:
45
a = int(time.time() * 256) # use fractional seconds
46
47
if not isinstance(a, int):
48
a = hash(a)
49
50
a, x = divmod(a, 30268)
51
a, y = divmod(a, 30306)
52
a, z = divmod(a, 30322)
53
self._seed = int(x) + 1, int(y) + 1, int(z) + 1
54
55
self.gauss_next = None
56
57
def random(self):
58
"""Get the next random number in the range [0.0, 1.0)."""
59
60
# Wichman-Hill random number generator.
61
#
62
# Wichmann, B. A. & Hill, I. D. (1982)
63
# Algorithm AS 183:
64
# An efficient and portable pseudo-random number generator
65
# Applied Statistics 31 (1982) 188-190
66
#
67
# see also:
68
# Correction to Algorithm AS 183
69
# Applied Statistics 33 (1984) 123
70
#
71
# McLeod, A. I. (1985)
72
# A remark on Algorithm AS 183
73
# Applied Statistics 34 (1985),198-200
74
75
# This part is thread-unsafe:
76
# BEGIN CRITICAL SECTION
77
x, y, z = self._seed
78
x = (171 * x) % 30269
79
y = (172 * y) % 30307
80
z = (170 * z) % 30323
81
self._seed = x, y, z
82
# END CRITICAL SECTION
83
84
# Note: on a platform using IEEE-754 double arithmetic, this can
85
# never return 0.0 (asserted by Tim; proof too long for a comment).
86
return (x / 30269.0 + y / 30307.0 + z / 30323.0) % 1.0
87
88
def getstate(self):
89
"""Return internal state; can be passed to setstate() later."""
90
return self.VERSION, self._seed, self.gauss_next
91
92
def setstate(self, state):
93
"""Restore internal state from object returned by getstate()."""
94
version = state[0]
95
if version == 1:
96
version, self._seed, self.gauss_next = state
97
else:
98
raise ValueError("state with version %s passed to "
99
"Random.setstate() of version %s" %
100
(version, self.VERSION))
101
102
def jumpahead(self, n):
103
"""Act as if n calls to random() were made, but quickly.
104
105
n is an int, greater than or equal to 0.
106
107
Example use: If you have 2 threads and know that each will
108
consume no more than a million random numbers, create two Random
109
objects r1 and r2, then do
110
r2.setstate(r1.getstate())
111
r2.jumpahead(1000000)
112
Then r1 and r2 will use guaranteed-disjoint segments of the full
113
period.
114
"""
115
116
if n < 0:
117
raise ValueError("n must be >= 0")
118
x, y, z = self._seed
119
x = int(x * pow(171, n, 30269)) % 30269
120
y = int(y * pow(172, n, 30307)) % 30307
121
z = int(z * pow(170, n, 30323)) % 30323
122
self._seed = x, y, z
123
124
def __whseed(self, x=0, y=0, z=0):
125
"""Set the Wichmann-Hill seed from (x, y, z).
126
127
These must be integers in the range [0, 256).
128
"""
129
130
if not type(x) == type(y) == type(z) == int:
131
raise TypeError('seeds must be integers')
132
if not (0 <= x < 256 and 0 <= y < 256 and 0 <= z < 256):
133
raise ValueError('seeds must be in range(0, 256)')
134
if 0 == x == y == z:
135
# Initialize from current time
136
t = int(time.time() * 256)
137
t = int((t & 0xffffff) ^ (t >> 24))
138
t, x = divmod(t, 256)
139
t, y = divmod(t, 256)
140
t, z = divmod(t, 256)
141
# Zero is a poor seed, so substitute 1
142
self._seed = (x or 1, y or 1, z or 1)
143
144
self.gauss_next = None
145
146
def whseed(self, a=None):
147
"""Seed from hashable object's hash code.
148
149
None or no argument seeds from current time. It is not guaranteed
150
that objects with distinct hash codes lead to distinct internal
151
states.
152
153
This is obsolete, provided for compatibility with the seed routine
154
used prior to Python 2.1. Use the .seed() method instead.
155
"""
156
157
if a is None:
158
self.__whseed()
159
return
160
a = hash(a)
161
a, x = divmod(a, 256)
162
a, y = divmod(a, 256)
163
a, z = divmod(a, 256)
164
x = (x + a) % 256 or 1
165
y = (y + a) % 256 or 1
166
z = (z + a) % 256 or 1
167
self.__whseed(x, y, z)
168
169
def patchHeaders(headers):
170
if headers is not None and not hasattr(headers, "headers"):
171
if isinstance(headers, dict):
172
class _(dict):
173
def __getitem__(self, key):
174
for key_ in self:
175
if key_.lower() == key.lower():
176
return super(_, self).__getitem__(key_)
177
178
raise KeyError(key)
179
180
def get(self, key, default=None):
181
try:
182
return self[key]
183
except KeyError:
184
return default
185
186
headers = _(headers)
187
188
headers.headers = ["%s: %s\r\n" % (header, headers[header]) for header in headers]
189
190
return headers
191
192
def cmp(a, b):
193
"""
194
>>> cmp("a", "b")
195
-1
196
>>> cmp(2, 1)
197
1
198
"""
199
200
if a < b:
201
return -1
202
elif a > b:
203
return 1
204
else:
205
return 0
206
207
# Reference: https://github.com/urllib3/urllib3/blob/master/src/urllib3/filepost.py
208
def choose_boundary():
209
"""
210
>>> len(choose_boundary()) == 32
211
True
212
"""
213
214
retval = ""
215
216
try:
217
retval = uuid.uuid4().hex
218
except AttributeError:
219
retval = "".join(random.sample("0123456789abcdef", 1)[0] for _ in xrange(32))
220
221
return retval
222
223
# Reference: http://python3porting.com/differences.html
224
def round(x, d=0):
225
"""
226
>>> round(2.0)
227
2.0
228
>>> round(2.5)
229
3.0
230
"""
231
232
p = 10 ** d
233
if x > 0:
234
return float(math.floor((x * p) + 0.5)) / p
235
else:
236
return float(math.ceil((x * p) - 0.5)) / p
237
238
# Reference: https://code.activestate.com/recipes/576653-convert-a-cmp-function-to-a-key-function/
239
def cmp_to_key(mycmp):
240
"""Convert a cmp= function into a key= function"""
241
class K(object):
242
__slots__ = ['obj']
243
244
def __init__(self, obj, *args):
245
self.obj = obj
246
247
def __lt__(self, other):
248
return mycmp(self.obj, other.obj) < 0
249
250
def __gt__(self, other):
251
return mycmp(self.obj, other.obj) > 0
252
253
def __eq__(self, other):
254
return mycmp(self.obj, other.obj) == 0
255
256
def __le__(self, other):
257
return mycmp(self.obj, other.obj) <= 0
258
259
def __ge__(self, other):
260
return mycmp(self.obj, other.obj) >= 0
261
262
def __ne__(self, other):
263
return mycmp(self.obj, other.obj) != 0
264
265
def __hash__(self):
266
raise TypeError('hash not implemented')
267
268
return K
269
270
# Note: patch for Python 2.6
271
if not hasattr(functools, "cmp_to_key"):
272
functools.cmp_to_key = cmp_to_key
273
274
if sys.version_info >= (3, 0):
275
xrange = range
276
buffer = memoryview
277
else:
278
xrange = xrange
279
buffer = buffer
280
281
def LooseVersion(version):
282
"""
283
>>> LooseVersion("1.0") == LooseVersion("1.0")
284
True
285
>>> LooseVersion("1.0.1") > LooseVersion("1.0")
286
True
287
>>> LooseVersion("1.0.1-") == LooseVersion("1.0.1")
288
True
289
>>> LooseVersion("1.0.11") < LooseVersion("1.0.111")
290
True
291
>>> LooseVersion("foobar") > LooseVersion("1.0")
292
False
293
>>> LooseVersion("1.0") > LooseVersion("foobar")
294
False
295
>>> LooseVersion("3.22-mysql") == LooseVersion("3.22-mysql-ubuntu0.3")
296
True
297
>>> LooseVersion("8.0.22-0ubuntu0.20.04.2")
298
8.000022
299
"""
300
301
match = re.search(r"\A(\d[\d.]*)", version or "")
302
303
if match:
304
result = 0
305
value = match.group(1)
306
weight = 1.0
307
for part in value.strip('.').split('.'):
308
if part.isdigit():
309
result += int(part) * weight
310
weight *= 1e-3
311
else:
312
result = float("NaN")
313
314
return result
315
316