class EXTRACT(Script, EventHandler): reservednames = ['CON', 'PRN', 'AUX', 'CLOCK$', 'NUL', 'COM0', 'COM1', 'COM2', 'COM3', 'COM4', 'COM5', 'COM6', 'COM7', 'COM8', 'COM9', 'LPT0', 'LPT1', 'LPT2', 'LPT3', 'LPT4', 'LPT5', 'LPT6', 'LPT7', 'LPT8', 'LPT9', '$AttrDef', '$BadClus', '$Bitmap', '$Boot', '$LogFile', '$MFT', '$MFTMirr', 'pagefile.sys', '$Secure', '$UpCase', '$Volume', '$Extend'] max_depth = 2**31-1 def __init__(self): Script.__init__(self, "extract") EventHandler.__init__(self) self.vfs = vfs.vfs() self.extractor = Extract() self.extractor.connection(self) def start(self, args): self.total_files = 0 self.total_folders = 0 self.extracted_files = 0 self.extracted_folders = 0 self.files_errors = 0 self.folders_errors = 0 self.ommited_files = 0 self.ommited_folders = 0 self.__failed_files = [] self.__failed_folders = [] self.__renamed = {} try: self.nodes = args['files'].value() self.syspath = args['syspath'].value().path if not os.path.isdir(self.syspath): self.res["errors"] = Variant(self.syspath + " is not a valid directory") return if args.has_key('recursive'): self.recursive = args["recursive"].value() else: self.recursive = False if args.has_key('preserve'): self.preserve = args["preserve"].value() else: self.preserve = False if args.has_key('overwrite'): self.overwrite = args["overwrite"].value() else: self.overwrite = False self.__extract() self.__createReport() except KeyError: pass def Event(self, e): if e.type == Extract.FileProgress: idx = self.stateinfo.rfind("extracting") vl = e.value.value() node = vl[0].value() percent = vl[1].value() if idx != -1: buff = self.stateinfo[:idx] buff += "extracting " + node.absolute() + ": " + str(percent) + " %" self.stateinfo = buff else: self.stateinfo += "extracting " + node.absolute() + ": " + str(percent) + " %" if e.type == Extract.OverallProgress: self.stateinfo = str(e.value) if e.type == Extract.FileFailed: vl = e.value.value() self.__failed_files.append(vl[0].value()) print "extracting file failed", vl[0].value(), "\n", vl[1] if e.type == Extract.FolderFailed: vl = e.value.value() self.__failed_folders.append(vl[0].value()) print "extracting folder failed", vl[0].value(), "\n", vl[1] if e.type == Extract.PreserveFailed: vl = e.value.value() self.__preserved_failed = vl[0].value() print "preserving tree failed", vl[0].value(), "\n", vl[1] if e.type == Extract.RenameOccured: vl = e.value.value() if not self.__renamed.has_key(vl[0].value()): self.__renamed[str(vl[0])] = [] self.__renamed[str(vl[0])].append(str(vl[1])) print "rename: ", vl[0], " --> ", vl[1] del e def __extract(self): for vnode in self.nodes: node = vnode.value() if self.recursive: self.extractor.extractTree(node, self.syspath, self.preserve, self.overwrite) else: if node.hasChildren() or node.isDir(): self.extractor.extractFolder(node, self.syspath, self.preserve, self.overwrite) else: self.extractor.extractFile(node, self.syspath, self.preserve, self.overwrite) def __createReport(self): if len(self.__failed_files): vl = VList() for ffile in self.__failed_files: vl.append(Variant(ffile)) self.res["failed extraction for files"] = vl if len(self.__failed_folders): vl = VList() for ffolder in self.__failed_folders: vl.append(Variant(ffolder)) self.res["failed extraction for folders"] = vl if len(self.__renamed): vmap = VMap() for key in self.__renamed: vl = VList() for val in self.__renamed[key]: vl.append(Variant(val)) vmap[key] = vl self.res["renamed"] = vmap
class EXTRACT(Script, EventHandler): reservednames = [ 'CON', 'PRN', 'AUX', 'CLOCK$', 'NUL', 'COM0', 'COM1', 'COM2', 'COM3', 'COM4', 'COM5', 'COM6', 'COM7', 'COM8', 'COM9', 'LPT0', 'LPT1', 'LPT2', 'LPT3', 'LPT4', 'LPT5', 'LPT6', 'LPT7', 'LPT8', 'LPT9', '$AttrDef', '$BadClus', '$Bitmap', '$Boot', '$LogFile', '$MFT', '$MFTMirr', 'pagefile.sys', '$Secure', '$UpCase', '$Volume', '$Extend' ] max_depth = 2**31 - 1 def __init__(self): Script.__init__(self, "extract") EventHandler.__init__(self) self.vfs = vfs.vfs() self.extractor = Extract() self.extractor.connection(self) def start(self, args): self.total_files = 0 self.total_folders = 0 self.extracted_files = 0 self.extracted_folders = 0 self.files_errors = 0 self.folders_errors = 0 self.ommited_files = 0 self.ommited_folders = 0 self.__failed_files = [] self.__failed_folders = [] self.__renamed = {} try: self.nodes = args['files'].value() self.syspath = args['syspath'].value().path if not os.path.isdir(self.syspath): self.res["errors"] = Variant(self.syspath + " is not a valid directory") return if args.has_key('recursive'): self.recursive = args["recursive"].value() else: self.recursive = False if args.has_key('preserve'): self.preserve = args["preserve"].value() else: self.preserve = False if args.has_key('overwrite'): self.overwrite = args["overwrite"].value() else: self.overwrite = False self.__extract() self.__createReport() except KeyError: pass def Event(self, e): if e.type == Extract.FileProgress: idx = self.stateinfo.rfind("extracting") vl = e.value.value() node = vl[0].value() percent = vl[1].value() if idx != -1: buff = self.stateinfo[:idx] buff += "extracting " + node.absolute() + ": " + str( percent) + " %" self.stateinfo = buff else: self.stateinfo += "extracting " + node.absolute() + ": " + str( percent) + " %" if e.type == Extract.OverallProgress: self.stateinfo = str(e.value) if e.type == Extract.FileFailed: vl = e.value.value() self.__failed_files.append(vl[0].value()) print "extracting file failed", vl[0].value(), "\n", vl[1] if e.type == Extract.FolderFailed: vl = e.value.value() self.__failed_folders.append(vl[0].value()) print "extracting folder failed", vl[0].value(), "\n", vl[1] if e.type == Extract.PreserveFailed: vl = e.value.value() self.__preserved_failed = vl[0].value() print "preserving tree failed", vl[0].value(), "\n", vl[1] if e.type == Extract.RenameOccured: vl = e.value.value() if not self.__renamed.has_key(vl[0].value()): self.__renamed[str(vl[0])] = [] self.__renamed[str(vl[0])].append(str(vl[1])) print "rename: ", vl[0], " --> ", vl[1] del e def __extract(self): for vnode in self.nodes: node = vnode.value() if self.recursive: self.extractor.extractTree(node, self.syspath, self.preserve, self.overwrite) else: if node.hasChildren() or node.isDir(): self.extractor.extractFolder(node, self.syspath, self.preserve, self.overwrite) else: self.extractor.extractFile(node, self.syspath, self.preserve, self.overwrite) def __createReport(self): if len(self.__failed_files): vl = VList() for ffile in self.__failed_files: vl.append(Variant(ffile)) self.res["failed extraction for files"] = vl if len(self.__failed_folders): vl = VList() for ffolder in self.__failed_folders: vl.append(Variant(ffolder)) self.res["failed extraction for folders"] = vl if len(self.__renamed): vmap = VMap() for key in self.__renamed: vl = VList() for val in self.__renamed[key]: vl.append(Variant(val)) vmap[key] = vl self.res["renamed"] = vmap
class NodeListFragment(ReportPageFragment): DefaultHeader = [ { 'title': 'name', 'callback': lambda Node: Node.name() }, { 'title': 'size', 'callback': lambda Node: Node.size() }, { 'title': 'tags', 'callback': lambda Node: getTags(Node) }, ] ListView = 0 GalleryView = 1 DetailedAttributes = None HeaderAttributes = None HeaderAttributesName = None def __init__(self, title, nodes, thead, view): ReportPageFragment.__init__(self, title) self.nodes = nodes self.thead = thead self.view = view self.extract = Extract() self.filepath = None self.thumbpath = None if QApplication.instance(): self.gui = True else: self.gui = False #XXX header don't support '.' in name def addNode(self, node): self.nodes.append(node) def elements(self): return self.nodes def dumpsJSON(self): thead = [] for head in self.thead: thead.append(head['title']) if NodeListFragment.HeaderAttributes: for attribute in NodeListFragment.HeaderAttributes: thead.append(attribute) buff = '{"title": "' + self.title + '",' + '"widget": "node_list", "thead":' buff += json.dumps(thead) buff += ', "view" : ' + str(self.view) + ', "data" : [' for node in self.nodes: try: rowjson = {} rowjson['widget'] = 'node' for head in self.thead: cb = head['callback'](node) if type(cb) == str: cb = cb.decode('utf-8', 'replace').encode('utf-8') rowjson[head['title']] = cb if self.gui: #Need qt gui for QPixmap or will crash in console #print 'self as GUI !', QApplication.instance() self.thumbnailer = Thumbnailer() if self.thumbnailer.isThumbnailable(node): rowjson[ "thumb"] = "dff-node-thumbnail://" + node.absolute( ).decode('utf-8', 'replace').encode('utf-8') self.thumbnailer.unregister() rowjson['row_details'] = { 'widget': 'node_attribute', 'data': self.attributesToMap(node.attributes()) } buff += json.dumps(rowjson) buff += "," except UnicodeError as e: print "Can't dump node " + str( node.absolute()) + " : " + str(e) buff += "]}" return buff def writeSize(self, exportContent): size = 0 if exportContent: for node in self.nodes: size += node.size() return size def writeJSON__(self, fd, page_path, report_path, exportContent=True): self.filepath = page_path + "/" + 'files' self.thumbpath = page_path + "/" + 'thumbs' buff = '{"title": "' + self.title + '",' + '"widget": "node_list", "thead":' fd.write(buff) thead = [] for head in self.thead: thead.append(head['title']) #XXX header don't support '.' in name if NodeListFragment.HeaderAttributesName: for name in NodeListFragment.HeaderAttributesName: thead.append(name) json.dump(thead, fd) bdata = ', "view" : ' + str(self.view) + ', "data" : [' fd.write(bdata) self.notifyWrite(ReportPageFragment.EventWriteElements, len(self.nodes)) for node in self.nodes: self.notifyWrite(ReportPageFragment.EventWriteElementStart, node.absolute()) try: filename = None if exportContent: filename = self.exportNode(node, self.filepath, report_path) self.nodeToJSON(node, filename, fd, report_path, page_path, True) fd.write(',\n') except Exception as e: print "Can't write node " + str( node.absolute()) + " : " + str(e) self.notifyWrite(ReportPageFragment.EventWriteElementFinish, node.absolute()) fd.write("]}") def attributesToMap(self, attributes): attributesMap = {} for key, variantMap in attributes.iteritems(): vmap = self.recurseVariant(variantMap, {}, '') if len(vmap): attributesMap[key] = vmap attributesMap = OrderedDict( sorted(attributesMap.items(), key=lambda t: t[0])) return attributesMap def recurseVariant(self, variant, varMap, keyPath): if isinstance(variant, VMap): for key, vvar in variant.iteritems(): if len(keyPath): self.recurseVariant(vvar, varMap, keyPath + '.' + str(key)) else: self.recurseVariant(vvar, varMap, str(key)) if isinstance(variant, VList): l = [] for i in range(len(variant)): self.recurseVariant(variant[i], varMap, keyPath + ' (' + str(i) + ')') if isinstance(variant, Variant) or isinstance(variant, RCVariant): val = variant.value() if isinstance(val, VMap) or isinstance(val, VList): self.recurseVariant(val, varMap, keyPath) else: if isinstance(val, DateTime): try: val = str(val) except: val = "Invalid" if type(val) == str: val = val.decode('utf-8', 'replace').encode('utf-8') translated = False if NodeListFragment.DetailedAttributes: for ( finalName, attributeName ) in NodeListFragment.DetailedAttributes: #HeaderAttributes depend of this because it's attribute filled in the table will use the result of this function called by attributesMap if there is no detailed attributes there will no translation and the header can't be filled if keyPath == attributeName: varMap[finalName] = val if not translated: varMap[keyPath] = val varMap = OrderedDict(sorted(varMap.items(), key=lambda t: t[0])) return varMap def findInAttributesMap(self, attribute, attributesMap): for module in attributesMap: moduleAttributes = attributesMap.get(module) if moduleAttributes: result = moduleAttributes.get(attribute) if result: return result return "" def nodeToJSON(self, node, filename, fd, report_path, page_path, thumb=False): rowjson = {} rowjson['widget'] = 'node' attrMap = self.attributesToMap(node.attributes()) for head in self.thead: cb = head['callback'](node) if type(cb) == str: cb = cb.decode('utf-8', 'replace').encode('utf-8') rowjson[head['title']] = cb if NodeListFragment.HeaderAttributes: for (name, attribute) in NodeListFragment.HeaderAttributes: result = self.findInAttributesMap(name, attrMap) rowjson[name] = result if filename: rowjson["file"] = self.filepath + "/" + filename if thumb and self.gui: if self.exportThumbnail(report_path, self.thumbpath, filename + '.jpg', node): rowjson["thumb"] = self.thumbpath + "/" + filename + '.jpg' rowjson['row_details'] = {'widget': 'node_attribute', 'data': attrMap} try: json.dump(rowjson, fd) except UnicodeError as e: print 'report.fragment.nodeToJSON failed ' + str(e) print rowjson def exportThumbnail(self, report_path, thumbpath, name, node, size=None): self.thumbnailer = Thumbnailer() if self.thumbnailer.isThumbnailable(node): pixmap = self.thumbnailer.generate(node, iconSize=256, frames=10, blocking=True) self.thumbnailer.unregister() if pixmap: try: exportPath = os.path.join(report_path, os.path.join(thumbpath, name)) array = QByteArray() qfile = QBuffer(array) qfile.open(QIODevice.ReadWrite) pixmap.save(qfile, 'JPG') qfile.seek(0) with open(exportPath, 'wb') as f: f.write(qfile.read(qfile.size())) qfile.close() return True except Exception as e: qfile.close() return False else: return False def exportNode(self, node, path, report_path): abspath = os.path.join(report_path, path) try: local_path = self.extract.extractFile(node, abspath) except Exception as e: pass if local_path: return os.path.basename(local_path) else: return None