Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sqlmapproject
GitHub Repository: sqlmapproject/sqlmap
Path: blob/master/plugins/generic/entries.py
2989 views
1
#!/usr/bin/env python
2
3
"""
4
Copyright (c) 2006-2025 sqlmap developers (https://sqlmap.org)
5
See the file 'LICENSE' for copying permission
6
"""
7
8
import re
9
10
from lib.core.agent import agent
11
from lib.core.bigarray import BigArray
12
from lib.core.common import Backend
13
from lib.core.common import clearConsoleLine
14
from lib.core.common import getLimitRange
15
from lib.core.common import getSafeExString
16
from lib.core.common import isInferenceAvailable
17
from lib.core.common import isListLike
18
from lib.core.common import isNoneValue
19
from lib.core.common import isNumPosStrValue
20
from lib.core.common import isTechniqueAvailable
21
from lib.core.common import prioritySortColumns
22
from lib.core.common import readInput
23
from lib.core.common import safeSQLIdentificatorNaming
24
from lib.core.common import singleTimeLogMessage
25
from lib.core.common import singleTimeWarnMessage
26
from lib.core.common import unArrayizeValue
27
from lib.core.common import unsafeSQLIdentificatorNaming
28
from lib.core.convert import getConsoleLength
29
from lib.core.convert import getUnicode
30
from lib.core.data import conf
31
from lib.core.data import kb
32
from lib.core.data import logger
33
from lib.core.data import queries
34
from lib.core.dicts import DUMP_REPLACEMENTS
35
from lib.core.enums import CHARSET_TYPE
36
from lib.core.enums import DBMS
37
from lib.core.enums import EXPECTED
38
from lib.core.enums import PAYLOAD
39
from lib.core.exception import SqlmapConnectionException
40
from lib.core.exception import SqlmapMissingMandatoryOptionException
41
from lib.core.exception import SqlmapNoneDataException
42
from lib.core.exception import SqlmapUnsupportedFeatureException
43
from lib.core.settings import CHECK_ZERO_COLUMNS_THRESHOLD
44
from lib.core.settings import CURRENT_DB
45
from lib.core.settings import METADB_SUFFIX
46
from lib.core.settings import NULL
47
from lib.core.settings import PLUS_ONE_DBMSES
48
from lib.core.settings import UPPER_CASE_DBMSES
49
from lib.request import inject
50
from lib.utils.hash import attackDumpedTable
51
from lib.utils.pivotdumptable import pivotDumpTable
52
from thirdparty import six
53
from thirdparty.six.moves import zip as _zip
54
55
class Entries(object):
56
"""
57
This class defines entries' enumeration functionalities for plugins.
58
"""
59
60
def __init__(self):
61
pass
62
63
def dumpTable(self, foundData=None):
64
self.forceDbmsEnum()
65
66
if conf.db is None or conf.db == CURRENT_DB:
67
if conf.db is None:
68
warnMsg = "missing database parameter. sqlmap is going "
69
warnMsg += "to use the current database to enumerate "
70
warnMsg += "table(s) entries"
71
logger.warning(warnMsg)
72
73
conf.db = self.getCurrentDb()
74
75
elif conf.db is not None:
76
if Backend.getIdentifiedDbms() in UPPER_CASE_DBMSES:
77
conf.db = conf.db.upper()
78
79
if ',' in conf.db:
80
errMsg = "only one database name is allowed when enumerating "
81
errMsg += "the tables' columns"
82
raise SqlmapMissingMandatoryOptionException(errMsg)
83
84
if conf.exclude and re.search(conf.exclude, conf.db, re.I) is not None:
85
infoMsg = "skipping database '%s'" % unsafeSQLIdentificatorNaming(conf.db)
86
singleTimeLogMessage(infoMsg)
87
return
88
89
conf.db = safeSQLIdentificatorNaming(conf.db) or ""
90
91
if conf.tbl:
92
if Backend.getIdentifiedDbms() in UPPER_CASE_DBMSES:
93
conf.tbl = conf.tbl.upper()
94
95
tblList = conf.tbl.split(',')
96
else:
97
self.getTables()
98
99
if len(kb.data.cachedTables) > 0:
100
tblList = list(six.itervalues(kb.data.cachedTables))
101
102
if tblList and isListLike(tblList[0]):
103
tblList = tblList[0]
104
elif conf.db and not conf.search:
105
errMsg = "unable to retrieve the tables "
106
errMsg += "in database '%s'" % unsafeSQLIdentificatorNaming(conf.db)
107
raise SqlmapNoneDataException(errMsg)
108
else:
109
return
110
111
for tbl in tblList:
112
tblList[tblList.index(tbl)] = safeSQLIdentificatorNaming(tbl, True)
113
114
for tbl in tblList:
115
if kb.dumpKeyboardInterrupt:
116
break
117
118
if conf.exclude and re.search(conf.exclude, unsafeSQLIdentificatorNaming(tbl), re.I) is not None:
119
infoMsg = "skipping table '%s'" % unsafeSQLIdentificatorNaming(tbl)
120
singleTimeLogMessage(infoMsg)
121
continue
122
123
conf.tbl = tbl
124
kb.data.dumpedTable = {}
125
126
if foundData is None:
127
kb.data.cachedColumns = {}
128
self.getColumns(onlyColNames=True, dumpMode=True)
129
else:
130
kb.data.cachedColumns = foundData
131
132
try:
133
if Backend.isDbms(DBMS.INFORMIX):
134
kb.dumpTable = "%s:%s" % (conf.db, tbl)
135
elif Backend.isDbms(DBMS.SQLITE):
136
kb.dumpTable = tbl
137
elif METADB_SUFFIX.upper() in conf.db.upper():
138
kb.dumpTable = tbl
139
else:
140
kb.dumpTable = "%s.%s" % (conf.db, tbl)
141
142
if safeSQLIdentificatorNaming(conf.db) not in kb.data.cachedColumns or safeSQLIdentificatorNaming(tbl, True) not in kb.data.cachedColumns[safeSQLIdentificatorNaming(conf.db)] or not kb.data.cachedColumns[safeSQLIdentificatorNaming(conf.db)][safeSQLIdentificatorNaming(tbl, True)]:
143
warnMsg = "unable to enumerate the columns for table '%s'" % unsafeSQLIdentificatorNaming(tbl)
144
if METADB_SUFFIX.upper() not in conf.db.upper():
145
warnMsg += " in database '%s'" % unsafeSQLIdentificatorNaming(conf.db)
146
warnMsg += ", skipping" if len(tblList) > 1 else ""
147
logger.warning(warnMsg)
148
149
continue
150
151
columns = kb.data.cachedColumns[safeSQLIdentificatorNaming(conf.db)][safeSQLIdentificatorNaming(tbl, True)]
152
colList = sorted(column for column in columns if column)
153
154
if conf.exclude:
155
colList = [_ for _ in colList if re.search(conf.exclude, _, re.I) is None]
156
157
if not colList:
158
warnMsg = "skipping table '%s'" % unsafeSQLIdentificatorNaming(tbl)
159
if METADB_SUFFIX.upper() not in conf.db.upper():
160
warnMsg += " in database '%s'" % unsafeSQLIdentificatorNaming(conf.db)
161
warnMsg += " (no usable column names)"
162
logger.warning(warnMsg)
163
continue
164
165
kb.dumpColumns = [unsafeSQLIdentificatorNaming(_) for _ in colList]
166
colNames = colString = ','.join(column for column in colList)
167
rootQuery = queries[Backend.getIdentifiedDbms()].dump_table
168
169
infoMsg = "fetching entries"
170
if conf.col:
171
infoMsg += " of column(s) '%s'" % colNames
172
infoMsg += " for table '%s'" % unsafeSQLIdentificatorNaming(tbl)
173
if METADB_SUFFIX.upper() not in conf.db.upper():
174
infoMsg += " in database '%s'" % unsafeSQLIdentificatorNaming(conf.db)
175
logger.info(infoMsg)
176
177
for column in colList:
178
_ = agent.preprocessField(tbl, column)
179
if _ != column:
180
colString = re.sub(r"\b%s\b" % re.escape(column), _.replace("\\", r"\\"), colString)
181
182
entriesCount = 0
183
184
if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR, PAYLOAD.TECHNIQUE.QUERY)) or conf.direct:
185
entries = []
186
query = None
187
188
if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.DERBY, DBMS.ALTIBASE, DBMS.MIMERSQL):
189
query = rootQuery.inband.query % (colString, tbl.upper() if not conf.db else ("%s.%s" % (conf.db.upper(), tbl.upper())))
190
elif Backend.getIdentifiedDbms() in (DBMS.SQLITE, DBMS.ACCESS, DBMS.FIREBIRD, DBMS.MAXDB, DBMS.MCKOI, DBMS.EXTREMEDB, DBMS.RAIMA):
191
query = rootQuery.inband.query % (colString, tbl)
192
elif Backend.getIdentifiedDbms() in (DBMS.SYBASE, DBMS.MSSQL):
193
# Partial inband and error
194
if not (isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION) and kb.injection.data[PAYLOAD.TECHNIQUE.UNION].where == PAYLOAD.WHERE.ORIGINAL):
195
table = "%s.%s" % (conf.db, tbl) if conf.db else tbl
196
197
if Backend.isDbms(DBMS.MSSQL) and not conf.forcePivoting:
198
warnMsg = "in case of table dumping problems (e.g. column entry order) "
199
warnMsg += "you are advised to rerun with '--force-pivoting'"
200
singleTimeWarnMessage(warnMsg)
201
202
query = rootQuery.blind.count % table
203
query = agent.whereQuery(query)
204
205
count = inject.getValue(query, blind=False, time=False, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS)
206
if isNumPosStrValue(count):
207
try:
208
indexRange = getLimitRange(count, plusOne=True)
209
210
for index in indexRange:
211
row = []
212
for column in colList:
213
query = rootQuery.blind.query3 % (column, column, table, index)
214
query = agent.whereQuery(query)
215
value = inject.getValue(query, blind=False, time=False, dump=True) or ""
216
row.append(value)
217
218
if not entries and isNoneValue(row):
219
break
220
221
entries.append(row)
222
223
except KeyboardInterrupt:
224
kb.dumpKeyboardInterrupt = True
225
clearConsoleLine()
226
warnMsg = "Ctrl+C detected in dumping phase"
227
logger.warning(warnMsg)
228
229
if isNoneValue(entries) and not kb.dumpKeyboardInterrupt:
230
try:
231
retVal = pivotDumpTable(table, colList, blind=False)
232
except KeyboardInterrupt:
233
retVal = None
234
kb.dumpKeyboardInterrupt = True
235
clearConsoleLine()
236
warnMsg = "Ctrl+C detected in dumping phase"
237
logger.warning(warnMsg)
238
239
if retVal:
240
entries, _ = retVal
241
entries = BigArray(_zip(*[entries[colName] for colName in colList]))
242
else:
243
query = rootQuery.inband.query % (colString, conf.db, tbl)
244
elif Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.HSQLDB, DBMS.H2, DBMS.VERTICA, DBMS.PRESTO, DBMS.CRATEDB, DBMS.CACHE, DBMS.VIRTUOSO, DBMS.CLICKHOUSE):
245
query = rootQuery.inband.query % (colString, conf.db, tbl, prioritySortColumns(colList)[0])
246
else:
247
query = rootQuery.inband.query % (colString, conf.db, tbl)
248
249
query = agent.whereQuery(query)
250
251
if not entries and query and not kb.dumpKeyboardInterrupt:
252
try:
253
entries = inject.getValue(query, blind=False, time=False, dump=True)
254
except KeyboardInterrupt:
255
entries = None
256
kb.dumpKeyboardInterrupt = True
257
clearConsoleLine()
258
warnMsg = "Ctrl+C detected in dumping phase"
259
logger.warning(warnMsg)
260
261
if not isNoneValue(entries):
262
if isinstance(entries, six.string_types):
263
entries = [entries]
264
elif not isListLike(entries):
265
entries = []
266
267
entriesCount = len(entries)
268
269
for index, column in enumerate(colList):
270
if column not in kb.data.dumpedTable:
271
kb.data.dumpedTable[column] = {"length": len(column), "values": BigArray()}
272
273
for entry in entries:
274
if entry is None or len(entry) == 0:
275
continue
276
277
if isinstance(entry, six.string_types):
278
colEntry = entry
279
else:
280
colEntry = unArrayizeValue(entry[index]) if index < len(entry) else u''
281
282
maxLen = max(getConsoleLength(column), getConsoleLength(DUMP_REPLACEMENTS.get(getUnicode(colEntry), getUnicode(colEntry))))
283
284
if maxLen > kb.data.dumpedTable[column]["length"]:
285
kb.data.dumpedTable[column]["length"] = maxLen
286
287
kb.data.dumpedTable[column]["values"].append(colEntry)
288
289
if not kb.data.dumpedTable and isInferenceAvailable() and not conf.direct:
290
infoMsg = "fetching number of "
291
if conf.col:
292
infoMsg += "column(s) '%s' " % colNames
293
infoMsg += "entries for table '%s' " % unsafeSQLIdentificatorNaming(tbl)
294
infoMsg += "in database '%s'" % unsafeSQLIdentificatorNaming(conf.db)
295
logger.info(infoMsg)
296
297
if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.DERBY, DBMS.ALTIBASE, DBMS.MIMERSQL):
298
query = rootQuery.blind.count % (tbl.upper() if not conf.db else ("%s.%s" % (conf.db.upper(), tbl.upper())))
299
elif Backend.getIdentifiedDbms() in (DBMS.SQLITE, DBMS.MAXDB, DBMS.ACCESS, DBMS.FIREBIRD, DBMS.MCKOI, DBMS.EXTREMEDB, DBMS.RAIMA):
300
query = rootQuery.blind.count % tbl
301
elif Backend.getIdentifiedDbms() in (DBMS.SYBASE, DBMS.MSSQL):
302
query = rootQuery.blind.count % ("%s.%s" % (conf.db, tbl)) if conf.db else tbl
303
elif Backend.isDbms(DBMS.INFORMIX):
304
query = rootQuery.blind.count % (conf.db, tbl)
305
else:
306
query = rootQuery.blind.count % (conf.db, tbl)
307
308
query = agent.whereQuery(query)
309
310
count = inject.getValue(query, union=False, error=False, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS)
311
312
lengths = {}
313
entries = {}
314
315
if count == 0:
316
warnMsg = "table '%s' " % unsafeSQLIdentificatorNaming(tbl)
317
warnMsg += "in database '%s' " % unsafeSQLIdentificatorNaming(conf.db)
318
warnMsg += "appears to be empty"
319
logger.warning(warnMsg)
320
321
for column in colList:
322
lengths[column] = len(column)
323
entries[column] = []
324
325
elif not isNumPosStrValue(count):
326
warnMsg = "unable to retrieve the number of "
327
if conf.col:
328
warnMsg += "column(s) '%s' " % colNames
329
warnMsg += "entries for table '%s' " % unsafeSQLIdentificatorNaming(tbl)
330
warnMsg += "in database '%s'" % unsafeSQLIdentificatorNaming(conf.db)
331
logger.warning(warnMsg)
332
333
continue
334
335
elif Backend.getIdentifiedDbms() in (DBMS.ACCESS, DBMS.SYBASE, DBMS.MAXDB, DBMS.MSSQL, DBMS.INFORMIX, DBMS.MCKOI, DBMS.RAIMA):
336
if Backend.getIdentifiedDbms() in (DBMS.ACCESS, DBMS.MCKOI, DBMS.RAIMA):
337
table = tbl
338
elif Backend.getIdentifiedDbms() in (DBMS.SYBASE, DBMS.MSSQL, DBMS.MAXDB):
339
table = "%s.%s" % (conf.db, tbl) if conf.db else tbl
340
elif Backend.isDbms(DBMS.INFORMIX):
341
table = "%s:%s" % (conf.db, tbl) if conf.db else tbl
342
343
if Backend.isDbms(DBMS.MSSQL) and not conf.forcePivoting:
344
warnMsg = "in case of table dumping problems (e.g. column entry order) "
345
warnMsg += "you are advised to rerun with '--force-pivoting'"
346
singleTimeWarnMessage(warnMsg)
347
348
try:
349
indexRange = getLimitRange(count, plusOne=True)
350
351
for index in indexRange:
352
for column in colList:
353
query = rootQuery.blind.query3 % (column, column, table, index)
354
query = agent.whereQuery(query)
355
356
value = inject.getValue(query, union=False, error=False, dump=True) or ""
357
358
if column not in lengths:
359
lengths[column] = 0
360
361
if column not in entries:
362
entries[column] = BigArray()
363
364
lengths[column] = max(lengths[column], len(DUMP_REPLACEMENTS.get(getUnicode(value), getUnicode(value))))
365
entries[column].append(value)
366
367
except KeyboardInterrupt:
368
kb.dumpKeyboardInterrupt = True
369
clearConsoleLine()
370
warnMsg = "Ctrl+C detected in dumping phase"
371
logger.warning(warnMsg)
372
373
if not entries and not kb.dumpKeyboardInterrupt:
374
try:
375
retVal = pivotDumpTable(table, colList, count, blind=True)
376
except KeyboardInterrupt:
377
retVal = None
378
kb.dumpKeyboardInterrupt = True
379
clearConsoleLine()
380
warnMsg = "Ctrl+C detected in dumping phase"
381
logger.warning(warnMsg)
382
383
if retVal:
384
entries, lengths = retVal
385
386
else:
387
emptyColumns = []
388
plusOne = Backend.getIdentifiedDbms() in PLUS_ONE_DBMSES
389
indexRange = getLimitRange(count, plusOne=plusOne)
390
391
if len(colList) < len(indexRange) > CHECK_ZERO_COLUMNS_THRESHOLD:
392
debugMsg = "checking for empty columns"
393
logger.debug(infoMsg)
394
395
for column in colList:
396
if not inject.checkBooleanExpression("(SELECT COUNT(%s) FROM %s)>0" % (column, kb.dumpTable)):
397
emptyColumns.append(column)
398
debugMsg = "column '%s' of table '%s' will not be " % (column, kb.dumpTable)
399
debugMsg += "dumped as it appears to be empty"
400
logger.debug(debugMsg)
401
402
try:
403
for index in indexRange:
404
for column in colList:
405
value = ""
406
407
if column not in lengths:
408
lengths[column] = 0
409
410
if column not in entries:
411
entries[column] = BigArray()
412
413
if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.HSQLDB, DBMS.H2, DBMS.VERTICA, DBMS.PRESTO, DBMS.CRATEDB, DBMS.CACHE, DBMS.CLICKHOUSE):
414
query = rootQuery.blind.query % (agent.preprocessField(tbl, column), conf.db, conf.tbl, sorted(colList, key=len)[0], index)
415
elif Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.DERBY, DBMS.ALTIBASE,):
416
query = rootQuery.blind.query % (agent.preprocessField(tbl, column), tbl.upper() if not conf.db else ("%s.%s" % (conf.db.upper(), tbl.upper())), index)
417
elif Backend.getIdentifiedDbms() in (DBMS.MIMERSQL,):
418
query = rootQuery.blind.query % (agent.preprocessField(tbl, column), tbl.upper() if not conf.db else ("%s.%s" % (conf.db.upper(), tbl.upper())), sorted(colList, key=len)[0], index)
419
elif Backend.getIdentifiedDbms() in (DBMS.SQLITE, DBMS.EXTREMEDB):
420
query = rootQuery.blind.query % (agent.preprocessField(tbl, column), tbl, index)
421
elif Backend.isDbms(DBMS.FIREBIRD):
422
query = rootQuery.blind.query % (index, agent.preprocessField(tbl, column), tbl)
423
elif Backend.getIdentifiedDbms() in (DBMS.INFORMIX, DBMS.VIRTUOSO):
424
query = rootQuery.blind.query % (index, agent.preprocessField(tbl, column), conf.db, tbl, sorted(colList, key=len)[0])
425
elif Backend.isDbms(DBMS.FRONTBASE):
426
query = rootQuery.blind.query % (index, agent.preprocessField(tbl, column), conf.db, tbl)
427
else:
428
query = rootQuery.blind.query % (agent.preprocessField(tbl, column), conf.db, tbl, index)
429
430
query = agent.whereQuery(query)
431
432
value = NULL if column in emptyColumns else inject.getValue(query, union=False, error=False, dump=True)
433
value = '' if value is None else value
434
435
lengths[column] = max(lengths[column], len(DUMP_REPLACEMENTS.get(getUnicode(value), getUnicode(value))))
436
entries[column].append(value)
437
438
except KeyboardInterrupt:
439
kb.dumpKeyboardInterrupt = True
440
clearConsoleLine()
441
warnMsg = "Ctrl+C detected in dumping phase"
442
logger.warning(warnMsg)
443
444
for column, columnEntries in entries.items():
445
length = max(lengths[column], len(column))
446
447
kb.data.dumpedTable[column] = {"length": length, "values": columnEntries}
448
449
entriesCount = len(columnEntries)
450
451
if len(kb.data.dumpedTable) == 0 or (entriesCount == 0 and kb.permissionFlag):
452
warnMsg = "unable to retrieve the entries "
453
if conf.col:
454
warnMsg += "of columns '%s' " % colNames
455
warnMsg += "for table '%s' " % unsafeSQLIdentificatorNaming(tbl)
456
warnMsg += "in database '%s'%s" % (unsafeSQLIdentificatorNaming(conf.db), " (permission denied)" if kb.permissionFlag else "")
457
logger.warning(warnMsg)
458
else:
459
kb.data.dumpedTable["__infos__"] = {"count": entriesCount,
460
"table": safeSQLIdentificatorNaming(tbl, True),
461
"db": safeSQLIdentificatorNaming(conf.db)}
462
463
if not conf.disableHashing:
464
try:
465
attackDumpedTable()
466
except (IOError, OSError) as ex:
467
errMsg = "an error occurred while attacking "
468
errMsg += "table dump ('%s')" % getSafeExString(ex)
469
logger.critical(errMsg)
470
471
conf.dumper.dbTableValues(kb.data.dumpedTable)
472
473
except SqlmapConnectionException as ex:
474
errMsg = "connection exception detected in dumping phase "
475
errMsg += "('%s')" % getSafeExString(ex)
476
logger.critical(errMsg)
477
478
finally:
479
kb.dumpColumns = None
480
kb.dumpTable = None
481
482
def dumpAll(self):
483
if conf.db is not None and conf.tbl is None:
484
self.dumpTable()
485
return
486
487
if Backend.isDbms(DBMS.MYSQL) and not kb.data.has_information_schema:
488
errMsg = "information_schema not available, "
489
errMsg += "back-end DBMS is MySQL < 5.0"
490
raise SqlmapUnsupportedFeatureException(errMsg)
491
492
infoMsg = "sqlmap will dump entries of all tables from all databases now"
493
logger.info(infoMsg)
494
495
conf.tbl = None
496
conf.col = None
497
498
self.getTables()
499
500
if kb.data.cachedTables:
501
if isinstance(kb.data.cachedTables, list):
502
kb.data.cachedTables = {None: kb.data.cachedTables}
503
504
for db, tables in kb.data.cachedTables.items():
505
conf.db = db
506
507
for table in tables:
508
if conf.exclude and re.search(conf.exclude, table, re.I) is not None:
509
infoMsg = "skipping table '%s'" % unsafeSQLIdentificatorNaming(table)
510
logger.info(infoMsg)
511
continue
512
513
try:
514
conf.tbl = table
515
kb.data.cachedColumns = {}
516
kb.data.dumpedTable = {}
517
518
self.dumpTable()
519
except SqlmapNoneDataException:
520
infoMsg = "skipping table '%s'" % unsafeSQLIdentificatorNaming(table)
521
logger.info(infoMsg)
522
523
def dumpFoundColumn(self, dbs, foundCols, colConsider):
524
message = "do you want to dump found column(s) entries? [Y/n] "
525
526
if not readInput(message, default='Y', boolean=True):
527
return
528
529
dumpFromDbs = []
530
message = "which database(s)?\n[a]ll (default)\n"
531
532
for db, tblData in dbs.items():
533
if tblData:
534
message += "[%s]\n" % unsafeSQLIdentificatorNaming(db)
535
536
message += "[q]uit"
537
choice = readInput(message, default='a')
538
539
if not choice or choice in ('a', 'A'):
540
dumpFromDbs = list(dbs.keys())
541
elif choice in ('q', 'Q'):
542
return
543
else:
544
dumpFromDbs = choice.replace(" ", "").split(',')
545
546
for db, tblData in dbs.items():
547
if db not in dumpFromDbs or not tblData:
548
continue
549
550
conf.db = db
551
dumpFromTbls = []
552
message = "which table(s) of database '%s'?\n" % unsafeSQLIdentificatorNaming(db)
553
message += "[a]ll (default)\n"
554
555
for tbl in tblData:
556
message += "[%s]\n" % tbl
557
558
message += "[s]kip\n"
559
message += "[q]uit"
560
choice = readInput(message, default='a')
561
562
if not choice or choice in ('a', 'A'):
563
dumpFromTbls = tblData
564
elif choice in ('s', 'S'):
565
continue
566
elif choice in ('q', 'Q'):
567
return
568
else:
569
dumpFromTbls = choice.replace(" ", "").split(',')
570
571
for table, columns in tblData.items():
572
if table not in dumpFromTbls:
573
continue
574
575
conf.tbl = table
576
colList = [_ for _ in columns if _]
577
578
if conf.exclude:
579
colList = [_ for _ in colList if re.search(conf.exclude, _, re.I) is None]
580
581
conf.col = ','.join(colList)
582
kb.data.cachedColumns = {}
583
kb.data.dumpedTable = {}
584
585
data = self.dumpTable(dbs)
586
587
if data:
588
conf.dumper.dbTableValues(data)
589
590
def dumpFoundTables(self, tables):
591
message = "do you want to dump found table(s) entries? [Y/n] "
592
593
if not readInput(message, default='Y', boolean=True):
594
return
595
596
dumpFromDbs = []
597
message = "which database(s)?\n[a]ll (default)\n"
598
599
for db, tablesList in tables.items():
600
if tablesList:
601
message += "[%s]\n" % unsafeSQLIdentificatorNaming(db)
602
603
message += "[q]uit"
604
choice = readInput(message, default='a')
605
606
if not choice or choice.lower() == 'a':
607
dumpFromDbs = list(tables.keys())
608
elif choice.lower() == 'q':
609
return
610
else:
611
dumpFromDbs = choice.replace(" ", "").split(',')
612
613
for db, tablesList in tables.items():
614
if db not in dumpFromDbs or not tablesList:
615
continue
616
617
conf.db = db
618
dumpFromTbls = []
619
message = "which table(s) of database '%s'?\n" % unsafeSQLIdentificatorNaming(db)
620
message += "[a]ll (default)\n"
621
622
for tbl in tablesList:
623
message += "[%s]\n" % unsafeSQLIdentificatorNaming(tbl)
624
625
message += "[s]kip\n"
626
message += "[q]uit"
627
choice = readInput(message, default='a')
628
629
if not choice or choice.lower() == 'a':
630
dumpFromTbls = tablesList
631
elif choice.lower() == 's':
632
continue
633
elif choice.lower() == 'q':
634
return
635
else:
636
dumpFromTbls = choice.replace(" ", "").split(',')
637
638
for table in dumpFromTbls:
639
conf.tbl = table
640
kb.data.cachedColumns = {}
641
kb.data.dumpedTable = {}
642
643
data = self.dumpTable()
644
645
if data:
646
conf.dumper.dbTableValues(data)
647
648