zip実装会にまた行ってきて横道にそれた
zip実装会に行って
zipを実装しようと思ったけど、やっぱりうまく理解できなかったので
zipファイルを読み込んで、ヘッダを順番に出力するスクリプトを書きました。
未チェックです。あとで直します。
使い方は、引数にzipファイルを指定すると、
ヘッダがずらずら出力されます。
- 例
readzip.py hoge.zip
みたいな使い方です。
import struct import sys data = open(sys.argv[1], 'rb').read() start = 0 print "-- header --" while 1 : sig_field = struct.unpack('<L', data[start:start+4]) signature, = sig_field if hex(signature) != '0x4034b50' : break headers = struct.unpack('<L5H', data[start:start+14]) signature, needver, option, comptype, filetime, filedate = headers print 'signature',hex(signature) print 'needver', hex(needver) print 'option', hex(option) print 'comptype', hex(comptype) print 'filetime', hex(filetime) print 'filedate', hex(filedate) start += 14 fields = struct.unpack('<3L2H', data[start:start+16]) crc32, compsize, uncompsize, fnamelen, extralen = fields start += 16 filename = data[start:start+fnamelen] start += fnamelen extra = data[start:start+extralen] print 'crc32', hex(crc32) print 'compsize', compsize print 'uncompsize', uncompsize print 'fnamelen', fnamelen print 'extralen', extralen print 'filename', filename start += extralen b_type = str(compsize) + 's' filedata = struct.unpack(b_type, data[start:start+compsize]) print "filedata", filedata start += compsize print "----" print "-- StartCentralDirHeader --" while 1 : sig_field = struct.unpack('<L', data[start:start+4]) signature, = sig_field if hex(signature) != '0x2014b50' : break c_headers = struct.unpack('<L6H3L5H2L',data[start:start+46]) signature, madever, needver, option, comptype, filetime, filedate, crc32, compsize, uncompsize, fnamelen, extralen, commentlen, disknum, inattr, outattr, headerpos = c_headers start += 46 print 'signature',hex(signature) print 'madever',hex(madever) print 'needver', hex(needver) print 'option', hex(option) print 'comptype', hex(comptype) print 'filetime', hex(filetime) print 'filedate', hex(filedate) print 'crc32', hex(crc32) print 'compsize', compsize print 'uncompsize', uncompsize print 'fnamelen', fnamelen print 'extralen', hex(extralen) print 'commentlen', hex(commentlen) print 'disknum', hex(disknum) print 'inattr', hex(inattr) print 'outattr', hex(outattr) print 'headerpos', hex(headerpos) filename = data[start:start+fnamelen] print 'filename', filename start += fnamelen extra = data[start:start+extralen] start += extralen print "----" e_headers = struct.unpack('<L4H2LH',data[start:start+22]) signature, disknum, startdisknum, diskdirentry, direntry, dirsize, startpos, commentlen = e_headers print "-- EndCentralDirHeader --" print 'signature',hex(signature) print 'disknum',hex(disknum) print 'startdisknum', hex(startdisknum) print 'diskdirentry', hex(diskdirentry) print 'direntry', hex(direntry) print 'dirsize', hex(dirsize) print 'commentlen', hex(commentlen)
ええと、あとからsignatureのチェックをちょろちょろ書いたり
変数名を例のホームページの表記に合わせたりしたので
いろいろ間違ってるとこがあるかもしれませんが、
後日に修正します。
出力結果はこんなカンジです。
-- header -- signature 0x4034b50 needver 0xa option 0x0 comptype 0x0 filetime 0x88f6 filedate 0x3d67 crc32 0x3bb935c6 compsize 5 uncompsize 5 fnamelen 8 extralen 28 filename hoge.txt filedata ('test\n',) ---- signature 0x4034b50 needver 0xa option 0x0 comptype 0x0 filetime 0x8e15 filedate 0x3d67 crc32 0x4788814e compsize 4 uncompsize 4 fnamelen 8 extralen 28 filename boge.txt filedata ('abc\n',) ---- -- StartCentralDirHeader -- signature 0x2014b50 madever 0x31e needver 0xa option 0x0 comptype 0x0 filetime 0x88f6 filedate 0x3d67 crc32 0x3bb935c6 compsize 5 uncompsize 5 fnamelen 8 extralen 0x18 commentlen 0x0 disknum 0x0 inattr 0x1 outattr 0x81a40000 headerpos 0x0 filename hoge.txt ---- signature 0x2014b50 madever 0x31e needver 0xa option 0x0 comptype 0x0 filetime 0x8e15 filedate 0x3d67 crc32 0x4788814e compsize 4 uncompsize 4 fnamelen 8 extralen 0x18 commentlen 0x0 disknum 0x0 inattr 0x1 outattr 0x81a40000 headerpos 0x47 filename boge.txt ---- -- EndCentralDirHeader -- signature 0x6054b50 disknum 0x0 startdisknum 0x0 diskdirentry 0x2 direntry 0x2 dirsize 0x9c commentlen 0x0