|
|
@@ -6,73 +6,20 @@ __version__ = '$Change$' |
|
|
|
|
|
|
|
import binascii |
|
|
|
import os |
|
|
|
import twisted.python.zipstream |
|
|
|
import zipfile |
|
|
|
from zipfile import * |
|
|
|
try: |
|
|
|
import zlib # We may need its compression method |
|
|
|
except ImportError: |
|
|
|
zlib = None |
|
|
|
|
|
|
|
__all__ = zipfile.__all__ |
|
|
|
|
|
|
|
def dupfile(fp): |
|
|
|
if not hasattr(fp, 'fileno'): |
|
|
|
raise ValueError, 'must be operating on real file' |
|
|
|
newfp = os.fdopen(os.dup(fp.fileno())) |
|
|
|
return newfp |
|
|
|
|
|
|
|
class ZipFile(ZipFile): |
|
|
|
class ZipFile(twisted.python.zipstream.ChunkingZipFile): |
|
|
|
def readiter(self, name, blksize=16384): |
|
|
|
"""Return file bytes (as a string) for name.""" |
|
|
|
|
|
|
|
if self.mode not in ("r", "a"): |
|
|
|
raise RuntimeError, 'read() requires mode "r" or "a"' |
|
|
|
if not self.fp: |
|
|
|
raise RuntimeError, "Attempt to read ZIP archive " \ |
|
|
|
"that was already closed" |
|
|
|
zinfo = self.getinfo(name) |
|
|
|
fp = dupfile(self.fp) |
|
|
|
fp.seek(zinfo.file_offset, 0) |
|
|
|
if zinfo.compress_type == ZIP_STORED: |
|
|
|
assert zinfo.file_size == zinfo.compress_size |
|
|
|
i = 0 |
|
|
|
while i < zinfo.file_size: |
|
|
|
yield fp.read(min(blksize, zinfo.file_size - i)) |
|
|
|
elif zinfo.compress_type == ZIP_DEFLATED: |
|
|
|
if not zlib: |
|
|
|
raise RuntimeError, "De-compression requires " \ |
|
|
|
"the (missing) zlib module" |
|
|
|
# zlib compress/decompress code by Jeremy Hylton of CNRI |
|
|
|
uncomp = 0 |
|
|
|
comp = 0 |
|
|
|
dc = zlib.decompressobj(-15) |
|
|
|
crc = None |
|
|
|
doflush = False |
|
|
|
while uncomp < zinfo.file_size: |
|
|
|
if not dc.unconsumed_tail: |
|
|
|
compread = min(blksize, |
|
|
|
zinfo.compress_size - comp) |
|
|
|
bytes = fp.read(compread) |
|
|
|
comp += compread |
|
|
|
if compread == 0: |
|
|
|
doflush = True |
|
|
|
else: |
|
|
|
bytes = dc.unconsumed_tail |
|
|
|
if doflush: |
|
|
|
# need to feed in unused pad byte so |
|
|
|
# that zlib won't choke |
|
|
|
bytes = dc.decompress('Z') + dc.flush() |
|
|
|
else: |
|
|
|
bytes = dc.decompress(bytes, blksize) |
|
|
|
yield bytes |
|
|
|
uncomp += len(bytes) |
|
|
|
if crc is None: |
|
|
|
crc = binascii.crc32(bytes) |
|
|
|
else: |
|
|
|
crc = binascii.crc32(bytes, crc) |
|
|
|
if crc != zinfo.CRC: |
|
|
|
raise BadZipfile, "Bad CRC-32 for file %s" % \ |
|
|
|
name |
|
|
|
else: |
|
|
|
raise BadZipfile, "Unsupported compression method " \ |
|
|
|
"%d for file %s" % (zinfo.compress_type, name) |
|
|
|
#print 'ri:', `self`, `name` |
|
|
|
fp = self.readfile(name) |
|
|
|
while True: |
|
|
|
d = fp.read(blksize) |
|
|
|
if not d: |
|
|
|
break |
|
|
|
yield d |