From e6dcd82dc6ba86c00da9c401a6c80f317941fa44 Mon Sep 17 00:00:00 2001 From: John-Mark Gurney Date: Tue, 4 Jul 2006 11:44:49 -0800 Subject: [PATCH] add new wrapper for iterzipfile instead of mod'ing the python modules directly... make use of this.. [git-p4: depot-paths = "//depot/": change = 811] --- ZipStorage.py | 3 +- iterzipfile.py | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 iterzipfile.py diff --git a/ZipStorage.py b/ZipStorage.py index 70c5f2a..4fdaf92 100644 --- a/ZipStorage.py +++ b/ZipStorage.py @@ -8,7 +8,8 @@ import itertools import os.path import sets import time -import zipfile +import iterzipfile +zipfile = iterzipfile import FileDIDL from DIDLLite import StorageFolder, Item, VideoItem, AudioItem, TextItem, ImageItem, Resource diff --git a/iterzipfile.py b/iterzipfile.py new file mode 100644 index 0000000..fd7557c --- /dev/null +++ b/iterzipfile.py @@ -0,0 +1,74 @@ +#!/usr/bin/env python + +import binascii +import os +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): + 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)