sqlmap/lib/utils/hashdb.py

127 lines
4.2 KiB
Python
Raw Normal View History

#!/usr/bin/env python
"""
$Id$
Copyright (c) 2006-2011 sqlmap developers (http://www.sqlmap.org/)
See the file 'doc/COPYING' for copying permission
"""
import hashlib
import sqlite3
import threading
2011-12-28 17:50:03 +04:00
from lib.core.common import serializeObject
from lib.core.common import unserializeObject
2011-10-10 21:45:16 +04:00
from lib.core.data import conf
2011-11-22 14:54:29 +04:00
from lib.core.settings import HASHDB_FLUSH_THRESHOLD
from lib.core.settings import UNICODE_ENCODING
2011-09-26 17:36:08 +04:00
from lib.core.threads import getCurrentThreadData
from lib.core.threads import getCurrentThreadName
2011-09-26 17:36:08 +04:00
class HashDB(object):
def __init__(self, filepath):
2011-09-26 17:36:08 +04:00
self.filepath = filepath
self._write_cache = {}
self._cache_lock = threading.Lock()
2011-09-26 17:36:08 +04:00
def _get_cursor(self):
threadData = getCurrentThreadData()
if threadData.hashDBCursor is None:
2011-10-10 18:23:17 +04:00
connection = sqlite3.connect(self.filepath, timeout=3, isolation_level=None)
2011-09-26 17:36:08 +04:00
threadData.hashDBCursor = connection.cursor()
threadData.hashDBCursor.execute("CREATE TABLE IF NOT EXISTS storage (id INTEGER PRIMARY KEY, value TEXT)")
return threadData.hashDBCursor
cursor = property(_get_cursor)
def close(self):
2011-10-25 15:20:42 +04:00
threadData = getCurrentThreadData()
try:
2011-10-25 15:20:42 +04:00
if threadData.hashDBCursor:
threadData.hashDBCursor.close()
threadData.hashDBCursor.connection.close()
threadData.hashDBCursor = None
except:
pass
@staticmethod
def hashKey(key):
key = key.encode(UNICODE_ENCODING) if isinstance(key, unicode) else repr(key)
retVal = int(hashlib.md5(key).hexdigest()[:8], 16)
return retVal
2011-12-28 17:50:03 +04:00
def retrieve(self, key, unserialize=False):
retVal = None
2011-10-12 02:27:49 +04:00
if key:
hash_ = HashDB.hashKey(key)
2011-11-22 14:54:29 +04:00
retVal = self._write_cache.get(hash_, None)
if not retVal:
while True:
try:
for row in self.cursor.execute("SELECT value FROM storage WHERE id=?", (hash_,)):
retVal = row[0]
except sqlite3.OperationalError, ex:
if not 'locked' in ex.message:
raise
else:
break
2011-12-28 17:50:03 +04:00
return retVal if not unserialize else unserializeObject(retVal)
2011-12-28 17:50:03 +04:00
def write(self, key, value, serialize=False):
if key:
hash_ = HashDB.hashKey(key)
self._cache_lock.acquire()
2011-12-28 17:50:03 +04:00
self._write_cache[hash_] = value if not serialize else serializeObject(value)
self._cache_lock.release()
if getCurrentThreadName() in ('0', 'MainThread'):
self.flush()
2011-11-22 14:54:29 +04:00
def flush(self, forced=False):
2011-11-22 14:41:56 +04:00
if not self._write_cache:
return
2011-11-22 14:54:29 +04:00
if not forced and len(self._write_cache) < HASHDB_FLUSH_THRESHOLD:
return
self._cache_lock.acquire()
2011-11-22 16:44:28 +04:00
_ = self._write_cache
self._write_cache = {}
self._cache_lock.release()
2011-11-22 15:04:43 +04:00
try:
self.beginTransaction()
2011-11-22 16:44:28 +04:00
for hash_, value in _.items():
2011-11-22 15:04:43 +04:00
while True:
2011-10-10 18:23:17 +04:00
try:
2011-11-22 15:04:43 +04:00
try:
self.cursor.execute("INSERT INTO storage VALUES (?, ?)", (hash_, value,))
except sqlite3.IntegrityError:
self.cursor.execute("UPDATE storage SET value=? WHERE id=?", (value, hash_,))
except sqlite3.OperationalError, ex:
if not 'locked' in ex.message:
raise
else:
break
finally:
self.endTransaction()
2011-11-02 13:57:42 +04:00
def beginTransaction(self):
2011-11-23 18:26:40 +04:00
threadData = getCurrentThreadData()
if not threadData.inTransaction:
2011-11-23 12:14:20 +04:00
self.cursor.execute('BEGIN TRANSACTION')
2011-11-23 18:26:40 +04:00
threadData.inTransaction = True
2011-11-02 13:57:42 +04:00
def endTransaction(self):
2011-11-23 18:26:40 +04:00
threadData = getCurrentThreadData()
if threadData.inTransaction:
2011-12-21 15:50:49 +04:00
try:
self.cursor.execute('END TRANSACTION')
2011-12-22 02:59:23 +04:00
except sqlite3.OperationalError:
2011-12-21 15:50:49 +04:00
pass
finally:
threadData.inTransaction = False