def main(): print("""\ <?xml version="1.0" encoding="UTF-8"?> <dfxml xmlns="%s" xmlns:delta="%s" version="1.1.0"> <creator> <program>%s</program> <version>%s</version> <execution_environment> <command_line>%s</command_line> </execution_environment> </creator> <source> <image_filename>%s</image_filename> </source>\ """ % (dfxml.XMLNS_DFXML, dfxml.XMLNS_DELTA, sys.argv[0], __version__, " ".join(sys.argv), args.filename)) ET.register_namespace("delta", dfxml.XMLNS_DELTA) xs = [] for fi in dfxml.iter_dfxml(xmlfile=open(args.filename, "rb"), preserve_elements=True): _logger.debug("Processing: %s" % str(fi)) if args.cache: xs.append(fi.xml_element) else: _logger.debug("Printing without cache: %s" % str(fi)) print(dfxml.ET_tostring(fi.xml_element, encoding="unicode")) if args.cache: for x in xs: _logger.debug("Printing with cache: %s" % str(fi)) print(dfxml.ET_tostring(x, encoding="unicode")) print("""</dfxml>""")
def to_xml(self): import xml.etree.ElementTree as ET ET.register_namespace("delta", dfxml.XMLNS_DELTA) if not options.xmlfilename: sys.stderr.write("XML output filename not specified.\n") exit(1) metadict = dict() metadict["XMLNS_DFXML"] = dfxml.XMLNS_DFXML metadict["XMLNS_DELTA"] = dfxml.XMLNS_DELTA metadict["program"] = sys.argv[0] metadict["version"] = __version__ metadict["commandline"] = " ".join(sys.argv) metadict["priorf"] = self.prior_fname metadict["currentf"] = self.current_fname xmlfile = open(options.xmlfilename, "w") xmlfile.write("""\ <?xml version="1.0" encoding="UTF-8"?> <dfxml version="1.0" xmlns='%(XMLNS_DFXML)s' xmlns:dc='http://purl.org/dc/elements/1.1/' xmlns:delta='%(XMLNS_DELTA)s' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'> <metadata> <dc:type>Disk Image Difference Manifest</dc:type> </metadata> <creator> <program>%(program)s</program> <version>%(version)s</version> <execution_environment> <command_line>%(commandline)s</command_line> </execution_environment> </creator> <source> <image_filename>%(priorf)s</image_filename> <image_filename>%(currentf)s</image_filename> </source> """ % metadict) def _annotate_changes(tmpel, ofi, fi): """ Adds "delta:changed_property" attributes to elements that changed their values. Returns number of annotations needed. """ retval = 0 def _xpaths(xp): """ Returns a list of xpaths: First, with an xmlns; second, as input. @param xp An xpath expression where all elements and attributes needing a namespace declaration are prefixed with "{0}" (for Python string formatting). """ retval = [] for nsprefix in ["{" + dfxml.XMLNS_DFXML + "}", ""]: retval.append(xp.format(nsprefix)) return retval # Triplets: Old value, new value, XPaths to find element to annotate for (oval, nval, xpaths) in [ (ofi.filename(), fi.filename(), _xpaths("./{0}filename")), (ofi.sha1(), fi.sha1(), _xpaths("./{0}hashdigest[@type='sha1']")), (ofi.md5(), fi.md5(), _xpaths("./{0}hashdigest[@type='md5']")), (ofi.mtime(), fi.mtime(), _xpaths("./{0}mtime")), (ofi.atime(), fi.atime(), _xpaths("./{0}atime")), (ofi.ctime(), fi.ctime(), _xpaths("./{0}ctime")), (ofi.crtime(), fi.crtime(), _xpaths("./{0}crtime")), (ofi.filesize(), fi.filesize(), _xpaths("./{0}filesize")) ]: #Find and flag the changed properties #Skip null-null comparisons if oval is None and nval is None: continue if oval != nval: retval += 1 #Find first namespace match for the property element for xp in xpaths: propertyel = tmpel.find(xp) if not propertyel is None: break if propertyel is None: comment = ET.Comment( "Warning: Tried to note a changed property with the XPath queries %r; however, could not find the element." % xpaths) tmpel.insert(0, comment) else: propertyel.attrib["delta:changed_property"] = "1" return retval #List new files for fi in self.new_files: #xmlfile.write(" <!-- + %s -->\n" % fi.filename()) xmlfile.write(" ") tmpel = copy.copy(fi.xml_element) tmpel.attrib["delta:new_file"] = "1" xmlfile.write(dfxml.ET_tostring(tmpel, encoding="unicode")) xmlfile.write("\n") #List deleted files for fi in self.fnames.values(): #xmlfile.write("<!-- - %s -->\n" % fi.filename()) xmlfile.write(" ") tmpel = ET.Element("fileobject") tmpel.attrib["delta:deleted_file"] = "1" tmpchild = copy.copy(fi.xml_element) tmpchild.tag = "delta:original_fileobject" tmpel.insert(-1, tmpchild) xmlfile.write(dfxml.ET_tostring(tmpel, encoding="unicode")) xmlfile.write("\n") #List renamed files for (ofi, fi) in self.renamed_files: #xmlfile.write("<!-- ! %s -> %s -->\n" % (ofi.filename(), fi.filename())) tmpel = copy.copy(fi.xml_element) annos = _annotate_changes(tmpel, ofi, fi) tmpoldel = copy.copy(ofi.xml_element) tmpoldel.tag = "delta:original_fileobject" tmpel.append(tmpoldel) tmpel.attrib["delta:renamed_file"] = "1" if annos > 1: tmpel.attrib["delta:changed_file"] = "1" xmlfile.write(dfxml.ET_tostring(tmpel, encoding="unicode")) xmlfile.write("\n") #List files with with modified data or metadata changed_files = set.union(set(self.changed_content), set(self.changed_properties)) for (ofi, fi) in changed_files: #xmlfile.write("<!-- ~ %s -->\n" % fi.filename()) xmlfile.write(" ") tmpel = copy.copy(fi.xml_element) _annotate_changes(tmpel, ofi, fi) tmpoldel = copy.copy(ofi.xml_element) tmpoldel.tag = "delta:original_fileobject" tmpel.append(tmpoldel) tmpel.attrib["delta:changed_file"] = "1" xmlfile.write(dfxml.ET_tostring(tmpel, encoding="unicode")) xmlfile.write("\n") xmlfile.write("</dfxml>\n") xmlfile.close()