From 48e0261e68e49203a8032865456a7daf5d6b733d Mon Sep 17 00:00:00 2001 From: Miroslav Stampar Date: Fri, 24 Sep 2010 13:19:35 +0000 Subject: [PATCH] update for Feature #61 --- lib/core/dump.py | 35 ++++++++++++++++++++++++++--------- lib/core/optiondict.py | 1 + lib/core/replication.py | 28 ++++++++++++++-------------- lib/parse/cmdline.py | 3 +++ 4 files changed, 44 insertions(+), 23 deletions(-) diff --git a/lib/core/dump.py b/lib/core/dump.py index 7ca1cd393..1609fa2f9 100644 --- a/lib/core/dump.py +++ b/lib/core/dump.py @@ -30,7 +30,9 @@ from lib.core.common import dataToDumpFile from lib.core.common import dataToStdout from lib.core.common import getUnicode from lib.core.data import conf +from lib.core.data import kb from lib.core.data import logger +from lib.core.replication import Replication class Dump: """ @@ -44,10 +46,7 @@ class Dump: self.__outputFP = None def __write(self, data, n=True): - if n: - text = "%s\n" % data - else: - text = "%s " % data + text = "%s%s" % (data, "\n" if n else " ") dataToStdout(text) self.__outputFP.write(text) @@ -84,7 +83,7 @@ class Dump: self.__write("%s: '%s'\n" % (header, data)) else: self.__write("%s:\tNone\n" % header) - + def lister(self, header, elements, sort=True): if elements: self.__write("%s [%d]:" % (header, len(elements))) @@ -269,10 +268,12 @@ class Dump: dumpFileName = "%s%s%s.csv" % (dumpDbPath, os.sep, table) dumpFP = codecs.open(dumpFileName, "wb", conf.dataEncoding) - count = int(tableValues["__infos__"]["count"]) - separator = "" - field = 1 - fields = len(tableValues) - 1 + count = int(tableValues["__infos__"]["count"]) + separator = str() + field = 1 + fields = len(tableValues) - 1 + replication = None + rtable = None columns = tableValues.keys() columns.sort(key=lambda x: x.lower()) @@ -286,6 +287,14 @@ class Dump: separator += "+" self.__write("Database: %s\nTable: %s" % (db, table)) + + if conf.replicate: + replication = Replication("%s%s%s.sqlite" % (conf.outputPath, os.sep, db)) + cols = list(columns) + if "__infos__" in cols: + cols.remove("__infos__") + rtable = replication.createTable(table, cols, True) + if count == 1: self.__write("[1 entry]") else: @@ -315,6 +324,7 @@ class Dump: for i in range(count): field = 1 + values = [] for column in columns: if column != "__infos__": @@ -325,6 +335,7 @@ class Dump: if re.search("^[\ *]*$", value): value = "NULL" + values.append(value) maxlength = int(info["length"]) blank = " " * (maxlength - len(value)) self.__write("| %s%s" % (value, blank), n=False) @@ -336,6 +347,9 @@ class Dump: field += 1 + if conf.replicate: + rtable.insert(values) + self.__write("|") if not conf.multipleTargets: @@ -349,6 +363,9 @@ class Dump: logger.info("Table '%s.%s' dumped to CSV file '%s'" % (db, table, dumpFileName)) + if conf.replicate: + logger.info("Table '%s.%s' dumped to sqlite3 file '%s'" % (db, table, replication.dbpath)) + def dbColumns(self, dbColumns, colConsider, dbs): for column in dbColumns.keys(): if colConsider == "1": diff --git a/lib/core/optiondict.py b/lib/core/optiondict.py index 2051e77f4..69345770b 100644 --- a/lib/core/optiondict.py +++ b/lib/core/optiondict.py @@ -158,6 +158,7 @@ optDict = { "updateAll": "boolean", "batch": "boolean", "cleanup": "boolean", + "replicate": "boolean", "verbose": "integer" }, } diff --git a/lib/core/replication.py b/lib/core/replication.py index bb0db142f..0667ace8c 100644 --- a/lib/core/replication.py +++ b/lib/core/replication.py @@ -30,19 +30,19 @@ class Replication: This class holds all methods/classes used for database replication purposes. """ - + def __init__(self, dbpath): self.dbpath = dbpath self.connection = sqlite3.connect(dbpath) self.connection.isolation_level = None self.cursor = self.connection.cursor() - + class DataType: """ Using this class we define auxiliary objects used for representing sqlite data types. """ - + def __init__(self, name): self.name = name @@ -51,12 +51,12 @@ class Replication: def __repr__(self): return "" % self - + class Table: """ This class defines methods used to manipulate table objects. """ - + def __init__(self, parent, name, columns=None, create=True, typeless=False): self.parent = parent self.name = name @@ -67,17 +67,17 @@ class Replication: self.parent.cursor.execute('CREATE TABLE %s (%s)' % (self.name, ','.join('%s %s' % (colname, coltype) for colname, coltype in self.columns))) else: self.parent.cursor.execute('CREATE TABLE %s (%s)' % (self.name, ','.join(colname for colname in self.columns))) - - def insert(self, rows): + + def insert(self, values): """ This function is used for inserting row(s) into current table. """ - self.parent.cursor.executemany('INSERT INTO %s VALUES (?,?,?,?,?)' % self.name, rows) + self.parent.cursor.execute('INSERT INTO %s VALUES (%s)' % (self.name, ','.join(['?']*len(values))), values) def select(self, condition=None): """ This function is used for selecting row(s) from current table. - """ + """ stmt = 'SELECT * FROM %s' % self.name if condition: stmt += 'WHERE %s' % condition @@ -89,19 +89,19 @@ class Replication: REAL = DataType('REAL') TEXT = DataType('TEXT') BLOB = DataType('BLOB') - - def createTable(self, tblname, columns=None): + + def createTable(self, tblname, columns=None, typeless=False): """ This function creates Table instance with current connection settings. """ - return Table(self, tblname, columns) - + return Replication.Table(parent=self, name=tblname, columns=columns, typeless=typeless) + def dropTable(self, tblname): """ This function drops table with given name using current connection. """ self.cursor.execute('DROP TABLE IF EXISTS %s' % tblname) - + def __del__(self): self.cursor.close() self.connection.close() diff --git a/lib/parse/cmdline.py b/lib/parse/cmdline.py index f7d698ec2..7cb892fd5 100644 --- a/lib/parse/cmdline.py +++ b/lib/parse/cmdline.py @@ -457,6 +457,9 @@ def cmdLineParser(): help="Clean up the DBMS by sqlmap specific " "UDF and tables") + miscellaneous.add_option("--replicate", dest="replicate", action="store_true", + help="Replicate dumped data into a sqlite database") + # Hidden and/or experimental options parser.add_option("--profile", dest="profile", action="store_true", help=SUPPRESS_HELP)