diff -r 8e7a738c3840 Lib/zipfile.py --- a/Lib/zipfile.py Sat Nov 16 10:47:17 2013 -0500 +++ b/Lib/zipfile.py Sat Nov 16 20:41:45 2013 +0200 @@ -13,6 +13,7 @@ import shutil import struct import binascii +import collections try: @@ -160,6 +161,8 @@ _CD64_DIRECTORY_SIZE = 8 _CD64_OFFSET_START_CENTDIR = 9 +_EXTRA_FIELD_STRUCT = struct.Struct(' ZIP64_LIMIT or compress_size > ZIP64_LIMIT if zip64: - fmt = ' ZIP64_LIMIT or compress_size > ZIP64_LIMIT: if not zip64: raise LargeZipFile("Filesize would require ZIP64 extensions") @@ -398,8 +430,8 @@ self.extract_version, self.reserved, flag_bits, self.compress_type, dostime, dosdate, CRC, compress_size, file_size, - len(filename), len(extra)) - return header + filename + extra + len(filename), len(self.extra)) + return header + filename + self.extra def _encodeFilenameFlags(self): try: @@ -407,41 +439,62 @@ except UnicodeEncodeError: return self.filename.encode('utf-8'), self.flag_bits | 0x800 + @property + def extra(self): + if self._extra_bytes is None: + self._extra_bytes = b''.join( + _EXTRA_FIELD_STRUCT.pack(xid, len(data)) + data + for xid, data in self._extra_items) + return self._extra_bytes + + @extra.setter + def extra(self, value): + self._extra_bytes = value + self._extra_items = None + + @property + def _extra_list(self): + if self._extra_items is None: + extra = self._extra_bytes + items = [] + append = items.append + unpack = _EXTRA_FIELD_STRUCT.unpack + i = 0 + while i < len(extra): + xid, xlen = unpack(extra[i: i + 4]) + append((xid, extra[i + 4: i + 4 + xlen])) + i += 4 + xlen + self._extra_items = items + return self._extra_items + + @_extra_list.setter + def _extra_list(self, value): + self._extra_bytes = None + self._extra_items = value + + @property + def extra_map(self): + return ExtraMap(self) + + @extra_map.setter + def extra_map(self, value): + self._extra_list = tuple(value.items()) + def _decodeExtra(self): # Try to decode the extra field. - extra = self.extra - unpack = struct.unpack - while extra: - tp, ln = unpack('= 24: - counts = unpack('