User:Tardis/regdiff.py: Difference between revisions

Content deleted Content added
program to compare Windows registry dumps
 
version 0.2: improved safety
Line 4:
#Created November 9 2008
#Updated November 9 2008
#Version 0.12
 
#This program is free software; you can redistribute it and/or modify it under
#the terms of the GNU General Public License version 2, the GNU Free
#Documentation License version 1.2, or (atwith yourno option)Invariant any laterSections, versionwith ofno
#Front-Cover Texts, and with no Back-Cover Texts), or (at your option) any
#either license.
#later version of either license. It is distributed in the hope that it will
#be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
#Public License for more details.
 
#Description:
#Compares two Windows registry (.REG) files and produces a third such that
#applying it transforms a registry represented by the first into a registry
#represented by the second. (ThatUsually is,you itshould deletesredirect allthe keysoutput andto valuesa presentfile.
#in the first but not in the second!)
 
#Warnings:
#BUGS:
#The output deletes all keys and values present in the first but not in the
#second! Therefore, this should be run only on exports of complete subtrees.
 
#It's probably wise to double check any key removals in the output: look for
#lines beginning with the two characters "[-". Modern .REG files use UTF-16,
#so some editors and tools (like grep) may have trouble with them. Using
#"grep '^.\[.-' out.reg" should work to at least detect removals.
 
#You can disable deletions of keys or values entirely by setting the
#appropriate variables (allow*Delete). If keys cannot be deleted but values
#can, each value named in the old file under a key that would be deleted will
#be deleted. (This is not as dangerous because reapplying the old file will
#restore them.)
 
#History:
#Version 0.1, November 9 2008:
# - initial release
#Version 0.2, November 9 2008:
# - use CRLF newlines
# - support deletion disabling
# - detect misorderings
 
#Bugs:
#Assumes that no key contains assignments to @ and to "" -- I think the latter
#is invalid anyway. Also changes any literal \r\n in strings to \n.
 
#I don't know whether .REG files are really UTF-16 or UCS-2.
 
import sys,codecs
Line 25 ⟶ 54:
def __init__(self,s,k=None):
"""Parse s and make a line object.
Inherit key from line k unless we are a key or it is omitted or None.
Use k to detect misordered input if it is not None.
Names are not unescaped, but escaping is considered in their extent."""
self.old=False
Line 38 ⟶ 68:
elif self.iskey:
self.delete=s[1]=='-'
self.lastkey=self.name=s[1+self.delete:-23] # ends in "]\r\n"
if k is not None and self.lastkey<k.lastkey:
raise ValueError,"key %r precedes %r in input"%\
(k.lastkey,self.lastkey)
else:
if s[0]=='"':
Line 56 ⟶ 89:
raise IOError,"no assignment in" +repr(s)
self.delete=assign[1]=='-'
self.lastkey=None if k is None else k.lastkey:
self.lastkey=None
else:
self.lastkey=k.lastkey
if not k.iskey and self.name<k.name:
raise ValueError,"value %r precedes %r in input"%\
(k.name,self.name)
 
def valname(self):
Line 77 ⟶ 116:
if k!=self.key:
self.key=k
self.out.write("\r\n["+k+"]\r\n")
 
def terminated(s):
Line 105 ⟶ 144:
ret+=c
done=terminated(ret)
#printif >>sys.stderr,repr(c!=l)+'/'+repr(c)+": -> "+repr(ret)+": term="+str(done)\r\n"
if c!=l: ret+='\n'
return ret
 
Line 117 ⟶ 155:
sys.exit(2) # BAD_ARGS
 
allowKeyDelete=True
allowValueDelete=True
ci=codecs.lookup("utf_16")
fo=ci.streamreader(open(sys.argv[1],'rb'))
Line 125 ⟶ 165:
if fn.readline()!=head:
raise IOError,"different file headers"
out.write(head.rstrip('\r\n')+'"\r\n'")
 
o=n=line(None)
Line 140 ⟶ 180:
# values (since the values go with a previous key), and EOF comes after
# everything. Positive values mean that n comes first.
c=o.eof-n.eof or cmp(o.lastkey,n.lastkey) or\
o.iskey-n.iskey or cmp(o.name,n.name)
o.old=c<=0
n.old=c>=0
Line 151 ⟶ 192:
# Delete a whole key if the new file is past all its subkeys.
# Note that n.lastkey!=o.name, because n must be a key.
if n.eof or not isunder(n.lastkey,o.name) and allowKeyDelete:
killing=o.name
out.write("\r\n[-"+o.name+"]\r\n")
elseelif allowValueDelete:
kp(o.lastkey)
out.write(o.valname()+"=-\r\n")
elif not n.iskey and n.str!=o.str:
kp(n.lastkey)
out.write(n.str)
 
out.write('"\r\n'")
</source>