Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sqlmapproject
GitHub Repository: sqlmapproject/sqlmap
Path: blob/master/lib/core/decorators.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
import functools
9
import hashlib
10
import threading
11
12
from lib.core.datatype import LRUDict
13
from lib.core.settings import MAX_CACHE_ITEMS
14
from lib.core.settings import UNICODE_ENCODING
15
from lib.core.threads import getCurrentThreadData
16
17
_cache = {}
18
_method_locks = {}
19
20
def cachedmethod(f):
21
"""
22
Method with a cached content
23
24
>>> __ = cachedmethod(lambda _: _)
25
>>> __(1)
26
1
27
>>> __(1)
28
1
29
>>> __ = cachedmethod(lambda *args, **kwargs: args[0])
30
>>> __(2)
31
2
32
>>> __ = cachedmethod(lambda *args, **kwargs: next(iter(kwargs.values())))
33
>>> __(foobar=3)
34
3
35
36
Reference: http://code.activestate.com/recipes/325205-cache-decorator-in-python-24/
37
"""
38
39
_cache[f] = LRUDict(capacity=MAX_CACHE_ITEMS)
40
_method_locks[f] = threading.RLock()
41
42
@functools.wraps(f)
43
def _f(*args, **kwargs):
44
parts = (
45
f.__module__ + "." + f.__name__,
46
"|".join(repr(a) for a in args),
47
"|".join("%s=%r" % (k, kwargs[k]) for k in sorted(kwargs))
48
)
49
try:
50
key = int(hashlib.md5("|".join(parts).encode(UNICODE_ENCODING)).hexdigest(), 16) & 0x7fffffffffffffff
51
except ValueError: # https://github.com/sqlmapproject/sqlmap/issues/4281 (NOTE: non-standard Python behavior where hexdigest returns binary value)
52
result = f(*args, **kwargs)
53
else:
54
lock, cache = _method_locks[f], _cache[f]
55
with lock:
56
try:
57
result = cache[key]
58
except KeyError:
59
result = f(*args, **kwargs)
60
cache[key] = result
61
62
return result
63
64
return _f
65
66
def stackedmethod(f):
67
"""
68
Method using pushValue/popValue functions (fallback function for stack realignment)
69
70
>>> threadData = getCurrentThreadData()
71
>>> original = len(threadData.valueStack)
72
>>> __ = stackedmethod(lambda _: threadData.valueStack.append(_))
73
>>> __(1)
74
>>> len(threadData.valueStack) == original
75
True
76
"""
77
78
@functools.wraps(f)
79
def _(*args, **kwargs):
80
threadData = getCurrentThreadData()
81
originalLevel = len(threadData.valueStack)
82
83
try:
84
result = f(*args, **kwargs)
85
finally:
86
if len(threadData.valueStack) > originalLevel:
87
threadData.valueStack = threadData.valueStack[:originalLevel]
88
89
return result
90
91
return _
92
93
def lockedmethod(f):
94
lock = threading.RLock()
95
96
@functools.wraps(f)
97
def _(*args, **kwargs):
98
with lock:
99
result = f(*args, **kwargs)
100
return result
101
102
return _
103
104