sqlmap/lib/core/threads.py

147 lines
4.0 KiB
Python
Raw Normal View History

#!/usr/bin/env python
"""
2011-01-31 14:41:28 +03:00
$Id$
Copyright (c) 2006-2011 sqlmap developers (http://sqlmap.sourceforge.net/)
See the file 'doc/COPYING' for copying permission
"""
import difflib
import threading
import time
from lib.core.data import kb
from lib.core.data import logger
from lib.core.datatype import advancedDict
from lib.core.exception import sqlmapThreadException
from lib.core.settings import MAX_NUMBER_OF_THREADS
from lib.core.settings import PYVERSION
shared = advancedDict()
class ThreadData():
"""
Represents thread independent data
"""
def __init__(self):
global shared
2011-04-30 17:20:05 +04:00
self.disableStdOut = False
self.lastErrorPage = None
self.lastHTTPError = None
self.lastRedirectMsg = None
self.lastQueryDuration = 0
self.lastRequestUID = 0
2011-05-11 16:54:33 +04:00
self.retriesCount = 0
2011-04-30 17:20:05 +04:00
self.seqMatcher = difflib.SequenceMatcher(None)
self.shared = shared
2011-04-30 17:20:05 +04:00
self.valueStack = []
def getCurrentThreadUID():
return hash(threading.currentThread())
def readInput(message, default=None):
pass
def getCurrentThreadData():
"""
Returns current thread's dependent data
"""
threadUID = getCurrentThreadUID()
if threadUID not in kb.threadData:
kb.threadData[threadUID] = ThreadData()
return kb.threadData[threadUID]
def exceptionHandledFunction(threadFunction):
try:
threadFunction()
except KeyboardInterrupt:
kb.threadContinue = False
kb.threadException = True
raise
2011-06-07 14:32:18 +04:00
except Exception, errMsg:
# thread is just going to be silently killed
print
logger.error("thread %s: %s" % (threading.currentThread().getName(), errMsg))
def runThreads(numThreads, threadFunction, cleanupFunction=None, forwardException=True, threadChoice=False):
threads = []
kb.multiThreadMode = True
kb.threadContinue = True
kb.threadException = False
if threadChoice and numThreads == 1:
while True:
message = "please enter number of threads? [Enter for %d (current)] " % numThreads
choice = readInput(message, default=str(numThreads))
if choice and choice.isdigit():
if int(choice) > MAX_NUMBER_OF_THREADS:
errMsg = "maximum number of used threads is %d avoiding possible connection issues" % MAX_NUMBER_OF_THREADS
logger.critical(errMsg)
else:
numThreads = int(choice)
break
if numThreads == 1:
warnMsg = "running in a single-thread mode. This could take a while."
logger.warn(warnMsg)
if numThreads > 1:
infoMsg = "starting %d threads" % numThreads
logger.info(infoMsg)
else:
threadFunction()
return
# Start the threads
for numThread in range(numThreads):
thread = threading.Thread(target=exceptionHandledFunction, name=str(numThread), args=[threadFunction])
# Reference: http://stackoverflow.com/questions/190010/daemon-threads-explanation
if PYVERSION >= "2.6":
thread.daemon = True
else:
thread.setDaemon(True)
thread.start()
threads.append(thread)
# And wait for them to all finish
try:
alive = True
while alive:
alive = False
for thread in threads:
if thread.isAlive():
alive = True
time.sleep(1)
except KeyboardInterrupt:
kb.threadContinue = False
kb.threadException = True
logger.info("waiting for threads to finish (Ctrl+C was pressed)")
try:
while (threading.activeCount() > 1):
pass
except KeyboardInterrupt:
raise sqlmapThreadException, "user aborted (Ctrl+C was pressed multiple times)"
2011-05-30 03:56:41 +04:00
if forwardException:
raise
finally:
kb.multiThreadMode = False
kb.bruteMode = False
kb.threadContinue = True
kb.threadException = False
if cleanupFunction:
cleanupFunction()