diff --git a/lib/controller/controller.py b/lib/controller/controller.py index 1764cb922..8902479c1 100644 --- a/lib/controller/controller.py +++ b/lib/controller/controller.py @@ -263,7 +263,7 @@ def _saveToResultsFile(): conf.resultsFP.flush() except IOError as ex: - errMsg = "unable to write to the results file '%s' ('%s'). " % (conf.resultsFilename, getSafeExString(ex)) + errMsg = "unable to write to the results file '%s' ('%s'). " % (conf.resultsFile, getSafeExString(ex)) raise SqlmapSystemException(errMsg) @stackedmethod @@ -738,9 +738,9 @@ def start(): logger.info("fetched data logged to text files under '%s'" % conf.outputPath) if conf.multipleTargets: - if conf.resultsFilename: + if conf.resultsFile: infoMsg = "you can find results of scanning in multiple targets " - infoMsg += "mode inside the CSV file '%s'" % conf.resultsFilename + infoMsg += "mode inside the CSV file '%s'" % conf.resultsFile logger.info(infoMsg) return True diff --git a/lib/core/option.py b/lib/core/option.py index ce54b2cac..0b5680215 100644 --- a/lib/core/option.py +++ b/lib/core/option.py @@ -1833,7 +1833,6 @@ def _setConfAttributes(): conf.path = None conf.port = None conf.proxyList = None - conf.resultsFilename = None conf.resultsFP = None conf.scheme = None conf.tests = [] diff --git a/lib/core/optiondict.py b/lib/core/optiondict.py index 62a72d6a4..0d90eedc9 100644 --- a/lib/core/optiondict.py +++ b/lib/core/optiondict.py @@ -238,6 +238,7 @@ optDict = { "listTampers": "boolean", "offline": "boolean", "purge": "boolean", + "resultsFile": "string", "tmpDir": "string", "unstable": "boolean", "updateAll": "boolean", diff --git a/lib/core/settings.py b/lib/core/settings.py index 36b149dcc..a71081f33 100644 --- a/lib/core/settings.py +++ b/lib/core/settings.py @@ -18,7 +18,7 @@ from lib.core.enums import OS from thirdparty.six import unichr as _unichr # sqlmap version (...) -VERSION = "1.3.10.41" +VERSION = "1.3.11.0" 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/target.py b/lib/core/target.py index f7d8fc098..591d2a9ba 100644 --- a/lib/core/target.py +++ b/lib/core/target.py @@ -561,16 +561,18 @@ def _setResultsFile(): return if not conf.resultsFP: - conf.resultsFilename = os.path.join(paths.SQLMAP_OUTPUT_PATH, time.strftime(RESULTS_FILE_FORMAT).lower()) + conf.resultsFile = conf.resultsFile or os.path.join(paths.SQLMAP_OUTPUT_PATH, time.strftime(RESULTS_FILE_FORMAT).lower()) + found = os.path.exists(conf.resultsFile) + try: - conf.resultsFP = openFile(conf.resultsFilename, "a", UNICODE_ENCODING, buffering=0) + conf.resultsFP = openFile(conf.resultsFile, "a", UNICODE_ENCODING, buffering=0) except (OSError, IOError) as ex: try: - warnMsg = "unable to create results file '%s' ('%s'). " % (conf.resultsFilename, getUnicode(ex)) - handle, conf.resultsFilename = tempfile.mkstemp(prefix=MKSTEMP_PREFIX.RESULTS, suffix=".csv") + warnMsg = "unable to create results file '%s' ('%s'). " % (conf.resultsFile, getUnicode(ex)) + handle, conf.resultsFile = tempfile.mkstemp(prefix=MKSTEMP_PREFIX.RESULTS, suffix=".csv") os.close(handle) - conf.resultsFP = openFile(conf.resultsFilename, "w+", UNICODE_ENCODING, buffering=0) - warnMsg += "Using temporary file '%s' instead" % conf.resultsFilename + conf.resultsFP = openFile(conf.resultsFile, "w+", UNICODE_ENCODING, buffering=0) + warnMsg += "Using temporary file '%s' instead" % conf.resultsFile logger.warn(warnMsg) except IOError as _: errMsg = "unable to write to the temporary directory ('%s'). " % _ @@ -579,9 +581,10 @@ def _setResultsFile(): errMsg += "create temporary files and/or directories" raise SqlmapSystemException(errMsg) - conf.resultsFP.writelines("Target URL,Place,Parameter,Technique(s),Note(s)%s" % os.linesep) + if not found: + conf.resultsFP.writelines("Target URL,Place,Parameter,Technique(s),Note(s)%s" % os.linesep) - logger.info("using '%s' as the CSV results file in multiple targets mode" % conf.resultsFilename) + logger.info("using '%s' as the CSV results file in multiple targets mode" % conf.resultsFile) def _createFilesDir(): """ diff --git a/lib/parse/cmdline.py b/lib/parse/cmdline.py index fbd3727a0..01b100b06 100644 --- a/lib/parse/cmdline.py +++ b/lib/parse/cmdline.py @@ -728,6 +728,9 @@ def cmdLineParser(argv=None): miscellaneous.add_argument("--purge", dest="purge", action="store_true", help="Safely remove all content from sqlmap data directory") + miscellaneous.add_argument("--results-file", dest="resultsFile", + help="Location of CSV results file in multiple targets mode") + miscellaneous.add_argument("--sqlmap-shell", dest="sqlmapShell", action="store_true", help="Prompt for an interactive sqlmap shell") diff --git a/sqlmap.conf b/sqlmap.conf index 07df2c5af..e2fa753c4 100644 --- a/sqlmap.conf +++ b/sqlmap.conf @@ -822,6 +822,9 @@ listTampers = False # Valid: True or False offline = False +# Location of CSV results file in multiple targets mode. +resultsFile = + # Local directory for storing temporary files. tmpDir =