Skip to content

Instantly share code, notes, and snippets.

@geekman geekman/modzip.py
Created Jul 1, 2015

Embed
What would you like to do?
Patches file attributes in ZIP files
#!/usr/bin/python
#
# modifies zip file attributes
# 2015.07.01 darell tan
#
from zipfile import *
import struct
import sys
eocdStruct = '<4s4H2LH'
sizeEndCentDir = struct.calcsize(eocdStruct)
cdStruct = '<4s4B4HL2L5H2L'
sizeCentDir = struct.calcsize(cdStruct)
FILE_ATTRIBUTE_NOT_CONTENT_INDEXED = 0x2000
FILE_ATTRIBUTE_ENCRYPTED = 0x4000
# don't write any changes
_NOOP = False
def main():
# get EoCD record
f = open(sys.argv[1], 'r+b')
f.seek(-sizeEndCentDir, 2)
data = f.read()
if data[0:4] == 'PK\005\006' and data[-2:] == '\000\000':
eocd = struct.unpack(eocdStruct, data)
cdSizeTotal, cdOffset = eocd[5:7]
f.seek(cdOffset)
else:
# maybe there's a comment?
# i'm not gonna find it - see zipfile.py for details
assert False, "can't find end of central directory"
cdCount = 0
while cdCount < cdSizeTotal:
#print "cd @", f.tell()
centDir = struct.unpack(cdStruct, f.read(sizeCentDir))
assert centDir[0] == 'PK\001\002'
createVer, createOs = centDir[1:3]
nameLen, extraLen, commentLen = centDir[12:15]
extAttrib = centDir[17]
name = f.read(nameLen)
print '%s\t%x' % (name, extAttrib)
# advance to next central directory
cdSize = sizeCentDir + nameLen + extraLen + commentLen
cdCount += cdSize
f.seek(extraLen + commentLen, 1)
#print "end cd @", f.tell()
# make modifications here
if createOs == 0:
#print 'modifying ext attrib @', f.tell()
f.seek(-cdSize + 38, 1)
assert struct.unpack('<L', f.read(4))[0] == extAttrib
# overwrite
extAttrib = extAttrib & ~FILE_ATTRIBUTE_ENCRYPTED
if not _NOOP:
f.seek(-4, 1)
f.write(struct.pack('<L', extAttrib))
f.seek(cdSize - 38 - 4, 1)
#print "cd end @ ", f.tell()
f.close()
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.