mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2025-02-18 12:30:36 +03:00
adding ordered set for kb.targetUrls (now the order of appereance in multiple targets mode will be respected)
This commit is contained in:
parent
5ee07b90b9
commit
53065ee1fb
29
extra/oset/LICENSE.txt
Normal file
29
extra/oset/LICENSE.txt
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
License
|
||||||
|
=======
|
||||||
|
|
||||||
|
Copyright (c) 2009, Raymond Hettinger, and others
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Package structured based on the one developed to odict
|
||||||
|
Copyright (c) 2010, BlueDynamics Alliance, Austria
|
||||||
|
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
* Neither the name of the BlueDynamics Alliance nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived from this
|
||||||
|
software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY BlueDynamics Alliance ``AS IS`` AND ANY
|
||||||
|
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL BlueDynamics Alliance BE LIABLE FOR ANY
|
||||||
|
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
3
extra/oset/__init__.py
Normal file
3
extra/oset/__init__.py
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
"""Main Ordered Set module """
|
||||||
|
|
||||||
|
from pyoset import oset
|
475
extra/oset/_abc.py
Normal file
475
extra/oset/_abc.py
Normal file
|
@ -0,0 +1,475 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- mode:python; tab-width: 2; coding: utf-8 -*-
|
||||||
|
|
||||||
|
"""Partially backported python ABC classes"""
|
||||||
|
|
||||||
|
from __future__ import absolute_import
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import types
|
||||||
|
|
||||||
|
if sys.version_info > (2, 6):
|
||||||
|
raise ImportError("Use native ABC classes istead of this one.")
|
||||||
|
|
||||||
|
|
||||||
|
# Instance of old-style class
|
||||||
|
class _C:
|
||||||
|
pass
|
||||||
|
|
||||||
|
_InstanceType = type(_C())
|
||||||
|
|
||||||
|
|
||||||
|
def abstractmethod(funcobj):
|
||||||
|
"""A decorator indicating abstract methods.
|
||||||
|
|
||||||
|
Requires that the metaclass is ABCMeta or derived from it. A
|
||||||
|
class that has a metaclass derived from ABCMeta cannot be
|
||||||
|
instantiated unless all of its abstract methods are overridden.
|
||||||
|
The abstract methods can be called using any of the normal
|
||||||
|
'super' call mechanisms.
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
|
||||||
|
class C:
|
||||||
|
__metaclass__ = ABCMeta
|
||||||
|
@abstractmethod
|
||||||
|
def my_abstract_method(self, ...):
|
||||||
|
...
|
||||||
|
"""
|
||||||
|
funcobj.__isabstractmethod__ = True
|
||||||
|
return funcobj
|
||||||
|
|
||||||
|
|
||||||
|
class ABCMeta(type):
|
||||||
|
|
||||||
|
"""Metaclass for defining Abstract Base Classes (ABCs).
|
||||||
|
|
||||||
|
Use this metaclass to create an ABC. An ABC can be subclassed
|
||||||
|
directly, and then acts as a mix-in class. You can also register
|
||||||
|
unrelated concrete classes (even built-in classes) and unrelated
|
||||||
|
ABCs as 'virtual subclasses' -- these and their descendants will
|
||||||
|
be considered subclasses of the registering ABC by the built-in
|
||||||
|
issubclass() function, but the registering ABC won't show up in
|
||||||
|
their MRO (Method Resolution Order) nor will method
|
||||||
|
implementations defined by the registering ABC be callable (not
|
||||||
|
even via super()).
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
# A global counter that is incremented each time a class is
|
||||||
|
# registered as a virtual subclass of anything. It forces the
|
||||||
|
# negative cache to be cleared before its next use.
|
||||||
|
_abc_invalidation_counter = 0
|
||||||
|
|
||||||
|
def __new__(mcls, name, bases, namespace):
|
||||||
|
cls = super(ABCMeta, mcls).__new__(mcls, name, bases, namespace)
|
||||||
|
# Compute set of abstract method names
|
||||||
|
abstracts = set(name
|
||||||
|
for name, value in namespace.items()
|
||||||
|
if getattr(value, "__isabstractmethod__", False))
|
||||||
|
for base in bases:
|
||||||
|
for name in getattr(base, "__abstractmethods__", set()):
|
||||||
|
value = getattr(cls, name, None)
|
||||||
|
if getattr(value, "__isabstractmethod__", False):
|
||||||
|
abstracts.add(name)
|
||||||
|
cls.__abstractmethods__ = frozenset(abstracts)
|
||||||
|
# Set up inheritance registry
|
||||||
|
cls._abc_registry = set()
|
||||||
|
cls._abc_cache = set()
|
||||||
|
cls._abc_negative_cache = set()
|
||||||
|
cls._abc_negative_cache_version = ABCMeta._abc_invalidation_counter
|
||||||
|
return cls
|
||||||
|
|
||||||
|
def register(cls, subclass):
|
||||||
|
"""Register a virtual subclass of an ABC."""
|
||||||
|
if not isinstance(subclass, (type, types.ClassType)):
|
||||||
|
raise TypeError("Can only register classes")
|
||||||
|
if issubclass(subclass, cls):
|
||||||
|
return # Already a subclass
|
||||||
|
# Subtle: test for cycles *after* testing for "already a subclass";
|
||||||
|
# this means we allow X.register(X) and interpret it as a no-op.
|
||||||
|
if issubclass(cls, subclass):
|
||||||
|
# This would create a cycle, which is bad for the algorithm below
|
||||||
|
raise RuntimeError("Refusing to create an inheritance cycle")
|
||||||
|
cls._abc_registry.add(subclass)
|
||||||
|
ABCMeta._abc_invalidation_counter += 1 # Invalidate negative cache
|
||||||
|
|
||||||
|
def _dump_registry(cls, file=None):
|
||||||
|
"""Debug helper to print the ABC registry."""
|
||||||
|
print >> file, "Class: %s.%s" % (cls.__module__, cls.__name__)
|
||||||
|
print >> file, "Inv.counter: %s" % ABCMeta._abc_invalidation_counter
|
||||||
|
for name in sorted(cls.__dict__.keys()):
|
||||||
|
if name.startswith("_abc_"):
|
||||||
|
value = getattr(cls, name)
|
||||||
|
print >> file, "%s: %r" % (name, value)
|
||||||
|
|
||||||
|
def __instancecheck__(cls, instance):
|
||||||
|
"""Override for isinstance(instance, cls)."""
|
||||||
|
# Inline the cache checking when it's simple.
|
||||||
|
subclass = getattr(instance, '__class__', None)
|
||||||
|
if subclass in cls._abc_cache:
|
||||||
|
return True
|
||||||
|
subtype = type(instance)
|
||||||
|
# Old-style instances
|
||||||
|
if subtype is _InstanceType:
|
||||||
|
subtype = subclass
|
||||||
|
if subtype is subclass or subclass is None:
|
||||||
|
if (cls._abc_negative_cache_version ==
|
||||||
|
ABCMeta._abc_invalidation_counter and
|
||||||
|
subtype in cls._abc_negative_cache):
|
||||||
|
return False
|
||||||
|
# Fall back to the subclass check.
|
||||||
|
return cls.__subclasscheck__(subtype)
|
||||||
|
return (cls.__subclasscheck__(subclass) or
|
||||||
|
cls.__subclasscheck__(subtype))
|
||||||
|
|
||||||
|
def __subclasscheck__(cls, subclass):
|
||||||
|
"""Override for issubclass(subclass, cls)."""
|
||||||
|
# Check cache
|
||||||
|
if subclass in cls._abc_cache:
|
||||||
|
return True
|
||||||
|
# Check negative cache; may have to invalidate
|
||||||
|
if cls._abc_negative_cache_version < ABCMeta._abc_invalidation_counter:
|
||||||
|
# Invalidate the negative cache
|
||||||
|
cls._abc_negative_cache = set()
|
||||||
|
cls._abc_negative_cache_version = ABCMeta._abc_invalidation_counter
|
||||||
|
elif subclass in cls._abc_negative_cache:
|
||||||
|
return False
|
||||||
|
# Check the subclass hook
|
||||||
|
ok = cls.__subclasshook__(subclass)
|
||||||
|
if ok is not NotImplemented:
|
||||||
|
assert isinstance(ok, bool)
|
||||||
|
if ok:
|
||||||
|
cls._abc_cache.add(subclass)
|
||||||
|
else:
|
||||||
|
cls._abc_negative_cache.add(subclass)
|
||||||
|
return ok
|
||||||
|
# Check if it's a direct subclass
|
||||||
|
if cls in getattr(subclass, '__mro__', ()):
|
||||||
|
cls._abc_cache.add(subclass)
|
||||||
|
return True
|
||||||
|
# Check if it's a subclass of a registered class (recursive)
|
||||||
|
for rcls in cls._abc_registry:
|
||||||
|
if issubclass(subclass, rcls):
|
||||||
|
cls._abc_cache.add(subclass)
|
||||||
|
return True
|
||||||
|
# Check if it's a subclass of a subclass (recursive)
|
||||||
|
for scls in cls.__subclasses__():
|
||||||
|
if issubclass(subclass, scls):
|
||||||
|
cls._abc_cache.add(subclass)
|
||||||
|
return True
|
||||||
|
# No dice; update negative cache
|
||||||
|
cls._abc_negative_cache.add(subclass)
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def _hasattr(C, attr):
|
||||||
|
try:
|
||||||
|
return any(attr in B.__dict__ for B in C.__mro__)
|
||||||
|
except AttributeError:
|
||||||
|
# Old-style class
|
||||||
|
return hasattr(C, attr)
|
||||||
|
|
||||||
|
|
||||||
|
class Sized:
|
||||||
|
__metaclass__ = ABCMeta
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def __len__(self):
|
||||||
|
return 0
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def __subclasshook__(cls, C):
|
||||||
|
if cls is Sized:
|
||||||
|
if _hasattr(C, "__len__"):
|
||||||
|
return True
|
||||||
|
return NotImplemented
|
||||||
|
|
||||||
|
|
||||||
|
class Container:
|
||||||
|
__metaclass__ = ABCMeta
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def __contains__(self, x):
|
||||||
|
return False
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def __subclasshook__(cls, C):
|
||||||
|
if cls is Container:
|
||||||
|
if _hasattr(C, "__contains__"):
|
||||||
|
return True
|
||||||
|
return NotImplemented
|
||||||
|
|
||||||
|
|
||||||
|
class Iterable:
|
||||||
|
__metaclass__ = ABCMeta
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def __iter__(self):
|
||||||
|
while False:
|
||||||
|
yield None
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def __subclasshook__(cls, C):
|
||||||
|
if cls is Iterable:
|
||||||
|
if _hasattr(C, "__iter__"):
|
||||||
|
return True
|
||||||
|
return NotImplemented
|
||||||
|
|
||||||
|
Iterable.register(str)
|
||||||
|
|
||||||
|
|
||||||
|
class Set(Sized, Iterable, Container):
|
||||||
|
"""A set is a finite, iterable container.
|
||||||
|
|
||||||
|
This class provides concrete generic implementations of all
|
||||||
|
methods except for __contains__, __iter__ and __len__.
|
||||||
|
|
||||||
|
To override the comparisons (presumably for speed, as the
|
||||||
|
semantics are fixed), all you have to do is redefine __le__ and
|
||||||
|
then the other operations will automatically follow suit.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __le__(self, other):
|
||||||
|
if not isinstance(other, Set):
|
||||||
|
return NotImplemented
|
||||||
|
if len(self) > len(other):
|
||||||
|
return False
|
||||||
|
for elem in self:
|
||||||
|
if elem not in other:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
def __lt__(self, other):
|
||||||
|
if not isinstance(other, Set):
|
||||||
|
return NotImplemented
|
||||||
|
return len(self) < len(other) and self.__le__(other)
|
||||||
|
|
||||||
|
def __gt__(self, other):
|
||||||
|
if not isinstance(other, Set):
|
||||||
|
return NotImplemented
|
||||||
|
return other < self
|
||||||
|
|
||||||
|
def __ge__(self, other):
|
||||||
|
if not isinstance(other, Set):
|
||||||
|
return NotImplemented
|
||||||
|
return other <= self
|
||||||
|
|
||||||
|
def __eq__(self, other):
|
||||||
|
if not isinstance(other, Set):
|
||||||
|
return NotImplemented
|
||||||
|
return len(self) == len(other) and self.__le__(other)
|
||||||
|
|
||||||
|
def __ne__(self, other):
|
||||||
|
return not (self == other)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _from_iterable(cls, it):
|
||||||
|
'''Construct an instance of the class from any iterable input.
|
||||||
|
|
||||||
|
Must override this method if the class constructor signature
|
||||||
|
does not accept an iterable for an input.
|
||||||
|
'''
|
||||||
|
return cls(it)
|
||||||
|
|
||||||
|
def __and__(self, other):
|
||||||
|
if not isinstance(other, Iterable):
|
||||||
|
return NotImplemented
|
||||||
|
return self._from_iterable(value for value in other if value in self)
|
||||||
|
|
||||||
|
def isdisjoint(self, other):
|
||||||
|
for value in other:
|
||||||
|
if value in self:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
def __or__(self, other):
|
||||||
|
if not isinstance(other, Iterable):
|
||||||
|
return NotImplemented
|
||||||
|
chain = (e for s in (self, other) for e in s)
|
||||||
|
return self._from_iterable(chain)
|
||||||
|
|
||||||
|
def __sub__(self, other):
|
||||||
|
if not isinstance(other, Set):
|
||||||
|
if not isinstance(other, Iterable):
|
||||||
|
return NotImplemented
|
||||||
|
other = self._from_iterable(other)
|
||||||
|
return self._from_iterable(value for value in self
|
||||||
|
if value not in other)
|
||||||
|
|
||||||
|
def __xor__(self, other):
|
||||||
|
if not isinstance(other, Set):
|
||||||
|
if not isinstance(other, Iterable):
|
||||||
|
return NotImplemented
|
||||||
|
other = self._from_iterable(other)
|
||||||
|
return (self - other) | (other - self)
|
||||||
|
|
||||||
|
# Sets are not hashable by default, but subclasses can change this
|
||||||
|
__hash__ = None
|
||||||
|
|
||||||
|
def _hash(self):
|
||||||
|
"""Compute the hash value of a set.
|
||||||
|
|
||||||
|
Note that we don't define __hash__: not all sets are hashable.
|
||||||
|
But if you define a hashable set type, its __hash__ should
|
||||||
|
call this function.
|
||||||
|
|
||||||
|
This must be compatible __eq__.
|
||||||
|
|
||||||
|
All sets ought to compare equal if they contain the same
|
||||||
|
elements, regardless of how they are implemented, and
|
||||||
|
regardless of the order of the elements; so there's not much
|
||||||
|
freedom for __eq__ or __hash__. We match the algorithm used
|
||||||
|
by the built-in frozenset type.
|
||||||
|
"""
|
||||||
|
MAX = sys.maxint
|
||||||
|
MASK = 2 * MAX + 1
|
||||||
|
n = len(self)
|
||||||
|
h = 1927868237 * (n + 1)
|
||||||
|
h &= MASK
|
||||||
|
for x in self:
|
||||||
|
hx = hash(x)
|
||||||
|
h ^= (hx ^ (hx << 16) ^ 89869747) * 3644798167
|
||||||
|
h &= MASK
|
||||||
|
h = h * 69069 + 907133923
|
||||||
|
h &= MASK
|
||||||
|
if h > MAX:
|
||||||
|
h -= MASK + 1
|
||||||
|
if h == -1:
|
||||||
|
h = 590923713
|
||||||
|
return h
|
||||||
|
|
||||||
|
Set.register(frozenset)
|
||||||
|
|
||||||
|
|
||||||
|
class MutableSet(Set):
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def add(self, value):
|
||||||
|
"""Add an element."""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def discard(self, value):
|
||||||
|
"""Remove an element. Do not raise an exception if absent."""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def remove(self, value):
|
||||||
|
"""Remove an element. If not a member, raise a KeyError."""
|
||||||
|
if value not in self:
|
||||||
|
raise KeyError(value)
|
||||||
|
self.discard(value)
|
||||||
|
|
||||||
|
def pop(self):
|
||||||
|
"""Return the popped value. Raise KeyError if empty."""
|
||||||
|
it = iter(self)
|
||||||
|
try:
|
||||||
|
value = it.next()
|
||||||
|
except StopIteration:
|
||||||
|
raise KeyError
|
||||||
|
self.discard(value)
|
||||||
|
return value
|
||||||
|
|
||||||
|
def clear(self):
|
||||||
|
"""This is slow (creates N new iterators!) but effective."""
|
||||||
|
try:
|
||||||
|
while True:
|
||||||
|
self.pop()
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def __ior__(self, it):
|
||||||
|
for value in it:
|
||||||
|
self.add(value)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __iand__(self, it):
|
||||||
|
for value in (self - it):
|
||||||
|
self.discard(value)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __ixor__(self, it):
|
||||||
|
if not isinstance(it, Set):
|
||||||
|
it = self._from_iterable(it)
|
||||||
|
for value in it:
|
||||||
|
if value in self:
|
||||||
|
self.discard(value)
|
||||||
|
else:
|
||||||
|
self.add(value)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __isub__(self, it):
|
||||||
|
for value in it:
|
||||||
|
self.discard(value)
|
||||||
|
return self
|
||||||
|
|
||||||
|
MutableSet.register(set)
|
||||||
|
|
||||||
|
|
||||||
|
class OrderedSet(MutableSet):
|
||||||
|
|
||||||
|
def __init__(self, iterable=None):
|
||||||
|
self.end = end = []
|
||||||
|
end += [None, end, end] # sentinel node for doubly linked list
|
||||||
|
self.map = {} # key --> [key, prev, next]
|
||||||
|
if iterable is not None:
|
||||||
|
self |= iterable
|
||||||
|
|
||||||
|
def __len__(self):
|
||||||
|
return len(self.map)
|
||||||
|
|
||||||
|
def __contains__(self, key):
|
||||||
|
return key in self.map
|
||||||
|
|
||||||
|
def __getitem__(self, key):
|
||||||
|
return list(self)[key]
|
||||||
|
|
||||||
|
def add(self, key):
|
||||||
|
if key not in self.map:
|
||||||
|
end = self.end
|
||||||
|
curr = end[PREV]
|
||||||
|
curr[NEXT] = end[PREV] = self.map[key] = [key, curr, end]
|
||||||
|
|
||||||
|
def discard(self, key):
|
||||||
|
if key in self.map:
|
||||||
|
key, prev, next = self.map.pop(key)
|
||||||
|
prev[NEXT] = next
|
||||||
|
next[PREV] = prev
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
end = self.end
|
||||||
|
curr = end[NEXT]
|
||||||
|
while curr is not end:
|
||||||
|
yield curr[KEY]
|
||||||
|
curr = curr[NEXT]
|
||||||
|
|
||||||
|
def __reversed__(self):
|
||||||
|
end = self.end
|
||||||
|
curr = end[PREV]
|
||||||
|
while curr is not end:
|
||||||
|
yield curr[KEY]
|
||||||
|
curr = curr[PREV]
|
||||||
|
|
||||||
|
def pop(self, last=True):
|
||||||
|
if not self:
|
||||||
|
raise KeyError('set is empty')
|
||||||
|
key = reversed(self).next() if last else iter(self).next()
|
||||||
|
self.discard(key)
|
||||||
|
return key
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
if not self:
|
||||||
|
return '%s()' % (self.__class__.__name__,)
|
||||||
|
return '%s(%r)' % (self.__class__.__name__, list(self))
|
||||||
|
|
||||||
|
def __eq__(self, other):
|
||||||
|
if isinstance(other, OrderedSet):
|
||||||
|
return len(self) == len(other) and list(self) == list(other)
|
||||||
|
return set(self) == set(other)
|
||||||
|
|
||||||
|
def __del__(self):
|
||||||
|
self.clear() # remove circular references
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
print(OrderedSet('abracadaba'))
|
||||||
|
print(OrderedSet('simsalabim'))
|
82
extra/oset/pyoset.py
Normal file
82
extra/oset/pyoset.py
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- mode:python; tab-width: 2; coding: utf-8 -*-
|
||||||
|
|
||||||
|
"""Partially backported python ABC classes"""
|
||||||
|
|
||||||
|
from __future__ import absolute_import
|
||||||
|
|
||||||
|
try:
|
||||||
|
from collections import MutableSet
|
||||||
|
except ImportError:
|
||||||
|
# Running in Python <= 2.5
|
||||||
|
from ._abc import MutableSet
|
||||||
|
|
||||||
|
|
||||||
|
KEY, PREV, NEXT = range(3)
|
||||||
|
|
||||||
|
|
||||||
|
class OrderedSet(MutableSet):
|
||||||
|
|
||||||
|
def __init__(self, iterable=None):
|
||||||
|
self.end = end = []
|
||||||
|
end += [None, end, end] # sentinel node for doubly linked list
|
||||||
|
self.map = {} # key --> [key, prev, next]
|
||||||
|
if iterable is not None:
|
||||||
|
self |= iterable
|
||||||
|
|
||||||
|
def __len__(self):
|
||||||
|
return len(self.map)
|
||||||
|
|
||||||
|
def __contains__(self, key):
|
||||||
|
return key in self.map
|
||||||
|
|
||||||
|
def __getitem__(self, key):
|
||||||
|
return list(self)[key]
|
||||||
|
|
||||||
|
def add(self, key):
|
||||||
|
if key not in self.map:
|
||||||
|
end = self.end
|
||||||
|
curr = end[PREV]
|
||||||
|
curr[NEXT] = end[PREV] = self.map[key] = [key, curr, end]
|
||||||
|
|
||||||
|
def discard(self, key):
|
||||||
|
if key in self.map:
|
||||||
|
key, prev, next = self.map.pop(key)
|
||||||
|
prev[NEXT] = next
|
||||||
|
next[PREV] = prev
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
end = self.end
|
||||||
|
curr = end[NEXT]
|
||||||
|
while curr is not end:
|
||||||
|
yield curr[KEY]
|
||||||
|
curr = curr[NEXT]
|
||||||
|
|
||||||
|
def __reversed__(self):
|
||||||
|
end = self.end
|
||||||
|
curr = end[PREV]
|
||||||
|
while curr is not end:
|
||||||
|
yield curr[KEY]
|
||||||
|
curr = curr[PREV]
|
||||||
|
|
||||||
|
def pop(self, last=True):
|
||||||
|
if not self:
|
||||||
|
raise KeyError('set is empty')
|
||||||
|
key = reversed(self).next() if last else iter(self).next()
|
||||||
|
self.discard(key)
|
||||||
|
return key
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
if not self:
|
||||||
|
return '%s()' % (self.__class__.__name__,)
|
||||||
|
return '%s(%r)' % (self.__class__.__name__, list(self))
|
||||||
|
|
||||||
|
def __eq__(self, other):
|
||||||
|
if isinstance(other, OrderedSet):
|
||||||
|
return len(self) == len(other) and list(self) == list(other)
|
||||||
|
return set(self) == set(other)
|
||||||
|
|
||||||
|
def __del__(self):
|
||||||
|
self.clear() # remove circular references
|
||||||
|
|
||||||
|
oset = OrderedSet
|
|
@ -23,6 +23,7 @@ import urlparse
|
||||||
from extra.clientform.clientform import ParseResponse
|
from extra.clientform.clientform import ParseResponse
|
||||||
from extra.clientform.clientform import ParseError
|
from extra.clientform.clientform import ParseError
|
||||||
from extra.keepalive import keepalive
|
from extra.keepalive import keepalive
|
||||||
|
from extra.oset.pyoset import oset
|
||||||
from extra.xmlobject import xmlobject
|
from extra.xmlobject import xmlobject
|
||||||
from lib.controller.checks import checkConnection
|
from lib.controller.checks import checkConnection
|
||||||
from lib.core.common import Backend
|
from lib.core.common import Backend
|
||||||
|
@ -1399,7 +1400,7 @@ def __setKnowledgeBaseAttributes(flushAll=True):
|
||||||
if flushAll:
|
if flushAll:
|
||||||
kb.keywords = set(getFileItems(paths.SQL_KEYWORDS))
|
kb.keywords = set(getFileItems(paths.SQL_KEYWORDS))
|
||||||
kb.tamperFunctions = []
|
kb.tamperFunctions = []
|
||||||
kb.targetUrls = set()
|
kb.targetUrls = oset()
|
||||||
kb.testedParams = set()
|
kb.testedParams = set()
|
||||||
kb.userAgents = None
|
kb.userAgents = None
|
||||||
kb.wordlist = None
|
kb.wordlist = None
|
||||||
|
|
Loading…
Reference in New Issue
Block a user