diff --git a/lib/core/common.py b/lib/core/common.py index 1d7580958..2a91c3510 100644 --- a/lib/core/common.py +++ b/lib/core/common.py @@ -4646,19 +4646,20 @@ def resetCookieJar(cookieJar): def decloakToTemp(filename): """ Decloaks content of a given file to a temporary file with similar name and extension + + >>> _ = decloakToTemp(os.path.join(paths.SQLMAP_SHELL_PATH, "stagers", "stager.asp_")) + >>> openFile(_, "rb", encoding=None).read().startswith(b'<%') + True """ content = decloak(filename) - _ = getBytes(os.path.split(filename[:-1])[-1]) - - prefix, suffix = os.path.splitext(_) - prefix = prefix.split(os.extsep)[0] - + parts = getBytes(os.path.split(filename[:-1])[-1]).split(b'.') + prefix, suffix = parts[0], b".%s" % parts[-1] handle, filename = tempfile.mkstemp(prefix=prefix, suffix=suffix) os.close(handle) - with open(filename, "w+b") as f: + with openFile(filename, "w+b", encoding=None) as f: f.write(content) return filename diff --git a/lib/core/datatype.py b/lib/core/datatype.py index 2285948c3..0aa4bd611 100644 --- a/lib/core/datatype.py +++ b/lib/core/datatype.py @@ -13,8 +13,7 @@ from thirdparty.odict import OrderedDict class AttribDict(dict): """ - This class defines the sqlmap object, inheriting from Python data - type dictionary. + This class defines the dictionary with added capability to access members as attributes >>> foo = AttribDict() >>> foo.bar = 1 @@ -110,6 +109,19 @@ class InjectionDict(AttribDict): # Reference: https://www.kunxi.org/2014/05/lru-cache-in-python class LRUDict(object): + """ + This class defines the LRU dictionary + + >>> foo = LRUDict(capacity=2) + >>> foo["first"] = 1 + >>> foo["second"] = 2 + >>> foo["third"] = 3 + >>> "first" in foo + False + >>> "third" in foo + True + """ + def __init__(self, capacity): self.capacity = capacity self.cache = OrderedDict() @@ -144,6 +156,21 @@ class LRUDict(object): # Reference: https://code.activestate.com/recipes/576694/ class OrderedSet(collections.MutableSet): + """ + This class defines the set with ordered (as added) items + + >>> foo = OrderedSet() + >>> foo.add(1) + >>> foo.add(2) + >>> foo.add(3) + >>> foo.pop() + 3 + >>> foo.pop() + 2 + >>> foo.pop() + 1 + """ + def __init__(self, iterable=None): self.end = end = [] end += [None, end, end] # sentinel node for doubly linked list diff --git a/lib/core/decorators.py b/lib/core/decorators.py index b98f4f1d3..7c2ea82a1 100644 --- a/lib/core/decorators.py +++ b/lib/core/decorators.py @@ -20,6 +20,16 @@ def cachedmethod(f, cache=LRUDict(capacity=MAX_CACHE_ITEMS)): """ Method with a cached content + >>> __ = cachedmethod(lambda _: _) + >>> __(1) + 1 + >>> __ = cachedmethod(lambda *args, **kwargs: args[0]) + >>> __(2) + 2 + >>> __ = cachedmethod(lambda *args, **kwargs: list(kwargs.values())[0]) + >>> __(foobar=3) + 3 + Reference: http://code.activestate.com/recipes/325205-cache-decorator-in-python-24/ """ @@ -43,6 +53,13 @@ def cachedmethod(f, cache=LRUDict(capacity=MAX_CACHE_ITEMS)): def stackedmethod(f): """ Method using pushValue/popValue functions (fallback function for stack realignment) + + >>> threadData = getCurrentThreadData() + >>> original = len(threadData.valueStack) + >>> __ = stackedmethod(lambda _: threadData.valueStack.append(_)) + >>> __(1) + >>> len(threadData.valueStack) == original + True """ @functools.wraps(f) diff --git a/lib/core/readlineng.py b/lib/core/readlineng.py index 4d063325a..0726e5f15 100644 --- a/lib/core/readlineng.py +++ b/lib/core/readlineng.py @@ -35,7 +35,7 @@ if IS_WIN and _readline: # Thanks to Boyd Waters for this patch. uses_libedit = False -if PLATFORM == 'mac' and _readline: +if PLATFORM == "mac" and _readline: import commands (status, result) = commands.getstatusoutput("otool -L %s | grep libedit" % _readline.__file__) diff --git a/lib/core/revision.py b/lib/core/revision.py index 23d2d840b..5255cb1b6 100644 --- a/lib/core/revision.py +++ b/lib/core/revision.py @@ -12,6 +12,9 @@ import subprocess def getRevisionNumber(): """ Returns abbreviated commit hash number as retrieved with "git rev-parse --short HEAD" + + >>> len(getRevisionNumber() or (' ' * 7)) == 7 + True """ retVal = None diff --git a/lib/core/settings.py b/lib/core/settings.py index 743d18ab5..c4f2c0405 100644 --- a/lib/core/settings.py +++ b/lib/core/settings.py @@ -18,7 +18,7 @@ from lib.core.enums import OS from thirdparty import six # sqlmap version (...) -VERSION = "1.3.5.28" +VERSION = "1.3.5.29" TYPE = "dev" if VERSION.count('.') > 2 and VERSION.split('.')[-1] != '0' else "stable" TYPE_COLORS = {"dev": 33, "stable": 90, "pip": 34} VERSION_STRING = "sqlmap/%s#%s" % ('.'.join(VERSION.split('.')[:-1]) if VERSION.count('.') > 2 and VERSION.split('.')[-1] == '0' else VERSION, TYPE) diff --git a/lib/core/wordlist.py b/lib/core/wordlist.py index 6265fbd34..a99e3df9c 100644 --- a/lib/core/wordlist.py +++ b/lib/core/wordlist.py @@ -16,10 +16,14 @@ from thirdparty import six class Wordlist(six.Iterator): """ Iterator for looping over a large dictionaries + + >>> from lib.core.option import paths + >>> isinstance(next(Wordlist(paths.SMALL_DICT)), six.string_types) + True """ def __init__(self, filenames, proc_id=None, proc_count=None, custom=None): - self.filenames = filenames + self.filenames = [filenames] if isinstance(filenames, six.string_types) else filenames self.fp = None self.index = 0 self.counter = -1