""" Commandline tool which convert a cronos database to .csv, .sql or .html. python3 croconvert.py -t html chechnya_proverki_ul_2012/ """ from .Database import Database from .crodump import strucrack, dbcrack from .hexdump import unhex from sys import exit, stdout from os.path import dirname, abspath, join from os import mkdir, chdir from datetime import datetime import base64 import csv def template_convert(kod, args): """looks up template to convert to, parses the database and passes it to jinja2""" try: from jinja2 import Environment, FileSystemLoader except ImportError: exit( "Fatal: Jinja templating engine not found. Install using pip install jinja2" ) db = Database(args.dbdir, args.compact, kod) template_dir = join(dirname(dirname(abspath(__file__))), "templates") j2_env = Environment(loader=FileSystemLoader(template_dir)) j2_templ = j2_env.get_template(args.template + ".j2") j2_templ.stream(db=db, base64=base64).dump(stdout) def safepathname(name): return name.replace(':', '_').replace('/', '_').replace('\\', '_') def csv_output(kod, args): """creates a directory with the current timestamp and in it a set of CSV or TSV files with all the tables found and an extra directory with all the files""" db = Database(args.dbdir, args.compact, kod) mkdir(args.outputdir) chdir(args.outputdir) filereferences = [] # first dump all non-file tables for table in db.enumerate_tables(files=False): tablesafename = safepathname(table.tablename) + ".csv" with open(tablesafename, 'w', encoding='utf-8') as csvfile: writer = csv.writer(csvfile, delimiter=args.delimiter, escapechar='\\') writer.writerow([field.name for field in table.fields]) # Record should be iterable over its fields, so we could use writerows for record in db.enumerate_records(table): writer.writerow([field.content for field in record.fields]) filereferences.extend([field for field in record.fields if field.typ == 6]) # Write all files from the file table. This is useful for unreferenced files for table in db.enumerate_tables(files=True): filedir = "Files-" + table.abbrev mkdir(filedir) for system_number, content in db.enumerate_files(table): with open(join(filedir, str(system_number)), "wb") as binfile: binfile.write(content) if len(filereferences): filedir = "Files-Referenced" mkdir(filedir) # Write all referenced files with their filename and extension intact for reffile in filereferences: if reffile.content: # only print when file is not NULL filesafename = safepathname(reffile.filename) + "." + safepathname(reffile.extname) content = db.get_record(reffile.filedatarecord) with open(join("Files-Referenced", filesafename), "wb") as binfile: binfile.write(content) def main(): import argparse parser = argparse.ArgumentParser(description="CRONOS database converter") parser.add_argument("--template", "-t", type=str, default="html", help="output template to use for conversion") parser.add_argument("--csv", "-c", action='store_true', help="create output in .csv format") parser.add_argument("--delimiter", "-d", default=",", help="delimiter used in csv output") parser.add_argument("--outputdir", "-o", type=str, help="directory to create the dump in") parser.add_argument("--kod", type=str, help="specify custom KOD table") parser.add_argument("--compact", action="store_true", help="save memory by not caching the index, note: increases convert time by factor 1.15") parser.add_argument("--strucrack", action="store_true", help="infer the KOD sbox from CroStru.dat") parser.add_argument("--dbcrack", action="store_true", help="infer the KOD sbox from CroIndex.dat+CroBank.dat") parser.add_argument("--nokod", "-n", action="store_true", help="don't KOD decode") parser.add_argument("dbdir", type=str) args = parser.parse_args() import crodump.koddecoder if args.kod: if len(args.kod)!=512: raise Exception("--kod should have a 512 hex digit argument") kod = crodump.koddecoder.new(list(unhex(args.kod))) elif args.nokod: kod = None elif args.strucrack: class Cls: pass cargs = Cls() cargs.dbdir = args.dbdir cargs.sys = False cargs.silent = True cracked = strucrack(None, cargs) if not cracked: return kod = crodump.koddecoder.new(cracked) elif args.dbcrack: class Cls: pass cargs = Cls() cargs.dbdir = args.dbdir cargs.sys = False cargs.silent = True cracked = dbcrack(None, cargs) if not cracked: return kod = crodump.koddecoder.new(cracked) else: kod = crodump.koddecoder.new() if args.csv: if not args.outputdir: args.outputdir = "cronodump"+datetime.now().strftime("-%Y-%m-%d-%H-%M-%S-%f") csv_output(kod, args) else: template_convert(kod, args) if __name__ == "__main__": main()