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